diff --git a/404.html b/404.html new file mode 100644 index 0000000000..020e6b9c0e --- /dev/null +++ b/404.html @@ -0,0 +1,46 @@ + + + + + + 404 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/assets/Class.Cx5QD1OX.jpeg b/assets/Class.Cx5QD1OX.jpeg new file mode 100644 index 0000000000..ff8c1b8a67 Binary files /dev/null and b/assets/Class.Cx5QD1OX.jpeg differ diff --git a/assets/Comment.BYtNY-L1.jpeg b/assets/Comment.BYtNY-L1.jpeg new file mode 100644 index 0000000000..ba1ed5e1a7 Binary files /dev/null and b/assets/Comment.BYtNY-L1.jpeg differ diff --git a/assets/Declaration.CplvpFd-.jpeg b/assets/Declaration.CplvpFd-.jpeg new file mode 100644 index 0000000000..f8d05e6c65 Binary files /dev/null and b/assets/Declaration.CplvpFd-.jpeg differ diff --git a/assets/Expression.DczLaznn.jpeg b/assets/Expression.DczLaznn.jpeg new file mode 100644 index 0000000000..89139b9ac4 Binary files /dev/null and b/assets/Expression.DczLaznn.jpeg differ diff --git a/assets/ExpressionStatement.zaIHlhIF.jpeg b/assets/ExpressionStatement.zaIHlhIF.jpeg new file mode 100644 index 0000000000..a9d17062c4 Binary files /dev/null and b/assets/ExpressionStatement.zaIHlhIF.jpeg differ diff --git a/assets/File.BiH2GpuW.jpeg b/assets/File.BiH2GpuW.jpeg new file mode 100644 index 0000000000..4cfced7196 Binary files /dev/null and b/assets/File.BiH2GpuW.jpeg differ diff --git a/assets/Identifier.lJSxyFTe.jpeg b/assets/Identifier.lJSxyFTe.jpeg new file mode 100644 index 0000000000..0967dee625 Binary files /dev/null and b/assets/Identifier.lJSxyFTe.jpeg differ diff --git a/assets/Literal.Dl-JxujV.jpeg b/assets/Literal.Dl-JxujV.jpeg new file mode 100644 index 0000000000..f0597018ce Binary files /dev/null and b/assets/Literal.Dl-JxujV.jpeg differ diff --git a/assets/Program.BBf_t-me.jpeg b/assets/Program.BBf_t-me.jpeg new file mode 100644 index 0000000000..367a39adda Binary files /dev/null and b/assets/Program.BBf_t-me.jpeg differ diff --git a/assets/Statement.9lGuRes5.jpeg b/assets/Statement.9lGuRes5.jpeg new file mode 100644 index 0000000000..2e576181f2 Binary files /dev/null and b/assets/Statement.9lGuRes5.jpeg differ diff --git a/assets/ali_doc.CYo30EHy.webp b/assets/ali_doc.CYo30EHy.webp new file mode 100644 index 0000000000..eeb0a272f3 Binary files /dev/null and b/assets/ali_doc.CYo30EHy.webp differ diff --git a/assets/app.BaY_JH1S.js b/assets/app.BaY_JH1S.js new file mode 100644 index 0000000000..6734b073f6 --- /dev/null +++ b/assets/app.BaY_JH1S.js @@ -0,0 +1 @@ +import{R as i}from"./chunks/theme.CPGewkGm.js";import{R as o,ah as u,ai as l,aj as c,ak as f,al as d,am as m,an as h,ao as g,ap as A,aq as v,d as P,u as R,v as w,s as y,ar as C,as as b,at as E,a0 as S}from"./chunks/framework.C-ai2y4t.js";function p(e){if(e.extends){const a=p(e.extends);return{...a,...e,async enhanceApp(t){a.enhanceApp&&await a.enhanceApp(t),e.enhanceApp&&await e.enhanceApp(t)}}}return e}const s=p(i),T=P({name:"VitePressApp",setup(){const{site:e,lang:a,dir:t}=R();return w(()=>{y(()=>{document.documentElement.lang=a.value,document.documentElement.dir=t.value})}),e.value.router.prefetchLinks&&C(),b(),E(),s.setup&&s.setup(),()=>S(s.Layout)}});async function j(){globalThis.__VITEPRESS__=!0;const e=_(),a=D();a.provide(l,e);const t=c(e.route);return a.provide(f,t),a.component("Content",d),a.component("ClientOnly",m),Object.defineProperties(a.config.globalProperties,{$frontmatter:{get(){return t.frontmatter.value}},$params:{get(){return t.page.value.params}}}),s.enhanceApp&&await s.enhanceApp({app:a,router:e,siteData:h}),{app:a,router:e,data:t}}function D(){return g(T)}function _(){let e=o,a;return A(t=>{let n=v(t),r=null;return n&&(e&&(a=n),(e||a===n)&&(n=n.replace(/\.js$/,".lean.js")),r=import(n)),o&&(e=!1),r},s.NotFound)}o&&j().then(({app:e,router:a,data:t})=>{a.go().then(()=>{u(a.route,t.site),e.mount("#app")})});export{j as createApp}; diff --git a/assets/aqiyi_demo.s0swGzvF.webp b/assets/aqiyi_demo.s0swGzvF.webp new file mode 100644 index 0000000000..ba3f6c3e96 Binary files /dev/null and b/assets/aqiyi_demo.s0swGzvF.webp differ diff --git a/assets/axtexplorer.D7PG-3cx.jpeg b/assets/axtexplorer.D7PG-3cx.jpeg new file mode 100644 index 0000000000..260657479a Binary files /dev/null and b/assets/axtexplorer.D7PG-3cx.jpeg differ diff --git a/assets/axtexplorerSave.a5hTrvd2.jpeg b/assets/axtexplorerSave.a5hTrvd2.jpeg new file mode 100644 index 0000000000..237a350ad3 Binary files /dev/null and b/assets/axtexplorerSave.a5hTrvd2.jpeg differ diff --git a/assets/balanceTree.DP_9yIkO.png b/assets/balanceTree.DP_9yIkO.png new file mode 100644 index 0000000000..7dd260e1f1 Binary files /dev/null and b/assets/balanceTree.DP_9yIkO.png differ diff --git a/assets/bili_demo.CI8Ur8IA.webp b/assets/bili_demo.CI8Ur8IA.webp new file mode 100644 index 0000000000..51778f4e13 Binary files /dev/null and b/assets/bili_demo.CI8Ur8IA.webp differ diff --git a/assets/bili_demo_url.BQDGtHUp.webp b/assets/bili_demo_url.BQDGtHUp.webp new file mode 100644 index 0000000000..a3a011160b Binary files /dev/null and b/assets/bili_demo_url.BQDGtHUp.webp differ diff --git a/assets/bilibili_video_code.DgWtgAEf.webp b/assets/bilibili_video_code.DgWtgAEf.webp new file mode 100644 index 0000000000..8baf5b006d Binary files /dev/null and b/assets/bilibili_video_code.DgWtgAEf.webp differ diff --git a/assets/bilibili_video_m4s.BccuY7bk.webp b/assets/bilibili_video_m4s.BccuY7bk.webp new file mode 100644 index 0000000000..095b94023f Binary files /dev/null and b/assets/bilibili_video_m4s.BccuY7bk.webp differ diff --git a/assets/bubble.Csp5B4TH.gif b/assets/bubble.Csp5B4TH.gif new file mode 100644 index 0000000000..9dd0ed47f9 Binary files /dev/null and b/assets/bubble.Csp5B4TH.gif differ diff --git a/assets/bundle.bky0NmdF.png b/assets/bundle.bky0NmdF.png new file mode 100644 index 0000000000..b1e14cba8f Binary files /dev/null and b/assets/bundle.bky0NmdF.png differ diff --git a/assets/chunks/add-user-BN1JlY7e.D6YNNzf8.js b/assets/chunks/add-user-BN1JlY7e.D6YNNzf8.js new file mode 100644 index 0000000000..4429dfafa5 --- /dev/null +++ b/assets/chunks/add-user-BN1JlY7e.D6YNNzf8.js @@ -0,0 +1,6 @@ +const c={success:!0,_identification:!0,data:` + +`};export{c as default}; diff --git a/assets/chunks/balanceTree.CCEoBiag.js b/assets/chunks/balanceTree.CCEoBiag.js new file mode 100644 index 0000000000..94d3536f9f --- /dev/null +++ b/assets/chunks/balanceTree.CCEoBiag.js @@ -0,0 +1 @@ +const s="/ran/assets/balanceTree.DP_9yIkO.png";export{s as _}; diff --git a/assets/chunks/book-nTEFXU2x.DPEdiL1I.js b/assets/chunks/book-nTEFXU2x.DPEdiL1I.js new file mode 100644 index 0000000000..baf7b4e3e4 --- /dev/null +++ b/assets/chunks/book-nTEFXU2x.DPEdiL1I.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/bubble.Dg5jgvyl.js b/assets/chunks/bubble.Dg5jgvyl.js new file mode 100644 index 0000000000..68d97083ad --- /dev/null +++ b/assets/chunks/bubble.Dg5jgvyl.js @@ -0,0 +1 @@ +const s="/ran/assets/bubble.Csp5B4TH.gif";export{s as _}; diff --git a/assets/chunks/bundle.BxrzsuA1.js b/assets/chunks/bundle.BxrzsuA1.js new file mode 100644 index 0000000000..36568ff578 --- /dev/null +++ b/assets/chunks/bundle.BxrzsuA1.js @@ -0,0 +1 @@ +const s="/ran/assets/bundle.bky0NmdF.png";export{s as _}; diff --git a/assets/chunks/check-circle-fill-B_pd8ZSs.Dxgzakn4.js b/assets/chunks/check-circle-fill-B_pd8ZSs.Dxgzakn4.js new file mode 100644 index 0000000000..ddd2ec2f3f --- /dev/null +++ b/assets/chunks/check-circle-fill-B_pd8ZSs.Dxgzakn4.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/check-circle-szyAJiap.CM_vbBX5.js b/assets/chunks/check-circle-szyAJiap.CM_vbBX5.js new file mode 100644 index 0000000000..55caf815a8 --- /dev/null +++ b/assets/chunks/check-circle-szyAJiap.CM_vbBX5.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/close-CFnkhudp.IMqD2L1-.js b/assets/chunks/close-CFnkhudp.IMqD2L1-.js new file mode 100644 index 0000000000..db4e601db5 --- /dev/null +++ b/assets/chunks/close-CFnkhudp.IMqD2L1-.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/close-circle-CwmuN2C6.D612j4KD.js b/assets/chunks/close-circle-CwmuN2C6.D612j4KD.js new file mode 100644 index 0000000000..a36c96ed78 --- /dev/null +++ b/assets/chunks/close-circle-CwmuN2C6.D612j4KD.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/close-circle-fill-jSqPPw9i.BsLXh5-a.js b/assets/chunks/close-circle-fill-jSqPPw9i.BsLXh5-a.js new file mode 100644 index 0000000000..8191d4e4ee --- /dev/null +++ b/assets/chunks/close-circle-fill-jSqPPw9i.BsLXh5-a.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/colz-DJZvo_8B.DBiU5Tau.js b/assets/chunks/colz-DJZvo_8B.DBiU5Tau.js new file mode 100644 index 0000000000..f0058c788f --- /dev/null +++ b/assets/chunks/colz-DJZvo_8B.DBiU5Tau.js @@ -0,0 +1 @@ +var $=Object.defineProperty,p=(s,t,i)=>t in s?$(s,t,{enumerable:!0,configurable:!0,writable:!0,value:i}):s[t]=i,e=(s,t,i)=>p(s,typeof t!="symbol"?t+"":t,i);const l=Math.round;class f{constructor(t){e(this,"r"),e(this,"g"),e(this,"b"),this.r=t[0],this.g=t[1],this.b=t[2]}toString(){return`rgb(${this.r},${this.g},${this.b})`}}class x extends f{constructor(t){super(t),e(this,"a"),this.a=t[3]}toString(){return`rgba(${this.r},${this.g},${this.b},${this.a})`}}class d{constructor(t){e(this,"h"),e(this,"s"),e(this,"l"),this.h=t[0],this.s=t[1],this.l=t[2]}toString(){return`hsl(${this.h},${this.s}%,${this.l}%)`}}class N extends d{constructor(t){super(t),e(this,"a"),this.a=t[3]}toString(){return`hsla(${this.h},${this.s}%,${this.l}%,${this.a})`}}class F{constructor(t,i=0,h=0,a=1){if(e(this,"r"),e(this,"g"),e(this,"b"),e(this,"a"),e(this,"rgb"),e(this,"rgba"),e(this,"hex"),e(this,"hsl"),e(this,"hsla"),e(this,"h"),e(this,"s"),e(this,"l"),typeof t=="string"){let r=t;r.charAt(0)!=="#"&&(r="#"+r),r.length<7&&(r="#"+r[1]+r[1]+r[2]+r[2]+r[3]+r[3]),[t,i,h]=m(r)}else t instanceof Array&&(a=t[3]||a,h=t[2],i=t[1],t=t[0]);this.r=Number(t),this.g=Number(i),this.b=Number(h),this.a=a,this.rgb=new f([this.r,this.g,this.b]),this.rgba=new x([this.r,this.g,this.b,this.a]),this.hex=b(this.r,this.g,this.b),this.hsl=new d(H(this.r,this.g,this.b)),this.h=this.hsl.h,this.s=this.hsl.s,this.l=this.hsl.l,this.hsla=new N([this.h,this.s,this.l,this.a])}setHue(t){this.h=t,this.hsl.h=t,this.hsla.h=t,this.updateFromHsl()}setSat(t){this.s=t,this.hsl.s=t,this.hsla.s=t,this.updateFromHsl()}setLum(t){this.l=t,this.hsl.l=t,this.hsla.l=t,this.updateFromHsl()}setAlpha(t){this.a=t,this.hsla.a=t,this.rgba.a=t}updateFromHsl(){this.rgb=new f(_(this.h,this.s,this.l)),this.r=this.rgb.r,this.g=this.rgb.g,this.b=this.rgb.b,this.rgba.r=this.rgb.r,this.rgba.g=this.rgb.g,this.rgba.b=this.rgb.b,this.hex=b([this.r,this.g,this.b])}}const m=function(s){const t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(s);return t?[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]:null},M=(s,t)=>{const i=m(s)||[];for(let h=0;h<3;h++)i[h]=Math.floor(Number(i[h])*(1-t));return b(i[0],i[1],i[2])};function T(s,t){const i=m(s)||[];for(let h=0;h<3;h++)i[h]=Math.floor((255-Number(i[h]))*t+Number(i[h]));return b(i[0],i[1],i[2])}const c=function(s){const t=s.toString(16);return t.length===1?"0"+t:t},b=function(s,t=0,i=0){return s instanceof Array&&(i=s[2],t=s[1],s=s[0]),"#"+c(s)+c(t)+c(i)},H=function(s,t=0,i=0){s instanceof Array&&(i=s[2],t=s[1],s=s[0]);let h,a,r,n=0;s/=255,t/=255,i/=255;const o=Math.max(s,t,i),u=Math.min(s,t,i);if(a=(o+u)/2,o===u)n=h=0;else{switch(r=o-u,h=a>.5?r/(2-o-u):r/(o+u),o){case s:n=(t-i)/r+(t1&&(i-=1),i<1/6?s+(t-s)*6*i:i<1/2?t:i<2/3?s+(t-s)*(2/3-i)*6:s},_=function(s,t,i){s instanceof Array&&(i=s[2],t=s[1],s=s[0]),s=Number(s)/360,t=Number(t)/100,i=Number(i)/100;let h,a,r,n,o;return t===0?h=a=r=i:(n=i<.5?i*(1+t):i+t-i*t,o=2*i-n,h=g(o,n,s+1/3),a=g(o,n,s),r=g(o,n,s-1/3)),[l(h*255),l(a*255),l(r*255)]};export{F as C,M as a,T as g}; diff --git a/assets/chunks/commonjs-dynamic-modules-DLbDWi6a.CRNIONdy.js b/assets/chunks/commonjs-dynamic-modules-DLbDWi6a.CRNIONdy.js new file mode 100644 index 0000000000..0073b2c9c8 --- /dev/null +++ b/assets/chunks/commonjs-dynamic-modules-DLbDWi6a.CRNIONdy.js @@ -0,0 +1 @@ +var o=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function n(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function r(e){throw new Error('Could not dynamically require "'+e+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}export{r as a,o as c,n as g}; diff --git a/assets/chunks/complexity.CSkvDr7k.js b/assets/chunks/complexity.CSkvDr7k.js new file mode 100644 index 0000000000..84a1fc1a12 --- /dev/null +++ b/assets/chunks/complexity.CSkvDr7k.js @@ -0,0 +1 @@ +const s="/ran/assets/sort.CSVZS1AV.png",t="/ran/assets/complexity.DSLVsjHt.png";export{s as _,t as a}; diff --git a/assets/chunks/count.CcfK-WL7.js b/assets/chunks/count.CcfK-WL7.js new file mode 100644 index 0000000000..17e6ed3f6e --- /dev/null +++ b/assets/chunks/count.CcfK-WL7.js @@ -0,0 +1 @@ +const s="/ran/assets/count.CWSWBe_h.gif";export{s as _}; diff --git a/assets/chunks/customElements.qitHOM3M.js b/assets/chunks/customElements.qitHOM3M.js new file mode 100644 index 0000000000..2bb142f5b8 --- /dev/null +++ b/assets/chunks/customElements.qitHOM3M.js @@ -0,0 +1 @@ +const s="/ran/assets/customElements.DbqgaaNb.png";export{s as _}; diff --git a/assets/chunks/docx-VUApAnRr.Cl4GUa7G.js b/assets/chunks/docx-VUApAnRr.Cl4GUa7G.js new file mode 100644 index 0000000000..90f7ddbdfa --- /dev/null +++ b/assets/chunks/docx-VUApAnRr.Cl4GUa7G.js @@ -0,0 +1,16 @@ +import{J as ye}from"./jszip.min-BIf20mgf.BsDI-Ugu.js";import"./commonjs-dynamic-modules-DLbDWi6a.CRNIONdy.js";var k;(function(s){s.OfficeDocument="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",s.FontTable="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",s.Image="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",s.Numbering="http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",s.Styles="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",s.StylesWithEffects="http://schemas.microsoft.com/office/2007/relationships/stylesWithEffects",s.Theme="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",s.Settings="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",s.WebSettings="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",s.Hyperlink="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",s.Footnotes="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",s.Endnotes="http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes",s.Footer="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer",s.Header="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header",s.ExtendedProperties="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",s.CoreProperties="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",s.CustomProperties="http://schemas.openxmlformats.org/package/2006/relationships/metadata/custom-properties"})(k||(k={}));function Pe(s,e){return e.elements(s).map(t=>({id:e.attr(t,"Id"),type:e.attr(t,"Type"),target:e.attr(t,"Target"),targetMode:e.attr(t,"TargetMode")}))}const ne={wordml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main",drawingml:"http://schemas.openxmlformats.org/drawingml/2006/main",picture:"http://schemas.openxmlformats.org/drawingml/2006/picture",compatibility:"http://schemas.openxmlformats.org/markup-compatibility/2006",math:"http://schemas.openxmlformats.org/officeDocument/2006/math"},v={Dxa:{mul:.05,unit:"pt"},Emu:{mul:1/12700,unit:"pt"},FontSize:{mul:.5,unit:"pt"},Border:{mul:.125,unit:"pt"},Point:{mul:1,unit:"pt"},Percent:{mul:.02,unit:"%"},LineHeight:{mul:1/240,unit:""},VmlEmu:{mul:1/12700,unit:""}};function le(s,e=v.Dxa){return s==null||/.+(p[xt]|[%])$/.test(s)?s:`${(parseInt(s)*e.mul).toFixed(2)}${e.unit}`}function Se(s,e=!1){switch(s){case"1":return!0;case"0":return!1;case"on":return!0;case"off":return!1;case"true":return!0;case"false":return!1;default:return e}}function ie(s,e,t){if(s.namespaceURI!=ne.wordml)return!1;switch(s.localName){case"color":e.color=t.attr(s,"val");break;case"sz":e.fontSize=t.lengthAttr(s,"val",v.FontSize);break;default:return!1}return!0}function we(s,e=!1){e&&(s=s.replace(/<[?].*[?]>/,"")),s=Ce(s);const t=new DOMParser().parseFromString(s,"application/xml"),r=Me(t);if(r)throw new Error(r);return t}function Me(s){var e;return(e=s.getElementsByTagName("parsererror")[0])==null?void 0:e.textContent}function Ce(s){return s.charCodeAt(0)===65279?s.substring(1):s}function Ne(s){return new XMLSerializer().serializeToString(s)}class oe{elements(e,t=null){const r=[];for(let a=0,n=e.childNodes.length;axe(t,e))}function xe(s,e){let t={name:e.attr(s,"name"),embedFontRefs:[]};for(let r of e.elements(s))switch(r.localName){case"family":t.family=e.attr(r,"val");break;case"altName":t.altName=e.attr(r,"val");break;case"embedRegular":case"embedBold":case"embedItalic":case"embedBoldItalic":t.embedFontRefs.push(Fe(r,e));break}return t}function Fe(s,e){return{id:e.attr(s,"id"),key:e.attr(s,"fontKey"),type:Ae[s.localName]}}class Be extends w{parseXml(e){this.fonts=Ee(e,this._package.xmlParser)}}function Re(s){return s==null?void 0:s.replace(/[ .]+/g,"-").replace(/[&]+/g,"and").toLowerCase()}function $(s){let e=s.lastIndexOf("/")+1,t=e==0?"":s.substring(0,e),r=e==0?s:s.substring(e);return[t,r]}function I(s,e){try{const t="http://docx/";return new URL(s,t+e).toString().substring(t.length)}catch{return`${e}${s}`}}function A(s,e){return s.reduce((t,r)=>(t[e(r)]=r,t),{})}function Le(s){return new Promise((e,t)=>{const r=new FileReader;r.onloadend=()=>e(r.result),r.onerror=()=>t(),r.readAsDataURL(s)})}function H(s){return s&&typeof s=="object"&&!Array.isArray(s)}function Te(s){return typeof s=="string"||s instanceof String}function D(s,...e){if(!e.length)return s;const t=e.shift();if(H(s)&&H(t))for(const a in t)if(H(t[a])){var r;const n=(r=s[a])!==null&&r!==void 0?r:s[a]={};D(n,t[a])}else s[a]=t[a];return D(s,...e)}function x(s){return Array.isArray(s)?s:[s]}class j{constructor(e,t){this._zip=e,this.options=t,this.xmlParser=new oe}get(e){return this._zip.files[$e(e)]}update(e,t){this._zip.file(e,t)}static async load(e,t){const r=await ye.loadAsync(e);return new j(r,t)}save(e="blob"){return this._zip.generateAsync({type:e})}load(e,t="string"){var r,a;return(a=(r=this.get(e))==null?void 0:r.async(t))!==null&&a!==void 0?a:Promise.resolve(null)}async loadRelationships(e=null){let t="_rels/.rels";if(e!=null){const[a,n]=$(e);t=`${a}_rels/${n}.rels`}const r=await this.load(t);return r?Pe(this.parseXmlDocument(r).firstElementChild,this.xmlParser):null}parseXmlDocument(e){return we(e,this.options.trimXmlDeclaration)}}function $e(s){return s.startsWith("/")?s.substr(1):s}class _e extends w{constructor(e,t,r){super(e,t),this._documentParser=r}parseXml(e){this.body=this._documentParser.parseDocumentFile(e)}}function T(s,e){return{type:e.attr(s,"val"),color:e.attr(s,"color"),size:e.lengthAttr(s,"sz",v.Border),offset:e.lengthAttr(s,"space",v.Point),frame:e.boolAttr(s,"frame"),shadow:e.boolAttr(s,"shadow")}}function De(s,e){var t={};for(let r of e.elements(s))switch(r.localName){case"left":t.left=T(r,e);break;case"top":t.top=T(r,e);break;case"right":t.right=T(r,e);break;case"bottom":t.bottom=T(r,e);break}return t}var q;(function(s){s.Continuous="continuous",s.NextPage="nextPage",s.NextColumn="nextColumn",s.EvenPage="evenPage",s.OddPage="oddPage"})(q||(q={}));function ce(s,e=l){var t,r,a={};for(let n of e.elements(s))switch(n.localName){case"pgSz":a.pageSize={width:e.lengthAttr(n,"w"),height:e.lengthAttr(n,"h"),orientation:e.attr(n,"orient")};break;case"type":a.type=e.attr(n,"val");break;case"pgMar":a.pageMargins={left:e.lengthAttr(n,"left"),right:e.lengthAttr(n,"right"),top:e.lengthAttr(n,"top"),bottom:e.lengthAttr(n,"bottom"),header:e.lengthAttr(n,"header"),footer:e.lengthAttr(n,"footer"),gutter:e.lengthAttr(n,"gutter")};break;case"cols":a.columns=Oe(n,e);break;case"headerReference":((t=a.headerRefs)!==null&&t!==void 0?t:a.headerRefs=[]).push(J(n,e));break;case"footerReference":((r=a.footerRefs)!==null&&r!==void 0?r:a.footerRefs=[]).push(J(n,e));break;case"titlePg":a.titlePage=e.boolAttr(n,"val",!0);break;case"pgBorders":a.pageBorders=De(n,e);break;case"pgNumType":a.pageNumber=Ie(n,e);break}return a}function Oe(s,e){return{numberOfColumns:e.intAttr(s,"num"),space:e.lengthAttr(s,"space"),separator:e.boolAttr(s,"sep"),equalWidth:e.boolAttr(s,"equalWidth",!0),columns:e.elements(s,"col").map(t=>({width:e.lengthAttr(t,"w"),space:e.lengthAttr(t,"space")}))}}function Ie(s,e){return{chapSep:e.attr(s,"chapSep"),chapStyle:e.attr(s,"chapStyle"),format:e.attr(s,"fmt"),start:e.intAttr(s,"start")}}function J(s,e){return{id:e.attr(s,"id"),type:e.attr(s,"type")}}function He(s,e){return{before:e.lengthAttr(s,"before"),after:e.lengthAttr(s,"after"),line:e.intAttr(s,"line"),lineRule:e.attr(s,"lineRule")}}function W(s,e){let t={};for(let r of e.elements(s))Ve(r,t,e);return t}function Ve(s,e,t){return!!ie(s,e,t)}function ue(s,e){let t={};for(let r of e.elements(s))he(r,t,e);return t}function he(s,e,t){if(s.namespaceURI!=ne.wordml)return!1;if(ie(s,e,t))return!0;switch(s.localName){case"tabs":e.tabs=ze(s,t);break;case"sectPr":e.sectionProps=ce(s,t);break;case"numPr":e.numbering=je(s,t);break;case"spacing":return e.lineSpacing=He(s,t),!1;case"textAlignment":return e.textAlignment=t.attr(s,"val"),!1;case"keepLines":e.keepLines=t.boolAttr(s,"val",!0);break;case"keepNext":e.keepNext=t.boolAttr(s,"val",!0);break;case"pageBreakBefore":e.pageBreakBefore=t.boolAttr(s,"val",!0);break;case"outlineLvl":e.outlineLevel=t.intAttr(s,"val");break;case"pStyle":e.styleName=t.attr(s,"val");break;case"rPr":e.runProps=W(s,t);break;default:return!1}return!0}function ze(s,e){return e.elements(s,"tab").map(t=>({position:e.lengthAttr(t,"pos"),leader:e.attr(t,"leader"),style:e.attr(t,"val")}))}function je(s,e){var t={};for(let r of e.elements(s))switch(r.localName){case"numId":t.id=e.attr(r,"val");break;case"ilvl":t.level=e.intAttr(r,"val");break}return t}function We(s,e){let t={numberings:[],abstractNumberings:[],bulletPictures:[]};for(let r of e.elements(s))switch(r.localName){case"num":t.numberings.push(Xe(r,e));break;case"abstractNum":t.abstractNumberings.push(Ue(r,e));break;case"numPicBullet":t.bulletPictures.push(qe(r,e));break}return t}function Xe(s,e){let t={id:e.attr(s,"numId"),overrides:[]};for(let r of e.elements(s))switch(r.localName){case"abstractNumId":t.abstractId=e.attr(r,"val");break;case"lvlOverride":t.overrides.push(Ge(r,e));break}return t}function Ue(s,e){let t={id:e.attr(s,"abstractNumId"),levels:[]};for(let r of e.elements(s))switch(r.localName){case"name":t.name=e.attr(r,"val");break;case"multiLevelType":t.multiLevelType=e.attr(r,"val");break;case"numStyleLink":t.numberingStyleLink=e.attr(r,"val");break;case"styleLink":t.styleLink=e.attr(r,"val");break;case"lvl":t.levels.push(de(r,e));break}return t}function de(s,e){let t={level:e.intAttr(s,"ilvl")};for(let r of e.elements(s))switch(r.localName){case"start":t.start=e.attr(r,"val");break;case"lvlRestart":t.restart=e.intAttr(r,"val");break;case"numFmt":t.format=e.attr(r,"val");break;case"lvlText":t.text=e.attr(r,"val");break;case"lvlJc":t.justification=e.attr(r,"val");break;case"lvlPicBulletId":t.bulletPictureId=e.attr(r,"val");break;case"pStyle":t.paragraphStyle=e.attr(r,"val");break;case"pPr":t.paragraphProps=ue(r,e);break;case"rPr":t.runProps=W(r,e);break}return t}function Ge(s,e){let t={level:e.intAttr(s,"ilvl")};for(let r of e.elements(s))switch(r.localName){case"startOverride":t.start=e.intAttr(r,"val");break;case"lvl":t.numberingLevel=de(r,e);break}return t}function qe(s,e){var t=e.element(s,"pict"),r=t&&e.element(t,"shape"),a=r&&e.element(r,"imagedata");return a?{id:e.attr(s,"numPicBulletId"),referenceId:e.attr(a,"id"),style:e.attr(r,"style")}:null}class Je extends w{constructor(e,t,r){super(e,t),this._documentParser=r}parseXml(e){Object.assign(this,We(e,this._package.xmlParser)),this.domNumberings=this._documentParser.parseNumberingFile(e)}}class Ze extends w{constructor(e,t,r){super(e,t),this._documentParser=r}parseXml(e){this.styles=this._documentParser.parseStylesFile(e)}}var o;(function(s){s.Document="document",s.Paragraph="paragraph",s.Run="run",s.Break="break",s.NoBreakHyphen="noBreakHyphen",s.Table="table",s.Row="row",s.Cell="cell",s.Hyperlink="hyperlink",s.Drawing="drawing",s.Image="image",s.Text="text",s.Tab="tab",s.Symbol="symbol",s.BookmarkStart="bookmarkStart",s.BookmarkEnd="bookmarkEnd",s.Footer="footer",s.Header="header",s.FootnoteReference="footnoteReference",s.EndnoteReference="endnoteReference",s.Footnote="footnote",s.Endnote="endnote",s.SimpleField="simpleField",s.ComplexField="complexField",s.Instruction="instruction",s.VmlPicture="vmlPicture",s.MmlMath="mmlMath",s.MmlMathParagraph="mmlMathParagraph",s.MmlFraction="mmlFraction",s.MmlFunction="mmlFunction",s.MmlFunctionName="mmlFunctionName",s.MmlNumerator="mmlNumerator",s.MmlDenominator="mmlDenominator",s.MmlRadical="mmlRadical",s.MmlBase="mmlBase",s.MmlDegree="mmlDegree",s.MmlSuperscript="mmlSuperscript",s.MmlSubscript="mmlSubscript",s.MmlPreSubSuper="mmlPreSubSuper",s.MmlSubArgument="mmlSubArgument",s.MmlSuperArgument="mmlSuperArgument",s.MmlNary="mmlNary",s.MmlDelimiter="mmlDelimiter",s.MmlRun="mmlRun",s.MmlEquationArray="mmlEquationArray",s.MmlLimit="mmlLimit",s.MmlLimitLower="mmlLimitLower",s.MmlMatrix="mmlMatrix",s.MmlMatrixRow="mmlMatrixRow",s.MmlBox="mmlBox",s.MmlBar="mmlBar",s.MmlGroupChar="mmlGroupChar",s.VmlElement="vmlElement",s.Inserted="inserted",s.Deleted="deleted",s.DeletedText="deletedText"})(o||(o={}));class X{constructor(){this.children=[],this.cssStyle={}}}class Ye extends X{constructor(){super(...arguments),this.type=o.Header}}class Ke extends X{constructor(){super(...arguments),this.type=o.Footer}}class pe extends w{constructor(e,t,r){super(e,t),this._documentParser=r}parseXml(e){this.rootElement=this.createRootElement(),this.rootElement.children=this._documentParser.parseBodyElements(e)}}class Qe extends pe{createRootElement(){return new Ye}}class et extends pe{createRootElement(){return new Ke}}function tt(s,e){const t={};for(let r of e.elements(s))switch(r.localName){case"Template":t.template=r.textContent;break;case"Pages":t.pages=F(r.textContent);break;case"Words":t.words=F(r.textContent);break;case"Characters":t.characters=F(r.textContent);break;case"Application":t.application=r.textContent;break;case"Lines":t.lines=F(r.textContent);break;case"Paragraphs":t.paragraphs=F(r.textContent);break;case"Company":t.company=r.textContent;break;case"AppVersion":t.appVersion=r.textContent;break}return t}function F(s){if(!(typeof s>"u"))return parseInt(s)}class rt extends w{parseXml(e){this.props=tt(e,this._package.xmlParser)}}function at(s,e){const t={};for(let r of e.elements(s))switch(r.localName){case"title":t.title=r.textContent;break;case"description":t.description=r.textContent;break;case"subject":t.subject=r.textContent;break;case"creator":t.creator=r.textContent;break;case"keywords":t.keywords=r.textContent;break;case"language":t.language=r.textContent;break;case"lastModifiedBy":t.lastModifiedBy=r.textContent;break;case"revision":r.textContent&&(t.revision=parseInt(r.textContent));break}return t}class st extends w{parseXml(e){this.props=at(e,this._package.xmlParser)}}class nt{}function lt(s,e){var t=new nt,r=e.element(s,"themeElements");for(let a of e.elements(r))switch(a.localName){case"clrScheme":t.colorScheme=it(a,e);break;case"fontScheme":t.fontScheme=ot(a,e);break}return t}function it(s,e){var t={name:e.attr(s,"name"),colors:{}};for(let n of e.elements(s)){var r=e.element(n,"srgbClr"),a=e.element(n,"sysClr");r?t.colors[n.localName]=e.attr(r,"val"):a&&(t.colors[n.localName]=e.attr(a,"lastClr"))}return t}function ot(s,e){var t={name:e.attr(s,"name")};for(let r of e.elements(s))switch(r.localName){case"majorFont":t.majorFont=Z(r,e);break;case"minorFont":t.minorFont=Z(r,e);break}return t}function Z(s,e){return{latinTypeface:e.elementAttr(s,"latin","typeface"),eaTypeface:e.elementAttr(s,"ea","typeface"),csTypeface:e.elementAttr(s,"cs","typeface")}}class ct extends w{constructor(e,t){super(e,t)}parseXml(e){this.theme=lt(e,this._package.xmlParser)}}class fe{}class ut extends fe{constructor(){super(...arguments),this.type=o.Footnote}}class ht extends fe{constructor(){super(...arguments),this.type=o.Endnote}}class me extends w{constructor(e,t,r){super(e,t),this._documentParser=r}}class dt extends me{constructor(e,t,r){super(e,t,r)}parseXml(e){this.notes=this._documentParser.parseNotes(e,"footnote",ut)}}class pt extends me{constructor(e,t,r){super(e,t,r)}parseXml(e){this.notes=this._documentParser.parseNotes(e,"endnote",ht)}}function ft(s,e){var t={};for(let r of e.elements(s))switch(r.localName){case"defaultTabStop":t.defaultTabStop=e.lengthAttr(r,"val");break;case"footnotePr":t.footnoteProps=Y(r,e);break;case"endnotePr":t.endnoteProps=Y(r,e);break;case"autoHyphenation":t.autoHyphenation=e.boolAttr(r,"val");break}return t}function Y(s,e){var t={defaultNoteIds:[]};for(let r of e.elements(s))switch(r.localName){case"numFmt":t.nummeringFormat=e.attr(r,"val");break;case"footnote":case"endnote":t.defaultNoteIds.push(e.attr(r,"id"));break}return t}class mt extends w{constructor(e,t){super(e,t)}parseXml(e){this.settings=ft(e,this._package.xmlParser)}}function bt(s,e){return e.elements(s,"property").map(t=>{const r=t.firstChild;return{formatId:e.attr(t,"fmtid"),name:e.attr(t,"name"),type:r.nodeName,value:r.textContent}})}class gt extends w{parseXml(e){this.props=bt(e,this._package.xmlParser)}}const vt=[{type:k.OfficeDocument,target:"word/document.xml"},{type:k.ExtendedProperties,target:"docProps/app.xml"},{type:k.CoreProperties,target:"docProps/core.xml"},{type:k.CustomProperties,target:"docProps/custom.xml"}];class U{constructor(){this.parts=[],this.partsMap={}}static async load(e,t,r){var a=new U;return a._options=r,a._parser=t,a._package=await j.load(e,r),a.rels=await a._package.loadRelationships(),await Promise.all(vt.map(n=>{var i;const c=(i=a.rels.find(u=>u.type===n.type))!==null&&i!==void 0?i:n;return a.loadRelationshipPart(c.target,c.type)})),a}save(e="blob"){return this._package.save(e)}async loadRelationshipPart(e,t){var r;if(this.partsMap[e])return this.partsMap[e];if(!this._package.get(e))return null;let a=null;switch(t){case k.OfficeDocument:this.documentPart=a=new _e(this._package,e,this._parser);break;case k.FontTable:this.fontTablePart=a=new Be(this._package,e);break;case k.Numbering:this.numberingPart=a=new Je(this._package,e,this._parser);break;case k.Styles:this.stylesPart=a=new Ze(this._package,e,this._parser);break;case k.Theme:this.themePart=a=new ct(this._package,e);break;case k.Footnotes:this.footnotesPart=a=new dt(this._package,e,this._parser);break;case k.Endnotes:this.endnotesPart=a=new pt(this._package,e,this._parser);break;case k.Footer:a=new et(this._package,e,this._parser);break;case k.Header:a=new Qe(this._package,e,this._parser);break;case k.CoreProperties:this.corePropsPart=a=new st(this._package,e);break;case k.ExtendedProperties:this.extendedPropsPart=a=new rt(this._package,e);break;case k.CustomProperties:a=new gt(this._package,e);break;case k.Settings:this.settingsPart=a=new mt(this._package,e);break}if(a==null)return Promise.resolve(null);if(this.partsMap[e]=a,this.parts.push(a),await a.load(),((r=a.rels)==null?void 0:r.length)>0){const[n]=$(a.path);await Promise.all(a.rels.map(i=>this.loadRelationshipPart(I(i.target,n),i.type)))}return a}async loadDocumentImage(e,t){const r=await this.loadResource(t??this.documentPart,e,"blob");return this.blobToURL(r)}async loadNumberingImage(e){const t=await this.loadResource(this.numberingPart,e,"blob");return this.blobToURL(t)}async loadFont(e,t){const r=await this.loadResource(this.fontTablePart,e,"uint8array");return r&&this.blobToURL(new Blob([kt(r,t)]))}blobToURL(e){return e?this._options.useBase64URL?Le(e):URL.createObjectURL(e):null}findPartByRelId(e,t=null){var r,a=((r=t.rels)!==null&&r!==void 0?r:this.rels).find(i=>i.id==e);const n=t?$(t.path)[0]:"";return a?this.partsMap[I(a.target,n)]:null}getPathById(e,t){const r=e.rels.find(n=>n.id==t),[a]=$(e.path);return r?I(r.target,a):null}loadResource(e,t,r){const a=this.getPathById(e,t);return a?this._package.load(a,r):Promise.resolve(null)}}function kt(s,e){const r=e.replace(/{|}|-/g,""),a=new Array(16);for(let n=0;n<16;n++)a[16-n-1]=parseInt(r.substr(n*2,2),16);for(let n=0;n<32;n++)s[n]=s[n]^a[n%16];return s}function yt(s,e){return{type:o.BookmarkStart,id:e.attr(s,"id"),name:e.attr(s,"name"),colFirst:e.intAttr(s,"colFirst"),colLast:e.intAttr(s,"colLast")}}function Pt(s,e){return{type:o.BookmarkEnd,id:e.attr(s,"id")}}class St extends X{constructor(){super(...arguments),this.type=o.VmlElement,this.attrs={}}}function be(s,e){var t=new St;switch(s.localName){case"rect":t.tagName="rect",Object.assign(t.attrs,{width:"100%",height:"100%"});break;case"oval":t.tagName="ellipse",Object.assign(t.attrs,{cx:"50%",cy:"50%",rx:"50%",ry:"50%"});break;case"line":t.tagName="line";break;case"shape":t.tagName="g";break;case"textbox":t.tagName="foreignObject",Object.assign(t.attrs,{width:"100%",height:"100%"});break;default:return null}for(const r of l.attrs(s))switch(r.localName){case"style":t.cssStyleText=r.value;break;case"fillcolor":t.attrs.fill=r.value;break;case"from":const[a,n]=K(r.value);Object.assign(t.attrs,{x1:a,y1:n});break;case"to":const[i,c]=K(r.value);Object.assign(t.attrs,{x2:i,y2:c});break}for(const r of l.elements(s))switch(r.localName){case"stroke":Object.assign(t.attrs,wt(r));break;case"fill":Object.assign(t.attrs,Mt());break;case"imagedata":t.tagName="image",Object.assign(t.attrs,{width:"100%",height:"100%"}),t.imageHref={id:l.attr(r,"id"),title:l.attr(r,"title")};break;case"txbxContent":t.children.push(...e.parseBodyElements(r));break;default:const a=be(r,e);a&&t.children.push(a);break}return t}function wt(s){var e;return{stroke:l.attr(s,"color"),"stroke-width":(e=l.lengthAttr(s,"weight",v.Emu))!==null&&e!==void 0?e:"1px"}}function Mt(s){return{}}function K(s){return s.split(",")}var _={shd:"inherit",color:"black",borderColor:"black",highlight:"transparent"};const Ct=[],Q={oMath:o.MmlMath,oMathPara:o.MmlMathParagraph,f:o.MmlFraction,func:o.MmlFunction,fName:o.MmlFunctionName,num:o.MmlNumerator,den:o.MmlDenominator,rad:o.MmlRadical,deg:o.MmlDegree,e:o.MmlBase,sSup:o.MmlSuperscript,sSub:o.MmlSubscript,sPre:o.MmlPreSubSuper,sup:o.MmlSuperArgument,sub:o.MmlSubArgument,d:o.MmlDelimiter,nary:o.MmlNary,eqArr:o.MmlEquationArray,lim:o.MmlLimit,limLow:o.MmlLimitLower,m:o.MmlMatrix,mr:o.MmlMatrixRow,box:o.MmlBox,bar:o.MmlBar,groupChr:o.MmlGroupChar};class Nt{constructor(e){this.options={ignoreWidth:!1,debug:!1,...e}}parseNotes(e,t,r){var a=[];for(let n of l.elements(e,t)){const i=new r;i.id=l.attr(n,"id"),i.noteType=l.attr(n,"type"),i.children=this.parseBodyElements(n),a.push(i)}return a}parseDocumentFile(e){var t=l.element(e,"body"),r=l.element(e,"background"),a=l.element(t,"sectPr");return{type:o.Document,children:this.parseBodyElements(t),props:a?ce(a,l):{},cssStyle:r?this.parseBackground(r):{}}}parseBackground(e){var t={},r=g.colorAttr(e,"color");return r&&(t["background-color"]=r),t}parseBodyElements(e){var t=[];for(let r of l.elements(e))switch(r.localName){case"p":t.push(this.parseParagraph(r));break;case"tbl":t.push(this.parseTable(r));break;case"sdt":t.push(...this.parseSdt(r,a=>this.parseBodyElements(a)));break}return t}parseStylesFile(e){var t=[];return g.foreach(e,r=>{switch(r.localName){case"style":t.push(this.parseStyle(r));break;case"docDefaults":t.push(this.parseDefaultStyles(r));break}}),t}parseDefaultStyles(e){var t={id:null,name:null,target:null,basedOn:null,styles:[]};return g.foreach(e,r=>{switch(r.localName){case"rPrDefault":var a=l.element(r,"rPr");a&&t.styles.push({target:"span",values:this.parseDefaultProperties(a,{})});break;case"pPrDefault":var n=l.element(r,"pPr");n&&t.styles.push({target:"p",values:this.parseDefaultProperties(n,{})});break}}),t}parseStyle(e){var t={id:l.attr(e,"styleId"),isDefault:l.boolAttr(e,"default"),name:null,target:null,basedOn:null,styles:[],linked:null};switch(l.attr(e,"type")){case"paragraph":t.target="p";break;case"table":t.target="table";break;case"character":t.target="span";break}return g.foreach(e,r=>{switch(r.localName){case"basedOn":t.basedOn=l.attr(r,"val");break;case"name":t.name=l.attr(r,"val");break;case"link":t.linked=l.attr(r,"val");break;case"next":t.next=l.attr(r,"val");break;case"aliases":t.aliases=l.attr(r,"val").split(",");break;case"pPr":t.styles.push({target:"p",values:this.parseDefaultProperties(r,{})}),t.paragraphProps=ue(r,l);break;case"rPr":t.styles.push({target:"span",values:this.parseDefaultProperties(r,{})}),t.runProps=W(r,l);break;case"tblPr":case"tcPr":t.styles.push({target:"td",values:this.parseDefaultProperties(r,{})});break;case"tblStylePr":for(let a of this.parseTableStyle(r))t.styles.push(a);break;case"rsid":case"qFormat":case"hidden":case"semiHidden":case"unhideWhenUsed":case"autoRedefine":case"uiPriority":break;default:this.options.debug&&console.warn(`DOCX: Unknown style element: ${r.localName}`)}}),t}parseTableStyle(e){var t=[],r=l.attr(e,"type"),a="",n="";switch(r){case"firstRow":n=".first-row",a="tr.first-row td";break;case"lastRow":n=".last-row",a="tr.last-row td";break;case"firstCol":n=".first-col",a="td.first-col";break;case"lastCol":n=".last-col",a="td.last-col";break;case"band1Vert":n=":not(.no-vband)",a="td.odd-col";break;case"band2Vert":n=":not(.no-vband)",a="td.even-col";break;case"band1Horz":n=":not(.no-hband)",a="tr.odd-row";break;case"band2Horz":n=":not(.no-hband)",a="tr.even-row";break;default:return[]}return g.foreach(e,i=>{switch(i.localName){case"pPr":t.push({target:`${a} p`,mod:n,values:this.parseDefaultProperties(i,{})});break;case"rPr":t.push({target:`${a} span`,mod:n,values:this.parseDefaultProperties(i,{})});break;case"tblPr":case"tcPr":t.push({target:a,mod:n,values:this.parseDefaultProperties(i,{})});break}}),t}parseNumberingFile(e){var t=[],r={},a=[];return g.foreach(e,n=>{switch(n.localName){case"abstractNum":this.parseAbstractNumbering(n,a).forEach(u=>t.push(u));break;case"numPicBullet":a.push(this.parseNumberingPicBullet(n));break;case"num":var i=l.attr(n,"numId"),c=l.elementAttr(n,"abstractNumId","val");r[c]=i;break}}),t.forEach(n=>n.id=r[n.id]),t}parseNumberingPicBullet(e){var t=l.element(e,"pict"),r=t&&l.element(t,"shape"),a=r&&l.element(r,"imagedata");return a?{id:l.intAttr(e,"numPicBulletId"),src:l.attr(a,"id"),style:l.attr(r,"style")}:null}parseAbstractNumbering(e,t){var r=[],a=l.attr(e,"abstractNumId");return g.foreach(e,n=>{switch(n.localName){case"lvl":r.push(this.parseNumberingLevel(a,n,t));break}}),r}parseNumberingLevel(e,t,r){var a={id:e,level:l.intAttr(t,"ilvl"),start:1,pStyleName:void 0,pStyle:{},rStyle:{},suff:"tab"};return g.foreach(t,n=>{switch(n.localName){case"start":a.start=l.intAttr(n,"val");break;case"pPr":this.parseDefaultProperties(n,a.pStyle);break;case"rPr":this.parseDefaultProperties(n,a.rStyle);break;case"lvlPicBulletId":var i=l.intAttr(n,"val");a.bullet=r.find(c=>c.id==i);break;case"lvlText":a.levelText=l.attr(n,"val");break;case"pStyle":a.pStyleName=l.attr(n,"val");break;case"numFmt":a.format=l.attr(n,"val");break;case"suff":a.suff=l.attr(n,"val");break}}),a}parseSdt(e,t){const r=l.element(e,"sdtContent");return r?t(r):[]}parseInserted(e,t){var r,a;return{type:o.Inserted,children:(a=(r=t(e))==null?void 0:r.children)!==null&&a!==void 0?a:[]}}parseDeleted(e,t){var r,a;return{type:o.Deleted,children:(a=(r=t(e))==null?void 0:r.children)!==null&&a!==void 0?a:[]}}parseParagraph(e){var t={type:o.Paragraph,children:[]};for(let r of l.elements(e))switch(r.localName){case"pPr":this.parseParagraphProperties(r,t);break;case"r":t.children.push(this.parseRun(r,t));break;case"hyperlink":t.children.push(this.parseHyperlink(r,t));break;case"bookmarkStart":t.children.push(yt(r,l));break;case"bookmarkEnd":t.children.push(Pt(r,l));break;case"oMath":case"oMathPara":t.children.push(this.parseMathElement(r));break;case"sdt":t.children.push(...this.parseSdt(r,a=>this.parseParagraph(a).children));break;case"ins":t.children.push(this.parseInserted(r,a=>this.parseParagraph(a)));break;case"del":t.children.push(this.parseDeleted(r,a=>this.parseParagraph(a)));break}return t}parseParagraphProperties(e,t){this.parseDefaultProperties(e,t.cssStyle={},null,r=>{if(he(r,t,l))return!0;switch(r.localName){case"pStyle":t.styleName=l.attr(r,"val");break;case"cnfStyle":t.className=f.classNameOfCnfStyle(r);break;case"framePr":this.parseFrame(r,t);break;case"rPr":break;default:return!1}return!0})}parseFrame(e,t){var r=l.attr(e,"dropCap");r=="drop"&&(t.cssStyle.float="left")}parseHyperlink(e,t){var r={type:o.Hyperlink,parent:t,children:[]},a=l.attr(e,"anchor"),n=l.attr(e,"id");return a&&(r.href="#"+a),n&&(r.id=n),g.foreach(e,i=>{switch(i.localName){case"r":r.children.push(this.parseRun(i,r));break}}),r}parseRun(e,t){var r={type:o.Run,parent:t,children:[]};return g.foreach(e,a=>{switch(a=this.checkAlternateContent(a),a.localName){case"t":r.children.push({type:o.Text,text:a.textContent});break;case"delText":r.children.push({type:o.DeletedText,text:a.textContent});break;case"fldSimple":r.children.push({type:o.SimpleField,instruction:l.attr(a,"instr"),lock:l.boolAttr(a,"lock",!1),dirty:l.boolAttr(a,"dirty",!1)});break;case"instrText":r.fieldRun=!0,r.children.push({type:o.Instruction,text:a.textContent});break;case"fldChar":r.fieldRun=!0,r.children.push({type:o.ComplexField,charType:l.attr(a,"fldCharType"),lock:l.boolAttr(a,"lock",!1),dirty:l.boolAttr(a,"dirty",!1)});break;case"noBreakHyphen":r.children.push({type:o.NoBreakHyphen});break;case"br":r.children.push({type:o.Break,break:l.attr(a,"type")||"textWrapping"});break;case"lastRenderedPageBreak":r.children.push({type:o.Break,break:"lastRenderedPageBreak"});break;case"sym":r.children.push({type:o.Symbol,font:l.attr(a,"font"),char:l.attr(a,"char")});break;case"tab":r.children.push({type:o.Tab});break;case"footnoteReference":r.children.push({type:o.FootnoteReference,id:l.attr(a,"id")});break;case"endnoteReference":r.children.push({type:o.EndnoteReference,id:l.attr(a,"id")});break;case"drawing":let n=this.parseDrawing(a);n&&(r.children=[n]);break;case"pict":r.children.push(this.parseVmlPicture(a));break;case"rPr":this.parseRunProperties(a,r);break}}),r}parseMathElement(e){const t=`${e.localName}Pr`,r={type:Q[e.localName],children:[]};for(const n of l.elements(e))if(Q[n.localName])r.children.push(this.parseMathElement(n));else if(n.localName=="r"){var a=this.parseRun(n);a.type=o.MmlRun,r.children.push(a)}else n.localName==t&&(r.props=this.parseMathProperies(n));return r}parseMathProperies(e){const t={};for(const r of l.elements(e))switch(r.localName){case"chr":t.char=l.attr(r,"val");break;case"vertJc":t.verticalJustification=l.attr(r,"val");break;case"pos":t.position=l.attr(r,"val");break;case"degHide":t.hideDegree=l.boolAttr(r,"val");break;case"begChr":t.beginChar=l.attr(r,"val");break;case"endChr":t.endChar=l.attr(r,"val");break}return t}parseRunProperties(e,t){this.parseDefaultProperties(e,t.cssStyle={},null,r=>{switch(r.localName){case"rStyle":t.styleName=l.attr(r,"val");break;case"vertAlign":t.verticalAlign=f.valueOfVertAlign(r,!0);break;default:return!1}return!0})}parseVmlPicture(e){const t={type:o.VmlPicture,children:[]};for(const r of l.elements(e)){const a=be(r,this);a&&t.children.push(a)}return t}checkAlternateContent(e){var t;if(e.localName!="AlternateContent")return e;var r=l.element(e,"Choice");if(r){var a=l.attr(r,"Requires"),n=e.lookupNamespaceURI(a);if(Ct.includes(n))return r.firstElementChild}return(t=l.element(e,"Fallback"))==null?void 0:t.firstElementChild}parseDrawing(e){for(var t of l.elements(e))switch(t.localName){case"inline":case"anchor":return this.parseDrawingWrapper(t)}}parseDrawingWrapper(e){var t={type:o.Drawing,children:[],cssStyle:{}},r=e.localName=="anchor";let a=null,n=l.boolAttr(e,"simplePos"),i={relative:"page",align:"left",offset:"0"},c={relative:"page",align:"top",offset:"0"};for(var u of l.elements(e))switch(u.localName){case"simplePos":n&&(i.offset=l.lengthAttr(u,"x",v.Emu),c.offset=l.lengthAttr(u,"y",v.Emu));break;case"extent":t.cssStyle.width=l.lengthAttr(u,"cx",v.Emu),t.cssStyle.height=l.lengthAttr(u,"cy",v.Emu);break;case"positionH":case"positionV":if(!n){var h;let P=u.localName=="positionH"?i:c;var d=l.element(u,"align"),b=l.element(u,"posOffset");P.relative=(h=l.attr(u,"relativeFrom"))!==null&&h!==void 0?h:P.relative,d&&(P.align=d.textContent),b&&(P.offset=g.sizeValue(b,v.Emu))}break;case"wrapTopAndBottom":a="wrapTopAndBottom";break;case"wrapNone":a="wrapNone";break;case"graphic":var y=this.parseGraphic(u);y&&t.children.push(y);break}return a=="wrapTopAndBottom"?(t.cssStyle.display="block",i.align&&(t.cssStyle["text-align"]=i.align,t.cssStyle.width="100%")):a=="wrapNone"?(t.cssStyle.display="block",t.cssStyle.position="relative",t.cssStyle.width="0px",t.cssStyle.height="0px",i.offset&&(t.cssStyle.left=i.offset),c.offset&&(t.cssStyle.top=c.offset)):r&&(i.align=="left"||i.align=="right")&&(t.cssStyle.float=i.align),t}parseGraphic(e){var t=l.element(e,"graphicData");for(let r of l.elements(t))switch(r.localName){case"pic":return this.parsePicture(r)}return null}parsePicture(e){var t={type:o.Image,src:"",cssStyle:{}},r=l.element(e,"blipFill"),a=l.element(r,"blip");t.src=l.attr(a,"embed");var n=l.element(e,"spPr"),i=l.element(n,"xfrm");t.cssStyle.position="relative";for(var c of l.elements(i))switch(c.localName){case"ext":t.cssStyle.width=l.lengthAttr(c,"cx",v.Emu),t.cssStyle.height=l.lengthAttr(c,"cy",v.Emu);break;case"off":t.cssStyle.left=l.lengthAttr(c,"x",v.Emu),t.cssStyle.top=l.lengthAttr(c,"y",v.Emu);break}return t}parseTable(e){var t={type:o.Table,children:[]};return g.foreach(e,r=>{switch(r.localName){case"tr":t.children.push(this.parseTableRow(r));break;case"tblGrid":t.columns=this.parseTableColumns(r);break;case"tblPr":this.parseTableProperties(r,t);break}}),t}parseTableColumns(e){var t=[];return g.foreach(e,r=>{switch(r.localName){case"gridCol":t.push({width:l.lengthAttr(r,"w")});break}}),t}parseTableProperties(e,t){switch(t.cssStyle={},t.cellStyle={},this.parseDefaultProperties(e,t.cssStyle,t.cellStyle,r=>{switch(r.localName){case"tblStyle":t.styleName=l.attr(r,"val");break;case"tblLook":t.className=f.classNameOftblLook(r);break;case"tblpPr":this.parseTablePosition(r,t);break;case"tblStyleColBandSize":t.colBandSize=l.intAttr(r,"val");break;case"tblStyleRowBandSize":t.rowBandSize=l.intAttr(r,"val");break;default:return!1}return!0}),t.cssStyle["text-align"]){case"center":delete t.cssStyle["text-align"],t.cssStyle["margin-left"]="auto",t.cssStyle["margin-right"]="auto";break;case"right":delete t.cssStyle["text-align"],t.cssStyle["margin-left"]="auto";break}}parseTablePosition(e,t){var r=l.lengthAttr(e,"topFromText"),a=l.lengthAttr(e,"bottomFromText"),n=l.lengthAttr(e,"rightFromText"),i=l.lengthAttr(e,"leftFromText");t.cssStyle.float="left",t.cssStyle["margin-bottom"]=f.addSize(t.cssStyle["margin-bottom"],a),t.cssStyle["margin-left"]=f.addSize(t.cssStyle["margin-left"],i),t.cssStyle["margin-right"]=f.addSize(t.cssStyle["margin-right"],n),t.cssStyle["margin-top"]=f.addSize(t.cssStyle["margin-top"],r)}parseTableRow(e){var t={type:o.Row,children:[]};return g.foreach(e,r=>{switch(r.localName){case"tc":t.children.push(this.parseTableCell(r));break;case"trPr":this.parseTableRowProperties(r,t);break}}),t}parseTableRowProperties(e,t){t.cssStyle=this.parseDefaultProperties(e,{},null,r=>{switch(r.localName){case"cnfStyle":t.className=f.classNameOfCnfStyle(r);break;case"tblHeader":t.isHeader=l.boolAttr(r,"val");break;default:return!1}return!0})}parseTableCell(e){var t={type:o.Cell,children:[]};return g.foreach(e,r=>{switch(r.localName){case"tbl":t.children.push(this.parseTable(r));break;case"p":t.children.push(this.parseParagraph(r));break;case"tcPr":this.parseTableCellProperties(r,t);break}}),t}parseTableCellProperties(e,t){t.cssStyle=this.parseDefaultProperties(e,{},null,r=>{var a;switch(r.localName){case"gridSpan":t.span=l.intAttr(r,"val",null);break;case"vMerge":t.verticalMerge=(a=l.attr(r,"val"))!==null&&a!==void 0?a:"continue";break;case"cnfStyle":t.className=f.classNameOfCnfStyle(r);break;default:return!1}return!0})}parseDefaultProperties(e,t=null,r=null,a=null){return t=t||{},g.foreach(e,n=>{if(!(a!=null&&a(n)))switch(n.localName){case"jc":t["text-align"]=f.valueOfJc(n);break;case"textAlignment":t["vertical-align"]=f.valueOfTextAlignment(n);break;case"color":t.color=g.colorAttr(n,"val",null,_.color);break;case"sz":t["font-size"]=t["min-height"]=l.lengthAttr(n,"val",v.FontSize);break;case"shd":t["background-color"]=g.colorAttr(n,"fill",null,_.shd);break;case"highlight":t["background-color"]=g.colorAttr(n,"val",null,_.highlight);break;case"vertAlign":break;case"position":t.verticalAlign=l.lengthAttr(n,"val",v.FontSize);break;case"tcW":if(this.options.ignoreWidth)break;case"tblW":t.width=f.valueOfSize(n,"w");break;case"trHeight":this.parseTrHeight(n,t);break;case"strike":t["text-decoration"]=l.boolAttr(n,"val",!0)?"line-through":"none";break;case"b":t["font-weight"]=l.boolAttr(n,"val",!0)?"bold":"normal";break;case"i":t["font-style"]=l.boolAttr(n,"val",!0)?"italic":"normal";break;case"caps":t["text-transform"]=l.boolAttr(n,"val",!0)?"uppercase":"none";break;case"smallCaps":t["font-variant"]=l.boolAttr(n,"val",!0)?"small-caps":"none";break;case"u":this.parseUnderline(n,t);break;case"ind":case"tblInd":this.parseIndentation(n,t);break;case"rFonts":this.parseFont(n,t);break;case"tblBorders":this.parseBorderProperties(n,r||t);break;case"tblCellSpacing":t["border-spacing"]=f.valueOfMargin(n),t["border-collapse"]="separate";break;case"pBdr":this.parseBorderProperties(n,t);break;case"bdr":t.border=f.valueOfBorder(n);break;case"tcBorders":this.parseBorderProperties(n,t);break;case"vanish":l.boolAttr(n,"val",!0)&&(t.display="none");break;case"kern":break;case"noWrap":break;case"tblCellMar":case"tcMar":this.parseMarginProperties(n,r||t);break;case"tblLayout":t["table-layout"]=f.valueOfTblLayout(n);break;case"vAlign":t["vertical-align"]=f.valueOfTextAlignment(n);break;case"spacing":e.localName=="pPr"&&this.parseSpacing(n,t);break;case"wordWrap":l.boolAttr(n,"val")&&(t["overflow-wrap"]="break-word");break;case"suppressAutoHyphens":t.hyphens=l.boolAttr(n,"val",!0)?"none":"auto";break;case"lang":t.$lang=l.attr(n,"val");break;case"bCs":case"iCs":case"szCs":case"tabs":case"outlineLvl":case"contextualSpacing":case"tblStyleColBandSize":case"tblStyleRowBandSize":case"webHidden":case"pageBreakBefore":case"suppressLineNumbers":case"keepLines":case"keepNext":case"widowControl":case"bidi":case"rtl":case"noProof":break;default:this.options.debug&&console.warn(`DOCX: Unknown document element: ${e.localName}.${n.localName}`);break}}),t}parseUnderline(e,t){var r=l.attr(e,"val");if(r!=null){switch(r){case"dash":case"dashDotDotHeavy":case"dashDotHeavy":case"dashedHeavy":case"dashLong":case"dashLongHeavy":case"dotDash":case"dotDotDash":t["text-decoration"]="underline dashed";break;case"dotted":case"dottedHeavy":t["text-decoration"]="underline dotted";break;case"double":t["text-decoration"]="underline double";break;case"single":case"thick":t["text-decoration"]="underline";break;case"wave":case"wavyDouble":case"wavyHeavy":t["text-decoration"]="underline wavy";break;case"words":t["text-decoration"]="underline";break;case"none":t["text-decoration"]="none";break}var a=g.colorAttr(e,"color");a&&(t["text-decoration-color"]=a)}}parseFont(e,t){var r=l.attr(e,"ascii"),a=f.themeValue(e,"asciiTheme"),n=[r,a].filter(i=>i).join(", ");n.length>0&&(t["font-family"]=n)}parseIndentation(e,t){var r=l.lengthAttr(e,"firstLine"),a=l.lengthAttr(e,"hanging"),n=l.lengthAttr(e,"left"),i=l.lengthAttr(e,"start"),c=l.lengthAttr(e,"right"),u=l.lengthAttr(e,"end");r&&(t["text-indent"]=r),a&&(t["text-indent"]=`-${a}`),(n||i)&&(t["margin-left"]=n||i),(c||u)&&(t["margin-right"]=c||u)}parseSpacing(e,t){var r=l.lengthAttr(e,"before"),a=l.lengthAttr(e,"after"),n=l.intAttr(e,"line",null),i=l.attr(e,"lineRule");if(r&&(t["margin-top"]=r),a&&(t["margin-bottom"]=a),n!==null)switch(i){case"auto":t["line-height"]=`${(n/240).toFixed(2)}`;break;case"atLeast":t["line-height"]=`calc(100% + ${n/20}pt)`;break;default:t["line-height"]=t["min-height"]=`${n/20}pt`;break}}parseMarginProperties(e,t){g.foreach(e,r=>{switch(r.localName){case"left":t["padding-left"]=f.valueOfMargin(r);break;case"right":t["padding-right"]=f.valueOfMargin(r);break;case"top":t["padding-top"]=f.valueOfMargin(r);break;case"bottom":t["padding-bottom"]=f.valueOfMargin(r);break}})}parseTrHeight(e,t){switch(l.attr(e,"hRule")){case"exact":t.height=l.lengthAttr(e,"val");break;case"atLeast":default:t.height=l.lengthAttr(e,"val");break}}parseBorderProperties(e,t){g.foreach(e,r=>{switch(r.localName){case"start":case"left":t["border-left"]=f.valueOfBorder(r);break;case"end":case"right":t["border-right"]=f.valueOfBorder(r);break;case"top":t["border-top"]=f.valueOfBorder(r);break;case"bottom":t["border-bottom"]=f.valueOfBorder(r);break}})}}const At=["black","blue","cyan","darkBlue","darkCyan","darkGray","darkGreen","darkMagenta","darkRed","darkYellow","green","lightGray","magenta","none","red","white","yellow"];class g{static foreach(e,t){for(var r=0;rt[n]=="1").join(" ")}static valueOfJc(e){var t=l.attr(e,"val");switch(t){case"start":case"left":return"left";case"center":return"center";case"end":case"right":return"right";case"both":return"justify"}return t}static valueOfVertAlign(e,t=!1){var r=l.attr(e,"val");switch(r){case"subscript":return"sub";case"superscript":return t?"sup":"super"}return t?null:r}static valueOfTextAlignment(e){var t=l.attr(e,"val");switch(t){case"auto":case"baseline":return"baseline";case"top":return"top";case"center":return"middle";case"bottom":return"bottom"}return t}static addSize(e,t){return e==null?t:t==null?e:`calc(${e} + ${t})`}static classNameOftblLook(e){const t=l.hexAttr(e,"val",0);let r="";return(l.boolAttr(e,"firstRow")||t&32)&&(r+=" first-row"),(l.boolAttr(e,"lastRow")||t&64)&&(r+=" last-row"),(l.boolAttr(e,"firstColumn")||t&128)&&(r+=" first-col"),(l.boolAttr(e,"lastColumn")||t&256)&&(r+=" last-col"),(l.boolAttr(e,"noHBand")||t&512)&&(r+=" no-hband"),(l.boolAttr(e,"noVBand")||t&1024)&&(r+=" no-vband"),r.trim()}}const ee={pos:0,leader:"none",style:"left"},Et=50;function xt(s=document.body){const e=document.createElement("div");e.style.width="100pt",s.appendChild(e);const t=100/e.offsetWidth;return s.removeChild(e),t}function Ft(s,e,t,r=72/96){const a=s.closest("p"),n=s.getBoundingClientRect(),i=a.getBoundingClientRect(),c=getComputedStyle(a),u=(e==null?void 0:e.length)>0?e.map(S=>({pos:te(S.position),leader:S.leader,style:S.style})).sort((S,R)=>S.pos-R.pos):[ee],h=u[u.length-1],d=i.width*r,b=te(t);let y=h.pos+b;if(yS.style!="clear"&&S.pos>M);if(C==null)return;let O=1;if(C.style=="right"||C.style=="center"){const S=Array.from(a.querySelectorAll(`.${s.className}`)),R=S.indexOf(s)+1,L=document.createRange();L.setStart(s,1),Rc.id)),e.endnotesPart&&(this.endnoteMap=A(e.endnotesPart.notes,c=>c.id)),e.settingsPart&&(this.defaultTabSize=(n=e.settingsPart.settings)==null?void 0:n.defaultTabStop),!a.ignoreFonts&&e.fontTablePart&&this.renderFontTable(e.fontTablePart,r);var i=this.renderSections(e.documentPart.body);this.options.inWrapper?t.appendChild(this.renderWrapper(i)):z(t,i),this.refreshTabStops()}renderTheme(e,t){var r,a;const n={},i=(r=e.theme)==null?void 0:r.fontScheme;i&&(i.majorFont&&(n["--docx-majorHAnsi-font"]=i.majorFont.latinTypeface),i.minorFont&&(n["--docx-minorHAnsi-font"]=i.minorFont.latinTypeface));const c=(a=e.theme)==null?void 0:a.colorScheme;if(c)for(let[h,d]of Object.entries(c.colors))n[`--docx-${h}-color`]=`#${d}`;const u=this.styleToString(`.${this.className}`,n);t.appendChild(E(u))}renderFontTable(e,t){for(let r of e.fonts)for(let a of r.embedFontRefs)this.tasks.push(this.document.loadFont(a.id,a.key).then(n=>{const i={"font-family":r.name,src:`url(${n})`};(a.type=="bold"||a.type=="boldItalic")&&(i["font-weight"]="bold"),(a.type=="italic"||a.type=="boldItalic")&&(i["font-style"]="italic"),B(t,`docxjs ${r.name} font`);const c=this.styleToString("@font-face",i);t.appendChild(E(c)),this.refreshTabStops()}))}processStyleName(e){return e?`${this.className}_${Re(e)}`:this.className}processStyles(e){const t=A(e.filter(a=>a.id!=null),a=>a.id);for(const a of e.filter(n=>n.basedOn)){var r=t[a.basedOn];if(r){a.paragraphProps=D(a.paragraphProps,r.paragraphProps),a.runProps=D(a.runProps,r.runProps);for(const n of r.styles){const i=a.styles.find(c=>c.target==n.target);i?this.copyStyleProperties(n.values,i.values):a.styles.push({...n,values:{...n.values}})}}else this.options.debug&&console.warn(`Can't find base style ${a.basedOn}`)}for(let a of e)a.cssName=this.processStyleName(a.id);return t}prodessNumberings(e){var t;for(let r of e.filter(a=>a.pStyleName)){const a=this.findStyle(r.pStyleName);(t=a==null?void 0:a.paragraphProps)!=null&&t.numbering&&(a.paragraphProps.numbering.level=r.level)}}processElement(e){if(e.children)for(var t of e.children)t.parent=e,t.type==o.Table?this.processTable(t):this.processElement(t)}processTable(e){for(var t of e.children)for(var r of t.children)r.cssStyle=this.copyStyleProperties(e.cellStyle,r.cssStyle,["border-left","border-right","border-top","border-bottom","padding-left","padding-right","padding-top","padding-bottom"]),this.processElement(r)}copyStyleProperties(e,t,r=null){if(!e)return t;t==null&&(t={}),r==null&&(r=Object.getOwnPropertyNames(e));for(var a of r)e.hasOwnProperty(a)&&!t.hasOwnProperty(a)&&(t[a]=e[a]);return t}createSection(e,t){var r=this.createElement("section",{className:e});return t&&(t.pageMargins&&(r.style.paddingLeft=t.pageMargins.left,r.style.paddingRight=t.pageMargins.right,r.style.paddingTop=t.pageMargins.top,r.style.paddingBottom=t.pageMargins.bottom),t.pageSize&&(this.options.ignoreWidth||(r.style.width=t.pageSize.width),this.options.ignoreHeight||(r.style.minHeight=t.pageSize.height)),t.columns&&t.columns.numberOfColumns&&(r.style.columnCount=`${t.columns.numberOfColumns}`,r.style.columnGap=t.columns.space,t.columns.separator&&(r.style.columnRule="1px solid black"))),r}renderSections(e){const t=[];this.processElement(e);const r=this.splitBySection(e.children);let a=null;for(let i=0,c=r.length;id.type=="first"):null)!==null&&c!==void 0?c:r%2==1?e.find(d=>d.type=="even"):null)!==null&&i!==void 0?i:e.find(d=>d.type=="default"),h=u&&this.document.findPartByRelId(u.id,this.document.documentPart);if(h){this.currentPart=h,this.usedHederFooterParts.includes(h.path)||(this.processElement(h.rootElement),this.usedHederFooterParts.push(h.path));const[d]=this.renderElements([h.rootElement],n);t!=null&&t.pageMargins&&(h.rootElement.type===o.Header?(d.style.marginTop=`calc(${t.pageMargins.header} - ${t.pageMargins.top})`,d.style.minHeight=`calc(${t.pageMargins.top} - ${t.pageMargins.header})`):h.rootElement.type===o.Footer&&(d.style.marginBottom=`calc(${t.pageMargins.footer} - ${t.pageMargins.bottom})`,d.style.minHeight=`calc(${t.pageMargins.bottom} - ${t.pageMargins.footer})`)),this.currentPart=null}}}isPageBreakElement(e){return e.type!=o.Break?!1:e.break=="lastRenderedPageBreak"?!this.options.ignoreLastRenderedPageBreak:e.break=="page"}splitBySection(e){var t,r={sectProps:null,elements:[]},a=[r];for(let b of e){if(b.type==o.Paragraph){const y=this.findStyle(b.styleName);(t=y==null?void 0:y.paragraphProps)!=null&&t.pageBreakBefore&&(r.sectProps=n,r={sectProps:null,elements:[]},a.push(r))}if(r.elements.push(b),b.type==o.Paragraph){const y=b;var n=y.sectionProps,i=-1,c=-1;if(this.options.breakPages&&y.children&&(i=y.children.findIndex(P=>{var N,M;return c=(M=(N=P.children)==null?void 0:N.findIndex(this.isPageBreakElement.bind(this)))!==null&&M!==void 0?M:-1,c!=-1})),(n||i!=-1)&&(r.sectProps=n,r={sectProps:null,elements:[]},a.push(r)),i!=-1){let P=y.children[i],N=c=0;b--)a[b].sectProps==null?a[b].sectProps=d:d=a[b].sectProps;return a}renderWrapper(e){return this.createElement("div",{className:`${this.className}-wrapper`},e)}renderDefaultStyle(){var e=this.className,t=` +.${e}-wrapper { background: gray; padding: 30px; padding-bottom: 0px; display: flex; flex-flow: column; align-items: center; } +.${e}-wrapper>section.${e} { background: white; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); margin-bottom: 30px; } +.${e} { color: black; hyphens: auto; text-underline-position: from-font; } +section.${e} { box-sizing: border-box; display: flex; flex-flow: column nowrap; position: relative; overflow: hidden; } +section.${e}>article { margin-bottom: auto; z-index: 1; } +section.${e}>footer { z-index: 1; } +.${e} table { border-collapse: collapse; } +.${e} table td, .${e} table th { vertical-align: top; } +.${e} p { margin: 0pt; min-height: 1em; } +.${e} span { white-space: pre-wrap; overflow-wrap: break-word; } +.${e} a { color: inherit; text-decoration: inherit; } +`;return E(t)}renderNumbering(e,t){var r="",a=[];for(var n of e){var i=`p.${this.numberingClass(n.id,n.level)}`,c="none";if(n.bullet){let u=`--${this.className}-${n.bullet.src}`.toLowerCase();r+=this.styleToString(`${i}:before`,{content:"' '",display:"inline-block",background:`var(${u})`},n.bullet.style),this.tasks.push(this.document.loadNumberingImage(n.bullet.src).then(h=>{var d=`${this.rootSelector} { ${u}: url(${h}) }`;t.appendChild(E(d))}))}else if(n.levelText){let u=this.numberingCounter(n.id,n.level);const h=u+" "+(n.start-1);n.level>0&&(r+=this.styleToString(`p.${this.numberingClass(n.id,n.level-1)}`,{"counter-reset":h})),a.push(h),r+=this.styleToString(`${i}:before`,{content:this.levelTextToContent(n.levelText,n.suff,n.id,this.numFormatToCssValue(n.format)),"counter-increment":u,...n.rStyle})}else c=this.numFormatToCssValue(n.format);r+=this.styleToString(i,{display:"list-item","list-style-position":"inside","list-style-type":c,...n.pStyle})}return a.length>0&&(r+=this.styleToString(this.rootSelector,{"counter-reset":a.join(" ")})),E(r)}renderStyles(e){var t="";const r=this.styleMap,a=A(e.filter(h=>h.isDefault),h=>h.target);for(const h of e){var n=h.styles;if(h.linked){var i=h.linked&&r[h.linked];i?n=n.concat(i.styles):this.options.debug&&console.warn(`Can't find linked style ${h.linked}`)}for(const d of n){var c,u=`${(c=h.target)!==null&&c!==void 0?c:""}.${h.cssName}`;h.target!=d.target&&(u+=` ${d.target}`),a[h.target]==h&&(u=`.${this.className} ${h.target}, `+u),t+=this.styleToString(u,d.values)}}return E(t)}renderNotes(e,t,r){var a=e.map(i=>t[i]).filter(i=>i);if(a.length>0){var n=this.createElement("ol",null,this.renderElements(a));r.appendChild(n)}}renderElement(e){switch(e.type){case o.Paragraph:return this.renderParagraph(e);case o.BookmarkStart:return this.renderBookmarkStart(e);case o.BookmarkEnd:return null;case o.Run:return this.renderRun(e);case o.Table:return this.renderTable(e);case o.Row:return this.renderTableRow(e);case o.Cell:return this.renderTableCell(e);case o.Hyperlink:return this.renderHyperlink(e);case o.Drawing:return this.renderDrawing(e);case o.Image:return this.renderImage(e);case o.Text:return this.renderText(e);case o.Text:return this.renderText(e);case o.DeletedText:return this.renderDeletedText(e);case o.Tab:return this.renderTab(e);case o.Symbol:return this.renderSymbol(e);case o.Break:return this.renderBreak(e);case o.Footer:return this.renderContainer(e,"footer");case o.Header:return this.renderContainer(e,"header");case o.Footnote:case o.Endnote:return this.renderContainer(e,"li");case o.FootnoteReference:return this.renderFootnoteReference(e);case o.EndnoteReference:return this.renderEndnoteReference(e);case o.NoBreakHyphen:return this.createElement("wbr");case o.VmlPicture:return this.renderVmlPicture(e);case o.VmlElement:return this.renderVmlElement(e);case o.MmlMath:return this.renderContainerNS(e,p.mathML,"math",{xmlns:p.mathML});case o.MmlMathParagraph:return this.renderContainer(e,"span");case o.MmlFraction:return this.renderContainerNS(e,p.mathML,"mfrac");case o.MmlBase:return this.renderContainerNS(e,p.mathML,e.parent.type==o.MmlMatrixRow?"mtd":"mrow");case o.MmlNumerator:case o.MmlDenominator:case o.MmlFunction:case o.MmlLimit:case o.MmlBox:return this.renderContainerNS(e,p.mathML,"mrow");case o.MmlGroupChar:return this.renderMmlGroupChar(e);case o.MmlLimitLower:return this.renderContainerNS(e,p.mathML,"munder");case o.MmlMatrix:return this.renderContainerNS(e,p.mathML,"mtable");case o.MmlMatrixRow:return this.renderContainerNS(e,p.mathML,"mtr");case o.MmlRadical:return this.renderMmlRadical(e);case o.MmlSuperscript:return this.renderContainerNS(e,p.mathML,"msup");case o.MmlSubscript:return this.renderContainerNS(e,p.mathML,"msub");case o.MmlDegree:case o.MmlSuperArgument:case o.MmlSubArgument:return this.renderContainerNS(e,p.mathML,"mn");case o.MmlFunctionName:return this.renderContainerNS(e,p.mathML,"ms");case o.MmlDelimiter:return this.renderMmlDelimiter(e);case o.MmlRun:return this.renderMmlRun(e);case o.MmlNary:return this.renderMmlNary(e);case o.MmlPreSubSuper:return this.renderMmlPreSubSuper(e);case o.MmlBar:return this.renderMmlBar(e);case o.MmlEquationArray:return this.renderMllList(e);case o.Inserted:return this.renderInserted(e);case o.Deleted:return this.renderDeleted(e)}return null}renderChildren(e,t){return this.renderElements(e.children,t)}renderElements(e,t){if(e==null)return null;var r=e.flatMap(a=>this.renderElement(a)).filter(a=>a!=null);return t&&z(t,r),r}renderContainer(e,t,r){return this.createElement(t,r,this.renderChildren(e))}renderContainerNS(e,t,r,a){return m(t,r,a,this.renderChildren(e))}renderParagraph(e){var t,r,a,n,i=this.createElement("p");const c=this.findStyle(e.styleName);(a=e.tabs)!==null&&a!==void 0||(e.tabs=(t=c==null?void 0:c.paragraphProps)==null?void 0:t.tabs),this.renderClass(e,i),this.renderChildren(e,i),this.renderStyleValues(e.cssStyle,i),this.renderCommonProperties(i.style,e);const u=(n=e.numbering)!==null&&n!==void 0?n:(r=c==null?void 0:c.paragraphProps)==null?void 0:r.numbering;return u&&i.classList.add(this.numberingClass(u.id,u.level)),i}renderRunProperties(e,t){this.renderCommonProperties(e,t)}renderCommonProperties(e,t){t!=null&&(t.color&&(e.color=t.color),t.fontSize&&(e["font-size"]=t.fontSize))}renderHyperlink(e){var t=this.createElement("a");if(this.renderChildren(e,t),this.renderStyleValues(e.cssStyle,t),e.href)t.href=e.href;else if(e.id){const r=this.document.documentPart.rels.find(a=>a.id==e.id&&a.targetMode==="External");t.href=r==null?void 0:r.target}return t}renderDrawing(e){var t=this.createElement("div");return t.style.display="inline-block",t.style.position="relative",t.style.textIndent="0px",this.renderChildren(e,t),this.renderStyleValues(e.cssStyle,t),t}renderImage(e){let t=this.createElement("img");return this.renderStyleValues(e.cssStyle,t),this.document&&this.tasks.push(this.document.loadDocumentImage(e.src,this.currentPart).then(r=>{t.src=r})),t}renderText(e){return this.htmlDocument.createTextNode(e.text)}renderDeletedText(e){return this.options.renderEndnotes?this.htmlDocument.createTextNode(e.text):null}renderBreak(e){return e.break=="textWrapping"?this.createElement("br"):null}renderInserted(e){return this.options.renderChanges?this.renderContainer(e,"ins"):this.renderChildren(e)}renderDeleted(e){return this.options.renderChanges?this.renderContainer(e,"del"):null}renderSymbol(e){var t=this.createElement("span");return t.style.fontFamily=e.font,t.innerHTML=`&#x${e.char};`,t}renderFootnoteReference(e){var t=this.createElement("sup");return this.currentFootnoteIds.push(e.id),t.textContent=`${this.currentFootnoteIds.length}`,t}renderEndnoteReference(e){var t=this.createElement("sup");return this.currentEndnoteIds.push(e.id),t.textContent=`${this.currentEndnoteIds.length}`,t}renderTab(e){var t,r=this.createElement("span");if(r.innerHTML=" ",this.options.experimental){r.className=this.tabStopClass();var a=(t=Rt(e,o.Paragraph))==null?void 0:t.tabs;this.currentTabs.push({stops:a,span:r})}return r}renderBookmarkStart(e){var t=this.createElement("span");return t.id=e.name,t}renderRun(e){if(e.fieldRun)return null;const t=this.createElement("span");if(e.id&&(t.id=e.id),this.renderClass(e,t),this.renderStyleValues(e.cssStyle,t),e.verticalAlign){const r=this.createElement(e.verticalAlign);this.renderChildren(e,r),t.appendChild(r)}else this.renderChildren(e,t);return t}renderTable(e){let t=this.createElement("table");return this.tableCellPositions.push(this.currentCellPosition),this.tableVerticalMerges.push(this.currentVerticalMerge),this.currentVerticalMerge={},this.currentCellPosition={col:0,row:0},e.columns&&t.appendChild(this.renderTableColumns(e.columns)),this.renderClass(e,t),this.renderChildren(e,t),this.renderStyleValues(e.cssStyle,t),this.currentVerticalMerge=this.tableVerticalMerges.pop(),this.currentCellPosition=this.tableCellPositions.pop(),t}renderTableColumns(e){let t=this.createElement("colgroup");for(let r of e){let a=this.createElement("col");r.width&&(a.style.width=r.width),t.appendChild(a)}return t}renderTableRow(e){let t=this.createElement("tr");return this.currentCellPosition.col=0,this.renderClass(e,t),this.renderChildren(e,t),this.renderStyleValues(e.cssStyle,t),this.currentCellPosition.row++,t}renderTableCell(e){let t=this.createElement("td");const r=this.currentCellPosition.col;return e.verticalMerge?e.verticalMerge=="restart"?(this.currentVerticalMerge[r]=t,t.rowSpan=1):this.currentVerticalMerge[r]&&(this.currentVerticalMerge[r].rowSpan+=1,t.style.display="none"):this.currentVerticalMerge[r]=null,this.renderClass(e,t),this.renderChildren(e,t),this.renderStyleValues(e.cssStyle,t),e.span&&(t.colSpan=e.span),this.currentCellPosition.col+=t.colSpan,t}renderVmlPicture(e){var t=V("div");return this.renderChildren(e,t),t}renderVmlElement(e){var t,r,a=re("svg");a.setAttribute("style",e.cssStyleText);const n=this.renderVmlChildElement(e);return(t=e.imageHref)!=null&&t.id&&this.tasks.push((r=this.document)==null?void 0:r.loadDocumentImage(e.imageHref.id,this.currentPart).then(i=>n.setAttribute("href",i))),a.appendChild(n),requestAnimationFrame(()=>{const i=a.firstElementChild.getBBox();a.setAttribute("width",`${Math.ceil(i.x+i.width)}`),a.setAttribute("height",`${Math.ceil(i.y+i.height)}`)}),a}renderVmlChildElement(e){const t=re(e.tagName);Object.entries(e.attrs).forEach(([r,a])=>t.setAttribute(r,a));for(let r of e.children)r.type==o.VmlElement?t.appendChild(this.renderVmlChildElement(r)):t.appendChild(...x(this.renderElement(r)));return t}renderMmlRadical(e){var t;const r=e.children.find(n=>n.type==o.MmlBase);if((t=e.props)!=null&&t.hideDegree)return m(p.mathML,"msqrt",null,this.renderElements([r]));const a=e.children.find(n=>n.type==o.MmlDegree);return m(p.mathML,"mroot",null,this.renderElements([r,a]))}renderMmlDelimiter(e){var t,r;const a=[];return a.push(m(p.mathML,"mo",null,[(t=e.props.beginChar)!==null&&t!==void 0?t:"("])),a.push(...this.renderElements(e.children)),a.push(m(p.mathML,"mo",null,[(r=e.props.endChar)!==null&&r!==void 0?r:")"])),m(p.mathML,"mrow",null,a)}renderMmlNary(e){var t,r;const a=[],n=A(e.children,b=>b.type),i=n[o.MmlSuperArgument],c=n[o.MmlSubArgument],u=i?m(p.mathML,"mo",null,x(this.renderElement(i))):null,h=c?m(p.mathML,"mo",null,x(this.renderElement(c))):null,d=m(p.mathML,"mo",null,[(r=(t=e.props)==null?void 0:t.char)!==null&&r!==void 0?r:"∫"]);return u||h?a.push(m(p.mathML,"munderover",null,[d,h,u])):u?a.push(m(p.mathML,"mover",null,[d,u])):h?a.push(m(p.mathML,"munder",null,[d,h])):a.push(d),a.push(...this.renderElements(n[o.MmlBase].children)),m(p.mathML,"mrow",null,a)}renderMmlPreSubSuper(e){const t=[],r=A(e.children,h=>h.type),a=r[o.MmlSuperArgument],n=r[o.MmlSubArgument],i=a?m(p.mathML,"mo",null,x(this.renderElement(a))):null,c=n?m(p.mathML,"mo",null,x(this.renderElement(n))):null,u=m(p.mathML,"mo",null);return t.push(m(p.mathML,"msubsup",null,[u,c,i])),t.push(...this.renderElements(r[o.MmlBase].children)),m(p.mathML,"mrow",null,t)}renderMmlGroupChar(e){const t=e.props.verticalJustification==="bot"?"mover":"munder",r=this.renderContainerNS(e,p.mathML,t);return e.props.char&&r.appendChild(m(p.mathML,"mo",null,[e.props.char])),r}renderMmlBar(e){const t=this.renderContainerNS(e,p.mathML,"mrow");switch(e.props.position){case"top":t.style.textDecoration="overline";break;case"bottom":t.style.textDecoration="underline";break}return t}renderMmlRun(e){const t=m(p.mathML,"ms");return this.renderClass(e,t),this.renderStyleValues(e.cssStyle,t),this.renderChildren(e,t),t}renderMllList(e){const t=m(p.mathML,"mtable");this.renderClass(e,t),this.renderStyleValues(e.cssStyle,t),this.renderChildren(e);for(let r of this.renderChildren(e))t.appendChild(m(p.mathML,"mtr",null,[m(p.mathML,"mtd",null,[r])]));return t}renderStyleValues(e,t){for(let r in e)r.startsWith("$")?t.setAttribute(r.slice(1),e[r]):t.style[r]=e[r]}renderClass(e,t){e.className&&(t.className=e.className),e.styleName&&t.classList.add(this.processStyleName(e.styleName))}findStyle(e){var t;return e&&((t=this.styleMap)==null?void 0:t[e])}numberingClass(e,t){return`${this.className}-num-${e}-${t}`}tabStopClass(){return`${this.className}-tab-stop`}styleToString(e,t,r=null){let a=`${e} {\r +`;for(const n in t)n.startsWith("$")||(a+=` ${n}: ${t[n]};\r +`);return r&&(a+=r),a+`}\r +`}numberingCounter(e,t){return`${this.className}-num-${e}-${t}`}levelTextToContent(e,t,r,a){var n;const i={tab:"\\9",space:"\\a0"};var c=e.replace(/%\d*/g,u=>{let h=parseInt(u.substring(1),10)-1;return`"counter(${this.numberingCounter(r,h)}, ${a})"`});return`"${c}${(n=i[t])!==null&&n!==void 0?n:""}"`}numFormatToCssValue(e){var t,r={none:"none",bullet:"disc",decimal:"decimal",lowerLetter:"lower-alpha",upperLetter:"upper-alpha",lowerRoman:"lower-roman",upperRoman:"upper-roman",decimalZero:"decimal-leading-zero",aiueo:"katakana",aiueoFullWidth:"katakana",chineseCounting:"simp-chinese-informal",chineseCountingThousand:"simp-chinese-informal",chineseLegalSimplified:"simp-chinese-formal",chosung:"hangul-consonant",ideographDigital:"cjk-ideographic",ideographTraditional:"cjk-heavenly-stem",ideographLegalTraditional:"trad-chinese-formal",ideographZodiac:"cjk-earthly-branch",iroha:"katakana-iroha",irohaFullWidth:"katakana-iroha",japaneseCounting:"japanese-informal",japaneseDigitalTenThousand:"cjk-decimal",japaneseLegal:"japanese-formal",thaiNumbers:"thai",koreanCounting:"korean-hangul-formal",koreanDigital:"korean-hangul-formal",koreanDigital2:"korean-hanja-informal",hebrew1:"hebrew",hebrew2:"hebrew",hindiNumbers:"devanagari",ganada:"hangul",taiwaneseCounting:"cjk-ideographic",taiwaneseCountingThousand:"cjk-ideographic",taiwaneseDigital:"cjk-decimal"};return(t=r[e])!==null&&t!==void 0?t:e}refreshTabStops(){this.options.experimental&&(clearTimeout(this.tabsTimeout),this.tabsTimeout=setTimeout(()=>{const e=xt();for(let t of this.currentTabs)Ft(t.span,t.stops,this.defaultTabSize,e)},500))}}function V(s,e,t){return m(void 0,s,e,t)}function re(s,e,t){return m(p.svg,s,e,t)}function m(s,e,t,r){var a=s?document.createElementNS(s,e):document.createElement(e);return Object.assign(a,t),r&&z(a,r),a}function ae(s){s.innerHTML=""}function z(s,e){e.forEach(t=>s.appendChild(Te(t)?document.createTextNode(t):t))}function E(s){return V("style",{innerHTML:s})}function B(s,e){s.appendChild(document.createComment(e))}function Rt(s,e){for(var t=s.parent;t!=null&&t.type!=e;)t=t.parent;return t}const ge={ignoreHeight:!1,ignoreWidth:!1,ignoreFonts:!1,breakPages:!0,debug:!1,experimental:!1,className:"docx",inWrapper:!0,trimXmlDeclaration:!0,ignoreLastRenderedPageBreak:!0,renderHeaders:!0,renderFooters:!0,renderFootnotes:!0,renderEndnotes:!0,useBase64URL:!1,renderChanges:!1};function Lt(s,e){const t={...ge,...e};return U.load(s,new Nt(t),t)}async function Tt(s,e,t,r){const a={...ge,...r},n=new Bt(window.document);return n.render(s,e,t,a),Promise.allSettled(n.tasks.filter(i=>i))}async function se(s,e,t,r){const a=await Lt(s,r);return await Tt(a,e,t,r),a}const Dt=async s=>{if(typeof document<"u"){const{bodyContainer:e,styleContainer:t,buffer:r,docxOptions:a={}}=s,i=Object.assign({},{className:"docx"},a);if(e)return se(r,e,t,i);{const c=document.createElement("div");return document.body.appendChild(c),se(r,c,t,i)}}};export{Dt as renderDocx}; diff --git a/assets/chunks/en.Bkn4-Vvy.js b/assets/chunks/en.Bkn4-Vvy.js new file mode 100644 index 0000000000..fd3f603cc0 --- /dev/null +++ b/assets/chunks/en.Bkn4-Vvy.js @@ -0,0 +1 @@ +const t="English",o="Generate",n="Please enter the key of 2FA",e="You haven't entered the key for 2FA",p="expires",s="The entered key value is invalid",_="2FA Verification",c={lang:t,components_totp_1:o,components_totp_2:n,components_totp_3:e,components_totp_4:p,components_totp_5:s,components_totp_6:_};export{o as components_totp_1,n as components_totp_2,e as components_totp_3,p as components_totp_4,s as components_totp_5,_ as components_totp_6,c as default,t as lang}; diff --git a/assets/chunks/extra.Cu56q3CZ.js b/assets/chunks/extra.Cu56q3CZ.js new file mode 100644 index 0000000000..d11064822b --- /dev/null +++ b/assets/chunks/extra.Cu56q3CZ.js @@ -0,0 +1 @@ +const s="/ran/assets/Literal.Dl-JxujV.jpeg",t="/ran/assets/Identifier.lJSxyFTe.jpeg",a="/ran/assets/Statement.9lGuRes5.jpeg",e="/ran/assets/Declaration.CplvpFd-.jpeg",r="/ran/assets/Expression.DczLaznn.jpeg",p="/ran/assets/ExpressionStatement.zaIHlhIF.jpeg",n="/ran/assets/Class.Cx5QD1OX.jpeg",o="/ran/assets/import.BTsVI5Tc.jpeg",_="/ran/assets/export.ne8l5ppO.jpeg",i="/ran/assets/Program.BBf_t-me.jpeg",m="/ran/assets/File.BiH2GpuW.jpeg",c="/ran/assets/axtexplorer.D7PG-3cx.jpeg",g="/ran/assets/axtexplorerSave.a5hTrvd2.jpeg",j="/ran/assets/Comment.BYtNY-L1.jpeg",l="/ran/assets/extra.Da45cF33.jpeg";export{s as _,t as a,a as b,e as c,r as d,p as e,n as f,o as g,_ as h,i,m as j,c as k,g as l,j as m,l as n}; diff --git a/assets/chunks/eye-D_mEt17f.DJFa_ttF.js b/assets/chunks/eye-D_mEt17f.DJFa_ttF.js new file mode 100644 index 0000000000..2e1a518505 --- /dev/null +++ b/assets/chunks/eye-D_mEt17f.DJFa_ttF.js @@ -0,0 +1,4 @@ +const t={success:!0,_identification:!0,data:` + + +`};export{t as default}; diff --git a/assets/chunks/eye-close-BVr3NJtg.DsdsDDgX.js b/assets/chunks/eye-close-BVr3NJtg.DsdsDDgX.js new file mode 100644 index 0000000000..b4d0e62868 --- /dev/null +++ b/assets/chunks/eye-close-BVr3NJtg.DsdsDDgX.js @@ -0,0 +1,4 @@ +const c={success:!0,_identification:!0,data:` + + +`};export{c as default}; diff --git a/assets/chunks/framework.C-ai2y4t.js b/assets/chunks/framework.C-ai2y4t.js new file mode 100644 index 0000000000..959c0e7fad --- /dev/null +++ b/assets/chunks/framework.C-ai2y4t.js @@ -0,0 +1,18 @@ +/** +* @vue/shared v3.5.6 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**//*! #__NO_SIDE_EFFECTS__ */function Ls(e){const t=Object.create(null);for(const n of e.split(","))t[n]=1;return n=>n in t}const ee={},Et=[],Ve=()=>{},Uo=()=>!1,Xt=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),Ns=e=>e.startsWith("onUpdate:"),le=Object.assign,Fs=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Bo=Object.prototype.hasOwnProperty,z=(e,t)=>Bo.call(e,t),U=Array.isArray,xt=e=>Mn(e)==="[object Map]",Zr=e=>Mn(e)==="[object Set]",q=e=>typeof e=="function",re=e=>typeof e=="string",st=e=>typeof e=="symbol",ne=e=>e!==null&&typeof e=="object",ei=e=>(ne(e)||q(e))&&q(e.then)&&q(e.catch),ti=Object.prototype.toString,Mn=e=>ti.call(e),Wo=e=>Mn(e).slice(8,-1),ni=e=>Mn(e)==="[object Object]",Hs=e=>re(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Tt=Ls(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),Pn=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Ko=/-(\w)/g,Ne=Pn(e=>e.replace(Ko,(t,n)=>n?n.toUpperCase():"")),qo=/\B([A-Z])/g,rt=Pn(e=>e.replace(qo,"-$1").toLowerCase()),In=Pn(e=>e.charAt(0).toUpperCase()+e.slice(1)),gn=Pn(e=>e?`on${In(e)}`:""),tt=(e,t)=>!Object.is(e,t),zn=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:s,value:n})},Go=e=>{const t=parseFloat(e);return isNaN(t)?e:t},Yo=e=>{const t=re(e)?Number(e):NaN;return isNaN(t)?e:t};let ir;const ri=()=>ir||(ir=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Ds(e){if(U(e)){const t={};for(let n=0;n{if(n){const s=n.split(Jo);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function $s(e){let t="";if(re(e))t=e;else if(U(e))for(let n=0;n!!(e&&e.__v_isRef===!0),tl=e=>re(e)?e:e==null?"":U(e)||ne(e)&&(e.toString===ti||!q(e.toString))?oi(e)?tl(e.value):JSON.stringify(e,li,2):String(e),li=(e,t)=>oi(t)?li(e,t.value):xt(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,r],i)=>(n[Qn(s,i)+" =>"]=r,n),{})}:Zr(t)?{[`Set(${t.size})`]:[...t.values()].map(n=>Qn(n))}:st(t)?Qn(t):ne(t)&&!U(t)&&!ni(t)?String(t):t,Qn=(e,t="")=>{var n;return st(e)?`Symbol(${(n=e.description)!=null?n:t})`:e};/** +* @vue/reactivity v3.5.6 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let ve;class ci{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=ve,!t&&ve&&(this.index=(ve.scopes||(ve.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){this._isPaused=!0;let t,n;if(this.scopes)for(t=0,n=this.scopes.length;t0)return;let e;for(;Dt;){let t=Dt;for(Dt=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(s){e||(e=s)}t=n}}if(e)throw e}function hi(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function pi(e){let t,n=e.depsTail,s=n;for(;s;){const r=s.prevDep;s.version===-1?(s===n&&(n=r),ks(s),sl(s)):t=s,s.dep.activeLink=s.prevActiveLink,s.prevActiveLink=void 0,s=r}e.deps=t,e.depsTail=n}function bs(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(gi(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function gi(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===Ut))return;e.globalVersion=Ut;const t=e.dep;if(e.flags|=2,t.version>0&&!e.isSSR&&e.deps&&!bs(e)){e.flags&=-3;return}const n=Z,s=Le;Z=e,Le=!0;try{hi(e);const r=e.fn(e._value);(t.version===0||tt(r,e._value))&&(e._value=r,t.version++)}catch(r){throw t.version++,r}finally{Z=n,Le=s,pi(e),e.flags&=-3}}function ks(e){const{dep:t,prevSub:n,nextSub:s}=e;if(n&&(n.nextSub=s,e.prevSub=void 0),s&&(s.prevSub=n,e.nextSub=void 0),t.subs===e&&(t.subs=n),!t.subs&&t.computed){t.computed.flags&=-5;for(let r=t.computed.deps;r;r=r.nextDep)ks(r)}}function sl(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}let Le=!0;const mi=[];function it(){mi.push(Le),Le=!1}function ot(){const e=mi.pop();Le=e===void 0?!0:e}function or(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const n=Z;Z=void 0;try{t()}finally{Z=n}}}let Ut=0;class rl{constructor(t,n){this.sub=t,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class Ln{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0}track(t){if(!Z||!Le||Z===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==Z)n=this.activeLink=new rl(Z,this),Z.deps?(n.prevDep=Z.depsTail,Z.depsTail.nextDep=n,Z.depsTail=n):Z.deps=Z.depsTail=n,Z.flags&4&&yi(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const s=n.nextDep;s.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=s),n.prevDep=Z.depsTail,n.nextDep=void 0,Z.depsTail.nextDep=n,Z.depsTail=n,Z.deps===n&&(Z.deps=s)}return n}trigger(t){this.version++,Ut++,this.notify(t)}notify(t){js();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{Vs()}}}function yi(e){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let s=t.deps;s;s=s.nextDep)yi(s)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}const wn=new WeakMap,ht=Symbol(""),vs=Symbol(""),Bt=Symbol("");function _e(e,t,n){if(Le&&Z){let s=wn.get(e);s||wn.set(e,s=new Map);let r=s.get(n);r||s.set(n,r=new Ln),r.track()}}function Ke(e,t,n,s,r,i){const o=wn.get(e);if(!o){Ut++;return}const l=c=>{c&&c.trigger()};if(js(),t==="clear")o.forEach(l);else{const c=U(e),u=c&&Hs(n);if(c&&n==="length"){const f=Number(s);o.forEach((h,p)=>{(p==="length"||p===Bt||!st(p)&&p>=f)&&l(h)})}else switch(n!==void 0&&l(o.get(n)),u&&l(o.get(Bt)),t){case"add":c?u&&l(o.get("length")):(l(o.get(ht)),xt(e)&&l(o.get(vs)));break;case"delete":c||(l(o.get(ht)),xt(e)&&l(o.get(vs)));break;case"set":xt(e)&&l(o.get(ht));break}}Vs()}function il(e,t){var n;return(n=wn.get(e))==null?void 0:n.get(t)}function vt(e){const t=J(e);return t===e?t:(_e(t,"iterate",Bt),Pe(e)?t:t.map(me))}function Nn(e){return _e(e=J(e),"iterate",Bt),e}const ol={__proto__:null,[Symbol.iterator](){return es(this,Symbol.iterator,me)},concat(...e){return vt(this).concat(...e.map(t=>U(t)?vt(t):t))},entries(){return es(this,"entries",e=>(e[1]=me(e[1]),e))},every(e,t){return Ue(this,"every",e,t,void 0,arguments)},filter(e,t){return Ue(this,"filter",e,t,n=>n.map(me),arguments)},find(e,t){return Ue(this,"find",e,t,me,arguments)},findIndex(e,t){return Ue(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return Ue(this,"findLast",e,t,me,arguments)},findLastIndex(e,t){return Ue(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return Ue(this,"forEach",e,t,void 0,arguments)},includes(...e){return ts(this,"includes",e)},indexOf(...e){return ts(this,"indexOf",e)},join(e){return vt(this).join(e)},lastIndexOf(...e){return ts(this,"lastIndexOf",e)},map(e,t){return Ue(this,"map",e,t,void 0,arguments)},pop(){return Lt(this,"pop")},push(...e){return Lt(this,"push",e)},reduce(e,...t){return lr(this,"reduce",e,t)},reduceRight(e,...t){return lr(this,"reduceRight",e,t)},shift(){return Lt(this,"shift")},some(e,t){return Ue(this,"some",e,t,void 0,arguments)},splice(...e){return Lt(this,"splice",e)},toReversed(){return vt(this).toReversed()},toSorted(e){return vt(this).toSorted(e)},toSpliced(...e){return vt(this).toSpliced(...e)},unshift(...e){return Lt(this,"unshift",e)},values(){return es(this,"values",me)}};function es(e,t,n){const s=Nn(e),r=s[t]();return s!==e&&!Pe(e)&&(r._next=r.next,r.next=()=>{const i=r._next();return i.value&&(i.value=n(i.value)),i}),r}const ll=Array.prototype;function Ue(e,t,n,s,r,i){const o=Nn(e),l=o!==e&&!Pe(e),c=o[t];if(c!==ll[t]){const h=c.apply(e,i);return l?me(h):h}let u=n;o!==e&&(l?u=function(h,p){return n.call(this,me(h),p,e)}:n.length>2&&(u=function(h,p){return n.call(this,h,p,e)}));const f=c.call(o,u,s);return l&&r?r(f):f}function lr(e,t,n,s){const r=Nn(e);let i=n;return r!==e&&(Pe(e)?n.length>3&&(i=function(o,l,c){return n.call(this,o,l,c,e)}):i=function(o,l,c){return n.call(this,o,me(l),c,e)}),r[t](i,...s)}function ts(e,t,n){const s=J(e);_e(s,"iterate",Bt);const r=s[t](...n);return(r===-1||r===!1)&&Ks(n[0])?(n[0]=J(n[0]),s[t](...n)):r}function Lt(e,t,n=[]){it(),js();const s=J(e)[t].apply(e,n);return Vs(),ot(),s}const cl=Ls("__proto__,__v_isRef,__isVue"),_i=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(st));function al(e){st(e)||(e=String(e));const t=J(this);return _e(t,"has",e),t.hasOwnProperty(e)}class bi{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,s){const r=this._isReadonly,i=this._isShallow;if(n==="__v_isReactive")return!r;if(n==="__v_isReadonly")return r;if(n==="__v_isShallow")return i;if(n==="__v_raw")return s===(r?i?Sl:Ei:i?Si:wi).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(s)?t:void 0;const o=U(t);if(!r){let c;if(o&&(c=ol[n]))return c;if(n==="hasOwnProperty")return al}const l=Reflect.get(t,n,ae(t)?t:s);return(st(n)?_i.has(n):cl(n))||(r||_e(t,"get",n),i)?l:ae(l)?o&&Hs(n)?l:l.value:ne(l)?r?Dn(l):Hn(l):l}}class vi extends bi{constructor(t=!1){super(!1,t)}set(t,n,s,r){let i=t[n];if(!this._isShallow){const c=_t(i);if(!Pe(s)&&!_t(s)&&(i=J(i),s=J(s)),!U(t)&&ae(i)&&!ae(s))return c?!1:(i.value=s,!0)}const o=U(t)&&Hs(n)?Number(n)e,Fn=e=>Reflect.getPrototypeOf(e);function en(e,t,n=!1,s=!1){e=e.__v_raw;const r=J(e),i=J(t);n||(tt(t,i)&&_e(r,"get",t),_e(r,"get",i));const{has:o}=Fn(r),l=s?Us:n?qs:me;if(o.call(r,t))return l(e.get(t));if(o.call(r,i))return l(e.get(i));e!==r&&e.get(t)}function tn(e,t=!1){const n=this.__v_raw,s=J(n),r=J(e);return t||(tt(e,r)&&_e(s,"has",e),_e(s,"has",r)),e===r?n.has(e):n.has(e)||n.has(r)}function nn(e,t=!1){return e=e.__v_raw,!t&&_e(J(e),"iterate",ht),Reflect.get(e,"size",e)}function cr(e,t=!1){!t&&!Pe(e)&&!_t(e)&&(e=J(e));const n=J(this);return Fn(n).has.call(n,e)||(n.add(e),Ke(n,"add",e,e)),this}function ar(e,t,n=!1){!n&&!Pe(t)&&!_t(t)&&(t=J(t));const s=J(this),{has:r,get:i}=Fn(s);let o=r.call(s,e);o||(e=J(e),o=r.call(s,e));const l=i.call(s,e);return s.set(e,t),o?tt(t,l)&&Ke(s,"set",e,t):Ke(s,"add",e,t),this}function fr(e){const t=J(this),{has:n,get:s}=Fn(t);let r=n.call(t,e);r||(e=J(e),r=n.call(t,e)),s&&s.call(t,e);const i=t.delete(e);return r&&Ke(t,"delete",e,void 0),i}function ur(){const e=J(this),t=e.size!==0,n=e.clear();return t&&Ke(e,"clear",void 0,void 0),n}function sn(e,t){return function(s,r){const i=this,o=i.__v_raw,l=J(o),c=t?Us:e?qs:me;return!e&&_e(l,"iterate",ht),o.forEach((u,f)=>s.call(r,c(u),c(f),i))}}function rn(e,t,n){return function(...s){const r=this.__v_raw,i=J(r),o=xt(i),l=e==="entries"||e===Symbol.iterator&&o,c=e==="keys"&&o,u=r[e](...s),f=n?Us:t?qs:me;return!t&&_e(i,"iterate",c?vs:ht),{next(){const{value:h,done:p}=u.next();return p?{value:h,done:p}:{value:l?[f(h[0]),f(h[1])]:f(h),done:p}},[Symbol.iterator](){return this}}}}function Ye(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function pl(){const e={get(i){return en(this,i)},get size(){return nn(this)},has:tn,add:cr,set:ar,delete:fr,clear:ur,forEach:sn(!1,!1)},t={get(i){return en(this,i,!1,!0)},get size(){return nn(this)},has:tn,add(i){return cr.call(this,i,!0)},set(i,o){return ar.call(this,i,o,!0)},delete:fr,clear:ur,forEach:sn(!1,!0)},n={get(i){return en(this,i,!0)},get size(){return nn(this,!0)},has(i){return tn.call(this,i,!0)},add:Ye("add"),set:Ye("set"),delete:Ye("delete"),clear:Ye("clear"),forEach:sn(!0,!1)},s={get(i){return en(this,i,!0,!0)},get size(){return nn(this,!0)},has(i){return tn.call(this,i,!0)},add:Ye("add"),set:Ye("set"),delete:Ye("delete"),clear:Ye("clear"),forEach:sn(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(i=>{e[i]=rn(i,!1,!1),n[i]=rn(i,!0,!1),t[i]=rn(i,!1,!0),s[i]=rn(i,!0,!0)}),[e,n,t,s]}const[gl,ml,yl,_l]=pl();function Bs(e,t){const n=t?e?_l:yl:e?ml:gl;return(s,r,i)=>r==="__v_isReactive"?!e:r==="__v_isReadonly"?e:r==="__v_raw"?s:Reflect.get(z(n,r)&&r in s?n:s,r,i)}const bl={get:Bs(!1,!1)},vl={get:Bs(!1,!0)},wl={get:Bs(!0,!1)};const wi=new WeakMap,Si=new WeakMap,Ei=new WeakMap,Sl=new WeakMap;function El(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function xl(e){return e.__v_skip||!Object.isExtensible(e)?0:El(Wo(e))}function Hn(e){return _t(e)?e:Ws(e,!1,ul,bl,wi)}function Tl(e){return Ws(e,!1,hl,vl,Si)}function Dn(e){return Ws(e,!0,dl,wl,Ei)}function Ws(e,t,n,s,r){if(!ne(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const i=r.get(e);if(i)return i;const o=xl(e);if(o===0)return e;const l=new Proxy(e,o===2?s:n);return r.set(e,l),l}function pt(e){return _t(e)?pt(e.__v_raw):!!(e&&e.__v_isReactive)}function _t(e){return!!(e&&e.__v_isReadonly)}function Pe(e){return!!(e&&e.__v_isShallow)}function Ks(e){return e?!!e.__v_raw:!1}function J(e){const t=e&&e.__v_raw;return t?J(t):e}function mn(e){return!z(e,"__v_skip")&&Object.isExtensible(e)&&si(e,"__v_skip",!0),e}const me=e=>ne(e)?Hn(e):e,qs=e=>ne(e)?Dn(e):e;function ae(e){return e?e.__v_isRef===!0:!1}function de(e){return Ti(e,!1)}function xi(e){return Ti(e,!0)}function Ti(e,t){return ae(e)?e:new Cl(e,t)}class Cl{constructor(t,n){this.dep=new Ln,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=n?t:J(t),this._value=n?t:me(t),this.__v_isShallow=n}get value(){return this.dep.track(),this._value}set value(t){const n=this._rawValue,s=this.__v_isShallow||Pe(t)||_t(t);t=s?t:J(t),tt(t,n)&&(this._rawValue=t,this._value=s?t:me(t),this.dep.trigger())}}function Ci(e){return ae(e)?e.value:e}const Al={get:(e,t,n)=>t==="__v_raw"?e:Ci(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const r=e[t];return ae(r)&&!ae(n)?(r.value=n,!0):Reflect.set(e,t,n,s)}};function Ai(e){return pt(e)?e:new Proxy(e,Al)}class Rl{constructor(t){this.__v_isRef=!0,this._value=void 0;const n=this.dep=new Ln,{get:s,set:r}=t(n.track.bind(n),n.trigger.bind(n));this._get=s,this._set=r}get value(){return this._value=this._get()}set value(t){this._set(t)}}function Ol(e){return new Rl(e)}function Tf(e){const t=U(e)?new Array(e.length):{};for(const n in e)t[n]=Ri(e,n);return t}class Ml{constructor(t,n,s){this._object=t,this._key=n,this._defaultValue=s,this.__v_isRef=!0,this._value=void 0}get value(){const t=this._object[this._key];return this._value=t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return il(J(this._object),this._key)}}class Pl{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0,this._value=void 0}get value(){return this._value=this._getter()}}function Il(e,t,n){return ae(e)?e:q(e)?new Pl(e):ne(e)&&arguments.length>1?Ri(e,t,n):de(e)}function Ri(e,t,n){const s=e[t];return ae(s)?s:new Ml(e,t,n)}class Ll{constructor(t,n,s){this.fn=t,this.setter=n,this._value=void 0,this.dep=new Ln(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=Ut-1,this.effect=this,this.__v_isReadonly=!n,this.isSSR=s}notify(){if(this.flags|=16,!(this.flags&8)&&Z!==this)return di(this),!0}get value(){const t=this.dep.track();return gi(this),t&&(t.version=this.dep.version),this._value}set value(t){this.setter&&this.setter(t)}}function Nl(e,t,n=!1){let s,r;return q(e)?s=e:(s=e.get,r=e.set),new Ll(s,r,n)}const on={},Sn=new WeakMap;let ut;function Fl(e,t=!1,n=ut){if(n){let s=Sn.get(n);s||Sn.set(n,s=[]),s.push(e)}}function Hl(e,t,n=ee){const{immediate:s,deep:r,once:i,scheduler:o,augmentJob:l,call:c}=n,u=g=>r?g:Pe(g)||r===!1||r===0?We(g,1):We(g);let f,h,p,v,T=!1,I=!1;if(ae(e)?(h=()=>e.value,T=Pe(e)):pt(e)?(h=()=>u(e),T=!0):U(e)?(I=!0,T=e.some(g=>pt(g)||Pe(g)),h=()=>e.map(g=>{if(ae(g))return g.value;if(pt(g))return u(g);if(q(g))return c?c(g,2):g()})):q(e)?t?h=c?()=>c(e,2):e:h=()=>{if(p){it();try{p()}finally{ot()}}const g=ut;ut=f;try{return c?c(e,3,[v]):e(v)}finally{ut=g}}:h=Ve,t&&r){const g=h,O=r===!0?1/0:r;h=()=>We(g(),O)}const G=ai(),V=()=>{f.stop(),G&&Fs(G.effects,f)};if(i&&t){const g=t;t=(...O)=>{g(...O),V()}}let K=I?new Array(e.length).fill(on):on;const m=g=>{if(!(!(f.flags&1)||!f.dirty&&!g))if(t){const O=f.run();if(r||T||(I?O.some((N,H)=>tt(N,K[H])):tt(O,K))){p&&p();const N=ut;ut=f;try{const H=[O,K===on?void 0:I&&K[0]===on?[]:K,v];c?c(t,3,H):t(...H),K=O}finally{ut=N}}}else f.run()};return l&&l(m),f=new fi(h),f.scheduler=o?()=>o(m,!1):m,v=g=>Fl(g,!1,f),p=f.onStop=()=>{const g=Sn.get(f);if(g){if(c)c(g,4);else for(const O of g)O();Sn.delete(f)}},t?s?m(!0):K=f.run():o?o(m.bind(null,!0),!0):f.run(),V.pause=f.pause.bind(f),V.resume=f.resume.bind(f),V.stop=V,V}function We(e,t=1/0,n){if(t<=0||!ne(e)||e.__v_skip||(n=n||new Set,n.has(e)))return e;if(n.add(e),t--,ae(e))We(e.value,t,n);else if(U(e))for(let s=0;s{We(s,t,n)});else if(ni(e)){for(const s in e)We(e[s],t,n);for(const s of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,s)&&We(e[s],t,n)}return e}/** +* @vue/runtime-core v3.5.6 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/function Jt(e,t,n,s){try{return s?e(...s):e()}catch(r){$n(r,t,n)}}function Fe(e,t,n,s){if(q(e)){const r=Jt(e,t,n,s);return r&&ei(r)&&r.catch(i=>{$n(i,t,n)}),r}if(U(e)){const r=[];for(let i=0;i>>1,r=we[s],i=Kt(r);i=Kt(n)?we.push(e):we.splice($l(t),0,e),e.flags|=1,Mi()}}function Mi(){!Wt&&!ws&&(ws=!0,Gs=Oi.then(Pi))}function jl(e){U(e)?Ct.push(...e):ze&&e.id===-1?ze.splice(St+1,0,e):e.flags&1||(Ct.push(e),e.flags|=1),Mi()}function dr(e,t,n=Wt?$e+1:0){for(;nKt(n)-Kt(s));if(Ct.length=0,ze){ze.push(...t);return}for(ze=t,St=0;Ste.id==null?e.flags&2?-1:1/0:e.id;function Pi(e){ws=!1,Wt=!0;try{for($e=0;$e{s._d&&Cr(-1);const i=xn(t);let o;try{o=e(...r)}finally{xn(i),s._d&&Cr(1)}return o};return s._n=!0,s._c=!0,s._d=!0,s}function Cf(e,t){if(ce===null)return e;const n=Gn(ce),s=e.dirs||(e.dirs=[]);for(let r=0;re.__isTeleport,$t=e=>e&&(e.disabled||e.disabled===""),kl=e=>e&&(e.defer||e.defer===""),hr=e=>typeof SVGElement<"u"&&e instanceof SVGElement,pr=e=>typeof MathMLElement=="function"&&e instanceof MathMLElement,Ss=(e,t)=>{const n=e&&e.to;return re(n)?t?t(n):null:n},Ul={name:"Teleport",__isTeleport:!0,process(e,t,n,s,r,i,o,l,c,u){const{mc:f,pc:h,pbc:p,o:{insert:v,querySelector:T,createText:I,createComment:G}}=u,V=$t(t.props);let{shapeFlag:K,children:m,dynamicChildren:g}=t;if(e==null){const O=t.el=I(""),N=t.anchor=I("");v(O,n,s),v(N,n,s);const H=(A,_)=>{K&16&&(r&&r.isCE&&(r.ce._teleportTarget=A),f(m,A,_,r,i,o,l,c))},$=()=>{const A=t.target=Ss(t.props,T),_=Fi(A,t,I,v);A&&(o!=="svg"&&hr(A)?o="svg":o!=="mathml"&&pr(A)&&(o="mathml"),V||(H(A,_),yn(t)))};V&&(H(n,N),yn(t)),kl(t.props)?Ee($,i):$()}else{t.el=e.el,t.targetStart=e.targetStart;const O=t.anchor=e.anchor,N=t.target=e.target,H=t.targetAnchor=e.targetAnchor,$=$t(e.props),A=$?n:N,_=$?O:H;if(o==="svg"||hr(N)?o="svg":(o==="mathml"||pr(N))&&(o="mathml"),g?(p(e.dynamicChildren,g,A,r,i,o,l),zs(e,t,!0)):c||h(e,t,A,_,r,i,o,l,!1),V)$?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):ln(t,n,O,u,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const L=t.target=Ss(t.props,T);L&&ln(t,L,null,u,0)}else $&&ln(t,N,H,u,1);yn(t)}},remove(e,t,n,{um:s,o:{remove:r}},i){const{shapeFlag:o,children:l,anchor:c,targetStart:u,targetAnchor:f,target:h,props:p}=e;if(h&&(r(u),r(f)),i&&r(c),o&16){const v=i||!$t(p);for(let T=0;T{e.isMounted=!0}),Wi(()=>{e.isUnmounting=!0}),e}const Re=[Function,Array],Hi={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Re,onEnter:Re,onAfterEnter:Re,onEnterCancelled:Re,onBeforeLeave:Re,onLeave:Re,onAfterLeave:Re,onLeaveCancelled:Re,onBeforeAppear:Re,onAppear:Re,onAfterAppear:Re,onAppearCancelled:Re},Di=e=>{const t=e.subTree;return t.component?Di(t.component):t},Kl={name:"BaseTransition",props:Hi,setup(e,{slots:t}){const n=Kn(),s=Wl();return()=>{const r=t.default&&Vi(t.default(),!0);if(!r||!r.length)return;const i=$i(r),o=J(e),{mode:l}=o;if(s.isLeaving)return ns(i);const c=gr(i);if(!c)return ns(i);let u=Es(c,o,s,n,p=>u=p);c.type!==ye&&qt(c,u);const f=n.subTree,h=f&&gr(f);if(h&&h.type!==ye&&!dt(c,h)&&Di(n).type!==ye){const p=Es(h,o,s,n);if(qt(h,p),l==="out-in"&&c.type!==ye)return s.isLeaving=!0,p.afterLeave=()=>{s.isLeaving=!1,n.job.flags&8||n.update(),delete p.afterLeave},ns(i);l==="in-out"&&c.type!==ye&&(p.delayLeave=(v,T,I)=>{const G=ji(s,h);G[String(h.key)]=h,v[Qe]=()=>{T(),v[Qe]=void 0,delete u.delayedLeave},u.delayedLeave=I})}return i}}};function $i(e){let t=e[0];if(e.length>1){for(const n of e)if(n.type!==ye){t=n;break}}return t}const ql=Kl;function ji(e,t){const{leavingVNodes:n}=e;let s=n.get(t.type);return s||(s=Object.create(null),n.set(t.type,s)),s}function Es(e,t,n,s,r){const{appear:i,mode:o,persisted:l=!1,onBeforeEnter:c,onEnter:u,onAfterEnter:f,onEnterCancelled:h,onBeforeLeave:p,onLeave:v,onAfterLeave:T,onLeaveCancelled:I,onBeforeAppear:G,onAppear:V,onAfterAppear:K,onAppearCancelled:m}=t,g=String(e.key),O=ji(n,e),N=(A,_)=>{A&&Fe(A,s,9,_)},H=(A,_)=>{const L=_[1];N(A,_),U(A)?A.every(S=>S.length<=1)&&L():A.length<=1&&L()},$={mode:o,persisted:l,beforeEnter(A){let _=c;if(!n.isMounted)if(i)_=G||c;else return;A[Qe]&&A[Qe](!0);const L=O[g];L&&dt(e,L)&&L.el[Qe]&&L.el[Qe](),N(_,[A])},enter(A){let _=u,L=f,S=h;if(!n.isMounted)if(i)_=V||u,L=K||f,S=m||h;else return;let B=!1;const se=A[cn]=oe=>{B||(B=!0,oe?N(S,[A]):N(L,[A]),$.delayedLeave&&$.delayedLeave(),A[cn]=void 0)};_?H(_,[A,se]):se()},leave(A,_){const L=String(e.key);if(A[cn]&&A[cn](!0),n.isUnmounting)return _();N(p,[A]);let S=!1;const B=A[Qe]=se=>{S||(S=!0,_(),se?N(I,[A]):N(T,[A]),A[Qe]=void 0,O[L]===e&&delete O[L])};O[L]=e,v?H(v,[A,B]):B()},clone(A){const _=Es(A,t,n,s,r);return r&&r(_),_}};return $}function ns(e){if(Vn(e))return e=nt(e),e.children=null,e}function gr(e){if(!Vn(e))return Ni(e.type)&&e.children?$i(e.children):e;const{shapeFlag:t,children:n}=e;if(n){if(t&16)return n[0];if(t&32&&q(n.default))return n.default()}}function qt(e,t){e.shapeFlag&6&&e.component?(e.transition=t,qt(e.component.subTree,t)):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Vi(e,t=!1,n){let s=[],r=0;for(let i=0;i1)for(let i=0;iTn(T,t&&(U(t)?t[I]:t),n,s,r));return}if(gt(s)&&!r)return;const i=s.shapeFlag&4?Gn(s.component):s.el,o=r?null:i,{i:l,r:c}=e,u=t&&t.r,f=l.refs===ee?l.refs={}:l.refs,h=l.setupState,p=J(h),v=h===ee?()=>!1:T=>z(p,T);if(u!=null&&u!==c&&(re(u)?(f[u]=null,v(u)&&(h[u]=null)):ae(u)&&(u.value=null)),q(c))Jt(c,l,12,[o,f]);else{const T=re(c),I=ae(c);if(T||I){const G=()=>{if(e.f){const V=T?v(c)?h[c]:f[c]:c.value;r?U(V)&&Fs(V,i):U(V)?V.includes(i)||V.push(i):T?(f[c]=[i],v(c)&&(h[c]=f[c])):(c.value=[i],e.k&&(f[e.k]=c.value))}else T?(f[c]=o,v(c)&&(h[c]=o)):I&&(c.value=o,e.k&&(f[e.k]=o))};o?(G.id=-1,Ee(G,n)):G()}}}let mr=!1;const wt=()=>{mr||(console.error("Hydration completed but contains mismatches."),mr=!0)},Gl=e=>e.namespaceURI.includes("svg")&&e.tagName!=="foreignObject",Yl=e=>e.namespaceURI.includes("MathML"),an=e=>{if(e.nodeType===1){if(Gl(e))return"svg";if(Yl(e))return"mathml"}},fn=e=>e.nodeType===8;function Xl(e){const{mt:t,p:n,o:{patchProp:s,createText:r,nextSibling:i,parentNode:o,remove:l,insert:c,createComment:u}}=e,f=(m,g)=>{if(!g.hasChildNodes()){n(null,m,g),En(),g._vnode=m;return}h(g.firstChild,m,null,null,null),En(),g._vnode=m},h=(m,g,O,N,H,$=!1)=>{$=$||!!g.dynamicChildren;const A=fn(m)&&m.data==="[",_=()=>I(m,g,O,N,H,A),{type:L,ref:S,shapeFlag:B,patchFlag:se}=g;let oe=m.nodeType;g.el=m,se===-2&&($=!1,g.dynamicChildren=null);let j=null;switch(L){case mt:oe!==3?g.children===""?(c(g.el=r(""),o(m),m),j=m):j=_():(m.data!==g.children&&(wt(),m.data=g.children),j=i(m));break;case ye:K(m)?(j=i(m),V(g.el=m.content.firstChild,m,O)):oe!==8||A?j=_():j=i(m);break;case Vt:if(A&&(m=i(m),oe=m.nodeType),oe===1||oe===3){j=m;const Y=!g.children.length;for(let D=0;D{$=$||!!g.dynamicChildren;const{type:A,props:_,patchFlag:L,shapeFlag:S,dirs:B,transition:se}=g,oe=A==="input"||A==="option";if(oe||L!==-1){B&&je(g,null,O,"created");let j=!1;if(K(m)){j=oo(N,se)&&O&&O.vnode.props&&O.vnode.props.appear;const D=m.content.firstChild;j&&se.beforeEnter(D),V(D,m,O),g.el=m=D}if(S&16&&!(_&&(_.innerHTML||_.textContent))){let D=v(m.firstChild,g,m,O,N,H,$);for(;D;){un(m,1)||wt();const fe=D;D=D.nextSibling,l(fe)}}else if(S&8){let D=g.children;D[0]===` +`&&(m.tagName==="PRE"||m.tagName==="TEXTAREA")&&(D=D.slice(1)),m.textContent!==D&&(un(m,0)||wt(),m.textContent=g.children)}if(_){if(oe||!$||L&48){const D=m.tagName.includes("-");for(const fe in _)(oe&&(fe.endsWith("value")||fe==="indeterminate")||Xt(fe)&&!Tt(fe)||fe[0]==="."||D)&&s(m,fe,null,_[fe],void 0,O)}else if(_.onClick)s(m,"onClick",null,_.onClick,void 0,O);else if(L&4&&pt(_.style))for(const D in _.style)_.style[D]}let Y;(Y=_&&_.onVnodeBeforeMount)&&Oe(Y,O,g),B&&je(g,null,O,"beforeMount"),((Y=_&&_.onVnodeMounted)||B||j)&&ho(()=>{Y&&Oe(Y,O,g),j&&se.enter(m),B&&je(g,null,O,"mounted")},N)}return m.nextSibling},v=(m,g,O,N,H,$,A)=>{A=A||!!g.dynamicChildren;const _=g.children,L=_.length;for(let S=0;S{const{slotScopeIds:A}=g;A&&(H=H?H.concat(A):A);const _=o(m),L=v(i(m),g,_,O,N,H,$);return L&&fn(L)&&L.data==="]"?i(g.anchor=L):(wt(),c(g.anchor=u("]"),_,L),L)},I=(m,g,O,N,H,$)=>{if(un(m.parentElement,1)||wt(),g.el=null,$){const L=G(m);for(;;){const S=i(m);if(S&&S!==L)l(S);else break}}const A=i(m),_=o(m);return l(m),n(null,g,_,A,O,N,an(_),H),A},G=(m,g="[",O="]")=>{let N=0;for(;m;)if(m=i(m),m&&fn(m)&&(m.data===g&&N++,m.data===O)){if(N===0)return i(m);N--}return m},V=(m,g,O)=>{const N=g.parentNode;N&&N.replaceChild(m,g);let H=O;for(;H;)H.vnode.el===g&&(H.vnode.el=H.subTree.el=m),H=H.parent},K=m=>m.nodeType===1&&m.tagName==="TEMPLATE";return[f,h]}const yr="data-allow-mismatch",Jl={0:"text",1:"children",2:"class",3:"style",4:"attribute"};function un(e,t){if(t===0||t===1)for(;e&&!e.hasAttribute(yr);)e=e.parentElement;const n=e&&e.getAttribute(yr);if(n==null)return!1;if(n==="")return!0;{const s=n.split(",");return t===0&&s.includes("children")?!0:n.split(",").includes(Jl[t])}}const gt=e=>!!e.type.__asyncLoader,Vn=e=>e.type.__isKeepAlive;function zl(e,t){Bi(e,"a",t)}function Ql(e,t){Bi(e,"da",t)}function Bi(e,t,n=ue){const s=e.__wdc||(e.__wdc=()=>{let r=n;for(;r;){if(r.isDeactivated)return;r=r.parent}return e()});if(kn(t,s,n),n){let r=n.parent;for(;r&&r.parent;)Vn(r.parent.vnode)&&Zl(s,t,n,r),r=r.parent}}function Zl(e,t,n,s){const r=kn(t,e,s,!0);Un(()=>{Fs(s[t],r)},n)}function kn(e,t,n=ue,s=!1){if(n){const r=n[e]||(n[e]=[]),i=t.__weh||(t.__weh=(...o)=>{it();const l=zt(n),c=Fe(t,n,e,o);return l(),ot(),c});return s?r.unshift(i):r.push(i),i}}const Ge=e=>(t,n=ue)=>{(!qn||e==="sp")&&kn(e,(...s)=>t(...s),n)},ec=Ge("bm"),Mt=Ge("m"),tc=Ge("bu"),nc=Ge("u"),Wi=Ge("bum"),Un=Ge("um"),sc=Ge("sp"),rc=Ge("rtg"),ic=Ge("rtc");function oc(e,t=ue){kn("ec",e,t)}const Ki="components";function Rf(e,t){return Gi(Ki,e,!0,t)||e}const qi=Symbol.for("v-ndc");function Of(e){return re(e)?Gi(Ki,e,!1)||e:e||qi}function Gi(e,t,n=!0,s=!1){const r=ce||ue;if(r){const i=r.type;{const l=Kc(i,!1);if(l&&(l===t||l===Ne(t)||l===In(Ne(t))))return i}const o=_r(r[e]||i[e],t)||_r(r.appContext[e],t);return!o&&s?i:o}}function _r(e,t){return e&&(e[t]||e[Ne(t)]||e[In(Ne(t))])}function Mf(e,t,n,s){let r;const i=n,o=U(e);if(o||re(e)){const l=o&&pt(e);let c=!1;l&&(c=!Pe(e),e=Nn(e)),r=new Array(e.length);for(let u=0,f=e.length;ut(l,c,void 0,i));else{const l=Object.keys(e);r=new Array(l.length);for(let c=0,u=l.length;c{const i=s.fn(...r);return i&&(i.key=s.key),i}:s.fn)}return e}function If(e,t,n={},s,r){if(ce.ce||ce.parent&>(ce.parent)&&ce.parent.ce)return t!=="default"&&(n.name=t),Rs(),Os(Se,null,[he("slot",n,s&&s())],64);let i=e[t];i&&i._c&&(i._d=!1),Rs();const o=i&&Yi(i(n)),l=Os(Se,{key:(n.key||o&&o.key||`_${t}`)+(!o&&s?"_fb":"")},o||(s?s():[]),o&&e._===1?64:-2);return!r&&l.scopeId&&(l.slotScopeIds=[l.scopeId+"-s"]),i&&i._c&&(i._d=!0),l}function Yi(e){return e.some(t=>An(t)?!(t.type===ye||t.type===Se&&!Yi(t.children)):!0)?e:null}function Lf(e,t){const n={};for(const s in e)n[/[A-Z]/.test(s)?`on:${s}`:gn(s)]=e[s];return n}const xs=e=>e?_o(e)?Gn(e):xs(e.parent):null,jt=le(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>xs(e.parent),$root:e=>xs(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>Xs(e),$forceUpdate:e=>e.f||(e.f=()=>{Ys(e.update)}),$nextTick:e=>e.n||(e.n=jn.bind(e.proxy)),$watch:e=>Rc.bind(e)}),ss=(e,t)=>e!==ee&&!e.__isScriptSetup&&z(e,t),lc={get({_:e},t){if(t==="__v_skip")return!0;const{ctx:n,setupState:s,data:r,props:i,accessCache:o,type:l,appContext:c}=e;let u;if(t[0]!=="$"){const v=o[t];if(v!==void 0)switch(v){case 1:return s[t];case 2:return r[t];case 4:return n[t];case 3:return i[t]}else{if(ss(s,t))return o[t]=1,s[t];if(r!==ee&&z(r,t))return o[t]=2,r[t];if((u=e.propsOptions[0])&&z(u,t))return o[t]=3,i[t];if(n!==ee&&z(n,t))return o[t]=4,n[t];Ts&&(o[t]=0)}}const f=jt[t];let h,p;if(f)return t==="$attrs"&&_e(e.attrs,"get",""),f(e);if((h=l.__cssModules)&&(h=h[t]))return h;if(n!==ee&&z(n,t))return o[t]=4,n[t];if(p=c.config.globalProperties,z(p,t))return p[t]},set({_:e},t,n){const{data:s,setupState:r,ctx:i}=e;return ss(r,t)?(r[t]=n,!0):s!==ee&&z(s,t)?(s[t]=n,!0):z(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:r,propsOptions:i}},o){let l;return!!n[o]||e!==ee&&z(e,o)||ss(t,o)||(l=i[0])&&z(l,o)||z(s,o)||z(jt,o)||z(r.config.globalProperties,o)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:z(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};function Nf(){return cc().slots}function cc(){const e=Kn();return e.setupContext||(e.setupContext=vo(e))}function br(e){return U(e)?e.reduce((t,n)=>(t[n]=null,t),{}):e}let Ts=!0;function ac(e){const t=Xs(e),n=e.proxy,s=e.ctx;Ts=!1,t.beforeCreate&&vr(t.beforeCreate,e,"bc");const{data:r,computed:i,methods:o,watch:l,provide:c,inject:u,created:f,beforeMount:h,mounted:p,beforeUpdate:v,updated:T,activated:I,deactivated:G,beforeDestroy:V,beforeUnmount:K,destroyed:m,unmounted:g,render:O,renderTracked:N,renderTriggered:H,errorCaptured:$,serverPrefetch:A,expose:_,inheritAttrs:L,components:S,directives:B,filters:se}=t;if(u&&fc(u,s,null),o)for(const Y in o){const D=o[Y];q(D)&&(s[Y]=D.bind(n))}if(r){const Y=r.call(n,n);ne(Y)&&(e.data=Hn(Y))}if(Ts=!0,i)for(const Y in i){const D=i[Y],fe=q(D)?D.bind(n,n):q(D.get)?D.get.bind(n,n):Ve,Qt=!q(D)&&q(D.set)?D.set.bind(n):Ve,lt=ie({get:fe,set:Qt});Object.defineProperty(s,Y,{enumerable:!0,configurable:!0,get:()=>lt.value,set:He=>lt.value=He})}if(l)for(const Y in l)Xi(l[Y],s,n,Y);if(c){const Y=q(c)?c.call(n):c;Reflect.ownKeys(Y).forEach(D=>{mc(D,Y[D])})}f&&vr(f,e,"c");function j(Y,D){U(D)?D.forEach(fe=>Y(fe.bind(n))):D&&Y(D.bind(n))}if(j(ec,h),j(Mt,p),j(tc,v),j(nc,T),j(zl,I),j(Ql,G),j(oc,$),j(ic,N),j(rc,H),j(Wi,K),j(Un,g),j(sc,A),U(_))if(_.length){const Y=e.exposed||(e.exposed={});_.forEach(D=>{Object.defineProperty(Y,D,{get:()=>n[D],set:fe=>n[D]=fe})})}else e.exposed||(e.exposed={});O&&e.render===Ve&&(e.render=O),L!=null&&(e.inheritAttrs=L),S&&(e.components=S),B&&(e.directives=B),A&&Ui(e)}function fc(e,t,n=Ve){U(e)&&(e=Cs(e));for(const s in e){const r=e[s];let i;ne(r)?"default"in r?i=Rt(r.from||s,r.default,!0):i=Rt(r.from||s):i=Rt(r),ae(i)?Object.defineProperty(t,s,{enumerable:!0,configurable:!0,get:()=>i.value,set:o=>i.value=o}):t[s]=i}}function vr(e,t,n){Fe(U(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function Xi(e,t,n,s){let r=s.includes(".")?ao(n,s):()=>n[s];if(re(e)){const i=t[e];q(i)&&ke(r,i)}else if(q(e))ke(r,e.bind(n));else if(ne(e))if(U(e))e.forEach(i=>Xi(i,t,n,s));else{const i=q(e.handler)?e.handler.bind(n):t[e.handler];q(i)&&ke(r,i,e)}}function Xs(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:r,optionsCache:i,config:{optionMergeStrategies:o}}=e.appContext,l=i.get(t);let c;return l?c=l:!r.length&&!n&&!s?c=t:(c={},r.length&&r.forEach(u=>Cn(c,u,o,!0)),Cn(c,t,o)),ne(t)&&i.set(t,c),c}function Cn(e,t,n,s=!1){const{mixins:r,extends:i}=t;i&&Cn(e,i,n,!0),r&&r.forEach(o=>Cn(e,o,n,!0));for(const o in t)if(!(s&&o==="expose")){const l=uc[o]||n&&n[o];e[o]=l?l(e[o],t[o]):t[o]}return e}const uc={data:wr,props:Sr,emits:Sr,methods:Ht,computed:Ht,beforeCreate:be,created:be,beforeMount:be,mounted:be,beforeUpdate:be,updated:be,beforeDestroy:be,beforeUnmount:be,destroyed:be,unmounted:be,activated:be,deactivated:be,errorCaptured:be,serverPrefetch:be,components:Ht,directives:Ht,watch:hc,provide:wr,inject:dc};function wr(e,t){return t?e?function(){return le(q(e)?e.call(this,this):e,q(t)?t.call(this,this):t)}:t:e}function dc(e,t){return Ht(Cs(e),Cs(t))}function Cs(e){if(U(e)){const t={};for(let n=0;n1)return n&&q(t)?t.call(s&&s.proxy):t}}const zi={},Qi=()=>Object.create(zi),Zi=e=>Object.getPrototypeOf(e)===zi;function yc(e,t,n,s=!1){const r={},i=Qi();e.propsDefaults=Object.create(null),eo(e,t,r,i);for(const o in e.propsOptions[0])o in r||(r[o]=void 0);n?e.props=s?r:Tl(r):e.type.props?e.props=r:e.props=i,e.attrs=i}function _c(e,t,n,s){const{props:r,attrs:i,vnode:{patchFlag:o}}=e,l=J(r),[c]=e.propsOptions;let u=!1;if((s||o>0)&&!(o&16)){if(o&8){const f=e.vnode.dynamicProps;for(let h=0;h{c=!0;const[p,v]=to(h,t,!0);le(o,p),v&&l.push(...v)};!n&&t.mixins.length&&t.mixins.forEach(f),e.extends&&f(e.extends),e.mixins&&e.mixins.forEach(f)}if(!i&&!c)return ne(e)&&s.set(e,Et),Et;if(U(i))for(let f=0;fe[0]==="_"||e==="$stable",Js=e=>U(e)?e.map(Me):[Me(e)],vc=(e,t,n)=>{if(t._n)return t;const s=Vl((...r)=>Js(t(...r)),n);return s._c=!1,s},so=(e,t,n)=>{const s=e._ctx;for(const r in e){if(no(r))continue;const i=e[r];if(q(i))t[r]=vc(r,i,s);else if(i!=null){const o=Js(i);t[r]=()=>o}}},ro=(e,t)=>{const n=Js(t);e.slots.default=()=>n},io=(e,t,n)=>{for(const s in t)(n||s!=="_")&&(e[s]=t[s])},wc=(e,t,n)=>{const s=e.slots=Qi();if(e.vnode.shapeFlag&32){const r=t._;r?(io(s,t,n),n&&si(s,"_",r,!0)):so(t,s)}else t&&ro(e,t)},Sc=(e,t,n)=>{const{vnode:s,slots:r}=e;let i=!0,o=ee;if(s.shapeFlag&32){const l=t._;l?n&&l===1?i=!1:io(r,t,n):(i=!t.$stable,so(t,r)),o=t}else t&&(ro(e,t),o={default:1});if(i)for(const l in r)!no(l)&&o[l]==null&&delete r[l]},Ee=ho;function Ec(e){return xc(e,Xl)}function xc(e,t){const n=ri();n.__VUE__=!0;const{insert:s,remove:r,patchProp:i,createElement:o,createText:l,createComment:c,setText:u,setElementText:f,parentNode:h,nextSibling:p,setScopeId:v=Ve,insertStaticContent:T}=e,I=(a,d,y,E=null,b=null,w=null,M=void 0,R=null,C=!!d.dynamicChildren)=>{if(a===d)return;a&&!dt(a,d)&&(E=Zt(a),He(a,b,w,!0),a=null),d.patchFlag===-2&&(C=!1,d.dynamicChildren=null);const{type:x,ref:k,shapeFlag:P}=d;switch(x){case mt:G(a,d,y,E);break;case ye:V(a,d,y,E);break;case Vt:a==null&&K(d,y,E,M);break;case Se:S(a,d,y,E,b,w,M,R,C);break;default:P&1?O(a,d,y,E,b,w,M,R,C):P&6?B(a,d,y,E,b,w,M,R,C):(P&64||P&128)&&x.process(a,d,y,E,b,w,M,R,C,bt)}k!=null&&b&&Tn(k,a&&a.ref,w,d||a,!d)},G=(a,d,y,E)=>{if(a==null)s(d.el=l(d.children),y,E);else{const b=d.el=a.el;d.children!==a.children&&u(b,d.children)}},V=(a,d,y,E)=>{a==null?s(d.el=c(d.children||""),y,E):d.el=a.el},K=(a,d,y,E)=>{[a.el,a.anchor]=T(a.children,d,y,E,a.el,a.anchor)},m=({el:a,anchor:d},y,E)=>{let b;for(;a&&a!==d;)b=p(a),s(a,y,E),a=b;s(d,y,E)},g=({el:a,anchor:d})=>{let y;for(;a&&a!==d;)y=p(a),r(a),a=y;r(d)},O=(a,d,y,E,b,w,M,R,C)=>{d.type==="svg"?M="svg":d.type==="math"&&(M="mathml"),a==null?N(d,y,E,b,w,M,R,C):A(a,d,b,w,M,R,C)},N=(a,d,y,E,b,w,M,R)=>{let C,x;const{props:k,shapeFlag:P,transition:F,dirs:W}=a;if(C=a.el=o(a.type,w,k&&k.is,k),P&8?f(C,a.children):P&16&&$(a.children,C,null,E,b,rs(a,w),M,R),W&&je(a,null,E,"created"),H(C,a,a.scopeId,M,E),k){for(const te in k)te!=="value"&&!Tt(te)&&i(C,te,null,k[te],w,E);"value"in k&&i(C,"value",null,k.value,w),(x=k.onVnodeBeforeMount)&&Oe(x,E,a)}W&&je(a,null,E,"beforeMount");const X=oo(b,F);X&&F.beforeEnter(C),s(C,d,y),((x=k&&k.onVnodeMounted)||X||W)&&Ee(()=>{x&&Oe(x,E,a),X&&F.enter(C),W&&je(a,null,E,"mounted")},b)},H=(a,d,y,E,b)=>{if(y&&v(a,y),E)for(let w=0;w{for(let x=C;x{const R=d.el=a.el;let{patchFlag:C,dynamicChildren:x,dirs:k}=d;C|=a.patchFlag&16;const P=a.props||ee,F=d.props||ee;let W;if(y&&ct(y,!1),(W=F.onVnodeBeforeUpdate)&&Oe(W,y,d,a),k&&je(d,a,y,"beforeUpdate"),y&&ct(y,!0),(P.innerHTML&&F.innerHTML==null||P.textContent&&F.textContent==null)&&f(R,""),x?_(a.dynamicChildren,x,R,y,E,rs(d,b),w):M||D(a,d,R,null,y,E,rs(d,b),w,!1),C>0){if(C&16)L(R,P,F,y,b);else if(C&2&&P.class!==F.class&&i(R,"class",null,F.class,b),C&4&&i(R,"style",P.style,F.style,b),C&8){const X=d.dynamicProps;for(let te=0;te{W&&Oe(W,y,d,a),k&&je(d,a,y,"updated")},E)},_=(a,d,y,E,b,w,M)=>{for(let R=0;R{if(d!==y){if(d!==ee)for(const w in d)!Tt(w)&&!(w in y)&&i(a,w,d[w],null,b,E);for(const w in y){if(Tt(w))continue;const M=y[w],R=d[w];M!==R&&w!=="value"&&i(a,w,R,M,b,E)}"value"in y&&i(a,"value",d.value,y.value,b)}},S=(a,d,y,E,b,w,M,R,C)=>{const x=d.el=a?a.el:l(""),k=d.anchor=a?a.anchor:l("");let{patchFlag:P,dynamicChildren:F,slotScopeIds:W}=d;W&&(R=R?R.concat(W):W),a==null?(s(x,y,E),s(k,y,E),$(d.children||[],y,k,b,w,M,R,C)):P>0&&P&64&&F&&a.dynamicChildren?(_(a.dynamicChildren,F,y,b,w,M,R),(d.key!=null||b&&d===b.subTree)&&zs(a,d,!0)):D(a,d,y,k,b,w,M,R,C)},B=(a,d,y,E,b,w,M,R,C)=>{d.slotScopeIds=R,a==null?d.shapeFlag&512?b.ctx.activate(d,y,E,M,C):se(d,y,E,b,w,M,C):oe(a,d,C)},se=(a,d,y,E,b,w,M)=>{const R=a.component=kc(a,E,b);if(Vn(a)&&(R.ctx.renderer=bt),Uc(R,!1,M),R.asyncDep){if(b&&b.registerDep(R,j,M),!a.el){const C=R.subTree=he(ye);V(null,C,d,y)}}else j(R,a,d,y,b,w,M)},oe=(a,d,y)=>{const E=d.component=a.component;if(Lc(a,d,y))if(E.asyncDep&&!E.asyncResolved){Y(E,d,y);return}else E.next=d,E.update();else d.el=a.el,E.vnode=d},j=(a,d,y,E,b,w,M)=>{const R=()=>{if(a.isMounted){let{next:P,bu:F,u:W,parent:X,vnode:te}=a;{const Te=lo(a);if(Te){P&&(P.el=te.el,Y(a,P,M)),Te.asyncDep.then(()=>{a.isUnmounted||R()});return}}let Q=P,xe;ct(a,!1),P?(P.el=te.el,Y(a,P,M)):P=te,F&&zn(F),(xe=P.props&&P.props.onVnodeBeforeUpdate)&&Oe(xe,X,P,te),ct(a,!0);const pe=is(a),Ie=a.subTree;a.subTree=pe,I(Ie,pe,h(Ie.el),Zt(Ie),a,b,w),P.el=pe.el,Q===null&&Nc(a,pe.el),W&&Ee(W,b),(xe=P.props&&P.props.onVnodeUpdated)&&Ee(()=>Oe(xe,X,P,te),b)}else{let P;const{el:F,props:W}=d,{bm:X,m:te,parent:Q,root:xe,type:pe}=a,Ie=gt(d);if(ct(a,!1),X&&zn(X),!Ie&&(P=W&&W.onVnodeBeforeMount)&&Oe(P,Q,d),ct(a,!0),F&&Jn){const Te=()=>{a.subTree=is(a),Jn(F,a.subTree,a,b,null)};Ie&&pe.__asyncHydrate?pe.__asyncHydrate(F,a,Te):Te()}else{xe.ce&&xe.ce._injectChildStyle(pe);const Te=a.subTree=is(a);I(null,Te,y,E,a,b,w),d.el=Te.el}if(te&&Ee(te,b),!Ie&&(P=W&&W.onVnodeMounted)){const Te=d;Ee(()=>Oe(P,Q,Te),b)}(d.shapeFlag&256||Q&>(Q.vnode)&&Q.vnode.shapeFlag&256)&&a.a&&Ee(a.a,b),a.isMounted=!0,d=y=E=null}};a.scope.on();const C=a.effect=new fi(R);a.scope.off();const x=a.update=C.run.bind(C),k=a.job=C.runIfDirty.bind(C);k.i=a,k.id=a.uid,C.scheduler=()=>Ys(k),ct(a,!0),x()},Y=(a,d,y)=>{d.component=a;const E=a.vnode.props;a.vnode=d,a.next=null,_c(a,d.props,E,y),Sc(a,d.children,y),it(),dr(a),ot()},D=(a,d,y,E,b,w,M,R,C=!1)=>{const x=a&&a.children,k=a?a.shapeFlag:0,P=d.children,{patchFlag:F,shapeFlag:W}=d;if(F>0){if(F&128){Qt(x,P,y,E,b,w,M,R,C);return}else if(F&256){fe(x,P,y,E,b,w,M,R,C);return}}W&8?(k&16&&Pt(x,b,w),P!==x&&f(y,P)):k&16?W&16?Qt(x,P,y,E,b,w,M,R,C):Pt(x,b,w,!0):(k&8&&f(y,""),W&16&&$(P,y,E,b,w,M,R,C))},fe=(a,d,y,E,b,w,M,R,C)=>{a=a||Et,d=d||Et;const x=a.length,k=d.length,P=Math.min(x,k);let F;for(F=0;Fk?Pt(a,b,w,!0,!1,P):$(d,y,E,b,w,M,R,C,P)},Qt=(a,d,y,E,b,w,M,R,C)=>{let x=0;const k=d.length;let P=a.length-1,F=k-1;for(;x<=P&&x<=F;){const W=a[x],X=d[x]=C?Ze(d[x]):Me(d[x]);if(dt(W,X))I(W,X,y,null,b,w,M,R,C);else break;x++}for(;x<=P&&x<=F;){const W=a[P],X=d[F]=C?Ze(d[F]):Me(d[F]);if(dt(W,X))I(W,X,y,null,b,w,M,R,C);else break;P--,F--}if(x>P){if(x<=F){const W=F+1,X=WF)for(;x<=P;)He(a[x],b,w,!0),x++;else{const W=x,X=x,te=new Map;for(x=X;x<=F;x++){const Ce=d[x]=C?Ze(d[x]):Me(d[x]);Ce.key!=null&&te.set(Ce.key,x)}let Q,xe=0;const pe=F-X+1;let Ie=!1,Te=0;const It=new Array(pe);for(x=0;x=pe){He(Ce,b,w,!0);continue}let De;if(Ce.key!=null)De=te.get(Ce.key);else for(Q=X;Q<=F;Q++)if(It[Q-X]===0&&dt(Ce,d[Q])){De=Q;break}De===void 0?He(Ce,b,w,!0):(It[De-X]=x+1,De>=Te?Te=De:Ie=!0,I(Ce,d[De],y,null,b,w,M,R,C),xe++)}const sr=Ie?Tc(It):Et;for(Q=sr.length-1,x=pe-1;x>=0;x--){const Ce=X+x,De=d[Ce],rr=Ce+1{const{el:w,type:M,transition:R,children:C,shapeFlag:x}=a;if(x&6){lt(a.component.subTree,d,y,E);return}if(x&128){a.suspense.move(d,y,E);return}if(x&64){M.move(a,d,y,bt);return}if(M===Se){s(w,d,y);for(let P=0;PR.enter(w),b);else{const{leave:P,delayLeave:F,afterLeave:W}=R,X=()=>s(w,d,y),te=()=>{P(w,()=>{X(),W&&W()})};F?F(w,X,te):te()}else s(w,d,y)},He=(a,d,y,E=!1,b=!1)=>{const{type:w,props:M,ref:R,children:C,dynamicChildren:x,shapeFlag:k,patchFlag:P,dirs:F,cacheIndex:W}=a;if(P===-2&&(b=!1),R!=null&&Tn(R,null,y,a,!0),W!=null&&(d.renderCache[W]=void 0),k&256){d.ctx.deactivate(a);return}const X=k&1&&F,te=!gt(a);let Q;if(te&&(Q=M&&M.onVnodeBeforeUnmount)&&Oe(Q,d,a),k&6)ko(a.component,y,E);else{if(k&128){a.suspense.unmount(y,E);return}X&&je(a,null,d,"beforeUnmount"),k&64?a.type.remove(a,d,y,bt,E):x&&!x.hasOnce&&(w!==Se||P>0&&P&64)?Pt(x,d,y,!1,!0):(w===Se&&P&384||!b&&k&16)&&Pt(C,d,y),E&&tr(a)}(te&&(Q=M&&M.onVnodeUnmounted)||X)&&Ee(()=>{Q&&Oe(Q,d,a),X&&je(a,null,d,"unmounted")},y)},tr=a=>{const{type:d,el:y,anchor:E,transition:b}=a;if(d===Se){Vo(y,E);return}if(d===Vt){g(a);return}const w=()=>{r(y),b&&!b.persisted&&b.afterLeave&&b.afterLeave()};if(a.shapeFlag&1&&b&&!b.persisted){const{leave:M,delayLeave:R}=b,C=()=>M(y,w);R?R(a.el,w,C):C()}else w()},Vo=(a,d)=>{let y;for(;a!==d;)y=p(a),r(a),a=y;r(d)},ko=(a,d,y)=>{const{bum:E,scope:b,job:w,subTree:M,um:R,m:C,a:x}=a;xr(C),xr(x),E&&zn(E),b.stop(),w&&(w.flags|=8,He(M,a,d,y)),R&&Ee(R,d),Ee(()=>{a.isUnmounted=!0},d),d&&d.pendingBranch&&!d.isUnmounted&&a.asyncDep&&!a.asyncResolved&&a.suspenseId===d.pendingId&&(d.deps--,d.deps===0&&d.resolve())},Pt=(a,d,y,E=!1,b=!1,w=0)=>{for(let M=w;M{if(a.shapeFlag&6)return Zt(a.component.subTree);if(a.shapeFlag&128)return a.suspense.next();const d=p(a.anchor||a.el),y=d&&d[Li];return y?p(y):d};let Yn=!1;const nr=(a,d,y)=>{a==null?d._vnode&&He(d._vnode,null,null,!0):I(d._vnode||null,a,d,null,null,null,y),d._vnode=a,Yn||(Yn=!0,dr(),En(),Yn=!1)},bt={p:I,um:He,m:lt,r:tr,mt:se,mc:$,pc:D,pbc:_,n:Zt,o:e};let Xn,Jn;return t&&([Xn,Jn]=t(bt)),{render:nr,hydrate:Xn,createApp:gc(nr,Xn)}}function rs({type:e,props:t},n){return n==="svg"&&e==="foreignObject"||n==="mathml"&&e==="annotation-xml"&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function ct({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function oo(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function zs(e,t,n=!1){const s=e.children,r=t.children;if(U(s)&&U(r))for(let i=0;i>1,e[n[l]]0&&(t[s]=n[i-1]),n[i]=s)}}for(i=n.length,o=n[i-1];i-- >0;)n[i]=o,o=t[o];return n}function lo(e){const t=e.subTree.component;if(t)return t.asyncDep&&!t.asyncResolved?t:lo(t)}function xr(e){if(e)for(let t=0;tRt(Cc);function co(e,t){return Bn(e,null,t)}function Ff(e,t){return Bn(e,null,{flush:"post"})}function ke(e,t,n){return Bn(e,t,n)}function Bn(e,t,n=ee){const{immediate:s,deep:r,flush:i,once:o}=n,l=le({},n);let c;if(qn)if(i==="sync"){const p=Ac();c=p.__watcherHandles||(p.__watcherHandles=[])}else if(!t||s)l.once=!0;else{const p=()=>{};return p.stop=Ve,p.resume=Ve,p.pause=Ve,p}const u=ue;l.call=(p,v,T)=>Fe(p,u,v,T);let f=!1;i==="post"?l.scheduler=p=>{Ee(p,u&&u.suspense)}:i!=="sync"&&(f=!0,l.scheduler=(p,v)=>{v?p():Ys(p)}),l.augmentJob=p=>{t&&(p.flags|=4),f&&(p.flags|=2,u&&(p.id=u.uid,p.i=u))};const h=Hl(e,t,l);return c&&c.push(h),h}function Rc(e,t,n){const s=this.proxy,r=re(e)?e.includes(".")?ao(s,e):()=>s[e]:e.bind(s,s);let i;q(t)?i=t:(i=t.handler,n=t);const o=zt(this),l=Bn(r,i.bind(s),n);return o(),l}function ao(e,t){const n=t.split(".");return()=>{let s=e;for(let r=0;rt==="modelValue"||t==="model-value"?e.modelModifiers:e[`${t}Modifiers`]||e[`${Ne(t)}Modifiers`]||e[`${rt(t)}Modifiers`];function Mc(e,t,...n){if(e.isUnmounted)return;const s=e.vnode.props||ee;let r=n;const i=t.startsWith("update:"),o=i&&Oc(s,t.slice(7));o&&(o.trim&&(r=n.map(f=>re(f)?f.trim():f)),o.number&&(r=n.map(Go)));let l,c=s[l=gn(t)]||s[l=gn(Ne(t))];!c&&i&&(c=s[l=gn(rt(t))]),c&&Fe(c,e,6,r);const u=s[l+"Once"];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,Fe(u,e,6,r)}}function fo(e,t,n=!1){const s=t.emitsCache,r=s.get(e);if(r!==void 0)return r;const i=e.emits;let o={},l=!1;if(!q(e)){const c=u=>{const f=fo(u,t,!0);f&&(l=!0,le(o,f))};!n&&t.mixins.length&&t.mixins.forEach(c),e.extends&&c(e.extends),e.mixins&&e.mixins.forEach(c)}return!i&&!l?(ne(e)&&s.set(e,null),null):(U(i)?i.forEach(c=>o[c]=null):le(o,i),ne(e)&&s.set(e,o),o)}function Wn(e,t){return!e||!Xt(t)?!1:(t=t.slice(2).replace(/Once$/,""),z(e,t[0].toLowerCase()+t.slice(1))||z(e,rt(t))||z(e,t))}function is(e){const{type:t,vnode:n,proxy:s,withProxy:r,propsOptions:[i],slots:o,attrs:l,emit:c,render:u,renderCache:f,props:h,data:p,setupState:v,ctx:T,inheritAttrs:I}=e,G=xn(e);let V,K;try{if(n.shapeFlag&4){const g=r||s,O=g;V=Me(u.call(O,g,f,h,v,p,T)),K=l}else{const g=t;V=Me(g.length>1?g(h,{attrs:l,slots:o,emit:c}):g(h,null)),K=t.props?l:Pc(l)}}catch(g){kt.length=0,$n(g,e,1),V=he(ye)}let m=V;if(K&&I!==!1){const g=Object.keys(K),{shapeFlag:O}=m;g.length&&O&7&&(i&&g.some(Ns)&&(K=Ic(K,i)),m=nt(m,K,!1,!0))}return n.dirs&&(m=nt(m,null,!1,!0),m.dirs=m.dirs?m.dirs.concat(n.dirs):n.dirs),n.transition&&qt(m,n.transition),V=m,xn(G),V}const Pc=e=>{let t;for(const n in e)(n==="class"||n==="style"||Xt(n))&&((t||(t={}))[n]=e[n]);return t},Ic=(e,t)=>{const n={};for(const s in e)(!Ns(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function Lc(e,t,n){const{props:s,children:r,component:i}=e,{props:o,children:l,patchFlag:c}=t,u=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&c>=0){if(c&1024)return!0;if(c&16)return s?Tr(s,o,u):!!o;if(c&8){const f=t.dynamicProps;for(let h=0;he.__isSuspense;function ho(e,t){t&&t.pendingBranch?U(e)?t.effects.push(...e):t.effects.push(e):jl(e)}const Se=Symbol.for("v-fgt"),mt=Symbol.for("v-txt"),ye=Symbol.for("v-cmt"),Vt=Symbol.for("v-stc"),kt=[];let Ae=null;function Rs(e=!1){kt.push(Ae=e?null:[])}function Fc(){kt.pop(),Ae=kt[kt.length-1]||null}let Gt=1;function Cr(e){Gt+=e,e<0&&Ae&&(Ae.hasOnce=!0)}function po(e){return e.dynamicChildren=Gt>0?Ae||Et:null,Fc(),Gt>0&&Ae&&Ae.push(e),e}function Hf(e,t,n,s,r,i){return po(mo(e,t,n,s,r,i,!0))}function Os(e,t,n,s,r){return po(he(e,t,n,s,r,!0))}function An(e){return e?e.__v_isVNode===!0:!1}function dt(e,t){return e.type===t.type&&e.key===t.key}const go=({key:e})=>e??null,_n=({ref:e,ref_key:t,ref_for:n})=>(typeof e=="number"&&(e=""+e),e!=null?re(e)||ae(e)||q(e)?{i:ce,r:e,k:t,f:!!n}:e:null);function mo(e,t=null,n=null,s=0,r=null,i=e===Se?0:1,o=!1,l=!1){const c={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&go(t),ref:t&&_n(t),scopeId:Ii,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:s,dynamicProps:r,dynamicChildren:null,appContext:null,ctx:ce};return l?(Qs(c,n),i&128&&e.normalize(c)):n&&(c.shapeFlag|=re(n)?8:16),Gt>0&&!o&&Ae&&(c.patchFlag>0||i&6)&&c.patchFlag!==32&&Ae.push(c),c}const he=Hc;function Hc(e,t=null,n=null,s=0,r=null,i=!1){if((!e||e===qi)&&(e=ye),An(e)){const l=nt(e,t,!0);return n&&Qs(l,n),Gt>0&&!i&&Ae&&(l.shapeFlag&6?Ae[Ae.indexOf(e)]=l:Ae.push(l)),l.patchFlag=-2,l}if(qc(e)&&(e=e.__vccOpts),t){t=Dc(t);let{class:l,style:c}=t;l&&!re(l)&&(t.class=$s(l)),ne(c)&&(Ks(c)&&!U(c)&&(c=le({},c)),t.style=Ds(c))}const o=re(e)?1:uo(e)?128:Ni(e)?64:ne(e)?4:q(e)?2:0;return mo(e,t,n,s,r,o,i,!0)}function Dc(e){return e?Ks(e)||Zi(e)?le({},e):e:null}function nt(e,t,n=!1,s=!1){const{props:r,ref:i,patchFlag:o,children:l,transition:c}=e,u=t?$c(r||{},t):r,f={__v_isVNode:!0,__v_skip:!0,type:e.type,props:u,key:u&&go(u),ref:t&&t.ref?n&&i?U(i)?i.concat(_n(t)):[i,_n(t)]:_n(t):i,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:l,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Se?o===-1?16:o|16:o,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:c,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&nt(e.ssContent),ssFallback:e.ssFallback&&nt(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return c&&s&&qt(f,c.clone(f)),f}function yo(e=" ",t=0){return he(mt,null,e,t)}function Df(e,t){const n=he(Vt,null,e);return n.staticCount=t,n}function $f(e="",t=!1){return t?(Rs(),Os(ye,null,e)):he(ye,null,e)}function Me(e){return e==null||typeof e=="boolean"?he(ye):U(e)?he(Se,null,e.slice()):typeof e=="object"?Ze(e):he(mt,null,String(e))}function Ze(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:nt(e)}function Qs(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(U(t))n=16;else if(typeof t=="object")if(s&65){const r=t.default;r&&(r._c&&(r._d=!1),Qs(e,r()),r._c&&(r._d=!0));return}else{n=32;const r=t._;!r&&!Zi(t)?t._ctx=ce:r===3&&ce&&(ce.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else q(t)?(t={default:t,_ctx:ce},n=32):(t=String(t),s&64?(n=16,t=[yo(t)]):n=8);e.children=t,e.shapeFlag|=n}function $c(...e){const t={};for(let n=0;nue||ce;let Rn,Ms;{const e=ri(),t=(n,s)=>{let r;return(r=e[n])||(r=e[n]=[]),r.push(s),i=>{r.length>1?r.forEach(o=>o(i)):r[0](i)}};Rn=t("__VUE_INSTANCE_SETTERS__",n=>ue=n),Ms=t("__VUE_SSR_SETTERS__",n=>qn=n)}const zt=e=>{const t=ue;return Rn(e),e.scope.on(),()=>{e.scope.off(),Rn(t)}},Ar=()=>{ue&&ue.scope.off(),Rn(null)};function _o(e){return e.vnode.shapeFlag&4}let qn=!1;function Uc(e,t=!1,n=!1){t&&Ms(t);const{props:s,children:r}=e.vnode,i=_o(e);yc(e,s,i,t),wc(e,r,n);const o=i?Bc(e,t):void 0;return t&&Ms(!1),o}function Bc(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,lc);const{setup:s}=n;if(s){const r=e.setupContext=s.length>1?vo(e):null,i=zt(e);it();const o=Jt(s,e,0,[e.props,r]);if(ot(),i(),ei(o)){if(gt(e)||Ui(e),o.then(Ar,Ar),t)return o.then(l=>{Rr(e,l,t)}).catch(l=>{$n(l,e,0)});e.asyncDep=o}else Rr(e,o,t)}else bo(e,t)}function Rr(e,t,n){q(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:ne(t)&&(e.setupState=Ai(t)),bo(e,n)}let Or;function bo(e,t,n){const s=e.type;if(!e.render){if(!t&&Or&&!s.render){const r=s.template||Xs(e).template;if(r){const{isCustomElement:i,compilerOptions:o}=e.appContext.config,{delimiters:l,compilerOptions:c}=s,u=le(le({isCustomElement:i,delimiters:l},o),c);s.render=Or(r,u)}}e.render=s.render||Ve}{const r=zt(e);it();try{ac(e)}finally{ot(),r()}}}const Wc={get(e,t){return _e(e,"get",""),e[t]}};function vo(e){const t=n=>{e.exposed=n||{}};return{attrs:new Proxy(e.attrs,Wc),slots:e.slots,emit:e.emit,expose:t}}function Gn(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(Ai(mn(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in jt)return jt[n](e)},has(t,n){return n in t||n in jt}})):e.proxy}function Kc(e,t=!0){return q(e)?e.displayName||e.name:e.name||t&&e.__name}function qc(e){return q(e)&&"__vccOpts"in e}const ie=(e,t)=>Nl(e,t,qn);function Ps(e,t,n){const s=arguments.length;return s===2?ne(t)&&!U(t)?An(t)?he(e,null,[t]):he(e,t):he(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&An(n)&&(n=[n]),he(e,t,n))}const Gc="3.5.6";/** +* @vue/runtime-dom v3.5.6 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/let Is;const Mr=typeof window<"u"&&window.trustedTypes;if(Mr)try{Is=Mr.createPolicy("vue",{createHTML:e=>e})}catch{}const wo=Is?e=>Is.createHTML(e):e=>e,Yc="http://www.w3.org/2000/svg",Xc="http://www.w3.org/1998/Math/MathML",Be=typeof document<"u"?document:null,Pr=Be&&Be.createElement("template"),Jc={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t==="svg"?Be.createElementNS(Yc,e):t==="mathml"?Be.createElementNS(Xc,e):n?Be.createElement(e,{is:n}):Be.createElement(e);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>Be.createTextNode(e),createComment:e=>Be.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Be.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,r,i){const o=n?n.previousSibling:t.lastChild;if(r&&(r===i||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===i||!(r=r.nextSibling)););else{Pr.innerHTML=wo(s==="svg"?`${e}`:s==="mathml"?`${e}`:e);const l=Pr.content;if(s==="svg"||s==="mathml"){const c=l.firstChild;for(;c.firstChild;)l.appendChild(c.firstChild);l.removeChild(c)}t.insertBefore(l,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},Xe="transition",Nt="animation",Yt=Symbol("_vtc"),So={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},zc=le({},Hi,So),Qc=e=>(e.displayName="Transition",e.props=zc,e),jf=Qc((e,{slots:t})=>Ps(ql,Zc(e),t)),at=(e,t=[])=>{U(e)?e.forEach(n=>n(...t)):e&&e(...t)},Ir=e=>e?U(e)?e.some(t=>t.length>1):e.length>1:!1;function Zc(e){const t={};for(const S in e)S in So||(t[S]=e[S]);if(e.css===!1)return t;const{name:n="v",type:s,duration:r,enterFromClass:i=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:c=i,appearActiveClass:u=o,appearToClass:f=l,leaveFromClass:h=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:v=`${n}-leave-to`}=e,T=ea(r),I=T&&T[0],G=T&&T[1],{onBeforeEnter:V,onEnter:K,onEnterCancelled:m,onLeave:g,onLeaveCancelled:O,onBeforeAppear:N=V,onAppear:H=K,onAppearCancelled:$=m}=t,A=(S,B,se)=>{ft(S,B?f:l),ft(S,B?u:o),se&&se()},_=(S,B)=>{S._isLeaving=!1,ft(S,h),ft(S,v),ft(S,p),B&&B()},L=S=>(B,se)=>{const oe=S?H:K,j=()=>A(B,S,se);at(oe,[B,j]),Lr(()=>{ft(B,S?c:i),Je(B,S?f:l),Ir(oe)||Nr(B,s,I,j)})};return le(t,{onBeforeEnter(S){at(V,[S]),Je(S,i),Je(S,o)},onBeforeAppear(S){at(N,[S]),Je(S,c),Je(S,u)},onEnter:L(!1),onAppear:L(!0),onLeave(S,B){S._isLeaving=!0;const se=()=>_(S,B);Je(S,h),Je(S,p),sa(),Lr(()=>{S._isLeaving&&(ft(S,h),Je(S,v),Ir(g)||Nr(S,s,G,se))}),at(g,[S,se])},onEnterCancelled(S){A(S,!1),at(m,[S])},onAppearCancelled(S){A(S,!0),at($,[S])},onLeaveCancelled(S){_(S),at(O,[S])}})}function ea(e){if(e==null)return null;if(ne(e))return[os(e.enter),os(e.leave)];{const t=os(e);return[t,t]}}function os(e){return Yo(e)}function Je(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e[Yt]||(e[Yt]=new Set)).add(t)}function ft(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const n=e[Yt];n&&(n.delete(t),n.size||(e[Yt]=void 0))}function Lr(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let ta=0;function Nr(e,t,n,s){const r=e._endId=++ta,i=()=>{r===e._endId&&s()};if(n)return setTimeout(i,n);const{type:o,timeout:l,propCount:c}=na(e,t);if(!o)return s();const u=o+"end";let f=0;const h=()=>{e.removeEventListener(u,p),i()},p=v=>{v.target===e&&++f>=c&&h()};setTimeout(()=>{f(n[T]||"").split(", "),r=s(`${Xe}Delay`),i=s(`${Xe}Duration`),o=Fr(r,i),l=s(`${Nt}Delay`),c=s(`${Nt}Duration`),u=Fr(l,c);let f=null,h=0,p=0;t===Xe?o>0&&(f=Xe,h=o,p=i.length):t===Nt?u>0&&(f=Nt,h=u,p=c.length):(h=Math.max(o,u),f=h>0?o>u?Xe:Nt:null,p=f?f===Xe?i.length:c.length:0);const v=f===Xe&&/\b(transform|all)(,|$)/.test(s(`${Xe}Property`).toString());return{type:f,timeout:h,propCount:p,hasTransform:v}}function Fr(e,t){for(;e.lengthHr(n)+Hr(e[s])))}function Hr(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function sa(){return document.body.offsetHeight}function ra(e,t,n){const s=e[Yt];s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}const On=Symbol("_vod"),Eo=Symbol("_vsh"),Vf={beforeMount(e,{value:t},{transition:n}){e[On]=e.style.display==="none"?"":e.style.display,n&&t?n.beforeEnter(e):Ft(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:s}){!t!=!n&&(s?t?(s.beforeEnter(e),Ft(e,!0),s.enter(e)):s.leave(e,()=>{Ft(e,!1)}):Ft(e,t))},beforeUnmount(e,{value:t}){Ft(e,t)}};function Ft(e,t){e.style.display=t?e[On]:"none",e[Eo]=!t}const ia=Symbol(""),oa=/(^|;)\s*display\s*:/;function la(e,t,n){const s=e.style,r=re(n);let i=!1;if(n&&!r){if(t)if(re(t))for(const o of t.split(";")){const l=o.slice(0,o.indexOf(":")).trim();n[l]==null&&bn(s,l,"")}else for(const o in t)n[o]==null&&bn(s,o,"");for(const o in n)o==="display"&&(i=!0),bn(s,o,n[o])}else if(r){if(t!==n){const o=s[ia];o&&(n+=";"+o),s.cssText=n,i=oa.test(n)}}else t&&e.removeAttribute("style");On in e&&(e[On]=i?s.display:"",e[Eo]&&(s.display="none"))}const Dr=/\s*!important$/;function bn(e,t,n){if(U(n))n.forEach(s=>bn(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=ca(e,t);Dr.test(n)?e.setProperty(rt(s),n.replace(Dr,""),"important"):e[s]=n}}const $r=["Webkit","Moz","ms"],ls={};function ca(e,t){const n=ls[t];if(n)return n;let s=Ne(t);if(s!=="filter"&&s in e)return ls[t]=s;s=In(s);for(let r=0;r<$r.length;r++){const i=$r[r]+s;if(i in e)return ls[t]=i}return t}const jr="http://www.w3.org/1999/xlink";function Vr(e,t,n,s,r,i=el(t)){s&&t.startsWith("xlink:")?n==null?e.removeAttributeNS(jr,t.slice(6,t.length)):e.setAttributeNS(jr,t,n):n==null||i&&!ii(n)?e.removeAttribute(t):e.setAttribute(t,i?"":st(n)?String(n):n)}function aa(e,t,n,s){if(t==="innerHTML"||t==="textContent"){n!=null&&(e[t]=t==="innerHTML"?wo(n):n);return}const r=e.tagName;if(t==="value"&&r!=="PROGRESS"&&!r.includes("-")){const o=r==="OPTION"?e.getAttribute("value")||"":e.value,l=n==null?e.type==="checkbox"?"on":"":String(n);(o!==l||!("_value"in e))&&(e.value=l),n==null&&e.removeAttribute(t),e._value=n;return}let i=!1;if(n===""||n==null){const o=typeof e[t];o==="boolean"?n=ii(n):n==null&&o==="string"?(n="",i=!0):o==="number"&&(n=0,i=!0)}try{e[t]=n}catch{}i&&e.removeAttribute(t)}function fa(e,t,n,s){e.addEventListener(t,n,s)}function ua(e,t,n,s){e.removeEventListener(t,n,s)}const kr=Symbol("_vei");function da(e,t,n,s,r=null){const i=e[kr]||(e[kr]={}),o=i[t];if(s&&o)o.value=s;else{const[l,c]=ha(t);if(s){const u=i[t]=ma(s,r);fa(e,l,u,c)}else o&&(ua(e,l,o,c),i[t]=void 0)}}const Ur=/(?:Once|Passive|Capture)$/;function ha(e){let t;if(Ur.test(e)){t={};let s;for(;s=e.match(Ur);)e=e.slice(0,e.length-s[0].length),t[s[0].toLowerCase()]=!0}return[e[2]===":"?e.slice(3):rt(e.slice(2)),t]}let cs=0;const pa=Promise.resolve(),ga=()=>cs||(pa.then(()=>cs=0),cs=Date.now());function ma(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;Fe(ya(s,n.value),t,5,[s])};return n.value=e,n.attached=ga(),n}function ya(e,t){if(U(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>r=>!r._stopped&&s&&s(r))}else return t}const Br=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,_a=(e,t,n,s,r,i)=>{const o=r==="svg";t==="class"?ra(e,s,o):t==="style"?la(e,n,s):Xt(t)?Ns(t)||da(e,t,n,s,i):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):ba(e,t,s,o))?(aa(e,t,s),!e.tagName.includes("-")&&(t==="value"||t==="checked"||t==="selected")&&Vr(e,t,s,o,i,t!=="value")):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Vr(e,t,s,o))};function ba(e,t,n,s){if(s)return!!(t==="innerHTML"||t==="textContent"||t in e&&Br(t)&&q(n));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const r=e.tagName;if(r==="IMG"||r==="VIDEO"||r==="CANVAS"||r==="SOURCE")return!1}return Br(t)&&re(n)?!1:!!(t in e||e._isVueCE&&(/[A-Z]/.test(t)||!re(n)))}const va=["ctrl","shift","alt","meta"],wa={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&e.button!==0,middle:e=>"button"in e&&e.button!==1,right:e=>"button"in e&&e.button!==2,exact:(e,t)=>va.some(n=>e[`${n}Key`]&&!t.includes(n))},kf=(e,t)=>{const n=e._withMods||(e._withMods={}),s=t.join(".");return n[s]||(n[s]=(r,...i)=>{for(let o=0;o{const n=e._withKeys||(e._withKeys={}),s=t.join(".");return n[s]||(n[s]=r=>{if(!("key"in r))return;const i=rt(r.key);if(t.some(o=>o===i||Sa[o]===i))return e(r)})},Ea=le({patchProp:_a},Jc);let as,Wr=!1;function xa(){return as=Wr?as:Ec(Ea),Wr=!0,as}const Bf=(...e)=>{const t=xa().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=Ca(s);if(r)return n(r,!0,Ta(r))},t};function Ta(e){if(e instanceof SVGElement)return"svg";if(typeof MathMLElement=="function"&&e instanceof MathMLElement)return"mathml"}function Ca(e){return re(e)?document.querySelector(e):e}const Wf=(e,t)=>{const n=e.__vccOpts||e;for(const[s,r]of t)n[s]=r;return n},Aa="modulepreload",Ra=function(e){return"/ran/"+e},Kr={},Kf=function(t,n,s){let r=Promise.resolve();if(n&&n.length>0){document.getElementsByTagName("link");const o=document.querySelector("meta[property=csp-nonce]"),l=(o==null?void 0:o.nonce)||(o==null?void 0:o.getAttribute("nonce"));r=Promise.allSettled(n.map(c=>{if(c=Ra(c),c in Kr)return;Kr[c]=!0;const u=c.endsWith(".css"),f=u?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${c}"]${f}`))return;const h=document.createElement("link");if(h.rel=u?"stylesheet":Aa,u||(h.as="script"),h.crossOrigin="",h.href=c,l&&h.setAttribute("nonce",l),document.head.appendChild(h),u)return new Promise((p,v)=>{h.addEventListener("load",p),h.addEventListener("error",()=>v(new Error(`Unable to preload CSS for ${c}`)))})}))}function i(o){const l=new Event("vite:preloadError",{cancelable:!0});if(l.payload=o,window.dispatchEvent(l),!l.defaultPrevented)throw o}return r.then(o=>{for(const l of o||[])l.status==="rejected"&&i(l.reason);return t().catch(i)})},Oa=window.__VP_SITE_DATA__;function Zs(e){return ai()?(nl(e),!0):!1}function et(e){return typeof e=="function"?e():Ci(e)}const xo=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const Ma=Object.prototype.toString,Pa=e=>Ma.call(e)==="[object Object]",To=()=>{},qr=Ia();function Ia(){var e,t;return xo&&((e=window==null?void 0:window.navigator)==null?void 0:e.userAgent)&&(/iP(?:ad|hone|od)/.test(window.navigator.userAgent)||((t=window==null?void 0:window.navigator)==null?void 0:t.maxTouchPoints)>2&&/iPad|Macintosh/.test(window==null?void 0:window.navigator.userAgent))}function La(e,t){function n(...s){return new Promise((r,i)=>{Promise.resolve(e(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(r).catch(i)})}return n}const Co=e=>e();function Na(e=Co){const t=de(!0);function n(){t.value=!1}function s(){t.value=!0}const r=(...i)=>{t.value&&e(...i)};return{isActive:Dn(t),pause:n,resume:s,eventFilter:r}}function Fa(e){return Kn()}function Ao(...e){if(e.length!==1)return Il(...e);const t=e[0];return typeof t=="function"?Dn(Ol(()=>({get:t,set:To}))):de(t)}function Ha(e,t,n={}){const{eventFilter:s=Co,...r}=n;return ke(e,La(s,t),r)}function Da(e,t,n={}){const{eventFilter:s,...r}=n,{eventFilter:i,pause:o,resume:l,isActive:c}=Na(s);return{stop:Ha(e,t,{...r,eventFilter:i}),pause:o,resume:l,isActive:c}}function er(e,t=!0,n){Fa()?Mt(e,n):t?e():jn(e)}const qe=xo?window:void 0;function Ro(e){var t;const n=et(e);return(t=n==null?void 0:n.$el)!=null?t:n}function Ot(...e){let t,n,s,r;if(typeof e[0]=="string"||Array.isArray(e[0])?([n,s,r]=e,t=qe):[t,n,s,r]=e,!t)return To;Array.isArray(n)||(n=[n]),Array.isArray(s)||(s=[s]);const i=[],o=()=>{i.forEach(f=>f()),i.length=0},l=(f,h,p,v)=>(f.addEventListener(h,p,v),()=>f.removeEventListener(h,p,v)),c=ke(()=>[Ro(t),et(r)],([f,h])=>{if(o(),!f)return;const p=Pa(h)?{...h}:h;i.push(...n.flatMap(v=>s.map(T=>l(f,v,T,p))))},{immediate:!0,flush:"post"}),u=()=>{c(),o()};return Zs(u),u}function $a(e){return typeof e=="function"?e:typeof e=="string"?t=>t.key===e:Array.isArray(e)?t=>e.includes(t.key):()=>!0}function qf(...e){let t,n,s={};e.length===3?(t=e[0],n=e[1],s=e[2]):e.length===2?typeof e[1]=="object"?(t=!0,n=e[0],s=e[1]):(t=e[0],n=e[1]):(t=!0,n=e[0]);const{target:r=qe,eventName:i="keydown",passive:o=!1,dedupe:l=!1}=s,c=$a(t);return Ot(r,i,f=>{f.repeat&&et(l)||c(f)&&n(f)},o)}function ja(){const e=de(!1),t=Kn();return t&&Mt(()=>{e.value=!0},t),e}function Va(e){const t=ja();return ie(()=>(t.value,!!e()))}function Oo(e,t={}){const{window:n=qe}=t,s=Va(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let r;const i=de(!1),o=u=>{i.value=u.matches},l=()=>{r&&("removeEventListener"in r?r.removeEventListener("change",o):r.removeListener(o))},c=co(()=>{s.value&&(l(),r=n.matchMedia(et(e)),"addEventListener"in r?r.addEventListener("change",o):r.addListener(o),i.value=r.matches)});return Zs(()=>{c(),l(),r=void 0}),i}const dn=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},hn="__vueuse_ssr_handlers__",ka=Ua();function Ua(){return hn in dn||(dn[hn]=dn[hn]||{}),dn[hn]}function Mo(e,t){return ka[e]||t}function Po(e){return Oo("(prefers-color-scheme: dark)",e)}function Ba(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const Wa={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},Gr="vueuse-storage";function Ka(e,t,n,s={}){var r;const{flush:i="pre",deep:o=!0,listenToStorageChanges:l=!0,writeDefaults:c=!0,mergeDefaults:u=!1,shallow:f,window:h=qe,eventFilter:p,onError:v=_=>{console.error(_)},initOnMounted:T}=s,I=(f?xi:de)(typeof t=="function"?t():t);if(!n)try{n=Mo("getDefaultStorage",()=>{var _;return(_=qe)==null?void 0:_.localStorage})()}catch(_){v(_)}if(!n)return I;const G=et(t),V=Ba(G),K=(r=s.serializer)!=null?r:Wa[V],{pause:m,resume:g}=Da(I,()=>N(I.value),{flush:i,deep:o,eventFilter:p});h&&l&&er(()=>{n instanceof Storage?Ot(h,"storage",$):Ot(h,Gr,A),T&&$()}),T||$();function O(_,L){if(h){const S={key:e,oldValue:_,newValue:L,storageArea:n};h.dispatchEvent(n instanceof Storage?new StorageEvent("storage",S):new CustomEvent(Gr,{detail:S}))}}function N(_){try{const L=n.getItem(e);if(_==null)O(L,null),n.removeItem(e);else{const S=K.write(_);L!==S&&(n.setItem(e,S),O(L,S))}}catch(L){v(L)}}function H(_){const L=_?_.newValue:n.getItem(e);if(L==null)return c&&G!=null&&n.setItem(e,K.write(G)),G;if(!_&&u){const S=K.read(L);return typeof u=="function"?u(S,G):V==="object"&&!Array.isArray(S)?{...G,...S}:S}else return typeof L!="string"?L:K.read(L)}function $(_){if(!(_&&_.storageArea!==n)){if(_&&_.key==null){I.value=G;return}if(!(_&&_.key!==e)){m();try{(_==null?void 0:_.newValue)!==K.write(I.value)&&(I.value=H(_))}catch(L){v(L)}finally{_?jn(g):g()}}}}function A(_){$(_.detail)}return I}const qa="*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}";function Ga(e={}){const{selector:t="html",attribute:n="class",initialValue:s="auto",window:r=qe,storage:i,storageKey:o="vueuse-color-scheme",listenToStorageChanges:l=!0,storageRef:c,emitAuto:u,disableTransition:f=!0}=e,h={auto:"",light:"light",dark:"dark",...e.modes||{}},p=Po({window:r}),v=ie(()=>p.value?"dark":"light"),T=c||(o==null?Ao(s):Ka(o,s,i,{window:r,listenToStorageChanges:l})),I=ie(()=>T.value==="auto"?v.value:T.value),G=Mo("updateHTMLAttrs",(g,O,N)=>{const H=typeof g=="string"?r==null?void 0:r.document.querySelector(g):Ro(g);if(!H)return;const $=new Set,A=new Set;let _=null;if(O==="class"){const S=N.split(/\s/g);Object.values(h).flatMap(B=>(B||"").split(/\s/g)).filter(Boolean).forEach(B=>{S.includes(B)?$.add(B):A.add(B)})}else _={key:O,value:N};if($.size===0&&A.size===0&&_===null)return;let L;f&&(L=r.document.createElement("style"),L.appendChild(document.createTextNode(qa)),r.document.head.appendChild(L));for(const S of $)H.classList.add(S);for(const S of A)H.classList.remove(S);_&&H.setAttribute(_.key,_.value),f&&(r.getComputedStyle(L).opacity,document.head.removeChild(L))});function V(g){var O;G(t,n,(O=h[g])!=null?O:g)}function K(g){e.onChanged?e.onChanged(g,V):V(g)}ke(I,K,{flush:"post",immediate:!0}),er(()=>K(I.value));const m=ie({get(){return u?T.value:I.value},set(g){T.value=g}});try{return Object.assign(m,{store:T,system:v,state:I})}catch{return m}}function Ya(e={}){const{valueDark:t="dark",valueLight:n="",window:s=qe}=e,r=Ga({...e,onChanged:(l,c)=>{var u;e.onChanged?(u=e.onChanged)==null||u.call(e,l==="dark",c,l):c(l)},modes:{dark:t,light:n}}),i=ie(()=>r.system?r.system.value:Po({window:s}).value?"dark":"light");return ie({get(){return r.value==="dark"},set(l){const c=l?"dark":"light";i.value===c?r.value="auto":r.value=c}})}function fs(e){return typeof Window<"u"&&e instanceof Window?e.document.documentElement:typeof Document<"u"&&e instanceof Document?e.documentElement:e}function Io(e){const t=window.getComputedStyle(e);if(t.overflowX==="scroll"||t.overflowY==="scroll"||t.overflowX==="auto"&&e.clientWidth1?!0:(t.preventDefault&&t.preventDefault(),!1)}const us=new WeakMap;function Gf(e,t=!1){const n=de(t);let s=null,r="";ke(Ao(e),l=>{const c=fs(et(l));if(c){const u=c;if(us.get(u)||us.set(u,u.style.overflow),u.style.overflow!=="hidden"&&(r=u.style.overflow),u.style.overflow==="hidden")return n.value=!0;if(n.value)return u.style.overflow="hidden"}},{immediate:!0});const i=()=>{const l=fs(et(e));!l||n.value||(qr&&(s=Ot(l,"touchmove",c=>{Xa(c)},{passive:!1})),l.style.overflow="hidden",n.value=!0)},o=()=>{const l=fs(et(e));!l||!n.value||(qr&&(s==null||s()),l.style.overflow=r,us.delete(l),n.value=!1)};return Zs(o),ie({get(){return n.value},set(l){l?i():o()}})}function Yf(e={}){const{window:t=qe,behavior:n="auto"}=e;if(!t)return{x:de(0),y:de(0)};const s=de(t.scrollX),r=de(t.scrollY),i=ie({get(){return s.value},set(l){scrollTo({left:l,behavior:n})}}),o=ie({get(){return r.value},set(l){scrollTo({top:l,behavior:n})}});return Ot(t,"scroll",()=>{s.value=t.scrollX,r.value=t.scrollY},{capture:!1,passive:!0}),{x:i,y:o}}function Xf(e={}){const{window:t=qe,initialWidth:n=Number.POSITIVE_INFINITY,initialHeight:s=Number.POSITIVE_INFINITY,listenOrientation:r=!0,includeScrollbar:i=!0,type:o="inner"}=e,l=de(n),c=de(s),u=()=>{t&&(o==="outer"?(l.value=t.outerWidth,c.value=t.outerHeight):i?(l.value=t.innerWidth,c.value=t.innerHeight):(l.value=t.document.documentElement.clientWidth,c.value=t.document.documentElement.clientHeight))};if(u(),er(u),Ot("resize",u,{passive:!0}),r){const f=Oo("(orientation: portrait)");ke(f,()=>u())}return{width:l,height:c}}const ds={BASE_URL:"/ran/",DEV:!1,MODE:"production",PROD:!0,SSR:!1};var hs={};const Lo=/^(?:[a-z]+:|\/\/)/i,Ja="vitepress-theme-appearance",za=/#.*$/,Qa=/[?#].*$/,Za=/(?:(^|\/)index)?\.(?:md|html)$/,ge=typeof document<"u",No={relativePath:"404.md",filePath:"",title:"404",description:"Not Found",headers:[],frontmatter:{sidebar:!1,layout:"page"},lastUpdated:0,isNotFound:!0};function ef(e,t,n=!1){if(t===void 0)return!1;if(e=Yr(`/${e}`),n)return new RegExp(t).test(e);if(Yr(t)!==e)return!1;const s=t.match(za);return s?(ge?location.hash:"")===s[0]:!0}function Yr(e){return decodeURI(e).replace(Qa,"").replace(Za,"$1")}function tf(e){return Lo.test(e)}function nf(e,t){return Object.keys((e==null?void 0:e.locales)||{}).find(n=>n!=="root"&&!tf(n)&&ef(t,`/${n}/`,!0))||"root"}function sf(e,t){var s,r,i,o,l,c,u;const n=nf(e,t);return Object.assign({},e,{localeIndex:n,lang:((s=e.locales[n])==null?void 0:s.lang)??e.lang,dir:((r=e.locales[n])==null?void 0:r.dir)??e.dir,title:((i=e.locales[n])==null?void 0:i.title)??e.title,titleTemplate:((o=e.locales[n])==null?void 0:o.titleTemplate)??e.titleTemplate,description:((l=e.locales[n])==null?void 0:l.description)??e.description,head:Ho(e.head,((c=e.locales[n])==null?void 0:c.head)??[]),themeConfig:{...e.themeConfig,...(u=e.locales[n])==null?void 0:u.themeConfig}})}function Fo(e,t){const n=t.title||e.title,s=t.titleTemplate??e.titleTemplate;if(typeof s=="string"&&s.includes(":title"))return s.replace(/:title/g,n);const r=rf(e.title,s);return n===r.slice(3)?n:`${n}${r}`}function rf(e,t){return t===!1?"":t===!0||t===void 0?` | ${e}`:e===t?"":` | ${t}`}function of(e,t){const[n,s]=t;if(n!=="meta")return!1;const r=Object.entries(s)[0];return r==null?!1:e.some(([i,o])=>i===n&&o[r[0]]===r[1])}function Ho(e,t){return[...e.filter(n=>!of(t,n)),...t]}const lf=/[\u0000-\u001F"#$&*+,:;<=>?[\]^`{|}\u007F]/g,cf=/^[a-z]:/i;function Xr(e){const t=cf.exec(e),n=t?t[0]:"";return n+e.slice(n.length).replace(lf,"_").replace(/(^|\/)_+(?=[^/]*$)/,"$1")}const ps=new Set;function af(e){if(ps.size===0){const n=typeof process=="object"&&(hs==null?void 0:hs.VITE_EXTRA_EXTENSIONS)||(ds==null?void 0:ds.VITE_EXTRA_EXTENSIONS)||"";("3g2,3gp,aac,ai,apng,au,avif,bin,bmp,cer,class,conf,crl,css,csv,dll,doc,eps,epub,exe,gif,gz,ics,ief,jar,jpe,jpeg,jpg,js,json,jsonld,m4a,man,mid,midi,mjs,mov,mp2,mp3,mp4,mpe,mpeg,mpg,mpp,oga,ogg,ogv,ogx,opus,otf,p10,p7c,p7m,p7s,pdf,png,ps,qt,roff,rtf,rtx,ser,svg,t,tif,tiff,tr,ts,tsv,ttf,txt,vtt,wav,weba,webm,webp,woff,woff2,xhtml,xml,yaml,yml,zip"+(n&&typeof n=="string"?","+n:"")).split(",").forEach(s=>ps.add(s))}const t=e.split(".").pop();return t==null||!ps.has(t.toLowerCase())}const ff=Symbol(),yt=xi(Oa);function Jf(e){const t=ie(()=>sf(yt.value,e.data.relativePath)),n=t.value.appearance,s=n==="force-dark"?de(!0):n?Ya({storageKey:Ja,initialValue:()=>n==="dark"?"dark":"auto",...typeof n=="object"?n:{}}):de(!1),r=de(ge?location.hash:"");return ge&&window.addEventListener("hashchange",()=>{r.value=location.hash}),ke(()=>e.data,()=>{r.value=ge?location.hash:""}),{site:t,theme:ie(()=>t.value.themeConfig),page:ie(()=>e.data),frontmatter:ie(()=>e.data.frontmatter),params:ie(()=>e.data.params),lang:ie(()=>t.value.lang),dir:ie(()=>e.data.frontmatter.dir||t.value.dir),localeIndex:ie(()=>t.value.localeIndex||"root"),title:ie(()=>Fo(t.value,e.data)),description:ie(()=>e.data.description||t.value.description),isDark:s,hash:ie(()=>r.value)}}function uf(){const e=Rt(ff);if(!e)throw new Error("vitepress data not properly injected in app");return e}function df(e,t){return`${e}${t}`.replace(/\/+/g,"/")}function Jr(e){return Lo.test(e)||!e.startsWith("/")?e:df(yt.value.base,e)}function hf(e){let t=e.replace(/\.html$/,"");if(t=decodeURIComponent(t),t=t.replace(/\/$/,"/index"),ge){const n="/ran/";t=Xr(t.slice(n.length).replace(/\//g,"_")||"index")+".md";let s=__VP_HASH_MAP__[t.toLowerCase()];if(s||(t=t.endsWith("_index.md")?t.slice(0,-9)+".md":t.slice(0,-3)+"_index.md",s=__VP_HASH_MAP__[t.toLowerCase()]),!s)return null;t=`${n}assets/${t}.${s}.js`}else t=`./${Xr(t.slice(1).replace(/\//g,"_"))}.md.js`;return t}let vn=[];function zf(e){vn.push(e),Un(()=>{vn=vn.filter(t=>t!==e)})}function pf(){let e=yt.value.scrollOffset,t=0,n=24;if(typeof e=="object"&&"padding"in e&&(n=e.padding,e=e.selector),typeof e=="number")t=e;else if(typeof e=="string")t=zr(e,n);else if(Array.isArray(e))for(const s of e){const r=zr(s,n);if(r){t=r;break}}return t}function zr(e,t){const n=document.querySelector(e);if(!n)return 0;const s=n.getBoundingClientRect().bottom;return s<0?0:s+t}const gf=Symbol(),Do="http://a.com",mf=()=>({path:"/",component:null,data:No});function Qf(e,t){const n=Hn(mf()),s={route:n,go:r};async function r(l=ge?location.href:"/"){var c,u;l=gs(l),await((c=s.onBeforeRouteChange)==null?void 0:c.call(s,l))!==!1&&(ge&&l!==gs(location.href)&&(history.replaceState({scrollPosition:window.scrollY},""),history.pushState({},"",l)),await o(l),await((u=s.onAfterRouteChanged)==null?void 0:u.call(s,l)))}let i=null;async function o(l,c=0,u=!1){var p;if(await((p=s.onBeforePageLoad)==null?void 0:p.call(s,l))===!1)return;const f=new URL(l,Do),h=i=f.pathname;try{let v=await e(h);if(!v)throw new Error(`Page not found: ${h}`);if(i===h){i=null;const{default:T,__pageData:I}=v;if(!T)throw new Error(`Invalid route component: ${T}`);n.path=ge?h:Jr(h),n.component=mn(T),n.data=mn(I),ge&&jn(()=>{let G=yt.value.base+I.relativePath.replace(/(?:(^|\/)index)?\.md$/,"$1");if(!yt.value.cleanUrls&&!G.endsWith("/")&&(G+=".html"),G!==f.pathname&&(f.pathname=G,l=G+f.search+f.hash,history.replaceState({},"",l)),f.hash&&!c){let V=null;try{V=document.getElementById(decodeURIComponent(f.hash).slice(1))}catch(K){console.warn(K)}if(V){Qr(V,f.hash);return}}window.scrollTo(0,c)})}}catch(v){if(!/fetch|Page not found/.test(v.message)&&!/^\/404(\.html|\/)?$/.test(l)&&console.error(v),!u)try{const T=await fetch(yt.value.base+"hashmap.json");window.__VP_HASH_MAP__=await T.json(),await o(l,c,!0);return}catch{}if(i===h){i=null,n.path=ge?h:Jr(h),n.component=t?mn(t):null;const T=ge?h.replace(/(^|\/)$/,"$1index").replace(/(\.html)?$/,".md").replace(/^\//,""):"404.md";n.data={...No,relativePath:T}}}}return ge&&(history.state===null&&history.replaceState({},""),window.addEventListener("click",l=>{if(l.defaultPrevented||!(l.target instanceof Element)||l.target.closest("button")||l.button!==0||l.ctrlKey||l.shiftKey||l.altKey||l.metaKey)return;const c=l.target.closest("a");if(!c||c.closest(".vp-raw")||c.hasAttribute("download")||c.hasAttribute("target"))return;const u=c.getAttribute("href")??(c instanceof SVGAElement?c.getAttribute("xlink:href"):null);if(u==null)return;const{href:f,origin:h,pathname:p,hash:v,search:T}=new URL(u,c.baseURI),I=new URL(location.href);h===I.origin&&af(p)&&(l.preventDefault(),p===I.pathname&&T===I.search?(v!==I.hash&&(history.pushState({},"",f),window.dispatchEvent(new HashChangeEvent("hashchange",{oldURL:I.href,newURL:f}))),v?Qr(c,v,c.classList.contains("header-anchor")):window.scrollTo(0,0)):r(f))},{capture:!0}),window.addEventListener("popstate",async l=>{var c;l.state!==null&&(await o(gs(location.href),l.state&&l.state.scrollPosition||0),(c=s.onAfterRouteChanged)==null||c.call(s,location.href))}),window.addEventListener("hashchange",l=>{l.preventDefault()})),s}function yf(){const e=Rt(gf);if(!e)throw new Error("useRouter() is called without provider.");return e}function $o(){return yf().route}function Qr(e,t,n=!1){let s=null;try{s=e.classList.contains("header-anchor")?e:document.getElementById(decodeURIComponent(t).slice(1))}catch(r){console.warn(r)}if(s){let r=function(){!n||Math.abs(o-window.scrollY)>window.innerHeight?window.scrollTo(0,o):window.scrollTo({left:0,top:o,behavior:"smooth"})};const i=parseInt(window.getComputedStyle(s).paddingTop,10),o=window.scrollY+s.getBoundingClientRect().top-pf()+i;requestAnimationFrame(r)}}function gs(e){const t=new URL(e,Do);return t.pathname=t.pathname.replace(/(^|\/)index(\.html)?$/,"$1"),yt.value.cleanUrls?t.pathname=t.pathname.replace(/\.html$/,""):!t.pathname.endsWith("/")&&!t.pathname.endsWith(".html")&&(t.pathname+=".html"),t.pathname+t.search+t.hash}const ms=()=>vn.forEach(e=>e()),Zf=ki({name:"VitePressContent",props:{as:{type:[Object,String],default:"div"}},setup(e){const t=$o(),{site:n}=uf();return()=>Ps(e.as,n.value.contentProps??{style:{position:"relative"}},[t.component?Ps(t.component,{onVnodeMounted:ms,onVnodeUpdated:ms,onVnodeUnmounted:ms}):"404 Page Not Found"])}}),eu=(e,t,n)=>{const s=e[t];return s?typeof s=="function"?s():Promise.resolve(s):new Promise((r,i)=>{(typeof queueMicrotask=="function"?queueMicrotask:setTimeout)(i.bind(null,new Error("Unknown variable dynamic import: "+t+(t.split("/").length!==n?". Note that variables only represent file names one level deep.":""))))})},tu=ki({setup(e,{slots:t}){const n=de(!1);return Mt(()=>{n.value=!0}),()=>n.value&&t.default?t.default():null}});function nu(){ge&&window.addEventListener("click",e=>{var n;const t=e.target;if(t.matches(".vp-code-group input")){const s=(n=t.parentElement)==null?void 0:n.parentElement;if(!s)return;const r=Array.from(s.querySelectorAll("input")).indexOf(t);if(r<0)return;const i=s.querySelector(".blocks");if(!i)return;const o=Array.from(i.children).find(u=>u.classList.contains("active"));if(!o)return;const l=i.children[r];if(!l||o===l)return;o.classList.remove("active"),l.classList.add("active");const c=s==null?void 0:s.querySelector(`label[for="${t.id}"]`);c==null||c.scrollIntoView({block:"nearest"})}})}function su(){if(ge){const e=new WeakMap;window.addEventListener("click",t=>{var s;const n=t.target;if(n.matches('div[class*="language-"] > button.copy')){const r=n.parentElement,i=(s=n.nextElementSibling)==null?void 0:s.nextElementSibling;if(!r||!i)return;const o=/language-(shellscript|shell|bash|sh|zsh)/.test(r.className),l=[".vp-copy-ignore",".diff.remove"],c=i.cloneNode(!0);c.querySelectorAll(l.join(",")).forEach(f=>f.remove());let u=c.textContent||"";o&&(u=u.replace(/^ *(\$|>) /gm,"").trim()),_f(u).then(()=>{n.classList.add("copied"),clearTimeout(e.get(n));const f=setTimeout(()=>{n.classList.remove("copied"),n.blur(),e.delete(n)},2e3);e.set(n,f)})}})}}async function _f(e){try{return navigator.clipboard.writeText(e)}catch{const t=document.createElement("textarea"),n=document.activeElement;t.value=e,t.setAttribute("readonly",""),t.style.contain="strict",t.style.position="absolute",t.style.left="-9999px",t.style.fontSize="12pt";const s=document.getSelection(),r=s?s.rangeCount>0&&s.getRangeAt(0):null;document.body.appendChild(t),t.select(),t.selectionStart=0,t.selectionEnd=e.length,document.execCommand("copy"),document.body.removeChild(t),r&&(s.removeAllRanges(),s.addRange(r)),n&&n.focus()}}function ru(e,t){let n=!0,s=[];const r=i=>{if(n){n=!1,i.forEach(l=>{const c=ys(l);for(const u of document.head.children)if(u.isEqualNode(c)){s.push(u);return}});return}const o=i.map(ys);s.forEach((l,c)=>{const u=o.findIndex(f=>f==null?void 0:f.isEqualNode(l??null));u!==-1?delete o[u]:(l==null||l.remove(),delete s[c])}),o.forEach(l=>l&&document.head.appendChild(l)),s=[...s,...o].filter(Boolean)};co(()=>{const i=e.data,o=t.value,l=i&&i.description,c=i&&i.frontmatter.head||[],u=Fo(o,i);u!==document.title&&(document.title=u);const f=l||o.description;let h=document.querySelector("meta[name=description]");h?h.getAttribute("content")!==f&&h.setAttribute("content",f):ys(["meta",{name:"description",content:f}]),r(Ho(o.head,vf(c)))})}function ys([e,t,n]){const s=document.createElement(e);for(const r in t)s.setAttribute(r,t[r]);return n&&(s.innerHTML=n),e==="script"&&!t.async&&(s.async=!1),s}function bf(e){return e[0]==="meta"&&e[1]&&e[1].name==="description"}function vf(e){return e.filter(t=>!bf(t))}const _s=new Set,jo=()=>document.createElement("link"),wf=e=>{const t=jo();t.rel="prefetch",t.href=e,document.head.appendChild(t)},Sf=e=>{const t=new XMLHttpRequest;t.open("GET",e,t.withCredentials=!0),t.send()};let pn;const Ef=ge&&(pn=jo())&&pn.relList&&pn.relList.supports&&pn.relList.supports("prefetch")?wf:Sf;function iu(){if(!ge||!window.IntersectionObserver)return;let e;if((e=navigator.connection)&&(e.saveData||/2g/.test(e.effectiveType)))return;const t=window.requestIdleCallback||setTimeout;let n=null;const s=()=>{n&&n.disconnect(),n=new IntersectionObserver(i=>{i.forEach(o=>{if(o.isIntersecting){const l=o.target;n.unobserve(l);const{pathname:c}=l;if(!_s.has(c)){_s.add(c);const u=hf(c);u&&Ef(u)}}})}),t(()=>{document.querySelectorAll("#app a").forEach(i=>{const{hostname:o,pathname:l}=new URL(i.href instanceof SVGAnimatedString?i.href.animVal:i.href,i.baseURI),c=l.match(/\.\w+$/);c&&c[0]!==".html"||i.target!=="_blank"&&o===location.hostname&&(l!==location.pathname?n.observe(i):_s.add(l))})})};Mt(s);const r=$o();ke(()=>r.path,s),Un(()=>{n&&n.disconnect()})}export{Tf as $,pf as A,Rf as B,Mf as C,xi as D,zf as E,Se as F,he as G,Lo as H,Of as I,$o as J,$c as K,Rt as L,Xf as M,Ds as N,qf as O,jn as P,Yf as Q,ge as R,Dn as S,jf as T,Hn as U,mc as V,Wi as W,Af as X,Cf as Y,Vf as Z,Wf as _,yo as a,Ps as a0,ai as a1,nl as a2,Df as a3,yf as a4,Pf as a5,Gf as a6,Lf as a7,Uf as a8,kf as a9,Nf as aa,xf as ab,ae as ac,Kn as ad,mt as ae,eu as af,Kf as ag,ru as ah,gf as ai,Jf as aj,ff as ak,Zf as al,tu as am,yt as an,Bf as ao,Qf as ap,hf as aq,iu as ar,su as as,nu as at,Os as b,Hf as c,ki as d,$f as e,af as f,Jr as g,ie as h,tf as i,mo as j,Ci as k,ef as l,Oo as m,$s as n,Rs as o,de as p,ke as q,If as r,co as s,tl as t,uf as u,Mt as v,Vl as w,Un as x,Ff as y,nc as z}; diff --git a/assets/chunks/heap.xduQWyUN.js b/assets/chunks/heap.xduQWyUN.js new file mode 100644 index 0000000000..02b2fd165d --- /dev/null +++ b/assets/chunks/heap.xduQWyUN.js @@ -0,0 +1 @@ +const s="/ran/assets/heap.D4myjC6C.gif";export{s as _}; diff --git a/assets/chunks/home-BUQ4USMk.BqTharGj.js b/assets/chunks/home-BUQ4USMk.BqTharGj.js new file mode 100644 index 0000000000..7a71eb8222 --- /dev/null +++ b/assets/chunks/home-BUQ4USMk.BqTharGj.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/index-Ba501-HG.DsTDD0-N.js b/assets/chunks/index-Ba501-HG.DsTDD0-N.js new file mode 100644 index 0000000000..754ef3f828 --- /dev/null +++ b/assets/chunks/index-Ba501-HG.DsTDD0-N.js @@ -0,0 +1,96 @@ +import{c as Dt,a as Oa}from"./commonjs-dynamic-modules-DLbDWi6a.CRNIONdy.js";import{t as hs}from"./index.CBA5mFK_.js";import{g as eg,a as tg}from"./colz-DJZvo_8B.DBiU5Tau.js";import"./framework.C-ai2y4t.js";var rg=Object.defineProperty,ig=(B,v,e)=>v in B?rg(B,v,{enumerable:!0,configurable:!0,writable:!0,value:e}):B[v]=e,Si=(B,v,e)=>ig(B,typeof v!="symbol"?v+"":v,e),Wa={exports:{}};/** + * @license + * Lodash + * Copyright OpenJS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */Wa.exports;(function(B,v){(function(){var e,d="4.17.21",m=200,l="Unsupported core-js use. Try https://npms.io/search?q=ponyfill.",c="Expected a function",h="Invalid `variable` option passed into `_.template`",s="__lodash_hash_undefined__",t=500,i="__lodash_placeholder__",r=1,n=2,o=4,f=1,a=2,g=1,b=2,u=4,w=8,y=16,S=32,E=64,I=128,P=256,F=512,j=30,W="...",G=800,V=16,J=1,$=2,M=3,T=1/0,x=9007199254740991,A=17976931348623157e292,N=NaN,L=4294967295,z=L-1,R=L>>>1,k=[["ary",I],["bind",g],["bindKey",b],["curry",w],["curryRight",y],["flip",F],["partial",S],["partialRight",E],["rearg",P]],C="[object Arguments]",O="[object Array]",X="[object AsyncFunction]",ie="[object Boolean]",he="[object Date]",ue="[object DOMException]",ke="[object Error]",pe="[object Function]",ee="[object GeneratorFunction]",Z="[object Map]",q="[object Number]",de="[object Null]",Me="[object Object]",ae="[object Promise]",ne="[object Proxy]",Q="[object RegExp]",H="[object Set]",Y="[object String]",le="[object Symbol]",we="[object Undefined]",U="[object WeakMap]",ge="[object WeakSet]",Se="[object ArrayBuffer]",te="[object DataView]",se="[object Float32Array]",ve="[object Float64Array]",Ee="[object Int8Array]",Ie="[object Int16Array]",Te="[object Int32Array]",Pe="[object Uint8Array]",He="[object Uint8ClampedArray]",me="[object Uint16Array]",Ce="[object Uint32Array]",Le=/\b__p \+= '';/g,ze=/\b(__p \+=) '' \+/g,Ye=/(__e\(.*?\)|\b__t\)) \+\n'';/g,ot=/&(?:amp|lt|gt|quot|#39);/g,pt=/[&<>"']/g,it=RegExp(ot.source),rt=RegExp(pt.source),Tt=/<%-([\s\S]+?)%>/g,Qe=/<%([\s\S]+?)%>/g,et=/<%=([\s\S]+?)%>/g,At=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,lt=/^\w*$/,jt=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Ot=/[\\^$.*+?()[\]{}|]/g,ct=RegExp(Ot.source),Bt=/^\s+/,Ut=/\s/,yt=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,er=/\{\n\/\* \[wrapped with (.+)\] \*/,Kt=/,? & /,dt=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Gt=/[()=,{}\[\]\/\s]/,Mt=/\\(\\)?/g,wt=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,$t=/\w*$/,Qt=/^[-+]0x[0-9a-f]+$/i,mt=/^0b[01]+$/i,qt=/^\[object .+?Constructor\]$/,_t=/^0o[0-7]+$/i,Ct=/^(?:0|[1-9]\d*)$/,be=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,De=/($^)/,Fe=/['\n\r\u2028\u2029\\]/g,Je="\\ud800-\\udfff",at="\\u0300-\\u036f",Rt="\\ufe20-\\ufe2f",rr="\\u20d0-\\u20ff",vr=at+Rt+rr,Br="\\u2700-\\u27bf",br="a-z\\xdf-\\xf6\\xf8-\\xff",lr="\\xac\\xb1\\xd7\\xf7",ri="\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf",ii="\\u2000-\\u206f",ar=" \\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",Xr="A-Z\\xc0-\\xd6\\xd8-\\xde",Wr="\\ufe0e\\ufe0f",Vr=lr+ri+ii+ar,Ei="['’]",Vi="["+Je+"]",jn="["+Vr+"]",Kr="["+vr+"]",$n="\\d+",Ki="["+Br+"]",Sn="["+br+"]",En="[^"+Je+Vr+$n+Br+br+Xr+"]",fn="\\ud83c[\\udffb-\\udfff]",bs="(?:"+Kr+"|"+fn+")",zn="[^"+Je+"]",Gi="(?:\\ud83c[\\udde6-\\uddff]){2}",cn="[\\ud800-\\udbff][\\udc00-\\udfff]",Fi="["+Xr+"]",Hn="\\u200d",Cn="(?:"+Sn+"|"+En+")",hn="(?:"+Fi+"|"+En+")",Ci="(?:"+Ei+"(?:d|ll|m|re|s|t|ve))?",Un="(?:"+Ei+"(?:D|LL|M|RE|S|T|VE))?",Xn=bs+"?",ni="["+Wr+"]?",ys="(?:"+Hn+"(?:"+[zn,Gi,cn].join("|")+")"+ni+Xn+")*",Wn="\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",ws="\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])",Vn=ni+Xn+ys,_s="(?:"+[Ki,Gi,cn].join("|")+")"+Vn,pi="(?:"+[zn+Kr+"?",Kr,Gi,cn,Vi].join("|")+")",Kn=RegExp(Ei,"g"),xs=RegExp(Kr,"g"),si=RegExp(fn+"(?="+fn+")|"+pi+Vn,"g"),Ss=RegExp([Fi+"?"+Sn+"+"+Ci+"(?="+[jn,Fi,"$"].join("|")+")",hn+"+"+Un+"(?="+[jn,Fi+Cn,"$"].join("|")+")",Fi+"?"+Cn+"+"+Ci,Fi+"+"+Un,ws,Wn,$n,_s].join("|"),"g"),mi=RegExp("["+Hn+Je+vr+Wr+"]"),gi=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Gn=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Tn=-1,Zt={};Zt[se]=Zt[ve]=Zt[Ee]=Zt[Ie]=Zt[Te]=Zt[Pe]=Zt[He]=Zt[me]=Zt[Ce]=!0,Zt[C]=Zt[O]=Zt[Se]=Zt[ie]=Zt[te]=Zt[he]=Zt[ke]=Zt[pe]=Zt[Z]=Zt[q]=Zt[Me]=Zt[Q]=Zt[H]=Zt[Y]=Zt[U]=!1;var Yt={};Yt[C]=Yt[O]=Yt[Se]=Yt[te]=Yt[ie]=Yt[he]=Yt[se]=Yt[ve]=Yt[Ee]=Yt[Ie]=Yt[Te]=Yt[Z]=Yt[q]=Yt[Me]=Yt[Q]=Yt[H]=Yt[Y]=Yt[le]=Yt[Pe]=Yt[He]=Yt[me]=Yt[Ce]=!0,Yt[ke]=Yt[pe]=Yt[U]=!1;var Yn={À:"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",Ā:"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"},Es={"&":"&","<":"<",">":">",'"':""","'":"'"},Zn={"&":"&","<":"<",">":">",""":'"',"'":"'"},Jn={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},ye=parseFloat,Re=parseInt,Xe=typeof Dt=="object"&&Dt&&Dt.Object===Object&&Dt,tt=typeof self=="object"&&self&&self.Object===Object&&self,Et=Xe||tt||Function("return this")(),xt=v&&!v.nodeType&&v,Jt=xt&&!0&&B&&!B.nodeType&&B,ir=Jt&&Jt.exports===xt,fr=ir&&Xe.process,zt=function(){try{var Oe=Jt&&Jt.require&&Jt.require("util").types;return Oe||fr&&fr.binding&&fr.binding("util")}catch{}}(),Cr=zt&&zt.isArrayBuffer,Rr=zt&&zt.isDate,hr=zt&&zt.isMap,Sr=zt&&zt.isRegExp,Tr=zt&&zt.isSet,ai=zt&&zt.isTypedArray;function cr(Oe,Ue,$e){switch($e.length){case 0:return Oe.call(Ue);case 1:return Oe.call(Ue,$e[0]);case 2:return Oe.call(Ue,$e[0],$e[1]);case 3:return Oe.call(Ue,$e[0],$e[1],$e[2])}return Oe.apply(Ue,$e)}function Ti(Oe,Ue,$e,st){for(var kt=-1,tr=Oe==null?0:Oe.length;++kt-1}function xe(Oe,Ue,$e){for(var st=-1,kt=Oe==null?0:Oe.length;++st-1;);return $e}function Ol(Oe,Ue){for(var $e=Oe.length;$e--&&mr(Ue,Oe[$e],0)>-1;);return $e}function Oh(Oe,Ue){for(var $e=Oe.length,st=0;$e--;)Oe[$e]===Ue&&++st;return st}var Ph=Mi(Yn),Nh=Mi(Es);function Dh(Oe){return"\\"+Jn[Oe]}function Bh(Oe,Ue){return Oe==null?e:Oe[Ue]}function qn(Oe){return mi.test(Oe)}function Fh(Oe){return gi.test(Oe)}function Lh(Oe){for(var Ue,$e=[];!(Ue=Oe.next()).done;)$e.push(Ue.value);return $e}function no(Oe){var Ue=-1,$e=Array(Oe.size);return Oe.forEach(function(st,kt){$e[++Ue]=[kt,st]}),$e}function Pl(Oe,Ue){return function($e){return Oe(Ue($e))}}function dn(Oe,Ue){for(var $e=-1,st=Oe.length,kt=0,tr=[];++$e-1}function Cu(p,_){var D=this.__data__,K=ca(D,p);return K<0?(++this.size,D.push([p,_])):D[K][1]=_,this}Zi.prototype.clear=_u,Zi.prototype.delete=xu,Zi.prototype.get=Su,Zi.prototype.has=Eu,Zi.prototype.set=Cu;function Ji(p){var _=-1,D=p==null?0:p.length;for(this.clear();++_=_?p:_)),p}function yi(p,_,D,K,re,ce){var _e,Ae=_&r,Ne=_&n,We=_&o;if(D&&(_e=re?D(p,K,re,ce):D(p)),_e!==e)return _e;if(!pr(p))return p;var Ve=It(p);if(Ve){if(_e=Md(p),!Ae)return Yr(p,_e)}else{var Ke=Lr(p),qe=Ke==pe||Ke==ee;if(yn(p))return gf(p,Ae);if(Ke==Me||Ke==C||qe&&!re){if(_e=Ne||qe?{}:Df(p),!Ae)return Ne?bd(p,zu(_e,p)):vd(p,Wl(_e,p))}else{if(!Yt[Ke])return re?p:{};_e=Rd(p,Ke,Ae)}}ce||(ce=new Ii);var ft=ce.get(p);if(ft)return ft;ce.set(p,_e),cc(p)?p.forEach(function(bt){_e.add(yi(bt,_,D,bt,p,ce))}):lc(p)&&p.forEach(function(bt,Ht){_e.set(Ht,yi(bt,_,D,Ht,p,ce))});var vt=We?Ne?Io:Ro:Ne?Jr:Or,Ft=Ve?e:vt(p);return Pr(Ft||p,function(bt,Ht){Ft&&(Ht=bt,bt=p[Ht]),Os(_e,Ht,yi(bt,_,D,Ht,p,ce))}),_e}function Hu(p){var _=Or(p);return function(D){return Vl(D,p,_)}}function Vl(p,_,D){var K=D.length;if(p==null)return!K;for(p=or(p);K--;){var re=D[K],ce=_[re],_e=p[re];if(_e===e&&!(re in p)||!ce(_e))return!1}return!0}function Kl(p,_,D){if(typeof p!="function")throw new vi(c);return js(function(){p.apply(e,D)},_)}function Ps(p,_,D,K){var re=-1,ce=oe,_e=!0,Ae=p.length,Ne=[],We=_.length;if(!Ae)return Ne;D&&(_=Be(_,li(D))),K?(ce=xe,_e=!1):_.length>=m&&(ce=Ts,_e=!1,_=new Mn(_));e:for(;++rere?0:re+D),K=K===e||K>re?re:Nt(K),K<0&&(K+=re),K=D>K?0:uc(K);D0&&D(Ae)?_>1?Dr(Ae,_-1,D,K,re):Ge(re,Ae):K||(re[re.length]=Ae)}return re}var ho=xf(),Zl=xf(!0);function ji(p,_){return p&&ho(p,_,Or)}function uo(p,_){return p&&Zl(p,_,Or)}function ua(p,_){return Li(_,function(D){return rn(p[D])})}function In(p,_){_=vn(_,p);for(var D=0,K=_.length;p!=null&&D_}function Wu(p,_){return p!=null&&sr.call(p,_)}function Vu(p,_){return p!=null&&_ in or(p)}function Ku(p,_,D){return p>=Fr(_,D)&&p=120&&Ve.length>=120)?new Mn(_e&&Ve):e}Ve=p[0];var Ke=-1,qe=Ae[0];e:for(;++Ke-1;)Ae!==p&&ia.call(Ae,Ne,1),ia.call(p,Ne,1);return p}function lf(p,_){for(var D=p?_.length:0,K=D-1;D--;){var re=_[D];if(D==K||re!==ce){var ce=re;tn(re)?ia.call(p,re,1):So(p,re)}}return p}function wo(p,_){return p+aa(zl()*(_-p+1))}function ad(p,_,D,K){for(var re=-1,ce=Mr(sa((_-p)/(D||1)),0),_e=$e(ce);ce--;)_e[K?ce:++re]=p,p+=D;return _e}function _o(p,_){var D="";if(!p||_<1||_>x)return D;do _%2&&(D+=p),_=aa(_/2),_&&(p+=p);while(_);return D}function Lt(p,_){return Lo(Lf(p,_,Qr),p+"")}function od(p){return Xl(cs(p))}function ld(p,_){var D=cs(p);return Sa(D,Rn(_,0,D.length))}function Bs(p,_,D,K){if(!pr(p))return p;_=vn(_,p);for(var re=-1,ce=_.length,_e=ce-1,Ae=p;Ae!=null&&++rere?0:re+_),D=D>re?re:D,D<0&&(D+=re),re=_>D?0:D-_>>>0,_>>>=0;for(var ce=$e(re);++K>>1,_e=p[ce];_e!==null&&!ci(_e)&&(D?_e<=_:_e<_)?K=ce+1:re=ce}return re}return xo(p,_,Qr,D)}function xo(p,_,D,K){var re=0,ce=p==null?0:p.length;if(ce===0)return 0;_=D(_);for(var _e=_!==_,Ae=_===null,Ne=ci(_),We=_===e;re=m){var We=_?null:xd(p);if(We)return Ys(We);_e=!1,re=Ts,Ne=new Mn}else Ne=_?[]:Ae;e:for(;++K=K?p:wi(p,_,D)}var mf=qh||function(p){return Et.clearTimeout(p)};function gf(p,_){if(_)return p.slice();var D=p.length,K=Bl?Bl(D):new p.constructor(D);return p.copy(K),K}function Ao(p){var _=new p.constructor(p.byteLength);return new ta(_).set(new ta(p)),_}function dd(p,_){var D=_?Ao(p.buffer):p.buffer;return new p.constructor(D,p.byteOffset,p.byteLength)}function pd(p){var _=new p.constructor(p.source,$t.exec(p));return _.lastIndex=p.lastIndex,_}function md(p){return Is?or(Is.call(p)):{}}function vf(p,_){var D=_?Ao(p.buffer):p.buffer;return new p.constructor(D,p.byteOffset,p.length)}function bf(p,_){if(p!==_){var D=p!==e,K=p===null,re=p===p,ce=ci(p),_e=_!==e,Ae=_===null,Ne=_===_,We=ci(_);if(!Ae&&!We&&!ce&&p>_||ce&&_e&&Ne&&!Ae&&!We||K&&_e&&Ne||!D&&Ne||!re)return 1;if(!K&&!ce&&!We&&p<_||We&&D&&re&&!K&&!ce||Ae&&D&&re||!_e&&re||!Ne)return-1}return 0}function gd(p,_,D){for(var K=-1,re=p.criteria,ce=_.criteria,_e=re.length,Ae=D.length;++K<_e;){var Ne=bf(re[K],ce[K]);if(Ne){if(K>=Ae)return Ne;var We=D[K];return Ne*(We=="desc"?-1:1)}}return p.index-_.index}function yf(p,_,D,K){for(var re=-1,ce=p.length,_e=D.length,Ae=-1,Ne=_.length,We=Mr(ce-_e,0),Ve=$e(Ne+We),Ke=!K;++Ae1?D[re-1]:e,_e=re>2?D[2]:e;for(ce=p.length>3&&typeof ce=="function"?(re--,ce):e,_e&&Hr(D[0],D[1],_e)&&(ce=re<3?e:ce,re=1),_=or(_);++K-1?re[ce?_[_e]:_e]:e}}function Cf(p){return en(function(_){var D=_.length,K=D,re=bi.prototype.thru;for(p&&_.reverse();K--;){var ce=_[K];if(typeof ce!="function")throw new vi(c);if(re&&!_e&&_a(ce)=="wrapper")var _e=new bi([],!0)}for(K=_e?K:D;++K1&&Vt.reverse(),Ve&&NeAe))return!1;var We=ce.get(p),Ve=ce.get(_);if(We&&Ve)return We==_&&Ve==p;var Ke=-1,qe=!0,ft=D&a?new Mn:e;for(ce.set(p,_),ce.set(_,p);++Ke1?"& ":"")+_[K],_=_.join(D>2?", ":" "),p.replace(yt,`{ +/* [wrapped with `+_+`] */ +`)}function Od(p){return It(p)||Nn(p)||!!(jl&&p&&p[jl])}function tn(p,_){var D=typeof p;return _=_??x,!!_&&(D=="number"||D!="symbol"&&Ct.test(p))&&p>-1&&p%1==0&&p<_}function Hr(p,_,D){if(!pr(D))return!1;var K=typeof _;return(K=="number"?Zr(D)&&tn(_,D.length):K=="string"&&_ in D)?Oi(D[_],p):!1}function Do(p,_){if(It(p))return!1;var D=typeof p;return D=="number"||D=="symbol"||D=="boolean"||p==null||ci(p)?!0:lt.test(p)||!At.test(p)||_!=null&&p in or(_)}function Pd(p){var _=typeof p;return _=="string"||_=="number"||_=="symbol"||_=="boolean"?p!=="__proto__":p===null}function Bo(p){var _=_a(p),D=fe[_];if(typeof D!="function"||!(_ in Xt.prototype))return!1;if(p===D)return!0;var K=Oo(D);return!!K&&p===K[0]}function Nd(p){return!!Dl&&Dl in p}var Dd=Js?rn:qo;function Ls(p){var _=p&&p.constructor,D=typeof _=="function"&&_.prototype||rs;return p===D}function Bf(p){return p===p&&!pr(p)}function Ff(p,_){return function(D){return D==null?!1:D[p]===_&&(_!==e||p in or(D))}}function Bd(p){var _=Aa(p,function(K){return D.size===t&&D.clear(),K}),D=_.cache;return _}function Fd(p,_){var D=p[1],K=_[1],re=D|K,ce=re<(g|b|I),_e=K==I&&D==w||K==I&&D==P&&p[7].length<=_[8]||K==(I|P)&&_[7].length<=_[8]&&D==w;if(!(ce||_e))return p;K&g&&(p[2]=_[2],re|=D&g?0:u);var Ae=_[3];if(Ae){var Ne=p[3];p[3]=Ne?yf(Ne,Ae,_[4]):Ae,p[4]=Ne?dn(p[3],i):_[4]}return Ae=_[5],Ae&&(Ne=p[5],p[5]=Ne?wf(Ne,Ae,_[6]):Ae,p[6]=Ne?dn(p[5],i):_[6]),Ae=_[7],Ae&&(p[7]=Ae),K&I&&(p[8]=p[8]==null?_[8]:Fr(p[8],_[8])),p[9]==null&&(p[9]=_[9]),p[0]=_[0],p[1]=re,p}function Ld(p){var _=[];if(p!=null)for(var D in or(p))_.push(D);return _}function jd(p){return qs.call(p)}function Lf(p,_,D){return _=Mr(_===e?p.length-1:_,0),function(){for(var K=arguments,re=-1,ce=Mr(K.length-_,0),_e=$e(ce);++re0){if(++_>=G)return arguments[0]}else _=0;return p.apply(e,arguments)}}function Sa(p,_){var D=-1,K=p.length,re=K-1;for(_=_===e?K:_;++D<_;){var ce=wo(D,re),_e=p[ce];p[ce]=p[D],p[D]=_e}return p.length=_,p}var Uf=Bd(function(p){var _=[];return p.charCodeAt(0)===46&&_.push(""),p.replace(jt,function(D,K,re,ce){_.push(re?ce.replace(Mt,"$1"):K||D)}),_});function zi(p){if(typeof p=="string"||ci(p))return p;var _=p+"";return _=="0"&&1/p==-T?"-0":_}function Pn(p){if(p!=null){try{return Qs.call(p)}catch{}try{return p+""}catch{}}return""}function zd(p,_){return Pr(k,function(D){var K="_."+D[0];_&D[1]&&!oe(p,K)&&p.push(K)}),p.sort()}function Xf(p){if(p instanceof Xt)return p.clone();var _=new bi(p.__wrapped__,p.__chain__);return _.__actions__=Yr(p.__actions__),_.__index__=p.__index__,_.__values__=p.__values__,_}function Hd(p,_,D){(D?Hr(p,_,D):_===e)?_=1:_=Mr(Nt(_),0);var K=p==null?0:p.length;if(!K||_<1)return[];for(var re=0,ce=0,_e=$e(sa(K/_));re1?p[_-1]:e;return D=typeof D=="function"?(p.pop(),D):e,Zf(p,D)});function Jf(p){var _=fe(p);return _.__chain__=!0,_}function Up(p,_){return _(p),p}function Ea(p,_){return _(p)}var Xp=en(function(p){var _=p.length,D=_?p[0]:0,K=this.__wrapped__,re=function(ce){return co(ce,p)};return _>1||this.__actions__.length||!(K instanceof Xt)||!tn(D)?this.thru(re):(K=K.slice(D,+D+(_?1:0)),K.__actions__.push({func:Ea,args:[re],thisArg:e}),new bi(K,this.__chain__).thru(function(ce){return _&&!ce.length&&ce.push(e),ce}))});function Wp(){return Jf(this)}function Vp(){return new bi(this.value(),this.__chain__)}function Kp(){this.__values__===e&&(this.__values__=hc(this.value()));var p=this.__index__>=this.__values__.length,_=p?e:this.__values__[this.__index__++];return{done:p,value:_}}function Gp(){return this}function Yp(p){for(var _,D=this;D instanceof fa;){var K=Xf(D);K.__index__=0,K.__values__=e,_?re.__wrapped__=K:_=K;var re=K;D=D.__wrapped__}return re.__wrapped__=p,_}function Zp(){var p=this.__wrapped__;if(p instanceof Xt){var _=p;return this.__actions__.length&&(_=new Xt(this)),_=_.reverse(),_.__actions__.push({func:Ea,args:[jo],thisArg:e}),new bi(_,this.__chain__)}return this.thru(jo)}function Jp(){return df(this.__wrapped__,this.__actions__)}var Qp=ga(function(p,_,D){sr.call(p,D)?++p[D]:Qi(p,D,1)});function qp(p,_,D){var K=It(p)?Yi:Uu;return D&&Hr(p,_,D)&&(_=e),K(p,gt(_,3))}function e0(p,_){var D=It(p)?Li:Yl;return D(p,gt(_,3))}var t0=Ef(Wf),r0=Ef(Vf);function i0(p,_){return Dr(Ca(p,_),1)}function n0(p,_){return Dr(Ca(p,_),T)}function s0(p,_,D){return D=D===e?1:Nt(D),Dr(Ca(p,_),D)}function Qf(p,_){var D=It(p)?Pr:mn;return D(p,gt(_,3))}function qf(p,_){var D=It(p)?Ai:Gl;return D(p,gt(_,3))}var a0=ga(function(p,_,D){sr.call(p,D)?p[D].push(_):Qi(p,D,[_])});function o0(p,_,D,K){p=Zr(p)?p:cs(p),D=D&&!K?Nt(D):0;var re=p.length;return D<0&&(D=Mr(re+D,0)),Ra(p)?D<=re&&p.indexOf(_,D)>-1:!!re&&mr(p,_,D)>-1}var l0=Lt(function(p,_,D){var K=-1,re=typeof _=="function",ce=Zr(p)?$e(p.length):[];return mn(p,function(_e){ce[++K]=re?cr(_,_e,D):Ns(_e,_,D)}),ce}),f0=ga(function(p,_,D){Qi(p,D,_)});function Ca(p,_){var D=It(p)?Be:tf;return D(p,gt(_,3))}function c0(p,_,D,K){return p==null?[]:(It(_)||(_=_==null?[]:[_]),D=K?e:D,It(D)||(D=D==null?[]:[D]),af(p,_,D))}var h0=ga(function(p,_,D){p[D?0:1].push(_)},function(){return[[],[]]});function u0(p,_,D){var K=It(p)?ut:Cs,re=arguments.length<3;return K(p,gt(_,4),D,re,mn)}function d0(p,_,D){var K=It(p)?nt:Cs,re=arguments.length<3;return K(p,gt(_,4),D,re,Gl)}function p0(p,_){var D=It(p)?Li:Yl;return D(p,ka(gt(_,3)))}function m0(p){var _=It(p)?Xl:od;return _(p)}function g0(p,_,D){(D?Hr(p,_,D):_===e)?_=1:_=Nt(_);var K=It(p)?Lu:ld;return K(p,_)}function v0(p){var _=It(p)?ju:cd;return _(p)}function b0(p){if(p==null)return 0;if(Zr(p))return Ra(p)?es(p):p.length;var _=Lr(p);return _==Z||_==H?p.size:vo(p).length}function y0(p,_,D){var K=It(p)?St:hd;return D&&Hr(p,_,D)&&(_=e),K(p,gt(_,3))}var w0=Lt(function(p,_){if(p==null)return[];var D=_.length;return D>1&&Hr(p,_[0],_[1])?_=[]:D>2&&Hr(_[0],_[1],_[2])&&(_=[_[0]]),af(p,Dr(_,1),[])}),Ta=eu||function(){return Et.Date.now()};function _0(p,_){if(typeof _!="function")throw new vi(c);return p=Nt(p),function(){if(--p<1)return _.apply(this,arguments)}}function ec(p,_,D){return _=D?e:_,_=p&&_==null?p.length:_,qi(p,I,e,e,e,e,_)}function tc(p,_){var D;if(typeof _!="function")throw new vi(c);return p=Nt(p),function(){return--p>0&&(D=_.apply(this,arguments)),p<=1&&(_=e),D}}var zo=Lt(function(p,_,D){var K=g;if(D.length){var re=dn(D,ls(zo));K|=S}return qi(p,K,_,D,re)}),rc=Lt(function(p,_,D){var K=g|b;if(D.length){var re=dn(D,ls(rc));K|=S}return qi(_,K,p,D,re)});function ic(p,_,D){_=D?e:_;var K=qi(p,w,e,e,e,e,e,_);return K.placeholder=ic.placeholder,K}function nc(p,_,D){_=D?e:_;var K=qi(p,y,e,e,e,e,e,_);return K.placeholder=nc.placeholder,K}function sc(p,_,D){var K,re,ce,_e,Ae,Ne,We=0,Ve=!1,Ke=!1,qe=!0;if(typeof p!="function")throw new vi(c);_=xi(_)||0,pr(D)&&(Ve=!!D.leading,Ke="maxWait"in D,ce=Ke?Mr(xi(D.maxWait)||0,_):ce,qe="trailing"in D?!!D.trailing:qe);function ft(_r){var Pi=K,sn=re;return K=re=e,We=_r,_e=p.apply(sn,Pi),_e}function vt(_r){return We=_r,Ae=js(Ht,_),Ve?ft(_r):_e}function Ft(_r){var Pi=_r-Ne,sn=_r-We,Ec=_-Pi;return Ke?Fr(Ec,ce-sn):Ec}function bt(_r){var Pi=_r-Ne,sn=_r-We;return Ne===e||Pi>=_||Pi<0||Ke&&sn>=ce}function Ht(){var _r=Ta();if(bt(_r))return Vt(_r);Ae=js(Ht,Ft(_r))}function Vt(_r){return Ae=e,qe&&K?ft(_r):(K=re=e,_e)}function hi(){Ae!==e&&mf(Ae),We=0,K=Ne=re=Ae=e}function Ur(){return Ae===e?_e:Vt(Ta())}function ui(){var _r=Ta(),Pi=bt(_r);if(K=arguments,re=this,Ne=_r,Pi){if(Ae===e)return vt(Ne);if(Ke)return mf(Ae),Ae=js(Ht,_),ft(Ne)}return Ae===e&&(Ae=js(Ht,_)),_e}return ui.cancel=hi,ui.flush=Ur,ui}var x0=Lt(function(p,_){return Kl(p,1,_)}),S0=Lt(function(p,_,D){return Kl(p,xi(_)||0,D)});function E0(p){return qi(p,F)}function Aa(p,_){if(typeof p!="function"||_!=null&&typeof _!="function")throw new vi(c);var D=function(){var K=arguments,re=_?_.apply(this,K):K[0],ce=D.cache;if(ce.has(re))return ce.get(re);var _e=p.apply(this,K);return D.cache=ce.set(re,_e)||ce,_e};return D.cache=new(Aa.Cache||Ji),D}Aa.Cache=Ji;function ka(p){if(typeof p!="function")throw new vi(c);return function(){var _=arguments;switch(_.length){case 0:return!p.call(this);case 1:return!p.call(this,_[0]);case 2:return!p.call(this,_[0],_[1]);case 3:return!p.call(this,_[0],_[1],_[2])}return!p.apply(this,_)}}function C0(p){return tc(2,p)}var T0=ud(function(p,_){_=_.length==1&&It(_[0])?Be(_[0],li(gt())):Be(Dr(_,1),li(gt()));var D=_.length;return Lt(function(K){for(var re=-1,ce=Fr(K.length,D);++re=_}),Nn=Ql(function(){return arguments}())?Ql:function(p){return gr(p)&&sr.call(p,"callee")&&!Ll.call(p,"callee")},It=$e.isArray,z0=Cr?li(Cr):Yu;function Zr(p){return p!=null&&Ma(p.length)&&!rn(p)}function wr(p){return gr(p)&&Zr(p)}function H0(p){return p===!0||p===!1||gr(p)&&zr(p)==ie}var yn=ru||qo,U0=Rr?li(Rr):Zu;function X0(p){return gr(p)&&p.nodeType===1&&!$s(p)}function W0(p){if(p==null)return!0;if(Zr(p)&&(It(p)||typeof p=="string"||typeof p.splice=="function"||yn(p)||fs(p)||Nn(p)))return!p.length;var _=Lr(p);if(_==Z||_==H)return!p.size;if(Ls(p))return!vo(p).length;for(var D in p)if(sr.call(p,D))return!1;return!0}function V0(p,_){return Ds(p,_)}function K0(p,_,D){D=typeof D=="function"?D:e;var K=D?D(p,_):e;return K===e?Ds(p,_,e,D):!!K}function Uo(p){if(!gr(p))return!1;var _=zr(p);return _==ke||_==ue||typeof p.message=="string"&&typeof p.name=="string"&&!$s(p)}function G0(p){return typeof p=="number"&&$l(p)}function rn(p){if(!pr(p))return!1;var _=zr(p);return _==pe||_==ee||_==X||_==ne}function oc(p){return typeof p=="number"&&p==Nt(p)}function Ma(p){return typeof p=="number"&&p>-1&&p%1==0&&p<=x}function pr(p){var _=typeof p;return p!=null&&(_=="object"||_=="function")}function gr(p){return p!=null&&typeof p=="object"}var lc=hr?li(hr):Qu;function Y0(p,_){return p===_||go(p,_,Po(_))}function Z0(p,_,D){return D=typeof D=="function"?D:e,go(p,_,Po(_),D)}function J0(p){return fc(p)&&p!=+p}function Q0(p){if(Dd(p))throw new kt(l);return ql(p)}function q0(p){return p===null}function em(p){return p==null}function fc(p){return typeof p=="number"||gr(p)&&zr(p)==q}function $s(p){if(!gr(p)||zr(p)!=Me)return!1;var _=ra(p);if(_===null)return!0;var D=sr.call(_,"constructor")&&_.constructor;return typeof D=="function"&&D instanceof D&&Qs.call(D)==Zh}var Xo=Sr?li(Sr):qu;function tm(p){return oc(p)&&p>=-x&&p<=x}var cc=Tr?li(Tr):ed;function Ra(p){return typeof p=="string"||!It(p)&&gr(p)&&zr(p)==Y}function ci(p){return typeof p=="symbol"||gr(p)&&zr(p)==le}var fs=ai?li(ai):td;function rm(p){return p===e}function im(p){return gr(p)&&Lr(p)==U}function nm(p){return gr(p)&&zr(p)==ge}var sm=wa(bo),am=wa(function(p,_){return p<=_});function hc(p){if(!p)return[];if(Zr(p))return Ra(p)?Ri(p):Yr(p);if(As&&p[As])return Lh(p[As]());var _=Lr(p),D=_==Z?no:_==H?Ys:cs;return D(p)}function nn(p){if(!p)return p===0?p:0;if(p=xi(p),p===T||p===-T){var _=p<0?-1:1;return _*A}return p===p?p:0}function Nt(p){var _=nn(p),D=_%1;return _===_?D?_-D:_:0}function uc(p){return p?Rn(Nt(p),0,L):0}function xi(p){if(typeof p=="number")return p;if(ci(p))return N;if(pr(p)){var _=typeof p.valueOf=="function"?p.valueOf():p;p=pr(_)?_+"":_}if(typeof p!="string")return p===0?p:+p;p=Rl(p);var D=mt.test(p);return D||_t.test(p)?Re(p.slice(2),D?2:8):Qt.test(p)?N:+p}function dc(p){return $i(p,Jr(p))}function om(p){return p?Rn(Nt(p),-x,x):p===0?p:0}function nr(p){return p==null?"":fi(p)}var lm=as(function(p,_){if(Ls(_)||Zr(_)){$i(_,Or(_),p);return}for(var D in _)sr.call(_,D)&&Os(p,D,_[D])}),pc=as(function(p,_){$i(_,Jr(_),p)}),Ia=as(function(p,_,D,K){$i(_,Jr(_),p,K)}),fm=as(function(p,_,D,K){$i(_,Or(_),p,K)}),cm=en(co);function hm(p,_){var D=ss(p);return _==null?D:Wl(D,_)}var um=Lt(function(p,_){p=or(p);var D=-1,K=_.length,re=K>2?_[2]:e;for(re&&Hr(_[0],_[1],re)&&(K=1);++D1),ce}),$i(p,Io(p),D),K&&(D=yi(D,r|n|o,Sd));for(var re=_.length;re--;)So(D,_[re]);return D});function Rm(p,_){return gc(p,ka(gt(_)))}var Im=en(function(p,_){return p==null?{}:nd(p,_)});function gc(p,_){if(p==null)return{};var D=Be(Io(p),function(K){return[K]});return _=gt(_),of(p,D,function(K,re){return _(K,re[0])})}function Om(p,_,D){_=vn(_,p);var K=-1,re=_.length;for(re||(re=1,p=e);++K_){var K=p;p=_,_=K}if(D||p%1||_%1){var re=zl();return Fr(p+re*(_-p+ye("1e-"+((re+"").length-1))),_)}return wo(p,_)}var Um=os(function(p,_,D){return _=_.toLowerCase(),p+(D?yc(_):_)});function yc(p){return Ko(nr(p).toLowerCase())}function wc(p){return p=nr(p),p&&p.replace(be,Ph).replace(xs,"")}function Xm(p,_,D){p=nr(p),_=fi(_);var K=p.length;D=D===e?K:Rn(Nt(D),0,K);var re=D;return D-=_.length,D>=0&&p.slice(D,re)==_}function Wm(p){return p=nr(p),p&&rt.test(p)?p.replace(pt,Nh):p}function Vm(p){return p=nr(p),p&&ct.test(p)?p.replace(Ot,"\\$&"):p}var Km=os(function(p,_,D){return p+(D?"-":"")+_.toLowerCase()}),Gm=os(function(p,_,D){return p+(D?" ":"")+_.toLowerCase()}),Ym=Sf("toLowerCase");function Zm(p,_,D){p=nr(p),_=Nt(_);var K=_?es(p):0;if(!_||K>=_)return p;var re=(_-K)/2;return ya(aa(re),D)+p+ya(sa(re),D)}function Jm(p,_,D){p=nr(p),_=Nt(_);var K=_?es(p):0;return _&&K<_?p+ya(_-K,D):p}function Qm(p,_,D){p=nr(p),_=Nt(_);var K=_?es(p):0;return _&&K<_?ya(_-K,D)+p:p}function qm(p,_,D){return D||_==null?_=0:_&&(_=+_),au(nr(p).replace(Bt,""),_||0)}function e1(p,_,D){return(D?Hr(p,_,D):_===e)?_=1:_=Nt(_),_o(nr(p),_)}function t1(){var p=arguments,_=nr(p[0]);return p.length<3?_:_.replace(p[1],p[2])}var r1=os(function(p,_,D){return p+(D?"_":"")+_.toLowerCase()});function i1(p,_,D){return D&&typeof D!="number"&&Hr(p,_,D)&&(_=D=e),D=D===e?L:D>>>0,D?(p=nr(p),p&&(typeof _=="string"||_!=null&&!Xo(_))&&(_=fi(_),!_&&qn(p))?bn(Ri(p),0,D):p.split(_,D)):[]}var n1=os(function(p,_,D){return p+(D?" ":"")+Ko(_)});function s1(p,_,D){return p=nr(p),D=D==null?0:Rn(Nt(D),0,p.length),_=fi(_),p.slice(D,D+_.length)==_}function a1(p,_,D){var K=fe.templateSettings;D&&Hr(p,_,D)&&(_=e),p=nr(p),_=Ia({},_,K,Rf);var re=Ia({},_.imports,K.imports,Rf),ce=Or(re),_e=io(re,ce),Ae,Ne,We=0,Ve=_.interpolate||De,Ke="__p += '",qe=so((_.escape||De).source+"|"+Ve.source+"|"+(Ve===et?wt:De).source+"|"+(_.evaluate||De).source+"|$","g"),ft="//# sourceURL="+(sr.call(_,"sourceURL")?(_.sourceURL+"").replace(/\s/g," "):"lodash.templateSources["+ ++Tn+"]")+` +`;p.replace(qe,function(bt,Ht,Vt,hi,Ur,ui){return Vt||(Vt=hi),Ke+=p.slice(We,ui).replace(Fe,Dh),Ht&&(Ae=!0,Ke+=`' + +__e(`+Ht+`) + +'`),Ur&&(Ne=!0,Ke+=`'; +`+Ur+`; +__p += '`),Vt&&(Ke+=`' + +((__t = (`+Vt+`)) == null ? '' : __t) + +'`),We=ui+bt.length,bt}),Ke+=`'; +`;var vt=sr.call(_,"variable")&&_.variable;if(!vt)Ke=`with (obj) { +`+Ke+` +} +`;else if(Gt.test(vt))throw new kt(h);Ke=(Ne?Ke.replace(Le,""):Ke).replace(ze,"$1").replace(Ye,"$1;"),Ke="function("+(vt||"obj")+`) { +`+(vt?"":`obj || (obj = {}); +`)+"var __t, __p = ''"+(Ae?", __e = _.escape":"")+(Ne?`, __j = Array.prototype.join; +function print() { __p += __j.call(arguments, '') } +`:`; +`)+Ke+`return __p +}`;var Ft=xc(function(){return tr(ce,ft+"return "+Ke).apply(e,_e)});if(Ft.source=Ke,Uo(Ft))throw Ft;return Ft}function o1(p){return nr(p).toLowerCase()}function l1(p){return nr(p).toUpperCase()}function f1(p,_,D){if(p=nr(p),p&&(D||_===e))return Rl(p);if(!p||!(_=fi(_)))return p;var K=Ri(p),re=Ri(_),ce=Il(K,re),_e=Ol(K,re)+1;return bn(K,ce,_e).join("")}function c1(p,_,D){if(p=nr(p),p&&(D||_===e))return p.slice(0,Nl(p)+1);if(!p||!(_=fi(_)))return p;var K=Ri(p),re=Ol(K,Ri(_))+1;return bn(K,0,re).join("")}function h1(p,_,D){if(p=nr(p),p&&(D||_===e))return p.replace(Bt,"");if(!p||!(_=fi(_)))return p;var K=Ri(p),re=Il(K,Ri(_));return bn(K,re).join("")}function u1(p,_){var D=j,K=W;if(pr(_)){var re="separator"in _?_.separator:re;D="length"in _?Nt(_.length):D,K="omission"in _?fi(_.omission):K}p=nr(p);var ce=p.length;if(qn(p)){var _e=Ri(p);ce=_e.length}if(D>=ce)return p;var Ae=D-es(K);if(Ae<1)return K;var Ne=_e?bn(_e,0,Ae).join(""):p.slice(0,Ae);if(re===e)return Ne+K;if(_e&&(Ae+=Ne.length-Ae),Xo(re)){if(p.slice(Ae).search(re)){var We,Ve=Ne;for(re.global||(re=so(re.source,nr($t.exec(re))+"g")),re.lastIndex=0;We=re.exec(Ve);)var Ke=We.index;Ne=Ne.slice(0,Ke===e?Ae:Ke)}}else if(p.indexOf(fi(re),Ae)!=Ae){var qe=Ne.lastIndexOf(re);qe>-1&&(Ne=Ne.slice(0,qe))}return Ne+K}function d1(p){return p=nr(p),p&&it.test(p)?p.replace(ot,Hh):p}var p1=os(function(p,_,D){return p+(D?" ":"")+_.toUpperCase()}),Ko=Sf("toUpperCase");function _c(p,_,D){return p=nr(p),_=D?e:_,_===e?Fh(p)?Wh(p):Ir(p):p.match(_)||[]}var xc=Lt(function(p,_){try{return cr(p,e,_)}catch(D){return Uo(D)?D:new kt(D)}}),m1=en(function(p,_){return Pr(_,function(D){D=zi(D),Qi(p,D,zo(p[D],p))}),p});function g1(p){var _=p==null?0:p.length,D=gt();return p=_?Be(p,function(K){if(typeof K[1]!="function")throw new vi(c);return[D(K[0]),K[1]]}):[],Lt(function(K){for(var re=-1;++re<_;){var ce=p[re];if(cr(ce[0],this,K))return cr(ce[1],this,K)}})}function v1(p){return Hu(yi(p,r))}function Go(p){return function(){return p}}function b1(p,_){return p==null||p!==p?_:p}var y1=Cf(),w1=Cf(!0);function Qr(p){return p}function Yo(p){return ef(typeof p=="function"?p:yi(p,r))}function _1(p){return rf(yi(p,r))}function x1(p,_){return nf(p,yi(_,r))}var S1=Lt(function(p,_){return function(D){return Ns(D,p,_)}}),E1=Lt(function(p,_){return function(D){return Ns(p,D,_)}});function Zo(p,_,D){var K=Or(_),re=ua(_,K);D==null&&!(pr(_)&&(re.length||!K.length))&&(D=_,_=p,p=this,re=ua(_,Or(_)));var ce=!(pr(D)&&"chain"in D)||!!D.chain,_e=rn(p);return Pr(re,function(Ae){var Ne=_[Ae];p[Ae]=Ne,_e&&(p.prototype[Ae]=function(){var We=this.__chain__;if(ce||We){var Ve=p(this.__wrapped__),Ke=Ve.__actions__=Yr(this.__actions__);return Ke.push({func:Ne,args:arguments,thisArg:p}),Ve.__chain__=We,Ve}return Ne.apply(p,Ge([this.value()],arguments))})}),p}function C1(){return Et._===this&&(Et._=Jh),this}function Jo(){}function T1(p){return p=Nt(p),Lt(function(_){return sf(_,p)})}var A1=ko(Be),k1=ko(Yi),M1=ko(St);function Sc(p){return Do(p)?oi(zi(p)):sd(p)}function R1(p){return function(_){return p==null?e:In(p,_)}}var I1=Af(),O1=Af(!0);function Qo(){return[]}function qo(){return!1}function P1(){return{}}function N1(){return""}function D1(){return!0}function B1(p,_){if(p=Nt(p),p<1||p>x)return[];var D=L,K=Fr(p,L);_=gt(_),p-=L;for(var re=ro(K,_);++D0||_<0)?new Xt(D):(p<0?D=D.takeRight(-p):p&&(D=D.drop(p)),_!==e&&(_=Nt(_),D=_<0?D.dropRight(-_):D.take(_-p)),D)},Xt.prototype.takeRightWhile=function(p){return this.reverse().takeWhile(p).reverse()},Xt.prototype.toArray=function(){return this.take(L)},ji(Xt.prototype,function(p,_){var D=/^(?:filter|find|map|reject)|While$/.test(_),K=/^(?:head|last)$/.test(_),re=fe[K?"take"+(_=="last"?"Right":""):_],ce=K||/^find/.test(_);re&&(fe.prototype[_]=function(){var _e=this.__wrapped__,Ae=K?[1]:arguments,Ne=_e instanceof Xt,We=Ae[0],Ve=Ne||It(_e),Ke=function(Ht){var Vt=re.apply(fe,Ge([Ht],Ae));return K&&qe?Vt[0]:Vt};Ve&&D&&typeof We=="function"&&We.length!=1&&(Ne=Ve=!1);var qe=this.__chain__,ft=!!this.__actions__.length,vt=ce&&!qe,Ft=Ne&&!ft;if(!ce&&Ve){_e=Ft?_e:new Xt(this);var bt=p.apply(_e,Ae);return bt.__actions__.push({func:Ea,args:[Ke],thisArg:e}),new bi(bt,qe)}return vt&&Ft?p.apply(this,Ae):(bt=this.thru(Ke),vt?K?bt.value()[0]:bt.value():bt)})}),Pr(["pop","push","shift","sort","splice","unshift"],function(p){var _=Zs[p],D=/^(?:push|sort|unshift)$/.test(p)?"tap":"thru",K=/^(?:pop|shift)$/.test(p);fe.prototype[p]=function(){var re=arguments;if(K&&!this.__chain__){var ce=this.value();return _.apply(It(ce)?ce:[],re)}return this[D](function(_e){return _.apply(It(_e)?_e:[],re)})}}),ji(Xt.prototype,function(p,_){var D=fe[_];if(D){var K=D.name+"";sr.call(ns,K)||(ns[K]=[]),ns[K].push({name:_,func:D})}}),ns[va(e,b).name]=[{name:"wrapper",func:e}],Xt.prototype.clone=du,Xt.prototype.reverse=pu,Xt.prototype.value=mu,fe.prototype.at=Xp,fe.prototype.chain=Wp,fe.prototype.commit=Vp,fe.prototype.next=Kp,fe.prototype.plant=Yp,fe.prototype.reverse=Zp,fe.prototype.toJSON=fe.prototype.valueOf=fe.prototype.value=Jp,fe.prototype.first=fe.prototype.head,As&&(fe.prototype[As]=Gp),fe},ts=Vh();Jt?((Jt.exports=ts)._=ts,xt._=ts):Et._=ts}).call(Dt)})(Wa,Wa.exports);var qa=Wa.exports;class Ln{constructor(v,e=""){typeof v=="string"?(this.el=document.createElement(v),this.el.className=e):this.el=v,this.data={}}data(v,e){return e!==void 0?(this.data[v]=e,this):this.data[v]}on(v,e){const[d,...m]=v.split(".");let l=d;return l==="mousewheel"&&/Firefox/i.test(window.navigator.userAgent)&&(l="DOMMouseScroll"),this.el.addEventListener(l,c=>{e(c);for(let h=0;h{this.css(c,`${v[c]}px`)}),this;const{offsetTop:e,offsetLeft:d,offsetHeight:m,offsetWidth:l}=this.el;return{top:e,left:d,height:m,width:l}}scroll(v){const{el:e}=this;return v!==void 0&&(v.left!==void 0&&(e.scrollLeft=v.left),v.top!==void 0&&(e.scrollTop=v.top)),{left:e.scrollLeft,top:e.scrollTop}}box(){return this.el.getBoundingClientRect()}parent(){return new Ln(this.el.parentNode)}children(...v){return arguments.length===0?this.el.childNodes:(v.forEach(e=>this.child(e)),this)}removeChild(v){this.el.removeChild(v)}child(v){let e=v;return typeof v=="string"?e=document.createTextNode(v):v instanceof Ln&&(e=v.el),this.el.appendChild(e),this}contains(v){return this.el.contains(v)}className(v){return v!==void 0?(this.el.className=v,this):this.el.className}addClass(v){return this.el.classList.add(v),this}hasClass(v){return this.el.classList.contains(v)}removeClass(v){return this.el.classList.remove(v),this}toggle(v="active"){return this.toggleClass(v)}toggleClass(v){return this.el.classList.toggle(v)}active(v=!0,e="active"){return v?this.addClass(e):this.removeClass(e),this}checked(v=!0){return this.active(v,"checked"),this}disabled(v=!0){return v?this.addClass("disabled"):this.removeClass("disabled"),this}attr(v,e){if(e!==void 0)this.el.setAttribute(v,e);else{if(typeof v=="string")return this.el.getAttribute(v);Object.keys(v).forEach(d=>{this.el.setAttribute(d,v[d])})}return this}removeAttr(v){return this.el.removeAttribute(v),this}html(v){return v!==void 0?(this.el.innerHTML=v,this):this.el.innerHTML}val(v){return v!==void 0?(this.el.value=v,this):this.el.value}focus(){this.el.focus()}cssRemoveKeys(...v){return v.forEach(e=>this.el.style.removeProperty(e)),this}css(v,e){return e===void 0&&typeof v!="string"?(Object.keys(v).forEach(d=>{this.el.style[d]=v[d]}),this):e!==void 0?(this.el.style[v]=e,this):this.el.style[v]}computedStyle(){return window.getComputedStyle(this.el,null)}show(){return this.css("display","block"),this}hide(){return this.css("display","none"),this}}const je=(B,v="")=>new Ln(B,v),_n=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];function oh(B){let v="",e=B;for(;e>=_n.length;)e/=_n.length,e-=1,v+=_n[parseInt(e,10)%_n.length];const d=B%_n.length;return v+=_n[d],v}function ng(B){let v=0;for(let e=0;e="0"&&B.charAt(d)<="9"?e+=B.charAt(d):v+=B.charAt(d);return[ng(v),parseInt(e,10)-1]}function on(B,v){return`${oh(B)}${v+1}`}function zs(B,v,e,d=()=>!0){if(v===0&&e===0)return B;const[m,l]=xn(B);return d(m,l)?on(m+v,l+e):B}class xr{constructor(v,e,d,m,l=0,c=0){this.sri=v,this.sci=e,this.eri=d,this.eci=m,this.w=l,this.h=c}set(v,e,d,m){this.sri=v,this.sci=e,this.eri=d,this.eci=m}multiple(){return this.eri-this.sri>0||this.eci-this.sci>0}includes(...v){let[e,d]=[0,0];v.length===1?[d,e]=xn(v[0]):v.length===2&&([e,d]=v);const{sri:m,sci:l,eri:c,eci:h}=this;return m<=e&&e<=c&&l<=d&&d<=h}each(v,e=()=>!0){const{sri:d,sci:m,eri:l,eci:c}=this;for(let h=d;h<=l;h+=1)if(e(h))for(let s=m;s<=c;s+=1)v(h,s)}contains(v){return this.sri<=v.sri&&this.sci<=v.sci&&this.eri>=v.eri&&this.eci>=v.eci}within(v){return this.sri>=v.sri&&this.sci>=v.sci&&this.eri<=v.eri&&this.eci<=v.eci}disjoint(v){return this.sri>v.eri||this.sci>v.eci||v.sri>this.eri||v.sci>this.eci}intersects(v){return this.sri<=v.eri&&this.sci<=v.eci&&v.sri<=this.eri&&v.sci<=this.eci}union(v){const{sri:e,sci:d,eri:m,eci:l}=this;return new xr(v.srim?v.eri:m,v.eci>l?v.eci:l)}difference(v){const e=[],d=(n,o,f,a)=>{e.push(new xr(n,o,f,a))},{sri:m,sci:l,eri:c,eci:h}=this,s=v.sri-m,t=v.sci-l,i=c-v.eri,r=h-v.eci;return s>0?(d(m,l,v.sri-1,h),i>0?(d(v.eri+1,l,c,h),t>0&&d(v.sri,l,v.eri,v.sci-1),r>0&&d(v.sri,v.eci+1,v.eri,h)):(t>0&&d(v.sri,l,c,v.sci-1),r>0&&d(v.sri,v.eci+1,c,h))):i>0&&(d(v.eri+1,l,c,h),t>0&&d(m,l,v.eri,v.sci-1),r>0&&d(m,v.eci+1,v.eri,h)),t>0?(d(m,l,c,v.sci-1),r>0?(d(m,v.eri+1,c,h),s>0&&d(m,v.sci,v.sri-1,v.eci),i>0&&d(v.sri+1,v.sci,c,v.eci)):(s>0&&d(m,v.sci,v.sri-1,h),i>0&&d(v.sri+1,v.sci,c,h))):r>0&&(d(c,v.eci+1,c,h),s>0&&d(m,l,v.sri-1,v.eci),i>0&&d(v.eri+1,l,c,v.eci)),e}size(){return[this.eri-this.sri+1,this.eci-this.sci+1]}toString(){const{sri:v,sci:e,eri:d,eci:m}=this;let l=on(e,v);return this.multiple()&&(l=`${l}:${on(m,d)}`),l}clone(){const{sri:v,sci:e,eri:d,eci:m,w:l,h:c}=this;return new xr(v,e,d,m,l,c)}equals(v){return this.eri===v.eri&&this.eci===v.eci&&this.sri===v.sri&&this.sci===v.sci}static valueOf(v){const e=v.split(":"),[d,m]=xn(e[0]);let[l,c]=[m,d];return e.length>1&&([c,l]=xn(e[1])),new xr(m,d,l,c)}}let sg=class{constructor(){this.range=new xr(0,0,0,0),this.ri=0,this.ci=0}multiple(){return this.range.multiple()}setIndexes(v,e){this.ri=v,this.ci=e}size(){return this.range.size()}};class ag{constructor(){this.x=0,this.y=0,this.ri=0,this.ci=0}}class og{constructor(){this.undoItems=[],this.redoItems=[]}add(v){this.undoItems.push(JSON.stringify(v)),this.redoItems=[]}canUndo(){return this.undoItems.length>0}canRedo(){return this.redoItems.length>0}undo(v,e){const{undoItems:d,redoItems:m}=this;this.canUndo()&&(m.push(JSON.stringify(v)),e(JSON.parse(d.pop())))}redo(v,e){const{undoItems:d,redoItems:m}=this;this.canRedo()&&(d.push(JSON.stringify(v)),e(JSON.parse(m.pop())))}}class lg{constructor(){this.range=null,this.state="clear"}copy(v){return this.range=v,this.state="copy",this}cut(v){return this.range=v,this.state="cut",this}isCopy(){return this.state==="copy"}isCut(){return this.state==="cut"}isClear(){return this.state==="clear"}clear(){this.range=null,this.state="clear"}}class Cc{constructor(v,e,d){this.ci=v,this.operator=e,this.value=d}set(v,e){this.operator=v,this.value=e}includes(v){const{operator:e,value:d}=this;return e==="all"?!0:e==="in"?d.includes(v):!1}vlength(){const{operator:v,value:e}=this;return v==="in"?e.length:0}getData(){const{ci:v,operator:e,value:d}=this;return{ci:v,operator:e,value:d}}}class Tc{constructor(v,e){this.ci=v,this.order=e}asc(){return this.order==="asc"}desc(){return this.order==="desc"}}class fg{constructor(){this.ref=null,this.filters=[],this.sort=null}setData({ref:v,filters:e,sort:d}){v!=null&&(this.ref=v,this.filters=e.map(m=>new Cc(m.ci,m.operator,m.value)),d&&(this.sort=new Tc(d.ci,d.order)))}getData(){if(this.active()){const{ref:v,filters:e,sort:d}=this;return{ref:v,filters:e.map(m=>m.getData()),sort:d}}return{}}addFilter(v,e,d){const m=this.getFilter(v);m==null?this.filters.push(new Cc(v,e,d)):m.set(e,d)}setSort(v,e){this.sort=e?new Tc(v,e):null}includes(v,e){return this.active()?this.hrange().includes(v,e):!1}getSort(v){const{sort:e}=this;return e&&e.ci===v?e:null}getFilter(v){const{filters:e}=this;for(let d=0;d!e.within(v))}getFirstIncludes(v,e){for(let d=0;de.intersects(v)))}intersects(v){for(let e=0;e{d.intersects(e)&&(e=d.union(e))}),e}add(v){this.deleteWithin(v),this._.push(v)}shift(v,e,d,m){this._.forEach(l=>{const{sri:c,sci:h,eri:s,eci:t}=l,i=l;v==="row"?c>=e?(i.sri+=d,i.eri+=d):c=e?(i.sci+=d,i.eci+=d):h{const l=m;l.within(v)&&(l.eri+=e,l.sri+=e,l.sci+=d,l.eci+=d)})}setData(v){return this._=v.map(e=>xr.valueOf(e)),this}getData(){return this._.map(v=>v.toString())}}function cg(B){return JSON.parse(JSON.stringify(B))}const lh=(B={},...v)=>(v.forEach(e=>{Object.keys(e).forEach(d=>{const m=e[d];typeof m=="string"||typeof m=="number"||typeof m=="boolean"?B[d]=m:typeof m!="function"&&!Array.isArray(m)&&m instanceof Object?(B[d]=B[d]||{},lh(B[d],m)):B[d]=m})}),B);function hl(B,v){const e=Object.keys(B);if(e.length!==Object.keys(v).length)return!1;for(let d=0;de)=>{let e=0,d=0;return Object.keys(B).forEach(m=>{e+=v(B[m],m),d+=1}),[e,d]};function ug(B,v){const e=B[`${v}`];return delete B[`${v}`],e}function dg(B,v,e,d,m,l){let c=e,h=d,s=B;for(;sm);s+=1)h=l(s),c+=h;return[s,c-h,h]}function pg(B,v,e){let d=0;for(let m=B;m5?h.toFixed(2):h;return h.toFixed(Math.max(d,m))}const qr={cloneDeep:cg,merge:(...B)=>lh({},...B),equals:hl,arrayEquals:gg,sum:hg,rangeEach:mg,rangeSum:pg,rangeReduceIf:dg,deleteProperty:ug,numberCalc:Dn};class vg{constructor({len:v,height:e}){this._={},this.len=v,this.height=e}getHeight(v){if(this.isHide(v))return 0;const e=this.get(v);return e&&e.height?e.height:this.height}setHeight(v,e){const d=this.getOrNew(v);d.height=e}unhide(v){let e=v;for(;e>0&&(e-=1,this.isHide(e));)this.setHide(e,!1)}isHide(v){const e=this.get(v);return e&&e.hide}setHide(v,e){const d=this.getOrNew(v);e===!0?d.hide=!0:delete d.hide}setStyle(v,e){const d=this.getOrNew(v);d.style=e}sumHeight(v,e,d){return qr.rangeSum(v,e,m=>d&&d.has(m)?0:this.getHeight(m))}totalHeight(){return this.sumHeight(0,this.len)}get(v){return this._[v]}getOrNew(v){return this._[v]=this._[v]||{cells:{}},this._[v]}getCell(v,e){const d=this.get(v);return d!==void 0&&d.cells!==void 0&&d.cells[e]!==void 0?d.cells[e]:null}getCellMerge(v,e){const d=this.getCell(v,e);return d&&d.merge?d.merge:[0,0]}getCellOrNew(v,e){const d=this.getOrNew(v);return d.cells[e]=d.cells[e]||{},d.cells[e]}setCell(v,e,d,m="all"){const l=this.getOrNew(v);m==="all"?l.cells[e]=d:m==="text"?(l.cells[e]=l.cells[e]||{},l.cells[e].text=d.text):m==="format"&&(l.cells[e]=l.cells[e]||{},l.cells[e].style=d.style,d.merge&&(l.cells[e].merge=d.merge))}setCellText(v,e,d){const m=this.getCellOrNew(v,e);m.editable!==!1&&(m.text=d)}copyPaste(v,e,d,m=!1,l=()=>{}){const{sri:c,sci:h,eri:s,eci:t}=v,i=e.sri,r=e.sci,n=e.eri,o=e.eci,[f,a]=v.size(),[g,b]=e.size();let u=!0,w=0;(n0){const{text:W}=j;let G=I-r+(E-i)+2;if(u||(G-=w+1),W[0]==="=")j.text=W.replace(/[a-zA-Z]{1,3}\d+/g,V=>{let[J,$]=[0,0];return c===i?J=G-1:$=G-1,/^\d+$/.test(V)?V:zs(V,J,$)});else if(f<=1&&a>1&&(i>s||n1&&(r>t||o{this.eachCells(m,l=>{let c=parseInt(m,10),h=parseInt(l,10);v.includes(m,l)&&(c=e.sri+(c-v.sri),h=e.sci+(h-v.sci)),d[c]=d[c]||{cells:{}},d[c].cells[h]=this._[m].cells[l]})}),this._=d}paste(v,e){if(v.length<=0)return;const{sri:d,sci:m}=e;v.forEach((l,c)=>{const h=d+c;l.forEach((s,t)=>{const i=m+t;this.setCellText(h,i,s)})})}insert(v,e=1){const d={};this.each((m,l)=>{let c=parseInt(m,10);c>=v&&(c+=e,this.eachCells(m,(h,s)=>{s.text&&s.text[0]==="="&&(s.text=s.text.replace(/[a-zA-Z]{1,3}\d+/g,t=>zs(t,0,e,(i,r)=>r>=v)))})),d[c]=l}),this._=d,this.len+=e}delete(v,e){const d=e-v+1,m={};this.each((l,c)=>{const h=parseInt(l,10);he&&(m[h-d]=c,this.eachCells(l,(s,t)=>{t.text&&t.text[0]==="="&&(t.text=t.text.replace(/[a-zA-Z]{1,3}\d+/g,i=>zs(i,0,-d,(r,n)=>n>e)))}))}),this._=m,this.len-=d}insertColumn(v,e=1){this.each((d,m)=>{const l={};this.eachCells(d,(c,h)=>{let s=parseInt(c,10);s>=v&&(s+=e,h.text&&h.text[0]==="="&&(h.text=h.text.replace(/[a-zA-Z]{1,3}\d+/g,t=>zs(t,e,0,i=>i>=v)))),l[s]=h}),m.cells=l})}deleteColumn(v,e){const d=e-v+1;this.each((m,l)=>{const c={};this.eachCells(m,(h,s)=>{const t=parseInt(h,10);te&&(c[t-d]=s,s.text&&s.text[0]==="="&&(s.text=s.text.replace(/[a-zA-Z]{1,3}\d+/g,i=>zs(i,-d,0,r=>r>e))))}),l.cells=c})}deleteCells(v,e="all"){v.each((d,m)=>{this.deleteCell(d,m,e)})}deleteCell(v,e,d="all"){const m=this.get(v);if(m!==null){const l=this.getCell(v,e);l!==null&&l.editable!==!1&&(d==="all"?delete m.cells[e]:d==="text"?(l.text&&delete l.text,l.value&&delete l.value):d==="format"?(l.style!==void 0&&delete l.style,l.merge&&delete l.merge):d==="merge"&&l.merge&&delete l.merge)}}maxCell(){const v=Object.keys(this._),e=v[v.length-1],d=this._[e];if(d){const{cells:m}=d,l=Object.keys(m),c=l[l.length-1];return[parseInt(e,10),parseInt(c,10)]}return[0,0]}each(v){Object.entries(this._).forEach(([e,d])=>{v(e,d)})}eachCells(v,e){this._[v]&&this._[v].cells&&Object.entries(this._[v].cells).forEach(([d,m])=>{e(d,m)})}setData(v){v.len&&(this.len=v.len,delete v.len),this._=v}getData(){const{len:v}=this;return Object.assign({len:v},this._)}}class bg{constructor({len:v,width:e,indexWidth:d,minWidth:m}){this._={},this.len=v,this.width=e,this.indexWidth=d,this.minWidth=m}setData(v){v.len&&(this.len=v.len,delete v.len),this._=v}getData(){const{len:v}=this;return Object.assign({len:v},this._)}getWidth(v){if(this.isHide(v))return 0;const e=this._[v];return e&&e.width?e.width:this.width}getOrNew(v){return this._[v]=this._[v]||{},this._[v]}setWidth(v,e){const d=this.getOrNew(v);d.width=e}unhide(v){let e=v;for(;e>0&&(e-=1,this.isHide(e));)this.setHide(e,!1)}isHide(v){const e=this._[v];return e&&e.hide}setHide(v,e){const d=this.getOrNew(v);e===!0?d.hide=!0:delete d.hide}setStyle(v,e){const d=this.getOrNew(v);d.style=e}sumWidth(v,e){return qr.rangeSum(v,e,d=>this.getWidth(d))}totalWidth(){return this.sumWidth(0,this.len)}}const yg={toolbar:{undo:"Undo",redo:"Redo",print:"Print",paintformat:"Paint format",clearformat:"Clear format",format:"Format",fontName:"Font",fontSize:"Font size",fontBold:"Font bold",fontItalic:"Font italic",underline:"Underline",strike:"Strike",color:"Text color",bgcolor:"Fill color",border:"Borders",merge:"Merge cells",align:"Horizontal align",valign:"Vertical align",textwrap:"Text wrapping",freeze:"Freeze cell",autofilter:"Filter",formula:"Functions",more:"More"},contextmenu:{copy:"Copy",cut:"Cut",paste:"Paste",pasteValue:"Paste values only",pasteFormat:"Paste format only",hide:"Hide",insertRow:"Insert row",insertColumn:"Insert column",deleteSheet:"Delete",deleteRow:"Delete row",deleteColumn:"Delete column",deleteCell:"Delete cell",deleteCellText:"Delete cell text",validation:"Data validations",cellprintable:"Enable export",cellnonprintable:"Disable export",celleditable:"Enable editing",cellnoneditable:"Disable editing"},print:{size:"Paper size",orientation:"Page orientation",orientations:["Landscape","Portrait"]},format:{normal:"Normal",text:"Plain Text",number:"Number",percent:"Percent",rmb:"RMB",usd:"USD",eur:"EUR",date:"Date",time:"Time",datetime:"Date time",duration:"Duration"},formula:{sum:"Sum",average:"Average",max:"Max",min:"Min",_if:"IF",and:"AND",or:"OR",concat:"Concat"},validation:{required:"it must be required",notMatch:"it not match its validation rule",between:"it is between {} and {}",notBetween:"it is not between {} and {}",notIn:"it is not in list",equal:"it equal to {}",notEqual:"it not equal to {}",lessThan:"it less than {}",lessThanEqual:"it less than or equal to {}",greaterThan:"it greater than {}",greaterThanEqual:"it greater than or equal to {}"},error:{pasteForMergedCell:"Unable to do this for merged cells"},calendar:{weeks:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"]},button:{next:"Next",cancel:"Cancel",remove:"Remove",save:"Save",ok:"OK"},sort:{desc:"Sort Z -> A",asc:"Sort A -> Z"},filter:{empty:"empty"},dataValidation:{mode:"Mode",range:"Cell Range",criteria:"Criteria",modeType:{cell:"Cell",column:"Colun",row:"Row"},type:{list:"List",number:"Number",date:"Date",phone:"Phone",email:"Email"},operator:{be:"between",nbe:"not betwwen",lt:"less than",lte:"less than or equal to",gt:"greater than",gte:"greater than or equal to",eq:"equal to",neq:"not equal to"}}};let ul=["en"];const fh={en:yg};function Ac(B,v){if(v)for(const e of ul){if(!v[e])break;let d=v[e];const m=B.match(/(?:\\.|[^.])+/g);for(let l=0;lEr(B)}function ch(B,v,e=!1){e?ul=[B]:ul.unshift(B),v&&(fh[B]=v)}const kc={phone:/^[1-9]\d{10}$/,email:/w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*/};function Ni(B,v,...e){let d="";return B||(d=Er(`validation.${v}`,...e)),[B,d]}class hh{constructor(v,e,d,m){this.required=e,this.value=d,this.type=v,this.operator=m,this.message=""}parseValue(v){const{type:e}=this;return e==="date"?new Date(v):e==="number"?Number(v):v}equals(v){let e=this.type===v.type&&this.required===v.required&&this.operator===v.operator;return e&&(Array.isArray(this.value)?e=qr.arrayEquals(this.value,v.value):e=this.value===v.value),e}values(){return this.value.split(",")}validate(v){const{required:e,operator:d,value:m,type:l}=this;if(e&&/^\s*$/.test(v))return Ni(!1,"required");if(/^\s*$/.test(v))return[!0];if(kc[l]&&!kc[l].test(v))return Ni(!1,"notMatch");if(l==="list")return Ni(this.values().includes(v),"notIn");if(d){const c=this.parseValue(v);if(d==="be"){const[h,s]=m;return Ni(c>=this.parseValue(h)&&c<=this.parseValue(s),"between",h,s)}if(d==="nbe"){const[h,s]=m;return Ni(cthis.parseValue(s),"notBetween",h,s)}if(d==="eq")return Ni(c===this.parseValue(m),"equal",m);if(d==="neq")return Ni(c!==this.parseValue(m),"notEqual",m);if(d==="lt")return Ni(cthis.parseValue(m),"greaterThan",m);if(d==="gte")return Ni(c>=this.parseValue(m),"greaterThanEqual",m)}return[!0]}}class Va{constructor(v,e,d){this.refs=e,this.mode=v,this.validator=d}includes(v,e){const{refs:d}=this;for(let m=0;m{const m=xr.valueOf(d);m.intersects(v)?m.difference(v).forEach(c=>e.push(c.toString())):e.push(d)}),this.refs=e}getData(){const{refs:v,mode:e,validator:d}=this,{type:m,required:l,operator:c,value:h}=d;return{refs:v,mode:e,type:m,required:l,operator:c,value:h}}static valueOf({refs:v,mode:e,type:d,required:m,operator:l,value:c}){return new Va(e,v,new hh(d,m,c,l))}}class wg{constructor(){this._=[],this.errors=new Map}getError(v,e){return this.errors.get(`${v}_${e}`)}validate(v,e,d){const m=this.get(v,e),l=`${v}_${e}`,{errors:c}=this;if(m!==null){const[h,s]=m.validator.validate(d);h?c.delete(l):c.set(l,s)}else c.delete(l);return!0}add(v,e,{type:d,required:m,value:l,operator:c}){const h=new hh(d,m,l,c),s=this.getByValidator(h);s!==null?s.addRef(e):this._.push(new Va(v,[e],h))}getByValidator(v){for(let e=0;e{e.remove(v)})}each(v){this._.forEach(e=>v(e))}getData(){return this._.filter(v=>v.refs.length>0).map(v=>v.getData())}setData(v){this._=v.map(e=>Va.valueOf(e))}}const _g={mode:"edit",view:{height:()=>document.documentElement.clientHeight,width:()=>document.documentElement.clientWidth},showGrid:!0,showToolbar:!0,showContextmenu:!0,showBottomBar:!0,row:{len:100,height:25},col:{len:26,width:100,indexWidth:60,minWidth:60},style:{bgcolor:"#ffffff",align:"left",valign:"middle",textwrap:!1,strike:!1,underline:!1,color:"#0a0a0a",font:{name:"Arial",size:10,bold:!1,italic:!1},format:"normal"}},xg=41,Sg=41,Mc=(B,v)=>Object.prototype.hasOwnProperty.call(B,v);function Rc(B,v,e=()=>{}){const{merges:d}=this,m=v.clone(),[l,c]=B.size(),[h,s]=v.size();return l>h&&(m.eri=v.sri+l-1),c>s&&(m.eci=v.sci+c-1),d.intersects(m)?(e(Er("error.pasteForMergedCell")),!1):!0}function Ic(B,v,e,d=!1){const{rows:m,merges:l}=this;(e==="all"||e==="format")&&(m.deleteCells(v,e),l.deleteWithin(v)),m.copyPaste(B,v,e,d,(c,h,s)=>{if(s&&s.merge){const[t,i]=s.merge;if(t<=0&&i<=0)return;l.add(new xr(c,h,c+t,h+i))}})}function Eg(B,v){const{clipboard:e,rows:d,merges:m}=this;d.cutPaste(B,v),m.move(B,v.sri-B.sri,v.sci-B.sci),e.clear()}function us(B,v,e){const{styles:d,rows:m}=this,l=m.getCellOrNew(B,v);let c={};l.style!==void 0&&(c=qr.cloneDeep(d[l.style])),c=qr.merge(c,{border:e}),l.style=this.addStyle(c)}function Cg({mode:B,style:v,color:e}){const{styles:d,selector:m,rows:l}=this,{sri:c,sci:h,eri:s,eci:t}=m.range,i=!this.isSignleSelected();if(!(!i&&(B==="inside"||B==="horizontal"||B==="vertical"))){if(B==="outside"&&!i)us.call(this,c,h,{top:[v,e],bottom:[v,e],left:[v,e],right:[v,e]});else if(B==="none")m.range.each((r,n)=>{const o=l.getCell(r,n);if(o&&o.style!==void 0){const f=qr.cloneDeep(d[o.style]);delete f.border,o.style=this.addStyle(f)}});else if(B==="all"||B==="inside"||B==="outside"||B==="horizontal"||B==="vertical"){const r=[];for(let n=c;n<=s;n+=1)for(let o=h;o<=t;o+=1){const f=[];for(let S=0;Sr.splice(S,1)),o>t)break;const a=l.getCell(n,o);let[g,b]=[0,0];a&&a.merge&&([g,b]=a.merge,r.push([n,o,g,b]));const u=g>0&&n+g===s,w=b>0&&o+b===t;let y={};B==="all"?y={bottom:[v,e],top:[v,e],left:[v,e],right:[v,e]}:B==="inside"?(!w&&o0&&us.call(this,n,o,y),o+=b}}else if(B==="top"||B==="bottom")for(let r=h;r<=t;r+=1)B==="top"&&(us.call(this,c,r,{top:[v,e]}),r+=l.getCellMerge(c,r)[1]),B==="bottom"&&(us.call(this,s,r,{bottom:[v,e]}),r+=l.getCellMerge(s,r)[1]);else if(B==="left"||B==="right")for(let r=c;r<=s;r+=1)B==="left"&&(us.call(this,r,h,{left:[v,e]}),r+=l.getCellMerge(r,h)[0]),B==="right"&&(us.call(this,r,t,{right:[v,e]}),r+=l.getCellMerge(r,t)[0])}}function Tg(B,v){const{rows:e}=this,d=this.freezeTotalHeight();let m=e.height;d+e.heightB);c+=1)l.has(c)||(s=e.getHeight(c),h+=s);return h-=s,h<=0?{ri:-1,top:0,height:s}:{ri:c-1,top:h,height:s}}function Ag(B,v){const{cols:e}=this,d=this.freezeTotalWidth();let m=e.indexWidth;d+e.indexWidthe.getWidth(s));return c<=0?{ci:-1,left:0,width:e.indexWidth}:{ci:l-1,left:c,width:h}}class kg{constructor(v,e){this.settings=qr.merge(_g,e||{}),this.name=v||"sheet",this.freeze=[0,0],this.styles=[],this.merges=new wl,this.rows=new vg(this.settings.row),this.cols=new bg(this.settings.col),this.validations=new wg,this.hyperlinks={},this.comments={},this.selector=new sg,this.scroll=new ag,this.history=new og,this.clipboard=new lg,this.autoFilter=new fg,this.change=()=>{},this.exceptRowSet=new Set,this.sortedRowMap=new Map,this.unsortedRowMap=new Map}addValidation(v,e,d){this.changeData(()=>{this.validations.add(v,e,d)})}removeValidation(){const{range:v}=this.selector;this.changeData(()=>{this.validations.remove(v)})}getSelectedValidator(){const{ri:v,ci:e}=this.selector,d=this.validations.get(v,e);return d?d.validator:null}getSelectedValidation(){const{ri:v,ci:e,range:d}=this.selector,m=this.validations.get(v,e),l={ref:d.toString()};return m!==null&&(l.mode=m.mode,l.validator=m.validator),l}canUndo(){return this.history.canUndo()}canRedo(){return this.history.canRedo()}undo(){this.history.undo(this.getData(),v=>{this.setData(v)})}redo(){this.history.redo(this.getData(),v=>{this.setData(v)})}copy(){this.clipboard.copy(this.selector.range)}copyToSystemClipboard(){if(navigator.clipboard===void 0)return;let v="";const e=this.rows.getData();for(let d=this.selector.range.sri;d<=this.selector.range.eri;d+=1){if(Mc(e,d)){for(let m=this.selector.range.sci;m<=this.selector.range.eci;m+=1)if(m>this.selector.range.sci&&(v+=" "),Mc(e[d].cells,m)){const l=String(e[d].cells[m].text);l.indexOf(` +`)===-1&&l.indexOf(" ")===-1&&l.indexOf('"')===-1?v+=l:v+=`"${l}"`}}else for(let m=this.selector.range.sci;m<=this.selector.range.eci;m+=1)v+=" ";v+=` +`}navigator.clipboard.writeText(v).then(()=>{},d=>{})}cut(){this.clipboard.cut(this.selector.range)}paste(v="all",e=()=>{}){const{clipboard:d,selector:m}=this;return d.isClear()||!Rc.call(this,d.range,m.range,e)?!1:(this.changeData(()=>{d.isCopy()?Ic.call(this,d.range,m.range,v):d.isCut()&&Eg.call(this,d.range,m.range)}),!0)}pasteFromText(v){const e=v.split(`\r +`).map(l=>l.replace(/"/g,"").split(" "));e.length>0&&(e.length-=1);const{rows:d,selector:m}=this;this.changeData(()=>{d.paste(e,m.range)})}autofill(v,e,d=()=>{}){const m=this.selector.range;return Rc.call(this,m,v,d)?(this.changeData(()=>{Ic.call(this,m,v,e,!0)}),!0):!1}clearClipboard(){this.clipboard.clear()}calSelectedRangeByEnd(v,e){const{selector:d,rows:m,cols:l,merges:c}=this;let{sri:h,sci:s,eri:t,eci:i}=d.range;const r=d.ri,n=d.ci;let[o,f]=[v,e];return v<0&&(o=m.len-1),e<0&&(f=l.len-1),o>r?[h,t]=[r,o]:[h,t]=[o,r],f>n?[s,i]=[n,f]:[s,i]=[f,n],d.range=c.union(new xr(h,s,t,i)),d.range=c.union(d.range),d.range}calSelectedRangeByStart(v,e){const{selector:d,rows:m,cols:l,merges:c}=this;let h=c.getFirstIncludes(v,e);return h===null&&(h=new xr(v,e,v,e),v===-1&&(h.sri=0,h.eri=m.len-1),e===-1&&(h.sci=0,h.eci=l.len-1)),d.range=h,h}setSelectedCellAttr(v,e){this.changeData(()=>{const{selector:d,styles:m,rows:l}=this;if(v==="merge")e?this.merge():this.unmerge();else if(v==="border")Cg.call(this,e);else if(v==="formula"){const{ri:c,ci:h,range:s}=d;if(d.multiple()){const[t,i]=d.size(),{sri:r,sci:n,eri:o,eci:f}=s;if(t>1)for(let a=n;a<=f;a+=1){const g=l.getCellOrNew(o+1,a);g.text=`=${e}(${on(a,r)}:${on(a,o)})`}else if(i>1){const a=l.getCellOrNew(c,f+1);a.text=`=${e}(${on(n,c)}:${on(f,c)})`}}else{const t=l.getCellOrNew(c,h);t.text=`=${e}()`}}else d.range.each((c,h)=>{const s=l.getCellOrNew(c,h);let t={};if(s.style!==void 0&&(t=qr.cloneDeep(m[s.style])),v==="format")t.format=e,s.style=this.addStyle(t);else if(v==="font-bold"||v==="font-italic"||v==="font-name"||v==="font-size"){const i={};i[v.split("-")[1]]=e,t.font=Object.assign(t.font||{},i),s.style=this.addStyle(t)}else v==="strike"||v==="textwrap"||v==="underline"||v==="align"||v==="valign"||v==="color"||v==="bgcolor"?(t[v]=e,s.style=this.addStyle(t)):s[v]=e})})}setSelectedCellText(v,e="input"){const{autoFilter:d,selector:m,rows:l}=this,{ri:c,ci:h}=m;let s=c;this.unsortedRowMap.has(c)&&(s=this.unsortedRowMap.get(c));const t=l.getCell(s,h),i=t?t.text:"";if(this.setCellText(s,h,v,e),d.active()){const r=d.getFilter(h);if(r){const n=r.value.findIndex(o=>o===i);n>=0&&r.value.splice(n,1,v)}}}getSelectedCell(){const{ri:v,ci:e}=this.selector;let d=v;return this.unsortedRowMap.has(v)&&(d=this.unsortedRowMap.get(v)),this.rows.getCell(d,e)}xyInSelectedRect(v,e){const{left:d,top:m,width:l,height:c}=this.getSelectedRect(),h=v-this.cols.indexWidth,s=e-this.rows.height;return h>d&&hm&&s0&&b>i&&(f=i),g>0&&g>r&&(a=r),{l:i,t:r,left:f,top:a,height:n,width:o,scroll:e}}getCellRectByXY(v,e){const{scroll:d,merges:m,rows:l,cols:c}=this;let{ri:h,top:s,height:t}=Tg.call(this,e,d.y),{ci:i,left:r,width:n}=Ag.call(this,v,d.x);if(i===-1&&(n=c.totalWidth()),h===-1&&(t=l.totalHeight()),h>=0||i>=0){const o=m.getFirstIncludes(h,i);o&&(h=o.sri,i=o.sci,{left:r,top:s,width:n,height:t}=this.cellRect(h,i))}return{ri:h,ci:i,left:r,top:s,width:n,height:t}}isSignleSelected(){const{sri:v,sci:e,eri:d,eci:m}=this.selector.range,l=this.getCell(v,e);if(l&&l.merge){const[c,h]=l.merge;if(v+c===d&&e+h===m)return!0}return!this.selector.multiple()}canUnmerge(){const{sri:v,sci:e,eri:d,eci:m}=this.selector.range,l=this.getCell(v,e);if(l&&l.merge){const[c,h]=l.merge;if(v+c===d&&e+h===m)return!0}return!1}merge(){const{selector:v,rows:e}=this;if(this.isSignleSelected())return;const[d,m]=v.size();if(d>1||m>1){const{sri:l,sci:c}=v.range;this.changeData(()=>{const h=e.getCellOrNew(l,c);h.merge=[d-1,m-1],this.merges.add(v.range),this.rows.deleteCells(v.range),this.rows.setCell(l,c,h)})}}unmerge(){const{selector:v}=this;if(!this.isSignleSelected())return;const{sri:e,sci:d}=v.range;this.changeData(()=>{this.rows.deleteCell(e,d,"merge"),this.merges.deleteWithin(v.range)})}canAutofilter(){return!this.autoFilter.active()}autofilter(){const{autoFilter:v,selector:e}=this;this.changeData(()=>{v.active()?(v.clear(),this.exceptRowSet=new Set,this.sortedRowMap=new Map,this.unsortedRowMap=new Map):v.ref=e.range.toString()})}setAutoFilter(v,e,d,m){const{autoFilter:l}=this;l.addFilter(v,d,m),l.setSort(v,e),this.resetAutoFilter()}resetAutoFilter(){const{autoFilter:v,rows:e}=this;if(!v.active())return;const{sort:d}=v,{rset:m,fset:l}=v.filteredRows((s,t)=>e.getCell(s,t)),c=Array.from(l),h=Array.from(l);d&&c.sort((s,t)=>d.order==="asc"?s-t:d.order==="desc"?t-s:0),this.exceptRowSet=m,this.sortedRowMap=new Map,this.unsortedRowMap=new Map,c.forEach((s,t)=>{this.sortedRowMap.set(h[t],s),this.unsortedRowMap.set(s,h[t])})}deleteCell(v="all"){const{selector:e}=this;this.changeData(()=>{this.rows.deleteCells(e.range,v),(v==="all"||v==="format")&&this.merges.deleteWithin(e.range)})}insert(v,e=1){this.changeData(()=>{const{sri:d,sci:m}=this.selector.range,{rows:l,merges:c,cols:h}=this;let s=d;v==="row"?l.insert(d,e):v==="column"&&(l.insertColumn(m,e),s=m,h.len+=1),c.shift(v,s,e,(t,i,r,n)=>{const o=l.getCell(t,i);o.merge[0]+=r,o.merge[1]+=n})})}delete(v){this.changeData(()=>{const{rows:e,merges:d,selector:m,cols:l}=this,{range:c}=m,{sri:h,sci:s,eri:t,eci:i}=m.range,[r,n]=m.range.size();let o=h,f=r;v==="row"?e.delete(h,t):v==="column"&&(e.deleteColumn(s,i),o=c.sci,f=n,l.len-=1),d.shift(v,o,-f,(a,g,b,u)=>{const w=e.getCell(a,g);w.merge[0]+=b,w.merge[1]+=u,w.merge[0]===0&&w.merge[1]===0&&delete w.merge})})}scrollx(v,e){const{scroll:d,freeze:m,cols:l}=this,[,c]=m,[h,s,t]=qr.rangeReduceIf(c,l.len,0,0,v,r=>l.getWidth(r));let i=s;v>0&&(i+=t),d.x!==i&&(d.ci=v>0?h:0,d.x=i,e())}scrolly(v,e){const{scroll:d,freeze:m,rows:l}=this,[c]=m,[h,s,t]=qr.rangeReduceIf(c,l.len,0,0,v,r=>l.getHeight(r));let i=s;v>0&&(i+=t),d.y!==i&&(d.ri=v>0?h:0,d.y=i,e())}cellRect(v,e){const{rows:d,cols:m}=this,l=m.sumWidth(0,e),c=d.sumHeight(0,v),h=d.getCell(v,e);let s=m.getWidth(e),t=d.getHeight(v);if(h!==null&&h.merge){const[i,r]=h.merge;if(i>0)for(let n=1;n<=i;n+=1)t+=d.getHeight(v+n);if(r>0)for(let n=1;n<=r;n+=1)s+=m.getWidth(e+n)}return{left:l,top:c,width:s,height:t,cell:h}}getCell(v,e){return this.rows.getCell(v,e)}getCellTextOrDefault(v,e){const d=this.getCell(v,e);return d&&d.text?d.text:""}getCellStyle(v,e){const d=this.getCell(v,e);return d&&d.style!==void 0?this.styles[d.style]:null}getCellStyleOrDefault(v,e){const{styles:d,rows:m}=this,l=m.getCell(v,e),c=l&&l.style!==void 0?d[l.style]:{};return qr.merge(this.defaultStyle(),c)}getSelectedCellStyle(){const{ri:v,ci:e}=this.selector;return this.getCellStyleOrDefault(v,e)}setCellText(v,e,d,m){const{rows:l,history:c,validations:h}=this;m==="finished"?(l.setCellText(v,e,""),c.add(this.getData()),l.setCellText(v,e,d)):(l.setCellText(v,e,d),this.change(this.getData())),h.validate(v,e,d)}freezeIsActive(){const[v,e]=this.freeze;return v>0||e>0}setFreeze(v,e){this.changeData(()=>{this.freeze=[v,e]})}freezeTotalWidth(){return this.cols.sumWidth(0,this.freeze[1])}freezeTotalHeight(){return this.rows.sumHeight(0,this.freeze[0])}setRowHeight(v,e){this.changeData(()=>{this.rows.setHeight(v,e)})}setColWidth(v,e){this.changeData(()=>{this.cols.setWidth(v,e)})}viewHeight(){const{view:v,showToolbar:e,showBottomBar:d}=this.settings;let m=v.height();return d&&(m-=Sg),e&&(m-=xg),m}viewWidth(){return this.settings.view.width()}freezeViewRange(){const[v,e]=this.freeze;return new xr(0,0,v-1,e-1,this.freezeTotalWidth(),this.freezeTotalHeight())}contentRange(){const{rows:v,cols:e}=this,[d,m]=v.maxCell(),l=v.sumHeight(0,d+1),c=e.sumWidth(0,m+1);return new xr(0,0,d,m,c,l)}exceptRowTotalHeight(v,e){const{exceptRowSet:d,rows:m}=this,l=Array.from(d);let c=0;return l.forEach(h=>{if(he){const s=m.getHeight(h);c+=s}}),c}viewRange(){const{scroll:v,rows:e,cols:d,freeze:m,exceptRowSet:l}=this;let{ri:c,ci:h}=v;c<=0&&([c]=m),h<=0&&([,h]=m);let[s,t]=[0,0],[i,r]=[e.len,d.len];for(let n=c;nthis.viewHeight()));n+=1);for(let n=h;nthis.viewWidth()));n+=1);return new xr(c,h,i,r,s,t)}eachMergesInView(v,e){this.merges.filterIntersects(v).forEach(d=>e(d))}hideRowsOrCols(){const{rows:v,cols:e,selector:d}=this,[m,l]=d.size(),{sri:c,sci:h,eri:s,eci:t}=d.range;if(m===v.len)for(let i=h;i<=t;i+=1)e.setHide(i,!0);else if(l===e.len)for(let i=c;i<=s;i+=1)v.setHide(i,!0)}unhideRowsOrCols(v,e){this[`${v}s`].unhide(e)}rowEach(v,e,d){let m=0;const{rows:l}=this,c=this.exceptRowSet,h=[...c];let s=0;for(let t=0;t0&&(d(t,m,i),m+=i,m>this.viewHeight()))break}}colEach(v,e,d){let m=0;const{cols:l}=this;for(let c=v;c<=e;c+=1){const h=l.getWidth(c);if(h>0&&(d(c,m,h),m+=h,m>this.viewWidth()))break}}defaultStyle(){return this.settings.style}addStyle(v){const{styles:e}=this;for(let d=0;d{if(e==="merges"||e==="rows"||e==="cols"||e==="validations")this[e].setData(v[e]);else if(e==="freeze"){const[d,m]=xn(v[e]);this.freeze=[m,d]}else e==="autofilter"?this.autoFilter.setData(v[e]):v[e]!==void 0&&(this[e]=v[e])}),this}getData(){const{name:v,freeze:e,styles:d,merges:m,rows:l,cols:c,validations:h,autoFilter:s}=this;return{name:v,freeze:on(e[1],e[0]),styles:d,merges:m.getData(),rows:l.getData(),cols:c.getData(),validations:h.getData(),autofilter:s.getData()}}}function ti(B,v,e){B.addEventListener(v,e)}function Ka(B,v,e){B.removeEventListener(v,e)}function vs(B){B.xclickoutside&&(Ka(window.document.body,"click",B.xclickoutside),delete B.xclickoutside)}function Vs(B,v){B.xclickoutside=e=>{e.detail===2||B.contains(e.target)||(v?v(B):(B.hide(),vs(B)))},ti(window.document.body,"click",B.xclickoutside)}function uh(B,v,e){ti(B,"mousemove",v);const d=B;d.xEvtUp=m=>{Ka(B,"mousemove",v),Ka(B,"mouseup",B.xEvtUp),e(m)},ti(B,"mouseup",B.xEvtUp)}function Oc(B,v,e,d){let m="";Math.abs(B)>Math.abs(v)?(m=B>0?"right":"left",d(m,B,e)):(m=v>0?"down":"up",d(m,v,e))}function Mg(B,{move:v,end:e}){let d=0,m=0;ti(B,"touchstart",l=>{const{pageX:c,pageY:h}=l.touches[0];d=c,m=h}),ti(B,"touchmove",l=>{if(!v)return;const{pageX:c,pageY:h}=l.changedTouches[0],s=c-d,t=h-m;(Math.abs(s)>10||Math.abs(t)>10)&&(Oc(s,t,l,v),d=c,m=h),l.preventDefault()}),ti(B,"touchend",l=>{if(!e)return;const{pageX:c,pageY:h}=l.changedTouches[0],s=c-d,t=h-m;Oc(s,t,l,e)})}function Rg(){const B=new Map;function v(c,h){const s=()=>{const i=B.get(c);return Array.isArray(i)&&i.push(h)||!1},t=()=>B.set(c,[].concat(h));return B.has(c)&&s()||t()}function e(c,h){const s=()=>{const t=B.get(c);for(const i of t)i.call(null,...h)};return B.has(c)&&s()}function d(c,h){const s=()=>{const t=B.get(c),i=t.indexOf(h);return i>=0&&t.splice(i,1)&&B.get(c).length===0&&B.delete(c)};return B.has(c)&&s()}function m(c,h){const s=(...t)=>{h.call(null,...t),d(c,s)};return v(c,s)}function l(){B.clear()}return{get current(){return B},on:v,once:m,fire:e,removeListener:d,removeAllListeners:l}}const Ze="x-spreadsheet";class Pc{constructor(v=!1,e){this.moving=!1,this.vertical=v,this.el=je("div",`${Ze}-resizer ${v?"vertical":"horizontal"}`).children(this.unhideHoverEl=je("div",`${Ze}-resizer-hover`).on("dblclick.stop",d=>this.mousedblclickHandler(d)).css("position","absolute").hide(),this.hoverEl=je("div",`${Ze}-resizer-hover`).on("mousedown.stop",d=>this.mousedownHandler(d)),this.lineEl=je("div",`${Ze}-resizer-line`).hide()).hide(),this.cRect=null,this.finishedFn=null,this.minDistance=e,this.unhideFn=()=>{}}showUnhide(v){this.unhideIndex=v,this.unhideHoverEl.show()}hideUnhide(){this.unhideHoverEl.hide()}show(v,e){const{moving:d,vertical:m,hoverEl:l,lineEl:c,el:h,unhideHoverEl:s}=this;if(d)return;this.cRect=v;const{left:t,top:i,width:r,height:n}=v;h.offset({left:m?t+r-5:t,top:m?i:i+n-5}).show(),l.offset({width:m?5:r,height:m?n:5}),c.offset({width:m?0:e.width,height:m?e.height:0}),s.offset({left:m?5-r:t,top:m?i:5-n,width:m?5:r,height:m?n:5})}hide(){this.el.offset({left:0,top:0}).hide(),this.hideUnhide()}mousedblclickHandler(){this.unhideIndex&&this.unhideFn(this.unhideIndex)}mousedownHandler(v){let e=v;const{el:d,lineEl:m,cRect:l,vertical:c,minDistance:h}=this;let s=c?l.width:l.height;m.show(),uh(window,t=>{this.moving=!0,e!==null&&t.buttons===1&&(c?(s+=t.movementX,s>h&&d.css("left",`${l.left+s}px`)):(s+=t.movementY,s>h&&d.css("top",`${l.top+s}px`)),e=t)},()=>{e=null,m.hide(),this.moving=!1,this.hide(),this.finishedFn&&(s{}).on("scroll.stop",e=>{const{scrollTop:d,scrollLeft:m}=e.target;this.moveFn&&this.moveFn(this.vertical?d:m,e)})}move(v){return this.el.scroll(v),this}scroll(){return this.el.scroll()}set(v,e){const d=v-1;if(e>d){const m=this.vertical?"height":"width";this.el.css(m,`${d-15}px`).show(),this.contentEl.css(this.vertical?"width":"height","1px").css(m,`${e}px`)}else this.el.hide();return this}}const Pa=2*2-1;let dl=10;class Na{constructor(v=!1){this.useHideInput=v,this.inputChange=()=>{},this.cornerEl=je("div",`${Ze}-selector-corner`),this.areaEl=je("div",`${Ze}-selector-area`).child(this.cornerEl).hide(),this.clipboardEl=je("div",`${Ze}-selector-clipboard`).hide(),this.autofillEl=je("div",`${Ze}-selector-autofill`).hide(),this.el=je("div",`${Ze}-selector`).css("z-index",`${dl}`).children(this.areaEl,this.clipboardEl,this.autofillEl).hide(),v&&(this.hideInput=je("input","").on("compositionend",e=>{this.inputChange(e.target.value)}),this.el.child(this.hideInputDiv=je("div","hide-input").child(this.hideInput)),this.el.child(this.hideInputDiv=je("div","hide-input").child(this.hideInput))),dl+=1}setOffset(v){return this.el.offset(v).show(),this}hide(){return this.el.hide(),this}setAreaOffset(v){const{left:e,top:d,width:m,height:l}=v,c={width:m-Pa+.8,height:l-Pa+.8,left:e-.8,top:d-.8};this.areaEl.offset(c).show(),this.useHideInput&&(this.hideInputDiv.offset(c),this.hideInput.val("").focus())}setClipboardOffset(v){const{left:e,top:d,width:m,height:l}=v;this.clipboardEl.offset({left:e,top:d,width:m-5,height:l-5})}showAutofill(v){const{left:e,top:d,width:m,height:l}=v;this.autofillEl.offset({width:m-Pa,height:l-Pa,left:e,top:d}).show()}hideAutofill(){this.autofillEl.hide()}showClipboard(){this.clipboardEl.show()}hideClipboard(){this.clipboardEl.hide()}}function _l(B){const{data:v}=this,{left:e,top:d,width:m,height:l,scroll:c,l:h,t:s}=B,t=v.freezeTotalWidth(),i=v.freezeTotalHeight();let r=e-t;t>h&&(r-=c.x);let n=d-i;return i>s&&(n-=c.y),{left:r,top:n,width:m,height:l}}function xl(B){const{data:v}=this,{left:e,width:d,height:m,l,t:c,scroll:h}=B,s=v.freezeTotalWidth();let t=e-s;return s>l&&(t-=h.x),{left:t,top:c,width:d,height:m}}function Sl(B){const{data:v}=this,{top:e,width:d,height:m,l,t:c,scroll:h}=B,s=v.freezeTotalHeight();let t=e-s;return s>c&&(t-=h.y),{left:l,top:t,width:d,height:m}}function pl(B){const{br:v}=this;v.setAreaOffset(_l.call(this,B))}function Ig(B){const{tl:v}=this;v.setAreaOffset(B)}function dh(B){const{t:v}=this;v.setAreaOffset(xl.call(this,B))}function ph(B){const{l:v}=this;v.setAreaOffset(Sl.call(this,B))}function mh(B){const{l:v}=this;v.setClipboardOffset(Sl.call(this,B))}function ml(B){const{br:v}=this;v.setClipboardOffset(_l.call(this,B))}function Og(B){const{tl:v}=this;v.setClipboardOffset(B)}function gh(B){const{t:v}=this;v.setClipboardOffset(xl.call(this,B))}function Dc(B){pl.call(this,B),Ig.call(this,B),dh.call(this,B),ph.call(this,B)}function Bc(B){ml.call(this,B),Og.call(this,B),gh.call(this,B),mh.call(this,B)}class Pg{constructor(v){this.inputChange=()=>{},this.data=v,this.br=new Na(!0),this.t=new Na,this.l=new Na,this.tl=new Na,this.br.inputChange=e=>{this.inputChange(e)},this.br.el.show(),this.offset=null,this.areaOffset=null,this.indexes=null,this.range=null,this.arange=null,this.el=je("div",`${Ze}-selectors`).children(this.tl.el,this.t.el,this.l.el,this.br.el).hide(),this.lastri=-1,this.lastci=-1,dl+=1}resetData(v){this.data=v,this.range=v.selector.range,this.resetAreaOffset()}hide(){this.el.hide()}resetOffset(){const{data:v,tl:e,t:d,l:m,br:l}=this,c=v.freezeTotalHeight(),h=v.freezeTotalWidth();c>0||h>0?(e.setOffset({width:h,height:c}),d.setOffset({left:h,height:c}),m.setOffset({top:c,width:h}),l.setOffset({left:h,top:c})):(e.hide(),d.hide(),m.hide(),l.setOffset({left:0,top:0}))}resetAreaOffset(){const v=this.data.getSelectedRect(),e=this.data.getClipboardRect();Dc.call(this,v),Bc.call(this,e),this.resetOffset()}resetBRTAreaOffset(){const v=this.data.getSelectedRect(),e=this.data.getClipboardRect();pl.call(this,v),dh.call(this,v),ml.call(this,e),gh.call(this,e),this.resetOffset()}resetBRLAreaOffset(){const v=this.data.getSelectedRect(),e=this.data.getClipboardRect();pl.call(this,v),ph.call(this,v),ml.call(this,e),mh.call(this,e),this.resetOffset()}set(v,e,d=!0){const{data:m}=this,l=m.calSelectedRangeByStart(v,e),{sri:c,sci:h}=l;if(d){let[s,t]=[v,e];v<0&&(s=0),e<0&&(t=0),m.selector.setIndexes(s,t),this.indexes=[s,t]}this.moveIndexes=[c,h],this.range=l,this.resetAreaOffset(),this.el.show()}setEnd(v,e,d=!0){const{data:m,lastri:l,lastci:c}=this;if(d){if(v===l&&e===c)return;this.lastri=v,this.lastci=e}this.range=m.calSelectedRangeByEnd(v,e),Dc.call(this,this.data.getSelectedRect())}reset(){const{eri:v,eci:e}=this.data.selector.range;this.setEnd(v,e)}showAutofill(v,e){if(v===-1&&e===-1)return;const{sri:d,sci:m,eri:l,eci:c}=this.range,[h,s]=[v,e],t=d-v,i=m-e,r=l-v,n=c-e;if(i>0)this.arange=new xr(d,s,l,m-1);else if(t>0)this.arange=new xr(h,m,d-1,c);else if(n<0)this.arange=new xr(d,c+1,l,s);else if(r<0)this.arange=new xr(l+1,m,h,c);else{this.arange=null;return}if(this.arange!==null){const o=this.data.getRect(this.arange);o.width+=2,o.height+=2;const{br:f,l:a,t:g,tl:b}=this;f.showAutofill(_l.call(this,o)),a.showAutofill(Sl.call(this,o)),g.showAutofill(xl.call(this,o)),b.showAutofill(o)}}hideAutofill(){["br","l","t","tl"].forEach(v=>{this[v].hideAutofill()})}showClipboard(){const v=this.data.getClipboardRect();Bc.call(this,v),["br","l","t","tl"].forEach(e=>{this[e].showClipboard()})}hideClipboard(){["br","l","t","tl"].forEach(v=>{this[v].hideClipboard()})}}function Ng(B){B.preventDefault(),B.stopPropagation();const{filterItems:v}=this;v.length<=0||(this.itemIndex>=0&&v[this.itemIndex].toggle(),this.itemIndex-=1,this.itemIndex<0&&(this.itemIndex=v.length-1),v[this.itemIndex].toggle())}function Dg(B){B.stopPropagation();const{filterItems:v}=this;v.length<=0||(this.itemIndex>=0&&v[this.itemIndex].toggle(),this.itemIndex+=1,this.itemIndex>v.length-1&&(this.itemIndex=0),v[this.itemIndex].toggle())}function Fc(B){B.preventDefault();const{filterItems:v}=this;v.length<=0||(B.stopPropagation(),this.itemIndex<0&&(this.itemIndex=0),v[this.itemIndex].el.click(),this.hide())}function Bg(B){const{keyCode:v}=B;switch(B.ctrlKey&&B.stopPropagation(),v){case 37:B.stopPropagation();break;case 38:Ng.call(this,B);break;case 39:B.stopPropagation();break;case 40:Dg.call(this,B);break;case 13:Fc.call(this,B);break;case 9:Fc.call(this,B);break;default:B.stopPropagation();break}}class vh{constructor(v,e,d="200px"){this.filterItems=[],this.items=v,this.el=je("div",`${Ze}-suggest`).css("width",d).hide(),this.itemClick=e,this.itemIndex=-1}setOffset(v){this.el.cssRemoveKeys("top","bottom").offset(v)}hide(){const{el:v}=this;this.filterItems=[],this.itemIndex=-1,v.hide(),vs(this.el.parent())}setItems(v){this.items=v}search(v){let{items:e}=this;if(/^\s*$/.test(v)||(e=e.filter(m=>(m.key||m).startsWith(v.toUpperCase()))),e=e.map(m=>{let{title:l}=m;l?typeof l=="function"&&(l=l()):l=m;const c=je("div",`${Ze}-item`).child(l).on("click.stop",()=>{this.itemClick(m),this.hide()});return m.label&&c.child(je("div","label").html(m.label)),c}),this.filterItems=e,e.length<=0)return;const{el:d}=this;d.html("").children(...e).show(),Vs(d.parent(),()=>{this.hide()})}bindInputEvents(v){v.on("keydown",e=>Bg.call(this,e))}}class jr extends Ln{constructor(v){super("div",`${Ze}-icon`),this.iconNameEl=je("div",`${Ze}-icon-img ${v}`),this.child(this.iconNameEl)}setName(v){this.iconNameEl.className(`${Ze}-icon-img ${v}`)}}function Lc(B,v){B.setMonth(B.getMonth()+v)}function Fg(B,v){const e=new Date(B);return e.setDate(v-B.getDay()+1),e}function Lg(B,v,e){const d=new Date(B,v,1,23,59,59),m=[[],[],[],[],[],[]];for(let l=0;l<6;l+=1)for(let c=0;c<7;c+=1){const h=l*7+c,s=Fg(d,h),t=s.getMonth()!==v,i=s.getMonth()===e.getMonth()&&s.getDate()===e.getDate();m[l][c]={d:s,disabled:t,active:i}}return m}class jg{constructor(v){this.value=v,this.cvalue=new Date(v),this.headerLeftEl=je("div","calendar-header-left"),this.bodyEl=je("tbody",""),this.buildAll(),this.el=je("div","x-spreadsheet-calendar").children(je("div","calendar-header").children(this.headerLeftEl,je("div","calendar-header-right").children(je("a","calendar-prev").on("click.stop",()=>this.prev()).child(new jr("chevron-left")),je("a","calendar-next").on("click.stop",()=>this.next()).child(new jr("chevron-right")))),je("table","calendar-body").children(je("thead","").child(je("tr","").children(...Er("calendar.weeks").map(e=>je("th","cell").child(e)))),this.bodyEl)),this.selectChange=()=>{}}setValue(v){this.value=v,this.cvalue=new Date(v),this.buildAll()}prev(){const{value:v}=this;Lc(v,-1),this.buildAll()}next(){const{value:v}=this;Lc(v,1),this.buildAll()}buildAll(){this.buildHeaderLeft(),this.buildBody()}buildHeaderLeft(){const{value:v}=this;this.headerLeftEl.html(`${Er("calendar.months")[v.getMonth()]} ${v.getFullYear()}`)}buildBody(){const{value:v,cvalue:e,bodyEl:d}=this,l=Lg(v.getFullYear(),v.getMonth(),e).map(c=>{const h=c.map(s=>{let t="cell";return s.disabled&&(t+=" disabled"),s.active&&(t+=" active"),je("td","").child(je("div",t).on("click.stop",()=>{this.selectChange(s.d)}).child(s.d.getDate().toString()))});return je("tr","").children(...h)});d.html("").children(...l)}}class $g{constructor(){this.calendar=new jg(new Date),this.el=je("div",`${Ze}-datepicker`).child(this.calendar.el).hide()}setValue(v){const{calendar:e}=this;return typeof v=="string"?/^\d{4}-\d{1,2}-\d{1,2}$/.test(v)&&e.setValue(new Date(v.replace(new RegExp("-","g"),"/"))):v instanceof Date&&e.setValue(v),this}change(v){this.calendar.selectChange=e=>{v(e),this.hide()}}show(){this.el.show()}hide(){this.el.hide()}}function Ga(){const{inputText:B}=this;if(!/^\s*$/.test(B)){const{textlineEl:v,textEl:e,areaOffset:d}=this,m=B.split(` +`),l=Math.max(...m.map(r=>r.length)),h=v.offset().width/B.length,s=(l+1)*h+5,t=this.viewFn().width-d.left-h;let i=m.length;if(s>d.width){let r=s;s>t&&(r=t,i+=parseInt(s/t,10),i+=s%t>0?1:0),e.css("width",`${r}px`)}i*=this.rowHeight,i>d.height&&e.css("height",`${i}px`)}}function zg({target:B},v){const{value:e,selectionEnd:d}=B,m=`${e.slice(0,d)}${v}${e.slice(d)}`;B.value=m,B.setSelectionRange(d+1,d+1),this.inputText=m,this.textlineEl.html(m),Ga.call(this)}function Hg(B){const{keyCode:v,altKey:e}=B;v!==13&&v!==9&&B.stopPropagation(),v===13&&e&&(zg.call(this,B,` +`),B.stopPropagation()),v===13&&!e&&B.preventDefault()}function Ug(B){const v=B.target.value,{suggest:e,textlineEl:d,validator:m}=this,{cell:l}=this;if(l!==null)if("editable"in l&&l.editable===!0||l.editable===void 0){if(this.inputText=v,m)m.type==="list"?e.search(v):e.hide();else{const c=v.lastIndexOf("=");c!==-1?e.search(v.substring(c+1)):e.hide()}d.html(v),Ga.call(this),this.change("input",v)}else B.target.value=l.text;else{if(this.inputText=v,m)m.type==="list"?e.search(v):e.hide();else{const c=v.lastIndexOf("=");c!==-1?e.search(v.substring(c+1)):e.hide()}d.html(v),Ga.call(this),this.change("input",v)}}function Xg(B){const{el:v}=this.textEl;setTimeout(()=>{v.focus(),v.setSelectionRange(B,B)},0)}function bh(B,v){const{textEl:e,textlineEl:d}=this;e.el.blur(),e.val(B),d.html(B),Xg.call(this,v)}function Wg(B){const{inputText:v,validator:e}=this;let d=0;if(e&&e.type==="list")this.inputText=B,d=this.inputText.length;else{const m=v.lastIndexOf("="),l=v.substring(0,m+1);let c=v.substring(m+1);c.indexOf(")")!==-1?c=c.substring(c.indexOf(")")):c="",this.inputText=`${l+B.key}(`,d=this.inputText.length,this.inputText+=`)${c}`}bh.call(this,this.inputText,d)}function Vg(){this.suggest.setItems(this.formulas)}function Kg(B){let v=B.getMonth()+1,e=B.getDate();return v<10&&(v=`0${v}`),e<10&&(e=`0${e}`),`${B.getFullYear()}-${v}-${e}`}class Gg{constructor(v,e,d){this.viewFn=e,this.rowHeight=d,this.formulas=v,this.suggest=new vh(v,m=>{Wg.call(this,m)}),this.datepicker=new $g,this.datepicker.change(m=>{this.setText(Kg(m)),this.clear()}),this.areaEl=je("div",`${Ze}-editor-area`).children(this.textEl=je("textarea","").on("input",m=>Ug.call(this,m)).on("paste.stop",()=>{}).on("keydown",m=>Hg.call(this,m)),this.textlineEl=je("div","textline"),this.suggest.el,this.datepicker.el).on("mousemove.stop",()=>{}).on("mousedown.stop",()=>{}),this.el=je("div",`${Ze}-editor`).child(this.areaEl).hide(),this.suggest.bindInputEvents(this.textEl),this.areaOffset=null,this.freeze={w:0,h:0},this.cell=null,this.inputText="",this.change=()=>{}}setFreezeLengths(v,e){this.freeze.w=v,this.freeze.h=e}clear(){this.inputText!==""&&this.change("finished",this.inputText),this.cell=null,this.areaOffset=null,this.inputText="",this.el.hide(),this.textEl.val(""),this.textlineEl.html(""),Vg.call(this),this.datepicker.hide()}setOffset(v,e="top"){const{textEl:d,areaEl:m,suggest:l,freeze:c,el:h}=this;if(v){this.areaOffset=v;const{left:s,top:t,width:i,height:r,l:n,t:o}=v,f={left:0,top:0};c.w>n&&c.h>o||(c.wn?f.top=c.h:c.h>o&&(f.left=c.w)),h.offset(f),m.offset({left:s-f.left-.8,top:t-f.top-.8}),d.offset({width:i-9+.8,height:r-3+.8});const a={left:0};a[e]=r,l.setOffset(a),l.hide()}}setCell(v,e){const{el:d,datepicker:m,suggest:l}=this;d.show(),this.cell=v;const c=v&&v.text||"";if(this.setText(c),this.validator=e,e){const{type:h}=e;h==="date"&&(m.show(),/^\s*$/.test(c)||m.setValue(c)),h==="list"&&(l.setItems(e.values()),l.search(""))}}setText(v){this.inputText=v,bh.call(this,v,v.length),Ga.call(this)}}class Bn extends Ln{constructor(v,e=""){super("div",`${Ze}-button ${e}`),this.child(Er(`button.${v}`))}}function Ya(){return window.devicePixelRatio||1}function El(){return Ya()-.5}function Pt(B){return parseInt(B*Ya(),10)}function ds(B){const v=Pt(B);return v>0?v-.5:.5}class Yg{constructor(v,e,d,m,l=0){this.x=v,this.y=e,this.width=d,this.height=m,this.padding=l,this.bgcolor="#ffffff",this.borderTop=null,this.borderRight=null,this.borderBottom=null,this.borderLeft=null}setBorders({top:v,bottom:e,left:d,right:m}){v&&(this.borderTop=v),m&&(this.borderRight=m),e&&(this.borderBottom=e),d&&(this.borderLeft=d)}innerWidth(){return this.width-this.padding*2-2}innerHeight(){return this.height-this.padding*2-2}textx(v){const{width:e,padding:d}=this;let{x:m}=this;return v==="left"?m+=d:v==="center"?m+=e/2:v==="right"&&(m+=e-d),m}texty(v,e){const{height:d,padding:m}=this;let{y:l}=this;return v==="top"?l+=m:v==="middle"?l+=d/2-e/2:v==="bottom"&&(l+=d-m-e),l}topxys(){const{x:v,y:e,width:d}=this;return[[v,e],[v+d,e]]}rightxys(){const{x:v,y:e,width:d,height:m}=this;return[[v+d,e],[v+d,e+m]]}bottomxys(){const{x:v,y:e,width:d,height:m}=this;return[[v,e+m],[v+d,e+m]]}leftxys(){const{x:v,y:e,height:d}=this;return[[v,e],[v,e+d]]}}function jc(B,v,e,d,m,l,c){const h={x:0,y:0};B==="underline"?m==="bottom"?h.y=0:m==="top"?h.y=-(l+2):h.y=-l/2:B==="strike"&&(m==="bottom"?h.y=l/2:m==="top"&&(h.y=-(l/2+2))),d==="center"?h.x=c/2:d==="right"&&(h.x=c),this.line([v-h.x,e-h.y],[v-h.x+c,e-h.y])}class yh{constructor(v,e,d){this.el=v,this.ctx=v.getContext("2d"),this.resize(e,d),this.ctx.scale(Ya(),Ya())}resize(v,e){this.el.style.width=`${v}px`,this.el.style.height=`${e}px`,this.el.width=Pt(v),this.el.height=Pt(e)}clear(){const{width:v,height:e}=this.el;return this.ctx.clearRect(0,0,v,e),this}attr(v){return Object.assign(this.ctx,v),this}save(){return this.ctx.save(),this.ctx.beginPath(),this}restore(){return this.ctx.restore(),this}beginPath(){return this.ctx.beginPath(),this}translate(v,e){return this.ctx.translate(Pt(v),Pt(e)),this}scale(v,e){return this.ctx.scale(v,e),this}clearRect(v,e,d,m){return this.ctx.clearRect(v,e,d,m),this}fillRect(v,e,d,m){return this.ctx.fillRect(Pt(v)-.5,Pt(e)-.5,Pt(d),Pt(m)),this}fillText(v,e,d){return this.ctx.fillText(v,Pt(e),Pt(d)),this}text(v,e,d={},m=!0){const{ctx:l}=this,{align:c,valign:h,font:s,color:t,strike:i,underline:r}=d,n=e.textx(c);l.save(),l.beginPath(),this.attr({textAlign:c,textBaseline:h,font:`${s.italic?"italic":""} ${s.bold?"bold":""} ${Pt(s.size)}px ${s.name}`,fillStyle:t,strokeStyle:t});const o=`${v}`.split(` +`),f=e.innerWidth(),a=[];o.forEach(u=>{const w=l.measureText(u).width;if(m&&w>Pt(f)){let y={w:0,len:0,start:0};for(let S=0;S=Pt(f)&&(a.push(u.substr(y.start,y.len)),y={w:0,len:0,start:S}),y.len+=1,y.w+=l.measureText(u[S]).width+1;y.len>0&&a.push(u.substr(y.start,y.len))}else a.push(u)});const g=(a.length-1)*(s.size+2);let b=e.texty(h,g);return a.forEach(u=>{const w=l.measureText(u).width;this.fillText(u,n,b),i&&jc.call(this,"strike",n,b,c,h,s.size,w),r&&jc.call(this,"underline",n,b,c,h,s.size,w),b+=s.size+2}),l.restore(),this}border(v,e){const{ctx:d}=this;return d.lineWidth=El,d.strokeStyle=e,v==="medium"?d.lineWidth=Pt(2)-.5:v==="thick"?d.lineWidth=Pt(3):v==="dashed"?d.setLineDash([Pt(3),Pt(2)]):v==="dotted"?d.setLineDash([Pt(1),Pt(1)]):v==="double"&&d.setLineDash([Pt(2),0]),this}line(...v){const{ctx:e}=this;if(v.length>1){e.beginPath();const[d,m]=v[0];e.moveTo(ds(d),ds(m));for(let l=1;l{const v=[],e=[];let d=[],m=0,l="",c=1,h="";for(let s=0;s="a"&&t<="z")d.push(t.toUpperCase());else if(t>="0"&&t<="9"||t>="A"&&t<="Z"||t===".")d.push(t);else if(t==='"'){for(s+=1;B.charAt(s)!=='"';)d.push(B.charAt(s)),s+=1;e.push(`"${d.join("")}`),d=[]}else if(t==="-"&&/[+\-*/,(]/.test(h))d.push(t);else{if(t!=="("&&d.length>0&&e.push(d.join("")),t===")"){let i=v.pop();if(m===2)try{const[r,n]=xn(e.pop()),[o,f]=xn(e.pop());let a=0;for(let g=o;g<=r;g+=1)for(let b=f;b<=n;b+=1)e.push(on(g,b)),a+=1;e.push([i,a])}catch{}else if(m===1||m===3)m===3&&e.push(l),e.push([i,c]),c=1;else for(;i!=="("&&(e.push(i),!(v.length<=0));)i=v.pop();m=0}else if(t==="="||t===">"||t==="<"){const i=B.charAt(s+1);l=t,(i==="="||i==="-")&&(l+=i,s+=1),m=3}else if(t===":")m=2;else if(t===",")m===3&&e.push(l),m=1,c+=1;else if(t==="("&&d.length>0)v.push(d.join(""));else{if(v.length>0&&(t==="+"||t==="-")){let i=v[v.length-1];if(i!=="("&&e.push(v.pop()),i==="*"||i==="/")for(;v.length>0&&(i=v[v.length-1],i!=="(");)e.push(v.pop())}else if(v.length>0){const i=v[v.length-1];(i==="*"||i==="/")&&e.push(v.pop())}v.push(t)}d=[]}h=t}}for(d.length>0&&e.push(d.join(""));v.length>0;)e.push(v.pop());return e},Qg=(B,v)=>{const[e]=B;let d=B;if(e==='"')return B.substring(1);let m=1;if(e==="-"&&(d=B.substring(1),m=-1),d[0]>="0"&&d[0]<="9")return m*Number(d);const[l,c]=xn(d);return m*v(l,c)},qg=(B,v,e,d)=>{const m=[];for(let l=0;l"||h==="<"){let s=m.pop();Number.isNaN(s)||(s=Number(s));let t=m.pop();Number.isNaN(t)||(t=Number(t));let i=!1;h==="="?i=t===s:c===">"?i=t>s:c===">="?i=t>=s:c==="<"?i=t="a"&&h<="z"||h>="A"&&h<="Z")&&d.push(c),m.push(Qg(c,e)),d.pop()}}return m[0]},wh=(B,v,e,d=[])=>{if(B[0]==="="){const m=Jg(B.substring(1));return m.length<=0?B:qg(m,v,(l,c)=>wh(e(l,c),v,e,d),d)}return B},ev={render:wh},Cl=[{key:"SUM",title:Wt("formula.sum"),render:B=>B.reduce((v,e)=>Dn("+",v,e),0)},{key:"AVERAGE",title:Wt("formula.average"),render:B=>B.reduce((v,e)=>Number(v)+Number(e),0)/B.length},{key:"MAX",title:Wt("formula.max"),render:B=>Math.max(...B.map(v=>Number(v)))},{key:"MIN",title:Wt("formula.min"),render:B=>Math.min(...B.map(v=>Number(v)))},{key:"IF",title:Wt("formula._if"),render:([B,v,e])=>B?v:e},{key:"AND",title:Wt("formula.and"),render:B=>B.every(v=>v)},{key:"OR",title:Wt("formula.or"),render:B=>B.some(v=>v)},{key:"CONCAT",title:Wt("formula.concat"),render:B=>B.join("")}],tv=Cl,_h={};Cl.forEach(B=>{_h[B.key]=B});const ps=B=>B,Da=B=>{if(/^(-?\d*.?\d*)$/.test(B)){const v=Number(B).toFixed(2).toString(),[e,...d]=v.split("\\.");return[e.replace(/(\d)(?=(\d{3})+(?!\d))/g,"$1,"),...d]}return B},Hs=[{key:"normal",title:Wt("format.normal"),type:"string",render:ps},{key:"text",title:Wt("format.text"),type:"string",render:ps},{key:"number",title:Wt("format.number"),type:"number",label:"1,000.12",render:Da},{key:"percent",title:Wt("format.percent"),type:"number",label:"10.12%",render:B=>`${B}%`},{key:"rmb",title:Wt("format.rmb"),type:"number",label:"¥10.00",render:B=>`¥${Da(B)}`},{key:"usd",title:Wt("format.usd"),type:"number",label:"$10.00",render:B=>`$${Da(B)}`},{key:"eur",title:Wt("format.eur"),type:"number",label:"€10.00",render:B=>`€${Da(B)}`},{key:"date",title:Wt("format.date"),type:"date",label:"26/09/2008",render:ps},{key:"time",title:Wt("format.time"),type:"date",label:"15:59:00",render:ps},{key:"datetime",title:Wt("format.datetime"),type:"date",label:"26/09/2008 15:59:00",render:ps},{key:"duration",title:Wt("format.duration"),type:"date",label:"24:01:00",render:ps}],xh={};Hs.forEach(B=>{xh[B.key]=B});const rv=5,iv={fillStyle:"#f4f5f8"},nv={fillStyle:"#fff",lineWidth:El,strokeStyle:"#e6e6e6"};function sv(){return{textAlign:"center",textBaseline:"middle",font:`500 ${Pt(12)}px Source Sans Pro`,fillStyle:"#585757",lineWidth:El(),strokeStyle:"#e6e6e6"}}function Sh(B,v,e,d=0){const{left:m,top:l,width:c,height:h}=B.cellRect(v,e);return new Yg(m,l+d,c,h,rv)}function Za(B,v,e,d,m=0){const{sortedRowMap:l,rows:c,cols:h}=v;if(c.isHide(e)||h.isHide(d))return;let s=e;l.has(e)&&(s=l.get(e));const t=v.getCell(s,d);if(t===null)return;let i=!1;"editable"in t&&t.editable===!1&&(i=!0);const r=v.getCellStyleOrDefault(s,d),n=Sh(v,e,d,m);n.bgcolor=r.bgcolor,r.border!==void 0&&(n.setBorders(r.border),B.strokeBorders(n)),B.rect(n,()=>{let o="";v.settings.evalPaused?o=t.text||"":o=ev.render(t.text||"",_h,(g,b)=>v.getCellTextOrDefault(b,g)),r.format&&(o=xh[r.format].render(o));const f=Object.assign({},r.font);f.size=Zg(f.size),B.text(o,n,{align:r.align,valign:r.valign,font:f,color:r.color,strike:r.strike,underline:r.underline},r.textwrap),v.validations.getError(e,d)&&B.error(n),i&&B.frozen(n)})}function av(B){const{data:v,draw:e}=this;if(B){const{autoFilter:d}=v;if(!d.active())return;const m=d.hrange();B.intersects(m)&&m.each((l,c)=>{const h=Sh(v,l,c);e.dropdown(h)})}}function Ba(B,v,e,d,m){const{draw:l,data:c}=this;l.save(),l.translate(v,e).translate(d,m);const{exceptRowSet:h}=c,s=r=>{const n=h.has(r);if(n){const o=c.rows.getHeight(r);l.translate(0,-o)}return!n},t=c.exceptRowTotalHeight(B.sri,B.eri);l.save(),l.translate(0,-t),B.each((r,n)=>{Za(l,c,r,n)},r=>s(r)),l.restore();const i=new Set;l.save(),l.translate(0,-t),c.eachMergesInView(B,({sri:r,sci:n,eri:o})=>{if(!h.has(r))Za(l,c,r,n);else if(!i.has(r)){i.add(r);const f=c.rows.sumHeight(r,o+1);l.translate(0,-f)}}),l.restore(),av.call(this,B),l.restore()}function zc(B,v,e,d){const{draw:m}=this;m.save(),m.attr({fillStyle:"rgba(75, 137, 255, 0.08)"}).fillRect(B,v,e,d),m.restore()}function Fa(B,v,e,d,m,l){const{draw:c,data:h}=this,s=v.h,t=v.w,i=l+d,r=m+e;c.save(),c.attr(iv),(B==="all"||B==="left")&&c.fillRect(0,i,e,s),(B==="all"||B==="top")&&c.fillRect(r,0,t,d);const{sri:n,sci:o,eri:f,eci:a}=h.selector.range;c.attr(sv()),(B==="all"||B==="left")&&(h.rowEach(v.sri,v.eri,(g,b,u)=>{const w=i+b,y=g;c.line([0,w],[e,w]),n<=y&&y0&&h.rows.isHide(g-1)&&(c.save(),c.attr({strokeStyle:"#c6c6c6"}),c.line([5,w+5],[e-5,w+5]),c.restore())}),c.line([0,s+i],[e,s+i]),c.line([e,i],[e,s+i])),(B==="all"||B==="top")&&(h.colEach(v.sci,v.eci,(g,b,u)=>{const w=r+b,y=g;c.line([w,0],[w,d]),o<=y&&y0&&h.cols.isHide(g-1)&&(c.save(),c.attr({strokeStyle:"#c6c6c6"}),c.line([w+5,5],[w+5,d-5]),c.restore())}),c.line([t+r,0],[t+r,d]),c.line([0,d],[t+r,d])),c.restore()}function ov(B,v){const{draw:e}=this;e.save(),e.attr({fillStyle:"#f4f5f8"}).fillRect(0,0,B,v),e.restore()}function La({sri:B,sci:v,eri:e,eci:d,w:m,h:l},c,h,s,t){const{draw:i,data:r}=this,{settings:n}=r;if(i.save(),i.attr(nv).translate(c+s,h+t),!n.showGrid){i.restore();return}r.rowEach(B,e,(o,f,a)=>{o!==B&&i.line([0,f],[m,f]),o===e&&i.line([0,f+a],[m,f+a])}),r.colEach(v,d,(o,f,a)=>{o!==v&&i.line([f,0],[f,l]),o===d&&i.line([f+a,0],[f+a,l])}),i.restore()}function lv(B,v,e,d){const{draw:m,data:l}=this,c=l.viewWidth()-B,h=l.viewHeight()-v;m.save().translate(B,v).attr({strokeStyle:"rgba(75, 137, 255, .6)"}),m.line([0,d],[c,d]),m.line([e,0],[e,h]),m.restore()}class fv{constructor(v,e){this.el=v,this.draw=new yh(v,e.viewWidth(),e.viewHeight()),this.data=e}resetData(v){this.data=v,this.render()}render(){const{data:v}=this,{rows:e,cols:d}=v,m=d.indexWidth,l=e.height;this.draw.resize(v.viewWidth(),v.viewHeight()),this.clear();const c=v.viewRange(),h=v.freezeTotalWidth(),s=v.freezeTotalHeight(),{x:t,y:i}=v.scroll;La.call(this,c,m,l,h,s),Ba.call(this,c,m,l,-t,-i),Fa.call(this,"all",c,m,l,h,s),ov.call(this,m,l);const[r,n]=v.freeze;if(r>0||n>0){if(r>0){const f=c.clone();f.sri=0,f.eri=r-1,f.h=s,La.call(this,f,m,l,h,0),Ba.call(this,f,m,l,-t,0),Fa.call(this,"top",f,m,l,h,0)}if(n>0){const f=c.clone();f.sci=0,f.eci=n-1,f.w=h,La.call(this,f,m,l,0,s),Fa.call(this,"left",f,m,l,0,s),Ba.call(this,f,m,l,0,-i)}const o=v.freezeViewRange();La.call(this,o,m,l,0,0),Fa.call(this,"all",o,m,l,0,0),Ba.call(this,o,m,l,0,0),lv.call(this,m,l,h,s)}}clear(){this.draw.clear()}}const $a=[["A3",11.69,16.54],["A4",8.27,11.69],["A5",5.83,8.27],["B4",9.84,13.9],["B5",6.93,9.84]],vl=["landscape","portrait"];function Ja(B){return parseInt(96*B,10)}function Hc(B){B==="cancel"?this.el.hide():this.toPrint()}function cv(B){const{paper:v}=this,{value:e}=B.target,d=$a[e];v.w=Ja(d[1]),v.h=Ja(d[2]),this.preview()}function hv(B){const{paper:v}=this,{value:e}=B.target,d=vl[e];v.orientation=d,this.preview()}let uv=class{constructor(v){this.paper={w:Ja($a[0][1]),h:Ja($a[0][2]),padding:50,orientation:vl[0],get width(){return this.orientation==="landscape"?this.h:this.w},get height(){return this.orientation==="landscape"?this.w:this.h}},this.data=v,this.el=je("div",`${Ze}-print`).children(je("div",`${Ze}-print-bar`).children(je("div","-title").child("Print settings"),je("div","-right").children(je("div",`${Ze}-buttons`).children(new Bn("cancel").on("click",Hc.bind(this,"cancel")),new Bn("next","primary").on("click",Hc.bind(this,"next"))))),je("div",`${Ze}-print-content`).children(this.contentEl=je("div","-content"),je("div","-sider").child(je("form","").children(je("fieldset","").children(je("label","").child(`${Er("print.size")}`),je("select","").children(...$a.map((e,d)=>je("option","").attr("value",d).child(`${e[0]} ( ${e[1]}''x${e[2]}'' )`))).on("change",cv.bind(this))),je("fieldset","").children(je("label","").child(`${Er("print.orientation")}`),je("select","").children(...vl.map((e,d)=>je("option","").attr("value",d).child(`${Er("print.orientations")[d]}`))).on("change",hv.bind(this))))))).hide()}resetData(v){this.data=v}preview(){const{data:v,paper:e}=this,{width:d,height:m,padding:l}=e,c=d-l*2,h=m-l*2,s=v.contentRange(),t=parseInt(s.h/h,10)+1,i=c/s.w;let r=l;const n=l;i>1&&(r+=(c-s.w)/2);let o=0,f=0;this.contentEl.html(""),this.canvases=[];const a={sri:0,sci:0,eri:0,eci:0};for(let g=0;g{Za(S,v,I,P,E)}),S.restore(),a.sri=a.eri,a.sci=a.eci,f+=u,this.contentEl.child(je("div",`${Ze}-canvas-card-wraper`).child(w.child(y)))}this.el.show()}toPrint(){this.el.hide();const{paper:v}=this,e=je("iframe","").hide(),{el:d}=e;window.document.body.appendChild(d);const{contentWindow:m}=d,l=m.document,c=document.createElement("style");c.innerHTML=` + @page { size: ${v.width}px ${v.height}px; }; + canvas { + page-break-before: auto; + page-break-after: always; + image-rendering: pixelated; + }; + `,l.head.appendChild(c),this.canvases.forEach(h=>{const s=h.cloneNode(!1);s.getContext("2d").drawImage(h,0,0),l.body.appendChild(s)}),m.print()}};const dv=[{key:"copy",title:Wt("contextmenu.copy"),label:"Ctrl+C"},{key:"cut",title:Wt("contextmenu.cut"),label:"Ctrl+X"},{key:"paste",title:Wt("contextmenu.paste"),label:"Ctrl+V"},{key:"paste-value",title:Wt("contextmenu.pasteValue"),label:"Ctrl+Shift+V"},{key:"paste-format",title:Wt("contextmenu.pasteFormat"),label:"Ctrl+Alt+V"},{key:"divider"},{key:"insert-row",title:Wt("contextmenu.insertRow")},{key:"insert-column",title:Wt("contextmenu.insertColumn")},{key:"divider"},{key:"delete-row",title:Wt("contextmenu.deleteRow")},{key:"delete-column",title:Wt("contextmenu.deleteColumn")},{key:"delete-cell-text",title:Wt("contextmenu.deleteCellText")},{key:"hide",title:Wt("contextmenu.hide")},{key:"divider"},{key:"validation",title:Wt("contextmenu.validation")},{key:"divider"},{key:"cell-printable",title:Wt("contextmenu.cellprintable")},{key:"cell-non-printable",title:Wt("contextmenu.cellnonprintable")},{key:"divider"},{key:"cell-editable",title:Wt("contextmenu.celleditable")},{key:"cell-non-editable",title:Wt("contextmenu.cellnoneditable")}];function pv(B){return B.key==="divider"?je("div",`${Ze}-item divider`):je("div",`${Ze}-item`).on("click",()=>{this.itemClick(B.key),this.hide()}).children(B.title(),je("div","label").child(B.label||""))}function mv(){return dv.map(B=>pv.call(this,B))}let gv=class{constructor(v,e=!1){this.menuItems=mv.call(this),this.el=je("div",`${Ze}-contextmenu`).children(...this.menuItems).hide(),this.viewFn=v,this.itemClick=()=>{},this.isHide=e,this.setMode("range")}setMode(v){const e=this.menuItems[12];v==="row-col"?e.show():e.hide()}hide(){const{el:v}=this;v.hide(),vs(v)}setPosition(v,e){if(this.isHide)return;const{el:d}=this,{width:m}=d.show().offset(),l=this.viewFn(),c=l.height/2;let h=v;l.width-v<=m&&(h-=m),d.css("left",`${h}px`),e>c?d.css("bottom",`${l.height-e}px`).css("max-height",`${e}px`).css("top","auto"):d.css("top",`${e}px`).css("max-height",`${l.height-e}px`).css("bottom","auto"),Vs(d)}};function vv(B,v){if(v.classList.contains("active"))return;const{left:e,top:d,width:m,height:l}=v.getBoundingClientRect(),c=je("div",`${Ze}-tooltip`).html(B).show();document.body.appendChild(c.el);const h=c.box();c.css("left",`${e+m/2-h.width/2}px`).css("top",`${d+l+2}px`),ti(v,"mouseleave",()=>{document.body.contains(c.el)&&document.body.removeChild(c.el)}),ti(v,"click",()=>{document.body.contains(c.el)&&document.body.removeChild(c.el)})}class Tl{constructor(v,e,d){this.tip=Er(`toolbar.${v.replace(/-[a-z]/g,m=>m[1].toUpperCase())}`),e&&(this.tip+=` (${e})`),this.tag=v,this.shortcut=e,this.value=d,this.el=this.element(),this.change=()=>{}}element(){const{tip:v}=this;return je("div",`${Ze}-toolbar-btn`).on("mouseenter",e=>{vv(v,e.target)}).attr("data-tooltip",v)}setState(){}}class Xi extends Tl{dropdown(){}getValue(v){return v}element(){const{tag:v}=this;return this.dd=this.dropdown(),this.dd.change=e=>this.change(v,this.getValue(e)),super.element().child(this.dd)}setState(v){v&&(this.value=v,this.dd.setTitle(v))}}class Wi extends Ln{constructor(v,e,d,m,...l){super("div",`${Ze}-dropdown ${m}`),this.title=v,this.change=()=>{},this.headerClick=()=>{},typeof v=="string"?this.title=je("div",`${Ze}-dropdown-title`).child(v):d&&this.title.addClass("arrow-left"),this.contentEl=je("div",`${Ze}-dropdown-content`).css("width",e).hide(),this.setContentChildren(...l),this.headerEl=je("div",`${Ze}-dropdown-header`),this.headerEl.on("click",()=>{this.contentEl.css("display")!=="block"?this.show():this.hide()}).children(this.title,d?je("div",`${Ze}-icon arrow-right`).child(je("div",`${Ze}-icon-img arrow-down`)):""),this.children(this.headerEl,this.contentEl)}setContentChildren(...v){this.contentEl.html(""),v.length>0&&this.contentEl.children(...v)}setTitle(v){this.title.html(v),this.hide()}show(){const{contentEl:v}=this;v.show(),this.parent().active(),Vs(this.parent(),()=>{this.hide()})}hide(){this.parent().active(!1),this.contentEl.hide(),vs(this.parent())}}function bv(B){return je("div",`${Ze}-item`).child(new jr(B))}class Eh extends Wi{constructor(v,e){const d=new jr(`align-${e}`),m=v.map(l=>bv(`align-${l}`).on("click",()=>{this.setTitle(l),this.change(l)}));super(d,"auto",!0,"bottom-left",...m)}setTitle(v){this.title.setName(`align-${v}`),this.hide()}}class yv extends Xi{constructor(v){super("align","",v)}dropdown(){const{value:v}=this;return new Eh(["left","center","right"],v)}}class wv extends Xi{constructor(v){super("valign","",v)}dropdown(){const{value:v}=this;return new Eh(["top","middle","bottom"],v)}}class ln extends Tl{element(){const{tag:v}=this;return super.element().child(new jr(v)).on("click",()=>this.click())}click(){this.change(this.tag,this.toggle())}setState(v){this.el.active(v)}toggle(){return this.el.toggle()}active(){return this.el.hasClass("active")}}class _v extends ln{constructor(){super("autofilter")}setState(){}}class xv extends ln{constructor(){super("font-bold","Ctrl+B")}}class Sv extends ln{constructor(){super("font-italic","Ctrl+I")}}class Ev extends ln{constructor(){super("strike","Ctrl+U")}}class Cv extends ln{constructor(){super("underline","Ctrl+U")}}const Tv=["#ffffff","#000100","#e7e5e6","#445569","#5b9cd6","#ed7d31","#a5a5a5","#ffc001","#4371c6","#71ae47"],Av=[["#f2f2f2","#7f7f7f","#d0cecf","#d5dce4","#deeaf6","#fce5d5","#ededed","#fff2cd","#d9e2f3","#e3efd9"],["#d8d8d8","#595959","#afabac","#adb8ca","#bdd7ee","#f7ccac","#dbdbdb","#ffe59a","#b3c6e7","#c5e0b3"],["#bfbfbf","#3f3f3f","#756f6f","#8596b0","#9cc2e6","#f4b184","#c9c9c9","#fed964","#8eaada","#a7d08c"],["#a5a5a5","#262626","#3a3839","#333f4f","#2e75b5","#c45a10","#7b7b7b","#bf8e01","#2f5596","#538136"],["#7f7f7f","#0c0c0c","#171516","#222a35","#1f4e7a","#843c0a","#525252","#7e6000","#203864","#365624"]],kv=["#c00000","#fe0000","#fdc101","#ffff01","#93d051","#00b04e","#01b0f1","#0170c1","#012060","#7030a0"];function tl(B){return je("td","").child(je("div",`${Ze}-color-palette-cell`).on("click.stop",()=>this.change(B)).css("background-color",B))}class Mv{constructor(){this.el=je("div",`${Ze}-color-palette`),this.change=()=>{};const v=je("table","").children(je("tbody","").children(je("tr",`${Ze}-theme-color-placeholders`).children(...Tv.map(e=>tl.call(this,e))),...Av.map(e=>je("tr",`${Ze}-theme-colors`).children(...e.map(d=>tl.call(this,d)))),je("tr",`${Ze}-standard-colors`).children(...kv.map(e=>tl.call(this,e)))));this.el.child(v)}}class Al extends Wi{constructor(v,e){const d=new jr(v).css("height","16px").css("border-bottom",`3px solid ${e}`),m=new Mv;m.change=l=>{this.setTitle(l),this.change(l)},super(d,"auto",!1,"bottom-left",m.el)}setTitle(v){this.title.css("border-color",v),this.hide()}}const Rv=[["thin",''],["medium",''],["thick",''],["dashed",''],["dotted",'']];class Iv extends Wi{constructor(v){const e=new jr("line-type");let d=0;const m=Rv.map((l,c)=>je("div",`${Ze}-item state ${v===l[0]?"checked":""}`).on("click",()=>{m[d].toggle("checked"),m[c].toggle("checked"),d=c,this.hide(),this.change(l)}).child(je("div",`${Ze}-line-type`).html(l[1])));super(e,"auto",!1,"bottom-left",...m)}}function Uc(...B){return je("table","").child(je("tbody","").children(...B))}function Xc(B){return je("td","").child(je("div",`${Ze}-border-palette-cell`).child(new jr(`border-${B}`)).on("click",()=>{this.mode=B;const{mode:v,style:e,color:d}=this;this.change({mode:v,style:e,color:d})}))}class Ov{constructor(){this.color="#000",this.style="thin",this.mode="all",this.change=()=>{},this.ddColor=new Al("line-color",this.color),this.ddColor.change=e=>{this.color=e},this.ddType=new Iv(this.style),this.ddType.change=([e])=>{this.style=e},this.el=je("div",`${Ze}-border-palette`);const v=Uc(je("tr","").children(je("td",`${Ze}-border-palette-left`).child(Uc(je("tr","").children(...["all","inside","horizontal","vertical","outside"].map(e=>Xc.call(this,e))),je("tr","").children(...["left","top","right","bottom","none"].map(e=>Xc.call(this,e))))),je("td",`${Ze}-border-palette-right`).children(je("div",`${Ze}-toolbar-btn`).child(this.ddColor.el),je("div",`${Ze}-toolbar-btn`).child(this.ddType.el))));this.el.child(v)}}class Pv extends Wi{constructor(){const v=new jr("border-all"),e=new Ov;e.change=d=>{this.change(d),this.hide()},super(v,"auto",!1,"bottom-left",e.el)}}class Nv extends Xi{constructor(){super("border")}dropdown(){return new Pv}}class eo extends Tl{element(){return super.element().child(new jr(this.tag)).on("click",()=>this.change(this.tag))}setState(v){this.el.disabled(v)}}class Dv extends eo{constructor(){super("clearformat")}}class Bv extends ln{constructor(){super("paintformat")}setState(){}}class Fv extends Xi{constructor(v){super("color",void 0,v)}dropdown(){const{tag:v,value:e}=this;return new Al(v,e)}}class Lv extends Xi{constructor(v){super("bgcolor",void 0,v)}dropdown(){const{tag:v,value:e}=this;return new Al(v,e)}}class jv extends Wi{constructor(){const v=gl.map(e=>je("div",`${Ze}-item`).on("click",()=>{this.setTitle(`${e.pt}`),this.change(e)}).child(`${e.pt}`));super("10","60px",!0,"bottom-left",...v)}}let $v=class extends Xi{constructor(){super("font-size")}getValue(v){return v.pt}dropdown(){return new jv}};class zv extends Wi{constructor(){const v=$c.map(e=>je("div",`${Ze}-item`).on("click",()=>{this.setTitle(e.title),this.change(e)}).child(e.title));super($c[0].title,"160px",!0,"bottom-left",...v)}}class Hv extends Xi{constructor(){super("font-name")}getValue(v){return v.key}dropdown(){return new zv}}class Uv extends Wi{constructor(){let v=Hs.slice(0);v.splice(2,0,{key:"divider"}),v.splice(8,0,{key:"divider"}),v=v.map(e=>{const d=je("div",`${Ze}-item`);return e.key==="divider"?d.addClass("divider"):(d.child(e.title()).on("click",()=>{this.setTitle(e.title()),this.change(e)}),e.label&&d.child(je("div","label").html(e.label))),d}),super("Normal","220px",!0,"bottom-left",...v)}setTitle(v){for(let e=0;eje("div",`${Ze}-item`).on("click",()=>{this.hide(),this.change(e)}).child(e.key));super(new jr("formula"),"180px",!0,"bottom-left",...v)}}class Vv extends Xi{constructor(){super("formula")}getValue(v){return v.key}dropdown(){return new Wv}}class Kv extends ln{constructor(){super("freeze")}}class Gv extends ln{constructor(){super("merge")}setState(v,e){this.el.active(v).disabled(e)}}class Yv extends eo{constructor(){super("redo","Ctrl+Y")}}class Zv extends eo{constructor(){super("undo","Ctrl+Z")}}class Jv extends eo{constructor(){super("print","Ctrl+P")}}class Qv extends ln{constructor(){super("textwrap")}}let qv=class extends Wi{constructor(){const v=new jr("ellipsis"),e=je("div",`${Ze}-toolbar-more`);super(v,"auto",!1,"bottom-right",e),this.moreBtns=e,this.contentEl.css("max-width","420px")}};class eb extends Xi{constructor(){super("more"),this.el.hide()}dropdown(){return new qv}show(){this.el.show()}hide(){this.el.hide()}}function ms(){return je("div",`${Ze}-toolbar-divider`)}function tb(){this.btns2=[],this.items.forEach(B=>{if(Array.isArray(B))B.forEach(({el:v})=>{const e=v.box(),{marginLeft:d,marginRight:m}=v.computedStyle();this.btns2.push([v,e.width+parseInt(d,10)+parseInt(m,10)])});else{const v=B.box(),{marginLeft:e,marginRight:d}=B.computedStyle();this.btns2.push([B,v.width+parseInt(e,10)+parseInt(d,10)])}})}function Wc(){const{el:B,btns:v,moreEl:e,btns2:d}=this,{moreBtns:m,contentEl:l}=e.dd;B.css("width",`${this.widthFn()-60}px`);const c=B.box();let h=160,s=12;const t=[],i=[];d.forEach(([r,n],o)=>{h+=n,o===d.length-1||h0?e.show():e.hide()}class rb{constructor(v,e,d=!1){this.data=v,this.change=()=>{},this.widthFn=e,this.isHide=d;const m=v.defaultStyle();this.items=[[this.undoEl=new Zv,this.redoEl=new Yv,new Jv,this.paintformatEl=new Bv,this.clearformatEl=new Dv],ms(),[this.formatEl=new Xv],ms(),[this.fontEl=new Hv,this.fontSizeEl=new $v],ms(),[this.boldEl=new xv,this.italicEl=new Sv,this.underlineEl=new Cv,this.strikeEl=new Ev,this.textColorEl=new Fv(m.color)],ms(),[this.fillColorEl=new Lv(m.bgcolor),this.borderEl=new Nv,this.mergeEl=new Gv],ms(),[this.alignEl=new yv(m.align),this.valignEl=new wv(m.valign),this.textwrapEl=new Qv],ms(),[this.freezeEl=new Kv,this.autofilterEl=new _v,this.formulaEl=new Vv,this.moreEl=new eb]],this.el=je("div",`${Ze}-toolbar`),this.btns=je("div",`${Ze}-toolbar-btns`),this.items.forEach(l=>{Array.isArray(l)?l.forEach(c=>{this.btns.child(c.el),c.change=(...h)=>{this.change(...h)}}):this.btns.child(l.el)}),this.el.child(this.btns),d?this.el.hide():(this.reset(),setTimeout(()=>{tb.call(this),Wc.call(this)},0),ti(window,"resize",()=>{Wc.call(this)}))}paintformatActive(){return this.paintformatEl.active()}paintformatToggle(){this.paintformatEl.toggle()}trigger(v){this[`${v}El`].click()}resetData(v){this.data=v,this.reset()}reset(){if(this.isHide)return;const{data:v}=this,e=v.getSelectedCellStyle();this.undoEl.setState(!v.canUndo()),this.redoEl.setState(!v.canRedo()),this.mergeEl.setState(v.canUnmerge(),!v.selector.multiple()),this.autofilterEl.setState(!v.canAutofilter());const{font:d,format:m}=e;this.formatEl.setState(m),this.fontEl.setState(d.name),this.fontSizeEl.setState(d.size),this.boldEl.setState(d.bold),this.italicEl.setState(d.italic),this.underlineEl.setState(e.underline),this.strikeEl.setState(e.strike),this.textColorEl.setState(e.color),this.fillColorEl.setState(e.bgcolor),this.alignEl.setState(e.align),this.valignEl.setState(e.valign),this.textwrapEl.setState(e.textwrap),this.freezeEl.setState(v.freezeIsActive())}}class ib{constructor(v,e,d="600px"){this.title=v,this.el=je("div",`${Ze}-modal`).css("width",d).children(je("div",`${Ze}-modal-header`).children(new jr("close").on("click.stop",()=>this.hide()),this.title),je("div",`${Ze}-modal-content`).children(...e)).hide()}show(){this.dimmer=je("div",`${Ze}-dimmer active`),document.body.appendChild(this.dimmer.el);const{width:v,height:e}=this.el.show().box(),{clientHeight:d,clientWidth:m}=document.documentElement;this.el.offset({left:(m-v)/2,top:(d-e)/3}),window.xkeydownEsc=l=>{l.keyCode===27&&this.hide()},ti(window,"keydown",window.xkeydownEsc)}hide(){this.el.hide(),document.body.removeChild(this.dimmer.el),Ka(window,"keydown",window.xkeydownEsc),delete window.xkeydownEsc}}class gs{constructor(v,e){this.vchange=()=>{},this.el=je("div",`${Ze}-form-input`),this.input=je("input","").css("width",v).on("input",d=>this.vchange(d)).attr("placeholder",e),this.el.child(this.input)}focus(){setTimeout(()=>{this.input.el.focus()},10)}hint(v){this.input.attr("placeholder",v)}val(v){return this.input.val(v)}}class rl{constructor(v,e,d,m=c=>c,l=()=>{}){this.key=v,this.getTitle=m,this.vchange=()=>{},this.el=je("div",`${Ze}-form-select`),this.suggest=new vh(e.map(c=>({key:c,title:this.getTitle(c)})),c=>{this.itemClick(c.key),l(c.key),this.vchange(c.key)},d,this.el),this.el.children(this.itemEl=je("div","input-text").html(this.getTitle(v)),this.suggest.el).on("click",()=>this.show())}show(){this.suggest.search("")}itemClick(v){this.key=v,this.itemEl.html(this.getTitle(v))}val(v){return v!==void 0?(this.key=v,this.itemEl.html(this.getTitle(v)),this):this.key}}const nb={number:/(^\d+$)|(^\d+(\.\d{0,4})?$)/,date:/^\d{4}-\d{1,2}-\d{1,2}$/};class wn{constructor(v,e,d,m){this.label="",this.rule=e,d&&(this.label=je("label","label").css("width",`${m}px`).html(d)),this.tip=je("div","tip").child("tip").hide(),this.input=v,this.input.vchange=()=>this.validate(),this.el=je("div",`${Ze}-form-field`).children(this.label,v.el,this.tip)}isShow(){return this.el.css("display")!=="none"}show(){this.el.show()}hide(){return this.el.hide(),this}val(v){return this.input.val(v)}hint(v){this.input.hint(v)}validate(){const{input:v,rule:e,tip:d,el:m}=this,l=v.val();return e.required&&/^\s*$/.test(l)?(d.html(Er("validation.required")),m.addClass("error"),!1):(e.type||e.pattern)&&!(e.pattern||nb[e.type]).test(l)?(d.html(Er("validation.notMatch")),m.addClass("error"),!1):(m.removeClass("error"),!0)}}const Vc=100;class sb extends ib{constructor(){const v=new wn(new rl("cell",["cell"],"100%",t=>Er(`dataValidation.modeType.${t}`)),{required:!0},`${Er("dataValidation.range")}:`,Vc),e=new wn(new gs("120px","E3 or E3:F12"),{required:!0,pattern:/^([A-Z]{1,2}[1-9]\d*)(:[A-Z]{1,2}[1-9]\d*)?$/}),d=new wn(new rl("list",["list","number","date","phone","email"],"100%",t=>Er(`dataValidation.type.${t}`),t=>this.criteriaSelected(t)),{required:!0},`${Er("dataValidation.criteria")}:`,Vc),m=new wn(new rl("be",["be","nbe","eq","neq","lt","lte","gt","gte"],"160px",t=>Er(`dataValidation.operator.${t}`),t=>this.criteriaOperatorSelected(t)),{required:!0}).hide(),l=new wn(new gs("70px","10"),{required:!0}).hide(),c=new wn(new gs("70px","100"),{required:!0,type:"number"}).hide(),h=new wn(new gs("120px","a,b,c"),{required:!0}),s=new wn(new gs("70px","10"),{required:!0,type:"number"}).hide();super(Er("contextmenu.validation"),[je("div",`${Ze}-form-fields`).children(v.el,e.el),je("div",`${Ze}-form-fields`).children(d.el,m.el,l.el,c.el,s.el,h.el),je("div",`${Ze}-buttons`).children(new Bn("cancel").on("click",()=>this.btnClick("cancel")),new Bn("remove").on("click",()=>this.btnClick("remove")),new Bn("save","primary").on("click",()=>this.btnClick("save")))]),this.mf=v,this.rf=e,this.cf=d,this.of=m,this.minvf=l,this.maxvf=c,this.vf=s,this.svf=h,this.change=()=>{}}showVf(v){const e=v==="date"?"2018-11-12":"10",{vf:d}=this;d.input.hint(e),d.show()}criteriaSelected(v){const{of:e,minvf:d,maxvf:m,vf:l,svf:c}=this;v==="date"||v==="number"?(e.show(),d.rule.type=v,m.rule.type=v,v==="date"?(d.hint("2018-11-12"),m.hint("2019-11-12")):(d.hint("10"),m.hint("100")),d.show(),m.show(),l.hide(),c.hide()):(v==="list"?c.show():c.hide(),l.hide(),e.hide(),d.hide(),m.hide())}criteriaOperatorSelected(v){if(!v)return;const{minvf:e,maxvf:d,vf:m}=this;if(v==="be"||v==="nbe")e.show(),d.show(),m.hide();else{const l=this.cf.val();m.rule.type=l,l==="date"?m.hint("2018-11-12"):m.hint("10"),m.show(),e.hide(),d.hide()}}btnClick(v){if(v==="cancel")this.hide();else if(v==="remove")this.change("remove"),this.hide();else if(v==="save"){const e=["mf","rf","cf","of","svf","vf","minvf","maxvf"];for(let s=0;sthis.itemClick(B))}function ab(B){const{filterbEl:v,filterValues:e}=this;v.html(""),Object.keys(B).forEach((m,l)=>{const c=B[m],h=e.includes(m)?"checked":"";v.child(je("div",`${Ze}-item state ${h}`).on("click.stop",()=>this.filterClick(l,m)).children(m===""?Er("filter.empty"):m,je("div","label").html(`(${c})`)))})}function Gc(){const{filterhEl:B,filterValues:v,values:e}=this;B.html(`${v.length} / ${e.length}`),B.checked(v.length===e.length)}class ob{constructor(){this.filterbEl=je("div",`${Ze}-body`),this.filterhEl=je("div",`${Ze}-header state`).on("click.stop",()=>this.filterClick(0,"all")),this.el=je("div",`${Ze}-sort-filter`).children(this.sortAscEl=Kc.call(this,"asc"),this.sortDescEl=Kc.call(this,"desc"),Ch("divider"),je("div",`${Ze}-filter`).children(this.filterhEl,this.filterbEl),je("div",`${Ze}-buttons`).children(new Bn("cancel").on("click",()=>this.btnClick("cancel")),new Bn("ok","primary").on("click",()=>this.btnClick("ok")))).hide(),this.ci=null,this.sortDesc=null,this.values=null,this.filterValues=[]}btnClick(v){if(v==="ok"){const{ci:e,sort:d,filterValues:m}=this;this.ok&&this.ok(e,d,"in",m)}this.hide()}itemClick(v){this.sort=v;const{sortAscEl:e,sortDescEl:d}=this;e.checked(v==="asc"),d.checked(v==="desc")}filterClick(v,e){const{filterbEl:d,filterValues:m,values:l}=this,c=d.children();e==="all"?c.length===m.length?(this.filterValues=[],c.forEach(h=>je(h).checked(!1))):(this.filterValues=Array.from(l),c.forEach(h=>je(h).checked(!0))):je(c[v]).toggle("checked")?m.push(e):m.splice(m.findIndex(s=>s===e),1),Gc.call(this)}set(v,e,d,m){this.ci=v;const{sortAscEl:l,sortDescEl:c}=this;m!==null?(this.sort=m.order,l.checked(m.asc()),c.checked(m.desc())):(this.sortDesc=null,l.checked(!1),c.checked(!1)),this.values=Object.keys(e),this.filterValues=d?Array.from(d.value):Object.keys(e),ab.call(this,e,d),Gc.call(this)}setOffset(v){this.el.offset(v).show();let e=1;Vs(this.el,()=>{e<=0&&this.hide(),e-=1})}show(){this.el.show()}hide(){this.el.hide(),vs(this.el)}}function Th(B,v){const e=je("div",`${Ze}-toast`),d=je("div",`${Ze}-dimmer active`),m=()=>{document.body.removeChild(e.el),document.body.removeChild(d.el)};e.children(je("div",`${Ze}-toast-header`).children(new jr("close").on("click.stop",()=>m()),B),je("div",`${Ze}-toast-content`).html(v)),document.body.appendChild(e.el),document.body.appendChild(d.el);const{width:l,height:c}=e.box(),{clientHeight:h,clientWidth:s}=document.documentElement;e.offset({left:(s-l)/2,top:(h-c)/3})}function il(B,v){let e;return(...d)=>{const m=this,l=d;e||(e=setTimeout(()=>{e=null,B.apply(m,l)},v))}}function lb(){const{data:B,verticalScrollbar:v,horizontalScrollbar:e}=this,{l:d,t:m,left:l,top:c,width:h,height:s}=B.getSelectedRect(),t=this.getTableOffset();if(Math.abs(l)+h>t.width)e.move({left:d+h-t.width});else{const i=B.freezeTotalWidth();lt.height)v.move({top:m+s-t.height-1});else{const i=B.freezeTotalHeight();c0&&(h-=1):v==="right"?(t!==h&&(h=t),h0&&(c-=1):v==="down"?(s!==c&&(c=s),cs.indexWidth&&e>h.height){d.hide(),m.hide();return}const t=l.box(),i=c.getCellRectByXY(B.offsetX,B.offsetY);i.ri>=0&&i.ci===-1?(i.width=s.indexWidth,d.show(i,{width:t.width}),h.isHide(i.ri-1)?d.showUnhide(i.ri):d.hideUnhide()):d.hide(),i.ri===-1&&i.ci>=0?(i.height=h.height,m.show(i,{height:t.height}),s.isHide(i.ci-1)?m.showUnhide(i.ci):m.hideUnhide()):m.hide()}function cb(B){const{verticalScrollbar:v,horizontalScrollbar:e,data:d}=this,{top:m}=v.scroll(),{left:l}=e.scroll(),{rows:c,cols:h}=d,{deltaY:s,deltaX:t}=B,i=(g,b)=>{let u=g,w=0;do w=b(u),u+=1;while(w<=0);return w},r=g=>{if(g>0){const b=d.scroll.ri+1;if(bc.getHeight(w));v.move({top:m+u-1})}}else{const b=d.scroll.ri-1;if(b>=0){const u=i(b,w=>c.getHeight(w));v.move({top:b===0?0:m-u})}}},n=g=>{if(g>0){const b=d.scroll.ci+1;if(bh.getWidth(w));e.move({left:l+u-1})}}else{const b=d.scroll.ci-1;if(b>=0){const u=i(b,w=>h.getWidth(w));e.move({left:b===0?0:l-u})}}},o=Math.abs(s),f=Math.abs(t),a=Math.max(o,f);/Firefox/i.test(window.navigator.userAgent)&&il(r(B.detail),50),a===f&&il(n(t),50),a===o&&il(r(s),50)}function hb(B,v){const{verticalScrollbar:e,horizontalScrollbar:d}=this,{top:m}=e.scroll(),{left:l}=d.scroll();B==="left"||B==="right"?d.move({left:l-v}):(B==="up"||B==="down")&&e.move({top:m-v})}function kl(){const{data:B,verticalScrollbar:v}=this,{height:e}=this.getTableOffset(),d=B.exceptRowTotalHeight(0,-1);v.set(e,B.rows.totalHeight()-d)}function Ml(){const{data:B,horizontalScrollbar:v}=this,{width:e}=this.getTableOffset();B&&v.set(e,B.cols.totalWidth())}function ub(){const{selector:B,data:v,editor:e}=this,[d,m]=v.freeze;if(d>0||m>0){const l=v.freezeTotalWidth(),c=v.freezeTotalHeight();e.setFreezeLengths(l,c)}B.resetAreaOffset()}function ei(){const{tableEl:B,overlayerEl:v,overlayerCEl:e,table:d,toolbar:m,selector:l,el:c}=this,h=this.getTableOffset(),s=this.getRect();B.attr(s),v.offset(s),e.offset(h),c.css("width",`${s.width}px`),kl.call(this),Ml.call(this),ub.call(this),d.render(),m.reset(),l.reset()}function Ks(){const{data:B,selector:v}=this;B.clearClipboard(),v.hideClipboard()}function bl(){const{data:B,selector:v}=this;B.copy(),B.copyToSystemClipboard(),v.showClipboard()}function Yc(){const{data:B,selector:v}=this;B.cut(),v.showClipboard()}function Us(B,v){const{data:e}=this;if(e.settings.mode!=="read"){if(e.paste(B,d=>Th("Tip",d)))ei.call(this);else if(v){const d=v.clipboardData.getData("text/plain");this.data.pasteFromText(d),ei.call(this)}}}function db(){this.data.hideRowsOrCols(),ei.call(this)}function Zc(B,v){this.data.unhideRowsOrCols(B,v),ei.call(this)}function pb(){const{data:B}=this;B.autofilter(),ei.call(this)}function mb(){const{toolbar:B}=this;B.paintformatActive()&&(Us.call(this,"format"),Ks.call(this),B.paintformatToggle())}function Jc(B){const{selector:v,data:e,table:d,sortFilter:m}=this,{offsetX:l,offsetY:c}=B,h=B.target.className===`${Ze}-selector-corner`,s=e.getCellRectByXY(l,c),{left:t,top:i,width:r,height:n}=s;let{ri:o,ci:f}=s;const{autoFilter:a}=e;if(a.includes(o,f)&&t+r-20e.rows.getCell(b,u));m.hide(),m.set(f,g,a.getFilter(f),a.getSort(f)),m.setOffset({left:t,top:i+n+2});return}B.shiftKey||(h?v.showAutofill(o,f):Fn.call(this,!1,o,f),uh(window,g=>{({ri:o,ci:f}=e.getCellRectByXY(g.offsetX,g.offsetY)),h?v.showAutofill(o,f):g.buttons===1&&!g.shiftKey&&Fn.call(this,!0,o,f,!0,!0)},()=>{h&&v.arange&&e.settings.mode!=="read"&&e.autofill(v.arange,"all",g=>Th("Tip",g))&&d.render(),v.hideAutofill(),mb.call(this)})),!h&&B.buttons===1&&B.shiftKey&&Fn.call(this,!0,o,f)}function Gs(){const{editor:B,data:v}=this,e=v.getSelectedRect(),d=this.getTableOffset();let m="top";e.top>d.height/2&&(m="bottom"),B.setOffset(e,m)}function Xs(){const{editor:B,data:v}=this;v.settings.mode!=="read"&&(Gs.call(this),B.setCell(v.getSelectedCell(),v.getSelectedValidator()),Ks.call(this))}function gb(B){const{data:v,table:e,selector:d}=this;v.scrolly(B,()=>{d.resetBRLAreaOffset(),Gs.call(this),e.render()})}function vb(B){const{data:v,table:e,selector:d}=this;v.scrollx(B,()=>{d.resetBRTAreaOffset(),Gs.call(this),e.render()})}function bb(B,v){const{ri:e}=B,{table:d,selector:m,data:l}=this;l.rows.setHeight(e,v),d.render(),m.resetAreaOffset(),kl.call(this),Gs.call(this)}function yb(B,v){const{ci:e}=B,{table:d,selector:m,data:l}=this;l.cols.setWidth(e,v),d.render(),m.resetAreaOffset(),Ml.call(this),Gs.call(this)}function nl(B,v="finished"){const{data:e,table:d}=this;if(e.settings.mode==="read")return;e.setSelectedCellText(B,v);const{ri:m,ci:l}=e.selector;v==="finished"?d.render():this.trigger("cell-edited",B,m,l)}function za(B){const{data:v}=this;v.settings.mode!=="read"&&(B==="insert-row"?v.insert("row"):B==="delete-row"?v.delete("row"):B==="insert-column"?v.insert("column"):B==="delete-column"?v.delete("column"):B==="delete-cell"?v.deleteCell():B==="delete-cell-format"?v.deleteCell("format"):B==="delete-cell-text"?v.deleteCell("text"):B==="cell-printable"?v.setSelectedCellAttr("printable",!0):B==="cell-non-printable"?v.setSelectedCellAttr("printable",!1):B==="cell-editable"?v.setSelectedCellAttr("editable",!0):B==="cell-non-editable"&&v.setSelectedCellAttr("editable",!1),Ks.call(this),ei.call(this))}function wb(B,v){const{data:e}=this;if(B==="undo")this.undo();else if(B==="redo")this.redo();else if(B==="print")this.print.preview();else if(B==="paintformat")v===!0?bl.call(this):Ks.call(this);else if(B==="clearformat")za.call(this,"delete-cell-format");else if(B!=="link"){if(B!=="chart")if(B==="autofilter")pb.call(this);else if(B==="freeze")if(v){const{ri:d,ci:m}=e.selector;this.freeze(d,m)}else this.freeze(0,0);else e.setSelectedCellAttr(B,v),B==="formula"&&!e.selector.multiple()&&Xs.call(this),ei.call(this)}}function _b(B,v,e,d){this.data.setAutoFilter(B,v,e,d),ei.call(this)}function xb(){const{selector:B,overlayerEl:v,rowResizer:e,colResizer:d,verticalScrollbar:m,horizontalScrollbar:l,editor:c,contextMenu:h,toolbar:s,modalValidation:t,sortFilter:i}=this;v.on("mousemove",r=>{fb.call(this,r)}).on("mousedown",r=>{c.clear(),h.hide(),r.buttons===2?(this.data.xyInSelectedRect(r.offsetX,r.offsetY)||Jc.call(this,r),h.setPosition(r.offsetX,r.offsetY),r.stopPropagation()):r.detail===2?Xs.call(this):Jc.call(this,r)}).on("mousewheel.stop",r=>{cb.call(this,r)}).on("mouseout",r=>{const{offsetX:n,offsetY:o}=r;o<=0&&d.hide(),n<=0&&e.hide()}),B.inputChange=r=>{nl.call(this,r,"input"),Xs.call(this)},Mg(v.el,{move:(r,n)=>{hb.call(this,r,n)}}),s.change=(r,n)=>wb.call(this,r,n),i.ok=(r,n,o,f)=>_b.call(this,r,n,o,f),e.finishedFn=(r,n)=>{bb.call(this,r,n)},d.finishedFn=(r,n)=>{yb.call(this,r,n)},e.unhideFn=r=>{Zc.call(this,"row",r)},d.unhideFn=r=>{Zc.call(this,"col",r)},m.moveFn=(r,n)=>{gb.call(this,r,n)},l.moveFn=(r,n)=>{vb.call(this,r,n)},c.change=(r,n)=>{nl.call(this,n,r)},t.change=(r,...n)=>{r==="save"?this.data.addValidation(...n):this.data.removeValidation()},h.itemClick=r=>{r==="validation"?t.setValue(this.data.getSelectedValidation()):r==="copy"?bl.call(this):r==="cut"?Yc.call(this):r==="paste"?Us.call(this,"all"):r==="paste-value"?Us.call(this,"text"):r==="paste-format"?Us.call(this,"format"):r==="hide"?db.call(this):za.call(this,r)},ti(window,"resize",()=>{this.reload()}),ti(window,"click",r=>{this.focusing=v.contains(r.target)}),ti(window,"paste",r=>{this.focusing&&(Us.call(this,"all",r),r.preventDefault())}),ti(window,"keydown",r=>{if(!this.focusing)return;const n=r.keyCode||r.which,{key:o,ctrlKey:f,shiftKey:a,metaKey:g}=r;if(f||g)switch(n){case 90:this.undo(),r.preventDefault();break;case 89:this.redo(),r.preventDefault();break;case 67:bl.call(this),r.preventDefault();break;case 88:Yc.call(this),r.preventDefault();break;case 85:s.trigger("underline"),r.preventDefault();break;case 86:break;case 37:Hi.call(this,a,"row-first"),r.preventDefault();break;case 38:Hi.call(this,a,"col-first"),r.preventDefault();break;case 39:Hi.call(this,a,"row-last"),r.preventDefault();break;case 40:Hi.call(this,a,"col-last"),r.preventDefault();break;case 32:Fn.call(this,!1,-1,this.data.selector.ci,!1),r.preventDefault();break;case 66:s.trigger("bold");break;case 73:s.trigger("italic");break}else{switch(n){case 32:a&&Fn.call(this,!1,this.data.selector.ri,-1,!1);break;case 27:h.hide(),Ks.call(this);break;case 37:Hi.call(this,a,"left"),r.preventDefault();break;case 38:Hi.call(this,a,"up"),r.preventDefault();break;case 39:Hi.call(this,a,"right"),r.preventDefault();break;case 40:Hi.call(this,a,"down"),r.preventDefault();break;case 9:c.clear(),Hi.call(this,!1,a?"left":"right"),r.preventDefault();break;case 13:c.clear(),Hi.call(this,!1,a?"up":"down"),r.preventDefault();break;case 8:za.call(this,"delete-cell-text"),r.preventDefault();break}o==="Delete"?(za.call(this,"delete-cell-text"),r.preventDefault()):n>=65&&n<=90||n>=48&&n<=57||n>=96&&n<=105||r.key==="="?(nl.call(this,r.key,"input"),Xs.call(this)):n===113&&Xs.call(this)}})}class Sb{constructor(v,e){this.eventMap=Rg();const{view:d,showToolbar:m,showContextmenu:l}=e.settings;this.el=je("div",`${Ze}-sheet`),this.toolbar=new rb(e,d.width,!m),this.print=new uv(e),v.children(this.toolbar.el,this.el,this.print.el),this.data=e,this.tableEl=je("canvas",`${Ze}-table`),this.rowResizer=new Pc(!1,e.rows.height),this.colResizer=new Pc(!0,e.cols.minWidth),this.verticalScrollbar=new Nc(!0),this.horizontalScrollbar=new Nc(!1),this.editor=new Gg(tv,()=>this.getTableOffset(),e.rows.height),this.modalValidation=new sb,this.contextMenu=new gv(()=>this.getRect(),!l),this.selector=new Pg(e),this.overlayerCEl=je("div",`${Ze}-overlayer-content`).children(this.editor.el,this.selector.el),this.overlayerEl=je("div",`${Ze}-overlayer`).child(this.overlayerCEl),this.sortFilter=new ob,this.el.children(this.tableEl,this.overlayerEl.el,this.rowResizer.el,this.colResizer.el,this.verticalScrollbar.el,this.horizontalScrollbar.el,this.contextMenu.el,this.modalValidation.el,this.sortFilter.el),this.table=new fv(this.tableEl.el,e),xb.call(this),ei.call(this),Fn.call(this,!1,0,0)}on(v,e){return this.eventMap.on(v,e),this}trigger(v,...e){const{eventMap:d}=this;d.fire(v,e)}resetData(v){this.editor.clear(),this.data=v,kl.call(this),Ml.call(this),this.toolbar.resetData(v),this.print.resetData(v),this.selector.resetData(v),this.table.resetData(v)}loadData(v){return this.data.setData(v),ei.call(this),this}freeze(v,e){const{data:d}=this;return d.setFreeze(v,e),ei.call(this),this}undo(){this.data.undo(),ei.call(this)}redo(){this.data.redo(),ei.call(this)}reload(){return ei.call(this),this}getRect(){const{data:v}=this;return{width:v.viewWidth(),height:v.viewHeight()}}getTableOffset(){const{rows:v,cols:e}=this.data,{width:d,height:m}=this.getRect();return{width:d-e.indexWidth,height:m-v.height,left:e.indexWidth,top:v.height}}}class Eb extends Wi{constructor(v){const e=new jr("ellipsis");super(e,"auto",!1,"top-left"),this.contentClick=v}reset(v){const e=v.map((d,m)=>je("div",`${Ze}-item`).css("width","150px").css("font-weight","normal").on("click",()=>{this.contentClick(m),this.hide()}).child(d));this.setContentChildren(...e)}setTitle(){}}const Cb=[{key:"delete",title:Wt("contextmenu.deleteSheet")}];function Tb(B){return je("div",`${Ze}-item`).child(B.title()).on("click",()=>{this.itemClick(B.key),this.hide()})}function Ab(){return Cb.map(B=>Tb.call(this,B))}class kb{constructor(){this.el=je("div",`${Ze}-contextmenu`).css("width","160px").children(...Ab.call(this)).hide(),this.itemClick=()=>{}}hide(){const{el:v}=this;v.hide(),vs(v)}setOffset(v){const{el:e}=this;e.offset(v),e.show(),Vs(e)}}class Mb{constructor(v=()=>{},e=()=>{},d=()=>{},m=()=>{}){this.swapFunc=e,this.updateFunc=m,this.dataNames=[],this.activeEl=null,this.deleteEl=null,this.items=[],this.moreEl=new Eb(l=>{this.clickSwap2(this.items[l])}),this.contextMenu=new kb,this.contextMenu.itemClick=d,this.el=je("div",`${Ze}-bottombar`).children(this.contextMenu.el,this.menuEl=je("ul",`${Ze}-menu`).child(je("li","").children(new jr("add").on("click",()=>{v()}),je("span","").child(this.moreEl))))}addItem(v,e){this.dataNames.push(v);const d=je("li",e?"active":"").child(v);d.on("click",()=>{this.clickSwap2(d)}).on("contextmenu",m=>{const{offsetLeft:l,offsetHeight:c}=m.target;this.contextMenu.setOffset({left:l,bottom:c+1}),this.deleteEl=d}).on("dblclick",()=>{const m=d.html(),l=new gs("auto","");l.val(m),l.input.on("blur",({target:c})=>{const{value:h}=c,s=this.dataNames.findIndex(t=>t===m);this.renameItem(s,h)}),d.html("").child(l.el),l.focus()}),e&&this.clickSwap(d),this.items.push(d),this.menuEl.child(d),this.moreEl.reset(this.dataNames)}renameItem(v,e){this.dataNames.splice(v,1,e),this.moreEl.reset(this.dataNames),this.items[v].html("").child(e),this.updateFunc(v,e)}clear(){this.items.forEach(v=>{this.menuEl.removeChild(v.el)}),this.items=[],this.dataNames=[],this.moreEl.reset(this.dataNames)}deleteItem(){const{activeEl:v,deleteEl:e}=this;if(this.items.length>1){const d=this.items.findIndex(m=>m===e);if(this.items.splice(d,1),this.dataNames.splice(d,1),this.menuEl.removeChild(e.el),this.moreEl.reset(this.dataNames),v===e){const[m]=this.items;return this.activeEl=m,this.activeEl.toggle(),[d,0]}return[d,-1]}return[-1]}clickSwap2(v){const e=this.items.findIndex(d=>d===v);this.clickSwap(v),this.activeEl.toggle(),this.swapFunc(e)}clickSwap(v){this.activeEl!==null&&this.activeEl.toggle(),this.activeEl=v}}class Ah{constructor(v,e={}){let d=v;this.options={showBottomBar:!0,...e},this.sheetIndex=1,this.datas=[],typeof v=="string"&&(d=document.querySelector(v)),this.bottombar=this.options.showBottomBar?new Mb(()=>{const l=this.addSheet();this.sheet.resetData(l)},l=>{const c=this.datas[l];this.sheet.resetData(c)},()=>{this.deleteSheet()},(l,c)=>{this.datas[l].name=c}):null,this.data=this.addSheet();const m=je("div",`${Ze}`).on("contextmenu",l=>l.preventDefault());d.appendChild(m.el),this.sheet=new Sb(m,this.data),this.bottombar!==null&&m.child(this.bottombar.el)}addSheet(v,e=!0){const d=v||`sheet${this.sheetIndex}`,m=new kg(d,this.options);return m.change=(...l)=>{this.sheet.trigger("change",...l)},this.datas.push(m),this.bottombar!==null&&this.bottombar.addItem(d,e),this.sheetIndex+=1,m}deleteSheet(){if(this.bottombar===null)return;const[v,e]=this.bottombar.deleteItem();v>=0&&(this.datas.splice(v,1),e>=0&&this.sheet.resetData(this.datas[e]))}loadData(v){const e=Array.isArray(v)?v:[v];if(this.bottombar!==null&&this.bottombar.clear(),this.datas=[],e.length>0)for(let d=0;dv.getData())}cellText(v,e,d,m=0){return this.datas[m].setCellText(v,e,d,"finished"),this}cell(v,e,d=0){return this.datas[d].getCell(v,e)}cellStyle(v,e,d=0){return this.datas[d].getCellStyle(v,e)}reRender(){return this.sheet.table.render(),this}on(v,e){return this.sheet.on(v,e),this}validate(){const{validations:v}=this.data;return v.errors.size<=0}change(v){return this.sheet.on("change",v),this}static locale(v,e){ch(v,e)}}const Rb=(B,v={})=>new Ah(B,v);typeof window<"u"&&(window.x_spreadsheet=Rb,window.x_spreadsheet.locale=(B,v)=>ch(B,v));var kh={exports:{}};(function(B,v){(function(e){B.exports=e()})(function(){return function(){function e(d,m,l){function c(t,i){if(!m[t]){if(!d[t]){var r=typeof Oa=="function"&&Oa;if(!i&&r)return r(t,!0);if(h)return h(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var o=m[t]={exports:{}};d[t][0].call(o.exports,function(f){var a=d[t][1][f];return c(a||f)},o,o.exports,e,d,m,l)}return m[t].exports}for(var h=typeof Oa=="function"&&Oa,s=0;s{const w=this.workbook.addWorksheet(g.sheetName),y=g.dateFormats||["YYYY-MM-DD[T]HH:mm:ssZ","YYYY-MM-DD[T]HH:mm:ss","MM-DD-YYYY","YYYY-MM-DD"],S=g.map||function(I){if(I==="")return null;const P=Number(I);if(!Number.isNaN(P)&&P!==1/0)return P;const F=y.reduce((W,G)=>{if(W)return W;const V=t(I,G,!0);return V.isValid()?V:null},null);if(F)return new Date(F.valueOf());const j=n[I];return j!==void 0?j:I},E=c.parse(g.parserOptions).on("data",I=>{w.addRow(I.map(S))}).on("end",()=>{E.emit("worksheet",w)});E.on("worksheet",b).on("error",u),a.pipe(E)})}createInputStream(){throw new Error("`CSV#createInputStream` is deprecated. You should use `CSV#read` instead. This method will be removed in version 5.0. Please follow upgrade instruction: https://github.com/exceljs/exceljs/blob/master/UPGRADE-4.0.md")}write(a,g){return new Promise((b,u)=>{g=g||{};const w=this.workbook.getWorksheet(g.sheetName||g.sheetId),y=c.format(g.formatterOptions);a.on("finish",()=>{b()}),y.on("error",u),y.pipe(a);const{dateFormat:S,dateUTC:E}=g,I=g.map||(j=>{if(j){if(j.text||j.hyperlink)return j.hyperlink||j.text||"";if(j.formula||j.result)return j.result||"";if(j instanceof Date)return S?E?t.utc(j).format(S):t(j).format(S):E?t.utc(j).format():t(j).format();if(j.error)return j.error;if(typeof j=="object")return JSON.stringify(j)}return j}),P=g.includeEmptyRows===void 0||g.includeEmptyRows;let F=1;w&&w.eachRow((j,W)=>{if(P)for(;F++2&&arguments[2]!==void 0?arguments[2]:0;if(this.worksheet=s,!t)this.nativeCol=0,this.nativeColOff=0,this.nativeRow=0,this.nativeRowOff=0;else if(typeof t=="string"){const r=l.decodeAddress(t);this.nativeCol=r.col+i,this.nativeColOff=0,this.nativeRow=r.row+i,this.nativeRowOff=0}else t.nativeCol!==void 0?(this.nativeCol=t.nativeCol||0,this.nativeColOff=t.nativeColOff||0,this.nativeRow=t.nativeRow||0,this.nativeRowOff=t.nativeRowOff||0):t.col!==void 0?(this.col=t.col+i,this.row=t.row+i):(this.nativeCol=0,this.nativeColOff=0,this.nativeRow=0,this.nativeRowOff=0)}static asInstance(s){return s instanceof c||s==null?s:new c(s)}get col(){return this.nativeCol+Math.min(this.colWidth-1,this.nativeColOff)/this.colWidth}set col(s){this.nativeCol=Math.floor(s),this.nativeColOff=Math.floor((s-this.nativeCol)*this.colWidth)}get row(){return this.nativeRow+Math.min(this.rowHeight-1,this.nativeRowOff)/this.rowHeight}set row(s){this.nativeRow=Math.floor(s),this.nativeRowOff=Math.floor((s-this.nativeRow)*this.rowHeight)}get colWidth(){return this.worksheet&&this.worksheet.getColumn(this.nativeCol+1)&&this.worksheet.getColumn(this.nativeCol+1).isCustomWidth?Math.floor(this.worksheet.getColumn(this.nativeCol+1).width*1e4):64e4}get rowHeight(){return this.worksheet&&this.worksheet.getRow(this.nativeRow+1)&&this.worksheet.getRow(this.nativeRow+1).height?Math.floor(this.worksheet.getRow(this.nativeRow+1).height*1e4):18e4}get model(){return{nativeCol:this.nativeCol,nativeColOff:this.nativeColOff,nativeRow:this.nativeRow,nativeRowOff:this.nativeRowOff}}set model(s){this.nativeCol=s.nativeCol,this.nativeColOff=s.nativeColOff,this.nativeRow=s.nativeRow,this.nativeRowOff=s.nativeRowOff}}d.exports=c},{"../utils/col-cache":19}],3:[function(e,d,m){const l=e("../utils/col-cache"),c=e("../utils/under-dash"),h=e("./enums"),{slideFormula:s}=e("../utils/shared-formula"),t=e("./note");class i{constructor(F,j,W){if(!F||!j)throw new Error("A Cell needs a Row");this._row=F,this._column=j,l.validateAddress(W),this._address=W,this._value=I.create(i.Types.Null,this),this.style=this._mergeStyle(F.style,j.style,{}),this._mergeCount=0}get worksheet(){return this._row.worksheet}get workbook(){return this._row.worksheet.workbook}destroy(){delete this.style,delete this._value,delete this._row,delete this._column,delete this._address}get numFmt(){return this.style.numFmt}set numFmt(F){this.style.numFmt=F}get font(){return this.style.font}set font(F){this.style.font=F}get alignment(){return this.style.alignment}set alignment(F){this.style.alignment=F}get border(){return this.style.border}set border(F){this.style.border=F}get fill(){return this.style.fill}set fill(F){this.style.fill=F}get protection(){return this.style.protection}set protection(F){this.style.protection=F}_mergeStyle(F,j,W){const G=F&&F.numFmt||j&&j.numFmt;G&&(W.numFmt=G);const V=F&&F.font||j&&j.font;V&&(W.font=V);const J=F&&F.alignment||j&&j.alignment;J&&(W.alignment=J);const $=F&&F.border||j&&j.border;$&&(W.border=$);const M=F&&F.fill||j&&j.fill;M&&(W.fill=M);const T=F&&F.protection||j&&j.protection;return T&&(W.protection=T),W}get address(){return this._address}get row(){return this._row.number}get col(){return this._column.number}get $col$row(){return`$${this._column.letter}$${this.row}`}get type(){return this._value.type}get effectiveType(){return this._value.effectiveType}toCsvString(){return this._value.toCsvString()}addMergeRef(){this._mergeCount++}releaseMergeRef(){this._mergeCount--}get isMerged(){return this._mergeCount>0||this.type===i.Types.Merge}merge(F,j){this._value.release(),this._value=I.create(i.Types.Merge,this,F),j||(this.style=F.style)}unmerge(){this.type===i.Types.Merge&&(this._value.release(),this._value=I.create(i.Types.Null,this),this.style=this._mergeStyle(this._row.style,this._column.style,{}))}isMergedTo(F){return this._value.type!==i.Types.Merge?!1:this._value.isMergedTo(F)}get master(){return this.type===i.Types.Merge?this._value.master:this}get isHyperlink(){return this._value.type===i.Types.Hyperlink}get hyperlink(){return this._value.hyperlink}get value(){return this._value.value}set value(F){if(this.type===i.Types.Merge){this._value.master.value=F;return}this._value.release(),this._value=I.create(I.getType(F),this,F)}get note(){return this._comment&&this._comment.note}set note(F){this._comment=new t(F)}get text(){return this._value.toString()}get html(){return c.escapeHtml(this.text)}toString(){return this.text}_upgradeToHyperlink(F){this.type===i.Types.String&&(this._value=I.create(i.Types.Hyperlink,this,{text:this._value.value,hyperlink:F}))}get formula(){return this._value.formula}get result(){return this._value.result}get formulaType(){return this._value.formulaType}get fullAddress(){const{worksheet:F}=this._row;return{sheetName:F.name,address:this.address,row:this.row,col:this.col}}get name(){return this.names[0]}set name(F){this.names=[F]}get names(){return this.workbook.definedNames.getNamesEx(this.fullAddress)}set names(F){const{definedNames:j}=this.workbook;j.removeAllNames(this.fullAddress),F.forEach(W=>{j.addEx(this.fullAddress,W)})}addName(F){this.workbook.definedNames.addEx(this.fullAddress,F)}removeName(F){this.workbook.definedNames.removeEx(this.fullAddress,F)}removeAllNames(){this.workbook.definedNames.removeAllNames(this.fullAddress)}get _dataValidations(){return this.worksheet.dataValidations}get dataValidation(){return this._dataValidations.find(this.address)}set dataValidation(F){this._dataValidations.add(this.address,F)}get model(){const{model:F}=this._value;return F.style=this.style,this._comment&&(F.comment=this._comment.model),F}set model(F){if(this._value.release(),this._value=I.create(F.type,this),this._value.model=F,F.comment)switch(F.comment.type){case"note":this._comment=t.fromModel(F.comment);break}F.style?this.style=F.style:this.style={}}}i.Types=h.ValueType;class r{constructor(F){this.model={address:F.address,type:i.Types.Null}}get value(){return null}set value(F){}get type(){return i.Types.Null}get effectiveType(){return i.Types.Null}get address(){return this.model.address}set address(F){this.model.address=F}toCsvString(){return""}release(){}toString(){return""}}class n{constructor(F,j){this.model={address:F.address,type:i.Types.Number,value:j}}get value(){return this.model.value}set value(F){this.model.value=F}get type(){return i.Types.Number}get effectiveType(){return i.Types.Number}get address(){return this.model.address}set address(F){this.model.address=F}toCsvString(){return this.model.value.toString()}release(){}toString(){return this.model.value.toString()}}class o{constructor(F,j){this.model={address:F.address,type:i.Types.String,value:j}}get value(){return this.model.value}set value(F){this.model.value=F}get type(){return i.Types.String}get effectiveType(){return i.Types.String}get address(){return this.model.address}set address(F){this.model.address=F}toCsvString(){return`"${this.model.value.replace(/"/g,'""')}"`}release(){}toString(){return this.model.value}}class f{constructor(F,j){this.model={address:F.address,type:i.Types.String,value:j}}get value(){return this.model.value}set value(F){this.model.value=F}toString(){return this.model.value.richText.map(F=>F.text).join("")}get type(){return i.Types.RichText}get effectiveType(){return i.Types.RichText}get address(){return this.model.address}set address(F){this.model.address=F}toCsvString(){return`"${this.text.replace(/"/g,'""')}"`}release(){}}class a{constructor(F,j){this.model={address:F.address,type:i.Types.Date,value:j}}get value(){return this.model.value}set value(F){this.model.value=F}get type(){return i.Types.Date}get effectiveType(){return i.Types.Date}get address(){return this.model.address}set address(F){this.model.address=F}toCsvString(){return this.model.value.toISOString()}release(){}toString(){return this.model.value.toString()}}class g{constructor(F,j){this.model={address:F.address,type:i.Types.Hyperlink,text:j?j.text:void 0,hyperlink:j?j.hyperlink:void 0},j&&j.tooltip&&(this.model.tooltip=j.tooltip)}get value(){const F={text:this.model.text,hyperlink:this.model.hyperlink};return this.model.tooltip&&(F.tooltip=this.model.tooltip),F}set value(F){this.model={text:F.text,hyperlink:F.hyperlink},F.tooltip&&(this.model.tooltip=F.tooltip)}get text(){return this.model.text}set text(F){this.model.text=F}get hyperlink(){return this.model.hyperlink}set hyperlink(F){this.model.hyperlink=F}get type(){return i.Types.Hyperlink}get effectiveType(){return i.Types.Hyperlink}get address(){return this.model.address}set address(F){this.model.address=F}toCsvString(){return this.model.hyperlink}release(){}toString(){return this.model.text}}class b{constructor(F,j){this.model={address:F.address,type:i.Types.Merge,master:j?j.address:void 0},this._master=j,j&&j.addMergeRef()}get value(){return this._master.value}set value(F){F instanceof i?(this._master&&this._master.releaseMergeRef(),F.addMergeRef(),this._master=F):this._master.value=F}isMergedTo(F){return F===this._master}get master(){return this._master}get type(){return i.Types.Merge}get effectiveType(){return this._master.effectiveType}get address(){return this.model.address}set address(F){this.model.address=F}toCsvString(){return""}release(){this._master.releaseMergeRef()}toString(){return this.value.toString()}}class u{constructor(F,j){this.cell=F,this.model={address:F.address,type:i.Types.Formula,shareType:j?j.shareType:void 0,ref:j?j.ref:void 0,formula:j?j.formula:void 0,sharedFormula:j?j.sharedFormula:void 0,result:j?j.result:void 0}}_copyModel(F){const j={},W=G=>{const V=F[G];V&&(j[G]=V)};return W("formula"),W("result"),W("ref"),W("shareType"),W("sharedFormula"),j}get value(){return this._copyModel(this.model)}set value(F){this.model=this._copyModel(F)}validate(F){switch(I.getType(F)){case i.Types.Null:case i.Types.String:case i.Types.Number:case i.Types.Date:break;case i.Types.Hyperlink:case i.Types.Formula:default:throw new Error("Cannot process that type of result value")}}get dependencies(){const F=this.formula.match(/([a-zA-Z0-9]+!)?[A-Z]{1,3}\d{1,4}:[A-Z]{1,3}\d{1,4}/g),j=this.formula.replace(/([a-zA-Z0-9]+!)?[A-Z]{1,3}\d{1,4}:[A-Z]{1,3}\d{1,4}/g,"").match(/([a-zA-Z0-9]+!)?[A-Z]{1,3}\d{1,4}/g);return{ranges:F,cells:j}}get formula(){return this.model.formula||this._getTranslatedFormula()}set formula(F){this.model.formula=F}get formulaType(){return this.model.formula?h.FormulaType.Master:this.model.sharedFormula?h.FormulaType.Shared:h.FormulaType.None}get result(){return this.model.result}set result(F){this.model.result=F}get type(){return i.Types.Formula}get effectiveType(){const F=this.model.result;return F==null?h.ValueType.Null:F instanceof String||typeof F=="string"?h.ValueType.String:typeof F=="number"?h.ValueType.Number:F instanceof Date?h.ValueType.Date:F.text&&F.hyperlink?h.ValueType.Hyperlink:F.formula?h.ValueType.Formula:h.ValueType.Null}get address(){return this.model.address}set address(F){this.model.address=F}_getTranslatedFormula(){if(!this._translatedFormula&&this.model.sharedFormula){const{worksheet:F}=this.cell,j=F.findCell(this.model.sharedFormula);this._translatedFormula=j&&s(j.formula,j.address,this.model.address)}return this._translatedFormula}toCsvString(){return`${this.model.result||""}`}release(){}toString(){return this.model.result?this.model.result.toString():""}}class w{constructor(F,j){this.model={address:F.address,type:i.Types.SharedString,value:j}}get value(){return this.model.value}set value(F){this.model.value=F}get type(){return i.Types.SharedString}get effectiveType(){return i.Types.SharedString}get address(){return this.model.address}set address(F){this.model.address=F}toCsvString(){return this.model.value.toString()}release(){}toString(){return this.model.value.toString()}}class y{constructor(F,j){this.model={address:F.address,type:i.Types.Boolean,value:j}}get value(){return this.model.value}set value(F){this.model.value=F}get type(){return i.Types.Boolean}get effectiveType(){return i.Types.Boolean}get address(){return this.model.address}set address(F){this.model.address=F}toCsvString(){return this.model.value?1:0}release(){}toString(){return this.model.value.toString()}}class S{constructor(F,j){this.model={address:F.address,type:i.Types.Error,value:j}}get value(){return this.model.value}set value(F){this.model.value=F}get type(){return i.Types.Error}get effectiveType(){return i.Types.Error}get address(){return this.model.address}set address(F){this.model.address=F}toCsvString(){return this.toString()}release(){}toString(){return this.model.value.error.toString()}}class E{constructor(F,j){this.model={address:F.address,type:i.Types.String,value:JSON.stringify(j),rawValue:j}}get value(){return this.model.rawValue}set value(F){this.model.rawValue=F,this.model.value=JSON.stringify(F)}get type(){return i.Types.String}get effectiveType(){return i.Types.String}get address(){return this.model.address}set address(F){this.model.address=F}toCsvString(){return this.model.value}release(){}toString(){return this.model.value}}const I={getType(P){return P==null?i.Types.Null:P instanceof String||typeof P=="string"?i.Types.String:typeof P=="number"?i.Types.Number:typeof P=="boolean"?i.Types.Boolean:P instanceof Date?i.Types.Date:P.text&&P.hyperlink?i.Types.Hyperlink:P.formula||P.sharedFormula?i.Types.Formula:P.richText?i.Types.RichText:P.sharedString?i.Types.SharedString:P.error?i.Types.Error:i.Types.JSON},types:[{t:i.Types.Null,f:r},{t:i.Types.Number,f:n},{t:i.Types.String,f:o},{t:i.Types.Date,f:a},{t:i.Types.Hyperlink,f:g},{t:i.Types.Formula,f:u},{t:i.Types.Merge,f:b},{t:i.Types.JSON,f:E},{t:i.Types.SharedString,f:w},{t:i.Types.RichText,f},{t:i.Types.Boolean,f:y},{t:i.Types.Error,f:S}].reduce((P,F)=>(P[F.t]=F.f,P),[]),create(P,F,j){const W=this.types[P];if(!W)throw new Error(`Could not create Value of type ${P}`);return new W(F,j)}};d.exports=i},{"../utils/col-cache":19,"../utils/shared-formula":23,"../utils/under-dash":26,"./enums":7,"./note":9}],4:[function(e,d,m){const l=e("../utils/under-dash"),c=e("./enums"),h=e("../utils/col-cache"),s=9;class t{constructor(r,n,o){this._worksheet=r,this._number=n,o!==!1&&(this.defn=o)}get number(){return this._number}get worksheet(){return this._worksheet}get letter(){return h.n2l(this._number)}get isCustomWidth(){return this.width!==void 0&&this.width!==s}get defn(){return{header:this._header,key:this.key,width:this.width,style:this.style,hidden:this.hidden,outlineLevel:this.outlineLevel}}set defn(r){r?(this.key=r.key,this.width=r.width!==void 0?r.width:s,this.outlineLevel=r.outlineLevel,r.style?this.style=r.style:this.style={},this.header=r.header,this._hidden=!!r.hidden):(delete this._header,delete this._key,delete this.width,this.style={},this.outlineLevel=0)}get headers(){return this._header&&this._header instanceof Array?this._header:[this._header]}get header(){return this._header}set header(r){r!==void 0?(this._header=r,this.headers.forEach((n,o)=>{this._worksheet.getCell(o+1,this.number).value=n})):this._header=void 0}get key(){return this._key}set key(r){(this._key&&this._worksheet.getColumnKey(this._key))===this&&this._worksheet.deleteColumnKey(this._key),this._key=r,r&&this._worksheet.setColumnKey(this._key,this)}get hidden(){return!!this._hidden}set hidden(r){this._hidden=r}get outlineLevel(){return this._outlineLevel||0}set outlineLevel(r){this._outlineLevel=r}get collapsed(){return!!(this._outlineLevel&&this._outlineLevel>=this._worksheet.properties.outlineLevelCol)}toString(){return JSON.stringify({key:this.key,width:this.width,headers:this.headers.length?this.headers:void 0})}equivalentTo(r){return this.width===r.width&&this.hidden===r.hidden&&this.outlineLevel===r.outlineLevel&&l.isEqual(this.style,r.style)}get isDefault(){if(this.isCustomWidth||this.hidden||this.outlineLevel)return!1;const r=this.style;return!(r&&(r.font||r.numFmt||r.alignment||r.border||r.fill||r.protection))}get headerCount(){return this.headers.length}eachCell(r,n){const o=this.number;n||(n=r,r=null),this._worksheet.eachRow(r,(f,a)=>{n(f.getCell(o),a)})}get values(){const r=[];return this.eachCell((n,o)=>{n&&n.type!==c.ValueType.Null&&(r[o]=n.value)}),r}set values(r){if(!r)return;const n=this.number;let o=0;r.hasOwnProperty("0")&&(o=1),r.forEach((f,a)=>{this._worksheet.getCell(a+o,n).value=f})}_applyStyle(r,n){return this.style[r]=n,this.eachCell(o=>{o[r]=n}),n}get numFmt(){return this.style.numFmt}set numFmt(r){this._applyStyle("numFmt",r)}get font(){return this.style.font}set font(r){this._applyStyle("font",r)}get alignment(){return this.style.alignment}set alignment(r){this._applyStyle("alignment",r)}get protection(){return this.style.protection}set protection(r){this._applyStyle("protection",r)}get border(){return this.style.border}set border(r){this._applyStyle("border",r)}get fill(){return this.style.fill}set fill(r){this._applyStyle("fill",r)}static toModel(r){const n=[];let o=null;return r&&r.forEach((f,a)=>{f.isDefault?o&&(o=null):!o||!f.equivalentTo(o)?(o={min:a+1,max:a+1,width:f.width!==void 0?f.width:s,style:f.style,isCustomWidth:f.isCustomWidth,hidden:f.hidden,outlineLevel:f.outlineLevel,collapsed:f.collapsed},n.push(o)):o.max=a+1}),n.length?n:void 0}static fromModel(r,n){n=n||[];const o=[];let f=1,a=0;for(n=n.sort(function(g,b){return g.min-b.min});a{o.removeCellEx(n)})}forEach(n){l.each(this.matrixMap,(o,f)=>{o.forEach(a=>{n(f,a)})})}getNames(n){return this.getNamesEx(c.decodeEx(n))}getNamesEx(n){return l.map(this.matrixMap,(o,f)=>o.findCellEx(n)&&f).filter(Boolean)}_explore(n,o){o.mark=!1;const{sheetName:f}=o,a=new s(o.row,o.col,o.row,o.col,f);let g,b;function u(y,S){const E=n.findCellAt(f,y,o.col);return!E||!E.mark?!1:(a[S]=y,E.mark=!1,!0)}for(b=o.row-1;u(b,"top");b--);for(b=o.row+1;u(b,"bottom");b++);function w(y,S){const E=[];for(b=a.top;b<=a.bottom;b++){const I=n.findCellAt(f,b,y);if(I&&I.mark)E.push(I);else return!1}a[S]=y;for(let I=0;I{a.mark=!0});const f=o.map(a=>a.mark&&this._explore(o,a)).filter(Boolean).map(a=>a.$shortRange);return{name:n,ranges:f}}normaliseMatrix(n,o){n.forEachInSheet(o,(f,a,g)=>{f&&(f.row!==a||f.col!==g)&&(f.row=a,f.col=g,f.address=c.n2l(g)+a)})}spliceRows(n,o,f,a){l.each(this.matrixMap,g=>{g.spliceRows(n,o,f,a),this.normaliseMatrix(g,n)})}spliceColumns(n,o,f,a){l.each(this.matrixMap,g=>{g.spliceColumns(n,o,f,a),this.normaliseMatrix(g,n)})}get model(){return l.map(this.matrixMap,(n,o)=>this.getRanges(o,n)).filter(n=>n.ranges.length)}set model(n){const o=this.matrixMap={};n.forEach(f=>{const a=o[f.name]=new h;f.ranges.forEach(g=>{t.test(g.split("!").pop()||"")&&a.addCell(g)})})}}d.exports=i},{"../utils/cell-matrix":18,"../utils/col-cache":19,"../utils/under-dash":26,"./range":10}],7:[function(e,d,m){d.exports={ValueType:{Null:0,Merge:1,Number:2,String:3,Date:4,Hyperlink:5,Formula:6,SharedString:7,RichText:8,Boolean:9,Error:10},FormulaType:{None:0,Master:1,Shared:2},RelationshipType:{None:0,OfficeDocument:1,Worksheet:2,CalcChain:3,SharedStrings:4,Styles:5,Theme:6,Hyperlink:7},DocumentType:{Xlsx:1},ReadingOrder:{LeftToRight:1,RightToLeft:2},ErrorValue:{NotApplicable:"#N/A",Ref:"#REF!",Name:"#NAME?",DivZero:"#DIV/0!",Null:"#NULL!",Value:"#VALUE!",Num:"#NUM!"}}},{}],8:[function(e,d,m){const l=e("../utils/col-cache"),c=e("./anchor");class h{constructor(t,i){this.worksheet=t,this.model=i}get model(){switch(this.type){case"background":return{type:this.type,imageId:this.imageId};case"image":return{type:this.type,imageId:this.imageId,hyperlinks:this.range.hyperlinks,range:{tl:this.range.tl.model,br:this.range.br&&this.range.br.model,ext:this.range.ext,editAs:this.range.editAs}};default:throw new Error("Invalid Image Type")}}set model(t){let{type:i,imageId:r,range:n,hyperlinks:o}=t;if(this.type=i,this.imageId=r,i==="image")if(typeof n=="string"){const f=l.decode(n);this.range={tl:new c(this.worksheet,{col:f.left,row:f.top},-1),br:new c(this.worksheet,{col:f.right,row:f.bottom},0),editAs:"oneCell"}}else this.range={tl:new c(this.worksheet,n.tl,0),br:n.br&&new c(this.worksheet,n.br,0),ext:n.ext,editAs:n.editAs,hyperlinks:o||n.hyperlinks}}}d.exports=h},{"../utils/col-cache":19,"./anchor":2}],9:[function(e,d,m){const l=e("../utils/under-dash");class c{constructor(s){this.note=s}get model(){let s=null;switch(typeof this.note){case"string":s={type:"note",note:{texts:[{text:this.note}]}};break;default:s={type:"note",note:this.note};break}return l.deepMerge({},c.DEFAULT_CONFIGS,s)}set model(s){const{note:t}=s,{texts:i}=t;i.length===1&&Object.keys(i[0]).length===1?this.note=i[0].text:this.note=t}static fromModel(s){const t=new c;return t.model=s,t}}c.DEFAULT_CONFIGS={note:{margins:{insetmode:"auto",inset:[.13,.13,.25,.25]},protection:{locked:"True",lockText:"True"},editAs:"absolute"}},d.exports=c},{"../utils/under-dash":26}],10:[function(e,d,m){const l=e("../utils/col-cache");class c{constructor(){this.decode(arguments)}setTLBR(s,t,i,r,n){if(arguments.length<4){const o=l.decodeAddress(s),f=l.decodeAddress(t);this.model={top:Math.min(o.row,f.row),left:Math.min(o.col,f.col),bottom:Math.max(o.row,f.row),right:Math.max(o.col,f.col),sheetName:i},this.setTLBR(o.row,o.col,f.row,f.col,n)}else this.model={top:Math.min(s,i),left:Math.min(t,r),bottom:Math.max(s,i),right:Math.max(t,r),sheetName:n}}decode(s){switch(s.length){case 5:this.setTLBR(s[0],s[1],s[2],s[3],s[4]);break;case 4:this.setTLBR(s[0],s[1],s[2],s[3]);break;case 3:this.setTLBR(s[0],s[1],s[2]);break;case 2:this.setTLBR(s[0],s[1]);break;case 1:{const t=s[0];if(t instanceof c)this.model={top:t.model.top,left:t.model.left,bottom:t.model.bottom,right:t.model.right,sheetName:t.sheetName};else if(t instanceof Array)this.decode(t);else if(t.top&&t.left&&t.bottom&&t.right)this.model={top:t.top,left:t.left,bottom:t.bottom,right:t.right,sheetName:t.sheetName};else{const i=l.decodeEx(t);i.top?this.model={top:i.top,left:i.left,bottom:i.bottom,right:i.right,sheetName:i.sheetName}:this.model={top:i.row,left:i.col,bottom:i.row,right:i.col,sheetName:i.sheetName}}break}case 0:this.model={top:0,left:0,bottom:0,right:0};break;default:throw new Error(`Invalid number of arguments to _getDimensions() - ${s.length}`)}}get top(){return this.model.top||1}set top(s){this.model.top=s}get left(){return this.model.left||1}set left(s){this.model.left=s}get bottom(){return this.model.bottom||1}set bottom(s){this.model.bottom=s}get right(){return this.model.right||1}set right(s){this.model.right=s}get sheetName(){return this.model.sheetName}set sheetName(s){this.model.sheetName=s}get _serialisedSheetName(){const{sheetName:s}=this.model;return s?/^[a-zA-Z0-9]*$/.test(s)?`${s}!`:`'${s}'!`:""}expand(s,t,i,r){(!this.model.top||sthis.bottom)&&(this.bottom=i),(!this.model.right||r>this.right)&&(this.right=r)}expandRow(s){if(s){const{dimensions:t,number:i}=s;t&&this.expand(i,t.min,i,t.max)}}expandToAddress(s){const t=l.decodeEx(s);this.expand(t.row,t.col,t.row,t.col)}get tl(){return l.n2l(this.left)+this.top}get $t$l(){return`$${l.n2l(this.left)}$${this.top}`}get br(){return l.n2l(this.right)+this.bottom}get $b$r(){return`$${l.n2l(this.right)}$${this.bottom}`}get range(){return`${this._serialisedSheetName+this.tl}:${this.br}`}get $range(){return`${this._serialisedSheetName+this.$t$l}:${this.$b$r}`}get shortRange(){return this.count>1?this.range:this._serialisedSheetName+this.tl}get $shortRange(){return this.count>1?this.$range:this._serialisedSheetName+this.$t$l}get count(){return(1+this.bottom-this.top)*(1+this.right-this.left)}toString(){return this.range}intersects(s){return!(s.sheetName&&this.sheetName&&s.sheetName!==this.sheetName||s.bottomthis.bottom||s.rightthis.right)}contains(s){const t=l.decodeEx(s);return this.containsEx(t)}containsEx(s){return s.sheetName&&this.sheetName&&s.sheetName!==this.sheetName?!1:s.row>=this.top&&s.row<=this.bottom&&s.col>=this.left&&s.col<=this.right}forEachAddress(s){for(let t=this.left;t<=this.right;t++)for(let i=this.top;i<=this.bottom;i++)s(l.encodeAddress(i,t),i,t)}}d.exports=c},{"../utils/col-cache":19}],11:[function(e,d,m){const l=e("../utils/under-dash"),c=e("./enums"),h=e("../utils/col-cache"),s=e("./cell");class t{constructor(r,n){this._worksheet=r,this._number=n,this._cells=[],this.style={},this.outlineLevel=0}get number(){return this._number}get worksheet(){return this._worksheet}commit(){this._worksheet._commitRow(this)}destroy(){delete this._worksheet,delete this._cells,delete this.style}findCell(r){return this._cells[r-1]}getCellEx(r){let n=this._cells[r.col-1];if(!n){const o=this._worksheet.getColumn(r.col);n=new s(this,o,r.address),this._cells[r.col-1]=n}return n}getCell(r){if(typeof r=="string"){const n=this._worksheet.getColumnKey(r);n?r=n.number:r=h.l2n(r)}return this._cells[r-1]||this.getCellEx({address:h.encodeAddress(this._number,r),row:this._number,col:r})}splice(r,n){const o=r+n;for(var f=arguments.length,a=new Array(f>2?f-2:0),g=2;g0)for(w=u;w>=o;w--)y=this._cells[w-1],y?(S=this.getCell(w+b),S.value=y.value,S.style=y.style,S._comment=y._comment):this._cells[w+b-1]=void 0;for(w=0;w{o&&o.type!==c.ValueType.Null&&n(o,f+1)})}addPageBreak(r,n){const o=this._worksheet,f=Math.max(0,r-1)||0,a=Math.max(0,n-1)||16838,g={id:this._number,max:a,man:1};f&&(g.min=f),o.rowBreaks.push(g)}get values(){const r=[];return this._cells.forEach(n=>{n&&n.type!==c.ValueType.Null&&(r[n.col]=n.value)}),r}set values(r){if(this._cells=[],r)if(r instanceof Array){let n=0;r.hasOwnProperty("0")&&(n=1),r.forEach((o,f)=>{o!==void 0&&(this.getCellEx({address:h.encodeAddress(this._number,f+n),row:this._number,col:f+n}).value=o)})}else this._worksheet.eachColumnKey((n,o)=>{r[o]!==void 0&&(this.getCellEx({address:h.encodeAddress(this._number,n.number),row:this._number,col:n.number}).value=r[o])})}get hasValues(){return l.some(this._cells,r=>r&&r.type!==c.ValueType.Null)}get cellCount(){return this._cells.length}get actualCellCount(){let r=0;return this.eachCell(()=>{r++}),r}get dimensions(){let r=0,n=0;return this._cells.forEach(o=>{o&&o.type!==c.ValueType.Null&&((!r||r>o.col)&&(r=o.col),n0?{min:r,max:n}:null}_applyStyle(r,n){return this.style[r]=n,this._cells.forEach(o=>{o&&(o[r]=n)}),n}get numFmt(){return this.style.numFmt}set numFmt(r){this._applyStyle("numFmt",r)}get font(){return this.style.font}set font(r){this._applyStyle("font",r)}get alignment(){return this.style.alignment}set alignment(r){this._applyStyle("alignment",r)}get protection(){return this.style.protection}set protection(r){this._applyStyle("protection",r)}get border(){return this.style.border}set border(r){this._applyStyle("border",r)}get fill(){return this.style.fill}set fill(r){this._applyStyle("fill",r)}get hidden(){return!!this._hidden}set hidden(r){this._hidden=r}get outlineLevel(){return this._outlineLevel||0}set outlineLevel(r){this._outlineLevel=r}get collapsed(){return!!(this._outlineLevel&&this._outlineLevel>=this._worksheet.properties.outlineLevelRow)}get model(){const r=[];let n=0,o=0;return this._cells.forEach(f=>{if(f){const a=f.model;a&&((!n||n>f.col)&&(n=f.col),o{switch(o.type){case s.Types.Merge:break;default:{let f;if(o.address)f=h.decodeAddress(o.address);else if(n){const{row:g}=n,b=n.col+1;f={row:g,col:b,address:h.encodeAddress(g,b),$col$row:`$${h.n2l(b)}$${g}`}}n=f;const a=this.getCellEx(f);a.model=o;break}}}),r.height?this.height=r.height:delete this.height,this.hidden=r.hidden,this.outlineLevel=r.outlineLevel||0,this.style=r.style&&JSON.parse(JSON.stringify(r.style))||{}}}d.exports=t},{"../utils/col-cache":19,"../utils/under-dash":26,"./cell":3,"./enums":7}],12:[function(e,d,m){const l=e("../utils/col-cache");class c{constructor(t,i,r){this.table=t,this.column=i,this.index=r}_set(t,i){this.table.cacheState(),this.column[t]=i}get name(){return this.column.name}set name(t){this._set("name",t)}get filterButton(){return this.column.filterButton}set filterButton(t){this.column.filterButton=t}get style(){return this.column.style}set style(t){this.column.style=t}get totalsRowLabel(){return this.column.totalsRowLabel}set totalsRowLabel(t){this._set("totalsRowLabel",t)}get totalsRowFunction(){return this.column.totalsRowFunction}set totalsRowFunction(t){this._set("totalsRowFunction",t)}get totalsRowResult(){return this.column.totalsRowResult}set totalsRowResult(t){this._set("totalsRowResult",t)}get totalsRowFormula(){return this.column.totalsRowFormula}set totalsRowFormula(t){this._set("totalsRowFormula",t)}}class h{constructor(t,i){this.worksheet=t,i&&(this.table=i,this.validate(),this.store())}getFormula(t){switch(t.totalsRowFunction){case"none":return null;case"average":return`SUBTOTAL(101,${this.table.name}[${t.name}])`;case"countNums":return`SUBTOTAL(102,${this.table.name}[${t.name}])`;case"count":return`SUBTOTAL(103,${this.table.name}[${t.name}])`;case"max":return`SUBTOTAL(104,${this.table.name}[${t.name}])`;case"min":return`SUBTOTAL(105,${this.table.name}[${t.name}])`;case"stdDev":return`SUBTOTAL(106,${this.table.name}[${t.name}])`;case"var":return`SUBTOTAL(107,${this.table.name}[${t.name}])`;case"sum":return`SUBTOTAL(109,${this.table.name}[${t.name}])`;case"custom":return t.totalsRowFormula;default:throw new Error(`Invalid Totals Row Function: ${t.totalsRowFunction}`)}}get width(){return this.table.columns.length}get height(){return this.table.rows.length}get filterHeight(){return this.height+(this.table.headerRow?1:0)}get tableHeight(){return this.filterHeight+(this.table.totalsRow?1:0)}validate(){const{table:t}=this,i=(b,u,w)=>{b[u]===void 0&&(b[u]=w)};i(t,"headerRow",!0),i(t,"totalsRow",!1),i(t,"style",{}),i(t.style,"theme","TableStyleMedium2"),i(t.style,"showFirstColumn",!1),i(t.style,"showLastColumn",!1),i(t.style,"showRowStripes",!1),i(t.style,"showColumnStripes",!1);const r=(b,u)=>{if(!b)throw new Error(u)};r(t.ref,"Table must have ref"),r(t.columns,"Table must have column definitions"),r(t.rows,"Table must have row definitions"),t.tl=l.decodeAddress(t.ref);const{row:n,col:o}=t.tl;r(n>0,"Table must be on valid row"),r(o>0,"Table must be on valid col");const{width:f,filterHeight:a,tableHeight:g}=this;t.autoFilterRef=l.encode(n,o,n+a-1,o+f-1),t.tableRef=l.encode(n,o,n+g-1,o+f-1),t.columns.forEach((b,u)=>{r(b.name,`Column ${u} must have a name`),u===0?i(b,"totalsRowLabel","Total"):(i(b,"totalsRowFunction","none"),b.totalsRowFormula=this.getFormula(b))})}store(){const t=(a,g)=>{g&&Object.keys(g).forEach(b=>{a[b]=g[b]})},{worksheet:i,table:r}=this,{row:n,col:o}=r.tl;let f=0;if(r.headerRow){const a=i.getRow(n+f++);r.columns.forEach((g,b)=>{const{style:u,name:w}=g,y=a.getCell(o+b);y.value=w,t(y,u)})}if(r.rows.forEach(a=>{const g=i.getRow(n+f++);a.forEach((b,u)=>{const w=g.getCell(o+u);w.value=b,t(w,r.columns[u].style)})}),r.totalsRow){const a=i.getRow(n+f++);r.columns.forEach((g,b)=>{const u=a.getCell(o+b);b===0?u.value=g.totalsRowLabel:this.getFormula(g)?u.value={formula:g.totalsRowFormula,result:g.totalsRowResult}:u.value=null,t(u,g.style)})}}load(t){const{table:i}=this,{row:r,col:n}=i.tl;let o=0;if(i.headerRow){const f=t.getRow(r+o++);i.columns.forEach((a,g)=>{const b=f.getCell(n+g);b.value=a.name})}if(i.rows.forEach(f=>{const a=t.getRow(r+o++);f.forEach((g,b)=>{const u=a.getCell(n+b);u.value=g})}),i.totalsRow){const f=t.getRow(r+o++);i.columns.forEach((a,g)=>{const b=f.getCell(n+g);g===0?b.value=a.totalsRowLabel:this.getFormula(a)&&(b.value={formula:a.totalsRowFormula,result:a.totalsRowResult})})}}get model(){return this.table}set model(t){this.table=t}cacheState(){this._cache||(this._cache={ref:this.ref,width:this.width,tableHeight:this.tableHeight})}commit(){if(!this._cache)return;this.validate();const t=l.decodeAddress(this._cache.ref);if(this.ref!==this._cache.ref)for(let i=0;i1&&arguments[1]!==void 0?arguments[1]:1;this.cacheState(),this.table.rows.splice(t,i)}getColumn(t){const i=this.table.columns[t];return new c(this,i,t)}addColumn(t,i,r){this.cacheState(),r===void 0?(this.table.columns.push(t),this.table.rows.forEach((n,o)=>{n.push(i[o])})):(this.table.columns.splice(r,0,t),this.table.rows.forEach((n,o)=>{n.splice(r,0,i[o])}))}removeColumns(t){let i=arguments.length>1&&arguments[1]!==void 0?arguments[1]:1;this.cacheState(),this.table.columns.splice(t,i),this.table.rows.forEach(r=>{r.splice(t,i)})}_assign(t,i,r){this.cacheState(),t[i]=r}get ref(){return this.table.ref}set ref(t){this._assign(this.table,"ref",t)}get name(){return this.table.name}set name(t){this.table.name=t}get displayName(){return this.table.displyName||this.table.name}set displayNamename(t){this.table.displayName=t}get headerRow(){return this.table.headerRow}set headerRow(t){this._assign(this.table,"headerRow",t)}get totalsRow(){return this.table.totalsRow}set totalsRow(t){this._assign(this.table,"totalsRow",t)}get theme(){return this.table.style.name}set theme(t){this.table.style.name=t}get showFirstColumn(){return this.table.style.showFirstColumn}set showFirstColumn(t){this.table.style.showFirstColumn=t}get showLastColumn(){return this.table.style.showLastColumn}set showLastColumn(t){this.table.style.showLastColumn=t}get showRowStripes(){return this.table.style.showRowStripes}set showRowStripes(t){this.table.style.showRowStripes=t}get showColumnStripes(){return this.table.style.showColumnStripes}set showColumnStripes(t){this.table.style.showColumnStripes=t}}d.exports=h},{"../utils/col-cache":19}],13:[function(e,d,m){const l=e("./worksheet"),c=e("./defined-names"),h=e("../xlsx/xlsx"),s=e("../csv/csv");class t{constructor(){this.category="",this.company="",this.created=new Date,this.description="",this.keywords="",this.manager="",this.modified=this.created,this.properties={},this.calcProperties={},this._worksheets=[],this.subject="",this.title="",this.views=[],this.media=[],this._definedNames=new c}get xlsx(){return this._xlsx||(this._xlsx=new h(this)),this._xlsx}get csv(){return this._csv||(this._csv=new s(this)),this._csv}get nextId(){for(let r=1;r(u&&u.orderNo)>b?u.orderNo:b,0),a=Object.assign({},n,{id:o,name:r,orderNo:f+1,workbook:this}),g=new l(a);return this._worksheets[o]=g,g}removeWorksheetEx(r){delete this._worksheets[r.id]}removeWorksheet(r){const n=this.getWorksheet(r);n&&n.destroy()}getWorksheet(r){if(r===void 0)return this._worksheets.find(Boolean);if(typeof r=="number")return this._worksheets[r];if(typeof r=="string")return this._worksheets.find(n=>n&&n.name===r)}get worksheets(){return this._worksheets.slice(1).sort((r,n)=>r.orderNo-n.orderNo).filter(Boolean)}eachSheet(r){this.worksheets.forEach(n=>{r(n,n.id)})}get definedNames(){return this._definedNames}clearThemes(){this._themes=void 0}addImage(r){const n=this.media.length;return this.media.push(Object.assign({},r,{type:"image"})),n}getImage(r){return this.media[r]}get model(){return{creator:this.creator||"Unknown",lastModifiedBy:this.lastModifiedBy||"Unknown",lastPrinted:this.lastPrinted,created:this.created,modified:this.modified,properties:this.properties,worksheets:this.worksheets.map(r=>r.model),sheets:this.worksheets.map(r=>r.model).filter(Boolean),definedNames:this._definedNames.model,views:this.views,company:this.company,manager:this.manager,title:this.title,subject:this.subject,keywords:this.keywords,category:this.category,description:this.description,language:this.language,revision:this.revision,contentStatus:this.contentStatus,themes:this._themes,media:this.media,calcProperties:this.calcProperties}}set model(r){this.creator=r.creator,this.lastModifiedBy=r.lastModifiedBy,this.lastPrinted=r.lastPrinted,this.created=r.created,this.modified=r.modified,this.company=r.company,this.manager=r.manager,this.title=r.title,this.subject=r.subject,this.keywords=r.keywords,this.category=r.category,this.description=r.description,this.language=r.language,this.revision=r.revision,this.contentStatus=r.contentStatus,this.properties=r.properties,this.calcProperties=r.calcProperties,this._worksheets=[],r.worksheets.forEach(n=>{const{id:o,name:f,state:a}=n,g=r.sheets&&r.sheets.findIndex(u=>u.id===o),b=this._worksheets[o]=new l({id:o,name:f,orderNo:g,state:a,workbook:this});b.model=n}),this._definedNames.model=r.definedNames,this.views=r.views,this._themes=r.themes,this.media=r.media||[]}}d.exports=t},{"../csv/csv":1,"../xlsx/xlsx":144,"./defined-names":6,"./worksheet":14}],14:[function(e,d,m){const l=e("../utils/under-dash"),c=e("../utils/col-cache"),h=e("./range"),s=e("./row"),t=e("./column"),i=e("./enums"),r=e("./image"),n=e("./table"),o=e("./data-validations"),f=e("../utils/encryptor"),{copyStyle:a}=e("../utils/copy-style");class g{constructor(u){u=u||{},this._workbook=u.workbook,this.id=u.id,this.orderNo=u.orderNo,this.name=u.name,this.state=u.state||"visible",this._rows=[],this._columns=null,this._keys={},this._merges={},this.rowBreaks=[],this.properties=Object.assign({},{defaultRowHeight:15,dyDescent:55,outlineLevelCol:0,outlineLevelRow:0},u.properties),this.pageSetup=Object.assign({},{margins:{left:.7,right:.7,top:.75,bottom:.75,header:.3,footer:.3},orientation:"portrait",horizontalDpi:4294967295,verticalDpi:4294967295,fitToPage:!!(u.pageSetup&&(u.pageSetup.fitToWidth||u.pageSetup.fitToHeight)&&!u.pageSetup.scale),pageOrder:"downThenOver",blackAndWhite:!1,draft:!1,cellComments:"None",errors:"displayed",scale:100,fitToWidth:1,fitToHeight:1,paperSize:void 0,showRowColHeaders:!1,showGridLines:!1,firstPageNumber:void 0,horizontalCentered:!1,verticalCentered:!1,rowBreaks:null,colBreaks:null},u.pageSetup),this.headerFooter=Object.assign({},{differentFirst:!1,differentOddEven:!1,oddHeader:null,oddFooter:null,evenHeader:null,evenFooter:null,firstHeader:null,firstFooter:null},u.headerFooter),this.dataValidations=new o,this.views=u.views||[],this.autoFilter=u.autoFilter||null,this._media=[],this.sheetProtection=null,this.tables={},this.conditionalFormattings=[]}get name(){return this._name}set name(u){if(u===void 0&&(u=`sheet${this.id}`),this._name!==u){if(typeof u!="string")throw new Error("The name has to be a string.");if(u==="")throw new Error("The name can't be empty.");if(u==="History")throw new Error('The name "History" is protected. Please use a different name.');if(/[*?:/\\[\]]/.test(u))throw new Error(`Worksheet name ${u} cannot include any of the following characters: * ? : \\ / [ ]`);if(/(^')|('$)/.test(u))throw new Error(`The first or last character of worksheet name cannot be a single quotation mark: ${u}`);if(u&&u.length>31&&(console.warn(`Worksheet name ${u} exceeds 31 chars. This will be truncated`),u=u.substring(0,31)),this._workbook._worksheets.find(w=>w&&w.name.toLowerCase()===u.toLowerCase()))throw new Error(`Worksheet name already exists: ${u}`);this._name=u}}get workbook(){return this._workbook}destroy(){this._workbook.removeWorksheetEx(this)}get dimensions(){const u=new h;return this._rows.forEach(w=>{if(w){const y=w.dimensions;y&&u.expand(w.number,y.min,w.number,y.max)}}),u}get columns(){return this._columns}set columns(u){this._headerRowCount=u.reduce((S,E)=>{const I=E.header&&1||E.headers&&E.headers.length||0;return Math.max(S,I)},0);let w=1;const y=this._columns=[];u.forEach(S=>{const E=new t(this,w++,!1);y.push(E),E.defn=S})}getColumnKey(u){return this._keys[u]}setColumnKey(u,w){this._keys[u]=w}deleteColumnKey(u){delete this._keys[u]}eachColumnKey(u){l.each(this._keys,u)}getColumn(u){if(typeof u=="string"){const w=this._keys[u];if(w)return w;u=c.l2n(u)}if(this._columns||(this._columns=[]),u>this._columns.length){let w=this._columns.length+1;for(;w<=u;)this._columns.push(new t(this,w++))}return this._columns[u-1]}spliceColumns(u,w){const S=this._rows.length;for(var E=arguments.length,I=new Array(E>2?E-2:0),P=2;P0)for(let G=0;G{V.push($[G]||null)});const J=this.getRow(G+1);J.splice.apply(J,V)}else this._rows.forEach(G=>{G&&G.splice(u,w)});const F=I.length-w,j=u+w,W=this._columns.length;if(F<0)for(let G=u+I.length;G<=W;G++)this.getColumn(G).defn=this.getColumn(G-F).defn;else if(F>0)for(let G=W;G>=j;G--)this.getColumn(G+F).defn=this.getColumn(G).defn;for(let G=u;G{u=Math.max(u,w.cellCount)}),u}get actualColumnCount(){const u=[];let w=0;return this.eachRow(y=>{y.eachCell(S=>{let{col:E}=S;u[E]||(u[E]=!0,w++)})}),w}_commitRow(){}get _lastRowNumber(){const u=this._rows;let w=u.length;for(;w>0&&u[w-1]===void 0;)w--;return w}get _nextRow(){return this._lastRowNumber+1}get lastRow(){if(this._rows.length)return this._rows[this._rows.length-1]}findRow(u){return this._rows[u-1]}findRows(u,w){return this._rows.slice(u-1,u-1+w)}get rowCount(){return this._lastRowNumber}get actualRowCount(){let u=0;return this.eachRow(()=>{u++}),u}getRow(u){let w=this._rows[u-1];return w||(w=this._rows[u-1]=new s(this,u)),w}getRows(u,w){if(w<1)return;const y=[];for(let S=u;S1&&arguments[1]!==void 0?arguments[1]:"n";const y=this._nextRow,S=this.getRow(y);return S.values=u,this._setStyleOption(y,w[0]==="i"?w:"n"),S}addRows(u){let w=arguments.length>1&&arguments[1]!==void 0?arguments[1]:"n";const y=[];return u.forEach(S=>{y.push(this.addRow(S,w))}),y}insertRow(u,w){let y=arguments.length>2&&arguments[2]!==void 0?arguments[2]:"n";return this.spliceRows(u,0,w),this._setStyleOption(u,y),this.getRow(u)}insertRows(u,w){let y=arguments.length>2&&arguments[2]!==void 0?arguments[2]:"n";if(this.spliceRows(u,0,...w),y!=="n")for(let S=0;S1&&arguments[1]!==void 0?arguments[1]:"n";w[0]==="o"&&this.findRow(u+1)!==void 0?this._copyStyle(u+1,u,w[1]==="+"):w[0]==="i"&&this.findRow(u-1)!==void 0&&this._copyStyle(u-1,u,w[1]==="+")}_copyStyle(u,w){let y=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1;const S=this.getRow(u),E=this.getRow(w);E.style=a(S.style),S.eachCell({includeEmpty:y},(I,P)=>{E.getCell(P).style=a(I.style)}),E.height=S.height}duplicateRow(u,w){let y=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1;const S=this._rows[u-1],E=new Array(w).fill(S.values);this.spliceRows(u+1,y?0:w,...E);for(let I=0;I{P.getCell(j).style=F.style})}}spliceRows(u,w){const y=u+w;for(var S=arguments.length,E=new Array(S>2?S-2:0),I=2;I{V.getCell($).style=J.style}),this._rows[W-1]=void 0}else this._rows[W+F-1]=void 0;else if(F>0)for(W=j;W>=y;W--)if(G=this._rows[W-1],G){const V=this.getRow(W+F);V.values=G.values,V.style=G.style,V.height=G.height,G.eachCell({includeEmpty:!0},(J,$)=>{if(V.getCell($).style=J.style,J._value.constructor.name==="MergeValue"){const M=this.getRow(J._row._number+P).getCell($),T=J._value._master,x=this.getRow(T._row._number+P).getCell(T._column._number);M.merge(x)}})}else this._rows[W+F-1]=void 0;for(W=0;W{y&&y.hasValues&&w(y,y.number)})}getSheetValues(){const u=[];return this._rows.forEach(w=>{w&&(u[w.number]=w.values)}),u}findCell(u,w){const y=c.getAddress(u,w),S=this._rows[y.row-1];return S?S.findCell(y.col):void 0}getCell(u,w){const y=c.getAddress(u,w);return this.getRow(y.row).getCellEx(y)}mergeCells(){for(var u=arguments.length,w=new Array(u),y=0;y{if(S.intersects(u))throw new Error("Cannot merge already merged cells")});const y=this.getCell(u.top,u.left);for(let S=u.top;S<=u.bottom;S++)for(let E=u.left;E<=u.right;E++)(S>u.top||E>u.left)&&this.getCell(S,E).merge(y,w);this._merges[y.address]=u}_unMergeMaster(u){const w=this._merges[u.address];if(w){for(let y=w.top;y<=w.bottom;y++)for(let S=w.left;S<=w.right;S++)this.getCell(y,S).unmerge();delete this._merges[u.address]}}get hasMerges(){return l.some(this._merges,Boolean)}unMergeCells(){for(var u=arguments.length,w=new Array(u),y=0;y3&&arguments[3]!==void 0?arguments[3]:"shared";const E=c.decode(u),{top:I,left:P,bottom:F,right:j}=E,W=j-P+1,G=c.encodeAddress(I,P),V=S==="shared";let J;typeof y=="function"?J=y:Array.isArray(y)?Array.isArray(y[0])?J=(M,T)=>y[M-I][T-P]:J=(M,T)=>y[(M-I)*W+(T-P)]:J=()=>{};let $=!0;for(let M=I;M<=F;M++)for(let T=P;T<=j;T++)$?(this.getCell(M,T).value={shareType:S,formula:w,ref:u,result:J(M,T)},$=!1):this.getCell(M,T).value=V?{sharedFormula:G,result:J(M,T)}:J(M,T)}addImage(u,w){const y={type:"image",imageId:u,range:w};this._media.push(new r(this,y))}getImages(){return this._media.filter(u=>u.type==="image")}addBackgroundImage(u){const w={type:"background",imageId:u};this._media.push(new r(this,w))}getBackgroundImageId(){const u=this._media.find(w=>w.type==="background");return u&&u.imageId}protect(u,w){return new Promise(y=>{this.sheetProtection={sheet:!0},w&&"spinCount"in w&&(w.spinCount=Number.isFinite(w.spinCount)?Math.round(Math.max(0,w.spinCount)):1e5),u&&(this.sheetProtection.algorithmName="SHA-512",this.sheetProtection.saltValue=f.randomBytes(16).toString("base64"),this.sheetProtection.spinCount=w&&"spinCount"in w?w.spinCount:1e5,this.sheetProtection.hashValue=f.convertPasswordToHash(u,"SHA512",this.sheetProtection.saltValue,this.sheetProtection.spinCount)),w&&(this.sheetProtection=Object.assign(this.sheetProtection,w),!u&&"spinCount"in w&&delete this.sheetProtection.spinCount),y()})}unprotect(){this.sheetProtection=null}addTable(u){const w=new n(this,u);return this.tables[u.name]=w,w}getTable(u){return this.tables[u]}removeTable(u){delete this.tables[u]}getTables(){return Object.values(this.tables)}addConditionalFormatting(u){this.conditionalFormattings.push(u)}removeConditionalFormatting(u){typeof u=="number"?this.conditionalFormattings.splice(u,1):u instanceof Function?this.conditionalFormattings=this.conditionalFormattings.filter(u):this.conditionalFormattings=[]}get tabColor(){return console.trace("worksheet.tabColor property is now deprecated. Please use worksheet.properties.tabColor"),this.properties.tabColor}set tabColor(u){console.trace("worksheet.tabColor property is now deprecated. Please use worksheet.properties.tabColor"),this.properties.tabColor=u}get model(){const u={id:this.id,name:this.name,dataValidations:this.dataValidations.model,properties:this.properties,state:this.state,pageSetup:this.pageSetup,headerFooter:this.headerFooter,rowBreaks:this.rowBreaks,views:this.views,autoFilter:this.autoFilter,media:this._media.map(S=>S.model),sheetProtection:this.sheetProtection,tables:Object.values(this.tables).map(S=>S.model),conditionalFormattings:this.conditionalFormattings};u.cols=t.toModel(this.columns);const w=u.rows=[],y=u.dimensions=new h;return this._rows.forEach(S=>{const E=S&&S.model;E&&(y.expand(E.number,E.min,E.number,E.max),w.push(E))}),u.merges=[],l.each(this._merges,S=>{u.merges.push(S.range)}),u}_parseRows(u){this._rows=[],u.rows.forEach(w=>{const y=new s(this,w.number);this._rows[y.number-1]=y,y.model=w})}_parseMergeCells(u){l.each(u.mergeCells,w=>{this.mergeCellsWithoutStyle(w)})}set model(u){this.name=u.name,this._columns=t.fromModel(this,u.cols),this._parseRows(u),this._parseMergeCells(u),this.dataValidations=new o(u.dataValidations),this.properties=u.properties,this.pageSetup=u.pageSetup,this.headerFooter=u.headerFooter,this.views=u.views,this.autoFilter=u.autoFilter,this._media=u.media.map(w=>new r(this,w)),this.sheetProtection=u.sheetProtection,this.tables=u.tables.reduce((w,y)=>{const S=new n;return S.model=y,w[y.name]=S,w},{}),this.conditionalFormattings=u.conditionalFormattings}}d.exports=g},{"../utils/col-cache":19,"../utils/copy-style":20,"../utils/encryptor":21,"../utils/under-dash":26,"./column":4,"./data-validations":5,"./enums":7,"./image":8,"./range":10,"./row":11,"./table":12}],15:[function(e,d,m){e("core-js/modules/es.promise"),e("core-js/modules/es.promise.finally"),e("core-js/modules/es.object.assign"),e("core-js/modules/es.object.keys"),e("core-js/modules/es.object.values"),e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.async-iterator"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.find-index"),e("core-js/modules/es.array.find"),e("core-js/modules/es.string.from-code-point"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.number.is-nan"),e("regenerator-runtime/runtime");const l={Workbook:e("./doc/workbook")},c=e("./doc/enums");Object.keys(c).forEach(h=>{l[h]=c[h]}),d.exports=l},{"./doc/enums":7,"./doc/workbook":13,"core-js/modules/es.array.find":359,"core-js/modules/es.array.find-index":358,"core-js/modules/es.array.includes":360,"core-js/modules/es.array.iterator":361,"core-js/modules/es.number.is-nan":363,"core-js/modules/es.object.assign":364,"core-js/modules/es.object.keys":366,"core-js/modules/es.object.values":367,"core-js/modules/es.promise":372,"core-js/modules/es.promise.finally":371,"core-js/modules/es.string.from-code-point":376,"core-js/modules/es.string.includes":377,"core-js/modules/es.symbol":381,"core-js/modules/es.symbol.async-iterator":378,"regenerator-runtime/runtime":492}],16:[function(e,d,m){const l=typeof TextDecoder>"u"?null:new TextDecoder("utf-8");function c(h){return typeof h=="string"?h:l?l.decode(h):h.toString()}m.bufferToString=c},{}],17:[function(e,d,m){const l=typeof TextEncoder>"u"?null:new TextEncoder("utf-8"),{Buffer:c}=e("buffer");function h(s){return typeof s!="string"?s:l?c.from(l.encode(s).buffer):c.from(s)}m.stringToBuffer=h},{buffer:220}],18:[function(e,d,m){const l=e("./under-dash"),c=e("./col-cache");class h{constructor(t){this.template=t,this.sheets={}}addCell(t){this.addCellEx(c.decodeEx(t))}getCell(t){return this.findCellEx(c.decodeEx(t),!0)}findCell(t){return this.findCellEx(c.decodeEx(t),!1)}findCellAt(t,i,r){const n=this.sheets[t],o=n&&n[i];return o&&o[r]}addCellEx(t){if(t.top)for(let i=t.top;i<=t.bottom;i++)for(let r=t.left;r<=t.right;r++)this.getCellAt(t.sheetName,i,r);else this.findCellEx(t,!0)}getCellEx(t){return this.findCellEx(t,!0)}findCellEx(t,i){const r=this.findSheet(t,i),n=this.findSheetRow(r,t,i);return this.findRowCell(n,t,i)}getCellAt(t,i,r){const n=this.sheets[t]||(this.sheets[t]=[]),o=n[i]||(n[i]=[]);return o[r]||(o[r]={sheetName:t,address:c.n2l(r)+i,row:i,col:r})}removeCellEx(t){const i=this.findSheet(t);if(!i)return;const r=this.findSheetRow(i,t);r&&delete r[t.col]}forEachInSheet(t,i){const r=this.sheets[t];r&&r.forEach((n,o)=>{n&&n.forEach((f,a)=>{f&&i(f,o,a)})})}forEach(t){l.each(this.sheets,(i,r)=>{this.forEachInSheet(r,t)})}map(t){const i=[];return this.forEach(r=>{i.push(t(r))}),i}findSheet(t,i){const r=t.sheetName;if(this.sheets[r])return this.sheets[r];if(i)return this.sheets[r]=[]}findSheetRow(t,i,r){const{row:n}=i;if(t&&t[n])return t[n];if(r)return t[n]=[]}findRowCell(t,i,r){const{col:n}=i;if(t&&t[n])return t[n];if(r)return t[n]=this.template?Object.assign(i,JSON.parse(JSON.stringify(this.template))):i}spliceRows(t,i,r,n){const o=this.sheets[t];if(o){const f=[];for(let a=0;a{a.splice(i,r,...f)})}}}d.exports=h},{"./col-cache":19,"./under-dash":26}],19:[function(e,d,m){const l=/^[A-Z]+\d+$/,c={_dictionary:["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"],_l2nFill:0,_l2n:{},_n2l:[],_level(h){return h<=26?1:h<=676?2:3},_fill(h){let s,t,i,r,n,o=1;if(h>=4)throw new Error("Out of bounds. Excel supports columns from 1 to 16384");if(this._l2nFill<1&&h>=1){for(;o<=26;)s=this._dictionary[o-1],this._n2l[o]=s,this._l2n[s]=o,o++;this._l2nFill=1}if(this._l2nFill<2&&h>=2){for(o=27;o<=702;)t=o-27,i=t%26,r=Math.floor(t/26),s=this._dictionary[r]+this._dictionary[i],this._n2l[o]=s,this._l2n[s]=o,o++;this._l2nFill=2}if(this._l2nFill<3&&h>=3){for(o=703;o<=16384;)t=o-703,i=t%26,r=Math.floor(t/26)%26,n=Math.floor(t/676),s=this._dictionary[n]+this._dictionary[r]+this._dictionary[i],this._n2l[o]=s,this._l2n[s]=o,o++;this._l2nFill=3}},l2n(h){if(this._l2n[h]||this._fill(h.length),!this._l2n[h])throw new Error(`Out of bounds. Invalid column letter: ${h}`);return this._l2n[h]},n2l(h){if(h<1||h>16384)throw new Error(`${h} is out of bounds. Excel supports columns from 1 to 16384`);return this._n2l[h]||this._fill(this._level(h)),this._n2l[h]},_hash:{},validateAddress(h){if(!l.test(h))throw new Error(`Invalid Address: ${h}`);return!0},decodeAddress(h){const s=h.length<5&&this._hash[h];if(s)return s;let t=!1,i="",r=0,n=!1,o="",f=0;for(let g=0,b;g=65&&b<=90)t=!0,i+=h[g],r=r*26+b-64;else if(b>=48&&b<=57)n=!0,o+=h[g],f=f*10+b-48;else if(n&&t&&b!==36)break;if(!t)r=void 0;else if(r>16384)throw new Error(`Out of bounds. Invalid column letter: ${i}`);n||(f=void 0),h=i+o;const a={address:h,col:r,row:f,$col$row:`$${i}$${o}`};return r<=100&&f<=100&&(this._hash[h]=a,this._hash[a.$col$row]=a),a},getAddress(h,s){if(s){const t=this.n2l(s)+h;return this.decodeAddress(t)}return this.decodeAddress(h)},decode(h){const s=h.split(":");if(s.length===2){const t=this.decodeAddress(s[0]),i=this.decodeAddress(s[1]),r={top:Math.min(t.row,i.row),left:Math.min(t.col,i.col),bottom:Math.max(t.row,i.row),right:Math.max(t.col,i.col)};return r.tl=this.n2l(r.left)+r.top,r.br=this.n2l(r.right)+r.bottom,r.dimensions=`${r.tl}:${r.br}`,r}return this.decodeAddress(h)},decodeEx(h){const s=h.match(/(?:(?:(?:'((?:[^']|'')*)')|([^'^ !]*))!)?(.*)/),t=s[1]||s[2],i=s[3],r=i.split(":");if(r.length>1){let o=this.decodeAddress(r[0]),f=this.decodeAddress(r[1]);const a=Math.min(o.row,f.row),g=Math.min(o.col,f.col),b=Math.max(o.row,f.row),u=Math.max(o.col,f.col);return o=this.n2l(g)+a,f=this.n2l(u)+b,{top:a,left:g,bottom:b,right:u,sheetName:t,tl:{address:o,col:g,row:a,$col$row:`$${this.n2l(g)}$${a}`,sheetName:t},br:{address:f,col:u,row:b,$col$row:`$${this.n2l(u)}$${b}`,sheetName:t},dimensions:`${o}:${f}`}}if(i.startsWith("#"))return t?{sheetName:t,error:i}:{error:i};const n=this.decodeAddress(i);return t?{sheetName:t,...n}:n},encodeAddress(h,s){return c.n2l(s)+h},encode(){switch(arguments.length){case 2:return c.encodeAddress(arguments[0],arguments[1]);case 4:return`${c.encodeAddress(arguments[0],arguments[1])}:${c.encodeAddress(arguments[2],arguments[3])}`;default:throw new Error("Can only encode with 2 or 4 arguments")}},inRange(h,s){const[t,i,,r,n]=h,[o,f]=s;return o>=t&&o<=r&&f>=i&&f<=n}};d.exports=c},{}],20:[function(e,d,m){const l=(t,i)=>({...t,...i.reduce((r,n)=>(t[n]&&(r[n]={...t[n]}),r),{})}),c=function(t,i,r){let n=arguments.length>3&&arguments[3]!==void 0?arguments[3]:[];t[r]&&(i[r]=l(t[r],n))},h=t=>Object.keys(t).length===0,s=t=>{if(!t)return t;if(h(t))return{};const i={...t};return c(t,i,"font",["color"]),c(t,i,"alignment"),c(t,i,"protection"),t.border&&(c(t,i,"border"),c(t.border,i.border,"top",["color"]),c(t.border,i.border,"left",["color"]),c(t.border,i.border,"bottom",["color"]),c(t.border,i.border,"right",["color"]),c(t.border,i.border,"diagonal",["color"])),t.fill&&(c(t,i,"fill",["fgColor","bgColor","center"]),t.fill.stops&&(i.fill.stops=t.fill.stops.map(r=>l(r,["color"])))),i};m.copyStyle=s},{}],21:[function(e,d,m){(function(l){(function(){const c=e("crypto"),h={hash(s){const t=c.createHash(s);for(var i=arguments.length,r=new Array(i>1?i-1:0),n=1;n{i=n});let r=[];t.on("opentag",n=>r.push({eventType:"opentag",value:n})),t.on("text",n=>r.push({eventType:"text",value:n})),t.on("closetag",n=>r.push({eventType:"closetag",value:n}));for await(const n of s){if(t.write(h(n)),i)throw i;yield r,r=[]}}},{"./browser-buffer-decode":16,"readable-stream":491,saxes:496}],23:[function(e,d,m){const l=e("./col-cache"),c=/(([a-z_\-0-9]*)!)?([a-z0-9_$]{2,})([(])?/gi,h=/^([$])?([a-z]+)([$])?([1-9][0-9]*)$/i;function s(t,i,r){const n=l.decode(i),o=l.decode(r);return t.replace(c,(f,a,g,b,u)=>{if(u)return f;const w=h.exec(b);if(w){const y=w[1],S=w[2].toUpperCase(),E=w[3],I=w[4];if(S.length>3||S.length===3&&S>"XFD")return f;let P=l.l2n(S),F=parseInt(I,10);return y||(P+=o.col-n.col),E||(F+=o.row-n.row),(a||"")+(y||"")+l.n2l(P)+(E||"")+F}return f})}d.exports={slideFormula:s}},{"./col-cache":19}],24:[function(e,d,m){(function(l,c){(function(){const h=e("readable-stream"),s=e("./utils"),t=e("./string-buf");class i{constructor(g,b){this._data=g,this._encoding=b}get length(){return this.toBuffer().length}copy(g,b,u,w){return this.toBuffer().copy(g,b,u,w)}toBuffer(){return this._buffer||(this._buffer=c.from(this._data,this._encoding)),this._buffer}}class r{constructor(g){this._data=g}get length(){return this._data.length}copy(g,b,u,w){return this._data._buf.copy(g,b,u,w)}toBuffer(){return this._data.toBuffer()}}class n{constructor(g){this._data=g}get length(){return this._data.length}copy(g,b,u,w){this._data.copy(g,b,u,w)}toBuffer(){return this._data}}class o{constructor(g){this.size=g,this.buffer=c.alloc(g),this.iRead=0,this.iWrite=0}toBuffer(){if(this.iRead===0&&this.iWrite===this.size)return this.buffer;const g=c.alloc(this.iWrite-this.iRead);return this.buffer.copy(g,0,this.iRead,this.iWrite),g}get length(){return this.iWrite-this.iRead}get eod(){return this.iRead===this.iWrite}get full(){return this.iWrite===this.size}read(g){let b;return g===0?null:g===void 0||g>=this.length?(b=this.toBuffer(),this.iRead=this.iWrite,b):(b=c.alloc(g),this.buffer.copy(b,0,this.iRead,g),this.iRead+=g,b)}write(g,b,u){const w=Math.min(u,this.size-this.iWrite);return g.copy(this.buffer,this.iWrite,b,b+w),this.iWrite+=w,w}}const f=function(a){a=a||{},this.bufSize=a.bufSize||1024*1024,this.buffers=[],this.batch=a.batch||!1,this.corked=!1,this.inPos=0,this.outPos=0,this.pipes=[],this.paused=!1,this.encoding=null};s.inherits(f,h.Duplex,{toBuffer(){switch(this.buffers.length){case 0:return null;case 1:return this.buffers[0].toBuffer();default:return c.concat(this.buffers.map(a=>a.toBuffer()))}},_getWritableBuffer(){if(this.buffers.length){const g=this.buffers[this.buffers.length-1];if(!g.full)return g}const a=new o(this.bufSize);return this.buffers.push(a),a},async _pipe(a){const g=function(b){return new Promise(u=>{b.write(a.toBuffer(),()=>{u()})})};await Promise.all(this.pipes.map(g))},_writeToBuffers(a){let g=0;const b=a.length;for(;g1;)this._pipe(this.buffers.shift());else this.corked?(this._writeToBuffers(u),l.nextTick(b)):(await this._pipe(u),b());else this.paused||this.emit("data",u.toBuffer()),this._writeToBuffers(u),this.emit("readable");return!0},cork(){this.corked=!0},_flush(){if(this.pipes.length)for(;this.buffers.length;)this._pipe(this.buffers.shift())},uncork(){this.corked=!1,this._flush()},end(a,g,b){const u=w=>{w?b(w):(this._flush(),this.pipes.forEach(y=>{y.end()}),this.emit("finish"))};a?this.write(a,g,u):u()},read(a){let g;if(a){for(g=[];a&&this.buffers.length&&!this.buffers[0].eod;){const b=this.buffers[0],u=b.read(a);a-=u.length,g.push(u),b.eod&&b.full&&this.buffers.shift()}return c.concat(g)}return g=this.buffers.map(b=>b.toBuffer()).filter(Boolean),this.buffers=[],c.concat(g)},setEncoding(a){this.encoding=a},pause(){this.paused=!0},resume(){this.paused=!1},isPaused(){return!!this.paused},pipe(a){this.pipes.push(a),!this.paused&&this.buffers.length&&this.end()},unpipe(a){this.pipes=this.pipes.filter(g=>g!==a)},unshift(){throw new Error("Not Implemented")},wrap(){throw new Error("Not Implemented")}}),d.exports=f}).call(this)}).call(this,e("_process"),e("buffer").Buffer)},{"./string-buf":25,"./utils":27,_process:467,buffer:220,"readable-stream":491}],25:[function(e,d,m){(function(l){(function(){class c{constructor(s){this._buf=l.alloc(s&&s.size||16384),this._encoding=s&&s.encoding||"utf8",this._inPos=0,this._buffer=void 0}get length(){return this._inPos}get capacity(){return this._buf.length}get buffer(){return this._buf}toBuffer(){return this._buffer||(this._buffer=l.alloc(this.length),this._buf.copy(this._buffer,0,0,this.length)),this._buffer}reset(s){s=s||0,this._buffer=void 0,this._inPos=s}_grow(s){let t=this._buf.length*2;for(;t=this._buf.length-4;)this._grow(this._inPos+s.length),t=this._inPos+this._buf.write(s,this._inPos,this._encoding);this._inPos=t}addStringBuf(s){s.length&&(this._buffer=void 0,this.length+s.length>this.capacity&&this._grow(this.length+s.length),s._buf.copy(this._buf,this._inPos,0,s.length),this._inPos+=s.length)}}d.exports=c}).call(this)}).call(this,e("buffer").Buffer)},{buffer:220}],26:[function(e,d,m){const{toString:l}=Object.prototype,c=/["&<>]/,h={each:function(t,i){t&&(Array.isArray(t)?t.forEach(i):Object.keys(t).forEach(r=>{i(t[r],r)}))},some:function(t,i){return t?Array.isArray(t)?t.some(i):Object.keys(t).some(r=>i(t[r],r)):!1},every:function(t,i){return t?Array.isArray(t)?t.every(i):Object.keys(t).every(r=>i(t[r],r)):!0},map:function(t,i){return t?Array.isArray(t)?t.map(i):Object.keys(t).map(r=>i(t[r],r)):[]},keyBy(s,t){return s.reduce((i,r)=>(i[r[t]]=r,i),{})},isEqual:function(t,i){const r=typeof t,n=typeof i,o=Array.isArray(t),f=Array.isArray(i);let a;if(r!==n)return!1;switch(typeof t){case"object":if(o||f)return o&&f?t.length===i.length&&t.every((g,b)=>{const u=i[b];return h.isEqual(g,u)}):!1;if(t===null||i===null)return t===i;if(a=Object.keys(t),Object.keys(i).length!==a.length)return!1;for(const g of a)if(!i.hasOwnProperty(g))return!1;return h.every(t,(g,b)=>{const u=i[b];return h.isEqual(g,u)});default:return t===i}},escapeHtml(s){const t=c.exec(s);if(!t)return s;let i="",r="",n=0,o=t.index;for(;o":r=">";break;default:continue}n!==o&&(i+=s.substring(n,o)),n=o+1,i+=r}return n!==o?i+s.substring(n,o):i},strcmp(s,t){return st?1:0},isUndefined(s){return l.call(s)==="[object Undefined]"},isObject(s){return l.call(s)==="[object Object]"},deepMerge(){const s=arguments[0]||{},{length:t}=arguments;let i,r,n;function o(f,a){i=s[a],n=Array.isArray(f),h.isObject(f)||n?(n?(n=!1,r=i&&Array.isArray(i)?i:[]):r=i&&h.isObject(i)?i:{},s[a]=h.deepMerge(r,f)):h.isUndefined(f)||(s[a]=f)}for(let f=0;f{Object.defineProperty(r,g,Object.getOwnPropertyDescriptor(o,g))});const a={constructor:{value:r,enumerable:!1,writable:!1,configurable:!0}};f&&Object.keys(f).forEach(g=>{a[g]=Object.getOwnPropertyDescriptor(f,g)}),r.prototype=Object.create(n.prototype,a)},t=/[<>&'"\x7F\x00-\x08\x0B-\x0C\x0E-\x1F]/,i={nop(){},promiseImmediate(r){return new Promise(n=>{l.setImmediate?c(()=>{n(r)}):setTimeout(()=>{n(r)},1)})},inherits:s,dateToExcel(r,n){return 25569+r.getTime()/(24*3600*1e3)-(n?1462:0)},excelToDate(r,n){const o=Math.round((r-25569+(n?1462:0))*24*3600*1e3);return new Date(o)},parsePath(r){const n=r.lastIndexOf("/");return{path:r.substring(0,n),name:r.substring(n+1)}},getRelsPath(r){const n=i.parsePath(r);return`${n.path}/_rels/${n.name}.rels`},xmlEncode(r){const n=t.exec(r);if(!n)return r;let o="",f="",a=0,g=n.index;for(;g=11&&b!==13)){f="";break}continue}}a!==g&&(o+=r.substring(a,g)),a=g+1,f&&(o+=f)}return a!==g?o+r.substring(a,g):o},xmlDecode(r){return r.replace(/&([a-z]*);/g,n=>{switch(n){case"<":return"<";case">":return">";case"&":return"&";case"'":return"'";case""":return'"';default:return n}})},validInt(r){const n=parseInt(r,10);return Number.isNaN(n)?0:n},isDateFmt(r){return r?(r=r.replace(/\[[^\]]*]/g,""),r=r.replace(/"[^"]*"/g,""),r.match(/[ymdhMsb]+/)!==null):!1},fs:{exists(r){return new Promise(n=>{h.access(r,h.constants.F_OK,o=>{n(!o)})})}},toIsoDateString(r){return r.toIsoString().subsstr(0,10)},parseBoolean(r){return r===!0||r==="true"||r===1||r==="1"}};d.exports=i}).call(this)}).call(this,typeof Dt<"u"?Dt:typeof self<"u"?self:typeof window<"u"?window:{},e("timers").setImmediate)},{fs:216,timers:523}],28:[function(e,d,m){const l=e("./under-dash"),c=e("./utils"),h="<",s=">",t="";function r(f,a,g){f.push(` ${a}="${c.xmlEncode(g.toString())}"`)}function n(f,a){if(a){const g=[];l.each(a,(b,u)=>{b!==void 0&&r(g,u,b)}),f.push(g.join(""))}}class o{constructor(){this._xml=[],this._stack=[],this._rollbacks=[]}get tos(){return this._stack.length?this._stack[this._stack.length-1]:void 0}get cursor(){return this._xml.length}openXml(a){const g=this._xml;g.push(" +`)}openNode(a,g){const b=this.tos,u=this._xml;b&&this.open&&u.push(s),this._stack.push(a),u.push(h),u.push(a),n(u,g),this.leaf=!0,this.open=!0}addAttribute(a,g){if(!this.open)throw new Error("Cannot write attributes to node if it is not open");g!==void 0&&r(this._xml,a,g)}addAttributes(a){if(!this.open)throw new Error("Cannot write attributes to node if it is not open");n(this._xml,a)}writeText(a){const g=this._xml;this.open&&(g.push(s),this.open=!1),this.leaf=!1,g.push(c.xmlEncode(a.toString()))}writeXml(a){this.open&&(this._xml.push(s),this.open=!1),this.leaf=!1,this._xml.push(a)}closeNode(){const a=this._stack.pop(),g=this._xml;this.leaf?g.push(i):(g.push(t),g.push(a),g.push(s)),this.open=!1,this.leaf=!1}leafNode(a,g,b){this.openNode(a,g),b!==void 0&&this.writeText(b),this.closeNode()}closeAll(){for(;this._stack.length;)this.closeNode()}addRollback(){return this._rollbacks.push({xml:this._xml.length,stack:this._stack.length,leaf:this.leaf,open:this.open}),this.cursor}commit(){this._rollbacks.pop()}rollback(){const a=this._rollbacks.pop();this._xml.length>a.xml&&this._xml.splice(a.xml,this._xml.length-a.xml),this._stack.length>a.stack&&this._stack.splice(a.stack,this._stack.length-a.stack),this.leaf=a.leaf,this.open=a.open}get xml(){return this.closeAll(),this._xml.join("")}}o.StdDocAttributes={version:"1.0",encoding:"UTF-8",standalone:"yes"},d.exports=o},{"./under-dash":26,"./utils":27}],29:[function(e,d,m){(function(l){(function(){const c=e("events"),h=e("jszip"),s=e("./stream-buf"),{stringToBuffer:t}=e("./browser-buffer-encode");class i extends c.EventEmitter{constructor(n){super(),this.options=Object.assign({type:"nodebuffer",compression:"DEFLATE"},n),this.zip=new h,this.stream=new s}append(n,o){o.hasOwnProperty("base64")&&o.base64?this.zip.file(o.name,n,{base64:!0}):(l.browser&&typeof n=="string"&&(n=t(n)),this.zip.file(o.name,n))}async finalize(){const n=await this.zip.generateAsync(this.options);this.stream.end(n),this.emit("finish")}read(n){return this.stream.read(n)}setEncoding(n){return this.stream.setEncoding(n)}pause(){return this.stream.pause()}resume(){return this.stream.resume()}isPaused(){return this.stream.isPaused()}pipe(n,o){return this.stream.pipe(n,o)}unpipe(n){return this.stream.unpipe(n)}unshift(n){return this.stream.unshift(n)}wrap(n){return this.stream.wrap(n)}}d.exports={ZipWriter:i}}).call(this)}).call(this,e("_process"))},{"./browser-buffer-encode":17,"./stream-buf":24,_process:467,events:422,jszip:441}],30:[function(e,d,m){d.exports={0:{f:"General"},1:{f:"0"},2:{f:"0.00"},3:{f:"#,##0"},4:{f:"#,##0.00"},9:{f:"0%"},10:{f:"0.00%"},11:{f:"0.00E+00"},12:{f:"# ?/?"},13:{f:"# ??/??"},14:{f:"mm-dd-yy"},15:{f:"d-mmm-yy"},16:{f:"d-mmm"},17:{f:"mmm-yy"},18:{f:"h:mm AM/PM"},19:{f:"h:mm:ss AM/PM"},20:{f:"h:mm"},21:{f:"h:mm:ss"},22:{f:'m/d/yy "h":mm'},27:{"zh-tw":"[$-404]e/m/d","zh-cn":'yyyy"年"m"月"',"ja-jp":"[$-411]ge.m.d","ko-kr":'yyyy"年" mm"月" dd"日"'},28:{"zh-tw":'[$-404]e"年"m"月"d"日"',"zh-cn":'m"月"d"日"',"ja-jp":'[$-411]ggge"年"m"月"d"日"',"ko-kr":"mm-dd"},29:{"zh-tw":'[$-404]e"年"m"月"d"日"',"zh-cn":'m"月"d"日"',"ja-jp":'[$-411]ggge"年"m"月"d"日"',"ko-kr":"mm-dd"},30:{"zh-tw":"m/d/yy ","zh-cn":"m-d-yy","ja-jp":"m/d/yy","ko-kr":"mm-dd-yy"},31:{"zh-tw":'yyyy"年"m"月"d"日"',"zh-cn":'yyyy"年"m"月"d"日"',"ja-jp":'yyyy"年"m"月"d"日"',"ko-kr":'yyyy"년" mm"월" dd"일"'},32:{"zh-tw":'hh"時"mm"分"',"zh-cn":'h"时"mm"分"',"ja-jp":'h"時"mm"分"',"ko-kr":'h"시" mm"분"'},33:{"zh-tw":'hh"時"mm"分"ss"秒"',"zh-cn":'h"时"mm"分"ss"秒"',"ja-jp":'h"時"mm"分"ss"秒"',"ko-kr":'h"시" mm"분" ss"초"'},34:{"zh-tw":'上午/下午 hh"時"mm"分"',"zh-cn":'上午/下午 h"时"mm"分"',"ja-jp":'yyyy"年"m"月"',"ko-kr":"yyyy-mm-dd"},35:{"zh-tw":'上午/下午 hh"時"mm"分"ss"秒"',"zh-cn":'上午/下午 h"时"mm"分"ss"秒"',"ja-jp":'m"月"d"日"',"ko-kr":"yyyy-mm-dd"},36:{"zh-tw":"[$-404]e/m/d","zh-cn":'yyyy"年"m"月"',"ja-jp":"[$-411]ge.m.d","ko-kr":'yyyy"年" mm"月" dd"日"'},37:{f:"#,##0 ;(#,##0)"},38:{f:"#,##0 ;[Red](#,##0)"},39:{f:"#,##0.00 ;(#,##0.00)"},40:{f:"#,##0.00 ;[Red](#,##0.00)"},45:{f:"mm:ss"},46:{f:"[h]:mm:ss"},47:{f:"mmss.0"},48:{f:"##0.0E+0"},49:{f:"@"},50:{"zh-tw":"[$-404]e/m/d","zh-cn":'yyyy"年"m"月"',"ja-jp":"[$-411]ge.m.d","ko-kr":'yyyy"年" mm"月" dd"日"'},51:{"zh-tw":'[$-404]e"年"m"月"d"日"',"zh-cn":'m"月"d"日"',"ja-jp":'[$-411]ggge"年"m"月"d"日"',"ko-kr":"mm-dd"},52:{"zh-tw":'上午/下午 hh"時"mm"分"',"zh-cn":'yyyy"年"m"月"',"ja-jp":'yyyy"年"m"月"',"ko-kr":"yyyy-mm-dd"},53:{"zh-tw":'上午/下午 hh"時"mm"分"ss"秒"',"zh-cn":'m"月"d"日"',"ja-jp":'m"月"d"日"',"ko-kr":"yyyy-mm-dd"},54:{"zh-tw":'[$-404]e"年"m"月"d"日"',"zh-cn":'m"月"d"日"',"ja-jp":'[$-411]ggge"年"m"月"d"日"',"ko-kr":"mm-dd"},55:{"zh-tw":'上午/下午 hh"時"mm"分"',"zh-cn":'上午/下午 h"时"mm"分"',"ja-jp":'yyyy"年"m"月"',"ko-kr":"yyyy-mm-dd"},56:{"zh-tw":'上午/下午 hh"時"mm"分"ss"秒"',"zh-cn":'上午/下午 h"时"mm"分"ss"秒"',"ja-jp":'m"月"d"日"',"ko-kr":"yyyy-mm-dd"},57:{"zh-tw":"[$-404]e/m/d","zh-cn":'yyyy"年"m"月"',"ja-jp":"[$-411]ge.m.d","ko-kr":'yyyy"年" mm"月" dd"日"'},58:{"zh-tw":'[$-404]e"年"m"月"d"日"',"zh-cn":'m"月"d"日"',"ja-jp":'[$-411]ggge"年"m"月"d"日"',"ko-kr":"mm-dd"},59:{"th-th":"t0"},60:{"th-th":"t0.00"},61:{"th-th":"t#,##0"},62:{"th-th":"t#,##0.00"},67:{"th-th":"t0%"},68:{"th-th":"t0.00%"},69:{"th-th":"t# ?/?"},70:{"th-th":"t# ??/??"},81:{"th-th":"d/m/bb"}}},{}],31:[function(e,d,m){d.exports={OfficeDocument:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",Worksheet:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet",CalcChain:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain",SharedStrings:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings",Styles:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",Theme:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",Hyperlink:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",Image:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",CoreProperties:"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",ExtenderProperties:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",Comments:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",VmlDrawing:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing",Table:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/table"}},{}],32:[function(e,d,m){const l=e("../../utils/parse-sax"),c=e("../../utils/xml-stream");class h{prepare(){}render(){}parseOpen(t){}parseText(t){}parseClose(t){}reconcile(t,i){}reset(){this.model=null,this.map&&Object.values(this.map).forEach(t=>{t instanceof h?t.reset():t.xform&&t.xform.reset()})}mergeModel(t){this.model=Object.assign(this.model||{},t)}async parse(t){for await(const i of t)for(const{eventType:r,value:n}of i)if(r==="opentag")this.parseOpen(n);else if(r==="text")this.parseText(n);else if(r==="closetag"&&!this.parseClose(n.name))return this.model;return this.model}async parseStream(t){return this.parse(l(t))}get xml(){return this.toXml(this.model)}toXml(t){const i=new c;return this.render(i,t),i.xml}static toAttribute(t,i){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1;if(t===void 0){if(r)return i}else if(r||t!==i)return t.toString()}static toStringAttribute(t,i){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1;return h.toAttribute(t,i,r)}static toStringValue(t,i){return t===void 0?i:t}static toBoolAttribute(t,i){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1;if(t===void 0){if(r)return i}else if(r||t!==i)return t?"1":"0"}static toBoolValue(t,i){return t===void 0?i:t==="1"}static toIntAttribute(t,i){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1;return h.toAttribute(t,i,r)}static toIntValue(t,i){return t===void 0?i:parseInt(t,10)}static toFloatAttribute(t,i){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1;return h.toAttribute(t,i,r)}static toFloatValue(t,i){return t===void 0?i:parseFloat(t)}}d.exports=h},{"../../utils/parse-sax":22,"../../utils/xml-stream":28}],33:[function(e,d,m){const l=e("../base-xform"),c=e("../../../utils/col-cache");class h extends l{render(r,n){r.openNode("definedName",{name:n.name,localSheetId:n.localSheetId}),r.writeText(n.ranges.join(",")),r.closeNode()}parseOpen(r){switch(r.name){case"definedName":return this._parsedName=r.attributes.name,this._parsedLocalSheetId=r.attributes.localSheetId,this._parsedText=[],!0;default:return!1}}parseText(r){this._parsedText.push(r)}parseClose(){return this.model={name:this._parsedName,ranges:t(this._parsedText.join(""))},this._parsedLocalSheetId!==void 0&&(this.model.localSheetId=parseInt(this._parsedLocalSheetId,10)),!1}}function s(i){try{return c.decodeEx(i),!0}catch{return!1}}function t(i){const r=[];let n=!1,o="";return i.split(",").forEach(f=>{if(!f)return;const a=(f.match(/'/g)||[]).length;if(!a){n?o+=`${f},`:s(f)&&r.push(f);return}const g=a%2===0;!n&&g&&s(f)?r.push(f):n&&!g?(n=!1,s(o+f)&&r.push(o+f),o=""):(n=!0,o+=`${f},`)}),r}d.exports=h},{"../../../utils/col-cache":19,"../base-xform":32}],34:[function(e,d,m){const l=e("../../../utils/utils"),c=e("../base-xform");class h extends c{render(t,i){t.leafNode("sheet",{sheetId:i.id,name:i.name,state:i.state,"r:id":i.rId})}parseOpen(t){return t.name==="sheet"?(this.model={name:l.xmlDecode(t.attributes.name),id:parseInt(t.attributes.sheetId,10),state:t.attributes.state,rId:t.attributes["r:id"]},!0):!1}parseText(){}parseClose(){return!1}}d.exports=h},{"../../../utils/utils":27,"../base-xform":32}],35:[function(e,d,m){const l=e("../base-xform");class c extends l{render(s,t){s.leafNode("calcPr",{calcId:171027,fullCalcOnLoad:t.fullCalcOnLoad?1:void 0})}parseOpen(s){return s.name==="calcPr"?(this.model={},!0):!1}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],36:[function(e,d,m){const l=e("../base-xform");class c extends l{render(s,t){s.leafNode("workbookPr",{date1904:t.date1904?1:void 0,defaultThemeVersion:164011,filterPrivacy:1})}parseOpen(s){return s.name==="workbookPr"?(this.model={date1904:s.attributes.date1904==="1"},!0):!1}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],37:[function(e,d,m){const l=e("../base-xform");class c extends l{render(s,t){const i={xWindow:t.x||0,yWindow:t.y||0,windowWidth:t.width||12e3,windowHeight:t.height||24e3,firstSheet:t.firstSheet,activeTab:t.activeTab};t.visibility&&t.visibility!=="visible"&&(i.visibility=t.visibility),s.leafNode("workbookView",i)}parseOpen(s){if(s.name==="workbookView"){const t=this.model={},i=function(n,o,f){const a=o!==void 0?t[n]=o:f;a!==void 0&&(t[n]=a)},r=function(n,o,f){const a=o!==void 0?t[n]=parseInt(o,10):f;a!==void 0&&(t[n]=a)};return r("x",s.attributes.xWindow,0),r("y",s.attributes.yWindow,0),r("width",s.attributes.windowWidth,25e3),r("height",s.attributes.windowHeight,1e4),i("visibility",s.attributes.visibility,"visible"),r("activeTab",s.attributes.activeTab,void 0),r("firstSheet",s.attributes.firstSheet,void 0),!0}return!1}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],38:[function(e,d,m){const l=e("../../../utils/under-dash"),c=e("../../../utils/col-cache"),h=e("../../../utils/xml-stream"),s=e("../base-xform"),t=e("../static-xform"),i=e("../list-xform"),r=e("./defined-name-xform"),n=e("./sheet-xform"),o=e("./workbook-view-xform"),f=e("./workbook-properties-xform"),a=e("./workbook-calc-properties-xform");class g extends s{constructor(){super(),this.map={fileVersion:g.STATIC_XFORMS.fileVersion,workbookPr:new f,bookViews:new i({tag:"bookViews",count:!1,childXform:new o}),sheets:new i({tag:"sheets",count:!1,childXform:new n}),definedNames:new i({tag:"definedNames",count:!1,childXform:new r}),calcPr:new a}}prepare(u){u.sheets=u.worksheets;const w=[];let y=0;u.sheets.forEach(S=>{if(S.pageSetup&&S.pageSetup.printArea&&S.pageSetup.printArea.split("&&").forEach(E=>{const I=E.split(":"),P={name:"_xlnm.Print_Area",ranges:[`'${S.name}'!$${I[0]}:$${I[1]}`],localSheetId:y};w.push(P)}),S.pageSetup&&(S.pageSetup.printTitlesRow||S.pageSetup.printTitlesColumn)){const E=[];if(S.pageSetup.printTitlesColumn){const P=S.pageSetup.printTitlesColumn.split(":");E.push(`'${S.name}'!$${P[0]}:$${P[1]}`)}if(S.pageSetup.printTitlesRow){const P=S.pageSetup.printTitlesRow.split(":");E.push(`'${S.name}'!$${P[0]}:$${P[1]}`)}const I={name:"_xlnm.Print_Titles",ranges:E,localSheetId:y};w.push(I)}y++}),w.length&&(u.definedNames=u.definedNames.concat(w)),(u.media||[]).forEach((S,E)=>{S.name=S.type+(E+1)})}render(u,w){u.openXml(h.StdDocAttributes),u.openNode("workbook",g.WORKBOOK_ATTRIBUTES),this.map.fileVersion.render(u),this.map.workbookPr.render(u,w.properties),this.map.bookViews.render(u,w.views),this.map.sheets.render(u,w.sheets),this.map.definedNames.render(u,w.definedNames),this.map.calcPr.render(u,w.calcProperties),u.closeNode()}parseOpen(u){if(this.parser)return this.parser.parseOpen(u),!0;switch(u.name){case"workbook":return!0;default:return this.parser=this.map[u.name],this.parser&&this.parser.parseOpen(u),!0}}parseText(u){this.parser&&this.parser.parseText(u)}parseClose(u){if(this.parser)return this.parser.parseClose(u)||(this.parser=void 0),!0;switch(u){case"workbook":return this.model={sheets:this.map.sheets.model,properties:this.map.workbookPr.model||{},views:this.map.bookViews.model,calcProperties:{}},this.map.definedNames.model&&(this.model.definedNames=this.map.definedNames.model),!1;default:return!0}}reconcile(u){const w=(u.workbookRels||[]).reduce((P,F)=>(P[F.Id]=F,P),{}),y=[];let S,E=0;(u.sheets||[]).forEach(P=>{const F=w[P.rId];F&&(S=u.worksheetHash[`xl/${F.Target.replace(/^(\s|\/xl\/)+/,"")}`],S&&(S.name=P.name,S.id=P.id,S.state=P.state,y[E++]=S))});const I=[];l.each(u.definedNames,P=>{if(P.name==="_xlnm.Print_Area"){if(S=y[P.localSheetId],S){S.pageSetup||(S.pageSetup={});const F=c.decodeEx(P.ranges[0]);S.pageSetup.printArea=S.pageSetup.printArea?`${S.pageSetup.printArea}&&${F.dimensions}`:F.dimensions}}else if(P.name==="_xlnm.Print_Titles"){if(S=y[P.localSheetId],S){S.pageSetup||(S.pageSetup={});const F=P.ranges.join(","),j=/\$/g,W=/\$\d+:\$\d+/,G=F.match(W);if(G&&G.length){const $=G[0];S.pageSetup.printTitlesRow=$.replace(j,"")}const V=/\$[A-Z]+:\$[A-Z]+/,J=F.match(V);if(J&&J.length){const $=J[0];S.pageSetup.printTitlesColumn=$.replace(j,"")}}}else I.push(P)}),u.definedNames=I,u.media.forEach((P,F)=>{P.index=F})}}g.WORKBOOK_ATTRIBUTES={xmlns:"http://schemas.openxmlformats.org/spreadsheetml/2006/main","xmlns:r":"http://schemas.openxmlformats.org/officeDocument/2006/relationships","xmlns:mc":"http://schemas.openxmlformats.org/markup-compatibility/2006","mc:Ignorable":"x15","xmlns:x15":"http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"},g.STATIC_XFORMS={fileVersion:new t({tag:"fileVersion",$:{appName:"xl",lastEdited:5,lowestEdited:5,rupBuild:9303}})},d.exports=g},{"../../../utils/col-cache":19,"../../../utils/under-dash":26,"../../../utils/xml-stream":28,"../base-xform":32,"../list-xform":71,"../static-xform":120,"./defined-name-xform":33,"./sheet-xform":34,"./workbook-calc-properties-xform":35,"./workbook-properties-xform":36,"./workbook-view-xform":37}],39:[function(e,d,m){const l=e("../strings/rich-text-xform"),c=e("../../../utils/utils"),h=e("../base-xform"),s=d.exports=function(t){this.model=t};c.inherits(s,h,{get tag(){return"r"},get richTextXform(){return this._richTextXform||(this._richTextXform=new l),this._richTextXform},render(t,i){i=i||this.model,t.openNode("comment",{ref:i.ref,authorId:0}),t.openNode("text"),i&&i.note&&i.note.texts&&i.note.texts.forEach(r=>{this.richTextXform.render(t,r)}),t.closeNode(),t.closeNode()},parseOpen(t){if(this.parser)return this.parser.parseOpen(t),!0;switch(t.name){case"comment":return this.model={type:"note",note:{texts:[]},...t.attributes},!0;case"r":return this.parser=this.richTextXform,this.parser.parseOpen(t),!0;default:return!1}},parseText(t){this.parser&&this.parser.parseText(t)},parseClose(t){switch(t){case"comment":return!1;case"r":return this.model.note.texts.push(this.parser.model),this.parser=void 0,!0;default:return this.parser&&this.parser.parseClose(t),!0}}})},{"../../../utils/utils":27,"../base-xform":32,"../strings/rich-text-xform":122}],40:[function(e,d,m){const l=e("../../../utils/xml-stream"),c=e("../../../utils/utils"),h=e("../base-xform"),s=e("./comment-xform"),t=d.exports=function(){this.map={comment:new s}};c.inherits(t,h,{COMMENTS_ATTRIBUTES:{xmlns:"http://schemas.openxmlformats.org/spreadsheetml/2006/main"}},{render(i,r){r=r||this.model,i.openXml(l.StdDocAttributes),i.openNode("comments",t.COMMENTS_ATTRIBUTES),i.openNode("authors"),i.leafNode("author",null,"Author"),i.closeNode(),i.openNode("commentList"),r.comments.forEach(n=>{this.map.comment.render(i,n)}),i.closeNode(),i.closeNode()},parseOpen(i){if(this.parser)return this.parser.parseOpen(i),!0;switch(i.name){case"commentList":return this.model={comments:[]},!0;case"comment":return this.parser=this.map.comment,this.parser.parseOpen(i),!0;default:return!1}},parseText(i){this.parser&&this.parser.parseText(i)},parseClose(i){switch(i){case"commentList":return!1;case"comment":return this.model.comments.push(this.parser.model),this.parser=void 0,!0;default:return this.parser&&this.parser.parseClose(i),!0}}})},{"../../../utils/utils":27,"../../../utils/xml-stream":28,"../base-xform":32,"./comment-xform":39}],41:[function(e,d,m){const l=e("../../base-xform");class c extends l{constructor(s){super(),this._model=s}get tag(){return this._model&&this._model.tag}render(s,t,i){t===i[2]?s.leafNode(this.tag):this.tag==="x:SizeWithCells"&&t===i[1]&&s.leafNode(this.tag)}parseOpen(s){switch(s.name){case this.tag:return this.model={},this.model[this.tag]=!0,!0;default:return!1}}parseText(){}parseClose(){return!1}}d.exports=c},{"../../base-xform":32}],42:[function(e,d,m){const l=e("../../base-xform");class c extends l{constructor(s){super(),this._model=s}get tag(){return this._model&&this._model.tag}render(s,t){s.leafNode(this.tag,null,t)}parseOpen(s){switch(s.name){case this.tag:return this.text="",!0;default:return!1}}parseText(s){this.text=s}parseClose(){return!1}}d.exports=c},{"../../base-xform":32}],43:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"x:Anchor"}getAnchorRect(s){const t=Math.floor(s.left),i=Math.floor((s.left-t)*68),r=Math.floor(s.top),n=Math.floor((s.top-r)*18),o=Math.floor(s.right),f=Math.floor((s.right-o)*68),a=Math.floor(s.bottom),g=Math.floor((s.bottom-a)*18);return[t,i,r,n,o,f,a,g]}getDefaultRect(s){const t=s.col,i=6,r=Math.max(s.row-2,0),n=14,o=t+2,f=2,a=r+4;return[t,i,r,n,o,f,a,16]}render(s,t){const i=t.anchor?this.getAnchorRect(t.anchor):this.getDefaultRect(t.refAddress);s.leafNode("x:Anchor",null,i.join(", "))}parseOpen(s){switch(s.name){case this.tag:return this.text="",!0;default:return!1}}parseText(s){this.text=s}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],44:[function(e,d,m){const l=e("../base-xform"),c=e("./vml-anchor-xform"),h=e("./style/vml-protection-xform"),s=e("./style/vml-position-xform"),t=["twoCells","oneCells","absolute"];class i extends l{constructor(){super(),this.map={"x:Anchor":new c,"x:Locked":new h({tag:"x:Locked"}),"x:LockText":new h({tag:"x:LockText"}),"x:SizeWithCells":new s({tag:"x:SizeWithCells"}),"x:MoveWithCells":new s({tag:"x:MoveWithCells"})}}get tag(){return"x:ClientData"}render(n,o){const{protection:f,editAs:a}=o.note;n.openNode(this.tag,{ObjectType:"Note"}),this.map["x:MoveWithCells"].render(n,a,t),this.map["x:SizeWithCells"].render(n,a,t),this.map["x:Anchor"].render(n,o),this.map["x:Locked"].render(n,f.locked),n.leafNode("x:AutoFill",null,"False"),this.map["x:LockText"].render(n,f.lockText),n.leafNode("x:Row",null,o.refAddress.row-1),n.leafNode("x:Column",null,o.refAddress.col-1),n.closeNode()}parseOpen(n){switch(n.name){case this.tag:this.reset(),this.model={anchor:[],protection:{},editAs:""};break;default:this.parser=this.map[n.name],this.parser&&this.parser.parseOpen(n);break}return!0}parseText(n){this.parser&&this.parser.parseText(n)}parseClose(n){if(this.parser)return this.parser.parseClose(n)||(this.parser=void 0),!0;switch(n){case this.tag:return this.normalizeModel(),!1;default:return!0}}normalizeModel(){const n=Object.assign({},this.map["x:MoveWithCells"].model,this.map["x:SizeWithCells"].model),o=Object.keys(n).length;this.model.editAs=t[o],this.model.anchor=this.map["x:Anchor"].text,this.model.protection.locked=this.map["x:Locked"].text,this.model.protection.lockText=this.map["x:LockText"].text}}d.exports=i},{"../base-xform":32,"./style/vml-position-xform":41,"./style/vml-protection-xform":42,"./vml-anchor-xform":43}],45:[function(e,d,m){const l=e("../../../utils/xml-stream"),c=e("../base-xform"),h=e("./vml-shape-xform");class s extends c{constructor(){super(),this.map={"v:shape":new h}}get tag(){return"xml"}render(i,r){i.openXml(l.StdDocAttributes),i.openNode(this.tag,s.DRAWING_ATTRIBUTES),i.openNode("o:shapelayout",{"v:ext":"edit"}),i.leafNode("o:idmap",{"v:ext":"edit",data:1}),i.closeNode(),i.openNode("v:shapetype",{id:"_x0000_t202",coordsize:"21600,21600","o:spt":202,path:"m,l,21600r21600,l21600,xe"}),i.leafNode("v:stroke",{joinstyle:"miter"}),i.leafNode("v:path",{gradientshapeok:"t","o:connecttype":"rect"}),i.closeNode(),r.comments.forEach((n,o)=>{this.map["v:shape"].render(i,n,o)}),i.closeNode()}parseOpen(i){if(this.parser)return this.parser.parseOpen(i),!0;switch(i.name){case this.tag:this.reset(),this.model={comments:[]};break;default:this.parser=this.map[i.name],this.parser&&this.parser.parseOpen(i);break}return!0}parseText(i){this.parser&&this.parser.parseText(i)}parseClose(i){if(this.parser)return this.parser.parseClose(i)||(this.model.comments.push(this.parser.model),this.parser=void 0),!0;switch(i){case this.tag:return!1;default:return!0}}reconcile(i,r){i.anchors.forEach(n=>{n.br?this.map["xdr:twoCellAnchor"].reconcile(n,r):this.map["xdr:oneCellAnchor"].reconcile(n,r)})}}s.DRAWING_ATTRIBUTES={"xmlns:v":"urn:schemas-microsoft-com:vml","xmlns:o":"urn:schemas-microsoft-com:office:office","xmlns:x":"urn:schemas-microsoft-com:office:excel"},d.exports=s},{"../../../utils/xml-stream":28,"../base-xform":32,"./vml-shape-xform":46}],46:[function(e,d,m){const l=e("../base-xform"),c=e("./vml-textbox-xform"),h=e("./vml-client-data-xform");class s extends l{constructor(){super(),this.map={"v:textbox":new c,"x:ClientData":new h}}get tag(){return"v:shape"}render(i,r,n){i.openNode("v:shape",s.V_SHAPE_ATTRIBUTES(r,n)),i.leafNode("v:fill",{color2:"infoBackground [80]"}),i.leafNode("v:shadow",{color:"none [81]",obscured:"t"}),i.leafNode("v:path",{"o:connecttype":"none"}),this.map["v:textbox"].render(i,r),this.map["x:ClientData"].render(i,r),i.closeNode()}parseOpen(i){if(this.parser)return this.parser.parseOpen(i),!0;switch(i.name){case this.tag:this.reset(),this.model={margins:{insetmode:i.attributes["o:insetmode"]},anchor:"",editAs:"",protection:{}};break;default:this.parser=this.map[i.name],this.parser&&this.parser.parseOpen(i);break}return!0}parseText(i){this.parser&&this.parser.parseText(i)}parseClose(i){if(this.parser)return this.parser.parseClose(i)||(this.parser=void 0),!0;switch(i){case this.tag:return this.model.margins.inset=this.map["v:textbox"].model&&this.map["v:textbox"].model.inset,this.model.protection=this.map["x:ClientData"].model&&this.map["x:ClientData"].model.protection,this.model.anchor=this.map["x:ClientData"].model&&this.map["x:ClientData"].model.anchor,this.model.editAs=this.map["x:ClientData"].model&&this.map["x:ClientData"].model.editAs,!1;default:return!0}}}s.V_SHAPE_ATTRIBUTES=(t,i)=>({id:`_x0000_s${1025+i}`,type:"#_x0000_t202",style:"position:absolute; margin-left:105.3pt;margin-top:10.5pt;width:97.8pt;height:59.1pt;z-index:1;visibility:hidden",fillcolor:"infoBackground [80]",strokecolor:"none [81]","o:insetmode":t.note.margins&&t.note.margins.insetmode}),d.exports=s},{"../base-xform":32,"./vml-client-data-xform":44,"./vml-textbox-xform":47}],47:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"v:textbox"}conversionUnit(s,t,i){return`${parseFloat(s)*t.toFixed(2)}${i}`}reverseConversionUnit(s){return(s||"").split(",").map(t=>Number(parseFloat(this.conversionUnit(parseFloat(t),.1,"")).toFixed(2)))}render(s,t){const i={style:"mso-direction-alt:auto"};if(t&&t.note){let{inset:r}=t.note&&t.note.margins;Array.isArray(r)&&(r=r.map(n=>this.conversionUnit(n,10,"mm")).join(",")),r&&(i.inset=r)}s.openNode("v:textbox",i),s.leafNode("div",{style:"text-align:left"}),s.closeNode()}parseOpen(s){switch(s.name){case this.tag:return this.model={inset:this.reverseConversionUnit(s.attributes.inset)},!0;default:return!0}}parseText(){}parseClose(s){switch(s){case this.tag:return!1;default:return!0}}}d.exports=c},{"../base-xform":32}],48:[function(e,d,m){const l=e("./base-xform");class c extends l{createNewModel(s){return{}}parseOpen(s){return this.parser=this.parser||this.map[s.name],this.parser?(this.parser.parseOpen(s),!0):s.name===this.tag?(this.model=this.createNewModel(s),!0):!1}parseText(s){this.parser&&this.parser.parseText(s)}onParserClose(s,t){this.model[s]=t.model}parseClose(s){return this.parser?(this.parser.parseClose(s)||(this.onParserClose(s,this.parser),this.parser=void 0),!0):s!==this.tag}}d.exports=c},{"./base-xform":32}],49:[function(e,d,m){const l=e("../base-xform");class c extends l{render(s,t){s.openNode("HeadingPairs"),s.openNode("vt:vector",{size:2,baseType:"variant"}),s.openNode("vt:variant"),s.leafNode("vt:lpstr",void 0,"Worksheets"),s.closeNode(),s.openNode("vt:variant"),s.leafNode("vt:i4",void 0,t.length),s.closeNode(),s.closeNode(),s.closeNode()}parseOpen(s){return s.name==="HeadingPairs"}parseText(){}parseClose(s){return s!=="HeadingPairs"}}d.exports=c},{"../base-xform":32}],50:[function(e,d,m){const l=e("../base-xform");class c extends l{render(s,t){s.openNode("TitlesOfParts"),s.openNode("vt:vector",{size:t.length,baseType:"lpstr"}),t.forEach(i=>{s.leafNode("vt:lpstr",void 0,i.name)}),s.closeNode(),s.closeNode()}parseOpen(s){return s.name==="TitlesOfParts"}parseText(){}parseClose(s){return s!=="TitlesOfParts"}}d.exports=c},{"../base-xform":32}],51:[function(e,d,m){const l=e("../../../utils/xml-stream"),c=e("../base-xform"),h=e("../simple/string-xform"),s=e("./app-heading-pairs-xform"),t=e("./app-titles-of-parts-xform");class i extends c{constructor(){super(),this.map={Company:new h({tag:"Company"}),Manager:new h({tag:"Manager"}),HeadingPairs:new s,TitleOfParts:new t}}render(n,o){n.openXml(l.StdDocAttributes),n.openNode("Properties",i.PROPERTY_ATTRIBUTES),n.leafNode("Application",void 0,"Microsoft Excel"),n.leafNode("DocSecurity",void 0,"0"),n.leafNode("ScaleCrop",void 0,"false"),this.map.HeadingPairs.render(n,o.worksheets),this.map.TitleOfParts.render(n,o.worksheets),this.map.Company.render(n,o.company||""),this.map.Manager.render(n,o.manager),n.leafNode("LinksUpToDate",void 0,"false"),n.leafNode("SharedDoc",void 0,"false"),n.leafNode("HyperlinksChanged",void 0,"false"),n.leafNode("AppVersion",void 0,"16.0300"),n.closeNode()}parseOpen(n){if(this.parser)return this.parser.parseOpen(n),!0;switch(n.name){case"Properties":return!0;default:return this.parser=this.map[n.name],this.parser?(this.parser.parseOpen(n),!0):!1}}parseText(n){this.parser&&this.parser.parseText(n)}parseClose(n){if(this.parser)return this.parser.parseClose(n)||(this.parser=void 0),!0;switch(n){case"Properties":return this.model={worksheets:this.map.TitleOfParts.model,company:this.map.Company.model,manager:this.map.Manager.model},!1;default:return!0}}}i.DateFormat=function(r){return r.toISOString().replace(/[.]\d{3,6}/,"")},i.DateAttrs={"xsi:type":"dcterms:W3CDTF"},i.PROPERTY_ATTRIBUTES={xmlns:"http://schemas.openxmlformats.org/officeDocument/2006/extended-properties","xmlns:vt":"http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"},d.exports=i},{"../../../utils/xml-stream":28,"../base-xform":32,"../simple/string-xform":119,"./app-heading-pairs-xform":49,"./app-titles-of-parts-xform":50}],52:[function(e,d,m){const l=e("../../../utils/xml-stream"),c=e("../base-xform");class h extends c{render(t,i){t.openXml(l.StdDocAttributes),t.openNode("Types",h.PROPERTY_ATTRIBUTES);const r={};(i.media||[]).forEach(o=>{if(o.type==="image"){const f=o.extension;r[f]||(r[f]=!0,t.leafNode("Default",{Extension:f,ContentType:`image/${f}`}))}}),t.leafNode("Default",{Extension:"rels",ContentType:"application/vnd.openxmlformats-package.relationships+xml"}),t.leafNode("Default",{Extension:"xml",ContentType:"application/xml"}),t.leafNode("Override",{PartName:"/xl/workbook.xml",ContentType:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"}),i.worksheets.forEach(o=>{const f=`/xl/worksheets/sheet${o.id}.xml`;t.leafNode("Override",{PartName:f,ContentType:"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"})}),t.leafNode("Override",{PartName:"/xl/theme/theme1.xml",ContentType:"application/vnd.openxmlformats-officedocument.theme+xml"}),t.leafNode("Override",{PartName:"/xl/styles.xml",ContentType:"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"}),i.sharedStrings&&i.sharedStrings.count&&t.leafNode("Override",{PartName:"/xl/sharedStrings.xml",ContentType:"application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"}),i.tables&&i.tables.forEach(o=>{t.leafNode("Override",{PartName:`/xl/tables/${o.target}`,ContentType:"application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml"})}),i.drawings&&i.drawings.forEach(o=>{t.leafNode("Override",{PartName:`/xl/drawings/${o.name}.xml`,ContentType:"application/vnd.openxmlformats-officedocument.drawing+xml"})}),i.commentRefs&&(t.leafNode("Default",{Extension:"vml",ContentType:"application/vnd.openxmlformats-officedocument.vmlDrawing"}),i.commentRefs.forEach(o=>{let{commentName:f}=o;t.leafNode("Override",{PartName:`/xl/${f}.xml`,ContentType:"application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml"})})),t.leafNode("Override",{PartName:"/docProps/core.xml",ContentType:"application/vnd.openxmlformats-package.core-properties+xml"}),t.leafNode("Override",{PartName:"/docProps/app.xml",ContentType:"application/vnd.openxmlformats-officedocument.extended-properties+xml"}),t.closeNode()}parseOpen(){return!1}parseText(){}parseClose(){return!1}}h.PROPERTY_ATTRIBUTES={xmlns:"http://schemas.openxmlformats.org/package/2006/content-types"},d.exports=h},{"../../../utils/xml-stream":28,"../base-xform":32}],53:[function(e,d,m){const l=e("../../../utils/xml-stream"),c=e("../base-xform"),h=e("../simple/date-xform"),s=e("../simple/string-xform"),t=e("../simple/integer-xform");class i extends c{constructor(){super(),this.map={"dc:creator":new s({tag:"dc:creator"}),"dc:title":new s({tag:"dc:title"}),"dc:subject":new s({tag:"dc:subject"}),"dc:description":new s({tag:"dc:description"}),"dc:identifier":new s({tag:"dc:identifier"}),"dc:language":new s({tag:"dc:language"}),"cp:keywords":new s({tag:"cp:keywords"}),"cp:category":new s({tag:"cp:category"}),"cp:lastModifiedBy":new s({tag:"cp:lastModifiedBy"}),"cp:lastPrinted":new h({tag:"cp:lastPrinted",format:i.DateFormat}),"cp:revision":new t({tag:"cp:revision"}),"cp:version":new s({tag:"cp:version"}),"cp:contentStatus":new s({tag:"cp:contentStatus"}),"cp:contentType":new s({tag:"cp:contentType"}),"dcterms:created":new h({tag:"dcterms:created",attrs:i.DateAttrs,format:i.DateFormat}),"dcterms:modified":new h({tag:"dcterms:modified",attrs:i.DateAttrs,format:i.DateFormat})}}render(n,o){n.openXml(l.StdDocAttributes),n.openNode("cp:coreProperties",i.CORE_PROPERTY_ATTRIBUTES),this.map["dc:creator"].render(n,o.creator),this.map["dc:title"].render(n,o.title),this.map["dc:subject"].render(n,o.subject),this.map["dc:description"].render(n,o.description),this.map["dc:identifier"].render(n,o.identifier),this.map["dc:language"].render(n,o.language),this.map["cp:keywords"].render(n,o.keywords),this.map["cp:category"].render(n,o.category),this.map["cp:lastModifiedBy"].render(n,o.lastModifiedBy),this.map["cp:lastPrinted"].render(n,o.lastPrinted),this.map["cp:revision"].render(n,o.revision),this.map["cp:version"].render(n,o.version),this.map["cp:contentStatus"].render(n,o.contentStatus),this.map["cp:contentType"].render(n,o.contentType),this.map["dcterms:created"].render(n,o.created),this.map["dcterms:modified"].render(n,o.modified),n.closeNode()}parseOpen(n){if(this.parser)return this.parser.parseOpen(n),!0;switch(n.name){case"cp:coreProperties":case"coreProperties":return!0;default:if(this.parser=this.map[n.name],this.parser)return this.parser.parseOpen(n),!0;throw new Error(`Unexpected xml node in parseOpen: ${JSON.stringify(n)}`)}}parseText(n){this.parser&&this.parser.parseText(n)}parseClose(n){if(this.parser)return this.parser.parseClose(n)||(this.parser=void 0),!0;switch(n){case"cp:coreProperties":case"coreProperties":return this.model={creator:this.map["dc:creator"].model,title:this.map["dc:title"].model,subject:this.map["dc:subject"].model,description:this.map["dc:description"].model,identifier:this.map["dc:identifier"].model,language:this.map["dc:language"].model,keywords:this.map["cp:keywords"].model,category:this.map["cp:category"].model,lastModifiedBy:this.map["cp:lastModifiedBy"].model,lastPrinted:this.map["cp:lastPrinted"].model,revision:this.map["cp:revision"].model,contentStatus:this.map["cp:contentStatus"].model,contentType:this.map["cp:contentType"].model,created:this.map["dcterms:created"].model,modified:this.map["dcterms:modified"].model},!1;default:throw new Error(`Unexpected xml node in parseClose: ${n}`)}}}i.DateFormat=function(r){return r.toISOString().replace(/[.]\d{3}/,"")},i.DateAttrs={"xsi:type":"dcterms:W3CDTF"},i.CORE_PROPERTY_ATTRIBUTES={"xmlns:cp":"http://schemas.openxmlformats.org/package/2006/metadata/core-properties","xmlns:dc":"http://purl.org/dc/elements/1.1/","xmlns:dcterms":"http://purl.org/dc/terms/","xmlns:dcmitype":"http://purl.org/dc/dcmitype/","xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance"},d.exports=i},{"../../../utils/xml-stream":28,"../base-xform":32,"../simple/date-xform":117,"../simple/integer-xform":118,"../simple/string-xform":119}],54:[function(e,d,m){const l=e("../base-xform");class c extends l{render(s,t){s.leafNode("Relationship",t)}parseOpen(s){switch(s.name){case"Relationship":return this.model=s.attributes,!0;default:return!1}}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],55:[function(e,d,m){const l=e("../../../utils/xml-stream"),c=e("../base-xform"),h=e("./relationship-xform");class s extends c{constructor(){super(),this.map={Relationship:new h}}render(i,r){r=r||this._values,i.openXml(l.StdDocAttributes),i.openNode("Relationships",s.RELATIONSHIPS_ATTRIBUTES),r.forEach(n=>{this.map.Relationship.render(i,n)}),i.closeNode()}parseOpen(i){if(this.parser)return this.parser.parseOpen(i),!0;switch(i.name){case"Relationships":return this.model=[],!0;default:if(this.parser=this.map[i.name],this.parser)return this.parser.parseOpen(i),!0;throw new Error(`Unexpected xml node in parseOpen: ${JSON.stringify(i)}`)}}parseText(i){this.parser&&this.parser.parseText(i)}parseClose(i){if(this.parser)return this.parser.parseClose(i)||(this.model.push(this.parser.model),this.parser=void 0),!0;switch(i){case"Relationships":return!1;default:throw new Error(`Unexpected xml node in parseClose: ${i}`)}}}s.RELATIONSHIPS_ATTRIBUTES={xmlns:"http://schemas.openxmlformats.org/package/2006/relationships"},d.exports=s},{"../../../utils/xml-stream":28,"../base-xform":32,"./relationship-xform":54}],56:[function(e,d,m){const l=e("../base-xform");class c extends l{parseOpen(s){if(this.parser)return this.parser.parseOpen(s),!0;switch(s.name){case this.tag:this.reset(),this.model={range:{editAs:s.attributes.editAs||"oneCell"}};break;default:this.parser=this.map[s.name],this.parser&&this.parser.parseOpen(s);break}return!0}parseText(s){this.parser&&this.parser.parseText(s)}reconcilePicture(s,t){if(s&&s.rId){const r=t.rels[s.rId].Target.match(/.*\/media\/(.+[.][a-zA-Z]{3,4})/);if(r){const n=r[1],o=t.mediaIndex[n];return t.media[o]}}}}d.exports=c},{"../base-xform":32}],57:[function(e,d,m){const l=e("../base-xform"),c=e("./blip-xform");class h extends l{constructor(){super(),this.map={"a:blip":new c}}get tag(){return"xdr:blipFill"}render(t,i){t.openNode(this.tag),this.map["a:blip"].render(t,i),t.openNode("a:stretch"),t.leafNode("a:fillRect"),t.closeNode(),t.closeNode()}parseOpen(t){if(this.parser)return this.parser.parseOpen(t),!0;switch(t.name){case this.tag:this.reset();break;default:this.parser=this.map[t.name],this.parser&&this.parser.parseOpen(t);break}return!0}parseText(){}parseClose(t){if(this.parser)return this.parser.parseClose(t)||(this.parser=void 0),!0;switch(t){case this.tag:return this.model=this.map["a:blip"].model,!1;default:return!0}}}d.exports=h},{"../base-xform":32,"./blip-xform":58}],58:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"a:blip"}render(s,t){s.leafNode(this.tag,{"xmlns:r":"http://schemas.openxmlformats.org/officeDocument/2006/relationships","r:embed":t.rId,cstate:"print"})}parseOpen(s){switch(s.name){case this.tag:return this.model={rId:s.attributes["r:embed"]},!0;default:return!0}}parseText(){}parseClose(s){switch(s){case this.tag:return!1;default:return!0}}}d.exports=c},{"../base-xform":32}],59:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"xdr:cNvPicPr"}render(s){s.openNode(this.tag),s.leafNode("a:picLocks",{noChangeAspect:"1"}),s.closeNode()}parseOpen(s){switch(s.name){case this.tag:return!0;default:return!0}}parseText(){}parseClose(s){switch(s){case this.tag:return!1;default:return!0}}}d.exports=c},{"../base-xform":32}],60:[function(e,d,m){const l=e("../base-xform"),c=e("./hlink-click-xform"),h=e("./ext-lst-xform");class s extends l{constructor(){super(),this.map={"a:hlinkClick":new c,"a:extLst":new h}}get tag(){return"xdr:cNvPr"}render(i,r){i.openNode(this.tag,{id:r.index,name:`Picture ${r.index}`}),this.map["a:hlinkClick"].render(i,r),this.map["a:extLst"].render(i,r),i.closeNode()}parseOpen(i){if(this.parser)return this.parser.parseOpen(i),!0;switch(i.name){case this.tag:this.reset();break;default:this.parser=this.map[i.name],this.parser&&this.parser.parseOpen(i);break}return!0}parseText(){}parseClose(i){if(this.parser)return this.parser.parseClose(i)||(this.parser=void 0),!0;switch(i){case this.tag:return this.model=this.map["a:hlinkClick"].model,!1;default:return!0}}}d.exports=s},{"../base-xform":32,"./ext-lst-xform":63,"./hlink-click-xform":65}],61:[function(e,d,m){const l=e("../base-xform"),c=e("../simple/integer-xform");class h extends l{constructor(t){super(),this.tag=t.tag,this.map={"xdr:col":new c({tag:"xdr:col",zero:!0}),"xdr:colOff":new c({tag:"xdr:colOff",zero:!0}),"xdr:row":new c({tag:"xdr:row",zero:!0}),"xdr:rowOff":new c({tag:"xdr:rowOff",zero:!0})}}render(t,i){t.openNode(this.tag),this.map["xdr:col"].render(t,i.nativeCol),this.map["xdr:colOff"].render(t,i.nativeColOff),this.map["xdr:row"].render(t,i.nativeRow),this.map["xdr:rowOff"].render(t,i.nativeRowOff),t.closeNode()}parseOpen(t){if(this.parser)return this.parser.parseOpen(t),!0;switch(t.name){case this.tag:this.reset();break;default:this.parser=this.map[t.name],this.parser&&this.parser.parseOpen(t);break}return!0}parseText(t){this.parser&&this.parser.parseText(t)}parseClose(t){if(this.parser)return this.parser.parseClose(t)||(this.parser=void 0),!0;switch(t){case this.tag:return this.model={nativeCol:this.map["xdr:col"].model,nativeColOff:this.map["xdr:colOff"].model,nativeRow:this.map["xdr:row"].model,nativeRowOff:this.map["xdr:rowOff"].model},!1;default:return!0}}}d.exports=h},{"../base-xform":32,"../simple/integer-xform":118}],62:[function(e,d,m){const l=e("../../../utils/col-cache"),c=e("../../../utils/xml-stream"),h=e("../base-xform"),s=e("./two-cell-anchor-xform"),t=e("./one-cell-anchor-xform");function i(n){return(typeof n.range=="string"?l.decode(n.range):n.range).br?"xdr:twoCellAnchor":"xdr:oneCellAnchor"}class r extends h{constructor(){super(),this.map={"xdr:twoCellAnchor":new s,"xdr:oneCellAnchor":new t}}prepare(o){o.anchors.forEach((f,a)=>{f.anchorType=i(f),this.map[f.anchorType].prepare(f,{index:a})})}get tag(){return"xdr:wsDr"}render(o,f){o.openXml(c.StdDocAttributes),o.openNode(this.tag,r.DRAWING_ATTRIBUTES),f.anchors.forEach(a=>{this.map[a.anchorType].render(o,a)}),o.closeNode()}parseOpen(o){if(this.parser)return this.parser.parseOpen(o),!0;switch(o.name){case this.tag:this.reset(),this.model={anchors:[]};break;default:this.parser=this.map[o.name],this.parser&&this.parser.parseOpen(o);break}return!0}parseText(o){this.parser&&this.parser.parseText(o)}parseClose(o){if(this.parser)return this.parser.parseClose(o)||(this.model.anchors.push(this.parser.model),this.parser=void 0),!0;switch(o){case this.tag:return!1;default:return!0}}reconcile(o,f){o.anchors.forEach(a=>{a.br?this.map["xdr:twoCellAnchor"].reconcile(a,f):this.map["xdr:oneCellAnchor"].reconcile(a,f)})}}r.DRAWING_ATTRIBUTES={"xmlns:xdr":"http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing","xmlns:a":"http://schemas.openxmlformats.org/drawingml/2006/main"},d.exports=r},{"../../../utils/col-cache":19,"../../../utils/xml-stream":28,"../base-xform":32,"./one-cell-anchor-xform":67,"./two-cell-anchor-xform":70}],63:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"a:extLst"}render(s){s.openNode(this.tag),s.openNode("a:ext",{uri:"{FF2B5EF4-FFF2-40B4-BE49-F238E27FC236}"}),s.leafNode("a16:creationId",{"xmlns:a16":"http://schemas.microsoft.com/office/drawing/2014/main",id:"{00000000-0008-0000-0000-000002000000}"}),s.closeNode(),s.closeNode()}parseOpen(s){switch(s.name){case this.tag:return!0;default:return!0}}parseText(){}parseClose(s){switch(s){case this.tag:return!1;default:return!0}}}d.exports=c},{"../base-xform":32}],64:[function(e,d,m){const l=e("../base-xform"),c=9525;class h extends l{constructor(t){super(),this.tag=t.tag,this.map={}}render(t,i){t.openNode(this.tag);const r=Math.floor(i.width*c),n=Math.floor(i.height*c);t.addAttribute("cx",r),t.addAttribute("cy",n),t.closeNode()}parseOpen(t){return t.name===this.tag?(this.model={width:parseInt(t.attributes.cx||"0",10)/c,height:parseInt(t.attributes.cy||"0",10)/c},!0):!1}parseText(){}parseClose(){return!1}}d.exports=h},{"../base-xform":32}],65:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"a:hlinkClick"}render(s,t){t.hyperlinks&&t.hyperlinks.rId&&s.leafNode(this.tag,{"xmlns:r":"http://schemas.openxmlformats.org/officeDocument/2006/relationships","r:id":t.hyperlinks.rId,tooltip:t.hyperlinks.tooltip})}parseOpen(s){switch(s.name){case this.tag:return this.model={hyperlinks:{rId:s.attributes["r:id"],tooltip:s.attributes.tooltip}},!0;default:return!0}}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],66:[function(e,d,m){const l=e("../base-xform"),c=e("./c-nv-pr-xform"),h=e("./c-nv-pic-pr-xform");class s extends l{constructor(){super(),this.map={"xdr:cNvPr":new c,"xdr:cNvPicPr":new h}}get tag(){return"xdr:nvPicPr"}render(i,r){i.openNode(this.tag),this.map["xdr:cNvPr"].render(i,r),this.map["xdr:cNvPicPr"].render(i,r),i.closeNode()}parseOpen(i){if(this.parser)return this.parser.parseOpen(i),!0;switch(i.name){case this.tag:this.reset();break;default:this.parser=this.map[i.name],this.parser&&this.parser.parseOpen(i);break}return!0}parseText(){}parseClose(i){if(this.parser)return this.parser.parseClose(i)||(this.parser=void 0),!0;switch(i){case this.tag:return this.model=this.map["xdr:cNvPr"].model,!1;default:return!0}}}d.exports=s},{"../base-xform":32,"./c-nv-pic-pr-xform":59,"./c-nv-pr-xform":60}],67:[function(e,d,m){const l=e("./base-cell-anchor-xform"),c=e("../static-xform"),h=e("./cell-position-xform"),s=e("./ext-xform"),t=e("./pic-xform");class i extends l{constructor(){super(),this.map={"xdr:from":new h({tag:"xdr:from"}),"xdr:ext":new s({tag:"xdr:ext"}),"xdr:pic":new t,"xdr:clientData":new c({tag:"xdr:clientData"})}}get tag(){return"xdr:oneCellAnchor"}prepare(n,o){this.map["xdr:pic"].prepare(n.picture,o)}render(n,o){n.openNode(this.tag,{editAs:o.range.editAs||"oneCell"}),this.map["xdr:from"].render(n,o.range.tl),this.map["xdr:ext"].render(n,o.range.ext),this.map["xdr:pic"].render(n,o.picture),this.map["xdr:clientData"].render(n,{}),n.closeNode()}parseClose(n){if(this.parser)return this.parser.parseClose(n)||(this.parser=void 0),!0;switch(n){case this.tag:return this.model.range.tl=this.map["xdr:from"].model,this.model.range.ext=this.map["xdr:ext"].model,this.model.picture=this.map["xdr:pic"].model,!1;default:return!0}}reconcile(n,o){n.medium=this.reconcilePicture(n.picture,o)}}d.exports=i},{"../static-xform":120,"./base-cell-anchor-xform":56,"./cell-position-xform":61,"./ext-xform":64,"./pic-xform":68}],68:[function(e,d,m){const l=e("../base-xform"),c=e("../static-xform"),h=e("./blip-fill-xform"),s=e("./nv-pic-pr-xform"),t=e("./sp-pr");class i extends l{constructor(){super(),this.map={"xdr:nvPicPr":new s,"xdr:blipFill":new h,"xdr:spPr":new c(t)}}get tag(){return"xdr:pic"}prepare(n,o){n.index=o.index+1}render(n,o){n.openNode(this.tag),this.map["xdr:nvPicPr"].render(n,o),this.map["xdr:blipFill"].render(n,o),this.map["xdr:spPr"].render(n,o),n.closeNode()}parseOpen(n){if(this.parser)return this.parser.parseOpen(n),!0;switch(n.name){case this.tag:this.reset();break;default:this.parser=this.map[n.name],this.parser&&this.parser.parseOpen(n);break}return!0}parseText(){}parseClose(n){if(this.parser)return this.parser.parseClose(n)||(this.mergeModel(this.parser.model),this.parser=void 0),!0;switch(n){case this.tag:return!1;default:return!0}}}d.exports=i},{"../base-xform":32,"../static-xform":120,"./blip-fill-xform":57,"./nv-pic-pr-xform":66,"./sp-pr":69}],69:[function(e,d,m){d.exports={tag:"xdr:spPr",c:[{tag:"a:xfrm",c:[{tag:"a:off",$:{x:"0",y:"0"}},{tag:"a:ext",$:{cx:"0",cy:"0"}}]},{tag:"a:prstGeom",$:{prst:"rect"},c:[{tag:"a:avLst"}]}]}},{}],70:[function(e,d,m){const l=e("./base-cell-anchor-xform"),c=e("../static-xform"),h=e("./cell-position-xform"),s=e("./pic-xform");class t extends l{constructor(){super(),this.map={"xdr:from":new h({tag:"xdr:from"}),"xdr:to":new h({tag:"xdr:to"}),"xdr:pic":new s,"xdr:clientData":new c({tag:"xdr:clientData"})}}get tag(){return"xdr:twoCellAnchor"}prepare(r,n){this.map["xdr:pic"].prepare(r.picture,n)}render(r,n){r.openNode(this.tag,{editAs:n.range.editAs||"oneCell"}),this.map["xdr:from"].render(r,n.range.tl),this.map["xdr:to"].render(r,n.range.br),this.map["xdr:pic"].render(r,n.picture),this.map["xdr:clientData"].render(r,{}),r.closeNode()}parseClose(r){if(this.parser)return this.parser.parseClose(r)||(this.parser=void 0),!0;switch(r){case this.tag:return this.model.range.tl=this.map["xdr:from"].model,this.model.range.br=this.map["xdr:to"].model,this.model.picture=this.map["xdr:pic"].model,!1;default:return!0}}reconcile(r,n){r.medium=this.reconcilePicture(r.picture,n)}}d.exports=t},{"../static-xform":120,"./base-cell-anchor-xform":56,"./cell-position-xform":61,"./pic-xform":68}],71:[function(e,d,m){const l=e("./base-xform");class c extends l{constructor(s){super(),this.tag=s.tag,this.always=!!s.always,this.count=s.count,this.empty=s.empty,this.$count=s.$count||"count",this.$=s.$,this.childXform=s.childXform,this.maxItems=s.maxItems}prepare(s,t){const{childXform:i}=this;s&&s.forEach((r,n)=>{t.index=n,i.prepare(r,t)})}render(s,t){if(this.always||t&&t.length){s.openNode(this.tag,this.$),this.count&&s.addAttribute(this.$count,t&&t.length||0);const{childXform:i}=this;(t||[]).forEach((r,n)=>{i.render(s,r,n)}),s.closeNode()}else this.empty&&s.leafNode(this.tag)}parseOpen(s){if(this.parser)return this.parser.parseOpen(s),!0;switch(s.name){case this.tag:return this.model=[],!0;default:return this.childXform.parseOpen(s)?(this.parser=this.childXform,!0):!1}}parseText(s){this.parser&&this.parser.parseText(s)}parseClose(s){if(this.parser){if(!this.parser.parseClose(s)&&(this.model.push(this.parser.model),this.parser=void 0,this.maxItems&&this.model.length>this.maxItems))throw new Error(`Max ${this.childXform.tag} count (${this.maxItems}) exceeded`);return!0}return!1}reconcile(s,t){if(s){const{childXform:i}=this;s.forEach(r=>{i.reconcile(r,t)})}}}d.exports=c},{"./base-xform":32}],72:[function(e,d,m){const l=e("../../../utils/col-cache"),c=e("../base-xform");class h extends c{get tag(){return"autoFilter"}render(t,i){if(i)if(typeof i=="string")t.leafNode("autoFilter",{ref:i});else{const r=function(f){return typeof f=="string"?f:l.getAddress(f.row,f.column).address},n=r(i.from),o=r(i.to);n&&o&&t.leafNode("autoFilter",{ref:`${n}:${o}`})}}parseOpen(t){t.name==="autoFilter"&&(this.model=t.attributes.ref)}}d.exports=h},{"../../../utils/col-cache":19,"../base-xform":32}],73:[function(e,d,m){const l=e("../../../utils/utils"),c=e("../base-xform"),h=e("../../../doc/range"),s=e("../../../doc/enums"),t=e("../strings/rich-text-xform");function i(o){if(o==null)return s.ValueType.Null;if(o instanceof String||typeof o=="string")return s.ValueType.String;if(typeof o=="number")return s.ValueType.Number;if(typeof o=="boolean")return s.ValueType.Boolean;if(o instanceof Date)return s.ValueType.Date;if(o.text&&o.hyperlink)return s.ValueType.Hyperlink;if(o.formula)return s.ValueType.Formula;if(o.error)return s.ValueType.Error;throw new Error("I could not understand type of value")}function r(o){switch(o.type){case s.ValueType.Formula:return i(o.result);default:return o.type}}class n extends c{constructor(){super(),this.richTextXForm=new t}get tag(){return"c"}prepare(f,a){const g=a.styles.addStyleModel(f.style||{},r(f));switch(g&&(f.styleId=g),f.comment&&a.comments.push({...f.comment,ref:f.address}),f.type){case s.ValueType.String:case s.ValueType.RichText:a.sharedStrings&&(f.ssId=a.sharedStrings.add(f.value));break;case s.ValueType.Date:a.date1904&&(f.date1904=!0);break;case s.ValueType.Hyperlink:a.sharedStrings&&f.text!==void 0&&f.text!==null&&(f.ssId=a.sharedStrings.add(f.text)),a.hyperlinks.push({address:f.address,target:f.hyperlink,tooltip:f.tooltip});break;case s.ValueType.Merge:a.merges.add(f);break;case s.ValueType.Formula:if(a.date1904&&(f.date1904=!0),f.shareType==="shared"&&(f.si=a.siFormulae++),f.formula)a.formulae[f.address]=f;else if(f.sharedFormula){const b=a.formulae[f.sharedFormula];if(!b)throw new Error(`Shared Formula master must exist above and or left of clone for cell ${f.address}`);b.si===void 0?(b.shareType="shared",b.si=a.siFormulae++,b.range=new h(b.address,f.address)):b.range&&b.range.expandToAddress(f.address),f.si=b.si}break}}renderFormula(f,a){let g=null;switch(a.shareType){case"shared":g={t:"shared",ref:a.ref||a.range.range,si:a.si};break;case"array":g={t:"array",ref:a.ref};break;default:a.si!==void 0&&(g={t:"shared",si:a.si});break}switch(i(a.result)){case s.ValueType.Null:f.leafNode("f",g,a.formula);break;case s.ValueType.String:f.addAttribute("t","str"),f.leafNode("f",g,a.formula),f.leafNode("v",null,a.result);break;case s.ValueType.Number:f.leafNode("f",g,a.formula),f.leafNode("v",null,a.result);break;case s.ValueType.Boolean:f.addAttribute("t","b"),f.leafNode("f",g,a.formula),f.leafNode("v",null,a.result?1:0);break;case s.ValueType.Error:f.addAttribute("t","e"),f.leafNode("f",g,a.formula),f.leafNode("v",null,a.result.error);break;case s.ValueType.Date:f.leafNode("f",g,a.formula),f.leafNode("v",null,l.dateToExcel(a.result,a.date1904));break;default:throw new Error("I could not understand type of value")}}render(f,a){if(!(a.type===s.ValueType.Null&&!a.styleId)){switch(f.openNode("c"),f.addAttribute("r",a.address),a.styleId&&f.addAttribute("s",a.styleId),a.type){case s.ValueType.Null:break;case s.ValueType.Number:f.leafNode("v",null,a.value);break;case s.ValueType.Boolean:f.addAttribute("t","b"),f.leafNode("v",null,a.value?"1":"0");break;case s.ValueType.Error:f.addAttribute("t","e"),f.leafNode("v",null,a.value.error);break;case s.ValueType.String:case s.ValueType.RichText:a.ssId!==void 0?(f.addAttribute("t","s"),f.leafNode("v",null,a.ssId)):a.value&&a.value.richText?(f.addAttribute("t","inlineStr"),f.openNode("is"),a.value.richText.forEach(g=>{this.richTextXForm.render(f,g)}),f.closeNode("is")):(f.addAttribute("t","str"),f.leafNode("v",null,a.value));break;case s.ValueType.Date:f.leafNode("v",null,l.dateToExcel(a.value,a.date1904));break;case s.ValueType.Hyperlink:a.ssId!==void 0?(f.addAttribute("t","s"),f.leafNode("v",null,a.ssId)):(f.addAttribute("t","str"),f.leafNode("v",null,a.text));break;case s.ValueType.Formula:this.renderFormula(f,a);break;case s.ValueType.Merge:break}f.closeNode()}}parseOpen(f){if(this.parser)return this.parser.parseOpen(f),!0;switch(f.name){case"c":return this.model={address:f.attributes.r},this.t=f.attributes.t,f.attributes.s&&(this.model.styleId=parseInt(f.attributes.s,10)),!0;case"f":return this.currentNode="f",this.model.si=f.attributes.si,this.model.shareType=f.attributes.t,this.model.ref=f.attributes.ref,!0;case"v":return this.currentNode="v",!0;case"t":return this.currentNode="t",!0;case"r":return this.parser=this.richTextXForm,this.parser.parseOpen(f),!0;default:return!1}}parseText(f){if(this.parser){this.parser.parseText(f);return}switch(this.currentNode){case"f":this.model.formula=this.model.formula?this.model.formula+f:f;break;case"v":case"t":this.model.value&&this.model.value.richText?this.model.value.richText.text=this.model.value.richText.text?this.model.value.richText.text+f:f:this.model.value=this.model.value?this.model.value+f:f;break}}parseClose(f){switch(f){case"c":{const{model:a}=this;if(a.formula||a.shareType)a.type=s.ValueType.Formula,a.value&&(this.t==="str"?a.result=l.xmlDecode(a.value):this.t==="b"?a.result=parseInt(a.value,10)!==0:this.t==="e"?a.result={error:a.value}:a.result=parseFloat(a.value),a.value=void 0);else if(a.value!==void 0)switch(this.t){case"s":a.type=s.ValueType.String,a.value=parseInt(a.value,10);break;case"str":a.type=s.ValueType.String,a.value=l.xmlDecode(a.value);break;case"inlineStr":a.type=s.ValueType.String;break;case"b":a.type=s.ValueType.Boolean,a.value=parseInt(a.value,10)!==0;break;case"e":a.type=s.ValueType.Error,a.value={error:a.value};break;default:a.type=s.ValueType.Number,a.value=parseFloat(a.value);break}else a.styleId?a.type=s.ValueType.Null:a.type=s.ValueType.Merge;return!1}case"f":case"v":case"is":return this.currentNode=void 0,!0;case"t":return this.parser?(this.parser.parseClose(f),!0):(this.currentNode=void 0,!0);case"r":return this.model.value=this.model.value||{},this.model.value.richText=this.model.value.richText||[],this.model.value.richText.push(this.parser.model),this.parser=void 0,this.currentNode=void 0,!0;default:return this.parser?(this.parser.parseClose(f),!0):!1}}reconcile(f,a){const g=f.styleId&&a.styles&&a.styles.getStyleModel(f.styleId);switch(g&&(f.style=g),f.styleId!==void 0&&(f.styleId=void 0),f.type){case s.ValueType.String:typeof f.value=="number"&&a.sharedStrings&&(f.value=a.sharedStrings.getString(f.value)),f.value.richText&&(f.type=s.ValueType.RichText);break;case s.ValueType.Number:g&&l.isDateFmt(g.numFmt)&&(f.type=s.ValueType.Date,f.value=l.excelToDate(f.value,a.date1904));break;case s.ValueType.Formula:f.result!==void 0&&g&&l.isDateFmt(g.numFmt)&&(f.result=l.excelToDate(f.result,a.date1904)),f.shareType==="shared"&&(f.ref?a.formulae[f.si]=f.address:(f.sharedFormula=a.formulae[f.si],delete f.shareType),delete f.si);break}const b=a.hyperlinkMap[f.address];b&&(f.type===s.ValueType.Formula?(f.text=f.result,f.result=void 0):(f.text=f.value,f.value=void 0),f.type=s.ValueType.Hyperlink,f.hyperlink=b);const u=a.commentsMap&&a.commentsMap[f.address];u&&(f.comment=u)}}d.exports=n},{"../../../doc/enums":7,"../../../doc/range":10,"../../../utils/utils":27,"../base-xform":32,"../strings/rich-text-xform":122}],74:[function(e,d,m){const l=e("../../base-xform");class c extends l{get tag(){return"x14:cfIcon"}render(s,t){s.leafNode(this.tag,{iconSet:t.iconSet,iconId:t.iconId})}parseOpen(s){let{attributes:t}=s;this.model={iconSet:t.iconSet,iconId:l.toIntValue(t.iconId)}}parseClose(s){return s!==this.tag}}d.exports=c},{"../../base-xform":32}],75:[function(e,d,m){const{v4:l}=e("uuid"),c=e("../../base-xform"),h=e("../../composite-xform"),s=e("./databar-ext-xform"),t=e("./icon-set-ext-xform"),i={"3Triangles":!0,"3Stars":!0,"5Boxes":!0};class r extends h{constructor(){super(),this.map={"x14:dataBar":this.databarXform=new s,"x14:iconSet":this.iconSetXform=new t}}get tag(){return"x14:cfRule"}static isExt(o){return o.type==="dataBar"?s.isExt(o):!!(o.type==="iconSet"&&(o.custom||i[o.iconSet]))}prepare(o){r.isExt(o)&&(o.x14Id=`{${l()}}`.toUpperCase())}render(o,f){if(r.isExt(f))switch(f.type){case"dataBar":this.renderDataBar(o,f);break;case"iconSet":this.renderIconSet(o,f);break}}renderDataBar(o,f){o.openNode(this.tag,{type:"dataBar",id:f.x14Id}),this.databarXform.render(o,f),o.closeNode()}renderIconSet(o,f){o.openNode(this.tag,{type:"iconSet",priority:f.priority,id:f.x14Id||`{${l()}}`}),this.iconSetXform.render(o,f),o.closeNode()}createNewModel(o){let{attributes:f}=o;return{type:f.type,x14Id:f.id,priority:c.toIntValue(f.priority)}}onParserClose(o,f){Object.assign(this.model,f.model)}}d.exports=r},{"../../base-xform":32,"../../composite-xform":48,"./databar-ext-xform":79,"./icon-set-ext-xform":81,uuid:528}],76:[function(e,d,m){const l=e("../../composite-xform"),c=e("./f-ext-xform");class h extends l{constructor(){super(),this.map={"xm:f":this.fExtXform=new c}}get tag(){return"x14:cfvo"}render(t,i){t.openNode(this.tag,{type:i.type}),i.value!==void 0&&this.fExtXform.render(t,i.value),t.closeNode()}createNewModel(t){return{type:t.attributes.type}}onParserClose(t,i){switch(t){case"xm:f":this.model.value=i.model?parseFloat(i.model):0;break}}}d.exports=h},{"../../composite-xform":48,"./f-ext-xform":80}],77:[function(e,d,m){const l=e("../../composite-xform"),c=e("./sqref-ext-xform"),h=e("./cf-rule-ext-xform");class s extends l{constructor(){super(),this.map={"xm:sqref":this.sqRef=new c,"x14:cfRule":this.cfRule=new h}}get tag(){return"x14:conditionalFormatting"}prepare(i,r){i.rules.forEach(n=>{this.cfRule.prepare(n,r)})}render(i,r){r.rules.some(h.isExt)&&(i.openNode(this.tag,{"xmlns:xm":"http://schemas.microsoft.com/office/excel/2006/main"}),r.rules.filter(h.isExt).forEach(n=>this.cfRule.render(i,n)),this.sqRef.render(i,r.ref),i.closeNode())}createNewModel(){return{rules:[]}}onParserClose(i,r){switch(i){case"xm:sqref":this.model.ref=r.model;break;case"x14:cfRule":this.model.rules.push(r.model);break}}}d.exports=s},{"../../composite-xform":48,"./cf-rule-ext-xform":75,"./sqref-ext-xform":82}],78:[function(e,d,m){const l=e("../../composite-xform"),c=e("./cf-rule-ext-xform"),h=e("./conditional-formatting-ext-xform");class s extends l{constructor(){super(),this.map={"x14:conditionalFormatting":this.cfXform=new h}}get tag(){return"x14:conditionalFormattings"}hasContent(i){return i.hasExtContent===void 0&&(i.hasExtContent=i.some(r=>r.rules.some(c.isExt))),i.hasExtContent}prepare(i,r){i.forEach(n=>{this.cfXform.prepare(n,r)})}render(i,r){this.hasContent(r)&&(i.openNode(this.tag),r.forEach(n=>this.cfXform.render(i,n)),i.closeNode())}createNewModel(){return[]}onParserClose(i,r){this.model.push(r.model)}}d.exports=s},{"../../composite-xform":48,"./cf-rule-ext-xform":75,"./conditional-formatting-ext-xform":77}],79:[function(e,d,m){const l=e("../../base-xform"),c=e("../../composite-xform"),h=e("../../style/color-xform"),s=e("./cfvo-ext-xform");class t extends c{constructor(){super(),this.map={"x14:cfvo":this.cfvoXform=new s,"x14:borderColor":this.borderColorXform=new h("x14:borderColor"),"x14:negativeBorderColor":this.negativeBorderColorXform=new h("x14:negativeBorderColor"),"x14:negativeFillColor":this.negativeFillColorXform=new h("x14:negativeFillColor"),"x14:axisColor":this.axisColorXform=new h("x14:axisColor")}}static isExt(r){return!r.gradient}get tag(){return"x14:dataBar"}render(r,n){r.openNode(this.tag,{minLength:l.toIntAttribute(n.minLength,0,!0),maxLength:l.toIntAttribute(n.maxLength,100,!0),border:l.toBoolAttribute(n.border,!1),gradient:l.toBoolAttribute(n.gradient,!0),negativeBarColorSameAsPositive:l.toBoolAttribute(n.negativeBarColorSameAsPositive,!0),negativeBarBorderColorSameAsPositive:l.toBoolAttribute(n.negativeBarBorderColorSameAsPositive,!0),axisPosition:l.toAttribute(n.axisPosition,"auto"),direction:l.toAttribute(n.direction,"leftToRight")}),n.cfvo.forEach(o=>{this.cfvoXform.render(r,o)}),this.borderColorXform.render(r,n.borderColor),this.negativeBorderColorXform.render(r,n.negativeBorderColor),this.negativeFillColorXform.render(r,n.negativeFillColor),this.axisColorXform.render(r,n.axisColor),r.closeNode()}createNewModel(r){let{attributes:n}=r;return{cfvo:[],minLength:l.toIntValue(n.minLength,0),maxLength:l.toIntValue(n.maxLength,100),border:l.toBoolValue(n.border,!1),gradient:l.toBoolValue(n.gradient,!0),negativeBarColorSameAsPositive:l.toBoolValue(n.negativeBarColorSameAsPositive,!0),negativeBarBorderColorSameAsPositive:l.toBoolValue(n.negativeBarBorderColorSameAsPositive,!0),axisPosition:l.toStringValue(n.axisPosition,"auto"),direction:l.toStringValue(n.direction,"leftToRight")}}onParserClose(r,n){const[,o]=r.split(":");switch(o){case"cfvo":this.model.cfvo.push(n.model);break;default:this.model[o]=n.model;break}}}d.exports=t},{"../../base-xform":32,"../../composite-xform":48,"../../style/color-xform":128,"./cfvo-ext-xform":76}],80:[function(e,d,m){const l=e("../../base-xform");class c extends l{get tag(){return"xm:f"}render(s,t){s.leafNode(this.tag,null,t)}parseOpen(){this.model=""}parseText(s){this.model+=s}parseClose(s){return s!==this.tag}}d.exports=c},{"../../base-xform":32}],81:[function(e,d,m){const l=e("../../base-xform"),c=e("../../composite-xform"),h=e("./cfvo-ext-xform"),s=e("./cf-icon-ext-xform");class t extends c{constructor(){super(),this.map={"x14:cfvo":this.cfvoXform=new h,"x14:cfIcon":this.cfIconXform=new s}}get tag(){return"x14:iconSet"}render(r,n){r.openNode(this.tag,{iconSet:l.toStringAttribute(n.iconSet),reverse:l.toBoolAttribute(n.reverse,!1),showValue:l.toBoolAttribute(n.showValue,!0),custom:l.toBoolAttribute(n.icons,!1)}),n.cfvo.forEach(o=>{this.cfvoXform.render(r,o)}),n.icons&&n.icons.forEach((o,f)=>{o.iconId=f,this.cfIconXform.render(r,o)}),r.closeNode()}createNewModel(r){let{attributes:n}=r;return{cfvo:[],iconSet:l.toStringValue(n.iconSet,"3TrafficLights"),reverse:l.toBoolValue(n.reverse,!1),showValue:l.toBoolValue(n.showValue,!0)}}onParserClose(r,n){const[,o]=r.split(":");switch(o){case"cfvo":this.model.cfvo.push(n.model);break;case"cfIcon":this.model.icons||(this.model.icons=[]),this.model.icons.push(n.model);break;default:this.model[o]=n.model;break}}}d.exports=t},{"../../base-xform":32,"../../composite-xform":48,"./cf-icon-ext-xform":74,"./cfvo-ext-xform":76}],82:[function(e,d,m){const l=e("../../base-xform");class c extends l{get tag(){return"xm:sqref"}render(s,t){s.leafNode(this.tag,null,t)}parseOpen(){this.model=""}parseText(s){this.model+=s}parseClose(s){return s!==this.tag}}d.exports=c},{"../../base-xform":32}],83:[function(e,d,m){const l=e("../../base-xform"),c=e("../../composite-xform"),h=e("../../../../doc/range"),s=e("./databar-xform"),t=e("./ext-lst-ref-xform"),i=e("./formula-xform"),r=e("./color-scale-xform"),n=e("./icon-set-xform"),o={"3Triangles":!0,"3Stars":!0,"5Boxes":!0},f=u=>{if(u.formulae&&u.formulae[0])return u.formulae[0];const w=new h(u.ref),{tl:y}=w;switch(u.operator){case"containsText":return`NOT(ISERROR(SEARCH("${u.text}",${y})))`;case"containsBlanks":return`LEN(TRIM(${y}))=0`;case"notContainsBlanks":return`LEN(TRIM(${y}))>0`;case"containsErrors":return`ISERROR(${y})`;case"notContainsErrors":return`NOT(ISERROR(${y}))`;default:return}},a=u=>{if(u.formulae&&u.formulae[0])return u.formulae[0];const w=new h(u.ref),{tl:y}=w;switch(u.timePeriod){case"thisWeek":return`AND(TODAY()-ROUNDDOWN(${y},0)<=WEEKDAY(TODAY())-1,ROUNDDOWN(${y},0)-TODAY()<=7-WEEKDAY(TODAY()))`;case"lastWeek":return`AND(TODAY()-ROUNDDOWN(${y},0)>=(WEEKDAY(TODAY())),TODAY()-ROUNDDOWN(${y},0)<(WEEKDAY(TODAY())+7))`;case"nextWeek":return`AND(ROUNDDOWN(${y},0)-TODAY()>(7-WEEKDAY(TODAY())),ROUNDDOWN(${y},0)-TODAY()<(15-WEEKDAY(TODAY())))`;case"yesterday":return`FLOOR(${y},1)=TODAY()-1`;case"today":return`FLOOR(${y},1)=TODAY()`;case"tomorrow":return`FLOOR(${y},1)=TODAY()+1`;case"last7Days":return`AND(TODAY()-FLOOR(${y},1)<=6,FLOOR(${y},1)<=TODAY())`;case"lastMonth":return`AND(MONTH(${y})=MONTH(EDATE(TODAY(),0-1)),YEAR(${y})=YEAR(EDATE(TODAY(),0-1)))`;case"thisMonth":return`AND(MONTH(${y})=MONTH(TODAY()),YEAR(${y})=YEAR(TODAY()))`;case"nextMonth":return`AND(MONTH(${y})=MONTH(EDATE(TODAY(),0+1)),YEAR(${y})=YEAR(EDATE(TODAY(),0+1)))`;default:return}},g=u=>{const{type:w,operator:y}=u;switch(w){case"containsText":case"containsBlanks":case"notContainsBlanks":case"containsErrors":case"notContainsErrors":return{type:"containsText",operator:w};default:return{type:w,operator:y}}};class b extends c{constructor(){super(),this.map={dataBar:this.databarXform=new s,extLst:this.extLstRefXform=new t,formula:this.formulaXform=new i,colorScale:this.colorScaleXform=new r,iconSet:this.iconSetXform=new n}}get tag(){return"cfRule"}static isPrimitive(w){return!(w.type==="iconSet"&&(w.custom||o[w.iconSet]))}render(w,y){switch(y.type){case"expression":this.renderExpression(w,y);break;case"cellIs":this.renderCellIs(w,y);break;case"top10":this.renderTop10(w,y);break;case"aboveAverage":this.renderAboveAverage(w,y);break;case"dataBar":this.renderDataBar(w,y);break;case"colorScale":this.renderColorScale(w,y);break;case"iconSet":this.renderIconSet(w,y);break;case"containsText":this.renderText(w,y);break;case"timePeriod":this.renderTimePeriod(w,y);break}}renderExpression(w,y){w.openNode(this.tag,{type:"expression",dxfId:y.dxfId,priority:y.priority}),this.formulaXform.render(w,y.formulae[0]),w.closeNode()}renderCellIs(w,y){w.openNode(this.tag,{type:"cellIs",dxfId:y.dxfId,priority:y.priority,operator:y.operator}),y.formulae.forEach(S=>{this.formulaXform.render(w,S)}),w.closeNode()}renderTop10(w,y){w.leafNode(this.tag,{type:"top10",dxfId:y.dxfId,priority:y.priority,percent:l.toBoolAttribute(y.percent,!1),bottom:l.toBoolAttribute(y.bottom,!1),rank:l.toIntValue(y.rank,10,!0)})}renderAboveAverage(w,y){w.leafNode(this.tag,{type:"aboveAverage",dxfId:y.dxfId,priority:y.priority,aboveAverage:l.toBoolAttribute(y.aboveAverage,!0)})}renderDataBar(w,y){w.openNode(this.tag,{type:"dataBar",priority:y.priority}),this.databarXform.render(w,y),this.extLstRefXform.render(w,y),w.closeNode()}renderColorScale(w,y){w.openNode(this.tag,{type:"colorScale",priority:y.priority}),this.colorScaleXform.render(w,y),w.closeNode()}renderIconSet(w,y){b.isPrimitive(y)&&(w.openNode(this.tag,{type:"iconSet",priority:y.priority}),this.iconSetXform.render(w,y),w.closeNode())}renderText(w,y){w.openNode(this.tag,{type:y.operator,dxfId:y.dxfId,priority:y.priority,operator:l.toStringAttribute(y.operator,"containsText")});const S=f(y);S&&this.formulaXform.render(w,S),w.closeNode()}renderTimePeriod(w,y){w.openNode(this.tag,{type:"timePeriod",dxfId:y.dxfId,priority:y.priority,timePeriod:y.timePeriod});const S=a(y);S&&this.formulaXform.render(w,S),w.closeNode()}createNewModel(w){let{attributes:y}=w;return{...g(y),dxfId:l.toIntValue(y.dxfId),priority:l.toIntValue(y.priority),timePeriod:y.timePeriod,percent:l.toBoolValue(y.percent),bottom:l.toBoolValue(y.bottom),rank:l.toIntValue(y.rank),aboveAverage:l.toBoolValue(y.aboveAverage)}}onParserClose(w,y){switch(w){case"dataBar":case"extLst":case"colorScale":case"iconSet":Object.assign(this.model,y.model);break;case"formula":this.model.formulae=this.model.formulae||[],this.model.formulae.push(y.model);break}}}d.exports=b},{"../../../../doc/range":10,"../../base-xform":32,"../../composite-xform":48,"./color-scale-xform":85,"./databar-xform":88,"./ext-lst-ref-xform":89,"./formula-xform":90,"./icon-set-xform":91}],84:[function(e,d,m){const l=e("../../base-xform");class c extends l{get tag(){return"cfvo"}render(s,t){s.leafNode(this.tag,{type:t.type,val:t.value})}parseOpen(s){this.model={type:s.attributes.type,value:l.toFloatValue(s.attributes.val)}}parseClose(s){return s!==this.tag}}d.exports=c},{"../../base-xform":32}],85:[function(e,d,m){const l=e("../../composite-xform"),c=e("../../style/color-xform"),h=e("./cfvo-xform");class s extends l{constructor(){super(),this.map={cfvo:this.cfvoXform=new h,color:this.colorXform=new c}}get tag(){return"colorScale"}render(i,r){i.openNode(this.tag),r.cfvo.forEach(n=>{this.cfvoXform.render(i,n)}),r.color.forEach(n=>{this.colorXform.render(i,n)}),i.closeNode()}createNewModel(i){return{cfvo:[],color:[]}}onParserClose(i,r){this.model[i].push(r.model)}}d.exports=s},{"../../composite-xform":48,"../../style/color-xform":128,"./cfvo-xform":84}],86:[function(e,d,m){const l=e("../../composite-xform"),c=e("./cf-rule-xform");class h extends l{constructor(){super(),this.map={cfRule:new c}}get tag(){return"conditionalFormatting"}render(t,i){i.rules.some(c.isPrimitive)&&(t.openNode(this.tag,{sqref:i.ref}),i.rules.forEach(r=>{c.isPrimitive(r)&&(r.ref=i.ref,this.map.cfRule.render(t,r))}),t.closeNode())}createNewModel(t){let{attributes:i}=t;return{ref:i.sqref,rules:[]}}onParserClose(t,i){this.model.rules.push(i.model)}}d.exports=h},{"../../composite-xform":48,"./cf-rule-xform":83}],87:[function(e,d,m){const l=e("../../base-xform"),c=e("./conditional-formatting-xform");class h extends l{constructor(){super(),this.cfXform=new c}get tag(){return"conditionalFormatting"}reset(){this.model=[]}prepare(t,i){let r=t.reduce((n,o)=>Math.max(n,...o.rules.map(f=>f.priority||0)),1);t.forEach(n=>{n.rules.forEach(o=>{o.priority||(o.priority=r++),o.style&&(o.dxfId=i.styles.addDxfStyle(o.style))})})}render(t,i){i.forEach(r=>{this.cfXform.render(t,r)})}parseOpen(t){if(this.parser)return this.parser.parseOpen(t),!0;switch(t.name){case"conditionalFormatting":return this.parser=this.cfXform,this.parser.parseOpen(t),!0;default:return!1}}parseText(t){this.parser&&this.parser.parseText(t)}parseClose(t){return this.parser?this.parser.parseClose(t)?!0:(this.model.push(this.parser.model),this.parser=void 0,!1):!1}reconcile(t,i){t.forEach(r=>{r.rules.forEach(n=>{n.dxfId!==void 0&&(n.style=i.styles.getDxfStyle(n.dxfId),delete n.dxfId)})})}}d.exports=h},{"../../base-xform":32,"./conditional-formatting-xform":86}],88:[function(e,d,m){const l=e("../../composite-xform"),c=e("../../style/color-xform"),h=e("./cfvo-xform");class s extends l{constructor(){super(),this.map={cfvo:this.cfvoXform=new h,color:this.colorXform=new c}}get tag(){return"dataBar"}render(i,r){i.openNode(this.tag),r.cfvo.forEach(n=>{this.cfvoXform.render(i,n)}),this.colorXform.render(i,r.color),i.closeNode()}createNewModel(){return{cfvo:[]}}onParserClose(i,r){switch(i){case"cfvo":this.model.cfvo.push(r.model);break;case"color":this.model.color=r.model;break}}}d.exports=s},{"../../composite-xform":48,"../../style/color-xform":128,"./cfvo-xform":84}],89:[function(e,d,m){const l=e("../../base-xform"),c=e("../../composite-xform");class h extends l{get tag(){return"x14:id"}render(r,n){r.leafNode(this.tag,null,n)}parseOpen(){this.model=""}parseText(r){this.model+=r}parseClose(r){return r!==this.tag}}class s extends c{constructor(){super(),this.map={"x14:id":this.idXform=new h}}get tag(){return"ext"}render(r,n){r.openNode(this.tag,{uri:"{B025F937-C7B1-47D3-B67F-A62EFF666E3E}","xmlns:x14":"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"}),this.idXform.render(r,n.x14Id),r.closeNode()}createNewModel(){return{}}onParserClose(r,n){this.model.x14Id=n.model}}class t extends c{constructor(){super(),this.map={ext:new s}}get tag(){return"extLst"}render(r,n){r.openNode(this.tag),this.map.ext.render(r,n),r.closeNode()}createNewModel(){return{}}onParserClose(r,n){Object.assign(this.model,n.model)}}d.exports=t},{"../../base-xform":32,"../../composite-xform":48}],90:[function(e,d,m){const l=e("../../base-xform");class c extends l{get tag(){return"formula"}render(s,t){s.leafNode(this.tag,null,t)}parseOpen(){this.model=""}parseText(s){this.model+=s}parseClose(s){return s!==this.tag}}d.exports=c},{"../../base-xform":32}],91:[function(e,d,m){const l=e("../../base-xform"),c=e("../../composite-xform"),h=e("./cfvo-xform");class s extends c{constructor(){super(),this.map={cfvo:this.cfvoXform=new h}}get tag(){return"iconSet"}render(i,r){i.openNode(this.tag,{iconSet:l.toStringAttribute(r.iconSet,"3TrafficLights"),reverse:l.toBoolAttribute(r.reverse,!1),showValue:l.toBoolAttribute(r.showValue,!0)}),r.cfvo.forEach(n=>{this.cfvoXform.render(i,n)}),i.closeNode()}createNewModel(i){let{attributes:r}=i;return{iconSet:l.toStringValue(r.iconSet,"3TrafficLights"),reverse:l.toBoolValue(r.reverse),showValue:l.toBoolValue(r.showValue),cfvo:[]}}onParserClose(i,r){this.model[i].push(r.model)}}d.exports=s},{"../../base-xform":32,"../../composite-xform":48,"./cfvo-xform":84}],92:[function(e,d,m){const l=e("../../../utils/utils"),c=e("../base-xform");class h extends c{get tag(){return"col"}prepare(t,i){const r=i.styles.addStyleModel(t.style||{});r&&(t.styleId=r)}render(t,i){t.openNode("col"),t.addAttribute("min",i.min),t.addAttribute("max",i.max),i.width&&t.addAttribute("width",i.width),i.styleId&&t.addAttribute("style",i.styleId),i.hidden&&t.addAttribute("hidden","1"),i.bestFit&&t.addAttribute("bestFit","1"),i.outlineLevel&&t.addAttribute("outlineLevel",i.outlineLevel),i.collapsed&&t.addAttribute("collapsed","1"),t.addAttribute("customWidth","1"),t.closeNode()}parseOpen(t){if(t.name==="col"){const i=this.model={min:parseInt(t.attributes.min||"0",10),max:parseInt(t.attributes.max||"0",10),width:t.attributes.width===void 0?void 0:parseFloat(t.attributes.width||"0")};return t.attributes.style&&(i.styleId=parseInt(t.attributes.style,10)),l.parseBoolean(t.attributes.hidden)&&(i.hidden=!0),l.parseBoolean(t.attributes.bestFit)&&(i.bestFit=!0),t.attributes.outlineLevel&&(i.outlineLevel=parseInt(t.attributes.outlineLevel,10)),l.parseBoolean(t.attributes.collapsed)&&(i.collapsed=!0),!0}return!1}parseText(){}parseClose(){return!1}reconcile(t,i){t.styleId&&(t.style=i.styles.getStyleModel(t.styleId))}}d.exports=h},{"../../../utils/utils":27,"../base-xform":32}],93:[function(e,d,m){const l=e("../../../utils/under-dash"),c=e("../../../utils/utils"),h=e("../../../utils/col-cache"),s=e("../base-xform"),t=e("../../../doc/range");function i(f,a,g,b){const u=a[g];u!==void 0?f[g]=u:b!==void 0&&(f[g]=b)}function r(f,a,g,b){const u=a[g];u!==void 0&&(f[g]=c.parseBoolean(u))}function n(f){const a=l.map(f,(u,w)=>({address:w,dataValidation:u,marked:!1})).sort((u,w)=>l.strcmp(u.address,w.address)),g=l.keyBy(a,"address"),b=(u,w,y)=>{for(let S=0;S{if(!u.marked){const w=h.decodeEx(u.address);if(w.dimensions)return g[w.dimensions].marked=!0,{...u.dataValidation,sqref:u.address};let y=1,S=h.encodeAddress(w.row+y,w.col);for(;f[S]&&l.isEqual(u.dataValidation,f[S]);)y++,S=h.encodeAddress(w.row+y,w.col);let E=1;for(;b(w,y,w.col+E);)E++;for(let I=0;I1||E>1){const I=w.row+(y-1),P=w.col+(E-1);return{...u.dataValidation,sqref:`${u.address}:${h.encodeAddress(I,P)}`}}return{...u.dataValidation,sqref:u.address}}return null}).filter(Boolean)}class o extends s{get tag(){return"dataValidations"}render(a,g){const b=n(g);b.length&&(a.openNode("dataValidations",{count:b.length}),b.forEach(u=>{a.openNode("dataValidation"),u.type!=="any"&&(a.addAttribute("type",u.type),u.operator&&u.type!=="list"&&u.operator!=="between"&&a.addAttribute("operator",u.operator),u.allowBlank&&a.addAttribute("allowBlank","1")),u.showInputMessage&&a.addAttribute("showInputMessage","1"),u.promptTitle&&a.addAttribute("promptTitle",u.promptTitle),u.prompt&&a.addAttribute("prompt",u.prompt),u.showErrorMessage&&a.addAttribute("showErrorMessage","1"),u.errorStyle&&a.addAttribute("errorStyle",u.errorStyle),u.errorTitle&&a.addAttribute("errorTitle",u.errorTitle),u.error&&a.addAttribute("error",u.error),a.addAttribute("sqref",u.sqref),(u.formulae||[]).forEach((w,y)=>{a.openNode(`formula${y+1}`),u.type==="date"?a.writeText(c.dateToExcel(new Date(w))):a.writeText(w),a.closeNode()}),a.closeNode()}),a.closeNode())}parseOpen(a){switch(a.name){case"dataValidations":return this.model={},!0;case"dataValidation":{this._address=a.attributes.sqref;const g={type:a.attributes.type||"any",formulae:[]};switch(a.attributes.type&&r(g,a.attributes,"allowBlank"),r(g,a.attributes,"showInputMessage"),r(g,a.attributes,"showErrorMessage"),g.type){case"any":case"list":case"custom":break;default:i(g,a.attributes,"operator","between");break}return i(g,a.attributes,"promptTitle"),i(g,a.attributes,"prompt"),i(g,a.attributes,"errorStyle"),i(g,a.attributes,"errorTitle"),i(g,a.attributes,"error"),this._dataValidation=g,!0}case"formula1":case"formula2":return this._formula=[],!0;default:return!1}}parseText(a){this._formula&&this._formula.push(a)}parseClose(a){switch(a){case"dataValidations":return!1;case"dataValidation":return(!this._dataValidation.formulae||!this._dataValidation.formulae.length)&&(delete this._dataValidation.formulae,delete this._dataValidation.operator),(this._address.split(/\s+/g)||[]).forEach(b=>{b.includes(":")?new t(b).forEachAddress(w=>{this.model[w]=this._dataValidation}):this.model[b]=this._dataValidation}),!0;case"formula1":case"formula2":{let g=this._formula.join("");switch(this._dataValidation.type){case"whole":case"textLength":g=parseInt(g,10);break;case"decimal":g=parseFloat(g);break;case"date":g=c.excelToDate(parseFloat(g));break}return this._dataValidation.formulae.push(g),this._formula=void 0,!0}default:return!0}}}d.exports=o},{"../../../doc/range":10,"../../../utils/col-cache":19,"../../../utils/under-dash":26,"../../../utils/utils":27,"../base-xform":32}],94:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"dimension"}render(s,t){t&&s.leafNode("dimension",{ref:t})}parseOpen(s){return s.name==="dimension"?(this.model=s.attributes.ref,!0):!1}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],95:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"drawing"}render(s,t){t&&s.leafNode(this.tag,{"r:id":t.rId})}parseOpen(s){switch(s.name){case this.tag:return this.model={rId:s.attributes["r:id"]},!0;default:return!1}}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],96:[function(e,d,m){const l=e("../composite-xform"),c=e("./cf-ext/conditional-formattings-ext-xform");class h extends l{constructor(){super(),this.map={"x14:conditionalFormattings":this.conditionalFormattings=new c}}get tag(){return"ext"}hasContent(i){return this.conditionalFormattings.hasContent(i.conditionalFormattings)}prepare(i,r){this.conditionalFormattings.prepare(i.conditionalFormattings,r)}render(i,r){i.openNode("ext",{uri:"{78C0D931-6437-407d-A8EE-F0AAD7539E65}","xmlns:x14":"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"}),this.conditionalFormattings.render(i,r.conditionalFormattings),i.closeNode()}createNewModel(){return{}}onParserClose(i,r){this.model[i]=r.model}}class s extends l{constructor(){super(),this.map={ext:this.ext=new h}}get tag(){return"extLst"}prepare(i,r){this.ext.prepare(i,r)}hasContent(i){return this.ext.hasContent(i)}render(i,r){this.hasContent(r)&&(i.openNode("extLst"),this.ext.render(i,r),i.closeNode())}createNewModel(){return{}}onParserClose(i,r){Object.assign(this.model,r.model)}}d.exports=s},{"../composite-xform":48,"./cf-ext/conditional-formattings-ext-xform":78}],97:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"headerFooter"}render(s,t){if(t){s.addRollback();let i=!1;s.openNode("headerFooter"),t.differentFirst&&(s.addAttribute("differentFirst","1"),i=!0),t.differentOddEven&&(s.addAttribute("differentOddEven","1"),i=!0),t.oddHeader&&typeof t.oddHeader=="string"&&(s.leafNode("oddHeader",null,t.oddHeader),i=!0),t.oddFooter&&typeof t.oddFooter=="string"&&(s.leafNode("oddFooter",null,t.oddFooter),i=!0),t.evenHeader&&typeof t.evenHeader=="string"&&(s.leafNode("evenHeader",null,t.evenHeader),i=!0),t.evenFooter&&typeof t.evenFooter=="string"&&(s.leafNode("evenFooter",null,t.evenFooter),i=!0),t.firstHeader&&typeof t.firstHeader=="string"&&(s.leafNode("firstHeader",null,t.firstHeader),i=!0),t.firstFooter&&typeof t.firstFooter=="string"&&(s.leafNode("firstFooter",null,t.firstFooter),i=!0),i?(s.closeNode(),s.commit()):s.rollback()}}parseOpen(s){switch(s.name){case"headerFooter":return this.model={},s.attributes.differentFirst&&(this.model.differentFirst=parseInt(s.attributes.differentFirst,0)===1),s.attributes.differentOddEven&&(this.model.differentOddEven=parseInt(s.attributes.differentOddEven,0)===1),!0;case"oddHeader":return this.currentNode="oddHeader",!0;case"oddFooter":return this.currentNode="oddFooter",!0;case"evenHeader":return this.currentNode="evenHeader",!0;case"evenFooter":return this.currentNode="evenFooter",!0;case"firstHeader":return this.currentNode="firstHeader",!0;case"firstFooter":return this.currentNode="firstFooter",!0;default:return!1}}parseText(s){switch(this.currentNode){case"oddHeader":this.model.oddHeader=s;break;case"oddFooter":this.model.oddFooter=s;break;case"evenHeader":this.model.evenHeader=s;break;case"evenFooter":this.model.evenFooter=s;break;case"firstHeader":this.model.firstHeader=s;break;case"firstFooter":this.model.firstFooter=s;break}}parseClose(){switch(this.currentNode){case"oddHeader":case"oddFooter":case"evenHeader":case"evenFooter":case"firstHeader":case"firstFooter":return this.currentNode=void 0,!0;default:return!1}}}d.exports=c},{"../base-xform":32}],98:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"hyperlink"}render(s,t){this.isInternalLink(t)?s.leafNode("hyperlink",{ref:t.address,"r:id":t.rId,tooltip:t.tooltip,location:t.target}):s.leafNode("hyperlink",{ref:t.address,"r:id":t.rId,tooltip:t.tooltip})}parseOpen(s){return s.name==="hyperlink"?(this.model={address:s.attributes.ref,rId:s.attributes["r:id"],tooltip:s.attributes.tooltip},s.attributes.location&&(this.model.target=s.attributes.location),!0):!1}parseText(){}parseClose(){return!1}isInternalLink(s){return s.target&&/^[^!]+![a-zA-Z]+[\d]+$/.test(s.target)}}d.exports=c},{"../base-xform":32}],99:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"mergeCell"}render(s,t){s.leafNode("mergeCell",{ref:t})}parseOpen(s){return s.name==="mergeCell"?(this.model=s.attributes.ref,!0):!1}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],100:[function(e,d,m){const l=e("../../../utils/under-dash"),c=e("../../../doc/range"),h=e("../../../utils/col-cache"),s=e("../../../doc/enums");class t{constructor(){this.merges={}}add(r){if(this.merges[r.master])this.merges[r.master].expandToAddress(r.address);else{const n=`${r.master}:${r.address}`;this.merges[r.master]=new c(n)}}get mergeCells(){return l.map(this.merges,r=>r.range)}reconcile(r,n){l.each(r,o=>{const f=h.decode(o);for(let a=f.top;a<=f.bottom;a++){const g=n[a-1];for(let b=f.left;b<=f.right;b++){const u=g.cells[b-1];u?u.type===s.ValueType.Merge&&(u.master=f.tl):g.cells[b]={type:s.ValueType.Null,address:h.encodeAddress(a,b)}}}})}getMasterAddress(r){const n=this.hash[r];return n&&n.tl}}d.exports=t},{"../../../doc/enums":7,"../../../doc/range":10,"../../../utils/col-cache":19,"../../../utils/under-dash":26}],101:[function(e,d,m){const l=e("../base-xform"),c=s=>typeof s<"u";class h extends l{get tag(){return"outlinePr"}render(t,i){return i&&(c(i.summaryBelow)||c(i.summaryRight))?(t.leafNode(this.tag,{summaryBelow:c(i.summaryBelow)?Number(i.summaryBelow):void 0,summaryRight:c(i.summaryRight)?Number(i.summaryRight):void 0}),!0):!1}parseOpen(t){return t.name===this.tag?(this.model={summaryBelow:c(t.attributes.summaryBelow)?!!Number(t.attributes.summaryBelow):void 0,summaryRight:c(t.attributes.summaryRight)?!!Number(t.attributes.summaryRight):void 0},!0):!1}parseText(){}parseClose(){return!1}}d.exports=h},{"../base-xform":32}],102:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"brk"}render(s,t){s.leafNode("brk",t)}parseOpen(s){return s.name==="brk"?(this.model=s.attributes.ref,!0):!1}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],103:[function(e,d,m){const l=e("../../../utils/under-dash"),c=e("../base-xform");class h extends c{get tag(){return"pageMargins"}render(t,i){if(i){const r={left:i.left,right:i.right,top:i.top,bottom:i.bottom,header:i.header,footer:i.footer};l.some(r,n=>n!==void 0)&&t.leafNode(this.tag,r)}}parseOpen(t){switch(t.name){case this.tag:return this.model={left:parseFloat(t.attributes.left||.7),right:parseFloat(t.attributes.right||.7),top:parseFloat(t.attributes.top||.75),bottom:parseFloat(t.attributes.bottom||.75),header:parseFloat(t.attributes.header||.3),footer:parseFloat(t.attributes.footer||.3)},!0;default:return!1}}parseText(){}parseClose(){return!1}}d.exports=h},{"../../../utils/under-dash":26,"../base-xform":32}],104:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"pageSetUpPr"}render(s,t){return t&&t.fitToPage?(s.leafNode(this.tag,{fitToPage:t.fitToPage?"1":void 0}),!0):!1}parseOpen(s){return s.name===this.tag?(this.model={fitToPage:s.attributes.fitToPage==="1"},!0):!1}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],105:[function(e,d,m){const l=e("../../../utils/under-dash"),c=e("../base-xform");function h(o){return o?"1":void 0}function s(o){switch(o){case"overThenDown":return o;default:return}}function t(o){switch(o){case"atEnd":case"asDisplyed":return o;default:return}}function i(o){switch(o){case"dash":case"blank":case"NA":return o;default:return}}function r(o){return o!==void 0?parseInt(o,10):void 0}class n extends c{get tag(){return"pageSetup"}render(f,a){if(a){const g={paperSize:a.paperSize,orientation:a.orientation,horizontalDpi:a.horizontalDpi,verticalDpi:a.verticalDpi,pageOrder:s(a.pageOrder),blackAndWhite:h(a.blackAndWhite),draft:h(a.draft),cellComments:t(a.cellComments),errors:i(a.errors),scale:a.scale,fitToWidth:a.fitToWidth,fitToHeight:a.fitToHeight,firstPageNumber:a.firstPageNumber,useFirstPageNumber:h(a.firstPageNumber),usePrinterDefaults:h(a.usePrinterDefaults),copies:a.copies};l.some(g,b=>b!==void 0)&&f.leafNode(this.tag,g)}}parseOpen(f){switch(f.name){case this.tag:return this.model={paperSize:r(f.attributes.paperSize),orientation:f.attributes.orientation||"portrait",horizontalDpi:parseInt(f.attributes.horizontalDpi||"4294967295",10),verticalDpi:parseInt(f.attributes.verticalDpi||"4294967295",10),pageOrder:f.attributes.pageOrder||"downThenOver",blackAndWhite:f.attributes.blackAndWhite==="1",draft:f.attributes.draft==="1",cellComments:f.attributes.cellComments||"None",errors:f.attributes.errors||"displayed",scale:parseInt(f.attributes.scale||"100",10),fitToWidth:parseInt(f.attributes.fitToWidth||"1",10),fitToHeight:parseInt(f.attributes.fitToHeight||"1",10),firstPageNumber:parseInt(f.attributes.firstPageNumber||"1",10),useFirstPageNumber:f.attributes.useFirstPageNumber==="1",usePrinterDefaults:f.attributes.usePrinterDefaults==="1",copies:parseInt(f.attributes.copies||"1",10)},!0;default:return!1}}parseText(){}parseClose(){return!1}}d.exports=n},{"../../../utils/under-dash":26,"../base-xform":32}],106:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"picture"}render(s,t){t&&s.leafNode(this.tag,{"r:id":t.rId})}parseOpen(s){switch(s.name){case this.tag:return this.model={rId:s.attributes["r:id"]},!0;default:return!1}}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],107:[function(e,d,m){const l=e("../../../utils/under-dash"),c=e("../base-xform");function h(t){return t?"1":void 0}class s extends c{get tag(){return"printOptions"}render(i,r){if(r){const n={headings:h(r.showRowColHeaders),gridLines:h(r.showGridLines),horizontalCentered:h(r.horizontalCentered),verticalCentered:h(r.verticalCentered)};l.some(n,o=>o!==void 0)&&i.leafNode(this.tag,n)}}parseOpen(i){switch(i.name){case this.tag:return this.model={showRowColHeaders:i.attributes.headings==="1",showGridLines:i.attributes.gridLines==="1",horizontalCentered:i.attributes.horizontalCentered==="1",verticalCentered:i.attributes.verticalCentered==="1"},!0;default:return!1}}parseText(){}parseClose(){return!1}}d.exports=s},{"../../../utils/under-dash":26,"../base-xform":32}],108:[function(e,d,m){const l=e("./page-breaks-xform"),c=e("../list-xform");class h extends c{constructor(){const t={tag:"rowBreaks",count:!0,childXform:new l};super(t)}render(t,i){if(i&&i.length){t.openNode(this.tag,this.$),this.count&&(t.addAttribute(this.$count,i.length),t.addAttribute("manualBreakCount",i.length));const{childXform:r}=this;i.forEach(n=>{r.render(t,n)}),t.closeNode()}else this.empty&&t.leafNode(this.tag)}}d.exports=h},{"../list-xform":71,"./page-breaks-xform":102}],109:[function(e,d,m){const l=e("../base-xform"),c=e("../../../utils/utils"),h=e("./cell-xform");class s extends l{constructor(i){super(),this.maxItems=i&&i.maxItems,this.map={c:new h}}get tag(){return"row"}prepare(i,r){const n=r.styles.addStyleModel(i.style);n&&(i.styleId=n);const o=this.map.c;i.cells.forEach(f=>{o.prepare(f,r)})}render(i,r,n){i.openNode("row"),i.addAttribute("r",r.number),r.height&&(i.addAttribute("ht",r.height),i.addAttribute("customHeight","1")),r.hidden&&i.addAttribute("hidden","1"),r.min>0&&r.max>0&&r.min<=r.max&&i.addAttribute("spans",`${r.min}:${r.max}`),r.styleId&&(i.addAttribute("s",r.styleId),i.addAttribute("customFormat","1")),i.addAttribute("x14ac:dyDescent","0.25"),r.outlineLevel&&i.addAttribute("outlineLevel",r.outlineLevel),r.collapsed&&i.addAttribute("collapsed","1");const o=this.map.c;r.cells.forEach(f=>{o.render(i,f,n)}),i.closeNode()}parseOpen(i){if(this.parser)return this.parser.parseOpen(i),!0;if(i.name==="row"){this.numRowsSeen+=1;const r=i.attributes.spans?i.attributes.spans.split(":").map(o=>parseInt(o,10)):[void 0,void 0],n=this.model={number:parseInt(i.attributes.r,10),min:r[0],max:r[1],cells:[]};return i.attributes.s&&(n.styleId=parseInt(i.attributes.s,10)),c.parseBoolean(i.attributes.hidden)&&(n.hidden=!0),c.parseBoolean(i.attributes.bestFit)&&(n.bestFit=!0),i.attributes.ht&&(n.height=parseFloat(i.attributes.ht)),i.attributes.outlineLevel&&(n.outlineLevel=parseInt(i.attributes.outlineLevel,10)),c.parseBoolean(i.attributes.collapsed)&&(n.collapsed=!0),!0}return this.parser=this.map[i.name],this.parser?(this.parser.parseOpen(i),!0):!1}parseText(i){this.parser&&this.parser.parseText(i)}parseClose(i){if(this.parser){if(!this.parser.parseClose(i)){if(this.model.cells.push(this.parser.model),this.maxItems&&this.model.cells.length>this.maxItems)throw new Error(`Max column count (${this.maxItems}) exceeded`);this.parser=void 0}return!0}return!1}reconcile(i,r){i.style=i.styleId?r.styles.getStyleModel(i.styleId):{},i.styleId!==void 0&&(i.styleId=void 0);const n=this.map.c;i.cells.forEach(o=>{n.reconcile(o,r)})}}d.exports=s},{"../../../utils/utils":27,"../base-xform":32,"./cell-xform":73}],110:[function(e,d,m){const l=e("../../../utils/under-dash"),c=e("../base-xform");class h extends c{get tag(){return"sheetFormatPr"}render(t,i){if(i){const r={defaultRowHeight:i.defaultRowHeight,outlineLevelRow:i.outlineLevelRow,outlineLevelCol:i.outlineLevelCol,"x14ac:dyDescent":i.dyDescent};i.defaultColWidth&&(r.defaultColWidth=i.defaultColWidth),(!i.defaultRowHeight||i.defaultRowHeight!==15)&&(r.customHeight="1"),l.some(r,n=>n!==void 0)&&t.leafNode("sheetFormatPr",r)}}parseOpen(t){return t.name==="sheetFormatPr"?(this.model={defaultRowHeight:parseFloat(t.attributes.defaultRowHeight||"0"),dyDescent:parseFloat(t.attributes["x14ac:dyDescent"]||"0"),outlineLevelRow:parseInt(t.attributes.outlineLevelRow||"0",10),outlineLevelCol:parseInt(t.attributes.outlineLevelCol||"0",10)},t.attributes.defaultColWidth&&(this.model.defaultColWidth=parseFloat(t.attributes.defaultColWidth)),!0):!1}parseText(){}parseClose(){return!1}}d.exports=h},{"../../../utils/under-dash":26,"../base-xform":32}],111:[function(e,d,m){const l=e("../base-xform"),c=e("../style/color-xform"),h=e("./page-setup-properties-xform"),s=e("./outline-properties-xform");class t extends l{constructor(){super(),this.map={tabColor:new c("tabColor"),pageSetUpPr:new h,outlinePr:new s}}get tag(){return"sheetPr"}render(r,n){if(n){r.addRollback(),r.openNode("sheetPr");let o=!1;o=this.map.tabColor.render(r,n.tabColor)||o,o=this.map.pageSetUpPr.render(r,n.pageSetup)||o,o=this.map.outlinePr.render(r,n.outlineProperties)||o,o?(r.closeNode(),r.commit()):r.rollback()}}parseOpen(r){return this.parser?(this.parser.parseOpen(r),!0):r.name===this.tag?(this.reset(),!0):this.map[r.name]?(this.parser=this.map[r.name],this.parser.parseOpen(r),!0):!1}parseText(r){return this.parser?(this.parser.parseText(r),!0):!1}parseClose(r){return this.parser?(this.parser.parseClose(r)||(this.parser=void 0),!0):(this.map.tabColor.model||this.map.pageSetUpPr.model||this.map.outlinePr.model?(this.model={},this.map.tabColor.model&&(this.model.tabColor=this.map.tabColor.model),this.map.pageSetUpPr.model&&(this.model.pageSetup=this.map.pageSetUpPr.model),this.map.outlinePr.model&&(this.model.outlineProperties=this.map.outlinePr.model)):this.model=null,!1)}}d.exports=t},{"../base-xform":32,"../style/color-xform":128,"./outline-properties-xform":101,"./page-setup-properties-xform":104}],112:[function(e,d,m){const l=e("../../../utils/under-dash"),c=e("../base-xform");function h(i,r){return i?r:void 0}function s(i,r){return i===r?!0:void 0}class t extends c{get tag(){return"sheetProtection"}render(r,n){if(n){const o={sheet:h(n.sheet,"1"),selectLockedCells:n.selectLockedCells===!1?"1":void 0,selectUnlockedCells:n.selectUnlockedCells===!1?"1":void 0,formatCells:h(n.formatCells,"0"),formatColumns:h(n.formatColumns,"0"),formatRows:h(n.formatRows,"0"),insertColumns:h(n.insertColumns,"0"),insertRows:h(n.insertRows,"0"),insertHyperlinks:h(n.insertHyperlinks,"0"),deleteColumns:h(n.deleteColumns,"0"),deleteRows:h(n.deleteRows,"0"),sort:h(n.sort,"0"),autoFilter:h(n.autoFilter,"0"),pivotTables:h(n.pivotTables,"0")};n.sheet&&(o.algorithmName=n.algorithmName,o.hashValue=n.hashValue,o.saltValue=n.saltValue,o.spinCount=n.spinCount,o.objects=h(n.objects===!1,"1"),o.scenarios=h(n.scenarios===!1,"1")),l.some(o,f=>f!==void 0)&&r.leafNode(this.tag,o)}}parseOpen(r){switch(r.name){case this.tag:return this.model={sheet:s(r.attributes.sheet,"1"),objects:r.attributes.objects==="1"?!1:void 0,scenarios:r.attributes.scenarios==="1"?!1:void 0,selectLockedCells:r.attributes.selectLockedCells==="1"?!1:void 0,selectUnlockedCells:r.attributes.selectUnlockedCells==="1"?!1:void 0,formatCells:s(r.attributes.formatCells,"0"),formatColumns:s(r.attributes.formatColumns,"0"),formatRows:s(r.attributes.formatRows,"0"),insertColumns:s(r.attributes.insertColumns,"0"),insertRows:s(r.attributes.insertRows,"0"),insertHyperlinks:s(r.attributes.insertHyperlinks,"0"),deleteColumns:s(r.attributes.deleteColumns,"0"),deleteRows:s(r.attributes.deleteRows,"0"),sort:s(r.attributes.sort,"0"),autoFilter:s(r.attributes.autoFilter,"0"),pivotTables:s(r.attributes.pivotTables,"0")},r.attributes.algorithmName&&(this.model.algorithmName=r.attributes.algorithmName,this.model.hashValue=r.attributes.hashValue,this.model.saltValue=r.attributes.saltValue,this.model.spinCount=parseInt(r.attributes.spinCount,10)),!0;default:return!1}}parseText(){}parseClose(){return!1}}d.exports=t},{"../../../utils/under-dash":26,"../base-xform":32}],113:[function(e,d,m){const l=e("../../../utils/col-cache"),c=e("../base-xform"),h={frozen:"frozen",frozenSplit:"frozen",split:"split"};class s extends c{get tag(){return"sheetView"}prepare(i){switch(i.state){case"frozen":case"split":break;default:i.state="normal";break}}render(i,r){i.openNode("sheetView",{workbookViewId:r.workbookViewId||0});const n=function(b,u,w){w&&i.addAttribute(b,u)};n("rightToLeft","1",r.rightToLeft===!0),n("tabSelected","1",r.tabSelected),n("showRuler","0",r.showRuler===!1),n("showRowColHeaders","0",r.showRowColHeaders===!1),n("showGridLines","0",r.showGridLines===!1),n("zoomScale",r.zoomScale,r.zoomScale),n("zoomScaleNormal",r.zoomScaleNormal,r.zoomScaleNormal),n("view",r.style,r.style);let o,f,a,g;switch(r.state){case"frozen":f=r.xSplit||0,a=r.ySplit||0,o=r.topLeftCell||l.getAddress(a+1,f+1).address,g=r.xSplit&&r.ySplit&&"bottomRight"||r.xSplit&&"topRight"||"bottomLeft",i.leafNode("pane",{xSplit:r.xSplit||void 0,ySplit:r.ySplit||void 0,topLeftCell:o,activePane:g,state:"frozen"}),i.leafNode("selection",{pane:g,activeCell:r.activeCell,sqref:r.activeCell});break;case"split":r.activePane==="topLeft"&&(r.activePane=void 0),i.leafNode("pane",{xSplit:r.xSplit||void 0,ySplit:r.ySplit||void 0,topLeftCell:r.topLeftCell,activePane:r.activePane}),i.leafNode("selection",{pane:r.activePane,activeCell:r.activeCell,sqref:r.activeCell});break;case"normal":r.activeCell&&i.leafNode("selection",{activeCell:r.activeCell,sqref:r.activeCell});break}i.closeNode()}parseOpen(i){switch(i.name){case"sheetView":return this.sheetView={workbookViewId:parseInt(i.attributes.workbookViewId,10),rightToLeft:i.attributes.rightToLeft==="1",tabSelected:i.attributes.tabSelected==="1",showRuler:i.attributes.showRuler!=="0",showRowColHeaders:i.attributes.showRowColHeaders!=="0",showGridLines:i.attributes.showGridLines!=="0",zoomScale:parseInt(i.attributes.zoomScale||"100",10),zoomScaleNormal:parseInt(i.attributes.zoomScaleNormal||"100",10),style:i.attributes.view},this.pane=void 0,this.selections={},!0;case"pane":return this.pane={xSplit:parseInt(i.attributes.xSplit||"0",10),ySplit:parseInt(i.attributes.ySplit||"0",10),topLeftCell:i.attributes.topLeftCell,activePane:i.attributes.activePane||"topLeft",state:i.attributes.state},!0;case"selection":{const r=i.attributes.pane||"topLeft";return this.selections[r]={pane:r,activeCell:i.attributes.activeCell},!0}default:return!1}}parseText(){}parseClose(i){let r,n;switch(i){case"sheetView":return this.sheetView&&this.pane?(r=this.model={workbookViewId:this.sheetView.workbookViewId,rightToLeft:this.sheetView.rightToLeft,state:h[this.pane.state]||"split",xSplit:this.pane.xSplit,ySplit:this.pane.ySplit,topLeftCell:this.pane.topLeftCell,showRuler:this.sheetView.showRuler,showRowColHeaders:this.sheetView.showRowColHeaders,showGridLines:this.sheetView.showGridLines,zoomScale:this.sheetView.zoomScale,zoomScaleNormal:this.sheetView.zoomScaleNormal},this.model.state==="split"&&(r.activePane=this.pane.activePane),n=this.selections[this.pane.activePane],n&&n.activeCell&&(r.activeCell=n.activeCell),this.sheetView.style&&(r.style=this.sheetView.style)):(r=this.model={workbookViewId:this.sheetView.workbookViewId,rightToLeft:this.sheetView.rightToLeft,state:"normal",showRuler:this.sheetView.showRuler,showRowColHeaders:this.sheetView.showRowColHeaders,showGridLines:this.sheetView.showGridLines,zoomScale:this.sheetView.zoomScale,zoomScaleNormal:this.sheetView.zoomScaleNormal},n=this.selections.topLeft,n&&n.activeCell&&(r.activeCell=n.activeCell),this.sheetView.style&&(r.style=this.sheetView.style)),!1;default:return!0}}reconcile(){}}d.exports=s},{"../../../utils/col-cache":19,"../base-xform":32}],114:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"tablePart"}render(s,t){t&&s.leafNode(this.tag,{"r:id":t.rId})}parseOpen(s){switch(s.name){case this.tag:return this.model={rId:s.attributes["r:id"]},!0;default:return!1}}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],115:[function(e,d,m){const l=e("../../../utils/under-dash"),c=e("../../../utils/col-cache"),h=e("../../../utils/xml-stream"),s=e("../../rel-type"),t=e("./merges"),i=e("../base-xform"),r=e("../list-xform"),n=e("./row-xform"),o=e("./col-xform"),f=e("./dimension-xform"),a=e("./hyperlink-xform"),g=e("./merge-cell-xform"),b=e("./data-validations-xform"),u=e("./sheet-properties-xform"),w=e("./sheet-format-properties-xform"),y=e("./sheet-view-xform"),S=e("./sheet-protection-xform"),E=e("./page-margins-xform"),I=e("./page-setup-xform"),P=e("./print-options-xform"),F=e("./auto-filter-xform"),j=e("./picture-xform"),W=e("./drawing-xform"),G=e("./table-part-xform"),V=e("./row-breaks-xform"),J=e("./header-footer-xform"),$=e("./cf/conditional-formattings-xform"),M=e("./ext-lst-xform"),T=(N,L)=>{Object.keys(L).forEach(z=>{const R=N[z],k=L[z];R===void 0&&k!==void 0&&(N[z]=k)})},x=(N,L)=>{if(!L||!L.length)return N;if(!N||!N.length)return L;const z={},R={};return N.forEach(k=>{z[k.ref]=k,k.rules.forEach(C=>{const{x14Id:O}=C;O&&(R[O]=C)})}),L.forEach(k=>{k.rules.forEach(C=>{const O=R[C.x14Id];O?T(O,C):z[k.ref]?z[k.ref].rules.push(C):N.push({ref:k.ref,rules:[C]})})}),N};class A extends i{constructor(L){super();const{maxRows:z,maxCols:R,ignoreNodes:k}=L||{};this.ignoreNodes=k||[],this.map={sheetPr:new u,dimension:new f,sheetViews:new r({tag:"sheetViews",count:!1,childXform:new y}),sheetFormatPr:new w,cols:new r({tag:"cols",count:!1,childXform:new o}),sheetData:new r({tag:"sheetData",count:!1,empty:!0,childXform:new n({maxItems:R}),maxItems:z}),autoFilter:new F,mergeCells:new r({tag:"mergeCells",count:!0,childXform:new g}),rowBreaks:new V,hyperlinks:new r({tag:"hyperlinks",count:!1,childXform:new a}),pageMargins:new E,dataValidations:new b,pageSetup:new I,headerFooter:new J,printOptions:new P,picture:new j,drawing:new W,sheetProtection:new S,tableParts:new r({tag:"tableParts",count:!0,childXform:new G}),conditionalFormatting:new $,extLst:new M}}prepare(L,z){z.merges=new t,L.hyperlinks=z.hyperlinks=[],L.comments=z.comments=[],z.formulae={},z.siFormulae=0,this.map.cols.prepare(L.cols,z),this.map.sheetData.prepare(L.rows,z),this.map.conditionalFormatting.prepare(L.conditionalFormattings,z),L.mergeCells=z.merges.mergeCells;const R=L.rels=[];function k(X){return`rId${X.length+1}`}if(L.hyperlinks.forEach(X=>{const ie=k(R);X.rId=ie,R.push({Id:ie,Type:s.Hyperlink,Target:X.target,TargetMode:"External"})}),L.comments.length>0){const X={Id:k(R),Type:s.Comments,Target:`../comments${L.id}.xml`};R.push(X);const ie={Id:k(R),Type:s.VmlDrawing,Target:`../drawings/vmlDrawing${L.id}.vml`};R.push(ie),L.comments.forEach(he=>{he.refAddress=c.decodeAddress(he.ref)}),z.commentRefs.push({commentName:`comments${L.id}`,vmlDrawing:`vmlDrawing${L.id}`})}const C=[];let O;L.media.forEach(X=>{if(X.type==="background"){const ie=k(R);O=z.media[X.imageId],R.push({Id:ie,Type:s.Image,Target:`../media/${O.name}.${O.extension}`}),L.background={rId:ie},L.image=z.media[X.imageId]}else if(X.type==="image"){let{drawing:ie}=L;O=z.media[X.imageId],ie||(ie=L.drawing={rId:k(R),name:`drawing${++z.drawingsCount}`,anchors:[],rels:[]},z.drawings.push(ie),R.push({Id:ie.rId,Type:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing",Target:`../drawings/${ie.name}.xml`}));let he=this.preImageId===X.imageId?C[X.imageId]:C[ie.rels.length];he||(he=k(ie.rels),C[ie.rels.length]=he,ie.rels.push({Id:he,Type:"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",Target:`../media/${O.name}.${O.extension}`}));const ue={picture:{rId:he},range:X.range};if(X.hyperlinks&&X.hyperlinks.hyperlink){const ke=k(ie.rels);C[ie.rels.length]=ke,ue.picture.hyperlinks={tooltip:X.hyperlinks.tooltip,rId:ke},ie.rels.push({Id:ke,Type:s.Hyperlink,Target:X.hyperlinks.hyperlink,TargetMode:"External"})}this.preImageId=X.imageId,ie.anchors.push(ue)}}),L.tables.forEach(X=>{const ie=k(R);X.rId=ie,R.push({Id:ie,Type:s.Table,Target:`../tables/${X.target}`}),X.columns.forEach(he=>{const{style:ue}=he;ue&&(he.dxfId=z.styles.addDxfStyle(ue))})}),this.map.extLst.prepare(L,z)}render(L,z){L.openXml(h.StdDocAttributes),L.openNode("worksheet",A.WORKSHEET_ATTRIBUTES);const R=z.properties?{defaultRowHeight:z.properties.defaultRowHeight,dyDescent:z.properties.dyDescent,outlineLevelCol:z.properties.outlineLevelCol,outlineLevelRow:z.properties.outlineLevelRow}:void 0;z.properties&&z.properties.defaultColWidth&&(R.defaultColWidth=z.properties.defaultColWidth);const k={outlineProperties:z.properties&&z.properties.outlineProperties,tabColor:z.properties&&z.properties.tabColor,pageSetup:z.pageSetup&&z.pageSetup.fitToPage?{fitToPage:z.pageSetup.fitToPage}:void 0},C=z.pageSetup&&z.pageSetup.margins,O={showRowColHeaders:z.pageSetup&&z.pageSetup.showRowColHeaders,showGridLines:z.pageSetup&&z.pageSetup.showGridLines,horizontalCentered:z.pageSetup&&z.pageSetup.horizontalCentered,verticalCentered:z.pageSetup&&z.pageSetup.verticalCentered},X=z.sheetProtection;this.map.sheetPr.render(L,k),this.map.dimension.render(L,z.dimensions),this.map.sheetViews.render(L,z.views),this.map.sheetFormatPr.render(L,R),this.map.cols.render(L,z.cols),this.map.sheetData.render(L,z.rows),this.map.sheetProtection.render(L,X),this.map.autoFilter.render(L,z.autoFilter),this.map.mergeCells.render(L,z.mergeCells),this.map.conditionalFormatting.render(L,z.conditionalFormattings),this.map.dataValidations.render(L,z.dataValidations),this.map.hyperlinks.render(L,z.hyperlinks),this.map.printOptions.render(L,O),this.map.pageMargins.render(L,C),this.map.pageSetup.render(L,z.pageSetup),this.map.headerFooter.render(L,z.headerFooter),this.map.rowBreaks.render(L,z.rowBreaks),this.map.drawing.render(L,z.drawing),this.map.picture.render(L,z.background),this.map.tableParts.render(L,z.tables),this.map.extLst.render(L,z),z.rels&&z.rels.forEach(ie=>{ie.Type===s.VmlDrawing&&L.leafNode("legacyDrawing",{"r:id":ie.Id})}),L.closeNode()}parseOpen(L){return this.parser?(this.parser.parseOpen(L),!0):L.name==="worksheet"?(l.each(this.map,z=>{z.reset()}),!0):(this.map[L.name]&&!this.ignoreNodes.includes(L.name)&&(this.parser=this.map[L.name],this.parser.parseOpen(L)),!0)}parseText(L){this.parser&&this.parser.parseText(L)}parseClose(L){if(this.parser)return this.parser.parseClose(L)||(this.parser=void 0),!0;switch(L){case"worksheet":{const z=this.map.sheetFormatPr.model||{};this.map.sheetPr.model&&this.map.sheetPr.model.tabColor&&(z.tabColor=this.map.sheetPr.model.tabColor),this.map.sheetPr.model&&this.map.sheetPr.model.outlineProperties&&(z.outlineProperties=this.map.sheetPr.model.outlineProperties);const R={fitToPage:this.map.sheetPr.model&&this.map.sheetPr.model.pageSetup&&this.map.sheetPr.model.pageSetup.fitToPage||!1,margins:this.map.pageMargins.model},k=Object.assign(R,this.map.pageSetup.model,this.map.printOptions.model),C=x(this.map.conditionalFormatting.model,this.map.extLst.model&&this.map.extLst.model["x14:conditionalFormattings"]);return this.model={dimensions:this.map.dimension.model,cols:this.map.cols.model,rows:this.map.sheetData.model,mergeCells:this.map.mergeCells.model,hyperlinks:this.map.hyperlinks.model,dataValidations:this.map.dataValidations.model,properties:z,views:this.map.sheetViews.model,pageSetup:k,headerFooter:this.map.headerFooter.model,background:this.map.picture.model,drawing:this.map.drawing.model,tables:this.map.tableParts.model,conditionalFormattings:C},this.map.autoFilter.model&&(this.model.autoFilter=this.map.autoFilter.model),this.map.sheetProtection.model&&(this.model.sheetProtection=this.map.sheetProtection.model),!1}default:return!0}}reconcile(L,z){const R=(L.relationships||[]).reduce((C,O)=>{if(C[O.Id]=O,O.Type===s.Comments&&(L.comments=z.comments[O.Target].comments),O.Type===s.VmlDrawing&&L.comments&&L.comments.length){const X=z.vmlDrawings[O.Target].comments;L.comments.forEach((ie,he)=>{ie.note=Object.assign({},ie.note,X[he])})}return C},{});if(z.commentsMap=(L.comments||[]).reduce((C,O)=>(O.ref&&(C[O.ref]=O),C),{}),z.hyperlinkMap=(L.hyperlinks||[]).reduce((C,O)=>(O.rId&&(C[O.address]=R[O.rId].Target),C),{}),z.formulae={},L.rows=L.rows&&L.rows.filter(Boolean)||[],L.rows.forEach(C=>{C.cells=C.cells&&C.cells.filter(Boolean)||[]}),this.map.cols.reconcile(L.cols,z),this.map.sheetData.reconcile(L.rows,z),this.map.conditionalFormatting.reconcile(L.conditionalFormattings,z),L.media=[],L.drawing){const O=R[L.drawing.rId].Target.match(/\/drawings\/([a-zA-Z0-9]+)[.][a-zA-Z]{3,4}$/);if(O){const X=O[1];z.drawings[X].anchors.forEach(he=>{if(he.medium){const ue={type:"image",imageId:he.medium.index,range:he.range,hyperlinks:he.picture.hyperlinks};L.media.push(ue)}})}}const k=L.background&&R[L.background.rId];if(k){const C=k.Target.split("/media/")[1],O=z.mediaIndex&&z.mediaIndex[C];O!==void 0&&L.media.push({type:"background",imageId:O})}L.tables=(L.tables||[]).map(C=>{const O=R[C.rId];return z.tables[O.Target]}),delete L.relationships,delete L.hyperlinks,delete L.comments}}A.WORKSHEET_ATTRIBUTES={xmlns:"http://schemas.openxmlformats.org/spreadsheetml/2006/main","xmlns:r":"http://schemas.openxmlformats.org/officeDocument/2006/relationships","xmlns:mc":"http://schemas.openxmlformats.org/markup-compatibility/2006","mc:Ignorable":"x14ac","xmlns:x14ac":"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"},d.exports=A},{"../../../utils/col-cache":19,"../../../utils/under-dash":26,"../../../utils/xml-stream":28,"../../rel-type":31,"../base-xform":32,"../list-xform":71,"./auto-filter-xform":72,"./cf/conditional-formattings-xform":87,"./col-xform":92,"./data-validations-xform":93,"./dimension-xform":94,"./drawing-xform":95,"./ext-lst-xform":96,"./header-footer-xform":97,"./hyperlink-xform":98,"./merge-cell-xform":99,"./merges":100,"./page-margins-xform":103,"./page-setup-xform":105,"./picture-xform":106,"./print-options-xform":107,"./row-breaks-xform":108,"./row-xform":109,"./sheet-format-properties-xform":110,"./sheet-properties-xform":111,"./sheet-protection-xform":112,"./sheet-view-xform":113,"./table-part-xform":114}],116:[function(e,d,m){const l=e("../base-xform");class c extends l{constructor(s){super(),this.tag=s.tag,this.attr=s.attr}render(s,t){t&&(s.openNode(this.tag),s.closeNode())}parseOpen(s){s.name===this.tag&&(this.model=!0)}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],117:[function(e,d,m){const l=e("../base-xform");class c extends l{constructor(s){super(),this.tag=s.tag,this.attr=s.attr,this.attrs=s.attrs,this._format=s.format||function(t){try{return Number.isNaN(t.getTime())?"":t.toISOString()}catch{return""}},this._parse=s.parse||function(t){return new Date(t)}}render(s,t){t&&(s.openNode(this.tag),this.attrs&&s.addAttributes(this.attrs),this.attr?s.addAttribute(this.attr,this._format(t)):s.writeText(this._format(t)),s.closeNode())}parseOpen(s){s.name===this.tag&&(this.attr?this.model=this._parse(s.attributes[this.attr]):this.text=[])}parseText(s){this.attr||this.text.push(s)}parseClose(){return this.attr||(this.model=this._parse(this.text.join(""))),!1}}d.exports=c},{"../base-xform":32}],118:[function(e,d,m){const l=e("../base-xform");class c extends l{constructor(s){super(),this.tag=s.tag,this.attr=s.attr,this.attrs=s.attrs,this.zero=s.zero}render(s,t){(t||this.zero)&&(s.openNode(this.tag),this.attrs&&s.addAttributes(this.attrs),this.attr?s.addAttribute(this.attr,t):s.writeText(t),s.closeNode())}parseOpen(s){return s.name===this.tag?(this.attr?this.model=parseInt(s.attributes[this.attr],10):this.text=[],!0):!1}parseText(s){this.attr||this.text.push(s)}parseClose(){return this.attr||(this.model=parseInt(this.text.join("")||0,10)),!1}}d.exports=c},{"../base-xform":32}],119:[function(e,d,m){const l=e("../base-xform");class c extends l{constructor(s){super(),this.tag=s.tag,this.attr=s.attr,this.attrs=s.attrs}render(s,t){t!==void 0&&(s.openNode(this.tag),this.attrs&&s.addAttributes(this.attrs),this.attr?s.addAttribute(this.attr,t):s.writeText(t),s.closeNode())}parseOpen(s){s.name===this.tag&&(this.attr?this.model=s.attributes[this.attr]:this.text=[])}parseText(s){this.attr||this.text.push(s)}parseClose(){return this.attr||(this.model=this.text.join("")),!1}}d.exports=c},{"../base-xform":32}],120:[function(e,d,m){const l=e("./base-xform"),c=e("../../utils/xml-stream");function h(t,i){t.openNode(i.tag,i.$),i.c&&i.c.forEach(r=>{h(t,r)}),i.t&&t.writeText(i.t),t.closeNode()}class s extends l{constructor(i){super(),this._model=i}render(i){if(!this._xml){const r=new c;h(r,this._model),this._xml=r.xml}i.writeXml(this._xml)}parseOpen(){return!0}parseText(){}parseClose(i){switch(i){case this._model.tag:return!1;default:return!0}}}d.exports=s},{"../../utils/xml-stream":28,"./base-xform":32}],121:[function(e,d,m){const l=e("./text-xform"),c=e("./rich-text-xform"),h=e("../base-xform");class s extends h{constructor(){super(),this.map={r:new c,t:new l}}get tag(){return"rPh"}render(i,r){if(i.openNode(this.tag,{sb:r.sb||0,eb:r.eb||0}),r&&r.hasOwnProperty("richText")&&r.richText){const{r:n}=this.map;r.richText.forEach(o=>{n.render(i,o)})}else r&&this.map.t.render(i,r.text);i.closeNode()}parseOpen(i){const{name:r}=i;return this.parser?(this.parser.parseOpen(i),!0):r===this.tag?(this.model={sb:parseInt(i.attributes.sb,10),eb:parseInt(i.attributes.eb,10)},!0):(this.parser=this.map[r],this.parser?(this.parser.parseOpen(i),!0):!1)}parseText(i){this.parser&&this.parser.parseText(i)}parseClose(i){if(this.parser){if(!this.parser.parseClose(i)){switch(i){case"r":{let r=this.model.richText;r||(r=this.model.richText=[]),r.push(this.parser.model);break}case"t":this.model.text=this.parser.model;break}this.parser=void 0}return!0}switch(i){case this.tag:return!1;default:return!0}}}d.exports=s},{"../base-xform":32,"./rich-text-xform":122,"./text-xform":125}],122:[function(e,d,m){const l=e("./text-xform"),c=e("../style/font-xform"),h=e("../base-xform");class s extends h{constructor(i){super(),this.model=i}get tag(){return"r"}get textXform(){return this._textXform||(this._textXform=new l)}get fontXform(){return this._fontXform||(this._fontXform=new c(s.FONT_OPTIONS))}render(i,r){r=r||this.model,i.openNode("r"),r.font&&this.fontXform.render(i,r.font),this.textXform.render(i,r.text),i.closeNode()}parseOpen(i){if(this.parser)return this.parser.parseOpen(i),!0;switch(i.name){case"r":return this.model={},!0;case"t":return this.parser=this.textXform,this.parser.parseOpen(i),!0;case"rPr":return this.parser=this.fontXform,this.parser.parseOpen(i),!0;default:return!1}}parseText(i){this.parser&&this.parser.parseText(i)}parseClose(i){switch(i){case"r":return!1;case"t":return this.model.text=this.parser.model,this.parser=void 0,!0;case"rPr":return this.model.font=this.parser.model,this.parser=void 0,!0;default:return this.parser&&this.parser.parseClose(i),!0}}}s.FONT_OPTIONS={tagName:"rPr",fontNameTag:"rFont"},d.exports=s},{"../base-xform":32,"../style/font-xform":131,"./text-xform":125}],123:[function(e,d,m){const l=e("./text-xform"),c=e("./rich-text-xform"),h=e("./phonetic-text-xform"),s=e("../base-xform");class t extends s{constructor(r){super(),this.model=r,this.map={r:new c,t:new l,rPh:new h}}get tag(){return"si"}render(r,n){r.openNode(this.tag),n&&n.hasOwnProperty("richText")&&n.richText?n.richText.length?n.richText.forEach(o=>{this.map.r.render(r,o)}):this.map.t.render(r,""):n!=null&&this.map.t.render(r,n),r.closeNode()}parseOpen(r){const{name:n}=r;return this.parser?(this.parser.parseOpen(r),!0):n===this.tag?(this.model={},!0):(this.parser=this.map[n],this.parser?(this.parser.parseOpen(r),!0):!1)}parseText(r){this.parser&&this.parser.parseText(r)}parseClose(r){if(this.parser){if(!this.parser.parseClose(r)){switch(r){case"r":{let n=this.model.richText;n||(n=this.model.richText=[]),n.push(this.parser.model);break}case"t":this.model=this.parser.model;break}this.parser=void 0}return!0}switch(r){case this.tag:return!1;default:return!0}}}d.exports=t},{"../base-xform":32,"./phonetic-text-xform":121,"./rich-text-xform":122,"./text-xform":125}],124:[function(e,d,m){const l=e("../../../utils/xml-stream"),c=e("../base-xform"),h=e("./shared-string-xform");class s extends c{constructor(i){super(),this.model=i||{values:[],count:0},this.hash=Object.create(null),this.rich=Object.create(null)}get sharedStringXform(){return this._sharedStringXform||(this._sharedStringXform=new h)}get values(){return this.model.values}get uniqueCount(){return this.model.values.length}get count(){return this.model.count}getString(i){return this.model.values[i]}add(i){return i.richText?this.addRichText(i):this.addText(i)}addText(i){let r=this.hash[i];return r===void 0&&(r=this.hash[i]=this.model.values.length,this.model.values.push(i)),this.model.count++,r}addRichText(i){const r=this.sharedStringXform.toXml(i);let n=this.rich[r];return n===void 0&&(n=this.rich[r]=this.model.values.length,this.model.values.push(i)),this.model.count++,n}render(i,r){r=r||this._values,i.openXml(l.StdDocAttributes),i.openNode("sst",{xmlns:"http://schemas.openxmlformats.org/spreadsheetml/2006/main",count:r.count,uniqueCount:r.values.length});const n=this.sharedStringXform;r.values.forEach(o=>{n.render(i,o)}),i.closeNode()}parseOpen(i){if(this.parser)return this.parser.parseOpen(i),!0;switch(i.name){case"sst":return!0;case"si":return this.parser=this.sharedStringXform,this.parser.parseOpen(i),!0;default:throw new Error(`Unexpected xml node in parseOpen: ${JSON.stringify(i)}`)}}parseText(i){this.parser&&this.parser.parseText(i)}parseClose(i){if(this.parser)return this.parser.parseClose(i)||(this.model.values.push(this.parser.model),this.model.count++,this.parser=void 0),!0;switch(i){case"sst":return!1;default:throw new Error(`Unexpected xml node in parseClose: ${i}`)}}}d.exports=s},{"../../../utils/xml-stream":28,"../base-xform":32,"./shared-string-xform":123}],125:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"t"}render(s,t){s.openNode("t"),/^\s|\n|\s$/.test(t)&&s.addAttribute("xml:space","preserve"),s.writeText(t),s.closeNode()}get model(){return this._text.join("").replace(/_x([0-9A-F]{4})_/g,(s,t)=>String.fromCharCode(parseInt(t,16)))}parseOpen(s){switch(s.name){case"t":return this._text=[],!0;default:return!1}}parseText(s){this._text.push(s)}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],126:[function(e,d,m){const l=e("../../../doc/enums"),c=e("../../../utils/utils"),h=e("../base-xform"),s={horizontalValues:["left","center","right","fill","centerContinuous","distributed","justify"].reduce((r,n)=>(r[n]=!0,r),{}),horizontal(r){return this.horizontalValues[r]?r:void 0},verticalValues:["top","middle","bottom","distributed","justify"].reduce((r,n)=>(r[n]=!0,r),{}),vertical(r){return r==="middle"?"center":this.verticalValues[r]?r:void 0},wrapText(r){return r?!0:void 0},shrinkToFit(r){return r?!0:void 0},textRotation(r){switch(r){case"vertical":return r;default:return r=c.validInt(r),r>=-90&&r<=90?r:void 0}},indent(r){return r=c.validInt(r),Math.max(0,r)},readingOrder(r){switch(r){case"ltr":return l.ReadingOrder.LeftToRight;case"rtl":return l.ReadingOrder.RightToLeft;default:return}}},t={toXml(r){if(r=s.textRotation(r),r){if(r==="vertical")return 255;const n=Math.round(r);if(n>=0&&n<=90)return n;if(n<0&&n>=-90)return 90-n}},toModel(r){const n=c.validInt(r);if(n!==void 0){if(n===255)return"vertical";if(n>=0&&n<=90)return n;if(n>90&&n<=180)return 90-n}}};class i extends h{get tag(){return"alignment"}render(n,o){n.addRollback(),n.openNode("alignment");let f=!1;function a(g,b){b&&(n.addAttribute(g,b),f=!0)}a("horizontal",s.horizontal(o.horizontal)),a("vertical",s.vertical(o.vertical)),a("wrapText",s.wrapText(o.wrapText)?"1":!1),a("shrinkToFit",s.shrinkToFit(o.shrinkToFit)?"1":!1),a("indent",s.indent(o.indent)),a("textRotation",t.toXml(o.textRotation)),a("readingOrder",s.readingOrder(o.readingOrder)),n.closeNode(),f?n.commit():n.rollback()}parseOpen(n){const o={};let f=!1;function a(g,b,u){g&&(o[b]=u,f=!0)}a(n.attributes.horizontal,"horizontal",n.attributes.horizontal),a(n.attributes.vertical,"vertical",n.attributes.vertical==="center"?"middle":n.attributes.vertical),a(n.attributes.wrapText,"wrapText",c.parseBoolean(n.attributes.wrapText)),a(n.attributes.shrinkToFit,"shrinkToFit",c.parseBoolean(n.attributes.shrinkToFit)),a(n.attributes.indent,"indent",parseInt(n.attributes.indent,10)),a(n.attributes.textRotation,"textRotation",t.toModel(n.attributes.textRotation)),a(n.attributes.readingOrder,"readingOrder",n.attributes.readingOrder==="2"?"rtl":"ltr"),this.model=f?o:null}parseText(){}parseClose(){return!1}}d.exports=i},{"../../../doc/enums":7,"../../../utils/utils":27,"../base-xform":32}],127:[function(e,d,m){const l=e("../base-xform"),c=e("../../../utils/utils"),h=e("./color-xform");class s extends l{constructor(r){super(),this.name=r,this.map={color:new h}}get tag(){return this.name}render(r,n,o){const f=n&&n.color||o||this.defaultColor;r.openNode(this.name),n&&n.style&&(r.addAttribute("style",n.style),f&&this.map.color.render(r,f)),r.closeNode()}parseOpen(r){if(this.parser)return this.parser.parseOpen(r),!0;switch(r.name){case this.name:{const{style:n}=r.attributes;return n?this.model={style:n}:this.model=void 0,!0}case"color":return this.parser=this.map.color,this.parser.parseOpen(r),!0;default:return!1}}parseText(r){this.parser&&this.parser.parseText(r)}parseClose(r){return this.parser?(this.parser.parseClose(r)||(this.parser=void 0),!0):(r===this.name&&this.map.color.model&&(this.model||(this.model={}),this.model.color=this.map.color.model),!1)}validStyle(r){return s.validStyleValues[r]}}s.validStyleValues=["thin","dashed","dotted","dashDot","hair","dashDotDot","slantDashDot","mediumDashed","mediumDashDotDot","mediumDashDot","medium","double","thick"].reduce((i,r)=>(i[r]=!0,i),{});class t extends l{constructor(){super(),this.map={top:new s("top"),left:new s("left"),bottom:new s("bottom"),right:new s("right"),diagonal:new s("diagonal")}}render(r,n){const{color:o}=n;r.openNode("border"),n.diagonal&&n.diagonal.style&&(n.diagonal.up&&r.addAttribute("diagonalUp","1"),n.diagonal.down&&r.addAttribute("diagonalDown","1"));function f(a,g){a&&!a.color&&n.color&&(a={...a,color:n.color}),g.render(r,a,o)}f(n.left,this.map.left),f(n.right,this.map.right),f(n.top,this.map.top),f(n.bottom,this.map.bottom),f(n.diagonal,this.map.diagonal),r.closeNode()}parseOpen(r){if(this.parser)return this.parser.parseOpen(r),!0;switch(r.name){case"border":return this.reset(),this.diagonalUp=c.parseBoolean(r.attributes.diagonalUp),this.diagonalDown=c.parseBoolean(r.attributes.diagonalDown),!0;default:return this.parser=this.map[r.name],this.parser?(this.parser.parseOpen(r),!0):!1}}parseText(r){this.parser&&this.parser.parseText(r)}parseClose(r){if(this.parser)return this.parser.parseClose(r)||(this.parser=void 0),!0;if(r==="border"){const n=this.model={},o=function(f,a,g){a&&(g&&Object.assign(a,g),n[f]=a)};o("left",this.map.left.model),o("right",this.map.right.model),o("top",this.map.top.model),o("bottom",this.map.bottom.model),o("diagonal",this.map.diagonal.model,{up:this.diagonalUp,down:this.diagonalDown})}return!1}}d.exports=t},{"../../../utils/utils":27,"../base-xform":32,"./color-xform":128}],128:[function(e,d,m){const l=e("../base-xform");class c extends l{constructor(s){super(),this.name=s||"color"}get tag(){return this.name}render(s,t){return t?(s.openNode(this.name),t.argb?s.addAttribute("rgb",t.argb):t.theme!==void 0?(s.addAttribute("theme",t.theme),t.tint!==void 0&&s.addAttribute("tint",t.tint)):t.indexed!==void 0?s.addAttribute("indexed",t.indexed):s.addAttribute("auto","1"),s.closeNode(),!0):!1}parseOpen(s){return s.name===this.name?(s.attributes.rgb?this.model={argb:s.attributes.rgb}:s.attributes.theme?(this.model={theme:parseInt(s.attributes.theme,10)},s.attributes.tint&&(this.model.tint=parseFloat(s.attributes.tint))):s.attributes.indexed?this.model={indexed:parseInt(s.attributes.indexed,10)}:this.model=void 0,!0):!1}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],129:[function(e,d,m){const l=e("../base-xform"),c=e("./alignment-xform"),h=e("./border-xform"),s=e("./fill-xform"),t=e("./font-xform"),i=e("./numfmt-xform"),r=e("./protection-xform");class n extends l{constructor(){super(),this.map={alignment:new c,border:new h,fill:new s,font:new t,numFmt:new i,protection:new r}}get tag(){return"dxf"}render(f,a){if(f.openNode(this.tag),a.font&&this.map.font.render(f,a.font),a.numFmt&&a.numFmtId){const g={id:a.numFmtId,formatCode:a.numFmt};this.map.numFmt.render(f,g)}a.fill&&this.map.fill.render(f,a.fill),a.alignment&&this.map.alignment.render(f,a.alignment),a.border&&this.map.border.render(f,a.border),a.protection&&this.map.protection.render(f,a.protection),f.closeNode()}parseOpen(f){if(this.parser)return this.parser.parseOpen(f),!0;switch(f.name){case this.tag:return this.reset(),!0;default:return this.parser=this.map[f.name],this.parser&&this.parser.parseOpen(f),!0}}parseText(f){this.parser&&this.parser.parseText(f)}parseClose(f){return this.parser?(this.parser.parseClose(f)||(this.parser=void 0),!0):f===this.tag?(this.model={alignment:this.map.alignment.model,border:this.map.border.model,fill:this.map.fill.model,font:this.map.font.model,numFmt:this.map.numFmt.model,protection:this.map.protection.model},!1):!0}}d.exports=n},{"../base-xform":32,"./alignment-xform":126,"./border-xform":127,"./fill-xform":130,"./font-xform":131,"./numfmt-xform":132,"./protection-xform":133}],130:[function(e,d,m){const l=e("../base-xform"),c=e("./color-xform");class h extends l{constructor(){super(),this.map={color:new c}}get tag(){return"stop"}render(n,o){n.openNode("stop"),n.addAttribute("position",o.position),this.map.color.render(n,o.color),n.closeNode()}parseOpen(n){if(this.parser)return this.parser.parseOpen(n),!0;switch(n.name){case"stop":return this.model={position:parseFloat(n.attributes.position)},!0;case"color":return this.parser=this.map.color,this.parser.parseOpen(n),!0;default:return!1}}parseText(){}parseClose(n){return this.parser?(this.parser.parseClose(n)||(this.model.color=this.parser.model,this.parser=void 0),!0):!1}}class s extends l{constructor(){super(),this.map={fgColor:new c("fgColor"),bgColor:new c("bgColor")}}get name(){return"pattern"}get tag(){return"patternFill"}render(n,o){n.openNode("patternFill"),n.addAttribute("patternType",o.pattern),o.fgColor&&this.map.fgColor.render(n,o.fgColor),o.bgColor&&this.map.bgColor.render(n,o.bgColor),n.closeNode()}parseOpen(n){if(this.parser)return this.parser.parseOpen(n),!0;switch(n.name){case"patternFill":return this.model={type:"pattern",pattern:n.attributes.patternType},!0;default:return this.parser=this.map[n.name],this.parser?(this.parser.parseOpen(n),!0):!1}}parseText(n){this.parser&&this.parser.parseText(n)}parseClose(n){return this.parser?(this.parser.parseClose(n)||(this.parser.model&&(this.model[n]=this.parser.model),this.parser=void 0),!0):!1}}class t extends l{constructor(){super(),this.map={stop:new h}}get name(){return"gradient"}get tag(){return"gradientFill"}render(n,o){switch(n.openNode("gradientFill"),o.gradient){case"angle":n.addAttribute("degree",o.degree);break;case"path":n.addAttribute("type","path"),o.center.left&&(n.addAttribute("left",o.center.left),o.center.right===void 0&&n.addAttribute("right",o.center.left)),o.center.right&&n.addAttribute("right",o.center.right),o.center.top&&(n.addAttribute("top",o.center.top),o.center.bottom===void 0&&n.addAttribute("bottom",o.center.top)),o.center.bottom&&n.addAttribute("bottom",o.center.bottom);break}const f=this.map.stop;o.stops.forEach(a=>{f.render(n,a)}),n.closeNode()}parseOpen(n){if(this.parser)return this.parser.parseOpen(n),!0;switch(n.name){case"gradientFill":{const o=this.model={stops:[]};return n.attributes.degree?(o.gradient="angle",o.degree=parseInt(n.attributes.degree,10)):n.attributes.type==="path"&&(o.gradient="path",o.center={left:n.attributes.left?parseFloat(n.attributes.left):0,top:n.attributes.top?parseFloat(n.attributes.top):0},n.attributes.right!==n.attributes.left&&(o.center.right=n.attributes.right?parseFloat(n.attributes.right):0),n.attributes.bottom!==n.attributes.top&&(o.center.bottom=n.attributes.bottom?parseFloat(n.attributes.bottom):0)),!0}case"stop":return this.parser=this.map.stop,this.parser.parseOpen(n),!0;default:return!1}}parseText(n){this.parser&&this.parser.parseText(n)}parseClose(n){return this.parser?(this.parser.parseClose(n)||(this.model.stops.push(this.parser.model),this.parser=void 0),!0):!1}}class i extends l{constructor(){super(),this.map={patternFill:new s,gradientFill:new t}}get tag(){return"fill"}render(n,o){switch(n.addRollback(),n.openNode("fill"),o.type){case"pattern":this.map.patternFill.render(n,o);break;case"gradient":this.map.gradientFill.render(n,o);break;default:n.rollback();return}n.closeNode(),n.commit()}parseOpen(n){if(this.parser)return this.parser.parseOpen(n),!0;switch(n.name){case"fill":return this.model={},!0;default:return this.parser=this.map[n.name],this.parser?(this.parser.parseOpen(n),!0):!1}}parseText(n){this.parser&&this.parser.parseText(n)}parseClose(n){return this.parser?(this.parser.parseClose(n)||(this.model=this.parser.model,this.model.type=this.parser.name,this.parser=void 0),!0):!1}validStyle(n){return i.validPatternValues[n]}}i.validPatternValues=["none","solid","darkVertical","darkGray","mediumGray","lightGray","gray125","gray0625","darkHorizontal","darkVertical","darkDown","darkUp","darkGrid","darkTrellis","lightHorizontal","lightVertical","lightDown","lightUp","lightGrid","lightTrellis","lightGrid"].reduce((r,n)=>(r[n]=!0,r),{}),i.StopXform=h,i.PatternFillXform=s,i.GradientFillXform=t,d.exports=i},{"../base-xform":32,"./color-xform":128}],131:[function(e,d,m){const l=e("./color-xform"),c=e("../simple/boolean-xform"),h=e("../simple/integer-xform"),s=e("../simple/string-xform"),t=e("./underline-xform"),i=e("../../../utils/under-dash"),r=e("../base-xform");class n extends r{constructor(f){super(),this.options=f||n.OPTIONS,this.map={b:{prop:"bold",xform:new c({tag:"b",attr:"val"})},i:{prop:"italic",xform:new c({tag:"i",attr:"val"})},u:{prop:"underline",xform:new t},charset:{prop:"charset",xform:new h({tag:"charset",attr:"val"})},color:{prop:"color",xform:new l},condense:{prop:"condense",xform:new c({tag:"condense",attr:"val"})},extend:{prop:"extend",xform:new c({tag:"extend",attr:"val"})},family:{prop:"family",xform:new h({tag:"family",attr:"val"})},outline:{prop:"outline",xform:new c({tag:"outline",attr:"val"})},vertAlign:{prop:"vertAlign",xform:new s({tag:"vertAlign",attr:"val"})},scheme:{prop:"scheme",xform:new s({tag:"scheme",attr:"val"})},shadow:{prop:"shadow",xform:new c({tag:"shadow",attr:"val"})},strike:{prop:"strike",xform:new c({tag:"strike",attr:"val"})},sz:{prop:"size",xform:new h({tag:"sz",attr:"val"})}},this.map[this.options.fontNameTag]={prop:"name",xform:new s({tag:this.options.fontNameTag,attr:"val"})}}get tag(){return this.options.tagName}render(f,a){const{map:g}=this;f.openNode(this.options.tagName),i.each(this.map,(b,u)=>{g[u].xform.render(f,a[b.prop])}),f.closeNode()}parseOpen(f){if(this.parser)return this.parser.parseOpen(f),!0;if(this.map[f.name])return this.parser=this.map[f.name].xform,this.parser.parseOpen(f);switch(f.name){case this.options.tagName:return this.model={},!0;default:return!1}}parseText(f){this.parser&&this.parser.parseText(f)}parseClose(f){if(this.parser&&!this.parser.parseClose(f)){const a=this.map[f];return this.parser.model&&(this.model[a.prop]=this.parser.model),this.parser=void 0,!0}switch(f){case this.options.tagName:return!1;default:return!0}}}n.OPTIONS={tagName:"font",fontNameTag:"name"},d.exports=n},{"../../../utils/under-dash":26,"../base-xform":32,"../simple/boolean-xform":116,"../simple/integer-xform":118,"../simple/string-xform":119,"./color-xform":128,"./underline-xform":136}],132:[function(e,d,m){const l=e("../../../utils/under-dash"),c=e("../../defaultnumformats"),h=e("../base-xform");function s(){const r={};return l.each(c,(n,o)=>{n.f&&(r[n.f]=parseInt(o,10))}),r}const t=s();class i extends h{constructor(n,o){super(),this.id=n,this.formatCode=o}get tag(){return"numFmt"}render(n,o){n.leafNode("numFmt",{numFmtId:o.id,formatCode:o.formatCode})}parseOpen(n){switch(n.name){case"numFmt":return this.model={id:parseInt(n.attributes.numFmtId,10),formatCode:n.attributes.formatCode.replace(/[\\](.)/g,"$1")},!0;default:return!1}}parseText(){}parseClose(){return!1}}i.getDefaultFmtId=function(n){return t[n]},i.getDefaultFmtCode=function(n){return c[n]&&c[n].f},d.exports=i},{"../../../utils/under-dash":26,"../../defaultnumformats":30,"../base-xform":32}],133:[function(e,d,m){const l=e("../base-xform"),c={boolean(s,t){return s===void 0?t:s}};class h extends l{get tag(){return"protection"}render(t,i){t.addRollback(),t.openNode("protection");let r=!1;function n(o,f){f!==void 0&&(t.addAttribute(o,f),r=!0)}n("locked",c.boolean(i.locked,!0)?void 0:"0"),n("hidden",c.boolean(i.hidden,!1)?"1":void 0),t.closeNode(),r?t.commit():t.rollback()}parseOpen(t){const i={locked:t.attributes.locked!=="0",hidden:t.attributes.hidden==="1"},r=!i.locked||i.hidden;this.model=r?i:null}parseText(){}parseClose(){return!1}}d.exports=h},{"../base-xform":32}],134:[function(e,d,m){const l=e("../base-xform"),c=e("./alignment-xform"),h=e("./protection-xform");class s extends l{constructor(i){super(),this.xfId=!!(i&&i.xfId),this.map={alignment:new c,protection:new h}}get tag(){return"xf"}render(i,r){i.openNode("xf",{numFmtId:r.numFmtId||0,fontId:r.fontId||0,fillId:r.fillId||0,borderId:r.borderId||0}),this.xfId&&i.addAttribute("xfId",r.xfId||0),r.numFmtId&&i.addAttribute("applyNumberFormat","1"),r.fontId&&i.addAttribute("applyFont","1"),r.fillId&&i.addAttribute("applyFill","1"),r.borderId&&i.addAttribute("applyBorder","1"),r.alignment&&i.addAttribute("applyAlignment","1"),r.protection&&i.addAttribute("applyProtection","1"),r.alignment&&this.map.alignment.render(i,r.alignment),r.protection&&this.map.protection.render(i,r.protection),i.closeNode()}parseOpen(i){if(this.parser)return this.parser.parseOpen(i),!0;switch(i.name){case"xf":return this.model={numFmtId:parseInt(i.attributes.numFmtId,10),fontId:parseInt(i.attributes.fontId,10),fillId:parseInt(i.attributes.fillId,10),borderId:parseInt(i.attributes.borderId,10)},this.xfId&&(this.model.xfId=parseInt(i.attributes.xfId,10)),!0;case"alignment":return this.parser=this.map.alignment,this.parser.parseOpen(i),!0;case"protection":return this.parser=this.map.protection,this.parser.parseOpen(i),!0;default:return!1}}parseText(i){this.parser&&this.parser.parseText(i)}parseClose(i){return this.parser?(this.parser.parseClose(i)||(this.map.protection===this.parser?this.model.protection=this.parser.model:this.model.alignment=this.parser.model,this.parser=void 0),!0):i!=="xf"}}d.exports=s},{"../base-xform":32,"./alignment-xform":126,"./protection-xform":133}],135:[function(e,d,m){const l=e("../../../doc/enums"),c=e("../../../utils/xml-stream"),h=e("../base-xform"),s=e("../static-xform"),t=e("../list-xform"),i=e("./font-xform"),r=e("./fill-xform"),n=e("./border-xform"),o=e("./numfmt-xform"),f=e("./style-xform"),a=e("./dxf-xform"),g=164;class b extends h{constructor(y){super(),this.map={numFmts:new t({tag:"numFmts",count:!0,childXform:new o}),fonts:new t({tag:"fonts",count:!0,childXform:new i,$:{"x14ac:knownFonts":1}}),fills:new t({tag:"fills",count:!0,childXform:new r}),borders:new t({tag:"borders",count:!0,childXform:new n}),cellStyleXfs:new t({tag:"cellStyleXfs",count:!0,childXform:new f}),cellXfs:new t({tag:"cellXfs",count:!0,childXform:new f({xfId:!0})}),dxfs:new t({tag:"dxfs",always:!0,count:!0,childXform:new a}),numFmt:new o,font:new i,fill:new r,border:new n,style:new f({xfId:!0}),cellStyles:b.STATIC_XFORMS.cellStyles,tableStyles:b.STATIC_XFORMS.tableStyles,extLst:b.STATIC_XFORMS.extLst},y&&this.init()}initIndex(){this.index={style:{},numFmt:{},numFmtNextId:164,font:{},border:{},fill:{}}}init(){this.model={styles:[],numFmts:[],fonts:[],borders:[],fills:[],dxfs:[]},this.initIndex(),this._addBorder({}),this._addStyle({numFmtId:0,fontId:0,fillId:0,borderId:0,xfId:0}),this._addFill({type:"pattern",pattern:"none"}),this._addFill({type:"pattern",pattern:"gray125"}),this.weakMap=new WeakMap}render(y,S){S=S||this.model,y.openXml(c.StdDocAttributes),y.openNode("styleSheet",b.STYLESHEET_ATTRIBUTES),this.index?(S.numFmts&&S.numFmts.length&&(y.openNode("numFmts",{count:S.numFmts.length}),S.numFmts.forEach(E=>{y.writeXml(E)}),y.closeNode()),S.fonts.length||this._addFont({size:11,color:{theme:1},name:"Calibri",family:2,scheme:"minor"}),y.openNode("fonts",{count:S.fonts.length,"x14ac:knownFonts":1}),S.fonts.forEach(E=>{y.writeXml(E)}),y.closeNode(),y.openNode("fills",{count:S.fills.length}),S.fills.forEach(E=>{y.writeXml(E)}),y.closeNode(),y.openNode("borders",{count:S.borders.length}),S.borders.forEach(E=>{y.writeXml(E)}),y.closeNode(),this.map.cellStyleXfs.render(y,[{numFmtId:0,fontId:0,fillId:0,borderId:0,xfId:0}]),y.openNode("cellXfs",{count:S.styles.length}),S.styles.forEach(E=>{y.writeXml(E)}),y.closeNode()):(this.map.numFmts.render(y,S.numFmts),this.map.fonts.render(y,S.fonts),this.map.fills.render(y,S.fills),this.map.borders.render(y,S.borders),this.map.cellStyleXfs.render(y,[{numFmtId:0,fontId:0,fillId:0,borderId:0,xfId:0}]),this.map.cellXfs.render(y,S.styles)),b.STATIC_XFORMS.cellStyles.render(y),this.map.dxfs.render(y,S.dxfs),b.STATIC_XFORMS.tableStyles.render(y),b.STATIC_XFORMS.extLst.render(y),y.closeNode()}parseOpen(y){if(this.parser)return this.parser.parseOpen(y),!0;switch(y.name){case"styleSheet":return this.initIndex(),!0;default:return this.parser=this.map[y.name],this.parser&&this.parser.parseOpen(y),!0}}parseText(y){this.parser&&this.parser.parseText(y)}parseClose(y){if(this.parser)return this.parser.parseClose(y)||(this.parser=void 0),!0;switch(y){case"styleSheet":{this.model={};const S=(E,I)=>{I.model&&I.model.length&&(this.model[E]=I.model)};if(S("numFmts",this.map.numFmts),S("fonts",this.map.fonts),S("fills",this.map.fills),S("borders",this.map.borders),S("styles",this.map.cellXfs),S("dxfs",this.map.dxfs),this.index={model:[],numFmt:[]},this.model.numFmts){const E=this.index.numFmt;this.model.numFmts.forEach(I=>{E[I.id]=I.formatCode})}return!1}default:return!0}}addStyleModel(y,S){if(!y)return 0;if(this.model.fonts.length||this._addFont({size:11,color:{theme:1},name:"Calibri",family:2,scheme:"minor"}),this.weakMap&&this.weakMap.has(y))return this.weakMap.get(y);const E={};if(S=S||l.ValueType.Number,y.numFmt)E.numFmtId=this._addNumFmtStr(y.numFmt);else switch(S){case l.ValueType.Number:E.numFmtId=this._addNumFmtStr("General");break;case l.ValueType.Date:E.numFmtId=this._addNumFmtStr("mm-dd-yy");break}y.font&&(E.fontId=this._addFont(y.font)),y.border&&(E.borderId=this._addBorder(y.border)),y.fill&&(E.fillId=this._addFill(y.fill)),y.alignment&&(E.alignment=y.alignment),y.protection&&(E.protection=y.protection);const I=this._addStyle(E);return this.weakMap&&this.weakMap.set(y,I),I}getStyleModel(y){const S=this.model.styles[y];if(!S)return null;let E=this.index.model[y];if(E)return E;if(E=this.index.model[y]={},S.numFmtId){const P=this.index.numFmt[S.numFmtId]||o.getDefaultFmtCode(S.numFmtId);P&&(E.numFmt=P)}function I(P,F,j){if(j||j===0){const W=F[j];W&&(E[P]=W)}}return I("font",this.model.fonts,S.fontId),I("border",this.model.borders,S.borderId),I("fill",this.model.fills,S.fillId),S.alignment&&(E.alignment=S.alignment),S.protection&&(E.protection=S.protection),E}addDxfStyle(y){return y.numFmt&&(y.numFmtId=this._addNumFmtStr(y.numFmt)),this.model.dxfs.push(y),this.model.dxfs.length-1}getDxfStyle(y){return this.model.dxfs[y]}_addStyle(y){const S=this.map.style.toXml(y);let E=this.index.style[S];return E===void 0&&(E=this.index.style[S]=this.model.styles.length,this.model.styles.push(S)),E}_addNumFmtStr(y){let S=o.getDefaultFmtId(y);if(S!==void 0||(S=this.index.numFmt[y],S!==void 0))return S;S=this.index.numFmt[y]=g+this.model.numFmts.length;const E=this.map.numFmt.toXml({id:S,formatCode:y});return this.model.numFmts.push(E),S}_addFont(y){const S=this.map.font.toXml(y);let E=this.index.font[S];return E===void 0&&(E=this.index.font[S]=this.model.fonts.length,this.model.fonts.push(S)),E}_addBorder(y){const S=this.map.border.toXml(y);let E=this.index.border[S];return E===void 0&&(E=this.index.border[S]=this.model.borders.length,this.model.borders.push(S)),E}_addFill(y){const S=this.map.fill.toXml(y);let E=this.index.fill[S];return E===void 0&&(E=this.index.fill[S]=this.model.fills.length,this.model.fills.push(S)),E}}b.STYLESHEET_ATTRIBUTES={xmlns:"http://schemas.openxmlformats.org/spreadsheetml/2006/main","xmlns:mc":"http://schemas.openxmlformats.org/markup-compatibility/2006","mc:Ignorable":"x14ac x16r2","xmlns:x14ac":"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac","xmlns:x16r2":"http://schemas.microsoft.com/office/spreadsheetml/2015/02/main"},b.STATIC_XFORMS={cellStyles:new s({tag:"cellStyles",$:{count:1},c:[{tag:"cellStyle",$:{name:"Normal",xfId:0,builtinId:0}}]}),dxfs:new s({tag:"dxfs",$:{count:0}}),tableStyles:new s({tag:"tableStyles",$:{count:0,defaultTableStyle:"TableStyleMedium2",defaultPivotStyle:"PivotStyleLight16"}}),extLst:new s({tag:"extLst",c:[{tag:"ext",$:{uri:"{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}","xmlns:x14":"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"},c:[{tag:"x14:slicerStyles",$:{defaultSlicerStyle:"SlicerStyleLight1"}}]},{tag:"ext",$:{uri:"{9260A510-F301-46a8-8635-F512D64BE5F5}","xmlns:x15":"http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"},c:[{tag:"x15:timelineStyles",$:{defaultTimelineStyle:"TimeSlicerStyleLight1"}}]}]})};class u extends b{constructor(){super(),this.model={styles:[{numFmtId:0,fontId:0,fillId:0,borderId:0,xfId:0}],numFmts:[],fonts:[{size:11,color:{theme:1},name:"Calibri",family:2,scheme:"minor"}],borders:[{}],fills:[{type:"pattern",pattern:"none"},{type:"pattern",pattern:"gray125"}]}}parseStream(y){return y.autodrain(),Promise.resolve()}addStyleModel(y,S){switch(S){case l.ValueType.Date:return this.dateStyleId;default:return 0}}get dateStyleId(){if(!this._dateStyleId){const y={numFmtId:o.getDefaultFmtId("mm-dd-yy")};this._dateStyleId=this.model.styles.length,this.model.styles.push(y)}return this._dateStyleId}getStyleModel(){return{}}}b.Mock=u,d.exports=b},{"../../../doc/enums":7,"../../../utils/xml-stream":28,"../base-xform":32,"../list-xform":71,"../static-xform":120,"./border-xform":127,"./dxf-xform":129,"./fill-xform":130,"./font-xform":131,"./numfmt-xform":132,"./style-xform":134}],136:[function(e,d,m){const l=e("../base-xform");class c extends l{constructor(s){super(),this.model=s}get tag(){return"u"}render(s,t){if(t=t||this.model,t===!0)s.leafNode("u");else{const i=c.Attributes[t];i&&s.leafNode("u",i)}}parseOpen(s){s.name==="u"&&(this.model=s.attributes.val||!0)}parseText(){}parseClose(){return!1}}c.Attributes={single:{},double:{val:"double"},singleAccounting:{val:"singleAccounting"},doubleAccounting:{val:"doubleAccounting"}},d.exports=c},{"../base-xform":32}],137:[function(e,d,m){const l=e("../base-xform"),c=e("./filter-column-xform");class h extends l{constructor(){super(),this.map={filterColumn:new c}}get tag(){return"autoFilter"}prepare(t){t.columns.forEach((i,r)=>{this.map.filterColumn.prepare(i,{index:r})})}render(t,i){return t.openNode(this.tag,{ref:i.autoFilterRef}),i.columns.forEach(r=>{this.map.filterColumn.render(t,r)}),t.closeNode(),!0}parseOpen(t){if(this.parser)return this.parser.parseOpen(t),!0;switch(t.name){case this.tag:return this.model={autoFilterRef:t.attributes.ref,columns:[]},!0;default:if(this.parser=this.map[t.name],this.parser)return this.parseOpen(t),!0;throw new Error(`Unexpected xml node in parseOpen: ${JSON.stringify(t)}`)}}parseText(t){this.parser&&this.parser.parseText(t)}parseClose(t){if(this.parser)return this.parser.parseClose(t)||(this.model.columns.push(this.parser.model),this.parser=void 0),!0;switch(t){case this.tag:return!1;default:throw new Error(`Unexpected xml node in parseClose: ${t}`)}}}d.exports=h},{"../base-xform":32,"./filter-column-xform":139}],138:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"customFilter"}render(s,t){s.leafNode(this.tag,{val:t.val,operator:t.operator})}parseOpen(s){return s.name===this.tag?(this.model={val:s.attributes.val,operator:s.attributes.operator},!0):!1}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],139:[function(e,d,m){const l=e("../base-xform"),c=e("../list-xform"),h=e("./custom-filter-xform"),s=e("./filter-xform");class t extends l{constructor(){super(),this.map={customFilters:new c({tag:"customFilters",count:!1,empty:!0,childXform:new h}),filters:new c({tag:"filters",count:!1,empty:!0,childXform:new s})}}get tag(){return"filterColumn"}prepare(r,n){r.colId=n.index.toString()}render(r,n){return n.customFilters?(r.openNode(this.tag,{colId:n.colId,hiddenButton:n.filterButton?"0":"1"}),this.map.customFilters.render(r,n.customFilters),r.closeNode(),!0):(r.leafNode(this.tag,{colId:n.colId,hiddenButton:n.filterButton?"0":"1"}),!0)}parseOpen(r){if(this.parser)return this.parser.parseOpen(r),!0;const{attributes:n}=r;switch(r.name){case this.tag:return this.model={filterButton:n.hiddenButton==="0"},!0;default:if(this.parser=this.map[r.name],this.parser)return this.parseOpen(r),!0;throw new Error(`Unexpected xml node in parseOpen: ${JSON.stringify(r)}`)}}parseText(){}parseClose(r){if(this.parser)return this.parser.parseClose(r)||(this.parser=void 0),!0;switch(r){case this.tag:return this.model.customFilters=this.map.customFilters.model,!1;default:return!0}}}d.exports=t},{"../base-xform":32,"../list-xform":71,"./custom-filter-xform":138,"./filter-xform":140}],140:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"filter"}render(s,t){s.leafNode(this.tag,{val:t.val})}parseOpen(s){return s.name===this.tag?(this.model={val:s.attributes.val},!0):!1}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],141:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"tableColumn"}prepare(s,t){s.id=t.index+1}render(s,t){return s.leafNode(this.tag,{id:t.id.toString(),name:t.name,totalsRowLabel:t.totalsRowLabel,totalsRowFunction:t.totalsRowFunction,dxfId:t.dxfId}),!0}parseOpen(s){if(s.name===this.tag){const{attributes:t}=s;return this.model={name:t.name,totalsRowLabel:t.totalsRowLabel,totalsRowFunction:t.totalsRowFunction,dxfId:t.dxfId},!0}return!1}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],142:[function(e,d,m){const l=e("../base-xform");class c extends l{get tag(){return"tableStyleInfo"}render(s,t){return s.leafNode(this.tag,{name:t.theme?t.theme:void 0,showFirstColumn:t.showFirstColumn?"1":"0",showLastColumn:t.showLastColumn?"1":"0",showRowStripes:t.showRowStripes?"1":"0",showColumnStripes:t.showColumnStripes?"1":"0"}),!0}parseOpen(s){if(s.name===this.tag){const{attributes:t}=s;return this.model={theme:t.name?t.name:null,showFirstColumn:t.showFirstColumn==="1",showLastColumn:t.showLastColumn==="1",showRowStripes:t.showRowStripes==="1",showColumnStripes:t.showColumnStripes==="1"},!0}return!1}parseText(){}parseClose(){return!1}}d.exports=c},{"../base-xform":32}],143:[function(e,d,m){const l=e("../../../utils/xml-stream"),c=e("../base-xform"),h=e("../list-xform"),s=e("./auto-filter-xform"),t=e("./table-column-xform"),i=e("./table-style-info-xform");class r extends c{constructor(){super(),this.map={autoFilter:new s,tableColumns:new h({tag:"tableColumns",count:!0,empty:!0,childXform:new t}),tableStyleInfo:new i}}prepare(o,f){this.map.autoFilter.prepare(o),this.map.tableColumns.prepare(o.columns,f)}get tag(){return"table"}render(o,f){o.openXml(l.StdDocAttributes),o.openNode(this.tag,{...r.TABLE_ATTRIBUTES,id:f.id,name:f.name,displayName:f.displayName||f.name,ref:f.tableRef,totalsRowCount:f.totalsRow?"1":void 0,totalsRowShown:f.totalsRow?void 0:"1",headerRowCount:f.headerRow?"1":"0"}),this.map.autoFilter.render(o,f),this.map.tableColumns.render(o,f.columns),this.map.tableStyleInfo.render(o,f.style),o.closeNode()}parseOpen(o){if(this.parser)return this.parser.parseOpen(o),!0;const{name:f,attributes:a}=o;switch(f){case this.tag:this.reset(),this.model={name:a.name,displayName:a.displayName||a.name,tableRef:a.ref,totalsRow:a.totalsRowCount==="1",headerRow:a.headerRowCount==="1"};break;default:this.parser=this.map[o.name],this.parser&&this.parser.parseOpen(o);break}return!0}parseText(o){this.parser&&this.parser.parseText(o)}parseClose(o){if(this.parser)return this.parser.parseClose(o)||(this.parser=void 0),!0;switch(o){case this.tag:return this.model.columns=this.map.tableColumns.model,this.map.autoFilter.model&&(this.model.autoFilterRef=this.map.autoFilter.model.autoFilterRef,this.map.autoFilter.model.columns.forEach((f,a)=>{this.model.columns[a].filterButton=f.filterButton})),this.model.style=this.map.tableStyleInfo.model,!1;default:return!0}}reconcile(o,f){o.columns.forEach(a=>{a.dxfId!==void 0&&(a.style=f.styles.getDxfStyle(a.dxfId))})}}r.TABLE_ATTRIBUTES={xmlns:"http://schemas.openxmlformats.org/spreadsheetml/2006/main","xmlns:mc":"http://schemas.openxmlformats.org/markup-compatibility/2006","mc:Ignorable":"xr xr3","xmlns:xr":"http://schemas.microsoft.com/office/spreadsheetml/2014/revision","xmlns:xr3":"http://schemas.microsoft.com/office/spreadsheetml/2016/revision3"},d.exports=r},{"../../../utils/xml-stream":28,"../base-xform":32,"../list-xform":71,"./auto-filter-xform":137,"./table-column-xform":141,"./table-style-info-xform":142}],144:[function(e,d,m){(function(l,c){(function(){const h=e("fs"),s=e("jszip"),{PassThrough:t}=e("readable-stream"),i=e("../utils/zip-stream"),r=e("../utils/stream-buf"),n=e("../utils/utils"),o=e("../utils/xml-stream"),{bufferToString:f}=e("../utils/browser-buffer-decode"),a=e("./xform/style/styles-xform"),g=e("./xform/core/core-xform"),b=e("./xform/strings/shared-strings-xform"),u=e("./xform/core/relationships-xform"),w=e("./xform/core/content-types-xform"),y=e("./xform/core/app-xform"),S=e("./xform/book/workbook-xform"),E=e("./xform/sheet/worksheet-xform"),I=e("./xform/drawing/drawing-xform"),P=e("./xform/table/table-xform"),F=e("./xform/comment/comments-xform"),j=e("./xform/comment/vml-notes-xform"),W=e("./xml/theme1");function G(J,$){return new Promise((M,T)=>{h.readFile(J,$,(x,A)=>{x?T(x):M(A)})})}class V{constructor($){this.workbook=$}async readFile($,M){if(!await n.fs.exists($))throw new Error(`File not found: ${$}`);const T=h.createReadStream($);try{const x=await this.read(T,M);return T.close(),x}catch(x){throw T.close(),x}}parseRels($){return new u().parseStream($)}parseWorkbook($){return new S().parseStream($)}parseSharedStrings($){return new b().parseStream($)}reconcile($,M){const T=new S,x=new E(M),A=new I,N=new P;T.reconcile($);const L={media:$.media,mediaIndex:$.mediaIndex};Object.keys($.drawings).forEach(k=>{const C=$.drawings[k],O=$.drawingRels[k];O&&(L.rels=O.reduce((X,ie)=>(X[ie.Id]=ie,X),{}),(C.anchors||[]).forEach(X=>{const ie=X.picture&&X.picture.hyperlinks;ie&&L.rels[ie.rId]&&(ie.hyperlink=L.rels[ie.rId].Target,delete ie.rId)}),A.reconcile(C,L))});const z={styles:$.styles};Object.values($.tables).forEach(k=>{N.reconcile(k,z)});const R={styles:$.styles,sharedStrings:$.sharedStrings,media:$.media,mediaIndex:$.mediaIndex,date1904:$.properties&&$.properties.date1904,drawings:$.drawings,comments:$.comments,tables:$.tables,vmlDrawings:$.vmlDrawings};$.worksheets.forEach(k=>{k.relationships=$.worksheetRels[k.sheetNo],x.reconcile(k,R)}),delete $.worksheetHash,delete $.worksheetRels,delete $.globalRels,delete $.sharedStrings,delete $.workbookRels,delete $.sheetDefs,delete $.styles,delete $.mediaIndex,delete $.drawings,delete $.drawingRels,delete $.vmlDrawings}async _processWorksheetEntry($,M,T,x,A){const L=await new E(x).parseStream($);L.sheetNo=T,M.worksheetHash[A]=L,M.worksheets.push(L)}async _processCommentEntry($,M,T){const A=await new F().parseStream($);M.comments[`../${T}.xml`]=A}async _processTableEntry($,M,T){const A=await new P().parseStream($);M.tables[`../tables/${T}.xml`]=A}async _processWorksheetRelsEntry($,M,T){const A=await new u().parseStream($);M.worksheetRels[T]=A}async _processMediaEntry($,M,T){const x=T.lastIndexOf(".");if(x>=1){const A=T.substr(x+1),N=T.substr(0,x);await new Promise((L,z)=>{const R=new r;R.on("finish",()=>{M.mediaIndex[T]=M.media.length,M.mediaIndex[N]=M.media.length;const k={type:"image",name:N,extension:A,buffer:R.toBuffer()};M.media.push(k),L()}),$.on("error",k=>{z(k)}),$.pipe(R)})}}async _processDrawingEntry($,M,T){const A=await new I().parseStream($);M.drawings[T]=A}async _processDrawingRelsEntry($,M,T){const A=await new u().parseStream($);M.drawingRels[T]=A}async _processVmlDrawingEntry($,M,T){const A=await new j().parseStream($);M.vmlDrawings[`../drawings/${T}.vml`]=A}async _processThemeEntry($,M,T){await new Promise((x,A)=>{const N=new r;$.on("error",A),N.on("error",A),N.on("finish",()=>{M.themes[T]=N.read().toString(),x()}),$.pipe(N)})}createInputStream(){throw new Error("`XLSX#createInputStream` is deprecated. You should use `XLSX#read` instead. This method will be removed in version 5.0. Please follow upgrade instruction: https://github.com/exceljs/exceljs/blob/master/UPGRADE-4.0.md")}async read($,M){!$[Symbol.asyncIterator]&&$.pipe&&($=$.pipe(new t));const T=[];for await(const x of $)T.push(x);return this.load(c.concat(T),M)}async load($,M){let T;M&&M.base64?T=c.from($.toString(),"base64"):T=$;const x={worksheets:[],worksheetHash:{},worksheetRels:[],themes:{},media:[],mediaIndex:{},drawings:{},drawingRels:{},comments:{},tables:{},vmlDrawings:{}},A=await s.loadAsync(T);for(const N of Object.values(A.files))if(!N.dir){let L=N.name;L[0]==="/"&&(L=L.substr(1));let z;if(L.match(/xl\/media\//)||L.match(/xl\/theme\/([a-zA-Z0-9]+)[.]xml/))z=new t,z.write(await N.async("nodebuffer"));else{z=new t({writableObjectMode:!0,readableObjectMode:!0});let R;l.browser?R=f(await N.async("nodebuffer")):R=await N.async("string");const k=16*1024;for(let C=0;C{if(T.type==="image"){const x=`xl/media/${T.name}.${T.extension}`;if(T.filename){const A=await G(T.filename);return $.append(A,{name:x})}if(T.buffer)return $.append(T.buffer,{name:x});if(T.base64){const A=T.base64,N=A.substring(A.indexOf(",")+1);return $.append(N,{name:x,base64:!0})}}throw new Error("Unsupported media")}))}addDrawings($,M){const T=new I,x=new u;M.worksheets.forEach(A=>{const{drawing:N}=A;if(N){T.prepare(N,{});let L=T.toXml(N);$.append(L,{name:`xl/drawings/${N.name}.xml`}),L=x.toXml(N.rels),$.append(L,{name:`xl/drawings/_rels/${N.name}.xml.rels`})}})}addTables($,M){const T=new P;M.worksheets.forEach(x=>{const{tables:A}=x;A.forEach(N=>{T.prepare(N,{});const L=T.toXml(N);$.append(L,{name:`xl/tables/${N.target}`})})})}async addContentTypes($,M){const x=new w().toXml(M);$.append(x,{name:"[Content_Types].xml"})}async addApp($,M){const x=new y().toXml(M);$.append(x,{name:"docProps/app.xml"})}async addCore($,M){const T=new g;$.append(T.toXml(M),{name:"docProps/core.xml"})}async addThemes($,M){const T=M.themes||{theme1:W};Object.keys(T).forEach(x=>{const A=T[x],N=`xl/theme/${x}.xml`;$.append(A,{name:N})})}async addOfficeRels($){const T=new u().toXml([{Id:"rId1",Type:V.RelType.OfficeDocument,Target:"xl/workbook.xml"},{Id:"rId2",Type:V.RelType.CoreProperties,Target:"docProps/core.xml"},{Id:"rId3",Type:V.RelType.ExtenderProperties,Target:"docProps/app.xml"}]);$.append(T,{name:"_rels/.rels"})}async addWorkbookRels($,M){let T=1;const x=[{Id:`rId${T++}`,Type:V.RelType.Styles,Target:"styles.xml"},{Id:`rId${T++}`,Type:V.RelType.Theme,Target:"theme/theme1.xml"}];M.sharedStrings.count&&x.push({Id:`rId${T++}`,Type:V.RelType.SharedStrings,Target:"sharedStrings.xml"}),M.worksheets.forEach(L=>{L.rId=`rId${T++}`,x.push({Id:L.rId,Type:V.RelType.Worksheet,Target:`worksheets/sheet${L.id}.xml`})});const N=new u().toXml(x);$.append(N,{name:"xl/_rels/workbook.xml.rels"})}async addSharedStrings($,M){M.sharedStrings&&M.sharedStrings.count&&$.append(M.sharedStrings.xml,{name:"xl/sharedStrings.xml"})}async addStyles($,M){const{xml:T}=M.styles;T&&$.append(T,{name:"xl/styles.xml"})}async addWorkbook($,M){const T=new S;$.append(T.toXml(M),{name:"xl/workbook.xml"})}async addWorksheets($,M){const T=new E,x=new u,A=new F,N=new j;M.worksheets.forEach(L=>{let z=new o;T.render(z,L),$.append(z.xml,{name:`xl/worksheets/sheet${L.id}.xml`}),L.rels&&L.rels.length&&(z=new o,x.render(z,L.rels),$.append(z.xml,{name:`xl/worksheets/_rels/sheet${L.id}.xml.rels`})),L.comments.length>0&&(z=new o,A.render(z,L),$.append(z.xml,{name:`xl/comments${L.id}.xml`}),z=new o,N.render(z,L),$.append(z.xml,{name:`xl/drawings/vmlDrawing${L.id}.vml`}))})}_finalize($){return new Promise((M,T)=>{$.on("finish",()=>{M(this)}),$.on("error",T),$.finalize()})}prepareModel($,M){$.creator=$.creator||"ExcelJS",$.lastModifiedBy=$.lastModifiedBy||"ExcelJS",$.created=$.created||new Date,$.modified=$.modified||new Date,$.useSharedStrings=M.useSharedStrings!==void 0?M.useSharedStrings:!0,$.useStyles=M.useStyles!==void 0?M.useStyles:!0,$.sharedStrings=new b,$.styles=$.useStyles?new a(!0):new a.Mock;const T=new S,x=new E;T.prepare($);const A={sharedStrings:$.sharedStrings,styles:$.styles,date1904:$.properties.date1904,drawingsCount:0,media:$.media};A.drawings=$.drawings=[],A.commentRefs=$.commentRefs=[];let N=0;$.tables=[],$.worksheets.forEach(L=>{L.tables.forEach(z=>{N++,z.target=`table${N}.xml`,z.id=N,$.tables.push(z)}),x.prepare(L,A)})}async write($,M){M=M||{};const{model:T}=this.workbook,x=new i.ZipWriter(M.zip);return x.pipe($),this.prepareModel(T,M),await this.addContentTypes(x,T),await this.addOfficeRels(x,T),await this.addWorkbookRels(x,T),await this.addWorksheets(x,T),await this.addSharedStrings(x,T),await this.addDrawings(x,T),await this.addTables(x,T),await Promise.all([this.addThemes(x,T),this.addStyles(x,T)]),await this.addMedia(x,T),await Promise.all([this.addApp(x,T),this.addCore(x,T)]),await this.addWorkbook(x,T),this._finalize(x)}writeFile($,M){const T=h.createWriteStream($);return new Promise((x,A)=>{T.on("finish",()=>{x()}),T.on("error",N=>{A(N)}),this.write(T,M).then(()=>{T.end()}).catch(N=>{A(N)})})}async writeBuffer($){const M=new r;return await this.write(M,$),M.read()}}V.RelType=e("./rel-type"),d.exports=V}).call(this)}).call(this,e("_process"),e("buffer").Buffer)},{"../utils/browser-buffer-decode":16,"../utils/stream-buf":24,"../utils/utils":27,"../utils/xml-stream":28,"../utils/zip-stream":29,"./rel-type":31,"./xform/book/workbook-xform":38,"./xform/comment/comments-xform":40,"./xform/comment/vml-notes-xform":45,"./xform/core/app-xform":51,"./xform/core/content-types-xform":52,"./xform/core/core-xform":53,"./xform/core/relationships-xform":55,"./xform/drawing/drawing-xform":62,"./xform/sheet/worksheet-xform":115,"./xform/strings/shared-strings-xform":124,"./xform/style/styles-xform":135,"./xform/table/table-xform":143,"./xml/theme1":145,_process:467,buffer:220,fs:216,jszip:441,"readable-stream":491}],145:[function(e,d,m){d.exports=` + `},{}],146:[function(e,d,m){(function(l){(function(){Object.defineProperty(m,"__esModule",{value:!0}),m.CsvFormatterStream=void 0;const c=e("stream"),h=e("./formatter");class s extends c.Transform{constructor(i){super({writableObjectMode:i.objectMode}),this.hasWrittenBOM=!1,this.formatterOptions=i,this.rowFormatter=new h.RowFormatter(i),this.hasWrittenBOM=!i.writeBOM}transform(i){return this.rowFormatter.rowTransform=i,this}_transform(i,r,n){let o=!1;try{this.hasWrittenBOM||(this.push(this.formatterOptions.BOM),this.hasWrittenBOM=!0),this.rowFormatter.format(i,(f,a)=>f?(o=!0,n(f)):(a&&a.forEach(g=>{this.push(l.from(g,"utf8"))}),o=!0,n()))}catch(f){if(o)throw f;n(f)}}_flush(i){this.rowFormatter.finish((r,n)=>r?i(r):(n&&n.forEach(o=>{this.push(l.from(o,"utf8"))}),i()))}}m.CsvFormatterStream=s}).call(this)}).call(this,e("buffer").Buffer)},{"./formatter":150,buffer:220,stream:505}],147:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.FormatterOptions=void 0;class l{constructor(){let h=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};var s;this.objectMode=!0,this.delimiter=",",this.rowDelimiter=` +`,this.quote='"',this.escape=this.quote,this.quoteColumns=!1,this.quoteHeaders=this.quoteColumns,this.headers=null,this.includeEndRowDelimiter=!1,this.writeBOM=!1,this.BOM="\uFEFF",this.alwaysWriteHeaders=!1,Object.assign(this,h||{}),typeof(h==null?void 0:h.quoteHeaders)>"u"&&(this.quoteHeaders=this.quoteColumns),(h==null?void 0:h.quote)===!0?this.quote='"':(h==null?void 0:h.quote)===!1&&(this.quote=""),typeof(h==null?void 0:h.escape)!="string"&&(this.escape=this.quote),this.shouldWriteHeaders=!!this.headers&&((s=h.writeHeaders)!==null&&s!==void 0?s:!0),this.headers=Array.isArray(this.headers)?this.headers:null,this.escapedQuote=`${this.escape}${this.quote}`}}m.FormatterOptions=l},{}],148:[function(e,d,m){var l=function(i){return i&&i.__esModule?i:{default:i}};Object.defineProperty(m,"__esModule",{value:!0}),m.FieldFormatter=void 0;const c=l(e("lodash.isboolean")),h=l(e("lodash.isnil")),s=l(e("lodash.escaperegexp"));class t{constructor(r){this._headers=null,this.formatterOptions=r,r.headers!==null&&(this.headers=r.headers),this.REPLACE_REGEXP=new RegExp(r.quote,"g");const n=`[${r.delimiter}${s.default(r.rowDelimiter)}|\r| +]`;this.ESCAPE_REGEXP=new RegExp(n)}set headers(r){this._headers=r}shouldQuote(r,n){const o=n?this.formatterOptions.quoteHeaders:this.formatterOptions.quoteColumns;return c.default(o)?o:Array.isArray(o)?o[r]:this._headers!==null?o[this._headers[r]]:!1}format(r,n,o){const f=`${h.default(r)?"":r}`.replace(/\0/g,""),{formatterOptions:a}=this;return a.quote!==""&&f.indexOf(a.quote)!==-1?this.quoteField(f.replace(this.REPLACE_REGEXP,a.escapedQuote)):f.search(this.ESCAPE_REGEXP)!==-1||this.shouldQuote(n,o)?this.quoteField(f):f}quoteField(r){const{quote:n}=this.formatterOptions;return`${n}${r}${n}`}}m.FieldFormatter=t},{"lodash.escaperegexp":442,"lodash.isboolean":444,"lodash.isnil":447}],149:[function(e,d,m){var l=function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(m,"__esModule",{value:!0}),m.RowFormatter=void 0;const c=l(e("lodash.isfunction")),h=l(e("lodash.isequal")),s=e("./FieldFormatter"),t=e("../types");class i{constructor(n){this.rowCount=0,this.formatterOptions=n,this.fieldFormatter=new s.FieldFormatter(n),this.headers=n.headers,this.shouldWriteHeaders=n.shouldWriteHeaders,this.hasWrittenHeaders=!1,this.headers!==null&&(this.fieldFormatter.headers=this.headers),n.transform&&(this.rowTransform=n.transform)}static isRowHashArray(n){return Array.isArray(n)?Array.isArray(n[0])&&n[0].length===2:!1}static isRowArray(n){return Array.isArray(n)&&!this.isRowHashArray(n)}static gatherHeaders(n){return i.isRowHashArray(n)?n.map(o=>o[0]):Array.isArray(n)?n:Object.keys(n)}static createTransform(n){return t.isSyncTransform(n)?(o,f)=>{let a=null;try{a=n(o)}catch(g){return f(g)}return f(null,a)}:(o,f)=>{n(o,f)}}set rowTransform(n){if(!c.default(n))throw new TypeError("The transform should be a function");this._rowTransform=i.createTransform(n)}format(n,o){this.callTransformer(n,(f,a)=>{if(f)return o(f);if(!n)return o(null);const g=[];if(a){const{shouldFormatColumns:b,headers:u}=this.checkHeaders(a);if(this.shouldWriteHeaders&&u&&!this.hasWrittenHeaders&&(g.push(this.formatColumns(u,!0)),this.hasWrittenHeaders=!0),b){const w=this.gatherColumns(a);g.push(this.formatColumns(w,!1))}}return o(null,g)})}finish(n){const o=[];if(this.formatterOptions.alwaysWriteHeaders&&this.rowCount===0){if(!this.headers)return n(new Error("`alwaysWriteHeaders` option is set to true but `headers` option not provided."));o.push(this.formatColumns(this.headers,!0))}return this.formatterOptions.includeEndRowDelimiter&&o.push(this.formatterOptions.rowDelimiter),n(null,o)}checkHeaders(n){if(this.headers)return{shouldFormatColumns:!0,headers:this.headers};const o=i.gatherHeaders(n);return this.headers=o,this.fieldFormatter.headers=o,this.shouldWriteHeaders?{shouldFormatColumns:!h.default(o,n),headers:o}:{shouldFormatColumns:!0,headers:null}}gatherColumns(n){if(this.headers===null)throw new Error("Headers is currently null");return Array.isArray(n)?i.isRowHashArray(n)?this.headers.map((o,f)=>{const a=n[f];return a?a[1]:""}):i.isRowArray(n)&&!this.shouldWriteHeaders?n:this.headers.map((o,f)=>n[f]):this.headers.map(o=>n[o])}callTransformer(n,o){return this._rowTransform?this._rowTransform(n,o):o(null,n)}formatColumns(n,o){const f=n.map((g,b)=>this.fieldFormatter.format(g,b,o)).join(this.formatterOptions.delimiter),{rowCount:a}=this;return this.rowCount+=1,a?[this.formatterOptions.rowDelimiter,f].join(""):f}}m.RowFormatter=i},{"../types":152,"./FieldFormatter":148,"lodash.isequal":445,"lodash.isfunction":446}],150:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.FieldFormatter=m.RowFormatter=void 0;var l=e("./RowFormatter");Object.defineProperty(m,"RowFormatter",{enumerable:!0,get:function(){return l.RowFormatter}});var c=e("./FieldFormatter");Object.defineProperty(m,"FieldFormatter",{enumerable:!0,get:function(){return c.FieldFormatter}})},{"./FieldFormatter":148,"./RowFormatter":149}],151:[function(e,d,m){(function(l){(function(){var c=Object.create?function(b,u,w,y){y===void 0&&(y=w),Object.defineProperty(b,y,{enumerable:!0,get:function(){return u[w]}})}:function(b,u,w,y){y===void 0&&(y=w),b[y]=u[w]},h=Object.create?function(b,u){Object.defineProperty(b,"default",{enumerable:!0,value:u})}:function(b,u){b.default=u},s=function(b){if(b&&b.__esModule)return b;var u={};if(b!=null)for(var w in b)w!=="default"&&Object.prototype.hasOwnProperty.call(b,w)&&c(u,b,w);return h(u,b),u},t=function(b,u){for(var w in b)w!=="default"&&!Object.prototype.hasOwnProperty.call(u,w)&&c(u,b,w)};Object.defineProperty(m,"__esModule",{value:!0}),m.writeToPath=m.writeToString=m.writeToBuffer=m.writeToStream=m.write=m.format=m.FormatterOptions=m.CsvFormatterStream=void 0;const i=e("util"),r=e("stream"),n=s(e("fs")),o=e("./FormatterOptions"),f=e("./CsvFormatterStream");t(e("./types"),m);var a=e("./CsvFormatterStream");Object.defineProperty(m,"CsvFormatterStream",{enumerable:!0,get:function(){return a.CsvFormatterStream}});var g=e("./FormatterOptions");Object.defineProperty(m,"FormatterOptions",{enumerable:!0,get:function(){return g.FormatterOptions}}),m.format=b=>new f.CsvFormatterStream(new o.FormatterOptions(b)),m.write=(b,u)=>{const w=m.format(u),y=i.promisify((S,E)=>{w.write(S,void 0,E)});return b.reduce((S,E)=>S.then(()=>y(E)),Promise.resolve()).then(()=>w.end()).catch(S=>{w.emit("error",S)}),w},m.writeToStream=(b,u,w)=>m.write(u,w).pipe(b),m.writeToBuffer=function(b){let u=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};const w=[],y=new r.Writable({write(S,E,I){w.push(S),I()}});return new Promise((S,E)=>{y.on("error",E).on("finish",()=>S(l.concat(w))),m.write(b,u).pipe(y)})},m.writeToString=(b,u)=>m.writeToBuffer(b,u).then(w=>w.toString()),m.writeToPath=(b,u,w)=>{const y=n.createWriteStream(b,{encoding:"utf8"});return m.write(u,w).pipe(y)}}).call(this)}).call(this,e("buffer").Buffer)},{"./CsvFormatterStream":146,"./FormatterOptions":147,"./types":152,buffer:220,fs:216,stream:505,util:527}],152:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.isSyncTransform=void 0,m.isSyncTransform=l=>l.length===1},{}],153:[function(e,d,m){(function(l){(function(){Object.defineProperty(m,"__esModule",{value:!0}),m.CsvParserStream=void 0;const c=e("string_decoder"),h=e("stream"),s=e("./transforms"),t=e("./parser");class i extends h.Transform{constructor(n){super({objectMode:n.objectMode}),this.lines="",this.rowCount=0,this.parsedRowCount=0,this.parsedLineCount=0,this.endEmitted=!1,this.headersEmitted=!1,this.parserOptions=n,this.parser=new t.Parser(n),this.headerTransformer=new s.HeaderTransformer(n),this.decoder=new c.StringDecoder(n.encoding),this.rowTransformerValidator=new s.RowTransformerValidator}get hasHitRowLimit(){return this.parserOptions.limitRows&&this.rowCount>=this.parserOptions.maxRows}get shouldEmitRows(){return this.parsedRowCount>this.parserOptions.skipRows}get shouldSkipLine(){return this.parsedLineCount<=this.parserOptions.skipLines}transform(n){return this.rowTransformerValidator.rowTransform=n,this}validate(n){return this.rowTransformerValidator.rowValidator=n,this}emit(n){if(n==="end")return this.endEmitted||(this.endEmitted=!0,super.emit("end",this.rowCount)),!1;for(var o=arguments.length,f=new Array(o>1?o-1:0),a=1;a{const b=y=>{if(y)return o(y);if(g%100===0){l(()=>a(g+1));return}return a(g+1)};if(this.checkAndEmitHeaders(),g>=f||this.hasHitRowLimit)return o();if(this.parsedLineCount+=1,this.shouldSkipLine)return b();const u=n[g];this.rowCount+=1,this.parsedRowCount+=1;const w=this.rowCount;return this.transformRow(u,(y,S)=>{if(y)return this.rowCount-=1,b(y);if(!S)return b(new Error("expected transform result"));if(!S.isValid)this.emit("data-invalid",S.row,w,S.reason);else if(S.row)return this.pushRow(S.row,b);return b()})};a(0)}transformRow(n,o){try{this.headerTransformer.transform(n,(f,a)=>f?o(f):a?a.isValid?a.row?this.shouldEmitRows?this.rowTransformerValidator.transformAndValidate(a.row,o):this.skipRow(o):(this.rowCount-=1,this.parsedRowCount-=1,o(null,{row:null,isValid:!0})):this.shouldEmitRows?o(null,{isValid:!1,row:n}):this.skipRow(o):o(new Error("Expected result from header transform")))}catch(f){o(f)}}checkAndEmitHeaders(){!this.headersEmitted&&this.headerTransformer.headers&&(this.headersEmitted=!0,this.emit("headers",this.headerTransformer.headers))}skipRow(n){return this.rowCount-=1,n(null,{row:null,isValid:!0})}pushRow(n,o){try{this.parserOptions.objectMode?this.push(n):this.push(JSON.stringify(n)),o()}catch(f){o(f)}}static wrapDoneCallback(n){let o=!1;return function(f){if(f){if(o)throw f;o=!0,n(f);return}for(var a=arguments.length,g=new Array(a>1?a-1:0),b=1;b1)throw new Error("delimiter option must be one character long");this.escapedDelimiter=c.default(this.delimiter),this.escapeChar=(r=this.escape)!==null&&r!==void 0?r:this.quote,this.supportsComments=!h.default(this.comment),this.NEXT_TOKEN_REGEXP=new RegExp(`([^\\s]|\\r\\n|\\n|\\r|${this.escapedDelimiter})`),this.maxRows>0&&(this.limitRows=!0)}}m.ParserOptions=s},{"lodash.escaperegexp":442,"lodash.isnil":447}],155:[function(e,d,m){var l=Object.create?function(a,g,b,u){u===void 0&&(u=b),Object.defineProperty(a,u,{enumerable:!0,get:function(){return g[b]}})}:function(a,g,b,u){u===void 0&&(u=b),a[u]=g[b]},c=Object.create?function(a,g){Object.defineProperty(a,"default",{enumerable:!0,value:g})}:function(a,g){a.default=g},h=function(a){if(a&&a.__esModule)return a;var g={};if(a!=null)for(var b in a)b!=="default"&&Object.prototype.hasOwnProperty.call(a,b)&&l(g,a,b);return c(g,a),g},s=function(a,g){for(var b in a)b!=="default"&&!Object.prototype.hasOwnProperty.call(g,b)&&l(g,a,b)};Object.defineProperty(m,"__esModule",{value:!0}),m.parseString=m.parseFile=m.parseStream=m.parse=m.ParserOptions=m.CsvParserStream=void 0;const t=h(e("fs")),i=e("stream"),r=e("./ParserOptions"),n=e("./CsvParserStream");s(e("./types"),m);var o=e("./CsvParserStream");Object.defineProperty(m,"CsvParserStream",{enumerable:!0,get:function(){return o.CsvParserStream}});var f=e("./ParserOptions");Object.defineProperty(m,"ParserOptions",{enumerable:!0,get:function(){return f.ParserOptions}}),m.parse=a=>new n.CsvParserStream(new r.ParserOptions(a)),m.parseStream=(a,g)=>a.pipe(new n.CsvParserStream(new r.ParserOptions(g))),m.parseFile=function(a){let g=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};return t.createReadStream(a).pipe(new n.CsvParserStream(new r.ParserOptions(g)))},m.parseString=(a,g)=>{const b=new i.Readable;return b.push(a),b.push(null),b.pipe(new n.CsvParserStream(new r.ParserOptions(g)))}},{"./CsvParserStream":153,"./ParserOptions":154,"./types":169,fs:216,stream:505}],156:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.Parser=void 0;const l=e("./Scanner"),c=e("./RowParser"),h=e("./Token");class s{constructor(i){this.parserOptions=i,this.rowParser=new c.RowParser(this.parserOptions)}static removeBOM(i){return i&&i.charCodeAt(0)===65279?i.slice(1):i}parse(i,r){const n=new l.Scanner({line:s.removeBOM(i),parserOptions:this.parserOptions,hasMoreData:r});return this.parserOptions.supportsComments?this.parseWithComments(n):this.parseWithoutComments(n)}parseWithoutComments(i){const r=[];let n=!0;for(;n;)n=this.parseRow(i,r);return{line:i.line,rows:r}}parseWithComments(i){const{parserOptions:r}=this,n=[];for(let o=i.nextCharacterToken;o!==null;o=i.nextCharacterToken)if(h.Token.isTokenComment(o,r)){if(i.advancePastLine()===null)return{line:i.lineFromCursor,rows:n};if(!i.hasMoreCharacters)return{line:i.lineFromCursor,rows:n};i.truncateToCursor()}else if(!this.parseRow(i,n))break;return{line:i.line,rows:n}}parseRow(i,r){if(!i.nextNonSpaceToken)return!1;const o=this.rowParser.parse(i);return o===null?!1:(this.parserOptions.ignoreEmpty&&c.RowParser.isEmptyRow(o)||r.push(o),!0)}}m.Parser=s},{"./RowParser":157,"./Scanner":158,"./Token":159}],157:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.RowParser=void 0;const l=e("./column"),c=e("./Token"),h="";class s{constructor(i){this.parserOptions=i,this.columnParser=new l.ColumnParser(i)}static isEmptyRow(i){return i.join(h).replace(/\s+/g,h)===h}parse(i){const{parserOptions:r}=this,{hasMoreData:n}=i,o=i,f=[];let a=this.getStartToken(o,f);for(;a;){if(c.Token.isTokenRowDelimiter(a))return o.advancePastToken(a),!o.hasMoreCharacters&&c.Token.isTokenCarriageReturn(a,r)&&n?null:(o.truncateToCursor(),f);if(!this.shouldSkipColumnParse(o,a,f)){const g=this.columnParser.parse(o);if(g===null)return null;f.push(g)}a=o.nextNonSpaceToken}return n?null:(o.truncateToCursor(),f)}getStartToken(i,r){const n=i.nextNonSpaceToken;return n!==null&&c.Token.isTokenDelimiter(n,this.parserOptions)?(r.push(""),i.nextNonSpaceToken):n}shouldSkipColumnParse(i,r,n){const{parserOptions:o}=this;if(c.Token.isTokenDelimiter(r,o)){i.advancePastToken(r);const f=i.nextCharacterToken;if(!i.hasMoreCharacters||f!==null&&c.Token.isTokenRowDelimiter(f)||f!==null&&c.Token.isTokenDelimiter(f,o))return n.push(""),!0}return!1}}m.RowParser=s},{"./Token":159,"./column":164}],158:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.Scanner=void 0;const l=e("./Token"),c=/((?:\r\n)|\n|\r)/;class h{constructor(t){this.cursor=0,this.line=t.line,this.lineLength=this.line.length,this.parserOptions=t.parserOptions,this.hasMoreData=t.hasMoreData,this.cursor=t.cursor||0}get hasMoreCharacters(){return this.lineLength>this.cursor}get nextNonSpaceToken(){const{lineFromCursor:t}=this,i=this.parserOptions.NEXT_TOKEN_REGEXP;if(t.search(i)===-1)return null;const r=i.exec(t);if(r==null)return null;const n=r[1],o=this.cursor+(r.index||0);return new l.Token({token:n,startCursor:o,endCursor:o+n.length-1})}get nextCharacterToken(){const{cursor:t,lineLength:i}=this;return i<=t?null:new l.Token({token:this.line[t],startCursor:t,endCursor:t})}get lineFromCursor(){return this.line.substr(this.cursor)}advancePastLine(){const t=c.exec(this.lineFromCursor);return t?(this.cursor+=(t.index||0)+t[0].length,this):this.hasMoreData?null:(this.cursor=this.lineLength,this)}advanceTo(t){return this.cursor=t,this}advanceToToken(t){return this.cursor=t.startCursor,this}advancePastToken(t){return this.cursor=t.endCursor+1,this}truncateToCursor(){return this.line=this.lineFromCursor,this.lineLength=this.line.length,this.cursor=0,this}}m.Scanner=h},{"./Token":159}],159:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.Token=void 0;class l{constructor(h){this.token=h.token,this.startCursor=h.startCursor,this.endCursor=h.endCursor}static isTokenRowDelimiter(h){const s=h.token;return s==="\r"||s===` +`||s===`\r +`}static isTokenCarriageReturn(h,s){return h.token===s.carriageReturn}static isTokenComment(h,s){return s.supportsComments&&!!h&&h.token===s.comment}static isTokenEscapeCharacter(h,s){return h.token===s.escapeChar}static isTokenQuote(h,s){return h.token===s.quote}static isTokenDelimiter(h,s){return h.token===s.delimiter}}m.Token=l},{}],160:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.ColumnFormatter=void 0;class l{constructor(h){h.trim?this.format=s=>s.trim():h.ltrim?this.format=s=>s.trimLeft():h.rtrim?this.format=s=>s.trimRight():this.format=s=>s}}m.ColumnFormatter=l},{}],161:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.ColumnParser=void 0;const l=e("./NonQuotedColumnParser"),c=e("./QuotedColumnParser"),h=e("../Token");class s{constructor(i){this.parserOptions=i,this.quotedColumnParser=new c.QuotedColumnParser(i),this.nonQuotedColumnParser=new l.NonQuotedColumnParser(i)}parse(i){const{nextNonSpaceToken:r}=i;return r!==null&&h.Token.isTokenQuote(r,this.parserOptions)?(i.advanceToToken(r),this.quotedColumnParser.parse(i)):this.nonQuotedColumnParser.parse(i)}}m.ColumnParser=s},{"../Token":159,"./NonQuotedColumnParser":162,"./QuotedColumnParser":163}],162:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.NonQuotedColumnParser=void 0;const l=e("./ColumnFormatter"),c=e("../Token");class h{constructor(t){this.parserOptions=t,this.columnFormatter=new l.ColumnFormatter(t)}parse(t){if(!t.hasMoreCharacters)return null;const{parserOptions:i}=this,r=[];let n=t.nextCharacterToken;for(;n&&!(c.Token.isTokenDelimiter(n,i)||c.Token.isTokenRowDelimiter(n));n=t.nextCharacterToken)r.push(n.token),t.advancePastToken(n);return this.columnFormatter.format(r.join(""))}}m.NonQuotedColumnParser=h},{"../Token":159,"./ColumnFormatter":160}],163:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.QuotedColumnParser=void 0;const l=e("./ColumnFormatter"),c=e("../Token");class h{constructor(t){this.parserOptions=t,this.columnFormatter=new l.ColumnFormatter(t)}parse(t){if(!t.hasMoreCharacters)return null;const i=t.cursor,{foundClosingQuote:r,col:n}=this.gatherDataBetweenQuotes(t);if(!r){if(t.advanceTo(i),!t.hasMoreData)throw new Error(`Parse Error: missing closing: '${this.parserOptions.quote||""}' in line: at '${t.lineFromCursor.replace(/[\r\n]/g,"\\n'")}'`);return null}return this.checkForMalformedColumn(t),n}gatherDataBetweenQuotes(t){const{parserOptions:i}=this;let r=!1,n=!1;const o=[];let f=t.nextCharacterToken;for(;!n&&f!==null;f=t.nextCharacterToken){const a=c.Token.isTokenQuote(f,i);if(!r&&a)r=!0;else if(r)if(c.Token.isTokenEscapeCharacter(f,i)){t.advancePastToken(f);const g=t.nextCharacterToken;g!==null&&(c.Token.isTokenQuote(g,i)||c.Token.isTokenEscapeCharacter(g,i))?(o.push(g.token),f=g):a?n=!0:o.push(f.token)}else a?n=!0:o.push(f.token);t.advancePastToken(f)}return{col:this.columnFormatter.format(o.join("")),foundClosingQuote:n}}checkForMalformedColumn(t){const{parserOptions:i}=this,{nextNonSpaceToken:r}=t;if(r){const n=c.Token.isTokenDelimiter(r,i),o=c.Token.isTokenRowDelimiter(r);if(!(n||o)){const f=t.lineFromCursor.substr(0,10).replace(/[\r\n]/g,"\\n'");throw new Error(`Parse Error: expected: '${i.escapedDelimiter}' OR new line got: '${r.token}'. at '${f}`)}t.advanceToToken(r)}else t.hasMoreData||t.advancePastLine()}}m.QuotedColumnParser=h},{"../Token":159,"./ColumnFormatter":160}],164:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.ColumnFormatter=m.QuotedColumnParser=m.NonQuotedColumnParser=m.ColumnParser=void 0;var l=e("./ColumnParser");Object.defineProperty(m,"ColumnParser",{enumerable:!0,get:function(){return l.ColumnParser}});var c=e("./NonQuotedColumnParser");Object.defineProperty(m,"NonQuotedColumnParser",{enumerable:!0,get:function(){return c.NonQuotedColumnParser}});var h=e("./QuotedColumnParser");Object.defineProperty(m,"QuotedColumnParser",{enumerable:!0,get:function(){return h.QuotedColumnParser}});var s=e("./ColumnFormatter");Object.defineProperty(m,"ColumnFormatter",{enumerable:!0,get:function(){return s.ColumnFormatter}})},{"./ColumnFormatter":160,"./ColumnParser":161,"./NonQuotedColumnParser":162,"./QuotedColumnParser":163}],165:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.QuotedColumnParser=m.NonQuotedColumnParser=m.ColumnParser=m.Token=m.Scanner=m.RowParser=m.Parser=void 0;var l=e("./Parser");Object.defineProperty(m,"Parser",{enumerable:!0,get:function(){return l.Parser}});var c=e("./RowParser");Object.defineProperty(m,"RowParser",{enumerable:!0,get:function(){return c.RowParser}});var h=e("./Scanner");Object.defineProperty(m,"Scanner",{enumerable:!0,get:function(){return h.Scanner}});var s=e("./Token");Object.defineProperty(m,"Token",{enumerable:!0,get:function(){return s.Token}});var t=e("./column");Object.defineProperty(m,"ColumnParser",{enumerable:!0,get:function(){return t.ColumnParser}}),Object.defineProperty(m,"NonQuotedColumnParser",{enumerable:!0,get:function(){return t.NonQuotedColumnParser}}),Object.defineProperty(m,"QuotedColumnParser",{enumerable:!0,get:function(){return t.QuotedColumnParser}})},{"./Parser":156,"./RowParser":157,"./Scanner":158,"./Token":159,"./column":164}],166:[function(e,d,m){var l=function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(m,"__esModule",{value:!0}),m.HeaderTransformer=void 0;const c=l(e("lodash.isundefined")),h=l(e("lodash.isfunction")),s=l(e("lodash.uniq")),t=l(e("lodash.groupby"));class i{constructor(n){this.headers=null,this.receivedHeaders=!1,this.shouldUseFirstRow=!1,this.processedFirstRow=!1,this.headersLength=0,this.parserOptions=n,n.headers===!0?this.shouldUseFirstRow=!0:Array.isArray(n.headers)?this.setHeaders(n.headers):h.default(n.headers)&&(this.headersTransform=n.headers)}transform(n,o){return this.shouldMapRow(n)?o(null,this.processRow(n)):o(null,{row:null,isValid:!0})}shouldMapRow(n){const{parserOptions:o}=this;if(!this.headersTransform&&o.renameHeaders&&!this.processedFirstRow){if(!this.receivedHeaders)throw new Error("Error renaming headers: new headers must be provided in an array");return this.processedFirstRow=!0,!1}if(!this.receivedHeaders&&Array.isArray(n)){if(this.headersTransform)this.setHeaders(this.headersTransform(n));else if(this.shouldUseFirstRow)this.setHeaders(n);else return!0;return!1}return!0}processRow(n){if(!this.headers)return{row:n,isValid:!0};const{parserOptions:o}=this;if(!o.discardUnmappedColumns&&n.length>this.headersLength){if(!o.strictColumnHandling)throw new Error(`Unexpected Error: column header mismatch expected: ${this.headersLength} columns got: ${n.length}`);return{row:n,isValid:!1,reason:`Column header mismatch expected: ${this.headersLength} columns got: ${n.length}`}}return o.strictColumnHandling&&n.length!!a);if(s.default(f).length!==f.length){const a=t.default(f),g=Object.keys(a).filter(b=>a[b].length>1);throw new Error(`Duplicate headers found ${JSON.stringify(g)}`)}this.headers=n,this.receivedHeaders=!0,this.headersLength=((o=this.headers)===null||o===void 0?void 0:o.length)||0}}m.HeaderTransformer=i},{"lodash.groupby":443,"lodash.isfunction":446,"lodash.isundefined":448,"lodash.uniq":449}],167:[function(e,d,m){var l=function(t){return t&&t.__esModule?t:{default:t}};Object.defineProperty(m,"__esModule",{value:!0}),m.RowTransformerValidator=void 0;const c=l(e("lodash.isfunction")),h=e("../types");class s{constructor(){this._rowTransform=null,this._rowValidator=null}static createTransform(i){return h.isSyncTransform(i)?(r,n)=>{let o=null;try{o=i(r)}catch(f){return n(f)}return n(null,o)}:i}static createValidator(i){return h.isSyncValidate(i)?(r,n)=>{n(null,{row:r,isValid:i(r)})}:(r,n)=>{i(r,(o,f,a)=>o?n(o):f?n(null,{row:r,isValid:f,reason:a}):n(null,{row:r,isValid:!1,reason:a}))}}set rowTransform(i){if(!c.default(i))throw new TypeError("The transform should be a function");this._rowTransform=s.createTransform(i)}set rowValidator(i){if(!c.default(i))throw new TypeError("The validate should be a function");this._rowValidator=s.createValidator(i)}transformAndValidate(i,r){return this.callTransformer(i,(n,o)=>n?r(n):o?this.callValidator(o,(f,a)=>f?r(f):a&&!a.isValid?r(null,{row:o,isValid:!1,reason:a.reason}):r(null,{row:o,isValid:!0})):r(null,{row:null,isValid:!0}))}callTransformer(i,r){return this._rowTransform?this._rowTransform(i,r):r(null,i)}callValidator(i,r){return this._rowValidator?this._rowValidator(i,r):r(null,{row:i,isValid:!0})}}m.RowTransformerValidator=s},{"../types":169,"lodash.isfunction":446}],168:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.HeaderTransformer=m.RowTransformerValidator=void 0;var l=e("./RowTransformerValidator");Object.defineProperty(m,"RowTransformerValidator",{enumerable:!0,get:function(){return l.RowTransformerValidator}});var c=e("./HeaderTransformer");Object.defineProperty(m,"HeaderTransformer",{enumerable:!0,get:function(){return c.HeaderTransformer}})},{"./HeaderTransformer":166,"./RowTransformerValidator":167}],169:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.isSyncValidate=m.isSyncTransform=void 0,m.isSyncTransform=l=>l.length===1,m.isSyncValidate=l=>l.length===1},{}],170:[function(e,d,m){const l=m;l.bignum=e("bn.js"),l.define=e("./asn1/api").define,l.base=e("./asn1/base"),l.constants=e("./asn1/constants"),l.decoders=e("./asn1/decoders"),l.encoders=e("./asn1/encoders")},{"./asn1/api":171,"./asn1/base":173,"./asn1/constants":177,"./asn1/decoders":179,"./asn1/encoders":182,"bn.js":184}],171:[function(e,d,m){const l=e("./encoders"),c=e("./decoders"),h=e("inherits"),s=m;s.define=function(r,n){return new t(r,n)};function t(i,r){this.name=i,this.body=r,this.decoders={},this.encoders={}}t.prototype._createNamed=function(r){const n=this.name;function o(f){this._initNamed(f,n)}return h(o,r),o.prototype._initNamed=function(a,g){r.call(this,a,g)},new o(this)},t.prototype._getDecoder=function(r){return r=r||"der",this.decoders.hasOwnProperty(r)||(this.decoders[r]=this._createNamed(c[r])),this.decoders[r]},t.prototype.decode=function(r,n,o){return this._getDecoder(n).decode(r,o)},t.prototype._getEncoder=function(r){return r=r||"der",this.encoders.hasOwnProperty(r)||(this.encoders[r]=this._createNamed(l[r])),this.encoders[r]},t.prototype.encode=function(r,n,o){return this._getEncoder(n).encode(r,o)}},{"./decoders":179,"./encoders":182,inherits:440}],172:[function(e,d,m){const l=e("inherits"),c=e("../base/reporter").Reporter,h=e("safer-buffer").Buffer;function s(i,r){if(c.call(this,r),!h.isBuffer(i)){this.error("Input not Buffer");return}this.base=i,this.offset=0,this.length=i.length}l(s,c),m.DecoderBuffer=s,s.isDecoderBuffer=function(r){return r instanceof s?!0:typeof r=="object"&&h.isBuffer(r.base)&&r.constructor.name==="DecoderBuffer"&&typeof r.offset=="number"&&typeof r.length=="number"&&typeof r.save=="function"&&typeof r.restore=="function"&&typeof r.isEmpty=="function"&&typeof r.readUInt8=="function"&&typeof r.skip=="function"&&typeof r.raw=="function"},s.prototype.save=function(){return{offset:this.offset,reporter:c.prototype.save.call(this)}},s.prototype.restore=function(r){const n=new s(this.base);return n.offset=r.offset,n.length=this.offset,this.offset=r.offset,c.prototype.restore.call(this,r.reporter),n},s.prototype.isEmpty=function(){return this.offset===this.length},s.prototype.readUInt8=function(r){return this.offset+1<=this.length?this.base.readUInt8(this.offset++,!0):this.error(r||"DecoderBuffer overrun")},s.prototype.skip=function(r,n){if(!(this.offset+r<=this.length))return this.error(n||"DecoderBuffer overrun");const o=new s(this.base);return o._reporterState=this._reporterState,o.offset=this.offset,o.length=this.offset+r,this.offset+=r,o},s.prototype.raw=function(r){return this.base.slice(r?r.offset:this.offset,this.length)};function t(i,r){if(Array.isArray(i))this.length=0,this.value=i.map(function(n){return t.isEncoderBuffer(n)||(n=new t(n,r)),this.length+=n.length,n},this);else if(typeof i=="number"){if(!(0<=i&&i<=255))return r.error("non-byte EncoderBuffer value");this.value=i,this.length=1}else if(typeof i=="string")this.value=i,this.length=h.byteLength(i);else if(h.isBuffer(i))this.value=i,this.length=i.length;else return r.error("Unsupported type: "+typeof i)}m.EncoderBuffer=t,t.isEncoderBuffer=function(r){return r instanceof t?!0:typeof r=="object"&&r.constructor.name==="EncoderBuffer"&&typeof r.length=="number"&&typeof r.join=="function"},t.prototype.join=function(r,n){return r||(r=h.alloc(this.length)),n||(n=0),this.length===0||(Array.isArray(this.value)?this.value.forEach(function(o){o.join(r,n),n+=o.length}):(typeof this.value=="number"?r[n]=this.value:typeof this.value=="string"?r.write(this.value,n):h.isBuffer(this.value)&&this.value.copy(r,n),n+=this.length)),r}},{"../base/reporter":175,inherits:440,"safer-buffer":495}],173:[function(e,d,m){const l=m;l.Reporter=e("./reporter").Reporter,l.DecoderBuffer=e("./buffer").DecoderBuffer,l.EncoderBuffer=e("./buffer").EncoderBuffer,l.Node=e("./node")},{"./buffer":172,"./node":174,"./reporter":175}],174:[function(e,d,m){const l=e("../base/reporter").Reporter,c=e("../base/buffer").EncoderBuffer,h=e("../base/buffer").DecoderBuffer,s=e("minimalistic-assert"),t=["seq","seqof","set","setof","objid","bool","gentime","utctime","null_","enum","int","objDesc","bitstr","bmpstr","charstr","genstr","graphstr","ia5str","iso646str","numstr","octstr","printstr","t61str","unistr","utf8str","videostr"],i=["key","obj","use","optional","explicit","implicit","def","choice","any","contains"].concat(t),r=["_peekTag","_decodeTag","_use","_decodeStr","_decodeObjid","_decodeTime","_decodeNull","_decodeInt","_decodeBool","_decodeList","_encodeComposite","_encodeStr","_encodeObjid","_encodeTime","_encodeNull","_encodeInt","_encodeBool"];function n(f,a,g){const b={};this._baseState=b,b.name=g,b.enc=f,b.parent=a||null,b.children=null,b.tag=null,b.args=null,b.reverseArgs=null,b.choice=null,b.optional=!1,b.any=!1,b.obj=!1,b.use=null,b.useDecoder=null,b.key=null,b.default=null,b.explicit=null,b.implicit=null,b.contains=null,b.parent||(b.children=[],this._wrap())}d.exports=n;const o=["enc","parent","children","tag","args","reverseArgs","choice","optional","any","obj","use","alteredUse","key","default","explicit","implicit","contains"];n.prototype.clone=function(){const a=this._baseState,g={};o.forEach(function(u){g[u]=a[u]});const b=new this.constructor(g.parent);return b._baseState=g,b},n.prototype._wrap=function(){const a=this._baseState;i.forEach(function(g){this[g]=function(){const u=new this.constructor(this);return a.children.push(u),u[g].apply(u,arguments)}},this)},n.prototype._init=function(a){const g=this._baseState;s(g.parent===null),a.call(this),g.children=g.children.filter(function(b){return b._baseState.parent===this},this),s.equal(g.children.length,1,"Root node can have only one child")},n.prototype._useArgs=function(a){const g=this._baseState,b=a.filter(function(u){return u instanceof this.constructor},this);a=a.filter(function(u){return!(u instanceof this.constructor)},this),b.length!==0&&(s(g.children===null),g.children=b,b.forEach(function(u){u._baseState.parent=this},this)),a.length!==0&&(s(g.args===null),g.args=a,g.reverseArgs=a.map(function(u){if(typeof u!="object"||u.constructor!==Object)return u;const w={};return Object.keys(u).forEach(function(y){y==(y|0)&&(y|=0);const S=u[y];w[S]=y}),w}))},r.forEach(function(f){n.prototype[f]=function(){const g=this._baseState;throw new Error(f+" not implemented for encoding: "+g.enc)}}),t.forEach(function(f){n.prototype[f]=function(){const g=this._baseState,b=Array.prototype.slice.call(arguments);return s(g.tag===null),g.tag=f,this._useArgs(b),this}}),n.prototype.use=function(a){s(a);const g=this._baseState;return s(g.use===null),g.use=a,this},n.prototype.optional=function(){const a=this._baseState;return a.optional=!0,this},n.prototype.def=function(a){const g=this._baseState;return s(g.default===null),g.default=a,g.optional=!0,this},n.prototype.explicit=function(a){const g=this._baseState;return s(g.explicit===null&&g.implicit===null),g.explicit=a,this},n.prototype.implicit=function(a){const g=this._baseState;return s(g.explicit===null&&g.implicit===null),g.implicit=a,this},n.prototype.obj=function(){const a=this._baseState,g=Array.prototype.slice.call(arguments);return a.obj=!0,g.length!==0&&this._useArgs(g),this},n.prototype.key=function(a){const g=this._baseState;return s(g.key===null),g.key=a,this},n.prototype.any=function(){const a=this._baseState;return a.any=!0,this},n.prototype.choice=function(a){const g=this._baseState;return s(g.choice===null),g.choice=a,this._useArgs(Object.keys(a).map(function(b){return a[b]})),this},n.prototype.contains=function(a){const g=this._baseState;return s(g.use===null),g.contains=a,this},n.prototype._decode=function(a,g){const b=this._baseState;if(b.parent===null)return a.wrapResult(b.children[0]._decode(a,g));let u=b.default,w=!0,y=null;if(b.key!==null&&(y=a.enterKey(b.key)),b.optional){let E=null;if(b.explicit!==null?E=b.explicit:b.implicit!==null?E=b.implicit:b.tag!==null&&(E=b.tag),E===null&&!b.any){const I=a.save();try{b.choice===null?this._decodeGeneric(b.tag,a,g):this._decodeChoice(a,g),w=!0}catch{w=!1}a.restore(I)}else if(w=this._peekTag(a,E,b.any),a.isError(w))return w}let S;if(b.obj&&w&&(S=a.enterObject()),w){if(b.explicit!==null){const I=this._decodeTag(a,b.explicit);if(a.isError(I))return I;a=I}const E=a.offset;if(b.use===null&&b.choice===null){let I;b.any&&(I=a.save());const P=this._decodeTag(a,b.implicit!==null?b.implicit:b.tag,b.any);if(a.isError(P))return P;b.any?u=a.raw(I):a=P}if(g&&g.track&&b.tag!==null&&g.track(a.path(),E,a.length,"tagged"),g&&g.track&&b.tag!==null&&g.track(a.path(),a.offset,a.length,"content"),b.any||(b.choice===null?u=this._decodeGeneric(b.tag,a,g):u=this._decodeChoice(a,g)),a.isError(u))return u;if(!b.any&&b.choice===null&&b.children!==null&&b.children.forEach(function(P){P._decode(a,g)}),b.contains&&(b.tag==="octstr"||b.tag==="bitstr")){const I=new h(u);u=this._getUse(b.contains,a._reporterState.obj)._decode(I,g)}}return b.obj&&w&&(u=a.leaveObject(S)),b.key!==null&&(u!==null||w===!0)?a.leaveKey(y,b.key,u):y!==null&&a.exitKey(y),u},n.prototype._decodeGeneric=function(a,g,b){const u=this._baseState;return a==="seq"||a==="set"?null:a==="seqof"||a==="setof"?this._decodeList(g,a,u.args[0],b):/str$/.test(a)?this._decodeStr(g,a,b):a==="objid"&&u.args?this._decodeObjid(g,u.args[0],u.args[1],b):a==="objid"?this._decodeObjid(g,null,null,b):a==="gentime"||a==="utctime"?this._decodeTime(g,a,b):a==="null_"?this._decodeNull(g,b):a==="bool"?this._decodeBool(g,b):a==="objDesc"?this._decodeStr(g,a,b):a==="int"||a==="enum"?this._decodeInt(g,u.args&&u.args[0],b):u.use!==null?this._getUse(u.use,g._reporterState.obj)._decode(g,b):g.error("unknown tag: "+a)},n.prototype._getUse=function(a,g){const b=this._baseState;return b.useDecoder=this._use(a,g),s(b.useDecoder._baseState.parent===null),b.useDecoder=b.useDecoder._baseState.children[0],b.implicit!==b.useDecoder._baseState.implicit&&(b.useDecoder=b.useDecoder.clone(),b.useDecoder._baseState.implicit=b.implicit),b.useDecoder},n.prototype._decodeChoice=function(a,g){const b=this._baseState;let u=null,w=!1;return Object.keys(b.choice).some(function(y){const S=a.save(),E=b.choice[y];try{const I=E._decode(a,g);if(a.isError(I))return!1;u={type:y,value:I},w=!0}catch{return a.restore(S),!1}return!0},this),w?u:a.error("Choice not matched")},n.prototype._createEncoderBuffer=function(a){return new c(a,this.reporter)},n.prototype._encode=function(a,g,b){const u=this._baseState;if(u.default!==null&&u.default===a)return;const w=this._encodeValue(a,g,b);if(w!==void 0&&!this._skipDefault(w,g,b))return w},n.prototype._encodeValue=function(a,g,b){const u=this._baseState;if(u.parent===null)return u.children[0]._encode(a,g||new l);let w=null;if(this.reporter=g,u.optional&&a===void 0)if(u.default!==null)a=u.default;else return;let y=null,S=!1;if(u.any)w=this._createEncoderBuffer(a);else if(u.choice)w=this._encodeChoice(a,g);else if(u.contains)y=this._getUse(u.contains,b)._encode(a,g),S=!0;else if(u.children)y=u.children.map(function(E){if(E._baseState.tag==="null_")return E._encode(null,g,a);if(E._baseState.key===null)return g.error("Child should have a key");const I=g.enterKey(E._baseState.key);if(typeof a!="object")return g.error("Child expected, but input is not object");const P=E._encode(a[E._baseState.key],g,a);return g.leaveKey(I),P},this).filter(function(E){return E}),y=this._createEncoderBuffer(y);else if(u.tag==="seqof"||u.tag==="setof"){if(!(u.args&&u.args.length===1))return g.error("Too many args for : "+u.tag);if(!Array.isArray(a))return g.error("seqof/setof, but data is not Array");const E=this.clone();E._baseState.implicit=null,y=this._createEncoderBuffer(a.map(function(I){const P=this._baseState;return this._getUse(P.args[0],a)._encode(I,g)},E))}else u.use!==null?w=this._getUse(u.use,b)._encode(a,g):(y=this._encodePrimitive(u.tag,a),S=!0);if(!u.any&&u.choice===null){const E=u.implicit!==null?u.implicit:u.tag,I=u.implicit===null?"universal":"context";E===null?u.use===null&&g.error("Tag could be omitted only for .use()"):u.use===null&&(w=this._encodeComposite(E,S,I,y))}return u.explicit!==null&&(w=this._encodeComposite(u.explicit,!1,"context",w)),w},n.prototype._encodeChoice=function(a,g){const b=this._baseState,u=b.choice[a.type];return u||s(!1,a.type+" not found in "+JSON.stringify(Object.keys(b.choice))),u._encode(a.value,g)},n.prototype._encodePrimitive=function(a,g){const b=this._baseState;if(/str$/.test(a))return this._encodeStr(g,a);if(a==="objid"&&b.args)return this._encodeObjid(g,b.reverseArgs[0],b.args[1]);if(a==="objid")return this._encodeObjid(g,null,null);if(a==="gentime"||a==="utctime")return this._encodeTime(g,a);if(a==="null_")return this._encodeNull();if(a==="int"||a==="enum")return this._encodeInt(g,b.args&&b.reverseArgs[0]);if(a==="bool")return this._encodeBool(g);if(a==="objDesc")return this._encodeStr(g,a);throw new Error("Unsupported tag: "+a)},n.prototype._isNumstr=function(a){return/^[0-9 ]*$/.test(a)},n.prototype._isPrintstr=function(a){return/^[A-Za-z0-9 '()+,-./:=?]*$/.test(a)}},{"../base/buffer":172,"../base/reporter":175,"minimalistic-assert":453}],175:[function(e,d,m){const l=e("inherits");function c(s){this._reporterState={obj:null,path:[],options:s||{},errors:[]}}m.Reporter=c,c.prototype.isError=function(t){return t instanceof h},c.prototype.save=function(){const t=this._reporterState;return{obj:t.obj,pathLen:t.path.length}},c.prototype.restore=function(t){const i=this._reporterState;i.obj=t.obj,i.path=i.path.slice(0,t.pathLen)},c.prototype.enterKey=function(t){return this._reporterState.path.push(t)},c.prototype.exitKey=function(t){const i=this._reporterState;i.path=i.path.slice(0,t-1)},c.prototype.leaveKey=function(t,i,r){const n=this._reporterState;this.exitKey(t),n.obj!==null&&(n.obj[i]=r)},c.prototype.path=function(){return this._reporterState.path.join("/")},c.prototype.enterObject=function(){const t=this._reporterState,i=t.obj;return t.obj={},i},c.prototype.leaveObject=function(t){const i=this._reporterState,r=i.obj;return i.obj=t,r},c.prototype.error=function(t){let i;const r=this._reporterState,n=t instanceof h;if(n?i=t:i=new h(r.path.map(function(o){return"["+JSON.stringify(o)+"]"}).join(""),t.message||t,t.stack),!r.options.partial)throw i;return n||r.errors.push(i),i},c.prototype.wrapResult=function(t){const i=this._reporterState;return i.options.partial?{result:this.isError(t)?null:t,errors:i.errors}:t};function h(s,t){this.path=s,this.rethrow(t)}l(h,Error),h.prototype.rethrow=function(t){if(this.message=t+" at: "+(this.path||"(shallow)"),Error.captureStackTrace&&Error.captureStackTrace(this,h),!this.stack)try{throw new Error(this.message)}catch(i){this.stack=i.stack}return this}},{inherits:440}],176:[function(e,d,m){function l(c){const h={};return Object.keys(c).forEach(function(s){(s|0)==s&&(s=s|0);const t=c[s];h[t]=s}),h}m.tagClass={0:"universal",1:"application",2:"context",3:"private"},m.tagClassByName=l(m.tagClass),m.tag={0:"end",1:"bool",2:"int",3:"bitstr",4:"octstr",5:"null_",6:"objid",7:"objDesc",8:"external",9:"real",10:"enum",11:"embed",12:"utf8str",13:"relativeOid",16:"seq",17:"set",18:"numstr",19:"printstr",20:"t61str",21:"videostr",22:"ia5str",23:"utctime",24:"gentime",25:"graphstr",26:"iso646str",27:"genstr",28:"unistr",29:"charstr",30:"bmpstr"},m.tagByName=l(m.tag)},{}],177:[function(e,d,m){const l=m;l._reverse=function(h){const s={};return Object.keys(h).forEach(function(t){(t|0)==t&&(t=t|0);const i=h[t];s[i]=t}),s},l.der=e("./der")},{"./der":176}],178:[function(e,d,m){const l=e("inherits"),c=e("bn.js"),h=e("../base/buffer").DecoderBuffer,s=e("../base/node"),t=e("../constants/der");function i(f){this.enc="der",this.name=f.name,this.entity=f,this.tree=new r,this.tree._init(f.body)}d.exports=i,i.prototype.decode=function(a,g){return h.isDecoderBuffer(a)||(a=new h(a,g)),this.tree._decode(a,g)};function r(f){s.call(this,"der",f)}l(r,s),r.prototype._peekTag=function(a,g,b){if(a.isEmpty())return!1;const u=a.save(),w=n(a,'Failed to peek tag: "'+g+'"');return a.isError(w)?w:(a.restore(u),w.tag===g||w.tagStr===g||w.tagStr+"of"===g||b)},r.prototype._decodeTag=function(a,g,b){const u=n(a,'Failed to decode tag of "'+g+'"');if(a.isError(u))return u;let w=o(a,u.primitive,'Failed to get length of "'+g+'"');if(a.isError(w))return w;if(!b&&u.tag!==g&&u.tagStr!==g&&u.tagStr+"of"!==g)return a.error('Failed to match tag: "'+g+'"');if(u.primitive||w!==null)return a.skip(w,'Failed to match body of: "'+g+'"');const y=a.save(),S=this._skipUntilEnd(a,'Failed to skip indefinite length body: "'+this.tag+'"');return a.isError(S)?S:(w=a.offset-y.offset,a.restore(y),a.skip(w,'Failed to match body of: "'+g+'"'))},r.prototype._skipUntilEnd=function(a,g){for(;;){const b=n(a,g);if(a.isError(b))return b;const u=o(a,b.primitive,g);if(a.isError(u))return u;let w;if(b.primitive||u!==null?w=a.skip(u):w=this._skipUntilEnd(a,g),a.isError(w))return w;if(b.tagStr==="end")break}},r.prototype._decodeList=function(a,g,b,u){const w=[];for(;!a.isEmpty();){const y=this._peekTag(a,"end");if(a.isError(y))return y;const S=b.decode(a,"der",u);if(a.isError(S)&&y)break;w.push(S)}return w},r.prototype._decodeStr=function(a,g){if(g==="bitstr"){const b=a.readUInt8();return a.isError(b)?b:{unused:b,data:a.raw()}}else if(g==="bmpstr"){const b=a.raw();if(b.length%2===1)return a.error("Decoding of string type: bmpstr length mismatch");let u="";for(let w=0;w>6],u=(g&32)===0;if((g&31)===31){let y=g;for(g=0;(y&128)===128;){if(y=f.readUInt8(a),f.isError(y))return y;g<<=7,g|=y&127}}else g&=31;const w=t.tag[g];return{cls:b,primitive:u,tag:g,tagStr:w}}function o(f,a,g){let b=f.readUInt8(g);if(f.isError(b))return b;if(!a&&b===128)return null;if(!(b&128))return b;const u=b&127;if(u>4)return f.error("length octect is too long");b=0;for(let w=0;w=256;S>>=8)w++;const y=c.alloc(2+w);y[0]=u,y[1]=128|w;for(let S=1+w,E=b.length;E>0;S--,E>>=8)y[S]=E&255;return this._createEncoderBuffer([y,b])},i.prototype._encodeStr=function(f,a){if(a==="bitstr")return this._createEncoderBuffer([f.unused|0,f.data]);if(a==="bmpstr"){const g=c.alloc(f.length*2);for(let b=0;b=40)return this.reporter.error("Second objid identifier OOB");f.splice(0,2,f[0]*40+f[1])}let b=0;for(let y=0;y=128;S>>=7)b++}const u=c.alloc(b);let w=u.length-1;for(let y=f.length-1;y>=0;y--){let S=f[y];for(u[w--]=S&127;(S>>=7)>0;)u[w--]=128|S&127}return this._createEncoderBuffer(u)};function r(o){return o<10?"0"+o:o}i.prototype._encodeTime=function(f,a){let g;const b=new Date(f);return a==="gentime"?g=[r(b.getUTCFullYear()),r(b.getUTCMonth()+1),r(b.getUTCDate()),r(b.getUTCHours()),r(b.getUTCMinutes()),r(b.getUTCSeconds()),"Z"].join(""):a==="utctime"?g=[r(b.getUTCFullYear()%100),r(b.getUTCMonth()+1),r(b.getUTCDate()),r(b.getUTCHours()),r(b.getUTCMinutes()),r(b.getUTCSeconds()),"Z"].join(""):this.reporter.error("Encoding "+a+" time is not supported yet"),this._encodeStr(g,"octstr")},i.prototype._encodeNull=function(){return this._createEncoderBuffer("")},i.prototype._encodeInt=function(f,a){if(typeof f=="string"){if(!a)return this.reporter.error("String int or enum given, but no values map");if(!a.hasOwnProperty(f))return this.reporter.error("Values map doesn't contain: "+JSON.stringify(f));f=a[f]}if(typeof f!="number"&&!c.isBuffer(f)){const u=f.toArray();!f.sign&&u[0]&128&&u.unshift(0),f=c.from(u)}if(c.isBuffer(f)){let u=f.length;f.length===0&&u++;const w=c.alloc(u);return f.copy(w),f.length===0&&(w[0]=0),this._createEncoderBuffer(w)}if(f<128)return this._createEncoderBuffer(f);if(f<256)return this._createEncoderBuffer([0,f]);let g=1;for(let u=f;u>=256;u>>=8)g++;const b=new Array(g);for(let u=b.length-1;u>=0;u--)b[u]=f&255,f>>=8;return b[0]&128&&b.unshift(0),this._createEncoderBuffer(c.from(b))},i.prototype._encodeBool=function(f){return this._createEncoderBuffer(f?255:0)},i.prototype._use=function(f,a){return typeof f=="function"&&(f=f(a)),f._getEncoder("der").tree},i.prototype._skipDefault=function(f,a,g){const b=this._baseState;let u;if(b.default===null)return!1;const w=f.join();if(b.defaultBuffer===void 0&&(b.defaultBuffer=this._encodeValue(b.default,a,g).join()),w.length!==b.defaultBuffer.length)return!1;for(u=0;u=31?g.error("Multi-octet tag encoding unsupported"):(f||(b|=32),b|=s.tagClassByName[a||"universal"]<<6,b)}},{"../base/node":174,"../constants/der":176,inherits:440,"safer-buffer":495}],182:[function(e,d,m){const l=m;l.der=e("./der"),l.pem=e("./pem")},{"./der":181,"./pem":183}],183:[function(e,d,m){const l=e("inherits"),c=e("./der");function h(s){c.call(this,s),this.enc="pem"}l(h,c),d.exports=h,h.prototype.encode=function(t,i){const n=c.prototype.encode.call(this,t).toString("base64"),o=["-----BEGIN "+i.label+"-----"];for(let f=0;f0?M:T},t.min=function(M,T){return M.cmp(T)<0?M:T},t.prototype._init=function(M,T,x){if(typeof M=="number")return this._initNumber(M,T,x);if(typeof M=="object")return this._initArray(M,T,x);T==="hex"&&(T=16),h(T===(T|0)&&T>=2&&T<=36),M=M.toString().replace(/\s+/g,"");var A=0;M[0]==="-"&&(A++,this.negative=1),A=0;A-=3)L=M[A]|M[A-1]<<8|M[A-2]<<16,this.words[N]|=L<>>26-z&67108863,z+=24,z>=26&&(z-=26,N++);else if(x==="le")for(A=0,N=0;A>>26-z&67108863,z+=24,z>=26&&(z-=26,N++);return this.strip()};function r($,M){var T=$.charCodeAt(M);return T>=65&&T<=70?T-55:T>=97&&T<=102?T-87:T-48&15}function n($,M,T){var x=r($,T);return T-1>=M&&(x|=r($,T-1)<<4),x}t.prototype._parseHex=function(M,T,x){this.length=Math.ceil((M.length-T)/6),this.words=new Array(this.length);for(var A=0;A=T;A-=2)z=n(M,T,A)<=18?(N-=18,L+=1,this.words[L]|=z>>>26):N+=8;else{var R=M.length-T;for(A=R%2===0?T+1:T;A=18?(N-=18,L+=1,this.words[L]|=z>>>26):N+=8}this.strip()};function o($,M,T,x){for(var A=0,N=Math.min($.length,T),L=M;L=49?A+=z-49+10:z>=17?A+=z-17+10:A+=z}return A}t.prototype._parseBase=function(M,T,x){this.words=[0],this.length=1;for(var A=0,N=1;N<=67108863;N*=T)A++;A--,N=N/T|0;for(var L=M.length-x,z=L%A,R=Math.min(L,L-z)+x,k=0,C=x;C1&&this.words[this.length-1]===0;)this.length--;return this._normSign()},t.prototype._normSign=function(){return this.length===1&&this.words[0]===0&&(this.negative=0),this},t.prototype.inspect=function(){return(this.red?""};var f=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],a=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],g=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];t.prototype.toString=function(M,T){M=M||10,T=T|0||1;var x;if(M===16||M==="hex"){x="";for(var A=0,N=0,L=0;L>>24-A&16777215,N!==0||L!==this.length-1?x=f[6-R.length]+R+x:x=R+x,A+=2,A>=26&&(A-=26,L--)}for(N!==0&&(x=N.toString(16)+x);x.length%T!==0;)x="0"+x;return this.negative!==0&&(x="-"+x),x}if(M===(M|0)&&M>=2&&M<=36){var k=a[M],C=g[M];x="";var O=this.clone();for(O.negative=0;!O.isZero();){var X=O.modn(C).toString(M);O=O.idivn(C),O.isZero()?x=X+x:x=f[k-X.length]+X+x}for(this.isZero()&&(x="0"+x);x.length%T!==0;)x="0"+x;return this.negative!==0&&(x="-"+x),x}h(!1,"Base should be between 2 and 36")},t.prototype.toNumber=function(){var M=this.words[0];return this.length===2?M+=this.words[1]*67108864:this.length===3&&this.words[2]===1?M+=4503599627370496+this.words[1]*67108864:this.length>2&&h(!1,"Number can only safely store up to 53 bits"),this.negative!==0?-M:M},t.prototype.toJSON=function(){return this.toString(16)},t.prototype.toBuffer=function(M,T){return h(typeof i<"u"),this.toArrayLike(i,M,T)},t.prototype.toArray=function(M,T){return this.toArrayLike(Array,M,T)},t.prototype.toArrayLike=function(M,T,x){var A=this.byteLength(),N=x||Math.max(1,A);h(A<=N,"byte array longer than desired length"),h(N>0,"Requested array length <= 0"),this.strip();var L=T==="le",z=new M(N),R,k,C=this.clone();if(L){for(k=0;!C.isZero();k++)R=C.andln(255),C.iushrn(8),z[k]=R;for(;k=4096&&(x+=13,T>>>=13),T>=64&&(x+=7,T>>>=7),T>=8&&(x+=4,T>>>=4),T>=2&&(x+=2,T>>>=2),x+T},t.prototype._zeroBits=function(M){if(M===0)return 26;var T=M,x=0;return T&8191||(x+=13,T>>>=13),T&127||(x+=7,T>>>=7),T&15||(x+=4,T>>>=4),T&3||(x+=2,T>>>=2),T&1||x++,x},t.prototype.bitLength=function(){var M=this.words[this.length-1],T=this._countBits(M);return(this.length-1)*26+T};function b($){for(var M=new Array($.bitLength()),T=0;T>>A}return M}t.prototype.zeroBits=function(){if(this.isZero())return 0;for(var M=0,T=0;TM.length?this.clone().ior(M):M.clone().ior(this)},t.prototype.uor=function(M){return this.length>M.length?this.clone().iuor(M):M.clone().iuor(this)},t.prototype.iuand=function(M){var T;this.length>M.length?T=M:T=this;for(var x=0;xM.length?this.clone().iand(M):M.clone().iand(this)},t.prototype.uand=function(M){return this.length>M.length?this.clone().iuand(M):M.clone().iuand(this)},t.prototype.iuxor=function(M){var T,x;this.length>M.length?(T=this,x=M):(T=M,x=this);for(var A=0;AM.length?this.clone().ixor(M):M.clone().ixor(this)},t.prototype.uxor=function(M){return this.length>M.length?this.clone().iuxor(M):M.clone().iuxor(this)},t.prototype.inotn=function(M){h(typeof M=="number"&&M>=0);var T=Math.ceil(M/26)|0,x=M%26;this._expand(T),x>0&&T--;for(var A=0;A0&&(this.words[A]=~this.words[A]&67108863>>26-x),this.strip()},t.prototype.notn=function(M){return this.clone().inotn(M)},t.prototype.setn=function(M,T){h(typeof M=="number"&&M>=0);var x=M/26|0,A=M%26;return this._expand(x+1),T?this.words[x]=this.words[x]|1<M.length?(x=this,A=M):(x=M,A=this);for(var N=0,L=0;L>>26;for(;N!==0&&L>>26;if(this.length=x.length,N!==0)this.words[this.length]=N,this.length++;else if(x!==this)for(;LM.length?this.clone().iadd(M):M.clone().iadd(this)},t.prototype.isub=function(M){if(M.negative!==0){M.negative=0;var T=this.iadd(M);return M.negative=1,T._normSign()}else if(this.negative!==0)return this.negative=0,this.iadd(M),this.negative=1,this._normSign();var x=this.cmp(M);if(x===0)return this.negative=0,this.length=1,this.words[0]=0,this;var A,N;x>0?(A=this,N=M):(A=M,N=this);for(var L=0,z=0;z>26,this.words[z]=T&67108863;for(;L!==0&&z>26,this.words[z]=T&67108863;if(L===0&&z>>26,O=R&67108863,X=Math.min(k,M.length-1),ie=Math.max(0,k-$.length+1);ie<=X;ie++){var he=k-ie|0;A=$.words[he]|0,N=M.words[ie]|0,L=A*N+O,C+=L/67108864|0,O=L&67108863}T.words[k]=O|0,R=C|0}return R!==0?T.words[k]=R|0:T.length--,T.strip()}var w=function(M,T,x){var A=M.words,N=T.words,L=x.words,z=0,R,k,C,O=A[0]|0,X=O&8191,ie=O>>>13,he=A[1]|0,ue=he&8191,ke=he>>>13,pe=A[2]|0,ee=pe&8191,Z=pe>>>13,q=A[3]|0,de=q&8191,Me=q>>>13,ae=A[4]|0,ne=ae&8191,Q=ae>>>13,H=A[5]|0,Y=H&8191,le=H>>>13,we=A[6]|0,U=we&8191,ge=we>>>13,Se=A[7]|0,te=Se&8191,se=Se>>>13,ve=A[8]|0,Ee=ve&8191,Ie=ve>>>13,Te=A[9]|0,Pe=Te&8191,He=Te>>>13,me=N[0]|0,Ce=me&8191,Le=me>>>13,ze=N[1]|0,Ye=ze&8191,ot=ze>>>13,pt=N[2]|0,it=pt&8191,rt=pt>>>13,Tt=N[3]|0,Qe=Tt&8191,et=Tt>>>13,At=N[4]|0,lt=At&8191,jt=At>>>13,Ot=N[5]|0,ct=Ot&8191,Bt=Ot>>>13,Ut=N[6]|0,yt=Ut&8191,er=Ut>>>13,Kt=N[7]|0,dt=Kt&8191,Gt=Kt>>>13,Mt=N[8]|0,wt=Mt&8191,$t=Mt>>>13,Qt=N[9]|0,mt=Qt&8191,qt=Qt>>>13;x.negative=M.negative^T.negative,x.length=19,R=Math.imul(X,Ce),k=Math.imul(X,Le),k=k+Math.imul(ie,Ce)|0,C=Math.imul(ie,Le);var _t=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(_t>>>26)|0,_t&=67108863,R=Math.imul(ue,Ce),k=Math.imul(ue,Le),k=k+Math.imul(ke,Ce)|0,C=Math.imul(ke,Le),R=R+Math.imul(X,Ye)|0,k=k+Math.imul(X,ot)|0,k=k+Math.imul(ie,Ye)|0,C=C+Math.imul(ie,ot)|0;var Ct=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(Ct>>>26)|0,Ct&=67108863,R=Math.imul(ee,Ce),k=Math.imul(ee,Le),k=k+Math.imul(Z,Ce)|0,C=Math.imul(Z,Le),R=R+Math.imul(ue,Ye)|0,k=k+Math.imul(ue,ot)|0,k=k+Math.imul(ke,Ye)|0,C=C+Math.imul(ke,ot)|0,R=R+Math.imul(X,it)|0,k=k+Math.imul(X,rt)|0,k=k+Math.imul(ie,it)|0,C=C+Math.imul(ie,rt)|0;var be=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(be>>>26)|0,be&=67108863,R=Math.imul(de,Ce),k=Math.imul(de,Le),k=k+Math.imul(Me,Ce)|0,C=Math.imul(Me,Le),R=R+Math.imul(ee,Ye)|0,k=k+Math.imul(ee,ot)|0,k=k+Math.imul(Z,Ye)|0,C=C+Math.imul(Z,ot)|0,R=R+Math.imul(ue,it)|0,k=k+Math.imul(ue,rt)|0,k=k+Math.imul(ke,it)|0,C=C+Math.imul(ke,rt)|0,R=R+Math.imul(X,Qe)|0,k=k+Math.imul(X,et)|0,k=k+Math.imul(ie,Qe)|0,C=C+Math.imul(ie,et)|0;var De=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(De>>>26)|0,De&=67108863,R=Math.imul(ne,Ce),k=Math.imul(ne,Le),k=k+Math.imul(Q,Ce)|0,C=Math.imul(Q,Le),R=R+Math.imul(de,Ye)|0,k=k+Math.imul(de,ot)|0,k=k+Math.imul(Me,Ye)|0,C=C+Math.imul(Me,ot)|0,R=R+Math.imul(ee,it)|0,k=k+Math.imul(ee,rt)|0,k=k+Math.imul(Z,it)|0,C=C+Math.imul(Z,rt)|0,R=R+Math.imul(ue,Qe)|0,k=k+Math.imul(ue,et)|0,k=k+Math.imul(ke,Qe)|0,C=C+Math.imul(ke,et)|0,R=R+Math.imul(X,lt)|0,k=k+Math.imul(X,jt)|0,k=k+Math.imul(ie,lt)|0,C=C+Math.imul(ie,jt)|0;var Fe=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(Fe>>>26)|0,Fe&=67108863,R=Math.imul(Y,Ce),k=Math.imul(Y,Le),k=k+Math.imul(le,Ce)|0,C=Math.imul(le,Le),R=R+Math.imul(ne,Ye)|0,k=k+Math.imul(ne,ot)|0,k=k+Math.imul(Q,Ye)|0,C=C+Math.imul(Q,ot)|0,R=R+Math.imul(de,it)|0,k=k+Math.imul(de,rt)|0,k=k+Math.imul(Me,it)|0,C=C+Math.imul(Me,rt)|0,R=R+Math.imul(ee,Qe)|0,k=k+Math.imul(ee,et)|0,k=k+Math.imul(Z,Qe)|0,C=C+Math.imul(Z,et)|0,R=R+Math.imul(ue,lt)|0,k=k+Math.imul(ue,jt)|0,k=k+Math.imul(ke,lt)|0,C=C+Math.imul(ke,jt)|0,R=R+Math.imul(X,ct)|0,k=k+Math.imul(X,Bt)|0,k=k+Math.imul(ie,ct)|0,C=C+Math.imul(ie,Bt)|0;var Je=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(Je>>>26)|0,Je&=67108863,R=Math.imul(U,Ce),k=Math.imul(U,Le),k=k+Math.imul(ge,Ce)|0,C=Math.imul(ge,Le),R=R+Math.imul(Y,Ye)|0,k=k+Math.imul(Y,ot)|0,k=k+Math.imul(le,Ye)|0,C=C+Math.imul(le,ot)|0,R=R+Math.imul(ne,it)|0,k=k+Math.imul(ne,rt)|0,k=k+Math.imul(Q,it)|0,C=C+Math.imul(Q,rt)|0,R=R+Math.imul(de,Qe)|0,k=k+Math.imul(de,et)|0,k=k+Math.imul(Me,Qe)|0,C=C+Math.imul(Me,et)|0,R=R+Math.imul(ee,lt)|0,k=k+Math.imul(ee,jt)|0,k=k+Math.imul(Z,lt)|0,C=C+Math.imul(Z,jt)|0,R=R+Math.imul(ue,ct)|0,k=k+Math.imul(ue,Bt)|0,k=k+Math.imul(ke,ct)|0,C=C+Math.imul(ke,Bt)|0,R=R+Math.imul(X,yt)|0,k=k+Math.imul(X,er)|0,k=k+Math.imul(ie,yt)|0,C=C+Math.imul(ie,er)|0;var at=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(at>>>26)|0,at&=67108863,R=Math.imul(te,Ce),k=Math.imul(te,Le),k=k+Math.imul(se,Ce)|0,C=Math.imul(se,Le),R=R+Math.imul(U,Ye)|0,k=k+Math.imul(U,ot)|0,k=k+Math.imul(ge,Ye)|0,C=C+Math.imul(ge,ot)|0,R=R+Math.imul(Y,it)|0,k=k+Math.imul(Y,rt)|0,k=k+Math.imul(le,it)|0,C=C+Math.imul(le,rt)|0,R=R+Math.imul(ne,Qe)|0,k=k+Math.imul(ne,et)|0,k=k+Math.imul(Q,Qe)|0,C=C+Math.imul(Q,et)|0,R=R+Math.imul(de,lt)|0,k=k+Math.imul(de,jt)|0,k=k+Math.imul(Me,lt)|0,C=C+Math.imul(Me,jt)|0,R=R+Math.imul(ee,ct)|0,k=k+Math.imul(ee,Bt)|0,k=k+Math.imul(Z,ct)|0,C=C+Math.imul(Z,Bt)|0,R=R+Math.imul(ue,yt)|0,k=k+Math.imul(ue,er)|0,k=k+Math.imul(ke,yt)|0,C=C+Math.imul(ke,er)|0,R=R+Math.imul(X,dt)|0,k=k+Math.imul(X,Gt)|0,k=k+Math.imul(ie,dt)|0,C=C+Math.imul(ie,Gt)|0;var Rt=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(Rt>>>26)|0,Rt&=67108863,R=Math.imul(Ee,Ce),k=Math.imul(Ee,Le),k=k+Math.imul(Ie,Ce)|0,C=Math.imul(Ie,Le),R=R+Math.imul(te,Ye)|0,k=k+Math.imul(te,ot)|0,k=k+Math.imul(se,Ye)|0,C=C+Math.imul(se,ot)|0,R=R+Math.imul(U,it)|0,k=k+Math.imul(U,rt)|0,k=k+Math.imul(ge,it)|0,C=C+Math.imul(ge,rt)|0,R=R+Math.imul(Y,Qe)|0,k=k+Math.imul(Y,et)|0,k=k+Math.imul(le,Qe)|0,C=C+Math.imul(le,et)|0,R=R+Math.imul(ne,lt)|0,k=k+Math.imul(ne,jt)|0,k=k+Math.imul(Q,lt)|0,C=C+Math.imul(Q,jt)|0,R=R+Math.imul(de,ct)|0,k=k+Math.imul(de,Bt)|0,k=k+Math.imul(Me,ct)|0,C=C+Math.imul(Me,Bt)|0,R=R+Math.imul(ee,yt)|0,k=k+Math.imul(ee,er)|0,k=k+Math.imul(Z,yt)|0,C=C+Math.imul(Z,er)|0,R=R+Math.imul(ue,dt)|0,k=k+Math.imul(ue,Gt)|0,k=k+Math.imul(ke,dt)|0,C=C+Math.imul(ke,Gt)|0,R=R+Math.imul(X,wt)|0,k=k+Math.imul(X,$t)|0,k=k+Math.imul(ie,wt)|0,C=C+Math.imul(ie,$t)|0;var rr=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(rr>>>26)|0,rr&=67108863,R=Math.imul(Pe,Ce),k=Math.imul(Pe,Le),k=k+Math.imul(He,Ce)|0,C=Math.imul(He,Le),R=R+Math.imul(Ee,Ye)|0,k=k+Math.imul(Ee,ot)|0,k=k+Math.imul(Ie,Ye)|0,C=C+Math.imul(Ie,ot)|0,R=R+Math.imul(te,it)|0,k=k+Math.imul(te,rt)|0,k=k+Math.imul(se,it)|0,C=C+Math.imul(se,rt)|0,R=R+Math.imul(U,Qe)|0,k=k+Math.imul(U,et)|0,k=k+Math.imul(ge,Qe)|0,C=C+Math.imul(ge,et)|0,R=R+Math.imul(Y,lt)|0,k=k+Math.imul(Y,jt)|0,k=k+Math.imul(le,lt)|0,C=C+Math.imul(le,jt)|0,R=R+Math.imul(ne,ct)|0,k=k+Math.imul(ne,Bt)|0,k=k+Math.imul(Q,ct)|0,C=C+Math.imul(Q,Bt)|0,R=R+Math.imul(de,yt)|0,k=k+Math.imul(de,er)|0,k=k+Math.imul(Me,yt)|0,C=C+Math.imul(Me,er)|0,R=R+Math.imul(ee,dt)|0,k=k+Math.imul(ee,Gt)|0,k=k+Math.imul(Z,dt)|0,C=C+Math.imul(Z,Gt)|0,R=R+Math.imul(ue,wt)|0,k=k+Math.imul(ue,$t)|0,k=k+Math.imul(ke,wt)|0,C=C+Math.imul(ke,$t)|0,R=R+Math.imul(X,mt)|0,k=k+Math.imul(X,qt)|0,k=k+Math.imul(ie,mt)|0,C=C+Math.imul(ie,qt)|0;var vr=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(vr>>>26)|0,vr&=67108863,R=Math.imul(Pe,Ye),k=Math.imul(Pe,ot),k=k+Math.imul(He,Ye)|0,C=Math.imul(He,ot),R=R+Math.imul(Ee,it)|0,k=k+Math.imul(Ee,rt)|0,k=k+Math.imul(Ie,it)|0,C=C+Math.imul(Ie,rt)|0,R=R+Math.imul(te,Qe)|0,k=k+Math.imul(te,et)|0,k=k+Math.imul(se,Qe)|0,C=C+Math.imul(se,et)|0,R=R+Math.imul(U,lt)|0,k=k+Math.imul(U,jt)|0,k=k+Math.imul(ge,lt)|0,C=C+Math.imul(ge,jt)|0,R=R+Math.imul(Y,ct)|0,k=k+Math.imul(Y,Bt)|0,k=k+Math.imul(le,ct)|0,C=C+Math.imul(le,Bt)|0,R=R+Math.imul(ne,yt)|0,k=k+Math.imul(ne,er)|0,k=k+Math.imul(Q,yt)|0,C=C+Math.imul(Q,er)|0,R=R+Math.imul(de,dt)|0,k=k+Math.imul(de,Gt)|0,k=k+Math.imul(Me,dt)|0,C=C+Math.imul(Me,Gt)|0,R=R+Math.imul(ee,wt)|0,k=k+Math.imul(ee,$t)|0,k=k+Math.imul(Z,wt)|0,C=C+Math.imul(Z,$t)|0,R=R+Math.imul(ue,mt)|0,k=k+Math.imul(ue,qt)|0,k=k+Math.imul(ke,mt)|0,C=C+Math.imul(ke,qt)|0;var Br=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(Br>>>26)|0,Br&=67108863,R=Math.imul(Pe,it),k=Math.imul(Pe,rt),k=k+Math.imul(He,it)|0,C=Math.imul(He,rt),R=R+Math.imul(Ee,Qe)|0,k=k+Math.imul(Ee,et)|0,k=k+Math.imul(Ie,Qe)|0,C=C+Math.imul(Ie,et)|0,R=R+Math.imul(te,lt)|0,k=k+Math.imul(te,jt)|0,k=k+Math.imul(se,lt)|0,C=C+Math.imul(se,jt)|0,R=R+Math.imul(U,ct)|0,k=k+Math.imul(U,Bt)|0,k=k+Math.imul(ge,ct)|0,C=C+Math.imul(ge,Bt)|0,R=R+Math.imul(Y,yt)|0,k=k+Math.imul(Y,er)|0,k=k+Math.imul(le,yt)|0,C=C+Math.imul(le,er)|0,R=R+Math.imul(ne,dt)|0,k=k+Math.imul(ne,Gt)|0,k=k+Math.imul(Q,dt)|0,C=C+Math.imul(Q,Gt)|0,R=R+Math.imul(de,wt)|0,k=k+Math.imul(de,$t)|0,k=k+Math.imul(Me,wt)|0,C=C+Math.imul(Me,$t)|0,R=R+Math.imul(ee,mt)|0,k=k+Math.imul(ee,qt)|0,k=k+Math.imul(Z,mt)|0,C=C+Math.imul(Z,qt)|0;var br=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(br>>>26)|0,br&=67108863,R=Math.imul(Pe,Qe),k=Math.imul(Pe,et),k=k+Math.imul(He,Qe)|0,C=Math.imul(He,et),R=R+Math.imul(Ee,lt)|0,k=k+Math.imul(Ee,jt)|0,k=k+Math.imul(Ie,lt)|0,C=C+Math.imul(Ie,jt)|0,R=R+Math.imul(te,ct)|0,k=k+Math.imul(te,Bt)|0,k=k+Math.imul(se,ct)|0,C=C+Math.imul(se,Bt)|0,R=R+Math.imul(U,yt)|0,k=k+Math.imul(U,er)|0,k=k+Math.imul(ge,yt)|0,C=C+Math.imul(ge,er)|0,R=R+Math.imul(Y,dt)|0,k=k+Math.imul(Y,Gt)|0,k=k+Math.imul(le,dt)|0,C=C+Math.imul(le,Gt)|0,R=R+Math.imul(ne,wt)|0,k=k+Math.imul(ne,$t)|0,k=k+Math.imul(Q,wt)|0,C=C+Math.imul(Q,$t)|0,R=R+Math.imul(de,mt)|0,k=k+Math.imul(de,qt)|0,k=k+Math.imul(Me,mt)|0,C=C+Math.imul(Me,qt)|0;var lr=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(lr>>>26)|0,lr&=67108863,R=Math.imul(Pe,lt),k=Math.imul(Pe,jt),k=k+Math.imul(He,lt)|0,C=Math.imul(He,jt),R=R+Math.imul(Ee,ct)|0,k=k+Math.imul(Ee,Bt)|0,k=k+Math.imul(Ie,ct)|0,C=C+Math.imul(Ie,Bt)|0,R=R+Math.imul(te,yt)|0,k=k+Math.imul(te,er)|0,k=k+Math.imul(se,yt)|0,C=C+Math.imul(se,er)|0,R=R+Math.imul(U,dt)|0,k=k+Math.imul(U,Gt)|0,k=k+Math.imul(ge,dt)|0,C=C+Math.imul(ge,Gt)|0,R=R+Math.imul(Y,wt)|0,k=k+Math.imul(Y,$t)|0,k=k+Math.imul(le,wt)|0,C=C+Math.imul(le,$t)|0,R=R+Math.imul(ne,mt)|0,k=k+Math.imul(ne,qt)|0,k=k+Math.imul(Q,mt)|0,C=C+Math.imul(Q,qt)|0;var ri=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(ri>>>26)|0,ri&=67108863,R=Math.imul(Pe,ct),k=Math.imul(Pe,Bt),k=k+Math.imul(He,ct)|0,C=Math.imul(He,Bt),R=R+Math.imul(Ee,yt)|0,k=k+Math.imul(Ee,er)|0,k=k+Math.imul(Ie,yt)|0,C=C+Math.imul(Ie,er)|0,R=R+Math.imul(te,dt)|0,k=k+Math.imul(te,Gt)|0,k=k+Math.imul(se,dt)|0,C=C+Math.imul(se,Gt)|0,R=R+Math.imul(U,wt)|0,k=k+Math.imul(U,$t)|0,k=k+Math.imul(ge,wt)|0,C=C+Math.imul(ge,$t)|0,R=R+Math.imul(Y,mt)|0,k=k+Math.imul(Y,qt)|0,k=k+Math.imul(le,mt)|0,C=C+Math.imul(le,qt)|0;var ii=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(ii>>>26)|0,ii&=67108863,R=Math.imul(Pe,yt),k=Math.imul(Pe,er),k=k+Math.imul(He,yt)|0,C=Math.imul(He,er),R=R+Math.imul(Ee,dt)|0,k=k+Math.imul(Ee,Gt)|0,k=k+Math.imul(Ie,dt)|0,C=C+Math.imul(Ie,Gt)|0,R=R+Math.imul(te,wt)|0,k=k+Math.imul(te,$t)|0,k=k+Math.imul(se,wt)|0,C=C+Math.imul(se,$t)|0,R=R+Math.imul(U,mt)|0,k=k+Math.imul(U,qt)|0,k=k+Math.imul(ge,mt)|0,C=C+Math.imul(ge,qt)|0;var ar=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(ar>>>26)|0,ar&=67108863,R=Math.imul(Pe,dt),k=Math.imul(Pe,Gt),k=k+Math.imul(He,dt)|0,C=Math.imul(He,Gt),R=R+Math.imul(Ee,wt)|0,k=k+Math.imul(Ee,$t)|0,k=k+Math.imul(Ie,wt)|0,C=C+Math.imul(Ie,$t)|0,R=R+Math.imul(te,mt)|0,k=k+Math.imul(te,qt)|0,k=k+Math.imul(se,mt)|0,C=C+Math.imul(se,qt)|0;var Xr=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(Xr>>>26)|0,Xr&=67108863,R=Math.imul(Pe,wt),k=Math.imul(Pe,$t),k=k+Math.imul(He,wt)|0,C=Math.imul(He,$t),R=R+Math.imul(Ee,mt)|0,k=k+Math.imul(Ee,qt)|0,k=k+Math.imul(Ie,mt)|0,C=C+Math.imul(Ie,qt)|0;var Wr=(z+R|0)+((k&8191)<<13)|0;z=(C+(k>>>13)|0)+(Wr>>>26)|0,Wr&=67108863,R=Math.imul(Pe,mt),k=Math.imul(Pe,qt),k=k+Math.imul(He,mt)|0,C=Math.imul(He,qt);var Vr=(z+R|0)+((k&8191)<<13)|0;return z=(C+(k>>>13)|0)+(Vr>>>26)|0,Vr&=67108863,L[0]=_t,L[1]=Ct,L[2]=be,L[3]=De,L[4]=Fe,L[5]=Je,L[6]=at,L[7]=Rt,L[8]=rr,L[9]=vr,L[10]=Br,L[11]=br,L[12]=lr,L[13]=ri,L[14]=ii,L[15]=ar,L[16]=Xr,L[17]=Wr,L[18]=Vr,z!==0&&(L[19]=z,x.length++),x};Math.imul||(w=u);function y($,M,T){T.negative=M.negative^$.negative,T.length=$.length+M.length;for(var x=0,A=0,N=0;N>>26)|0,A+=L>>>26,L&=67108863}T.words[N]=z,x=L,L=A}return x!==0?T.words[N]=x:T.length--,T.strip()}function S($,M,T){var x=new E;return x.mulp($,M,T)}t.prototype.mulTo=function(M,T){var x,A=this.length+M.length;return this.length===10&&M.length===10?x=w(this,M,T):A<63?x=u(this,M,T):A<1024?x=y(this,M,T):x=S(this,M,T),x};function E($,M){this.x=$,this.y=M}E.prototype.makeRBT=function(M){for(var T=new Array(M),x=t.prototype._countBits(M)-1,A=0;A>=1;return A},E.prototype.permute=function(M,T,x,A,N,L){for(var z=0;z>>1)N++;return 1<>>13,x[2*L+1]=N&8191,N=N>>>13;for(L=2*T;L>=26,T+=A/67108864|0,T+=N>>>26,this.words[x]=N&67108863}return T!==0&&(this.words[x]=T,this.length++),this},t.prototype.muln=function(M){return this.clone().imuln(M)},t.prototype.sqr=function(){return this.mul(this)},t.prototype.isqr=function(){return this.imul(this.clone())},t.prototype.pow=function(M){var T=b(M);if(T.length===0)return new t(1);for(var x=this,A=0;A=0);var T=M%26,x=(M-T)/26,A=67108863>>>26-T<<26-T,N;if(T!==0){var L=0;for(N=0;N>>26-T}L&&(this.words[N]=L,this.length++)}if(x!==0){for(N=this.length-1;N>=0;N--)this.words[N+x]=this.words[N];for(N=0;N=0);var A;T?A=(T-T%26)/26:A=0;var N=M%26,L=Math.min((M-N)/26,this.length),z=67108863^67108863>>>N<L)for(this.length-=L,k=0;k=0&&(C!==0||k>=A);k--){var O=this.words[k]|0;this.words[k]=C<<26-N|O>>>N,C=O&z}return R&&C!==0&&(R.words[R.length++]=C),this.length===0&&(this.words[0]=0,this.length=1),this.strip()},t.prototype.ishrn=function(M,T,x){return h(this.negative===0),this.iushrn(M,T,x)},t.prototype.shln=function(M){return this.clone().ishln(M)},t.prototype.ushln=function(M){return this.clone().iushln(M)},t.prototype.shrn=function(M){return this.clone().ishrn(M)},t.prototype.ushrn=function(M){return this.clone().iushrn(M)},t.prototype.testn=function(M){h(typeof M=="number"&&M>=0);var T=M%26,x=(M-T)/26,A=1<=0);var T=M%26,x=(M-T)/26;if(h(this.negative===0,"imaskn works only with positive numbers"),this.length<=x)return this;if(T!==0&&x++,this.length=Math.min(x,this.length),T!==0){var A=67108863^67108863>>>T<=67108864;T++)this.words[T]-=67108864,T===this.length-1?this.words[T+1]=1:this.words[T+1]++;return this.length=Math.max(this.length,T+1),this},t.prototype.isubn=function(M){if(h(typeof M=="number"),h(M<67108864),M<0)return this.iaddn(-M);if(this.negative!==0)return this.negative=0,this.iaddn(M),this.negative=1,this;if(this.words[0]-=M,this.length===1&&this.words[0]<0)this.words[0]=-this.words[0],this.negative=1;else for(var T=0;T>26)-(R/67108864|0),this.words[N+x]=L&67108863}for(;N>26,this.words[N+x]=L&67108863;if(z===0)return this.strip();for(h(z===-1),z=0,N=0;N>26,this.words[N]=L&67108863;return this.negative=1,this.strip()},t.prototype._wordDiv=function(M,T){var x=this.length-M.length,A=this.clone(),N=M,L=N.words[N.length-1]|0,z=this._countBits(L);x=26-z,x!==0&&(N=N.ushln(x),A.iushln(x),L=N.words[N.length-1]|0);var R=A.length-N.length,k;if(T!=="mod"){k=new t(null),k.length=R+1,k.words=new Array(k.length);for(var C=0;C=0;X--){var ie=(A.words[N.length+X]|0)*67108864+(A.words[N.length+X-1]|0);for(ie=Math.min(ie/L|0,67108863),A._ishlnsubmul(N,ie,X);A.negative!==0;)ie--,A.negative=0,A._ishlnsubmul(N,1,X),A.isZero()||(A.negative^=1);k&&(k.words[X]=ie)}return k&&k.strip(),A.strip(),T!=="div"&&x!==0&&A.iushrn(x),{div:k||null,mod:A}},t.prototype.divmod=function(M,T,x){if(h(!M.isZero()),this.isZero())return{div:new t(0),mod:new t(0)};var A,N,L;return this.negative!==0&&M.negative===0?(L=this.neg().divmod(M,T),T!=="mod"&&(A=L.div.neg()),T!=="div"&&(N=L.mod.neg(),x&&N.negative!==0&&N.iadd(M)),{div:A,mod:N}):this.negative===0&&M.negative!==0?(L=this.divmod(M.neg(),T),T!=="mod"&&(A=L.div.neg()),{div:A,mod:L.mod}):this.negative&M.negative?(L=this.neg().divmod(M.neg(),T),T!=="div"&&(N=L.mod.neg(),x&&N.negative!==0&&N.isub(M)),{div:L.div,mod:N}):M.length>this.length||this.cmp(M)<0?{div:new t(0),mod:this}:M.length===1?T==="div"?{div:this.divn(M.words[0]),mod:null}:T==="mod"?{div:null,mod:new t(this.modn(M.words[0]))}:{div:this.divn(M.words[0]),mod:new t(this.modn(M.words[0]))}:this._wordDiv(M,T)},t.prototype.div=function(M){return this.divmod(M,"div",!1).div},t.prototype.mod=function(M){return this.divmod(M,"mod",!1).mod},t.prototype.umod=function(M){return this.divmod(M,"mod",!0).mod},t.prototype.divRound=function(M){var T=this.divmod(M);if(T.mod.isZero())return T.div;var x=T.div.negative!==0?T.mod.isub(M):T.mod,A=M.ushrn(1),N=M.andln(1),L=x.cmp(A);return L<0||N===1&&L===0?T.div:T.div.negative!==0?T.div.isubn(1):T.div.iaddn(1)},t.prototype.modn=function(M){h(M<=67108863);for(var T=(1<<26)%M,x=0,A=this.length-1;A>=0;A--)x=(T*x+(this.words[A]|0))%M;return x},t.prototype.idivn=function(M){h(M<=67108863);for(var T=0,x=this.length-1;x>=0;x--){var A=(this.words[x]|0)+T*67108864;this.words[x]=A/M|0,T=A%M}return this.strip()},t.prototype.divn=function(M){return this.clone().idivn(M)},t.prototype.egcd=function(M){h(M.negative===0),h(!M.isZero());var T=this,x=M.clone();T.negative!==0?T=T.umod(M):T=T.clone();for(var A=new t(1),N=new t(0),L=new t(0),z=new t(1),R=0;T.isEven()&&x.isEven();)T.iushrn(1),x.iushrn(1),++R;for(var k=x.clone(),C=T.clone();!T.isZero();){for(var O=0,X=1;!(T.words[0]&X)&&O<26;++O,X<<=1);if(O>0)for(T.iushrn(O);O-- >0;)(A.isOdd()||N.isOdd())&&(A.iadd(k),N.isub(C)),A.iushrn(1),N.iushrn(1);for(var ie=0,he=1;!(x.words[0]&he)&&ie<26;++ie,he<<=1);if(ie>0)for(x.iushrn(ie);ie-- >0;)(L.isOdd()||z.isOdd())&&(L.iadd(k),z.isub(C)),L.iushrn(1),z.iushrn(1);T.cmp(x)>=0?(T.isub(x),A.isub(L),N.isub(z)):(x.isub(T),L.isub(A),z.isub(N))}return{a:L,b:z,gcd:x.iushln(R)}},t.prototype._invmp=function(M){h(M.negative===0),h(!M.isZero());var T=this,x=M.clone();T.negative!==0?T=T.umod(M):T=T.clone();for(var A=new t(1),N=new t(0),L=x.clone();T.cmpn(1)>0&&x.cmpn(1)>0;){for(var z=0,R=1;!(T.words[0]&R)&&z<26;++z,R<<=1);if(z>0)for(T.iushrn(z);z-- >0;)A.isOdd()&&A.iadd(L),A.iushrn(1);for(var k=0,C=1;!(x.words[0]&C)&&k<26;++k,C<<=1);if(k>0)for(x.iushrn(k);k-- >0;)N.isOdd()&&N.iadd(L),N.iushrn(1);T.cmp(x)>=0?(T.isub(x),A.isub(N)):(x.isub(T),N.isub(A))}var O;return T.cmpn(1)===0?O=A:O=N,O.cmpn(0)<0&&O.iadd(M),O},t.prototype.gcd=function(M){if(this.isZero())return M.abs();if(M.isZero())return this.abs();var T=this.clone(),x=M.clone();T.negative=0,x.negative=0;for(var A=0;T.isEven()&&x.isEven();A++)T.iushrn(1),x.iushrn(1);do{for(;T.isEven();)T.iushrn(1);for(;x.isEven();)x.iushrn(1);var N=T.cmp(x);if(N<0){var L=T;T=x,x=L}else if(N===0||x.cmpn(1)===0)break;T.isub(x)}while(!0);return x.iushln(A)},t.prototype.invm=function(M){return this.egcd(M).a.umod(M)},t.prototype.isEven=function(){return(this.words[0]&1)===0},t.prototype.isOdd=function(){return(this.words[0]&1)===1},t.prototype.andln=function(M){return this.words[0]&M},t.prototype.bincn=function(M){h(typeof M=="number");var T=M%26,x=(M-T)/26,A=1<>>26,z&=67108863,this.words[L]=z}return N!==0&&(this.words[L]=N,this.length++),this},t.prototype.isZero=function(){return this.length===1&&this.words[0]===0},t.prototype.cmpn=function(M){var T=M<0;if(this.negative!==0&&!T)return-1;if(this.negative===0&&T)return 1;this.strip();var x;if(this.length>1)x=1;else{T&&(M=-M),h(M<=67108863,"Number is too big");var A=this.words[0]|0;x=A===M?0:AM.length)return 1;if(this.length=0;x--){var A=this.words[x]|0,N=M.words[x]|0;if(A!==N){AN&&(T=1);break}}return T},t.prototype.gtn=function(M){return this.cmpn(M)===1},t.prototype.gt=function(M){return this.cmp(M)===1},t.prototype.gten=function(M){return this.cmpn(M)>=0},t.prototype.gte=function(M){return this.cmp(M)>=0},t.prototype.ltn=function(M){return this.cmpn(M)===-1},t.prototype.lt=function(M){return this.cmp(M)===-1},t.prototype.lten=function(M){return this.cmpn(M)<=0},t.prototype.lte=function(M){return this.cmp(M)<=0},t.prototype.eqn=function(M){return this.cmpn(M)===0},t.prototype.eq=function(M){return this.cmp(M)===0},t.red=function(M){return new V(M)},t.prototype.toRed=function(M){return h(!this.red,"Already a number in reduction context"),h(this.negative===0,"red works only with positives"),M.convertTo(this)._forceRed(M)},t.prototype.fromRed=function(){return h(this.red,"fromRed works only with numbers in reduction context"),this.red.convertFrom(this)},t.prototype._forceRed=function(M){return this.red=M,this},t.prototype.forceRed=function(M){return h(!this.red,"Already a number in reduction context"),this._forceRed(M)},t.prototype.redAdd=function(M){return h(this.red,"redAdd works only with red numbers"),this.red.add(this,M)},t.prototype.redIAdd=function(M){return h(this.red,"redIAdd works only with red numbers"),this.red.iadd(this,M)},t.prototype.redSub=function(M){return h(this.red,"redSub works only with red numbers"),this.red.sub(this,M)},t.prototype.redISub=function(M){return h(this.red,"redISub works only with red numbers"),this.red.isub(this,M)},t.prototype.redShl=function(M){return h(this.red,"redShl works only with red numbers"),this.red.shl(this,M)},t.prototype.redMul=function(M){return h(this.red,"redMul works only with red numbers"),this.red._verify2(this,M),this.red.mul(this,M)},t.prototype.redIMul=function(M){return h(this.red,"redMul works only with red numbers"),this.red._verify2(this,M),this.red.imul(this,M)},t.prototype.redSqr=function(){return h(this.red,"redSqr works only with red numbers"),this.red._verify1(this),this.red.sqr(this)},t.prototype.redISqr=function(){return h(this.red,"redISqr works only with red numbers"),this.red._verify1(this),this.red.isqr(this)},t.prototype.redSqrt=function(){return h(this.red,"redSqrt works only with red numbers"),this.red._verify1(this),this.red.sqrt(this)},t.prototype.redInvm=function(){return h(this.red,"redInvm works only with red numbers"),this.red._verify1(this),this.red.invm(this)},t.prototype.redNeg=function(){return h(this.red,"redNeg works only with red numbers"),this.red._verify1(this),this.red.neg(this)},t.prototype.redPow=function(M){return h(this.red&&!M.red,"redPow(normalNum)"),this.red._verify1(this),this.red.pow(this,M)};var I={k256:null,p224:null,p192:null,p25519:null};function P($,M){this.name=$,this.p=new t(M,16),this.n=this.p.bitLength(),this.k=new t(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}P.prototype._tmp=function(){var M=new t(null);return M.words=new Array(Math.ceil(this.n/13)),M},P.prototype.ireduce=function(M){var T=M,x;do this.split(T,this.tmp),T=this.imulK(T),T=T.iadd(this.tmp),x=T.bitLength();while(x>this.n);var A=x0?T.isub(this.p):T.strip!==void 0?T.strip():T._strip(),T},P.prototype.split=function(M,T){M.iushrn(this.n,0,T)},P.prototype.imulK=function(M){return M.imul(this.k)};function F(){P.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}s(F,P),F.prototype.split=function(M,T){for(var x=4194303,A=Math.min(M.length,9),N=0;N>>22,L=z}L>>>=22,M.words[N-10]=L,L===0&&M.length>10?M.length-=10:M.length-=9},F.prototype.imulK=function(M){M.words[M.length]=0,M.words[M.length+1]=0,M.length+=2;for(var T=0,x=0;x>>=26,M.words[x]=N,T=A}return T!==0&&(M.words[M.length++]=T),M},t._prime=function(M){if(I[M])return I[M];var T;if(M==="k256")T=new F;else if(M==="p224")T=new j;else if(M==="p192")T=new W;else if(M==="p25519")T=new G;else throw new Error("Unknown prime "+M);return I[M]=T,T};function V($){if(typeof $=="string"){var M=t._prime($);this.m=M.p,this.prime=M}else h($.gtn(1),"modulus must be greater than 1"),this.m=$,this.prime=null}V.prototype._verify1=function(M){h(M.negative===0,"red works only with positives"),h(M.red,"red works only with red numbers")},V.prototype._verify2=function(M,T){h((M.negative|T.negative)===0,"red works only with positives"),h(M.red&&M.red===T.red,"red works only with red numbers")},V.prototype.imod=function(M){return this.prime?this.prime.ireduce(M)._forceRed(this):M.umod(this.m)._forceRed(this)},V.prototype.neg=function(M){return M.isZero()?M.clone():this.m.sub(M)._forceRed(this)},V.prototype.add=function(M,T){this._verify2(M,T);var x=M.add(T);return x.cmp(this.m)>=0&&x.isub(this.m),x._forceRed(this)},V.prototype.iadd=function(M,T){this._verify2(M,T);var x=M.iadd(T);return x.cmp(this.m)>=0&&x.isub(this.m),x},V.prototype.sub=function(M,T){this._verify2(M,T);var x=M.sub(T);return x.cmpn(0)<0&&x.iadd(this.m),x._forceRed(this)},V.prototype.isub=function(M,T){this._verify2(M,T);var x=M.isub(T);return x.cmpn(0)<0&&x.iadd(this.m),x},V.prototype.shl=function(M,T){return this._verify1(M),this.imod(M.ushln(T))},V.prototype.imul=function(M,T){return this._verify2(M,T),this.imod(M.imul(T))},V.prototype.mul=function(M,T){return this._verify2(M,T),this.imod(M.mul(T))},V.prototype.isqr=function(M){return this.imul(M,M.clone())},V.prototype.sqr=function(M){return this.mul(M,M)},V.prototype.sqrt=function(M){if(M.isZero())return M.clone();var T=this.m.andln(3);if(h(T%2===1),T===3){var x=this.m.add(new t(1)).iushrn(2);return this.pow(M,x)}for(var A=this.m.subn(1),N=0;!A.isZero()&&A.andln(1)===0;)N++,A.iushrn(1);h(!A.isZero());var L=new t(1).toRed(this),z=L.redNeg(),R=this.m.subn(1).iushrn(1),k=this.m.bitLength();for(k=new t(2*k*k).toRed(this);this.pow(k,R).cmp(z)!==0;)k.redIAdd(z);for(var C=this.pow(k,A),O=this.pow(M,A.addn(1).iushrn(1)),X=this.pow(M,A),ie=N;X.cmp(L)!==0;){for(var he=X,ue=0;he.cmp(L)!==0;ue++)he=he.redSqr();h(ue=0;N--){for(var C=T.words[N],O=k-1;O>=0;O--){var X=C>>O&1;if(L!==A[0]&&(L=this.sqr(L)),X===0&&z===0){R=0;continue}z<<=1,z|=X,R++,!(R!==x&&(N!==0||O!==0))&&(L=this.mul(L,A[z]),R=0,z=0)}k=26}return L},V.prototype.convertTo=function(M){var T=M.umod(this.m);return T===M?T.clone():T},V.prototype.convertFrom=function(M){var T=M.clone();return T.red=null,T},t.mont=function(M){return new J(M)};function J($){V.call(this,$),this.shift=this.m.bitLength(),this.shift%26!==0&&(this.shift+=26-this.shift%26),this.r=new t(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}s(J,V),J.prototype.convertTo=function(M){return this.imod(M.ushln(this.shift))},J.prototype.convertFrom=function(M){var T=this.imod(M.mul(this.rinv));return T.red=null,T},J.prototype.imul=function(M,T){if(M.isZero()||T.isZero())return M.words[0]=0,M.length=1,M;var x=M.imul(T),A=x.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),N=x.isub(A).iushrn(this.shift),L=N;return N.cmp(this.m)>=0?L=N.isub(this.m):N.cmpn(0)<0&&(L=N.iadd(this.m)),L._forceRed(this)},J.prototype.mul=function(M,T){if(M.isZero()||T.isZero())return new t(0)._forceRed(this);var x=M.mul(T),A=x.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),N=x.isub(A).iushrn(this.shift),L=N;return N.cmp(this.m)>=0?L=N.isub(this.m):N.cmpn(0)<0&&(L=N.iadd(this.m)),L._forceRed(this)},J.prototype.invm=function(M){var T=this.imod(M._invmp(this.m).mul(this.r2));return T._forceRed(this)}})(typeof d>"u"||d,void 0)},{buffer:188}],185:[function(e,d,m){m.byteLength=n,m.toByteArray=f,m.fromByteArray=b;for(var l=[],c=[],h=typeof Uint8Array<"u"?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",t=0,i=s.length;t0)throw new Error("Invalid string. Length must be a multiple of 4");var y=u.indexOf("=");y===-1&&(y=w);var S=y===w?0:4-y%4;return[y,S]}function n(u){var w=r(u),y=w[0],S=w[1];return(y+S)*3/4-S}function o(u,w,y){return(w+y)*3/4-y}function f(u){var w,y=r(u),S=y[0],E=y[1],I=new h(o(u,S,E)),P=0,F=E>0?S-4:S,j;for(j=0;j>16&255,I[P++]=w>>8&255,I[P++]=w&255;return E===2&&(w=c[u.charCodeAt(j)]<<2|c[u.charCodeAt(j+1)]>>4,I[P++]=w&255),E===1&&(w=c[u.charCodeAt(j)]<<10|c[u.charCodeAt(j+1)]<<4|c[u.charCodeAt(j+2)]>>2,I[P++]=w>>8&255,I[P++]=w&255),I}function a(u){return l[u>>18&63]+l[u>>12&63]+l[u>>6&63]+l[u&63]}function g(u,w,y){for(var S,E=[],I=w;IF?F:P+I));return S===1?(w=u[y-1],E.push(l[w>>2]+l[w<<4&63]+"==")):S===2&&(w=(u[y-2]<<8)+u[y-1],E.push(l[w>>10]+l[w>>4&63]+l[w<<2&63]+"=")),E.join("")}},{}],186:[function(e,d,m){(function(l,c){function h(T,x){if(!T)throw new Error(x||"Assertion failed")}function s(T,x){T.super_=x;var A=function(){};A.prototype=x.prototype,T.prototype=new A,T.prototype.constructor=T}function t(T,x,A){if(t.isBN(T))return T;this.negative=0,this.words=null,this.length=0,this.red=null,T!==null&&((x==="le"||x==="be")&&(A=x,x=10),this._init(T||0,x||10,A||"be"))}typeof l=="object"?l.exports=t:c.BN=t,t.BN=t,t.wordSize=26;var i;try{typeof window<"u"&&typeof window.Buffer<"u"?i=window.Buffer:i=e("buffer").Buffer}catch{}t.isBN=function(x){return x instanceof t?!0:x!==null&&typeof x=="object"&&x.constructor.wordSize===t.wordSize&&Array.isArray(x.words)},t.max=function(x,A){return x.cmp(A)>0?x:A},t.min=function(x,A){return x.cmp(A)<0?x:A},t.prototype._init=function(x,A,N){if(typeof x=="number")return this._initNumber(x,A,N);if(typeof x=="object")return this._initArray(x,A,N);A==="hex"&&(A=16),h(A===(A|0)&&A>=2&&A<=36),x=x.toString().replace(/\s+/g,"");var L=0;x[0]==="-"&&(L++,this.negative=1),L=0;L-=3)R=x[L]|x[L-1]<<8|x[L-2]<<16,this.words[z]|=R<>>26-k&67108863,k+=24,k>=26&&(k-=26,z++);else if(N==="le")for(L=0,z=0;L>>26-k&67108863,k+=24,k>=26&&(k-=26,z++);return this._strip()};function r(T,x){var A=T.charCodeAt(x);if(A>=48&&A<=57)return A-48;if(A>=65&&A<=70)return A-55;if(A>=97&&A<=102)return A-87;h(!1,"Invalid character in "+T)}function n(T,x,A){var N=r(T,A);return A-1>=x&&(N|=r(T,A-1)<<4),N}t.prototype._parseHex=function(x,A,N){this.length=Math.ceil((x.length-A)/6),this.words=new Array(this.length);for(var L=0;L=A;L-=2)k=n(x,A,L)<=18?(z-=18,R+=1,this.words[R]|=k>>>26):z+=8;else{var C=x.length-A;for(L=C%2===0?A+1:A;L=18?(z-=18,R+=1,this.words[R]|=k>>>26):z+=8}this._strip()};function o(T,x,A,N){for(var L=0,z=0,R=Math.min(T.length,A),k=x;k=49?z=C-49+10:C>=17?z=C-17+10:z=C,h(C>=0&&z1&&this.words[this.length-1]===0;)this.length--;return this._normSign()},t.prototype._normSign=function(){return this.length===1&&this.words[0]===0&&(this.negative=0),this},typeof Symbol<"u"&&typeof Symbol.for=="function")try{t.prototype[Symbol.for("nodejs.util.inspect.custom")]=a}catch{t.prototype.inspect=a}else t.prototype.inspect=a;function a(){return(this.red?""}var g=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],b=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],u=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];t.prototype.toString=function(x,A){x=x||10,A=A|0||1;var N;if(x===16||x==="hex"){N="";for(var L=0,z=0,R=0;R>>24-L&16777215,L+=2,L>=26&&(L-=26,R--),z!==0||R!==this.length-1?N=g[6-C.length]+C+N:N=C+N}for(z!==0&&(N=z.toString(16)+N);N.length%A!==0;)N="0"+N;return this.negative!==0&&(N="-"+N),N}if(x===(x|0)&&x>=2&&x<=36){var O=b[x],X=u[x];N="";var ie=this.clone();for(ie.negative=0;!ie.isZero();){var he=ie.modrn(X).toString(x);ie=ie.idivn(X),ie.isZero()?N=he+N:N=g[O-he.length]+he+N}for(this.isZero()&&(N="0"+N);N.length%A!==0;)N="0"+N;return this.negative!==0&&(N="-"+N),N}h(!1,"Base should be between 2 and 36")},t.prototype.toNumber=function(){var x=this.words[0];return this.length===2?x+=this.words[1]*67108864:this.length===3&&this.words[2]===1?x+=4503599627370496+this.words[1]*67108864:this.length>2&&h(!1,"Number can only safely store up to 53 bits"),this.negative!==0?-x:x},t.prototype.toJSON=function(){return this.toString(16,2)},i&&(t.prototype.toBuffer=function(x,A){return this.toArrayLike(i,x,A)}),t.prototype.toArray=function(x,A){return this.toArrayLike(Array,x,A)};var w=function(x,A){return x.allocUnsafe?x.allocUnsafe(A):new x(A)};t.prototype.toArrayLike=function(x,A,N){this._strip();var L=this.byteLength(),z=N||Math.max(1,L);h(L<=z,"byte array longer than desired length"),h(z>0,"Requested array length <= 0");var R=w(x,z),k=A==="le"?"LE":"BE";return this["_toArrayLike"+k](R,L),R},t.prototype._toArrayLikeLE=function(x,A){for(var N=0,L=0,z=0,R=0;z>8&255),N>16&255),R===6?(N>24&255),L=0,R=0):(L=k>>>24,R+=2)}if(N=0&&(x[N--]=k>>8&255),N>=0&&(x[N--]=k>>16&255),R===6?(N>=0&&(x[N--]=k>>24&255),L=0,R=0):(L=k>>>24,R+=2)}if(N>=0)for(x[N--]=L;N>=0;)x[N--]=0},Math.clz32?t.prototype._countBits=function(x){return 32-Math.clz32(x)}:t.prototype._countBits=function(x){var A=x,N=0;return A>=4096&&(N+=13,A>>>=13),A>=64&&(N+=7,A>>>=7),A>=8&&(N+=4,A>>>=4),A>=2&&(N+=2,A>>>=2),N+A},t.prototype._zeroBits=function(x){if(x===0)return 26;var A=x,N=0;return A&8191||(N+=13,A>>>=13),A&127||(N+=7,A>>>=7),A&15||(N+=4,A>>>=4),A&3||(N+=2,A>>>=2),A&1||N++,N},t.prototype.bitLength=function(){var x=this.words[this.length-1],A=this._countBits(x);return(this.length-1)*26+A};function y(T){for(var x=new Array(T.bitLength()),A=0;A>>L&1}return x}t.prototype.zeroBits=function(){if(this.isZero())return 0;for(var x=0,A=0;Ax.length?this.clone().ior(x):x.clone().ior(this)},t.prototype.uor=function(x){return this.length>x.length?this.clone().iuor(x):x.clone().iuor(this)},t.prototype.iuand=function(x){var A;this.length>x.length?A=x:A=this;for(var N=0;Nx.length?this.clone().iand(x):x.clone().iand(this)},t.prototype.uand=function(x){return this.length>x.length?this.clone().iuand(x):x.clone().iuand(this)},t.prototype.iuxor=function(x){var A,N;this.length>x.length?(A=this,N=x):(A=x,N=this);for(var L=0;Lx.length?this.clone().ixor(x):x.clone().ixor(this)},t.prototype.uxor=function(x){return this.length>x.length?this.clone().iuxor(x):x.clone().iuxor(this)},t.prototype.inotn=function(x){h(typeof x=="number"&&x>=0);var A=Math.ceil(x/26)|0,N=x%26;this._expand(A),N>0&&A--;for(var L=0;L0&&(this.words[L]=~this.words[L]&67108863>>26-N),this._strip()},t.prototype.notn=function(x){return this.clone().inotn(x)},t.prototype.setn=function(x,A){h(typeof x=="number"&&x>=0);var N=x/26|0,L=x%26;return this._expand(N+1),A?this.words[N]=this.words[N]|1<x.length?(N=this,L=x):(N=x,L=this);for(var z=0,R=0;R>>26;for(;z!==0&&R>>26;if(this.length=N.length,z!==0)this.words[this.length]=z,this.length++;else if(N!==this)for(;Rx.length?this.clone().iadd(x):x.clone().iadd(this)},t.prototype.isub=function(x){if(x.negative!==0){x.negative=0;var A=this.iadd(x);return x.negative=1,A._normSign()}else if(this.negative!==0)return this.negative=0,this.iadd(x),this.negative=1,this._normSign();var N=this.cmp(x);if(N===0)return this.negative=0,this.length=1,this.words[0]=0,this;var L,z;N>0?(L=this,z=x):(L=x,z=this);for(var R=0,k=0;k>26,this.words[k]=A&67108863;for(;R!==0&&k>26,this.words[k]=A&67108863;if(R===0&&k>>26,ie=C&67108863,he=Math.min(O,x.length-1),ue=Math.max(0,O-T.length+1);ue<=he;ue++){var ke=O-ue|0;L=T.words[ke]|0,z=x.words[ue]|0,R=L*z+ie,X+=R/67108864|0,ie=R&67108863}A.words[O]=ie|0,C=X|0}return C!==0?A.words[O]=C|0:A.length--,A._strip()}var E=function(x,A,N){var L=x.words,z=A.words,R=N.words,k=0,C,O,X,ie=L[0]|0,he=ie&8191,ue=ie>>>13,ke=L[1]|0,pe=ke&8191,ee=ke>>>13,Z=L[2]|0,q=Z&8191,de=Z>>>13,Me=L[3]|0,ae=Me&8191,ne=Me>>>13,Q=L[4]|0,H=Q&8191,Y=Q>>>13,le=L[5]|0,we=le&8191,U=le>>>13,ge=L[6]|0,Se=ge&8191,te=ge>>>13,se=L[7]|0,ve=se&8191,Ee=se>>>13,Ie=L[8]|0,Te=Ie&8191,Pe=Ie>>>13,He=L[9]|0,me=He&8191,Ce=He>>>13,Le=z[0]|0,ze=Le&8191,Ye=Le>>>13,ot=z[1]|0,pt=ot&8191,it=ot>>>13,rt=z[2]|0,Tt=rt&8191,Qe=rt>>>13,et=z[3]|0,At=et&8191,lt=et>>>13,jt=z[4]|0,Ot=jt&8191,ct=jt>>>13,Bt=z[5]|0,Ut=Bt&8191,yt=Bt>>>13,er=z[6]|0,Kt=er&8191,dt=er>>>13,Gt=z[7]|0,Mt=Gt&8191,wt=Gt>>>13,$t=z[8]|0,Qt=$t&8191,mt=$t>>>13,qt=z[9]|0,_t=qt&8191,Ct=qt>>>13;N.negative=x.negative^A.negative,N.length=19,C=Math.imul(he,ze),O=Math.imul(he,Ye),O=O+Math.imul(ue,ze)|0,X=Math.imul(ue,Ye);var be=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(be>>>26)|0,be&=67108863,C=Math.imul(pe,ze),O=Math.imul(pe,Ye),O=O+Math.imul(ee,ze)|0,X=Math.imul(ee,Ye),C=C+Math.imul(he,pt)|0,O=O+Math.imul(he,it)|0,O=O+Math.imul(ue,pt)|0,X=X+Math.imul(ue,it)|0;var De=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(De>>>26)|0,De&=67108863,C=Math.imul(q,ze),O=Math.imul(q,Ye),O=O+Math.imul(de,ze)|0,X=Math.imul(de,Ye),C=C+Math.imul(pe,pt)|0,O=O+Math.imul(pe,it)|0,O=O+Math.imul(ee,pt)|0,X=X+Math.imul(ee,it)|0,C=C+Math.imul(he,Tt)|0,O=O+Math.imul(he,Qe)|0,O=O+Math.imul(ue,Tt)|0,X=X+Math.imul(ue,Qe)|0;var Fe=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(Fe>>>26)|0,Fe&=67108863,C=Math.imul(ae,ze),O=Math.imul(ae,Ye),O=O+Math.imul(ne,ze)|0,X=Math.imul(ne,Ye),C=C+Math.imul(q,pt)|0,O=O+Math.imul(q,it)|0,O=O+Math.imul(de,pt)|0,X=X+Math.imul(de,it)|0,C=C+Math.imul(pe,Tt)|0,O=O+Math.imul(pe,Qe)|0,O=O+Math.imul(ee,Tt)|0,X=X+Math.imul(ee,Qe)|0,C=C+Math.imul(he,At)|0,O=O+Math.imul(he,lt)|0,O=O+Math.imul(ue,At)|0,X=X+Math.imul(ue,lt)|0;var Je=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(Je>>>26)|0,Je&=67108863,C=Math.imul(H,ze),O=Math.imul(H,Ye),O=O+Math.imul(Y,ze)|0,X=Math.imul(Y,Ye),C=C+Math.imul(ae,pt)|0,O=O+Math.imul(ae,it)|0,O=O+Math.imul(ne,pt)|0,X=X+Math.imul(ne,it)|0,C=C+Math.imul(q,Tt)|0,O=O+Math.imul(q,Qe)|0,O=O+Math.imul(de,Tt)|0,X=X+Math.imul(de,Qe)|0,C=C+Math.imul(pe,At)|0,O=O+Math.imul(pe,lt)|0,O=O+Math.imul(ee,At)|0,X=X+Math.imul(ee,lt)|0,C=C+Math.imul(he,Ot)|0,O=O+Math.imul(he,ct)|0,O=O+Math.imul(ue,Ot)|0,X=X+Math.imul(ue,ct)|0;var at=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(at>>>26)|0,at&=67108863,C=Math.imul(we,ze),O=Math.imul(we,Ye),O=O+Math.imul(U,ze)|0,X=Math.imul(U,Ye),C=C+Math.imul(H,pt)|0,O=O+Math.imul(H,it)|0,O=O+Math.imul(Y,pt)|0,X=X+Math.imul(Y,it)|0,C=C+Math.imul(ae,Tt)|0,O=O+Math.imul(ae,Qe)|0,O=O+Math.imul(ne,Tt)|0,X=X+Math.imul(ne,Qe)|0,C=C+Math.imul(q,At)|0,O=O+Math.imul(q,lt)|0,O=O+Math.imul(de,At)|0,X=X+Math.imul(de,lt)|0,C=C+Math.imul(pe,Ot)|0,O=O+Math.imul(pe,ct)|0,O=O+Math.imul(ee,Ot)|0,X=X+Math.imul(ee,ct)|0,C=C+Math.imul(he,Ut)|0,O=O+Math.imul(he,yt)|0,O=O+Math.imul(ue,Ut)|0,X=X+Math.imul(ue,yt)|0;var Rt=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(Rt>>>26)|0,Rt&=67108863,C=Math.imul(Se,ze),O=Math.imul(Se,Ye),O=O+Math.imul(te,ze)|0,X=Math.imul(te,Ye),C=C+Math.imul(we,pt)|0,O=O+Math.imul(we,it)|0,O=O+Math.imul(U,pt)|0,X=X+Math.imul(U,it)|0,C=C+Math.imul(H,Tt)|0,O=O+Math.imul(H,Qe)|0,O=O+Math.imul(Y,Tt)|0,X=X+Math.imul(Y,Qe)|0,C=C+Math.imul(ae,At)|0,O=O+Math.imul(ae,lt)|0,O=O+Math.imul(ne,At)|0,X=X+Math.imul(ne,lt)|0,C=C+Math.imul(q,Ot)|0,O=O+Math.imul(q,ct)|0,O=O+Math.imul(de,Ot)|0,X=X+Math.imul(de,ct)|0,C=C+Math.imul(pe,Ut)|0,O=O+Math.imul(pe,yt)|0,O=O+Math.imul(ee,Ut)|0,X=X+Math.imul(ee,yt)|0,C=C+Math.imul(he,Kt)|0,O=O+Math.imul(he,dt)|0,O=O+Math.imul(ue,Kt)|0,X=X+Math.imul(ue,dt)|0;var rr=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(rr>>>26)|0,rr&=67108863,C=Math.imul(ve,ze),O=Math.imul(ve,Ye),O=O+Math.imul(Ee,ze)|0,X=Math.imul(Ee,Ye),C=C+Math.imul(Se,pt)|0,O=O+Math.imul(Se,it)|0,O=O+Math.imul(te,pt)|0,X=X+Math.imul(te,it)|0,C=C+Math.imul(we,Tt)|0,O=O+Math.imul(we,Qe)|0,O=O+Math.imul(U,Tt)|0,X=X+Math.imul(U,Qe)|0,C=C+Math.imul(H,At)|0,O=O+Math.imul(H,lt)|0,O=O+Math.imul(Y,At)|0,X=X+Math.imul(Y,lt)|0,C=C+Math.imul(ae,Ot)|0,O=O+Math.imul(ae,ct)|0,O=O+Math.imul(ne,Ot)|0,X=X+Math.imul(ne,ct)|0,C=C+Math.imul(q,Ut)|0,O=O+Math.imul(q,yt)|0,O=O+Math.imul(de,Ut)|0,X=X+Math.imul(de,yt)|0,C=C+Math.imul(pe,Kt)|0,O=O+Math.imul(pe,dt)|0,O=O+Math.imul(ee,Kt)|0,X=X+Math.imul(ee,dt)|0,C=C+Math.imul(he,Mt)|0,O=O+Math.imul(he,wt)|0,O=O+Math.imul(ue,Mt)|0,X=X+Math.imul(ue,wt)|0;var vr=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(vr>>>26)|0,vr&=67108863,C=Math.imul(Te,ze),O=Math.imul(Te,Ye),O=O+Math.imul(Pe,ze)|0,X=Math.imul(Pe,Ye),C=C+Math.imul(ve,pt)|0,O=O+Math.imul(ve,it)|0,O=O+Math.imul(Ee,pt)|0,X=X+Math.imul(Ee,it)|0,C=C+Math.imul(Se,Tt)|0,O=O+Math.imul(Se,Qe)|0,O=O+Math.imul(te,Tt)|0,X=X+Math.imul(te,Qe)|0,C=C+Math.imul(we,At)|0,O=O+Math.imul(we,lt)|0,O=O+Math.imul(U,At)|0,X=X+Math.imul(U,lt)|0,C=C+Math.imul(H,Ot)|0,O=O+Math.imul(H,ct)|0,O=O+Math.imul(Y,Ot)|0,X=X+Math.imul(Y,ct)|0,C=C+Math.imul(ae,Ut)|0,O=O+Math.imul(ae,yt)|0,O=O+Math.imul(ne,Ut)|0,X=X+Math.imul(ne,yt)|0,C=C+Math.imul(q,Kt)|0,O=O+Math.imul(q,dt)|0,O=O+Math.imul(de,Kt)|0,X=X+Math.imul(de,dt)|0,C=C+Math.imul(pe,Mt)|0,O=O+Math.imul(pe,wt)|0,O=O+Math.imul(ee,Mt)|0,X=X+Math.imul(ee,wt)|0,C=C+Math.imul(he,Qt)|0,O=O+Math.imul(he,mt)|0,O=O+Math.imul(ue,Qt)|0,X=X+Math.imul(ue,mt)|0;var Br=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(Br>>>26)|0,Br&=67108863,C=Math.imul(me,ze),O=Math.imul(me,Ye),O=O+Math.imul(Ce,ze)|0,X=Math.imul(Ce,Ye),C=C+Math.imul(Te,pt)|0,O=O+Math.imul(Te,it)|0,O=O+Math.imul(Pe,pt)|0,X=X+Math.imul(Pe,it)|0,C=C+Math.imul(ve,Tt)|0,O=O+Math.imul(ve,Qe)|0,O=O+Math.imul(Ee,Tt)|0,X=X+Math.imul(Ee,Qe)|0,C=C+Math.imul(Se,At)|0,O=O+Math.imul(Se,lt)|0,O=O+Math.imul(te,At)|0,X=X+Math.imul(te,lt)|0,C=C+Math.imul(we,Ot)|0,O=O+Math.imul(we,ct)|0,O=O+Math.imul(U,Ot)|0,X=X+Math.imul(U,ct)|0,C=C+Math.imul(H,Ut)|0,O=O+Math.imul(H,yt)|0,O=O+Math.imul(Y,Ut)|0,X=X+Math.imul(Y,yt)|0,C=C+Math.imul(ae,Kt)|0,O=O+Math.imul(ae,dt)|0,O=O+Math.imul(ne,Kt)|0,X=X+Math.imul(ne,dt)|0,C=C+Math.imul(q,Mt)|0,O=O+Math.imul(q,wt)|0,O=O+Math.imul(de,Mt)|0,X=X+Math.imul(de,wt)|0,C=C+Math.imul(pe,Qt)|0,O=O+Math.imul(pe,mt)|0,O=O+Math.imul(ee,Qt)|0,X=X+Math.imul(ee,mt)|0,C=C+Math.imul(he,_t)|0,O=O+Math.imul(he,Ct)|0,O=O+Math.imul(ue,_t)|0,X=X+Math.imul(ue,Ct)|0;var br=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(br>>>26)|0,br&=67108863,C=Math.imul(me,pt),O=Math.imul(me,it),O=O+Math.imul(Ce,pt)|0,X=Math.imul(Ce,it),C=C+Math.imul(Te,Tt)|0,O=O+Math.imul(Te,Qe)|0,O=O+Math.imul(Pe,Tt)|0,X=X+Math.imul(Pe,Qe)|0,C=C+Math.imul(ve,At)|0,O=O+Math.imul(ve,lt)|0,O=O+Math.imul(Ee,At)|0,X=X+Math.imul(Ee,lt)|0,C=C+Math.imul(Se,Ot)|0,O=O+Math.imul(Se,ct)|0,O=O+Math.imul(te,Ot)|0,X=X+Math.imul(te,ct)|0,C=C+Math.imul(we,Ut)|0,O=O+Math.imul(we,yt)|0,O=O+Math.imul(U,Ut)|0,X=X+Math.imul(U,yt)|0,C=C+Math.imul(H,Kt)|0,O=O+Math.imul(H,dt)|0,O=O+Math.imul(Y,Kt)|0,X=X+Math.imul(Y,dt)|0,C=C+Math.imul(ae,Mt)|0,O=O+Math.imul(ae,wt)|0,O=O+Math.imul(ne,Mt)|0,X=X+Math.imul(ne,wt)|0,C=C+Math.imul(q,Qt)|0,O=O+Math.imul(q,mt)|0,O=O+Math.imul(de,Qt)|0,X=X+Math.imul(de,mt)|0,C=C+Math.imul(pe,_t)|0,O=O+Math.imul(pe,Ct)|0,O=O+Math.imul(ee,_t)|0,X=X+Math.imul(ee,Ct)|0;var lr=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(lr>>>26)|0,lr&=67108863,C=Math.imul(me,Tt),O=Math.imul(me,Qe),O=O+Math.imul(Ce,Tt)|0,X=Math.imul(Ce,Qe),C=C+Math.imul(Te,At)|0,O=O+Math.imul(Te,lt)|0,O=O+Math.imul(Pe,At)|0,X=X+Math.imul(Pe,lt)|0,C=C+Math.imul(ve,Ot)|0,O=O+Math.imul(ve,ct)|0,O=O+Math.imul(Ee,Ot)|0,X=X+Math.imul(Ee,ct)|0,C=C+Math.imul(Se,Ut)|0,O=O+Math.imul(Se,yt)|0,O=O+Math.imul(te,Ut)|0,X=X+Math.imul(te,yt)|0,C=C+Math.imul(we,Kt)|0,O=O+Math.imul(we,dt)|0,O=O+Math.imul(U,Kt)|0,X=X+Math.imul(U,dt)|0,C=C+Math.imul(H,Mt)|0,O=O+Math.imul(H,wt)|0,O=O+Math.imul(Y,Mt)|0,X=X+Math.imul(Y,wt)|0,C=C+Math.imul(ae,Qt)|0,O=O+Math.imul(ae,mt)|0,O=O+Math.imul(ne,Qt)|0,X=X+Math.imul(ne,mt)|0,C=C+Math.imul(q,_t)|0,O=O+Math.imul(q,Ct)|0,O=O+Math.imul(de,_t)|0,X=X+Math.imul(de,Ct)|0;var ri=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(ri>>>26)|0,ri&=67108863,C=Math.imul(me,At),O=Math.imul(me,lt),O=O+Math.imul(Ce,At)|0,X=Math.imul(Ce,lt),C=C+Math.imul(Te,Ot)|0,O=O+Math.imul(Te,ct)|0,O=O+Math.imul(Pe,Ot)|0,X=X+Math.imul(Pe,ct)|0,C=C+Math.imul(ve,Ut)|0,O=O+Math.imul(ve,yt)|0,O=O+Math.imul(Ee,Ut)|0,X=X+Math.imul(Ee,yt)|0,C=C+Math.imul(Se,Kt)|0,O=O+Math.imul(Se,dt)|0,O=O+Math.imul(te,Kt)|0,X=X+Math.imul(te,dt)|0,C=C+Math.imul(we,Mt)|0,O=O+Math.imul(we,wt)|0,O=O+Math.imul(U,Mt)|0,X=X+Math.imul(U,wt)|0,C=C+Math.imul(H,Qt)|0,O=O+Math.imul(H,mt)|0,O=O+Math.imul(Y,Qt)|0,X=X+Math.imul(Y,mt)|0,C=C+Math.imul(ae,_t)|0,O=O+Math.imul(ae,Ct)|0,O=O+Math.imul(ne,_t)|0,X=X+Math.imul(ne,Ct)|0;var ii=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(ii>>>26)|0,ii&=67108863,C=Math.imul(me,Ot),O=Math.imul(me,ct),O=O+Math.imul(Ce,Ot)|0,X=Math.imul(Ce,ct),C=C+Math.imul(Te,Ut)|0,O=O+Math.imul(Te,yt)|0,O=O+Math.imul(Pe,Ut)|0,X=X+Math.imul(Pe,yt)|0,C=C+Math.imul(ve,Kt)|0,O=O+Math.imul(ve,dt)|0,O=O+Math.imul(Ee,Kt)|0,X=X+Math.imul(Ee,dt)|0,C=C+Math.imul(Se,Mt)|0,O=O+Math.imul(Se,wt)|0,O=O+Math.imul(te,Mt)|0,X=X+Math.imul(te,wt)|0,C=C+Math.imul(we,Qt)|0,O=O+Math.imul(we,mt)|0,O=O+Math.imul(U,Qt)|0,X=X+Math.imul(U,mt)|0,C=C+Math.imul(H,_t)|0,O=O+Math.imul(H,Ct)|0,O=O+Math.imul(Y,_t)|0,X=X+Math.imul(Y,Ct)|0;var ar=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(ar>>>26)|0,ar&=67108863,C=Math.imul(me,Ut),O=Math.imul(me,yt),O=O+Math.imul(Ce,Ut)|0,X=Math.imul(Ce,yt),C=C+Math.imul(Te,Kt)|0,O=O+Math.imul(Te,dt)|0,O=O+Math.imul(Pe,Kt)|0,X=X+Math.imul(Pe,dt)|0,C=C+Math.imul(ve,Mt)|0,O=O+Math.imul(ve,wt)|0,O=O+Math.imul(Ee,Mt)|0,X=X+Math.imul(Ee,wt)|0,C=C+Math.imul(Se,Qt)|0,O=O+Math.imul(Se,mt)|0,O=O+Math.imul(te,Qt)|0,X=X+Math.imul(te,mt)|0,C=C+Math.imul(we,_t)|0,O=O+Math.imul(we,Ct)|0,O=O+Math.imul(U,_t)|0,X=X+Math.imul(U,Ct)|0;var Xr=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(Xr>>>26)|0,Xr&=67108863,C=Math.imul(me,Kt),O=Math.imul(me,dt),O=O+Math.imul(Ce,Kt)|0,X=Math.imul(Ce,dt),C=C+Math.imul(Te,Mt)|0,O=O+Math.imul(Te,wt)|0,O=O+Math.imul(Pe,Mt)|0,X=X+Math.imul(Pe,wt)|0,C=C+Math.imul(ve,Qt)|0,O=O+Math.imul(ve,mt)|0,O=O+Math.imul(Ee,Qt)|0,X=X+Math.imul(Ee,mt)|0,C=C+Math.imul(Se,_t)|0,O=O+Math.imul(Se,Ct)|0,O=O+Math.imul(te,_t)|0,X=X+Math.imul(te,Ct)|0;var Wr=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(Wr>>>26)|0,Wr&=67108863,C=Math.imul(me,Mt),O=Math.imul(me,wt),O=O+Math.imul(Ce,Mt)|0,X=Math.imul(Ce,wt),C=C+Math.imul(Te,Qt)|0,O=O+Math.imul(Te,mt)|0,O=O+Math.imul(Pe,Qt)|0,X=X+Math.imul(Pe,mt)|0,C=C+Math.imul(ve,_t)|0,O=O+Math.imul(ve,Ct)|0,O=O+Math.imul(Ee,_t)|0,X=X+Math.imul(Ee,Ct)|0;var Vr=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(Vr>>>26)|0,Vr&=67108863,C=Math.imul(me,Qt),O=Math.imul(me,mt),O=O+Math.imul(Ce,Qt)|0,X=Math.imul(Ce,mt),C=C+Math.imul(Te,_t)|0,O=O+Math.imul(Te,Ct)|0,O=O+Math.imul(Pe,_t)|0,X=X+Math.imul(Pe,Ct)|0;var Ei=(k+C|0)+((O&8191)<<13)|0;k=(X+(O>>>13)|0)+(Ei>>>26)|0,Ei&=67108863,C=Math.imul(me,_t),O=Math.imul(me,Ct),O=O+Math.imul(Ce,_t)|0,X=Math.imul(Ce,Ct);var Vi=(k+C|0)+((O&8191)<<13)|0;return k=(X+(O>>>13)|0)+(Vi>>>26)|0,Vi&=67108863,R[0]=be,R[1]=De,R[2]=Fe,R[3]=Je,R[4]=at,R[5]=Rt,R[6]=rr,R[7]=vr,R[8]=Br,R[9]=br,R[10]=lr,R[11]=ri,R[12]=ii,R[13]=ar,R[14]=Xr,R[15]=Wr,R[16]=Vr,R[17]=Ei,R[18]=Vi,k!==0&&(R[19]=k,N.length++),N};Math.imul||(E=S);function I(T,x,A){A.negative=x.negative^T.negative,A.length=T.length+x.length;for(var N=0,L=0,z=0;z>>26)|0,L+=R>>>26,R&=67108863}A.words[z]=k,N=R,R=L}return N!==0?A.words[z]=N:A.length--,A._strip()}function P(T,x,A){return I(T,x,A)}t.prototype.mulTo=function(x,A){var N,L=this.length+x.length;return this.length===10&&x.length===10?N=E(this,x,A):L<63?N=S(this,x,A):L<1024?N=I(this,x,A):N=P(this,x,A),N},t.prototype.mul=function(x){var A=new t(null);return A.words=new Array(this.length+x.length),this.mulTo(x,A)},t.prototype.mulf=function(x){var A=new t(null);return A.words=new Array(this.length+x.length),P(this,x,A)},t.prototype.imul=function(x){return this.clone().mulTo(x,this)},t.prototype.imuln=function(x){var A=x<0;A&&(x=-x),h(typeof x=="number"),h(x<67108864);for(var N=0,L=0;L>=26,N+=z/67108864|0,N+=R>>>26,this.words[L]=R&67108863}return N!==0&&(this.words[L]=N,this.length++),A?this.ineg():this},t.prototype.muln=function(x){return this.clone().imuln(x)},t.prototype.sqr=function(){return this.mul(this)},t.prototype.isqr=function(){return this.imul(this.clone())},t.prototype.pow=function(x){var A=y(x);if(A.length===0)return new t(1);for(var N=this,L=0;L=0);var A=x%26,N=(x-A)/26,L=67108863>>>26-A<<26-A,z;if(A!==0){var R=0;for(z=0;z>>26-A}R&&(this.words[z]=R,this.length++)}if(N!==0){for(z=this.length-1;z>=0;z--)this.words[z+N]=this.words[z];for(z=0;z=0);var L;A?L=(A-A%26)/26:L=0;var z=x%26,R=Math.min((x-z)/26,this.length),k=67108863^67108863>>>z<R)for(this.length-=R,O=0;O=0&&(X!==0||O>=L);O--){var ie=this.words[O]|0;this.words[O]=X<<26-z|ie>>>z,X=ie&k}return C&&X!==0&&(C.words[C.length++]=X),this.length===0&&(this.words[0]=0,this.length=1),this._strip()},t.prototype.ishrn=function(x,A,N){return h(this.negative===0),this.iushrn(x,A,N)},t.prototype.shln=function(x){return this.clone().ishln(x)},t.prototype.ushln=function(x){return this.clone().iushln(x)},t.prototype.shrn=function(x){return this.clone().ishrn(x)},t.prototype.ushrn=function(x){return this.clone().iushrn(x)},t.prototype.testn=function(x){h(typeof x=="number"&&x>=0);var A=x%26,N=(x-A)/26,L=1<=0);var A=x%26,N=(x-A)/26;if(h(this.negative===0,"imaskn works only with positive numbers"),this.length<=N)return this;if(A!==0&&N++,this.length=Math.min(N,this.length),A!==0){var L=67108863^67108863>>>A<=67108864;A++)this.words[A]-=67108864,A===this.length-1?this.words[A+1]=1:this.words[A+1]++;return this.length=Math.max(this.length,A+1),this},t.prototype.isubn=function(x){if(h(typeof x=="number"),h(x<67108864),x<0)return this.iaddn(-x);if(this.negative!==0)return this.negative=0,this.iaddn(x),this.negative=1,this;if(this.words[0]-=x,this.length===1&&this.words[0]<0)this.words[0]=-this.words[0],this.negative=1;else for(var A=0;A>26)-(C/67108864|0),this.words[z+N]=R&67108863}for(;z>26,this.words[z+N]=R&67108863;if(k===0)return this._strip();for(h(k===-1),k=0,z=0;z>26,this.words[z]=R&67108863;return this.negative=1,this._strip()},t.prototype._wordDiv=function(x,A){var N=this.length-x.length,L=this.clone(),z=x,R=z.words[z.length-1]|0,k=this._countBits(R);N=26-k,N!==0&&(z=z.ushln(N),L.iushln(N),R=z.words[z.length-1]|0);var C=L.length-z.length,O;if(A!=="mod"){O=new t(null),O.length=C+1,O.words=new Array(O.length);for(var X=0;X=0;he--){var ue=(L.words[z.length+he]|0)*67108864+(L.words[z.length+he-1]|0);for(ue=Math.min(ue/R|0,67108863),L._ishlnsubmul(z,ue,he);L.negative!==0;)ue--,L.negative=0,L._ishlnsubmul(z,1,he),L.isZero()||(L.negative^=1);O&&(O.words[he]=ue)}return O&&O._strip(),L._strip(),A!=="div"&&N!==0&&L.iushrn(N),{div:O||null,mod:L}},t.prototype.divmod=function(x,A,N){if(h(!x.isZero()),this.isZero())return{div:new t(0),mod:new t(0)};var L,z,R;return this.negative!==0&&x.negative===0?(R=this.neg().divmod(x,A),A!=="mod"&&(L=R.div.neg()),A!=="div"&&(z=R.mod.neg(),N&&z.negative!==0&&z.iadd(x)),{div:L,mod:z}):this.negative===0&&x.negative!==0?(R=this.divmod(x.neg(),A),A!=="mod"&&(L=R.div.neg()),{div:L,mod:R.mod}):this.negative&x.negative?(R=this.neg().divmod(x.neg(),A),A!=="div"&&(z=R.mod.neg(),N&&z.negative!==0&&z.isub(x)),{div:R.div,mod:z}):x.length>this.length||this.cmp(x)<0?{div:new t(0),mod:this}:x.length===1?A==="div"?{div:this.divn(x.words[0]),mod:null}:A==="mod"?{div:null,mod:new t(this.modrn(x.words[0]))}:{div:this.divn(x.words[0]),mod:new t(this.modrn(x.words[0]))}:this._wordDiv(x,A)},t.prototype.div=function(x){return this.divmod(x,"div",!1).div},t.prototype.mod=function(x){return this.divmod(x,"mod",!1).mod},t.prototype.umod=function(x){return this.divmod(x,"mod",!0).mod},t.prototype.divRound=function(x){var A=this.divmod(x);if(A.mod.isZero())return A.div;var N=A.div.negative!==0?A.mod.isub(x):A.mod,L=x.ushrn(1),z=x.andln(1),R=N.cmp(L);return R<0||z===1&&R===0?A.div:A.div.negative!==0?A.div.isubn(1):A.div.iaddn(1)},t.prototype.modrn=function(x){var A=x<0;A&&(x=-x),h(x<=67108863);for(var N=(1<<26)%x,L=0,z=this.length-1;z>=0;z--)L=(N*L+(this.words[z]|0))%x;return A?-L:L},t.prototype.modn=function(x){return this.modrn(x)},t.prototype.idivn=function(x){var A=x<0;A&&(x=-x),h(x<=67108863);for(var N=0,L=this.length-1;L>=0;L--){var z=(this.words[L]|0)+N*67108864;this.words[L]=z/x|0,N=z%x}return this._strip(),A?this.ineg():this},t.prototype.divn=function(x){return this.clone().idivn(x)},t.prototype.egcd=function(x){h(x.negative===0),h(!x.isZero());var A=this,N=x.clone();A.negative!==0?A=A.umod(x):A=A.clone();for(var L=new t(1),z=new t(0),R=new t(0),k=new t(1),C=0;A.isEven()&&N.isEven();)A.iushrn(1),N.iushrn(1),++C;for(var O=N.clone(),X=A.clone();!A.isZero();){for(var ie=0,he=1;!(A.words[0]&he)&&ie<26;++ie,he<<=1);if(ie>0)for(A.iushrn(ie);ie-- >0;)(L.isOdd()||z.isOdd())&&(L.iadd(O),z.isub(X)),L.iushrn(1),z.iushrn(1);for(var ue=0,ke=1;!(N.words[0]&ke)&&ue<26;++ue,ke<<=1);if(ue>0)for(N.iushrn(ue);ue-- >0;)(R.isOdd()||k.isOdd())&&(R.iadd(O),k.isub(X)),R.iushrn(1),k.iushrn(1);A.cmp(N)>=0?(A.isub(N),L.isub(R),z.isub(k)):(N.isub(A),R.isub(L),k.isub(z))}return{a:R,b:k,gcd:N.iushln(C)}},t.prototype._invmp=function(x){h(x.negative===0),h(!x.isZero());var A=this,N=x.clone();A.negative!==0?A=A.umod(x):A=A.clone();for(var L=new t(1),z=new t(0),R=N.clone();A.cmpn(1)>0&&N.cmpn(1)>0;){for(var k=0,C=1;!(A.words[0]&C)&&k<26;++k,C<<=1);if(k>0)for(A.iushrn(k);k-- >0;)L.isOdd()&&L.iadd(R),L.iushrn(1);for(var O=0,X=1;!(N.words[0]&X)&&O<26;++O,X<<=1);if(O>0)for(N.iushrn(O);O-- >0;)z.isOdd()&&z.iadd(R),z.iushrn(1);A.cmp(N)>=0?(A.isub(N),L.isub(z)):(N.isub(A),z.isub(L))}var ie;return A.cmpn(1)===0?ie=L:ie=z,ie.cmpn(0)<0&&ie.iadd(x),ie},t.prototype.gcd=function(x){if(this.isZero())return x.abs();if(x.isZero())return this.abs();var A=this.clone(),N=x.clone();A.negative=0,N.negative=0;for(var L=0;A.isEven()&&N.isEven();L++)A.iushrn(1),N.iushrn(1);do{for(;A.isEven();)A.iushrn(1);for(;N.isEven();)N.iushrn(1);var z=A.cmp(N);if(z<0){var R=A;A=N,N=R}else if(z===0||N.cmpn(1)===0)break;A.isub(N)}while(!0);return N.iushln(L)},t.prototype.invm=function(x){return this.egcd(x).a.umod(x)},t.prototype.isEven=function(){return(this.words[0]&1)===0},t.prototype.isOdd=function(){return(this.words[0]&1)===1},t.prototype.andln=function(x){return this.words[0]&x},t.prototype.bincn=function(x){h(typeof x=="number");var A=x%26,N=(x-A)/26,L=1<>>26,k&=67108863,this.words[R]=k}return z!==0&&(this.words[R]=z,this.length++),this},t.prototype.isZero=function(){return this.length===1&&this.words[0]===0},t.prototype.cmpn=function(x){var A=x<0;if(this.negative!==0&&!A)return-1;if(this.negative===0&&A)return 1;this._strip();var N;if(this.length>1)N=1;else{A&&(x=-x),h(x<=67108863,"Number is too big");var L=this.words[0]|0;N=L===x?0:Lx.length)return 1;if(this.length=0;N--){var L=this.words[N]|0,z=x.words[N]|0;if(L!==z){Lz&&(A=1);break}}return A},t.prototype.gtn=function(x){return this.cmpn(x)===1},t.prototype.gt=function(x){return this.cmp(x)===1},t.prototype.gten=function(x){return this.cmpn(x)>=0},t.prototype.gte=function(x){return this.cmp(x)>=0},t.prototype.ltn=function(x){return this.cmpn(x)===-1},t.prototype.lt=function(x){return this.cmp(x)===-1},t.prototype.lten=function(x){return this.cmpn(x)<=0},t.prototype.lte=function(x){return this.cmp(x)<=0},t.prototype.eqn=function(x){return this.cmpn(x)===0},t.prototype.eq=function(x){return this.cmp(x)===0},t.red=function(x){return new $(x)},t.prototype.toRed=function(x){return h(!this.red,"Already a number in reduction context"),h(this.negative===0,"red works only with positives"),x.convertTo(this)._forceRed(x)},t.prototype.fromRed=function(){return h(this.red,"fromRed works only with numbers in reduction context"),this.red.convertFrom(this)},t.prototype._forceRed=function(x){return this.red=x,this},t.prototype.forceRed=function(x){return h(!this.red,"Already a number in reduction context"),this._forceRed(x)},t.prototype.redAdd=function(x){return h(this.red,"redAdd works only with red numbers"),this.red.add(this,x)},t.prototype.redIAdd=function(x){return h(this.red,"redIAdd works only with red numbers"),this.red.iadd(this,x)},t.prototype.redSub=function(x){return h(this.red,"redSub works only with red numbers"),this.red.sub(this,x)},t.prototype.redISub=function(x){return h(this.red,"redISub works only with red numbers"),this.red.isub(this,x)},t.prototype.redShl=function(x){return h(this.red,"redShl works only with red numbers"),this.red.shl(this,x)},t.prototype.redMul=function(x){return h(this.red,"redMul works only with red numbers"),this.red._verify2(this,x),this.red.mul(this,x)},t.prototype.redIMul=function(x){return h(this.red,"redMul works only with red numbers"),this.red._verify2(this,x),this.red.imul(this,x)},t.prototype.redSqr=function(){return h(this.red,"redSqr works only with red numbers"),this.red._verify1(this),this.red.sqr(this)},t.prototype.redISqr=function(){return h(this.red,"redISqr works only with red numbers"),this.red._verify1(this),this.red.isqr(this)},t.prototype.redSqrt=function(){return h(this.red,"redSqrt works only with red numbers"),this.red._verify1(this),this.red.sqrt(this)},t.prototype.redInvm=function(){return h(this.red,"redInvm works only with red numbers"),this.red._verify1(this),this.red.invm(this)},t.prototype.redNeg=function(){return h(this.red,"redNeg works only with red numbers"),this.red._verify1(this),this.red.neg(this)},t.prototype.redPow=function(x){return h(this.red&&!x.red,"redPow(normalNum)"),this.red._verify1(this),this.red.pow(this,x)};var F={k256:null,p224:null,p192:null,p25519:null};function j(T,x){this.name=T,this.p=new t(x,16),this.n=this.p.bitLength(),this.k=new t(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}j.prototype._tmp=function(){var x=new t(null);return x.words=new Array(Math.ceil(this.n/13)),x},j.prototype.ireduce=function(x){var A=x,N;do this.split(A,this.tmp),A=this.imulK(A),A=A.iadd(this.tmp),N=A.bitLength();while(N>this.n);var L=N0?A.isub(this.p):A.strip!==void 0?A.strip():A._strip(),A},j.prototype.split=function(x,A){x.iushrn(this.n,0,A)},j.prototype.imulK=function(x){return x.imul(this.k)};function W(){j.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}s(W,j),W.prototype.split=function(x,A){for(var N=4194303,L=Math.min(x.length,9),z=0;z>>22,R=k}R>>>=22,x.words[z-10]=R,R===0&&x.length>10?x.length-=10:x.length-=9},W.prototype.imulK=function(x){x.words[x.length]=0,x.words[x.length+1]=0,x.length+=2;for(var A=0,N=0;N>>=26,x.words[N]=z,A=L}return A!==0&&(x.words[x.length++]=A),x},t._prime=function(x){if(F[x])return F[x];var A;if(x==="k256")A=new W;else if(x==="p224")A=new G;else if(x==="p192")A=new V;else if(x==="p25519")A=new J;else throw new Error("Unknown prime "+x);return F[x]=A,A};function $(T){if(typeof T=="string"){var x=t._prime(T);this.m=x.p,this.prime=x}else h(T.gtn(1),"modulus must be greater than 1"),this.m=T,this.prime=null}$.prototype._verify1=function(x){h(x.negative===0,"red works only with positives"),h(x.red,"red works only with red numbers")},$.prototype._verify2=function(x,A){h((x.negative|A.negative)===0,"red works only with positives"),h(x.red&&x.red===A.red,"red works only with red numbers")},$.prototype.imod=function(x){return this.prime?this.prime.ireduce(x)._forceRed(this):(f(x,x.umod(this.m)._forceRed(this)),x)},$.prototype.neg=function(x){return x.isZero()?x.clone():this.m.sub(x)._forceRed(this)},$.prototype.add=function(x,A){this._verify2(x,A);var N=x.add(A);return N.cmp(this.m)>=0&&N.isub(this.m),N._forceRed(this)},$.prototype.iadd=function(x,A){this._verify2(x,A);var N=x.iadd(A);return N.cmp(this.m)>=0&&N.isub(this.m),N},$.prototype.sub=function(x,A){this._verify2(x,A);var N=x.sub(A);return N.cmpn(0)<0&&N.iadd(this.m),N._forceRed(this)},$.prototype.isub=function(x,A){this._verify2(x,A);var N=x.isub(A);return N.cmpn(0)<0&&N.iadd(this.m),N},$.prototype.shl=function(x,A){return this._verify1(x),this.imod(x.ushln(A))},$.prototype.imul=function(x,A){return this._verify2(x,A),this.imod(x.imul(A))},$.prototype.mul=function(x,A){return this._verify2(x,A),this.imod(x.mul(A))},$.prototype.isqr=function(x){return this.imul(x,x.clone())},$.prototype.sqr=function(x){return this.mul(x,x)},$.prototype.sqrt=function(x){if(x.isZero())return x.clone();var A=this.m.andln(3);if(h(A%2===1),A===3){var N=this.m.add(new t(1)).iushrn(2);return this.pow(x,N)}for(var L=this.m.subn(1),z=0;!L.isZero()&&L.andln(1)===0;)z++,L.iushrn(1);h(!L.isZero());var R=new t(1).toRed(this),k=R.redNeg(),C=this.m.subn(1).iushrn(1),O=this.m.bitLength();for(O=new t(2*O*O).toRed(this);this.pow(O,C).cmp(k)!==0;)O.redIAdd(k);for(var X=this.pow(O,L),ie=this.pow(x,L.addn(1).iushrn(1)),he=this.pow(x,L),ue=z;he.cmp(R)!==0;){for(var ke=he,pe=0;ke.cmp(R)!==0;pe++)ke=ke.redSqr();h(pe=0;z--){for(var X=A.words[z],ie=O-1;ie>=0;ie--){var he=X>>ie&1;if(R!==L[0]&&(R=this.sqr(R)),he===0&&k===0){C=0;continue}k<<=1,k|=he,C++,!(C!==N&&(z!==0||ie!==0))&&(R=this.mul(R,L[k]),C=0,k=0)}O=26}return R},$.prototype.convertTo=function(x){var A=x.umod(this.m);return A===x?A.clone():A},$.prototype.convertFrom=function(x){var A=x.clone();return A.red=null,A},t.mont=function(x){return new M(x)};function M(T){$.call(this,T),this.shift=this.m.bitLength(),this.shift%26!==0&&(this.shift+=26-this.shift%26),this.r=new t(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}s(M,$),M.prototype.convertTo=function(x){return this.imod(x.ushln(this.shift))},M.prototype.convertFrom=function(x){var A=this.imod(x.mul(this.rinv));return A.red=null,A},M.prototype.imul=function(x,A){if(x.isZero()||A.isZero())return x.words[0]=0,x.length=1,x;var N=x.imul(A),L=N.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),z=N.isub(L).iushrn(this.shift),R=z;return z.cmp(this.m)>=0?R=z.isub(this.m):z.cmpn(0)<0&&(R=z.iadd(this.m)),R._forceRed(this)},M.prototype.mul=function(x,A){if(x.isZero()||A.isZero())return new t(0)._forceRed(this);var N=x.mul(A),L=N.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),z=N.isub(L).iushrn(this.shift),R=z;return z.cmp(this.m)>=0?R=z.isub(this.m):z.cmpn(0)<0&&(R=z.iadd(this.m)),R._forceRed(this)},M.prototype.invm=function(x){var A=this.imod(x._invmp(this.m).mul(this.r2));return A._forceRed(this)}})(typeof d>"u"||d,void 0)},{buffer:188}],187:[function(e,d,m){var l;d.exports=function(t){return l||(l=new c(null)),l.generate(t)};function c(s){this.rand=s}if(d.exports.Rand=c,c.prototype.generate=function(t){return this._rand(t)},c.prototype._rand=function(t){if(this.rand.getBytes)return this.rand.getBytes(t);for(var i=new Uint8Array(t),r=0;r>>24]^u[E>>>16&255]^w[I>>>8&255]^y[P&255]^o[V++],j=b[E>>>24]^u[I>>>16&255]^w[P>>>8&255]^y[S&255]^o[V++],W=b[I>>>24]^u[P>>>16&255]^w[S>>>8&255]^y[E&255]^o[V++],G=b[P>>>24]^u[S>>>16&255]^w[E>>>8&255]^y[I&255]^o[V++],S=F,E=j,I=W,P=G;return F=(a[S>>>24]<<24|a[E>>>16&255]<<16|a[I>>>8&255]<<8|a[P&255])^o[V++],j=(a[E>>>24]<<24|a[I>>>16&255]<<16|a[P>>>8&255]<<8|a[S&255])^o[V++],W=(a[I>>>24]<<24|a[P>>>16&255]<<16|a[S>>>8&255]<<8|a[E&255])^o[V++],G=(a[P>>>24]<<24|a[S>>>16&255]<<16|a[E>>>8&255]<<8|a[I&255])^o[V++],F=F>>>0,j=j>>>0,W=W>>>0,G=G>>>0,[F,j,W,G]}var t=[0,1,2,4,8,16,32,64,128,27,54],i=function(){for(var n=new Array(256),o=0;o<256;o++)o<128?n[o]=o<<1:n[o]=o<<1^283;for(var f=[],a=[],g=[[],[],[],[]],b=[[],[],[],[]],u=0,w=0,y=0;y<256;++y){var S=w^w<<1^w<<2^w<<3^w<<4;S=S>>>8^S&255^99,f[u]=S,a[S]=u;var E=n[u],I=n[E],P=n[I],F=n[S]*257^S*16843008;g[0][u]=F<<24|F>>>8,g[1][u]=F<<16|F>>>16,g[2][u]=F<<8|F>>>24,g[3][u]=F,F=P*16843009^I*65537^E*257^u*16843008,b[0][S]=F<<24|F>>>8,b[1][S]=F<<16|F>>>16,b[2][S]=F<<8|F>>>24,b[3][S]=F,u===0?u=w=1:(u=E^n[n[n[P^E]]],w^=n[n[w]])}return{SBOX:f,INV_SBOX:a,SUB_MIX:g,INV_SUB_MIX:b}}();function r(n){this._key=c(n),this._reset()}r.blockSize=4*4,r.keySize=256/8,r.prototype.blockSize=r.blockSize,r.prototype.keySize=r.keySize,r.prototype._reset=function(){for(var n=this._key,o=n.length,f=o+6,a=(f+1)*4,g=[],b=0;b>>24,u=i.SBOX[u>>>24]<<24|i.SBOX[u>>>16&255]<<16|i.SBOX[u>>>8&255]<<8|i.SBOX[u&255],u^=t[b/o|0]<<24):o>6&&b%o===4&&(u=i.SBOX[u>>>24]<<24|i.SBOX[u>>>16&255]<<16|i.SBOX[u>>>8&255]<<8|i.SBOX[u&255]),g[b]=g[b-o]^u}for(var w=[],y=0;y>>24]]^i.INV_SUB_MIX[1][i.SBOX[E>>>16&255]]^i.INV_SUB_MIX[2][i.SBOX[E>>>8&255]]^i.INV_SUB_MIX[3][i.SBOX[E&255]]}this._nRounds=f,this._keySchedule=g,this._invKeySchedule=w},r.prototype.encryptBlockRaw=function(n){return n=c(n),s(n,this._keySchedule,i.SUB_MIX,i.SBOX,this._nRounds)},r.prototype.encryptBlock=function(n){var o=this.encryptBlockRaw(n),f=l.allocUnsafe(16);return f.writeUInt32BE(o[0],0),f.writeUInt32BE(o[1],4),f.writeUInt32BE(o[2],8),f.writeUInt32BE(o[3],12),f},r.prototype.decryptBlock=function(n){n=c(n);var o=n[1];n[1]=n[3],n[3]=o;var f=s(n,this._invKeySchedule,i.INV_SUB_MIX,i.INV_SBOX,this._nRounds),a=l.allocUnsafe(16);return a.writeUInt32BE(f[0],0),a.writeUInt32BE(f[3],4),a.writeUInt32BE(f[2],8),a.writeUInt32BE(f[1],12),a},r.prototype.scrub=function(){h(this._keySchedule),h(this._invKeySchedule),h(this._key)},d.exports.AES=r},{"safe-buffer":494}],190:[function(e,d,m){var l=e("./aes"),c=e("safe-buffer").Buffer,h=e("cipher-base"),s=e("inherits"),t=e("./ghash"),i=e("buffer-xor"),r=e("./incr32");function n(a,g){var b=0;a.length!==g.length&&b++;for(var u=Math.min(a.length,g.length),w=0;w16)return w=this.cache.slice(0,16),this.cache=this.cache.slice(16),w}else if(this.cache.length>=16)return w=this.cache.slice(0,16),this.cache=this.cache.slice(16),w;return null},f.prototype.flush=function(){if(this.cache.length)return this.cache};function a(u){var w=u[15];if(w<1||w>16)throw new Error("unable to decrypt data");for(var y=-1;++y15){var u=this.cache.slice(0,16);return this.cache=this.cache.slice(16),u}return null},a.prototype.flush=function(){for(var u=16-this.cache.length,w=h.allocUnsafe(u),y=-1;++y>>0,0),r.writeUInt32BE(i[1]>>>0,4),r.writeUInt32BE(i[2]>>>0,8),r.writeUInt32BE(i[3]>>>0,12),r}function t(i){this.h=i,this.state=l.alloc(16,0),this.cache=l.allocUnsafe(0)}t.prototype.ghash=function(i){for(var r=-1;++r0;n--)i[n]=i[n]>>>1|(i[n-1]&1)<<31;i[0]=i[0]>>>1,f&&(i[0]=i[0]^225<<24)}this.state=s(r)},t.prototype.update=function(i){this.cache=l.concat([this.cache,i]);for(var r;this.cache.length>=16;)r=this.cache.slice(0,16),this.cache=this.cache.slice(16),this.ghash(r)},t.prototype.final=function(i,r){return this.cache.length&&this.ghash(l.concat([this.cache,c],16)),this.ghash(s([0,i,0,r])),this.state},d.exports=t},{"safe-buffer":494}],195:[function(e,d,m){function l(c){for(var h=c.length,s;h--;)if(s=c.readUInt8(h),s===255)c.writeUInt8(0,h);else{s++,c.writeUInt8(s,h);break}}d.exports=l},{}],196:[function(e,d,m){var l=e("buffer-xor");m.encrypt=function(c,h){var s=l(h,c._prev);return c._prev=c._cipher.encryptBlock(s),c._prev},m.decrypt=function(c,h){var s=c._prev;c._prev=h;var t=c._cipher.decryptBlock(h);return l(t,s)}},{"buffer-xor":219}],197:[function(e,d,m){var l=e("safe-buffer").Buffer,c=e("buffer-xor");function h(s,t,i){var r=t.length,n=c(t,s._cache);return s._cache=s._cache.slice(r),s._prev=l.concat([s._prev,i?t:n]),n}m.encrypt=function(s,t,i){for(var r=l.allocUnsafe(0),n;t.length;)if(s._cache.length===0&&(s._cache=s._cipher.encryptBlock(s._prev),s._prev=l.allocUnsafe(0)),s._cache.length<=t.length)n=s._cache.length,r=l.concat([r,h(s,t.slice(0,n),i)]),t=t.slice(n);else{r=l.concat([r,h(s,t,i)]);break}return r}},{"buffer-xor":219,"safe-buffer":494}],198:[function(e,d,m){var l=e("safe-buffer").Buffer;function c(s,t,i){for(var r,n=-1,o=8,f=0,a,g;++n>n%8,s._prev=h(s._prev,i?a:g);return f}function h(s,t){var i=s.length,r=-1,n=l.allocUnsafe(s.length);for(s=l.concat([s,l.from([t])]);++r>7;return n}m.encrypt=function(s,t,i){for(var r=t.length,n=l.allocUnsafe(r),o=-1;++o=0||!o.umod(r.prime1)||!o.umod(r.prime2));return o}function i(r,n){var o=s(n),f=n.modulus.byteLength(),a=new c(r).mul(o.blinder).umod(n.modulus),g=a.toRed(c.mont(n.prime1)),b=a.toRed(c.mont(n.prime2)),u=n.coefficient,w=n.prime1,y=n.prime2,S=g.redPow(n.exponent1).fromRed(),E=b.redPow(n.exponent2).fromRed(),I=S.isub(E).imul(u).umod(w).imul(y);return E.iadd(I).imul(o.unblinder).umod(n.modulus).toArrayLike(l,"be",f)}i.getr=t,d.exports=i}).call(this)}).call(this,e("buffer").Buffer)},{"bn.js":186,buffer:220,randombytes:475}],210:[function(e,d,m){d.exports=e("./browser/algorithms.json")},{"./browser/algorithms.json":211}],211:[function(e,d,m){d.exports={sha224WithRSAEncryption:{sign:"rsa",hash:"sha224",id:"302d300d06096086480165030402040500041c"},"RSA-SHA224":{sign:"ecdsa/rsa",hash:"sha224",id:"302d300d06096086480165030402040500041c"},sha256WithRSAEncryption:{sign:"rsa",hash:"sha256",id:"3031300d060960864801650304020105000420"},"RSA-SHA256":{sign:"ecdsa/rsa",hash:"sha256",id:"3031300d060960864801650304020105000420"},sha384WithRSAEncryption:{sign:"rsa",hash:"sha384",id:"3041300d060960864801650304020205000430"},"RSA-SHA384":{sign:"ecdsa/rsa",hash:"sha384",id:"3041300d060960864801650304020205000430"},sha512WithRSAEncryption:{sign:"rsa",hash:"sha512",id:"3051300d060960864801650304020305000440"},"RSA-SHA512":{sign:"ecdsa/rsa",hash:"sha512",id:"3051300d060960864801650304020305000440"},"RSA-SHA1":{sign:"rsa",hash:"sha1",id:"3021300906052b0e03021a05000414"},"ecdsa-with-SHA1":{sign:"ecdsa",hash:"sha1",id:""},sha256:{sign:"ecdsa",hash:"sha256",id:""},sha224:{sign:"ecdsa",hash:"sha224",id:""},sha384:{sign:"ecdsa",hash:"sha384",id:""},sha512:{sign:"ecdsa",hash:"sha512",id:""},"DSA-SHA":{sign:"dsa",hash:"sha1",id:""},"DSA-SHA1":{sign:"dsa",hash:"sha1",id:""},DSA:{sign:"dsa",hash:"sha1",id:""},"DSA-WITH-SHA224":{sign:"dsa",hash:"sha224",id:""},"DSA-SHA224":{sign:"dsa",hash:"sha224",id:""},"DSA-WITH-SHA256":{sign:"dsa",hash:"sha256",id:""},"DSA-SHA256":{sign:"dsa",hash:"sha256",id:""},"DSA-WITH-SHA384":{sign:"dsa",hash:"sha384",id:""},"DSA-SHA384":{sign:"dsa",hash:"sha384",id:""},"DSA-WITH-SHA512":{sign:"dsa",hash:"sha512",id:""},"DSA-SHA512":{sign:"dsa",hash:"sha512",id:""},"DSA-RIPEMD160":{sign:"dsa",hash:"rmd160",id:""},ripemd160WithRSA:{sign:"rsa",hash:"rmd160",id:"3021300906052b2403020105000414"},"RSA-RIPEMD160":{sign:"rsa",hash:"rmd160",id:"3021300906052b2403020105000414"},md5WithRSAEncryption:{sign:"rsa",hash:"md5",id:"3020300c06082a864886f70d020505000410"},"RSA-MD5":{sign:"rsa",hash:"md5",id:"3020300c06082a864886f70d020505000410"}}},{}],212:[function(e,d,m){d.exports={"1.3.132.0.10":"secp256k1","1.3.132.0.33":"p224","1.2.840.10045.3.1.1":"p192","1.2.840.10045.3.1.7":"p256","1.3.132.0.34":"p384","1.3.132.0.35":"p521"}},{}],213:[function(e,d,m){var l=e("safe-buffer").Buffer,c=e("create-hash"),h=e("readable-stream"),s=e("inherits"),t=e("./sign"),i=e("./verify"),r=e("./algorithms.json");Object.keys(r).forEach(function(g){r[g].id=l.from(r[g].id,"hex"),r[g.toLowerCase()]=r[g]});function n(g){h.Writable.call(this);var b=r[g];if(!b)throw new Error("Unknown message digest");this._hashType=b.hash,this._hash=c(b.hash),this._tag=b.id,this._signType=b.sign}s(n,h.Writable),n.prototype._write=function(b,u,w){this._hash.update(b),w()},n.prototype.update=function(b,u){return typeof b=="string"&&(b=l.from(b,u)),this._hash.update(b),this},n.prototype.sign=function(b,u){this.end();var w=this._hash.digest(),y=t(w,b,this._hashType,this._signType,this._tag);return u?y.toString(u):y};function o(g){h.Writable.call(this);var b=r[g];if(!b)throw new Error("Unknown message digest");this._hash=c(b.hash),this._tag=b.id,this._signType=b.sign}s(o,h.Writable),o.prototype._write=function(b,u,w){this._hash.update(b),w()},o.prototype.update=function(b,u){return typeof b=="string"&&(b=l.from(b,u)),this._hash.update(b),this},o.prototype.verify=function(b,u,w){typeof u=="string"&&(u=l.from(u,w)),this.end();var y=this._hash.digest();return i(u,y,b,this._signType,this._tag)};function f(g){return new n(g)}function a(g){return new o(g)}d.exports={Sign:f,Verify:a,createSign:f,createVerify:a}},{"./algorithms.json":211,"./sign":214,"./verify":215,"create-hash":386,inherits:440,"readable-stream":491,"safe-buffer":494}],214:[function(e,d,m){var l=e("safe-buffer").Buffer,c=e("create-hmac"),h=e("browserify-rsa"),s=e("elliptic").ec,t=e("bn.js"),i=e("parse-asn1"),r=e("./curves.json");function n(S,E,I,P,F){var j=i(E);if(j.curve){if(P!=="ecdsa"&&P!=="ecdsa/rsa")throw new Error("wrong private key type");return o(S,j)}else if(j.type==="dsa"){if(P!=="dsa")throw new Error("wrong private key type");return f(S,j,I)}else if(P!=="rsa"&&P!=="ecdsa/rsa")throw new Error("wrong private key type");S=l.concat([F,S]);for(var W=j.modulus.byteLength(),G=[0,1];S.length+G.length+10&&I.ishrn(P),I}function u(S,E){S=b(S,E),S=S.mod(E);var I=l.from(S.toArray());if(I.length=a)throw new Error("invalid sig")}d.exports=i},{"./curves.json":212,"bn.js":186,elliptic:405,"parse-asn1":459,"safe-buffer":494}],216:[function(e,d,m){},{}],217:[function(e,d,m){var l=e("buffer"),c=l.Buffer;function h(t,i){for(var r in t)i[r]=t[r]}c.from&&c.alloc&&c.allocUnsafe&&c.allocUnsafeSlow?d.exports=l:(h(l,m),m.Buffer=s);function s(t,i,r){return c(t,i,r)}h(c,s),s.from=function(t,i,r){if(typeof t=="number")throw new TypeError("Argument must not be a number");return c(t,i,r)},s.alloc=function(t,i,r){if(typeof t!="number")throw new TypeError("Argument must be a number");var n=c(t);return i!==void 0?typeof r=="string"?n.fill(i,r):n.fill(i):n.fill(0),n},s.allocUnsafe=function(t){if(typeof t!="number")throw new TypeError("Argument must be a number");return c(t)},s.allocUnsafeSlow=function(t){if(typeof t!="number")throw new TypeError("Argument must be a number");return l.SlowBuffer(t)}},{buffer:220}],218:[function(e,d,m){var l=e("safe-buffer").Buffer,c=l.isEncoding||function(E){switch(E=""+E,E&&E.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function h(E){if(!E)return"utf8";for(var I;;)switch(E){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return E;default:if(I)return;E=(""+E).toLowerCase(),I=!0}}function s(E){var I=h(E);if(typeof I!="string"&&(l.isEncoding===c||!c(E)))throw new Error("Unknown encoding: "+E);return I||E}m.StringDecoder=t;function t(E){this.encoding=s(E);var I;switch(this.encoding){case"utf16le":this.text=g,this.end=b,I=4;break;case"utf8":this.fillLast=o,I=4;break;case"base64":this.text=u,this.end=w,I=3;break;default:this.write=y,this.end=S;return}this.lastNeed=0,this.lastTotal=0,this.lastChar=l.allocUnsafe(I)}t.prototype.write=function(E){if(E.length===0)return"";var I,P;if(this.lastNeed){if(I=this.fillLast(E),I===void 0)return"";P=this.lastNeed,this.lastNeed=0}else P=0;return P>5===6?2:E>>4===14?3:E>>3===30?4:E>>6===2?-1:-2}function r(E,I,P){var F=I.length-1;if(F=0?(j>0&&(E.lastNeed=j-1),j):--F=0?(j>0&&(E.lastNeed=j-2),j):--F=0?(j>0&&(j===2?j=0:E.lastNeed=j-3),j):0))}function n(E,I,P){if((I[0]&192)!==128)return E.lastNeed=0,"�";if(E.lastNeed>1&&I.length>1){if((I[1]&192)!==128)return E.lastNeed=1,"�";if(E.lastNeed>2&&I.length>2&&(I[2]&192)!==128)return E.lastNeed=2,"�"}}function o(E){var I=this.lastTotal-this.lastNeed,P=n(this,E);if(P!==void 0)return P;if(this.lastNeed<=E.length)return E.copy(this.lastChar,I,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);E.copy(this.lastChar,I,0,E.length),this.lastNeed-=E.length}function f(E,I){var P=r(this,E,I);if(!this.lastNeed)return E.toString("utf8",I);this.lastTotal=P;var F=E.length-(P-this.lastNeed);return E.copy(this.lastChar,0,F),E.toString("utf8",I,F)}function a(E){var I=E&&E.length?this.write(E):"";return this.lastNeed?I+"�":I}function g(E,I){if((E.length-I)%2===0){var P=E.toString("utf16le",I);if(P){var F=P.charCodeAt(P.length-1);if(F>=55296&&F<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=E[E.length-2],this.lastChar[1]=E[E.length-1],P.slice(0,-1)}return P}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=E[E.length-1],E.toString("utf16le",I,E.length-1)}function b(E){var I=E&&E.length?this.write(E):"";if(this.lastNeed){var P=this.lastTotal-this.lastNeed;return I+this.lastChar.toString("utf16le",0,P)}return I}function u(E,I){var P=(E.length-I)%3;return P===0?E.toString("base64",I):(this.lastNeed=3-P,this.lastTotal=3,P===1?this.lastChar[0]=E[E.length-1]:(this.lastChar[0]=E[E.length-2],this.lastChar[1]=E[E.length-1]),E.toString("base64",I,E.length-P))}function w(E){var I=E&&E.length?this.write(E):"";return this.lastNeed?I+this.lastChar.toString("base64",0,3-this.lastNeed):I}function y(E){return E.toString(this.encoding)}function S(E){return E&&E.length?this.write(E):""}},{"safe-buffer":217}],219:[function(e,d,m){(function(l){(function(){d.exports=function(h,s){for(var t=Math.min(h.length,s.length),i=new l(t),r=0;rs)throw new RangeError('The value "'+Q+'" is invalid for option "size"');var H=new Uint8Array(Q);return H.__proto__=r.prototype,H}function r(Q,H,Y){if(typeof Q=="number"){if(typeof H=="string")throw new TypeError('The "string" argument must be of type string. Received type number');return a(Q)}return n(Q,H,Y)}typeof Symbol<"u"&&Symbol.species!=null&&r[Symbol.species]===r&&Object.defineProperty(r,Symbol.species,{value:null,configurable:!0,enumerable:!1,writable:!1}),r.poolSize=8192;function n(Q,H,Y){if(typeof Q=="string")return g(Q,H);if(ArrayBuffer.isView(Q))return b(Q);if(Q==null)throw TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof Q);if(ae(Q,ArrayBuffer)||Q&&ae(Q.buffer,ArrayBuffer))return u(Q,H,Y);if(typeof Q=="number")throw new TypeError('The "value" argument must not be of type number. Received type number');var le=Q.valueOf&&Q.valueOf();if(le!=null&&le!==Q)return r.from(le,H,Y);var we=w(Q);if(we)return we;if(typeof Symbol<"u"&&Symbol.toPrimitive!=null&&typeof Q[Symbol.toPrimitive]=="function")return r.from(Q[Symbol.toPrimitive]("string"),H,Y);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof Q)}r.from=function(Q,H,Y){return n(Q,H,Y)},r.prototype.__proto__=Uint8Array.prototype,r.__proto__=Uint8Array;function o(Q){if(typeof Q!="number")throw new TypeError('"size" argument must be of type number');if(Q<0)throw new RangeError('The value "'+Q+'" is invalid for option "size"')}function f(Q,H,Y){return o(Q),Q<=0?i(Q):H!==void 0?typeof Y=="string"?i(Q).fill(H,Y):i(Q).fill(H):i(Q)}r.alloc=function(Q,H,Y){return f(Q,H,Y)};function a(Q){return o(Q),i(Q<0?0:y(Q)|0)}r.allocUnsafe=function(Q){return a(Q)},r.allocUnsafeSlow=function(Q){return a(Q)};function g(Q,H){if((typeof H!="string"||H==="")&&(H="utf8"),!r.isEncoding(H))throw new TypeError("Unknown encoding: "+H);var Y=E(Q,H)|0,le=i(Y),we=le.write(Q,H);return we!==Y&&(le=le.slice(0,we)),le}function b(Q){for(var H=Q.length<0?0:y(Q.length)|0,Y=i(H),le=0;le=s)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+s.toString(16)+" bytes");return Q|0}function S(Q){return+Q!=Q&&(Q=0),r.alloc(+Q)}r.isBuffer=function(H){return H!=null&&H._isBuffer===!0&&H!==r.prototype},r.compare=function(H,Y){if(ae(H,Uint8Array)&&(H=r.from(H,H.offset,H.byteLength)),ae(Y,Uint8Array)&&(Y=r.from(Y,Y.offset,Y.byteLength)),!r.isBuffer(H)||!r.isBuffer(Y))throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');if(H===Y)return 0;for(var le=H.length,we=Y.length,U=0,ge=Math.min(le,we);U2&&arguments[2]===!0;if(!le&&Y===0)return 0;for(var we=!1;;)switch(H){case"ascii":case"latin1":case"binary":return Y;case"utf8":case"utf-8":return ee(Q).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Y*2;case"hex":return Y>>>1;case"base64":return de(Q).length;default:if(we)return le?-1:ee(Q).length;H=(""+H).toLowerCase(),we=!0}}r.byteLength=E;function I(Q,H,Y){var le=!1;if((H===void 0||H<0)&&(H=0),H>this.length||((Y===void 0||Y>this.length)&&(Y=this.length),Y<=0)||(Y>>>=0,H>>>=0,Y<=H))return"";for(Q||(Q="utf8");;)switch(Q){case"hex":return R(this,H,Y);case"utf8":case"utf-8":return x(this,H,Y);case"ascii":return L(this,H,Y);case"latin1":case"binary":return z(this,H,Y);case"base64":return T(this,H,Y);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return k(this,H,Y);default:if(le)throw new TypeError("Unknown encoding: "+Q);Q=(Q+"").toLowerCase(),le=!0}}r.prototype._isBuffer=!0;function P(Q,H,Y){var le=Q[H];Q[H]=Q[Y],Q[Y]=le}r.prototype.swap16=function(){var H=this.length;if(H%2!==0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var Y=0;YY&&(H+=" ... "),""},r.prototype.compare=function(H,Y,le,we,U){if(ae(H,Uint8Array)&&(H=r.from(H,H.offset,H.byteLength)),!r.isBuffer(H))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof H);if(Y===void 0&&(Y=0),le===void 0&&(le=H?H.length:0),we===void 0&&(we=0),U===void 0&&(U=this.length),Y<0||le>H.length||we<0||U>this.length)throw new RangeError("out of range index");if(we>=U&&Y>=le)return 0;if(we>=U)return-1;if(Y>=le)return 1;if(Y>>>=0,le>>>=0,we>>>=0,U>>>=0,this===H)return 0;for(var ge=U-we,Se=le-Y,te=Math.min(ge,Se),se=this.slice(we,U),ve=H.slice(Y,le),Ee=0;Ee2147483647?Y=2147483647:Y<-2147483648&&(Y=-2147483648),Y=+Y,ne(Y)&&(Y=we?0:Q.length-1),Y<0&&(Y=Q.length+Y),Y>=Q.length){if(we)return-1;Y=Q.length-1}else if(Y<0)if(we)Y=0;else return-1;if(typeof H=="string"&&(H=r.from(H,le)),r.isBuffer(H))return H.length===0?-1:j(Q,H,Y,le,we);if(typeof H=="number")return H=H&255,typeof Uint8Array.prototype.indexOf=="function"?we?Uint8Array.prototype.indexOf.call(Q,H,Y):Uint8Array.prototype.lastIndexOf.call(Q,H,Y):j(Q,[H],Y,le,we);throw new TypeError("val must be string, number or Buffer")}function j(Q,H,Y,le,we){var U=1,ge=Q.length,Se=H.length;if(le!==void 0&&(le=String(le).toLowerCase(),le==="ucs2"||le==="ucs-2"||le==="utf16le"||le==="utf-16le")){if(Q.length<2||H.length<2)return-1;U=2,ge/=2,Se/=2,Y/=2}function te(Te,Pe){return U===1?Te[Pe]:Te.readUInt16BE(Pe*U)}var se;if(we){var ve=-1;for(se=Y;sege&&(Y=ge-Se),se=Y;se>=0;se--){for(var Ee=!0,Ie=0;Iewe&&(le=we)):le=we;var U=H.length;le>U/2&&(le=U/2);for(var ge=0;ge>>0,isFinite(le)?(le=le>>>0,we===void 0&&(we="utf8")):(we=le,le=void 0);else throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");var U=this.length-Y;if((le===void 0||le>U)&&(le=U),H.length>0&&(le<0||Y<0)||Y>this.length)throw new RangeError("Attempt to write outside buffer bounds");we||(we="utf8");for(var ge=!1;;)switch(we){case"hex":return W(this,H,Y,le);case"utf8":case"utf-8":return G(this,H,Y,le);case"ascii":return V(this,H,Y,le);case"latin1":case"binary":return J(this,H,Y,le);case"base64":return $(this,H,Y,le);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return M(this,H,Y,le);default:if(ge)throw new TypeError("Unknown encoding: "+we);we=(""+we).toLowerCase(),ge=!0}},r.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function T(Q,H,Y){return H===0&&Y===Q.length?c.fromByteArray(Q):c.fromByteArray(Q.slice(H,Y))}function x(Q,H,Y){Y=Math.min(Q.length,Y);for(var le=[],we=H;we239?4:U>223?3:U>191?2:1;if(we+Se<=Y){var te,se,ve,Ee;switch(Se){case 1:U<128&&(ge=U);break;case 2:te=Q[we+1],(te&192)===128&&(Ee=(U&31)<<6|te&63,Ee>127&&(ge=Ee));break;case 3:te=Q[we+1],se=Q[we+2],(te&192)===128&&(se&192)===128&&(Ee=(U&15)<<12|(te&63)<<6|se&63,Ee>2047&&(Ee<55296||Ee>57343)&&(ge=Ee));break;case 4:te=Q[we+1],se=Q[we+2],ve=Q[we+3],(te&192)===128&&(se&192)===128&&(ve&192)===128&&(Ee=(U&15)<<18|(te&63)<<12|(se&63)<<6|ve&63,Ee>65535&&Ee<1114112&&(ge=Ee))}}ge===null?(ge=65533,Se=1):ge>65535&&(ge-=65536,le.push(ge>>>10&1023|55296),ge=56320|ge&1023),le.push(ge),we+=Se}return N(le)}var A=4096;function N(Q){var H=Q.length;if(H<=A)return String.fromCharCode.apply(String,Q);for(var Y="",le=0;lele)&&(Y=le);for(var we="",U=H;Ule&&(H=le),Y<0?(Y+=le,Y<0&&(Y=0)):Y>le&&(Y=le),YY)throw new RangeError("Trying to access beyond buffer length")}r.prototype.readUIntLE=function(H,Y,le){H=H>>>0,Y=Y>>>0,le||C(H,Y,this.length);for(var we=this[H],U=1,ge=0;++ge>>0,Y=Y>>>0,le||C(H,Y,this.length);for(var we=this[H+--Y],U=1;Y>0&&(U*=256);)we+=this[H+--Y]*U;return we},r.prototype.readUInt8=function(H,Y){return H=H>>>0,Y||C(H,1,this.length),this[H]},r.prototype.readUInt16LE=function(H,Y){return H=H>>>0,Y||C(H,2,this.length),this[H]|this[H+1]<<8},r.prototype.readUInt16BE=function(H,Y){return H=H>>>0,Y||C(H,2,this.length),this[H]<<8|this[H+1]},r.prototype.readUInt32LE=function(H,Y){return H=H>>>0,Y||C(H,4,this.length),(this[H]|this[H+1]<<8|this[H+2]<<16)+this[H+3]*16777216},r.prototype.readUInt32BE=function(H,Y){return H=H>>>0,Y||C(H,4,this.length),this[H]*16777216+(this[H+1]<<16|this[H+2]<<8|this[H+3])},r.prototype.readIntLE=function(H,Y,le){H=H>>>0,Y=Y>>>0,le||C(H,Y,this.length);for(var we=this[H],U=1,ge=0;++ge=U&&(we-=Math.pow(2,8*Y)),we},r.prototype.readIntBE=function(H,Y,le){H=H>>>0,Y=Y>>>0,le||C(H,Y,this.length);for(var we=Y,U=1,ge=this[H+--we];we>0&&(U*=256);)ge+=this[H+--we]*U;return U*=128,ge>=U&&(ge-=Math.pow(2,8*Y)),ge},r.prototype.readInt8=function(H,Y){return H=H>>>0,Y||C(H,1,this.length),this[H]&128?(255-this[H]+1)*-1:this[H]},r.prototype.readInt16LE=function(H,Y){H=H>>>0,Y||C(H,2,this.length);var le=this[H]|this[H+1]<<8;return le&32768?le|4294901760:le},r.prototype.readInt16BE=function(H,Y){H=H>>>0,Y||C(H,2,this.length);var le=this[H+1]|this[H]<<8;return le&32768?le|4294901760:le},r.prototype.readInt32LE=function(H,Y){return H=H>>>0,Y||C(H,4,this.length),this[H]|this[H+1]<<8|this[H+2]<<16|this[H+3]<<24},r.prototype.readInt32BE=function(H,Y){return H=H>>>0,Y||C(H,4,this.length),this[H]<<24|this[H+1]<<16|this[H+2]<<8|this[H+3]},r.prototype.readFloatLE=function(H,Y){return H=H>>>0,Y||C(H,4,this.length),h.read(this,H,!0,23,4)},r.prototype.readFloatBE=function(H,Y){return H=H>>>0,Y||C(H,4,this.length),h.read(this,H,!1,23,4)},r.prototype.readDoubleLE=function(H,Y){return H=H>>>0,Y||C(H,8,this.length),h.read(this,H,!0,52,8)},r.prototype.readDoubleBE=function(H,Y){return H=H>>>0,Y||C(H,8,this.length),h.read(this,H,!1,52,8)};function O(Q,H,Y,le,we,U){if(!r.isBuffer(Q))throw new TypeError('"buffer" argument must be a Buffer instance');if(H>we||HQ.length)throw new RangeError("Index out of range")}r.prototype.writeUIntLE=function(H,Y,le,we){if(H=+H,Y=Y>>>0,le=le>>>0,!we){var U=Math.pow(2,8*le)-1;O(this,H,Y,le,U,0)}var ge=1,Se=0;for(this[Y]=H&255;++Se>>0,le=le>>>0,!we){var U=Math.pow(2,8*le)-1;O(this,H,Y,le,U,0)}var ge=le-1,Se=1;for(this[Y+ge]=H&255;--ge>=0&&(Se*=256);)this[Y+ge]=H/Se&255;return Y+le},r.prototype.writeUInt8=function(H,Y,le){return H=+H,Y=Y>>>0,le||O(this,H,Y,1,255,0),this[Y]=H&255,Y+1},r.prototype.writeUInt16LE=function(H,Y,le){return H=+H,Y=Y>>>0,le||O(this,H,Y,2,65535,0),this[Y]=H&255,this[Y+1]=H>>>8,Y+2},r.prototype.writeUInt16BE=function(H,Y,le){return H=+H,Y=Y>>>0,le||O(this,H,Y,2,65535,0),this[Y]=H>>>8,this[Y+1]=H&255,Y+2},r.prototype.writeUInt32LE=function(H,Y,le){return H=+H,Y=Y>>>0,le||O(this,H,Y,4,4294967295,0),this[Y+3]=H>>>24,this[Y+2]=H>>>16,this[Y+1]=H>>>8,this[Y]=H&255,Y+4},r.prototype.writeUInt32BE=function(H,Y,le){return H=+H,Y=Y>>>0,le||O(this,H,Y,4,4294967295,0),this[Y]=H>>>24,this[Y+1]=H>>>16,this[Y+2]=H>>>8,this[Y+3]=H&255,Y+4},r.prototype.writeIntLE=function(H,Y,le,we){if(H=+H,Y=Y>>>0,!we){var U=Math.pow(2,8*le-1);O(this,H,Y,le,U-1,-U)}var ge=0,Se=1,te=0;for(this[Y]=H&255;++ge>0)-te&255;return Y+le},r.prototype.writeIntBE=function(H,Y,le,we){if(H=+H,Y=Y>>>0,!we){var U=Math.pow(2,8*le-1);O(this,H,Y,le,U-1,-U)}var ge=le-1,Se=1,te=0;for(this[Y+ge]=H&255;--ge>=0&&(Se*=256);)H<0&&te===0&&this[Y+ge+1]!==0&&(te=1),this[Y+ge]=(H/Se>>0)-te&255;return Y+le},r.prototype.writeInt8=function(H,Y,le){return H=+H,Y=Y>>>0,le||O(this,H,Y,1,127,-128),H<0&&(H=255+H+1),this[Y]=H&255,Y+1},r.prototype.writeInt16LE=function(H,Y,le){return H=+H,Y=Y>>>0,le||O(this,H,Y,2,32767,-32768),this[Y]=H&255,this[Y+1]=H>>>8,Y+2},r.prototype.writeInt16BE=function(H,Y,le){return H=+H,Y=Y>>>0,le||O(this,H,Y,2,32767,-32768),this[Y]=H>>>8,this[Y+1]=H&255,Y+2},r.prototype.writeInt32LE=function(H,Y,le){return H=+H,Y=Y>>>0,le||O(this,H,Y,4,2147483647,-2147483648),this[Y]=H&255,this[Y+1]=H>>>8,this[Y+2]=H>>>16,this[Y+3]=H>>>24,Y+4},r.prototype.writeInt32BE=function(H,Y,le){return H=+H,Y=Y>>>0,le||O(this,H,Y,4,2147483647,-2147483648),H<0&&(H=4294967295+H+1),this[Y]=H>>>24,this[Y+1]=H>>>16,this[Y+2]=H>>>8,this[Y+3]=H&255,Y+4};function X(Q,H,Y,le,we,U){if(Y+le>Q.length)throw new RangeError("Index out of range");if(Y<0)throw new RangeError("Index out of range")}function ie(Q,H,Y,le,we){return H=+H,Y=Y>>>0,we||X(Q,H,Y,4),h.write(Q,H,Y,le,23,4),Y+4}r.prototype.writeFloatLE=function(H,Y,le){return ie(this,H,Y,!0,le)},r.prototype.writeFloatBE=function(H,Y,le){return ie(this,H,Y,!1,le)};function he(Q,H,Y,le,we){return H=+H,Y=Y>>>0,we||X(Q,H,Y,8),h.write(Q,H,Y,le,52,8),Y+8}r.prototype.writeDoubleLE=function(H,Y,le){return he(this,H,Y,!0,le)},r.prototype.writeDoubleBE=function(H,Y,le){return he(this,H,Y,!1,le)},r.prototype.copy=function(H,Y,le,we){if(!r.isBuffer(H))throw new TypeError("argument should be a Buffer");if(le||(le=0),!we&&we!==0&&(we=this.length),Y>=H.length&&(Y=H.length),Y||(Y=0),we>0&&we=this.length)throw new RangeError("Index out of range");if(we<0)throw new RangeError("sourceEnd out of bounds");we>this.length&&(we=this.length),H.length-Y=0;--ge)H[ge+Y]=this[ge+le];else Uint8Array.prototype.set.call(H,this.subarray(le,we),Y);return U},r.prototype.fill=function(H,Y,le,we){if(typeof H=="string"){if(typeof Y=="string"?(we=Y,Y=0,le=this.length):typeof le=="string"&&(we=le,le=this.length),we!==void 0&&typeof we!="string")throw new TypeError("encoding must be a string");if(typeof we=="string"&&!r.isEncoding(we))throw new TypeError("Unknown encoding: "+we);if(H.length===1){var U=H.charCodeAt(0);(we==="utf8"&&U<128||we==="latin1")&&(H=U)}}else typeof H=="number"&&(H=H&255);if(Y<0||this.length>>0,le=le===void 0?this.length:le>>>0,H||(H=0);var ge;if(typeof H=="number")for(ge=Y;ge55295&&Y<57344){if(!we){if(Y>56319){(H-=3)>-1&&U.push(239,191,189);continue}else if(ge+1===le){(H-=3)>-1&&U.push(239,191,189);continue}we=Y;continue}if(Y<56320){(H-=3)>-1&&U.push(239,191,189),we=Y;continue}Y=(we-55296<<10|Y-56320)+65536}else we&&(H-=3)>-1&&U.push(239,191,189);if(we=null,Y<128){if((H-=1)<0)break;U.push(Y)}else if(Y<2048){if((H-=2)<0)break;U.push(Y>>6|192,Y&63|128)}else if(Y<65536){if((H-=3)<0)break;U.push(Y>>12|224,Y>>6&63|128,Y&63|128)}else if(Y<1114112){if((H-=4)<0)break;U.push(Y>>18|240,Y>>12&63|128,Y>>6&63|128,Y&63|128)}else throw new Error("Invalid code point")}return U}function Z(Q){for(var H=[],Y=0;Y>8,we=Y%256,U.push(we),U.push(le);return U}function de(Q){return c.toByteArray(ke(Q))}function Me(Q,H,Y,le){for(var we=0;we=H.length||we>=Q.length);++we)H[we+Y]=Q[we];return we}function ae(Q,H){return Q instanceof H||Q!=null&&Q.constructor!=null&&Q.constructor.name!=null&&Q.constructor.name===H.name}function ne(Q){return Q!==Q}}).call(this)}).call(this,e("buffer").Buffer)},{"base64-js":185,buffer:220,ieee754:439}],221:[function(e,d,m){var l=e("safe-buffer").Buffer,c=e("stream").Transform,h=e("string_decoder").StringDecoder,s=e("inherits");function t(i){c.call(this),this.hashMode=typeof i=="string",this.hashMode?this[i]=this._finalOrDigest:this.final=this._finalOrDigest,this._final&&(this.__final=this._final,this._final=null),this._decoder=null,this._encoding=null}s(t,c),t.prototype.update=function(i,r,n){typeof i=="string"&&(i=l.from(i,r));var o=this._update(i);return this.hashMode?this:(n&&(o=this._toString(o,n)),o)},t.prototype.setAutoPadding=function(){},t.prototype.getAuthTag=function(){throw new Error("trying to get auth tag in unsupported state")},t.prototype.setAuthTag=function(){throw new Error("trying to set auth tag in unsupported state")},t.prototype.setAAD=function(){throw new Error("trying to set aad in unsupported state")},t.prototype._transform=function(i,r,n){var o;try{this.hashMode?this._update(i):this.push(this._update(i))}catch(f){o=f}finally{n(o)}},t.prototype._flush=function(i){var r;try{this.push(this.__final())}catch(n){r=n}i(r)},t.prototype._finalOrDigest=function(i){var r=this.__final()||l.alloc(0);return i&&(r=this._toString(r,i,!0)),r},t.prototype._toString=function(i,r,n){if(this._decoder||(this._decoder=new h(r),this._encoding=r),this._encoding!==r)throw new Error("can't switch encodings");var o=this._decoder.write(i);return n&&(o+=this._decoder.end()),o},d.exports=t},{inherits:440,"safe-buffer":494,stream:505,string_decoder:218}],222:[function(e,d,m){var l=e("../internals/is-callable"),c=e("../internals/try-to-string"),h=TypeError;d.exports=function(s){if(l(s))return s;throw new h(c(s)+" is not a function")}},{"../internals/is-callable":285,"../internals/try-to-string":349}],223:[function(e,d,m){var l=e("../internals/is-constructor"),c=e("../internals/try-to-string"),h=TypeError;d.exports=function(s){if(l(s))return s;throw new h(c(s)+" is not a constructor")}},{"../internals/is-constructor":286,"../internals/try-to-string":349}],224:[function(e,d,m){var l=e("../internals/is-callable"),c=String,h=TypeError;d.exports=function(s){if(typeof s=="object"||l(s))return s;throw new h("Can't set "+c(s)+" as a prototype")}},{"../internals/is-callable":285}],225:[function(e,d,m){var l=e("../internals/well-known-symbol"),c=e("../internals/object-create"),h=e("../internals/object-define-property").f,s=l("unscopables"),t=Array.prototype;t[s]===void 0&&h(t,s,{configurable:!0,value:c(null)}),d.exports=function(i){t[s][i]=!0}},{"../internals/object-create":306,"../internals/object-define-property":308,"../internals/well-known-symbol":357}],226:[function(e,d,m){var l=e("../internals/object-is-prototype-of"),c=TypeError;d.exports=function(h,s){if(l(s,h))return h;throw new c("Incorrect invocation")}},{"../internals/object-is-prototype-of":314}],227:[function(e,d,m){var l=e("../internals/is-object"),c=String,h=TypeError;d.exports=function(s){if(l(s))return s;throw new h(c(s)+" is not an object")}},{"../internals/is-object":289}],228:[function(e,d,m){var l=e("../internals/to-indexed-object"),c=e("../internals/to-absolute-index"),h=e("../internals/length-of-array-like"),s=function(t){return function(i,r,n){var o=l(i),f=h(o),a=c(n,f),g;if(t&&r!==r){for(;f>a;)if(g=o[a++],g!==g)return!0}else for(;f>a;a++)if((t||a in o)&&o[a]===r)return t||a||0;return!t&&-1}};d.exports={includes:s(!0),indexOf:s(!1)}},{"../internals/length-of-array-like":299,"../internals/to-absolute-index":340,"../internals/to-indexed-object":341}],229:[function(e,d,m){var l=e("../internals/function-bind-context"),c=e("../internals/function-uncurry-this"),h=e("../internals/indexed-object"),s=e("../internals/to-object"),t=e("../internals/length-of-array-like"),i=e("../internals/array-species-create"),r=c([].push),n=function(o){var f=o===1,a=o===2,g=o===3,b=o===4,u=o===6,w=o===7,y=o===5||u;return function(S,E,I,P){for(var F=s(S),j=h(F),W=l(E,I),G=t(j),V=0,J=P||i,$=f?J(S,G):a||w?J(S,0):void 0,M,T;G>V;V++)if((y||V in j)&&(M=j[V],T=W(M,V,F),o))if(f)$[V]=T;else if(T)switch(o){case 3:return!0;case 5:return M;case 6:return V;case 2:r($,M)}else switch(o){case 4:return!1;case 7:r($,M)}return u?-1:g||b?b:$}};d.exports={forEach:n(0),map:n(1),filter:n(2),some:n(3),every:n(4),find:n(5),findIndex:n(6),filterReject:n(7)}},{"../internals/array-species-create":233,"../internals/function-bind-context":262,"../internals/function-uncurry-this":268,"../internals/indexed-object":280,"../internals/length-of-array-like":299,"../internals/to-object":344}],230:[function(e,d,m){var l=e("../internals/to-absolute-index"),c=e("../internals/length-of-array-like"),h=e("../internals/create-property"),s=Array,t=Math.max;d.exports=function(i,r,n){for(var o=c(i),f=l(r,o),a=l(n===void 0?o:n,o),g=s(t(a-f,0)),b=0;f"u"&&l!==void 0;d.exports={all:l,IS_HTMLDDA:c}},{}],249:[function(e,d,m){var l=e("../internals/global"),c=e("../internals/is-object"),h=l.document,s=c(h)&&c(h.createElement);d.exports=function(t){return s?h.createElement(t):{}}},{"../internals/global":274,"../internals/is-object":289}],250:[function(e,d,m){var l=e("../internals/engine-is-deno"),c=e("../internals/engine-is-node");d.exports=!l&&!c&&typeof window=="object"&&typeof document=="object"},{"../internals/engine-is-deno":251,"../internals/engine-is-node":254}],251:[function(e,d,m){d.exports=typeof Deno=="object"&&Deno&&typeof Deno.version=="object"},{}],252:[function(e,d,m){var l=e("../internals/engine-user-agent");d.exports=/ipad|iphone|ipod/i.test(l)&&typeof Pebble<"u"},{"../internals/engine-user-agent":256}],253:[function(e,d,m){var l=e("../internals/engine-user-agent");d.exports=/(?:ipad|iphone|ipod).*applewebkit/i.test(l)},{"../internals/engine-user-agent":256}],254:[function(e,d,m){var l=e("../internals/global"),c=e("../internals/classof-raw");d.exports=c(l.process)==="process"},{"../internals/classof-raw":235,"../internals/global":274}],255:[function(e,d,m){var l=e("../internals/engine-user-agent");d.exports=/web0s(?!.*chrome)/i.test(l)},{"../internals/engine-user-agent":256}],256:[function(e,d,m){d.exports=typeof navigator<"u"&&String(navigator.userAgent)||""},{}],257:[function(e,d,m){var l=e("../internals/global"),c=e("../internals/engine-user-agent"),h=l.process,s=l.Deno,t=h&&h.versions||s&&s.version,i=t&&t.v8,r,n;i&&(r=i.split("."),n=r[0]>0&&r[0]<4?1:+(r[0]+r[1])),!n&&c&&(r=c.match(/Edge\/(\d+)/),(!r||r[1]>=74)&&(r=c.match(/Chrome\/(\d+)/),r&&(n=+r[1]))),d.exports=n},{"../internals/engine-user-agent":256,"../internals/global":274}],258:[function(e,d,m){d.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},{}],259:[function(e,d,m){var l=e("../internals/global"),c=e("../internals/object-get-own-property-descriptor").f,h=e("../internals/create-non-enumerable-property"),s=e("../internals/define-built-in"),t=e("../internals/define-global-property"),i=e("../internals/copy-constructor-properties"),r=e("../internals/is-forced");d.exports=function(n,o){var f=n.target,a=n.global,g=n.stat,b,u,w,y,S,E;if(a?u=l:g?u=l[f]||t(f,{}):u=(l[f]||{}).prototype,u)for(w in o){if(S=o[w],n.dontCallGetSet?(E=c(u,w),y=E&&E.value):y=u[w],b=r(a?w:f+(g?".":"#")+w,n.forced),!b&&y!==void 0){if(typeof S==typeof y)continue;i(S,y)}(n.sham||y&&y.sham)&&h(S,"sham",!0),s(u,w,S,n)}}},{"../internals/copy-constructor-properties":237,"../internals/create-non-enumerable-property":241,"../internals/define-built-in":245,"../internals/define-global-property":246,"../internals/global":274,"../internals/is-forced":287,"../internals/object-get-own-property-descriptor":309}],260:[function(e,d,m){d.exports=function(l){try{return!!l()}catch{return!0}}},{}],261:[function(e,d,m){var l=e("../internals/function-bind-native"),c=Function.prototype,h=c.apply,s=c.call;d.exports=typeof Reflect=="object"&&Reflect.apply||(l?s.bind(h):function(){return s.apply(h,arguments)})},{"../internals/function-bind-native":263}],262:[function(e,d,m){var l=e("../internals/function-uncurry-this-clause"),c=e("../internals/a-callable"),h=e("../internals/function-bind-native"),s=l(l.bind);d.exports=function(t,i){return c(t),i===void 0?t:h?s(t,i):function(){return t.apply(i,arguments)}}},{"../internals/a-callable":222,"../internals/function-bind-native":263,"../internals/function-uncurry-this-clause":267}],263:[function(e,d,m){var l=e("../internals/fails");d.exports=!l(function(){var c=(function(){}).bind();return typeof c!="function"||c.hasOwnProperty("prototype")})},{"../internals/fails":260}],264:[function(e,d,m){var l=e("../internals/function-bind-native"),c=Function.prototype.call;d.exports=l?c.bind(c):function(){return c.apply(c,arguments)}},{"../internals/function-bind-native":263}],265:[function(e,d,m){var l=e("../internals/descriptors"),c=e("../internals/has-own-property"),h=Function.prototype,s=l&&Object.getOwnPropertyDescriptor,t=c(h,"name"),i=t&&(function(){}).name==="something",r=t&&(!l||l&&s(h,"name").configurable);d.exports={EXISTS:t,PROPER:i,CONFIGURABLE:r}},{"../internals/descriptors":247,"../internals/has-own-property":275}],266:[function(e,d,m){var l=e("../internals/function-uncurry-this"),c=e("../internals/a-callable");d.exports=function(h,s,t){try{return l(c(Object.getOwnPropertyDescriptor(h,s)[t]))}catch{}}},{"../internals/a-callable":222,"../internals/function-uncurry-this":268}],267:[function(e,d,m){var l=e("../internals/classof-raw"),c=e("../internals/function-uncurry-this");d.exports=function(h){if(l(h)==="Function")return c(h)}},{"../internals/classof-raw":235,"../internals/function-uncurry-this":268}],268:[function(e,d,m){var l=e("../internals/function-bind-native"),c=Function.prototype,h=c.call,s=l&&c.bind.bind(h,h);d.exports=l?s:function(t){return function(){return h.apply(t,arguments)}}},{"../internals/function-bind-native":263}],269:[function(e,d,m){var l=e("../internals/global"),c=e("../internals/is-callable"),h=function(s){return c(s)?s:void 0};d.exports=function(s,t){return arguments.length<2?h(l[s]):l[s]&&l[s][t]}},{"../internals/global":274,"../internals/is-callable":285}],270:[function(e,d,m){var l=e("../internals/classof"),c=e("../internals/get-method"),h=e("../internals/is-null-or-undefined"),s=e("../internals/iterators"),t=e("../internals/well-known-symbol"),i=t("iterator");d.exports=function(r){if(!h(r))return c(r,i)||c(r,"@@iterator")||s[l(r)]}},{"../internals/classof":236,"../internals/get-method":273,"../internals/is-null-or-undefined":288,"../internals/iterators":298,"../internals/well-known-symbol":357}],271:[function(e,d,m){var l=e("../internals/function-call"),c=e("../internals/a-callable"),h=e("../internals/an-object"),s=e("../internals/try-to-string"),t=e("../internals/get-iterator-method"),i=TypeError;d.exports=function(r,n){var o=arguments.length<2?t(r):n;if(c(o))return h(l(o,r));throw new i(s(r)+" is not iterable")}},{"../internals/a-callable":222,"../internals/an-object":227,"../internals/function-call":264,"../internals/get-iterator-method":270,"../internals/try-to-string":349}],272:[function(e,d,m){var l=e("../internals/function-uncurry-this"),c=e("../internals/is-array"),h=e("../internals/is-callable"),s=e("../internals/classof-raw"),t=e("../internals/to-string"),i=l([].push);d.exports=function(r){if(h(r))return r;if(c(r)){for(var n=r.length,o=[],f=0;fV;V++)if($=A(u[V]),$&&r(b,$))return $;return new g(!1)}W=n(u,G)}for(M=I?u.next:W.next;!(T=c(M,W)).done;){try{$=A(T.value)}catch(N){f(W,"throw",N)}if(typeof $=="object"&&$&&r(b,$))return $}return new g(!1)}},{"../internals/an-object":227,"../internals/function-bind-context":262,"../internals/function-call":264,"../internals/get-iterator":271,"../internals/get-iterator-method":270,"../internals/is-array-iterator-method":283,"../internals/iterator-close":294,"../internals/length-of-array-like":299,"../internals/object-is-prototype-of":314,"../internals/try-to-string":349}],294:[function(e,d,m){var l=e("../internals/function-call"),c=e("../internals/an-object"),h=e("../internals/get-method");d.exports=function(s,t,i){var r,n;c(s);try{if(r=h(s,"return"),!r){if(t==="throw")throw i;return i}r=l(r,s)}catch(o){n=!0,r=o}if(t==="throw")throw i;if(n)throw r;return c(r),i}},{"../internals/an-object":227,"../internals/function-call":264,"../internals/get-method":273}],295:[function(e,d,m){var l=e("../internals/iterators-core").IteratorPrototype,c=e("../internals/object-create"),h=e("../internals/create-property-descriptor"),s=e("../internals/set-to-string-tag"),t=e("../internals/iterators"),i=function(){return this};d.exports=function(r,n,o,f){var a=n+" Iterator";return r.prototype=c(l,{next:h(+!f,o)}),s(r,a,!1,!0),t[a]=i,r}},{"../internals/create-property-descriptor":242,"../internals/iterators":298,"../internals/iterators-core":297,"../internals/object-create":306,"../internals/set-to-string-tag":331}],296:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/function-call"),h=e("../internals/is-pure"),s=e("../internals/function-name"),t=e("../internals/is-callable"),i=e("../internals/iterator-create-constructor"),r=e("../internals/object-get-prototype-of"),n=e("../internals/object-set-prototype-of"),o=e("../internals/set-to-string-tag"),f=e("../internals/create-non-enumerable-property"),a=e("../internals/define-built-in"),g=e("../internals/well-known-symbol"),b=e("../internals/iterators"),u=e("../internals/iterators-core"),w=s.PROPER,y=s.CONFIGURABLE,S=u.IteratorPrototype,E=u.BUGGY_SAFARI_ITERATORS,I=g("iterator"),P="keys",F="values",j="entries",W=function(){return this};d.exports=function(G,V,J,$,M,T,x){i(J,V,$);var A=function(he){if(he===M&&k)return k;if(!E&&he&&he in z)return z[he];switch(he){case P:return function(){return new J(this,he)};case F:return function(){return new J(this,he)};case j:return function(){return new J(this,he)}}return function(){return new J(this)}},N=V+" Iterator",L=!1,z=G.prototype,R=z[I]||z["@@iterator"]||M&&z[M],k=!E&&R||A(M),C=V==="Array"&&z.entries||R,O,X,ie;if(C&&(O=r(C.call(new G)),O!==Object.prototype&&O.next&&(!h&&r(O)!==S&&(n?n(O,S):t(O[I])||a(O,I,W)),o(O,N,!0,!0),h&&(b[N]=W))),w&&M===F&&R&&R.name!==F&&(!h&&y?f(z,"name",F):(L=!0,k=function(){return c(R,this)})),M)if(X={values:A(F),keys:T?k:A(P),entries:A(j)},x)for(ie in X)(E||L||!(ie in z))&&a(z,ie,X[ie]);else l({target:V,proto:!0,forced:E||L},X);return(!h||x)&&z[I]!==k&&a(z,I,k,{name:M}),b[V]=k,X}},{"../internals/create-non-enumerable-property":241,"../internals/define-built-in":245,"../internals/export":259,"../internals/function-call":264,"../internals/function-name":265,"../internals/is-callable":285,"../internals/is-pure":290,"../internals/iterator-create-constructor":295,"../internals/iterators":298,"../internals/iterators-core":297,"../internals/object-get-prototype-of":313,"../internals/object-set-prototype-of":318,"../internals/set-to-string-tag":331,"../internals/well-known-symbol":357}],297:[function(e,d,m){var l=e("../internals/fails"),c=e("../internals/is-callable"),h=e("../internals/is-object"),s=e("../internals/object-create"),t=e("../internals/object-get-prototype-of"),i=e("../internals/define-built-in"),r=e("../internals/well-known-symbol"),n=e("../internals/is-pure"),o=r("iterator"),f=!1,a,g,b;[].keys&&(b=[].keys(),"next"in b?(g=t(t(b)),g!==Object.prototype&&(a=g)):f=!0);var u=!h(a)||l(function(){var w={};return a[o].call(w)!==w});u?a={}:n&&(a=s(a)),c(a[o])||i(a,o,function(){return this}),d.exports={IteratorPrototype:a,BUGGY_SAFARI_ITERATORS:f}},{"../internals/define-built-in":245,"../internals/fails":260,"../internals/is-callable":285,"../internals/is-object":289,"../internals/is-pure":290,"../internals/object-create":306,"../internals/object-get-prototype-of":313,"../internals/well-known-symbol":357}],298:[function(e,d,m){arguments[4][276][0].apply(m,arguments)},{dup:276}],299:[function(e,d,m){var l=e("../internals/to-length");d.exports=function(c){return l(c.length)}},{"../internals/to-length":343}],300:[function(e,d,m){var l=e("../internals/function-uncurry-this"),c=e("../internals/fails"),h=e("../internals/is-callable"),s=e("../internals/has-own-property"),t=e("../internals/descriptors"),i=e("../internals/function-name").CONFIGURABLE,r=e("../internals/inspect-source"),n=e("../internals/internal-state"),o=n.enforce,f=n.get,a=String,g=Object.defineProperty,b=l("".slice),u=l("".replace),w=l([].join),y=t&&!c(function(){return g(function(){},"length",{value:8}).length!==8}),S=String(String).split("String"),E=d.exports=function(I,P,F){b(a(P),0,7)==="Symbol("&&(P="["+u(a(P),/^Symbol\(([^)]*)\)/,"$1")+"]"),F&&F.getter&&(P="get "+P),F&&F.setter&&(P="set "+P),(!s(I,"name")||i&&I.name!==P)&&(t?g(I,"name",{value:P,configurable:!0}):I.name=P),y&&F&&s(F,"arity")&&I.length!==F.arity&&g(I,"length",{value:F.arity});try{F&&s(F,"constructor")&&F.constructor?t&&g(I,"prototype",{writable:!1}):I.prototype&&(I.prototype=void 0)}catch{}var j=o(I);return s(j,"source")||(j.source=w(S,typeof P=="string"?P:"")),I};Function.prototype.toString=E(function(){return h(this)&&f(this).source||r(this)},"toString")},{"../internals/descriptors":247,"../internals/fails":260,"../internals/function-name":265,"../internals/function-uncurry-this":268,"../internals/has-own-property":275,"../internals/inspect-source":281,"../internals/internal-state":282,"../internals/is-callable":285}],301:[function(e,d,m){var l=Math.ceil,c=Math.floor;d.exports=Math.trunc||function(s){var t=+s;return(t>0?c:l)(t)}},{}],302:[function(e,d,m){var l=e("../internals/global"),c=e("../internals/function-bind-context"),h=e("../internals/object-get-own-property-descriptor").f,s=e("../internals/task").set,t=e("../internals/queue"),i=e("../internals/engine-is-ios"),r=e("../internals/engine-is-ios-pebble"),n=e("../internals/engine-is-webos-webkit"),o=e("../internals/engine-is-node"),f=l.MutationObserver||l.WebKitMutationObserver,a=l.document,g=l.process,b=l.Promise,u=h(l,"queueMicrotask"),w=u&&u.value,y,S,E,I,P;if(!w){var F=new t,j=function(){var W,G;for(o&&(W=g.domain)&&W.exit();G=F.get();)try{G()}catch(V){throw F.head&&y(),V}W&&W.enter()};!i&&!o&&!n&&f&&a?(S=!0,E=a.createTextNode(""),new f(j).observe(E,{characterData:!0}),y=function(){E.data=S=!S}):!r&&b&&b.resolve?(I=b.resolve(void 0),I.constructor=b,P=c(I.then,I),y=function(){P(j)}):o?y=function(){g.nextTick(j)}:(s=c(s,l),y=function(){s(j)}),w=function(W){F.head||y(),F.add(W)}}d.exports=w},{"../internals/engine-is-ios":253,"../internals/engine-is-ios-pebble":252,"../internals/engine-is-node":254,"../internals/engine-is-webos-webkit":255,"../internals/function-bind-context":262,"../internals/global":274,"../internals/object-get-own-property-descriptor":309,"../internals/queue":328,"../internals/task":339}],303:[function(e,d,m){var l=e("../internals/a-callable"),c=TypeError,h=function(s){var t,i;this.promise=new s(function(r,n){if(t!==void 0||i!==void 0)throw new c("Bad Promise constructor");t=r,i=n}),this.resolve=l(t),this.reject=l(i)};d.exports.f=function(s){return new h(s)}},{"../internals/a-callable":222}],304:[function(e,d,m){var l=e("../internals/is-regexp"),c=TypeError;d.exports=function(h){if(l(h))throw new c("The method doesn't accept regular expressions");return h}},{"../internals/is-regexp":291}],305:[function(e,d,m){var l=e("../internals/descriptors"),c=e("../internals/function-uncurry-this"),h=e("../internals/function-call"),s=e("../internals/fails"),t=e("../internals/object-keys"),i=e("../internals/object-get-own-property-symbols"),r=e("../internals/object-property-is-enumerable"),n=e("../internals/to-object"),o=e("../internals/indexed-object"),f=Object.assign,a=Object.defineProperty,g=c([].concat);d.exports=!f||s(function(){if(l&&f({b:1},f(a({},"a",{enumerable:!0,get:function(){a(this,"b",{value:3,enumerable:!1})}}),{b:2})).b!==1)return!0;var b={},u={},w=Symbol("assign detection"),y="abcdefghijklmnopqrst";return b[w]=7,y.split("").forEach(function(S){u[S]=S}),f({},b)[w]!==7||t(f({},u)).join("")!==y})?function(u,w){for(var y=n(u),S=arguments.length,E=1,I=i.f,P=r.f;S>E;)for(var F=o(arguments[E++]),j=I?g(t(F),I(F)):t(F),W=j.length,G=0,V;W>G;)V=j[G++],(!l||h(P,F,V))&&(y[V]=F[V]);return y}:f},{"../internals/descriptors":247,"../internals/fails":260,"../internals/function-call":264,"../internals/function-uncurry-this":268,"../internals/indexed-object":280,"../internals/object-get-own-property-symbols":312,"../internals/object-keys":316,"../internals/object-property-is-enumerable":317,"../internals/to-object":344}],306:[function(e,d,m){var l=e("../internals/an-object"),c=e("../internals/object-define-properties"),h=e("../internals/enum-bug-keys"),s=e("../internals/hidden-keys"),t=e("../internals/html"),i=e("../internals/document-create-element"),r=e("../internals/shared-key"),n=">",o="<",f="prototype",a="script",g=r("IE_PROTO"),b=function(){},u=function(I){return o+a+n+I+o+"/"+a+n},w=function(I){I.write(u("")),I.close();var P=I.parentWindow.Object;return I=null,P},y=function(){var I=i("iframe"),P="java"+a+":",F;return I.style.display="none",t.appendChild(I),I.src=String(P),F=I.contentWindow.document,F.open(),F.write(u("document.F=Object")),F.close(),F.F},S,E=function(){try{S=new ActiveXObject("htmlfile")}catch{}E=typeof document<"u"?document.domain&&S?w(S):y():w(S);for(var I=h.length;I--;)delete E[f][h[I]];return E()};s[g]=!0,d.exports=Object.create||function(P,F){var j;return P!==null?(b[f]=l(P),j=new b,b[f]=null,j[g]=P):j=E(),F===void 0?j:c.f(j,F)}},{"../internals/an-object":227,"../internals/document-create-element":249,"../internals/enum-bug-keys":258,"../internals/hidden-keys":276,"../internals/html":278,"../internals/object-define-properties":307,"../internals/shared-key":332}],307:[function(e,d,m){var l=e("../internals/descriptors"),c=e("../internals/v8-prototype-define-bug"),h=e("../internals/object-define-property"),s=e("../internals/an-object"),t=e("../internals/to-indexed-object"),i=e("../internals/object-keys");m.f=l&&!c?Object.defineProperties:function(n,o){s(n);for(var f=t(o),a=i(o),g=a.length,b=0,u;g>b;)h.f(n,u=a[b++],f[u]);return n}},{"../internals/an-object":227,"../internals/descriptors":247,"../internals/object-define-property":308,"../internals/object-keys":316,"../internals/to-indexed-object":341,"../internals/v8-prototype-define-bug":352}],308:[function(e,d,m){var l=e("../internals/descriptors"),c=e("../internals/ie8-dom-define"),h=e("../internals/v8-prototype-define-bug"),s=e("../internals/an-object"),t=e("../internals/to-property-key"),i=TypeError,r=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o="enumerable",f="configurable",a="writable";m.f=l?h?function(b,u,w){if(s(b),u=t(u),s(w),typeof b=="function"&&u==="prototype"&&"value"in w&&a in w&&!w[a]){var y=n(b,u);y&&y[a]&&(b[u]=w.value,w={configurable:f in w?w[f]:y[f],enumerable:o in w?w[o]:y[o],writable:!1})}return r(b,u,w)}:r:function(b,u,w){if(s(b),u=t(u),s(w),c)try{return r(b,u,w)}catch{}if("get"in w||"set"in w)throw new i("Accessors not supported");return"value"in w&&(b[u]=w.value),b}},{"../internals/an-object":227,"../internals/descriptors":247,"../internals/ie8-dom-define":279,"../internals/to-property-key":346,"../internals/v8-prototype-define-bug":352}],309:[function(e,d,m){var l=e("../internals/descriptors"),c=e("../internals/function-call"),h=e("../internals/object-property-is-enumerable"),s=e("../internals/create-property-descriptor"),t=e("../internals/to-indexed-object"),i=e("../internals/to-property-key"),r=e("../internals/has-own-property"),n=e("../internals/ie8-dom-define"),o=Object.getOwnPropertyDescriptor;m.f=l?o:function(a,g){if(a=t(a),g=i(g),n)try{return o(a,g)}catch{}if(r(a,g))return s(!c(h.f,a,g),a[g])}},{"../internals/create-property-descriptor":242,"../internals/descriptors":247,"../internals/function-call":264,"../internals/has-own-property":275,"../internals/ie8-dom-define":279,"../internals/object-property-is-enumerable":317,"../internals/to-indexed-object":341,"../internals/to-property-key":346}],310:[function(e,d,m){var l=e("../internals/classof-raw"),c=e("../internals/to-indexed-object"),h=e("../internals/object-get-own-property-names").f,s=e("../internals/array-slice-simple"),t=typeof window=="object"&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],i=function(r){try{return h(r)}catch{return s(t)}};d.exports.f=function(n){return t&&l(n)==="Window"?i(n):h(c(n))}},{"../internals/array-slice-simple":230,"../internals/classof-raw":235,"../internals/object-get-own-property-names":311,"../internals/to-indexed-object":341}],311:[function(e,d,m){var l=e("../internals/object-keys-internal"),c=e("../internals/enum-bug-keys"),h=c.concat("length","prototype");m.f=Object.getOwnPropertyNames||function(t){return l(t,h)}},{"../internals/enum-bug-keys":258,"../internals/object-keys-internal":315}],312:[function(e,d,m){m.f=Object.getOwnPropertySymbols},{}],313:[function(e,d,m){var l=e("../internals/has-own-property"),c=e("../internals/is-callable"),h=e("../internals/to-object"),s=e("../internals/shared-key"),t=e("../internals/correct-prototype-getter"),i=s("IE_PROTO"),r=Object,n=r.prototype;d.exports=t?r.getPrototypeOf:function(o){var f=h(o);if(l(f,i))return f[i];var a=f.constructor;return c(a)&&f instanceof a?a.prototype:f instanceof r?n:null}},{"../internals/correct-prototype-getter":239,"../internals/has-own-property":275,"../internals/is-callable":285,"../internals/shared-key":332,"../internals/to-object":344}],314:[function(e,d,m){var l=e("../internals/function-uncurry-this");d.exports=l({}.isPrototypeOf)},{"../internals/function-uncurry-this":268}],315:[function(e,d,m){var l=e("../internals/function-uncurry-this"),c=e("../internals/has-own-property"),h=e("../internals/to-indexed-object"),s=e("../internals/array-includes").indexOf,t=e("../internals/hidden-keys"),i=l([].push);d.exports=function(r,n){var o=h(r),f=0,a=[],g;for(g in o)!c(t,g)&&c(o,g)&&i(a,g);for(;n.length>f;)c(o,g=n[f++])&&(~s(a,g)||i(a,g));return a}},{"../internals/array-includes":228,"../internals/function-uncurry-this":268,"../internals/has-own-property":275,"../internals/hidden-keys":276,"../internals/to-indexed-object":341}],316:[function(e,d,m){var l=e("../internals/object-keys-internal"),c=e("../internals/enum-bug-keys");d.exports=Object.keys||function(s){return l(s,c)}},{"../internals/enum-bug-keys":258,"../internals/object-keys-internal":315}],317:[function(e,d,m){var l={}.propertyIsEnumerable,c=Object.getOwnPropertyDescriptor,h=c&&!l.call({1:2},1);m.f=h?function(t){var i=c(this,t);return!!i&&i.enumerable}:l},{}],318:[function(e,d,m){var l=e("../internals/function-uncurry-this-accessor"),c=e("../internals/an-object"),h=e("../internals/a-possible-prototype");d.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var s=!1,t={},i;try{i=l(Object.prototype,"__proto__","set"),i(t,[]),s=t instanceof Array}catch{}return function(n,o){return c(n),h(o),s?i(n,o):n.__proto__=o,n}}():void 0)},{"../internals/a-possible-prototype":224,"../internals/an-object":227,"../internals/function-uncurry-this-accessor":266}],319:[function(e,d,m){var l=e("../internals/descriptors"),c=e("../internals/fails"),h=e("../internals/function-uncurry-this"),s=e("../internals/object-get-prototype-of"),t=e("../internals/object-keys"),i=e("../internals/to-indexed-object"),r=e("../internals/object-property-is-enumerable").f,n=h(r),o=h([].push),f=l&&c(function(){var g=Object.create(null);return g[2]=2,!n(g,2)}),a=function(g){return function(b){for(var u=i(b),w=t(u),y=f&&s(u)===null,S=w.length,E=0,I=[],P;S>E;)P=w[E++],(!l||(y?P in u:n(u,P)))&&o(I,g?[P,u[P]]:u[P]);return I}};d.exports={entries:a(!0),values:a(!1)}},{"../internals/descriptors":247,"../internals/fails":260,"../internals/function-uncurry-this":268,"../internals/object-get-prototype-of":313,"../internals/object-keys":316,"../internals/object-property-is-enumerable":317,"../internals/to-indexed-object":341}],320:[function(e,d,m){var l=e("../internals/function-call"),c=e("../internals/is-callable"),h=e("../internals/is-object"),s=TypeError;d.exports=function(t,i){var r,n;if(i==="string"&&c(r=t.toString)&&!h(n=l(r,t))||c(r=t.valueOf)&&!h(n=l(r,t))||i!=="string"&&c(r=t.toString)&&!h(n=l(r,t)))return n;throw new s("Can't convert object to primitive value")}},{"../internals/function-call":264,"../internals/is-callable":285,"../internals/is-object":289}],321:[function(e,d,m){var l=e("../internals/get-built-in"),c=e("../internals/function-uncurry-this"),h=e("../internals/object-get-own-property-names"),s=e("../internals/object-get-own-property-symbols"),t=e("../internals/an-object"),i=c([].concat);d.exports=l("Reflect","ownKeys")||function(n){var o=h.f(t(n)),f=s.f;return f?i(o,f(n)):o}},{"../internals/an-object":227,"../internals/function-uncurry-this":268,"../internals/get-built-in":269,"../internals/object-get-own-property-names":311,"../internals/object-get-own-property-symbols":312}],322:[function(e,d,m){var l=e("../internals/global");d.exports=l},{"../internals/global":274}],323:[function(e,d,m){d.exports=function(l){try{return{error:!1,value:l()}}catch(c){return{error:!0,value:c}}}},{}],324:[function(e,d,m){var l=e("../internals/global"),c=e("../internals/promise-native-constructor"),h=e("../internals/is-callable"),s=e("../internals/is-forced"),t=e("../internals/inspect-source"),i=e("../internals/well-known-symbol"),r=e("../internals/engine-is-browser"),n=e("../internals/engine-is-deno"),o=e("../internals/is-pure"),f=e("../internals/engine-v8-version"),a=c&&c.prototype,g=i("species"),b=!1,u=h(l.PromiseRejectionEvent),w=s("Promise",function(){var y=t(c),S=y!==String(c);if(!S&&f===66||o&&!(a.catch&&a.finally))return!0;if(!f||f<51||!/native code/.test(y)){var E=new c(function(F){F(1)}),I=function(F){F(function(){},function(){})},P=E.constructor={};if(P[g]=I,b=E.then(function(){})instanceof I,!b)return!0}return!S&&(r||n)&&!u});d.exports={CONSTRUCTOR:w,REJECTION_EVENT:u,SUBCLASSING:b}},{"../internals/engine-is-browser":250,"../internals/engine-is-deno":251,"../internals/engine-v8-version":257,"../internals/global":274,"../internals/inspect-source":281,"../internals/is-callable":285,"../internals/is-forced":287,"../internals/is-pure":290,"../internals/promise-native-constructor":325,"../internals/well-known-symbol":357}],325:[function(e,d,m){var l=e("../internals/global");d.exports=l.Promise},{"../internals/global":274}],326:[function(e,d,m){var l=e("../internals/an-object"),c=e("../internals/is-object"),h=e("../internals/new-promise-capability");d.exports=function(s,t){if(l(s),c(t)&&t.constructor===s)return t;var i=h.f(s),r=i.resolve;return r(t),i.promise}},{"../internals/an-object":227,"../internals/is-object":289,"../internals/new-promise-capability":303}],327:[function(e,d,m){var l=e("../internals/promise-native-constructor"),c=e("../internals/check-correctness-of-iteration"),h=e("../internals/promise-constructor-detection").CONSTRUCTOR;d.exports=h||!c(function(s){l.all(s).then(void 0,function(){})})},{"../internals/check-correctness-of-iteration":234,"../internals/promise-constructor-detection":324,"../internals/promise-native-constructor":325}],328:[function(e,d,m){var l=function(){this.head=null,this.tail=null};l.prototype={add:function(c){var h={item:c,next:null},s=this.tail;s?s.next=h:this.head=h,this.tail=h},get:function(){var c=this.head;if(c){var h=this.head=c.next;return h===null&&(this.tail=null),c.item}}},d.exports=l},{}],329:[function(e,d,m){var l=e("../internals/is-null-or-undefined"),c=TypeError;d.exports=function(h){if(l(h))throw new c("Can't call method on "+h);return h}},{"../internals/is-null-or-undefined":288}],330:[function(e,d,m){var l=e("../internals/get-built-in"),c=e("../internals/define-built-in-accessor"),h=e("../internals/well-known-symbol"),s=e("../internals/descriptors"),t=h("species");d.exports=function(i){var r=l(i);s&&r&&!r[t]&&c(r,t,{configurable:!0,get:function(){return this}})}},{"../internals/define-built-in-accessor":244,"../internals/descriptors":247,"../internals/get-built-in":269,"../internals/well-known-symbol":357}],331:[function(e,d,m){var l=e("../internals/object-define-property").f,c=e("../internals/has-own-property"),h=e("../internals/well-known-symbol"),s=h("toStringTag");d.exports=function(t,i,r){t&&!r&&(t=t.prototype),t&&!c(t,s)&&l(t,s,{configurable:!0,value:i})}},{"../internals/has-own-property":275,"../internals/object-define-property":308,"../internals/well-known-symbol":357}],332:[function(e,d,m){var l=e("../internals/shared"),c=e("../internals/uid"),h=l("keys");d.exports=function(s){return h[s]||(h[s]=c(s))}},{"../internals/shared":334,"../internals/uid":350}],333:[function(e,d,m){var l=e("../internals/global"),c=e("../internals/define-global-property"),h="__core-js_shared__",s=l[h]||c(h,{});d.exports=s},{"../internals/define-global-property":246,"../internals/global":274}],334:[function(e,d,m){var l=e("../internals/is-pure"),c=e("../internals/shared-store");(d.exports=function(h,s){return c[h]||(c[h]=s!==void 0?s:{})})("versions",[]).push({version:"3.33.0",mode:l?"pure":"global",copyright:"© 2014-2023 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.33.0/LICENSE",source:"https://github.com/zloirock/core-js"})},{"../internals/is-pure":290,"../internals/shared-store":333}],335:[function(e,d,m){var l=e("../internals/an-object"),c=e("../internals/a-constructor"),h=e("../internals/is-null-or-undefined"),s=e("../internals/well-known-symbol"),t=s("species");d.exports=function(i,r){var n=l(i).constructor,o;return n===void 0||h(o=l(n)[t])?r:c(o)}},{"../internals/a-constructor":223,"../internals/an-object":227,"../internals/is-null-or-undefined":288,"../internals/well-known-symbol":357}],336:[function(e,d,m){var l=e("../internals/engine-v8-version"),c=e("../internals/fails"),h=e("../internals/global"),s=h.String;d.exports=!!Object.getOwnPropertySymbols&&!c(function(){var t=Symbol("symbol detection");return!s(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&l&&l<41})},{"../internals/engine-v8-version":257,"../internals/fails":260,"../internals/global":274}],337:[function(e,d,m){var l=e("../internals/function-call"),c=e("../internals/get-built-in"),h=e("../internals/well-known-symbol"),s=e("../internals/define-built-in");d.exports=function(){var t=c("Symbol"),i=t&&t.prototype,r=i&&i.valueOf,n=h("toPrimitive");i&&!i[n]&&s(i,n,function(o){return l(r,this)},{arity:1})}},{"../internals/define-built-in":245,"../internals/function-call":264,"../internals/get-built-in":269,"../internals/well-known-symbol":357}],338:[function(e,d,m){var l=e("../internals/symbol-constructor-detection");d.exports=l&&!!Symbol.for&&!!Symbol.keyFor},{"../internals/symbol-constructor-detection":336}],339:[function(e,d,m){var l=e("../internals/global"),c=e("../internals/function-apply"),h=e("../internals/function-bind-context"),s=e("../internals/is-callable"),t=e("../internals/has-own-property"),i=e("../internals/fails"),r=e("../internals/html"),n=e("../internals/array-slice"),o=e("../internals/document-create-element"),f=e("../internals/validate-arguments-length"),a=e("../internals/engine-is-ios"),g=e("../internals/engine-is-node"),b=l.setImmediate,u=l.clearImmediate,w=l.process,y=l.Dispatch,S=l.Function,E=l.MessageChannel,I=l.String,P=0,F={},j="onreadystatechange",W,G,V,J;i(function(){W=l.location});var $=function(A){if(t(F,A)){var N=F[A];delete F[A],N()}},M=function(A){return function(){$(A)}},T=function(A){$(A.data)},x=function(A){l.postMessage(I(A),W.protocol+"//"+W.host)};(!b||!u)&&(b=function(N){f(arguments.length,1);var L=s(N)?N:S(N),z=n(arguments,1);return F[++P]=function(){c(L,void 0,z)},G(P),P},u=function(N){delete F[N]},g?G=function(A){w.nextTick(M(A))}:y&&y.now?G=function(A){y.now(M(A))}:E&&!a?(V=new E,J=V.port2,V.port1.onmessage=T,G=h(J.postMessage,J)):l.addEventListener&&s(l.postMessage)&&!l.importScripts&&W&&W.protocol!=="file:"&&!i(x)?(G=x,l.addEventListener("message",T,!1)):j in o("script")?G=function(A){r.appendChild(o("script"))[j]=function(){r.removeChild(this),$(A)}}:G=function(A){setTimeout(M(A),0)}),d.exports={set:b,clear:u}},{"../internals/array-slice":231,"../internals/document-create-element":249,"../internals/engine-is-ios":253,"../internals/engine-is-node":254,"../internals/fails":260,"../internals/function-apply":261,"../internals/function-bind-context":262,"../internals/global":274,"../internals/has-own-property":275,"../internals/html":278,"../internals/is-callable":285,"../internals/validate-arguments-length":353}],340:[function(e,d,m){var l=e("../internals/to-integer-or-infinity"),c=Math.max,h=Math.min;d.exports=function(s,t){var i=l(s);return i<0?c(i+t,0):h(i,t)}},{"../internals/to-integer-or-infinity":342}],341:[function(e,d,m){var l=e("../internals/indexed-object"),c=e("../internals/require-object-coercible");d.exports=function(h){return l(c(h))}},{"../internals/indexed-object":280,"../internals/require-object-coercible":329}],342:[function(e,d,m){var l=e("../internals/math-trunc");d.exports=function(c){var h=+c;return h!==h||h===0?0:l(h)}},{"../internals/math-trunc":301}],343:[function(e,d,m){var l=e("../internals/to-integer-or-infinity"),c=Math.min;d.exports=function(h){return h>0?c(l(h),9007199254740991):0}},{"../internals/to-integer-or-infinity":342}],344:[function(e,d,m){var l=e("../internals/require-object-coercible"),c=Object;d.exports=function(h){return c(l(h))}},{"../internals/require-object-coercible":329}],345:[function(e,d,m){var l=e("../internals/function-call"),c=e("../internals/is-object"),h=e("../internals/is-symbol"),s=e("../internals/get-method"),t=e("../internals/ordinary-to-primitive"),i=e("../internals/well-known-symbol"),r=TypeError,n=i("toPrimitive");d.exports=function(o,f){if(!c(o)||h(o))return o;var a=s(o,n),g;if(a){if(f===void 0&&(f="default"),g=l(a,o,f),!c(g)||h(g))return g;throw new r("Can't convert object to primitive value")}return f===void 0&&(f="number"),t(o,f)}},{"../internals/function-call":264,"../internals/get-method":273,"../internals/is-object":289,"../internals/is-symbol":292,"../internals/ordinary-to-primitive":320,"../internals/well-known-symbol":357}],346:[function(e,d,m){var l=e("../internals/to-primitive"),c=e("../internals/is-symbol");d.exports=function(h){var s=l(h,"string");return c(s)?s:s+""}},{"../internals/is-symbol":292,"../internals/to-primitive":345}],347:[function(e,d,m){var l=e("../internals/well-known-symbol"),c=l("toStringTag"),h={};h[c]="z",d.exports=String(h)==="[object z]"},{"../internals/well-known-symbol":357}],348:[function(e,d,m){var l=e("../internals/classof"),c=String;d.exports=function(h){if(l(h)==="Symbol")throw new TypeError("Cannot convert a Symbol value to a string");return c(h)}},{"../internals/classof":236}],349:[function(e,d,m){var l=String;d.exports=function(c){try{return l(c)}catch{return"Object"}}},{}],350:[function(e,d,m){var l=e("../internals/function-uncurry-this"),c=0,h=Math.random(),s=l(1 .toString);d.exports=function(t){return"Symbol("+(t===void 0?"":t)+")_"+s(++c+h,36)}},{"../internals/function-uncurry-this":268}],351:[function(e,d,m){var l=e("../internals/symbol-constructor-detection");d.exports=l&&!Symbol.sham&&typeof Symbol.iterator=="symbol"},{"../internals/symbol-constructor-detection":336}],352:[function(e,d,m){var l=e("../internals/descriptors"),c=e("../internals/fails");d.exports=l&&c(function(){return Object.defineProperty(function(){},"prototype",{value:42,writable:!1}).prototype!==42})},{"../internals/descriptors":247,"../internals/fails":260}],353:[function(e,d,m){var l=TypeError;d.exports=function(c,h){if(c1?arguments[1]:void 0)}}),h(s)},{"../internals/add-to-unscopables":225,"../internals/array-iteration":229,"../internals/export":259}],359:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/array-iteration").find,h=e("../internals/add-to-unscopables"),s="find",t=!0;s in[]&&Array(1)[s](function(){t=!1}),l({target:"Array",proto:!0,forced:t},{find:function(r){return c(this,r,arguments.length>1?arguments[1]:void 0)}}),h(s)},{"../internals/add-to-unscopables":225,"../internals/array-iteration":229,"../internals/export":259}],360:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/array-includes").includes,h=e("../internals/fails"),s=e("../internals/add-to-unscopables"),t=h(function(){return!Array(1).includes()});l({target:"Array",proto:!0,forced:t},{includes:function(r){return c(this,r,arguments.length>1?arguments[1]:void 0)}}),s("includes")},{"../internals/add-to-unscopables":225,"../internals/array-includes":228,"../internals/export":259,"../internals/fails":260}],361:[function(e,d,m){var l=e("../internals/to-indexed-object"),c=e("../internals/add-to-unscopables"),h=e("../internals/iterators"),s=e("../internals/internal-state"),t=e("../internals/object-define-property").f,i=e("../internals/iterator-define"),r=e("../internals/create-iter-result-object"),n=e("../internals/is-pure"),o=e("../internals/descriptors"),f="Array Iterator",a=s.set,g=s.getterFor(f);d.exports=i(Array,"Array",function(u,w){a(this,{type:f,target:l(u),index:0,kind:w})},function(){var u=g(this),w=u.target,y=u.kind,S=u.index++;if(!w||S>=w.length)return u.target=void 0,r(void 0,!0);switch(y){case"keys":return r(S,!1);case"values":return r(w[S],!1)}return r([S,w[S]],!1)},"values");var b=h.Arguments=h.Array;if(c("keys"),c("values"),c("entries"),!n&&o&&b.name!=="values")try{t(b,"name",{value:"values"})}catch{}},{"../internals/add-to-unscopables":225,"../internals/create-iter-result-object":240,"../internals/descriptors":247,"../internals/internal-state":282,"../internals/is-pure":290,"../internals/iterator-define":296,"../internals/iterators":298,"../internals/object-define-property":308,"../internals/to-indexed-object":341}],362:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/get-built-in"),h=e("../internals/function-apply"),s=e("../internals/function-call"),t=e("../internals/function-uncurry-this"),i=e("../internals/fails"),r=e("../internals/is-callable"),n=e("../internals/is-symbol"),o=e("../internals/array-slice"),f=e("../internals/get-json-replacer-function"),a=e("../internals/symbol-constructor-detection"),g=String,b=c("JSON","stringify"),u=t(/./.exec),w=t("".charAt),y=t("".charCodeAt),S=t("".replace),E=t(1 .toString),I=/[\uD800-\uDFFF]/g,P=/^[\uD800-\uDBFF]$/,F=/^[\uDC00-\uDFFF]$/,j=!a||i(function(){var J=c("Symbol")("stringify detection");return b([J])!=="[null]"||b({a:J})!=="{}"||b(Object(J))!=="{}"}),W=i(function(){return b("\uDF06\uD834")!=='"\\udf06\\ud834"'||b("\uDEAD")!=='"\\udead"'}),G=function(J,$){var M=o(arguments),T=f($);if(!(!r(T)&&(J===void 0||n(J))))return M[1]=function(x,A){if(r(T)&&(A=s(T,this,g(x),A)),!n(A))return A},h(b,null,M)},V=function(J,$,M){var T=w(M,$-1),x=w(M,$+1);return u(P,J)&&!u(F,x)||u(F,J)&&!u(P,T)?"\\u"+E(y(J,0),16):J};b&&l({target:"JSON",stat:!0,arity:3,forced:j||W},{stringify:function($,M,T){var x=o(arguments),A=h(j?G:b,null,x);return W&&typeof A=="string"?S(A,I,V):A}})},{"../internals/array-slice":231,"../internals/export":259,"../internals/fails":260,"../internals/function-apply":261,"../internals/function-call":264,"../internals/function-uncurry-this":268,"../internals/get-built-in":269,"../internals/get-json-replacer-function":272,"../internals/is-callable":285,"../internals/is-symbol":292,"../internals/symbol-constructor-detection":336}],363:[function(e,d,m){var l=e("../internals/export");l({target:"Number",stat:!0},{isNaN:function(h){return h!==h}})},{"../internals/export":259}],364:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/object-assign");l({target:"Object",stat:!0,arity:2,forced:Object.assign!==c},{assign:c})},{"../internals/export":259,"../internals/object-assign":305}],365:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/symbol-constructor-detection"),h=e("../internals/fails"),s=e("../internals/object-get-own-property-symbols"),t=e("../internals/to-object"),i=!c||h(function(){s.f(1)});l({target:"Object",stat:!0,forced:i},{getOwnPropertySymbols:function(n){var o=s.f;return o?o(t(n)):[]}})},{"../internals/export":259,"../internals/fails":260,"../internals/object-get-own-property-symbols":312,"../internals/symbol-constructor-detection":336,"../internals/to-object":344}],366:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/to-object"),h=e("../internals/object-keys"),s=e("../internals/fails"),t=s(function(){h(1)});l({target:"Object",stat:!0,forced:t},{keys:function(r){return h(c(r))}})},{"../internals/export":259,"../internals/fails":260,"../internals/object-keys":316,"../internals/to-object":344}],367:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/object-to-array").values;l({target:"Object",stat:!0},{values:function(s){return c(s)}})},{"../internals/export":259,"../internals/object-to-array":319}],368:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/function-call"),h=e("../internals/a-callable"),s=e("../internals/new-promise-capability"),t=e("../internals/perform"),i=e("../internals/iterate"),r=e("../internals/promise-statics-incorrect-iteration");l({target:"Promise",stat:!0,forced:r},{all:function(o){var f=this,a=s.f(f),g=a.resolve,b=a.reject,u=t(function(){var w=h(f.resolve),y=[],S=0,E=1;i(o,function(I){var P=S++,F=!1;E++,c(w,f,I).then(function(j){F||(F=!0,y[P]=j,--E||g(y))},b)}),--E||g(y)});return u.error&&b(u.value),a.promise}})},{"../internals/a-callable":222,"../internals/export":259,"../internals/function-call":264,"../internals/iterate":293,"../internals/new-promise-capability":303,"../internals/perform":323,"../internals/promise-statics-incorrect-iteration":327}],369:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/is-pure"),h=e("../internals/promise-constructor-detection").CONSTRUCTOR,s=e("../internals/promise-native-constructor"),t=e("../internals/get-built-in"),i=e("../internals/is-callable"),r=e("../internals/define-built-in"),n=s&&s.prototype;if(l({target:"Promise",proto:!0,forced:h,real:!0},{catch:function(f){return this.then(void 0,f)}}),!c&&i(s)){var o=t("Promise").prototype.catch;n.catch!==o&&r(n,"catch",o,{unsafe:!0})}},{"../internals/define-built-in":245,"../internals/export":259,"../internals/get-built-in":269,"../internals/is-callable":285,"../internals/is-pure":290,"../internals/promise-constructor-detection":324,"../internals/promise-native-constructor":325}],370:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/is-pure"),h=e("../internals/engine-is-node"),s=e("../internals/global"),t=e("../internals/function-call"),i=e("../internals/define-built-in"),r=e("../internals/object-set-prototype-of"),n=e("../internals/set-to-string-tag"),o=e("../internals/set-species"),f=e("../internals/a-callable"),a=e("../internals/is-callable"),g=e("../internals/is-object"),b=e("../internals/an-instance"),u=e("../internals/species-constructor"),w=e("../internals/task").set,y=e("../internals/microtask"),S=e("../internals/host-report-errors"),E=e("../internals/perform"),I=e("../internals/queue"),P=e("../internals/internal-state"),F=e("../internals/promise-native-constructor"),j=e("../internals/promise-constructor-detection"),W=e("../internals/new-promise-capability"),G="Promise",V=j.CONSTRUCTOR,J=j.REJECTION_EVENT,$=j.SUBCLASSING,M=P.getterFor(G),T=P.set,x=F&&F.prototype,A=F,N=x,L=s.TypeError,z=s.document,R=s.process,k=W.f,C=k,O=!!(z&&z.createEvent&&s.dispatchEvent),X="unhandledrejection",ie="rejectionhandled",he=0,ue=1,ke=2,pe=1,ee=2,Z,q,de,Me,ae=function(te){var se;return g(te)&&a(se=te.then)?se:!1},ne=function(te,se){var ve=se.value,Ee=se.state===ue,Ie=Ee?te.ok:te.fail,Te=te.resolve,Pe=te.reject,He=te.domain,me,Ce,Le;try{Ie?(Ee||(se.rejection===ee&&we(se),se.rejection=pe),Ie===!0?me=ve:(He&&He.enter(),me=Ie(ve),He&&(He.exit(),Le=!0)),me===te.promise?Pe(new L("Promise-chain cycle")):(Ce=ae(me))?t(Ce,me,Te,Pe):Te(me)):Pe(ve)}catch(ze){He&&!Le&&He.exit(),Pe(ze)}},Q=function(te,se){te.notified||(te.notified=!0,y(function(){for(var ve=te.reactions,Ee;Ee=ve.get();)ne(Ee,te);te.notified=!1,se&&!te.rejection&&Y(te)}))},H=function(te,se,ve){var Ee,Ie;O?(Ee=z.createEvent("Event"),Ee.promise=se,Ee.reason=ve,Ee.initEvent(te,!1,!0),s.dispatchEvent(Ee)):Ee={promise:se,reason:ve},!J&&(Ie=s["on"+te])?Ie(Ee):te===X&&S("Unhandled promise rejection",ve)},Y=function(te){t(w,s,function(){var se=te.facade,ve=te.value,Ee=le(te),Ie;if(Ee&&(Ie=E(function(){h?R.emit("unhandledRejection",ve,se):H(X,se,ve)}),te.rejection=h||le(te)?ee:pe,Ie.error))throw Ie.value})},le=function(te){return te.rejection!==pe&&!te.parent},we=function(te){t(w,s,function(){var se=te.facade;h?R.emit("rejectionHandled",se):H(ie,se,te.value)})},U=function(te,se,ve){return function(Ee){te(se,Ee,ve)}},ge=function(te,se,ve){te.done||(te.done=!0,ve&&(te=ve),te.value=se,te.state=ke,Q(te,!0))},Se=function(te,se,ve){if(!te.done){te.done=!0,ve&&(te=ve);try{if(te.facade===se)throw new L("Promise can't be resolved itself");var Ee=ae(se);Ee?y(function(){var Ie={done:!1};try{t(Ee,se,U(Se,Ie,te),U(ge,Ie,te))}catch(Te){ge(Ie,Te,te)}}):(te.value=se,te.state=ue,Q(te,!1))}catch(Ie){ge({done:!1},Ie,te)}}};if(V&&(A=function(se){b(this,N),f(se),t(Z,this);var ve=M(this);try{se(U(Se,ve),U(ge,ve))}catch(Ee){ge(ve,Ee)}},N=A.prototype,Z=function(se){T(this,{type:G,done:!1,notified:!1,parent:!1,reactions:new I,rejection:!1,state:he,value:void 0})},Z.prototype=i(N,"then",function(se,ve){var Ee=M(this),Ie=k(u(this,A));return Ee.parent=!0,Ie.ok=a(se)?se:!0,Ie.fail=a(ve)&&ve,Ie.domain=h?R.domain:void 0,Ee.state===he?Ee.reactions.add(Ie):y(function(){ne(Ie,Ee)}),Ie.promise}),q=function(){var te=new Z,se=M(te);this.promise=te,this.resolve=U(Se,se),this.reject=U(ge,se)},W.f=k=function(te){return te===A||te===de?new q(te):C(te)},!c&&a(F)&&x!==Object.prototype)){Me=x.then,$||i(x,"then",function(se,ve){var Ee=this;return new A(function(Ie,Te){t(Me,Ee,Ie,Te)}).then(se,ve)},{unsafe:!0});try{delete x.constructor}catch{}r&&r(x,N)}l({global:!0,constructor:!0,wrap:!0,forced:V},{Promise:A}),n(A,G,!1,!0),o(G)},{"../internals/a-callable":222,"../internals/an-instance":226,"../internals/define-built-in":245,"../internals/engine-is-node":254,"../internals/export":259,"../internals/function-call":264,"../internals/global":274,"../internals/host-report-errors":277,"../internals/internal-state":282,"../internals/is-callable":285,"../internals/is-object":289,"../internals/is-pure":290,"../internals/microtask":302,"../internals/new-promise-capability":303,"../internals/object-set-prototype-of":318,"../internals/perform":323,"../internals/promise-constructor-detection":324,"../internals/promise-native-constructor":325,"../internals/queue":328,"../internals/set-species":330,"../internals/set-to-string-tag":331,"../internals/species-constructor":335,"../internals/task":339}],371:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/is-pure"),h=e("../internals/promise-native-constructor"),s=e("../internals/fails"),t=e("../internals/get-built-in"),i=e("../internals/is-callable"),r=e("../internals/species-constructor"),n=e("../internals/promise-resolve"),o=e("../internals/define-built-in"),f=h&&h.prototype,a=!!h&&s(function(){f.finally.call({then:function(){}},function(){})});if(l({target:"Promise",proto:!0,real:!0,forced:a},{finally:function(b){var u=r(this,t("Promise")),w=i(b);return this.then(w?function(y){return n(u,b()).then(function(){return y})}:b,w?function(y){return n(u,b()).then(function(){throw y})}:b)}}),!c&&i(h)){var g=t("Promise").prototype.finally;f.finally!==g&&o(f,"finally",g,{unsafe:!0})}},{"../internals/define-built-in":245,"../internals/export":259,"../internals/fails":260,"../internals/get-built-in":269,"../internals/is-callable":285,"../internals/is-pure":290,"../internals/promise-native-constructor":325,"../internals/promise-resolve":326,"../internals/species-constructor":335}],372:[function(e,d,m){e("../modules/es.promise.constructor"),e("../modules/es.promise.all"),e("../modules/es.promise.catch"),e("../modules/es.promise.race"),e("../modules/es.promise.reject"),e("../modules/es.promise.resolve")},{"../modules/es.promise.all":368,"../modules/es.promise.catch":369,"../modules/es.promise.constructor":370,"../modules/es.promise.race":373,"../modules/es.promise.reject":374,"../modules/es.promise.resolve":375}],373:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/function-call"),h=e("../internals/a-callable"),s=e("../internals/new-promise-capability"),t=e("../internals/perform"),i=e("../internals/iterate"),r=e("../internals/promise-statics-incorrect-iteration");l({target:"Promise",stat:!0,forced:r},{race:function(o){var f=this,a=s.f(f),g=a.reject,b=t(function(){var u=h(f.resolve);i(o,function(w){c(u,f,w).then(a.resolve,g)})});return b.error&&g(b.value),a.promise}})},{"../internals/a-callable":222,"../internals/export":259,"../internals/function-call":264,"../internals/iterate":293,"../internals/new-promise-capability":303,"../internals/perform":323,"../internals/promise-statics-incorrect-iteration":327}],374:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/function-call"),h=e("../internals/new-promise-capability"),s=e("../internals/promise-constructor-detection").CONSTRUCTOR;l({target:"Promise",stat:!0,forced:s},{reject:function(i){var r=h.f(this);return c(r.reject,void 0,i),r.promise}})},{"../internals/export":259,"../internals/function-call":264,"../internals/new-promise-capability":303,"../internals/promise-constructor-detection":324}],375:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/get-built-in"),h=e("../internals/is-pure"),s=e("../internals/promise-native-constructor"),t=e("../internals/promise-constructor-detection").CONSTRUCTOR,i=e("../internals/promise-resolve"),r=c("Promise"),n=h&&!t;l({target:"Promise",stat:!0,forced:h||t},{resolve:function(f){return i(n&&this===r?s:this,f)}})},{"../internals/export":259,"../internals/get-built-in":269,"../internals/is-pure":290,"../internals/promise-constructor-detection":324,"../internals/promise-native-constructor":325,"../internals/promise-resolve":326}],376:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/function-uncurry-this"),h=e("../internals/to-absolute-index"),s=RangeError,t=String.fromCharCode,i=String.fromCodePoint,r=c([].join),n=!!i&&i.length!==1;l({target:"String",stat:!0,arity:1,forced:n},{fromCodePoint:function(f){for(var a=[],g=arguments.length,b=0,u;g>b;){if(u=+arguments[b++],h(u,1114111)!==u)throw new s(u+" is not a valid code point");a[b]=u<65536?t(u):t(((u-=65536)>>10)+55296,u%1024+56320)}return r(a,"")}})},{"../internals/export":259,"../internals/function-uncurry-this":268,"../internals/to-absolute-index":340}],377:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/function-uncurry-this"),h=e("../internals/not-a-regexp"),s=e("../internals/require-object-coercible"),t=e("../internals/to-string"),i=e("../internals/correct-is-regexp-logic"),r=c("".indexOf);l({target:"String",proto:!0,forced:!i("includes")},{includes:function(o){return!!~r(t(s(this)),t(h(o)),arguments.length>1?arguments[1]:void 0)}})},{"../internals/correct-is-regexp-logic":238,"../internals/export":259,"../internals/function-uncurry-this":268,"../internals/not-a-regexp":304,"../internals/require-object-coercible":329,"../internals/to-string":348}],378:[function(e,d,m){var l=e("../internals/well-known-symbol-define");l("asyncIterator")},{"../internals/well-known-symbol-define":355}],379:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/global"),h=e("../internals/function-call"),s=e("../internals/function-uncurry-this"),t=e("../internals/is-pure"),i=e("../internals/descriptors"),r=e("../internals/symbol-constructor-detection"),n=e("../internals/fails"),o=e("../internals/has-own-property"),f=e("../internals/object-is-prototype-of"),a=e("../internals/an-object"),g=e("../internals/to-indexed-object"),b=e("../internals/to-property-key"),u=e("../internals/to-string"),w=e("../internals/create-property-descriptor"),y=e("../internals/object-create"),S=e("../internals/object-keys"),E=e("../internals/object-get-own-property-names"),I=e("../internals/object-get-own-property-names-external"),P=e("../internals/object-get-own-property-symbols"),F=e("../internals/object-get-own-property-descriptor"),j=e("../internals/object-define-property"),W=e("../internals/object-define-properties"),G=e("../internals/object-property-is-enumerable"),V=e("../internals/define-built-in"),J=e("../internals/define-built-in-accessor"),$=e("../internals/shared"),M=e("../internals/shared-key"),T=e("../internals/hidden-keys"),x=e("../internals/uid"),A=e("../internals/well-known-symbol"),N=e("../internals/well-known-symbol-wrapped"),L=e("../internals/well-known-symbol-define"),z=e("../internals/symbol-define-to-primitive"),R=e("../internals/set-to-string-tag"),k=e("../internals/internal-state"),C=e("../internals/array-iteration").forEach,O=M("hidden"),X="Symbol",ie="prototype",he=k.set,ue=k.getterFor(X),ke=Object[ie],pe=c.Symbol,ee=pe&&pe[ie],Z=c.RangeError,q=c.TypeError,de=c.QObject,Me=F.f,ae=j.f,ne=I.f,Q=G.f,H=s([].push),Y=$("symbols"),le=$("op-symbols"),we=$("wks"),U=!de||!de[ie]||!de[ie].findChild,ge=function(me,Ce,Le){var ze=Me(ke,Ce);ze&&delete ke[Ce],ae(me,Ce,Le),ze&&me!==ke&&ae(ke,Ce,ze)},Se=i&&n(function(){return y(ae({},"a",{get:function(){return ae(this,"a",{value:7}).a}})).a!==7})?ge:ae,te=function(me,Ce){var Le=Y[me]=y(ee);return he(Le,{type:X,tag:me,description:Ce}),i||(Le.description=Ce),Le},se=function(Ce,Le,ze){Ce===ke&&se(le,Le,ze),a(Ce);var Ye=b(Le);return a(ze),o(Y,Ye)?(ze.enumerable?(o(Ce,O)&&Ce[O][Ye]&&(Ce[O][Ye]=!1),ze=y(ze,{enumerable:w(0,!1)})):(o(Ce,O)||ae(Ce,O,w(1,{})),Ce[O][Ye]=!0),Se(Ce,Ye,ze)):ae(Ce,Ye,ze)},ve=function(Ce,Le){a(Ce);var ze=g(Le),Ye=S(ze).concat(He(ze));return C(Ye,function(ot){(!i||h(Ie,ze,ot))&&se(Ce,ot,ze[ot])}),Ce},Ee=function(Ce,Le){return Le===void 0?y(Ce):ve(y(Ce),Le)},Ie=function(Ce){var Le=b(Ce),ze=h(Q,this,Le);return this===ke&&o(Y,Le)&&!o(le,Le)?!1:ze||!o(this,Le)||!o(Y,Le)||o(this,O)&&this[O][Le]?ze:!0},Te=function(Ce,Le){var ze=g(Ce),Ye=b(Le);if(!(ze===ke&&o(Y,Ye)&&!o(le,Ye))){var ot=Me(ze,Ye);return ot&&o(Y,Ye)&&!(o(ze,O)&&ze[O][Ye])&&(ot.enumerable=!0),ot}},Pe=function(Ce){var Le=ne(g(Ce)),ze=[];return C(Le,function(Ye){!o(Y,Ye)&&!o(T,Ye)&&H(ze,Ye)}),ze},He=function(me){var Ce=me===ke,Le=ne(Ce?le:g(me)),ze=[];return C(Le,function(Ye){o(Y,Ye)&&(!Ce||o(ke,Ye))&&H(ze,Y[Ye])}),ze};r||(pe=function(){if(f(ee,this))throw new q("Symbol is not a constructor");var Ce=!arguments.length||arguments[0]===void 0?void 0:u(arguments[0]),Le=x(Ce),ze=function(Ye){this===ke&&h(ze,le,Ye),o(this,O)&&o(this[O],Le)&&(this[O][Le]=!1);var ot=w(1,Ye);try{Se(this,Le,ot)}catch(pt){if(!(pt instanceof Z))throw pt;ge(this,Le,ot)}};return i&&U&&Se(ke,Le,{configurable:!0,set:ze}),te(Le,Ce)},ee=pe[ie],V(ee,"toString",function(){return ue(this).tag}),V(pe,"withoutSetter",function(me){return te(x(me),me)}),G.f=Ie,j.f=se,W.f=ve,F.f=Te,E.f=I.f=Pe,P.f=He,N.f=function(me){return te(A(me),me)},i&&(J(ee,"description",{configurable:!0,get:function(){return ue(this).description}}),t||V(ke,"propertyIsEnumerable",Ie,{unsafe:!0}))),l({global:!0,constructor:!0,wrap:!0,forced:!r,sham:!r},{Symbol:pe}),C(S(we),function(me){L(me)}),l({target:X,stat:!0,forced:!r},{useSetter:function(){U=!0},useSimple:function(){U=!1}}),l({target:"Object",stat:!0,forced:!r,sham:!i},{create:Ee,defineProperty:se,defineProperties:ve,getOwnPropertyDescriptor:Te}),l({target:"Object",stat:!0,forced:!r},{getOwnPropertyNames:Pe}),z(),R(pe,X),T[O]=!0},{"../internals/an-object":227,"../internals/array-iteration":229,"../internals/create-property-descriptor":242,"../internals/define-built-in":245,"../internals/define-built-in-accessor":244,"../internals/descriptors":247,"../internals/export":259,"../internals/fails":260,"../internals/function-call":264,"../internals/function-uncurry-this":268,"../internals/global":274,"../internals/has-own-property":275,"../internals/hidden-keys":276,"../internals/internal-state":282,"../internals/is-pure":290,"../internals/object-create":306,"../internals/object-define-properties":307,"../internals/object-define-property":308,"../internals/object-get-own-property-descriptor":309,"../internals/object-get-own-property-names":311,"../internals/object-get-own-property-names-external":310,"../internals/object-get-own-property-symbols":312,"../internals/object-is-prototype-of":314,"../internals/object-keys":316,"../internals/object-property-is-enumerable":317,"../internals/set-to-string-tag":331,"../internals/shared":334,"../internals/shared-key":332,"../internals/symbol-constructor-detection":336,"../internals/symbol-define-to-primitive":337,"../internals/to-indexed-object":341,"../internals/to-property-key":346,"../internals/to-string":348,"../internals/uid":350,"../internals/well-known-symbol":357,"../internals/well-known-symbol-define":355,"../internals/well-known-symbol-wrapped":356}],380:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/get-built-in"),h=e("../internals/has-own-property"),s=e("../internals/to-string"),t=e("../internals/shared"),i=e("../internals/symbol-registry-detection"),r=t("string-to-symbol-registry"),n=t("symbol-to-string-registry");l({target:"Symbol",stat:!0,forced:!i},{for:function(o){var f=s(o);if(h(r,f))return r[f];var a=c("Symbol")(f);return r[f]=a,n[a]=f,a}})},{"../internals/export":259,"../internals/get-built-in":269,"../internals/has-own-property":275,"../internals/shared":334,"../internals/symbol-registry-detection":338,"../internals/to-string":348}],381:[function(e,d,m){e("../modules/es.symbol.constructor"),e("../modules/es.symbol.for"),e("../modules/es.symbol.key-for"),e("../modules/es.json.stringify"),e("../modules/es.object.get-own-property-symbols")},{"../modules/es.json.stringify":362,"../modules/es.object.get-own-property-symbols":365,"../modules/es.symbol.constructor":379,"../modules/es.symbol.for":380,"../modules/es.symbol.key-for":382}],382:[function(e,d,m){var l=e("../internals/export"),c=e("../internals/has-own-property"),h=e("../internals/is-symbol"),s=e("../internals/try-to-string"),t=e("../internals/shared"),i=e("../internals/symbol-registry-detection"),r=t("symbol-to-string-registry");l({target:"Symbol",stat:!0,forced:!i},{keyFor:function(o){if(!h(o))throw new TypeError(s(o)+" is not a symbol");if(c(r,o))return r[o]}})},{"../internals/export":259,"../internals/has-own-property":275,"../internals/is-symbol":292,"../internals/shared":334,"../internals/symbol-registry-detection":338,"../internals/try-to-string":349}],383:[function(e,d,m){function l(y){return Array.isArray?Array.isArray(y):w(y)==="[object Array]"}m.isArray=l;function c(y){return typeof y=="boolean"}m.isBoolean=c;function h(y){return y===null}m.isNull=h;function s(y){return y==null}m.isNullOrUndefined=s;function t(y){return typeof y=="number"}m.isNumber=t;function i(y){return typeof y=="string"}m.isString=i;function r(y){return typeof y=="symbol"}m.isSymbol=r;function n(y){return y===void 0}m.isUndefined=n;function o(y){return w(y)==="[object RegExp]"}m.isRegExp=o;function f(y){return typeof y=="object"&&y!==null}m.isObject=f;function a(y){return w(y)==="[object Date]"}m.isDate=a;function g(y){return w(y)==="[object Error]"||y instanceof Error}m.isError=g;function b(y){return typeof y=="function"}m.isFunction=b;function u(y){return y===null||typeof y=="boolean"||typeof y=="number"||typeof y=="string"||typeof y=="symbol"||typeof y>"u"}m.isPrimitive=u,m.isBuffer=e("buffer").Buffer.isBuffer;function w(y){return Object.prototype.toString.call(y)}},{buffer:220}],384:[function(e,d,m){(function(l){(function(){var c=e("elliptic"),h=e("bn.js");d.exports=function(n){return new t(n)};var s={secp256k1:{name:"secp256k1",byteLength:32},secp224r1:{name:"p224",byteLength:28},prime256v1:{name:"p256",byteLength:32},prime192v1:{name:"p192",byteLength:24},ed25519:{name:"ed25519",byteLength:32},secp384r1:{name:"p384",byteLength:48},secp521r1:{name:"p521",byteLength:66}};s.p224=s.secp224r1,s.p256=s.secp256r1=s.prime256v1,s.p192=s.secp192r1=s.prime192v1,s.p384=s.secp384r1,s.p521=s.secp521r1;function t(r){this.curveType=s[r],this.curveType||(this.curveType={name:r}),this.curve=new c.ec(this.curveType.name),this.keys=void 0}t.prototype.generateKeys=function(r,n){return this.keys=this.curve.genKeyPair(),this.getPublicKey(r,n)},t.prototype.computeSecret=function(r,n,o){n=n||"utf8",l.isBuffer(r)||(r=new l(r,n));var f=this.curve.keyFromPublic(r).getPublic(),a=f.mul(this.keys.getPrivate()).getX();return i(a,o,this.curveType.byteLength)},t.prototype.getPublicKey=function(r,n){var o=this.keys.getPublic(n==="compressed",!0);return n==="hybrid"&&(o[o.length-1]%2?o[0]=7:o[0]=6),i(o,r)},t.prototype.getPrivateKey=function(r){return i(this.keys.getPrivate(),r)},t.prototype.setPublicKey=function(r,n){return n=n||"utf8",l.isBuffer(r)||(r=new l(r,n)),this.keys._importPublic(r),this},t.prototype.setPrivateKey=function(r,n){n=n||"utf8",l.isBuffer(r)||(r=new l(r,n));var o=new h(r);return o=o.toString(16),this.keys=this.curve.genKeyPair(),this.keys._importPrivate(o),this};function i(r,n,o){Array.isArray(r)||(r=r.toArray());var f=new l(r);if(o&&f.lengthg){var b=f==="rmd160"?new i:r(f);a=b.update(a).digest()}else a.lengtht?n=r(n):n.length=x?T:""+Array(x+1-N.length).join(A)+T},I={s:E,z:function(T){var x=-T.utcOffset(),A=Math.abs(x),N=Math.floor(A/60),L=A%60;return(x<=0?"+":"-")+E(N,2,"0")+":"+E(L,2,"0")},m:function T(x,A){if(x.date()1)return T(R[0])}else{var k=x.name;F[k]=x,L=k}return!N&&L&&(P=L),L||!N&&P},V=function(T,x){if(W(T))return T.clone();var A=typeof x=="object"?x:{};return A.date=T,A.args=arguments,new $(A)},J=I;J.l=G,J.i=W,J.w=function(T,x){return V(T,{locale:x.$L,utc:x.$u,x:x.$x,$offset:x.$offset})};var $=function(){function T(A){this.$L=G(A.locale,null,!0),this.parse(A),this.$x=this.$x||A.x||{},this[j]=!0}var x=T.prototype;return x.parse=function(A){this.$d=function(N){var L=N.date,z=N.utc;if(L===null)return new Date(NaN);if(J.u(L))return new Date;if(L instanceof Date)return new Date(L);if(typeof L=="string"&&!/Z$/i.test(L)){var R=L.match(w);if(R){var k=R[2]-1||0,C=(R[7]||"0").substring(0,3);return z?new Date(Date.UTC(R[1],k,R[3]||1,R[4]||0,R[5]||0,R[6]||0,C)):new Date(R[1],k,R[3]||1,R[4]||0,R[5]||0,R[6]||0,C)}}return new Date(L)}(A),this.init()},x.init=function(){var A=this.$d;this.$y=A.getFullYear(),this.$M=A.getMonth(),this.$D=A.getDate(),this.$W=A.getDay(),this.$H=A.getHours(),this.$m=A.getMinutes(),this.$s=A.getSeconds(),this.$ms=A.getMilliseconds()},x.$utils=function(){return J},x.isValid=function(){return this.$d.toString()!==u},x.isSame=function(A,N){var L=V(A);return this.startOf(N)<=L&&L<=this.endOf(N)},x.isAfter=function(A,N){return V(A)68?1900:2e3)},n=function(u){return function(w){this[u]=+w}},o=[/[+-]\d\d:?(\d\d)?|Z/,function(u){(this.zone||(this.zone={})).offset=function(w){if(!w||w==="Z")return 0;var y=w.match(/([+-]|\d\d)/g),S=60*y[1]+(+y[2]||0);return S===0?0:y[0]==="+"?-S:S}(u)}],f=function(u){var w=i[u];return w&&(w.indexOf?w:w.s.concat(w.f))},a=function(u,w){var y,S=i.meridiem;if(S){for(var E=1;E<=24;E+=1)if(u.indexOf(S(E,0,w))>-1){y=E>12;break}}else y=u===(w?"pm":"PM");return y},g={A:[t,function(u){this.afternoon=a(u,!1)}],a:[t,function(u){this.afternoon=a(u,!0)}],S:[/\d/,function(u){this.milliseconds=100*+u}],SS:[h,function(u){this.milliseconds=10*+u}],SSS:[/\d{3}/,function(u){this.milliseconds=+u}],s:[s,n("seconds")],ss:[s,n("seconds")],m:[s,n("minutes")],mm:[s,n("minutes")],H:[s,n("hours")],h:[s,n("hours")],HH:[s,n("hours")],hh:[s,n("hours")],D:[s,n("day")],DD:[h,n("day")],Do:[t,function(u){var w=i.ordinal,y=u.match(/\d+/);if(this.day=y[0],w)for(var S=1;S<=31;S+=1)w(S).replace(/\[|\]/g,"")===u&&(this.day=S)}],M:[s,n("month")],MM:[h,n("month")],MMM:[t,function(u){var w=f("months"),y=(f("monthsShort")||w.map(function(S){return S.slice(0,3)})).indexOf(u)+1;if(y<1)throw new Error;this.month=y%12||y}],MMMM:[t,function(u){var w=f("months").indexOf(u)+1;if(w<1)throw new Error;this.month=w%12||w}],Y:[/[+-]?\d+/,n("year")],YY:[h,function(u){this.year=r(u)}],YYYY:[/\d{4}/,n("year")],Z:o,ZZ:o};function b(u){var w,y;w=u,y=i&&i.formats;for(var S=(u=w.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,function(G,V,J){var $=J&&J.toUpperCase();return V||y[J]||l[J]||y[$].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,function(M,T,x){return T||x.slice(1)})})).match(c),E=S.length,I=0;I-1)return new Date((N==="X"?1e3:1)*A);var z=b(N)(A),R=z.year,k=z.month,C=z.day,O=z.hours,X=z.minutes,ie=z.seconds,he=z.milliseconds,ue=z.zone,ke=new Date,pe=C||(R||k?1:ke.getDate()),ee=R||ke.getFullYear(),Z=0;R&&!k||(Z=k>0?k-1:ke.getMonth());var q=O||0,de=X||0,Me=ie||0,ae=he||0;return ue?new Date(Date.UTC(ee,Z,pe,q,de,Me,ae+60*ue.offset*1e3)):L?new Date(Date.UTC(ee,Z,pe,q,de,Me,ae)):new Date(ee,Z,pe,q,de,Me,ae)}catch{return new Date("")}}(P,W,F),this.init(),$&&$!==!0&&(this.$L=this.locale($).$L),J&&P!=this.format(W)&&(this.$d=new Date("")),i={}}else if(W instanceof Array)for(var M=W.length,T=1;T<=M;T+=1){j[1]=W[T-1];var x=y.apply(this,j);if(x.isValid()){this.$d=x.$d,this.$L=x.$L,this.init();break}T===M&&(this.$d=new Date(""))}else E.call(this,I)}}})},{}],393:[function(e,d,m){(function(l,c){typeof m=="object"&&typeof d<"u"?d.exports=c():(l=typeof globalThis<"u"?globalThis:l||self).dayjs_plugin_utc=c()})(void 0,function(){var l="minute",c=/[+-]\d\d(?::?\d\d)?/g,h=/([+-]|\d\d)/g;return function(s,t,i){var r=t.prototype;i.utc=function(u){var w={date:u,utc:!0,args:arguments};return new t(w)},r.utc=function(u){var w=i(this.toDate(),{locale:this.$L,utc:!0});return u?w.add(this.utcOffset(),l):w},r.local=function(){return i(this.toDate(),{locale:this.$L,utc:!1})};var n=r.parse;r.parse=function(u){u.utc&&(this.$u=!0),this.$utils().u(u.$offset)||(this.$offset=u.$offset),n.call(this,u)};var o=r.init;r.init=function(){if(this.$u){var u=this.$d;this.$y=u.getUTCFullYear(),this.$M=u.getUTCMonth(),this.$D=u.getUTCDate(),this.$W=u.getUTCDay(),this.$H=u.getUTCHours(),this.$m=u.getUTCMinutes(),this.$s=u.getUTCSeconds(),this.$ms=u.getUTCMilliseconds()}else o.call(this)};var f=r.utcOffset;r.utcOffset=function(u,w){var y=this.$utils().u;if(y(u))return this.$u?0:y(this.$offset)?f.call(this):this.$offset;if(typeof u=="string"&&(u=function(P){P===void 0&&(P="");var F=P.match(c);if(!F)return null;var j=(""+F[0]).match(h)||["-",0,0],W=j[0],G=60*+j[1]+ +j[2];return G===0?0:W==="+"?G:-G}(u),u===null))return this;var S=Math.abs(u)<=16?60*u:u,E=this;if(w)return E.$offset=S,E.$u=u===0,E;if(u!==0){var I=this.$u?this.toDate().getTimezoneOffset():-1*this.utcOffset();(E=this.local().add(S+I,l)).$offset=S,E.$x.$localOffset=I}else E=this.utc();return E};var a=r.format;r.format=function(u){var w=u||(this.$u?"YYYY-MM-DDTHH:mm:ss[Z]":"");return a.call(this,w)},r.valueOf=function(){var u=this.$utils().u(this.$offset)?0:this.$offset+(this.$x.$localOffset||this.$d.getTimezoneOffset());return this.$d.valueOf()-6e4*u},r.isUTC=function(){return!!this.$u},r.toISOString=function(){return this.toDate().toISOString()},r.toString=function(){return this.toDate().toUTCString()};var g=r.toDate;r.toDate=function(u){return u==="s"&&this.$offset?i(this.format("YYYY-MM-DD HH:mm:ss:SSS")).toDate():g.call(this)};var b=r.diff;r.diff=function(u,w,y){if(u&&this.$u===u.$u)return b.call(this,u,w,y);var S=this.local(),E=i(u).local();return b.call(S,E,w,y)}}})},{}],394:[function(e,d,m){m.utils=e("./des/utils"),m.Cipher=e("./des/cipher"),m.DES=e("./des/des"),m.CBC=e("./des/cbc"),m.EDE=e("./des/ede")},{"./des/cbc":395,"./des/cipher":396,"./des/des":397,"./des/ede":398,"./des/utils":399}],395:[function(e,d,m){var l=e("minimalistic-assert"),c=e("inherits"),h={};function s(i){l.equal(i.length,8,"Invalid IV length"),this.iv=new Array(8);for(var r=0;r0;r--)t+=this._buffer(s,t),i+=this._flushBuffer(n,i);return t+=this._buffer(s,t),n},c.prototype.final=function(s){var t;s&&(t=this.update(s));var i;return this.type==="encrypt"?i=this._finalEncrypt():i=this._finalDecrypt(),t?t.concat(i):i},c.prototype._pad=function(s,t){if(t===0)return!1;for(;t>>1];a=h.r28shl(a,u),g=h.r28shl(g,u),h.pc2(a,g,o.keys,b)}},i.prototype._update=function(o,f,a,g){var b=this._desState,u=h.readUInt32BE(o,f),w=h.readUInt32BE(o,f+4);h.ip(u,w,b.tmp,0),u=b.tmp[0],w=b.tmp[1],this.type==="encrypt"?this._encrypt(b,u,w,b.tmp,0):this._decrypt(b,u,w,b.tmp,0),u=b.tmp[0],w=b.tmp[1],h.writeUInt32BE(a,u,g),h.writeUInt32BE(a,w,g+4)},i.prototype._pad=function(o,f){if(this.padding===!1)return!1;for(var a=o.length-f,g=f;g>>0,u=F}h.rip(w,u,g,b)},i.prototype._decrypt=function(o,f,a,g,b){for(var u=a,w=f,y=o.keys.length-2;y>=0;y-=2){var S=o.keys[y],E=o.keys[y+1];h.expand(u,o.tmp,0),S^=o.tmp[0],E^=o.tmp[1];var I=h.substitute(S,E),P=h.permute(I),F=u;u=(w^P)>>>0,w=F}h.rip(u,w,g,b)}},{"./cipher":396,"./utils":399,inherits:440,"minimalistic-assert":453}],398:[function(e,d,m){var l=e("minimalistic-assert"),c=e("inherits"),h=e("./cipher"),s=e("./des");function t(r,n){l.equal(n.length,24,"Invalid key length");var o=n.slice(0,8),f=n.slice(8,16),a=n.slice(16,24);r==="encrypt"?this.ciphers=[s.create({type:"encrypt",key:o}),s.create({type:"decrypt",key:f}),s.create({type:"encrypt",key:a})]:this.ciphers=[s.create({type:"decrypt",key:a}),s.create({type:"encrypt",key:f}),s.create({type:"decrypt",key:o})]}function i(r){h.call(this,r);var n=new t(this.type,this.options.key);this._edeState=n}c(i,h),d.exports=i,i.create=function(n){return new i(n)},i.prototype._update=function(n,o,f,a){var g=this._edeState;g.ciphers[0]._update(n,o,f,a),g.ciphers[1]._update(f,a,f,a),g.ciphers[2]._update(f,a,f,a)},i.prototype._pad=s.prototype._pad,i.prototype._unpad=s.prototype._unpad},{"./cipher":396,"./des":397,inherits:440,"minimalistic-assert":453}],399:[function(e,d,m){m.readUInt32BE=function(t,i){var r=t[0+i]<<24|t[1+i]<<16|t[2+i]<<8|t[3+i];return r>>>0},m.writeUInt32BE=function(t,i,r){t[0+r]=i>>>24,t[1+r]=i>>>16&255,t[2+r]=i>>>8&255,t[3+r]=i&255},m.ip=function(t,i,r,n){for(var o=0,f=0,a=6;a>=0;a-=2){for(var g=0;g<=24;g+=8)o<<=1,o|=i>>>g+a&1;for(var g=0;g<=24;g+=8)o<<=1,o|=t>>>g+a&1}for(var a=6;a>=0;a-=2){for(var g=1;g<=25;g+=8)f<<=1,f|=i>>>g+a&1;for(var g=1;g<=25;g+=8)f<<=1,f|=t>>>g+a&1}r[n+0]=o>>>0,r[n+1]=f>>>0},m.rip=function(t,i,r,n){for(var o=0,f=0,a=0;a<4;a++)for(var g=24;g>=0;g-=8)o<<=1,o|=i>>>g+a&1,o<<=1,o|=t>>>g+a&1;for(var a=4;a<8;a++)for(var g=24;g>=0;g-=8)f<<=1,f|=i>>>g+a&1,f<<=1,f|=t>>>g+a&1;r[n+0]=o>>>0,r[n+1]=f>>>0},m.pc1=function(t,i,r,n){for(var o=0,f=0,a=7;a>=5;a--){for(var g=0;g<=24;g+=8)o<<=1,o|=i>>g+a&1;for(var g=0;g<=24;g+=8)o<<=1,o|=t>>g+a&1}for(var g=0;g<=24;g+=8)o<<=1,o|=i>>g+a&1;for(var a=1;a<=3;a++){for(var g=0;g<=24;g+=8)f<<=1,f|=i>>g+a&1;for(var g=0;g<=24;g+=8)f<<=1,f|=t>>g+a&1}for(var g=0;g<=24;g+=8)f<<=1,f|=t>>g+a&1;r[n+0]=o>>>0,r[n+1]=f>>>0},m.r28shl=function(t,i){return t<>>28-i};var l=[14,11,17,4,27,23,25,0,13,22,7,18,5,9,16,24,2,20,12,21,1,8,15,26,15,4,25,19,9,1,26,16,5,11,23,8,12,7,17,0,22,3,10,14,6,20,27,24];m.pc2=function(t,i,r,n){for(var o=0,f=0,a=l.length>>>1,g=0;g>>l[g]&1;for(var g=a;g>>l[g]&1;r[n+0]=o>>>0,r[n+1]=f>>>0},m.expand=function(t,i,r){var n=0,o=0;n=(t&1)<<5|t>>>27;for(var f=23;f>=15;f-=4)n<<=6,n|=t>>>f&63;for(var f=11;f>=3;f-=4)o|=t>>>f&63,o<<=6;o|=(t&31)<<1|t>>>31,i[r+0]=n>>>0,i[r+1]=o>>>0};var c=[14,0,4,15,13,7,1,4,2,14,15,2,11,13,8,1,3,10,10,6,6,12,12,11,5,9,9,5,0,3,7,8,4,15,1,12,14,8,8,2,13,4,6,9,2,1,11,7,15,5,12,11,9,3,7,14,3,10,10,0,5,6,0,13,15,3,1,13,8,4,14,7,6,15,11,2,3,8,4,14,9,12,7,0,2,1,13,10,12,6,0,9,5,11,10,5,0,13,14,8,7,10,11,1,10,3,4,15,13,4,1,2,5,11,8,6,12,7,6,12,9,0,3,5,2,14,15,9,10,13,0,7,9,0,14,9,6,3,3,4,15,6,5,10,1,2,13,8,12,5,7,14,11,12,4,11,2,15,8,1,13,1,6,10,4,13,9,0,8,6,15,9,3,8,0,7,11,4,1,15,2,14,12,3,5,11,10,5,14,2,7,12,7,13,13,8,14,11,3,5,0,6,6,15,9,0,10,3,1,4,2,7,8,2,5,12,11,1,12,10,4,14,15,9,10,3,6,15,9,0,0,6,12,10,11,1,7,13,13,8,15,9,1,4,3,5,14,11,5,12,2,7,8,2,4,14,2,14,12,11,4,2,1,12,7,4,10,7,11,13,6,1,8,5,5,0,3,15,15,10,13,3,0,9,14,8,9,6,4,11,2,8,1,12,11,7,10,1,13,14,7,2,8,13,15,6,9,15,12,0,5,9,6,10,3,4,0,5,14,3,12,10,1,15,10,4,15,2,9,7,2,12,6,9,8,5,0,6,13,1,3,13,4,14,14,0,7,11,5,3,11,8,9,4,14,3,15,2,5,12,2,9,8,5,12,15,3,10,7,11,0,14,4,1,10,7,1,6,13,0,11,8,6,13,4,13,11,0,2,11,14,7,15,4,0,9,8,1,13,10,3,14,12,3,9,5,7,12,5,2,10,15,6,8,1,6,1,6,4,11,11,13,13,8,12,1,3,4,7,10,14,7,10,9,15,5,6,0,8,15,0,14,5,2,9,3,2,12,13,1,2,15,8,13,4,8,6,10,15,3,11,7,1,4,10,12,9,5,3,6,14,11,5,0,0,14,12,9,7,2,7,2,11,1,4,14,1,7,9,4,12,10,14,8,2,13,0,15,6,12,10,9,13,0,15,3,3,5,5,6,8,11];m.substitute=function(t,i){for(var r=0,n=0;n<4;n++){var o=t>>>18-n*6&63,f=c[n*64+o];r<<=4,r|=f}for(var n=0;n<4;n++){var o=i>>>18-n*6&63,f=c[4*64+n*64+o];r<<=4,r|=f}return r>>>0};var h=[16,25,12,11,3,20,4,15,31,17,9,6,27,14,1,22,30,24,8,18,0,5,29,23,13,19,2,26,10,21,28,7];m.permute=function(t){for(var i=0,r=0;r>>h[r]&1;return i>>>0},m.padSplit=function(t,i,r){for(var n=t.toString(2);n.lengthE;)P.ishrn(1);if(P.isEven()&&P.iadd(i),P.testn(1)||P.iadd(r),I.cmp(r)){if(!I.cmp(n))for(;P.mod(o).cmp(f);)P.iadd(g)}else for(;P.mod(h).cmp(a);)P.iadd(g);if(F=P.shrn(1),w(F)&&w(P)&&y(F)&&y(P)&&t.test(F)&&t.test(P))return P}}},{"bn.js":404,"miller-rabin":451,randombytes:475}],403:[function(e,d,m){d.exports={modp1:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff"},modp2:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff"},modp5:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff"},modp14:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff"},modp15:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff"},modp16:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff"},modp17:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff"},modp18:{gen:"02",prime:"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff"}}},{}],404:[function(e,d,m){arguments[4][184][0].apply(m,arguments)},{buffer:188,dup:184}],405:[function(e,d,m){var l=m;l.version=e("../package.json").version,l.utils=e("./elliptic/utils"),l.rand=e("brorand"),l.curve=e("./elliptic/curve"),l.curves=e("./elliptic/curves"),l.ec=e("./elliptic/ec"),l.eddsa=e("./elliptic/eddsa")},{"../package.json":421,"./elliptic/curve":408,"./elliptic/curves":411,"./elliptic/ec":412,"./elliptic/eddsa":415,"./elliptic/utils":419,brorand:187}],406:[function(e,d,m){var l=e("bn.js"),c=e("../utils"),h=c.getNAF,s=c.getJSF,t=c.assert;function i(n,o){this.type=n,this.p=new l(o.p,16),this.red=o.prime?l.red(o.prime):l.mont(this.p),this.zero=new l(0).toRed(this.red),this.one=new l(1).toRed(this.red),this.two=new l(2).toRed(this.red),this.n=o.n&&new l(o.n,16),this.g=o.g&&this.pointFromJSON(o.g,o.gRed),this._wnafT1=new Array(4),this._wnafT2=new Array(4),this._wnafT3=new Array(4),this._wnafT4=new Array(4),this._bitLength=this.n?this.n.bitLength():0;var f=this.n&&this.p.div(this.n);!f||f.cmpn(100)>0?this.redN=null:(this._maxwellTrick=!0,this.redN=this.n.toRed(this.red))}d.exports=i,i.prototype.point=function(){throw new Error("Not implemented")},i.prototype.validate=function(){throw new Error("Not implemented")},i.prototype._fixedNafMul=function(o,f){t(o.precomputed);var a=o._getDoubles(),g=h(f,1,this._bitLength),b=(1<=w;S--)y=(y<<1)+g[S];u.push(y)}for(var E=this.jpoint(null,null,null),I=this.jpoint(null,null,null),P=b;P>0;P--){for(w=0;w=0;y--){for(var S=0;y>=0&&u[y]===0;y--)S++;if(y>=0&&S++,w=w.dblp(S),y<0)break;var E=u[y];t(E!==0),o.type==="affine"?E>0?w=w.mixedAdd(b[E-1>>1]):w=w.mixedAdd(b[-E-1>>1].neg()):E>0?w=w.add(b[E-1>>1]):w=w.add(b[-E-1>>1].neg())}return o.type==="affine"?w.toP():w},i.prototype._wnafMulAdd=function(o,f,a,g,b){var u=this._wnafT1,w=this._wnafT2,y=this._wnafT3,S=0,E,I,P;for(E=0;E=1;E-=2){var j=E-1,W=E;if(u[j]!==1||u[W]!==1){y[j]=h(a[j],u[j],this._bitLength),y[W]=h(a[W],u[W],this._bitLength),S=Math.max(y[j].length,S),S=Math.max(y[W].length,S);continue}var G=[f[j],null,null,f[W]];f[j].y.cmp(f[W].y)===0?(G[1]=f[j].add(f[W]),G[2]=f[j].toJ().mixedAdd(f[W].neg())):f[j].y.cmp(f[W].y.redNeg())===0?(G[1]=f[j].toJ().mixedAdd(f[W]),G[2]=f[j].add(f[W].neg())):(G[1]=f[j].toJ().mixedAdd(f[W]),G[2]=f[j].toJ().mixedAdd(f[W].neg()));var V=[-3,-1,-5,-7,0,7,5,1,3],J=s(a[j],a[W]);for(S=Math.max(J[0].length,S),y[j]=new Array(S),y[W]=new Array(S),I=0;I=0;E--){for(var A=0;E>=0;){var N=!0;for(I=0;I=0&&A++,T=T.dblp(A),E<0)break;for(I=0;I0?P=w[I][L-1>>1]:L<0&&(P=w[I][-L-1>>1].neg()),P.type==="affine"?T=T.mixedAdd(P):T=T.add(P))}}for(E=0;E=Math.ceil((o.bitLength()+1)/f.step):!1},r.prototype._getDoubles=function(o,f){if(this.precomputed&&this.precomputed.doubles)return this.precomputed.doubles;for(var a=[this],g=this,b=0;b":""},r.prototype.isInfinity=function(){return this.x.cmpn(0)===0&&(this.y.cmp(this.z)===0||this.zOne&&this.y.cmp(this.curve.c)===0)},r.prototype._extDbl=function(){var o=this.x.redSqr(),f=this.y.redSqr(),a=this.z.redSqr();a=a.redIAdd(a);var g=this.curve._mulA(o),b=this.x.redAdd(this.y).redSqr().redISub(o).redISub(f),u=g.redAdd(f),w=u.redSub(a),y=g.redSub(f),S=b.redMul(w),E=u.redMul(y),I=b.redMul(y),P=w.redMul(u);return this.curve.point(S,E,P,I)},r.prototype._projDbl=function(){var o=this.x.redAdd(this.y).redSqr(),f=this.x.redSqr(),a=this.y.redSqr(),g,b,u,w,y,S;if(this.curve.twisted){w=this.curve._mulA(f);var E=w.redAdd(a);this.zOne?(g=o.redSub(f).redSub(a).redMul(E.redSub(this.curve.two)),b=E.redMul(w.redSub(a)),u=E.redSqr().redSub(E).redSub(E)):(y=this.z.redSqr(),S=E.redSub(y).redISub(y),g=o.redSub(f).redISub(a).redMul(S),b=E.redMul(w.redSub(a)),u=E.redMul(S))}else w=f.redAdd(a),y=this.curve._mulC(this.z).redSqr(),S=w.redSub(y).redSub(y),g=this.curve._mulC(o.redISub(w)).redMul(S),b=this.curve._mulC(w).redMul(f.redISub(a)),u=w.redMul(S);return this.curve.point(g,b,u)},r.prototype.dbl=function(){return this.isInfinity()?this:this.curve.extended?this._extDbl():this._projDbl()},r.prototype._extAdd=function(o){var f=this.y.redSub(this.x).redMul(o.y.redSub(o.x)),a=this.y.redAdd(this.x).redMul(o.y.redAdd(o.x)),g=this.t.redMul(this.curve.dd).redMul(o.t),b=this.z.redMul(o.z.redAdd(o.z)),u=a.redSub(f),w=b.redSub(g),y=b.redAdd(g),S=a.redAdd(f),E=u.redMul(w),I=y.redMul(S),P=u.redMul(S),F=w.redMul(y);return this.curve.point(E,I,F,P)},r.prototype._projAdd=function(o){var f=this.z.redMul(o.z),a=f.redSqr(),g=this.x.redMul(o.x),b=this.y.redMul(o.y),u=this.curve.d.redMul(g).redMul(b),w=a.redSub(u),y=a.redAdd(u),S=this.x.redAdd(this.y).redMul(o.x.redAdd(o.y)).redISub(g).redISub(b),E=f.redMul(w).redMul(S),I,P;return this.curve.twisted?(I=f.redMul(y).redMul(b.redSub(this.curve._mulA(g))),P=w.redMul(y)):(I=f.redMul(y).redMul(b.redSub(g)),P=this.curve._mulC(w).redMul(y)),this.curve.point(E,I,P)},r.prototype.add=function(o){return this.isInfinity()?o:o.isInfinity()?this:this.curve.extended?this._extAdd(o):this._projAdd(o)},r.prototype.mul=function(o){return this._hasDoubles(o)?this.curve._fixedNafMul(this,o):this.curve._wnafMul(this,o)},r.prototype.mulAdd=function(o,f,a){return this.curve._wnafMulAdd(1,[this,f],[o,a],2,!1)},r.prototype.jmulAdd=function(o,f,a){return this.curve._wnafMulAdd(1,[this,f],[o,a],2,!0)},r.prototype.normalize=function(){if(this.zOne)return this;var o=this.z.redInvm();return this.x=this.x.redMul(o),this.y=this.y.redMul(o),this.t&&(this.t=this.t.redMul(o)),this.z=this.curve.one,this.zOne=!0,this},r.prototype.neg=function(){return this.curve.point(this.x.redNeg(),this.y,this.z,this.t&&this.t.redNeg())},r.prototype.getX=function(){return this.normalize(),this.x.fromRed()},r.prototype.getY=function(){return this.normalize(),this.y.fromRed()},r.prototype.eq=function(o){return this===o||this.getX().cmp(o.getX())===0&&this.getY().cmp(o.getY())===0},r.prototype.eqXToP=function(o){var f=o.toRed(this.curve.red).redMul(this.z);if(this.x.cmp(f)===0)return!0;for(var a=o.clone(),g=this.curve.redN.redMul(this.z);;){if(a.iadd(this.curve.n),a.cmp(this.curve.p)>=0)return!1;if(f.redIAdd(g),this.x.cmp(f)===0)return!0}},r.prototype.toP=r.prototype.normalize,r.prototype.mixedAdd=r.prototype.add},{"../utils":419,"./base":406,"bn.js":420,inherits:440}],408:[function(e,d,m){var l=m;l.base=e("./base"),l.short=e("./short"),l.mont=e("./mont"),l.edwards=e("./edwards")},{"./base":406,"./edwards":407,"./mont":409,"./short":410}],409:[function(e,d,m){var l=e("bn.js"),c=e("inherits"),h=e("./base"),s=e("../utils");function t(r){h.call(this,"mont",r),this.a=new l(r.a,16).toRed(this.red),this.b=new l(r.b,16).toRed(this.red),this.i4=new l(4).toRed(this.red).redInvm(),this.two=new l(2).toRed(this.red),this.a24=this.i4.redMul(this.a.redAdd(this.two))}c(t,h),d.exports=t,t.prototype.validate=function(n){var o=n.normalize().x,f=o.redSqr(),a=f.redMul(o).redAdd(f.redMul(this.a)).redAdd(o),g=a.redSqrt();return g.redSqr().cmp(a)===0};function i(r,n,o){h.BasePoint.call(this,r,"projective"),n===null&&o===null?(this.x=this.curve.one,this.z=this.curve.zero):(this.x=new l(n,16),this.z=new l(o,16),this.x.red||(this.x=this.x.toRed(this.curve.red)),this.z.red||(this.z=this.z.toRed(this.curve.red)))}c(i,h.BasePoint),t.prototype.decodePoint=function(n,o){return this.point(s.toArray(n,o),1)},t.prototype.point=function(n,o){return new i(this,n,o)},t.prototype.pointFromJSON=function(n){return i.fromJSON(this,n)},i.prototype.precompute=function(){},i.prototype._encode=function(){return this.getX().toArray("be",this.curve.p.byteLength())},i.fromJSON=function(n,o){return new i(n,o[0],o[1]||n.one)},i.prototype.inspect=function(){return this.isInfinity()?"":""},i.prototype.isInfinity=function(){return this.z.cmpn(0)===0},i.prototype.dbl=function(){var n=this.x.redAdd(this.z),o=n.redSqr(),f=this.x.redSub(this.z),a=f.redSqr(),g=o.redSub(a),b=o.redMul(a),u=g.redMul(a.redAdd(this.curve.a24.redMul(g)));return this.curve.point(b,u)},i.prototype.add=function(){throw new Error("Not supported on Montgomery curve")},i.prototype.diffAdd=function(n,o){var f=this.x.redAdd(this.z),a=this.x.redSub(this.z),g=n.x.redAdd(n.z),b=n.x.redSub(n.z),u=b.redMul(f),w=g.redMul(a),y=o.z.redMul(u.redAdd(w).redSqr()),S=o.x.redMul(u.redISub(w).redSqr());return this.curve.point(y,S)},i.prototype.mul=function(n){for(var o=n.clone(),f=this,a=this.curve.point(null,null),g=this,b=[];o.cmpn(0)!==0;o.iushrn(1))b.push(o.andln(1));for(var u=b.length-1;u>=0;u--)b[u]===0?(f=f.diffAdd(a,g),a=a.dbl()):(a=f.diffAdd(a,g),f=f.dbl());return a},i.prototype.mulAdd=function(){throw new Error("Not supported on Montgomery curve")},i.prototype.jumlAdd=function(){throw new Error("Not supported on Montgomery curve")},i.prototype.eq=function(n){return this.getX().cmp(n.getX())===0},i.prototype.normalize=function(){return this.x=this.x.redMul(this.z.redInvm()),this.z=this.curve.one,this},i.prototype.getX=function(){return this.normalize(),this.x.fromRed()}},{"../utils":419,"./base":406,"bn.js":420,inherits:440}],410:[function(e,d,m){var l=e("../utils"),c=e("bn.js"),h=e("inherits"),s=e("./base"),t=l.assert;function i(o){s.call(this,"short",o),this.a=new c(o.a,16).toRed(this.red),this.b=new c(o.b,16).toRed(this.red),this.tinv=this.two.redInvm(),this.zeroA=this.a.fromRed().cmpn(0)===0,this.threeA=this.a.fromRed().sub(this.p).cmpn(-3)===0,this.endo=this._getEndomorphism(o),this._endoWnafT1=new Array(4),this._endoWnafT2=new Array(4)}h(i,s),d.exports=i,i.prototype._getEndomorphism=function(f){if(!(!this.zeroA||!this.g||!this.n||this.p.modn(3)!==1)){var a,g;if(f.beta)a=new c(f.beta,16).toRed(this.red);else{var b=this._getEndoRoots(this.p);a=b[0].cmp(b[1])<0?b[0]:b[1],a=a.toRed(this.red)}if(f.lambda)g=new c(f.lambda,16);else{var u=this._getEndoRoots(this.n);this.g.mul(u[0]).x.cmp(this.g.x.redMul(a))===0?g=u[0]:(g=u[1],t(this.g.mul(g).x.cmp(this.g.x.redMul(a))===0))}var w;return f.basis?w=f.basis.map(function(y){return{a:new c(y.a,16),b:new c(y.b,16)}}):w=this._getEndoBasis(g),{beta:a,lambda:g,basis:w}}},i.prototype._getEndoRoots=function(f){var a=f===this.p?this.red:c.mont(f),g=new c(2).toRed(a).redInvm(),b=g.redNeg(),u=new c(3).toRed(a).redNeg().redSqrt().redMul(g),w=b.redAdd(u).fromRed(),y=b.redSub(u).fromRed();return[w,y]},i.prototype._getEndoBasis=function(f){for(var a=this.n.ushrn(Math.floor(this.n.bitLength()/2)),g=f,b=this.n.clone(),u=new c(1),w=new c(0),y=new c(0),S=new c(1),E,I,P,F,j,W,G,V=0,J,$;g.cmpn(0)!==0;){var M=b.div(g);J=b.sub(M.mul(g)),$=y.sub(M.mul(u));var T=S.sub(M.mul(w));if(!P&&J.cmp(a)<0)E=G.neg(),I=u,P=J.neg(),F=$;else if(P&&++V===2)break;G=J,b=g,g=J,y=u,u=$,S=w,w=T}j=J.neg(),W=$;var x=P.sqr().add(F.sqr()),A=j.sqr().add(W.sqr());return A.cmp(x)>=0&&(j=E,W=I),P.negative&&(P=P.neg(),F=F.neg()),j.negative&&(j=j.neg(),W=W.neg()),[{a:P,b:F},{a:j,b:W}]},i.prototype._endoSplit=function(f){var a=this.endo.basis,g=a[0],b=a[1],u=b.b.mul(f).divRound(this.n),w=g.b.neg().mul(f).divRound(this.n),y=u.mul(g.a),S=w.mul(b.a),E=u.mul(g.b),I=w.mul(b.b),P=f.sub(y).sub(S),F=E.add(I).neg();return{k1:P,k2:F}},i.prototype.pointFromX=function(f,a){f=new c(f,16),f.red||(f=f.toRed(this.red));var g=f.redSqr().redMul(f).redIAdd(f.redMul(this.a)).redIAdd(this.b),b=g.redSqrt();if(b.redSqr().redSub(g).cmp(this.zero)!==0)throw new Error("invalid point");var u=b.fromRed().isOdd();return(a&&!u||!a&&u)&&(b=b.redNeg()),this.point(f,b)},i.prototype.validate=function(f){if(f.inf)return!0;var a=f.x,g=f.y,b=this.a.redMul(a),u=a.redSqr().redMul(a).redIAdd(b).redIAdd(this.b);return g.redSqr().redISub(u).cmpn(0)===0},i.prototype._endoWnafMulAdd=function(f,a,g){for(var b=this._endoWnafT1,u=this._endoWnafT2,w=0;w":""},r.prototype.isInfinity=function(){return this.inf},r.prototype.add=function(f){if(this.inf)return f;if(f.inf)return this;if(this.eq(f))return this.dbl();if(this.neg().eq(f))return this.curve.point(null,null);if(this.x.cmp(f.x)===0)return this.curve.point(null,null);var a=this.y.redSub(f.y);a.cmpn(0)!==0&&(a=a.redMul(this.x.redSub(f.x).redInvm()));var g=a.redSqr().redISub(this.x).redISub(f.x),b=a.redMul(this.x.redSub(g)).redISub(this.y);return this.curve.point(g,b)},r.prototype.dbl=function(){if(this.inf)return this;var f=this.y.redAdd(this.y);if(f.cmpn(0)===0)return this.curve.point(null,null);var a=this.curve.a,g=this.x.redSqr(),b=f.redInvm(),u=g.redAdd(g).redIAdd(g).redIAdd(a).redMul(b),w=u.redSqr().redISub(this.x.redAdd(this.x)),y=u.redMul(this.x.redSub(w)).redISub(this.y);return this.curve.point(w,y)},r.prototype.getX=function(){return this.x.fromRed()},r.prototype.getY=function(){return this.y.fromRed()},r.prototype.mul=function(f){return f=new c(f,16),this.isInfinity()?this:this._hasDoubles(f)?this.curve._fixedNafMul(this,f):this.curve.endo?this.curve._endoWnafMulAdd([this],[f]):this.curve._wnafMul(this,f)},r.prototype.mulAdd=function(f,a,g){var b=[this,a],u=[f,g];return this.curve.endo?this.curve._endoWnafMulAdd(b,u):this.curve._wnafMulAdd(1,b,u,2)},r.prototype.jmulAdd=function(f,a,g){var b=[this,a],u=[f,g];return this.curve.endo?this.curve._endoWnafMulAdd(b,u,!0):this.curve._wnafMulAdd(1,b,u,2,!0)},r.prototype.eq=function(f){return this===f||this.inf===f.inf&&(this.inf||this.x.cmp(f.x)===0&&this.y.cmp(f.y)===0)},r.prototype.neg=function(f){if(this.inf)return this;var a=this.curve.point(this.x,this.y.redNeg());if(f&&this.precomputed){var g=this.precomputed,b=function(u){return u.neg()};a.precomputed={naf:g.naf&&{wnd:g.naf.wnd,points:g.naf.points.map(b)},doubles:g.doubles&&{step:g.doubles.step,points:g.doubles.points.map(b)}}}return a},r.prototype.toJ=function(){if(this.inf)return this.curve.jpoint(null,null,null);var f=this.curve.jpoint(this.x,this.y,this.curve.one);return f};function n(o,f,a,g){s.BasePoint.call(this,o,"jacobian"),f===null&&a===null&&g===null?(this.x=this.curve.one,this.y=this.curve.one,this.z=new c(0)):(this.x=new c(f,16),this.y=new c(a,16),this.z=new c(g,16)),this.x.red||(this.x=this.x.toRed(this.curve.red)),this.y.red||(this.y=this.y.toRed(this.curve.red)),this.z.red||(this.z=this.z.toRed(this.curve.red)),this.zOne=this.z===this.curve.one}h(n,s.BasePoint),i.prototype.jpoint=function(f,a,g){return new n(this,f,a,g)},n.prototype.toP=function(){if(this.isInfinity())return this.curve.point(null,null);var f=this.z.redInvm(),a=f.redSqr(),g=this.x.redMul(a),b=this.y.redMul(a).redMul(f);return this.curve.point(g,b)},n.prototype.neg=function(){return this.curve.jpoint(this.x,this.y.redNeg(),this.z)},n.prototype.add=function(f){if(this.isInfinity())return f;if(f.isInfinity())return this;var a=f.z.redSqr(),g=this.z.redSqr(),b=this.x.redMul(a),u=f.x.redMul(g),w=this.y.redMul(a.redMul(f.z)),y=f.y.redMul(g.redMul(this.z)),S=b.redSub(u),E=w.redSub(y);if(S.cmpn(0)===0)return E.cmpn(0)!==0?this.curve.jpoint(null,null,null):this.dbl();var I=S.redSqr(),P=I.redMul(S),F=b.redMul(I),j=E.redSqr().redIAdd(P).redISub(F).redISub(F),W=E.redMul(F.redISub(j)).redISub(w.redMul(P)),G=this.z.redMul(f.z).redMul(S);return this.curve.jpoint(j,W,G)},n.prototype.mixedAdd=function(f){if(this.isInfinity())return f.toJ();if(f.isInfinity())return this;var a=this.z.redSqr(),g=this.x,b=f.x.redMul(a),u=this.y,w=f.y.redMul(a).redMul(this.z),y=g.redSub(b),S=u.redSub(w);if(y.cmpn(0)===0)return S.cmpn(0)!==0?this.curve.jpoint(null,null,null):this.dbl();var E=y.redSqr(),I=E.redMul(y),P=g.redMul(E),F=S.redSqr().redIAdd(I).redISub(P).redISub(P),j=S.redMul(P.redISub(F)).redISub(u.redMul(I)),W=this.z.redMul(y);return this.curve.jpoint(F,j,W)},n.prototype.dblp=function(f){if(f===0)return this;if(this.isInfinity())return this;if(!f)return this.dbl();var a;if(this.curve.zeroA||this.curve.threeA){var g=this;for(a=0;a=0)return!1;if(g.redIAdd(u),this.x.cmp(g)===0)return!0}},n.prototype.inspect=function(){return this.isInfinity()?"":""},n.prototype.isInfinity=function(){return this.z.cmpn(0)===0}},{"../utils":419,"./base":406,"bn.js":420,inherits:440}],411:[function(e,d,m){var l=m,c=e("hash.js"),h=e("./curve"),s=e("./utils"),t=s.assert;function i(o){o.type==="short"?this.curve=new h.short(o):o.type==="edwards"?this.curve=new h.edwards(o):this.curve=new h.mont(o),this.g=this.curve.g,this.n=this.curve.n,this.hash=o.hash,t(this.g.validate(),"Invalid curve"),t(this.g.mul(this.n).isInfinity(),"Invalid curve, G*N != O")}l.PresetCurve=i;function r(o,f){Object.defineProperty(l,o,{configurable:!0,enumerable:!0,get:function(){var a=new i(f);return Object.defineProperty(l,o,{configurable:!0,enumerable:!0,value:a}),a}})}r("p192",{type:"short",prime:"p192",p:"ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff",a:"ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc",b:"64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1",n:"ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831",hash:c.sha256,gRed:!1,g:["188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012","07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811"]}),r("p224",{type:"short",prime:"p224",p:"ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001",a:"ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe",b:"b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4",n:"ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d",hash:c.sha256,gRed:!1,g:["b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21","bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34"]}),r("p256",{type:"short",prime:null,p:"ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff",a:"ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc",b:"5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b",n:"ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551",hash:c.sha256,gRed:!1,g:["6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296","4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5"]}),r("p384",{type:"short",prime:null,p:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe ffffffff 00000000 00000000 ffffffff",a:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe ffffffff 00000000 00000000 fffffffc",b:"b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f 5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef",n:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 f4372ddf 581a0db2 48b0a77a ecec196a ccc52973",hash:c.sha384,gRed:!1,g:["aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7","3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 0a60b1ce 1d7e819d 7a431d7c 90ea0e5f"]}),r("p521",{type:"short",prime:null,p:"000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff",a:"000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffc",b:"00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b 99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd 3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00",n:"000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409",hash:c.sha512,gRed:!1,g:["000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66","00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 3fad0761 353c7086 a272c240 88be9476 9fd16650"]}),r("curve25519",{type:"mont",prime:"p25519",p:"7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed",a:"76d06",b:"1",n:"1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed",hash:c.sha256,gRed:!1,g:["9"]}),r("ed25519",{type:"edwards",prime:"p25519",p:"7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed",a:"-1",c:"1",d:"52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3",n:"1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed",hash:c.sha256,gRed:!1,g:["216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a","6666666666666666666666666666666666666666666666666666666666666658"]});var n;try{n=e("./precomputed/secp256k1")}catch{n=void 0}r("secp256k1",{type:"short",prime:"k256",p:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f",a:"0",b:"7",n:"ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141",h:"1",hash:c.sha256,beta:"7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee",lambda:"5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72",basis:[{a:"3086d221a7d46bcde86c90e49284eb15",b:"-e4437ed6010e88286f547fa90abfe4c3"},{a:"114ca50f7a8e2f3f657c1108d9d44cfd8",b:"3086d221a7d46bcde86c90e49284eb15"}],gRed:!1,g:["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",n]})},{"./curve":408,"./precomputed/secp256k1":418,"./utils":419,"hash.js":426}],412:[function(e,d,m){var l=e("bn.js"),c=e("hmac-drbg"),h=e("../utils"),s=e("../curves"),t=e("brorand"),i=h.assert,r=e("./key"),n=e("./signature");function o(f){if(!(this instanceof o))return new o(f);typeof f=="string"&&(i(Object.prototype.hasOwnProperty.call(s,f),"Unknown curve "+f),f=s[f]),f instanceof s.PresetCurve&&(f={curve:f}),this.curve=f.curve.curve,this.n=this.curve.n,this.nh=this.n.ushrn(1),this.g=this.curve.g,this.g=f.curve.g,this.g.precompute(f.curve.n.bitLength()+1),this.hash=f.hash||f.curve.hash}d.exports=o,o.prototype.keyPair=function(a){return new r(this,a)},o.prototype.keyFromPrivate=function(a,g){return r.fromPrivate(this,a,g)},o.prototype.keyFromPublic=function(a,g){return r.fromPublic(this,a,g)},o.prototype.genKeyPair=function(a){a||(a={});for(var g=new c({hash:this.hash,pers:a.pers,persEnc:a.persEnc||"utf8",entropy:a.entropy||t(this.hash.hmacStrength),entropyEnc:a.entropy&&a.entropyEnc||"utf8",nonce:this.n.toArray()}),b=this.n.byteLength(),u=this.n.sub(new l(2));;){var w=new l(g.generate(b));if(!(w.cmp(u)>0))return w.iaddn(1),this.keyFromPrivate(w)}},o.prototype._truncateToN=function(a,g){var b=a.byteLength()*8-this.n.bitLength();return b>0&&(a=a.ushrn(b)),!g&&a.cmp(this.n)>=0?a.sub(this.n):a},o.prototype.sign=function(a,g,b,u){typeof b=="object"&&(u=b,b=null),u||(u={}),g=this.keyFromPrivate(g,b),a=this._truncateToN(new l(a,16));for(var w=this.n.byteLength(),y=g.getPrivate().toArray("be",w),S=a.toArray("be",w),E=new c({hash:this.hash,entropy:y,nonce:S,pers:u.pers,persEnc:u.persEnc||"utf8"}),I=this.n.sub(new l(1)),P=0;;P++){var F=u.k?u.k(P):new l(E.generate(this.n.byteLength()));if(F=this._truncateToN(F,!0),!(F.cmpn(1)<=0||F.cmp(I)>=0)){var j=this.g.mul(F);if(!j.isInfinity()){var W=j.getX(),G=W.umod(this.n);if(G.cmpn(0)!==0){var V=F.invm(this.n).mul(G.mul(g.getPrivate()).iadd(a));if(V=V.umod(this.n),V.cmpn(0)!==0){var J=(j.getY().isOdd()?1:0)|(W.cmp(G)!==0?2:0);return u.canonical&&V.cmp(this.nh)>0&&(V=this.n.sub(V),J^=1),new n({r:G,s:V,recoveryParam:J})}}}}}},o.prototype.verify=function(a,g,b,u){a=this._truncateToN(new l(a,16)),b=this.keyFromPublic(b,u),g=new n(g,"hex");var w=g.r,y=g.s;if(w.cmpn(1)<0||w.cmp(this.n)>=0||y.cmpn(1)<0||y.cmp(this.n)>=0)return!1;var S=y.invm(this.n),E=S.mul(a).umod(this.n),I=S.mul(w).umod(this.n),P;return this.curve._maxwellTrick?(P=this.g.jmulAdd(E,b.getPublic(),I),P.isInfinity()?!1:P.eqXToP(w)):(P=this.g.mulAdd(E,b.getPublic(),I),P.isInfinity()?!1:P.getX().umod(this.n).cmp(w)===0)},o.prototype.recoverPubKey=function(f,a,g,b){i((3&g)===g,"The recovery param is more than two bits"),a=new n(a,b);var u=this.n,w=new l(f),y=a.r,S=a.s,E=g&1,I=g>>1;if(y.cmp(this.curve.p.umod(this.curve.n))>=0&&I)throw new Error("Unable to find sencond key candinate");I?y=this.curve.pointFromX(y.add(this.curve.n),E):y=this.curve.pointFromX(y,E);var P=a.r.invm(u),F=u.sub(w).mul(P).umod(u),j=S.mul(P).umod(u);return this.g.mulAdd(F,y,j)},o.prototype.getKeyRecoveryParam=function(f,a,g,b){if(a=new n(a,b),a.recoveryParam!==null)return a.recoveryParam;for(var u=0;u<4;u++){var w;try{w=this.recoverPubKey(f,a,u)}catch{continue}if(w.eq(g))return u}throw new Error("Unable to find valid recovery factor")}},{"../curves":411,"../utils":419,"./key":413,"./signature":414,"bn.js":420,brorand:187,"hmac-drbg":438}],413:[function(e,d,m){var l=e("bn.js"),c=e("../utils"),h=c.assert;function s(t,i){this.ec=t,this.priv=null,this.pub=null,i.priv&&this._importPrivate(i.priv,i.privEnc),i.pub&&this._importPublic(i.pub,i.pubEnc)}d.exports=s,s.fromPublic=function(i,r,n){return r instanceof s?r:new s(i,{pub:r,pubEnc:n})},s.fromPrivate=function(i,r,n){return r instanceof s?r:new s(i,{priv:r,privEnc:n})},s.prototype.validate=function(){var i=this.getPublic();return i.isInfinity()?{result:!1,reason:"Invalid public key"}:i.validate()?i.mul(this.ec.curve.n).isInfinity()?{result:!0,reason:null}:{result:!1,reason:"Public key * N != O"}:{result:!1,reason:"Public key is not a point"}},s.prototype.getPublic=function(i,r){return typeof i=="string"&&(r=i,i=null),this.pub||(this.pub=this.ec.g.mul(this.priv)),r?this.pub.encode(r,i):this.pub},s.prototype.getPrivate=function(i){return i==="hex"?this.priv.toString(16,2):this.priv},s.prototype._importPrivate=function(i,r){this.priv=new l(i,r||16),this.priv=this.priv.umod(this.ec.curve.n)},s.prototype._importPublic=function(i,r){if(i.x||i.y){this.ec.curve.type==="mont"?h(i.x,"Need x coordinate"):(this.ec.curve.type==="short"||this.ec.curve.type==="edwards")&&h(i.x&&i.y,"Need both x and y coordinate"),this.pub=this.ec.curve.point(i.x,i.y);return}this.pub=this.ec.curve.decodePoint(i,r)},s.prototype.derive=function(i){return i.validate()||h(i.validate(),"public point not validated"),i.mul(this.priv).getX()},s.prototype.sign=function(i,r,n){return this.ec.sign(i,this,r,n)},s.prototype.verify=function(i,r){return this.ec.verify(i,r,this)},s.prototype.inspect=function(){return""}},{"../utils":419,"bn.js":420}],414:[function(e,d,m){var l=e("bn.js"),c=e("../utils"),h=c.assert;function s(o,f){if(o instanceof s)return o;this._importDER(o,f)||(h(o.r&&o.s,"Signature without r or s"),this.r=new l(o.r,16),this.s=new l(o.s,16),o.recoveryParam===void 0?this.recoveryParam=null:this.recoveryParam=o.recoveryParam)}d.exports=s;function t(){this.place=0}function i(o,f){var a=o[f.place++];if(!(a&128))return a;var g=a&15;if(g===0||g>4)return!1;for(var b=0,u=0,w=f.place;u>>=0;return b<=127?!1:(f.place=w,b)}function r(o){for(var f=0,a=o.length-1;!o[f]&&!(o[f+1]&128)&&f>>3);for(o.push(a|128);--a;)o.push(f>>>(a<<3)&255);o.push(f)}s.prototype.toDER=function(f){var a=this.r.toArray(),g=this.s.toArray();for(a[0]&128&&(a=[0].concat(a)),g[0]&128&&(g=[0].concat(g)),a=r(a),g=r(g);!g[0]&&!(g[1]&128);)g=g.slice(1);var b=[2];n(b,a.length),b=b.concat(a),b.push(2),n(b,g.length);var u=b.concat(g),w=[48];return n(w,u.length),w=w.concat(u),c.encode(w,f)}},{"../utils":419,"bn.js":420}],415:[function(e,d,m){var l=e("hash.js"),c=e("../curves"),h=e("../utils"),s=h.assert,t=h.parseBytes,i=e("./key"),r=e("./signature");function n(o){if(s(o==="ed25519","only tested with ed25519 so far"),!(this instanceof n))return new n(o);o=c[o].curve,this.curve=o,this.g=o.g,this.g.precompute(o.n.bitLength()+1),this.pointClass=o.point().constructor,this.encodingLength=Math.ceil(o.n.bitLength()/8),this.hash=l.sha512}d.exports=n,n.prototype.sign=function(f,a){f=t(f);var g=this.keyFromSecret(a),b=this.hashInt(g.messagePrefix(),f),u=this.g.mul(b),w=this.encodePoint(u),y=this.hashInt(w,g.pubBytes(),f).mul(g.priv()),S=b.add(y).umod(this.curve.n);return this.makeSignature({R:u,S,Rencoded:w})},n.prototype.verify=function(f,a,g){f=t(f),a=this.makeSignature(a);var b=this.keyFromPublic(g),u=this.hashInt(a.Rencoded(),b.pubBytes(),f),w=this.g.mul(a.S()),y=a.R().add(b.pub().mul(u));return y.eq(w)},n.prototype.hashInt=function(){for(var f=this.hash(),a=0;a(u>>1)-1?S=(u>>1)-E:S=E,w.isubn(S)):S=0,b[y]=S,w.iushrn(1)}return b}l.getNAF=t;function i(f,a){var g=[[],[]];f=f.clone(),a=a.clone();for(var b=0,u=0,w;f.cmpn(-b)>0||a.cmpn(-u)>0;){var y=f.andln(3)+b&3,S=a.andln(3)+u&3;y===3&&(y=-1),S===3&&(S=-1);var E;y&1?(w=f.andln(7)+b&7,(w===3||w===5)&&S===2?E=-y:E=y):E=0,g[0].push(E);var I;S&1?(w=a.andln(7)+u&7,(w===3||w===5)&&y===2?I=-S:I=S):I=0,g[1].push(I),2*b===E+1&&(b=1-b),2*u===I+1&&(u=1-u),f.iushrn(1),a.iushrn(1)}return g}l.getJSF=i;function r(f,a,g){var b="_"+a;f.prototype[a]=function(){return this[b]!==void 0?this[b]:this[b]=g.call(this)}}l.cachedProperty=r;function n(f){return typeof f=="string"?l.toArray(f,"hex"):f}l.parseBytes=n;function o(f){return new c(f,"hex","le")}l.intFromLE=o},{"bn.js":420,"minimalistic-assert":453,"minimalistic-crypto-utils":454}],420:[function(e,d,m){arguments[4][184][0].apply(m,arguments)},{buffer:188,dup:184}],421:[function(e,d,m){d.exports={name:"elliptic",version:"6.5.4",description:"EC cryptography",main:"lib/elliptic.js",files:["lib"],scripts:{lint:"eslint lib test","lint:fix":"npm run lint -- --fix",unit:"istanbul test _mocha --reporter=spec test/index.js",test:"npm run lint && npm run unit",version:"grunt dist && git add dist/"},repository:{type:"git",url:"git@github.com:indutny/elliptic"},keywords:["EC","Elliptic","curve","Cryptography"],author:"Fedor Indutny ",license:"MIT",bugs:{url:"https://github.com/indutny/elliptic/issues"},homepage:"https://github.com/indutny/elliptic",devDependencies:{brfs:"^2.0.2",coveralls:"^3.1.0",eslint:"^7.6.0",grunt:"^1.2.1","grunt-browserify":"^5.3.0","grunt-cli":"^1.3.2","grunt-contrib-connect":"^3.0.0","grunt-contrib-copy":"^1.0.0","grunt-contrib-uglify":"^5.0.0","grunt-mocha-istanbul":"^5.0.2","grunt-saucelabs":"^9.0.1",istanbul:"^0.4.5",mocha:"^8.0.1"},dependencies:{"bn.js":"^4.11.9",brorand:"^1.1.0","hash.js":"^1.0.0","hmac-drbg":"^1.0.1",inherits:"^2.0.4","minimalistic-assert":"^1.0.1","minimalistic-crypto-utils":"^1.0.1"}}},{}],422:[function(e,d,m){var l=Object.create||j,c=Object.keys||W,h=Function.prototype.bind||G;function s(){(!this._events||!Object.prototype.hasOwnProperty.call(this,"_events"))&&(this._events=l(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0}d.exports=s,s.EventEmitter=s,s.prototype._events=void 0,s.prototype._maxListeners=void 0;var t=10,i;try{var r={};Object.defineProperty&&Object.defineProperty(r,"x",{value:0}),i=r.x===0}catch{i=!1}i?Object.defineProperty(s,"defaultMaxListeners",{enumerable:!0,get:function(){return t},set:function(V){if(typeof V!="number"||V<0||V!==V)throw new TypeError('"defaultMaxListeners" must be a positive number');t=V}}):s.defaultMaxListeners=t,s.prototype.setMaxListeners=function(J){if(typeof J!="number"||J<0||isNaN(J))throw new TypeError('"n" argument must be a positive number');return this._maxListeners=J,this};function n(V){return V._maxListeners===void 0?s.defaultMaxListeners:V._maxListeners}s.prototype.getMaxListeners=function(){return n(this)};function o(V,J,$){if(J)V.call($);else for(var M=V.length,T=P(V,M),x=0;x1&&($=arguments[1]),$ instanceof Error)throw $;var z=new Error('Unhandled "error" event. ('+$+")");throw z.context=$,z}if(M=N[J],!M)return!1;var R=typeof M=="function";switch(T=arguments.length,T){case 1:o(M,R,this);break;case 2:f(M,R,this,arguments[1]);break;case 3:a(M,R,this,arguments[1],arguments[2]);break;case 4:g(M,R,this,arguments[1],arguments[2],arguments[3]);break;default:for(x=new Array(T-1),A=1;A0&&A.length>T)){A.warned=!0;var N=new Error("Possible EventEmitter memory leak detected. "+A.length+' "'+String(J)+'" listeners added. Use emitter.setMaxListeners() to increase limit.');N.name="MaxListenersExceededWarning",N.emitter=V,N.type=J,N.count=A.length,typeof console=="object"&&console.warn&&console.warn("%s: %s",N.name,N.message)}return V}s.prototype.addListener=function(J,$){return u(this,J,$,!1)},s.prototype.on=s.prototype.addListener,s.prototype.prependListener=function(J,$){return u(this,J,$,!0)};function w(){if(!this.fired)switch(this.target.removeListener(this.type,this.wrapFn),this.fired=!0,arguments.length){case 0:return this.listener.call(this.target);case 1:return this.listener.call(this.target,arguments[0]);case 2:return this.listener.call(this.target,arguments[0],arguments[1]);case 3:return this.listener.call(this.target,arguments[0],arguments[1],arguments[2]);default:for(var V=new Array(arguments.length),J=0;J=0;A--)if(M[A]===$||M[A].listener===$){N=M[A].listener,x=A;break}if(x<0)return this;x===0?M.shift():I(M,x),M.length===1&&(T[J]=M[0]),T.removeListener&&this.emit("removeListener",J,N||$)}return this},s.prototype.removeAllListeners=function(J){var $,M,T;if(M=this._events,!M)return this;if(!M.removeListener)return arguments.length===0?(this._events=l(null),this._eventsCount=0):M[J]&&(--this._eventsCount===0?this._events=l(null):delete M[J]),this;if(arguments.length===0){var x=c(M),A;for(T=0;T=0;T--)this.removeListener(J,$[T]);return this};function S(V,J,$){var M=V._events;if(!M)return[];var T=M[J];return T?typeof T=="function"?$?[T.listener||T]:[T]:$?F(T):P(T,T.length):[]}s.prototype.listeners=function(J){return S(this,J,!0)},s.prototype.rawListeners=function(J){return S(this,J,!1)},s.listenerCount=function(V,J){return typeof V.listenerCount=="function"?V.listenerCount(J):E.call(V,J)},s.prototype.listenerCount=E;function E(V){var J=this._events;if(J){var $=J[V];if(typeof $=="function")return 1;if($)return $.length}return 0}s.prototype.eventNames=function(){return this._eventsCount>0?Reflect.ownKeys(this._events):[]};function I(V,J){for(var $=J,M=$+1,T=V.length;M0||r>0;){var g=new c;g.update(a),g.update(s),t&&g.update(t),a=g.digest();var b=0;if(n>0){var u=o.length-n;b=Math.min(n,a.length),a.copy(o,u,0,b),n-=b}if(b0){var w=f.length-r,y=Math.min(r,a.length-b);a.copy(f,w,b,b+y),r-=y}}return a.fill(0),{key:o,iv:f}}d.exports=h},{"md5.js":450,"safe-buffer":494}],424:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.CsvParserStream=m.ParserOptions=m.parseFile=m.parseStream=m.parseString=m.parse=m.FormatterOptions=m.CsvFormatterStream=m.writeToPath=m.writeToString=m.writeToBuffer=m.writeToStream=m.write=m.format=void 0;var l=e("@fast-csv/format");Object.defineProperty(m,"format",{enumerable:!0,get:function(){return l.format}}),Object.defineProperty(m,"write",{enumerable:!0,get:function(){return l.write}}),Object.defineProperty(m,"writeToStream",{enumerable:!0,get:function(){return l.writeToStream}}),Object.defineProperty(m,"writeToBuffer",{enumerable:!0,get:function(){return l.writeToBuffer}}),Object.defineProperty(m,"writeToString",{enumerable:!0,get:function(){return l.writeToString}}),Object.defineProperty(m,"writeToPath",{enumerable:!0,get:function(){return l.writeToPath}}),Object.defineProperty(m,"CsvFormatterStream",{enumerable:!0,get:function(){return l.CsvFormatterStream}}),Object.defineProperty(m,"FormatterOptions",{enumerable:!0,get:function(){return l.FormatterOptions}});var c=e("@fast-csv/parse");Object.defineProperty(m,"parse",{enumerable:!0,get:function(){return c.parse}}),Object.defineProperty(m,"parseString",{enumerable:!0,get:function(){return c.parseString}}),Object.defineProperty(m,"parseStream",{enumerable:!0,get:function(){return c.parseStream}}),Object.defineProperty(m,"parseFile",{enumerable:!0,get:function(){return c.parseFile}}),Object.defineProperty(m,"ParserOptions",{enumerable:!0,get:function(){return c.ParserOptions}}),Object.defineProperty(m,"CsvParserStream",{enumerable:!0,get:function(){return c.CsvParserStream}})},{"@fast-csv/format":151,"@fast-csv/parse":155}],425:[function(e,d,m){var l=e("safe-buffer").Buffer,c=e("readable-stream").Transform,h=e("inherits");function s(i,r){if(!l.isBuffer(i)&&typeof i!="string")throw new TypeError(r+" must be a string or a buffer")}function t(i){c.call(this),this._block=l.allocUnsafe(i),this._blockSize=i,this._blockOffset=0,this._length=[0,0,0,0],this._finalized=!1}h(t,c),t.prototype._transform=function(i,r,n){var o=null;try{this.update(i,r)}catch(f){o=f}n(o)},t.prototype._flush=function(i){var r=null;try{this.push(this.digest())}catch(n){r=n}i(r)},t.prototype.update=function(i,r){if(s(i,"Data"),this._finalized)throw new Error("Digest already called");l.isBuffer(i)||(i=l.from(i,r));for(var n=this._block,o=0;this._blockOffset+i.length-o>=this._blockSize;){for(var f=this._blockOffset;f0;++a)this._length[a]+=g,g=this._length[a]/4294967296|0,g>0&&(this._length[a]-=4294967296*g);return this},t.prototype._update=function(){throw new Error("_update is not implemented")},t.prototype.digest=function(i){if(this._finalized)throw new Error("Digest already called");this._finalized=!0;var r=this._digest();i!==void 0&&(r=r.toString(i)),this._block.fill(0),this._blockOffset=0;for(var n=0;n<4;++n)this._length[n]=0;return r},t.prototype._digest=function(){throw new Error("_digest is not implemented")},d.exports=t},{inherits:440,"readable-stream":491,"safe-buffer":494}],426:[function(e,d,m){var l=m;l.utils=e("./hash/utils"),l.common=e("./hash/common"),l.sha=e("./hash/sha"),l.ripemd=e("./hash/ripemd"),l.hmac=e("./hash/hmac"),l.sha1=l.sha.sha1,l.sha256=l.sha.sha256,l.sha224=l.sha.sha224,l.sha384=l.sha.sha384,l.sha512=l.sha.sha512,l.ripemd160=l.ripemd.ripemd160},{"./hash/common":427,"./hash/hmac":428,"./hash/ripemd":429,"./hash/sha":430,"./hash/utils":437}],427:[function(e,d,m){var l=e("./utils"),c=e("minimalistic-assert");function h(){this.pending=null,this.pendingTotal=0,this.blockSize=this.constructor.blockSize,this.outSize=this.constructor.outSize,this.hmacStrength=this.constructor.hmacStrength,this.padLength=this.constructor.padLength/8,this.endian="big",this._delta8=this.blockSize/8,this._delta32=this.blockSize/32}m.BlockHash=h,h.prototype.update=function(t,i){if(t=l.toArray(t,i),this.pending?this.pending=this.pending.concat(t):this.pending=t,this.pendingTotal+=t.length,this.pending.length>=this._delta8){t=this.pending;var r=t.length%this._delta8;this.pending=t.slice(t.length-r,t.length),this.pending.length===0&&(this.pending=null),t=l.join32(t,0,t.length-r,this.endian);for(var n=0;n>>24&255,n[o++]=t>>>16&255,n[o++]=t>>>8&255,n[o++]=t&255}else for(n[o++]=t&255,n[o++]=t>>>8&255,n[o++]=t>>>16&255,n[o++]=t>>>24&255,n[o++]=0,n[o++]=0,n[o++]=0,n[o++]=0,f=8;fthis.blockSize&&(t=new this.Hash().update(t).digest()),c(t.length<=this.blockSize);for(var i=t.length;i>>3}m.g0_256=o;function f(a){return c(a,17)^c(a,19)^a>>>10}m.g1_256=f},{"../utils":437}],437:[function(e,d,m){var l=e("minimalistic-assert"),c=e("inherits");m.inherits=c;function h(T,x){return(T.charCodeAt(x)&64512)!==55296||x<0||x+1>=T.length?!1:(T.charCodeAt(x+1)&64512)===56320}function s(T,x){if(Array.isArray(T))return T.slice();if(!T)return[];var A=[];if(typeof T=="string")if(x){if(x==="hex")for(T=T.replace(/[^a-z0-9]+/ig,""),T.length%2!==0&&(T="0"+T),L=0;L>6|192,A[N++]=z&63|128):h(T,L)?(z=65536+((z&1023)<<10)+(T.charCodeAt(++L)&1023),A[N++]=z>>18|240,A[N++]=z>>12&63|128,A[N++]=z>>6&63|128,A[N++]=z&63|128):(A[N++]=z>>12|224,A[N++]=z>>6&63|128,A[N++]=z&63|128)}else for(L=0;L>>24|T>>>8&65280|T<<8&16711680|(T&255)<<24;return x>>>0}m.htonl=i;function r(T,x){for(var A="",N=0;N>>0}return z}m.join32=f;function a(T,x){for(var A=new Array(T.length*4),N=0,L=0;N>>24,A[L+1]=z>>>16&255,A[L+2]=z>>>8&255,A[L+3]=z&255):(A[L+3]=z>>>24,A[L+2]=z>>>16&255,A[L+1]=z>>>8&255,A[L]=z&255)}return A}m.split32=a;function g(T,x){return T>>>x|T<<32-x}m.rotr32=g;function b(T,x){return T<>>32-x}m.rotl32=b;function u(T,x){return T+x>>>0}m.sum32=u;function w(T,x,A){return T+x+A>>>0}m.sum32_3=w;function y(T,x,A,N){return T+x+A+N>>>0}m.sum32_4=y;function S(T,x,A,N,L){return T+x+A+N+L>>>0}m.sum32_5=S;function E(T,x,A,N){var L=T[x],z=T[x+1],R=N+z>>>0,k=(R>>0,T[x+1]=R}m.sum64=E;function I(T,x,A,N){var L=x+N>>>0,z=(L>>0}m.sum64_hi=I;function P(T,x,A,N){var L=x+N;return L>>>0}m.sum64_lo=P;function F(T,x,A,N,L,z,R,k){var C=0,O=x;O=O+N>>>0,C+=O>>0,C+=O>>0,C+=O>>0}m.sum64_4_hi=F;function j(T,x,A,N,L,z,R,k){var C=x+N+z+k;return C>>>0}m.sum64_4_lo=j;function W(T,x,A,N,L,z,R,k,C,O){var X=0,ie=x;ie=ie+N>>>0,X+=ie>>0,X+=ie>>0,X+=ie>>0,X+=ie>>0}m.sum64_5_hi=W;function G(T,x,A,N,L,z,R,k,C,O){var X=x+N+z+k+O;return X>>>0}m.sum64_5_lo=G;function V(T,x,A){var N=x<<32-A|T>>>A;return N>>>0}m.rotr64_hi=V;function J(T,x,A){var N=T<<32-A|x>>>A;return N>>>0}m.rotr64_lo=J;function $(T,x,A){return T>>>A}m.shr64_hi=$;function M(T,x,A){var N=T<<32-A|x>>>A;return N>>>0}m.shr64_lo=M},{inherits:440,"minimalistic-assert":453}],438:[function(e,d,m){var l=e("hash.js"),c=e("minimalistic-crypto-utils"),h=e("minimalistic-assert");function s(t){if(!(this instanceof s))return new s(t);this.hash=t.hash,this.predResist=!!t.predResist,this.outLen=this.hash.outSize,this.minEntropy=t.minEntropy||this.hash.hmacStrength,this._reseed=null,this.reseedInterval=null,this.K=null,this.V=null;var i=c.toArray(t.entropy,t.entropyEnc||"hex"),r=c.toArray(t.nonce,t.nonceEnc||"hex"),n=c.toArray(t.pers,t.persEnc||"hex");h(i.length>=this.minEntropy/8,"Not enough entropy. Minimum is: "+this.minEntropy+" bits"),this._init(i,r,n)}d.exports=s,s.prototype._init=function(i,r,n){var o=i.concat(r).concat(n);this.K=new Array(this.outLen/8),this.V=new Array(this.outLen/8);for(var f=0;f=this.minEntropy/8,"Not enough entropy. Minimum is: "+this.minEntropy+" bits"),this._update(i.concat(n||[])),this._reseed=1},s.prototype.generate=function(i,r,n,o){if(this._reseed>this.reseedInterval)throw new Error("Reseed is required");typeof r!="string"&&(o=n,n=r,r=null),n&&(n=c.toArray(n,o||"hex"),this._update(n));for(var f=[];f.length */m.read=function(l,c,h,s,t){var i,r,n=t*8-s-1,o=(1<>1,a=-7,g=h?t-1:0,b=h?-1:1,u=l[c+g];for(g+=b,i=u&(1<<-a)-1,u>>=-a,a+=n;a>0;i=i*256+l[c+g],g+=b,a-=8);for(r=i&(1<<-a)-1,i>>=-a,a+=s;a>0;r=r*256+l[c+g],g+=b,a-=8);if(i===0)i=1-f;else{if(i===o)return r?NaN:(u?-1:1)*(1/0);r=r+Math.pow(2,s),i=i-f}return(u?-1:1)*r*Math.pow(2,i-s)},m.write=function(l,c,h,s,t,i){var r,n,o,f=i*8-t-1,a=(1<>1,b=t===23?Math.pow(2,-24)-Math.pow(2,-77):0,u=s?0:i-1,w=s?1:-1,y=c<0||c===0&&1/c<0?1:0;for(c=Math.abs(c),isNaN(c)||c===1/0?(n=isNaN(c)?1:0,r=a):(r=Math.floor(Math.log(c)/Math.LN2),c*(o=Math.pow(2,-r))<1&&(r--,o*=2),r+g>=1?c+=b/o:c+=b*Math.pow(2,1-g),c*o>=2&&(r++,o/=2),r+g>=a?(n=0,r=a):r+g>=1?(n=(c*o-1)*Math.pow(2,t),r=r+g):(n=c*Math.pow(2,g-1)*Math.pow(2,t),r=0));t>=8;l[h+u]=n&255,u+=w,n/=256,t-=8);for(r=r<0;l[h+u]=r&255,u+=w,r/=256,f-=8);l[h+u-w]|=y*128}},{}],440:[function(e,d,m){typeof Object.create=="function"?d.exports=function(c,h){h&&(c.super_=h,c.prototype=Object.create(h.prototype,{constructor:{value:c,enumerable:!1,writable:!0,configurable:!0}}))}:d.exports=function(c,h){if(h){c.super_=h;var s=function(){};s.prototype=h.prototype,c.prototype=new s,c.prototype.constructor=c}}},{}],441:[function(e,d,m){(function(l,c,h,s,t,i,r,n){(function(){/*! + + JSZip v3.10.1 - A JavaScript class for generating and reading zip files + + + (c) 2009-2016 Stuart Knightley + Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/main/LICENSE.markdown. + + JSZip uses the library pako released under the MIT license : + https://github.com/nodeca/pako/blob/main/LICENSE + */(function(o){typeof m=="object"&&typeof d<"u"?d.exports=o():(typeof window<"u"?window:typeof c<"u"?c:typeof self<"u"?self:this).JSZip=o()})(function(){return function o(f,a,g){function b(y,S){if(!a[y]){if(!f[y]){var E=typeof e=="function"&&e;if(!S&&E)return E(y,!0);if(u)return u(y,!0);var I=new Error("Cannot find module '"+y+"'");throw I.code="MODULE_NOT_FOUND",I}var P=a[y]={exports:{}};f[y][0].call(P.exports,function(F){var j=f[y][1][F];return b(j||F)},P,P.exports,o,f,a,g)}return a[y].exports}for(var u=typeof e=="function"&&e,w=0;w>2,P=(3&y)<<4|S>>4,F=1>6:64,j=2>4,S=(15&I)<<4|(P=u.indexOf(w.charAt(j++)))>>2,E=(3&P)<<6|(F=u.indexOf(w.charAt(j++))),V[W++]=y,P!==64&&(V[W++]=S),F!==64&&(V[W++]=E);return V}},{"./support":30,"./utils":32}],2:[function(o,f,a){var g=o("./external"),b=o("./stream/DataWorker"),u=o("./stream/Crc32Probe"),w=o("./stream/DataLengthProbe");function y(S,E,I,P,F){this.compressedSize=S,this.uncompressedSize=E,this.crc32=I,this.compression=P,this.compressedContent=F}y.prototype={getContentWorker:function(){var S=new b(g.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new w("data_length")),E=this;return S.on("end",function(){if(this.streamInfo.data_length!==E.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")}),S},getCompressedWorker:function(){return new b(g.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},y.createWorkerFrom=function(S,E,I){return S.pipe(new u).pipe(new w("uncompressedSize")).pipe(E.compressWorker(I)).pipe(new w("compressedSize")).withStreamInfo("compression",E)},f.exports=y},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(o,f,a){var g=o("./stream/GenericWorker");a.STORE={magic:"\0\0",compressWorker:function(){return new g("STORE compression")},uncompressWorker:function(){return new g("STORE decompression")}},a.DEFLATE=o("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(o,f,a){var g=o("./utils"),b=function(){for(var u,w=[],y=0;y<256;y++){u=y;for(var S=0;S<8;S++)u=1&u?3988292384^u>>>1:u>>>1;w[y]=u}return w}();f.exports=function(u,w){return u!==void 0&&u.length?g.getTypeOf(u)!=="string"?function(y,S,E,I){var P=b,F=I+E;y^=-1;for(var j=I;j>>8^P[255&(y^S[j])];return-1^y}(0|w,u,u.length,0):function(y,S,E,I){var P=b,F=I+E;y^=-1;for(var j=I;j>>8^P[255&(y^S.charCodeAt(j))];return-1^y}(0|w,u,u.length,0):0}},{"./utils":32}],5:[function(o,f,a){a.base64=!1,a.binary=!1,a.dir=!1,a.createFolders=!0,a.date=null,a.compression=null,a.compressionOptions=null,a.comment=null,a.unixPermissions=null,a.dosPermissions=null},{}],6:[function(o,f,a){var g=null;g=typeof Promise<"u"?Promise:o("lie"),f.exports={Promise:g}},{lie:37}],7:[function(o,f,a){var g=typeof Uint8Array<"u"&&typeof Uint16Array<"u"&&typeof Uint32Array<"u",b=o("pako"),u=o("./utils"),w=o("./stream/GenericWorker"),y=g?"uint8array":"array";function S(E,I){w.call(this,"FlateWorker/"+E),this._pako=null,this._pakoAction=E,this._pakoOptions=I,this.meta={}}a.magic="\b\0",u.inherits(S,w),S.prototype.processChunk=function(E){this.meta=E.meta,this._pako===null&&this._createPako(),this._pako.push(u.transformTo(y,E.data),!1)},S.prototype.flush=function(){w.prototype.flush.call(this),this._pako===null&&this._createPako(),this._pako.push([],!0)},S.prototype.cleanUp=function(){w.prototype.cleanUp.call(this),this._pako=null},S.prototype._createPako=function(){this._pako=new b[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var E=this;this._pako.onData=function(I){E.push({data:I,meta:E.meta})}},a.compressWorker=function(E){return new S("Deflate",E)},a.uncompressWorker=function(){return new S("Inflate",{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(o,f,a){function g(P,F){var j,W="";for(j=0;j>>=8;return W}function b(P,F,j,W,G,V){var J,$,M=P.file,T=P.compression,x=V!==y.utf8encode,A=u.transformTo("string",V(M.name)),N=u.transformTo("string",y.utf8encode(M.name)),L=M.comment,z=u.transformTo("string",V(L)),R=u.transformTo("string",y.utf8encode(L)),k=N.length!==M.name.length,C=R.length!==L.length,O="",X="",ie="",he=M.dir,ue=M.date,ke={crc32:0,compressedSize:0,uncompressedSize:0};F&&!j||(ke.crc32=P.crc32,ke.compressedSize=P.compressedSize,ke.uncompressedSize=P.uncompressedSize);var pe=0;F&&(pe|=8),x||!k&&!C||(pe|=2048);var ee=0,Z=0;he&&(ee|=16),G==="UNIX"?(Z=798,ee|=function(de,Me){var ae=de;return de||(ae=Me?16893:33204),(65535&ae)<<16}(M.unixPermissions,he)):(Z=20,ee|=function(de){return 63&(de||0)}(M.dosPermissions)),J=ue.getUTCHours(),J<<=6,J|=ue.getUTCMinutes(),J<<=5,J|=ue.getUTCSeconds()/2,$=ue.getUTCFullYear()-1980,$<<=4,$|=ue.getUTCMonth()+1,$<<=5,$|=ue.getUTCDate(),k&&(X=g(1,1)+g(S(A),4)+N,O+="up"+g(X.length,2)+X),C&&(ie=g(1,1)+g(S(z),4)+R,O+="uc"+g(ie.length,2)+ie);var q="";return q+=` +\0`,q+=g(pe,2),q+=T.magic,q+=g(J,2),q+=g($,2),q+=g(ke.crc32,4),q+=g(ke.compressedSize,4),q+=g(ke.uncompressedSize,4),q+=g(A.length,2),q+=g(O.length,2),{fileRecord:E.LOCAL_FILE_HEADER+q+A+O,dirRecord:E.CENTRAL_FILE_HEADER+g(Z,2)+q+g(z.length,2)+"\0\0\0\0"+g(ee,4)+g(W,4)+A+O+z}}var u=o("../utils"),w=o("../stream/GenericWorker"),y=o("../utf8"),S=o("../crc32"),E=o("../signature");function I(P,F,j,W){w.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=F,this.zipPlatform=j,this.encodeFileName=W,this.streamFiles=P,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}u.inherits(I,w),I.prototype.push=function(P){var F=P.meta.percent||0,j=this.entriesCount,W=this._sources.length;this.accumulate?this.contentBuffer.push(P):(this.bytesWritten+=P.data.length,w.prototype.push.call(this,{data:P.data,meta:{currentFile:this.currentFile,percent:j?(F+100*(j-W-1))/j:100}}))},I.prototype.openedSource=function(P){this.currentSourceOffset=this.bytesWritten,this.currentFile=P.file.name;var F=this.streamFiles&&!P.file.dir;if(F){var j=b(P,F,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:j.fileRecord,meta:{percent:0}})}else this.accumulate=!0},I.prototype.closedSource=function(P){this.accumulate=!1;var F=this.streamFiles&&!P.file.dir,j=b(P,F,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(j.dirRecord),F)this.push({data:function(W){return E.DATA_DESCRIPTOR+g(W.crc32,4)+g(W.compressedSize,4)+g(W.uncompressedSize,4)}(P),meta:{percent:100}});else for(this.push({data:j.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},I.prototype.flush=function(){for(var P=this.bytesWritten,F=0;F=this.index;w--)y=(y<<8)+this.byteAt(w);return this.index+=u,y},readString:function(u){return g.transformTo("string",this.readData(u))},readData:function(){},lastIndexOfSignature:function(){},readAndCheckSignature:function(){},readDate:function(){var u=this.readInt(4);return new Date(Date.UTC(1980+(u>>25&127),(u>>21&15)-1,u>>16&31,u>>11&31,u>>5&63,(31&u)<<1))}},f.exports=b},{"../utils":32}],19:[function(o,f,a){var g=o("./Uint8ArrayReader");function b(u){g.call(this,u)}o("../utils").inherits(b,g),b.prototype.readData=function(u){this.checkOffset(u);var w=this.data.slice(this.zero+this.index,this.zero+this.index+u);return this.index+=u,w},f.exports=b},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(o,f,a){var g=o("./DataReader");function b(u){g.call(this,u)}o("../utils").inherits(b,g),b.prototype.byteAt=function(u){return this.data.charCodeAt(this.zero+u)},b.prototype.lastIndexOfSignature=function(u){return this.data.lastIndexOf(u)-this.zero},b.prototype.readAndCheckSignature=function(u){return u===this.readData(4)},b.prototype.readData=function(u){this.checkOffset(u);var w=this.data.slice(this.zero+this.index,this.zero+this.index+u);return this.index+=u,w},f.exports=b},{"../utils":32,"./DataReader":18}],21:[function(o,f,a){var g=o("./ArrayReader");function b(u){g.call(this,u)}o("../utils").inherits(b,g),b.prototype.readData=function(u){if(this.checkOffset(u),u===0)return new Uint8Array(0);var w=this.data.subarray(this.zero+this.index,this.zero+this.index+u);return this.index+=u,w},f.exports=b},{"../utils":32,"./ArrayReader":17}],22:[function(o,f,a){var g=o("../utils"),b=o("../support"),u=o("./ArrayReader"),w=o("./StringReader"),y=o("./NodeBufferReader"),S=o("./Uint8ArrayReader");f.exports=function(E){var I=g.getTypeOf(E);return g.checkSupport(I),I!=="string"||b.uint8array?I==="nodebuffer"?new y(E):b.uint8array?new S(g.transformTo("uint8array",E)):new u(g.transformTo("array",E)):new w(E)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(o,f,a){a.LOCAL_FILE_HEADER="PK",a.CENTRAL_FILE_HEADER="PK",a.CENTRAL_DIRECTORY_END="PK",a.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK\x07",a.ZIP64_CENTRAL_DIRECTORY_END="PK",a.DATA_DESCRIPTOR="PK\x07\b"},{}],24:[function(o,f,a){var g=o("./GenericWorker"),b=o("../utils");function u(w){g.call(this,"ConvertWorker to "+w),this.destType=w}b.inherits(u,g),u.prototype.processChunk=function(w){this.push({data:b.transformTo(this.destType,w.data),meta:w.meta})},f.exports=u},{"../utils":32,"./GenericWorker":28}],25:[function(o,f,a){var g=o("./GenericWorker"),b=o("../crc32");function u(){g.call(this,"Crc32Probe"),this.withStreamInfo("crc32",0)}o("../utils").inherits(u,g),u.prototype.processChunk=function(w){this.streamInfo.crc32=b(w.data,this.streamInfo.crc32||0),this.push(w)},f.exports=u},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(o,f,a){var g=o("../utils"),b=o("./GenericWorker");function u(w){b.call(this,"DataLengthProbe for "+w),this.propName=w,this.withStreamInfo(w,0)}g.inherits(u,b),u.prototype.processChunk=function(w){if(w){var y=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=y+w.data.length}b.prototype.processChunk.call(this,w)},f.exports=u},{"../utils":32,"./GenericWorker":28}],27:[function(o,f,a){var g=o("../utils"),b=o("./GenericWorker");function u(w){b.call(this,"DataWorker");var y=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,w.then(function(S){y.dataIsReady=!0,y.data=S,y.max=S&&S.length||0,y.type=g.getTypeOf(S),y.isPaused||y._tickAndRepeat()},function(S){y.error(S)})}g.inherits(u,b),u.prototype.cleanUp=function(){b.prototype.cleanUp.call(this),this.data=null},u.prototype.resume=function(){return!!b.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,g.delay(this._tickAndRepeat,[],this)),!0)},u.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(g.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},u.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var w=null,y=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case"string":w=this.data.substring(this.index,y);break;case"uint8array":w=this.data.subarray(this.index,y);break;case"array":case"nodebuffer":w=this.data.slice(this.index,y)}return this.index=y,this.push({data:w,meta:{percent:this.max?this.index/this.max*100:0}})},f.exports=u},{"../utils":32,"./GenericWorker":28}],28:[function(o,f,a){function g(b){this.name=b||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}g.prototype={push:function(b){this.emit("data",b)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch(b){this.emit("error",b)}return!0},error:function(b){return!this.isFinished&&(this.isPaused?this.generatedError=b:(this.isFinished=!0,this.emit("error",b),this.previous&&this.previous.error(b),this.cleanUp()),!0)},on:function(b,u){return this._listeners[b].push(u),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(b,u){if(this._listeners[b])for(var w=0;w "+b:b}},f.exports=g},{}],29:[function(o,f,a){var g=o("../utils"),b=o("./ConvertWorker"),u=o("./GenericWorker"),w=o("../base64"),y=o("../support"),S=o("../external"),E=null;if(y.nodestream)try{E=o("../nodejs/NodejsStreamOutputAdapter")}catch{}function I(F,j){return new S.Promise(function(W,G){var V=[],J=F._internalType,$=F._outputType,M=F._mimeType;F.on("data",function(T,x){V.push(T),j&&j(x)}).on("error",function(T){V=[],G(T)}).on("end",function(){try{var T=function(x,A,N){switch(x){case"blob":return g.newBlob(g.transformTo("arraybuffer",A),N);case"base64":return w.encode(A);default:return g.transformTo(x,A)}}($,function(x,A){var N,L=0,z=null,R=0;for(N=0;N"u")a.blob=!1;else{var g=new ArrayBuffer(0);try{a.blob=new Blob([g],{type:"application/zip"}).size===0}catch{try{var b=new(self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder);b.append(g),a.blob=b.getBlob("application/zip").size===0}catch{a.blob=!1}}}try{a.nodestream=!!o("readable-stream").Readable}catch{a.nodestream=!1}},{"readable-stream":16}],31:[function(o,f,a){for(var g=o("./utils"),b=o("./support"),u=o("./nodejsUtils"),w=o("./stream/GenericWorker"),y=new Array(256),S=0;S<256;S++)y[S]=252<=S?6:248<=S?5:240<=S?4:224<=S?3:192<=S?2:1;y[254]=y[254]=1;function E(){w.call(this,"utf-8 decode"),this.leftOver=null}function I(){w.call(this,"utf-8 encode")}a.utf8encode=function(P){return b.nodebuffer?u.newBufferFrom(P,"utf-8"):function(F){var j,W,G,V,J,$=F.length,M=0;for(V=0;V<$;V++)(64512&(W=F.charCodeAt(V)))==55296&&V+1<$&&(64512&(G=F.charCodeAt(V+1)))==56320&&(W=65536+(W-55296<<10)+(G-56320),V++),M+=W<128?1:W<2048?2:W<65536?3:4;for(j=b.uint8array?new Uint8Array(M):new Array(M),V=J=0;J>>6:(W<65536?j[J++]=224|W>>>12:(j[J++]=240|W>>>18,j[J++]=128|W>>>12&63),j[J++]=128|W>>>6&63),j[J++]=128|63&W);return j}(P)},a.utf8decode=function(P){return b.nodebuffer?g.transformTo("nodebuffer",P).toString("utf-8"):function(F){var j,W,G,V,J=F.length,$=new Array(2*J);for(j=W=0;j>10&1023,$[W++]=56320|1023&G)}return $.length!==W&&($.subarray?$=$.subarray(0,W):$.length=W),g.applyFromCharCode($)}(P=g.transformTo(b.uint8array?"uint8array":"array",P))},g.inherits(E,w),E.prototype.processChunk=function(P){var F=g.transformTo(b.uint8array?"uint8array":"array",P.data);if(this.leftOver&&this.leftOver.length){if(b.uint8array){var j=F;(F=new Uint8Array(j.length+this.leftOver.length)).set(this.leftOver,0),F.set(j,this.leftOver.length)}else F=this.leftOver.concat(F);this.leftOver=null}var W=function(V,J){var $;for((J=J||V.length)>V.length&&(J=V.length),$=J-1;0<=$&&(192&V[$])==128;)$--;return $<0||$===0?J:$+y[V[$]]>J?$:J}(F),G=F;W!==F.length&&(b.uint8array?(G=F.subarray(0,W),this.leftOver=F.subarray(W,F.length)):(G=F.slice(0,W),this.leftOver=F.slice(W,F.length))),this.push({data:a.utf8decode(G),meta:P.meta})},E.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:a.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},a.Utf8DecodeWorker=E,g.inherits(I,w),I.prototype.processChunk=function(P){this.push({data:a.utf8encode(P.data),meta:P.meta})},a.Utf8EncodeWorker=I},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(o,f,a){var g=o("./support"),b=o("./base64"),u=o("./nodejsUtils"),w=o("./external");function y(j){return j}function S(j,W){for(var G=0;G>8;this.dir=!!(16&this.externalFileAttributes),P==0&&(this.dosPermissions=63&this.externalFileAttributes),P==3&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||this.fileNameStr.slice(-1)!=="/"||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var P=g(this.extraFields[1].value);this.uncompressedSize===b.MAX_VALUE_32BITS&&(this.uncompressedSize=P.readInt(8)),this.compressedSize===b.MAX_VALUE_32BITS&&(this.compressedSize=P.readInt(8)),this.localHeaderOffset===b.MAX_VALUE_32BITS&&(this.localHeaderOffset=P.readInt(8)),this.diskNumberStart===b.MAX_VALUE_32BITS&&(this.diskNumberStart=P.readInt(4))}},readExtraFields:function(P){var F,j,W,G=P.index+this.extraFieldsLength;for(this.extraFields||(this.extraFields={});P.index+4>>6:(P<65536?I[W++]=224|P>>>12:(I[W++]=240|P>>>18,I[W++]=128|P>>>12&63),I[W++]=128|P>>>6&63),I[W++]=128|63&P);return I},a.buf2binstring=function(E){return S(E,E.length)},a.binstring2buf=function(E){for(var I=new g.Buf8(E.length),P=0,F=I.length;P>10&1023,V[F++]=56320|1023&j)}return S(V,F)},a.utf8border=function(E,I){var P;for((I=I||E.length)>E.length&&(I=E.length),P=I-1;0<=P&&(192&E[P])==128;)P--;return P<0||P===0?I:P+w[E[P]]>I?P:I}},{"./common":41}],43:[function(o,f,a){f.exports=function(g,b,u,w){for(var y=65535&g|0,S=g>>>16&65535|0,E=0;u!==0;){for(u-=E=2e3>>1:b>>>1;u[w]=b}return u}();f.exports=function(b,u,w,y){var S=g,E=y+w;b^=-1;for(var I=y;I>>8^S[255&(b^u[I])];return-1^b}},{}],46:[function(o,f,a){var g,b=o("../utils/common"),u=o("./trees"),w=o("./adler32"),y=o("./crc32"),S=o("./messages"),E=0,I=4,P=0,F=-2,j=-1,W=4,G=2,V=8,J=9,$=286,M=30,T=19,x=2*$+1,A=15,N=3,L=258,z=L+N+1,R=42,k=113,C=1,O=2,X=3,ie=4;function he(U,ge){return U.msg=S[ge],ge}function ue(U){return(U<<1)-(4U.avail_out&&(Se=U.avail_out),Se!==0&&(b.arraySet(U.output,ge.pending_buf,ge.pending_out,Se,U.next_out),U.next_out+=Se,ge.pending_out+=Se,U.total_out+=Se,U.avail_out-=Se,ge.pending-=Se,ge.pending===0&&(ge.pending_out=0))}function ee(U,ge){u._tr_flush_block(U,0<=U.block_start?U.block_start:-1,U.strstart-U.block_start,ge),U.block_start=U.strstart,pe(U.strm)}function Z(U,ge){U.pending_buf[U.pending++]=ge}function q(U,ge){U.pending_buf[U.pending++]=ge>>>8&255,U.pending_buf[U.pending++]=255&ge}function de(U,ge){var Se,te,se=U.max_chain_length,ve=U.strstart,Ee=U.prev_length,Ie=U.nice_match,Te=U.strstart>U.w_size-z?U.strstart-(U.w_size-z):0,Pe=U.window,He=U.w_mask,me=U.prev,Ce=U.strstart+L,Le=Pe[ve+Ee-1],ze=Pe[ve+Ee];U.prev_length>=U.good_match&&(se>>=2),Ie>U.lookahead&&(Ie=U.lookahead);do if(Pe[(Se=ge)+Ee]===ze&&Pe[Se+Ee-1]===Le&&Pe[Se]===Pe[ve]&&Pe[++Se]===Pe[ve+1]){ve+=2,Se++;do;while(Pe[++ve]===Pe[++Se]&&Pe[++ve]===Pe[++Se]&&Pe[++ve]===Pe[++Se]&&Pe[++ve]===Pe[++Se]&&Pe[++ve]===Pe[++Se]&&Pe[++ve]===Pe[++Se]&&Pe[++ve]===Pe[++Se]&&Pe[++ve]===Pe[++Se]&&veTe&&--se!=0);return Ee<=U.lookahead?Ee:U.lookahead}function Me(U){var ge,Se,te,se,ve,Ee,Ie,Te,Pe,He,me=U.w_size;do{if(se=U.window_size-U.lookahead-U.strstart,U.strstart>=me+(me-z)){for(b.arraySet(U.window,U.window,me,me,0),U.match_start-=me,U.strstart-=me,U.block_start-=me,ge=Se=U.hash_size;te=U.head[--ge],U.head[ge]=me<=te?te-me:0,--Se;);for(ge=Se=me;te=U.prev[--ge],U.prev[ge]=me<=te?te-me:0,--Se;);se+=me}if(U.strm.avail_in===0)break;if(Ee=U.strm,Ie=U.window,Te=U.strstart+U.lookahead,Pe=se,He=void 0,He=Ee.avail_in,Pe=N)for(ve=U.strstart-U.insert,U.ins_h=U.window[ve],U.ins_h=(U.ins_h<=N&&(U.ins_h=(U.ins_h<=N)if(te=u._tr_tally(U,U.strstart-U.match_start,U.match_length-N),U.lookahead-=U.match_length,U.match_length<=U.max_lazy_match&&U.lookahead>=N){for(U.match_length--;U.strstart++,U.ins_h=(U.ins_h<=N&&(U.ins_h=(U.ins_h<=N&&U.match_length<=U.prev_length){for(se=U.strstart+U.lookahead-N,te=u._tr_tally(U,U.strstart-1-U.prev_match,U.prev_length-N),U.lookahead-=U.prev_length-1,U.prev_length-=2;++U.strstart<=se&&(U.ins_h=(U.ins_h<U.pending_buf_size-5&&(Se=U.pending_buf_size-5);;){if(U.lookahead<=1){if(Me(U),U.lookahead===0&&ge===E)return C;if(U.lookahead===0)break}U.strstart+=U.lookahead,U.lookahead=0;var te=U.block_start+Se;if((U.strstart===0||U.strstart>=te)&&(U.lookahead=U.strstart-te,U.strstart=te,ee(U,!1),U.strm.avail_out===0)||U.strstart-U.block_start>=U.w_size-z&&(ee(U,!1),U.strm.avail_out===0))return C}return U.insert=0,ge===I?(ee(U,!0),U.strm.avail_out===0?X:ie):(U.strstart>U.block_start&&(ee(U,!1),U.strm.avail_out),C)}),new Q(4,4,8,4,ae),new Q(4,5,16,8,ae),new Q(4,6,32,32,ae),new Q(4,4,16,16,ne),new Q(8,16,32,32,ne),new Q(8,16,128,128,ne),new Q(8,32,128,256,ne),new Q(32,128,258,1024,ne),new Q(32,258,258,4096,ne)],a.deflateInit=function(U,ge){return we(U,ge,V,15,8,0)},a.deflateInit2=we,a.deflateReset=le,a.deflateResetKeep=Y,a.deflateSetHeader=function(U,ge){return U&&U.state?U.state.wrap!==2?F:(U.state.gzhead=ge,P):F},a.deflate=function(U,ge){var Se,te,se,ve;if(!U||!U.state||5>8&255),Z(te,te.gzhead.time>>16&255),Z(te,te.gzhead.time>>24&255),Z(te,te.level===9?2:2<=te.strategy||te.level<2?4:0),Z(te,255&te.gzhead.os),te.gzhead.extra&&te.gzhead.extra.length&&(Z(te,255&te.gzhead.extra.length),Z(te,te.gzhead.extra.length>>8&255)),te.gzhead.hcrc&&(U.adler=y(U.adler,te.pending_buf,te.pending,0)),te.gzindex=0,te.status=69):(Z(te,0),Z(te,0),Z(te,0),Z(te,0),Z(te,0),Z(te,te.level===9?2:2<=te.strategy||te.level<2?4:0),Z(te,3),te.status=k);else{var Ee=V+(te.w_bits-8<<4)<<8;Ee|=(2<=te.strategy||te.level<2?0:te.level<6?1:te.level===6?2:3)<<6,te.strstart!==0&&(Ee|=32),Ee+=31-Ee%31,te.status=k,q(te,Ee),te.strstart!==0&&(q(te,U.adler>>>16),q(te,65535&U.adler)),U.adler=1}if(te.status===69)if(te.gzhead.extra){for(se=te.pending;te.gzindex<(65535&te.gzhead.extra.length)&&(te.pending!==te.pending_buf_size||(te.gzhead.hcrc&&te.pending>se&&(U.adler=y(U.adler,te.pending_buf,te.pending-se,se)),pe(U),se=te.pending,te.pending!==te.pending_buf_size));)Z(te,255&te.gzhead.extra[te.gzindex]),te.gzindex++;te.gzhead.hcrc&&te.pending>se&&(U.adler=y(U.adler,te.pending_buf,te.pending-se,se)),te.gzindex===te.gzhead.extra.length&&(te.gzindex=0,te.status=73)}else te.status=73;if(te.status===73)if(te.gzhead.name){se=te.pending;do{if(te.pending===te.pending_buf_size&&(te.gzhead.hcrc&&te.pending>se&&(U.adler=y(U.adler,te.pending_buf,te.pending-se,se)),pe(U),se=te.pending,te.pending===te.pending_buf_size)){ve=1;break}ve=te.gzindexse&&(U.adler=y(U.adler,te.pending_buf,te.pending-se,se)),ve===0&&(te.gzindex=0,te.status=91)}else te.status=91;if(te.status===91)if(te.gzhead.comment){se=te.pending;do{if(te.pending===te.pending_buf_size&&(te.gzhead.hcrc&&te.pending>se&&(U.adler=y(U.adler,te.pending_buf,te.pending-se,se)),pe(U),se=te.pending,te.pending===te.pending_buf_size)){ve=1;break}ve=te.gzindexse&&(U.adler=y(U.adler,te.pending_buf,te.pending-se,se)),ve===0&&(te.status=103)}else te.status=103;if(te.status===103&&(te.gzhead.hcrc?(te.pending+2>te.pending_buf_size&&pe(U),te.pending+2<=te.pending_buf_size&&(Z(te,255&U.adler),Z(te,U.adler>>8&255),U.adler=0,te.status=k)):te.status=k),te.pending!==0){if(pe(U),U.avail_out===0)return te.last_flush=-1,P}else if(U.avail_in===0&&ue(ge)<=ue(Se)&&ge!==I)return he(U,-5);if(te.status===666&&U.avail_in!==0)return he(U,-5);if(U.avail_in!==0||te.lookahead!==0||ge!==E&&te.status!==666){var Ie=te.strategy===2?function(Te,Pe){for(var He;;){if(Te.lookahead===0&&(Me(Te),Te.lookahead===0)){if(Pe===E)return C;break}if(Te.match_length=0,He=u._tr_tally(Te,0,Te.window[Te.strstart]),Te.lookahead--,Te.strstart++,He&&(ee(Te,!1),Te.strm.avail_out===0))return C}return Te.insert=0,Pe===I?(ee(Te,!0),Te.strm.avail_out===0?X:ie):Te.last_lit&&(ee(Te,!1),Te.strm.avail_out===0)?C:O}(te,ge):te.strategy===3?function(Te,Pe){for(var He,me,Ce,Le,ze=Te.window;;){if(Te.lookahead<=L){if(Me(Te),Te.lookahead<=L&&Pe===E)return C;if(Te.lookahead===0)break}if(Te.match_length=0,Te.lookahead>=N&&0Te.lookahead&&(Te.match_length=Te.lookahead)}if(Te.match_length>=N?(He=u._tr_tally(Te,1,Te.match_length-N),Te.lookahead-=Te.match_length,Te.strstart+=Te.match_length,Te.match_length=0):(He=u._tr_tally(Te,0,Te.window[Te.strstart]),Te.lookahead--,Te.strstart++),He&&(ee(Te,!1),Te.strm.avail_out===0))return C}return Te.insert=0,Pe===I?(ee(Te,!0),Te.strm.avail_out===0?X:ie):Te.last_lit&&(ee(Te,!1),Te.strm.avail_out===0)?C:O}(te,ge):g[te.level].func(te,ge);if(Ie!==X&&Ie!==ie||(te.status=666),Ie===C||Ie===X)return U.avail_out===0&&(te.last_flush=-1),P;if(Ie===O&&(ge===1?u._tr_align(te):ge!==5&&(u._tr_stored_block(te,0,0,!1),ge===3&&(ke(te.head),te.lookahead===0&&(te.strstart=0,te.block_start=0,te.insert=0))),pe(U),U.avail_out===0))return te.last_flush=-1,P}return ge!==I?P:te.wrap<=0?1:(te.wrap===2?(Z(te,255&U.adler),Z(te,U.adler>>8&255),Z(te,U.adler>>16&255),Z(te,U.adler>>24&255),Z(te,255&U.total_in),Z(te,U.total_in>>8&255),Z(te,U.total_in>>16&255),Z(te,U.total_in>>24&255)):(q(te,U.adler>>>16),q(te,65535&U.adler)),pe(U),0=Se.w_size&&(ve===0&&(ke(Se.head),Se.strstart=0,Se.block_start=0,Se.insert=0),Pe=new b.Buf8(Se.w_size),b.arraySet(Pe,ge,He-Se.w_size,Se.w_size,0),ge=Pe,He=Se.w_size),Ee=U.avail_in,Ie=U.next_in,Te=U.input,U.avail_in=He,U.next_in=0,U.input=ge,Me(Se);Se.lookahead>=N;){for(te=Se.strstart,se=Se.lookahead-(N-1);Se.ins_h=(Se.ins_h<>>=N=A>>>24,J-=N,(N=A>>>16&255)===0)O[S++]=65535&A;else{if(!(16&N)){if(!(64&N)){A=$[(65535&A)+(V&(1<>>=N,J-=N),J<15&&(V+=C[w++]<>>=N=A>>>24,J-=N,!(16&(N=A>>>16&255))){if(!(64&N)){A=M[(65535&A)+(V&(1<>>=N,J-=N,(N=S-E)>3,V&=(1<<(J-=L<<3))-1,g.next_in=w,g.next_out=S,g.avail_in=w>>24&255)+(R>>>8&65280)+((65280&R)<<8)+((255&R)<<24)}function V(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new g.Buf16(320),this.work=new g.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function J(R){var k;return R&&R.state?(k=R.state,R.total_in=R.total_out=k.total=0,R.msg="",k.wrap&&(R.adler=1&k.wrap),k.mode=F,k.last=0,k.havedict=0,k.dmax=32768,k.head=null,k.hold=0,k.bits=0,k.lencode=k.lendyn=new g.Buf32(j),k.distcode=k.distdyn=new g.Buf32(W),k.sane=1,k.back=-1,I):P}function $(R){var k;return R&&R.state?((k=R.state).wsize=0,k.whave=0,k.wnext=0,J(R)):P}function M(R,k){var C,O;return R&&R.state?(O=R.state,k<0?(C=0,k=-k):(C=1+(k>>4),k<48&&(k&=15)),k&&(k<8||15=ie.wsize?(g.arraySet(ie.window,k,C-ie.wsize,ie.wsize,0),ie.wnext=0,ie.whave=ie.wsize):(O<(X=ie.wsize-ie.wnext)&&(X=O),g.arraySet(ie.window,k,C-O,X,ie.wnext),(O-=X)?(g.arraySet(ie.window,k,C-O,O,0),ie.wnext=O,ie.whave=ie.wsize):(ie.wnext+=X,ie.wnext===ie.wsize&&(ie.wnext=0),ie.whave>>8&255,C.check=u(C.check,ve,2,0),ee=pe=0,C.mode=2;break}if(C.flags=0,C.head&&(C.head.done=!1),!(1&C.wrap)||(((255&pe)<<8)+(pe>>8))%31){R.msg="incorrect header check",C.mode=30;break}if((15&pe)!=8){R.msg="unknown compression method",C.mode=30;break}if(ee-=4,U=8+(15&(pe>>>=4)),C.wbits===0)C.wbits=U;else if(U>C.wbits){R.msg="invalid window size",C.mode=30;break}C.dmax=1<>8&1),512&C.flags&&(ve[0]=255&pe,ve[1]=pe>>>8&255,C.check=u(C.check,ve,2,0)),ee=pe=0,C.mode=3;case 3:for(;ee<32;){if(ue===0)break e;ue--,pe+=O[ie++]<>>8&255,ve[2]=pe>>>16&255,ve[3]=pe>>>24&255,C.check=u(C.check,ve,4,0)),ee=pe=0,C.mode=4;case 4:for(;ee<16;){if(ue===0)break e;ue--,pe+=O[ie++]<>8),512&C.flags&&(ve[0]=255&pe,ve[1]=pe>>>8&255,C.check=u(C.check,ve,2,0)),ee=pe=0,C.mode=5;case 5:if(1024&C.flags){for(;ee<16;){if(ue===0)break e;ue--,pe+=O[ie++]<>>8&255,C.check=u(C.check,ve,2,0)),ee=pe=0}else C.head&&(C.head.extra=null);C.mode=6;case 6:if(1024&C.flags&&(ue<(de=C.length)&&(de=ue),de&&(C.head&&(U=C.head.extra_len-C.length,C.head.extra||(C.head.extra=new Array(C.head.extra_len)),g.arraySet(C.head.extra,O,ie,de,U)),512&C.flags&&(C.check=u(C.check,O,de,ie)),ue-=de,ie+=de,C.length-=de),C.length))break e;C.length=0,C.mode=7;case 7:if(2048&C.flags){if(ue===0)break e;for(de=0;U=O[ie+de++],C.head&&U&&C.length<65536&&(C.head.name+=String.fromCharCode(U)),U&&de>9&1,C.head.done=!0),R.adler=C.check=0,C.mode=12;break;case 10:for(;ee<32;){if(ue===0)break e;ue--,pe+=O[ie++]<>>=7&ee,ee-=7&ee,C.mode=27;break}for(;ee<3;){if(ue===0)break e;ue--,pe+=O[ie++]<>>=1)){case 0:C.mode=14;break;case 1:if(L(C),C.mode=20,k!==6)break;pe>>>=2,ee-=2;break e;case 2:C.mode=17;break;case 3:R.msg="invalid block type",C.mode=30}pe>>>=2,ee-=2;break;case 14:for(pe>>>=7&ee,ee-=7ⅇee<32;){if(ue===0)break e;ue--,pe+=O[ie++]<>>16^65535)){R.msg="invalid stored block lengths",C.mode=30;break}if(C.length=65535&pe,ee=pe=0,C.mode=15,k===6)break e;case 15:C.mode=16;case 16:if(de=C.length){if(ue>>=5,ee-=5,C.ndist=1+(31&pe),pe>>>=5,ee-=5,C.ncode=4+(15&pe),pe>>>=4,ee-=4,286>>=3,ee-=3}for(;C.have<19;)C.lens[Ee[C.have++]]=0;if(C.lencode=C.lendyn,C.lenbits=7,Se={bits:C.lenbits},ge=y(0,C.lens,0,19,C.lencode,0,C.work,Se),C.lenbits=Se.bits,ge){R.msg="invalid code lengths set",C.mode=30;break}C.have=0,C.mode=19;case 19:for(;C.have>>16&255,H=65535&se,!((ne=se>>>24)<=ee);){if(ue===0)break e;ue--,pe+=O[ie++]<>>=ne,ee-=ne,C.lens[C.have++]=H;else{if(H===16){for(te=ne+2;ee>>=ne,ee-=ne,C.have===0){R.msg="invalid bit length repeat",C.mode=30;break}U=C.lens[C.have-1],de=3+(3&pe),pe>>>=2,ee-=2}else if(H===17){for(te=ne+3;ee>>=ne)),pe>>>=3,ee-=3}else{for(te=ne+7;ee>>=ne)),pe>>>=7,ee-=7}if(C.have+de>C.nlen+C.ndist){R.msg="invalid bit length repeat",C.mode=30;break}for(;de--;)C.lens[C.have++]=U}}if(C.mode===30)break;if(C.lens[256]===0){R.msg="invalid code -- missing end-of-block",C.mode=30;break}if(C.lenbits=9,Se={bits:C.lenbits},ge=y(S,C.lens,0,C.nlen,C.lencode,0,C.work,Se),C.lenbits=Se.bits,ge){R.msg="invalid literal/lengths set",C.mode=30;break}if(C.distbits=6,C.distcode=C.distdyn,Se={bits:C.distbits},ge=y(E,C.lens,C.nlen,C.ndist,C.distcode,0,C.work,Se),C.distbits=Se.bits,ge){R.msg="invalid distances set",C.mode=30;break}if(C.mode=20,k===6)break e;case 20:C.mode=21;case 21:if(6<=ue&&258<=ke){R.next_out=he,R.avail_out=ke,R.next_in=ie,R.avail_in=ue,C.hold=pe,C.bits=ee,w(R,q),he=R.next_out,X=R.output,ke=R.avail_out,ie=R.next_in,O=R.input,ue=R.avail_in,pe=C.hold,ee=C.bits,C.mode===12&&(C.back=-1);break}for(C.back=0;Q=(se=C.lencode[pe&(1<>>16&255,H=65535&se,!((ne=se>>>24)<=ee);){if(ue===0)break e;ue--,pe+=O[ie++]<>Y)])>>>16&255,H=65535&se,!(Y+(ne=se>>>24)<=ee);){if(ue===0)break e;ue--,pe+=O[ie++]<>>=Y,ee-=Y,C.back+=Y}if(pe>>>=ne,ee-=ne,C.back+=ne,C.length=H,Q===0){C.mode=26;break}if(32&Q){C.back=-1,C.mode=12;break}if(64&Q){R.msg="invalid literal/length code",C.mode=30;break}C.extra=15&Q,C.mode=22;case 22:if(C.extra){for(te=C.extra;ee>>=C.extra,ee-=C.extra,C.back+=C.extra}C.was=C.length,C.mode=23;case 23:for(;Q=(se=C.distcode[pe&(1<>>16&255,H=65535&se,!((ne=se>>>24)<=ee);){if(ue===0)break e;ue--,pe+=O[ie++]<>Y)])>>>16&255,H=65535&se,!(Y+(ne=se>>>24)<=ee);){if(ue===0)break e;ue--,pe+=O[ie++]<>>=Y,ee-=Y,C.back+=Y}if(pe>>>=ne,ee-=ne,C.back+=ne,64&Q){R.msg="invalid distance code",C.mode=30;break}C.offset=H,C.extra=15&Q,C.mode=24;case 24:if(C.extra){for(te=C.extra;ee>>=C.extra,ee-=C.extra,C.back+=C.extra}if(C.offset>C.dmax){R.msg="invalid distance too far back",C.mode=30;break}C.mode=25;case 25:if(ke===0)break e;if(de=q-ke,C.offset>de){if((de=C.offset-de)>C.whave&&C.sane){R.msg="invalid distance too far back",C.mode=30;break}Me=de>C.wnext?(de-=C.wnext,C.wsize-de):C.wnext-de,de>C.length&&(de=C.length),ae=C.window}else ae=X,Me=he-C.offset,de=C.length;for(kex?(N=Me[ae+W[k]],ee[Z+W[k]]):(N=96,0),V=1<>he)+(J-=V)]=A<<24|N<<16|L|0,J!==0;);for(V=1<>=1;if(V!==0?(pe&=V-1,pe+=V):pe=0,k++,--q[R]==0){if(R===O)break;R=E[I+W[k]]}if(X>>7)]}function Z(se,ve){se.pending_buf[se.pending++]=255&ve,se.pending_buf[se.pending++]=ve>>>8&255}function q(se,ve,Ee){se.bi_valid>G-Ee?(se.bi_buf|=ve<>G-se.bi_valid,se.bi_valid+=Ee-G):(se.bi_buf|=ve<>>=1,Ee<<=1,0<--ve;);return Ee>>>1}function ae(se,ve,Ee){var Ie,Te,Pe=new Array(W+1),He=0;for(Ie=1;Ie<=W;Ie++)Pe[Ie]=He=He+Ee[Ie-1]<<1;for(Te=0;Te<=ve;Te++){var me=se[2*Te+1];me!==0&&(se[2*Te]=Me(Pe[me]++,me))}}function ne(se){var ve;for(ve=0;ve>1;1<=Ee;Ee--)Y(se,Pe,Ee);for(Te=Ce;Ee=se.heap[1],se.heap[1]=se.heap[se.heap_len--],Y(se,Pe,1),Ie=se.heap[1],se.heap[--se.heap_max]=Ee,se.heap[--se.heap_max]=Ie,Pe[2*Te]=Pe[2*Ee]+Pe[2*Ie],se.depth[Te]=(se.depth[Ee]>=se.depth[Ie]?se.depth[Ee]:se.depth[Ie])+1,Pe[2*Ee+1]=Pe[2*Ie+1]=Te,se.heap[1]=Te++,Y(se,Pe,1),2<=se.heap_len;);se.heap[--se.heap_max]=se.heap[1],function(ze,Ye){var ot,pt,it,rt,Tt,Qe,et=Ye.dyn_tree,At=Ye.max_code,lt=Ye.stat_desc.static_tree,jt=Ye.stat_desc.has_stree,Ot=Ye.stat_desc.extra_bits,ct=Ye.stat_desc.extra_base,Bt=Ye.stat_desc.max_length,Ut=0;for(rt=0;rt<=W;rt++)ze.bl_count[rt]=0;for(et[2*ze.heap[ze.heap_max]+1]=0,ot=ze.heap_max+1;ot>=7;Te>>=1)if(1&Le&&me.dyn_ltree[2*Ce]!==0)return b;if(me.dyn_ltree[18]!==0||me.dyn_ltree[20]!==0||me.dyn_ltree[26]!==0)return u;for(Ce=32;Ce>>3,(Pe=se.static_len+3+7>>>3)<=Te&&(Te=Pe)):Te=Pe=Ee+5,Ee+4<=Te&&ve!==-1?te(se,ve,Ee,Ie):se.strategy===4||Pe===Te?(q(se,2+(Ie?1:0),3),le(se,z,R)):(q(se,4+(Ie?1:0),3),function(me,Ce,Le,ze){var Ye;for(q(me,Ce-257,5),q(me,Le-1,5),q(me,ze-4,4),Ye=0;Ye>>8&255,se.pending_buf[se.d_buf+2*se.last_lit+1]=255&ve,se.pending_buf[se.l_buf+se.last_lit]=255&Ee,se.last_lit++,ve===0?se.dyn_ltree[2*Ee]++:(se.matches++,ve--,se.dyn_ltree[2*(C[Ee]+E+1)]++,se.dyn_dtree[2*ee(ve)]++),se.last_lit===se.lit_bufsize-1},a._tr_align=function(se){q(se,2,3),de(se,J,z),function(ve){ve.bi_valid===16?(Z(ve,ve.bi_buf),ve.bi_buf=0,ve.bi_valid=0):8<=ve.bi_valid&&(ve.pending_buf[ve.pending++]=255&ve.bi_buf,ve.bi_buf>>=8,ve.bi_valid-=8)}(se)}},{"../utils/common":41}],53:[function(o,f,a){f.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(o,f,a){(function(g){(function(b,u){if(!b.setImmediate){var w,y,S,E,I=1,P={},F=!1,j=b.document,W=Object.getPrototypeOf&&Object.getPrototypeOf(b);W=W&&W.setTimeout?W:b,w={}.toString.call(b.process)==="[object process]"?function($){l.nextTick(function(){V($)})}:function(){if(b.postMessage&&!b.importScripts){var $=!0,M=b.onmessage;return b.onmessage=function(){$=!1},b.postMessage("","*"),b.onmessage=M,$}}()?(E="setImmediate$"+Math.random()+"$",b.addEventListener?b.addEventListener("message",J,!1):b.attachEvent("onmessage",J),function($){b.postMessage(E+$,"*")}):b.MessageChannel?((S=new MessageChannel).port1.onmessage=function($){V($.data)},function($){S.port2.postMessage($)}):j&&"onreadystatechange"in j.createElement("script")?(y=j.documentElement,function($){var M=j.createElement("script");M.onreadystatechange=function(){V($),M.onreadystatechange=null,y.removeChild(M),M=null},y.appendChild(M)}):function($){setTimeout(V,0,$)},W.setImmediate=function($){typeof $!="function"&&($=new Function(""+$));for(var M=new Array(arguments.length-1),T=0;T"u"?g===void 0?this:g:self)}).call(this,typeof c<"u"?c:typeof self<"u"?self:typeof window<"u"?window:{})},{}]},{},[10])(10)})}).call(this)}).call(this,e("_process"),typeof Dt<"u"?Dt:typeof self<"u"?self:typeof window<"u"?window:{},e("buffer").Buffer,arguments[3],arguments[4],arguments[5],arguments[6],e("timers").setImmediate)},{_process:467,buffer:220,timers:523}],442:[function(e,d,m){(function(l){(function(){var c=1/0,h="[object Symbol]",s=/[\\^$.*+?()[\]{}|]/g,t=RegExp(s.source),i=typeof l=="object"&&l&&l.Object===Object&&l,r=typeof self=="object"&&self&&self.Object===Object&&self,n=i||r||Function("return this")(),o=Object.prototype,f=o.toString,a=n.Symbol,g=a?a.prototype:void 0,b=g?g.toString:void 0;function u(I){if(typeof I=="string")return I;if(y(I))return b?b.call(I):"";var P=I+"";return P=="0"&&1/I==-c?"-0":P}function w(I){return!!I&&typeof I=="object"}function y(I){return typeof I=="symbol"||w(I)&&f.call(I)==h}function S(I){return I==null?"":u(I)}function E(I){return I=S(I),I&&t.test(I)?I.replace(s,"\\$&"):I}d.exports=E}).call(this)}).call(this,typeof Dt<"u"?Dt:typeof self<"u"?self:typeof window<"u"?window:{})},{}],443:[function(e,d,m){(function(l){(function(){var c=200,h="Expected a function",s="__lodash_hash_undefined__",t=1,i=2,r=1/0,n=9007199254740991,o="[object Arguments]",f="[object Array]",a="[object Boolean]",g="[object Date]",b="[object Error]",u="[object Function]",w="[object GeneratorFunction]",y="[object Map]",S="[object Number]",E="[object Object]",I="[object Promise]",P="[object RegExp]",F="[object Set]",j="[object String]",W="[object Symbol]",G="[object WeakMap]",V="[object ArrayBuffer]",J="[object DataView]",$="[object Float32Array]",M="[object Float64Array]",T="[object Int8Array]",x="[object Int16Array]",A="[object Int32Array]",N="[object Uint8Array]",L="[object Uint8ClampedArray]",z="[object Uint16Array]",R="[object Uint32Array]",k=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,C=/^\w*$/,O=/^\./,X=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,ie=/[\\^$.*+?()[\]{}|]/g,he=/\\(\\)?/g,ue=/^\[object .+?Constructor\]$/,ke=/^(?:0|[1-9]\d*)$/,pe={};pe[$]=pe[M]=pe[T]=pe[x]=pe[A]=pe[N]=pe[L]=pe[z]=pe[R]=!0,pe[o]=pe[f]=pe[V]=pe[a]=pe[J]=pe[g]=pe[b]=pe[u]=pe[y]=pe[S]=pe[E]=pe[P]=pe[F]=pe[j]=pe[G]=!1;var ee=typeof l=="object"&&l&&l.Object===Object&&l,Z=typeof self=="object"&&self&&self.Object===Object&&self,q=ee||Z||Function("return this")(),de=typeof m=="object"&&m&&!m.nodeType&&m,Me=de&&typeof d=="object"&&d&&!d.nodeType&&d,ae=Me&&Me.exports===de,ne=ae&&ee.process,Q=function(){try{return ne&&ne.binding("util")}catch{}}(),H=Q&&Q.isTypedArray;function Y(oe,xe,Be,Ge){for(var ut=-1,nt=oe?oe.length:0;++ut-1}function Je(oe,xe){var Be=this.__data__,Ge=Kr(Be,oe);return Ge<0?Be.push([oe,xe]):Be[Ge][1]=xe,this}_t.prototype.clear=Ct,_t.prototype.delete=be,_t.prototype.get=De,_t.prototype.has=Fe,_t.prototype.set=Je;function at(oe){var xe=-1,Be=oe?oe.length:0;for(this.clear();++xeyr))return!1;var Ir=nt.get(oe);if(Ir&&nt.get(xe))return Ir==xe;var Nr=-1,Ar=!0,mr=ut&t?new lr:void 0;for(nt.set(oe,xe),nt.set(xe,oe);++Nr-1&&oe%1==0&&oe-1&&oe%1==0&&oe<=n}function hr(oe){var xe=typeof oe;return!!oe&&(xe=="object"||xe=="function")}function Sr(oe){return!!oe&&typeof oe=="object"}function Tr(oe){return typeof oe=="symbol"||Sr(oe)&&ze.call(oe)==W}var ai=H?ge(H):Cn;function cr(oe){return oe==null?"":ys(oe)}function Ti(oe,xe,Be){var Ge=oe==null?void 0:fn(oe,xe);return Ge===void 0?Be:Ge}function Pr(oe,xe){return oe!=null&&Gn(oe,xe,zn)}function Ai(oe){return fr(oe)?jn(oe):Ci(oe)}function Yi(oe){return oe}function Li(oe){return Zt(oe)?we(Re(oe)):ni(oe)}d.exports=tt}).call(this)}).call(this,typeof Dt<"u"?Dt:typeof self<"u"?self:typeof window<"u"?window:{})},{}],444:[function(e,d,m){var l="[object Boolean]",c=Object.prototype,h=c.toString;function s(i){return i===!0||i===!1||t(i)&&h.call(i)==l}function t(i){return!!i&&typeof i=="object"}d.exports=s},{}],445:[function(e,d,m){(function(l){(function(){var c=200,h="__lodash_hash_undefined__",s=1,t=2,i=9007199254740991,r="[object Arguments]",n="[object Array]",o="[object AsyncFunction]",f="[object Boolean]",a="[object Date]",g="[object Error]",b="[object Function]",u="[object GeneratorFunction]",w="[object Map]",y="[object Number]",S="[object Null]",E="[object Object]",I="[object Promise]",P="[object Proxy]",F="[object RegExp]",j="[object Set]",W="[object String]",G="[object Symbol]",V="[object Undefined]",J="[object WeakMap]",$="[object ArrayBuffer]",M="[object DataView]",T="[object Float32Array]",x="[object Float64Array]",A="[object Int8Array]",N="[object Int16Array]",L="[object Int32Array]",z="[object Uint8Array]",R="[object Uint8ClampedArray]",k="[object Uint16Array]",C="[object Uint32Array]",O=/[\\^$.*+?()[\]{}|]/g,X=/^\[object .+?Constructor\]$/,ie=/^(?:0|[1-9]\d*)$/,he={};he[T]=he[x]=he[A]=he[N]=he[L]=he[z]=he[R]=he[k]=he[C]=!0,he[r]=he[n]=he[$]=he[f]=he[M]=he[a]=he[g]=he[b]=he[w]=he[y]=he[E]=he[F]=he[j]=he[W]=he[J]=!1;var ue=typeof l=="object"&&l&&l.Object===Object&&l,ke=typeof self=="object"&&self&&self.Object===Object&&self,pe=ue||ke||Function("return this")(),ee=typeof m=="object"&&m&&!m.nodeType&&m,Z=ee&&typeof d=="object"&&d&&!d.nodeType&&d,q=Z&&Z.exports===ee,de=q&&ue.process,Me=function(){try{return de&&de.binding&&de.binding("util")}catch{}}(),ae=Me&&Me.isTypedArray;function ne(ye,Re){for(var Xe=-1,tt=ye==null?0:ye.length,Et=0,xt=[];++Xe-1}function Je(ye,Re){var Xe=this.__data__,tt=Kr(Xe,ye);return tt<0?(++this.size,Xe.push([ye,Re])):Xe[tt][1]=Re,this}_t.prototype.clear=Ct,_t.prototype.delete=be,_t.prototype.get=De,_t.prototype.has=Fe,_t.prototype.set=Je;function at(ye){var Re=-1,Xe=ye==null?0:ye.length;for(this.clear();++Reir))return!1;var zt=xt.get(ye);if(zt&&xt.get(Re))return zt==Re;var Cr=-1,Rr=!0,hr=Xe&t?new lr:void 0;for(xt.set(ye,Re),xt.set(Re,ye);++Cr-1&&ye%1==0&&ye-1&&ye%1==0&&ye<=i}function Zt(ye){var Re=typeof ye;return ye!=null&&(Re=="object"||Re=="function")}function Yt(ye){return ye!=null&&typeof ye=="object"}var Yn=ae?le(ae):zn;function Es(ye){return Ss(ye)?jn(ye):Gi(ye)}function Zn(){return[]}function Jn(){return!1}d.exports=gi}).call(this)}).call(this,typeof Dt<"u"?Dt:typeof self<"u"?self:typeof window<"u"?window:{})},{}],446:[function(e,d,m){(function(l){(function(){var c="[object AsyncFunction]",h="[object Function]",s="[object GeneratorFunction]",t="[object Null]",i="[object Proxy]",r="[object Undefined]",n=typeof l=="object"&&l&&l.Object===Object&&l,o=typeof self=="object"&&self&&self.Object===Object&&self,f=n||o||Function("return this")(),a=Object.prototype,g=a.hasOwnProperty,b=a.toString,u=f.Symbol,w=u?u.toStringTag:void 0;function y(F){return F==null?F===void 0?r:t:w&&w in Object(F)?S(F):E(F)}function S(F){var j=g.call(F,w),W=F[w];try{F[w]=void 0;var G=!0}catch{}var V=b.call(F);return G&&(j?F[w]=W:delete F[w]),V}function E(F){return b.call(F)}function I(F){if(!P(F))return!1;var j=y(F);return j==h||j==s||j==c||j==i}function P(F){var j=typeof F;return F!=null&&(j=="object"||j=="function")}d.exports=I}).call(this)}).call(this,typeof Dt<"u"?Dt:typeof self<"u"?self:typeof window<"u"?window:{})},{}],447:[function(e,d,m){function l(c){return c==null}d.exports=l},{}],448:[function(e,d,m){function l(c){return c===void 0}d.exports=l},{}],449:[function(e,d,m){(function(l){(function(){var c=200,h="__lodash_hash_undefined__",s=1/0,t="[object Function]",i="[object GeneratorFunction]",r=/[\\^$.*+?()[\]{}|]/g,n=/^\[object .+?Constructor\]$/,o=typeof l=="object"&&l&&l.Object===Object&&l,f=typeof self=="object"&&self&&self.Object===Object&&self,a=o||f||Function("return this")();function g(me,Ce){var Le=me?me.length:0;return!!Le&&u(me,Ce,0)>-1}function b(me,Ce,Le,ze){for(var Ye=me.length,ot=Le+-1;++ot-1}function pe(me,Ce){var Le=this.__data__,ze=Y(Le,me);return ze<0?Le.push([me,Ce]):Le[ze][1]=Ce,this}X.prototype.clear=ie,X.prototype.delete=he,X.prototype.get=ue,X.prototype.has=ke,X.prototype.set=pe;function ee(me){var Ce=-1,Le=me?me.length:0;for(this.clear();++Ce=c){var Tt=U(me);if(Tt)return I(Tt);pt=!1,Ye=y,rt=new ne}else rt=it;e:for(;++ze56&&(this._block.fill(0,this._blockOffset,64),this._update(),this._blockOffset=0),this._block.fill(0,this._blockOffset,56),this._block.writeUInt32LE(this._length[0],56),this._block.writeUInt32LE(this._length[1],60),this._update();var a=h.allocUnsafe(16);return a.writeInt32LE(this._a,0),a.writeInt32LE(this._b,4),a.writeInt32LE(this._c,8),a.writeInt32LE(this._d,12),a};function i(a,g){return a<>>32-g}function r(a,g,b,u,w,y,S){return i(a+(g&b|~g&u)+w+y|0,S)+g|0}function n(a,g,b,u,w,y,S){return i(a+(g&u|b&~u)+w+y|0,S)+g|0}function o(a,g,b,u,w,y,S){return i(a+(g^b^u)+w+y|0,S)+g|0}function f(a,g,b,u,w,y,S){return i(a+(b^(g|~u))+w+y|0,S)+g|0}d.exports=t},{"hash-base":425,inherits:440,"safe-buffer":494}],451:[function(e,d,m){var l=e("bn.js"),c=e("brorand");function h(s){this.rand=s||new c.Rand}d.exports=h,h.create=function(t){return new h(t)},h.prototype._randbelow=function(t){var i=t.bitLength(),r=Math.ceil(i/8);do var n=new l(this.rand.generate(r));while(n.cmp(t)>=0);return n},h.prototype._randrange=function(t,i){var r=i.sub(t);return t.add(this._randbelow(r))},h.prototype.test=function(t,i,r){var n=t.bitLength(),o=l.mont(t),f=new l(1).toRed(o);i||(i=Math.max(1,n/48|0));for(var a=t.subn(1),g=0;!a.testn(g);g++);for(var b=t.shrn(g),u=a.toRed(o),w=!0;i>0;i--){var y=this._randrange(new l(2),a);r&&r(y);var S=y.toRed(o).redPow(b);if(!(S.cmp(f)===0||S.cmp(u)===0)){for(var E=1;E0;i--){var u=this._randrange(new l(2),f),w=t.gcd(u);if(w.cmpn(1)!==0)return w;var y=u.toRed(n).redPow(g);if(!(y.cmp(o)===0||y.cmp(b)===0)){for(var S=1;S>8,a=o&255;f?r.push(f,a):r.push(a)}return r}l.toArray=c;function h(t){return t.length===1?"0"+t:t}l.zero2=h;function s(t){for(var i="",r=0;r=6?"utf-8":"binary"}else h="utf-8";d.exports=h}).call(this)}).call(this,e("_process"),typeof Dt<"u"?Dt:typeof self<"u"?self:typeof window<"u"?window:{})},{_process:467}],463:[function(e,d,m){var l=Math.pow(2,30)-1;d.exports=function(c,h){if(typeof c!="number")throw new TypeError("Iterations not a number");if(c<0)throw new TypeError("Bad iterations");if(typeof h!="number")throw new TypeError("Key length not a number");if(h<0||h>l||h!==h)throw new TypeError("Bad key length")}},{}],464:[function(e,d,m){var l=e("create-hash/md5"),c=e("ripemd160"),h=e("sha.js"),s=e("safe-buffer").Buffer,t=e("./precondition"),i=e("./default-encoding"),r=e("./to-buffer"),n=s.alloc(128),o={md5:16,sha1:20,sha224:28,sha256:32,sha384:48,sha512:64,rmd160:20,ripemd160:20};function f(b,u,w){var y=a(b),S=b==="sha512"||b==="sha384"?128:64;u.length>S?u=y(u):u.length"u"||!l.version||l.version.indexOf("v0.")===0||l.version.indexOf("v1.")===0&&l.version.indexOf("v1.8.")!==0?d.exports={nextTick:c}:d.exports=l;function c(h,s,t,i){if(typeof h!="function")throw new TypeError('"callback" argument must be a function');var r=arguments.length,n,o;switch(r){case 0:case 1:return l.nextTick(h);case 2:return l.nextTick(function(){h.call(null,s)});case 3:return l.nextTick(function(){h.call(null,s,t)});case 4:return l.nextTick(function(){h.call(null,s,t,i)});default:for(n=new Array(r-1),o=0;o1)for(var E=1;EE||new s(u).cmp(S.modulus)>=0)throw new Error("decryption error");var I;w?I=r(new s(u),S):I=t(u,S);var P=n.alloc(E-I.length);if(I=n.concat([P,I],E),y===4)return o(S,I);if(y===1)return f(S,I,w);if(y===3)return I;throw new Error("unknown padding")};function o(g,b){var u=g.modulus.byteLength(),w=i("sha1").update(n.alloc(0)).digest(),y=w.length;if(b[0]!==0)throw new Error("decryption error");var S=b.slice(1,y+1),E=b.slice(y+1),I=h(S,c(E,y)),P=h(E,c(I,u-y-1));if(a(w,P.slice(0,y)))throw new Error("decryption error");for(var F=y;P[F]===0;)F++;if(P[F++]!==1)throw new Error("decryption error");return P.slice(F)}function f(g,b,u){for(var w=b.slice(0,2),y=2,S=0;b[y++]!==0;)if(y>=b.length){S++;break}var E=b.slice(2,y-1);if((w.toString("hex")!=="0002"&&!u||w.toString("hex")!=="0001"&&u)&&S++,E.length<8&&S++,S)throw new Error("decryption error");return b.slice(y)}function a(g,b){g=n.from(g),b=n.from(b);var u=0,w=g.length;g.length!==b.length&&(u++,w=Math.min(g.length,b.length));for(var y=-1;++y=0)throw new Error("data too long for modulus")}else throw new Error("unknown padding");return y?n(I,E):r(I,E)};function f(b,u){var w=b.modulus.byteLength(),y=u.length,S=h("sha1").update(o.alloc(0)).digest(),E=S.length,I=2*E;if(y>w-I-2)throw new Error("message too long");var P=o.alloc(w-y-I-2),F=w-E-1,j=c(E),W=t(o.concat([S,P,o.alloc(1,1),u],F),s(j,F)),G=t(j,s(W,E));return new i(o.concat([o.alloc(1),G,W],w))}function a(b,u,w){var y=u.length,S=b.modulus.byteLength();if(y>S-11)throw new Error("message too long");var E;return w?E=o.alloc(S-y-3,255):E=g(S-y-3),new i(o.concat([o.from([0,w?1:2]),E,o.alloc(1),u],S))}function g(b){for(var u=o.allocUnsafe(b),w=0,y=c(b*2),S=0,E;ws)throw new RangeError("requested too many random bytes");var a=i.allocUnsafe(o);if(o>0)if(o>h)for(var g=0;go||w<0)throw new TypeError("offset must be a uint32");if(w>r||w>y)throw new RangeError("offset out of range")}function a(w,y,S){if(typeof w!="number"||w!==w)throw new TypeError("size must be a number");if(w>o||w<0)throw new TypeError("size must be a uint32");if(w+y>S||w>r)throw new RangeError("buffer too small")}n&&n.getRandomValues||!l.browser?(m.randomFill=g,m.randomFillSync=u):(m.randomFill=h,m.randomFillSync=h);function g(w,y,S,E){if(!i.isBuffer(w)&&!(w instanceof c.Uint8Array))throw new TypeError('"buf" argument must be a Buffer or Uint8Array');if(typeof y=="function")E=y,y=0,S=w.length;else if(typeof S=="function")E=S,S=w.length-y;else if(typeof E!="function")throw new TypeError('"cb" argument must be a function');return f(y,w.length),a(S,y,w.length),b(w,y,S,E)}function b(w,y,S,E){if(l.browser){var I=w.buffer,P=new Uint8Array(I,y,S);if(n.getRandomValues(P),E){l.nextTick(function(){E(null,w)});return}return w}if(E){t(S,function(j,W){if(j)return E(j);W.copy(w,y),E(null,w)});return}var F=t(S);return F.copy(w,y),w}function u(w,y,S){if(typeof y>"u"&&(y=0),!i.isBuffer(w)&&!(w instanceof c.Uint8Array))throw new TypeError('"buf" argument must be a Buffer or Uint8Array');return f(y,w.length),S===void 0&&(S=w.length-y),a(S,y,w.length),b(w,y,S)}}).call(this)}).call(this,e("_process"),typeof Dt<"u"?Dt:typeof self<"u"?self:typeof window<"u"?window:{})},{_process:467,randombytes:475,"safe-buffer":494}],477:[function(e,d,m){function l(n,o){n.prototype=Object.create(o.prototype),n.prototype.constructor=n,n.__proto__=o}var c={};function h(n,o,f){f||(f=Error);function a(b,u,w){return typeof o=="string"?o:o(b,u,w)}var g=function(b){l(u,b);function u(w,y,S){return b.call(this,a(w,y,S))||this}return u}(f);g.prototype.name=f.name,g.prototype.code=n,c[n]=g}function s(n,o){if(Array.isArray(n)){var f=n.length;return n=n.map(function(a){return String(a)}),f>2?"one of ".concat(o," ").concat(n.slice(0,f-1).join(", "),", or ")+n[f-1]:f===2?"one of ".concat(o," ").concat(n[0]," or ").concat(n[1]):"of ".concat(o," ").concat(n[0])}else return"of ".concat(o," ").concat(String(n))}function t(n,o,f){return n.substr(0,o.length)===o}function i(n,o,f){return(f===void 0||f>n.length)&&(f=n.length),n.substring(f-o.length,f)===o}function r(n,o,f){return typeof f!="number"&&(f=0),f+o.length>n.length?!1:n.indexOf(o,f)!==-1}h("ERR_INVALID_OPT_VALUE",function(n,o){return'The value "'+o+'" is invalid for option "'+n+'"'},TypeError),h("ERR_INVALID_ARG_TYPE",function(n,o,f){var a;typeof o=="string"&&t(o,"not ")?(a="must not be",o=o.replace(/^not /,"")):a="must be";var g;if(i(n," argument"))g="The ".concat(n," ").concat(a," ").concat(s(o,"type"));else{var b=r(n,".")?"property":"argument";g='The "'.concat(n,'" ').concat(b," ").concat(a," ").concat(s(o,"type"))}return g+=". Received type ".concat(typeof f),g},TypeError),h("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF"),h("ERR_METHOD_NOT_IMPLEMENTED",function(n){return"The "+n+" method is not implemented"}),h("ERR_STREAM_PREMATURE_CLOSE","Premature close"),h("ERR_STREAM_DESTROYED",function(n){return"Cannot call "+n+" after a stream was destroyed"}),h("ERR_MULTIPLE_CALLBACK","Callback called multiple times"),h("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable"),h("ERR_STREAM_WRITE_AFTER_END","write after end"),h("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError),h("ERR_UNKNOWN_ENCODING",function(n){return"Unknown encoding: "+n},TypeError),h("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event"),d.exports.codes=c},{}],478:[function(e,d,m){(function(l){(function(){var c=Object.keys||function(a){var g=[];for(var b in a)g.push(b);return g};d.exports=n;var h=e("./_stream_readable"),s=e("./_stream_writable");e("inherits")(n,h);for(var t=c(s.prototype),i=0;i0)if(typeof ne!="string"&&!le.objectMode&&Object.getPrototypeOf(ne)!==i.prototype&&(ne=n(ne)),H)le.endEmitted?G(ae,new P):x(ae,le,ne,!0);else if(le.ended)G(ae,new E);else{if(le.destroyed)return!1;le.reading=!1,le.decoder&&!Q?(ne=le.decoder.write(ne),le.objectMode||ne.length!==0?x(ae,le,ne,!1):O(ae,le)):x(ae,le,ne,!1)}else H||(le.reading=!1,O(ae,le))}return!le.ended&&(le.length=N?ae=N:(ae--,ae|=ae>>>1,ae|=ae>>>2,ae|=ae>>>4,ae|=ae>>>8,ae|=ae>>>16,ae++),ae}function z(ae,ne){return ae<=0||ne.length===0&&ne.ended?0:ne.objectMode?1:ae!==ae?ne.flowing&&ne.length?ne.buffer.head.data.length:ne.length:(ae>ne.highWaterMark&&(ne.highWaterMark=L(ae)),ae<=ne.length?ae:ne.ended?ne.length:(ne.needReadable=!0,0))}M.prototype.read=function(ae){a("read",ae),ae=parseInt(ae,10);var ne=this._readableState,Q=ae;if(ae!==0&&(ne.emittedReadable=!1),ae===0&&ne.needReadable&&((ne.highWaterMark!==0?ne.length>=ne.highWaterMark:ne.length>0)||ne.ended))return a("read: emitReadable",ne.length,ne.ended),ne.length===0&&ne.ended?q(this):k(this),null;if(ae=z(ae,ne),ae===0&&ne.ended)return ne.length===0&&q(this),null;var H=ne.needReadable;a("need readable",H),(ne.length===0||ne.length-ae0?Y=Z(ae,ne):Y=null,Y===null?(ne.needReadable=ne.length<=ne.highWaterMark,ae=0):(ne.length-=ae,ne.awaitDrain=0),ne.length===0&&(ne.ended||(ne.needReadable=!0),Q!==ae&&ne.ended&&q(this)),Y!==null&&this.emit("data",Y),Y};function R(ae,ne){if(a("onEofChunk"),!ne.ended){if(ne.decoder){var Q=ne.decoder.end();Q&&Q.length&&(ne.buffer.push(Q),ne.length+=ne.objectMode?1:Q.length)}ne.ended=!0,ne.sync?k(ae):(ne.needReadable=!1,ne.emittedReadable||(ne.emittedReadable=!0,C(ae)))}}function k(ae){var ne=ae._readableState;a("emitReadable",ne.needReadable,ne.emittedReadable),ne.needReadable=!1,ne.emittedReadable||(a("emitReadable",ne.flowing),ne.emittedReadable=!0,l.nextTick(C,ae))}function C(ae){var ne=ae._readableState;a("emitReadable_",ne.destroyed,ne.length,ne.ended),!ne.destroyed&&(ne.length||ne.ended)&&(ae.emit("readable"),ne.emittedReadable=!1),ne.needReadable=!ne.flowing&&!ne.ended&&ne.length<=ne.highWaterMark,ee(ae)}function O(ae,ne){ne.readingMore||(ne.readingMore=!0,l.nextTick(X,ae,ne))}function X(ae,ne){for(;!ne.reading&&!ne.ended&&(ne.length1&&Me(H.pipes,ae)!==-1)&&!Se&&(a("false write response, pause",H.awaitDrain),H.awaitDrain++),Q.pause())}function ve(Pe){a("onerror",Pe),Te(),ae.removeListener("error",ve),s(ae,"error")===0&&G(ae,Pe)}J(ae,"error",ve);function Ee(){ae.removeListener("finish",Ie),Te()}ae.once("close",Ee);function Ie(){a("onfinish"),ae.removeListener("close",Ee),Te()}ae.once("finish",Ie);function Te(){a("unpipe"),Q.unpipe(ae)}return ae.emit("pipe",Q),H.flowing||(a("pipe resume"),Q.resume()),ae};function ie(ae){return function(){var Q=ae._readableState;a("pipeOnDrain",Q.awaitDrain),Q.awaitDrain&&Q.awaitDrain--,Q.awaitDrain===0&&s(ae,"data")&&(Q.flowing=!0,ee(ae))}}M.prototype.unpipe=function(ae){var ne=this._readableState,Q={hasUnpiped:!1};if(ne.pipesCount===0)return this;if(ne.pipesCount===1)return ae&&ae!==ne.pipes?this:(ae||(ae=ne.pipes),ne.pipes=null,ne.pipesCount=0,ne.flowing=!1,ae&&ae.emit("unpipe",this,Q),this);if(!ae){var H=ne.pipes,Y=ne.pipesCount;ne.pipes=null,ne.pipesCount=0,ne.flowing=!1;for(var le=0;le0,H.flowing!==!1&&this.resume()):ae==="readable"&&!H.endEmitted&&!H.readableListening&&(H.readableListening=H.needReadable=!0,H.flowing=!1,H.emittedReadable=!1,a("on readable",H.length,H.reading),H.length?k(this):H.reading||l.nextTick(ue,this)),Q},M.prototype.addListener=M.prototype.on,M.prototype.removeListener=function(ae,ne){var Q=t.prototype.removeListener.call(this,ae,ne);return ae==="readable"&&l.nextTick(he,this),Q},M.prototype.removeAllListeners=function(ae){var ne=t.prototype.removeAllListeners.apply(this,arguments);return(ae==="readable"||ae===void 0)&&l.nextTick(he,this),ne};function he(ae){var ne=ae._readableState;ne.readableListening=ae.listenerCount("readable")>0,ne.resumeScheduled&&!ne.paused?ne.flowing=!0:ae.listenerCount("data")>0&&ae.resume()}function ue(ae){a("readable nexttick read 0"),ae.read(0)}M.prototype.resume=function(){var ae=this._readableState;return ae.flowing||(a("resume"),ae.flowing=!ae.readableListening,ke(this,ae)),ae.paused=!1,this};function ke(ae,ne){ne.resumeScheduled||(ne.resumeScheduled=!0,l.nextTick(pe,ae,ne))}function pe(ae,ne){a("resume",ne.reading),ne.reading||ae.read(0),ne.resumeScheduled=!1,ae.emit("resume"),ee(ae),ne.flowing&&!ne.reading&&ae.read(0)}M.prototype.pause=function(){return a("call pause flowing=%j",this._readableState.flowing),this._readableState.flowing!==!1&&(a("pause"),this._readableState.flowing=!1,this.emit("pause")),this._readableState.paused=!0,this};function ee(ae){var ne=ae._readableState;for(a("flow",ne.flowing);ne.flowing&&ae.read()!==null;);}M.prototype.wrap=function(ae){var ne=this,Q=this._readableState,H=!1;ae.on("end",function(){if(a("wrapped end"),Q.decoder&&!Q.ended){var we=Q.decoder.end();we&&we.length&&ne.push(we)}ne.push(null)}),ae.on("data",function(we){if(a("wrapped data"),Q.decoder&&(we=Q.decoder.write(we)),!(Q.objectMode&&we==null)&&!(!Q.objectMode&&(!we||!we.length))){var U=ne.push(we);U||(H=!0,ae.pause())}});for(var Y in ae)this[Y]===void 0&&typeof ae[Y]=="function"&&(this[Y]=function(U){return function(){return ae[U].apply(ae,arguments)}}(Y));for(var le=0;le=ne.length?(ne.decoder?Q=ne.buffer.join(""):ne.buffer.length===1?Q=ne.buffer.first():Q=ne.buffer.concat(ne.length),ne.buffer.clear()):Q=ne.buffer.consume(ae,ne.decoder),Q}function q(ae){var ne=ae._readableState;a("endReadable",ne.endEmitted),ne.endEmitted||(ne.ended=!0,l.nextTick(de,ne,ae))}function de(ae,ne){if(a("endReadableNT",ae.endEmitted,ae.length),!ae.endEmitted&&ae.length===0&&(ae.endEmitted=!0,ne.readable=!1,ne.emit("end"),ae.autoDestroy)){var Q=ne._writableState;(!Q||Q.autoDestroy&&Q.finished)&&ne.destroy()}}typeof Symbol=="function"&&(M.from=function(ae,ne){return W===void 0&&(W=e("./internal/streams/from")),W(M,ae,ne)});function Me(ae,ne){for(var Q=0,H=ae.length;Q-1))throw new j(Z);return this._writableState.defaultEncoding=Z,this},Object.defineProperty($.prototype,"writableBuffer",{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}});function x(ee,Z,q){return!ee.objectMode&&ee.decodeStrings!==!1&&typeof Z=="string"&&(Z=r.from(Z,q)),Z}Object.defineProperty($.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}});function A(ee,Z,q,de,Me,ae){if(!q){var ne=x(Z,de,Me);de!==ne&&(q=!0,Me="buffer",de=ne)}var Q=Z.objectMode?1:de.length;Z.length+=Q;var H=Z.length0?this.tail.next=E:this.head=E,this.tail=E,++this.length}},{key:"unshift",value:function(S){var E={data:S,next:this.head};this.length===0&&(this.tail=E),this.head=E,++this.length}},{key:"shift",value:function(){if(this.length!==0){var S=this.head.data;return this.length===1?this.head=this.tail=null:this.head=this.head.next,--this.length,S}}},{key:"clear",value:function(){this.head=this.tail=null,this.length=0}},{key:"join",value:function(S){if(this.length===0)return"";for(var E=this.head,I=""+E.data;E=E.next;)I+=S+E.data;return I}},{key:"concat",value:function(S){if(this.length===0)return f.alloc(0);for(var E=f.allocUnsafe(S>>>0),I=this.head,P=0;I;)u(I.data,E,P),P+=I.data.length,I=I.next;return E}},{key:"consume",value:function(S,E){var I;return SF.length?F.length:S;if(j===F.length?P+=F:P+=F.slice(0,S),S-=j,S===0){j===F.length?(++I,E.next?this.head=E.next:this.head=this.tail=null):(this.head=E,E.data=F.slice(j));break}++I}return this.length-=I,P}},{key:"_getBuffer",value:function(S){var E=f.allocUnsafe(S),I=this.head,P=1;for(I.data.copy(E),S-=I.data.length;I=I.next;){var F=I.data,j=S>F.length?F.length:S;if(F.copy(E,E.length-S,0,j),S-=j,S===0){j===F.length?(++P,I.next?this.head=I.next:this.head=this.tail=null):(this.head=I,I.data=F.slice(j));break}++P}return this.length-=P,E}},{key:b,value:function(S,E){return g(this,c(c({},E),{},{depth:0,customInspect:!1}))}}]),w}()},{buffer:220,util:188}],485:[function(e,d,m){(function(l){(function(){function c(n,o){var f=this,a=this._readableState&&this._readableState.destroyed,g=this._writableState&&this._writableState.destroyed;return a||g?(o?o(n):n&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,l.nextTick(i,this,n)):l.nextTick(i,this,n)),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(n||null,function(b){!o&&b?f._writableState?f._writableState.errorEmitted?l.nextTick(s,f):(f._writableState.errorEmitted=!0,l.nextTick(h,f,b)):l.nextTick(h,f,b):o?(l.nextTick(s,f),o(b)):l.nextTick(s,f)}),this)}function h(n,o){i(n,o),s(n)}function s(n){n._writableState&&!n._writableState.emitClose||n._readableState&&!n._readableState.emitClose||n.emit("close")}function t(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}function i(n,o){n.emit("error",o)}function r(n,o){var f=n._readableState,a=n._writableState;f&&f.autoDestroy||a&&a.autoDestroy?n.destroy(o):n.emit("error",o)}d.exports={destroy:c,undestroy:t,errorOrDestroy:r}}).call(this)}).call(this,e("_process"))},{_process:467}],486:[function(e,d,m){var l=e("../../../errors").codes.ERR_STREAM_PREMATURE_CLOSE;function c(i){var r=!1;return function(){if(!r){r=!0;for(var n=arguments.length,o=new Array(n),f=0;f0;return n(I,F,j,function(W){S||(S=W),W&&E.forEach(o),!F&&(E.forEach(o),y(S))})});return u.reduce(f)}d.exports=g},{"../../../errors":477,"./end-of-stream":486}],489:[function(e,d,m){var l=e("../../../errors").codes.ERR_INVALID_OPT_VALUE;function c(s,t,i){return s.highWaterMark!=null?s.highWaterMark:t?s[i]:null}function h(s,t,i,r){var n=c(t,r,i);if(n!=null){if(!(isFinite(n)&&Math.floor(n)===n)||n<0){var o=r?i:"highWaterMark";throw new l(o,n)}return Math.floor(n)}return s.objectMode?16:16*1024}d.exports={getHighWaterMark:h}},{"../../../errors":477}],490:[function(e,d,m){d.exports=e("events").EventEmitter},{events:422}],491:[function(e,d,m){m=d.exports=e("./lib/_stream_readable.js"),m.Stream=m,m.Readable=m,m.Writable=e("./lib/_stream_writable.js"),m.Duplex=e("./lib/_stream_duplex.js"),m.Transform=e("./lib/_stream_transform.js"),m.PassThrough=e("./lib/_stream_passthrough.js"),m.finished=e("./lib/internal/streams/end-of-stream.js"),m.pipeline=e("./lib/internal/streams/pipeline.js")},{"./lib/_stream_duplex.js":478,"./lib/_stream_passthrough.js":479,"./lib/_stream_readable.js":480,"./lib/_stream_transform.js":481,"./lib/_stream_writable.js":482,"./lib/internal/streams/end-of-stream.js":486,"./lib/internal/streams/pipeline.js":488}],492:[function(e,d,m){var l=function(c){var h=Object.prototype,s=h.hasOwnProperty,t=Object.defineProperty||function(R,k,C){R[k]=C.value},i,r=typeof Symbol=="function"?Symbol:{},n=r.iterator||"@@iterator",o=r.asyncIterator||"@@asyncIterator",f=r.toStringTag||"@@toStringTag";function a(R,k,C){return Object.defineProperty(R,k,{value:C,enumerable:!0,configurable:!0,writable:!0}),R[k]}try{a({},"")}catch{a=function(k,C,O){return k[C]=O}}function g(R,k,C,O){var X=k&&k.prototype instanceof I?k:I,ie=Object.create(X.prototype),he=new N(O||[]);return t(ie,"_invoke",{value:M(R,C,he)}),ie}c.wrap=g;function b(R,k,C){try{return{type:"normal",arg:R.call(k,C)}}catch(O){return{type:"throw",arg:O}}}var u="suspendedStart",w="suspendedYield",y="executing",S="completed",E={};function I(){}function P(){}function F(){}var j={};a(j,n,function(){return this});var W=Object.getPrototypeOf,G=W&&W(W(L([])));G&&G!==h&&s.call(G,n)&&(j=G);var V=F.prototype=I.prototype=Object.create(j);P.prototype=F,t(V,"constructor",{value:F,configurable:!0}),t(F,"constructor",{value:P,configurable:!0}),P.displayName=a(F,f,"GeneratorFunction");function J(R){["next","throw","return"].forEach(function(k){a(R,k,function(C){return this._invoke(k,C)})})}c.isGeneratorFunction=function(R){var k=typeof R=="function"&&R.constructor;return k?k===P||(k.displayName||k.name)==="GeneratorFunction":!1},c.mark=function(R){return Object.setPrototypeOf?Object.setPrototypeOf(R,F):(R.__proto__=F,a(R,f,"GeneratorFunction")),R.prototype=Object.create(V),R},c.awrap=function(R){return{__await:R}};function $(R,k){function C(ie,he,ue,ke){var pe=b(R[ie],R,he);if(pe.type==="throw")ke(pe.arg);else{var ee=pe.arg,Z=ee.value;return Z&&typeof Z=="object"&&s.call(Z,"__await")?k.resolve(Z.__await).then(function(q){C("next",q,ue,ke)},function(q){C("throw",q,ue,ke)}):k.resolve(Z).then(function(q){ee.value=q,ue(ee)},function(q){return C("throw",q,ue,ke)})}}var O;function X(ie,he){function ue(){return new k(function(ke,pe){C(ie,he,ke,pe)})}return O=O?O.then(ue,ue):ue()}t(this,"_invoke",{value:X})}J($.prototype),a($.prototype,o,function(){return this}),c.AsyncIterator=$,c.async=function(R,k,C,O,X){X===void 0&&(X=Promise);var ie=new $(g(R,k,C,O),X);return c.isGeneratorFunction(k)?ie:ie.next().then(function(he){return he.done?he.value:ie.next()})};function M(R,k,C){var O=u;return function(ie,he){if(O===y)throw new Error("Generator is already running");if(O===S){if(ie==="throw")throw he;return z()}for(C.method=ie,C.arg=he;;){var ue=C.delegate;if(ue){var ke=T(ue,C);if(ke){if(ke===E)continue;return ke}}if(C.method==="next")C.sent=C._sent=C.arg;else if(C.method==="throw"){if(O===u)throw O=S,C.arg;C.dispatchException(C.arg)}else C.method==="return"&&C.abrupt("return",C.arg);O=y;var pe=b(R,k,C);if(pe.type==="normal"){if(O=C.done?S:w,pe.arg===E)continue;return{value:pe.arg,done:C.done}}else pe.type==="throw"&&(O=S,C.method="throw",C.arg=pe.arg)}}}function T(R,k){var C=k.method,O=R.iterator[C];if(O===i)return k.delegate=null,C==="throw"&&R.iterator.return&&(k.method="return",k.arg=i,T(R,k),k.method==="throw")||C!=="return"&&(k.method="throw",k.arg=new TypeError("The iterator does not provide a '"+C+"' method")),E;var X=b(O,R.iterator,k.arg);if(X.type==="throw")return k.method="throw",k.arg=X.arg,k.delegate=null,E;var ie=X.arg;if(!ie)return k.method="throw",k.arg=new TypeError("iterator result is not an object"),k.delegate=null,E;if(ie.done)k[R.resultName]=ie.value,k.next=R.nextLoc,k.method!=="return"&&(k.method="next",k.arg=i);else return ie;return k.delegate=null,E}J(V),a(V,f,"Generator"),a(V,n,function(){return this}),a(V,"toString",function(){return"[object Generator]"});function x(R){var k={tryLoc:R[0]};1 in R&&(k.catchLoc=R[1]),2 in R&&(k.finallyLoc=R[2],k.afterLoc=R[3]),this.tryEntries.push(k)}function A(R){var k=R.completion||{};k.type="normal",delete k.arg,R.completion=k}function N(R){this.tryEntries=[{tryLoc:"root"}],R.forEach(x,this),this.reset(!0)}c.keys=function(R){var k=Object(R),C=[];for(var O in k)C.push(O);return C.reverse(),function X(){for(;C.length;){var ie=C.pop();if(ie in k)return X.value=ie,X.done=!1,X}return X.done=!0,X}};function L(R){if(R){var k=R[n];if(k)return k.call(R);if(typeof R.next=="function")return R;if(!isNaN(R.length)){var C=-1,O=function X(){for(;++C=0;--O){var X=this.tryEntries[O],ie=X.completion;if(X.tryLoc==="root")return C("end");if(X.tryLoc<=this.prev){var he=s.call(X,"catchLoc"),ue=s.call(X,"finallyLoc");if(he&&ue){if(this.prev=0;--C){var O=this.tryEntries[C];if(O.tryLoc<=this.prev&&s.call(O,"finallyLoc")&&this.prev=0;--k){var C=this.tryEntries[k];if(C.finallyLoc===R)return this.complete(C.completion,C.afterLoc),A(C),E}},catch:function(R){for(var k=this.tryEntries.length-1;k>=0;--k){var C=this.tryEntries[k];if(C.tryLoc===R){var O=C.completion;if(O.type==="throw"){var X=O.arg;A(C)}return X}}throw new Error("illegal catch attempt")},delegateYield:function(R,k,C){return this.delegate={iterator:L(R),resultName:k,nextLoc:C},this.method==="next"&&(this.arg=i),E}},c}(typeof d=="object"?d.exports:{});try{regeneratorRuntime=l}catch{typeof globalThis=="object"?globalThis.regeneratorRuntime=l:Function("r","regeneratorRuntime = r")(l)}},{}],493:[function(e,d,m){var l=e("buffer").Buffer,c=e("inherits"),h=e("hash-base"),s=new Array(16),t=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13],i=[5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11],r=[11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6],n=[8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11],o=[0,1518500249,1859775393,2400959708,2840853838],f=[1352829926,1548603684,1836072691,2053994217,0];function a(){h.call(this,64),this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520}c(a,h),a.prototype._update=function(){for(var E=s,I=0;I<16;++I)E[I]=this._block.readInt32LE(I*4);for(var P=this._a|0,F=this._b|0,j=this._c|0,W=this._d|0,G=this._e|0,V=this._a|0,J=this._b|0,$=this._c|0,M=this._d|0,T=this._e|0,x=0;x<80;x+=1){var A,N;x<16?(A=b(P,F,j,W,G,E[t[x]],o[0],r[x]),N=S(V,J,$,M,T,E[i[x]],f[0],n[x])):x<32?(A=u(P,F,j,W,G,E[t[x]],o[1],r[x]),N=y(V,J,$,M,T,E[i[x]],f[1],n[x])):x<48?(A=w(P,F,j,W,G,E[t[x]],o[2],r[x]),N=w(V,J,$,M,T,E[i[x]],f[2],n[x])):x<64?(A=y(P,F,j,W,G,E[t[x]],o[3],r[x]),N=u(V,J,$,M,T,E[i[x]],f[3],n[x])):(A=S(P,F,j,W,G,E[t[x]],o[4],r[x]),N=b(V,J,$,M,T,E[i[x]],f[4],n[x])),P=G,G=W,W=g(j,10),j=F,F=A,V=T,T=M,M=g($,10),$=J,J=N}var L=this._b+j+M|0;this._b=this._c+W+T|0,this._c=this._d+G+V|0,this._d=this._e+P+J|0,this._e=this._a+F+$|0,this._a=L},a.prototype._digest=function(){this._block[this._blockOffset++]=128,this._blockOffset>56&&(this._block.fill(0,this._blockOffset,64),this._update(),this._blockOffset=0),this._block.fill(0,this._blockOffset,56),this._block.writeUInt32LE(this._length[0],56),this._block.writeUInt32LE(this._length[1],60),this._update();var E=l.alloc?l.alloc(20):new l(20);return E.writeInt32LE(this._a,0),E.writeInt32LE(this._b,4),E.writeInt32LE(this._c,8),E.writeInt32LE(this._d,12),E.writeInt32LE(this._e,16),E};function g(E,I){return E<>>32-I}function b(E,I,P,F,j,W,G,V){return g(E+(I^P^F)+W+G|0,V)+j|0}function u(E,I,P,F,j,W,G,V){return g(E+(I&P|~I&F)+W+G|0,V)+j|0}function w(E,I,P,F,j,W,G,V){return g(E+((I|~P)^F)+W+G|0,V)+j|0}function y(E,I,P,F,j,W,G,V){return g(E+(I&F|P&~F)+W+G|0,V)+j|0}function S(E,I,P,F,j,W,G,V){return g(E+(I^(P|~F))+W+G|0,V)+j|0}d.exports=a},{buffer:220,"hash-base":425,inherits:440}],494:[function(e,d,m){/*! safe-buffer. MIT License. Feross Aboukhadijeh */var l=e("buffer"),c=l.Buffer;function h(t,i){for(var r in t)i[r]=t[r]}c.from&&c.alloc&&c.allocUnsafe&&c.allocUnsafeSlow?d.exports=l:(h(l,m),m.Buffer=s);function s(t,i,r){return c(t,i,r)}s.prototype=Object.create(c.prototype),h(c,s),s.from=function(t,i,r){if(typeof t=="number")throw new TypeError("Argument must not be a number");return c(t,i,r)},s.alloc=function(t,i,r){if(typeof t!="number")throw new TypeError("Argument must be a number");var n=c(t);return i!==void 0?typeof r=="string"?n.fill(i,r):n.fill(i):n.fill(0),n},s.allocUnsafe=function(t){if(typeof t!="number")throw new TypeError("Argument must be a number");return c(t)},s.allocUnsafeSlow=function(t){if(typeof t!="number")throw new TypeError("Argument must be a number");return l.SlowBuffer(t)}},{buffer:220}],495:[function(e,d,m){(function(l){(function(){var c=e("buffer"),h=c.Buffer,s={},t;for(t in c)c.hasOwnProperty(t)&&(t==="SlowBuffer"||t==="Buffer"||(s[t]=c[t]));var i=s.Buffer={};for(t in h)h.hasOwnProperty(t)&&(t==="allocUnsafe"||t==="allocUnsafeSlow"||(i[t]=h[t]));if(s.Buffer.prototype=h.prototype,(!i.from||i.from===Uint8Array.from)&&(i.from=function(r,n,o){if(typeof r=="number")throw new TypeError('The "value" argument must not be of type number. Received type '+typeof r);if(r&&typeof r.length>"u")throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof r);return h(r,n,o)}),i.alloc||(i.alloc=function(r,n,o){if(typeof r!="number")throw new TypeError('The "size" argument must be of type number. Received type '+typeof r);if(r<0||r>=2*(1<<30))throw new RangeError('The value "'+r+'" is invalid for option "size"');var f=h(r);return!n||n.length===0?f.fill(0):typeof o=="string"?f.fill(n,o):f.fill(n),f}),!s.kStringMaxLength)try{s.kStringMaxLength=l.binding("buffer").kStringMaxLength}catch{}s.constants||(s.constants={MAX_LENGTH:s.kMaxLength},s.kStringMaxLength&&(s.constants.MAX_STRING_LENGTH=s.kStringMaxLength)),d.exports=s}).call(this)}).call(this,e("_process"))},{_process:467,buffer:220}],496:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0});const l=e("xmlchars/xml/1.0/ed5"),c=e("xmlchars/xml/1.1/ed2"),h=e("xmlchars/xmlns/1.0/ed3");var s=l.isS,t=l.isChar,i=l.isNameStartChar,r=l.isNameChar,n=l.S_LIST,o=l.NAME_RE,f=c.isChar,a=h.isNCNameStartChar,g=h.isNCNameChar,b=h.NC_NAME_RE;const u="http://www.w3.org/XML/1998/namespace",w="http://www.w3.org/2000/xmlns/",y={__proto__:null,xml:u,xmlns:w},S={__proto__:null,amp:"&",gt:">",lt:"<",quot:'"',apos:"'"},E=-1,I=-2,P=0,F=1,j=2,W=3,G=4,V=5,J=6,$=7,M=8,T=9,x=10,A=11,N=12,L=13,z=14,R=15,k=16,C=17,O=18,X=19,ie=20,he=21,ue=22,ke=23,pe=24,ee=25,Z=26,q=27,de=28,Me=29,ae=30,ne=31,Q=32,H=33,Y=34,le=35,we=36,U=37,ge=38,Se=39,te=40,se=41,ve=42,Ee=43,Ie=44,Te=9,Pe=10,He=13,me=32,Ce=33,Le=34,ze=38,Ye=39,ot=45,pt=47,it=59,rt=60,Tt=61,Qe=62,et=63,At=91,lt=93,jt=133,Ot=8232,ct=Ct=>Ct===Le||Ct===Ye,Bt=[Le,Ye],Ut=[...Bt,At,Qe],yt=[...Bt,rt,lt],er=[Tt,et,...n],Kt=[...n,Qe,ze,rt];function dt(Ct,be,De){switch(be){case"xml":De!==u&&Ct.fail(`xml prefix must be bound to ${u}.`);break;case"xmlns":De!==w&&Ct.fail(`xmlns prefix must be bound to ${w}.`);break}switch(De){case w:Ct.fail(be===""?`the default namespace may not be set to ${De}.`:`may not assign a prefix (even "xmlns") to the URI ${w}.`);break;case u:switch(be){case"xml":break;case"":Ct.fail(`the default namespace may not be set to ${De}.`);break;default:Ct.fail("may not assign the xml namespace to another prefix.")}break}}function Gt(Ct,be){for(const De of Object.keys(be))dt(Ct,De,be[De])}const Mt=Ct=>b.test(Ct),wt=Ct=>o.test(Ct),$t=0,Qt=1,mt=2;m.EVENTS=["xmldecl","text","processinginstruction","doctype","comment","opentagstart","attribute","opentag","closetag","cdata","error","end","ready"];const qt={xmldecl:"xmldeclHandler",text:"textHandler",processinginstruction:"piHandler",doctype:"doctypeHandler",comment:"commentHandler",opentagstart:"openTagStartHandler",attribute:"attributeHandler",opentag:"openTagHandler",closetag:"closeTagHandler",cdata:"cdataHandler",error:"errorHandler",end:"endHandler",ready:"readyHandler"};class _t{constructor(be){this.opt=be??{},this.fragmentOpt=!!this.opt.fragment;const De=this.xmlnsOpt=!!this.opt.xmlns;if(this.trackPosition=this.opt.position!==!1,this.fileName=this.opt.fileName,De){this.nameStartCheck=a,this.nameCheck=g,this.isName=Mt,this.processAttribs=this.processAttribsNS,this.pushAttrib=this.pushAttribNS,this.ns=Object.assign({__proto__:null},y);const Fe=this.opt.additionalNamespaces;Fe!=null&&(Gt(this,Fe),Object.assign(this.ns,Fe))}else this.nameStartCheck=i,this.nameCheck=r,this.isName=wt,this.processAttribs=this.processAttribsPlain,this.pushAttrib=this.pushAttribPlain;this.stateTable=[this.sBegin,this.sBeginWhitespace,this.sDoctype,this.sDoctypeQuote,this.sDTD,this.sDTDQuoted,this.sDTDOpenWaka,this.sDTDOpenWakaBang,this.sDTDComment,this.sDTDCommentEnding,this.sDTDCommentEnded,this.sDTDPI,this.sDTDPIEnding,this.sText,this.sEntity,this.sOpenWaka,this.sOpenWakaBang,this.sComment,this.sCommentEnding,this.sCommentEnded,this.sCData,this.sCDataEnding,this.sCDataEnding2,this.sPIFirstChar,this.sPIRest,this.sPIBody,this.sPIEnding,this.sXMLDeclNameStart,this.sXMLDeclName,this.sXMLDeclEq,this.sXMLDeclValueStart,this.sXMLDeclValue,this.sXMLDeclSeparator,this.sXMLDeclEnding,this.sOpenTag,this.sOpenTagSlash,this.sAttrib,this.sAttribName,this.sAttribNameSawWhite,this.sAttribValue,this.sAttribValueQuoted,this.sAttribValueClosed,this.sAttribValueUnquoted,this.sCloseTag,this.sCloseTagSawWhite],this._init()}get closed(){return this._closed}_init(){var be;this.openWakaBang="",this.text="",this.name="",this.piTarget="",this.entity="",this.q=null,this.tags=[],this.tag=null,this.topNS=null,this.chunk="",this.chunkPosition=0,this.i=0,this.prevI=0,this.carriedFromPrevious=void 0,this.forbiddenState=$t,this.attribList=[];const{fragmentOpt:De}=this;this.state=De?L:P,this.reportedTextBeforeRoot=this.reportedTextAfterRoot=this.closedRoot=this.sawRoot=De,this.xmlDeclPossible=!De,this.xmlDeclExpects=["version"],this.entityReturnState=void 0;let{defaultXMLVersion:Fe}=this.opt;if(Fe===void 0){if(this.opt.forceXMLVersion===!0)throw new Error("forceXMLVersion set but defaultXMLVersion is not set");Fe="1.0"}this.setXMLVersion(Fe),this.positionAtNewLine=0,this.doctype=!1,this._closed=!1,this.xmlDecl={version:void 0,encoding:void 0,standalone:void 0},this.line=1,this.column=0,this.ENTITIES=Object.create(S),(be=this.readyHandler)===null||be===void 0||be.call(this)}get position(){return this.chunkPosition+this.i}get columnIndex(){return this.position-this.positionAtNewLine}on(be,De){this[qt[be]]=De}off(be){this[qt[be]]=void 0}makeError(be){var De;let Fe=(De=this.fileName)!==null&&De!==void 0?De:"";return this.trackPosition&&(Fe.length>0&&(Fe+=":"),Fe+=`${this.line}:${this.column}`),Fe.length>0&&(Fe+=": "),new Error(Fe+be)}fail(be){const De=this.makeError(be),Fe=this.errorHandler;if(Fe===void 0)throw De;return Fe(De),this}write(be){if(this.closed)return this.fail("cannot write after close; assign an onready handler.");let De=!1;be===null?(De=!0,be=""):typeof be=="object"&&(be=be.toString()),this.carriedFromPrevious!==void 0&&(be=`${this.carriedFromPrevious}${be}`,this.carriedFromPrevious=void 0);let Fe=be.length;const Je=be.charCodeAt(Fe-1);!De&&(Je===He||Je>=55296&&Je<=56319)&&(this.carriedFromPrevious=be[Fe-1],Fe--,be=be.slice(0,Fe));const{stateTable:at}=this;for(this.chunk=be,this.i=0;this.i=be.length)return E;const Fe=be.charCodeAt(De);if(this.column++,Fe<55296){if(Fe>=me||Fe===Te)return Fe;switch(Fe){case Pe:return this.line++,this.column=0,this.positionAtNewLine=this.position,Pe;case He:return be.charCodeAt(De+1)===Pe&&(this.i=De+2),this.line++,this.column=0,this.positionAtNewLine=this.position,I;default:return this.fail("disallowed character."),Fe}}if(Fe>56319)return Fe>=57344&&Fe<=65533||this.fail("disallowed character."),Fe;const Je=65536+(Fe-55296)*1024+(be.charCodeAt(De+1)-56320);return this.i=De+2,Je>1114111&&this.fail("disallowed character."),Je}getCode11(){const{chunk:be,i:De}=this;if(this.prevI=De,this.i=De+1,De>=be.length)return E;const Fe=be.charCodeAt(De);if(this.column++,Fe<55296){if(Fe>31&&Fe<127||Fe>159&&Fe!==Ot||Fe===Te)return Fe;switch(Fe){case Pe:return this.line++,this.column=0,this.positionAtNewLine=this.position,Pe;case He:{const at=be.charCodeAt(De+1);(at===Pe||at===jt)&&(this.i=De+2)}case jt:case Ot:return this.line++,this.column=0,this.positionAtNewLine=this.position,I;default:return this.fail("disallowed character."),Fe}}if(Fe>56319)return Fe>=57344&&Fe<=65533||this.fail("disallowed character."),Fe;const Je=65536+(Fe-55296)*1024+(be.charCodeAt(De+1)-56320);return this.i=De+2,Je>1114111&&this.fail("disallowed character."),Je}getCodeNorm(){const be=this.getCode();return be===I?Pe:be}unget(){this.i=this.prevI,this.column--}captureTo(be){let{i:De}=this;const{chunk:Fe}=this;for(;;){const Je=this.getCode(),at=Je===I,Rt=at?Pe:Je;if(Rt===E||be.includes(Rt))return this.text+=Fe.slice(De,this.prevI),Rt;at&&(this.text+=`${Fe.slice(De,this.prevI)} +`,De=this.i)}}captureToChar(be){let{i:De}=this;const{chunk:Fe}=this;for(;;){let Je=this.getCode();switch(Je){case I:this.text+=`${Fe.slice(De,this.prevI)} +`,De=this.i,Je=Pe;break;case E:return this.text+=Fe.slice(De),!1}if(Je===be)return this.text+=Fe.slice(De,this.prevI),!0}}captureNameChars(){const{chunk:be,i:De}=this;for(;;){const Fe=this.getCode();if(Fe===E)return this.name+=be.slice(De),E;if(!r(Fe))return this.name+=be.slice(De,this.prevI),Fe===I?Pe:Fe}}skipSpaces(){for(;;){const be=this.getCodeNorm();if(be===E||!s(be))return be}}setXMLVersion(be){this.currentXMLVersion=be,be==="1.0"?(this.isChar=t,this.getCode=this.getCode10):(this.isChar=f,this.getCode=this.getCode11)}sBegin(){this.chunk.charCodeAt(0)===65279&&(this.i++,this.column++),this.state=F}sBeginWhitespace(){const be=this.i,De=this.skipSpaces();switch(this.prevI!==be&&(this.xmlDeclPossible=!1),De){case rt:if(this.state=R,this.text.length!==0)throw new Error("no-empty text at start");break;case E:break;default:this.unget(),this.state=L,this.xmlDeclPossible=!1}}sDoctype(){var be;const De=this.captureTo(Ut);switch(De){case Qe:{(be=this.doctypeHandler)===null||be===void 0||be.call(this,this.text),this.text="",this.state=L,this.doctype=!0;break}case E:break;default:this.text+=String.fromCodePoint(De),De===At?this.state=G:ct(De)&&(this.state=W,this.q=De)}}sDoctypeQuote(){const be=this.q;this.captureToChar(be)&&(this.text+=String.fromCodePoint(be),this.q=null,this.state=j)}sDTD(){const be=this.captureTo(yt);be!==E&&(this.text+=String.fromCodePoint(be),be===lt?this.state=j:be===rt?this.state=J:ct(be)&&(this.state=V,this.q=be))}sDTDQuoted(){const be=this.q;this.captureToChar(be)&&(this.text+=String.fromCodePoint(be),this.state=G,this.q=null)}sDTDOpenWaka(){const be=this.getCodeNorm();switch(this.text+=String.fromCodePoint(be),be){case Ce:this.state=$,this.openWakaBang="";break;case et:this.state=A;break;default:this.state=G}}sDTDOpenWakaBang(){const be=String.fromCodePoint(this.getCodeNorm()),De=this.openWakaBang+=be;this.text+=be,De!=="-"&&(this.state=De==="--"?M:G,this.openWakaBang="")}sDTDComment(){this.captureToChar(ot)&&(this.text+="-",this.state=T)}sDTDCommentEnding(){const be=this.getCodeNorm();this.text+=String.fromCodePoint(be),this.state=be===ot?x:M}sDTDCommentEnded(){const be=this.getCodeNorm();this.text+=String.fromCodePoint(be),be===Qe?this.state=G:(this.fail("malformed comment."),this.state=M)}sDTDPI(){this.captureToChar(et)&&(this.text+="?",this.state=N)}sDTDPIEnding(){const be=this.getCodeNorm();this.text+=String.fromCodePoint(be),be===Qe&&(this.state=G)}sText(){this.tags.length!==0?this.handleTextInRoot():this.handleTextOutsideRoot()}sEntity(){let{i:be}=this;const{chunk:De}=this;e:for(;;)switch(this.getCode()){case I:this.entity+=`${De.slice(be,this.prevI)} +`,be=this.i;break;case it:{const{entityReturnState:Fe}=this,Je=this.entity+De.slice(be,this.prevI);this.state=Fe;let at;Je===""?(this.fail("empty entity name."),at="&;"):(at=this.parseEntity(Je),this.entity=""),(Fe!==L||this.textHandler!==void 0)&&(this.text+=at);break e}case E:this.entity+=De.slice(be);break e}}sOpenWaka(){const be=this.getCode();if(i(be))this.state=Y,this.unget(),this.xmlDeclPossible=!1;else switch(be){case pt:this.state=Ee,this.xmlDeclPossible=!1;break;case Ce:this.state=k,this.openWakaBang="",this.xmlDeclPossible=!1;break;case et:this.state=ke;break;default:this.fail("disallowed character in tag name"),this.state=L,this.xmlDeclPossible=!1}}sOpenWakaBang(){switch(this.openWakaBang+=String.fromCodePoint(this.getCodeNorm()),this.openWakaBang){case"[CDATA[":!this.sawRoot&&!this.reportedTextBeforeRoot&&(this.fail("text data outside of root node."),this.reportedTextBeforeRoot=!0),this.closedRoot&&!this.reportedTextAfterRoot&&(this.fail("text data outside of root node."),this.reportedTextAfterRoot=!0),this.state=ie,this.openWakaBang="";break;case"--":this.state=C,this.openWakaBang="";break;case"DOCTYPE":this.state=j,(this.doctype||this.sawRoot)&&this.fail("inappropriately located doctype declaration."),this.openWakaBang="";break;default:this.openWakaBang.length>=7&&this.fail("incorrect syntax.")}}sComment(){this.captureToChar(ot)&&(this.state=O)}sCommentEnding(){var be;const De=this.getCodeNorm();De===ot?(this.state=X,(be=this.commentHandler)===null||be===void 0||be.call(this,this.text),this.text=""):(this.text+=`-${String.fromCodePoint(De)}`,this.state=C)}sCommentEnded(){const be=this.getCodeNorm();be!==Qe?(this.fail("malformed comment."),this.text+=`--${String.fromCodePoint(be)}`,this.state=C):this.state=L}sCData(){this.captureToChar(lt)&&(this.state=he)}sCDataEnding(){const be=this.getCodeNorm();be===lt?this.state=ue:(this.text+=`]${String.fromCodePoint(be)}`,this.state=ie)}sCDataEnding2(){var be;const De=this.getCodeNorm();switch(De){case Qe:{(be=this.cdataHandler)===null||be===void 0||be.call(this,this.text),this.text="",this.state=L;break}case lt:this.text+="]";break;default:this.text+=`]]${String.fromCodePoint(De)}`,this.state=ie}}sPIFirstChar(){const be=this.getCodeNorm();this.nameStartCheck(be)?(this.piTarget+=String.fromCodePoint(be),this.state=pe):be===et||s(be)?(this.fail("processing instruction without a target."),this.state=be===et?Z:ee):(this.fail("disallowed character in processing instruction name."),this.piTarget+=String.fromCodePoint(be),this.state=pe)}sPIRest(){const{chunk:be,i:De}=this;for(;;){const Fe=this.getCodeNorm();if(Fe===E){this.piTarget+=be.slice(De);return}if(!this.nameCheck(Fe)){this.piTarget+=be.slice(De,this.prevI);const Je=Fe===et;Je||s(Fe)?this.piTarget==="xml"?(this.xmlDeclPossible||this.fail("an XML declaration must be at the start of the document."),this.state=Je?H:q):this.state=Je?Z:ee:(this.fail("disallowed character in processing instruction name."),this.piTarget+=String.fromCodePoint(Fe));break}}}sPIBody(){if(this.text.length===0){const be=this.getCodeNorm();be===et?this.state=Z:s(be)||(this.text=String.fromCodePoint(be))}else this.captureToChar(et)&&(this.state=Z)}sPIEnding(){var be;const De=this.getCodeNorm();if(De===Qe){const{piTarget:Fe}=this;Fe.toLowerCase()==="xml"&&this.fail("the XML declaration must appear at the start of the document."),(be=this.piHandler)===null||be===void 0||be.call(this,{target:Fe,body:this.text}),this.piTarget=this.text="",this.state=L}else De===et?this.text+="?":(this.text+=`?${String.fromCodePoint(De)}`,this.state=ee);this.xmlDeclPossible=!1}sXMLDeclNameStart(){const be=this.skipSpaces();if(be===et){this.state=H;return}be!==E&&(this.state=de,this.name=String.fromCodePoint(be))}sXMLDeclName(){const be=this.captureTo(er);if(be===et){this.state=H,this.name+=this.text,this.text="",this.fail("XML declaration is incomplete.");return}if(s(be)||be===Tt){if(this.name+=this.text,this.text="",!this.xmlDeclExpects.includes(this.name))switch(this.name.length){case 0:this.fail("did not expect any more name/value pairs.");break;case 1:this.fail(`expected the name ${this.xmlDeclExpects[0]}.`);break;default:this.fail(`expected one of ${this.xmlDeclExpects.join(", ")}`)}this.state=be===Tt?ae:Me}}sXMLDeclEq(){const be=this.getCodeNorm();if(be===et){this.state=H,this.fail("XML declaration is incomplete.");return}s(be)||(be!==Tt&&this.fail("value required."),this.state=ae)}sXMLDeclValueStart(){const be=this.getCodeNorm();if(be===et){this.state=H,this.fail("XML declaration is incomplete.");return}s(be)||(ct(be)?this.q=be:(this.fail("value must be quoted."),this.q=me),this.state=ne)}sXMLDeclValue(){const be=this.captureTo([this.q,et]);if(be===et){this.state=H,this.text="",this.fail("XML declaration is incomplete.");return}if(be===E)return;const De=this.text;switch(this.text="",this.name){case"version":{this.xmlDeclExpects=["encoding","standalone"];const Fe=De;this.xmlDecl.version=Fe,/^1\.[0-9]+$/.test(Fe)?this.opt.forceXMLVersion||this.setXMLVersion(Fe):this.fail("version number must match /^1\\.[0-9]+$/.");break}case"encoding":/^[A-Za-z][A-Za-z0-9._-]*$/.test(De)||this.fail("encoding value must match /^[A-Za-z0-9][A-Za-z0-9._-]*$/."),this.xmlDeclExpects=["standalone"],this.xmlDecl.encoding=De;break;case"standalone":De!=="yes"&&De!=="no"&&this.fail('standalone value must match "yes" or "no".'),this.xmlDeclExpects=[],this.xmlDecl.standalone=De;break}this.name="",this.state=Q}sXMLDeclSeparator(){const be=this.getCodeNorm();if(be===et){this.state=H;return}s(be)||(this.fail("whitespace required."),this.unget()),this.state=q}sXMLDeclEnding(){var be;this.getCodeNorm()===Qe?(this.piTarget!=="xml"?this.fail("processing instructions are not allowed before root."):this.name!=="version"&&this.xmlDeclExpects.includes("version")&&this.fail("XML declaration must contain a version."),(be=this.xmldeclHandler)===null||be===void 0||be.call(this,this.xmlDecl),this.name="",this.piTarget=this.text="",this.state=L):this.fail("The character ? is disallowed anywhere in XML declarations."),this.xmlDeclPossible=!1}sOpenTag(){var be;const De=this.captureNameChars();if(De===E)return;const Fe=this.tag={name:this.name,attributes:Object.create(null)};switch(this.name="",this.xmlnsOpt&&(this.topNS=Fe.ns=Object.create(null)),(be=this.openTagStartHandler)===null||be===void 0||be.call(this,Fe),this.sawRoot=!0,!this.fragmentOpt&&this.closedRoot&&this.fail("documents may contain only one root."),De){case Qe:this.openTag();break;case pt:this.state=le;break;default:s(De)||this.fail("disallowed character in tag name."),this.state=we}}sOpenTagSlash(){this.getCode()===Qe?this.openSelfClosingTag():(this.fail("forward-slash in opening tag not followed by >."),this.state=we)}sAttrib(){const be=this.skipSpaces();be!==E&&(i(be)?(this.unget(),this.state=U):be===Qe?this.openTag():be===pt?this.state=le:this.fail("disallowed character in attribute name."))}sAttribName(){const be=this.captureNameChars();be===Tt?this.state=Se:s(be)?this.state=ge:be===Qe?(this.fail("attribute without value."),this.pushAttrib(this.name,this.name),this.name=this.text="",this.openTag()):be!==E&&this.fail("disallowed character in attribute name.")}sAttribNameSawWhite(){const be=this.skipSpaces();switch(be){case E:return;case Tt:this.state=Se;break;default:this.fail("attribute without value."),this.text="",this.name="",be===Qe?this.openTag():i(be)?(this.unget(),this.state=U):(this.fail("disallowed character in attribute name."),this.state=we)}}sAttribValue(){const be=this.getCodeNorm();ct(be)?(this.q=be,this.state=te):s(be)||(this.fail("unquoted attribute value."),this.state=ve,this.unget())}sAttribValueQuoted(){const{q:be,chunk:De}=this;let{i:Fe}=this;for(;;)switch(this.getCode()){case be:this.pushAttrib(this.name,this.text+De.slice(Fe,this.prevI)),this.name=this.text="",this.q=null,this.state=se;return;case ze:this.text+=De.slice(Fe,this.prevI),this.state=z,this.entityReturnState=te;return;case Pe:case I:case Te:this.text+=`${De.slice(Fe,this.prevI)} `,Fe=this.i;break;case rt:this.text+=De.slice(Fe,this.prevI),this.fail("disallowed character.");return;case E:this.text+=De.slice(Fe);return}}sAttribValueClosed(){const be=this.getCodeNorm();s(be)?this.state=we:be===Qe?this.openTag():be===pt?this.state=le:i(be)?(this.fail("no whitespace between attributes."),this.unget(),this.state=U):this.fail("disallowed character in attribute name.")}sAttribValueUnquoted(){const be=this.captureTo(Kt);switch(be){case ze:this.state=z,this.entityReturnState=ve;break;case rt:this.fail("disallowed character.");break;case E:break;default:this.text.includes("]]>")&&this.fail('the string "]]>" is disallowed in char data.'),this.pushAttrib(this.name,this.text),this.name=this.text="",be===Qe?this.openTag():this.state=we}}sCloseTag(){const be=this.captureNameChars();be===Qe?this.closeTag():s(be)?this.state=Ie:be!==E&&this.fail("disallowed character in closing tag.")}sCloseTagSawWhite(){switch(this.skipSpaces()){case Qe:this.closeTag();break;case E:break;default:this.fail("disallowed character in closing tag.")}}handleTextInRoot(){let{i:be,forbiddenState:De}=this;const{chunk:Fe,textHandler:Je}=this;e:for(;;)switch(this.getCode()){case rt:{if(this.state=R,Je!==void 0){const{text:at}=this,Rt=Fe.slice(be,this.prevI);at.length!==0?(Je(at+Rt),this.text=""):Rt.length!==0&&Je(Rt)}De=$t;break e}case ze:this.state=z,this.entityReturnState=L,Je!==void 0&&(this.text+=Fe.slice(be,this.prevI)),De=$t;break e;case lt:switch(De){case $t:De=Qt;break;case Qt:De=mt;break;case mt:break;default:throw new Error("impossible state")}break;case Qe:De===mt&&this.fail('the string "]]>" is disallowed in char data.'),De=$t;break;case I:Je!==void 0&&(this.text+=`${Fe.slice(be,this.prevI)} +`),be=this.i,De=$t;break;case E:Je!==void 0&&(this.text+=Fe.slice(be));break e;default:De=$t}this.forbiddenState=De}handleTextOutsideRoot(){let{i:be}=this;const{chunk:De,textHandler:Fe}=this;let Je=!1;e:for(;;){const at=this.getCode();switch(at){case rt:{if(this.state=R,Fe!==void 0){const{text:Rt}=this,rr=De.slice(be,this.prevI);Rt.length!==0?(Fe(Rt+rr),this.text=""):rr.length!==0&&Fe(rr)}break e}case ze:this.state=z,this.entityReturnState=L,Fe!==void 0&&(this.text+=De.slice(be,this.prevI)),Je=!0;break e;case I:Fe!==void 0&&(this.text+=`${De.slice(be,this.prevI)} +`),be=this.i;break;case E:Fe!==void 0&&(this.text+=De.slice(be));break e;default:s(at)||(Je=!0)}}Je&&(!this.sawRoot&&!this.reportedTextBeforeRoot&&(this.fail("text data outside of root node."),this.reportedTextBeforeRoot=!0),this.closedRoot&&!this.reportedTextAfterRoot&&(this.fail("text data outside of root node."),this.reportedTextAfterRoot=!0))}pushAttribNS(be,De){var Fe;const{prefix:Je,local:at}=this.qname(be),Rt={name:be,prefix:Je,local:at,value:De};if(this.attribList.push(Rt),(Fe=this.attributeHandler)===null||Fe===void 0||Fe.call(this,Rt),Je==="xmlns"){const rr=De.trim();this.currentXMLVersion==="1.0"&&rr===""&&this.fail("invalid attempt to undefine prefix in XML 1.0"),this.topNS[at]=rr,dt(this,at,rr)}else if(be==="xmlns"){const rr=De.trim();this.topNS[""]=rr,dt(this,"",rr)}}pushAttribPlain(be,De){var Fe;const Je={name:be,value:De};this.attribList.push(Je),(Fe=this.attributeHandler)===null||Fe===void 0||Fe.call(this,Je)}end(){var be,De;this.sawRoot||this.fail("document must contain a root element.");const{tags:Fe}=this;for(;Fe.length>0;){const at=Fe.pop();this.fail(`unclosed tag: ${at.name}`)}this.state!==P&&this.state!==L&&this.fail("unexpected end.");const{text:Je}=this;return Je.length!==0&&((be=this.textHandler)===null||be===void 0||be.call(this,Je),this.text=""),this._closed=!0,(De=this.endHandler)===null||De===void 0||De.call(this),this._init(),this}resolve(be){var De,Fe;let Je=this.topNS[be];if(Je!==void 0)return Je;const{tags:at}=this;for(let Rt=at.length-1;Rt>=0;Rt--)if(Je=at[Rt].ns[be],Je!==void 0)return Je;return Je=this.ns[be],Je!==void 0?Je:(Fe=(De=this.opt).resolvePrefix)===null||Fe===void 0?void 0:Fe.call(De,be)}qname(be){const De=be.indexOf(":");if(De===-1)return{prefix:"",local:be};const Fe=be.slice(De+1),Je=be.slice(0,De);return(Je===""||Fe===""||Fe.includes(":"))&&this.fail(`malformed name: ${be}.`),{prefix:Je,local:Fe}}processAttribsNS(){var be;const{attribList:De}=this,Fe=this.tag;{const{prefix:Rt,local:rr}=this.qname(Fe.name);Fe.prefix=Rt,Fe.local=rr;const vr=Fe.uri=(be=this.resolve(Rt))!==null&&be!==void 0?be:"";Rt!==""&&(Rt==="xmlns"&&this.fail('tags may not have "xmlns" as prefix.'),vr===""&&(this.fail(`unbound namespace prefix: ${JSON.stringify(Rt)}.`),Fe.uri=Rt))}if(De.length===0)return;const{attributes:Je}=Fe,at=new Set;for(const Rt of De){const{name:rr,prefix:vr,local:Br}=Rt;let br,lr;vr===""?(br=rr==="xmlns"?w:"",lr=rr):(br=this.resolve(vr),br===void 0&&(this.fail(`unbound namespace prefix: ${JSON.stringify(vr)}.`),br=vr),lr=`{${br}}${Br}`),at.has(lr)&&this.fail(`duplicate attribute: ${lr}.`),at.add(lr),Rt.uri=br,Je[rr]=Rt}this.attribList=[]}processAttribsPlain(){const{attribList:be}=this,De=this.tag.attributes;for(const{name:Fe,value:Je}of be)De[Fe]!==void 0&&this.fail(`duplicate attribute: ${Fe}.`),De[Fe]=Je;this.attribList=[]}openTag(){var be;this.processAttribs();const{tags:De}=this,Fe=this.tag;Fe.isSelfClosing=!1,(be=this.openTagHandler)===null||be===void 0||be.call(this,Fe),De.push(Fe),this.state=L,this.name=""}openSelfClosingTag(){var be,De,Fe;this.processAttribs();const{tags:Je}=this,at=this.tag;at.isSelfClosing=!0,(be=this.openTagHandler)===null||be===void 0||be.call(this,at),(De=this.closeTagHandler)===null||De===void 0||De.call(this,at),(this.tag=(Fe=Je[Je.length-1])!==null&&Fe!==void 0?Fe:null)===null&&(this.closedRoot=!0),this.state=L,this.name=""}closeTag(){const{tags:be,name:De}=this;if(this.state=L,this.name="",De===""){this.fail("weird empty close tag."),this.text+="";return}const Fe=this.closeTagHandler;let Je=be.length;for(;Je-- >0;){const at=this.tag=be.pop();if(this.topNS=at.ns,Fe==null||Fe(at),at.name===De)break;this.fail("unexpected close tag.")}Je===0?this.closedRoot=!0:Je<0&&(this.fail(`unmatched closing tag: ${De}.`),this.text+=``)}parseEntity(be){if(be[0]!=="#"){const Fe=this.ENTITIES[be];return Fe!==void 0?Fe:(this.fail(this.isName(be)?"undefined entity.":"disallowed character in entity name."),`&${be};`)}let De=NaN;return be[1]==="x"&&/^#x[0-9a-f]+$/i.test(be)?De=parseInt(be.slice(2),16):/^#[0-9]+$/.test(be)&&(De=parseInt(be.slice(1),10)),this.isChar(De)?String.fromCodePoint(De):(this.fail("malformed character entity."),`&${be};`)}}m.SaxesParser=_t},{"xmlchars/xml/1.0/ed5":543,"xmlchars/xml/1.1/ed2":544,"xmlchars/xmlns/1.0/ed3":545}],497:[function(e,d,m){var l=e("safe-buffer").Buffer;function c(h,s){this._block=l.alloc(h),this._finalSize=s,this._blockSize=h,this._len=0}c.prototype.update=function(h,s){typeof h=="string"&&(s=s||"utf8",h=l.from(h,s));for(var t=this._block,i=this._blockSize,r=h.length,n=this._len,o=0;o=this._finalSize&&(this._update(this._block),this._block.fill(0));var t=this._len*8;if(t<=4294967295)this._block.writeUInt32BE(t,this._blockSize-4);else{var i=(t&4294967295)>>>0,r=(t-i)/4294967296;this._block.writeUInt32BE(r,this._blockSize-8),this._block.writeUInt32BE(i,this._blockSize-4)}this._update(this._block);var n=this._hash();return h?n.toString(h):n},c.prototype._update=function(){throw new Error("_update must be implemented by subclass")},d.exports=c},{"safe-buffer":494}],498:[function(e,d,m){var l=d.exports=function(h){h=h.toLowerCase();var s=l[h];if(!s)throw new Error(h+" is not supported (we accept pull requests)");return new s};l.sha=e("./sha"),l.sha1=e("./sha1"),l.sha224=e("./sha224"),l.sha256=e("./sha256"),l.sha384=e("./sha384"),l.sha512=e("./sha512")},{"./sha":499,"./sha1":500,"./sha224":501,"./sha256":502,"./sha384":503,"./sha512":504}],499:[function(e,d,m){var l=e("inherits"),c=e("./hash"),h=e("safe-buffer").Buffer,s=[1518500249,1859775393,-1894007588,-899497514],t=new Array(80);function i(){this.init(),this._w=t,c.call(this,64,56)}l(i,c),i.prototype.init=function(){return this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520,this};function r(f){return f<<5|f>>>27}function n(f){return f<<30|f>>>2}function o(f,a,g,b){return f===0?a&g|~a&b:f===2?a&g|a&b|g&b:a^g^b}i.prototype._update=function(f){for(var a=this._w,g=this._a|0,b=this._b|0,u=this._c|0,w=this._d|0,y=this._e|0,S=0;S<16;++S)a[S]=f.readInt32BE(S*4);for(;S<80;++S)a[S]=a[S-3]^a[S-8]^a[S-14]^a[S-16];for(var E=0;E<80;++E){var I=~~(E/20),P=r(g)+o(I,b,u,w)+y+a[E]+s[I]|0;y=w,w=u,u=n(b),b=g,g=P}this._a=g+this._a|0,this._b=b+this._b|0,this._c=u+this._c|0,this._d=w+this._d|0,this._e=y+this._e|0},i.prototype._hash=function(){var f=h.allocUnsafe(20);return f.writeInt32BE(this._a|0,0),f.writeInt32BE(this._b|0,4),f.writeInt32BE(this._c|0,8),f.writeInt32BE(this._d|0,12),f.writeInt32BE(this._e|0,16),f},d.exports=i},{"./hash":497,inherits:440,"safe-buffer":494}],500:[function(e,d,m){var l=e("inherits"),c=e("./hash"),h=e("safe-buffer").Buffer,s=[1518500249,1859775393,-1894007588,-899497514],t=new Array(80);function i(){this.init(),this._w=t,c.call(this,64,56)}l(i,c),i.prototype.init=function(){return this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520,this};function r(a){return a<<1|a>>>31}function n(a){return a<<5|a>>>27}function o(a){return a<<30|a>>>2}function f(a,g,b,u){return a===0?g&b|~g&u:a===2?g&b|g&u|b&u:g^b^u}i.prototype._update=function(a){for(var g=this._w,b=this._a|0,u=this._b|0,w=this._c|0,y=this._d|0,S=this._e|0,E=0;E<16;++E)g[E]=a.readInt32BE(E*4);for(;E<80;++E)g[E]=r(g[E-3]^g[E-8]^g[E-14]^g[E-16]);for(var I=0;I<80;++I){var P=~~(I/20),F=n(b)+f(P,u,w,y)+S+g[I]+s[P]|0;S=y,y=w,w=o(u),u=b,b=F}this._a=b+this._a|0,this._b=u+this._b|0,this._c=w+this._c|0,this._d=y+this._d|0,this._e=S+this._e|0},i.prototype._hash=function(){var a=h.allocUnsafe(20);return a.writeInt32BE(this._a|0,0),a.writeInt32BE(this._b|0,4),a.writeInt32BE(this._c|0,8),a.writeInt32BE(this._d|0,12),a.writeInt32BE(this._e|0,16),a},d.exports=i},{"./hash":497,inherits:440,"safe-buffer":494}],501:[function(e,d,m){var l=e("inherits"),c=e("./sha256"),h=e("./hash"),s=e("safe-buffer").Buffer,t=new Array(64);function i(){this.init(),this._w=t,h.call(this,64,56)}l(i,c),i.prototype.init=function(){return this._a=3238371032,this._b=914150663,this._c=812702999,this._d=4144912697,this._e=4290775857,this._f=1750603025,this._g=1694076839,this._h=3204075428,this},i.prototype._hash=function(){var r=s.allocUnsafe(28);return r.writeInt32BE(this._a,0),r.writeInt32BE(this._b,4),r.writeInt32BE(this._c,8),r.writeInt32BE(this._d,12),r.writeInt32BE(this._e,16),r.writeInt32BE(this._f,20),r.writeInt32BE(this._g,24),r},d.exports=i},{"./hash":497,"./sha256":502,inherits:440,"safe-buffer":494}],502:[function(e,d,m){var l=e("inherits"),c=e("./hash"),h=e("safe-buffer").Buffer,s=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],t=new Array(64);function i(){this.init(),this._w=t,c.call(this,64,56)}l(i,c),i.prototype.init=function(){return this._a=1779033703,this._b=3144134277,this._c=1013904242,this._d=2773480762,this._e=1359893119,this._f=2600822924,this._g=528734635,this._h=1541459225,this};function r(b,u,w){return w^b&(u^w)}function n(b,u,w){return b&u|w&(b|u)}function o(b){return(b>>>2|b<<30)^(b>>>13|b<<19)^(b>>>22|b<<10)}function f(b){return(b>>>6|b<<26)^(b>>>11|b<<21)^(b>>>25|b<<7)}function a(b){return(b>>>7|b<<25)^(b>>>18|b<<14)^b>>>3}function g(b){return(b>>>17|b<<15)^(b>>>19|b<<13)^b>>>10}i.prototype._update=function(b){for(var u=this._w,w=this._a|0,y=this._b|0,S=this._c|0,E=this._d|0,I=this._e|0,P=this._f|0,F=this._g|0,j=this._h|0,W=0;W<16;++W)u[W]=b.readInt32BE(W*4);for(;W<64;++W)u[W]=g(u[W-2])+u[W-7]+a(u[W-15])+u[W-16]|0;for(var G=0;G<64;++G){var V=j+f(I)+r(I,P,F)+s[G]+u[G]|0,J=o(w)+n(w,y,S)|0;j=F,F=P,P=I,I=E+V|0,E=S,S=y,y=w,w=V+J|0}this._a=w+this._a|0,this._b=y+this._b|0,this._c=S+this._c|0,this._d=E+this._d|0,this._e=I+this._e|0,this._f=P+this._f|0,this._g=F+this._g|0,this._h=j+this._h|0},i.prototype._hash=function(){var b=h.allocUnsafe(32);return b.writeInt32BE(this._a,0),b.writeInt32BE(this._b,4),b.writeInt32BE(this._c,8),b.writeInt32BE(this._d,12),b.writeInt32BE(this._e,16),b.writeInt32BE(this._f,20),b.writeInt32BE(this._g,24),b.writeInt32BE(this._h,28),b},d.exports=i},{"./hash":497,inherits:440,"safe-buffer":494}],503:[function(e,d,m){var l=e("inherits"),c=e("./sha512"),h=e("./hash"),s=e("safe-buffer").Buffer,t=new Array(160);function i(){this.init(),this._w=t,h.call(this,128,112)}l(i,c),i.prototype.init=function(){return this._ah=3418070365,this._bh=1654270250,this._ch=2438529370,this._dh=355462360,this._eh=1731405415,this._fh=2394180231,this._gh=3675008525,this._hh=1203062813,this._al=3238371032,this._bl=914150663,this._cl=812702999,this._dl=4144912697,this._el=4290775857,this._fl=1750603025,this._gl=1694076839,this._hl=3204075428,this},i.prototype._hash=function(){var r=s.allocUnsafe(48);function n(o,f,a){r.writeInt32BE(o,a),r.writeInt32BE(f,a+4)}return n(this._ah,this._al,0),n(this._bh,this._bl,8),n(this._ch,this._cl,16),n(this._dh,this._dl,24),n(this._eh,this._el,32),n(this._fh,this._fl,40),r},d.exports=i},{"./hash":497,"./sha512":504,inherits:440,"safe-buffer":494}],504:[function(e,d,m){var l=e("inherits"),c=e("./hash"),h=e("safe-buffer").Buffer,s=[1116352408,3609767458,1899447441,602891725,3049323471,3964484399,3921009573,2173295548,961987163,4081628472,1508970993,3053834265,2453635748,2937671579,2870763221,3664609560,3624381080,2734883394,310598401,1164996542,607225278,1323610764,1426881987,3590304994,1925078388,4068182383,2162078206,991336113,2614888103,633803317,3248222580,3479774868,3835390401,2666613458,4022224774,944711139,264347078,2341262773,604807628,2007800933,770255983,1495990901,1249150122,1856431235,1555081692,3175218132,1996064986,2198950837,2554220882,3999719339,2821834349,766784016,2952996808,2566594879,3210313671,3203337956,3336571891,1034457026,3584528711,2466948901,113926993,3758326383,338241895,168717936,666307205,1188179964,773529912,1546045734,1294757372,1522805485,1396182291,2643833823,1695183700,2343527390,1986661051,1014477480,2177026350,1206759142,2456956037,344077627,2730485921,1290863460,2820302411,3158454273,3259730800,3505952657,3345764771,106217008,3516065817,3606008344,3600352804,1432725776,4094571909,1467031594,275423344,851169720,430227734,3100823752,506948616,1363258195,659060556,3750685593,883997877,3785050280,958139571,3318307427,1322822218,3812723403,1537002063,2003034995,1747873779,3602036899,1955562222,1575990012,2024104815,1125592928,2227730452,2716904306,2361852424,442776044,2428436474,593698344,2756734187,3733110249,3204031479,2999351573,3329325298,3815920427,3391569614,3928383900,3515267271,566280711,3940187606,3454069534,4118630271,4000239992,116418474,1914138554,174292421,2731055270,289380356,3203993006,460393269,320620315,685471733,587496836,852142971,1086792851,1017036298,365543100,1126000580,2618297676,1288033470,3409855158,1501505948,4234509866,1607167915,987167468,1816402316,1246189591],t=new Array(160);function i(){this.init(),this._w=t,c.call(this,128,112)}l(i,c),i.prototype.init=function(){return this._ah=1779033703,this._bh=3144134277,this._ch=1013904242,this._dh=2773480762,this._eh=1359893119,this._fh=2600822924,this._gh=528734635,this._hh=1541459225,this._al=4089235720,this._bl=2227873595,this._cl=4271175723,this._dl=1595750129,this._el=2917565137,this._fl=725511199,this._gl=4215389547,this._hl=327033209,this};function r(y,S,E){return E^y&(S^E)}function n(y,S,E){return y&S|E&(y|S)}function o(y,S){return(y>>>28|S<<4)^(S>>>2|y<<30)^(S>>>7|y<<25)}function f(y,S){return(y>>>14|S<<18)^(y>>>18|S<<14)^(S>>>9|y<<23)}function a(y,S){return(y>>>1|S<<31)^(y>>>8|S<<24)^y>>>7}function g(y,S){return(y>>>1|S<<31)^(y>>>8|S<<24)^(y>>>7|S<<25)}function b(y,S){return(y>>>19|S<<13)^(S>>>29|y<<3)^y>>>6}function u(y,S){return(y>>>19|S<<13)^(S>>>29|y<<3)^(y>>>6|S<<26)}function w(y,S){return y>>>0>>0?1:0}i.prototype._update=function(y){for(var S=this._w,E=this._ah|0,I=this._bh|0,P=this._ch|0,F=this._dh|0,j=this._eh|0,W=this._fh|0,G=this._gh|0,V=this._hh|0,J=this._al|0,$=this._bl|0,M=this._cl|0,T=this._dl|0,x=this._el|0,A=this._fl|0,N=this._gl|0,L=this._hl|0,z=0;z<32;z+=2)S[z]=y.readInt32BE(z*4),S[z+1]=y.readInt32BE(z*4+4);for(;z<160;z+=2){var R=S[z-30],k=S[z-15*2+1],C=a(R,k),O=g(k,R);R=S[z-2*2],k=S[z-2*2+1];var X=b(R,k),ie=u(k,R),he=S[z-7*2],ue=S[z-7*2+1],ke=S[z-16*2],pe=S[z-16*2+1],ee=O+ue|0,Z=C+he+w(ee,O)|0;ee=ee+ie|0,Z=Z+X+w(ee,ie)|0,ee=ee+pe|0,Z=Z+ke+w(ee,pe)|0,S[z]=Z,S[z+1]=ee}for(var q=0;q<160;q+=2){Z=S[q],ee=S[q+1];var de=n(E,I,P),Me=n(J,$,M),ae=o(E,J),ne=o(J,E),Q=f(j,x),H=f(x,j),Y=s[q],le=s[q+1],we=r(j,W,G),U=r(x,A,N),ge=L+H|0,Se=V+Q+w(ge,L)|0;ge=ge+U|0,Se=Se+we+w(ge,U)|0,ge=ge+le|0,Se=Se+Y+w(ge,le)|0,ge=ge+ee|0,Se=Se+Z+w(ge,ee)|0;var te=ne+Me|0,se=ae+de+w(te,ne)|0;V=G,L=N,G=W,N=A,W=j,A=x,x=T+ge|0,j=F+Se+w(x,T)|0,F=P,T=M,P=I,M=$,I=E,$=J,J=ge+te|0,E=Se+se+w(J,ge)|0}this._al=this._al+J|0,this._bl=this._bl+$|0,this._cl=this._cl+M|0,this._dl=this._dl+T|0,this._el=this._el+x|0,this._fl=this._fl+A|0,this._gl=this._gl+N|0,this._hl=this._hl+L|0,this._ah=this._ah+E+w(this._al,J)|0,this._bh=this._bh+I+w(this._bl,$)|0,this._ch=this._ch+P+w(this._cl,M)|0,this._dh=this._dh+F+w(this._dl,T)|0,this._eh=this._eh+j+w(this._el,x)|0,this._fh=this._fh+W+w(this._fl,A)|0,this._gh=this._gh+G+w(this._gl,N)|0,this._hh=this._hh+V+w(this._hl,L)|0},i.prototype._hash=function(){var y=h.allocUnsafe(64);function S(E,I,P){y.writeInt32BE(E,P),y.writeInt32BE(I,P+4)}return S(this._ah,this._al,0),S(this._bh,this._bl,8),S(this._ch,this._cl,16),S(this._dh,this._dl,24),S(this._eh,this._el,32),S(this._fh,this._fl,40),S(this._gh,this._gl,48),S(this._hh,this._hl,56),y},d.exports=i},{"./hash":497,inherits:440,"safe-buffer":494}],505:[function(e,d,m){d.exports=h;var l=e("events").EventEmitter,c=e("inherits");c(h,l),h.Readable=e("readable-stream/readable.js"),h.Writable=e("readable-stream/writable.js"),h.Duplex=e("readable-stream/duplex.js"),h.Transform=e("readable-stream/transform.js"),h.PassThrough=e("readable-stream/passthrough.js"),h.Stream=h;function h(){l.call(this)}h.prototype.pipe=function(s,t){var i=this;function r(u){s.writable&&s.write(u)===!1&&i.pause&&i.pause()}i.on("data",r);function n(){i.readable&&i.resume&&i.resume()}s.on("drain",n),!s._isStdio&&(!t||t.end!==!1)&&(i.on("end",f),i.on("close",a));var o=!1;function f(){o||(o=!0,s.end())}function a(){o||(o=!0,typeof s.destroy=="function"&&s.destroy())}function g(u){if(b(),l.listenerCount(this,"error")===0)throw u}i.on("error",g),s.on("error",g);function b(){i.removeListener("data",r),s.removeListener("drain",n),i.removeListener("end",f),i.removeListener("close",a),i.removeListener("error",g),s.removeListener("error",g),i.removeListener("end",b),i.removeListener("close",b),s.removeListener("close",b)}return i.on("end",b),i.on("close",b),s.on("close",b),s.emit("pipe",i),s}},{events:422,inherits:440,"readable-stream/duplex.js":507,"readable-stream/passthrough.js":516,"readable-stream/readable.js":517,"readable-stream/transform.js":518,"readable-stream/writable.js":519}],506:[function(e,d,m){var l={}.toString;d.exports=Array.isArray||function(c){return l.call(c)=="[object Array]"}},{}],507:[function(e,d,m){d.exports=e("./lib/_stream_duplex.js")},{"./lib/_stream_duplex.js":508}],508:[function(e,d,m){var l=e("process-nextick-args"),c=Object.keys||function(g){var b=[];for(var u in g)b.push(u);return b};d.exports=o;var h=Object.create(e("core-util-is"));h.inherits=e("inherits");var s=e("./_stream_readable"),t=e("./_stream_writable");h.inherits(o,s);for(var i=c(t.prototype),r=0;r0?(typeof q!="string"&&!ne.objectMode&&Object.getPrototypeOf(q)!==n.prototype&&(q=f(q)),Me?ne.endEmitted?Z.emit("error",new Error("stream.unshift() after end event")):W(Z,ne,q,!0):ne.ended?Z.emit("error",new Error("stream.push() after EOF")):(ne.reading=!1,ne.decoder&&!de?(q=ne.decoder.write(q),ne.objectMode||q.length!==0?W(Z,ne,q,!1):N(Z,ne)):W(Z,ne,q,!1))):Me||(ne.reading=!1)}return V(ne)}function W(Z,q,de,Me){q.flowing&&q.length===0&&!q.sync?(Z.emit("data",de),Z.read(0)):(q.length+=q.objectMode?1:de.length,Me?q.buffer.unshift(de):q.buffer.push(de),q.needReadable&&x(Z)),N(Z,q)}function G(Z,q){var de;return!a(q)&&typeof q!="string"&&q!==void 0&&!Z.objectMode&&(de=new TypeError("Invalid non-string/buffer chunk")),de}function V(Z){return!Z.ended&&(Z.needReadable||Z.length=J?Z=J:(Z--,Z|=Z>>>1,Z|=Z>>>2,Z|=Z>>>4,Z|=Z>>>8,Z|=Z>>>16,Z++),Z}function M(Z,q){return Z<=0||q.length===0&&q.ended?0:q.objectMode?1:Z!==Z?q.flowing&&q.length?q.buffer.head.data.length:q.length:(Z>q.highWaterMark&&(q.highWaterMark=$(Z)),Z<=q.length?Z:q.ended?q.length:(q.needReadable=!0,0))}F.prototype.read=function(Z){u("read",Z),Z=parseInt(Z,10);var q=this._readableState,de=Z;if(Z!==0&&(q.emittedReadable=!1),Z===0&&q.needReadable&&(q.length>=q.highWaterMark||q.ended))return u("read: emitReadable",q.length,q.ended),q.length===0&&q.ended?ke(this):x(this),null;if(Z=M(Z,q),Z===0&&q.ended)return q.length===0&&ke(this),null;var Me=q.needReadable;u("need readable",Me),(q.length===0||q.length-Z0?ae=X(Z,q):ae=null,ae===null?(q.needReadable=!0,Z=0):q.length-=Z,q.length===0&&(q.ended||(q.needReadable=!0),de!==Z&&q.ended&&ke(this)),ae!==null&&this.emit("data",ae),ae};function T(Z,q){if(!q.ended){if(q.decoder){var de=q.decoder.end();de&&de.length&&(q.buffer.push(de),q.length+=q.objectMode?1:de.length)}q.ended=!0,x(Z)}}function x(Z){var q=Z._readableState;q.needReadable=!1,q.emittedReadable||(u("emitReadable",q.flowing),q.emittedReadable=!0,q.sync?h.nextTick(A,Z):A(Z))}function A(Z){u("emit readable"),Z.emit("readable"),O(Z)}function N(Z,q){q.readingMore||(q.readingMore=!0,h.nextTick(L,Z,q))}function L(Z,q){for(var de=q.length;!q.reading&&!q.flowing&&!q.ended&&q.length1&&ee(Me.pipes,Z)!==-1)&&!le&&(u("false write response, pause",Me.awaitDrain),Me.awaitDrain++,U=!0),de.pause())}function Se(Ee){u("onerror",Ee),ve(),Z.removeListener("error",Se),i(Z,"error")===0&&Z.emit("error",Ee)}I(Z,"error",Se);function te(){Z.removeListener("finish",se),ve()}Z.once("close",te);function se(){u("onfinish"),Z.removeListener("close",te),ve()}Z.once("finish",se);function ve(){u("unpipe"),de.unpipe(Z)}return Z.emit("pipe",de),Me.flowing||(u("pipe resume"),de.resume()),Z};function z(Z){return function(){var q=Z._readableState;u("pipeOnDrain",q.awaitDrain),q.awaitDrain&&q.awaitDrain--,q.awaitDrain===0&&i(Z,"data")&&(q.flowing=!0,O(Z))}}F.prototype.unpipe=function(Z){var q=this._readableState,de={hasUnpiped:!1};if(q.pipesCount===0)return this;if(q.pipesCount===1)return Z&&Z!==q.pipes?this:(Z||(Z=q.pipes),q.pipes=null,q.pipesCount=0,q.flowing=!1,Z&&Z.emit("unpipe",this,de),this);if(!Z){var Me=q.pipes,ae=q.pipesCount;q.pipes=null,q.pipesCount=0,q.flowing=!1;for(var ne=0;ne=q.length?(q.decoder?de=q.buffer.join(""):q.buffer.length===1?de=q.buffer.head.data:de=q.buffer.concat(q.length),q.buffer.clear()):de=ie(Z,q.buffer,q.decoder),de}function ie(Z,q,de){var Me;return Zne.length?ne.length:Z;if(Q===ne.length?ae+=ne:ae+=ne.slice(0,Z),Z-=Q,Z===0){Q===ne.length?(++Me,de.next?q.head=de.next:q.head=q.tail=null):(q.head=de,de.data=ne.slice(Q));break}++Me}return q.length-=Me,ae}function ue(Z,q){var de=n.allocUnsafe(Z),Me=q.head,ae=1;for(Me.data.copy(de),Z-=Me.data.length;Me=Me.next;){var ne=Me.data,Q=Z>ne.length?ne.length:Z;if(ne.copy(de,de.length-Z,0,Q),Z-=Q,Z===0){Q===ne.length?(++ae,Me.next?q.head=Me.next:q.head=q.tail=null):(q.head=Me,Me.data=ne.slice(Q));break}++ae}return q.length-=ae,de}function ke(Z){var q=Z._readableState;if(q.length>0)throw new Error('"endReadable()" called on non-empty stream');q.endEmitted||(q.ended=!0,h.nextTick(pe,q,Z))}function pe(Z,q){!Z.endEmitted&&Z.length===0&&(Z.endEmitted=!0,q.readable=!1,q.emit("end"))}function ee(Z,q){for(var de=0,Me=Z.length;de-1?h:s.nextTick,r;I.WritableState=S;var n=Object.create(e("core-util-is"));n.inherits=e("inherits");var o={deprecate:e("util-deprecate")},f=e("./internal/streams/stream"),a=e("safe-buffer").Buffer,g=(typeof c<"u"?c:typeof window<"u"?window:typeof self<"u"?self:{}).Uint8Array||function(){};function b(C){return a.from(C)}function u(C){return a.isBuffer(C)||C instanceof g}var w=e("./internal/streams/destroy");n.inherits(I,f);function y(){}function S(C,O){r=r||e("./_stream_duplex"),C=C||{};var X=O instanceof r;this.objectMode=!!C.objectMode,X&&(this.objectMode=this.objectMode||!!C.writableObjectMode);var ie=C.highWaterMark,he=C.writableHighWaterMark,ue=this.objectMode?16:16*1024;ie||ie===0?this.highWaterMark=ie:X&&(he||he===0)?this.highWaterMark=he:this.highWaterMark=ue,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var ke=C.decodeStrings===!1;this.decodeStrings=!ke,this.defaultEncoding=C.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(pe){$(O,pe)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new t(this)}S.prototype.getBuffer=function(){for(var O=this.bufferedRequest,X=[];O;)X.push(O),O=O.next;return X},function(){try{Object.defineProperty(S.prototype,"buffer",{get:o.deprecate(function(){return this.getBuffer()},"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch{}}();var E;typeof Symbol=="function"&&Symbol.hasInstance&&typeof Function.prototype[Symbol.hasInstance]=="function"?(E=Function.prototype[Symbol.hasInstance],Object.defineProperty(I,Symbol.hasInstance,{value:function(C){return E.call(this,C)?!0:this!==I?!1:C&&C._writableState instanceof S}})):E=function(C){return C instanceof this};function I(C){if(r=r||e("./_stream_duplex"),!E.call(I,this)&&!(this instanceof r))return new I(C);this._writableState=new S(C,this),this.writable=!0,C&&(typeof C.write=="function"&&(this._write=C.write),typeof C.writev=="function"&&(this._writev=C.writev),typeof C.destroy=="function"&&(this._destroy=C.destroy),typeof C.final=="function"&&(this._final=C.final)),f.call(this)}I.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))};function P(C,O){var X=new Error("write after end");C.emit("error",X),s.nextTick(O,X)}function F(C,O,X,ie){var he=!0,ue=!1;return X===null?ue=new TypeError("May not write null values to stream"):typeof X!="string"&&X!==void 0&&!O.objectMode&&(ue=new TypeError("Invalid non-string/buffer chunk")),ue&&(C.emit("error",ue),s.nextTick(ie,ue),he=!1),he}I.prototype.write=function(C,O,X){var ie=this._writableState,he=!1,ue=!ie.objectMode&&u(C);return ue&&!a.isBuffer(C)&&(C=b(C)),typeof O=="function"&&(X=O,O=null),ue?O="buffer":O||(O=ie.defaultEncoding),typeof X!="function"&&(X=y),ie.ended?P(this,X):(ue||F(this,ie,C,X))&&(ie.pendingcb++,he=W(this,ie,ue,C,O,X)),he},I.prototype.cork=function(){var C=this._writableState;C.corked++},I.prototype.uncork=function(){var C=this._writableState;C.corked&&(C.corked--,!C.writing&&!C.corked&&!C.bufferProcessing&&C.bufferedRequest&&x(this,C))},I.prototype.setDefaultEncoding=function(O){if(typeof O=="string"&&(O=O.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((O+"").toLowerCase())>-1))throw new TypeError("Unknown encoding: "+O);return this._writableState.defaultEncoding=O,this};function j(C,O,X){return!C.objectMode&&C.decodeStrings!==!1&&typeof O=="string"&&(O=a.from(O,X)),O}Object.defineProperty(I.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}});function W(C,O,X,ie,he,ue){if(!X){var ke=j(O,ie,he);ie!==ke&&(X=!0,he="buffer",ie=ke)}var pe=O.objectMode?1:ie.length;O.length+=pe;var ee=O.length0?this.tail.next=n:this.head=n,this.tail=n,++this.length},t.prototype.unshift=function(r){var n={data:r,next:this.head};this.length===0&&(this.tail=n),this.head=n,++this.length},t.prototype.shift=function(){if(this.length!==0){var r=this.head.data;return this.length===1?this.head=this.tail=null:this.head=this.head.next,--this.length,r}},t.prototype.clear=function(){this.head=this.tail=null,this.length=0},t.prototype.join=function(r){if(this.length===0)return"";for(var n=this.head,o=""+n.data;n=n.next;)o+=r+n.data;return o},t.prototype.concat=function(r){if(this.length===0)return c.alloc(0);for(var n=c.allocUnsafe(r>>>0),o=this.head,f=0;o;)s(o.data,n,f),f+=o.data.length,o=o.next;return n},t}(),h&&h.inspect&&h.inspect.custom&&(d.exports.prototype[h.inspect.custom]=function(){var t=h.inspect({length:this.length});return this.constructor.name+" "+t})},{"safe-buffer":520,util:188}],514:[function(e,d,m){var l=e("process-nextick-args");function c(t,i){var r=this,n=this._readableState&&this._readableState.destroyed,o=this._writableState&&this._writableState.destroyed;return n||o?(i?i(t):t&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,l.nextTick(s,this,t)):l.nextTick(s,this,t)),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(t||null,function(f){!i&&f?r._writableState?r._writableState.errorEmitted||(r._writableState.errorEmitted=!0,l.nextTick(s,r,f)):l.nextTick(s,r,f):i&&i(f)}),this)}function h(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}function s(t,i){t.emit("error",i)}d.exports={destroy:c,undestroy:h}},{"process-nextick-args":466}],515:[function(e,d,m){arguments[4][490][0].apply(m,arguments)},{dup:490,events:422}],516:[function(e,d,m){d.exports=e("./readable").PassThrough},{"./readable":517}],517:[function(e,d,m){m=d.exports=e("./lib/_stream_readable.js"),m.Stream=m,m.Readable=m,m.Writable=e("./lib/_stream_writable.js"),m.Duplex=e("./lib/_stream_duplex.js"),m.Transform=e("./lib/_stream_transform.js"),m.PassThrough=e("./lib/_stream_passthrough.js")},{"./lib/_stream_duplex.js":508,"./lib/_stream_passthrough.js":509,"./lib/_stream_readable.js":510,"./lib/_stream_transform.js":511,"./lib/_stream_writable.js":512}],518:[function(e,d,m){d.exports=e("./readable").Transform},{"./readable":517}],519:[function(e,d,m){d.exports=e("./lib/_stream_writable.js")},{"./lib/_stream_writable.js":512}],520:[function(e,d,m){arguments[4][217][0].apply(m,arguments)},{buffer:220,dup:217}],521:[function(e,d,m){arguments[4][218][0].apply(m,arguments)},{dup:218,"safe-buffer":520}],522:[function(e,d,m){arguments[4][218][0].apply(m,arguments)},{dup:218,"safe-buffer":494}],523:[function(e,d,m){(function(l,c){(function(){var h=e("process/browser.js").nextTick,s=Function.prototype.apply,t=Array.prototype.slice,i={},r=0;m.setTimeout=function(){return new n(s.call(setTimeout,window,arguments),clearTimeout)},m.setInterval=function(){return new n(s.call(setInterval,window,arguments),clearInterval)},m.clearTimeout=m.clearInterval=function(o){o.close()};function n(o,f){this._id=o,this._clearFn=f}n.prototype.unref=n.prototype.ref=function(){},n.prototype.close=function(){this._clearFn.call(window,this._id)},m.enroll=function(o,f){clearTimeout(o._idleTimeoutId),o._idleTimeout=f},m.unenroll=function(o){clearTimeout(o._idleTimeoutId),o._idleTimeout=-1},m._unrefActive=m.active=function(o){clearTimeout(o._idleTimeoutId);var f=o._idleTimeout;f>=0&&(o._idleTimeoutId=setTimeout(function(){o._onTimeout&&o._onTimeout()},f))},m.setImmediate=typeof l=="function"?l:function(o){var f=r++,a=arguments.length<2?!1:t.call(arguments,1);return i[f]=!0,h(function(){i[f]&&(a?o.apply(null,a):o.call(null),m.clearImmediate(f))}),f},m.clearImmediate=typeof c=="function"?c:function(o){delete i[o]}}).call(this)}).call(this,e("timers").setImmediate,e("timers").clearImmediate)},{"process/browser.js":467,timers:523}],524:[function(e,d,m){(function(l){(function(){d.exports=c;function c(s,t){if(h("noDeprecation"))return s;var i=!1;function r(){if(!i){if(h("throwDeprecation"))throw new Error(t);h("traceDeprecation")?console.trace(t):console.warn(t),i=!0}return s.apply(this,arguments)}return r}function h(s){try{if(!l.localStorage)return!1}catch{return!1}var t=l.localStorage[s];return t==null?!1:String(t).toLowerCase()==="true"}}).call(this)}).call(this,typeof Dt<"u"?Dt:typeof self<"u"?self:typeof window<"u"?window:{})},{}],525:[function(e,d,m){typeof Object.create=="function"?d.exports=function(c,h){c.super_=h,c.prototype=Object.create(h.prototype,{constructor:{value:c,enumerable:!1,writable:!0,configurable:!0}})}:d.exports=function(c,h){c.super_=h;var s=function(){};s.prototype=h.prototype,c.prototype=new s,c.prototype.constructor=c}},{}],526:[function(e,d,m){d.exports=function(c){return c&&typeof c=="object"&&typeof c.copy=="function"&&typeof c.fill=="function"&&typeof c.readUInt8=="function"}},{}],527:[function(e,d,m){(function(l,c){(function(){var h=/%[sdj%]/g;m.format=function(R){if(!F(R)){for(var k=[],C=0;C=X)return ue;switch(ue){case"%s":return String(O[C++]);case"%d":return Number(O[C++]);case"%j":try{return JSON.stringify(O[C++])}catch{return"[Circular]"}default:return ue}}),he=O[C];C=3&&(C.depth=arguments[2]),arguments.length>=4&&(C.colors=arguments[3]),S(k)?C.showHidden=k:k&&m._extend(C,k),W(C.showHidden)&&(C.showHidden=!1),W(C.depth)&&(C.depth=2),W(C.colors)&&(C.colors=!1),W(C.customInspect)&&(C.customInspect=!0),C.colors&&(C.stylize=r),f(C,R,C.depth)}m.inspect=i,i.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},i.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"};function r(R,k){var C=i.styles[k];return C?"\x1B["+i.colors[C][0]+"m"+R+"\x1B["+i.colors[C][1]+"m":R}function n(R,k){return R}function o(R){var k={};return R.forEach(function(C,O){k[C]=!0}),k}function f(R,k,C){if(R.customInspect&&k&&M(k.inspect)&&k.inspect!==m.inspect&&!(k.constructor&&k.constructor.prototype===k)){var O=k.inspect(C,R);return F(O)||(O=f(R,O,C)),O}var X=a(R,k);if(X)return X;var ie=Object.keys(k),he=o(ie);if(R.showHidden&&(ie=Object.getOwnPropertyNames(k)),$(k)&&(ie.indexOf("message")>=0||ie.indexOf("description")>=0))return g(k);if(ie.length===0){if(M(k)){var ue=k.name?": "+k.name:"";return R.stylize("[Function"+ue+"]","special")}if(G(k))return R.stylize(RegExp.prototype.toString.call(k),"regexp");if(J(k))return R.stylize(Date.prototype.toString.call(k),"date");if($(k))return g(k)}var ke="",pe=!1,ee=["{","}"];if(y(k)&&(pe=!0,ee=["[","]"]),M(k)){var Z=k.name?": "+k.name:"";ke=" [Function"+Z+"]"}if(G(k)&&(ke=" "+RegExp.prototype.toString.call(k)),J(k)&&(ke=" "+Date.prototype.toUTCString.call(k)),$(k)&&(ke=" "+g(k)),ie.length===0&&(!pe||k.length==0))return ee[0]+ke+ee[1];if(C<0)return G(k)?R.stylize(RegExp.prototype.toString.call(k),"regexp"):R.stylize("[Object]","special");R.seen.push(k);var q;return pe?q=b(R,k,C,he,ie):q=ie.map(function(de){return u(R,k,C,he,de,pe)}),R.seen.pop(),w(q,ke,ee)}function a(R,k){if(W(k))return R.stylize("undefined","undefined");if(F(k)){var C="'"+JSON.stringify(k).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return R.stylize(C,"string")}if(P(k))return R.stylize(""+k,"number");if(S(k))return R.stylize(""+k,"boolean");if(E(k))return R.stylize("null","null")}function g(R){return"["+Error.prototype.toString.call(R)+"]"}function b(R,k,C,O,X){for(var ie=[],he=0,ue=k.length;he-1&&(ie?ue=ue.split(` +`).map(function(pe){return" "+pe}).join(` +`).substr(2):ue=` +`+ue.split(` +`).map(function(pe){return" "+pe}).join(` +`))):ue=R.stylize("[Circular]","special")),W(he)){if(ie&&X.match(/^\d+$/))return ue;he=JSON.stringify(""+X),he.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(he=he.substr(1,he.length-2),he=R.stylize(he,"name")):(he=he.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),he=R.stylize(he,"string"))}return he+": "+ue}function w(R,k,C){var O=R.reduce(function(X,ie){return ie.indexOf(` +`)>=0,X+ie.replace(/\u001b\[\d\d?m/g,"").length+1},0);return O>60?C[0]+(k===""?"":k+` + `)+" "+R.join(`, + `)+" "+C[1]:C[0]+k+" "+R.join(", ")+" "+C[1]}function y(R){return Array.isArray(R)}m.isArray=y;function S(R){return typeof R=="boolean"}m.isBoolean=S;function E(R){return R===null}m.isNull=E;function I(R){return R==null}m.isNullOrUndefined=I;function P(R){return typeof R=="number"}m.isNumber=P;function F(R){return typeof R=="string"}m.isString=F;function j(R){return typeof R=="symbol"}m.isSymbol=j;function W(R){return R===void 0}m.isUndefined=W;function G(R){return V(R)&&x(R)==="[object RegExp]"}m.isRegExp=G;function V(R){return typeof R=="object"&&R!==null}m.isObject=V;function J(R){return V(R)&&x(R)==="[object Date]"}m.isDate=J;function $(R){return V(R)&&(x(R)==="[object Error]"||R instanceof Error)}m.isError=$;function M(R){return typeof R=="function"}m.isFunction=M;function T(R){return R===null||typeof R=="boolean"||typeof R=="number"||typeof R=="string"||typeof R=="symbol"||typeof R>"u"}m.isPrimitive=T,m.isBuffer=e("./support/isBuffer");function x(R){return Object.prototype.toString.call(R)}function A(R){return R<10?"0"+R.toString(10):R.toString(10)}var N=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function L(){var R=new Date,k=[A(R.getHours()),A(R.getMinutes()),A(R.getSeconds())].join(":");return[R.getDate(),N[R.getMonth()],k].join(" ")}m.log=function(){console.log("%s - %s",L(),m.format.apply(m,arguments))},m.inherits=e("inherits"),m._extend=function(R,k){if(!k||!V(k))return R;for(var C=Object.keys(k),O=C.length;O--;)R[C[O]]=k[C[O]];return R};function z(R,k){return Object.prototype.hasOwnProperty.call(R,k)}}).call(this)}).call(this,e("_process"),typeof Dt<"u"?Dt:typeof self<"u"?self:typeof window<"u"?window:{})},{"./support/isBuffer":526,_process:467,inherits:525}],528:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),Object.defineProperty(m,"v1",{enumerable:!0,get:function(){return l.default}}),Object.defineProperty(m,"v3",{enumerable:!0,get:function(){return c.default}}),Object.defineProperty(m,"v4",{enumerable:!0,get:function(){return h.default}}),Object.defineProperty(m,"v5",{enumerable:!0,get:function(){return s.default}}),Object.defineProperty(m,"NIL",{enumerable:!0,get:function(){return t.default}}),Object.defineProperty(m,"version",{enumerable:!0,get:function(){return i.default}}),Object.defineProperty(m,"validate",{enumerable:!0,get:function(){return r.default}}),Object.defineProperty(m,"stringify",{enumerable:!0,get:function(){return n.default}}),Object.defineProperty(m,"parse",{enumerable:!0,get:function(){return o.default}});var l=f(e("./v1.js")),c=f(e("./v3.js")),h=f(e("./v4.js")),s=f(e("./v5.js")),t=f(e("./nil.js")),i=f(e("./version.js")),r=f(e("./validate.js")),n=f(e("./stringify.js")),o=f(e("./parse.js"));function f(a){return a&&a.__esModule?a:{default:a}}},{"./nil.js":530,"./parse.js":531,"./stringify.js":535,"./v1.js":536,"./v3.js":537,"./v4.js":539,"./v5.js":540,"./validate.js":541,"./version.js":542}],529:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.default=void 0;function l(u){if(typeof u=="string"){const w=unescape(encodeURIComponent(u));u=new Uint8Array(w.length);for(let y=0;y>5]>>>E%32&255,P=parseInt(S.charAt(I>>>4&15)+S.charAt(I&15),16);w.push(P)}return w}function h(u){return(u+64>>>9<<4)+14+1}function s(u,w){u[w>>5]|=128<>5]|=(u[S/8]&255)<>16)+(w>>16)+(y>>16)<<16|y&65535}function r(u,w){return u<>>32-w}function n(u,w,y,S,E,I){return i(r(i(i(w,u),i(S,I)),E),y)}function o(u,w,y,S,E,I,P){return n(w&y|~w&S,u,w,E,I,P)}function f(u,w,y,S,E,I,P){return n(w&S|y&~S,u,w,E,I,P)}function a(u,w,y,S,E,I,P){return n(w^y^S,u,w,E,I,P)}function g(u,w,y,S,E,I,P){return n(y^(w|~S),u,w,E,I,P)}var b=l;m.default=b},{}],530:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.default=void 0;var l="00000000-0000-0000-0000-000000000000";m.default=l},{}],531:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.default=void 0;var l=c(e("./validate.js"));function c(t){return t&&t.__esModule?t:{default:t}}function h(t){if(!(0,l.default)(t))throw TypeError("Invalid UUID");let i;const r=new Uint8Array(16);return r[0]=(i=parseInt(t.slice(0,8),16))>>>24,r[1]=i>>>16&255,r[2]=i>>>8&255,r[3]=i&255,r[4]=(i=parseInt(t.slice(9,13),16))>>>8,r[5]=i&255,r[6]=(i=parseInt(t.slice(14,18),16))>>>8,r[7]=i&255,r[8]=(i=parseInt(t.slice(19,23),16))>>>8,r[9]=i&255,r[10]=(i=parseInt(t.slice(24,36),16))/1099511627776&255,r[11]=i/4294967296&255,r[12]=i>>>24&255,r[13]=i>>>16&255,r[14]=i>>>8&255,r[15]=i&255,r}var s=h;m.default=s},{"./validate.js":541}],532:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.default=void 0;var l=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;m.default=l},{}],533:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.default=h;let l;const c=new Uint8Array(16);function h(){if(!l&&(l=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||typeof msCrypto<"u"&&typeof msCrypto.getRandomValues=="function"&&msCrypto.getRandomValues.bind(msCrypto),!l))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return l(c)}},{}],534:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.default=void 0;function l(t,i,r,n){switch(t){case 0:return i&r^~i&n;case 1:return i^r^n;case 2:return i&r^i&n^r&n;case 3:return i^r^n}}function c(t,i){return t<>>32-i}function h(t){const i=[1518500249,1859775393,2400959708,3395469782],r=[1732584193,4023233417,2562383102,271733878,3285377520];if(typeof t=="string"){const a=unescape(encodeURIComponent(t));t=[];for(let g=0;g>>0;S=y,y=w,w=c(u,30)>>>0,u=b,b=P}r[0]=r[0]+b>>>0,r[1]=r[1]+u>>>0,r[2]=r[2]+w>>>0,r[3]=r[3]+y>>>0,r[4]=r[4]+S>>>0}return[r[0]>>24&255,r[0]>>16&255,r[0]>>8&255,r[0]&255,r[1]>>24&255,r[1]>>16&255,r[1]>>8&255,r[1]&255,r[2]>>24&255,r[2]>>16&255,r[2]>>8&255,r[2]&255,r[3]>>24&255,r[3]>>16&255,r[3]>>8&255,r[3]&255,r[4]>>24&255,r[4]>>16&255,r[4]>>8&255,r[4]&255]}var s=h;m.default=s},{}],535:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.default=void 0;var l=c(e("./validate.js"));function c(i){return i&&i.__esModule?i:{default:i}}const h=[];for(let i=0;i<256;++i)h.push((i+256).toString(16).substr(1));function s(i){let r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0;const n=(h[i[r+0]]+h[i[r+1]]+h[i[r+2]]+h[i[r+3]]+"-"+h[i[r+4]]+h[i[r+5]]+"-"+h[i[r+6]]+h[i[r+7]]+"-"+h[i[r+8]]+h[i[r+9]]+"-"+h[i[r+10]]+h[i[r+11]]+h[i[r+12]]+h[i[r+13]]+h[i[r+14]]+h[i[r+15]]).toLowerCase();if(!(0,l.default)(n))throw TypeError("Stringified UUID is invalid");return n}var t=s;m.default=t},{"./validate.js":541}],536:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.default=void 0;var l=h(e("./rng.js")),c=h(e("./stringify.js"));function h(f){return f&&f.__esModule?f:{default:f}}let s,t,i=0,r=0;function n(f,a,g){let b=a&&g||0;const u=a||new Array(16);f=f||{};let w=f.node||s,y=f.clockseq!==void 0?f.clockseq:t;if(w==null||y==null){const j=f.random||(f.rng||l.default)();w==null&&(w=s=[j[0]|1,j[1],j[2],j[3],j[4],j[5]]),y==null&&(y=t=(j[6]<<8|j[7])&16383)}let S=f.msecs!==void 0?f.msecs:Date.now(),E=f.nsecs!==void 0?f.nsecs:r+1;const I=S-i+(E-r)/1e4;if(I<0&&f.clockseq===void 0&&(y=y+1&16383),(I<0||S>i)&&f.nsecs===void 0&&(E=0),E>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");i=S,r=E,t=y,S+=122192928e5;const P=((S&268435455)*1e4+E)%4294967296;u[b++]=P>>>24&255,u[b++]=P>>>16&255,u[b++]=P>>>8&255,u[b++]=P&255;const F=S/4294967296*1e4&268435455;u[b++]=F>>>8&255,u[b++]=F&255,u[b++]=F>>>24&15|16,u[b++]=F>>>16&255,u[b++]=y>>>8|128,u[b++]=y&255;for(let j=0;j<6;++j)u[b+j]=w[j];return a||(0,c.default)(u)}var o=n;m.default=o},{"./rng.js":533,"./stringify.js":535}],537:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.default=void 0;var l=h(e("./v35.js")),c=h(e("./md5.js"));function h(i){return i&&i.__esModule?i:{default:i}}var t=(0,l.default)("v3",48,c.default);m.default=t},{"./md5.js":529,"./v35.js":538}],538:[function(e,d,m){Object.defineProperty(m,"__esModule",{value:!0}),m.default=r,m.URL=m.DNS=void 0;var l=h(e("./stringify.js")),c=h(e("./parse.js"));function h(n){return n&&n.__esModule?n:{default:n}}function s(n){n=unescape(encodeURIComponent(n));const o=[];for(let f=0;f=s&&o<=55295||o===c||o===h||o===l||o>=57344&&o<=65533||o>=65536&&o<=1114111}m.isChar=t;function i(o){return o===s||o===c||o===h||o===l}m.isS=i;function r(o){return o>=65&&o<=90||o>=97&&o<=122||o===58||o===95||o===8204||o===8205||o>=192&&o<=214||o>=216&&o<=246||o>=248&&o<=767||o>=880&&o<=893||o>=895&&o<=8191||o>=8304&&o<=8591||o>=11264&&o<=12271||o>=12289&&o<=55295||o>=63744&&o<=64975||o>=65008&&o<=65533||o>=65536&&o<=983039}m.isNameStartChar=r;function n(o){return r(o)||o>=48&&o<=57||o===45||o===46||o===183||o>=768&&o<=879||o>=8255&&o<=8256}m.isNameChar=n},{}],544:[function(e,d,m){/** +* Character classes and associated utilities for the 2nd edition of XML 1.1. +* +* @author Louis-Dominique Dubeau +* @license MIT +* @copyright Louis-Dominique Dubeau +*/Object.defineProperty(m,"__esModule",{value:!0}),m.CHAR="-퟿-�𐀀-􏿿",m.RESTRICTED_CHAR="-\b\v\f--„†-Ÿ",m.S=` \r +`,m.NAME_START_CHAR=":A-Z_a-zÀ-ÖØ-öø-˿Ͱ-ͽͿ-῿‌‍⁰-↏Ⰰ-⿯、-퟿豈-﷏ﷰ-�𐀀-󯿿",m.NAME_CHAR="-"+m.NAME_START_CHAR+".0-9·̀-ͯ‿-⁀",m.CHAR_RE=new RegExp("^["+m.CHAR+"]$","u"),m.RESTRICTED_CHAR_RE=new RegExp("^["+m.RESTRICTED_CHAR+"]$","u"),m.S_RE=new RegExp("^["+m.S+"]+$","u"),m.NAME_START_CHAR_RE=new RegExp("^["+m.NAME_START_CHAR+"]$","u"),m.NAME_CHAR_RE=new RegExp("^["+m.NAME_CHAR+"]$","u"),m.NAME_RE=new RegExp("^["+m.NAME_START_CHAR+"]["+m.NAME_CHAR+"]*$","u"),m.NMTOKEN_RE=new RegExp("^["+m.NAME_CHAR+"]+$","u");var l=9,c=10,h=13,s=32;m.S_LIST=[s,c,h,l];function t(a){return a>=1&&a<=55295||a>=57344&&a<=65533||a>=65536&&a<=1114111}m.isChar=t;function i(a){return a>=1&&a<=8||a===11||a===12||a>=14&&a<=31||a>=127&&a<=132||a>=134&&a<=159}m.isRestrictedChar=i;function r(a){return a===9||a===10||a===13||a>31&&a<127||a===133||a>159&&a<=55295||a>=57344&&a<=65533||a>=65536&&a<=1114111}m.isCharAndNotRestricted=r;function n(a){return a===s||a===c||a===h||a===l}m.isS=n;function o(a){return a>=65&&a<=90||a>=97&&a<=122||a===58||a===95||a===8204||a===8205||a>=192&&a<=214||a>=216&&a<=246||a>=248&&a<=767||a>=880&&a<=893||a>=895&&a<=8191||a>=8304&&a<=8591||a>=11264&&a<=12271||a>=12289&&a<=55295||a>=63744&&a<=64975||a>=65008&&a<=65533||a>=65536&&a<=983039}m.isNameStartChar=o;function f(a){return o(a)||a>=48&&a<=57||a===45||a===46||a===183||a>=768&&a<=879||a>=8255&&a<=8256}m.isNameChar=f},{}],545:[function(e,d,m){/** +* Character class utilities for XML NS 1.0 edition 3. +* +* @author Louis-Dominique Dubeau +* @license MIT +* @copyright Louis-Dominique Dubeau +*/Object.defineProperty(m,"__esModule",{value:!0}),m.NC_NAME_START_CHAR="A-Z_a-zÀ-ÖØ-öø-˿Ͱ-ͽͿ-῿‌-‍⁰-↏Ⰰ-⿯、-퟿豈-﷏ﷰ-�𐀀-󯿿",m.NC_NAME_CHAR="-"+m.NC_NAME_START_CHAR+".0-9·̀-ͯ‿-⁀",m.NC_NAME_START_CHAR_RE=new RegExp("^["+m.NC_NAME_START_CHAR+"]$","u"),m.NC_NAME_CHAR_RE=new RegExp("^["+m.NC_NAME_CHAR+"]$","u"),m.NC_NAME_RE=new RegExp("^["+m.NC_NAME_START_CHAR+"]["+m.NC_NAME_CHAR+"]*$","u");function l(h){return h>=65&&h<=90||h===95||h>=97&&h<=122||h>=192&&h<=214||h>=216&&h<=246||h>=248&&h<=767||h>=880&&h<=893||h>=895&&h<=8191||h>=8204&&h<=8205||h>=8304&&h<=8591||h>=11264&&h<=12271||h>=12289&&h<=55295||h>=63744&&h<=64975||h>=65008&&h<=65533||h>=65536&&h<=983039}m.isNCNameStartChar=l;function c(h){return l(h)||h===45||h===46||h>=48&&h<=57||h===183||h>=768&&h<=879||h>=8255&&h<=8256}m.isNCNameChar=c},{}]},{},[15])(15)})})(kh);var Ib=kh.exports;function Qa(B){"@babel/helpers - typeof";return Qa=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(v){return typeof v}:function(v){return v&&typeof Symbol=="function"&&v.constructor===Symbol&&v!==Symbol.prototype?"symbol":typeof v},Qa(B)}var Ob=/^\s+/,Pb=/\s+$/;function ht(B,v){if(B=B||"",v=v||{},B instanceof ht)return B;if(!(this instanceof ht))return new ht(B,v);var e=Nb(B);this._originalInput=B,this._r=e.r,this._g=e.g,this._b=e.b,this._a=e.a,this._roundA=Math.round(100*this._a)/100,this._format=v.format||e.format,this._gradientType=v.gradientType,this._r<1&&(this._r=Math.round(this._r)),this._g<1&&(this._g=Math.round(this._g)),this._b<1&&(this._b=Math.round(this._b)),this._ok=e.ok}ht.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var v=this.toRgb();return(v.r*299+v.g*587+v.b*114)/1e3},getLuminance:function(){var v=this.toRgb(),e,d,m,l,c,h;return e=v.r/255,d=v.g/255,m=v.b/255,e<=.03928?l=e/12.92:l=Math.pow((e+.055)/1.055,2.4),d<=.03928?c=d/12.92:c=Math.pow((d+.055)/1.055,2.4),m<=.03928?h=m/12.92:h=Math.pow((m+.055)/1.055,2.4),.2126*l+.7152*c+.0722*h},setAlpha:function(v){return this._a=Mh(v),this._roundA=Math.round(100*this._a)/100,this},toHsv:function(){var v=qc(this._r,this._g,this._b);return{h:v.h*360,s:v.s,v:v.v,a:this._a}},toHsvString:function(){var v=qc(this._r,this._g,this._b),e=Math.round(v.h*360),d=Math.round(v.s*100),m=Math.round(v.v*100);return this._a==1?"hsv("+e+", "+d+"%, "+m+"%)":"hsva("+e+", "+d+"%, "+m+"%, "+this._roundA+")"},toHsl:function(){var v=Qc(this._r,this._g,this._b);return{h:v.h*360,s:v.s,l:v.l,a:this._a}},toHslString:function(){var v=Qc(this._r,this._g,this._b),e=Math.round(v.h*360),d=Math.round(v.s*100),m=Math.round(v.l*100);return this._a==1?"hsl("+e+", "+d+"%, "+m+"%)":"hsla("+e+", "+d+"%, "+m+"%, "+this._roundA+")"},toHex:function(v){return eh(this._r,this._g,this._b,v)},toHexString:function(v){return"#"+this.toHex(v)},toHex8:function(v){return Lb(this._r,this._g,this._b,this._a,v)},toHex8String:function(v){return"#"+this.toHex8(v)},toRgb:function(){return{r:Math.round(this._r),g:Math.round(this._g),b:Math.round(this._b),a:this._a}},toRgbString:function(){return this._a==1?"rgb("+Math.round(this._r)+", "+Math.round(this._g)+", "+Math.round(this._b)+")":"rgba("+Math.round(this._r)+", "+Math.round(this._g)+", "+Math.round(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:Math.round(dr(this._r,255)*100)+"%",g:Math.round(dr(this._g,255)*100)+"%",b:Math.round(dr(this._b,255)*100)+"%",a:this._a}},toPercentageRgbString:function(){return this._a==1?"rgb("+Math.round(dr(this._r,255)*100)+"%, "+Math.round(dr(this._g,255)*100)+"%, "+Math.round(dr(this._b,255)*100)+"%)":"rgba("+Math.round(dr(this._r,255)*100)+"%, "+Math.round(dr(this._g,255)*100)+"%, "+Math.round(dr(this._b,255)*100)+"%, "+this._roundA+")"},toName:function(){return this._a===0?"transparent":this._a<1?!1:Zb[eh(this._r,this._g,this._b,!0)]||!1},toFilter:function(v){var e="#"+th(this._r,this._g,this._b,this._a),d=e,m=this._gradientType?"GradientType = 1, ":"";if(v){var l=ht(v);d="#"+th(l._r,l._g,l._b,l._a)}return"progid:DXImageTransform.Microsoft.gradient("+m+"startColorstr="+e+",endColorstr="+d+")"},toString:function(v){var e=!!v;v=v||this._format;var d=!1,m=this._a<1&&this._a>=0,l=!e&&m&&(v==="hex"||v==="hex6"||v==="hex3"||v==="hex4"||v==="hex8"||v==="name");return l?v==="name"&&this._a===0?this.toName():this.toRgbString():(v==="rgb"&&(d=this.toRgbString()),v==="prgb"&&(d=this.toPercentageRgbString()),(v==="hex"||v==="hex6")&&(d=this.toHexString()),v==="hex3"&&(d=this.toHexString(!0)),v==="hex4"&&(d=this.toHex8String(!0)),v==="hex8"&&(d=this.toHex8String()),v==="name"&&(d=this.toName()),v==="hsl"&&(d=this.toHslString()),v==="hsv"&&(d=this.toHsvString()),d||this.toHexString())},clone:function(){return ht(this.toString())},_applyModification:function(v,e){var d=v.apply(null,[this].concat([].slice.call(e)));return this._r=d._r,this._g=d._g,this._b=d._b,this.setAlpha(d._a),this},lighten:function(){return this._applyModification(Hb,arguments)},brighten:function(){return this._applyModification(Ub,arguments)},darken:function(){return this._applyModification(Xb,arguments)},desaturate:function(){return this._applyModification(jb,arguments)},saturate:function(){return this._applyModification($b,arguments)},greyscale:function(){return this._applyModification(zb,arguments)},spin:function(){return this._applyModification(Wb,arguments)},_applyCombination:function(v,e){return v.apply(null,[this].concat([].slice.call(e)))},analogous:function(){return this._applyCombination(Gb,arguments)},complement:function(){return this._applyCombination(Vb,arguments)},monochromatic:function(){return this._applyCombination(Yb,arguments)},splitcomplement:function(){return this._applyCombination(Kb,arguments)},triad:function(){return this._applyCombination(rh,[3])},tetrad:function(){return this._applyCombination(rh,[4])}};ht.fromRatio=function(B,v){if(Qa(B)=="object"){var e={};for(var d in B)B.hasOwnProperty(d)&&(d==="a"?e[d]=B[d]:e[d]=Ws(B[d]));B=e}return ht(B,v)};function Nb(B){var v={r:0,g:0,b:0},e=1,d=null,m=null,l=null,c=!1,h=!1;return typeof B=="string"&&(B=ey(B)),Qa(B)=="object"&&(an(B.r)&&an(B.g)&&an(B.b)?(v=Db(B.r,B.g,B.b),c=!0,h=String(B.r).substr(-1)==="%"?"prgb":"rgb"):an(B.h)&&an(B.s)&&an(B.v)?(d=Ws(B.s),m=Ws(B.v),v=Fb(B.h,d,m),c=!0,h="hsv"):an(B.h)&&an(B.s)&&an(B.l)&&(d=Ws(B.s),l=Ws(B.l),v=Bb(B.h,d,l),c=!0,h="hsl"),B.hasOwnProperty("a")&&(e=B.a)),e=Mh(e),{ok:c,format:B.format||h,r:Math.min(255,Math.max(v.r,0)),g:Math.min(255,Math.max(v.g,0)),b:Math.min(255,Math.max(v.b,0)),a:e}}function Db(B,v,e){return{r:dr(B,255)*255,g:dr(v,255)*255,b:dr(e,255)*255}}function Qc(B,v,e){B=dr(B,255),v=dr(v,255),e=dr(e,255);var d=Math.max(B,v,e),m=Math.min(B,v,e),l,c,h=(d+m)/2;if(d==m)l=c=0;else{var s=d-m;switch(c=h>.5?s/(2-d-m):s/(d+m),d){case B:l=(v-e)/s+(v1&&(r-=1),r<1/6?t+(i-t)*6*r:r<1/2?i:r<2/3?t+(i-t)*(2/3-r)*6:t}if(v===0)d=m=l=e;else{var h=e<.5?e*(1+v):e+v-e*v,s=2*e-h;d=c(s,h,B+1/3),m=c(s,h,B),l=c(s,h,B-1/3)}return{r:d*255,g:m*255,b:l*255}}function qc(B,v,e){B=dr(B,255),v=dr(v,255),e=dr(e,255);var d=Math.max(B,v,e),m=Math.min(B,v,e),l,c,h=d,s=d-m;if(c=d===0?0:s/d,d==m)l=0;else{switch(d){case B:l=(v-e)/s+(v>1)+720)%360;--v;)d.h=(d.h+m)%360,l.push(ht(d));return l}function Yb(B,v){v=v||6;for(var e=ht(B).toHsv(),d=e.h,m=e.s,l=e.v,c=[],h=1/v;v--;)c.push(ht({h:d,s:m,v:l})),l=(l+h)%1;return c}ht.mix=function(B,v,e){e=e===0?0:e||50;var d=ht(B).toRgb(),m=ht(v).toRgb(),l=e/100,c={r:(m.r-d.r)*l+d.r,g:(m.g-d.g)*l+d.g,b:(m.b-d.b)*l+d.b,a:(m.a-d.a)*l+d.a};return ht(c)};ht.readability=function(B,v){var e=ht(B),d=ht(v);return(Math.max(e.getLuminance(),d.getLuminance())+.05)/(Math.min(e.getLuminance(),d.getLuminance())+.05)};ht.isReadable=function(B,v,e){var d=ht.readability(B,v),m,l;switch(l=!1,m=ty(e),m.level+m.size){case"AAsmall":case"AAAlarge":l=d>=4.5;break;case"AAlarge":l=d>=3;break;case"AAAsmall":l=d>=7;break}return l};ht.mostReadable=function(B,v,e){var d=null,m=0,l,c,h,s;e=e||{},c=e.includeFallbackColors,h=e.level,s=e.size;for(var t=0;tm&&(m=l,d=ht(v[t]));return ht.isReadable(B,d,{level:h,size:s})||!c?d:(e.includeFallbackColors=!1,ht.mostReadable(B,["#fff","#000"],e))};var yl=ht.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},Zb=ht.hexNames=Jb(yl);function Jb(B){var v={};for(var e in B)B.hasOwnProperty(e)&&(v[B[e]]=e);return v}function Mh(B){return B=parseFloat(B),(isNaN(B)||B<0||B>1)&&(B=1),B}function dr(B,v){Qb(B)&&(B="100%");var e=qb(B);return B=Math.min(v,Math.max(0,parseFloat(B))),e&&(B=parseInt(B*v,10)/100),Math.abs(B-v)<1e-6?1:B%v/parseFloat(v)}function to(B){return Math.min(1,Math.max(0,B))}function di(B){return parseInt(B,16)}function Qb(B){return typeof B=="string"&&B.indexOf(".")!=-1&&parseFloat(B)===1}function qb(B){return typeof B=="string"&&B.indexOf("%")!=-1}function Bi(B){return B.length==1?"0"+B:""+B}function Ws(B){return B<=1&&(B=B*100+"%"),B}function Rh(B){return Math.round(parseFloat(B)*255).toString(16)}function ih(B){return di(B)/255}var Di=function(){var B="[-\\+]?\\d+%?",v="[-\\+]?\\d*\\.\\d+%?",e="(?:"+v+")|(?:"+B+")",d="[\\s|\\(]+("+e+")[,|\\s]+("+e+")[,|\\s]+("+e+")\\s*\\)?",m="[\\s|\\(]+("+e+")[,|\\s]+("+e+")[,|\\s]+("+e+")[,|\\s]+("+e+")\\s*\\)?";return{CSS_UNIT:new RegExp(e),rgb:new RegExp("rgb"+d),rgba:new RegExp("rgba"+m),hsl:new RegExp("hsl"+d),hsla:new RegExp("hsla"+m),hsv:new RegExp("hsv"+d),hsva:new RegExp("hsva"+m),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}}();function an(B){return!!Di.CSS_UNIT.exec(B)}function ey(B){B=B.replace(Ob,"").replace(Pb,"").toLowerCase();var v=!1;if(yl[B])B=yl[B],v=!0;else if(B=="transparent")return{r:0,g:0,b:0,a:0,format:"name"};var e;return(e=Di.rgb.exec(B))?{r:e[1],g:e[2],b:e[3]}:(e=Di.rgba.exec(B))?{r:e[1],g:e[2],b:e[3],a:e[4]}:(e=Di.hsl.exec(B))?{h:e[1],s:e[2],l:e[3]}:(e=Di.hsla.exec(B))?{h:e[1],s:e[2],l:e[3],a:e[4]}:(e=Di.hsv.exec(B))?{h:e[1],s:e[2],v:e[3]}:(e=Di.hsva.exec(B))?{h:e[1],s:e[2],v:e[3],a:e[4]}:(e=Di.hex8.exec(B))?{r:di(e[1]),g:di(e[2]),b:di(e[3]),a:ih(e[4]),format:v?"name":"hex8"}:(e=Di.hex6.exec(B))?{r:di(e[1]),g:di(e[2]),b:di(e[3]),format:v?"name":"hex"}:(e=Di.hex4.exec(B))?{r:di(e[1]+""+e[1]),g:di(e[2]+""+e[2]),b:di(e[3]+""+e[3]),a:ih(e[4]+""+e[4]),format:v?"name":"hex8"}:(e=Di.hex3.exec(B))?{r:di(e[1]+""+e[1]),g:di(e[2]+""+e[2]),b:di(e[3]+""+e[3]),format:v?"name":"hex"}:!1}function ty(B){var v,e;return B=B||{level:"AA",size:"small"},v=(B.level||"AA").toUpperCase(),e=(B.size||"small").toLowerCase(),v!=="AA"&&v!=="AAA"&&(v="AA"),e!=="small"&&e!=="large"&&(e="small"),{level:v,size:e}}const sl=["#FFFFFF","#000000","#BFBFBF","#323232","#4472C4","#ED7D31","#A5A5A5","#FFC000","#5B9BD5","#71AD47"],al=["#000000","#FFFFFF","#FF0000","#00FF00","#0000FF","#FFFF00","#FF00FF","#00FFFF","#000000","#FFFFFF","#FF0000","#00FF00","#0000FF","#FFFF00","#FF00FF","#00FFFF","#800000","#008000","#000080","#808000","#800080","#008080","#C0C0C0","#808080","#9999FF","#993366","#FFFFCC","#CCFFFF","#660066","#FF8080","#0066CC","#CCCCFF","#000080","#FF00FF","#FFFF00","#00FFFF","#800080","#800000","#008080","#0000FF","#00CCFF","#CCFFFF","#CCFFCC","#FFFF99","#99CCFF","#FF99CC","#CC99FF","#FFCC99","#3366FF","#33CCCC","#99CC00","#FFCC00","#FF9900","#FF6600","#666699","#969696","#003366","#339966","#003300","#333300","#993300","#993366","#333399","#333333","#FFFFFF"],nh=80,sh=24;function ry(B){try{return new Ib.Workbook().xlsx.load(B)}catch(v){return console.warn(v),Promise.reject(v)}}function iy(B,v,e){for(let d=0;d<(B.columns||[]).length;d++)v.cols[d.toString()]={},B.columns[d].width?v.cols[d.toString()].width=nh+B.columns[d].width*6+(e.widthOffset||0):v.cols[d.toString()].width=nh+(e.widthOffset||0);v.cols.len=Math.max(Object.keys(v.cols).length,e.minColLength||0)}function ny(B){const{numFmt:v,value:e,type:d}=B;switch(d){case 2:try{if(B.style.numFmt){if(B.style.numFmt.endsWith("%")){const m=B.style.numFmt.match(/\.(\d+)%/);return m?(Number(e)*100).toFixed(m[1].length)+"%":Number(e)*100+"%"}else if(/0(?:\.0+)?/.test(B.style.numFmt)){if(Number(e)===0&&B.style.numFmt.startsWith("_"))return"-";let m=B.style.numFmt.match(/0\.(0+)(_|;|$)/);m?m=m[1].length:m=0;let l=Number(e).toFixed(m)+"";if(B.style.numFmt.includes("#,##")){l=l.split(".");const c=l[0].split("").reverse(),h=[];for(let s=0;s9?"#C7C9CC":typeof v>"u"?sl[B]:v>0?eg(sl[B],v):tg(sl[B],Math.abs(v))}function sy(B){B.style=qa.cloneDeep(B.style);let v=null;B.style.fill&&B.style.fill.fgColor&&(B.style.fill.fgColor.argb?v=ol(B.style.fill.fgColor.argb):Object.prototype.hasOwnProperty.call(B.style.fill.fgColor,"theme")?v=ll(B.style.fill.fgColor.theme,B.style.fill.fgColor.tint):B.style.fill.fgColor.indexed?v=al[B.style.fill.fgColor.indexed]||"#C7C9CC":v="#C7C9CC"),v&&(B.style.bgcolor=v);let e=null;if(B.style.font&&B.style.font.color&&(B.style.font.color.argb?e=ol(B.style.font.color.argb):Object.prototype.hasOwnProperty.call(B.style.font.color,"theme")?e=ll(B.style.font.color.theme,B.style.font.color.tint):B.style.font.color.indexed?e=al[B.style.font.color.indexed]||"#000000":e="#000000"),e&&(B.style.color=e),B.style.alignment&&(B.style.alignment.horizontal&&(B.style.align="middle"),B.style.alignment.vertical&&(B.style.valign="top")),B.style.alignment&&B.style.alignment.wrapText&&(B.style.textwrap=!0),B.style.border){const d={};Object.keys(B.style.border).forEach(m=>{const l=B.style.border[m];let c="#000000";typeof l.color=="string"?c=l.color:l.color&&(l.color.argb?c=ol(l.color.argb)||"":Object.prototype.hasOwnProperty.call(l.color,"theme")?c=ll(l.color.theme,l.color.tint):l.color.indexed&&(c=al[l.color.indexed])),d[m]=[l.style||"thin",c]}),B.style.border2={...B.style.border},B.style.border=d}return B.style}function ay(B,v){const e=[];return B.eachSheet(d=>{const m={name:d.name,styles:[],rows:{},cols:{},merges:[],media:[]},l=[];for(const c in d._merges){m.merges.push(d._merges[c].shortRange);const h={};h.startAddress=d._merges[c].tl,h.endAddress=d._merges[c].br,h.YRange=d._merges[c].model.bottom-d._merges[c].model.top,h.XRange=d._merges[c].model.right-d._merges[c].model.left,l.push(h)}iy(d,m,v),(d._rows||[]).forEach((c,h)=>{m.rows[h]={cells:{}},c.height?m.rows[h].height=sh+c.height+(v.heightOffset||0):m.rows[h].height=sh+(v.heightOffset||0),(c._cells||[]).forEach((s,t)=>{m.rows[h].cells[t]={};const i=qa.find(l,function(r){return r.startAddress===s._address});i&&s.master.address!==i.startAddress||(i&&(m.rows[h].cells[t].merge=[i.YRange,i.XRange]),m.rows[h].cells[t].text=ny(s),m.styles.push(sy(s)),m.rows[h].cells[t].style=m.styles.length-1)})}),m._media&&(m.media=m._media),m.rows.len=Math.max(Object.keys(m.rows).length,100),e.push(m)}),{workbookData:e,workbookSource:B,medias:B.media||[]}}let Ha=[];function ja(B,v,e,d){e&&e._media.length&&e._media.forEach(m=>{const{imageId:l,range:c,type:h}=m;if(h==="image"){const s=oy(e,c,d);ly(B,l,v[l],s)}})}const Ua=60,Xa=25,fl=80,cl=24,Ui=window.devicePixelRatio;function oy(B,v,e){var d,m,l,c,h,s,t,i,r,n,o,f,a,g;const{tl:b={},br:u={}}=v,{nativeCol:w,nativeColOff:y,nativeRow:S,nativeRowOff:E}=b;let I=Ua,P=Xa;for(let T=0;T{let l=0,c=0,h=m.width,s=m.height,t=d.x,i=d.y,r=d.width,n=d.height;const o=r/h,f=n/s;if(t{})}function fy(B,v){return new Promise((e,d)=>{if(Ha[B])return e(Ha[B]);const{buffer:m,extension:l}=v.buffer,c=new Blob([m],{type:"image/"+l}),h=URL.createObjectURL(c),s=new Image;s.src=h,s.onload=function(){e(s),Ha[B]=s},s.onerror=function(t){d(t)}})}function cy(B){if(B){const v=B.querySelectorAll("input");for(const e of v)e&&!e.readOnly&&(e.readOnly=!0)}}const hy={minColLength:20};class uy{constructor(v,e={}){Si(this,"container"),Si(this,"options",{}),Si(this,"wrapper"),Si(this,"wrapperMain"),Si(this,"xs"),Si(this,"sheetIndex"),Si(this,"mediasSource"),Si(this,"workbookDataSource"),Si(this,"ctx"),Si(this,"fileData"),Si(this,"observer"),Si(this,"offset"),this.container=v,this.options={...hy,...e},this.sheetIndex=1,this.mediasSource={},this.workbookDataSource={_worksheets:[]},this.createWrapper(),this.initSpreadsheet(),this.hack()}createWrapper(){this.wrapper=document.createElement("div"),this.wrapper.className="r-preview-excel-main",this.container.appendChild(this.wrapper)}async initSpreadsheet(){var v;if(!this.wrapper&&typeof window<"u"||(this.xs=new Ah(this.wrapper,{mode:"read",showToolbar:!1,showContextmenu:this.options.showContextmenu||!1,view:{height:()=>this.wrapper&&this.wrapper.clientHeight||300,width:()=>this.wrapper&&this.wrapper.clientWidth||1200},row:{height:24,len:100},col:{len:26,width:80,indexWidth:60,minWidth:60}}).loadData({}),!this.xs))return;if(this.xs.bottombar){const d=this.xs.bottombar.swapFunc;this.xs.bottombar.swapFunc=m=>{var l;d.call((l=this.xs)==null?void 0:l.bottombar,m),this.sheetIndex=m+1,setTimeout(()=>{var c,h;(c=this.xs)!=null&&c.reRender&&((h=this.xs)==null||h.reRender()),this.mediasSource&&this.ctx&&this.offset&&ja(this.ctx,this.mediasSource,this.workbookDataSource._worksheets[this.sheetIndex],this.offset)})}}if((v=this.xs.sheet)!=null&&v.editor){const d=this.xs.sheet.editor.clear;this.xs.sheet.editor.clear=(...l)=>{var c,h;d.apply((h=(c=this.xs)==null?void 0:c.sheet)==null?void 0:h.editor,l),setTimeout(()=>{this.ctx&&this.mediasSource&&this.offset&&ja(this.ctx,this.mediasSource,this.workbookDataSource._worksheets[this.sheetIndex],this.offset)})};const m=this.xs.sheet.editor.setOffset;this.xs.sheet.editor.setOffset=(...l)=>{var c,h;m.apply((h=(c=this.xs)==null?void 0:c.sheet)==null?void 0:h.editor,l),l.length>1&&(this.offset=l.shift()),this.ctx&&this.mediasSource&&this.offset&&ja(this.ctx,this.mediasSource,this.workbookDataSource._worksheets[this.sheetIndex],this.offset)}}const e=this.wrapper&&this.wrapper.querySelector("canvas");e&&(this.ctx=e.getContext("2d"))}renderExcel(v,e,d){return this.fileData=v,ry(v).then(m=>{var l;if(!m._worksheets||m._worksheets.length===0)throw e&&e({success:!1,data:null,message:"未获取到数据,可能文件格式不正确或文件已损坏"}),new Error("未获取到数据,可能文件格式不正确或文件已损坏");const{workbookData:c,medias:h,workbookSource:s}=ay(m,this.options);this.mediasSource=h,this.workbookDataSource=s,this.offset=void 0,this.sheetIndex=1,ah(),(l=this.xs)==null||l.loadData(c),this.ctx&&this.mediasSource&&this.offset&&ja(this.ctx,this.mediasSource,this.workbookDataSource._worksheets[this.sheetIndex],this.offset),d&&d({success:!0,data:m})}).catch(m=>{var l;return this.mediasSource=[],this.workbookDataSource={_worksheets:[]},ah(),(l=this.xs)==null||l.loadData({}),e&&e({success:!1,message:"未获取到数据,可能文件格式不正确或文件已损坏"}),Promise.reject(m)})}hack(){if(!this.wrapper)return;const v=qa.debounce(cy,200).bind(this,this.wrapper);this.observer=new MutationObserver(v);const e={attributes:!0,childList:!0,subtree:!0};this.observer.observe(this.wrapper,e),v()}}const Sy=(B,v)=>{const{dom:e,onError:d,onLoad:m}=v;if(!e)return Promise.reject();const l=new uy(e);return new Promise((h,s)=>{const t=new FileReader;t.readAsArrayBuffer(B),t.onload=()=>{t.result?h(t==null?void 0:t.result):s()}}).then(h=>{l.renderExcel(h,d,m)})};export{Sy as renderExcel}; diff --git a/assets/chunks/index-Co9E57uv.BBrTYzuH.js b/assets/chunks/index-Co9E57uv.BBrTYzuH.js new file mode 100644 index 0000000000..faba7eacde --- /dev/null +++ b/assets/chunks/index-Co9E57uv.BBrTYzuH.js @@ -0,0 +1,10 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/chunks/jszip.min-BIf20mgf.BsDI-Ugu.js","assets/chunks/commonjs-dynamic-modules-DLbDWi6a.CRNIONdy.js"])))=>i.map(i=>d[i]); +import{ag as gc}from"./framework.C-ai2y4t.js";import{C as da}from"./colz-DJZvo_8B.DBiU5Tau.js";window.E0DD32CBDCB63F=function(){var o={version:"3.5.9"},h=[].slice,w=function(t){return h.call(t)},v=this.document;function z(t){return t&&(t.ownerDocument||t.document||t).documentElement}function B(t){return t&&(t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView)}if(v)try{w(v.documentElement.childNodes)[0].nodeType}catch{w=function(e){for(var n=e.length,r=new Array(n);n--;)r[n]=e[n];return r}}if(Date.now||(Date.now=function(){return+new Date}),v)try{v.createElement("DIV").style.setProperty("opacity",0,"")}catch{var T=this.Element.prototype,D=T.setAttribute,R=T.setAttributeNS,M=this.CSSStyleDeclaration.prototype,I=M.setProperty;T.setAttribute=function(e,n){D.call(this,e,n+"")},T.setAttributeNS=function(e,n,r){R.call(this,e,n,r+"")},M.setProperty=function(e,n,r){I.call(this,e,n+"",r)}}o.ascending=k;function k(t,e){return te?1:t>=e?0:NaN}o.descending=function(t,e){return et?1:e>=t?0:NaN},o.min=function(t,e){var n=-1,r=t.length,i,a;if(arguments.length===1){for(;++n=a){i=a;break}for(;++na&&(i=a)}else{for(;++n=a){i=a;break}for(;++na&&(i=a)}return i},o.max=function(t,e){var n=-1,r=t.length,i,a;if(arguments.length===1){for(;++n=a){i=a;break}for(;++ni&&(i=a)}else{for(;++n=a){i=a;break}for(;++ni&&(i=a)}return i},o.extent=function(t,e){var n=-1,r=t.length,i,a,l;if(arguments.length===1){for(;++n=a){i=l=a;break}for(;++na&&(i=a),l=a){i=l=a;break}for(;++na&&(i=a),l1)return l/(u-1)},o.deviation=function(){var t=o.variance.apply(this,arguments);return t&&Math.sqrt(t)};function q(t){return{left:function(e,n,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=e.length);r>>1;t(e[a],n)<0?r=a+1:i=a}return r},right:function(e,n,r,i){for(arguments.length<3&&(r=0),arguments.length<4&&(i=e.length);r>>1;t(e[a],n)>0?i=a:r=a+1}return r}}}var G=q(k);o.bisectLeft=G.left,o.bisect=o.bisectRight=G.right,o.bisector=function(t){return q(t.length===1?function(e,n){return k(t(e),n)}:t)},o.shuffle=function(t,e,n){(r=arguments.length)<3&&(n=t.length,r<2&&(e=0));for(var r=n-e,i,a;r;)a=Math.random()*r--|0,i=t[r+e],t[r+e]=t[a+e],t[a+e]=i;return t},o.permute=function(t,e){for(var n=e.length,r=new Array(n);n--;)r[n]=t[e[n]];return r},o.pairs=function(t){for(var e=0,n=t.length-1,r=t[0],i=new Array(n<0?0:n);e=0;)for(l=t[e],n=l.length;--n>=0;)a[--i]=l[n];return a};var rt=Math.abs;o.range=function(t,e,n){if(arguments.length<3&&(n=1,arguments.length<2&&(e=t,t=0)),(e-t)/n===1/0)throw new Error("infinite range");var r=[],i=vt(rt(n)),a=-1,l;if(t*=i,e*=i,n*=i,n<0)for(;(l=t+n*++a)>e;)r.push(l/i);else for(;(l=t+n*++a)=e.length)return i?i.call(t,u):r?u.sort(r):u;for(var f=-1,g=u.length,d=e[c++],x,A,m,_=new dt,y;++f=e.length)return s;var c=[],f=n[u++];return s.forEach(function(g,d){c.push({key:g,values:l(d,u)})}),f?c.sort(function(g,d){return f(g.key,d.key)}):c}return t.map=function(s,u){return a(u,s,0)},t.entries=function(s){return l(a(o.map,s,0),0)},t.key=function(s){return e.push(s),t},t.sortKeys=function(s){return n[e.length-1]=s,t},t.sortValues=function(s){return r=s,t},t.rollup=function(s){return i=s,t},t},o.set=function(t){var e=new le;if(t)for(var n=0,r=t.length;n=0&&(r=t.slice(n+1),t=t.slice(0,n)),t)return arguments.length<2?this[t].on(r):this[t].on(r,e);if(arguments.length===2){if(e==null)for(t in this)this.hasOwnProperty(t)&&this[t].on(r,null);return this}};function ae(t){var e=[],n=new dt;function r(){for(var i=e,a=-1,l=i.length,s;++a=0&&(n=t.slice(0,e))!=="xmlns"&&(t=t.slice(e+1)),Pe.hasOwnProperty(n)?{space:Pe[n],local:t}:t}},Ot.attr=function(t,e){if(arguments.length<2){if(typeof t=="string"){var n=this.node();return t=o.ns.qualify(t),t.local?n.getAttributeNS(t.space,t.local):n.getAttribute(t)}for(e in t)this.each(mn(e,t[e]));return this}return this.each(mn(t,e))};function mn(t,e){t=o.ns.qualify(t);function n(){this.removeAttribute(t)}function r(){this.removeAttributeNS(t.space,t.local)}function i(){this.setAttribute(t,e)}function a(){this.setAttributeNS(t.space,t.local,e)}function l(){var u=e.apply(this,arguments);u==null?this.removeAttribute(t):this.setAttribute(t,u)}function s(){var u=e.apply(this,arguments);u==null?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,u)}return e==null?t.local?r:n:typeof e=="function"?t.local?s:l:t.local?a:i}function un(t){return t.trim().replace(/\s+/g," ")}Ot.classed=function(t,e){if(arguments.length<2){if(typeof t=="string"){var n=this.node(),r=(t=Se(t)).length,i=-1;if(e=n.classList){for(;++i=0;)(a=n[r])&&(i&&i!==a.nextSibling&&i.parentNode.insertBefore(a,i),i=a);return this},Ot.sort=function(t){t=di.apply(this,arguments);for(var e=-1,n=this.length;++e=e&&(e=i+1);!(u=l[e])&&++e0&&(t=t.slice(0,i));var l=E.get(t);l&&(t=l,a=U);function s(){var f=this[r];f&&(this.removeEventListener(t,f,f.$),delete this[r])}function u(){var f=a(e,w(arguments));s.call(this),this.addEventListener(t,this[r]=f,f.$=n),f._=e}function c(){var f=new RegExp("^__on([^.]+)"+o.requote(t)+"$"),g;for(var d in this)if(g=d.match(f)){var x=this[d];this.removeEventListener(g[1],x,x.$),delete this[d]}}return i?e?u:s:e?ue:c}var E=o.map({mouseenter:"mouseover",mouseleave:"mouseout"});v&&E.forEach(function(t){"on"+t in v&&E.remove(t)});function j(t,e){return function(n){var r=o.event;o.event=n,e[0]=this.__data__;try{t.apply(this,e)}finally{o.event=r}}}function U(t,e){var n=j(t,e);return function(r){var i=this,a=r.relatedTarget;(!a||a!==i&&!(a.compareDocumentPosition(i)&8))&&n.call(i,r)}}var J,at=0;function lt(t){var e=".dragsuppress-"+ ++at,n="click"+e,r=o.select(B(t)).on("touchmove"+e,Qt).on("dragstart"+e,Qt).on("selectstart"+e,Qt);if(J==null&&(J="onselectstart"in t?!1:ge(t.style,"userSelect")),J){var i=z(t).style,a=i[J];i[J]="none"}return function(l){if(r.on(e,null),J&&(i[J]=a),l){var s=function(){r.on(n,null)};r.on(n,function(){Qt(),s()},!0),setTimeout(s,0)}}}o.mouse=function(t){return ct(t,me())};var ot=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;function ct(t,e){e.changedTouches&&(e=e.changedTouches[0]);var n=t.ownerSVGElement||t;if(n.createSVGPoint){var r=n.createSVGPoint();if(ot<0){var i=B(t);if(i.scrollX||i.scrollY){n=o.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var a=n[0][0].getScreenCTM();ot=!(a.f||a.e),n.remove()}}return ot?(r.x=e.pageX,r.y=e.pageY):(r.x=e.clientX,r.y=e.clientY),r=r.matrixTransform(t.getScreenCTM().inverse()),[r.x,r.y]}var l=t.getBoundingClientRect();return[e.clientX-l.left-t.clientLeft,e.clientY-l.top-t.clientTop]}o.touch=function(t,e,n){if(arguments.length<3&&(n=e,e=me().changedTouches),e){for(var r=0,i=e.length,a;r0?1:t<0?-1:0}function X(t,e,n){return(e[0]-t[0])*(n[1]-t[1])-(e[1]-t[1])*(n[0]-t[0])}function ht(t){return t>1?0:t<-1?it:Math.acos(t)}function Yt(t){return t>1?bt:t<-1?-bt:Math.asin(t)}function Wt(t){return((t=Math.exp(t))-1/t)/2}function Xt(t){return((t=Math.exp(t))+1/t)/2}function Jt(t){return((t=Math.exp(2*t))-1)/(t+1)}function te(t){return(t=Math.sin(t/2))*t}var Tt=Math.SQRT2,Rt=2,Bt=4;o.interpolateZoom=function(t,e){var n=t[0],r=t[1],i=t[2],a=e[0],l=e[1],s=e[2],u=a-n,c=l-r,f=u*u+c*c,g,d;if(f0&&(nt=nt.transition().duration(l)),nt.call(b.event)}function st(){_&&_.domain(m.range().map(function(nt){return(nt-t.x)/t.k}).map(m.invert)),F&&F.domain(y.range().map(function(nt){return(nt-t.y)/t.k}).map(y.invert))}function gt(nt){s++||nt({type:"zoomstart"})}function At(nt){st(),nt({type:"zoom",scale:t.k,translate:[t.x,t.y]})}function xt(nt){--s||(nt({type:"zoomend"}),n=null)}function Ct(){var nt=this,mt=A.of(nt,arguments),Dt=0,Ht=o.select(B(nt)).on(c,pe).on(f,Ee),Zt=P(o.mouse(nt)),se=lt(nt);si.call(nt),gt(mt);function pe(){Dt=1,H(o.mouse(nt),Zt),At(mt)}function Ee(){Ht.on(c,null).on(f,null),se(Dt),xt(mt)}}function tt(){var nt=this,mt=A.of(nt,arguments),Dt={},Ht=0,Zt,se=".zoom-"+o.event.changedTouches[0].identifier,pe="touchmove"+se,Ee="touchend"+se,Ie=[],Be=o.select(nt),Re=lt(nt);Oe(),gt(mt),Be.on(u,null).on(d,Oe);function Te(){var tn=o.touches(nt);return Zt=t.k,tn.forEach(function(Fe){Fe.identifier in Dt&&(Dt[Fe.identifier]=P(Fe))}),tn}function Oe(){var tn=o.event.target;o.select(tn).on(pe,In).on(Ee,hc),Ie.push(tn);for(var Fe=o.event.changedTouches,Xe=0,ln=Fe.length;Xe1){var zn=We[0],kn=We[1],fi=zn[0]-kn[0],ws=zn[1]-kn[1];Ht=fi*fi+ws*ws}}function In(){var tn=o.touches(nt),Fe,Xe,ln,We;si.call(nt);for(var Qn=0,zn=tn.length;Qn1?1:e,n=n<0?0:n>1?1:n,i=n<=.5?n*(1+e):n+e-n*e,r=2*n-i;function a(s){return s>360?s-=360:s<0&&(s+=360),s<60?r+(i-r)*s/60:s<180?i:s<240?r+(i-r)*(240-s)/60:r}function l(s){return Math.round(a(s)*255)}return new ze(l(t+120),l(t),l(t-120))}o.hcl=ke;function ke(t,e,n){return this instanceof ke?(this.h=+t,this.c=+e,void(this.l=+n)):arguments.length<2?t instanceof ke?new ke(t.h,t.c,t.l):t instanceof xe?yr(t.l,t.a,t.b):yr((t=va((t=o.rgb(t)).r,t.g,t.b)).l,t.a,t.b):new ke(t,e,n)}var Ne=ke.prototype=new Kt;Ne.brighter=function(t){return new ke(this.h,this.c,Math.min(100,this.l+rn*(arguments.length?t:1)))},Ne.darker=function(t){return new ke(this.h,this.c,Math.max(0,this.l-rn*(arguments.length?t:1)))},Ne.rgb=function(){return Ge(this.h,this.c,this.l).rgb()};function Ge(t,e,n){return isNaN(t)&&(t=0),isNaN(e)&&(e=0),new xe(n,Math.cos(t*=_t)*e,Math.sin(t)*e)}o.lab=xe;function xe(t,e,n){return this instanceof xe?(this.l=+t,this.a=+e,void(this.b=+n)):arguments.length<2?t instanceof xe?new xe(t.l,t.a,t.b):t instanceof ke?Ge(t.h,t.c,t.l):va((t=ze(t)).r,t.g,t.b):new xe(t,e,n)}var rn=18,Ve=.95047,an=1,Ue=1.08883,fn=xe.prototype=new Kt;fn.brighter=function(t){return new xe(Math.min(100,this.l+rn*(arguments.length?t:1)),this.a,this.b)},fn.darker=function(t){return new xe(Math.max(0,this.l-rn*(arguments.length?t:1)),this.a,this.b)},fn.rgb=function(){return jn(this.l,this.a,this.b)};function jn(t,e,n){var r=(t+16)/116,i=r+e/500,a=r-n/200;return i=tr(i)*Ve,r=tr(r)*an,a=tr(a)*Ue,new ze(mi(3.2404542*i-1.5371385*r-.4985314*a),mi(-.969266*i+1.8760108*r+.041556*a),mi(.0556434*i-.2040259*r+1.0572252*a))}function yr(t,e,n){return t>0?new ke(Math.atan2(n,e)*zt,Math.sqrt(e*e+n*n),t):new ke(NaN,NaN,t)}function tr(t){return t>.206893034?t*t*t:(t-4/29)/7.787037}function pi(t){return t>.008856?Math.pow(t,1/3):7.787037*t+4/29}function mi(t){return Math.round(255*(t<=.00304?12.92*t:1.055*Math.pow(t,1/2.4)-.055))}o.rgb=ze;function ze(t,e,n){return this instanceof ze?(this.r=~~t,this.g=~~e,void(this.b=~~n)):arguments.length<2?t instanceof ze?new ze(t.r,t.g,t.b):_a(""+t,ze,Mn):new ze(t,e,n)}function ma(t){return new ze(t>>16,t>>8&255,t&255)}function vr(t){return ma(t)+""}var xr=ze.prototype=new Kt;xr.brighter=function(t){t=Math.pow(.7,arguments.length?t:1);var e=this.r,n=this.g,r=this.b,i=30;return!e&&!n&&!r?new ze(i,i,i):(e&&e>4,r=r>>4|r,i=u&240,i=i>>4|i,a=u&15,a=a<<4|a):t.length===7&&(r=(u&16711680)>>16,i=(u&65280)>>8,a=u&255)),e(r,i,a))}function ya(t,e,n){var r=Math.min(t/=255,e/=255,n/=255),i=Math.max(t,e,n),a=i-r,l,s,u=(i+r)/2;return a?(s=u<.5?a/(i+r):a/(2-i-r),t==i?l=(e-n)/a+(e0&&u<1?0:l),new he(l,s,u)}function va(t,e,n){t=_i(t),e=_i(e),n=_i(n);var r=pi((.4124564*t+.3575761*e+.1804375*n)/Ve),i=pi((.2126729*t+.7151522*e+.072175*n)/an),a=pi((.0193339*t+.119192*e+.9503041*n)/Ue);return xe(116*i-16,500*(r-i),200*(i-a))}function _i(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function yi(t){var e=parseFloat(t);return t.charAt(t.length-1)==="%"?Math.round(e*2.55):e}var br=o.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});br.forEach(function(t,e){br.set(t,ma(e))});function de(t){return typeof t=="function"?t:function(){return t}}o.functor=de,o.xhr=vi(ie);function vi(t){return function(e,n,r){return arguments.length===2&&typeof n=="function"&&(r=n,n=null),wr(e,n,t,r)}}function wr(t,e,n,r){var i={},a=o.dispatch("beforesend","progress","load","error"),l={},s=new XMLHttpRequest,u=null;this.XDomainRequest&&!("withCredentials"in s)&&/^(http(s)?:)?\/\//.test(t)&&(s=new XDomainRequest),"onload"in s?s.onload=s.onerror=c:s.onreadystatechange=function(){s.readyState>3&&c()};function c(){var f=s.status,g;if(!f&&Ms(s)||f>=200&&f<300||f===304){try{g=n.call(i,s)}catch(d){a.error.call(i,d);return}a.load.call(i,g)}else a.error.call(i,s)}return s.onprogress=function(f){var g=o.event;o.event=f;try{a.progress.call(i,s)}finally{o.event=g}},i.header=function(f,g){return f=(f+"").toLowerCase(),arguments.length<2?l[f]:(g==null?delete l[f]:l[f]=g+"",i)},i.mimeType=function(f){return arguments.length?(e=f==null?null:f+"",i):e},i.responseType=function(f){return arguments.length?(u=f,i):u},i.response=function(f){return n=f,i},["get","post"].forEach(function(f){i[f]=function(){return i.send.apply(i,[f].concat(w(arguments)))}}),i.send=function(f,g,d){if(arguments.length===2&&typeof g=="function"&&(d=g,g=null),s.open(f,t,!0),e!=null&&!("accept"in l)&&(l.accept=e+",*/*"),s.setRequestHeader)for(var x in l)s.setRequestHeader(x,l[x]);return e!=null&&s.overrideMimeType&&s.overrideMimeType(e),u!=null&&(s.responseType=u),d!=null&&i.on("error",d).on("load",function(A){d(null,A)}),a.beforesend.call(i,s),s.send(g??null),i},i.abort=function(){return s.abort(),i},o.rebind(i,a,"on"),r==null?i:i.get(Cs(r))}function Cs(t){return t.length===1?function(e,n){t(e==null?n:null)}:t}function Ms(t){var e=t.responseType;return e&&e!=="text"?t.response:t.responseText}o.dsv=function(t,e){var n=new RegExp('["'+t+` +]`),r=t.charCodeAt(0);function i(c,f,g){arguments.length<3&&(g=f,f=null);var d=wr(c,e,f==null?a:l(f),g);return d.row=function(x){return arguments.length?d.response((f=x)==null?a:l(x)):f},d}function a(c){return i.parse(c.responseText)}function l(c){return function(f){return i.parse(f.responseText,c)}}i.parse=function(c,f){var g;return i.parseRows(c,function(d,x){if(g)return g(d,x-1);var A=new Function("d","return {"+d.map(function(m,_){return JSON.stringify(m)+": d["+_+"]"}).join(",")+"}");g=f?function(m,_){return f(A(m),_)}:A})},i.parseRows=function(c,f){var g={},d={},x=[],A=c.length,m=0,_=0,y,F;function b(){if(m>=A)return d;if(F)return F=!1,g;var W=m;if(c.charCodeAt(W)===34){for(var Y=W;Y++24?(isFinite(e)&&(clearTimeout(Sr),Sr=setTimeout(xi,e)),Mr=0):(Mr=1,xa(xi))}o.timer.flush=function(){ba(),wa()};function ba(){for(var t=Date.now(),e=kr;e;)t>=e.t&&e.c(t-e.t)&&(e.c=null),e=e.n;return t}function wa(){for(var t,e=kr,n=1/0;e;)e.c?(e.t8?function(r){return r/n}:function(r){return r*n},symbol:t}}function As(t){var e=t.decimal,n=t.thousands,r=t.grouping,i=t.currency,a=r&&n?function(l,s){for(var u=l.length,c=[],f=0,g=r[0],d=0;u>0&&g>0&&(d+g+1>s&&(g=Math.max(1,s-d)),c.push(l.substring(u-=g,u+g)),!((d+=g+1)>s));)g=r[f=(f+1)%r.length];return c.reverse().join(n)}:ie;return function(l){var s=ka.exec(l),u=s[1]||" ",c=s[2]||">",f=s[3]||"-",g=s[4]||"",d=s[5],x=+s[6],A=s[7],m=s[8],_=s[9],y=1,F="",b="",P=!1,W=!0;switch(m&&(m=+m.substring(1)),(d||u==="0"&&c==="=")&&(d=u="0",c="="),_){case"n":A=!0,_="g";break;case"%":y=100,b="%",_="f";break;case"p":y=100,b="%",_="r";break;case"b":case"o":case"x":case"X":g==="#"&&(F="0"+_.toLowerCase());case"c":W=!1;case"d":P=!0,m=0;break;case"s":y=-1,_="r";break}g==="$"&&(F=i[0],b=i[1]),_=="r"&&!m&&(_="g"),m!=null&&(_=="g"?m=Math.max(1,Math.min(21,m)):(_=="e"||_=="f")&&(m=Math.max(0,Math.min(20,m)))),_=Fs.get(_)||Ls;var Y=d&&A;return function(H){var V=b;if(P&&H%1)return"";var st=H<0||H===0&&1/H<0?(H=-H,"-"):f==="-"?"":f;if(y<0){var gt=o.formatPrefix(H,m);H=gt.scale(H),V=gt.symbol+b}else H*=y;H=_(H,m);var At=H.lastIndexOf("."),xt,Ct;if(At<0){var tt=W?H.lastIndexOf("e"):-1;tt<0?(xt=H,Ct=""):(xt=H.substring(0,tt),Ct=H.substring(tt))}else xt=H.substring(0,At),Ct=e+H.substring(At+1);!d&&A&&(xt=a(xt,1/0));var ft=F.length+xt.length+Ct.length+(Y?0:st.length),yt=ft"?yt+st+H:c==="^"?yt.substring(0,ft>>=1)+st+H+yt.substring(ft):st+(Y?H:yt+H))+V}}}var ka=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,Fs=o.map({b:function(t){return t.toString(2)},c:function(t){return String.fromCharCode(t)},o:function(t){return t.toString(8)},x:function(t){return t.toString(16)},X:function(t){return t.toString(16).toUpperCase()},g:function(t,e){return t.toPrecision(e)},e:function(t,e){return t.toExponential(e)},f:function(t,e){return t.toFixed(e)},r:function(t,e){return(t=o.round(t,bi(t,e))).toFixed(Math.max(0,Math.min(20,bi(t*(1+1e-15),e))))}});function Ls(t){return t+""}var It=o.time={},Le=Date;function hn(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}hn.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){gn.setUTCDate.apply(this._,arguments)},setDay:function(){gn.setUTCDay.apply(this._,arguments)},setFullYear:function(){gn.setUTCFullYear.apply(this._,arguments)},setHours:function(){gn.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){gn.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){gn.setUTCMinutes.apply(this._,arguments)},setMonth:function(){gn.setUTCMonth.apply(this._,arguments)},setSeconds:function(){gn.setUTCSeconds.apply(this._,arguments)},setTime:function(){gn.setTime.apply(this._,arguments)}};var gn=Date.prototype;function Sn(t,e,n){function r(c){var f=t(c),g=a(f,1);return c-f1)for(;d=pe)return-1;if(mt=ft.charCodeAt(Zt++),mt===37){if(Ht=ft.charAt(Zt++),Dt=W[Ht in Ca?ft.charAt(Zt++):Ht],!Dt||(nt=Dt(tt,yt,nt))<0)return-1}else if(mt!=yt.charCodeAt(nt++))return-1}return nt}c.utc=function(tt){var ft=c(tt);function yt(nt){try{Le=hn;var mt=new Le;return mt._=nt,ft(mt)}finally{Le=Date}}return yt.parse=function(nt){try{Le=hn;var mt=ft.parse(nt);return mt&&mt._}finally{Le=Date}},yt.toString=ft.toString,yt},c.multi=c.utc.multi=Ys;var g=o.map(),d=Fr(a),x=Lr(a),A=Fr(l),m=Lr(l),_=Fr(s),y=Lr(s),F=Fr(u),b=Lr(u);i.forEach(function(tt,ft){g.set(tt.toLowerCase(),ft)});var P={a:function(tt){return l[tt.getDay()]},A:function(tt){return a[tt.getDay()]},b:function(tt){return u[tt.getMonth()]},B:function(tt){return s[tt.getMonth()]},c:c(e),d:function(tt,ft){return De(tt.getDate(),ft,2)},e:function(tt,ft){return De(tt.getDate(),ft,2)},H:function(tt,ft){return De(tt.getHours(),ft,2)},I:function(tt,ft){return De(tt.getHours()%12||12,ft,2)},j:function(tt,ft){return De(1+It.dayOfYear(tt),ft,3)},L:function(tt,ft){return De(tt.getMilliseconds(),ft,3)},m:function(tt,ft){return De(tt.getMonth()+1,ft,2)},M:function(tt,ft){return De(tt.getMinutes(),ft,2)},p:function(tt){return i[+(tt.getHours()>=12)]},S:function(tt,ft){return De(tt.getSeconds(),ft,2)},U:function(tt,ft){return De(It.sundayOfYear(tt),ft,2)},w:function(tt){return tt.getDay()},W:function(tt,ft){return De(It.mondayOfYear(tt),ft,2)},x:c(n),X:c(r),y:function(tt,ft){return De(tt.getFullYear()%100,ft,2)},Y:function(tt,ft){return De(tt.getFullYear()%1e4,ft,4)},Z:Hs,"%":function(){return"%"}},W={a:Y,A:H,b:V,B:st,c:gt,d:Sa,e:Sa,H:Pa,I:Pa,j:js,L:qs,m:Os,M:Gs,p:Ct,S:Vs,U:Es,w:Ns,W:Bs,x:At,X:xt,y:Is,Y:Ds,Z:zs,"%":Us};function Y(tt,ft,yt){A.lastIndex=0;var nt=A.exec(ft.slice(yt));return nt?(tt.w=m.get(nt[0].toLowerCase()),yt+nt[0].length):-1}function H(tt,ft,yt){d.lastIndex=0;var nt=d.exec(ft.slice(yt));return nt?(tt.w=x.get(nt[0].toLowerCase()),yt+nt[0].length):-1}function V(tt,ft,yt){F.lastIndex=0;var nt=F.exec(ft.slice(yt));return nt?(tt.m=b.get(nt[0].toLowerCase()),yt+nt[0].length):-1}function st(tt,ft,yt){_.lastIndex=0;var nt=_.exec(ft.slice(yt));return nt?(tt.m=y.get(nt[0].toLowerCase()),yt+nt[0].length):-1}function gt(tt,ft,yt){return f(tt,P.c.toString(),ft,yt)}function At(tt,ft,yt){return f(tt,P.x.toString(),ft,yt)}function xt(tt,ft,yt){return f(tt,P.X.toString(),ft,yt)}function Ct(tt,ft,yt){var nt=g.get(ft.slice(yt,yt+=2).toLowerCase());return nt==null?-1:(tt.p=nt,yt)}return c}var Ca={"-":"",_:" ",0:"0"},we=/^\s*\d+/,Ma=/^%/;function De(t,e,n){var r=t<0?"-":"",i=(r?-t:t)+"",a=i.length;return r+(a68?1900:2e3)}function Os(t,e,n){we.lastIndex=0;var r=we.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function Sa(t,e,n){we.lastIndex=0;var r=we.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function js(t,e,n){we.lastIndex=0;var r=we.exec(e.slice(n,n+3));return r?(t.j=+r[0],n+r[0].length):-1}function Pa(t,e,n){we.lastIndex=0;var r=we.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function Gs(t,e,n){we.lastIndex=0;var r=we.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function Vs(t,e,n){we.lastIndex=0;var r=we.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function qs(t,e,n){we.lastIndex=0;var r=we.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function Hs(t){var e=t.getTimezoneOffset(),n=e>0?"-":"+",r=rt(e)/60|0,i=rt(e)%60;return n+De(r,"0",2)+De(i,"0",2)}function Us(t,e,n){Ma.lastIndex=0;var r=Ma.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function Ys(t){for(var e=t.length,n=-1;++n=0?1:-1,f=c*u,g=Math.cos(s),d=Math.sin(s),x=i*d,A=r*g+x*Math.cos(f),m=x*c*Math.sin(f);Pn.add(Math.atan2(m,A)),n=l,r=g,i=d}qe.lineEnd=function(){a(t,e)}}function An(t){var e=t[0],n=t[1],r=Math.cos(n);return[r*Math.cos(e),r*Math.sin(e),Math.sin(n)]}function Br(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function Vn(t,e){return[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]]}function Ci(t,e){t[0]+=e[0],t[1]+=e[1],t[2]+=e[2]}function Dr(t,e){return[t[0]*e,t[1]*e,t[2]*e]}function Ir(t){var e=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=e,t[1]/=e,t[2]/=e}function zr(t){return[Math.atan2(t[1],t[0]),Yt(t[2])]}function Rr(t,e){return rt(t[0]-e[0])Q?r=90:u<-Q&&(e=-90),f[0]=t,f[1]=n}};function d(Y,H){c.push(f=[t=Y,n=Y]),Hr&&(r=H)}function x(Y,H){var V=An([Y*_t,H*_t]);if(s){var st=Vn(s,V),gt=[st[1],-st[0],0],At=Vn(gt,st);Ir(At),At=zr(At);var xt=Y-i,Ct=xt>0?1:-1,tt=At[0]*zt*Ct,ft=rt(xt)>180;if(ft^(Ct*ir&&(r=yt)}else if(tt=(tt+360)%360-180,ft^(Ct*ir&&(r=H);ft?Yb(t,n)&&(n=Y):b(Y,n)>b(t,n)&&(t=Y):n>=t?(Yn&&(n=Y)):Y>i?b(t,Y)>b(t,n)&&(n=Y):b(Y,n)>b(t,n)&&(t=Y)}else d(Y,H);s=V,i=Y}function A(){g.point=x}function m(){f[0]=t,f[1]=n,g.point=d,s=null}function _(Y,H){if(s){var V=Y-i;u+=rt(V)>180?V+(V>0?360:-360):V}else a=Y,l=H;qe.point(Y,H),x(Y,H)}function y(){qe.lineStart()}function F(){_(a,l),qe.lineEnd(),rt(u)>Q&&(t=-(n=180)),f[0]=t,f[1]=n,s=null}function b(Y,H){return(H-=Y)<0?H+360:H}function P(Y,H){return Y[0]-H[0]}function W(Y,H){return H[0]<=H[1]?H[0]<=Y&&Y<=H[1]:Yb(st[0],st[1])&&(st[1]=gt[1]),b(gt[0],st[1])>b(st[0],st[1])&&(st[0]=gt[0])):At.push(st=gt);for(var xt=-1/0,Ct,H=At.length-1,V=0,st=At[H],gt;V<=H;st=gt,++V)gt=At[V],(Ct=b(st[1],gt[0]))>xt&&(xt=Ct,t=gt[0],n=st[1])}return c=f=null,t===1/0||e===1/0?[[NaN,NaN],[NaN,NaN]]:[[t,e],[n,r]]}}(),o.geo.centroid=function(t){er=Or=Fn=Ln=dn=_n=yn=on=qn=Hn=vn=0,o.geo.stream(t,Ke);var e=qn,n=Hn,r=vn,i=e*e+n*n+r*r;return i=0;--s)i.point((d=g[s])[0],d[1])}else r(x.x,x.p.x,-1,i);x=x.p}x=x.o,g=x.z,A=!A}while(!x.v);i.lineEnd()}}}function za(t){if(e=t.length){for(var e,n=0,r=t[0],i;++n0){for(_||(a.polygonStart(),_=!0),a.lineStart();++gt1&&Y&2&&H.push(H.pop().concat(H.shift())),x.push(H.filter(Zs))}}return u}}function Zs(t){return t.length>1}function Oa(){var t=[],e;return{lineStart:function(){t.push(e=[])},point:function(n,r){e.push([n,r])},lineEnd:ue,buffer:function(){var n=t;return t=[],e=null,n},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function $s(t,e){return((t=t.x)[0]<0?t[1]-bt-Q:bt-t[1])-((e=e.x)[0]<0?e[1]-bt-Q:bt-e[1])}var ja=Ra(rr,Ks,Qs,[-it,-it/2]);function Ks(t){var e=NaN,n=NaN,r=NaN,i;return{lineStart:function(){t.lineStart(),i=1},point:function(a,l){var s=a>0?it:-it,u=rt(a-e);rt(u-it)0?bt:-bt),t.point(r,n),t.lineEnd(),t.lineStart(),t.point(s,n),t.point(a,n),i=0):r!==s&&u>=it&&(rt(e-r)Q?Math.atan((Math.sin(e)*(a=Math.cos(r))*Math.sin(n)-Math.sin(r)*(i=Math.cos(e))*Math.sin(t))/(i*a*l)):(e+r)/2}function Qs(t,e,n,r){var i;if(t==null)i=n*bt,r.point(-it,i),r.point(0,i),r.point(it,i),r.point(it,0),r.point(it,-i),r.point(0,-i),r.point(-it,-i),r.point(-it,0),r.point(-it,i);else if(rt(t[0]-e[0])>Q){var a=t[0]=0?1:-1,H=Y*W,V=H>it,st=A*b;if(Pn.add(Math.atan2(st*Y*Math.sin(H),m*P+st*Math.cos(H))),a+=V?W+Y*K:W,V^d>=n^y>=n){var gt=Vn(An(g),An(t));Ir(gt);var At=Vn(i,gt);Ir(At);var xt=(V^W>=0?-1:1)*Yt(At[2]);(r>xt||r===xt&&(gt[0]||gt[1]))&&(l+=V^W>=0?1:-1)}if(!_++)break;d=y,A=b,m=P,g=t}}return(a<-Q||a0,r=rt(e)>Q,i=Ti(t,6*_t);return Ra(a,l,i,n?[0,-t]:[-it,t-it]);function a(c,f){return Math.cos(c)*Math.cos(f)>e}function l(c){var f,g,d,x,A;return{lineStart:function(){x=d=!1,A=1},point:function(m,_){var y=[m,_],F,b=a(m,_),P=n?b?0:u(m,_):b?u(m+(m<0?it:-it),_):0;if(!f&&(x=d=b)&&c.lineStart(),b!==d&&(F=s(f,y),(Rr(f,F)||Rr(y,F))&&(y[0]+=Q,y[1]+=Q,b=a(y[0],y[1]))),b!==d)A=0,b?(c.lineStart(),F=s(y,f),c.point(F[0],F[1])):(F=s(f,y),c.point(F[0],F[1]),c.lineEnd()),f=F;else if(r&&f&&n^b){var W;!(P&g)&&(W=s(y,f,!0))&&(A=0,n?(c.lineStart(),c.point(W[0][0],W[0][1]),c.point(W[1][0],W[1][1]),c.lineEnd()):(c.point(W[1][0],W[1][1]),c.lineEnd(),c.lineStart(),c.point(W[0][0],W[0][1])))}b&&(!f||!Rr(f,y))&&c.point(y[0],y[1]),f=y,d=b,g=P},lineEnd:function(){d&&c.lineEnd(),f=null},clean:function(){return A|(x&&d)<<1}}}function s(c,f,g){var d=An(c),x=An(f),A=[1,0,0],m=Vn(d,x),_=Br(m,m),y=m[0],F=_-y*y;if(!F)return!g&&c;var b=e*_/F,P=-e*y/F,W=Vn(A,m),Y=Dr(A,b),H=Dr(m,P);Ci(Y,H);var V=W,st=Br(Y,V),gt=Br(V,V),At=st*st-gt*(Br(Y,Y)-1);if(!(At<0)){var xt=Math.sqrt(At),Ct=Dr(V,(-st-xt)/gt);if(Ci(Ct,Y),Ct=zr(Ct),!g)return Ct;var tt=c[0],ft=f[0],yt=c[1],nt=f[1],mt;ft0^Ct[1]<(rt(Ct[0]-tt)it^(tt<=Ct[0]&&Ct[0]<=ft)){var se=Dr(V,(-st+xt)/gt);return Ci(se,Y),[Ct,zr(se)]}}}function u(c,f){var g=n?t:it-t,d=0;return c<-g?d|=1:c>g&&(d|=2),f<-g?d|=4:f>g&&(d|=8),d}}function Ga(t,e,n,r){return function(i){var a=i.a,l=i.b,s=a.x,u=a.y,c=l.x,f=l.y,g=0,d=1,x=c-s,A=f-u,m;if(m=t-s,!(!x&&m>0)){if(m/=x,x<0){if(m0){if(m>d)return;m>g&&(g=m)}if(m=n-s,!(!x&&m<0)){if(m/=x,x<0){if(m>d)return;m>g&&(g=m)}else if(x>0){if(m0)){if(m/=A,A<0){if(m0){if(m>d)return;m>g&&(g=m)}if(m=r-u,!(!A&&m<0)){if(m/=A,A<0){if(m>d)return;m>g&&(g=m)}else if(A>0){if(m0&&(i.a={x:s+g*x,y:u+g*A}),d<1&&(i.b={x:s+d*x,y:u+d*A}),i}}}}}}var Gr=1e9;o.geo.clipExtent=function(){var t,e,n,r,i,a,l={stream:function(s){return i&&(i.valid=!1),i=a(s),i.valid=!0,i},extent:function(s){return arguments.length?(a=Va(t=+s[0][0],e=+s[0][1],n=+s[1][0],r=+s[1][1]),i&&(i.valid=!1,i=null),l):[[t,e],[n,r]]}};return l.extent([[0,0],[960,500]])};function Va(t,e,n,r){return function(s){var u=s,c=Oa(),f=Ga(t,e,n,r),g,d,x,A={point:F,lineStart:At,lineEnd:xt,polygonStart:function(){s=c,g=[],d=[],gt=!0},polygonEnd:function(){s=u,g=o.merge(g);var tt=m([t,r]),ft=gt&&tt,yt=g.length;(ft||yt)&&(s.polygonStart(),ft&&(s.lineStart(),_(null,null,1,s),s.lineEnd()),yt&&Ia(g,a,tt,_,s),s.polygonEnd()),g=d=x=null}};function m(tt){for(var ft=0,yt=d.length,nt=tt[1],mt=0;mtnt&&X(se,pe,tt)>0&&++ft:pe[1]<=nt&&X(se,pe,tt)<0&&--ft,se=pe;return ft!==0}function _(tt,ft,yt,nt){var mt=0,Dt=0;if(tt==null||(mt=i(tt,yt))!==(Dt=i(ft,yt))||l(tt,ft)<0^yt>0)do nt.point(mt===0||mt===3?t:n,mt>1?r:e);while((mt=(mt+yt+4)%4)!==Dt);else nt.point(ft[0],ft[1])}function y(tt,ft){return t<=tt&&tt<=n&&e<=ft&&ft<=r}function F(tt,ft){y(tt,ft)&&s.point(tt,ft)}var b,P,W,Y,H,V,st,gt;function At(){A.point=Ct,d&&d.push(x=[]),st=!0,V=!1,Y=H=NaN}function xt(){g&&(Ct(b,P),W&&V&&c.rejoin(),g.push(c.buffer())),A.point=F,V&&s.lineEnd()}function Ct(tt,ft){tt=Math.max(-Gr,Math.min(Gr,tt)),ft=Math.max(-Gr,Math.min(Gr,ft));var yt=y(tt,ft);if(d&&x.push([tt,ft]),st)b=tt,P=ft,W=yt,st=!1,yt&&(s.lineStart(),s.point(tt,ft));else if(yt&&V)s.point(tt,ft);else{var nt={a:{x:Y,y:H},b:{x:tt,y:ft}};f(nt)?(V||(s.lineStart(),s.point(nt.a.x,nt.a.y)),s.point(nt.b.x,nt.b.y),yt||s.lineEnd(),gt=!1):yt&&(s.lineStart(),s.point(tt,ft),gt=!1)}Y=tt,H=ft,V=yt}return A};function i(s,u){return rt(s[0]-t)0?0:3:rt(s[0]-n)0?2:1:rt(s[1]-e)0?1:0:u>0?3:2}function a(s,u){return l(s.x,u.x)}function l(s,u){var c=i(s,1),f=i(u,1);return c!==f?c-f:c===0?u[1]-s[1]:c===1?s[0]-u[0]:c===2?s[1]-u[1]:u[0]-s[0]}}function Si(t){var e=0,n=it/3,r=Fi(t),i=r(e,n);return i.parallels=function(a){return arguments.length?r(e=a[0]*it/180,n=a[1]*it/180):[e/it*180,n/it*180]},i}function qa(t,e){var n=Math.sin(t),r=(n+Math.sin(e))/2,i=1+n*(2*r-n),a=Math.sqrt(i)/r;function l(s,u){var c=Math.sqrt(i-2*r*Math.sin(u))/r;return[c*Math.sin(s*=r),a-c*Math.cos(s)]}return l.invert=function(s,u){var c=a-u;return[Math.atan2(s,c)/r,Yt((i-(s*s+c*c)*r*r)/(2*r))]},l}(o.geo.conicEqualArea=function(){return Si(qa)}).raw=qa,o.geo.albers=function(){return o.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},o.geo.albersUsa=function(){var t=o.geo.albers(),e=o.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),n=o.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),r,i={point:function(c,f){r=[c,f]}},a,l,s;function u(c){var f=c[0],g=c[1];return r=null,a(f,g),r||(l(f,g),r)||s(f,g),r}return u.invert=function(c){var f=t.scale(),g=t.translate(),d=(c[0]-g[0])/f,x=(c[1]-g[1])/f;return(x>=.12&&x<.234&&d>=-.425&&d<-.214?e:x>=.166&&x<.234&&d>=-.214&&d<-.115?n:t).invert(c)},u.stream=function(c){var f=t.stream(c),g=e.stream(c),d=n.stream(c);return{point:function(x,A){f.point(x,A),g.point(x,A),d.point(x,A)},sphere:function(){f.sphere(),g.sphere(),d.sphere()},lineStart:function(){f.lineStart(),g.lineStart(),d.lineStart()},lineEnd:function(){f.lineEnd(),g.lineEnd(),d.lineEnd()},polygonStart:function(){f.polygonStart(),g.polygonStart(),d.polygonStart()},polygonEnd:function(){f.polygonEnd(),g.polygonEnd(),d.polygonEnd()}}},u.precision=function(c){return arguments.length?(t.precision(c),e.precision(c),n.precision(c),u):t.precision()},u.scale=function(c){return arguments.length?(t.scale(c),e.scale(c*.35),n.scale(c),u.translate(t.translate())):t.scale()},u.translate=function(c){if(!arguments.length)return t.translate();var f=t.scale(),g=+c[0],d=+c[1];return a=t.translate(c).clipExtent([[g-.455*f,d-.238*f],[g+.455*f,d+.238*f]]).stream(i).point,l=e.translate([g-.307*f,d+.201*f]).clipExtent([[g-.425*f+Q,d+.12*f+Q],[g-.214*f-Q,d+.234*f-Q]]).stream(i).point,s=n.translate([g-.205*f,d+.212*f]).clipExtent([[g-.214*f+Q,d+.166*f+Q],[g-.115*f-Q,d+.234*f-Q]]).stream(i).point,u},u.scale(1070)};var Pi,Ai,xn={point:ue,lineStart:ue,lineEnd:ue,polygonStart:function(){Ai=0,xn.lineStart=nl},polygonEnd:function(){xn.lineStart=xn.lineEnd=xn.point=ue,Pi+=rt(Ai/2)}};function nl(){var t,e,n,r;xn.point=function(a,l){xn.point=i,t=n=a,e=r=l};function i(a,l){Ai+=r*a-n*l,n=a,r=l}xn.lineEnd=function(){i(t,e)}}var Vr,qr,Hr,Ur,rl={point:il,lineStart:ue,lineEnd:ue,polygonStart:ue,polygonEnd:ue};function il(t,e){tHr&&(Hr=t),eUr&&(Ur=e)}function al(){var t=Ha(4.5),e=[],n={point:r,lineStart:function(){n.point=i},lineEnd:l,polygonStart:function(){n.lineEnd=s},polygonEnd:function(){n.lineEnd=l,n.point=r},pointRadius:function(u){return t=Ha(u),n},result:function(){if(e.length){var u=e.join("");return e=[],u}}};function r(u,c){e.push("M",u,",",c,t)}function i(u,c){e.push("M",u,",",c),n.point=a}function a(u,c){e.push("L",u,",",c)}function l(){n.point=r}function s(){e.push("Z")}return n}function Ha(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}var Je={point:Tn,lineStart:Ua,lineEnd:Ya,polygonStart:function(){Je.lineStart=ol},polygonEnd:function(){Je.point=Tn,Je.lineStart=Ua,Je.lineEnd=Ya}};function Tn(t,e){Fn+=t,Ln+=e,++dn}function Ua(){var t,e;Je.point=function(r,i){Je.point=n,Tn(t=r,e=i)};function n(r,i){var a=r-t,l=i-e,s=Math.sqrt(a*a+l*l);_n+=s*(t+r)/2,yn+=s*(e+i)/2,on+=s,Tn(t=r,e=i)}}function Ya(){Je.point=Tn}function ol(){var t,e,n,r;Je.point=function(a,l){Je.point=i,Tn(t=n=a,e=r=l)};function i(a,l){var s=a-n,u=l-r,c=Math.sqrt(s*s+u*u);_n+=c*(n+a)/2,yn+=c*(r+l)/2,on+=c,c=r*a-n*l,qn+=c*(n+a),Hn+=c*(r+l),vn+=c*3,Tn(n=a,r=l)}Je.lineEnd=function(){i(t,e)}}function sl(t){var e=4.5,n={point:r,lineStart:function(){n.point=i},lineEnd:l,polygonStart:function(){n.lineEnd=s},polygonEnd:function(){n.lineEnd=l,n.point=r},pointRadius:function(u){return e=u,n},result:ue};function r(u,c){t.moveTo(u+e,c),t.arc(u,c,e,0,K)}function i(u,c){t.moveTo(u,c),n.point=a}function a(u,c){t.lineTo(u,c)}function l(){n.point=r}function s(){t.closePath()}return n}function Xa(t){var e=.5,n=Math.cos(30*_t),r=16;function i(u){return(r?l:a)(u)}function a(u){return Za(u,function(c,f){c=t(c,f),u.point(c[0],c[1])})}function l(u){var c,f,g,d,x,A,m,_,y,F,b,P,W={point:Y,lineStart:H,lineEnd:st,polygonStart:function(){u.polygonStart(),W.lineStart=gt},polygonEnd:function(){u.polygonEnd(),W.lineStart=H}};function Y(Ct,tt){Ct=t(Ct,tt),u.point(Ct[0],Ct[1])}function H(){_=NaN,W.point=V,u.lineStart()}function V(Ct,tt){var ft=An([Ct,tt]),yt=t(Ct,tt);s(_,y,m,F,b,P,_=yt[0],y=yt[1],m=Ct,F=ft[0],b=ft[1],P=ft[2],r,u),u.point(_,y)}function st(){W.point=Y,u.lineEnd()}function gt(){H(),W.point=At,W.lineEnd=xt}function At(Ct,tt){V(c=Ct,tt),f=_,g=y,d=F,x=b,A=P,W.point=V}function xt(){s(_,y,m,F,b,P,f,g,c,d,x,A,r,u),W.lineEnd=st,st()}return W}function s(u,c,f,g,d,x,A,m,_,y,F,b,P,W){var Y=A-u,H=m-c,V=Y*Y+H*H;if(V>4*e&&P--){var st=g+y,gt=d+F,At=x+b,xt=Math.sqrt(st*st+gt*gt+At*At),Ct=Math.asin(At/=xt),tt=rt(rt(At)-1)e||rt((Y*mt+H*Dt)/V-.5)>.3||g*y+d*F+x*b0&&16,i):Math.sqrt(e)},i}o.geo.path=function(){var t=4.5,e,n,r,i,a;function l(u){return u&&(typeof t=="function"&&i.pointRadius(+t.apply(this,arguments)),(!a||!a.valid)&&(a=r(i)),o.geo.stream(u,a)),i.result()}l.area=function(u){return Pi=0,o.geo.stream(u,r(xn)),Pi},l.centroid=function(u){return Fn=Ln=dn=_n=yn=on=qn=Hn=vn=0,o.geo.stream(u,r(Je)),vn?[qn/vn,Hn/vn]:on?[_n/on,yn/on]:dn?[Fn/dn,Ln/dn]:[NaN,NaN]},l.bounds=function(u){return Hr=Ur=-(Vr=qr=1/0),o.geo.stream(u,r(rl)),[[Vr,qr],[Hr,Ur]]},l.projection=function(u){return arguments.length?(r=(e=u)?u.stream||ll(u):ie,s()):e},l.context=function(u){return arguments.length?(i=(n=u)==null?new al:new sl(u),typeof t!="function"&&i.pointRadius(t),s()):n},l.pointRadius=function(u){return arguments.length?(t=typeof u=="function"?u:(i.pointRadius(+u),+u),l):t};function s(){return a=null,l}return l.projection(o.geo.albersUsa()).context(null)};function ll(t){var e=Xa(function(n,r){return t([n*zt,r*zt])});return function(n){return $a(e(n))}}o.geo.transform=function(t){return{stream:function(e){var n=new Wa(e);for(var r in t)n[r]=t[r];return n}}};function Wa(t){this.stream=t}Wa.prototype={point:function(t,e){this.stream.point(t,e)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};function Za(t,e){return{point:e,sphere:function(){t.sphere()},lineStart:function(){t.lineStart()},lineEnd:function(){t.lineEnd()},polygonStart:function(){t.polygonStart()},polygonEnd:function(){t.polygonEnd()}}}o.geo.projection=bn,o.geo.projectionMutator=Fi;function bn(t){return Fi(function(){return t})()}function Fi(t){var e,n,r,i=Xa(function(V,st){return V=e(V,st),[V[0]*a+x,A-V[1]*a]}),a=150,l=480,s=250,u=0,c=0,f=0,g=0,d=0,x,A,m=ja,_=ie,y=null,F=null,b;function P(V){return V=r(V[0]*_t,V[1]*_t),[V[0]*a+x,A-V[1]*a]}function W(V){return V=r.invert((V[0]-x)/a,(A-V[1])/a),V&&[V[0]*zt,V[1]*zt]}P.stream=function(V){return b&&(b.valid=!1),b=$a(m(n,i(_(V)))),b.valid=!0,b},P.clipAngle=function(V){return arguments.length?(m=V==null?(y=V,ja):el((y=+V)*_t),H()):y},P.clipExtent=function(V){return arguments.length?(F=V,_=V?Va(V[0][0],V[0][1],V[1][0],V[1][1]):ie,H()):F},P.scale=function(V){return arguments.length?(a=+V,Y()):a},P.translate=function(V){return arguments.length?(l=+V[0],s=+V[1],Y()):[l,s]},P.center=function(V){return arguments.length?(u=V[0]%360*_t,c=V[1]%360*_t,Y()):[u*zt,c*zt]},P.rotate=function(V){return arguments.length?(f=V[0]%360*_t,g=V[1]%360*_t,d=V.length>2?V[2]%360*_t:0,Y()):[f*zt,g*zt,d*zt]},o.rebind(P,i,"precision");function Y(){r=Da(n=Li(f,g,d),e);var V=e(u,c);return x=l-V[0]*a,A=s+V[1]*a,H()}function H(){return b&&(b.valid=!1,b=null),P}return function(){return e=t.apply(this,arguments),P.invert=e.invert&&W,Y()}}function $a(t){return Za(t,function(e,n){t.point(e*_t,n*_t)})}function ir(t,e){return[t,e]}(o.geo.equirectangular=function(){return bn(ir)}).raw=ir.invert=ir,o.geo.rotation=function(t){t=Li(t[0]%360*_t,t[1]*_t,t.length>2?t[2]*_t:0);function e(n){return n=t(n[0]*_t,n[1]*_t),n[0]*=zt,n[1]*=zt,n}return e.invert=function(n){return n=t.invert(n[0]*_t,n[1]*_t),n[0]*=zt,n[1]*=zt,n},e};function Ka(t,e){return[t>it?t-K:t<-it?t+K:t,e]}Ka.invert=ir;function Li(t,e,n){return t?e||n?Da(Qa(t),to(e,n)):Qa(t):e||n?to(e,n):Ka}function Ja(t){return function(e,n){return e+=t,[e>it?e-K:e<-it?e+K:e,n]}}function Qa(t){var e=Ja(t);return e.invert=Ja(-t),e}function to(t,e){var n=Math.cos(t),r=Math.sin(t),i=Math.cos(e),a=Math.sin(e);function l(s,u){var c=Math.cos(u),f=Math.cos(s)*c,g=Math.sin(s)*c,d=Math.sin(u),x=d*n+f*r;return[Math.atan2(g*i-x*a,f*n-d*r),Yt(x*i+g*a)]}return l.invert=function(s,u){var c=Math.cos(u),f=Math.cos(s)*c,g=Math.sin(s)*c,d=Math.sin(u),x=d*i-g*a;return[Math.atan2(g*i+d*a,f*n+x*r),Yt(x*n-f*r)]},l}o.geo.circle=function(){var t=[0,0],e,n=6,r;function i(){var a=typeof t=="function"?t.apply(this,arguments):t,l=Li(-a[0]*_t,-a[1]*_t,0).invert,s=[];return r(null,null,1,{point:function(u,c){s.push(u=l(u,c)),u[0]*=zt,u[1]*=zt}}),{type:"Polygon",coordinates:[s]}}return i.origin=function(a){return arguments.length?(t=a,i):t},i.angle=function(a){return arguments.length?(r=Ti((e=+a)*_t,n*_t),i):e},i.precision=function(a){return arguments.length?(r=Ti(e*_t,(n=+a)*_t),i):n},i.angle(90)};function Ti(t,e){var n=Math.cos(t),r=Math.sin(t);return function(i,a,l,s){var u=l*e;i!=null?(i=eo(n,i),a=eo(n,a),(l>0?ia)&&(i+=l*K)):(i=t+l*K,a=t-.5*u);for(var c,f=i;l>0?f>a:fQ}).map(d)).concat(o.range(Math.ceil(a/c)*c,i,c).filter(function(b){return rt(b%g)>Q}).map(x))}return y.lines=function(){return F().map(function(b){return{type:"LineString",coordinates:b}})},y.outline=function(){return{type:"Polygon",coordinates:[A(r).concat(m(l).slice(1),A(n).reverse().slice(1),m(s).reverse().slice(1))]}},y.extent=function(b){return arguments.length?y.majorExtent(b).minorExtent(b):y.minorExtent()},y.majorExtent=function(b){return arguments.length?(r=+b[0][0],n=+b[1][0],s=+b[0][1],l=+b[1][1],r>n&&(b=r,r=n,n=b),s>l&&(b=s,s=l,l=b),y.precision(_)):[[r,s],[n,l]]},y.minorExtent=function(b){return arguments.length?(e=+b[0][0],t=+b[1][0],a=+b[0][1],i=+b[1][1],e>t&&(b=e,e=t,t=b),a>i&&(b=a,a=i,i=b),y.precision(_)):[[e,a],[t,i]]},y.step=function(b){return arguments.length?y.majorStep(b).minorStep(b):y.minorStep()},y.majorStep=function(b){return arguments.length?(f=+b[0],g=+b[1],y):[f,g]},y.minorStep=function(b){return arguments.length?(u=+b[0],c=+b[1],y):[u,c]},y.precision=function(b){return arguments.length?(_=+b,d=no(a,i,90),x=ro(e,t,_),A=no(s,l,90),m=ro(r,n,_),y):_},y.majorExtent([[-180,-90+Q],[180,90-Q]]).minorExtent([[-180,-80-Q],[180,80+Q]])};function no(t,e,n){var r=o.range(t,e-Q,n).concat(e);return function(i){return r.map(function(a){return[i,a]})}}function ro(t,e,n){var r=o.range(t,e-Q,n).concat(e);return function(i){return r.map(function(a){return[a,i]})}}function Ni(t){return t.source}function Ei(t){return t.target}o.geo.greatArc=function(){var t=Ni,e,n=Ei,r;function i(){return{type:"LineString",coordinates:[e||t.apply(this,arguments),r||n.apply(this,arguments)]}}return i.distance=function(){return o.geo.distance(e||t.apply(this,arguments),r||n.apply(this,arguments))},i.source=function(a){return arguments.length?(t=a,e=typeof a=="function"?null:a,i):t},i.target=function(a){return arguments.length?(n=a,r=typeof a=="function"?null:a,i):n},i.precision=function(){return arguments.length?i:0},i},o.geo.interpolate=function(t,e){return ul(t[0]*_t,t[1]*_t,e[0]*_t,e[1]*_t)};function ul(t,e,n,r){var i=Math.cos(e),a=Math.sin(e),l=Math.cos(r),s=Math.sin(r),u=i*Math.cos(t),c=i*Math.sin(t),f=l*Math.cos(n),g=l*Math.sin(n),d=2*Math.asin(Math.sqrt(te(r-e)+i*l*te(n-t))),x=1/Math.sin(d),A=d?function(m){var _=Math.sin(m*=d)*x,y=Math.sin(d-m)*x,F=y*u+_*f,b=y*c+_*g,P=y*a+_*s;return[Math.atan2(b,F)*zt,Math.atan2(P,Math.sqrt(F*F+b*b))*zt]}:function(){return[t*zt,e*zt]};return A.distance=d,A}o.geo.length=function(t){return Bi=0,o.geo.stream(t,Un),Bi};var Bi,Un={sphere:ue,point:ue,lineStart:cl,lineEnd:ue,polygonStart:ue,polygonEnd:ue};function cl(){var t,e,n;Un.point=function(i,a){t=i*_t,e=Math.sin(a*=_t),n=Math.cos(a),Un.point=r},Un.lineEnd=function(){Un.point=Un.lineEnd=ue};function r(i,a){var l=Math.sin(a*=_t),s=Math.cos(a),u=rt((i*=_t)-t),c=Math.cos(u);Bi+=Math.atan2(Math.sqrt((u=s*Math.sin(u))*u+(u=n*l-e*s*c)*u),e*l+n*s*c),t=i,e=l,n=s}}function ar(t,e){function n(r,i){var a=Math.cos(r),l=Math.cos(i),s=t(a*l);return[s*l*Math.sin(r),s*Math.sin(i)]}return n.invert=function(r,i){var a=Math.sqrt(r*r+i*i),l=e(a),s=Math.sin(l),u=Math.cos(l);return[Math.atan2(r*s,a*u),Math.asin(a&&i*s/a)]},n}var io=ar(function(t){return Math.sqrt(2/(1+t))},function(t){return 2*Math.asin(t/2)});(o.geo.azimuthalEqualArea=function(){return bn(io)}).raw=io;var ao=ar(function(t){var e=Math.acos(t);return e&&e/Math.sin(e)},ie);(o.geo.azimuthalEquidistant=function(){return bn(ao)}).raw=ao;function oo(t,e){var n=Math.cos(t),r=function(s){return Math.tan(it/4+s/2)},i=t===e?Math.sin(t):Math.log(n/Math.cos(e))/Math.log(r(e)/r(t)),a=n*Math.pow(r(t),i)/i;if(!i)return Yr;function l(s,u){a>0?u<-bt+Q&&(u=-bt+Q):u>bt-Q&&(u=bt-Q);var c=a/Math.pow(r(u),i);return[c*Math.sin(i*s),a-c*Math.cos(i*s)]}return l.invert=function(s,u){var c=a-u,f=$(i)*Math.sqrt(s*s+c*c);return[Math.atan2(s,c)/i,2*Math.atan(Math.pow(a/f,1/i))-bt]},l}(o.geo.conicConformal=function(){return Si(oo)}).raw=oo;function so(t,e){var n=Math.cos(t),r=t===e?Math.sin(t):(n-Math.cos(e))/(e-t),i=n/r+t;if(rt(r)2?r[2]+90:90]):(r=n(),[r[0],r[1],r[2]-90])},n([0,0,90])}).raw=Di,o.geom={};function Yn(t){return t[0]}function or(t){return t[1]}o.geom.hull=function(t){var e=Yn,n=or;if(arguments.length)return r(t);function r(i){if(i.length<3)return[];var a=de(e),l=de(n),s,u=i.length,c=[],f=[];for(s=0;s=0;--s)m.push(i[c[g[s]][2]]);for(s=+x;s1&&X(t[n[r-2]],t[n[r-1]],t[i])<=0;)--r;n[r++]=i}return n.slice(0,r)}function fl(t,e){return t[0]-e[0]||t[1]-e[1]}o.geom.polygon=function(t){return _e(t,Xr),t};var Xr=o.geom.polygon.prototype=[];Xr.area=function(){for(var t=-1,e=this.length,n,r=this[e-1],i=0;++tQ)s=s.L;else if(l=e-pl(s,n),l>Q){if(!s.R){r=s;break}s=s.R}else{a>-Q?(r=s.P,i=s):l>-Q?(r=s,i=s.N):r=i=s;break}var u=_o(t);if(Wn.insert(r,u),!(!r&&!i)){if(r===i){$n(r),i=_o(r.site),Wn.insert(u,i),u.edge=i.edge=lr(r.site,u.site),Zn(r),Zn(i);return}if(!i){u.edge=lr(r.site,u.site);return}$n(r),$n(i);var c=r.site,f=c.x,g=c.y,d=t.x-f,x=t.y-g,A=i.site,m=A.x-f,_=A.y-g,y=2*(d*_-x*m),F=d*d+x*x,b=m*m+_*_,P={x:(_*F-x*b)/y+f,y:(d*b-m*F)/y+g};Wr(i.edge,c,A,P),u.edge=lr(c,t,null,P),i.edge=lr(t,A,null,P),Zn(r),Zn(i)}}function yo(t,e){var n=t.site,r=n.x,i=n.y,a=i-e;if(!a)return r;var l=t.P;if(!l)return-1/0;n=l.site;var s=n.x,u=n.y,c=u-e;if(!c)return s;var f=s-r,g=1/a-1/c,d=f/c;return g?(-d+Math.sqrt(d*d-2*g*(f*f/(-2*c)-u+c/2+i-a/2)))/g+r:(r+s)/2}function pl(t,e){var n=t.N;if(n)return yo(n,e);var r=t.site;return r.y===e?r.x:1/0}function vo(t){this.site=t,this.edges=[]}vo.prototype.prepare=function(){for(var t=this.edges,e=t.length,n;e--;)n=t[e].edge,(!n.b||!n.a)&&t.splice(e,1);return t.sort(xo),t.length};function ml(t){for(var e=t[0][0],n=t[1][0],r=t[0][1],i=t[1][1],a,l,s,u,c=Nn,f=c.length,g,d,x,A,m,_;f--;)if(g=c[f],!(!g||!g.prepare()))for(x=g.edges,A=x.length,d=0;dQ||rt(u-l)>Q)&&(x.splice(d,0,new Zr(xl(g.site,_,rt(s-e)Q?{x:e,y:rt(a-e)Q?{x:rt(l-i)Q?{x:n,y:rt(a-n)Q?{x:rt(l-r)=-jt)){var d=u*u+c*c,x=f*f+_*_,A=(_*d-c*x)/g,m=(u*x-f*d)/g,_=m+s,y=mo.pop()||new _l;y.arc=t,y.site=i,y.x=A+l,y.y=_+Math.sqrt(A*A+m*m),y.cy=_,t.circle=y;for(var F=null,b=sr._;b;)if(y.y=a)return;if(f>d){if(!r)r={x:A,y:l};else if(r.y>=s)return;n={x:A,y:s}}else{if(!r)r={x:A,y:s};else if(r.y1)if(f>d){if(!r)r={x:(l-y)/_,y:l};else if(r.y>=s)return;n={x:(s-y)/_,y:s}}else{if(!r)r={x:(s-y)/_,y:s};else if(r.y=a)return;n={x:a,y:_*a+y}}else{if(!r)r={x:a,y:_*a+y};else if(r.x=f&&y.x<=d&&y.y>=g&&y.y<=x?[[f,x],[d,x],[d,g],[f,g]]:[];F.point=u[m]}),c}function s(u){return u.map(function(c,f){return{x:Math.round(r(c,f)/Q)*Q,y:Math.round(i(c,f)/Q)*Q,i:f}})}return l.links=function(u){return Gi(s(u)).edges.filter(function(c){return c.l&&c.r}).map(function(c){return{source:u[c.l.i],target:u[c.r.i]}})},l.triangles=function(u){var c=[];return Gi(s(u)).cells.forEach(function(f,g){for(var d=f.site,x=f.edges.sort(xo),A=-1,m=x.length,_,y=x[m-1].edge,F=y.l===d?y.r:y.l;++Ab&&(b=f.x),f.y>P&&(P=f.y),x.push(f.x),A.push(f.y);else for(m=0;m<_;++m){var W=+g(f=c[m],m),Y=+d(f,m);Wb&&(b=W),Y>P&&(P=Y),x.push(W),A.push(Y)}var H=b-y,V=P-F;H>V?P=F+H:b=y+V;function st(xt,Ct,tt,ft,yt,nt,mt,Dt){if(!(isNaN(tt)||isNaN(ft)))if(xt.leaf){var Ht=xt.x,Zt=xt.y;if(Ht!=null)if(rt(Ht-tt)+rt(Zt-ft)<.01)gt(xt,Ct,tt,ft,yt,nt,mt,Dt);else{var se=xt.point;xt.x=xt.y=xt.point=null,gt(xt,se,Ht,Zt,yt,nt,mt,Dt),gt(xt,Ct,tt,ft,yt,nt,mt,Dt)}else xt.x=tt,xt.y=ft,xt.point=Ct}else gt(xt,Ct,tt,ft,yt,nt,mt,Dt)}function gt(xt,Ct,tt,ft,yt,nt,mt,Dt){var Ht=(yt+mt)*.5,Zt=(nt+Dt)*.5,se=tt>=Ht,pe=ft>=Zt,Ee=pe<<1|se;xt.leaf=!1,xt=xt.nodes[Ee]||(xt.nodes[Ee]=ko()),se?yt=Ht:mt=Ht,pe?nt=Zt:Dt=Zt,st(xt,Ct,tt,ft,yt,nt,mt,Dt)}var At=ko();if(At.add=function(xt){st(At,xt,+g(xt,++m),+d(xt,m),y,F,b,P)},At.visit=function(xt){fr(xt,At,y,F,b,P)},At.find=function(xt){return Ml(At,xt[0],xt[1],y,F,b,P)},m=-1,e==null){for(;++m<_;)st(At,c[m],x[m],A[m],y,F,b,P);--m}else c.forEach(At.add);return x=A=c=f=null,At}return u.x=function(c){return arguments.length?(a=c,u):a},u.y=function(c){return arguments.length?(l=c,u):l},u.extent=function(c){return arguments.length?(c==null?e=n=r=i=null:(e=+c[0][0],n=+c[0][1],r=+c[1][0],i=+c[1][1]),u):e==null?null:[[e,n],[r,i]]},u.size=function(c){return arguments.length?(c==null?e=n=r=i=null:(e=n=0,r=+c[0],i=+c[1]),u):e==null?null:[r-e,i-n]},u};function kl(t){return t.x}function Cl(t){return t.y}function ko(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function fr(t,e,n,r,i,a){if(!t(e,n,r,i,a)){var l=(n+i)*.5,s=(r+a)*.5,u=e.nodes;u[0]&&fr(t,u[0],n,r,l,s),u[1]&&fr(t,u[1],l,r,i,s),u[2]&&fr(t,u[2],n,s,l,a),u[3]&&fr(t,u[3],l,s,i,a)}}function Ml(t,e,n,r,i,a,l){var s=1/0,u;return function c(f,g,d,x,A){if(!(g>a||d>l||x=W,V=n>=Y,st=V<<1|H,gt=st+4;stn&&(a=e.slice(n,a),s[l]?s[l]+=a:s[++l]=a),(r=r[0])===(i=i[0])?s[l]?s[l]+=i:s[++l]=i:(s[++l]=null,u.push({i:l,x:pn(r,i)})),n=Hi.lastIndex;return n=0&&!(r=o.interpolators[n](t,e)););return r}o.interpolators=[function(t,e){var n=typeof e;return(n==="string"?br.has(e.toLowerCase())||/^(#|rgb\(|hsl\()/i.test(e)?Vi:Mo:e instanceof Kt?Vi:Array.isArray(e)?Jr:n==="object"&&isNaN(e)?Co:pn)(t,e)}],o.interpolateArray=Jr;function Jr(t,e){var n=[],r=[],i=t.length,a=e.length,l=Math.min(t.length,e.length),s;for(s=0;s=0?t.slice(0,e):t,r=e>=0?t.slice(e+1):"in";return n=Sl.get(n)||So,r=Pl.get(r)||ie,Al(r(n.apply(null,h.call(arguments,1))))};function Al(t){return function(e){return e<=0?0:e>=1?1:t(e)}}function Po(t){return function(e){return 1-t(1-e)}}function Ao(t){return function(e){return .5*(e<.5?t(2*e):2-t(2-2*e))}}function Fl(t){return t*t}function Ll(t){return t*t*t}function Tl(t){if(t<=0)return 0;if(t>=1)return 1;var e=t*t,n=e*t;return 4*(t<.5?n:3*(t-e)+n-.75)}function Nl(t){return function(e){return Math.pow(e,t)}}function El(t){return 1-Math.cos(t*bt)}function Bl(t){return Math.pow(2,10*(t-1))}function Dl(t){return 1-Math.sqrt(1-t*t)}function Il(t,e){var n;return arguments.length<2&&(e=.45),arguments.length?n=e/K*Math.asin(1/t):(t=1,n=e/4),function(r){return 1+t*Math.pow(2,-10*r)*Math.sin((r-n)*K/e)}}function zl(t){return t||(t=1.70158),function(e){return e*e*((t+1)*e-t)}}function Rl(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}o.interpolateHcl=Ol;function Ol(t,e){t=o.hcl(t),e=o.hcl(e);var n=t.h,r=t.c,i=t.l,a=e.h-n,l=e.c-r,s=e.l-i;return isNaN(l)&&(l=0,r=isNaN(r)?e.c:r),isNaN(a)?(a=0,n=isNaN(n)?e.h:n):a>180?a-=360:a<-180&&(a+=360),function(u){return Ge(n+a*u,r+l*u,i+s*u)+""}}o.interpolateHsl=jl;function jl(t,e){t=o.hsl(t),e=o.hsl(e);var n=t.h,r=t.s,i=t.l,a=e.h-n,l=e.s-r,s=e.l-i;return isNaN(l)&&(l=0,r=isNaN(r)?e.s:r),isNaN(a)?(a=0,n=isNaN(n)?e.h:n):a>180?a-=360:a<-180&&(a+=360),function(u){return Mn(n+a*u,r+l*u,i+s*u)+""}}o.interpolateLab=Gl;function Gl(t,e){t=o.lab(t),e=o.lab(e);var n=t.l,r=t.a,i=t.b,a=e.l-n,l=e.a-r,s=e.b-i;return function(u){return jn(n+a*u,r+l*u,i+s*u)+""}}o.interpolateRound=Fo;function Fo(t,e){return e-=t,function(n){return Math.round(t+e*n)}}o.transform=function(t){var e=v.createElementNS(o.ns.prefix.svg,"g");return(o.transform=function(n){if(n!=null){e.setAttribute("transform",n);var r=e.transform.baseVal.consolidate()}return new Lo(r?r.matrix:ql)})(t)};function Lo(t){var e=[t.a,t.b],n=[t.c,t.d],r=No(e),i=To(e,n),a=No(Vl(n,e,-i))||0;e[0]*n[1]180?e+=360:e-t>180&&(t+=360),r.push({i:n.push(Kn(n)+"rotate(",null,")")-2,x:pn(t,e)})):e&&n.push(Kn(n)+"rotate("+e+")")}function Yl(t,e,n,r){t!==e?r.push({i:n.push(Kn(n)+"skewX(",null,")")-2,x:pn(t,e)}):e&&n.push(Kn(n)+"skewX("+e+")")}function Xl(t,e,n,r){if(t[0]!==e[0]||t[1]!==e[1]){var i=n.push(Kn(n)+"scale(",null,",",null,")");r.push({i:i-4,x:pn(t[0],e[0])},{i:i-2,x:pn(t[1],e[1])})}else(e[0]!==1||e[1]!==1)&&n.push(Kn(n)+"scale("+e+")")}function Eo(t,e){var n=[],r=[];return t=o.transform(t),e=o.transform(e),Hl(t.translate,e.translate,n,r),Ul(t.rotate,e.rotate,n,r),Yl(t.skew,e.skew,n,r),Xl(t.scale,e.scale,n,r),t=e=null,function(i){for(var a=-1,l=r.length,s;++a0?a=P:(n.c=null,n.t=NaN,n=null,e.start({type:"end",alpha:a=0})):P>0&&(e.start({type:"start",alpha:a=P}),n=Pr(t.tick)),t):a},t.start=function(){var P,W=x.length,Y=A.length,H=r[0],V=r[1],st,gt;for(P=0;P=0;)a.push(f=c[u]),f.parent=s,f.depth=s.depth+1;n&&(s.value=0),s.children=c}else n&&(s.value=+n.call(r,s,s.depth)||0),delete s.children;return sn(i,function(g){var d,x;t&&(d=g.children)&&d.sort(t),n&&(x=g.parent)&&(x.value+=g.value)}),l}return r.sort=function(i){return arguments.length?(t=i,r):t},r.children=function(i){return arguments.length?(e=i,r):e},r.value=function(i){return arguments.length?(n=i,r):n},r.revalue=function(i){return n&&(gr(i,function(a){a.children&&(a.value=0)}),sn(i,function(a){var l;a.children||(a.value=+n.call(r,a,a.depth)||0),(l=a.parent)&&(l.value+=a.value)})),i},r};function hr(t,e){return o.rebind(t,e,"sort","children","value"),t.nodes=t,t.links=lu,t}function gr(t,e){for(var n=[t];(t=n.pop())!=null;)if(e(t),(i=t.children)&&(r=i.length))for(var r,i;--r>=0;)n.push(i[r])}function sn(t,e){for(var n=[t],r=[];(t=n.pop())!=null;)if(r.push(t),(l=t.children)&&(a=l.length))for(var i=-1,a,l;++ii&&(i=s),r.push(s)}for(l=0;lr&&(n=e,r=i);return n}function pu(t){return t.reduce(mu,0)}function mu(t,e){return t+e[1]}o.layout.histogram=function(){var t=!0,e=Number,n=yu,r=_u;function i(a,d){for(var s=[],u=a.map(e,this),c=n.call(this,u,d),f=r.call(this,c,u,d),g,d=-1,x=u.length,A=f.length-1,m=t?1:1/x,_;++d0)for(d=-1;++d=c[0]&&_<=c[1]&&(g=s[o.bisect(f,_,1,A)-1],g.y+=m,g.push(a[d]));return s}return i.value=function(a){return arguments.length?(e=a,i):e},i.range=function(a){return arguments.length?(n=de(a),i):n},i.bins=function(a){return arguments.length?(r=typeof a=="number"?function(l){return zo(l,a)}:de(a),i):r},i.frequency=function(a){return arguments.length?(t=!!a,i):t},i};function _u(t,e){return zo(t,Math.ceil(Math.log(e.length)/Math.LN2+1))}function zo(t,e){for(var n=-1,r=+t[0],i=(t[1]-r)/e,a=[];++n<=e;)a[n]=i*n+r;return a}function yu(t){return[o.min(t),o.max(t)]}o.layout.pack=function(){var t=o.layout.hierarchy().sort(vu),e=0,n=[1,1],r;function i(a,l){var s=t.call(this,a,l),u=s[0],c=n[0],f=n[1],g=r==null?Math.sqrt:typeof r=="function"?r:function(){return r};if(u.x=u.y=0,sn(u,function(x){x.r=+g(x.value)}),sn(u,jo),e){var d=e*(r?1:Math.max(2*u.r/c,2*u.r/f))/2;sn(u,function(x){x.r+=d}),sn(u,jo),sn(u,function(x){x.r-=d})}return Go(u,c/2,f/2,r?1:1/Math.max(2*u.r/c,2*u.r/f)),s}return i.size=function(a){return arguments.length?(n=a,i):n},i.radius=function(a){return arguments.length?(r=a==null||typeof a=="function"?a:+a,i):r},i.padding=function(a){return arguments.length?(e=+a,i):e},hr(i,t)};function vu(t,e){return t.value-e.value}function Xi(t,e){var n=t._pack_next;t._pack_next=e,e._pack_prev=t,e._pack_next=n,n._pack_prev=e}function Ro(t,e){t._pack_next=e,e._pack_prev=t}function Oo(t,e){var n=e.x-t.x,r=e.y-t.y,i=t.r+e.r;return .999*i*i>n*n+r*r}function jo(t){if(!(e=t.children)||!(d=e.length))return;var e,n=1/0,r=-1/0,i=1/0,a=-1/0,l,s,u,c,f,g,d;function x(P){n=Math.min(P.x-P.r,n),r=Math.max(P.x+P.r,r),i=Math.min(P.y-P.r,i),a=Math.max(P.y+P.r,a)}if(e.forEach(xu),l=e[0],l.x=-l.r,l.y=0,x(l),d>1&&(s=e[1],s.x=s.r,s.y=0,x(s),d>2))for(u=e[2],Vo(l,s,u),x(u),Xi(l,u),l._pack_prev=u,Xi(u,s),s=l._pack_next,c=3;c_.x&&(_=W),W.depth>y.depth&&(y=W)});var F=e(m,_)/2-m.x,b=n[0]/(_.x+e(_,m)/2+F),P=n[1]/(y.depth||1);gr(x,function(W){W.x=(W.x+F)*b,W.y=W.depth*P})}return d}function a(f){for(var g={A:null,children:[f]},d=[g],x;(x=d.pop())!=null;)for(var A=x.children,m,_=0,y=A.length;_0&&(wu(Cu(m,f,d),f,W),y+=W,F+=W),b+=m.m,y+=x.m,P+=_.m,F+=A.m;m&&!Zi(A)&&(A.t=m,A.m+=b-F),x&&!Wi(_)&&(_.t=x,_.m+=y-P,d=f)}return d}function c(f){f.x*=n[0],f.y=f.depth*n[1]}return i.separation=function(f){return arguments.length?(e=f,i):e},i.size=function(f){return arguments.length?(r=(n=f)==null?c:null,i):r?null:n},i.nodeSize=function(f){return arguments.length?(r=(n=f)==null?null:c,i):r?n:null},hr(i,t)};function qo(t,e){return t.parent==e.parent?1:2}function Wi(t){var e=t.children;return e.length?e[0]:t.t}function Zi(t){var e=t.children,n;return(n=e.length)?e[n-1]:t.t}function wu(t,e,n){var r=n/(e.i-t.i);e.c-=r,e.s+=n,t.c+=r,e.z+=n,e.m+=n}function ku(t){for(var e=0,n=0,r=t.children,i=r.length,a;--i>=0;)a=r[i],a.z+=e,a.m+=e,e+=a.s+(n+=a.c)}function Cu(t,e,n){return t.a.parent===e.parent?t.a:n}o.layout.cluster=function(){var t=o.layout.hierarchy().sort(null).value(null),e=qo,n=[1,1],r=!1;function i(a,l){var s=t.call(this,a,l),u=s[0],c,f=0;sn(u,function(m){var _=m.children;_&&_.length?(m.x=Su(_),m.y=Mu(_)):(m.x=c?f+=e(m,c):0,m.y=0,c=m)});var g=Ho(u),d=Uo(u),x=g.x-e(g,d)/2,A=d.x+e(d,g)/2;return sn(u,r?function(m){m.x=(m.x-u.x)*n[0],m.y=(u.y-m.y)*n[1]}:function(m){m.x=(m.x-x)/(A-x)*n[0],m.y=(1-(u.y?m.y/u.y:1))*n[1]}),s}return i.separation=function(a){return arguments.length?(e=a,i):e},i.size=function(a){return arguments.length?(r=(n=a)==null,i):r?null:n},i.nodeSize=function(a){return arguments.length?(r=(n=a)!=null,i):r?n:null},hr(i,t)};function Mu(t){return 1+o.max(t,function(e){return e.y})}function Su(t){return t.reduce(function(e,n){return e+n.x},0)/t.length}function Ho(t){var e=t.children;return e&&e.length?Ho(e[0]):t}function Uo(t){var e=t.children,n;return e&&(n=e.length)?Uo(e[n-1]):t}o.layout.treemap=function(){var t=o.layout.hierarchy(),e=Math.round,n=[1,1],r=null,i=$i,a=!1,l,s="squarify",u=.5*(1+Math.sqrt(5));function c(m,_){for(var y=-1,F=m.length,b,P;++y0;)F.push(P=b[V-1]),F.area+=P.area,s!=="squarify"||(Y=d(F,H))<=W?(b.pop(),W=Y):(F.area-=F.pop().area,x(F,H,y,!1),H=Math.min(y.dx,y.dy),F.length=F.area=0,W=1/0);F.length&&(x(F,H,y,!0),F.length=F.area=0),_.forEach(f)}}function g(m){var _=m.children;if(_&&_.length){var y=i(m),F=_.slice(),b,P=[];for(c(F,y.dx*y.dy/m.value),P.area=0;b=F.pop();)P.push(b),P.area+=b.area,b.z!=null&&(x(P,b.z?y.dx:y.dy,y,!F.length),P.length=P.area=0);_.forEach(g)}}function d(m,_){for(var y=m.area,F,b=0,P=1/0,W=-1,Y=m.length;++Wb&&(b=F));return y*=y,_*=_,y?Math.max(_*b*u/y,y/(_*P*u)):1/0}function x(m,_,y,F){var b=-1,P=m.length,W=y.x,Y=y.y,H=_?e(m.area/_):0,V;if(_==y.dx){for((F||H>y.dy)&&(H=y.dy);++by.dx)&&(H=y.dx);++b1);return t+e*r*Math.sqrt(-2*Math.log(a)/a)}},logNormal:function(){var t=o.random.normal.apply(o,arguments);return function(){return Math.exp(t())}},bates:function(t){var e=o.random.irwinHall(t);return function(){return e()/t}},irwinHall:function(t){return function(){for(var e=0,n=0;n2?Lu:Pu,c=r?Zl:Wl;return i=u(t,e,c,n),a=u(e,t,c,En),s}function s(u){return i(u)}return s.invert=function(u){return a(u)},s.domain=function(u){return arguments.length?(t=u.map(Number),l()):t},s.range=function(u){return arguments.length?(e=u,l()):e},s.rangeRound=function(u){return s.range(u).interpolate(Fo)},s.clamp=function(u){return arguments.length?(r=u,l()):r},s.interpolate=function(u){return arguments.length?(n=u,l()):n},s.ticks=function(u){return Qi(t,u)},s.tickFormat=function(u,c){return ta(t,u,c)},s.nice=function(u){return Wo(t,u),l()},s.copy=function(){return Xo(t,e,n,r)},l()}function Ji(t,e){return o.rebind(t,e,"range","rangeRound","interpolate","clamp")}function Wo(t,e){return Ki(t,Au(dr(t,e)[2]))}function dr(t,e){e==null&&(e=10);var n=Jn(t),r=n[1]-n[0],i=Math.pow(10,Math.floor(Math.log(r/e)/Math.LN10)),a=e/r*i;return a<=.15?i*=10:a<=.35?i*=5:a<=.75&&(i*=2),n[0]=Math.ceil(n[0]/i)*i,n[1]=Math.floor(n[1]/i)*i+i*.5,n[2]=i,n}function Qi(t,e){return o.range.apply(o,dr(t,e))}function ta(t,e,n){var r=dr(t,e);if(n){var i=ka.exec(n);if(i.shift(),i[8]==="s"){var a=o.formatPrefix(Math.max(rt(r[0]),rt(r[1])));return i[7]||(i[7]="."+ti(a.scale(r[2]))),i[8]="f",n=o.format(i.join("")),function(l){return n(a.scale(l))+a.symbol}}i[7]||(i[7]="."+Nu(i[8],r)),n=i.join("")}else n=",."+ti(r[2])+"f";return o.format(n)}var Tu={s:1,g:1,p:1,r:1,e:1};function ti(t){return-Math.floor(Math.log(t)/Math.LN10+.01)}function Nu(t,e){var n=ti(e[2]);return t in Tu?Math.abs(n-ti(Math.max(rt(e[0]),rt(e[1]))))+ +(t!=="e"):n-(t==="%")*2}o.scale.log=function(){return Zo(o.scale.linear().domain([0,1]),10,!0,[1,10])};function Zo(t,e,n,r){function i(s){return(n?Math.log(s<0?0:s):-Math.log(s>0?0:-s))/Math.log(e)}function a(s){return n?Math.pow(e,s):-Math.pow(e,-s)}function l(s){return t(i(s))}return l.invert=function(s){return a(t.invert(s))},l.domain=function(s){return arguments.length?(n=s[0]>=0,t.domain((r=s.map(Number)).map(i)),l):r},l.base=function(s){return arguments.length?(e=+s,t.domain(r.map(i)),l):e},l.nice=function(){var s=Ki(r.map(i),n?Math:Eu);return t.domain(s),r=s.map(a),l},l.ticks=function(){var s=Jn(r),u=[],c=s[0],f=s[1],g=Math.floor(i(c)),d=Math.ceil(i(f)),x=e%1?2:e;if(isFinite(d-g)){if(n){for(;g0;A--)u.push(a(g)*A);for(g=0;u[g]f;d--);u=u.slice(g,d)}return u},l.tickFormat=function(s,u){if(!arguments.length)return $o;arguments.length<2?u=$o:typeof u!="function"&&(u=o.format(u));var c=Math.max(.1,s/l.ticks().length),f=n?(g=1e-12,Math.ceil):(g=-1e-12,Math.floor),g;return function(d){return d/a(f(i(d)+g))<=c?u(d):""}},l.copy=function(){return Zo(t.copy(),e,n,r)},Ji(l,t)}var $o=o.format(".0e"),Eu={floor:function(t){return-Math.ceil(-t)},ceil:function(t){return-Math.floor(-t)}};o.scale.pow=function(){return Ko(o.scale.linear(),1,[0,1])};function Ko(t,e,n){var r=ei(e),i=ei(1/e);function a(l){return t(r(l))}return a.invert=function(l){return i(t.invert(l))},a.domain=function(l){return arguments.length?(t.domain((n=l.map(Number)).map(r)),a):n},a.ticks=function(l){return Qi(n,l)},a.tickFormat=function(l,s){return ta(n,l,s)},a.nice=function(l){return a.domain(Wo(n,l))},a.exponent=function(l){return arguments.length?(r=ei(e=l),i=ei(1/e),t.domain(n.map(r)),a):e},a.copy=function(){return Ko(t.copy(),e,n)},Ji(a,t)}function ei(t){return function(e){return e<0?-Math.pow(-e,t):Math.pow(e,t)}}o.scale.sqrt=function(){return o.scale.pow().exponent(.5)},o.scale.ordinal=function(){return Jo([],{t:"range",a:[[]]})};function Jo(t,e){var n,r,i;function a(s){return r[((n.get(s)||(e.t==="range"?n.set(s,t.push(s)):NaN))-1)%r.length]}function l(s,u){return o.range(t.length).map(function(c){return s+u*c})}return a.domain=function(s){if(!arguments.length)return t;t=[],n=new dt;for(var u=-1,c=s.length,f;++u0?n[a-1]:t[0],ad?0:1;if(f=Lt)return u(f,A)+(c?u(c,1-A):"")+"Z";var m,_,y,F,b=0,P=0,W,Y,H,V,st,gt,At,xt,Ct=[];if((F=(+l.apply(this,arguments)||0)/2)&&(y=r===ni?Math.sqrt(c*c+f*f):+r.apply(this,arguments),A||(P*=-1),f&&(P=Yt(y/f*Math.sin(F))),c&&(b=Yt(y/c*Math.sin(F)))),f){W=f*Math.cos(g+P),Y=f*Math.sin(g+P),H=f*Math.cos(d-P),V=f*Math.sin(d-P);var tt=Math.abs(d-g-2*P)<=it?0:1;if(P&&ri(W,Y,H,V)===A^tt){var ft=(g+d)/2;W=f*Math.cos(ft),Y=f*Math.sin(ft),H=V=null}}else W=Y=0;if(c){st=c*Math.cos(d-b),gt=c*Math.sin(d-b),At=c*Math.cos(g+b),xt=c*Math.sin(g+b);var yt=Math.abs(g-d+2*b)<=it?0:1;if(b&&ri(st,gt,At,xt)===1-A^yt){var nt=(g+d)/2;st=c*Math.cos(nt),gt=c*Math.sin(nt),At=xt=null}}else st=gt=0;if(x>Q&&(m=Math.min(Math.abs(f-c)/2,+n.apply(this,arguments)))>.001){_=c0?0:1}function ii(t,e,n,r,i){var a=t[0]-e[0],l=t[1]-e[1],s=(i?r:-r)/Math.sqrt(a*a+l*l),u=s*l,c=-s*a,f=t[0]+u,g=t[1]+c,d=e[0]+u,x=e[1]+c,A=(f+d)/2,m=(g+x)/2,_=d-f,y=x-g,F=_*_+y*y,b=n-r,P=f*x-d*g,W=(y<0?-1:1)*Math.sqrt(Math.max(0,b*b*F-P*P)),Y=(P*y-_*W)/F,H=(-P*_-y*W)/F,V=(P*y+_*W)/F,st=(-P*_+y*W)/F,gt=Y-A,At=H-m,xt=V-A,Ct=st-m;return gt*gt+At*At>xt*xt+Ct*Ct&&(Y=V,H=st),[[Y-u,H-c],[Y*n/b,H*n/b]]}function as(t){var e=Yn,n=or,r=rr,i=Qe,a=i.key,l=.7;function s(u){var c=[],f=[],g=-1,d=u.length,x,A=de(e),m=de(n);function _(){c.push("M",i(t(f),l))}for(;++g1?t.join("L"):t+"Z"}function os(t){return t.join("L")+"Z"}function Vu(t){for(var e=0,n=t.length,r=t[0],i=[r[0],",",r[1]];++e1&&i.push("H",r[0]),i.join("")}function na(t){for(var e=0,n=t.length,r=t[0],i=[r[0],",",r[1]];++e1){s=e[1],a=t[u],u++,r+="C"+(i[0]+l[0])+","+(i[1]+l[1])+","+(a[0]-s[0])+","+(a[1]-s[1])+","+a[0]+","+a[1];for(var c=2;c9&&(a=n*3/Math.sqrt(a),l[s]=a*r,l[s+1]=a*i));for(s=-1;++s<=u;)a=(t[Math.min(u,s+1)][0]-t[Math.max(0,s-1)][0])/(6*(1+l[s]*l[s])),e.push([a||0,l[s]*a||0]);return e}function Ku(t){return t.length<3?Qe(t):t[0]+ai(t,$u(t))}o.svg.line.radial=function(){var t=as(cs);return t.radius=t.x,delete t.x,t.angle=t.y,delete t.y,t};function cs(t){for(var e,n=-1,r=t.length,i,a;++nit)+",1 "+g}function c(f,g,d,x){return"Q 0,0 "+x}return a.radius=function(f){return arguments.length?(n=de(f),a):n},a.source=function(f){return arguments.length?(t=de(f),a):t},a.target=function(f){return arguments.length?(e=de(f),a):e},a.startAngle=function(f){return arguments.length?(r=de(f),a):r},a.endAngle=function(f){return arguments.length?(i=de(f),a):i},a};function Ju(t){return t.radius}o.svg.diagonal=function(){var t=Ni,e=Ei,n=hs;function r(i,a){var l=t.call(this,i,a),s=e.call(this,i,a),u=(l.y+s.y)/2,c=[l,{x:l.x,y:u},{x:s.x,y:u},s];return c=c.map(n),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}return r.source=function(i){return arguments.length?(t=de(i),r):t},r.target=function(i){return arguments.length?(e=de(i),r):e},r.projection=function(i){return arguments.length?(n=i,r):n},r};function hs(t){return[t.x,t.y]}o.svg.diagonal.radial=function(){var t=o.svg.diagonal(),e=hs,n=t.projection;return t.projection=function(r){return arguments.length?n(Qu(e=r)):e},t};function Qu(t){return function(){var e=t.apply(this,arguments),n=e[0],r=e[1]-bt;return[n*Math.cos(r),n*Math.sin(r)]}}o.svg.symbol=function(){var t=ec,e=tc;function n(r,i){return(ds.get(t.call(this,r,i))||gs)(e.call(this,r,i))}return n.type=function(r){return arguments.length?(t=de(r),n):t},n.size=function(r){return arguments.length?(e=de(r),n):e},n};function tc(){return 64}function ec(){return"circle"}function gs(t){var e=Math.sqrt(t/it);return"M0,"+e+"A"+e+","+e+" 0 1,1 0,"+-e+"A"+e+","+e+" 0 1,1 0,"+e+"Z"}var ds=o.map({circle:gs,cross:function(t){var e=Math.sqrt(t/5)/2;return"M"+-3*e+","+-e+"H"+-e+"V"+-3*e+"H"+e+"V"+-e+"H"+3*e+"V"+e+"H"+e+"V"+3*e+"H"+-e+"V"+e+"H"+-3*e+"Z"},diamond:function(t){var e=Math.sqrt(t/(2*ps)),n=e*ps;return"M0,"+-e+"L"+n+",0 0,"+e+" "+-n+",0Z"},square:function(t){var e=Math.sqrt(t)/2;return"M"+-e+","+-e+"L"+e+","+-e+" "+e+","+e+" "+-e+","+e+"Z"},"triangle-down":function(t){var e=Math.sqrt(t/oi),n=e*oi/2;return"M0,"+n+"L"+e+","+-n+" "+-e+","+-n+"Z"},"triangle-up":function(t){var e=Math.sqrt(t/oi),n=e*oi/2;return"M0,"+-n+"L"+e+","+n+" "+-e+","+n+"Z"}});o.svg.symbolTypes=ds.keys();var oi=Math.sqrt(3),ps=Math.tan(30*_t);Ot.transition=function(t){for(var e=Bn||++_s,n=la(t),r=[],i,a,l=li||{time:Date.now(),ease:Tl,delay:0,duration:250},s=-1,u=this.length;++s0;)g[--F].call(t,y);if(_>=1)return l.event&&l.event.end.call(t,t.__data__,e),--a.count?delete a[r]:delete t[n],1}l||(s=i.time,u=Pr(d,0,s),l=a[r]={tween:new dt,time:s,timer:u,delay:i.delay,duration:i.duration,ease:i.ease,index:e},i=null,++a.count)}o.svg.axis=function(){var t=o.scale.linear(),e=ys,n=6,r=6,i=3,a=[10],l=null,s;function u(c){c.each(function(){var f=o.select(this),g=this.__chart__||t,d=this.__chart__=t.copy(),x=l??(d.ticks?d.ticks.apply(d,a):d.domain()),A=s??(d.tickFormat?d.tickFormat.apply(d,a):ie),m=f.selectAll(".tick").data(x,d),_=m.enter().insert("g",".domain").attr("class","tick").style("opacity",Q),y=o.transition(m.exit()).style("opacity",Q).remove(),F=o.transition(m.order()).style("opacity",1),b=Math.max(n,0)+i,P,W=Qr(d),Y=f.selectAll(".domain").data([0]),H=(Y.enter().append("path").attr("class","domain"),o.transition(Y));_.append("line"),_.append("text");var V=_.select("line"),st=F.select("line"),gt=m.select("text").text(A),At=_.select("text"),xt=F.select("text"),Ct=e==="top"||e==="left"?-1:1,tt,ft,yt,nt;if(e==="bottom"||e==="top"?(P=ic,tt="x",yt="y",ft="x2",nt="y2",gt.attr("dy",Ct<0?"0em":".71em").style("text-anchor","middle"),H.attr("d","M"+W[0]+","+Ct*r+"V0H"+W[1]+"V"+Ct*r)):(P=ac,tt="y",yt="x",ft="y2",nt="x2",gt.attr("dy",".32em").style("text-anchor",Ct<0?"end":"start"),H.attr("d","M"+Ct*r+","+W[0]+"H0V"+W[1]+"H"+Ct*r)),V.attr(nt,Ct*n),At.attr(yt,Ct*b),st.attr(ft,0).attr(nt,Ct*n),xt.attr(tt,0).attr(yt,Ct*b),d.rangeBand){var mt=d,Dt=mt.rangeBand()/2;g=d=function(Ht){return mt(Ht)+Dt}}else g.rangeBand?g=d:y.call(P,d,g);_.call(P,g,d),F.call(P,d,d)})}return u.scale=function(c){return arguments.length?(t=c,u):t},u.orient=function(c){return arguments.length?(e=c in rc?c+"":ys,u):e},u.ticks=function(){return arguments.length?(a=w(arguments),u):a},u.tickValues=function(c){return arguments.length?(l=c,u):l},u.tickFormat=function(c){return arguments.length?(s=c,u):s},u.tickSize=function(c){var f=arguments.length;return f?(n=+c,r=+arguments[f-1],u):n},u.innerTickSize=function(c){return arguments.length?(n=+c,u):n},u.outerTickSize=function(c){return arguments.length?(r=+c,u):r},u.tickPadding=function(c){return arguments.length?(i=+c,u):i},u.tickSubdivide=function(){return arguments.length&&u},u};var ys="bottom",rc={top:1,right:1,bottom:1,left:1};function ic(t,e,n){t.attr("transform",function(r){var i=e(r);return"translate("+(isFinite(i)?i:n(r))+",0)"})}function ac(t,e,n){t.attr("transform",function(r){var i=e(r);return"translate(0,"+(isFinite(i)?i:n(r))+")"})}o.svg.brush=function(){var t=Ce(f,"brushstart","brush","brushend"),e=null,n=null,r=[0,0],i=[0,0],a,l,s=!0,u=!0,c=ua[0];function f(m){m.each(function(){var _=o.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",A).on("touchstart.brush",A),y=_.selectAll(".background").data([0]);y.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),_.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var F=_.selectAll(".resize").data(c,ie);F.exit().remove(),F.enter().append("g").attr("class",function(Y){return"resize "+Y}).style("cursor",function(Y){return oc[Y]}).append("rect").attr("x",function(Y){return/[ew]$/.test(Y)?-3:null}).attr("y",function(Y){return/^[ns]/.test(Y)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),F.style("display",f.empty()?"none":null);var b=o.transition(_),P=o.transition(y),W;e&&(W=Qr(e),P.attr("x",W[0]).attr("width",W[1]-W[0]),d(b)),n&&(W=Qr(n),P.attr("y",W[0]).attr("height",W[1]-W[0]),x(b)),g(b)})}f.event=function(m){m.each(function(){var _=t.of(this,arguments),y={x:r,y:i,i:a,j:l},F=this.__chart__||y;this.__chart__=y,Bn?o.select(this).transition().each("start.brush",function(){a=F.i,l=F.j,r=F.x,i=F.y,_({type:"brushstart"})}).tween("brush:brush",function(){var b=Jr(r,y.x),P=Jr(i,y.y);return a=l=null,function(W){r=y.x=b(W),i=y.y=P(W),_({type:"brush",mode:"resize"})}}).each("end.brush",function(){a=y.i,l=y.j,_({type:"brush",mode:"resize"}),_({type:"brushend"})}):(_({type:"brushstart"}),_({type:"brush",mode:"resize"}),_({type:"brushend"}))})};function g(m){m.selectAll(".resize").attr("transform",function(_){return"translate("+r[+/e$/.test(_)]+","+i[+/^s/.test(_)]+")"})}function d(m){m.select(".extent").attr("x",r[0]),m.selectAll(".extent,.n>rect,.s>rect").attr("width",r[1]-r[0])}function x(m){m.select(".extent").attr("y",i[0]),m.selectAll(".extent,.e>rect,.w>rect").attr("height",i[1]-i[0])}function A(){var m=this,_=o.select(o.event.target),y=t.of(m,arguments),F=o.select(m),b=_.datum(),P=!/^(n|s)$/.test(b)&&e,W=!/^(e|w)$/.test(b)&&n,Y=_.classed("extent"),H=lt(m),V,st=o.mouse(m),gt,At=o.select(B(m)).on("keydown.brush",tt).on("keyup.brush",ft);if(o.event.changedTouches?At.on("touchmove.brush",yt).on("touchend.brush",mt):At.on("mousemove.brush",yt).on("mouseup.brush",mt),F.interrupt().selectAll("*").interrupt(),Y)st[0]=r[0]-st[0],st[1]=i[0]-st[1];else if(b){var xt=+/w$/.test(b),Ct=+/^n/.test(b);gt=[r[1-xt]-st[0],i[1-Ct]-st[1]],st[0]=r[xt],st[1]=i[Ct]}else o.event.altKey&&(V=st.slice());F.style("pointer-events","none").selectAll(".resize").style("display",null),o.select("body").style("cursor",_.style("cursor")),y({type:"brushstart"}),yt();function tt(){o.event.keyCode==32&&(Y||(V=null,st[0]-=r[1],st[1]-=i[1],Y=2),Qt())}function ft(){o.event.keyCode==32&&Y==2&&(st[0]+=r[1],st[1]+=i[1],Y=0,Qt())}function yt(){var Dt=o.mouse(m),Ht=!1;gt&&(Dt[0]+=gt[0],Dt[1]+=gt[1]),Y||(o.event.altKey?(V||(V=[(r[0]+r[1])/2,(i[0]+i[1])/2]),st[0]=r[+(Dt[0]1?{floor:function(g){for(;f(g=a.floor(g));)g=Dn(g-1);return g},ceil:function(g){for(;f(g=a.ceil(g));)g=Dn(+g+1);return g}}:a))},r.ticks=function(a,l){var s=Jn(r.domain()),u=a==null?i(s,10):typeof a=="number"?i(s,a):!a.range&&[{range:a},l];return u&&(a=u[0],l=u[1]),a.range(s[0],Dn(+s[1]+1),l<1?1:l)},r.tickFormat=function(){return n},r.copy=function(){return ha(t.copy(),e,n)},Ji(r,t)}function Dn(t){return new Date(t)}var ci=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],ga=[[It.second,1],[It.second,5],[It.second,15],[It.second,30],[It.minute,1],[It.minute,5],[It.minute,15],[It.minute,30],[It.hour,1],[It.hour,3],[It.hour,6],[It.hour,12],[It.day,1],[It.day,2],[It.week,1],[It.month,1],[It.month,3],[It.year,1]],sc=ca.multi([[".%L",function(t){return t.getMilliseconds()}],[":%S",function(t){return t.getSeconds()}],["%I:%M",function(t){return t.getMinutes()}],["%I %p",function(t){return t.getHours()}],["%a %d",function(t){return t.getDay()&&t.getDate()!=1}],["%b %d",function(t){return t.getDate()!=1}],["%B",function(t){return t.getMonth()}],["%Y",rr]]),lc={range:function(t,e,n){return o.range(Math.ceil(t/n)*n,+e,n).map(Dn)},floor:ie,ceil:ie};ga.year=It.year,It.scale=function(){return ha(o.scale.linear(),ga,sc)};var bs=ga.map(function(t){return[t[0].utc,t[1]]}),uc=vs.multi([[".%L",function(t){return t.getUTCMilliseconds()}],[":%S",function(t){return t.getUTCSeconds()}],["%I:%M",function(t){return t.getUTCMinutes()}],["%I %p",function(t){return t.getUTCHours()}],["%a %d",function(t){return t.getUTCDay()&&t.getUTCDate()!=1}],["%b %d",function(t){return t.getUTCDate()!=1}],["%B",function(t){return t.getUTCMonth()}],["%Y",rr]]);bs.year=It.year.utc,It.scale.utc=function(){return ha(o.scale.linear(),bs,uc)},o.text=vi(function(t){return t.responseText}),o.json=function(t,e){return wr(t,"application/json",cc,e)};function cc(t){return JSON.parse(t.responseText)}o.html=function(t,e){return wr(t,"text/html",fc,e)};function fc(t){var e=v.createRange();return e.selectNode(v.body),e.createContextualFragment(t.responseText)}return o.xml=vi(function(t){return t.responseXML}),o};const pt=window.E0DD32CBDCB63F();let gi=1;function dc(p){const o="<",w=">",I=`\r + >/= `;let k=0;function N(){const C=[];for(;p[k];){if(p.charCodeAt(k)===60){if(p.charCodeAt(k+1)===47)return k=p.indexOf(w,k),C;if(p.charCodeAt(k+1)===33){if(p.charCodeAt(k+2)===45){for(;!(p.charCodeAt(k)===62&&p.charCodeAt(k-1)===45&&p.charCodeAt(k-2)===45&&k!==-1);)k=p.indexOf(w,k+1);k===-1&&(k=p.length)}else for(k+=2;p.charCodeAt(k)!==62;k++);k++;continue}else if(p.charCodeAt(k+1)===63){k=p.indexOf(w,k),k++;continue}k++;let q=k;for(;I.indexOf(p[k])===-1;k++);const G=p.slice(q,k);let et=!1,rt={};for(;p.charCodeAt(k)!==62;k++){const Ft=p.charCodeAt(k);if(Ft>64&&Ft<91||Ft>96&&Ft<123){for(q=k;I.indexOf(p[k])===-1;k++);const dt=p.slice(q,k);let ut=p.charCodeAt(k);for(;ut!==39&&ut!==34;)k++,ut=p.charCodeAt(k);const Mt=p[k],Gt=++k;k=p.indexOf(Mt,Gt);const Nt=p.slice(Gt,k);et||(rt={},et=!0),rt[dt]=Nt}}let vt;p.charCodeAt(k-1)!==47&&(k++,vt=N()),C.push({children:vt,tagName:G,attrs:rt})}else{const q=k;k=p.indexOf(o,k)-1,k===-2&&(k=p.length);const G=p.slice(q,k+1);G.trim().length>0&&C.push(G)}k++}return C}return gi=1,ks(N())}function ks(p){const o={};if(p===void 0)return{};if(p.length===1&&(typeof p[0]=="string"||p[0]instanceof String))return new String(p[0]);p.forEach(function(h){if(typeof h!="string"&&(o[h.tagName]||(o[h.tagName]=[])),typeof h=="object"){const w=ks(h.children);h.attrs&&(w.attrs=h.attrs),w.attrs===void 0?w.attrs={order:gi}:w.attrs.order=gi,gi++,o[h.tagName].push(w)}});for(const h in o)o[h].length===1&&(o[h]=o[h][0]);return o}function pa(p){const o=new Uint8Array(p);let h="";for(let w=0;w{switch(S.type){case"processPPTX":{try{await D(S.data)}catch(O){console.error("AN ERROR HAPPENED DURING processPPTX",O),o({type:"ERROR",data:O.toString()})}break}}});async function D(S){var O;const j=await(await gc(()=>import("./jszip.min-BIf20mgf.BsDI-Ugu.js"),__vite__mapDeps([0,1])).then(ct=>ct.j)).loadAsync(S),U=Date.now();if(j.file("docProps/thumbnail.jpeg")){const ct=await((O=j.file("docProps/thumbnail.jpeg"))==null?void 0:O.async("base64"));o({type:"pptx-thumb",data:ct})}const J=await M(j),at=await I(j);v=await k(j),T=await R(j,"ppt/tableStyles.xml"),o({type:"slideSize",data:at});const lt=J.slides.length;for(let ct=0;ct";for(const Pt in Xt)if(Xt[Pt].constructor===Array)for(let ye=0;ye"}function C(S){const O=Object.keys(S),E=S[O[0]]["p:cSld"]["p:spTree"],j={},U={},J={};for(const at in E){if(at==="p:nvGrpSpPr"||at==="p:grpSpPr")continue;const lt=E[at];if(lt.constructor===Array)for(let ot=0;ot";for(const K in S)if(S[K].constructor===Array)for(let Lt=0;Lt",it+="",Xt=await Ut(S,!0,ot);const Rt=re(Z(S,["p:spPr"]));if(Rt==="GRADIENT_FILL"){Jt=!0;const Bt=Xt.color,oe=Xt.rot,Pt=di($.toString(),X.toString(),oe,Bt,K);it+=Pt}else if(Rt==="PIC_FILL"){te=!0;const Bt=$e(Xt,K);it+=Bt}if(ht=be(S,!0),Yt=Z(S,["p:spPr","a:ln","a:headEnd","attrs"]),Wt=Z(S,["p:spPr","a:ln","a:tailEnd","attrs"]),Yt!==void 0&&(Yt.type==="triangle"||Yt.type==="arrow")||Wt!==void 0&&(Wt.type==="triangle"||Wt.type==="arrow")){const Bt="";it+=Bt}it+=""}if(Lt!==void 0&&bt===void 0){switch(Lt){case"accentBorderCallout1":case"accentBorderCallout2":case"accentBorderCallout3":case"accentCallout1":case"accentCallout2":case"accentCallout3":case"actionButtonBackPrevious":case"actionButtonBeginning":case"actionButtonBlank":case"actionButtonDocument":case"actionButtonEnd":case"actionButtonForwardNext":case"actionButtonHelp":case"actionButtonHome":case"actionButtonInformation":case"actionButtonMovie":case"actionButtonReturn":case"actionButtonSound":case"arc":case"bevel":case"blockArc":case"borderCallout1":case"borderCallout2":case"borderCallout3":case"bracePair":case"bracketPair":case"callout1":case"callout2":case"callout3":case"can":case"chartPlus":case"chartStar":case"chartX":case"chevron":case"chord":case"cloud":case"cloudCallout":case"corner":case"cornerTabs":case"cube":case"diagStripe":case"donut":case"doubleWave":case"downArrowCallout":case"ellipseRibbon":case"ellipseRibbon2":case"flowChartAlternateProcess":case"flowChartCollate":case"flowChartConnector":case"flowChartDecision":case"flowChartDelay":case"flowChartDisplay":case"flowChartDocument":case"flowChartExtract":case"flowChartInputOutput":case"flowChartInternalStorage":case"flowChartMagneticDisk":case"flowChartMagneticDrum":case"flowChartMagneticTape":case"flowChartManualInput":case"flowChartManualOperation":case"flowChartMerge":case"flowChartMultidocument":case"flowChartOfflineStorage":case"flowChartOffpageConnector":case"flowChartOnlineStorage":case"flowChartOr":case"flowChartPredefinedProcess":case"flowChartPreparation":case"flowChartProcess":case"flowChartPunchedCard":case"flowChartPunchedTape":case"flowChartSort":case"flowChartSummingJunction":case"flowChartTerminator":case"folderCorner":case"frame":case"funnel":case"gear6":case"gear9":case"halfFrame":case"heart":case"homePlate":case"horizontalScroll":case"irregularSeal1":case"irregularSeal2":case"leftArrowCallout":case"leftBrace":case"leftBracket":case"leftRightArrowCallout":case"leftRightRibbon":case"lightningBolt":case"lineInv":case"mathDivide":case"mathEqual":case"mathMinus":case"mathMultiply":case"mathNotEqual":case"mathPlus":case"moon":case"nonIsoscelesTrapezoid":case"noSmoking":case"pie":case"pieWedge":case"plaque":case"plaqueTabs":case"quadArrowCallout":case"rect":case"ribbon":case"ribbon2":case"rightArrowCallout":case"rightBrace":case"rightBracket":case"round1Rect":case"round2DiagRect":case"round2SameRect":case"smileyFace":case"snip1Rect":case"snip2DiagRect":case"snip2SameRect":case"snipRoundRect":case"squareTabs":case"star10":case"star12":case"star16":case"star24":case"star32":case"star4":case"star5":case"star6":case"star7":case"star8":case"sun":case"teardrop":case"upArrowCallout":case"upDownArrowCallout":case"verticalScroll":case"wave":case"wedgeEllipseCallout":case"wedgeRectCallout":case"wedgeRoundRectCallout":{it+="";break}case"ellipse":{it+="";break}case"roundRect":{it+="";break}case"bentConnector2":{let Tt;_t?Tt="M 0 "+$+" L "+X+" "+$+" L "+X+" 0":Tt="M "+$+" 0 L "+$+" "+X+" L 0 "+X,it+="";break}case"triangle":{const Tt=Z(S,["p:spPr","a:prstGeom","a:avLst","a:gd","attrs","fmla"]);let Rt=.5;Tt!==void 0&&(Rt=parseInt(Tt.substr(4))*96/9144e3),it+=" ";break}case"diamond":{it+=" ";break}case"trapezoid":{const Tt=Z(S,["p:spPr","a:prstGeom","a:avLst","a:gd","attrs","fmla"]);let Rt=.25;Tt!==void 0&&(Rt=parseInt(Tt.substr(4))*96/9144e3*.5/.7407),it+=" ";break}case"parallelogram":{const Tt=Z(S,["p:spPr","a:prstGeom","a:avLst","a:gd","attrs","fmla"]);let Rt=.25,Bt;$>X?Bt=$/X:Bt=X/$,Tt!==void 0&&(Rt=parseInt(Tt.substr(4))/1e5/Bt),it+=" ";break}case"pentagon":{it+=" ";break}case"hexagon":{const Tt=Z(S,["p:spPr","a:prstGeom","a:avLst","a:gd"])||[];let Rt;for(let Pt=0;Pt";break}case"heptagon":{it+=" ";break}case"octagon":{const Tt=Z(S,["p:spPr","a:prstGeom","a:avLst","a:gd","attrs","fmla"]);let Rt=.25;Tt!==void 0&&(Rt=parseInt(Tt.substr(4))/1e5);const Bt=1-Rt;it+=" ";break}case"decagon":{it+=" ";break}case"dodecagon":{it+=" ";break}case"bentConnector3":{const Tt=Z(S,["p:spPr","a:prstGeom","a:avLst","a:gd","attrs","fmla"]);let Rt=.5;Tt!==void 0&&(Rt=parseInt(Tt.substr(4))/1e5,_t?it+=" ";break}case"line":case"straightConnector1":case"bentConnector4":case"bentConnector5":case"curvedConnector2":case"curvedConnector3":case"curvedConnector4":case"curvedConnector5":{_t?it+="";break}case"leftArrow":{const Tt=Z(S,["p:spPr","a:prstGeom","a:avLst","a:gd"]);let Rt,Bt=.5,oe,Pt=.5;const ye=$/X;if(Tt!==void 0)for(let Kt=0;Kt";break}case"downArrow":{const Tt=Z(S,["p:spPr","a:prstGeom","a:avLst","a:gd"]);let Rt,Bt=.5,oe,Pt=.5;const ye=X/$;if(Tt!==void 0)for(let Kt=0;Kt";break}case"upArrow":{const Tt=Z(S,["p:spPr","a:prstGeom","a:avLst","a:gd"]);let Rt,Bt=.5,oe,Pt=.5;const ye=X/$;if(Tt!==void 0)for(let Kt=0;Kt";break}case"leftRightArrow":{const Tt=Z(S,["p:spPr","a:prstGeom","a:avLst","a:gd"]);let Rt,Bt=.5,oe,Pt=.5;const ye=$/X;if(Tt!==void 0)for(let Kt=0;Kt";break}case"upDownArrow":{const Tt=Z(S,["p:spPr","a:prstGeom","a:avLst","a:gd"]);let Rt,Bt=.5,oe,Pt=.5;const ye=X/$;if(Tt!==void 0)for(let Kt=0;Kt";break}case"bentArrow":case"bentUpArrow":case"stripedRightArrow":case"quadArrow":case"circularArrow":case"swooshArrow":case"leftRightUpArrow":case"leftUpArrow":case"leftCircularArrow":case"notchedRightArrow":case"curvedDownArrow":case"curvedLeftArrow":case"curvedRightArrow":case"curvedUpArrow":case"uturnArrow":case"leftRightCircularArrow":break;case void 0:default:console.warn("Undefine shape type.")}it+="",it+="
",S["p:txBody"]!==void 0&&(it+=await ut(S["p:txBody"],O,E,at,ot)),it+="
"}else if(bt!==void 0){const Tt=Z(bt,["a:pathLst"]),Rt=Z(Tt,["a:path","a:close"]),Bt=Z(Tt,["a:path","a:moveTo","a:pt","attrs"])||{x:"0",y:"0"},oe=parseInt(Bt.x)*96/914400,Pt=parseInt(Bt.y)*96/914400;let ye="M"+oe+","+Pt;const Kt=Z(Tt,["a:path"]),he=Kt["a:lnTo"],je=Kt["a:cubicBezTo"],Mn=[];he!==void 0&&Object.keys(he).forEach(function(Ge){const xe=he[Ge]["a:pt"];xe!==void 0&&Object.keys(xe).forEach(function(rn){const Ve={},an=xe[rn],Ue=an.x,fn=an.y,jn=an.order;Ve.type="lnto",Ve.order=jn,Ve.x=Ue,Ve.y=fn,Mn.push(Ve)})}),je!==void 0&&Object.keys(je).forEach(function(Ge){const xe=je[Ge]["a:pt"];xe!==void 0&&Object.keys(xe).forEach(function(rn){const Ve=xe[rn];Object.keys(Ve).forEach(function(an){const Ue={},fn=Ve[an],jn=fn.x,yr=fn.y,tr=fn.order;Ue.type="cubicBezTo",Ue.order=tr,Ue.x=jn,Ue.y=yr,Mn.push(Ue)})})});const ke=Mn.slice(0);ke.sort(function(Ge,xe){return Ge.order-xe.order});let Ne=0;for(;Ne",S["p:txBody"]!==void 0&&(it+=await ut(S["p:txBody"],O,E,at,ot)),it+=""}else it+="
",S["p:txBody"]!==void 0&&(it+=await ut(S["p:txBody"],O,E,at="",ot)),it+="
";return it}async function Ft(S,O){const E=S.attrs.order,j=S["p:blipFill"]["a:blip"].attrs["r:embed"],U=O.slideResObj[j].target,J=pc(U).toLowerCase(),lt=await O.zip.file(U).async("arraybuffer");let ot="";const ct=S["p:spPr"]["a:xfrm"],kt=He(S["p:spPr"]["a:xfrm"].attrs.rot);return ot=On(J),"
"}async function dt(S,O){let E="";switch(Z(S,["a:graphic","a:graphicData","attrs","uri"])){case"http://schemas.openxmlformats.org/drawingml/2006/table":E=await qt(S,O);break;case"http://schemas.openxmlformats.org/drawingml/2006/chart":E=await ce(S,O);break;case"http://schemas.openxmlformats.org/drawingml/2006/diagram":E=$t(S);break}return E}async function ut(S,O,E,j,U){let J="";const at=U&&U.slideMasterTextStyles;if(S===void 0)return J;let lt,ot;if(S["a:p"].constructor===Array)for(let ct=0;ct",J+=await Mt(lt,O,E,j,U||{}),ot===void 0)J+=Gt(lt,O,E,j,U||{});else if(ot.constructor===Array)for(let kt=0;kt"}else{if(lt=S["a:p"],ot=lt["a:r"],J+="
",J+=await Mt(lt,O,E,j,U),ot===void 0)J+=Gt(lt,O,E,j,U||{});else if(ot.constructor===Array)for(let ct=0;ct"}return J}async function Mt(S,O,E,j,U){const J=U&&U.slideMasterTextStyles,at=S["a:r"];let lt,ot,ct,kt;at!==void 0?(lt=ge(at),ot=ve(at,O,E,j,J)):(lt=ge(S),ot=ve(S,O,E,j,J));let Q="";const jt=S["a:pPr"],it=Z(jt,["attrs","rtl"]);let K=!1;it!==void 0&&it==="1"&&(K=!0);let Lt=parseInt(Z(jt,["attrs","lvl"]));isNaN(Lt)&&(Lt=0);const bt=Z(jt,["a:buChar","attrs","char"]);let _t="TYPE_NONE";const zt=Z(jt,["a:buAutoNum","attrs","type"]),$=Z(jt,["a:buBlip"]);bt!==void 0&&(_t="TYPE_BULLET"),zt!==void 0&&(_t="TYPE_NUMERIC"),$!==void 0&&(_t="TYPE_BULPIC");let X={};_t!=="TYPE_NONE"&&(X=Z(jt,["a:buFont","attrs"]));let ht="NoNe";if(jt){const Jt=jt["a:buClr"];Jt!==void 0&&(ht=Vt(Jt)||"")}ht==="NoNe"?ct=lt:ct="#"+ht;let Yt;if(Yt=Z(jt,["a:buSzPts","attrs","val"]),Yt!==void 0)kt=parseInt(Yt)/100+"pt";else if(Yt=Z(jt,["a:buSzPct","attrs","val"]),Yt!==void 0){const Jt=parseInt(Yt)/1e5,te=ot.substr(0,ot.length-2);kt=Jt*parseInt(te)+"pt"}else kt=ot;let Wt,Xt;if(_t==="TYPE_BULLET")X!==void 0?(Wt=parseInt(Z(jt,["attrs","marL"]))*96/914400,Xt=parseInt(X.pitchFamily),isNaN(Wt)&&(Wt=328600*96/914400),isNaN(Xt)&&(Xt=0),Q=""+bt+""):(Wt=328600*96/914400*Lt,Q=""+bt+"");else if(_t==="TYPE_NUMERIC")X!==void 0?(Wt=parseInt(Z(jt,["attrs","marL"]))*96/914400,Xt=parseInt(X.pitchFamily),isNaN(Wt)&&(Wt=328600*96/914400),isNaN(Xt)&&(Xt=0),Q=""):(Wt=328600*96/914400*Lt,Q="");else if(_t==="TYPE_BULPIC"){Wt=parseInt(Z(jt,["attrs","marL"]))*96/914400,Xt=parseInt(Z(jt,["attrs","marR"]))*96/914400,isNaN(Xt)&&(Xt=0),isNaN(Wt)?Wt=328600*96/914400:Wt=0;const Jt=Z($,["a:blip","attrs","r:embed"]);let te;if(Jt!==void 0){const Tt=U&&U.slideResObj[Jt].target,Rt=U&&await U.zip.file(Tt).async("arraybuffer"),Bt=Tt.split(".").pop();te=""}Jt===void 0&&(te="‣"),Q=""+te+" "}else Q="";return Q}function Gt(S,O,E,j,U){const J=U.slideMasterTextStyles;let at=S["a:t"];typeof at!="string"&&!(at instanceof String)&&(at=Z(S,["a:fld","a:t"]),typeof at!="string"&&!(at instanceof String)&&(at=" "));let lt="color:"+ge(S)+";font-size:"+ve(S,O,E,j,J)+";font-family:"+en(S,j)+";font-weight:"+ue(S)+";font-style:"+St(S)+";text-decoration:"+ae(S)+";text-align:"+Qt(S)+";vertical-align:"+me(S)+";";const ot=Z(S,["a:rPr","a:highlight"]);ot!==void 0&&(lt+="background-color:#"+Vt(ot)+";",lt+="Opacity:"+Se(ot)+";");let ct="";lt in B?ct=B[lt].name:(ct="_css_"+(Object.keys(B).length+1),B[lt]={name:ct,text:lt});const kt=Z(S,["a:rPr","a:hlinkClick","attrs","r:id"]);if(kt!==void 0){const Q=U.slideResObj[kt].target;return""+at.replace(/\s/," ")+""}else return""+at.replace(/\s/," ")+""}function Nt(){let S="";for(const O in B)S+="section ."+B[O].name+"{"+B[O].text+`} +`;return S}async function qt(S,O){const E=S.attrs.order,j=Z(S,["a:graphic","a:graphicData","a:tbl"]),U=Z(S,["p:xfrm"]),J=Z(S,["a:graphic","a:graphicData","a:tbl","a:tblPr"]),at=Z(S,["a:graphic","a:graphicData","a:tbl","a:tblGrid","a:gridCol"]);let lt="";J!==void 0&&(lt=J.attrs.rtl===1?"dir=rtl":"dir=ltr");const ot=J.attrs.firstRow,ct=J.attrs.bandRow;let kt="";const Q=j["a:tr"];if(Q.constructor===Array)for(let jt=0;jt0&&ct!==void 0){let $="fff",X=1;if(jt%2===0){if(bt["a:band2H"]!==void 0){const ht=Z(bt,["a:band2H","a:tcStyle","a:fill","a:solidFill"]);ht!==void 0&&($=Vt(ht),X=Se(ht));const Yt=Z(bt,["a:band2H","a:tcStyle","a:tcBdr"]);if(Yt!==void 0){const Wt=Ce(Yt);Lt+=Wt}Z(bt,["a:band2H","a:tcTxStyle"])}}else if(bt["a:band1H"]!==void 0){const ht=Z(bt,["a:band1H","a:tcStyle","a:fill","a:solidFill"]);ht!==void 0&&($=Vt(ht),X=Se(ht));const Yt=Z(bt,["a:band1H","a:tcStyle","a:tcBdr"]);if(Yt!==void 0){const Wt=Ce(Yt);Lt+=Wt}Z(bt,["a:band1H","a:tcTxStyle"])}Lt+=" background-color:#"+$+"; opacity:"+X+";"}kt+="";const zt=Q[jt]["a:tc"];if(zt.constructor===Array)for(let $=0;$"+X+"":Yt!==void 0?kt+="":Wt===void 0&&Xt===void 0&&(kt+="")}else{const $=await ut(zt["a:txBody"]),X=at[0].attrs.w;let ht="";if(X!==void 0){const Jt=parseInt(X)*96/914400;ht+="width:"+Jt+"px;"}const Yt=zt["a:tcPr"]["a:solidFill"];let Wt="",Xt=1;Yt!==void 0&&(Wt=Vt(Yt),Xt=Se(Yt)),Wt!==""&&(ht+=" background-color:#"+Wt+";",ht+=" opacity"+Xt+";"),kt+=""}kt+=""}else{const jt=Q.attrs.h;let it=0;jt!==void 0?(it=parseInt(jt)*96/914400,kt+=""):kt+="";const K=Q["a:tc"];if(K.constructor===Array)for(let Lt=0;Lt"+bt+""}else{const Lt=await ut(K["a:txBody"]),bt=at[0].attrs.w;let _t="";if(bt!==void 0){const ht=parseInt(bt)*96/914400;_t+="width:"+ht+"px;"}const zt=K["a:tcPr"]["a:solidFill"];let $="",X=1;zt!==void 0&&($=Vt(zt),X=Se(zt)),$!==""&&(_t+=" background-color:#"+$+";",_t+=" opacity"+X+";"),kt+=""}kt+=""}return kt}async function ce(S,O){const E=S.attrs.order,j=Z(S,["p:xfrm"]),U="
",J=S["a:graphic"]["a:graphicData"]["c:chart"].attrs["r:id"],at=O.slideResObj[J].target,lt=await R(O.zip,at),ot=Z(lt,["c:chartSpace","c:chart","c:plotArea"]);let ct=null;for(const kt in ot)switch(kt){case"c:lineChart":ct={type:"createChart",data:{chartID:"chart"+w,chartType:"lineChart",chartData:nn(ot[kt]["c:ser"])}};break;case"c:barChart":ct={type:"createChart",data:{chartID:"chart"+w,chartType:"barChart",chartData:nn(ot[kt]["c:ser"])}};break;case"c:pieChart":ct={type:"createChart",data:{chartID:"chart"+w,chartType:"pieChart",chartData:nn(ot[kt]["c:ser"])}};break;case"c:pie3DChart":ct={type:"createChart",data:{chartID:"chart"+w,chartType:"pie3DChart",chartData:nn(ot[kt]["c:ser"])}};break;case"c:areaChart":ct={type:"createChart",data:{chartID:"chart"+w,chartType:"areaChart",chartData:nn(ot[kt]["c:ser"])}};break;case"c:scatterChart":ct={type:"createChart",data:{chartID:"chart"+w,chartType:"scatterChart",chartData:nn(ot[kt]["c:ser"])}};break}return ct!=null&&h.push(ct),w++,U}function $t(S){const O=Z(S,["p:xfrm"]);return"
TODO: diagram
"}function Et(S,O,E){let j,U=-1,J=-1;return S!==void 0?j=S["a:off"].attrs:O!==void 0?j=O["a:off"].attrs:E!==void 0&&(j=E["a:off"].attrs),j===void 0?"":(U=parseInt(j.x)*96/914400,J=parseInt(j.y)*96/914400,isNaN(U)||isNaN(J)?"":"top:"+J+"px; left:"+U+"px;")}function ee(S,O,E){let j,U=-1,J=-1;return S!==void 0?j=S["a:ext"].attrs:O!==void 0?j=O["a:ext"].attrs:E!==void 0&&(j=E["a:ext"].attrs),j===void 0?"":(U=parseInt(j.cx)*96/914400,J=parseInt(j.cy)*96/914400,isNaN(U)||isNaN(J)?"":"width:"+U+"px; height:"+J+"px;")}function le(S,O,E,j,U){let J=Z(S,["a:pPr","attrs","algn"]);if(J===void 0&&(J=Z(O,["p:txBody","a:p","a:pPr","attrs","algn"]),J===void 0&&(J=Z(E,["p:txBody","a:p","a:pPr","attrs","algn"]),J===void 0)))switch(j){case"title":case"subTitle":case"ctrTitle":{J=Z(U,["p:titleStyle","a:lvl1pPr","attrs","alng"]);break}default:J=Z(U,["p:otherStyle","a:lvl1pPr","attrs","alng"])}if(J===void 0){if(j==="title"||j==="subTitle"||j==="ctrTitle")return"h-mid";if(j==="sldNum")return"h-right"}return J==="ctr"?"h-mid":J==="r"?"h-right":"h-left"}function ie(S,O,E,j,U){let J=Z(S,["p:txBody","a:bodyPr","attrs","anchor"]);return J===void 0&&(J=Z(O,["p:txBody","a:bodyPr","attrs","anchor"]),J===void 0&&(J=Z(E,["p:txBody","a:bodyPr","attrs","anchor"]))),J==="ctr"?"v-mid":J==="b"?"v-down":"v-up"}function en(S,O,E){let j=Z(S,["a:rPr","a:latin","attrs","typeface"]);if(j===void 0){const U=Z(v,["a:theme","a:themeElements","a:fontScheme"]);O==="title"||O==="subTitle"||O==="ctrTitle"?j=Z(U,["a:majorFont","a:latin","attrs","typeface"]):O==="body"?j=Z(U,["a:minorFont","a:latin","attrs","typeface"]):j=Z(U,["a:minorFont","a:latin","attrs","typeface"])}return j===void 0?"inherit":j}function ge(S,O,E){const j=Rn(S,"a:rPr a:solidFill"),U=Vt(j);return U===void 0||U==="FFF"?"#000":"#"+U}function ve(S,O,E,j,U){let J=16,at="";return S["a:rPr"]!==void 0&&(J=parseInt(S["a:rPr"].attrs.sz)/100),(isNaN(J)||J===void 0)&&(at=Z(O,["p:txBody","a:lstStyle","a:lvl1pPr","a:defRPr","attrs","sz"]),J=parseInt(at)/100),(isNaN(J)||J===void 0)&&(j==="title"||j==="subTitle"||j==="ctrTitle"?at=Z(U,["p:titleStyle","a:lvl1pPr","a:defRPr","attrs","sz"]):j==="body"?at=Z(U,["p:bodyStyle","a:lvl1pPr","a:defRPr","attrs","sz"]):j==="dt"||j==="sldNum"?at="1200":j===void 0&&(at=Z(U,["p:otherStyle","a:lvl1pPr","a:defRPr","attrs","sz"])),J=parseInt(at)/100),Z(S,["a:rPr","attrs","baseline"])!==void 0&&!isNaN(J)&&(J-=10),isNaN(J)?"inherit":J+"pt"}function ue(S,O,E){return S["a:rPr"]!==void 0&&S["a:rPr"].attrs.b==="1"?"bold":"initial"}function St(S,O,E){return S["a:rPr"]!==void 0&&S["a:rPr"].attrs.i==="1"?"italic":"normal"}function ae(S,O,E){if(S["a:rPr"]!==void 0){const j=S["a:rPr"].attrs.u!==void 0?S["a:rPr"].attrs.u:"none",U=S["a:rPr"].attrs.strike!==void 0?S["a:rPr"].attrs.strike:"noStrike";return j!=="none"&&U==="noStrike"?"underline":j==="none"&&U!=="noStrike"?"line-through":j!=="none"&&U!=="noStrike"?"underline line-through":"initial"}else return"initial"}function Qt(S,O,E){const j=Z(S,["a:pPr","attrs","algn"]);let U="initial";if(j!==void 0)switch(j){case"l":{U="left";break}case"r":{U="right";break}case"ctr":{U="center";break}case"just":{U="justify";break}case"dist":{U="justify";break}default:U="initial"}return U}function me(S,O,E){const j=Z(S,["a:rPr","attrs","baseline"]);return j===void 0?"baseline":parseInt(j)/1e3+"%"}function Ce(S){let O="",E,j;return S["a:bottom"]!==void 0&&(E={"p:spPr":{"a:ln":S["a:bottom"]["a:ln"]}},j=be(E,!1),O+=j.replace("border","border-bottom")),S["a:top"]!==void 0&&(E={"p:spPr":{"a:ln":S["a:top"]["a:ln"]}},j=be(E,!1),O+=j.replace("border","border-top")),S["a:right"]!==void 0&&(E={"p:spPr":{"a:ln":S["a:right"]["a:ln"]}},j=be(E,!1),O+=j.replace("border","border-right")),S["a:left"]!==void 0&&(E={"p:spPr":{"a:ln":S["a:left"]["a:ln"]}},j=be(E,!1),O+=j.replace("border","border-left")),O}function be(S,O){let E="border: ";const j=S["p:spPr"]["a:ln"],U=parseInt(Z(j,["attrs","w"]))/12700;isNaN(U)||U<1?E+="1pt ":E+=U+"pt ";const J=Z(j,["a:prstDash","attrs","val"]);let at="0";switch(J){case"solid":{E+="solid",at="0";break}case"dash":{E+="dashed",at="5";break}case"dashDot":{E+="dashed",at="5, 5, 1, 5";break}case"dot":{E+="dotted",at="1, 5";break}case"lgDash":{E+="dashed",at="10, 5";break}case"lgDashDotDot":{E+="dashed",at="10, 5, 1, 5, 1, 5";break}case"sysDash":{E+="dashed",at="5, 2";break}case"sysDashDot":{E+="dashed",at="5, 2, 1, 5";break}case"sysDashDotDot":{E+="dashed",at="5, 2, 1, 5, 1, 5";break}case"sysDot":{E+="dotted",at="2, 5";break}default:E+="solid",at="0"}let lt=Z(j,["a:solidFill","a:srgbClr","attrs","val"]);if(lt===void 0){const ot=Z(j,["a:solidFill","a:schemeClr"]);if(ot!==void 0){const ct="a:"+Z(ot,["attrs","val"]);lt=Ae(ct,void 0)}}if(lt===void 0){const ot=Z(S,["p:style","a:lnRef","a:schemeClr"]);if(ot!==void 0){const ct="a:"+Z(ot,["attrs","val"]);lt=Ae(ct,void 0)}if(lt!==void 0){let ct=Z(ot,["a:shade","attrs","val"]);if(ct!==void 0){ct=(parseInt(ct)/1e5).toString();const kt=new da("#"+lt);kt.setLum(Number(kt.hsl.l)*Number(ct)),lt=kt.hex.replace("#","")}}}return lt===void 0?O?lt="none":lt="#000":lt="#"+lt,E+=" "+lt+" ",O?{color:lt,width:U,type:J,strokeDasharray:at}:E+";"}async function _e(S,O,E,j){let U=Z(S,["p:sld","p:cSld","p:bg","p:bgPr"]),J=Z(S,["p:sld","p:cSld","p:bg","p:bgRef"]),at;if(U!==void 0){const lt=re(U);if(lt==="SOLID_FILL"){const ot=U["a:solidFill"],ct=Vt(ot),kt=Se(ot);at="background: rgba("+wt(ct)+","+kt+");"}else if(lt==="GRADIENT_FILL"){const ot=U["a:gradFill"],ct=ot["a:gsLst"]["a:gs"],kt=[],Q=[];for(let K=0;K0&&ot<1e3)){if(ot>1e3){const ct=ot-1e3,kt=v["a:theme"]["a:themeElements"]["a:fmtScheme"]["a:bgFillStyleLst"],Q=[];Object.keys(kt).forEach(function(Lt){const bt=kt[Lt];if(Lt!=="attrs")if(bt.constructor===Array)for(let _t=0;_t0&&ot<1e3)){if(ot>1e3){const ct=ot-1e3,kt=v["a:theme"]["a:themeElements"]["a:fmtScheme"]["a:bgFillStyleLst"],Q=[];Object.keys(kt).forEach(function(Lt){const bt=kt[Lt];if(Lt!=="attrs")if(bt.constructor===Array)for(let _t=0;_t=6&&(E-=6),E<1?(O-S)*E+S:E<3?O:E<4?(O-S)*(4-E)+S:S}function Cn(S){let O;const E=["AliceBlue","AntiqueWhite","Aqua","Aquamarine","Azure","Beige","Bisque","Black","BlanchedAlmond","Blue","BlueViolet","Brown","BurlyWood","CadetBlue","Chartreuse","Chocolate","Coral","CornflowerBlue","Cornsilk","Crimson","Cyan","DarkBlue","DarkCyan","DarkGoldenRod","DarkGray","DarkGrey","DarkGreen","DarkKhaki","DarkMagenta","DarkOliveGreen","DarkOrange","DarkOrchid","DarkRed","DarkSalmon","DarkSeaGreen","DarkSlateBlue","DarkSlateGray","DarkSlateGrey","DarkTurquoise","DarkViolet","DeepPink","DeepSkyBlue","DimGray","DimGrey","DodgerBlue","FireBrick","FloralWhite","ForestGreen","Fuchsia","Gainsboro","GhostWhite","Gold","GoldenRod","Gray","Grey","Green","GreenYellow","HoneyDew","HotPink","IndianRed","Indigo","Ivory","Khaki","Lavender","LavenderBlush","LawnGreen","LemonChiffon","LightBlue","LightCoral","LightCyan","LightGoldenRodYellow","LightGray","LightGrey","LightGreen","LightPink","LightSalmon","LightSeaGreen","LightSkyBlue","LightSlateGray","LightSlateGrey","LightSteelBlue","LightYellow","Lime","LimeGreen","Linen","Magenta","Maroon","MediumAquaMarine","MediumBlue","MediumOrchid","MediumPurple","MediumSeaGreen","MediumSlateBlue","MediumSpringGreen","MediumTurquoise","MediumVioletRed","MidnightBlue","MintCream","MistyRose","Moccasin","NavajoWhite","Navy","OldLace","Olive","OliveDrab","Orange","OrangeRed","Orchid","PaleGoldenRod","PaleGreen","PaleTurquoise","PaleVioletRed","PapayaWhip","PeachPuff","Peru","Pink","Plum","PowderBlue","Purple","RebeccaPurple","Red","RosyBrown","RoyalBlue","SaddleBrown","Salmon","SandyBrown","SeaGreen","SeaShell","Sienna","Silver","SkyBlue","SlateBlue","SlateGray","SlateGrey","Snow","SpringGreen","SteelBlue","Tan","Teal","Thistle","Tomato","Turquoise","Violet","Wheat","White","WhiteSmoke","Yellow","YellowGreen"],j=["f0f8ff","faebd7","00ffff","7fffd4","f0ffff","f5f5dc","ffe4c4","000000","ffebcd","0000ff","8a2be2","a52a2a","deb887","5f9ea0","7fff00","d2691e","ff7f50","6495ed","fff8dc","dc143c","00ffff","00008b","008b8b","b8860b","a9a9a9","a9a9a9","006400","bdb76b","8b008b","556b2f","ff8c00","9932cc","8b0000","e9967a","8fbc8f","483d8b","2f4f4f","2f4f4f","00ced1","9400d3","ff1493","00bfff","696969","696969","1e90ff","b22222","fffaf0","228b22","ff00ff","dcdcdc","f8f8ff","ffd700","daa520","808080","808080","008000","adff2f","f0fff0","ff69b4","cd5c5c","4b0082","fffff0","f0e68c","e6e6fa","fff0f5","7cfc00","fffacd","add8e6","f08080","e0ffff","fafad2","d3d3d3","d3d3d3","90ee90","ffb6c1","ffa07a","20b2aa","87cefa","778899","778899","b0c4de","ffffe0","00ff00","32cd32","faf0e6","ff00ff","800000","66cdaa","0000cd","ba55d3","9370db","3cb371","7b68ee","00fa9a","48d1cc","c71585","191970","f5fffa","ffe4e1","ffe4b5","ffdead","000080","fdf5e6","808000","6b8e23","ffa500","ff4500","da70d6","eee8aa","98fb98","afeeee","db7093","ffefd5","ffdab9","cd853f","ffc0cb","dda0dd","b0e0e6","800080","663399","ff0000","bc8f8f","4169e1","8b4513","fa8072","f4a460","2e8b57","fff5ee","a0522d","c0c0c0","87ceeb","6a5acd","708090","708090","fffafa","00ff7f","4682b4","d2b48c","008080","d8bfd8","ff6347","40e0d0","ee82ee","f5deb3","ffffff","f5f5f5","ffff00","9acd32"],U=E.indexOf(S);return U!==-1&&(O=j[U]),O}function Se(S){if(S===void 0)return;let O=1;if(S["a:srgbClr"]!==void 0){const E=Z(S,["a:srgbClr","a:tint","attrs","val"]);E!==void 0&&(O=parseInt(E)/1e5)}else if(S["a:schemeClr"]!==void 0){const E=Z(S,["a:schemeClr","a:tint","attrs","val"]);E!==void 0&&(O=parseInt(E)/1e5)}else if(S["a:scrgbClr"]!==void 0){const E=Z(S,["a:scrgbClr","a:tint","attrs","val"]);E!==void 0&&(O=parseInt(E)/1e5)}else if(S["a:prstClr"]!==void 0){const E=Z(S,["a:prstClr","a:tint","attrs","val"]);E!==void 0&&(O=parseInt(E)/1e5)}else if(S["a:hslClr"]!==void 0){const E=Z(S,["a:hslClr","a:tint","attrs","val"]);E!==void 0&&(O=parseInt(E)/1e5)}else if(S["a:sysClr"]!==void 0){const E=Z(S,["a:sysClr","a:tint","attrs","val"]);E!==void 0&&(O=parseInt(E)/1e5)}return O}function Ae(S,O){(z===""||z===void 0)&&(z=Z(O,["p:sldMaster","p:clrMap","attrs"])||{});const E=S.substr(2);switch(E){case"tx1":case"tx2":case"bg1":case"bg2":{S="a:"+z[E.toString()];break}}const j=Z(v,["a:theme","a:themeElements","a:clrScheme",S]);let U=Z(j,["a:srgbClr","attrs","val"]);return U===void 0&&(U=Z(j,["a:sysClr","attrs","lastClr"])),U}function nn(S){const O=[];if(S===void 0)return O;if(S["c:xVal"]!==void 0){let E=[];cn(S["c:xVal"]["c:numRef"]["c:numCache"]["c:pt"],function(j,U){return E.push(parseFloat(j["c:v"])),""}),O.push(E),E=[],cn(S["c:yVal"]["c:numRef"]["c:numCache"]["c:pt"],function(j,U){return E.push(parseFloat(j["c:v"])),""}),O.push(E)}else cn(S,function(E,j){const U=[],J=Z(E,["c:tx","c:strRef","c:strCache","c:pt","c:v"])||j,at={};return Z(E,["c:cat","c:strRef","c:strCache","c:pt"])!==void 0?cn(E["c:cat"]["c:strRef"]["c:strCache"]["c:pt"],function(lt,ot){return at[lt.attrs.idx]=lt["c:v"],""}):Z(E,["c:cat","c:numRef","c:numCache","c:pt"])!==void 0&&cn(E["c:cat"]["c:numRef"]["c:numCache"]["c:pt"],function(lt,ot){return at[lt.attrs.idx]=lt["c:v"],""}),Z(E,["c:val","c:numRef","c:numCache","c:pt"])!==void 0&&cn(E["c:val"]["c:numRef"]["c:numCache"]["c:pt"],function(lt,ot){return U.push({x:lt.attrs.idx,y:parseFloat(lt["c:v"])}),""}),O.push({key:J,values:U,xlabels:at}),""});return O}function Rn(S,O){return Z(S,O.trim().split(/\s+/))}function Z(S,O){if(O.constructor!==Array)throw Error("Error of path type! path is not array.");if(S===void 0)return;const E=O.length;for(let j=0;j +`;for(let Lt=0;Lt +`;return K+=` +`,K}function Ze(S){const O=["0%","100%"];if(S===0)return!0;{let E=S;for(;E--;){const U=100-100/(S+1)*(E+1)+"%";O.splice(-1,0,U)}}return O}function _r(S,O,E){const j=parseFloat(E),U=parseFloat(O),J=parseFloat(S);let at=2,lt=2;const ot=j/2,ct=U/2;let kt=2,Q=2,jt=2,it=2;const K=(J%360+360)%360,Lt=(360-K)*Math.PI/180,bt=Math.tan(Lt),_t=ct-bt*ot;K===0?(kt=j,Q=ct,jt=0,it=ct):K<90?(lt=j,at=0):K===90?(kt=ot,Q=0,jt=ot,it=U):K<180?(lt=0,at=0):K===180?(kt=0,Q=ct,jt=j,it=ct):K<270?(lt=0,at=U):K===270?(kt=ot,Q=U,jt=ot,it=0):(lt=j,at=U);const zt=at+lt/bt;kt=kt===2?bt*(zt-_t)/(Math.pow(bt,2)+1):kt,Q=Q===2?bt*kt+_t:Q,jt=jt===2?j-kt:jt,it=it===2?U-Q:it;const $=Math.round(jt/j*100*100)/100,X=Math.round(it/U*100*100)/100,ht=Math.round(kt/j*100*100)/100,Yt=Math.round(Q/U*100*100)/100;return[$,X,ht,Yt]}function $e(S,O){let E='';return E+='',E+="",E}}const L={version:"2.2.0",plot:{},aggregateMethod:{}};L.axis=function(p,o,h,w,v,z){this.chart=p,this.position=o,this.categoryFields=v==null?h:[].concat(v),this.measure=w,this.timeField=v,this.floatingBarWidth=5,this.hidden=!1,this.showPercent=!1,this.colors=null,this.overrideMin=null,this.overrideMax=null,this.shapes=null,this.showGridlines=null,this.gridlineShapes=null,this.titleShape=null,this.dateParseFormat=null,this.tickFormat=null,this.timePeriod=null,this.timeInterval=1,this.useLog=!1,this.logBase=10,this.title=void 0,this.clamp=!0,this.ticks=null,this.fontSize="10px",this.fontFamily="sans-serif",this.autoRotateLabel=z??!0,this._slaves=[],this._scale=null,this._min=0,this._max=0,this._previousOrigin=null,this._origin=null,this._orderRules=[],this._groupOrderRules=[],this._draw=null,this._getAxisData=function(){var B,T,D=[],R=!1;if(this.chart&&this.chart.series){for(B=0;B0?D=D.concat(T.data):R=!0);R&&this.chart.data&&(D=D.concat(this.chart.data))}return D},this._getFontSize=function(){var B;return!this.fontSize||this.fontSize.toString().toLowerCase()==="auto"?B=(this.chart._heightPixels()/35>10?this.chart._heightPixels()/35:10)+"px":isNaN(this.fontSize)?B=this.fontSize:B=this.fontSize+"px",B},this._getFormat=function(){var B,T,D,R,M,I,k;return this.tickFormat!==null&&this.tickFormat!==void 0?this._hasTimeField()?B=pt.timeFormat(this.tickFormat):B=pt.format(this.tickFormat):this.showPercent?B=pt.format(".0%"):this.useLog&&this.measure!==null?B=function(N){var C=Math.floor(Math.abs(N),0).toString().length,q=Math.min(Math.floor((C-1)/3),4),G="kmBT".substring(q-1,q),et=Math.round(N/Math.pow(1e3,q)*10).toString().slice(-1)==="0"?0:1;return N===0?0:pt.format(",."+et+"f")(N/Math.pow(1e3,q))+G}:this.measure!==null?(T=Math.floor(Math.abs(this._max),0).toString(),D=Math.floor(Math.abs(this._min),0).toString(),R=Math.max(D.length,T.length),R>3?(M=Math.min(Math.floor((R-1)/3),4),I="kmBT".substring(M-1,M),k=R-M*3<=1?1:0,B=function(N){return N===0?0:pt.format(",."+k+"f")(N/Math.pow(1e3,M))+I}):(k=Math.max(-(this._tick_step?Math.floor(Math.log(this._tick_step)/Math.LN10):0),0),B=pt.format(",."+k+"f"))):B=function(N){return N},B},this._getTimePeriod=function(){var B=this.timePeriod,T=30,D=this._max-this._min;return this._hasTimeField()&&!this.timePeriod&&(D/1e3<=T?B=pt.timeSecond:D/6e4<=T?B=pt.timeMinute:D/36e5<=T?B=pt.timeHour:D/864e5<=T?B=pt.timeHay:D/6048e5<=T?B=pt.timeWeek:D/26298e5<=T?B=pt.timeMonth:B=pt.timeYear),B},this._getTooltipText=function(B,T){if(this._hasTimeField())T[this.position+"Field"][0]&&B.push(this.timeField+": "+this._getFormat()(T[this.position+"Field"][0]));else if(this._hasCategories())this.categoryFields.forEach(function(D,R){D!=null&&T[this.position+"Field"][R]&&B.push(D+(T[this.position+"Field"][R]!==D?": "+T[this.position+"Field"][R]:""))},this);else if(this._hasMeasure())switch(this.position){case"x":B.push(this.measure+": "+this._getFormat()(T.width));break;case"y":B.push(this.measure+": "+this._getFormat()(T.height));break;case"p":B.push(this.measure+": "+this._getFormat()(T.angle)+" ("+pt.format(".0%")(T.piePct)+")");break;default:B.push(this.measure+": "+this._getFormat()(T[this.position+"Value"]));break}},this._getTopMaster=function(){var B=this;return this.master!==null&&this.master!==void 0&&(B=this.master._getTopMaster()),B},this._hasCategories=function(){return this.categoryFields!==null&&this.categoryFields!==void 0&&this.categoryFields.length>0},this._hasMeasure=function(){return this.measure!==null&&this.measure!==void 0},this._hasTimeField=function(){return this.timeField!==null&&this.timeField!==void 0},this._parseDate=function(B){var T;return this.dateParseFormat===null||this.dateParseFormat===void 0?isNaN(B)?T=Date.parse(B):T=new Date(B):T=pt.timeParse(this.dateParseFormat)(B),T},this._update=function(B){var T=[],D,R,M,I,k=this.ticks||10,N=function(C,q,G){var et=C.categoryFields[0],rt=C._getAxisData(),vt=et,Ft=!1,dt=!0,ut=null,Mt,Gt;for(Mt=0;Mt1?1:this._max,this._min=this.overrideMin!==null?this.overrideMin:this._min,this._max=this.overrideMax!==null?this.overrideMax:this._max,this.position==="x"&&(this._scale===null||B)){if(this._hasTimeField()?this._scale=pt.scaleTime().range([this.chart._xPixels(),this.chart._xPixels()+this.chart._widthPixels()]).domain([this._min,this._max]).clamp(this.clamp):this.useLog?this._scale=pt.scaleLog().range([this.chart._xPixels(),this.chart._xPixels()+this.chart._widthPixels()]).domain([this._min===0?Math.pow(this.logBase,-1):this._min,this._max===0?-1*Math.pow(this.logBase,-1):this._max]).clamp(this.clamp).base(this.logBase).nice():this.measure===null||this.measure===void 0?(T=N(this,"x","y"),this._slaves!==null&&this._slaves!==void 0&&this._slaves.forEach(function(C){T=T.concat(N(C,"x","y"))},this),this._scale=pt.scalePoint().range([this.chart._xPixels(),this.chart._xPixels()+this.chart._widthPixels()]).domain(T.concat([""]))):this._scale=pt.scaleLinear().range([this.chart._xPixels(),this.chart._xPixels()+this.chart._widthPixels()]).domain([this._min,this._max]).clamp(this.clamp).nice(),!this.hidden)switch(this.chart._axisIndex(this,"x")){case 0:this._draw=pt.axisBottom().scale(this._scale),this.ticks&&this._draw.ticks(k);break;case 1:this._draw=pt.axisTop().scale(this._scale),this.ticks&&this._draw.ticks(k);break}}else if(this.position==="y"&&(this._scale===null||B)){if(this._hasTimeField()?this._scale=pt.scaleTime().range([this.chart._yPixels()+this.chart._heightPixels(),this.chart._yPixels()]).domain([this._min,this._max]).clamp(this.clamp):this.useLog?this._scale=pt.scaleLog().range([this.chart._yPixels()+this.chart._heightPixels(),this.chart._yPixels()]).domain([this._min===0?Math.pow(this.logBase,-1):this._min,this._max===0?-1*Math.pow(this.logBase,-1):this._max]).clamp(this.clamp).base(this.logBase).nice():this.measure===null||this.measure===void 0?(T=N(this,"y","x"),this._slaves!==null&&this._slaves!==void 0&&this._slaves.forEach(function(C){T=T.concat(N(C,"y","x"))},this),this._scale=pt.scalePoint().range([this.chart._yPixels()+this.chart._heightPixels(),this.chart._yPixels()]).domain(T.concat([""]))):this._scale=pt.scaleLinear().range([this.chart._yPixels()+this.chart._heightPixels(),this.chart._yPixels()]).domain([this._min,this._max]).clamp(this.clamp).nice(),!this.hidden)switch(this.chart._axisIndex(this,"y")){case 0:this._draw=pt.axisLeft().scale(this._scale),this.ticks&&this._draw.ticks(k);break;case 1:this._draw=pt.axisRight().scale(this._scale),this.ticks&&this._draw.ticks(k);break}}else this.position.length>0&&this.position[0]==="z"&&this._scale===null?this.useLog?this._scale=pt.scaleLog().range([this.chart._heightPixels()/300,this.chart._heightPixels()/10]).domain([this._min===0?Math.pow(this.logBase,-1):this._min,this._max===0?-1*Math.pow(this.logBase,-1):this._max]).clamp(this.clamp).base(this.logBase):this._scale=pt.scaleLinear().range([1,this.chart._heightPixels()/10]).domain([this._min,this._max]).clamp(this.clamp):this.position.length>0&&this.position[0]==="p"&&this._scale===null?this.useLog?this._scale=pt.scaleLog().range([0,360]).domain([this._min===0?Math.pow(this.logBase,-1):this._min,this._max===0?-1*Math.pow(this.logBase,-1):this._max]).clamp(this.clamp).base(this.logBase):this._scale=pt.scaleLinear().range([0,360]).domain([this._min,this._max]).clamp(this.clamp):this.position.length>0&&this.position[0]==="c"&&this._scale===null&&(this._scale=pt.scaleLinear().range([0,this.colors===null||this.colors.length===1?1:this.colors.length-1]).domain([this._min,this._max]).clamp(this.clamp));return this._slaves!==null&&this._slaves!==void 0&&this._slaves.length>0&&this._slaves.forEach(function(C){C._scale=this._scale},this),(B==null||B===!1)&&!this._hasTimeField()&&this._scale!==null&&this._scale.ticks!==null&&this._scale.ticks!==void 0&&this._scale.ticks(k).length>0&&(this.position==="x"||this.position==="y")&&(D=this._scale.ticks(k),R=D[1]-D[0],M=((this._max-this._min)%R).toFixed(0),this._tick_step=R,M!==0&&(this._max=Math.ceil(this._max/R)*R,this._min=Math.floor(this._min/R)*R,this._update(!0))),T!=null&&T.length>0?I=this._scale.copy()(T[0]):this._min>0?I=this._scale.copy()(this._min):this._max<0?I=this._scale.copy()(this._max):I=this._scale.copy()(0),this._origin!==I&&(this._previousOrigin=this._origin===null?I:this._origin,this._origin=I),this},this.addGroupOrderRule=function(B,T){this._groupOrderRules.push({ordering:B,desc:T})},this.addOrderRule=function(B,T){this._orderRules.push({ordering:B,desc:T})}};L.chart=function(p,o){this.svg=p,this.x="10%",this.y="10%",this.width="80%",this.height="80%",this.data=o,this.noFormats=!1,this.axes=[],this.series=[],this.legends=[],this.storyboard=null,this.titleShape=null,this.shapes=null,this.ease=pt.easeCubicInOut,this.staggerDraw=!1,this.transition={},this._group=p.append("g"),this._group.attr("class","dimple-chart"),this._gridlines_group=this._group.insert("g"),this._gridlines_group.attr("class","dimple-gridlines-group"),this._axis_group=this._group.insert("g"),this._axis_group.attr("class","dimple-axis-group"),this._tooltipGroup=null,this._assignedColors={},this._assignedClasses={},this._nextColor=0,this._nextClass=0,this._axisIndex=function(h,w){var v=0,z=0,B=-1;for(v=0;v0&&(h=h.concat(this.data)),this.series!==null&&this.series!==void 0&&this.series.length>0&&this.series.forEach(function(w){w.data!==null&&w.data!==void 0&&w.data.length>0&&(h=h.concat(w.data))}),h},this._getData=function(h,w,v,z,B,T,D,R,M,I){var k=[],N=function(St,ae){var Qt=[];return St!==null&&(St._hasTimeField()?Qt.push(St._parseDate(ae[St.timeField])):St._hasCategories()&&St.categoryFields.forEach(function(me){Qt.push(ae[me])},this)),Qt},C={x:!1,y:!1,z:!1,p:!1,c:!1},q={x:[],y:[]},G={x:[],y:[],z:[],p:[]},et={min:null,max:null},rt,vt={x:[],y:[],z:[],p:[]},Ft=[],dt={},ut={x:0,y:0,z:0,p:0},Mt,Gt="",Nt=[],qt=[],ce=[],$t="",Et=[],ee="",le=[],ie="",en=[],ge=[],ve=h,ue=[];this.storyboard&&this.storyboard.categoryFields.length>0&&(Gt=this.storyboard.categoryFields[0],Nt=L._getOrderedList(ve,Gt,this.storyboard._orderRules)),T&&T._hasCategories()&&T._hasMeasure()&&($t=T.categoryFields[0],Et=L._getOrderedList(ve,$t,T._orderRules.concat([{ordering:T.measure,desc:!0}]))),D&&D._hasCategories()&&D._hasMeasure()&&(ee=D.categoryFields[0],le=L._getOrderedList(ve,ee,D._orderRules.concat([{ordering:D.measure,desc:!0}]))),M&&M._hasCategories()&&M._hasMeasure()&&(ie=M.categoryFields[0],en=L._getOrderedList(ve,ie,M._orderRules.concat([{ordering:M.measure,desc:!0}]))),ve.length>0&&w&&w.length>0&&(ge=[].concat(z),qt=[],w.forEach(function(St){ve[0][St]!==void 0&&qt.push(St)},this),M&&M._hasMeasure()?ge.push({ordering:M.measure,desc:!0}):I&&I._hasMeasure()?ge.push({ordering:I.measure,desc:!0}):R&&R._hasMeasure()?ge.push({ordering:R.measure,desc:!0}):T&&T._hasMeasure()?ge.push({ordering:T.measure,desc:!0}):D&&D._hasMeasure()&&ge.push({ordering:D.measure,desc:!0}),ce=L._getOrderedList(ve,qt,ge)),ve.sort(function(St,ae){var Qt=0,me,Ce,be,_e,wt,Ut;if(Gt!==""&&(Qt=Nt.indexOf(St[Gt])-Nt.indexOf(ae[Gt])),$t!==""&&Qt===0&&(Qt=Et.indexOf(St[$t])-Et.indexOf(ae[$t])),ee!==""&&Qt===0&&(Qt=le.indexOf(St[ee])-le.indexOf(ae[ee])),ie!==""&&Qt===0&&(Qt=en.indexOf(St[ie])-le.indexOf(ae[ie])),qt&&qt.length>0&&Qt===0)for(me=[].concat(qt),Qt=0,be=0;be0&&(Se+="/"),Se+=St[nn],Pe=Se===Cn},this)),fe!=null&&Pe&&(Ae=k[ae],fe._hasMeasure()&&St[fe.measure]!==null&&St[fe.measure]!==void 0&&(Ae[fe.position+"ValueList"].indexOf(St[fe.measure])===-1&&Ae[fe.position+"ValueList"].push(St[fe.measure]),isNaN(parseFloat(St[fe.measure]))&&(C[fe.position]=!0),mn.value=Ae[fe.position+"Value"],mn.count=Ae[fe.position+"Count"],un.value=St[fe.measure],Ae[fe.position+"Value"]=v(mn,un),Ae[fe.position+"Count"]+=1))},Ot(T,this.storyboard),Ot(D,this.storyboard),Ot(R,this.storyboard),Ot(M,this.storyboard),Ot(I,this.storyboard)},this),T&&T._hasCategories()&&T.categoryFields.length>1&&q.x!==void 0&&(ue=[],D._hasMeasure()&&ue.push({ordering:D.measure,desc:!0}),q.x=L._getOrderedList(ve,T.categoryFields[1],T._groupOrderRules.concat(ue))),D&&D._hasCategories()&&D.categoryFields.length>1&&q.y!==void 0&&(ue=[],T._hasMeasure()&&ue.push({ordering:T.measure,desc:!0}),q.y=L._getOrderedList(ve,D.categoryFields[1],D._groupOrderRules.concat(ue)),q.y.reverse()),k.forEach(function(St){T!==null&&(C.x===!0&&(St.xValue=St.xValueList.length),T._hasMeasure()&&T._hasCategories()?rt=(G.x[St.xField.join("/")]||0)+(T._hasMeasure()?Math.abs(St.xValue):0):rt=(G.x[St.xField.join("/")]||0)+(D._hasMeasure()?Math.abs(St.yValue):0),G.x[St.xField.join("/")]=rt),D!==null&&(C.y===!0&&(St.yValue=St.yValueList.length),D._hasMeasure()&&D._hasCategories()?rt=(G.y[St.yField.join("/")]||0)+(D._hasMeasure()?Math.abs(St.yValue):0):rt=(G.y[St.yField.join("/")]||0)+(T._hasMeasure()?Math.abs(St.xValue):0),G.y[St.yField.join("/")]=rt),M!==null&&(C.p===!0&&(St.pValue=St.pValueList.length),rt=(G.p[St.pField.join("/")]||0)+(M._hasMeasure()?Math.abs(St.pValue):0),G.p[St.pField.join("/")]=rt),R!==null&&(C.z===!0&&(St.zValue=St.zValueList.length),rt=(G.z[St.zField.join("/")]||0)+(R._hasMeasure()?Math.abs(St.zValue):0),G.z[St.zField.join("/")]=rt),I!==null&&((et.min===null||St.cValueet.max)&&(et.max=St.cValue))},this);for(Mt in G.x)Object.prototype.hasOwnProperty.call(G.x,Mt)&&(ut.x+=G.x[Mt]);for(Mt in G.y)Object.prototype.hasOwnProperty.call(G.y,Mt)&&(ut.y+=G.y[Mt]);for(Mt in G.p)Object.prototype.hasOwnProperty.call(G.p,Mt)&&(ut.p+=G.p[Mt]);for(Mt in G.z)Object.prototype.hasOwnProperty.call(G.z,Mt)&&(ut.z+=G.z[Mt]);return k.forEach(function(St){var ae,Qt,me,Ce,be,_e=function(wt,Ut,re){var ne,Ot,fe,Vt,Pe;wt!=null&&(Vt=wt.position,wt._hasCategories()?wt._hasMeasure()?(ne=St[wt.position+"Field"].join("/"),Ot=wt.showPercent?G[wt.position][ne]/ut[wt.position]:G[wt.position][ne],Ft.indexOf(ne)===-1&&(dt[ne]=Ot+(Ft.length>0?dt[Ft[Ft.length-1]]:0),Ft.push(ne)),fe=St[Vt+"Bound"]=St["c"+Vt]=(Vt==="x"||Vt==="y")&&B?dt[ne]:Ot,St[re]=Ot,St[Vt]=fe-(Vt==="x"&&Ot>=0||Vt==="y"&&Ot<=0?Ot:0)):(St[Vt]=St["c"+Vt]=St[Vt+"Field"][0],St[re]=1,q[Vt]!==void 0&&q[Vt]!==null&&q[Vt].length>=2&&(St[Vt+"Offset"]=q[Vt].indexOf(St[Vt+"Field"][1]),St[re]=1/q[Vt].length)):(Ot=wt.showPercent?St[Vt+"Value"]/G[Ut][St[Ut+"Field"].join("/")]:St[Vt+"Value"],ne=St[Ut+"Field"].join("/")+(St[Vt+"Value"]>=0),Pe=vt[Vt][ne]=(vt[Vt][ne]===null||vt[Vt][ne]===void 0||Vt==="z"||Vt==="p"?0:vt[Vt][ne])+Ot,fe=St[Vt+"Bound"]=St["c"+Vt]=(Vt==="x"||Vt==="y")&&B?Pe:Ot,St[re]=Ot,St[Vt]=fe-(Vt==="x"&&Ot>=0||Vt==="y"&&Ot<=0?Ot:0)))};_e(T,"y","width"),_e(D,"x","height"),_e(R,"z","r"),_e(M,"p","angle"),I!==null&&et.min!==null&&et.max!==null&&(et.min===et.max&&(et.min-=.5,et.max+=.5),et.min=I.overrideMin||et.min,et.max=I.overrideMax||et.max,St.cValue=St.cValue>et.max?et.max:St.cValue1?(ae=pt.rgb(I.colors[Math.floor(Ce)]),Qt=pt.rgb(I.colors[Math.ceil(Ce)])):(ae=pt.rgb("white"),Qt=pt.rgb(this.getColor(St.aggField.slice(-1)[0]).fill)),ae.r=Math.floor(ae.r+(Qt.r-ae.r)*be),ae.g=Math.floor(ae.g+(Qt.g-ae.g)*be),ae.b=Math.floor(ae.b+(Qt.b-ae.b)*be),St.fill=ae.toString(),St.stroke=ae.darker(.5).toString())},this),k},this._getDelay=function(h,w,v){return function(z){var B=0;return v&&w.staggerDraw&&(v.x._hasCategories()?B=L._helpers.cx(z,w,v)/w._widthPixels()*h:v.y._hasCategories()&&(B=(1-L._helpers.cy(z,w,v)/w._heightPixels())*h)),B}},this._getSeriesData=function(){this.series!==null&&this.series!==void 0&&this.series.forEach(function(h){var w=h.data||this.data||[],v=[].concat(h.categoryFields||"All"),z=this._getData(w,v,h.aggregate,h._orderRules,h._isStacked(),h.x,h.y,h.z,h.p,h.c),B=[],T,D,R,M,I,k,N={},C=h.startAngle*(Math.PI/180)||0,q=(h.endAngle||360)*(Math.PI/180);if(C>q&&(C-=2*Math.PI),h.p&&v.length>0){if(h.x&&h.y){for(v.pop(),B=this._getData(w,["__dimple_placeholder__"].concat(v),h.aggregate,h._orderRules,h._isStacked(),h.x,h.y,h.z,h.p,h.c),T=0;T0&&h._eventHandlers.forEach(function(w){var v,z=function(B){var T=new L.eventArgs;h.chart.storyboard!==null&&(T.frameValue=h.chart.storyboard.getFrameValue()),T.seriesValue=B.aggField,T.xValue=B.x,T.yValue=B.y,T.zValue=B.z,T.pValue=B.p,T.colorValue=B.cValue,T.seriesShapes=h.shapes,T.selectedShape=pt.select(this),w.handler(T)};if(w.handler!==null&&typeof w.handler=="function")if(h._markers!==null&&h._markers!==void 0)for(v in h._markers)Object.prototype.hasOwnProperty.call(h._markers,v)&&h._markers[v].on(w.event,z);else h.shapes.on(w.event,z)},this)},this._widthPixels=function(){return L._parseXPosition(this.width,this.svg.node())},this._xPixels=function(){return L._parseXPosition(this.x,this.svg.node())},this._yPixels=function(){return L._parseYPosition(this.y,this.svg.node())},this.addAxis=function(h,w,v,z){var B=null,T=null,D;if(w!=null&&(w=[].concat(w)),typeof h=="string"||h instanceof String)B=new L.axis(this,h,w,v,z),this.axes.push(B);else{if(T=h,B=new L.axis(this,T.position,w,v,z),B._hasMeasure()!==T._hasMeasure()?D="You have specified a composite axis where some but not all axes have a measure - this is not supported, all axes must be of the same type.":B._hasTimeField()!==T._hasTimeField()?D="You have specified a composite axis where some but not all axes have a time field - this is not supported, all axes must be of the same type.":(B.categoryFields===null||B.categoryFields===void 0?0:B.categoryFields.length)!==(T.categoryFields===null||T.categoryFields===void 0?0:T.categoryFields.length)&&(D="You have specified a composite axis where axes have differing numbers of category fields - this is not supported, all axes must be of the same type."),D)throw D;T._slaves.push(B)}return B},this.addCategoryAxis=function(h,w){return this.addAxis(h,w,null)},this.addColorAxis=function(h,w){var v=this.addAxis("c",null,h);return v.colors=w==null?null:[].concat(w),v},this.addLegend=function(h,w,v,z,B,T){T=T==null?this.series:[].concat(T),B=B??"left";var D=new L.legend(this,h,w,v,z,B,T);return this.legends.push(D),D},this.addLogAxis=function(h,w,v){var z=this.addAxis(h,null,w,null);return v!=null&&(z.logBase=v),z.useLog=!0,z},this.addMeasureAxis=function(h,w){return this.addAxis(h,null,w)},this.addPctAxis=function(h,w,v){var z=null;return v!=null?z=this.addAxis(h,v,w):z=this.addMeasureAxis(h,w),z.showPercent=!0,z},this.addSeries=function(h,w,v){v==null&&(v=this.axes),w==null&&(w=L.plot.bubble);var z=null,B=null,T=null,D=null,R=null,M;return v.forEach(function(I){I!==null&&w.supportedAxes.indexOf(I.position)>-1&&(z===null&&I.position[0]==="x"?z=I:B===null&&I.position[0]==="y"?B=I:T===null&&I.position[0]==="z"?T=I:D===null&&I.position[0]==="c"?D=I:D===null&&I.position[0]==="p"&&(R=I))},this),h&&(h=[].concat(h)),M=new L.series(this,h,z,B,T,D,R,w,L.aggregateMethod.sum,w.stacked),this.series.push(M),M},this.addTimeAxis=function(h,w,v,z){var B=this.addAxis(h,null,null,w);return B.tickFormat=z,B.dateParseFormat=v,B},this.assignClass=function(h,w){return this._assignedClasses[h]=w,this._assignedClasses[h]},this.assignColor=function(h,w,v,z){return this._assignedColors[h]=new L.color(w,v,z),this._assignedColors[h]},this.customClassList={axisLine:"dimple-custom-axis-line",axisLabel:"dimple-custom-axis-label",axisTitle:"dimple-custom-axis-title",tooltipBox:"dimple-custom-tooltip-box",tooltipLabel:"dimple-custom-tooltip-label",tooltipDropLine:"dimple-custom-tooltip-dropline",lineMarker:"dimple-custom-line-marker",lineMarkerCircle:"dimple-custom-line-marker-circle",legendLabel:"dimple-custom-legend-label",legendKey:"dimple-custom-legend-key",areaSeries:"dimple-custom-series-area",barSeries:"dimple-custom-series-bar",bubbleSeries:"dimple-custom-series-bubble",lineSeries:"dimple-custom-series-line",pieSeries:"dimple-custom-series-pie",gridline:"dimple-custom-gridline",colorClasses:["dimple-custom-format-1","dimple-custom-format-2","dimple-custom-format-3","dimple-custom-format-4","dimple-custom-format-5","dimple-custom-format-6","dimple-custom-format-7","dimple-custom-format-8","dimple-custom-format-9","dimple-custom-format-10"]},this.defaultColors=[new L.color("#80B1D3"),new L.color("#FB8072"),new L.color("#FDB462"),new L.color("#B3DE69"),new L.color("#FFED6F"),new L.color("#BC80BD"),new L.color("#8DD3C7"),new L.color("#CCEBC5"),new L.color("#FFFFB3"),new L.color("#BEBADA"),new L.color("#FCCDE5"),new L.color("#D9D9D9")],this.draw=function(h,w){h=h||0;var v=null,z=null,B,T=!1,D=!1,R=this._xPixels(),M=this._yPixels(),I=this._widthPixels(),k=this._heightPixels(),N;return(w==null||w===!1)&&this._getSeriesData(),this.axes.forEach(function(C){C._scale=null},this),this.axes.forEach(function(C){if(C._min=0,C._max=0,N=[],C._hasMeasure()){var q=!1;this.series.forEach(function(G){if(G._deepMatch(C)){var et=G._axisBounds(C.position);C._min>et.min&&(C._min=et.min),C._maxG[C.measure]&&(C._min=G[C.measure]),C._maxC._max)&&(C._max=rt)},this)},this)):C._hasCategories()&&(C._min=0,B=[],this.series.forEach(function(G){G._deepMatch(C)&&G[C.position].categoryFields[0]!==null&&G[C.position].categoryFields[0]!==void 0&&N.indexOf(G[C.position].categoryFields[0])===-1&&N.push(G[C.position].categoryFields[0])},this),C._getAxisData().forEach(function(G){N.forEach(function(et){B.indexOf(G[et])===-1&&B.push(G[et])},this)},this),C._max=B.length);C._slaves!==null&&C._slaves!==void 0&&C._slaves.length>0&&C._slaves.forEach(function(G){G._min=C._min,G._max=C._max},this),C._update(),v===null&&C.position==="x"?v=C:z===null&&C.position==="y"&&(z=C)},this),this.axes.forEach(function(C){var q=!1,G=null,et=0,rt=null,vt=!1,Ft=0,dt={l:null,t:null,r:null,b:null},ut=0,Mt=0,Gt="",Nt=this,qt=function(Et){var ee;return G===null||h===0||q?ee=Et:ee=Nt._handleTransition(Et,h,Nt),ee},ce=function(){var Et=pt.select(this).selectAll("text");return!C.measure&&C._max>0&&(C.position==="x"?Et.attr("x",I/C._max/2):C.position==="y"&&Et.attr("y",-1*(k/C._max)/2)),C.categoryFields&&C.categoryFields.length>0&&(C===v&&(z.categoryFields===null||z.categoryFields.length===0)&&Et.attr("y",M+k-z._scale(0)+9),C===z&&(v.categoryFields===null||v.categoryFields.length===0)&&Et.attr("x",-1*(v._scale(0)-R)-9)),this},$t=function(Et){return function(){var ee=pt.select(this).attr("class")||"";return ee.indexOf(Et)===-1&&(ee+=" "+Et),ee.trim()}};C.gridlineShapes===null?(C.showGridlines||C.showGridlines===null&&!C._hasCategories()&&(!T&&C.position==="x"||!D&&C.position==="y"))&&(C.gridlineShapes=this._gridlines_group.append("g").attr("class","dimple-gridline"),C.position==="x"?T=!0:D=!0):C.position==="x"?T=!0:D=!0,C.shapes===null&&(C.shapes=this._axis_group.append("g").attr("class","dimple-axis dimple-axis-"+C.position).each(function(){Nt.noFormats||pt.select(this).style("font-family",C.fontFamily).style("font-size",C._getFontSize())}),q=!0),C===v&&z!==null?(G="translate(0, "+(z.categoryFields===null||z.categoryFields.length===0?z._scale(0):M+k)+")",rt="translate(0, "+(C===v?M+k:M)+")",et=-k):C===z&&v!==null?(G="translate("+(v.categoryFields===null||v.categoryFields.length===0?v._scale(0):R)+", 0)",rt="translate("+(C===z?R:R+I)+", 0)",et=-I):C.position==="x"?(rt=G="translate(0, "+(C===v?M+k:M)+")",et=-k):C.position==="y"&&(rt=G="translate("+(C===z?R:R+I)+", 0)",et=-I),G!==null&&C._draw!==null&&(C._hasTimeField()?qt(C.shapes).call(C._draw.ticks(C._getTimePeriod(),C.timeInterval).tickFormat(C._getFormat())).attr("transform",G).each(ce):C.useLog?qt(C.shapes).call(C._draw.ticks(4,C._getFormat())).attr("transform",G).each(ce):qt(C.shapes).call(C._draw.tickFormat(C._getFormat())).attr("transform",G).each(ce),C.gridlineShapes!==null&&qt(C.gridlineShapes).call(C._draw.tickSize(et,0,0).tickFormat("")).attr("transform",rt)),qt(C.shapes.selectAll("text")).attr("class",$t(Nt.customClassList.axisLabel)).call(function(Et){Nt.noFormats||Et.style("font-family",C.fontFamily).style("font-size",C._getFontSize())}),qt(C.shapes.selectAll("path, line")).attr("class",$t(Nt.customClassList.axisLine)).call(function(Et){Nt.noFormats||Et.style("fill","none").style("stroke","black").style("shape-rendering","crispEdges")}),C.gridlineShapes!==null&&(C.gridlineShapes.selectAll("path").remove(),qt(C.gridlineShapes.selectAll("line")).attr("class",$t(Nt.customClassList.gridline)).call(function(Et){Nt.noFormats||Et.style("fill","none").style("stroke","lightgray").style("opacity",.8)})),(C.measure===null||C.measure===void 0)&&(C.autoRotateLabel?C===v?(Ft=0,C.shapes.selectAll("text").each(function(){var Et=this.getComputedTextLength();Ft=Et>Ft?Et:Ft}),Ft>I/C.shapes.selectAll("text").nodes().length?(vt=!0,C.shapes.selectAll("text").style("text-anchor","start").each(function(){var Et=this.getBBox();pt.select(this).attr("transform","rotate(90,"+Et.x+","+(Et.y+Et.height/2)+") translate(-5, 0)")})):(vt=!1,C.shapes.selectAll("text").style("text-anchor","middle").attr("transform",""))):C.position==="x"&&(Ft=0,C.shapes.selectAll("text").each(function(){var Et=this.getComputedTextLength();Ft=Et>Ft?Et:Ft}),Ft>I/C.shapes.selectAll("text").nodes().length?(vt=!0,C.shapes.selectAll("text").style("text-anchor","end").each(function(){var Et=this.getBBox();pt.select(this).attr("transform","rotate(90,"+(Et.x+Et.width)+","+(Et.y+Et.height/2)+") translate(5, 0)")})):(vt=!1,C.shapes.selectAll("text").style("text-anchor","middle").attr("transform",""))):(vt=!1,C.shapes.selectAll("text").style("text-anchor","middle").attr("transform",""))),C.titleShape!==null&&C.titleShape!==void 0&&C.titleShape.remove(),C.shapes.selectAll("text").each(function(){var Et=this.getBBox();(dt.l===null||-9-Et.widthdt.r)&&(dt.r=Et.x+Et.width),vt?((dt.t===null||Et.y+Et.height-Et.widthdt.b)&&(dt.b=Et.height+Et.width)):((dt.t===null||Et.ydt.b)&&(dt.b=9+Et.height))}),C.position==="x"?(C===v?Mt=M+k+dt.b+5:Mt=M+dt.t-10,ut=R+I/2):C.position==="y"&&(C===z?ut=R+dt.l-10:ut=R+I+dt.r+20,Mt=M+k/2,Gt="rotate(270, "+ut+", "+Mt+")"),!C.hidden&&(C.position==="x"||C.position==="y")&&C.title!==null&&(C.titleShape=this._axis_group.append("text").attr("class","dimple-axis dimple-title "+Nt.customClassList.axisTitle+" dimple-axis-"+C.position),C.titleShape.attr("x",ut).attr("y",Mt).attr("text-anchor","middle").attr("transform",Gt).text(C.title!==void 0?C.title:C.categoryFields===null||C.categoryFields===void 0||C.categoryFields.length===0?C.measure:C.categoryFields.join("/")).each(function(){Nt.noFormats||pt.select(this).style("font-family",C.fontFamily).style("font-size",C._getFontSize())}),C===v?C.titleShape.each(function(){pt.select(this).attr("y",Mt+this.getBBox().height/1.65)}):C===z&&C.titleShape.each(function(){pt.select(this).attr("x",ut+this.getBBox().height/1.65)}))},this),this.series.forEach(function(C){C.plot.draw(this,C,h),this._registerEventHandlers(C)},this),this.legends.forEach(function(C){C._draw()},this),this.storyboard&&(this.storyboard._drawText(),this.storyboard.autoplay&&this.storyboard.startAnimation()),this},this.getClass=function(h){return this._assignedClasses[h]||(this._assignedClasses[h]=this.customClassList.colorClasses[this._nextClass],this._nextClass=(this._nextClass+1)%this.customClassList.colorClasses.length),this._assignedClasses[h]},this.getColor=function(h){return(this._assignedColors[h]===null||this._assignedColors[h]===void 0)&&(this._assignedColors[h]=this.defaultColors[this._nextColor],this._nextColor=(this._nextColor+1)%this.defaultColors.length),this._assignedColors[h]},this.setBounds=function(h,w,v,z){return this.x=h,this.y=w,this.width=v,this.height=z,this._xPixels=function(){return L._parseXPosition(this.x,this.svg.node())},this.draw(0,!0),this._yPixels=function(){return L._parseYPosition(this.y,this.svg.node())},this._widthPixels=function(){return L._parseXPosition(this.width,this.svg.node())},this._heightPixels=function(){return L._parseYPosition(this.height,this.svg.node())},this},this.setMargins=function(h,w,v,z){return this.x=h,this.y=w,this.width=0,this.height=0,this._xPixels=function(){return L._parseXPosition(this.x,this.svg.node())},this._yPixels=function(){return L._parseYPosition(this.y,this.svg.node())},this._widthPixels=function(){return L._parentWidth(this.svg.node())-this._xPixels()-L._parseXPosition(v,this.svg.node())},this._heightPixels=function(){return L._parentHeight(this.svg.node())-this._yPixels()-L._parseYPosition(z,this.svg.node())},this},this.setStoryboard=function(h,w){return this.storyboard=new L.storyboard(this,h),w!=null&&(this.storyboard.onTick=w),this.storyboard}};L.color=function(p,o,h){this.fill=p,this.stroke=o??pt.rgb(p).darker(.5).toString(),this.opacity=h??.8};L.eventArgs=function(){this.seriesValue=null,this.xValue=null,this.yValue=null,this.zValue=null,this.pValue=null,this.colorValue=null,this.frameValue=null,this.seriesShapes=null,this.selectedShape=null};L.legend=function(p,o,h,w,v,z,B){this.chart=p,this.series=B,this.x=o,this.y=h,this.width=w,this.height=v,this.horizontalAlign=z,this.shapes=null,this.fontSize="10px",this.fontFamily="sans-serif",this._draw=function(){var T=this._getEntries(),D=0,R=0,M=0,I=0,k=15,N=9,C=5,q=this,G;this.shapes&&this.shapes.remove(),G=this.chart._group.selectAll(".dimple-dont-select-any").data(T).enter().append("g").attr("class",function(et){return"dimple-legend "+L._createClass(et.aggField)}).attr("opacity",1),G.append("text").attr("class",function(et){return"dimple-legend dimple-legend-text "+L._createClass(et.aggField)+" "+q.chart.customClassList.legendLabel}).text(function(et){return et.key}).call(function(et){q.chart.noFormats||et.style("font-family",q.fontFamily).style("font-size",q._getFontSize()).style("shape-rendering","crispEdges")}).each(function(){var et=this.getBBox();et.width>D&&(D=et.width),et.height>R&&(R=et.height)}),G.append("rect").attr("class",function(et){return"dimple-legend dimple-legend-key "+L._createClass(et.aggField)}).attr("height",N).attr("width",k),R=(Rq._widthPixels()&&(M=0,I+=R),I>q._heightPixels()?pt.select(this).remove():(pt.select(this).select("text").attr("x",q.horizontalAlign==="left"?q._xPixels()+k+C+M:q._xPixels()+(q._widthPixels()-M-D)+k+C).attr("y",function(){return q._yPixels()+I+this.getBBox().height/1.65}).attr("width",q._widthPixels()).attr("height",q._heightPixels()),pt.select(this).select("rect").attr("class",function(rt){return"dimple-legend dimple-legend-key "+L._createClass(rt.aggField)+" "+q.chart.customClassList.legendKey+" "+rt.css}).attr("x",q.horizontalAlign==="left"?q._xPixels()+M:q._xPixels()+(q._widthPixels()-M-D)).attr("y",q._yPixels()+I).attr("height",N).attr("width",k).call(function(rt){q.chart.noFormats||rt.style("fill",et.fill).style("stroke",et.stroke).style("opacity",et.opacity).style("shape-rendering","crispEdges")}),M+=D)}),this.shapes=G},this._getEntries=function(){var T=[];return this.series&&this.series.forEach(function(D){var R=D._positionData;R.forEach(function(M){var I=-1,k,N=D.plot.grouped&&!D.x._hasCategories()&&!D.y._hasCategories()&&M.aggField.length<2?"All":M.aggField.slice(-1)[0];for(k=0;k10?this.chart._heightPixels()/35:10)+"px":isNaN(this.fontSize)?T=this.fontSize:T=this.fontSize+"px",T},this._getHorizontalPadding=function(){var T;return isNaN(this.horizontalPadding)?T=20:T=this.horizontalPadding,T},this._getVerticalPadding=function(){var T;return isNaN(this.verticalPadding)?T=2:T=this.verticalPadding,T},this._heightPixels=function(){return L._parseYPosition(this.height,this.chart.svg.node())},this._widthPixels=function(){return L._parseXPosition(this.width,this.chart.svg.node())},this._xPixels=function(){return L._parseXPosition(this.x,this.chart.svg.node())},this._yPixels=function(){return L._parseYPosition(this.y,this.chart.svg.node())}};L.series=function(p,o,h,w,v,z,B,T,D,R){this.chart=p,this.x=h,this.y=w,this.z=v,this.c=z,this.p=B,this.plot=T,this.categoryFields=o,this.aggregate=D,this.stacked=R,this.barGap=.2,this.clusterBarGap=.1,this.lineWeight=2,this.lineMarkers=!1,this.afterDraw=null,this.interpolation="linear",this.tooltipFontSize="10px",this.tooltipFontFamily="sans-serif",this.radius="auto",this._group=p._group.append("g"),this._group.attr("class","dimple-series-group-"+p.series.length),this._eventHandlers=[],this._positionData=[],this._orderRules=[],this._axisBounds=function(M){var I={min:0,max:0},k=null,N=null,C=[],q,G,et,rt=this._positionData;return M==="x"?(k=this.x,N=this.y):M==="y"?(k=this.y,N=this.x):M==="z"?k=this.z:M==="p"?k=this.p:M==="c"&&(k=this.c),k.showPercent?rt.forEach(function(vt){vt[k.position+"Bound"]I.max&&(I.max=vt[k.position+"Bound"])},this):N===null||N.categoryFields===null||N.categoryFields.length===0?rt.forEach(function(vt){this._isStacked()&&(k.position==="x"||k.position==="y")?vt[k.position+"Value"]<0?I.min=I.min+vt[k.position+"Value"]:I.max=I.max+vt[k.position+"Value"]:(vt[k.position+"Value"]I.max&&(I.max=vt[k.position+"Value"]))},this):(q=k.position+"Value",G=N.position+"Field",et=[],rt.forEach(function(vt){var Ft=vt[G].join("/"),dt=et.indexOf(Ft);dt===-1&&(et.push(Ft),dt=et.length-1),C[dt]===void 0&&(C[dt]={min:0,max:0}),this.stacked?vt[q]<0?C[dt].min=C[dt].min+vt[q]:C[dt].max=C[dt].max+vt[q]:(vt[q]C[dt].max&&(C[dt].max=vt[q]))},this),C.forEach(function(vt){vt!==void 0&&(vt.minI.max&&(I.max=vt.max))},this)),I},this._deepMatch=function(M){var I=!1;return this[M.position]===M?I=!0:M._slaves!==void 0&&M._slaves!==null&&M._slaves.length>0&&M._slaves.forEach(function(k){I=I||this._deepMatch(k)},this),I},this._dropLineOrigin=function(){var M=0,I=0,k={x:null,y:null},N={x:null,y:null};return this.chart.axes.forEach(function(C){C.position==="x"&&N.x===null?C._hasTimeField()?N.x=this.chart._xPixels():N.x=C._origin:C.position==="y"&&N.y===null&&(C._hasTimeField()?N.y=this.chart._yPixels()+this.chart._heightPixels():N.y=C._origin)},this),this.chart.axes.forEach(function(C){C.position==="x"&&!this.x.hidden?(this._deepMatch(C)&&(M===0?k.y=N.y:M===1&&(k.y=this.chart._yPixels())),M+=1):C.position==="y"&&!this.y.hidden&&(this._deepMatch(C)&&(I===0?k.x=N.x:I===1&&(k.x=this.chart._xPixels()+this.chart._widthPixels())),I+=1)},this),k},this._getTooltipFontSize=function(){var M;return!this.tooltipFontSize||this.tooltipFontSize.toString().toLowerCase()==="auto"?M=(this.chart._heightPixels()/35>10?this.chart._heightPixels()/35:10)+"px":isNaN(this.tooltipFontSize)?M=this.tooltipFontSize:M=this.tooltipFontSize+"px",M},this._isStacked=function(){return this.stacked&&(this.x._hasCategories()||this.y._hasCategories())},this.addEventHandler=function(M,I){this._eventHandlers.push({event:M,handler:I})},this.addOrderRule=function(M,I){this._orderRules.push({ordering:M,desc:I})},this.getTooltipText=function(M){var I=[];return this.categoryFields!==null&&this.categoryFields!==void 0&&this.categoryFields.length>0&&this.categoryFields.forEach(function(k,N){k!=null&&M.aggField[N]!==null&&M.aggField[N]!==void 0&&I.push(k+(M.aggField[N]!==k?": "+M.aggField[N]:""))},this),this.p?(this.x&&this.x._hasCategories()&&this.x._getTooltipText(I,M),this.y&&this.y._hasCategories()&&this.y._getTooltipText(I,M),this.z&&this.z._hasCategories()&&this.z._getTooltipText(I,M),this.p._getTooltipText(I,M)):(this.x&&this.x._getTooltipText(I,M),this.y&&this.y._getTooltipText(I,M),this.z&&this.z._getTooltipText(I,M)),this.c&&this.c._getTooltipText(I,M),I.filter(function(k,N){return I.indexOf(k)===N})}};L.storyboard=function(p,o){o!=null&&(o=[].concat(o)),this.chart=p,this.categoryFields=o,this.autoplay=!0,this.frameDuration=3e3,this.storyLabel=null,this.onTick=null,this.fontSize="10px",this.fontFamily="sans-serif",this._frame=0,this._animationTimer=null,this._categories=[],this._cachedCategoryFields=[],this._orderRules=[],this._drawText=function(){var h=this,w=0;h.storyLabel||(h.chart.axes.forEach(function(v){v.position==="x"&&(w+=1)},h),h.storyLabel=h.chart._group.append("text").attr("class","dimple-storyboard-label").attr("opacity",1).attr("x",h.chart._xPixels()+h.chart._widthPixels()*.01).attr("y",h.chart._yPixels()+(h.chart._heightPixels()/35>10?h.chart._heightPixels()/35:10)*(w>1?1.25:-1)).call(function(v){p.noFormats||v.style("font-family",h.fontFamily).style("font-size",h._getFontSize())})),h.storyLabel.text(h.categoryFields.join("\\")+": "+h.getFrameValue())},this._getCategories=function(){return this._categoryFields!==this._cachedCategoryFields&&(this._categories=[],this.chart._getAllData().forEach(function(h){var w=-1,v="";this.categoryFields!==null&&(this.categoryFields.forEach(function(z,B){B>0&&(v+="/"),v+=h[z]},this),w=this._categories.indexOf(v),w===-1&&(this._categories.push(v),w=this._categories.length-1))},this),this._cachedCategoryFields=this._categoryFields),this._categories},this._getFontSize=function(){var h;return!this.fontSize||this.fontSize.toString().toLowerCase()==="auto"?h=(this.chart._heightPixels()/35>10?this.chart._heightPixels()/35:10)+"px":isNaN(this.fontSize)?h=this.fontSize:h=this.fontSize+"px",h},this._goToFrameIndex=function(h){this._frame=h%this._getCategories().length,this.chart.draw(this.frameDuration/2)},this.addOrderRule=function(h,w){this._orderRules.push({ordering:h,desc:w})},this.getFrameValue=function(){var h=null;return this._frame>=0&&this._getCategories().length>this._frame&&(h=this._getCategories()[this._frame]),h},this.goToFrame=function(h){if(this._getCategories().length>0){var w=this._getCategories().indexOf(h);this._goToFrameIndex(w)}},this.pauseAnimation=function(){this._animationTimer!==null&&(clearInterval(this._animationTimer),this._animationTimer=null)},this.startAnimation=function(){this._animationTimer===null&&(this.onTick!==null&&this.onTick(this.getFrameValue()),this._animationTimer=setInterval(function(h){return function(){h._goToFrameIndex(h._frame+1),h.onTick!==null&&h.onTick(h.getFrameValue()),h._drawText(h.frameDuration/2)}}(this),this.frameDuration))},this.stopAnimation=function(){this._animationTimer!==null&&(clearInterval(this._animationTimer),this._animationTimer=null,this._frame=0)}};L.aggregateMethod.avg=function(p,o){return p.value=p.value===null||p.value===void 0?0:parseFloat(p.value),p.count=p.count===null||p.count===void 0?1:parseFloat(p.count),o.value=o.value===null||o.value===void 0?0:parseFloat(o.value),o.count=o.count===null||o.count===void 0?1:parseFloat(o.count),(p.value*p.count+o.value*o.count)/(p.count+o.count)};L.aggregateMethod.count=function(p,o){return p.count=p.count===null||p.count===void 0?0:parseFloat(p.count),o.count=o.count===null||o.count===void 0?0:parseFloat(o.count),p.count+o.count};L.aggregateMethod.max=function(p,o){return p.value=p.value===null||p.value===void 0?0:parseFloat(p.value),o.value=o.value===null||o.value===void 0?0:parseFloat(o.value),p.value>o.value?p.value:o.value};L.aggregateMethod.min=function(p,o){return p.value===null?parseFloat(o.value):parseFloat(p.value)re&&fe=2?w[M][ge+"Field"][0]:"All"})),v[q].data.push(w[M])}for(vt&&v.sort(function(wt,Ut){return L._arrayIndexCompare(vt,wt.key,Ut.key)}),M=0;M1&&ge&&(o.x._hasCategories()?(ut.push({x:2*ut[ut.length-1].x-ut[ut.length-2].x,y:ut[ut.length-1].y}),Ft[v[M].group][ut[ut.length-1][ge]]=o[ve]._origin):o.y._hasCategories()&&(ut=[{x:ut[0].x,y:2*ut[0].y-ut[1].y}].concat(ut),Ft[v[M].group][ut[0][ge]]=o[ve]._origin,v[M].points=ut))}for(qt in Ft)if(Object.prototype.hasOwnProperty.call(Ft,qt)){dt[qt]=[];for(ce in Ft[qt])Object.prototype.hasOwnProperty.call(Ft[qt],ce)&&dt[qt].push(parseFloat(ce));dt[qt].sort(Ce)}for(M=0;M0)for(I=0,k=0;I=ut[0][ge]&&dt[$t][I]<=ut[ut.length-1][ge]&&(Nt={},Nt[ge]=dt[$t][I],Nt[ve]=Ft[$t][dt[$t][I]],Gt.push(Nt),ut[k][ge]>dt[$t][I]?Mt.push(Nt):(Mt.push(ut[k]),Ft[v[M].group][dt[$t][I]]=ut[k][ve],k+=1));else if(o._orderRules&&o._orderRules.length>0)Mt=ut.concat(ut[0]);else{ut=ut.sort(be),Mt.push(ut[0]),en=0;do en=_e(ut,Mt,en);while(Mt.length<=ut.length&&(Mt[0].x!==Mt[Mt.length-1].x||Mt[0].y!==Mt[Mt.length-1].y))}Gt=Gt.reverse(),Et=me(D,"_previousOrigin")(Mt),ee=me(D==="step-after"?"step-before":D==="step-before"?"step-after":D,"_previousOrigin")(Gt),le=me("linear","_previousOrigin")(Mt),ie=le.indexOf("L")===-1?void 0:le.indexOf("L"),v[M].entry=Et+(ee&&ee.length>0?"L"+ee.substring(1):"")+(le&&le.length>0?"L"+le.substring(1,ie):0),Et=me(D)(Mt),ee=me(D==="step-after"?"step-before":D==="step-before"?"step-after":D)(Gt),le=me("linear")(Mt),ie=le.indexOf("L")===-1?void 0:le.indexOf("L"),v[M].update=Et+(ee&&ee.length>0?"L"+ee.substring(1):"")+(le&&le.length>0?"L"+le.substring(1,ie):0),Et=me(D,"_origin")(Mt),ee=me(D==="step-after"?"step-before":D==="step-before"?"step-after":D,"_origin")(Gt),le=me("linear","_origin")(Mt),ie=le.indexOf("L")===-1?void 0:le.indexOf("L"),v[M].exit=Et+(ee&&ee.length>0?"L"+ee.substring(1):"")+(le&&le.length>0?"L"+le.substring(1,ie):0),v[M].color=p.getColor(v[M].key.length>0?v[M].key[v[M].key.length-1]:"All"),v[M].css=p.getClass(v[M].key.length>0?v[M].key[v[M].key.length-1]:"All")}p._tooltipGroup&&p._tooltipGroup.remove(),o.shapes?z=o.shapes.data(v,function(wt){return wt.key}):z=o._group.selectAll("."+B).data(v,function(wt){return wt.key}),G=z.enter().append("path").attr("id",function(wt){return L._createClass([wt.key])}).attr("class",function(wt){return B+" dimple-line "+wt.keyString+" "+p.customClassList.areaSeries+" "+wt.css}).attr("d",function(wt){return wt.entry}).call(function(wt){p.noFormats||wt.attr("opacity",function(Ut){return R?1:Ut.color.opacity}).style("fill",function(Ut){return R?"url(#"+L._createClass(["fill-area-gradient-"+Ut.keyString])+")":Ut.color.fill}).style("stroke",function(Ut){return R?"url(#"+L._createClass(["stroke-area-gradient-"+Ut.keyString])+")":Ut.color.stroke}).style("stroke-width",o.lineWeight)}).each(function(wt){wt.markerData=wt.data,ae(wt,this)}),et=p._handleTransition(z.merge(G),h,p).attr("d",function(wt){return wt.update}).each(function(wt){wt.markerData=wt.data,ae(wt,this)}),rt=p._handleTransition(z.exit(),h,p).attr("d",function(wt){return wt.exit}).each(function(wt){wt.markerData=[],ae(wt,this)}),L._postDrawHandling(o,et,rt,h),o.shapes=o._group.selectAll("."+B)}};L.plot.bar={stacked:!0,grouped:!1,supportedAxes:["x","y","c"],draw:function(p,o,h){var w=o._positionData,v=null,z=["dimple-series-"+p.series.indexOf(o),"dimple-bar"],B,T,D,R=!o._isStacked()&&o.x._hasMeasure(),M=!o._isStacked()&&o.y._hasMeasure(),I="none";o.x._hasCategories()&&o.y._hasCategories()?I="both":o.x._hasCategories()?I="x":o.y._hasCategories()&&(I="y"),p._tooltipGroup&&p._tooltipGroup.remove(),o.shapes?v=o.shapes.data(w,function(k){return k.key}):v=o._group.selectAll("."+z.join(".")).data(w,function(k){return k.key}),B=v.enter().append("rect").attr("id",function(k){return L._createClass([k.key])}).attr("class",function(k){var N=[];return N=N.concat(k.aggField),N=N.concat(k.xField),N=N.concat(k.yField),z.join(" ")+" "+L._createClass(N)+" "+p.customClassList.barSeries+" "+L._helpers.css(k,p)}).attr("x",function(k){var N=o.x._previousOrigin;return I==="x"?N=L._helpers.x(k,p,o):I==="both"&&(N=L._helpers.cx(k,p,o)),N}).attr("y",function(k){var N=o.y._previousOrigin;return I==="y"?N=L._helpers.y(k,p,o):I==="both"&&(N=L._helpers.cy(k,p,o)),N}).attr("width",function(k){return I==="x"?L._helpers.width(k,p,o):0}).attr("height",function(k){return I==="y"?L._helpers.height(k,p,o):0}).on("mouseover",function(k){L._showBarTooltip(k,this,p,o)}).on("mouseleave",function(k){L._removeTooltip(k,this,p,o)}).call(function(k){p.noFormats||k.attr("opacity",function(N){return L._helpers.opacity(N,p,o)}).style("fill",function(N){return L._helpers.fill(N,p,o)}).style("stroke",function(N){return L._helpers.stroke(N,p,o)})}),T=p._handleTransition(v.merge(B),h,p,o).attr("x",function(k){return R?L._helpers.cx(k,p,o)-o.x.floatingBarWidth/2:L._helpers.x(k,p,o)}).attr("y",function(k){return M?L._helpers.cy(k,p,o)-o.y.floatingBarWidth/2:L._helpers.y(k,p,o)}).attr("width",function(k){return R?o.x.floatingBarWidth:L._helpers.width(k,p,o)}).attr("height",function(k){return M?o.y.floatingBarWidth:L._helpers.height(k,p,o)}).call(function(k){p.noFormats||k.attr("fill",function(N){return L._helpers.fill(N,p,o)}).attr("stroke",function(N){return L._helpers.stroke(N,p,o)})}),D=p._handleTransition(v.exit(),h,p,o).attr("x",function(k){var N=o.x._origin;return I==="x"?N=L._helpers.x(k,p,o):I==="both"&&(N=L._helpers.cx(k,p,o)),N}).attr("y",function(k){var N=o.y._origin;return I==="y"?N=L._helpers.y(k,p,o):I==="both"&&(N=L._helpers.cy(k,p,o)),N}).attr("width",function(k){return I==="x"?L._helpers.width(k,p,o):0}).attr("height",function(k){return I==="y"?L._helpers.height(k,p,o):0}),L._postDrawHandling(o,T,D,h),o.shapes=o._group.selectAll("."+z.join("."))}};L.plot.bubble={stacked:!1,grouped:!1,supportedAxes:["x","y","z","c"],draw:function(p,o,h){var w=o._positionData,v=null,z=["dimple-series-"+p.series.indexOf(o),"dimple-bubble"],B,T,D;p._tooltipGroup&&p._tooltipGroup.remove(),o.shapes?v=o.shapes.data(w,function(R){return R.key}):v=o._group.selectAll("."+z.join(".")).data(w,function(R){return R.key}),B=v.enter().append("circle").attr("id",function(R){return L._createClass([R.key])}).attr("class",function(R){var M=[];return M=M.concat(R.aggField),M=M.concat(R.xField),M=M.concat(R.yField),M=M.concat(R.zField),z.join(" ")+" "+L._createClass(M)+" "+p.customClassList.bubbleSeries+" "+L._helpers.css(R,p)}).attr("cx",function(R){return o.x._hasCategories()?L._helpers.cx(R,p,o):o.x._previousOrigin}).attr("cy",function(R){return o.y._hasCategories()?L._helpers.cy(R,p,o):o.y._previousOrigin}).attr("r",0).on("mouseover",function(R){L._showPointTooltip(R,this,p,o)}).on("mouseleave",function(R){L._removeTooltip(R,this,p,o)}).call(function(R){p.noFormats||R.attr("opacity",function(M){return L._helpers.opacity(M,p,o)}).style("fill",function(M){return L._helpers.fill(M,p,o)}).style("stroke",function(M){return L._helpers.stroke(M,p,o)})}),T=p._handleTransition(v.merge(B),h,p,o).attr("cx",function(R){return L._helpers.cx(R,p,o)}).attr("cy",function(R){return L._helpers.cy(R,p,o)}).attr("r",function(R){return L._helpers.r(R,p,o)}).call(function(R){p.noFormats||R.attr("fill",function(M){return L._helpers.fill(M,p,o)}).attr("stroke",function(M){return L._helpers.stroke(M,p,o)})}),D=p._handleTransition(v.exit(),h,p,o).attr("r",0).attr("cx",function(R){return o.x._hasCategories()?L._helpers.cx(R,p,o):o.x._origin}).attr("cy",function(R){return o.y._hasCategories()?L._helpers.cy(R,p,o):o.y._origin}),L._postDrawHandling(o,T,D,h),o.shapes=o._group.selectAll("."+z.join("."))}};L.plot.line={stacked:!1,grouped:!0,supportedAxes:["x","y","c"],draw:function(p,o,h){var w=o._positionData,v=[],z=null,B="dimple-series-"+p.series.indexOf(o),T=o.x._hasCategories()||o.y._hasCategories()?0:1,D,R=!1,M,I,k,N,C,q,G,et,rt,vt,Ft=function(){return function(Nt,qt,ce,$t){pt.select(qt).style("opacity",1),L._showPointTooltip(Nt,qt,ce,$t)}},dt=function(Nt){return function(qt,ce,$t,Et){pt.select(ce).style("opacity",Et.lineMarkers||Nt.data.length<2?L._helpers.opacity(qt,$t,Et):0),L._removeTooltip(qt,ce,$t,Et)}},ut=function(Nt,qt){L._drawMarkers(Nt,p,o,h,B,R,Ft(),dt(Nt),qt)},Mt=function(Nt,qt){var ce;return o.interpolation==="step"&&o[Nt]._hasCategories()?(o.barGap=0,o.clusterBarGap=0,ce=L._helpers[Nt](qt,p,o)+(Nt==="y"?L._helpers.height(qt,p,o):0)):ce=L._helpers["c"+Nt](qt,p,o),parseFloat(ce.toFixed(1))},Gt=function(Nt,qt){var ce=pt.line().x(function($t){return o.x._hasCategories()||!qt?$t.x:o.x[qt]}).y(function($t){return o.y._hasCategories()||!qt?$t.y:o.y[qt]});return L._interpolate(ce,Nt),ce};for(D=o.interpolation==="step"?"step-after":o.interpolation,vt=L._getSeriesOrder(o.data||p.data,o),o.c&&(o.x._hasCategories()&&o.y._hasMeasure()||o.y._hasCategories()&&o.x._hasMeasure())&&(R=!0),M=0;M1&&(o.x._hasCategories()?v[M].points.push({x:2*v[M].points[v[M].points.length-1].x-v[M].points[v[M].points.length-2].x,y:v[M].points[v[M].points.length-1].y}):o.y._hasCategories()&&(v[M].points=[{x:v[M].points[0].x,y:2*v[M].points[0].y-v[M].points[1].y}].concat(v[M].points))),v&&v[M]&&v[M].points&&v[M].points.length===1&&v[M].points.push({x:v[M].points[0].x,y:v[M].points[0].y}),v[M].entry=Gt(D,"_previousOrigin")(v[M].points),v[M].update=Gt(D)(v[M].points),v[M].exit=Gt(D,"_origin")(v[M].points),v[M].color=p.getColor(v[M].key.length>0?v[M].key[v[M].key.length-1]:"All"),v[M].css=p.getClass(v[M].key.length>0?v[M].key[v[M].key.length-1]:"All")}p._tooltipGroup&&p._tooltipGroup.remove(),o.shapes?z=o.shapes.data(v,function(Nt){return Nt.key}):z=o._group.selectAll("."+B).data(v,function(Nt){return Nt.key}),G=z.enter().append("path").attr("id",function(Nt){return L._createClass([Nt.key])}).attr("class",function(Nt){return B+" dimple-line "+Nt.keyString+" "+p.customClassList.lineSeries+" "+Nt.css}).attr("d",function(Nt){return Nt.entry}).call(function(Nt){p.noFormats||Nt.attr("opacity",function(qt){return R?1:qt.color.opacity}).style("fill","none").style("stroke",function(qt){return R?"url(#"+L._createClass(["fill-line-gradient-"+qt.keyString])+")":qt.color.stroke}).style("stroke-width",o.lineWeight)}).each(function(Nt){Nt.markerData=Nt.data,ut(Nt,this)}),et=p._handleTransition(z.merge(G),h,p).attr("d",function(Nt){return Nt.update}).each(function(Nt){Nt.markerData=Nt.data,ut(Nt,this)}),rt=p._handleTransition(z.exit(),h,p).attr("d",function(Nt){return Nt.exit}).each(function(Nt){Nt.markerData=[],ut(Nt,this)}),L._postDrawHandling(o,et,rt,h),o.shapes=o._group.selectAll("."+B)}};L.plot.pie={stacked:!1,grouped:!1,supportedAxes:["x","y","c","z","p"],draw:function(p,o,h){var w=o._positionData,v=null,z=["dimple-series-"+p.series.indexOf(o),"dimple-pie"],B,T,D,R=function(q){var G;return o.x&&o.y?G=L._helpers.r(q,p,o):G=p._widthPixels()0?q.attrTween("d",N):q.attr("d",k),p.noFormats||q.attr("fill",function(G){return L._helpers.fill(G,p,o)}).attr("stroke",function(G){return L._helpers.stroke(G,p,o)})}).attr("transform",C(!1)),D=p._handleTransition(v.exit(),h,p,o).attr("transform",C(!0)).attr("d",k),L._postDrawHandling(o,T,D,h),o.shapes=o._group.selectAll("."+z.join("."))}};L._addGradient=function(p,o,h,w,v,z,B){var T=[].concat(p),D=v.svg.select("#"+L._createClass([o])),R=[],M=h.position+"Field",I=!0,k=[];w.forEach(function(N){R.indexOf(N[M])===-1&&N.aggField.join("_")===T.join("_")&&R.push(N[M])},this),R=R.sort(function(N,C){return h._scale(N)-h._scale(C)}),D.node()===null&&(I=!1,D=v.svg.append("defs").append("linearGradient").attr("id",L._createClass([o])).attr("gradientUnits","userSpaceOnUse").attr("x1",h.position==="x"?h._scale(R[0])+v._widthPixels()/R.length/2:0).attr("y1",h.position==="y"?h._scale(R[0])-v._heightPixels()/R.length/2:0).attr("x2",h.position==="x"?h._scale(R[R.length-1])+v._widthPixels()/R.length/2:0).attr("y2",h.position==="y"?h._scale(R[R.length-1])-v._heightPixels()/R.length/2:0)),R.forEach(function(N,C){var q={},G=0;for(G=0;G=65&&z<=90&&(B=v.toLowerCase()),B},p.length>0)for(o=0;o0?N.aggField[N.aggField.length-1]:"All");return h.x._hasCategories()&&(C=C.concat(N.xField)),h.y._hasCategories()&&(C=C.concat(N.yField)),L._createClass(C)+" "+M.join(" ")+" "+o.customClassList.lineMarker+" "+q}).on("mouseover",function(N){B(N,this,o,h)}).on("mouseleave",function(N){T(N,this,o,h)}).attr("cx",function(N){return h.x._hasCategories()?L._helpers.cx(N,o,h):h.x._previousOrigin}).attr("cy",function(N){return h.y._hasCategories()?L._helpers.cy(N,o,h):h.y._previousOrigin}).attr("r",0).attr("opacity",h.lineMarkers||p.data.length<2?p.color.opacity:0).call(function(N){o.noFormats||N.attr("fill","white").style("stroke-width",h.lineWeight).attr("stroke",function(C){return z?L._helpers.fill(C,o,h):p.color.stroke})}),o._handleTransition(R.merge(k),w,o).attr("cx",function(N){return L._helpers.cx(N,o,h)}).attr("cy",function(N){return L._helpers.cy(N,o,h)}).attr("r",2+h.lineWeight).attr("opacity",h.lineMarkers||p.data.length<2?p.color.opacity:0).call(function(N){o.noFormats||N.attr("fill","white").style("stroke-width",h.lineWeight).attr("stroke",function(C){return z?L._helpers.fill(C,o,h):p.color.stroke})}),I=o._handleTransition(R.exit(),w,o).attr("cx",function(N){return h.x._hasCategories()?L._helpers.cx(N,o,h):h.x._origin}).attr("cy",function(N){return h.y._hasCategories()?L._helpers.cy(N,o,h):h.y._origin}).attr("r",0),w===0?I.remove():I.each("end",function(){pt.select(this).remove()}),(h._markers===void 0||h._markers===null)&&(h._markers={}),h._markers[p.keyString]=R,L._drawMarkerBacks(p,o,h,w,v,D)};L._ease=function(p,o){if(p&&o&&Object.prototype.toString.call(o)==="[object String]"){switch(o){case"linear":o=pt.easeLinear;break;case"poly":o=pt.easePoly;break;case"quad":o=pt.easeQuad;break;case"cubic":o=pt.easeCubic;break;case"sin":o=pt.easeSin;break;case"exp":o=pt.easeExp;break;case"circle":o=pt.easeCircle;break;case"elastic":o=pt.easeElastic;break;case"back":o=pt.easeBack;break;case"bounce":o=pt.easeBounce;break}p.ease(o)}};L._getOrderedList=function(p,o,h){var w,v=[],z=[],B=[].concat(o),T=[].concat(o),D=[];return h!=null&&(D=D.concat(h)),D=D.concat({ordering:B,desc:!1}),D.forEach(function(R){var M,I=[],k=[];if(typeof R.ordering=="function"){if(p&&p.length>0)for(M in p[0])Object.prototype.hasOwnProperty.call(p[0],M)&&T.indexOf(M)===-1&&T.push(M)}else if(!(R.ordering instanceof Array))T.push(R.ordering);else{for(M=0;M0&&Object.prototype.hasOwnProperty.call(p[0],R.ordering[M])&&k.push(R.ordering[M]),I.push(R.ordering[M]);k.length>I.length/2?T.concat(k):R.values=I}},this),w=L._rollUp(p,B,T),D.length>=1&&(D.forEach(function(R){var M=R.desc===null||R.desc===void 0?!1:R.desc,I=R.ordering,k=[],N=function(q){var G=0,et;for(et=0;etG[0]&&(et=1),et};typeof I=="function"?v.push(function(q,G){return(M?-1:1)*I(q,G)}):R.values&&R.values.length>0?(R.values.forEach(function(q){k.push([].concat(q).join("|"))},this),v.push(function(q,G){var et="",rt="",vt,Ft,dt;for(dt=0;dt0&&(et+="|",rt+="|"),et+=q[B[dt]],rt+=G[B[dt]];return vt=k.indexOf(et),Ft=k.indexOf(rt),vt=vt<0?M?-1:k.length:vt,Ft=Ft<0?M?-1:k.length:Ft,(M?-1:1)*(vt-Ft)})):[].concat(R.ordering).forEach(function(q){v.push(function(G,et){var rt=0;return G[q]!==void 0&&et[q]!==void 0&&(rt=C([].concat(G[q]),[].concat(et[q]))),(M?-1:1)*rt})})}),w.sort(function(R,M){for(var I=0,k=0;I0&&(o.c!==null&&o.c!==void 0&&o.c._hasMeasure()&&h.push({ordering:o.c.measure,desc:!0}),o.x._hasMeasure()&&h.push({ordering:o.x.measure,desc:!0}),o.y._hasMeasure()&&h.push({ordering:o.y.measure,desc:!0}),v=L._getOrderedList(p,w,h)),v};L._getSeriesSortPredicate=function(p,o,h){return function(w,v){var z=0;return o.x._hasCategories()&&(z=L._helpers.cx(w,p,o)-L._helpers.cx(v,p,o)),z===0&&o.y._hasCategories()&&(z=L._helpers.cy(w,p,o)-L._helpers.cy(v,p,o)),z===0&&h&&(z=L._arrayIndexCompare(h,w.aggField,v.aggField)),z}};L._helpers={cx:function(p,o,h){var w=0;return h.x.measure!==null&&h.x.measure!==void 0?w=h.x._scale(p.cx):h.x._hasCategories()&&h.x.categoryFields.length>=2?w=h.x._scale(p.cx)+L._helpers.xGap(o,h)+(p.xOffset+.5)*((o._widthPixels()/h.x._max-2*L._helpers.xGap(o,h))*p.width):w=h.x._scale(p.cx)+o._widthPixels()/h.x._max/2,w},cy:function(p,o,h){var w=0;return h.y.measure!==null&&h.y.measure!==void 0?w=h.y._scale(p.cy):h.y.categoryFields!==null&&h.y.categoryFields!==void 0&&h.y.categoryFields.length>=2?w=h.y._scale(p.cy)-o._heightPixels()/h.y._max+L._helpers.yGap(o,h)+(p.yOffset+.5)*((o._heightPixels()/h.y._max-2*L._helpers.yGap(o,h))*p.height):w=h.y._scale(p.cy)-o._heightPixels()/h.y._max/2,w},r:function(p,o,h){var w=0,v=1;return h.z===null||h.z===void 0?w=!h.radius||h.radius==="auto"?5:h.radius:(h.radius&&h.radius!=="auto"&&h.radius>1&&(v=h.radius/h.z._scale(h.z._max)),h.z._hasMeasure()?w=h.z._scale(p.r)*v:w=h.z._scale(o._heightPixels()/100)*v),w},xGap:function(p,o){var h=0;return(o.x.measure===null||o.x.measure===void 0)&&o.barGap>0&&(h=p._widthPixels()/o.x._max*(o.barGap>.99?.99:o.barGap)/2),h},xClusterGap:function(p,o,h){var w=0;return h.x.categoryFields!==null&&h.x.categoryFields!==void 0&&h.x.categoryFields.length>=2&&h.clusterBarGap>0&&!h.x._hasMeasure()&&(w=p.width*(o._widthPixels()/h.x._max-L._helpers.xGap(o,h)*2)*(h.clusterBarGap>.99?.99:h.clusterBarGap)/2),w},yGap:function(p,o){var h=0;return(o.y.measure===null||o.y.measure===void 0)&&o.barGap>0&&(h=p._heightPixels()/o.y._max*(o.barGap>.99?.99:o.barGap)/2),h},yClusterGap:function(p,o,h){var w=0;return h.y.categoryFields!==null&&h.y.categoryFields!==void 0&&h.y.categoryFields.length>=2&&h.clusterBarGap>0&&!h.y._hasMeasure()&&(w=p.height*(o._heightPixels()/h.y._max-L._helpers.yGap(o,h)*2)*(h.clusterBarGap>.99?.99:h.clusterBarGap)/2),w},x:function(p,o,h){var w=0;return h.x._hasTimeField()?w=h.x._scale(p.x)-L._helpers.width(p,o,h)/2:h.x.measure!==null&&h.x.measure!==void 0?w=h.x._scale(p.x):w=h.x._scale(p.x)+L._helpers.xGap(o,h)+p.xOffset*(L._helpers.width(p,o,h)+2*L._helpers.xClusterGap(p,o,h))+L._helpers.xClusterGap(p,o,h),w},y:function(p,o,h){var w=0;return h.y._hasTimeField()?w=h.y._scale(p.y)-L._helpers.height(p,o,h)/2:h.y.measure!==null&&h.y.measure!==void 0?w=h.y._scale(p.y):w=h.y._scale(p.y)-o._heightPixels()/h.y._max+L._helpers.yGap(o,h)+p.yOffset*(L._helpers.height(p,o,h)+2*L._helpers.yClusterGap(p,o,h))+L._helpers.yClusterGap(p,o,h),w},width:function(p,o,h){var w=0;return h.x.measure!==null&&h.x.measure!==void 0?w=Math.abs(h.x._scale(p.x<0?p.x-p.width:p.x+p.width)-h.x._scale(p.x)):h.x._hasTimeField()?w=h.x.floatingBarWidth:w=p.width*(o._widthPixels()/h.x._max-L._helpers.xGap(o,h)*2)-L._helpers.xClusterGap(p,o,h)*2,w},height:function(p,o,h){var w=0;return h.y._hasTimeField()?w=h.y.floatingBarWidth:h.y.measure!==null&&h.y.measure!==void 0?w=Math.abs(h.y._scale(p.y)-h.y._scale(p.y<=0?p.y+p.height:p.y-p.height)):w=p.height*(o._heightPixels()/h.y._max-L._helpers.yGap(o,h)*2)-L._helpers.yClusterGap(p,o,h)*2,w},opacity:function(p,o,h){var w=0;return h.c!==null&&h.c!==void 0?w=p.opacity:w=o.getColor(p.aggField.slice(-1)[0]).opacity,w},fill:function(p,o,h){var w=0;return h.c!==null&&h.c!==void 0?w=p.fill:w=o.getColor(p.aggField.slice(-1)[0]).fill,w},stroke:function(p,o,h){var w=0;return h.c!==null&&h.c!==void 0?w=p.stroke:w=o.getColor(p.aggField.slice(-1)[0]).stroke,w},css:function(p,o){return o.getClass(p.aggField.slice(-1)[0])}};L._interpolate=function(p,o){if(p&&o){if(Object.prototype.toString.call(o)==="[object String]")switch(o){case"linear":o=pt.curveLinear;break;case"linear-closed":o=pt.curveLinearClosed;break;case"step":o=pt.curveStep;break;case"step-before":o=pt.curveStepBefore;break;case"step-after":o=pt.curveStepAfter;break;case"basis":o=pt.curveBasis;break;case"basis-open":o=pt.curveBasisOpen;break;case"basis-closed":o=pt.curveBasisClosed;break;case"bundle":o=pt.curveBundle;break;case"cardinal":o=pt.curveCardinal;break;case"cardinal-open":o=pt.curveCardinalOpen;break;case"cardinal-closed":o=pt.curveCardinalClosed;break;case"monotone":o=pt.curveMonotoneX;break}p.curve(o)}};L._parentHeight=function(p){var o=p.getBoundingClientRect().height;return(!o||o<0)&&(o=p.clientHeight),o};L._parentWidth=function(p){var o=p.getBoundingClientRect().width;return(!o||o<0)&&(o=p.clientWidth),o};L._parsePosition=function(p,o){var h=0,w;return p&&(w=p.toString().split(","),w.forEach(function(v){v&&(isNaN(v)?v.slice(-1)==="%"?h+=o*(parseFloat(v.slice(0,v.length-1))/100):v.slice(-2)==="px"?h+=parseFloat(v.slice(0,v.length-2)):h=p:h+=parseFloat(v))},this)),h<0&&(h=o+h),h};L._parseXPosition=function(p,o){return L._parsePosition(p,L._parentWidth(o))};L._parseYPosition=function(p,o){return L._parsePosition(p,L._parentHeight(o))};L._postDrawHandling=function(p,o,h,w){w===0?(o.each(function(v,z){p.afterDraw&&p.afterDraw(this,v,z)}),h.remove()):(o.on("end",function(v,z){p.afterDraw&&p.afterDraw(this,v,z)}),h.call(function(){p.shapes&&p.shapes.exit().remove()}))};L._removeTooltip=function(p,o,h,w){h._tooltipGroup&&h._tooltipGroup.remove()};L._rollUp=function(p,o,h){var w=[];return o!=null?o=[].concat(o):o=[],p.forEach(function(v){var z=-1,B={},T=!0;w.forEach(function(D,R){z===-1&&(T=!0,o.forEach(function(M){T=T&&v[M]===D[M]},this),T&&(z=R))},this),z!==-1?B=w[z]:(o.forEach(function(D){B[D]=v[D]},this),w.push(B),z=w.length-1),h.forEach(function(D){o.indexOf(D)===-1&&(B[D]===void 0&&(B[D]=[]),B[D]=B[D].concat(v[D]))},this),w[z]=B},this),w};L._showBarTooltip=function(p,o,h,w){var v=5,z=10,B=750,T=pt.select(o),D=T.node().getBBox().x,R=T.node().getBBox().y,M=T.node().getBBox().width,I=T.node().getBBox().height,k=T.attr("opacity"),N=T.attr("fill"),C=w._dropLineOrigin(),q=pt.rgb(pt.rgb(N).r+.6*(255-pt.rgb(N).r),pt.rgb(N).g+.6*(255-pt.rgb(N).g),pt.rgb(N).b+.6*(255-pt.rgb(N).b)),G=pt.rgb(pt.rgb(N).r+.8*(255-pt.rgb(N).r),pt.rgb(N).g+.8*(255-pt.rgb(N).g),pt.rgb(N).b+.8*(255-pt.rgb(N).b)),et,rt,vt=w.getTooltipText(p),Ft=0,dt=0,ut=0,Mt,Gt,Nt,qt,ce=function($t,Et){var ee=T.node().getCTM(),le=h.svg.node().createSVGPoint();return le.x=$t||0,le.y=Et||0,le.matrixTransform(ee)};h._tooltipGroup!==null&&h._tooltipGroup!==void 0&&h._tooltipGroup.remove(),h._tooltipGroup=h.svg.append("g"),w.p||(qt=w._isStacked()?1:M/2,!w.x._hasCategories()&&C.y!==null&&h._tooltipGroup.append("line").attr("class","dimple-tooltip-dropline "+h.customClassList.tooltipDropLine).attr("x1",Ddt?this.getBBox().width:dt,ut=this.getBBox().width>ut?this.getBBox().height:ut}),et.selectAll("text").attr("x",0).attr("y",function(){return Ft+=this.getBBox().height,Ft-this.getBBox().height/2}),rt.attr("x",-v).attr("y",-v).attr("height",Math.floor(Ft+v)-.5).attr("width",dt+2*v).attr("rx",5).attr("ry",5).call(function($t){h.noFormats||$t.style("fill",G).style("stroke",q).style("stroke-width",2).style("opacity",.95)}),ce(D+M+v+z+dt).x0?(Mt=D-(v+z+dt),Gt=R+I/2-(Ft-(ut-v))/2):ce(0,R+I+Ft+z+v).y0?Mt:z,Mt=Mt+dt0?Mt:z,Mt=Mt+dtet?this.getBBox().width:et,rt=this.getBBox().width>rt?this.getBBox().height:rt}),vt.selectAll("text").attr("x",0).attr("y",function(){return G+=this.getBBox().height,G-this.getBBox().height/2}),Ft.attr("x",-v).attr("y",-v).attr("height",Math.floor(G+v)-.5).attr("width",et+2*v).attr("rx",5).attr("ry",5).call(function(Gt){h.noFormats||Gt.style("fill",q).style("stroke",C).style("stroke-width",2).style("opacity",.95)}),D+M+v+z+et0?(ut=D-M-(v+z+et),Mt=R-(G-(rt-v))/2):R+M+G+z+v0?ut:z,ut=ut+et0?ut:z,ut=ut+et-1)&&w.push(v)},this)),w};L.getUniqueValues=function(p,o){var h=[];return o!=null&&(o=[].concat(o),p.forEach(function(w){var v="";o.forEach(function(z,B){B>0&&(v+="/"),v+=w[z]},this),h.indexOf(v)===-1&&h.push(v)},this)),h};L.newSvg=function(p,o,h){var w=null;if(p==null&&(p="body"),w=pt.select(p),w.empty())throw"The '"+p+"' selector did not match any elements. Please prefix with '#' to select by id or '.' to select by class";return w.append("svg").attr("width",o).attr("height",h)};const hi=(p,o,h)=>{(p==null||p===void 0)&&(p="body");const w=pt.select(p);if(w.empty())throw"The '"+p+"' selector did not match any elements. Please prefix with '#' to select by id or '.' to select by class";return w.append("svg").attr("width",o).attr("height",h)},vc=p=>{if(typeof window<"u"){const{pptx:I,resultElement:k,thumbElement:N,onError:C,onLoad:q}=p,G=document.createElement("div");G.setAttribute("class","r-preview-pptx-main"),k.innerHTML="",k.appendChild(G);let et=!1;return new Promise((rt,vt)=>{const Ft=ut=>{if(et)return;const Mt=document.createElement("div"),Gt=document.createElement("style");switch(ut.type){case"slide":Mt.innerHTML=ut.data,G.appendChild(Mt);break;case"pptx-thumb":N&&(N==null||N.setAttribute("src",`data:image/jpeg;base64,${ut.data}`));break;case"slideSize":break;case"globalCSS":Gt.innerHTML=ut.data,G.appendChild(Gt);break;case"Done":et=!0,o(ut.data.charts),q&&q({success:!0,data:ut}),rt(ut.data.time);break;case"WARN":console.warn("PPTX processing warning: ",ut.data);break;case"ERROR":et=!0,console.error("PPTX processing error: ",ut.data),C&&C({success:!1,data:ut}),vt(new Error(ut.data));break}},dt={postMessage};mc(ut=>{dt.postMessage=ut},Ft),dt.postMessage({type:"processPPTX",data:I})}).then(rt=>{const vt=()=>{const Ft=Math.max(...Array.from(G.children).filter(ut=>ut.nodeName==="section").map(ut=>ut.offsetWidth)),dt=G.children[0].offsetWidth;G.setAttribute("style",`transform: scale(${dt/Ft}),transform-origin': 'top left'`)};return vt(),window.addEventListener("resize",vt),z(document.getElementsByClassName("block")),z(document.getElementsByTagName("td")),rt})}function o(I){for(let k=0;k{const et=q.key;C[G]=q.key,q.values.forEach((rt,vt)=>{const Ft=q.xlabels[vt];N[vt]=q.xlabels[vt],k.push({name:Ft,group:et,value:rt.y})})}),{data:k,xLabels:N,groupLabels:C}}function w(I){const k=I.chartID,N=I.chartType,C=I.chartData;let q=[];switch(N){case"lineChart":{const{data:G,xLabels:et,groupLabels:rt}=h(C);q=G;const vt=document.getElementById(k)||document.body,Ft=vt&&hi(`#${k}`,vt.style.width,vt.style.height),dt=new L.chart(Ft,q),ut=dt.addCategoryAxis("x","name");ut.addOrderRule(et),ut.addGroupOrderRule(rt),ut.title=null;const Mt=dt.addMeasureAxis("y","value");Mt.title=null,dt.addSeries("group",L.plot.line),dt.addLegend(60,10,500,20,"right"),dt.draw();break}case"barChart":{const{data:G,xLabels:et,groupLabels:rt}=h(C);q=G;const vt=document.getElementById(k)||document.body,Ft=hi("#"+k,vt.style.width,vt.style.height),dt=new L.chart(Ft,q),ut=dt.addCategoryAxis("x",["name","group"]);ut.addOrderRule(et),ut.addGroupOrderRule(rt),ut.title=null;const Mt=dt.addMeasureAxis("y","value");Mt.title=null,dt.addSeries("group",L.plot.bar),dt.addLegend(60,10,500,20,"right"),dt.draw();break}case"pieChart":case"pie3DChart":{const{data:G,groupLabels:et}=h(C);q=G;const rt=document.getElementById(k)||document.body,vt=hi(`#${k}`,rt.style.width,rt.style.height),Ft=new L.chart(vt,q);Ft.addMeasureAxis("p","value").addOrderRule(et),Ft.addSeries("name",L.plot.pie),Ft.addLegend(50,20,400,300,"left"),Ft.draw();break}case"areaChart":{const{data:G,xLabels:et,groupLabels:rt}=h(C);q=G;const vt=document.getElementById(k)||document.body,Ft=hi("#"+k,vt.style.width,vt.style.height),dt=new L.chart(Ft,q),ut=dt.addCategoryAxis("x","name");ut.addOrderRule(et),ut.addGroupOrderRule(rt),ut.title=null;const Mt=dt.addMeasureAxis("y","value");Mt.title=null,dt.addSeries("group",L.plot.area),dt.addLegend(60,10,500,20,"right"),dt.draw();break}case"scatterChart":{for(let G=0;G{q.forEach(G=>{G.children.length>0&&C(Array.from(G.children)),Array.from(G.classList).includes(k)&&N.push(G)})};return I.children.length>0&&C(Array.from(I.children)),N}function z(I){const k=Array.from(I);for(let N=0;N0){let q="",G="",et=0;const rt=[];let vt=0;const Ft=[];for(let dt=0;dtNumber(G)?(q=ut,G=Mt,vt++,rt[vt]=et,Ft[vt]=ut,et=1):ut!==q&&Number(Mt){const q=C[0];if(parseInt(q.toString())>0)for(;k>=Number(q);k-=Number(q))N+=C[1];else N=N.replace(q.toString(),C[1])}),N}}}function M(I,k){I=Number(I)-1;let N="";return k==="upperCase"?N=((I/26>=1?String.fromCharCode(I/26+64):"")+String.fromCharCode(I%26+65)).toUpperCase():k==="lowerCase"&&(N=((I/26>=1?String.fromCharCode(I/26+64):"")+String.fromCharCode(I%26+65)).toLowerCase()),N}};export{vc as renderPptx}; diff --git a/assets/chunks/index.CBA5mFK_.js b/assets/chunks/index.CBA5mFK_.js new file mode 100644 index 0000000000..dc4baad08d --- /dev/null +++ b/assets/chunks/index.CBA5mFK_.js @@ -0,0 +1,44 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/chunks/index-Co9E57uv.BBrTYzuH.js","assets/chunks/framework.C-ai2y4t.js","assets/chunks/colz-DJZvo_8B.DBiU5Tau.js","assets/chunks/docx-VUApAnRr.Cl4GUa7G.js","assets/chunks/jszip.min-BIf20mgf.BsDI-Ugu.js","assets/chunks/commonjs-dynamic-modules-DLbDWi6a.CRNIONdy.js","assets/chunks/pdf-Cx0VWKFo.BP4nEulL.js","assets/chunks/index-Ba501-HG.DsTDD0-N.js"])))=>i.map(i=>d[i]); +import{ag as V}from"./framework.C-ai2y4t.js";var ed=Object.defineProperty,td=(k,h,p)=>h in k?ed(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,be=(k,h,p)=>td(k,typeof h!="symbol"?h+"":h,p);const Yo=()=>{},dn=()=>{if(typeof window<"u"){const k=navigator.userAgent.toLowerCase();return/ipad|ipod/.test(k)?"ipad":/android/.test(k)?"android":/iphone/.test(k)?"iphone":"pc"}return"pc"},jo=typeof window<"u",_t=()=>{if(!jo)return!1;const k=window.navigator.userAgent;return!!/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(k)},$=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298];class U{constructor(h,p){be(this,"highOrder"),be(this,"lowOrder"),this.highOrder=h,this.lowOrder=p}}new U($[0],3609767458),new U($[1],602891725),new U($[2],3964484399),new U($[3],2173295548),new U($[4],4081628472),new U($[5],3053834265),new U($[6],2937671579),new U($[7],3664609560),new U($[8],2734883394),new U($[9],1164996542),new U($[10],1323610764),new U($[11],3590304994),new U($[12],4068182383),new U($[13],991336113),new U($[14],633803317),new U($[15],3479774868),new U($[16],2666613458),new U($[17],944711139),new U($[18],2341262773),new U($[19],2007800933),new U($[20],1495990901),new U($[21],1856431235),new U($[22],3175218132),new U($[23],2198950837),new U($[24],3999719339),new U($[25],766784016),new U($[26],2566594879),new U($[27],3203337956),new U($[28],1034457026),new U($[29],2466948901),new U($[30],3758326383),new U($[31],168717936),new U($[32],1188179964),new U($[33],1546045734),new U($[34],1522805485),new U($[35],2643833823),new U($[36],2343527390),new U($[37],1014477480),new U($[38],1206759142),new U($[39],344077627),new U($[40],1290863460),new U($[41],3158454273),new U($[42],3505952657),new U($[43],106217008),new U($[44],3606008344),new U($[45],1432725776),new U($[46],1467031594),new U($[47],851169720),new U($[48],3100823752),new U($[49],1363258195),new U($[50],3750685593),new U($[51],3785050280),new U($[52],3318307427),new U($[53],3812723403),new U($[54],2003034995),new U($[55],3602036899),new U($[56],1575990012),new U($[57],1125592928),new U($[58],2716904306),new U($[59],442776044),new U($[60],593698344),new U($[61],3733110249),new U($[62],2999351573),new U($[63],3815920427),new U(3391569614,3928383900),new U(3515267271,566280711),new U(3940187606,3454069534),new U(4118630271,4000239992),new U(116418474,1914138554),new U(174292421,2731055270),new U(289380356,3203993006),new U(460393269,320620315),new U(685471733,587496836),new U(852142971,1086792851),new U(1017036298,365543100),new U(1126000580,2618297676),new U(1288033470,3409855158),new U(1501505948,4234509866),new U(1607167915,987167468),new U(1816402316,1246189591);new U(0,1),new U(0,32898),new U(2147483648,32906),new U(2147483648,2147516416),new U(0,32907),new U(0,2147483649),new U(2147483648,2147516545),new U(2147483648,32777),new U(0,138),new U(0,136),new U(0,2147516425),new U(0,2147483658),new U(0,2147516555),new U(2147483648,139),new U(2147483648,32905),new U(2147483648,32771),new U(2147483648,32770),new U(2147483648,128),new U(0,32778),new U(2147483648,2147483658),new U(2147483648,2147516545),new U(2147483648,32896),new U(0,2147483649),new U(2147483648,2147516424);function Et(k){return k<10?`0${k}`:k}function id(k){let h=new Date;return k&&(h=new Date(k)),h.format=(p="YYYY-MM-DD HH:mm:ss")=>{const f=h.getFullYear(),w=Et(h.getMonth()+1),x=Et(h.getDate()),T=Et(h.getHours()),D=Et(h.getMinutes()),G=Et(h.getSeconds());return p.replace(/Y+/gi,`${f}`).replace(/M+/g,`${w}`).replace(/D+/gi,`${x}`).replace(/H+/gi,`${T}`).replace(/m+/g,`${D}`).replace(/S+/gi,`${G}`)},h}const vi=k=>{if(k===0)return"00:00";if(!k)return"";const h=Math.trunc(k/3600),p=Math.trunc(k%3600/60),f=Et(Math.trunc(k-h*3600-p*60));return h===0?`${Et(p)}:${f}`:`${Et(h)}:${Et(p)}:${f}`},Zt=k=>{const h=k.backingStorePixelRatio||k.webkitBackingStorePixelRatio||k.mozBackingStorePixelRatio||k.msBackingStorePixelRatio||k.oBackingStorePixelRatio||1;return(jo&&window.devicePixelRatio||1)/h},Re=(k,h)=>{if(typeof document>"u")return;const p=k.classList;p.contains(h)||p.add(h)},Ve=(k,h)=>{if(typeof document>"u")return;const p=k.classList;p.contains(h)&&p.remove(h)},rt=k=>{if(typeof document>"u")return;const h=document.createDocumentFragment();return k.forEach(p=>h.appendChild(p)),h},rd="http://www.w3.org/2000/svg",nd=["svg","path","g","circle","rect","line","polyline","polygon","ellipse","text","tspan","textPath","defs","marker","radialGradient","stop","linearGradient","clipPath","mask","pattern","image","use","symbol","foreignObject","feGaussianBlur","feColorMatrix"];class An{constructor(h,p){be(this,"listener"),be(this,"element"),be(this,"create",(f,w)=>nd.includes(f)?document.createElementNS(rd,f,w):document.createElement(f,w)),be(this,"setAttribute",(f,w)=>(this.element.setAttribute(f,w),this)),be(this,"removeAttribute",f=>(this.element.removeAttribute(f),this)),be(this,"append",f=>(this.element.appendChild(f),this)),be(this,"remove",f=>(this.element.removeChild(f),this)),be(this,"setTextContent",f=>(this.element.textContent=f,this)),be(this,"setStyle",(f,w)=>(this.element.style.setProperty(f,w),this)),be(this,"addElementByType",(f,w)=>{f instanceof An&&w.appendChild(f.element),f instanceof HTMLElement&&w.appendChild(f)}),be(this,"addChild",f=>{if(Array.isArray(f)){const w=document.createDocumentFragment();f.forEach(x=>{this.addElementByType(x,w)}),this.element.appendChild(w)}else this.addElementByType(f,this.element);return this}),be(this,"listen",(f,w,x)=>{let T=this.listener.get(f);T||(T=new Map,this.listener.set(f,T));const D=T.get(w.name);return D===w&&console.warn(`${D.name} listener has been added to ${f} event, please remove it first.`),this.element.addEventListener(f,w,x),T.set(w.name,w),this}),be(this,"clearListener",(f,w,x)=>{this.element.removeEventListener(f,w,x);const T=this.listener.get(f);return T?T.delete(w.name):console.warn(`No ${f} event listener has been added.`),this}),be(this,"clearAllListener",()=>{for(const[f,w]of this.listener){for(const[x,T]of w)this.element.removeEventListener(f,T),w.delete(x);this.listener.delete(f)}return this}),this.element=this.create(h,p),this.listener=new Map}}const z=(k,h)=>new An(k,h),Zi=()=>{let k;return function(h,p=300){return function(...f){k&&(clearTimeout(k),k=void 0);const w=this;k||(k=setTimeout(()=>{h.apply(w,f),clearTimeout(k),k=void 0},p))}}},on=new Map([[100,"Continue"],[101,"Switching Protocols"],[102,"Processing"],[103,"Early Hints"],[200,"OK"],[201,"Created"],[202,"Accepted"],[203,"Non-Authoritative Information"],[204,"No Content"],[205,"Reset Content"],[206,"Partial Content"],[207,"Multi-Status"],[208,"Already Reported"],[226,"IM Used"],[300,"Multiple Choices"],[301,"Moved Permanently"],[302,"Found"],[303,"See Other"],[304,"Not Modified"],[305,"Use Proxy"],[307,"Temporary Redirect"],[308,"Permanent Redirect"],[400,"Bad Request"],[401,"Unauthorized"],[402,"Payment Required"],[403,"Forbidden"],[404,"Not Found"],[405,"Method Not Allowed"],[406,"Not Acceptable"],[407,"Proxy Authentication Required"],[408,"Request Timeout"],[409,"Conflict"],[410,"Gone"],[411,"Length Required"],[412,"Precondition Failed"],[413,"Payload Too Large"],[414,"URI Too Long"],[415,"Unsupported Media Type"],[416,"Range Not Satisfiable"],[417,"Expectation Failed"],[418,"I'm a Teapot"],[421,"Misdirected Request"],[422,"Unprocessable Entity"],[423,"Locked"],[424,"Failed Dependency"],[425,"Too Early"],[426,"Upgrade Required"],[428,"Precondition Required"],[429,"Too Many Requests"],[431,"Request Header Fields Too Large"],[451,"Unavailable For Legal Reasons"],[500,"Internal Server Error"],[501,"Not Implemented"],[502,"Bad Gateway"],[503,"Service Unavailable"],[504,"Gateway Timeout"],[505,"HTTP Version Not Supported"],[506,"Variant Also Negotiates"],[507,"Insufficient Storage"],[508,"Loop Detected"],[509,"Bandwidth Limit Exceeded"],[510,"Not Extended"],[511,"Network Authentication Required"]]);ad(on),od(on);function ad(k){const h=new Map;for(const[p,f]of k)h.set(f.toLowerCase(),p);return h}function od(k){const h=[];for(const[p,f]of k)h.push(p);return h}const Qi=(k="")=>{if(k.length===0)return 0;if(k.endsWith("%")){const h=Number(k.replace("%",""));return h>1?h/100:h}else return Number(k)},At=(k,h=0,p=1)=>Math.min(p,Math.max(h,k)),ft=class{constructor(){be(this,"getDecimalLength",h=>{const[p,f]=h.toString().split(".");return f?f.length:0}),be(this,"amend",(h,p=15)=>parseFloat(Number(h).toPrecision(p))),be(this,"power",(h,p)=>Math.pow(10,Math.max(this.getDecimalLength(h),this.getDecimalLength(p))))}};be(ft,"handleMethod",(k,h)=>{const p=new ft,{power:f,amend:w}=p,x=f(k,h),T=w(k*x),D=w(h*x);return G=>{switch(G){case"+":return(T+D)/x;case"-":return(T-D)/x;case"*":return T*D/(x*x);case"/":return T/D}}});be(ft,"add",(k,h)=>ft.handleMethod(k,h)("+"));be(ft,"divide",(k,h)=>ft.handleMethod(k,h)("/"));be(ft,"multiply",(k,h)=>ft.handleMethod(k,h)("*"));be(ft,"subtract",(k,h)=>ft.handleMethod(k,h)("-"));const wo="NEW_LISTENER";class qo{constructor(){be(this,"_events"),be(this,"tap",(h,p)=>{this._events[h]&&h!==Symbol.for(wo)&&this.call(Symbol.for(wo),h);const f=this._events[h]||[];return typeof p=="function"?f.push({name:h,callback:p}):f.push(p),this._events[h]=f,this}),be(this,"call",(h,...p)=>{(this._events[h]||[]).forEach(w=>{const{callback:x}=w;x(...p)})}),be(this,"callSync",async(h,...p)=>{const f=this._events[h]||[];for(const w of f){const{callback:x}=w;await x(...p)}}),be(this,"once",(h,p)=>{let f;if(typeof p=="function")f={name:h,callback:(...w)=>{p(...w),this.off(h,f)},initialCallback:p};else{const{callback:w}=p;f={name:h,callback:(...x)=>{w(...x),this.off(h,f)},initialCallback:w}}return this.tap(h,f),this}),be(this,"off",(h,p)=>{const w=(this._events[h]||[]).filter(x=>{if(typeof p=="function")return x.callback!==p&&x.initialCallback!==p;{const{callback:T}=p;return x.callback!==T&&x.initialCallback!==T}});return this._events[h]=w,this}),this._events={}}}const sd={success:!0,_identification:!0,data:` + +`},ld=Object.freeze(Object.defineProperty({__proto__:null,default:sd},Symbol.toStringTag,{value:"Module"})),cn=Object.freeze(Object.defineProperty({__proto__:null,S:qo,a:Re,b:dn,c:z,d:rt,e:At,f:Zi,g:Zt,h:id,i:_t,j:ld,n:Yo,p:Qi,r:Ve,t:vi},Symbol.toStringTag,{value:"Module"}));var dd=Object.defineProperty,cd=(k,h,p)=>h in k?dd(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,hd=(k,h,p)=>cd(k,h+"",p);const nt=[!1,"false",null,void 0],Ce=k=>{const h=k.hasAttribute("disabled"),p=k.getAttribute("disabled");return!!(h&&!nt.includes(p))},ud=(k,h)=>{const p=k.querySelectorAll(`.${h}`);p.length>0&&p.forEach(f=>f.classList.remove(h))},ru=k=>new Promise((h,p)=>{const f=document.createElement("script");f.src=k,f.onload=function(){h({success:!0})},f.onerror=function(w){p({success:!1,error:w})},document.body.append(f)});function Ie(k=""){return class{constructor(p=k){hd(this,"message"),this.message=p}}}const Fe=()=>typeof document<"u"?HTMLElement:null,Jt=(k,h)=>{const p={value:k,subscribers:new Set,comparator:h==null?void 0:h.equals},{subscriber:f}=h||{};f&&Array.isArray(f)&&f.forEach(D=>{typeof D=="function"&&!p.subscribers.has(D)&&p.subscribers.add(D)});const w=()=>p.value,x=D=>{p.value!==D&&(p.value=D,p.subscribers.forEach(G=>G(D)))};return[w,D=>{const{comparator:G}=p;if(G instanceof Function)return!G(p.value,D)&&x(D);G===void 0?p.value!==D&&x(D):!G&&x(D)}]};var fd=Object.defineProperty,pd=(k,h,p)=>h in k?fd(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,it=(k,h,p)=>pd(k,typeof h!="symbol"?h+"":h,p);const gd='.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}:host{position:var(--ran-btn-position, relative);display:var(--ran-btn-display, inline-block);background-image:var(--ran-btn-background-image, none);box-shadow:var(--ran-btn-box-shadow, 0 2px #00000004);cursor:var(--ran-btn-cursor, pointer);-webkit-user-select:var(--ran-btn-user-select, none);user-select:var(--ran-btn-user-select, none);touch-action:var(--ran-btn-touch-action, manipulation);overflow:var(--ran-btn-overflow, hidden);pointer-events:var(--ran-btn-pointer-events, auto)}:host .ran-btn{position:var(--ran-btn-contain-position, relative);display:var(--ran-btn-contain-display, inline-block);background-image:var(--ran-btn-contain-background-image, none);cursor:var(--ran-btn-contain-cursor, pointer);transition:var(--ran-btn-contain-transition, all .3s cubic-bezier(.645, .045, .355, 1));-webkit-user-select:var(--ran-btn-contain-user-select, none);user-select:var(--ran-btn-contain-user-select, none);touch-action:var(--ran-btn-contain-touch-action, manipulation);background:var(--ran-btn-contain-background, #fff)}:host,:host(:active),:host(:focus){outline:0;-webkit-tap-highlight-color:transparent}:host .ran-btn,:host(:active) .ran-btn,:host(:focus) .ran-btn{outline:var(--ran-btn-contain-outline, 0)}:host([type="primary"]) .ran-btn-content{background-color:var(--ran-btn-content-background-color, #1890ff);border-color:var(--ran-btn-content-border-color, #1890ff);color:var(--ran-btn-content-color, #fff)}:host([type="primary"]:not([disabled])) .ran-btn:after{background-image:var(--ran-btn-after-background-image, radial-gradient(circle, #fff 10%, transparent 10.01%))}@media (min-width: 1024px){:host(:not([disabled]):hover) .ran-btn-content{border-color:var(--ran-btn-content-hover-border-color, #1890ff);color:var(--ran-btn-content-hover-color, #1890ff)}:host([type="primary"]:not([disabled]):hover) .ran-btn-content{background-color:var(--ran-btn-content-hover-background-color, #40a9ff);color:var(--ran-btn-content-hover-color, #fff)}:host([type="warning"]:not([disabled]):hover) .ran-btn-content{border-color:var(--ran-btn-content-warning-border-color, #ff4d4f);background-color:var(--ran-btn-content-warning-background-color, #ff4d4f);color:var(--ran-btn-content-warning-color, #fff)}}:host([type="warning"]) .ran-btn-content{border-color:var(--ran-btn-content-warning-border-color, #ff4d4f);background-color:var(--ran-btn-content-warning-background-color, #ff4d4f);color:var(--ran-btn-content-warning-color, #fff)}:host([type="warning"]:not([disabled])) .ran-btn:after{background-image:var(--ran-btn-after-background-image, radial-gradient(circle, #fff 10%, transparent 10.01%))}:host([type="text"]) .ran-btn-content{border:var(--ran-btn-content-text-border, none)}:host([disabled]){cursor:var(--ran-btn-disabled-cursor, not-allowed);pointer-events:var(--ran-btn-disabled-pointer-events, all);opacity:var(--ran-btn-disabled-opacity, .6)}:host([disabled]) .ran-btn{cursor:var(--ran-btn-disabled-container-cursor, not-allowed);pointer-events:var(--ran-btn-disabled-container-pointer-events, all);opacity:var(--ran-btn-disabled-container-opacity, .6)}:host(:not([disabled]):active) .ran-btn:after{transform:var(--ran-btn-after-transform, translate(-50%, -50%) scale(0));opacity:var(--ran-btn-after-opacity, .3);transition:var(--ran-btn-after-transition, 0s)}@media (min-width: 1024px){:host(:not([disabled],[effect])) .ran-btn:after{content:"";display:block;position:absolute;width:100%;height:100%;left:var(--ran-x, 0);top:var(--ran-y, 0);pointer-events:none;background-image:radial-gradient(circle,#1890ff 10%,transparent 10.01%);background-repeat:no-repeat;background-position:50%;transform:translate(-50%,-50%) scale(10);opacity:0;transition:transform .3s,opacity .8s}}:host .slot{display:var(--ran-btn-slot-display, block)}.ran-btn-content{display:var(--ran-btn-content-display, flex);justify-content:var(--ran-btn-content-display, space-between);align-items:var(--ran-btn-content-align-items, center);padding:var(--ran-btn-content-padding, 4px 15px);border:var(--ran-btn-content-border, 1px solid transparent);border-radius:var(--ran-btn-content-border-radius, 2px);border-color:var(--ran-btn-content-border-color, #d9d9d9);color:var(--ran-btn-content-color, #000000d9);line-height:var(--ran-btn-content-line-height, 22px);font-size:var(--ran-btn-content-font-size, 14px);font-weight:var(--ran-btn-content-font-weight, 400);white-space:var(--ran-btn-content-white-space, nowrap);text-align:var(--ran-btn-content-text-align, center)}.ran-btn-content .icon{margin-right:var(--ran-btn-icon-margin-right, 2px)}';class hn extends Fe(){constructor(){super(),it(this,"_btn"),it(this,"_btnContent"),it(this,"_iconElement"),it(this,"_slot"),it(this,"_shadowDom"),it(this,"debounceTimeId"),it(this,"setIcon",()=>{if(this.icon){const{width:f,height:w}=this._slot.getBoundingClientRect(),x=Math.min(f,w);this._iconElement?this._iconElement.setAttribute("name",this.icon):(this._iconElement=document.createElement("r-icon"),this._iconElement.setAttribute("name",this.icon),this._iconElement.setAttribute("color","currentColor"),this._iconElement.setAttribute("class","icon"),this._slot.insertAdjacentElement("beforebegin",this._iconElement)),this.iconSize?this._iconElement.setAttribute("size",this.iconSize):this._iconElement.setAttribute("size",`${x-5}`)}}),it(this,"mousedown",f=>{if(dn()==="pc"&&(!this.disabled||this.disabled==="false")){this.debounceMouseEvent();const{left:w,top:x}=this.getBoundingClientRect();this._btn.style.setProperty("--ran-x",f.clientX-w+"px"),this._btn.style.setProperty("--ran-y",f.clientY-x+"px")}}),it(this,"mouseup",f=>{dn()==="pc"&&(this.debounceTimeId||(this.debounceTimeId=setTimeout(()=>{this._btn.style.removeProperty("--ran-x"),this._btn.style.removeProperty("--ran-y"),this.debounceMouseEvent()},600)))}),it(this,"debounceMouseEvent",()=>{clearTimeout(this.debounceTimeId),this.debounceTimeId=void 0}),it(this,"handlerExternalCss",()=>{if(this.sheet)try{const f=new CSSStyleSheet;f.insertRule(this.sheet),this._shadowDom.adoptedStyleSheets=[f]}catch{console.error(`Failed to parse the rule in CSSStyleSheet: ${this.sheet}`)}}),this._slot=document.createElement("slot"),this._btnContent=document.createElement("div"),this._btn=document.createElement("div"),this._btn.setAttribute("class","ran-btn"),this._btn.setAttribute("part","ran-btn"),this._btnContent.setAttribute("class","ran-btn-content"),this._btnContent.setAttribute("part","ran-btn-content"),this._btnContent.appendChild(this._slot),this._slot.setAttribute("class","slot");const h=this.attachShadow({mode:"closed"}),p=document.createElement("style");p.textContent=gd,h.appendChild(p),this._shadowDom=h,this._btn.appendChild(this._btnContent),h.appendChild(this._btn)}static get observedAttributes(){return["disabled","icon","effect","iconSize","sheet"]}get sheet(){return this.getAttribute("sheet")||""}set sheet(h){this.setAttribute("sheet",h||"")}get disabled(){return Ce(this)}set disabled(h){!h||h==="false"?(this.removeAttribute("disabled"),this.removeAttribute("aria-disabled")):(this.setAttribute("disabled",""),this.setAttribute("aria-disabled","true"))}get iconSize(){return this.getAttribute("iconSize")||""}set iconSize(h){!h||h==="false"?this.removeAttribute("iconSize"):(this.setAttribute("iconSize",h),this.setIcon())}get icon(){return this.getAttribute("icon")||""}set icon(h){!h||h==="false"?this.removeAttribute("icon"):(this.setAttribute("icon",h),this.setIcon())}get effect(){return this.getAttribute("effect")||""}set effect(h){nt.includes(h)||!h?this.removeAttribute("effect"):this.setAttribute("effect",h)}connectedCallback(){this._btn.addEventListener("mousedown",this.mousedown),this._btn.addEventListener("mouseup",this.mouseup),this.handlerExternalCss(),this.setIcon(),this.setAttribute("role","button"),this.setAttribute("tabindex","0")}disconnectCallback(){this._btn.removeEventListener("mousedown",this.mousedown),this._btn.removeEventListener("mouseup",this.mouseup)}attributeChangedCallback(h,p,f){h==="disabled"&&this._btnContent&&(!f||f==="false"?this._btnContent.setAttribute("disabled",""):this._btnContent.removeAttribute("disabled")),h==="icon"&&this._btnContent&&p!==f&&this.setIcon(),h==="iconSize"&&this._btnContent&&p!==f&&this._btnContent.setAttribute("iconSize",f),h==="sheet"&&this._shadowDom&&p!==f&&this.handlerExternalCss()}}function md(){return typeof document<"u"&&!customElements.get("r-button")?(customElements.define("r-button",hn),hn):Ie("document is undefined or r-button is exist")}const vd=md(),bd=Object.freeze(Object.defineProperty({__proto__:null,Button:hn,default:vd},Symbol.toStringTag,{value:"Module"})),Xi=(k,h="text/xml")=>{if(window.DOMParser)return new window.DOMParser().parseFromString(k,h).documentElement;if(typeof window.ActiveXObject<"u"){const p=new window.ActiveXObject("Microsoft.XMLDOM");return p.async="false",p.loadXML(k),p}},Ji=(k,h,p)=>{const f=k[h];return f?typeof f=="function"?f():Promise.resolve(f):new Promise((w,x)=>{(typeof queueMicrotask=="function"?queueMicrotask:setTimeout)(x.bind(null,new Error("Unknown variable dynamic import: "+h+(h.split("/").length!==p?". Note that variables only represent file names one level deep.":""))))})},yd={success:!0,_identification:!0,data:` + + + + + +`},wd=Object.freeze(Object.defineProperty({__proto__:null,default:yd},Symbol.toStringTag,{value:"Module"})),un=Object.freeze(Object.defineProperty({__proto__:null,_:Ji,d:wd,s:Xi},Symbol.toStringTag,{value:"Module"}));var Ed=Object.defineProperty,Ad=(k,h,p)=>h in k?Ed(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,Oe=(k,h,p)=>Ad(k,typeof h!="symbol"?h+"":h,p);const _d=".remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}:host{display:var(--ran-icon-host-display, inline-flex)}:host([spin]){animation-name:var(--ran-icon-host-spin-animation-name, rotate);animation-duration:var(--ran-icon-host-spin-animation-name, 1.4s);animation-timing-function:linear;animation-iteration-count:var(--ran-icon-host-spin-animation-name, infinite)}.ran-icon{display:var(--ran-icon-display, flex);align-items:var(--ran-icon-align-items, center);justify-content:var(--ran-icon-justify-content, center)}@keyframes rotate{to{transform:var(--ran-icon-keyframes-to-transform, rotate(360deg))}}",ji="http://www.w3.org/1999/xlink",Eo="xlink:href";function kd(){if(typeof window<"u"&&!customElements.get("r-icon")){class k extends HTMLElement{constructor(){super(),Oe(this,"_icon"),Oe(this,"_div"),Oe(this,"loadLocal",()=>new Promise((w,x)=>{Ji(Object.assign({"../../assets/icons/add-user.svg":()=>V(()=>import("./add-user-BN1JlY7e.D6YNNzf8.js"),[]),"../../assets/icons/arrow-down.svg":()=>V(()=>Promise.resolve().then(()=>cn),void 0).then(T=>T.j),"../../assets/icons/book.svg":()=>V(()=>import("./book-nTEFXU2x.DPEdiL1I.js"),[]),"../../assets/icons/check-circle-fill.svg":()=>V(()=>import("./check-circle-fill-B_pd8ZSs.Dxgzakn4.js"),[]),"../../assets/icons/check-circle.svg":()=>V(()=>import("./check-circle-szyAJiap.CM_vbBX5.js"),[]),"../../assets/icons/close-circle-fill.svg":()=>V(()=>import("./close-circle-fill-jSqPPw9i.BsLXh5-a.js"),[]),"../../assets/icons/close-circle.svg":()=>V(()=>import("./close-circle-CwmuN2C6.D612j4KD.js"),[]),"../../assets/icons/close.svg":()=>V(()=>import("./close-CFnkhudp.IMqD2L1-.js"),[]),"../../assets/icons/drop.svg":()=>V(()=>Promise.resolve().then(()=>un),void 0).then(T=>T.d),"../../assets/icons/eye-close.svg":()=>V(()=>import("./eye-close-BVr3NJtg.DsdsDDgX.js"),[]),"../../assets/icons/eye.svg":()=>V(()=>import("./eye-D_mEt17f.DJFa_ttF.js"),[]),"../../assets/icons/home.svg":()=>V(()=>import("./home-BUQ4USMk.BqTharGj.js"),[]),"../../assets/icons/info-circle-fill.svg":()=>V(()=>import("./info-circle-fill-CFeVMdci.CUxFtRNn.js"),[]),"../../assets/icons/info-circle.svg":()=>V(()=>import("./info-circle-COnL5bTJ.B9YJorcw.js"),[]),"../../assets/icons/loading-scene.svg":()=>V(()=>import("./loading-scene-BMc2wqKm.Di19NrRU.js"),[]),"../../assets/icons/loading.svg":()=>V(()=>import("./loading-Dcc5RApI.D3l74EUI.js"),[]),"../../assets/icons/lock.svg":()=>V(()=>import("./lock-Cr7BnmWN.0WfYXC2j.js"),[]),"../../assets/icons/message.svg":()=>V(()=>import("./message-D36_Zo2l.CR8K3LhI.js"),[]),"../../assets/icons/power-off.svg":()=>V(()=>import("./power-off-lQRbiBak.r13EH4bb.js"),[]),"../../assets/icons/preview.svg":()=>V(()=>import("./preview-CJbz9GjO.C8N16-9H.js"),[]),"../../assets/icons/setting.svg":()=>V(()=>import("./setting-DemlgzVC.DkD4YPwp.js"),[]),"../../assets/icons/sprite.svg":()=>V(()=>import("./sprite-CH2zLtZy.Djo3sTkk.js"),[]),"../../assets/icons/team.svg":()=>V(()=>import("./team-tl4NJXPC.D7881a1v.js"),[]),"../../assets/icons/unlock.svg":()=>V(()=>import("./unlock-CeU74z9n.58atcEuH.js"),[]),"../../assets/icons/user.svg":()=>V(()=>import("./user-B-eVXwuk.DyoYYAjs.js"),[]),"../../assets/icons/warning-circle-fill.svg":()=>V(()=>import("./warning-circle-fill-lODUKz0i.7RyGfSeR.js"),[]),"../../assets/icons/warning-circle.svg":()=>V(()=>import("./warning-circle-DDUgEDIv.1BX6MOiy.js"),[])}),`../../assets/icons/${this.name}.svg`,5).then(T=>{if(T&&T.default&&T.default._identification){const{data:D}=T.default;this._icon&&this._div.removeChild(this._icon),this._icon=Xi(D,"image/svg+xml"),this._icon&&(this._div.appendChild(this._icon),this.setSize(),this.setColor(),w())}else this.loadNs(),x(` + couldn't be loaded by r-icon, message: ${this.name} icon is undefined`)}).catch(T=>{this.loadNs()})})),Oe(this,"loadNs",()=>{this._icon&&this._div&&this._div.removeChild(this._icon),this._icon=document.createElement("svg"),this._icon.setAttribute("class","icon"),this._icon.setAttribute("viewBox","0 0 1024 1024"),this._icon.setAttribute("width","100"),this._icon.setAttribute("height","100");const w=document.createElementNS(ji,"use");w.setAttributeNS(ji,Eo,`../../assets/iconfont/icon.svg#icon-${this.name}`),this._icon.appendChild(w),this._div.appendChild(this._icon)}),Oe(this,"setIcon",async()=>{this.name&&this.loadLocal()}),Oe(this,"setSize",()=>{this._icon&&this.size&&(this._icon.setAttribute("width",this.size),this._icon.setAttribute("height",this.size))}),Oe(this,"setColor",()=>{this._icon&&(this.color?this._icon.setAttribute("fill",this.color):this._icon.setAttribute("fill","currentColor"))}),Oe(this,"setSpin",()=>{this.spin&&this.style.setProperty("animation-duration",`${this.spin}s`)}),this._div=document.createElement("div"),this._div.setAttribute("class","ran-icon"),this._div.setAttribute("part","ran-icon");const p=this.attachShadow({mode:"closed"}),f=document.createElement("style");f.textContent=_d,p.appendChild(f),p.appendChild(this._div)}static get observedAttributes(){return["name","size","color","spin"]}get name(){return this.getAttribute("name")}set name(p){p&&this.setAttribute("name",p)}get size(){return this.getAttribute("size")}set size(p){p&&this.setAttribute("size",p)}get color(){return this.getAttribute("color")}set color(p){p&&this.setAttribute("color",p)}get spin(){return this.getAttribute("spin")}set spin(p){p!=null&&this.setAttribute("spin",p)}connectedCallback(){this.setIcon()}attributeChangedCallback(p,f,w){w!==f&&(p==="name"&&this.setIcon(),p==="size"&&this.setSize(),p==="color"&&this.setColor(),p==="spin"&&this.setSpin())}}customElements.define("r-icon",k)}if(typeof window<"u"&&!customElements.get("ra-icon")){class k extends HTMLElement{constructor(){super(),Oe(this,"_icon"),Oe(this,"_div"),Oe(this,"loadLocal",()=>new Promise((p,f)=>{Ji(Object.assign({"../../assets/icons/add-user.svg":()=>V(()=>import("./add-user-BN1JlY7e.D6YNNzf8.js"),[]),"../../assets/icons/arrow-down.svg":()=>V(()=>Promise.resolve().then(()=>cn),void 0).then(w=>w.j),"../../assets/icons/book.svg":()=>V(()=>import("./book-nTEFXU2x.DPEdiL1I.js"),[]),"../../assets/icons/check-circle-fill.svg":()=>V(()=>import("./check-circle-fill-B_pd8ZSs.Dxgzakn4.js"),[]),"../../assets/icons/check-circle.svg":()=>V(()=>import("./check-circle-szyAJiap.CM_vbBX5.js"),[]),"../../assets/icons/close-circle-fill.svg":()=>V(()=>import("./close-circle-fill-jSqPPw9i.BsLXh5-a.js"),[]),"../../assets/icons/close-circle.svg":()=>V(()=>import("./close-circle-CwmuN2C6.D612j4KD.js"),[]),"../../assets/icons/close.svg":()=>V(()=>import("./close-CFnkhudp.IMqD2L1-.js"),[]),"../../assets/icons/drop.svg":()=>V(()=>Promise.resolve().then(()=>un),void 0).then(w=>w.d),"../../assets/icons/eye-close.svg":()=>V(()=>import("./eye-close-BVr3NJtg.DsdsDDgX.js"),[]),"../../assets/icons/eye.svg":()=>V(()=>import("./eye-D_mEt17f.DJFa_ttF.js"),[]),"../../assets/icons/home.svg":()=>V(()=>import("./home-BUQ4USMk.BqTharGj.js"),[]),"../../assets/icons/info-circle-fill.svg":()=>V(()=>import("./info-circle-fill-CFeVMdci.CUxFtRNn.js"),[]),"../../assets/icons/info-circle.svg":()=>V(()=>import("./info-circle-COnL5bTJ.B9YJorcw.js"),[]),"../../assets/icons/loading-scene.svg":()=>V(()=>import("./loading-scene-BMc2wqKm.Di19NrRU.js"),[]),"../../assets/icons/loading.svg":()=>V(()=>import("./loading-Dcc5RApI.D3l74EUI.js"),[]),"../../assets/icons/lock.svg":()=>V(()=>import("./lock-Cr7BnmWN.0WfYXC2j.js"),[]),"../../assets/icons/message.svg":()=>V(()=>import("./message-D36_Zo2l.CR8K3LhI.js"),[]),"../../assets/icons/power-off.svg":()=>V(()=>import("./power-off-lQRbiBak.r13EH4bb.js"),[]),"../../assets/icons/preview.svg":()=>V(()=>import("./preview-CJbz9GjO.C8N16-9H.js"),[]),"../../assets/icons/setting.svg":()=>V(()=>import("./setting-DemlgzVC.DkD4YPwp.js"),[]),"../../assets/icons/sprite.svg":()=>V(()=>import("./sprite-CH2zLtZy.Djo3sTkk.js"),[]),"../../assets/icons/team.svg":()=>V(()=>import("./team-tl4NJXPC.D7881a1v.js"),[]),"../../assets/icons/unlock.svg":()=>V(()=>import("./unlock-CeU74z9n.58atcEuH.js"),[]),"../../assets/icons/user.svg":()=>V(()=>import("./user-B-eVXwuk.DyoYYAjs.js"),[]),"../../assets/icons/warning-circle-fill.svg":()=>V(()=>import("./warning-circle-fill-lODUKz0i.7RyGfSeR.js"),[]),"../../assets/icons/warning-circle.svg":()=>V(()=>import("./warning-circle-DDUgEDIv.1BX6MOiy.js"),[])}),`../../assets/icons/${this.name}.svg`,5).then(w=>{if(w&&w.default&&w.default._identification){const{data:x}=w.default;this._icon&&this._div.removeChild(this._icon),this._icon=Xi(x,"image/svg+xml"),this._icon&&(this._div.appendChild(this._icon),this.setSize(),this.setColor(),p())}else this.loadNs(),f(` + couldn't be loaded by r-icon, message: ${this.name} icon is undefined`)}).catch(w=>{this.loadNs()})})),Oe(this,"loadNs",()=>{this._icon&&this._div&&this._div.removeChild(this._icon),this._icon=document.createElement("svg"),this._icon.setAttribute("class","icon"),this._icon.setAttribute("viewBox","0 0 1024 1024"),this._icon.setAttribute("width","100"),this._icon.setAttribute("height","100");const p=document.createElementNS(ji,"use");p.setAttributeNS(ji,Eo,`../../assets/iconfont/icon.svg#icon-${this.name}`),this._icon.appendChild(p),this._div.appendChild(this._icon)}),Oe(this,"setIcon",async()=>{this.name&&this.loadLocal()}),Oe(this,"setSize",()=>{this._icon&&this.size&&(this._icon.setAttribute("width",this.size),this._icon.setAttribute("height",this.size))}),Oe(this,"setColor",()=>{this._icon&&(this.color?this._icon.setAttribute("fill",this.color):this._icon.setAttribute("fill","currentColor"))}),Oe(this,"setSpin",()=>{this.spin&&this.style.setProperty("animation-duration",`${this.spin}s`)}),this._div=document.createElement("div"),this._div.setAttribute("class","ran-icon"),this._div.setAttribute("part","ran-icon")}static get observedAttributes(){return["name","size","color","spin"]}get name(){return this.getAttribute("name")}set name(p){p&&this.setAttribute("name",p)}get size(){return this.getAttribute("size")}set size(p){p&&this.setAttribute("size",p)}get color(){return this.getAttribute("color")}set color(p){p&&this.setAttribute("color",p)}get spin(){return this.getAttribute("spin")}set spin(p){p!=null&&this.setAttribute("spin",p)}connectedCallback(){this.appendChild(this._div),this.setIcon()}attributeChangedCallback(p,f,w){w!==f&&(p==="name"&&this.setIcon(),p==="size"&&this.setSize(),p==="color"&&this.setColor(),p==="spin"&&this.setSpin())}}customElements.define("ra-icon",k)}}const xd=kd(),Td=Object.freeze(Object.defineProperty({__proto__:null,default:xd},Symbol.toStringTag,{value:"Module"}));var Cd=Object.defineProperty,Sd=(k,h,p)=>h in k?Cd(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,Ao=(k,h,p)=>Sd(k,typeof h!="symbol"?h+"":h,p);const Ld=".remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}",Dd=` + data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg== +`;function Rd(){if(typeof window<"u"&&!customElements.get("r-img")){class k extends HTMLElement{constructor(){super(),Ao(this,"_image"),Ao(this,"_container"),this._container=document.createElement("div"),this._container.setAttribute("class","ran-image");const p=this.attachShadow({mode:"closed"}),f=document.createElement("style");f.textContent=Ld,p.appendChild(f),p.appendChild(this._container)}static get observedAttributes(){return["fallback"]}get fallback(){return this.getAttribute("fallback")||Dd}set fallback(p){p?this.setAttribute("fallback",p):this.removeAttribute("fallback")}listenFallback(p,f){p==="fallback"&&this._image&&(f?this._image.setAttribute("fallback",f):this._image.removeAttribute("fallback"))}connectedCallback(){const p=this.getAttribute("src")||"";this._image=new Image,this._image.src=p,this._image.addEventListener("error",()=>{this._image&&this.fallback&&(this._image.src=this.fallback)}),this._image.addEventListener("load",()=>{this._image&&this._container.appendChild(this._image)})}attributeChangedCallback(p,f,w){this.listenFallback(p,w)}}customElements.define("r-img",k)}}const Id=Rd(),Pd=Object.freeze(Object.defineProperty({__proto__:null,default:Id},Symbol.toStringTag,{value:"Module"}));var Od=Object.defineProperty,Md=(k,h,p)=>h in k?Od(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,He=(k,h,p)=>Md(k,typeof h!="symbol"?h+"":h,p);const Fd='.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}.ran-input{position:var(--ran-input-position, relative);display:var(--ran-input-display, flex);width:var(--ran-input-width, calc(100% - 16px) );height:var(--ran-input-height, calc(100% - 4px) );min-width:0;padding:var(--ran-input-padding, 2px 8px);color:#000000d9;font-size:var(--ran-input-font-size, 12px);line-height:var(--ran-input-line-height, 1.5715);background-color:var(--ran-input-background-color, #fff);background-image:var(--ran-input-background-image, none);border:var(--ran-input-border, 1px solid #d9d9d9);border-radius:var(--ran-input-border-radius, 2px);transition:var(--ran-input-transition, all .3s)}.ran-input .ran-icon{display:var(--ran-input-icon-display, flex);align-items:var(--ran-input-icon-align-items, center);justify-content:var(--ran-input-icon-justify-content, center)}.ran-input:active{border-color:var(--ran-input-active-border-color, #40a9ff);box-shadow:var(--ran-input-active-box-shadow, 0 0 0 2px rgba(24, 144, 255, .2));border-right-width:var(--ran-input-active-border-right-width, 1px);outline:var(--ran-input-active-outline, 0)}.ran-input:hover{border-color:var(--ran-input-hover-border-color, #40a9ff);border-right-width:var(--ran-input-hover-border-right-width, 1px)}.ran-input>.ran-input-content:hover~.ran-input-label{color:var(--ran-input-label-hover-color, #40a9ff)}.ran-input[value]>.ran-input-label{transform:var(--ran-input-label-value-transform, translateY( calc(-50% - .43em) ) scale(.8));color:var(--ran-input-label-value-color, #00000040)}.ran-input[status=error]{border-color:var(--ran-input-status-error-border-color, #ff4d4f)}.ran-input[status=error]>.ran-input-content~.ran-input-label{color:var(--ran-input-label-status-error-color, #ff4d4f)}.ran-input[status=warning]{border-color:var(--ran-input-status-warning-border-color, #ff7875)}.ran-input[status=warning]>.ran-input-content~.ran-input-label{color:var(--ran-input-label-status-warning-color, #ff7875)}.ran-input[disabled]{color:var(--ran-input-disabled-color, #00000040);background-color:var(--ran-input-disabled-background-color, #f5f5f5);border-color:var(--ran-input-disabled-border-color, #d9d9d9);box-shadow:var(--ran-input-disabled-box-shadow, none);cursor:var(--ran-input-disabled-cursor, not-allowed);opacity:var(--ran-input-disabled-opacity, 1)}.ran-input[disabled]>.ran-input-content{color:var(--ran-input-content-disabled-color, #00000040);background-color:var(--ran-input-content-disabled-background-color, #f5f5f5);border-color:var(--ran-input-content-disabled-border-color, #d9d9d9);box-shadow:var(--ran-input-content-disabled-box-shadow, none);cursor:var(--ran-input-content-disabled-cursor, not-allowed);opacity:var(--ran-input-content-disabled-opacity, 1)}.ran-input[disabled]>.ran-input-content~.ran-input-label{color:var(--ran-input-label-disabled-color, #00000040);background-color:var(--ran-input-label-disabled-background-color, #f5f5f5)}.ran-input[disabled]>.ran-input-label{color:#999;border-color:var(--ran-input-label-disabled-border-color, #d9d9d9);box-shadow:var(--ran-input-label-disabled-box-shadow, none);cursor:var(--ran-input-label-disabled-cursor, not-allowed)}.ran-input-content{writing-mode:var(--ran-input-content-writing-mode, horizontal-tb);text-rendering:var(--ran-input-content-text-rendering, auto);letter-spacing:var(--ran-input-content-letter-spacing, normal);word-spacing:var(--ran-input-content-word-spacing, normal);text-transform:var(--ran-input-content-text-transform, none);text-indent:var(--ran-input-content-text-indent, 0px);text-shadow:var(--ran-input-content-text-shadow, none);text-align:var(--ran-input-content-text-align, start);cursor:var(--ran-input-content-cursor, text);touch-action:var(--ran-input-content-touch-action, manipulation);-webkit-appearance:var(--ran-input-content--webkit-appearance, none);text-overflow:var(--ran-input-content-text-overflow, ellipsis);box-sizing:var(--ran-input-content-box-sizing, border-box);margin:var(--ran-input-content-margin, 0);font-variant:var(--ran-input-content-font-variant, tabular-nums);list-style:var(--ran-input-content-list-style, none);font-feature-settings:var(--ran-input-content-font-feature-settings, "tnum");position:var(--ran-input-content-position, relative);border:var(--ran-input-content-border, none);width:var(--ran-input-content-width, 100%);min-width:var(--ran-input-content-min-width, 0);color:var(--ran-input-content-color, #000000d9);font-size:var(--ran-input-content-font-size, 14px);line-height:var(--ran-input-content-line-height, 1.48);background-color:var(--ran-input-content-background-color, #fff);background-image:var(--ran-input-content-background-image, none);transition:var(--ran-input-content-transition, all .3s);outline:var(--ran-input-content-outline, none)}.ran-input-content:focus,.ran-input-content:hover{border:var(--ran-input-content-hover-border, none);outline:var(--ran-input-content-hover-outline, 0)}.ran-input-content::placeholder{color:var(--ran-input-content-placeholder-color, #999)}.ran-input-content:placeholder-shown~.ran-input-label{transform:var(--ran-input-content-placeholder-label-transform, translateY( calc(-50% - .43em) ) scale(.8))}.ran-input-content:focus~.ran-input-label{transform:var(--ran-input-content-focus-label-transform, translateY( calc(-50% - .43em) ) scale(.8))}.ran-input-content::-webkit-search-cancel-button{display:none;-webkit-appearance:none}.ran-input-label{pointer-events:var(--ran-input-label-pointer-events, none);position:var(--ran-input-label-position, absolute);font-size:var(--ran-input-label-font-size, 14px);left:var(--ran-input-label-left, 8px);transition:var(--ran-input-label-transition, transform .3s, color .3s, background-color .3s, backdrop-filter .3s);transform-origin:var(--ran-input-label-transform-origin, left);padding:var(--ran-input-label-padding, 0 .2em);color:var(--ran-input-label-color, #999);background:var(--ran-input-label-background, #fff);opacity:var(--ran-input-label-opacity, .9)}';let fn=class extends Fe(){constructor(){super(),He(this,"_input"),He(this,"_label"),He(this,"_inputContent"),He(this,"_icon"),He(this,"customInput",f=>{f.stopPropagation(),f.preventDefault();const{target:w,data:x=""}=f;this.value=(w==null?void 0:w.value)||x||"",this.customChange(),this.dispatchEvent(new CustomEvent("input",{detail:{value:this.value}}))}),He(this,"customChange",()=>{this.dispatchEvent(new CustomEvent("change",{detail:{value:this.value}}))}),He(this,"listenPlaceholder",(f,w)=>{f==="placeholder"&&this._inputContent&&(w!=null?this._inputContent.setAttribute("placeholder",w):this._inputContent.removeAttribute("placeholder"))}),He(this,"listenLabel",(f,w)=>{f==="label"&&this._inputContent&&(w!=null?this._label?this._label.innerHTML=w:(this._label=document.createElement("label"),this._label.innerHTML=w,this._label.setAttribute("class","ran-input-label"),this._label.setAttribute("part","ran-input-label"),this._input.appendChild(this._label)):(this._input.removeAttribute("label"),this._label&&(this._input.removeChild(this._label),this._label=void 0)))}),He(this,"listenType",(f,w)=>{f==="type"&&this._inputContent&&(w?this._inputContent.setAttribute("type",w):(this._inputContent.removeAttribute("type"),this._inputContent.removeAttribute("min"),this._inputContent.removeAttribute("max"),this._inputContent.removeAttribute("step")))}),He(this,"listenStatus",(f,w)=>{f==="status"&&this._input&&(w?this._input.setAttribute("status",w):this._input.removeAttribute("status"))}),He(this,"listenDisabled",(f,w)=>{f==="disabled"&&this._input&&(nt.includes(w)?this._input.removeAttribute("disabled"):(this._input.setAttribute("disabled",""),this._inputContent.setAttribute("disabled","")))}),He(this,"listenIcon",(f,w,x)=>{f==="icon"&&w&&w!==x&&(this.removeAttribute("label"),this.setAttribute("icon",w),this.dealIcon())}),He(this,"dealIcon",()=>{if(!this._icon){this._icon=document.createElement("ra-icon");const{width:f,height:w}=this._inputContent.getBoundingClientRect(),x=Math.min(f,w);this._icon.setAttribute("size",`${x}`),this._inputContent.insertAdjacentElement("beforebegin",this._icon)}this.icon&&this._icon.setAttribute("name",this.icon)}),He(this,"listenEvent",(f,w,x)=>{this.listenPlaceholder(f,x),this.listenLabel(f,x),this.listenStatus(f,x),this.listenDisabled(f,x),this.listenIcon(f,x,w),f==="value"&&w!==x&&(this._inputContent.value=x,this._input.setAttribute("value",x))});const h=this.attachShadow({mode:"closed"}),p=document.createElement("style");p.textContent=Fd,h.appendChild(p),this._input=document.createElement("div"),this._input.setAttribute("class","ran-input"),this._input.setAttribute("part","ran-input"),this._inputContent=document.createElement("input"),this._inputContent.setAttribute("class","ran-input-content"),this._inputContent.setAttribute("part","ran-input-content"),this._input.appendChild(this._inputContent),h.appendChild(this._input)}static get observedAttributes(){return["label","disabled","name","placeholder","type","icon","value","status","prefix","suffix","allowclear","count","maxlength","showcount","onPressEnter","variant","minrows","maxrows"]}get value(){return this.getAttribute("value")||""}set value(h){!Ce(this)&&h?(this.setAttribute("value",h),this._input.setAttribute("value",h)):(this.removeAttribute("value"),this._input.removeAttribute("value"))}get placeholder(){return this.getAttribute("placeholder")||""}set placeholder(h){h?this.setAttribute("placeholder",h):this.removeAttribute("placeholder")}get required(){return this.getAttribute("required")||""}set required(h){!h||h==="false"?this.removeAttribute("required"):this.setAttribute("required","")}get disabled(){return`${Ce(this)}`}set disabled(h){nt.includes(h)?(this.removeAttribute("disabled"),this._input.removeAttribute("disabled"),this._inputContent.removeAttribute("disabled")):(this.setAttribute("disabled",""),this._input.setAttribute("disabled",""),this._inputContent.setAttribute("disabled",""))}get label(){return this.getAttribute("label")||""}set label(h){this.setAttribute("label",h)}get status(){return this.getAttribute("status")||""}set status(h){h?(this.setAttribute("status",h),this._input.setAttribute("status",h)):(this.removeAttribute("status"),this._input.removeAttribute("status"))}get name(){return this.getAttribute("name")||""}set name(h){this.setAttribute("name",h)}get min(){return this.getAttribute("min")||""}set min(h){this.type==="number"&&this.setAttribute("min",h)}get max(){return this.getAttribute("max")||""}set max(h){this.type==="number"&&this.setAttribute("max",h)}get step(){return this.getAttribute("step")||""}set step(h){this.type==="number"&&this.setAttribute("step",h)}get icon(){return this.getAttribute("icon")||""}set icon(h){h?this.setAttribute("icon",h):this.removeAttribute("icon")}get prefix(){return this.getAttribute("prefix")||""}set prefix(h){h?this.setAttribute("prefix",h):this.removeAttribute("prefix")}get suffix(){return this.getAttribute("suffix")||""}set suffix(h){h?this.setAttribute("suffix",h):this.removeAttribute("suffix")}get type(){return this.getAttribute("type")||""}set type(h){h?this.setAttribute("type",h):this.removeAttribute("type")}connectedCallback(){this.value&&(this._inputContent.value=this.value,this._input.setAttribute("value",this.value)),this.status&&this._input.setAttribute("status",this.status),Ce(this)&&(this._input.setAttribute("disabled",""),this._inputContent.setAttribute("disabled","")),this.type&&this._inputContent.setAttribute("type",this.type),this._inputContent.addEventListener("input",this.customInput),document.readyState==="complete"&&this.dealIcon()}disconnectCallback(){this._inputContent.removeEventListener("input",this.customInput)}attributeChangedCallback(h,p,f){this.listenEvent(h,p,f)}};function Bd(){return typeof window<"u"&&!customElements.get("r-input")?(customElements.define("r-input",fn),fn):Ie("document is undefined or r-input is exist")}const Nd=Bd(),Ud=Object.freeze(Object.defineProperty({__proto__:null,Input:fn,default:Nd},Symbol.toStringTag,{value:"Module"}));var Gd=Object.defineProperty,Hd=(k,h,p)=>h in k?Gd(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,Ct=(k,h,p)=>Hd(k,typeof h!="symbol"?h+"":h,p);const _o='.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}:host([type="toast"]) .ran-message-notice{padding:8px;text-align:center;max-width:90%;margin:0 auto;word-break:break-all}:host([type="toast"]) .ran-message-notice-content{display:inline-block;padding:10px 16px;background:#000000b3;border-radius:7px;pointer-events:all}:host([type="toast"]) .ran-message-notice-content-info{align-items:center;display:flex}:host([type="toast"]) .ran-message-notice-content-info span{margin:0;padding:0;font-size:14px;font-variant:tabular-nums;list-style:none;font-feature-settings:"tnum";z-index:1010;width:100%;pointer-events:none;color:#fff}.ran-message-notice{padding:var(--ran-message-notice-padding, 8px);text-align:var(--ran-message-notice-text-align, center);max-width:var(--ran-message-notice-max-width, 90%);margin:var(--ran-message-notice-margin, 0 auto);word-break:var(--ran-message-notice-word-break, break-all)}.ran-message-notice-content{display:var(--ran-message-notice-content-display, inline-block);padding:var(--ran-message-notice-content-padding, 10px 16px);background:var(--ran-message-notice-content-background, #fff);border-radius:var(--ran-message-notice-content-border-radius, 8px);box-shadow:var(--ran-message-notice-content-box-shadow, 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d);pointer-events:var(--ran-message-notice-content-pointer-events, all)}.ran-message-notice-content-info{align-items:var(--ran-message-notice-content-info-align-items, center);display:var(--ran-message-notice-content-info-display, flex)}.ran-message-notice-content-info span{margin:var(--ran-message-notice-content-info-span-margin, 0);padding:var(--ran-message-notice-content-info-span-padding, 0);color:var(--ran-message-notice-content-info-span-color, #000000d9);font-size:var(--ran-message-notice-content-info-span-font-size, 14px);font-variant:var(--ran-message-notice-content-info-span-font-variant, tabular-nums);list-style:var(--ran-message-notice-content-info-span-list-style, none);font-feature-settings:var(--ran-message-notice-content-info-span-font-feature-settings, "tnum");z-index:var(--ran-message-notice-content-info-span-z-index, 1010);width:var(--ran-message-notice-content-info-span-width, 100%);pointer-events:var(--ran-message-notice-content-info-span-pointer-events, none)}@keyframes rotate{to{transform:rotate(360deg)}}@keyframes MessageMoveIn{0%{padding:0;transform:translateY(-100%);opacity:0}to{padding:8px;transform:translateY(0);opacity:1}}@keyframes MessageMoveOut{0%{max-height:150px;padding:8px;opacity:1}to{max-height:0;padding:0;opacity:0}}.ranui-message{box-sizing:var(--ran-message-box-sizing, border-box);margin:var(--ran-message-margin, 0);padding:var(--ran-message-padding, 0);color:var(--ran-message-color, #000000d9);font-size:var(--ran-message-font-size, 14px);font-variant:var(--ran-message-font-variant, tabular-nums);line-height:var(--ran-message-line-height, 1.5715);list-style:var(--ran-message-ist-style, none);font-feature-settings:var(--ran-message-font-feature-settings, "tnum");position:var(--ran-message-position, fixed);top:var(--ran-message-top, 8px);left:var(--ran-message-left, 0);z-index:var(--ran-message-z-index, 1010);width:var(--ran-message-width, 100%);pointer-events:var(--ran-message-pointer-events, none)}.ranui-message .message-in{animation-name:var(--ran-message-in-animation-name, MessageMoveIn);animation-duration:var(--ran-message-in-animation-duration, .3s);animation-timing-function:var(--ran-message-in-animation-timing-function, cubic-bezier(.78, .14, .15, .86))}.ranui-message .message-leave{animation-name:var(--ran-message-leave-animation-name, MessageMoveOut);animation-duration:var(--ran-message-leave-animation-duration, .3s);animation-timing-function:var(--ran-message-leave-animation-timing-function, cubic-bezier(.78, .14, .15, .86))}',ko=300,xo=3e3,Kd=new Map([["success","check-circle-fill"],["warning","warning-circle-fill"],["error","close-circle-fill"],["info","info-circle-fill"],["toast",null]]),Vd=new Map([["success","#52c41a"],["warning","#faad14"],["error","#ff4d4f"],["info","#1890ff"],["toast","rgba(0, 0, 0, 0.7)"]]);function zd(){if(typeof window<"u"&&!customElements.get("r-message")){class k extends HTMLElement{constructor(){super(),Ct(this,"_info"),Ct(this,"_notice"),Ct(this,"_content"),Ct(this,"_icon"),Ct(this,"_span"),Ct(this,"timeId"),Ct(this,"close"),Ct(this,"setIcon",G=>{var F,q,j,de;const te=Kd.get(G),le=Vd.get(G);te&&((F=this._icon)==null||F.setAttribute("name",te),(q=this._icon)==null||q.style.setProperty("margin-right","8px"),(j=this._icon)==null||j.setAttribute("size","18"),le&&((de=this._icon)==null||de.setAttribute("color",le)))}),this._notice=document.createElement("div"),this._notice.setAttribute("class","ran-message-notice"),this._content=document.createElement("div"),this._content.setAttribute("class","ran-message-notice-content"),this._info=document.createElement("div"),this._info.setAttribute("class","ran-message-notice-content-info"),this._icon=document.createElement("r-icon"),this._span=document.createElement("span"),this._info.appendChild(this._icon),this._info.appendChild(this._span),this._content.appendChild(this._info),this._notice.appendChild(this._content);const T=this.attachShadow({mode:"closed"}),D=document.createElement("style");D.textContent=_o,T.appendChild(D),T.appendChild(this._notice)}static get observedAttributes(){return["type","content"]}get type(){return this.getAttribute("type")}set type(T){T&&this.setAttribute("type",T)}get content(){return this.getAttribute("content")}set content(T){T&&this.setAttribute("content",T)}attributeChangedCallback(T,D,G){T==="content"&&D!==G&&(this._span.textContent=G),T==="type"&&D!==G&&this.setIcon(G)}}customElements.define("r-message",k);const h=document.createElement("div"),p=z("style").setTextContent(_o),f=document.createElement("div");f.setAttribute("class","ranui-message"),document.body.appendChild(h),h.appendChild(p.element),h.appendChild(f);const w=x=>T=>{const D=new k;D.setAttribute("class","message"),D.timeId&&clearTimeout(D.timeId),D.setAttribute("type",x);let G=xo,F;if(!T)return;typeof T=="string"?D.setAttribute("content",T):(D.setAttribute("content",T.content),F=T.close,G=T.duration||xo);const q=setTimeout(()=>{D.classList.remove("message-in"),D.classList.add("message-leave"),clearTimeout(q)},G-ko);D.timeId=setTimeout(()=>{D.classList.remove("message-leave"),f.removeChild(D),F&&F()},G),f.appendChild(D),D.classList.add("message-in"),setTimeout(()=>{D.classList.remove("message-in")},ko)};return{info:w("info"),success:w("success"),error:w("error"),warning:w("warning"),toast:w("toast")}}return null}const bi=zd();typeof window<"u"&&bi&&(window.message=bi,window.ranui||(window.ranui={}),window.ranui.message=bi);const Yd=Object.freeze(Object.defineProperty({__proto__:null,default:bi},Symbol.toStringTag,{value:"Module"}));var jd=Object.defineProperty,qd=(k,h,p)=>h in k?jd(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,je=(k,h,p)=>qd(k,typeof h!="symbol"?h+"":h,p);const To='.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}.r-preview-slot{display:block}:host{cursor:pointer}.r-preview-mask{position:fixed;top:0;left:0;width:100vw;height:100vh;background-color:#00000073;z-index:1081}.r-preview-mask .r-preview-loading{position:absolute;top:30vh;left:50vw;transform:translate(-50%);display:flex;flex-flow:column;align-items:center}.r-preview-mask .r-preview-loading-text{color:#fff;font-size:16px}.r-preview-mask .r-preview-options{width:100%;pointer-events:auto;display:flex;flex-flow:row-reverse nowrap;align-items:center;justify-content:space-between}.r-preview-mask .r-preview-options-close{margin:14px;border:none;cursor:pointer;transition:all .3s;-webkit-user-select:none;user-select:none}.r-preview-mask .r-preview-contain{max-width:calc(100vw - 20px);margin:0 auto;display:flex;flex-flow:column nowrap;align-items:center;justify-content:center}.r-preview-mask .r-preview-contain .r-preview-context{margin:0 auto;height:calc(100vh - 68px);display:flex;flex-flow:column nowrap;justify-content:flex-start;align-items:center;overflow:auto}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main{width:100%;height:100%;margin-bottom:10px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet{font-size:13px;line-height:normal;-webkit-user-select:none;user-select:none;-moz-user-select:none;font-family:Lato,Source Sans Pro,Roboto,Helvetica,Arial,sans-serif;box-sizing:content-box;background:#fff;-webkit-font-smoothing:antialiased}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet textarea{font:400 13px Arial,Lato,Source Sans Pro,Roboto,Helvetica,sans-serif}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-sheet{position:relative;overflow:hidden}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-table{vertical-align:bottom}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-tooltip{font-family:inherit;position:absolute;padding:5px 10px;color:#fff;border-radius:1px;background:#000;font-size:12px;z-index:201}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-tooltip:before{pointer-events:none;position:absolute;left:calc(50% - 4px);top:-4px;content:"";width:8px;height:8px;background:inherit;-webkit-transform:rotate(45deg);transform:rotate(45deg);z-index:1;box-shadow:1px 1px 3px -1px #0000004d}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-color-palette{padding:5px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-color-palette table{margin:0;padding:0;border-collapse:separate;border-spacing:2;background:#fff}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-color-palette table td{margin:0;cursor:pointer;border:1px solid transparent}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-color-palette table td:hover{border-color:#ddd}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-color-palette table td .x-spreadsheet-color-palette-cell{width:16px;height:16px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-border-palette{padding:6px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-border-palette table{margin:0;padding:0;border-collapse:separate;border-spacing:0;background:#fff;table-layout:fixed}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-border-palette table td{margin:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-border-palette .x-spreadsheet-border-palette-left{border-right:1px solid #eee;padding-right:6px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell{width:30px;height:30px;cursor:pointer;text-align:center}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell:hover{background-color:#eee}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-border-palette .x-spreadsheet-border-palette-right{padding-left:6px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-border-palette .x-spreadsheet-border-palette-right .x-spreadsheet-line-type{position:relative;left:0;top:-3px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-dropdown{position:relative}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-dropdown .x-spreadsheet-dropdown-content{position:absolute;z-index:200;background:#fff;box-shadow:1px 2px 5px 2px #33333326}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-dropdown.bottom-left .x-spreadsheet-dropdown-content{top:calc(100% + 5px);left:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-dropdown.bottom-right .x-spreadsheet-dropdown-content{top:calc(100% + 5px);right:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-dropdown.top-left .x-spreadsheet-dropdown-content{bottom:calc(100% + 5px);left:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-dropdown.top-right .x-spreadsheet-dropdown-content{bottom:calc(100% + 5px);right:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-dropdown .x-spreadsheet-dropdown-title{padding:0 5px;display:inline-block}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-resizer{position:absolute;z-index:11}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-resizer .x-spreadsheet-resizer-hover{background-color:#4b89ff40}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-resizer .x-spreadsheet-resizer-line{position:absolute}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-resizer.horizontal{cursor:row-resize}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-resizer.horizontal .x-spreadsheet-resizer-line{border-bottom:2px dashed #4b89ff;left:0;bottom:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-resizer.vertical{cursor:col-resize}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-resizer.vertical .x-spreadsheet-resizer-line{border-right:2px dashed #4b89ff;top:0;right:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-scrollbar{position:absolute;bottom:0;right:0;background-color:#f4f5f8;opacity:.9;z-index:12}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-scrollbar.horizontal{right:15px;overflow-x:scroll;overflow-y:hidden}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-scrollbar.horizontal>div{height:1px;background:#ddd}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-scrollbar.vertical{bottom:15px;overflow-x:hidden;overflow-y:scroll}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-scrollbar.vertical>div{width:1px;background:#ddd}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-overlayer{position:absolute;left:0;top:0;z-index:10}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-overlayer .x-spreadsheet-overlayer-content{position:absolute;overflow:hidden;pointer-events:none;width:100%;height:100%}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-editor,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-selector{box-sizing:content-box;position:absolute;overflow:hidden;pointer-events:none;top:0;left:0;width:100%;height:100%}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-selector .hide-input{position:absolute;z-index:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-selector .hide-input input{padding:0;width:0;border:none!important}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-selector .x-spreadsheet-selector-area{position:absolute;border:2px solid #4b89ff;background:#4b89ff1a;z-index:5}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-selector .x-spreadsheet-selector-clipboard,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-selector .x-spreadsheet-selector-autofill{position:absolute;background:transparent;z-index:100}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-selector .x-spreadsheet-selector-clipboard{border:2px dashed #4b89ff}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-selector .x-spreadsheet-selector-autofill{border:1px dashed rgba(0,0,0,.45)}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-selector .x-spreadsheet-selector-corner{pointer-events:auto;position:absolute;cursor:crosshair;font-size:0;height:5px;width:5px;right:-5px;bottom:-5px;border:2px solid #ffffff;background:#4b89ff}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-editor{z-index:20}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-editor .x-spreadsheet-editor-area{position:absolute;text-align:left;border:2px solid #4b89ff;line-height:0;z-index:100;pointer-events:auto}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-editor .x-spreadsheet-editor-area textarea{box-sizing:content-box;border:none;padding:0 3px;outline:none;resize:none;text-align:start;overflow-y:hidden;font:400 13px Arial,Lato,Source Sans Pro,Roboto,Helvetica,sans-serif;color:inherit;white-space:normal;word-wrap:break-word;line-height:22px;margin:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-editor .x-spreadsheet-editor-area .textline{overflow:hidden;visibility:hidden;position:fixed;top:0;left:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-item{-webkit-user-select:none;user-select:none;background:0;border:1px solid transparent;outline:none;height:26px;color:#000000e6;line-height:26px;list-style:none;padding:2px 10px;cursor:default;text-align:left;overflow:hidden}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-item.disabled{pointer-events:none;opacity:.5}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-item:hover,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-item.active{background:#0000000d}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-item.divider{height:0;padding:0;margin:5px 0;border:none;border-bottom:1px solid rgba(0,0,0,.1)}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-item .label{float:right;opacity:.65;font-size:1em}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-item.state,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-header.state{padding-left:35px!important;position:relative}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-item.state:before,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-header.state:before{content:"";position:absolute;width:10px;height:10px;left:12px;top:calc(50% - 5px);background:#00000014;border-radius:2px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-item.state.checked:before,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-header.state.checked:before{background:#4b89ff}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-checkbox{position:relative;display:inline-block;backface-visibility:hidden;outline:0;vertical-align:baseline;font-style:normal;font-size:1rem;line-height:1em}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-checkbox>input{position:absolute;top:0;left:0;opacity:0!important;outline:0;z-index:-1}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-suggest,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-contextmenu,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-sort-filter{position:absolute;box-shadow:1px 2px 5px 2px #33333326;background:#fff;z-index:100;width:260px;pointer-events:auto;overflow:auto}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-suggest{width:200px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-filter{border:1px solid #e9e9e9;font-size:12px;margin:10px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-filter .x-spreadsheet-header{padding:.5em .75em;background:#f8f8f9;border-bottom:1px solid #e9e9e9;border-left:1px solid transparent}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-filter .x-spreadsheet-body{height:200px;overflow-y:auto}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-filter .x-spreadsheet-body .x-spreadsheet-item{height:20px;line-height:20px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-sort-filter .x-spreadsheet-buttons{margin:10px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-bottombar{height:40px;padding:0 30px;text-align:left;background:#f5f6f7;display:flex}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-bottombar{position:relative;border-top:1px solid #e0e2e4}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-bottombar .x-spreadsheet-menu>li{line-height:40px;height:40px;padding-top:0;padding-bottom:0;vertical-align:middle;border-right:1px solid #e8eaed}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-menu{list-style:none;margin:0;padding:0;-webkit-user-select:none;user-select:none}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-menu>li{float:left;line-height:1.25em;padding:.785em 1em;margin:0;vertical-align:middle;text-align:left;font-weight:400;color:#80868b;white-space:nowrap;cursor:pointer;transition:all .3s;font-weight:700}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-menu>li.active{background-color:#fff;color:#000000a6}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-menu>li .x-spreadsheet-dropdown{display:inline-block}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-print{position:absolute;left:0;top:0;z-index:100;width:100%;height:100%;display:flex;flex-direction:column}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-print-bar{background:#424242;height:60px;line-height:60px;padding:0 30px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-print-bar .-title{color:#fff;font-weight:700;font-size:1.2em;float:left}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-print-bar .-right{float:right;margin-top:12px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-print-content{display:flex;flex:auto;flex-direction:row;background:#d0d0d0;height:calc(100% - 60px)}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-print-content .-sider{flex:0 0 300px;width:300px;border-left:2px solid #ccc;background:#fff}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-print-content .-content{flex:auto;overflow-x:auto;overflow-y:scroll;height:100%}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-canvas-card-wraper{margin:40px 20px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-canvas-card{background:#fff;margin:auto;page-break-before:auto;page-break-after:always;box-shadow:0 8px 10px 1px #00000024,0 3px 14px 3px #0000001f,0 4px 5px #0003}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar{color:#000000a6;background:#fff;-webkit-user-select:none;user-select:none}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar .calendar-header{font-weight:700;line-height:30px;text-align:center;width:100%;float:left;background:#f9fafb}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar .calendar-header .calendar-header-left{padding-left:5px;float:left}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar .calendar-header .calendar-header-right{float:right}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar .calendar-header .calendar-header-right a{padding:3px 0;margin-right:2px;border-radius:2px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar .calendar-header .calendar-header-right a:hover{background:#00000014}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar .calendar-body{border-collapse:collapse;border-spacing:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar .calendar-body th,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar .calendar-body td{width:14.28571429%;min-width:32px;text-align:center;font-weight:700;line-height:30px;padding:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar .calendar-body td>.cell:hover{background:#ecf6fd}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar .calendar-body td>.cell.active,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar .calendar-body td>.cell.active:hover{background:#ecf6fd;color:#2185d0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-calendar .calendar-body td>.cell.disabled{pointer-events:none;opacity:.5}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-datepicker{box-shadow:2px 2px 5px #0003;position:absolute;left:0;top:calc(100% + 5px);z-index:10;width:auto}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-buttons{display:flex;justify-content:flex-end}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-buttons .x-spreadsheet-button{margin-left:8px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-button{display:inline-block;border-radius:3px;line-height:1em;min-height:1em;white-space:nowrap;text-align:center;cursor:pointer;font-size:1em;font-weight:700;padding:.75em 1em;color:#0009;background:#e0e1e2;text-decoration:none;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;outline:none;vertical-align:baseline;zoom:1;-webkit-user-select:none;user-select:none;transition:all .1s linear}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-button.active,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-button:hover{background-color:#c0c1c2;color:#000c}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-button.primary{color:#fff;background-color:#2185d0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-button.primary:hover,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-button.primary.active{color:#fff;background-color:#1678c2}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-input{font-size:1em;position:relative;font-weight:400;display:inline-flex;color:#000000de}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-input input{z-index:1;margin:0;max-width:100%;flex:1 0 auto;outline:0;-webkit-tap-highlight-color:rgba(255,255,255,0);text-align:left;line-height:30px;height:30px;padding:0 8px;background:#fff;border:1px solid #e9e9e9;border-radius:3px;transition:box-shadow .1s ease,border-color .1s ease;box-shadow:inset 0 1px 2px #0a0a0a0f}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-input input:focus{border-color:#4b89ff;box-shadow:inset 0 1px 2px #4b89ff33}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-select{position:relative;display:inline-block;background:#fff;border:1px solid #e9e9e9;border-radius:2px;cursor:pointer;color:#000000de;-webkit-user-select:none;user-select:none;box-shadow:inset 0 1px 2px #0a0a0a0f}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-select .input-text{text-overflow:ellipsis;white-space:nowrap;min-width:60px;width:auto;height:30px;line-height:30px;padding:0 8px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-fields{display:flex;flex-direction:row;flex-wrap:wrap}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-fields .x-spreadsheet-form-field{flex:0 1 auto}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-fields .x-spreadsheet-form-field .label{display:inline-block;margin:0 10px 0 0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-field{display:block;vertical-align:middle;margin-left:10px;margin-bottom:10px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-field:first-child{margin-left:0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-field.error .x-spreadsheet-form-select,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-field.error input{border-color:#f04134}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-form-field .tip{color:#f04134;font-size:.9em}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-dimmer{display:none;position:absolute;top:0!important;left:0!important;width:100%;height:100%;text-align:center;vertical-align:middle;background-color:#0009;opacity:0;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.5s;animation-duration:.5s;transition:background-color .5s linear;-webkit-user-select:none;user-select:none;z-index:1000}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-dimmer.active{display:block;opacity:1}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main form fieldset{border:none}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main form fieldset label{display:block;margin-bottom:.5em;font-size:1em;color:#666}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main form fieldset select{font-size:1.1em;width:100%;background-color:#fff;border:none;border-bottom:2px solid #ddd;padding:.5em .85em;border-radius:2px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-modal,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-toast{font-size:13px;position:fixed;z-index:1001;text-align:left;line-height:1.25em;min-width:360px;color:#000000de;font-family:Lato,Source Sans Pro,Roboto,Helvetica,Arial,sans-serif;border-radius:4px;border:1px solid rgba(0,0,0,.1);background-color:#fff;background-clip:padding-box;box-shadow:#0003 0 2px 8px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-toast{background-color:#ffffffd9}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-modal-header,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-toast-header{font-weight:600;background-clip:padding-box;background-color:#ffffffd9;border-bottom:1px solid rgba(0,0,0,.05);border-radius:4px 4px 0 0}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-toast-header{color:#f2711c}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-modal-header{border-bottom:1px solid #e0e2e4;background:#00000014;font-size:1.0785em}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-modal-header,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-modal-content,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-toast-header,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-toast-content{padding:.75em 1em}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-excel-main .x-spreadsheet-menu li:first-child{display:none}.r-preview-mask .r-preview-contain .r-preview-context .docx-wrapper{background:none}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section{width:100%;height:690px;position:relative;border:1px solid #333;background-color:#efefef;text-align:center;border-radius:10px;box-shadow:1px 1px 3px #aaa;overflow:hidden}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.block{position:absolute;top:0;left:0;width:100%}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.content{display:flex;flex-direction:column}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.v-up{justify-content:flex-start}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.v-mid{justify-content:center}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.v-down{justify-content:flex-end}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.h-left{align-items:flex-start;text-align:left}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.h-mid{align-items:center;text-align:center}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.h-right{align-items:flex-end;text-align:right}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.up-left{justify-content:flex-start;align-items:flex-start;text-align:left}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.up-center{justify-content:flex-start;align-items:center}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.up-right{justify-content:flex-start;align-items:flex-end}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.center-left{justify-content:center;align-items:flex-start;text-align:left}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.center-center{justify-content:center;align-items:center}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.center-right{justify-content:center;align-items:flex-end}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.down-left{justify-content:flex-end;align-items:flex-start;text-align:left}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.down-center{justify-content:flex-end;align-items:center}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section div.down-right{justify-content:flex-end;align-items:flex-end}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main li.slide{margin:10px 0;font-size:18px}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main div.footer{text-align:center}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section table{position:absolute}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section table,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section th,.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section td{border:1px solid black}.r-preview-mask .r-preview-contain .r-preview-context .r-preview-pptx-main section svg.drawing{position:absolute;overflow:visible}',$d="application/vnd.openxmlformats-officedocument.presentationml.presentation",Qd="application/pdf",Wd="application/vnd.openxmlformats-officedocument.wordprocessingml.document",Co="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",So="application/vnd.ms-excel";async function Xd(){if(typeof document<"u"&&!customElements.get("r-preview")){const{warning:k=Yo}=bi,{renderPptx:h}=await V(async()=>{const{renderPptx:q}=await import("./index-Co9E57uv.BBrTYzuH.js");return{renderPptx:q}},__vite__mapDeps([0,1,2])),{renderDocx:p}=await V(async()=>{const{renderDocx:q}=await import("./docx-VUApAnRr.Cl4GUa7G.js");return{renderDocx:q}},__vite__mapDeps([3,4,5])),{renderPdf:f}=await V(async()=>{const{renderPdf:q}=await import("./pdf-Cx0VWKFo.BP4nEulL.js");return{renderPdf:q}},__vite__mapDeps([6,1])),{renderExcel:w}=await V(async()=>{const{renderExcel:q}=await import("./index-Ba501-HG.DsTDD0-N.js");return{renderExcel:q}},__vite__mapDeps([7,5,2,1])),x=(q,j)=>{if(typeof XMLHttpRequest>"u")throw new Error("XMLHttpRequest is not defined");return typeof document>"u"?Promise.reject("document is not defined"):new Promise(function(de,te){const le=new XMLHttpRequest;le.open(j.method||"GET",q,!0),le.responseType=j.responseType||"arraybuffer",le.onload=function(){if(le.status===200){const ce={success:!0,data:le.response,message:""};j.onLoad&&j.onLoad(ce),de(ce)}else{const ce={success:!1,data:le.status,message:`The request status is${le.status}`};j.onError&&j.onError(ce),te(ce)}},le.onerror=function(ce){const Pe={success:!1,data:ce,message:""};j.onError&&j.onError(Pe),te(Pe)},le.onprogress=ce=>{j.onProgress&&j.onProgress(ce)},le.withCredentials=j.withCredentials||!1,j.headers&&Object.keys(j.headers).forEach(function(ce){j!=null&&j.headers&&le.setRequestHeader(ce,j.headers[ce])}),le.send(j.body)})},T=(q,j)=>{const{dom:de,onError:te,onLoad:le}=j;return new Promise((ce,Pe)=>{const ze=new FileReader;ze.readAsArrayBuffer(q),ze.onload=()=>{var qe;if(ze.result&&de){const ei={pptx:ze.result,resultElement:de,onError:te,onLoad:le};(qe=h(ei))==null||qe.then(()=>{ce()})}},ze.onerror=qe=>{Pe(qe)},ze.onabort=qe=>{Pe(qe)}})},D=(q,j)=>{const{dom:de,onError:te,onLoad:le}=j;return Promise.resolve().then(()=>p({buffer:q,bodyContainer:de})).then(()=>{le&&le({success:!0,message:""})}).catch(ce=>{te&&te({success:!0,data:ce,message:""})})},G=new Map([[Qd,f],[$d,T],[Wd,D],[Co,w],[So,w]]);class F extends HTMLElement{constructor(){super(),je(this,"_loadingText"),je(this,"preview"),je(this,"previewContext"),je(this,"_slot"),je(this,"_div"),je(this,"_loadingElement"),je(this,"createLoading",()=>{this._loadingElement=document.createElement("div"),this._loadingElement.setAttribute("class","r-preview-loading");const te=document.createElement("r-icon");return te.setAttribute("name","loading"),te.setAttribute("size","100"),te.setAttribute("color","#1E90FF"),te.setAttribute("spin",""),this._loadingText=document.createElement("div"),this._loadingElement.appendChild(te),this._loadingText.setAttribute("class","r-preview-loading-text"),this._loadingElement.appendChild(this._loadingText),this._loadingElement}),je(this,"onProgress",te=>{const le=te.loaded/te.total*100,ce=Math.min(99,le).toFixed(2)+"%";this._loadingText&&this._loadingElement&&(this._loadingText.innerText=`Loading ${ce}`,le>=100&&setTimeout(()=>{this._loadingText.innerText="Loading..."},300))}),je(this,"onError",()=>{var te;(te=this.preview)==null||te.removeChild(this._loadingElement)}),je(this,"onLoad",()=>{var te;(te=this.preview)==null||te.removeChild(this._loadingElement)}),je(this,"handleFile",async te=>{try{if(typeof te=="string"){const{success:le,data:ce,message:Pe}=await x(te,{onProgress:this.onProgress,onError:this.onError,responseType:"blob"});if(le&&ce){te=new File([ce],ce.name,{type:ce.type});const{type:ze}=te,qe=G.get(ze);if(qe&&this.previewContext){ze===Co||ze===So?this.previewContext.style.setProperty("width","100%"):this.previewContext.style.setProperty("width","100%");const ei={dom:this.previewContext,onError:this.onError,onLoad:this.onLoad};qe(te,ei)}}else k(Pe)}}catch{}}),je(this,"closePreview",()=>{this.preview&&(document.body.removeChild(this.preview),this.preview=void 0)}),je(this,"showPreview",()=>{var te;if(this.src){if(this.preview)this.preview.style.display="block";else{this.preview=document.createElement("div"),this.preview.setAttribute("class","r-preview-mask"),this.preview.setAttribute("id","r-preview-mask");const le=document.createElement("div");if(le.setAttribute("class","r-preview-options"),this.closeable!=="false"){const Pe=document.createElement("r-icon");Pe.setAttribute("class","r-preview-options-close"),Pe.setAttribute("name","close-circle-fill"),Pe.setAttribute("size","40"),Pe.addEventListener("click",this.closePreview),le.appendChild(Pe)}const ce=document.createElement("div");ce.setAttribute("class","r-preview-contain"),this.previewContext=document.createElement("div"),this.previewContext.setAttribute("class","r-preview-context"),ce.appendChild(this.previewContext),this.preview.appendChild(le),(te=this.preview)==null||te.appendChild(ce),this._loadingElement=this.createLoading(),this.preview.appendChild(this._loadingElement),document.body.appendChild(this.preview)}this.handleFile(this.src)}}),this._div=document.createElement("div"),this.preview=document.getElementById("r-preview-mask"),this._slot=document.createElement("slot"),this._div.appendChild(this._slot),this._slot.setAttribute("class","r-preview-slot"),this._div.setAttribute("class","r-preview");const j=this.attachShadow({mode:"closed"}),de=document.createElement("style");de.textContent=To,j.appendChild(de),j.appendChild(this._div)}static get observedAttributes(){return["src","closeable"]}get label(){return this.getAttribute("label")}set label(j){j&&this.setAttribute("label",j)}get src(){return this.getAttribute("src")}set src(j){j&&this.setAttribute("src",j)}get closeable(){return this.getAttribute("closeable")}set closeable(j){j&&this.setAttribute("closeable",j)}connectedCallback(){this.preview=document.getElementById("r-preview-mask"),this.addEventListener("click",this.showPreview)}disconnectedCallback(){this.removeEventListener("click",this.showPreview)}attributeChangedCallback(j,de,te){te!==de&&j==="src"&&te&&(this.setAttribute("src",te),this.showPreview())}}if(typeof document<"u"&&!customElements.get("r-preview")){customElements.define("r-preview",F);const q=z("style").setTextContent(To);document.body.appendChild(q.element)}}}const Jd=Xd(),Zd=Object.freeze(Object.defineProperty({__proto__:null,default:Jd},Symbol.toStringTag,{value:"Module"}));var ec=Object.defineProperty,tc=(k,h,p)=>h in k?ec(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,ic=(k,h,p)=>tc(k,h+"",p);const rc='.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}@keyframes skeleton{0%{transform:translate(-37.5%)}to{transform:translate(37.5%)}}.ran-skeleton{position:relative;z-index:0;overflow:hidden;background:0 0;width:100%;height:16px;background:#0000000f;border-radius:4px}.ran-skeleton:after{position:absolute;top:0;inset-inline-end:-150%;bottom:0;inset-inline-start:-150%;background:linear-gradient(90deg,#0000000f 25%,#00000026 37%,#0000000f 63%);animation-name:skeleton;animation-duration:1.4s;animation-timing-function:ease;animation-iteration-count:infinite;content:""}';function nc(){if(typeof window<"u"&&!customElements.get("r-skeleton")){class k extends HTMLElement{constructor(){super(),ic(this,"_div"),this._div=document.createElement("div"),this._div.setAttribute("class","ran-skeleton");const p=this.attachShadow({mode:"closed"}),f=document.createElement("style");f.textContent=rc,p.appendChild(f),p.appendChild(this._div)}static get observedAttributes(){return["disabled"]}connectedCallback(){}disconnectCallback(){}attributeChangedCallback(p,f,w){}}window.customElements.define("r-skeleton",k)}}const ac=nc(),oc=Object.freeze(Object.defineProperty({__proto__:null,default:ac},Symbol.toStringTag,{value:"Module"}));var sc=Object.defineProperty,lc=(k,h,p)=>h in k?sc(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,sn=(k,h,p)=>lc(k,typeof h!="symbol"?h+"":h,p);const dc=".remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}";function cc(){if(typeof window<"u"&&!customElements.get("r-tab")){class k extends HTMLElement{constructor(){super(),sn(this,"_div"),sn(this,"parent"),sn(this,"initAttribute",()=>{var w,x,T;this.parent=this.parentNode,this.key&&((w=this.parent)==null||w.updateAttribute(this.key,"icon",this.icon)),this.key&&((x=this.parent)==null||x.updateAttribute(this.key,"iconSize",this.iconSize)),this.key&&((T=this.parent)==null||T.updateAttribute(this.key,"effect",this.effect))}),this._div=document.createElement("slot");const p=this.attachShadow({mode:"closed"}),f=document.createElement("style");f.textContent=dc,p.appendChild(f),p.appendChild(this._div)}static get observedAttributes(){return["label","key","disabled","icon","effect","iconSize"]}get label(){return this.getAttribute("label")||""}set label(p){this.setAttribute("label",p)}get icon(){return this.getAttribute("icon")}set icon(p){!p||p==="false"?this.removeAttribute("icon"):this.setAttribute("icon",p)}get iconSize(){return this.getAttribute("iconSize")}set iconSize(p){!p||p==="false"?this.removeAttribute("iconSize"):this.setAttribute("iconSize",p)}get key(){return this.getAttribute("r-key")}set key(p){p?this.setAttribute("r-key",p):this.removeAttribute("r-key")}get disabled(){return this.getAttribute("disabled")}set disabled(p){!p||p==="false"?this.removeAttribute("disabled"):this.setAttribute("disabled",p)}get effect(){return this.getAttribute("effect")}set effect(p){!p||p==="false"?this.removeAttribute("effect"):this.setAttribute("effect",p)}onClick(p){}connectedCallback(){this._div.addEventListener("click",this.onClick),document.addEventListener("DOMContentLoaded",this.initAttribute)}disconnectCallback(){document.removeEventListener("DOMContentLoaded",this.initAttribute)}attributeChangedCallback(p,f,w){var x,T,D,G,F;f!==w&&this.key&&((x=this.parent)!=null&&x.updateAttribute)&&(p==="icon"&&((T=this.parent)==null||T.updateAttribute(this.key,"icon",w)),p==="iconSize"&&((D=this.parent)==null||D.updateAttribute(this.key,"iconSize",w)),p==="effect"&&((G=this.parent)==null||G.updateAttribute(this.key,"effect",w)),p==="disabled"&&((F=this.parent)==null||F.updateAttribute(this.key,"disabled",w)))}}return customElements.define("r-tab",k),k}}const hc=cc(),uc=Object.freeze(Object.defineProperty({__proto__:null,default:hc},Symbol.toStringTag,{value:"Module"}));var fc=Object.defineProperty,pc=(k,h,p)=>h in k?fc(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,Te=(k,h,p)=>pc(k,typeof h!="symbol"?h+"":h,p);const gc='.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}.ran-tab ::slotted(r-tab){box-sizing:border-box;width:100%;height:100%;padding:10px;flex-shrink:0;overflow:auto;text-align:start}.ran-tab-header{position:relative;overflow:hidden;scroll-behavior:smooth}.ran-tab-header-nav{display:flex;flex-flow:row nowrap;justify-content:flex-start;align-items:center}.ran-tab-header-nav::-webkit-scrollbar{display:none}.ran-tab-header-nav-item{flex-shrink:0}.ran-tab-header-nav .active{color:var(--active-color, #1890ff)}.ran-tab-header-line{position:absolute;width:0;margin-top:-2px;height:2px;border-radius:2px;background:var(--line-color, #1890ff);transition:.2s}.ran-tab-content{overflow:hidden}.ran-tab-content-wrap{display:flex;width:100%;height:100%;transition:.2s}:host([type="line"]) .ran-tab-header-nav-item{border:solid 1px transparent}:host([type="line"]) .ran-tab-header-nav .active{color:var(--line-color, #1890ff);border:solid 1px transparent;border-color:var(--border-color, rgba(0, 0, 0, .2)) var(--border-color, rgba(0, 0, 0, .2)) transparent;border-radius:var(--border-radius, .25em) var(--border-radius, .25em) 0 0}:host([type="line"]) .ran-tab-header-line{transition:none;visibility:hidden}:host([type="line"]) .ran-tab-header-line:after,:host([type="line"]) .ran-tab-header-line:before{content:"";position:absolute;visibility:visible;width:9999px;height:1px;bottom:0;background:var(--border-color, rgba(0, 0, 0, .2))}:host([type="line"]) .ran-tab-header-line:after{left:100%}:host([type="line"]) .ran-tab-header-line:before{right:100%}:host([align="center"]) .ran-tab-header-nav{justify-content:center}:host([align="center"]) .ran-tab-header-line{left:50%}:host([align="end"]) .ran-tab-header-nav{justify-content:flex-end}';function mc(){if(typeof window<"u"&&!customElements.get("r-tabs")){class k extends HTMLElement{constructor(){super(),Te(this,"_container"),Te(this,"_header"),Te(this,"_nav"),Te(this,"_line"),Te(this,"_content"),Te(this,"_wrap"),Te(this,"_slot"),Te(this,"tabHeaderKeyMapIndex"),Te(this,"initTabHeaderKeyMapIndex",(w,x)=>{if(this.tabHeaderKeyMapIndex[w])throw new Error("tab 组件的 key 值存在重复,或者某个 tab 组件缺少 key 属性");this.tabHeaderKeyMapIndex[w]=x}),Te(this,"initTabLineAlignCenter",()=>{const{length:w}=this._nav.children;let x=0;for(let T=0;T{const{length:w}=this._nav.children;let x=0;for(let T=0;T{if(w){const x=this.tabHeaderKeyMapIndex[w],T=this._nav.children[x],{width:D=0}=T.getBoundingClientRect();this._line.style.setProperty("width",`${D}px`);let G=0;for(let F=0;F{if(w){const x=this.tabHeaderKeyMapIndex[w];this._wrap.style.setProperty("transform",`translateX(${x*-100}%)`)}}),Te(this,"clickTabHead",w=>{const x=w.target,T=x.getAttribute("r-key");!Ce(x)&&T&&(this.setAttribute("active",T),this.setTabLine(T),this.setTabContent(T),ud(this._nav,"active"),Re(x,"active"))}),Te(this,"updateAttribute",(w,x,T="")=>{var D,G;const F=this.tabHeaderKeyMapIndex[w];w&&T&&this._nav.children[F]?(D=this._nav.children[F])==null||D.setAttribute(x,T):(G=this._nav.children[F])==null||G.removeAttribute(x)}),Te(this,"initActive",()=>{const w=[...this._nav.children],x=w.filter(F=>!Ce(F));let T;if(this.active!=null&&(T=x.find(F=>F.getAttribute("r-key")===this.active),T==null||T.setAttribute("r-key",this.active)),T||(T=x.shift()),!T)return;const D=w.findIndex(F=>F===T),G=(T==null?void 0:T.getAttribute("r-key"))||`${D}`;G!=null&&(this.setAttribute("active",`${G}`),Re(T,"active"),this.setTabContent(G),setTimeout(()=>{this.setTabLine(G)},200))}),Te(this,"listenSlotChange",()=>{this._slot.assignedElements().forEach((x,T)=>{const D=this.createTabHeader(x,T);this._nav.appendChild(D),D.addEventListener("click",this.clickTabHead)}),this.initActive(),this.align&&(this.align==="center"&&this.initTabLineAlignCenter(),this.align==="end"&&this.initTabLineAlignEnd())}),Te(this,"initTab",()=>{this._slot.addEventListener("slotchange",this.listenSlotChange)}),Te(this,"unloadTab",()=>{this._slot.removeEventListener("slotchange",this.listenSlotChange)}),this._container=document.createElement("div"),this._container.setAttribute("class","ran-tab"),this._header=document.createElement("div"),this._header.setAttribute("class","ran-tab-header"),this._nav=document.createElement("div"),this._nav.setAttribute("class","ran-tab-header-nav"),this._line=document.createElement("div"),this._line.setAttribute("class","ran-tab-header-line"),this._content=document.createElement("div"),this._content.setAttribute("class","ran-tab-content"),this._wrap=document.createElement("div"),this._wrap.setAttribute("class","ran-tab-content-wrap"),this._slot=document.createElement("slot"),this._wrap.appendChild(this._slot),this._content.appendChild(this._wrap),this._header.appendChild(rt([this._nav,this._line])),this._container.appendChild(rt([this._header,this._content])),this.tabHeaderKeyMapIndex={};const p=this.attachShadow({mode:"closed"}),f=document.createElement("style");f.textContent=gc,p.appendChild(f),p.appendChild(this._container)}static get observedAttributes(){return["active","forceRender","type","align","effect"]}get align(){return this.getAttribute("align")||"start"}set align(p){this.setAttribute("align",p)}set type(p){this.setAttribute("type",p)}get type(){return this.getAttribute("type")||"flat"}get active(){return this.getAttribute("active")}set active(p){p?(this.setAttribute("active",p),this.setTabLine(p),this.setTabContent(p)):this.removeAttribute("active")}get effect(){return this.getAttribute("effect")}set effect(p){!p||p==="false"?this.removeAttribute("effect"):this.setAttribute("effect",p)}createTabHeader(p,f){const w=p.getAttribute("label")||"",x=p.getAttribute("icon")||"",T=p.getAttribute("iconSize")||"",D=p.getAttribute("r-key")||`${f}`,G=p.getAttribute("type")||"text";this.initTabHeaderKeyMapIndex(D,f);const F=document.createElement("r-button");return F.setAttribute("class","tab-header-nav-item"),F.setAttribute("type",G),x&&F.setAttribute("icon",x),T&&F.setAttribute("iconSize",T),Ce(p)&&F.setAttribute("disabled",""),F.setAttribute("r-key",D),this.effect&&(p.setAttribute("effect",this.effect),this._line.style.setProperty("display","none")),p.setAttribute("r-key",D),F.innerHTML=w,F}connectedCallback(){this.initTab()}disconnectCallback(){this.unloadTab()}attributeChangedCallback(p,f,w){f!==w&&(this.dispatchEvent(new CustomEvent("change",{detail:{active:this.active}})),p==="align"&&(w==="center"&&this.initTabLineAlignCenter(),w==="end"&&this.initTabLineAlignEnd()),p==="effect"&&[...this._nav.children].forEach(T=>{!this.effect||this.effect==="false"?T.removeAttribute("effect"):T.setAttribute("effect",w)}),p==="active"&&this.setAttribute(p,w))}}return customElements.define("r-tabs",k),k}}const vc=mc(),bc=Object.freeze(Object.defineProperty({__proto__:null,default:vc},Symbol.toStringTag,{value:"Module"}));var yc=Object.defineProperty,wc=(k,h,p)=>h in k?yc(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,ht=(k,h,p)=>wc(k,typeof h!="symbol"?h+"":h,p);const Ec=".remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}.ran-radar{position:var(--ran-radar-position, relative);width:var(--ran-radar-width, 100%);height:var(--ran-radar-height, 100%);display:var(--ran-radar-display, block)}",Ac="rgba(0,0,0,0)",_c="rgba(0,0,0,1)",Lo="#e6e6e6",Do="#e6e6e6",kc="黑体",Ro="rgba(255,121,35,0.60)",Io="rgba(255,121,35,0.60)";function xc(){if(typeof document<"u"&&!customElements.get("r-radar")){class k extends HTMLElement{constructor(){super(),ht(this,"mData"),ht(this,"mCount"),ht(this,"mW"),ht(this,"mCenter"),ht(this,"mRadius"),ht(this,"mAngle"),ht(this,"abilityRadarChartContainer"),ht(this,"abilityRadarChart"),ht(this,"_iconElement"),ht(this,"_shadowDom"),this.abilityRadarChartContainer=document.createElement("div"),this.abilityRadarChartContainer.setAttribute("class","ran-radar"),this.abilityRadarChart=document.createElement("canvas"),this.abilityRadarChart.style.setProperty("width","100%"),this.abilityRadarChart.style.setProperty("height","100%"),this.abilityRadarChartContainer.appendChild(this.abilityRadarChart);const p=this.attachShadow({mode:"closed"}),f=document.createElement("style");f.textContent=Ec,p.appendChild(f),this._shadowDom=p,p.appendChild(this.abilityRadarChartContainer)}static get observedAttributes(){return["abilitys","colorPolygon","colorLine","fillColor","strokeColor"]}get abilitys(){const p=this.getAttribute("abilitys");if(typeof p=="string")try{return JSON.parse(p)}catch{return p}return p}set abilitys(p){typeof p=="string"?this.setAttribute("abilitys",p||""):this.setAttribute("abilitys",JSON.stringify(p)||"")}get colorPolygon(){return this.getAttribute("colorPolygon")||Lo}set colorPolygon(p){this.setAttribute("colorPolygon",p||Lo)}get colorLine(){return this.getAttribute("colorLine")||Do}set colorLine(p){this.setAttribute("colorLine",p||Do)}get fillColor(){return this.getAttribute("fillColor")||Ro}set fillColor(p){this.setAttribute("fillColor",p||Ro)}get strokeColor(){return this.getAttribute("strokeColor")||Io}set strokeColor(p){this.setAttribute("strokeColor",p||Io)}refreshData(){var p;const f=this.abilityRadarChart.getContext("2d");if(!this.abilityRadarChartContainer||!f)return;const w=Zt(f),x=this.abilityRadarChartContainer.clientWidth*w,T=this.abilityRadarChartContainer.clientHeight*w;this.abilityRadarChart.width=x,this.abilityRadarChart.height=T,this.mW=x,this.mData=this.abilitys,this.mCount=((p=this.mData)==null?void 0:p.length)||1,this.mCenter=this.mW/2,this.mRadius=this.mCenter-50*w,this.mAngle=Math.PI*2/this.mCount,this.drawPolygon(f),this.drawSide(f),this.drawLines(f),this.drawText(f),this.drawRegion(f),this.drawCircle(f)}drawSide(p){if(!this.mRadius||!this.mCount||!this.mCenter||!this.mAngle)return;p.save(),p.strokeStyle=this.colorLine;const f=this.mRadius;for(let w=0;w=0&&this.mAngle*F=Math.PI/2&&this.mAngle*F=Math.PI&&this.mAngle*Fh in k?Sc(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,St=(k,h,p)=>Lc(k,typeof h!="symbol"?h+"":h,p);const Dc='.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}@keyframes ranui-dropdown-down-in{0%{transform:scaleY(.8);transform-origin:100% 100%;opacity:0}to{transform:scaleY(1);transform-origin:100% 100%;opacity:1}}@keyframes ranui-dropdown-down-out{0%{transform:scaleY(1);transform-origin:100% 100%;opacity:1}to{transform:scaleY(.8);transform-origin:100% 100%;opacity:0}}@keyframes ranui-dropdown-up-in{0%{transform:scaleY(.8);transform-origin:0% 0%;opacity:0}to{transform:scaleY(1);transform-origin:0% 0%;opacity:1}}@keyframes ranui-dropdown-up-out{0%{transform:scaleY(1);transform-origin:0% 0%;opacity:1}to{transform:scaleY(.8);transform-origin:0% 0%;opacity:0}}.ran-dropdown-down-in{animation:ranui-dropdown-up-in .2s;animation-fill-mode:forwards}.ran-dropdown-down-out{animation:ranui-dropdown-up-out .2s;animation-fill-mode:forwards}.ran-dropdown-up-in{animation:ranui-dropdown-down-in .2s;animation-fill-mode:forwards}.ran-dropdown-up-out{animation:ranui-dropdown-down-out .2s;animation-fill-mode:forwards}:host{text-align:var(--ran-dropdown-host-text-align, left);z-index:10}.ranui-dropdown{transform-origin:var(--ran-x, 50%) var(--ran-y, 50%);box-sizing:var(--ran-dropdown-box-sizing, border-box);margin:var(--ran-dropdown-margin, 0);padding:var(--ran-dropdown-padding, 4px);color:var(--ran-dropdown-color, rgba(0, 0, 0, .88));font-size:var(--ran-dropdown-font-size, 14px);list-style:var(--ran-dropdown-list-style, none);font-family:var(--ran-dropdown-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");z-index:var(--ran-dropdown-z-index, 1050);overflow:var(--ran-dropdown-overflow, hidden);font-variant:var(--ran-dropdown-font-variant, initial);background:var(--ran-dropdown-background, #ffffff);border-radius:var(--ran-dropdown-border-radius, 8px);outline:var(--ran-dropdown-outline, none);box-shadow:var(--ran-dropdown-box-shadow, 0 6px 16px 0 rgba(0, 0, 0, .08), 0 3px 6px -4px rgba(0, 0, 0, .12), 0 9px 28px 8px rgba(0, 0, 0, .05));cursor:var(--ran-dropdown-cursor, pointer);width:var(--ran-dropdown-width, 100%)}.ranui-dropdown-container{position:var(--ran-dropdown-container-position, relative);display:var(--ran-dropdown-container-display, inline-block);width:var(--ran-dropdown-container-width, 100%);min-width:var(--ran-popover-width)}.ranui-dropdown-container .top{transform:translate(calc(var(--ran-popover-width) / 2 - 8px)) translateY(-16px) rotate(0);top:0}.ranui-dropdown-container .bottom{transform:translate(calc(var(--ran-popover-width) / 2 - 8px)) translateY(0) rotate(180deg);top:calc(var(--ran-popover-height) - 4px,0px)}.ranui-dropdown-arrow{position:var(--ran-dropdown-arrow-position, absolute);z-index:var(--ran-dropdown-arrow-z-index, 1);display:var(--ran-dropdown-arrow-display, block);pointer-events:var(--ran-dropdown-arrow-pointer-events, none);width:var(--ran-dropdown-arrow-width, 16px);height:var(--ran-dropdown-arrow-height, 16px);overflow:var(--ran-dropdown-arrow-overflow, hidden)}.ranui-dropdown-arrow:before{background:var(--ran-dropdown-arrow-before-background, #fff);position:var(--ran-dropdown-arrow-before-position, absolute);bottom:var(--ran-dropdown-arrow-before-bottom, 0);inset-inline-start:0;width:var(--ran-dropdown-arrow-before-width, 16px);height:var(--ran-dropdown-arrow-before-height, 8px );clip-path:path("M 0 8 A 4 4 0 0 0 2.82842712474619 6.82842712474619 L 6.585786437626905 3.0710678118654755 A 2 2 0 0 1 9.414213562373096 3.0710678118654755 L 13.17157287525381 6.82842712474619 A 4 4 0 0 0 16 8 Z");content:var(--ran-dropdown-arrow-before-content, "")}.ranui-dropdown-arrow:after{content:var(--ran-dropdown-arrow-after-content, "");position:var(--ran-dropdown-arrow-after-position, absolute);width:var(--ran-dropdown-arrow-after-width, 9px);height:var(--ran-dropdown-arrow-after-height, 9px);bottom:var(--ran-dropdown-arrow-after-bottom, 0);inset-inline:0;margin:var(--ran-dropdown-arrow-after-margin, auto);border-radius:var(--ran-dropdown-arrow-after-border-radius, 0 0 2px 0);transform:var(--ran-dropdown-arrow-after-transform, translateY(50%) rotate(-135deg));box-shadow:var(--ran-dropdown-arrow-after-box-shadow, 2px 2px 5px rgba(0, 0, 0, .05));z-index:var(--ran-dropdown-arrow-after-z-index, 0);background:var(--ran-dropdown-arrow-after-background, transparent)}',Po=300;class Oo extends Fe(){constructor(){super(),St(this,"dropdown"),St(this,"_slot"),St(this,"_shadowDom"),St(this,"arrowIcon"),St(this,"container"),St(this,"handlerTransit",()=>{this.transit&&(Re(this.dropdown.element,this.transit),setTimeout(()=>{Ve(this.dropdown.element,this.transit)},Po))}),St(this,"handlerArrow",()=>{this.arrow&&(this.arrowIcon||(this.arrowIcon=z("div").setAttribute("class",`ranui-dropdown-arrow ${this.arrow}`),this.container.addChild([this.arrowIcon])))}),St(this,"stopPropagation",f=>{f.stopPropagation()}),this._slot=z("slot").setAttribute("class","slot"),this.dropdown=z("div").setStyle("-webkit-tap-highlight-color","transparent").setStyle("outline","0").setAttribute("class","ranui-dropdown").setAttribute("part","ranui-dropdown").addChild([this._slot]),this.container=z("div").setAttribute("class","ranui-dropdown-container").addChild([this.dropdown]);const h=this.attachShadow({mode:"closed"}),p=document.createElement("style");p.textContent=Dc,h.appendChild(p),this._shadowDom=h,h.appendChild(this.container.element)}static get observedAttributes(){return["transit","arrow"]}get transit(){return this.getAttribute("transit")||""}set transit(h){h?this.setAttribute("transit",h):this.removeAttribute("transit")}get arrow(){return this.getAttribute("arrow")||""}set arrow(h){h?this.setAttribute("arrow",h):this.removeAttribute("arrow")}get show(){return this.getAttribute("show")||""}set show(h){h?this.setAttribute("show",h):this.removeAttribute("show")}connectedCallback(){this.handlerTransit(),this.handlerArrow()}disconnectedCallback(){}attributeChangedCallback(h,p,f){h==="transit"&&f&&(Re(this.dropdown.element,this.transit),setTimeout(()=>{Ve(this.dropdown.element,this.transit)},Po)),h==="arrow"&&this.handlerArrow()}}function Rc(){return typeof document<"u"&&!customElements.get("r-dropdown")?(customElements.define("r-dropdown",Oo),Oo):Ie("document is undefined or r-dropdown is exist")}Rc();var Ic=Object.defineProperty,Pc=(k,h,p)=>h in k?Ic(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,se=(k,h,p)=>Pc(k,typeof h!="symbol"?h+"":h,p);const Oc='.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}r-select{position:var(--ran-select, relative);width:var(--ran-select, 120px);height:var(--ran-select, 40px)}:host{position:var(--ran-select-host, relative);display:var(--ran-select-host, inline-block);cursor:var(--ran-select-host, pointer);height:var(--ran-select-host, 32px);outline:var(--ran-select-host, 0);-webkit-tap-highlight-color:var(--ran-select-host-highlight-color, transparent)}:host,:host(:focus),:host(:active){outline:var(--ran-select-host-focus-outline, 0);-webkit-tap-highlight-color:transparent}:host ::slotted(r-option){display:none}:host([disabled]){cursor:var(--ran-select-host-disabled-cursor, not-allowed);pointer-events:var(--ran-select-host-disabled-pointer-events, all);opacity:var(--ran-select-host-disabled-opacity, .6)}:host([type="text"])::part(selection){border:none}:host([type="text"])::part(icon){display:none}:host(:not([disabled]):hover) .select{cursor:var(--ran-select-host-hover-cursor, pointer)}:host(:not([disabled]):hover) .selection{border:var(--ran-select-host-selection-border, 1px solid #1890ff)}:host(:not([disabled]):hover) .selection-search{cursor:var(--ran-select-host-selection-search-cursor, pointer)}:host(:not([disabled]):hover) .selection-item{cursor:var(--ran-select-host-selection-item-cursor, pointer);color:var(--ran-select-host-selection-item-color, #bfbfbf)}:host(:not([disabled]):focus) .selection{border:var(--ran-select-host-selection-focus-border, 1px solid #1890ff)}:host(:not([disabled]):focus) .selection-search{cursor:var(--ran-select-host-selection-focus-search-cursor, pointer)}:host(:not([disabled]):focus) .selection-item{cursor:var(--ran-select-host-selection-focus-item-cursor, pointer);color:var(--ran-select-host-selection-focus-item-color, #bfbfbf)}:host .selection-search{display:var(--ran-select-host-selection-search-display, none)}:host([showSearch]:not([disabled])) .selection-search{cursor:var(--ran-select-host-showSearch-selection-search-cursor, text);display:var(--ran-select-host-showSearch-selection-search-display, block)}:host([showSearch]:not([disabled])) .selection-item{cursor:var(--ran-select-host-showSearch-selection-item-cursor, pointer)}:host([showSearch]:not([disabled]):focus) .selection-search{display:var(--ran-select-host-showSearch-selection-search-display, block);cursor:var(--ran-select-host-showSearch-selection-search-cursor, text);opacity:var(--ran-select-host-showSearch-selection-search-opacity, 1)}.ran-select{width:var(--ran-select-width, 100%);height:var(--ran-select-width, 100%);font-size:var(--ran-select-font-size, 14px);box-sizing:var(--ran-select-box-sizing, border-box);margin:var(--ran-select-margin, 0);padding:var(--ran-select-padding, 0);color:var(--ran-select-color, rgba(0, 0, 0, .88));line-height:var(--ran-select-line-height, 1.57142857);list-style:var(--ran-select-list-style, none);font-family:var(--ran-select-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");position:var(--ran-select-position, relative);display:var(--ran-select-display, inline-block)}.ran-select .selection{position:var(--ran-select-selection-position, relative);background-color:var(--ran-select-selection-background-color, #ffffff);border:var(--ran-select-selection-border, 1px solid #d9d9d9);transition:var(--ran-select-selection-transition, all .2s cubic-bezier(.645, .045, .355, 1));width:var(--ran-select-selection-width, 100%);height:var(--ran-select-selection-height, 100%);padding:var(--ran-select-selection-padding, 0 11px);box-sizing:var(--ran-select-selection-box-sizing, border-box);margin:var(--ran-select-selection-margin, 0);color:var(--ran-select-selection-color, rgba(0, 0, 0, .88));font-size:var(--ran-select-selection-font-size, 14px);line-height:var(--ran-select-selection-line-height, 1.57142857);list-style:var(--ran-select-selection-list-style, none);font-family:var(--ran-select-selection-font-family, inherit);display:var(--ran-select-selection-display, flex);border-radius:var(--ran-select-selection-border-radius, 6px)}.ran-select .selection-search{position:var(--ran-select-selection-search-position, absolute);opacity:var(--ran-select-selection-search-opacity, 0);top:var(--ran-select-selection-search-top, 0);left:var(--ran-select-selection-search-left, 0);height:var(--ran-select-selection-search-height, 100%);inset-inline-start:var(--ran-select-selection-search-inset-inline-start, 11px);inset-inline-end:var(--ran-select-selection-search-inset-inline-end, 11px);margin:var(--ran-select-selection-search-margin, 0);padding:var(--ran-select-selection-search-padding, 0);background:var(--ran-select-selection-search-background, transparent);border:var(--ran-select-selection-search-border, none);outline:var(--ran-select-selection-search-outline, none);-webkit-appearance:var(--ran-select-selection-search-appearance, none);-moz-appearance:var(--ran-select-selection-search-appearance, none);appearance:var(--ran-select-selection-search-appearance, none);font-family:var(--ran-select-selection-search-font-family, inherit);cursor:var(--ran-select-selection-search-cursor, not-allowed)}.ran-select .selection-search::-webkit-search-cancel-button{display:none;-webkit-appearance:none}.ran-select .selection-search::part(ran-input){border:none;padding:0;height:100%;outline:none}.ran-select .selection-search::part(ran-input):active{border:none;padding:0;height:100%;outline:none;border-color:transparent;box-shadow:none;border-right-width:0px}.ran-select .selection-item{position:var(--ran-select-selection-item-position, absolute);top:var(--ran-select-selection-item-top, 0);left:var(--ran-select-selection-item-left, 12px);margin:var(--ran-select-selection-item-margin, 0);padding:var(--ran-select-selection-item-padding, 0);background:var(--ran-select-selection-item-background, transparent);border:var(--ran-select-selection-item-border, none);outline:var(--ran-select-selection-item-outline, none);-webkit-appearance:var(--ran-select-selection-item-appearance, none);-moz-appearance:var(--ran-select-selection-item-appearance, none);appearance:var(--ran-select-selection-item-appearance, none);font-family:var(--ran-select-selection-item-font-family, inherit);height:var(--ran-select-selection-item-height, 100%);-webkit-user-select:var(--ran-select-selection-item-user-select, none);user-select:var(--ran-select-selection-item-user-select, none);overflow:var(--ran-select-selection-item-overflow, hidden);white-space:var(--ran-select-selection-item-white-space, nowrap);text-overflow:var(--ran-select-selection-item-text-overflow, ellipsis);cursor:var(--ran-select-selection-item-cursor, pointer)}.ran-select .selection-select{color:var(--ran-select-selection-select-color, rgba(0, 0, 0, .25))}.ran-select .selection .icon{display:var(--ran-select-selection-icon-display, flex);align-items:var(--ran-select-selection-icon-align-items, center);color:var(--ran-select-selection-icon-color, rgba(0, 0, 0, .25));font-style:var(--ran-select-selection-icon-font-style, normal);text-align:var(--ran-select-selection-icon-text-align, center);text-transform:var(--ran-select-selection-icon-text-transform, none);text-rendering:var(--ran-select-selection-icon-text-rendering, optimizeLegibility);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:var(--ran-select-selection-icon-position, absolute);top:var(--ran-select-selection-icon-top, 50%);inset-inline-start:var(--ran-select-selection-icon-inset-inline-start, auto);inset-inline-end:var(--ran-select-selection-icon-inset-inline-end, 8px);height:var(--ran-select-selection-icon-height, 12px);margin-top:var(--ran-select-selection-icon-margin-top, -3px);font-size:var(--ran-select-selection-icon-font-size, 12px);pointer-events:var(--ran-select-selection-icon-color, pointer-events)}';function Mc(){if(typeof document<"u"&&!customElements.get("r-option")){class k extends HTMLElement{constructor(){super(),se(this,"_option"),se(this,"_optionContent"),se(this,"_shadowDom"),se(this,"_slot"),this._slot=document.createElement("slot"),this._option=document.createElement("div"),this._option.setAttribute("class","ran-option"),this._optionContent=document.createElement("div"),this._optionContent.setAttribute("class","ran-option-content"),this._optionContent.appendChild(this._slot),this._option.appendChild(this._optionContent);const p=this.attachShadow({mode:"closed"});this._shadowDom=p,p.appendChild(this._option)}static get observedAttributes(){return["disabled","sheet","value"]}get value(){return this.getAttribute("value")}set value(p){this.setAttribute("value",p||"")}get sheet(){return this.getAttribute("sheet")}set sheet(p){this.setAttribute("sheet",p||"")}get disabled(){return Ce(this)}set disabled(p){!p||p==="false"?this.removeAttribute("disabled"):this.setAttribute("disabled","")}handlerExternalCss(){if(this.sheet)try{const p=new CSSStyleSheet;p.insertRule(this.sheet),this._shadowDom.adoptedStyleSheets=[p]}catch{console.error(`Failed to parse the rule in CSSStyleSheet: ${this.sheet}`)}}connectedCallback(){}disconnectCallback(){}attributeChangedCallback(p,f,w){p==="disabled"&&this._option&&(!w||w==="false"?this._option.setAttribute("disabled",""):this._option.removeAttribute("disabled")),p==="sheet"&&this._shadowDom&&f!==w&&this.handlerExternalCss()}}return k}else return Ie("document is undefined or r-option is exist")}Mc();const Fc='.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}.ranui-dropdown-option-item{position:var(--ran-dropdown-option-item-position, relative);display:var(--ran-dropdown-option-item-display, block);padding:var(--ran-dropdown-option-item-padding, 5px 12px);color:var(--ran-dropdown-option-item-color, rgba(0, 0, 0, .88));font-weight:var(--ran-dropdown-option-item-font-weight, normal);font-size:var(--ran-dropdown-option-item-font-size, 14px);transition:var(--ran-dropdown-option-item-transition, background .3s ease);border-radius:var(--ran-dropdown-option-item-border-radius, 4px)}.ranui-dropdown-option-item:hover{background-color:var(--ran-dropdown-option-item-hover-background-color, rgba(0, 0, 0, .04))}.ranui-dropdown-option-item-content{text-align:var(--ran-dropdown-content-text-align, left);overflow:var(--ran-dropdown-content-overflow, hidden);white-space:var(--ran-dropdown-content-white-space, nowrap);text-overflow:var(--ran-dropdown-content-text-overflow, ellipsis);color:var(--ran-dropdown-content-color, rgba(0, 0, 0, .88));font-size:var(--ran-dropdown-content-font-size, 14px);line-height:var(--ran-dropdown-content-line-height, 1.57142857);box-sizing:var(--ran-dropdown-content-box-sizing, border-box);list-style:var(--ran-dropdown-content-list-style, none);font-family:var(--ran-dropdown-content-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-variant:var(--ran-dropdown-content-font-variant, initial)}.ranui-dropdown-option-active{background-color:var(--ran-dropdown-option-active-background-color, #e6f7ff);font-weight:var(--ran-dropdown-option-active-font-weight, bold)}.ranui-dropdown-option-active:hover{background-color:var(--ran-dropdown-option-active-hover-background-color, #e6f7ff)}';class Mo extends Fe(){constructor(){super(),se(this,"ionDropdownItem"),se(this,"_slot"),se(this,"_shadowDom"),se(this,"ionDropdownItemContent"),this._slot=z("slot").setAttribute("class","slot"),this.ionDropdownItemContent=z("div").setAttribute("class","ranui-dropdown-option-item-content").setAttribute("part","ranui-dropdown-option-item-content").addChild(this._slot),this.ionDropdownItem=z("div").setAttribute("class","ranui-dropdown-option-item").setAttribute("part","ranui-dropdown-option-item").addChild([this.ionDropdownItemContent]);const h=this.attachShadow({mode:"closed"});this._shadowDom=h;const p=z("style").setTextContent(Fc);h.appendChild(p.element),h.appendChild(this.ionDropdownItem.element)}static get observedAttributes(){return["active","value","title"]}get value(){return this.getAttribute("value")||""}set value(h){!Ce(this)&&h?this.setAttribute("value",h):this.removeAttribute("value")}get active(){return this.getAttribute("active")||""}set active(h){h?this.setAttribute("active",h):this.removeAttribute("active")}get title(){return this.getAttribute("title")||""}set title(h){h?this.setAttribute("title",h):this.removeAttribute("title")}connectedCallback(){this.active&&Re(this.ionDropdownItem.element,"ranui-dropdown-option-active")}attributeChangedCallback(h,p,f){h==="active"&&f?Re(this.ionDropdownItem.element,"ranui-dropdown-option-active"):Ve(this.ionDropdownItem.element,"ranui-dropdown-option-active")}}function Bc(){return typeof document<"u"&&!customElements.get("r-dropdown-item")?(customElements.define("r-dropdown-item",Mo),Mo):Ie("document is undefined or r-dropdown-item is exist")}Bc();const Fo={bottom:{add:"ran-dropdown-down-in",remove:"ran-dropdown-down-out"},top:{add:"ran-dropdown-up-in",remove:"ran-dropdown-up-out"}},Nc=Zi(),Bo=300;let pn=class extends Fe(){constructor(){super(),se(this,"removeTimeId"),se(this,"_slot"),se(this,"_shadowDom"),se(this,"_select"),se(this,"_selection"),se(this,"_search"),se(this,"_icon"),se(this,"_selectDropdown"),se(this,"_selectionDropdown"),se(this,"_selectDropDownInTimeId"),se(this,"_selectDropDownOutTimeId"),se(this,"_optionList"),se(this,"_optionLabelMapValue"),se(this,"_optionValueMapLabel"),se(this,"_activeOption"),se(this,"_text"),se(this,"_selector"),se(this,"onSearch"),se(this,"setSelectDropdownDisplayNone",()=>{this._selectDropDownOutTimeId||this._selectionDropdown&&this._selectionDropdown.style.display!=="none"&&(this._selectionDropdown.setAttribute("transit",Fo[this.placement].remove),this._selectDropDownOutTimeId=setTimeout(()=>{var f;(f=this._selectionDropdown)==null||f.style.setProperty("display","none"),this._selectionDropdown&&this._selectionDropdown.removeAttribute("transit"),clearTimeout(this._selectDropDownOutTimeId),this._selectDropDownOutTimeId=void 0},Bo))}),se(this,"setSelectDropdownDisplayBlock",()=>{var f;this._selectDropDownInTimeId||this._selectionDropdown&&this._selectionDropdown.style.display!=="block"&&(this._selectionDropdown.setAttribute("transit",Fo[this.placement].add),(f=this._selectionDropdown)==null||f.style.setProperty("display","block"),this._selectDropDownInTimeId=setTimeout(()=>{this._selectionDropdown&&this._selectionDropdown.removeAttribute("transit"),clearTimeout(this._selectDropDownInTimeId),this._selectDropDownInTimeId=void 0},Bo))}),se(this,"placementPosition",()=>{if(!this._selectionDropdown||!this._selectDropdown)return;const f=this.getBoundingClientRect(),{top:w,left:x,bottom:T,width:D,height:G,x:F,y:q,right:j}=f,de=document.getElementById(this.getPopupContainerId);this._selectionDropdown.style.setProperty("position","absolute"),this._selectionDropdown.style.setProperty("--ran-x",`${w+window.scrollX}`),this._selectionDropdown.style.setProperty("--ran-y",`${x+window.scrollY}`);let te=T+window.scrollY,le=x+window.scrollX;if(this._selectionDropdown.style.setProperty("width",`${D}px`),this.placement==="top"&&(te=w+window.scrollY-this._selectionDropdown.clientHeight),this.getPopupContainerId&&de){const ce=de.getBoundingClientRect();le=x-ce.left,this.placement==="top"?te=w-de.getBoundingClientRect().top-this._selectionDropdown.clientHeight:te=de.getBoundingClientRect().height}this._selectionDropdown.style.setProperty("inset",`${te}px auto auto ${le}px`)}),se(this,"selectMouseDown",f=>{f.stopPropagation(),!Ce(this)&&(this.removeDropDownTimeId(f),this.setSelectDropdownDisplayNone(),this.setSelectDropdownDisplayBlock(),this.placementPosition())}),se(this,"removeDropDownTimeId",f=>{f.stopPropagation(),this._search.setAttribute("value",""),this.trigger.includes("hover")&&!_t()&&(clearTimeout(this.removeTimeId),this.removeTimeId=void 0)}),se(this,"selectBlur",f=>{f.stopPropagation(),this.removeTimeId&&this.removeDropDownTimeId(f),this.removeTimeId=setTimeout(()=>{this.removeDropDownTimeId(f),this.setSelectDropdownDisplayNone()},300)}),se(this,"clickOption",f=>{f.stopPropagation();const w=f.target,x=w.innerHTML,T=this._optionLabelMapValue.get(x);T&&(this.setAttribute("value",T),this._text.innerHTML=x,this._text.setAttribute("title",x),this._search.setAttribute("placeholder",x));const D=this.getBoundingClientRect(),{height:G}=D;this._text.style.setProperty("line-height",`${G}px`),this._activeOption&&this._activeOption.removeAttribute("active"),this._activeOption=w,this._activeOption&&this._activeOption.setAttribute("active",T||""),this.setSelectDropdownDisplayNone(),this.dispatchEvent(new CustomEvent("change",{detail:{value:T,label:x}})),this.removeDropDownTimeId(f)}),se(this,"createOption",()=>{if(!this._selectDropdown){const f=document.getElementById(this.getPopupContainerId)||document.body;this._selectDropdown=document.createElement("div"),this._selectDropdown.style.setProperty("-webkit-tap-highlight-color","transparent"),this._selectDropdown.style.setProperty("outline","0"),this._selectDropdown.addEventListener("click",this.clickOption),this._selectionDropdown=document.createElement("r-dropdown"),this.dropdownclass&&this._selectionDropdown.setAttribute("class",this.dropdownclass),this.trigger.includes("hover")&&!_t()&&(this._selectDropdown.addEventListener("mouseleave",this.selectBlur),this._selectDropdown.addEventListener("mouseenter",this.removeDropDownTimeId)),this._selectDropdown.appendChild(this._selectionDropdown),this._selectionDropdown.style.setProperty("display","none"),f.appendChild(this._selectDropdown)}}),se(this,"removeSelectDropdown",()=>{try{this._selectDropdown&&(document.getElementById(this.getPopupContainerId)||document.body).removeChild(this._selectDropdown)}catch{}}),se(this,"addOptionToSlot",()=>{this._slot.assignedElements().forEach(w=>{var x;if(w.tagName!=="R-OPTION")return;const T=w.innerHTML,D=w.getAttribute("value")||"";(x=this._optionList)==null||x.push({label:T,value:D}),this._optionLabelMapValue.get(T)&&console.warn(`${T} is repeat option`),this._optionValueMapLabel.get(D)&&console.warn(`${D} is repeat option`),this._optionLabelMapValue.set(T,D),this._optionValueMapLabel.set(D,T)}),this.createSelectDropdownContent(this._optionList)}),se(this,"createSelectDropdownContent",(f=[])=>{var w,x;f.length===0?(w=this._selectDropdown)==null||w.style.setProperty("display","none"):(x=this._selectDropdown)==null||x.style.setProperty("display","block"),f.forEach(T=>{if(this._selectionDropdown){const{label:D,value:G}=T,F=document.createElement("r-dropdown-item");(this.getAttribute("defaultValue")||this.getAttribute("value"))===G?(F.setAttribute("active",G),this._activeOption=F):F.removeAttribute("active"),F.innerHTML=`${D}`,F.setAttribute("value",`${G}`),F.setAttribute("title",`${D}`),this._selectionDropdown.appendChild(F)}}),this.setDefaultValue()}),se(this,"setDefaultValue",()=>{const f=this.getAttribute("defaultValue")||this.getAttribute("value");if(!f)return;const w=this._optionValueMapLabel.get(f);if(!w)return;this.setAttribute("value",f);const x=this.getBoundingClientRect(),{height:T}=x;this._text.style.setProperty("line-height",`${T}px`),this._text.innerHTML=w,this._text.setAttribute("title",w)}),se(this,"changeSearch",f=>{const w=f.detail.value||"";if(this.dispatchEvent(new CustomEvent("search",{detail:{value:w}})),this._selectionDropdown&&(this._selectionDropdown.innerHTML=""),w.length>0){const x=this._optionList.map(T=>{const{label:D}=T;if(`${D}`.toLowerCase().includes(w))return{label:D,value:T.value}}).filter(T=>T);this.createSelectDropdownContent(x)}else this.createSelectDropdownContent(this._optionList)}),se(this,"setShowSearch",()=>{this.onSearch=Nc(this.changeSearch),this.onSearch&&this._search.addEventListener("change",this.onSearch),this.onSearch&&this._search.addEventListener("click",this.onSearch)}),se(this,"removeShowSearch",()=>{this.onSearch&&this._search.removeEventListener("change",this.onSearch),this.onSearch&&this._search.removeEventListener("click",this.onSearch)}),se(this,"listenSlotChange",()=>{this._slot.addEventListener("slotchange",this.addOptionToSlot)}),se(this,"removeListenSlotChange",()=>{this._slot.removeEventListener("slotchange",this.addOptionToSlot)}),se(this,"listenActionEvent",()=>{this.removeEventListener("mouseenter",this.selectMouseDown),this.removeEventListener("mouseleave",this.selectBlur),this.removeEventListener("click",this.selectMouseDown),this.removeEventListener("blur",this.selectBlur),this.trigger.includes("hover")&&!_t()&&(this.addEventListener("mouseenter",this.selectMouseDown),this.addEventListener("mouseleave",this.selectBlur)),this.trigger.includes("click")&&(this.addEventListener("click",this.selectMouseDown),this.addEventListener("blur",this.selectBlur))}),se(this,"clickRemoveSelect",f=>{f.stopPropagation(),this.setSelectDropdownDisplayNone()}),this._slot=document.createElement("slot"),this._select=document.createElement("div"),this._select.setAttribute("class","ran-select"),this._select.setAttribute("part","select"),this._selection=document.createElement("div"),this._selection.setAttribute("class","selection"),this._selection.setAttribute("part","selection"),this._selector=document.createElement("div"),this._search=document.createElement("r-input"),this._search.setAttribute("class","selection-search"),this._search.setAttribute("part","search"),this._search.setAttribute("type","search"),this._search.setAttribute("autocomplete","off"),this._text=document.createElement("span"),this._text.setAttribute("class","selection-item"),this._text.setAttribute("part","selection-item"),this._icon=document.createElement("ra-icon"),this._icon.setAttribute("class","icon"),this._icon.setAttribute("part","icon"),this._icon.setAttribute("name","arrow-down"),this._icon.setAttribute("color","#d9d9d9"),this._icon.setAttribute("size","16"),this._selector.appendChild(this._text),this._selector.appendChild(this._search),this._selection.appendChild(this._icon),this._selection.appendChild(this._selector),this._slot.setAttribute("class","slot"),this._select.appendChild(this._selection),this._select.appendChild(this._slot),this._optionList=[],this._optionLabelMapValue=new Map,this._optionValueMapLabel=new Map;const h=this.attachShadow({mode:"closed"}),p=document.createElement("style");p.textContent=Oc,h.appendChild(p),this._shadowDom=h,this._shadowDom.appendChild(this._select)}static get observedAttributes(){return["disabled","sheet","clear","type","defaultValue","showSearch","placement","getPopupContainerId","dropdownclass","trigger"]}get value(){return this.getAttribute("value")||""}set value(h){!Ce(this)&&h?this.setAttribute("value",h):this.removeAttribute("value")}get defaultValue(){return this.getAttribute("defaultValue")||""}set defaultValue(h){this.setAttribute("defaultValue",h||"")}get showSearch(){return this.getAttribute("showSearch")||""}set showSearch(h){this.setAttribute("showSearch",h||"")}get type(){return this.getAttribute("type")||""}set type(h){this.setAttribute("type",h||"")}get placement(){return this.getAttribute("placement")||"bottom"}set placement(h){this.setAttribute("placement",h||"")}get sheet(){return this.getAttribute("sheet")||""}set sheet(h){this.setAttribute("sheet",h||"")}get getPopupContainerId(){return this.getAttribute("getPopupContainerId")||""}set getPopupContainerId(h){this.setAttribute("getPopupContainerId",h||"")}get dropdownclass(){return this.getAttribute("dropdownclass")||""}set dropdownclass(h){this.setAttribute("dropdownclass",h||"")}get trigger(){return this.getAttribute("trigger")||"click"}set trigger(h){this.setAttribute("trigger",h||"")}get disabled(){return Ce(this)}set disabled(h){!h||h==="false"?(this.removeAttribute("disabled"),this._selection.removeAttribute("disabled")):(this.setAttribute("disabled",""),this._selection.setAttribute("disabled",""))}handlerExternalCss(){if(this.sheet)try{const h=new CSSStyleSheet;h.insertRule(this.sheet),this._shadowDom.adoptedStyleSheets=[h]}catch{console.error(`Failed to parse the rule in CSSStyleSheet: ${this.sheet}`)}}connectedCallback(){this.handlerExternalCss(),this.createOption(),this.listenActionEvent(),this.listenSlotChange(),this.setShowSearch(),document.addEventListener("click",this.clickRemoveSelect)}disconnectCallback(){var h;this.removeEventListener("mouseenter",this.selectMouseDown),this.removeEventListener("mouseleave",this.selectBlur),this.removeEventListener("click",this.selectMouseDown),this.removeEventListener("blur",this.selectBlur),this.removeSelectDropdown(),(h=this._selectDropdown)==null||h.removeEventListener("click",this.clickOption),this.removeListenSlotChange(),document.removeEventListener("click",this.clickRemoveSelect)}attributeChangedCallback(h,p,f){h==="disabled"&&this._select&&(!f||f==="false"?(this._select.setAttribute("disabled",""),this._selection.setAttribute("disabled","")):(this._select.removeAttribute("disabled"),this._selection.removeAttribute("disabled"))),h==="sheet"&&this._shadowDom&&p!==f&&this.handlerExternalCss()}};function Uc(){return typeof document<"u"&&!customElements.get("r-select")?(customElements.define("r-select",pn),pn):Ie("document is undefined or r-select is exist")}const Gc=Uc(),Hc=Object.freeze(Object.defineProperty({__proto__:null,Select:pn,default:Gc},Symbol.toStringTag,{value:"Module"}));var Kc=Object.defineProperty,Vc=(k,h,p)=>h in k?Kc(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,H=(k,h,p)=>Vc(k,typeof h!="symbol"?h+"":h,p);(function k(h){var p,f;p=this,f=function(){function w(o,n){var e=Object.keys(o);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(o);n&&(t=t.filter(function(i){return Object.getOwnPropertyDescriptor(o,i).enumerable})),e.push.apply(e,t)}return e}function x(o){for(var n=1;n"u"||!Reflect.construct||Reflect.construct.sham)return!1;if(typeof Proxy=="function")return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch{return!1}}function le(o,n,e){return le=te()?Reflect.construct.bind():function(t,i,r){var a=[null];a.push.apply(a,i);var s=new(Function.bind.apply(t,a));return r&&de(s,r.prototype),s},le.apply(null,arguments)}function ce(o){var n=typeof Map=="function"?new Map:void 0;return ce=function(e){if(e===null||(t=e,Function.toString.call(t).indexOf("[native code]")===-1))return e;var t;if(typeof e!="function")throw new TypeError("Super expression must either be null or a function");if(n!==void 0){if(n.has(e))return n.get(e);n.set(e,i)}function i(){return le(e,arguments,j(this).constructor)}return i.prototype=Object.create(e.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}),de(i,e)},ce(o)}function Pe(o,n){(n==null||n>o.length)&&(n=o.length);for(var e=0,t=new Array(n);e=o.length?{done:!0}:{done:!1,value:o[t++]}}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function qe(o){var n=function(e,t){if(typeof e!="object"||e===null)return e;var i=e[Symbol.toPrimitive];if(i!==void 0){var r=i.call(e,t||"default");if(typeof r!="object")return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return(t==="string"?String:Number)(e)}(o,"string");return typeof n=="symbol"?n:String(n)}function ei(o){return o&&o.__esModule&&Object.prototype.hasOwnProperty.call(o,"default")?o.default:o}var _n={exports:{}};(function(o,n){var e,t,i,r,a;e=/^(?=((?:[a-zA-Z0-9+\-.]+:)?))\1(?=((?:\/\/[^\/?#]*)?))\2(?=((?:(?:[^?#\/]*\/)*[^;?#\/]*)?))\3((?:;[^?#]*)?)(\?[^#]*)?(#[^]*)?$/,t=/^(?=([^\/?#]*))\1([^]*)$/,i=/(?:\/|^)\.(?=\/)/g,r=/(?:\/|^)\.\.\/(?!\.\.\/)[^\/]*(?=\/)/g,a={buildAbsoluteURL:function(s,l,d){if(d=d||{},s=s.trim(),!(l=l.trim())){if(!d.alwaysNormalize)return s;var c=a.parseURL(s);if(!c)throw new Error("Error trying to parse base URL.");return c.path=a.normalizePath(c.path),a.buildURLFromParts(c)}var u=a.parseURL(l);if(!u)throw new Error("Error trying to parse relative URL.");if(u.scheme)return d.alwaysNormalize?(u.path=a.normalizePath(u.path),a.buildURLFromParts(u)):l;var g=a.parseURL(s);if(!g)throw new Error("Error trying to parse base URL.");if(!g.netLoc&&g.path&&g.path[0]!=="/"){var m=t.exec(g.path);g.netLoc=m[1],g.path=m[2]}g.netLoc&&!g.path&&(g.path="/");var v={scheme:g.scheme,netLoc:u.netLoc,path:null,params:u.params,query:u.query,fragment:u.fragment};if(!u.netLoc&&(v.netLoc=g.netLoc,u.path[0]!=="/"))if(u.path){var y=g.path,_=y.substring(0,y.lastIndexOf("/")+1)+u.path;v.path=a.normalizePath(_)}else v.path=g.path,u.params||(v.params=g.params,u.query||(v.query=g.query));return v.path===null&&(v.path=d.alwaysNormalize?a.normalizePath(u.path):u.path),a.buildURLFromParts(v)},parseURL:function(s){var l=e.exec(s);return l?{scheme:l[1]||"",netLoc:l[2]||"",path:l[3]||"",params:l[4]||"",query:l[5]||"",fragment:l[6]||""}:null},normalizePath:function(s){for(s=s.split("").reverse().join("").replace(i,"");s.length!==(s=s.replace(r,"")).length;);return s.split("").reverse().join("")},buildURLFromParts:function(s){return s.scheme+s.netLoc+s.path+s.params+s.query+s.fragment}},o.exports=a})(_n);var er=_n.exports,ie=Number.isFinite||function(o){return typeof o=="number"&&isFinite(o)},A=function(o){return o.MEDIA_ATTACHING="hlsMediaAttaching",o.MEDIA_ATTACHED="hlsMediaAttached",o.MEDIA_DETACHING="hlsMediaDetaching",o.MEDIA_DETACHED="hlsMediaDetached",o.BUFFER_RESET="hlsBufferReset",o.BUFFER_CODECS="hlsBufferCodecs",o.BUFFER_CREATED="hlsBufferCreated",o.BUFFER_APPENDING="hlsBufferAppending",o.BUFFER_APPENDED="hlsBufferAppended",o.BUFFER_EOS="hlsBufferEos",o.BUFFER_FLUSHING="hlsBufferFlushing",o.BUFFER_FLUSHED="hlsBufferFlushed",o.MANIFEST_LOADING="hlsManifestLoading",o.MANIFEST_LOADED="hlsManifestLoaded",o.MANIFEST_PARSED="hlsManifestParsed",o.LEVEL_SWITCHING="hlsLevelSwitching",o.LEVEL_SWITCHED="hlsLevelSwitched",o.LEVEL_LOADING="hlsLevelLoading",o.LEVEL_LOADED="hlsLevelLoaded",o.LEVEL_UPDATED="hlsLevelUpdated",o.LEVEL_PTS_UPDATED="hlsLevelPtsUpdated",o.LEVELS_UPDATED="hlsLevelsUpdated",o.AUDIO_TRACKS_UPDATED="hlsAudioTracksUpdated",o.AUDIO_TRACK_SWITCHING="hlsAudioTrackSwitching",o.AUDIO_TRACK_SWITCHED="hlsAudioTrackSwitched",o.AUDIO_TRACK_LOADING="hlsAudioTrackLoading",o.AUDIO_TRACK_LOADED="hlsAudioTrackLoaded",o.SUBTITLE_TRACKS_UPDATED="hlsSubtitleTracksUpdated",o.SUBTITLE_TRACKS_CLEARED="hlsSubtitleTracksCleared",o.SUBTITLE_TRACK_SWITCH="hlsSubtitleTrackSwitch",o.SUBTITLE_TRACK_LOADING="hlsSubtitleTrackLoading",o.SUBTITLE_TRACK_LOADED="hlsSubtitleTrackLoaded",o.SUBTITLE_FRAG_PROCESSED="hlsSubtitleFragProcessed",o.CUES_PARSED="hlsCuesParsed",o.NON_NATIVE_TEXT_TRACKS_FOUND="hlsNonNativeTextTracksFound",o.INIT_PTS_FOUND="hlsInitPtsFound",o.FRAG_LOADING="hlsFragLoading",o.FRAG_LOAD_EMERGENCY_ABORTED="hlsFragLoadEmergencyAborted",o.FRAG_LOADED="hlsFragLoaded",o.FRAG_DECRYPTED="hlsFragDecrypted",o.FRAG_PARSING_INIT_SEGMENT="hlsFragParsingInitSegment",o.FRAG_PARSING_USERDATA="hlsFragParsingUserdata",o.FRAG_PARSING_METADATA="hlsFragParsingMetadata",o.FRAG_PARSED="hlsFragParsed",o.FRAG_BUFFERED="hlsFragBuffered",o.FRAG_CHANGED="hlsFragChanged",o.FPS_DROP="hlsFpsDrop",o.FPS_DROP_LEVEL_CAPPING="hlsFpsDropLevelCapping",o.ERROR="hlsError",o.DESTROYING="hlsDestroying",o.KEY_LOADING="hlsKeyLoading",o.KEY_LOADED="hlsKeyLoaded",o.LIVE_BACK_BUFFER_REACHED="hlsLiveBackBufferReached",o.BACK_BUFFER_REACHED="hlsBackBufferReached",o}({}),ne=function(o){return o.NETWORK_ERROR="networkError",o.MEDIA_ERROR="mediaError",o.KEY_SYSTEM_ERROR="keySystemError",o.MUX_ERROR="muxError",o.OTHER_ERROR="otherError",o}({}),O=function(o){return o.KEY_SYSTEM_NO_KEYS="keySystemNoKeys",o.KEY_SYSTEM_NO_ACCESS="keySystemNoAccess",o.KEY_SYSTEM_NO_SESSION="keySystemNoSession",o.KEY_SYSTEM_NO_CONFIGURED_LICENSE="keySystemNoConfiguredLicense",o.KEY_SYSTEM_LICENSE_REQUEST_FAILED="keySystemLicenseRequestFailed",o.KEY_SYSTEM_SERVER_CERTIFICATE_REQUEST_FAILED="keySystemServerCertificateRequestFailed",o.KEY_SYSTEM_SERVER_CERTIFICATE_UPDATE_FAILED="keySystemServerCertificateUpdateFailed",o.KEY_SYSTEM_SESSION_UPDATE_FAILED="keySystemSessionUpdateFailed",o.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED="keySystemStatusOutputRestricted",o.KEY_SYSTEM_STATUS_INTERNAL_ERROR="keySystemStatusInternalError",o.MANIFEST_LOAD_ERROR="manifestLoadError",o.MANIFEST_LOAD_TIMEOUT="manifestLoadTimeOut",o.MANIFEST_PARSING_ERROR="manifestParsingError",o.MANIFEST_INCOMPATIBLE_CODECS_ERROR="manifestIncompatibleCodecsError",o.LEVEL_EMPTY_ERROR="levelEmptyError",o.LEVEL_LOAD_ERROR="levelLoadError",o.LEVEL_LOAD_TIMEOUT="levelLoadTimeOut",o.LEVEL_PARSING_ERROR="levelParsingError",o.LEVEL_SWITCH_ERROR="levelSwitchError",o.AUDIO_TRACK_LOAD_ERROR="audioTrackLoadError",o.AUDIO_TRACK_LOAD_TIMEOUT="audioTrackLoadTimeOut",o.SUBTITLE_LOAD_ERROR="subtitleTrackLoadError",o.SUBTITLE_TRACK_LOAD_TIMEOUT="subtitleTrackLoadTimeOut",o.FRAG_LOAD_ERROR="fragLoadError",o.FRAG_LOAD_TIMEOUT="fragLoadTimeOut",o.FRAG_DECRYPT_ERROR="fragDecryptError",o.FRAG_PARSING_ERROR="fragParsingError",o.FRAG_GAP="fragGap",o.REMUX_ALLOC_ERROR="remuxAllocError",o.KEY_LOAD_ERROR="keyLoadError",o.KEY_LOAD_TIMEOUT="keyLoadTimeOut",o.BUFFER_ADD_CODEC_ERROR="bufferAddCodecError",o.BUFFER_INCOMPATIBLE_CODECS_ERROR="bufferIncompatibleCodecsError",o.BUFFER_APPEND_ERROR="bufferAppendError",o.BUFFER_APPENDING_ERROR="bufferAppendingError",o.BUFFER_STALLED_ERROR="bufferStalledError",o.BUFFER_FULL_ERROR="bufferFullError",o.BUFFER_SEEK_OVER_HOLE="bufferSeekOverHole",o.BUFFER_NUDGE_ON_STALL="bufferNudgeOnStall",o.INTERNAL_EXCEPTION="internalException",o.INTERNAL_ABORTED="aborted",o.UNKNOWN="unknown",o}({}),Rt=function(){},tr={trace:Rt,debug:Rt,log:Rt,warn:Rt,info:Rt,error:Rt},ti=tr;function Qo(o){var n=self.console[o];return n?n.bind(self.console,"["+o+"] >"):Rt}function kn(o,n){if(self.console&&o===!0||typeof o=="object"){(function(e){for(var t=arguments.length,i=new Array(t>1?t-1:0),r=1;rNumber.MAX_SAFE_INTEGER?1/0:t},n.hexadecimalInteger=function(e){if(this[e]){var t=(this[e]||"0x").slice(2);t=(1&t.length?"0":"")+t;for(var i=new Uint8Array(t.length/2),r=0;rNumber.MAX_SAFE_INTEGER?1/0:t},n.decimalFloatingPoint=function(e){return parseFloat(this[e])},n.optionalFloat=function(e,t){var i=this[e];return i?parseFloat(i):t},n.enumeratedString=function(e){return this[e]},n.bool=function(e){return this[e]==="YES"},n.decimalResolution=function(e){var t=Wo.exec(this[e]);if(t!==null)return{width:parseInt(t[1],10),height:parseInt(t[2],10)}},o.parseAttrList=function(e){var t,i={};for(xn.lastIndex=0;(t=xn.exec(e))!==null;){var r=t[2];r.indexOf('"')===0&&r.lastIndexOf('"')===r.length-1&&(r=r.slice(1,-1)),i[t[1].trim()]=r}return i},o}();function Xo(o){return o==="SCTE35-OUT"||o==="SCTE35-IN"}var Tn=function(){function o(n,e){if(this.attr=void 0,this._startDate=void 0,this._endDate=void 0,this._badValueForSameId=void 0,e){var t=e.attr;for(var i in t)if(Object.prototype.hasOwnProperty.call(n,i)&&n[i]!==t[i]){R.warn('DATERANGE tag attribute: "'+i+'" does not match for tags with ID: "'+n.ID+'"'),this._badValueForSameId=i;break}n=F(new _e({}),t,n)}if(this.attr=n,this._startDate=new Date(n["START-DATE"]),"END-DATE"in this.attr){var r=new Date(this.attr["END-DATE"]);ie(r.getTime())&&(this._endDate=r)}}return D(o,[{key:"id",get:function(){return this.attr.ID}},{key:"class",get:function(){return this.attr.CLASS}},{key:"startDate",get:function(){return this._startDate}},{key:"endDate",get:function(){if(this._endDate)return this._endDate;var n=this.duration;return n!==null?new Date(this._startDate.getTime()+1e3*n):null}},{key:"duration",get:function(){if("DURATION"in this.attr){var n=this.attr.decimalFloatingPoint("DURATION");if(ie(n))return n}else if(this._endDate)return(this._endDate.getTime()-this._startDate.getTime())/1e3;return null}},{key:"plannedDuration",get:function(){return"PLANNED-DURATION"in this.attr?this.attr.decimalFloatingPoint("PLANNED-DURATION"):null}},{key:"endOnNext",get:function(){return this.attr.bool("END-ON-NEXT")}},{key:"isValid",get:function(){return!!this.id&&!this._badValueForSameId&&ie(this.startDate.getTime())&&(this.duration===null||this.duration>=0)&&(!this.endOnNext||!!this.class)}}]),o}(),yi=function(){this.aborted=!1,this.loaded=0,this.retry=0,this.total=0,this.chunkCount=0,this.bwEstimate=0,this.loading={start:0,first:0,end:0},this.parsing={start:0,end:0},this.buffering={start:0,first:0,end:0}},Be="audio",Ze="video",ir="audiovideo",Cn=function(){function o(n){var e;this._byteRange=null,this._url=null,this.baseurl=void 0,this.relurl=void 0,this.elementaryStreams=((e={})[Be]=null,e[Ze]=null,e[ir]=null,e),this.baseurl=n}return o.prototype.setByteRange=function(n,e){var t=n.split("@",2),i=[];t.length===1?i[0]=e?e.byteRangeEndOffset:0:i[0]=parseInt(t[1]),i[1]=parseInt(t[0])+i[0],this._byteRange=i},D(o,[{key:"byteRange",get:function(){return this._byteRange?this._byteRange:[]}},{key:"byteRangeStartOffset",get:function(){return this.byteRange[0]}},{key:"byteRangeEndOffset",get:function(){return this.byteRange[1]}},{key:"url",get:function(){return!this._url&&this.baseurl&&this.relurl&&(this._url=er.buildAbsoluteURL(this.baseurl,this.relurl,{alwaysNormalize:!0})),this._url||""},set:function(n){this._url=n}}]),o}(),rr=function(o){function n(t,i){var r;return(r=o.call(this,i)||this)._decryptdata=null,r.rawProgramDateTime=null,r.programDateTime=null,r.tagList=[],r.duration=0,r.sn=0,r.levelkeys=void 0,r.type=void 0,r.loader=null,r.keyLoader=null,r.level=-1,r.cc=0,r.startPTS=void 0,r.endPTS=void 0,r.startDTS=void 0,r.endDTS=void 0,r.start=0,r.deltaPTS=void 0,r.maxStartPTS=void 0,r.minEndPTS=void 0,r.stats=new yi,r.urlId=0,r.data=void 0,r.bitrateTest=!1,r.title=null,r.initSegment=null,r.endList=void 0,r.gap=void 0,r.type=t,r}q(n,o);var e=n.prototype;return e.setKeyFormat=function(t){if(this.levelkeys){var i=this.levelkeys[t];i&&!this._decryptdata&&(this._decryptdata=i.getDecryptData(this.sn))}},e.abortRequests=function(){var t,i;(t=this.loader)==null||t.abort(),(i=this.keyLoader)==null||i.abort()},e.setElementaryStreamInfo=function(t,i,r,a,s,l){l===void 0&&(l=!1);var d=this.elementaryStreams,c=d[t];c?(c.startPTS=Math.min(c.startPTS,i),c.endPTS=Math.max(c.endPTS,r),c.startDTS=Math.min(c.startDTS,a),c.endDTS=Math.max(c.endDTS,s)):d[t]={startPTS:i,endPTS:r,startDTS:a,endDTS:s,partial:l}},e.clearElementaryStreamInfo=function(){var t=this.elementaryStreams;t[Be]=null,t[Ze]=null,t[ir]=null},D(n,[{key:"decryptdata",get:function(){if(!this.levelkeys&&!this._decryptdata)return null;if(!this._decryptdata&&this.levelkeys&&!this.levelkeys.NONE){var t=this.levelkeys.identity;if(t)this._decryptdata=t.getDecryptData(this.sn);else{var i=Object.keys(this.levelkeys);if(i.length===1)return this._decryptdata=this.levelkeys[i[0]].getDecryptData(this.sn)}}return this._decryptdata}},{key:"end",get:function(){return this.start+this.duration}},{key:"endProgramDateTime",get:function(){if(this.programDateTime===null||!ie(this.programDateTime))return null;var t=ie(this.duration)?this.duration:0;return this.programDateTime+1e3*t}},{key:"encrypted",get:function(){var t;if((t=this._decryptdata)!=null&&t.encrypted)return!0;if(this.levelkeys){var i=Object.keys(this.levelkeys),r=i.length;if(r>1||r===1&&this.levelkeys[i[0]].encrypted)return!0}return!1}}]),n}(Cn),Jo=function(o){function n(e,t,i,r,a){var s;(s=o.call(this,i)||this).fragOffset=0,s.duration=0,s.gap=!1,s.independent=!1,s.relurl=void 0,s.fragment=void 0,s.index=void 0,s.stats=new yi,s.duration=e.decimalFloatingPoint("DURATION"),s.gap=e.bool("GAP"),s.independent=e.bool("INDEPENDENT"),s.relurl=e.enumeratedString("URI"),s.fragment=t,s.index=r;var l=e.enumeratedString("BYTERANGE");return l&&s.setByteRange(l,a),a&&(s.fragOffset=a.fragOffset+a.duration),s}return q(n,o),D(n,[{key:"start",get:function(){return this.fragment.start+this.fragOffset}},{key:"end",get:function(){return this.start+this.duration}},{key:"loaded",get:function(){var e=this.elementaryStreams;return!!(e.audio||e.video||e.audiovideo)}}]),n}(Cn),Zo=function(){function o(n){this.PTSKnown=!1,this.alignedSliding=!1,this.averagetargetduration=void 0,this.endCC=0,this.endSN=0,this.fragments=void 0,this.fragmentHint=void 0,this.partList=null,this.dateRanges=void 0,this.live=!0,this.ageHeader=0,this.advancedDateTime=void 0,this.updated=!0,this.advanced=!0,this.availabilityDelay=void 0,this.misses=0,this.startCC=0,this.startSN=0,this.startTimeOffset=null,this.targetduration=0,this.totalduration=0,this.type=null,this.url=void 0,this.m3u8="",this.version=null,this.canBlockReload=!1,this.canSkipUntil=0,this.canSkipDateRanges=!1,this.skippedSegments=0,this.recentlyRemovedDateranges=void 0,this.partHoldBack=0,this.holdBack=0,this.partTarget=0,this.preloadHint=void 0,this.renditionReports=void 0,this.tuneInGoal=0,this.deltaUpdateFailed=void 0,this.driftStartTime=0,this.driftEndTime=0,this.driftStart=0,this.driftEnd=0,this.encryptedFragments=void 0,this.playlistParsingError=null,this.variableList=null,this.hasVariableRefs=!1,this.fragments=[],this.encryptedFragments=[],this.dateRanges={},this.url=n}return o.prototype.reloaded=function(n){if(!n)return this.advanced=!0,void(this.updated=!0);var e=this.lastPartSn-n.lastPartSn,t=this.lastPartIndex-n.lastPartIndex;this.updated=this.endSN!==n.endSN||!!t||!!e||!this.live,this.advanced=this.endSN>n.endSN||e>0||e===0&&t>0,this.updated||this.advanced?this.misses=Math.floor(.6*n.misses):this.misses=n.misses+1,this.availabilityDelay=n.availabilityDelay},D(o,[{key:"hasProgramDateTime",get:function(){return!!this.fragments.length&&ie(this.fragments[this.fragments.length-1].programDateTime)}},{key:"levelTargetDuration",get:function(){return this.averagetargetduration||this.targetduration||10}},{key:"drift",get:function(){var n=this.driftEndTime-this.driftStartTime;return n>0?1e3*(this.driftEnd-this.driftStart)/n:1}},{key:"edge",get:function(){return this.partEnd||this.fragmentEnd}},{key:"partEnd",get:function(){var n;return(n=this.partList)!=null&&n.length?this.partList[this.partList.length-1].end:this.fragmentEnd}},{key:"fragmentEnd",get:function(){var n;return(n=this.fragments)!=null&&n.length?this.fragments[this.fragments.length-1].end:0}},{key:"age",get:function(){return this.advancedDateTime?Math.max(Date.now()-this.advancedDateTime,0)/1e3:0}},{key:"lastPartIndex",get:function(){var n;return(n=this.partList)!=null&&n.length?this.partList[this.partList.length-1].index:-1}},{key:"lastPartSn",get:function(){var n;return(n=this.partList)!=null&&n.length?this.partList[this.partList.length-1].fragment.sn:this.endSN}}]),o}();function nr(o){return Uint8Array.from(atob(o),function(n){return n.charCodeAt(0)})}function es(o){var n,e,t=o.split(":"),i=null;if(t[0]==="data"&&t.length===2){var r=t[1].split(";"),a=r[r.length-1].split(",");if(a.length===2){var s=a[0]==="base64",l=a[1];s?(r.splice(-1,1),i=nr(l)):(n=Sn(l).subarray(0,16),(e=new Uint8Array(16)).set(n,16-n.length),i=e)}}return i}function Sn(o){return Uint8Array.from(unescape(encodeURIComponent(o)),function(n){return n.charCodeAt(0)})}var Ee={CLEARKEY:"org.w3.clearkey",FAIRPLAY:"com.apple.fps",PLAYREADY:"com.microsoft.playready",WIDEVINE:"com.widevine.alpha"},ar="org.w3.clearkey",or="com.apple.streamingkeydelivery",wi="com.microsoft.playready",Ei="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed";function Ln(o){switch(o){case or:return Ee.FAIRPLAY;case wi:return Ee.PLAYREADY;case Ei:return Ee.WIDEVINE;case ar:return Ee.CLEARKEY}}var Dn="edef8ba979d64acea3c827dcd51d21ed";function Rn(o){switch(o){case Ee.FAIRPLAY:return or;case Ee.PLAYREADY:return wi;case Ee.WIDEVINE:return Ei;case Ee.CLEARKEY:return ar}}function sr(o){var n=o.drmSystems,e=o.widevineLicenseUrl,t=n?[Ee.FAIRPLAY,Ee.WIDEVINE,Ee.PLAYREADY,Ee.CLEARKEY].filter(function(i){return!!n[i]}):[];return!t[Ee.WIDEVINE]&&e&&t.push(Ee.WIDEVINE),t}var In=typeof self<"u"&&self.navigator&&self.navigator.requestMediaKeySystemAccess?self.navigator.requestMediaKeySystemAccess.bind(self.navigator):null;function It(o,n,e){return Uint8Array.prototype.slice?o.slice(n,e):new Uint8Array(Array.prototype.slice.call(o,n,e))}var lr,dr=function(o,n){return n+10<=o.length&&o[n]===73&&o[n+1]===68&&o[n+2]===51&&o[n+3]<255&&o[n+4]<255&&o[n+6]<128&&o[n+7]<128&&o[n+8]<128&&o[n+9]<128},Pn=function(o,n){return n+10<=o.length&&o[n]===51&&o[n+1]===68&&o[n+2]===73&&o[n+3]<255&&o[n+4]<255&&o[n+6]<128&&o[n+7]<128&&o[n+8]<128&&o[n+9]<128},Ai=function(o,n){for(var e=n,t=0;dr(o,n);)t+=10,t+=_i(o,n+6),Pn(o,n+10)&&(t+=10),n+=t;if(t>0)return o.subarray(e,e+t)},_i=function(o,n){var e=0;return e=(127&o[n])<<21,e|=(127&o[n+1])<<14,e|=(127&o[n+2])<<7,e|=127&o[n+3]},ts=function(o,n){return dr(o,n)&&_i(o,n+6)+10<=o.length-n},On=function(o){return o&&o.key==="PRIV"&&o.info==="com.apple.streaming.transportStreamTimestamp"},is=function(o){var n=String.fromCharCode(o[0],o[1],o[2],o[3]),e=_i(o,4);return{type:n,size:e,data:o.subarray(10,10+e)}},Mn=function(o){for(var n=0,e=[];dr(o,n);){for(var t=_i(o,n+6),i=(n+=10)+t;n+8>4){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:d+=String.fromCharCode(r);break;case 12:case 13:a=o[c++],d+=String.fromCharCode((31&r)<<6|63&a);break;case 14:a=o[c++],s=o[c++],d+=String.fromCharCode((15&r)<<12|(63&a)<<6|(63&s)<<0)}}return d};function ls(){return lr||self.TextDecoder===void 0||(lr=new self.TextDecoder("utf-8")),lr}var ot=function(o){for(var n="",e=0;e>24,o[n+1]=e>>16&255,o[n+2]=e>>8&255,o[n+3]=255&e}function ge(o,n){var e=[];if(!n.length)return e;for(var t=o.byteLength,i=0;i1?i+r:t;if(Se(o.subarray(i+4,i+8))===n[0])if(n.length===1)e.push(o.subarray(i+8,a));else{var s=ge(o.subarray(i+8,a),n.slice(1));s.length&&ds.apply(e,s)}i=a}return e}function cs(o){var n=[],e=o[0],t=8,i=oe(o,t);t+=4,t+=e===0?8:16,t+=2;var r=o.length+0,a=Bn(o,t);t+=2;for(var s=0;s>>31==1)return R.warn("SIDX has hierarchical references (not supported)"),null;var u=oe(o,l);l+=4,n.push({referenceSize:c,subsegmentDuration:u,info:{duration:u/i,start:r,end:r+c-1}}),r+=c,t=l+=4}return{earliestPresentationTime:0,timescale:i,version:e,referencesCount:a,references:n}}function Un(o){for(var n=[],e=ge(o,["moov","trak"]),t=0;t>1&63;return e===39||e===40}return(31&n)==6}function Kn(o,n,e,t){var i=Vn(o),r=0;r+=n;for(var a=0,s=0,l=!1,d=0;r=i.length)break;a+=d=i[r++]}while(d===255);s=0;do{if(r>=i.length)break;s+=d=i[r++]}while(d===255);var c=i.length-r;if(!l&&a===4&&r16){for(var S=[],C=0;C<16;C++){var L=i[r++].toString(16);S.push(L.length==1?"0"+L:L),C!==3&&C!==5&&C!==7&&C!==9||S.push("-")}for(var I=s-16,P=new Uint8Array(I),N=0;Nc)break}}function Vn(o){for(var n=o.byteLength,e=[],t=1;t0?(r=new Uint8Array(4),n.length>0&&new DataView(r.buffer).setUint32(0,n.length,!1)):r=new Uint8Array;var a=new Uint8Array(4);return e&&e.byteLength>0&&new DataView(a.buffer).setUint32(0,e.byteLength,!1),function(s){for(var l=arguments.length,d=new Array(l>1?l-1:0),c=1;c>24&255,v[1]=g>>16&255,v[2]=g>>8&255,v[3]=255&g,v.set(s,4),m=0,g=8;m>8*(15-E)&255;return b}(e);return new o(this.method,this.uri,"identity",this.keyFormatVersions,t)}var i=es(this.uri);if(i)switch(this.keyFormat){case Ei:this.pssh=i,i.length>=22&&(this.keyId=i.subarray(i.length-22,i.length-6));break;case wi:var r=new Uint8Array([154,4,240,121,152,64,66,134,171,146,230,91,224,136,95,149]);this.pssh=fs(r,null,i);var a=new Uint16Array(i.buffer,i.byteOffset,i.byteLength/2),s=String.fromCharCode.apply(null,Array.from(a)),l=s.substring(s.indexOf("<"),s.length),d=new DOMParser().parseFromString(l,"text/xml").getElementsByTagName("KID")[0];if(d){var c=d.childNodes[0]?d.childNodes[0].nodeValue:d.getAttribute("VALUE");if(c){var u=nr(c).subarray(0,16);(function(_){var b=function(E,S,C){var L=E[S];E[S]=E[C],E[C]=L};b(_,0,3),b(_,1,2),b(_,4,5),b(_,6,7)})(u),this.keyId=u}}break;default:var g=i.subarray(0,16);if(g.length!==16){var m=new Uint8Array(16);m.set(g,16-g.length),g=m}this.keyId=g}if(!this.keyId||this.keyId.byteLength!==16){var v=xi[this.uri];if(!v){var y=Object.keys(xi).length%Number.MAX_SAFE_INTEGER;v=new Uint8Array(16),new DataView(v.buffer,12,4).setUint32(0,y),xi[this.uri]=v}this.keyId=v}return this},o}(),zn=/\{\$([a-zA-Z0-9-_]+)\}/g;function Yn(o){return zn.test(o)}function Ne(o,n,e){if(o.variableList!==null||o.hasVariableRefs)for(var t=e.length;t--;){var i=e[t],r=n[i];r&&(n[i]=ur(o,r))}}function ur(o,n){if(o.variableList!==null||o.hasVariableRefs){var e=o.variableList;return n.replace(zn,function(t){var i=t.substring(2,t.length-1),r=e==null?void 0:e[i];return r===void 0?(o.playlistParsingError||(o.playlistParsingError=new Error('Missing preceding EXT-X-DEFINE tag for Variable Reference: "'+i+'"')),t):r})}return n}function jn(o,n,e){var t,i,r=o.variableList;if(r||(o.variableList=r={}),"QUERYPARAM"in n){t=n.QUERYPARAM;try{var a=new self.URL(e).searchParams;if(!a.has(t))throw new Error('"'+t+'" does not match any query parameter in URI: "'+e+'"');i=a.get(t)}catch(s){o.playlistParsingError||(o.playlistParsingError=new Error("EXT-X-DEFINE QUERYPARAM: "+s.message))}}else t=n.NAME,i=n.VALUE;t in r?o.playlistParsingError||(o.playlistParsingError=new Error('EXT-X-DEFINE duplicate Variable Name declarations: "'+t+'"')):r[t]=i||""}function ps(o,n,e){var t=n.IMPORT;if(e&&t in e){var i=o.variableList;i||(o.variableList=i={}),i[t]=e[t]}else o.playlistParsingError||(o.playlistParsingError=new Error('EXT-X-DEFINE IMPORT attribute not found in Multivariant Playlist: "'+t+'"'))}function Ti(){if(typeof self<"u")return self.MediaSource||self.WebKitMediaSource}var gs={audio:{a3ds:!0,"ac-3":!0,"ac-4":!0,alac:!0,alaw:!0,dra1:!0,"dts+":!0,"dts-":!0,dtsc:!0,dtse:!0,dtsh:!0,"ec-3":!0,enca:!0,g719:!0,g726:!0,m4ae:!0,mha1:!0,mha2:!0,mhm1:!0,mhm2:!0,mlpa:!0,mp4a:!0,"raw ":!0,Opus:!0,opus:!0,samr:!0,sawb:!0,sawp:!0,sevc:!0,sqcp:!0,ssmv:!0,twos:!0,ulaw:!0},video:{avc1:!0,avc2:!0,avc3:!0,avc4:!0,avcp:!0,av01:!0,drac:!0,dva1:!0,dvav:!0,dvh1:!0,dvhe:!0,encv:!0,hev1:!0,hvc1:!0,mjp2:!0,mp4v:!0,mvc1:!0,mvc2:!0,mvc3:!0,mvc4:!0,resv:!0,rv60:!0,s263:!0,svc1:!0,svc2:!0,"vc-1":!0,vp08:!0,vp09:!0},text:{stpp:!0,wvtt:!0}},qn=Ti();function fr(o,n){var e;return(e=qn==null?void 0:qn.isTypeSupported((n||"video")+'/mp4;codecs="'+o+'"'))!=null&&e}var $n=/#EXT-X-STREAM-INF:([^\r\n]*)(?:[\r\n](?:#[^\r\n]*)?)*([^\r\n]+)|#EXT-X-(SESSION-DATA|SESSION-KEY|DEFINE|CONTENT-STEERING|START):([^\r\n]*)[\r\n]+/g,Qn=/#EXT-X-MEDIA:(.*)/g,ms=/^#EXT(?:INF|-X-TARGETDURATION):/m,Wn=new RegExp([/#EXTINF:\s*(\d*(?:\.\d+)?)(?:,(.*)\s+)?/.source,/(?!#) *(\S[\S ]*)/.source,/#EXT-X-BYTERANGE:*(.+)/.source,/#EXT-X-PROGRAM-DATE-TIME:(.+)/.source,/#.*/.source].join("|"),"g"),vs=new RegExp([/#(EXTM3U)/.source,/#EXT-X-(DATERANGE|DEFINE|KEY|MAP|PART|PART-INF|PLAYLIST-TYPE|PRELOAD-HINT|RENDITION-REPORT|SERVER-CONTROL|SKIP|START):(.+)/.source,/#EXT-X-(BITRATE|DISCONTINUITY-SEQUENCE|MEDIA-SEQUENCE|TARGETDURATION|VERSION): *(\d+)/.source,/#EXT-X-(DISCONTINUITY|ENDLIST|GAP)/.source,/(#)([^:]*):(.*)/.source,/(#)(.*)(?:.*)\r?\n?/.source].join("|")),ii=function(){function o(){}return o.findGroup=function(n,e){for(var t=0;t2){var t=e.shift()+".";return t+=parseInt(e.shift()).toString(16),t+=("000"+parseInt(e.shift()).toString(16)).slice(-4)}return n},o.resolve=function(n,e){return er.buildAbsoluteURL(e,n,{alwaysNormalize:!0})},o.isMediaPlaylist=function(n){return ms.test(n)},o.parseMasterPlaylist=function(n,e){var t,i={contentSteering:null,levels:[],playlistParsingError:null,sessionData:null,sessionKeys:null,startTimeOffset:null,variableList:null,hasVariableRefs:Yn(n)},r=[];for($n.lastIndex=0;(t=$n.exec(n))!=null;)if(t[1]){var a,s=new _e(t[1]);Ne(i,s,["CODECS","SUPPLEMENTAL-CODECS","ALLOWED-CPC","PATHWAY-ID","STABLE-VARIANT-ID","AUDIO","VIDEO","SUBTITLES","CLOSED-CAPTIONS","NAME"]);var l=ur(i,t[2]),d={attrs:s,bitrate:s.decimalInteger("AVERAGE-BANDWIDTH")||s.decimalInteger("BANDWIDTH"),name:s.NAME,url:o.resolve(l,e)},c=s.decimalResolution("RESOLUTION");c&&(d.width=c.width,d.height=c.height),bs((s.CODECS||"").split(/[ ,]+/).filter(function(S){return S}),d),d.videoCodec&&d.videoCodec.indexOf("avc1")!==-1&&(d.videoCodec=o.convertAVC1ToAVCOTI(d.videoCodec)),(a=d.unknownCodecs)!=null&&a.length||r.push(d),i.levels.push(d)}else if(t[3]){var u=t[3],g=t[4];switch(u){case"SESSION-DATA":var m=new _e(g);Ne(i,m,["DATA-ID","LANGUAGE","VALUE","URI"]);var v=m["DATA-ID"];v&&(i.sessionData===null&&(i.sessionData={}),i.sessionData[v]=m);break;case"SESSION-KEY":var y=Xn(g,e,i);y.encrypted&&y.isSupported()?(i.sessionKeys===null&&(i.sessionKeys=[]),i.sessionKeys.push(y)):R.warn('[Keys] Ignoring invalid EXT-X-SESSION-KEY tag: "'+g+'"');break;case"DEFINE":var _=new _e(g);Ne(i,_,["NAME","VALUE","QUERYPARAM"]),jn(i,_,e);break;case"CONTENT-STEERING":var b=new _e(g);Ne(i,b,["SERVER-URI","PATHWAY-ID"]),i.contentSteering={uri:o.resolve(b["SERVER-URI"],e),pathwayId:b["PATHWAY-ID"]||"."};break;case"START":i.startTimeOffset=Jn(g)}}var E=r.length>0&&r.length0&&ye.bool("CAN-SKIP-DATERANGES"),c.partHoldBack=ye.optionalFloat("PART-HOLD-BACK",0),c.holdBack=ye.optionalFloat("HOLD-BACK",0);break;case"PART-INF":var Ge=new _e(B);c.partTarget=Ge.decimalFloatingPoint("PART-TARGET");break;case"PART":var ke=c.partList;ke||(ke=c.partList=[]);var et=v>0?ke[ke.length-1]:void 0,Xe=v++,Je=new _e(B);Ne(c,Je,["BYTERANGE","URI"]);var xe=new Jo(Je,E,e,Xe,et);ke.push(xe),E.duration+=xe.duration;break;case"PRELOAD-HINT":var De=new _e(B);Ne(c,De,["URI"]),c.preloadHint=De;break;case"RENDITION-REPORT":var ct=new _e(B);Ne(c,ct,["URI"]),c.renditionReports=c.renditionReports||[],c.renditionReports.push(ct);break;default:R.warn("line parsed but not handled: "+s)}}}b&&!b.relurl?(u.pop(),y-=b.duration,c.partList&&(c.fragmentHint=b)):c.partList&&(ea(E,b),E.cc=_,c.fragmentHint=E,d&&ia(E,d,c));var Tt=u.length,Ye=u[0],pi=u[Tt-1];if((y+=c.skippedSegments*c.targetduration)>0&&Tt&&pi){c.averagetargetduration=y/Tt;var gi=pi.sn;c.endSN=gi!=="initSegment"?gi:0,c.live||(pi.endList=!0),Ye&&(c.startCC=Ye.cc)}else c.endSN=0,c.startCC=0;return c.fragmentHint&&(y+=c.fragmentHint.duration),c.totalduration=y,c.endCC=_,S>0&&function(zi,Xt){for(var Ut=zi[Xt],mi=Xt;mi--;){var wt=zi[mi];if(!wt)return;wt.programDateTime=Ut.programDateTime-1e3*wt.duration,Ut=wt}}(u,S),c},o}();function Xn(o,n,e){var t,i,r=new _e(o);Ne(e,r,["KEYFORMAT","KEYFORMATVERSIONS","URI","IV","URI"]);var a=(t=r.METHOD)!=null?t:"",s=r.URI,l=r.hexadecimalInteger("IV"),d=r.KEYFORMATVERSIONS,c=(i=r.KEYFORMAT)!=null?i:"identity";s&&r.IV&&!l&&R.error("Invalid IV: "+r.IV);var u=s?ii.resolve(s,n):"",g=(d||"1").split("/").map(Number).filter(Number.isFinite);return new hr(a,u,c,g,l)}function Jn(o){var n=new _e(o).decimalFloatingPoint("TIME-OFFSET");return ie(n)?n:null}function bs(o,n){["video","audio","text"].forEach(function(e){var t=o.filter(function(r){return function(a,s){var l=gs[s];return!!l&&l[a.slice(0,4)]===!0}(r,e)});if(t.length){var i=t.filter(function(r){return r.lastIndexOf("avc1",0)===0||r.lastIndexOf("mp4a",0)===0});n[e+"Codec"]=i.length>0?i[0]:t[0],o=o.filter(function(r){return t.indexOf(r)===-1})}}),n.unknownCodecs=o}function Zn(o,n,e){var t=n[e];t&&(o[e]=t)}function ea(o,n){o.rawProgramDateTime?o.programDateTime=Date.parse(o.rawProgramDateTime):n!=null&&n.programDateTime&&(o.programDateTime=n.endProgramDateTime),ie(o.programDateTime)||(o.programDateTime=null,o.rawProgramDateTime=null)}function ta(o,n,e,t){o.relurl=n.URI,n.BYTERANGE&&o.setByteRange(n.BYTERANGE),o.level=e,o.sn="initSegment",t&&(o.levelkeys=t),o.initSegment=null}function ia(o,n,e){o.levelkeys=n;var t=e.encryptedFragments;t.length&&t[t.length-1].levelkeys===n||!Object.keys(n).some(function(i){return n[i].isCommonEncryption})||t.push(o)}var Gt="manifest",Ot="level",st="audioTrack",pt="subtitleTrack",ve="main",lt="audio",kt="subtitle";function ra(o){switch(o.type){case st:return lt;case pt:return kt;default:return ve}}function pr(o,n){var e=o.url;return e!==void 0&&e.indexOf("data:")!==0||(e=n.url),e}var ys=function(){function o(e){this.hls=void 0,this.loaders=Object.create(null),this.variableList=null,this.hls=e,this.registerListeners()}var n=o.prototype;return n.startLoad=function(e){},n.stopLoad=function(){this.destroyInternalLoaders()},n.registerListeners=function(){var e=this.hls;e.on(A.MANIFEST_LOADING,this.onManifestLoading,this),e.on(A.LEVEL_LOADING,this.onLevelLoading,this),e.on(A.AUDIO_TRACK_LOADING,this.onAudioTrackLoading,this),e.on(A.SUBTITLE_TRACK_LOADING,this.onSubtitleTrackLoading,this)},n.unregisterListeners=function(){var e=this.hls;e.off(A.MANIFEST_LOADING,this.onManifestLoading,this),e.off(A.LEVEL_LOADING,this.onLevelLoading,this),e.off(A.AUDIO_TRACK_LOADING,this.onAudioTrackLoading,this),e.off(A.SUBTITLE_TRACK_LOADING,this.onSubtitleTrackLoading,this)},n.createInternalLoader=function(e){var t=this.hls.config,i=t.pLoader,r=t.loader,a=new(i||r)(t);return this.loaders[e.type]=a,a},n.getInternalLoader=function(e){return this.loaders[e.type]},n.resetInternalLoader=function(e){this.loaders[e]&&delete this.loaders[e]},n.destroyInternalLoaders=function(){for(var e in this.loaders){var t=this.loaders[e];t&&t.destroy(),this.resetInternalLoader(e)}},n.destroy=function(){this.variableList=null,this.unregisterListeners(),this.destroyInternalLoaders()},n.onManifestLoading=function(e,t){var i=t.url;this.variableList=null,this.load({id:null,level:0,responseType:"text",type:Gt,url:i,deliveryDirectives:null})},n.onLevelLoading=function(e,t){var i=t.id,r=t.level,a=t.url,s=t.deliveryDirectives;this.load({id:i,level:r,responseType:"text",type:Ot,url:a,deliveryDirectives:s})},n.onAudioTrackLoading=function(e,t){var i=t.id,r=t.groupId,a=t.url,s=t.deliveryDirectives;this.load({id:i,groupId:r,level:null,responseType:"text",type:st,url:a,deliveryDirectives:s})},n.onSubtitleTrackLoading=function(e,t){var i=t.id,r=t.groupId,a=t.url,s=t.deliveryDirectives;this.load({id:i,groupId:r,level:null,responseType:"text",type:pt,url:a,deliveryDirectives:s})},n.load=function(e){var t,i,r,a=this,s=this.hls.config,l=this.getInternalLoader(e);if(l){var d=l.context;if(d&&d.url===e.url)return void R.trace("[playlist-loader]: playlist request ongoing");R.log("[playlist-loader]: aborting previous loader for type: "+e.type),l.abort()}if(i=e.type===Gt?s.manifestLoadPolicy.default:F({},s.playlistLoadPolicy.default,{timeoutRetry:null,errorRetry:null}),l=this.createInternalLoader(e),(t=e.deliveryDirectives)!=null&&t.part&&(e.type===Ot&&e.level!==null?r=this.hls.levels[e.level].details:e.type===st&&e.id!==null?r=this.hls.audioTracks[e.id].details:e.type===pt&&e.id!==null&&(r=this.hls.subtitleTracks[e.id].details),r)){var c=r.partTarget,u=r.targetduration;if(c&&u){var g=1e3*Math.max(3*c,.8*u);i=F({},i,{maxTimeToFirstByteMs:Math.min(g,i.maxTimeToFirstByteMs),maxLoadTimeMs:Math.min(g,i.maxTimeToFirstByteMs)})}}var m=i.errorRetry||i.timeoutRetry||{},v={loadPolicy:i,timeout:i.maxLoadTimeMs,maxRetry:m.maxNumRetry||0,retryDelay:m.retryDelayMs||0,maxRetryDelay:m.maxRetryDelayMs||0},y={onSuccess:function(_,b,E,S){var C=a.getInternalLoader(E);a.resetInternalLoader(E.type);var L=_.data;L.indexOf("#EXTM3U")===0?(b.parsing.start=performance.now(),ii.isMediaPlaylist(L)?a.handleTrackOrLevelPlaylist(_,b,E,S||null,C):a.handleMasterPlaylist(_,b,E,S)):a.handleManifestParsingError(_,E,new Error("no EXTM3U delimiter"),S||null,b)},onError:function(_,b,E,S){a.handleNetworkError(b,E,!1,_,S)},onTimeout:function(_,b,E){a.handleNetworkError(b,E,!0,void 0,_)}};l.load(e,v,y)},n.handleMasterPlaylist=function(e,t,i,r){var a=this.hls,s=e.data,l=pr(e,i),d=ii.parseMasterPlaylist(s,l);if(d.playlistParsingError)this.handleManifestParsingError(e,i,d.playlistParsingError,r,t);else{var c=d.contentSteering,u=d.levels,g=d.sessionData,m=d.sessionKeys,v=d.startTimeOffset,y=d.variableList;this.variableList=y;var _=ii.parseMasterPlaylistMedia(s,l,d),b=_.AUDIO,E=b===void 0?[]:b,S=_.SUBTITLES,C=_["CLOSED-CAPTIONS"];E.length&&(E.some(function(L){return!L.url})||!u[0].audioCodec||u[0].attrs.AUDIO||(R.log("[playlist-loader]: audio codec signaled in quality level, but no embedded audio track signaled, create one"),E.unshift({type:"main",name:"main",groupId:"main",default:!1,autoselect:!1,forced:!1,id:-1,attrs:new _e({}),bitrate:0,url:""}))),a.trigger(A.MANIFEST_LOADED,{levels:u,audioTracks:E,subtitles:S,captions:C,contentSteering:c,url:l,stats:t,networkDetails:r,sessionData:g,sessionKeys:m,startTimeOffset:v,variableList:y})}},n.handleTrackOrLevelPlaylist=function(e,t,i,r,a){var s=this.hls,l=i.id,d=i.level,c=i.type,u=pr(e,i),g=ie(l)?l:0,m=ie(d)?d:g,v=ra(i),y=ii.parseLevelPlaylist(e.data,u,m,v,g,this.variableList);if(c===Gt){var _={attrs:new _e({}),bitrate:0,details:y,name:"",url:u};s.trigger(A.MANIFEST_LOADED,{levels:[_],audioTracks:[],url:u,stats:t,networkDetails:r,sessionData:null,sessionKeys:null,contentSteering:null,startTimeOffset:null,variableList:null})}t.parsing.end=performance.now(),i.levelDetails=y,this.handlePlaylistLoaded(y,e,t,i,r,a)},n.handleManifestParsingError=function(e,t,i,r,a){this.hls.trigger(A.ERROR,{type:ne.NETWORK_ERROR,details:O.MANIFEST_PARSING_ERROR,fatal:t.type===Gt,url:e.url,err:i,error:i,reason:i.message,response:e,context:t,networkDetails:r,stats:a})},n.handleNetworkError=function(e,t,i,r,a){i===void 0&&(i=!1);var s="A network "+(i?"timeout":"error"+(r?" (status "+r.code+")":""))+" occurred while loading "+e.type;e.type===Ot?s+=": "+e.level+" id: "+e.id:e.type!==st&&e.type!==pt||(s+=" id: "+e.id+' group-id: "'+e.groupId+'"');var l=new Error(s);R.warn("[playlist-loader]: "+s);var d=O.UNKNOWN,c=!1,u=this.getInternalLoader(e);switch(e.type){case Gt:d=i?O.MANIFEST_LOAD_TIMEOUT:O.MANIFEST_LOAD_ERROR,c=!0;break;case Ot:d=i?O.LEVEL_LOAD_TIMEOUT:O.LEVEL_LOAD_ERROR,c=!1;break;case st:d=i?O.AUDIO_TRACK_LOAD_TIMEOUT:O.AUDIO_TRACK_LOAD_ERROR,c=!1;break;case pt:d=i?O.SUBTITLE_TRACK_LOAD_TIMEOUT:O.SUBTITLE_LOAD_ERROR,c=!1}u&&this.resetInternalLoader(e.type);var g={type:ne.NETWORK_ERROR,details:d,fatal:c,url:e.url,loader:u,context:e,error:l,networkDetails:t,stats:a};if(r){var m=(t==null?void 0:t.url)||e.url;g.response=x({url:m,data:void 0},r)}this.hls.trigger(A.ERROR,g)},n.handlePlaylistLoaded=function(e,t,i,r,a,s){var l=this.hls,d=r.type,c=r.level,u=r.id,g=r.groupId,m=r.deliveryDirectives,v=pr(t,r),y=ra(r),_=typeof r.level=="number"&&y===ve?c:void 0;if(e.fragments.length){e.targetduration||(e.playlistParsingError=new Error("Missing Target Duration"));var b=e.playlistParsingError;if(b)l.trigger(A.ERROR,{type:ne.NETWORK_ERROR,details:O.LEVEL_PARSING_ERROR,fatal:!1,url:v,error:b,reason:b.message,response:t,context:r,level:_,parent:y,networkDetails:a,stats:i});else switch(e.live&&s&&(s.getCacheAge&&(e.ageHeader=s.getCacheAge()||0),s.getCacheAge&&!isNaN(e.ageHeader)||(e.ageHeader=0)),d){case Gt:case Ot:l.trigger(A.LEVEL_LOADED,{details:e,level:_||0,id:u||0,stats:i,networkDetails:a,deliveryDirectives:m});break;case st:l.trigger(A.AUDIO_TRACK_LOADED,{details:e,id:u||0,groupId:g||"",stats:i,networkDetails:a,deliveryDirectives:m});break;case pt:l.trigger(A.SUBTITLE_TRACK_LOADED,{details:e,id:u||0,groupId:g||"",stats:i,networkDetails:a,deliveryDirectives:m})}}else{var E=new Error("No Segments found in Playlist");l.trigger(A.ERROR,{type:ne.NETWORK_ERROR,details:O.LEVEL_EMPTY_ERROR,fatal:!1,url:v,error:E,reason:E.message,response:t,context:r,level:_,parent:y,networkDetails:a,stats:i})}},o}();function na(o,n){var e;try{e=new Event("addtrack")}catch{(e=document.createEvent("Event")).initEvent("addtrack",!1,!1)}e.track=o,n.dispatchEvent(e)}function aa(o,n){var e=o.mode;if(e==="disabled"&&(o.mode="hidden"),o.cues&&!o.cues.getCueById(n.id))try{if(o.addCue(n),!o.cues.getCueById(n.id))throw new Error("addCue is failed for: "+n)}catch(i){R.debug("[texttrack-utils]: "+i);try{var t=new self.TextTrackCue(n.startTime,n.endTime,n.text);t.id=n.id,o.addCue(t)}catch(r){R.debug("[texttrack-utils]: Legacy TextTrackCue fallback failed: "+r)}}e==="disabled"&&(o.mode=e)}function Ht(o){var n=o.mode;if(n==="disabled"&&(o.mode="hidden"),o.cues)for(var e=o.cues.length;e--;)o.removeCue(o.cues[e]);n==="disabled"&&(o.mode=n)}function gr(o,n,e,t){var i=o.mode;if(i==="disabled"&&(o.mode="hidden"),o.cues&&o.cues.length>0)for(var r=function(s,l,d){var c=[],u=function(y,_){if(_y[b].endTime)return-1;for(var E=0,S=b;E<=S;){var C=Math.floor((S+E)/2);if(_y[C].startTime&&E-1)for(var g=u,m=s.length;g=l&&v.endTime<=d)c.push(v);else if(v.startTime>d)return c}return c}(o.cues,n,e),a=0;aCi&&(m=Ci),m-g<=0&&(m=g+.25);for(var v=0;vS.startDate&&Z.push(he),Z},[]).sort(function(Z,ae){return Z.startDate.getTime()-ae.startDate.getTime()})[0];B&&(N=vr(B.startDate,v),I=!0)}for(var Y,K,Q=Object.keys(S.attr),re=0;re.05&&this.forwardBufferLength>1){var u=Math.min(2,Math.max(1,s)),g=Math.round(2/(1+Math.exp(-.75*d-this.edgeStalled))*20)/20;e.playbackRate=Math.min(u,Math.max(1,g))}else e.playbackRate!==1&&e.playbackRate!==0&&(e.playbackRate=1)}}}}},n.estimateLiveEdge=function(){var e=this.levelDetails;return e===null?null:e.edge+e.age},n.computeLatency=function(){var e=this.estimateLiveEdge();return e===null?null:e-this.currentTime},D(o,[{key:"latency",get:function(){return this._latency||0}},{key:"maxLatency",get:function(){var e=this.config,t=this.levelDetails;return e.liveMaxLatencyDuration!==void 0?e.liveMaxLatencyDuration:t?e.liveMaxLatencyDurationCount*t.targetduration:0}},{key:"targetLatency",get:function(){var e=this.levelDetails;if(e===null)return null;var t=e.holdBack,i=e.partHoldBack,r=e.targetduration,a=this.config,s=a.liveSyncDuration,l=a.liveSyncDurationCount,d=a.lowLatencyMode,c=this.hls.userConfig,u=d&&i||t;(c.liveSyncDuration||c.liveSyncDurationCount||u===0)&&(u=s!==void 0?s:l*r);var g=r;return u+Math.min(1*this.stallCount,g)}},{key:"liveSyncPosition",get:function(){var e=this.estimateLiveEdge(),t=this.targetLatency,i=this.levelDetails;if(e===null||t===null||i===null)return null;var r=i.edge,a=e-t-this.edgeStalled,s=r-i.totalduration,l=r-(this.config.lowLatencyMode&&i.partTarget||i.targetduration);return Math.min(Math.max(s,a),l)}},{key:"drift",get:function(){var e=this.levelDetails;return e===null?1:e.drift}},{key:"edgeStalled",get:function(){var e=this.levelDetails;if(e===null)return 0;var t=3*(this.config.lowLatencyMode&&e.partTarget||e.targetduration);return Math.max(e.age-t,0)}},{key:"forwardBufferLength",get:function(){var e=this.media,t=this.levelDetails;if(!e||!t)return 0;var i=e.buffered.length;return(i?e.buffered.end(i-1):t.edge)-this.currentTime}}]),o}(),br=["NONE","TYPE-0","TYPE-1",null],yr="",_s="YES",ks="v2",oa=function(){function o(n,e,t){this.msn=void 0,this.part=void 0,this.skip=void 0,this.msn=n,this.part=e,this.skip=t}return o.prototype.addDirectives=function(n){var e=new self.URL(n);return this.msn!==void 0&&e.searchParams.set("_HLS_msn",this.msn.toString()),this.part!==void 0&&e.searchParams.set("_HLS_part",this.part.toString()),this.skip&&e.searchParams.set("_HLS_skip",this.skip),e.href},o}(),ai=function(){function o(n){this._attrs=void 0,this.audioCodec=void 0,this.bitrate=void 0,this.codecSet=void 0,this.height=void 0,this.id=void 0,this.name=void 0,this.videoCodec=void 0,this.width=void 0,this.unknownCodecs=void 0,this.audioGroupIds=void 0,this.details=void 0,this.fragmentError=0,this.loadError=0,this.loaded=void 0,this.realBitrate=0,this.textGroupIds=void 0,this.url=void 0,this._urlId=0,this.url=[n.url],this._attrs=[n.attrs],this.bitrate=n.bitrate,n.details&&(this.details=n.details),this.id=n.id||0,this.name=n.name,this.width=n.width||0,this.height=n.height||0,this.audioCodec=n.audioCodec,this.videoCodec=n.videoCodec,this.unknownCodecs=n.unknownCodecs,this.codecSet=[n.videoCodec,n.audioCodec].filter(function(e){return e}).join(",").replace(/\.[^.,]+/g,"")}return o.prototype.addFallback=function(n){this.url.push(n.url),this._attrs.push(n.attrs)},D(o,[{key:"maxBitrate",get:function(){return Math.max(this.realBitrate,this.bitrate)}},{key:"attrs",get:function(){return this._attrs[this._urlId]}},{key:"pathwayId",get:function(){return this.attrs["PATHWAY-ID"]||"."}},{key:"uri",get:function(){return this.url[this._urlId]||""}},{key:"urlId",get:function(){return this._urlId},set:function(n){var e=n%this.url.length;this._urlId!==e&&(this.fragmentError=0,this.loadError=0,this.details=void 0,this._urlId=e)}},{key:"audioGroupId",get:function(){var n;return(n=this.audioGroupIds)==null?void 0:n[this.urlId]}},{key:"textGroupId",get:function(){var n;return(n=this.textGroupIds)==null?void 0:n[this.urlId]}}]),o}();function wr(o,n){var e=n.startPTS;if(ie(e)){var t,i=0;n.sn>o.sn?(i=e-o.start,t=o):(i=o.start-e,t=n),t.duration!==i&&(t.duration=i)}else n.sn>o.sn?o.cc===n.cc&&o.minEndPTS?n.start=o.start+(o.minEndPTS-o.start):n.start=o.start+o.duration:n.start=Math.max(o.start-n.duration,0)}function sa(o,n,e,t,i,r){t-e<=0&&(R.warn("Fragment should have a positive duration",n),t=e+n.duration,r=i+n.duration);var a=e,s=t,l=n.startPTS,d=n.endPTS;if(ie(l)){var c=Math.abs(l-e);ie(n.deltaPTS)?n.deltaPTS=Math.max(c,n.deltaPTS):n.deltaPTS=c,a=Math.max(e,l),e=Math.min(e,l),i=Math.min(i,n.startDTS),s=Math.min(t,d),t=Math.max(t,d),r=Math.max(r,n.endDTS)}var u=e-n.start;n.start!==0&&(n.start=e),n.duration=t-n.start,n.startPTS=e,n.maxStartPTS=a,n.startDTS=i,n.endPTS=t,n.minEndPTS=s,n.endDTS=r;var g,m=n.sn;if(!o||mo.endSN)return 0;var v=m-o.startSN,y=o.fragments;for(y[v]=n,g=v;g>0;g--)wr(y[g],y[g-1]);for(g=v;g=0;i--){var r=t[i].initSegment;if(r){e=r;break}}o.fragmentHint&&delete o.fragmentHint.endPTS;var a,s,l,d,c,u=0;if(function(b,E,S){for(var C=E.skippedSegments,L=Math.max(b.startSN,E.startSN)-E.startSN,I=(b.fragmentHint?1:0)+(C?E.endSN:Math.min(b.endSN,E.endSN))-E.startSN,P=E.startSN-b.startSN,N=E.fragmentHint?E.fragments.concat(E.fragmentHint):E.fragments,M=b.fragmentHint?b.fragments.concat(b.fragmentHint):b.fragments,B=L;B<=I;B++){var Y=M[P+B],K=N[B];C&&!K&&B=t.length||Er(n,t[e].start)}function Er(o,n){if(n){for(var e=o.fragments,t=o.skippedSegments;t499)}(t)||!!e)}var fa=function(o,n){for(var e=0,t=o.length-1,i=null,r=null;e<=t;){var a=n(r=o[i=(e+t)/2|0]);if(a>0)e=i+1;else{if(!(a<0))return r;t=i-1}}return null};function oi(o,n,e,t){e===void 0&&(e=0),t===void 0&&(t=0);var i=null;if(o?i=n[o.sn-n[0].sn+1]||null:e===0&&n[0].start===0&&(i=n[0]),i&&_r(e,t,i)===0)return i;var r=fa(n,_r.bind(null,e,t));return!r||r===o&&i?i:r}function _r(o,n,e){if(o===void 0&&(o=0),n===void 0&&(n=0),e.start<=o&&e.start+e.duration>o)return 0;var t=Math.min(n,e.duration+(e.deltaPTS?e.deltaPTS:0));return e.start+e.duration-t<=o?1:e.start-t>o&&e.start?-1:0}function Ts(o,n,e){var t=1e3*Math.min(n,e.duration+(e.deltaPTS?e.deltaPTS:0));return(e.endProgramDateTime||0)-t>o}var kr,Cs=3e5,xr=0,gt=2,Di=5,Kt=0,Ri=1,pa=2,Ss=function(){function o(e){this.hls=void 0,this.playlistError=0,this.penalizedRenditions={},this.log=void 0,this.warn=void 0,this.error=void 0,this.hls=e,this.log=R.log.bind(R,"[info]:"),this.warn=R.warn.bind(R,"[warning]:"),this.error=R.error.bind(R,"[error]:"),this.registerListeners()}var n=o.prototype;return n.registerListeners=function(){var e=this.hls;e.on(A.ERROR,this.onError,this),e.on(A.MANIFEST_LOADING,this.onManifestLoading,this),e.on(A.LEVEL_UPDATED,this.onLevelUpdated,this)},n.unregisterListeners=function(){var e=this.hls;e&&(e.off(A.ERROR,this.onError,this),e.off(A.ERROR,this.onErrorOut,this),e.off(A.MANIFEST_LOADING,this.onManifestLoading,this),e.off(A.LEVEL_UPDATED,this.onLevelUpdated,this))},n.destroy=function(){this.unregisterListeners(),this.hls=null,this.penalizedRenditions={}},n.startLoad=function(e){this.playlistError=0},n.stopLoad=function(){},n.getVariantLevelIndex=function(e){return(e==null?void 0:e.type)===ve?e.level:this.hls.loadLevel},n.onManifestLoading=function(){this.playlistError=0,this.penalizedRenditions={}},n.onLevelUpdated=function(){this.playlistError=0},n.onError=function(e,t){var i,r;if(!t.fatal){var a=this.hls,s=t.context;switch(t.details){case O.FRAG_LOAD_ERROR:case O.FRAG_LOAD_TIMEOUT:case O.KEY_LOAD_ERROR:case O.KEY_LOAD_TIMEOUT:return void(t.errorAction=this.getFragRetryOrSwitchAction(t));case O.FRAG_PARSING_ERROR:if((i=t.frag)!=null&&i.gap)return void(t.errorAction={action:xr,flags:Kt});case O.FRAG_GAP:case O.FRAG_DECRYPT_ERROR:return t.errorAction=this.getFragRetryOrSwitchAction(t),void(t.errorAction.action=gt);case O.LEVEL_EMPTY_ERROR:case O.LEVEL_PARSING_ERROR:var l,d,c=t.parent===ve?t.level:a.loadLevel;return void(t.details===O.LEVEL_EMPTY_ERROR&&(l=t.context)!=null&&(d=l.levelDetails)!=null&&d.live?t.errorAction=this.getPlaylistRetryOrSwitchAction(t,c):(t.levelRetry=!1,t.errorAction=this.getLevelSwitchAction(t,c)));case O.LEVEL_LOAD_ERROR:case O.LEVEL_LOAD_TIMEOUT:return void(typeof(s==null?void 0:s.level)=="number"&&(t.errorAction=this.getPlaylistRetryOrSwitchAction(t,s.level)));case O.AUDIO_TRACK_LOAD_ERROR:case O.AUDIO_TRACK_LOAD_TIMEOUT:case O.SUBTITLE_LOAD_ERROR:case O.SUBTITLE_TRACK_LOAD_TIMEOUT:if(s){var u=a.levels[a.loadLevel];if(u&&(s.type===st&&s.groupId===u.audioGroupId||s.type===pt&&s.groupId===u.textGroupId))return t.errorAction=this.getPlaylistRetryOrSwitchAction(t,a.loadLevel),t.errorAction.action=gt,void(t.errorAction.flags=Ri)}return;case O.KEY_SYSTEM_STATUS_OUTPUT_RESTRICTED:var g=a.levels[a.loadLevel],m=g==null?void 0:g.attrs["HDCP-LEVEL"];return void(m&&(t.errorAction={action:gt,flags:pa,hdcpLevel:m}));case O.BUFFER_ADD_CODEC_ERROR:case O.REMUX_ALLOC_ERROR:return void(t.errorAction=this.getLevelSwitchAction(t,(r=t.level)!=null?r:a.loadLevel));case O.INTERNAL_EXCEPTION:case O.BUFFER_APPENDING_ERROR:case O.BUFFER_APPEND_ERROR:case O.BUFFER_FULL_ERROR:case O.LEVEL_SWITCH_ERROR:case O.BUFFER_STALLED_ERROR:case O.BUFFER_SEEK_OVER_HOLE:case O.BUFFER_NUDGE_ON_STALL:return void(t.errorAction={action:xr,flags:Kt})}if(t.type===ne.KEY_SYSTEM_ERROR){var v=this.getVariantLevelIndex(t.frag);return t.levelRetry=!1,void(t.errorAction=this.getLevelSwitchAction(t,v))}}},n.getPlaylistRetryOrSwitchAction=function(e,t){var i,r=ha(this.hls.config.playlistLoadPolicy,e),a=this.playlistError++,s=(i=e.response)==null?void 0:i.code;if(Li(r,a,Si(e),s))return{action:Di,flags:Kt,retryConfig:r,retryCount:a};var l=this.getLevelSwitchAction(e,t);return r&&(l.retryConfig=r,l.retryCount=a),l},n.getFragRetryOrSwitchAction=function(e){var t=this.hls,i=this.getVariantLevelIndex(e.frag),r=t.levels[i],a=t.config,s=a.fragLoadPolicy,l=a.keyLoadPolicy,d=ha(e.details.startsWith("key")?l:s,e),c=t.levels.reduce(function(v,y){return v+y.fragmentError},0);if(r){var u;e.details!==O.FRAG_GAP&&r.fragmentError++;var g=(u=e.response)==null?void 0:u.code;if(Li(d,c,Si(e),g))return{action:Di,flags:Kt,retryConfig:d,retryCount:c}}var m=this.getLevelSwitchAction(e,i);return d&&(m.retryConfig=d,m.retryCount=c),m},n.getLevelSwitchAction=function(e,t){var i=this.hls;t==null&&(t=i.loadLevel);var r=this.hls.levels[t];if(r&&(r.loadError++,i.autoLevelEnabled)){for(var a,s,l=-1,d=i.levels,c=i.loadLevel,u=i.minAutoLevel,g=i.maxAutoLevel,m=(a=e.frag)==null?void 0:a.type,v=(s=e.context)!=null?s:{},y=v.type,_=v.groupId,b=d.length;b--;){var E=(b+c)%d.length;if(E!==c&&E>=u&&E<=g&&d[E].loadError===0){var S=d[E];if(e.details===O.FRAG_GAP&&e.frag){var C=d[E].details;if(C){var L=oi(e.frag,C.fragments,e.frag.start);if(L!=null&&L.gap)continue}}else if(y===st&&_===S.audioGroupId||y===pt&&_===S.textGroupId||m===lt&&r.audioGroupId===S.audioGroupId||m===kt&&r.textGroupId===S.textGroupId)continue;l=E;break}}if(l>-1&&i.loadLevel!==l)return e.levelRetry=!0,this.playlistError=0,{action:gt,flags:Kt,nextAutoLevel:l}}return{action:gt,flags:Ri}},n.onErrorOut=function(e,t){var i;switch((i=t.errorAction)==null?void 0:i.action){case xr:break;case gt:this.sendAlternateToPenaltyBox(t),t.errorAction.resolved||t.details===O.FRAG_GAP||(t.fatal=!0)}t.fatal&&this.hls.stopLoad()},n.sendAlternateToPenaltyBox=function(e){var t=this.hls,i=e.errorAction;if(i){var r=i.flags,a=i.hdcpLevel,s=i.nextAutoLevel;switch(r){case Kt:this.switchLevel(e,s);break;case Ri:i.resolved||(i.resolved=this.redundantFailover(e));break;case pa:a&&(t.maxHdcpLevel=br[br.indexOf(a)-1],i.resolved=!0),this.warn('Restricting playback to HDCP-LEVEL of "'+t.maxHdcpLevel+'" or lower')}i.resolved||this.switchLevel(e,s)}},n.switchLevel=function(e,t){t!==void 0&&e.errorAction&&(this.warn("switching to level "+t+" after "+e.details),this.hls.nextAutoLevel=t,e.errorAction.resolved=!0,this.hls.nextLoadLevel=this.hls.nextAutoLevel)},n.redundantFailover=function(e){var t=this,i=this.hls,r=this.penalizedRenditions,a=e.parent===ve?e.level:i.loadLevel,s=i.levels[a],l=s.url.length,d=e.frag?e.frag.urlId:s.urlId;s.urlId!==d||e.frag&&!s.details||this.penalizeRendition(s,e);for(var c=function(){var m=(d+u)%l,v=r[m];if(!v||function(y,_,b){if(performance.now()-y.lastErrorPerfMs>Cs)return!0;var E=y.details;if(_.details===O.FRAG_GAP&&E&&_.frag){var S=_.frag.start,C=oi(null,E.fragments,S);if(C&&!C.gap)return!0}if(b&&y.errors.length3*E.targetduration)return!0}return!1}(v,e,r[d]))return t.warn("Switching to Redundant Stream "+(m+1)+"/"+l+': "'+s.url[m]+'" after '+e.details),t.playlistError=0,i.levels.forEach(function(y){y.urlId=m}),i.nextLoadLevel=a,{v:!0}},u=1;u=0&&g>t.partTarget&&(u+=1)}return new oa(c,u>=0?u:void 0,yr)}}},n.loadPlaylist=function(e){this.requestScheduled===-1&&(this.requestScheduled=self.performance.now())},n.shouldLoadPlaylist=function(e){return this.canLoad&&!!e&&!!e.url&&(!e.details||e.details.live)},n.shouldReloadPlaylist=function(e){return this.timer===-1&&this.requestScheduled===-1&&this.shouldLoadPlaylist(e)},n.playlistLoaded=function(e,t,i){var r=this,a=t.details,s=t.stats,l=self.performance.now(),d=s.loading.first?Math.max(0,l-s.loading.first):0;if(a.advancedDateTime=Date.now()-d,a.live||i!=null&&i.live){if(a.reloaded(i),i&&this.log("live playlist "+e+" "+(a.advanced?"REFRESHED "+a.lastPartSn+"-"+a.lastPartIndex:a.updated?"UPDATED":"MISSED")),i&&a.fragments.length>0&&xs(i,a),!this.canLoad||!a.live)return;var c,u=void 0,g=void 0;if(a.canBlockReload&&a.endSN&&a.advanced){var m=this.hls.config.lowLatencyMode,v=a.lastPartSn,y=a.endSN,_=a.lastPartIndex,b=v===y;_!==-1?(u=b?y+1:v,g=b?m?0:_:_+1):u=y+1;var E=a.age,S=E+a.ageHeader,C=Math.min(S-a.partTarget,1.5*a.targetduration);if(C>0){if(i&&C>i.tuneInGoal)this.warn("CDN Tune-in goal increased from: "+i.tuneInGoal+" to: "+C+" with playlist age: "+a.age),C=0;else{var L=Math.floor(C/a.targetduration);u+=L,g!==void 0&&(g+=Math.round(C%a.targetduration/a.partTarget)),this.log("CDN Tune-in age: "+a.ageHeader+"s last advanced "+E.toFixed(2)+"s goal: "+C+" skip sn "+L+" to part "+g)}a.tuneInGoal=C}if(c=this.getDeliveryDirectives(a,t.deliveryDirectives,u,g),m||!b)return void this.loadPlaylist(c)}else(a.canBlockReload||a.canSkipUntil)&&(c=this.getDeliveryDirectives(a,t.deliveryDirectives,u,g));var I=this.hls.mainForwardBufferInfo,P=I?I.end-I.len:0,N=function(B,Y){Y===void 0&&(Y=1/0);var K=1e3*B.targetduration;if(B.updated){var Q=B.fragments;if(Q.length&&4*K>Y){var re=1e3*Q[Q.length-1].duration;rethis.requestScheduled+N&&(this.requestScheduled=s.loading.start),u!==void 0&&a.canBlockReload?this.requestScheduled=s.loading.first+N-(1e3*a.partTarget||1e3):this.requestScheduled===-1||this.requestScheduled+N=u.maxNumRetry)return!1;if(r&&(m=e.context)!=null&&m.deliveryDirectives)this.warn("Retrying playlist loading "+(c+1)+"/"+u.maxNumRetry+' after "'+i+'" without delivery-directives'),this.loadPlaylist();else{var v=Ar(u,c);this.timer=self.setTimeout(function(){return t.loadPlaylist()},v),this.warn("Retrying playlist loading "+(c+1)+"/"+u.maxNumRetry+' after "'+i+'" in '+v+"ms")}e.levelRetry=!0,a.resolved=!0}return g},o}(),Ls=function(o){function n(t,i){var r;return(r=o.call(this,t,"[level-controller]")||this)._levels=[],r._firstLevel=-1,r._startLevel=void 0,r.currentLevel=null,r.currentLevelIndex=-1,r.manualLevelIndex=-1,r.steering=void 0,r.onParsedComplete=void 0,r.steering=i,r._registerListeners(),r}q(n,o);var e=n.prototype;return e._registerListeners=function(){var t=this.hls;t.on(A.MANIFEST_LOADING,this.onManifestLoading,this),t.on(A.MANIFEST_LOADED,this.onManifestLoaded,this),t.on(A.LEVEL_LOADED,this.onLevelLoaded,this),t.on(A.LEVELS_UPDATED,this.onLevelsUpdated,this),t.on(A.AUDIO_TRACK_SWITCHED,this.onAudioTrackSwitched,this),t.on(A.FRAG_LOADED,this.onFragLoaded,this),t.on(A.ERROR,this.onError,this)},e._unregisterListeners=function(){var t=this.hls;t.off(A.MANIFEST_LOADING,this.onManifestLoading,this),t.off(A.MANIFEST_LOADED,this.onManifestLoaded,this),t.off(A.LEVEL_LOADED,this.onLevelLoaded,this),t.off(A.LEVELS_UPDATED,this.onLevelsUpdated,this),t.off(A.AUDIO_TRACK_SWITCHED,this.onAudioTrackSwitched,this),t.off(A.FRAG_LOADED,this.onFragLoaded,this),t.off(A.ERROR,this.onError,this)},e.destroy=function(){this._unregisterListeners(),this.steering=null,this.resetLevels(),o.prototype.destroy.call(this)},e.startLoad=function(){this._levels.forEach(function(t){t.loadError=0,t.fragmentError=0}),o.prototype.startLoad.call(this)},e.resetLevels=function(){this._startLevel=void 0,this.manualLevelIndex=-1,this.currentLevelIndex=-1,this.currentLevel=null,this._levels=[]},e.onManifestLoading=function(t,i){this.resetLevels()},e.onManifestLoaded=function(t,i){var r,a=[],s={};i.levels.forEach(function(l){var d,c=l.attrs;((d=l.audioCodec)==null?void 0:d.indexOf("mp4a.40.34"))!==-1&&(kr||(kr=/chrome|firefox/i.test(navigator.userAgent)),kr&&(l.audioCodec=void 0));var u=c.AUDIO,g=c.CODECS,m=c["FRAME-RATE"],v=c["PATHWAY-ID"],y=c.RESOLUTION,_=c.SUBTITLES,b=(v||".")+"-"+l.bitrate+"-"+y+"-"+m+"-"+g;(r=s[b])?r.addFallback(l):(r=new ai(l),s[b]=r,a.push(r)),Ii(r,"audio",u),Ii(r,"text",_)}),this.filterAndSortMediaOptions(a,i)},e.filterAndSortMediaOptions=function(t,i){var r=this,a=[],s=[],l=!1,d=!1,c=!1,u=t.filter(function(E){var S=E.audioCodec,C=E.videoCodec,L=E.width,I=E.height,P=E.unknownCodecs;return l||(l=!(!L||!I)),d||(d=!!C),c||(c=!!S),!(P!=null&&P.length)&&(!S||fr(S,"audio"))&&(!C||fr(C,"video"))});if((l||d)&&c&&(u=u.filter(function(E){var S=E.videoCodec,C=E.width,L=E.height;return!!S||!(!C||!L)})),u.length!==0){i.audioTracks&&ga(a=i.audioTracks.filter(function(E){return!E.audioCodec||fr(E.audioCodec,"audio")})),i.subtitles&&ga(s=i.subtitles);var g=u.slice(0);u.sort(function(E,S){return E.attrs["HDCP-LEVEL"]!==S.attrs["HDCP-LEVEL"]?(E.attrs["HDCP-LEVEL"]||"")>(S.attrs["HDCP-LEVEL"]||"")?1:-1:E.bitrate!==S.bitrate?E.bitrate-S.bitrate:E.attrs["FRAME-RATE"]!==S.attrs["FRAME-RATE"]?E.attrs.decimalFloatingPoint("FRAME-RATE")-S.attrs.decimalFloatingPoint("FRAME-RATE"):E.attrs.SCORE!==S.attrs.SCORE?E.attrs.decimalFloatingPoint("SCORE")-S.attrs.decimalFloatingPoint("SCORE"):l&&E.height!==S.height?E.height-S.height:0});var m=g[0];if(this.steering&&(u=this.steering.filterParsedLevels(u)).length!==g.length){for(var v=0;v1&&i!==void 0?(l.url=l.url.filter(a),l.audioGroupIds&&(l.audioGroupIds=l.audioGroupIds.filter(a)),l.textGroupIds&&(l.textGroupIds=l.textGroupIds.filter(a)),l.urlId=0,!0):(r.steering&&r.steering.removeLevel(l),!1))});this.hls.trigger(A.LEVELS_UPDATED,{levels:s})},e.onLevelsUpdated=function(t,i){var r=i.levels;r.forEach(function(a,s){var l=a.details;l!=null&&l.fragments&&l.fragments.forEach(function(d){d.level=s})}),this._levels=r},D(n,[{key:"levels",get:function(){return this._levels.length===0?null:this._levels}},{key:"level",get:function(){return this.currentLevelIndex},set:function(t){var i=this._levels;if(i.length!==0){if(t<0||t>=i.length){var r=new Error("invalid level idx"),a=t<0;if(this.hls.trigger(A.ERROR,{type:ne.OTHER_ERROR,details:O.LEVEL_SWITCH_ERROR,level:t,fatal:a,error:r,reason:r.message}),a)return;t=Math.min(t,i.length-1)}var s=this.currentLevelIndex,l=this.currentLevel,d=l?l.attrs["PATHWAY-ID"]:void 0,c=i[t],u=c.attrs["PATHWAY-ID"];if(this.currentLevelIndex=t,this.currentLevel=c,s!==t||!c.details||!l||d!==u){this.log("Switching to level "+t+(u?" with Pathway "+u:"")+" from level "+s+(d?" with Pathway "+d:""));var g=F({},c,{level:t,maxBitrate:c.maxBitrate,attrs:c.attrs,uri:c.uri,urlId:c.urlId});delete g._attrs,delete g._urlId,this.hls.trigger(A.LEVEL_SWITCHING,g);var m=c.details;if(!m||m.live){var v=this.switchParams(c.uri,l==null?void 0:l.details);this.loadPlaylist(v)}}}}},{key:"manualLevel",get:function(){return this.manualLevelIndex},set:function(t){this.manualLevelIndex=t,this._startLevel===void 0&&(this._startLevel=t),t!==-1&&(this.level=t)}},{key:"firstLevel",get:function(){return this._firstLevel},set:function(t){this._firstLevel=t}},{key:"startLevel",get:function(){if(this._startLevel===void 0){var t=this.hls.config.startLevel;return t!==void 0?t:this._firstLevel}return this._startLevel},set:function(t){this._startLevel=t}},{key:"nextLoadLevel",get:function(){return this.manualLevelIndex!==-1?this.manualLevelIndex:this.hls.nextAutoLevel},set:function(t){this.level=t,this.manualLevelIndex===-1&&(this.hls.nextAutoLevel=t)}}]),n}(Tr);function Ii(o,n,e){e&&(n==="audio"?(o.audioGroupIds||(o.audioGroupIds=[]),o.audioGroupIds[o.url.length-1]=e):n==="text"&&(o.textGroupIds||(o.textGroupIds=[]),o.textGroupIds[o.url.length-1]=e))}function ga(o){var n={};o.forEach(function(e){var t=e.groupId||"";e.id=n[t]=n[t]||0,n[t]++})}var si="NOT_LOADED",ma="APPENDING",Vt="PARTIAL",li="OK",Ds=function(){function o(e){this.activePartLists=Object.create(null),this.endListFragments=Object.create(null),this.fragments=Object.create(null),this.timeRanges=Object.create(null),this.bufferPadding=.2,this.hls=void 0,this.hasGaps=!1,this.hls=e,this._registerListeners()}var n=o.prototype;return n._registerListeners=function(){var e=this.hls;e.on(A.BUFFER_APPENDED,this.onBufferAppended,this),e.on(A.FRAG_BUFFERED,this.onFragBuffered,this),e.on(A.FRAG_LOADED,this.onFragLoaded,this)},n._unregisterListeners=function(){var e=this.hls;e.off(A.BUFFER_APPENDED,this.onBufferAppended,this),e.off(A.FRAG_BUFFERED,this.onFragBuffered,this),e.off(A.FRAG_LOADED,this.onFragLoaded,this)},n.destroy=function(){this._unregisterListeners(),this.fragments=this.activePartLists=this.endListFragments=this.timeRanges=null},n.getAppendedFrag=function(e,t){var i=this.activePartLists[t];if(i)for(var r=i.length;r--;){var a=i[r];if(!a)break;var s=a.end;if(a.start<=e&&s!==null&&e<=s)return a}return this.getBufferedFrag(e,t)},n.getBufferedFrag=function(e,t){for(var i=this.fragments,r=Object.keys(i),a=r.length;a--;){var s=i[r[a]];if((s==null?void 0:s.body.type)===t&&s.buffered){var l=s.body;if(l.start<=e&&e<=l.end)return l}}return null},n.detectEvictedFragments=function(e,t,i,r){var a=this;this.timeRanges&&(this.timeRanges[e]=t);var s=(r==null?void 0:r.fragment.sn)||-1;Object.keys(this.fragments).forEach(function(l){var d=a.fragments[l];if(d&&!(s>=d.body.sn))if(d.buffered||d.loaded){var c=d.range[e];c&&c.time.some(function(u){var g=!a.isTimeBuffered(u.startPTS,u.endPTS,t);return g&&a.removeFragment(d.body),g})}else d.body.type===i&&a.removeFragment(d.body)})},n.detectPartialFragments=function(e){var t=this,i=this.timeRanges,r=e.frag,a=e.part;if(i&&r.sn!=="initSegment"){var s=zt(r),l=this.fragments[s];if(!(!l||l.buffered&&r.gap)){var d=!r.relurl;Object.keys(i).forEach(function(c){var u=r.elementaryStreams[c];if(u){var g=i[c],m=d||u.partial===!0;l.range[c]=t.getBufferedTimes(r,a,m,g)}}),l.loaded=null,Object.keys(l.range).length?(l.buffered=!0,(l.body.endList=r.endList||l.body.endList)&&(this.endListFragments[l.body.type]=l),Pi(l)||this.removeParts(r.sn-1,r.type)):this.removeFragment(l.body)}}},n.removeParts=function(e,t){var i=this.activePartLists[t];i&&(this.activePartLists[t]=i.filter(function(r){return r.fragment.sn>=e}))},n.fragBuffered=function(e,t){var i=zt(e),r=this.fragments[i];!r&&t&&(r=this.fragments[i]={body:e,appendedPTS:null,loaded:null,buffered:!1,range:Object.create(null)},e.gap&&(this.hasGaps=!0)),r&&(r.loaded=null,r.buffered=!0)},n.getBufferedTimes=function(e,t,i,r){for(var a={time:[],partial:i},s=e.start,l=e.end,d=e.minEndPTS||l,c=e.maxStartPTS||s,u=0;u=g&&d<=m){a.time.push({startPTS:Math.max(s,r.start(u)),endPTS:Math.min(l,r.end(u))});break}if(sg)a.partial=!0,a.time.push({startPTS:Math.max(s,r.start(u)),endPTS:Math.min(l,r.end(u))});else if(l<=g)break}return a},n.getPartialFragment=function(e){var t,i,r,a=null,s=0,l=this.bufferPadding,d=this.fragments;return Object.keys(d).forEach(function(c){var u=d[c];u&&Pi(u)&&(i=u.body.start-l,r=u.body.end+l,e>=i&&e<=r&&(t=Math.min(e-i,r-e),s<=t&&(a=u.body,s=t)))}),a},n.isEndListAppended=function(e){var t=this.endListFragments[e];return t!==void 0&&(t.buffered||Pi(t))},n.getState=function(e){var t=zt(e),i=this.fragments[t];return i?i.buffered?Pi(i)?Vt:li:ma:si},n.isTimeBuffered=function(e,t,i){for(var r,a,s=0;s=r&&t<=a)return!0;if(t<=r)return!1}return!1},n.onFragLoaded=function(e,t){var i=t.frag,r=t.part;if(i.sn!=="initSegment"&&!i.bitrateTest){var a=r?null:t,s=zt(i);this.fragments[s]={body:i,appendedPTS:null,loaded:a,buffered:!1,range:Object.create(null)}}},n.onBufferAppended=function(e,t){var i=this,r=t.frag,a=t.part,s=t.timeRanges;if(r.sn!=="initSegment"){var l=r.type;if(a){var d=this.activePartLists[l];d||(this.activePartLists[l]=d=[]),d.push(a)}this.timeRanges=s,Object.keys(s).forEach(function(c){var u=s[c];i.detectEvictedFragments(c,u,l,a)})}},n.onFragBuffered=function(e,t){this.detectPartialFragments(t)},n.hasFragment=function(e){var t=zt(e);return!!this.fragments[t]},n.hasParts=function(e){var t;return!((t=this.activePartLists[e])==null||!t.length)},n.removeFragmentsInRange=function(e,t,i,r,a){var s=this;r&&!this.hasGaps||Object.keys(this.fragments).forEach(function(l){var d=s.fragments[l];if(d){var c=d.body;c.type!==i||r&&!c.gap||c.starte&&(d.buffered||a)&&s.removeFragment(c)}})},n.removeFragment=function(e){var t=zt(e);e.stats.loaded=0,e.clearElementaryStreamInfo();var i=this.activePartLists[e.type];if(i){var r=e.sn;this.activePartLists[e.type]=i.filter(function(a){return a.fragment.sn!==r})}delete this.fragments[t],e.endList&&delete this.endListFragments[e.type]},n.removeAllFragments=function(){this.fragments=Object.create(null),this.endListFragments=Object.create(null),this.activePartLists=Object.create(null),this.hasGaps=!1},o}();function Pi(o){var n,e,t;return o.buffered&&(o.body.gap||((n=o.range.video)==null?void 0:n.partial)||((e=o.range.audio)==null?void 0:e.partial)||((t=o.range.audiovideo)==null?void 0:t.partial))}function zt(o){return o.type+"_"+o.level+"_"+o.urlId+"_"+o.sn}var va=Math.pow(2,17),Rs=function(){function o(e){this.config=void 0,this.loader=null,this.partLoadTimeout=-1,this.config=e}var n=o.prototype;return n.destroy=function(){this.loader&&(this.loader.destroy(),this.loader=null)},n.abort=function(){this.loader&&this.loader.abort()},n.load=function(e,t){var i=this,r=e.url;if(!r)return Promise.reject(new mt({type:ne.NETWORK_ERROR,details:O.FRAG_LOAD_ERROR,fatal:!1,frag:e,error:new Error("Fragment does not have a "+(r?"part list":"url")),networkDetails:null}));this.abort();var a=this.config,s=a.fLoader,l=a.loader;return new Promise(function(d,c){if(i.loader&&i.loader.destroy(),e.gap){if(e.tagList.some(function(y){return y[0]==="GAP"}))return void c(ya(e));e.gap=!1}var u=i.loader=e.loader=s?new s(a):new l(a),g=ba(e),m=ua(a.fragLoadPolicy.default),v={loadPolicy:m,timeout:m.maxLoadTimeMs,maxRetry:0,retryDelay:0,maxRetryDelay:0,highWaterMark:e.sn==="initSegment"?1/0:va};e.stats=u.stats,u.load(g,v,{onSuccess:function(y,_,b,E){i.resetLoader(e,u);var S=y.data;b.resetIV&&e.decryptdata&&(e.decryptdata.iv=new Uint8Array(S.slice(0,16)),S=S.slice(16)),d({frag:e,part:null,payload:S,networkDetails:E})},onError:function(y,_,b,E){i.resetLoader(e,u),c(new mt({type:ne.NETWORK_ERROR,details:O.FRAG_LOAD_ERROR,fatal:!1,frag:e,response:x({url:r,data:void 0},y),error:new Error("HTTP Error "+y.code+" "+y.text),networkDetails:b,stats:E}))},onAbort:function(y,_,b){i.resetLoader(e,u),c(new mt({type:ne.NETWORK_ERROR,details:O.INTERNAL_ABORTED,fatal:!1,frag:e,error:new Error("Aborted"),networkDetails:b,stats:y}))},onTimeout:function(y,_,b){i.resetLoader(e,u),c(new mt({type:ne.NETWORK_ERROR,details:O.FRAG_LOAD_TIMEOUT,fatal:!1,frag:e,error:new Error("Timeout after "+v.timeout+"ms"),networkDetails:b,stats:y}))},onProgress:function(y,_,b,E){t&&t({frag:e,part:null,payload:b,networkDetails:E})}})})},n.loadPart=function(e,t,i){var r=this;this.abort();var a=this.config,s=a.fLoader,l=a.loader;return new Promise(function(d,c){if(r.loader&&r.loader.destroy(),e.gap||t.gap)c(ya(e,t));else{var u=r.loader=e.loader=s?new s(a):new l(a),g=ba(e,t),m=ua(a.fragLoadPolicy.default),v={loadPolicy:m,timeout:m.maxLoadTimeMs,maxRetry:0,retryDelay:0,maxRetryDelay:0,highWaterMark:va};t.stats=u.stats,u.load(g,v,{onSuccess:function(y,_,b,E){r.resetLoader(e,u),r.updateStatsFromPart(e,t);var S={frag:e,part:t,payload:y.data,networkDetails:E};i(S),d(S)},onError:function(y,_,b,E){r.resetLoader(e,u),c(new mt({type:ne.NETWORK_ERROR,details:O.FRAG_LOAD_ERROR,fatal:!1,frag:e,part:t,response:x({url:g.url,data:void 0},y),error:new Error("HTTP Error "+y.code+" "+y.text),networkDetails:b,stats:E}))},onAbort:function(y,_,b){e.stats.aborted=t.stats.aborted,r.resetLoader(e,u),c(new mt({type:ne.NETWORK_ERROR,details:O.INTERNAL_ABORTED,fatal:!1,frag:e,part:t,error:new Error("Aborted"),networkDetails:b,stats:y}))},onTimeout:function(y,_,b){r.resetLoader(e,u),c(new mt({type:ne.NETWORK_ERROR,details:O.FRAG_LOAD_TIMEOUT,fatal:!1,frag:e,part:t,error:new Error("Timeout after "+v.timeout+"ms"),networkDetails:b,stats:y}))}})}})},n.updateStatsFromPart=function(e,t){var i=e.stats,r=t.stats,a=r.total;if(i.loaded+=r.loaded,a){var s=Math.round(e.duration/t.duration),l=Math.min(Math.round(i.loaded/a),s),d=(s-l)*Math.round(i.loaded/l);i.total=i.loaded+d}else i.total=Math.max(i.loaded,i.total);var c=i.loading,u=r.loading;c.start?c.first+=u.first-u.start:(c.start=u.start,c.first=u.first),c.end=u.end},n.resetLoader=function(e,t){e.loader=null,this.loader===t&&(self.clearTimeout(this.partLoadTimeout),this.loader=null),t.destroy()},o}();function ba(o,n){n===void 0&&(n=null);var e=n||o,t={frag:o,part:n,responseType:"arraybuffer",url:e.url,headers:{},rangeStart:0,rangeEnd:0},i=e.byteRangeStartOffset,r=e.byteRangeEndOffset;if(ie(i)&&ie(r)){var a,s=i,l=r;if(o.sn==="initSegment"&&((a=o.decryptdata)==null?void 0:a.method)==="AES-128"){var d=r-i;d%16&&(l=r+(16-d%16)),i!==0&&(t.resetIV=!0,s=i-16)}t.rangeStart=s,t.rangeEnd=l}return t}function ya(o,n){var e=new Error("GAP "+(o.gap?"tag":"attribute")+" found"),t={type:ne.MEDIA_ERROR,details:O.FRAG_GAP,fatal:!1,frag:o,error:e,networkDetails:null};return n&&(t.part=n),(n||o).stats.aborted=!0,new mt(t)}var mt=function(o){function n(e){var t;return(t=o.call(this,e.error.message)||this).data=void 0,t.data=e,t}return q(n,o),n}(ce(Error)),Is=function(){function o(e){this.config=void 0,this.keyUriToKeyInfo={},this.emeController=null,this.config=e}var n=o.prototype;return n.abort=function(e){for(var t in this.keyUriToKeyInfo){var i=this.keyUriToKeyInfo[t].loader;if(i){if(e&&e!==i.context.frag.type)return;i.abort()}}},n.detach=function(){for(var e in this.keyUriToKeyInfo){var t=this.keyUriToKeyInfo[e];(t.mediaKeySessionContext||t.decryptdata.isCommonEncryption)&&delete this.keyUriToKeyInfo[e]}},n.destroy=function(){for(var e in this.detach(),this.keyUriToKeyInfo){var t=this.keyUriToKeyInfo[e].loader;t&&t.destroy()}this.keyUriToKeyInfo={}},n.createKeyLoadError=function(e,t,i,r,a){return t===void 0&&(t=O.KEY_LOAD_ERROR),new mt({type:ne.NETWORK_ERROR,details:t,fatal:!1,frag:e,response:a,error:i,networkDetails:r})},n.loadClear=function(e,t){var i=this;if(this.emeController&&this.config.emeEnabled)for(var r=e.sn,a=e.cc,s=function(){var d=t[l];if(a<=d.cc&&(r==="initSegment"||d.sn==="initSegment"||r1&&this.tickImmediate(),this._tickCallCount=0)},n.tickImmediate=function(){this.clearNextTick(),this._tickTimer=self.setTimeout(this._boundTick,0)},n.doTick=function(){},o}(),Os={length:0,start:function(){return 0},end:function(){return 0}},Ae=function(){function o(){}return o.isBuffered=function(n,e){try{if(n){for(var t=o.getBuffered(n),i=0;i=t.start(i)&&e<=t.end(i))return!0}}catch{}return!1},o.bufferInfo=function(n,e,t){try{if(n){var i,r=o.getBuffered(n),a=[];for(i=0;is&&(i[a-1].end=n[r].end):i.push(n[r])}else i.push(n[r])}else i=n;for(var l,d=0,c=e,u=e,g=0;g=m&&ed.startCC||s&&s.cc>>8^255&E^99,e[y]=E,t[E]=y;var S=v[y],C=v[S],L=v[C],I=257*v[E]^16843008*E;r[y]=I<<24|I>>>8,a[y]=I<<16|I>>>16,s[y]=I<<8|I>>>24,l[y]=I,I=16843009*L^65537*C^257*S^16843008*y,c[E]=I<<24|I>>>8,u[E]=I<<16|I>>>16,g[E]=I<<8|I>>>24,m[E]=I,y?(y=S^v[v[v[L^S]]],_^=v[v[_]]):y=_=1}},n.expandKey=function(e){for(var t=this.uint8ArrayToUint32Array_(e),i=!0,r=0;rd.end){var m=l>g;(l0&&d&&d.key&&d.iv&&d.method==="AES-128"){var c=self.performance.now();return r.decrypter.decrypt(new Uint8Array(l),d.key.buffer,d.iv.buffer).catch(function(u){throw s.trigger(A.ERROR,{type:ne.MEDIA_ERROR,details:O.FRAG_DECRYPT_ERROR,fatal:!1,error:u,reason:u.message,frag:t}),u}).then(function(u){var g=self.performance.now();return s.trigger(A.FRAG_DECRYPTED,{frag:t,payload:u,stats:{tstart:c,tdecrypt:g}}),a.payload=u,a})}return a}).then(function(a){var s=r.fragCurrent,l=r.hls;if(!r.levels)throw new Error("init load aborted, missing levels");var d=t.stats;r.state=ue,i.fragmentError=0,t.data=new Uint8Array(a.payload),d.parsing.start=d.buffering.start=self.performance.now(),d.parsing.end=d.buffering.end=self.performance.now(),a.frag===s&&l.trigger(A.FRAG_BUFFERED,{stats:d,frag:s,part:null,id:t.type}),r.tick()}).catch(function(a){r.state!==$e&&r.state!==qt&&(r.warn(a),r.resetFragmentLoading(t))})},e.fragContextChanged=function(t){var i=this.fragCurrent;return!t||!i||t.level!==i.level||t.sn!==i.sn||t.urlId!==i.urlId},e.fragBufferedComplete=function(t,i){var r,a,s,l,d=this.mediaBuffer?this.mediaBuffer:this.media;this.log("Buffered "+t.type+" sn: "+t.sn+(i?" part: "+i.index:"")+" of "+(this.playlistType===ve?"level":"track")+" "+t.level+" (frag:["+((r=t.startPTS)!=null?r:NaN).toFixed(3)+"-"+((a=t.endPTS)!=null?a:NaN).toFixed(3)+"] > buffer:"+(d?Us(Ae.getBuffered(d)):"(detached)")+")"),this.state=ue,d&&(!this.loadedmetadata&&t.type==ve&&d.buffered.length&&((s=this.fragCurrent)==null?void 0:s.sn)===((l=this.fragPrevious)==null?void 0:l.sn)&&(this.loadedmetadata=!0,this.seekToStartPos()),this.tick())},e.seekToStartPos=function(){},e._handleFragmentLoadComplete=function(t){var i=this.transmuxer;if(i){var r=t.frag,a=t.part,s=t.partsLoaded,l=!s||s.length===0||s.some(function(c){return!c}),d=new Cr(r.level,r.sn,r.stats.chunkCount+1,0,a?a.index:-1,!l);i.flush(d)}},e._handleFragmentLoadProgress=function(t){},e._doFragLoad=function(t,i,r,a){var s,l=this;r===void 0&&(r=null);var d=i==null?void 0:i.details;if(!this.levels||!d)throw new Error("frag load aborted, missing level"+(d?"":" detail")+"s");var c=null;if(!t.encrypted||(s=t.decryptdata)!=null&&s.key?!t.encrypted&&d.encryptedFragments.length&&this.keyLoader.loadClear(t,d.encryptedFragments):(this.log("Loading key for "+t.sn+" of ["+d.startSN+"-"+d.endSN+"], "+(this.logPrefix==="[stream-controller]"?"level":"track")+" "+t.level),this.state=Dr,this.fragCurrent=t,c=this.keyLoader.load(t).then(function(b){if(!l.fragContextChanged(b.frag))return l.hls.trigger(A.KEY_LOADED,b),l.state===Dr&&(l.state=ue),b}),this.hls.trigger(A.KEY_LOADING,{frag:t}),this.fragCurrent===null&&(c=Promise.reject(new Error("frag load aborted, context changed in KEY_LOADING")))),r=Math.max(t.start,r||0),this.config.lowLatencyMode&&t.sn!=="initSegment"){var u=d.partList;if(u&&a){r>t.end&&d.fragmentHint&&(t=d.fragmentHint);var g=this.getNextPart(u,t,r);if(g>-1){var m,v=u[g];return this.log("Loading part sn: "+t.sn+" p: "+v.index+" cc: "+t.cc+" of playlist ["+d.startSN+"-"+d.endSN+"] parts [0-"+g+"-"+(u.length-1)+"] "+(this.logPrefix==="[stream-controller]"?"level":"track")+": "+t.level+", target: "+parseFloat(r.toFixed(3))),this.nextLoadPosition=v.start+v.duration,this.state=Yt,m=c?c.then(function(b){return!b||l.fragContextChanged(b.frag)?null:l.doFragPartsLoad(t,v,i,a)}).catch(function(b){return l.handleFragLoadError(b)}):this.doFragPartsLoad(t,v,i,a).catch(function(b){return l.handleFragLoadError(b)}),this.hls.trigger(A.FRAG_LOADING,{frag:t,part:v,targetBufferTime:r}),this.fragCurrent===null?Promise.reject(new Error("frag load aborted, context changed in FRAG_LOADING parts")):m}if(!t.url||this.loadedEndOfParts(u,r))return Promise.resolve(null)}}this.log("Loading fragment "+t.sn+" cc: "+t.cc+" "+(d?"of ["+d.startSN+"-"+d.endSN+"] ":"")+(this.logPrefix==="[stream-controller]"?"level":"track")+": "+t.level+", target: "+parseFloat(r.toFixed(3))),ie(t.sn)&&!this.bitrateTest&&(this.nextLoadPosition=t.start+t.duration),this.state=Yt;var y,_=this.config.progressive;return y=_&&c?c.then(function(b){return!b||l.fragContextChanged(b==null?void 0:b.frag)?null:l.fragmentLoader.load(t,a)}).catch(function(b){return l.handleFragLoadError(b)}):Promise.all([this.fragmentLoader.load(t,_?a:void 0),c]).then(function(b){var E=b[0];return!_&&E&&a&&a(E),E}).catch(function(b){return l.handleFragLoadError(b)}),this.hls.trigger(A.FRAG_LOADING,{frag:t,targetBufferTime:r}),this.fragCurrent===null?Promise.reject(new Error("frag load aborted, context changed in FRAG_LOADING")):y},e.doFragPartsLoad=function(t,i,r,a){var s=this;return new Promise(function(l,d){var c,u=[],g=(c=r.details)==null?void 0:c.partList;(function m(v){s.fragmentLoader.loadPart(t,v,a).then(function(y){u[v.index]=y;var _=y.part;s.hls.trigger(A.FRAG_LOADED,y);var b=da(r,t.sn,v.index+1)||ca(g,t.sn,v.index+1);if(!b)return l({frag:t,part:_,partsLoaded:u});m(b)}).catch(d)})(i)})},e.handleFragLoadError=function(t){if("data"in t){var i=t.data;t.data&&i.details===O.INTERNAL_ABORTED?this.handleFragLoadAborted(i.frag,i.part):this.hls.trigger(A.ERROR,i)}else this.hls.trigger(A.ERROR,{type:ne.OTHER_ERROR,details:O.INTERNAL_EXCEPTION,err:t,error:t,fatal:!0});return null},e._handleTransmuxerFlush=function(t){var i=this.getCurrentContext(t);if(i&&this.state===vt){var r=i.frag,a=i.part,s=i.level,l=self.performance.now();r.stats.parsing.end=l,a&&(a.stats.parsing.end=l),this.updateLevelTiming(r,a,s,t.partial)}else this.fragCurrent||this.state===$e||this.state===qt||(this.state=ue)},e.getCurrentContext=function(t){var i=this.levels,r=this.fragCurrent,a=t.level,s=t.sn,l=t.part;if(i==null||!i[a])return this.warn("Levels object was unset while buffering fragment "+s+" of level "+a+". The current chunk will not be buffered."),null;var d=i[a],c=l>-1?da(d,s,l):null,u=c?c.fragment:function(g,m,v){if(g==null||!g.details)return null;var y=g.details,_=y.fragments[m-y.startSN];return _||((_=y.fragmentHint)&&_.sn===m?_:ml&&this.flushMainBuffer(d,t.start)}else this.flushMainBuffer(0,t.start)},e.getFwdBufferInfo=function(t,i){var r=this.getLoadPosition();return ie(r)?this.getFwdBufferInfoAtPos(t,r,i):null},e.getFwdBufferInfoAtPos=function(t,i,r){var a=this.config.maxBufferHole,s=Ae.bufferInfo(t,i,a);if(s.len===0&&s.nextStart!==void 0){var l=this.fragmentTracker.getBufferedFrag(i,r);if(l&&s.nextStart=r&&(i.maxMaxBufferLength/=2,this.warn("Reduce max buffer length to "+i.maxMaxBufferLength+"s"),!0)},e.getAppendedFrag=function(t,i){var r=this.fragmentTracker.getAppendedFrag(t,ve);return r&&"fragment"in r?r.fragment:r},e.getNextFragment=function(t,i){var r=i.fragments,a=r.length;if(!a)return null;var s,l=this.config,d=r[0].start;if(i.live){var c=l.initialLiveManifestSize;if(ai},e.getNextFragmentLoopLoading=function(t,i,r,a,s){var l=t.gap,d=this.getNextFragment(this.nextLoadPosition,i);if(d===null)return d;if(t=d,l&&t&&!t.gap&&r.nextStart){var c=this.getFwdBufferInfoAtPos(this.mediaBuffer?this.mediaBuffer:this.media,r.nextStart,a);if(c!==null&&r.len+c.len>=s)return this.log('buffer full after gaps in "'+a+'" playlist starting at sn: '+t.sn),null}return t},e.mapToInitFragWhenRequired=function(t){return t==null||!t.initSegment||t!=null&&t.initSegment.data||this.bitrateTest?t:t.initSegment},e.getNextPart=function(t,i,r){for(var a=-1,s=!1,l=!0,d=0,c=t.length;d-1&&rr.start&&r.loaded},e.getInitialLiveFragment=function(t,i){var r=this.fragPrevious,a=null;if(r){if(t.hasProgramDateTime&&(this.log("Live playlist, switching playlist, load frag with same PDT: "+r.programDateTime),a=function(c,u,g){if(u===null||!Array.isArray(c)||!c.length||!ie(u)||u<(c[0].programDateTime||0)||u>=(c[c.length-1].endProgramDateTime||0))return null;g=g||0;for(var m=0;m=t.startSN&&s<=t.endSN){var l=i[s-t.startSN];r.cc===l.cc&&(a=l,this.log("Live playlist, switching playlist, load frag with next SN: "+a.sn))}a||(a=function(c,u){return fa(c,function(g){return g.ccu?-1:0})}(i,r.cc),a&&this.log("Live playlist, switching playlist, load frag with same CC: "+a.sn))}}else{var d=this.hls.liveSyncPosition;d!==null&&(a=this.getFragmentAtPosition(d,this.bitrateTest?t.fragmentEnd:t.edge,t))}return a},e.getFragmentAtPosition=function(t,i,r){var a,s=this.config,l=this.fragPrevious,d=r.fragments,c=r.endSN,u=r.fragmentHint,g=s.maxFragLookUpTolerance,m=r.partList,v=!!(s.lowLatencyMode&&m!=null&&m.length&&u);if(v&&u&&!this.bitrateTest&&(d=d.concat(u),c=u.sn),a=ti-g?0:g):d[d.length-1]){var y=a.sn-r.startSN,_=this.fragmentTracker.getState(a);if((_===li||_===Vt&&a.gap)&&(l=a),l&&a.sn===l.sn&&(!v||m[0].fragment.sn>a.sn)&&l&&a.level===l.level){var b=d[y+1];a=a.sn=l-i.maxFragLookUpTolerance&&s<=d;if(a!==null&&r.duration>a&&(s"+t.startSN+" prev-sn: "+(s?s.sn:"na")+" fragments: "+d),m}return c},e.waitForCdnTuneIn=function(t){return t.live&&t.canBlockReload&&t.partTarget&&t.tuneInGoal>Math.max(t.partHoldBack,3*t.partTarget)},e.setStartPosition=function(t,i){var r=this.startPosition;if(r "+((s=this.fragCurrent)==null?void 0:s.url))}else{var l=i.details===O.FRAG_GAP;l&&this.fragmentTracker.fragBuffered(a,!0);var d=i.errorAction,c=d||{},u=c.action,g=c.retryCount,m=g===void 0?0:g,v=c.retryConfig;if(d&&u===Di&&v){var y;this.resetStartWhenNotLoaded((y=this.levelLastLoaded)!=null?y:a.level);var _=Ar(v,m);this.warn("Fragment "+a.sn+" of "+t+" "+a.level+" errored with "+i.details+", retrying loading "+(m+1)+"/"+v.maxNumRetry+" in "+_+"ms"),d.resolved=!0,this.retryDate=self.performance.now()+_,this.state=jt}else v&&d?(this.resetFragmentErrors(t),m.5;a&&this.reduceMaxBufferLength(r.len);var s=!a;return s&&this.warn("Buffer full error while media.currentTime is not buffered, flush "+i+" buffer"),t.frag&&(this.fragmentTracker.removeFragment(t.frag),this.nextLoadPosition=t.frag.start),this.resetLoadingState(),s}return!1},e.resetFragmentErrors=function(t){t===lt&&(this.fragCurrent=null),this.loadedmetadata||(this.startFragRequested=!1),this.state!==$e&&(this.state=ue)},e.afterBufferFlushed=function(t,i,r){if(t){var a=Ae.getBuffered(t);this.fragmentTracker.detectEvictedFragments(i,a,r),this.state===ci&&this.resetLoadingState()}},e.resetLoadingState=function(){this.log("Reset loading state"),this.fragCurrent=null,this.fragPrevious=null,this.state=ue},e.resetStartWhenNotLoaded=function(t){if(!this.loadedmetadata){this.startFragRequested=!1;var i=this.levels?this.levels[t].details:null;i!=null&&i.live?(this.startPosition=-1,this.setStartPosition(i,0),this.resetLoadingState()):this.nextLoadPosition=this.startPosition}},e.resetWhenMissingContext=function(t){var i;this.warn("The loading context changed while buffering fragment "+t.sn+" of level "+t.level+". This chunk will not be buffered."),this.removeUnbufferedFrags(),this.resetStartWhenNotLoaded((i=this.levelLastLoaded)!=null?i:t.level),this.resetLoadingState()},e.removeUnbufferedFrags=function(t){t===void 0&&(t=0),this.fragmentTracker.removeFragmentsInRange(t,1/0,this.playlistType,!1,!0)},e.updateLevelTiming=function(t,i,r,a){var s,l=this,d=r.details;if(d){if(Object.keys(t.elementaryStreams).reduce(function(u,g){var m=t.elementaryStreams[g];if(m){var v=m.endPTS-m.startPTS;if(v<=0)return l.warn("Could not parse fragment "+t.sn+" "+g+" duration reliably ("+v+")"),u||!1;var y=a?0:sa(d,t,m.startPTS,m.endPTS,m.startDTS,m.endDTS);return l.hls.trigger(A.LEVEL_PTS_UPDATED,{details:d,level:r,drift:y,type:g,frag:t,start:m.startPTS,end:m.endPTS}),!0}return u},!1))r.fragmentError=0;else if(((s=this.transmuxer)==null?void 0:s.error)===null){var c=new Error("Found no media in fragment "+t.sn+" of level "+t.level+" resetting transmuxer to fallback to playlist timing");if(r.fragmentError===0&&(r.fragmentError++,t.gap=!0,this.fragmentTracker.removeFragment(t),this.fragmentTracker.fragBuffered(t,!0)),this.warn(c.message),this.hls.trigger(A.ERROR,{type:ne.MEDIA_ERROR,details:O.FRAG_PARSING_ERROR,fatal:!1,error:c,frag:t,reason:"Found no media in msn "+t.sn+' of level "'+r.url+'"'}),!this.hls)return;this.resetTransmuxer()}this.state=Oi,this.hls.trigger(A.FRAG_PARSED,{frag:t,part:i})}else this.warn("level.details undefined")},e.resetTransmuxer=function(){this.transmuxer&&(this.transmuxer.destroy(),this.transmuxer=null)},e.recoverWorkerError=function(t){var i,r,a;t.event==="demuxerWorker"&&(this.fragmentTracker.removeAllFragments(),this.resetTransmuxer(),this.resetStartWhenNotLoaded((i=(r=this.levelLastLoaded)!=null?r:(a=this.fragCurrent)==null?void 0:a.level)!=null?i:0),this.resetLoadingState())},D(n,[{key:"state",get:function(){return this._state},set:function(t){var i=this._state;i!==t&&(this._state=t,this.log(i+"->"+t))}}]),n}(Ps);function _a(){return self.SourceBuffer||self.WebKitSourceBuffer}function dt(o,n){return o===void 0&&(o=""),n===void 0&&(n=9e4),{type:o,id:-1,pid:-1,inputTimeScale:n,sequenceNumber:-1,samples:[],dropped:0}}var ka=function(){function o(){this._audioTrack=void 0,this._id3Track=void 0,this.frameIndex=0,this.cachedData=null,this.basePTS=null,this.initPTS=null,this.lastPTS=null}var n=o.prototype;return n.resetInitSegment=function(e,t,i,r){this._id3Track={type:"id3",id:3,pid:-1,inputTimeScale:9e4,sequenceNumber:0,samples:[],dropped:0}},n.resetTimeStamp=function(e){this.initPTS=e,this.resetContiguity()},n.resetContiguity=function(){this.basePTS=null,this.lastPTS=null,this.frameIndex=0},n.canParse=function(e,t){return!1},n.appendFrame=function(e,t,i){},n.demux=function(e,t){this.cachedData&&(e=Pt(this.cachedData,e),this.cachedData=null);var i,r=Ai(e,0),a=r?r.length:0,s=this._audioTrack,l=this._id3Track,d=r?function(m){for(var v=Mn(m),y=0;y0&&l.samples.push({pts:this.lastPTS,dts:this.lastPTS,data:r,type:ri,duration:Number.POSITIVE_INFINITY});a>>5}function Mi(o,n){return n+1=o.length)return!1;var t=Ir(o,n);if(t<=e)return!1;var i=n+t;return i===o.length||Mi(o,i)}return!1}function Ca(o,n,e,t,i){if(!o.samplerate){var r=function(a,s,l,d){var c,u,g,m,v=navigator.userAgent.toLowerCase(),y=d,_=[96e3,88200,64e3,48e3,44100,32e3,24e3,22050,16e3,12e3,11025,8e3,7350];c=1+((192&s[l+2])>>>6);var b=(60&s[l+2])>>>2;if(!(b>_.length-1))return g=(1&s[l+2])<<2,g|=(192&s[l+3])>>>6,R.log("manifest codec:"+d+", ADTS type:"+c+", samplingIndex:"+b),/firefox/i.test(v)?b>=6?(c=5,m=new Array(4),u=b-3):(c=2,m=new Array(2),u=b):v.indexOf("android")!==-1?(c=2,m=new Array(2),u=b):(c=5,m=new Array(4),d&&(d.indexOf("mp4a.40.29")!==-1||d.indexOf("mp4a.40.5")!==-1)||!d&&b>=6?u=b-3:((d&&d.indexOf("mp4a.40.2")!==-1&&(b>=6&&g===1||/vivaldi/i.test(v))||!d&&g===1)&&(c=2,m=new Array(2)),u=b)),m[0]=c<<3,m[0]|=(14&b)>>1,m[1]|=(1&b)<<7,m[1]|=g<<3,c===5&&(m[1]|=(14&u)>>1,m[2]=(1&u)<<7,m[2]|=8,m[3]=0),{config:m,samplerate:_[b],channelCount:g,codec:"mp4a.40."+c,manifestCodec:y};a.trigger(A.ERROR,{type:ne.MEDIA_ERROR,details:O.FRAG_PARSING_ERROR,fatal:!0,reason:"invalid ADTS sampling index:"+b})}(n,e,t,i);if(!r)return;o.config=r.config,o.samplerate=r.samplerate,o.channelCount=r.channelCount,o.codec=r.codec,o.manifestCodec=r.manifestCodec,R.log("parsed codec:"+o.codec+", rate:"+r.samplerate+", channels:"+r.channelCount)}}function Sa(o){return 9216e4/o}function La(o,n,e,t,i){var r,a=t+i*Sa(o.samplerate),s=function(v,y){var _=Ta(v,y);if(y+_<=v.length){var b=Ir(v,y)-_;if(b>0)return{headerLength:_,frameLength:b}}}(n,e);if(s){var l=s.frameLength,d=s.headerLength,c=d+l,u=Math.max(0,e+c-n.length);u?(r=new Uint8Array(c-d)).set(n.subarray(e+d,n.length),0):r=n.subarray(e+d,e+c);var g={unit:r,pts:a};return u||o.samples.push(g),{sample:g,length:c,missing:u}}var m=n.length-e;return(r=new Uint8Array(m)).set(n.subarray(e,n.length),0),{sample:{unit:r,pts:a},length:m,missing:-1}}var Ks=function(o){function n(t,i){var r;return(r=o.call(this)||this).observer=void 0,r.config=void 0,r.observer=t,r.config=i,r}q(n,o);var e=n.prototype;return e.resetInitSegment=function(t,i,r,a){o.prototype.resetInitSegment.call(this,t,i,r,a),this._audioTrack={container:"audio/adts",type:"audio",id:2,pid:-1,sequenceNumber:0,segmentCodec:"aac",samples:[],manifestCodec:i,duration:a,inputTimeScale:9e4,dropped:0}},n.probe=function(t){if(!t)return!1;for(var i=(Ai(t,0)||[]).length,r=t.length;i16384?e.subarray(0,16384):e,["moof"]).length>0},n.demux=function(e,t){this.timeOffset=t;var i=e,r=this.videoTrack,a=this.txtTrack;if(this.config.progressive){this.remainderData&&(i=Pt(this.remainderData,e));var s=function(d){var c={valid:null,remainder:null},u=ge(d,["moof"]);if(!u)return c;if(u.length<2)return c.remainder=d,c;var g=u[u.length-1];return c.valid=It(d,0,g.byteOffset-8),c.remainder=It(d,g.byteOffset-8),c}(i);this.remainderData=s.remainder,r.samples=s.valid||new Uint8Array}else r.samples=i;var l=this.extractID3Track(r,t);return a.samples=Hn(t,r),{videoTrack:r,audioTrack:this.audioTrack,id3Track:l,textTrack:this.txtTrack}},n.flush=function(){var e=this.timeOffset,t=this.videoTrack,i=this.txtTrack;t.samples=this.remainderData||new Uint8Array,this.remainderData=null;var r=this.extractID3Track(t,this.timeOffset);return i.samples=Hn(e,t),{videoTrack:t,audioTrack:dt(),id3Track:r,textTrack:dt()}},n.extractID3Track=function(e,t){var i=this.id3Track;if(e.samples.length){var r=ge(e.samples,["emsg"]);r&&r.forEach(function(a){var s=function(u){var g=u[0],m="",v="",y=0,_=0,b=0,E=0,S=0,C=0;if(g===0){for(;Se(u.subarray(C,C+1))!=="\0";)m+=Se(u.subarray(C,C+1)),C+=1;for(m+=Se(u.subarray(C,C+1)),C+=1;Se(u.subarray(C,C+1))!=="\0";)v+=Se(u.subarray(C,C+1)),C+=1;v+=Se(u.subarray(C,C+1)),C+=1,y=oe(u,12),_=oe(u,16),E=oe(u,20),S=oe(u,24),C=28}else if(g===1){y=oe(u,C+=4);var L=oe(u,C+=4),I=oe(u,C+=4);for(C+=4,b=Math.pow(2,32)*L+I,Number.isSafeInteger(b)||(b=Number.MAX_SAFE_INTEGER,R.warn("Presentation time exceeds safe integer limit and wrapped to max safe integer in parsing emsg box")),E=oe(u,C),S=oe(u,C+=4),C+=4;Se(u.subarray(C,C+1))!=="\0";)m+=Se(u.subarray(C,C+1)),C+=1;for(m+=Se(u.subarray(C,C+1)),C+=1;Se(u.subarray(C,C+1))!=="\0";)v+=Se(u.subarray(C,C+1)),C+=1;v+=Se(u.subarray(C,C+1)),C+=1}return{schemeIdUri:m,value:v,timeScale:y,presentationTime:b,presentationTimeDelta:_,eventDuration:E,id:S,payload:u.subarray(C,u.byteLength)}}(a);if(Vs.test(s.schemeIdUri)){var l=ie(s.presentationTime)?s.presentationTime/s.timeScale:t+s.presentationTimeDelta/s.timeScale,d=s.eventDuration===4294967295?Number.POSITIVE_INFINITY:s.eventDuration/s.timeScale;d<=.001&&(d=Number.POSITIVE_INFINITY);var c=s.payload;i.samples.push({data:c,len:c.byteLength,dts:l,pts:l,type:ni,duration:d})}})}return i},n.demuxSampleAes=function(e,t,i){return Promise.reject(new Error("The MP4 demuxer does not support SAMPLE-AES decryption"))},n.destroy=function(){},o}(),Fi=null,Ys=[32,64,96,128,160,192,224,256,288,320,352,384,416,448,32,48,56,64,80,96,112,128,160,192,224,256,320,384,32,40,48,56,64,80,96,112,128,160,192,224,256,320,32,48,56,64,80,96,112,128,144,160,176,192,224,256,8,16,24,32,40,48,56,64,80,96,112,128,144,160],js=[44100,48e3,32e3,22050,24e3,16e3,11025,12e3,8e3],qs=[[0,72,144,12],[0,0,0,0],[0,72,144,12],[0,144,144,12]],$s=[0,1,1,4];function Da(o,n,e,t,i){if(!(e+24>n.length)){var r=Ra(n,e);if(r&&e+r.frameLength<=n.length){var a=t+i*(9e4*r.samplesPerFrame/r.sampleRate),s={unit:n.subarray(e,e+r.frameLength),pts:a,dts:a};return o.config=[],o.channelCount=r.channelCount,o.samplerate=r.sampleRate,o.samples.push(s),{sample:s,length:r.frameLength,missing:0}}}}function Ra(o,n){var e=o[n+1]>>3&3,t=o[n+1]>>1&3,i=o[n+2]>>4&15,r=o[n+2]>>2&3;if(e!==1&&i!==0&&i!==15&&r!==3){var a=o[n+2]>>1&1,s=o[n+3]>>6,l=1e3*Ys[14*(e===3?3-t:t===3?3:4)+i-1],d=js[3*(e===3?0:e===2?1:2)+r],c=s===3?1:2,u=qs[e][t],g=$s[t],m=8*u*g,v=Math.floor(u*l/d+a)*g;if(Fi===null){var y=(navigator.userAgent||"").match(/Chrome\/(\d+)/i);Fi=y?parseInt(y[1]):0}return Fi&&Fi<=87&&t===2&&l>=224e3&&s===0&&(o[n+3]=128|o[n+3]),{sampleRate:d,channelCount:c,frameLength:v,samplesPerFrame:m}}}function Pr(o,n){return o[n]===255&&(224&o[n+1])==224&&(6&o[n+1])!=0}function Ia(o,n){return n+1e?(this.word<<=e,this.bitsAvailable-=e):(e-=this.bitsAvailable,e-=(t=e>>3)<<3,this.bytesAvailable-=t,this.loadWord(),this.word<<=e,this.bitsAvailable-=e)},n.readBits=function(e){var t=Math.min(this.bitsAvailable,e),i=this.word>>>32-t;if(e>32&&R.error("Cannot read more than 32 bits at a time"),this.bitsAvailable-=t,this.bitsAvailable>0)this.word<<=t;else{if(!(this.bytesAvailable>0))throw new Error("no bits available");this.loadWord()}return(t=e-t)>0&&this.bitsAvailable?i<>>e)return this.word<<=e,this.bitsAvailable-=e,e;return this.loadWord(),e+this.skipLZ()},n.skipUEG=function(){this.skipBits(1+this.skipLZ())},n.skipEG=function(){this.skipBits(1+this.skipLZ())},n.readUEG=function(){var e=this.skipLZ();return this.readBits(e+1)-1},n.readEG=function(){var e=this.readUEG();return 1&e?1+e>>>1:-1*(e>>>1)},n.readBoolean=function(){return this.readBits(1)===1},n.readUByte=function(){return this.readBits(8)},n.readUShort=function(){return this.readBits(16)},n.readUInt=function(){return this.readBits(32)},n.skipScalingList=function(e){for(var t=8,i=8,r=0;r=e.length)return void i();if(!(e[t].unit.length<32||(this.decryptAacSample(e,t,i),this.decrypter.isSync())))return}},n.getAvcEncryptedData=function(e){for(var t=16*Math.floor((e.length-48)/160)+16,i=new Int8Array(t),r=0,a=32;a=e.length)return void r();for(var a=e[t].units;!(i>=a.length);i++){var s=a[i];if(!(s.data.length<=48||s.type!==1&&s.type!==5||(this.decryptAvcSample(e,t,i,r,s),this.decrypter.isSync())))return}}},o}(),Ue=188,Xs=function(){function o(e,t,i){this.observer=void 0,this.config=void 0,this.typeSupported=void 0,this.sampleAes=null,this.pmtParsed=!1,this.audioCodec=void 0,this.videoCodec=void 0,this._duration=0,this._pmtId=-1,this._avcTrack=void 0,this._audioTrack=void 0,this._id3Track=void 0,this._txtTrack=void 0,this.aacOverFlow=null,this.avcSample=null,this.remainderData=null,this.observer=e,this.config=t,this.typeSupported=i}o.probe=function(e){var t=o.syncOffset(e);return t>0&&R.warn("MPEG2-TS detected but first sync word found @ offset "+t),t!==-1},o.syncOffset=function(e){for(var t=e.length,i=Math.min(940,e.length-Ue)+1,r=0;r1&&(s===0&&l>2||d+Ue>i))return s}r++}return-1},o.createTrack=function(e,t){return{container:e==="video"||e==="audio"?"video/mp2t":void 0,type:e,id:Fn[e],pid:-1,inputTimeScale:9e4,sequenceNumber:0,samples:[],dropped:0,duration:e==="audio"?t:void 0}};var n=o.prototype;return n.resetInitSegment=function(e,t,i,r){this.pmtParsed=!1,this._pmtId=-1,this._avcTrack=o.createTrack("video"),this._audioTrack=o.createTrack("audio",r),this._id3Track=o.createTrack("id3"),this._txtTrack=o.createTrack("text"),this._audioTrack.segmentCodec="aac",this.aacOverFlow=null,this.avcSample=null,this.remainderData=null,this.audioCodec=t,this.videoCodec=i,this._duration=r},n.resetTimeStamp=function(){},n.resetContiguity=function(){var e=this._audioTrack,t=this._avcTrack,i=this._id3Track;e&&(e.pesData=null),t&&(t.pesData=null),i&&(i.pesData=null),this.aacOverFlow=null,this.avcSample=null,this.remainderData=null},n.demux=function(e,t,i,r){var a;i===void 0&&(i=!1),r===void 0&&(r=!1),i||(this.sampleAes=null);var s=this._avcTrack,l=this._audioTrack,d=this._id3Track,c=this._txtTrack,u=s.pid,g=s.pesData,m=l.pid,v=d.pid,y=l.pesData,_=d.pesData,b=null,E=this.pmtParsed,S=this._pmtId,C=e.length;if(this.remainderData&&(C=(e=Pt(this.remainderData,e)).length,this.remainderData=null),C>4>1){if((B=P+5+e[P+4])===P+Ue)continue}else B=P+4;switch(M){case u:N&&(g&&(a=$t(g))&&this.parseAVCPES(s,c,a,!1),g={data:[],size:0}),g&&(g.data.push(e.subarray(B,P+Ue)),g.size+=P+Ue-B);break;case m:if(N){if(y&&(a=$t(y)))switch(l.segmentCodec){case"aac":this.parseAACPES(l,a);break;case"mp3":this.parseMPEGPES(l,a)}y={data:[],size:0}}y&&(y.data.push(e.subarray(B,P+Ue)),y.size+=P+Ue-B);break;case v:N&&(_&&(a=$t(_))&&this.parseID3PES(d,a),_={data:[],size:0}),_&&(_.data.push(e.subarray(B,P+Ue)),_.size+=P+Ue-B);break;case 0:N&&(B+=e[B]+1),S=this._pmtId=Js(e,B);break;case S:N&&(B+=e[B]+1);var Y=Zs(e,B,this.typeSupported,i);(u=Y.avc)>0&&(s.pid=u),(m=Y.audio)>0&&(l.pid=m,l.segmentCodec=Y.segmentCodec),(v=Y.id3)>0&&(d.pid=v),b===null||E||(R.warn("MPEG-TS PMT found at "+P+" after unknown PID '"+b+"'. Backtracking to sync byte @"+L+" to parse all TS packets."),b=null,P=L-188),E=this.pmtParsed=!0;break;case 17:case 8191:break;default:b=M}}else I++;if(I>0){var K=new Error("Found "+I+" TS packet/s that do not start with 0x47");this.observer.emit(A.ERROR,A.ERROR,{type:ne.MEDIA_ERROR,details:O.FRAG_PARSING_ERROR,fatal:!1,error:K,reason:K.message})}s.pesData=g,l.pesData=y,d.pesData=_;var Q={audioTrack:l,videoTrack:s,id3Track:d,textTrack:c};return r&&this.extractRemainingSamples(Q),Q},n.flush=function(){var e,t=this.remainderData;return this.remainderData=null,e=t?this.demux(t,-1,!1,!0):{videoTrack:this._avcTrack,audioTrack:this._audioTrack,id3Track:this._id3Track,textTrack:this._txtTrack},this.extractRemainingSamples(e),this.sampleAes?this.decrypt(e,this.sampleAes):e},n.extractRemainingSamples=function(e){var t,i=e.audioTrack,r=e.videoTrack,a=e.id3Track,s=e.textTrack,l=r.pesData,d=i.pesData,c=a.pesData;if(l&&(t=$t(l))?(this.parseAVCPES(r,s,t,!0),r.pesData=null):r.pesData=l,d&&(t=$t(d))){switch(i.segmentCodec){case"aac":this.parseAACPES(i,t);break;case"mp3":this.parseMPEGPES(i,t)}i.pesData=null}else d!=null&&d.size&&R.log("last AAC PES packet truncated,might overlap between fragments"),i.pesData=d;c&&(t=$t(c))?(this.parseID3PES(a,t),a.pesData=null):a.pesData=c},n.demuxSampleAes=function(e,t,i){var r=this.demux(e,i,!0,!this.config.progressive),a=this.sampleAes=new Ws(this.observer,this.config,t);return this.decrypt(r,a)},n.decrypt=function(e,t){return new Promise(function(i){var r=e.audioTrack,a=e.videoTrack;r.samples&&r.segmentCodec==="aac"?t.decryptAacSamples(r.samples,0,function(){a.samples?t.decryptAvcSamples(a.samples,0,0,function(){i(e)}):i(e)}):a.samples&&t.decryptAvcSamples(a.samples,0,0,function(){i(e)})})},n.destroy=function(){this._duration=0},n.parseAVCPES=function(e,t,i,r){var a,s=this,l=this.parseAVCNALu(e,i.data),d=this.avcSample,c=!1;i.data=null,d&&l.length&&!e.audFound&&(ui(d,e),d=this.avcSample=Bi(!1,i.pts,i.dts,"")),l.forEach(function(u){var g;switch(u.type){case 1:var m=!1;a=!0;var v,y=u.data;if(c&&y.length>4){var _=new Pa(y).readSliceType();_!==2&&_!==4&&_!==7&&_!==9||(m=!0)}m&&(v=d)!=null&&v.frame&&!d.key&&(ui(d,e),d=s.avcSample=null),d||(d=s.avcSample=Bi(!0,i.pts,i.dts,"")),d.frame=!0,d.key=m;break;case 5:a=!0,(g=d)!=null&&g.frame&&!d.key&&(ui(d,e),d=s.avcSample=null),d||(d=s.avcSample=Bi(!0,i.pts,i.dts,"")),d.key=!0,d.frame=!0;break;case 6:a=!0,Kn(u.data,1,i.pts,t.samples);break;case 7:if(a=!0,c=!0,!e.sps){var b=u.data,E=new Pa(b).readSPS();e.width=E.width,e.height=E.height,e.pixelRatio=E.pixelRatio,e.sps=[b],e.duration=s._duration;for(var S=b.subarray(1,4),C="avc1.",L=0;L<3;L++){var I=S[L].toString(16);I.length<2&&(I="0"+I),C+=I}e.codec=C}break;case 8:a=!0,e.pps||(e.pps=[u.data]);break;case 9:a=!1,e.audFound=!0,d&&ui(d,e),d=s.avcSample=Bi(!1,i.pts,i.dts,"");break;case 12:a=!0;break;default:a=!1,d&&(d.debug+="unknown NAL "+u.type+" ")}d&&a&&d.units.push(u)}),r&&d&&(ui(d,e),this.avcSample=null)},n.getLastNalUnit=function(e){var t,i,r=this.avcSample;if(r&&r.units.length!==0||(r=e[e.length-1]),(t=r)!=null&&t.units){var a=r.units;i=a[a.length-1]}return i},n.parseAVCNALu=function(e,t){var i,r,a=t.byteLength,s=e.naluState||0,l=s,d=[],c=0,u=-1,g=0;for(s===-1&&(u=0,g=31&t[0],s=0,c=1);c=0){var m={data:t.subarray(u,c-s-1),type:g};d.push(m)}else{var v=this.getLastNalUnit(e.samples);if(v&&(l&&c<=4-l&&v.state&&(v.data=v.data.subarray(0,v.data.byteLength-l)),(r=c-s-1)>0)){var y=new Uint8Array(v.data.byteLength+r);y.set(v.data,0),y.set(t.subarray(0,r),v.data.byteLength),v.data=y,v.state=0}}c=0&&s>=0){var _={data:t.subarray(u,a),type:g,state:s};d.push(_)}if(d.length===0){var b=this.getLastNalUnit(e.samples);if(b){var E=new Uint8Array(b.data.byteLength+t.byteLength);E.set(b.data,0),E.set(t,b.data.byteLength),b.data=E}}return e.naluState=s,d},n.parseAACPES=function(e,t){var i,r,a,s=0,l=this.aacOverFlow,d=t.data;if(l){this.aacOverFlow=null;var c=l.missing,u=l.sample.unit.byteLength;if(c===-1){var g=new Uint8Array(u+d.byteLength);g.set(l.sample.unit,0),g.set(d,u),d=g}else{var m=u-c;l.sample.unit.set(d.subarray(0,c),m),e.samples.push(l.sample),s=l.missing}}for(i=s,r=d.length;i1;){var l=new Uint8Array(s[0].length+s[1].length);l.set(s[0]),l.set(s[1],s[0].length),s[0]=l,s.splice(1,1)}if(((n=s[0])[0]<<16)+(n[1]<<8)+n[2]===1){if((e=(n[4]<<8)+n[5])&&e>o.size-6)return null;var d=n[7];192&d&&(i=536870912*(14&n[9])+4194304*(255&n[10])+16384*(254&n[11])+128*(255&n[12])+(254&n[13])/2,64&d?i-(r=536870912*(14&n[14])+4194304*(255&n[15])+16384*(254&n[16])+128*(255&n[17])+(254&n[18])/2)>54e5&&(R.warn(Math.round((i-r)/9e4)+"s delta between PTS and DTS, align them"),i=r):r=i);var c=(t=n[8])+9;if(o.size<=c)return null;o.size-=c;for(var u=new Uint8Array(o.size),g=0,m=s.length;gv){c-=v;continue}n=n.subarray(c),v-=c,c=0}u.set(n,a),a+=v}return e&&(e-=t+3),{data:u,pts:i,dts:r,len:e}}return null}function ui(o,n){if(o.units.length&&o.frame){if(o.pts===void 0){var e=n.samples,t=e.length;if(!t)return void n.dropped++;var i=e[t-1];o.pts=i.pts,o.dts=i.dts}n.samples.push(o)}o.debug.length&&R.log(o.pts+"/"+o.dts+":"+o.debug)}var el=function(o){function n(){return o.apply(this,arguments)||this}q(n,o);var e=n.prototype;return e.resetInitSegment=function(t,i,r,a){o.prototype.resetInitSegment.call(this,t,i,r,a),this._audioTrack={container:"audio/mpeg",type:"audio",id:2,pid:-1,sequenceNumber:0,segmentCodec:"mp3",samples:[],manifestCodec:i,duration:a,inputTimeScale:9e4,dropped:0}},n.probe=function(t){if(!t)return!1;for(var i=(Ai(t,0)||[]).length,r=t.length;i1?t-1:0),r=1;r>24&255,l[1]=e>>16&255,l[2]=e>>8&255,l[3]=255&e,l.set(n,4),a=0,e=8;a>24&255,n>>16&255,n>>8&255,255&n,t>>24,t>>16&255,t>>8&255,255&t,i>>24,i>>16&255,i>>8&255,255&i,85,196,0,0]))},o.mdia=function(n){return o.box(o.types.mdia,o.mdhd(n.timescale,n.duration),o.hdlr(n.type),o.minf(n))},o.mfhd=function(n){return o.box(o.types.mfhd,new Uint8Array([0,0,0,0,n>>24,n>>16&255,n>>8&255,255&n]))},o.minf=function(n){return n.type==="audio"?o.box(o.types.minf,o.box(o.types.smhd,o.SMHD),o.DINF,o.stbl(n)):o.box(o.types.minf,o.box(o.types.vmhd,o.VMHD),o.DINF,o.stbl(n))},o.moof=function(n,e,t){return o.box(o.types.moof,o.mfhd(n),o.traf(t,e))},o.moov=function(n){for(var e=n.length,t=[];e--;)t[e]=o.trak(n[e]);return o.box.apply(null,[o.types.moov,o.mvhd(n[0].timescale,n[0].duration)].concat(t).concat(o.mvex(n)))},o.mvex=function(n){for(var e=n.length,t=[];e--;)t[e]=o.trex(n[e]);return o.box.apply(null,[o.types.mvex].concat(t))},o.mvhd=function(n,e){e*=n;var t=Math.floor(e/(xt+1)),i=Math.floor(e%(xt+1)),r=new Uint8Array([1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,3,n>>24&255,n>>16&255,n>>8&255,255&n,t>>24,t>>16&255,t>>8&255,255&t,i>>24,i>>16&255,i>>8&255,255&i,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]);return o.box(o.types.mvhd,r)},o.sdtp=function(n){var e,t,i=n.samples||[],r=new Uint8Array(4+i.length);for(e=0;e>>8&255),r.push(255&i),r=r.concat(Array.prototype.slice.call(t));for(e=0;e>>8&255),a.push(255&i),a=a.concat(Array.prototype.slice.call(t));var s=o.box(o.types.avcC,new Uint8Array([1,r[3],r[4],r[5],255,224|n.sps.length].concat(r).concat([n.pps.length]).concat(a))),l=n.width,d=n.height,c=n.pixelRatio[0],u=n.pixelRatio[1];return o.box(o.types.avc1,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,l>>8&255,255&l,d>>8&255,255&d,0,72,0,0,0,72,0,0,0,0,0,0,0,1,18,100,97,105,108,121,109,111,116,105,111,110,47,104,108,115,46,106,115,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,17,17]),s,o.box(o.types.btrt,new Uint8Array([0,28,156,128,0,45,198,192,0,45,198,192])),o.box(o.types.pasp,new Uint8Array([c>>24,c>>16&255,c>>8&255,255&c,u>>24,u>>16&255,u>>8&255,255&u])))},o.esds=function(n){var e=n.config.length;return new Uint8Array([0,0,0,0,3,23+e,0,1,0,4,15+e,64,21,0,0,0,0,0,0,0,0,0,0,0,5].concat([e]).concat(n.config).concat([6,1,2]))},o.mp4a=function(n){var e=n.samplerate;return o.box(o.types.mp4a,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,n.channelCount,0,16,0,0,0,0,e>>8&255,255&e,0,0]),o.box(o.types.esds,o.esds(n)))},o.mp3=function(n){var e=n.samplerate;return o.box(o.types[".mp3"],new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,n.channelCount,0,16,0,0,0,0,e>>8&255,255&e,0,0]))},o.stsd=function(n){return n.type==="audio"?n.segmentCodec==="mp3"&&n.codec==="mp3"?o.box(o.types.stsd,o.STSD,o.mp3(n)):o.box(o.types.stsd,o.STSD,o.mp4a(n)):o.box(o.types.stsd,o.STSD,o.avc1(n))},o.tkhd=function(n){var e=n.id,t=n.duration*n.timescale,i=n.width,r=n.height,a=Math.floor(t/(xt+1)),s=Math.floor(t%(xt+1));return o.box(o.types.tkhd,new Uint8Array([1,0,0,7,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,3,e>>24&255,e>>16&255,e>>8&255,255&e,0,0,0,0,a>>24,a>>16&255,a>>8&255,255&a,s>>24,s>>16&255,s>>8&255,255&s,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,i>>8&255,255&i,0,0,r>>8&255,255&r,0,0]))},o.traf=function(n,e){var t=o.sdtp(n),i=n.id,r=Math.floor(e/(xt+1)),a=Math.floor(e%(xt+1));return o.box(o.types.traf,o.box(o.types.tfhd,new Uint8Array([0,0,0,0,i>>24,i>>16&255,i>>8&255,255&i])),o.box(o.types.tfdt,new Uint8Array([1,0,0,0,r>>24,r>>16&255,r>>8&255,255&r,a>>24,a>>16&255,a>>8&255,255&a])),o.trun(n,t.length+16+20+8+16+8+8),t)},o.trak=function(n){return n.duration=n.duration||4294967295,o.box(o.types.trak,o.tkhd(n),o.mdia(n))},o.trex=function(n){var e=n.id;return o.box(o.types.trex,new Uint8Array([0,0,0,0,e>>24,e>>16&255,e>>8&255,255&e,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]))},o.trun=function(n,e){var t,i,r,a,s,l,d=n.samples||[],c=d.length,u=12+16*c,g=new Uint8Array(u);for(e+=8+u,g.set([n.type==="video"?1:0,0,15,1,c>>>24&255,c>>>16&255,c>>>8&255,255&c,e>>>24&255,e>>>16&255,e>>>8&255,255&e],0),t=0;t>>24&255,r>>>16&255,r>>>8&255,255&r,a>>>24&255,a>>>16&255,a>>>8&255,255&a,s.isLeading<<2|s.dependsOn,s.isDependedOn<<6|s.hasRedundancy<<4|s.paddingValue<<1|s.isNonSync,61440&s.degradPrio,15&s.degradPrio,l>>>24&255,l>>>16&255,l>>>8&255,255&l],12+16*t);return o.box(o.types.trun,g)},o.initSegment=function(n){o.types||o.init();var e=o.moov(n),t=new Uint8Array(o.FTYP.byteLength+e.byteLength);return t.set(o.FTYP),t.set(e,o.FTYP.byteLength),t},o}();function Mr(o,n,e,t){e===void 0&&(e=1),t===void 0&&(t=!1);var i=o*n*e;return t?Math.round(i):i}function fi(o,n){return Mr(o,1e3,1/9e4,n)}Le.types=void 0,Le.HDLR_TYPES=void 0,Le.STTS=void 0,Le.STSC=void 0,Le.STCO=void 0,Le.STSZ=void 0,Le.VMHD=void 0,Le.SMHD=void 0,Le.STSD=void 0,Le.FTYP=void 0,Le.DINF=void 0;var Ni=null,Fr=null,Br=function(){function o(e,t,i,r){if(this.observer=void 0,this.config=void 0,this.typeSupported=void 0,this.ISGenerated=!1,this._initPTS=null,this._initDTS=null,this.nextAvcDts=null,this.nextAudioPts=null,this.videoSampleDuration=null,this.isAudioContiguous=!1,this.isVideoContiguous=!1,this.observer=e,this.config=t,this.typeSupported=i,this.ISGenerated=!1,Ni===null){var a=(navigator.userAgent||"").match(/Chrome\/(\d+)/i);Ni=a?parseInt(a[1]):0}if(Fr===null){var s=navigator.userAgent.match(/Safari\/(\d+)/i);Fr=s?parseInt(s[1]):0}}var n=o.prototype;return n.destroy=function(){},n.resetTimeStamp=function(e){R.log("[mp4-remuxer]: initPTS & initDTS reset"),this._initPTS=this._initDTS=e},n.resetNextTimestamp=function(){R.log("[mp4-remuxer]: reset next timestamp"),this.isVideoContiguous=!1,this.isAudioContiguous=!1},n.resetInitSegment=function(){R.log("[mp4-remuxer]: ISGenerated flag reset"),this.ISGenerated=!1},n.getVideoStartPts=function(e){var t=!1,i=e.reduce(function(r,a){var s=a.pts-r;return s<-4294967296?(t=!0,Qe(r,a.pts)):s>0?r:a.pts},e[0].pts);return t&&R.debug("PTS rollover detected"),i},n.remux=function(e,t,i,r,a,s,l,d){var c,u,g,m,v,y,_=a,b=a,E=e.pid>-1,S=t.pid>-1,C=t.samples.length,L=e.samples.length>0,I=l&&C>0||C>1;if((!E||L)&&(!S||I)||this.ISGenerated||l){this.ISGenerated||(g=this.generateIS(e,t,a,s));var P,N=this.isVideoContiguous,M=-1;if(I&&(M=function(re){for(var W=0;W0){R.warn("[mp4-remuxer]: Dropped "+M+" out of "+C+" video samples due to a missing keyframe");var B=this.getVideoStartPts(t.samples);t.samples=t.samples.slice(M),t.dropped+=M,P=b+=(t.samples[0].pts-B)/t.inputTimeScale}else M===-1&&(R.warn("[mp4-remuxer]: No keyframe found out of "+C+" video samples"),y=!1);if(this.ISGenerated){if(L&&I){var Y=this.getVideoStartPts(t.samples),K=(Qe(e.samples[0].pts,Y)-Y)/t.inputTimeScale;_+=Math.max(0,K),b+=Math.max(0,-K)}if(L){if(e.samplerate||(R.warn("[mp4-remuxer]: regenerate InitSegment as audio detected"),g=this.generateIS(e,t,a,s)),u=this.remuxAudio(e,_,this.isAudioContiguous,s,S||I||d===lt?b:void 0),I){var Q=u?u.endPTS-u.startPTS:0;t.inputTimeScale||(R.warn("[mp4-remuxer]: regenerate InitSegment as video detected"),g=this.generateIS(e,t,a,s)),c=this.remuxVideo(t,b,N,Q)}}else I&&(c=this.remuxVideo(t,b,N,0));c&&(c.firstKeyFrame=M,c.independent=M!==-1,c.firstKeyFramePTS=P)}}return this.ISGenerated&&this._initPTS&&this._initDTS&&(i.samples.length&&(v=Ma(i,a,this._initPTS,this._initDTS)),r.samples.length&&(m=Fa(r,a,this._initPTS))),{audio:u,video:c,initSegment:g,independent:y,text:m,id3:v}},n.generateIS=function(e,t,i,r){var a,s,l,d=e.samples,c=t.samples,u=this.typeSupported,g={},m=this._initPTS,v=!m||r,y="audio/mp4";if(v&&(a=s=1/0),e.config&&d.length&&(e.timescale=e.samplerate,e.segmentCodec==="mp3"&&(u.mpeg?(y="audio/mpeg",e.codec=""):u.mp3&&(e.codec="mp3")),g.audio={id:"audio",container:y,codec:e.codec,initSegment:e.segmentCodec==="mp3"&&u.mpeg?new Uint8Array(0):Le.initSegment([e]),metadata:{channelCount:e.channelCount}},v&&(l=e.inputTimeScale,m&&l===m.timescale?v=!1:a=s=d[0].pts-Math.round(l*i))),t.sps&&t.pps&&c.length&&(t.timescale=t.inputTimeScale,g.video={id:"main",container:"video/mp4",codec:t.codec,initSegment:Le.initSegment([t]),metadata:{width:t.width,height:t.height}},v))if(l=t.inputTimeScale,m&&l===m.timescale)v=!1;else{var _=this.getVideoStartPts(c),b=Math.round(l*i);s=Math.min(s,Qe(c[0].dts,_)-b),a=Math.min(a,_-b)}if(Object.keys(g).length)return this.ISGenerated=!0,v?(this._initPTS={baseTime:a,timescale:l},this._initDTS={baseTime:s,timescale:l}):a=l=void 0,{tracks:g,initPTS:a,timescale:l}},n.remuxVideo=function(e,t,i,r){var a,s,l=e.inputTimeScale,d=e.samples,c=[],u=d.length,g=this._initPTS,m=this.nextAvcDts,v=8,y=this.videoSampleDuration,_=Number.POSITIVE_INFINITY,b=Number.NEGATIVE_INFINITY,E=!1;i&&m!==null||(m=t*l-(d[0].pts-Qe(d[0].dts,d[0].pts)));for(var S=g.baseTime*l/g.timescale,C=0;C0?C-1:C].dts&&(E=!0)}E&&d.sort(function(Yi,yo){var Jl=Yi.dts-yo.dts,Zl=Yi.pts-yo.pts;return Jl||Zl}),a=d[0].dts;var I=(s=d[d.length-1].dts)-a,P=I?Math.round(I/(u-1)):y||e.inputTimeScale/30;if(i){var N=a-m,M=N>P,B=N<-1;if((M||B)&&(M?R.warn("AVC: "+fi(N,!0)+" ms ("+N+"dts) hole between fragments detected, filling it"):R.warn("AVC: "+fi(-N,!0)+" ms ("+N+"dts) overlapping between fragments detected"),!B||m>=d[0].pts)){a=m;var Y=d[0].pts-N;d[0].dts=a,d[0].pts=Y,R.log("Video: First PTS/DTS adjusted: "+fi(Y,!0)+"/"+fi(a,!0)+", delta: "+fi(N,!0)+" ms")}}a=Math.max(0,a);for(var K=0,Q=0,re=0;re0?De.dts-d[xe-1].dts:P;if(Ut=xe>0?De.pts-d[xe-1].pts:P,mi.stretchShortVideoTrack&&this.nextAudioPts!==null){var ql=Math.floor(mi.maxBufferHole*l),nn=(r?_+r*l:this.nextAudioPts)-De.pts;nn>ql?((y=nn-wt)<0?y=wt:Ge=!0,R.log("[mp4-remuxer]: It is approximately "+nn/90+" ms to the next segment; using duration "+y/90+" ms for the last video frame.")):y=wt}else y=wt}var $l=Math.round(De.pts-De.dts);ke=Math.min(ke,y),Xe=Math.max(Xe,y),et=Math.min(et,Ut),Je=Math.max(Je,Ut),c.push(new Ba(De.key,y,Tt,$l))}if(c.length){if(Ni){if(Ni<70){var mo=c[0].flags;mo.dependsOn=2,mo.isNonSync=0}}else if(Fr&&Je-et0&&(r&&Math.abs(E-b)<9e3||Math.abs(Qe(y[0].pts-S,E)-b)<20*c),y.forEach(function(Ye){Ye.pts=Qe(Ye.pts-S,E)}),!i||b<0){if(y=y.filter(function(Ye){return Ye.pts>=0}),!y.length)return;b=a===0?0:r&&!v?Math.max(0,E):y[0].pts}if(e.segmentCodec==="aac")for(var C=this.config.maxAudioFramesDrift,L=0,I=b;L=C*c&&B<1e4&&v){var Y=Math.round(M/c);(I=N-Y*c)<0&&(Y--,I+=c),L===0&&(this.nextAudioPts=b=I),R.warn("[mp4-remuxer]: Injecting "+Y+" audio frame @ "+(I/s).toFixed(3)+"s due to "+Math.round(1e3*M/s)+" ms gap.");for(var K=0;K0))return;Z+=_;try{W=new Uint8Array(Z)}catch(Ye){return void this.observer.emit(A.ERROR,A.ERROR,{type:ne.MUX_ERROR,details:O.REMUX_ALLOC_ERROR,fatal:!1,error:Ye,bytes:Z,reason:"fail allocating audio mdat "+Z})}g||(new DataView(W.buffer).setUint32(0,Z),W.set(Le.types.mdat,4))}W.set(Ge,_);var et=Ge.byteLength;_+=et,m.push(new Ba(!0,d,et,0)),ee=ke}var Xe=m.length;if(Xe){var Je=m[m.length-1];this.nextAudioPts=b=ee+l*Je.duration;var xe=g?new Uint8Array(0):Le.moof(e.sequenceNumber++,J/l,F({},e,{samples:m}));e.samples=[];var De=J/s,ct=b/s,Tt={data1:xe,data2:W,startPTS:De,endPTS:ct,startDTS:De,endDTS:ct,type:"audio",hasAudio:!0,hasVideo:!1,nb:Xe};return this.isAudioContiguous=!0,Tt}},n.remuxEmptyAudio=function(e,t,i,r){var a=e.inputTimeScale,s=a/(e.samplerate?e.samplerate:a),l=this.nextAudioPts,d=this._initDTS,c=9e4*d.baseTime/d.timescale,u=(l!==null?l:r.startDTS*a)+c,g=r.endDTS*a+c,m=1024*s,v=Math.ceil((g-u)/m),y=Oa.getSilentFrame(e.manifestCodec||e.codec,e.channelCount);if(R.warn("[mp4-remuxer]: remux empty Audio"),y){for(var _=[],b=0;b4294967296;)o+=e;return o}function Ma(o,n,e,t){var i=o.samples.length;if(i){for(var r=o.inputTimeScale,a=0;a0;g||(u=ge(c,["encv"])),u.forEach(function(m){ge(g?m.subarray(28):m.subarray(78),["sinf"]).forEach(function(v){var y=Gn(v);if(y){var _=y.subarray(8,24);_.some(function(b){return b!==0})||(R.log("[eme] Patching keyId in 'enc"+(g?"a":"v")+">sinf>>tenc' box: "+ot(_)+" -> "+ot(l)),y.set(l,8))}})})}),a}(e,r)),this.emitInitSegment=!0},n.generateInitSegment=function(e){var t=this.audioCodec,i=this.videoCodec;if(e==null||!e.byteLength)return this.initTracks=void 0,void(this.initData=void 0);var r=this.initData=Un(e);t||(t=Na(r.audio,Be)),i||(i=Na(r.video,Ze));var a={};r.audio&&r.video?a.audiovideo={container:"video/mp4",codec:t+","+i,initSegment:e,id:"main"}:r.audio?a.audio={container:"audio/mp4",codec:t,initSegment:e,id:"audio"}:r.video?a.video={container:"video/mp4",codec:i,initSegment:e,id:"main"}:R.warn("[passthrough-remuxer.ts]: initSegment does not contain moov or trak boxes."),this.initTracks=a},n.remux=function(e,t,i,r,a,s){var l,d,c=this.initPTS,u=this.lastEndTime,g={audio:void 0,video:void 0,text:r,id3:i,initSegment:void 0};ie(u)||(u=this.lastEndTime=a||0);var m=t.samples;if(m==null||!m.length)return g;var v={initPTS:void 0,timescale:1},y=this.initData;if((l=y)!=null&&l.length||(this.generateInitSegment(m),y=this.initData),(d=y)==null||!d.length)return R.warn("[passthrough-remuxer.ts]: Failed to generate initSegment."),g;this.emitInitSegment&&(v.tracks=this.initTracks,this.emitInitSegment=!1);var _=function(M,B){for(var Y=0,K=0,Q=0,re=ge(M,["moof","traf"]),W=0;WQ}(c,E,a,_)||v.timescale!==c.timescale&&s)&&(v.initPTS=E-a,c&&c.timescale===1&&R.warn("Adjusting initPTS by "+(v.initPTS-c.baseTime)),this.initPTS=c={baseTime:v.initPTS,timescale:1});var S=e?E-c.baseTime/c.timescale:u,C=S+_;(function(M,B,Y){ge(B,["moof","traf"]).forEach(function(K){ge(K,["tfhd"]).forEach(function(Q){var re=oe(Q,4),W=M[re];if(W){var J=W.timescale||9e4;ge(K,["tfdt"]).forEach(function(ee){var Z=ee[0],ae=oe(ee,4);if(Z===0)ae-=Y*J,cr(ee,4,ae=Math.max(ae,0));else{ae*=Math.pow(2,32),ae+=oe(ee,8),ae-=Y*J,ae=Math.max(ae,0);var he=Math.floor(ae/(ki+1)),fe=Math.floor(ae%(ki+1));cr(ee,4,he),cr(ee,8,fe)}})}})})})(y,m,c.baseTime/c.timescale),_>0?this.lastEndTime=C:(R.warn("Duration parsed from mp4 should be greater than zero"),this.resetNextTimestamp());var L=!!y.audio,I=!!y.video,P="";L&&(P+="audio"),I&&(P+="video");var N={data1:m,startPTS:S,startDTS:S,endPTS:C,endDTS:C,type:P,hasAudio:L,hasVideo:I,nb:1,dropped:0};return g.audio=N.type==="audio"?N:void 0,g.video=N.type!=="audio"?N:void 0,g.initSegment=v,g.id3=Ma(i,a,c,c),r.samples.length&&(g.text=Fa(r,a,c)),g},o}();function Na(o,n){var e=o==null?void 0:o.codec;return e&&e.length>4?e:e==="hvc1"||e==="hev1"?"hvc1.1.6.L120.90":e==="av01"?"av01.0.04M.08":e==="avc1"||n===Ze?"avc1.42e01e":"mp4a.40.5"}try{bt=self.performance.now.bind(self.performance)}catch{R.debug("Unable to use Performance API on this environment"),bt=typeof self<"u"&&self.Date.now}var Nr=[{demux:zs,remux:il},{demux:Xs,remux:Br},{demux:Ks,remux:Br},{demux:el,remux:Br}],Ur=function(){function o(e,t,i,r,a){this.async=!1,this.observer=void 0,this.typeSupported=void 0,this.config=void 0,this.vendor=void 0,this.id=void 0,this.demuxer=void 0,this.remuxer=void 0,this.decrypter=void 0,this.probe=void 0,this.decryptionPromise=null,this.transmuxConfig=void 0,this.currentTransmuxState=void 0,this.observer=e,this.typeSupported=t,this.config=i,this.vendor=r,this.id=a}var n=o.prototype;return n.configure=function(e){this.transmuxConfig=e,this.decrypter&&this.decrypter.reset()},n.push=function(e,t,i,r){var a=this,s=i.transmuxing;s.executeStart=bt();var l=new Uint8Array(e),d=this.currentTransmuxState,c=this.transmuxConfig;r&&(this.currentTransmuxState=r);var u=r||d,g=u.contiguous,m=u.discontinuity,v=u.trackSwitch,y=u.accurateTimeOffset,_=u.timeOffset,b=u.initSegmentChange,E=c.audioCodec,S=c.videoCodec,C=c.defaultInitPts,L=c.duration,I=c.initSegmentData,P=function(re,W){var J=null;return re.byteLength>0&&W!=null&&W.key!=null&&W.iv!==null&&W.method!=null&&(J=W),J}(l,t);if(P&&P.method==="AES-128"){var N=this.getDecrypter();if(!N.isSync())return this.decryptionPromise=N.webCryptoDecrypt(l,P.key.buffer,P.iv.buffer).then(function(re){var W=a.push(re,null,i);return a.decryptionPromise=null,W}),this.decryptionPromise;var M=N.softwareDecrypt(l,P.key.buffer,P.iv.buffer);if(i.part>-1&&(M=N.flush()),!M)return s.executeEnd=bt(),Gr(i);l=new Uint8Array(M)}var B=this.needsProbing(m,v);if(B){var Y=this.configureTransmuxer(l);if(Y)return R.warn("[transmuxer] "+Y.message),this.observer.emit(A.ERROR,A.ERROR,{type:ne.MEDIA_ERROR,details:O.FRAG_PARSING_ERROR,fatal:!1,error:Y,reason:Y.message}),s.executeEnd=bt(),Gr(i)}(m||v||b||B)&&this.resetInitSegment(I,E,S,L,t),(m||b||B)&&this.resetInitialTimestamp(C),g||this.resetContiguity();var K=this.transmux(l,P,_,y,i),Q=this.currentTransmuxState;return Q.contiguous=!0,Q.discontinuity=!1,Q.trackSwitch=!1,s.executeEnd=bt(),K},n.flush=function(e){var t=this,i=e.transmuxing;i.executeStart=bt();var r=this.decrypter,a=this.currentTransmuxState,s=this.decryptionPromise;if(s)return s.then(function(){return t.flush(e)});var l=[],d=a.timeOffset;if(r){var c=r.flush();c&&l.push(this.push(c,null,e))}var u=this.demuxer,g=this.remuxer;if(!u||!g)return i.executeEnd=bt(),[Gr(e)];var m=u.flush(d);return Ft(m)?m.then(function(v){return t.flushRemux(l,v,e),l}):(this.flushRemux(l,m,e),l)},n.flushRemux=function(e,t,i){var r=t.audioTrack,a=t.videoTrack,s=t.id3Track,l=t.textTrack,d=this.currentTransmuxState,c=d.accurateTimeOffset,u=d.timeOffset;R.log("[transmuxer.ts]: Flushed fragment "+i.sn+(i.part>-1?" p: "+i.part:"")+" of level "+i.level);var g=this.remuxer.remux(r,a,s,l,u,c,!0,this.id);e.push({remuxResult:g,chunkMeta:i}),i.transmuxing.executeEnd=bt()},n.resetInitialTimestamp=function(e){var t=this.demuxer,i=this.remuxer;t&&i&&(t.resetTimeStamp(e),i.resetTimeStamp(e))},n.resetContiguity=function(){var e=this.demuxer,t=this.remuxer;e&&t&&(e.resetContiguity(),t.resetNextTimestamp())},n.resetInitSegment=function(e,t,i,r,a){var s=this.demuxer,l=this.remuxer;s&&l&&(s.resetInitSegment(e,t,i,r),l.resetInitSegment(e,t,i,a))},n.destroy=function(){this.demuxer&&(this.demuxer.destroy(),this.demuxer=void 0),this.remuxer&&(this.remuxer.destroy(),this.remuxer=void 0)},n.transmux=function(e,t,i,r,a){return t&&t.method==="SAMPLE-AES"?this.transmuxSampleAes(e,t,i,r,a):this.transmuxUnencrypted(e,i,r,a)},n.transmuxUnencrypted=function(e,t,i,r){var a=this.demuxer.demux(e,t,!1,!this.config.progressive),s=a.audioTrack,l=a.videoTrack,d=a.id3Track,c=a.textTrack;return{remuxResult:this.remuxer.remux(s,l,d,c,t,i,!1,this.id),chunkMeta:r}},n.transmuxSampleAes=function(e,t,i,r,a){var s=this;return this.demuxer.demuxSampleAes(e,t,i).then(function(l){return{remuxResult:s.remuxer.remux(l.audioTrack,l.videoTrack,l.id3Track,l.textTrack,i,r,!1,s.id),chunkMeta:a}})},n.configureTransmuxer=function(e){for(var t,i=this.config,r=this.observer,a=this.typeSupported,s=this.vendor,l=0,d=Nr.length;l"u"||(s.workerPath,0))this.transmuxer=new Ur(this.observer,m,s,v,t);else try{s.workerPath?(R.log("loading Web Worker "+s.workerPath+' for "'+t+'"'),this.workerContext=(u=s.workerPath,g=new self.URL(u,self.location.href).href,{worker:new self.Worker(g),scriptURL:g})):(R.log('injecting Web Worker for "'+t+'"'),this.workerContext=(d=new self.Blob(["var exports={};var module={exports:exports};function define(f){f()};define.amd=true;("+k.toString()+")(true);"],{type:"text/javascript"}),c=self.URL.createObjectURL(d),{worker:new self.Worker(c),objectURL:c})),this.onwmsg=function(_){return a.onWorkerMessage(_)};var y=this.workerContext.worker;y.addEventListener("message",this.onwmsg),y.onerror=function(_){var b=new Error(_.message+" ("+_.filename+":"+_.lineno+")");s.enableWorker=!1,R.warn('Error in "'+t+'" Web Worker, fallback to inline'),a.hls.trigger(A.ERROR,{type:ne.OTHER_ERROR,details:O.INTERNAL_EXCEPTION,fatal:!1,event:"demuxerWorker",error:b})},y.postMessage({cmd:"init",typeSupported:m,vendor:v,id:t,config:JSON.stringify(s)})}catch(_){R.warn('Error setting up "'+t+'" Web Worker, fallback to inline',_),this.resetWorker(),this.error=null,this.transmuxer=new Ur(this.observer,m,s,v,t)}}var n=o.prototype;return n.resetWorker=function(){if(this.workerContext){var e=this.workerContext,t=e.worker,i=e.objectURL;i&&self.URL.revokeObjectURL(i),t.removeEventListener("message",this.onwmsg),t.onerror=null,t.terminate(),this.workerContext=null}},n.destroy=function(){if(this.workerContext)this.resetWorker(),this.onwmsg=void 0;else{var e=this.transmuxer;e&&(e.destroy(),this.transmuxer=null)}var t=this.observer;t&&t.removeAllListeners(),this.frag=null,this.observer=null,this.hls=null},n.push=function(e,t,i,r,a,s,l,d,c,u){var g,m,v=this;c.transmuxing.start=self.performance.now();var y=this.transmuxer,_=s?s.start:a.start,b=a.decryptdata,E=this.frag,S=!(E&&a.cc===E.cc),C=!(E&&c.level===E.level),L=E?c.sn-E.sn:-1,I=this.part?c.part-this.part.index:-1,P=L===0&&c.id>1&&c.id===(E==null?void 0:E.stats.chunkCount),N=!C&&(L===1||L===0&&(I===1||P&&I<=0)),M=self.performance.now();(C||L||a.stats.parsing.start===0)&&(a.stats.parsing.start=M),!s||!I&&N||(s.stats.parsing.start=M);var B=!(E&&((g=a.initSegment)==null?void 0:g.url)===((m=E.initSegment)==null?void 0:m.url)),Y=new nl(S,N,d,C,_,B);if(!N||S||B){R.log("[transmuxer-interface, "+a.type+"]: Starting new transmux session for sn: "+c.sn+" p: "+c.part+" level: "+c.level+" id: "+c.id+` + discontinuity: `+S+` + trackSwitch: `+C+` + contiguous: `+N+` + accurateTimeOffset: `+d+` + timeOffset: `+_+` + initSegmentChange: `+B);var K=new rl(i,r,t,l,u);this.configureTransmuxer(K)}if(this.frag=a,this.part=s,this.workerContext)this.workerContext.worker.postMessage({cmd:"demux",data:e,decryptdata:b,chunkMeta:c,state:Y},e instanceof ArrayBuffer?[e]:[]);else if(y){var Q=y.push(e,b,c,Y);Ft(Q)?(y.async=!0,Q.then(function(re){v.handleTransmuxComplete(re)}).catch(function(re){v.transmuxerError(re,c,"transmuxer-interface push error")})):(y.async=!1,this.handleTransmuxComplete(Q))}},n.flush=function(e){var t=this;e.transmuxing.start=self.performance.now();var i=this.transmuxer;if(this.workerContext)this.workerContext.worker.postMessage({cmd:"flush",chunkMeta:e});else if(i){var r=i.flush(e);Ft(r)||i.async?(Ft(r)||(r=Promise.resolve(r)),r.then(function(a){t.handleFlushResult(a,e)}).catch(function(a){t.transmuxerError(a,e,"transmuxer-interface flush error")})):this.handleFlushResult(r,e)}},n.transmuxerError=function(e,t,i){this.hls&&(this.error=e,this.hls.trigger(A.ERROR,{type:ne.MEDIA_ERROR,details:O.FRAG_PARSING_ERROR,chunkMeta:t,fatal:!1,error:e,err:e,reason:i}))},n.handleFlushResult=function(e,t){var i=this;e.forEach(function(r){i.handleTransmuxComplete(r)}),this.onFlush(t)},n.onWorkerMessage=function(e){var t=e.data,i=this.hls;switch(t.event){case"init":var r,a=(r=this.workerContext)==null?void 0:r.objectURL;a&&self.URL.revokeObjectURL(a);break;case"transmuxComplete":this.handleTransmuxComplete(t.data);break;case"flush":this.onFlush(t.data);break;case"workerLog":R[t.data.logType]&&R[t.data.logType](t.data.message);break;default:t.data=t.data||{},t.data.frag=this.frag,t.data.id=this.id,i.trigger(t.event,t.data)}},n.configureTransmuxer=function(e){var t=this.transmuxer;this.workerContext?this.workerContext.worker.postMessage({cmd:"configure",config:e}):t&&t.configure(e)},n.handleTransmuxComplete=function(e){e.chunkMeta.transmuxing.end=self.performance.now(),this.onTransmuxComplete(e)},o}(),al=function(){function o(e,t,i,r){this.config=void 0,this.media=null,this.fragmentTracker=void 0,this.hls=void 0,this.nudgeRetry=0,this.stallReported=!1,this.stalled=null,this.moved=!1,this.seeking=!1,this.config=e,this.media=t,this.fragmentTracker=i,this.hls=r}var n=o.prototype;return n.destroy=function(){this.media=null,this.hls=this.fragmentTracker=null},n.poll=function(e,t){var i=this.config,r=this.media,a=this.stalled;if(r!==null){var s=r.currentTime,l=r.seeking,d=this.seeking&&!l,c=!this.seeking&&l;if(this.seeking=l,s===e){if(c||d)this.stalled=null;else if(!(r.paused&&!l||r.ended||r.playbackRate===0)&&Ae.getBuffered(r).length){var u=Ae.bufferInfo(r,s,0),g=u.len>0,m=u.nextStart||0;if(g||m){if(l){var v=u.len>2,y=!m||t&&t.start<=s||m-s>2&&!this.fragmentTracker.getPartialFragment(s);if(v||y)return;this.moved=!1}if(!this.moved&&this.stalled!==null){var _,b=Math.max(m,u.start||0)-s,E=this.hls.levels?this.hls.levels[this.hls.currentLevel]:null,S=!(E==null||(_=E.details)==null)&&_.live?2*E.details.targetduration:2,C=this.fragmentTracker.getPartialFragment(s);if(b>0&&(b<=S||C))return void this._trySkipBufferHole(C)}var L=self.performance.now();if(a!==null){var I=L-a;if(l||!(I>=250)||(this._reportStall(u),this.media)){var P=Ae.bufferInfo(r,s,i.maxBufferHole);this._tryFixBufferStall(P,I)}}else this.stalled=L}}}else if(this.moved=!0,a!==null){if(this.stallReported){var N=self.performance.now()-a;R.warn("playback not stuck anymore @"+s+", after "+Math.round(N)+"ms"),this.stallReported=!1}this.stalled=null,this.nudgeRetry=0}}},n._tryFixBufferStall=function(e,t){var i=this.config,r=this.fragmentTracker,a=this.media;if(a!==null){var s=a.currentTime,l=r.getPartialFragment(s);if(l&&(this._trySkipBufferHole(l)||!this.media))return;(e.len>i.maxBufferHole||e.nextStart&&e.nextStart-s1e3*i.highBufferWatchdogPeriod&&(R.warn("Trying to nudge playhead over buffer-hole"),this.stalled=null,this._tryNudgeBuffer())}},n._reportStall=function(e){var t=this.hls,i=this.media;if(!this.stallReported&&i){this.stallReported=!0;var r=new Error("Playback stalling at @"+i.currentTime+" due to low buffer ("+JSON.stringify(e)+")");R.warn(r.message),t.trigger(A.ERROR,{type:ne.MEDIA_ERROR,details:O.BUFFER_STALLED_ERROR,fatal:!1,error:r,buffer:e.len})}},n._trySkipBufferHole=function(e){var t=this.config,i=this.hls,r=this.media;if(r===null)return 0;var a=r.currentTime,s=Ae.bufferInfo(r,a,0),l=a0&&s.len<1&&r.readyState<3,u=l-a;if(u>0&&(d||c)){if(u>t.maxBufferHole){var g=this.fragmentTracker,m=!1;if(a===0){var v=g.getAppendedFrag(0,ve);v&&l1?(a=0,this.bitrateTest=!0):a=r.nextAutoLevel),this.level=r.nextLoadLevel=a,this.loadedmetadata=!1}i>0&&t===-1&&(this.log("Override startPosition with lastCurrentTime @"+i.toFixed(3)),t=i),this.state=ue,this.nextLoadPosition=this.startPosition=this.lastCurrentTime=t,this.tick()}else this._forceStartLoad=!0,this.state=$e},e.stopLoad=function(){this._forceStartLoad=!1,o.prototype.stopLoad.call(this)},e.doTick=function(){switch(this.state){case Mt:var t,i=this.levels,r=this.level,a=i==null||(t=i[r])==null?void 0:t.details;if(a&&(!a.live||this.levelLastLoaded===this.level)){if(this.waitForCdnTuneIn(a))break;this.state=ue;break}if(this.hls.nextLoadLevel!==this.level){this.state=ue;break}break;case jt:var s,l=self.performance.now(),d=this.retryDate;(!d||l>=d||(s=this.media)!=null&&s.seeking)&&(this.resetStartWhenNotLoaded(this.level),this.state=ue)}this.state===ue&&this.doTickIdle(),this.onTickEnd()},e.onTickEnd=function(){o.prototype.onTickEnd.call(this),this.checkBuffer(),this.checkFragmentChanged()},e.doTickIdle=function(){var t=this.hls,i=this.levelLastLoaded,r=this.levels,a=this.media,s=t.config,l=t.nextLoadLevel;if(i!==null&&(a||!this.startFragRequested&&s.startFragPrefetch)&&(!this.altAudio||!this.audioOnly)&&r!=null&&r[l]){var d=r[l],c=this.getMainFwdBufferInfo();if(c!==null){var u=this.getLevelDetails();if(u&&this._streamEnded(c,u)){var g={};return this.altAudio&&(g.type="video"),this.hls.trigger(A.BUFFER_EOS,g),void(this.state=ci)}t.loadLevel!==l&&t.manualLevel===-1&&this.log("Adapting to level "+l+" from level "+this.level),this.level=t.nextLoadLevel=l;var m=d.details;if(!m||this.state===Mt||m.live&&this.levelLastLoaded!==l)return this.level=l,void(this.state=Mt);var v=c.len,y=this.getMaxBufferLength(d.maxBitrate);if(!(v>=y)){this.backtrackFragment&&this.backtrackFragment.start>c.end&&(this.backtrackFragment=null);var _=this.backtrackFragment?this.backtrackFragment.start:c.end,b=this.getNextFragment(_,m);if(this.couldBacktrack&&!this.fragPrevious&&b&&b.sn!=="initSegment"&&this.fragmentTracker.getState(b)!==li){var E,S=((E=this.backtrackFragment)!=null?E:b).sn-m.startSN,C=m.fragments[S-1];C&&b.cc===C.cc&&(b=C,this.fragmentTracker.removeFragment(C))}else this.backtrackFragment&&c.len&&(this.backtrackFragment=null);if(b&&this.isLoopLoading(b,_)){if(!b.gap){var L=this.audioOnly&&!this.altAudio?Be:Ze,I=(L===Ze?this.videoBuffer:this.mediaBuffer)||this.media;I&&this.afterBufferFlushed(I,L,ve)}b=this.getNextFragmentLoopLoading(b,m,c,ve,y)}b&&(!b.initSegment||b.initSegment.data||this.bitrateTest||(b=b.initSegment),this.loadFragment(b,d,_))}}}},e.loadFragment=function(t,i,r){var a=this.fragmentTracker.getState(t);this.fragCurrent=t,a===si||a===Vt?t.sn==="initSegment"?this._loadInitSegment(t,i):this.bitrateTest?(this.log("Fragment "+t.sn+" of level "+t.level+" is being downloaded to test bitrate and will not be buffered"),this._loadBitrateTestFrag(t,i)):(this.startFragRequested=!0,o.prototype.loadFragment.call(this,t,i,r)):this.clearTrackerIfNeeded(t)},e.getBufferedFrag=function(t){return this.fragmentTracker.getBufferedFrag(t,ve)},e.followingBufferedFrag=function(t){return t?this.getBufferedFrag(t.end+.5):null},e.immediateLevelSwitch=function(){this.abortCurrentFrag(),this.flushMainBuffer(0,Number.POSITIVE_INFINITY)},e.nextLevelSwitch=function(){var t=this.levels,i=this.media;if(i!=null&&i.readyState){var r,a=this.getAppendedFrag(i.currentTime);a&&a.start>1&&this.flushMainBuffer(0,a.start-1);var s=this.getLevelDetails();if(s!=null&&s.live){var l=this.getMainFwdBufferInfo();if(!l||l.len<2*s.targetduration)return}if(!i.paused&&t){var d=t[this.hls.nextLoadLevel],c=this.fragLastKbps;r=c&&this.fragCurrent?this.fragCurrent.duration*d.maxBitrate/(1e3*c)+1:0}else r=0;var u=this.getBufferedFrag(i.currentTime+r);if(u){var g=this.followingBufferedFrag(u);if(g){this.abortCurrentFrag();var m=g.maxStartPTS?g.maxStartPTS:g.start,v=g.duration,y=Math.max(u.end,m+Math.min(Math.max(v-this.config.maxFragLookUpTolerance,.5*v),.75*v));this.flushMainBuffer(y,Number.POSITIVE_INFINITY)}}}},e.abortCurrentFrag=function(){var t=this.fragCurrent;switch(this.fragCurrent=null,this.backtrackFragment=null,t&&(t.abortRequests(),this.fragmentTracker.removeFragment(t)),this.state){case Dr:case Yt:case jt:case vt:case Oi:this.state=ue}this.nextLoadPosition=this.getLoadPosition()},e.flushMainBuffer=function(t,i){o.prototype.flushMainBuffer.call(this,t,i,this.altAudio?"video":null)},e.onMediaAttached=function(t,i){o.prototype.onMediaAttached.call(this,t,i);var r=i.media;this.onvplaying=this.onMediaPlaying.bind(this),this.onvseeked=this.onMediaSeeked.bind(this),r.addEventListener("playing",this.onvplaying),r.addEventListener("seeked",this.onvseeked),this.gapController=new al(this.config,r,this.fragmentTracker,this.hls)},e.onMediaDetaching=function(){var t=this.media;t&&this.onvplaying&&this.onvseeked&&(t.removeEventListener("playing",this.onvplaying),t.removeEventListener("seeked",this.onvseeked),this.onvplaying=this.onvseeked=null,this.videoBuffer=null),this.fragPlaying=null,this.gapController&&(this.gapController.destroy(),this.gapController=null),o.prototype.onMediaDetaching.call(this)},e.onMediaPlaying=function(){this.tick()},e.onMediaSeeked=function(){var t=this.media,i=t?t.currentTime:null;ie(i)&&this.log("Media seeked to "+i.toFixed(3));var r=this.getMainFwdBufferInfo();r!==null&&r.len!==0?this.tick():this.warn('Main forward buffer length on "seeked" event '+(r?r.len:"empty")+")")},e.onManifestLoading=function(){this.log("Trigger BUFFER_RESET"),this.hls.trigger(A.BUFFER_RESET,void 0),this.fragmentTracker.removeAllFragments(),this.couldBacktrack=!1,this.startPosition=this.lastCurrentTime=0,this.levels=this.fragPlaying=this.backtrackFragment=null,this.altAudio=this.audioOnly=!1},e.onManifestParsed=function(t,i){var r,a,s,l=!1,d=!1;i.levels.forEach(function(c){(r=c.audioCodec)&&(r.indexOf("mp4a.40.2")!==-1&&(l=!0),r.indexOf("mp4a.40.5")!==-1&&(d=!0))}),this.audioCodecSwitch=l&&d&&typeof((s=_a())==null||(a=s.prototype)==null?void 0:a.changeType)!="function",this.audioCodecSwitch&&this.log("Both AAC/HE-AAC audio found in levels; declaring level codec as HE-AAC"),this.levels=i.levels,this.startFragRequested=!1},e.onLevelLoading=function(t,i){var r=this.levels;if(r&&this.state===ue){var a=r[i.level];(!a.details||a.details.live&&this.levelLastLoaded!==i.level||this.waitForCdnTuneIn(a.details))&&(this.state=Mt)}},e.onLevelLoaded=function(t,i){var r,a=this.levels,s=i.level,l=i.details,d=l.totalduration;if(a){this.log("Level "+s+" loaded ["+l.startSN+","+l.endSN+"]"+(l.lastPartSn?"[part-"+l.lastPartSn+"-"+l.lastPartIndex+"]":"")+", cc ["+l.startCC+", "+l.endCC+"] duration:"+d);var c=a[s],u=this.fragCurrent;!u||this.state!==Yt&&this.state!==jt||u.level===i.level&&u.urlId===c.urlId||!u.loader||this.abortCurrentFrag();var g=0;if(l.live||(r=c.details)!=null&&r.live){if(this.checkLiveUpdate(l),l.deltaUpdateFailed)return;g=this.alignPlaylists(l,c.details)}if(c.details=l,this.levelLastLoaded=s,this.hls.trigger(A.LEVEL_UPDATED,{details:l,level:s}),this.state===Mt){if(this.waitForCdnTuneIn(l))return;this.state=ue}this.startFragRequested?l.live&&this.synchronizeToLiveEdge(l):this.setStartPosition(l,g),this.tick()}else this.warn("Levels were reset while loading level "+s)},e._handleFragmentLoadProgress=function(t){var i,r=t.frag,a=t.part,s=t.payload,l=this.levels;if(l){var d=l[r.level],c=d.details;if(!c)return this.warn("Dropping fragment "+r.sn+" of level "+r.level+" after level details were reset"),void this.fragmentTracker.removeFragment(r);var u=d.videoCodec,g=c.PTSKnown||!c.live,m=(i=r.initSegment)==null?void 0:i.data,v=this._getAudioCodec(d),y=this.transmuxer=this.transmuxer||new Ka(this.hls,ve,this._handleTransmuxComplete.bind(this),this._handleTransmuxerFlush.bind(this)),_=a?a.index:-1,b=_!==-1,E=new Cr(r.level,r.sn,r.stats.chunkCount,s.byteLength,_,b),S=this.initPTS[r.cc];y.push(s,m,v,u,r,a,c.totalduration,g,E,S)}else this.warn("Levels were reset while fragment load was in progress. Fragment "+r.sn+" of level "+r.level+" will not be buffered")},e.onAudioTrackSwitching=function(t,i){var r=this.altAudio;if(!i.url){if(this.mediaBuffer!==this.media){this.log("Switching on main audio, use media.buffered to schedule main fragment loading"),this.mediaBuffer=this.media;var a=this.fragCurrent;a&&(this.log("Switching to main audio track, cancel main fragment load"),a.abortRequests(),this.fragmentTracker.removeFragment(a)),this.resetTransmuxer(),this.resetLoadingState()}else this.audioOnly&&this.resetTransmuxer();var s=this.hls;r&&(s.trigger(A.BUFFER_FLUSHING,{startOffset:0,endOffset:Number.POSITIVE_INFINITY,type:null}),this.fragmentTracker.removeAllFragments()),s.trigger(A.AUDIO_TRACK_SWITCHED,i)}},e.onAudioTrackSwitched=function(t,i){var r=i.id,a=!!this.hls.audioTracks[r].url;if(a){var s=this.videoBuffer;s&&this.mediaBuffer!==s&&(this.log("Switching on alternate audio, use video.buffered to schedule main fragment loading"),this.mediaBuffer=s)}this.altAudio=a,this.tick()},e.onBufferCreated=function(t,i){var r,a,s=i.tracks,l=!1;for(var d in s){var c=s[d];if(c.id==="main"){if(a=d,r=c,d==="video"){var u=s[d];u&&(this.videoBuffer=u.buffer)}}else l=!0}l&&r?(this.log("Alternate track found, use "+a+".buffered to schedule main fragment loading"),this.mediaBuffer=r.buffer):this.mediaBuffer=this.media},e.onFragBuffered=function(t,i){var r=i.frag,a=i.part;if(!r||r.type===ve){if(this.fragContextChanged(r))return this.warn("Fragment "+r.sn+(a?" p: "+a.index:"")+" of level "+r.level+" finished buffering, but was aborted. state: "+this.state),void(this.state===Oi&&(this.state=ue));var s=a?a.stats:r.stats;this.fragLastKbps=Math.round(8*s.total/(s.buffering.end-s.loading.first)),r.sn!=="initSegment"&&(this.fragPrevious=r),this.fragBufferedComplete(r,a)}},e.onError=function(t,i){var r;if(i.fatal)this.state=qt;else switch(i.details){case O.FRAG_GAP:case O.FRAG_PARSING_ERROR:case O.FRAG_DECRYPT_ERROR:case O.FRAG_LOAD_ERROR:case O.FRAG_LOAD_TIMEOUT:case O.KEY_LOAD_ERROR:case O.KEY_LOAD_TIMEOUT:this.onFragmentOrKeyLoadError(ve,i);break;case O.LEVEL_LOAD_ERROR:case O.LEVEL_LOAD_TIMEOUT:case O.LEVEL_PARSING_ERROR:i.levelRetry||this.state!==Mt||((r=i.context)==null?void 0:r.type)!==Ot||(this.state=ue);break;case O.BUFFER_FULL_ERROR:if(!i.parent||i.parent!=="main")return;this.reduceLengthAndFlushBuffer(i)&&this.flushMainBuffer(0,Number.POSITIVE_INFINITY);break;case O.INTERNAL_EXCEPTION:this.recoverWorkerError(i)}},e.checkBuffer=function(){var t=this.media,i=this.gapController;if(t&&i&&t.readyState){if(this.loadedmetadata||!Ae.getBuffered(t).length){var r=this.state!==ue?this.fragCurrent:null;i.poll(this.lastCurrentTime,r)}this.lastCurrentTime=t.currentTime}},e.onFragLoadEmergencyAborted=function(){this.state=ue,this.loadedmetadata||(this.startFragRequested=!1,this.nextLoadPosition=this.startPosition),this.tickImmediate()},e.onBufferFlushed=function(t,i){var r=i.type;if(r!==Be||this.audioOnly&&!this.altAudio){var a=(r===Ze?this.videoBuffer:this.mediaBuffer)||this.media;this.afterBufferFlushed(a,r,ve)}},e.onLevelsUpdated=function(t,i){this.levels=i.levels},e.swapAudioCodec=function(){this.audioCodecSwap=!this.audioCodecSwap},e.seekToStartPos=function(){var t=this.media;if(t){var i=t.currentTime,r=this.startPosition;if(r>=0&&i0&&(sI.cc;if(s.independent!==!1){var M=m.startPTS,B=m.endPTS,Y=m.startDTS,K=m.endDTS;if(u)u.elementaryStreams[m.type]={startPTS:M,endPTS:B,startDTS:Y,endDTS:K};else if(m.firstKeyFrame&&m.independent&&l.id===1&&!N&&(this.couldBacktrack=!0),m.dropped&&m.independent){var Q=this.getMainFwdBufferInfo(),re=(Q?Q.end:this.getLoadPosition())+this.config.maxBufferHole,W=m.firstKeyFramePTS?m.firstKeyFramePTS:M;if(!P&&re1&&t.seeking===!1){var r=t.currentTime;if(Ae.isBuffered(t,r)?i=this.getAppendedFrag(r):Ae.isBuffered(t,r+.1)&&(i=this.getAppendedFrag(r+.1)),i){this.backtrackFragment=null;var a=this.fragPlaying,s=i.level;a&&i.sn===a.sn&&a.level===s&&i.urlId===a.urlId||(this.fragPlaying=i,this.hls.trigger(A.FRAG_CHANGED,{frag:i}),a&&a.level===s||this.hls.trigger(A.LEVEL_SWITCHED,{level:s}))}}},D(n,[{key:"nextLevel",get:function(){var t=this.nextBufferedFrag;return t?t.level:-1}},{key:"currentFrag",get:function(){var t=this.media;return t?this.fragPlaying||this.getAppendedFrag(t.currentTime):null}},{key:"currentProgramDateTime",get:function(){var t=this.media;if(t){var i=t.currentTime,r=this.currentFrag;if(r&&ie(i)&&ie(r.programDateTime)){var a=r.programDateTime+1e3*(i-r.start);return new Date(a)}}return null}},{key:"currentLevel",get:function(){var t=this.currentFrag;return t?t.level:-1}},{key:"nextBufferedFrag",get:function(){var t=this.currentFrag;return t?this.followingBufferedFrag(t):null}},{key:"forceStartLoad",get:function(){return this._forceStartLoad}}]),n}(Rr),Qt=function(){function o(e,t,i){t===void 0&&(t=0),i===void 0&&(i=0),this.halfLife=void 0,this.alpha_=void 0,this.estimate_=void 0,this.totalWeight_=void 0,this.halfLife=e,this.alpha_=e?Math.exp(Math.log(.5)/e):0,this.estimate_=t,this.totalWeight_=i}var n=o.prototype;return n.sample=function(e,t){var i=Math.pow(this.alpha_,e);this.estimate_=t*(1-i)+i*this.estimate_,this.totalWeight_+=e},n.getTotalWeight=function(){return this.totalWeight_},n.getEstimate=function(){if(this.alpha_){var e=1-Math.pow(this.alpha_,this.totalWeight_);if(e)return this.estimate_/e}return this.estimate_},o}(),sl=function(){function o(e,t,i,r){r===void 0&&(r=100),this.defaultEstimate_=void 0,this.minWeight_=void 0,this.minDelayMs_=void 0,this.slow_=void 0,this.fast_=void 0,this.defaultTTFB_=void 0,this.ttfb_=void 0,this.defaultEstimate_=i,this.minWeight_=.001,this.minDelayMs_=50,this.slow_=new Qt(e),this.fast_=new Qt(t),this.defaultTTFB_=r,this.ttfb_=new Qt(e)}var n=o.prototype;return n.update=function(e,t){var i=this.slow_,r=this.fast_,a=this.ttfb_;i.halfLife!==e&&(this.slow_=new Qt(e,i.getEstimate(),i.getTotalWeight())),r.halfLife!==t&&(this.fast_=new Qt(t,r.getEstimate(),r.getTotalWeight())),a.halfLife!==e&&(this.ttfb_=new Qt(e,a.getEstimate(),a.getTotalWeight()))},n.sample=function(e,t){var i=(e=Math.max(e,this.minDelayMs_))/1e3,r=8*t/i;this.fast_.sample(i,r),this.slow_.sample(i,r)},n.sampleTTFB=function(e){var t=e/1e3,i=Math.sqrt(2)*Math.exp(-Math.pow(t,2)/2);this.ttfb_.sample(i,Math.max(e,5))},n.canEstimate=function(){return this.fast_.getTotalWeight()>=this.minWeight_},n.getEstimate=function(){return this.canEstimate()?Math.min(this.fast_.getEstimate(),this.slow_.getEstimate()):this.defaultEstimate_},n.getEstimateTTFB=function(){return this.ttfb_.getTotalWeight()>=this.minWeight_?this.ttfb_.getEstimate():this.defaultTTFB_},n.destroy=function(){},o}(),ll=function(){function o(e){this.hls=void 0,this.lastLevelLoadSec=0,this.lastLoadedFragLevel=0,this._nextAutoLevel=-1,this.timer=-1,this.onCheck=this._abandonRulesCheck.bind(this),this.fragCurrent=null,this.partCurrent=null,this.bitrateTestDelay=0,this.bwEstimator=void 0,this.hls=e;var t=e.config;this.bwEstimator=new sl(t.abrEwmaSlowVoD,t.abrEwmaFastVoD,t.abrEwmaDefaultEstimate),this.registerListeners()}var n=o.prototype;return n.registerListeners=function(){var e=this.hls;e.on(A.FRAG_LOADING,this.onFragLoading,this),e.on(A.FRAG_LOADED,this.onFragLoaded,this),e.on(A.FRAG_BUFFERED,this.onFragBuffered,this),e.on(A.LEVEL_SWITCHING,this.onLevelSwitching,this),e.on(A.LEVEL_LOADED,this.onLevelLoaded,this)},n.unregisterListeners=function(){var e=this.hls;e.off(A.FRAG_LOADING,this.onFragLoading,this),e.off(A.FRAG_LOADED,this.onFragLoaded,this),e.off(A.FRAG_BUFFERED,this.onFragBuffered,this),e.off(A.LEVEL_SWITCHING,this.onLevelSwitching,this),e.off(A.LEVEL_LOADED,this.onLevelLoaded,this)},n.destroy=function(){this.unregisterListeners(),this.clearTimer(),this.hls=this.onCheck=null,this.fragCurrent=this.partCurrent=null},n.onFragLoading=function(e,t){var i,r=t.frag;this.ignoreFragment(r)||(this.fragCurrent=r,this.partCurrent=(i=t.part)!=null?i:null,this.clearTimer(),this.timer=self.setInterval(this.onCheck,100))},n.onLevelSwitching=function(e,t){this.clearTimer()},n.getTimeToLoadFrag=function(e,t,i,r){return e+i/t+(r?this.lastLevelLoadSec:0)},n.onLevelLoaded=function(e,t){var i=this.hls.config,r=t.stats,a=r.total,s=r.bwEstimate;ie(a)&&ie(s)&&(this.lastLevelLoadSec=8*a/s),t.details.live?this.bwEstimator.update(i.abrEwmaSlowLive,i.abrEwmaFastLive):this.bwEstimator.update(i.abrEwmaSlowVoD,i.abrEwmaFastVoD)},n._abandonRulesCheck=function(){var e=this.fragCurrent,t=this.partCurrent,i=this.hls,r=i.autoLevelEnabled,a=i.media;if(e&&a){var s=performance.now(),l=t?t.stats:e.stats,d=t?t.duration:e.duration,c=s-l.loading.start;if(l.aborted||l.loaded&&l.loaded===l.total||e.level===0)return this.clearTimer(),void(this._nextAutoLevel=-1);if(r&&!a.paused&&a.playbackRate&&a.readyState){var u=i.mainForwardBufferInfo;if(u!==null){var g=this.bwEstimator.getEstimateTTFB(),m=Math.abs(a.playbackRate);if(!(c<=Math.max(g,d/(2*m)*1e3))){var v=u.len/m;if(!(v>=2*d/m)){var y=l.loading.first?l.loading.first-l.loading.start:-1,_=l.loaded&&y>-1,b=this.bwEstimator.getEstimate(),E=i.levels,S=i.minAutoLevel,C=E[e.level],L=l.total||Math.max(l.loaded,Math.round(d*C.maxBitrate/8)),I=c-y;I<1&&_&&(I=Math.min(c,8*l.loaded/b));var P=_?1e3*l.loaded/I:0,N=P?(L-l.loaded)/P:8*L/b+g/1e3;if(!(N<=v)){var M,B=P?8*P:b,Y=Number.POSITIVE_INFINITY;for(M=e.level-1;M>S;M--){var K=E[M].maxBitrate;if((Y=this.getTimeToLoadFrag(g/1e3,B,d*K,!E[M].details))=N||Y>10*d||(i.nextLoadLevel=M,_?this.bwEstimator.sample(c-Math.min(g,y),l.loaded):this.bwEstimator.sampleTTFB(c),this.clearTimer(),R.warn("[abr] Fragment "+e.sn+(t?" part "+t.index:"")+" of level "+e.level+` is loading too slowly; + Time to underbuffer: `+v.toFixed(3)+` s + Estimated load time for current fragment: `+N.toFixed(3)+` s + Estimated load time for down switch fragment: `+Y.toFixed(3)+` s + TTFB estimate: `+y+` + Current BW estimate: `+(ie(b)?(b/1024).toFixed(3):"Unknown")+` Kb/s + New BW estimate: `+(this.bwEstimator.getEstimate()/1024).toFixed(3)+` Kb/s + Aborting and switching to level `+M),e.loader&&(this.fragCurrent=this.partCurrent=null,e.abortRequests()),i.trigger(A.FRAG_LOAD_EMERGENCY_ABORTED,{frag:e,part:t,stats:l}))}}}}}}},n.onFragLoaded=function(e,t){var i=t.frag,r=t.part,a=r?r.stats:i.stats;if(i.type===ve&&this.bwEstimator.sampleTTFB(a.loading.first-a.loading.start),!this.ignoreFragment(i)){if(this.clearTimer(),this.lastLoadedFragLevel=i.level,this._nextAutoLevel=-1,this.hls.config.abrMaxWithRealBitrate){var s=r?r.duration:i.duration,l=this.hls.levels[i.level],d=(l.loaded?l.loaded.bytes:0)+a.loaded,c=(l.loaded?l.loaded.duration:0)+s;l.loaded={bytes:d,duration:c},l.realBitrate=Math.round(8*d/c)}if(i.bitrateTest){var u={stats:a,frag:i,part:r,id:i.type};this.onFragBuffered(A.FRAG_BUFFERED,u),i.bitrateTest=!1}}},n.onFragBuffered=function(e,t){var i=t.frag,r=t.part,a=r!=null&&r.stats.loaded?r.stats:i.stats;if(!a.aborted&&!this.ignoreFragment(i)){var s=a.parsing.end-a.loading.start-Math.min(a.loading.first-a.loading.start,this.bwEstimator.getEstimateTTFB());this.bwEstimator.sample(s,a.loaded),a.bwEstimate=this.bwEstimator.getEstimate(),i.bitrateTest?this.bitrateTestDelay=s/1e3:this.bitrateTestDelay=0}},n.ignoreFragment=function(e){return e.type!==ve||e.sn==="initSegment"},n.clearTimer=function(){self.clearInterval(this.timer)},n.getNextABRAutoLevel=function(){var e=this.fragCurrent,t=this.partCurrent,i=this.hls,r=i.maxAutoLevel,a=i.config,s=i.minAutoLevel,l=i.media,d=t?t.duration:e?e.duration:0,c=l&&l.playbackRate!==0?Math.abs(l.playbackRate):1,u=this.bwEstimator?this.bwEstimator.getEstimate():a.abrEwmaDefaultEstimate,g=i.mainForwardBufferInfo,m=(g?g.len:0)/c,v=this.findBestLevel(u,s,r,m,a.abrBandWidthFactor,a.abrBandWidthUpFactor);if(v>=0)return v;R.trace("[abr] "+(m?"rebuffering expected":"buffer is empty")+", finding optimal quality level");var y=d?Math.min(d,a.maxStarvationDelay):a.maxStarvationDelay,_=a.abrBandWidthFactor,b=a.abrBandWidthUpFactor;if(!m){var E=this.bitrateTestDelay;E&&(y=(d?Math.min(d,a.maxLoadingDelay):a.maxLoadingDelay)-E,R.trace("[abr] bitrate test took "+Math.round(1e3*E)+"ms, set first fragment max fetchDuration to "+Math.round(1e3*y)+" ms"),_=b=1)}return v=this.findBestLevel(u,s,r,m+y,_,b),Math.max(v,0)},n.findBestLevel=function(e,t,i,r,a,s){for(var l,d=this.fragCurrent,c=this.partCurrent,u=this.lastLoadedFragLevel,g=this.hls.levels,m=g[u],v=!(m==null||(l=m.details)==null||!l.live),y=m==null?void 0:m.codecSet,_=c?c.duration:d?d.duration:0,b=this.bwEstimator.getEstimateTTFB()/1e3,E=t,S=-1,C=i;C>=t;C--){var L=g[C];if(!L||y&&L.codecSet!==y)L&&(E=Math.min(C,E),S=Math.max(C,S));else{S!==-1&&R.trace("[abr] Skipped level(s) "+E+"-"+S+' with CODECS:"'+g[S].attrs.CODECS+'"; not compatible with "'+m.attrs.CODECS+'"');var I=L.details,P=(c?I==null?void 0:I.partTarget:I==null?void 0:I.averagetargetduration)||_,N=void 0;N=C<=u?a*e:s*e;var M=g[C].maxBitrate,B=this.getTimeToLoadFrag(b,N,M*P,I===void 0);if(R.trace("[abr] level:"+C+" adjustedbw-bitrate:"+Math.round(N-M)+" avgDuration:"+P.toFixed(1)+" maxFetchDuration:"+r.toFixed(1)+" fetchDuration:"+B.toFixed(1)),N>M&&(B===0||!ie(B)||v&&!this.bitrateTestDelay||BMath.max(e,i)&&r[e].loadError<=r[i].loadError)return e}return e!==-1&&(i=Math.min(e,i)),i},set:function(e){this._nextAutoLevel=e}}]),o}(),Va=function(){function o(){this.chunks=[],this.dataLength=0}var n=o.prototype;return n.push=function(e){this.chunks.push(e),this.dataLength+=e.length},n.flush=function(){var e,t=this.chunks,i=this.dataLength;return t.length?(e=t.length===1?t[0]:function(r,a){for(var s=new Uint8Array(a),l=0,d=0;d0&&t===-1?(this.log("Override startPosition with lastCurrentTime @"+i.toFixed(3)),t=i,this.state=ue):(this.loadedmetadata=!1,this.state=di),this.nextLoadPosition=this.startPosition=this.lastCurrentTime=t,this.tick()},e.doTick=function(){switch(this.state){case ue:this.doTickIdle();break;case di:var t,i=this.levels,r=this.trackId,a=i==null||(t=i[r])==null?void 0:t.details;if(a){if(this.waitForCdnTuneIn(a))break;this.state=hi}break;case jt:var s,l=performance.now(),d=this.retryDate;(!d||l>=d||(s=this.media)!=null&&s.seeking)&&(this.log("RetryDate reached, switch back to IDLE state"),this.resetStartWhenNotLoaded(this.trackId),this.state=ue);break;case hi:var c=this.waitingData;if(c){var u=c.frag,g=c.part,m=c.cache,v=c.complete;if(this.initPTS[u.cc]!==void 0){this.waitingData=null,this.waitingVideoCC=-1,this.state=Yt;var y={frag:u,part:g,payload:m.flush(),networkDetails:null};this._handleFragmentLoadProgress(y),v&&o.prototype._handleFragmentLoadComplete.call(this,y)}else if(this.videoTrackCC!==this.waitingVideoCC)this.log("Waiting fragment cc ("+u.cc+") cancelled because video is at cc "+this.videoTrackCC),this.clearWaitingFragment();else{var _=this.getLoadPosition(),b=Ae.bufferInfo(this.mediaBuffer,_,this.config.maxBufferHole);_r(b.end,this.config.maxFragLookUpTolerance,u)<0&&(this.log("Waiting fragment cc ("+u.cc+") @ "+u.start+" cancelled because another fragment at "+b.end+" is needed"),this.clearWaitingFragment())}}else this.state=ue}this.onTickEnd()},e.clearWaitingFragment=function(){var t=this.waitingData;t&&(this.fragmentTracker.removeFragment(t.frag),this.waitingData=null,this.waitingVideoCC=-1,this.state=ue)},e.resetLoadingState=function(){this.clearWaitingFragment(),o.prototype.resetLoadingState.call(this)},e.onTickEnd=function(){var t=this.media;t!=null&&t.readyState&&(this.lastCurrentTime=t.currentTime)},e.doTickIdle=function(){var t=this.hls,i=this.levels,r=this.media,a=this.trackId,s=t.config;if(i!=null&&i[a]&&(r||!this.startFragRequested&&s.startFragPrefetch)){var l=i[a],d=l.details;if(!d||d.live&&this.levelLastLoaded!==a||this.waitForCdnTuneIn(d))this.state=di;else{var c=this.mediaBuffer?this.mediaBuffer:this.media;this.bufferFlushed&&c&&(this.bufferFlushed=!1,this.afterBufferFlushed(c,Be,lt));var u=this.getFwdBufferInfo(c,lt);if(u!==null){var g=this.bufferedTrack,m=this.switchingTrack;if(!m&&this._streamEnded(u,d))return t.trigger(A.BUFFER_EOS,{type:"audio"}),void(this.state=ci);var v=this.getFwdBufferInfo(this.videoBuffer?this.videoBuffer:this.media,ve),y=u.len,_=this.getMaxBufferLength(v==null?void 0:v.len);if(!(y>=_)||m){var b=d.fragments[0].start,E=u.end;if(m&&r){var S=this.getLoadPosition();g&&m.attrs!==g.attrs&&(E=S),d.PTSKnown&&Sb||u.nextStart)&&(this.log("Alt audio track ahead of main track, seek to start of alt audio track"),r.currentTime=b+.05)}var C=this.getNextFragment(E,d),L=!1;if(C&&this.isLoopLoading(C,E)&&(L=!!C.gap,C=this.getNextFragmentLoopLoading(C,d,u,ve,_)),C){var I=v&&C.start>v.end+d.targetduration;if(I||(v==null||!v.len)&&u.len){var P=this.getAppendedFrag(C.start,ve);if(P===null||(L||(L=!!P.gap||!!I&&v.len===0),I&&!L||L&&u.nextStart&&u.nextStart=i.length)this.warn("Invalid id passed to audio-track controller");else{this.clearTimer();var r=this.currentTrack;i[this.trackId];var a=i[t],s=a.groupId,l=a.name;if(this.log("Switching to audio-track "+t+' "'+l+'" lang:'+a.lang+" group:"+s),this.trackId=t,this.currentTrack=a,this.selectDefaultTrack=!1,this.hls.trigger(A.AUDIO_TRACK_SWITCHING,x({},a)),!a.details||a.details.live){var d=this.switchParams(a.url,r==null?void 0:r.details);this.loadPlaylist(d)}}},e.selectInitialTrack=function(){var t=this.tracksInGroup,i=this.findTrackId(this.currentTrack)|this.findTrackId(null);if(i!==-1)this.setAudioTrack(i);else{var r=new Error("No track found for running audio group-ID: "+this.groupId+" track count: "+t.length);this.warn(r.message),this.hls.trigger(A.ERROR,{type:ne.MEDIA_ERROR,details:O.AUDIO_TRACK_LOAD_ERROR,fatal:!0,error:r})}},e.findTrackId=function(t){for(var i=this.tracksInGroup,r=0;r=s[c].start&&d<=s[c].end){l=s[c];break}var u=r.start+r.duration;l?l.end=u:(l={start:d,end:u},s.push(l)),this.fragmentTracker.fragBuffered(r)}}},e.onBufferFlushing=function(t,i){var r=i.startOffset,a=i.endOffset;if(r===0&&a!==Number.POSITIVE_INFINITY){var s=a-1;if(s<=0)return;i.endOffsetSubtitles=Math.max(0,s),this.tracksBuffered.forEach(function(l){for(var d=0;d=d.length||s!==l)&&c){this.mediaBuffer=this.mediaBufferTimeRanges;var u=0;if(a.live||(r=c.details)!=null&&r.live){var g=this.mainDetails;if(a.deltaUpdateFailed||!g)return;var m=g.fragments[0];c.details?(u=this.alignPlaylists(a,c.details))===0&&m&&Er(a,u=m.start):a.hasProgramDateTime&&g.hasProgramDateTime?(Aa(a,g),u=a.fragments[0].start):m&&Er(a,u=m.start)}c.details=a,this.levelLastLoaded=s,this.startFragRequested||!this.mainDetails&&a.live||this.setStartPosition(c.details,u),this.tick(),a.live&&!this.fragCurrent&&this.media&&this.state===ue&&(oi(null,a.fragments,this.media.currentTime,0)||(this.warn("Subtitle playlist not aligned with playback"),c.details=void 0))}}},e._handleFragmentLoadComplete=function(t){var i=this,r=t.frag,a=t.payload,s=r.decryptdata,l=this.hls;if(!this.fragContextChanged(r)&&a&&a.byteLength>0&&s&&s.key&&s.iv&&s.method==="AES-128"){var d=performance.now();this.decrypter.decrypt(new Uint8Array(a),s.key.buffer,s.iv.buffer).catch(function(c){throw l.trigger(A.ERROR,{type:ne.MEDIA_ERROR,details:O.FRAG_DECRYPT_ERROR,fatal:!1,error:c,reason:c.message,frag:r}),c}).then(function(c){var u=performance.now();l.trigger(A.FRAG_DECRYPTED,{frag:r,payload:c,stats:{tstart:d,tdecrypt:u}})}).catch(function(c){i.warn(c.name+": "+c.message),i.state=ue})}},e.doTick=function(){if(this.media){if(this.state===ue){var t=this.currentTrackId,i=this.levels,r=i[t];if(!i.length||!r||!r.details)return;var a=this.config,s=this.getLoadPosition(),l=Ae.bufferedInfo(this.tracksBuffered[this.currentTrackId]||[],s,a.maxBufferHole),d=l.end,c=l.len,u=this.getFwdBufferInfo(this.media,ve),g=r.details;if(c>this.getMaxBufferLength(u==null?void 0:u.len)+g.levelTargetDuration)return;var m=g.fragments,v=m.length,y=g.edge,_=null,b=this.fragPrevious;if(dy-E?0:E;!(_=oi(b,m,Math.max(m[0].start,d),S))&&b&&b.start>>=0)>i-1)throw new DOMException("Failed to execute '"+e+"' on 'TimeRanges': The index provided ("+t+") is greater than the maximum bound ("+i+")");return o[t][e]};this.buffered={get length(){return o.length},end:function(e){return n("end",e,o.length)},start:function(e){return n("start",e,o.length)}}},pl=function(o){function n(t){var i;return(i=o.call(this,t,"[subtitle-track-controller]")||this).media=null,i.tracks=[],i.groupId=null,i.tracksInGroup=[],i.trackId=-1,i.selectDefaultTrack=!0,i.queuedDefaultTrack=-1,i.trackChangeListener=function(){return i.onTextTracksChanged()},i.asyncPollTrackChange=function(){return i.pollTrackChange(0)},i.useTextTrackPolling=!1,i.subtitlePollingInterval=-1,i._subtitleDisplay=!0,i.registerListeners(),i}q(n,o);var e=n.prototype;return e.destroy=function(){this.unregisterListeners(),this.tracks.length=0,this.tracksInGroup.length=0,this.trackChangeListener=this.asyncPollTrackChange=null,o.prototype.destroy.call(this)},e.registerListeners=function(){var t=this.hls;t.on(A.MEDIA_ATTACHED,this.onMediaAttached,this),t.on(A.MEDIA_DETACHING,this.onMediaDetaching,this),t.on(A.MANIFEST_LOADING,this.onManifestLoading,this),t.on(A.MANIFEST_PARSED,this.onManifestParsed,this),t.on(A.LEVEL_LOADING,this.onLevelLoading,this),t.on(A.LEVEL_SWITCHING,this.onLevelSwitching,this),t.on(A.SUBTITLE_TRACK_LOADED,this.onSubtitleTrackLoaded,this),t.on(A.ERROR,this.onError,this)},e.unregisterListeners=function(){var t=this.hls;t.off(A.MEDIA_ATTACHED,this.onMediaAttached,this),t.off(A.MEDIA_DETACHING,this.onMediaDetaching,this),t.off(A.MANIFEST_LOADING,this.onManifestLoading,this),t.off(A.MANIFEST_PARSED,this.onManifestParsed,this),t.off(A.LEVEL_LOADING,this.onLevelLoading,this),t.off(A.LEVEL_SWITCHING,this.onLevelSwitching,this),t.off(A.SUBTITLE_TRACK_LOADED,this.onSubtitleTrackLoaded,this),t.off(A.ERROR,this.onError,this)},e.onMediaAttached=function(t,i){this.media=i.media,this.media&&(this.queuedDefaultTrack>-1&&(this.subtitleTrack=this.queuedDefaultTrack,this.queuedDefaultTrack=-1),this.useTextTrackPolling=!(this.media.textTracks&&"onchange"in this.media.textTracks),this.useTextTrackPolling?this.pollTrackChange(500):this.media.textTracks.addEventListener("change",this.asyncPollTrackChange))},e.pollTrackChange=function(t){self.clearInterval(this.subtitlePollingInterval),this.subtitlePollingInterval=self.setInterval(this.trackChangeListener,t)},e.onMediaDetaching=function(){this.media&&(self.clearInterval(this.subtitlePollingInterval),this.useTextTrackPolling||this.media.textTracks.removeEventListener("change",this.asyncPollTrackChange),this.trackId>-1&&(this.queuedDefaultTrack=this.trackId),Vr(this.media.textTracks).forEach(function(t){Ht(t)}),this.subtitleTrack=-1,this.media=null)},e.onManifestLoading=function(){this.tracks=[],this.groupId=null,this.tracksInGroup=[],this.trackId=-1,this.selectDefaultTrack=!0},e.onManifestParsed=function(t,i){this.tracks=i.subtitleTracks},e.onSubtitleTrackLoaded=function(t,i){var r=i.id,a=i.details,s=this.trackId,l=this.tracksInGroup[s];if(l){var d=l.details;l.details=i.details,this.log("subtitle track "+r+" loaded ["+a.startSN+"-"+a.endSN+"]"),r===this.trackId&&this.playlistLoaded(r,i,d)}else this.warn("Invalid subtitle track id "+r)},e.onLevelLoading=function(t,i){this.switchLevel(i.level)},e.onLevelSwitching=function(t,i){this.switchLevel(i.level)},e.switchLevel=function(t){var i=this.hls.levels[t];if(i!=null&&i.textGroupIds){var r=i.textGroupIds[i.urlId],a=this.tracksInGroup?this.tracksInGroup[this.trackId]:void 0;if(this.groupId!==r){var s=this.tracks.filter(function(c){return!r||c.groupId===r});this.tracksInGroup=s;var l=this.findTrackId(a==null?void 0:a.name)||this.findTrackId();this.groupId=r||null;var d={subtitleTracks:s};this.log("Updating subtitle tracks, "+s.length+' track(s) found in "'+r+'" group-id'),this.hls.trigger(A.SUBTITLE_TRACKS_UPDATED,d),l!==-1&&this.setSubtitleTrack(l,a)}else this.shouldReloadPlaylist(a)&&this.setSubtitleTrack(this.trackId,a)}},e.findTrackId=function(t){for(var i=this.tracksInGroup,r=0;r=a.length)){this.clearTimer();var s=a[t];if(this.log("Switching to subtitle-track "+t+(s?' "'+s.name+'" lang:'+s.lang+" group:"+s.groupId:"")),this.trackId=t,s){var l=s.id,d=s.groupId,c=d===void 0?"":d,u=s.name,g=s.type,m=s.url;this.hls.trigger(A.SUBTITLE_TRACK_SWITCH,{id:l,groupId:c,name:u,type:g,url:m});var v=this.switchParams(s.url,i==null?void 0:i.details);this.loadPlaylist(v)}else this.hls.trigger(A.SUBTITLE_TRACK_SWITCH,{id:t})}}else this.queuedDefaultTrack=t},e.onTextTracksChanged=function(){if(this.useTextTrackPolling||self.clearInterval(this.subtitlePollingInterval),this.media&&this.hls.config.renderTextTracksNatively){for(var t=-1,i=Vr(this.media.textTracks),r=0;r-1&&this.toggleTrackModes(this.trackId)}},{key:"subtitleTracks",get:function(){return this.tracksInGroup}},{key:"subtitleTrack",get:function(){return this.trackId},set:function(t){this.selectDefaultTrack=!1;var i=this.tracksInGroup?this.tracksInGroup[this.trackId]:void 0;this.setSubtitleTrack(t,i)}}]),n}(Tr);function Vr(o){for(var n=[],e=0;e "+i.src+")")},this.hls=e,this._initSourceBuffer(),this.registerListeners()}var n=o.prototype;return n.hasSourceTypes=function(){return this.getSourceBufferTypes().length>0||Object.keys(this.pendingTracks).length>0},n.destroy=function(){this.unregisterListeners(),this.details=null,this.lastMpegAudioChunk=null},n.registerListeners=function(){var e=this.hls;e.on(A.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(A.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(A.MANIFEST_LOADING,this.onManifestLoading,this),e.on(A.MANIFEST_PARSED,this.onManifestParsed,this),e.on(A.BUFFER_RESET,this.onBufferReset,this),e.on(A.BUFFER_APPENDING,this.onBufferAppending,this),e.on(A.BUFFER_CODECS,this.onBufferCodecs,this),e.on(A.BUFFER_EOS,this.onBufferEos,this),e.on(A.BUFFER_FLUSHING,this.onBufferFlushing,this),e.on(A.LEVEL_UPDATED,this.onLevelUpdated,this),e.on(A.FRAG_PARSED,this.onFragParsed,this),e.on(A.FRAG_CHANGED,this.onFragChanged,this)},n.unregisterListeners=function(){var e=this.hls;e.off(A.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(A.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(A.MANIFEST_LOADING,this.onManifestLoading,this),e.off(A.MANIFEST_PARSED,this.onManifestParsed,this),e.off(A.BUFFER_RESET,this.onBufferReset,this),e.off(A.BUFFER_APPENDING,this.onBufferAppending,this),e.off(A.BUFFER_CODECS,this.onBufferCodecs,this),e.off(A.BUFFER_EOS,this.onBufferEos,this),e.off(A.BUFFER_FLUSHING,this.onBufferFlushing,this),e.off(A.LEVEL_UPDATED,this.onLevelUpdated,this),e.off(A.FRAG_PARSED,this.onFragParsed,this),e.off(A.FRAG_CHANGED,this.onFragChanged,this)},n._initSourceBuffer=function(){this.sourceBuffer={},this.operationQueue=new gl(this.sourceBuffer),this.listeners={audio:[],video:[],audiovideo:[]},this.lastMpegAudioChunk=null},n.onManifestLoading=function(){this.bufferCodecEventsExpected=this._bufferCodecEventsTotal=0,this.details=null},n.onManifestParsed=function(e,t){var i=2;(t.audio&&!t.video||!t.altAudio)&&(i=1),this.bufferCodecEventsExpected=this._bufferCodecEventsTotal=i,R.log(this.bufferCodecEventsExpected+" bufferCodec event(s) expected")},n.onMediaAttaching=function(e,t){var i=this.media=t.media;if(i&&Ya){var r=this.mediaSource=new Ya;r.addEventListener("sourceopen",this._onMediaSourceOpen),r.addEventListener("sourceended",this._onMediaSourceEnded),r.addEventListener("sourceclose",this._onMediaSourceClose),i.src=self.URL.createObjectURL(r),this._objectUrl=i.src,i.addEventListener("emptied",this._onMediaEmptied)}},n.onMediaDetaching=function(){var e=this.media,t=this.mediaSource,i=this._objectUrl;if(t){if(R.log("[buffer-controller]: media source detaching"),t.readyState==="open")try{t.endOfStream()}catch(r){R.warn("[buffer-controller]: onMediaDetaching: "+r.message+" while calling endOfStream")}this.onBufferReset(),t.removeEventListener("sourceopen",this._onMediaSourceOpen),t.removeEventListener("sourceended",this._onMediaSourceEnded),t.removeEventListener("sourceclose",this._onMediaSourceClose),e&&(e.removeEventListener("emptied",this._onMediaEmptied),i&&self.URL.revokeObjectURL(i),e.src===i?(e.removeAttribute("src"),e.load()):R.warn("[buffer-controller]: media.src was changed by a third party - skip cleanup")),this.mediaSource=null,this.media=null,this._objectUrl=null,this.bufferCodecEventsExpected=this._bufferCodecEventsTotal,this.pendingTracks={},this.tracks={}}this.hls.trigger(A.MEDIA_DETACHED,void 0)},n.onBufferReset=function(){var e=this;this.getSourceBufferTypes().forEach(function(t){var i=e.sourceBuffer[t];try{i&&(e.removeBufferListeners(t),e.mediaSource&&e.mediaSource.removeSourceBuffer(i),e.sourceBuffer[t]=void 0)}catch(r){R.warn("[buffer-controller]: Failed to reset the "+t+" buffer",r)}}),this._initSourceBuffer()},n.onBufferCodecs=function(e,t){var i=this,r=this.getSourceBufferTypes().length;Object.keys(t).forEach(function(a){if(r){var s=i.tracks[a];if(s&&typeof s.buffer.changeType=="function"){var l=t[a],d=l.id,c=l.codec,u=l.levelCodec,g=l.container,m=l.metadata,v=(s.levelCodec||s.codec).replace(ja,"$1"),y=(u||c).replace(ja,"$1");if(v!==y){var _=g+";codecs="+(u||c);i.appendChangeType(a,_),R.log("[buffer-controller]: switching codec "+v+" to "+y),i.tracks[a]={buffer:s.buffer,codec:c,container:g,levelCodec:u,metadata:m,id:d}}}}else i.pendingTracks[a]=t[a]}),r||(this.bufferCodecEventsExpected=Math.max(this.bufferCodecEventsExpected-1,0),this.mediaSource&&this.mediaSource.readyState==="open"&&this.checkPendingTracks())},n.appendChangeType=function(e,t){var i=this,r=this.operationQueue,a={execute:function(){var s=i.sourceBuffer[e];s&&(R.log("[buffer-controller]: changing "+e+" sourceBuffer type to "+t),s.changeType(t)),r.shiftAndExecuteNext(e)},onStart:function(){},onComplete:function(){},onError:function(s){R.warn("[buffer-controller]: Failed to change "+e+" SourceBuffer type",s)}};r.append(a,e)},n.onBufferAppending=function(e,t){var i=this,r=this.hls,a=this.operationQueue,s=this.tracks,l=t.data,d=t.type,c=t.frag,u=t.part,g=t.chunkMeta,m=g.buffering[d],v=self.performance.now();m.start=v;var y=c.stats.buffering,_=u?u.stats.buffering:null;y.start===0&&(y.start=v),_&&_.start===0&&(_.start=v);var b=s.audio,E=!1;d==="audio"&&(b==null?void 0:b.container)==="audio/mpeg"&&(E=!this.lastMpegAudioChunk||g.id===1||this.lastMpegAudioChunk.sn!==g.sn,this.lastMpegAudioChunk=g);var S=c.start,C={execute:function(){if(m.executeStart=self.performance.now(),E){var L=i.sourceBuffer[d];if(L){var I=S-L.timestampOffset;Math.abs(I)>=.1&&(R.log("[buffer-controller]: Updating audio SourceBuffer timestampOffset to "+S+" (delta: "+I+") sn: "+c.sn+")"),L.timestampOffset=S)}}i.appendExecutor(l,d)},onStart:function(){},onComplete:function(){var L=self.performance.now();m.executeEnd=m.end=L,y.first===0&&(y.first=L),_&&_.first===0&&(_.first=L);var I=i.sourceBuffer,P={};for(var N in I)P[N]=Ae.getBuffered(I[N]);i.appendError=0,i.hls.trigger(A.BUFFER_APPENDED,{type:d,frag:c,part:u,chunkMeta:g,parent:c.type,timeRanges:P})},onError:function(L){R.error("[buffer-controller]: Error encountered while trying to append to the "+d+" SourceBuffer",L);var I={type:ne.MEDIA_ERROR,parent:c.type,details:O.BUFFER_APPEND_ERROR,frag:c,part:u,chunkMeta:g,error:L,err:L,fatal:!1};L.code===DOMException.QUOTA_EXCEEDED_ERR?I.details=O.BUFFER_FULL_ERROR:(i.appendError++,I.details=O.BUFFER_APPEND_ERROR,i.appendError>r.config.appendErrorMaxRetry&&(R.error("[buffer-controller]: Failed "+r.config.appendErrorMaxRetry+" times to append segment in sourceBuffer"),I.fatal=!0)),r.trigger(A.ERROR,I)}};a.append(C,d)},n.onBufferFlushing=function(e,t){var i=this,r=this.operationQueue,a=function(s){return{execute:i.removeExecutor.bind(i,s,t.startOffset,t.endOffset),onStart:function(){},onComplete:function(){i.hls.trigger(A.BUFFER_FLUSHED,{type:s})},onError:function(l){R.warn("[buffer-controller]: Failed to remove from "+s+" SourceBuffer",l)}}};t.type?r.append(a(t.type),t.type):this.getSourceBufferTypes().forEach(function(s){r.append(a(s),s)})},n.onFragParsed=function(e,t){var i=this,r=t.frag,a=t.part,s=[],l=a?a.elementaryStreams:r.elementaryStreams;l[ir]?s.push("audiovideo"):(l[Be]&&s.push("audio"),l[Ze]&&s.push("video")),s.length===0&&R.warn("Fragments must have at least one ElementaryStreamType set. type: "+r.type+" level: "+r.level+" sn: "+r.sn),this.blockBuffers(function(){var d=self.performance.now();r.stats.buffering.end=d,a&&(a.stats.buffering.end=d);var c=a?a.stats:r.stats;i.hls.trigger(A.FRAG_BUFFERED,{frag:r,part:a,stats:c,id:r.type})},s)},n.onFragChanged=function(e,t){this.flushBackBuffer()},n.onBufferEos=function(e,t){var i=this;this.getSourceBufferTypes().reduce(function(r,a){var s=i.sourceBuffer[a];return!s||t.type&&t.type!==a||(s.ending=!0,s.ended||(s.ended=!0,R.log("[buffer-controller]: "+a+" sourceBuffer now EOS"))),r&&!(s&&!s.ended)},!0)&&(R.log("[buffer-controller]: Queueing mediaSource.endOfStream()"),this.blockBuffers(function(){i.getSourceBufferTypes().forEach(function(a){var s=i.sourceBuffer[a];s&&(s.ending=!1)});var r=i.mediaSource;r&&r.readyState==="open"?(R.log("[buffer-controller]: Calling mediaSource.endOfStream()"),r.endOfStream()):r&&R.info("[buffer-controller]: Could not call mediaSource.endOfStream(). mediaSource.readyState: "+r.readyState)}))},n.onLevelUpdated=function(e,t){var i=t.details;i.fragments.length&&(this.details=i,this.getSourceBufferTypes().length?this.blockBuffers(this.updateMediaElementDuration.bind(this)):this.updateMediaElementDuration())},n.flushBackBuffer=function(){var e=this.hls,t=this.details,i=this.media,r=this.sourceBuffer;if(i&&t!==null){var a=this.getSourceBufferTypes();if(a.length){var s=t.live&&e.config.liveBackBufferLength!==null?e.config.liveBackBufferLength:e.config.backBufferLength;if(ie(s)&&!(s<0)){var l=i.currentTime,d=t.levelTargetDuration,c=Math.max(s,d),u=Math.floor(l/d)*d-c;a.forEach(function(g){var m=r[g];if(m){var v=Ae.getBuffered(m);if(v.length>0&&u>v.start(0)){if(e.trigger(A.BACK_BUFFER_REACHED,{bufferEnd:u}),t.live)e.trigger(A.LIVE_BACK_BUFFER_REACHED,{bufferEnd:u});else if(m.ended&&v.end(v.length-1)-l<2*d)return void R.info("[buffer-controller]: Cannot flush "+g+" back buffer while SourceBuffer is in ended state");e.trigger(A.BUFFER_FLUSHING,{startOffset:0,endOffset:u,type:g})}}})}}}},n.updateMediaElementDuration=function(){if(this.details&&this.media&&this.mediaSource&&this.mediaSource.readyState==="open"){var e=this.details,t=this.hls,i=this.media,r=this.mediaSource,a=e.fragments[0].start+e.totalduration,s=i.duration,l=ie(r.duration)?r.duration:0;e.live&&t.config.liveDurationInfinity?(R.log("[buffer-controller]: Media Source duration is set to Infinity"),r.duration=1/0,this.updateSeekableRange(e)):(a>l&&a>s||!ie(s))&&(R.log("[buffer-controller]: Updating Media Source duration to "+a.toFixed(3)),r.duration=a)}},n.updateSeekableRange=function(e){var t=this.mediaSource,i=e.fragments;if(i.length&&e.live&&t!=null&&t.setLiveSeekableRange){var r=Math.max(0,i[0].start),a=Math.max(r,r+e.totalduration);t.setLiveSeekableRange(r,a)}},n.checkPendingTracks=function(){var e=this.bufferCodecEventsExpected,t=this.operationQueue,i=this.pendingTracks,r=Object.keys(i).length;if(r&&!e||r===2){this.createSourceBuffers(i),this.pendingTracks={};var a=this.getSourceBufferTypes();if(a.length)this.hls.trigger(A.BUFFER_CREATED,{tracks:this.tracks}),a.forEach(function(l){t.executeNext(l)});else{var s=new Error("could not create source buffer for media codec(s)");this.hls.trigger(A.ERROR,{type:ne.MEDIA_ERROR,details:O.BUFFER_INCOMPATIBLE_CODECS_ERROR,fatal:!0,error:s,reason:s.message})}}},n.createSourceBuffers=function(e){var t=this.sourceBuffer,i=this.mediaSource;if(!i)throw Error("createSourceBuffers called when mediaSource was null");for(var r in e)if(!t[r]){var a=e[r];if(!a)throw Error("source buffer exists for track "+r+", however track does not");var s=a.levelCodec||a.codec,l=a.container+";codecs="+s;R.log("[buffer-controller]: creating sourceBuffer("+l+")");try{var d=t[r]=i.addSourceBuffer(l),c=r;this.addBufferListener(c,"updatestart",this._onSBUpdateStart),this.addBufferListener(c,"updateend",this._onSBUpdateEnd),this.addBufferListener(c,"error",this._onSBUpdateError),this.tracks[r]={buffer:d,codec:s,container:a.container,levelCodec:a.levelCodec,metadata:a.metadata,id:a.id}}catch(u){R.error("[buffer-controller]: error while trying to add sourceBuffer: "+u.message),this.hls.trigger(A.ERROR,{type:ne.MEDIA_ERROR,details:O.BUFFER_ADD_CODEC_ERROR,fatal:!1,error:u,mimeType:l})}}},n._onSBUpdateStart=function(e){this.operationQueue.current(e).onStart()},n._onSBUpdateEnd=function(e){var t=this.operationQueue;t.current(e).onComplete(),t.shiftAndExecuteNext(e)},n._onSBUpdateError=function(e,t){var i=new Error(e+" SourceBuffer error");R.error("[buffer-controller]: "+i,t),this.hls.trigger(A.ERROR,{type:ne.MEDIA_ERROR,details:O.BUFFER_APPENDING_ERROR,error:i,fatal:!1});var r=this.operationQueue.current(e);r&&r.onError(t)},n.removeExecutor=function(e,t,i){var r=this.media,a=this.mediaSource,s=this.operationQueue,l=this.sourceBuffer[e];if(!r||!a||!l)return R.warn("[buffer-controller]: Attempting to remove from the "+e+" SourceBuffer, but it does not exist"),void s.shiftAndExecuteNext(e);var d=ie(r.duration)?r.duration:1/0,c=ie(a.duration)?a.duration:1/0,u=Math.max(0,t),g=Math.min(i,d,c);g>u&&!l.ending?(l.ended=!1,R.log("[buffer-controller]: Removing ["+u+","+g+"] from the "+e+" SourceBuffer"),l.remove(u,g)):s.shiftAndExecuteNext(e)},n.appendExecutor=function(e,t){var i=this.operationQueue,r=this.sourceBuffer[t];if(!r)return R.warn("[buffer-controller]: Attempting to append to the "+t+" SourceBuffer, but it does not exist"),void i.shiftAndExecuteNext(t);r.ended=!1,r.appendBuffer(e)},n.blockBuffers=function(e,t){var i=this;if(t===void 0&&(t=this.getSourceBufferTypes()),!t.length)return R.log("[buffer-controller]: Blocking operation requested, but no SourceBuffers exist"),void Promise.resolve().then(e);var r=this.operationQueue,a=t.map(function(s){return r.appendBlocker(s)});Promise.all(a).then(function(){e(),t.forEach(function(s){var l=i.sourceBuffer[s];l!=null&&l.updating||r.shiftAndExecuteNext(s)})})},n.getSourceBufferTypes=function(){return Object.keys(this.sourceBuffer)},n.addBufferListener=function(e,t,i){var r=this.sourceBuffer[e];if(r){var a=i.bind(this,e);this.listeners[e].push({event:t,listener:a}),r.addEventListener(t,a)}},n.removeBufferListeners=function(e){var t=this.sourceBuffer[e];t&&this.listeners[e].forEach(function(i){t.removeEventListener(i.event,i.listener)})},o}(),qa={42:225,92:233,94:237,95:243,96:250,123:231,124:247,125:209,126:241,127:9608,128:174,129:176,130:189,131:191,132:8482,133:162,134:163,135:9834,136:224,137:32,138:232,139:226,140:234,141:238,142:244,143:251,144:193,145:201,146:211,147:218,148:220,149:252,150:8216,151:161,152:42,153:8217,154:9473,155:169,156:8480,157:8226,158:8220,159:8221,160:192,161:194,162:199,163:200,164:202,165:203,166:235,167:206,168:207,169:239,170:212,171:217,172:249,173:219,174:171,175:187,176:195,177:227,178:205,179:204,180:236,181:210,182:242,183:213,184:245,185:123,186:125,187:92,188:94,189:95,190:124,191:8764,192:196,193:228,194:214,195:246,196:223,197:165,198:164,199:9475,200:197,201:229,202:216,203:248,204:9487,205:9491,206:9495,207:9499},$a=function(o){var n=o;return qa.hasOwnProperty(o)&&(n=qa[o]),String.fromCharCode(n)},Bt=15,yt=100,vl={17:1,18:3,21:5,22:7,23:9,16:11,19:12,20:14},bl={17:2,18:4,21:6,22:8,23:10,19:13,20:15},yl={25:1,26:3,29:5,30:7,31:9,24:11,27:12,28:14},wl={25:2,26:4,29:6,30:8,31:10,27:13,28:15},El=["white","green","blue","cyan","red","yellow","magenta","black","transparent"],Al=function(){function o(){this.time=null,this.verboseLevel=0}return o.prototype.log=function(n,e){if(this.verboseLevel>=n){var t=typeof e=="function"?e():e;R.log(this.time+" ["+n+"] "+t)}},o}(),Nt=function(o){for(var n=[],e=0;eyt&&(this.logger.log(3,"Too large cursor position "+this.pos),this.pos=yt)},n.moveCursor=function(e){var t=this.pos+e;if(e>1)for(var i=this.pos+1;i=144&&this.backSpace();var i=$a(e);this.pos>=yt?this.logger.log(0,function(){return"Cannot insert "+e.toString(16)+" ("+i+") at position "+t.pos+". Skipping it!"}):(this.chars[this.pos].setChar(i,this.currPenState),this.moveCursor(1))},n.clearFromPos=function(e){var t;for(t=e;t0&&(i=e?"["+t.join(" | ")+"]":t.join(` +`)),i},n.getTextAndFormat=function(){return this.rows},o}(),Wa=function(){function o(e,t,i){this.chNr=void 0,this.outputFilter=void 0,this.mode=void 0,this.verbose=void 0,this.displayedMemory=void 0,this.nonDisplayedMemory=void 0,this.lastOutputScreen=void 0,this.currRollUpRow=void 0,this.writeScreen=void 0,this.cueStartTime=void 0,this.logger=void 0,this.chNr=e,this.outputFilter=t,this.mode=null,this.verbose=0,this.displayedMemory=new zr(i),this.nonDisplayedMemory=new zr(i),this.lastOutputScreen=new zr(i),this.currRollUpRow=this.displayedMemory.rows[14],this.writeScreen=this.displayedMemory,this.mode=null,this.cueStartTime=null,this.logger=i}var n=o.prototype;return n.reset=function(){this.mode=null,this.displayedMemory.reset(),this.nonDisplayedMemory.reset(),this.lastOutputScreen.reset(),this.outputFilter.reset(),this.currRollUpRow=this.displayedMemory.rows[14],this.writeScreen=this.displayedMemory,this.mode=null,this.cueStartTime=null},n.getHandler=function(){return this.outputFilter},n.setHandler=function(e){this.outputFilter=e},n.setPAC=function(e){this.writeScreen.setPAC(e)},n.setBkgData=function(e){this.writeScreen.setBkgData(e)},n.setMode=function(e){e!==this.mode&&(this.mode=e,this.logger.log(2,function(){return"MODE="+e}),this.mode==="MODE_POP-ON"?this.writeScreen=this.nonDisplayedMemory:(this.writeScreen=this.displayedMemory,this.writeScreen.reset()),this.mode!=="MODE_ROLL-UP"&&(this.displayedMemory.nrRollUpRows=null,this.nonDisplayedMemory.nrRollUpRows=null),this.mode=e)},n.insertChars=function(e){for(var t=this,i=0;i=46,t.italics)t.foreground="white";else{var i=Math.floor(e/2)-16;t.foreground=["white","green","blue","cyan","red","yellow","magenta"][i]}this.logger.log(2,"MIDROW: "+JSON.stringify(t)),this.writeScreen.setPen(t)},n.outputDataUpdate=function(e){e===void 0&&(e=!1);var t=this.logger.time;t!==null&&this.outputFilter&&(this.cueStartTime!==null||this.displayedMemory.isEmpty()?this.displayedMemory.equals(this.lastOutputScreen)||(this.outputFilter.newCue(this.cueStartTime,t,this.lastOutputScreen),e&&this.outputFilter.dispatchCue&&this.outputFilter.dispatchCue(),this.cueStartTime=this.displayedMemory.isEmpty()?null:t):this.cueStartTime=t,this.lastOutputScreen.copy(this.displayedMemory))},n.cueSplitAtTime=function(e){this.outputFilter&&(this.displayedMemory.isEmpty()||(this.outputFilter.newCue&&this.outputFilter.newCue(this.cueStartTime,e,this.displayedMemory),this.cueStartTime=e))},o}(),Xa=function(){function o(e,t,i){this.channels=void 0,this.currentChannel=0,this.cmdHistory=void 0,this.logger=void 0;var r=new Al;this.channels=[null,new Wa(e,t,r),new Wa(e+1,i,r)],this.cmdHistory={a:null,b:null},this.logger=r}var n=o.prototype;return n.getHandler=function(e){return this.channels[e].getHandler()},n.setHandler=function(e,t){this.channels[e].setHandler(t)},n.addData=function(e,t){var i,r,a,s=!1;this.logger.time=e;for(var l=0;l ("+Nt([r,a])+")"),(i=this.parseCmd(r,a))||(i=this.parseMidrow(r,a)),i||(i=this.parsePAC(r,a)),i||(i=this.parseBackgroundAttributes(r,a)),!i&&(s=this.parseChars(r,a))){var d=this.currentChannel;d&&d>0?this.channels[d].insertChars(s):this.logger.log(2,"No channel found yet. TEXT-MODE?")}i||s||this.logger.log(2,"Couldn't parse cleaned data "+Nt([r,a])+" orig: "+Nt([t[l],t[l+1]]))}},n.parseCmd=function(e,t){var i=this.cmdHistory;if(!((e===20||e===28||e===21||e===29)&&t>=32&&t<=47||(e===23||e===31)&&t>=33&&t<=35))return!1;if(Ja(e,t,i))return Wt(null,null,i),this.logger.log(3,"Repeated command ("+Nt([e,t])+") is dropped"),!0;var r=e===20||e===21||e===23?1:2,a=this.channels[r];return e===20||e===21||e===28||e===29?t===32?a.ccRCL():t===33?a.ccBS():t===34?a.ccAOF():t===35?a.ccAON():t===36?a.ccDER():t===37?a.ccRU(2):t===38?a.ccRU(3):t===39?a.ccRU(4):t===40?a.ccFON():t===41?a.ccRDC():t===42?a.ccTR():t===43?a.ccRTD():t===44?a.ccEDM():t===45?a.ccCR():t===46?a.ccENM():t===47&&a.ccEOC():a.ccTO(t-32),Wt(e,t,i),this.currentChannel=r,!0},n.parseMidrow=function(e,t){var i=0;if((e===17||e===25)&&t>=32&&t<=47){if((i=e===17?1:2)!==this.currentChannel)return this.logger.log(0,"Mismatch channel in midrow parsing"),!1;var r=this.channels[i];return!!r&&(r.ccMIDROW(t),this.logger.log(3,"MIDROW ("+Nt([e,t])+")"),!0)}return!1},n.parsePAC=function(e,t){var i,r=this.cmdHistory;if(!((e>=17&&e<=23||e>=25&&e<=31)&&t>=64&&t<=127||(e===16||e===24)&&t>=64&&t<=95))return!1;if(Ja(e,t,r))return Wt(null,null,r),!0;var a=e<=23?1:2;i=t>=64&&t<=95?a===1?vl[e]:yl[e]:a===1?bl[e]:wl[e];var s=this.channels[a];return!!s&&(s.setPAC(this.interpretPAC(i,t)),Wt(e,t,r),this.currentChannel=a,!0)},n.interpretPAC=function(e,t){var i,r={color:null,italics:!1,indent:null,underline:!1,row:e};return i=t>95?t-96:t-64,r.underline=(1&i)==1,i<=13?r.color=["white","green","blue","cyan","red","yellow","magenta","white"][Math.floor(i/2)]:i<=15?(r.italics=!0,r.color="white"):r.indent=4*Math.floor((i-16)/2),r},n.parseChars=function(e,t){var i,r,a=null,s=null;if(e>=25?(i=2,s=e-8):(i=1,s=e),s>=17&&s<=19?(r=s===17?t+80:s===18?t+112:t+144,this.logger.log(2,"Special char '"+$a(r)+"' in channel "+i),a=[r]):e>=32&&e<=127&&(a=t===0?[e]:[e,t]),a){var l=Nt(a);this.logger.log(3,"Char codes = "+l.join(",")),Wt(e,t,this.cmdHistory)}return a},n.parseBackgroundAttributes=function(e,t){var i;if(!((e===16||e===24)&&t>=32&&t<=47||(e===23||e===31)&&t>=45&&t<=47))return!1;var r={};e===16||e===24?(i=Math.floor((t-32)/2),r.background=El[i],t%2==1&&(r.background=r.background+"_semi")):t===45?r.background="transparent":(r.foreground="black",t===47&&(r.underline=!0));var a=e<=23?1:2;return this.channels[a].setBkgData(r),Wt(e,t,this.cmdHistory),!0},n.reset=function(){for(var e=0;ee)&&(this.startTime=e),this.endTime=t,this.screen=i,this.timelineController.createCaptionsTrack(this.trackName)},n.reset=function(){this.cueRanges=[],this.startTime=null},o}(),Yr=function(){if(typeof self<"u"&&self.VTTCue)return self.VTTCue;var o=["","lr","rl"],n=["start","middle","end","left","right"];function e(a,s){if(typeof s!="string"||!Array.isArray(a))return!1;var l=s.toLowerCase();return!!~a.indexOf(l)&&l}function t(a){return e(n,a)}function i(a){for(var s=arguments.length,l=new Array(s>1?s-1:0),d=1;d100)throw new Error("Position must be between 0 and 100.");L=M,this.hasBeenReset=!0}})),Object.defineProperty(d,"positionAlign",i({},c,{get:function(){return I},set:function(M){var B=t(M);if(!B)throw new SyntaxError("An invalid or illegal string was specified.");I=B,this.hasBeenReset=!0}})),Object.defineProperty(d,"size",i({},c,{get:function(){return P},set:function(M){if(M<0||M>100)throw new Error("Size must be between 0 and 100.");P=M,this.hasBeenReset=!0}})),Object.defineProperty(d,"align",i({},c,{get:function(){return N},set:function(M){var B=t(M);if(!B)throw new SyntaxError("An invalid or illegal string was specified.");N=B,this.hasBeenReset=!0}})),d.displayState=void 0}return r.prototype.getCueAsHTML=function(){return self.WebVTT.convertCueToDOMTree(self,this.text)},r}(),xl=function(){function o(){}return o.prototype.decode=function(n,e){if(!n)return"";if(typeof n!="string")throw new Error("Error - expected string data.");return decodeURIComponent(encodeURIComponent(n))},o}();function Za(o){function n(t,i,r,a){return 3600*(0|t)+60*(0|i)+(0|r)+parseFloat(a||0)}var e=o.match(/^(?:(\d+):)?(\d{2}):(\d{2})(\.\d+)?/);return e?parseFloat(e[2])>59?n(e[2],e[3],0,e[4]):n(e[1],e[2],e[3],e[4]):null}var Tl=function(){function o(){this.values=Object.create(null)}var n=o.prototype;return n.set=function(e,t){this.get(e)||t===""||(this.values[e]=t)},n.get=function(e,t,i){return i?this.has(e)?this.values[e]:t[i]:this.has(e)?this.values[e]:t},n.has=function(e){return e in this.values},n.alt=function(e,t,i){for(var r=0;r=0&&i<=100)return this.set(e,i),!0}return!1},o}();function eo(o,n,e,t){var i=t?o.split(t):[o];for(var r in i)if(typeof i[r]=="string"){var a=i[r].split(e);a.length===2&&n(a[0],a[1])}}var jr=new Yr(0,0,""),Hi=jr.align==="middle"?"middle":"center";function Cl(o,n,e){var t=o;function i(){var a=Za(o);if(a===null)throw new Error("Malformed timestamp: "+t);return o=o.replace(/^[^\sa-zA-Z-]+/,""),a}function r(){o=o.replace(/^\s+/,"")}if(r(),n.startTime=i(),r(),o.slice(0,3)!=="-->")throw new Error("Malformed time stamp (time stamps must be separated by '-->'): "+t);o=o.slice(3),r(),n.endTime=i(),r(),function(a,s){var l=new Tl;eo(a,function(u,g){var m;switch(u){case"region":for(var v=e.length-1;v>=0;v--)if(e[v].id===g){l.set(u,e[v].region);break}break;case"vertical":l.alt(u,g,["rl","lr"]);break;case"line":m=g.split(","),l.integer(u,m[0]),l.percent(u,m[0])&&l.set("snapToLines",!1),l.alt(u,m[0],["auto"]),m.length===2&&l.alt("lineAlign",m[1],["start",Hi,"end"]);break;case"position":m=g.split(","),l.percent(u,m[0]),m.length===2&&l.alt("positionAlign",m[1],["start",Hi,"end","line-left","line-right","auto"]);break;case"size":l.percent(u,g);break;case"align":l.alt(u,g,["start",Hi,"end","left","right"])}},/:/,/\s/),s.region=l.get("region",null),s.vertical=l.get("vertical","");var d=l.get("line","auto");d==="auto"&&jr.line===-1&&(d=-1),s.line=d,s.lineAlign=l.get("lineAlign","start"),s.snapToLines=l.get("snapToLines",!0),s.size=l.get("size",100),s.align=l.get("align",Hi);var c=l.get("position","auto");c==="auto"&&jr.position===50&&(c=s.align==="start"||s.align==="left"?0:s.align==="end"||s.align==="right"?100:50),s.position=c}(o,n)}function to(o){return o.replace(//gi,` +`)}var Sl=function(){function o(){this.state="INITIAL",this.buffer="",this.decoder=new xl,this.regionList=[],this.cue=null,this.oncue=void 0,this.onparsingerror=void 0,this.onflush=void 0}var n=o.prototype;return n.parse=function(e){var t=this;function i(){var d=t.buffer,c=0;for(d=to(d);c")===-1){t.cue.id=r;continue}case"CUE":if(!t.cue){t.state="BADCUE";continue}try{Cl(r,t.cue,t.regionList)}catch{t.cue=null,t.state="BADCUE";continue}t.state="CUETEXT";continue;case"CUETEXT":var l=r.indexOf("-->")!==-1;if(!r||l&&(s=!0)){t.oncue&&t.cue&&t.oncue(t.cue),t.cue=null,t.state="ID";continue}if(t.cue===null)continue;t.cue.text&&(t.cue.text+=` +`),t.cue.text+=r;continue;case"BADCUE":r||(t.state="ID")}}}catch{t.state==="CUETEXT"&&t.cue&&t.oncue&&t.oncue(t.cue),t.cue=null,t.state=t.state==="INITIAL"?"BADWEBVTT":"BADCUE"}return this},n.flush=function(){var e=this;try{if((e.cue||e.state==="HEADER")&&(e.buffer+=` + +`,e.parse()),e.state==="INITIAL"||e.state==="BADWEBVTT")throw new Error("Malformed WebVTT signature.")}catch(t){e.onparsingerror&&e.onparsingerror(t)}return e.onflush&&e.onflush(),this},o}(),Ll=/\r\n|\n\r|\n|\r/g,qr=function(o,n,e){return e===void 0&&(e=0),o.slice(e,e+n.length)===n},$r=function(o){for(var n=5381,e=o.length;e;)n=33*n^o.charCodeAt(--e);return(n>>>0).toString()};function Qr(o,n,e){return $r(o.toString())+$r(n.toString())+$r(e)}function Dl(o,n,e,t,i,r,a){var s,l,d,c=new Sl,u=at(new Uint8Array(o)).trim().replace(Ll,` +`).split(` +`),g=[],m=n?(s=n.baseTime,(l=n.timescale)===void 0&&(l=1),Mr(s,9e4,1/l)):0,v="00:00.000",y=0,_=0,b=!0;c.oncue=function(E){var S=e[t],C=e.ccOffset,L=(y-m)/9e4;if(S!=null&&S.new&&(_!==void 0?C=e.ccOffset=S.start:function(M,B,Y){var K=M[B],Q=M[K.prevCC];if(!Q||!Q.new&&K.new)return M.ccOffset=M.presentationOffset=K.start,void(K.new=!1);for(;(re=Q)!=null&&re.new;){var re;M.ccOffset+=K.start-Q.start,K.new=!1,Q=M[(K=Q).prevCC]}M.presentationOffset=Y}(e,t,L)),L){if(!n)return void(d=new Error("Missing initPTS for VTT MPEGTS"));C=L-e.presentationOffset}var I=E.endTime-E.startTime,P=Qe(9e4*(E.startTime+C-_),9e4*i)/9e4;E.startTime=Math.max(P,0),E.endTime=Math.max(P+I,0);var N=E.text.trim();E.text=decodeURIComponent(encodeURIComponent(N)),E.id||(E.id=Qr(E.startTime,E.endTime,N)),E.endTime>0&&g.push(E)},c.onparsingerror=function(E){d=E},c.onflush=function(){d?a(d):r(g)},u.forEach(function(E){if(b){if(qr(E,"X-TIMESTAMP-MAP=")){b=!1,E.slice(16).split(",").forEach(function(S){qr(S,"LOCAL:")?v=S.slice(6):qr(S,"MPEGTS:")&&(y=parseInt(S.slice(7)))});try{_=function(S){var C=parseInt(S.slice(-3)),L=parseInt(S.slice(-6,-4)),I=parseInt(S.slice(-9,-7)),P=S.length>9?parseInt(S.substring(0,S.indexOf(":"))):0;if(!(ie(C)&&ie(L)&&ie(I)&&ie(P)))throw Error("Malformed X-TIMESTAMP-MAP: Local:"+S);return C+=1e3*L,(C+=6e4*I)+36e5*P}(v)/1e3}catch(S){d=S}return}E===""&&(b=!1)}c.parse(E+` +`)}),c.flush()}var Wr="stpp.ttml.im1t",io=/^(\d{2,}):(\d{2}):(\d{2}):(\d{2})\.?(\d+)?$/,ro=/^(\d*(?:\.\d*)?)(h|m|s|ms|f|t)$/,Rl={left:"start",center:"center",right:"end",start:"start",end:"end"};function no(o,n,e,t){var i=ge(new Uint8Array(o),["mdat"]);if(i.length!==0){var r,a,s,l,d=i.map(function(u){return at(u)}),c=(r=n.baseTime,a=1,(s=n.timescale)===void 0&&(s=1),l===void 0&&(l=!1),Mr(r,a,1/s,l));try{d.forEach(function(u){return e(function(g,m){var v=new DOMParser().parseFromString(g,"text/xml").getElementsByTagName("tt")[0];if(!v)throw new Error("Invalid ttml");var y={frameRate:30,subFrameRate:1,frameRateMultiplier:0,tickRate:0},_=Object.keys(y).reduce(function(L,I){return L[I]=v.getAttribute("ttp:"+I)||y[I],L},{}),b=v.getAttribute("xml:space")!=="preserve",E=ao(Xr(v,"styling","style")),S=ao(Xr(v,"layout","region")),C=Xr(v,"body","[begin]");return[].map.call(C,function(L){var I=oo(L,b);if(!I||!L.hasAttribute("begin"))return null;var P=Zr(L.getAttribute("begin"),_),N=Zr(L.getAttribute("dur"),_),M=Zr(L.getAttribute("end"),_);if(P===null)throw so(L);if(M===null){if(N===null)throw so(L);M=P+N}var B=new Yr(P-m,M-m,I);B.id=Qr(B.startTime,B.endTime,B.text);var Y=function(re,W,J){var ee="http://www.w3.org/ns/ttml#styling",Z=null,ae=["displayAlign","textAlign","color","backgroundColor","fontSize","fontFamily"],he=re!=null&&re.hasAttribute("style")?re.getAttribute("style"):null;return he&&J.hasOwnProperty(he)&&(Z=J[he]),ae.reduce(function(fe,ye){var Ge=Jr(W,ee,ye)||Jr(re,ee,ye)||Jr(Z,ee,ye);return Ge&&(fe[ye]=Ge),fe},{})}(S[L.getAttribute("region")],E[L.getAttribute("style")],E),K=Y.textAlign;if(K){var Q=Rl[K];Q&&(B.lineAlign=Q),B.align=K}return F(B,Y),B}).filter(function(L){return L!==null})}(u,c))})}catch(u){t(u)}}else t(new Error("Could not parse IMSC1 mdat"))}function Xr(o,n,e){var t=o.getElementsByTagName(n)[0];return t?[].slice.call(t.querySelectorAll(e)):[]}function ao(o){return o.reduce(function(n,e){var t=e.getAttribute("xml:id");return t&&(n[t]=e),n},{})}function oo(o,n){return[].slice.call(o.childNodes).reduce(function(e,t,i){var r;return t.nodeName==="br"&&i?e+` +`:(r=t.childNodes)!=null&&r.length?oo(t,n):n?e+t.textContent.trim().replace(/\s+/g," "):e+t.textContent},"")}function Jr(o,n,e){return o&&o.hasAttributeNS(n,e)?o.getAttributeNS(n,e):null}function so(o){return new Error("Could not parse ttml timestamp "+o)}function Zr(o,n){if(!o)return null;var e=Za(o);return e===null&&(io.test(o)?e=function(t,i){var r=io.exec(t),a=(0|r[4])+(0|r[5])/i.subFrameRate;return 3600*(0|r[1])+60*(0|r[2])+(0|r[3])+a/i.frameRate}(o,n):ro.test(o)&&(e=function(t,i){var r=ro.exec(t),a=Number(r[1]);switch(r[2]){case"h":return 3600*a;case"m":return 60*a;case"ms":return 1e3*a;case"f":return a/i.frameRate;case"t":return a/i.tickRate}return a}(o,n))),e}var Il=function(){function o(e){if(this.hls=void 0,this.media=null,this.config=void 0,this.enabled=!0,this.Cues=void 0,this.textTracks=[],this.tracks=[],this.initPTS=[],this.unparsedVttFrags=[],this.captionsTracks={},this.nonNativeCaptionsTracks={},this.cea608Parser1=void 0,this.cea608Parser2=void 0,this.lastSn=-1,this.lastPartIndex=-1,this.prevCC=-1,this.vttCCs={ccOffset:0,presentationOffset:0,0:{start:0,prevCC:-1,new:!0}},this.captionsProperties=void 0,this.hls=e,this.config=e.config,this.Cues=e.config.cueHandler,this.captionsProperties={textTrack1:{label:this.config.captionsTextTrack1Label,languageCode:this.config.captionsTextTrack1LanguageCode},textTrack2:{label:this.config.captionsTextTrack2Label,languageCode:this.config.captionsTextTrack2LanguageCode},textTrack3:{label:this.config.captionsTextTrack3Label,languageCode:this.config.captionsTextTrack3LanguageCode},textTrack4:{label:this.config.captionsTextTrack4Label,languageCode:this.config.captionsTextTrack4LanguageCode}},this.config.enableCEA708Captions){var t=new Gi(this,"textTrack1"),i=new Gi(this,"textTrack2"),r=new Gi(this,"textTrack3"),a=new Gi(this,"textTrack4");this.cea608Parser1=new Xa(1,t,i),this.cea608Parser2=new Xa(3,r,a)}e.on(A.MEDIA_ATTACHING,this.onMediaAttaching,this),e.on(A.MEDIA_DETACHING,this.onMediaDetaching,this),e.on(A.MANIFEST_LOADING,this.onManifestLoading,this),e.on(A.MANIFEST_LOADED,this.onManifestLoaded,this),e.on(A.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),e.on(A.FRAG_LOADING,this.onFragLoading,this),e.on(A.FRAG_LOADED,this.onFragLoaded,this),e.on(A.FRAG_PARSING_USERDATA,this.onFragParsingUserdata,this),e.on(A.FRAG_DECRYPTED,this.onFragDecrypted,this),e.on(A.INIT_PTS_FOUND,this.onInitPtsFound,this),e.on(A.SUBTITLE_TRACKS_CLEARED,this.onSubtitleTracksCleared,this),e.on(A.BUFFER_FLUSHING,this.onBufferFlushing,this)}var n=o.prototype;return n.destroy=function(){var e=this.hls;e.off(A.MEDIA_ATTACHING,this.onMediaAttaching,this),e.off(A.MEDIA_DETACHING,this.onMediaDetaching,this),e.off(A.MANIFEST_LOADING,this.onManifestLoading,this),e.off(A.MANIFEST_LOADED,this.onManifestLoaded,this),e.off(A.SUBTITLE_TRACKS_UPDATED,this.onSubtitleTracksUpdated,this),e.off(A.FRAG_LOADING,this.onFragLoading,this),e.off(A.FRAG_LOADED,this.onFragLoaded,this),e.off(A.FRAG_PARSING_USERDATA,this.onFragParsingUserdata,this),e.off(A.FRAG_DECRYPTED,this.onFragDecrypted,this),e.off(A.INIT_PTS_FOUND,this.onInitPtsFound,this),e.off(A.SUBTITLE_TRACKS_CLEARED,this.onSubtitleTracksCleared,this),e.off(A.BUFFER_FLUSHING,this.onBufferFlushing,this),this.hls=this.config=this.cea608Parser1=this.cea608Parser2=null},n.addCues=function(e,t,i,r,a){for(var s,l,d,c,u=!1,g=a.length;g--;){var m=a[g],v=(s=m[0],l=m[1],d=t,c=i,Math.min(l,c)-Math.max(s,d));if(v>=0&&(m[0]=Math.min(m[0],t),m[1]=Math.max(m[1],i),u=!0,v/(i-t)>.5))return}if(u||a.push([t,i]),this.config.renderTextTracksNatively){var y=this.captionsTracks[e];this.Cues.newCue(y,t,i,r)}else{var _=this.Cues.newCue(null,t,i,r);this.hls.trigger(A.CUES_PARSED,{type:"captions",cues:_,track:e})}},n.onInitPtsFound=function(e,t){var i=this,r=t.frag,a=t.id,s=t.initPTS,l=t.timescale,d=this.unparsedVttFrags;a==="main"&&(this.initPTS[r.cc]={baseTime:s,timescale:l}),d.length&&(this.unparsedVttFrags=[],d.forEach(function(c){i.onFragLoaded(A.FRAG_LOADED,c)}))},n.getExistingTrack=function(e){var t=this.media;if(t)for(var i=0;ir.cc||c.trigger(A.SUBTITLE_FRAG_PROCESSED,{success:!1,frag:r,error:u})})}else l.push(e)},n._fallbackToIMSC1=function(e,t){var i=this,r=this.tracks[e.level];r.textCodec||no(t,this.initPTS[e.cc],function(){r.textCodec=Wr,i._parseIMSC1(e,t)},function(){r.textCodec="wvtt"})},n._appendCues=function(e,t){var i=this.hls;if(this.config.renderTextTracksNatively){var r=this.textTracks[t];if(!r||r.mode==="disabled")return;e.forEach(function(l){return aa(r,l)})}else{var a=this.tracks[t];if(!a)return;var s=a.default?"default":"subtitles"+t;i.trigger(A.CUES_PARSED,{type:"subtitles",cues:e,track:s})}},n.onFragDecrypted=function(e,t){t.frag.type===kt&&this.onFragLoaded(A.FRAG_LOADED,t)},n.onSubtitleTracksCleared=function(){this.tracks=[],this.captionsTracks={}},n.onFragParsingUserdata=function(e,t){var i=this.cea608Parser1,r=this.cea608Parser2;if(this.enabled&&i&&r){var a=t.frag,s=t.samples;if(a.type!==ve||this.closedCaptionsForLevel(a)!=="NONE")for(var l=0;l0&&this.mediaWidth>0){var e=this.hls.levels;if(e.length){var t=this.hls;t.autoLevelCapping=this.getMaxLevel(e.length-1),t.autoLevelCapping>this.autoLevelCapping&&this.streamController&&this.streamController.nextLevelSwitch(),this.autoLevelCapping=t.autoLevelCapping}}},n.getMaxLevel=function(e){var t=this,i=this.hls.levels;if(!i.length)return-1;var r=i.filter(function(a,s){return t.isLevelAllowed(a)&&s<=e});return this.clientRect=null,o.getMaxLevelByMediaSize(r,this.mediaWidth,this.mediaHeight)},n.startCapping=function(){this.timer||(this.autoLevelCapping=Number.POSITIVE_INFINITY,this.hls.firstLevel=this.getMaxLevel(this.firstLevel),self.clearInterval(this.timer),this.timer=self.setInterval(this.detectPlayerSize.bind(this),1e3),this.detectPlayerSize())},n.stopCapping=function(){this.restrictedLevels=[],this.firstLevel=-1,this.autoLevelCapping=Number.POSITIVE_INFINITY,this.timer&&(self.clearInterval(this.timer),this.timer=void 0)},n.getDimensions=function(){if(this.clientRect)return this.clientRect;var e=this.media,t={width:0,height:0};if(e){var i=e.getBoundingClientRect();t.width=i.width,t.height=i.height,t.width||t.height||(t.width=i.right-i.left||e.width||0,t.height=i.bottom-i.top||e.height||0)}return this.clientRect=t,t},n.isLevelAllowed=function(e){return!this.restrictedLevels.some(function(t){return e.bitrate===t.bitrate&&e.width===t.width&&e.height===t.height})},o.getMaxLevelByMediaSize=function(e,t,i){if(e==null||!e.length)return-1;for(var r,a,s=e.length-1,l=0;l=t||d.height>=i)&&(r=d,!(a=e[l+1])||r.width!==a.width||r.height!==a.height)){s=l;break}}return s},D(o,[{key:"mediaWidth",get:function(){return this.getDimensions().width*this.contentScaleFactor}},{key:"mediaHeight",get:function(){return this.getDimensions().height*this.contentScaleFactor}},{key:"contentScaleFactor",get:function(){var e=1;if(!this.hls.config.ignoreDevicePixelRatio)try{e=self.devicePixelRatio}catch{}return e}}]),o}(),Ml=function(){function o(e){this.hls=void 0,this.isVideoPlaybackQualityAvailable=!1,this.timer=void 0,this.media=null,this.lastTime=void 0,this.lastDroppedFrames=0,this.lastDecodedFrames=0,this.streamController=void 0,this.hls=e,this.registerListeners()}var n=o.prototype;return n.setStreamController=function(e){this.streamController=e},n.registerListeners=function(){this.hls.on(A.MEDIA_ATTACHING,this.onMediaAttaching,this)},n.unregisterListeners=function(){this.hls.off(A.MEDIA_ATTACHING,this.onMediaAttaching,this)},n.destroy=function(){this.timer&&clearInterval(this.timer),this.unregisterListeners(),this.isVideoPlaybackQualityAvailable=!1,this.media=null},n.onMediaAttaching=function(e,t){var i=this.hls.config;if(i.capLevelOnFPSDrop){var r=t.media instanceof self.HTMLVideoElement?t.media:null;this.media=r,r&&typeof r.getVideoPlaybackQuality=="function"&&(this.isVideoPlaybackQualityAvailable=!0),self.clearInterval(this.timer),this.timer=self.setInterval(this.checkFPSInterval.bind(this),i.fpsDroppedMonitoringPeriod)}},n.checkFPS=function(e,t,i){var r=performance.now();if(t){if(this.lastTime){var a=r-this.lastTime,s=i-this.lastDroppedFrames,l=t-this.lastDecodedFrames,d=1e3*s/a,c=this.hls;if(c.trigger(A.FPS_DROP,{currentDropped:s,currentDecoded:l,totalDroppedFrames:i}),d>0&&s>c.config.fpsDroppedMonitoringThreshold*l){var u=c.currentLevel;R.warn("drop FPS ratio greater than max allowed value for currentLevel: "+u),u>0&&(c.autoLevelCapping===-1||c.autoLevelCapping>=u)&&(u-=1,c.trigger(A.FPS_DROP_LEVEL_CAPPING,{level:u,droppedLevel:c.currentLevel}),c.autoLevelCapping=u,this.streamController.nextLevelSwitch())}}this.lastTime=r,this.lastDroppedFrames=i,this.lastDecodedFrames=t}},n.checkFPSInterval=function(){var e=this.media;if(e)if(this.isVideoPlaybackQualityAvailable){var t=e.getVideoPlaybackQuality();this.checkFPS(e,t.totalVideoFrames,t.droppedVideoFrames)}else this.checkFPS(e,e.webkitDecodedFrameCount,e.webkitDroppedFrameCount)},o}(),Ki="[eme]",lo=function(){function o(e){this.hls=void 0,this.config=void 0,this.media=null,this.keyFormatPromise=null,this.keySystemAccessPromises={},this._requestLicenseFailureCount=0,this.mediaKeySessions=[],this.keyIdToKeySessionPromise={},this.setMediaKeysQueue=o.CDMCleanupPromise?[o.CDMCleanupPromise]:[],this.onMediaEncrypted=this._onMediaEncrypted.bind(this),this.onWaitingForKey=this._onWaitingForKey.bind(this),this.debug=R.debug.bind(R,Ki),this.log=R.log.bind(R,Ki),this.warn=R.warn.bind(R,Ki),this.error=R.error.bind(R,Ki),this.hls=e,this.config=e.config,this.registerListeners()}var n=o.prototype;return n.destroy=function(){this.unregisterListeners(),this.onMediaDetached();var e=this.config;e.requestMediaKeySystemAccessFunc=null,e.licenseXhrSetup=e.licenseResponseCallback=void 0,e.drmSystems=e.drmSystemOptions={},this.hls=this.onMediaEncrypted=this.onWaitingForKey=this.keyIdToKeySessionPromise=null,this.config=null},n.registerListeners=function(){this.hls.on(A.MEDIA_ATTACHED,this.onMediaAttached,this),this.hls.on(A.MEDIA_DETACHED,this.onMediaDetached,this),this.hls.on(A.MANIFEST_LOADING,this.onManifestLoading,this),this.hls.on(A.MANIFEST_LOADED,this.onManifestLoaded,this)},n.unregisterListeners=function(){this.hls.off(A.MEDIA_ATTACHED,this.onMediaAttached,this),this.hls.off(A.MEDIA_DETACHED,this.onMediaDetached,this),this.hls.off(A.MANIFEST_LOADING,this.onManifestLoading,this),this.hls.off(A.MANIFEST_LOADED,this.onManifestLoaded,this)},n.getLicenseServerUrl=function(e){var t=this.config,i=t.drmSystems,r=t.widevineLicenseUrl,a=i[e];if(a)return a.licenseUrl;if(e===Ee.WIDEVINE&&r)return r;throw new Error('no license server URL configured for key-system "'+e+'"')},n.getServerCertificateUrl=function(e){var t=this.config.drmSystems[e];if(t)return t.serverCertificateUrl;this.log('No Server Certificate in config.drmSystems["'+e+'"]')},n.attemptKeySystemAccess=function(e){var t=this,i=this.hls.levels,r=function(l,d,c){return!!l&&c.indexOf(l)===d},a=i.map(function(l){return l.audioCodec}).filter(r),s=i.map(function(l){return l.videoCodec}).filter(r);return a.length+s.length===0&&s.push("avc1.42e01e"),new Promise(function(l,d){(function c(u){var g=u.shift();t.getMediaKeysPromise(g,a,s).then(function(m){return l({keySystem:g,mediaKeys:m})}).catch(function(m){u.length?c(u):d(m instanceof We?m:new We({type:ne.KEY_SYSTEM_ERROR,details:O.KEY_SYSTEM_NO_ACCESS,error:m,fatal:!0},m.message))})})(e)})},n.requestMediaKeySystemAccess=function(e,t){var i=this.config.requestMediaKeySystemAccessFunc;if(typeof i!="function"){var r="Configured requestMediaKeySystemAccess is not a function "+i;return In===null&&self.location.protocol==="http:"&&(r="navigator.requestMediaKeySystemAccess is not available over insecure protocol "+location.protocol),Promise.reject(new Error(r))}return i(e,t)},n.getMediaKeysPromise=function(e,t,i){var r=this,a=function(c,u,g,m){var v;switch(c){case Ee.FAIRPLAY:v=["cenc","sinf"];break;case Ee.WIDEVINE:case Ee.PLAYREADY:v=["cenc"];break;case Ee.CLEARKEY:v=["cenc","keyids"];break;default:throw new Error("Unknown key-system: "+c)}return function(y,_,b,E){return[{initDataTypes:y,persistentState:E.persistentState||"not-allowed",distinctiveIdentifier:E.distinctiveIdentifier||"not-allowed",sessionTypes:E.sessionTypes||[E.sessionType||"temporary"],audioCapabilities:_.map(function(S){return{contentType:'audio/mp4; codecs="'+S+'"',robustness:E.audioRobustness||"",encryptionScheme:E.audioEncryptionScheme||null}}),videoCapabilities:b.map(function(S){return{contentType:'video/mp4; codecs="'+S+'"',robustness:E.videoRobustness||"",encryptionScheme:E.videoEncryptionScheme||null}})}]}(v,u,g,m)}(e,t,i,this.config.drmSystemOptions),s=this.keySystemAccessPromises[e],l=s==null?void 0:s.keySystemAccess;if(!l){this.log('Requesting encrypted media "'+e+'" key-system access with config: '+JSON.stringify(a)),l=this.requestMediaKeySystemAccess(e,a);var d=this.keySystemAccessPromises[e]={keySystemAccess:l};return l.catch(function(c){r.log('Failed to obtain access to key-system "'+e+'": '+c)}),l.then(function(c){r.log('Access for key-system "'+c.keySystem+'" obtained');var u=r.fetchServerCertificate(e);return r.log('Create media-keys for "'+e+'"'),d.mediaKeys=c.createMediaKeys().then(function(g){return r.log('Media-keys created for "'+e+'"'),u.then(function(m){return m?r.setMediaKeysServerCertificate(g,e,m):g})}),d.mediaKeys.catch(function(g){r.error('Failed to create media-keys for "'+e+'"}: '+g)}),d.mediaKeys})}return l.then(function(){return s.mediaKeys})},n.createMediaKeySessionContext=function(e){var t=e.decryptdata,i=e.keySystem,r=e.mediaKeys;this.log('Creating key-system session "'+i+'" keyId: '+ot(t.keyId||[]));var a=r.createSession(),s={decryptdata:t,keySystem:i,mediaKeys:r,mediaKeysSession:a,keyStatus:"status-pending"};return this.mediaKeySessions.push(s),s},n.renewKeySession=function(e){var t=e.decryptdata;if(t.pssh){var i=this.createMediaKeySessionContext(e),r=this.getKeyIdString(t);this.keyIdToKeySessionPromise[r]=this.generateRequestWithPreferredKeySession(i,"cenc",t.pssh,"expired")}else this.warn("Could not renew expired session. Missing pssh initData.");this.removeSession(e)},n.getKeyIdString=function(e){if(!e)throw new Error("Could not read keyId of undefined decryptdata");if(e.keyId===null)throw new Error("keyId is null");return ot(e.keyId)},n.updateKeySession=function(e,t){var i,r=e.mediaKeysSession;return this.log('Updating key-session "'+r.sessionId+'" for keyID '+ot(((i=e.decryptdata)==null?void 0:i.keyId)||[])+` + } (data length: `+(t&&t.byteLength)+")"),r.update(t)},n.selectKeySystemFormat=function(e){var t=Object.keys(e.levelkeys||{});return this.keyFormatPromise||(this.log("Selecting key-system from fragment (sn: "+e.sn+" "+e.type+": "+e.level+") key formats "+t.join(", ")),this.keyFormatPromise=this.getKeyFormatPromise(t)),this.keyFormatPromise},n.getKeyFormatPromise=function(e){var t=this;return new Promise(function(i,r){var a=sr(t.config),s=e.map(Ln).filter(function(l){return!!l&&a.indexOf(l)!==-1});return t.getKeySystemSelectionPromise(s).then(function(l){var d=l.keySystem,c=Rn(d);c?i(c):r(new Error('Unable to find format for key-system "'+d+'"'))}).catch(r)})},n.loadKey=function(e){var t=this,i=e.keyInfo.decryptdata,r=this.getKeyIdString(i),a="(keyId: "+r+' format: "'+i.keyFormat+'" method: '+i.method+" uri: "+i.uri+")";this.log("Starting session for key "+a);var s=this.keyIdToKeySessionPromise[r];return s||(s=this.keyIdToKeySessionPromise[r]=this.getKeySystemForKeyPromise(i).then(function(l){var d=l.keySystem,c=l.mediaKeys;return t.throwIfDestroyed(),t.log("Handle encrypted media sn: "+e.frag.sn+" "+e.frag.type+": "+e.frag.level+" using key "+a),t.attemptSetMediaKeys(d,c).then(function(){t.throwIfDestroyed();var u=t.createMediaKeySessionContext({keySystem:d,mediaKeys:c,decryptdata:i});return t.generateRequestWithPreferredKeySession(u,"cenc",i.pssh,"playlist-key")})})).catch(function(l){return t.handleError(l)}),s},n.throwIfDestroyed=function(e){if(!this.hls)throw new Error("invalid state")},n.handleError=function(e){this.hls&&(this.error(e.message),e instanceof We?this.hls.trigger(A.ERROR,e.data):this.hls.trigger(A.ERROR,{type:ne.KEY_SYSTEM_ERROR,details:O.KEY_SYSTEM_NO_KEYS,error:e,fatal:!0}))},n.getKeySystemForKeyPromise=function(e){var t=this.getKeyIdString(e),i=this.keyIdToKeySessionPromise[t];if(!i){var r=Ln(e.keyFormat),a=r?[r]:sr(this.config);return this.attemptKeySystemAccess(a)}return i},n.getKeySystemSelectionPromise=function(e){if(e.length||(e=sr(this.config)),e.length===0)throw new We({type:ne.KEY_SYSTEM_ERROR,details:O.KEY_SYSTEM_NO_CONFIGURED_LICENSE,fatal:!0},"Missing key-system license configuration options "+JSON.stringify({drmSystems:this.config.drmSystems}));return this.attemptKeySystemAccess(e)},n._onMediaEncrypted=function(e){var t=this,i=e.initDataType,r=e.initData;if(this.debug('"'+e.type+'" event: init data type: "'+i+'"'),r!==null){var a,s;if(i==="sinf"&&this.config.drmSystems[Ee.FAIRPLAY]){var l=Se(new Uint8Array(r));try{var d=nr(JSON.parse(l).sinf),c=Gn(new Uint8Array(d));if(!c)return;a=c.subarray(8,24),s=Ee.FAIRPLAY}catch{return void this.warn('Failed to parse sinf "encrypted" event message initData')}}else{var u=function(S){if(!(S instanceof ArrayBuffer)||S.byteLength<32)return null;var C={version:0,systemId:"",kids:null,data:null},L=new DataView(S),I=L.getUint32(0);if(S.byteLength!==I&&I>44||L.getUint32(4)!==1886614376||(C.version=L.getUint32(8)>>>24,C.version>1))return null;C.systemId=ot(new Uint8Array(S,12,16));var P=L.getUint32(28);if(C.version===0){if(I-32m||d.status>=400&&d.status<500)s(new We({type:ne.KEY_SYSTEM_ERROR,details:O.KEY_SYSTEM_LICENSE_REQUEST_FAILED,fatal:!0,networkDetails:d,response:{url:l,data:void 0,code:d.status,text:d.statusText}},"License Request XHR failed ("+l+"). Status: "+d.status+" ("+d.statusText+")"));else{var v=m-i._requestLicenseFailureCount+1;i.warn("Retrying license request, "+v+" attempts left"),i.requestLicense(e,t).then(a,s)}}},e.licenseXhr&&e.licenseXhr.readyState!==XMLHttpRequest.DONE&&e.licenseXhr.abort(),e.licenseXhr=d,i.setupLicenseXHR(d,l,e,t).then(function(c){var u=c.xhr,g=c.licenseChallenge;u.send(g)})})},n.onMediaAttached=function(e,t){if(this.config.emeEnabled){var i=t.media;this.media=i,i.addEventListener("encrypted",this.onMediaEncrypted),i.addEventListener("waitingforkey",this.onWaitingForKey)}},n.onMediaDetached=function(){var e=this,t=this.media,i=this.mediaKeySessions;t&&(t.removeEventListener("encrypted",this.onMediaEncrypted),t.removeEventListener("waitingforkey",this.onWaitingForKey),this.media=null),this._requestLicenseFailureCount=0,this.setMediaKeysQueue=[],this.mediaKeySessions=[],this.keyIdToKeySessionPromise={},hr.clearKeyUriToKeyIdMap();var r=i.length;o.CDMCleanupPromise=Promise.all(i.map(function(a){return e.removeSession(a)}).concat(t==null?void 0:t.setMediaKeys(null).catch(function(a){e.log("Could not clear media keys: "+a+". media.src: "+(t==null?void 0:t.src))}))).then(function(){r&&(e.log("finished closing key sessions and clearing media keys"),i.length=0)}).catch(function(a){e.log("Could not close sessions and clear media keys: "+a+". media.src: "+(t==null?void 0:t.src))})},n.onManifestLoading=function(){this.keyFormatPromise=null},n.onManifestLoaded=function(e,t){var i=t.sessionKeys;if(i&&this.config.emeEnabled&&!this.keyFormatPromise){var r=i.reduce(function(a,s){return a.indexOf(s.keyFormat)===-1&&a.push(s.keyFormat),a},[]);this.log("Selecting key-system from session-keys "+r.join(", ")),this.keyFormatPromise=this.getKeyFormatPromise(r)}},n.removeSession=function(e){var t=this,i=e.mediaKeysSession,r=e.licenseXhr;if(i){this.log("Remove licenses and keys and close session "+i.sessionId),i.onmessage=null,i.onkeystatuseschange=null,r&&r.readyState!==XMLHttpRequest.DONE&&r.abort(),e.mediaKeysSession=e.decryptdata=e.licenseXhr=void 0;var a=this.mediaKeySessions.indexOf(e);return a>-1&&this.mediaKeySessions.splice(a,1),i.remove().catch(function(s){t.log("Could not remove session: "+s)}).then(function(){return i.close()}).catch(function(s){t.log("Could not close session: "+s)})}},o}();lo.CDMCleanupPromise=void 0;var We=function(o){function n(e,t){var i;return(i=o.call(this,t)||this).data=void 0,e.error||(e.error=new Error(t)),i.data=e,e.err=e.error,i}return q(n,o),n}(ce(Error)),Fl="m",Vi="a",en="v",tn="av",co="i",Bl="tt",Nl=function(){function o(e){var t=this;this.hls=void 0,this.config=void 0,this.media=void 0,this.sid=void 0,this.cid=void 0,this.useHeaders=!1,this.initialized=!1,this.starved=!1,this.buffering=!0,this.audioBuffer=void 0,this.videoBuffer=void 0,this.onWaiting=function(){t.initialized&&(t.starved=!0),t.buffering=!0},this.onPlaying=function(){t.initialized||(t.initialized=!0),t.buffering=!1},this.applyPlaylistData=function(a){try{t.apply(a,{ot:Fl,su:!t.initialized})}catch(s){R.warn("Could not generate manifest CMCD data.",s)}},this.applyFragmentData=function(a){try{var s=a.frag,l=t.hls.levels[s.level],d=t.getObjectType(s),c={d:1e3*s.duration,ot:d};d!==en&&d!==Vi&&d!=tn||(c.br=l.bitrate/1e3,c.tb=t.getTopBandwidth(d)/1e3,c.bl=t.getBufferLength(d)),t.apply(a,c)}catch(u){R.warn("Could not generate segment CMCD data.",u)}},this.hls=e;var i=this.config=e.config,r=i.cmcd;r!=null&&(i.pLoader=this.createPlaylistLoader(),i.fLoader=this.createFragmentLoader(),this.sid=r.sessionId||o.uuid(),this.cid=r.contentId,this.useHeaders=r.useHeaders===!0,this.registerListeners())}var n=o.prototype;return n.registerListeners=function(){var e=this.hls;e.on(A.MEDIA_ATTACHED,this.onMediaAttached,this),e.on(A.MEDIA_DETACHED,this.onMediaDetached,this),e.on(A.BUFFER_CREATED,this.onBufferCreated,this)},n.unregisterListeners=function(){var e=this.hls;e.off(A.MEDIA_ATTACHED,this.onMediaAttached,this),e.off(A.MEDIA_DETACHED,this.onMediaDetached,this),e.off(A.BUFFER_CREATED,this.onBufferCreated,this)},n.destroy=function(){this.unregisterListeners(),this.onMediaDetached(),this.hls=this.config=this.audioBuffer=this.videoBuffer=null},n.onMediaAttached=function(e,t){this.media=t.media,this.media.addEventListener("waiting",this.onWaiting),this.media.addEventListener("playing",this.onPlaying)},n.onMediaDetached=function(){this.media&&(this.media.removeEventListener("waiting",this.onWaiting),this.media.removeEventListener("playing",this.onPlaying),this.media=null)},n.onBufferCreated=function(e,t){var i,r;this.audioBuffer=(i=t.tracks.audio)==null?void 0:i.buffer,this.videoBuffer=(r=t.tracks.video)==null?void 0:r.buffer},n.createData=function(){var e;return{v:1,sf:"h",sid:this.sid,cid:this.cid,pr:(e=this.media)==null?void 0:e.playbackRate,mtp:this.hls.bandwidthEstimate/1e3}},n.apply=function(e,t){t===void 0&&(t={}),F(t,this.createData());var i=t.ot===co||t.ot===en||t.ot===tn;if(this.starved&&i&&(t.bs=!0,t.su=!0,this.starved=!1),t.su==null&&(t.su=this.buffering),this.useHeaders){var r=o.toHeaders(t);if(!Object.keys(r).length)return;e.headers||(e.headers={}),F(e.headers,r)}else{var a=o.toQuery(t);if(!a)return;e.url=o.appendQueryToUri(e.url,a)}},n.getObjectType=function(e){var t=e.type;return t==="subtitle"?Bl:e.sn==="initSegment"?co:t==="audio"?Vi:t==="main"?this.hls.audioTracks.length?en:tn:void 0},n.getTopBandwidth=function(e){var t,i=0,r=this.hls;if(e===Vi)t=r.audioTracks;else{var a=r.maxAutoLevel,s=a>-1?a+1:r.levels.length;t=r.levels.slice(0,s)}for(var l,d=ze(t);!(l=d()).done;){var c=l.value;c.bitrate>i&&(i=c.bitrate)}return i>0?i:NaN},n.getBufferLength=function(e){var t=this.hls.media,i=e===Vi?this.audioBuffer:this.videoBuffer;return i&&t?1e3*Ae.bufferInfo(i,t.currentTime,this.config.maxBufferHole).len:NaN},n.createPlaylistLoader=function(){var e=this.config.pLoader,t=this.applyPlaylistData,i=e||this.config.loader;return function(){function r(s){this.loader=void 0,this.loader=new i(s)}var a=r.prototype;return a.destroy=function(){this.loader.destroy()},a.abort=function(){this.loader.abort()},a.load=function(s,l,d){t(s),this.loader.load(s,l,d)},D(r,[{key:"stats",get:function(){return this.loader.stats}},{key:"context",get:function(){return this.loader.context}}]),r}()},n.createFragmentLoader=function(){var e=this.config.fLoader,t=this.applyFragmentData,i=e||this.config.loader;return function(){function r(s){this.loader=void 0,this.loader=new i(s)}var a=r.prototype;return a.destroy=function(){this.loader.destroy()},a.abort=function(){this.loader.abort()},a.load=function(s,l,d){t(s),this.loader.load(s,l,d)},D(r,[{key:"stats",get:function(){return this.loader.stats}},{key:"context",get:function(){return this.loader.context}}]),r}()},o.uuid=function(){var e=URL.createObjectURL(new Blob),t=e.toString();return URL.revokeObjectURL(e),t.slice(t.lastIndexOf("/")+1)},o.serialize=function(e){for(var t,i=[],r=function(y){return!Number.isNaN(y)&&y!=null&&y!==""&&y!==!1},a=function(y){return Math.round(y)},s=function(y){return 100*a(y/100)},l={br:a,d:a,bl:s,dl:s,mtp:s,nor:function(y){return encodeURIComponent(y)},rtp:s,tb:a},d=ze(Object.keys(e||{}).sort());!(t=d()).done;){var c=t.value,u=e[c];if(r(u)&&!(c==="v"&&u===1||c=="pr"&&u===1)){var g=l[c];g&&(u=g(u));var m=typeof u,v=void 0;v=c==="ot"||c==="sf"||c==="st"?c+"="+u:m==="boolean"?c:m==="number"?c+"="+u:c+"="+JSON.stringify(u),i.push(v)}}return i.join(",")},o.toHeaders=function(e){for(var t={},i=["Object","Request","Session","Status"],r=[{},{},{},{}],a={br:0,d:0,ot:0,tb:0,bl:1,dl:1,mtp:1,nor:1,nrr:1,su:1,cid:2,pr:2,sf:2,sid:2,st:2,v:2,bs:3,rtp:3},s=0,l=Object.keys(e);s1&&(this.updatePathwayPriority(r),i.resolved=this.pathwayId!==a)}},n.filterParsedLevels=function(e){this.levels=e;var t=this.getLevelsForPathway(this.pathwayId);if(t.length===0){var i=e[0].pathwayId;this.log("No levels found in Pathway "+this.pathwayId+'. Setting initial Pathway to "'+i+'"'),t=this.getLevelsForPathway(i),this.pathwayId=i}return t.length!==e.length?(this.log("Found "+t.length+"/"+e.length+' levels in Pathway "'+this.pathwayId+'"'),t):e},n.getLevelsForPathway=function(e){return this.levels===null?[]:this.levels.filter(function(t){return e===t.pathwayId})},n.updatePathwayPriority=function(e){var t;this.pathwayPriority=e;var i=this.penalizedPathways,r=performance.now();Object.keys(i).forEach(function(u){r-i[u]>3e5&&delete i[u]});for(var a=0;a0){this.log('Setting Pathway to "'+s+'"'),this.pathwayId=s,this.hls.trigger(A.LEVELS_UPDATED,{levels:t});var c=this.hls.levels[l];d&&c&&this.levels&&(c.attrs["STABLE-VARIANT-ID"]!==d.attrs["STABLE-VARIANT-ID"]&&c.bitrate!==d.bitrate&&this.log("Unstable Pathways change from bitrate "+d.bitrate+" to "+c.bitrate),this.hls.nextLoadLevel=l);break}}}},n.clonePathways=function(e){var t=this,i=this.levels;if(i){var r={},a={};e.forEach(function(s){var l=s.ID,d=s["BASE-ID"],c=s["URI-REPLACEMENT"];if(!i.some(function(g){return g.pathwayId===l})){var u=t.getLevelsForPathway(d).map(function(g){var m=F({},g);m.details=void 0,m.url=uo(g.uri,g.attrs["STABLE-VARIANT-ID"],"PER-VARIANT-URIS",c);var v=new _e(g.attrs);v["PATHWAY-ID"]=l;var y=v.AUDIO&&v.AUDIO+"_clone_"+l,_=v.SUBTITLES&&v.SUBTITLES+"_clone_"+l;y&&(r[v.AUDIO]=y,v.AUDIO=y),_&&(a[v.SUBTITLES]=_,v.SUBTITLES=_),m.attrs=v;var b=new ai(m);return Ii(b,"audio",y),Ii(b,"text",_),b});i.push.apply(i,u),ho(t.audioTracks,r,c,l),ho(t.subtitleTracks,a,c,l)}})}},n.loadSteeringManifest=function(e){var t,i=this,r=this.hls.config,a=r.loader;this.loader&&this.loader.destroy(),this.loader=new a(r);try{t=new self.URL(e)}catch{return this.enabled=!1,void this.log("Failed to parse Steering Manifest URI: "+e)}if(t.protocol!=="data:"){var s=0|(this.hls.bandwidthEstimate||r.abrEwmaDefaultEstimate);t.searchParams.set("_HLS_pathway",this.pathwayId),t.searchParams.set("_HLS_throughput",""+s)}var l={responseType:"json",url:t.href},d=r.steeringManifestLoadPolicy.default,c=d.errorRetry||d.timeoutRetry||{},u={loadPolicy:d,timeout:d.maxLoadTimeMs,maxRetry:c.maxNumRetry||0,retryDelay:c.retryDelayMs||0,maxRetryDelay:c.maxRetryDelayMs||0},g={onSuccess:function(m,v,y,_){i.log('Loaded steering manifest: "'+t+'"');var b=m.data;if(b.VERSION===1){i.updated=performance.now(),i.timeToLoad=b.TTL;var E=b["RELOAD-URI"],S=b["PATHWAY-CLONES"],C=b["PATHWAY-PRIORITY"];if(E)try{i.uri=new self.URL(E,t).href}catch{return i.enabled=!1,void i.log("Failed to parse Steering Manifest RELOAD-URI: "+E)}i.scheduleRefresh(i.uri||y.url),S&&i.clonePathways(S),C&&i.updatePathwayPriority(C)}else i.log("Steering VERSION "+b.VERSION+" not supported!")},onError:function(m,v,y,_){if(i.log("Error loading steering manifest: "+m.code+" "+m.text+" ("+v.url+")"),i.stopLoad(),m.code===410)return i.enabled=!1,void i.log("Steering manifest "+v.url+" no longer available");var b=1e3*i.timeToLoad;if(m.code!==429)i.scheduleRefresh(i.uri||v.url,b);else{var E=i.loader;if(typeof(E==null?void 0:E.getResponseHeader)=="function"){var S=E.getResponseHeader("Retry-After");S&&(b=1e3*parseFloat(S))}i.log("Steering manifest "+v.url+" rate limited")}},onTimeout:function(m,v,y){i.log("Timeout loading steering manifest ("+v.url+")"),i.scheduleRefresh(i.uri||v.url)}};this.log("Requesting steering manifest: "+t),this.loader.load(l,u,g)},n.scheduleRefresh=function(e,t){var i=this;t===void 0&&(t=1e3*this.timeToLoad),self.clearTimeout(this.reloadTimer),this.reloadTimer=self.setTimeout(function(){i.loadSteeringManifest(e)},t)},o}();function ho(o,n,e,t){o&&Object.keys(n).forEach(function(i){var r=o.filter(function(a){return a.groupId===i}).map(function(a){var s=F({},a);return s.details=void 0,s.attrs=new _e(s.attrs),s.url=s.attrs.URI=uo(a.url,a.attrs["STABLE-RENDITION-ID"],"PER-RENDITION-URIS",e),s.groupId=s.attrs["GROUP-ID"]=n[i],s.attrs["PATHWAY-ID"]=t,s});o.push.apply(o,r)})}function uo(o,n,e,t){var i,r=t.HOST,a=t.PARAMS,s=t[e];n&&(i=s==null?void 0:s[n])&&(o=i);var l=new self.URL(o);return r&&!i&&(l.host=r),a&&Object.keys(a).sort().forEach(function(d){d&&l.searchParams.set(d,a[d])}),l.href}var Gl=/^age:\s*[\d.]+\s*$/im,fo=function(){function o(e){this.xhrSetup=void 0,this.requestTimeout=void 0,this.retryTimeout=void 0,this.retryDelay=void 0,this.config=null,this.callbacks=null,this.context=void 0,this.loader=null,this.stats=void 0,this.xhrSetup=e&&e.xhrSetup||null,this.stats=new yi,this.retryDelay=0}var n=o.prototype;return n.destroy=function(){this.callbacks=null,this.abortInternal(),this.loader=null,this.config=null},n.abortInternal=function(){var e=this.loader;self.clearTimeout(this.requestTimeout),self.clearTimeout(this.retryTimeout),e&&(e.onreadystatechange=null,e.onprogress=null,e.readyState!==4&&(this.stats.aborted=!0,e.abort()))},n.abort=function(){var e;this.abortInternal(),(e=this.callbacks)!=null&&e.onAbort&&this.callbacks.onAbort(this.stats,this.context,this.loader)},n.load=function(e,t,i){if(this.stats.loading.start)throw new Error("Loader can only be used once.");this.stats.loading.start=self.performance.now(),this.context=e,this.config=t,this.callbacks=i,this.loadInternal()},n.loadInternal=function(){var e=this,t=this.config,i=this.context;if(t){var r=this.loader=new self.XMLHttpRequest,a=this.stats;a.loading.first=0,a.loaded=0,a.aborted=!1;var s=this.xhrSetup;s?Promise.resolve().then(function(){if(!e.stats.aborted)return s(r,i.url)}).catch(function(l){return r.open("GET",i.url,!0),s(r,i.url)}).then(function(){e.stats.aborted||e.openAndSendXhr(r,i,t)}).catch(function(l){e.callbacks.onError({code:r.status,text:l.message},i,r,a)}):this.openAndSendXhr(r,i,t)}},n.openAndSendXhr=function(e,t,i){e.readyState||e.open("GET",t.url,!0);var r=this.context.headers,a=i.loadPolicy,s=a.maxTimeToFirstByteMs,l=a.maxLoadTimeMs;if(r)for(var d in r)e.setRequestHeader(d,r[d]);t.rangeEnd&&e.setRequestHeader("Range","bytes="+t.rangeStart+"-"+(t.rangeEnd-1)),e.onreadystatechange=this.readystatechange.bind(this),e.onprogress=this.loadprogress.bind(this),e.responseType=t.responseType,self.clearTimeout(this.requestTimeout),i.timeout=s&&ie(s)?s:l,this.requestTimeout=self.setTimeout(this.loadtimeout.bind(this),i.timeout),e.send()},n.readystatechange=function(){var e=this.context,t=this.loader,i=this.stats;if(e&&t){var r=t.readyState,a=this.config;if(!i.aborted&&r>=2&&(i.loading.first===0&&(i.loading.first=Math.max(self.performance.now(),i.loading.start),a.timeout!==a.loadPolicy.maxLoadTimeMs&&(self.clearTimeout(this.requestTimeout),a.timeout=a.loadPolicy.maxLoadTimeMs,this.requestTimeout=self.setTimeout(this.loadtimeout.bind(this),a.loadPolicy.maxLoadTimeMs-(i.loading.first-i.loading.start)))),r===4)){self.clearTimeout(this.requestTimeout),t.onreadystatechange=null,t.onprogress=null;var s=t.status,l=t.responseType!=="text";if(s>=200&&s<300&&(l&&t.response||t.responseText!==null)){i.loading.end=Math.max(self.performance.now(),i.loading.first);var d=l?t.response:t.responseText,c=t.responseType==="arraybuffer"?d.byteLength:d.length;if(i.loaded=i.total=c,i.bwEstimate=8e3*i.total/(i.loading.end-i.loading.first),!this.callbacks)return;var u=this.callbacks.onProgress;if(u&&u(i,e,d,t),!this.callbacks)return;var g={url:t.responseURL,data:d,code:s};this.callbacks.onSuccess(g,i,e,t)}else{var m=a.loadPolicy.errorRetry;Li(m,i.retry,!1,s)?this.retry(m):(R.error(s+" while loading "+e.url),this.callbacks.onError({code:s,text:t.statusText},e,t,i))}}}},n.loadtimeout=function(){var e,t=(e=this.config)==null?void 0:e.loadPolicy.timeoutRetry;if(Li(t,this.stats.retry,!0))this.retry(t);else{R.warn("timeout while loading "+this.context.url);var i=this.callbacks;i&&(this.abortInternal(),i.onTimeout(this.stats,this.context,this.loader))}},n.retry=function(e){var t=this.context,i=this.stats;this.retryDelay=Ar(e,i.retry),i.retry++,R.warn((status?"HTTP Status "+status:"Timeout")+" while loading "+t.url+", retrying "+i.retry+"/"+e.maxNumRetry+" in "+this.retryDelay+"ms"),this.abortInternal(),this.loader=null,self.clearTimeout(this.retryTimeout),this.retryTimeout=self.setTimeout(this.loadInternal.bind(this),this.retryDelay)},n.loadprogress=function(e){var t=this.stats;t.loaded=e.loaded,e.lengthComputable&&(t.total=e.total)},n.getCacheAge=function(){var e=null;if(this.loader&&Gl.test(this.loader.getAllResponseHeaders())){var t=this.loader.getResponseHeader("age");e=t?parseFloat(t):null}return e},n.getResponseHeader=function(e){return this.loader&&new RegExp("^"+e+":\\s*[\\d.]+\\s*$","im").test(this.loader.getAllResponseHeaders())?this.loader.getResponseHeader(e):null},o}(),Hl=/(\d+)-(\d+)\/(\d+)/,po=function(){function o(e){this.fetchSetup=void 0,this.requestTimeout=void 0,this.request=void 0,this.response=void 0,this.controller=void 0,this.context=void 0,this.config=null,this.callbacks=null,this.stats=void 0,this.loader=null,this.fetchSetup=e.fetchSetup||Kl,this.controller=new self.AbortController,this.stats=new yi}var n=o.prototype;return n.destroy=function(){this.loader=this.callbacks=null,this.abortInternal()},n.abortInternal=function(){var e=this.response;e!=null&&e.ok||(this.stats.aborted=!0,this.controller.abort())},n.abort=function(){var e;this.abortInternal(),(e=this.callbacks)!=null&&e.onAbort&&this.callbacks.onAbort(this.stats,this.context,this.response)},n.load=function(e,t,i){var r=this,a=this.stats;if(a.loading.start)throw new Error("Loader can only be used once.");a.loading.start=self.performance.now();var s=function(v,y){var _={method:"GET",mode:"cors",credentials:"same-origin",signal:y,headers:new self.Headers(F({},v.headers))};return v.rangeEnd&&_.headers.set("Range","bytes="+v.rangeStart+"-"+String(v.rangeEnd-1)),_}(e,this.controller.signal),l=i.onProgress,d=e.responseType==="arraybuffer",c=d?"byteLength":"length",u=t.loadPolicy,g=u.maxTimeToFirstByteMs,m=u.maxLoadTimeMs;this.context=e,this.config=t,this.callbacks=i,this.request=this.fetchSetup(e,s),self.clearTimeout(this.requestTimeout),t.timeout=g&&ie(g)?g:m,this.requestTimeout=self.setTimeout(function(){r.abortInternal(),i.onTimeout(a,e,r.response)},t.timeout),self.fetch(this.request).then(function(v){r.response=r.loader=v;var y=Math.max(self.performance.now(),a.loading.start);if(self.clearTimeout(r.requestTimeout),t.timeout=m,r.requestTimeout=self.setTimeout(function(){r.abortInternal(),i.onTimeout(a,e,r.response)},m-(y-a.loading.start)),!v.ok){var _=v.status,b=v.statusText;throw new Vl(b||"fetch, bad network response",_,v)}return a.loading.first=y,a.total=function(E){var S=E.get("Content-Range");if(S){var C=function(I){var P=Hl.exec(I);if(P)return parseInt(P[2])-parseInt(P[1])+1}(S);if(ie(C))return C}var L=E.get("Content-Length");if(L)return parseInt(L)}(v.headers)||a.total,l&&ie(t.highWaterMark)?r.loadProgressively(v,a,e,t.highWaterMark,l):d?v.arrayBuffer():e.responseType==="json"?v.json():v.text()}).then(function(v){var y=r.response;self.clearTimeout(r.requestTimeout),a.loading.end=Math.max(self.performance.now(),a.loading.first);var _=v[c];_&&(a.loaded=a.total=_);var b={url:y.url,data:v,code:y.status};l&&!ie(t.highWaterMark)&&l(a,e,v,y),i.onSuccess(b,a,e,y)}).catch(function(v){if(self.clearTimeout(r.requestTimeout),!a.aborted){var y=v&&v.code||0,_=v?v.message:null;i.onError({code:y,text:_},e,v?v.details:null,a)}})},n.getCacheAge=function(){var e=null;if(this.response){var t=this.response.headers.get("age");e=t?parseFloat(t):null}return e},n.getResponseHeader=function(e){return this.response?this.response.headers.get(e):null},n.loadProgressively=function(e,t,i,r,a){r===void 0&&(r=0);var s=new Va,l=e.body.getReader();return function d(){return l.read().then(function(c){if(c.done)return s.dataLength&&a(t,i,s.flush(),e),Promise.resolve(new ArrayBuffer(0));var u=c.value,g=u.length;return t.loaded+=g,g=r&&a(t,i,s.flush(),e)):a(t,i,u,e),d()}).catch(function(){return Promise.reject()})}()},o}();function Kl(o,n){return new self.Request(o.url,n)}var Vl=function(o){function n(e,t,i){var r;return(r=o.call(this,e)||this).code=void 0,r.details=void 0,r.code=t,r.details=i,r}return q(n,o),n}(ce(Error)),zl=/\s/,Yl=x(x({autoStartLoad:!0,startPosition:-1,defaultAudioCodec:void 0,debug:!1,capLevelOnFPSDrop:!1,capLevelToPlayerSize:!1,ignoreDevicePixelRatio:!1,initialLiveManifestSize:1,maxBufferLength:30,backBufferLength:1/0,maxBufferSize:6e7,maxBufferHole:.1,highBufferWatchdogPeriod:2,nudgeOffset:.1,nudgeMaxRetry:3,maxFragLookUpTolerance:.25,liveSyncDurationCount:3,liveMaxLatencyDurationCount:1/0,liveSyncDuration:void 0,liveMaxLatencyDuration:void 0,maxLiveSyncPlaybackRate:1,liveDurationInfinity:!1,liveBackBufferLength:null,maxMaxBufferLength:600,enableWorker:!0,workerPath:null,enableSoftwareAES:!0,startLevel:void 0,startFragPrefetch:!1,fpsDroppedMonitoringPeriod:5e3,fpsDroppedMonitoringThreshold:.2,appendErrorMaxRetry:3,loader:fo,fLoader:void 0,pLoader:void 0,xhrSetup:void 0,licenseXhrSetup:void 0,licenseResponseCallback:void 0,abrController:ll,bufferController:ml,capLevelController:Ol,errorController:Ss,fpsController:Ml,stretchShortVideoTrack:!1,maxAudioFramesDrift:1,forceKeyFrameOnDiscontinuity:!0,abrEwmaFastLive:3,abrEwmaSlowLive:9,abrEwmaFastVoD:3,abrEwmaSlowVoD:9,abrEwmaDefaultEstimate:5e5,abrBandWidthFactor:.95,abrBandWidthUpFactor:.7,abrMaxWithRealBitrate:!1,maxStarvationDelay:4,maxLoadingDelay:4,minAutoBitrate:0,emeEnabled:!1,widevineLicenseUrl:void 0,drmSystems:{},drmSystemOptions:{},requestMediaKeySystemAccessFunc:In,testBandwidth:!0,progressive:!1,lowLatencyMode:!0,cmcd:void 0,enableDateRangeMetadataCues:!0,enableEmsgMetadataCues:!0,enableID3MetadataCues:!0,certLoadPolicy:{default:{maxTimeToFirstByteMs:8e3,maxLoadTimeMs:2e4,timeoutRetry:null,errorRetry:null}},keyLoadPolicy:{default:{maxTimeToFirstByteMs:8e3,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:1,retryDelayMs:1e3,maxRetryDelayMs:2e4,backoff:"linear"},errorRetry:{maxNumRetry:8,retryDelayMs:1e3,maxRetryDelayMs:2e4,backoff:"linear"}}},manifestLoadPolicy:{default:{maxTimeToFirstByteMs:1/0,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:1,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},playlistLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:2,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},fragLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:12e4,timeoutRetry:{maxNumRetry:4,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:6,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},steeringManifestLoadPolicy:{default:{maxTimeToFirstByteMs:1e4,maxLoadTimeMs:2e4,timeoutRetry:{maxNumRetry:2,retryDelayMs:0,maxRetryDelayMs:0},errorRetry:{maxNumRetry:1,retryDelayMs:1e3,maxRetryDelayMs:8e3}}},manifestLoadingTimeOut:1e4,manifestLoadingMaxRetry:1,manifestLoadingRetryDelay:1e3,manifestLoadingMaxRetryTimeout:64e3,levelLoadingTimeOut:1e4,levelLoadingMaxRetry:4,levelLoadingRetryDelay:1e3,levelLoadingMaxRetryTimeout:64e3,fragLoadingTimeOut:2e4,fragLoadingMaxRetry:6,fragLoadingRetryDelay:1e3,fragLoadingMaxRetryTimeout:64e3},{cueHandler:{newCue:function(o,n,e,t){for(var i,r,a,s,l,d=[],c=self.VTTCue||self.TextTrackCue,u=0;u=16?s--:s++;var v=to(l.trim()),y=Qr(n,e,v);o!=null&&(g=o.cues)!=null&&g.getCueById(y)||((r=new c(n,e,v)).id=y,r.line=u+1,r.align="left",r.position=10+Math.min(80,10*Math.floor(8*s/32)),d.push(r))}return o&&d.length&&(d.sort(function(_,b){return _.line==="auto"||b.line==="auto"?0:_.line>8&&b.line>8?b.line-_.line:_.line-b.line}),d.forEach(function(_){return aa(o,_)})),d}},enableWebVTT:!0,enableIMSC1:!0,enableCEA708Captions:!0,captionsTextTrack1Label:"English",captionsTextTrack1LanguageCode:"en",captionsTextTrack2Label:"Spanish",captionsTextTrack2LanguageCode:"es",captionsTextTrack3Label:"Unknown CC",captionsTextTrack3LanguageCode:"",captionsTextTrack4Label:"Unknown CC",captionsTextTrack4LanguageCode:"",renderTextTracksNatively:!0}),{},{subtitleStreamController:ul,subtitleTrackController:pl,timelineController:Il,audioStreamController:dl,audioTrackController:cl,emeController:lo,cmcdController:Nl,contentSteeringController:Ul});function rn(o){return o&&typeof o=="object"?Array.isArray(o)?o.map(rn):Object.keys(o).reduce(function(n,e){return n[e]=rn(o[e]),n},{}):o}function jl(o){var n=o.loader;n!==po&&n!==fo?(R.log("[config]: Custom loader detected, cannot enable progressive streaming"),o.progressive=!1):function(){if(self.fetch&&self.AbortController&&self.ReadableStream&&self.Request)try{return new self.ReadableStream({}),!0}catch{}return!1}()&&(o.loader=po,o.progressive=!0,o.enableSoftwareAES=!0,R.log("[config]: Progressive streaming enabled, using FetchLoader"))}var go=function(){function o(e){e===void 0&&(e={}),this.config=void 0,this.userConfig=void 0,this.coreComponents=void 0,this.networkControllers=void 0,this._emitter=new Ui,this._autoLevelCapping=void 0,this._maxHdcpLevel=null,this.abrController=void 0,this.bufferController=void 0,this.capLevelController=void 0,this.latencyController=void 0,this.levelController=void 0,this.streamController=void 0,this.audioTrackController=void 0,this.subtitleTrackController=void 0,this.emeController=void 0,this.cmcdController=void 0,this._media=null,this.url=null,kn(e.debug||!1,"Hls instance");var t=this.config=function(Y,K){if((K.liveSyncDurationCount||K.liveMaxLatencyDurationCount)&&(K.liveSyncDuration||K.liveMaxLatencyDuration))throw new Error("Illegal hls.js config: don't mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration");if(K.liveMaxLatencyDurationCount!==void 0&&(K.liveSyncDurationCount===void 0||K.liveMaxLatencyDurationCount<=K.liveSyncDurationCount))throw new Error('Illegal hls.js config: "liveMaxLatencyDurationCount" must be greater than "liveSyncDurationCount"');if(K.liveMaxLatencyDuration!==void 0&&(K.liveSyncDuration===void 0||K.liveMaxLatencyDuration<=K.liveSyncDuration))throw new Error('Illegal hls.js config: "liveMaxLatencyDuration" must be greater than "liveSyncDuration"');var Q=rn(Y),re=["TimeOut","MaxRetry","RetryDelay","MaxRetryTimeout"];return["manifest","level","frag"].forEach(function(W){var J=(W==="level"?"playlist":W)+"LoadPolicy",ee=K[J]===void 0,Z=[];re.forEach(function(ae){var he=W+"Loading"+ae,fe=K[he];if(fe!==void 0&&ee){Z.push(he);var ye=Q[J].default;switch(K[J]={default:ye},ae){case"TimeOut":ye.maxLoadTimeMs=fe,ye.maxTimeToFirstByteMs=fe;break;case"MaxRetry":ye.errorRetry.maxNumRetry=fe,ye.timeoutRetry.maxNumRetry=fe;break;case"RetryDelay":ye.errorRetry.retryDelayMs=fe,ye.timeoutRetry.retryDelayMs=fe;break;case"MaxRetryTimeout":ye.errorRetry.maxRetryDelayMs=fe,ye.timeoutRetry.maxRetryDelayMs=fe}}}),Z.length&&R.warn('hls.js config: "'+Z.join('", "')+'" setting(s) are deprecated, use "'+J+'": '+JSON.stringify(K[J]))}),x(x({},Q),K)}(o.DefaultConfig,e);this.userConfig=e,this._autoLevelCapping=-1,t.progressive&&jl(t);var i=t.abrController,r=t.bufferController,a=t.capLevelController,s=t.errorController,l=t.fpsController,d=new s(this),c=this.abrController=new i(this),u=this.bufferController=new r(this),g=this.capLevelController=new a(this),m=new l(this),v=new ys(this),y=new Es(this),_=t.contentSteeringController,b=_?new _(this):null,E=this.levelController=new Ls(this,b),S=new Ds(this),C=new Is(this.config),L=this.streamController=new ol(this,S,C);g.setStreamController(L),m.setStreamController(L);var I=[v,E,L];b&&I.splice(1,0,b),this.networkControllers=I;var P=[c,u,g,m,y,S];this.audioTrackController=this.createController(t.audioTrackController,I);var N=t.audioStreamController;N&&I.push(new N(this,S,C)),this.subtitleTrackController=this.createController(t.subtitleTrackController,I);var M=t.subtitleStreamController;M&&I.push(new M(this,S,C)),this.createController(t.timelineController,P),C.emeController=this.emeController=this.createController(t.emeController,P),this.cmcdController=this.createController(t.cmcdController,P),this.latencyController=this.createController(As,P),this.coreComponents=P,I.push(d);var B=d.onErrorOut;typeof B=="function"&&this.on(A.ERROR,B,d)}o.isSupported=function(){return function(){var e=Ti();if(!e)return!1;var t=_a(),i=e&&typeof e.isTypeSupported=="function"&&e.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"'),r=!t||t.prototype&&typeof t.prototype.appendBuffer=="function"&&typeof t.prototype.remove=="function";return!!i&&!!r}()};var n=o.prototype;return n.createController=function(e,t){if(e){var i=new e(this);return t&&t.push(i),i}return null},n.on=function(e,t,i){i===void 0&&(i=this),this._emitter.on(e,t,i)},n.once=function(e,t,i){i===void 0&&(i=this),this._emitter.once(e,t,i)},n.removeAllListeners=function(e){this._emitter.removeAllListeners(e)},n.off=function(e,t,i,r){i===void 0&&(i=this),this._emitter.off(e,t,i,r)},n.listeners=function(e){return this._emitter.listeners(e)},n.emit=function(e,t,i){return this._emitter.emit(e,t,i)},n.trigger=function(e,t){if(this.config.debug)return this.emit(e,e,t);try{return this.emit(e,e,t)}catch(i){R.error("An internal error happened while handling event "+e+'. Error message: "'+i.message+'". Here is a stacktrace:',i),this.trigger(A.ERROR,{type:ne.OTHER_ERROR,details:O.INTERNAL_EXCEPTION,fatal:!1,event:e,error:i})}return!1},n.listenerCount=function(e){return this._emitter.listenerCount(e)},n.destroy=function(){R.log("destroy"),this.trigger(A.DESTROYING,void 0),this.detachMedia(),this.removeAllListeners(),this._autoLevelCapping=-1,this.url=null,this.networkControllers.forEach(function(t){return t.destroy()}),this.networkControllers.length=0,this.coreComponents.forEach(function(t){return t.destroy()}),this.coreComponents.length=0;var e=this.config;e.xhrSetup=e.fetchSetup=void 0,this.userConfig=null},n.attachMedia=function(e){R.log("attachMedia"),this._media=e,this.trigger(A.MEDIA_ATTACHING,{media:e})},n.detachMedia=function(){R.log("detachMedia"),this.trigger(A.MEDIA_DETACHING,void 0),this._media=null},n.loadSource=function(e){this.stopLoad();var t=this.media,i=this.url,r=this.url=er.buildAbsoluteURL(self.location.href,e,{alwaysNormalize:!0});R.log("loadSource:"+r),t&&i&&(i!==r||this.bufferController.hasSourceTypes())&&(this.detachMedia(),this.attachMedia(t)),this.trigger(A.MANIFEST_LOADING,{url:e})},n.startLoad=function(e){e===void 0&&(e=-1),R.log("startLoad("+e+")"),this.networkControllers.forEach(function(t){t.startLoad(e)})},n.stopLoad=function(){R.log("stopLoad"),this.networkControllers.forEach(function(e){e.stopLoad()})},n.swapAudioCodec=function(){R.log("swapAudioCodec"),this.streamController.swapAudioCodec()},n.recoverMediaError=function(){R.log("recoverMediaError");var e=this._media;this.detachMedia(),e&&this.attachMedia(e)},n.removeLevel=function(e,t){t===void 0&&(t=0),this.levelController.removeLevel(e,t)},D(o,[{key:"levels",get:function(){var e=this.levelController.levels;return e||[]}},{key:"currentLevel",get:function(){return this.streamController.currentLevel},set:function(e){R.log("set currentLevel:"+e),this.loadLevel=e,this.abrController.clearTimer(),this.streamController.immediateLevelSwitch()}},{key:"nextLevel",get:function(){return this.streamController.nextLevel},set:function(e){R.log("set nextLevel:"+e),this.levelController.manualLevel=e,this.streamController.nextLevelSwitch()}},{key:"loadLevel",get:function(){return this.levelController.level},set:function(e){R.log("set loadLevel:"+e),this.levelController.manualLevel=e}},{key:"nextLoadLevel",get:function(){return this.levelController.nextLoadLevel},set:function(e){this.levelController.nextLoadLevel=e}},{key:"firstLevel",get:function(){return Math.max(this.levelController.firstLevel,this.minAutoLevel)},set:function(e){R.log("set firstLevel:"+e),this.levelController.firstLevel=e}},{key:"startLevel",get:function(){return this.levelController.startLevel},set:function(e){R.log("set startLevel:"+e),e!==-1&&(e=Math.max(e,this.minAutoLevel)),this.levelController.startLevel=e}},{key:"capLevelToPlayerSize",get:function(){return this.config.capLevelToPlayerSize},set:function(e){var t=!!e;t!==this.config.capLevelToPlayerSize&&(t?this.capLevelController.startCapping():(this.capLevelController.stopCapping(),this.autoLevelCapping=-1,this.streamController.nextLevelSwitch()),this.config.capLevelToPlayerSize=t)}},{key:"autoLevelCapping",get:function(){return this._autoLevelCapping},set:function(e){this._autoLevelCapping!==e&&(R.log("set autoLevelCapping:"+e),this._autoLevelCapping=e)}},{key:"bandwidthEstimate",get:function(){var e=this.abrController.bwEstimator;return e?e.getEstimate():NaN}},{key:"ttfbEstimate",get:function(){var e=this.abrController.bwEstimator;return e?e.getEstimateTTFB():NaN}},{key:"maxHdcpLevel",get:function(){return this._maxHdcpLevel},set:function(e){br.indexOf(e)>-1&&(this._maxHdcpLevel=e)}},{key:"autoLevelEnabled",get:function(){return this.levelController.manualLevel===-1}},{key:"manualLevel",get:function(){return this.levelController.manualLevel}},{key:"minAutoLevel",get:function(){var e=this.levels,t=this.config.minAutoBitrate;if(!e)return 0;for(var i=e.length,r=0;r=t)return r;return 0}},{key:"maxAutoLevel",get:function(){var e,t=this.levels,i=this.autoLevelCapping,r=this.maxHdcpLevel;if(e=i===-1&&t&&t.length?t.length-1:i,r)for(var a=e;a--;){var s=t[a].attrs["HDCP-LEVEL"];if(s&&s<=r)return a}return e}},{key:"nextAutoLevel",get:function(){return Math.min(Math.max(this.abrController.nextAutoLevel,this.minAutoLevel),this.maxAutoLevel)},set:function(e){this.abrController.nextAutoLevel=Math.max(this.minAutoLevel,e)}},{key:"playingDate",get:function(){return this.streamController.currentProgramDateTime}},{key:"mainForwardBufferInfo",get:function(){return this.streamController.getMainFwdBufferInfo()}},{key:"audioTracks",get:function(){var e=this.audioTrackController;return e?e.audioTracks:[]}},{key:"audioTrack",get:function(){var e=this.audioTrackController;return e?e.audioTrack:-1},set:function(e){var t=this.audioTrackController;t&&(t.audioTrack=e)}},{key:"subtitleTracks",get:function(){var e=this.subtitleTrackController;return e?e.subtitleTracks:[]}},{key:"subtitleTrack",get:function(){var e=this.subtitleTrackController;return e?e.subtitleTrack:-1},set:function(e){var t=this.subtitleTrackController;t&&(t.subtitleTrack=e)}},{key:"media",get:function(){return this._media}},{key:"subtitleDisplay",get:function(){var e=this.subtitleTrackController;return!!e&&e.subtitleDisplay},set:function(e){var t=this.subtitleTrackController;t&&(t.subtitleDisplay=e)}},{key:"lowLatencyMode",get:function(){return this.config.lowLatencyMode},set:function(e){this.config.lowLatencyMode=e}},{key:"liveSyncPosition",get:function(){return this.latencyController.liveSyncPosition}},{key:"latency",get:function(){return this.latencyController.latency}},{key:"maxLatency",get:function(){return this.latencyController.maxLatency}},{key:"targetLatency",get:function(){return this.latencyController.targetLatency}},{key:"drift",get:function(){return this.latencyController.drift}},{key:"forceStartLoad",get:function(){return this.streamController.forceStartLoad}}],[{key:"version",get:function(){return"1.4.12"}},{key:"Events",get:function(){return A}},{key:"ErrorTypes",get:function(){return ne}},{key:"ErrorDetails",get:function(){return O}},{key:"DefaultConfig",get:function(){return o.defaultConfig?o.defaultConfig:Yl},set:function(e){o.defaultConfig=e}}]),o}();return go.defaultConfig=void 0,go},typeof exports=="object"&&typeof module<"u"?module.exports=f():typeof define=="function"&&define.amd?define(f):(p=typeof globalThis<"u"?globalThis:p||self).Hls=f()})(!1);const qi=["play","playing","timeupdate"],zc=Zi(),Yc=[{label:"2.0X",value:2},{label:"1.5X",value:1.5},{label:"1.0X",value:1},{label:"0.8X",value:.8},{label:"0.5X",value:.5}];class gn extends Fe(){constructor(){super(),H(this,"ctx"),H(this,"_player"),H(this,"_container"),H(this,"_slot"),H(this,"_playerController"),H(this,"_playerBtn"),H(this,"_progress"),H(this,"_progressDot"),H(this,"_progressWrap"),H(this,"_progressWrapValue"),H(this,"requestAnimationFrameId"),H(this,"moveProgress"),H(this,"_playerControllerBottom"),H(this,"_playerControllerBottomRight"),H(this,"_playerControllerBottomLeft"),H(this,"_playerControllerBottomPlayBtn"),H(this,"_playerControllerBottomTimeCurrent"),H(this,"_playerControllerBottomTimeDuration"),H(this,"_playerControllerBottomTimeDivide"),H(this,"_playControllerBottomClarity"),H(this,"_playControllerBottomSpeed"),H(this,"_playControllerBottomSpeedIcon"),H(this,"_playControllerBottomVolumeProgress"),H(this,"_playControllerBottomRightFullScreen"),H(this,"_playControllerBottomVolume"),H(this,"_playControllerBottomSpeedPopover"),H(this,"controllerBarTimeId"),H(this,"_playerTip"),H(this,"_playerTipTime"),H(this,"_playerTipText"),H(this,"_volume"),H(this,"_video"),H(this,"_hls"),H(this,"changeClarityToSetVideo",()=>{const{currentTime:f,playbackRate:w,volume:x,currentState:T}=this.ctx;this.setCurrentTime(f),this.setPlaybackRate(w),this.setVolume(x),qi.includes(T)?this.play():this.pause()}),H(this,"changeClarity",f=>{this.ctx.clarity=f.detail.value;const w=this.ctx.levelMap.get(f.detail.value);w&&this._hls&&(this._hls.loadSource(w),this._hls.startLoad(),this.changeClarityToSetVideo())}),H(this,"createClaritySelect",()=>{const{levels:f,url:w}=this.ctx;if(this._playControllerBottomClarity.innerHTML="",f.length<=0)return;const x=document.createDocumentFragment();f.forEach(G=>{const{name:F,url:q}=G;if(!F||!q)return;this.ctx.levelMap.set(F,q);const j=document.createElement("r-option");j.setAttribute("value",F),j.innerHTML=F,x.appendChild(j)});const T=document.createElement("r-select");T.setAttribute("value",this.ctx.clarity||"Auto"),T.appendChild(x),T.setAttribute("type","text"),T.setAttribute("trigger","hover,click"),T.setAttribute("placement","top");const D=this._player.getAttribute("id");D&&T.setAttribute("getPopupContainerId",D),T.setAttribute("dropdownclass","video-clarity-dropdown"),T.addEventListener("change",this.changeClarity),this._playControllerBottomClarity.appendChild(T)}),H(this,"manifestLoaded",(f,w)=>{if(f==="hlsManifestLoaded"){const{url:x,levels:T=[]}=w;if(T.length<=0)return;T.forEach(D=>{this.ctx.levelMap.get(D.name)!==D.url&&this.ctx.levels.push(D)}),this.ctx.levelMap.get("Auto")||(this.ctx.levels.push({name:"Auto",url:x}),this.ctx.levelMap.set("Auto",x)),this.ctx.url=x,this.createClaritySelect(),this.change("hlsManifestLoaded",{data:w})}}),H(this,"updatePlayer",()=>{var f;const w=window.Hls;this.innerHTML="",this.contains(this._player)||this.appendChild(this._player),this._hls&&(this._hls.destroy(),this._hls=void 0),this._video=document.createElement("video"),this._video.setAttribute("class","ran-player-video"),this._video.setAttribute("preload","auto"),this._video.setAttribute("x5-video-player-type","h5"),this._video.setAttribute("x5-video-orientation","portrait"),this._video.setAttribute("webkit-playsinline","true"),this._video.setAttribute("playsinline","true"),this._video.setAttribute("controls","false"),this._video.controls=!1,this._video.setAttribute("initial-time","0.01");try{this._video.canPlayType("application/vnd.apple.mpegurl")&&this.src?this._video.src=this.src:w!=null&&w.isSupported()&&this.src&&(this._hls=new w,this._hls&&(this._hls.off(w.Events.MANIFEST_LOADED,this.manifestLoaded),this._hls.on(w.Events.MANIFEST_LOADED,this.manifestLoaded),this._hls.off(w.Events.ERROR,this.hlsError),this._hls.on(w.Events.ERROR,this.hlsError),this._hls.loadSource(this.src),this._hls.attachMedia(this._video)),this._container.appendChild(this._video),(f=this._video.parentElement)==null||f.setAttribute("class","ran-player-contain")),this.listenEvent()}catch{}}),H(this,"hlsError",(f,w)=>{this.change("hlsError",{event:f,data:w}),this._video&&(this._video.src=this.src)}),H(this,"change",(f,w)=>{const x=this.getCurrentTime(),T=this.getTotalTime();this.debug&&console.log(f,w),this.dispatchEvent(new CustomEvent("change",{detail:{type:f,data:w,currentTime:x,duration:T,tag:this}}))}),H(this,"onCanplay",f=>{this.ctx.currentState=f.type,Ve(this._playerControllerBottomPlayBtn,"ran-player-controller-bottom-left-btn-pause"),Re(this._playerControllerBottomPlayBtn,"ran-player-controller-bottom-left-btn-play"),this.change("canplay",f),this.resize()}),H(this,"onCanplaythrough",f=>{this.ctx.currentState=f.type,this.change("canplaythrough",f)}),H(this,"onComplete",f=>{this.ctx.currentState=f.type,this.change("complete",f)}),H(this,"onDurationchange",f=>{this.ctx.currentState=f.type,this.change("durationchange",f)}),H(this,"onEmptied",f=>{this.ctx.currentState=f.type,this.change("emptied",f)}),H(this,"onEnded",f=>{this.ctx.currentState=f.type,this.change("ended",f)}),H(this,"onError",f=>{this.ctx.currentState=f.type,this.change("error",f)}),H(this,"onLoadedmetadata",f=>{this.ctx.currentState=f.type,this.change("loadedmetadata",f)}),H(this,"onLoadstart",f=>{this.ctx.currentState=f.type,this.change("loadstart",f)}),H(this,"onProgress",f=>{this.ctx.currentState=f.type,this.change("progress",f)}),H(this,"onRatechange",f=>{this.ctx.currentState=f.type,this.change("ratechange",f)}),H(this,"onSeeked",f=>{this.ctx.currentState=f.type,this.change("seeked",f)}),H(this,"onSeeking",f=>{this.ctx.currentState=f.type,this.change("seeking",f)}),H(this,"onStalled",f=>{this.ctx.currentState=f.type,this.change("stalled",f)}),H(this,"onSuspend",f=>{this.ctx.currentState=f.type,this.change("suspend",f)}),H(this,"onLoadeddata",f=>{this.ctx.currentState=f.type;const w=this.getTotalTime();this.ctx.duration=w,this._playerControllerBottomTimeCurrent.innerText="00:00",this._playerControllerBottomTimeDivide.innerText="/",this._playerControllerBottomTimeDuration.innerText=vi(this.ctx.duration),this.change("loadeddata",f)}),H(this,"onTimeupdate",f=>{this.ctx.currentState=f.type,this.change("timeupdate",f)}),H(this,"onVolumechange",f=>{this.ctx.currentState=f.type,this.change("volumechange",f)}),H(this,"onWaiting",f=>{this.ctx.currentState=f.type,this.change("waiting",f)}),H(this,"onPlay",f=>{this.ctx.currentState=f.type,this.requestAnimationFrame(this.updateCurrentProgress),Ve(this._playerControllerBottomPlayBtn,"ran-player-controller-bottom-left-btn-play"),Re(this._playerControllerBottomPlayBtn,"ran-player-controller-bottom-left-btn-pause"),this.showControllerBar(),this.change("play",f)}),H(this,"onPlaying",f=>{this.ctx.currentState=f.type,this._playerBtn.style.setProperty("display","none"),Ve(this._playerControllerBottomPlayBtn,"ran-player-controller-bottom-left-btn-play"),Re(this._playerControllerBottomPlayBtn,"ran-player-controller-bottom-left-btn-pause"),this.requestAnimationFrame(this.updateCurrentProgress),this.showControllerBar(),this.change("playing",f)}),H(this,"onPause",f=>{this.ctx.currentState=f.type,this._playerBtn.style.setProperty("display","block"),this.change("pause",f),Ve(this._playerControllerBottomPlayBtn,"ran-player-controller-bottom-left-btn-pause"),Re(this._playerControllerBottomPlayBtn,"ran-player-controller-bottom-left-btn-play"),this.cancelAnimationFrame(),this._playerController.style.setProperty("opacity","1"),this.controllerBarTimeId&&(clearTimeout(this.controllerBarTimeId),this.controllerBarTimeId=void 0)}),H(this,"clearListenerEvent",()=>{this._video&&(this._video.removeEventListener("canplay",this.onCanplay),this._video.removeEventListener("canplaythrough",this.onCanplaythrough),this._video.removeEventListener("complete",this.onComplete),this._video.removeEventListener("durationchange",this.onDurationchange),this._video.removeEventListener("emptied",this.onEmptied),this._video.removeEventListener("ended",this.onEnded),this._video.removeEventListener("error",this.onError),this._video.removeEventListener("loadeddata",this.onLoadeddata),this._video.removeEventListener("loadedmetadata",this.onLoadedmetadata),this._video.removeEventListener("loadstart",this.onLoadstart),this._video.removeEventListener("pause",this.onPause),this._video.removeEventListener("play",this.onPlay),this._video.removeEventListener("playing",this.onPlaying),this._video.removeEventListener("progress",this.onProgress),this._video.removeEventListener("ratechange",this.onRatechange),this._video.removeEventListener("seeked",this.onSeeked),this._video.removeEventListener("seeking",this.onSeeking),this._video.removeEventListener("stalled",this.onStalled),this._video.removeEventListener("suspend",this.onSuspend),this._video.removeEventListener("timeupdate",this.onTimeupdate),this._video.removeEventListener("volumechange",this.onVolumechange),this._video.removeEventListener("waiting",this.onWaiting))}),H(this,"listenEvent",()=>{this._video&&(this.clearListenerEvent(),this._video.addEventListener("canplay",this.onCanplay),this._video.addEventListener("canplaythrough",this.onCanplaythrough),this._video.addEventListener("complete",this.onComplete),this._video.addEventListener("durationchange",this.onDurationchange),this._video.addEventListener("emptied",this.onEmptied),this._video.addEventListener("ended",this.onEnded),this._video.addEventListener("error",this.onError),this._video.addEventListener("loadeddata",this.onLoadeddata),this._video.addEventListener("loadedmetadata",this.onLoadedmetadata),this._video.addEventListener("loadstart",this.onLoadstart),this._video.addEventListener("pause",this.onPause),this._video.addEventListener("play",this.onPlay),this._video.addEventListener("playing",this.onPlaying),this._video.addEventListener("progress",this.onProgress),this._video.addEventListener("ratechange",this.onRatechange),this._video.addEventListener("seeked",this.onSeeked),this._video.addEventListener("seeking",this.onSeeking),this._video.addEventListener("stalled",this.onStalled),this._video.addEventListener("suspend",this.onSuspend),this._video.addEventListener("timeupdate",this.onTimeupdate),this._video.addEventListener("volumechange",this.onVolumechange),this._video.addEventListener("waiting",this.onWaiting))}),H(this,"showControllerBar",f=>{if(f&&f.target.classList.value.includes("ran-player-controller")){this._playerController.style.setProperty("opacity","1"),this.controllerBarTimeId&&(clearTimeout(this.controllerBarTimeId),this.controllerBarTimeId=void 0);return}qi.includes(this.ctx.currentState)?(this._playerController.style.setProperty("opacity","1"),this.controllerBarTimeId&&(clearTimeout(this.controllerBarTimeId),this.controllerBarTimeId=void 0),this.controllerBarTimeId=setTimeout(()=>{this._playerController.style.setProperty("opacity","0"),clearTimeout(this.controllerBarTimeId),this.controllerBarTimeId=void 0},2e3)):(this._playerController.style.setProperty("opacity","1"),this.controllerBarTimeId&&(clearTimeout(this.controllerBarTimeId),this.controllerBarTimeId=void 0))}),H(this,"progressClick",f=>{const w=this._progressWrap.getBoundingClientRect(),x=f.clientX-w.left,T=At(x/this._progress.offsetWidth);this.setCurrentTime(this.ctx.duration*T),this.updateCurrentProgress()}),H(this,"progressDotMouseDown",f=>{this._playerBtn.style.setProperty("display","none"),this.moveProgress.mouseDown=!0,this.cancelAnimationFrame()}),H(this,"progressDotMouseMove",f=>{if(this.showControllerBar(f),!this.moveProgress.mouseDown)return;const w=this._progress.getBoundingClientRect(),x=f.clientX-w.left-9,T=At(x/this._progress.offsetWidth);this._progressWrapValue.style.setProperty("transform",`scaleX(${T})`),this._progressDot.style.setProperty("transform",`translateX(${T*this._progress.offsetWidth}px)`),this.moveProgress.percentage=Math.floor(T*100)/100}),H(this,"progressDotMouseUp",()=>{if(!this.moveProgress.mouseDown)return;const f=this.moveProgress.percentage;this.setCurrentTime(this.ctx.duration*f),this.play(),this.moveProgress.mouseDown=!1,this.requestAnimationFrame(this.updateCurrentProgress)}),H(this,"requestAnimationFrame",f=>{this.requestAnimationFrameId||(this.requestAnimationFrameId=window.requestAnimationFrame(()=>{f(),this.requestAnimationFrameId&&cancelAnimationFrame(this.requestAnimationFrameId),this.requestAnimationFrameId=void 0,this.requestAnimationFrame(f)}))}),H(this,"cancelAnimationFrame",()=>{this.requestAnimationFrameId&&(cancelAnimationFrame(this.requestAnimationFrameId),this.requestAnimationFrameId=void 0)}),H(this,"updateCurrentProgress",()=>{const f=this.getCurrentTime();this.ctx.currentTime=f;const{duration:w}=this.ctx;this._progressWrapValue.style.setProperty("transform",`scaleX(${f/w})`),this._progressDot.style.setProperty("transform",`translateX(${f/w*this._progress.offsetWidth}px)`),f>=0&&(this._playerControllerBottomTimeCurrent.innerText=vi(f))}),H(this,"changeAttribute",(f,w,x,T,D)=>{f===T&&w!==x&&zc(D)()}),H(this,"dispatchClickPlayerContainerAction",f=>{f.stopPropagation(),f.preventDefault(),qi.includes(this.ctx.currentState)?(this.pause(),this._playerBtn.style.setProperty("display","block")):(this.play(),this._playerBtn.style.setProperty("display","none"))}),H(this,"SpaceKeyDown",f=>{const{currentTime:w,duration:x}=this.ctx;if(f.code==="Space"&&this.dispatchClickPlayerBtnAction(f),f.code==="Escape"&&this.customExitFullscreen().then(()=>{this.ctx.fullScreen=!1}).catch(T=>{}),f.code==="ArrowLeft"){const T=At(w-5,0,x);this.setCurrentTime(T),this.play()}if(f.code==="ArrowRight"){const T=At(w+5,0,x);this.setCurrentTime(T),this.play()}}),H(this,"dispatchClickPlayerBtnAction",f=>{f.stopPropagation(),f.preventDefault(),qi.includes(this.ctx.currentState)?(this.pause(),this._playerBtn.style.setProperty("display","block")):(this.play(),this._playerBtn.style.setProperty("display","none"))}),H(this,"changeVolumeProgress",f=>{this._video&&(this.setVolume(f.detail.value),this.change("volume",f.detail.value),f.detail.value>0&&(this._volume=f.detail.value))}),H(this,"customRequestFullscreen",f=>this._player.requestFullscreen()||this._player.mozRequestFullScreen()||this._player.msRequestFullscreen()||this._player.oRequestFullscreen()||this._player.webkitRequestFullscreen()||this._player.webkitEnterFullscreen()),H(this,"customExitFullscreen",()=>document.exitFullscreen()||document.msExitFullscreen()||document.mozCancelFullScreen()||document.oCancelFullScreen()||document.webkitExitFullscreen()),H(this,"openFullScreen",()=>{this.ctx.fullScreen?this.customExitFullscreen().then(()=>{this.resize(),this.ctx.fullScreen=!1}).catch(f=>{}):this.customRequestFullscreen().then(()=>{this.resize(),this.ctx.fullScreen=!0}).catch(f=>{})}),H(this,"changeSpeed",f=>{this.change("speed",f.detail.value),this.setPlaybackRate(f.detail.value)}),H(this,"progressMouseEnter",f=>{this._playerTip.style.setProperty("opacity","1");const w=this._progress.getBoundingClientRect(),x=f.clientX-w.left;this._playerTipText.innerText?this._playerTip.style.setProperty("transform",`translate(calc(${x}px - 50%),-20px)`):this._playerTip.style.setProperty("transform",`translateX(calc(${x}px - 50%))`),this._playerTipTime.innerText=vi(x/this._progress.clientWidth*this.ctx.duration)}),H(this,"progressMouseLeave",f=>{f.target.classList.contains("ran-player-controller-progress-wrap-dot")||this._playerTip.style.setProperty("opacity","0")}),H(this,"progressMouseMove",f=>{const w=this._progress.getBoundingClientRect();this._playerTip.style.setProperty("opacity","1");const x=f.clientX-w.left;this._playerTipText.innerText?this._playerTip.style.setProperty("transform",`translate(calc(${x}px - 50%),-20px)`):this._playerTip.style.setProperty("transform",`translateX(calc(${x}px - 50%))`),this._playerTipTime.innerText=vi(x/this._progress.clientWidth*this.ctx.duration)}),H(this,"changePlayerVolume",()=>{if(!this._video)return;const{volume:f}=this.ctx;f>0?(Re(this._playControllerBottomSpeedIcon,"ran-player-controller-bottom-right-volume-icon-mute"),Ve(this._playControllerBottomSpeedIcon,"ran-player-controller-bottom-right-volume-icon-volume"),this._playControllerBottomVolumeProgress.setAttribute("percent","0"),this.setVolume(0),this.change("volume",0)):(Re(this._playControllerBottomSpeedIcon,"ran-player-controller-bottom-right-volume-icon-volume"),Ve(this._playControllerBottomSpeedIcon,"ran-player-controller-bottom-right-volume-icon-mute"),this._playControllerBottomVolumeProgress.setAttribute("percent",`${this._volume||.5}`),this.setVolume(.5),this.change("volume",this._volume||.5))}),H(this,"resize",()=>{if(this._video){const{width:f,height:w}=this._player.getBoundingClientRect();this._video.style.setProperty("width",`${f}px`),this._video.style.setProperty("height",`${w}px`),document.body.clientWidth<500?this._playControllerBottomVolume.style.setProperty("display","none"):this._playControllerBottomVolume.style.setProperty("display","flex")}this.updateCurrentProgress()}),H(this,"fullScreenChange",()=>{var f;(f=document.fullscreenElement)!=null&&f.classList.contains("ran-player")?(this.change("fullscreen",!0),this.ctx.fullScreen=!0):(this.change("fullscreen",!1),this.ctx.fullScreen=!1)}),H(this,"getPlaybackRate",()=>(this._video&&(this.ctx.playbackRate=this._video.playbackRate||0),this.ctx.playbackRate)),H(this,"setPlaybackRate",f=>(this._video&&(this.ctx.playbackRate=f,this._video.playbackRate=f),this.ctx.playbackRate)),H(this,"setVolume",f=>(this._video&&(this.ctx.volume=f,this._video.volume=f),this.ctx.volume)),H(this,"getVolume",()=>(this._video&&(this.ctx.volume=this._video.volume||0),this.ctx.volume)),H(this,"setCurrentTime",f=>(this._video&&(this.ctx.currentTime=f,this._video.currentTime=f),this.ctx.currentTime)),H(this,"getCurrentTime",()=>(this._video&&(this.ctx.currentTime=this._video.currentTime||0),this.ctx.currentTime)),H(this,"getTotalTime",()=>(this._video&&(this.ctx.duration=this._video.duration||0),this.ctx.duration)),H(this,"play",f=>{this._video&&(f!==void 0&&f>=0&&(this.ctx.currentTime=f,this._video.currentTime=f),this._video.play())}),H(this,"pause",()=>{this._video&&this._video.pause()}),this.innerHTML="",this._player=document.createElement("div"),this._container=document.createElement("div"),this._slot=document.createElement("slot"),this._playerBtn=document.createElement("div"),this._progress=document.createElement("div"),this._progressWrap=document.createElement("div"),this._progressWrapValue=document.createElement("div"),this._progressDot=document.createElement("div"),this._playerControllerBottom=document.createElement("div"),this._playerControllerBottomRight=document.createElement("div"),this._playerControllerBottomLeft=document.createElement("div"),this._player.setAttribute("class","ran-player"),this._player.setAttribute("id","ran-player"+`${performance.now()}`.replace(".","")),this._playerBtn.setAttribute("class","ran-player-play-btn"),this._progress.setAttribute("class","ran-player-controller-progress"),this._progressWrap.setAttribute("class","ran-player-controller-progress-wrap"),this._progressWrapValue.setAttribute("class","ran-player-controller-progress-wrap-value"),this._progressDot.setAttribute("class","ran-player-controller-progress-dot"),this._playerControllerBottom.setAttribute("class","ran-player-controller-bottom"),this._playerControllerBottomRight.setAttribute("class","ran-player-controller-bottom-right"),this._playerControllerBottomLeft.setAttribute("class","ran-player-controller-bottom-left"),this._playerControllerBottomPlayBtn=document.createElement("div"),this._playerControllerBottomPlayBtn.setAttribute("class","ran-player-controller-bottom-left-btn"),this._playerControllerBottomTimeCurrent=document.createElement("div"),this._playerControllerBottomTimeCurrent.setAttribute("class","ran-player-controller-bottom-left-time-current"),this._playerControllerBottomTimeDivide=document.createElement("div"),this._playerControllerBottomTimeDivide.setAttribute("class","ran-player-controller-bottom-left-time-divide"),this._playerControllerBottomTimeDuration=document.createElement("div"),this._playerControllerBottomTimeDuration.setAttribute("class","ran-player-controller-bottom-left-time-duration"),this._playControllerBottomSpeed=document.createElement("div"),this._playControllerBottomSpeed.setAttribute("class","ran-player-controller-bottom-right-speed"),this._playControllerBottomSpeedPopover=document.createElement("r-select"),this._playControllerBottomSpeedPopover.setAttribute("value","1"),this._playControllerBottomSpeedPopover.setAttribute("trigger","hover,click"),this._playControllerBottomSpeedPopover.setAttribute("type","text"),this._playControllerBottomSpeedPopover.setAttribute("placement","top");const h=this._player.getAttribute("id");h&&this._playControllerBottomSpeedPopover.setAttribute("getPopupContainerId",h),this._playControllerBottomSpeedPopover.setAttribute("dropdownclass","video-speed-dropdown"),this._playControllerBottomSpeedPopover.addEventListener("change",this.changeSpeed);const p=document.createDocumentFragment();Yc.forEach(f=>{const{label:w,value:x}=f,T=document.createElement("r-option");T.innerHTML=w,T.setAttribute("value",`${x}`),p.appendChild(T)}),this._playControllerBottomSpeedPopover.appendChild(p),this._playControllerBottomSpeed.appendChild(this._playControllerBottomSpeedPopover),this._playControllerBottomVolume=document.createElement("div"),this._playControllerBottomVolume.setAttribute("class","ran-player-controller-bottom-right-volume"),this._playControllerBottomVolumeProgress=document.createElement("r-progress"),this._playControllerBottomVolumeProgress.setAttribute("class","ran-player-controller-bottom-right-volume-progress"),this._playControllerBottomVolumeProgress.setAttribute("percent","0.5"),this._playControllerBottomVolumeProgress.setAttribute("type","drag"),this._playControllerBottomSpeedIcon=document.createElement("div"),this._playControllerBottomSpeedIcon.setAttribute("class","ran-player-controller-bottom-right-volume-icon ran-player-controller-bottom-right-volume-icon-volume"),this._playControllerBottomClarity=document.createElement("div"),this._playControllerBottomClarity.setAttribute("class","ran-player-controller-bottom-right-clarity"),this._playControllerBottomRightFullScreen=document.createElement("div"),this._playControllerBottomRightFullScreen.setAttribute("class","ran-player-controller-bottom-right-full"),this._playerController=document.createElement("div"),this._playerController.setAttribute("class","ran-player-controller"),this._playerTip=document.createElement("div"),this._playerTip.setAttribute("class","ran-player-controller-tip"),this._playerTipTime=document.createElement("div"),this._playerTipTime.setAttribute("class","ran-player-controller-tip-time"),this._playerTipText=document.createElement("div"),this._playerTipText.setAttribute("class","ran-player-controller-tip-text"),this._playerTip.appendChild(rt([this._playerTipTime,this._playerTipText])),this._playerController.appendChild(rt([this._playerTip,this._progress,this._playerControllerBottom])),this._player.appendChild(rt([this._container,this._slot,this._playerBtn,this._playerController])),this._progressWrap.appendChild(this._progressWrapValue),this._progress.appendChild(rt([this._progressWrap,this._progressDot])),this._playerControllerBottom.appendChild(rt([this._playerControllerBottomLeft,this._playerControllerBottomRight])),this._playerControllerBottomLeft.appendChild(rt([this._playerControllerBottomPlayBtn,this._playerControllerBottomTimeCurrent,this._playerControllerBottomTimeDivide,this._playerControllerBottomTimeDuration])),this._playControllerBottomVolume.appendChild(rt([this._playControllerBottomSpeedIcon,this._playControllerBottomVolumeProgress])),this._playerControllerBottomRight.appendChild(rt([this._playControllerBottomClarity,this._playControllerBottomSpeed,this._playControllerBottomVolume,this._playControllerBottomRightFullScreen])),this.ctx={currentTime:0,duration:0,currentState:"",action:new qo,volume:.5,playbackRate:1,clarity:"",fullScreen:!1,levels:[],url:"",levelMap:new Map},this.moveProgress={percentage:0,mouseDown:!1}}static get observedAttributes(){return["src","volume","currentTime","playbackRate","debug"]}get src(){return this.getAttribute("src")||""}set src(h){this.setAttribute("src",h||"")}get debug(){return this.getAttribute("debug")||""}set debug(h){this.setAttribute("debug",h||"")}get volume(){return this.getAttribute("volume")||""}set volume(h){this.setAttribute("volume",h||"")}get currentTime(){return this.getAttribute("currentTime")||""}set currentTime(h){this.setAttribute("currentTime",h||"")}get playbackRate(){return this.getAttribute("playbackRate")||""}set playbackRate(h){this.setAttribute("playbackRate",h||"")}connectedCallback(){this._container.addEventListener("click",this.dispatchClickPlayerContainerAction),this._playerBtn.addEventListener("click",this.dispatchClickPlayerBtnAction),this.addEventListener("keydown",this.SpaceKeyDown),this._progressDot.addEventListener("mousedown",this.progressDotMouseDown),this._playerControllerBottomPlayBtn.addEventListener("click",this.dispatchClickPlayerBtnAction),this._progress.addEventListener("click",this.progressClick),this._progress.addEventListener("mouseenter",this.progressMouseEnter),this._progress.addEventListener("mousemove",this.progressMouseMove),this._progress.addEventListener("mouseleave",this.progressMouseLeave),this._player.addEventListener("mousemove",this.progressDotMouseMove),this._player.addEventListener("mouseup",this.progressDotMouseUp),this._playControllerBottomVolumeProgress.addEventListener("change",this.changeVolumeProgress),this._playControllerBottomRightFullScreen.addEventListener("click",this.openFullScreen),this._playControllerBottomSpeedIcon.addEventListener("click",this.changePlayerVolume),document.addEventListener("fullscreenchange",this.fullScreenChange),window.addEventListener("resize",this.resize),this.updatePlayer()}disconnectCallback(){this._container.removeEventListener("click",this.dispatchClickPlayerContainerAction),this._playerBtn.removeEventListener("click",this.dispatchClickPlayerBtnAction),this._playerControllerBottomPlayBtn.removeEventListener("click",this.dispatchClickPlayerBtnAction),this.cancelAnimationFrame(),this.removeEventListener("keydown",this.SpaceKeyDown),this._progress.removeEventListener("click",this.progressClick),this._progress.removeEventListener("mouseenter",this.progressMouseEnter),this._progress.removeEventListener("mousemove",this.progressMouseMove),this._progress.removeEventListener("mouseleave",this.progressMouseLeave),this._progressDot.removeEventListener("mousedown",this.progressDotMouseDown),this._player.removeEventListener("mousemove",this.progressDotMouseMove),this._player.removeEventListener("mouseup",this.progressDotMouseUp),this._playControllerBottomVolumeProgress.removeEventListener("change",this.changeVolumeProgress),this._playControllerBottomRightFullScreen.removeEventListener("click",this.openFullScreen),window.removeEventListener("resize",this.resize),document.removeEventListener("fullscreenchange",this.fullScreenChange)}attributeChangedCallback(h,p,f){}}function jc(){if(typeof document<"u"&&!customElements.get("r-player"))return customElements.define("r-player",gn),gn}const qc=jc(),$c=Object.freeze(Object.defineProperty({__proto__:null,RanPlayer:gn,default:qc},Symbol.toStringTag,{value:"Module"}));function Qc(){if(typeof window<"u"&&!customElements.get("r-modal")){class k extends HTMLElement{constructor(){super()}}customElements.define("r-modal",k)}}const Wc=Qc(),Xc=Object.freeze(Object.defineProperty({__proto__:null,default:Wc},Symbol.toStringTag,{value:"Module"}));var Jc=Object.defineProperty,Zc=(k,h,p)=>h in k?Jc(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,Me=(k,h,p)=>Zc(k,typeof h!="symbol"?h+"":h,p);const eh=".remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}:host:active,:host:focus{outline:0;-webkit-tap-highlight-color:transparent}.ran-progress{position:var(--ran-progress-position, relative);cursor:var(--ran-progress-cursor, pointer);width:var(--ran-progress-width, 100%);height:var(--ran-progress-height, 100%)}.ran-progress:active,.ran-progress:focus{outline:0;-webkit-tap-highlight-color:transparent}.ran-progress-wrap{width:var(--ran-progress-wrap-width, 100%);height:var(--ran-progress-wrap-height, 8px);border-radius:var(--ran-progress-wrap-border-radius, 20px);background:var(--ran-progress-wrap-background, #5b5b5b);position:var(--ran-progress-wrap-position, relative);overflow:var(--ran-progress-wrap-overflow, hidden)}.ran-progress-wrap-value{position:var(--ran-progress-wrap-value-position, absolute);top:var(--ran-progress-wrap-value-top, 0);left:var(--ran-progress-wrap-value-left, 0);height:var(--ran-progress-wrap-value-height, 100%);width:var(--ran-progress-wrap-value-width, 100%);transform:var(--ran-progress-wrap-value-transform, scaleX(0));transform-origin:var(--ran-progress-wrap-value-transform-origin, 0 0);will-change:var(--ran-progress-wrap-value-will-change, transform);background:var(--ran-progress-wrap-value-background, linear-gradient(90deg, #0bc8bb 2.42%, #00d297 98.79%));border-radius:var(--ran-progress-wrap-value-border-radius, 20px)}.ran-progress-dot{position:var(--ran-progress-dot-position, absolute);top:var(--ran-progress-dot-top, -5px);left:var(--ran-progress-dot-left, -9px);border-radius:var(--ran-progress-dot-border-radius, 50%);width:var(--ran-progress-dot-width, 18px);height:var(--ran-progress-dot-height, 18px);background:var(--ran-progress-dot-background, linear-gradient(90deg, #0bc8bb 2.42%, #00d297 98.79%));cursor:var(--ran-progress-dot-cursor, pointer)}",th=["percent","type","total","dot"];class Wi extends Fe(){constructor(){super(),Me(this,"_progress"),Me(this,"_progressWrap"),Me(this,"_progressWrapValue"),Me(this,"_progressDot"),Me(this,"moveProgress"),Me(this,"_shadowDom"),Me(this,"progressClick",f=>{const w=this._progress.getBoundingClientRect(),x=f.clientX-w.left,T=Math.min(1,Math.max(0,x/this._progress.offsetWidth));this.percent=`${T*Number(this.total)}`,this._progressWrapValue.style.setProperty("transform",`scaleX(${T})`),this._progressDot.style.setProperty("transform",`translateX(${T*this._progress.offsetWidth}px)`),this.change()}),Me(this,"progressDotMouseDown",()=>{this.moveProgress.mouseDown=!0}),Me(this,"progressDotMouseMove",f=>{if(!this.moveProgress.mouseDown)return;const w=this._progress.getBoundingClientRect(),x=f.clientX-w.left,T=Math.min(1,Math.max(0,x/this._progress.offsetWidth));this.percent=`${T*Number(this.total)}`,this._progressWrapValue.style.setProperty("transform",`scaleX(${T})`),this._progressDot.style.setProperty("transform",`translateX(${T*this._progress.offsetWidth}px)`),this.change()}),Me(this,"progressDotMouseUp",f=>{this.moveProgress.mouseDown&&(this.moveProgress.mouseDown=!1)}),Me(this,"change",()=>{this.dispatchEvent(new CustomEvent("change",{detail:{value:this.percent,percent:this.percent,total:this.total}}))}),Me(this,"appendProgressDot",()=>{this.dot==="true"&&!this._progress.contains(this._progressDot)&&this._progress.appendChild(this._progressDot),this.dot==="false"&&this._progress.contains(this._progressDot)&&this._progress.removeChild(this._progressDot)}),Me(this,"updateCurrentProgress",()=>{const f=Number(this.percent)/Number(this.total);this._progressWrapValue.style.setProperty("transform",`scaleX(${f})`),this._progressDot.style.setProperty("transform",`translateX(${f*this._progress.offsetWidth}px)`)}),Me(this,"dragEvent",()=>{this.type==="drag"&&(this._progress.addEventListener("click",this.progressClick),this._progressDot.addEventListener("mousedown",this.progressDotMouseDown),document.addEventListener("mousemove",this.progressDotMouseMove),document.addEventListener("mouseup",this.progressDotMouseUp))}),Me(this,"resize",()=>{this.updateCurrentProgress()}),this._progress=document.createElement("div"),this._progress.setAttribute("class","ran-progress"),this._progress.setAttribute("role","progressbar"),this._progressWrap=document.createElement("div"),this._progressWrap.setAttribute("class","ran-progress-wrap"),this._progress.appendChild(this._progressWrap),this._progressWrapValue=document.createElement("div"),this._progressWrapValue.setAttribute("class","ran-progress-wrap-value"),this._progressWrap.appendChild(this._progressWrapValue),this._progressDot=document.createElement("div"),this._progressDot.setAttribute("class","ran-progress-dot"),this.moveProgress={mouseDown:!1},this._progress.appendChild(this._progressDot);const h=this.attachShadow({mode:"closed"}),p=document.createElement("style");p.textContent=eh,h.appendChild(p),this._shadowDom=h,h.appendChild(this._progress)}static get observedAttributes(){return th}get percent(){const h=this.getAttribute("percent")||"",p=Qi(h);return Number(p)>Number(this.total)?(console.error("percent must be < total"),this.total):`${Qi(h)}`}set percent(h){this.setAttribute("percent",`${h||0}`),this.setAttribute("aria-valuenow",`${h||0}`)}get total(){const h=this.getAttribute("total");return h?`${Qi(h)}`:"1"}set total(h){this.setAttribute("total",h||"")}get type(){const h=["primary","drag"],p=this.getAttribute("type")||"";return h.includes(p)?p:"primary"}set type(h){this.setAttribute("type",h||"primary")}get animation(){const h=["play","pause"],p=this.getAttribute("animation")||"";return h.includes(p)?p:"pause"}set animation(h){this.setAttribute("animation",h||"pause")}get dot(){const h=["true","false"],p=this.getAttribute("dot")||"";return h.includes(p)?p:"true"}set dot(h){this.setAttribute("dot",h||"true")}connectedCallback(){this.getAttribute("type")||this.setAttribute("type","primary"),this.dragEvent(),this.updateCurrentProgress(),window.addEventListener("resize",this.resize)}disconnectCallback(){this._progress.removeEventListener("click",this.progressClick),this._progressDot.removeEventListener("mousedown",this.progressDotMouseDown),document.removeEventListener("mousemove",this.progressDotMouseMove),document.removeEventListener("mouseup",this.progressDotMouseUp),window.removeEventListener("resize",this.resize)}attributeChangedCallback(h,p,f){p!==f&&(h==="dot"&&this.appendProgressDot(),h==="percent"&&this.updateCurrentProgress())}}function ih(){return typeof document<"u"&&!customElements.get("r-progress")?(Wi&&customElements.define("r-progress",Wi),Wi):Ie("document is undefined or r-progress is exist")}const rh=ih(),nh=Object.freeze(Object.defineProperty({__proto__:null,Progress:Wi,default:rh},Symbol.toStringTag,{value:"Module"}));var ah=Object.defineProperty,oh=(k,h,p)=>h in k?ah(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,Lt=(k,h,p)=>oh(k,typeof h!="symbol"?h+"":h,p);const sh='.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}:host{position:var(--ran-checkbox-host-position, relative);display:var(--ran-checkbox-host-display, block);margin:var(--ran-checkbox-host-margin, 0);padding:var(--ran-checkbox-host-padding, 0);box-sizing:var(--ran-checkbox-host-box-sizing, border-box);list-style:var(--ran-checkbox-host-list-style, none)}:host([disabled]){opacity:var(--ran-checkbox-disabled-opacity, .6)}:host([disabled]) .ran-checkbox-input{cursor:var(--ran-checkbox-disabled-cursor, not-allowed);pointer-events:var(--ran-checkbox-disabled-pointer-events, all)}:host([disabled]) .ran-checkbox-inner{background-color:var(--ran-checkbox-checked-background-color, #d9d9d9);border:1px solid #d9d9d9}:host([disabled]) .ran-checkbox-inner:after{cursor:not-allowed;pointer-events:none;opacity:var(--ran-checkbox-checked-after-opacity, 1)}:host([disabled]) .ran-checkbox-checked .ran-checkbox-inner{background-color:var(--ran-checkbox-checked-background-color, #d9d9d9)}:host([disabled]) .ran-checkbox-checked .ran-checkbox-inner:after{opacity:var(--ran-checkbox-checked-after-opacity, 0)}.ran-checkbox{position:var(--ran-checkbox-position, relative);display:var(--ran-checkbox-display, block);box-sizing:var(--ran-checkbox-box-sizing, border-box);margin:var(--ran-checkbox-margin, 0);width:var(--ran-checkbox-width, 16px);height:var(--ran-checkbox-height, 16px);padding:var(--ran-checkbox-padding, 0);color:var(--ran-checkbox-color, rgba(0, 0, 0, .88));font-size:var(--ran-checkbox-font-size, 14px);line-height:var(--ran-checkbox-line-height, 1);list-style:var(--ran-checkbox-list-style, none);font-family:var(--ran-checkbox-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");white-space:var(--ran-checkbox-white-space, nowrap);cursor:var(--ran-checkbox-cursor, pointer);border-radius:var(--ran-checkbox-border-radius, 4px)}.ran-checkbox-input{position:var(--ran-checkbox-input-position, absolute);inset:var(--ran-checkbox-input-inset, 0);z-index:var(--ran-checkbox-input-z-index, 1);cursor:var(--ran-checkbox-input-cursor, pointer);opacity:var(--ran-checkbox-input-opacity, 0);margin:var(--ran-checkbox-input-margin, 0)}.ran-checkbox-inner{box-sizing:var(--ran-checkbox-inner-box-sizing, border-box);display:var(--ran-checkbox-inner-display, block);width:var(--ran-checkbox-inner-width, 16px);height:var(--ran-checkbox-inner-height, 16px);direction:var(--ran-checkbox-inner-direction, ltr);background-color:var(--ran-checkbox-inner-background-color, #fff);border:var(--ran-checkbox-inner-border, 1px solid #d9d9d9);border-radius:var(--ran-checkbox-inner-border-radius, 4px);border-collapse:var(--ran-checkbox-inner-border-collapse, separate)}.ran-checkbox-inner:after{box-sizing:var(--ran-checkbox-inner-after-box-sizing, border-box);position:var(--ran-checkbox-inner-after-position, absolute);top:var(--ran-checkbox-inner-after-top, 50%);inset-inline-start:var(--ran-checkbox-inner-after-inset-inline-start, 25%);display:var(--ran-checkbox-inner-after-display, table);width:var(--ran-checkbox-inner-after-width, calc(16px / 14 * 5));height:var(--ran-checkbox-inner-after-height, calc(16px / 14 * 8));border:var(--ran-checkbox-inner-after-border, 2px solid #fff);border-top:var(--ran-checkbox-inner-after-border-top, 0);border-inline-start:var(--ran-checkbox-inner-after-border-inline-start, 0);opacity:var(--ran-checkbox-inner-after-opacity, 0);content:var(--ran-checkbox-inner-after-content, "");transition:var(--ran-checkbox-inner-after-transition, all .1s cubic-bezier(.71, -.46, .88, .6), opacity .1s);transform:var(--ran-checkbox-inner-after-transform, rotate(45deg) scale(1) translate(-50%, -50%))}.ran-checkbox-checked .ran-checkbox-inner{background-color:var(--ran-checkbox-checked-background-color, #1677ff);border:var(--ran-checkbox-checked-border, 1px solid #1677ff)}.ran-checkbox-checked .ran-checkbox-inner:after{opacity:var(--ran-checkbox-checked-after-opacity, 1)}';class mn extends Fe(){constructor(){super(),Lt(this,"checkInput"),Lt(this,"checkInner"),Lt(this,"context"),Lt(this,"container"),Lt(this,"_shadowDom"),Lt(this,"updateChecked",()=>{const{checked:f}=this.context;f?(this.setAttribute("checked","true"),this.setAttribute("value","true"),Re(this.container,"ran-checkbox-checked")):(this.setAttribute("checked","false"),this.setAttribute("value","false"),Ve(this.container,"ran-checkbox-checked"))}),Lt(this,"update",()=>{this.updateChecked()}),Lt(this,"onChange",()=>{if(nt.includes(this.disabled)||this.hasAttribute("disabled"))return;const{checked:f}=this.context;this.context.checked=!f,this.dispatchEvent(new CustomEvent("change",{detail:{checked:this.context.checked}})),this.update()}),this.checkInput=document.createElement("input"),this.checkInput.setAttribute("class","ran-checkbox-input"),this.checkInput.setAttribute("type","checkbox"),this.checkInner=document.createElement("span"),this.checkInner.setAttribute("class","ran-checkbox-inner"),this.container=z("div").setAttribute("class","ran-checkbox").addChild([this.checkInput,this.checkInner]).element;const h=this.attachShadow({mode:"closed"}),p=document.createElement("style");p.textContent=sh,h.appendChild(p),this._shadowDom=h,h.appendChild(this.container),this.context={checked:!1}}static get observedAttributes(){return["disabled","checked","value"]}get disabled(){return this.getAttribute("disabled")||""}set disabled(h){this.setAttribute("disabled",h)}get value(){const h=this.getAttribute("value");return nt.includes(h)&&(this.context.checked=!1),`${this.context.checked}`}set value(h){nt.includes(h)?(this.setAttribute("value","false"),this.context.checked=!1):(this.setAttribute("value","true"),this.context.checked=!0),this.updateChecked()}get checked(){const h=this.getAttribute("checked");return nt.includes(h)&&(this.context.checked=!1),`${this.context.checked}`}set checked(h){nt.includes(h)?(this.setAttribute("checked","false"),this.context.checked=!1):(this.setAttribute("checked","true"),this.context.checked=!0),this.updateChecked()}connectedCallback(){this.addEventListener("click",this.onChange)}disconnectCallback(){this.removeEventListener("click",this.onChange)}attributeChangedCallback(h,p,f){p!==f&&(h==="checked"&&(this.checked=f,this.value=f),h==="value"&&(this.checked=f,this.value=f))}}function lh(){return typeof document<"u"&&!customElements.get("r-checkbox")?(customElements.define("r-checkbox",mn),mn):Ie("document is undefined or r-checkbox is exist")}const dh=lh(),ch=Object.freeze(Object.defineProperty({__proto__:null,Checkbox:mn,default:dh},Symbol.toStringTag,{value:"Module"}));var hh=Object.defineProperty,uh=(k,h,p)=>h in k?hh(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,we=(k,h,p)=>uh(k,typeof h!="symbol"?h+"":h,p);const fh=".remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}:host{display:var(--ran-popover-host-display, inline-block)}.ran-popover{box-sizing:var(--ran-popover-box-sizing, border-box);position:var(--ran-popover-position, relative);display:var(--ran-popover-display, inline-block);margin:var(--ran-popover-margin, 0);padding:var(--ran-popover-padding, 0)}.ran-popover-block{display:var(--ran-popover-block-display, inline-block)}",ph=".remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}:host{visibility:hidden;position:absolute}";class No extends Fe(){constructor(){super(),we(this,"observer"),we(this,"_shadowDom"),we(this,"_slot"),we(this,"callback",(f,w)=>{for(const x of f)x.type==="childList"?this.onChange(x):x.type==="attributes"&&this.onChange(x)}),we(this,"onChange",f=>{this.dispatchEvent(new CustomEvent("change",{detail:{type:f.type,value:{content:this.children,mutation:f}}}))}),this._slot=z("slot").setAttribute("class","slot").element;const h=this.attachShadow({mode:"closed"});this._shadowDom=h;const p=z("style").setTextContent(ph);h.appendChild(p.element),h.appendChild(this._slot),this.observer=new MutationObserver(this.callback)}connectedCallback(){this.observer.observe(this,{attributes:!0,childList:!0,subtree:!0})}disconnectCallback(){this.observer.disconnect()}}function gh(){return typeof document<"u"&&!customElements.get("r-content")?(customElements.define("r-content",No),No):Ie("document is undefined or r-content is exist")}gh();const ln=4,Uo=300,Go={bottom:{add:"ran-dropdown-down-in",remove:"ran-dropdown-down-out"},top:{add:"ran-dropdown-up-in",remove:"ran-dropdown-up-out"}};class vn extends Fe(){constructor(){super(),we(this,"_slot"),we(this,"popoverBlock"),we(this,"popoverContent"),we(this,"popoverInner"),we(this,"popoverInnerBlock"),we(this,"_shadowDom"),we(this,"dropDownInTimeId"),we(this,"dropDownOutTimeId"),we(this,"removeTimeId"),we(this,"stopPropagation",f=>{f.stopPropagation()}),we(this,"createContent",f=>{var w,x,T;if(f){if(!this.popoverContent){const D=document.createElement("div");this.popoverContent=z("r-dropdown").setAttribute("class","ran-popover-dropdown").setStyle("display","none").setStyle("position","absolute").element,(w=this.popoverContent)==null||w.addEventListener("click",this.stopPropagation),this.popoverContent&&D.appendChild(this.popoverContent),this.trigger.includes("hover")&&!_t()&&((x=this.popoverContent)==null||x.addEventListener("mouseleave",this.blur),(T=this.popoverContent)==null||T.addEventListener("mouseenter",this.removeDropDownTimeId)),document.body.appendChild(D)}if(this.popoverContent&&f.length>0){this.popoverContent.innerHTML="";const D=document.createDocumentFragment();for(const G of f)D.appendChild(G);this.popoverContent.appendChild(D)}}}),we(this,"watchContent",f=>{const{value:w}=f.detail;this.createContent(w.content)}),we(this,"blur",()=>{this.removeTimeId&&this.removeDropDownTimeId(),this.removeTimeId=setTimeout(()=>{this.removeDropDownTimeId(),this.setDropdownDisplayNone()},300)}),we(this,"removeDropDownTimeId",()=>{this.trigger.includes("hover")&&!_t()&&(clearTimeout(this.removeTimeId),this.removeTimeId=void 0)}),we(this,"setDropdownDisplayBlock",()=>{var f;this.dropDownInTimeId||this.popoverContent&&this.popoverContent.style.display!=="block"&&(this.popoverContent.setAttribute("transit",Go[this.placement].add),(f=this.popoverContent)==null||f.style.setProperty("display","block"),this.dropDownInTimeId=setTimeout(()=>{this.popoverContent&&this.popoverContent.removeAttribute("transit"),clearTimeout(this.dropDownInTimeId),this.dropDownInTimeId=void 0},Uo))}),we(this,"setDropdownDisplayNone",()=>{this.dropDownOutTimeId||this.popoverContent&&this.popoverContent.style.display!=="none"&&(this.popoverContent.setAttribute("transit",Go[this.placement].remove),this.dropDownOutTimeId=setTimeout(()=>{var f;(f=this.popoverContent)==null||f.style.setProperty("display","none"),this.popoverContent&&this.popoverContent.removeAttribute("transit"),clearTimeout(this.dropDownOutTimeId),this.dropDownOutTimeId=void 0},Uo))}),we(this,"placementPosition",()=>{if(!this.popoverContent)return;const f=this.getBoundingClientRect(),{top:w,left:x,bottom:T,width:D,height:G}=f;let F=T+window.scrollY+ln,q=x+window.scrollX;const j=document.getElementById(this.getPopupContainerId),de=this.popoverContent.getBoundingClientRect();if(this.placement==="top"&&(F=w+window.scrollY-de.height-ln,this.getPopupContainerId&&j)){const te=j.getBoundingClientRect();q=x-te.left,F=w-j.getBoundingClientRect().top-this.popoverContent.clientHeight-ln,q=x-j.getBoundingClientRect().left}this.popoverContent.style.setProperty("inset",`${F}px auto auto ${q}px`),this.popoverContent.style.setProperty("--ran-x",`${q}px`),this.popoverContent.style.setProperty("--ran-y",`${F}px`),this.popoverContent.style.setProperty("--ran-popover-width",`${D}px`),this.popoverContent.style.setProperty("--ran-popover-height",`${de.height}px`)}),we(this,"hoverPopover",f=>{this.clickPopover(f)}),we(this,"clickContent",f=>{f.stopPropagation()}),we(this,"clickPopover",f=>{f.stopPropagation(),f.preventDefault(),this.setDropdownDisplayBlock(),this.placementPosition()}),we(this,"clickRemovePopover",f=>{this.hoverRemovePopover(f)}),we(this,"popoverTrigger",()=>{this.removeEventListener("mouseenter",this.hoverPopover),this.removeEventListener("mouseleave",this.blur),this.removeEventListener("click",this.clickPopover),this.trigger.includes("hover")&&(this.addEventListener("mouseenter",this.hoverPopover),this.addEventListener("mouseleave",this.blur)),this.addEventListener("click",this.clickPopover)}),we(this,"hoverRemovePopover",f=>{f.stopPropagation(),this.setDropdownDisplayNone()}),we(this,"changePlacement",()=>{var f;if(this.placement){const w=this.placement==="bottom"?"top":"bottom";(f=this.popoverContent)==null||f.setAttribute("arrow",w)}}),this._slot=document.createElement("slot"),this._slot.setAttribute("class","slot"),this.popoverBlock=document.createElement("div"),this.popoverBlock.setAttribute("class","ran-popover-block"),this.popoverBlock.setAttribute("role","tooltip"),this.popoverBlock.appendChild(this._slot);const h=this.attachShadow({mode:"closed"}),p=document.createElement("style");p.textContent=fh,h.appendChild(p),this._shadowDom=h,h.appendChild(this.popoverBlock)}static get observedAttributes(){return["placement","arrow","trigger"]}get placement(){return this.getAttribute("placement")||"top"}set placement(h){this.setAttribute("placement",h)}get arrow(){return this.getAttribute("arrow")||""}set arrow(h){this.setAttribute("arrow",h)}get trigger(){return this.getAttribute("trigger")||"hover"}set trigger(h){this.setAttribute("trigger",h)}get getPopupContainerId(){return this.getAttribute("getPopupContainerId")||""}set getPopupContainerId(h){this.setAttribute("getPopupContainerId",h)}connectedCallback(){for(const h of this.children)h.tagName==="R-CONTENT"&&(h.addEventListener("change",this.watchContent),this.createContent(h.children));this.popoverTrigger(),this.changePlacement(),document.addEventListener("click",this.clickRemovePopover)}disconnectCallback(){this.removeEventListener("mouseenter",this.hoverPopover),this.removeEventListener("mouseleave",this.hoverRemovePopover),this.removeEventListener("click",this.hoverPopover),document.removeEventListener("click",this.clickRemovePopover)}attributeChangedCallback(h,p,f){p!==f&&(h==="trigger"&&this.popoverTrigger(),h==="placement"&&this.changePlacement())}}function mh(){return typeof document<"u"&&!customElements.get("r-popover")?(customElements.define("r-popover",vn),vn):Ie("document is undefined or r-popover is exist")}const vh=mh(),bh=Object.freeze(Object.defineProperty({__proto__:null,Popover:vn,default:vh},Symbol.toStringTag,{value:"Module"}));var yh=Object.defineProperty,wh=(k,h,p)=>h in k?yh(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,Ke=(k,h,p)=>wh(k,typeof h!="symbol"?h+"":h,p);class Ho extends Fe(){constructor(){super(),Ke(this,"_input"),Ke(this,"_label"),Ke(this,"_inputContent"),Ke(this,"_icon"),Ke(this,"customInput",h=>{h.stopPropagation(),h.preventDefault();const{target:p,data:f=""}=h;this.value=(p==null?void 0:p.value)||f||"",this.customChange(),this.dispatchEvent(new CustomEvent("input",{detail:{value:this.value}}))}),Ke(this,"customChange",()=>{this.dispatchEvent(new CustomEvent("change",{detail:{value:this.value}}))}),Ke(this,"listenPlaceholder",(h,p)=>{h==="placeholder"&&this._inputContent&&(p!=null?this._inputContent.setAttribute("placeholder",p):this._inputContent.removeAttribute("placeholder"))}),Ke(this,"listenLabel",(h,p)=>{h==="label"&&this._inputContent&&(p!=null?this._label?this._label.innerHTML=p:(this._label=document.createElement("label"),this._label.innerHTML=p,this._label.setAttribute("class","ran-input-label"),this._label.setAttribute("part","ran-input-label"),this._input.appendChild(this._label)):(this._input.removeAttribute("label"),this._label&&(this._input.removeChild(this._label),this._label=void 0)))}),Ke(this,"listenType",(h,p)=>{h==="type"&&this._inputContent&&(p?this._inputContent.setAttribute("type",p):(this._inputContent.removeAttribute("type"),this._inputContent.removeAttribute("min"),this._inputContent.removeAttribute("max"),this._inputContent.removeAttribute("step")))}),Ke(this,"listenStatus",(h,p)=>{h==="status"&&this._input&&(p?this._input.setAttribute("status",p):this._input.removeAttribute("status"))}),Ke(this,"listenDisabled",(h,p)=>{h==="disabled"&&this._input&&(nt.includes(p)?this._input.removeAttribute("disabled"):(this._input.setAttribute("disabled",""),this._inputContent.setAttribute("disabled","")))}),Ke(this,"listenIcon",(h,p,f)=>{h==="icon"&&p&&p!==f&&(this.removeAttribute("label"),this.setAttribute("icon",p),this.dealIcon())}),Ke(this,"dealIcon",()=>{if(!this._icon){this._icon=document.createElement("ra-icon");const{width:h,height:p}=this._inputContent.getBoundingClientRect(),f=Math.min(h,p);this._icon.setAttribute("size",`${f}`),this._inputContent.insertAdjacentElement("beforebegin",this._icon)}this.icon&&this._icon.setAttribute("name",this.icon)}),Ke(this,"listenEvent",(h,p,f)=>{this.listenPlaceholder(h,f),this.listenLabel(h,f),this.listenStatus(h,f),this.listenDisabled(h,f),this.listenIcon(h,f,p),h==="value"&&p!==f&&(this._inputContent.value=f,this._input.setAttribute("value",f))}),this._input=document.createElement("div"),this._input.setAttribute("class","ran-input"),this._input.setAttribute("part","ran-input"),this._inputContent=document.createElement("input"),this._inputContent.setAttribute("class","ran-input-content"),this._inputContent.setAttribute("part","ran-input-content"),this._input.appendChild(this._inputContent)}static get observedAttributes(){return["label","disabled","name","placeholder","type","icon","value","status","prefix","suffix","allowclear","count","maxlength","showcount","onPressEnter","variant","minrows","maxrows"]}get value(){return this.getAttribute("value")||""}set value(h){!Ce(this)&&h?(this.setAttribute("value",h),this._input.setAttribute("value",h)):(this.removeAttribute("value"),this._input.removeAttribute("value"))}get placeholder(){return this.getAttribute("placeholder")||""}set placeholder(h){h?this.setAttribute("placeholder",h):this.removeAttribute("placeholder")}get required(){return this.getAttribute("required")||""}set required(h){!h||h==="false"?this.removeAttribute("required"):this.setAttribute("required","")}get disabled(){return`${Ce(this)}`}set disabled(h){nt.includes(h)?(this.removeAttribute("disabled"),this._input.removeAttribute("disabled"),this._inputContent.removeAttribute("disabled")):(this.setAttribute("disabled",""),this._input.setAttribute("disabled",""),this._inputContent.setAttribute("disabled",""))}get label(){return this.getAttribute("label")||""}set label(h){this.setAttribute("label",h)}get status(){return this.getAttribute("status")||""}set status(h){h?(this.setAttribute("status",h),this._input.setAttribute("status",h)):(this.removeAttribute("status"),this._input.removeAttribute("status"))}get name(){return this.getAttribute("name")||""}set name(h){this.setAttribute("name",h)}get min(){return this.getAttribute("min")||""}set min(h){this.type==="number"&&this.setAttribute("min",h)}get max(){return this.getAttribute("max")||""}set max(h){this.type==="number"&&this.setAttribute("max",h)}get step(){return this.getAttribute("step")||""}set step(h){this.type==="number"&&this.setAttribute("step",h)}get icon(){return this.getAttribute("icon")||""}set icon(h){h?this.setAttribute("icon",h):this.removeAttribute("icon")}get prefix(){return this.getAttribute("prefix")||""}set prefix(h){h?this.setAttribute("prefix",h):this.removeAttribute("prefix")}get suffix(){return this.getAttribute("suffix")||""}set suffix(h){h?this.setAttribute("suffix",h):this.removeAttribute("suffix")}get type(){return this.getAttribute("type")||""}set type(h){h?this.setAttribute("type",h):this.removeAttribute("type")}connectedCallback(){this.value&&(this._inputContent.value=this.value,this._input.setAttribute("value",this.value)),this.status&&this._input.setAttribute("status",this.status),Ce(this)&&(this._input.setAttribute("disabled",""),this._inputContent.setAttribute("disabled","")),this.type&&this._inputContent.setAttribute("type",this.type),this._inputContent.addEventListener("input",this.customInput),document.readyState==="complete"&&this.dealIcon(),this.appendChild(this._input)}disconnectCallback(){this._inputContent.removeEventListener("input",this.customInput)}attributeChangedCallback(h,p,f){this.listenEvent(h,p,f)}}function Eh(){return typeof window<"u"&&!customElements.get("ra-input")?(customElements.define("ra-input",Ho),Ho):Ie("document is undefined or ra-input is exist")}Eh();var Ah=Object.defineProperty,_h=(k,h,p)=>h in k?Ah(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,Dt=(k,h,p)=>_h(k,typeof h!="symbol"?h+"":h,p);const Ko="http://www.w3.org/1999/xlink",kh="xlink:href";function xh(){if(typeof window<"u"&&!customElements.get("ra-icon")){class k extends HTMLElement{constructor(){super(),Dt(this,"_icon"),Dt(this,"_div"),Dt(this,"loadLocal",()=>new Promise((p,f)=>{Ji(Object.assign({"../../assets/icons/add-user.svg":()=>V(()=>import("./add-user-BN1JlY7e.D6YNNzf8.js"),[]),"../../assets/icons/arrow-down.svg":()=>V(()=>Promise.resolve().then(()=>cn),void 0).then(w=>w.j),"../../assets/icons/book.svg":()=>V(()=>import("./book-nTEFXU2x.DPEdiL1I.js"),[]),"../../assets/icons/check-circle-fill.svg":()=>V(()=>import("./check-circle-fill-B_pd8ZSs.Dxgzakn4.js"),[]),"../../assets/icons/check-circle.svg":()=>V(()=>import("./check-circle-szyAJiap.CM_vbBX5.js"),[]),"../../assets/icons/close-circle-fill.svg":()=>V(()=>import("./close-circle-fill-jSqPPw9i.BsLXh5-a.js"),[]),"../../assets/icons/close-circle.svg":()=>V(()=>import("./close-circle-CwmuN2C6.D612j4KD.js"),[]),"../../assets/icons/close.svg":()=>V(()=>import("./close-CFnkhudp.IMqD2L1-.js"),[]),"../../assets/icons/drop.svg":()=>V(()=>Promise.resolve().then(()=>un),void 0).then(w=>w.d),"../../assets/icons/eye-close.svg":()=>V(()=>import("./eye-close-BVr3NJtg.DsdsDDgX.js"),[]),"../../assets/icons/eye.svg":()=>V(()=>import("./eye-D_mEt17f.DJFa_ttF.js"),[]),"../../assets/icons/home.svg":()=>V(()=>import("./home-BUQ4USMk.BqTharGj.js"),[]),"../../assets/icons/info-circle-fill.svg":()=>V(()=>import("./info-circle-fill-CFeVMdci.CUxFtRNn.js"),[]),"../../assets/icons/info-circle.svg":()=>V(()=>import("./info-circle-COnL5bTJ.B9YJorcw.js"),[]),"../../assets/icons/loading-scene.svg":()=>V(()=>import("./loading-scene-BMc2wqKm.Di19NrRU.js"),[]),"../../assets/icons/loading.svg":()=>V(()=>import("./loading-Dcc5RApI.D3l74EUI.js"),[]),"../../assets/icons/lock.svg":()=>V(()=>import("./lock-Cr7BnmWN.0WfYXC2j.js"),[]),"../../assets/icons/message.svg":()=>V(()=>import("./message-D36_Zo2l.CR8K3LhI.js"),[]),"../../assets/icons/power-off.svg":()=>V(()=>import("./power-off-lQRbiBak.r13EH4bb.js"),[]),"../../assets/icons/preview.svg":()=>V(()=>import("./preview-CJbz9GjO.C8N16-9H.js"),[]),"../../assets/icons/setting.svg":()=>V(()=>import("./setting-DemlgzVC.DkD4YPwp.js"),[]),"../../assets/icons/sprite.svg":()=>V(()=>import("./sprite-CH2zLtZy.Djo3sTkk.js"),[]),"../../assets/icons/team.svg":()=>V(()=>import("./team-tl4NJXPC.D7881a1v.js"),[]),"../../assets/icons/unlock.svg":()=>V(()=>import("./unlock-CeU74z9n.58atcEuH.js"),[]),"../../assets/icons/user.svg":()=>V(()=>import("./user-B-eVXwuk.DyoYYAjs.js"),[]),"../../assets/icons/warning-circle-fill.svg":()=>V(()=>import("./warning-circle-fill-lODUKz0i.7RyGfSeR.js"),[]),"../../assets/icons/warning-circle.svg":()=>V(()=>import("./warning-circle-DDUgEDIv.1BX6MOiy.js"),[])}),`../../assets/icons/${this.name}.svg`,5).then(w=>{if(w&&w.default&&w.default._identification){const{data:x}=w.default;this._icon&&this._div.removeChild(this._icon),this._icon=Xi(x,"image/svg+xml"),this._icon&&(this._div.appendChild(this._icon),this.setSize(),this.setColor(),p())}else this.loadNs(),f(` + couldn't be loaded by ra-icon, message: ${this.name} icon is undefined`)}).catch(w=>{this.loadNs()})})),Dt(this,"loadNs",()=>{this._icon&&this._div&&this._div.removeChild(this._icon),this._icon=document.createElement("svg"),this._icon.setAttribute("class","icon"),this._icon.setAttribute("viewBox","0 0 1024 1024"),this._icon.setAttribute("width","100"),this._icon.setAttribute("height","100");const p=document.createElementNS(Ko,"use");p.setAttributeNS(Ko,kh,`../../assets/iconfont/icon.svg#icon-${this.name}`),this._icon.appendChild(p),this._div.appendChild(this._icon)}),Dt(this,"setIcon",async()=>{this.name&&this.loadLocal()}),Dt(this,"setSize",()=>{this._icon&&this.size&&(this._icon.setAttribute("width",this.size),this._icon.setAttribute("height",this.size))}),Dt(this,"setColor",()=>{this._icon&&(this.color?this._icon.setAttribute("fill",this.color):this._icon.setAttribute("fill","currentColor"))}),Dt(this,"setSpin",()=>{this.spin&&this.style.setProperty("animation-duration",`${this.spin}s`)}),this._div=document.createElement("div"),this._div.setAttribute("class","ran-icon"),this._div.setAttribute("part","ran-icon")}static get observedAttributes(){return["name","size","color","spin"]}get name(){return this.getAttribute("name")}set name(p){p&&this.setAttribute("name",p)}get size(){return this.getAttribute("size")}set size(p){p&&this.setAttribute("size",p)}get color(){return this.getAttribute("color")}set color(p){p&&this.setAttribute("color",p)}get spin(){return this.getAttribute("spin")}set spin(p){p!=null&&this.setAttribute("spin",p)}connectedCallback(){this.appendChild(this._div),this.setIcon()}attributeChangedCallback(p,f,w){w!==f&&(p==="name"&&this.setIcon(),p==="size"&&this.setSize(),p==="color"&&this.setColor(),p==="spin"&&this.setSpin())}}customElements.define("ra-icon",k)}}xh();var Th=Object.defineProperty,Ch=(k,h,p)=>h in k?Th(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,pe=(k,h,p)=>Ch(k,typeof h!="symbol"?h+"":h,p);function Sh(){if(typeof document<"u"&&!customElements.get("ra-option")){class k extends HTMLElement{constructor(){super(),pe(this,"_option"),pe(this,"_optionContent"),pe(this,"_shadowDom"),pe(this,"_slot"),this._slot=document.createElement("slot"),this._option=document.createElement("div"),this._option.setAttribute("class","ran-option"),this._optionContent=document.createElement("div"),this._optionContent.setAttribute("class","ran-option-content"),this._optionContent.appendChild(this._slot),this._option.appendChild(this._optionContent);const p=this.attachShadow({mode:"closed"});this._shadowDom=p,p.appendChild(this._option)}static get observedAttributes(){return["disabled","sheet","value"]}get value(){return this.getAttribute("value")}set value(p){this.setAttribute("value",p||"")}get sheet(){return this.getAttribute("sheet")}set sheet(p){this.setAttribute("sheet",p||"")}get disabled(){return Ce(this)}set disabled(p){!p||p==="false"?this.removeAttribute("disabled"):this.setAttribute("disabled","")}handlerExternalCss(){if(this.sheet)try{const p=new CSSStyleSheet;p.insertRule(this.sheet),this._shadowDom.adoptedStyleSheets=[p]}catch{console.error(`Failed to parse the rule in CSSStyleSheet: ${this.sheet}`)}}connectedCallback(){}disconnectCallback(){}attributeChangedCallback(p,f,w){p==="disabled"&&this._option&&(!w||w==="false"?this._option.setAttribute("disabled",""):this._option.removeAttribute("disabled")),p==="sheet"&&this._shadowDom&&f!==w&&this.handlerExternalCss()}}return k}else return Ie("document is undefined or ra-option is exist")}Sh();const $i={bottom:{add:"ran-select-dropdown-down-in",remove:"ran-select-dropdown-down-out"},top:{add:"ran-select-dropdown-up-in",remove:"ran-select-dropdown-up-out"}},Lh=Zi();class Vo extends Fe(){constructor(){super(),pe(this,"removeTimeId"),pe(this,"_select"),pe(this,"_selection"),pe(this,"_search"),pe(this,"_icon"),pe(this,"_selectDropdown"),pe(this,"_selectionDropdown"),pe(this,"_selectDropDownInTimeId"),pe(this,"_selectDropDownOutTimeId"),pe(this,"_optionList"),pe(this,"_optionLabelMapValue"),pe(this,"_optionValueMapLabel"),pe(this,"_activeOption"),pe(this,"_text"),pe(this,"_selector"),pe(this,"onSearch"),pe(this,"setSelectDropdownDisplayNone",()=>{this._selectDropDownOutTimeId||this._selectionDropdown&&this._selectionDropdown.style.display!=="none"&&(Re(this._selectionDropdown,$i[this.placement].remove),this._selectDropDownOutTimeId=setTimeout(()=>{var h;(h=this._selectionDropdown)==null||h.style.setProperty("display","none"),this._selectionDropdown&&Ve(this._selectionDropdown,$i[this.placement].remove),clearTimeout(this._selectDropDownOutTimeId),this._selectDropDownOutTimeId=void 0},300))}),pe(this,"setSelectDropdownDisplayBlock",()=>{var h;this._selectDropDownInTimeId||this._selectionDropdown&&this._selectionDropdown.style.display!=="block"&&(Re(this._selectionDropdown,$i[this.placement].add),(h=this._selectionDropdown)==null||h.style.setProperty("display","block"),this._selectDropDownInTimeId=setTimeout(()=>{this._selectionDropdown&&Ve(this._selectionDropdown,$i[this.placement].add),clearTimeout(this._selectDropDownInTimeId),this._selectDropDownInTimeId=void 0},200))}),pe(this,"placementPosition",()=>{if(!this._selectionDropdown||!this._selectDropdown)return;const h=this.getBoundingClientRect(),{top:p,left:f,bottom:w,width:x,height:T,x:D,y:G,right:F}=h,q=document.getElementById(this.getPopupContainerId);this._selectionDropdown.style.setProperty("--ran-x",`${p+window.scrollX}`),this._selectionDropdown.style.setProperty("--ran-y",`${f+window.scrollY}`);let j=w+window.scrollY,de=f+window.scrollX;this._selectionDropdown.style.setProperty("width",`${x}px`),this.placement==="top"&&(j=p+window.scrollY-this._selectionDropdown.clientHeight),this.getPopupContainerId&&q&&(this.placement==="top"?j=p-q.getBoundingClientRect().top-this._selectionDropdown.clientHeight:j=q.getBoundingClientRect().height,de=0),this._selectionDropdown.style.setProperty("inset",`${j}px auto auto ${de}px`)}),pe(this,"selectMouseDown",h=>{h.stopPropagation(),!Ce(this)&&(this.removeDropDownTimeId(),this.setSelectDropdownDisplayNone(),this.setSelectDropdownDisplayBlock(),this.placementPosition())}),pe(this,"removeDropDownTimeId",()=>{this._search.setAttribute("value",""),this.trigger.includes("hover")&&!_t()&&(clearTimeout(this.removeTimeId),this.removeTimeId=void 0)}),pe(this,"selectBlur",()=>{this.removeTimeId&&this.removeDropDownTimeId(),this.removeTimeId=setTimeout(()=>{this.removeDropDownTimeId(),this.setSelectDropdownDisplayNone()},100)}),pe(this,"clickOption",h=>{var p,f;h.stopPropagation();let w=h.target;if((p=w.classList)!=null&&p.contains("ranui-select-dropdown-option-item")&&(w=w.children[0]),!((f=w.classList)!=null&&f.contains("ranui-select-dropdown-option-item-content")))return;const x=w.innerHTML,T=this._optionLabelMapValue.get(x);T&&(this.setAttribute("value",T),this._text.innerHTML=x,this._text.setAttribute("title",x),this._search.setAttribute("placeholder",x));const D=this.getBoundingClientRect(),{height:G}=D;this._text.style.setProperty("line-height",`${G}px`),this._activeOption&&Ve(this._activeOption,"ranui-select-dropdown-option-active"),setTimeout(()=>{this._activeOption=(w==null?void 0:w.parentElement)||void 0,this._activeOption&&Re(this._activeOption,"ranui-select-dropdown-option-active")},200),this.setSelectDropdownDisplayNone(),this.dispatchEvent(new CustomEvent("change",{detail:{value:T,label:x}})),this.removeDropDownTimeId()}),pe(this,"createOption",()=>{if(!this._selectDropdown){this.appendChild(this._select);const h=document.getElementById(this.getPopupContainerId)||document.body;this._selectDropdown=document.createElement("div"),this._selectDropdown.style.setProperty("-webkit-tap-highlight-color","transparent"),this._selectDropdown.style.setProperty("outline","0"),this._selectDropdown.addEventListener("click",this.clickOption),this._selectionDropdown=document.createElement("div"),this._selectionDropdown.style.setProperty("-webkit-tap-highlight-color","transparent"),this._selectionDropdown.style.setProperty("outline","0"),this.dropdownclass?this._selectionDropdown.setAttribute("class",`${this.dropdownclass} ranui-select-dropdown`):this._selectionDropdown.setAttribute("class","ranui-select-dropdown"),this.trigger.includes("hover")&&!_t()&&(this._selectDropdown.addEventListener("mouseleave",this.selectBlur),this._selectDropdown.addEventListener("mouseenter",this.removeDropDownTimeId)),this._selectDropdown.appendChild(this._selectionDropdown),this._selectionDropdown.style.setProperty("display","none"),h.appendChild(this._selectDropdown)}this.addOptionToSlot()}),pe(this,"removeSelectDropdown",()=>{try{this._selectDropdown&&(document.getElementById(this.getPopupContainerId)||document.body).removeChild(this._selectDropdown)}catch{}}),pe(this,"addOptionToSlot",()=>{var h;const p=this.children||[];this._optionList=[];for(const f of p)if(f.tagName==="R-OPTION"){const w=f.innerHTML,x=f.getAttribute("value")||"";(h=this._optionList)==null||h.push({label:w,value:x}),this._optionLabelMapValue.set(w,x),this._optionValueMapLabel.set(x,w)}this.createSelectDropdownContent(this._optionList)}),pe(this,"createSelectDropdownContent",(h=[])=>{var p,f;h.length===0?(p=this._selectDropdown)==null||p.style.setProperty("display","none"):(f=this._selectDropdown)==null||f.style.setProperty("display","block"),this._selectionDropdown&&(this._selectionDropdown.innerHTML=""),h.forEach(w=>{if(this._selectionDropdown){const{label:x,value:T}=w,D=document.createElement("div");(this.getAttribute("defaultValue")||this.getAttribute("value"))===T?(D.setAttribute("class","ranui-select-dropdown-option-active ranui-select-dropdown-option-item"),this._activeOption=D):D.setAttribute("class","ranui-select-dropdown-option-item");const F=document.createElement("div");F.setAttribute("class","ranui-select-dropdown-option-item-content"),F.innerHTML=`${x}`,F.setAttribute("value",`${T}`),F.setAttribute("title",`${x}`),D.appendChild(F),this._selectionDropdown.appendChild(D)}}),this.setDefaultValue()}),pe(this,"setDefaultValue",()=>{const h=this.getAttribute("defaultValue")||this.getAttribute("value");if(!h)return;const p=this._optionValueMapLabel.get(h);if(!p)return;this.setAttribute("value",h);const f=this.getBoundingClientRect(),{height:w}=f;this._text.style.setProperty("line-height",`${w}px`),this._text.innerHTML=p,this._text.setAttribute("title",p)}),pe(this,"changeSearch",h=>{const p=h.detail.value||"";if(this.dispatchEvent(new CustomEvent("search",{detail:{value:p}})),this._selectionDropdown&&(this._selectionDropdown.innerHTML=""),p.length>0){const f=this._optionList.map(w=>{const{label:x}=w;if(`${x}`.toLowerCase().includes(p))return{label:x,value:w.value}}).filter(w=>w);this.createSelectDropdownContent(f)}else this.createSelectDropdownContent(this._optionList)}),pe(this,"setShowSearch",()=>{this.onSearch=Lh(this.changeSearch),this.onSearch&&this._search.addEventListener("change",this.onSearch),this.onSearch&&this._search.addEventListener("click",this.onSearch)}),pe(this,"removeShowSearch",()=>{this.onSearch&&this._search.removeEventListener("change",this.onSearch),this.onSearch&&this._search.removeEventListener("click",this.onSearch)}),pe(this,"listenActionEvent",()=>{this.removeEventListener("mouseenter",this.selectMouseDown),this.removeEventListener("mouseleave",this.selectBlur),this.removeEventListener("click",this.selectMouseDown),this.removeEventListener("blur",this.selectBlur),this.trigger.includes("hover")&&!_t()&&(this.addEventListener("mouseenter",this.selectMouseDown),this.addEventListener("mouseleave",this.selectBlur)),this.trigger.includes("click")&&(this.addEventListener("click",this.selectMouseDown),this.addEventListener("blur",this.selectBlur))}),pe(this,"clickRemoveSelect",h=>{h.stopPropagation(),this.setSelectDropdownDisplayNone()}),this._select=document.createElement("div"),this._select.setAttribute("class","ran-select"),this._select.setAttribute("part","select"),this._selection=document.createElement("div"),this._selection.setAttribute("class","selection"),this._selection.setAttribute("part","selection"),this._selector=document.createElement("div"),this._search=document.createElement("ra-input"),this._search.setAttribute("class","selection-search"),this._search.setAttribute("part","search"),this._search.setAttribute("type","search"),this._search.setAttribute("autocomplete","off"),this._text=document.createElement("span"),this._text.setAttribute("class","selection-item"),this._text.setAttribute("part","selection-item"),this._icon=document.createElement("ra-icon"),this._icon.setAttribute("class","icon"),this._icon.setAttribute("part","icon"),this._icon.setAttribute("name","arrow-down"),this._icon.setAttribute("color","#d9d9d9"),this._icon.setAttribute("size","16"),this._selector.appendChild(this._text),this._selector.appendChild(this._search),this._selection.appendChild(this._icon),this._selection.appendChild(this._selector),this._select.appendChild(this._selection),this._optionList=[],this._optionLabelMapValue=new Map,this._optionValueMapLabel=new Map}static get observedAttributes(){return["disabled","sheet","clear","type","defaultValue","showSearch","placement","getPopupContainerId","dropdownclass","trigger"]}get value(){return this.getAttribute("value")||""}set value(h){!Ce(this)&&h?this.setAttribute("value",h):this.removeAttribute("value")}get defaultValue(){return this.getAttribute("defaultValue")||""}set defaultValue(h){this.setAttribute("defaultValue",h||"")}get showSearch(){return this.getAttribute("showSearch")||""}set showSearch(h){this.setAttribute("showSearch",h||"")}get type(){return this.getAttribute("type")||""}set type(h){this.setAttribute("type",h||"")}get placement(){return this.getAttribute("placement")||"bottom"}set placement(h){this.setAttribute("placement",h||"")}get sheet(){return this.getAttribute("sheet")||""}set sheet(h){this.setAttribute("sheet",h||"")}get getPopupContainerId(){return this.getAttribute("getPopupContainerId")||""}set getPopupContainerId(h){this.setAttribute("getPopupContainerId",h||"")}get dropdownclass(){return this.getAttribute("dropdownclass")||""}set dropdownclass(h){this.setAttribute("dropdownclass",h||"")}get trigger(){return this.getAttribute("trigger")||"click"}set trigger(h){this.setAttribute("trigger",h||"")}get disabled(){return Ce(this)}set disabled(h){!h||h==="false"?(this.removeAttribute("disabled"),this._selection.removeAttribute("disabled")):(this.setAttribute("disabled",""),this._selection.setAttribute("disabled",""))}connectedCallback(){this.createOption(),this.listenActionEvent(),this.setShowSearch(),document.addEventListener("click",this.clickRemoveSelect)}disconnectCallback(){var h;this.removeEventListener("mouseenter",this.selectMouseDown),this.removeEventListener("mouseleave",this.selectBlur),this.removeEventListener("click",this.selectMouseDown),this.removeEventListener("blur",this.selectBlur),this.removeSelectDropdown(),(h=this._selectDropdown)==null||h.removeEventListener("click",this.clickOption),document.removeEventListener("click",this.clickRemoveSelect)}attributeChangedCallback(h,p,f){h==="disabled"&&this._select&&(!f||f==="false"?(this._select.setAttribute("disabled",""),this._selection.setAttribute("disabled","")):(this._select.removeAttribute("disabled"),this._selection.removeAttribute("disabled")))}}function Dh(){return typeof document<"u"&&!customElements.get("ra-select")?(customElements.define("ra-select",Vo),Vo):Ie("document is undefined or ra-select is exist")}Dh();var Rh=Object.defineProperty,Ih=(k,h,p)=>h in k?Rh(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,X=(k,h,p)=>Ih(k,typeof h!="symbol"?h+"":h,p);const Ph=k=>{const{r:h,g:p,b:f}=Oh(k);return bn(h,p,f)},Oh=k=>(k[0]==="#"&&(k=k.substr(1)),k.length===3?{r:parseInt(k[0]+k[0],16),g:parseInt(k[1]+k[1],16),b:parseInt(k[2]+k[2],16)}:{r:parseInt(k.substr(0,2),16),g:parseInt(k.substr(2,2),16),b:parseInt(k.substr(4,2),16)}),bn=(k,h,p)=>{let f;const w=Math.max(k,h,p),x=Math.min(k,h,p),T=w-x;T===0?f=0:k===w?f=(h-p)/T%6:h===w?f=(p-k)/T+2:f=(k-h)/T+4,f=Math.round(f*60),f<0&&(f+=360);const D=Math.round((w===0?0:T/w)*100),G=Math.round(w/255*100);return{h:f,s:D,v:G}},zo=(k,h,p)=>{h=h/100,p=p/100;let f=[];const w=p*h,x=k/60,T=w*(1-Math.abs(x%2-1)),D=p-w;return x>=0&&x<1?f=[w,T,0]:x>=1&&x<2?f=[T,w,0]:x>=2&&x<3?f=[0,w,T]:k>=3&&x<4?f=[0,T,w]:k>=4&&x<5?f=[T,0,w]:k>=5&&x<=6?f=[w,0,T]:f=[0,0,0],{r:Math.round(255*(f[0]+D)),g:Math.round(255*(f[1]+D)),b:Math.round(255*(f[2]+D))}},Mh=/^#([\da-f]{6}|[\da-f]{3})$/i,Fh=/^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$/,Bh=/^rgba\((\d{1,3}),(\d{1,3}),(\d{1,3}),(\d{1,3}(\.\d+)?)\)$/,ut=8,Nh=360;class yn extends Fe(){constructor(){super(),X(this,"colorpicker"),X(this,"colorpickerInner"),X(this,"context"),X(this,"popoverBlock"),X(this,"popoverContent"),X(this,"colorPickerInner"),X(this,"colorPickerInnerContent"),X(this,"colorPickerPanel"),X(this,"colorPickerInputContainer"),X(this,"colorPickerPanelDot"),X(this,"colorPickerPanelSliderContainer"),X(this,"colorPickerPanelSliderGroup"),X(this,"colorPickerPanelSliderHue"),X(this,"colorPickerPanelSliderAlpha"),X(this,"colorPickerColorBlockInner"),X(this,"colorPickerColorBlock"),X(this,"colorPickerInnerContentSelect"),X(this,"colorPickerPanelPalette"),X(this,"colorPickerPanelSaturation"),X(this,"colorPickerInputContainerSelect"),X(this,"colorPickerInputContainerInputColor"),X(this,"colorPickerInputContainerInputNumber"),X(this,"colorPickerInputContainerSelectItem"),X(this,"colorPickerPaletteSelect"),X(this,"colorPickerPanelDotInner"),X(this,"createContext",()=>{this.context={value:this.createColorValueSignal(),disabled:this.createColorDisabled(),hue:this.createColorHue(),saturation:this.createColorSaturation(),lightness:this.createColorLightness(),transparency:this.createColorTransparency()}}),X(this,"createColorHue",()=>{const[h,p]=Jt(0,{subscriber:[this.updateColorPickerPanelSaturationBackground,this.updateColorPickerPanelSliderHueProgressPercent,this.updateColorPickerPanelSliderAlphaProgressWrap,this.updateColorPickerPanelSliderAlphaProgressDot,this.updateColorPickerColorBlockInnerBackground,this.updateColorPickerPanelSliderHueProgressDot]});return{getter:h,setter:p}}),X(this,"createColorSaturation",()=>{const[h,p]=Jt(100,{subscriber:[this.updateColorPickerPanelSliderAlphaProgressWrap,this.updateColorPickerPanelSliderAlphaProgressDot,this.updateColorPickerColorBlockInnerBackground]});return{getter:h,setter:p}}),X(this,"createColorLightness",()=>{const[h,p]=Jt(100,{subscriber:[this.updateColorPickerPanelSliderAlphaProgressWrap,this.updateColorPickerPanelSliderAlphaProgressDot,this.updateColorPickerColorBlockInnerBackground]});return{getter:h,setter:p}}),X(this,"createColorTransparency",()=>{const[h,p]=Jt(80,{subscriber:[this.updateColorPickerPanelSliderAlphaProgressPercent,this.updateColorPickerColorBlockInnerBackground,this.updateColorPickerPanelSliderAlphaProgressDot]});return{getter:h,setter:p}}),X(this,"createColorDisabled",()=>{const[h,p]=Jt(!0,{subscriber:[]});return{getter:h,setter:p}}),X(this,"createColorValueSignal",()=>{const[h,p]=Jt("",{subscriber:[this.updateColorValue]});return{getter:h,setter:p}}),X(this,"generateHue2rgb",()=>{const{hue:h}=this.context,{r:p,g:f,b:w}=zo(h.getter(),100,100);return`rgb(${p}, ${f}, ${w})`}),X(this,"generateHsv2Rgb",()=>{const{r:h,g:p,b:f}=this.generateHsv2Rgba();return`rgb(${h}, ${p}, ${f})`}),X(this,"generateHsv2Rgba",()=>{const{hue:h,saturation:p,lightness:f,transparency:w}=this.context,{r:x,g:T,b:D}=zo(h.getter(),p.getter(),f.getter());return{r:x,g:T,b:D,a:w.getter()/100}}),X(this,"generateHsv2RgbaValue",()=>{const{r:h,g:p,b:f,a:w}=this.generateHsv2Rgba();return`rgb(${h}, ${p}, ${f}, ${w})`}),X(this,"generateColorPickerProgress",()=>{const{r:h,g:p,b:f}=this.generateHsv2Rgba();return`linear-gradient(to right, rgba(255, 0, 4, 0), rgba(${h}, ${p}, ${f}, 1))`}),X(this,"updateColorValue",h=>{var p,f;if(h!==((p=this.context)==null?void 0:p.value.getter())){const w=Mh.exec(h),x=Fh.exec(h.replace(/\s+/g,"")),T=Bh.exec(h.replace(/\s+/g,""));if(w){const{h:D,s:G,v:F}=Ph(w[0]);this.context.hue.setter(D),this.context.saturation.setter(G),this.context.lightness.setter(F),this.context.transparency.setter(100)}else if(T){const{h:D,s:G,v:F}=bn(Number(T[1]),Number(T[2]),Number(T[3]));this.context.hue.setter(D),this.context.saturation.setter(G),this.context.lightness.setter(F),this.context.transparency.setter(Number(T[4]))}else if(x){const{h:D,s:G,v:F}=bn(Number(x[1]),Number(x[2]),Number(x[3]));this.context.hue.setter(D),this.context.saturation.setter(G),this.context.lightness.setter(F),this.context.transparency.setter(100)}else return;this.setAttribute("value",h),this.colorpickerInner.style.setProperty("background",h),(f=this.context)==null||f.value.setter(h)}}),X(this,"updateColorPickerPanelSliderHueProgressPercent",h=>{var p;(p=this.colorPickerPanelSliderHue)==null||p.setAttribute("percent",`${h/360}`)}),X(this,"updateColorPickerPanelSliderAlphaProgressPercent",h=>{var p;(p=this.colorPickerPanelSliderAlpha)==null||p.setAttribute("percent",`${h/100}`)}),X(this,"updateColorPickerPanelSliderAlphaProgressWrap",()=>{var h;(h=this.colorPickerPanelSliderAlpha)==null||h.style.setProperty("--ran-progress-wrap-background",this.generateColorPickerProgress())}),X(this,"updateColorPickerPanelSliderAlphaProgressDot",()=>{var h;(h=this.colorPickerPanelSliderAlpha)==null||h.style.setProperty("--ran-progress-dot-background",this.generateHsv2RgbaValue())}),X(this,"updateColorPickerPanelSliderHueProgressDot",()=>{var h;(h=this.colorPickerPanelSliderHue)==null||h.style.setProperty("--ran-progress-dot-background",this.generateHue2rgb())}),X(this,"updateColorPickerColorBlockInnerBackground",()=>{var h;(h=this.colorPickerColorBlockInner)==null||h.style.setProperty("background",this.generateHsv2RgbaValue())}),X(this,"updateColorPickerPanelSaturationBackground",()=>{var h;(h=this.colorPickerPanelSaturation)==null||h.style.setProperty("background-color",this.generateHue2rgb())}),X(this,"clickStop",h=>{h.stopPropagation(),h.preventDefault()}),X(this,"changeColorPalettePositionByContext",()=>{window.requestAnimationFrame(()=>{var h,p,f,w,x;if(this.updateColorValue(this.value),!this.colorPickerPanelPalette||!((h=this.context)!=null&&h.lightness.getter)||!((p=this.context)!=null&&p.saturation.getter))return;const{width:T,height:D}=((f=this.colorPickerPanelPalette)==null?void 0:f.getBoundingClientRect())||{},G=D-this.context.lightness.getter()/100*D,F=this.context.saturation.getter()/100*T;(w=this.colorPickerPanelDot)==null||w.style.setProperty("top",`${G-ut}px`),(x=this.colorPickerPanelDot)==null||x.style.setProperty("left",`${F-ut}px`)})}),X(this,"changeColorPalettePosition",(h,p)=>{var f,w,x;if(!this.colorPickerPanelPalette||!((f=this.context)!=null&&f.lightness.getter)||!((w=this.context)!=null&&w.saturation.getter))return;const{width:T,height:D}=((x=this.colorPickerPanelPalette)==null?void 0:x.getBoundingClientRect())||{},G=D-At(p,0,D),F=At(h,0,T);this.context.saturation.setter(F/T*100),this.context.lightness.setter(G/D*100),window.requestAnimationFrame(()=>{var q,j;(q=this.colorPickerPanelDot)==null||q.style.setProperty("top",`${p-ut}px`),(j=this.colorPickerPanelDot)==null||j.style.setProperty("left",`${h-ut}px`)})}),X(this,"clickColorPalette",h=>{const{offsetX:p,offsetY:f}=h;this.changeColorPalettePosition(p,f)}),X(this,"createColorPickerProgress",()=>{this.colorPickerPanelSliderContainer=document.createElement("div"),this.colorPickerPanelSliderContainer.setAttribute("class","ran-color-picker-slider-container"),this.colorPickerPanelSliderGroup=document.createElement("div"),this.colorPickerPanelSliderGroup.setAttribute("class","ran-color-picker-slider-container-group"),this.colorPickerPanelSliderHue=document.createElement("r-progress"),this.updateColorPickerPanelSliderHueProgressDot(),this.colorPickerPanelSliderHue.style.setProperty("--ran-progress-wrap-background","linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)"),this.colorPickerPanelSliderHue.setAttribute("percent",`${this.context.hue.getter()/360}`),this.colorPickerPanelSliderHue.addEventListener("change",this.changeColorPickerHue),this.colorPickerPanelSliderHue.setAttribute("type","drag"),this.colorPickerPanelSliderHue.setAttribute("class","ran-color-picker-slider-container-group-hue"),this.colorPickerPanelSliderAlpha=document.createElement("r-progress"),this.updateColorPickerPanelSliderAlphaProgressDot(),this.colorPickerPanelSliderAlpha.setAttribute("percent",`${this.context.transparency.getter()/100}`),this.updateColorPickerPanelSliderAlphaProgressWrap(),this.colorPickerPanelSliderAlpha.addEventListener("change",this.changeColorPickerAlpha),this.colorPickerPanelSliderAlpha.setAttribute("type","drag"),this.colorPickerPanelSliderAlpha.setAttribute("class","ran-color-picker-slider-container-group-alpha"),this.colorPickerPanelSliderGroup.appendChild(this.colorPickerPanelSliderHue),this.colorPickerPanelSliderGroup.appendChild(this.colorPickerPanelSliderAlpha),this.colorPickerPanelSliderContainer.appendChild(this.colorPickerPanelSliderGroup),this.colorPickerColorBlock=document.createElement("div"),this.colorPickerColorBlock.setAttribute("class","ran-color-picker-slider-container-color-block"),this.colorPickerColorBlockInner=document.createElement("div"),this.colorPickerColorBlockInner.setAttribute("class","ran-color-picker-slider-container-color-block-inner"),this.updateColorPickerColorBlockInnerBackground(),this.colorPickerColorBlock.appendChild(this.colorPickerColorBlockInner),this.colorPickerPanelSliderContainer.appendChild(this.colorPickerColorBlock)}),X(this,"changeColorPickerHue",h=>{this.context.hue.setter(h.detail.value*Nh)}),X(this,"changeColorPickerAlpha",h=>{this.context.transparency.setter(h.detail.value*100)}),X(this,"createColorPickerSelect",()=>{this.colorPickerPanel=document.createElement("div"),this.colorPickerPanel.setAttribute("class","ran-color-picker-panel"),this.colorPickerInnerContentSelect=document.createElement("div"),this.colorPickerInnerContentSelect.setAttribute("class","ran-color-picker-select"),this.colorPickerPanel.appendChild(this.colorPickerInnerContentSelect),this.colorPickerPanelPalette=document.createElement("div"),this.colorPickerPanelPalette.setAttribute("class","ran-color-picker-palette"),this.colorPickerInnerContentSelect.appendChild(this.colorPickerPanelPalette),this.colorPickerPanelSaturation=document.createElement("div"),this.colorPickerPanelSaturation.setAttribute("class","ran-color-picker-saturation"),this.updateColorPickerPanelSaturationBackground(),this.colorPickerPanelDot=document.createElement("div"),this.colorPickerPanelDotInner=document.createElement("div"),this.colorPickerPanelDotInner.setAttribute("class","ran-color-picker-palette-dot-inner"),this.colorPickerPanelDot.setAttribute("class","ran-color-picker-palette-dot"),this.colorPickerPanelDot.addEventListener("mousedown",this.mouseDownColorPickerPalette),document.body.addEventListener("mousemove",this.mouseMoveColorPickerPalette),this.colorPickerPanelDot.addEventListener("mouseup",this.mouseUpColorPickerPalette),this.colorPickerPanelDot.appendChild(this.colorPickerPanelDotInner),this.colorPickerPanelPalette.appendChild(this.colorPickerPanelDot),this.colorPickerPanelPalette.appendChild(this.colorPickerPanelSaturation),this.colorPickerPanelPalette.addEventListener("mousedown",this.clickColorPalette)}),X(this,"createColorPickerInput",()=>{this.colorPickerInputContainer=document.createElement("div"),this.colorPickerInputContainer.setAttribute("class","ran-color-picker-input-container");const h=`${performance.now()}`.replace(".","");this.colorPickerInputContainerSelect=document.createElement("div"),this.colorPickerInputContainerSelect.setAttribute("class","ran-color-picker-input-container-select"),this.colorPickerInputContainerSelect.setAttribute("id",h),this.colorPickerInputContainerSelectItem=document.createElement("ra-select"),this.colorPickerInputContainerSelectItem.setAttribute("value","HEX"),this.colorPickerInputContainerSelectItem.setAttribute("class","ran-color-picker-input-container-select-item"),this.colorPickerInputContainerSelectItem.setAttribute("type","text"),this.colorPickerInputContainerSelectItem.setAttribute("getPopupContainerId",h);const p=["HEX","HSB","RGB"],f=document.createDocumentFragment();p.forEach(w=>{const x=document.createElement("r-option");x.setAttribute("value",w),x.innerText=w,f.appendChild(x)}),this.colorPickerInputContainerSelectItem.appendChild(f),this.colorPickerInputContainerSelect.appendChild(this.colorPickerInputContainerSelectItem),this.colorPickerInputContainer.appendChild(this.colorPickerInputContainerSelect),this.colorPickerInputContainerInputColor=document.createElement("ra-input"),this.colorPickerInputContainerInputColor.setAttribute("class","ran-color-picker-input-container-input-color"),this.colorPickerInputContainerInputNumber=document.createElement("ra-input"),this.colorPickerInputContainerInputNumber.setAttribute("class","ran-color-picker-input-container-input-number"),this.colorPickerInputContainer.appendChild(this.colorPickerInputContainerInputColor),this.colorPickerInputContainer.appendChild(this.colorPickerInputContainerInputNumber)}),X(this,"openColorPicker",()=>{this.colorPickerInner||(this.colorPickerInner=document.createElement("div"),this.colorPickerInner.setAttribute("class","ran-color-picker-inner"),this.colorPickerInnerContent=document.createElement("div"),this.colorPickerInnerContent.setAttribute("class","ran-color-picker-inner-content"),this.createColorPickerProgress(),this.createColorPickerSelect(),this.createColorPickerInput(),this.colorPickerPanel&&this.colorPickerInnerContent.appendChild(this.colorPickerPanel),this.colorPickerPanelSliderContainer&&this.colorPickerInnerContent.appendChild(this.colorPickerPanelSliderContainer),this.colorPickerInputContainer&&this.colorPickerInnerContent.appendChild(this.colorPickerInputContainer),this.colorPickerInner.appendChild(this.colorPickerInnerContent),this.popoverContent.appendChild(this.colorPickerInner),this.changeColorPalettePositionByContext())}),X(this,"mouseMoveColorPickerPalette",h=>{var p;if(!this.colorPickerPanelPalette||!this.colorPickerPaletteSelect)return;const{pageX:f,pageY:w}=h,{top:x=0,left:T=0,width:D,height:G}=((p=this.colorPickerPanelPalette)==null?void 0:p.getBoundingClientRect())||{},F=At(w-x-ut,-ut,G-ut),q=At(f-T-ut,-ut,D-ut);this.context.saturation.setter(q/D*100),this.context.lightness.setter(F/G*100),window.requestAnimationFrame(()=>{var j,de;(j=this.colorPickerPanelDot)==null||j.style.setProperty("top",`${F}px`),(de=this.colorPickerPanelDot)==null||de.style.setProperty("left",`${q}px`)})}),X(this,"mouseDownColorPickerPalette",h=>{h.stopPropagation(),h.preventDefault(),this.colorPickerPaletteSelect=!0}),X(this,"mouseUpColorPickerPalette",h=>{this.colorPickerPaletteSelect=!1}),this.setAttribute("class","ran-colorpicker"),this.popoverBlock=document.createElement("r-popover"),this.popoverBlock.setAttribute("class","ran-popover"),this.popoverContent=document.createElement("r-content"),this.popoverContent.setAttribute("class","ran-content"),this.colorpicker=document.createElement("div"),this.colorpicker.setAttribute("class","ran-colorpicker-block"),this.colorpickerInner=document.createElement("div"),this.colorpickerInner.setAttribute("class","ran-colorpicker-inner"),this.popoverBlock.appendChild(this.colorpicker),this.popoverBlock.appendChild(this.popoverContent),this.colorpicker.appendChild(this.colorpickerInner),this.appendChild(this.popoverBlock),this.colorPickerPaletteSelect=!1,this.createContext()}static get observedAttributes(){return["disabled","value"]}get value(){var h;return((h=this.context)==null?void 0:h.value.getter())||""}set value(h){this.setAttribute("value",h),this.updateColorValue(h)}connectedCallback(){this.popoverBlock.addEventListener("click",this.openColorPicker)}disconnectCallback(){var h,p,f;this.popoverBlock.removeEventListener("click",this.openColorPicker),(h=this.colorPickerPanelDot)==null||h.removeEventListener("mousedown",this.mouseDownColorPickerPalette),document.body.removeEventListener("mousemove",this.mouseMoveColorPickerPalette),(p=this.colorPickerPanelDot)==null||p.removeEventListener("mouseup",this.mouseUpColorPickerPalette),(f=this.colorPickerPanelPalette)==null||f.removeEventListener("mousedown",this.clickColorPalette)}attributeChangedCallback(h,p,f){p!==f&&h==="value"&&this.updateColorValue(f)}}function Uh(){return typeof document<"u"&&!customElements.get("r-colorpicker")?(customElements.define("r-colorpicker",yn),yn):Ie("document is undefined or r-colorpicker is exist")}const Gh=Uh(),Hh=Object.freeze(Object.defineProperty({__proto__:null,ColorPicker:yn,default:Gh},Symbol.toStringTag,{value:"Module"}));var Kh=Object.defineProperty,Vh=(k,h,p)=>h in k?Kh(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,me=(k,h,p)=>Vh(k,typeof h!="symbol"?h+"":h,p);const zh='.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}.ran-loading .stretch{width:var(--loading-stretch-width, 4em);height:var(--loading-stretch-height, 5em);text-align:var(--loading-stretch-text-align, center);display:var(--loading-stretch-display, flex);flex-flow:var(--loading-stretch-flex-flow, row nowrap);justify-content:var(--loading-stretch-justify-content, space-between);align-items:var(--loading-stretch-align-items, center)}@keyframes ran-loading-stretch{0%,40%,to{transform:var(--loading-stretch-keyframes-0, scaleY(.4))}20%{transform:var(--loading-stretch-keyframes-20, scaleY(1))}}.ran-loading .stretch div{background-color:var(--loading-stretch-div-background-color, #4096ff);height:var(--loading-stretch-div-height, 100%);width:var(--loading-stretch-div-width, .4em);animation:var(--loading-stretch-div-animation, ran-loading-stretch 1.2s infinite ease-in-out);animation-play-state:var(--loading-stretch-div-animation-play-state, running)}.ran-loading .stretch .rect5{animation-delay:var(--loading-stretch-rect-animation-delay, -.8s)}.ran-loading .stretch .rect4{animation-delay:var(--loading-stretch-rect-animation-delay, -.9s)}.ran-loading .stretch .rect3{animation-delay:var(--loading-stretch-rect-animation-delay, -1s)}.ran-loading .stretch .rect2{animation-delay:var(--loading-stretch-rect-animation-delay, -1.1s)}.ran-loading .rotate{width:var(--loading-rotate-width, 4em);height:var(--loading-rotate-height, 4em);background:var(--loading-rotate-background, #4096ff);animation:var(--loading-rotate-animation, ran-loading-rotate 1.2s infinite ease-in-out);animation-play-state:var(--loading-rotate-div-animation-play-state, running)}@keyframes ran-loading-rotate{0%{transform:var(--loading-rotate-keyframes-0, perspective(120px) rotateX(0deg) rotateY(0deg))}50%{transform:var(--loading-rotate-keyframes-50, perspective(120px) rotateX(-180.1deg) rotateY(0deg))}to{transform:var(--loading-rotate-keyframes-100, perspective(120px) rotateX(-180deg) rotateY(-179.9deg))}}.ran-loading .double-bounce{width:var(--loading-double-bounce-width, 4em);height:var(--loading-double-bounce-height, 4em);position:var(--loading-double-bounce-height, relative)}.ran-loading .double-bounce .double-bounce1{width:var(--loading-double-bounce1-width, 100%);height:var(--loading-double-bounce1-height, 100%);border-radius:var(--loading-double-bounce1-border-radius, 50%);background:var(--loading-double-bounce1-background, #4096ff);opacity:var(--loading-double-bounce1-opacity, .6);position:var(--loading-double-bounce1-position, absolute);top:var(--loading-double-bounce1-top, 0);left:var(--loading-double-bounce1-left, 0);animation:var(--loading-double-bounce1-animation, ran-loading-bounce 2s infinite ease-in-out);animation-play-state:var(--loading-double-bounce1-animation-play-state, running)}.ran-loading .double-bounce .double-bounce2{width:var(--loading-double-bounce2-width, 100%);height:var(--loading-double-bounce2-height, 100%);border-radius:var(--loading-double-bounce2-border-radius, 50%);background:var(--loading-double-bounce2-background, #4096ff);opacity:var(--loading-double-bounce2-opacity, .6);position:var(--loading-double-bounce2-position, absolute);top:var(--loading-double-bounce2-top, 0);left:var(--loading-double-bounce2-left, 0);animation:var(--loading-double-bounce2-animation, ran-loading-bounce 2s infinite ease-in-out);animation-delay:var(--loading-double-bounce2-animation-delay, -1s);animation-play-state:var(--loading-double-bounce2-animation-play-state, running)}@keyframes ran-loading-bounce{0%,to{transform:var(--loading-double-bounce-keyframes-0, scale(0))}50%{transform:var(--loading-double-bounce-keyframes-50, scale(1))}}.ran-loading .cube{width:var(--loading-cube-width, 2em);height:var(--loading-cube-width, 2em);position:var(--loading-cube-width, relative)}.ran-loading .cube .cube1{background:var(--loading-cube1-background, #4096ff);width:var(--loading-cube1-width, 2em);height:var(--loading-cube1-height, 2em);position:var(--loading-cube1-position, absolute);top:var(--loading-cube1-top, 0);left:var(--loading-cube1-left, 0);animation:var(--loading-cube1-animation, ran-loading-cube 1.8s infinite ease-in-out);animation-play-state:var(--loading-cube1-animation-play-state, running)}.ran-loading .cube .cube2{background:var(--loading-cube2-background, #4096ff);width:var(--loading-cube2-width, 2em);height:var(--loading-cube2-height, 2em);position:var(--loading-cube2-position, absolute);top:var(--loading-cube2-top, 0);left:var(--loading-cube2-left, 0);animation:var(--loading-cube2-animation, ran-loading-cube 1.8s infinite ease-in-out);animation-delay:var(--loading-cube2-animation-delay, -.9s);animation-play-state:var(--loading-cube2-animation-play-state, running)}@keyframes ran-loading-cube{25%{transform:var(--loading-cube-keyframes-25, translateX(42px) rotate(-90deg) scale(.5))}50%{transform:var(--loading-cube-keyframes-50, translateX(42px) translateY(42px) rotate(-179deg))}50.1%{transform:var(--loading-cube-keyframes-501, translateX(42px) translateY(42px) rotate(-180deg))}75%{transform:var(--loading-cube-keyframes-75, translateX(0px) translateY(42px) rotate(-270deg) scale(.5))}to{transform:var(--loading-cube-keyframes-100, rotate(-360deg))}}.ran-loading .dot{width:var(--loading-dot-width, 4em);height:var(--loading-dot-height, 4em);position:var(--loading-dot-position, relative);text-align:var(--loading-dot-text-align, center);animation:var(--loading-dot-animation, ran-loading-dot-rotate 2s infinite linear);animation-play-state:var(--loading-dot-animation-play-state, running)}.ran-loading .dot .dot1{width:var(--loading-dot1-width, 60%);height:var(--loading-dot1-height, 60%);display:var(--loading-dot1-display, inline-block);position:var(--loading-dot1-position, absolute);top:var(--loading-dot1-top, 0);background:var(--loading-dot1-background, #4096ff);border-radius:var(--loading-dot1-border-radius, 100%);animation:var(--loading-dot1-animation, ran-loading-dot-bounce 2s infinite ease-in-out);animation-play-state:var(--loading-dot1-animation-play-state, running)}.ran-loading .dot .dot2{width:var(--loading-dot2-width, 60%);height:var(--loading-dot2-height, 60%);display:var(--loading-dot2-display, inline-block);position:var(--loading-dot2-position, absolute);background:var(--loading-dot2-background, #4096ff);border-radius:var(--loading-dot2-border-radius, 100%);animation:var(--loading-dot2-animation, ran-loading-dot-bounce 2s infinite ease-in-out);top:var(--loading-dot2-top, auto);bottom:var(--loading-dot2-bottom, 0px);animation-delay:var(--loading-dot2-animation-delay, -1s);animation-play-state:var(--loading-dot2-animation-play-state, running)}@keyframes ran-loading-dot-rotate{to{transform:var(--loading-dot-keyframes-rotate, rotate(360deg))}}@keyframes ran-loading-dot-bounce{0%,to{transform:var(--loading-dot-keyframes-bounce-0, scale(0))}50%{transform:var(--loading-dot-keyframes-bounce-50, scale(1))}}.ran-loading .triple-bounce{width:var(--loading-triple-bounce-width, 10em);text-align:var(--loading-triple-bounce-text-align, center)}.ran-loading .triple-bounce div{width:var(--loading-triple-bounce-div-width, 2em);height:var(--loading-triple-bounce-div-height, 2em);background:var(--loading-triple-bounce-div-background, #4096ff);border-radius:var(--loading-triple-bounce-div-border-radius, 100%);display:var(--loading-triple-bounce-div-display, inline-block);animation:var(--loading-triple-bounce-div-animation, ran-loading-triple-bounce 1.4s infinite ease-in-out);animation-play-state:var(--loading-triple-bounce-div-animation-play-state, running);animation-fill-mode:var(--loading-triple-bounce-div-animation-fill-mode, both)}.ran-loading .triple-bounce .triple-bounce1{animation-delay:var(--loading-triple-bounce1-animation-delay, -.32s)}.ran-loading .triple-bounce .triple-bounce2{animation-delay:var(--loading-triple-bounce2-animation-delay, -.16s)}@keyframes ran-loading-triple-bounce{0%,80%,to{transform:var(--loading-triple-bounce-keyframes-0, scale(0))}40%{transform:var(--loading-triple-bounce-keyframes-40, scale(1))}}.ran-loading .scale-out{width:var(--loading-scale-out-width, 4em);height:var(--loading-scale-out-height, 4em);background:var(--loading-scale-out-background, #4096ff);border-radius:var(--loading-scale-out-border-radius, 100%);animation:var(--loading-scale-out-animation, ran-loading-scale-out 1s infinite ease-in-out);animation-play-state:var(--loading-scale-out-animation-play-state, running)}@keyframes ran-loading-scale-out{0%{transform:var(--loading-scale-out-keyframes-0-transform, scale(0))}to{transform:var(--loading-scale-out-keyframes-100-transform, scale(1));opacity:var(--loading-scale-out-keyframes-100-transform, 0)}}.ran-loading .circle{width:var(--loading-circle-width, 4em);height:var(--loading-circle-height, 4em);position:var(--loading-circle-position, relative)}.ran-loading .circle-container{position:var(--loading-circle-container-position, absolute);width:var(--loading-circle-container-width, 100%);height:var(--loading-circle-container-height, 100%)}.ran-loading .circle-container div{width:var(--loading-circle-container-div-width, 1em);height:var(--loading-circle-container-div-height, 1em);background:var(--loading-circle-container-div-background, #4096ff);border-radius:var(--loading-circle-container-div-border-radius, 100%);position:var(--loading-circle-container-div-position, absolute);animation:var(--loading-circle-container-div-animation, ran-loading-circle 1.2s infinite ease-in-out);animation-play-state:var(--loading-circle-container-div-animation-play-state, running);animation-fill-mode:var(--loading-circle-container-div-animation-fill-mode, both)}.ran-loading .circle .container1 .circle2{animation-delay:var(--loading-circle-container1-circle2-animation-delay, -.9s)}.ran-loading .circle .container1 .circle3{animation-delay:var(--loading-circle-container1-circle3-animation-delay, -.6s)}.ran-loading .circle .container1 .circle4{animation-delay:var(--loading-circle-container1-circle4-animation-delay, -.3s)}.ran-loading .circle .container2{transform:var(--loading-circle-container2-transform, rotateZ(45deg))}.ran-loading .circle .container2 .circle1{animation-delay:var(--loading-circle-container2-circle1-animation-delay, -1.1s)}.ran-loading .circle .container2 .circle2{animation-delay:var(--loading-circle-container2-circle2-animation-delay, -.8s)}.ran-loading .circle .container2 .circle3{animation-delay:var(--loading-circle-container2-circle3-animation-delay, -.5s)}.ran-loading .circle .container2 .circle4{animation-delay:var(--loading-circle-container2-circle4-animation-delay, -.2s)}.ran-loading .circle .container3{transform:var(--loading-circle-container3-transform, rotateZ(90deg))}.ran-loading .circle .container3 .circle1{animation-delay:var(--loading-circle-container3-circle1-transform, -1s)}.ran-loading .circle .container3 .circle2{animation-delay:var(--loading-circle-container3-circle2-transform, -.7s)}.ran-loading .circle .container3 .circle3{animation-delay:var(--loading-circle-container3-circle3-transform, -.4s)}.ran-loading .circle .container3 .circle4{animation-delay:var(--loading-circle-container3-circle4-transform, -.1s)}.ran-loading .circle .circle1{top:var(--loading-circle1-top, 0);left:var(--loading-circle1-left, 0)}.ran-loading .circle .circle2{top:var(--loading-circle2-top, 0);right:var(--loading-circle2-right, 0)}.ran-loading .circle .circle3{right:var(--loading-circle3-right, 0);bottom:var(--loading-circle3-bottom, 0)}.ran-loading .circle .circle4{left:var(--loading-circle3-left, 0);bottom:var(--loading-circle3-bottom, 0)}@keyframes ran-loading-circle{0%,80%,to{transform:var(--loading-circle-keyframes-0, scale(0))}40%{transform:var(--loading-circle-keyframes-40, scale(1))}}@keyframes circle-line{0%{transform:var(--loading-circle-line-keyframes-from, rotate(0))}to{transform:var(--loading-circle-line-keyframes-to, rotate(359deg))}}.ran-loading .circle-line-border{width:var(--loading-circle-line-border-width, 50px);height:var(--loading-circle-line-border-height, 50px);padding:var(--loading-circle-line-border-padding, 3px);display:var(--loading-circle-line-border-display, flex);justify-content:var(--loading-circle-line-border-justify-content, center);align-items:var(--loading-circle-line-border-align-items, center);border-radius:var(--loading-circle-line-border-border-radius, 50%);background:var(--loading-circle-line-border-background, linear-gradient(0deg, rgba(63, 249, 220, .1) 33%, #3ff9dc 100%));animation:var(--loading-circle-line-border-animation, circle-line .8s linear 0s infinite);animation-play-state:var(--loading-circle-line-border-animation-play-state, running)}.ran-loading .circle-line-core{width:var(--loading-circle-line-core-width, 100%);height:var(--loading-circle-line-core-height, 100%);background:var(--loading-circle-line-core-background, #fff);border-radius:var(--loading-circle-line-core-border-radius, 50%)}@keyframes square-box1{0%{transform:var(--loading-square-box1-keyframes-0, rotate(0))}25%{transform:var(--loading-square-box1-keyframes-25, rotate(90deg))}50%{transform:var(--loading-square-box1-keyframes-50, rotate(180deg))}75%{transform:var(--loading-square-box1-keyframes-75, rotate(270deg))}to{transform:var(--loading-square-box1-keyframes-100, rotate(360deg))}}@keyframes square-box2{0%{transform:var(--loading-square-box2-keyframes-0, rotate(45deg))}25%{transform:var(--loading-square-box2-keyframes-25, rotate(-45deg))}50%{transform:var(--loading-square-box2-keyframes-50, rotate(-135deg))}75%{transform:var(--loading-square-box2-keyframes-75, rotate(-225deg))}to{transform:var(--loading-square-box2-keyframes-100, rotate(-315deg))}}.ran-loading .square-box1{width:var(--loading-square-box1-width, 50px);height:var(--loading-square-box1-height, 50px);padding:var(--loading-square-box1-padding, 3px);position:var(--loading-square-box1-position, absolute);display:var(--loading-square-box1-display, flex);justify-content:var(--loading-square-box1-justify-content, center);align-items:var(--loading-square-box1-align-items, center);background:var(--loading-square-box1-background, #ffab91);animation:var(--loading-square-box1-animation, square-box1 3s ease-in-out 0s infinite alternate);animation-play-state:var(--loading-square-box1-animation-play-state, running)}.ran-loading .square-box2{width:var(--loading-square-box2-width, 50px);height:var(--loading-square-box2-height, 50px);padding:var(--loading-square-box2-padding, 3px);left:var(--loading-square-box2-left, -50px);display:var(--loading-square-box2-display, flex);justify-content:var(--loading-square-box2-justify-content, center);align-items:var(--loading-square-box2-align-items, center);background:var(--loading-square-box2-background, #3ff9dc);transform:var(--loading-square-box2-transform, rotate(45deg));animation:var(--loading-square-box2-animation, square-box2 3s ease-in-out 0s infinite alternate);animation-play-state:var(--loading-square-box2-animation-play-state, running)}.ran-loading .square-core{width:var(--loading-square-core-width, 100%);height:var(--loading-square-core-height, 100%);background:var(--loading-square-core-background, #37474f)}.ran-loading .pulse{width:var(--loading-pulse-width, 120px);display:var(--loading-pulse-display, flex);justify-content:var(--loading-pulse-justify-content, space-between);align-items:var(--loading-pulse-align-items, center)}.ran-loading .pulse-bubble{width:var(--loading-pulse-bubble-width, 20px);height:var(--loading-pulse-bubble-height, 20px);border-radius:var(--loading-pulse-bubble-border-radius, 50%);background:var(--loading-pulse-bubble-background, #3ff9dc)}@keyframes pulse{0%{opacity:var(--loading-pulse-bubble-keyframes-from-opacity, 1);transform:var(--loading-pulse-bubble-keyframes-from-transform, scale(1))}to{opacity:var(--loading-pulse-bubble-keyframes-to-opacity, .25);transform:var(--loading-pulse-bubble-keyframes-to-transform, scale(.75))}}.ran-loading .pulse-bubble-1{animation:var(--loading-pulse-bubble-1-animation, pulse .4s ease 0s infinite alternate);animation-play-state:var(--loading-pulse-bubble-1-animation-play-state, running)}.ran-loading .pulse-bubble-2{animation:var(--loading-pulse-bubble-2-animation, pulse .4s ease .2s infinite alternate);animation-play-state:var(--loading-pulse-bubble-2-animation-play-state, running)}.ran-loading .pulse-bubble-3{animation:var(--loading-pulse-bubble-3-animation, pulse .4s ease .4s infinite alternate);animation-play-state:var(--loading-pulse-bubble-3-animation-play-state, running)}.ran-loading .solar{width:var(--loading-solar-width, 250px);height:var(--loading-solar-height, 250px);display:var(--loading-solar-display, flex);justify-content:var(--loading-solar-justify-content, center);align-items:var(--loading-solar-align-items, center)}@keyframes solar{0%{transform:var(--loading-solar-keyframes-from, rotate(0))}to{transform:var(--loading-solar-keyframes-to, rotate(359deg))}}.ran-loading .solar .orbit{position:var(--loading-solar-orbit-position, relative);display:var(--loading-solar-orbit-display, flex);justify-content:var(--loading-solar-orbit-justify-content, center);align-items:var(--loading-solar-orbit-align-items, center);border:var(--loading-solar-orbit-border, 1px solid #77777d);border-radius:var(--loading-solar-orbit-border-radius, 50%)}.ran-loading .solar .earth-orbit{width:var(--loading-solar-earth-orbit-width, 165px);height:var(--loading-solar-earth-orbit-height, 165px);animation:var(--loading-solar-earth-orbit-animation, solar 12s linear 0s infinite);animation-play-state:var(--loading-solar-earth-orbit-animation-play-state, running)}.ran-loading .solar .venus-orbit{width:var(--loading-solar-venus-orbit-width, 120px);height:var(--loading-solar-venus-orbit-height, 120px);animation:var(--loading-solar-venus-orbit-width, solar 7.4s linear 0s infinite);animation-play-state:var(--loading-solar-venus-orbit-animation-play-state, running)}.ran-loading .solar .mercury-orbit{width:var(--loading-solar-mercury-orbit-width, 90px);height:var(--loading-solar-mercury-orbit-height, 90px);animation:var(--loading-solar-mercury-orbit-animation, solar 3s linear 0s infinite);animation-play-state:var(--loading-solar-mercury-orbit-animation-play-state, running)}.ran-loading .solar .planet{position:var(--loading-solar-planet-position, absolute);top:var(--loading-solar-planet-top, -5px);width:var(--loading-solar-planet-width, 10px);height:var(--loading-solar-planet-height, 10px);border-radius:var(--loading-solar-planet-border-radius, 50%);background:var(--loading-solar-planet-background, #3ff9dc)}.ran-loading .solar .sun{width:var(--loading-solar-sun-width, 35px);height:var(--loading-solar-sun-height, 35px);border-radius:var(--loading-solar-sun-border-radius, 50%);background:var(--loading-solar-sun-background, #ffab91)}.ran-loading .cube-fold{width:var(--loading-cube-fold-width, 4em);height:var(--loading-cube-fold-height, 4em);position:var(--loading-cube-fold-position, relative);margin:var(--loading-cube-fold-margin, auto);transform:var(--loading-cube-fold-transform, rotateZ(45deg))}@keyframes cube-fold{0%,10%{transform:var(--loading-cube-fold-keyframes-0-transform, perspective(140px) rotateX(-180deg));opacity:var(--loading-cube-fold-keyframes-0-opacity, 0)}25%,75%{transform:var(--loading-cube-fold-keyframes-25-transform, perspective(140px) rotateX(0deg));opacity:var(--loading-cube-fold-keyframes-25-opacity, 1)}90%,to{transform:var(--loading-cube-fold-keyframes-90-transform, perspective(140px) rotateY(180deg));opacity:var(--loading-cube-fold-keyframes-90-opacity, 0)}}.ran-loading .cube-fold-item{float:var(--loading-cube-fold-item-float, left);width:var(--loading-cube-fold-item-width, 50%);height:var(--loading-cube-fold-item-height, 50%);position:var(--loading-cube-fold-item-position, relative);transform:var(--loading-cube-fold-item-transform, scale(1.1))}.ran-loading .cube-fold-item:before{content:var(--loading-cube-fold-item-before-content, " ");position:var(--loading-cube-fold-item-before-position, absolute);top:var(--loading-cube-fold-item-before-top, 0);left:var(--loading-cube-fold-item-before-left, 0);width:var(--loading-cube-fold-item-before-width, 100%);height:var(--loading-cube-fold-item-before-height, 100%);background:var(--loading-cube-fold-item-before-background, #337ab7);animation:var(--loading-cube-fold-item-before-animation, cube-fold 2.4s infinite linear both);animation-play-state:var(--loading-cube-fold-item-before-animation-play-state, running);transform-origin:var(--loading-cube-fold-item-before-transform-origin, 100% 100%)}.ran-loading .cube-fold-item-2{transform:var(--loading-cube-fold-item-2-transform, scale(1.1) rotateZ(90deg))}.ran-loading .cube-fold-item-2:before{animation-delay:var(--loading-cube-fold-item-2-before-animation-delay, .3s)}.ran-loading .cube-fold-item-3{transform:var(--loading-cube-fold-item-3-transform, scale(1.1) rotateZ(270deg))}.ran-loading .cube-fold-item-3:before{animation-delay:var(--loading-cube-fold-item-3-before-animation-delay, .9s)}.ran-loading .cube-fold-item-4{transform:var(--loading-cube-fold-item-4-transform, scale(1.1) rotateZ(180deg))}.ran-loading .cube-fold-item-4:before{animation-delay:var(--loading-cube-fold-item-4-before-animation-delay, .6s)}.ran-loading .circle-fold{width:var(--loading-circle-fold-width, 4em);height:var(--loading-circle-fold-height, 4em);position:var(--loading-circle-fold-position, relative);margin:var(--loading-circle-fold-margin, auto)}@keyframes circle-fold{0%,39%,to{opacity:var(--loading-circle-fold-keyframes-0-opacity, 0)}40%{opacity:var(--loading-circle-fold-keyframes-40-opacity, 1)}}.ran-loading .circle-fold-item{width:var(--loading-circle-fold-item-width, 100%);height:var(--loading-circle-fold-item-height, 100%);position:var(--loading-circle-fold-item-position, absolute);left:var(--loading-circle-fold-item-left, 0);top:var(--loading-circle-fold-item-top, 0)}.ran-loading .circle-fold-item:before{content:var(--loading-circle-fold-item-before-content, " ");display:var(--loading-circle-fold-item-before-display, block);margin:var(--loading-circle-fold-item-before-margin, 0 auto);width:var(--loading-circle-fold-item-before-width, 15%);height:var(--loading-circle-fold-item-before-height, 15%);background:var(--loading-circle-fold-item-before-background, #337ab7);border-radius:var(--loading-circle-fold-item-before-border-radius, 100%);animation:var(--loading-circle-fold-item-before-animation, circle-fold 1.2s infinite ease-in-out both);animation-play-state:var(--loading-circle-fold-item-before-animation-play-state, running)}.ran-loading .circle-fold-item-2{transform:var(--loading-circle-fold-item-2-transform, rotate(30deg))}.ran-loading .circle-fold-item-2:before{animation-delay:var(--loading-circle-fold-item-2-before-animation-delay, -1.1s)}.ran-loading .circle-fold-item-3{transform:var(--loading-circle-fold-item-3-transform, rotate(60deg))}.ran-loading .circle-fold-item-3:before{animation-delay:var(--loading-circle-fold-item-3-before-animation-delay, -1s)}.ran-loading .circle-fold-item-4{transform:var(--loading-circle-fold-item-4-transform, rotate(90deg))}.ran-loading .circle-fold-item-4:before{animation-delay:var(--loading-circle-fold-item-4-before-animation-delay, -.9s)}.ran-loading .circle-fold-item-5{transform:var(--loading-circle-fold-item-5-transform, rotate(120deg))}.ran-loading .circle-fold-item-5:before{animation-delay:var(--loading-circle-fold-item-5-before-animation-delay, -.8s)}.ran-loading .circle-fold-item-6{transform:var(--loading-circle-fold-item-6-transform, rotate(150deg))}.ran-loading .circle-fold-item-6:before{animation-delay:var(--loading-circle-fold-item-6-before-animation-delay, -.7s)}.ran-loading .circle-fold-item-7{transform:var(--loading-circle-fold-item-7-transform, rotate(180deg))}.ran-loading .circle-fold-item-7:before{animation-delay:var(--loading-circle-fold-item-7-before-animation-delay, -.6s)}.ran-loading .circle-fold-item-8{transform:var(--loading-circle-fold-item-8-transform, rotate(210deg))}.ran-loading .circle-fold-item-8:before{animation-delay:var(--loading-circle-fold-item-8-before-animation-delay, -.5s)}.ran-loading .circle-fold-item-9{transform:var(--loading-circle-fold-item-9-transform, rotate(240deg))}.ran-loading .circle-fold-item-9:before{animation-delay:var(--loading-circle-fold-item-9-before-animation-delay, -.4s)}.ran-loading .circle-fold-item-10{transform:var(--loading-circle-fold-item-10-transform, rotate(270deg))}.ran-loading .circle-fold-item-10:before{animation-delay:var(--loading-circle-fold-item-10-before-animation-delay, -.3s)}.ran-loading .circle-fold-item-11{transform:var(--loading-circle-fold-item-11-transform, rotate(300deg))}.ran-loading .circle-fold-item-11:before{animation-delay:var(--loading-circle-fold-item-11-before-animation-delay, -.2s)}.ran-loading .circle-fold-item-12{transform:var(--loading-circle-fold-item-12-transform, rotate(330deg))}.ran-loading .circle-fold-item-12:before{animation-delay:var(--loading-circle-fold-item-12-before-animation-delay, -.1s)}.ran-loading .cube-grid{width:var(--loading-cube-grid-width, 4em);height:var(--loading-cube-grid-height, 4em);margin:var(--loading-cube-grid-margin, auto)}@keyframes cube-grid{0%,70%,to{transform:var(--loading-cube-grid-keyframes-0-transform, scale3D(1, 1, 1))}35%{transform:var(--loading-cube-grid-keyframes-35-transform, scale3D(0, 0, 1))}}.ran-loading .cube-grid-item{width:var(--loading-cube-grid-item-width, 33%);height:var(--loading-cube-grid-item-height, 33%);background:var(--loading-cube-grid-item-background, #337ab7);float:var(--loading-cube-grid-item-float, left);animation:var(--loading-cube-grid-item-animation, cube-grid 1.3s infinite ease-in-out);animation-play-state:var(--loading-cube-grid-item-animation-play-state, running)}.ran-loading .cube-grid-item-1{animation-delay:var(--loading-cube-grid-item-1-animation-delay, .2s)}.ran-loading .cube-grid-item-2{animation-delay:var(--loading-cube-grid-item-2-animation-delay, .3s)}.ran-loading .cube-grid-item-3{animation-delay:var(--loading-cube-grid-item-3-animation-delay, .4s)}.ran-loading .cube-grid-item-4{animation-delay:var(--loading-cube-grid-item-4-animation-delay, .1s)}.ran-loading .cube-grid-item-5{animation-delay:var(--loading-cube-grid-item-5-animation-delay, .2s)}.ran-loading .cube-grid-item-6{animation-delay:var(--loading-cube-grid-item-6-animation-delay, .3s)}.ran-loading .cube-grid-item-7{animation-delay:var(--loading-cube-grid-item-7-animation-delay, 0s)}.ran-loading .cube-grid-item-8{animation-delay:var(--loading-cube-grid-item-8-animation-delay, .1s)}.ran-loading .cube-grid-item-9{animation-delay:var(--loading-cube-grid-item-9-animation-delay, .2s)}.ran-loading .circle-turn{width:var(--loading-circle-turn-width, 30px);height:var(--loading-circle-turn-height, 30px);border:var(--loading-circle-turn-border, 8px solid #fff);border-right-color:var(--loading-circle-turn-border-right-color, transparent);border-top-color:var(--loading-circle-turn-border-top-color, transparent);border-radius:var(--loading-circle-turn-border-radius, 50%);box-shadow:var(--loading-circle-turn-box-shadow, 0 0 25px 2px);border-color:var(--loading-circle-turn-border-color, #f00);color:var(--loading-circle-turn-color, #cc0000);animation:var(--loading-circle-turn-animation, circle-turn 1s linear infinite normal);animation-play-state:var(--loading-circle-turn-animation-play-state, running);animation-delay:var(--loading-circle-turn-animation-delay, 0);margin:var(--loading-circle-turn-margin, 30px auto 0)}@keyframes circle-turn{0%{transform:var(--loading-circle-turn-keyframes-from-transform, rotate(0deg));opacity:var(--loading-circle-turn-keyframes-from-opacity, .2)}50%{transform:var(--loading-circle-turn-keyframes-50-transform, rotate(180deg));opacity:var(--loading-circle-turn-keyframes-50-opacity, 1)}to{transform:var(--loading-circle-turn-keyframes-50-transform, rotate(360deg));opacity:var(--loading-circle-turn-keyframes-50-opacity, .2)}}.ran-loading .circle-turn:after{display:var(--loading-circle-turn-after-display, block);width:var(--loading-circle-turn-after-width, 13px);height:var(--loading-circle-turn-after-height, 13px);margin:var(--loading-circle-turn-after-margin, 3px);border:var(--loading-circle-turn-after-border, 6px solid #f00);content:var(--loading-circle-turn-after-content, " ");border-radius:var(--loading-circle-turn-after-border-radius, 50%);border-left-color:var(--loading-circle-turn-after-border-left-color, transparent);border-bottom-color:var(--loading-circle-turn-after-border-bottom-color, transparent)}.ran-loading .circle-rotate{margin:var(--loading-circle-rotate-margin, 30px auto 0)}@keyframes spin-right{0%{transform:var(--loading-circle-rotate-keyframes-spin-right-from-transform, rotate(0deg));opacity:var(--loading-circle-rotate-keyframes-spin-right-from-opacity, var(--loading-circle-rotate-margin, .2))}50%{transform:var(--loading-circle-rotate-keyframes-spin-right-50-opacity, rotate(180deg));opacity:var(--loading-circle-rotate-keyframes-spin-right-50-opacity, 1)}to{transform:var(--loading-circle-rotate-keyframes-spin-right-to-opacity, rotate(360deg));opacity:var(--loading-circle-rotate-keyframes-spin-right-to-opacity, .2)}}@keyframes spin-left{0%{transform:var(--loading-circle-rotate-keyframes-spin-left-from-transform, rotate(0deg));opacity:var(--loading-circle-rotate-keyframes-spin-left-from-opacity, .2)}50%{transform:var(--loading-circle-rotate-keyframes-spin-left-50-transform, rotate(-180deg));opacity:var(--loading-circle-rotate-keyframes-spin-left-50-opacity, 1)}to{transform:var(--loading-circle-rotate-keyframes-spin-left-to-transform, rotate(-360deg));opacity:var(--loading-circle-rotate-keyframes-spin-left-to-opacity, .2)}}.ran-loading .circle-rotate-outer{border:var(--loading-circle-rotate-outer-border, 5px solid rgba(0, 183, 229, .9));opacity:var(--loading-circle-rotate-outer-opacity, .9);width:var(--loading-circle-rotate-outer-width, 50px);height:var(--loading-circle-rotate-outer-height, 50px);border-top-color:var(--loading-circle-rotate-outer-border-top-color, transparent);border-bottom-color:var(--loading-circle-rotate-outer-border-bottom-color, transparent);border-radius:var(--loading-circle-rotate-outer-border-radius, 50%);box-shadow:var(--loading-circle-rotate-outer-box-shadow, 0 0 35px rgba(0, 61, 76, .9));animation:var(--loading-circle-rotate-outer-animation, spin-right .5s linear infinite normal);animation-play-state:var(--loading-circle-rotate-outer-animation-play-state, running);animation-delay:var(--loading-circle-rotate-outer-animation-delay, 0);margin:var(--loading-circle-rotate-outer-margin, 0 auto)}.ran-loading .circle-rotate-inner{display:var(--loading-circle-rotate-inner-display, block);width:var(--loading-circle-rotate-inner-width, 30px);height:var(--loading-circle-rotate-inner-height, 30px);border:var(--loading-circle-rotate-inner-border, 5px solid rgba(0, 183, 229, .9));opacity:var(--loading-circle-rotate-inner-opacity, .9);border-radius:var(--loading-circle-rotate-inner-border-radius, 50%);border-left-color:var(--loading-circle-rotate-inner-border-left-color, transparent);border-bottom-color:var(--loading-circle-rotate-inner-border-bottom-color, transparent);box-shadow:var(--loading-circle-rotate-inner-box-shadow, 0 0 35px rgba(0, 61, 76, .9));position:var(--loading-circle-rotate-inner-position, relative);top:var(--loading-circle-rotate-inner-top, -50px);margin:var(--loading-circle-rotate-inner-margin, 0 auto);animation:var(--loading-circle-rotate-inner-animation, spin-left .5s linear infinite normal);animation-play-state:var(--loading-circle-rotate-inner-animation-play-state, running);animation-delay:var(--loading-circle-rotate-inner-animation-delay, 0)}@keyframes spin-right{0%{transform:var(--loading-circle-spin-keyframes-spin-right-from-transform, rotate(0deg));opacity:var(--loading-circle-spin-keyframes-spin-right-from-opacity, .2)}50%{transform:var(--loading-circle-spin-keyframes-spin-right-50-transform, rotate(180deg));opacity:var(--loading-circle-spin-keyframes-spin-right-50-opacity, 1)}to{transform:var(--loading-circle-spin-keyframes-spin-right-to-transform, rotate(360deg));opacity:var(--loading-circle-spin-keyframes-spin-right-to-opacity, .2)}}@keyframes spin-pulse{0%{transform:var(--loading-circle-spin-keyframes-spin-pulse-from-transform, rotate(160deg));opacity:var(--loading-circle-spin-keyframes-spin-pulse-from-opacity, 0);box-shadow:var(--loading-circle-spin-keyframes-spin-pulse-from-box-shadow, 0 0 1px rgba(0, 61, 76, .9))}50%{transform:var(--loading-circle-spin-keyframes-spin-pulse-50-transform, rotate(145deg));opacity:var(--loading-circle-spin-keyframes-spin-pulse-50-opacity, 1)}to{transform:var(--loading-circle-spin-keyframes-spin-pulse-to-transform, rotate(-320deg));opacity:var(--loading-circle-spin-keyframes-spin-pulse-to-opacity, 0)}}.ran-loading .circle-spin-inner{border:var(--loading-circle-spin-inner-border, 5px solid rgba(0, 229, 183, .9));opacity:var(--loading-circle-spin-inner-opacity, .9);border-left-color:var(--loading-circle-spin-inner-border-left-color, transparent);border-right-color:var(--loading-circle-spin-inner-border-right-color, transparent);border-radius:var(--loading-circle-spin-inner-border-radius, 50%);box-shadow:var(--loading-circle-spin-inner-box-shadow, 0 0 15px rgba(0, 76, 61, .9));width:var(--loading-circle-spin-inner-width, 30px);height:var(--loading-circle-spin-inner-height, 30px);position:var(--loading-circle-spin-inner-position, relative);top:var(--loading-circle-spin-inner-top, -50px);margin:var(--loading-circle-spin-inner-margin, 0 auto);animation:var(--loading-circle-spin-inner-animation, spin-right 1s linear infinite normal);animation-play-state:var(--loading-circle-spin-inner-animation-play-state, running);animation-delay:var(--loading-circle-spin-inner-animation-delay, 0)}.ran-loading .circle-spin-outer{border:var(--loading-circle-spin-inner-border, 5px solid rgba(0, 229, 183, .9));opacity:var(--loading-circle-spin-inner-border, .9);border-right-color:var(--loading-circle-spin-inner-border, transparent);border-left-color:var(--loading-circle-spin-inner-border, transparent);width:var(--loading-circle-spin-inner-border, 50px);height:var(--loading-circle-spin-inner-border, 50px);margin:var(--loading-circle-spin-inner-border, 0 auto);border-radius:var(--loading-circle-spin-inner-border, 50%);box-shadow:var(--loading-circle-spin-inner-border, 0 0 35px rgba(0, 76, 61, .9));animation:var(--loading-circle-spin-inner-border, spin-pulse 1s linear infinite normal);animation-play-state:var(--loading-circle-spin-outer-animation-play-state, running);animation-delay:var(--loading-circle-spin-inner-border, 0)}.ran-loading .dot-bar{margin:var(--loading-dot-bar-margin, 0 auto);overflow:var(--loading-dot-bar-overflow, hidden);width:var(--loading-dot-bar-width, 90px)}@keyframes pulse{0%{transform:var(--loading-dot-bar-keyframes-from-transform, scale(1.2));opacity:var(--loading-dot-bar-margin-from-opacity, 1)}to{transform:var(--loading-dot-bar-keyframes-to-transform, scale(.7));opacity:var(--loading-dot-bar-keyframes-to-opacity, .1)}}.ran-loading .dot-bar-item{background-color:var(--loading-dot-bar-item-background-color, #8aff51);background-image:var(--loading-dot-bar-item-background-image, linear-gradient(45deg, #8aff51 25%, #f1ffea));width:var(--loading-dot-bar-item-width, 10px);height:var(--loading-dot-bar-item-height, 10px);float:var(--loading-dot-bar-item-float, left);margin-left:var(--loading-dot-bar-item-margin-left, 5px);opacity:var(--loading-dot-bar-item-opacity, .1);animation:var(--loading-dot-bar-item-animation, pulse 1s linear infinite normal);animation-play-state:var(--loading-dot-bar-item-animation-play-state, running);animation-delay:var(--loading-dot-bar-item-animation-delay, 0)}.ran-loading .dot-bar-item-1{animation-delay:var(--loading-dot-bar-item-1-animation-delay, .3s)}.ran-loading .dot-bar-item-2{animation-delay:var(--loading-dot-bar-item-2-animation-delay, .2s)}.ran-loading .dot-bar-item-3{animation-delay:var(--loading-dot-bar-item-3-animation-delay, .1s)}.ran-loading .dot-bar-item-4{animation-delay:var(--loading-dot-bar-item-4-animation-delay, .2s)}.ran-loading .dot-bar-item-5{animation-delay:var(--loading-dot-bar-item-5-animation-delay, .3s)}.ran-loading .dot-circle-item{background-color:var(--loading-dot-circle-item-background-color, #f00);background-image:var(--loading-dot-circle-item-background-image, linear-gradient(90deg, #f00 25%, #ff9999));width:var(--loading-dot-circle-item-width, 3px);height:var(--loading-dot-circle-item-height, 3px);border-radius:var(--loading-dot-circle-item-border-radius, 50%);box-shadow:var(--loading-dot-circle-item-box-shadow, 0 0 5px #cc0000);margin:var(--loading-dot-circle-item-margin, 0 auto);position:var(--loading-dot-circle-item-position, relative);animation:var(--loading-dot-circle-item-animation, dot-circle 2s infinite cubic-bezier(0, 0, .35, 1) normal)}.ran-loading .dot-circle-item-1{animation-play-state:var(--loading-dot-circle-item-1-animation-play-state, running);animation-delay:var(--loading-dot-circle-item-1-animation-delay, 0)}.ran-loading .dot-circle-item-2{opacity:var(--loading-dot-circle-item-2-opacity, .7);top:var(--loading-dot-circle-item-2-top, 1px);animation-play-state:var(--loading-dot-circle-item-2-animation-play-state, running);animation-delay:var(--loading-dot-circle-item-2-animation-delay, .1s)}.ran-loading .dot-circle-item-3{opacity:var(--loading-dot-circle-item-3-opacity, .5);top:var(--loading-dot-circle-item-3-top, 2px);animation-play-state:var(--loading-dot-circle-item-3-animation-play-state, running);animation-delay:var(--loading-dot-circle-item-3-animation-delay, .2s)}.ran-loading .dot-circle-item-4{opacity:var(--loading-dot-circle-item-4-opacity, .3);top:var(--loading-dot-circle-item-4-top, 3px);animation-play-state:var(--loading-dot-circle-item-4-animation-play-state, running);animation-delay:var(--loading-dot-circle-item-4-animation-delay, .3s)}.ran-loading .dot-circle-item-5{opacity:var(--loading-dot-circle-item-5-opacity, .1);top:var(--loading-dot-circle-item-5-top, 4px);animation-play-state:var(--loading-dot-circle-item-5-animation-play-state, running);animation-delay:var(--loading-dot-circle-item-5-animation-delay, .4s)}@keyframes dot-circle{0%{transform:var(--loading-dot-circle-keyframes-from-transform, translateX(0px))}25%{transform:var(--loading-dot-circle-keyframes-25-transform, translateX(25px));animation-timing-function:ease-in}50%{transform:var(--loading-dot-circle-keyframes-50-transform, translateX(0px))}75%{transform:var(--loading-dot-circle-keyframes-75-transform, translateX(-25px));animation-timing-function:ease-in}to{transform:var(--loading-dot-circle-keyframes-to-transform, translateX(0px))}}.ran-loading .line{width:var(--loading-line-width, 32px);height:var(--loading-line-width, 32px);margin:var(--loading-line-width, 0 auto)}@keyframes line{10%{margin-top:var(--loading-line-keyframes-10-margin-top, 5px);height:var(--loading-line-keyframes-10-height, 22px);border-color:var(--loading-line-keyframes-10-border-color, #d1d8e6);background-color:var(--loading-line-keyframes-10-background-color, #bac5db)}20%{margin-top:var(--loading-line-keyframes-20-margin-top, 0px);height:var(--loading-line-keyframes-20-height, 32px);border-color:var(--loading-line-keyframes-20-border-color, #d1d7e2);background-color:var(--loading-line-keyframes-20-background-color, #bac5db)}30%{margin-top:var(--loading-line-keyframes-30-margin-top, 1px);height:var(--loading-line-keyframes-30-height, 30px);border-color:var(--loading-line-keyframes-30-border-color, #d1d8e6);background-color:var(--loading-line-keyframes-30-background-color, #bac5db)}40%{margin-top:var(--loading-line-keyframes-40-margin-top, 3px);height:var(--loading-line-keyframes-40-height, 26px)}50%{margin-top:var(--loading-line-keyframes-50-margin-top, 5px);height:var(--loading-line-keyframes-50-height, 22px)}60%{margin-top:var(--loading-line-keyframes-60-margin-top, 6px);height:var(--loading-line-keyframes-60-height, 18px)}}.ran-loading .line-item{background:var(--loading-line-item-background, #99aaca);border:var(--loading-line-item-border, 1px solid #96a6c9);float:var(--loading-line-item-float, left);margin:var(--loading-line-item-margin, 6px 4px 0 0);width:var(--loading-line-item-width, 6px);height:var(--loading-line-item-height, 18px);animation:var(--loading-line-item-animation, line 1s linear infinite normal);animation-play-state:var(--loading-line-item-animation-play-state, running);animation-delay:var(--loading-line-item-animation-delay, 0)}.ran-loading .line-item:nth-child(2){animation-delay:var(--loading-line-nth-child-2-animation-delay, .1s)}.ran-loading .line-item:last-child{margin-right:var(--loading-line-last-child-margin-right, 0);animation-delay:var(--loading-line-last-child-animation-delay, .2s)}.ran-loading .dot-pulse{width:var(--loading-dot-pulse-width, 48px);padding:var(--loading-dot-pulse-padding, 8px 5px);margin:var(--loading-dot-pulse-margin, 30px auto);overflow:var(--loading-dot-pulse-overflow, hidden)}@keyframes dot-pulse{0%{transform:var(--loading-dot-pulse-keyframes-from, scale(0))}to{transform:var(--loading-dot-pulse-keyframes-to, scale(1))}}@keyframes dot-pulse-glow{0%{transform:var(--loading-dot-pulse-keyframes-glow-from-transform, scale(0));opacity:var(--loading-dot-pulse-keyframes-glow-from-opacity, 0)}10%{transform:var(--loading-dot-pulse-keyframes-glow-10-transform, scale(1));opacity:var(--loading-dot-pulse-keyframes-glow-10-opacity, .5)}50%{transform:var(--loading-dot-pulse-keyframes-glow-50-transform, scale(1.75));opacity:var(--loading-dot-pulse-keyframes-glow-50-opacity, 0)}to{transform:var(--loading-dot-pulse-keyframes-glow-to-transform, scale(0));opacity:var(--loading-dot-pulse-keyframes-glow-to-opacity, 0)}}.ran-loading .dot-pulse-item{float:var(--loading-dot-pulse-item-float, left);position:var(--loading-dot-pulse-item-position, relative);width:var(--loading-dot-pulse-item-width, 6px);height:var(--loading-dot-pulse-item-height, 6px);border-radius:var(--loading-dot-pulse-item-border-radius, 50px);margin-left:var(--loading-dot-pulse-item-margin-left, 2px)}.ran-loading .dot-pulse-item:first-child{margin-left:var(--loading-dot-pulse-item-first-child-margin-left, 0)}.ran-loading .dot-pulse-item-dot{background-color:var(--loading-dot-pulse-item-dot-background-color, #2187e7);background-image:var(--loading-dot-pulse-item-dot-background-image, linear-gradient(90deg, #2187e7 25%, #a0eaff));width:var(--loading-dot-pulse-item-dot-width, 6px);height:var(--loading-dot-pulse-item-dot-height, 6px);border-radius:var(--loading-dot-pulse-item-dot-border-radius, 50px);transform:var(--loading-dot-pulse-item-dot-transform, scale(0));animation:var(--loading-dot-pulse-item-dot-animation, dot-pulse 1s linear forwards normal);animation-play-state:var(--loading-dot-pulse-item-dot-animation-play-state, running);animation-delay:var(--loading-dot-pulse-item-dot-animation-delay, 0)}.ran-loading .dot-pulse-item-dot-1{animation-delay:var(--loading-dot-pulse-item-dot-1-animation-delay, .5s)}.ran-loading .dot-pulse-item-dot-2{animation-delay:var(--loading-dot-pulse-item-dot-2-animation-delay, 1s)}.ran-loading .dot-pulse-item-dot-3{animation-delay:var(--loading-dot-pulse-item-dot-3-animation-delay, 1.5s)}.ran-loading .dot-pulse-item-dot-4{animation-delay:var(--loading-dot-pulse-item-dot-4-animation-delay, 2s)}.ran-loading .dot-pulse-item-dot-5{animation-delay:var(--loading-dot-pulse-item-dot-5-animation-delay, 2.5s)}.ran-loading .dot-pulse-item-ball{width:var(--loading-dot-pulse-item-ball-width, 6px);height:var(--loading-dot-pulse-item-ball-height, 6px);border-radius:var(--loading-dot-pulse-item-ball-border-radius, 30px);border:var(--loading-dot-pulse-item-ball-border, 1px solid #00c6ff);box-shadow:var(--loading-dot-pulse-item-ball-box-shadow, 0 0 5px #00c6ff);position:var(--loading-dot-pulse-item-ball-position, absolute);top:var(--loading-dot-pulse-item-ball-top, -1px);left:var(--loading-dot-pulse-item-ball-left, -1px);transform:var(--loading-dot-pulse-item-ball-transform, scale(0));animation:var(--loading-dot-pulse-item-ball-animation, dot-pulse-glow 3s infinite ease-out normal);animation-play-state:var(--loading-dot-pulse-item-ball-animation-play-state, running);animation-delay:var(--loading-dot-pulse-item-ball-animation-delay, 0)}.ran-loading .dot-pulse-item-ball-1{animation-delay:var(--loading-dot-pulse-item-ball-1-animation-delay, 1.5s)}.ran-loading .dot-pulse-item-ball-2{animation-delay:var(--loading-dot-pulse-item-ball-2-animation-delay, 2s)}.ran-loading .dot-pulse-item-ball-3{animation-delay:var(--loading-dot-pulse-item-ball-3-animation-delay, 2.5s)}.ran-loading .dot-pulse-item-ball-4{animation-delay:var(--loading-dot-pulse-item-ball-4-animation-delay, 3s)}.ran-loading .dot-pulse-item-ball-5{animation-delay:var(--loading-dot-pulse-item-ball-5-animation-delay, 3.5s)}.ran-loading .line-scale{display:var(--loading-line-scale-display, block);position:var(--loading-line-scale-position, relative);overflow:var(--loading-line-scale-overflow, hidden);width:var(--loading-line-scale-width, 5em);margin:var(--loading-line-scale-margin, 30px auto);padding:var(--loading-line-scale-padding, 20px 10px)}@keyframes pound{to{transform:var(--loading-line-scale-keyframes-to-transform, scale(1.2))}}.ran-loading .line-scale-item{display:var(--loading-line-scale-item-display, block);float:var(--loading-line-scale-item-float, left);width:var(--loading-line-scale-item-width, .5em);height:var(--loading-line-scale-item-height, 3em);margin:var(--loading-line-scale-item-margin, 0 .5em 0 0);background:var(--loading-line-scale-item-background, #635863);background-image:var(--loading-line-scale-item-background-image, linear-gradient(top, #635863 25%, #3d353b));box-shadow:var(--loading-line-scale-item-box-shadow, 1px 1px 1px 0 rgba(0, 0, 0, 0), 1px 1px 1px 0 rgba(0, 0, 0, 0), 1px 1px 1px 0 rgba(0, 0, 0, 0));animation:var(--loading-line-scale-item-animation, pound .7s ease-in-out infinite alternate);animation-play-state:var(--loading-line-scale-item-animation-play-state, running);animation-delay:var(--loading-line-scale-item-animation-delay, .05s);transform-origin:var(--loading-line-scale-item-transform-origin, center bottom)}.ran-loading .line-scale-item:nth-child(2){animation-delay:var(--loading-line-scale-item--nth-child-2-animation-delay, .2s)}.ran-loading .line-scale-item:nth-child(3){animation-delay:var(--loading-line-scale-item--nth-child-3-animation-delay, .35s)}.ran-loading .line-scale-item:nth-child(4){animation-delay:var(--loading-line-scale-item--nth-child-4-animation-delay, .5s)}.ran-loading .line-scale-item:nth-child(5){animation-delay:var(--loading-line-scale-item--nth-child-5-animation-delay, .65s)}.ran-loading .text{text-align:var(--loading-text-text-align, center);text-transform:var(--loading-text-text-transform, uppercase);font-family:var(--loading-text-font-family, "Nunito", sans-serif);font-size:var(--loading-text-font-size, 4em);color:var(--loading-text-color, transparent);letter-spacing:var(--loading-text-letter-spacing, .4em)}@keyframes letters{to{text-shadow:var(--loading-text-keyframes-to-text-shadow, 0 0 2px rgba(204, 208, 212, .2), 0 0 3px rgba(0, 0, 0, .02), 0 0 0 rgba(0, 0, 0, 0), 0 0 0 rgba(255, 255, 255, 0), 0 0 0 rgba(0, 0, 0, 0), 0 0 0 rgba(255, 255, 255, 0), 0 0 0 rgba(255, 255, 255, 0))}}.ran-loading .text-item{text-shadow:var(--loading-text-item-text-shadow, 0 0 2px rgba(22, 22, 22, .9), 0 15px 25px rgba(0, 0, 0, .3), 0 -2px 3px rgba(0, 0, 0, .1), 0 -5px 10px rgba(22, 22, 22, .5), 0 5px 10px rgba(0, 0, 0, .3), 0 3px 4px rgba(22, 22, 22, .2), 0 0 20px rgba(22, 22, 22, .45));animation:var(--loading-text-item-animation, letters .85s ease-in-out infinite alternate);animation-play-state:var(--loading-text-item-animation-play-state, running);animation-delay:var(--loading-text-item-animation-delay, 0)}.ran-loading .text-item:nth-child(2){animation-delay:var(--loading-text-item-nth-child-2-animation-delay, .15s)}.ran-loading .text-item:nth-child(3){animation-delay:var(--loading-text-item-nth-child-3-animation-delay, .3s)}.ran-loading .text-item:nth-child(4){animation-delay:var(--loading-text-item-nth-child-4-animation-delay, .45s)}.ran-loading .text-item:nth-child(5){animation-delay:var(--loading-text-item-nth-child-5-animation-delay, .6s)}.ran-loading .text-item:nth-child(6){animation-delay:var(--loading-text-item-nth-child-6-animation-delay, .75s)}.ran-loading .text-item:nth-child(7){animation-delay:var(--loading-text-item-nth-child-7-animation-delay, .9s)}.ran-loading .cube-dim{height:var(--loading-cube-dim-height, 9em);width:var(--loading-cube-dim-width, 9em);padding:var(--loading-cube-dim-padding, 3em);transform:var(--loading-cube-dim-transform, rotateX(45deg) rotateZ(45deg));transform-style:var(--loading-cube-dim-transform-style, preserve-3d)}@keyframes anim{50%{transform:var(--loading-cube-dim-width, translateZ(.5em))}}.ran-loading .cube-dim-item{background-color:var(--loading-cube-dim-item-background-color, #05afd1);position:var(--loading-cube-dim-item-position, relative);transform:var(--loading-cube-dim-item-transform, translateZ(3em));transform-style:var(--loading-cube-dim-item-transform-style, preserve-3d);transition:var(--loading-cube-dim-item-transition, .25s);box-shadow:var(--loading-cube-dim-item-box-shadow, 13em 13em 1.5em rgba(0, 0, 0, .1));animation:var(--loading-cube-dim-item-animation, anim 1s infinite);animation-play-state:var(--loading-cube-dim-item-animation-play-state, running);float:var(--loading-cube-dim-item-float, left);height:var(--loading-cube-dim-item-height, 3em);width:var(--loading-cube-dim-item-width, 3em)}.ran-loading .cube-dim-item:nth-child(1){animation-delay:var(--loading-cube-dim-item-nth-child-1-animation-delay, .05s)}.ran-loading .cube-dim-item:nth-child(2){animation-delay:var(--loading-cube-dim-item-nth-child-2-animation-delay, .1s)}.ran-loading .cube-dim-item:nth-child(3){animation-delay:var(--loading-cube-dim-item-nth-child-3-animation-delay, .15s)}.ran-loading .cube-dim-item:nth-child(4){animation-delay:var(--loading-cube-dim-item-nth-child-4-animation-delay, .2s)}.ran-loading .cube-dim-item:nth-child(5){animation-delay:var(--loading-cube-dim-item-nth-child-5-animation-delay, .25s)}.ran-loading .cube-dim-item:nth-child(6){animation-delay:var(--loading-cube-dim-item-nth-child-6-animation-delay, .3s)}.ran-loading .cube-dim-item:nth-child(7){animation-delay:var(--loading-cube-dim-item-nth-child-7-animation-delay, .35s)}.ran-loading .cube-dim-item:nth-child(8){animation-delay:var(--loading-cube-dim-item-nth-child-8-animation-delay, .4s)}.ran-loading .cube-dim-item:nth-child(9){animation-delay:var(--loading-cube-dim-item-nth-child-9-animation-delay, .45s)}.ran-loading .cube-dim-item:before{content:var(--loading-cube-dim-item-before-content, "");float:var(--loading-cube-dim-item-before-float, left);height:var(--loading-cube-dim-item-before-height, 3em);position:var(--loading-cube-dim-item-before-position, absolute);width:var(--loading-cube-dim-item-before-width, 3em);background-color:var(--loading-cube-dim-item-before-background-color, #048ca7);transform:var(--loading-cube-dim-item-before-transform, rotateY(90deg) translateX(3em));transform-origin:var(--loading-cube-dim-item-before-transform-origin, 100% 0)}.ran-loading .cube-dim-item:after{content:var(--loading-cube-dim-item-after-content, "");float:var(--loading-cube-dim-item-after-float, left);height:var(--loading-cube-dim-item-after-height, 3em);position:var(--loading-cube-dim-item-after-position, absolute);width:var(--loading-cube-dim-item-after-width, 3em);background-color:var(--loading-cube-dim-item-after-background-color, #049dbc);transform:var(--loading-cube-dim-item-after-transform, rotateX(-90deg) translateY(3em));transform-origin:var(--loading-cube-dim-item-after-transform-origin, 100% 100%)}.ran-loading .dot-line{width:var(--loading-dot-line-width, 20em);height:var(--loading-dot-line-height, 20em);font-size:var(--loading-dot-line-font-size, 10px);position:var(--loading-dot-line-position, relative);display:var(--loading-dot-line-display, flex);align-items:var(--loading-dot-line-align-items, center);justify-content:var(--loading-dot-line-justify-content, center)}@keyframes dot-line{to{transform:var(--loading-dot-line-keyframes-to-transform, rotate(1turn))}}.ran-loading .dot-line-item{position:var(--loading-dot-line-item-position, absolute);border-radius:var(--loading-dot-line-item-border-radius, 50%);border-style:var(--loading-dot-line-item-order-style, solid);animation:var(--loading-dot-line-item-animation, dot-line 3s linear infinite);animation-play-state:var(--loading-dot-line-item-animation-play-state, running)}.ran-loading .dot-line-item:nth-child(1){width:var(--loading-dot-line-item-nth-child-1-width, 100%);height:var(--loading-dot-line-item-nth-child-1-height, 100%);color:var(--loading-dot-line-item-nth-child-1-color, gold);border-color:var(--loading-dot-line-item-nth-child-1-border-color, currentColor transparent transparent currentColor);border-width:var(--loading-dot-line-item-nth-child-1-border-width, .2em .2em 0em 0em);--deg: var(--loading-dot-line-item-nth-child-1-deg, -45deg);animation-direction:var(--loading-dot-line-item-nth-child-1-animation-direction, normal)}.ran-loading .dot-line-item:nth-child(2){width:var(--loading-dot-line-item-nth-child-2-width, 70%);height:var(--loading-dot-line-item-nth-child-2-height, 70%);color:var(--loading-dot-line-item-nth-child-2-color, lime);border-color:var(--loading-dot-line-item-nth-child-2-border-color, currentColor currentColor transparent transparent);border-width:var(--loading-dot-line-item-nth-child-2-border-width, .2em 0em 0em .2em);--deg: var(--loading-dot-line-item-nth-child-2-deg, -135deg);animation-direction:var(--loading-dot-line-item-nth-child-2-animation-direction, reverse)}.ran-loading .dot-line-item-circle{position:var(--loading-dot-line-item-circle-position, absolute);width:var(--loading-dot-line-item-circle-width, 50%);height:var(--loading-dot-line-item-circle-height, .1em);top:var(--loading-dot-line-item-circle-top, 50%);left:var(--loading-dot-line-item-circle-left, 50%);background-color:var(--loading-dot-line-item-circle-background-color, transparent);transform:rotate(var(--deg));transform-origin:var(--loading-dot-line-item-circle-transform-origin, left)}.ran-loading .dot-line-item-circle:before{position:var(--loading-dot-line-item-circle-before-position, absolute);top:var(--loading-dot-line-item-circle-before-top, -.5em);right:var(--loading-dot-line-item-circle-before-right, -.5em);content:var(--loading-dot-line-item-circle-before-content, "");width:var(--loading-dot-line-item-circle-before-width, 1em);height:var(--loading-dot-line-item-circle-before-height, 1em);background-color:var(--loading-dot-line-item-circle-before-background-color, currentColor);border-radius:var(--loading-dot-line-item-circle-before-border-radius, 50%);box-shadow:var(--loading-dot-line-item-circle-before-box-shadow, 0 0 2em, 0 0 4em, 0 0 6em, 0 0 8em, 0 0 10em, 0 0 0 .5em rgba(255, 255, 0, .1))}.ran-loading .arc{position:relative}@keyframes rt{to{transform:var(--loading-arc-keyframes-rt, rotate(360deg))}}@keyframes cw{0%{width:var(--loading-arc-keyframes-cw-0-width, 0);height:var(--loading-arc-keyframes-cw-0-height, 0)}75%{width:var(--loading-arc-keyframes-cw-75-width, 40px);height:var(--loading-arc-keyframes-cw-75-height, 40px)}to{width:var(--loading-arc-keyframes-cw-100-width, 0);height:var(--loading-arc-keyframes-cw-100-height, 0)}}@keyframes txt{0%{content:var(--loading-arc-keyframes-txt-0-content, "LOADING.")}50%{content:var(--loading-arc-keyframes-txt-50-content, "LOADING..")}to{content:var(--loading-arc-keyframes-txt-100-content, "LOADING...")}}.ran-loading .arc-item{margin:var(--loading-arc-item-margin, auto);width:var(--loading-arc-item-width, 100px);height:var(--loading-arc-item-height, 100px);border-radius:var(--loading-arc-item-border-radius, 50%);border-top:var(--loading-arc-item-border-top, 2px solid #ffea29);border-left:var(--loading-arc-item-border-left, 1px solid transparent);border-right:var(--loading-arc-item-border-right, 1px solid transparent);animation:var(--loading-arc-item-animation, rt 2s infinite linear);animation-play-state:var(--loading-arc-item-animation-play-state, running)}.ran-loading .arc-item:before{position:var(--loading-arc-item-before-position, absolute);margin:var(--loading-arc-item-before-margin, auto);top:var(--loading-arc-item-before-top, 0);right:var(--loading-arc-item-before-right, 0);bottom:var(--loading-arc-item-before-bottom, 0);left:var(--loading-arc-item-before-left, 0);width:var(--loading-arc-item-before-width, 70px);height:var(--loading-arc-item-before-height, 70px);border-radius:var(--loading-arc-item-before-border-radius, 50%);border-top:var(--loading-arc-item-before-border-top, 2px solid #8d29ff);border-left:var(--loading-arc-item-before-border-left, 1px solid transparent);border-right:var(--loading-arc-item-before-border-right, 1px solid transparent);animation:var(--loading-arc-item-before-animation, rt 4s infinite linear reverse);animation-play-state:var(--loading-arc-item-before-animation-play-state, running);content:var(--loading-arc-item-before-content, "")}.ran-loading .arc-item:after{position:var(--loading-arc-item-after-position, absolute);margin:var(--loading-arc-item-after-margin, auto);top:var(--loading-arc-item-after-top, 0);right:var(--loading-arc-item-after-right, 0);bottom:var(--loading-arc-item-after-bottom, 0);left:var(--loading-arc-item-after-left, 0);width:var(--loading-arc-item-after-width, 0);height:var(--loading-arc-item-after-height, 0);border-radius:var(--loading-arc-item-after-border-radius, 50%);border-top:var(--loading-arc-item-after-border-top, initial);border-left:var(--loading-arc-item-after-border-left, initial);border-right:var(--loading-arc-item-after-border-right, initial);animation:var(--loading-arc-item-after-animation, cw 1s infinite);animation-play-state:var(--loading-arc-item-after-animation-play-state, running);content:var(--loading-arc-item-after-content, "");background:var(--loading-arc-item-after-background, snow)}.ran-loading .arc h1{position:var(--loading-arc-h1-position, absolute);margin:var(--loading-arc-h1-margin, auto);top:var(--loading-arc-h1-top, 140px);left:var(--loading-arc-h1-left, 0);right:var(--loading-arc-h1-right, 0);bottom:var(--loading-arc-h1-bottom, 0);text-transform:var(--loading-arc-h1-text-transform, uppercase);text-align:var(--loading-arc-h1-text-align, center);letter-spacing:var(--loading-arc-h1-letter-spacing, .1em);font-size:var(--loading-arc-h1-font-size, 14px);font-weight:var(--loading-arc-h1-ont-weight, lighter);color:var(--loading-arc-h1-color, white)}.ran-loading .arc h1:after{animation:var(--loading-arc-h1-after-animation, txt 5s infinite);animation-play-state:var(--loading-arc-h1-after-animation-play-state, running);content:var(--loading-arc-h1-after-content, "");font-family:var(--loading-arc-h1-after-font-family, "Inconsolata", monospace)}.ran-loading .arc span{display:var(--loading-arc-span-display, none)}.ran-loading .drop{position:var(--loading-drop-position, relative);width:var(--loading-drop-position, 120px);height:var(--loading-drop-position, 120px)}@keyframes fade-in{0%{opacity:var(--loading-drop-keyframes-fade-in-0-opacity, 0)}to{opacity:var(--loading-drop-keyframes-fade-in-100-opacity, 1)}}@keyframes drop{0%{bottom:var(--loading-drop-keyframes-drop-0-bottom, 0px);opacity:var(--loading-drop-keyframes-drop-0-opacity, 1)}80%{opacity:var(--loading-drop-keyframes-drop-80-opacity, 1)}to{opacity:var(--loading-drop-keyframes-drop-100-opacity, 1);bottom:var(--loading-drop-keyframes-drop-100-bottom, -200px)}}@keyframes wave{0%{background-position:var(--loading-drop-keyframes-wave-0-background-position, 0 160px);background-size:var(--loading-drop-keyframes-wave-0-background-size, 170px 300px)}to{background-position:var(--loading-drop-keyframes-wave-100-background-position, 500px -18px);background-size:var(--loading-drop-keyframes-wave-100-background-size, 250px 150px)}}.ran-loading .drop-item{position:var(--loading-drop-item-position, absolute);width:var(--loading-drop-item-width, 100%);height:var(--loading-drop-item-height, 100%);left:var(--loading-drop-item-left, 0);right:var(--loading-drop-item-right, 0);top:var(--loading-drop-item-top, 0);bottom:var(--loading-drop-item-bottom, 0);background:var(--loading-drop-item-background, transparent repeat-x 0 100px/150px 300px url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAEsCAYAAACG+vy+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAABLdJREFUeNrs299nXGkcx/FPMhVKSZUQSinLUEooJSxlWEIJvS1lydXeLqX/Qf+H3i5bpVQverVEo9XYUkqJhhJql2UJIeSq2ovzDacju82PTjKTeb04TjMTjTyZ9zznPOfMxPmHK4Ejmkpy9X+e30myNoq/2Bl/W/ZwKckPtc3V/kLr+Zn6nsN6U/t/k3xMsp5kK8nb1mMC4USdTXKl3vkvVwTdCqIz4J99bR/f045mvfbvKiCBMJAgekluJLlVQQyzbu2v9z3+d8XythXNukA47Dv1QkXRO4aZ4ThcrO1m67GtJC9rW07yWiD814unl2SxopgZk997uoLZjWa7FcxK7QUypmaS3KltznAkSc7VzLnQmmH+SPK49pv7/Y8mLPOOpE69Wy7VvmNIDmS5QnmUZEMgp2u2+LXCmDEc38WbCuX3WgAQyAjqVhg/p7kox2C8TPJbxbItkOE3n+RummVZjs92zSoPJpPcS7P6wfBYTPIiyStxnNhJ/lKSPyeT3E/yV5LnSX5JMmt8TsRU/VHeJ3ma5EdDcvImzj9c+bzH46tJntWx2IZhGviJ91KdYzjxHpFA2j4keZLmgstymjszOfpssVgn3QuxTDvSgbR9aoWyXDMN+3c9zQW92/n67liG1EGvpHfS3MrQq683K5LVNPe/rNYKAI3dGwQX01zQsxhyygPpdyFf3wOTNHdXrrSi+TBmY9pN8lMdOvUqEsbkEOswtiqatTRXLddq2zwF4zeV5lrFfJpVp3mHTmaQg5quF0//suU/Fcq71n4nzT3+wzozXOnb5ryEBDIos7X19nhuO82HYHY/fvmx/r3eOsdZy9FX1Dp9L/LdT9nN1vlCtwIXgkCGyrns72OZ/Ta+ceh2MS6EcgoCOazLtcF3MWkIQCAgEBAICAQEAgIBgYBAQCCAQEAgIBAQCAgEBAICAYGAQEAggEBAICAQEAgIBAQCAgGBgEAAgYBAQCAgEBAICAQEAgIBgYBAAIGAQEAgIBAQCAgEBAICAYEAAgGBgEBAICAQEAgIBAQCAgGBAAIBgYBAQCAgEBAICAQEAgIBBAICAYGAQEAgIBAQCAgEBAICAQQCAgGBgEBAICAQEAgIBAQCAjEEIBAQCAgEBAICAYGAQEAgIBBAICAQEAgIBAQCAgGBgEBAICAQQCAgEBAICAQEAgIBgYBAQCCAQEAgIBAQCAgEBAICAYGAQEAggEBAICAQEAgIBAQCAgGBgEAAgYBAQCAgEBAICAQEAgIBgYBAAIGAQEAgIBAQCAgEBAICAYEAAgGBgEBAICAQEAgIBAQCAgGBAAIBgYBAQCAgEBAICAQEAgIBgRgCEAgIBAQCAgGBgEBAICAQEAggEBAICAQEAgIBgYBAQCAgEBAIIBAQCAgEBAICAYGAQEAgIBBAICAQEAgIBAQCAgGBgEBAICAQQCAgEBAICAQEAgIBgYBAQCCAQEAgIBAQCAgEBAICAYGAQEAggEBAICAQEAgIBAQCAgGBgEAAgYBAQCAgEBAICAQEAgIBgYBAAIGAQEAgIBAQCAgEBAICAYGAQAwBCAQEAgIBgYBAQCAgEBAICAQQCAgEBAICAYGAQEAgIBAQCIy3LwMAZISJmhIzD54AAAAASUVORK5CYII=));z-index:var(--loading-drop-item-z-index, 2);animation:var(--loading-drop-item-animation, wave 1s ease-out forwards);animation-play-state:var(--loading-drop-item-animation-play-state, running)}.ran-loading .drop-item-bg{text-align:var(--loading-drop-item-text-align, center);line-height:var(--loading-drop-item-line-height, 120px);font-family:var(--loading-drop-item-font-family, sans-serif);color:var(--loading-drop-item-color, #ffffff);font-size:var(--loading-drop-item-font-size, 16px)}.ran-loading .drop-dot{position:var(--loading-drop-dot-position, absolute);top:var(--loading-drop-dot-top, 0);left:var(--loading-drop-dot-left, 0);bottom:var(--loading-drop-dot-bottom, 0);right:var(--loading-drop-dot-right, 0);z-index:var(--loading-drop-dot-z-index, 1);opacity:var(--loading-drop-dot-opacity, 0);animation:var(--loading-drop-dot-animation, fade-in .1s linear .4s forwards);animation-play-state:var(--loading-drop-dot-animation-play-state, running);filter:var(--loading-drop-dot-filter, url(data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSI+CiAgICA8ZGVmcz4KICAgICAgPGZpbHRlciBpZD0icmFuLWxvYWRpbmctZHJvcCI+CiAgICAgICAgPGZlR2F1c3NpYW5CbHVyIGluPSJTb3VyY2VHcmFwaGljIiBzdGREZXZpYXRpb249IjEwIiByZXN1bHQ9ImJsdXIiIC8+CiAgICAgICAgPGZlQ29sb3JNYXRyaXggaW49ImJsdXIiIG1vZGU9Im1hdHJpeCIgdmFsdWVzPSIxIDAgMCAwIDAgIDAgMSAwIDAgMCAgMCAwIDEgMCAwICAwIDAgMCAxOCAtNyIgcmVzdWx0PSJyYW4tbG9hZGluZy1kcm9wIiAvPgogICAgICA8L2ZpbHRlcj4KICAgIDwvZGVmcz4KICA8L3N2Zz4=#ran-loading-drop))}.ran-loading .drop-dot-1{position:var(--loading-drop-dot-1-position, absolute);left:var(--loading-drop-dot-1-left, 0);right:var(--loading-drop-dot-1-right, 0);bottom:var(--loading-drop-dot-1-bottom, 0);margin:var(--loading-drop-dot-1-margin, auto);background-color:var(--loading-drop-dot-1-background-color, #10a7c1);width:var(--loading-drop-dot-1-width, 90px);height:var(--loading-drop-dot-1-height, 16px);bottom:var(--loading-drop-dot-1-bottom, 2px);border-radius:var(--loading-drop-dot-1-border-radius, 0)}.ran-loading .drop-dot-2{width:var(--loading-drop-dot-2-width, 21px);height:var(--loading-drop-dot-2-height, 24px);border-radius:var(--loading-drop-dot-2-border-radius, 50%);position:var(--loading-drop-dot-2-position, absolute);left:var(--loading-drop-dot-2-left, 0);right:var(--loading-drop-dot-2-right, 0);bottom:var(--loading-drop-dot-2-bottom, 0);margin:var(--loading-drop-dot-2-margin, auto);background-color:var(--loading-drop-dot-2-background-color, #10a7c1);animation:var(--loading-drop-dot-2-animation, drop 1.3s cubic-bezier(1, .19, .66, .12) .5s infinite);animation-play-state:var(--loading-drop-dot-2-animation-play-state, running)}.ran-loading .pacman{position:var(--loading-pacman-position, relative)}@keyframes rotate_pacman_half_up{0%{transform:var(--loading-pacman-keyframes-0-transform, rotate(270deg))}50%{transform:var(--loading-pacman-keyframes-50-transform, rotate(360deg))}to{transform:var(--loading-pacman-keyframes-100-transform, rotate(270deg))}}@keyframes pacman-balls{75%{opacity:var(--loading-pacman-keyframes-balls-75-opacity, .7)}to{transform:var(--loading-pacman-keyframes-balls-100-transform, translate(-100px, -6.25px))}}@keyframes rotate_pacman_half_down{0%{transform:var(--loading-pacman-keyframes-balls-100-transform, rotate(90deg))}50%{transform:var(--loading-pacman-keyframes-balls-100-transform, rotate(0deg))}to{transform:var(--loading-pacman-keyframes-balls-100-transform, rotate(90deg))}}.ran-loading .pacman div:nth-child(2){width:var(--loading-pacman-div-nth-child-2-width, 0px);height:var(--loading-pacman-div-nth-child-2-height, 0px);border-right:var(--loading-pacman-div-nth-child-2-border-right, 25px solid transparent);border-top:var(--loading-pacman-div-nth-child-2-border-top, 25px solid #279fcf);border-left:var(--loading-pacman-div-nth-child-2-border-left, 25px solid #279fcf);border-bottom:var(--loading-pacman-div-nth-child-2-border-bottom, 25px solid #279fcf);border-radius:var(--loading-pacman-div-nth-child-2-border-radius, 25px);margin-top:var(--loading-pacman-div-nth-child-2-margin-top, -50px);animation:var(--loading-pacman-div-nth-child-2-animation, rotate_pacman_half_down .5s 0s infinite);animation-play-state:var(--loading-pacman-div-nth-child-2-animation-play-state, running)}.ran-loading .pacman div:nth-child(3){background-color:var(--loading-pacman-div-nth-child-3-background-color, #279fcf);border-radius:var(--loading-pacman-div-nth-child-3-border-radius, 100%);margin:var(--loading-pacman-div-nth-child-3-margin, 2px);width:var(--loading-pacman-div-nth-child-3-width, 10px);height:var(--loading-pacman-div-nth-child-3-height, 10px);position:var(--loading-pacman-div-nth-child-3-position, absolute);transform:var(--loading-pacman-div-nth-child-3-transform, translate(0, -6.25px));top:var(--loading-pacman-div-nth-child-3-top, 25px);left:var(--loading-pacman-div-nth-child-3-left, 100px);animation:var(--loading-pacman-div-nth-child-3-animation, pacman-balls 1s .33s infinite linear);animation-play-state:var(--loading-pacman-div-nth-child-3-animation-play-state, running)}.ran-loading .pacman div:nth-child(4){background-color:var(--loading-pacman-div-nth-child-4-background-color, #279fcf);border-radius:var(--loading-pacman-div-nth-child-4-border-radius, 100%);margin:var(--loading-pacman-div-nth-child-4-margin, 2px);width:var(--loading-pacman-div-nth-child-4-width, 10px);height:var(--loading-pacman-div-nth-child-4-height, 10px);position:var(--loading-pacman-div-nth-child-4-position, absolute);transform:var(--loading-pacman-div-nth-child-4-transform, translate(0, -6.25px));top:var(--loading-pacman-div-nth-child-4-top, 25px);left:var(--loading-pacman-div-nth-child-4-left, 100px);animation:var(--loading-pacman-div-nth-child-4-animation, pacman-balls 1s .66s infinite linear);animation-play-state:var(--loading-pacman-div-nth-child-4-animation-play-state, running)}.ran-loading .pacman div:nth-child(5){background-color:var(--loading-pacman-div-nth-child-5-background-color, #279fcf);border-radius:var(--loading-pacman-div-nth-child-5-border-radius, 100%);margin:var(--loading-pacman-div-nth-child-5-margin, 2px);width:var(--loading-pacman-div-nth-child-5-width, 10px);height:var(--loading-pacman-div-nth-child-5-height, 10px);position:var(--loading-pacman-div-nth-child-5-position, absolute);transform:var(--loading-pacman-div-nth-child-5-transform, translate(0, -6.25px));top:var(--loading-pacman-div-nth-child-5-top, 25px);left:var(--loading-pacman-div-nth-child-5-left, 100px);animation:var(--loading-pacman-div-nth-child-5-animation, pacman-balls 1s .99s infinite linear);animation-play-state:var(--loading-pacman-div-nth-child-5-animation-play-state, running)}.ran-loading .pacman div:first-of-type{width:var(--loading-pacman-div-first-of-type-width, 0px);height:var(--loading-pacman-div-first-of-type-height, 0px);border-right:var(--loading-pacman-div-first-of-type-border-right, 25px solid transparent);border-top:var(--loading-pacman-div-first-of-type-border-top, 25px solid #279fcf);border-left:var(--loading-pacman-div-first-of-type-border-left, 25px solid #279fcf);border-bottom:var(--loading-pacman-div-first-of-type-border-bottom, 25px solid #279fcf);border-radius:var(--loading-pacman-div-first-of-type-border-radius, 25px);animation:var(--loading-pacman-div-first-of-type-animation, rotate_pacman_half_up .5s 0s infinite);animation-play-state:var(--loading-pacman-div-first-of-type-animation-play-state, running)}';var $o=(k=>(k.DOUBLE_BOUNCE="double-bounce",k.ROTATE="rotate",k.STRETCH="stretch",k.CUBE="cube",k.DOT="dot",k.TRIPLE_BOUNCE="triple-bounce",k.SCALE_OUT="scale-out",k.CIRCLE="circle",k.CIRCLE_LINE="circle-line",k.SQUARE="square",k.PULSE="pulse",k.SOLAR="solar",k.CUBE_FOLD="cube-fold",k.CIRCLE_FOLD="circle-fold",k.CUBE_GRID="cube-grid",k.CIRCLE_TURN="circle-turn",k.CIRCLE_ROTATE="circle-rotate",k.CIRCLE_SPIN="circle-spin",k.DOT_BAR="dot-bar",k.DOT_CIRCLE="dot-circle",k.LINE="line",k.DOT_PULSE="dot-pulse",k.LINE_SCALE="line-scale",k.TEXT="text",k.CUBE_DIM="cube-dim",k.DOT_LINE="dot-line",k.ARC="arc",k.DROP="drop",k.PACMAN="pacman",k))($o||{});class wn extends Fe(){constructor(){super(),me(this,"contain"),me(this,"rotateLoading",()=>{const f=document.createElement("div");f.setAttribute("class","rotate"),f.setAttribute("part","rotate"),this.contain.appendChild(f)}),me(this,"stretchLoading",()=>{const f=document.createElement("div");f.setAttribute("class","stretch"),f.setAttribute("part","stretch"),Array(5).fill(1).forEach((w,x)=>{const T=document.createElement("div");T.setAttribute("class",`rect${x+1}`),f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"doubleBounceLoading",()=>{const f=document.createElement("div");f.setAttribute("class","double-bounce"),f.setAttribute("part","double-bounce"),Array(2).fill(1).forEach((w,x)=>{const T=document.createElement("div");T.setAttribute("class",`double-bounce${x+1}`),f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"cubeLoading",()=>{const f=document.createElement("div");f.setAttribute("class","cube"),f.setAttribute("part","cube"),Array(2).fill(1).forEach((w,x)=>{const T=document.createElement("div");T.setAttribute("class",`cube${x+1}`),f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"dotLoading",()=>{const f=document.createElement("div");f.setAttribute("class","dot"),f.setAttribute("part","dot"),Array(2).fill(1).forEach((w,x)=>{const T=document.createElement("div");T.setAttribute("class",`dot${x+1}`),f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"tripleBounceLoading",()=>{const f=document.createElement("div");f.setAttribute("class","triple-bounce"),f.setAttribute("part","triple-bounce"),Array(3).fill(1).forEach((w,x)=>{const T=document.createElement("div");T.setAttribute("class",`triple-bounce${x+1}`),f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"scaleOutLoading",()=>{const f=document.createElement("div");f.setAttribute("class","scale-out"),f.setAttribute("part","scale-out"),this.contain.appendChild(f)}),me(this,"circleLoading",()=>{const f=document.createElement("div");f.setAttribute("class","circle"),f.setAttribute("part","circle"),Array(3).fill(1).map(()=>new Array(4).fill(1)).forEach((w,x)=>{const T=document.createElement("div");T.setAttribute("class",`circle-container container${x+1}`),w.forEach((D,G)=>{const F=document.createElement("div");F.setAttribute("class",`circle${G+1}`),T.appendChild(F)}),f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"circleLineLoading",()=>{const{element:f}=z("div").setAttribute("class","circle-line-core"),{element:w}=z("div").setAttribute("class","circle-line-border").append(f),{element:x}=z("div").setAttribute("class","circle-line").setAttribute("part","circle-line").append(w);this.contain.appendChild(x)}),me(this,"squareLoading",()=>{const{element:f}=z("div").setAttribute("class","square-core"),{element:w}=z("div").setAttribute("class","square-box1").append(f),{element:x}=z("div").setAttribute("class","square-box2").append(f),{element:T}=z("div").setAttribute("class","square").setAttribute("part","square").append(w).append(x);this.contain.appendChild(T)}),me(this,"pulseLoading",()=>{const f=z("div").setAttribute("class","pulse").setAttribute("part","pulse");Array(3).fill(1).forEach((w,x)=>{const{element:T}=z("div").setAttribute("class",`pulse-bubble pulse-bubble-${x+1}`);f.append(T)}),this.contain.appendChild(f.element)}),me(this,"solarLoading",()=>{const{element:f}=z("div").setAttribute("class","sun").setAttribute("part","sun"),{element:w}=z("div").setAttribute("class","planet mercury"),{element:x}=z("div").setAttribute("class","mercury-orbit orbit").append(w).append(f),{element:T}=z("div").setAttribute("class","planet venus"),{element:D}=z("div").setAttribute("class","venus-orbit orbit").append(T).append(x),{element:G}=z("div").setAttribute("class","planet earth"),{element:F}=z("div").setAttribute("class","earth-orbit orbit").append(G).append(D),{element:q}=z("div").setAttribute("class","solar").setAttribute("part","solar").append(F);this.contain.appendChild(q)}),me(this,"cubeFoldLoading",()=>{const{element:f}=z("div").setAttribute("class","cube-fold").setAttribute("part","cube-fold");Array(4).fill(1).forEach((w,x)=>{const{element:T}=z("div").setAttribute("class",`cube-fold-item cube-fold-item-${x+1}`);f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"circleFoldLoading",()=>{const f=z("div").setAttribute("class","circle-fold").setAttribute("part","circle-fold");Array(12).fill(1).forEach((w,x)=>{const{element:T}=z("div").setAttribute("class",`circle-fold-item circle-fold-item-${x+1}`);f.append(T)}),this.contain.appendChild(f.element)}),me(this,"cubeGridLoading",()=>{const f=z("div").setAttribute("class","cube-grid").setAttribute("part","cube-grid");Array(9).fill(1).forEach((w,x)=>{const{element:T}=z("div").setAttribute("class",`cube-grid-item cube-grid-item-${x+1}`);f.append(T)}),this.contain.appendChild(f.element)}),me(this,"circleTurnLoading",()=>{const{element:f}=z("div").setAttribute("class","circle-turn").setAttribute("part","circle-turn");this.contain.appendChild(f)}),me(this,"circleRotateLoading",()=>{const{element:f}=z("div").setAttribute("class","circle-rotate").setAttribute("part","circle-rotate"),{element:w}=z("div").setAttribute("class","circle-rotate-inner"),{element:x}=z("div").setAttribute("class","circle-rotate-outer");f.appendChild(x),f.appendChild(w),this.contain.appendChild(f)}),me(this,"circleSpinLoading",()=>{const{element:f}=z("div").setAttribute("class","circle-spin").setAttribute("part","circle-spin"),{element:w}=z("div").setAttribute("class","circle-spin-inner"),{element:x}=z("div").setAttribute("class","circle-spin-outer");f.appendChild(x),f.appendChild(w),this.contain.appendChild(f)}),me(this,"dotBarLoading",()=>{const{element:f}=z("div").setAttribute("class","dot-bar").setAttribute("part","dot-bar");Array(5).fill(1).forEach((w,x)=>{const{element:T}=z("div").setAttribute("class",`dot-bar-item dot-bar-item-${x+1}`);f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"dotCircleLoading",()=>{const{element:f}=z("div").setAttribute("class","dot-circle").setAttribute("part","dot-circle");Array(5).fill(1).forEach((w,x)=>{const{element:T}=z("div").setAttribute("class",`dot-circle-item dot-circle-item-${x+1}`);f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"lineLoading",()=>{const{element:f}=z("div").setAttribute("class","line").setAttribute("part","line");Array(3).fill(1).forEach(()=>{const{element:w}=z("div").setAttribute("class","line-item");f.appendChild(w)}),this.contain.appendChild(f)}),me(this,"dotPulseLoading",()=>{const{element:f}=z("div").setAttribute("class","dot-pulse").setAttribute("class","dot-pulse");Array(5).fill(1).forEach((w,x)=>{const{element:T}=z("div").setAttribute("class","dot-pulse-item"),{element:D}=z("div").setAttribute("class",`dot-pulse-item-dot dot-pulse-item-dot-${x+1}`),{element:G}=z("div").setAttribute("class",`dot-pulse-item-ball dot-pulse-item-ball-${x+1}`);T.appendChild(D),T.appendChild(G),f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"lineScaleLoading",()=>{const{element:f}=z("div").setAttribute("class","line-scale").setAttribute("part","line-scale");Array(5).fill(1).forEach((w,x)=>{const{element:T}=z("div").setAttribute("class","line-scale-item");f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"textLoading",()=>{const{element:f}=z("div").setAttribute("class","text").setAttribute("part","text");["L","o","a","d","i","n","g"].forEach(x=>{const{element:T}=z("span").setAttribute("class","text-item").setTextContent(x);f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"cubeDimLoading",()=>{const{element:f}=z("div").setAttribute("class","cube-dim").setAttribute("part","cube-dim");Array(9).fill(1).forEach((w,x)=>{const{element:T}=z("div").setAttribute("class","cube-dim-item");f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"dotLineLoading",()=>{const{element:f}=z("div").setAttribute("class","dot-line").setAttribute("part","dot-line");Array(2).fill(1).forEach((w,x)=>{const{element:T}=z("div").setAttribute("class","dot-line-item"),{element:D}=z("div").setAttribute("class","dot-line-item-circle");T.appendChild(D),f.appendChild(T)}),this.contain.appendChild(f)}),me(this,"arcLoading",()=>{const{element:f}=z("div").setAttribute("class","arc-item"),{element:w}=z("div").setAttribute("class","arc").setAttribute("part","arc").append(f),{element:x}=z("span").setTextContent("LOADING"),{element:T}=z("h1").append(x);w.appendChild(T),this.contain.appendChild(w)}),me(this,"dropLoading",()=>{const{element:f}=z("span").setTextContent("LOADING"),{element:w}=z("div").setAttribute("class","drop-item-bg").append(f),{element:x}=z("div").setAttribute("class","drop-dot-1"),{element:T}=z("div").setAttribute("class","drop-dot-2"),{element:D}=z("div").setAttribute("class","drop-dot").append(x).append(T),{element:G}=z("div").setAttribute("class","drop-item").append(w).append(D),{element:F}=z("div").setAttribute("class","drop").setAttribute("part","drop").append(G).append(D);this.contain.appendChild(F)}),me(this,"pacmanLoading",()=>{const{element:f}=z("div").setAttribute("class","pacman").setAttribute("part","pacman");Array(5).fill(1).forEach(()=>{const{element:w}=z("div");f.append(w)}),this.contain.appendChild(f)}),me(this,"createLoading",()=>{this.contain.innerHTML="";const w={stretch:this.stretchLoading,rotate:this.rotateLoading,"double-bounce":this.doubleBounceLoading,cube:this.cubeLoading,dot:this.dotLoading,"triple-bounce":this.tripleBounceLoading,"scale-out":this.scaleOutLoading,circle:this.circleLoading,"circle-line":this.circleLineLoading,square:this.squareLoading,pulse:this.pulseLoading,solar:this.solarLoading,"cube-fold":this.cubeFoldLoading,"circle-fold":this.circleFoldLoading,"cube-grid":this.cubeGridLoading,"circle-turn":this.circleTurnLoading,"circle-rotate":this.circleRotateLoading,"circle-spin":this.circleSpinLoading,"dot-bar":this.dotBarLoading,"dot-circle":this.dotCircleLoading,line:this.lineLoading,"dot-pulse":this.dotPulseLoading,"line-scale":this.lineScaleLoading,text:this.textLoading,"cube-dim":this.cubeDimLoading,"dot-line":this.dotLineLoading,arc:this.arcLoading,drop:this.dropLoading,pacman:this.pacmanLoading}[this.name];w&&w()}),this.contain=document.createElement("div"),this.contain.setAttribute("class","ran-loading");const h=this.attachShadow({mode:"open"}),p=document.createElement("style");p.textContent=zh,h.appendChild(p),h.appendChild(this.contain)}static get observedAttributes(){return["name"]}get name(){const h=this.getAttribute("name")||"";return h||"circle"}set name(h){this.setAttribute("name",h||"")}connectedCallback(){this.createLoading()}disconnectCallback(){}attributeChangedCallback(h,p,f){p!==f&&h==="name"&&this.createLoading()}}function Yh(){return typeof document<"u"&&!customElements.get("r-loading")?(customElements.define("r-loading",wn),wn):Ie("document is undefined or r-loading is exist")}const jh=Yh(),qh=Object.freeze(Object.defineProperty({__proto__:null,Loading:wn,NAME_AMP:$o,default:jh},Symbol.toStringTag,{value:"Module"}));var $h=Object.defineProperty,Qh=(k,h,p)=>h in k?$h(k,h,{enumerable:!0,configurable:!0,writable:!0,value:p}):k[h]=p,Wh=(k,h,p)=>Qh(k,h+"",p);const Xh=".remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}:host{position:var(--ran-math-position, relative)}.ran-math{display:var(--ran-math-display, flex);justify-content:var(--ran-math-justify-content, space-around);align-items:var(--ran-math-align-items, center)}.katex-html{display:var(--ran-math-katex-display, none)}";class En extends Fe(){constructor(){super(),Wh(this,"contain"),this.contain=z("div").setAttribute("class","ran-math").element;const h=this.attachShadow({mode:"closed"}),p=document.createElement("style");p.textContent=Xh,h.appendChild(p),h.appendChild(this.contain)}static get observedAttributes(){return["latex"]}get latex(){const h=this.getAttribute("latex")||"";return decodeURIComponent(h)}set latex(h){this.setAttribute("latex",h||"")}render(){this.latex&&V(()=>import("./katex-es-DoRbtDCO.BDSjlQ-m.js"),[]).then(h=>{this.contain.innerHTML="";const p=z("span").setTextContent(`$$${this.latex}$$`).element;this.contain.appendChild(p),h&&h.renderMathInElement(this.contain)}).catch(function(h){console.warn(`ranui math component warning: ${h.message} +${h}`)})}connectedCallback(){this.render()}disconnectCallback(){}attributeChangedCallback(h,p,f){p!==f&&h==="latex"&&this.render()}}async function Jh(){return typeof document<"u"&&!customElements.get("r-math")?(customElements.define("r-math",En),En):Ie("document is undefined or r-math is exist")}const Zh=Jh(),eu=Object.freeze(Object.defineProperty({__proto__:null,Math:En,default:Zh},Symbol.toStringTag,{value:"Module"})),su=Object.freeze(Object.defineProperty({__proto__:null,button:bd,checkbox:ch,colorpicker:Hh,icon:Td,image:Pd,input:Ud,loading:qh,math:eu,message:Yd,modal:Xc,player:$c,popover:bh,preview:Zd,progress:nh,radar:Cc,select:Hc,skeleton:oc,tab:bc,tabpane:uc},Symbol.toStringTag,{value:"Module"}));export{su as i,ru as l,id as t}; diff --git a/assets/chunks/info-circle-COnL5bTJ.B9YJorcw.js b/assets/chunks/info-circle-COnL5bTJ.B9YJorcw.js new file mode 100644 index 0000000000..fc9dcfe365 --- /dev/null +++ b/assets/chunks/info-circle-COnL5bTJ.B9YJorcw.js @@ -0,0 +1,5 @@ +const t={success:!0,_identification:!0,data:` + + + +`};export{t as default}; diff --git a/assets/chunks/info-circle-fill-CFeVMdci.CUxFtRNn.js b/assets/chunks/info-circle-fill-CFeVMdci.CUxFtRNn.js new file mode 100644 index 0000000000..0081e08d68 --- /dev/null +++ b/assets/chunks/info-circle-fill-CFeVMdci.CUxFtRNn.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/input-input.MnARRJC6.js b/assets/chunks/input-input.MnARRJC6.js new file mode 100644 index 0000000000..51576e88c2 --- /dev/null +++ b/assets/chunks/input-input.MnARRJC6.js @@ -0,0 +1 @@ +const s="/ran/assets/input-input.1X1aE5oH.jpg";export{s as _}; diff --git a/assets/chunks/insert.Bde3uDH4.js b/assets/chunks/insert.Bde3uDH4.js new file mode 100644 index 0000000000..a97a9ded73 --- /dev/null +++ b/assets/chunks/insert.Bde3uDH4.js @@ -0,0 +1 @@ +const s="/ran/assets/insert.gf3GhDvq.gif";export{s as _}; diff --git a/assets/chunks/jszip.min-BIf20mgf.BsDI-Ugu.js b/assets/chunks/jszip.min-BIf20mgf.BsDI-Ugu.js new file mode 100644 index 0000000000..27fd176d82 --- /dev/null +++ b/assets/chunks/jszip.min-BIf20mgf.BsDI-Ugu.js @@ -0,0 +1,12 @@ +import{c as vt,a as yt,g as Ot}from"./commonjs-dynamic-modules-DLbDWi6a.CRNIONdy.js";function Bt(ct,wt){for(var _=0;_N[w]})}}}return Object.freeze(Object.defineProperty(ct,Symbol.toStringTag,{value:"Module"}))}var zt={exports:{}};/*! + +JSZip v3.10.1 - A JavaScript class for generating and reading zip files + + +(c) 2009-2016 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/main/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/main/LICENSE +*/(function(ct,wt){(function(_){ct.exports=_()})(function(){return function _(N,w,h){function o(g,y){if(!w[g]){if(!N[g]){var p=typeof yt=="function"&&yt;if(!y&&p)return p(g,!0);if(n)return n(g,!0);var b=new Error("Cannot find module '"+g+"'");throw b.code="MODULE_NOT_FOUND",b}var i=w[g]={exports:{}};N[g][0].call(i.exports,function(d){var r=N[g][1][d];return o(r||d)},i,i.exports,_,N,w,h)}return w[g].exports}for(var n=typeof yt=="function"&&yt,u=0;u>2,i=(3&g)<<4|y>>4,d=1>6:64,r=2>4,y=(15&b)<<4|(i=n.indexOf(u.charAt(r++)))>>2,p=(3&i)<<6|(d=n.indexOf(u.charAt(r++))),c[l++]=g,i!==64&&(c[l++]=y),d!==64&&(c[l++]=p);return c}},{"./support":30,"./utils":32}],2:[function(_,N,w){var h=_("./external"),o=_("./stream/DataWorker"),n=_("./stream/Crc32Probe"),u=_("./stream/DataLengthProbe");function g(y,p,b,i,d){this.compressedSize=y,this.uncompressedSize=p,this.crc32=b,this.compression=i,this.compressedContent=d}g.prototype={getContentWorker:function(){var y=new o(h.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new u("data_length")),p=this;return y.on("end",function(){if(this.streamInfo.data_length!==p.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")}),y},getCompressedWorker:function(){return new o(h.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},g.createWorkerFrom=function(y,p,b){return y.pipe(new n).pipe(new u("uncompressedSize")).pipe(p.compressWorker(b)).pipe(new u("compressedSize")).withStreamInfo("compression",p)},N.exports=g},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(_,N,w){var h=_("./stream/GenericWorker");w.STORE={magic:"\0\0",compressWorker:function(){return new h("STORE compression")},uncompressWorker:function(){return new h("STORE decompression")}},w.DEFLATE=_("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(_,N,w){var h=_("./utils"),o=function(){for(var n,u=[],g=0;g<256;g++){n=g;for(var y=0;y<8;y++)n=1&n?3988292384^n>>>1:n>>>1;u[g]=n}return u}();N.exports=function(n,u){return n!==void 0&&n.length?h.getTypeOf(n)!=="string"?function(g,y,p,b){var i=o,d=b+p;g^=-1;for(var r=b;r>>8^i[255&(g^y[r])];return-1^g}(0|u,n,n.length,0):function(g,y,p,b){var i=o,d=b+p;g^=-1;for(var r=b;r>>8^i[255&(g^y.charCodeAt(r))];return-1^g}(0|u,n,n.length,0):0}},{"./utils":32}],5:[function(_,N,w){w.base64=!1,w.binary=!1,w.dir=!1,w.createFolders=!0,w.date=null,w.compression=null,w.compressionOptions=null,w.comment=null,w.unixPermissions=null,w.dosPermissions=null},{}],6:[function(_,N,w){var h=null;h=typeof Promise<"u"?Promise:_("lie"),N.exports={Promise:h}},{lie:37}],7:[function(_,N,w){var h=typeof Uint8Array<"u"&&typeof Uint16Array<"u"&&typeof Uint32Array<"u",o=_("pako"),n=_("./utils"),u=_("./stream/GenericWorker"),g=h?"uint8array":"array";function y(p,b){u.call(this,"FlateWorker/"+p),this._pako=null,this._pakoAction=p,this._pakoOptions=b,this.meta={}}w.magic="\b\0",n.inherits(y,u),y.prototype.processChunk=function(p){this.meta=p.meta,this._pako===null&&this._createPako(),this._pako.push(n.transformTo(g,p.data),!1)},y.prototype.flush=function(){u.prototype.flush.call(this),this._pako===null&&this._createPako(),this._pako.push([],!0)},y.prototype.cleanUp=function(){u.prototype.cleanUp.call(this),this._pako=null},y.prototype._createPako=function(){this._pako=new o[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var p=this;this._pako.onData=function(b){p.push({data:b,meta:p.meta})}},w.compressWorker=function(p){return new y("Deflate",p)},w.uncompressWorker=function(){return new y("Inflate",{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(_,N,w){function h(i,d){var r,l="";for(r=0;r>>=8;return l}function o(i,d,r,l,a,c){var v,S,x=i.file,D=i.compression,O=c!==g.utf8encode,j=n.transformTo("string",c(x.name)),I=n.transformTo("string",g.utf8encode(x.name)),W=x.comment,V=n.transformTo("string",c(W)),m=n.transformTo("string",g.utf8encode(W)),B=I.length!==x.name.length,e=m.length!==W.length,T="",q="",P="",$=x.dir,L=x.date,J={crc32:0,compressedSize:0,uncompressedSize:0};d&&!r||(J.crc32=i.crc32,J.compressedSize=i.compressedSize,J.uncompressedSize=i.uncompressedSize);var E=0;d&&(E|=8),O||!B&&!e||(E|=2048);var C=0,X=0;$&&(C|=16),a==="UNIX"?(X=798,C|=function(H,nt){var ot=H;return H||(ot=nt?16893:33204),(65535&ot)<<16}(x.unixPermissions,$)):(X=20,C|=function(H){return 63&(H||0)}(x.dosPermissions)),v=L.getUTCHours(),v<<=6,v|=L.getUTCMinutes(),v<<=5,v|=L.getUTCSeconds()/2,S=L.getUTCFullYear()-1980,S<<=4,S|=L.getUTCMonth()+1,S<<=5,S|=L.getUTCDate(),B&&(q=h(1,1)+h(y(j),4)+I,T+="up"+h(q.length,2)+q),e&&(P=h(1,1)+h(y(V),4)+m,T+="uc"+h(P.length,2)+P);var G="";return G+=` +\0`,G+=h(E,2),G+=D.magic,G+=h(v,2),G+=h(S,2),G+=h(J.crc32,4),G+=h(J.compressedSize,4),G+=h(J.uncompressedSize,4),G+=h(j.length,2),G+=h(T.length,2),{fileRecord:p.LOCAL_FILE_HEADER+G+j+T,dirRecord:p.CENTRAL_FILE_HEADER+h(X,2)+G+h(V.length,2)+"\0\0\0\0"+h(C,4)+h(l,4)+j+T+V}}var n=_("../utils"),u=_("../stream/GenericWorker"),g=_("../utf8"),y=_("../crc32"),p=_("../signature");function b(i,d,r,l){u.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=d,this.zipPlatform=r,this.encodeFileName=l,this.streamFiles=i,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}n.inherits(b,u),b.prototype.push=function(i){var d=i.meta.percent||0,r=this.entriesCount,l=this._sources.length;this.accumulate?this.contentBuffer.push(i):(this.bytesWritten+=i.data.length,u.prototype.push.call(this,{data:i.data,meta:{currentFile:this.currentFile,percent:r?(d+100*(r-l-1))/r:100}}))},b.prototype.openedSource=function(i){this.currentSourceOffset=this.bytesWritten,this.currentFile=i.file.name;var d=this.streamFiles&&!i.file.dir;if(d){var r=o(i,d,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:r.fileRecord,meta:{percent:0}})}else this.accumulate=!0},b.prototype.closedSource=function(i){this.accumulate=!1;var d=this.streamFiles&&!i.file.dir,r=o(i,d,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(r.dirRecord),d)this.push({data:function(l){return p.DATA_DESCRIPTOR+h(l.crc32,4)+h(l.compressedSize,4)+h(l.uncompressedSize,4)}(i),meta:{percent:100}});else for(this.push({data:r.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},b.prototype.flush=function(){for(var i=this.bytesWritten,d=0;d=this.index;u--)g=(g<<8)+this.byteAt(u);return this.index+=n,g},readString:function(n){return h.transformTo("string",this.readData(n))},readData:function(){},lastIndexOfSignature:function(){},readAndCheckSignature:function(){},readDate:function(){var n=this.readInt(4);return new Date(Date.UTC(1980+(n>>25&127),(n>>21&15)-1,n>>16&31,n>>11&31,n>>5&63,(31&n)<<1))}},N.exports=o},{"../utils":32}],19:[function(_,N,w){var h=_("./Uint8ArrayReader");function o(n){h.call(this,n)}_("../utils").inherits(o,h),o.prototype.readData=function(n){this.checkOffset(n);var u=this.data.slice(this.zero+this.index,this.zero+this.index+n);return this.index+=n,u},N.exports=o},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(_,N,w){var h=_("./DataReader");function o(n){h.call(this,n)}_("../utils").inherits(o,h),o.prototype.byteAt=function(n){return this.data.charCodeAt(this.zero+n)},o.prototype.lastIndexOfSignature=function(n){return this.data.lastIndexOf(n)-this.zero},o.prototype.readAndCheckSignature=function(n){return n===this.readData(4)},o.prototype.readData=function(n){this.checkOffset(n);var u=this.data.slice(this.zero+this.index,this.zero+this.index+n);return this.index+=n,u},N.exports=o},{"../utils":32,"./DataReader":18}],21:[function(_,N,w){var h=_("./ArrayReader");function o(n){h.call(this,n)}_("../utils").inherits(o,h),o.prototype.readData=function(n){if(this.checkOffset(n),n===0)return new Uint8Array(0);var u=this.data.subarray(this.zero+this.index,this.zero+this.index+n);return this.index+=n,u},N.exports=o},{"../utils":32,"./ArrayReader":17}],22:[function(_,N,w){var h=_("../utils"),o=_("../support"),n=_("./ArrayReader"),u=_("./StringReader"),g=_("./NodeBufferReader"),y=_("./Uint8ArrayReader");N.exports=function(p){var b=h.getTypeOf(p);return h.checkSupport(b),b!=="string"||o.uint8array?b==="nodebuffer"?new g(p):o.uint8array?new y(h.transformTo("uint8array",p)):new n(h.transformTo("array",p)):new u(p)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(_,N,w){w.LOCAL_FILE_HEADER="PK",w.CENTRAL_FILE_HEADER="PK",w.CENTRAL_DIRECTORY_END="PK",w.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK\x07",w.ZIP64_CENTRAL_DIRECTORY_END="PK",w.DATA_DESCRIPTOR="PK\x07\b"},{}],24:[function(_,N,w){var h=_("./GenericWorker"),o=_("../utils");function n(u){h.call(this,"ConvertWorker to "+u),this.destType=u}o.inherits(n,h),n.prototype.processChunk=function(u){this.push({data:o.transformTo(this.destType,u.data),meta:u.meta})},N.exports=n},{"../utils":32,"./GenericWorker":28}],25:[function(_,N,w){var h=_("./GenericWorker"),o=_("../crc32");function n(){h.call(this,"Crc32Probe"),this.withStreamInfo("crc32",0)}_("../utils").inherits(n,h),n.prototype.processChunk=function(u){this.streamInfo.crc32=o(u.data,this.streamInfo.crc32||0),this.push(u)},N.exports=n},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(_,N,w){var h=_("../utils"),o=_("./GenericWorker");function n(u){o.call(this,"DataLengthProbe for "+u),this.propName=u,this.withStreamInfo(u,0)}h.inherits(n,o),n.prototype.processChunk=function(u){if(u){var g=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=g+u.data.length}o.prototype.processChunk.call(this,u)},N.exports=n},{"../utils":32,"./GenericWorker":28}],27:[function(_,N,w){var h=_("../utils"),o=_("./GenericWorker");function n(u){o.call(this,"DataWorker");var g=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,u.then(function(y){g.dataIsReady=!0,g.data=y,g.max=y&&y.length||0,g.type=h.getTypeOf(y),g.isPaused||g._tickAndRepeat()},function(y){g.error(y)})}h.inherits(n,o),n.prototype.cleanUp=function(){o.prototype.cleanUp.call(this),this.data=null},n.prototype.resume=function(){return!!o.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,h.delay(this._tickAndRepeat,[],this)),!0)},n.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(h.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},n.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var u=null,g=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case"string":u=this.data.substring(this.index,g);break;case"uint8array":u=this.data.subarray(this.index,g);break;case"array":case"nodebuffer":u=this.data.slice(this.index,g)}return this.index=g,this.push({data:u,meta:{percent:this.max?this.index/this.max*100:0}})},N.exports=n},{"../utils":32,"./GenericWorker":28}],28:[function(_,N,w){function h(o){this.name=o||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}h.prototype={push:function(o){this.emit("data",o)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch(o){this.emit("error",o)}return!0},error:function(o){return!this.isFinished&&(this.isPaused?this.generatedError=o:(this.isFinished=!0,this.emit("error",o),this.previous&&this.previous.error(o),this.cleanUp()),!0)},on:function(o,n){return this._listeners[o].push(n),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(o,n){if(this._listeners[o])for(var u=0;u "+o:o}},N.exports=h},{}],29:[function(_,N,w){var h=_("../utils"),o=_("./ConvertWorker"),n=_("./GenericWorker"),u=_("../base64"),g=_("../support"),y=_("../external"),p=null;if(g.nodestream)try{p=_("../nodejs/NodejsStreamOutputAdapter")}catch{}function b(d,r){return new y.Promise(function(l,a){var c=[],v=d._internalType,S=d._outputType,x=d._mimeType;d.on("data",function(D,O){c.push(D),r&&r(O)}).on("error",function(D){c=[],a(D)}).on("end",function(){try{var D=function(O,j,I){switch(O){case"blob":return h.newBlob(h.transformTo("arraybuffer",j),I);case"base64":return u.encode(j);default:return h.transformTo(O,j)}}(S,function(O,j){var I,W=0,V=null,m=0;for(I=0;I"u")w.blob=!1;else{var h=new ArrayBuffer(0);try{w.blob=new Blob([h],{type:"application/zip"}).size===0}catch{try{var o=new(self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder);o.append(h),w.blob=o.getBlob("application/zip").size===0}catch{w.blob=!1}}}try{w.nodestream=!!_("readable-stream").Readable}catch{w.nodestream=!1}},{"readable-stream":16}],31:[function(_,N,w){for(var h=_("./utils"),o=_("./support"),n=_("./nodejsUtils"),u=_("./stream/GenericWorker"),g=new Array(256),y=0;y<256;y++)g[y]=252<=y?6:248<=y?5:240<=y?4:224<=y?3:192<=y?2:1;g[254]=g[254]=1;function p(){u.call(this,"utf-8 decode"),this.leftOver=null}function b(){u.call(this,"utf-8 encode")}w.utf8encode=function(i){return o.nodebuffer?n.newBufferFrom(i,"utf-8"):function(d){var r,l,a,c,v,S=d.length,x=0;for(c=0;c>>6:(l<65536?r[v++]=224|l>>>12:(r[v++]=240|l>>>18,r[v++]=128|l>>>12&63),r[v++]=128|l>>>6&63),r[v++]=128|63&l);return r}(i)},w.utf8decode=function(i){return o.nodebuffer?h.transformTo("nodebuffer",i).toString("utf-8"):function(d){var r,l,a,c,v=d.length,S=new Array(2*v);for(r=l=0;r>10&1023,S[l++]=56320|1023&a)}return S.length!==l&&(S.subarray?S=S.subarray(0,l):S.length=l),h.applyFromCharCode(S)}(i=h.transformTo(o.uint8array?"uint8array":"array",i))},h.inherits(p,u),p.prototype.processChunk=function(i){var d=h.transformTo(o.uint8array?"uint8array":"array",i.data);if(this.leftOver&&this.leftOver.length){if(o.uint8array){var r=d;(d=new Uint8Array(r.length+this.leftOver.length)).set(this.leftOver,0),d.set(r,this.leftOver.length)}else d=this.leftOver.concat(d);this.leftOver=null}var l=function(c,v){var S;for((v=v||c.length)>c.length&&(v=c.length),S=v-1;0<=S&&(192&c[S])==128;)S--;return S<0||S===0?v:S+g[c[S]]>v?S:v}(d),a=d;l!==d.length&&(o.uint8array?(a=d.subarray(0,l),this.leftOver=d.subarray(l,d.length)):(a=d.slice(0,l),this.leftOver=d.slice(l,d.length))),this.push({data:w.utf8decode(a),meta:i.meta})},p.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:w.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},w.Utf8DecodeWorker=p,h.inherits(b,u),b.prototype.processChunk=function(i){this.push({data:w.utf8encode(i.data),meta:i.meta})},w.Utf8EncodeWorker=b},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(_,N,w){var h=_("./support"),o=_("./base64"),n=_("./nodejsUtils"),u=_("./external");function g(r){return r}function y(r,l){for(var a=0;a>8;this.dir=!!(16&this.externalFileAttributes),i==0&&(this.dosPermissions=63&this.externalFileAttributes),i==3&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||this.fileNameStr.slice(-1)!=="/"||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var i=h(this.extraFields[1].value);this.uncompressedSize===o.MAX_VALUE_32BITS&&(this.uncompressedSize=i.readInt(8)),this.compressedSize===o.MAX_VALUE_32BITS&&(this.compressedSize=i.readInt(8)),this.localHeaderOffset===o.MAX_VALUE_32BITS&&(this.localHeaderOffset=i.readInt(8)),this.diskNumberStart===o.MAX_VALUE_32BITS&&(this.diskNumberStart=i.readInt(4))}},readExtraFields:function(i){var d,r,l,a=i.index+this.extraFieldsLength;for(this.extraFields||(this.extraFields={});i.index+4>>6:(i<65536?b[l++]=224|i>>>12:(b[l++]=240|i>>>18,b[l++]=128|i>>>12&63),b[l++]=128|i>>>6&63),b[l++]=128|63&i);return b},w.buf2binstring=function(p){return y(p,p.length)},w.binstring2buf=function(p){for(var b=new h.Buf8(p.length),i=0,d=b.length;i>10&1023,c[d++]=56320|1023&r)}return y(c,d)},w.utf8border=function(p,b){var i;for((b=b||p.length)>p.length&&(b=p.length),i=b-1;0<=i&&(192&p[i])==128;)i--;return i<0||i===0?b:i+u[p[i]]>b?i:b}},{"./common":41}],43:[function(_,N,w){N.exports=function(h,o,n,u){for(var g=65535&h|0,y=h>>>16&65535|0,p=0;n!==0;){for(n-=p=2e3>>1:o>>>1;n[u]=o}return n}();N.exports=function(o,n,u,g){var y=h,p=g+u;o^=-1;for(var b=g;b>>8^y[255&(o^n[b])];return-1^o}},{}],46:[function(_,N,w){var h,o=_("../utils/common"),n=_("./trees"),u=_("./adler32"),g=_("./crc32"),y=_("./messages"),p=0,b=4,i=0,d=-2,r=-1,l=4,a=2,c=8,v=9,S=286,x=30,D=19,O=2*S+1,j=15,I=3,W=258,V=W+I+1,m=42,B=113,e=1,T=2,q=3,P=4;function $(t,R){return t.msg=y[R],R}function L(t){return(t<<1)-(4t.avail_out&&(A=t.avail_out),A!==0&&(o.arraySet(t.output,R.pending_buf,R.pending_out,A,t.next_out),t.next_out+=A,R.pending_out+=A,t.total_out+=A,t.avail_out-=A,R.pending-=A,R.pending===0&&(R.pending_out=0))}function C(t,R){n._tr_flush_block(t,0<=t.block_start?t.block_start:-1,t.strstart-t.block_start,R),t.block_start=t.strstart,E(t.strm)}function X(t,R){t.pending_buf[t.pending++]=R}function G(t,R){t.pending_buf[t.pending++]=R>>>8&255,t.pending_buf[t.pending++]=255&R}function H(t,R){var A,f,s=t.max_chain_length,k=t.strstart,F=t.prev_length,U=t.nice_match,z=t.strstart>t.w_size-V?t.strstart-(t.w_size-V):0,Z=t.window,K=t.w_mask,M=t.prev,Y=t.strstart+W,rt=Z[k+F-1],tt=Z[k+F];t.prev_length>=t.good_match&&(s>>=2),U>t.lookahead&&(U=t.lookahead);do if(Z[(A=R)+F]===tt&&Z[A+F-1]===rt&&Z[A]===Z[k]&&Z[++A]===Z[k+1]){k+=2,A++;do;while(Z[++k]===Z[++A]&&Z[++k]===Z[++A]&&Z[++k]===Z[++A]&&Z[++k]===Z[++A]&&Z[++k]===Z[++A]&&Z[++k]===Z[++A]&&Z[++k]===Z[++A]&&Z[++k]===Z[++A]&&kz&&--s!=0);return F<=t.lookahead?F:t.lookahead}function nt(t){var R,A,f,s,k,F,U,z,Z,K,M=t.w_size;do{if(s=t.window_size-t.lookahead-t.strstart,t.strstart>=M+(M-V)){for(o.arraySet(t.window,t.window,M,M,0),t.match_start-=M,t.strstart-=M,t.block_start-=M,R=A=t.hash_size;f=t.head[--R],t.head[R]=M<=f?f-M:0,--A;);for(R=A=M;f=t.prev[--R],t.prev[R]=M<=f?f-M:0,--A;);s+=M}if(t.strm.avail_in===0)break;if(F=t.strm,U=t.window,z=t.strstart+t.lookahead,Z=s,K=void 0,K=F.avail_in,Z=I)for(k=t.strstart-t.insert,t.ins_h=t.window[k],t.ins_h=(t.ins_h<=I&&(t.ins_h=(t.ins_h<=I)if(f=n._tr_tally(t,t.strstart-t.match_start,t.match_length-I),t.lookahead-=t.match_length,t.match_length<=t.max_lazy_match&&t.lookahead>=I){for(t.match_length--;t.strstart++,t.ins_h=(t.ins_h<=I&&(t.ins_h=(t.ins_h<=I&&t.match_length<=t.prev_length){for(s=t.strstart+t.lookahead-I,f=n._tr_tally(t,t.strstart-1-t.prev_match,t.prev_length-I),t.lookahead-=t.prev_length-1,t.prev_length-=2;++t.strstart<=s&&(t.ins_h=(t.ins_h<t.pending_buf_size-5&&(A=t.pending_buf_size-5);;){if(t.lookahead<=1){if(nt(t),t.lookahead===0&&R===p)return e;if(t.lookahead===0)break}t.strstart+=t.lookahead,t.lookahead=0;var f=t.block_start+A;if((t.strstart===0||t.strstart>=f)&&(t.lookahead=t.strstart-f,t.strstart=f,C(t,!1),t.strm.avail_out===0)||t.strstart-t.block_start>=t.w_size-V&&(C(t,!1),t.strm.avail_out===0))return e}return t.insert=0,R===b?(C(t,!0),t.strm.avail_out===0?q:P):(t.strstart>t.block_start&&(C(t,!1),t.strm.avail_out),e)}),new et(4,4,8,4,ot),new et(4,5,16,8,ot),new et(4,6,32,32,ot),new et(4,4,16,16,Q),new et(8,16,32,32,Q),new et(8,16,128,128,Q),new et(8,32,128,256,Q),new et(32,128,258,1024,Q),new et(32,258,258,4096,Q)],w.deflateInit=function(t,R){return ut(t,R,c,15,8,0)},w.deflateInit2=ut,w.deflateReset=lt,w.deflateResetKeep=it,w.deflateSetHeader=function(t,R){return t&&t.state?t.state.wrap!==2?d:(t.state.gzhead=R,i):d},w.deflate=function(t,R){var A,f,s,k;if(!t||!t.state||5>8&255),X(f,f.gzhead.time>>16&255),X(f,f.gzhead.time>>24&255),X(f,f.level===9?2:2<=f.strategy||f.level<2?4:0),X(f,255&f.gzhead.os),f.gzhead.extra&&f.gzhead.extra.length&&(X(f,255&f.gzhead.extra.length),X(f,f.gzhead.extra.length>>8&255)),f.gzhead.hcrc&&(t.adler=g(t.adler,f.pending_buf,f.pending,0)),f.gzindex=0,f.status=69):(X(f,0),X(f,0),X(f,0),X(f,0),X(f,0),X(f,f.level===9?2:2<=f.strategy||f.level<2?4:0),X(f,3),f.status=B);else{var F=c+(f.w_bits-8<<4)<<8;F|=(2<=f.strategy||f.level<2?0:f.level<6?1:f.level===6?2:3)<<6,f.strstart!==0&&(F|=32),F+=31-F%31,f.status=B,G(f,F),f.strstart!==0&&(G(f,t.adler>>>16),G(f,65535&t.adler)),t.adler=1}if(f.status===69)if(f.gzhead.extra){for(s=f.pending;f.gzindex<(65535&f.gzhead.extra.length)&&(f.pending!==f.pending_buf_size||(f.gzhead.hcrc&&f.pending>s&&(t.adler=g(t.adler,f.pending_buf,f.pending-s,s)),E(t),s=f.pending,f.pending!==f.pending_buf_size));)X(f,255&f.gzhead.extra[f.gzindex]),f.gzindex++;f.gzhead.hcrc&&f.pending>s&&(t.adler=g(t.adler,f.pending_buf,f.pending-s,s)),f.gzindex===f.gzhead.extra.length&&(f.gzindex=0,f.status=73)}else f.status=73;if(f.status===73)if(f.gzhead.name){s=f.pending;do{if(f.pending===f.pending_buf_size&&(f.gzhead.hcrc&&f.pending>s&&(t.adler=g(t.adler,f.pending_buf,f.pending-s,s)),E(t),s=f.pending,f.pending===f.pending_buf_size)){k=1;break}k=f.gzindexs&&(t.adler=g(t.adler,f.pending_buf,f.pending-s,s)),k===0&&(f.gzindex=0,f.status=91)}else f.status=91;if(f.status===91)if(f.gzhead.comment){s=f.pending;do{if(f.pending===f.pending_buf_size&&(f.gzhead.hcrc&&f.pending>s&&(t.adler=g(t.adler,f.pending_buf,f.pending-s,s)),E(t),s=f.pending,f.pending===f.pending_buf_size)){k=1;break}k=f.gzindexs&&(t.adler=g(t.adler,f.pending_buf,f.pending-s,s)),k===0&&(f.status=103)}else f.status=103;if(f.status===103&&(f.gzhead.hcrc?(f.pending+2>f.pending_buf_size&&E(t),f.pending+2<=f.pending_buf_size&&(X(f,255&t.adler),X(f,t.adler>>8&255),t.adler=0,f.status=B)):f.status=B),f.pending!==0){if(E(t),t.avail_out===0)return f.last_flush=-1,i}else if(t.avail_in===0&&L(R)<=L(A)&&R!==b)return $(t,-5);if(f.status===666&&t.avail_in!==0)return $(t,-5);if(t.avail_in!==0||f.lookahead!==0||R!==p&&f.status!==666){var U=f.strategy===2?function(z,Z){for(var K;;){if(z.lookahead===0&&(nt(z),z.lookahead===0)){if(Z===p)return e;break}if(z.match_length=0,K=n._tr_tally(z,0,z.window[z.strstart]),z.lookahead--,z.strstart++,K&&(C(z,!1),z.strm.avail_out===0))return e}return z.insert=0,Z===b?(C(z,!0),z.strm.avail_out===0?q:P):z.last_lit&&(C(z,!1),z.strm.avail_out===0)?e:T}(f,R):f.strategy===3?function(z,Z){for(var K,M,Y,rt,tt=z.window;;){if(z.lookahead<=W){if(nt(z),z.lookahead<=W&&Z===p)return e;if(z.lookahead===0)break}if(z.match_length=0,z.lookahead>=I&&0z.lookahead&&(z.match_length=z.lookahead)}if(z.match_length>=I?(K=n._tr_tally(z,1,z.match_length-I),z.lookahead-=z.match_length,z.strstart+=z.match_length,z.match_length=0):(K=n._tr_tally(z,0,z.window[z.strstart]),z.lookahead--,z.strstart++),K&&(C(z,!1),z.strm.avail_out===0))return e}return z.insert=0,Z===b?(C(z,!0),z.strm.avail_out===0?q:P):z.last_lit&&(C(z,!1),z.strm.avail_out===0)?e:T}(f,R):h[f.level].func(f,R);if(U!==q&&U!==P||(f.status=666),U===e||U===q)return t.avail_out===0&&(f.last_flush=-1),i;if(U===T&&(R===1?n._tr_align(f):R!==5&&(n._tr_stored_block(f,0,0,!1),R===3&&(J(f.head),f.lookahead===0&&(f.strstart=0,f.block_start=0,f.insert=0))),E(t),t.avail_out===0))return f.last_flush=-1,i}return R!==b?i:f.wrap<=0?1:(f.wrap===2?(X(f,255&t.adler),X(f,t.adler>>8&255),X(f,t.adler>>16&255),X(f,t.adler>>24&255),X(f,255&t.total_in),X(f,t.total_in>>8&255),X(f,t.total_in>>16&255),X(f,t.total_in>>24&255)):(G(f,t.adler>>>16),G(f,65535&t.adler)),E(t),0=A.w_size&&(k===0&&(J(A.head),A.strstart=0,A.block_start=0,A.insert=0),Z=new o.Buf8(A.w_size),o.arraySet(Z,R,K-A.w_size,A.w_size,0),R=Z,K=A.w_size),F=t.avail_in,U=t.next_in,z=t.input,t.avail_in=K,t.next_in=0,t.input=R,nt(A);A.lookahead>=I;){for(f=A.strstart,s=A.lookahead-(I-1);A.ins_h=(A.ins_h<>>=I=j>>>24,v-=I,(I=j>>>16&255)===0)T[y++]=65535&j;else{if(!(16&I)){if(!(64&I)){j=S[(65535&j)+(c&(1<>>=I,v-=I),v<15&&(c+=e[u++]<>>=I=j>>>24,v-=I,!(16&(I=j>>>16&255))){if(!(64&I)){j=x[(65535&j)+(c&(1<>>=I,v-=I,(I=y-p)>3,c&=(1<<(v-=W<<3))-1,h.next_in=u,h.next_out=y,h.avail_in=u>>24&255)+(m>>>8&65280)+((65280&m)<<8)+((255&m)<<24)}function c(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new h.Buf16(320),this.work=new h.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function v(m){var B;return m&&m.state?(B=m.state,m.total_in=m.total_out=B.total=0,m.msg="",B.wrap&&(m.adler=1&B.wrap),B.mode=d,B.last=0,B.havedict=0,B.dmax=32768,B.head=null,B.hold=0,B.bits=0,B.lencode=B.lendyn=new h.Buf32(r),B.distcode=B.distdyn=new h.Buf32(l),B.sane=1,B.back=-1,b):i}function S(m){var B;return m&&m.state?((B=m.state).wsize=0,B.whave=0,B.wnext=0,v(m)):i}function x(m,B){var e,T;return m&&m.state?(T=m.state,B<0?(e=0,B=-B):(e=1+(B>>4),B<48&&(B&=15)),B&&(B<8||15=P.wsize?(h.arraySet(P.window,B,e-P.wsize,P.wsize,0),P.wnext=0,P.whave=P.wsize):(T<(q=P.wsize-P.wnext)&&(q=T),h.arraySet(P.window,B,e-T,q,P.wnext),(T-=q)?(h.arraySet(P.window,B,e-T,T,0),P.wnext=T,P.whave=P.wsize):(P.wnext+=q,P.wnext===P.wsize&&(P.wnext=0),P.whave>>8&255,e.check=n(e.check,k,2,0),C=E=0,e.mode=2;break}if(e.flags=0,e.head&&(e.head.done=!1),!(1&e.wrap)||(((255&E)<<8)+(E>>8))%31){m.msg="incorrect header check",e.mode=30;break}if((15&E)!=8){m.msg="unknown compression method",e.mode=30;break}if(C-=4,t=8+(15&(E>>>=4)),e.wbits===0)e.wbits=t;else if(t>e.wbits){m.msg="invalid window size",e.mode=30;break}e.dmax=1<>8&1),512&e.flags&&(k[0]=255&E,k[1]=E>>>8&255,e.check=n(e.check,k,2,0)),C=E=0,e.mode=3;case 3:for(;C<32;){if(L===0)break t;L--,E+=T[P++]<>>8&255,k[2]=E>>>16&255,k[3]=E>>>24&255,e.check=n(e.check,k,4,0)),C=E=0,e.mode=4;case 4:for(;C<16;){if(L===0)break t;L--,E+=T[P++]<>8),512&e.flags&&(k[0]=255&E,k[1]=E>>>8&255,e.check=n(e.check,k,2,0)),C=E=0,e.mode=5;case 5:if(1024&e.flags){for(;C<16;){if(L===0)break t;L--,E+=T[P++]<>>8&255,e.check=n(e.check,k,2,0)),C=E=0}else e.head&&(e.head.extra=null);e.mode=6;case 6:if(1024&e.flags&&(L<(H=e.length)&&(H=L),H&&(e.head&&(t=e.head.extra_len-e.length,e.head.extra||(e.head.extra=new Array(e.head.extra_len)),h.arraySet(e.head.extra,T,P,H,t)),512&e.flags&&(e.check=n(e.check,T,H,P)),L-=H,P+=H,e.length-=H),e.length))break t;e.length=0,e.mode=7;case 7:if(2048&e.flags){if(L===0)break t;for(H=0;t=T[P+H++],e.head&&t&&e.length<65536&&(e.head.name+=String.fromCharCode(t)),t&&H>9&1,e.head.done=!0),m.adler=e.check=0,e.mode=12;break;case 10:for(;C<32;){if(L===0)break t;L--,E+=T[P++]<>>=7&C,C-=7&C,e.mode=27;break}for(;C<3;){if(L===0)break t;L--,E+=T[P++]<>>=1)){case 0:e.mode=14;break;case 1:if(W(e),e.mode=20,B!==6)break;E>>>=2,C-=2;break t;case 2:e.mode=17;break;case 3:m.msg="invalid block type",e.mode=30}E>>>=2,C-=2;break;case 14:for(E>>>=7&C,C-=7&C;C<32;){if(L===0)break t;L--,E+=T[P++]<>>16^65535)){m.msg="invalid stored block lengths",e.mode=30;break}if(e.length=65535&E,C=E=0,e.mode=15,B===6)break t;case 15:e.mode=16;case 16:if(H=e.length){if(L>>=5,C-=5,e.ndist=1+(31&E),E>>>=5,C-=5,e.ncode=4+(15&E),E>>>=4,C-=4,286>>=3,C-=3}for(;e.have<19;)e.lens[F[e.have++]]=0;if(e.lencode=e.lendyn,e.lenbits=7,A={bits:e.lenbits},R=g(0,e.lens,0,19,e.lencode,0,e.work,A),e.lenbits=A.bits,R){m.msg="invalid code lengths set",e.mode=30;break}e.have=0,e.mode=19;case 19:for(;e.have>>16&255,st=65535&s,!((Q=s>>>24)<=C);){if(L===0)break t;L--,E+=T[P++]<>>=Q,C-=Q,e.lens[e.have++]=st;else{if(st===16){for(f=Q+2;C>>=Q,C-=Q,e.have===0){m.msg="invalid bit length repeat",e.mode=30;break}t=e.lens[e.have-1],H=3+(3&E),E>>>=2,C-=2}else if(st===17){for(f=Q+3;C>>=Q)),E>>>=3,C-=3}else{for(f=Q+7;C>>=Q)),E>>>=7,C-=7}if(e.have+H>e.nlen+e.ndist){m.msg="invalid bit length repeat",e.mode=30;break}for(;H--;)e.lens[e.have++]=t}}if(e.mode===30)break;if(e.lens[256]===0){m.msg="invalid code -- missing end-of-block",e.mode=30;break}if(e.lenbits=9,A={bits:e.lenbits},R=g(y,e.lens,0,e.nlen,e.lencode,0,e.work,A),e.lenbits=A.bits,R){m.msg="invalid literal/lengths set",e.mode=30;break}if(e.distbits=6,e.distcode=e.distdyn,A={bits:e.distbits},R=g(p,e.lens,e.nlen,e.ndist,e.distcode,0,e.work,A),e.distbits=A.bits,R){m.msg="invalid distances set",e.mode=30;break}if(e.mode=20,B===6)break t;case 20:e.mode=21;case 21:if(6<=L&&258<=J){m.next_out=$,m.avail_out=J,m.next_in=P,m.avail_in=L,e.hold=E,e.bits=C,u(m,G),$=m.next_out,q=m.output,J=m.avail_out,P=m.next_in,T=m.input,L=m.avail_in,E=e.hold,C=e.bits,e.mode===12&&(e.back=-1);break}for(e.back=0;et=(s=e.lencode[E&(1<>>16&255,st=65535&s,!((Q=s>>>24)<=C);){if(L===0)break t;L--,E+=T[P++]<>it)])>>>16&255,st=65535&s,!(it+(Q=s>>>24)<=C);){if(L===0)break t;L--,E+=T[P++]<>>=it,C-=it,e.back+=it}if(E>>>=Q,C-=Q,e.back+=Q,e.length=st,et===0){e.mode=26;break}if(32&et){e.back=-1,e.mode=12;break}if(64&et){m.msg="invalid literal/length code",e.mode=30;break}e.extra=15&et,e.mode=22;case 22:if(e.extra){for(f=e.extra;C>>=e.extra,C-=e.extra,e.back+=e.extra}e.was=e.length,e.mode=23;case 23:for(;et=(s=e.distcode[E&(1<>>16&255,st=65535&s,!((Q=s>>>24)<=C);){if(L===0)break t;L--,E+=T[P++]<>it)])>>>16&255,st=65535&s,!(it+(Q=s>>>24)<=C);){if(L===0)break t;L--,E+=T[P++]<>>=it,C-=it,e.back+=it}if(E>>>=Q,C-=Q,e.back+=Q,64&et){m.msg="invalid distance code",e.mode=30;break}e.offset=st,e.extra=15&et,e.mode=24;case 24:if(e.extra){for(f=e.extra;C>>=e.extra,C-=e.extra,e.back+=e.extra}if(e.offset>e.dmax){m.msg="invalid distance too far back",e.mode=30;break}e.mode=25;case 25:if(J===0)break t;if(H=G-J,e.offset>H){if((H=e.offset-H)>e.whave&&e.sane){m.msg="invalid distance too far back",e.mode=30;break}nt=H>e.wnext?(H-=e.wnext,e.wsize-H):e.wnext-H,H>e.length&&(H=e.length),ot=e.window}else ot=q,nt=$-e.offset,H=e.length;for(JO?(I=nt[ot+l[B]],C[X+l[B]]):(I=96,0),c=1<>$)+(v-=c)]=j<<24|I<<16|W|0,v!==0;);for(c=1<>=1;if(c!==0?(E&=c-1,E+=c):E=0,B++,--G[m]==0){if(m===T)break;m=p[b+l[B]]}if(q>>7)]}function X(s,k){s.pending_buf[s.pending++]=255&k,s.pending_buf[s.pending++]=k>>>8&255}function G(s,k,F){s.bi_valid>a-F?(s.bi_buf|=k<>a-s.bi_valid,s.bi_valid+=F-a):(s.bi_buf|=k<>>=1,F<<=1,0<--k;);return F>>>1}function ot(s,k,F){var U,z,Z=new Array(l+1),K=0;for(U=1;U<=l;U++)Z[U]=K=K+F[U-1]<<1;for(z=0;z<=k;z++){var M=s[2*z+1];M!==0&&(s[2*z]=nt(Z[M]++,M))}}function Q(s){var k;for(k=0;k>1;1<=F;F--)it(s,Z,F);for(z=Y;F=s.heap[1],s.heap[1]=s.heap[s.heap_len--],it(s,Z,1),U=s.heap[1],s.heap[--s.heap_max]=F,s.heap[--s.heap_max]=U,Z[2*z]=Z[2*F]+Z[2*U],s.depth[z]=(s.depth[F]>=s.depth[U]?s.depth[F]:s.depth[U])+1,Z[2*F+1]=Z[2*U+1]=z,s.heap[1]=z++,it(s,Z,1),2<=s.heap_len;);s.heap[--s.heap_max]=s.heap[1],function(tt,ht){var pt,ft,mt,at,gt,kt,dt=ht.dyn_tree,xt=ht.max_code,Et=ht.stat_desc.static_tree,At=ht.stat_desc.has_stree,It=ht.stat_desc.extra_bits,St=ht.stat_desc.extra_base,_t=ht.stat_desc.max_length,bt=0;for(at=0;at<=l;at++)tt.bl_count[at]=0;for(dt[2*tt.heap[tt.heap_max]+1]=0,pt=tt.heap_max+1;pt>=7;z>>=1)if(1&rt&&M.dyn_ltree[2*Y]!==0)return o;if(M.dyn_ltree[18]!==0||M.dyn_ltree[20]!==0||M.dyn_ltree[26]!==0)return n;for(Y=32;Y>>3,(Z=s.static_len+3+7>>>3)<=z&&(z=Z)):z=Z=F+5,F+4<=z&&k!==-1?f(s,k,F,U):s.strategy===4||Z===z?(G(s,2+(U?1:0),3),lt(s,V,m)):(G(s,4+(U?1:0),3),function(M,Y,rt,tt){var ht;for(G(M,Y-257,5),G(M,rt-1,5),G(M,tt-4,4),ht=0;ht>>8&255,s.pending_buf[s.d_buf+2*s.last_lit+1]=255&k,s.pending_buf[s.l_buf+s.last_lit]=255&F,s.last_lit++,k===0?s.dyn_ltree[2*F]++:(s.matches++,k--,s.dyn_ltree[2*(e[F]+p+1)]++,s.dyn_dtree[2*C(k)]++),s.last_lit===s.lit_bufsize-1},w._tr_align=function(s){G(s,2,3),H(s,v,V),function(k){k.bi_valid===16?(X(k,k.bi_buf),k.bi_buf=0,k.bi_valid=0):8<=k.bi_valid&&(k.pending_buf[k.pending++]=255&k.bi_buf,k.bi_buf>>=8,k.bi_valid-=8)}(s)}},{"../utils/common":41}],53:[function(_,N,w){N.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(_,N,w){(function(h){(function(o,n){if(!o.setImmediate){var u,g,y,p,b=1,i={},d=!1,r=o.document,l=Object.getPrototypeOf&&Object.getPrototypeOf(o);l=l&&l.setTimeout?l:o,u={}.toString.call(o.process)==="[object process]"?function(S){process.nextTick(function(){c(S)})}:function(){if(o.postMessage&&!o.importScripts){var S=!0,x=o.onmessage;return o.onmessage=function(){S=!1},o.postMessage("","*"),o.onmessage=x,S}}()?(p="setImmediate$"+Math.random()+"$",o.addEventListener?o.addEventListener("message",v,!1):o.attachEvent("onmessage",v),function(S){o.postMessage(p+S,"*")}):o.MessageChannel?((y=new MessageChannel).port1.onmessage=function(S){c(S.data)},function(S){y.port2.postMessage(S)}):r&&"onreadystatechange"in r.createElement("script")?(g=r.documentElement,function(S){var x=r.createElement("script");x.onreadystatechange=function(){c(S),x.onreadystatechange=null,g.removeChild(x),x=null},g.appendChild(x)}):function(S){setTimeout(c,0,S)},l.setImmediate=function(S){typeof S!="function"&&(S=new Function(""+S));for(var x=new Array(arguments.length-1),D=0;D"u"?h===void 0?this:h:self)}).call(this,typeof vt<"u"?vt:typeof self<"u"?self:typeof window<"u"?window:{})},{}]},{},[10])(10)})})(zt);var Ct=zt.exports;const Rt=Ot(Ct),Dt=Bt({__proto__:null,default:Rt},[Ct]);export{Rt as J,Dt as j}; diff --git a/assets/chunks/katex-es-DoRbtDCO.BDSjlQ-m.js b/assets/chunks/katex-es-DoRbtDCO.BDSjlQ-m.js new file mode 100644 index 0000000000..089827989e --- /dev/null +++ b/assets/chunks/katex-es-DoRbtDCO.BDSjlQ-m.js @@ -0,0 +1,261 @@ +class h0{constructor(e,t,a){this.lexer=void 0,this.start=void 0,this.end=void 0,this.lexer=e,this.start=t,this.end=a}static range(e,t){return t?!e||!e.loc||!t.loc||e.loc.lexer!==t.loc.lexer?null:new h0(e.loc.lexer,e.loc.start,t.loc.end):e&&e.loc}}class f0{constructor(e,t){this.text=void 0,this.loc=void 0,this.noexpand=void 0,this.treatAsRelax=void 0,this.text=e,this.loc=t}range(e,t){return new f0(t,h0.range(this,e))}}class M{constructor(e,t){this.name=void 0,this.position=void 0,this.length=void 0,this.rawMessage=void 0;var a="KaTeX parse error: "+e,n,s,o=t&&t.loc;if(o&&o.start<=o.end){var m=o.lexer.input;n=o.start,s=o.end,n===m.length?a+=" at end of input: ":a+=" at position "+(n+1)+": ";var c=m.slice(n,s).replace(/[^]/g,"$&̲"),p;n>15?p="…"+m.slice(n-15,n):p=m.slice(0,n);var g;s+15":">","<":"<",'"':""","'":"'"},ya=/[&><"']/g;function wa(r){return String(r).replace(ya,e=>ba[e])}var vr=function r(e){return e.type==="ordgroup"||e.type==="color"?e.body.length===1?r(e.body[0]):e:e.type==="font"?r(e.body):e},xa=function(e){var t=vr(e);return t.type==="mathord"||t.type==="textord"||t.type==="atom"},ka=function(e){if(!e)throw new Error("Expected non-null, but got "+String(e));return e},Sa=function(e){var t=/^[\x00-\x20]*([^\\/#?]*?)(:|�*58|�*3a|&colon)/i.exec(e);return t?t[2]!==":"||!/^[a-zA-Z][a-zA-Z0-9+\-.]*$/.test(t[1])?null:t[1].toLowerCase():"_relative"},R={contains:fa,deflt:pa,escape:wa,hyphenate:ga,getBaseElem:vr,isCharacterBox:xa,protocolFromUrl:Sa},ze={displayMode:{type:"boolean",description:"Render math in display mode, which puts the math in display style (so \\int and \\sum are large, for example), and centers the math on the page on its own line.",cli:"-d, --display-mode"},output:{type:{enum:["htmlAndMathml","html","mathml"]},description:"Determines the markup language of the output.",cli:"-F, --format "},leqno:{type:"boolean",description:"Render display math in leqno style (left-justified tags)."},fleqn:{type:"boolean",description:"Render display math flush left."},throwOnError:{type:"boolean",default:!0,cli:"-t, --no-throw-on-error",cliDescription:"Render errors (in the color given by --error-color) instead of throwing a ParseError exception when encountering an error."},errorColor:{type:"string",default:"#cc0000",cli:"-c, --error-color ",cliDescription:"A color string given in the format 'rgb' or 'rrggbb' (no #). This option determines the color of errors rendered by the -t option.",cliProcessor:r=>"#"+r},macros:{type:"object",cli:"-m, --macro ",cliDescription:"Define custom macro of the form '\\foo:expansion' (use multiple -m arguments for multiple macros).",cliDefault:[],cliProcessor:(r,e)=>(e.push(r),e)},minRuleThickness:{type:"number",description:"Specifies a minimum thickness, in ems, for fraction lines, `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, `\\hdashline`, `\\underline`, `\\overline`, and the borders of `\\fbox`, `\\boxed`, and `\\fcolorbox`.",processor:r=>Math.max(0,r),cli:"--min-rule-thickness ",cliProcessor:parseFloat},colorIsTextColor:{type:"boolean",description:"Makes \\color behave like LaTeX's 2-argument \\textcolor, instead of LaTeX's one-argument \\color mode change.",cli:"-b, --color-is-text-color"},strict:{type:[{enum:["warn","ignore","error"]},"boolean","function"],description:"Turn on strict / LaTeX faithfulness mode, which throws an error if the input uses features that are not supported by LaTeX.",cli:"-S, --strict",cliDefault:!1},trust:{type:["boolean","function"],description:"Trust the input, enabling all HTML features such as \\url.",cli:"-T, --trust"},maxSize:{type:"number",default:1/0,description:"If non-zero, all user-specified sizes, e.g. in \\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, elements and spaces can be arbitrarily large",processor:r=>Math.max(0,r),cli:"-s, --max-size ",cliProcessor:parseInt},maxExpand:{type:"number",default:1e3,description:"Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to Infinity, the macro expander will try to fully expand as in LaTeX.",processor:r=>Math.max(0,r),cli:"-e, --max-expand ",cliProcessor:r=>r==="Infinity"?1/0:parseInt(r)},globalGroup:{type:"boolean",cli:!1}};function Ma(r){if(r.default)return r.default;var e=r.type,t=Array.isArray(e)?e[0]:e;if(typeof t!="string")return t.enum[0];switch(t){case"boolean":return!1;case"string":return"";case"number":return 0;case"object":return{}}}class ct{constructor(e){this.displayMode=void 0,this.output=void 0,this.leqno=void 0,this.fleqn=void 0,this.throwOnError=void 0,this.errorColor=void 0,this.macros=void 0,this.minRuleThickness=void 0,this.colorIsTextColor=void 0,this.strict=void 0,this.trust=void 0,this.maxSize=void 0,this.maxExpand=void 0,this.globalGroup=void 0,e=e||{};for(var t in ze)if(ze.hasOwnProperty(t)){var a=ze[t];this[t]=e[t]!==void 0?a.processor?a.processor(e[t]):e[t]:Ma(a)}}reportNonstrict(e,t,a){var n=this.strict;if(typeof n=="function"&&(n=n(e,t,a)),!(!n||n==="ignore")){if(n===!0||n==="error")throw new M("LaTeX-incompatible input and strict mode is set to 'error': "+(t+" ["+e+"]"),a);n==="warn"?typeof console<"u"&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+(t+" ["+e+"]")):typeof console<"u"&&console.warn("LaTeX-incompatible input and strict mode is set to "+("unrecognized '"+n+"': "+t+" ["+e+"]"))}}useStrictBehavior(e,t,a){var n=this.strict;if(typeof n=="function")try{n=n(e,t,a)}catch{n="error"}return!n||n==="ignore"?!1:n===!0||n==="error"?!0:n==="warn"?(typeof console<"u"&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+(t+" ["+e+"]")),!1):(typeof console<"u"&&console.warn("LaTeX-incompatible input and strict mode is set to "+("unrecognized '"+n+"': "+t+" ["+e+"]")),!1)}isTrusted(e){if(e.url&&!e.protocol){var t=R.protocolFromUrl(e.url);if(t==null)return!1;e.protocol=t}var a=typeof this.trust=="function"?this.trust(e):this.trust;return!!a}}class O0{constructor(e,t,a){this.id=void 0,this.size=void 0,this.cramped=void 0,this.id=e,this.size=t,this.cramped=a}sup(){return y0[za[this.id]]}sub(){return y0[Ta[this.id]]}fracNum(){return y0[Aa[this.id]]}fracDen(){return y0[Ba[this.id]]}cramp(){return y0[Na[this.id]]}text(){return y0[Ca[this.id]]}isTight(){return this.size>=2}}var dt=0,Ae=1,_0=2,A0=3,le=4,d0=5,ee=6,n0=7,y0=[new O0(dt,0,!1),new O0(Ae,0,!0),new O0(_0,1,!1),new O0(A0,1,!0),new O0(le,2,!1),new O0(d0,2,!0),new O0(ee,3,!1),new O0(n0,3,!0)],za=[le,d0,le,d0,ee,n0,ee,n0],Ta=[d0,d0,d0,d0,n0,n0,n0,n0],Aa=[_0,A0,le,d0,ee,n0,ee,n0],Ba=[A0,A0,d0,d0,n0,n0,n0,n0],Na=[Ae,Ae,A0,A0,d0,d0,n0,n0],Ca=[dt,Ae,_0,A0,_0,A0,_0,A0],I={DISPLAY:y0[dt],TEXT:y0[_0],SCRIPT:y0[le],SCRIPTSCRIPT:y0[ee]},at=[{name:"latin",blocks:[[256,591],[768,879]]},{name:"cyrillic",blocks:[[1024,1279]]},{name:"armenian",blocks:[[1328,1423]]},{name:"brahmic",blocks:[[2304,4255]]},{name:"georgian",blocks:[[4256,4351]]},{name:"cjk",blocks:[[12288,12543],[19968,40879],[65280,65376]]},{name:"hangul",blocks:[[44032,55215]]}];function qa(r){for(var e=0;e=n[0]&&r<=n[1])return t.name}return null}var Te=[];at.forEach(r=>r.blocks.forEach(e=>Te.push(...e)));function gr(r){for(var e=0;e=Te[e]&&r<=Te[e+1])return!0;return!1}var Q0=80,Ra=function(e,t){return"M95,"+(622+e+t)+` +c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14 +c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54 +c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10 +s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429 +c69,-144,104.5,-217.7,106.5,-221 +l`+e/2.075+" -"+e+` +c5.3,-9.3,12,-14,20,-14 +H400000v`+(40+e)+`H845.2724 +s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7 +c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z +M`+(834+e)+" "+t+"h400000v"+(40+e)+"h-400000z"},Ea=function(e,t){return"M263,"+(601+e+t)+`c0.7,0,18,39.7,52,119 +c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120 +c340,-704.7,510.7,-1060.3,512,-1067 +l`+e/2.084+" -"+e+` +c4.7,-7.3,11,-11,19,-11 +H40000v`+(40+e)+`H1012.3 +s-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232 +c-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1 +s-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26 +c-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z +M`+(1001+e)+" "+t+"h400000v"+(40+e)+"h-400000z"},Ia=function(e,t){return"M983 "+(10+e+t)+` +l`+e/3.13+" -"+e+` +c4,-6.7,10,-10,18,-10 H400000v`+(40+e)+` +H1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7 +s-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744 +c-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30 +c26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722 +c56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5 +c53.7,-170.3,84.5,-266.8,92.5,-289.5z +M`+(1001+e)+" "+t+"h400000v"+(40+e)+"h-400000z"},Da=function(e,t){return"M424,"+(2398+e+t)+` +c-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514 +c0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20 +s-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121 +s209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081 +l`+e/4.223+" -"+e+`c4,-6.7,10,-10,18,-10 H400000 +v`+(40+e)+`H1014.6 +s-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185 +c-2,6,-10,9,-24,9 +c-8,0,-12,-0.7,-12,-2z M`+(1001+e)+" "+t+` +h400000v`+(40+e)+"h-400000z"},Oa=function(e,t){return"M473,"+(2713+e+t)+` +c339.3,-1799.3,509.3,-2700,510,-2702 l`+e/5.298+" -"+e+` +c3.3,-7.3,9.3,-11,18,-11 H400000v`+(40+e)+`H1017.7 +s-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9 +c-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200 +c0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26 +s76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104, +606zM`+(1001+e)+" "+t+"h400000v"+(40+e)+"H1017.7z"},La=function(e){var t=e/2;return"M400000 "+e+" H0 L"+t+" 0 l65 45 L145 "+(e-80)+" H400000z"},Ha=function(e,t,a){var n=a-54-t-e;return"M702 "+(e+t)+"H400000"+(40+e)+` +H742v`+n+`l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1 +h-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170 +c-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667 +219 661 l218 661zM702 `+t+"H400000v"+(40+e)+"H742z"},Fa=function(e,t,a){t=1e3*t;var n="";switch(e){case"sqrtMain":n=Ra(t,Q0);break;case"sqrtSize1":n=Ea(t,Q0);break;case"sqrtSize2":n=Ia(t,Q0);break;case"sqrtSize3":n=Da(t,Q0);break;case"sqrtSize4":n=Oa(t,Q0);break;case"sqrtTall":n=Ha(t,Q0,a)}return n},Pa=function(e,t){switch(e){case"⎜":return"M291 0 H417 V"+t+" H291z M291 0 H417 V"+t+" H291z";case"∣":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145z";case"∥":return"M145 0 H188 V"+t+" H145z M145 0 H188 V"+t+" H145z"+("M367 0 H410 V"+t+" H367z M367 0 H410 V"+t+" H367z");case"⎟":return"M457 0 H583 V"+t+" H457z M457 0 H583 V"+t+" H457z";case"⎢":return"M319 0 H403 V"+t+" H319z M319 0 H403 V"+t+" H319z";case"⎥":return"M263 0 H347 V"+t+" H263z M263 0 H347 V"+t+" H263z";case"⎪":return"M384 0 H504 V"+t+" H384z M384 0 H504 V"+t+" H384z";case"⏐":return"M312 0 H355 V"+t+" H312z M312 0 H355 V"+t+" H312z";case"‖":return"M257 0 H300 V"+t+" H257z M257 0 H300 V"+t+" H257z"+("M478 0 H521 V"+t+" H478z M478 0 H521 V"+t+" H478z");default:return""}},Dt={doubleleftarrow:`M262 157 +l10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3 + 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28 + 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5 +c2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5 + 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87 +-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7 +-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z +m8 0v40h399730v-40zm0 194v40h399730v-40z`,doublerightarrow:`M399738 392l +-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5 + 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88 +-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68 +-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18 +-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782 +c-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3 +-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z`,leftarrow:`M400000 241H110l3-3c68.7-52.7 113.7-120 + 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8 +-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247 +c-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208 + 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3 + 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202 + l-3-3h399890zM100 241v40h399900v-40z`,leftbrace:`M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117 +-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7 + 5-6 9-10 13-.7 1-7.3 1-20 1H6z`,leftbraceunder:`M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13 + 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688 + 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7 +-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z`,leftgroup:`M400000 80 +H435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0 + 435 0h399565z`,leftgroupunder:`M400000 262 +H435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219 + 435 219h399565z`,leftharpoon:`M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3 +-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5 +-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7 +-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z`,leftharpoonplus:`M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5 + 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3 +-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7 +-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z +m0 0v40h400000v-40z`,leftharpoondown:`M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333 + 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5 + 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667 +-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z`,leftharpoondownplus:`M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12 + 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7 +-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0 +v40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z`,lefthook:`M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5 +-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3 +-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21 + 71.5 23h399859zM103 281v-40h399897v40z`,leftlinesegment:`M40 281 V428 H0 V94 H40 V241 H400000 v40z +M40 281 V428 H0 V94 H40 V241 H400000 v40z`,leftmapsto:`M40 281 V448H0V74H40V241H400000v40z +M40 281 V448H0V74H40V241H400000v40z`,leftToFrom:`M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23 +-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8 +c28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3 + 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z`,longequal:`M0 50 h400000 v40H0z m0 194h40000v40H0z +M0 50 h400000 v40H0z m0 194h40000v40H0z`,midbrace:`M200428 334 +c-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14 +-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7 + 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11 + 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z`,midbraceunder:`M199572 214 +c100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14 + 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3 + 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0 +-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z`,oiintSize1:`M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6 +-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z +m368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8 +60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z`,oiintSize2:`M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8 +-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z +m502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2 +c0 110 84 276 504 276s502.4-166 502.4-276z`,oiiintSize1:`M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6 +-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z +m525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0 +85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z`,oiiintSize2:`M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8 +-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z +m770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1 +c0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z`,rightarrow:`M0 241v40h399891c-47.3 35.3-84 78-110 128 +-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 + 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 + 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85 +-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5 +-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67 + 151.7 139 205zm0 0v40h399900v-40z`,rightbrace:`M400000 542l +-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5 +s-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1 +c124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z`,rightbraceunder:`M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3 + 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237 +-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z`,rightgroup:`M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0 + 3-1 3-3v-38c-76-158-257-219-435-219H0z`,rightgroupunder:`M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18 + 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z`,rightharpoon:`M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3 +-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2 +-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 + 69.2 92 94.5zm0 0v40h399900v-40z`,rightharpoonplus:`M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11 +-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7 + 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z +m0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z`,rightharpoondown:`M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8 + 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5 +-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95 +-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z`,rightharpoondownplus:`M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8 + 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 + 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3 +-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z +m0-194v40h400000v-40zm0 0v40h400000v-40z`,righthook:`M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3 + 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0 +-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21 + 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z`,rightlinesegment:`M399960 241 V94 h40 V428 h-40 V281 H0 v-40z +M399960 241 V94 h40 V428 h-40 V281 H0 v-40z`,rightToFrom:`M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23 + 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32 +-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142 +-167z M100 147v40h399900v-40zM0 341v40h399900v-40z`,twoheadleftarrow:`M0 167c68 40 + 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69 +-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3 +-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19 +-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101 + 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z`,twoheadrightarrow:`M400000 167 +c-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3 + 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42 + 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333 +-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70 + 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z`,tilde1:`M200 55.538c-77 0-168 73.953-177 73.953-3 0-7 +-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0 + 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0 + 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128 +-68.267.847-113-73.952-191-73.952z`,tilde2:`M344 55.266c-142 0-300.638 81.316-311.5 86.418 +-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9 + 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114 +c1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751 + 181.476 676 181.476c-149 0-189-126.21-332-126.21z`,tilde3:`M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457 +-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0 + 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697 + 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696 + -338 0-409-156.573-744-156.573z`,tilde4:`M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345 +-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409 + 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9 + 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409 + -175.236-744-175.236z`,vec:`M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5 +3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11 +10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63 +-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1 +-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59 +H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359 +c-16-25.333-24-45-24-59z`,widehat1:`M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22 +c-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z`,widehat2:`M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10 +-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z`,widehat3:`M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10 +-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z`,widehat4:`M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10 +-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z`,widecheck1:`M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1, +-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z`,widecheck2:`M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10, +-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z`,widecheck3:`M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10, +-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z`,widecheck4:`M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10, +-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z`,baraboveleftarrow:`M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202 +c4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5 +c-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130 +s-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47 +121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6 +s2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11 +c0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z +M100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z`,rightarrowabovebar:`M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32 +-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0 +13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39 +-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5 +-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5 +-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67 +151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z`,baraboveshortleftharpoon:`M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11 +c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17 +c2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21 +c-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40 +c-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z +M0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z`,rightharpoonaboveshortbar:`M0,241 l0,40c399126,0,399993,0,399993,0 +c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199, +-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6 +c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z +M0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z`,shortbaraboveleftharpoon:`M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11 +c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9, +1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7, +-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z +M93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z`,shortrightharpoonabovebar:`M53,241l0,40c398570,0,399437,0,399437,0 +c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199, +-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6 +c-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z +M500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z`},Ga=function(e,t){switch(e){case"lbrack":return"M403 1759 V84 H666 V0 H319 V1759 v"+t+` v1759 h347 v-84 +H403z M403 1759 V0 H319 V1759 v`+t+" v1759 h84z";case"rbrack":return"M347 1759 V0 H0 V84 H263 V1759 v"+t+` v1759 H0 v84 H347z +M347 1759 V0 H263 V1759 v`+t+" v1759 h84z";case"vert":return"M145 15 v585 v"+t+` v585 c2.667,10,9.667,15,21,15 +c10,0,16.667,-5,20,-15 v-585 v`+-t+` v-585 c-2.667,-10,-9.667,-15,-21,-15 +c-10,0,-16.667,5,-20,15z M188 15 H145 v585 v`+t+" v585 h43z";case"doublevert":return"M145 15 v585 v"+t+` v585 c2.667,10,9.667,15,21,15 +c10,0,16.667,-5,20,-15 v-585 v`+-t+` v-585 c-2.667,-10,-9.667,-15,-21,-15 +c-10,0,-16.667,5,-20,15z M188 15 H145 v585 v`+t+` v585 h43z +M367 15 v585 v`+t+` v585 c2.667,10,9.667,15,21,15 +c10,0,16.667,-5,20,-15 v-585 v`+-t+` v-585 c-2.667,-10,-9.667,-15,-21,-15 +c-10,0,-16.667,5,-20,15z M410 15 H367 v585 v`+t+" v585 h43z";case"lfloor":return"M319 602 V0 H403 V602 v"+t+` v1715 h263 v84 H319z +MM319 602 V0 H403 V602 v`+t+" v1715 H319z";case"rfloor":return"M319 602 V0 H403 V602 v"+t+` v1799 H0 v-84 H319z +MM319 602 V0 H403 V602 v`+t+" v1715 H319z";case"lceil":return"M403 1759 V84 H666 V0 H319 V1759 v"+t+` v602 h84z +M403 1759 V0 H319 V1759 v`+t+" v602 h84z";case"rceil":return"M347 1759 V0 H0 V84 H263 V1759 v"+t+` v602 h84z +M347 1759 V0 h-84 V1759 v`+t+" v602 h84z";case"lparen":return`M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1 +c-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349, +-36,557 l0,`+(t+84)+`c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210, +949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9 +c0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5, +-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189 +l0,-`+(t+92)+`c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3, +-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z`;case"rparen":return`M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3, +63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5 +c11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0,`+(t+9)+` +c-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664 +c-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11 +c0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17 +c242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558 +l0,-`+(t+144)+`c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7, +-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z`;default:throw new Error("Unknown stretchy delimiter.")}};class he{constructor(e){this.children=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.children=e,this.classes=[],this.height=0,this.depth=0,this.maxFontSize=0,this.style={}}hasClass(e){return R.contains(this.classes,e)}toNode(){for(var e=document.createDocumentFragment(),t=0;tt.toText();return this.children.map(e).join("")}}var w0={"AMS-Regular":{32:[0,0,0,0,.25],65:[0,.68889,0,0,.72222],66:[0,.68889,0,0,.66667],67:[0,.68889,0,0,.72222],68:[0,.68889,0,0,.72222],69:[0,.68889,0,0,.66667],70:[0,.68889,0,0,.61111],71:[0,.68889,0,0,.77778],72:[0,.68889,0,0,.77778],73:[0,.68889,0,0,.38889],74:[.16667,.68889,0,0,.5],75:[0,.68889,0,0,.77778],76:[0,.68889,0,0,.66667],77:[0,.68889,0,0,.94445],78:[0,.68889,0,0,.72222],79:[.16667,.68889,0,0,.77778],80:[0,.68889,0,0,.61111],81:[.16667,.68889,0,0,.77778],82:[0,.68889,0,0,.72222],83:[0,.68889,0,0,.55556],84:[0,.68889,0,0,.66667],85:[0,.68889,0,0,.72222],86:[0,.68889,0,0,.72222],87:[0,.68889,0,0,1],88:[0,.68889,0,0,.72222],89:[0,.68889,0,0,.72222],90:[0,.68889,0,0,.66667],107:[0,.68889,0,0,.55556],160:[0,0,0,0,.25],165:[0,.675,.025,0,.75],174:[.15559,.69224,0,0,.94666],240:[0,.68889,0,0,.55556],295:[0,.68889,0,0,.54028],710:[0,.825,0,0,2.33334],732:[0,.9,0,0,2.33334],770:[0,.825,0,0,2.33334],771:[0,.9,0,0,2.33334],989:[.08167,.58167,0,0,.77778],1008:[0,.43056,.04028,0,.66667],8245:[0,.54986,0,0,.275],8463:[0,.68889,0,0,.54028],8487:[0,.68889,0,0,.72222],8498:[0,.68889,0,0,.55556],8502:[0,.68889,0,0,.66667],8503:[0,.68889,0,0,.44445],8504:[0,.68889,0,0,.66667],8513:[0,.68889,0,0,.63889],8592:[-.03598,.46402,0,0,.5],8594:[-.03598,.46402,0,0,.5],8602:[-.13313,.36687,0,0,1],8603:[-.13313,.36687,0,0,1],8606:[.01354,.52239,0,0,1],8608:[.01354,.52239,0,0,1],8610:[.01354,.52239,0,0,1.11111],8611:[.01354,.52239,0,0,1.11111],8619:[0,.54986,0,0,1],8620:[0,.54986,0,0,1],8621:[-.13313,.37788,0,0,1.38889],8622:[-.13313,.36687,0,0,1],8624:[0,.69224,0,0,.5],8625:[0,.69224,0,0,.5],8630:[0,.43056,0,0,1],8631:[0,.43056,0,0,1],8634:[.08198,.58198,0,0,.77778],8635:[.08198,.58198,0,0,.77778],8638:[.19444,.69224,0,0,.41667],8639:[.19444,.69224,0,0,.41667],8642:[.19444,.69224,0,0,.41667],8643:[.19444,.69224,0,0,.41667],8644:[.1808,.675,0,0,1],8646:[.1808,.675,0,0,1],8647:[.1808,.675,0,0,1],8648:[.19444,.69224,0,0,.83334],8649:[.1808,.675,0,0,1],8650:[.19444,.69224,0,0,.83334],8651:[.01354,.52239,0,0,1],8652:[.01354,.52239,0,0,1],8653:[-.13313,.36687,0,0,1],8654:[-.13313,.36687,0,0,1],8655:[-.13313,.36687,0,0,1],8666:[.13667,.63667,0,0,1],8667:[.13667,.63667,0,0,1],8669:[-.13313,.37788,0,0,1],8672:[-.064,.437,0,0,1.334],8674:[-.064,.437,0,0,1.334],8705:[0,.825,0,0,.5],8708:[0,.68889,0,0,.55556],8709:[.08167,.58167,0,0,.77778],8717:[0,.43056,0,0,.42917],8722:[-.03598,.46402,0,0,.5],8724:[.08198,.69224,0,0,.77778],8726:[.08167,.58167,0,0,.77778],8733:[0,.69224,0,0,.77778],8736:[0,.69224,0,0,.72222],8737:[0,.69224,0,0,.72222],8738:[.03517,.52239,0,0,.72222],8739:[.08167,.58167,0,0,.22222],8740:[.25142,.74111,0,0,.27778],8741:[.08167,.58167,0,0,.38889],8742:[.25142,.74111,0,0,.5],8756:[0,.69224,0,0,.66667],8757:[0,.69224,0,0,.66667],8764:[-.13313,.36687,0,0,.77778],8765:[-.13313,.37788,0,0,.77778],8769:[-.13313,.36687,0,0,.77778],8770:[-.03625,.46375,0,0,.77778],8774:[.30274,.79383,0,0,.77778],8776:[-.01688,.48312,0,0,.77778],8778:[.08167,.58167,0,0,.77778],8782:[.06062,.54986,0,0,.77778],8783:[.06062,.54986,0,0,.77778],8785:[.08198,.58198,0,0,.77778],8786:[.08198,.58198,0,0,.77778],8787:[.08198,.58198,0,0,.77778],8790:[0,.69224,0,0,.77778],8791:[.22958,.72958,0,0,.77778],8796:[.08198,.91667,0,0,.77778],8806:[.25583,.75583,0,0,.77778],8807:[.25583,.75583,0,0,.77778],8808:[.25142,.75726,0,0,.77778],8809:[.25142,.75726,0,0,.77778],8812:[.25583,.75583,0,0,.5],8814:[.20576,.70576,0,0,.77778],8815:[.20576,.70576,0,0,.77778],8816:[.30274,.79383,0,0,.77778],8817:[.30274,.79383,0,0,.77778],8818:[.22958,.72958,0,0,.77778],8819:[.22958,.72958,0,0,.77778],8822:[.1808,.675,0,0,.77778],8823:[.1808,.675,0,0,.77778],8828:[.13667,.63667,0,0,.77778],8829:[.13667,.63667,0,0,.77778],8830:[.22958,.72958,0,0,.77778],8831:[.22958,.72958,0,0,.77778],8832:[.20576,.70576,0,0,.77778],8833:[.20576,.70576,0,0,.77778],8840:[.30274,.79383,0,0,.77778],8841:[.30274,.79383,0,0,.77778],8842:[.13597,.63597,0,0,.77778],8843:[.13597,.63597,0,0,.77778],8847:[.03517,.54986,0,0,.77778],8848:[.03517,.54986,0,0,.77778],8858:[.08198,.58198,0,0,.77778],8859:[.08198,.58198,0,0,.77778],8861:[.08198,.58198,0,0,.77778],8862:[0,.675,0,0,.77778],8863:[0,.675,0,0,.77778],8864:[0,.675,0,0,.77778],8865:[0,.675,0,0,.77778],8872:[0,.69224,0,0,.61111],8873:[0,.69224,0,0,.72222],8874:[0,.69224,0,0,.88889],8876:[0,.68889,0,0,.61111],8877:[0,.68889,0,0,.61111],8878:[0,.68889,0,0,.72222],8879:[0,.68889,0,0,.72222],8882:[.03517,.54986,0,0,.77778],8883:[.03517,.54986,0,0,.77778],8884:[.13667,.63667,0,0,.77778],8885:[.13667,.63667,0,0,.77778],8888:[0,.54986,0,0,1.11111],8890:[.19444,.43056,0,0,.55556],8891:[.19444,.69224,0,0,.61111],8892:[.19444,.69224,0,0,.61111],8901:[0,.54986,0,0,.27778],8903:[.08167,.58167,0,0,.77778],8905:[.08167,.58167,0,0,.77778],8906:[.08167,.58167,0,0,.77778],8907:[0,.69224,0,0,.77778],8908:[0,.69224,0,0,.77778],8909:[-.03598,.46402,0,0,.77778],8910:[0,.54986,0,0,.76042],8911:[0,.54986,0,0,.76042],8912:[.03517,.54986,0,0,.77778],8913:[.03517,.54986,0,0,.77778],8914:[0,.54986,0,0,.66667],8915:[0,.54986,0,0,.66667],8916:[0,.69224,0,0,.66667],8918:[.0391,.5391,0,0,.77778],8919:[.0391,.5391,0,0,.77778],8920:[.03517,.54986,0,0,1.33334],8921:[.03517,.54986,0,0,1.33334],8922:[.38569,.88569,0,0,.77778],8923:[.38569,.88569,0,0,.77778],8926:[.13667,.63667,0,0,.77778],8927:[.13667,.63667,0,0,.77778],8928:[.30274,.79383,0,0,.77778],8929:[.30274,.79383,0,0,.77778],8934:[.23222,.74111,0,0,.77778],8935:[.23222,.74111,0,0,.77778],8936:[.23222,.74111,0,0,.77778],8937:[.23222,.74111,0,0,.77778],8938:[.20576,.70576,0,0,.77778],8939:[.20576,.70576,0,0,.77778],8940:[.30274,.79383,0,0,.77778],8941:[.30274,.79383,0,0,.77778],8994:[.19444,.69224,0,0,.77778],8995:[.19444,.69224,0,0,.77778],9416:[.15559,.69224,0,0,.90222],9484:[0,.69224,0,0,.5],9488:[0,.69224,0,0,.5],9492:[0,.37788,0,0,.5],9496:[0,.37788,0,0,.5],9585:[.19444,.68889,0,0,.88889],9586:[.19444,.74111,0,0,.88889],9632:[0,.675,0,0,.77778],9633:[0,.675,0,0,.77778],9650:[0,.54986,0,0,.72222],9651:[0,.54986,0,0,.72222],9654:[.03517,.54986,0,0,.77778],9660:[0,.54986,0,0,.72222],9661:[0,.54986,0,0,.72222],9664:[.03517,.54986,0,0,.77778],9674:[.11111,.69224,0,0,.66667],9733:[.19444,.69224,0,0,.94445],10003:[0,.69224,0,0,.83334],10016:[0,.69224,0,0,.83334],10731:[.11111,.69224,0,0,.66667],10846:[.19444,.75583,0,0,.61111],10877:[.13667,.63667,0,0,.77778],10878:[.13667,.63667,0,0,.77778],10885:[.25583,.75583,0,0,.77778],10886:[.25583,.75583,0,0,.77778],10887:[.13597,.63597,0,0,.77778],10888:[.13597,.63597,0,0,.77778],10889:[.26167,.75726,0,0,.77778],10890:[.26167,.75726,0,0,.77778],10891:[.48256,.98256,0,0,.77778],10892:[.48256,.98256,0,0,.77778],10901:[.13667,.63667,0,0,.77778],10902:[.13667,.63667,0,0,.77778],10933:[.25142,.75726,0,0,.77778],10934:[.25142,.75726,0,0,.77778],10935:[.26167,.75726,0,0,.77778],10936:[.26167,.75726,0,0,.77778],10937:[.26167,.75726,0,0,.77778],10938:[.26167,.75726,0,0,.77778],10949:[.25583,.75583,0,0,.77778],10950:[.25583,.75583,0,0,.77778],10955:[.28481,.79383,0,0,.77778],10956:[.28481,.79383,0,0,.77778],57350:[.08167,.58167,0,0,.22222],57351:[.08167,.58167,0,0,.38889],57352:[.08167,.58167,0,0,.77778],57353:[0,.43056,.04028,0,.66667],57356:[.25142,.75726,0,0,.77778],57357:[.25142,.75726,0,0,.77778],57358:[.41951,.91951,0,0,.77778],57359:[.30274,.79383,0,0,.77778],57360:[.30274,.79383,0,0,.77778],57361:[.41951,.91951,0,0,.77778],57366:[.25142,.75726,0,0,.77778],57367:[.25142,.75726,0,0,.77778],57368:[.25142,.75726,0,0,.77778],57369:[.25142,.75726,0,0,.77778],57370:[.13597,.63597,0,0,.77778],57371:[.13597,.63597,0,0,.77778]},"Caligraphic-Regular":{32:[0,0,0,0,.25],65:[0,.68333,0,.19445,.79847],66:[0,.68333,.03041,.13889,.65681],67:[0,.68333,.05834,.13889,.52653],68:[0,.68333,.02778,.08334,.77139],69:[0,.68333,.08944,.11111,.52778],70:[0,.68333,.09931,.11111,.71875],71:[.09722,.68333,.0593,.11111,.59487],72:[0,.68333,.00965,.11111,.84452],73:[0,.68333,.07382,0,.54452],74:[.09722,.68333,.18472,.16667,.67778],75:[0,.68333,.01445,.05556,.76195],76:[0,.68333,0,.13889,.68972],77:[0,.68333,0,.13889,1.2009],78:[0,.68333,.14736,.08334,.82049],79:[0,.68333,.02778,.11111,.79611],80:[0,.68333,.08222,.08334,.69556],81:[.09722,.68333,0,.11111,.81667],82:[0,.68333,0,.08334,.8475],83:[0,.68333,.075,.13889,.60556],84:[0,.68333,.25417,0,.54464],85:[0,.68333,.09931,.08334,.62583],86:[0,.68333,.08222,0,.61278],87:[0,.68333,.08222,.08334,.98778],88:[0,.68333,.14643,.13889,.7133],89:[.09722,.68333,.08222,.08334,.66834],90:[0,.68333,.07944,.13889,.72473],160:[0,0,0,0,.25]},"Fraktur-Regular":{32:[0,0,0,0,.25],33:[0,.69141,0,0,.29574],34:[0,.69141,0,0,.21471],38:[0,.69141,0,0,.73786],39:[0,.69141,0,0,.21201],40:[.24982,.74947,0,0,.38865],41:[.24982,.74947,0,0,.38865],42:[0,.62119,0,0,.27764],43:[.08319,.58283,0,0,.75623],44:[0,.10803,0,0,.27764],45:[.08319,.58283,0,0,.75623],46:[0,.10803,0,0,.27764],47:[.24982,.74947,0,0,.50181],48:[0,.47534,0,0,.50181],49:[0,.47534,0,0,.50181],50:[0,.47534,0,0,.50181],51:[.18906,.47534,0,0,.50181],52:[.18906,.47534,0,0,.50181],53:[.18906,.47534,0,0,.50181],54:[0,.69141,0,0,.50181],55:[.18906,.47534,0,0,.50181],56:[0,.69141,0,0,.50181],57:[.18906,.47534,0,0,.50181],58:[0,.47534,0,0,.21606],59:[.12604,.47534,0,0,.21606],61:[-.13099,.36866,0,0,.75623],63:[0,.69141,0,0,.36245],65:[0,.69141,0,0,.7176],66:[0,.69141,0,0,.88397],67:[0,.69141,0,0,.61254],68:[0,.69141,0,0,.83158],69:[0,.69141,0,0,.66278],70:[.12604,.69141,0,0,.61119],71:[0,.69141,0,0,.78539],72:[.06302,.69141,0,0,.7203],73:[0,.69141,0,0,.55448],74:[.12604,.69141,0,0,.55231],75:[0,.69141,0,0,.66845],76:[0,.69141,0,0,.66602],77:[0,.69141,0,0,1.04953],78:[0,.69141,0,0,.83212],79:[0,.69141,0,0,.82699],80:[.18906,.69141,0,0,.82753],81:[.03781,.69141,0,0,.82699],82:[0,.69141,0,0,.82807],83:[0,.69141,0,0,.82861],84:[0,.69141,0,0,.66899],85:[0,.69141,0,0,.64576],86:[0,.69141,0,0,.83131],87:[0,.69141,0,0,1.04602],88:[0,.69141,0,0,.71922],89:[.18906,.69141,0,0,.83293],90:[.12604,.69141,0,0,.60201],91:[.24982,.74947,0,0,.27764],93:[.24982,.74947,0,0,.27764],94:[0,.69141,0,0,.49965],97:[0,.47534,0,0,.50046],98:[0,.69141,0,0,.51315],99:[0,.47534,0,0,.38946],100:[0,.62119,0,0,.49857],101:[0,.47534,0,0,.40053],102:[.18906,.69141,0,0,.32626],103:[.18906,.47534,0,0,.5037],104:[.18906,.69141,0,0,.52126],105:[0,.69141,0,0,.27899],106:[0,.69141,0,0,.28088],107:[0,.69141,0,0,.38946],108:[0,.69141,0,0,.27953],109:[0,.47534,0,0,.76676],110:[0,.47534,0,0,.52666],111:[0,.47534,0,0,.48885],112:[.18906,.52396,0,0,.50046],113:[.18906,.47534,0,0,.48912],114:[0,.47534,0,0,.38919],115:[0,.47534,0,0,.44266],116:[0,.62119,0,0,.33301],117:[0,.47534,0,0,.5172],118:[0,.52396,0,0,.5118],119:[0,.52396,0,0,.77351],120:[.18906,.47534,0,0,.38865],121:[.18906,.47534,0,0,.49884],122:[.18906,.47534,0,0,.39054],160:[0,0,0,0,.25],8216:[0,.69141,0,0,.21471],8217:[0,.69141,0,0,.21471],58112:[0,.62119,0,0,.49749],58113:[0,.62119,0,0,.4983],58114:[.18906,.69141,0,0,.33328],58115:[.18906,.69141,0,0,.32923],58116:[.18906,.47534,0,0,.50343],58117:[0,.69141,0,0,.33301],58118:[0,.62119,0,0,.33409],58119:[0,.47534,0,0,.50073]},"Main-Bold":{32:[0,0,0,0,.25],33:[0,.69444,0,0,.35],34:[0,.69444,0,0,.60278],35:[.19444,.69444,0,0,.95833],36:[.05556,.75,0,0,.575],37:[.05556,.75,0,0,.95833],38:[0,.69444,0,0,.89444],39:[0,.69444,0,0,.31944],40:[.25,.75,0,0,.44722],41:[.25,.75,0,0,.44722],42:[0,.75,0,0,.575],43:[.13333,.63333,0,0,.89444],44:[.19444,.15556,0,0,.31944],45:[0,.44444,0,0,.38333],46:[0,.15556,0,0,.31944],47:[.25,.75,0,0,.575],48:[0,.64444,0,0,.575],49:[0,.64444,0,0,.575],50:[0,.64444,0,0,.575],51:[0,.64444,0,0,.575],52:[0,.64444,0,0,.575],53:[0,.64444,0,0,.575],54:[0,.64444,0,0,.575],55:[0,.64444,0,0,.575],56:[0,.64444,0,0,.575],57:[0,.64444,0,0,.575],58:[0,.44444,0,0,.31944],59:[.19444,.44444,0,0,.31944],60:[.08556,.58556,0,0,.89444],61:[-.10889,.39111,0,0,.89444],62:[.08556,.58556,0,0,.89444],63:[0,.69444,0,0,.54305],64:[0,.69444,0,0,.89444],65:[0,.68611,0,0,.86944],66:[0,.68611,0,0,.81805],67:[0,.68611,0,0,.83055],68:[0,.68611,0,0,.88194],69:[0,.68611,0,0,.75555],70:[0,.68611,0,0,.72361],71:[0,.68611,0,0,.90416],72:[0,.68611,0,0,.9],73:[0,.68611,0,0,.43611],74:[0,.68611,0,0,.59444],75:[0,.68611,0,0,.90138],76:[0,.68611,0,0,.69166],77:[0,.68611,0,0,1.09166],78:[0,.68611,0,0,.9],79:[0,.68611,0,0,.86388],80:[0,.68611,0,0,.78611],81:[.19444,.68611,0,0,.86388],82:[0,.68611,0,0,.8625],83:[0,.68611,0,0,.63889],84:[0,.68611,0,0,.8],85:[0,.68611,0,0,.88472],86:[0,.68611,.01597,0,.86944],87:[0,.68611,.01597,0,1.18888],88:[0,.68611,0,0,.86944],89:[0,.68611,.02875,0,.86944],90:[0,.68611,0,0,.70277],91:[.25,.75,0,0,.31944],92:[.25,.75,0,0,.575],93:[.25,.75,0,0,.31944],94:[0,.69444,0,0,.575],95:[.31,.13444,.03194,0,.575],97:[0,.44444,0,0,.55902],98:[0,.69444,0,0,.63889],99:[0,.44444,0,0,.51111],100:[0,.69444,0,0,.63889],101:[0,.44444,0,0,.52708],102:[0,.69444,.10903,0,.35139],103:[.19444,.44444,.01597,0,.575],104:[0,.69444,0,0,.63889],105:[0,.69444,0,0,.31944],106:[.19444,.69444,0,0,.35139],107:[0,.69444,0,0,.60694],108:[0,.69444,0,0,.31944],109:[0,.44444,0,0,.95833],110:[0,.44444,0,0,.63889],111:[0,.44444,0,0,.575],112:[.19444,.44444,0,0,.63889],113:[.19444,.44444,0,0,.60694],114:[0,.44444,0,0,.47361],115:[0,.44444,0,0,.45361],116:[0,.63492,0,0,.44722],117:[0,.44444,0,0,.63889],118:[0,.44444,.01597,0,.60694],119:[0,.44444,.01597,0,.83055],120:[0,.44444,0,0,.60694],121:[.19444,.44444,.01597,0,.60694],122:[0,.44444,0,0,.51111],123:[.25,.75,0,0,.575],124:[.25,.75,0,0,.31944],125:[.25,.75,0,0,.575],126:[.35,.34444,0,0,.575],160:[0,0,0,0,.25],163:[0,.69444,0,0,.86853],168:[0,.69444,0,0,.575],172:[0,.44444,0,0,.76666],176:[0,.69444,0,0,.86944],177:[.13333,.63333,0,0,.89444],184:[.17014,0,0,0,.51111],198:[0,.68611,0,0,1.04166],215:[.13333,.63333,0,0,.89444],216:[.04861,.73472,0,0,.89444],223:[0,.69444,0,0,.59722],230:[0,.44444,0,0,.83055],247:[.13333,.63333,0,0,.89444],248:[.09722,.54167,0,0,.575],305:[0,.44444,0,0,.31944],338:[0,.68611,0,0,1.16944],339:[0,.44444,0,0,.89444],567:[.19444,.44444,0,0,.35139],710:[0,.69444,0,0,.575],711:[0,.63194,0,0,.575],713:[0,.59611,0,0,.575],714:[0,.69444,0,0,.575],715:[0,.69444,0,0,.575],728:[0,.69444,0,0,.575],729:[0,.69444,0,0,.31944],730:[0,.69444,0,0,.86944],732:[0,.69444,0,0,.575],733:[0,.69444,0,0,.575],915:[0,.68611,0,0,.69166],916:[0,.68611,0,0,.95833],920:[0,.68611,0,0,.89444],923:[0,.68611,0,0,.80555],926:[0,.68611,0,0,.76666],928:[0,.68611,0,0,.9],931:[0,.68611,0,0,.83055],933:[0,.68611,0,0,.89444],934:[0,.68611,0,0,.83055],936:[0,.68611,0,0,.89444],937:[0,.68611,0,0,.83055],8211:[0,.44444,.03194,0,.575],8212:[0,.44444,.03194,0,1.14999],8216:[0,.69444,0,0,.31944],8217:[0,.69444,0,0,.31944],8220:[0,.69444,0,0,.60278],8221:[0,.69444,0,0,.60278],8224:[.19444,.69444,0,0,.51111],8225:[.19444,.69444,0,0,.51111],8242:[0,.55556,0,0,.34444],8407:[0,.72444,.15486,0,.575],8463:[0,.69444,0,0,.66759],8465:[0,.69444,0,0,.83055],8467:[0,.69444,0,0,.47361],8472:[.19444,.44444,0,0,.74027],8476:[0,.69444,0,0,.83055],8501:[0,.69444,0,0,.70277],8592:[-.10889,.39111,0,0,1.14999],8593:[.19444,.69444,0,0,.575],8594:[-.10889,.39111,0,0,1.14999],8595:[.19444,.69444,0,0,.575],8596:[-.10889,.39111,0,0,1.14999],8597:[.25,.75,0,0,.575],8598:[.19444,.69444,0,0,1.14999],8599:[.19444,.69444,0,0,1.14999],8600:[.19444,.69444,0,0,1.14999],8601:[.19444,.69444,0,0,1.14999],8636:[-.10889,.39111,0,0,1.14999],8637:[-.10889,.39111,0,0,1.14999],8640:[-.10889,.39111,0,0,1.14999],8641:[-.10889,.39111,0,0,1.14999],8656:[-.10889,.39111,0,0,1.14999],8657:[.19444,.69444,0,0,.70277],8658:[-.10889,.39111,0,0,1.14999],8659:[.19444,.69444,0,0,.70277],8660:[-.10889,.39111,0,0,1.14999],8661:[.25,.75,0,0,.70277],8704:[0,.69444,0,0,.63889],8706:[0,.69444,.06389,0,.62847],8707:[0,.69444,0,0,.63889],8709:[.05556,.75,0,0,.575],8711:[0,.68611,0,0,.95833],8712:[.08556,.58556,0,0,.76666],8715:[.08556,.58556,0,0,.76666],8722:[.13333,.63333,0,0,.89444],8723:[.13333,.63333,0,0,.89444],8725:[.25,.75,0,0,.575],8726:[.25,.75,0,0,.575],8727:[-.02778,.47222,0,0,.575],8728:[-.02639,.47361,0,0,.575],8729:[-.02639,.47361,0,0,.575],8730:[.18,.82,0,0,.95833],8733:[0,.44444,0,0,.89444],8734:[0,.44444,0,0,1.14999],8736:[0,.69224,0,0,.72222],8739:[.25,.75,0,0,.31944],8741:[.25,.75,0,0,.575],8743:[0,.55556,0,0,.76666],8744:[0,.55556,0,0,.76666],8745:[0,.55556,0,0,.76666],8746:[0,.55556,0,0,.76666],8747:[.19444,.69444,.12778,0,.56875],8764:[-.10889,.39111,0,0,.89444],8768:[.19444,.69444,0,0,.31944],8771:[.00222,.50222,0,0,.89444],8773:[.027,.638,0,0,.894],8776:[.02444,.52444,0,0,.89444],8781:[.00222,.50222,0,0,.89444],8801:[.00222,.50222,0,0,.89444],8804:[.19667,.69667,0,0,.89444],8805:[.19667,.69667,0,0,.89444],8810:[.08556,.58556,0,0,1.14999],8811:[.08556,.58556,0,0,1.14999],8826:[.08556,.58556,0,0,.89444],8827:[.08556,.58556,0,0,.89444],8834:[.08556,.58556,0,0,.89444],8835:[.08556,.58556,0,0,.89444],8838:[.19667,.69667,0,0,.89444],8839:[.19667,.69667,0,0,.89444],8846:[0,.55556,0,0,.76666],8849:[.19667,.69667,0,0,.89444],8850:[.19667,.69667,0,0,.89444],8851:[0,.55556,0,0,.76666],8852:[0,.55556,0,0,.76666],8853:[.13333,.63333,0,0,.89444],8854:[.13333,.63333,0,0,.89444],8855:[.13333,.63333,0,0,.89444],8856:[.13333,.63333,0,0,.89444],8857:[.13333,.63333,0,0,.89444],8866:[0,.69444,0,0,.70277],8867:[0,.69444,0,0,.70277],8868:[0,.69444,0,0,.89444],8869:[0,.69444,0,0,.89444],8900:[-.02639,.47361,0,0,.575],8901:[-.02639,.47361,0,0,.31944],8902:[-.02778,.47222,0,0,.575],8968:[.25,.75,0,0,.51111],8969:[.25,.75,0,0,.51111],8970:[.25,.75,0,0,.51111],8971:[.25,.75,0,0,.51111],8994:[-.13889,.36111,0,0,1.14999],8995:[-.13889,.36111,0,0,1.14999],9651:[.19444,.69444,0,0,1.02222],9657:[-.02778,.47222,0,0,.575],9661:[.19444,.69444,0,0,1.02222],9667:[-.02778,.47222,0,0,.575],9711:[.19444,.69444,0,0,1.14999],9824:[.12963,.69444,0,0,.89444],9825:[.12963,.69444,0,0,.89444],9826:[.12963,.69444,0,0,.89444],9827:[.12963,.69444,0,0,.89444],9837:[0,.75,0,0,.44722],9838:[.19444,.69444,0,0,.44722],9839:[.19444,.69444,0,0,.44722],10216:[.25,.75,0,0,.44722],10217:[.25,.75,0,0,.44722],10815:[0,.68611,0,0,.9],10927:[.19667,.69667,0,0,.89444],10928:[.19667,.69667,0,0,.89444],57376:[.19444,.69444,0,0,0]},"Main-BoldItalic":{32:[0,0,0,0,.25],33:[0,.69444,.11417,0,.38611],34:[0,.69444,.07939,0,.62055],35:[.19444,.69444,.06833,0,.94444],37:[.05556,.75,.12861,0,.94444],38:[0,.69444,.08528,0,.88555],39:[0,.69444,.12945,0,.35555],40:[.25,.75,.15806,0,.47333],41:[.25,.75,.03306,0,.47333],42:[0,.75,.14333,0,.59111],43:[.10333,.60333,.03306,0,.88555],44:[.19444,.14722,0,0,.35555],45:[0,.44444,.02611,0,.41444],46:[0,.14722,0,0,.35555],47:[.25,.75,.15806,0,.59111],48:[0,.64444,.13167,0,.59111],49:[0,.64444,.13167,0,.59111],50:[0,.64444,.13167,0,.59111],51:[0,.64444,.13167,0,.59111],52:[.19444,.64444,.13167,0,.59111],53:[0,.64444,.13167,0,.59111],54:[0,.64444,.13167,0,.59111],55:[.19444,.64444,.13167,0,.59111],56:[0,.64444,.13167,0,.59111],57:[0,.64444,.13167,0,.59111],58:[0,.44444,.06695,0,.35555],59:[.19444,.44444,.06695,0,.35555],61:[-.10889,.39111,.06833,0,.88555],63:[0,.69444,.11472,0,.59111],64:[0,.69444,.09208,0,.88555],65:[0,.68611,0,0,.86555],66:[0,.68611,.0992,0,.81666],67:[0,.68611,.14208,0,.82666],68:[0,.68611,.09062,0,.87555],69:[0,.68611,.11431,0,.75666],70:[0,.68611,.12903,0,.72722],71:[0,.68611,.07347,0,.89527],72:[0,.68611,.17208,0,.8961],73:[0,.68611,.15681,0,.47166],74:[0,.68611,.145,0,.61055],75:[0,.68611,.14208,0,.89499],76:[0,.68611,0,0,.69777],77:[0,.68611,.17208,0,1.07277],78:[0,.68611,.17208,0,.8961],79:[0,.68611,.09062,0,.85499],80:[0,.68611,.0992,0,.78721],81:[.19444,.68611,.09062,0,.85499],82:[0,.68611,.02559,0,.85944],83:[0,.68611,.11264,0,.64999],84:[0,.68611,.12903,0,.7961],85:[0,.68611,.17208,0,.88083],86:[0,.68611,.18625,0,.86555],87:[0,.68611,.18625,0,1.15999],88:[0,.68611,.15681,0,.86555],89:[0,.68611,.19803,0,.86555],90:[0,.68611,.14208,0,.70888],91:[.25,.75,.1875,0,.35611],93:[.25,.75,.09972,0,.35611],94:[0,.69444,.06709,0,.59111],95:[.31,.13444,.09811,0,.59111],97:[0,.44444,.09426,0,.59111],98:[0,.69444,.07861,0,.53222],99:[0,.44444,.05222,0,.53222],100:[0,.69444,.10861,0,.59111],101:[0,.44444,.085,0,.53222],102:[.19444,.69444,.21778,0,.4],103:[.19444,.44444,.105,0,.53222],104:[0,.69444,.09426,0,.59111],105:[0,.69326,.11387,0,.35555],106:[.19444,.69326,.1672,0,.35555],107:[0,.69444,.11111,0,.53222],108:[0,.69444,.10861,0,.29666],109:[0,.44444,.09426,0,.94444],110:[0,.44444,.09426,0,.64999],111:[0,.44444,.07861,0,.59111],112:[.19444,.44444,.07861,0,.59111],113:[.19444,.44444,.105,0,.53222],114:[0,.44444,.11111,0,.50167],115:[0,.44444,.08167,0,.48694],116:[0,.63492,.09639,0,.385],117:[0,.44444,.09426,0,.62055],118:[0,.44444,.11111,0,.53222],119:[0,.44444,.11111,0,.76777],120:[0,.44444,.12583,0,.56055],121:[.19444,.44444,.105,0,.56166],122:[0,.44444,.13889,0,.49055],126:[.35,.34444,.11472,0,.59111],160:[0,0,0,0,.25],168:[0,.69444,.11473,0,.59111],176:[0,.69444,0,0,.94888],184:[.17014,0,0,0,.53222],198:[0,.68611,.11431,0,1.02277],216:[.04861,.73472,.09062,0,.88555],223:[.19444,.69444,.09736,0,.665],230:[0,.44444,.085,0,.82666],248:[.09722,.54167,.09458,0,.59111],305:[0,.44444,.09426,0,.35555],338:[0,.68611,.11431,0,1.14054],339:[0,.44444,.085,0,.82666],567:[.19444,.44444,.04611,0,.385],710:[0,.69444,.06709,0,.59111],711:[0,.63194,.08271,0,.59111],713:[0,.59444,.10444,0,.59111],714:[0,.69444,.08528,0,.59111],715:[0,.69444,0,0,.59111],728:[0,.69444,.10333,0,.59111],729:[0,.69444,.12945,0,.35555],730:[0,.69444,0,0,.94888],732:[0,.69444,.11472,0,.59111],733:[0,.69444,.11472,0,.59111],915:[0,.68611,.12903,0,.69777],916:[0,.68611,0,0,.94444],920:[0,.68611,.09062,0,.88555],923:[0,.68611,0,0,.80666],926:[0,.68611,.15092,0,.76777],928:[0,.68611,.17208,0,.8961],931:[0,.68611,.11431,0,.82666],933:[0,.68611,.10778,0,.88555],934:[0,.68611,.05632,0,.82666],936:[0,.68611,.10778,0,.88555],937:[0,.68611,.0992,0,.82666],8211:[0,.44444,.09811,0,.59111],8212:[0,.44444,.09811,0,1.18221],8216:[0,.69444,.12945,0,.35555],8217:[0,.69444,.12945,0,.35555],8220:[0,.69444,.16772,0,.62055],8221:[0,.69444,.07939,0,.62055]},"Main-Italic":{32:[0,0,0,0,.25],33:[0,.69444,.12417,0,.30667],34:[0,.69444,.06961,0,.51444],35:[.19444,.69444,.06616,0,.81777],37:[.05556,.75,.13639,0,.81777],38:[0,.69444,.09694,0,.76666],39:[0,.69444,.12417,0,.30667],40:[.25,.75,.16194,0,.40889],41:[.25,.75,.03694,0,.40889],42:[0,.75,.14917,0,.51111],43:[.05667,.56167,.03694,0,.76666],44:[.19444,.10556,0,0,.30667],45:[0,.43056,.02826,0,.35778],46:[0,.10556,0,0,.30667],47:[.25,.75,.16194,0,.51111],48:[0,.64444,.13556,0,.51111],49:[0,.64444,.13556,0,.51111],50:[0,.64444,.13556,0,.51111],51:[0,.64444,.13556,0,.51111],52:[.19444,.64444,.13556,0,.51111],53:[0,.64444,.13556,0,.51111],54:[0,.64444,.13556,0,.51111],55:[.19444,.64444,.13556,0,.51111],56:[0,.64444,.13556,0,.51111],57:[0,.64444,.13556,0,.51111],58:[0,.43056,.0582,0,.30667],59:[.19444,.43056,.0582,0,.30667],61:[-.13313,.36687,.06616,0,.76666],63:[0,.69444,.1225,0,.51111],64:[0,.69444,.09597,0,.76666],65:[0,.68333,0,0,.74333],66:[0,.68333,.10257,0,.70389],67:[0,.68333,.14528,0,.71555],68:[0,.68333,.09403,0,.755],69:[0,.68333,.12028,0,.67833],70:[0,.68333,.13305,0,.65277],71:[0,.68333,.08722,0,.77361],72:[0,.68333,.16389,0,.74333],73:[0,.68333,.15806,0,.38555],74:[0,.68333,.14028,0,.525],75:[0,.68333,.14528,0,.76888],76:[0,.68333,0,0,.62722],77:[0,.68333,.16389,0,.89666],78:[0,.68333,.16389,0,.74333],79:[0,.68333,.09403,0,.76666],80:[0,.68333,.10257,0,.67833],81:[.19444,.68333,.09403,0,.76666],82:[0,.68333,.03868,0,.72944],83:[0,.68333,.11972,0,.56222],84:[0,.68333,.13305,0,.71555],85:[0,.68333,.16389,0,.74333],86:[0,.68333,.18361,0,.74333],87:[0,.68333,.18361,0,.99888],88:[0,.68333,.15806,0,.74333],89:[0,.68333,.19383,0,.74333],90:[0,.68333,.14528,0,.61333],91:[.25,.75,.1875,0,.30667],93:[.25,.75,.10528,0,.30667],94:[0,.69444,.06646,0,.51111],95:[.31,.12056,.09208,0,.51111],97:[0,.43056,.07671,0,.51111],98:[0,.69444,.06312,0,.46],99:[0,.43056,.05653,0,.46],100:[0,.69444,.10333,0,.51111],101:[0,.43056,.07514,0,.46],102:[.19444,.69444,.21194,0,.30667],103:[.19444,.43056,.08847,0,.46],104:[0,.69444,.07671,0,.51111],105:[0,.65536,.1019,0,.30667],106:[.19444,.65536,.14467,0,.30667],107:[0,.69444,.10764,0,.46],108:[0,.69444,.10333,0,.25555],109:[0,.43056,.07671,0,.81777],110:[0,.43056,.07671,0,.56222],111:[0,.43056,.06312,0,.51111],112:[.19444,.43056,.06312,0,.51111],113:[.19444,.43056,.08847,0,.46],114:[0,.43056,.10764,0,.42166],115:[0,.43056,.08208,0,.40889],116:[0,.61508,.09486,0,.33222],117:[0,.43056,.07671,0,.53666],118:[0,.43056,.10764,0,.46],119:[0,.43056,.10764,0,.66444],120:[0,.43056,.12042,0,.46389],121:[.19444,.43056,.08847,0,.48555],122:[0,.43056,.12292,0,.40889],126:[.35,.31786,.11585,0,.51111],160:[0,0,0,0,.25],168:[0,.66786,.10474,0,.51111],176:[0,.69444,0,0,.83129],184:[.17014,0,0,0,.46],198:[0,.68333,.12028,0,.88277],216:[.04861,.73194,.09403,0,.76666],223:[.19444,.69444,.10514,0,.53666],230:[0,.43056,.07514,0,.71555],248:[.09722,.52778,.09194,0,.51111],338:[0,.68333,.12028,0,.98499],339:[0,.43056,.07514,0,.71555],710:[0,.69444,.06646,0,.51111],711:[0,.62847,.08295,0,.51111],713:[0,.56167,.10333,0,.51111],714:[0,.69444,.09694,0,.51111],715:[0,.69444,0,0,.51111],728:[0,.69444,.10806,0,.51111],729:[0,.66786,.11752,0,.30667],730:[0,.69444,0,0,.83129],732:[0,.66786,.11585,0,.51111],733:[0,.69444,.1225,0,.51111],915:[0,.68333,.13305,0,.62722],916:[0,.68333,0,0,.81777],920:[0,.68333,.09403,0,.76666],923:[0,.68333,0,0,.69222],926:[0,.68333,.15294,0,.66444],928:[0,.68333,.16389,0,.74333],931:[0,.68333,.12028,0,.71555],933:[0,.68333,.11111,0,.76666],934:[0,.68333,.05986,0,.71555],936:[0,.68333,.11111,0,.76666],937:[0,.68333,.10257,0,.71555],8211:[0,.43056,.09208,0,.51111],8212:[0,.43056,.09208,0,1.02222],8216:[0,.69444,.12417,0,.30667],8217:[0,.69444,.12417,0,.30667],8220:[0,.69444,.1685,0,.51444],8221:[0,.69444,.06961,0,.51444],8463:[0,.68889,0,0,.54028]},"Main-Regular":{32:[0,0,0,0,.25],33:[0,.69444,0,0,.27778],34:[0,.69444,0,0,.5],35:[.19444,.69444,0,0,.83334],36:[.05556,.75,0,0,.5],37:[.05556,.75,0,0,.83334],38:[0,.69444,0,0,.77778],39:[0,.69444,0,0,.27778],40:[.25,.75,0,0,.38889],41:[.25,.75,0,0,.38889],42:[0,.75,0,0,.5],43:[.08333,.58333,0,0,.77778],44:[.19444,.10556,0,0,.27778],45:[0,.43056,0,0,.33333],46:[0,.10556,0,0,.27778],47:[.25,.75,0,0,.5],48:[0,.64444,0,0,.5],49:[0,.64444,0,0,.5],50:[0,.64444,0,0,.5],51:[0,.64444,0,0,.5],52:[0,.64444,0,0,.5],53:[0,.64444,0,0,.5],54:[0,.64444,0,0,.5],55:[0,.64444,0,0,.5],56:[0,.64444,0,0,.5],57:[0,.64444,0,0,.5],58:[0,.43056,0,0,.27778],59:[.19444,.43056,0,0,.27778],60:[.0391,.5391,0,0,.77778],61:[-.13313,.36687,0,0,.77778],62:[.0391,.5391,0,0,.77778],63:[0,.69444,0,0,.47222],64:[0,.69444,0,0,.77778],65:[0,.68333,0,0,.75],66:[0,.68333,0,0,.70834],67:[0,.68333,0,0,.72222],68:[0,.68333,0,0,.76389],69:[0,.68333,0,0,.68056],70:[0,.68333,0,0,.65278],71:[0,.68333,0,0,.78472],72:[0,.68333,0,0,.75],73:[0,.68333,0,0,.36111],74:[0,.68333,0,0,.51389],75:[0,.68333,0,0,.77778],76:[0,.68333,0,0,.625],77:[0,.68333,0,0,.91667],78:[0,.68333,0,0,.75],79:[0,.68333,0,0,.77778],80:[0,.68333,0,0,.68056],81:[.19444,.68333,0,0,.77778],82:[0,.68333,0,0,.73611],83:[0,.68333,0,0,.55556],84:[0,.68333,0,0,.72222],85:[0,.68333,0,0,.75],86:[0,.68333,.01389,0,.75],87:[0,.68333,.01389,0,1.02778],88:[0,.68333,0,0,.75],89:[0,.68333,.025,0,.75],90:[0,.68333,0,0,.61111],91:[.25,.75,0,0,.27778],92:[.25,.75,0,0,.5],93:[.25,.75,0,0,.27778],94:[0,.69444,0,0,.5],95:[.31,.12056,.02778,0,.5],97:[0,.43056,0,0,.5],98:[0,.69444,0,0,.55556],99:[0,.43056,0,0,.44445],100:[0,.69444,0,0,.55556],101:[0,.43056,0,0,.44445],102:[0,.69444,.07778,0,.30556],103:[.19444,.43056,.01389,0,.5],104:[0,.69444,0,0,.55556],105:[0,.66786,0,0,.27778],106:[.19444,.66786,0,0,.30556],107:[0,.69444,0,0,.52778],108:[0,.69444,0,0,.27778],109:[0,.43056,0,0,.83334],110:[0,.43056,0,0,.55556],111:[0,.43056,0,0,.5],112:[.19444,.43056,0,0,.55556],113:[.19444,.43056,0,0,.52778],114:[0,.43056,0,0,.39167],115:[0,.43056,0,0,.39445],116:[0,.61508,0,0,.38889],117:[0,.43056,0,0,.55556],118:[0,.43056,.01389,0,.52778],119:[0,.43056,.01389,0,.72222],120:[0,.43056,0,0,.52778],121:[.19444,.43056,.01389,0,.52778],122:[0,.43056,0,0,.44445],123:[.25,.75,0,0,.5],124:[.25,.75,0,0,.27778],125:[.25,.75,0,0,.5],126:[.35,.31786,0,0,.5],160:[0,0,0,0,.25],163:[0,.69444,0,0,.76909],167:[.19444,.69444,0,0,.44445],168:[0,.66786,0,0,.5],172:[0,.43056,0,0,.66667],176:[0,.69444,0,0,.75],177:[.08333,.58333,0,0,.77778],182:[.19444,.69444,0,0,.61111],184:[.17014,0,0,0,.44445],198:[0,.68333,0,0,.90278],215:[.08333,.58333,0,0,.77778],216:[.04861,.73194,0,0,.77778],223:[0,.69444,0,0,.5],230:[0,.43056,0,0,.72222],247:[.08333,.58333,0,0,.77778],248:[.09722,.52778,0,0,.5],305:[0,.43056,0,0,.27778],338:[0,.68333,0,0,1.01389],339:[0,.43056,0,0,.77778],567:[.19444,.43056,0,0,.30556],710:[0,.69444,0,0,.5],711:[0,.62847,0,0,.5],713:[0,.56778,0,0,.5],714:[0,.69444,0,0,.5],715:[0,.69444,0,0,.5],728:[0,.69444,0,0,.5],729:[0,.66786,0,0,.27778],730:[0,.69444,0,0,.75],732:[0,.66786,0,0,.5],733:[0,.69444,0,0,.5],915:[0,.68333,0,0,.625],916:[0,.68333,0,0,.83334],920:[0,.68333,0,0,.77778],923:[0,.68333,0,0,.69445],926:[0,.68333,0,0,.66667],928:[0,.68333,0,0,.75],931:[0,.68333,0,0,.72222],933:[0,.68333,0,0,.77778],934:[0,.68333,0,0,.72222],936:[0,.68333,0,0,.77778],937:[0,.68333,0,0,.72222],8211:[0,.43056,.02778,0,.5],8212:[0,.43056,.02778,0,1],8216:[0,.69444,0,0,.27778],8217:[0,.69444,0,0,.27778],8220:[0,.69444,0,0,.5],8221:[0,.69444,0,0,.5],8224:[.19444,.69444,0,0,.44445],8225:[.19444,.69444,0,0,.44445],8230:[0,.123,0,0,1.172],8242:[0,.55556,0,0,.275],8407:[0,.71444,.15382,0,.5],8463:[0,.68889,0,0,.54028],8465:[0,.69444,0,0,.72222],8467:[0,.69444,0,.11111,.41667],8472:[.19444,.43056,0,.11111,.63646],8476:[0,.69444,0,0,.72222],8501:[0,.69444,0,0,.61111],8592:[-.13313,.36687,0,0,1],8593:[.19444,.69444,0,0,.5],8594:[-.13313,.36687,0,0,1],8595:[.19444,.69444,0,0,.5],8596:[-.13313,.36687,0,0,1],8597:[.25,.75,0,0,.5],8598:[.19444,.69444,0,0,1],8599:[.19444,.69444,0,0,1],8600:[.19444,.69444,0,0,1],8601:[.19444,.69444,0,0,1],8614:[.011,.511,0,0,1],8617:[.011,.511,0,0,1.126],8618:[.011,.511,0,0,1.126],8636:[-.13313,.36687,0,0,1],8637:[-.13313,.36687,0,0,1],8640:[-.13313,.36687,0,0,1],8641:[-.13313,.36687,0,0,1],8652:[.011,.671,0,0,1],8656:[-.13313,.36687,0,0,1],8657:[.19444,.69444,0,0,.61111],8658:[-.13313,.36687,0,0,1],8659:[.19444,.69444,0,0,.61111],8660:[-.13313,.36687,0,0,1],8661:[.25,.75,0,0,.61111],8704:[0,.69444,0,0,.55556],8706:[0,.69444,.05556,.08334,.5309],8707:[0,.69444,0,0,.55556],8709:[.05556,.75,0,0,.5],8711:[0,.68333,0,0,.83334],8712:[.0391,.5391,0,0,.66667],8715:[.0391,.5391,0,0,.66667],8722:[.08333,.58333,0,0,.77778],8723:[.08333,.58333,0,0,.77778],8725:[.25,.75,0,0,.5],8726:[.25,.75,0,0,.5],8727:[-.03472,.46528,0,0,.5],8728:[-.05555,.44445,0,0,.5],8729:[-.05555,.44445,0,0,.5],8730:[.2,.8,0,0,.83334],8733:[0,.43056,0,0,.77778],8734:[0,.43056,0,0,1],8736:[0,.69224,0,0,.72222],8739:[.25,.75,0,0,.27778],8741:[.25,.75,0,0,.5],8743:[0,.55556,0,0,.66667],8744:[0,.55556,0,0,.66667],8745:[0,.55556,0,0,.66667],8746:[0,.55556,0,0,.66667],8747:[.19444,.69444,.11111,0,.41667],8764:[-.13313,.36687,0,0,.77778],8768:[.19444,.69444,0,0,.27778],8771:[-.03625,.46375,0,0,.77778],8773:[-.022,.589,0,0,.778],8776:[-.01688,.48312,0,0,.77778],8781:[-.03625,.46375,0,0,.77778],8784:[-.133,.673,0,0,.778],8801:[-.03625,.46375,0,0,.77778],8804:[.13597,.63597,0,0,.77778],8805:[.13597,.63597,0,0,.77778],8810:[.0391,.5391,0,0,1],8811:[.0391,.5391,0,0,1],8826:[.0391,.5391,0,0,.77778],8827:[.0391,.5391,0,0,.77778],8834:[.0391,.5391,0,0,.77778],8835:[.0391,.5391,0,0,.77778],8838:[.13597,.63597,0,0,.77778],8839:[.13597,.63597,0,0,.77778],8846:[0,.55556,0,0,.66667],8849:[.13597,.63597,0,0,.77778],8850:[.13597,.63597,0,0,.77778],8851:[0,.55556,0,0,.66667],8852:[0,.55556,0,0,.66667],8853:[.08333,.58333,0,0,.77778],8854:[.08333,.58333,0,0,.77778],8855:[.08333,.58333,0,0,.77778],8856:[.08333,.58333,0,0,.77778],8857:[.08333,.58333,0,0,.77778],8866:[0,.69444,0,0,.61111],8867:[0,.69444,0,0,.61111],8868:[0,.69444,0,0,.77778],8869:[0,.69444,0,0,.77778],8872:[.249,.75,0,0,.867],8900:[-.05555,.44445,0,0,.5],8901:[-.05555,.44445,0,0,.27778],8902:[-.03472,.46528,0,0,.5],8904:[.005,.505,0,0,.9],8942:[.03,.903,0,0,.278],8943:[-.19,.313,0,0,1.172],8945:[-.1,.823,0,0,1.282],8968:[.25,.75,0,0,.44445],8969:[.25,.75,0,0,.44445],8970:[.25,.75,0,0,.44445],8971:[.25,.75,0,0,.44445],8994:[-.14236,.35764,0,0,1],8995:[-.14236,.35764,0,0,1],9136:[.244,.744,0,0,.412],9137:[.244,.745,0,0,.412],9651:[.19444,.69444,0,0,.88889],9657:[-.03472,.46528,0,0,.5],9661:[.19444,.69444,0,0,.88889],9667:[-.03472,.46528,0,0,.5],9711:[.19444,.69444,0,0,1],9824:[.12963,.69444,0,0,.77778],9825:[.12963,.69444,0,0,.77778],9826:[.12963,.69444,0,0,.77778],9827:[.12963,.69444,0,0,.77778],9837:[0,.75,0,0,.38889],9838:[.19444,.69444,0,0,.38889],9839:[.19444,.69444,0,0,.38889],10216:[.25,.75,0,0,.38889],10217:[.25,.75,0,0,.38889],10222:[.244,.744,0,0,.412],10223:[.244,.745,0,0,.412],10229:[.011,.511,0,0,1.609],10230:[.011,.511,0,0,1.638],10231:[.011,.511,0,0,1.859],10232:[.024,.525,0,0,1.609],10233:[.024,.525,0,0,1.638],10234:[.024,.525,0,0,1.858],10236:[.011,.511,0,0,1.638],10815:[0,.68333,0,0,.75],10927:[.13597,.63597,0,0,.77778],10928:[.13597,.63597,0,0,.77778],57376:[.19444,.69444,0,0,0]},"Math-BoldItalic":{32:[0,0,0,0,.25],48:[0,.44444,0,0,.575],49:[0,.44444,0,0,.575],50:[0,.44444,0,0,.575],51:[.19444,.44444,0,0,.575],52:[.19444,.44444,0,0,.575],53:[.19444,.44444,0,0,.575],54:[0,.64444,0,0,.575],55:[.19444,.44444,0,0,.575],56:[0,.64444,0,0,.575],57:[.19444,.44444,0,0,.575],65:[0,.68611,0,0,.86944],66:[0,.68611,.04835,0,.8664],67:[0,.68611,.06979,0,.81694],68:[0,.68611,.03194,0,.93812],69:[0,.68611,.05451,0,.81007],70:[0,.68611,.15972,0,.68889],71:[0,.68611,0,0,.88673],72:[0,.68611,.08229,0,.98229],73:[0,.68611,.07778,0,.51111],74:[0,.68611,.10069,0,.63125],75:[0,.68611,.06979,0,.97118],76:[0,.68611,0,0,.75555],77:[0,.68611,.11424,0,1.14201],78:[0,.68611,.11424,0,.95034],79:[0,.68611,.03194,0,.83666],80:[0,.68611,.15972,0,.72309],81:[.19444,.68611,0,0,.86861],82:[0,.68611,.00421,0,.87235],83:[0,.68611,.05382,0,.69271],84:[0,.68611,.15972,0,.63663],85:[0,.68611,.11424,0,.80027],86:[0,.68611,.25555,0,.67778],87:[0,.68611,.15972,0,1.09305],88:[0,.68611,.07778,0,.94722],89:[0,.68611,.25555,0,.67458],90:[0,.68611,.06979,0,.77257],97:[0,.44444,0,0,.63287],98:[0,.69444,0,0,.52083],99:[0,.44444,0,0,.51342],100:[0,.69444,0,0,.60972],101:[0,.44444,0,0,.55361],102:[.19444,.69444,.11042,0,.56806],103:[.19444,.44444,.03704,0,.5449],104:[0,.69444,0,0,.66759],105:[0,.69326,0,0,.4048],106:[.19444,.69326,.0622,0,.47083],107:[0,.69444,.01852,0,.6037],108:[0,.69444,.0088,0,.34815],109:[0,.44444,0,0,1.0324],110:[0,.44444,0,0,.71296],111:[0,.44444,0,0,.58472],112:[.19444,.44444,0,0,.60092],113:[.19444,.44444,.03704,0,.54213],114:[0,.44444,.03194,0,.5287],115:[0,.44444,0,0,.53125],116:[0,.63492,0,0,.41528],117:[0,.44444,0,0,.68102],118:[0,.44444,.03704,0,.56666],119:[0,.44444,.02778,0,.83148],120:[0,.44444,0,0,.65903],121:[.19444,.44444,.03704,0,.59028],122:[0,.44444,.04213,0,.55509],160:[0,0,0,0,.25],915:[0,.68611,.15972,0,.65694],916:[0,.68611,0,0,.95833],920:[0,.68611,.03194,0,.86722],923:[0,.68611,0,0,.80555],926:[0,.68611,.07458,0,.84125],928:[0,.68611,.08229,0,.98229],931:[0,.68611,.05451,0,.88507],933:[0,.68611,.15972,0,.67083],934:[0,.68611,0,0,.76666],936:[0,.68611,.11653,0,.71402],937:[0,.68611,.04835,0,.8789],945:[0,.44444,0,0,.76064],946:[.19444,.69444,.03403,0,.65972],947:[.19444,.44444,.06389,0,.59003],948:[0,.69444,.03819,0,.52222],949:[0,.44444,0,0,.52882],950:[.19444,.69444,.06215,0,.50833],951:[.19444,.44444,.03704,0,.6],952:[0,.69444,.03194,0,.5618],953:[0,.44444,0,0,.41204],954:[0,.44444,0,0,.66759],955:[0,.69444,0,0,.67083],956:[.19444,.44444,0,0,.70787],957:[0,.44444,.06898,0,.57685],958:[.19444,.69444,.03021,0,.50833],959:[0,.44444,0,0,.58472],960:[0,.44444,.03704,0,.68241],961:[.19444,.44444,0,0,.6118],962:[.09722,.44444,.07917,0,.42361],963:[0,.44444,.03704,0,.68588],964:[0,.44444,.13472,0,.52083],965:[0,.44444,.03704,0,.63055],966:[.19444,.44444,0,0,.74722],967:[.19444,.44444,0,0,.71805],968:[.19444,.69444,.03704,0,.75833],969:[0,.44444,.03704,0,.71782],977:[0,.69444,0,0,.69155],981:[.19444,.69444,0,0,.7125],982:[0,.44444,.03194,0,.975],1009:[.19444,.44444,0,0,.6118],1013:[0,.44444,0,0,.48333],57649:[0,.44444,0,0,.39352],57911:[.19444,.44444,0,0,.43889]},"Math-Italic":{32:[0,0,0,0,.25],48:[0,.43056,0,0,.5],49:[0,.43056,0,0,.5],50:[0,.43056,0,0,.5],51:[.19444,.43056,0,0,.5],52:[.19444,.43056,0,0,.5],53:[.19444,.43056,0,0,.5],54:[0,.64444,0,0,.5],55:[.19444,.43056,0,0,.5],56:[0,.64444,0,0,.5],57:[.19444,.43056,0,0,.5],65:[0,.68333,0,.13889,.75],66:[0,.68333,.05017,.08334,.75851],67:[0,.68333,.07153,.08334,.71472],68:[0,.68333,.02778,.05556,.82792],69:[0,.68333,.05764,.08334,.7382],70:[0,.68333,.13889,.08334,.64306],71:[0,.68333,0,.08334,.78625],72:[0,.68333,.08125,.05556,.83125],73:[0,.68333,.07847,.11111,.43958],74:[0,.68333,.09618,.16667,.55451],75:[0,.68333,.07153,.05556,.84931],76:[0,.68333,0,.02778,.68056],77:[0,.68333,.10903,.08334,.97014],78:[0,.68333,.10903,.08334,.80347],79:[0,.68333,.02778,.08334,.76278],80:[0,.68333,.13889,.08334,.64201],81:[.19444,.68333,0,.08334,.79056],82:[0,.68333,.00773,.08334,.75929],83:[0,.68333,.05764,.08334,.6132],84:[0,.68333,.13889,.08334,.58438],85:[0,.68333,.10903,.02778,.68278],86:[0,.68333,.22222,0,.58333],87:[0,.68333,.13889,0,.94445],88:[0,.68333,.07847,.08334,.82847],89:[0,.68333,.22222,0,.58056],90:[0,.68333,.07153,.08334,.68264],97:[0,.43056,0,0,.52859],98:[0,.69444,0,0,.42917],99:[0,.43056,0,.05556,.43276],100:[0,.69444,0,.16667,.52049],101:[0,.43056,0,.05556,.46563],102:[.19444,.69444,.10764,.16667,.48959],103:[.19444,.43056,.03588,.02778,.47697],104:[0,.69444,0,0,.57616],105:[0,.65952,0,0,.34451],106:[.19444,.65952,.05724,0,.41181],107:[0,.69444,.03148,0,.5206],108:[0,.69444,.01968,.08334,.29838],109:[0,.43056,0,0,.87801],110:[0,.43056,0,0,.60023],111:[0,.43056,0,.05556,.48472],112:[.19444,.43056,0,.08334,.50313],113:[.19444,.43056,.03588,.08334,.44641],114:[0,.43056,.02778,.05556,.45116],115:[0,.43056,0,.05556,.46875],116:[0,.61508,0,.08334,.36111],117:[0,.43056,0,.02778,.57246],118:[0,.43056,.03588,.02778,.48472],119:[0,.43056,.02691,.08334,.71592],120:[0,.43056,0,.02778,.57153],121:[.19444,.43056,.03588,.05556,.49028],122:[0,.43056,.04398,.05556,.46505],160:[0,0,0,0,.25],915:[0,.68333,.13889,.08334,.61528],916:[0,.68333,0,.16667,.83334],920:[0,.68333,.02778,.08334,.76278],923:[0,.68333,0,.16667,.69445],926:[0,.68333,.07569,.08334,.74236],928:[0,.68333,.08125,.05556,.83125],931:[0,.68333,.05764,.08334,.77986],933:[0,.68333,.13889,.05556,.58333],934:[0,.68333,0,.08334,.66667],936:[0,.68333,.11,.05556,.61222],937:[0,.68333,.05017,.08334,.7724],945:[0,.43056,.0037,.02778,.6397],946:[.19444,.69444,.05278,.08334,.56563],947:[.19444,.43056,.05556,0,.51773],948:[0,.69444,.03785,.05556,.44444],949:[0,.43056,0,.08334,.46632],950:[.19444,.69444,.07378,.08334,.4375],951:[.19444,.43056,.03588,.05556,.49653],952:[0,.69444,.02778,.08334,.46944],953:[0,.43056,0,.05556,.35394],954:[0,.43056,0,0,.57616],955:[0,.69444,0,0,.58334],956:[.19444,.43056,0,.02778,.60255],957:[0,.43056,.06366,.02778,.49398],958:[.19444,.69444,.04601,.11111,.4375],959:[0,.43056,0,.05556,.48472],960:[0,.43056,.03588,0,.57003],961:[.19444,.43056,0,.08334,.51702],962:[.09722,.43056,.07986,.08334,.36285],963:[0,.43056,.03588,0,.57141],964:[0,.43056,.1132,.02778,.43715],965:[0,.43056,.03588,.02778,.54028],966:[.19444,.43056,0,.08334,.65417],967:[.19444,.43056,0,.05556,.62569],968:[.19444,.69444,.03588,.11111,.65139],969:[0,.43056,.03588,0,.62245],977:[0,.69444,0,.08334,.59144],981:[.19444,.69444,0,.08334,.59583],982:[0,.43056,.02778,0,.82813],1009:[.19444,.43056,0,.08334,.51702],1013:[0,.43056,0,.05556,.4059],57649:[0,.43056,0,.02778,.32246],57911:[.19444,.43056,0,.08334,.38403]},"SansSerif-Bold":{32:[0,0,0,0,.25],33:[0,.69444,0,0,.36667],34:[0,.69444,0,0,.55834],35:[.19444,.69444,0,0,.91667],36:[.05556,.75,0,0,.55],37:[.05556,.75,0,0,1.02912],38:[0,.69444,0,0,.83056],39:[0,.69444,0,0,.30556],40:[.25,.75,0,0,.42778],41:[.25,.75,0,0,.42778],42:[0,.75,0,0,.55],43:[.11667,.61667,0,0,.85556],44:[.10556,.13056,0,0,.30556],45:[0,.45833,0,0,.36667],46:[0,.13056,0,0,.30556],47:[.25,.75,0,0,.55],48:[0,.69444,0,0,.55],49:[0,.69444,0,0,.55],50:[0,.69444,0,0,.55],51:[0,.69444,0,0,.55],52:[0,.69444,0,0,.55],53:[0,.69444,0,0,.55],54:[0,.69444,0,0,.55],55:[0,.69444,0,0,.55],56:[0,.69444,0,0,.55],57:[0,.69444,0,0,.55],58:[0,.45833,0,0,.30556],59:[.10556,.45833,0,0,.30556],61:[-.09375,.40625,0,0,.85556],63:[0,.69444,0,0,.51945],64:[0,.69444,0,0,.73334],65:[0,.69444,0,0,.73334],66:[0,.69444,0,0,.73334],67:[0,.69444,0,0,.70278],68:[0,.69444,0,0,.79445],69:[0,.69444,0,0,.64167],70:[0,.69444,0,0,.61111],71:[0,.69444,0,0,.73334],72:[0,.69444,0,0,.79445],73:[0,.69444,0,0,.33056],74:[0,.69444,0,0,.51945],75:[0,.69444,0,0,.76389],76:[0,.69444,0,0,.58056],77:[0,.69444,0,0,.97778],78:[0,.69444,0,0,.79445],79:[0,.69444,0,0,.79445],80:[0,.69444,0,0,.70278],81:[.10556,.69444,0,0,.79445],82:[0,.69444,0,0,.70278],83:[0,.69444,0,0,.61111],84:[0,.69444,0,0,.73334],85:[0,.69444,0,0,.76389],86:[0,.69444,.01528,0,.73334],87:[0,.69444,.01528,0,1.03889],88:[0,.69444,0,0,.73334],89:[0,.69444,.0275,0,.73334],90:[0,.69444,0,0,.67223],91:[.25,.75,0,0,.34306],93:[.25,.75,0,0,.34306],94:[0,.69444,0,0,.55],95:[.35,.10833,.03056,0,.55],97:[0,.45833,0,0,.525],98:[0,.69444,0,0,.56111],99:[0,.45833,0,0,.48889],100:[0,.69444,0,0,.56111],101:[0,.45833,0,0,.51111],102:[0,.69444,.07639,0,.33611],103:[.19444,.45833,.01528,0,.55],104:[0,.69444,0,0,.56111],105:[0,.69444,0,0,.25556],106:[.19444,.69444,0,0,.28611],107:[0,.69444,0,0,.53056],108:[0,.69444,0,0,.25556],109:[0,.45833,0,0,.86667],110:[0,.45833,0,0,.56111],111:[0,.45833,0,0,.55],112:[.19444,.45833,0,0,.56111],113:[.19444,.45833,0,0,.56111],114:[0,.45833,.01528,0,.37222],115:[0,.45833,0,0,.42167],116:[0,.58929,0,0,.40417],117:[0,.45833,0,0,.56111],118:[0,.45833,.01528,0,.5],119:[0,.45833,.01528,0,.74445],120:[0,.45833,0,0,.5],121:[.19444,.45833,.01528,0,.5],122:[0,.45833,0,0,.47639],126:[.35,.34444,0,0,.55],160:[0,0,0,0,.25],168:[0,.69444,0,0,.55],176:[0,.69444,0,0,.73334],180:[0,.69444,0,0,.55],184:[.17014,0,0,0,.48889],305:[0,.45833,0,0,.25556],567:[.19444,.45833,0,0,.28611],710:[0,.69444,0,0,.55],711:[0,.63542,0,0,.55],713:[0,.63778,0,0,.55],728:[0,.69444,0,0,.55],729:[0,.69444,0,0,.30556],730:[0,.69444,0,0,.73334],732:[0,.69444,0,0,.55],733:[0,.69444,0,0,.55],915:[0,.69444,0,0,.58056],916:[0,.69444,0,0,.91667],920:[0,.69444,0,0,.85556],923:[0,.69444,0,0,.67223],926:[0,.69444,0,0,.73334],928:[0,.69444,0,0,.79445],931:[0,.69444,0,0,.79445],933:[0,.69444,0,0,.85556],934:[0,.69444,0,0,.79445],936:[0,.69444,0,0,.85556],937:[0,.69444,0,0,.79445],8211:[0,.45833,.03056,0,.55],8212:[0,.45833,.03056,0,1.10001],8216:[0,.69444,0,0,.30556],8217:[0,.69444,0,0,.30556],8220:[0,.69444,0,0,.55834],8221:[0,.69444,0,0,.55834]},"SansSerif-Italic":{32:[0,0,0,0,.25],33:[0,.69444,.05733,0,.31945],34:[0,.69444,.00316,0,.5],35:[.19444,.69444,.05087,0,.83334],36:[.05556,.75,.11156,0,.5],37:[.05556,.75,.03126,0,.83334],38:[0,.69444,.03058,0,.75834],39:[0,.69444,.07816,0,.27778],40:[.25,.75,.13164,0,.38889],41:[.25,.75,.02536,0,.38889],42:[0,.75,.11775,0,.5],43:[.08333,.58333,.02536,0,.77778],44:[.125,.08333,0,0,.27778],45:[0,.44444,.01946,0,.33333],46:[0,.08333,0,0,.27778],47:[.25,.75,.13164,0,.5],48:[0,.65556,.11156,0,.5],49:[0,.65556,.11156,0,.5],50:[0,.65556,.11156,0,.5],51:[0,.65556,.11156,0,.5],52:[0,.65556,.11156,0,.5],53:[0,.65556,.11156,0,.5],54:[0,.65556,.11156,0,.5],55:[0,.65556,.11156,0,.5],56:[0,.65556,.11156,0,.5],57:[0,.65556,.11156,0,.5],58:[0,.44444,.02502,0,.27778],59:[.125,.44444,.02502,0,.27778],61:[-.13,.37,.05087,0,.77778],63:[0,.69444,.11809,0,.47222],64:[0,.69444,.07555,0,.66667],65:[0,.69444,0,0,.66667],66:[0,.69444,.08293,0,.66667],67:[0,.69444,.11983,0,.63889],68:[0,.69444,.07555,0,.72223],69:[0,.69444,.11983,0,.59722],70:[0,.69444,.13372,0,.56945],71:[0,.69444,.11983,0,.66667],72:[0,.69444,.08094,0,.70834],73:[0,.69444,.13372,0,.27778],74:[0,.69444,.08094,0,.47222],75:[0,.69444,.11983,0,.69445],76:[0,.69444,0,0,.54167],77:[0,.69444,.08094,0,.875],78:[0,.69444,.08094,0,.70834],79:[0,.69444,.07555,0,.73611],80:[0,.69444,.08293,0,.63889],81:[.125,.69444,.07555,0,.73611],82:[0,.69444,.08293,0,.64584],83:[0,.69444,.09205,0,.55556],84:[0,.69444,.13372,0,.68056],85:[0,.69444,.08094,0,.6875],86:[0,.69444,.1615,0,.66667],87:[0,.69444,.1615,0,.94445],88:[0,.69444,.13372,0,.66667],89:[0,.69444,.17261,0,.66667],90:[0,.69444,.11983,0,.61111],91:[.25,.75,.15942,0,.28889],93:[.25,.75,.08719,0,.28889],94:[0,.69444,.0799,0,.5],95:[.35,.09444,.08616,0,.5],97:[0,.44444,.00981,0,.48056],98:[0,.69444,.03057,0,.51667],99:[0,.44444,.08336,0,.44445],100:[0,.69444,.09483,0,.51667],101:[0,.44444,.06778,0,.44445],102:[0,.69444,.21705,0,.30556],103:[.19444,.44444,.10836,0,.5],104:[0,.69444,.01778,0,.51667],105:[0,.67937,.09718,0,.23889],106:[.19444,.67937,.09162,0,.26667],107:[0,.69444,.08336,0,.48889],108:[0,.69444,.09483,0,.23889],109:[0,.44444,.01778,0,.79445],110:[0,.44444,.01778,0,.51667],111:[0,.44444,.06613,0,.5],112:[.19444,.44444,.0389,0,.51667],113:[.19444,.44444,.04169,0,.51667],114:[0,.44444,.10836,0,.34167],115:[0,.44444,.0778,0,.38333],116:[0,.57143,.07225,0,.36111],117:[0,.44444,.04169,0,.51667],118:[0,.44444,.10836,0,.46111],119:[0,.44444,.10836,0,.68334],120:[0,.44444,.09169,0,.46111],121:[.19444,.44444,.10836,0,.46111],122:[0,.44444,.08752,0,.43472],126:[.35,.32659,.08826,0,.5],160:[0,0,0,0,.25],168:[0,.67937,.06385,0,.5],176:[0,.69444,0,0,.73752],184:[.17014,0,0,0,.44445],305:[0,.44444,.04169,0,.23889],567:[.19444,.44444,.04169,0,.26667],710:[0,.69444,.0799,0,.5],711:[0,.63194,.08432,0,.5],713:[0,.60889,.08776,0,.5],714:[0,.69444,.09205,0,.5],715:[0,.69444,0,0,.5],728:[0,.69444,.09483,0,.5],729:[0,.67937,.07774,0,.27778],730:[0,.69444,0,0,.73752],732:[0,.67659,.08826,0,.5],733:[0,.69444,.09205,0,.5],915:[0,.69444,.13372,0,.54167],916:[0,.69444,0,0,.83334],920:[0,.69444,.07555,0,.77778],923:[0,.69444,0,0,.61111],926:[0,.69444,.12816,0,.66667],928:[0,.69444,.08094,0,.70834],931:[0,.69444,.11983,0,.72222],933:[0,.69444,.09031,0,.77778],934:[0,.69444,.04603,0,.72222],936:[0,.69444,.09031,0,.77778],937:[0,.69444,.08293,0,.72222],8211:[0,.44444,.08616,0,.5],8212:[0,.44444,.08616,0,1],8216:[0,.69444,.07816,0,.27778],8217:[0,.69444,.07816,0,.27778],8220:[0,.69444,.14205,0,.5],8221:[0,.69444,.00316,0,.5]},"SansSerif-Regular":{32:[0,0,0,0,.25],33:[0,.69444,0,0,.31945],34:[0,.69444,0,0,.5],35:[.19444,.69444,0,0,.83334],36:[.05556,.75,0,0,.5],37:[.05556,.75,0,0,.83334],38:[0,.69444,0,0,.75834],39:[0,.69444,0,0,.27778],40:[.25,.75,0,0,.38889],41:[.25,.75,0,0,.38889],42:[0,.75,0,0,.5],43:[.08333,.58333,0,0,.77778],44:[.125,.08333,0,0,.27778],45:[0,.44444,0,0,.33333],46:[0,.08333,0,0,.27778],47:[.25,.75,0,0,.5],48:[0,.65556,0,0,.5],49:[0,.65556,0,0,.5],50:[0,.65556,0,0,.5],51:[0,.65556,0,0,.5],52:[0,.65556,0,0,.5],53:[0,.65556,0,0,.5],54:[0,.65556,0,0,.5],55:[0,.65556,0,0,.5],56:[0,.65556,0,0,.5],57:[0,.65556,0,0,.5],58:[0,.44444,0,0,.27778],59:[.125,.44444,0,0,.27778],61:[-.13,.37,0,0,.77778],63:[0,.69444,0,0,.47222],64:[0,.69444,0,0,.66667],65:[0,.69444,0,0,.66667],66:[0,.69444,0,0,.66667],67:[0,.69444,0,0,.63889],68:[0,.69444,0,0,.72223],69:[0,.69444,0,0,.59722],70:[0,.69444,0,0,.56945],71:[0,.69444,0,0,.66667],72:[0,.69444,0,0,.70834],73:[0,.69444,0,0,.27778],74:[0,.69444,0,0,.47222],75:[0,.69444,0,0,.69445],76:[0,.69444,0,0,.54167],77:[0,.69444,0,0,.875],78:[0,.69444,0,0,.70834],79:[0,.69444,0,0,.73611],80:[0,.69444,0,0,.63889],81:[.125,.69444,0,0,.73611],82:[0,.69444,0,0,.64584],83:[0,.69444,0,0,.55556],84:[0,.69444,0,0,.68056],85:[0,.69444,0,0,.6875],86:[0,.69444,.01389,0,.66667],87:[0,.69444,.01389,0,.94445],88:[0,.69444,0,0,.66667],89:[0,.69444,.025,0,.66667],90:[0,.69444,0,0,.61111],91:[.25,.75,0,0,.28889],93:[.25,.75,0,0,.28889],94:[0,.69444,0,0,.5],95:[.35,.09444,.02778,0,.5],97:[0,.44444,0,0,.48056],98:[0,.69444,0,0,.51667],99:[0,.44444,0,0,.44445],100:[0,.69444,0,0,.51667],101:[0,.44444,0,0,.44445],102:[0,.69444,.06944,0,.30556],103:[.19444,.44444,.01389,0,.5],104:[0,.69444,0,0,.51667],105:[0,.67937,0,0,.23889],106:[.19444,.67937,0,0,.26667],107:[0,.69444,0,0,.48889],108:[0,.69444,0,0,.23889],109:[0,.44444,0,0,.79445],110:[0,.44444,0,0,.51667],111:[0,.44444,0,0,.5],112:[.19444,.44444,0,0,.51667],113:[.19444,.44444,0,0,.51667],114:[0,.44444,.01389,0,.34167],115:[0,.44444,0,0,.38333],116:[0,.57143,0,0,.36111],117:[0,.44444,0,0,.51667],118:[0,.44444,.01389,0,.46111],119:[0,.44444,.01389,0,.68334],120:[0,.44444,0,0,.46111],121:[.19444,.44444,.01389,0,.46111],122:[0,.44444,0,0,.43472],126:[.35,.32659,0,0,.5],160:[0,0,0,0,.25],168:[0,.67937,0,0,.5],176:[0,.69444,0,0,.66667],184:[.17014,0,0,0,.44445],305:[0,.44444,0,0,.23889],567:[.19444,.44444,0,0,.26667],710:[0,.69444,0,0,.5],711:[0,.63194,0,0,.5],713:[0,.60889,0,0,.5],714:[0,.69444,0,0,.5],715:[0,.69444,0,0,.5],728:[0,.69444,0,0,.5],729:[0,.67937,0,0,.27778],730:[0,.69444,0,0,.66667],732:[0,.67659,0,0,.5],733:[0,.69444,0,0,.5],915:[0,.69444,0,0,.54167],916:[0,.69444,0,0,.83334],920:[0,.69444,0,0,.77778],923:[0,.69444,0,0,.61111],926:[0,.69444,0,0,.66667],928:[0,.69444,0,0,.70834],931:[0,.69444,0,0,.72222],933:[0,.69444,0,0,.77778],934:[0,.69444,0,0,.72222],936:[0,.69444,0,0,.77778],937:[0,.69444,0,0,.72222],8211:[0,.44444,.02778,0,.5],8212:[0,.44444,.02778,0,1],8216:[0,.69444,0,0,.27778],8217:[0,.69444,0,0,.27778],8220:[0,.69444,0,0,.5],8221:[0,.69444,0,0,.5]},"Script-Regular":{32:[0,0,0,0,.25],65:[0,.7,.22925,0,.80253],66:[0,.7,.04087,0,.90757],67:[0,.7,.1689,0,.66619],68:[0,.7,.09371,0,.77443],69:[0,.7,.18583,0,.56162],70:[0,.7,.13634,0,.89544],71:[0,.7,.17322,0,.60961],72:[0,.7,.29694,0,.96919],73:[0,.7,.19189,0,.80907],74:[.27778,.7,.19189,0,1.05159],75:[0,.7,.31259,0,.91364],76:[0,.7,.19189,0,.87373],77:[0,.7,.15981,0,1.08031],78:[0,.7,.3525,0,.9015],79:[0,.7,.08078,0,.73787],80:[0,.7,.08078,0,1.01262],81:[0,.7,.03305,0,.88282],82:[0,.7,.06259,0,.85],83:[0,.7,.19189,0,.86767],84:[0,.7,.29087,0,.74697],85:[0,.7,.25815,0,.79996],86:[0,.7,.27523,0,.62204],87:[0,.7,.27523,0,.80532],88:[0,.7,.26006,0,.94445],89:[0,.7,.2939,0,.70961],90:[0,.7,.24037,0,.8212],160:[0,0,0,0,.25]},"Size1-Regular":{32:[0,0,0,0,.25],40:[.35001,.85,0,0,.45834],41:[.35001,.85,0,0,.45834],47:[.35001,.85,0,0,.57778],91:[.35001,.85,0,0,.41667],92:[.35001,.85,0,0,.57778],93:[.35001,.85,0,0,.41667],123:[.35001,.85,0,0,.58334],125:[.35001,.85,0,0,.58334],160:[0,0,0,0,.25],710:[0,.72222,0,0,.55556],732:[0,.72222,0,0,.55556],770:[0,.72222,0,0,.55556],771:[0,.72222,0,0,.55556],8214:[-99e-5,.601,0,0,.77778],8593:[1e-5,.6,0,0,.66667],8595:[1e-5,.6,0,0,.66667],8657:[1e-5,.6,0,0,.77778],8659:[1e-5,.6,0,0,.77778],8719:[.25001,.75,0,0,.94445],8720:[.25001,.75,0,0,.94445],8721:[.25001,.75,0,0,1.05556],8730:[.35001,.85,0,0,1],8739:[-.00599,.606,0,0,.33333],8741:[-.00599,.606,0,0,.55556],8747:[.30612,.805,.19445,0,.47222],8748:[.306,.805,.19445,0,.47222],8749:[.306,.805,.19445,0,.47222],8750:[.30612,.805,.19445,0,.47222],8896:[.25001,.75,0,0,.83334],8897:[.25001,.75,0,0,.83334],8898:[.25001,.75,0,0,.83334],8899:[.25001,.75,0,0,.83334],8968:[.35001,.85,0,0,.47222],8969:[.35001,.85,0,0,.47222],8970:[.35001,.85,0,0,.47222],8971:[.35001,.85,0,0,.47222],9168:[-99e-5,.601,0,0,.66667],10216:[.35001,.85,0,0,.47222],10217:[.35001,.85,0,0,.47222],10752:[.25001,.75,0,0,1.11111],10753:[.25001,.75,0,0,1.11111],10754:[.25001,.75,0,0,1.11111],10756:[.25001,.75,0,0,.83334],10758:[.25001,.75,0,0,.83334]},"Size2-Regular":{32:[0,0,0,0,.25],40:[.65002,1.15,0,0,.59722],41:[.65002,1.15,0,0,.59722],47:[.65002,1.15,0,0,.81111],91:[.65002,1.15,0,0,.47222],92:[.65002,1.15,0,0,.81111],93:[.65002,1.15,0,0,.47222],123:[.65002,1.15,0,0,.66667],125:[.65002,1.15,0,0,.66667],160:[0,0,0,0,.25],710:[0,.75,0,0,1],732:[0,.75,0,0,1],770:[0,.75,0,0,1],771:[0,.75,0,0,1],8719:[.55001,1.05,0,0,1.27778],8720:[.55001,1.05,0,0,1.27778],8721:[.55001,1.05,0,0,1.44445],8730:[.65002,1.15,0,0,1],8747:[.86225,1.36,.44445,0,.55556],8748:[.862,1.36,.44445,0,.55556],8749:[.862,1.36,.44445,0,.55556],8750:[.86225,1.36,.44445,0,.55556],8896:[.55001,1.05,0,0,1.11111],8897:[.55001,1.05,0,0,1.11111],8898:[.55001,1.05,0,0,1.11111],8899:[.55001,1.05,0,0,1.11111],8968:[.65002,1.15,0,0,.52778],8969:[.65002,1.15,0,0,.52778],8970:[.65002,1.15,0,0,.52778],8971:[.65002,1.15,0,0,.52778],10216:[.65002,1.15,0,0,.61111],10217:[.65002,1.15,0,0,.61111],10752:[.55001,1.05,0,0,1.51112],10753:[.55001,1.05,0,0,1.51112],10754:[.55001,1.05,0,0,1.51112],10756:[.55001,1.05,0,0,1.11111],10758:[.55001,1.05,0,0,1.11111]},"Size3-Regular":{32:[0,0,0,0,.25],40:[.95003,1.45,0,0,.73611],41:[.95003,1.45,0,0,.73611],47:[.95003,1.45,0,0,1.04445],91:[.95003,1.45,0,0,.52778],92:[.95003,1.45,0,0,1.04445],93:[.95003,1.45,0,0,.52778],123:[.95003,1.45,0,0,.75],125:[.95003,1.45,0,0,.75],160:[0,0,0,0,.25],710:[0,.75,0,0,1.44445],732:[0,.75,0,0,1.44445],770:[0,.75,0,0,1.44445],771:[0,.75,0,0,1.44445],8730:[.95003,1.45,0,0,1],8968:[.95003,1.45,0,0,.58334],8969:[.95003,1.45,0,0,.58334],8970:[.95003,1.45,0,0,.58334],8971:[.95003,1.45,0,0,.58334],10216:[.95003,1.45,0,0,.75],10217:[.95003,1.45,0,0,.75]},"Size4-Regular":{32:[0,0,0,0,.25],40:[1.25003,1.75,0,0,.79167],41:[1.25003,1.75,0,0,.79167],47:[1.25003,1.75,0,0,1.27778],91:[1.25003,1.75,0,0,.58334],92:[1.25003,1.75,0,0,1.27778],93:[1.25003,1.75,0,0,.58334],123:[1.25003,1.75,0,0,.80556],125:[1.25003,1.75,0,0,.80556],160:[0,0,0,0,.25],710:[0,.825,0,0,1.8889],732:[0,.825,0,0,1.8889],770:[0,.825,0,0,1.8889],771:[0,.825,0,0,1.8889],8730:[1.25003,1.75,0,0,1],8968:[1.25003,1.75,0,0,.63889],8969:[1.25003,1.75,0,0,.63889],8970:[1.25003,1.75,0,0,.63889],8971:[1.25003,1.75,0,0,.63889],9115:[.64502,1.155,0,0,.875],9116:[1e-5,.6,0,0,.875],9117:[.64502,1.155,0,0,.875],9118:[.64502,1.155,0,0,.875],9119:[1e-5,.6,0,0,.875],9120:[.64502,1.155,0,0,.875],9121:[.64502,1.155,0,0,.66667],9122:[-99e-5,.601,0,0,.66667],9123:[.64502,1.155,0,0,.66667],9124:[.64502,1.155,0,0,.66667],9125:[-99e-5,.601,0,0,.66667],9126:[.64502,1.155,0,0,.66667],9127:[1e-5,.9,0,0,.88889],9128:[.65002,1.15,0,0,.88889],9129:[.90001,0,0,0,.88889],9130:[0,.3,0,0,.88889],9131:[1e-5,.9,0,0,.88889],9132:[.65002,1.15,0,0,.88889],9133:[.90001,0,0,0,.88889],9143:[.88502,.915,0,0,1.05556],10216:[1.25003,1.75,0,0,.80556],10217:[1.25003,1.75,0,0,.80556],57344:[-.00499,.605,0,0,1.05556],57345:[-.00499,.605,0,0,1.05556],57680:[0,.12,0,0,.45],57681:[0,.12,0,0,.45],57682:[0,.12,0,0,.45],57683:[0,.12,0,0,.45]},"Typewriter-Regular":{32:[0,0,0,0,.525],33:[0,.61111,0,0,.525],34:[0,.61111,0,0,.525],35:[0,.61111,0,0,.525],36:[.08333,.69444,0,0,.525],37:[.08333,.69444,0,0,.525],38:[0,.61111,0,0,.525],39:[0,.61111,0,0,.525],40:[.08333,.69444,0,0,.525],41:[.08333,.69444,0,0,.525],42:[0,.52083,0,0,.525],43:[-.08056,.53055,0,0,.525],44:[.13889,.125,0,0,.525],45:[-.08056,.53055,0,0,.525],46:[0,.125,0,0,.525],47:[.08333,.69444,0,0,.525],48:[0,.61111,0,0,.525],49:[0,.61111,0,0,.525],50:[0,.61111,0,0,.525],51:[0,.61111,0,0,.525],52:[0,.61111,0,0,.525],53:[0,.61111,0,0,.525],54:[0,.61111,0,0,.525],55:[0,.61111,0,0,.525],56:[0,.61111,0,0,.525],57:[0,.61111,0,0,.525],58:[0,.43056,0,0,.525],59:[.13889,.43056,0,0,.525],60:[-.05556,.55556,0,0,.525],61:[-.19549,.41562,0,0,.525],62:[-.05556,.55556,0,0,.525],63:[0,.61111,0,0,.525],64:[0,.61111,0,0,.525],65:[0,.61111,0,0,.525],66:[0,.61111,0,0,.525],67:[0,.61111,0,0,.525],68:[0,.61111,0,0,.525],69:[0,.61111,0,0,.525],70:[0,.61111,0,0,.525],71:[0,.61111,0,0,.525],72:[0,.61111,0,0,.525],73:[0,.61111,0,0,.525],74:[0,.61111,0,0,.525],75:[0,.61111,0,0,.525],76:[0,.61111,0,0,.525],77:[0,.61111,0,0,.525],78:[0,.61111,0,0,.525],79:[0,.61111,0,0,.525],80:[0,.61111,0,0,.525],81:[.13889,.61111,0,0,.525],82:[0,.61111,0,0,.525],83:[0,.61111,0,0,.525],84:[0,.61111,0,0,.525],85:[0,.61111,0,0,.525],86:[0,.61111,0,0,.525],87:[0,.61111,0,0,.525],88:[0,.61111,0,0,.525],89:[0,.61111,0,0,.525],90:[0,.61111,0,0,.525],91:[.08333,.69444,0,0,.525],92:[.08333,.69444,0,0,.525],93:[.08333,.69444,0,0,.525],94:[0,.61111,0,0,.525],95:[.09514,0,0,0,.525],96:[0,.61111,0,0,.525],97:[0,.43056,0,0,.525],98:[0,.61111,0,0,.525],99:[0,.43056,0,0,.525],100:[0,.61111,0,0,.525],101:[0,.43056,0,0,.525],102:[0,.61111,0,0,.525],103:[.22222,.43056,0,0,.525],104:[0,.61111,0,0,.525],105:[0,.61111,0,0,.525],106:[.22222,.61111,0,0,.525],107:[0,.61111,0,0,.525],108:[0,.61111,0,0,.525],109:[0,.43056,0,0,.525],110:[0,.43056,0,0,.525],111:[0,.43056,0,0,.525],112:[.22222,.43056,0,0,.525],113:[.22222,.43056,0,0,.525],114:[0,.43056,0,0,.525],115:[0,.43056,0,0,.525],116:[0,.55358,0,0,.525],117:[0,.43056,0,0,.525],118:[0,.43056,0,0,.525],119:[0,.43056,0,0,.525],120:[0,.43056,0,0,.525],121:[.22222,.43056,0,0,.525],122:[0,.43056,0,0,.525],123:[.08333,.69444,0,0,.525],124:[.08333,.69444,0,0,.525],125:[.08333,.69444,0,0,.525],126:[0,.61111,0,0,.525],127:[0,.61111,0,0,.525],160:[0,0,0,0,.525],176:[0,.61111,0,0,.525],184:[.19445,0,0,0,.525],305:[0,.43056,0,0,.525],567:[.22222,.43056,0,0,.525],711:[0,.56597,0,0,.525],713:[0,.56555,0,0,.525],714:[0,.61111,0,0,.525],715:[0,.61111,0,0,.525],728:[0,.61111,0,0,.525],730:[0,.61111,0,0,.525],770:[0,.61111,0,0,.525],771:[0,.61111,0,0,.525],776:[0,.61111,0,0,.525],915:[0,.61111,0,0,.525],916:[0,.61111,0,0,.525],920:[0,.61111,0,0,.525],923:[0,.61111,0,0,.525],926:[0,.61111,0,0,.525],928:[0,.61111,0,0,.525],931:[0,.61111,0,0,.525],933:[0,.61111,0,0,.525],934:[0,.61111,0,0,.525],936:[0,.61111,0,0,.525],937:[0,.61111,0,0,.525],8216:[0,.61111,0,0,.525],8217:[0,.61111,0,0,.525],8242:[0,.61111,0,0,.525],9251:[.11111,.21944,0,0,.525]}},ve={slant:[.25,.25,.25],space:[0,0,0],stretch:[0,0,0],shrink:[0,0,0],xHeight:[.431,.431,.431],quad:[1,1.171,1.472],extraSpace:[0,0,0],num1:[.677,.732,.925],num2:[.394,.384,.387],num3:[.444,.471,.504],denom1:[.686,.752,1.025],denom2:[.345,.344,.532],sup1:[.413,.503,.504],sup2:[.363,.431,.404],sup3:[.289,.286,.294],sub1:[.15,.143,.2],sub2:[.247,.286,.4],supDrop:[.386,.353,.494],subDrop:[.05,.071,.1],delim1:[2.39,1.7,1.98],delim2:[1.01,1.157,1.42],axisHeight:[.25,.25,.25],defaultRuleThickness:[.04,.049,.049],bigOpSpacing1:[.111,.111,.111],bigOpSpacing2:[.166,.166,.166],bigOpSpacing3:[.2,.2,.2],bigOpSpacing4:[.6,.611,.611],bigOpSpacing5:[.1,.143,.143],sqrtRuleThickness:[.04,.04,.04],ptPerEm:[10,10,10],doubleRuleSep:[.2,.2,.2],arrayRuleWidth:[.04,.04,.04],fboxsep:[.3,.3,.3],fboxrule:[.04,.04,.04]},Ot={Å:"A",Ð:"D",Þ:"o",å:"a",ð:"d",þ:"o",А:"A",Б:"B",В:"B",Г:"F",Д:"A",Е:"E",Ж:"K",З:"3",И:"N",Й:"N",К:"K",Л:"N",М:"M",Н:"H",О:"O",П:"N",Р:"P",С:"C",Т:"T",У:"y",Ф:"O",Х:"X",Ц:"U",Ч:"h",Ш:"W",Щ:"W",Ъ:"B",Ы:"X",Ь:"B",Э:"3",Ю:"X",Я:"R",а:"a",б:"b",в:"a",г:"r",д:"y",е:"e",ж:"m",з:"e",и:"n",й:"n",к:"n",л:"n",м:"m",н:"n",о:"o",п:"n",р:"p",с:"c",т:"o",у:"y",ф:"b",х:"x",ц:"n",ч:"n",ш:"w",щ:"w",ъ:"a",ы:"m",ь:"a",э:"e",ю:"m",я:"r"};function Va(r,e){w0[r]=e}function ft(r,e,t){if(!w0[e])throw new Error("Font metrics not found for font: "+e+".");var a=r.charCodeAt(0),n=w0[e][a];if(!n&&r[0]in Ot&&(a=Ot[r[0]].charCodeAt(0),n=w0[e][a]),!n&&t==="text"&&gr(a)&&(n=w0[e][77]),n)return{depth:n[0],height:n[1],italic:n[2],skew:n[3],width:n[4]}}var Ue={};function Ua(r){var e;if(r>=5?e=0:r>=3?e=1:e=2,!Ue[e]){var t=Ue[e]={cssEmPerMu:ve.quad[e]/18};for(var a in ve)ve.hasOwnProperty(a)&&(t[a]=ve[a][e])}return Ue[e]}var $a=[[1,1,1],[2,1,1],[3,1,1],[4,2,1],[5,2,1],[6,3,1],[7,4,2],[8,6,3],[9,7,6],[10,8,7],[11,10,9]],Lt=[.5,.6,.7,.8,.9,1,1.2,1.44,1.728,2.074,2.488],Ht=function(e,t){return t.size<2?e:$a[e-1][t.size-1]};class T0{constructor(e){this.style=void 0,this.color=void 0,this.size=void 0,this.textSize=void 0,this.phantom=void 0,this.font=void 0,this.fontFamily=void 0,this.fontWeight=void 0,this.fontShape=void 0,this.sizeMultiplier=void 0,this.maxSize=void 0,this.minRuleThickness=void 0,this._fontMetrics=void 0,this.style=e.style,this.color=e.color,this.size=e.size||T0.BASESIZE,this.textSize=e.textSize||this.size,this.phantom=!!e.phantom,this.font=e.font||"",this.fontFamily=e.fontFamily||"",this.fontWeight=e.fontWeight||"",this.fontShape=e.fontShape||"",this.sizeMultiplier=Lt[this.size-1],this.maxSize=e.maxSize,this.minRuleThickness=e.minRuleThickness,this._fontMetrics=void 0}extend(e){var t={style:this.style,size:this.size,textSize:this.textSize,color:this.color,phantom:this.phantom,font:this.font,fontFamily:this.fontFamily,fontWeight:this.fontWeight,fontShape:this.fontShape,maxSize:this.maxSize,minRuleThickness:this.minRuleThickness};for(var a in e)e.hasOwnProperty(a)&&(t[a]=e[a]);return new T0(t)}havingStyle(e){return this.style===e?this:this.extend({style:e,size:Ht(this.textSize,e)})}havingCrampedStyle(){return this.havingStyle(this.style.cramp())}havingSize(e){return this.size===e&&this.textSize===e?this:this.extend({style:this.style.text(),size:e,textSize:e,sizeMultiplier:Lt[e-1]})}havingBaseStyle(e){e=e||this.style.text();var t=Ht(T0.BASESIZE,e);return this.size===t&&this.textSize===T0.BASESIZE&&this.style===e?this:this.extend({style:e,size:t})}havingBaseSizing(){var e;switch(this.style.id){case 4:case 5:e=3;break;case 6:case 7:e=1;break;default:e=6}return this.extend({style:this.style.text(),size:e})}withColor(e){return this.extend({color:e})}withPhantom(){return this.extend({phantom:!0})}withFont(e){return this.extend({font:e})}withTextFontFamily(e){return this.extend({fontFamily:e,font:""})}withTextFontWeight(e){return this.extend({fontWeight:e,font:""})}withTextFontShape(e){return this.extend({fontShape:e,font:""})}sizingClasses(e){return e.size!==this.size?["sizing","reset-size"+e.size,"size"+this.size]:[]}baseSizingClasses(){return this.size!==T0.BASESIZE?["sizing","reset-size"+this.size,"size"+T0.BASESIZE]:[]}fontMetrics(){return this._fontMetrics||(this._fontMetrics=Ua(this.size)),this._fontMetrics}getColor(){return this.phantom?"transparent":this.color}}T0.BASESIZE=6;var nt={pt:1,mm:7227/2540,cm:7227/254,in:72.27,bp:803/800,pc:12,dd:1238/1157,cc:14856/1157,nd:685/642,nc:1370/107,sp:1/65536,px:803/800},Xa={ex:!0,em:!0,mu:!0},br=function(e){return typeof e!="string"&&(e=e.unit),e in nt||e in Xa||e==="ex"},K=function(e,t){var a;if(e.unit in nt)a=nt[e.unit]/t.fontMetrics().ptPerEm/t.sizeMultiplier;else if(e.unit==="mu")a=t.fontMetrics().cssEmPerMu;else{var n;if(t.style.isTight()?n=t.havingStyle(t.style.text()):n=t,e.unit==="ex")a=n.fontMetrics().xHeight;else if(e.unit==="em")a=n.fontMetrics().quad;else throw new M("Invalid unit: '"+e.unit+"'");n!==t&&(a*=n.sizeMultiplier/t.sizeMultiplier)}return Math.min(e.number*a,t.maxSize)},T=function(e){return+e.toFixed(4)+"em"},F0=function(e){return e.filter(t=>t).join(" ")},yr=function(e,t,a){if(this.classes=e||[],this.attributes={},this.height=0,this.depth=0,this.maxFontSize=0,this.style=a||{},t){t.style.isTight()&&this.classes.push("mtight");var n=t.getColor();n&&(this.style.color=n)}},wr=function(e){var t=document.createElement(e);t.className=F0(this.classes);for(var a in this.style)this.style.hasOwnProperty(a)&&(t.style[a]=this.style[a]);for(var n in this.attributes)this.attributes.hasOwnProperty(n)&&t.setAttribute(n,this.attributes[n]);for(var s=0;s",t};class me{constructor(e,t,a,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.width=void 0,this.maxFontSize=void 0,this.style=void 0,yr.call(this,e,a,n),this.children=t||[]}setAttribute(e,t){this.attributes[e]=t}hasClass(e){return R.contains(this.classes,e)}toNode(){return wr.call(this,"span")}toMarkup(){return xr.call(this,"span")}}class pt{constructor(e,t,a,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,yr.call(this,t,n),this.children=a||[],this.setAttribute("href",e)}setAttribute(e,t){this.attributes[e]=t}hasClass(e){return R.contains(this.classes,e)}toNode(){return wr.call(this,"a")}toMarkup(){return xr.call(this,"a")}}class Ya{constructor(e,t,a){this.src=void 0,this.alt=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.alt=t,this.src=e,this.classes=["mord"],this.style=a}hasClass(e){return R.contains(this.classes,e)}toNode(){var e=document.createElement("img");e.src=this.src,e.alt=this.alt,e.className="mord";for(var t in this.style)this.style.hasOwnProperty(t)&&(e.style[t]=this.style[t]);return e}toMarkup(){var e=''+R.escape(this.alt)+'0&&(t=document.createElement("span"),t.style.marginRight=T(this.italic)),this.classes.length>0&&(t=t||document.createElement("span"),t.className=F0(this.classes));for(var a in this.style)this.style.hasOwnProperty(a)&&(t=t||document.createElement("span"),t.style[a]=this.style[a]);return t?(t.appendChild(e),t):e}toMarkup(){var e=!1,t="0&&(a+="margin-right:"+this.italic+"em;");for(var n in this.style)this.style.hasOwnProperty(n)&&(a+=R.hyphenate(n)+":"+this.style[n]+";");a&&(e=!0,t+=' style="'+R.escape(a)+'"');var s=R.escape(this.text);return e?(t+=">",t+=s,t+="",t):s}}class N0{constructor(e,t){this.children=void 0,this.attributes=void 0,this.children=e||[],this.attributes=t||{}}toNode(){var e="http://www.w3.org/2000/svg",t=document.createElementNS(e,"svg");for(var a in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,a)&&t.setAttribute(a,this.attributes[a]);for(var n=0;n':''}}class it{constructor(e){this.attributes=void 0,this.attributes=e||{}}toNode(){var e="http://www.w3.org/2000/svg",t=document.createElementNS(e,"line");for(var a in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,a)&&t.setAttribute(a,this.attributes[a]);return t}toMarkup(){var e=" but got "+String(r)+".")}var Za={bin:1,close:1,inner:1,open:1,punct:1,rel:1},Ka={"accent-token":1,mathord:1,"op-token":1,spacing:1,textord:1},Y={math:{},text:{}};function i(r,e,t,a,n,s){Y[r][n]={font:e,group:t,replace:a},s&&a&&(Y[r][a]=Y[r][n])}var l="math",k="text",h="main",d="ams",W="accent-token",N="bin",i0="close",te="inner",E="mathord",_="op-token",m0="open",Re="punct",f="rel",R0="spacing",v="textord";i(l,h,f,"≡","\\equiv",!0);i(l,h,f,"≺","\\prec",!0);i(l,h,f,"≻","\\succ",!0);i(l,h,f,"∼","\\sim",!0);i(l,h,f,"⊥","\\perp");i(l,h,f,"⪯","\\preceq",!0);i(l,h,f,"⪰","\\succeq",!0);i(l,h,f,"≃","\\simeq",!0);i(l,h,f,"∣","\\mid",!0);i(l,h,f,"≪","\\ll",!0);i(l,h,f,"≫","\\gg",!0);i(l,h,f,"≍","\\asymp",!0);i(l,h,f,"∥","\\parallel");i(l,h,f,"⋈","\\bowtie",!0);i(l,h,f,"⌣","\\smile",!0);i(l,h,f,"⊑","\\sqsubseteq",!0);i(l,h,f,"⊒","\\sqsupseteq",!0);i(l,h,f,"≐","\\doteq",!0);i(l,h,f,"⌢","\\frown",!0);i(l,h,f,"∋","\\ni",!0);i(l,h,f,"∝","\\propto",!0);i(l,h,f,"⊢","\\vdash",!0);i(l,h,f,"⊣","\\dashv",!0);i(l,h,f,"∋","\\owns");i(l,h,Re,".","\\ldotp");i(l,h,Re,"⋅","\\cdotp");i(l,h,v,"#","\\#");i(k,h,v,"#","\\#");i(l,h,v,"&","\\&");i(k,h,v,"&","\\&");i(l,h,v,"ℵ","\\aleph",!0);i(l,h,v,"∀","\\forall",!0);i(l,h,v,"ℏ","\\hbar",!0);i(l,h,v,"∃","\\exists",!0);i(l,h,v,"∇","\\nabla",!0);i(l,h,v,"♭","\\flat",!0);i(l,h,v,"ℓ","\\ell",!0);i(l,h,v,"♮","\\natural",!0);i(l,h,v,"♣","\\clubsuit",!0);i(l,h,v,"℘","\\wp",!0);i(l,h,v,"♯","\\sharp",!0);i(l,h,v,"♢","\\diamondsuit",!0);i(l,h,v,"ℜ","\\Re",!0);i(l,h,v,"♡","\\heartsuit",!0);i(l,h,v,"ℑ","\\Im",!0);i(l,h,v,"♠","\\spadesuit",!0);i(l,h,v,"§","\\S",!0);i(k,h,v,"§","\\S");i(l,h,v,"¶","\\P",!0);i(k,h,v,"¶","\\P");i(l,h,v,"†","\\dag");i(k,h,v,"†","\\dag");i(k,h,v,"†","\\textdagger");i(l,h,v,"‡","\\ddag");i(k,h,v,"‡","\\ddag");i(k,h,v,"‡","\\textdaggerdbl");i(l,h,i0,"⎱","\\rmoustache",!0);i(l,h,m0,"⎰","\\lmoustache",!0);i(l,h,i0,"⟯","\\rgroup",!0);i(l,h,m0,"⟮","\\lgroup",!0);i(l,h,N,"∓","\\mp",!0);i(l,h,N,"⊖","\\ominus",!0);i(l,h,N,"⊎","\\uplus",!0);i(l,h,N,"⊓","\\sqcap",!0);i(l,h,N,"∗","\\ast");i(l,h,N,"⊔","\\sqcup",!0);i(l,h,N,"◯","\\bigcirc",!0);i(l,h,N,"∙","\\bullet",!0);i(l,h,N,"‡","\\ddagger");i(l,h,N,"≀","\\wr",!0);i(l,h,N,"⨿","\\amalg");i(l,h,N,"&","\\And");i(l,h,f,"⟵","\\longleftarrow",!0);i(l,h,f,"⇐","\\Leftarrow",!0);i(l,h,f,"⟸","\\Longleftarrow",!0);i(l,h,f,"⟶","\\longrightarrow",!0);i(l,h,f,"⇒","\\Rightarrow",!0);i(l,h,f,"⟹","\\Longrightarrow",!0);i(l,h,f,"↔","\\leftrightarrow",!0);i(l,h,f,"⟷","\\longleftrightarrow",!0);i(l,h,f,"⇔","\\Leftrightarrow",!0);i(l,h,f,"⟺","\\Longleftrightarrow",!0);i(l,h,f,"↦","\\mapsto",!0);i(l,h,f,"⟼","\\longmapsto",!0);i(l,h,f,"↗","\\nearrow",!0);i(l,h,f,"↩","\\hookleftarrow",!0);i(l,h,f,"↪","\\hookrightarrow",!0);i(l,h,f,"↘","\\searrow",!0);i(l,h,f,"↼","\\leftharpoonup",!0);i(l,h,f,"⇀","\\rightharpoonup",!0);i(l,h,f,"↙","\\swarrow",!0);i(l,h,f,"↽","\\leftharpoondown",!0);i(l,h,f,"⇁","\\rightharpoondown",!0);i(l,h,f,"↖","\\nwarrow",!0);i(l,h,f,"⇌","\\rightleftharpoons",!0);i(l,d,f,"≮","\\nless",!0);i(l,d,f,"","\\@nleqslant");i(l,d,f,"","\\@nleqq");i(l,d,f,"⪇","\\lneq",!0);i(l,d,f,"≨","\\lneqq",!0);i(l,d,f,"","\\@lvertneqq");i(l,d,f,"⋦","\\lnsim",!0);i(l,d,f,"⪉","\\lnapprox",!0);i(l,d,f,"⊀","\\nprec",!0);i(l,d,f,"⋠","\\npreceq",!0);i(l,d,f,"⋨","\\precnsim",!0);i(l,d,f,"⪹","\\precnapprox",!0);i(l,d,f,"≁","\\nsim",!0);i(l,d,f,"","\\@nshortmid");i(l,d,f,"∤","\\nmid",!0);i(l,d,f,"⊬","\\nvdash",!0);i(l,d,f,"⊭","\\nvDash",!0);i(l,d,f,"⋪","\\ntriangleleft");i(l,d,f,"⋬","\\ntrianglelefteq",!0);i(l,d,f,"⊊","\\subsetneq",!0);i(l,d,f,"","\\@varsubsetneq");i(l,d,f,"⫋","\\subsetneqq",!0);i(l,d,f,"","\\@varsubsetneqq");i(l,d,f,"≯","\\ngtr",!0);i(l,d,f,"","\\@ngeqslant");i(l,d,f,"","\\@ngeqq");i(l,d,f,"⪈","\\gneq",!0);i(l,d,f,"≩","\\gneqq",!0);i(l,d,f,"","\\@gvertneqq");i(l,d,f,"⋧","\\gnsim",!0);i(l,d,f,"⪊","\\gnapprox",!0);i(l,d,f,"⊁","\\nsucc",!0);i(l,d,f,"⋡","\\nsucceq",!0);i(l,d,f,"⋩","\\succnsim",!0);i(l,d,f,"⪺","\\succnapprox",!0);i(l,d,f,"≆","\\ncong",!0);i(l,d,f,"","\\@nshortparallel");i(l,d,f,"∦","\\nparallel",!0);i(l,d,f,"⊯","\\nVDash",!0);i(l,d,f,"⋫","\\ntriangleright");i(l,d,f,"⋭","\\ntrianglerighteq",!0);i(l,d,f,"","\\@nsupseteqq");i(l,d,f,"⊋","\\supsetneq",!0);i(l,d,f,"","\\@varsupsetneq");i(l,d,f,"⫌","\\supsetneqq",!0);i(l,d,f,"","\\@varsupsetneqq");i(l,d,f,"⊮","\\nVdash",!0);i(l,d,f,"⪵","\\precneqq",!0);i(l,d,f,"⪶","\\succneqq",!0);i(l,d,f,"","\\@nsubseteqq");i(l,d,N,"⊴","\\unlhd");i(l,d,N,"⊵","\\unrhd");i(l,d,f,"↚","\\nleftarrow",!0);i(l,d,f,"↛","\\nrightarrow",!0);i(l,d,f,"⇍","\\nLeftarrow",!0);i(l,d,f,"⇏","\\nRightarrow",!0);i(l,d,f,"↮","\\nleftrightarrow",!0);i(l,d,f,"⇎","\\nLeftrightarrow",!0);i(l,d,f,"△","\\vartriangle");i(l,d,v,"ℏ","\\hslash");i(l,d,v,"▽","\\triangledown");i(l,d,v,"◊","\\lozenge");i(l,d,v,"Ⓢ","\\circledS");i(l,d,v,"®","\\circledR");i(k,d,v,"®","\\circledR");i(l,d,v,"∡","\\measuredangle",!0);i(l,d,v,"∄","\\nexists");i(l,d,v,"℧","\\mho");i(l,d,v,"Ⅎ","\\Finv",!0);i(l,d,v,"⅁","\\Game",!0);i(l,d,v,"‵","\\backprime");i(l,d,v,"▲","\\blacktriangle");i(l,d,v,"▼","\\blacktriangledown");i(l,d,v,"■","\\blacksquare");i(l,d,v,"⧫","\\blacklozenge");i(l,d,v,"★","\\bigstar");i(l,d,v,"∢","\\sphericalangle",!0);i(l,d,v,"∁","\\complement",!0);i(l,d,v,"ð","\\eth",!0);i(k,h,v,"ð","ð");i(l,d,v,"╱","\\diagup");i(l,d,v,"╲","\\diagdown");i(l,d,v,"□","\\square");i(l,d,v,"□","\\Box");i(l,d,v,"◊","\\Diamond");i(l,d,v,"¥","\\yen",!0);i(k,d,v,"¥","\\yen",!0);i(l,d,v,"✓","\\checkmark",!0);i(k,d,v,"✓","\\checkmark");i(l,d,v,"ℶ","\\beth",!0);i(l,d,v,"ℸ","\\daleth",!0);i(l,d,v,"ℷ","\\gimel",!0);i(l,d,v,"ϝ","\\digamma",!0);i(l,d,v,"ϰ","\\varkappa");i(l,d,m0,"┌","\\@ulcorner",!0);i(l,d,i0,"┐","\\@urcorner",!0);i(l,d,m0,"└","\\@llcorner",!0);i(l,d,i0,"┘","\\@lrcorner",!0);i(l,d,f,"≦","\\leqq",!0);i(l,d,f,"⩽","\\leqslant",!0);i(l,d,f,"⪕","\\eqslantless",!0);i(l,d,f,"≲","\\lesssim",!0);i(l,d,f,"⪅","\\lessapprox",!0);i(l,d,f,"≊","\\approxeq",!0);i(l,d,N,"⋖","\\lessdot");i(l,d,f,"⋘","\\lll",!0);i(l,d,f,"≶","\\lessgtr",!0);i(l,d,f,"⋚","\\lesseqgtr",!0);i(l,d,f,"⪋","\\lesseqqgtr",!0);i(l,d,f,"≑","\\doteqdot");i(l,d,f,"≓","\\risingdotseq",!0);i(l,d,f,"≒","\\fallingdotseq",!0);i(l,d,f,"∽","\\backsim",!0);i(l,d,f,"⋍","\\backsimeq",!0);i(l,d,f,"⫅","\\subseteqq",!0);i(l,d,f,"⋐","\\Subset",!0);i(l,d,f,"⊏","\\sqsubset",!0);i(l,d,f,"≼","\\preccurlyeq",!0);i(l,d,f,"⋞","\\curlyeqprec",!0);i(l,d,f,"≾","\\precsim",!0);i(l,d,f,"⪷","\\precapprox",!0);i(l,d,f,"⊲","\\vartriangleleft");i(l,d,f,"⊴","\\trianglelefteq");i(l,d,f,"⊨","\\vDash",!0);i(l,d,f,"⊪","\\Vvdash",!0);i(l,d,f,"⌣","\\smallsmile");i(l,d,f,"⌢","\\smallfrown");i(l,d,f,"≏","\\bumpeq",!0);i(l,d,f,"≎","\\Bumpeq",!0);i(l,d,f,"≧","\\geqq",!0);i(l,d,f,"⩾","\\geqslant",!0);i(l,d,f,"⪖","\\eqslantgtr",!0);i(l,d,f,"≳","\\gtrsim",!0);i(l,d,f,"⪆","\\gtrapprox",!0);i(l,d,N,"⋗","\\gtrdot");i(l,d,f,"⋙","\\ggg",!0);i(l,d,f,"≷","\\gtrless",!0);i(l,d,f,"⋛","\\gtreqless",!0);i(l,d,f,"⪌","\\gtreqqless",!0);i(l,d,f,"≖","\\eqcirc",!0);i(l,d,f,"≗","\\circeq",!0);i(l,d,f,"≜","\\triangleq",!0);i(l,d,f,"∼","\\thicksim");i(l,d,f,"≈","\\thickapprox");i(l,d,f,"⫆","\\supseteqq",!0);i(l,d,f,"⋑","\\Supset",!0);i(l,d,f,"⊐","\\sqsupset",!0);i(l,d,f,"≽","\\succcurlyeq",!0);i(l,d,f,"⋟","\\curlyeqsucc",!0);i(l,d,f,"≿","\\succsim",!0);i(l,d,f,"⪸","\\succapprox",!0);i(l,d,f,"⊳","\\vartriangleright");i(l,d,f,"⊵","\\trianglerighteq");i(l,d,f,"⊩","\\Vdash",!0);i(l,d,f,"∣","\\shortmid");i(l,d,f,"∥","\\shortparallel");i(l,d,f,"≬","\\between",!0);i(l,d,f,"⋔","\\pitchfork",!0);i(l,d,f,"∝","\\varpropto");i(l,d,f,"◀","\\blacktriangleleft");i(l,d,f,"∴","\\therefore",!0);i(l,d,f,"∍","\\backepsilon");i(l,d,f,"▶","\\blacktriangleright");i(l,d,f,"∵","\\because",!0);i(l,d,f,"⋘","\\llless");i(l,d,f,"⋙","\\gggtr");i(l,d,N,"⊲","\\lhd");i(l,d,N,"⊳","\\rhd");i(l,d,f,"≂","\\eqsim",!0);i(l,h,f,"⋈","\\Join");i(l,d,f,"≑","\\Doteq",!0);i(l,d,N,"∔","\\dotplus",!0);i(l,d,N,"∖","\\smallsetminus");i(l,d,N,"⋒","\\Cap",!0);i(l,d,N,"⋓","\\Cup",!0);i(l,d,N,"⩞","\\doublebarwedge",!0);i(l,d,N,"⊟","\\boxminus",!0);i(l,d,N,"⊞","\\boxplus",!0);i(l,d,N,"⋇","\\divideontimes",!0);i(l,d,N,"⋉","\\ltimes",!0);i(l,d,N,"⋊","\\rtimes",!0);i(l,d,N,"⋋","\\leftthreetimes",!0);i(l,d,N,"⋌","\\rightthreetimes",!0);i(l,d,N,"⋏","\\curlywedge",!0);i(l,d,N,"⋎","\\curlyvee",!0);i(l,d,N,"⊝","\\circleddash",!0);i(l,d,N,"⊛","\\circledast",!0);i(l,d,N,"⋅","\\centerdot");i(l,d,N,"⊺","\\intercal",!0);i(l,d,N,"⋒","\\doublecap");i(l,d,N,"⋓","\\doublecup");i(l,d,N,"⊠","\\boxtimes",!0);i(l,d,f,"⇢","\\dashrightarrow",!0);i(l,d,f,"⇠","\\dashleftarrow",!0);i(l,d,f,"⇇","\\leftleftarrows",!0);i(l,d,f,"⇆","\\leftrightarrows",!0);i(l,d,f,"⇚","\\Lleftarrow",!0);i(l,d,f,"↞","\\twoheadleftarrow",!0);i(l,d,f,"↢","\\leftarrowtail",!0);i(l,d,f,"↫","\\looparrowleft",!0);i(l,d,f,"⇋","\\leftrightharpoons",!0);i(l,d,f,"↶","\\curvearrowleft",!0);i(l,d,f,"↺","\\circlearrowleft",!0);i(l,d,f,"↰","\\Lsh",!0);i(l,d,f,"⇈","\\upuparrows",!0);i(l,d,f,"↿","\\upharpoonleft",!0);i(l,d,f,"⇃","\\downharpoonleft",!0);i(l,h,f,"⊶","\\origof",!0);i(l,h,f,"⊷","\\imageof",!0);i(l,d,f,"⊸","\\multimap",!0);i(l,d,f,"↭","\\leftrightsquigarrow",!0);i(l,d,f,"⇉","\\rightrightarrows",!0);i(l,d,f,"⇄","\\rightleftarrows",!0);i(l,d,f,"↠","\\twoheadrightarrow",!0);i(l,d,f,"↣","\\rightarrowtail",!0);i(l,d,f,"↬","\\looparrowright",!0);i(l,d,f,"↷","\\curvearrowright",!0);i(l,d,f,"↻","\\circlearrowright",!0);i(l,d,f,"↱","\\Rsh",!0);i(l,d,f,"⇊","\\downdownarrows",!0);i(l,d,f,"↾","\\upharpoonright",!0);i(l,d,f,"⇂","\\downharpoonright",!0);i(l,d,f,"⇝","\\rightsquigarrow",!0);i(l,d,f,"⇝","\\leadsto");i(l,d,f,"⇛","\\Rrightarrow",!0);i(l,d,f,"↾","\\restriction");i(l,h,v,"‘","`");i(l,h,v,"$","\\$");i(k,h,v,"$","\\$");i(k,h,v,"$","\\textdollar");i(l,h,v,"%","\\%");i(k,h,v,"%","\\%");i(l,h,v,"_","\\_");i(k,h,v,"_","\\_");i(k,h,v,"_","\\textunderscore");i(l,h,v,"∠","\\angle",!0);i(l,h,v,"∞","\\infty",!0);i(l,h,v,"′","\\prime");i(l,h,v,"△","\\triangle");i(l,h,v,"Γ","\\Gamma",!0);i(l,h,v,"Δ","\\Delta",!0);i(l,h,v,"Θ","\\Theta",!0);i(l,h,v,"Λ","\\Lambda",!0);i(l,h,v,"Ξ","\\Xi",!0);i(l,h,v,"Π","\\Pi",!0);i(l,h,v,"Σ","\\Sigma",!0);i(l,h,v,"Υ","\\Upsilon",!0);i(l,h,v,"Φ","\\Phi",!0);i(l,h,v,"Ψ","\\Psi",!0);i(l,h,v,"Ω","\\Omega",!0);i(l,h,v,"A","Α");i(l,h,v,"B","Β");i(l,h,v,"E","Ε");i(l,h,v,"Z","Ζ");i(l,h,v,"H","Η");i(l,h,v,"I","Ι");i(l,h,v,"K","Κ");i(l,h,v,"M","Μ");i(l,h,v,"N","Ν");i(l,h,v,"O","Ο");i(l,h,v,"P","Ρ");i(l,h,v,"T","Τ");i(l,h,v,"X","Χ");i(l,h,v,"¬","\\neg",!0);i(l,h,v,"¬","\\lnot");i(l,h,v,"⊤","\\top");i(l,h,v,"⊥","\\bot");i(l,h,v,"∅","\\emptyset");i(l,d,v,"∅","\\varnothing");i(l,h,E,"α","\\alpha",!0);i(l,h,E,"β","\\beta",!0);i(l,h,E,"γ","\\gamma",!0);i(l,h,E,"δ","\\delta",!0);i(l,h,E,"ϵ","\\epsilon",!0);i(l,h,E,"ζ","\\zeta",!0);i(l,h,E,"η","\\eta",!0);i(l,h,E,"θ","\\theta",!0);i(l,h,E,"ι","\\iota",!0);i(l,h,E,"κ","\\kappa",!0);i(l,h,E,"λ","\\lambda",!0);i(l,h,E,"μ","\\mu",!0);i(l,h,E,"ν","\\nu",!0);i(l,h,E,"ξ","\\xi",!0);i(l,h,E,"ο","\\omicron",!0);i(l,h,E,"π","\\pi",!0);i(l,h,E,"ρ","\\rho",!0);i(l,h,E,"σ","\\sigma",!0);i(l,h,E,"τ","\\tau",!0);i(l,h,E,"υ","\\upsilon",!0);i(l,h,E,"ϕ","\\phi",!0);i(l,h,E,"χ","\\chi",!0);i(l,h,E,"ψ","\\psi",!0);i(l,h,E,"ω","\\omega",!0);i(l,h,E,"ε","\\varepsilon",!0);i(l,h,E,"ϑ","\\vartheta",!0);i(l,h,E,"ϖ","\\varpi",!0);i(l,h,E,"ϱ","\\varrho",!0);i(l,h,E,"ς","\\varsigma",!0);i(l,h,E,"φ","\\varphi",!0);i(l,h,N,"∗","*",!0);i(l,h,N,"+","+");i(l,h,N,"−","-",!0);i(l,h,N,"⋅","\\cdot",!0);i(l,h,N,"∘","\\circ",!0);i(l,h,N,"÷","\\div",!0);i(l,h,N,"±","\\pm",!0);i(l,h,N,"×","\\times",!0);i(l,h,N,"∩","\\cap",!0);i(l,h,N,"∪","\\cup",!0);i(l,h,N,"∖","\\setminus",!0);i(l,h,N,"∧","\\land");i(l,h,N,"∨","\\lor");i(l,h,N,"∧","\\wedge",!0);i(l,h,N,"∨","\\vee",!0);i(l,h,v,"√","\\surd");i(l,h,m0,"⟨","\\langle",!0);i(l,h,m0,"∣","\\lvert");i(l,h,m0,"∥","\\lVert");i(l,h,i0,"?","?");i(l,h,i0,"!","!");i(l,h,i0,"⟩","\\rangle",!0);i(l,h,i0,"∣","\\rvert");i(l,h,i0,"∥","\\rVert");i(l,h,f,"=","=");i(l,h,f,":",":");i(l,h,f,"≈","\\approx",!0);i(l,h,f,"≅","\\cong",!0);i(l,h,f,"≥","\\ge");i(l,h,f,"≥","\\geq",!0);i(l,h,f,"←","\\gets");i(l,h,f,">","\\gt",!0);i(l,h,f,"∈","\\in",!0);i(l,h,f,"","\\@not");i(l,h,f,"⊂","\\subset",!0);i(l,h,f,"⊃","\\supset",!0);i(l,h,f,"⊆","\\subseteq",!0);i(l,h,f,"⊇","\\supseteq",!0);i(l,d,f,"⊈","\\nsubseteq",!0);i(l,d,f,"⊉","\\nsupseteq",!0);i(l,h,f,"⊨","\\models");i(l,h,f,"←","\\leftarrow",!0);i(l,h,f,"≤","\\le");i(l,h,f,"≤","\\leq",!0);i(l,h,f,"<","\\lt",!0);i(l,h,f,"→","\\rightarrow",!0);i(l,h,f,"→","\\to");i(l,d,f,"≱","\\ngeq",!0);i(l,d,f,"≰","\\nleq",!0);i(l,h,R0," ","\\ ");i(l,h,R0," ","\\space");i(l,h,R0," ","\\nobreakspace");i(k,h,R0," ","\\ ");i(k,h,R0," "," ");i(k,h,R0," ","\\space");i(k,h,R0," ","\\nobreakspace");i(l,h,R0,null,"\\nobreak");i(l,h,R0,null,"\\allowbreak");i(l,h,Re,",",",");i(l,h,Re,";",";");i(l,d,N,"⊼","\\barwedge",!0);i(l,d,N,"⊻","\\veebar",!0);i(l,h,N,"⊙","\\odot",!0);i(l,h,N,"⊕","\\oplus",!0);i(l,h,N,"⊗","\\otimes",!0);i(l,h,v,"∂","\\partial",!0);i(l,h,N,"⊘","\\oslash",!0);i(l,d,N,"⊚","\\circledcirc",!0);i(l,d,N,"⊡","\\boxdot",!0);i(l,h,N,"△","\\bigtriangleup");i(l,h,N,"▽","\\bigtriangledown");i(l,h,N,"†","\\dagger");i(l,h,N,"⋄","\\diamond");i(l,h,N,"⋆","\\star");i(l,h,N,"◃","\\triangleleft");i(l,h,N,"▹","\\triangleright");i(l,h,m0,"{","\\{");i(k,h,v,"{","\\{");i(k,h,v,"{","\\textbraceleft");i(l,h,i0,"}","\\}");i(k,h,v,"}","\\}");i(k,h,v,"}","\\textbraceright");i(l,h,m0,"{","\\lbrace");i(l,h,i0,"}","\\rbrace");i(l,h,m0,"[","\\lbrack",!0);i(k,h,v,"[","\\lbrack",!0);i(l,h,i0,"]","\\rbrack",!0);i(k,h,v,"]","\\rbrack",!0);i(l,h,m0,"(","\\lparen",!0);i(l,h,i0,")","\\rparen",!0);i(k,h,v,"<","\\textless",!0);i(k,h,v,">","\\textgreater",!0);i(l,h,m0,"⌊","\\lfloor",!0);i(l,h,i0,"⌋","\\rfloor",!0);i(l,h,m0,"⌈","\\lceil",!0);i(l,h,i0,"⌉","\\rceil",!0);i(l,h,v,"\\","\\backslash");i(l,h,v,"∣","|");i(l,h,v,"∣","\\vert");i(k,h,v,"|","\\textbar",!0);i(l,h,v,"∥","\\|");i(l,h,v,"∥","\\Vert");i(k,h,v,"∥","\\textbardbl");i(k,h,v,"~","\\textasciitilde");i(k,h,v,"\\","\\textbackslash");i(k,h,v,"^","\\textasciicircum");i(l,h,f,"↑","\\uparrow",!0);i(l,h,f,"⇑","\\Uparrow",!0);i(l,h,f,"↓","\\downarrow",!0);i(l,h,f,"⇓","\\Downarrow",!0);i(l,h,f,"↕","\\updownarrow",!0);i(l,h,f,"⇕","\\Updownarrow",!0);i(l,h,_,"∐","\\coprod");i(l,h,_,"⋁","\\bigvee");i(l,h,_,"⋀","\\bigwedge");i(l,h,_,"⨄","\\biguplus");i(l,h,_,"⋂","\\bigcap");i(l,h,_,"⋃","\\bigcup");i(l,h,_,"∫","\\int");i(l,h,_,"∫","\\intop");i(l,h,_,"∬","\\iint");i(l,h,_,"∭","\\iiint");i(l,h,_,"∏","\\prod");i(l,h,_,"∑","\\sum");i(l,h,_,"⨂","\\bigotimes");i(l,h,_,"⨁","\\bigoplus");i(l,h,_,"⨀","\\bigodot");i(l,h,_,"∮","\\oint");i(l,h,_,"∯","\\oiint");i(l,h,_,"∰","\\oiiint");i(l,h,_,"⨆","\\bigsqcup");i(l,h,_,"∫","\\smallint");i(k,h,te,"…","\\textellipsis");i(l,h,te,"…","\\mathellipsis");i(k,h,te,"…","\\ldots",!0);i(l,h,te,"…","\\ldots",!0);i(l,h,te,"⋯","\\@cdots",!0);i(l,h,te,"⋱","\\ddots",!0);i(l,h,v,"⋮","\\varvdots");i(l,h,W,"ˊ","\\acute");i(l,h,W,"ˋ","\\grave");i(l,h,W,"¨","\\ddot");i(l,h,W,"~","\\tilde");i(l,h,W,"ˉ","\\bar");i(l,h,W,"˘","\\breve");i(l,h,W,"ˇ","\\check");i(l,h,W,"^","\\hat");i(l,h,W,"⃗","\\vec");i(l,h,W,"˙","\\dot");i(l,h,W,"˚","\\mathring");i(l,h,E,"","\\@imath");i(l,h,E,"","\\@jmath");i(l,h,v,"ı","ı");i(l,h,v,"ȷ","ȷ");i(k,h,v,"ı","\\i",!0);i(k,h,v,"ȷ","\\j",!0);i(k,h,v,"ß","\\ss",!0);i(k,h,v,"æ","\\ae",!0);i(k,h,v,"œ","\\oe",!0);i(k,h,v,"ø","\\o",!0);i(k,h,v,"Æ","\\AE",!0);i(k,h,v,"Œ","\\OE",!0);i(k,h,v,"Ø","\\O",!0);i(k,h,W,"ˊ","\\'");i(k,h,W,"ˋ","\\`");i(k,h,W,"ˆ","\\^");i(k,h,W,"˜","\\~");i(k,h,W,"ˉ","\\=");i(k,h,W,"˘","\\u");i(k,h,W,"˙","\\.");i(k,h,W,"¸","\\c");i(k,h,W,"˚","\\r");i(k,h,W,"ˇ","\\v");i(k,h,W,"¨",'\\"');i(k,h,W,"˝","\\H");i(k,h,W,"◯","\\textcircled");var kr={"--":!0,"---":!0,"``":!0,"''":!0};i(k,h,v,"–","--",!0);i(k,h,v,"–","\\textendash");i(k,h,v,"—","---",!0);i(k,h,v,"—","\\textemdash");i(k,h,v,"‘","`",!0);i(k,h,v,"‘","\\textquoteleft");i(k,h,v,"’","'",!0);i(k,h,v,"’","\\textquoteright");i(k,h,v,"“","``",!0);i(k,h,v,"“","\\textquotedblleft");i(k,h,v,"”","''",!0);i(k,h,v,"”","\\textquotedblright");i(l,h,v,"°","\\degree",!0);i(k,h,v,"°","\\degree");i(k,h,v,"°","\\textdegree",!0);i(l,h,v,"£","\\pounds");i(l,h,v,"£","\\mathsterling",!0);i(k,h,v,"£","\\pounds");i(k,h,v,"£","\\textsterling",!0);i(l,d,v,"✠","\\maltese");i(k,d,v,"✠","\\maltese");var Pt='0123456789/@."';for(var $e=0;$e0)return b0(s,p,n,t,o.concat(g));if(c){var b,w;if(c==="boldsymbol"){var x=_a(s,n,t,o,a);b=x.fontName,w=[x.fontClass]}else m?(b=zr[c].fontName,w=[c]):(b=we(c,t.fontWeight,t.fontShape),w=[c,t.fontWeight,t.fontShape]);if(Ee(s,b,n).metrics)return b0(s,b,n,t,o.concat(w));if(kr.hasOwnProperty(s)&&b.slice(0,10)==="Typewriter"){for(var z=[],A=0;A{if(F0(r.classes)!==F0(e.classes)||r.skew!==e.skew||r.maxFontSize!==e.maxFontSize)return!1;if(r.classes.length===1){var t=r.classes[0];if(t==="mbin"||t==="mord")return!1}for(var a in r.style)if(r.style.hasOwnProperty(a)&&r.style[a]!==e.style[a])return!1;for(var n in e.style)if(e.style.hasOwnProperty(n)&&r.style[n]!==e.style[n])return!1;return!0},r1=r=>{for(var e=0;et&&(t=o.height),o.depth>a&&(a=o.depth),o.maxFontSize>n&&(n=o.maxFontSize)}e.height=t,e.depth=a,e.maxFontSize=n},l0=function(e,t,a,n){var s=new me(e,t,a,n);return vt(s),s},Sr=(r,e,t,a)=>new me(r,e,t,a),a1=function(e,t,a){var n=l0([e],[],t);return n.height=Math.max(a||t.fontMetrics().defaultRuleThickness,t.minRuleThickness),n.style.borderBottomWidth=T(n.height),n.maxFontSize=1,n},n1=function(e,t,a,n){var s=new pt(e,t,a,n);return vt(s),s},Mr=function(e){var t=new he(e);return vt(t),t},i1=function(e,t){return e instanceof he?l0([],[e],t):e},s1=function(e){if(e.positionType==="individualShift"){for(var t=e.children,a=[t[0]],n=-t[0].shift-t[0].elem.depth,s=n,o=1;o{var t=l0(["mspace"],[],e),a=K(r,e);return t.style.marginRight=T(a),t},we=function(e,t,a){var n="";switch(e){case"amsrm":n="AMS";break;case"textrm":n="Main";break;case"textsf":n="SansSerif";break;case"texttt":n="Typewriter";break;default:n=e}var s;return t==="textbf"&&a==="textit"?s="BoldItalic":t==="textbf"?s="Bold":t==="textit"?s="Italic":s="Regular",n+"-"+s},zr={mathbf:{variant:"bold",fontName:"Main-Bold"},mathrm:{variant:"normal",fontName:"Main-Regular"},textit:{variant:"italic",fontName:"Main-Italic"},mathit:{variant:"italic",fontName:"Main-Italic"},mathnormal:{variant:"italic",fontName:"Math-Italic"},mathbb:{variant:"double-struck",fontName:"AMS-Regular"},mathcal:{variant:"script",fontName:"Caligraphic-Regular"},mathfrak:{variant:"fraktur",fontName:"Fraktur-Regular"},mathscr:{variant:"script",fontName:"Script-Regular"},mathsf:{variant:"sans-serif",fontName:"SansSerif-Regular"},mathtt:{variant:"monospace",fontName:"Typewriter-Regular"}},Tr={vec:["vec",.471,.714],oiintSize1:["oiintSize1",.957,.499],oiintSize2:["oiintSize2",1.472,.659],oiiintSize1:["oiiintSize1",1.304,.499],oiiintSize2:["oiiintSize2",1.98,.659]},h1=function(e,t){var[a,n,s]=Tr[e],o=new P0(a),m=new N0([o],{width:T(n),height:T(s),style:"width:"+T(n),viewBox:"0 0 "+1e3*n+" "+1e3*s,preserveAspectRatio:"xMinYMin"}),c=Sr(["overlay"],[m],t);return c.height=s,c.style.height=T(s),c.style.width=T(n),c},y={fontMap:zr,makeSymbol:b0,mathsym:Qa,makeSpan:l0,makeSvgSpan:Sr,makeLineSpan:a1,makeAnchor:n1,makeFragment:Mr,wrapFragment:i1,makeVList:l1,makeOrd:e1,makeGlue:o1,staticSvg:h1,svgData:Tr,tryCombineChars:r1},Z={number:3,unit:"mu"},X0={number:4,unit:"mu"},z0={number:5,unit:"mu"},m1={mord:{mop:Z,mbin:X0,mrel:z0,minner:Z},mop:{mord:Z,mop:Z,mrel:z0,minner:Z},mbin:{mord:X0,mop:X0,mopen:X0,minner:X0},mrel:{mord:z0,mop:z0,mopen:z0,minner:z0},mopen:{},mclose:{mop:Z,mbin:X0,mrel:z0,minner:Z},mpunct:{mord:Z,mop:Z,mrel:z0,mopen:Z,mclose:Z,mpunct:Z,minner:Z},minner:{mord:Z,mop:Z,mbin:X0,mrel:z0,mopen:Z,mpunct:Z,minner:Z}},u1={mord:{mop:Z},mop:{mord:Z,mop:Z},mbin:{},mrel:{},mopen:{},mclose:{mop:Z},mpunct:{},minner:{mop:Z}},Ar={},Ne={},Ce={};function B(r){for(var{type:e,names:t,props:a,handler:n,htmlBuilder:s,mathmlBuilder:o}=r,m={type:e,numArgs:a.numArgs,argTypes:a.argTypes,allowedInArgument:!!a.allowedInArgument,allowedInText:!!a.allowedInText,allowedInMath:a.allowedInMath===void 0?!0:a.allowedInMath,numOptionalArgs:a.numOptionalArgs||0,infix:!!a.infix,primitive:!!a.primitive,handler:n},c=0;c{var C=A.classes[0],q=z.classes[0];C==="mbin"&&R.contains(d1,q)?A.classes[0]="mord":q==="mbin"&&R.contains(c1,C)&&(z.classes[0]="mord")},{node:b},w,x),Xt(s,(z,A)=>{var C=lt(A),q=lt(z),O=C&&q?z.hasClass("mtight")?u1[C][q]:m1[C][q]:null;if(O)return y.makeGlue(O,p)},{node:b},w,x),s},Xt=function r(e,t,a,n,s){n&&e.push(n);for(var o=0;ow=>{e.splice(b+1,0,w),o++})(o)}n&&e.pop()},Br=function(e){return e instanceof he||e instanceof pt||e instanceof me&&e.hasClass("enclosing")?e:null},v1=function r(e,t){var a=Br(e);if(a){var n=a.children;if(n.length){if(t==="right")return r(n[n.length-1],"right");if(t==="left")return r(n[0],"left")}}return e},lt=function(e,t){return e?(t&&(e=v1(e,t)),p1[e.classes[0]]||null):null},oe=function(e,t){var a=["nulldelimiter"].concat(e.baseSizingClasses());return C0(t.concat(a))},P=function(e,t,a){if(!e)return C0();if(Ne[e.type]){var n=Ne[e.type](e,t);if(a&&t.size!==a.size){n=C0(t.sizingClasses(a),[n],t);var s=t.sizeMultiplier/a.sizeMultiplier;n.height*=s,n.depth*=s}return n}else throw new M("Got group of unknown type: '"+e.type+"'")};function xe(r,e){var t=C0(["base"],r,e),a=C0(["strut"]);return a.style.height=T(t.height+t.depth),t.depth&&(a.style.verticalAlign=T(-t.depth)),t.children.unshift(a),t}function ot(r,e){var t=null;r.length===1&&r[0].type==="tag"&&(t=r[0].tag,r=r[0].body);var a=t0(r,e,"root"),n;a.length===2&&a[1].hasClass("tag")&&(n=a.pop());for(var s=[],o=[],m=0;m0&&(s.push(xe(o,e)),o=[]),s.push(a[m]));o.length>0&&s.push(xe(o,e));var p;t?(p=xe(t0(t,e,!0)),p.classes=["tag"],s.push(p)):n&&s.push(n);var g=C0(["katex-html"],s);if(g.setAttribute("aria-hidden","true"),p){var b=p.children[0];b.style.height=T(g.height+g.depth),g.depth&&(b.style.verticalAlign=T(-g.depth))}return g}function Nr(r){return new he(r)}class c0{constructor(e,t,a){this.type=void 0,this.attributes=void 0,this.children=void 0,this.classes=void 0,this.type=e,this.attributes={},this.children=t||[],this.classes=a||[]}setAttribute(e,t){this.attributes[e]=t}getAttribute(e){return this.attributes[e]}toNode(){var e=document.createElementNS("http://www.w3.org/1998/Math/MathML",this.type);for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);this.classes.length>0&&(e.className=F0(this.classes));for(var a=0;a0&&(e+=' class ="'+R.escape(F0(this.classes))+'"'),e+=">";for(var a=0;a",e}toText(){return this.children.map(e=>e.toText()).join("")}}class ie{constructor(e){this.text=void 0,this.text=e}toNode(){return document.createTextNode(this.text)}toMarkup(){return R.escape(this.toText())}toText(){return this.text}}class g1{constructor(e){this.width=void 0,this.character=void 0,this.width=e,e>=.05555&&e<=.05556?this.character=" ":e>=.1666&&e<=.1667?this.character=" ":e>=.2222&&e<=.2223?this.character=" ":e>=.2777&&e<=.2778?this.character="  ":e>=-.05556&&e<=-.05555?this.character=" ⁣":e>=-.1667&&e<=-.1666?this.character=" ⁣":e>=-.2223&&e<=-.2222?this.character=" ⁣":e>=-.2778&&e<=-.2777?this.character=" ⁣":this.character=null}toNode(){if(this.character)return document.createTextNode(this.character);var e=document.createElementNS("http://www.w3.org/1998/Math/MathML","mspace");return e.setAttribute("width",T(this.width)),e}toMarkup(){return this.character?""+this.character+"":''}toText(){return this.character?this.character:" "}}var S={MathNode:c0,TextNode:ie,SpaceNode:g1,newDocumentFragment:Nr},v0=function(e,t,a){return Y[t][e]&&Y[t][e].replace&&e.charCodeAt(0)!==55349&&!(kr.hasOwnProperty(e)&&a&&(a.fontFamily&&a.fontFamily.slice(4,6)==="tt"||a.font&&a.font.slice(4,6)==="tt"))&&(e=Y[t][e].replace),new S.TextNode(e)},gt=function(e){return e.length===1?e[0]:new S.MathNode("mrow",e)},bt=function(e,t){if(t.fontFamily==="texttt")return"monospace";if(t.fontFamily==="textsf")return t.fontShape==="textit"&&t.fontWeight==="textbf"?"sans-serif-bold-italic":t.fontShape==="textit"?"sans-serif-italic":t.fontWeight==="textbf"?"bold-sans-serif":"sans-serif";if(t.fontShape==="textit"&&t.fontWeight==="textbf")return"bold-italic";if(t.fontShape==="textit")return"italic";if(t.fontWeight==="textbf")return"bold";var a=t.font;if(!a||a==="mathnormal")return null;var n=e.mode;if(a==="mathit")return"italic";if(a==="boldsymbol")return e.type==="textord"?"bold":"bold-italic";if(a==="mathbf")return"bold";if(a==="mathbb")return"double-struck";if(a==="mathfrak")return"fraktur";if(a==="mathscr"||a==="mathcal")return"script";if(a==="mathsf")return"sans-serif";if(a==="mathtt")return"monospace";var s=e.text;if(R.contains(["\\imath","\\jmath"],s))return null;Y[n][s]&&Y[n][s].replace&&(s=Y[n][s].replace);var o=y.fontMap[a].fontName;return ft(s,o,n)?y.fontMap[a].variant:null},o0=function(e,t,a){if(e.length===1){var n=X(e[0],t);return a&&n instanceof c0&&n.type==="mo"&&(n.setAttribute("lspace","0em"),n.setAttribute("rspace","0em")),[n]}for(var s=[],o,m=0;m0&&(b.text=b.text.slice(0,1)+"̸"+b.text.slice(1),s.pop())}}}s.push(c),o=c}return s},G0=function(e,t,a){return gt(o0(e,t,a))},X=function(e,t){if(!e)return new S.MathNode("mrow");if(Ce[e.type]){var a=Ce[e.type](e,t);return a}else throw new M("Got group of unknown type: '"+e.type+"'")};function Yt(r,e,t,a,n){var s=o0(r,t),o;s.length===1&&s[0]instanceof c0&&R.contains(["mrow","mtable"],s[0].type)?o=s[0]:o=new S.MathNode("mrow",s);var m=new S.MathNode("annotation",[new S.TextNode(e)]);m.setAttribute("encoding","application/x-tex");var c=new S.MathNode("semantics",[o,m]),p=new S.MathNode("math",[c]);p.setAttribute("xmlns","http://www.w3.org/1998/Math/MathML"),a&&p.setAttribute("display","block");var g=n?"katex":"katex-mathml";return y.makeSpan([g],[p])}var Cr=function(e){return new T0({style:e.displayMode?I.DISPLAY:I.TEXT,maxSize:e.maxSize,minRuleThickness:e.minRuleThickness})},qr=function(e,t){if(t.displayMode){var a=["katex-display"];t.leqno&&a.push("leqno"),t.fleqn&&a.push("fleqn"),e=y.makeSpan(a,[e])}return e},b1=function(e,t,a){var n=Cr(a),s;if(a.output==="mathml")return Yt(e,t,n,a.displayMode,!0);if(a.output==="html"){var o=ot(e,n);s=y.makeSpan(["katex"],[o])}else{var m=Yt(e,t,n,a.displayMode,!1),c=ot(e,n);s=y.makeSpan(["katex"],[m,c])}return qr(s,a)},y1=function(e,t,a){var n=Cr(a),s=ot(e,n),o=y.makeSpan(["katex"],[s]);return qr(o,a)},w1={widehat:"^",widecheck:"ˇ",widetilde:"~",utilde:"~",overleftarrow:"←",underleftarrow:"←",xleftarrow:"←",overrightarrow:"→",underrightarrow:"→",xrightarrow:"→",underbrace:"⏟",overbrace:"⏞",overgroup:"⏠",undergroup:"⏡",overleftrightarrow:"↔",underleftrightarrow:"↔",xleftrightarrow:"↔",Overrightarrow:"⇒",xRightarrow:"⇒",overleftharpoon:"↼",xleftharpoonup:"↼",overrightharpoon:"⇀",xrightharpoonup:"⇀",xLeftarrow:"⇐",xLeftrightarrow:"⇔",xhookleftarrow:"↩",xhookrightarrow:"↪",xmapsto:"↦",xrightharpoondown:"⇁",xleftharpoondown:"↽",xrightleftharpoons:"⇌",xleftrightharpoons:"⇋",xtwoheadleftarrow:"↞",xtwoheadrightarrow:"↠",xlongequal:"=",xtofrom:"⇄",xrightleftarrows:"⇄",xrightequilibrium:"⇌",xleftequilibrium:"⇋","\\cdrightarrow":"→","\\cdleftarrow":"←","\\cdlongequal":"="},x1=function(e){var t=new S.MathNode("mo",[new S.TextNode(w1[e.replace(/^\\/,"")])]);return t.setAttribute("stretchy","true"),t},k1={overrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],overleftarrow:[["leftarrow"],.888,522,"xMinYMin"],underrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],underleftarrow:[["leftarrow"],.888,522,"xMinYMin"],xrightarrow:[["rightarrow"],1.469,522,"xMaxYMin"],"\\cdrightarrow":[["rightarrow"],3,522,"xMaxYMin"],xleftarrow:[["leftarrow"],1.469,522,"xMinYMin"],"\\cdleftarrow":[["leftarrow"],3,522,"xMinYMin"],Overrightarrow:[["doublerightarrow"],.888,560,"xMaxYMin"],xRightarrow:[["doublerightarrow"],1.526,560,"xMaxYMin"],xLeftarrow:[["doubleleftarrow"],1.526,560,"xMinYMin"],overleftharpoon:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoonup:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoondown:[["leftharpoondown"],.888,522,"xMinYMin"],overrightharpoon:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoonup:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoondown:[["rightharpoondown"],.888,522,"xMaxYMin"],xlongequal:[["longequal"],.888,334,"xMinYMin"],"\\cdlongequal":[["longequal"],3,334,"xMinYMin"],xtwoheadleftarrow:[["twoheadleftarrow"],.888,334,"xMinYMin"],xtwoheadrightarrow:[["twoheadrightarrow"],.888,334,"xMaxYMin"],overleftrightarrow:[["leftarrow","rightarrow"],.888,522],overbrace:[["leftbrace","midbrace","rightbrace"],1.6,548],underbrace:[["leftbraceunder","midbraceunder","rightbraceunder"],1.6,548],underleftrightarrow:[["leftarrow","rightarrow"],.888,522],xleftrightarrow:[["leftarrow","rightarrow"],1.75,522],xLeftrightarrow:[["doubleleftarrow","doublerightarrow"],1.75,560],xrightleftharpoons:[["leftharpoondownplus","rightharpoonplus"],1.75,716],xleftrightharpoons:[["leftharpoonplus","rightharpoondownplus"],1.75,716],xhookleftarrow:[["leftarrow","righthook"],1.08,522],xhookrightarrow:[["lefthook","rightarrow"],1.08,522],overlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],underlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],overgroup:[["leftgroup","rightgroup"],.888,342],undergroup:[["leftgroupunder","rightgroupunder"],.888,342],xmapsto:[["leftmapsto","rightarrow"],1.5,522],xtofrom:[["leftToFrom","rightToFrom"],1.75,528],xrightleftarrows:[["baraboveleftarrow","rightarrowabovebar"],1.75,901],xrightequilibrium:[["baraboveshortleftharpoon","rightharpoonaboveshortbar"],1.75,716],xleftequilibrium:[["shortbaraboveleftharpoon","shortrightharpoonabovebar"],1.75,716]},S1=function(e){return e.type==="ordgroup"?e.body.length:1},M1=function(e,t){function a(){var m=4e5,c=e.label.slice(1);if(R.contains(["widehat","widecheck","widetilde","utilde"],c)){var p=e,g=S1(p.base),b,w,x;if(g>5)c==="widehat"||c==="widecheck"?(b=420,m=2364,x=.42,w=c+"4"):(b=312,m=2340,x=.34,w="tilde4");else{var z=[1,1,2,2,3,3][g];c==="widehat"||c==="widecheck"?(m=[0,1062,2364,2364,2364][z],b=[0,239,300,360,420][z],x=[0,.24,.3,.3,.36,.42][z],w=c+z):(m=[0,600,1033,2339,2340][z],b=[0,260,286,306,312][z],x=[0,.26,.286,.3,.306,.34][z],w="tilde"+z)}var A=new P0(w),C=new N0([A],{width:"100%",height:T(x),viewBox:"0 0 "+m+" "+b,preserveAspectRatio:"none"});return{span:y.makeSvgSpan([],[C],t),minWidth:0,height:x}}else{var q=[],O=k1[c],[L,V,F]=O,U=F/1e3,G=L.length,j,$;if(G===1){var M0=O[3];j=["hide-tail"],$=[M0]}else if(G===2)j=["halfarrow-left","halfarrow-right"],$=["xMinYMin","xMaxYMin"];else if(G===3)j=["brace-left","brace-center","brace-right"],$=["xMinYMin","xMidYMin","xMaxYMin"];else throw new Error(`Correct katexImagesData or update code here to support + `+G+" children.");for(var r0=0;r00&&(n.style.minWidth=T(s)),n},z1=function(e,t,a,n,s){var o,m=e.height+e.depth+a+n;if(/fbox|color|angl/.test(t)){if(o=y.makeSpan(["stretchy",t],[],s),t==="fbox"){var c=s.color&&s.getColor();c&&(o.style.borderColor=c)}}else{var p=[];/^[bx]cancel$/.test(t)&&p.push(new it({x1:"0",y1:"0",x2:"100%",y2:"100%","stroke-width":"0.046em"})),/^x?cancel$/.test(t)&&p.push(new it({x1:"0",y1:"100%",x2:"100%",y2:"0","stroke-width":"0.046em"}));var g=new N0(p,{width:"100%",height:T(m)});o=y.makeSvgSpan([],[g],s)}return o.height=m,o.style.height=T(m),o},q0={encloseSpan:z1,mathMLnode:x1,svgSpan:M1};function H(r,e){if(!r||r.type!==e)throw new Error("Expected node of type "+e+", but got "+(r?"node of type "+r.type:String(r)));return r}function yt(r){var e=Ie(r);if(!e)throw new Error("Expected node of symbol group type, but got "+(r?"node of type "+r.type:String(r)));return e}function Ie(r){return r&&(r.type==="atom"||Ka.hasOwnProperty(r.type))?r:null}var wt=(r,e)=>{var t,a,n;r&&r.type==="supsub"?(a=H(r.base,"accent"),t=a.base,r.base=t,n=ja(P(r,e)),r.base=a):(a=H(r,"accent"),t=a.base);var s=P(t,e.havingCrampedStyle()),o=a.isShifty&&R.isCharacterBox(t),m=0;if(o){var c=R.getBaseElem(t),p=P(c,e.havingCrampedStyle());m=Ft(p).skew}var g=a.label==="\\c",b=g?s.height+s.depth:Math.min(s.height,e.fontMetrics().xHeight),w;if(a.isStretchy)w=q0.svgSpan(a,e),w=y.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:s},{type:"elem",elem:w,wrapperClasses:["svg-align"],wrapperStyle:m>0?{width:"calc(100% - "+T(2*m)+")",marginLeft:T(2*m)}:void 0}]},e);else{var x,z;a.label==="\\vec"?(x=y.staticSvg("vec",e),z=y.svgData.vec[1]):(x=y.makeOrd({mode:a.mode,text:a.label},e,"textord"),x=Ft(x),x.italic=0,z=x.width,g&&(b+=x.depth)),w=y.makeSpan(["accent-body"],[x]);var A=a.label==="\\textcircled";A&&(w.classes.push("accent-full"),b=s.height);var C=m;A||(C-=z/2),w.style.left=T(C),a.label==="\\textcircled"&&(w.style.top=".2em"),w=y.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:s},{type:"kern",size:-b},{type:"elem",elem:w}]},e)}var q=y.makeSpan(["mord","accent"],[w],e);return n?(n.children[0]=q,n.height=Math.max(q.height,n.height),n.classes[0]="mord",n):q},Rr=(r,e)=>{var t=r.isStretchy?q0.mathMLnode(r.label):new S.MathNode("mo",[v0(r.label,r.mode)]),a=new S.MathNode("mover",[X(r.base,e),t]);return a.setAttribute("accent","true"),a},T1=new RegExp(["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring"].map(r=>"\\"+r).join("|"));B({type:"accent",names:["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring","\\widecheck","\\widehat","\\widetilde","\\overrightarrow","\\overleftarrow","\\Overrightarrow","\\overleftrightarrow","\\overgroup","\\overlinesegment","\\overleftharpoon","\\overrightharpoon"],props:{numArgs:1},handler:(r,e)=>{var t=qe(e[0]),a=!T1.test(r.funcName),n=!a||r.funcName==="\\widehat"||r.funcName==="\\widetilde"||r.funcName==="\\widecheck";return{type:"accent",mode:r.parser.mode,label:r.funcName,isStretchy:a,isShifty:n,base:t}},htmlBuilder:wt,mathmlBuilder:Rr});B({type:"accent",names:["\\'","\\`","\\^","\\~","\\=","\\u","\\.",'\\"',"\\c","\\r","\\H","\\v","\\textcircled"],props:{numArgs:1,allowedInText:!0,allowedInMath:!0,argTypes:["primitive"]},handler:(r,e)=>{var t=e[0],a=r.parser.mode;return a==="math"&&(r.parser.settings.reportNonstrict("mathVsTextAccents","LaTeX's accent "+r.funcName+" works only in text mode"),a="text"),{type:"accent",mode:a,label:r.funcName,isStretchy:!1,isShifty:!0,base:t}},htmlBuilder:wt,mathmlBuilder:Rr});B({type:"accentUnder",names:["\\underleftarrow","\\underrightarrow","\\underleftrightarrow","\\undergroup","\\underlinesegment","\\utilde"],props:{numArgs:1},handler:(r,e)=>{var{parser:t,funcName:a}=r,n=e[0];return{type:"accentUnder",mode:t.mode,label:a,base:n}},htmlBuilder:(r,e)=>{var t=P(r.base,e),a=q0.svgSpan(r,e),n=r.label==="\\utilde"?.12:0,s=y.makeVList({positionType:"top",positionData:t.height,children:[{type:"elem",elem:a,wrapperClasses:["svg-align"]},{type:"kern",size:n},{type:"elem",elem:t}]},e);return y.makeSpan(["mord","accentunder"],[s],e)},mathmlBuilder:(r,e)=>{var t=q0.mathMLnode(r.label),a=new S.MathNode("munder",[X(r.base,e),t]);return a.setAttribute("accentunder","true"),a}});var ke=r=>{var e=new S.MathNode("mpadded",r?[r]:[]);return e.setAttribute("width","+0.6em"),e.setAttribute("lspace","0.3em"),e};B({type:"xArrow",names:["\\xleftarrow","\\xrightarrow","\\xLeftarrow","\\xRightarrow","\\xleftrightarrow","\\xLeftrightarrow","\\xhookleftarrow","\\xhookrightarrow","\\xmapsto","\\xrightharpoondown","\\xrightharpoonup","\\xleftharpoondown","\\xleftharpoonup","\\xrightleftharpoons","\\xleftrightharpoons","\\xlongequal","\\xtwoheadrightarrow","\\xtwoheadleftarrow","\\xtofrom","\\xrightleftarrows","\\xrightequilibrium","\\xleftequilibrium","\\\\cdrightarrow","\\\\cdleftarrow","\\\\cdlongequal"],props:{numArgs:1,numOptionalArgs:1},handler(r,e,t){var{parser:a,funcName:n}=r;return{type:"xArrow",mode:a.mode,label:n,body:e[0],below:t[0]}},htmlBuilder(r,e){var t=e.style,a=e.havingStyle(t.sup()),n=y.wrapFragment(P(r.body,a,e),e),s=r.label.slice(0,2)==="\\x"?"x":"cd";n.classes.push(s+"-arrow-pad");var o;r.below&&(a=e.havingStyle(t.sub()),o=y.wrapFragment(P(r.below,a,e),e),o.classes.push(s+"-arrow-pad"));var m=q0.svgSpan(r,e),c=-e.fontMetrics().axisHeight+.5*m.height,p=-e.fontMetrics().axisHeight-.5*m.height-.111;(n.depth>.25||r.label==="\\xleftequilibrium")&&(p-=n.depth);var g;if(o){var b=-e.fontMetrics().axisHeight+o.height+.5*m.height+.111;g=y.makeVList({positionType:"individualShift",children:[{type:"elem",elem:n,shift:p},{type:"elem",elem:m,shift:c},{type:"elem",elem:o,shift:b}]},e)}else g=y.makeVList({positionType:"individualShift",children:[{type:"elem",elem:n,shift:p},{type:"elem",elem:m,shift:c}]},e);return g.children[0].children[0].children[1].classes.push("svg-align"),y.makeSpan(["mrel","x-arrow"],[g],e)},mathmlBuilder(r,e){var t=q0.mathMLnode(r.label);t.setAttribute("minsize",r.label.charAt(0)==="x"?"1.75em":"3.0em");var a;if(r.body){var n=ke(X(r.body,e));if(r.below){var s=ke(X(r.below,e));a=new S.MathNode("munderover",[t,s,n])}else a=new S.MathNode("mover",[t,n])}else if(r.below){var o=ke(X(r.below,e));a=new S.MathNode("munder",[t,o])}else a=ke(),a=new S.MathNode("mover",[t,a]);return a}});var A1=y.makeSpan;function Er(r,e){var t=t0(r.body,e,!0);return A1([r.mclass],t,e)}function Ir(r,e){var t,a=o0(r.body,e);return r.mclass==="minner"?t=new S.MathNode("mpadded",a):r.mclass==="mord"?r.isCharacterBox?(t=a[0],t.type="mi"):t=new S.MathNode("mi",a):(r.isCharacterBox?(t=a[0],t.type="mo"):t=new S.MathNode("mo",a),r.mclass==="mbin"?(t.attributes.lspace="0.22em",t.attributes.rspace="0.22em"):r.mclass==="mpunct"?(t.attributes.lspace="0em",t.attributes.rspace="0.17em"):r.mclass==="mopen"||r.mclass==="mclose"?(t.attributes.lspace="0em",t.attributes.rspace="0em"):r.mclass==="minner"&&(t.attributes.lspace="0.0556em",t.attributes.width="+0.1111em")),t}B({type:"mclass",names:["\\mathord","\\mathbin","\\mathrel","\\mathopen","\\mathclose","\\mathpunct","\\mathinner"],props:{numArgs:1,primitive:!0},handler(r,e){var{parser:t,funcName:a}=r,n=e[0];return{type:"mclass",mode:t.mode,mclass:"m"+a.slice(5),body:Q(n),isCharacterBox:R.isCharacterBox(n)}},htmlBuilder:Er,mathmlBuilder:Ir});var De=r=>{var e=r.type==="ordgroup"&&r.body.length?r.body[0]:r;return e.type==="atom"&&(e.family==="bin"||e.family==="rel")?"m"+e.family:"mord"};B({type:"mclass",names:["\\@binrel"],props:{numArgs:2},handler(r,e){var{parser:t}=r;return{type:"mclass",mode:t.mode,mclass:De(e[0]),body:Q(e[1]),isCharacterBox:R.isCharacterBox(e[1])}}});B({type:"mclass",names:["\\stackrel","\\overset","\\underset"],props:{numArgs:2},handler(r,e){var{parser:t,funcName:a}=r,n=e[1],s=e[0],o;a!=="\\stackrel"?o=De(n):o="mrel";var m={type:"op",mode:n.mode,limits:!0,alwaysHandleSupSub:!0,parentIsSupSub:!1,symbol:!1,suppressBaseShift:a!=="\\stackrel",body:Q(n)},c={type:"supsub",mode:s.mode,base:m,sup:a==="\\underset"?null:s,sub:a==="\\underset"?s:null};return{type:"mclass",mode:t.mode,mclass:o,body:[c],isCharacterBox:R.isCharacterBox(c)}},htmlBuilder:Er,mathmlBuilder:Ir});B({type:"pmb",names:["\\pmb"],props:{numArgs:1,allowedInText:!0},handler(r,e){var{parser:t}=r;return{type:"pmb",mode:t.mode,mclass:De(e[0]),body:Q(e[0])}},htmlBuilder(r,e){var t=t0(r.body,e,!0),a=y.makeSpan([r.mclass],t,e);return a.style.textShadow="0.02em 0.01em 0.04px",a},mathmlBuilder(r,e){var t=o0(r.body,e),a=new S.MathNode("mstyle",t);return a.setAttribute("style","text-shadow: 0.02em 0.01em 0.04px"),a}});var B1={">":"\\\\cdrightarrow","<":"\\\\cdleftarrow","=":"\\\\cdlongequal",A:"\\uparrow",V:"\\downarrow","|":"\\Vert",".":"no arrow"},Wt=()=>({type:"styling",body:[],mode:"math",style:"display"}),jt=r=>r.type==="textord"&&r.text==="@",N1=(r,e)=>(r.type==="mathord"||r.type==="atom")&&r.text===e;function C1(r,e,t){var a=B1[r];switch(a){case"\\\\cdrightarrow":case"\\\\cdleftarrow":return t.callFunction(a,[e[0]],[e[1]]);case"\\uparrow":case"\\downarrow":{var n=t.callFunction("\\\\cdleft",[e[0]],[]),s={type:"atom",text:a,mode:"math",family:"rel"},o=t.callFunction("\\Big",[s],[]),m=t.callFunction("\\\\cdright",[e[1]],[]),c={type:"ordgroup",mode:"math",body:[n,o,m]};return t.callFunction("\\\\cdparent",[c],[])}case"\\\\cdlongequal":return t.callFunction("\\\\cdlongequal",[],[]);case"\\Vert":{var p={type:"textord",text:"\\Vert",mode:"math"};return t.callFunction("\\Big",[p],[])}default:return{type:"textord",text:" ",mode:"math"}}}function q1(r){var e=[];for(r.gullet.beginGroup(),r.gullet.macros.set("\\cr","\\\\\\relax"),r.gullet.beginGroup();;){e.push(r.parseExpression(!1,"\\\\")),r.gullet.endGroup(),r.gullet.beginGroup();var t=r.fetch().text;if(t==="&"||t==="\\\\")r.consume();else if(t==="\\end"){e[e.length-1].length===0&&e.pop();break}else throw new M("Expected \\\\ or \\cr or \\end",r.nextToken)}for(var a=[],n=[a],s=0;s-1))if("<>AV".indexOf(p)>-1)for(var b=0;b<2;b++){for(var w=!0,x=c+1;xAV=|." after @',o[c]);var z=C1(p,g,r),A={type:"styling",body:[z],mode:"math",style:"display"};a.push(A),m=Wt()}s%2===0?a.push(m):a.shift(),a=[],n.push(a)}r.gullet.endGroup(),r.gullet.endGroup();var C=new Array(n[0].length).fill({type:"align",align:"c",pregap:.25,postgap:.25});return{type:"array",mode:"math",body:n,arraystretch:1,addJot:!0,rowGaps:[null],cols:C,colSeparationType:"CD",hLinesBeforeRow:new Array(n.length+1).fill([])}}B({type:"cdlabel",names:["\\\\cdleft","\\\\cdright"],props:{numArgs:1},handler(r,e){var{parser:t,funcName:a}=r;return{type:"cdlabel",mode:t.mode,side:a.slice(4),label:e[0]}},htmlBuilder(r,e){var t=e.havingStyle(e.style.sup()),a=y.wrapFragment(P(r.label,t,e),e);return a.classes.push("cd-label-"+r.side),a.style.bottom=T(.8-a.depth),a.height=0,a.depth=0,a},mathmlBuilder(r,e){var t=new S.MathNode("mrow",[X(r.label,e)]);return t=new S.MathNode("mpadded",[t]),t.setAttribute("width","0"),r.side==="left"&&t.setAttribute("lspace","-1width"),t.setAttribute("voffset","0.7em"),t=new S.MathNode("mstyle",[t]),t.setAttribute("displaystyle","false"),t.setAttribute("scriptlevel","1"),t}});B({type:"cdlabelparent",names:["\\\\cdparent"],props:{numArgs:1},handler(r,e){var{parser:t}=r;return{type:"cdlabelparent",mode:t.mode,fragment:e[0]}},htmlBuilder(r,e){var t=y.wrapFragment(P(r.fragment,e),e);return t.classes.push("cd-vert-arrow"),t},mathmlBuilder(r,e){return new S.MathNode("mrow",[X(r.fragment,e)])}});B({type:"textord",names:["\\@char"],props:{numArgs:1,allowedInText:!0},handler(r,e){for(var{parser:t}=r,a=H(e[0],"ordgroup"),n=a.body,s="",o=0;o=1114111)throw new M("\\@char with invalid code point "+s);return c<=65535?p=String.fromCharCode(c):(c-=65536,p=String.fromCharCode((c>>10)+55296,(c&1023)+56320)),{type:"textord",mode:t.mode,text:p}}});var Dr=(r,e)=>{var t=t0(r.body,e.withColor(r.color),!1);return y.makeFragment(t)},Or=(r,e)=>{var t=o0(r.body,e.withColor(r.color)),a=new S.MathNode("mstyle",t);return a.setAttribute("mathcolor",r.color),a};B({type:"color",names:["\\textcolor"],props:{numArgs:2,allowedInText:!0,argTypes:["color","original"]},handler(r,e){var{parser:t}=r,a=H(e[0],"color-token").color,n=e[1];return{type:"color",mode:t.mode,color:a,body:Q(n)}},htmlBuilder:Dr,mathmlBuilder:Or});B({type:"color",names:["\\color"],props:{numArgs:1,allowedInText:!0,argTypes:["color"]},handler(r,e){var{parser:t,breakOnTokenText:a}=r,n=H(e[0],"color-token").color;t.gullet.macros.set("\\current@color",n);var s=t.parseExpression(!0,a);return{type:"color",mode:t.mode,color:n,body:s}},htmlBuilder:Dr,mathmlBuilder:Or});B({type:"cr",names:["\\\\"],props:{numArgs:0,numOptionalArgs:0,allowedInText:!0},handler(r,e,t){var{parser:a}=r,n=a.gullet.future().text==="["?a.parseSizeGroup(!0):null,s=!a.settings.displayMode||!a.settings.useStrictBehavior("newLineInDisplayMode","In LaTeX, \\\\ or \\newline does nothing in display mode");return{type:"cr",mode:a.mode,newLine:s,size:n&&H(n,"size").value}},htmlBuilder(r,e){var t=y.makeSpan(["mspace"],[],e);return r.newLine&&(t.classes.push("newline"),r.size&&(t.style.marginTop=T(K(r.size,e)))),t},mathmlBuilder(r,e){var t=new S.MathNode("mspace");return r.newLine&&(t.setAttribute("linebreak","newline"),r.size&&t.setAttribute("height",T(K(r.size,e)))),t}});var ht={"\\global":"\\global","\\long":"\\\\globallong","\\\\globallong":"\\\\globallong","\\def":"\\gdef","\\gdef":"\\gdef","\\edef":"\\xdef","\\xdef":"\\xdef","\\let":"\\\\globallet","\\futurelet":"\\\\globalfuture"},Lr=r=>{var e=r.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(e))throw new M("Expected a control sequence",r);return e},R1=r=>{var e=r.gullet.popToken();return e.text==="="&&(e=r.gullet.popToken(),e.text===" "&&(e=r.gullet.popToken())),e},Hr=(r,e,t,a)=>{var n=r.gullet.macros.get(t.text);n==null&&(t.noexpand=!0,n={tokens:[t],numArgs:0,unexpandable:!r.gullet.isExpandable(t.text)}),r.gullet.macros.set(e,n,a)};B({type:"internal",names:["\\global","\\long","\\\\globallong"],props:{numArgs:0,allowedInText:!0},handler(r){var{parser:e,funcName:t}=r;e.consumeSpaces();var a=e.fetch();if(ht[a.text])return(t==="\\global"||t==="\\\\globallong")&&(a.text=ht[a.text]),H(e.parseFunction(),"internal");throw new M("Invalid token after macro prefix",a)}});B({type:"internal",names:["\\def","\\gdef","\\edef","\\xdef"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler(r){var{parser:e,funcName:t}=r,a=e.gullet.popToken(),n=a.text;if(/^(?:[\\{}$&#^_]|EOF)$/.test(n))throw new M("Expected a control sequence",a);for(var s=0,o,m=[[]];e.gullet.future().text!=="{";)if(a=e.gullet.popToken(),a.text==="#"){if(e.gullet.future().text==="{"){o=e.gullet.future(),m[s].push("{");break}if(a=e.gullet.popToken(),!/^[1-9]$/.test(a.text))throw new M('Invalid argument number "'+a.text+'"');if(parseInt(a.text)!==s+1)throw new M('Argument number "'+a.text+'" out of order');s++,m.push([])}else{if(a.text==="EOF")throw new M("Expected a macro definition");m[s].push(a.text)}var{tokens:c}=e.gullet.consumeArg();return o&&c.unshift(o),(t==="\\edef"||t==="\\xdef")&&(c=e.gullet.expandTokens(c),c.reverse()),e.gullet.macros.set(n,{tokens:c,numArgs:s,delimiters:m},t===ht[t]),{type:"internal",mode:e.mode}}});B({type:"internal",names:["\\let","\\\\globallet"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler(r){var{parser:e,funcName:t}=r,a=Lr(e.gullet.popToken());e.gullet.consumeSpaces();var n=R1(e);return Hr(e,a,n,t==="\\\\globallet"),{type:"internal",mode:e.mode}}});B({type:"internal",names:["\\futurelet","\\\\globalfuture"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler(r){var{parser:e,funcName:t}=r,a=Lr(e.gullet.popToken()),n=e.gullet.popToken(),s=e.gullet.popToken();return Hr(e,a,s,t==="\\\\globalfuture"),e.gullet.pushToken(s),e.gullet.pushToken(n),{type:"internal",mode:e.mode}}});var ne=function(e,t,a){var n=Y.math[e]&&Y.math[e].replace,s=ft(n||e,t,a);if(!s)throw new Error("Unsupported symbol "+e+" and font size "+t+".");return s},xt=function(e,t,a,n){var s=a.havingBaseStyle(t),o=y.makeSpan(n.concat(s.sizingClasses(a)),[e],a),m=s.sizeMultiplier/a.sizeMultiplier;return o.height*=m,o.depth*=m,o.maxFontSize=s.sizeMultiplier,o},Fr=function(e,t,a){var n=t.havingBaseStyle(a),s=(1-t.sizeMultiplier/n.sizeMultiplier)*t.fontMetrics().axisHeight;e.classes.push("delimcenter"),e.style.top=T(s),e.height-=s,e.depth+=s},E1=function(e,t,a,n,s,o){var m=y.makeSymbol(e,"Main-Regular",s,n),c=xt(m,t,n,o);return a&&Fr(c,n,t),c},I1=function(e,t,a,n){return y.makeSymbol(e,"Size"+t+"-Regular",a,n)},Pr=function(e,t,a,n,s,o){var m=I1(e,t,s,n),c=xt(y.makeSpan(["delimsizing","size"+t],[m],n),I.TEXT,n,o);return a&&Fr(c,n,I.TEXT),c},je=function(e,t,a){var n;t==="Size1-Regular"?n="delim-size1":n="delim-size4";var s=y.makeSpan(["delimsizinginner",n],[y.makeSpan([],[y.makeSymbol(e,t,a)])]);return{type:"elem",elem:s}},Ze=function(e,t,a){var n=w0["Size4-Regular"][e.charCodeAt(0)]?w0["Size4-Regular"][e.charCodeAt(0)][4]:w0["Size1-Regular"][e.charCodeAt(0)][4],s=new P0("inner",Pa(e,Math.round(1e3*t))),o=new N0([s],{width:T(n),height:T(t),style:"width:"+T(n),viewBox:"0 0 "+1e3*n+" "+Math.round(1e3*t),preserveAspectRatio:"xMinYMin"}),m=y.makeSvgSpan([],[o],a);return m.height=t,m.style.height=T(t),m.style.width=T(n),{type:"elem",elem:m}},mt=.008,Se={type:"kern",size:-1*mt},D1=["|","\\lvert","\\rvert","\\vert"],O1=["\\|","\\lVert","\\rVert","\\Vert"],Gr=function(e,t,a,n,s,o){var m,c,p,g,b="",w=0;m=p=g=e,c=null;var x="Size1-Regular";e==="\\uparrow"?p=g="⏐":e==="\\Uparrow"?p=g="‖":e==="\\downarrow"?m=p="⏐":e==="\\Downarrow"?m=p="‖":e==="\\updownarrow"?(m="\\uparrow",p="⏐",g="\\downarrow"):e==="\\Updownarrow"?(m="\\Uparrow",p="‖",g="\\Downarrow"):R.contains(D1,e)?(p="∣",b="vert",w=333):R.contains(O1,e)?(p="∥",b="doublevert",w=556):e==="["||e==="\\lbrack"?(m="⎡",p="⎢",g="⎣",x="Size4-Regular",b="lbrack",w=667):e==="]"||e==="\\rbrack"?(m="⎤",p="⎥",g="⎦",x="Size4-Regular",b="rbrack",w=667):e==="\\lfloor"||e==="⌊"?(p=m="⎢",g="⎣",x="Size4-Regular",b="lfloor",w=667):e==="\\lceil"||e==="⌈"?(m="⎡",p=g="⎢",x="Size4-Regular",b="lceil",w=667):e==="\\rfloor"||e==="⌋"?(p=m="⎥",g="⎦",x="Size4-Regular",b="rfloor",w=667):e==="\\rceil"||e==="⌉"?(m="⎤",p=g="⎥",x="Size4-Regular",b="rceil",w=667):e==="("||e==="\\lparen"?(m="⎛",p="⎜",g="⎝",x="Size4-Regular",b="lparen",w=875):e===")"||e==="\\rparen"?(m="⎞",p="⎟",g="⎠",x="Size4-Regular",b="rparen",w=875):e==="\\{"||e==="\\lbrace"?(m="⎧",c="⎨",g="⎩",p="⎪",x="Size4-Regular"):e==="\\}"||e==="\\rbrace"?(m="⎫",c="⎬",g="⎭",p="⎪",x="Size4-Regular"):e==="\\lgroup"||e==="⟮"?(m="⎧",g="⎩",p="⎪",x="Size4-Regular"):e==="\\rgroup"||e==="⟯"?(m="⎫",g="⎭",p="⎪",x="Size4-Regular"):e==="\\lmoustache"||e==="⎰"?(m="⎧",g="⎭",p="⎪",x="Size4-Regular"):(e==="\\rmoustache"||e==="⎱")&&(m="⎫",g="⎩",p="⎪",x="Size4-Regular");var z=ne(m,x,s),A=z.height+z.depth,C=ne(p,x,s),q=C.height+C.depth,O=ne(g,x,s),L=O.height+O.depth,V=0,F=1;if(c!==null){var U=ne(c,x,s);V=U.height+U.depth,F=2}var G=A+L+V,j=Math.max(0,Math.ceil((t-G)/(F*q))),$=G+j*F*q,M0=n.fontMetrics().axisHeight;a&&(M0*=n.sizeMultiplier);var r0=$/2-M0,e0=[];if(b.length>0){var U0=$-A-L,s0=Math.round($*1e3),g0=Ga(b,Math.round(U0*1e3)),E0=new P0(b,g0),W0=(w/1e3).toFixed(3)+"em",j0=(s0/1e3).toFixed(3)+"em",Fe=new N0([E0],{width:W0,height:j0,viewBox:"0 0 "+w+" "+s0}),I0=y.makeSvgSpan([],[Fe],n);I0.height=s0/1e3,I0.style.width=W0,I0.style.height=j0,e0.push({type:"elem",elem:I0})}else{if(e0.push(je(g,x,s)),e0.push(Se),c===null){var D0=$-A-L+2*mt;e0.push(Ze(p,D0,n))}else{var u0=($-A-L-V)/2+2*mt;e0.push(Ze(p,u0,n)),e0.push(Se),e0.push(je(c,x,s)),e0.push(Se),e0.push(Ze(p,u0,n))}e0.push(Se),e0.push(je(m,x,s))}var ae=n.havingBaseStyle(I.TEXT),Pe=y.makeVList({positionType:"bottom",positionData:r0,children:e0},ae);return xt(y.makeSpan(["delimsizing","mult"],[Pe],ae),I.TEXT,n,o)},Ke=80,Je=.08,Qe=function(e,t,a,n,s){var o=Fa(e,n,a),m=new P0(e,o),c=new N0([m],{width:"400em",height:T(t),viewBox:"0 0 400000 "+a,preserveAspectRatio:"xMinYMin slice"});return y.makeSvgSpan(["hide-tail"],[c],s)},L1=function(e,t){var a=t.havingBaseSizing(),n=Xr("\\surd",e*a.sizeMultiplier,$r,a),s=a.sizeMultiplier,o=Math.max(0,t.minRuleThickness-t.fontMetrics().sqrtRuleThickness),m,c=0,p=0,g=0,b;return n.type==="small"?(g=1e3+1e3*o+Ke,e<1?s=1:e<1.4&&(s=.7),c=(1+o+Je)/s,p=(1+o)/s,m=Qe("sqrtMain",c,g,o,t),m.style.minWidth="0.853em",b=.833/s):n.type==="large"?(g=(1e3+Ke)*se[n.size],p=(se[n.size]+o)/s,c=(se[n.size]+o+Je)/s,m=Qe("sqrtSize"+n.size,c,g,o,t),m.style.minWidth="1.02em",b=1/s):(c=e+o+Je,p=e+o,g=Math.floor(1e3*e+o)+Ke,m=Qe("sqrtTall",c,g,o,t),m.style.minWidth="0.742em",b=1.056),m.height=p,m.style.height=T(c),{span:m,advanceWidth:b,ruleWidth:(t.fontMetrics().sqrtRuleThickness+o)*s}},Vr=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","⌊","⌋","\\lceil","\\rceil","⌈","⌉","\\surd"],H1=["\\uparrow","\\downarrow","\\updownarrow","\\Uparrow","\\Downarrow","\\Updownarrow","|","\\|","\\vert","\\Vert","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","⟮","⟯","\\lmoustache","\\rmoustache","⎰","⎱"],Ur=["<",">","\\langle","\\rangle","/","\\backslash","\\lt","\\gt"],se=[0,1.2,1.8,2.4,3],F1=function(e,t,a,n,s){if(e==="<"||e==="\\lt"||e==="⟨"?e="\\langle":(e===">"||e==="\\gt"||e==="⟩")&&(e="\\rangle"),R.contains(Vr,e)||R.contains(Ur,e))return Pr(e,t,!1,a,n,s);if(R.contains(H1,e))return Gr(e,se[t],!1,a,n,s);throw new M("Illegal delimiter: '"+e+"'")},P1=[{type:"small",style:I.SCRIPTSCRIPT},{type:"small",style:I.SCRIPT},{type:"small",style:I.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4}],G1=[{type:"small",style:I.SCRIPTSCRIPT},{type:"small",style:I.SCRIPT},{type:"small",style:I.TEXT},{type:"stack"}],$r=[{type:"small",style:I.SCRIPTSCRIPT},{type:"small",style:I.SCRIPT},{type:"small",style:I.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4},{type:"stack"}],V1=function(e){if(e.type==="small")return"Main-Regular";if(e.type==="large")return"Size"+e.size+"-Regular";if(e.type==="stack")return"Size4-Regular";throw new Error("Add support for delim type '"+e.type+"' here.")},Xr=function(e,t,a,n){for(var s=Math.min(2,3-n.style.size),o=s;ot)return a[o]}return a[a.length-1]},Yr=function(e,t,a,n,s,o){e==="<"||e==="\\lt"||e==="⟨"?e="\\langle":(e===">"||e==="\\gt"||e==="⟩")&&(e="\\rangle");var m;R.contains(Ur,e)?m=P1:R.contains(Vr,e)?m=$r:m=G1;var c=Xr(e,t,m,n);return c.type==="small"?E1(e,c.style,a,n,s,o):c.type==="large"?Pr(e,c.size,a,n,s,o):Gr(e,t,a,n,s,o)},U1=function(e,t,a,n,s,o){var m=n.fontMetrics().axisHeight*n.sizeMultiplier,c=901,p=5/n.fontMetrics().ptPerEm,g=Math.max(t-m,a+m),b=Math.max(g/500*c,2*g-p);return Yr(e,b,!0,n,s,o)},B0={sqrtImage:L1,sizedDelim:F1,sizeToMaxHeight:se,customSizedDelim:Yr,leftRightDelim:U1},Zt={"\\bigl":{mclass:"mopen",size:1},"\\Bigl":{mclass:"mopen",size:2},"\\biggl":{mclass:"mopen",size:3},"\\Biggl":{mclass:"mopen",size:4},"\\bigr":{mclass:"mclose",size:1},"\\Bigr":{mclass:"mclose",size:2},"\\biggr":{mclass:"mclose",size:3},"\\Biggr":{mclass:"mclose",size:4},"\\bigm":{mclass:"mrel",size:1},"\\Bigm":{mclass:"mrel",size:2},"\\biggm":{mclass:"mrel",size:3},"\\Biggm":{mclass:"mrel",size:4},"\\big":{mclass:"mord",size:1},"\\Big":{mclass:"mord",size:2},"\\bigg":{mclass:"mord",size:3},"\\Bigg":{mclass:"mord",size:4}},$1=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","⌊","⌋","\\lceil","\\rceil","⌈","⌉","<",">","\\langle","⟨","\\rangle","⟩","\\lt","\\gt","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","⟮","⟯","\\lmoustache","\\rmoustache","⎰","⎱","/","\\backslash","|","\\vert","\\|","\\Vert","\\uparrow","\\Uparrow","\\downarrow","\\Downarrow","\\updownarrow","\\Updownarrow","."];function Oe(r,e){var t=Ie(r);if(t&&R.contains($1,t.text))return t;throw t?new M("Invalid delimiter '"+t.text+"' after '"+e.funcName+"'",r):new M("Invalid delimiter type '"+r.type+"'",r)}B({type:"delimsizing",names:["\\bigl","\\Bigl","\\biggl","\\Biggl","\\bigr","\\Bigr","\\biggr","\\Biggr","\\bigm","\\Bigm","\\biggm","\\Biggm","\\big","\\Big","\\bigg","\\Bigg"],props:{numArgs:1,argTypes:["primitive"]},handler:(r,e)=>{var t=Oe(e[0],r);return{type:"delimsizing",mode:r.parser.mode,size:Zt[r.funcName].size,mclass:Zt[r.funcName].mclass,delim:t.text}},htmlBuilder:(r,e)=>r.delim==="."?y.makeSpan([r.mclass]):B0.sizedDelim(r.delim,r.size,e,r.mode,[r.mclass]),mathmlBuilder:r=>{var e=[];r.delim!=="."&&e.push(v0(r.delim,r.mode));var t=new S.MathNode("mo",e);r.mclass==="mopen"||r.mclass==="mclose"?t.setAttribute("fence","true"):t.setAttribute("fence","false"),t.setAttribute("stretchy","true");var a=T(B0.sizeToMaxHeight[r.size]);return t.setAttribute("minsize",a),t.setAttribute("maxsize",a),t}});function Kt(r){if(!r.body)throw new Error("Bug: The leftright ParseNode wasn't fully parsed.")}B({type:"leftright-right",names:["\\right"],props:{numArgs:1,primitive:!0},handler:(r,e)=>{var t=r.parser.gullet.macros.get("\\current@color");if(t&&typeof t!="string")throw new M("\\current@color set to non-string in \\right");return{type:"leftright-right",mode:r.parser.mode,delim:Oe(e[0],r).text,color:t}}});B({type:"leftright",names:["\\left"],props:{numArgs:1,primitive:!0},handler:(r,e)=>{var t=Oe(e[0],r),a=r.parser;++a.leftrightDepth;var n=a.parseExpression(!1);--a.leftrightDepth,a.expect("\\right",!1);var s=H(a.parseFunction(),"leftright-right");return{type:"leftright",mode:a.mode,body:n,left:t.text,right:s.delim,rightColor:s.color}},htmlBuilder:(r,e)=>{Kt(r);for(var t=t0(r.body,e,!0,["mopen","mclose"]),a=0,n=0,s=!1,o=0;o{Kt(r);var t=o0(r.body,e);if(r.left!=="."){var a=new S.MathNode("mo",[v0(r.left,r.mode)]);a.setAttribute("fence","true"),t.unshift(a)}if(r.right!=="."){var n=new S.MathNode("mo",[v0(r.right,r.mode)]);n.setAttribute("fence","true"),r.rightColor&&n.setAttribute("mathcolor",r.rightColor),t.push(n)}return gt(t)}});B({type:"middle",names:["\\middle"],props:{numArgs:1,primitive:!0},handler:(r,e)=>{var t=Oe(e[0],r);if(!r.parser.leftrightDepth)throw new M("\\middle without preceding \\left",t);return{type:"middle",mode:r.parser.mode,delim:t.text}},htmlBuilder:(r,e)=>{var t;if(r.delim===".")t=oe(e,[]);else{t=B0.sizedDelim(r.delim,1,e,r.mode,[]);var a={delim:r.delim,options:e};t.isMiddle=a}return t},mathmlBuilder:(r,e)=>{var t=r.delim==="\\vert"||r.delim==="|"?v0("|","text"):v0(r.delim,r.mode),a=new S.MathNode("mo",[t]);return a.setAttribute("fence","true"),a.setAttribute("lspace","0.05em"),a.setAttribute("rspace","0.05em"),a}});var kt=(r,e)=>{var t=y.wrapFragment(P(r.body,e),e),a=r.label.slice(1),n=e.sizeMultiplier,s,o=0,m=R.isCharacterBox(r.body);if(a==="sout")s=y.makeSpan(["stretchy","sout"]),s.height=e.fontMetrics().defaultRuleThickness/n,o=-.5*e.fontMetrics().xHeight;else if(a==="phase"){var c=K({number:.6,unit:"pt"},e),p=K({number:.35,unit:"ex"},e),g=e.havingBaseSizing();n=n/g.sizeMultiplier;var b=t.height+t.depth+c+p;t.style.paddingLeft=T(b/2+c);var w=Math.floor(1e3*b*n),x=La(w),z=new N0([new P0("phase",x)],{width:"400em",height:T(w/1e3),viewBox:"0 0 400000 "+w,preserveAspectRatio:"xMinYMin slice"});s=y.makeSvgSpan(["hide-tail"],[z],e),s.style.height=T(b),o=t.depth+c+p}else{/cancel/.test(a)?m||t.classes.push("cancel-pad"):a==="angl"?t.classes.push("anglpad"):t.classes.push("boxpad");var A=0,C=0,q=0;/box/.test(a)?(q=Math.max(e.fontMetrics().fboxrule,e.minRuleThickness),A=e.fontMetrics().fboxsep+(a==="colorbox"?0:q),C=A):a==="angl"?(q=Math.max(e.fontMetrics().defaultRuleThickness,e.minRuleThickness),A=4*q,C=Math.max(0,.25-t.depth)):(A=m?.2:0,C=A),s=q0.encloseSpan(t,a,A,C,e),/fbox|boxed|fcolorbox/.test(a)?(s.style.borderStyle="solid",s.style.borderWidth=T(q)):a==="angl"&&q!==.049&&(s.style.borderTopWidth=T(q),s.style.borderRightWidth=T(q)),o=t.depth+C,r.backgroundColor&&(s.style.backgroundColor=r.backgroundColor,r.borderColor&&(s.style.borderColor=r.borderColor))}var O;if(r.backgroundColor)O=y.makeVList({positionType:"individualShift",children:[{type:"elem",elem:s,shift:o},{type:"elem",elem:t,shift:0}]},e);else{var L=/cancel|phase/.test(a)?["svg-align"]:[];O=y.makeVList({positionType:"individualShift",children:[{type:"elem",elem:t,shift:0},{type:"elem",elem:s,shift:o,wrapperClasses:L}]},e)}return/cancel/.test(a)&&(O.height=t.height,O.depth=t.depth),/cancel/.test(a)&&!m?y.makeSpan(["mord","cancel-lap"],[O],e):y.makeSpan(["mord"],[O],e)},St=(r,e)=>{var t=0,a=new S.MathNode(r.label.indexOf("colorbox")>-1?"mpadded":"menclose",[X(r.body,e)]);switch(r.label){case"\\cancel":a.setAttribute("notation","updiagonalstrike");break;case"\\bcancel":a.setAttribute("notation","downdiagonalstrike");break;case"\\phase":a.setAttribute("notation","phasorangle");break;case"\\sout":a.setAttribute("notation","horizontalstrike");break;case"\\fbox":a.setAttribute("notation","box");break;case"\\angl":a.setAttribute("notation","actuarial");break;case"\\fcolorbox":case"\\colorbox":if(t=e.fontMetrics().fboxsep*e.fontMetrics().ptPerEm,a.setAttribute("width","+"+2*t+"pt"),a.setAttribute("height","+"+2*t+"pt"),a.setAttribute("lspace",t+"pt"),a.setAttribute("voffset",t+"pt"),r.label==="\\fcolorbox"){var n=Math.max(e.fontMetrics().fboxrule,e.minRuleThickness);a.setAttribute("style","border: "+n+"em solid "+String(r.borderColor))}break;case"\\xcancel":a.setAttribute("notation","updiagonalstrike downdiagonalstrike");break}return r.backgroundColor&&a.setAttribute("mathbackground",r.backgroundColor),a};B({type:"enclose",names:["\\colorbox"],props:{numArgs:2,allowedInText:!0,argTypes:["color","text"]},handler(r,e,t){var{parser:a,funcName:n}=r,s=H(e[0],"color-token").color,o=e[1];return{type:"enclose",mode:a.mode,label:n,backgroundColor:s,body:o}},htmlBuilder:kt,mathmlBuilder:St});B({type:"enclose",names:["\\fcolorbox"],props:{numArgs:3,allowedInText:!0,argTypes:["color","color","text"]},handler(r,e,t){var{parser:a,funcName:n}=r,s=H(e[0],"color-token").color,o=H(e[1],"color-token").color,m=e[2];return{type:"enclose",mode:a.mode,label:n,backgroundColor:o,borderColor:s,body:m}},htmlBuilder:kt,mathmlBuilder:St});B({type:"enclose",names:["\\fbox"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!0},handler(r,e){var{parser:t}=r;return{type:"enclose",mode:t.mode,label:"\\fbox",body:e[0]}}});B({type:"enclose",names:["\\cancel","\\bcancel","\\xcancel","\\sout","\\phase"],props:{numArgs:1},handler(r,e){var{parser:t,funcName:a}=r,n=e[0];return{type:"enclose",mode:t.mode,label:a,body:n}},htmlBuilder:kt,mathmlBuilder:St});B({type:"enclose",names:["\\angl"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!1},handler(r,e){var{parser:t}=r;return{type:"enclose",mode:t.mode,label:"\\angl",body:e[0]}}});var Wr={};function x0(r){for(var{type:e,names:t,props:a,handler:n,htmlBuilder:s,mathmlBuilder:o}=r,m={type:e,numArgs:a.numArgs||0,allowedInText:!1,numOptionalArgs:0,handler:n},c=0;c{var e=r.parser.settings;if(!e.displayMode)throw new M("{"+r.envName+"} can be used only in display mode.")};function Mt(r){if(r.indexOf("ed")===-1)return r.indexOf("*")===-1}function V0(r,e,t){var{hskipBeforeAndAfter:a,addJot:n,cols:s,arraystretch:o,colSeparationType:m,autoTag:c,singleRow:p,emptySingleRow:g,maxNumCols:b,leqno:w}=e;if(r.gullet.beginGroup(),p||r.gullet.macros.set("\\cr","\\\\\\relax"),!o){var x=r.gullet.expandMacroAsText("\\arraystretch");if(x==null)o=1;else if(o=parseFloat(x),!o||o<0)throw new M("Invalid \\arraystretch: "+x)}r.gullet.beginGroup();var z=[],A=[z],C=[],q=[],O=c!=null?[]:void 0;function L(){c&&r.gullet.macros.set("\\@eqnsw","1",!0)}function V(){O&&(r.gullet.macros.get("\\df@tag")?(O.push(r.subparse([new f0("\\df@tag")])),r.gullet.macros.set("\\df@tag",void 0,!0)):O.push(!!c&&r.gullet.macros.get("\\@eqnsw")==="1"))}for(L(),q.push(Jt(r));;){var F=r.parseExpression(!1,p?"\\end":"\\\\");r.gullet.endGroup(),r.gullet.beginGroup(),F={type:"ordgroup",mode:r.mode,body:F},t&&(F={type:"styling",mode:r.mode,style:t,body:[F]}),z.push(F);var U=r.fetch().text;if(U==="&"){if(b&&z.length===b){if(p||m)throw new M("Too many tab characters: &",r.nextToken);r.settings.reportNonstrict("textEnv","Too few columns specified in the {array} column argument.")}r.consume()}else if(U==="\\end"){V(),z.length===1&&F.type==="styling"&&F.body[0].body.length===0&&(A.length>1||!g)&&A.pop(),q.length0&&(L+=.25),p.push({pos:L,isDashed:fe[pe]})}for(V(o[0]),a=0;a0&&(r0+=O,Gfe))for(a=0;a=m)){var K0=void 0;(n>0||e.hskipBeforeAndAfter)&&(K0=R.deflt(u0.pregap,w),K0!==0&&(g0=y.makeSpan(["arraycolsep"],[]),g0.style.width=T(K0),s0.push(g0)));var J0=[];for(a=0;a0){for(var ca=y.makeLineSpan("hline",t,g),da=y.makeLineSpan("hdashline",t,g),Ge=[{type:"elem",elem:c,shift:0}];p.length>0;){var Et=p.pop(),It=Et.pos-e0;Et.isDashed?Ge.push({type:"elem",elem:da,shift:It}):Ge.push({type:"elem",elem:ca,shift:It})}c=y.makeVList({positionType:"individualShift",children:Ge},t)}if(W0.length===0)return y.makeSpan(["mord"],[c],t);var Ve=y.makeVList({positionType:"individualShift",children:W0},t);return Ve=y.makeSpan(["tag"],[Ve],t),y.makeFragment([c,Ve])},X1={c:"center ",l:"left ",r:"right "},S0=function(e,t){for(var a=[],n=new S.MathNode("mtd",[],["mtr-glue"]),s=new S.MathNode("mtd",[],["mml-eqn-num"]),o=0;o0){var z=e.cols,A="",C=!1,q=0,O=z.length;z[0].type==="separator"&&(w+="top ",q=1),z[z.length-1].type==="separator"&&(w+="bottom ",O-=1);for(var L=q;L0?"left ":"",w+=j[j.length-1].length>0?"right ":"";for(var $=1;$-1?"alignat":"align",s=e.envName==="split",o=V0(e.parser,{cols:a,addJot:!0,autoTag:s?void 0:Mt(e.envName),emptySingleRow:!0,colSeparationType:n,maxNumCols:s?2:void 0,leqno:e.parser.settings.leqno},"display"),m,c=0,p={type:"ordgroup",mode:e.mode,body:[]};if(t[0]&&t[0].type==="ordgroup"){for(var g="",b=0;b0&&x&&(C=1),a[z]={type:"align",align:A,pregap:C,postgap:0}}return o.colSeparationType=x?"align":"alignat",o};x0({type:"array",names:["array","darray"],props:{numArgs:1},handler(r,e){var t=Ie(e[0]),a=t?[e[0]]:H(e[0],"ordgroup").body,n=a.map(function(o){var m=yt(o),c=m.text;if("lcr".indexOf(c)!==-1)return{type:"align",align:c};if(c==="|")return{type:"separator",separator:"|"};if(c===":")return{type:"separator",separator:":"};throw new M("Unknown column alignment: "+c,o)}),s={cols:n,hskipBeforeAndAfter:!0,maxNumCols:n.length};return V0(r.parser,s,zt(r.envName))},htmlBuilder:k0,mathmlBuilder:S0});x0({type:"array",names:["matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","matrix*","pmatrix*","bmatrix*","Bmatrix*","vmatrix*","Vmatrix*"],props:{numArgs:0},handler(r){var e={matrix:null,pmatrix:["(",")"],bmatrix:["[","]"],Bmatrix:["\\{","\\}"],vmatrix:["|","|"],Vmatrix:["\\Vert","\\Vert"]}[r.envName.replace("*","")],t="c",a={hskipBeforeAndAfter:!1,cols:[{type:"align",align:t}]};if(r.envName.charAt(r.envName.length-1)==="*"){var n=r.parser;if(n.consumeSpaces(),n.fetch().text==="["){if(n.consume(),n.consumeSpaces(),t=n.fetch().text,"lcr".indexOf(t)===-1)throw new M("Expected l or c or r",n.nextToken);n.consume(),n.consumeSpaces(),n.expect("]"),n.consume(),a.cols=[{type:"align",align:t}]}}var s=V0(r.parser,a,zt(r.envName)),o=Math.max(0,...s.body.map(m=>m.length));return s.cols=new Array(o).fill({type:"align",align:t}),e?{type:"leftright",mode:r.mode,body:[s],left:e[0],right:e[1],rightColor:void 0}:s},htmlBuilder:k0,mathmlBuilder:S0});x0({type:"array",names:["smallmatrix"],props:{numArgs:0},handler(r){var e={arraystretch:.5},t=V0(r.parser,e,"script");return t.colSeparationType="small",t},htmlBuilder:k0,mathmlBuilder:S0});x0({type:"array",names:["subarray"],props:{numArgs:1},handler(r,e){var t=Ie(e[0]),a=t?[e[0]]:H(e[0],"ordgroup").body,n=a.map(function(o){var m=yt(o),c=m.text;if("lc".indexOf(c)!==-1)return{type:"align",align:c};throw new M("Unknown column alignment: "+c,o)});if(n.length>1)throw new M("{subarray} can contain only one column");var s={cols:n,hskipBeforeAndAfter:!1,arraystretch:.5};if(s=V0(r.parser,s,"script"),s.body.length>0&&s.body[0].length>1)throw new M("{subarray} can contain only one column");return s},htmlBuilder:k0,mathmlBuilder:S0});x0({type:"array",names:["cases","dcases","rcases","drcases"],props:{numArgs:0},handler(r){var e={arraystretch:1.2,cols:[{type:"align",align:"l",pregap:0,postgap:1},{type:"align",align:"l",pregap:0,postgap:0}]},t=V0(r.parser,e,zt(r.envName));return{type:"leftright",mode:r.mode,body:[t],left:r.envName.indexOf("r")>-1?".":"\\{",right:r.envName.indexOf("r")>-1?"\\}":".",rightColor:void 0}},htmlBuilder:k0,mathmlBuilder:S0});x0({type:"array",names:["align","align*","aligned","split"],props:{numArgs:0},handler:Zr,htmlBuilder:k0,mathmlBuilder:S0});x0({type:"array",names:["gathered","gather","gather*"],props:{numArgs:0},handler(r){R.contains(["gather","gather*"],r.envName)&&Le(r);var e={cols:[{type:"align",align:"c"}],addJot:!0,colSeparationType:"gather",autoTag:Mt(r.envName),emptySingleRow:!0,leqno:r.parser.settings.leqno};return V0(r.parser,e,"display")},htmlBuilder:k0,mathmlBuilder:S0});x0({type:"array",names:["alignat","alignat*","alignedat"],props:{numArgs:1},handler:Zr,htmlBuilder:k0,mathmlBuilder:S0});x0({type:"array",names:["equation","equation*"],props:{numArgs:0},handler(r){Le(r);var e={autoTag:Mt(r.envName),emptySingleRow:!0,singleRow:!0,maxNumCols:1,leqno:r.parser.settings.leqno};return V0(r.parser,e,"display")},htmlBuilder:k0,mathmlBuilder:S0});x0({type:"array",names:["CD"],props:{numArgs:0},handler(r){return Le(r),q1(r.parser)},htmlBuilder:k0,mathmlBuilder:S0});u("\\nonumber","\\gdef\\@eqnsw{0}");u("\\notag","\\nonumber");B({type:"text",names:["\\hline","\\hdashline"],props:{numArgs:0,allowedInText:!0,allowedInMath:!0},handler(r,e){throw new M(r.funcName+" valid only within array environment")}});var Qt=Wr;B({type:"environment",names:["\\begin","\\end"],props:{numArgs:1,argTypes:["text"]},handler(r,e){var{parser:t,funcName:a}=r,n=e[0];if(n.type!=="ordgroup")throw new M("Invalid environment name",n);for(var s="",o=0;o{var t=r.font,a=e.withFont(t);return P(r.body,a)},Jr=(r,e)=>{var t=r.font,a=e.withFont(t);return X(r.body,a)},_t={"\\Bbb":"\\mathbb","\\bold":"\\mathbf","\\frak":"\\mathfrak","\\bm":"\\boldsymbol"};B({type:"font",names:["\\mathrm","\\mathit","\\mathbf","\\mathnormal","\\mathbb","\\mathcal","\\mathfrak","\\mathscr","\\mathsf","\\mathtt","\\Bbb","\\bold","\\frak"],props:{numArgs:1,allowedInArgument:!0},handler:(r,e)=>{var{parser:t,funcName:a}=r,n=qe(e[0]),s=a;return s in _t&&(s=_t[s]),{type:"font",mode:t.mode,font:s.slice(1),body:n}},htmlBuilder:Kr,mathmlBuilder:Jr});B({type:"mclass",names:["\\boldsymbol","\\bm"],props:{numArgs:1},handler:(r,e)=>{var{parser:t}=r,a=e[0],n=R.isCharacterBox(a);return{type:"mclass",mode:t.mode,mclass:De(a),body:[{type:"font",mode:t.mode,font:"boldsymbol",body:a}],isCharacterBox:n}}});B({type:"font",names:["\\rm","\\sf","\\tt","\\bf","\\it","\\cal"],props:{numArgs:0,allowedInText:!0},handler:(r,e)=>{var{parser:t,funcName:a,breakOnTokenText:n}=r,{mode:s}=t,o=t.parseExpression(!0,n),m="math"+a.slice(1);return{type:"font",mode:s,font:m,body:{type:"ordgroup",mode:t.mode,body:o}}},htmlBuilder:Kr,mathmlBuilder:Jr});var Qr=(r,e)=>{var t=e;return r==="display"?t=t.id>=I.SCRIPT.id?t.text():I.DISPLAY:r==="text"&&t.size===I.DISPLAY.size?t=I.TEXT:r==="script"?t=I.SCRIPT:r==="scriptscript"&&(t=I.SCRIPTSCRIPT),t},Tt=(r,e)=>{var t=Qr(r.size,e.style),a=t.fracNum(),n=t.fracDen(),s;s=e.havingStyle(a);var o=P(r.numer,s,e);if(r.continued){var m=8.5/e.fontMetrics().ptPerEm,c=3.5/e.fontMetrics().ptPerEm;o.height=o.height0?z=3*w:z=7*w,A=e.fontMetrics().denom1):(b>0?(x=e.fontMetrics().num2,z=w):(x=e.fontMetrics().num3,z=3*w),A=e.fontMetrics().denom2);var C;if(g){var O=e.fontMetrics().axisHeight;x-o.depth-(O+.5*b){var t=new S.MathNode("mfrac",[X(r.numer,e),X(r.denom,e)]);if(!r.hasBarLine)t.setAttribute("linethickness","0px");else if(r.barSize){var a=K(r.barSize,e);t.setAttribute("linethickness",T(a))}var n=Qr(r.size,e.style);if(n.size!==e.style.size){t=new S.MathNode("mstyle",[t]);var s=n.size===I.DISPLAY.size?"true":"false";t.setAttribute("displaystyle",s),t.setAttribute("scriptlevel","0")}if(r.leftDelim!=null||r.rightDelim!=null){var o=[];if(r.leftDelim!=null){var m=new S.MathNode("mo",[new S.TextNode(r.leftDelim.replace("\\",""))]);m.setAttribute("fence","true"),o.push(m)}if(o.push(t),r.rightDelim!=null){var c=new S.MathNode("mo",[new S.TextNode(r.rightDelim.replace("\\",""))]);c.setAttribute("fence","true"),o.push(c)}return gt(o)}return t};B({type:"genfrac",names:["\\dfrac","\\frac","\\tfrac","\\dbinom","\\binom","\\tbinom","\\\\atopfrac","\\\\bracefrac","\\\\brackfrac"],props:{numArgs:2,allowedInArgument:!0},handler:(r,e)=>{var{parser:t,funcName:a}=r,n=e[0],s=e[1],o,m=null,c=null,p="auto";switch(a){case"\\dfrac":case"\\frac":case"\\tfrac":o=!0;break;case"\\\\atopfrac":o=!1;break;case"\\dbinom":case"\\binom":case"\\tbinom":o=!1,m="(",c=")";break;case"\\\\bracefrac":o=!1,m="\\{",c="\\}";break;case"\\\\brackfrac":o=!1,m="[",c="]";break;default:throw new Error("Unrecognized genfrac command")}switch(a){case"\\dfrac":case"\\dbinom":p="display";break;case"\\tfrac":case"\\tbinom":p="text";break}return{type:"genfrac",mode:t.mode,continued:!1,numer:n,denom:s,hasBarLine:o,leftDelim:m,rightDelim:c,size:p,barSize:null}},htmlBuilder:Tt,mathmlBuilder:At});B({type:"genfrac",names:["\\cfrac"],props:{numArgs:2},handler:(r,e)=>{var{parser:t,funcName:a}=r,n=e[0],s=e[1];return{type:"genfrac",mode:t.mode,continued:!0,numer:n,denom:s,hasBarLine:!0,leftDelim:null,rightDelim:null,size:"display",barSize:null}}});B({type:"infix",names:["\\over","\\choose","\\atop","\\brace","\\brack"],props:{numArgs:0,infix:!0},handler(r){var{parser:e,funcName:t,token:a}=r,n;switch(t){case"\\over":n="\\frac";break;case"\\choose":n="\\binom";break;case"\\atop":n="\\\\atopfrac";break;case"\\brace":n="\\\\bracefrac";break;case"\\brack":n="\\\\brackfrac";break;default:throw new Error("Unrecognized infix genfrac command")}return{type:"infix",mode:e.mode,replaceWith:n,token:a}}});var er=["display","text","script","scriptscript"],tr=function(e){var t=null;return e.length>0&&(t=e,t=t==="."?null:t),t};B({type:"genfrac",names:["\\genfrac"],props:{numArgs:6,allowedInArgument:!0,argTypes:["math","math","size","text","math","math"]},handler(r,e){var{parser:t}=r,a=e[4],n=e[5],s=qe(e[0]),o=s.type==="atom"&&s.family==="open"?tr(s.text):null,m=qe(e[1]),c=m.type==="atom"&&m.family==="close"?tr(m.text):null,p=H(e[2],"size"),g,b=null;p.isBlank?g=!0:(b=p.value,g=b.number>0);var w="auto",x=e[3];if(x.type==="ordgroup"){if(x.body.length>0){var z=H(x.body[0],"textord");w=er[Number(z.text)]}}else x=H(x,"textord"),w=er[Number(x.text)];return{type:"genfrac",mode:t.mode,numer:a,denom:n,continued:!1,hasBarLine:g,barSize:b,leftDelim:o,rightDelim:c,size:w}},htmlBuilder:Tt,mathmlBuilder:At});B({type:"infix",names:["\\above"],props:{numArgs:1,argTypes:["size"],infix:!0},handler(r,e){var{parser:t,funcName:a,token:n}=r;return{type:"infix",mode:t.mode,replaceWith:"\\\\abovefrac",size:H(e[0],"size").value,token:n}}});B({type:"genfrac",names:["\\\\abovefrac"],props:{numArgs:3,argTypes:["math","size","math"]},handler:(r,e)=>{var{parser:t,funcName:a}=r,n=e[0],s=ka(H(e[1],"infix").size),o=e[2],m=s.number>0;return{type:"genfrac",mode:t.mode,numer:n,denom:o,continued:!1,hasBarLine:m,barSize:s,leftDelim:null,rightDelim:null,size:"auto"}},htmlBuilder:Tt,mathmlBuilder:At});var _r=(r,e)=>{var t=e.style,a,n;r.type==="supsub"?(a=r.sup?P(r.sup,e.havingStyle(t.sup()),e):P(r.sub,e.havingStyle(t.sub()),e),n=H(r.base,"horizBrace")):n=H(r,"horizBrace");var s=P(n.base,e.havingBaseStyle(I.DISPLAY)),o=q0.svgSpan(n,e),m;if(n.isOver?(m=y.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:s},{type:"kern",size:.1},{type:"elem",elem:o}]},e),m.children[0].children[0].children[1].classes.push("svg-align")):(m=y.makeVList({positionType:"bottom",positionData:s.depth+.1+o.height,children:[{type:"elem",elem:o},{type:"kern",size:.1},{type:"elem",elem:s}]},e),m.children[0].children[0].children[0].classes.push("svg-align")),a){var c=y.makeSpan(["mord",n.isOver?"mover":"munder"],[m],e);n.isOver?m=y.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:c},{type:"kern",size:.2},{type:"elem",elem:a}]},e):m=y.makeVList({positionType:"bottom",positionData:c.depth+.2+a.height+a.depth,children:[{type:"elem",elem:a},{type:"kern",size:.2},{type:"elem",elem:c}]},e)}return y.makeSpan(["mord",n.isOver?"mover":"munder"],[m],e)},Y1=(r,e)=>{var t=q0.mathMLnode(r.label);return new S.MathNode(r.isOver?"mover":"munder",[X(r.base,e),t])};B({type:"horizBrace",names:["\\overbrace","\\underbrace"],props:{numArgs:1},handler(r,e){var{parser:t,funcName:a}=r;return{type:"horizBrace",mode:t.mode,label:a,isOver:/^\\over/.test(a),base:e[0]}},htmlBuilder:_r,mathmlBuilder:Y1});B({type:"href",names:["\\href"],props:{numArgs:2,argTypes:["url","original"],allowedInText:!0},handler:(r,e)=>{var{parser:t}=r,a=e[1],n=H(e[0],"url").url;return t.settings.isTrusted({command:"\\href",url:n})?{type:"href",mode:t.mode,href:n,body:Q(a)}:t.formatUnsupportedCmd("\\href")},htmlBuilder:(r,e)=>{var t=t0(r.body,e,!1);return y.makeAnchor(r.href,[],t,e)},mathmlBuilder:(r,e)=>{var t=G0(r.body,e);return t instanceof c0||(t=new c0("mrow",[t])),t.setAttribute("href",r.href),t}});B({type:"href",names:["\\url"],props:{numArgs:1,argTypes:["url"],allowedInText:!0},handler:(r,e)=>{var{parser:t}=r,a=H(e[0],"url").url;if(!t.settings.isTrusted({command:"\\url",url:a}))return t.formatUnsupportedCmd("\\url");for(var n=[],s=0;s{var{parser:t,funcName:a,token:n}=r,s=H(e[0],"raw").string,o=e[1];t.settings.strict&&t.settings.reportNonstrict("htmlExtension","HTML extension is disabled on strict mode");var m,c={};switch(a){case"\\htmlClass":c.class=s,m={command:"\\htmlClass",class:s};break;case"\\htmlId":c.id=s,m={command:"\\htmlId",id:s};break;case"\\htmlStyle":c.style=s,m={command:"\\htmlStyle",style:s};break;case"\\htmlData":{for(var p=s.split(","),g=0;g{var t=t0(r.body,e,!1),a=["enclosing"];r.attributes.class&&a.push(...r.attributes.class.trim().split(/\s+/));var n=y.makeSpan(a,t,e);for(var s in r.attributes)s!=="class"&&r.attributes.hasOwnProperty(s)&&n.setAttribute(s,r.attributes[s]);return n},mathmlBuilder:(r,e)=>G0(r.body,e)});B({type:"htmlmathml",names:["\\html@mathml"],props:{numArgs:2,allowedInText:!0},handler:(r,e)=>{var{parser:t}=r;return{type:"htmlmathml",mode:t.mode,html:Q(e[0]),mathml:Q(e[1])}},htmlBuilder:(r,e)=>{var t=t0(r.html,e,!1);return y.makeFragment(t)},mathmlBuilder:(r,e)=>G0(r.mathml,e)});var _e=function(e){if(/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(e))return{number:+e,unit:"bp"};var t=/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(e);if(!t)throw new M("Invalid size: '"+e+"' in \\includegraphics");var a={number:+(t[1]+t[2]),unit:t[3]};if(!br(a))throw new M("Invalid unit: '"+a.unit+"' in \\includegraphics.");return a};B({type:"includegraphics",names:["\\includegraphics"],props:{numArgs:1,numOptionalArgs:1,argTypes:["raw","url"],allowedInText:!1},handler:(r,e,t)=>{var{parser:a}=r,n={number:0,unit:"em"},s={number:.9,unit:"em"},o={number:0,unit:"em"},m="";if(t[0])for(var c=H(t[0],"raw").string,p=c.split(","),g=0;g{var t=K(r.height,e),a=0;r.totalheight.number>0&&(a=K(r.totalheight,e)-t);var n=0;r.width.number>0&&(n=K(r.width,e));var s={height:T(t+a)};n>0&&(s.width=T(n)),a>0&&(s.verticalAlign=T(-a));var o=new Ya(r.src,r.alt,s);return o.height=t,o.depth=a,o},mathmlBuilder:(r,e)=>{var t=new S.MathNode("mglyph",[]);t.setAttribute("alt",r.alt);var a=K(r.height,e),n=0;if(r.totalheight.number>0&&(n=K(r.totalheight,e)-a,t.setAttribute("valign",T(-n))),t.setAttribute("height",T(a+n)),r.width.number>0){var s=K(r.width,e);t.setAttribute("width",T(s))}return t.setAttribute("src",r.src),t}});B({type:"kern",names:["\\kern","\\mkern","\\hskip","\\mskip"],props:{numArgs:1,argTypes:["size"],primitive:!0,allowedInText:!0},handler(r,e){var{parser:t,funcName:a}=r,n=H(e[0],"size");if(t.settings.strict){var s=a[1]==="m",o=n.value.unit==="mu";s?(o||t.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+a+" supports only mu units, "+("not "+n.value.unit+" units")),t.mode!=="math"&&t.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+a+" works only in math mode")):o&&t.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+a+" doesn't support mu units")}return{type:"kern",mode:t.mode,dimension:n.value}},htmlBuilder(r,e){return y.makeGlue(r.dimension,e)},mathmlBuilder(r,e){var t=K(r.dimension,e);return new S.SpaceNode(t)}});B({type:"lap",names:["\\mathllap","\\mathrlap","\\mathclap"],props:{numArgs:1,allowedInText:!0},handler:(r,e)=>{var{parser:t,funcName:a}=r,n=e[0];return{type:"lap",mode:t.mode,alignment:a.slice(5),body:n}},htmlBuilder:(r,e)=>{var t;r.alignment==="clap"?(t=y.makeSpan([],[P(r.body,e)]),t=y.makeSpan(["inner"],[t],e)):t=y.makeSpan(["inner"],[P(r.body,e)]);var a=y.makeSpan(["fix"],[]),n=y.makeSpan([r.alignment],[t,a],e),s=y.makeSpan(["strut"]);return s.style.height=T(n.height+n.depth),n.depth&&(s.style.verticalAlign=T(-n.depth)),n.children.unshift(s),n=y.makeSpan(["thinbox"],[n],e),y.makeSpan(["mord","vbox"],[n],e)},mathmlBuilder:(r,e)=>{var t=new S.MathNode("mpadded",[X(r.body,e)]);if(r.alignment!=="rlap"){var a=r.alignment==="llap"?"-1":"-0.5";t.setAttribute("lspace",a+"width")}return t.setAttribute("width","0px"),t}});B({type:"styling",names:["\\(","$"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler(r,e){var{funcName:t,parser:a}=r,n=a.mode;a.switchMode("math");var s=t==="\\("?"\\)":"$",o=a.parseExpression(!1,s);return a.expect(s),a.switchMode(n),{type:"styling",mode:a.mode,style:"text",body:o}}});B({type:"text",names:["\\)","\\]"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler(r,e){throw new M("Mismatched "+r.funcName)}});var rr=(r,e)=>{switch(e.style.size){case I.DISPLAY.size:return r.display;case I.TEXT.size:return r.text;case I.SCRIPT.size:return r.script;case I.SCRIPTSCRIPT.size:return r.scriptscript;default:return r.text}};B({type:"mathchoice",names:["\\mathchoice"],props:{numArgs:4,primitive:!0},handler:(r,e)=>{var{parser:t}=r;return{type:"mathchoice",mode:t.mode,display:Q(e[0]),text:Q(e[1]),script:Q(e[2]),scriptscript:Q(e[3])}},htmlBuilder:(r,e)=>{var t=rr(r,e),a=t0(t,e,!1);return y.makeFragment(a)},mathmlBuilder:(r,e)=>{var t=rr(r,e);return G0(t,e)}});var ea=(r,e,t,a,n,s,o)=>{r=y.makeSpan([],[r]);var m=t&&R.isCharacterBox(t),c,p;if(e){var g=P(e,a.havingStyle(n.sup()),a);p={elem:g,kern:Math.max(a.fontMetrics().bigOpSpacing1,a.fontMetrics().bigOpSpacing3-g.depth)}}if(t){var b=P(t,a.havingStyle(n.sub()),a);c={elem:b,kern:Math.max(a.fontMetrics().bigOpSpacing2,a.fontMetrics().bigOpSpacing4-b.height)}}var w;if(p&&c){var x=a.fontMetrics().bigOpSpacing5+c.elem.height+c.elem.depth+c.kern+r.depth+o;w=y.makeVList({positionType:"bottom",positionData:x,children:[{type:"kern",size:a.fontMetrics().bigOpSpacing5},{type:"elem",elem:c.elem,marginLeft:T(-s)},{type:"kern",size:c.kern},{type:"elem",elem:r},{type:"kern",size:p.kern},{type:"elem",elem:p.elem,marginLeft:T(s)},{type:"kern",size:a.fontMetrics().bigOpSpacing5}]},a)}else if(c){var z=r.height-o;w=y.makeVList({positionType:"top",positionData:z,children:[{type:"kern",size:a.fontMetrics().bigOpSpacing5},{type:"elem",elem:c.elem,marginLeft:T(-s)},{type:"kern",size:c.kern},{type:"elem",elem:r}]},a)}else if(p){var A=r.depth+o;w=y.makeVList({positionType:"bottom",positionData:A,children:[{type:"elem",elem:r},{type:"kern",size:p.kern},{type:"elem",elem:p.elem,marginLeft:T(s)},{type:"kern",size:a.fontMetrics().bigOpSpacing5}]},a)}else return r;var C=[w];if(c&&s!==0&&!m){var q=y.makeSpan(["mspace"],[],a);q.style.marginRight=T(s),C.unshift(q)}return y.makeSpan(["mop","op-limits"],C,a)},ta=["\\smallint"],re=(r,e)=>{var t,a,n=!1,s;r.type==="supsub"?(t=r.sup,a=r.sub,s=H(r.base,"op"),n=!0):s=H(r,"op");var o=e.style,m=!1;o.size===I.DISPLAY.size&&s.symbol&&!R.contains(ta,s.name)&&(m=!0);var c;if(s.symbol){var p=m?"Size2-Regular":"Size1-Regular",g="";if((s.name==="\\oiint"||s.name==="\\oiiint")&&(g=s.name.slice(1),s.name=g==="oiint"?"\\iint":"\\iiint"),c=y.makeSymbol(s.name,p,"math",e,["mop","op-symbol",m?"large-op":"small-op"]),g.length>0){var b=c.italic,w=y.staticSvg(g+"Size"+(m?"2":"1"),e);c=y.makeVList({positionType:"individualShift",children:[{type:"elem",elem:c,shift:0},{type:"elem",elem:w,shift:m?.08:0}]},e),s.name="\\"+g,c.classes.unshift("mop"),c.italic=b}}else if(s.body){var x=t0(s.body,e,!0);x.length===1&&x[0]instanceof p0?(c=x[0],c.classes[0]="mop"):c=y.makeSpan(["mop"],x,e)}else{for(var z=[],A=1;A{var t;if(r.symbol)t=new c0("mo",[v0(r.name,r.mode)]),R.contains(ta,r.name)&&t.setAttribute("largeop","false");else if(r.body)t=new c0("mo",o0(r.body,e));else{t=new c0("mi",[new ie(r.name.slice(1))]);var a=new c0("mo",[v0("⁡","text")]);r.parentIsSupSub?t=new c0("mrow",[t,a]):t=Nr([t,a])}return t},W1={"∏":"\\prod","∐":"\\coprod","∑":"\\sum","⋀":"\\bigwedge","⋁":"\\bigvee","⋂":"\\bigcap","⋃":"\\bigcup","⨀":"\\bigodot","⨁":"\\bigoplus","⨂":"\\bigotimes","⨄":"\\biguplus","⨆":"\\bigsqcup"};B({type:"op",names:["\\coprod","\\bigvee","\\bigwedge","\\biguplus","\\bigcap","\\bigcup","\\intop","\\prod","\\sum","\\bigotimes","\\bigoplus","\\bigodot","\\bigsqcup","\\smallint","∏","∐","∑","⋀","⋁","⋂","⋃","⨀","⨁","⨂","⨄","⨆"],props:{numArgs:0},handler:(r,e)=>{var{parser:t,funcName:a}=r,n=a;return n.length===1&&(n=W1[n]),{type:"op",mode:t.mode,limits:!0,parentIsSupSub:!1,symbol:!0,name:n}},htmlBuilder:re,mathmlBuilder:ue});B({type:"op",names:["\\mathop"],props:{numArgs:1,primitive:!0},handler:(r,e)=>{var{parser:t}=r,a=e[0];return{type:"op",mode:t.mode,limits:!1,parentIsSupSub:!1,symbol:!1,body:Q(a)}},htmlBuilder:re,mathmlBuilder:ue});var j1={"∫":"\\int","∬":"\\iint","∭":"\\iiint","∮":"\\oint","∯":"\\oiint","∰":"\\oiiint"};B({type:"op",names:["\\arcsin","\\arccos","\\arctan","\\arctg","\\arcctg","\\arg","\\ch","\\cos","\\cosec","\\cosh","\\cot","\\cotg","\\coth","\\csc","\\ctg","\\cth","\\deg","\\dim","\\exp","\\hom","\\ker","\\lg","\\ln","\\log","\\sec","\\sin","\\sinh","\\sh","\\tan","\\tanh","\\tg","\\th"],props:{numArgs:0},handler(r){var{parser:e,funcName:t}=r;return{type:"op",mode:e.mode,limits:!1,parentIsSupSub:!1,symbol:!1,name:t}},htmlBuilder:re,mathmlBuilder:ue});B({type:"op",names:["\\det","\\gcd","\\inf","\\lim","\\max","\\min","\\Pr","\\sup"],props:{numArgs:0},handler(r){var{parser:e,funcName:t}=r;return{type:"op",mode:e.mode,limits:!0,parentIsSupSub:!1,symbol:!1,name:t}},htmlBuilder:re,mathmlBuilder:ue});B({type:"op",names:["\\int","\\iint","\\iiint","\\oint","\\oiint","\\oiiint","∫","∬","∭","∮","∯","∰"],props:{numArgs:0},handler(r){var{parser:e,funcName:t}=r,a=t;return a.length===1&&(a=j1[a]),{type:"op",mode:e.mode,limits:!1,parentIsSupSub:!1,symbol:!0,name:a}},htmlBuilder:re,mathmlBuilder:ue});var ra=(r,e)=>{var t,a,n=!1,s;r.type==="supsub"?(t=r.sup,a=r.sub,s=H(r.base,"operatorname"),n=!0):s=H(r,"operatorname");var o;if(s.body.length>0){for(var m=s.body.map(b=>{var w=b.text;return typeof w=="string"?{type:"textord",mode:b.mode,text:w}:b}),c=t0(m,e.withFont("mathrm"),!0),p=0;p{for(var t=o0(r.body,e.withFont("mathrm")),a=!0,n=0;ng.toText()).join("");t=[new S.TextNode(m)]}var c=new S.MathNode("mi",t);c.setAttribute("mathvariant","normal");var p=new S.MathNode("mo",[v0("⁡","text")]);return r.parentIsSupSub?new S.MathNode("mrow",[c,p]):S.newDocumentFragment([c,p])};B({type:"operatorname",names:["\\operatorname@","\\operatornamewithlimits"],props:{numArgs:1},handler:(r,e)=>{var{parser:t,funcName:a}=r,n=e[0];return{type:"operatorname",mode:t.mode,body:Q(n),alwaysHandleSupSub:a==="\\operatornamewithlimits",limits:!1,parentIsSupSub:!1}},htmlBuilder:ra,mathmlBuilder:Z1});u("\\operatorname","\\@ifstar\\operatornamewithlimits\\operatorname@");Y0({type:"ordgroup",htmlBuilder(r,e){return r.semisimple?y.makeFragment(t0(r.body,e,!1)):y.makeSpan(["mord"],t0(r.body,e,!0),e)},mathmlBuilder(r,e){return G0(r.body,e,!0)}});B({type:"overline",names:["\\overline"],props:{numArgs:1},handler(r,e){var{parser:t}=r,a=e[0];return{type:"overline",mode:t.mode,body:a}},htmlBuilder(r,e){var t=P(r.body,e.havingCrampedStyle()),a=y.makeLineSpan("overline-line",e),n=e.fontMetrics().defaultRuleThickness,s=y.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:t},{type:"kern",size:3*n},{type:"elem",elem:a},{type:"kern",size:n}]},e);return y.makeSpan(["mord","overline"],[s],e)},mathmlBuilder(r,e){var t=new S.MathNode("mo",[new S.TextNode("‾")]);t.setAttribute("stretchy","true");var a=new S.MathNode("mover",[X(r.body,e),t]);return a.setAttribute("accent","true"),a}});B({type:"phantom",names:["\\phantom"],props:{numArgs:1,allowedInText:!0},handler:(r,e)=>{var{parser:t}=r,a=e[0];return{type:"phantom",mode:t.mode,body:Q(a)}},htmlBuilder:(r,e)=>{var t=t0(r.body,e.withPhantom(),!1);return y.makeFragment(t)},mathmlBuilder:(r,e)=>{var t=o0(r.body,e);return new S.MathNode("mphantom",t)}});B({type:"hphantom",names:["\\hphantom"],props:{numArgs:1,allowedInText:!0},handler:(r,e)=>{var{parser:t}=r,a=e[0];return{type:"hphantom",mode:t.mode,body:a}},htmlBuilder:(r,e)=>{var t=y.makeSpan([],[P(r.body,e.withPhantom())]);if(t.height=0,t.depth=0,t.children)for(var a=0;a{var t=o0(Q(r.body),e),a=new S.MathNode("mphantom",t),n=new S.MathNode("mpadded",[a]);return n.setAttribute("height","0px"),n.setAttribute("depth","0px"),n}});B({type:"vphantom",names:["\\vphantom"],props:{numArgs:1,allowedInText:!0},handler:(r,e)=>{var{parser:t}=r,a=e[0];return{type:"vphantom",mode:t.mode,body:a}},htmlBuilder:(r,e)=>{var t=y.makeSpan(["inner"],[P(r.body,e.withPhantom())]),a=y.makeSpan(["fix"],[]);return y.makeSpan(["mord","rlap"],[t,a],e)},mathmlBuilder:(r,e)=>{var t=o0(Q(r.body),e),a=new S.MathNode("mphantom",t),n=new S.MathNode("mpadded",[a]);return n.setAttribute("width","0px"),n}});B({type:"raisebox",names:["\\raisebox"],props:{numArgs:2,argTypes:["size","hbox"],allowedInText:!0},handler(r,e){var{parser:t}=r,a=H(e[0],"size").value,n=e[1];return{type:"raisebox",mode:t.mode,dy:a,body:n}},htmlBuilder(r,e){var t=P(r.body,e),a=K(r.dy,e);return y.makeVList({positionType:"shift",positionData:-a,children:[{type:"elem",elem:t}]},e)},mathmlBuilder(r,e){var t=new S.MathNode("mpadded",[X(r.body,e)]),a=r.dy.number+r.dy.unit;return t.setAttribute("voffset",a),t}});B({type:"internal",names:["\\relax"],props:{numArgs:0,allowedInText:!0},handler(r){var{parser:e}=r;return{type:"internal",mode:e.mode}}});B({type:"rule",names:["\\rule"],props:{numArgs:2,numOptionalArgs:1,argTypes:["size","size","size"]},handler(r,e,t){var{parser:a}=r,n=t[0],s=H(e[0],"size"),o=H(e[1],"size");return{type:"rule",mode:a.mode,shift:n&&H(n,"size").value,width:s.value,height:o.value}},htmlBuilder(r,e){var t=y.makeSpan(["mord","rule"],[],e),a=K(r.width,e),n=K(r.height,e),s=r.shift?K(r.shift,e):0;return t.style.borderRightWidth=T(a),t.style.borderTopWidth=T(n),t.style.bottom=T(s),t.width=a,t.height=n+s,t.depth=-s,t.maxFontSize=n*1.125*e.sizeMultiplier,t},mathmlBuilder(r,e){var t=K(r.width,e),a=K(r.height,e),n=r.shift?K(r.shift,e):0,s=e.color&&e.getColor()||"black",o=new S.MathNode("mspace");o.setAttribute("mathbackground",s),o.setAttribute("width",T(t)),o.setAttribute("height",T(a));var m=new S.MathNode("mpadded",[o]);return n>=0?m.setAttribute("height",T(n)):(m.setAttribute("height",T(n)),m.setAttribute("depth",T(-n))),m.setAttribute("voffset",T(n)),m}});function aa(r,e,t){for(var a=t0(r,e,!1),n=e.sizeMultiplier/t.sizeMultiplier,s=0;s{var t=e.havingSize(r.size);return aa(r.body,t,e)};B({type:"sizing",names:ar,props:{numArgs:0,allowedInText:!0},handler:(r,e)=>{var{breakOnTokenText:t,funcName:a,parser:n}=r,s=n.parseExpression(!1,t);return{type:"sizing",mode:n.mode,size:ar.indexOf(a)+1,body:s}},htmlBuilder:K1,mathmlBuilder:(r,e)=>{var t=e.havingSize(r.size),a=o0(r.body,t),n=new S.MathNode("mstyle",a);return n.setAttribute("mathsize",T(t.sizeMultiplier)),n}});B({type:"smash",names:["\\smash"],props:{numArgs:1,numOptionalArgs:1,allowedInText:!0},handler:(r,e,t)=>{var{parser:a}=r,n=!1,s=!1,o=t[0]&&H(t[0],"ordgroup");if(o)for(var m="",c=0;c{var t=y.makeSpan([],[P(r.body,e)]);if(!r.smashHeight&&!r.smashDepth)return t;if(r.smashHeight&&(t.height=0,t.children))for(var a=0;a{var t=new S.MathNode("mpadded",[X(r.body,e)]);return r.smashHeight&&t.setAttribute("height","0px"),r.smashDepth&&t.setAttribute("depth","0px"),t}});B({type:"sqrt",names:["\\sqrt"],props:{numArgs:1,numOptionalArgs:1},handler(r,e,t){var{parser:a}=r,n=t[0],s=e[0];return{type:"sqrt",mode:a.mode,body:s,index:n}},htmlBuilder(r,e){var t=P(r.body,e.havingCrampedStyle());t.height===0&&(t.height=e.fontMetrics().xHeight),t=y.wrapFragment(t,e);var a=e.fontMetrics(),n=a.defaultRuleThickness,s=n;e.style.idt.height+t.depth+o&&(o=(o+b-t.height-t.depth)/2);var w=c.height-t.height-o-p;t.style.paddingLeft=T(g);var x=y.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:t,wrapperClasses:["svg-align"]},{type:"kern",size:-(t.height+w)},{type:"elem",elem:c},{type:"kern",size:p}]},e);if(r.index){var z=e.havingStyle(I.SCRIPTSCRIPT),A=P(r.index,z,e),C=.6*(x.height-x.depth),q=y.makeVList({positionType:"shift",positionData:-C,children:[{type:"elem",elem:A}]},e),O=y.makeSpan(["root"],[q]);return y.makeSpan(["mord","sqrt"],[O,x],e)}else return y.makeSpan(["mord","sqrt"],[x],e)},mathmlBuilder(r,e){var{body:t,index:a}=r;return a?new S.MathNode("mroot",[X(t,e),X(a,e)]):new S.MathNode("msqrt",[X(t,e)])}});var nr={display:I.DISPLAY,text:I.TEXT,script:I.SCRIPT,scriptscript:I.SCRIPTSCRIPT};B({type:"styling",names:["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler(r,e){var{breakOnTokenText:t,funcName:a,parser:n}=r,s=n.parseExpression(!0,t),o=a.slice(1,a.length-5);return{type:"styling",mode:n.mode,style:o,body:s}},htmlBuilder(r,e){var t=nr[r.style],a=e.havingStyle(t).withFont("");return aa(r.body,a,e)},mathmlBuilder(r,e){var t=nr[r.style],a=e.havingStyle(t),n=o0(r.body,a),s=new S.MathNode("mstyle",n),o={display:["0","true"],text:["0","false"],script:["1","false"],scriptscript:["2","false"]},m=o[r.style];return s.setAttribute("scriptlevel",m[0]),s.setAttribute("displaystyle",m[1]),s}});var J1=function(e,t){var a=e.base;if(a)if(a.type==="op"){var n=a.limits&&(t.style.size===I.DISPLAY.size||a.alwaysHandleSupSub);return n?re:null}else if(a.type==="operatorname"){var s=a.alwaysHandleSupSub&&(t.style.size===I.DISPLAY.size||a.limits);return s?ra:null}else{if(a.type==="accent")return R.isCharacterBox(a.base)?wt:null;if(a.type==="horizBrace"){var o=!e.sub;return o===a.isOver?_r:null}else return null}else return null};Y0({type:"supsub",htmlBuilder(r,e){var t=J1(r,e);if(t)return t(r,e);var{base:a,sup:n,sub:s}=r,o=P(a,e),m,c,p=e.fontMetrics(),g=0,b=0,w=a&&R.isCharacterBox(a);if(n){var x=e.havingStyle(e.style.sup());m=P(n,x,e),w||(g=o.height-x.fontMetrics().supDrop*x.sizeMultiplier/e.sizeMultiplier)}if(s){var z=e.havingStyle(e.style.sub());c=P(s,z,e),w||(b=o.depth+z.fontMetrics().subDrop*z.sizeMultiplier/e.sizeMultiplier)}var A;e.style===I.DISPLAY?A=p.sup1:e.style.cramped?A=p.sup3:A=p.sup2;var C=e.sizeMultiplier,q=T(.5/p.ptPerEm/C),O=null;if(c){var L=r.base&&r.base.type==="op"&&r.base.name&&(r.base.name==="\\oiint"||r.base.name==="\\oiiint");(o instanceof p0||L)&&(O=T(-o.italic))}var V;if(m&&c){g=Math.max(g,A,m.depth+.25*p.xHeight),b=Math.max(b,p.sub2);var F=p.defaultRuleThickness,U=4*F;if(g-m.depth-(c.height-b)0&&(g+=G,b-=G)}var j=[{type:"elem",elem:c,shift:b,marginRight:q,marginLeft:O},{type:"elem",elem:m,shift:-g,marginRight:q}];V=y.makeVList({positionType:"individualShift",children:j},e)}else if(c){b=Math.max(b,p.sub1,c.height-.8*p.xHeight);var $=[{type:"elem",elem:c,marginLeft:O,marginRight:q}];V=y.makeVList({positionType:"shift",positionData:b,children:$},e)}else if(m)g=Math.max(g,A,m.depth+.25*p.xHeight),V=y.makeVList({positionType:"shift",positionData:-g,children:[{type:"elem",elem:m,marginRight:q}]},e);else throw new Error("supsub must have either sup or sub.");var M0=lt(o,"right")||"mord";return y.makeSpan([M0],[o,y.makeSpan(["msupsub"],[V])],e)},mathmlBuilder(r,e){var t=!1,a,n;r.base&&r.base.type==="horizBrace"&&(n=!!r.sup,n===r.base.isOver&&(t=!0,a=r.base.isOver)),r.base&&(r.base.type==="op"||r.base.type==="operatorname")&&(r.base.parentIsSupSub=!0);var s=[X(r.base,e)];r.sub&&s.push(X(r.sub,e)),r.sup&&s.push(X(r.sup,e));var o;if(t)o=a?"mover":"munder";else if(r.sub)if(r.sup){var p=r.base;p&&p.type==="op"&&p.limits&&e.style===I.DISPLAY||p&&p.type==="operatorname"&&p.alwaysHandleSupSub&&(e.style===I.DISPLAY||p.limits)?o="munderover":o="msubsup"}else{var c=r.base;c&&c.type==="op"&&c.limits&&(e.style===I.DISPLAY||c.alwaysHandleSupSub)||c&&c.type==="operatorname"&&c.alwaysHandleSupSub&&(c.limits||e.style===I.DISPLAY)?o="munder":o="msub"}else{var m=r.base;m&&m.type==="op"&&m.limits&&(e.style===I.DISPLAY||m.alwaysHandleSupSub)||m&&m.type==="operatorname"&&m.alwaysHandleSupSub&&(m.limits||e.style===I.DISPLAY)?o="mover":o="msup"}return new S.MathNode(o,s)}});Y0({type:"atom",htmlBuilder(r,e){return y.mathsym(r.text,r.mode,e,["m"+r.family])},mathmlBuilder(r,e){var t=new S.MathNode("mo",[v0(r.text,r.mode)]);if(r.family==="bin"){var a=bt(r,e);a==="bold-italic"&&t.setAttribute("mathvariant",a)}else r.family==="punct"?t.setAttribute("separator","true"):(r.family==="open"||r.family==="close")&&t.setAttribute("stretchy","false");return t}});var na={mi:"italic",mn:"normal",mtext:"normal"};Y0({type:"mathord",htmlBuilder(r,e){return y.makeOrd(r,e,"mathord")},mathmlBuilder(r,e){var t=new S.MathNode("mi",[v0(r.text,r.mode,e)]),a=bt(r,e)||"italic";return a!==na[t.type]&&t.setAttribute("mathvariant",a),t}});Y0({type:"textord",htmlBuilder(r,e){return y.makeOrd(r,e,"textord")},mathmlBuilder(r,e){var t=v0(r.text,r.mode,e),a=bt(r,e)||"normal",n;return r.mode==="text"?n=new S.MathNode("mtext",[t]):/[0-9]/.test(r.text)?n=new S.MathNode("mn",[t]):r.text==="\\prime"?n=new S.MathNode("mo",[t]):n=new S.MathNode("mi",[t]),a!==na[n.type]&&n.setAttribute("mathvariant",a),n}});var et={"\\nobreak":"nobreak","\\allowbreak":"allowbreak"},tt={" ":{},"\\ ":{},"~":{className:"nobreak"},"\\space":{},"\\nobreakspace":{className:"nobreak"}};Y0({type:"spacing",htmlBuilder(r,e){if(tt.hasOwnProperty(r.text)){var t=tt[r.text].className||"";if(r.mode==="text"){var a=y.makeOrd(r,e,"textord");return a.classes.push(t),a}else return y.makeSpan(["mspace",t],[y.mathsym(r.text,r.mode,e)],e)}else{if(et.hasOwnProperty(r.text))return y.makeSpan(["mspace",et[r.text]],[],e);throw new M('Unknown type of space "'+r.text+'"')}},mathmlBuilder(r,e){var t;if(tt.hasOwnProperty(r.text))t=new S.MathNode("mtext",[new S.TextNode(" ")]);else{if(et.hasOwnProperty(r.text))return new S.MathNode("mspace");throw new M('Unknown type of space "'+r.text+'"')}return t}});var ir=()=>{var r=new S.MathNode("mtd",[]);return r.setAttribute("width","50%"),r};Y0({type:"tag",mathmlBuilder(r,e){var t=new S.MathNode("mtable",[new S.MathNode("mtr",[ir(),new S.MathNode("mtd",[G0(r.body,e)]),ir(),new S.MathNode("mtd",[G0(r.tag,e)])])]);return t.setAttribute("width","100%"),t}});var sr={"\\text":void 0,"\\textrm":"textrm","\\textsf":"textsf","\\texttt":"texttt","\\textnormal":"textrm"},lr={"\\textbf":"textbf","\\textmd":"textmd"},Q1={"\\textit":"textit","\\textup":"textup"},or=(r,e)=>{var t=r.font;if(t){if(sr[t])return e.withTextFontFamily(sr[t]);if(lr[t])return e.withTextFontWeight(lr[t]);if(t==="\\emph")return e.fontShape==="textit"?e.withTextFontShape("textup"):e.withTextFontShape("textit")}else return e;return e.withTextFontShape(Q1[t])};B({type:"text",names:["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textbf","\\textmd","\\textit","\\textup","\\emph"],props:{numArgs:1,argTypes:["text"],allowedInArgument:!0,allowedInText:!0},handler(r,e){var{parser:t,funcName:a}=r,n=e[0];return{type:"text",mode:t.mode,body:Q(n),font:a}},htmlBuilder(r,e){var t=or(r,e),a=t0(r.body,t,!0);return y.makeSpan(["mord","text"],a,t)},mathmlBuilder(r,e){var t=or(r,e);return G0(r.body,t)}});B({type:"underline",names:["\\underline"],props:{numArgs:1,allowedInText:!0},handler(r,e){var{parser:t}=r;return{type:"underline",mode:t.mode,body:e[0]}},htmlBuilder(r,e){var t=P(r.body,e),a=y.makeLineSpan("underline-line",e),n=e.fontMetrics().defaultRuleThickness,s=y.makeVList({positionType:"top",positionData:t.height,children:[{type:"kern",size:n},{type:"elem",elem:a},{type:"kern",size:3*n},{type:"elem",elem:t}]},e);return y.makeSpan(["mord","underline"],[s],e)},mathmlBuilder(r,e){var t=new S.MathNode("mo",[new S.TextNode("‾")]);t.setAttribute("stretchy","true");var a=new S.MathNode("munder",[X(r.body,e),t]);return a.setAttribute("accentunder","true"),a}});B({type:"vcenter",names:["\\vcenter"],props:{numArgs:1,argTypes:["original"],allowedInText:!1},handler(r,e){var{parser:t}=r;return{type:"vcenter",mode:t.mode,body:e[0]}},htmlBuilder(r,e){var t=P(r.body,e),a=e.fontMetrics().axisHeight,n=.5*(t.height-a-(t.depth+a));return y.makeVList({positionType:"shift",positionData:n,children:[{type:"elem",elem:t}]},e)},mathmlBuilder(r,e){return new S.MathNode("mpadded",[X(r.body,e)],["vcenter"])}});B({type:"verb",names:["\\verb"],props:{numArgs:0,allowedInText:!0},handler(r,e,t){throw new M("\\verb ended by end of line instead of matching delimiter")},htmlBuilder(r,e){for(var t=hr(r),a=[],n=e.havingStyle(e.style.text()),s=0;sr.body.replace(/ /g,r.star?"␣":" "),H0=Ar,ia=`[ \r + ]`,_1="\\\\[a-zA-Z@]+",e4="\\\\[^\uD800-\uDFFF]",t4="("+_1+")"+ia+"*",r4=`\\\\( +|[ \r ]+ +?)[ \r ]*`,ut="[̀-ͯ]",a4=new RegExp(ut+"+$"),n4="("+ia+"+)|"+(r4+"|")+"([!-\\[\\]-‧‪-퟿豈-￿]"+(ut+"*")+"|[\uD800-\uDBFF][\uDC00-\uDFFF]"+(ut+"*")+"|\\\\verb\\*([^]).*?\\4|\\\\verb([^*a-zA-Z]).*?\\5"+("|"+t4)+("|"+e4+")");class mr{constructor(e,t){this.input=void 0,this.settings=void 0,this.tokenRegex=void 0,this.catcodes=void 0,this.input=e,this.settings=t,this.tokenRegex=new RegExp(n4,"g"),this.catcodes={"%":14,"~":13}}setCatcode(e,t){this.catcodes[e]=t}lex(){var e=this.input,t=this.tokenRegex.lastIndex;if(t===e.length)return new f0("EOF",new h0(this,t,t));var a=this.tokenRegex.exec(e);if(a===null||a.index!==t)throw new M("Unexpected character: '"+e[t]+"'",new f0(e[t],new h0(this,t,t+1)));var n=a[6]||a[3]||(a[2]?"\\ ":" ");if(this.catcodes[n]===14){var s=e.indexOf(` +`,this.tokenRegex.lastIndex);return s===-1?(this.tokenRegex.lastIndex=e.length,this.settings.reportNonstrict("commentAtEnd","% comment has no terminating newline; LaTeX would fail because of commenting the end of math mode (e.g. $)")):this.tokenRegex.lastIndex=s+1,this.lex()}return new f0(n,new h0(this,t,this.tokenRegex.lastIndex))}}class i4{constructor(e,t){e===void 0&&(e={}),t===void 0&&(t={}),this.current=void 0,this.builtins=void 0,this.undefStack=void 0,this.current=t,this.builtins=e,this.undefStack=[]}beginGroup(){this.undefStack.push({})}endGroup(){if(this.undefStack.length===0)throw new M("Unbalanced namespace destruction: attempt to pop global namespace; please report this as a bug");var e=this.undefStack.pop();for(var t in e)e.hasOwnProperty(t)&&(e[t]==null?delete this.current[t]:this.current[t]=e[t])}endGroups(){for(;this.undefStack.length>0;)this.endGroup()}has(e){return this.current.hasOwnProperty(e)||this.builtins.hasOwnProperty(e)}get(e){return this.current.hasOwnProperty(e)?this.current[e]:this.builtins[e]}set(e,t,a){if(a===void 0&&(a=!1),a){for(var n=0;n0&&(this.undefStack[this.undefStack.length-1][e]=t)}else{var s=this.undefStack[this.undefStack.length-1];s&&!s.hasOwnProperty(e)&&(s[e]=this.current[e])}t==null?delete this.current[e]:this.current[e]=t}}var s4=jr;u("\\noexpand",function(r){var e=r.popToken();return r.isExpandable(e.text)&&(e.noexpand=!0,e.treatAsRelax=!0),{tokens:[e],numArgs:0}});u("\\expandafter",function(r){var e=r.popToken();return r.expandOnce(!0),{tokens:[e],numArgs:0}});u("\\@firstoftwo",function(r){var e=r.consumeArgs(2);return{tokens:e[0],numArgs:0}});u("\\@secondoftwo",function(r){var e=r.consumeArgs(2);return{tokens:e[1],numArgs:0}});u("\\@ifnextchar",function(r){var e=r.consumeArgs(3);r.consumeSpaces();var t=r.future();return e[0].length===1&&e[0][0].text===t.text?{tokens:e[1],numArgs:0}:{tokens:e[2],numArgs:0}});u("\\@ifstar","\\@ifnextchar *{\\@firstoftwo{#1}}");u("\\TextOrMath",function(r){var e=r.consumeArgs(2);return r.mode==="text"?{tokens:e[0],numArgs:0}:{tokens:e[1],numArgs:0}});var ur={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,a:10,A:10,b:11,B:11,c:12,C:12,d:13,D:13,e:14,E:14,f:15,F:15};u("\\char",function(r){var e=r.popToken(),t,a="";if(e.text==="'")t=8,e=r.popToken();else if(e.text==='"')t=16,e=r.popToken();else if(e.text==="`")if(e=r.popToken(),e.text[0]==="\\")a=e.text.charCodeAt(1);else{if(e.text==="EOF")throw new M("\\char` missing argument");a=e.text.charCodeAt(0)}else t=10;if(t){if(a=ur[e.text],a==null||a>=t)throw new M("Invalid base-"+t+" digit "+e.text);for(var n;(n=ur[r.future().text])!=null&&n{var a=r.consumeArg().tokens;if(a.length!==1)throw new M("\\newcommand's first argument must be a macro name");var n=a[0].text,s=r.isDefined(n);if(s&&!e)throw new M("\\newcommand{"+n+"} attempting to redefine "+(n+"; use \\renewcommand"));if(!s&&!t)throw new M("\\renewcommand{"+n+"} when command "+n+" does not yet exist; use \\newcommand");var o=0;if(a=r.consumeArg().tokens,a.length===1&&a[0].text==="["){for(var m="",c=r.expandNextToken();c.text!=="]"&&c.text!=="EOF";)m+=c.text,c=r.expandNextToken();if(!m.match(/^\s*[0-9]+\s*$/))throw new M("Invalid number of arguments: "+m);o=parseInt(m),a=r.consumeArg().tokens}return r.macros.set(n,{tokens:a,numArgs:o}),""};u("\\newcommand",r=>Bt(r,!1,!0));u("\\renewcommand",r=>Bt(r,!0,!1));u("\\providecommand",r=>Bt(r,!0,!0));u("\\message",r=>{var e=r.consumeArgs(1)[0];return console.log(e.reverse().map(t=>t.text).join("")),""});u("\\errmessage",r=>{var e=r.consumeArgs(1)[0];return console.error(e.reverse().map(t=>t.text).join("")),""});u("\\show",r=>{var e=r.popToken(),t=e.text;return console.log(e,r.macros.get(t),H0[t],Y.math[t],Y.text[t]),""});u("\\bgroup","{");u("\\egroup","}");u("~","\\nobreakspace");u("\\lq","`");u("\\rq","'");u("\\aa","\\r a");u("\\AA","\\r A");u("\\textcopyright","\\html@mathml{\\textcircled{c}}{\\char`©}");u("\\copyright","\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}");u("\\textregistered","\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`®}");u("ℬ","\\mathscr{B}");u("ℰ","\\mathscr{E}");u("ℱ","\\mathscr{F}");u("ℋ","\\mathscr{H}");u("ℐ","\\mathscr{I}");u("ℒ","\\mathscr{L}");u("ℳ","\\mathscr{M}");u("ℛ","\\mathscr{R}");u("ℭ","\\mathfrak{C}");u("ℌ","\\mathfrak{H}");u("ℨ","\\mathfrak{Z}");u("\\Bbbk","\\Bbb{k}");u("·","\\cdotp");u("\\llap","\\mathllap{\\textrm{#1}}");u("\\rlap","\\mathrlap{\\textrm{#1}}");u("\\clap","\\mathclap{\\textrm{#1}}");u("\\mathstrut","\\vphantom{(}");u("\\underbar","\\underline{\\text{#1}}");u("\\not",'\\html@mathml{\\mathrel{\\mathrlap\\@not}}{\\char"338}');u("\\neq","\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`≠}}");u("\\ne","\\neq");u("≠","\\neq");u("\\notin","\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}{\\mathrel{\\char`∉}}");u("∉","\\notin");u("≘","\\html@mathml{\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}}{\\mathrel{\\char`≘}}");u("≙","\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`≘}}");u("≚","\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`≚}}");u("≛","\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}{\\mathrel{\\char`≛}}");u("≝","\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}{\\mathrel{\\char`≝}}");u("≞","\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}{\\mathrel{\\char`≞}}");u("≟","\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`≟}}");u("⟂","\\perp");u("‼","\\mathclose{!\\mkern-0.8mu!}");u("∌","\\notni");u("⌜","\\ulcorner");u("⌝","\\urcorner");u("⌞","\\llcorner");u("⌟","\\lrcorner");u("©","\\copyright");u("®","\\textregistered");u("️","\\textregistered");u("\\ulcorner",'\\html@mathml{\\@ulcorner}{\\mathop{\\char"231c}}');u("\\urcorner",'\\html@mathml{\\@urcorner}{\\mathop{\\char"231d}}');u("\\llcorner",'\\html@mathml{\\@llcorner}{\\mathop{\\char"231e}}');u("\\lrcorner",'\\html@mathml{\\@lrcorner}{\\mathop{\\char"231f}}');u("\\vdots","\\mathord{\\varvdots\\rule{0pt}{15pt}}");u("⋮","\\vdots");u("\\varGamma","\\mathit{\\Gamma}");u("\\varDelta","\\mathit{\\Delta}");u("\\varTheta","\\mathit{\\Theta}");u("\\varLambda","\\mathit{\\Lambda}");u("\\varXi","\\mathit{\\Xi}");u("\\varPi","\\mathit{\\Pi}");u("\\varSigma","\\mathit{\\Sigma}");u("\\varUpsilon","\\mathit{\\Upsilon}");u("\\varPhi","\\mathit{\\Phi}");u("\\varPsi","\\mathit{\\Psi}");u("\\varOmega","\\mathit{\\Omega}");u("\\substack","\\begin{subarray}{c}#1\\end{subarray}");u("\\colon","\\nobreak\\mskip2mu\\mathpunct{}\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu\\relax");u("\\boxed","\\fbox{$\\displaystyle{#1}$}");u("\\iff","\\DOTSB\\;\\Longleftrightarrow\\;");u("\\implies","\\DOTSB\\;\\Longrightarrow\\;");u("\\impliedby","\\DOTSB\\;\\Longleftarrow\\;");var cr={",":"\\dotsc","\\not":"\\dotsb","+":"\\dotsb","=":"\\dotsb","<":"\\dotsb",">":"\\dotsb","-":"\\dotsb","*":"\\dotsb",":":"\\dotsb","\\DOTSB":"\\dotsb","\\coprod":"\\dotsb","\\bigvee":"\\dotsb","\\bigwedge":"\\dotsb","\\biguplus":"\\dotsb","\\bigcap":"\\dotsb","\\bigcup":"\\dotsb","\\prod":"\\dotsb","\\sum":"\\dotsb","\\bigotimes":"\\dotsb","\\bigoplus":"\\dotsb","\\bigodot":"\\dotsb","\\bigsqcup":"\\dotsb","\\And":"\\dotsb","\\longrightarrow":"\\dotsb","\\Longrightarrow":"\\dotsb","\\longleftarrow":"\\dotsb","\\Longleftarrow":"\\dotsb","\\longleftrightarrow":"\\dotsb","\\Longleftrightarrow":"\\dotsb","\\mapsto":"\\dotsb","\\longmapsto":"\\dotsb","\\hookrightarrow":"\\dotsb","\\doteq":"\\dotsb","\\mathbin":"\\dotsb","\\mathrel":"\\dotsb","\\relbar":"\\dotsb","\\Relbar":"\\dotsb","\\xrightarrow":"\\dotsb","\\xleftarrow":"\\dotsb","\\DOTSI":"\\dotsi","\\int":"\\dotsi","\\oint":"\\dotsi","\\iint":"\\dotsi","\\iiint":"\\dotsi","\\iiiint":"\\dotsi","\\idotsint":"\\dotsi","\\DOTSX":"\\dotsx"};u("\\dots",function(r){var e="\\dotso",t=r.expandAfterFuture().text;return t in cr?e=cr[t]:(t.slice(0,4)==="\\not"||t in Y.math&&R.contains(["bin","rel"],Y.math[t].group))&&(e="\\dotsb"),e});var Nt={")":!0,"]":!0,"\\rbrack":!0,"\\}":!0,"\\rbrace":!0,"\\rangle":!0,"\\rceil":!0,"\\rfloor":!0,"\\rgroup":!0,"\\rmoustache":!0,"\\right":!0,"\\bigr":!0,"\\biggr":!0,"\\Bigr":!0,"\\Biggr":!0,$:!0,";":!0,".":!0,",":!0};u("\\dotso",function(r){var e=r.future().text;return e in Nt?"\\ldots\\,":"\\ldots"});u("\\dotsc",function(r){var e=r.future().text;return e in Nt&&e!==","?"\\ldots\\,":"\\ldots"});u("\\cdots",function(r){var e=r.future().text;return e in Nt?"\\@cdots\\,":"\\@cdots"});u("\\dotsb","\\cdots");u("\\dotsm","\\cdots");u("\\dotsi","\\!\\cdots");u("\\dotsx","\\ldots\\,");u("\\DOTSI","\\relax");u("\\DOTSB","\\relax");u("\\DOTSX","\\relax");u("\\tmspace","\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax");u("\\,","\\tmspace+{3mu}{.1667em}");u("\\thinspace","\\,");u("\\>","\\mskip{4mu}");u("\\:","\\tmspace+{4mu}{.2222em}");u("\\medspace","\\:");u("\\;","\\tmspace+{5mu}{.2777em}");u("\\thickspace","\\;");u("\\!","\\tmspace-{3mu}{.1667em}");u("\\negthinspace","\\!");u("\\negmedspace","\\tmspace-{4mu}{.2222em}");u("\\negthickspace","\\tmspace-{5mu}{.277em}");u("\\enspace","\\kern.5em ");u("\\enskip","\\hskip.5em\\relax");u("\\quad","\\hskip1em\\relax");u("\\qquad","\\hskip2em\\relax");u("\\tag","\\@ifstar\\tag@literal\\tag@paren");u("\\tag@paren","\\tag@literal{({#1})}");u("\\tag@literal",r=>{if(r.macros.get("\\df@tag"))throw new M("Multiple \\tag");return"\\gdef\\df@tag{\\text{#1}}"});u("\\bmod","\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}");u("\\pod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)");u("\\pmod","\\pod{{\\rm mod}\\mkern6mu#1}");u("\\mod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1");u("\\newline","\\\\\\relax");u("\\TeX","\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}");var sa=T(w0["Main-Regular"][84][1]-.7*w0["Main-Regular"][65][1]);u("\\LaTeX","\\textrm{\\html@mathml{"+("L\\kern-.36em\\raisebox{"+sa+"}{\\scriptstyle A}")+"\\kern-.15em\\TeX}{LaTeX}}");u("\\KaTeX","\\textrm{\\html@mathml{"+("K\\kern-.17em\\raisebox{"+sa+"}{\\scriptstyle A}")+"\\kern-.15em\\TeX}{KaTeX}}");u("\\hspace","\\@ifstar\\@hspacer\\@hspace");u("\\@hspace","\\hskip #1\\relax");u("\\@hspacer","\\rule{0pt}{0pt}\\hskip #1\\relax");u("\\ordinarycolon",":");u("\\vcentcolon","\\mathrel{\\mathop\\ordinarycolon}");u("\\dblcolon",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char"2237}}');u("\\coloneqq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2254}}');u("\\Coloneqq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2237\\char"3d}}');u("\\coloneq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"3a\\char"2212}}');u("\\Coloneq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"2237\\char"2212}}');u("\\eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2255}}');u("\\Eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"3d\\char"2237}}');u("\\eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2239}}');u("\\Eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"2212\\char"2237}}');u("\\colonapprox",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"3a\\char"2248}}');u("\\Colonapprox",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"2237\\char"2248}}');u("\\colonsim",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"3a\\char"223c}}');u("\\Colonsim",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"2237\\char"223c}}');u("∷","\\dblcolon");u("∹","\\eqcolon");u("≔","\\coloneqq");u("≕","\\eqqcolon");u("⩴","\\Coloneqq");u("\\ratio","\\vcentcolon");u("\\coloncolon","\\dblcolon");u("\\colonequals","\\coloneqq");u("\\coloncolonequals","\\Coloneqq");u("\\equalscolon","\\eqqcolon");u("\\equalscoloncolon","\\Eqqcolon");u("\\colonminus","\\coloneq");u("\\coloncolonminus","\\Coloneq");u("\\minuscolon","\\eqcolon");u("\\minuscoloncolon","\\Eqcolon");u("\\coloncolonapprox","\\Colonapprox");u("\\coloncolonsim","\\Colonsim");u("\\simcolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}");u("\\simcoloncolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}");u("\\approxcolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}");u("\\approxcoloncolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}");u("\\notni","\\html@mathml{\\not\\ni}{\\mathrel{\\char`∌}}");u("\\limsup","\\DOTSB\\operatorname*{lim\\,sup}");u("\\liminf","\\DOTSB\\operatorname*{lim\\,inf}");u("\\injlim","\\DOTSB\\operatorname*{inj\\,lim}");u("\\projlim","\\DOTSB\\operatorname*{proj\\,lim}");u("\\varlimsup","\\DOTSB\\operatorname*{\\overline{lim}}");u("\\varliminf","\\DOTSB\\operatorname*{\\underline{lim}}");u("\\varinjlim","\\DOTSB\\operatorname*{\\underrightarrow{lim}}");u("\\varprojlim","\\DOTSB\\operatorname*{\\underleftarrow{lim}}");u("\\gvertneqq","\\html@mathml{\\@gvertneqq}{≩}");u("\\lvertneqq","\\html@mathml{\\@lvertneqq}{≨}");u("\\ngeqq","\\html@mathml{\\@ngeqq}{≱}");u("\\ngeqslant","\\html@mathml{\\@ngeqslant}{≱}");u("\\nleqq","\\html@mathml{\\@nleqq}{≰}");u("\\nleqslant","\\html@mathml{\\@nleqslant}{≰}");u("\\nshortmid","\\html@mathml{\\@nshortmid}{∤}");u("\\nshortparallel","\\html@mathml{\\@nshortparallel}{∦}");u("\\nsubseteqq","\\html@mathml{\\@nsubseteqq}{⊈}");u("\\nsupseteqq","\\html@mathml{\\@nsupseteqq}{⊉}");u("\\varsubsetneq","\\html@mathml{\\@varsubsetneq}{⊊}");u("\\varsubsetneqq","\\html@mathml{\\@varsubsetneqq}{⫋}");u("\\varsupsetneq","\\html@mathml{\\@varsupsetneq}{⊋}");u("\\varsupsetneqq","\\html@mathml{\\@varsupsetneqq}{⫌}");u("\\imath","\\html@mathml{\\@imath}{ı}");u("\\jmath","\\html@mathml{\\@jmath}{ȷ}");u("\\llbracket","\\html@mathml{\\mathopen{[\\mkern-3.2mu[}}{\\mathopen{\\char`⟦}}");u("\\rrbracket","\\html@mathml{\\mathclose{]\\mkern-3.2mu]}}{\\mathclose{\\char`⟧}}");u("⟦","\\llbracket");u("⟧","\\rrbracket");u("\\lBrace","\\html@mathml{\\mathopen{\\{\\mkern-3.2mu[}}{\\mathopen{\\char`⦃}}");u("\\rBrace","\\html@mathml{\\mathclose{]\\mkern-3.2mu\\}}}{\\mathclose{\\char`⦄}}");u("⦃","\\lBrace");u("⦄","\\rBrace");u("\\minuso","\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`⦵}}");u("⦵","\\minuso");u("\\darr","\\downarrow");u("\\dArr","\\Downarrow");u("\\Darr","\\Downarrow");u("\\lang","\\langle");u("\\rang","\\rangle");u("\\uarr","\\uparrow");u("\\uArr","\\Uparrow");u("\\Uarr","\\Uparrow");u("\\N","\\mathbb{N}");u("\\R","\\mathbb{R}");u("\\Z","\\mathbb{Z}");u("\\alef","\\aleph");u("\\alefsym","\\aleph");u("\\Alpha","\\mathrm{A}");u("\\Beta","\\mathrm{B}");u("\\bull","\\bullet");u("\\Chi","\\mathrm{X}");u("\\clubs","\\clubsuit");u("\\cnums","\\mathbb{C}");u("\\Complex","\\mathbb{C}");u("\\Dagger","\\ddagger");u("\\diamonds","\\diamondsuit");u("\\empty","\\emptyset");u("\\Epsilon","\\mathrm{E}");u("\\Eta","\\mathrm{H}");u("\\exist","\\exists");u("\\harr","\\leftrightarrow");u("\\hArr","\\Leftrightarrow");u("\\Harr","\\Leftrightarrow");u("\\hearts","\\heartsuit");u("\\image","\\Im");u("\\infin","\\infty");u("\\Iota","\\mathrm{I}");u("\\isin","\\in");u("\\Kappa","\\mathrm{K}");u("\\larr","\\leftarrow");u("\\lArr","\\Leftarrow");u("\\Larr","\\Leftarrow");u("\\lrarr","\\leftrightarrow");u("\\lrArr","\\Leftrightarrow");u("\\Lrarr","\\Leftrightarrow");u("\\Mu","\\mathrm{M}");u("\\natnums","\\mathbb{N}");u("\\Nu","\\mathrm{N}");u("\\Omicron","\\mathrm{O}");u("\\plusmn","\\pm");u("\\rarr","\\rightarrow");u("\\rArr","\\Rightarrow");u("\\Rarr","\\Rightarrow");u("\\real","\\Re");u("\\reals","\\mathbb{R}");u("\\Reals","\\mathbb{R}");u("\\Rho","\\mathrm{P}");u("\\sdot","\\cdot");u("\\sect","\\S");u("\\spades","\\spadesuit");u("\\sub","\\subset");u("\\sube","\\subseteq");u("\\supe","\\supseteq");u("\\Tau","\\mathrm{T}");u("\\thetasym","\\vartheta");u("\\weierp","\\wp");u("\\Zeta","\\mathrm{Z}");u("\\argmin","\\DOTSB\\operatorname*{arg\\,min}");u("\\argmax","\\DOTSB\\operatorname*{arg\\,max}");u("\\plim","\\DOTSB\\mathop{\\operatorname{plim}}\\limits");u("\\bra","\\mathinner{\\langle{#1}|}");u("\\ket","\\mathinner{|{#1}\\rangle}");u("\\braket","\\mathinner{\\langle{#1}\\rangle}");u("\\Bra","\\left\\langle#1\\right|");u("\\Ket","\\left|#1\\right\\rangle");var la=r=>e=>{var t=e.consumeArg().tokens,a=e.consumeArg().tokens,n=e.consumeArg().tokens,s=e.consumeArg().tokens,o=e.macros.get("|"),m=e.macros.get("\\|");e.macros.beginGroup();var c=b=>w=>{r&&(w.macros.set("|",o),n.length&&w.macros.set("\\|",m));var x=b;if(!b&&n.length){var z=w.future();z.text==="|"&&(w.popToken(),x=!0)}return{tokens:x?n:a,numArgs:0}};e.macros.set("|",c(!1)),n.length&&e.macros.set("\\|",c(!0));var p=e.consumeArg().tokens,g=e.expandTokens([...s,...p,...t]);return e.macros.endGroup(),{tokens:g.reverse(),numArgs:0}};u("\\bra@ket",la(!1));u("\\bra@set",la(!0));u("\\Braket","\\bra@ket{\\left\\langle}{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}");u("\\Set","\\bra@set{\\left\\{\\:}{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}");u("\\set","\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}");u("\\angln","{\\angl n}");u("\\blue","\\textcolor{##6495ed}{#1}");u("\\orange","\\textcolor{##ffa500}{#1}");u("\\pink","\\textcolor{##ff00af}{#1}");u("\\red","\\textcolor{##df0030}{#1}");u("\\green","\\textcolor{##28ae7b}{#1}");u("\\gray","\\textcolor{gray}{#1}");u("\\purple","\\textcolor{##9d38bd}{#1}");u("\\blueA","\\textcolor{##ccfaff}{#1}");u("\\blueB","\\textcolor{##80f6ff}{#1}");u("\\blueC","\\textcolor{##63d9ea}{#1}");u("\\blueD","\\textcolor{##11accd}{#1}");u("\\blueE","\\textcolor{##0c7f99}{#1}");u("\\tealA","\\textcolor{##94fff5}{#1}");u("\\tealB","\\textcolor{##26edd5}{#1}");u("\\tealC","\\textcolor{##01d1c1}{#1}");u("\\tealD","\\textcolor{##01a995}{#1}");u("\\tealE","\\textcolor{##208170}{#1}");u("\\greenA","\\textcolor{##b6ffb0}{#1}");u("\\greenB","\\textcolor{##8af281}{#1}");u("\\greenC","\\textcolor{##74cf70}{#1}");u("\\greenD","\\textcolor{##1fab54}{#1}");u("\\greenE","\\textcolor{##0d923f}{#1}");u("\\goldA","\\textcolor{##ffd0a9}{#1}");u("\\goldB","\\textcolor{##ffbb71}{#1}");u("\\goldC","\\textcolor{##ff9c39}{#1}");u("\\goldD","\\textcolor{##e07d10}{#1}");u("\\goldE","\\textcolor{##a75a05}{#1}");u("\\redA","\\textcolor{##fca9a9}{#1}");u("\\redB","\\textcolor{##ff8482}{#1}");u("\\redC","\\textcolor{##f9685d}{#1}");u("\\redD","\\textcolor{##e84d39}{#1}");u("\\redE","\\textcolor{##bc2612}{#1}");u("\\maroonA","\\textcolor{##ffbde0}{#1}");u("\\maroonB","\\textcolor{##ff92c6}{#1}");u("\\maroonC","\\textcolor{##ed5fa6}{#1}");u("\\maroonD","\\textcolor{##ca337c}{#1}");u("\\maroonE","\\textcolor{##9e034e}{#1}");u("\\purpleA","\\textcolor{##ddd7ff}{#1}");u("\\purpleB","\\textcolor{##c6b9fc}{#1}");u("\\purpleC","\\textcolor{##aa87ff}{#1}");u("\\purpleD","\\textcolor{##7854ab}{#1}");u("\\purpleE","\\textcolor{##543b78}{#1}");u("\\mintA","\\textcolor{##f5f9e8}{#1}");u("\\mintB","\\textcolor{##edf2df}{#1}");u("\\mintC","\\textcolor{##e0e5cc}{#1}");u("\\grayA","\\textcolor{##f6f7f7}{#1}");u("\\grayB","\\textcolor{##f0f1f2}{#1}");u("\\grayC","\\textcolor{##e3e5e6}{#1}");u("\\grayD","\\textcolor{##d6d8da}{#1}");u("\\grayE","\\textcolor{##babec2}{#1}");u("\\grayF","\\textcolor{##888d93}{#1}");u("\\grayG","\\textcolor{##626569}{#1}");u("\\grayH","\\textcolor{##3b3e40}{#1}");u("\\grayI","\\textcolor{##21242c}{#1}");u("\\kaBlue","\\textcolor{##314453}{#1}");u("\\kaGreen","\\textcolor{##71B307}{#1}");var oa={"^":!0,_:!0,"\\limits":!0,"\\nolimits":!0};class l4{constructor(e,t,a){this.settings=void 0,this.expansionCount=void 0,this.lexer=void 0,this.macros=void 0,this.stack=void 0,this.mode=void 0,this.settings=t,this.expansionCount=0,this.feed(e),this.macros=new i4(s4,t.macros),this.mode=a,this.stack=[]}feed(e){this.lexer=new mr(e,this.settings)}switchMode(e){this.mode=e}beginGroup(){this.macros.beginGroup()}endGroup(){this.macros.endGroup()}endGroups(){this.macros.endGroups()}future(){return this.stack.length===0&&this.pushToken(this.lexer.lex()),this.stack[this.stack.length-1]}popToken(){return this.future(),this.stack.pop()}pushToken(e){this.stack.push(e)}pushTokens(e){this.stack.push(...e)}scanArgument(e){var t,a,n;if(e){if(this.consumeSpaces(),this.future().text!=="[")return null;t=this.popToken(),{tokens:n,end:a}=this.consumeArg(["]"])}else({tokens:n,start:t,end:a}=this.consumeArg());return this.pushToken(new f0("EOF",a.loc)),this.pushTokens(n),t.range(a,"")}consumeSpaces(){for(;;){var e=this.future();if(e.text===" ")this.stack.pop();else break}}consumeArg(e){var t=[],a=e&&e.length>0;a||this.consumeSpaces();var n=this.future(),s,o=0,m=0;do{if(s=this.popToken(),t.push(s),s.text==="{")++o;else if(s.text==="}"){if(--o,o===-1)throw new M("Extra }",s)}else if(s.text==="EOF")throw new M("Unexpected end of input in a macro argument, expected '"+(e&&a?e[m]:"}")+"'",s);if(e&&a)if((o===0||o===1&&e[m]==="{")&&s.text===e[m]){if(++m,m===e.length){t.splice(-m,m);break}}else m=0}while(o!==0||a);return n.text==="{"&&t[t.length-1].text==="}"&&(t.pop(),t.shift()),t.reverse(),{tokens:t,start:n,end:s}}consumeArgs(e,t){if(t){if(t.length!==e+1)throw new M("The length of delimiters doesn't match the number of args!");for(var a=t[0],n=0;nthis.settings.maxExpand)throw new M("Too many expansions: infinite loop or need to increase maxExpand setting")}expandOnce(e){var t=this.popToken(),a=t.text,n=t.noexpand?null:this._getExpansion(a);if(n==null||e&&n.unexpandable){if(e&&n==null&&a[0]==="\\"&&!this.isDefined(a))throw new M("Undefined control sequence: "+a);return this.pushToken(t),!1}this.countExpansion(1);var s=n.tokens,o=this.consumeArgs(n.numArgs,n.delimiters);if(n.numArgs){s=s.slice();for(var m=s.length-1;m>=0;--m){var c=s[m];if(c.text==="#"){if(m===0)throw new M("Incomplete placeholder at end of macro body",c);if(c=s[--m],c.text==="#")s.splice(m+1,1);else if(/^[1-9]$/.test(c.text))s.splice(m,2,...o[+c.text-1]);else throw new M("Not a valid argument number",c)}}}return this.pushTokens(s),s.length}expandAfterFuture(){return this.expandOnce(),this.future()}expandNextToken(){for(;;)if(this.expandOnce()===!1){var e=this.stack.pop();return e.treatAsRelax&&(e.text="\\relax"),e}throw new Error}expandMacro(e){return this.macros.has(e)?this.expandTokens([new f0(e)]):void 0}expandTokens(e){var t=[],a=this.stack.length;for(this.pushTokens(e);this.stack.length>a;)if(this.expandOnce(!0)===!1){var n=this.stack.pop();n.treatAsRelax&&(n.noexpand=!1,n.treatAsRelax=!1),t.push(n)}return this.countExpansion(t.length),t}expandMacroAsText(e){var t=this.expandMacro(e);return t&&t.map(a=>a.text).join("")}_getExpansion(e){var t=this.macros.get(e);if(t==null)return t;if(e.length===1){var a=this.lexer.catcodes[e];if(a!=null&&a!==13)return}var n=typeof t=="function"?t(this):t;if(typeof n=="string"){var s=0;if(n.indexOf("#")!==-1)for(var o=n.replace(/##/g,"");o.indexOf("#"+(s+1))!==-1;)++s;for(var m=new mr(n,this.settings),c=[],p=m.lex();p.text!=="EOF";)c.push(p),p=m.lex();c.reverse();var g={tokens:c,numArgs:s};return g}return n}isDefined(e){return this.macros.has(e)||H0.hasOwnProperty(e)||Y.math.hasOwnProperty(e)||Y.text.hasOwnProperty(e)||oa.hasOwnProperty(e)}isExpandable(e){var t=this.macros.get(e);return t!=null?typeof t=="string"||typeof t=="function"||!t.unexpandable:H0.hasOwnProperty(e)&&!H0[e].primitive}}var dr=/^[₊₋₌₍₎₀₁₂₃₄₅₆₇₈₉ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓᵦᵧᵨᵩᵪ]/,Me=Object.freeze({"₊":"+","₋":"-","₌":"=","₍":"(","₎":")","₀":"0","₁":"1","₂":"2","₃":"3","₄":"4","₅":"5","₆":"6","₇":"7","₈":"8","₉":"9","ₐ":"a","ₑ":"e","ₕ":"h","ᵢ":"i","ⱼ":"j","ₖ":"k","ₗ":"l","ₘ":"m","ₙ":"n","ₒ":"o","ₚ":"p","ᵣ":"r","ₛ":"s","ₜ":"t","ᵤ":"u","ᵥ":"v","ₓ":"x","ᵦ":"β","ᵧ":"γ","ᵨ":"ρ","ᵩ":"ϕ","ᵪ":"χ","⁺":"+","⁻":"-","⁼":"=","⁽":"(","⁾":")","⁰":"0","¹":"1","²":"2","³":"3","⁴":"4","⁵":"5","⁶":"6","⁷":"7","⁸":"8","⁹":"9","ᴬ":"A","ᴮ":"B","ᴰ":"D","ᴱ":"E","ᴳ":"G","ᴴ":"H","ᴵ":"I","ᴶ":"J","ᴷ":"K","ᴸ":"L","ᴹ":"M","ᴺ":"N","ᴼ":"O","ᴾ":"P","ᴿ":"R","ᵀ":"T","ᵁ":"U","ⱽ":"V","ᵂ":"W","ᵃ":"a","ᵇ":"b","ᶜ":"c","ᵈ":"d","ᵉ":"e","ᶠ":"f","ᵍ":"g",ʰ:"h","ⁱ":"i",ʲ:"j","ᵏ":"k",ˡ:"l","ᵐ":"m",ⁿ:"n","ᵒ":"o","ᵖ":"p",ʳ:"r",ˢ:"s","ᵗ":"t","ᵘ":"u","ᵛ":"v",ʷ:"w",ˣ:"x",ʸ:"y","ᶻ":"z","ᵝ":"β","ᵞ":"γ","ᵟ":"δ","ᵠ":"ϕ","ᵡ":"χ","ᶿ":"θ"}),rt={"́":{text:"\\'",math:"\\acute"},"̀":{text:"\\`",math:"\\grave"},"̈":{text:'\\"',math:"\\ddot"},"̃":{text:"\\~",math:"\\tilde"},"̄":{text:"\\=",math:"\\bar"},"̆":{text:"\\u",math:"\\breve"},"̌":{text:"\\v",math:"\\check"},"̂":{text:"\\^",math:"\\hat"},"̇":{text:"\\.",math:"\\dot"},"̊":{text:"\\r",math:"\\mathring"},"̋":{text:"\\H"},"̧":{text:"\\c"}},fr={á:"á",à:"à",ä:"ä",ǟ:"ǟ",ã:"ã",ā:"ā",ă:"ă",ắ:"ắ",ằ:"ằ",ẵ:"ẵ",ǎ:"ǎ",â:"â",ấ:"ấ",ầ:"ầ",ẫ:"ẫ",ȧ:"ȧ",ǡ:"ǡ",å:"å",ǻ:"ǻ",ḃ:"ḃ",ć:"ć",ḉ:"ḉ",č:"č",ĉ:"ĉ",ċ:"ċ",ç:"ç",ď:"ď",ḋ:"ḋ",ḑ:"ḑ",é:"é",è:"è",ë:"ë",ẽ:"ẽ",ē:"ē",ḗ:"ḗ",ḕ:"ḕ",ĕ:"ĕ",ḝ:"ḝ",ě:"ě",ê:"ê",ế:"ế",ề:"ề",ễ:"ễ",ė:"ė",ȩ:"ȩ",ḟ:"ḟ",ǵ:"ǵ",ḡ:"ḡ",ğ:"ğ",ǧ:"ǧ",ĝ:"ĝ",ġ:"ġ",ģ:"ģ",ḧ:"ḧ",ȟ:"ȟ",ĥ:"ĥ",ḣ:"ḣ",ḩ:"ḩ",í:"í",ì:"ì",ï:"ï",ḯ:"ḯ",ĩ:"ĩ",ī:"ī",ĭ:"ĭ",ǐ:"ǐ",î:"î",ǰ:"ǰ",ĵ:"ĵ",ḱ:"ḱ",ǩ:"ǩ",ķ:"ķ",ĺ:"ĺ",ľ:"ľ",ļ:"ļ",ḿ:"ḿ",ṁ:"ṁ",ń:"ń",ǹ:"ǹ",ñ:"ñ",ň:"ň",ṅ:"ṅ",ņ:"ņ",ó:"ó",ò:"ò",ö:"ö",ȫ:"ȫ",õ:"õ",ṍ:"ṍ",ṏ:"ṏ",ȭ:"ȭ",ō:"ō",ṓ:"ṓ",ṑ:"ṑ",ŏ:"ŏ",ǒ:"ǒ",ô:"ô",ố:"ố",ồ:"ồ",ỗ:"ỗ",ȯ:"ȯ",ȱ:"ȱ",ő:"ő",ṕ:"ṕ",ṗ:"ṗ",ŕ:"ŕ",ř:"ř",ṙ:"ṙ",ŗ:"ŗ",ś:"ś",ṥ:"ṥ",š:"š",ṧ:"ṧ",ŝ:"ŝ",ṡ:"ṡ",ş:"ş",ẗ:"ẗ",ť:"ť",ṫ:"ṫ",ţ:"ţ",ú:"ú",ù:"ù",ü:"ü",ǘ:"ǘ",ǜ:"ǜ",ǖ:"ǖ",ǚ:"ǚ",ũ:"ũ",ṹ:"ṹ",ū:"ū",ṻ:"ṻ",ŭ:"ŭ",ǔ:"ǔ",û:"û",ů:"ů",ű:"ű",ṽ:"ṽ",ẃ:"ẃ",ẁ:"ẁ",ẅ:"ẅ",ŵ:"ŵ",ẇ:"ẇ",ẘ:"ẘ",ẍ:"ẍ",ẋ:"ẋ",ý:"ý",ỳ:"ỳ",ÿ:"ÿ",ỹ:"ỹ",ȳ:"ȳ",ŷ:"ŷ",ẏ:"ẏ",ẙ:"ẙ",ź:"ź",ž:"ž",ẑ:"ẑ",ż:"ż",Á:"Á",À:"À",Ä:"Ä",Ǟ:"Ǟ",Ã:"Ã",Ā:"Ā",Ă:"Ă",Ắ:"Ắ",Ằ:"Ằ",Ẵ:"Ẵ",Ǎ:"Ǎ",Â:"Â",Ấ:"Ấ",Ầ:"Ầ",Ẫ:"Ẫ",Ȧ:"Ȧ",Ǡ:"Ǡ",Å:"Å",Ǻ:"Ǻ",Ḃ:"Ḃ",Ć:"Ć",Ḉ:"Ḉ",Č:"Č",Ĉ:"Ĉ",Ċ:"Ċ",Ç:"Ç",Ď:"Ď",Ḋ:"Ḋ",Ḑ:"Ḑ",É:"É",È:"È",Ë:"Ë",Ẽ:"Ẽ",Ē:"Ē",Ḗ:"Ḗ",Ḕ:"Ḕ",Ĕ:"Ĕ",Ḝ:"Ḝ",Ě:"Ě",Ê:"Ê",Ế:"Ế",Ề:"Ề",Ễ:"Ễ",Ė:"Ė",Ȩ:"Ȩ",Ḟ:"Ḟ",Ǵ:"Ǵ",Ḡ:"Ḡ",Ğ:"Ğ",Ǧ:"Ǧ",Ĝ:"Ĝ",Ġ:"Ġ",Ģ:"Ģ",Ḧ:"Ḧ",Ȟ:"Ȟ",Ĥ:"Ĥ",Ḣ:"Ḣ",Ḩ:"Ḩ",Í:"Í",Ì:"Ì",Ï:"Ï",Ḯ:"Ḯ",Ĩ:"Ĩ",Ī:"Ī",Ĭ:"Ĭ",Ǐ:"Ǐ",Î:"Î",İ:"İ",Ĵ:"Ĵ",Ḱ:"Ḱ",Ǩ:"Ǩ",Ķ:"Ķ",Ĺ:"Ĺ",Ľ:"Ľ",Ļ:"Ļ",Ḿ:"Ḿ",Ṁ:"Ṁ",Ń:"Ń",Ǹ:"Ǹ",Ñ:"Ñ",Ň:"Ň",Ṅ:"Ṅ",Ņ:"Ņ",Ó:"Ó",Ò:"Ò",Ö:"Ö",Ȫ:"Ȫ",Õ:"Õ",Ṍ:"Ṍ",Ṏ:"Ṏ",Ȭ:"Ȭ",Ō:"Ō",Ṓ:"Ṓ",Ṑ:"Ṑ",Ŏ:"Ŏ",Ǒ:"Ǒ",Ô:"Ô",Ố:"Ố",Ồ:"Ồ",Ỗ:"Ỗ",Ȯ:"Ȯ",Ȱ:"Ȱ",Ő:"Ő",Ṕ:"Ṕ",Ṗ:"Ṗ",Ŕ:"Ŕ",Ř:"Ř",Ṙ:"Ṙ",Ŗ:"Ŗ",Ś:"Ś",Ṥ:"Ṥ",Š:"Š",Ṧ:"Ṧ",Ŝ:"Ŝ",Ṡ:"Ṡ",Ş:"Ş",Ť:"Ť",Ṫ:"Ṫ",Ţ:"Ţ",Ú:"Ú",Ù:"Ù",Ü:"Ü",Ǘ:"Ǘ",Ǜ:"Ǜ",Ǖ:"Ǖ",Ǚ:"Ǚ",Ũ:"Ũ",Ṹ:"Ṹ",Ū:"Ū",Ṻ:"Ṻ",Ŭ:"Ŭ",Ǔ:"Ǔ",Û:"Û",Ů:"Ů",Ű:"Ű",Ṽ:"Ṽ",Ẃ:"Ẃ",Ẁ:"Ẁ",Ẅ:"Ẅ",Ŵ:"Ŵ",Ẇ:"Ẇ",Ẍ:"Ẍ",Ẋ:"Ẋ",Ý:"Ý",Ỳ:"Ỳ",Ÿ:"Ÿ",Ỹ:"Ỹ",Ȳ:"Ȳ",Ŷ:"Ŷ",Ẏ:"Ẏ",Ź:"Ź",Ž:"Ž",Ẑ:"Ẑ",Ż:"Ż",ά:"ά",ὰ:"ὰ",ᾱ:"ᾱ",ᾰ:"ᾰ",έ:"έ",ὲ:"ὲ",ή:"ή",ὴ:"ὴ",ί:"ί",ὶ:"ὶ",ϊ:"ϊ",ΐ:"ΐ",ῒ:"ῒ",ῑ:"ῑ",ῐ:"ῐ",ό:"ό",ὸ:"ὸ",ύ:"ύ",ὺ:"ὺ",ϋ:"ϋ",ΰ:"ΰ",ῢ:"ῢ",ῡ:"ῡ",ῠ:"ῠ",ώ:"ώ",ὼ:"ὼ",Ύ:"Ύ",Ὺ:"Ὺ",Ϋ:"Ϋ",Ῡ:"Ῡ",Ῠ:"Ῠ",Ώ:"Ώ",Ὼ:"Ὼ"};class He{constructor(e,t){this.mode=void 0,this.gullet=void 0,this.settings=void 0,this.leftrightDepth=void 0,this.nextToken=void 0,this.mode="math",this.gullet=new l4(e,t,this.mode),this.settings=t,this.leftrightDepth=0}expect(e,t){if(t===void 0&&(t=!0),this.fetch().text!==e)throw new M("Expected '"+e+"', got '"+this.fetch().text+"'",this.fetch());t&&this.consume()}consume(){this.nextToken=null}fetch(){return this.nextToken==null&&(this.nextToken=this.gullet.expandNextToken()),this.nextToken}switchMode(e){this.mode=e,this.gullet.switchMode(e)}parse(){this.settings.globalGroup||this.gullet.beginGroup(),this.settings.colorIsTextColor&&this.gullet.macros.set("\\color","\\textcolor");try{var e=this.parseExpression(!1);return this.expect("EOF"),this.settings.globalGroup||this.gullet.endGroup(),e}finally{this.gullet.endGroups()}}subparse(e){var t=this.nextToken;this.consume(),this.gullet.pushToken(new f0("}")),this.gullet.pushTokens(e);var a=this.parseExpression(!1);return this.expect("}"),this.nextToken=t,a}parseExpression(e,t){for(var a=[];;){this.mode==="math"&&this.consumeSpaces();var n=this.fetch();if(He.endOfExpression.indexOf(n.text)!==-1||t&&n.text===t||e&&H0[n.text]&&H0[n.text].infix)break;var s=this.parseAtom(t);if(s){if(s.type==="internal")continue}else break;a.push(s)}return this.mode==="text"&&this.formLigatures(a),this.handleInfixNodes(a)}handleInfixNodes(e){for(var t=-1,a,n=0;n=0&&this.settings.reportNonstrict("unicodeTextInMathMode",'Latin-1/Unicode text character "'+t[0]+'" used in math mode',e);var m=Y[this.mode][t].group,c=h0.range(e),p;if(Za.hasOwnProperty(m)){var g=m;p={type:"atom",mode:this.mode,family:g,loc:c,text:t}}else p={type:m,mode:this.mode,loc:c,text:t};o=p}else if(t.charCodeAt(0)>=128)this.settings.strict&&(gr(t.charCodeAt(0))?this.mode==="math"&&this.settings.reportNonstrict("unicodeTextInMathMode",'Unicode text character "'+t[0]+'" used in math mode',e):this.settings.reportNonstrict("unknownSymbol",'Unrecognized Unicode character "'+t[0]+'"'+(" ("+t.charCodeAt(0)+")"),e)),o={type:"textord",mode:"text",loc:h0.range(e),text:t};else return null;if(this.consume(),s)for(var b=0;bc4(p.left)).join("|")+")");a=e.search(s),a!==-1;){a>0&&(n.push({type:"text",data:e.slice(0,a)}),e=e.slice(a));var o=t.findIndex(p=>e.startsWith(p.left));if(a=u4(t[o].right,e,t[o].left.length),a===-1)break;var m=e.slice(0,a+t[o].right.length),c=d4.test(m)?m:e.slice(t[o].left.length,a);n.push({type:"math",data:c,rawData:m,display:t[o].display}),e=e.slice(a+t[o].right.length)}return e!==""&&n.push({type:"text",data:e}),n},p4=function(e,t){var a=f4(e,t.delimiters);if(a.length===1&&a[0].type==="text")return null;for(var n=document.createDocumentFragment(),s=0;sg.indexOf(" "+w+" ")===-1);b&&r(n,t)}()}},g4=function(e,t){if(!e)throw new Error("No element provided to render");var a={};for(var n in t)t.hasOwnProperty(n)&&(a[n]=t[n]);a.delimiters=a.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],a.ignoredTags=a.ignoredTags||["script","noscript","style","textarea","pre","code","option"],a.ignoredClasses=a.ignoredClasses||[],a.errorCallback=a.errorCallback||console.error,a.macros=a.macros||{},v4(e,a)};export{g4 as default,g4 as renderMathInElement}; diff --git a/assets/chunks/loading-Dcc5RApI.D3l74EUI.js b/assets/chunks/loading-Dcc5RApI.D3l74EUI.js new file mode 100644 index 0000000000..ceb5523bec --- /dev/null +++ b/assets/chunks/loading-Dcc5RApI.D3l74EUI.js @@ -0,0 +1 @@ +const a={success:!0,_identification:!0,data:''};export{a as default}; diff --git a/assets/chunks/loading-scene-BMc2wqKm.Di19NrRU.js b/assets/chunks/loading-scene-BMc2wqKm.Di19NrRU.js new file mode 100644 index 0000000000..8b519cf669 --- /dev/null +++ b/assets/chunks/loading-scene-BMc2wqKm.Di19NrRU.js @@ -0,0 +1,53 @@ +const n={success:!0,_identification:!0,data:` + LOADING + + + + + + + + + + + + + + + + +`};export{n as default}; diff --git a/assets/chunks/loading.vue_vue_type_style_index_0_lang.Da-8gR4I.js b/assets/chunks/loading.vue_vue_type_style_index_0_lang.Da-8gR4I.js new file mode 100644 index 0000000000..b790f5e25e --- /dev/null +++ b/assets/chunks/loading.vue_vue_type_style_index_0_lang.Da-8gR4I.js @@ -0,0 +1 @@ +import"./index.CBA5mFK_.js";import{d as i,p as r,o,c as t,j as e,F as s,C as a,t as d}from"./framework.C-ai2y4t.js";const u={class:"loading"},p={class:"loading-icon"},m=["name"],h=i({__name:"loading",setup(_){const c=r(["stretch","rotate","double-bounce","cube","dot","triple-bounce","scale-out","circle","circle-line","square","pulse","solar","cube-fold","circle-fold","cube-grid","circle-turn","circle-rotate","circle-spin","dot-bar","dot-circle","line","dot-pulse","line-scale","text","cube-dim","dot-line","arc","drop","pacman"]);return(b,l)=>(o(),t("div",null,[l[0]||(l[0]=e("h3",null,"Move the mouse over the icon to see the loading animation",-1)),(o(!0),t(s,null,a(c.value,n=>(o(),t("div",null,[e("div",u,[e("div",null,d(n),1),e("div",p,[e("r-loading",{name:n},null,8,m)])])]))),256))]))}});export{h as _}; diff --git a/assets/chunks/lock-Cr7BnmWN.0WfYXC2j.js b/assets/chunks/lock-Cr7BnmWN.0WfYXC2j.js new file mode 100644 index 0000000000..03a616e822 --- /dev/null +++ b/assets/chunks/lock-Cr7BnmWN.0WfYXC2j.js @@ -0,0 +1,4 @@ +const c={success:!0,_identification:!0,data:` + + +`};export{c as default}; diff --git a/assets/chunks/merge.D_M4N_iU.js b/assets/chunks/merge.D_M4N_iU.js new file mode 100644 index 0000000000..efc2709aab --- /dev/null +++ b/assets/chunks/merge.D_M4N_iU.js @@ -0,0 +1 @@ +const s="/ran/assets/merge.Bguw-KQu.gif";export{s as _}; diff --git a/assets/chunks/message-D36_Zo2l.CR8K3LhI.js b/assets/chunks/message-D36_Zo2l.CR8K3LhI.js new file mode 100644 index 0000000000..a8c7b11120 --- /dev/null +++ b/assets/chunks/message-D36_Zo2l.CR8K3LhI.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/pdf-Cx0VWKFo.BP4nEulL.js b/assets/chunks/pdf-Cx0VWKFo.BP4nEulL.js new file mode 100644 index 0000000000..42a620f340 --- /dev/null +++ b/assets/chunks/pdf-Cx0VWKFo.BP4nEulL.js @@ -0,0 +1 @@ +import{l as N}from"./index.CBA5mFK_.js";import"./framework.C-ai2y4t.js";var s=Object.defineProperty,y=(A,I,g)=>I in A?s(A,I,{enumerable:!0,configurable:!0,writable:!0,value:g}):A[I]=g,C=(A,I,g)=>y(A,typeof I!="symbol"?I+"":I,g);const o="LyoqCiAqIEBsaWNzdGFydCBUaGUgZm9sbG93aW5nIGlzIHRoZSBlbnRpcmUgbGljZW5zZSBub3RpY2UgZm9yIHRoZQogKiBKYXZhU2NyaXB0IGNvZGUgaW4gdGhpcyBwYWdlCiAqCiAqIENvcHlyaWdodCAyMDIzIE1vemlsbGEgRm91bmRhdGlvbgogKgogKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLgogKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKICoKICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKgogKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICJBUyBJUyIgQkFTSVMsCiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgogKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLgogKgogKiBAbGljZW5kIFRoZSBhYm92ZSBpcyB0aGUgZW50aXJlIGxpY2Vuc2Ugbm90aWNlIGZvciB0aGUKICogSmF2YVNjcmlwdCBjb2RlIGluIHRoaXMgcGFnZQogKi8KCihmdW5jdGlvbiB3ZWJwYWNrVW5pdmVyc2FsTW9kdWxlRGVmaW5pdGlvbihyb290LCBmYWN0b3J5KSB7CiAgICBpZih0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcpCiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCk7CiAgICBlbHNlIGlmKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkKICAgICAgICBkZWZpbmUoInBkZmpzLWRpc3QvYnVpbGQvcGRmIiwgW10sIGZhY3RvcnkpOwogICAgZWxzZSBpZih0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcpCiAgICAgICAgZXhwb3J0c1sicGRmanMtZGlzdC9idWlsZC9wZGYiXSA9IGZhY3RvcnkoKTsKICAgIGVsc2UKICAgICAgICByb290WyJwZGZqcy1kaXN0L2J1aWxkL3BkZiJdID0gcm9vdC5wZGZqc0xpYiA9IGZhY3RvcnkoKTsKfSkoZ2xvYmFsVGhpcywgKCkgPT4gewogICAgcmV0dXJuIC8qKioqKiovICgoKSA9PiB7IC8vIHdlYnBhY2tCb290c3RyYXAKICAgICAgICAvKioqKioqLyAJdmFyIF9fd2VicGFja19tb2R1bGVzX18gPSAoWwogICAgICAgICAgICAvKiAwICovLAogICAgICAgICAgICAvKiAxICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuVmVyYm9zaXR5TGV2ZWwgPSBleHBvcnRzLlV0aWwgPSBleHBvcnRzLlVua25vd25FcnJvckV4Y2VwdGlvbiA9IGV4cG9ydHMuVW5leHBlY3RlZFJlc3BvbnNlRXhjZXB0aW9uID0gZXhwb3J0cy5UZXh0UmVuZGVyaW5nTW9kZSA9IGV4cG9ydHMuUmVuZGVyaW5nSW50ZW50RmxhZyA9IGV4cG9ydHMuUGVybWlzc2lvbkZsYWcgPSBleHBvcnRzLlBhc3N3b3JkUmVzcG9uc2VzID0gZXhwb3J0cy5QYXNzd29yZEV4Y2VwdGlvbiA9IGV4cG9ydHMuUGFnZUFjdGlvbkV2ZW50VHlwZSA9IGV4cG9ydHMuT1BTID0gZXhwb3J0cy5NaXNzaW5nUERGRXhjZXB0aW9uID0gZXhwb3J0cy5NQVhfSU1BR0VfU0laRV9UT19DQUNIRSA9IGV4cG9ydHMuTElORV9GQUNUT1IgPSBleHBvcnRzLkxJTkVfREVTQ0VOVF9GQUNUT1IgPSBleHBvcnRzLkludmFsaWRQREZFeGNlcHRpb24gPSBleHBvcnRzLkltYWdlS2luZCA9IGV4cG9ydHMuSURFTlRJVFlfTUFUUklYID0gZXhwb3J0cy5Gb3JtYXRFcnJvciA9IGV4cG9ydHMuRmVhdHVyZVRlc3QgPSBleHBvcnRzLkZPTlRfSURFTlRJVFlfTUFUUklYID0gZXhwb3J0cy5Eb2N1bWVudEFjdGlvbkV2ZW50VHlwZSA9IGV4cG9ydHMuQ01hcENvbXByZXNzaW9uVHlwZSA9IGV4cG9ydHMuQmFzZUV4Y2VwdGlvbiA9IGV4cG9ydHMuQkFTRUxJTkVfRkFDVE9SID0gZXhwb3J0cy5Bbm5vdGF0aW9uVHlwZSA9IGV4cG9ydHMuQW5ub3RhdGlvblN0YXRlTW9kZWxUeXBlID0gZXhwb3J0cy5Bbm5vdGF0aW9uUmV2aWV3U3RhdGUgPSBleHBvcnRzLkFubm90YXRpb25SZXBseVR5cGUgPSBleHBvcnRzLkFubm90YXRpb25Nb2RlID0gZXhwb3J0cy5Bbm5vdGF0aW9uTWFya2VkU3RhdGUgPSBleHBvcnRzLkFubm90YXRpb25GbGFnID0gZXhwb3J0cy5Bbm5vdGF0aW9uRmllbGRGbGFnID0gZXhwb3J0cy5Bbm5vdGF0aW9uRWRpdG9yVHlwZSA9IGV4cG9ydHMuQW5ub3RhdGlvbkVkaXRvclByZWZpeCA9IGV4cG9ydHMuQW5ub3RhdGlvbkVkaXRvclBhcmFtc1R5cGUgPSBleHBvcnRzLkFubm90YXRpb25Cb3JkZXJTdHlsZVR5cGUgPSBleHBvcnRzLkFubm90YXRpb25BY3Rpb25FdmVudFR5cGUgPSBleHBvcnRzLkFib3J0RXhjZXB0aW9uID0gdm9pZCAwOwogICAgICAgICAgICAgICAgZXhwb3J0cy5hc3NlcnQgPSBhc3NlcnQ7CiAgICAgICAgICAgICAgICBleHBvcnRzLmJ5dGVzVG9TdHJpbmcgPSBieXRlc1RvU3RyaW5nOwogICAgICAgICAgICAgICAgZXhwb3J0cy5jcmVhdGVQcm9taXNlQ2FwYWJpbGl0eSA9IGNyZWF0ZVByb21pc2VDYXBhYmlsaXR5OwogICAgICAgICAgICAgICAgZXhwb3J0cy5jcmVhdGVWYWxpZEFic29sdXRlVXJsID0gY3JlYXRlVmFsaWRBYnNvbHV0ZVVybDsKICAgICAgICAgICAgICAgIGV4cG9ydHMuZ2V0TW9kaWZpY2F0aW9uRGF0ZSA9IGdldE1vZGlmaWNhdGlvbkRhdGU7CiAgICAgICAgICAgICAgICBleHBvcnRzLmdldFZlcmJvc2l0eUxldmVsID0gZ2V0VmVyYm9zaXR5TGV2ZWw7CiAgICAgICAgICAgICAgICBleHBvcnRzLmluZm8gPSBpbmZvOwogICAgICAgICAgICAgICAgZXhwb3J0cy5pc0FycmF5QnVmZmVyID0gaXNBcnJheUJ1ZmZlcjsKICAgICAgICAgICAgICAgIGV4cG9ydHMuaXNBcnJheUVxdWFsID0gaXNBcnJheUVxdWFsOwogICAgICAgICAgICAgICAgZXhwb3J0cy5vYmplY3RGcm9tTWFwID0gb2JqZWN0RnJvbU1hcDsKICAgICAgICAgICAgICAgIGV4cG9ydHMub2JqZWN0U2l6ZSA9IG9iamVjdFNpemU7CiAgICAgICAgICAgICAgICBleHBvcnRzLnNldFZlcmJvc2l0eUxldmVsID0gc2V0VmVyYm9zaXR5TGV2ZWw7CiAgICAgICAgICAgICAgICBleHBvcnRzLnNoYWRvdyA9IHNoYWRvdzsKICAgICAgICAgICAgICAgIGV4cG9ydHMuc3RyaW5nMzIgPSBzdHJpbmczMjsKICAgICAgICAgICAgICAgIGV4cG9ydHMuc3RyaW5nVG9CeXRlcyA9IHN0cmluZ1RvQnl0ZXM7CiAgICAgICAgICAgICAgICBleHBvcnRzLnN0cmluZ1RvUERGU3RyaW5nID0gc3RyaW5nVG9QREZTdHJpbmc7CiAgICAgICAgICAgICAgICBleHBvcnRzLnN0cmluZ1RvVVRGOFN0cmluZyA9IHN0cmluZ1RvVVRGOFN0cmluZzsKICAgICAgICAgICAgICAgIGV4cG9ydHMudW5yZWFjaGFibGUgPSB1bnJlYWNoYWJsZTsKICAgICAgICAgICAgICAgIGV4cG9ydHMudXRmOFN0cmluZ1RvU3RyaW5nID0gdXRmOFN0cmluZ1RvU3RyaW5nOwogICAgICAgICAgICAgICAgZXhwb3J0cy53YXJuID0gd2FybjsKICAgICAgICAgICAgICAgIGlmICghZ2xvYmFsVGhpcy5fcGRmanNDb21wYXRpYmlsaXR5Q2hlY2tlZCkgewogICAgICAgICAgICAgICAgICAgIGdsb2JhbFRoaXMuX3BkZmpzQ29tcGF0aWJpbGl0eUNoZWNrZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIF9fd19wZGZqc19yZXF1aXJlX18oMik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjb25zdCBJREVOVElUWV9NQVRSSVggPSBbMSwgMCwgMCwgMSwgMCwgMF07CiAgICAgICAgICAgICAgICBleHBvcnRzLklERU5USVRZX01BVFJJWCA9IElERU5USVRZX01BVFJJWDsKICAgICAgICAgICAgICAgIGNvbnN0IEZPTlRfSURFTlRJVFlfTUFUUklYID0gWzAuMDAxLCAwLCAwLCAwLjAwMSwgMCwgMF07CiAgICAgICAgICAgICAgICBleHBvcnRzLkZPTlRfSURFTlRJVFlfTUFUUklYID0gRk9OVF9JREVOVElUWV9NQVRSSVg7CiAgICAgICAgICAgICAgICBjb25zdCBNQVhfSU1BR0VfU0laRV9UT19DQUNIRSA9IDEwZTY7CiAgICAgICAgICAgICAgICBleHBvcnRzLk1BWF9JTUFHRV9TSVpFX1RPX0NBQ0hFID0gTUFYX0lNQUdFX1NJWkVfVE9fQ0FDSEU7CiAgICAgICAgICAgICAgICBjb25zdCBMSU5FX0ZBQ1RPUiA9IDEuMzU7CiAgICAgICAgICAgICAgICBleHBvcnRzLkxJTkVfRkFDVE9SID0gTElORV9GQUNUT1I7CiAgICAgICAgICAgICAgICBjb25zdCBMSU5FX0RFU0NFTlRfRkFDVE9SID0gMC4zNTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuTElORV9ERVNDRU5UX0ZBQ1RPUiA9IExJTkVfREVTQ0VOVF9GQUNUT1I7CiAgICAgICAgICAgICAgICBjb25zdCBCQVNFTElORV9GQUNUT1IgPSBMSU5FX0RFU0NFTlRfRkFDVE9SIC8gTElORV9GQUNUT1I7CiAgICAgICAgICAgICAgICBleHBvcnRzLkJBU0VMSU5FX0ZBQ1RPUiA9IEJBU0VMSU5FX0ZBQ1RPUjsKICAgICAgICAgICAgICAgIGNvbnN0IFJlbmRlcmluZ0ludGVudEZsYWcgPSB7CiAgICAgICAgICAgICAgICAgICAgQU5ZOiAweDAxLAogICAgICAgICAgICAgICAgICAgIERJU1BMQVk6IDB4MDIsCiAgICAgICAgICAgICAgICAgICAgUFJJTlQ6IDB4MDQsCiAgICAgICAgICAgICAgICAgICAgU0FWRTogMHgwOCwKICAgICAgICAgICAgICAgICAgICBBTk5PVEFUSU9OU19GT1JNUzogMHgxMCwKICAgICAgICAgICAgICAgICAgICBBTk5PVEFUSU9OU19TVE9SQUdFOiAweDIwLAogICAgICAgICAgICAgICAgICAgIEFOTk9UQVRJT05TX0RJU0FCTEU6IDB4NDAsCiAgICAgICAgICAgICAgICAgICAgT1BMSVNUOiAweDEwMAogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuUmVuZGVyaW5nSW50ZW50RmxhZyA9IFJlbmRlcmluZ0ludGVudEZsYWc7CiAgICAgICAgICAgICAgICBjb25zdCBBbm5vdGF0aW9uTW9kZSA9IHsKICAgICAgICAgICAgICAgICAgICBESVNBQkxFOiAwLAogICAgICAgICAgICAgICAgICAgIEVOQUJMRTogMSwKICAgICAgICAgICAgICAgICAgICBFTkFCTEVfRk9STVM6IDIsCiAgICAgICAgICAgICAgICAgICAgRU5BQkxFX1NUT1JBR0U6IDMKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBleHBvcnRzLkFubm90YXRpb25Nb2RlID0gQW5ub3RhdGlvbk1vZGU7CiAgICAgICAgICAgICAgICBjb25zdCBBbm5vdGF0aW9uRWRpdG9yUHJlZml4ID0gInBkZmpzX2ludGVybmFsX2VkaXRvcl8iOwogICAgICAgICAgICAgICAgZXhwb3J0cy5Bbm5vdGF0aW9uRWRpdG9yUHJlZml4ID0gQW5ub3RhdGlvbkVkaXRvclByZWZpeDsKICAgICAgICAgICAgICAgIGNvbnN0IEFubm90YXRpb25FZGl0b3JUeXBlID0gewogICAgICAgICAgICAgICAgICAgIERJU0FCTEU6IC0xLAogICAgICAgICAgICAgICAgICAgIE5PTkU6IDAsCiAgICAgICAgICAgICAgICAgICAgRlJFRVRFWFQ6IDMsCiAgICAgICAgICAgICAgICAgICAgSU5LOiAxNQogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuQW5ub3RhdGlvbkVkaXRvclR5cGUgPSBBbm5vdGF0aW9uRWRpdG9yVHlwZTsKICAgICAgICAgICAgICAgIGNvbnN0IEFubm90YXRpb25FZGl0b3JQYXJhbXNUeXBlID0gewogICAgICAgICAgICAgICAgICAgIEZSRUVURVhUX1NJWkU6IDEsCiAgICAgICAgICAgICAgICAgICAgRlJFRVRFWFRfQ09MT1I6IDIsCiAgICAgICAgICAgICAgICAgICAgRlJFRVRFWFRfT1BBQ0lUWTogMywKICAgICAgICAgICAgICAgICAgICBJTktfQ09MT1I6IDExLAogICAgICAgICAgICAgICAgICAgIElOS19USElDS05FU1M6IDEyLAogICAgICAgICAgICAgICAgICAgIElOS19PUEFDSVRZOiAxMwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuQW5ub3RhdGlvbkVkaXRvclBhcmFtc1R5cGUgPSBBbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZTsKICAgICAgICAgICAgICAgIGNvbnN0IFBlcm1pc3Npb25GbGFnID0gewogICAgICAgICAgICAgICAgICAgIFBSSU5UOiAweDA0LAogICAgICAgICAgICAgICAgICAgIE1PRElGWV9DT05URU5UUzogMHgwOCwKICAgICAgICAgICAgICAgICAgICBDT1BZOiAweDEwLAogICAgICAgICAgICAgICAgICAgIE1PRElGWV9BTk5PVEFUSU9OUzogMHgyMCwKICAgICAgICAgICAgICAgICAgICBGSUxMX0lOVEVSQUNUSVZFX0ZPUk1TOiAweDEwMCwKICAgICAgICAgICAgICAgICAgICBDT1BZX0ZPUl9BQ0NFU1NJQklMSVRZOiAweDIwMCwKICAgICAgICAgICAgICAgICAgICBBU1NFTUJMRTogMHg0MDAsCiAgICAgICAgICAgICAgICAgICAgUFJJTlRfSElHSF9RVUFMSVRZOiAweDgwMAogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuUGVybWlzc2lvbkZsYWcgPSBQZXJtaXNzaW9uRmxhZzsKICAgICAgICAgICAgICAgIGNvbnN0IFRleHRSZW5kZXJpbmdNb2RlID0gewogICAgICAgICAgICAgICAgICAgIEZJTEw6IDAsCiAgICAgICAgICAgICAgICAgICAgU1RST0tFOiAxLAogICAgICAgICAgICAgICAgICAgIEZJTExfU1RST0tFOiAyLAogICAgICAgICAgICAgICAgICAgIElOVklTSUJMRTogMywKICAgICAgICAgICAgICAgICAgICBGSUxMX0FERF9UT19QQVRIOiA0LAogICAgICAgICAgICAgICAgICAgIFNUUk9LRV9BRERfVE9fUEFUSDogNSwKICAgICAgICAgICAgICAgICAgICBGSUxMX1NUUk9LRV9BRERfVE9fUEFUSDogNiwKICAgICAgICAgICAgICAgICAgICBBRERfVE9fUEFUSDogNywKICAgICAgICAgICAgICAgICAgICBGSUxMX1NUUk9LRV9NQVNLOiAzLAogICAgICAgICAgICAgICAgICAgIEFERF9UT19QQVRIX0ZMQUc6IDQKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBleHBvcnRzLlRleHRSZW5kZXJpbmdNb2RlID0gVGV4dFJlbmRlcmluZ01vZGU7CiAgICAgICAgICAgICAgICBjb25zdCBJbWFnZUtpbmQgPSB7CiAgICAgICAgICAgICAgICAgICAgR1JBWVNDQUxFXzFCUFA6IDEsCiAgICAgICAgICAgICAgICAgICAgUkdCXzI0QlBQOiAyLAogICAgICAgICAgICAgICAgICAgIFJHQkFfMzJCUFA6IDMKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBleHBvcnRzLkltYWdlS2luZCA9IEltYWdlS2luZDsKICAgICAgICAgICAgICAgIGNvbnN0IEFubm90YXRpb25UeXBlID0gewogICAgICAgICAgICAgICAgICAgIFRFWFQ6IDEsCiAgICAgICAgICAgICAgICAgICAgTElOSzogMiwKICAgICAgICAgICAgICAgICAgICBGUkVFVEVYVDogMywKICAgICAgICAgICAgICAgICAgICBMSU5FOiA0LAogICAgICAgICAgICAgICAgICAgIFNRVUFSRTogNSwKICAgICAgICAgICAgICAgICAgICBDSVJDTEU6IDYsCiAgICAgICAgICAgICAgICAgICAgUE9MWUdPTjogNywKICAgICAgICAgICAgICAgICAgICBQT0xZTElORTogOCwKICAgICAgICAgICAgICAgICAgICBISUdITElHSFQ6IDksCiAgICAgICAgICAgICAgICAgICAgVU5ERVJMSU5FOiAxMCwKICAgICAgICAgICAgICAgICAgICBTUVVJR0dMWTogMTEsCiAgICAgICAgICAgICAgICAgICAgU1RSSUtFT1VUOiAxMiwKICAgICAgICAgICAgICAgICAgICBTVEFNUDogMTMsCiAgICAgICAgICAgICAgICAgICAgQ0FSRVQ6IDE0LAogICAgICAgICAgICAgICAgICAgIElOSzogMTUsCiAgICAgICAgICAgICAgICAgICAgUE9QVVA6IDE2LAogICAgICAgICAgICAgICAgICAgIEZJTEVBVFRBQ0hNRU5UOiAxNywKICAgICAgICAgICAgICAgICAgICBTT1VORDogMTgsCiAgICAgICAgICAgICAgICAgICAgTU9WSUU6IDE5LAogICAgICAgICAgICAgICAgICAgIFdJREdFVDogMjAsCiAgICAgICAgICAgICAgICAgICAgU0NSRUVOOiAyMSwKICAgICAgICAgICAgICAgICAgICBQUklOVEVSTUFSSzogMjIsCiAgICAgICAgICAgICAgICAgICAgVFJBUE5FVDogMjMsCiAgICAgICAgICAgICAgICAgICAgV0FURVJNQVJLOiAyNCwKICAgICAgICAgICAgICAgICAgICBUSFJFRUQ6IDI1LAogICAgICAgICAgICAgICAgICAgIFJFREFDVDogMjYKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBleHBvcnRzLkFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGU7CiAgICAgICAgICAgICAgICBjb25zdCBBbm5vdGF0aW9uU3RhdGVNb2RlbFR5cGUgPSB7CiAgICAgICAgICAgICAgICAgICAgTUFSS0VEOiAiTWFya2VkIiwKICAgICAgICAgICAgICAgICAgICBSRVZJRVc6ICJSZXZpZXciCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgZXhwb3J0cy5Bbm5vdGF0aW9uU3RhdGVNb2RlbFR5cGUgPSBBbm5vdGF0aW9uU3RhdGVNb2RlbFR5cGU7CiAgICAgICAgICAgICAgICBjb25zdCBBbm5vdGF0aW9uTWFya2VkU3RhdGUgPSB7CiAgICAgICAgICAgICAgICAgICAgTUFSS0VEOiAiTWFya2VkIiwKICAgICAgICAgICAgICAgICAgICBVTk1BUktFRDogIlVubWFya2VkIgogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuQW5ub3RhdGlvbk1hcmtlZFN0YXRlID0gQW5ub3RhdGlvbk1hcmtlZFN0YXRlOwogICAgICAgICAgICAgICAgY29uc3QgQW5ub3RhdGlvblJldmlld1N0YXRlID0gewogICAgICAgICAgICAgICAgICAgIEFDQ0VQVEVEOiAiQWNjZXB0ZWQiLAogICAgICAgICAgICAgICAgICAgIFJFSkVDVEVEOiAiUmVqZWN0ZWQiLAogICAgICAgICAgICAgICAgICAgIENBTkNFTExFRDogIkNhbmNlbGxlZCIsCiAgICAgICAgICAgICAgICAgICAgQ09NUExFVEVEOiAiQ29tcGxldGVkIiwKICAgICAgICAgICAgICAgICAgICBOT05FOiAiTm9uZSIKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBleHBvcnRzLkFubm90YXRpb25SZXZpZXdTdGF0ZSA9IEFubm90YXRpb25SZXZpZXdTdGF0ZTsKICAgICAgICAgICAgICAgIGNvbnN0IEFubm90YXRpb25SZXBseVR5cGUgPSB7CiAgICAgICAgICAgICAgICAgICAgR1JPVVA6ICJHcm91cCIsCiAgICAgICAgICAgICAgICAgICAgUkVQTFk6ICJSIgogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuQW5ub3RhdGlvblJlcGx5VHlwZSA9IEFubm90YXRpb25SZXBseVR5cGU7CiAgICAgICAgICAgICAgICBjb25zdCBBbm5vdGF0aW9uRmxhZyA9IHsKICAgICAgICAgICAgICAgICAgICBJTlZJU0lCTEU6IDB4MDEsCiAgICAgICAgICAgICAgICAgICAgSElEREVOOiAweDAyLAogICAgICAgICAgICAgICAgICAgIFBSSU5UOiAweDA0LAogICAgICAgICAgICAgICAgICAgIE5PWk9PTTogMHgwOCwKICAgICAgICAgICAgICAgICAgICBOT1JPVEFURTogMHgxMCwKICAgICAgICAgICAgICAgICAgICBOT1ZJRVc6IDB4MjAsCiAgICAgICAgICAgICAgICAgICAgUkVBRE9OTFk6IDB4NDAsCiAgICAgICAgICAgICAgICAgICAgTE9DS0VEOiAweDgwLAogICAgICAgICAgICAgICAgICAgIFRPR0dMRU5PVklFVzogMHgxMDAsCiAgICAgICAgICAgICAgICAgICAgTE9DS0VEQ09OVEVOVFM6IDB4MjAwCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgZXhwb3J0cy5Bbm5vdGF0aW9uRmxhZyA9IEFubm90YXRpb25GbGFnOwogICAgICAgICAgICAgICAgY29uc3QgQW5ub3RhdGlvbkZpZWxkRmxhZyA9IHsKICAgICAgICAgICAgICAgICAgICBSRUFET05MWTogMHgwMDAwMDAxLAogICAgICAgICAgICAgICAgICAgIFJFUVVJUkVEOiAweDAwMDAwMDIsCiAgICAgICAgICAgICAgICAgICAgTk9FWFBPUlQ6IDB4MDAwMDAwNCwKICAgICAgICAgICAgICAgICAgICBNVUxUSUxJTkU6IDB4MDAwMTAwMCwKICAgICAgICAgICAgICAgICAgICBQQVNTV09SRDogMHgwMDAyMDAwLAogICAgICAgICAgICAgICAgICAgIE5PVE9HR0xFVE9PRkY6IDB4MDAwNDAwMCwKICAgICAgICAgICAgICAgICAgICBSQURJTzogMHgwMDA4MDAwLAogICAgICAgICAgICAgICAgICAgIFBVU0hCVVRUT046IDB4MDAxMDAwMCwKICAgICAgICAgICAgICAgICAgICBDT01CTzogMHgwMDIwMDAwLAogICAgICAgICAgICAgICAgICAgIEVESVQ6IDB4MDA0MDAwMCwKICAgICAgICAgICAgICAgICAgICBTT1JUOiAweDAwODAwMDAsCiAgICAgICAgICAgICAgICAgICAgRklMRVNFTEVDVDogMHgwMTAwMDAwLAogICAgICAgICAgICAgICAgICAgIE1VTFRJU0VMRUNUOiAweDAyMDAwMDAsCiAgICAgICAgICAgICAgICAgICAgRE9OT1RTUEVMTENIRUNLOiAweDA0MDAwMDAsCiAgICAgICAgICAgICAgICAgICAgRE9OT1RTQ1JPTEw6IDB4MDgwMDAwMCwKICAgICAgICAgICAgICAgICAgICBDT01COiAweDEwMDAwMDAsCiAgICAgICAgICAgICAgICAgICAgUklDSFRFWFQ6IDB4MjAwMDAwMCwKICAgICAgICAgICAgICAgICAgICBSQURJT1NJTlVOSVNPTjogMHgyMDAwMDAwLAogICAgICAgICAgICAgICAgICAgIENPTU1JVE9OU0VMQ0hBTkdFOiAweDQwMDAwMDAKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBleHBvcnRzLkFubm90YXRpb25GaWVsZEZsYWcgPSBBbm5vdGF0aW9uRmllbGRGbGFnOwogICAgICAgICAgICAgICAgY29uc3QgQW5ub3RhdGlvbkJvcmRlclN0eWxlVHlwZSA9IHsKICAgICAgICAgICAgICAgICAgICBTT0xJRDogMSwKICAgICAgICAgICAgICAgICAgICBEQVNIRUQ6IDIsCiAgICAgICAgICAgICAgICAgICAgQkVWRUxFRDogMywKICAgICAgICAgICAgICAgICAgICBJTlNFVDogNCwKICAgICAgICAgICAgICAgICAgICBVTkRFUkxJTkU6IDUKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBleHBvcnRzLkFubm90YXRpb25Cb3JkZXJTdHlsZVR5cGUgPSBBbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlOwogICAgICAgICAgICAgICAgY29uc3QgQW5ub3RhdGlvbkFjdGlvbkV2ZW50VHlwZSA9IHsKICAgICAgICAgICAgICAgICAgICBFOiAiTW91c2UgRW50ZXIiLAogICAgICAgICAgICAgICAgICAgIFg6ICJNb3VzZSBFeGl0IiwKICAgICAgICAgICAgICAgICAgICBEOiAiTW91c2UgRG93biIsCiAgICAgICAgICAgICAgICAgICAgVTogIk1vdXNlIFVwIiwKICAgICAgICAgICAgICAgICAgICBGbzogIkZvY3VzIiwKICAgICAgICAgICAgICAgICAgICBCbDogIkJsdXIiLAogICAgICAgICAgICAgICAgICAgIFBPOiAiUGFnZU9wZW4iLAogICAgICAgICAgICAgICAgICAgIFBDOiAiUGFnZUNsb3NlIiwKICAgICAgICAgICAgICAgICAgICBQVjogIlBhZ2VWaXNpYmxlIiwKICAgICAgICAgICAgICAgICAgICBQSTogIlBhZ2VJbnZpc2libGUiLAogICAgICAgICAgICAgICAgICAgIEs6ICJLZXlzdHJva2UiLAogICAgICAgICAgICAgICAgICAgIEY6ICJGb3JtYXQiLAogICAgICAgICAgICAgICAgICAgIFY6ICJWYWxpZGF0ZSIsCiAgICAgICAgICAgICAgICAgICAgQzogIkNhbGN1bGF0ZSIKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBleHBvcnRzLkFubm90YXRpb25BY3Rpb25FdmVudFR5cGUgPSBBbm5vdGF0aW9uQWN0aW9uRXZlbnRUeXBlOwogICAgICAgICAgICAgICAgY29uc3QgRG9jdW1lbnRBY3Rpb25FdmVudFR5cGUgPSB7CiAgICAgICAgICAgICAgICAgICAgV0M6ICJXaWxsQ2xvc2UiLAogICAgICAgICAgICAgICAgICAgIFdTOiAiV2lsbFNhdmUiLAogICAgICAgICAgICAgICAgICAgIERTOiAiRGlkU2F2ZSIsCiAgICAgICAgICAgICAgICAgICAgV1A6ICJXaWxsUHJpbnQiLAogICAgICAgICAgICAgICAgICAgIERQOiAiRGlkUHJpbnQiCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgZXhwb3J0cy5Eb2N1bWVudEFjdGlvbkV2ZW50VHlwZSA9IERvY3VtZW50QWN0aW9uRXZlbnRUeXBlOwogICAgICAgICAgICAgICAgY29uc3QgUGFnZUFjdGlvbkV2ZW50VHlwZSA9IHsKICAgICAgICAgICAgICAgICAgICBPOiAiUGFnZU9wZW4iLAogICAgICAgICAgICAgICAgICAgIEM6ICJQYWdlQ2xvc2UiCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgZXhwb3J0cy5QYWdlQWN0aW9uRXZlbnRUeXBlID0gUGFnZUFjdGlvbkV2ZW50VHlwZTsKICAgICAgICAgICAgICAgIGNvbnN0IFZlcmJvc2l0eUxldmVsID0gewogICAgICAgICAgICAgICAgICAgIEVSUk9SUzogMCwKICAgICAgICAgICAgICAgICAgICBXQVJOSU5HUzogMSwKICAgICAgICAgICAgICAgICAgICBJTkZPUzogNQogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuVmVyYm9zaXR5TGV2ZWwgPSBWZXJib3NpdHlMZXZlbDsKICAgICAgICAgICAgICAgIGNvbnN0IENNYXBDb21wcmVzc2lvblR5cGUgPSB7CiAgICAgICAgICAgICAgICAgICAgTk9ORTogMCwKICAgICAgICAgICAgICAgICAgICBCSU5BUlk6IDEKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBleHBvcnRzLkNNYXBDb21wcmVzc2lvblR5cGUgPSBDTWFwQ29tcHJlc3Npb25UeXBlOwogICAgICAgICAgICAgICAgY29uc3QgT1BTID0gewogICAgICAgICAgICAgICAgICAgIGRlcGVuZGVuY3k6IDEsCiAgICAgICAgICAgICAgICAgICAgc2V0TGluZVdpZHRoOiAyLAogICAgICAgICAgICAgICAgICAgIHNldExpbmVDYXA6IDMsCiAgICAgICAgICAgICAgICAgICAgc2V0TGluZUpvaW46IDQsCiAgICAgICAgICAgICAgICAgICAgc2V0TWl0ZXJMaW1pdDogNSwKICAgICAgICAgICAgICAgICAgICBzZXREYXNoOiA2LAogICAgICAgICAgICAgICAgICAgIHNldFJlbmRlcmluZ0ludGVudDogNywKICAgICAgICAgICAgICAgICAgICBzZXRGbGF0bmVzczogOCwKICAgICAgICAgICAgICAgICAgICBzZXRHU3RhdGU6IDksCiAgICAgICAgICAgICAgICAgICAgc2F2ZTogMTAsCiAgICAgICAgICAgICAgICAgICAgcmVzdG9yZTogMTEsCiAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiAxMiwKICAgICAgICAgICAgICAgICAgICBtb3ZlVG86IDEzLAogICAgICAgICAgICAgICAgICAgIGxpbmVUbzogMTQsCiAgICAgICAgICAgICAgICAgICAgY3VydmVUbzogMTUsCiAgICAgICAgICAgICAgICAgICAgY3VydmVUbzI6IDE2LAogICAgICAgICAgICAgICAgICAgIGN1cnZlVG8zOiAxNywKICAgICAgICAgICAgICAgICAgICBjbG9zZVBhdGg6IDE4LAogICAgICAgICAgICAgICAgICAgIHJlY3RhbmdsZTogMTksCiAgICAgICAgICAgICAgICAgICAgc3Ryb2tlOiAyMCwKICAgICAgICAgICAgICAgICAgICBjbG9zZVN0cm9rZTogMjEsCiAgICAgICAgICAgICAgICAgICAgZmlsbDogMjIsCiAgICAgICAgICAgICAgICAgICAgZW9GaWxsOiAyMywKICAgICAgICAgICAgICAgICAgICBmaWxsU3Ryb2tlOiAyNCwKICAgICAgICAgICAgICAgICAgICBlb0ZpbGxTdHJva2U6IDI1LAogICAgICAgICAgICAgICAgICAgIGNsb3NlRmlsbFN0cm9rZTogMjYsCiAgICAgICAgICAgICAgICAgICAgY2xvc2VFT0ZpbGxTdHJva2U6IDI3LAogICAgICAgICAgICAgICAgICAgIGVuZFBhdGg6IDI4LAogICAgICAgICAgICAgICAgICAgIGNsaXA6IDI5LAogICAgICAgICAgICAgICAgICAgIGVvQ2xpcDogMzAsCiAgICAgICAgICAgICAgICAgICAgYmVnaW5UZXh0OiAzMSwKICAgICAgICAgICAgICAgICAgICBlbmRUZXh0OiAzMiwKICAgICAgICAgICAgICAgICAgICBzZXRDaGFyU3BhY2luZzogMzMsCiAgICAgICAgICAgICAgICAgICAgc2V0V29yZFNwYWNpbmc6IDM0LAogICAgICAgICAgICAgICAgICAgIHNldEhTY2FsZTogMzUsCiAgICAgICAgICAgICAgICAgICAgc2V0TGVhZGluZzogMzYsCiAgICAgICAgICAgICAgICAgICAgc2V0Rm9udDogMzcsCiAgICAgICAgICAgICAgICAgICAgc2V0VGV4dFJlbmRlcmluZ01vZGU6IDM4LAogICAgICAgICAgICAgICAgICAgIHNldFRleHRSaXNlOiAzOSwKICAgICAgICAgICAgICAgICAgICBtb3ZlVGV4dDogNDAsCiAgICAgICAgICAgICAgICAgICAgc2V0TGVhZGluZ01vdmVUZXh0OiA0MSwKICAgICAgICAgICAgICAgICAgICBzZXRUZXh0TWF0cml4OiA0MiwKICAgICAgICAgICAgICAgICAgICBuZXh0TGluZTogNDMsCiAgICAgICAgICAgICAgICAgICAgc2hvd1RleHQ6IDQ0LAogICAgICAgICAgICAgICAgICAgIHNob3dTcGFjZWRUZXh0OiA0NSwKICAgICAgICAgICAgICAgICAgICBuZXh0TGluZVNob3dUZXh0OiA0NiwKICAgICAgICAgICAgICAgICAgICBuZXh0TGluZVNldFNwYWNpbmdTaG93VGV4dDogNDcsCiAgICAgICAgICAgICAgICAgICAgc2V0Q2hhcldpZHRoOiA0OCwKICAgICAgICAgICAgICAgICAgICBzZXRDaGFyV2lkdGhBbmRCb3VuZHM6IDQ5LAogICAgICAgICAgICAgICAgICAgIHNldFN0cm9rZUNvbG9yU3BhY2U6IDUwLAogICAgICAgICAgICAgICAgICAgIHNldEZpbGxDb2xvclNwYWNlOiA1MSwKICAgICAgICAgICAgICAgICAgICBzZXRTdHJva2VDb2xvcjogNTIsCiAgICAgICAgICAgICAgICAgICAgc2V0U3Ryb2tlQ29sb3JOOiA1MywKICAgICAgICAgICAgICAgICAgICBzZXRGaWxsQ29sb3I6IDU0LAogICAgICAgICAgICAgICAgICAgIHNldEZpbGxDb2xvck46IDU1LAogICAgICAgICAgICAgICAgICAgIHNldFN0cm9rZUdyYXk6IDU2LAogICAgICAgICAgICAgICAgICAgIHNldEZpbGxHcmF5OiA1NywKICAgICAgICAgICAgICAgICAgICBzZXRTdHJva2VSR0JDb2xvcjogNTgsCiAgICAgICAgICAgICAgICAgICAgc2V0RmlsbFJHQkNvbG9yOiA1OSwKICAgICAgICAgICAgICAgICAgICBzZXRTdHJva2VDTVlLQ29sb3I6IDYwLAogICAgICAgICAgICAgICAgICAgIHNldEZpbGxDTVlLQ29sb3I6IDYxLAogICAgICAgICAgICAgICAgICAgIHNoYWRpbmdGaWxsOiA2MiwKICAgICAgICAgICAgICAgICAgICBiZWdpbklubGluZUltYWdlOiA2MywKICAgICAgICAgICAgICAgICAgICBiZWdpbkltYWdlRGF0YTogNjQsCiAgICAgICAgICAgICAgICAgICAgZW5kSW5saW5lSW1hZ2U6IDY1LAogICAgICAgICAgICAgICAgICAgIHBhaW50WE9iamVjdDogNjYsCiAgICAgICAgICAgICAgICAgICAgbWFya1BvaW50OiA2NywKICAgICAgICAgICAgICAgICAgICBtYXJrUG9pbnRQcm9wczogNjgsCiAgICAgICAgICAgICAgICAgICAgYmVnaW5NYXJrZWRDb250ZW50OiA2OSwKICAgICAgICAgICAgICAgICAgICBiZWdpbk1hcmtlZENvbnRlbnRQcm9wczogNzAsCiAgICAgICAgICAgICAgICAgICAgZW5kTWFya2VkQ29udGVudDogNzEsCiAgICAgICAgICAgICAgICAgICAgYmVnaW5Db21wYXQ6IDcyLAogICAgICAgICAgICAgICAgICAgIGVuZENvbXBhdDogNzMsCiAgICAgICAgICAgICAgICAgICAgcGFpbnRGb3JtWE9iamVjdEJlZ2luOiA3NCwKICAgICAgICAgICAgICAgICAgICBwYWludEZvcm1YT2JqZWN0RW5kOiA3NSwKICAgICAgICAgICAgICAgICAgICBiZWdpbkdyb3VwOiA3NiwKICAgICAgICAgICAgICAgICAgICBlbmRHcm91cDogNzcsCiAgICAgICAgICAgICAgICAgICAgYmVnaW5Bbm5vdGF0aW9uOiA4MCwKICAgICAgICAgICAgICAgICAgICBlbmRBbm5vdGF0aW9uOiA4MSwKICAgICAgICAgICAgICAgICAgICBwYWludEltYWdlTWFza1hPYmplY3Q6IDgzLAogICAgICAgICAgICAgICAgICAgIHBhaW50SW1hZ2VNYXNrWE9iamVjdEdyb3VwOiA4NCwKICAgICAgICAgICAgICAgICAgICBwYWludEltYWdlWE9iamVjdDogODUsCiAgICAgICAgICAgICAgICAgICAgcGFpbnRJbmxpbmVJbWFnZVhPYmplY3Q6IDg2LAogICAgICAgICAgICAgICAgICAgIHBhaW50SW5saW5lSW1hZ2VYT2JqZWN0R3JvdXA6IDg3LAogICAgICAgICAgICAgICAgICAgIHBhaW50SW1hZ2VYT2JqZWN0UmVwZWF0OiA4OCwKICAgICAgICAgICAgICAgICAgICBwYWludEltYWdlTWFza1hPYmplY3RSZXBlYXQ6IDg5LAogICAgICAgICAgICAgICAgICAgIHBhaW50U29saWRDb2xvckltYWdlTWFzazogOTAsCiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0UGF0aDogOTEKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBleHBvcnRzLk9QUyA9IE9QUzsKICAgICAgICAgICAgICAgIGNvbnN0IFBhc3N3b3JkUmVzcG9uc2VzID0gewogICAgICAgICAgICAgICAgICAgIE5FRURfUEFTU1dPUkQ6IDEsCiAgICAgICAgICAgICAgICAgICAgSU5DT1JSRUNUX1BBU1NXT1JEOiAyCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgZXhwb3J0cy5QYXNzd29yZFJlc3BvbnNlcyA9IFBhc3N3b3JkUmVzcG9uc2VzOwogICAgICAgICAgICAgICAgbGV0IHZlcmJvc2l0eSA9IFZlcmJvc2l0eUxldmVsLldBUk5JTkdTOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gc2V0VmVyYm9zaXR5TGV2ZWwobGV2ZWwpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihsZXZlbCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zaXR5ID0gbGV2ZWw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gZ2V0VmVyYm9zaXR5TGV2ZWwoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZlcmJvc2l0eTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGluZm8obXNnKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKHZlcmJvc2l0eSA+PSBWZXJib3NpdHlMZXZlbC5JTkZPUykgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgSW5mbzogJHttc2d9YCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gd2Fybihtc2cpIHsKICAgICAgICAgICAgICAgICAgICBpZiAodmVyYm9zaXR5ID49IFZlcmJvc2l0eUxldmVsLldBUk5JTkdTKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBXYXJuaW5nOiAke21zZ31gKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiB1bnJlYWNoYWJsZShtc2cpIHsKICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGFzc2VydChjb25kLCBtc2cpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbmQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdW5yZWFjaGFibGUobXNnKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfaXNWYWxpZFByb3RvY29sKHVybCkgewogICAgICAgICAgICAgICAgICAgIGlmICghdXJsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh1cmwucHJvdG9jb2wpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiaHR0cDoiOgogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJodHRwczoiOgogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJmdHA6IjoKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAibWFpbHRvOiI6CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgInRlbDoiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlVmFsaWRBYnNvbHV0ZVVybCh1cmwpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgYmFzZVVybCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICBsZXQgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICBpZiAoIXVybCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMgJiYgdHlwZW9mIHVybCA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmFkZERlZmF1bHRQcm90b2NvbCAmJiB1cmwuc3RhcnRzV2l0aCgid3d3LiIpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZG90cyA9IHVybC5tYXRjaCgvXC4vZyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvdHMgJiYgZG90cy5sZW5ndGggPj0gMikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmwgPSBgaHR0cDovLyR7dXJsfWA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMudHJ5Q29udmVydEVuY29kaW5nKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsID0gc3RyaW5nVG9VVEY4U3RyaW5nKHVybCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXgpIHt9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYWJzb2x1dGVVcmwgPSBiYXNlVXJsID8gbmV3IFVSTCh1cmwsIGJhc2VVcmwpIDogbmV3IFVSTCh1cmwpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoX2lzVmFsaWRQcm90b2NvbChhYnNvbHV0ZVVybCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhYnNvbHV0ZVVybDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7fQogICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gc2hhZG93KG9iaiwgcHJvcCwgdmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgbm9uU2VyaWFsaXphYmxlID0gYXJndW1lbnRzLmxlbmd0aCA+IDMgJiYgYXJndW1lbnRzWzNdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbM10gOiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBwcm9wLCB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiAhbm9uU2VyaWFsaXphYmxlLAogICAgICAgICAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiBmYWxzZQogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNvbnN0IEJhc2VFeGNlcHRpb24gPSBmdW5jdGlvbiBCYXNlRXhjZXB0aW9uQ2xvc3VyZSgpIHsKICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBCYXNlRXhjZXB0aW9uKG1lc3NhZ2UsIG5hbWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uc3RydWN0b3IgPT09IEJhc2VFeGNlcHRpb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVucmVhY2hhYmxlKCJDYW5ub3QgaW5pdGlhbGl6ZSBCYXNlRXhjZXB0aW9uLiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIEJhc2VFeGNlcHRpb24ucHJvdG90eXBlID0gbmV3IEVycm9yKCk7CiAgICAgICAgICAgICAgICAgICAgQmFzZUV4Y2VwdGlvbi5jb25zdHJ1Y3RvciA9IEJhc2VFeGNlcHRpb247CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEJhc2VFeGNlcHRpb247CiAgICAgICAgICAgICAgICB9KCk7CiAgICAgICAgICAgICAgICBleHBvcnRzLkJhc2VFeGNlcHRpb24gPSBCYXNlRXhjZXB0aW9uOwogICAgICAgICAgICAgICAgY2xhc3MgUGFzc3dvcmRFeGNlcHRpb24gZXh0ZW5kcyBCYXNlRXhjZXB0aW9uIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3Rvcihtc2csIGNvZGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIobXNnLCAiUGFzc3dvcmRFeGNlcHRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb2RlID0gY29kZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLlBhc3N3b3JkRXhjZXB0aW9uID0gUGFzc3dvcmRFeGNlcHRpb247CiAgICAgICAgICAgICAgICBjbGFzcyBVbmtub3duRXJyb3JFeGNlcHRpb24gZXh0ZW5kcyBCYXNlRXhjZXB0aW9uIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3Rvcihtc2csIGRldGFpbHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIobXNnLCAiVW5rbm93bkVycm9yRXhjZXB0aW9uIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGV0YWlscyA9IGRldGFpbHM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5Vbmtub3duRXJyb3JFeGNlcHRpb24gPSBVbmtub3duRXJyb3JFeGNlcHRpb247CiAgICAgICAgICAgICAgICBjbGFzcyBJbnZhbGlkUERGRXhjZXB0aW9uIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IobXNnKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKG1zZywgIkludmFsaWRQREZFeGNlcHRpb24iKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLkludmFsaWRQREZFeGNlcHRpb24gPSBJbnZhbGlkUERGRXhjZXB0aW9uOwogICAgICAgICAgICAgICAgY2xhc3MgTWlzc2luZ1BERkV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKG1zZykgewogICAgICAgICAgICAgICAgICAgICAgICBzdXBlcihtc2csICJNaXNzaW5nUERGRXhjZXB0aW9uIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5NaXNzaW5nUERGRXhjZXB0aW9uID0gTWlzc2luZ1BERkV4Y2VwdGlvbjsKICAgICAgICAgICAgICAgIGNsYXNzIFVuZXhwZWN0ZWRSZXNwb25zZUV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKG1zZywgc3RhdHVzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKG1zZywgIlVuZXhwZWN0ZWRSZXNwb25zZUV4Y2VwdGlvbiIpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLlVuZXhwZWN0ZWRSZXNwb25zZUV4Y2VwdGlvbiA9IFVuZXhwZWN0ZWRSZXNwb25zZUV4Y2VwdGlvbjsKICAgICAgICAgICAgICAgIGNsYXNzIEZvcm1hdEVycm9yIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IobXNnKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKG1zZywgIkZvcm1hdEVycm9yIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5Gb3JtYXRFcnJvciA9IEZvcm1hdEVycm9yOwogICAgICAgICAgICAgICAgY2xhc3MgQWJvcnRFeGNlcHRpb24gZXh0ZW5kcyBCYXNlRXhjZXB0aW9uIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3Rvcihtc2cpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIobXNnLCAiQWJvcnRFeGNlcHRpb24iKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLkFib3J0RXhjZXB0aW9uID0gQWJvcnRFeGNlcHRpb247CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBieXRlc1RvU3RyaW5nKGJ5dGVzKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBieXRlcyAhPT0gIm9iamVjdCIgfHwgYnl0ZXMgPT09IG51bGwgfHwgYnl0ZXMubGVuZ3RoID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdW5yZWFjaGFibGUoIkludmFsaWQgYXJndW1lbnQgZm9yIGJ5dGVzVG9TdHJpbmciKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gYnl0ZXMubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IE1BWF9BUkdVTUVOVF9DT1VOVCA9IDgxOTI7CiAgICAgICAgICAgICAgICAgICAgaWYgKGxlbmd0aCA8IE1BWF9BUkdVTUVOVF9DT1VOVCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBieXRlcyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0ckJ1ZiA9IFtdOwogICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IE1BWF9BUkdVTUVOVF9DT1VOVCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaHVua0VuZCA9IE1hdGgubWluKGkgKyBNQVhfQVJHVU1FTlRfQ09VTlQsIGxlbmd0aCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNodW5rID0gYnl0ZXMuc3ViYXJyYXkoaSwgY2h1bmtFbmQpOwogICAgICAgICAgICAgICAgICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsIGNodW5rKSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJCdWYuam9pbigiIik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdUb0J5dGVzKHN0cikgewogICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3RyICE9PSAic3RyaW5nIikgewogICAgICAgICAgICAgICAgICAgICAgICB1bnJlYWNoYWJsZSgiSW52YWxpZCBhcmd1bWVudCBmb3Igc3RyaW5nVG9CeXRlcyIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBsZW5ndGggPSBzdHIubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoKTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzW2ldID0gc3RyLmNoYXJDb2RlQXQoaSkgJiAweGZmOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gYnl0ZXM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmczMih2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKHZhbHVlID4+IDI0ICYgMHhmZiwgdmFsdWUgPj4gMTYgJiAweGZmLCB2YWx1ZSA+PiA4ICYgMHhmZiwgdmFsdWUgJiAweGZmKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIG9iamVjdFNpemUob2JqKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikubGVuZ3RoOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gb2JqZWN0RnJvbU1hcChtYXApIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBvYmogPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIG1hcCkgewogICAgICAgICAgICAgICAgICAgICAgICBvYmpba2V5XSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2JqOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gaXNMaXR0bGVFbmRpYW4oKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KDQpOwogICAgICAgICAgICAgICAgICAgIGJ1ZmZlcjhbMF0gPSAxOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHZpZXczMiA9IG5ldyBVaW50MzJBcnJheShidWZmZXI4LmJ1ZmZlciwgMCwgMSk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZpZXczMlswXSA9PT0gMTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGlzRXZhbFN1cHBvcnRlZCgpIHsKICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICBuZXcgRnVuY3Rpb24oIiIpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBGZWF0dXJlVGVzdCB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIGdldCBpc0xpdHRsZUVuZGlhbigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiaXNMaXR0bGVFbmRpYW4iLCBpc0xpdHRsZUVuZGlhbigpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIGdldCBpc0V2YWxTdXBwb3J0ZWQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzaGFkb3codGhpcywgImlzRXZhbFN1cHBvcnRlZCIsIGlzRXZhbFN1cHBvcnRlZCgpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIGdldCBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQiLCB0eXBlb2YgT2Zmc2NyZWVuQ2FudmFzICE9PSAidW5kZWZpbmVkIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBnZXQgcGxhdGZvcm0oKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yID09PSAidW5kZWZpbmVkIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAicGxhdGZvcm0iLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNXaW46IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzTWFjOiBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAicGxhdGZvcm0iLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1dpbjogbmF2aWdhdG9yLnBsYXRmb3JtLmluY2x1ZGVzKCJXaW4iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzTWFjOiBuYXZpZ2F0b3IucGxhdGZvcm0uaW5jbHVkZXMoIk1hYyIpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuRmVhdHVyZVRlc3QgPSBGZWF0dXJlVGVzdDsKICAgICAgICAgICAgICAgIGNvbnN0IGhleE51bWJlcnMgPSBbLi4uQXJyYXkoMjU2KS5rZXlzKCldLm1hcChuID0+IG4udG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsICIwIikpOwogICAgICAgICAgICAgICAgY2xhc3MgVXRpbCB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIG1ha2VIZXhDb2xvcihyLCBnLCBiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBgIyR7aGV4TnVtYmVyc1tyXX0ke2hleE51bWJlcnNbZ119JHtoZXhOdW1iZXJzW2JdfWA7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBzY2FsZU1pbk1heCh0cmFuc2Zvcm0sIG1pbk1heCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgdGVtcDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyYW5zZm9ybVswXSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyYW5zZm9ybVswXSA8IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZW1wID0gbWluTWF4WzBdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbk1heFswXSA9IG1pbk1heFsxXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5NYXhbMV0gPSB0ZW1wOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluTWF4WzBdICo9IHRyYW5zZm9ybVswXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbk1heFsxXSAqPSB0cmFuc2Zvcm1bMF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHJhbnNmb3JtWzNdIDwgMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXAgPSBtaW5NYXhbMl07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluTWF4WzJdID0gbWluTWF4WzNdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbk1heFszXSA9IHRlbXA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5NYXhbMl0gKj0gdHJhbnNmb3JtWzNdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluTWF4WzNdICo9IHRyYW5zZm9ybVszXTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXAgPSBtaW5NYXhbMF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5NYXhbMF0gPSBtaW5NYXhbMl07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5NYXhbMl0gPSB0ZW1wOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcCA9IG1pbk1heFsxXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbk1heFsxXSA9IG1pbk1heFszXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbk1heFszXSA9IHRlbXA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHJhbnNmb3JtWzFdIDwgMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXAgPSBtaW5NYXhbMl07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluTWF4WzJdID0gbWluTWF4WzNdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbk1heFszXSA9IHRlbXA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5NYXhbMl0gKj0gdHJhbnNmb3JtWzFdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluTWF4WzNdICo9IHRyYW5zZm9ybVsxXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0cmFuc2Zvcm1bMl0gPCAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcCA9IG1pbk1heFswXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5NYXhbMF0gPSBtaW5NYXhbMV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluTWF4WzFdID0gdGVtcDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbk1heFswXSAqPSB0cmFuc2Zvcm1bMl07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5NYXhbMV0gKj0gdHJhbnNmb3JtWzJdOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIG1pbk1heFswXSArPSB0cmFuc2Zvcm1bNF07CiAgICAgICAgICAgICAgICAgICAgICAgIG1pbk1heFsxXSArPSB0cmFuc2Zvcm1bNF07CiAgICAgICAgICAgICAgICAgICAgICAgIG1pbk1heFsyXSArPSB0cmFuc2Zvcm1bNV07CiAgICAgICAgICAgICAgICAgICAgICAgIG1pbk1heFszXSArPSB0cmFuc2Zvcm1bNV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyB0cmFuc2Zvcm0obTEsIG0yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbbTFbMF0gKiBtMlswXSArIG0xWzJdICogbTJbMV0sIG0xWzFdICogbTJbMF0gKyBtMVszXSAqIG0yWzFdLCBtMVswXSAqIG0yWzJdICsgbTFbMl0gKiBtMlszXSwgbTFbMV0gKiBtMlsyXSArIG0xWzNdICogbTJbM10sIG0xWzBdICogbTJbNF0gKyBtMVsyXSAqIG0yWzVdICsgbTFbNF0sIG0xWzFdICogbTJbNF0gKyBtMVszXSAqIG0yWzVdICsgbTFbNV1dOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgYXBwbHlUcmFuc2Zvcm0ocCwgbSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB4dCA9IHBbMF0gKiBtWzBdICsgcFsxXSAqIG1bMl0gKyBtWzRdOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB5dCA9IHBbMF0gKiBtWzFdICsgcFsxXSAqIG1bM10gKyBtWzVdOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW3h0LCB5dF07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBhcHBseUludmVyc2VUcmFuc2Zvcm0ocCwgbSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkID0gbVswXSAqIG1bM10gLSBtWzFdICogbVsyXTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeHQgPSAocFswXSAqIG1bM10gLSBwWzFdICogbVsyXSArIG1bMl0gKiBtWzVdIC0gbVs0XSAqIG1bM10pIC8gZDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeXQgPSAoLXBbMF0gKiBtWzFdICsgcFsxXSAqIG1bMF0gKyBtWzRdICogbVsxXSAtIG1bNV0gKiBtWzBdKSAvIGQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbeHQsIHl0XTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIGdldEF4aWFsQWxpZ25lZEJvdW5kaW5nQm94KHIsIG0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcDEgPSBVdGlsLmFwcGx5VHJhbnNmb3JtKHIsIG0pOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwMiA9IFV0aWwuYXBwbHlUcmFuc2Zvcm0oci5zbGljZSgyLCA0KSwgbSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHAzID0gVXRpbC5hcHBseVRyYW5zZm9ybShbclswXSwgclszXV0sIG0pOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwNCA9IFV0aWwuYXBwbHlUcmFuc2Zvcm0oW3JbMl0sIHJbMV1dLCBtKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtNYXRoLm1pbihwMVswXSwgcDJbMF0sIHAzWzBdLCBwNFswXSksIE1hdGgubWluKHAxWzFdLCBwMlsxXSwgcDNbMV0sIHA0WzFdKSwgTWF0aC5tYXgocDFbMF0sIHAyWzBdLCBwM1swXSwgcDRbMF0pLCBNYXRoLm1heChwMVsxXSwgcDJbMV0sIHAzWzFdLCBwNFsxXSldOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgaW52ZXJzZVRyYW5zZm9ybShtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGQgPSBtWzBdICogbVszXSAtIG1bMV0gKiBtWzJdOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW21bM10gLyBkLCAtbVsxXSAvIGQsIC1tWzJdIC8gZCwgbVswXSAvIGQsIChtWzJdICogbVs1XSAtIG1bNF0gKiBtWzNdKSAvIGQsIChtWzRdICogbVsxXSAtIG1bNV0gKiBtWzBdKSAvIGRdOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgc2luZ3VsYXJWYWx1ZURlY29tcG9zZTJkU2NhbGUobSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0cmFuc3Bvc2UgPSBbbVswXSwgbVsyXSwgbVsxXSwgbVszXV07CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGEgPSBtWzBdICogdHJhbnNwb3NlWzBdICsgbVsxXSAqIHRyYW5zcG9zZVsyXTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYiA9IG1bMF0gKiB0cmFuc3Bvc2VbMV0gKyBtWzFdICogdHJhbnNwb3NlWzNdOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjID0gbVsyXSAqIHRyYW5zcG9zZVswXSArIG1bM10gKiB0cmFuc3Bvc2VbMl07CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGQgPSBtWzJdICogdHJhbnNwb3NlWzFdICsgbVszXSAqIHRyYW5zcG9zZVszXTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlyc3QgPSAoYSArIGQpIC8gMjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2Vjb25kID0gTWF0aC5zcXJ0KChhICsgZCkgKiogMiAtIDQgKiAoYSAqIGQgLSBjICogYikpIC8gMjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3ggPSBmaXJzdCArIHNlY29uZCB8fCAxOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzeSA9IGZpcnN0IC0gc2Vjb25kIHx8IDE7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbTWF0aC5zcXJ0KHN4KSwgTWF0aC5zcXJ0KHN5KV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBub3JtYWxpemVSZWN0KHJlY3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgciA9IHJlY3Quc2xpY2UoMCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZWN0WzBdID4gcmVjdFsyXSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgclswXSA9IHJlY3RbMl07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByWzJdID0gcmVjdFswXTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVjdFsxXSA+IHJlY3RbM10pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJbMV0gPSByZWN0WzNdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgclszXSA9IHJlY3RbMV07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBpbnRlcnNlY3QocmVjdDEsIHJlY3QyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHhMb3cgPSBNYXRoLm1heChNYXRoLm1pbihyZWN0MVswXSwgcmVjdDFbMl0pLCBNYXRoLm1pbihyZWN0MlswXSwgcmVjdDJbMl0pKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeEhpZ2ggPSBNYXRoLm1pbihNYXRoLm1heChyZWN0MVswXSwgcmVjdDFbMl0pLCBNYXRoLm1heChyZWN0MlswXSwgcmVjdDJbMl0pKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHhMb3cgPiB4SGlnaCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeUxvdyA9IE1hdGgubWF4KE1hdGgubWluKHJlY3QxWzFdLCByZWN0MVszXSksIE1hdGgubWluKHJlY3QyWzFdLCByZWN0MlszXSkpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB5SGlnaCA9IE1hdGgubWluKE1hdGgubWF4KHJlY3QxWzFdLCByZWN0MVszXSksIE1hdGgubWF4KHJlY3QyWzFdLCByZWN0MlszXSkpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoeUxvdyA+IHlIaWdoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW3hMb3csIHlMb3csIHhIaWdoLCB5SGlnaF07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBiZXppZXJCb3VuZGluZ0JveCh4MCwgeTAsIHgxLCB5MSwgeDIsIHkyLCB4MywgeTMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdHZhbHVlcyA9IFtdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm91bmRzID0gW1tdLCBbXV07CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhLCBiLCBjLCB0LCB0MSwgdDIsIGIyYWMsIHNxcnRiMmFjOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI7ICsraSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGkgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiID0gNiAqIHgwIC0gMTIgKiB4MSArIDYgKiB4MjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhID0gLTMgKiB4MCArIDkgKiB4MSAtIDkgKiB4MiArIDMgKiB4MzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjID0gMyAqIHgxIC0gMyAqIHgwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiID0gNiAqIHkwIC0gMTIgKiB5MSArIDYgKiB5MjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhID0gLTMgKiB5MCArIDkgKiB5MSAtIDkgKiB5MiArIDMgKiB5MzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjID0gMyAqIHkxIC0gMyAqIHkwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKE1hdGguYWJzKGEpIDwgMWUtMTIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoTWF0aC5hYnMoYikgPCAxZS0xMikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdCA9IC1jIC8gYjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoMCA8IHQgJiYgdCA8IDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHZhbHVlcy5wdXNoKHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGIyYWMgPSBiICogYiAtIDQgKiBjICogYTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNxcnRiMmFjID0gTWF0aC5zcXJ0KGIyYWMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGIyYWMgPCAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0MSA9ICgtYiArIHNxcnRiMmFjKSAvICgyICogYSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoMCA8IHQxICYmIHQxIDwgMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR2YWx1ZXMucHVzaCh0MSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0MiA9ICgtYiAtIHNxcnRiMmFjKSAvICgyICogYSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoMCA8IHQyICYmIHQyIDwgMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR2YWx1ZXMucHVzaCh0Mik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGogPSB0dmFsdWVzLmxlbmd0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG10OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBqbGVuID0gajsKICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGotLSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdCA9IHR2YWx1ZXNbal07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdCA9IDEgLSB0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm91bmRzWzBdW2pdID0gbXQgKiBtdCAqIG10ICogeDAgKyAzICogbXQgKiBtdCAqIHQgKiB4MSArIDMgKiBtdCAqIHQgKiB0ICogeDIgKyB0ICogdCAqIHQgKiB4MzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJvdW5kc1sxXVtqXSA9IG10ICogbXQgKiBtdCAqIHkwICsgMyAqIG10ICogbXQgKiB0ICogeTEgKyAzICogbXQgKiB0ICogdCAqIHkyICsgdCAqIHQgKiB0ICogeTM7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgYm91bmRzWzBdW2psZW5dID0geDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGJvdW5kc1sxXVtqbGVuXSA9IHkwOwogICAgICAgICAgICAgICAgICAgICAgICBib3VuZHNbMF1bamxlbiArIDFdID0geDM7CiAgICAgICAgICAgICAgICAgICAgICAgIGJvdW5kc1sxXVtqbGVuICsgMV0gPSB5MzsKICAgICAgICAgICAgICAgICAgICAgICAgYm91bmRzWzBdLmxlbmd0aCA9IGJvdW5kc1sxXS5sZW5ndGggPSBqbGVuICsgMjsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtNYXRoLm1pbiguLi5ib3VuZHNbMF0pLCBNYXRoLm1pbiguLi5ib3VuZHNbMV0pLCBNYXRoLm1heCguLi5ib3VuZHNbMF0pLCBNYXRoLm1heCguLi5ib3VuZHNbMV0pXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLlV0aWwgPSBVdGlsOwogICAgICAgICAgICAgICAgY29uc3QgUERGU3RyaW5nVHJhbnNsYXRlVGFibGUgPSBbMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMHgyZDgsIDB4MmM3LCAweDJjNiwgMHgyZDksIDB4MmRkLCAweDJkYiwgMHgyZGEsIDB4MmRjLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAweDIwMjIsIDB4MjAyMCwgMHgyMDIxLCAweDIwMjYsIDB4MjAxNCwgMHgyMDEzLCAweDE5MiwgMHgyMDQ0LCAweDIwMzksIDB4MjAzYSwgMHgyMjEyLCAweDIwMzAsIDB4MjAxZSwgMHgyMDFjLCAweDIwMWQsIDB4MjAxOCwgMHgyMDE5LCAweDIwMWEsIDB4MjEyMiwgMHhmYjAxLCAweGZiMDIsIDB4MTQxLCAweDE1MiwgMHgxNjAsIDB4MTc4LCAweDE3ZCwgMHgxMzEsIDB4MTQyLCAweDE1MywgMHgxNjEsIDB4MTdlLCAwLCAweDIwYWNdOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nVG9QREZTdHJpbmcoc3RyKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKHN0clswXSA+PSAiXHhFRiIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVuY29kaW5nOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RyWzBdID09PSAiXHhGRSIgJiYgc3RyWzFdID09PSAiXHhGRiIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuY29kaW5nID0gInV0Zi0xNmJlIjsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdHJbMF0gPT09ICJceEZGIiAmJiBzdHJbMV0gPT09ICJceEZFIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5jb2RpbmcgPSAidXRmLTE2bGUiOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN0clswXSA9PT0gIlx4RUYiICYmIHN0clsxXSA9PT0gIlx4QkIiICYmIHN0clsyXSA9PT0gIlx4QkYiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmNvZGluZyA9ICJ1dGYtOCI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVuY29kaW5nKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoZW5jb2RpbmcsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmF0YWw6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBidWZmZXIgPSBzdHJpbmdUb0J5dGVzKHN0cik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRlY29kZXIuZGVjb2RlKGJ1ZmZlcik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhcm4oYHN0cmluZ1RvUERGU3RyaW5nOiAiJHtleH0iLmApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0ckJ1ZiA9IFtdOwogICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHN0ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvZGUgPSBQREZTdHJpbmdUcmFuc2xhdGVUYWJsZVtzdHIuY2hhckNvZGVBdChpKV07CiAgICAgICAgICAgICAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKGNvZGUgPyBTdHJpbmcuZnJvbUNoYXJDb2RlKGNvZGUpIDogc3RyLmNoYXJBdChpKSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJCdWYuam9pbigiIik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdUb1VURjhTdHJpbmcoc3RyKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChlc2NhcGUoc3RyKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiB1dGY4U3RyaW5nVG9TdHJpbmcoc3RyKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChzdHIpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXlCdWZmZXIodikgewogICAgICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgdiA9PT0gIm9iamVjdCIgJiYgdiAhPT0gbnVsbCAmJiB2LmJ5dGVMZW5ndGggIT09IHVuZGVmaW5lZDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXlFcXVhbChhcnIxLCBhcnIyKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGFycjEubGVuZ3RoICE9PSBhcnIyLmxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGFycjEubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJyMVtpXSAhPT0gYXJyMltpXSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gZ2V0TW9kaWZpY2F0aW9uRGF0ZSgpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgZGF0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbmV3IERhdGUoKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBidWZmZXIgPSBbZGF0ZS5nZXRVVENGdWxsWWVhcigpLnRvU3RyaW5nKCksIChkYXRlLmdldFVUQ01vbnRoKCkgKyAxKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIiksIGRhdGUuZ2V0VVRDRGF0ZSgpLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgIjAiKSwgZGF0ZS5nZXRVVENIb3VycygpLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgIjAiKSwgZGF0ZS5nZXRVVENNaW51dGVzKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAiMCIpLCBkYXRlLmdldFVUQ1NlY29uZHMoKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIildOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBidWZmZXIuam9pbigiIik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVQcm9taXNlQ2FwYWJpbGl0eSgpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjYXBhYmlsaXR5ID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgICAgICAgICAgICBsZXQgaXNTZXR0bGVkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNhcGFiaWxpdHksICJzZXR0bGVkIiwgewogICAgICAgICAgICAgICAgICAgICAgICBnZXQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNTZXR0bGVkOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgY2FwYWJpbGl0eS5wcm9taXNlID0gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXBhYmlsaXR5LnJlc29sdmUgPSBmdW5jdGlvbiAoZGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNTZXR0bGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIGNhcGFiaWxpdHkucmVqZWN0ID0gZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNTZXR0bGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChyZWFzb24pOwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBjYXBhYmlsaXR5OwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAyICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCgogICAgICAgICAgICAgICAgdmFyIF9pc19ub2RlID0gX193X3BkZmpzX3JlcXVpcmVfXygzKTsKICAgICAgICAgICAgICAgIChmdW5jdGlvbiBjaGVja0RPTU1hdHJpeCgpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoZ2xvYmFsVGhpcy5ET01NYXRyaXggfHwgIV9pc19ub2RlLmlzTm9kZUpTKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2xvYmFsVGhpcy5ET01NYXRyaXggPSByZXF1aXJlKCJjYW52YXMiKS5ET01NYXRyaXg7CiAgICAgICAgICAgICAgICB9KSgpOwogICAgICAgICAgICAgICAgKGZ1bmN0aW9uIGNoZWNrUGF0aDJEKCkgewogICAgICAgICAgICAgICAgICAgIGlmIChnbG9iYWxUaGlzLlBhdGgyRCB8fCAhX2lzX25vZGUuaXNOb2RlSlMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgIENhbnZhc1JlbmRlcmluZ0NvbnRleHQyRAogICAgICAgICAgICAgICAgICAgIH0gPSByZXF1aXJlKCJjYW52YXMiKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgIHBvbHlmaWxsUGF0aDJECiAgICAgICAgICAgICAgICAgICAgfSA9IHJlcXVpcmUoInBhdGgyZC1wb2x5ZmlsbCIpOwogICAgICAgICAgICAgICAgICAgIGdsb2JhbFRoaXMuQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEID0gQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEOwogICAgICAgICAgICAgICAgICAgIHBvbHlmaWxsUGF0aDJEKGdsb2JhbFRoaXMpOwogICAgICAgICAgICAgICAgfSkoKTsKICAgICAgICAgICAgICAgIChmdW5jdGlvbiBjaGVja1JlYWRhYmxlU3RyZWFtKCkgewogICAgICAgICAgICAgICAgICAgIGlmIChnbG9iYWxUaGlzLlJlYWRhYmxlU3RyZWFtIHx8ICFfaXNfbm9kZS5pc05vZGVKUykgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdsb2JhbFRoaXMuUmVhZGFibGVTdHJlYW0gPSByZXF1aXJlKCJ3ZWItc3RyZWFtcy1wb2x5ZmlsbC9kaXN0L3BvbnlmaWxsLmpzIikuUmVhZGFibGVTdHJlYW07CiAgICAgICAgICAgICAgICB9KSgpOwogICAgICAgICAgICAgICAgKGZ1bmN0aW9uIGNoZWNrQXJyYXlBdCgpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoQXJyYXkucHJvdG90eXBlLmF0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX193X3BkZmpzX3JlcXVpcmVfXyg0KTsKICAgICAgICAgICAgICAgIH0pKCk7CiAgICAgICAgICAgICAgICAoZnVuY3Rpb24gY2hlY2tUeXBlZEFycmF5QXQoKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKFVpbnQ4QXJyYXkucHJvdG90eXBlLmF0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX193X3BkZmpzX3JlcXVpcmVfXyg3OCk7CiAgICAgICAgICAgICAgICB9KSgpOwogICAgICAgICAgICAgICAgKGZ1bmN0aW9uIGNoZWNrU3RydWN0dXJlZENsb25lKCkgewogICAgICAgICAgICAgICAgICAgIGlmIChnbG9iYWxUaGlzLnN0cnVjdHVyZWRDbG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9fd19wZGZqc19yZXF1aXJlX18oOTApOwogICAgICAgICAgICAgICAgfSkoKTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMyAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLmlzTm9kZUpTID0gdm9pZCAwOwogICAgICAgICAgICAgICAgY29uc3QgaXNOb2RlSlMgPSB0eXBlb2YgcHJvY2VzcyA9PT0gIm9iamVjdCIgJiYgcHJvY2VzcyArICIiID09PSAiW29iamVjdCBwcm9jZXNzXSIgJiYgIXByb2Nlc3MudmVyc2lvbnMubncgJiYgIShwcm9jZXNzLnZlcnNpb25zLmVsZWN0cm9uICYmIHByb2Nlc3MudHlwZSAmJiBwcm9jZXNzLnR5cGUgIT09ICJicm93c2VyIik7CiAgICAgICAgICAgICAgICBleHBvcnRzLmlzTm9kZUpTID0gaXNOb2RlSlM7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDQgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIF9fd19wZGZqc19yZXF1aXJlX18oNSk7CiAgICAgICAgICAgICAgICB2YXIgZW50cnlVbmJpbmQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDc3KTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZW50cnlVbmJpbmQoJ0FycmF5JywgJ2F0Jyk7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDUgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKICAgICAgICAgICAgICAgIHZhciAkID0gX193X3BkZmpzX3JlcXVpcmVfXyg2KTsKICAgICAgICAgICAgICAgIHZhciB0b09iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oNDMpOwogICAgICAgICAgICAgICAgdmFyIGxlbmd0aE9mQXJyYXlMaWtlID0gX193X3BkZmpzX3JlcXVpcmVfXyg2Nyk7CiAgICAgICAgICAgICAgICB2YXIgdG9JbnRlZ2VyT3JJbmZpbml0eSA9IF9fd19wZGZqc19yZXF1aXJlX18oNjUpOwogICAgICAgICAgICAgICAgdmFyIGFkZFRvVW5zY29wYWJsZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDcyKTsKICAgICAgICAgICAgICAgICQoewogICAgICAgICAgICAgICAgICAgIHRhcmdldDogJ0FycmF5JywKICAgICAgICAgICAgICAgICAgICBwcm90bzogdHJ1ZQogICAgICAgICAgICAgICAgfSwgewogICAgICAgICAgICAgICAgICAgIGF0OiBmdW5jdGlvbiBhdChpbmRleCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgTyA9IHRvT2JqZWN0KHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gbGVuZ3RoT2ZBcnJheUxpa2UoTyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZWxhdGl2ZUluZGV4ID0gdG9JbnRlZ2VyT3JJbmZpbml0eShpbmRleCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBrID0gcmVsYXRpdmVJbmRleCA+PSAwID8gcmVsYXRpdmVJbmRleCA6IGxlbiArIHJlbGF0aXZlSW5kZXg7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBrIDwgMCB8fCBrID49IGxlbiA/IHVuZGVmaW5lZCA6IE9ba107CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICBhZGRUb1Vuc2NvcGFibGVzKCdhdCcpOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA2ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgZ2xvYmFsID0gX193X3BkZmpzX3JlcXVpcmVfXyg3KTsKICAgICAgICAgICAgICAgIHZhciBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSAoX193X3BkZmpzX3JlcXVpcmVfXyg4KS5mKTsKICAgICAgICAgICAgICAgIHZhciBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ3KTsKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVCdWlsdEluID0gX193X3BkZmpzX3JlcXVpcmVfXyg1MSk7CiAgICAgICAgICAgICAgICB2YXIgZGVmaW5lR2xvYmFsUHJvcGVydHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQxKTsKICAgICAgICAgICAgICAgIHZhciBjb3B5Q29uc3RydWN0b3JQcm9wZXJ0aWVzID0gX193X3BkZmpzX3JlcXVpcmVfXyg1OSk7CiAgICAgICAgICAgICAgICB2YXIgaXNGb3JjZWQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDcxKTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9wdGlvbnMsIHNvdXJjZSkgewogICAgICAgICAgICAgICAgICAgIHZhciBUQVJHRVQgPSBvcHRpb25zLnRhcmdldDsKICAgICAgICAgICAgICAgICAgICB2YXIgR0xPQkFMID0gb3B0aW9ucy5nbG9iYWw7CiAgICAgICAgICAgICAgICAgICAgdmFyIFNUQVRJQyA9IG9wdGlvbnMuc3RhdDsKICAgICAgICAgICAgICAgICAgICB2YXIgRk9SQ0VELCB0YXJnZXQsIGtleSwgdGFyZ2V0UHJvcGVydHksIHNvdXJjZVByb3BlcnR5LCBkZXNjcmlwdG9yOwogICAgICAgICAgICAgICAgICAgIGlmIChHTE9CQUwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0ID0gZ2xvYmFsOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoU1RBVElDKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldCA9IGdsb2JhbFtUQVJHRVRdIHx8IGRlZmluZUdsb2JhbFByb3BlcnR5KFRBUkdFVCwge30pOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldCA9IChnbG9iYWxbVEFSR0VUXSB8fCB7fSkucHJvdG90eXBlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAodGFyZ2V0KQogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGtleSBpbiBzb3VyY2UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZVByb3BlcnR5ID0gc291cmNlW2tleV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5kb250Q2FsbEdldFNldCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0b3IgPSBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldFByb3BlcnR5ID0gZGVzY3JpcHRvciAmJiBkZXNjcmlwdG9yLnZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0UHJvcGVydHkgPSB0YXJnZXRba2V5XTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZPUkNFRCA9IGlzRm9yY2VkKEdMT0JBTCA/IGtleSA6IFRBUkdFVCArIChTVEFUSUMgPyAnLicgOiAnIycpICsga2V5LCBvcHRpb25zLmZvcmNlZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUZPUkNFRCAmJiB0YXJnZXRQcm9wZXJ0eSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzb3VyY2VQcm9wZXJ0eSA9PSB0eXBlb2YgdGFyZ2V0UHJvcGVydHkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcHlDb25zdHJ1Y3RvclByb3BlcnRpZXMoc291cmNlUHJvcGVydHksIHRhcmdldFByb3BlcnR5KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnNoYW0gfHwgdGFyZ2V0UHJvcGVydHkgJiYgdGFyZ2V0UHJvcGVydHkuc2hhbSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShzb3VyY2VQcm9wZXJ0eSwgJ3NoYW0nLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmluZUJ1aWx0SW4odGFyZ2V0LCBrZXksIHNvdXJjZVByb3BlcnR5LCBvcHRpb25zKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNyAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSkgPT4gewoKICAgICAgICAgICAgICAgIHZhciBjaGVjayA9IGZ1bmN0aW9uIChpdCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBpdCAmJiBpdC5NYXRoID09IE1hdGggJiYgaXQ7CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjaGVjayh0eXBlb2YgZ2xvYmFsVGhpcyA9PSAnb2JqZWN0JyAmJiBnbG9iYWxUaGlzKSB8fCBjaGVjayh0eXBlb2Ygd2luZG93ID09ICdvYmplY3QnICYmIHdpbmRvdykgfHwgY2hlY2sodHlwZW9mIHNlbGYgPT0gJ29iamVjdCcgJiYgc2VsZikgfHwgY2hlY2sodHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWwpIHx8IChmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICAgICAgICB9KCkpIHx8IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDggKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBERVNDUklQVE9SUyA9IF9fd19wZGZqc19yZXF1aXJlX18oOSk7CiAgICAgICAgICAgICAgICB2YXIgY2FsbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEpOwogICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5SXNFbnVtZXJhYmxlTW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXygxMyk7CiAgICAgICAgICAgICAgICB2YXIgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXygxNCk7CiAgICAgICAgICAgICAgICB2YXIgdG9JbmRleGVkT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNSk7CiAgICAgICAgICAgICAgICB2YXIgdG9Qcm9wZXJ0eUtleSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjEpOwogICAgICAgICAgICAgICAgdmFyIGhhc093biA9IF9fd19wZGZqc19yZXF1aXJlX18oNDIpOwogICAgICAgICAgICAgICAgdmFyIElFOF9ET01fREVGSU5FID0gX193X3BkZmpzX3JlcXVpcmVfXyg0NSk7CiAgICAgICAgICAgICAgICB2YXIgJGdldE93blByb3BlcnR5RGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7CiAgICAgICAgICAgICAgICBleHBvcnRzLmYgPSBERVNDUklQVE9SUyA/ICRnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgOiBmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoTywgUCkgewogICAgICAgICAgICAgICAgICAgIE8gPSB0b0luZGV4ZWRPYmplY3QoTyk7CiAgICAgICAgICAgICAgICAgICAgUCA9IHRvUHJvcGVydHlLZXkoUCk7CiAgICAgICAgICAgICAgICAgICAgaWYgKElFOF9ET01fREVGSU5FKQogICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoTywgUCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoaGFzT3duKE8sIFApKQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yKCFjYWxsKHByb3BlcnR5SXNFbnVtZXJhYmxlTW9kdWxlLmYsIE8sIFApLCBPW1BdKTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDkgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTApOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAhZmFpbHMoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sIDEsIHsKICAgICAgICAgICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gNzsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0pWzFdICE9IDc7CiAgICAgICAgICAgICAgICB9KTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTAgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUpID0+IHsKCiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChleGVjKSB7CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEhZXhlYygpOwogICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDExICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgTkFUSVZFX0JJTkQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyKTsKICAgICAgICAgICAgICAgIHZhciBjYWxsID0gRnVuY3Rpb24ucHJvdG90eXBlLmNhbGw7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE5BVElWRV9CSU5EID8gY2FsbC5iaW5kKGNhbGwpIDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWxsLmFwcGx5KGNhbGwsIGFyZ3VtZW50cyk7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMiAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGZhaWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMCk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9ICFmYWlscyhmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIHRlc3QgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgfS5iaW5kKCk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB0ZXN0ICE9ICdmdW5jdGlvbicgfHwgdGVzdC5oYXNPd25Qcm9wZXJ0eSgncHJvdG90eXBlJyk7CiAgICAgICAgICAgICAgICB9KTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTMgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCiAgICAgICAgICAgICAgICB2YXIgJHByb3BlcnR5SXNFbnVtZXJhYmxlID0ge30ucHJvcGVydHlJc0VudW1lcmFibGU7CiAgICAgICAgICAgICAgICB2YXIgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcjsKICAgICAgICAgICAgICAgIHZhciBOQVNIT1JOX0JVRyA9IGdldE93blByb3BlcnR5RGVzY3JpcHRvciAmJiAhJHByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwoeyAxOiAyIH0sIDEpOwogICAgICAgICAgICAgICAgZXhwb3J0cy5mID0gTkFTSE9STl9CVUcgPyBmdW5jdGlvbiBwcm9wZXJ0eUlzRW51bWVyYWJsZShWKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIGRlc2NyaXB0b3IgPSBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGhpcywgVik7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEhZGVzY3JpcHRvciAmJiBkZXNjcmlwdG9yLmVudW1lcmFibGU7CiAgICAgICAgICAgICAgICB9IDogJHByb3BlcnR5SXNFbnVtZXJhYmxlOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxNCAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSkgPT4gewoKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGJpdG1hcCwgdmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiAhKGJpdG1hcCAmIDEpLAogICAgICAgICAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6ICEoYml0bWFwICYgMiksCiAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiAhKGJpdG1hcCAmIDQpLAogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdmFsdWUKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTUgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBJbmRleGVkT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNik7CiAgICAgICAgICAgICAgICB2YXIgcmVxdWlyZU9iamVjdENvZXJjaWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTkpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gSW5kZXhlZE9iamVjdChyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKGl0KSk7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxNiAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNyk7CiAgICAgICAgICAgICAgICB2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwKTsKICAgICAgICAgICAgICAgIHZhciBjbGFzc29mID0gX193X3BkZmpzX3JlcXVpcmVfXygxOCk7CiAgICAgICAgICAgICAgICB2YXIgJE9iamVjdCA9IE9iamVjdDsKICAgICAgICAgICAgICAgIHZhciBzcGxpdCA9IHVuY3VycnlUaGlzKCcnLnNwbGl0KTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZmFpbHMoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiAhJE9iamVjdCgneicpLnByb3BlcnR5SXNFbnVtZXJhYmxlKDApOwogICAgICAgICAgICAgICAgfSkgPyBmdW5jdGlvbiAoaXQpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2xhc3NvZihpdCkgPT0gJ1N0cmluZycgPyBzcGxpdChpdCwgJycpIDogJE9iamVjdChpdCk7CiAgICAgICAgICAgICAgICB9IDogJE9iamVjdDsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTcgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBOQVRJVkVfQklORCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTIpOwogICAgICAgICAgICAgICAgdmFyIEZ1bmN0aW9uUHJvdG90eXBlID0gRnVuY3Rpb24ucHJvdG90eXBlOwogICAgICAgICAgICAgICAgdmFyIGNhbGwgPSBGdW5jdGlvblByb3RvdHlwZS5jYWxsOwogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzV2l0aEJpbmQgPSBOQVRJVkVfQklORCAmJiBGdW5jdGlvblByb3RvdHlwZS5iaW5kLmJpbmQoY2FsbCwgY2FsbCk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE5BVElWRV9CSU5EID8gdW5jdXJyeVRoaXNXaXRoQmluZCA6IGZ1bmN0aW9uIChmbikgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWxsLmFwcGx5KGZuLCBhcmd1bWVudHMpOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxOCAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNyk7CiAgICAgICAgICAgICAgICB2YXIgdG9TdHJpbmcgPSB1bmN1cnJ5VGhpcyh7fS50b1N0cmluZyk7CiAgICAgICAgICAgICAgICB2YXIgc3RyaW5nU2xpY2UgPSB1bmN1cnJ5VGhpcygnJy5zbGljZSk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJpbmdTbGljZSh0b1N0cmluZyhpdCksIDgsIC0xKTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDE5ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgaXNOdWxsT3JVbmRlZmluZWQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIwKTsKICAgICAgICAgICAgICAgIHZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoaXNOdWxsT3JVbmRlZmluZWQoaXQpKQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyAkVHlwZUVycm9yKCJDYW4ndCBjYWxsIG1ldGhvZCBvbiAiICsgaXQpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBpdDsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDIwICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlKSA9PiB7CgogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXQgPT09IG51bGwgfHwgaXQgPT09IHVuZGVmaW5lZDsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDIxICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgdG9QcmltaXRpdmUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIyKTsKICAgICAgICAgICAgICAgIHZhciBpc1N5bWJvbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjYpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICB2YXIga2V5ID0gdG9QcmltaXRpdmUoYXJndW1lbnQsICdzdHJpbmcnKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNTeW1ib2woa2V5KSA/IGtleSA6IGtleSArICcnOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMjIgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBjYWxsID0gX193X3BkZmpzX3JlcXVpcmVfXygxMSk7CiAgICAgICAgICAgICAgICB2YXIgaXNPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIzKTsKICAgICAgICAgICAgICAgIHZhciBpc1N5bWJvbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjYpOwogICAgICAgICAgICAgICAgdmFyIGdldE1ldGhvZCA9IF9fd19wZGZqc19yZXF1aXJlX18oMzMpOwogICAgICAgICAgICAgICAgdmFyIG9yZGluYXJ5VG9QcmltaXRpdmUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM2KTsKICAgICAgICAgICAgICAgIHZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM3KTsKICAgICAgICAgICAgICAgIHZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwogICAgICAgICAgICAgICAgdmFyIFRPX1BSSU1JVElWRSA9IHdlbGxLbm93blN5bWJvbCgndG9QcmltaXRpdmUnKTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGlucHV0LCBwcmVmKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChpbnB1dCkgfHwgaXNTeW1ib2woaW5wdXQpKQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5wdXQ7CiAgICAgICAgICAgICAgICAgICAgdmFyIGV4b3RpY1RvUHJpbSA9IGdldE1ldGhvZChpbnB1dCwgVE9fUFJJTUlUSVZFKTsKICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0OwogICAgICAgICAgICAgICAgICAgIGlmIChleG90aWNUb1ByaW0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByZWYgPT09IHVuZGVmaW5lZCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWYgPSAnZGVmYXVsdCc7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGNhbGwoZXhvdGljVG9QcmltLCBpbnB1dCwgcHJlZik7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3QocmVzdWx0KSB8fCBpc1N5bWJvbChyZXN1bHQpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgJFR5cGVFcnJvcigiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChwcmVmID09PSB1bmRlZmluZWQpCiAgICAgICAgICAgICAgICAgICAgICAgIHByZWYgPSAnbnVtYmVyJzsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3JkaW5hcnlUb1ByaW1pdGl2ZShpbnB1dCwgcHJlZik7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAyMyAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI0KTsKICAgICAgICAgICAgICAgIHZhciAkZG9jdW1lbnRBbGwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI1KTsKICAgICAgICAgICAgICAgIHZhciBkb2N1bWVudEFsbCA9ICRkb2N1bWVudEFsbC5hbGw7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9ICRkb2N1bWVudEFsbC5JU19IVE1MRERBID8gZnVuY3Rpb24gKGl0KSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBpdCA9PSAnb2JqZWN0JyA/IGl0ICE9PSBudWxsIDogaXNDYWxsYWJsZShpdCkgfHwgaXQgPT09IGRvY3VtZW50QWxsOwogICAgICAgICAgICAgICAgfSA6IGZ1bmN0aW9uIChpdCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgaXQgPT0gJ29iamVjdCcgPyBpdCAhPT0gbnVsbCA6IGlzQ2FsbGFibGUoaXQpOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMjQgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciAkZG9jdW1lbnRBbGwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI1KTsKICAgICAgICAgICAgICAgIHZhciBkb2N1bWVudEFsbCA9ICRkb2N1bWVudEFsbC5hbGw7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9ICRkb2N1bWVudEFsbC5JU19IVE1MRERBID8gZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBhcmd1bWVudCA9PSAnZnVuY3Rpb24nIHx8IGFyZ3VtZW50ID09PSBkb2N1bWVudEFsbDsKICAgICAgICAgICAgICAgIH0gOiBmdW5jdGlvbiAoYXJndW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIGFyZ3VtZW50ID09ICdmdW5jdGlvbic7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAyNSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSkgPT4gewoKICAgICAgICAgICAgICAgIHZhciBkb2N1bWVudEFsbCA9IHR5cGVvZiBkb2N1bWVudCA9PSAnb2JqZWN0JyAmJiBkb2N1bWVudC5hbGw7CiAgICAgICAgICAgICAgICB2YXIgSVNfSFRNTEREQSA9IHR5cGVvZiBkb2N1bWVudEFsbCA9PSAndW5kZWZpbmVkJyAmJiBkb2N1bWVudEFsbCAhPT0gdW5kZWZpbmVkOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7CiAgICAgICAgICAgICAgICAgICAgYWxsOiBkb2N1bWVudEFsbCwKICAgICAgICAgICAgICAgICAgICBJU19IVE1MRERBOiBJU19IVE1MRERBCiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAyNiAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGdldEJ1aWx0SW4gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI3KTsKICAgICAgICAgICAgICAgIHZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNCk7CiAgICAgICAgICAgICAgICB2YXIgaXNQcm90b3R5cGVPZiA9IF9fd19wZGZqc19yZXF1aXJlX18oMjgpOwogICAgICAgICAgICAgICAgdmFyIFVTRV9TWU1CT0xfQVNfVUlEID0gX193X3BkZmpzX3JlcXVpcmVfXygyOSk7CiAgICAgICAgICAgICAgICB2YXIgJE9iamVjdCA9IE9iamVjdDsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVVNFX1NZTUJPTF9BU19VSUQgPyBmdW5jdGlvbiAoaXQpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIGl0ID09ICdzeW1ib2wnOwogICAgICAgICAgICAgICAgfSA6IGZ1bmN0aW9uIChpdCkgewogICAgICAgICAgICAgICAgICAgIHZhciAkU3ltYm9sID0gZ2V0QnVpbHRJbignU3ltYm9sJyk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlzQ2FsbGFibGUoJFN5bWJvbCkgJiYgaXNQcm90b3R5cGVPZigkU3ltYm9sLnByb3RvdHlwZSwgJE9iamVjdChpdCkpOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMjcgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBnbG9iYWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDcpOwogICAgICAgICAgICAgICAgdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI0KTsKICAgICAgICAgICAgICAgIHZhciBhRnVuY3Rpb24gPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNDYWxsYWJsZShhcmd1bWVudCkgPyBhcmd1bWVudCA6IHVuZGVmaW5lZDsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChuYW1lc3BhY2UsIG1ldGhvZCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoIDwgMiA/IGFGdW5jdGlvbihnbG9iYWxbbmFtZXNwYWNlXSkgOiBnbG9iYWxbbmFtZXNwYWNlXSAmJiBnbG9iYWxbbmFtZXNwYWNlXVttZXRob2RdOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMjggKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTcpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB1bmN1cnJ5VGhpcyh7fS5pc1Byb3RvdHlwZU9mKTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMjkgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBOQVRJVkVfU1lNQk9MID0gX193X3BkZmpzX3JlcXVpcmVfXygzMCk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE5BVElWRV9TWU1CT0wgJiYgIVN5bWJvbC5zaGFtICYmIHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPT0gJ3N5bWJvbCc7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDMwICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgVjhfVkVSU0lPTiA9IF9fd19wZGZqc19yZXF1aXJlX18oMzEpOwogICAgICAgICAgICAgICAgdmFyIGZhaWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMCk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9ICEhT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyAmJiAhZmFpbHMoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHZhciBzeW1ib2wgPSBTeW1ib2woKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gIVN0cmluZyhzeW1ib2wpIHx8ICEoT2JqZWN0KHN5bWJvbCkgaW5zdGFuY2VvZiBTeW1ib2wpIHx8ICFTeW1ib2wuc2hhbSAmJiBWOF9WRVJTSU9OICYmIFY4X1ZFUlNJT04gPCA0MTsKICAgICAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAzMSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGdsb2JhbCA9IF9fd19wZGZqc19yZXF1aXJlX18oNyk7CiAgICAgICAgICAgICAgICB2YXIgdXNlckFnZW50ID0gX193X3BkZmpzX3JlcXVpcmVfXygzMik7CiAgICAgICAgICAgICAgICB2YXIgcHJvY2VzcyA9IGdsb2JhbC5wcm9jZXNzOwogICAgICAgICAgICAgICAgdmFyIERlbm8gPSBnbG9iYWwuRGVubzsKICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9ucyA9IHByb2Nlc3MgJiYgcHJvY2Vzcy52ZXJzaW9ucyB8fCBEZW5vICYmIERlbm8udmVyc2lvbjsKICAgICAgICAgICAgICAgIHZhciB2OCA9IHZlcnNpb25zICYmIHZlcnNpb25zLnY4OwogICAgICAgICAgICAgICAgdmFyIG1hdGNoLCB2ZXJzaW9uOwogICAgICAgICAgICAgICAgaWYgKHY4KSB7CiAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSB2OC5zcGxpdCgnLicpOwogICAgICAgICAgICAgICAgICAgIHZlcnNpb24gPSBtYXRjaFswXSA+IDAgJiYgbWF0Y2hbMF0gPCA0ID8gMSA6ICsobWF0Y2hbMF0gKyBtYXRjaFsxXSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoIXZlcnNpb24gJiYgdXNlckFnZW50KSB7CiAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSB1c2VyQWdlbnQubWF0Y2goL0VkZ2VcLyhcZCspLyk7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFtYXRjaCB8fCBtYXRjaFsxXSA+PSA3NCkgewogICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCA9IHVzZXJBZ2VudC5tYXRjaCgvQ2hyb21lXC8oXGQrKS8pOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uID0gK21hdGNoWzFdOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdmVyc2lvbjsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMzIgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUpID0+IHsKCiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHR5cGVvZiBuYXZpZ2F0b3IgIT0gJ3VuZGVmaW5lZCcgJiYgU3RyaW5nKG5hdmlnYXRvci51c2VyQWdlbnQpIHx8ICcnOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAzMyAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGFDYWxsYWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMzQpOwogICAgICAgICAgICAgICAgdmFyIGlzTnVsbE9yVW5kZWZpbmVkID0gX193X3BkZmpzX3JlcXVpcmVfXygyMCk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChWLCBQKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBWW1BdOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBpc051bGxPclVuZGVmaW5lZChmdW5jKSA/IHVuZGVmaW5lZCA6IGFDYWxsYWJsZShmdW5jKTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDM0ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgaXNDYWxsYWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjQpOwogICAgICAgICAgICAgICAgdmFyIHRyeVRvU3RyaW5nID0gX193X3BkZmpzX3JlcXVpcmVfXygzNSk7CiAgICAgICAgICAgICAgICB2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQ2FsbGFibGUoYXJndW1lbnQpKQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXJndW1lbnQ7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgJFR5cGVFcnJvcih0cnlUb1N0cmluZyhhcmd1bWVudCkgKyAnIGlzIG5vdCBhIGZ1bmN0aW9uJyk7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAzNSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSkgPT4gewoKICAgICAgICAgICAgICAgIHZhciAkU3RyaW5nID0gU3RyaW5nOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJFN0cmluZyhhcmd1bWVudCk7CiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdPYmplY3QnOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDM2ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgY2FsbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEpOwogICAgICAgICAgICAgICAgdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI0KTsKICAgICAgICAgICAgICAgIHZhciBpc09iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjMpOwogICAgICAgICAgICAgICAgdmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpbnB1dCwgcHJlZikgewogICAgICAgICAgICAgICAgICAgIHZhciBmbiwgdmFsOwogICAgICAgICAgICAgICAgICAgIGlmIChwcmVmID09PSAnc3RyaW5nJyAmJiBpc0NhbGxhYmxlKGZuID0gaW5wdXQudG9TdHJpbmcpICYmICFpc09iamVjdCh2YWwgPSBjYWxsKGZuLCBpbnB1dCkpKQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsOwogICAgICAgICAgICAgICAgICAgIGlmIChpc0NhbGxhYmxlKGZuID0gaW5wdXQudmFsdWVPZikgJiYgIWlzT2JqZWN0KHZhbCA9IGNhbGwoZm4sIGlucHV0KSkpCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWw7CiAgICAgICAgICAgICAgICAgICAgaWYgKHByZWYgIT09ICdzdHJpbmcnICYmIGlzQ2FsbGFibGUoZm4gPSBpbnB1dC50b1N0cmluZykgJiYgIWlzT2JqZWN0KHZhbCA9IGNhbGwoZm4sIGlucHV0KSkpCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWw7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgJFR5cGVFcnJvcigiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlIik7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAzNyAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGdsb2JhbCA9IF9fd19wZGZqc19yZXF1aXJlX18oNyk7CiAgICAgICAgICAgICAgICB2YXIgc2hhcmVkID0gX193X3BkZmpzX3JlcXVpcmVfXygzOCk7CiAgICAgICAgICAgICAgICB2YXIgaGFzT3duID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Mik7CiAgICAgICAgICAgICAgICB2YXIgdWlkID0gX193X3BkZmpzX3JlcXVpcmVfXyg0NCk7CiAgICAgICAgICAgICAgICB2YXIgTkFUSVZFX1NZTUJPTCA9IF9fd19wZGZqc19yZXF1aXJlX18oMzApOwogICAgICAgICAgICAgICAgdmFyIFVTRV9TWU1CT0xfQVNfVUlEID0gX193X3BkZmpzX3JlcXVpcmVfXygyOSk7CiAgICAgICAgICAgICAgICB2YXIgU3ltYm9sID0gZ2xvYmFsLlN5bWJvbDsKICAgICAgICAgICAgICAgIHZhciBXZWxsS25vd25TeW1ib2xzU3RvcmUgPSBzaGFyZWQoJ3drcycpOwogICAgICAgICAgICAgICAgdmFyIGNyZWF0ZVdlbGxLbm93blN5bWJvbCA9IFVTRV9TWU1CT0xfQVNfVUlEID8gU3ltYm9sWydmb3InXSB8fCBTeW1ib2wgOiBTeW1ib2wgJiYgU3ltYm9sLndpdGhvdXRTZXR0ZXIgfHwgdWlkOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAobmFtZSkgewogICAgICAgICAgICAgICAgICAgIGlmICghaGFzT3duKFdlbGxLbm93blN5bWJvbHNTdG9yZSwgbmFtZSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgV2VsbEtub3duU3ltYm9sc1N0b3JlW25hbWVdID0gTkFUSVZFX1NZTUJPTCAmJiBoYXNPd24oU3ltYm9sLCBuYW1lKSA/IFN5bWJvbFtuYW1lXSA6IGNyZWF0ZVdlbGxLbm93blN5bWJvbCgnU3ltYm9sLicgKyBuYW1lKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFdlbGxLbm93blN5bWJvbHNTdG9yZVtuYW1lXTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDM4ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgSVNfUFVSRSA9IF9fd19wZGZqc19yZXF1aXJlX18oMzkpOwogICAgICAgICAgICAgICAgdmFyIHN0b3JlID0gX193X3BkZmpzX3JlcXVpcmVfXyg0MCk7CiAgICAgICAgICAgICAgICAobW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBzdG9yZVtrZXldIHx8IChzdG9yZVtrZXldID0gdmFsdWUgIT09IHVuZGVmaW5lZCA/IHZhbHVlIDoge30pOwogICAgICAgICAgICAgICAgfSkoJ3ZlcnNpb25zJywgW10pLnB1c2goewogICAgICAgICAgICAgICAgICAgIHZlcnNpb246ICczLjI5LjEnLAogICAgICAgICAgICAgICAgICAgIG1vZGU6IElTX1BVUkUgPyAncHVyZScgOiAnZ2xvYmFsJywKICAgICAgICAgICAgICAgICAgICBjb3B5cmlnaHQ6ICfCqSAyMDE0LTIwMjMgRGVuaXMgUHVzaGthcmV2ICh6bG9pcm9jay5ydSknLAogICAgICAgICAgICAgICAgICAgIGxpY2Vuc2U6ICdodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9ibG9iL3YzLjI5LjEvTElDRU5TRScsCiAgICAgICAgICAgICAgICAgICAgc291cmNlOiAnaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMnCiAgICAgICAgICAgICAgICB9KTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMzkgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUpID0+IHsKCiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZhbHNlOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA0MCAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGdsb2JhbCA9IF9fd19wZGZqc19yZXF1aXJlX18oNyk7CiAgICAgICAgICAgICAgICB2YXIgZGVmaW5lR2xvYmFsUHJvcGVydHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQxKTsKICAgICAgICAgICAgICAgIHZhciBTSEFSRUQgPSAnX19jb3JlLWpzX3NoYXJlZF9fJzsKICAgICAgICAgICAgICAgIHZhciBzdG9yZSA9IGdsb2JhbFtTSEFSRURdIHx8IGRlZmluZUdsb2JhbFByb3BlcnR5KFNIQVJFRCwge30pOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBzdG9yZTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNDEgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBnbG9iYWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDcpOwogICAgICAgICAgICAgICAgdmFyIGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5OwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmluZVByb3BlcnR5KGdsb2JhbCwga2V5LCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICAgICAgICAgICAgICBnbG9iYWxba2V5XSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA0MiAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNyk7CiAgICAgICAgICAgICAgICB2YXIgdG9PYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQzKTsKICAgICAgICAgICAgICAgIHZhciBoYXNPd25Qcm9wZXJ0eSA9IHVuY3VycnlUaGlzKHt9Lmhhc093blByb3BlcnR5KTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gT2JqZWN0Lmhhc093biB8fCBmdW5jdGlvbiBoYXNPd24oaXQsIGtleSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBoYXNPd25Qcm9wZXJ0eSh0b09iamVjdChpdCksIGtleSk7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA0MyAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHJlcXVpcmVPYmplY3RDb2VyY2libGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE5KTsKICAgICAgICAgICAgICAgIHZhciAkT2JqZWN0ID0gT2JqZWN0OwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gJE9iamVjdChyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKGFyZ3VtZW50KSk7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA0NCAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNyk7CiAgICAgICAgICAgICAgICB2YXIgaWQgPSAwOwogICAgICAgICAgICAgICAgdmFyIHBvc3RmaXggPSBNYXRoLnJhbmRvbSgpOwogICAgICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gdW5jdXJyeVRoaXMoMS4wLnRvU3RyaW5nKTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiAnU3ltYm9sKCcgKyAoa2V5ID09PSB1bmRlZmluZWQgPyAnJyA6IGtleSkgKyAnKV8nICsgdG9TdHJpbmcoKytpZCArIHBvc3RmaXgsIDM2KTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDQ1ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgREVTQ1JJUFRPUlMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDkpOwogICAgICAgICAgICAgICAgdmFyIGZhaWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMCk7CiAgICAgICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IF9fd19wZGZqc19yZXF1aXJlX18oNDYpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAhREVTQ1JJUFRPUlMgJiYgIWZhaWxzKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KGNyZWF0ZUVsZW1lbnQoJ2RpdicpLCAnYScsIHsKICAgICAgICAgICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gNzsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0pLmEgIT0gNzsKICAgICAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA0NiAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGdsb2JhbCA9IF9fd19wZGZqc19yZXF1aXJlX18oNyk7CiAgICAgICAgICAgICAgICB2YXIgaXNPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIzKTsKICAgICAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IGdsb2JhbC5kb2N1bWVudDsKICAgICAgICAgICAgICAgIHZhciBFWElTVFMgPSBpc09iamVjdChkb2N1bWVudCkgJiYgaXNPYmplY3QoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBFWElTVFMgPyBkb2N1bWVudC5jcmVhdGVFbGVtZW50KGl0KSA6IHt9OwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNDcgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBERVNDUklQVE9SUyA9IF9fd19wZGZqc19yZXF1aXJlX18oOSk7CiAgICAgICAgICAgICAgICB2YXIgZGVmaW5lUHJvcGVydHlNb2R1bGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ4KTsKICAgICAgICAgICAgICAgIHZhciBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0KTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gREVTQ1JJUFRPUlMgPyBmdW5jdGlvbiAob2JqZWN0LCBrZXksIHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRlZmluZVByb3BlcnR5TW9kdWxlLmYob2JqZWN0LCBrZXksIGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvcigxLCB2YWx1ZSkpOwogICAgICAgICAgICAgICAgfSA6IGZ1bmN0aW9uIChvYmplY3QsIGtleSwgdmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICBvYmplY3Rba2V5XSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3Q7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA0OCAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIERFU0NSSVBUT1JTID0gX193X3BkZmpzX3JlcXVpcmVfXyg5KTsKICAgICAgICAgICAgICAgIHZhciBJRThfRE9NX0RFRklORSA9IF9fd19wZGZqc19yZXF1aXJlX18oNDUpOwogICAgICAgICAgICAgICAgdmFyIFY4X1BST1RPVFlQRV9ERUZJTkVfQlVHID0gX193X3BkZmpzX3JlcXVpcmVfXyg0OSk7CiAgICAgICAgICAgICAgICB2YXIgYW5PYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDUwKTsKICAgICAgICAgICAgICAgIHZhciB0b1Byb3BlcnR5S2V5ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMSk7CiAgICAgICAgICAgICAgICB2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKICAgICAgICAgICAgICAgIHZhciAkZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7CiAgICAgICAgICAgICAgICB2YXIgJGdldE93blByb3BlcnR5RGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7CiAgICAgICAgICAgICAgICB2YXIgRU5VTUVSQUJMRSA9ICdlbnVtZXJhYmxlJzsKICAgICAgICAgICAgICAgIHZhciBDT05GSUdVUkFCTEUgPSAnY29uZmlndXJhYmxlJzsKICAgICAgICAgICAgICAgIHZhciBXUklUQUJMRSA9ICd3cml0YWJsZSc7CiAgICAgICAgICAgICAgICBleHBvcnRzLmYgPSBERVNDUklQVE9SUyA/IFY4X1BST1RPVFlQRV9ERUZJTkVfQlVHID8gZnVuY3Rpb24gZGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcykgewogICAgICAgICAgICAgICAgICAgIGFuT2JqZWN0KE8pOwogICAgICAgICAgICAgICAgICAgIFAgPSB0b1Byb3BlcnR5S2V5KFApOwogICAgICAgICAgICAgICAgICAgIGFuT2JqZWN0KEF0dHJpYnV0ZXMpOwogICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTyA9PT0gJ2Z1bmN0aW9uJyAmJiBQID09PSAncHJvdG90eXBlJyAmJiAndmFsdWUnIGluIEF0dHJpYnV0ZXMgJiYgV1JJVEFCTEUgaW4gQXR0cmlidXRlcyAmJiAhQXR0cmlidXRlc1tXUklUQUJMRV0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGN1cnJlbnQgPSAkZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE8sIFApOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudCAmJiBjdXJyZW50W1dSSVRBQkxFXSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgT1tQXSA9IEF0dHJpYnV0ZXMudmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdHRyaWJ1dGVzID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogQ09ORklHVVJBQkxFIGluIEF0dHJpYnV0ZXMgPyBBdHRyaWJ1dGVzW0NPTkZJR1VSQUJMRV0gOiBjdXJyZW50W0NPTkZJR1VSQUJMRV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW51bWVyYWJsZTogRU5VTUVSQUJMRSBpbiBBdHRyaWJ1dGVzID8gQXR0cmlidXRlc1tFTlVNRVJBQkxFXSA6IGN1cnJlbnRbRU5VTUVSQUJMRV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IGZhbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiAkZGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcyk7CiAgICAgICAgICAgICAgICB9IDogJGRlZmluZVByb3BlcnR5IDogZnVuY3Rpb24gZGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcykgewogICAgICAgICAgICAgICAgICAgIGFuT2JqZWN0KE8pOwogICAgICAgICAgICAgICAgICAgIFAgPSB0b1Byb3BlcnR5S2V5KFApOwogICAgICAgICAgICAgICAgICAgIGFuT2JqZWN0KEF0dHJpYnV0ZXMpOwogICAgICAgICAgICAgICAgICAgIGlmIChJRThfRE9NX0RFRklORSkKICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAkZGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoJ2dldCcgaW4gQXR0cmlidXRlcyB8fCAnc2V0JyBpbiBBdHRyaWJ1dGVzKQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyAkVHlwZUVycm9yKCdBY2Nlc3NvcnMgbm90IHN1cHBvcnRlZCcpOwogICAgICAgICAgICAgICAgICAgIGlmICgndmFsdWUnIGluIEF0dHJpYnV0ZXMpCiAgICAgICAgICAgICAgICAgICAgICAgIE9bUF0gPSBBdHRyaWJ1dGVzLnZhbHVlOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBPOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNDkgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBERVNDUklQVE9SUyA9IF9fd19wZGZqc19yZXF1aXJlX18oOSk7CiAgICAgICAgICAgICAgICB2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwKTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gREVTQ1JJUFRPUlMgJiYgZmFpbHMoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIH0sICdwcm90b3R5cGUnLCB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiA0MiwKICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IGZhbHNlCiAgICAgICAgICAgICAgICAgICAgfSkucHJvdG90eXBlICE9IDQyOwogICAgICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDUwICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgaXNPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIzKTsKICAgICAgICAgICAgICAgIHZhciAkU3RyaW5nID0gU3RyaW5nOwogICAgICAgICAgICAgICAgdmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCkgewogICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChhcmd1bWVudCkpCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhcmd1bWVudDsKICAgICAgICAgICAgICAgICAgICB0aHJvdyAkVHlwZUVycm9yKCRTdHJpbmcoYXJndW1lbnQpICsgJyBpcyBub3QgYW4gb2JqZWN0Jyk7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA1MSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI0KTsKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVQcm9wZXJ0eU1vZHVsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNDgpOwogICAgICAgICAgICAgICAgdmFyIG1ha2VCdWlsdEluID0gX193X3BkZmpzX3JlcXVpcmVfXyg1Mik7CiAgICAgICAgICAgICAgICB2YXIgZGVmaW5lR2xvYmFsUHJvcGVydHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQxKTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKE8sIGtleSwgdmFsdWUsIG9wdGlvbnMpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIW9wdGlvbnMpCiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTsKICAgICAgICAgICAgICAgICAgICB2YXIgc2ltcGxlID0gb3B0aW9ucy5lbnVtZXJhYmxlOwogICAgICAgICAgICAgICAgICAgIHZhciBuYW1lID0gb3B0aW9ucy5uYW1lICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm5hbWUgOiBrZXk7CiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQ2FsbGFibGUodmFsdWUpKQogICAgICAgICAgICAgICAgICAgICAgICBtYWtlQnVpbHRJbih2YWx1ZSwgbmFtZSwgb3B0aW9ucyk7CiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZ2xvYmFsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW1wbGUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPW2tleV0gPSB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmaW5lR2xvYmFsUHJvcGVydHkoa2V5LCB2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghb3B0aW9ucy51bnNhZmUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIE9ba2V5XTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKE9ba2V5XSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW1wbGUgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW1wbGUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBPW2tleV0gPSB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmaW5lUHJvcGVydHlNb2R1bGUuZihPLCBrZXksIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiAhb3B0aW9ucy5ub25Db25maWd1cmFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6ICFvcHRpb25zLm5vbldyaXRhYmxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE87CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA1MiAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNyk7CiAgICAgICAgICAgICAgICB2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwKTsKICAgICAgICAgICAgICAgIHZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNCk7CiAgICAgICAgICAgICAgICB2YXIgaGFzT3duID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Mik7CiAgICAgICAgICAgICAgICB2YXIgREVTQ1JJUFRPUlMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDkpOwogICAgICAgICAgICAgICAgdmFyIENPTkZJR1VSQUJMRV9GVU5DVElPTl9OQU1FID0gKF9fd19wZGZqc19yZXF1aXJlX18oNTMpLkNPTkZJR1VSQUJMRSk7CiAgICAgICAgICAgICAgICB2YXIgaW5zcGVjdFNvdXJjZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNTQpOwogICAgICAgICAgICAgICAgdmFyIEludGVybmFsU3RhdGVNb2R1bGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDU1KTsKICAgICAgICAgICAgICAgIHZhciBlbmZvcmNlSW50ZXJuYWxTdGF0ZSA9IEludGVybmFsU3RhdGVNb2R1bGUuZW5mb3JjZTsKICAgICAgICAgICAgICAgIHZhciBnZXRJbnRlcm5hbFN0YXRlID0gSW50ZXJuYWxTdGF0ZU1vZHVsZS5nZXQ7CiAgICAgICAgICAgICAgICB2YXIgJFN0cmluZyA9IFN0cmluZzsKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTsKICAgICAgICAgICAgICAgIHZhciBzdHJpbmdTbGljZSA9IHVuY3VycnlUaGlzKCcnLnNsaWNlKTsKICAgICAgICAgICAgICAgIHZhciByZXBsYWNlID0gdW5jdXJyeVRoaXMoJycucmVwbGFjZSk7CiAgICAgICAgICAgICAgICB2YXIgam9pbiA9IHVuY3VycnlUaGlzKFtdLmpvaW4pOwogICAgICAgICAgICAgICAgdmFyIENPTkZJR1VSQUJMRV9MRU5HVEggPSBERVNDUklQVE9SUyAmJiAhZmFpbHMoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBkZWZpbmVQcm9wZXJ0eShmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgfSwgJ2xlbmd0aCcsIHsgdmFsdWU6IDggfSkubGVuZ3RoICE9PSA4OwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB2YXIgVEVNUExBVEUgPSBTdHJpbmcoU3RyaW5nKS5zcGxpdCgnU3RyaW5nJyk7CiAgICAgICAgICAgICAgICB2YXIgbWFrZUJ1aWx0SW4gPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh2YWx1ZSwgbmFtZSwgb3B0aW9ucykgewogICAgICAgICAgICAgICAgICAgIGlmIChzdHJpbmdTbGljZSgkU3RyaW5nKG5hbWUpLCAwLCA3KSA9PT0gJ1N5bWJvbCgnKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAnWycgKyByZXBsYWNlKCRTdHJpbmcobmFtZSksIC9eU3ltYm9sXCgoW14pXSopXCkvLCAnJDEnKSArICddJzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5nZXR0ZXIpCiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAnZ2V0ICcgKyBuYW1lOwogICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zICYmIG9wdGlvbnMuc2V0dGVyKQogICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gJ3NldCAnICsgbmFtZTsKICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc093bih2YWx1ZSwgJ25hbWUnKSB8fCBDT05GSUdVUkFCTEVfRlVOQ1RJT05fTkFNRSAmJiB2YWx1ZS5uYW1lICE9PSBuYW1lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChERVNDUklQVE9SUykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmluZVByb3BlcnR5KHZhbHVlLCAnbmFtZScsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogbmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS5uYW1lID0gbmFtZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKENPTkZJR1VSQUJMRV9MRU5HVEggJiYgb3B0aW9ucyAmJiBoYXNPd24ob3B0aW9ucywgJ2FyaXR5JykgJiYgdmFsdWUubGVuZ3RoICE9PSBvcHRpb25zLmFyaXR5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmluZVByb3BlcnR5KHZhbHVlLCAnbGVuZ3RoJywgeyB2YWx1ZTogb3B0aW9ucy5hcml0eSB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMgJiYgaGFzT3duKG9wdGlvbnMsICdjb25zdHJ1Y3RvcicpICYmIG9wdGlvbnMuY29uc3RydWN0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChERVNDUklQVE9SUykKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZpbmVQcm9wZXJ0eSh2YWx1ZSwgJ3Byb3RvdHlwZScsIHsgd3JpdGFibGU6IGZhbHNlIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLnByb3RvdHlwZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLnByb3RvdHlwZSA9IHVuZGVmaW5lZDsKICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB2YXIgc3RhdGUgPSBlbmZvcmNlSW50ZXJuYWxTdGF0ZSh2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNPd24oc3RhdGUsICdzb3VyY2UnKSkgewogICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5zb3VyY2UgPSBqb2luKFRFTVBMQVRFLCB0eXBlb2YgbmFtZSA9PSAnc3RyaW5nJyA/IG5hbWUgOiAnJyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBGdW5jdGlvbi5wcm90b3R5cGUudG9TdHJpbmcgPSBtYWtlQnVpbHRJbihmdW5jdGlvbiB0b1N0cmluZygpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNDYWxsYWJsZSh0aGlzKSAmJiBnZXRJbnRlcm5hbFN0YXRlKHRoaXMpLnNvdXJjZSB8fCBpbnNwZWN0U291cmNlKHRoaXMpOwogICAgICAgICAgICAgICAgfSwgJ3RvU3RyaW5nJyk7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDUzICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgREVTQ1JJUFRPUlMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDkpOwogICAgICAgICAgICAgICAgdmFyIGhhc093biA9IF9fd19wZGZqc19yZXF1aXJlX18oNDIpOwogICAgICAgICAgICAgICAgdmFyIEZ1bmN0aW9uUHJvdG90eXBlID0gRnVuY3Rpb24ucHJvdG90eXBlOwogICAgICAgICAgICAgICAgdmFyIGdldERlc2NyaXB0b3IgPSBERVNDUklQVE9SUyAmJiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yOwogICAgICAgICAgICAgICAgdmFyIEVYSVNUUyA9IGhhc093bihGdW5jdGlvblByb3RvdHlwZSwgJ25hbWUnKTsKICAgICAgICAgICAgICAgIHZhciBQUk9QRVIgPSBFWElTVFMgJiYgZnVuY3Rpb24gc29tZXRoaW5nKCkgewogICAgICAgICAgICAgICAgfS5uYW1lID09PSAnc29tZXRoaW5nJzsKICAgICAgICAgICAgICAgIHZhciBDT05GSUdVUkFCTEUgPSBFWElTVFMgJiYgKCFERVNDUklQVE9SUyB8fCBERVNDUklQVE9SUyAmJiBnZXREZXNjcmlwdG9yKEZ1bmN0aW9uUHJvdG90eXBlLCAnbmFtZScpLmNvbmZpZ3VyYWJsZSk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHsKICAgICAgICAgICAgICAgICAgICBFWElTVFM6IEVYSVNUUywKICAgICAgICAgICAgICAgICAgICBQUk9QRVI6IFBST1BFUiwKICAgICAgICAgICAgICAgICAgICBDT05GSUdVUkFCTEU6IENPTkZJR1VSQUJMRQogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNTQgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTcpOwogICAgICAgICAgICAgICAgdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI0KTsKICAgICAgICAgICAgICAgIHZhciBzdG9yZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNDApOwogICAgICAgICAgICAgICAgdmFyIGZ1bmN0aW9uVG9TdHJpbmcgPSB1bmN1cnJ5VGhpcyhGdW5jdGlvbi50b1N0cmluZyk7CiAgICAgICAgICAgICAgICBpZiAoIWlzQ2FsbGFibGUoc3RvcmUuaW5zcGVjdFNvdXJjZSkpIHsKICAgICAgICAgICAgICAgICAgICBzdG9yZS5pbnNwZWN0U291cmNlID0gZnVuY3Rpb24gKGl0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvblRvU3RyaW5nKGl0KTsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBzdG9yZS5pbnNwZWN0U291cmNlOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA1NSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIE5BVElWRV9XRUFLX01BUCA9IF9fd19wZGZqc19yZXF1aXJlX18oNTYpOwogICAgICAgICAgICAgICAgdmFyIGdsb2JhbCA9IF9fd19wZGZqc19yZXF1aXJlX18oNyk7CiAgICAgICAgICAgICAgICB2YXIgaXNPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIzKTsKICAgICAgICAgICAgICAgIHZhciBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ3KTsKICAgICAgICAgICAgICAgIHZhciBoYXNPd24gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQyKTsKICAgICAgICAgICAgICAgIHZhciBzaGFyZWQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQwKTsKICAgICAgICAgICAgICAgIHZhciBzaGFyZWRLZXkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDU3KTsKICAgICAgICAgICAgICAgIHZhciBoaWRkZW5LZXlzID0gX193X3BkZmpzX3JlcXVpcmVfXyg1OCk7CiAgICAgICAgICAgICAgICB2YXIgT0JKRUNUX0FMUkVBRFlfSU5JVElBTElaRUQgPSAnT2JqZWN0IGFscmVhZHkgaW5pdGlhbGl6ZWQnOwogICAgICAgICAgICAgICAgdmFyIFR5cGVFcnJvciA9IGdsb2JhbC5UeXBlRXJyb3I7CiAgICAgICAgICAgICAgICB2YXIgV2Vha01hcCA9IGdsb2JhbC5XZWFrTWFwOwogICAgICAgICAgICAgICAgdmFyIHNldCwgZ2V0LCBoYXM7CiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZSA9IGZ1bmN0aW9uIChpdCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBoYXMoaXQpID8gZ2V0KGl0KSA6IHNldChpdCwge30pOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciBnZXR0ZXJGb3IgPSBmdW5jdGlvbiAoVFlQRSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoaXQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHN0YXRlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KGl0KSB8fCAoc3RhdGUgPSBnZXQoaXQpKS50eXBlICE9PSBUWVBFKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoJ0luY29tcGF0aWJsZSByZWNlaXZlciwgJyArIFRZUEUgKyAnIHJlcXVpcmVkJyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0YXRlOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgaWYgKE5BVElWRV9XRUFLX01BUCB8fCBzaGFyZWQuc3RhdGUpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgc3RvcmUgPSBzaGFyZWQuc3RhdGUgfHwgKHNoYXJlZC5zdGF0ZSA9IG5ldyBXZWFrTWFwKCkpOwogICAgICAgICAgICAgICAgICAgIHN0b3JlLmdldCA9IHN0b3JlLmdldDsKICAgICAgICAgICAgICAgICAgICBzdG9yZS5oYXMgPSBzdG9yZS5oYXM7CiAgICAgICAgICAgICAgICAgICAgc3RvcmUuc2V0ID0gc3RvcmUuc2V0OwogICAgICAgICAgICAgICAgICAgIHNldCA9IGZ1bmN0aW9uIChpdCwgbWV0YWRhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0b3JlLmhhcyhpdCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoT0JKRUNUX0FMUkVBRFlfSU5JVElBTElaRUQpOwogICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YS5mYWNhZGUgPSBpdDsKICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmUuc2V0KGl0LCBtZXRhZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtZXRhZGF0YTsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGdldCA9IGZ1bmN0aW9uIChpdCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RvcmUuZ2V0KGl0KSB8fCB7fTsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGhhcyA9IGZ1bmN0aW9uIChpdCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RvcmUuaGFzKGl0KTsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICB2YXIgU1RBVEUgPSBzaGFyZWRLZXkoJ3N0YXRlJyk7CiAgICAgICAgICAgICAgICAgICAgaGlkZGVuS2V5c1tTVEFURV0gPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIHNldCA9IGZ1bmN0aW9uIChpdCwgbWV0YWRhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhhc093bihpdCwgU1RBVEUpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKE9CSkVDVF9BTFJFQURZX0lOSVRJQUxJWkVEKTsKICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEuZmFjYWRlID0gaXQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShpdCwgU1RBVEUsIG1ldGFkYXRhKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1ldGFkYXRhOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgZ2V0ID0gZnVuY3Rpb24gKGl0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBoYXNPd24oaXQsIFNUQVRFKSA/IGl0W1NUQVRFXSA6IHt9OwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgaGFzID0gZnVuY3Rpb24gKGl0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBoYXNPd24oaXQsIFNUQVRFKTsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7CiAgICAgICAgICAgICAgICAgICAgc2V0OiBzZXQsCiAgICAgICAgICAgICAgICAgICAgZ2V0OiBnZXQsCiAgICAgICAgICAgICAgICAgICAgaGFzOiBoYXMsCiAgICAgICAgICAgICAgICAgICAgZW5mb3JjZTogZW5mb3JjZSwKICAgICAgICAgICAgICAgICAgICBnZXR0ZXJGb3I6IGdldHRlckZvcgogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNTYgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBnbG9iYWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDcpOwogICAgICAgICAgICAgICAgdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI0KTsKICAgICAgICAgICAgICAgIHZhciBXZWFrTWFwID0gZ2xvYmFsLldlYWtNYXA7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzQ2FsbGFibGUoV2Vha01hcCkgJiYgL25hdGl2ZSBjb2RlLy50ZXN0KFN0cmluZyhXZWFrTWFwKSk7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDU3ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgc2hhcmVkID0gX193X3BkZmpzX3JlcXVpcmVfXygzOCk7CiAgICAgICAgICAgICAgICB2YXIgdWlkID0gX193X3BkZmpzX3JlcXVpcmVfXyg0NCk7CiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHNoYXJlZCgna2V5cycpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5KSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGtleXNba2V5XSB8fCAoa2V5c1trZXldID0gdWlkKGtleSkpOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNTggKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUpID0+IHsKCiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHt9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA1OSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGhhc093biA9IF9fd19wZGZqc19yZXF1aXJlX18oNDIpOwogICAgICAgICAgICAgICAgdmFyIG93bktleXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDYwKTsKICAgICAgICAgICAgICAgIHZhciBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JNb2R1bGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDgpOwogICAgICAgICAgICAgICAgdmFyIGRlZmluZVByb3BlcnR5TW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXyg0OCk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh0YXJnZXQsIHNvdXJjZSwgZXhjZXB0aW9ucykgewogICAgICAgICAgICAgICAgICAgIHZhciBrZXlzID0gb3duS2V5cyhzb3VyY2UpOwogICAgICAgICAgICAgICAgICAgIHZhciBkZWZpbmVQcm9wZXJ0eSA9IGRlZmluZVByb3BlcnR5TW9kdWxlLmY7CiAgICAgICAgICAgICAgICAgICAgdmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvciA9IGdldE93blByb3BlcnR5RGVzY3JpcHRvck1vZHVsZS5mOwogICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIga2V5ID0ga2V5c1tpXTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNPd24odGFyZ2V0LCBrZXkpICYmICEoZXhjZXB0aW9ucyAmJiBoYXNPd24oZXhjZXB0aW9ucywga2V5KSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Ioc291cmNlLCBrZXkpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDYwICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgZ2V0QnVpbHRJbiA9IF9fd19wZGZqc19yZXF1aXJlX18oMjcpOwogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNyk7CiAgICAgICAgICAgICAgICB2YXIgZ2V0T3duUHJvcGVydHlOYW1lc01vZHVsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNjEpOwogICAgICAgICAgICAgICAgdmFyIGdldE93blByb3BlcnR5U3ltYm9sc01vZHVsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNzApOwogICAgICAgICAgICAgICAgdmFyIGFuT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXyg1MCk7CiAgICAgICAgICAgICAgICB2YXIgY29uY2F0ID0gdW5jdXJyeVRoaXMoW10uY29uY2F0KTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZ2V0QnVpbHRJbignUmVmbGVjdCcsICdvd25LZXlzJykgfHwgZnVuY3Rpb24gb3duS2V5cyhpdCkgewogICAgICAgICAgICAgICAgICAgIHZhciBrZXlzID0gZ2V0T3duUHJvcGVydHlOYW1lc01vZHVsZS5mKGFuT2JqZWN0KGl0KSk7CiAgICAgICAgICAgICAgICAgICAgdmFyIGdldE93blByb3BlcnR5U3ltYm9scyA9IGdldE93blByb3BlcnR5U3ltYm9sc01vZHVsZS5mOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBnZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPyBjb25jYXQoa2V5cywgZ2V0T3duUHJvcGVydHlTeW1ib2xzKGl0KSkgOiBrZXlzOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNjEgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBpbnRlcm5hbE9iamVjdEtleXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDYyKTsKICAgICAgICAgICAgICAgIHZhciBlbnVtQnVnS2V5cyA9IF9fd19wZGZqc19yZXF1aXJlX18oNjkpOwogICAgICAgICAgICAgICAgdmFyIGhpZGRlbktleXMgPSBlbnVtQnVnS2V5cy5jb25jYXQoJ2xlbmd0aCcsICdwcm90b3R5cGUnKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuZiA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzIHx8IGZ1bmN0aW9uIGdldE93blByb3BlcnR5TmFtZXMoTykgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnRlcm5hbE9iamVjdEtleXMoTywgaGlkZGVuS2V5cyk7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA2MiAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNyk7CiAgICAgICAgICAgICAgICB2YXIgaGFzT3duID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Mik7CiAgICAgICAgICAgICAgICB2YXIgdG9JbmRleGVkT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNSk7CiAgICAgICAgICAgICAgICB2YXIgaW5kZXhPZiA9IChfX3dfcGRmanNfcmVxdWlyZV9fKDYzKS5pbmRleE9mKTsKICAgICAgICAgICAgICAgIHZhciBoaWRkZW5LZXlzID0gX193X3BkZmpzX3JlcXVpcmVfXyg1OCk7CiAgICAgICAgICAgICAgICB2YXIgcHVzaCA9IHVuY3VycnlUaGlzKFtdLnB1c2gpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqZWN0LCBuYW1lcykgewogICAgICAgICAgICAgICAgICAgIHZhciBPID0gdG9JbmRleGVkT2JqZWN0KG9iamVjdCk7CiAgICAgICAgICAgICAgICAgICAgdmFyIGkgPSAwOwogICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBbXTsKICAgICAgICAgICAgICAgICAgICB2YXIga2V5OwogICAgICAgICAgICAgICAgICAgIGZvciAoa2V5IGluIE8pCiAgICAgICAgICAgICAgICAgICAgICAgICFoYXNPd24oaGlkZGVuS2V5cywga2V5KSAmJiBoYXNPd24oTywga2V5KSAmJiBwdXNoKHJlc3VsdCwga2V5KTsKICAgICAgICAgICAgICAgICAgICB3aGlsZSAobmFtZXMubGVuZ3RoID4gaSkKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhhc093bihPLCBrZXkgPSBuYW1lc1tpKytdKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgfmluZGV4T2YocmVzdWx0LCBrZXkpIHx8IHB1c2gocmVzdWx0LCBrZXkpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDYzICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgdG9JbmRleGVkT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNSk7CiAgICAgICAgICAgICAgICB2YXIgdG9BYnNvbHV0ZUluZGV4ID0gX193X3BkZmpzX3JlcXVpcmVfXyg2NCk7CiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoT2ZBcnJheUxpa2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDY3KTsKICAgICAgICAgICAgICAgIHZhciBjcmVhdGVNZXRob2QgPSBmdW5jdGlvbiAoSVNfSU5DTFVERVMpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCR0aGlzLCBlbCwgZnJvbUluZGV4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBPID0gdG9JbmRleGVkT2JqZWN0KCR0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGxlbmd0aE9mQXJyYXlMaWtlKE8pOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSB0b0Fic29sdXRlSW5kZXgoZnJvbUluZGV4LCBsZW5ndGgpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChJU19JTkNMVURFUyAmJiBlbCAhPSBlbCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChsZW5ndGggPiBpbmRleCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gT1tpbmRleCsrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgIT0gdmFsdWUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKDsgbGVuZ3RoID4gaW5kZXg7IGluZGV4KyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoKElTX0lOQ0xVREVTIHx8IGluZGV4IGluIE8pICYmIE9baW5kZXhdID09PSBlbCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIElTX0lOQ0xVREVTIHx8IGluZGV4IHx8IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhSVNfSU5DTFVERVMgJiYgLTE7CiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHsKICAgICAgICAgICAgICAgICAgICBpbmNsdWRlczogY3JlYXRlTWV0aG9kKHRydWUpLAogICAgICAgICAgICAgICAgICAgIGluZGV4T2Y6IGNyZWF0ZU1ldGhvZChmYWxzZSkKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDY0ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgdG9JbnRlZ2VyT3JJbmZpbml0eSA9IF9fd19wZGZqc19yZXF1aXJlX18oNjUpOwogICAgICAgICAgICAgICAgdmFyIG1heCA9IE1hdGgubWF4OwogICAgICAgICAgICAgICAgdmFyIG1pbiA9IE1hdGgubWluOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaW5kZXgsIGxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgIHZhciBpbnRlZ2VyID0gdG9JbnRlZ2VyT3JJbmZpbml0eShpbmRleCk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGludGVnZXIgPCAwID8gbWF4KGludGVnZXIgKyBsZW5ndGgsIDApIDogbWluKGludGVnZXIsIGxlbmd0aCk7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA2NSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHRydW5jID0gX193X3BkZmpzX3JlcXVpcmVfXyg2Nik7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCkgewogICAgICAgICAgICAgICAgICAgIHZhciBudW1iZXIgPSArYXJndW1lbnQ7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciAhPT0gbnVtYmVyIHx8IG51bWJlciA9PT0gMCA/IDAgOiB0cnVuYyhudW1iZXIpOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNjYgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUpID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgY2VpbCA9IE1hdGguY2VpbDsKICAgICAgICAgICAgICAgIHZhciBmbG9vciA9IE1hdGguZmxvb3I7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE1hdGgudHJ1bmMgfHwgZnVuY3Rpb24gdHJ1bmMoeCkgewogICAgICAgICAgICAgICAgICAgIHZhciBuID0gK3g7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChuID4gMCA/IGZsb29yIDogY2VpbCkobik7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA2NyAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHRvTGVuZ3RoID0gX193X3BkZmpzX3JlcXVpcmVfXyg2OCk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmopIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdG9MZW5ndGgob2JqLmxlbmd0aCk7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA2OCAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHRvSW50ZWdlck9ySW5maW5pdHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDY1KTsKICAgICAgICAgICAgICAgIHZhciBtaW4gPSBNYXRoLm1pbjsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFyZ3VtZW50ID4gMCA/IG1pbih0b0ludGVnZXJPckluZmluaXR5KGFyZ3VtZW50KSwgMHgxRkZGRkZGRkZGRkZGRikgOiAwOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNjkgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUpID0+IHsKCiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFsKICAgICAgICAgICAgICAgICAgICAnY29uc3RydWN0b3InLAogICAgICAgICAgICAgICAgICAgICdoYXNPd25Qcm9wZXJ0eScsCiAgICAgICAgICAgICAgICAgICAgJ2lzUHJvdG90eXBlT2YnLAogICAgICAgICAgICAgICAgICAgICdwcm9wZXJ0eUlzRW51bWVyYWJsZScsCiAgICAgICAgICAgICAgICAgICAgJ3RvTG9jYWxlU3RyaW5nJywKICAgICAgICAgICAgICAgICAgICAndG9TdHJpbmcnLAogICAgICAgICAgICAgICAgICAgICd2YWx1ZU9mJwogICAgICAgICAgICAgICAgXTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNzAgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cykgPT4gewoKICAgICAgICAgICAgICAgIGV4cG9ydHMuZiA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHM7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDcxICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwKTsKICAgICAgICAgICAgICAgIHZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNCk7CiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZW1lbnQgPSAvI3xcLnByb3RvdHlwZVwuLzsKICAgICAgICAgICAgICAgIHZhciBpc0ZvcmNlZCA9IGZ1bmN0aW9uIChmZWF0dXJlLCBkZXRlY3Rpb24pIHsKICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBkYXRhW25vcm1hbGl6ZShmZWF0dXJlKV07CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlID09IFBPTFlGSUxMID8gdHJ1ZSA6IHZhbHVlID09IE5BVElWRSA/IGZhbHNlIDogaXNDYWxsYWJsZShkZXRlY3Rpb24pID8gZmFpbHMoZGV0ZWN0aW9uKSA6ICEhZGV0ZWN0aW9uOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciBub3JtYWxpemUgPSBpc0ZvcmNlZC5ub3JtYWxpemUgPSBmdW5jdGlvbiAoc3RyaW5nKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UocmVwbGFjZW1lbnQsICcuJykudG9Mb3dlckNhc2UoKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB2YXIgZGF0YSA9IGlzRm9yY2VkLmRhdGEgPSB7fTsKICAgICAgICAgICAgICAgIHZhciBOQVRJVkUgPSBpc0ZvcmNlZC5OQVRJVkUgPSAnTic7CiAgICAgICAgICAgICAgICB2YXIgUE9MWUZJTEwgPSBpc0ZvcmNlZC5QT0xZRklMTCA9ICdQJzsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNGb3JjZWQ7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDcyICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgd2VsbEtub3duU3ltYm9sID0gX193X3BkZmpzX3JlcXVpcmVfXygzNyk7CiAgICAgICAgICAgICAgICB2YXIgY3JlYXRlID0gX193X3BkZmpzX3JlcXVpcmVfXyg3Myk7CiAgICAgICAgICAgICAgICB2YXIgZGVmaW5lUHJvcGVydHkgPSAoX193X3BkZmpzX3JlcXVpcmVfXyg0OCkuZik7CiAgICAgICAgICAgICAgICB2YXIgVU5TQ09QQUJMRVMgPSB3ZWxsS25vd25TeW1ib2woJ3Vuc2NvcGFibGVzJyk7CiAgICAgICAgICAgICAgICB2YXIgQXJyYXlQcm90b3R5cGUgPSBBcnJheS5wcm90b3R5cGU7CiAgICAgICAgICAgICAgICBpZiAoQXJyYXlQcm90b3R5cGVbVU5TQ09QQUJMRVNdID09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgICAgIGRlZmluZVByb3BlcnR5KEFycmF5UHJvdG90eXBlLCBVTlNDT1BBQkxFUywgewogICAgICAgICAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBjcmVhdGUobnVsbCkKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgICAgICAgICAgIEFycmF5UHJvdG90eXBlW1VOU0NPUEFCTEVTXVtrZXldID0gdHJ1ZTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDczICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgYW5PYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDUwKTsKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVQcm9wZXJ0aWVzTW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXyg3NCk7CiAgICAgICAgICAgICAgICB2YXIgZW51bUJ1Z0tleXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDY5KTsKICAgICAgICAgICAgICAgIHZhciBoaWRkZW5LZXlzID0gX193X3BkZmpzX3JlcXVpcmVfXyg1OCk7CiAgICAgICAgICAgICAgICB2YXIgaHRtbCA9IF9fd19wZGZqc19yZXF1aXJlX18oNzYpOwogICAgICAgICAgICAgICAgdmFyIGRvY3VtZW50Q3JlYXRlRWxlbWVudCA9IF9fd19wZGZqc19yZXF1aXJlX18oNDYpOwogICAgICAgICAgICAgICAgdmFyIHNoYXJlZEtleSA9IF9fd19wZGZqc19yZXF1aXJlX18oNTcpOwogICAgICAgICAgICAgICAgdmFyIEdUID0gJz4nOwogICAgICAgICAgICAgICAgdmFyIExUID0gJzwnOwogICAgICAgICAgICAgICAgdmFyIFBST1RPVFlQRSA9ICdwcm90b3R5cGUnOwogICAgICAgICAgICAgICAgdmFyIFNDUklQVCA9ICdzY3JpcHQnOwogICAgICAgICAgICAgICAgdmFyIElFX1BST1RPID0gc2hhcmVkS2V5KCdJRV9QUk9UTycpOwogICAgICAgICAgICAgICAgdmFyIEVtcHR5Q29uc3RydWN0b3IgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgdmFyIHNjcmlwdFRhZyA9IGZ1bmN0aW9uIChjb250ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIExUICsgU0NSSVBUICsgR1QgKyBjb250ZW50ICsgTFQgKyAnLycgKyBTQ1JJUFQgKyBHVDsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB2YXIgTnVsbFByb3RvT2JqZWN0VmlhQWN0aXZlWCA9IGZ1bmN0aW9uIChhY3RpdmVYRG9jdW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICBhY3RpdmVYRG9jdW1lbnQud3JpdGUoc2NyaXB0VGFnKCcnKSk7CiAgICAgICAgICAgICAgICAgICAgYWN0aXZlWERvY3VtZW50LmNsb3NlKCk7CiAgICAgICAgICAgICAgICAgICAgdmFyIHRlbXAgPSBhY3RpdmVYRG9jdW1lbnQucGFyZW50V2luZG93Lk9iamVjdDsKICAgICAgICAgICAgICAgICAgICBhY3RpdmVYRG9jdW1lbnQgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIHJldHVybiB0ZW1wOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciBOdWxsUHJvdG9PYmplY3RWaWFJRnJhbWUgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIGlmcmFtZSA9IGRvY3VtZW50Q3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7CiAgICAgICAgICAgICAgICAgICAgdmFyIEpTID0gJ2phdmEnICsgU0NSSVBUICsgJzonOwogICAgICAgICAgICAgICAgICAgIHZhciBpZnJhbWVEb2N1bWVudDsKICAgICAgICAgICAgICAgICAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJzsKICAgICAgICAgICAgICAgICAgICBodG1sLmFwcGVuZENoaWxkKGlmcmFtZSk7CiAgICAgICAgICAgICAgICAgICAgaWZyYW1lLnNyYyA9IFN0cmluZyhKUyk7CiAgICAgICAgICAgICAgICAgICAgaWZyYW1lRG9jdW1lbnQgPSBpZnJhbWUuY29udGVudFdpbmRvdy5kb2N1bWVudDsKICAgICAgICAgICAgICAgICAgICBpZnJhbWVEb2N1bWVudC5vcGVuKCk7CiAgICAgICAgICAgICAgICAgICAgaWZyYW1lRG9jdW1lbnQud3JpdGUoc2NyaXB0VGFnKCdkb2N1bWVudC5GPU9iamVjdCcpKTsKICAgICAgICAgICAgICAgICAgICBpZnJhbWVEb2N1bWVudC5jbG9zZSgpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBpZnJhbWVEb2N1bWVudC5GOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciBhY3RpdmVYRG9jdW1lbnQ7CiAgICAgICAgICAgICAgICB2YXIgTnVsbFByb3RvT2JqZWN0ID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGl2ZVhEb2N1bWVudCA9IG5ldyBBY3RpdmVYT2JqZWN0KCdodG1sZmlsZScpOwogICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIE51bGxQcm90b09iamVjdCA9IHR5cGVvZiBkb2N1bWVudCAhPSAndW5kZWZpbmVkJyA/IGRvY3VtZW50LmRvbWFpbiAmJiBhY3RpdmVYRG9jdW1lbnQgPyBOdWxsUHJvdG9PYmplY3RWaWFBY3RpdmVYKGFjdGl2ZVhEb2N1bWVudCkgOiBOdWxsUHJvdG9PYmplY3RWaWFJRnJhbWUoKSA6IE51bGxQcm90b09iamVjdFZpYUFjdGl2ZVgoYWN0aXZlWERvY3VtZW50KTsKICAgICAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gZW51bUJ1Z0tleXMubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIHdoaWxlIChsZW5ndGgtLSkKICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIE51bGxQcm90b09iamVjdFtQUk9UT1RZUEVdW2VudW1CdWdLZXlzW2xlbmd0aF1dOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBOdWxsUHJvdG9PYmplY3QoKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBoaWRkZW5LZXlzW0lFX1BST1RPXSA9IHRydWU7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5jcmVhdGUgfHwgZnVuY3Rpb24gY3JlYXRlKE8sIFByb3BlcnRpZXMpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0OwogICAgICAgICAgICAgICAgICAgIGlmIChPICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIEVtcHR5Q29uc3RydWN0b3JbUFJPVE9UWVBFXSA9IGFuT2JqZWN0KE8pOwogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBuZXcgRW1wdHlDb25zdHJ1Y3RvcigpOwogICAgICAgICAgICAgICAgICAgICAgICBFbXB0eUNvbnN0cnVjdG9yW1BST1RPVFlQRV0gPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRbSUVfUFJPVE9dID0gTzsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gTnVsbFByb3RvT2JqZWN0KCk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFByb3BlcnRpZXMgPT09IHVuZGVmaW5lZCA/IHJlc3VsdCA6IGRlZmluZVByb3BlcnRpZXNNb2R1bGUuZihyZXN1bHQsIFByb3BlcnRpZXMpOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNzQgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBERVNDUklQVE9SUyA9IF9fd19wZGZqc19yZXF1aXJlX18oOSk7CiAgICAgICAgICAgICAgICB2YXIgVjhfUFJPVE9UWVBFX0RFRklORV9CVUcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ5KTsKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVQcm9wZXJ0eU1vZHVsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNDgpOwogICAgICAgICAgICAgICAgdmFyIGFuT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXyg1MCk7CiAgICAgICAgICAgICAgICB2YXIgdG9JbmRleGVkT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNSk7CiAgICAgICAgICAgICAgICB2YXIgb2JqZWN0S2V5cyA9IF9fd19wZGZqc19yZXF1aXJlX18oNzUpOwogICAgICAgICAgICAgICAgZXhwb3J0cy5mID0gREVTQ1JJUFRPUlMgJiYgIVY4X1BST1RPVFlQRV9ERUZJTkVfQlVHID8gT2JqZWN0LmRlZmluZVByb3BlcnRpZXMgOiBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKE8sIFByb3BlcnRpZXMpIHsKICAgICAgICAgICAgICAgICAgICBhbk9iamVjdChPKTsKICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHMgPSB0b0luZGV4ZWRPYmplY3QoUHJvcGVydGllcyk7CiAgICAgICAgICAgICAgICAgICAgdmFyIGtleXMgPSBvYmplY3RLZXlzKFByb3BlcnRpZXMpOwogICAgICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSAwOwogICAgICAgICAgICAgICAgICAgIHZhciBrZXk7CiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGxlbmd0aCA+IGluZGV4KQogICAgICAgICAgICAgICAgICAgICAgICBkZWZpbmVQcm9wZXJ0eU1vZHVsZS5mKE8sIGtleSA9IGtleXNbaW5kZXgrK10sIHByb3BzW2tleV0pOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBPOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNzUgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBpbnRlcm5hbE9iamVjdEtleXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDYyKTsKICAgICAgICAgICAgICAgIHZhciBlbnVtQnVnS2V5cyA9IF9fd19wZGZqc19yZXF1aXJlX18oNjkpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPYmplY3Qua2V5cyB8fCBmdW5jdGlvbiBrZXlzKE8pIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW50ZXJuYWxPYmplY3RLZXlzKE8sIGVudW1CdWdLZXlzKTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDc2ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgZ2V0QnVpbHRJbiA9IF9fd19wZGZqc19yZXF1aXJlX18oMjcpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBnZXRCdWlsdEluKCdkb2N1bWVudCcsICdkb2N1bWVudEVsZW1lbnQnKTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNzcgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBnbG9iYWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDcpOwogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNyk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChDT05TVFJVQ1RPUiwgTUVUSE9EKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHVuY3VycnlUaGlzKGdsb2JhbFtDT05TVFJVQ1RPUl0ucHJvdG90eXBlW01FVEhPRF0pOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogNzggKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgX193X3BkZmpzX3JlcXVpcmVfXyg3OSk7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDc5ICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCiAgICAgICAgICAgICAgICB2YXIgQXJyYXlCdWZmZXJWaWV3Q29yZSA9IF9fd19wZGZqc19yZXF1aXJlX18oODApOwogICAgICAgICAgICAgICAgdmFyIGxlbmd0aE9mQXJyYXlMaWtlID0gX193X3BkZmpzX3JlcXVpcmVfXyg2Nyk7CiAgICAgICAgICAgICAgICB2YXIgdG9JbnRlZ2VyT3JJbmZpbml0eSA9IF9fd19wZGZqc19yZXF1aXJlX18oNjUpOwogICAgICAgICAgICAgICAgdmFyIGFUeXBlZEFycmF5ID0gQXJyYXlCdWZmZXJWaWV3Q29yZS5hVHlwZWRBcnJheTsKICAgICAgICAgICAgICAgIHZhciBleHBvcnRUeXBlZEFycmF5TWV0aG9kID0gQXJyYXlCdWZmZXJWaWV3Q29yZS5leHBvcnRUeXBlZEFycmF5TWV0aG9kOwogICAgICAgICAgICAgICAgZXhwb3J0VHlwZWRBcnJheU1ldGhvZCgnYXQnLCBmdW5jdGlvbiBhdChpbmRleCkgewogICAgICAgICAgICAgICAgICAgIHZhciBPID0gYVR5cGVkQXJyYXkodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGxlbmd0aE9mQXJyYXlMaWtlKE8pOwogICAgICAgICAgICAgICAgICAgIHZhciByZWxhdGl2ZUluZGV4ID0gdG9JbnRlZ2VyT3JJbmZpbml0eShpbmRleCk7CiAgICAgICAgICAgICAgICAgICAgdmFyIGsgPSByZWxhdGl2ZUluZGV4ID49IDAgPyByZWxhdGl2ZUluZGV4IDogbGVuICsgcmVsYXRpdmVJbmRleDsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gayA8IDAgfHwgayA+PSBsZW4gPyB1bmRlZmluZWQgOiBPW2tdOwogICAgICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDgwICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgogICAgICAgICAgICAgICAgdmFyIE5BVElWRV9BUlJBWV9CVUZGRVIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDgxKTsKICAgICAgICAgICAgICAgIHZhciBERVNDUklQVE9SUyA9IF9fd19wZGZqc19yZXF1aXJlX18oOSk7CiAgICAgICAgICAgICAgICB2YXIgZ2xvYmFsID0gX193X3BkZmpzX3JlcXVpcmVfXyg3KTsKICAgICAgICAgICAgICAgIHZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNCk7CiAgICAgICAgICAgICAgICB2YXIgaXNPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIzKTsKICAgICAgICAgICAgICAgIHZhciBoYXNPd24gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQyKTsKICAgICAgICAgICAgICAgIHZhciBjbGFzc29mID0gX193X3BkZmpzX3JlcXVpcmVfXyg4Mik7CiAgICAgICAgICAgICAgICB2YXIgdHJ5VG9TdHJpbmcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM1KTsKICAgICAgICAgICAgICAgIHZhciBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ3KTsKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVCdWlsdEluID0gX193X3BkZmpzX3JlcXVpcmVfXyg1MSk7CiAgICAgICAgICAgICAgICB2YXIgZGVmaW5lQnVpbHRJbkFjY2Vzc29yID0gX193X3BkZmpzX3JlcXVpcmVfXyg4NCk7CiAgICAgICAgICAgICAgICB2YXIgaXNQcm90b3R5cGVPZiA9IF9fd19wZGZqc19yZXF1aXJlX18oMjgpOwogICAgICAgICAgICAgICAgdmFyIGdldFByb3RvdHlwZU9mID0gX193X3BkZmpzX3JlcXVpcmVfXyg4NSk7CiAgICAgICAgICAgICAgICB2YXIgc2V0UHJvdG90eXBlT2YgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDg3KTsKICAgICAgICAgICAgICAgIHZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM3KTsKICAgICAgICAgICAgICAgIHZhciB1aWQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ0KTsKICAgICAgICAgICAgICAgIHZhciBJbnRlcm5hbFN0YXRlTW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXyg1NSk7CiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUludGVybmFsU3RhdGUgPSBJbnRlcm5hbFN0YXRlTW9kdWxlLmVuZm9yY2U7CiAgICAgICAgICAgICAgICB2YXIgZ2V0SW50ZXJuYWxTdGF0ZSA9IEludGVybmFsU3RhdGVNb2R1bGUuZ2V0OwogICAgICAgICAgICAgICAgdmFyIEludDhBcnJheSA9IGdsb2JhbC5JbnQ4QXJyYXk7CiAgICAgICAgICAgICAgICB2YXIgSW50OEFycmF5UHJvdG90eXBlID0gSW50OEFycmF5ICYmIEludDhBcnJheS5wcm90b3R5cGU7CiAgICAgICAgICAgICAgICB2YXIgVWludDhDbGFtcGVkQXJyYXkgPSBnbG9iYWwuVWludDhDbGFtcGVkQXJyYXk7CiAgICAgICAgICAgICAgICB2YXIgVWludDhDbGFtcGVkQXJyYXlQcm90b3R5cGUgPSBVaW50OENsYW1wZWRBcnJheSAmJiBVaW50OENsYW1wZWRBcnJheS5wcm90b3R5cGU7CiAgICAgICAgICAgICAgICB2YXIgVHlwZWRBcnJheSA9IEludDhBcnJheSAmJiBnZXRQcm90b3R5cGVPZihJbnQ4QXJyYXkpOwogICAgICAgICAgICAgICAgdmFyIFR5cGVkQXJyYXlQcm90b3R5cGUgPSBJbnQ4QXJyYXlQcm90b3R5cGUgJiYgZ2V0UHJvdG90eXBlT2YoSW50OEFycmF5UHJvdG90eXBlKTsKICAgICAgICAgICAgICAgIHZhciBPYmplY3RQcm90b3R5cGUgPSBPYmplY3QucHJvdG90eXBlOwogICAgICAgICAgICAgICAgdmFyIFR5cGVFcnJvciA9IGdsb2JhbC5UeXBlRXJyb3I7CiAgICAgICAgICAgICAgICB2YXIgVE9fU1RSSU5HX1RBRyA9IHdlbGxLbm93blN5bWJvbCgndG9TdHJpbmdUYWcnKTsKICAgICAgICAgICAgICAgIHZhciBUWVBFRF9BUlJBWV9UQUcgPSB1aWQoJ1RZUEVEX0FSUkFZX1RBRycpOwogICAgICAgICAgICAgICAgdmFyIFRZUEVEX0FSUkFZX0NPTlNUUlVDVE9SID0gJ1R5cGVkQXJyYXlDb25zdHJ1Y3Rvcic7CiAgICAgICAgICAgICAgICB2YXIgTkFUSVZFX0FSUkFZX0JVRkZFUl9WSUVXUyA9IE5BVElWRV9BUlJBWV9CVUZGRVIgJiYgISFzZXRQcm90b3R5cGVPZiAmJiBjbGFzc29mKGdsb2JhbC5vcGVyYSkgIT09ICdPcGVyYSc7CiAgICAgICAgICAgICAgICB2YXIgVFlQRURfQVJSQVlfVEFHX1JFUVVJUkVEID0gZmFsc2U7CiAgICAgICAgICAgICAgICB2YXIgTkFNRSwgQ29uc3RydWN0b3IsIFByb3RvdHlwZTsKICAgICAgICAgICAgICAgIHZhciBUeXBlZEFycmF5Q29uc3RydWN0b3JzTGlzdCA9IHsKICAgICAgICAgICAgICAgICAgICBJbnQ4QXJyYXk6IDEsCiAgICAgICAgICAgICAgICAgICAgVWludDhBcnJheTogMSwKICAgICAgICAgICAgICAgICAgICBVaW50OENsYW1wZWRBcnJheTogMSwKICAgICAgICAgICAgICAgICAgICBJbnQxNkFycmF5OiAyLAogICAgICAgICAgICAgICAgICAgIFVpbnQxNkFycmF5OiAyLAogICAgICAgICAgICAgICAgICAgIEludDMyQXJyYXk6IDQsCiAgICAgICAgICAgICAgICAgICAgVWludDMyQXJyYXk6IDQsCiAgICAgICAgICAgICAgICAgICAgRmxvYXQzMkFycmF5OiA0LAogICAgICAgICAgICAgICAgICAgIEZsb2F0NjRBcnJheTogOAogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciBCaWdJbnRBcnJheUNvbnN0cnVjdG9yc0xpc3QgPSB7CiAgICAgICAgICAgICAgICAgICAgQmlnSW50NjRBcnJheTogOCwKICAgICAgICAgICAgICAgICAgICBCaWdVaW50NjRBcnJheTogOAogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciBpc1ZpZXcgPSBmdW5jdGlvbiBpc1ZpZXcoaXQpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KGl0KSkKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgIHZhciBrbGFzcyA9IGNsYXNzb2YoaXQpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBrbGFzcyA9PT0gJ0RhdGFWaWV3JyB8fCBoYXNPd24oVHlwZWRBcnJheUNvbnN0cnVjdG9yc0xpc3QsIGtsYXNzKSB8fCBoYXNPd24oQmlnSW50QXJyYXlDb25zdHJ1Y3RvcnNMaXN0LCBrbGFzcyk7CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgdmFyIGdldFR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IGZ1bmN0aW9uIChpdCkgewogICAgICAgICAgICAgICAgICAgIHZhciBwcm90byA9IGdldFByb3RvdHlwZU9mKGl0KTsKICAgICAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KHByb3RvKSkKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIHZhciBzdGF0ZSA9IGdldEludGVybmFsU3RhdGUocHJvdG8pOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBzdGF0ZSAmJiBoYXNPd24oc3RhdGUsIFRZUEVEX0FSUkFZX0NPTlNUUlVDVE9SKSA/IHN0YXRlW1RZUEVEX0FSUkFZX0NPTlNUUlVDVE9SXSA6IGdldFR5cGVkQXJyYXlDb25zdHJ1Y3Rvcihwcm90byk7CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgdmFyIGlzVHlwZWRBcnJheSA9IGZ1bmN0aW9uIChpdCkgewogICAgICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3QoaXQpKQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgdmFyIGtsYXNzID0gY2xhc3NvZihpdCk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGhhc093bihUeXBlZEFycmF5Q29uc3RydWN0b3JzTGlzdCwga2xhc3MpIHx8IGhhc093bihCaWdJbnRBcnJheUNvbnN0cnVjdG9yc0xpc3QsIGtsYXNzKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB2YXIgYVR5cGVkQXJyYXkgPSBmdW5jdGlvbiAoaXQpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoaXNUeXBlZEFycmF5KGl0KSkKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGl0OwogICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcignVGFyZ2V0IGlzIG5vdCBhIHR5cGVkIGFycmF5Jyk7CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgdmFyIGFUeXBlZEFycmF5Q29uc3RydWN0b3IgPSBmdW5jdGlvbiAoQykgewogICAgICAgICAgICAgICAgICAgIGlmIChpc0NhbGxhYmxlKEMpICYmICghc2V0UHJvdG90eXBlT2YgfHwgaXNQcm90b3R5cGVPZihUeXBlZEFycmF5LCBDKSkpCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBDOwogICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcih0cnlUb1N0cmluZyhDKSArICcgaXMgbm90IGEgdHlwZWQgYXJyYXkgY29uc3RydWN0b3InKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB2YXIgZXhwb3J0VHlwZWRBcnJheU1ldGhvZCA9IGZ1bmN0aW9uIChLRVksIHByb3BlcnR5LCBmb3JjZWQsIG9wdGlvbnMpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIURFU0NSSVBUT1JTKQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgaWYgKGZvcmNlZCkKICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgQVJSQVkgaW4gVHlwZWRBcnJheUNvbnN0cnVjdG9yc0xpc3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBUeXBlZEFycmF5Q29uc3RydWN0b3IgPSBnbG9iYWxbQVJSQVldOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFR5cGVkQXJyYXlDb25zdHJ1Y3RvciAmJiBoYXNPd24oVHlwZWRBcnJheUNvbnN0cnVjdG9yLnByb3RvdHlwZSwgS0VZKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgVHlwZWRBcnJheUNvbnN0cnVjdG9yLnByb3RvdHlwZVtLRVldOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUeXBlZEFycmF5Q29uc3RydWN0b3IucHJvdG90eXBlW0tFWV0gPSBwcm9wZXJ0eTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoIVR5cGVkQXJyYXlQcm90b3R5cGVbS0VZXSB8fCBmb3JjZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZGVmaW5lQnVpbHRJbihUeXBlZEFycmF5UHJvdG90eXBlLCBLRVksIGZvcmNlZCA/IHByb3BlcnR5IDogTkFUSVZFX0FSUkFZX0JVRkZFUl9WSUVXUyAmJiBJbnQ4QXJyYXlQcm90b3R5cGVbS0VZXSB8fCBwcm9wZXJ0eSwgb3B0aW9ucyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciBleHBvcnRUeXBlZEFycmF5U3RhdGljTWV0aG9kID0gZnVuY3Rpb24gKEtFWSwgcHJvcGVydHksIGZvcmNlZCkgewogICAgICAgICAgICAgICAgICAgIHZhciBBUlJBWSwgVHlwZWRBcnJheUNvbnN0cnVjdG9yOwogICAgICAgICAgICAgICAgICAgIGlmICghREVTQ1JJUFRPUlMpCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICBpZiAoc2V0UHJvdG90eXBlT2YpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZvcmNlZCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoQVJSQVkgaW4gVHlwZWRBcnJheUNvbnN0cnVjdG9yc0xpc3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUeXBlZEFycmF5Q29uc3RydWN0b3IgPSBnbG9iYWxbQVJSQVldOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChUeXBlZEFycmF5Q29uc3RydWN0b3IgJiYgaGFzT3duKFR5cGVkQXJyYXlDb25zdHJ1Y3RvciwgS0VZKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBUeXBlZEFycmF5Q29uc3RydWN0b3JbS0VZXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIVR5cGVkQXJyYXlbS0VZXSB8fCBmb3JjZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRlZmluZUJ1aWx0SW4oVHlwZWRBcnJheSwgS0VZLCBmb3JjZWQgPyBwcm9wZXJ0eSA6IE5BVElWRV9BUlJBWV9CVUZGRVJfVklFV1MgJiYgVHlwZWRBcnJheVtLRVldIHx8IHByb3BlcnR5KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmb3IgKEFSUkFZIGluIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnNMaXN0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIFR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IGdsb2JhbFtBUlJBWV07CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChUeXBlZEFycmF5Q29uc3RydWN0b3IgJiYgKCFUeXBlZEFycmF5Q29uc3RydWN0b3JbS0VZXSB8fCBmb3JjZWQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZpbmVCdWlsdEluKFR5cGVkQXJyYXlDb25zdHJ1Y3RvciwgS0VZLCBwcm9wZXJ0eSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgZm9yIChOQU1FIGluIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnNMaXN0KSB7CiAgICAgICAgICAgICAgICAgICAgQ29uc3RydWN0b3IgPSBnbG9iYWxbTkFNRV07CiAgICAgICAgICAgICAgICAgICAgUHJvdG90eXBlID0gQ29uc3RydWN0b3IgJiYgQ29uc3RydWN0b3IucHJvdG90eXBlOwogICAgICAgICAgICAgICAgICAgIGlmIChQcm90b3R5cGUpCiAgICAgICAgICAgICAgICAgICAgICAgIGVuZm9yY2VJbnRlcm5hbFN0YXRlKFByb3RvdHlwZSlbVFlQRURfQVJSQVlfQ09OU1RSVUNUT1JdID0gQ29uc3RydWN0b3I7CiAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICBOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTID0gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmb3IgKE5BTUUgaW4gQmlnSW50QXJyYXlDb25zdHJ1Y3RvcnNMaXN0KSB7CiAgICAgICAgICAgICAgICAgICAgQ29uc3RydWN0b3IgPSBnbG9iYWxbTkFNRV07CiAgICAgICAgICAgICAgICAgICAgUHJvdG90eXBlID0gQ29uc3RydWN0b3IgJiYgQ29uc3RydWN0b3IucHJvdG90eXBlOwogICAgICAgICAgICAgICAgICAgIGlmIChQcm90b3R5cGUpCiAgICAgICAgICAgICAgICAgICAgICAgIGVuZm9yY2VJbnRlcm5hbFN0YXRlKFByb3RvdHlwZSlbVFlQRURfQVJSQVlfQ09OU1RSVUNUT1JdID0gQ29uc3RydWN0b3I7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoIU5BVElWRV9BUlJBWV9CVUZGRVJfVklFV1MgfHwgIWlzQ2FsbGFibGUoVHlwZWRBcnJheSkgfHwgVHlwZWRBcnJheSA9PT0gRnVuY3Rpb24ucHJvdG90eXBlKSB7CiAgICAgICAgICAgICAgICAgICAgVHlwZWRBcnJheSA9IGZ1bmN0aW9uIFR5cGVkQXJyYXkoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcignSW5jb3JyZWN0IGludm9jYXRpb24nKTsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGlmIChOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTKQogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKE5BTUUgaW4gVHlwZWRBcnJheUNvbnN0cnVjdG9yc0xpc3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnbG9iYWxbTkFNRV0pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0UHJvdG90eXBlT2YoZ2xvYmFsW05BTUVdLCBUeXBlZEFycmF5KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKCFOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTIHx8ICFUeXBlZEFycmF5UHJvdG90eXBlIHx8IFR5cGVkQXJyYXlQcm90b3R5cGUgPT09IE9iamVjdFByb3RvdHlwZSkgewogICAgICAgICAgICAgICAgICAgIFR5cGVkQXJyYXlQcm90b3R5cGUgPSBUeXBlZEFycmF5LnByb3RvdHlwZTsKICAgICAgICAgICAgICAgICAgICBpZiAoTkFUSVZFX0FSUkFZX0JVRkZFUl9WSUVXUykKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChOQU1FIGluIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnNMaXN0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2xvYmFsW05BTUVdKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFByb3RvdHlwZU9mKGdsb2JhbFtOQU1FXS5wcm90b3R5cGUsIFR5cGVkQXJyYXlQcm90b3R5cGUpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoTkFUSVZFX0FSUkFZX0JVRkZFUl9WSUVXUyAmJiBnZXRQcm90b3R5cGVPZihVaW50OENsYW1wZWRBcnJheVByb3RvdHlwZSkgIT09IFR5cGVkQXJyYXlQcm90b3R5cGUpIHsKICAgICAgICAgICAgICAgICAgICBzZXRQcm90b3R5cGVPZihVaW50OENsYW1wZWRBcnJheVByb3RvdHlwZSwgVHlwZWRBcnJheVByb3RvdHlwZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoREVTQ1JJUFRPUlMgJiYgIWhhc093bihUeXBlZEFycmF5UHJvdG90eXBlLCBUT19TVFJJTkdfVEFHKSkgewogICAgICAgICAgICAgICAgICAgIFRZUEVEX0FSUkFZX1RBR19SRVFVSVJFRCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgZGVmaW5lQnVpbHRJbkFjY2Vzc29yKFR5cGVkQXJyYXlQcm90b3R5cGUsIFRPX1NUUklOR19UQUcsIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpc09iamVjdCh0aGlzKSA/IHRoaXNbVFlQRURfQVJSQVlfVEFHXSA6IHVuZGVmaW5lZDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIGZvciAoTkFNRSBpbiBUeXBlZEFycmF5Q29uc3RydWN0b3JzTGlzdCkKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdsb2JhbFtOQU1FXSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KGdsb2JhbFtOQU1FXSwgVFlQRURfQVJSQVlfVEFHLCBOQU1FKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7CiAgICAgICAgICAgICAgICAgICAgTkFUSVZFX0FSUkFZX0JVRkZFUl9WSUVXUzogTkFUSVZFX0FSUkFZX0JVRkZFUl9WSUVXUywKICAgICAgICAgICAgICAgICAgICBUWVBFRF9BUlJBWV9UQUc6IFRZUEVEX0FSUkFZX1RBR19SRVFVSVJFRCAmJiBUWVBFRF9BUlJBWV9UQUcsCiAgICAgICAgICAgICAgICAgICAgYVR5cGVkQXJyYXk6IGFUeXBlZEFycmF5LAogICAgICAgICAgICAgICAgICAgIGFUeXBlZEFycmF5Q29uc3RydWN0b3I6IGFUeXBlZEFycmF5Q29uc3RydWN0b3IsCiAgICAgICAgICAgICAgICAgICAgZXhwb3J0VHlwZWRBcnJheU1ldGhvZDogZXhwb3J0VHlwZWRBcnJheU1ldGhvZCwKICAgICAgICAgICAgICAgICAgICBleHBvcnRUeXBlZEFycmF5U3RhdGljTWV0aG9kOiBleHBvcnRUeXBlZEFycmF5U3RhdGljTWV0aG9kLAogICAgICAgICAgICAgICAgICAgIGdldFR5cGVkQXJyYXlDb25zdHJ1Y3RvcjogZ2V0VHlwZWRBcnJheUNvbnN0cnVjdG9yLAogICAgICAgICAgICAgICAgICAgIGlzVmlldzogaXNWaWV3LAogICAgICAgICAgICAgICAgICAgIGlzVHlwZWRBcnJheTogaXNUeXBlZEFycmF5LAogICAgICAgICAgICAgICAgICAgIFR5cGVkQXJyYXk6IFR5cGVkQXJyYXksCiAgICAgICAgICAgICAgICAgICAgVHlwZWRBcnJheVByb3RvdHlwZTogVHlwZWRBcnJheVByb3RvdHlwZQogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogODEgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUpID0+IHsKCiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHR5cGVvZiBBcnJheUJ1ZmZlciAhPSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgRGF0YVZpZXcgIT0gJ3VuZGVmaW5lZCc7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDgyICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgVE9fU1RSSU5HX1RBR19TVVBQT1JUID0gX193X3BkZmpzX3JlcXVpcmVfXyg4Myk7CiAgICAgICAgICAgICAgICB2YXIgaXNDYWxsYWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjQpOwogICAgICAgICAgICAgICAgdmFyIGNsYXNzb2ZSYXcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE4KTsKICAgICAgICAgICAgICAgIHZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM3KTsKICAgICAgICAgICAgICAgIHZhciBUT19TVFJJTkdfVEFHID0gd2VsbEtub3duU3ltYm9sKCd0b1N0cmluZ1RhZycpOwogICAgICAgICAgICAgICAgdmFyICRPYmplY3QgPSBPYmplY3Q7CiAgICAgICAgICAgICAgICB2YXIgQ09SUkVDVF9BUkdVTUVOVFMgPSBjbGFzc29mUmF3KChmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFyZ3VtZW50czsKICAgICAgICAgICAgICAgIH0oKSkpID09ICdBcmd1bWVudHMnOwogICAgICAgICAgICAgICAgdmFyIHRyeUdldCA9IGZ1bmN0aW9uIChpdCwga2V5KSB7CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGl0W2tleV07CiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBUT19TVFJJTkdfVEFHX1NVUFBPUlQgPyBjbGFzc29mUmF3IDogZnVuY3Rpb24gKGl0KSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIE8sIHRhZywgcmVzdWx0OwogICAgICAgICAgICAgICAgICAgIHJldHVybiBpdCA9PT0gdW5kZWZpbmVkID8gJ1VuZGVmaW5lZCcgOiBpdCA9PT0gbnVsbCA/ICdOdWxsJyA6IHR5cGVvZiAodGFnID0gdHJ5R2V0KE8gPSAkT2JqZWN0KGl0KSwgVE9fU1RSSU5HX1RBRykpID09ICdzdHJpbmcnID8gdGFnIDogQ09SUkVDVF9BUkdVTUVOVFMgPyBjbGFzc29mUmF3KE8pIDogKHJlc3VsdCA9IGNsYXNzb2ZSYXcoTykpID09ICdPYmplY3QnICYmIGlzQ2FsbGFibGUoTy5jYWxsZWUpID8gJ0FyZ3VtZW50cycgOiByZXN1bHQ7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA4MyAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHdlbGxLbm93blN5bWJvbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMzcpOwogICAgICAgICAgICAgICAgdmFyIFRPX1NUUklOR19UQUcgPSB3ZWxsS25vd25TeW1ib2woJ3RvU3RyaW5nVGFnJyk7CiAgICAgICAgICAgICAgICB2YXIgdGVzdCA9IHt9OwogICAgICAgICAgICAgICAgdGVzdFtUT19TVFJJTkdfVEFHXSA9ICd6JzsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gU3RyaW5nKHRlc3QpID09PSAnW29iamVjdCB6XSc7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDg0ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgbWFrZUJ1aWx0SW4gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDUyKTsKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVQcm9wZXJ0eSA9IF9fd19wZGZqc19yZXF1aXJlX18oNDgpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodGFyZ2V0LCBuYW1lLCBkZXNjcmlwdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGRlc2NyaXB0b3IuZ2V0KQogICAgICAgICAgICAgICAgICAgICAgICBtYWtlQnVpbHRJbihkZXNjcmlwdG9yLmdldCwgbmFtZSwgeyBnZXR0ZXI6IHRydWUgfSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKGRlc2NyaXB0b3Iuc2V0KQogICAgICAgICAgICAgICAgICAgICAgICBtYWtlQnVpbHRJbihkZXNjcmlwdG9yLnNldCwgbmFtZSwgeyBzZXR0ZXI6IHRydWUgfSk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRlZmluZVByb3BlcnR5LmYodGFyZ2V0LCBuYW1lLCBkZXNjcmlwdG9yKTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDg1ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgaGFzT3duID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Mik7CiAgICAgICAgICAgICAgICB2YXIgaXNDYWxsYWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjQpOwogICAgICAgICAgICAgICAgdmFyIHRvT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Myk7CiAgICAgICAgICAgICAgICB2YXIgc2hhcmVkS2V5ID0gX193X3BkZmpzX3JlcXVpcmVfXyg1Nyk7CiAgICAgICAgICAgICAgICB2YXIgQ09SUkVDVF9QUk9UT1RZUEVfR0VUVEVSID0gX193X3BkZmpzX3JlcXVpcmVfXyg4Nik7CiAgICAgICAgICAgICAgICB2YXIgSUVfUFJPVE8gPSBzaGFyZWRLZXkoJ0lFX1BST1RPJyk7CiAgICAgICAgICAgICAgICB2YXIgJE9iamVjdCA9IE9iamVjdDsKICAgICAgICAgICAgICAgIHZhciBPYmplY3RQcm90b3R5cGUgPSAkT2JqZWN0LnByb3RvdHlwZTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gQ09SUkVDVF9QUk9UT1RZUEVfR0VUVEVSID8gJE9iamVjdC5nZXRQcm90b3R5cGVPZiA6IGZ1bmN0aW9uIChPKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdCA9IHRvT2JqZWN0KE8pOwogICAgICAgICAgICAgICAgICAgIGlmIChoYXNPd24ob2JqZWN0LCBJRV9QUk9UTykpCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3RbSUVfUFJPVE9dOwogICAgICAgICAgICAgICAgICAgIHZhciBjb25zdHJ1Y3RvciA9IG9iamVjdC5jb25zdHJ1Y3RvcjsKICAgICAgICAgICAgICAgICAgICBpZiAoaXNDYWxsYWJsZShjb25zdHJ1Y3RvcikgJiYgb2JqZWN0IGluc3RhbmNlb2YgY29uc3RydWN0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbnN0cnVjdG9yLnByb3RvdHlwZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdCBpbnN0YW5jZW9mICRPYmplY3QgPyBPYmplY3RQcm90b3R5cGUgOiBudWxsOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogODYgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTApOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAhZmFpbHMoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIEYoKSB7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIEYucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKG5ldyBGKCkpICE9PSBGLnByb3RvdHlwZTsKICAgICAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA4NyAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzQWNjZXNzb3IgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDg4KTsKICAgICAgICAgICAgICAgIHZhciBhbk9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oNTApOwogICAgICAgICAgICAgICAgdmFyIGFQb3NzaWJsZVByb3RvdHlwZSA9IF9fd19wZGZqc19yZXF1aXJlX18oODkpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwgKCdfX3Byb3RvX18nIGluIHt9ID8gKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgQ09SUkVDVF9TRVRURVIgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB2YXIgdGVzdCA9IHt9OwogICAgICAgICAgICAgICAgICAgIHZhciBzZXR0ZXI7CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgc2V0dGVyID0gdW5jdXJyeVRoaXNBY2Nlc3NvcihPYmplY3QucHJvdG90eXBlLCAnX19wcm90b19fJywgJ3NldCcpOwogICAgICAgICAgICAgICAgICAgICAgICBzZXR0ZXIodGVzdCwgW10pOwogICAgICAgICAgICAgICAgICAgICAgICBDT1JSRUNUX1NFVFRFUiA9IHRlc3QgaW5zdGFuY2VvZiBBcnJheTsKICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gc2V0UHJvdG90eXBlT2YoTywgcHJvdG8pIHsKICAgICAgICAgICAgICAgICAgICAgICAgYW5PYmplY3QoTyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGFQb3NzaWJsZVByb3RvdHlwZShwcm90byk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChDT1JSRUNUX1NFVFRFUikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldHRlcihPLCBwcm90byk7CiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgIE8uX19wcm90b19fID0gcHJvdG87CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBPOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB9KCkpIDogdW5kZWZpbmVkKTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogODggKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTcpOwogICAgICAgICAgICAgICAgdmFyIGFDYWxsYWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMzQpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqZWN0LCBrZXksIG1ldGhvZCkgewogICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB1bmN1cnJ5VGhpcyhhQ2FsbGFibGUoT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIGtleSlbbWV0aG9kXSkpOwogICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogODkgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNCk7CiAgICAgICAgICAgICAgICB2YXIgJFN0cmluZyA9IFN0cmluZzsKICAgICAgICAgICAgICAgIHZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGFyZ3VtZW50ID09ICdvYmplY3QnIHx8IGlzQ2FsbGFibGUoYXJndW1lbnQpKQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXJndW1lbnQ7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgJFR5cGVFcnJvcigiQ2FuJ3Qgc2V0ICIgKyAkU3RyaW5nKGFyZ3VtZW50KSArICcgYXMgYSBwcm90b3R5cGUnKTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDkwICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICBfX3dfcGRmanNfcmVxdWlyZV9fKDkxKTsKICAgICAgICAgICAgICAgIF9fd19wZGZqc19yZXF1aXJlX18oOTgpOwogICAgICAgICAgICAgICAgX193X3BkZmpzX3JlcXVpcmVfXygxMDApOwogICAgICAgICAgICAgICAgX193X3BkZmpzX3JlcXVpcmVfXygxMjMpOwogICAgICAgICAgICAgICAgX193X3BkZmpzX3JlcXVpcmVfXygxMjUpOwogICAgICAgICAgICAgICAgdmFyIHBhdGggPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzNyk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGguc3RydWN0dXJlZENsb25lOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA5MSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKICAgICAgICAgICAgICAgIHZhciB0b0luZGV4ZWRPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1KTsKICAgICAgICAgICAgICAgIHZhciBhZGRUb1Vuc2NvcGFibGVzID0gX193X3BkZmpzX3JlcXVpcmVfXyg3Mik7CiAgICAgICAgICAgICAgICB2YXIgSXRlcmF0b3JzID0gX193X3BkZmpzX3JlcXVpcmVfXyg5Mik7CiAgICAgICAgICAgICAgICB2YXIgSW50ZXJuYWxTdGF0ZU1vZHVsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNTUpOwogICAgICAgICAgICAgICAgdmFyIGRlZmluZVByb3BlcnR5ID0gKF9fd19wZGZqc19yZXF1aXJlX18oNDgpLmYpOwogICAgICAgICAgICAgICAgdmFyIGRlZmluZUl0ZXJhdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXyg5Myk7CiAgICAgICAgICAgICAgICB2YXIgY3JlYXRlSXRlclJlc3VsdE9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oOTcpOwogICAgICAgICAgICAgICAgdmFyIElTX1BVUkUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM5KTsKICAgICAgICAgICAgICAgIHZhciBERVNDUklQVE9SUyA9IF9fd19wZGZqc19yZXF1aXJlX18oOSk7CiAgICAgICAgICAgICAgICB2YXIgQVJSQVlfSVRFUkFUT1IgPSAnQXJyYXkgSXRlcmF0b3InOwogICAgICAgICAgICAgICAgdmFyIHNldEludGVybmFsU3RhdGUgPSBJbnRlcm5hbFN0YXRlTW9kdWxlLnNldDsKICAgICAgICAgICAgICAgIHZhciBnZXRJbnRlcm5hbFN0YXRlID0gSW50ZXJuYWxTdGF0ZU1vZHVsZS5nZXR0ZXJGb3IoQVJSQVlfSVRFUkFUT1IpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkZWZpbmVJdGVyYXRvcihBcnJheSwgJ0FycmF5JywgZnVuY3Rpb24gKGl0ZXJhdGVkLCBraW5kKSB7CiAgICAgICAgICAgICAgICAgICAgc2V0SW50ZXJuYWxTdGF0ZSh0aGlzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IEFSUkFZX0lURVJBVE9SLAogICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQ6IHRvSW5kZXhlZE9iamVjdChpdGVyYXRlZCksCiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4OiAwLAogICAgICAgICAgICAgICAgICAgICAgICBraW5kOiBraW5kCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9LCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIHN0YXRlID0gZ2V0SW50ZXJuYWxTdGF0ZSh0aGlzKTsKICAgICAgICAgICAgICAgICAgICB2YXIgdGFyZ2V0ID0gc3RhdGUudGFyZ2V0OwogICAgICAgICAgICAgICAgICAgIHZhciBraW5kID0gc3RhdGUua2luZDsKICAgICAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBzdGF0ZS5pbmRleCsrOwogICAgICAgICAgICAgICAgICAgIGlmICghdGFyZ2V0IHx8IGluZGV4ID49IHRhcmdldC5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUudGFyZ2V0ID0gdW5kZWZpbmVkOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3JlYXRlSXRlclJlc3VsdE9iamVjdCh1bmRlZmluZWQsIHRydWUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoa2luZCA9PSAna2V5cycpCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjcmVhdGVJdGVyUmVzdWx0T2JqZWN0KGluZGV4LCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKGtpbmQgPT0gJ3ZhbHVlcycpCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjcmVhdGVJdGVyUmVzdWx0T2JqZWN0KHRhcmdldFtpbmRleF0sIGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3JlYXRlSXRlclJlc3VsdE9iamVjdChbCiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4LAogICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRbaW5kZXhdCiAgICAgICAgICAgICAgICAgICAgXSwgZmFsc2UpOwogICAgICAgICAgICAgICAgfSwgJ3ZhbHVlcycpOwogICAgICAgICAgICAgICAgdmFyIHZhbHVlcyA9IEl0ZXJhdG9ycy5Bcmd1bWVudHMgPSBJdGVyYXRvcnMuQXJyYXk7CiAgICAgICAgICAgICAgICBhZGRUb1Vuc2NvcGFibGVzKCdrZXlzJyk7CiAgICAgICAgICAgICAgICBhZGRUb1Vuc2NvcGFibGVzKCd2YWx1ZXMnKTsKICAgICAgICAgICAgICAgIGFkZFRvVW5zY29wYWJsZXMoJ2VudHJpZXMnKTsKICAgICAgICAgICAgICAgIGlmICghSVNfUFVSRSAmJiBERVNDUklQVE9SUyAmJiB2YWx1ZXMubmFtZSAhPT0gJ3ZhbHVlcycpCiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgZGVmaW5lUHJvcGVydHkodmFsdWVzLCAnbmFtZScsIHsgdmFsdWU6ICd2YWx1ZXMnIH0pOwogICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA5MiAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSkgPT4gewoKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0ge307CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDkzICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgogICAgICAgICAgICAgICAgdmFyICQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDYpOwogICAgICAgICAgICAgICAgdmFyIGNhbGwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExKTsKICAgICAgICAgICAgICAgIHZhciBJU19QVVJFID0gX193X3BkZmpzX3JlcXVpcmVfXygzOSk7CiAgICAgICAgICAgICAgICB2YXIgRnVuY3Rpb25OYW1lID0gX193X3BkZmpzX3JlcXVpcmVfXyg1Myk7CiAgICAgICAgICAgICAgICB2YXIgaXNDYWxsYWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjQpOwogICAgICAgICAgICAgICAgdmFyIGNyZWF0ZUl0ZXJhdG9yQ29uc3RydWN0b3IgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDk0KTsKICAgICAgICAgICAgICAgIHZhciBnZXRQcm90b3R5cGVPZiA9IF9fd19wZGZqc19yZXF1aXJlX18oODUpOwogICAgICAgICAgICAgICAgdmFyIHNldFByb3RvdHlwZU9mID0gX193X3BkZmpzX3JlcXVpcmVfXyg4Nyk7CiAgICAgICAgICAgICAgICB2YXIgc2V0VG9TdHJpbmdUYWcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDk2KTsKICAgICAgICAgICAgICAgIHZhciBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ3KTsKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVCdWlsdEluID0gX193X3BkZmpzX3JlcXVpcmVfXyg1MSk7CiAgICAgICAgICAgICAgICB2YXIgd2VsbEtub3duU3ltYm9sID0gX193X3BkZmpzX3JlcXVpcmVfXygzNyk7CiAgICAgICAgICAgICAgICB2YXIgSXRlcmF0b3JzID0gX193X3BkZmpzX3JlcXVpcmVfXyg5Mik7CiAgICAgICAgICAgICAgICB2YXIgSXRlcmF0b3JzQ29yZSA9IF9fd19wZGZqc19yZXF1aXJlX18oOTUpOwogICAgICAgICAgICAgICAgdmFyIFBST1BFUl9GVU5DVElPTl9OQU1FID0gRnVuY3Rpb25OYW1lLlBST1BFUjsKICAgICAgICAgICAgICAgIHZhciBDT05GSUdVUkFCTEVfRlVOQ1RJT05fTkFNRSA9IEZ1bmN0aW9uTmFtZS5DT05GSUdVUkFCTEU7CiAgICAgICAgICAgICAgICB2YXIgSXRlcmF0b3JQcm90b3R5cGUgPSBJdGVyYXRvcnNDb3JlLkl0ZXJhdG9yUHJvdG90eXBlOwogICAgICAgICAgICAgICAgdmFyIEJVR0dZX1NBRkFSSV9JVEVSQVRPUlMgPSBJdGVyYXRvcnNDb3JlLkJVR0dZX1NBRkFSSV9JVEVSQVRPUlM7CiAgICAgICAgICAgICAgICB2YXIgSVRFUkFUT1IgPSB3ZWxsS25vd25TeW1ib2woJ2l0ZXJhdG9yJyk7CiAgICAgICAgICAgICAgICB2YXIgS0VZUyA9ICdrZXlzJzsKICAgICAgICAgICAgICAgIHZhciBWQUxVRVMgPSAndmFsdWVzJzsKICAgICAgICAgICAgICAgIHZhciBFTlRSSUVTID0gJ2VudHJpZXMnOwogICAgICAgICAgICAgICAgdmFyIHJldHVyblRoaXMgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoSXRlcmFibGUsIE5BTUUsIEl0ZXJhdG9yQ29uc3RydWN0b3IsIG5leHQsIERFRkFVTFQsIElTX1NFVCwgRk9SQ0VEKSB7CiAgICAgICAgICAgICAgICAgICAgY3JlYXRlSXRlcmF0b3JDb25zdHJ1Y3RvcihJdGVyYXRvckNvbnN0cnVjdG9yLCBOQU1FLCBuZXh0KTsKICAgICAgICAgICAgICAgICAgICB2YXIgZ2V0SXRlcmF0aW9uTWV0aG9kID0gZnVuY3Rpb24gKEtJTkQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEtJTkQgPT09IERFRkFVTFQgJiYgZGVmYXVsdEl0ZXJhdG9yKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRlZmF1bHRJdGVyYXRvcjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFCVUdHWV9TQUZBUklfSVRFUkFUT1JTICYmIEtJTkQgaW4gSXRlcmFibGVQcm90b3R5cGUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gSXRlcmFibGVQcm90b3R5cGVbS0lORF07CiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoS0lORCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBLRVlTOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBrZXlzKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEl0ZXJhdG9yQ29uc3RydWN0b3IodGhpcywgS0lORCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgVkFMVUVTOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiB2YWx1ZXMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgSXRlcmF0b3JDb25zdHJ1Y3Rvcih0aGlzLCBLSU5EKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBFTlRSSUVTOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBlbnRyaWVzKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEl0ZXJhdG9yQ29uc3RydWN0b3IodGhpcywgS0lORCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBJdGVyYXRvckNvbnN0cnVjdG9yKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgdmFyIFRPX1NUUklOR19UQUcgPSBOQU1FICsgJyBJdGVyYXRvcic7CiAgICAgICAgICAgICAgICAgICAgdmFyIElOQ09SUkVDVF9WQUxVRVNfTkFNRSA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIHZhciBJdGVyYWJsZVByb3RvdHlwZSA9IEl0ZXJhYmxlLnByb3RvdHlwZTsKICAgICAgICAgICAgICAgICAgICB2YXIgbmF0aXZlSXRlcmF0b3IgPSBJdGVyYWJsZVByb3RvdHlwZVtJVEVSQVRPUl0gfHwgSXRlcmFibGVQcm90b3R5cGVbJ0BAaXRlcmF0b3InXSB8fCBERUZBVUxUICYmIEl0ZXJhYmxlUHJvdG90eXBlW0RFRkFVTFRdOwogICAgICAgICAgICAgICAgICAgIHZhciBkZWZhdWx0SXRlcmF0b3IgPSAhQlVHR1lfU0FGQVJJX0lURVJBVE9SUyAmJiBuYXRpdmVJdGVyYXRvciB8fCBnZXRJdGVyYXRpb25NZXRob2QoREVGQVVMVCk7CiAgICAgICAgICAgICAgICAgICAgdmFyIGFueU5hdGl2ZUl0ZXJhdG9yID0gTkFNRSA9PSAnQXJyYXknID8gSXRlcmFibGVQcm90b3R5cGUuZW50cmllcyB8fCBuYXRpdmVJdGVyYXRvciA6IG5hdGl2ZUl0ZXJhdG9yOwogICAgICAgICAgICAgICAgICAgIHZhciBDdXJyZW50SXRlcmF0b3JQcm90b3R5cGUsIG1ldGhvZHMsIEtFWTsKICAgICAgICAgICAgICAgICAgICBpZiAoYW55TmF0aXZlSXRlcmF0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlID0gZ2V0UHJvdG90eXBlT2YoYW55TmF0aXZlSXRlcmF0b3IuY2FsbChuZXcgSXRlcmFibGUoKSkpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlICE9PSBPYmplY3QucHJvdG90eXBlICYmIEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZS5uZXh0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUlTX1BVUkUgJiYgZ2V0UHJvdG90eXBlT2YoQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlKSAhPT0gSXRlcmF0b3JQcm90b3R5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2V0UHJvdG90eXBlT2YpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0UHJvdG90eXBlT2YoQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlLCBJdGVyYXRvclByb3RvdHlwZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNDYWxsYWJsZShDdXJyZW50SXRlcmF0b3JQcm90b3R5cGVbSVRFUkFUT1JdKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZpbmVCdWlsdEluKEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZSwgSVRFUkFUT1IsIHJldHVyblRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFRvU3RyaW5nVGFnKEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZSwgVE9fU1RSSU5HX1RBRywgdHJ1ZSwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoSVNfUFVSRSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJdGVyYXRvcnNbVE9fU1RSSU5HX1RBR10gPSByZXR1cm5UaGlzOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChQUk9QRVJfRlVOQ1RJT05fTkFNRSAmJiBERUZBVUxUID09IFZBTFVFUyAmJiBuYXRpdmVJdGVyYXRvciAmJiBuYXRpdmVJdGVyYXRvci5uYW1lICE9PSBWQUxVRVMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFJU19QVVJFICYmIENPTkZJR1VSQUJMRV9GVU5DVElPTl9OQU1FKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoSXRlcmFibGVQcm90b3R5cGUsICduYW1lJywgVkFMVUVTKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIElOQ09SUkVDVF9WQUxVRVNfTkFNRSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0SXRlcmF0b3IgPSBmdW5jdGlvbiB2YWx1ZXMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhbGwobmF0aXZlSXRlcmF0b3IsIHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoREVGQVVMVCkgewogICAgICAgICAgICAgICAgICAgICAgICBtZXRob2RzID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzOiBnZXRJdGVyYXRpb25NZXRob2QoVkFMVUVTKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleXM6IElTX1NFVCA/IGRlZmF1bHRJdGVyYXRvciA6IGdldEl0ZXJhdGlvbk1ldGhvZChLRVlTKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudHJpZXM6IGdldEl0ZXJhdGlvbk1ldGhvZChFTlRSSUVTKQogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoRk9SQ0VEKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChLRVkgaW4gbWV0aG9kcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChCVUdHWV9TQUZBUklfSVRFUkFUT1JTIHx8IElOQ09SUkVDVF9WQUxVRVNfTkFNRSB8fCAhKEtFWSBpbiBJdGVyYWJsZVByb3RvdHlwZSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmaW5lQnVpbHRJbihJdGVyYWJsZVByb3RvdHlwZSwgS0VZLCBtZXRob2RzW0tFWV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgJCh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0OiBOQU1FLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3RvOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcmNlZDogQlVHR1lfU0FGQVJJX0lURVJBVE9SUyB8fCBJTkNPUlJFQ1RfVkFMVUVTX05BTUUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIG1ldGhvZHMpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoKCFJU19QVVJFIHx8IEZPUkNFRCkgJiYgSXRlcmFibGVQcm90b3R5cGVbSVRFUkFUT1JdICE9PSBkZWZhdWx0SXRlcmF0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZGVmaW5lQnVpbHRJbihJdGVyYWJsZVByb3RvdHlwZSwgSVRFUkFUT1IsIGRlZmF1bHRJdGVyYXRvciwgeyBuYW1lOiBERUZBVUxUIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBJdGVyYXRvcnNbTkFNRV0gPSBkZWZhdWx0SXRlcmF0b3I7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1ldGhvZHM7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA5NCAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKICAgICAgICAgICAgICAgIHZhciBJdGVyYXRvclByb3RvdHlwZSA9IChfX3dfcGRmanNfcmVxdWlyZV9fKDk1KS5JdGVyYXRvclByb3RvdHlwZSk7CiAgICAgICAgICAgICAgICB2YXIgY3JlYXRlID0gX193X3BkZmpzX3JlcXVpcmVfXyg3Myk7CiAgICAgICAgICAgICAgICB2YXIgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXygxNCk7CiAgICAgICAgICAgICAgICB2YXIgc2V0VG9TdHJpbmdUYWcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDk2KTsKICAgICAgICAgICAgICAgIHZhciBJdGVyYXRvcnMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDkyKTsKICAgICAgICAgICAgICAgIHZhciByZXR1cm5UaGlzID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKEl0ZXJhdG9yQ29uc3RydWN0b3IsIE5BTUUsIG5leHQsIEVOVU1FUkFCTEVfTkVYVCkgewogICAgICAgICAgICAgICAgICAgIHZhciBUT19TVFJJTkdfVEFHID0gTkFNRSArICcgSXRlcmF0b3InOwogICAgICAgICAgICAgICAgICAgIEl0ZXJhdG9yQ29uc3RydWN0b3IucHJvdG90eXBlID0gY3JlYXRlKEl0ZXJhdG9yUHJvdG90eXBlLCB7IG5leHQ6IGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvcigrIUVOVU1FUkFCTEVfTkVYVCwgbmV4dCkgfSk7CiAgICAgICAgICAgICAgICAgICAgc2V0VG9TdHJpbmdUYWcoSXRlcmF0b3JDb25zdHJ1Y3RvciwgVE9fU1RSSU5HX1RBRywgZmFsc2UsIHRydWUpOwogICAgICAgICAgICAgICAgICAgIEl0ZXJhdG9yc1tUT19TVFJJTkdfVEFHXSA9IHJldHVyblRoaXM7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEl0ZXJhdG9yQ29uc3RydWN0b3I7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiA5NSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKICAgICAgICAgICAgICAgIHZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTApOwogICAgICAgICAgICAgICAgdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI0KTsKICAgICAgICAgICAgICAgIHZhciBpc09iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjMpOwogICAgICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNzMpOwogICAgICAgICAgICAgICAgdmFyIGdldFByb3RvdHlwZU9mID0gX193X3BkZmpzX3JlcXVpcmVfXyg4NSk7CiAgICAgICAgICAgICAgICB2YXIgZGVmaW5lQnVpbHRJbiA9IF9fd19wZGZqc19yZXF1aXJlX18oNTEpOwogICAgICAgICAgICAgICAgdmFyIHdlbGxLbm93blN5bWJvbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMzcpOwogICAgICAgICAgICAgICAgdmFyIElTX1BVUkUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM5KTsKICAgICAgICAgICAgICAgIHZhciBJVEVSQVRPUiA9IHdlbGxLbm93blN5bWJvbCgnaXRlcmF0b3InKTsKICAgICAgICAgICAgICAgIHZhciBCVUdHWV9TQUZBUklfSVRFUkFUT1JTID0gZmFsc2U7CiAgICAgICAgICAgICAgICB2YXIgSXRlcmF0b3JQcm90b3R5cGUsIFByb3RvdHlwZU9mQXJyYXlJdGVyYXRvclByb3RvdHlwZSwgYXJyYXlJdGVyYXRvcjsKICAgICAgICAgICAgICAgIGlmIChbXS5rZXlzKSB7CiAgICAgICAgICAgICAgICAgICAgYXJyYXlJdGVyYXRvciA9IFtdLmtleXMoKTsKICAgICAgICAgICAgICAgICAgICBpZiAoISgnbmV4dCcgaW4gYXJyYXlJdGVyYXRvcikpCiAgICAgICAgICAgICAgICAgICAgICAgIEJVR0dZX1NBRkFSSV9JVEVSQVRPUlMgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBQcm90b3R5cGVPZkFycmF5SXRlcmF0b3JQcm90b3R5cGUgPSBnZXRQcm90b3R5cGVPZihnZXRQcm90b3R5cGVPZihhcnJheUl0ZXJhdG9yKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChQcm90b3R5cGVPZkFycmF5SXRlcmF0b3JQcm90b3R5cGUgIT09IE9iamVjdC5wcm90b3R5cGUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBJdGVyYXRvclByb3RvdHlwZSA9IFByb3RvdHlwZU9mQXJyYXlJdGVyYXRvclByb3RvdHlwZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB2YXIgTkVXX0lURVJBVE9SX1BST1RPVFlQRSA9ICFpc09iamVjdChJdGVyYXRvclByb3RvdHlwZSkgfHwgZmFpbHMoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHZhciB0ZXN0ID0ge307CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEl0ZXJhdG9yUHJvdG90eXBlW0lURVJBVE9SXS5jYWxsKHRlc3QpICE9PSB0ZXN0OwogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICBpZiAoTkVXX0lURVJBVE9SX1BST1RPVFlQRSkKICAgICAgICAgICAgICAgICAgICBJdGVyYXRvclByb3RvdHlwZSA9IHt9OwogICAgICAgICAgICAgICAgZWxzZSBpZiAoSVNfUFVSRSkKICAgICAgICAgICAgICAgICAgICBJdGVyYXRvclByb3RvdHlwZSA9IGNyZWF0ZShJdGVyYXRvclByb3RvdHlwZSk7CiAgICAgICAgICAgICAgICBpZiAoIWlzQ2FsbGFibGUoSXRlcmF0b3JQcm90b3R5cGVbSVRFUkFUT1JdKSkgewogICAgICAgICAgICAgICAgICAgIGRlZmluZUJ1aWx0SW4oSXRlcmF0b3JQcm90b3R5cGUsIElURVJBVE9SLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7CiAgICAgICAgICAgICAgICAgICAgSXRlcmF0b3JQcm90b3R5cGU6IEl0ZXJhdG9yUHJvdG90eXBlLAogICAgICAgICAgICAgICAgICAgIEJVR0dZX1NBRkFSSV9JVEVSQVRPUlM6IEJVR0dZX1NBRkFSSV9JVEVSQVRPUlMKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDk2ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgZGVmaW5lUHJvcGVydHkgPSAoX193X3BkZmpzX3JlcXVpcmVfXyg0OCkuZik7CiAgICAgICAgICAgICAgICB2YXIgaGFzT3duID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Mik7CiAgICAgICAgICAgICAgICB2YXIgd2VsbEtub3duU3ltYm9sID0gX193X3BkZmpzX3JlcXVpcmVfXygzNyk7CiAgICAgICAgICAgICAgICB2YXIgVE9fU1RSSU5HX1RBRyA9IHdlbGxLbm93blN5bWJvbCgndG9TdHJpbmdUYWcnKTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHRhcmdldCwgVEFHLCBTVEFUSUMpIHsKICAgICAgICAgICAgICAgICAgICBpZiAodGFyZ2V0ICYmICFTVEFUSUMpCiAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldCA9IHRhcmdldC5wcm90b3R5cGU7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRhcmdldCAmJiAhaGFzT3duKHRhcmdldCwgVE9fU1RSSU5HX1RBRykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBUT19TVFJJTkdfVEFHLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogVEFHCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDk3ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlKSA9PiB7CgogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodmFsdWUsIGRvbmUpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgIGRvbmU6IGRvbmUKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogOTggKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIFRPX1NUUklOR19UQUdfU1VQUE9SVCA9IF9fd19wZGZqc19yZXF1aXJlX18oODMpOwogICAgICAgICAgICAgICAgdmFyIGRlZmluZUJ1aWx0SW4gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDUxKTsKICAgICAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IF9fd19wZGZqc19yZXF1aXJlX18oOTkpOwogICAgICAgICAgICAgICAgaWYgKCFUT19TVFJJTkdfVEFHX1NVUFBPUlQpIHsKICAgICAgICAgICAgICAgICAgICBkZWZpbmVCdWlsdEluKE9iamVjdC5wcm90b3R5cGUsICd0b1N0cmluZycsIHRvU3RyaW5nLCB7IHVuc2FmZTogdHJ1ZSB9KTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogOTkgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCiAgICAgICAgICAgICAgICB2YXIgVE9fU1RSSU5HX1RBR19TVVBQT1JUID0gX193X3BkZmpzX3JlcXVpcmVfXyg4Myk7CiAgICAgICAgICAgICAgICB2YXIgY2xhc3NvZiA9IF9fd19wZGZqc19yZXF1aXJlX18oODIpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBUT19TVFJJTkdfVEFHX1NVUFBPUlQgPyB7fS50b1N0cmluZyA6IGZ1bmN0aW9uIHRvU3RyaW5nKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiAnW29iamVjdCAnICsgY2xhc3NvZih0aGlzKSArICddJzsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEwMCAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICBfX3dfcGRmanNfcmVxdWlyZV9fKDEwMSk7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEwMSAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgogICAgICAgICAgICAgICAgdmFyIGNvbGxlY3Rpb24gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwMik7CiAgICAgICAgICAgICAgICB2YXIgY29sbGVjdGlvblN0cm9uZyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTIwKTsKICAgICAgICAgICAgICAgIGNvbGxlY3Rpb24oJ01hcCcsIGZ1bmN0aW9uIChpbml0KSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIE1hcCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluaXQodGhpcywgYXJndW1lbnRzLmxlbmd0aCA/IGFyZ3VtZW50c1swXSA6IHVuZGVmaW5lZCk7CiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIH0sIGNvbGxlY3Rpb25TdHJvbmcpOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMDIgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCiAgICAgICAgICAgICAgICB2YXIgJCA9IF9fd19wZGZqc19yZXF1aXJlX18oNik7CiAgICAgICAgICAgICAgICB2YXIgZ2xvYmFsID0gX193X3BkZmpzX3JlcXVpcmVfXyg3KTsKICAgICAgICAgICAgICAgIHZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTcpOwogICAgICAgICAgICAgICAgdmFyIGlzRm9yY2VkID0gX193X3BkZmpzX3JlcXVpcmVfXyg3MSk7CiAgICAgICAgICAgICAgICB2YXIgZGVmaW5lQnVpbHRJbiA9IF9fd19wZGZqc19yZXF1aXJlX18oNTEpOwogICAgICAgICAgICAgICAgdmFyIEludGVybmFsTWV0YWRhdGFNb2R1bGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwMyk7CiAgICAgICAgICAgICAgICB2YXIgaXRlcmF0ZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEwKTsKICAgICAgICAgICAgICAgIHZhciBhbkluc3RhbmNlID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTcpOwogICAgICAgICAgICAgICAgdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI0KTsKICAgICAgICAgICAgICAgIHZhciBpc051bGxPclVuZGVmaW5lZCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjApOwogICAgICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMyk7CiAgICAgICAgICAgICAgICB2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwKTsKICAgICAgICAgICAgICAgIHZhciBjaGVja0NvcnJlY3RuZXNzT2ZJdGVyYXRpb24gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExOCk7CiAgICAgICAgICAgICAgICB2YXIgc2V0VG9TdHJpbmdUYWcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDk2KTsKICAgICAgICAgICAgICAgIHZhciBpbmhlcml0SWZSZXF1aXJlZCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTE5KTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKENPTlNUUlVDVE9SX05BTUUsIHdyYXBwZXIsIGNvbW1vbikgewogICAgICAgICAgICAgICAgICAgIHZhciBJU19NQVAgPSBDT05TVFJVQ1RPUl9OQU1FLmluZGV4T2YoJ01hcCcpICE9PSAtMTsKICAgICAgICAgICAgICAgICAgICB2YXIgSVNfV0VBSyA9IENPTlNUUlVDVE9SX05BTUUuaW5kZXhPZignV2VhaycpICE9PSAtMTsKICAgICAgICAgICAgICAgICAgICB2YXIgQURERVIgPSBJU19NQVAgPyAnc2V0JyA6ICdhZGQnOwogICAgICAgICAgICAgICAgICAgIHZhciBOYXRpdmVDb25zdHJ1Y3RvciA9IGdsb2JhbFtDT05TVFJVQ1RPUl9OQU1FXTsKICAgICAgICAgICAgICAgICAgICB2YXIgTmF0aXZlUHJvdG90eXBlID0gTmF0aXZlQ29uc3RydWN0b3IgJiYgTmF0aXZlQ29uc3RydWN0b3IucHJvdG90eXBlOwogICAgICAgICAgICAgICAgICAgIHZhciBDb25zdHJ1Y3RvciA9IE5hdGl2ZUNvbnN0cnVjdG9yOwogICAgICAgICAgICAgICAgICAgIHZhciBleHBvcnRlZCA9IHt9OwogICAgICAgICAgICAgICAgICAgIHZhciBmaXhNZXRob2QgPSBmdW5jdGlvbiAoS0VZKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB1bmN1cnJpZWROYXRpdmVNZXRob2QgPSB1bmN1cnJ5VGhpcyhOYXRpdmVQcm90b3R5cGVbS0VZXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmluZUJ1aWx0SW4oTmF0aXZlUHJvdG90eXBlLCBLRVksIEtFWSA9PSAnYWRkJyA/IGZ1bmN0aW9uIGFkZCh2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5jdXJyaWVkTmF0aXZlTWV0aG9kKHRoaXMsIHZhbHVlID09PSAwID8gMCA6IHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgICAgICAgICAgICAgICB9IDogS0VZID09ICdkZWxldGUnID8gZnVuY3Rpb24gKGtleSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIElTX1dFQUsgJiYgIWlzT2JqZWN0KGtleSkgPyBmYWxzZSA6IHVuY3VycmllZE5hdGl2ZU1ldGhvZCh0aGlzLCBrZXkgPT09IDAgPyAwIDoga2V5KTsKICAgICAgICAgICAgICAgICAgICAgICAgfSA6IEtFWSA9PSAnZ2V0JyA/IGZ1bmN0aW9uIGdldChrZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBJU19XRUFLICYmICFpc09iamVjdChrZXkpID8gdW5kZWZpbmVkIDogdW5jdXJyaWVkTmF0aXZlTWV0aG9kKHRoaXMsIGtleSA9PT0gMCA/IDAgOiBrZXkpOwogICAgICAgICAgICAgICAgICAgICAgICB9IDogS0VZID09ICdoYXMnID8gZnVuY3Rpb24gaGFzKGtleSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIElTX1dFQUsgJiYgIWlzT2JqZWN0KGtleSkgPyBmYWxzZSA6IHVuY3VycmllZE5hdGl2ZU1ldGhvZCh0aGlzLCBrZXkgPT09IDAgPyAwIDoga2V5KTsKICAgICAgICAgICAgICAgICAgICAgICAgfSA6IGZ1bmN0aW9uIHNldChrZXksIHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmN1cnJpZWROYXRpdmVNZXRob2QodGhpcywga2V5ID09PSAwID8gMCA6IGtleSwgdmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgdmFyIFJFUExBQ0UgPSBpc0ZvcmNlZChDT05TVFJVQ1RPUl9OQU1FLCAhaXNDYWxsYWJsZShOYXRpdmVDb25zdHJ1Y3RvcikgfHwgIShJU19XRUFLIHx8IE5hdGl2ZVByb3RvdHlwZS5mb3JFYWNoICYmICFmYWlscyhmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBOYXRpdmVDb25zdHJ1Y3RvcigpLmVudHJpZXMoKS5uZXh0KCk7CiAgICAgICAgICAgICAgICAgICAgfSkpKTsKICAgICAgICAgICAgICAgICAgICBpZiAoUkVQTEFDRSkgewogICAgICAgICAgICAgICAgICAgICAgICBDb25zdHJ1Y3RvciA9IGNvbW1vbi5nZXRDb25zdHJ1Y3Rvcih3cmFwcGVyLCBDT05TVFJVQ1RPUl9OQU1FLCBJU19NQVAsIEFEREVSKTsKICAgICAgICAgICAgICAgICAgICAgICAgSW50ZXJuYWxNZXRhZGF0YU1vZHVsZS5lbmFibGUoKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzRm9yY2VkKENPTlNUUlVDVE9SX05BTUUsIHRydWUpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpbnN0YW5jZSA9IG5ldyBDb25zdHJ1Y3RvcigpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgSEFTTlRfQ0hBSU5JTkcgPSBpbnN0YW5jZVtBRERFUl0oSVNfV0VBSyA/IHt9IDogLTAsIDEpICE9IGluc3RhbmNlOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgVEhST1dTX09OX1BSSU1JVElWRVMgPSBmYWlscyhmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZS5oYXMoMSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgQUNDRVBUX0lURVJBQkxFUyA9IGNoZWNrQ29ycmVjdG5lc3NPZkl0ZXJhdGlvbihmdW5jdGlvbiAoaXRlcmFibGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBOYXRpdmVDb25zdHJ1Y3RvcihpdGVyYWJsZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgQlVHR1lfWkVSTyA9ICFJU19XRUFLICYmIGZhaWxzKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciAkaW5zdGFuY2UgPSBuZXcgTmF0aXZlQ29uc3RydWN0b3IoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IDU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaW5kZXgtLSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkaW5zdGFuY2VbQURERVJdKGluZGV4LCBpbmRleCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gISRpbnN0YW5jZS5oYXMoLTApOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFBQ0NFUFRfSVRFUkFCTEVTKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb25zdHJ1Y3RvciA9IHdyYXBwZXIoZnVuY3Rpb24gKGR1bW15LCBpdGVyYWJsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuSW5zdGFuY2UoZHVtbXksIE5hdGl2ZVByb3RvdHlwZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRoYXQgPSBpbmhlcml0SWZSZXF1aXJlZChuZXcgTmF0aXZlQ29uc3RydWN0b3IoKSwgZHVtbXksIENvbnN0cnVjdG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKGl0ZXJhYmxlKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlcmF0ZShpdGVyYWJsZSwgdGhhdFtBRERFUl0sIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQ6IHRoYXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBU19FTlRSSUVTOiBJU19NQVAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoYXQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIENvbnN0cnVjdG9yLnByb3RvdHlwZSA9IE5hdGl2ZVByb3RvdHlwZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5hdGl2ZVByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IENvbnN0cnVjdG9yOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChUSFJPV1NfT05fUFJJTUlUSVZFUyB8fCBCVUdHWV9aRVJPKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaXhNZXRob2QoJ2RlbGV0ZScpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZml4TWV0aG9kKCdoYXMnKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIElTX01BUCAmJiBmaXhNZXRob2QoJ2dldCcpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChCVUdHWV9aRVJPIHx8IEhBU05UX0NIQUlOSU5HKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZml4TWV0aG9kKEFEREVSKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKElTX1dFQUsgJiYgTmF0aXZlUHJvdG90eXBlLmNsZWFyKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIE5hdGl2ZVByb3RvdHlwZS5jbGVhcjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZXhwb3J0ZWRbQ09OU1RSVUNUT1JfTkFNRV0gPSBDb25zdHJ1Y3RvcjsKICAgICAgICAgICAgICAgICAgICAkKHsKICAgICAgICAgICAgICAgICAgICAgICAgZ2xvYmFsOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcjogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2VkOiBDb25zdHJ1Y3RvciAhPSBOYXRpdmVDb25zdHJ1Y3RvcgogICAgICAgICAgICAgICAgICAgIH0sIGV4cG9ydGVkKTsKICAgICAgICAgICAgICAgICAgICBzZXRUb1N0cmluZ1RhZyhDb25zdHJ1Y3RvciwgQ09OU1RSVUNUT1JfTkFNRSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFJU19XRUFLKQogICAgICAgICAgICAgICAgICAgICAgICBjb21tb24uc2V0U3Ryb25nKENvbnN0cnVjdG9yLCBDT05TVFJVQ1RPUl9OQU1FLCBJU19NQVApOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBDb25zdHJ1Y3RvcjsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEwMyAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyICQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDYpOwogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNyk7CiAgICAgICAgICAgICAgICB2YXIgaGlkZGVuS2V5cyA9IF9fd19wZGZqc19yZXF1aXJlX18oNTgpOwogICAgICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMyk7CiAgICAgICAgICAgICAgICB2YXIgaGFzT3duID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Mik7CiAgICAgICAgICAgICAgICB2YXIgZGVmaW5lUHJvcGVydHkgPSAoX193X3BkZmpzX3JlcXVpcmVfXyg0OCkuZik7CiAgICAgICAgICAgICAgICB2YXIgZ2V0T3duUHJvcGVydHlOYW1lc01vZHVsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNjEpOwogICAgICAgICAgICAgICAgdmFyIGdldE93blByb3BlcnR5TmFtZXNFeHRlcm5hbE1vZHVsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTA0KTsKICAgICAgICAgICAgICAgIHZhciBpc0V4dGVuc2libGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwNyk7CiAgICAgICAgICAgICAgICB2YXIgdWlkID0gX193X3BkZmpzX3JlcXVpcmVfXyg0NCk7CiAgICAgICAgICAgICAgICB2YXIgRlJFRVpJTkcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwOSk7CiAgICAgICAgICAgICAgICB2YXIgUkVRVUlSRUQgPSBmYWxzZTsKICAgICAgICAgICAgICAgIHZhciBNRVRBREFUQSA9IHVpZCgnbWV0YScpOwogICAgICAgICAgICAgICAgdmFyIGlkID0gMDsKICAgICAgICAgICAgICAgIHZhciBzZXRNZXRhZGF0YSA9IGZ1bmN0aW9uIChpdCkgewogICAgICAgICAgICAgICAgICAgIGRlZmluZVByb3BlcnR5KGl0LCBNRVRBREFUQSwgewogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogewogICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0SUQ6ICdPJyArIGlkKyssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3ZWFrRGF0YToge30KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciBmYXN0S2V5ID0gZnVuY3Rpb24gKGl0LCBjcmVhdGUpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KGl0KSkKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBpdCA9PSAnc3ltYm9sJyA/IGl0IDogKHR5cGVvZiBpdCA9PSAnc3RyaW5nJyA/ICdTJyA6ICdQJykgKyBpdDsKICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc093bihpdCwgTUVUQURBVEEpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaXNFeHRlbnNpYmxlKGl0KSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnRic7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY3JlYXRlKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdFJzsKICAgICAgICAgICAgICAgICAgICAgICAgc2V0TWV0YWRhdGEoaXQpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXRbTUVUQURBVEFdLm9iamVjdElEOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciBnZXRXZWFrRGF0YSA9IGZ1bmN0aW9uIChpdCwgY3JlYXRlKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNPd24oaXQsIE1FVEFEQVRBKSkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzRXh0ZW5zaWJsZShpdCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjcmVhdGUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHNldE1ldGFkYXRhKGl0KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGl0W01FVEFEQVRBXS53ZWFrRGF0YTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB2YXIgb25GcmVlemUgPSBmdW5jdGlvbiAoaXQpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoRlJFRVpJTkcgJiYgUkVRVUlSRUQgJiYgaXNFeHRlbnNpYmxlKGl0KSAmJiAhaGFzT3duKGl0LCBNRVRBREFUQSkpCiAgICAgICAgICAgICAgICAgICAgICAgIHNldE1ldGFkYXRhKGl0KTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXQ7CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgdmFyIGVuYWJsZSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICBtZXRhLmVuYWJsZSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIFJFUVVJUkVEID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICB2YXIgZ2V0T3duUHJvcGVydHlOYW1lcyA9IGdldE93blByb3BlcnR5TmFtZXNNb2R1bGUuZjsKICAgICAgICAgICAgICAgICAgICB2YXIgc3BsaWNlID0gdW5jdXJyeVRoaXMoW10uc3BsaWNlKTsKICAgICAgICAgICAgICAgICAgICB2YXIgdGVzdCA9IHt9OwogICAgICAgICAgICAgICAgICAgIHRlc3RbTUVUQURBVEFdID0gMTsKICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0T3duUHJvcGVydHlOYW1lcyh0ZXN0KS5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZ2V0T3duUHJvcGVydHlOYW1lc01vZHVsZS5mID0gZnVuY3Rpb24gKGl0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gZ2V0T3duUHJvcGVydHlOYW1lcyhpdCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gcmVzdWx0Lmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdFtpXSA9PT0gTUVUQURBVEEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BsaWNlKHJlc3VsdCwgaSwgMSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgICQoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0OiAnT2JqZWN0JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXQ6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JjZWQ6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgfSwgeyBnZXRPd25Qcm9wZXJ0eU5hbWVzOiBnZXRPd25Qcm9wZXJ0eU5hbWVzRXh0ZXJuYWxNb2R1bGUuZiB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgdmFyIG1ldGEgPSBtb2R1bGUuZXhwb3J0cyA9IHsKICAgICAgICAgICAgICAgICAgICBlbmFibGU6IGVuYWJsZSwKICAgICAgICAgICAgICAgICAgICBmYXN0S2V5OiBmYXN0S2V5LAogICAgICAgICAgICAgICAgICAgIGdldFdlYWtEYXRhOiBnZXRXZWFrRGF0YSwKICAgICAgICAgICAgICAgICAgICBvbkZyZWV6ZTogb25GcmVlemUKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBoaWRkZW5LZXlzW01FVEFEQVRBXSA9IHRydWU7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEwNCAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGNsYXNzb2YgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE4KTsKICAgICAgICAgICAgICAgIHZhciB0b0luZGV4ZWRPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1KTsKICAgICAgICAgICAgICAgIHZhciAkZ2V0T3duUHJvcGVydHlOYW1lcyA9IChfX3dfcGRmanNfcmVxdWlyZV9fKDYxKS5mKTsKICAgICAgICAgICAgICAgIHZhciBhcnJheVNsaWNlID0gX193X3BkZmpzX3JlcXVpcmVfXygxMDUpOwogICAgICAgICAgICAgICAgdmFyIHdpbmRvd05hbWVzID0gdHlwZW9mIHdpbmRvdyA9PSAnb2JqZWN0JyAmJiB3aW5kb3cgJiYgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMgPyBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh3aW5kb3cpIDogW107CiAgICAgICAgICAgICAgICB2YXIgZ2V0V2luZG93TmFtZXMgPSBmdW5jdGlvbiAoaXQpIHsKICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGdldE93blByb3BlcnR5TmFtZXMoaXQpOwogICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhcnJheVNsaWNlKHdpbmRvd05hbWVzKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMuZiA9IGZ1bmN0aW9uIGdldE93blByb3BlcnR5TmFtZXMoaXQpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gd2luZG93TmFtZXMgJiYgY2xhc3NvZihpdCkgPT0gJ1dpbmRvdycgPyBnZXRXaW5kb3dOYW1lcyhpdCkgOiAkZ2V0T3duUHJvcGVydHlOYW1lcyh0b0luZGV4ZWRPYmplY3QoaXQpKTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEwNSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHRvQWJzb2x1dGVJbmRleCA9IF9fd19wZGZqc19yZXF1aXJlX18oNjQpOwogICAgICAgICAgICAgICAgdmFyIGxlbmd0aE9mQXJyYXlMaWtlID0gX193X3BkZmpzX3JlcXVpcmVfXyg2Nyk7CiAgICAgICAgICAgICAgICB2YXIgY3JlYXRlUHJvcGVydHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwNik7CiAgICAgICAgICAgICAgICB2YXIgJEFycmF5ID0gQXJyYXk7CiAgICAgICAgICAgICAgICB2YXIgbWF4ID0gTWF0aC5tYXg7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChPLCBzdGFydCwgZW5kKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGxlbmd0aE9mQXJyYXlMaWtlKE8pOwogICAgICAgICAgICAgICAgICAgIHZhciBrID0gdG9BYnNvbHV0ZUluZGV4KHN0YXJ0LCBsZW5ndGgpOwogICAgICAgICAgICAgICAgICAgIHZhciBmaW4gPSB0b0Fic29sdXRlSW5kZXgoZW5kID09PSB1bmRlZmluZWQgPyBsZW5ndGggOiBlbmQsIGxlbmd0aCk7CiAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9ICRBcnJheShtYXgoZmluIC0gaywgMCkpOwogICAgICAgICAgICAgICAgICAgIGZvciAodmFyIG4gPSAwOyBrIDwgZmluOyBrKyssIG4rKykKICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlUHJvcGVydHkocmVzdWx0LCBuLCBPW2tdKTsKICAgICAgICAgICAgICAgICAgICByZXN1bHQubGVuZ3RoID0gbjsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTA2ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgogICAgICAgICAgICAgICAgdmFyIHRvUHJvcGVydHlLZXkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxKTsKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVQcm9wZXJ0eU1vZHVsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNDgpOwogICAgICAgICAgICAgICAgdmFyIGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqZWN0LCBrZXksIHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5S2V5ID0gdG9Qcm9wZXJ0eUtleShrZXkpOwogICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0eUtleSBpbiBvYmplY3QpCiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmluZVByb3BlcnR5TW9kdWxlLmYob2JqZWN0LCBwcm9wZXJ0eUtleSwgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yKDAsIHZhbHVlKSk7CiAgICAgICAgICAgICAgICAgICAgZWxzZQogICAgICAgICAgICAgICAgICAgICAgICBvYmplY3RbcHJvcGVydHlLZXldID0gdmFsdWU7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMDcgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTApOwogICAgICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMyk7CiAgICAgICAgICAgICAgICB2YXIgY2xhc3NvZiA9IF9fd19wZGZqc19yZXF1aXJlX18oMTgpOwogICAgICAgICAgICAgICAgdmFyIEFSUkFZX0JVRkZFUl9OT05fRVhURU5TSUJMRSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTA4KTsKICAgICAgICAgICAgICAgIHZhciAkaXNFeHRlbnNpYmxlID0gT2JqZWN0LmlzRXh0ZW5zaWJsZTsKICAgICAgICAgICAgICAgIHZhciBGQUlMU19PTl9QUklNSVRJVkVTID0gZmFpbHMoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgICRpc0V4dGVuc2libGUoMSk7CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRkFJTFNfT05fUFJJTUlUSVZFUyB8fCBBUlJBWV9CVUZGRVJfTk9OX0VYVEVOU0lCTEUgPyBmdW5jdGlvbiBpc0V4dGVuc2libGUoaXQpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KGl0KSkKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGlmIChBUlJBWV9CVUZGRVJfTk9OX0VYVEVOU0lCTEUgJiYgY2xhc3NvZihpdCkgPT0gJ0FycmF5QnVmZmVyJykKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgIHJldHVybiAkaXNFeHRlbnNpYmxlID8gJGlzRXh0ZW5zaWJsZShpdCkgOiB0cnVlOwogICAgICAgICAgICAgICAgfSA6ICRpc0V4dGVuc2libGU7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEwOCAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGZhaWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMCk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZhaWxzKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIEFycmF5QnVmZmVyID09ICdmdW5jdGlvbicpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcig4KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5pc0V4dGVuc2libGUoYnVmZmVyKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShidWZmZXIsICdhJywgeyB2YWx1ZTogOCB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9KTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTA5ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwKTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gIWZhaWxzKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmlzRXh0ZW5zaWJsZShPYmplY3QucHJldmVudEV4dGVuc2lvbnMoe30pKTsKICAgICAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMTAgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBiaW5kID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTEpOwogICAgICAgICAgICAgICAgdmFyIGNhbGwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExKTsKICAgICAgICAgICAgICAgIHZhciBhbk9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oNTApOwogICAgICAgICAgICAgICAgdmFyIHRyeVRvU3RyaW5nID0gX193X3BkZmpzX3JlcXVpcmVfXygzNSk7CiAgICAgICAgICAgICAgICB2YXIgaXNBcnJheUl0ZXJhdG9yTWV0aG9kID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTMpOwogICAgICAgICAgICAgICAgdmFyIGxlbmd0aE9mQXJyYXlMaWtlID0gX193X3BkZmpzX3JlcXVpcmVfXyg2Nyk7CiAgICAgICAgICAgICAgICB2YXIgaXNQcm90b3R5cGVPZiA9IF9fd19wZGZqc19yZXF1aXJlX18oMjgpOwogICAgICAgICAgICAgICAgdmFyIGdldEl0ZXJhdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTQpOwogICAgICAgICAgICAgICAgdmFyIGdldEl0ZXJhdG9yTWV0aG9kID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTUpOwogICAgICAgICAgICAgICAgdmFyIGl0ZXJhdG9yQ2xvc2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExNik7CiAgICAgICAgICAgICAgICB2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKICAgICAgICAgICAgICAgIHZhciBSZXN1bHQgPSBmdW5jdGlvbiAoc3RvcHBlZCwgcmVzdWx0KSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdG9wcGVkID0gc3RvcHBlZDsKICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc3VsdCA9IHJlc3VsdDsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB2YXIgUmVzdWx0UHJvdG90eXBlID0gUmVzdWx0LnByb3RvdHlwZTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0ZXJhYmxlLCB1bmJvdW5kRnVuY3Rpb24sIG9wdGlvbnMpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgdGhhdCA9IG9wdGlvbnMgJiYgb3B0aW9ucy50aGF0OwogICAgICAgICAgICAgICAgICAgIHZhciBBU19FTlRSSUVTID0gISEob3B0aW9ucyAmJiBvcHRpb25zLkFTX0VOVFJJRVMpOwogICAgICAgICAgICAgICAgICAgIHZhciBJU19SRUNPUkQgPSAhIShvcHRpb25zICYmIG9wdGlvbnMuSVNfUkVDT1JEKTsKICAgICAgICAgICAgICAgICAgICB2YXIgSVNfSVRFUkFUT1IgPSAhIShvcHRpb25zICYmIG9wdGlvbnMuSVNfSVRFUkFUT1IpOwogICAgICAgICAgICAgICAgICAgIHZhciBJTlRFUlJVUFRFRCA9ICEhKG9wdGlvbnMgJiYgb3B0aW9ucy5JTlRFUlJVUFRFRCk7CiAgICAgICAgICAgICAgICAgICAgdmFyIGZuID0gYmluZCh1bmJvdW5kRnVuY3Rpb24sIHRoYXQpOwogICAgICAgICAgICAgICAgICAgIHZhciBpdGVyYXRvciwgaXRlckZuLCBpbmRleCwgbGVuZ3RoLCByZXN1bHQsIG5leHQsIHN0ZXA7CiAgICAgICAgICAgICAgICAgICAgdmFyIHN0b3AgPSBmdW5jdGlvbiAoY29uZGl0aW9uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpdGVyYXRvcikKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZXJhdG9yQ2xvc2UoaXRlcmF0b3IsICdub3JtYWwnLCBjb25kaXRpb24pOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFJlc3VsdCh0cnVlLCBjb25kaXRpb24pOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgdmFyIGNhbGxGbiA9IGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoQVNfRU5UUklFUykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5PYmplY3QodmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIElOVEVSUlVQVEVEID8gZm4odmFsdWVbMF0sIHZhbHVlWzFdLCBzdG9wKSA6IGZuKHZhbHVlWzBdLCB2YWx1ZVsxXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIElOVEVSUlVQVEVEID8gZm4odmFsdWUsIHN0b3ApIDogZm4odmFsdWUpOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgaWYgKElTX1JFQ09SRCkgewogICAgICAgICAgICAgICAgICAgICAgICBpdGVyYXRvciA9IGl0ZXJhYmxlLml0ZXJhdG9yOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoSVNfSVRFUkFUT1IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaXRlcmF0b3IgPSBpdGVyYWJsZTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBpdGVyRm4gPSBnZXRJdGVyYXRvck1ldGhvZChpdGVyYWJsZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaXRlckZuKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgJFR5cGVFcnJvcih0cnlUb1N0cmluZyhpdGVyYWJsZSkgKyAnIGlzIG5vdCBpdGVyYWJsZScpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheUl0ZXJhdG9yTWV0aG9kKGl0ZXJGbikpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaW5kZXggPSAwLCBsZW5ndGggPSBsZW5ndGhPZkFycmF5TGlrZShpdGVyYWJsZSk7IGxlbmd0aCA+IGluZGV4OyBpbmRleCsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gY2FsbEZuKGl0ZXJhYmxlW2luZGV4XSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAmJiBpc1Byb3RvdHlwZU9mKFJlc3VsdFByb3RvdHlwZSwgcmVzdWx0KSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUmVzdWx0KGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpdGVyYXRvciA9IGdldEl0ZXJhdG9yKGl0ZXJhYmxlLCBpdGVyRm4pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBuZXh0ID0gSVNfUkVDT1JEID8gaXRlcmFibGUubmV4dCA6IGl0ZXJhdG9yLm5leHQ7CiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKCEoc3RlcCA9IGNhbGwobmV4dCwgaXRlcmF0b3IpKS5kb25lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBjYWxsRm4oc3RlcC52YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyYXRvckNsb3NlKGl0ZXJhdG9yLCAndGhyb3cnLCBlcnJvcik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiByZXN1bHQgPT0gJ29iamVjdCcgJiYgcmVzdWx0ICYmIGlzUHJvdG90eXBlT2YoUmVzdWx0UHJvdG90eXBlLCByZXN1bHQpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBSZXN1bHQoZmFsc2UpOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTExICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgdW5jdXJyeVRoaXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExMik7CiAgICAgICAgICAgICAgICB2YXIgYUNhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygzNCk7CiAgICAgICAgICAgICAgICB2YXIgTkFUSVZFX0JJTkQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyKTsKICAgICAgICAgICAgICAgIHZhciBiaW5kID0gdW5jdXJyeVRoaXModW5jdXJyeVRoaXMuYmluZCk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChmbiwgdGhhdCkgewogICAgICAgICAgICAgICAgICAgIGFDYWxsYWJsZShmbik7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoYXQgPT09IHVuZGVmaW5lZCA/IGZuIDogTkFUSVZFX0JJTkQgPyBiaW5kKGZuLCB0aGF0KSA6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZuLmFwcGx5KHRoYXQsIGFyZ3VtZW50cyk7CiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDExMiAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGNsYXNzb2ZSYXcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE4KTsKICAgICAgICAgICAgICAgIHZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTcpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZm4pIHsKICAgICAgICAgICAgICAgICAgICBpZiAoY2xhc3NvZlJhdyhmbikgPT09ICdGdW5jdGlvbicpCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB1bmN1cnJ5VGhpcyhmbik7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMTMgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM3KTsKICAgICAgICAgICAgICAgIHZhciBJdGVyYXRvcnMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDkyKTsKICAgICAgICAgICAgICAgIHZhciBJVEVSQVRPUiA9IHdlbGxLbm93blN5bWJvbCgnaXRlcmF0b3InKTsKICAgICAgICAgICAgICAgIHZhciBBcnJheVByb3RvdHlwZSA9IEFycmF5LnByb3RvdHlwZTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGl0ICE9PSB1bmRlZmluZWQgJiYgKEl0ZXJhdG9ycy5BcnJheSA9PT0gaXQgfHwgQXJyYXlQcm90b3R5cGVbSVRFUkFUT1JdID09PSBpdCk7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMTQgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBjYWxsID0gX193X3BkZmpzX3JlcXVpcmVfXygxMSk7CiAgICAgICAgICAgICAgICB2YXIgYUNhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygzNCk7CiAgICAgICAgICAgICAgICB2YXIgYW5PYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDUwKTsKICAgICAgICAgICAgICAgIHZhciB0cnlUb1N0cmluZyA9IF9fd19wZGZqc19yZXF1aXJlX18oMzUpOwogICAgICAgICAgICAgICAgdmFyIGdldEl0ZXJhdG9yTWV0aG9kID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTUpOwogICAgICAgICAgICAgICAgdmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCwgdXNpbmdJdGVyYXRvcikgewogICAgICAgICAgICAgICAgICAgIHZhciBpdGVyYXRvck1ldGhvZCA9IGFyZ3VtZW50cy5sZW5ndGggPCAyID8gZ2V0SXRlcmF0b3JNZXRob2QoYXJndW1lbnQpIDogdXNpbmdJdGVyYXRvcjsKICAgICAgICAgICAgICAgICAgICBpZiAoYUNhbGxhYmxlKGl0ZXJhdG9yTWV0aG9kKSkKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFuT2JqZWN0KGNhbGwoaXRlcmF0b3JNZXRob2QsIGFyZ3VtZW50KSk7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgJFR5cGVFcnJvcih0cnlUb1N0cmluZyhhcmd1bWVudCkgKyAnIGlzIG5vdCBpdGVyYWJsZScpOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTE1ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgY2xhc3NvZiA9IF9fd19wZGZqc19yZXF1aXJlX18oODIpOwogICAgICAgICAgICAgICAgdmFyIGdldE1ldGhvZCA9IF9fd19wZGZqc19yZXF1aXJlX18oMzMpOwogICAgICAgICAgICAgICAgdmFyIGlzTnVsbE9yVW5kZWZpbmVkID0gX193X3BkZmpzX3JlcXVpcmVfXygyMCk7CiAgICAgICAgICAgICAgICB2YXIgSXRlcmF0b3JzID0gX193X3BkZmpzX3JlcXVpcmVfXyg5Mik7CiAgICAgICAgICAgICAgICB2YXIgd2VsbEtub3duU3ltYm9sID0gX193X3BkZmpzX3JlcXVpcmVfXygzNyk7CiAgICAgICAgICAgICAgICB2YXIgSVRFUkFUT1IgPSB3ZWxsS25vd25TeW1ib2woJ2l0ZXJhdG9yJyk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkgewogICAgICAgICAgICAgICAgICAgIGlmICghaXNOdWxsT3JVbmRlZmluZWQoaXQpKQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZ2V0TWV0aG9kKGl0LCBJVEVSQVRPUikgfHwgZ2V0TWV0aG9kKGl0LCAnQEBpdGVyYXRvcicpIHx8IEl0ZXJhdG9yc1tjbGFzc29mKGl0KV07CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMTYgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBjYWxsID0gX193X3BkZmpzX3JlcXVpcmVfXygxMSk7CiAgICAgICAgICAgICAgICB2YXIgYW5PYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDUwKTsKICAgICAgICAgICAgICAgIHZhciBnZXRNZXRob2QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDMzKTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0ZXJhdG9yLCBraW5kLCB2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgIHZhciBpbm5lclJlc3VsdCwgaW5uZXJFcnJvcjsKICAgICAgICAgICAgICAgICAgICBhbk9iamVjdChpdGVyYXRvcik7CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgaW5uZXJSZXN1bHQgPSBnZXRNZXRob2QoaXRlcmF0b3IsICdyZXR1cm4nKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpbm5lclJlc3VsdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGtpbmQgPT09ICd0aHJvdycpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaW5uZXJSZXN1bHQgPSBjYWxsKGlubmVyUmVzdWx0LCBpdGVyYXRvcik7CiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaW5uZXJFcnJvciA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlubmVyUmVzdWx0ID0gZXJyb3I7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChraW5kID09PSAndGhyb3cnKQogICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICBpZiAoaW5uZXJFcnJvcikKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgaW5uZXJSZXN1bHQ7CiAgICAgICAgICAgICAgICAgICAgYW5PYmplY3QoaW5uZXJSZXN1bHQpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDExNyAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGlzUHJvdG90eXBlT2YgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI4KTsKICAgICAgICAgICAgICAgIHZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQsIFByb3RvdHlwZSkgewogICAgICAgICAgICAgICAgICAgIGlmIChpc1Byb3RvdHlwZU9mKFByb3RvdHlwZSwgaXQpKQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXQ7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgJFR5cGVFcnJvcignSW5jb3JyZWN0IGludm9jYXRpb24nKTsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDExOCAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHdlbGxLbm93blN5bWJvbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMzcpOwogICAgICAgICAgICAgICAgdmFyIElURVJBVE9SID0gd2VsbEtub3duU3ltYm9sKCdpdGVyYXRvcicpOwogICAgICAgICAgICAgICAgdmFyIFNBRkVfQ0xPU0lORyA9IGZhbHNlOwogICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICB2YXIgY2FsbGVkID0gMDsKICAgICAgICAgICAgICAgICAgICB2YXIgaXRlcmF0b3JXaXRoUmV0dXJuID0gewogICAgICAgICAgICAgICAgICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4geyBkb25lOiAhIWNhbGxlZCsrIH07CiAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICdyZXR1cm4nOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTQUZFX0NMT1NJTkcgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICBpdGVyYXRvcldpdGhSZXR1cm5bSVRFUkFUT1JdID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpczsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIEFycmF5LmZyb20oaXRlcmF0b3JXaXRoUmV0dXJuLCBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IDI7CiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZXhlYywgU0tJUF9DTE9TSU5HKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFTS0lQX0NMT1NJTkcgJiYgIVNBRkVfQ0xPU0lORykKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgIHZhciBJVEVSQVRJT05fU1VQUE9SVCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTsKICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0W0lURVJBVE9SXSA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4geyBkb25lOiBJVEVSQVRJT05fU1VQUE9SVCA9IHRydWUgfTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICBleGVjKG9iamVjdCk7CiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIElURVJBVElPTl9TVVBQT1JUOwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTE5ICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgaXNDYWxsYWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjQpOwogICAgICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMyk7CiAgICAgICAgICAgICAgICB2YXIgc2V0UHJvdG90eXBlT2YgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDg3KTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCR0aGlzLCBkdW1teSwgV3JhcHBlcikgewogICAgICAgICAgICAgICAgICAgIHZhciBOZXdUYXJnZXQsIE5ld1RhcmdldFByb3RvdHlwZTsKICAgICAgICAgICAgICAgICAgICBpZiAoc2V0UHJvdG90eXBlT2YgJiYgaXNDYWxsYWJsZShOZXdUYXJnZXQgPSBkdW1teS5jb25zdHJ1Y3RvcikgJiYgTmV3VGFyZ2V0ICE9PSBXcmFwcGVyICYmIGlzT2JqZWN0KE5ld1RhcmdldFByb3RvdHlwZSA9IE5ld1RhcmdldC5wcm90b3R5cGUpICYmIE5ld1RhcmdldFByb3RvdHlwZSAhPT0gV3JhcHBlci5wcm90b3R5cGUpCiAgICAgICAgICAgICAgICAgICAgICAgIHNldFByb3RvdHlwZU9mKCR0aGlzLCBOZXdUYXJnZXRQcm90b3R5cGUpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiAkdGhpczsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEyMCAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKICAgICAgICAgICAgICAgIHZhciBjcmVhdGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDczKTsKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVCdWlsdEluQWNjZXNzb3IgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDg0KTsKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVCdWlsdElucyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTIxKTsKICAgICAgICAgICAgICAgIHZhciBiaW5kID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTEpOwogICAgICAgICAgICAgICAgdmFyIGFuSW5zdGFuY2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExNyk7CiAgICAgICAgICAgICAgICB2YXIgaXNOdWxsT3JVbmRlZmluZWQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIwKTsKICAgICAgICAgICAgICAgIHZhciBpdGVyYXRlID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTApOwogICAgICAgICAgICAgICAgdmFyIGRlZmluZUl0ZXJhdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXyg5Myk7CiAgICAgICAgICAgICAgICB2YXIgY3JlYXRlSXRlclJlc3VsdE9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oOTcpOwogICAgICAgICAgICAgICAgdmFyIHNldFNwZWNpZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyMik7CiAgICAgICAgICAgICAgICB2YXIgREVTQ1JJUFRPUlMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDkpOwogICAgICAgICAgICAgICAgdmFyIGZhc3RLZXkgPSAoX193X3BkZmpzX3JlcXVpcmVfXygxMDMpLmZhc3RLZXkpOwogICAgICAgICAgICAgICAgdmFyIEludGVybmFsU3RhdGVNb2R1bGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDU1KTsKICAgICAgICAgICAgICAgIHZhciBzZXRJbnRlcm5hbFN0YXRlID0gSW50ZXJuYWxTdGF0ZU1vZHVsZS5zZXQ7CiAgICAgICAgICAgICAgICB2YXIgaW50ZXJuYWxTdGF0ZUdldHRlckZvciA9IEludGVybmFsU3RhdGVNb2R1bGUuZ2V0dGVyRm9yOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7CiAgICAgICAgICAgICAgICAgICAgZ2V0Q29uc3RydWN0b3I6IGZ1bmN0aW9uICh3cmFwcGVyLCBDT05TVFJVQ1RPUl9OQU1FLCBJU19NQVAsIEFEREVSKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBDb25zdHJ1Y3RvciA9IHdyYXBwZXIoZnVuY3Rpb24gKHRoYXQsIGl0ZXJhYmxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbkluc3RhbmNlKHRoYXQsIFByb3RvdHlwZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRJbnRlcm5hbFN0YXRlKHRoYXQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBDT05TVFJVQ1RPUl9OQU1FLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4OiBjcmVhdGUobnVsbCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlyc3Q6IHVuZGVmaW5lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0OiB1bmRlZmluZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZTogMAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIURFU0NSSVBUT1JTKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQuc2l6ZSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKGl0ZXJhYmxlKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVyYXRlKGl0ZXJhYmxlLCB0aGF0W0FEREVSXSwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGF0OiB0aGF0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBU19FTlRSSUVTOiBJU19NQVAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBQcm90b3R5cGUgPSBDb25zdHJ1Y3Rvci5wcm90b3R5cGU7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBnZXRJbnRlcm5hbFN0YXRlID0gaW50ZXJuYWxTdGF0ZUdldHRlckZvcihDT05TVFJVQ1RPUl9OQU1FKTsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRlZmluZSA9IGZ1bmN0aW9uICh0aGF0LCBrZXksIHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgc3RhdGUgPSBnZXRJbnRlcm5hbFN0YXRlKHRoYXQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVudHJ5ID0gZ2V0RW50cnkodGhhdCwga2V5KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91cywgaW5kZXg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZW50cnkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnRyeS52YWx1ZSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5sYXN0ID0gZW50cnkgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4OiBpbmRleCA9IGZhc3RLZXkoa2V5LCB0cnVlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5OiBrZXksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXM6IHByZXZpb3VzID0gc3RhdGUubGFzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dDogdW5kZWZpbmVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVkOiBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzdGF0ZS5maXJzdCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuZmlyc3QgPSBlbnRyeTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzLm5leHQgPSBlbnRyeTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoREVTQ1JJUFRPUlMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLnNpemUrKzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQuc2l6ZSsrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gJ0YnKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5pbmRleFtpbmRleF0gPSBlbnRyeTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGF0OwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgZ2V0RW50cnkgPSBmdW5jdGlvbiAodGhhdCwga2V5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgc3RhdGUgPSBnZXRJbnRlcm5hbFN0YXRlKHRoYXQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gZmFzdEtleShrZXkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVudHJ5OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSAnRicpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0YXRlLmluZGV4W2luZGV4XTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoZW50cnkgPSBzdGF0ZS5maXJzdDsgZW50cnk7IGVudHJ5ID0gZW50cnkubmV4dCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbnRyeS5rZXkgPT0ga2V5KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZW50cnk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmluZUJ1aWx0SW5zKFByb3RvdHlwZSwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXI6IGZ1bmN0aW9uIGNsZWFyKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpczsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgc3RhdGUgPSBnZXRJbnRlcm5hbFN0YXRlKHRoYXQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkYXRhID0gc3RhdGUuaW5kZXg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVudHJ5ID0gc3RhdGUuZmlyc3Q7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGVudHJ5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudHJ5LnJlbW92ZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZW50cnkucHJldmlvdXMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnRyeS5wcmV2aW91cyA9IGVudHJ5LnByZXZpb3VzLm5leHQgPSB1bmRlZmluZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBkYXRhW2VudHJ5LmluZGV4XTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW50cnkgPSBlbnRyeS5uZXh0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5maXJzdCA9IHN0YXRlLmxhc3QgPSB1bmRlZmluZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKERFU0NSSVBUT1JTKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5zaXplID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQuc2l6ZSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2RlbGV0ZSc6IGZ1bmN0aW9uIChrZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHN0YXRlID0gZ2V0SW50ZXJuYWxTdGF0ZSh0aGF0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgZW50cnkgPSBnZXRFbnRyeSh0aGF0LCBrZXkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbnRyeSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dCA9IGVudHJ5Lm5leHQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcmV2ID0gZW50cnkucHJldmlvdXM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzdGF0ZS5pbmRleFtlbnRyeS5pbmRleF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudHJ5LnJlbW92ZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJldikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXYubmV4dCA9IG5leHQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuZXh0KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dC5wcmV2aW91cyA9IHByZXY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZS5maXJzdCA9PSBlbnRyeSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLmZpcnN0ID0gbmV4dDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLmxhc3QgPT0gZW50cnkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5sYXN0ID0gcHJldjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKERFU0NSSVBUT1JTKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUuc2l6ZS0tOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGF0LnNpemUtLTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEhZW50cnk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yRWFjaDogZnVuY3Rpb24gZm9yRWFjaChjYWxsYmFja2ZuKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHN0YXRlID0gZ2V0SW50ZXJuYWxTdGF0ZSh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgYm91bmRGdW5jdGlvbiA9IGJpbmQoY2FsbGJhY2tmbiwgYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBhcmd1bWVudHNbMV0gOiB1bmRlZmluZWQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbnRyeTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoZW50cnkgPSBlbnRyeSA/IGVudHJ5Lm5leHQgOiBzdGF0ZS5maXJzdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib3VuZEZ1bmN0aW9uKGVudHJ5LnZhbHVlLCBlbnRyeS5rZXksIHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoZW50cnkgJiYgZW50cnkucmVtb3ZlZCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudHJ5ID0gZW50cnkucHJldmlvdXM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhczogZnVuY3Rpb24gaGFzKGtleSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhIWdldEVudHJ5KHRoaXMsIGtleSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBkZWZpbmVCdWlsdElucyhQcm90b3R5cGUsIElTX01BUCA/IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KGtleSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbnRyeSA9IGdldEVudHJ5KHRoaXMsIGtleSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVudHJ5ICYmIGVudHJ5LnZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldDogZnVuY3Rpb24gc2V0KGtleSwgdmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGVmaW5lKHRoaXMsIGtleSA9PT0gMCA/IDAgOiBrZXksIHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSA6IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZDogZnVuY3Rpb24gYWRkKHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRlZmluZSh0aGlzLCB2YWx1ZSA9IHZhbHVlID09PSAwID8gMCA6IHZhbHVlLCB2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoREVTQ1JJUFRPUlMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZpbmVCdWlsdEluQWNjZXNzb3IoUHJvdG90eXBlLCAnc2l6ZScsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBnZXRJbnRlcm5hbFN0YXRlKHRoaXMpLnNpemU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBDb25zdHJ1Y3RvcjsKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIHNldFN0cm9uZzogZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBDT05TVFJVQ1RPUl9OQU1FLCBJU19NQVApIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIElURVJBVE9SX05BTUUgPSBDT05TVFJVQ1RPUl9OQU1FICsgJyBJdGVyYXRvcic7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBnZXRJbnRlcm5hbENvbGxlY3Rpb25TdGF0ZSA9IGludGVybmFsU3RhdGVHZXR0ZXJGb3IoQ09OU1RSVUNUT1JfTkFNRSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBnZXRJbnRlcm5hbEl0ZXJhdG9yU3RhdGUgPSBpbnRlcm5hbFN0YXRlR2V0dGVyRm9yKElURVJBVE9SX05BTUUpOwogICAgICAgICAgICAgICAgICAgICAgICBkZWZpbmVJdGVyYXRvcihDb25zdHJ1Y3RvciwgQ09OU1RSVUNUT1JfTkFNRSwgZnVuY3Rpb24gKGl0ZXJhdGVkLCBraW5kKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRJbnRlcm5hbFN0YXRlKHRoaXMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBJVEVSQVRPUl9OQU1FLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldDogaXRlcmF0ZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGU6IGdldEludGVybmFsQ29sbGVjdGlvblN0YXRlKGl0ZXJhdGVkKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBraW5kOiBraW5kLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3Q6IHVuZGVmaW5lZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0sIGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBzdGF0ZSA9IGdldEludGVybmFsSXRlcmF0b3JTdGF0ZSh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBraW5kID0gc3RhdGUua2luZDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbnRyeSA9IHN0YXRlLmxhc3Q7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoZW50cnkgJiYgZW50cnkucmVtb3ZlZCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnRyeSA9IGVudHJ5LnByZXZpb3VzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzdGF0ZS50YXJnZXQgfHwgIShzdGF0ZS5sYXN0ID0gZW50cnkgPSBlbnRyeSA/IGVudHJ5Lm5leHQgOiBzdGF0ZS5zdGF0ZS5maXJzdCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS50YXJnZXQgPSB1bmRlZmluZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZUl0ZXJSZXN1bHRPYmplY3QodW5kZWZpbmVkLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChraW5kID09ICdrZXlzJykKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3JlYXRlSXRlclJlc3VsdE9iamVjdChlbnRyeS5rZXksIGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChraW5kID09ICd2YWx1ZXMnKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjcmVhdGVJdGVyUmVzdWx0T2JqZWN0KGVudHJ5LnZhbHVlLCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3JlYXRlSXRlclJlc3VsdE9iamVjdChbCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW50cnkua2V5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudHJ5LnZhbHVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBdLCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0sIElTX01BUCA/ICdlbnRyaWVzJyA6ICd2YWx1ZXMnLCAhSVNfTUFQLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgc2V0U3BlY2llcyhDT05TVFJVQ1RPUl9OQU1FKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMjEgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVCdWlsdEluID0gX193X3BkZmpzX3JlcXVpcmVfXyg1MSk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh0YXJnZXQsIHNyYywgb3B0aW9ucykgewogICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBzcmMpCiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmluZUJ1aWx0SW4odGFyZ2V0LCBrZXksIHNyY1trZXldLCBvcHRpb25zKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGFyZ2V0OwogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTIyICovCiAgICAgICAgICAgIC8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgogICAgICAgICAgICAgICAgdmFyIGdldEJ1aWx0SW4gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI3KTsKICAgICAgICAgICAgICAgIHZhciBkZWZpbmVCdWlsdEluQWNjZXNzb3IgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDg0KTsKICAgICAgICAgICAgICAgIHZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM3KTsKICAgICAgICAgICAgICAgIHZhciBERVNDUklQVE9SUyA9IF9fd19wZGZqc19yZXF1aXJlX18oOSk7CiAgICAgICAgICAgICAgICB2YXIgU1BFQ0lFUyA9IHdlbGxLbm93blN5bWJvbCgnc3BlY2llcycpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoQ09OU1RSVUNUT1JfTkFNRSkgewogICAgICAgICAgICAgICAgICAgIHZhciBDb25zdHJ1Y3RvciA9IGdldEJ1aWx0SW4oQ09OU1RSVUNUT1JfTkFNRSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKERFU0NSSVBUT1JTICYmIENvbnN0cnVjdG9yICYmICFDb25zdHJ1Y3RvcltTUEVDSUVTXSkgewogICAgICAgICAgICAgICAgICAgICAgICBkZWZpbmVCdWlsdEluQWNjZXNzb3IoQ29uc3RydWN0b3IsIFNQRUNJRVMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMjMgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgX193X3BkZmpzX3JlcXVpcmVfXygxMjQpOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMjQgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKICAgICAgICAgICAgICAgIHZhciBjb2xsZWN0aW9uID0gX193X3BkZmpzX3JlcXVpcmVfXygxMDIpOwogICAgICAgICAgICAgICAgdmFyIGNvbGxlY3Rpb25TdHJvbmcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyMCk7CiAgICAgICAgICAgICAgICBjb2xsZWN0aW9uKCdTZXQnLCBmdW5jdGlvbiAoaW5pdCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBTZXQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbml0KHRoaXMsIGFyZ3VtZW50cy5sZW5ndGggPyBhcmd1bWVudHNbMF0gOiB1bmRlZmluZWQpOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB9LCBjb2xsZWN0aW9uU3Ryb25nKTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTI1ICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBJU19QVVJFID0gX193X3BkZmpzX3JlcXVpcmVfXygzOSk7CiAgICAgICAgICAgICAgICB2YXIgJCA9IF9fd19wZGZqc19yZXF1aXJlX18oNik7CiAgICAgICAgICAgICAgICB2YXIgZ2xvYmFsID0gX193X3BkZmpzX3JlcXVpcmVfXyg3KTsKICAgICAgICAgICAgICAgIHZhciBnZXRCdWlsdGluID0gX193X3BkZmpzX3JlcXVpcmVfXygyNyk7CiAgICAgICAgICAgICAgICB2YXIgdW5jdXJyeVRoaXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE3KTsKICAgICAgICAgICAgICAgIHZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTApOwogICAgICAgICAgICAgICAgdmFyIHVpZCA9IF9fd19wZGZqc19yZXF1aXJlX18oNDQpOwogICAgICAgICAgICAgICAgdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI0KTsKICAgICAgICAgICAgICAgIHZhciBpc0NvbnN0cnVjdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXygxMjYpOwogICAgICAgICAgICAgICAgdmFyIGlzTnVsbE9yVW5kZWZpbmVkID0gX193X3BkZmpzX3JlcXVpcmVfXygyMCk7CiAgICAgICAgICAgICAgICB2YXIgaXNPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIzKTsKICAgICAgICAgICAgICAgIHZhciBpc1N5bWJvbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjYpOwogICAgICAgICAgICAgICAgdmFyIGl0ZXJhdGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExMCk7CiAgICAgICAgICAgICAgICB2YXIgYW5PYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDUwKTsKICAgICAgICAgICAgICAgIHZhciBjbGFzc29mID0gX193X3BkZmpzX3JlcXVpcmVfXyg4Mik7CiAgICAgICAgICAgICAgICB2YXIgaGFzT3duID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Mik7CiAgICAgICAgICAgICAgICB2YXIgY3JlYXRlUHJvcGVydHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwNik7CiAgICAgICAgICAgICAgICB2YXIgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5ID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Nyk7CiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoT2ZBcnJheUxpa2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDY3KTsKICAgICAgICAgICAgICAgIHZhciB2YWxpZGF0ZUFyZ3VtZW50c0xlbmd0aCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTI3KTsKICAgICAgICAgICAgICAgIHZhciBnZXRSZWdFeHBGbGFncyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTI4KTsKICAgICAgICAgICAgICAgIHZhciBNYXBIZWxwZXJzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzApOwogICAgICAgICAgICAgICAgdmFyIFNldEhlbHBlcnMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzMSk7CiAgICAgICAgICAgICAgICB2YXIgRVJST1JfU1RBQ0tfSU5TVEFMTEFCTEUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzMik7CiAgICAgICAgICAgICAgICB2YXIgUFJPUEVSX1RSQU5TRkVSID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzMpOwogICAgICAgICAgICAgICAgdmFyIE9iamVjdCA9IGdsb2JhbC5PYmplY3Q7CiAgICAgICAgICAgICAgICB2YXIgQXJyYXkgPSBnbG9iYWwuQXJyYXk7CiAgICAgICAgICAgICAgICB2YXIgRGF0ZSA9IGdsb2JhbC5EYXRlOwogICAgICAgICAgICAgICAgdmFyIEVycm9yID0gZ2xvYmFsLkVycm9yOwogICAgICAgICAgICAgICAgdmFyIEV2YWxFcnJvciA9IGdsb2JhbC5FdmFsRXJyb3I7CiAgICAgICAgICAgICAgICB2YXIgUmFuZ2VFcnJvciA9IGdsb2JhbC5SYW5nZUVycm9yOwogICAgICAgICAgICAgICAgdmFyIFJlZmVyZW5jZUVycm9yID0gZ2xvYmFsLlJlZmVyZW5jZUVycm9yOwogICAgICAgICAgICAgICAgdmFyIFN5bnRheEVycm9yID0gZ2xvYmFsLlN5bnRheEVycm9yOwogICAgICAgICAgICAgICAgdmFyIFR5cGVFcnJvciA9IGdsb2JhbC5UeXBlRXJyb3I7CiAgICAgICAgICAgICAgICB2YXIgVVJJRXJyb3IgPSBnbG9iYWwuVVJJRXJyb3I7CiAgICAgICAgICAgICAgICB2YXIgUGVyZm9ybWFuY2VNYXJrID0gZ2xvYmFsLlBlcmZvcm1hbmNlTWFyazsKICAgICAgICAgICAgICAgIHZhciBXZWJBc3NlbWJseSA9IGdsb2JhbC5XZWJBc3NlbWJseTsKICAgICAgICAgICAgICAgIHZhciBDb21waWxlRXJyb3IgPSBXZWJBc3NlbWJseSAmJiBXZWJBc3NlbWJseS5Db21waWxlRXJyb3IgfHwgRXJyb3I7CiAgICAgICAgICAgICAgICB2YXIgTGlua0Vycm9yID0gV2ViQXNzZW1ibHkgJiYgV2ViQXNzZW1ibHkuTGlua0Vycm9yIHx8IEVycm9yOwogICAgICAgICAgICAgICAgdmFyIFJ1bnRpbWVFcnJvciA9IFdlYkFzc2VtYmx5ICYmIFdlYkFzc2VtYmx5LlJ1bnRpbWVFcnJvciB8fCBFcnJvcjsKICAgICAgICAgICAgICAgIHZhciBET01FeGNlcHRpb24gPSBnZXRCdWlsdGluKCdET01FeGNlcHRpb24nKTsKICAgICAgICAgICAgICAgIHZhciBNYXAgPSBNYXBIZWxwZXJzLk1hcDsKICAgICAgICAgICAgICAgIHZhciBtYXBIYXMgPSBNYXBIZWxwZXJzLmhhczsKICAgICAgICAgICAgICAgIHZhciBtYXBHZXQgPSBNYXBIZWxwZXJzLmdldDsKICAgICAgICAgICAgICAgIHZhciBtYXBTZXQgPSBNYXBIZWxwZXJzLnNldDsKICAgICAgICAgICAgICAgIHZhciBTZXQgPSBTZXRIZWxwZXJzLlNldDsKICAgICAgICAgICAgICAgIHZhciBzZXRBZGQgPSBTZXRIZWxwZXJzLmFkZDsKICAgICAgICAgICAgICAgIHZhciBvYmplY3RLZXlzID0gZ2V0QnVpbHRpbignT2JqZWN0JywgJ2tleXMnKTsKICAgICAgICAgICAgICAgIHZhciBwdXNoID0gdW5jdXJyeVRoaXMoW10ucHVzaCk7CiAgICAgICAgICAgICAgICB2YXIgdGhpc0Jvb2xlYW5WYWx1ZSA9IHVuY3VycnlUaGlzKHRydWUudmFsdWVPZik7CiAgICAgICAgICAgICAgICB2YXIgdGhpc051bWJlclZhbHVlID0gdW5jdXJyeVRoaXMoMS4wLnZhbHVlT2YpOwogICAgICAgICAgICAgICAgdmFyIHRoaXNTdHJpbmdWYWx1ZSA9IHVuY3VycnlUaGlzKCcnLnZhbHVlT2YpOwogICAgICAgICAgICAgICAgdmFyIHRoaXNUaW1lVmFsdWUgPSB1bmN1cnJ5VGhpcyhEYXRlLnByb3RvdHlwZS5nZXRUaW1lKTsKICAgICAgICAgICAgICAgIHZhciBQRVJGT1JNQU5DRV9NQVJLID0gdWlkKCdzdHJ1Y3R1cmVkQ2xvbmUnKTsKICAgICAgICAgICAgICAgIHZhciBEQVRBX0NMT05FX0VSUk9SID0gJ0RhdGFDbG9uZUVycm9yJzsKICAgICAgICAgICAgICAgIHZhciBUUkFOU0ZFUlJJTkcgPSAnVHJhbnNmZXJyaW5nJzsKICAgICAgICAgICAgICAgIHZhciBjaGVja0Jhc2ljU2VtYW50aWMgPSBmdW5jdGlvbiAoc3RydWN0dXJlZENsb25lSW1wbGVtZW50YXRpb24pIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gIWZhaWxzKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHNldDEgPSBuZXcgZ2xvYmFsLlNldChbN10pOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgc2V0MiA9IHN0cnVjdHVyZWRDbG9uZUltcGxlbWVudGF0aW9uKHNldDEpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgbnVtYmVyID0gc3RydWN0dXJlZENsb25lSW1wbGVtZW50YXRpb24oT2JqZWN0KDcpKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNldDIgPT0gc2V0MSB8fCAhc2V0Mi5oYXMoNykgfHwgdHlwZW9mIG51bWJlciAhPSAnb2JqZWN0JyB8fCBudW1iZXIgIT0gNzsKICAgICAgICAgICAgICAgICAgICB9KSAmJiBzdHJ1Y3R1cmVkQ2xvbmVJbXBsZW1lbnRhdGlvbjsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB2YXIgY2hlY2tFcnJvcnNDbG9uaW5nID0gZnVuY3Rpb24gKHN0cnVjdHVyZWRDbG9uZUltcGxlbWVudGF0aW9uLCAkRXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gIWZhaWxzKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gbmV3ICRFcnJvcigpOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGVzdCA9IHN0cnVjdHVyZWRDbG9uZUltcGxlbWVudGF0aW9uKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGE6IGVycm9yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYjogZXJyb3IKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhKHRlc3QgJiYgdGVzdC5hID09PSB0ZXN0LmIgJiYgdGVzdC5hIGluc3RhbmNlb2YgJEVycm9yICYmIHRlc3QuYS5zdGFjayA9PT0gZXJyb3Iuc3RhY2spOwogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciBjaGVja05ld0Vycm9yc0Nsb25pbmdTZW1hbnRpYyA9IGZ1bmN0aW9uIChzdHJ1Y3R1cmVkQ2xvbmVJbXBsZW1lbnRhdGlvbikgewogICAgICAgICAgICAgICAgICAgIHJldHVybiAhZmFpbHMoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGVzdCA9IHN0cnVjdHVyZWRDbG9uZUltcGxlbWVudGF0aW9uKG5ldyBnbG9iYWwuQWdncmVnYXRlRXJyb3IoWzFdLCBQRVJGT1JNQU5DRV9NQVJLLCB7IGNhdXNlOiAzIH0pKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRlc3QubmFtZSAhPSAnQWdncmVnYXRlRXJyb3InIHx8IHRlc3QuZXJyb3JzWzBdICE9IDEgfHwgdGVzdC5tZXNzYWdlICE9IFBFUkZPUk1BTkNFX01BUksgfHwgdGVzdC5jYXVzZSAhPSAzOwogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciBuYXRpdmVTdHJ1Y3R1cmVkQ2xvbmUgPSBnbG9iYWwuc3RydWN0dXJlZENsb25lOwogICAgICAgICAgICAgICAgdmFyIEZPUkNFRF9SRVBMQUNFTUVOVCA9IElTX1BVUkUgfHwgIWNoZWNrRXJyb3JzQ2xvbmluZyhuYXRpdmVTdHJ1Y3R1cmVkQ2xvbmUsIEVycm9yKSB8fCAhY2hlY2tFcnJvcnNDbG9uaW5nKG5hdGl2ZVN0cnVjdHVyZWRDbG9uZSwgRE9NRXhjZXB0aW9uKSB8fCAhY2hlY2tOZXdFcnJvcnNDbG9uaW5nU2VtYW50aWMobmF0aXZlU3RydWN0dXJlZENsb25lKTsKICAgICAgICAgICAgICAgIHZhciBzdHJ1Y3R1cmVkQ2xvbmVGcm9tTWFyayA9ICFuYXRpdmVTdHJ1Y3R1cmVkQ2xvbmUgJiYgY2hlY2tCYXNpY1NlbWFudGljKGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUGVyZm9ybWFuY2VNYXJrKFBFUkZPUk1BTkNFX01BUkssIHsgZGV0YWlsOiB2YWx1ZSB9KS5kZXRhaWw7CiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIHZhciBuYXRpdmVSZXN0cmljdGVkU3RydWN0dXJlZENsb25lID0gY2hlY2tCYXNpY1NlbWFudGljKG5hdGl2ZVN0cnVjdHVyZWRDbG9uZSkgfHwgc3RydWN0dXJlZENsb25lRnJvbU1hcms7CiAgICAgICAgICAgICAgICB2YXIgdGhyb3dVbmNsb25lYWJsZSA9IGZ1bmN0aW9uICh0eXBlKSB7CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IERPTUV4Y2VwdGlvbignVW5jbG9uZWFibGUgdHlwZTogJyArIHR5cGUsIERBVEFfQ0xPTkVfRVJST1IpOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciB0aHJvd1VucG9seWZpbGxhYmxlID0gZnVuY3Rpb24gKHR5cGUsIGFjdGlvbikgewogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oKGFjdGlvbiB8fCAnQ2xvbmluZycpICsgJyBvZiAnICsgdHlwZSArICcgY2Fubm90IGJlIHByb3Blcmx5IHBvbHlmaWxsZWQgaW4gdGhpcyBlbmdpbmUnLCBEQVRBX0NMT05FX0VSUk9SKTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB2YXIgY3JlYXRlRGF0YVRyYW5zZmVyID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHZhciBkYXRhVHJhbnNmZXI7CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVRyYW5zZmVyID0gbmV3IGdsb2JhbC5EYXRhVHJhbnNmZXIoKTsKICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVRyYW5zZmVyID0gbmV3IGdsb2JhbC5DbGlwYm9hcmRFdmVudCgnJykuY2xpcGJvYXJkRGF0YTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRhdGFUcmFuc2ZlciAmJiBkYXRhVHJhbnNmZXIuaXRlbXMgJiYgZGF0YVRyYW5zZmVyLmZpbGVzID8gZGF0YVRyYW5zZmVyIDogbnVsbDsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB2YXIgc3RydWN0dXJlZENsb25lSW50ZXJuYWwgPSBmdW5jdGlvbiAodmFsdWUsIG1hcCkgewogICAgICAgICAgICAgICAgICAgIGlmIChpc1N5bWJvbCh2YWx1ZSkpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93VW5jbG9uZWFibGUoJ1N5bWJvbCcpOwogICAgICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3QodmFsdWUpKQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgaWYgKG1hcCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAobWFwSGFzKG1hcCwgdmFsdWUpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hcEdldChtYXAsIHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgbWFwID0gbmV3IE1hcCgpOwogICAgICAgICAgICAgICAgICAgIHZhciB0eXBlID0gY2xhc3NvZih2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgdmFyIGRlZXAgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB2YXIgQywgbmFtZSwgY2xvbmVkLCBkYXRhVHJhbnNmZXIsIGksIGxlbmd0aCwga2V5cywga2V5LCBzb3VyY2UsIHRhcmdldCwgb3B0aW9uczsKICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnQXJyYXknOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gQXJyYXkobGVuZ3RoT2ZBcnJheUxpa2UodmFsdWUpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZXAgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ09iamVjdCc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSB7fTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZXAgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ01hcCc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSBuZXcgTWFwKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWVwID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdTZXQnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gbmV3IFNldCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVlcCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnUmVnRXhwJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZCA9IG5ldyBSZWdFeHAodmFsdWUuc291cmNlLCBnZXRSZWdFeHBGbGFncyh2YWx1ZSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0Vycm9yJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSB2YWx1ZS5uYW1lOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChuYW1lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnQWdncmVnYXRlRXJyb3InOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSBnZXRCdWlsdGluKCdBZ2dyZWdhdGVFcnJvcicpKFtdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnRXZhbEVycm9yJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gRXZhbEVycm9yKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ1JhbmdlRXJyb3InOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSBSYW5nZUVycm9yKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ1JlZmVyZW5jZUVycm9yJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gUmVmZXJlbmNlRXJyb3IoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnU3ludGF4RXJyb3InOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSBTeW50YXhFcnJvcigpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdUeXBlRXJyb3InOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSBUeXBlRXJyb3IoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnVVJJRXJyb3InOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSBVUklFcnJvcigpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdDb21waWxlRXJyb3InOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSBDb21waWxlRXJyb3IoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnTGlua0Vycm9yJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gTGlua0Vycm9yKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ1J1bnRpbWVFcnJvcic6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZCA9IFJ1bnRpbWVFcnJvcigpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSBFcnJvcigpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVlcCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnRE9NRXhjZXB0aW9uJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZCA9IG5ldyBET01FeGNlcHRpb24odmFsdWUubWVzc2FnZSwgdmFsdWUubmFtZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWVwID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdEYXRhVmlldyc6CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0ludDhBcnJheSc6CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ1VpbnQ4QXJyYXknOgogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdVaW50OENsYW1wZWRBcnJheSc6CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0ludDE2QXJyYXknOgogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdVaW50MTZBcnJheSc6CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0ludDMyQXJyYXknOgogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdVaW50MzJBcnJheSc6CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0Zsb2F0MzJBcnJheSc6CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0Zsb2F0NjRBcnJheSc6CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0JpZ0ludDY0QXJyYXknOgogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdCaWdVaW50NjRBcnJheSc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBDID0gZ2xvYmFsW3R5cGVdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChDKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd1VucG9seWZpbGxhYmxlKHR5cGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gbmV3IEMoc3RydWN0dXJlZENsb25lSW50ZXJuYWwodmFsdWUuYnVmZmVyLCBtYXApLCB2YWx1ZS5ieXRlT2Zmc2V0LCB0eXBlID09PSAnRGF0YVZpZXcnID8gdmFsdWUuYnl0ZUxlbmd0aCA6IHZhbHVlLmxlbmd0aCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnRE9NUXVhZCc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZCA9IG5ldyBET01RdWFkKHN0cnVjdHVyZWRDbG9uZUludGVybmFsKHZhbHVlLnAxLCBtYXApLCBzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbCh2YWx1ZS5wMiwgbWFwKSwgc3RydWN0dXJlZENsb25lSW50ZXJuYWwodmFsdWUucDMsIG1hcCksIHN0cnVjdHVyZWRDbG9uZUludGVybmFsKHZhbHVlLnA0LCBtYXApKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5hdGl2ZVJlc3RyaWN0ZWRTdHJ1Y3R1cmVkQ2xvbmUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gbmF0aXZlUmVzdHJpY3RlZFN0cnVjdHVyZWRDbG9uZSh2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93VW5wb2x5ZmlsbGFibGUodHlwZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnRmlsZUxpc3QnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVRyYW5zZmVyID0gY3JlYXRlRGF0YVRyYW5zZmVyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YVRyYW5zZmVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuZ3RoID0gbGVuZ3RoT2ZBcnJheUxpa2UodmFsdWUpOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVRyYW5zZmVyLml0ZW1zLmFkZChzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbCh2YWx1ZVtpXSwgbWFwKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZCA9IGRhdGFUcmFuc2Zlci5maWxlczsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobmF0aXZlUmVzdHJpY3RlZFN0cnVjdHVyZWRDbG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZCA9IG5hdGl2ZVJlc3RyaWN0ZWRTdHJ1Y3R1cmVkQ2xvbmUodmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdJbWFnZURhdGEnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSBuZXcgSW1hZ2VEYXRhKHN0cnVjdHVyZWRDbG9uZUludGVybmFsKHZhbHVlLmRhdGEsIG1hcCksIHZhbHVlLndpZHRoLCB2YWx1ZS5oZWlnaHQsIHsgY29sb3JTcGFjZTogdmFsdWUuY29sb3JTcGFjZSB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5hdGl2ZVJlc3RyaWN0ZWRTdHJ1Y3R1cmVkQ2xvbmUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gbmF0aXZlUmVzdHJpY3RlZFN0cnVjdHVyZWRDbG9uZSh2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93VW5wb2x5ZmlsbGFibGUodHlwZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuYXRpdmVSZXN0cmljdGVkU3RydWN0dXJlZENsb25lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gbmF0aXZlUmVzdHJpY3RlZFN0cnVjdHVyZWRDbG9uZSh2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnQmlnSW50JzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZCA9IE9iamVjdCh2YWx1ZS52YWx1ZU9mKCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0Jvb2xlYW4nOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gT2JqZWN0KHRoaXNCb29sZWFuVmFsdWUodmFsdWUpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdOdW1iZXInOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gT2JqZWN0KHRoaXNOdW1iZXJWYWx1ZSh2YWx1ZSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ1N0cmluZyc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSBPYmplY3QodGhpc1N0cmluZ1ZhbHVlKHZhbHVlKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnRGF0ZSc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSBuZXcgRGF0ZSh0aGlzVGltZVZhbHVlKHZhbHVlKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnQXJyYXlCdWZmZXInOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQyA9IGdsb2JhbC5EYXRhVmlldzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghQyAmJiB0eXBlb2YgdmFsdWUuc2xpY2UgIT0gJ2Z1bmN0aW9uJykKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd1VucG9seWZpbGxhYmxlKHR5cGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlLnNsaWNlID09ICdmdW5jdGlvbicgJiYgIXZhbHVlLnJlc2l6YWJsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSB2YWx1ZS5zbGljZSgwKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGggPSB2YWx1ZS5ieXRlTGVuZ3RoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0gJ21heEJ5dGVMZW5ndGgnIGluIHZhbHVlID8geyBtYXhCeXRlTGVuZ3RoOiB2YWx1ZS5tYXhCeXRlTGVuZ3RoIH0gOiB1bmRlZmluZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZCA9IG5ldyBBcnJheUJ1ZmZlcihsZW5ndGgsIG9wdGlvbnMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2UgPSBuZXcgQyh2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldCA9IG5ldyBDKGNsb25lZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LnNldFVpbnQ4KGksIHNvdXJjZS5nZXRVaW50OChpKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ0FycmF5QnVmZmVyIGlzIGRldGFjaGVkJywgREFUQV9DTE9ORV9FUlJPUik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnU2hhcmVkQXJyYXlCdWZmZXInOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnQmxvYic6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lZCA9IHZhbHVlLnNsaWNlKDAsIHZhbHVlLnNpemUsIHZhbHVlLnR5cGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd1VucG9seWZpbGxhYmxlKHR5cGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0RPTVBvaW50JzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnRE9NUG9pbnRSZWFkT25seSc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDID0gZ2xvYmFsW3R5cGVdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQgPSBDLmZyb21Qb2ludCA/IEMuZnJvbVBvaW50KHZhbHVlKSA6IG5ldyBDKHZhbHVlLngsIHZhbHVlLnksIHZhbHVlLnosIHZhbHVlLncpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd1VucG9seWZpbGxhYmxlKHR5cGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0RPTVJlY3QnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdET01SZWN0UmVhZE9ubHknOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQyA9IGdsb2JhbFt0eXBlXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gQy5mcm9tUmVjdCA/IEMuZnJvbVJlY3QodmFsdWUpIDogbmV3IEModmFsdWUueCwgdmFsdWUueSwgdmFsdWUud2lkdGgsIHZhbHVlLmhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93VW5wb2x5ZmlsbGFibGUodHlwZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnRE9NTWF0cml4JzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnRE9NTWF0cml4UmVhZE9ubHknOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQyA9IGdsb2JhbFt0eXBlXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gQy5mcm9tTWF0cml4ID8gQy5mcm9tTWF0cml4KHZhbHVlKSA6IG5ldyBDKHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdBdWRpb0RhdGEnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdWaWRlb0ZyYW1lJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaXNDYWxsYWJsZSh2YWx1ZS5jbG9uZSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gdmFsdWUuY2xvbmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dVbmNsb25lYWJsZSh0eXBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdGaWxlJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkID0gbmV3IEZpbGUoW3ZhbHVlXSwgdmFsdWUubmFtZSwgdmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd1VucG9seWZpbGxhYmxlKHR5cGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0Nyb3BUYXJnZXQnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdDcnlwdG9LZXknOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdGaWxlU3lzdGVtRGlyZWN0b3J5SGFuZGxlJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnRmlsZVN5c3RlbUZpbGVIYW5kbGUnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdGaWxlU3lzdGVtSGFuZGxlJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnR1BVQ29tcGlsYXRpb25JbmZvJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnR1BVQ29tcGlsYXRpb25NZXNzYWdlJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnSW1hZ2VCaXRtYXAnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdSVENDZXJ0aWZpY2F0ZSc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ1dlYkFzc2VtYmx5Lk1vZHVsZSc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd1VucG9seWZpbGxhYmxlKHR5cGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dVbmNsb25lYWJsZSh0eXBlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIG1hcFNldChtYXAsIHZhbHVlLCBjbG9uZWQpOwogICAgICAgICAgICAgICAgICAgIGlmIChkZWVwKQogICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0FycmF5JzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ09iamVjdCc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5cyA9IG9iamVjdEtleXModmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDAsIGxlbmd0aCA9IGxlbmd0aE9mQXJyYXlMaWtlKGtleXMpOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5ID0ga2V5c1tpXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlUHJvcGVydHkoY2xvbmVkLCBrZXksIHN0cnVjdHVyZWRDbG9uZUludGVybmFsKHZhbHVlW2tleV0sIG1hcCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ01hcCc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUuZm9yRWFjaChmdW5jdGlvbiAodiwgaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXBTZXQoY2xvbmVkLCBzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbChrLCBtYXApLCBzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbCh2LCBtYXApKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ1NldCc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUuZm9yRWFjaChmdW5jdGlvbiAodikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRBZGQoY2xvbmVkLCBzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbCh2LCBtYXApKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0Vycm9yJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoY2xvbmVkLCAnbWVzc2FnZScsIHN0cnVjdHVyZWRDbG9uZUludGVybmFsKHZhbHVlLm1lc3NhZ2UsIG1hcCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChoYXNPd24odmFsdWUsICdjYXVzZScpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShjbG9uZWQsICdjYXVzZScsIHN0cnVjdHVyZWRDbG9uZUludGVybmFsKHZhbHVlLmNhdXNlLCBtYXApKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5hbWUgPT0gJ0FnZ3JlZ2F0ZUVycm9yJykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZWQuZXJyb3JzID0gc3RydWN0dXJlZENsb25lSW50ZXJuYWwodmFsdWUuZXJyb3JzLCBtYXApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0RPTUV4Y2VwdGlvbic6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEVSUk9SX1NUQUNLX0lOU1RBTExBQkxFKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShjbG9uZWQsICdzdGFjaycsIHN0cnVjdHVyZWRDbG9uZUludGVybmFsKHZhbHVlLnN0YWNrLCBtYXApKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2xvbmVkOwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIHZhciB0cnlUb1RyYW5zZmVyID0gZnVuY3Rpb24gKHJhd1RyYW5zZmVyLCBtYXApIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KHJhd1RyYW5zZmVyKSkKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKCdUcmFuc2ZlciBvcHRpb24gY2Fubm90IGJlIGNvbnZlcnRlZCB0byBhIHNlcXVlbmNlJyk7CiAgICAgICAgICAgICAgICAgICAgdmFyIHRyYW5zZmVyID0gW107CiAgICAgICAgICAgICAgICAgICAgaXRlcmF0ZShyYXdUcmFuc2ZlciwgZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHB1c2godHJhbnNmZXIsIGFuT2JqZWN0KHZhbHVlKSk7CiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgdmFyIGkgPSAwOwogICAgICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBsZW5ndGhPZkFycmF5TGlrZSh0cmFuc2Zlcik7CiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlLCB0eXBlLCBDLCB0cmFuc2ZlcnJlZEFycmF5LCB0cmFuc2ZlcnJlZCwgY2FudmFzLCBjb250ZXh0OwogICAgICAgICAgICAgICAgICAgIGlmIChQUk9QRVJfVFJBTlNGRVIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmZXJyZWRBcnJheSA9IG5hdGl2ZVN0cnVjdHVyZWRDbG9uZSh0cmFuc2ZlciwgeyB0cmFuc2ZlcjogdHJhbnNmZXIgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChpIDwgbGVuZ3RoKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwU2V0KG1hcCwgdHJhbnNmZXJbaV0sIHRyYW5zZmVycmVkQXJyYXlbaSsrXSk7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChpIDwgbGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRyYW5zZmVyW2krK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWFwSGFzKG1hcCwgdmFsdWUpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ0R1cGxpY2F0ZSB0cmFuc2ZlcmFibGUnLCBEQVRBX0NMT05FX0VSUk9SKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSBjbGFzc29mKHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0ltYWdlQml0bWFwJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQyA9IGdsb2JhbC5PZmZzY3JlZW5DYW52YXM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaXNDb25zdHJ1Y3RvcihDKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93VW5wb2x5ZmlsbGFibGUodHlwZSwgVFJBTlNGRVJSSU5HKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhcyA9IG5ldyBDKHZhbHVlLndpZHRoLCB2YWx1ZS5oZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCdiaXRtYXByZW5kZXJlcicpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dC50cmFuc2ZlckZyb21JbWFnZUJpdG1hcCh2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2ZlcnJlZCA9IGNhbnZhcy50cmFuc2ZlclRvSW1hZ2VCaXRtYXAoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdBdWRpb0RhdGEnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ1ZpZGVvRnJhbWUnOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzQ2FsbGFibGUodmFsdWUuY2xvbmUpIHx8ICFpc0NhbGxhYmxlKHZhbHVlLmNsb3NlKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93VW5wb2x5ZmlsbGFibGUodHlwZSwgVFJBTlNGRVJSSU5HKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZmVycmVkID0gdmFsdWUuY2xvbmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLmNsb3NlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnQXJyYXlCdWZmZXInOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzQ2FsbGFibGUodmFsdWUudHJhbnNmZXIpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlLCBUUkFOU0ZFUlJJTkcpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2ZlcnJlZCA9IHZhbHVlLnRyYW5zZmVyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ01lZGlhU291cmNlSGFuZGxlJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdNZXNzYWdlUG9ydCc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnT2Zmc2NyZWVuQ2FudmFzJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdSZWFkYWJsZVN0cmVhbSc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnVHJhbnNmb3JtU3RyZWFtJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdXcml0YWJsZVN0cmVhbSc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93VW5wb2x5ZmlsbGFibGUodHlwZSwgVFJBTlNGRVJSSU5HKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0cmFuc2ZlcnJlZCA9PT0gdW5kZWZpbmVkKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ1RoaXMgb2JqZWN0IGNhbm5vdCBiZSB0cmFuc2ZlcnJlZDogJyArIHR5cGUsIERBVEFfQ0xPTkVfRVJST1IpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwU2V0KG1hcCwgdmFsdWUsIHRyYW5zZmVycmVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICQoewogICAgICAgICAgICAgICAgICAgIGdsb2JhbDogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgIHNoYW06ICFQUk9QRVJfVFJBTlNGRVIsCiAgICAgICAgICAgICAgICAgICAgZm9yY2VkOiBGT1JDRURfUkVQTEFDRU1FTlQKICAgICAgICAgICAgICAgIH0sIHsKICAgICAgICAgICAgICAgICAgICBzdHJ1Y3R1cmVkQ2xvbmU6IGZ1bmN0aW9uIHN0cnVjdHVyZWRDbG9uZSh2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgb3B0aW9ucyA9IHZhbGlkYXRlQXJndW1lbnRzTGVuZ3RoKGFyZ3VtZW50cy5sZW5ndGgsIDEpID4gMSAmJiAhaXNOdWxsT3JVbmRlZmluZWQoYXJndW1lbnRzWzFdKSA/IGFuT2JqZWN0KGFyZ3VtZW50c1sxXSkgOiB1bmRlZmluZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB0cmFuc2ZlciA9IG9wdGlvbnMgPyBvcHRpb25zLnRyYW5zZmVyIDogdW5kZWZpbmVkOwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgbWFwOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodHJhbnNmZXIgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwID0gbmV3IE1hcCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5VG9UcmFuc2Zlcih0cmFuc2ZlciwgbWFwKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RydWN0dXJlZENsb25lSW50ZXJuYWwodmFsdWUsIG1hcCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEyNiAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNyk7CiAgICAgICAgICAgICAgICB2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwKTsKICAgICAgICAgICAgICAgIHZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNCk7CiAgICAgICAgICAgICAgICB2YXIgY2xhc3NvZiA9IF9fd19wZGZqc19yZXF1aXJlX18oODIpOwogICAgICAgICAgICAgICAgdmFyIGdldEJ1aWx0SW4gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI3KTsKICAgICAgICAgICAgICAgIHZhciBpbnNwZWN0U291cmNlID0gX193X3BkZmpzX3JlcXVpcmVfXyg1NCk7CiAgICAgICAgICAgICAgICB2YXIgbm9vcCA9IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB2YXIgZW1wdHkgPSBbXTsKICAgICAgICAgICAgICAgIHZhciBjb25zdHJ1Y3QgPSBnZXRCdWlsdEluKCdSZWZsZWN0JywgJ2NvbnN0cnVjdCcpOwogICAgICAgICAgICAgICAgdmFyIGNvbnN0cnVjdG9yUmVnRXhwID0gL15ccyooPzpjbGFzc3xmdW5jdGlvbilcYi87CiAgICAgICAgICAgICAgICB2YXIgZXhlYyA9IHVuY3VycnlUaGlzKGNvbnN0cnVjdG9yUmVnRXhwLmV4ZWMpOwogICAgICAgICAgICAgICAgdmFyIElOQ09SUkVDVF9UT19TVFJJTkcgPSAhY29uc3RydWN0b3JSZWdFeHAuZXhlYyhub29wKTsKICAgICAgICAgICAgICAgIHZhciBpc0NvbnN0cnVjdG9yTW9kZXJuID0gZnVuY3Rpb24gaXNDb25zdHJ1Y3Rvcihhcmd1bWVudCkgewogICAgICAgICAgICAgICAgICAgIGlmICghaXNDYWxsYWJsZShhcmd1bWVudCkpCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3Qobm9vcCwgZW1wdHksIGFyZ3VtZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB2YXIgaXNDb25zdHJ1Y3RvckxlZ2FjeSA9IGZ1bmN0aW9uIGlzQ29uc3RydWN0b3IoYXJndW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIWlzQ2FsbGFibGUoYXJndW1lbnQpKQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChjbGFzc29mKGFyZ3VtZW50KSkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdBc3luY0Z1bmN0aW9uJzoKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnR2VuZXJhdG9yRnVuY3Rpb24nOgogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdBc3luY0dlbmVyYXRvckZ1bmN0aW9uJzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIElOQ09SUkVDVF9UT19TVFJJTkcgfHwgISFleGVjKGNvbnN0cnVjdG9yUmVnRXhwLCBpbnNwZWN0U291cmNlKGFyZ3VtZW50KSk7CiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIGlzQ29uc3RydWN0b3JMZWdhY3kuc2hhbSA9IHRydWU7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9ICFjb25zdHJ1Y3QgfHwgZmFpbHMoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHZhciBjYWxsZWQ7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlzQ29uc3RydWN0b3JNb2Rlcm4oaXNDb25zdHJ1Y3Rvck1vZGVybi5jYWxsKSB8fCAhaXNDb25zdHJ1Y3Rvck1vZGVybihPYmplY3QpIHx8ICFpc0NvbnN0cnVjdG9yTW9kZXJuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICB9KSB8fCBjYWxsZWQ7CiAgICAgICAgICAgICAgICB9KSA/IGlzQ29uc3RydWN0b3JMZWdhY3kgOiBpc0NvbnN0cnVjdG9yTW9kZXJuOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMjcgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUpID0+IHsKCiAgICAgICAgICAgICAgICB2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHBhc3NlZCwgcmVxdWlyZWQpIHsKICAgICAgICAgICAgICAgICAgICBpZiAocGFzc2VkIDwgcmVxdWlyZWQpCiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICRUeXBlRXJyb3IoJ05vdCBlbm91Z2ggYXJndW1lbnRzJyk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhc3NlZDsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEyOCAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGNhbGwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExKTsKICAgICAgICAgICAgICAgIHZhciBoYXNPd24gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQyKTsKICAgICAgICAgICAgICAgIHZhciBpc1Byb3RvdHlwZU9mID0gX193X3BkZmpzX3JlcXVpcmVfXygyOCk7CiAgICAgICAgICAgICAgICB2YXIgcmVnRXhwRmxhZ3MgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyOSk7CiAgICAgICAgICAgICAgICB2YXIgUmVnRXhwUHJvdG90eXBlID0gUmVnRXhwLnByb3RvdHlwZTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKFIpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgZmxhZ3MgPSBSLmZsYWdzOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBmbGFncyA9PT0gdW5kZWZpbmVkICYmICEoJ2ZsYWdzJyBpbiBSZWdFeHBQcm90b3R5cGUpICYmICFoYXNPd24oUiwgJ2ZsYWdzJykgJiYgaXNQcm90b3R5cGVPZihSZWdFeHBQcm90b3R5cGUsIFIpID8gY2FsbChyZWdFeHBGbGFncywgUikgOiBmbGFnczsKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEyOSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKICAgICAgICAgICAgICAgIHZhciBhbk9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oNTApOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIHRoYXQgPSBhbk9iamVjdCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gJyc7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRoYXQuaGFzSW5kaWNlcykKICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdkJzsKICAgICAgICAgICAgICAgICAgICBpZiAodGhhdC5nbG9iYWwpCiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZyc7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRoYXQuaWdub3JlQ2FzZSkKICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdpJzsKICAgICAgICAgICAgICAgICAgICBpZiAodGhhdC5tdWx0aWxpbmUpCiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbSc7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRoYXQuZG90QWxsKQogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3MnOwogICAgICAgICAgICAgICAgICAgIGlmICh0aGF0LnVuaWNvZGUpCiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAndSc7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRoYXQudW5pY29kZVNldHMpCiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSAndic7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRoYXQuc3RpY2t5KQogICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3knOwogICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMzAgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTcpOwogICAgICAgICAgICAgICAgdmFyIE1hcFByb3RvdHlwZSA9IE1hcC5wcm90b3R5cGU7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHsKICAgICAgICAgICAgICAgICAgICBNYXA6IE1hcCwKICAgICAgICAgICAgICAgICAgICBzZXQ6IHVuY3VycnlUaGlzKE1hcFByb3RvdHlwZS5zZXQpLAogICAgICAgICAgICAgICAgICAgIGdldDogdW5jdXJyeVRoaXMoTWFwUHJvdG90eXBlLmdldCksCiAgICAgICAgICAgICAgICAgICAgaGFzOiB1bmN1cnJ5VGhpcyhNYXBQcm90b3R5cGUuaGFzKSwKICAgICAgICAgICAgICAgICAgICByZW1vdmU6IHVuY3VycnlUaGlzKE1hcFByb3RvdHlwZVsnZGVsZXRlJ10pLAogICAgICAgICAgICAgICAgICAgIHByb3RvOiBNYXBQcm90b3R5cGUKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEzMSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNyk7CiAgICAgICAgICAgICAgICB2YXIgU2V0UHJvdG90eXBlID0gU2V0LnByb3RvdHlwZTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gewogICAgICAgICAgICAgICAgICAgIFNldDogU2V0LAogICAgICAgICAgICAgICAgICAgIGFkZDogdW5jdXJyeVRoaXMoU2V0UHJvdG90eXBlLmFkZCksCiAgICAgICAgICAgICAgICAgICAgaGFzOiB1bmN1cnJ5VGhpcyhTZXRQcm90b3R5cGUuaGFzKSwKICAgICAgICAgICAgICAgICAgICByZW1vdmU6IHVuY3VycnlUaGlzKFNldFByb3RvdHlwZVsnZGVsZXRlJ10pLAogICAgICAgICAgICAgICAgICAgIHByb3RvOiBTZXRQcm90b3R5cGUsCiAgICAgICAgICAgICAgICAgICAgJGhhczogU2V0UHJvdG90eXBlLmhhcywKICAgICAgICAgICAgICAgICAgICAka2V5czogU2V0UHJvdG90eXBlLmtleXMKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEzMiAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIGZhaWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMCk7CiAgICAgICAgICAgICAgICB2YXIgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXygxNCk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9ICFmYWlscyhmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gRXJyb3IoJ2EnKTsKICAgICAgICAgICAgICAgICAgICBpZiAoISgnc3RhY2snIGluIGVycm9yKSkKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGVycm9yLCAnc3RhY2snLCBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IoMSwgNykpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBlcnJvci5zdGFjayAhPT0gNzsKICAgICAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMzMgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBnbG9iYWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDcpOwogICAgICAgICAgICAgICAgdmFyIGZhaWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMCk7CiAgICAgICAgICAgICAgICB2YXIgVjggPSBfX3dfcGRmanNfcmVxdWlyZV9fKDMxKTsKICAgICAgICAgICAgICAgIHZhciBJU19CUk9XU0VSID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzQpOwogICAgICAgICAgICAgICAgdmFyIElTX0RFTk8gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzNSk7CiAgICAgICAgICAgICAgICB2YXIgSVNfTk9ERSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTM2KTsKICAgICAgICAgICAgICAgIHZhciBzdHJ1Y3R1cmVkQ2xvbmUgPSBnbG9iYWwuc3RydWN0dXJlZENsb25lOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAhIXN0cnVjdHVyZWRDbG9uZSAmJiAhZmFpbHMoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIGlmIChJU19ERU5PICYmIFY4ID4gOTIgfHwgSVNfTk9ERSAmJiBWOCA+IDk0IHx8IElTX0JST1dTRVIgJiYgVjggPiA5NykKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgIHZhciBidWZmZXIgPSBuZXcgQXJyYXlCdWZmZXIoOCk7CiAgICAgICAgICAgICAgICAgICAgdmFyIGNsb25lID0gc3RydWN0dXJlZENsb25lKGJ1ZmZlciwgeyB0cmFuc2ZlcjogW2J1ZmZlcl0gfSk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGJ1ZmZlci5ieXRlTGVuZ3RoICE9IDAgfHwgY2xvbmUuYnl0ZUxlbmd0aCAhPSA4OwogICAgICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEzNCAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgdmFyIElTX0RFTk8gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzNSk7CiAgICAgICAgICAgICAgICB2YXIgSVNfTk9ERSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTM2KTsKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gIUlTX0RFTk8gJiYgIUlTX05PREUgJiYgdHlwZW9mIHdpbmRvdyA9PSAnb2JqZWN0JyAmJiB0eXBlb2YgZG9jdW1lbnQgPT0gJ29iamVjdCc7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEzNSAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSkgPT4gewoKICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdHlwZW9mIERlbm8gPT0gJ29iamVjdCcgJiYgRGVubyAmJiB0eXBlb2YgRGVuby52ZXJzaW9uID09ICdvYmplY3QnOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMzYgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBjbGFzc29mID0gX193X3BkZmpzX3JlcXVpcmVfXygxOCk7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHR5cGVvZiBwcm9jZXNzICE9ICd1bmRlZmluZWQnICYmIGNsYXNzb2YocHJvY2VzcykgPT0gJ3Byb2Nlc3MnOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxMzcgKi8KICAgICAgICAgICAgLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgIHZhciBnbG9iYWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDcpOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBnbG9iYWw7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEzOCAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLmJ1aWxkID0gZXhwb3J0cy5SZW5kZXJUYXNrID0gZXhwb3J0cy5QREZXb3JrZXJVdGlsID0gZXhwb3J0cy5QREZXb3JrZXIgPSBleHBvcnRzLlBERlBhZ2VQcm94eSA9IGV4cG9ydHMuUERGRG9jdW1lbnRQcm94eSA9IGV4cG9ydHMuUERGRG9jdW1lbnRMb2FkaW5nVGFzayA9IGV4cG9ydHMuUERGRGF0YVJhbmdlVHJhbnNwb3J0ID0gZXhwb3J0cy5Mb29wYmFja1BvcnQgPSBleHBvcnRzLkRlZmF1bHRTdGFuZGFyZEZvbnREYXRhRmFjdG9yeSA9IGV4cG9ydHMuRGVmYXVsdEZpbHRlckZhY3RvcnkgPSBleHBvcnRzLkRlZmF1bHRDYW52YXNGYWN0b3J5ID0gZXhwb3J0cy5EZWZhdWx0Q01hcFJlYWRlckZhY3RvcnkgPSB2b2lkIDA7CiAgICAgICAgICAgICAgICBleHBvcnRzLmdldERvY3VtZW50ID0gZ2V0RG9jdW1lbnQ7CiAgICAgICAgICAgICAgICBleHBvcnRzLnZlcnNpb24gPSB2b2lkIDA7CiAgICAgICAgICAgICAgICB2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEpOwogICAgICAgICAgICAgICAgdmFyIF9hbm5vdGF0aW9uX3N0b3JhZ2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzOSk7CiAgICAgICAgICAgICAgICB2YXIgX2Rpc3BsYXlfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0Mik7CiAgICAgICAgICAgICAgICB2YXIgX2ZvbnRfbG9hZGVyID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDUpOwogICAgICAgICAgICAgICAgdmFyIF9jYW52YXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0Nik7CiAgICAgICAgICAgICAgICB2YXIgX3dvcmtlcl9vcHRpb25zID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDkpOwogICAgICAgICAgICAgICAgdmFyIF9pc19ub2RlID0gX193X3BkZmpzX3JlcXVpcmVfXygzKTsKICAgICAgICAgICAgICAgIHZhciBfbWVzc2FnZV9oYW5kbGVyID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTApOwogICAgICAgICAgICAgICAgdmFyIF9tZXRhZGF0YSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTUxKTsKICAgICAgICAgICAgICAgIHZhciBfb3B0aW9uYWxfY29udGVudF9jb25maWcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1Mik7CiAgICAgICAgICAgICAgICB2YXIgX3RyYW5zcG9ydF9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1Myk7CiAgICAgICAgICAgICAgICB2YXIgX3hmYV90ZXh0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTQpOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKG9iaiwgcHJpdmF0ZVNldCkgeyBfY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbihvYmosIHByaXZhdGVTZXQpOyBwcml2YXRlU2V0LmFkZChvYmopOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyhvYmosIHByaXZhdGVNYXAsIHZhbHVlKSB7IF9jaGVja1ByaXZhdGVSZWRlY2xhcmF0aW9uKG9iaiwgcHJpdmF0ZU1hcCk7IHByaXZhdGVNYXAuc2V0KG9iaiwgdmFsdWUpOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbihvYmosIHByaXZhdGVDb2xsZWN0aW9uKSB7IGlmIChwcml2YXRlQ29sbGVjdGlvbi5oYXMob2JqKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgaW5pdGlhbGl6ZSB0aGUgc2FtZSBwcml2YXRlIGVsZW1lbnRzIHR3aWNlIG9uIGFuIG9iamVjdCIpOyB9IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVGaWVsZEdldChyZWNlaXZlciwgcHJpdmF0ZU1hcCkgeyB2YXIgZGVzY3JpcHRvciA9IF9jbGFzc0V4dHJhY3RGaWVsZERlc2NyaXB0b3IocmVjZWl2ZXIsIHByaXZhdGVNYXAsICJnZXQiKTsgcmV0dXJuIF9jbGFzc0FwcGx5RGVzY3JpcHRvckdldChyZWNlaXZlciwgZGVzY3JpcHRvcik7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc0FwcGx5RGVzY3JpcHRvckdldChyZWNlaXZlciwgZGVzY3JpcHRvcikgeyBpZiAoZGVzY3JpcHRvci5nZXQpIHsgcmV0dXJuIGRlc2NyaXB0b3IuZ2V0LmNhbGwocmVjZWl2ZXIpOyB9IHJldHVybiBkZXNjcmlwdG9yLnZhbHVlOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHJlY2VpdmVyLCBwcml2YXRlU2V0LCBmbikgeyBpZiAoIXByaXZhdGVTZXQuaGFzKHJlY2VpdmVyKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJhdHRlbXB0ZWQgdG8gZ2V0IHByaXZhdGUgZmllbGQgb24gbm9uLWluc3RhbmNlIik7IH0gcmV0dXJuIGZuOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlRmllbGRTZXQocmVjZWl2ZXIsIHByaXZhdGVNYXAsIHZhbHVlKSB7IHZhciBkZXNjcmlwdG9yID0gX2NsYXNzRXh0cmFjdEZpZWxkRGVzY3JpcHRvcihyZWNlaXZlciwgcHJpdmF0ZU1hcCwgInNldCIpOyBfY2xhc3NBcHBseURlc2NyaXB0b3JTZXQocmVjZWl2ZXIsIGRlc2NyaXB0b3IsIHZhbHVlKTsgcmV0dXJuIHZhbHVlOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NFeHRyYWN0RmllbGREZXNjcmlwdG9yKHJlY2VpdmVyLCBwcml2YXRlTWFwLCBhY3Rpb24pIHsgaWYgKCFwcml2YXRlTWFwLmhhcyhyZWNlaXZlcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigiYXR0ZW1wdGVkIHRvICIgKyBhY3Rpb24gKyAiIHByaXZhdGUgZmllbGQgb24gbm9uLWluc3RhbmNlIik7IH0gcmV0dXJuIHByaXZhdGVNYXAuZ2V0KHJlY2VpdmVyKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzQXBwbHlEZXNjcmlwdG9yU2V0KHJlY2VpdmVyLCBkZXNjcmlwdG9yLCB2YWx1ZSkgeyBpZiAoZGVzY3JpcHRvci5zZXQpIHsgZGVzY3JpcHRvci5zZXQuY2FsbChyZWNlaXZlciwgdmFsdWUpOyB9IGVsc2UgeyBpZiAoIWRlc2NyaXB0b3Iud3JpdGFibGUpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigiYXR0ZW1wdGVkIHRvIHNldCByZWFkIG9ubHkgcHJpdmF0ZSBmaWVsZCIpOyB9IGRlc2NyaXB0b3IudmFsdWUgPSB2YWx1ZTsgfSB9CiAgICAgICAgICAgICAgICBjb25zdCBERUZBVUxUX1JBTkdFX0NIVU5LX1NJWkUgPSA2NTUzNjsKICAgICAgICAgICAgICAgIGNvbnN0IFJFTkRFUklOR19DQU5DRUxMRURfVElNRU9VVCA9IDEwMDsKICAgICAgICAgICAgICAgIGNvbnN0IERFTEFZRURfQ0xFQU5VUF9USU1FT1VUID0gNTAwMDsKICAgICAgICAgICAgICAgIGxldCBEZWZhdWx0Q2FudmFzRmFjdG9yeSA9IF9kaXNwbGF5X3V0aWxzLkRPTUNhbnZhc0ZhY3Rvcnk7CiAgICAgICAgICAgICAgICBleHBvcnRzLkRlZmF1bHRDYW52YXNGYWN0b3J5ID0gRGVmYXVsdENhbnZhc0ZhY3Rvcnk7CiAgICAgICAgICAgICAgICBsZXQgRGVmYXVsdENNYXBSZWFkZXJGYWN0b3J5ID0gX2Rpc3BsYXlfdXRpbHMuRE9NQ01hcFJlYWRlckZhY3Rvcnk7CiAgICAgICAgICAgICAgICBleHBvcnRzLkRlZmF1bHRDTWFwUmVhZGVyRmFjdG9yeSA9IERlZmF1bHRDTWFwUmVhZGVyRmFjdG9yeTsKICAgICAgICAgICAgICAgIGxldCBEZWZhdWx0RmlsdGVyRmFjdG9yeSA9IF9kaXNwbGF5X3V0aWxzLkRPTUZpbHRlckZhY3Rvcnk7CiAgICAgICAgICAgICAgICBleHBvcnRzLkRlZmF1bHRGaWx0ZXJGYWN0b3J5ID0gRGVmYXVsdEZpbHRlckZhY3Rvcnk7CiAgICAgICAgICAgICAgICBsZXQgRGVmYXVsdFN0YW5kYXJkRm9udERhdGFGYWN0b3J5ID0gX2Rpc3BsYXlfdXRpbHMuRE9NU3RhbmRhcmRGb250RGF0YUZhY3Rvcnk7CiAgICAgICAgICAgICAgICBleHBvcnRzLkRlZmF1bHRTdGFuZGFyZEZvbnREYXRhRmFjdG9yeSA9IERlZmF1bHRTdGFuZGFyZEZvbnREYXRhRmFjdG9yeTsKICAgICAgICAgICAgICAgIGlmIChfaXNfbm9kZS5pc05vZGVKUykgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgTm9kZUNhbnZhc0ZhY3RvcnksCiAgICAgICAgICAgICAgICAgICAgICAgIE5vZGVDTWFwUmVhZGVyRmFjdG9yeSwKICAgICAgICAgICAgICAgICAgICAgICAgTm9kZUZpbHRlckZhY3RvcnksCiAgICAgICAgICAgICAgICAgICAgICAgIE5vZGVTdGFuZGFyZEZvbnREYXRhRmFjdG9yeQogICAgICAgICAgICAgICAgICAgIH0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1NSk7CiAgICAgICAgICAgICAgICAgICAgZXhwb3J0cy5EZWZhdWx0Q2FudmFzRmFjdG9yeSA9IERlZmF1bHRDYW52YXNGYWN0b3J5ID0gTm9kZUNhbnZhc0ZhY3Rvcnk7CiAgICAgICAgICAgICAgICAgICAgZXhwb3J0cy5EZWZhdWx0Q01hcFJlYWRlckZhY3RvcnkgPSBEZWZhdWx0Q01hcFJlYWRlckZhY3RvcnkgPSBOb2RlQ01hcFJlYWRlckZhY3Rvcnk7CiAgICAgICAgICAgICAgICAgICAgZXhwb3J0cy5EZWZhdWx0RmlsdGVyRmFjdG9yeSA9IERlZmF1bHRGaWx0ZXJGYWN0b3J5ID0gTm9kZUZpbHRlckZhY3Rvcnk7CiAgICAgICAgICAgICAgICAgICAgZXhwb3J0cy5EZWZhdWx0U3RhbmRhcmRGb250RGF0YUZhY3RvcnkgPSBEZWZhdWx0U3RhbmRhcmRGb250RGF0YUZhY3RvcnkgPSBOb2RlU3RhbmRhcmRGb250RGF0YUZhY3Rvcnk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBsZXQgY3JlYXRlUERGTmV0d29ya1N0cmVhbTsKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpZiAoX2lzX25vZGUuaXNOb2RlSlMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgUERGTm9kZVN0cmVhbQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTYpOwogICAgICAgICAgICAgICAgICAgICAgICBjcmVhdGVQREZOZXR3b3JrU3RyZWFtID0gcGFyYW1zID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUERGTm9kZVN0cmVhbShwYXJhbXMpOwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBERk5ldHdvcmtTdHJlYW0KICAgICAgICAgICAgICAgICAgICAgICAgfSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTU5KTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgUERGRmV0Y2hTdHJlYW0KICAgICAgICAgICAgICAgICAgICAgICAgfSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTYwKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlUERGTmV0d29ya1N0cmVhbSA9IHBhcmFtcyA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKDAsIF9kaXNwbGF5X3V0aWxzLmlzVmFsaWRGZXRjaFVybCkocGFyYW1zLnVybCkgPyBuZXcgUERGRmV0Y2hTdHJlYW0ocGFyYW1zKSA6IG5ldyBQREZOZXR3b3JrU3RyZWFtKHBhcmFtcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gZ2V0RG9jdW1lbnQoc3JjKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzcmMgPT09ICJzdHJpbmciIHx8IHNyYyBpbnN0YW5jZW9mIFVSTCkgewogICAgICAgICAgICAgICAgICAgICAgICBzcmMgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cmw6IHNyYwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoKDAsIF91dGlsLmlzQXJyYXlCdWZmZXIpKHNyYykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3JjID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogc3JjCiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3JjICE9PSAib2JqZWN0IikgewogICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgcGFyYW1ldGVyIGluIGdldERvY3VtZW50LCBuZWVkIHBhcmFtZXRlciBvYmplY3QuIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmICghc3JjLnVybCAmJiAhc3JjLmRhdGEgJiYgIXNyYy5yYW5nZSkgewogICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgcGFyYW1ldGVyIG9iamVjdDogbmVlZCBlaXRoZXIgLmRhdGEsIC5yYW5nZSBvciAudXJsIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBuZXcgUERGRG9jdW1lbnRMb2FkaW5nVGFzaygpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgZG9jSWQKICAgICAgICAgICAgICAgICAgICB9ID0gdGFzazsKICAgICAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSBzcmMudXJsID8gZ2V0VXJsUHJvcChzcmMudXJsKSA6IG51bGw7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IHNyYy5kYXRhID8gZ2V0RGF0YVByb3Aoc3JjLmRhdGEpIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBodHRwSGVhZGVycyA9IHNyYy5odHRwSGVhZGVycyB8fCBudWxsOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpdGhDcmVkZW50aWFscyA9IHNyYy53aXRoQ3JlZGVudGlhbHMgPT09IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFzc3dvcmQgPSBzcmMucGFzc3dvcmQgPz8gbnVsbDsKICAgICAgICAgICAgICAgICAgICBjb25zdCByYW5nZVRyYW5zcG9ydCA9IHNyYy5yYW5nZSBpbnN0YW5jZW9mIFBERkRhdGFSYW5nZVRyYW5zcG9ydCA/IHNyYy5yYW5nZSA6IG51bGw7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2VDaHVua1NpemUgPSBOdW1iZXIuaXNJbnRlZ2VyKHNyYy5yYW5nZUNodW5rU2l6ZSkgJiYgc3JjLnJhbmdlQ2h1bmtTaXplID4gMCA/IHNyYy5yYW5nZUNodW5rU2l6ZSA6IERFRkFVTFRfUkFOR0VfQ0hVTktfU0laRTsKICAgICAgICAgICAgICAgICAgICBsZXQgd29ya2VyID0gc3JjLndvcmtlciBpbnN0YW5jZW9mIFBERldvcmtlciA/IHNyYy53b3JrZXIgOiBudWxsOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHZlcmJvc2l0eSA9IHNyYy52ZXJib3NpdHk7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZG9jQmFzZVVybCA9IHR5cGVvZiBzcmMuZG9jQmFzZVVybCA9PT0gInN0cmluZyIgJiYgISgwLCBfZGlzcGxheV91dGlscy5pc0RhdGFTY2hlbWUpKHNyYy5kb2NCYXNlVXJsKSA/IHNyYy5kb2NCYXNlVXJsIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjTWFwVXJsID0gdHlwZW9mIHNyYy5jTWFwVXJsID09PSAic3RyaW5nIiA/IHNyYy5jTWFwVXJsIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjTWFwUGFja2VkID0gc3JjLmNNYXBQYWNrZWQgIT09IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IENNYXBSZWFkZXJGYWN0b3J5ID0gc3JjLkNNYXBSZWFkZXJGYWN0b3J5IHx8IERlZmF1bHRDTWFwUmVhZGVyRmFjdG9yeTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGFuZGFyZEZvbnREYXRhVXJsID0gdHlwZW9mIHNyYy5zdGFuZGFyZEZvbnREYXRhVXJsID09PSAic3RyaW5nIiA/IHNyYy5zdGFuZGFyZEZvbnREYXRhVXJsIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBTdGFuZGFyZEZvbnREYXRhRmFjdG9yeSA9IHNyYy5TdGFuZGFyZEZvbnREYXRhRmFjdG9yeSB8fCBEZWZhdWx0U3RhbmRhcmRGb250RGF0YUZhY3Rvcnk7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgaWdub3JlRXJyb3JzID0gc3JjLnN0b3BBdEVycm9ycyAhPT0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXhJbWFnZVNpemUgPSBOdW1iZXIuaXNJbnRlZ2VyKHNyYy5tYXhJbWFnZVNpemUpICYmIHNyYy5tYXhJbWFnZVNpemUgPiAtMSA/IHNyYy5tYXhJbWFnZVNpemUgOiAtMTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBpc0V2YWxTdXBwb3J0ZWQgPSBzcmMuaXNFdmFsU3VwcG9ydGVkICE9PSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCA9IHR5cGVvZiBzcmMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgPT09ICJib29sZWFuIiA/IHNyYy5pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCA6ICFfaXNfbm9kZS5pc05vZGVKUzsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW52YXNNYXhBcmVhSW5CeXRlcyA9IE51bWJlci5pc0ludGVnZXIoc3JjLmNhbnZhc01heEFyZWFJbkJ5dGVzKSA/IHNyYy5jYW52YXNNYXhBcmVhSW5CeXRlcyA6IC0xOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpc2FibGVGb250RmFjZSA9IHR5cGVvZiBzcmMuZGlzYWJsZUZvbnRGYWNlID09PSAiYm9vbGVhbiIgPyBzcmMuZGlzYWJsZUZvbnRGYWNlIDogX2lzX25vZGUuaXNOb2RlSlM7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZm9udEV4dHJhUHJvcGVydGllcyA9IHNyYy5mb250RXh0cmFQcm9wZXJ0aWVzID09PSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGVuYWJsZVhmYSA9IHNyYy5lbmFibGVYZmEgPT09IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3duZXJEb2N1bWVudCA9IHNyYy5vd25lckRvY3VtZW50IHx8IGdsb2JhbFRoaXMuZG9jdW1lbnQ7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGlzYWJsZVJhbmdlID0gc3JjLmRpc2FibGVSYW5nZSA9PT0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBkaXNhYmxlU3RyZWFtID0gc3JjLmRpc2FibGVTdHJlYW0gPT09IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZGlzYWJsZUF1dG9GZXRjaCA9IHNyYy5kaXNhYmxlQXV0b0ZldGNoID09PSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHBkZkJ1ZyA9IHNyYy5wZGZCdWcgPT09IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gcmFuZ2VUcmFuc3BvcnQgPyByYW5nZVRyYW5zcG9ydC5sZW5ndGggOiBzcmMubGVuZ3RoID8/IE5hTjsKICAgICAgICAgICAgICAgICAgICBjb25zdCB1c2VTeXN0ZW1Gb250cyA9IHR5cGVvZiBzcmMudXNlU3lzdGVtRm9udHMgPT09ICJib29sZWFuIiA/IHNyYy51c2VTeXN0ZW1Gb250cyA6ICFfaXNfbm9kZS5pc05vZGVKUyAmJiAhZGlzYWJsZUZvbnRGYWNlOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHVzZVdvcmtlckZldGNoID0gdHlwZW9mIHNyYy51c2VXb3JrZXJGZXRjaCA9PT0gImJvb2xlYW4iID8gc3JjLnVzZVdvcmtlckZldGNoIDogQ01hcFJlYWRlckZhY3RvcnkgPT09IF9kaXNwbGF5X3V0aWxzLkRPTUNNYXBSZWFkZXJGYWN0b3J5ICYmIFN0YW5kYXJkRm9udERhdGFGYWN0b3J5ID09PSBfZGlzcGxheV91dGlscy5ET01TdGFuZGFyZEZvbnREYXRhRmFjdG9yeSAmJiAoMCwgX2Rpc3BsYXlfdXRpbHMuaXNWYWxpZEZldGNoVXJsKShjTWFwVXJsLCBkb2N1bWVudC5iYXNlVVJJKSAmJiAoMCwgX2Rpc3BsYXlfdXRpbHMuaXNWYWxpZEZldGNoVXJsKShzdGFuZGFyZEZvbnREYXRhVXJsLCBkb2N1bWVudC5iYXNlVVJJKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW52YXNGYWN0b3J5ID0gc3JjLmNhbnZhc0ZhY3RvcnkgfHwgbmV3IERlZmF1bHRDYW52YXNGYWN0b3J5KHsKICAgICAgICAgICAgICAgICAgICAgICAgb3duZXJEb2N1bWVudAogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbHRlckZhY3RvcnkgPSBzcmMuZmlsdGVyRmFjdG9yeSB8fCBuZXcgRGVmYXVsdEZpbHRlckZhY3RvcnkoewogICAgICAgICAgICAgICAgICAgICAgICBkb2NJZCwKICAgICAgICAgICAgICAgICAgICAgICAgb3duZXJEb2N1bWVudAogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0eWxlRWxlbWVudCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnNldFZlcmJvc2l0eUxldmVsKSh2ZXJib3NpdHkpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zcG9ydEZhY3RvcnkgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhc0ZhY3RvcnksCiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlckZhY3RvcnkKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGlmICghdXNlV29ya2VyRmV0Y2gpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNwb3J0RmFjdG9yeS5jTWFwUmVhZGVyRmFjdG9yeSA9IG5ldyBDTWFwUmVhZGVyRmFjdG9yeSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXNlVXJsOiBjTWFwVXJsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNDb21wcmVzc2VkOiBjTWFwUGFja2VkCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB0cmFuc3BvcnRGYWN0b3J5LnN0YW5kYXJkRm9udERhdGFGYWN0b3J5ID0gbmV3IFN0YW5kYXJkRm9udERhdGFGYWN0b3J5KHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhc2VVcmw6IHN0YW5kYXJkRm9udERhdGFVcmwKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmICghd29ya2VyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdvcmtlclBhcmFtcyA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2l0eSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcnQ6IF93b3JrZXJfb3B0aW9ucy5HbG9iYWxXb3JrZXJPcHRpb25zLndvcmtlclBvcnQKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgd29ya2VyID0gd29ya2VyUGFyYW1zLnBvcnQgPyBQREZXb3JrZXIuZnJvbVBvcnQod29ya2VyUGFyYW1zKSA6IG5ldyBQREZXb3JrZXIod29ya2VyUGFyYW1zKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5fd29ya2VyID0gd29ya2VyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBmZXRjaERvY1BhcmFtcyA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgZG9jSWQsCiAgICAgICAgICAgICAgICAgICAgICAgIGFwaVZlcnNpb246ICczLjUuMTIyJywKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgcGFzc3dvcmQsCiAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVBdXRvRmV0Y2gsCiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlQ2h1bmtTaXplLAogICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGgsCiAgICAgICAgICAgICAgICAgICAgICAgIGRvY0Jhc2VVcmwsCiAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZVhmYSwKICAgICAgICAgICAgICAgICAgICAgICAgZXZhbHVhdG9yT3B0aW9uczogewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW1hZ2VTaXplLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZUZvbnRGYWNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlRXJyb3JzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNFdmFsU3VwcG9ydGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYW52YXNNYXhBcmVhSW5CeXRlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRFeHRyYVByb3BlcnRpZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VTeXN0ZW1Gb250cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNNYXBVcmw6IHVzZVdvcmtlckZldGNoID8gY01hcFVybCA6IG51bGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFuZGFyZEZvbnREYXRhVXJsOiB1c2VXb3JrZXJGZXRjaCA/IHN0YW5kYXJkRm9udERhdGFVcmwgOiBudWxsCiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zcG9ydFBhcmFtcyA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlRXJyb3JzLAogICAgICAgICAgICAgICAgICAgICAgICBpc0V2YWxTdXBwb3J0ZWQsCiAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVGb250RmFjZSwKICAgICAgICAgICAgICAgICAgICAgICAgZm9udEV4dHJhUHJvcGVydGllcywKICAgICAgICAgICAgICAgICAgICAgICAgZW5hYmxlWGZhLAogICAgICAgICAgICAgICAgICAgICAgICBvd25lckRvY3VtZW50LAogICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlQXV0b0ZldGNoLAogICAgICAgICAgICAgICAgICAgICAgICBwZGZCdWcsCiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlRWxlbWVudAogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgd29ya2VyLnByb21pc2UudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0YXNrLmRlc3Ryb3llZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJMb2FkaW5nIGFib3J0ZWQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3b3JrZXJJZFByb21pc2UgPSBfZmV0Y2hEb2N1bWVudCh3b3JrZXIsIGZldGNoRG9jUGFyYW1zKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV0d29ya1N0cmVhbVByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG5ldHdvcmtTdHJlYW07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmFuZ2VUcmFuc3BvcnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXR3b3JrU3RyZWFtID0gbmV3IF90cmFuc3BvcnRfc3RyZWFtLlBERkRhdGFUcmFuc3BvcnRTdHJlYW0oewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluaXRpYWxEYXRhOiByYW5nZVRyYW5zcG9ydC5pbml0aWFsRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3NpdmVEb25lOiByYW5nZVRyYW5zcG9ydC5wcm9ncmVzc2l2ZURvbmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnREaXNwb3NpdGlvbkZpbGVuYW1lOiByYW5nZVRyYW5zcG9ydC5jb250ZW50RGlzcG9zaXRpb25GaWxlbmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZVJhbmdlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlU3RyZWFtCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgcmFuZ2VUcmFuc3BvcnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghZGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldHdvcmtTdHJlYW0gPSBjcmVhdGVQREZOZXR3b3JrU3RyZWFtKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXJsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0dHBIZWFkZXJzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aXRoQ3JlZGVudGlhbHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlQ2h1bmtTaXplLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlUmFuZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVTdHJlYW0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUobmV0d29ya1N0cmVhbSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoW3dvcmtlcklkUHJvbWlzZSwgbmV0d29ya1N0cmVhbVByb21pc2VdKS50aGVuKGZ1bmN0aW9uIChfcmVmKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgW3dvcmtlcklkLCBuZXR3b3JrU3RyZWFtXSA9IF9yZWY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGFzay5kZXN0cm95ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkxvYWRpbmcgYWJvcnRlZCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWVzc2FnZUhhbmRsZXIgPSBuZXcgX21lc3NhZ2VfaGFuZGxlci5NZXNzYWdlSGFuZGxlcihkb2NJZCwgd29ya2VySWQsIHdvcmtlci5wb3J0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zcG9ydCA9IG5ldyBXb3JrZXJUcmFuc3BvcnQobWVzc2FnZUhhbmRsZXIsIHRhc2ssIG5ldHdvcmtTdHJlYW0sIHRyYW5zcG9ydFBhcmFtcywgdHJhbnNwb3J0RmFjdG9yeSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXNrLl90cmFuc3BvcnQgPSB0cmFuc3BvcnQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlSGFuZGxlci5zZW5kKCJSZWFkeSIsIG51bGwpOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCh0YXNrLl9jYXBhYmlsaXR5LnJlamVjdCk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRhc2s7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBhc3luYyBmdW5jdGlvbiBfZmV0Y2hEb2N1bWVudCh3b3JrZXIsIHNvdXJjZSkgewogICAgICAgICAgICAgICAgICAgIGlmICh3b3JrZXIuZGVzdHJveWVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiV29ya2VyIHdhcyBkZXN0cm95ZWQiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgd29ya2VySWQgPSBhd2FpdCB3b3JrZXIubWVzc2FnZUhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJHZXREb2NSZXF1ZXN0Iiwgc291cmNlLCBzb3VyY2UuZGF0YSA/IFtzb3VyY2UuZGF0YS5idWZmZXJdIDogbnVsbCk7CiAgICAgICAgICAgICAgICAgICAgaWYgKHdvcmtlci5kZXN0cm95ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJXb3JrZXIgd2FzIGRlc3Ryb3llZCIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gd29ya2VySWQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBnZXRVcmxQcm9wKHZhbCkgewogICAgICAgICAgICAgICAgICAgIGlmICh2YWwgaW5zdGFuY2VvZiBVUkwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbC5ocmVmOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFVSTCh2YWwsIHdpbmRvdy5sb2NhdGlvbikuaHJlZjsKICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoX2lzX25vZGUuaXNOb2RlSlMgJiYgdHlwZW9mIHZhbCA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWw7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJJbnZhbGlkIFBERiB1cmwgZGF0YTogIiArICJlaXRoZXIgc3RyaW5nIG9yIFVSTC1vYmplY3QgaXMgZXhwZWN0ZWQgaW4gdGhlIHVybCBwcm9wZXJ0eS4iKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGdldERhdGFQcm9wKHZhbCkgewogICAgICAgICAgICAgICAgICAgIGlmIChfaXNfbm9kZS5pc05vZGVKUyAmJiB0eXBlb2YgQnVmZmVyICE9PSAidW5kZWZpbmVkIiAmJiB2YWwgaW5zdGFuY2VvZiBCdWZmZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF9kaXNwbGF5X3V0aWxzLmRlcHJlY2F0ZWQpKCJQbGVhc2UgcHJvdmlkZSBiaW5hcnkgZGF0YSBhcyBgVWludDhBcnJheWAsIHJhdGhlciB0aGFuIGBCdWZmZXJgLiIpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkodmFsKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkgJiYgdmFsLmJ5dGVMZW5ndGggPT09IHZhbC5idWZmZXIuYnl0ZUxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbCA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICgwLCBfdXRpbC5zdHJpbmdUb0J5dGVzKSh2YWwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbCA9PT0gIm9iamVjdCIgJiYgIWlzTmFOKHZhbCA9PT0gbnVsbCB8fCB2YWwgPT09IHZvaWQgMCA/IHZvaWQgMCA6IHZhbC5sZW5ndGgpIHx8ICgwLCBfdXRpbC5pc0FycmF5QnVmZmVyKSh2YWwpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVWludDhBcnJheSh2YWwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgUERGIGJpbmFyeSBkYXRhOiBlaXRoZXIgVHlwZWRBcnJheSwgIiArICJzdHJpbmcsIG9yIGFycmF5LWxpa2Ugb2JqZWN0IGlzIGV4cGVjdGVkIGluIHRoZSBkYXRhIHByb3BlcnR5LiIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgUERGRG9jdW1lbnRMb2FkaW5nVGFzayB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGljICNkb2NJZCA9IDA7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3RyYW5zcG9ydCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3dvcmtlciA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZG9jSWQgPSBgZCR7UERGRG9jdW1lbnRMb2FkaW5nVGFzay4jZG9jSWQrK31gOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlc3Ryb3llZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uUGFzc3dvcmQgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uUHJvZ3Jlc3MgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgcHJvbWlzZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYXN5bmMgZGVzdHJveSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJF90cmFuc3BvcnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVzdHJveWVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgKChfdGhpcyRfdHJhbnNwb3J0ID0gdGhpcy5fdHJhbnNwb3J0KSA9PT0gbnVsbCB8fCBfdGhpcyRfdHJhbnNwb3J0ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRfdHJhbnNwb3J0LmRlc3Ryb3koKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3RyYW5zcG9ydCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl93b3JrZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3dvcmtlci5kZXN0cm95KCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl93b3JrZXIgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5QREZEb2N1bWVudExvYWRpbmdUYXNrID0gUERGRG9jdW1lbnRMb2FkaW5nVGFzazsKICAgICAgICAgICAgICAgIGNsYXNzIFBERkRhdGFSYW5nZVRyYW5zcG9ydCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IobGVuZ3RoLCBpbml0aWFsRGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcHJvZ3Jlc3NpdmVEb25lID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvbnRlbnREaXNwb3NpdGlvbkZpbGVuYW1lID0gYXJndW1lbnRzLmxlbmd0aCA+IDMgJiYgYXJndW1lbnRzWzNdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbM10gOiBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxlbmd0aCA9IGxlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0aWFsRGF0YSA9IGluaXRpYWxEYXRhOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2dyZXNzaXZlRG9uZSA9IHByb2dyZXNzaXZlRG9uZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250ZW50RGlzcG9zaXRpb25GaWxlbmFtZSA9IGNvbnRlbnREaXNwb3NpdGlvbkZpbGVuYW1lOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yYW5nZUxpc3RlbmVycyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wcm9ncmVzc0xpc3RlbmVycyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wcm9ncmVzc2l2ZVJlYWRMaXN0ZW5lcnMgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJvZ3Jlc3NpdmVEb25lTGlzdGVuZXJzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWR5Q2FwYWJpbGl0eSA9ICgwLCBfdXRpbC5jcmVhdGVQcm9taXNlQ2FwYWJpbGl0eSkoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYWRkUmFuZ2VMaXN0ZW5lcihsaXN0ZW5lcikgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yYW5nZUxpc3RlbmVycy5wdXNoKGxpc3RlbmVyKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYWRkUHJvZ3Jlc3NMaXN0ZW5lcihsaXN0ZW5lcikgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wcm9ncmVzc0xpc3RlbmVycy5wdXNoKGxpc3RlbmVyKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYWRkUHJvZ3Jlc3NpdmVSZWFkTGlzdGVuZXIobGlzdGVuZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJvZ3Jlc3NpdmVSZWFkTGlzdGVuZXJzLnB1c2gobGlzdGVuZXIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhZGRQcm9ncmVzc2l2ZURvbmVMaXN0ZW5lcihsaXN0ZW5lcikgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wcm9ncmVzc2l2ZURvbmVMaXN0ZW5lcnMucHVzaChsaXN0ZW5lcik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIG9uRGF0YVJhbmdlKGJlZ2luLCBjaHVuaykgewogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGxpc3RlbmVyIG9mIHRoaXMuX3JhbmdlTGlzdGVuZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcihiZWdpbiwgY2h1bmspOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIG9uRGF0YVByb2dyZXNzKGxvYWRlZCwgdG90YWwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZHlDYXBhYmlsaXR5LnByb21pc2UudGhlbigoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGxpc3RlbmVyIG9mIHRoaXMuX3Byb2dyZXNzTGlzdGVuZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIobG9hZGVkLCB0b3RhbCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBvbkRhdGFQcm9ncmVzc2l2ZVJlYWQoY2h1bmspIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZHlDYXBhYmlsaXR5LnByb21pc2UudGhlbigoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGxpc3RlbmVyIG9mIHRoaXMuX3Byb2dyZXNzaXZlUmVhZExpc3RlbmVycykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyKGNodW5rKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIG9uRGF0YVByb2dyZXNzaXZlRG9uZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZHlDYXBhYmlsaXR5LnByb21pc2UudGhlbigoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGxpc3RlbmVyIG9mIHRoaXMuX3Byb2dyZXNzaXZlRG9uZUxpc3RlbmVycykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB0cmFuc3BvcnRSZWFkeSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZHlDYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVxdWVzdERhdGFSYW5nZShiZWdpbiwgZW5kKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIkFic3RyYWN0IG1ldGhvZCBQREZEYXRhUmFuZ2VUcmFuc3BvcnQucmVxdWVzdERhdGFSYW5nZSIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhYm9ydCgpIHt9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLlBERkRhdGFSYW5nZVRyYW5zcG9ydCA9IFBERkRhdGFSYW5nZVRyYW5zcG9ydDsKICAgICAgICAgICAgICAgIGNsYXNzIFBERkRvY3VtZW50UHJveHkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHBkZkluZm8sIHRyYW5zcG9ydCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wZGZJbmZvID0gcGRmSW5mbzsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdHJhbnNwb3J0ID0gdHJhbnNwb3J0OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgYW5ub3RhdGlvblN0b3JhZ2UoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuYW5ub3RhdGlvblN0b3JhZ2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBmaWx0ZXJGYWN0b3J5KCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNwb3J0LmZpbHRlckZhY3Rvcnk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBudW1QYWdlcygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3BkZkluZm8ubnVtUGFnZXM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBmaW5nZXJwcmludHMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9wZGZJbmZvLmZpbmdlcnByaW50czsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGlzUHVyZVhmYSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJpc1B1cmVYZmEiLCAhIXRoaXMuX3RyYW5zcG9ydC5faHRtbEZvclhmYSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBhbGxYZmFIdG1sKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNwb3J0Ll9odG1sRm9yWGZhOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRQYWdlKHBhZ2VOdW1iZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3RyYW5zcG9ydC5nZXRQYWdlKHBhZ2VOdW1iZXIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRQYWdlSW5kZXgocmVmKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuZ2V0UGFnZUluZGV4KHJlZik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldERlc3RpbmF0aW9ucygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3RyYW5zcG9ydC5nZXREZXN0aW5hdGlvbnMoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0RGVzdGluYXRpb24oaWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3RyYW5zcG9ydC5nZXREZXN0aW5hdGlvbihpZCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldFBhZ2VMYWJlbHMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuZ2V0UGFnZUxhYmVscygpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRQYWdlTGF5b3V0KCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNwb3J0LmdldFBhZ2VMYXlvdXQoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0UGFnZU1vZGUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuZ2V0UGFnZU1vZGUoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0Vmlld2VyUHJlZmVyZW5jZXMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuZ2V0Vmlld2VyUHJlZmVyZW5jZXMoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0T3BlbkFjdGlvbigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3RyYW5zcG9ydC5nZXRPcGVuQWN0aW9uKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldEF0dGFjaG1lbnRzKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNwb3J0LmdldEF0dGFjaG1lbnRzKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldEphdmFTY3JpcHQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuZ2V0SmF2YVNjcmlwdCgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRKU0FjdGlvbnMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuZ2V0RG9jSlNBY3Rpb25zKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldE91dGxpbmUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuZ2V0T3V0bGluZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbENvbnRlbnRDb25maWcoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuZ2V0T3B0aW9uYWxDb250ZW50Q29uZmlnKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldFBlcm1pc3Npb25zKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNwb3J0LmdldFBlcm1pc3Npb25zKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldE1ldGFkYXRhKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNwb3J0LmdldE1ldGFkYXRhKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldE1hcmtJbmZvKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNwb3J0LmdldE1hcmtJbmZvKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldERhdGEoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuZ2V0RGF0YSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzYXZlRG9jdW1lbnQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuc2F2ZURvY3VtZW50KCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldERvd25sb2FkSW5mbygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3RyYW5zcG9ydC5kb3dubG9hZEluZm9DYXBhYmlsaXR5LnByb21pc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNsZWFudXAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBrZWVwTG9hZGVkRm9udHMgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNwb3J0LnN0YXJ0Q2xlYW51cChrZWVwTG9hZGVkRm9udHMgfHwgdGhpcy5pc1B1cmVYZmEpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkZXN0cm95KCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5sb2FkaW5nVGFzay5kZXN0cm95KCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBsb2FkaW5nUGFyYW1zKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNwb3J0LmxvYWRpbmdQYXJhbXM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBsb2FkaW5nVGFzaygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3RyYW5zcG9ydC5sb2FkaW5nVGFzazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0RmllbGRPYmplY3RzKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNwb3J0LmdldEZpZWxkT2JqZWN0cygpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBoYXNKU0FjdGlvbnMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuaGFzSlNBY3Rpb25zKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldENhbGN1bGF0aW9uT3JkZXJJZHMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuZ2V0Q2FsY3VsYXRpb25PcmRlcklkcygpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuUERGRG9jdW1lbnRQcm94eSA9IFBERkRvY3VtZW50UHJveHk7CiAgICAgICAgICAgICAgICB2YXIgX2RlbGF5ZWRDbGVhbnVwVGltZW91dCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9wZW5kaW5nQ2xlYW51cCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF90cnlDbGVhbnVwID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICB2YXIgX2Fib3J0RGVsYXllZENsZWFudXAgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIGNsYXNzIFBERlBhZ2VQcm94eSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFnZUluZGV4LCBwYWdlSW5mbywgdHJhbnNwb3J0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBwZGZCdWcgPSBhcmd1bWVudHMubGVuZ3RoID4gMyAmJiBhcmd1bWVudHNbM10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1szXSA6IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2Fib3J0RGVsYXllZENsZWFudXApOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX3RyeUNsZWFudXApOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfZGVsYXllZENsZWFudXBUaW1lb3V0LCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBudWxsCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfcGVuZGluZ0NsZWFudXAsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGZhbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wYWdlSW5kZXggPSBwYWdlSW5kZXg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3BhZ2VJbmZvID0gcGFnZUluZm87CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3RyYW5zcG9ydCA9IHRyYW5zcG9ydDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RhdHMgPSBwZGZCdWcgPyBuZXcgX2Rpc3BsYXlfdXRpbHMuU3RhdFRpbWVyKCkgOiBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wZGZCdWcgPSBwZGZCdWc7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbW9uT2JqcyA9IHRyYW5zcG9ydC5jb21tb25PYmpzOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9ianMgPSBuZXcgUERGT2JqZWN0cygpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9tYXliZUNsZWFudXBBZnRlclJlbmRlciA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9pbnRlbnRTdGF0ZXMgPSBuZXcgTWFwKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVzdHJveWVkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBwYWdlTnVtYmVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcGFnZUluZGV4ICsgMTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IHJvdGF0ZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3BhZ2VJbmZvLnJvdGF0ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IHJlZigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3BhZ2VJbmZvLnJlZjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IHVzZXJVbml0KCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcGFnZUluZm8udXNlclVuaXQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCB2aWV3KCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcGFnZUluZm8udmlldzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0Vmlld3BvcnQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0aW9uID0gdGhpcy5yb3RhdGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRYID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldFkgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9udEZsaXAgPSBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiB7fTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBfZGlzcGxheV91dGlscy5QYWdlVmlld3BvcnQoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlld0JveDogdGhpcy52aWV3LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3RhdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldFgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRZLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9udEZsaXAKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldEFubm90YXRpb25zKCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50ID0gImRpc3BsYXkiCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHt9OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbnRlbnRBcmdzID0gdGhpcy5fdHJhbnNwb3J0LmdldFJlbmRlcmluZ0ludGVudChpbnRlbnQpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNwb3J0LmdldEFubm90YXRpb25zKHRoaXMuX3BhZ2VJbmRleCwgaW50ZW50QXJncy5yZW5kZXJpbmdJbnRlbnQpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRKU0FjdGlvbnMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQuZ2V0UGFnZUpTQWN0aW9ucyh0aGlzLl9wYWdlSW5kZXgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgaXNQdXJlWGZhKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImlzUHVyZVhmYSIsICEhdGhpcy5fdHJhbnNwb3J0Ll9odG1sRm9yWGZhKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYXN5bmMgZ2V0WGZhKCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkX3RyYW5zcG9ydCRfaHRtOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKChfdGhpcyRfdHJhbnNwb3J0JF9odG0gPSB0aGlzLl90cmFuc3BvcnQuX2h0bWxGb3JYZmEpID09PSBudWxsIHx8IF90aGlzJF90cmFuc3BvcnQkX2h0bSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkX3RyYW5zcG9ydCRfaHRtLmNoaWxkcmVuW3RoaXMuX3BhZ2VJbmRleF0pIHx8IG51bGw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbmRlcihfcmVmMikgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkX3N0YXRzOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzQ29udGV4dCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdwb3J0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50ID0gImRpc3BsYXkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbk1vZGUgPSBfdXRpbC5Bbm5vdGF0aW9uTW9kZS5FTkFCTEUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSBudWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzRmFjdG9yeSA9IG51bGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kID0gbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbmFsQ29udGVudENvbmZpZ1Byb21pc2UgPSBudWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbkNhbnZhc01hcCA9IG51bGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlQ29sb3JzID0gbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW50QW5ub3RhdGlvblN0b3JhZ2UgPSBudWxsCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmMjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNhbnZhc0ZhY3RvcnkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfZGlzcGxheV91dGlscy5kZXByZWNhdGVkKSgicmVuZGVyIG5vIGxvbmdlciBhY2NlcHRzIHRoZSBgY2FudmFzRmFjdG9yeWAtb3B0aW9uLCAiICsgInBsZWFzZSBwYXNzIGl0IHRvIHRoZSBgZ2V0RG9jdW1lbnRgLWZ1bmN0aW9uIGluc3RlYWQuIik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJF9zdGF0cyA9IHRoaXMuX3N0YXRzKSA9PT0gbnVsbCB8fCBfdGhpcyRfc3RhdHMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJF9zdGF0cy50aW1lKCJPdmVyYWxsIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGludGVudEFyZ3MgPSB0aGlzLl90cmFuc3BvcnQuZ2V0UmVuZGVyaW5nSW50ZW50KGludGVudCwgYW5ub3RhdGlvbk1vZGUsIHByaW50QW5ub3RhdGlvblN0b3JhZ2UpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX3BlbmRpbmdDbGVhbnVwLCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2Fib3J0RGVsYXllZENsZWFudXAsIF9hYm9ydERlbGF5ZWRDbGVhbnVwMikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFvcHRpb25hbENvbnRlbnRDb25maWdQcm9taXNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25hbENvbnRlbnRDb25maWdQcm9taXNlID0gdGhpcy5fdHJhbnNwb3J0LmdldE9wdGlvbmFsQ29udGVudENvbmZpZygpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBpbnRlbnRTdGF0ZSA9IHRoaXMuX2ludGVudFN0YXRlcy5nZXQoaW50ZW50QXJncy5jYWNoZUtleSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaW50ZW50U3RhdGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudFN0YXRlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2ludGVudFN0YXRlcy5zZXQoaW50ZW50QXJncy5jYWNoZUtleSwgaW50ZW50U3RhdGUpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnRlbnRTdGF0ZS5zdHJlYW1SZWFkZXJDYW5jZWxUaW1lb3V0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQoaW50ZW50U3RhdGUuc3RyZWFtUmVhZGVyQ2FuY2VsVGltZW91dCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlbnRTdGF0ZS5zdHJlYW1SZWFkZXJDYW5jZWxUaW1lb3V0ID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbnRlbnRQcmludCA9ICEhKGludGVudEFyZ3MucmVuZGVyaW5nSW50ZW50ICYgX3V0aWwuUmVuZGVyaW5nSW50ZW50RmxhZy5QUklOVCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaW50ZW50U3RhdGUuZGlzcGxheVJlYWR5Q2FwYWJpbGl0eSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJF9zdGF0czI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlbnRTdGF0ZS5kaXNwbGF5UmVhZHlDYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50U3RhdGUub3BlcmF0b3JMaXN0ID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZuQXJyYXk6IFtdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3NBcnJheTogW10sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdENodW5rOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0ZUFubm90czogbnVsbAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRfc3RhdHMyID0gdGhpcy5fc3RhdHMpID09PSBudWxsIHx8IF90aGlzJF9zdGF0czIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJF9zdGF0czIudGltZSgiUGFnZSBSZXF1ZXN0Iik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wdW1wT3BlcmF0b3JMaXN0KGludGVudEFyZ3MpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbXBsZXRlID0gZXJyb3IgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJF9zdGF0czMsIF90aGlzJF9zdGF0czQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlbnRTdGF0ZS5yZW5kZXJUYXNrcy5kZWxldGUoaW50ZXJuYWxSZW5kZXJUYXNrKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9tYXliZUNsZWFudXBBZnRlclJlbmRlciB8fCBpbnRlbnRQcmludCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfcGVuZGluZ0NsZWFudXAsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfdHJ5Q2xlYW51cCwgX3RyeUNsZWFudXAyKS5jYWxsKHRoaXMsICFpbnRlbnRQcmludCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcm5hbFJlbmRlclRhc2suY2FwYWJpbGl0eS5yZWplY3QoZXJyb3IpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Fib3J0T3BlcmF0b3JMaXN0KHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50U3RhdGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yIDogbmV3IEVycm9yKGVycm9yKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcm5hbFJlbmRlclRhc2suY2FwYWJpbGl0eS5yZXNvbHZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkX3N0YXRzMyA9IHRoaXMuX3N0YXRzKSA9PT0gbnVsbCB8fCBfdGhpcyRfc3RhdHMzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRfc3RhdHMzLnRpbWVFbmQoIlJlbmRlcmluZyIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJF9zdGF0czQgPSB0aGlzLl9zdGF0cykgPT09IG51bGwgfHwgX3RoaXMkX3N0YXRzNCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkX3N0YXRzNC50aW1lRW5kKCJPdmVyYWxsIik7CiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGludGVybmFsUmVuZGVyVGFzayA9IG5ldyBJbnRlcm5hbFJlbmRlclRhc2soewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2s6IGNvbXBsZXRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzQ29udGV4dCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3cG9ydCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ianM6IHRoaXMub2JqcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbW1vbk9ianM6IHRoaXMuY29tbW9uT2JqcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25DYW52YXNNYXAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGVyYXRvckxpc3Q6IGludGVudFN0YXRlLm9wZXJhdG9yTGlzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VJbmRleDogdGhpcy5fcGFnZUluZGV4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzRmFjdG9yeTogY2FudmFzRmFjdG9yeSB8fCB0aGlzLl90cmFuc3BvcnQuY2FudmFzRmFjdG9yeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlckZhY3Rvcnk6IHRoaXMuX3RyYW5zcG9ydC5maWx0ZXJGYWN0b3J5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlUmVxdWVzdEFuaW1hdGlvbkZyYW1lOiAhaW50ZW50UHJpbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZGZCdWc6IHRoaXMuX3BkZkJ1ZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VDb2xvcnMKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIChpbnRlbnRTdGF0ZS5yZW5kZXJUYXNrcyB8fD0gbmV3IFNldCgpKS5hZGQoaW50ZXJuYWxSZW5kZXJUYXNrKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVuZGVyVGFzayA9IGludGVybmFsUmVuZGVyVGFzay50YXNrOwogICAgICAgICAgICAgICAgICAgICAgICBQcm9taXNlLmFsbChbaW50ZW50U3RhdGUuZGlzcGxheVJlYWR5Q2FwYWJpbGl0eS5wcm9taXNlLCBvcHRpb25hbENvbnRlbnRDb25maWdQcm9taXNlXSkudGhlbihfcmVmMyA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkX3N0YXRzNTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBbdHJhbnNwYXJlbmN5LCBvcHRpb25hbENvbnRlbnRDb25maWddID0gX3JlZjM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9wZW5kaW5nQ2xlYW51cCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wbGV0ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRfc3RhdHM1ID0gdGhpcy5fc3RhdHMpID09PSBudWxsIHx8IF90aGlzJF9zdGF0czUgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJF9zdGF0czUudGltZSgiUmVuZGVyaW5nIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcm5hbFJlbmRlclRhc2suaW5pdGlhbGl6ZUdyYXBoaWNzKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc3BhcmVuY3ksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxDb250ZW50Q29uZmlnCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVybmFsUmVuZGVyVGFzay5vcGVyYXRvckxpc3RDaGFuZ2VkKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGNvbXBsZXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlclRhc2s7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldE9wZXJhdG9yTGlzdCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudCA9ICJkaXNwbGF5IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25Nb2RlID0gX3V0aWwuQW5ub3RhdGlvbk1vZGUuRU5BQkxFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJpbnRBbm5vdGF0aW9uU3RvcmFnZSA9IG51bGwKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDoge307CiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIG9wZXJhdG9yTGlzdENoYW5nZWQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW50ZW50U3RhdGUub3BlcmF0b3JMaXN0Lmxhc3RDaHVuaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudFN0YXRlLm9wTGlzdFJlYWRDYXBhYmlsaXR5LnJlc29sdmUoaW50ZW50U3RhdGUub3BlcmF0b3JMaXN0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlbnRTdGF0ZS5yZW5kZXJUYXNrcy5kZWxldGUob3BMaXN0VGFzayk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW50ZW50QXJncyA9IHRoaXMuX3RyYW5zcG9ydC5nZXRSZW5kZXJpbmdJbnRlbnQoaW50ZW50LCBhbm5vdGF0aW9uTW9kZSwgcHJpbnRBbm5vdGF0aW9uU3RvcmFnZSwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBpbnRlbnRTdGF0ZSA9IHRoaXMuX2ludGVudFN0YXRlcy5nZXQoaW50ZW50QXJncy5jYWNoZUtleSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaW50ZW50U3RhdGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudFN0YXRlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2ludGVudFN0YXRlcy5zZXQoaW50ZW50QXJncy5jYWNoZUtleSwgaW50ZW50U3RhdGUpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBvcExpc3RUYXNrOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWludGVudFN0YXRlLm9wTGlzdFJlYWRDYXBhYmlsaXR5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkX3N0YXRzNjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wTGlzdFRhc2sgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3BMaXN0VGFzay5vcGVyYXRvckxpc3RDaGFuZ2VkID0gb3BlcmF0b3JMaXN0Q2hhbmdlZDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudFN0YXRlLm9wTGlzdFJlYWRDYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgKGludGVudFN0YXRlLnJlbmRlclRhc2tzIHx8PSBuZXcgU2V0KCkpLmFkZChvcExpc3RUYXNrKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudFN0YXRlLm9wZXJhdG9yTGlzdCA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbkFycmF5OiBbXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmdzQXJyYXk6IFtdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RDaHVuazogZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdGVBbm5vdHM6IG51bGwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkX3N0YXRzNiA9IHRoaXMuX3N0YXRzKSA9PT0gbnVsbCB8fCBfdGhpcyRfc3RhdHM2ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRfc3RhdHM2LnRpbWUoIlBhZ2UgUmVxdWVzdCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHVtcE9wZXJhdG9yTGlzdChpbnRlbnRBcmdzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW50ZW50U3RhdGUub3BMaXN0UmVhZENhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RyZWFtVGV4dENvbnRlbnQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlQ29tYmluZVRleHRJdGVtcyA9IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZU1hcmtlZENvbnRlbnQgPSBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiB7fTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgVEVYVF9DT05URU5UX0NIVU5LX1NJWkUgPSAxMDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl90cmFuc3BvcnQubWVzc2FnZUhhbmRsZXIuc2VuZFdpdGhTdHJlYW0oIkdldFRleHRDb250ZW50IiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUluZGV4OiB0aGlzLl9wYWdlSW5kZXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21iaW5lVGV4dEl0ZW1zOiBkaXNhYmxlQ29tYmluZVRleHRJdGVtcyAhPT0gdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluY2x1ZGVNYXJrZWRDb250ZW50OiBpbmNsdWRlTWFya2VkQ29udGVudCA9PT0gdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICB9LCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWdoV2F0ZXJNYXJrOiBURVhUX0NPTlRFTlRfQ0hVTktfU0laRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUodGV4dENvbnRlbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGV4dENvbnRlbnQuaXRlbXMubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0VGV4dENvbnRlbnQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBwYXJhbXMgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHt9OwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fdHJhbnNwb3J0Ll9odG1sRm9yWGZhKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRYZmEoKS50aGVuKHhmYSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF94ZmFfdGV4dC5YZmFUZXh0LnRleHRDb250ZW50KHhmYSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWFkYWJsZVN0cmVhbSA9IHRoaXMuc3RyZWFtVGV4dENvbnRlbnQocGFyYW1zKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHB1bXAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnJlYWQoKS50aGVuKGZ1bmN0aW9uIChfcmVmNCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmNDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbmUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUodGV4dENvbnRlbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24odGV4dENvbnRlbnQuc3R5bGVzLCB2YWx1ZS5zdHlsZXMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0Q29udGVudC5pdGVtcy5wdXNoKC4uLnZhbHVlLml0ZW1zKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHVtcCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIHJlamVjdCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWFkZXIgPSByZWFkYWJsZVN0cmVhbS5nZXRSZWFkZXIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRleHRDb250ZW50ID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1zOiBbXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZXM6IE9iamVjdC5jcmVhdGUobnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdW1wKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRTdHJ1Y3RUcmVlKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdHJhbnNwb3J0LmdldFN0cnVjdFRyZWUodGhpcy5fcGFnZUluZGV4KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2Rlc3Ryb3koKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVzdHJveWVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2FpdE9uID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaW50ZW50U3RhdGUgb2YgdGhpcy5faW50ZW50U3RhdGVzLnZhbHVlcygpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9hYm9ydE9wZXJhdG9yTGlzdCh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50U3RhdGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uOiBuZXcgRXJyb3IoIlBhZ2Ugd2FzIGRlc3Ryb3llZC4iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JjZTogdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW50ZW50U3RhdGUub3BMaXN0UmVhZENhcGFiaWxpdHkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaW50ZXJuYWxSZW5kZXJUYXNrIG9mIGludGVudFN0YXRlLnJlbmRlclRhc2tzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FpdE9uLnB1c2goaW50ZXJuYWxSZW5kZXJUYXNrLmNvbXBsZXRlZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJuYWxSZW5kZXJUYXNrLmNhbmNlbCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub2Jqcy5jbGVhcigpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX3BlbmRpbmdDbGVhbnVwLCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2Fib3J0RGVsYXllZENsZWFudXAsIF9hYm9ydERlbGF5ZWRDbGVhbnVwMikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHdhaXRPbik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNsZWFudXAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZXNldFN0YXRzID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9wZW5kaW5nQ2xlYW51cCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3MgPSBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF90cnlDbGVhbnVwLCBfdHJ5Q2xlYW51cDIpLmNhbGwodGhpcywgZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzZXRTdGF0cyAmJiBzdWNjZXNzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdGF0cyAmJj0gbmV3IF9kaXNwbGF5X3V0aWxzLlN0YXRUaW1lcigpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzdWNjZXNzOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfc3RhcnRSZW5kZXJQYWdlKHRyYW5zcGFyZW5jeSwgY2FjaGVLZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJF9zdGF0czcsIF9pbnRlbnRTdGF0ZSRkaXNwbGF5UjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW50ZW50U3RhdGUgPSB0aGlzLl9pbnRlbnRTdGF0ZXMuZ2V0KGNhY2hlS2V5KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpbnRlbnRTdGF0ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRfc3RhdHM3ID0gdGhpcy5fc3RhdHMpID09PSBudWxsIHx8IF90aGlzJF9zdGF0czcgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJF9zdGF0czcudGltZUVuZCgiUGFnZSBSZXF1ZXN0Iik7CiAgICAgICAgICAgICAgICAgICAgICAgIChfaW50ZW50U3RhdGUkZGlzcGxheVIgPSBpbnRlbnRTdGF0ZS5kaXNwbGF5UmVhZHlDYXBhYmlsaXR5KSA9PT0gbnVsbCB8fCBfaW50ZW50U3RhdGUkZGlzcGxheVIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9pbnRlbnRTdGF0ZSRkaXNwbGF5Ui5yZXNvbHZlKHRyYW5zcGFyZW5jeSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9yZW5kZXJQYWdlQ2h1bmsob3BlcmF0b3JMaXN0Q2h1bmssIGludGVudFN0YXRlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IG9wZXJhdG9yTGlzdENodW5rLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudFN0YXRlLm9wZXJhdG9yTGlzdC5mbkFycmF5LnB1c2gob3BlcmF0b3JMaXN0Q2h1bmsuZm5BcnJheVtpXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlbnRTdGF0ZS5vcGVyYXRvckxpc3QuYXJnc0FycmF5LnB1c2gob3BlcmF0b3JMaXN0Q2h1bmsuYXJnc0FycmF5W2ldKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpbnRlbnRTdGF0ZS5vcGVyYXRvckxpc3QubGFzdENodW5rID0gb3BlcmF0b3JMaXN0Q2h1bmsubGFzdENodW5rOwogICAgICAgICAgICAgICAgICAgICAgICBpbnRlbnRTdGF0ZS5vcGVyYXRvckxpc3Quc2VwYXJhdGVBbm5vdHMgPSBvcGVyYXRvckxpc3RDaHVuay5zZXBhcmF0ZUFubm90czsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBpbnRlcm5hbFJlbmRlclRhc2sgb2YgaW50ZW50U3RhdGUucmVuZGVyVGFza3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVybmFsUmVuZGVyVGFzay5vcGVyYXRvckxpc3RDaGFuZ2VkKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wZXJhdG9yTGlzdENodW5rLmxhc3RDaHVuaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfdHJ5Q2xlYW51cCwgX3RyeUNsZWFudXAyKS5jYWxsKHRoaXMsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9wdW1wT3BlcmF0b3JMaXN0KF9yZWY1KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJpbmdJbnRlbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWNoZUtleSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25TdG9yYWdlTWFwCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmNTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVhZGFibGVTdHJlYW0gPSB0aGlzLl90cmFuc3BvcnQubWVzc2FnZUhhbmRsZXIuc2VuZFdpdGhTdHJlYW0oIkdldE9wZXJhdG9yTGlzdCIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VJbmRleDogdGhpcy5fcGFnZUluZGV4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50OiByZW5kZXJpbmdJbnRlbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWNoZUtleSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25TdG9yYWdlOiBhbm5vdGF0aW9uU3RvcmFnZU1hcAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVhZGVyID0gcmVhZGFibGVTdHJlYW0uZ2V0UmVhZGVyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGludGVudFN0YXRlID0gdGhpcy5faW50ZW50U3RhdGVzLmdldChjYWNoZUtleSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGludGVudFN0YXRlLnN0cmVhbVJlYWRlciA9IHJlYWRlcjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcHVtcCA9ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRlci5yZWFkKCkudGhlbihfcmVmNiA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbmUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50U3RhdGUuc3RyZWFtUmVhZGVyID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fdHJhbnNwb3J0LmRlc3Ryb3llZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbmRlclBhZ2VDaHVuayh2YWx1ZSwgaW50ZW50U3RhdGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1bXAoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIHJlYXNvbiA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50U3RhdGUuc3RyZWFtUmVhZGVyID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fdHJhbnNwb3J0LmRlc3Ryb3llZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnRlbnRTdGF0ZS5vcGVyYXRvckxpc3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50U3RhdGUub3BlcmF0b3JMaXN0Lmxhc3RDaHVuayA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaW50ZXJuYWxSZW5kZXJUYXNrIG9mIGludGVudFN0YXRlLnJlbmRlclRhc2tzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcm5hbFJlbmRlclRhc2sub3BlcmF0b3JMaXN0Q2hhbmdlZCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3RyeUNsZWFudXAsIF90cnlDbGVhbnVwMikuY2FsbCh0aGlzLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGludGVudFN0YXRlLmRpc3BsYXlSZWFkeUNhcGFiaWxpdHkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50U3RhdGUuZGlzcGxheVJlYWR5Q2FwYWJpbGl0eS5yZWplY3QocmVhc29uKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGludGVudFN0YXRlLm9wTGlzdFJlYWRDYXBhYmlsaXR5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudFN0YXRlLm9wTGlzdFJlYWRDYXBhYmlsaXR5LnJlamVjdChyZWFzb24pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IHJlYXNvbjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgcHVtcCgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfYWJvcnRPcGVyYXRvckxpc3QoX3JlZjcpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudFN0YXRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2UgPSBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjc7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaW50ZW50U3RhdGUuc3RyZWFtUmVhZGVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGludGVudFN0YXRlLnN0cmVhbVJlYWRlckNhbmNlbFRpbWVvdXQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChpbnRlbnRTdGF0ZS5zdHJlYW1SZWFkZXJDYW5jZWxUaW1lb3V0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudFN0YXRlLnN0cmVhbVJlYWRlckNhbmNlbFRpbWVvdXQgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZm9yY2UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnRlbnRTdGF0ZS5yZW5kZXJUYXNrcy5zaXplID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBfZGlzcGxheV91dGlscy5SZW5kZXJpbmdDYW5jZWxsZWRFeGNlcHRpb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZGVsYXkgPSBSRU5ERVJJTkdfQ0FOQ0VMTEVEX1RJTUVPVVQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlYXNvbi5leHRyYURlbGF5ID4gMCAmJiByZWFzb24uZXh0cmFEZWxheSA8IDEwMDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsYXkgKz0gcmVhc29uLmV4dHJhRGVsYXk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudFN0YXRlLnN0cmVhbVJlYWRlckNhbmNlbFRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50U3RhdGUuc3RyZWFtUmVhZGVyQ2FuY2VsVGltZW91dCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Fib3J0T3BlcmF0b3JMaXN0KHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudFN0YXRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yY2U6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgZGVsYXkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpbnRlbnRTdGF0ZS5zdHJlYW1SZWFkZXIuY2FuY2VsKG5ldyBfdXRpbC5BYm9ydEV4Y2VwdGlvbihyZWFzb24ubWVzc2FnZSkpLmNhdGNoKCgpID0+IHt9KTsKICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50U3RhdGUuc3RyZWFtUmVhZGVyID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX3RyYW5zcG9ydC5kZXN0cm95ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IFtjdXJDYWNoZUtleSwgY3VySW50ZW50U3RhdGVdIG9mIHRoaXMuX2ludGVudFN0YXRlcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1ckludGVudFN0YXRlID09PSBpbnRlbnRTdGF0ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2ludGVudFN0YXRlcy5kZWxldGUoY3VyQ2FjaGVLZXkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYW51cCgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgc3RhdHMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9zdGF0czsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLlBERlBhZ2VQcm94eSA9IFBERlBhZ2VQcm94eTsKICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF90cnlDbGVhbnVwMigpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgZGVsYXllZCA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfYWJvcnREZWxheWVkQ2xlYW51cCwgX2Fib3J0RGVsYXllZENsZWFudXAyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgIGlmICghX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9wZW5kaW5nQ2xlYW51cCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoZGVsYXllZCkgewogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2RlbGF5ZWRDbGVhbnVwVGltZW91dCwgc2V0VGltZW91dCgoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2RlbGF5ZWRDbGVhbnVwVGltZW91dCwgbnVsbCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF90cnlDbGVhbnVwLCBfdHJ5Q2xlYW51cDIpLmNhbGwodGhpcywgZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICB9LCBERUxBWUVEX0NMRUFOVVBfVElNRU9VVCkpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJUYXNrcywKICAgICAgICAgICAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0CiAgICAgICAgICAgICAgICAgICAgfSBvZiB0aGlzLl9pbnRlbnRTdGF0ZXMudmFsdWVzKCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlbmRlclRhc2tzLnNpemUgPiAwIHx8ICFvcGVyYXRvckxpc3QubGFzdENodW5rKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdGhpcy5faW50ZW50U3RhdGVzLmNsZWFyKCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5vYmpzLmNsZWFyKCk7CiAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9wZW5kaW5nQ2xlYW51cCwgZmFsc2UpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2Fib3J0RGVsYXllZENsZWFudXAyKCkgewogICAgICAgICAgICAgICAgICAgIGlmIChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RlbGF5ZWRDbGVhbnVwVGltZW91dCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZGVsYXllZENsZWFudXBUaW1lb3V0KSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfZGVsYXllZENsZWFudXBUaW1lb3V0LCBudWxsKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBMb29wYmFja1BvcnQgewogICAgICAgICAgICAgICAgICAgICNsaXN0ZW5lcnMgPSBuZXcgU2V0KCk7CiAgICAgICAgICAgICAgICAgICAgI2RlZmVycmVkID0gUHJvbWlzZS5yZXNvbHZlKCk7CiAgICAgICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2Uob2JqLCB0cmFuc2ZlcikgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBldmVudCA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IHN0cnVjdHVyZWRDbG9uZShvYmosIHRyYW5zZmVyID8gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZmVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IDogbnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jZGVmZXJyZWQudGhlbigoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGxpc3RlbmVyIG9mIHRoaXMuI2xpc3RlbmVycykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyLmNhbGwodGhpcywgZXZlbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYWRkRXZlbnRMaXN0ZW5lcihuYW1lLCBsaXN0ZW5lcikgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNsaXN0ZW5lcnMuYWRkKGxpc3RlbmVyKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlRXZlbnRMaXN0ZW5lcihuYW1lLCBsaXN0ZW5lcikgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNsaXN0ZW5lcnMuZGVsZXRlKGxpc3RlbmVyKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdGVybWluYXRlKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNsaXN0ZW5lcnMuY2xlYXIoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLkxvb3BiYWNrUG9ydCA9IExvb3BiYWNrUG9ydDsKICAgICAgICAgICAgICAgIGNvbnN0IFBERldvcmtlclV0aWwgPSB7CiAgICAgICAgICAgICAgICAgICAgaXNXb3JrZXJEaXNhYmxlZDogZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgZmFsbGJhY2tXb3JrZXJTcmM6IG51bGwsCiAgICAgICAgICAgICAgICAgICAgZmFrZVdvcmtlcklkOiAwCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgZXhwb3J0cy5QREZXb3JrZXJVdGlsID0gUERGV29ya2VyVXRpbDsKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBpZiAoX2lzX25vZGUuaXNOb2RlSlMgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgUERGV29ya2VyVXRpbC5pc1dvcmtlckRpc2FibGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgUERGV29ya2VyVXRpbC5mYWxsYmFja1dvcmtlclNyYyA9ICIuL3BkZi53b3JrZXIuanMiOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGRvY3VtZW50ID09PSAib2JqZWN0IikgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX2RvY3VtZW50LCBfZG9jdW1lbnQkY3VycmVudFNjcmk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBkZmpzRmlsZVBhdGggPSAoX2RvY3VtZW50ID0gZG9jdW1lbnQpID09PSBudWxsIHx8IF9kb2N1bWVudCA9PT0gdm9pZCAwID8gdm9pZCAwIDogKF9kb2N1bWVudCRjdXJyZW50U2NyaSA9IF9kb2N1bWVudC5jdXJyZW50U2NyaXB0KSA9PT0gbnVsbCB8fCBfZG9jdW1lbnQkY3VycmVudFNjcmkgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9kb2N1bWVudCRjdXJyZW50U2NyaS5zcmM7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwZGZqc0ZpbGVQYXRoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBQREZXb3JrZXJVdGlsLmZhbGxiYWNrV29ya2VyU3JjID0gcGRmanNGaWxlUGF0aC5yZXBsYWNlKC8oXC4oPzptaW5cLik/anMpKFw/LiopPyQvaSwgIi53b3JrZXIkMSQyIik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgUERGV29ya2VyVXRpbC5pc1NhbWVPcmlnaW4gPSBmdW5jdGlvbiAoYmFzZVVybCwgb3RoZXJVcmwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGJhc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXNlID0gbmV3IFVSTChiYXNlVXJsKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYmFzZS5vcmlnaW4gfHwgYmFzZS5vcmlnaW4gPT09ICJudWxsIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG90aGVyID0gbmV3IFVSTChvdGhlclVybCwgYmFzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBiYXNlLm9yaWdpbiA9PT0gb3RoZXIub3JpZ2luOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgUERGV29ya2VyVXRpbC5jcmVhdGVDRE5XcmFwcGVyID0gZnVuY3Rpb24gKHVybCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3cmFwcGVyID0gYGltcG9ydFNjcmlwdHMoIiR7dXJsfSIpO2A7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBVUkwuY3JlYXRlT2JqZWN0VVJMKG5ldyBCbG9iKFt3cmFwcGVyXSkpOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBQREZXb3JrZXIgewogICAgICAgICAgICAgICAgICAgIHN0YXRpYyAjd29ya2VyUG9ydHMgPSBuZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9IG51bGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3J0ID0gbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2l0eSA9ICgwLCBfdXRpbC5nZXRWZXJib3NpdHlMZXZlbCkoKQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiB7fTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBvcnQgJiYgUERGV29ya2VyLiN3b3JrZXJQb3J0cy5oYXMocG9ydCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiQ2Fubm90IHVzZSBtb3JlIHRoYW4gb25lIFBERldvcmtlciBwZXIgcG9ydC4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hbWUgPSBuYW1lOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlc3Ryb3llZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZlcmJvc2l0eSA9IHZlcmJvc2l0eTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZHlDYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wb3J0ID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fd2ViV29ya2VyID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbWVzc2FnZUhhbmRsZXIgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAocG9ydCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgUERGV29ya2VyLiN3b3JrZXJQb3J0cy5zZXQocG9ydCwgdGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9pbml0aWFsaXplRnJvbVBvcnQocG9ydCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faW5pdGlhbGl6ZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgcHJvbWlzZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3JlYWR5Q2FwYWJpbGl0eS5wcm9taXNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgcG9ydCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3BvcnQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBtZXNzYWdlSGFuZGxlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX21lc3NhZ2VIYW5kbGVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfaW5pdGlhbGl6ZUZyb21Qb3J0KHBvcnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcG9ydCA9IHBvcnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX21lc3NhZ2VIYW5kbGVyID0gbmV3IF9tZXNzYWdlX2hhbmRsZXIuTWVzc2FnZUhhbmRsZXIoIm1haW4iLCAid29ya2VyIiwgcG9ydCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX21lc3NhZ2VIYW5kbGVyLm9uKCJyZWFkeSIsIGZ1bmN0aW9uICgpIHt9KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZHlDYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbWVzc2FnZUhhbmRsZXIuc2VuZCgiY29uZmlndXJlIiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zaXR5OiB0aGlzLnZlcmJvc2l0eQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2luaXRpYWxpemUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghUERGV29ya2VyVXRpbC5pc1dvcmtlckRpc2FibGVkICYmICFQREZXb3JrZXIuX21haW5UaHJlYWRXb3JrZXJNZXNzYWdlSGFuZGxlcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZXJTcmMKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBQREZXb3JrZXI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghUERGV29ya2VyVXRpbC5pc1NhbWVPcmlnaW4od2luZG93LmxvY2F0aW9uLmhyZWYsIHdvcmtlclNyYykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2VyU3JjID0gUERGV29ya2VyVXRpbC5jcmVhdGVDRE5XcmFwcGVyKG5ldyBVUkwod29ya2VyU3JjLCB3aW5kb3cubG9jYXRpb24pLmhyZWYpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3b3JrZXIgPSBuZXcgV29ya2VyKHdvcmtlclNyYyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWVzc2FnZUhhbmRsZXIgPSBuZXcgX21lc3NhZ2VfaGFuZGxlci5NZXNzYWdlSGFuZGxlcigibWFpbiIsICJ3b3JrZXIiLCB3b3JrZXIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRlcm1pbmF0ZUVhcmx5ID0gKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcigiZXJyb3IiLCBvbldvcmtlckVycm9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZUhhbmRsZXIuZGVzdHJveSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZXIudGVybWluYXRlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZHlDYXBhYmlsaXR5LnJlamVjdChuZXcgRXJyb3IoIldvcmtlciB3YXMgZGVzdHJveWVkIikpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0dXBGYWtlV29ya2VyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9uV29ya2VyRXJyb3IgPSAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5fd2ViV29ya2VyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXJtaW5hdGVFYXJseSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZXIuYWRkRXZlbnRMaXN0ZW5lcigiZXJyb3IiLCBvbldvcmtlckVycm9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlSGFuZGxlci5vbigidGVzdCIsIGRhdGEgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcigiZXJyb3IiLCBvbldvcmtlckVycm9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGVzdHJveWVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXJtaW5hdGVFYXJseSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9tZXNzYWdlSGFuZGxlciA9IG1lc3NhZ2VIYW5kbGVyOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcG9ydCA9IHdvcmtlcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3dlYldvcmtlciA9IHdvcmtlcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWR5Q2FwYWJpbGl0eS5yZXNvbHZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlSGFuZGxlci5zZW5kKCJjb25maWd1cmUiLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zaXR5OiB0aGlzLnZlcmJvc2l0eQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXR1cEZha2VXb3JrZXIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VIYW5kbGVyLmRlc3Ryb3koKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdvcmtlci50ZXJtaW5hdGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VIYW5kbGVyLm9uKCJyZWFkeSIsIGRhdGEgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcigiZXJyb3IiLCBvbldvcmtlckVycm9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGVzdHJveWVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXJtaW5hdGVFYXJseSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZW5kVGVzdCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXR1cEZha2VXb3JrZXIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNlbmRUZXN0ID0gKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXN0T2JqID0gbmV3IFVpbnQ4QXJyYXkoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZUhhbmRsZXIuc2VuZCgidGVzdCIsIHRlc3RPYmosIFt0ZXN0T2JqLmJ1ZmZlcl0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VuZFRlc3QoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLmluZm8pKCJUaGUgd29ya2VyIGhhcyBiZWVuIGRpc2FibGVkLiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldHVwRmFrZVdvcmtlcigpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfc2V0dXBGYWtlV29ya2VyKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIVBERldvcmtlclV0aWwuaXNXb3JrZXJEaXNhYmxlZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJTZXR0aW5nIHVwIGZha2Ugd29ya2VyLiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgUERGV29ya2VyVXRpbC5pc1dvcmtlckRpc2FibGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBQREZXb3JrZXIuX3NldHVwRmFrZVdvcmtlckdsb2JhbC50aGVuKFdvcmtlck1lc3NhZ2VIYW5kbGVyID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWR5Q2FwYWJpbGl0eS5yZWplY3QobmV3IEVycm9yKCJXb3JrZXIgd2FzIGRlc3Ryb3llZCIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb3J0ID0gbmV3IExvb3BiYWNrUG9ydCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcG9ydCA9IHBvcnQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpZCA9IGBmYWtlJHtQREZXb3JrZXJVdGlsLmZha2VXb3JrZXJJZCsrfWA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3b3JrZXJIYW5kbGVyID0gbmV3IF9tZXNzYWdlX2hhbmRsZXIuTWVzc2FnZUhhbmRsZXIoaWQgKyAiX3dvcmtlciIsIGlkLCBwb3J0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdvcmtlck1lc3NhZ2VIYW5kbGVyLnNldHVwKHdvcmtlckhhbmRsZXIsIHBvcnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWVzc2FnZUhhbmRsZXIgPSBuZXcgX21lc3NhZ2VfaGFuZGxlci5NZXNzYWdlSGFuZGxlcihpZCwgaWQgKyAiX3dvcmtlciIsIHBvcnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbWVzc2FnZUhhbmRsZXIgPSBtZXNzYWdlSGFuZGxlcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWR5Q2FwYWJpbGl0eS5yZXNvbHZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlSGFuZGxlci5zZW5kKCJjb25maWd1cmUiLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zaXR5OiB0aGlzLnZlcmJvc2l0eQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKHJlYXNvbiA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWFkeUNhcGFiaWxpdHkucmVqZWN0KG5ldyBFcnJvcihgU2V0dGluZyB1cCBmYWtlIHdvcmtlciBmYWlsZWQ6ICIke3JlYXNvbi5tZXNzYWdlfSIuYCkpOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZGVzdHJveSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZXN0cm95ZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fd2ViV29ya2VyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl93ZWJXb3JrZXIudGVybWluYXRlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl93ZWJXb3JrZXIgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIFBERldvcmtlci4jd29ya2VyUG9ydHMuZGVsZXRlKHRoaXMuX3BvcnQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wb3J0ID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX21lc3NhZ2VIYW5kbGVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9tZXNzYWdlSGFuZGxlci5kZXN0cm95KCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9tZXNzYWdlSGFuZGxlciA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIGZyb21Qb3J0KHBhcmFtcykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIShwYXJhbXMgIT09IG51bGwgJiYgcGFyYW1zICE9PSB2b2lkIDAgJiYgcGFyYW1zLnBvcnQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlBERldvcmtlci5mcm9tUG9ydCAtIGludmFsaWQgbWV0aG9kIHNpZ25hdHVyZS4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy4jd29ya2VyUG9ydHMuaGFzKHBhcmFtcy5wb3J0KSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuI3dvcmtlclBvcnRzLmdldChwYXJhbXMucG9ydCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQREZXb3JrZXIocGFyYW1zKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIGdldCB3b3JrZXJTcmMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfd29ya2VyX29wdGlvbnMuR2xvYmFsV29ya2VyT3B0aW9ucy53b3JrZXJTcmMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBfd29ya2VyX29wdGlvbnMuR2xvYmFsV29ya2VyT3B0aW9ucy53b3JrZXJTcmM7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFBERldvcmtlclV0aWwuZmFsbGJhY2tXb3JrZXJTcmMgIT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghX2lzX25vZGUuaXNOb2RlSlMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX2Rpc3BsYXlfdXRpbHMuZGVwcmVjYXRlZCkoJ05vICJHbG9iYWxXb3JrZXJPcHRpb25zLndvcmtlclNyYyIgc3BlY2lmaWVkLicpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFBERldvcmtlclV0aWwuZmFsbGJhY2tXb3JrZXJTcmM7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyAiR2xvYmFsV29ya2VyT3B0aW9ucy53b3JrZXJTcmMiIHNwZWNpZmllZC4nKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIGdldCBfbWFpblRocmVhZFdvcmtlck1lc3NhZ2VIYW5kbGVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9nbG9iYWxUaGlzJHBkZmpzV29yazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoKF9nbG9iYWxUaGlzJHBkZmpzV29yayA9IGdsb2JhbFRoaXMucGRmanNXb3JrZXIpID09PSBudWxsIHx8IF9nbG9iYWxUaGlzJHBkZmpzV29yayA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2dsb2JhbFRoaXMkcGRmanNXb3JrLldvcmtlck1lc3NhZ2VIYW5kbGVyKSB8fCBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIGdldCBfc2V0dXBGYWtlV29ya2VyR2xvYmFsKCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsb2FkZXIgPSBhc3luYyAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtYWluV29ya2VyTWVzc2FnZUhhbmRsZXIgPSB0aGlzLl9tYWluVGhyZWFkV29ya2VyTWVzc2FnZUhhbmRsZXI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWFpbldvcmtlck1lc3NhZ2VIYW5kbGVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1haW5Xb3JrZXJNZXNzYWdlSGFuZGxlcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfaXNfbm9kZS5pc05vZGVKUyAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gImZ1bmN0aW9uIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdvcmtlciA9IGV2YWwoInJlcXVpcmUiKSh0aGlzLndvcmtlclNyYyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdvcmtlci5Xb3JrZXJNZXNzYWdlSGFuZGxlcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0ICgwLCBfZGlzcGxheV91dGlscy5sb2FkU2NyaXB0KSh0aGlzLndvcmtlclNyYyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gd2luZG93LnBkZmpzV29ya2VyLldvcmtlck1lc3NhZ2VIYW5kbGVyOwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIl9zZXR1cEZha2VXb3JrZXJHbG9iYWwiLCBsb2FkZXIoKSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5QREZXb3JrZXIgPSBQREZXb3JrZXI7CiAgICAgICAgICAgICAgICB2YXIgX21ldGhvZFByb21pc2VzID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX3BhZ2VDYWNoZSA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9wYWdlUHJvbWlzZXMgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfY2FjaGVTaW1wbGVNZXRob2QgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIGNsYXNzIFdvcmtlclRyYW5zcG9ydCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IobWVzc2FnZUhhbmRsZXIsIGxvYWRpbmdUYXNrLCBuZXR3b3JrU3RyZWFtLCBwYXJhbXMsIGZhY3RvcnkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF9jYWNoZVNpbXBsZU1ldGhvZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9tZXRob2RQcm9taXNlcywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogbmV3IE1hcCgpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfcGFnZUNhY2hlLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBuZXcgTWFwKCkKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9wYWdlUHJvbWlzZXMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG5ldyBNYXAoKQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tZXNzYWdlSGFuZGxlciA9IG1lc3NhZ2VIYW5kbGVyOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRpbmdUYXNrID0gbG9hZGluZ1Rhc2s7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbW9uT2JqcyA9IG5ldyBQREZPYmplY3RzKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZm9udExvYWRlciA9IG5ldyBfZm9udF9sb2FkZXIuRm9udExvYWRlcih7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvd25lckRvY3VtZW50OiBwYXJhbXMub3duZXJEb2N1bWVudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlRWxlbWVudDogcGFyYW1zLnN0eWxlRWxlbWVudAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGFyYW1zID0gcGFyYW1zOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbnZhc0ZhY3RvcnkgPSBmYWN0b3J5LmNhbnZhc0ZhY3Rvcnk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyRmFjdG9yeSA9IGZhY3RvcnkuZmlsdGVyRmFjdG9yeTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jTWFwUmVhZGVyRmFjdG9yeSA9IGZhY3RvcnkuY01hcFJlYWRlckZhY3Rvcnk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhbmRhcmRGb250RGF0YUZhY3RvcnkgPSBmYWN0b3J5LnN0YW5kYXJkRm9udERhdGFGYWN0b3J5OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlc3Ryb3llZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlc3Ryb3lDYXBhYmlsaXR5ID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGFzc3dvcmRDYXBhYmlsaXR5ID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbmV0d29ya1N0cmVhbSA9IG5ldHdvcmtTdHJlYW07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Z1bGxSZWFkZXIgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9sYXN0UHJvZ3Jlc3MgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRvd25sb2FkSW5mb0NhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dXBNZXNzYWdlSGFuZGxlcigpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgYW5ub3RhdGlvblN0b3JhZ2UoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiYW5ub3RhdGlvblN0b3JhZ2UiLCBuZXcgX2Fubm90YXRpb25fc3RvcmFnZS5Bbm5vdGF0aW9uU3RvcmFnZSgpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0UmVuZGVyaW5nSW50ZW50KGludGVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgYW5ub3RhdGlvbk1vZGUgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IF91dGlsLkFubm90YXRpb25Nb2RlLkVOQUJMRTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHByaW50QW5ub3RhdGlvblN0b3JhZ2UgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBpc09wTGlzdCA9IGFyZ3VtZW50cy5sZW5ndGggPiAzICYmIGFyZ3VtZW50c1szXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzNdIDogZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZW5kZXJpbmdJbnRlbnQgPSBfdXRpbC5SZW5kZXJpbmdJbnRlbnRGbGFnLkRJU1BMQVk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhbm5vdGF0aW9uTWFwID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChpbnRlbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgImFueSI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyaW5nSW50ZW50ID0gX3V0aWwuUmVuZGVyaW5nSW50ZW50RmxhZy5BTlk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJkaXNwbGF5IjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgInByaW50IjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJpbmdJbnRlbnQgPSBfdXRpbC5SZW5kZXJpbmdJbnRlbnRGbGFnLlBSSU5UOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYGdldFJlbmRlcmluZ0ludGVudCAtIGludmFsaWQgaW50ZW50OiAke2ludGVudH1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGFubm90YXRpb25Nb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25Nb2RlLkRJU0FCTEU6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyaW5nSW50ZW50ICs9IF91dGlsLlJlbmRlcmluZ0ludGVudEZsYWcuQU5OT1RBVElPTlNfRElTQUJMRTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuQW5ub3RhdGlvbk1vZGUuRU5BQkxFOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uTW9kZS5FTkFCTEVfRk9STVM6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyaW5nSW50ZW50ICs9IF91dGlsLlJlbmRlcmluZ0ludGVudEZsYWcuQU5OT1RBVElPTlNfRk9STVM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25Nb2RlLkVOQUJMRV9TVE9SQUdFOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlcmluZ0ludGVudCArPSBfdXRpbC5SZW5kZXJpbmdJbnRlbnRGbGFnLkFOTk9UQVRJT05TX1NUT1JBR0U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYW5ub3RhdGlvblN0b3JhZ2UgPSByZW5kZXJpbmdJbnRlbnQgJiBfdXRpbC5SZW5kZXJpbmdJbnRlbnRGbGFnLlBSSU5UICYmIHByaW50QW5ub3RhdGlvblN0b3JhZ2UgaW5zdGFuY2VvZiBfYW5ub3RhdGlvbl9zdG9yYWdlLlByaW50QW5ub3RhdGlvblN0b3JhZ2UgPyBwcmludEFubm90YXRpb25TdG9yYWdlIDogdGhpcy5hbm5vdGF0aW9uU3RvcmFnZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uTWFwID0gYW5ub3RhdGlvblN0b3JhZ2Uuc2VyaWFsaXphYmxlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYGdldFJlbmRlcmluZ0ludGVudCAtIGludmFsaWQgYW5ub3RhdGlvbk1vZGU6ICR7YW5ub3RhdGlvbk1vZGV9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT3BMaXN0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJpbmdJbnRlbnQgKz0gX3V0aWwuUmVuZGVyaW5nSW50ZW50RmxhZy5PUExJU1Q7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlcmluZ0ludGVudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlS2V5OiBgJHtyZW5kZXJpbmdJbnRlbnR9XyR7X2Fubm90YXRpb25fc3RvcmFnZS5Bbm5vdGF0aW9uU3RvcmFnZS5nZXRIYXNoKGFubm90YXRpb25NYXApfWAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uU3RvcmFnZU1hcDogYW5ub3RhdGlvbk1hcAogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkZXN0cm95KCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kZXN0cm95Q2FwYWJpbGl0eSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVzdHJveUNhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlc3Ryb3llZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVzdHJveUNhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9wYXNzd29yZENhcGFiaWxpdHkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Bhc3N3b3JkQ2FwYWJpbGl0eS5yZWplY3QobmV3IEVycm9yKCJXb3JrZXIgd2FzIGRlc3Ryb3llZCBkdXJpbmcgb25QYXNzd29yZCBjYWxsYmFjayIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3YWl0T24gPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBwYWdlIG9mIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfcGFnZUNhY2hlKS52YWx1ZXMoKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FpdE9uLnB1c2gocGFnZS5fZGVzdHJveSgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3BhZ2VDYWNoZSkuY2xlYXIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9wYWdlUHJvbWlzZXMpLmNsZWFyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmhhc093blByb3BlcnR5KCJhbm5vdGF0aW9uU3RvcmFnZSIpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFubm90YXRpb25TdG9yYWdlLnJlc2V0TW9kaWZpZWQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXJtaW5hdGVkID0gdGhpcy5tZXNzYWdlSGFuZGxlci5zZW5kV2l0aFByb21pc2UoIlRlcm1pbmF0ZSIsIG51bGwpOwogICAgICAgICAgICAgICAgICAgICAgICB3YWl0T24ucHVzaCh0ZXJtaW5hdGVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgUHJvbWlzZS5hbGwod2FpdE9uKS50aGVuKCgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbW9uT2Jqcy5jbGVhcigpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mb250TG9hZGVyLmNsZWFyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX21ldGhvZFByb21pc2VzKS5jbGVhcigpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWx0ZXJGYWN0b3J5LmRlc3Ryb3koKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9uZXR3b3JrU3RyZWFtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbmV0d29ya1N0cmVhbS5jYW5jZWxBbGxSZXF1ZXN0cyhuZXcgX3V0aWwuQWJvcnRFeGNlcHRpb24oIldvcmtlciB3YXMgdGVybWluYXRlZC4iKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5tZXNzYWdlSGFuZGxlcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWVzc2FnZUhhbmRsZXIuZGVzdHJveSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWVzc2FnZUhhbmRsZXIgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZXN0cm95Q2FwYWJpbGl0eS5yZXNvbHZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0sIHRoaXMuZGVzdHJveUNhcGFiaWxpdHkucmVqZWN0KTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVzdHJveUNhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0dXBNZXNzYWdlSGFuZGxlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZUhhbmRsZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2FkaW5nVGFzawogICAgICAgICAgICAgICAgICAgICAgICB9ID0gdGhpczsKICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZUhhbmRsZXIub24oIkdldFJlYWRlciIsIChkYXRhLCBzaW5rKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwuYXNzZXJ0KSh0aGlzLl9uZXR3b3JrU3RyZWFtLCAiR2V0UmVhZGVyIC0gbm8gYElQREZTdHJlYW1gIGluc3RhbmNlIGF2YWlsYWJsZS4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Z1bGxSZWFkZXIgPSB0aGlzLl9uZXR3b3JrU3RyZWFtLmdldEZ1bGxSZWFkZXIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Z1bGxSZWFkZXIub25Qcm9ncmVzcyA9IGV2dCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbGFzdFByb2dyZXNzID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2FkZWQ6IGV2dC5sb2FkZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsOiBldnQudG90YWwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbmsub25QdWxsID0gKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Z1bGxSZWFkZXIucmVhZCgpLnRoZW4oZnVuY3Rpb24gKF9yZWY4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA9IF9yZWY4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2luay5jbG9zZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC5hc3NlcnQpKHZhbHVlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIsICJHZXRSZWFkZXIgLSBleHBlY3RlZCBhbiBBcnJheUJ1ZmZlci4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2luay5lbnF1ZXVlKG5ldyBVaW50OEFycmF5KHZhbHVlKSwgMSwgW3ZhbHVlXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2luay5lcnJvcihyZWFzb24pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbmsub25DYW5jZWwgPSByZWFzb24gPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Z1bGxSZWFkZXIuY2FuY2VsKHJlYXNvbik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2luay5yZWFkeS5jYXRjaChyZWFkeVJlYXNvbiA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IHJlYWR5UmVhc29uOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VIYW5kbGVyLm9uKCJSZWFkZXJIZWFkZXJzUmVhZHkiLCBkYXRhID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlYWRlcnNDYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZnVsbFJlYWRlciA9IHRoaXMuX2Z1bGxSZWFkZXI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdWxsUmVhZGVyLmhlYWRlcnNSZWFkeS50aGVuKCgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWZ1bGxSZWFkZXIuaXNTdHJlYW1pbmdTdXBwb3J0ZWQgfHwgIWZ1bGxSZWFkZXIuaXNSYW5nZVN1cHBvcnRlZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fbGFzdFByb2dyZXNzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX2xvYWRpbmdUYXNrJG9uUHJvZ3JlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKF9sb2FkaW5nVGFzayRvblByb2dyZSA9IGxvYWRpbmdUYXNrLm9uUHJvZ3Jlc3MpID09PSBudWxsIHx8IF9sb2FkaW5nVGFzayRvblByb2dyZSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2xvYWRpbmdUYXNrJG9uUHJvZ3JlLmNhbGwobG9hZGluZ1Rhc2ssIHRoaXMuX2xhc3RQcm9ncmVzcyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZnVsbFJlYWRlci5vblByb2dyZXNzID0gZXZ0ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfbG9hZGluZ1Rhc2skb25Qcm9ncmUyOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKF9sb2FkaW5nVGFzayRvblByb2dyZTIgPSBsb2FkaW5nVGFzay5vblByb2dyZXNzKSA9PT0gbnVsbCB8fCBfbG9hZGluZ1Rhc2skb25Qcm9ncmUyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfbG9hZGluZ1Rhc2skb25Qcm9ncmUyLmNhbGwobG9hZGluZ1Rhc2ssIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2FkZWQ6IGV2dC5sb2FkZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWw6IGV2dC50b3RhbAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlcnNDYXBhYmlsaXR5LnJlc29sdmUoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1N0cmVhbWluZ1N1cHBvcnRlZDogZnVsbFJlYWRlci5pc1N0cmVhbWluZ1N1cHBvcnRlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNSYW5nZVN1cHBvcnRlZDogZnVsbFJlYWRlci5pc1JhbmdlU3VwcG9ydGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50TGVuZ3RoOiBmdWxsUmVhZGVyLmNvbnRlbnRMZW5ndGgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIGhlYWRlcnNDYXBhYmlsaXR5LnJlamVjdCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaGVhZGVyc0NhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VIYW5kbGVyLm9uKCJHZXRSYW5nZVJlYWRlciIsIChkYXRhLCBzaW5rKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwuYXNzZXJ0KSh0aGlzLl9uZXR3b3JrU3RyZWFtLCAiR2V0UmFuZ2VSZWFkZXIgLSBubyBgSVBERlN0cmVhbWAgaW5zdGFuY2UgYXZhaWxhYmxlLiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2VSZWFkZXIgPSB0aGlzLl9uZXR3b3JrU3RyZWFtLmdldFJhbmdlUmVhZGVyKGRhdGEuYmVnaW4sIGRhdGEuZW5kKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghcmFuZ2VSZWFkZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW5rLmNsb3NlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2luay5vblB1bGwgPSAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2VSZWFkZXIucmVhZCgpLnRoZW4oZnVuY3Rpb24gKF9yZWY5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA9IF9yZWY5OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2luay5jbG9zZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC5hc3NlcnQpKHZhbHVlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIsICJHZXRSYW5nZVJlYWRlciAtIGV4cGVjdGVkIGFuIEFycmF5QnVmZmVyLiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW5rLmVucXVldWUobmV3IFVpbnQ4QXJyYXkodmFsdWUpLCAxLCBbdmFsdWVdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaChyZWFzb24gPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW5rLmVycm9yKHJlYXNvbik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2luay5vbkNhbmNlbCA9IHJlYXNvbiA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2VSZWFkZXIuY2FuY2VsKHJlYXNvbik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2luay5yZWFkeS5jYXRjaChyZWFkeVJlYXNvbiA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IHJlYWR5UmVhc29uOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VIYW5kbGVyLm9uKCJHZXREb2MiLCBfcmVmMTAgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZGZJbmZvCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjEwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbnVtUGFnZXMgPSBwZGZJbmZvLm51bVBhZ2VzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faHRtbEZvclhmYSA9IHBkZkluZm8uaHRtbEZvclhmYTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBwZGZJbmZvLmh0bWxGb3JYZmE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2FkaW5nVGFzay5fY2FwYWJpbGl0eS5yZXNvbHZlKG5ldyBQREZEb2N1bWVudFByb3h5KHBkZkluZm8sIHRoaXMpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VIYW5kbGVyLm9uKCJEb2NFeGNlcHRpb24iLCBmdW5jdGlvbiAoZXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZWFzb247CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGV4Lm5hbWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJQYXNzd29yZEV4Y2VwdGlvbiI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbiA9IG5ldyBfdXRpbC5QYXNzd29yZEV4Y2VwdGlvbihleC5tZXNzYWdlLCBleC5jb2RlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiSW52YWxpZFBERkV4Y2VwdGlvbiI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbiA9IG5ldyBfdXRpbC5JbnZhbGlkUERGRXhjZXB0aW9uKGV4Lm1lc3NhZ2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJNaXNzaW5nUERGRXhjZXB0aW9uIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uID0gbmV3IF91dGlsLk1pc3NpbmdQREZFeGNlcHRpb24oZXgubWVzc2FnZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIlVuZXhwZWN0ZWRSZXNwb25zZUV4Y2VwdGlvbiI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbiA9IG5ldyBfdXRpbC5VbmV4cGVjdGVkUmVzcG9uc2VFeGNlcHRpb24oZXgubWVzc2FnZSwgZXguc3RhdHVzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiVW5rbm93bkVycm9yRXhjZXB0aW9uIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uID0gbmV3IF91dGlsLlVua25vd25FcnJvckV4Y2VwdGlvbihleC5tZXNzYWdlLCBleC5kZXRhaWxzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiRG9jRXhjZXB0aW9uIC0gZXhwZWN0ZWQgYSB2YWxpZCBFcnJvci4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvYWRpbmdUYXNrLl9jYXBhYmlsaXR5LnJlamVjdChyZWFzb24pOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZUhhbmRsZXIub24oIlBhc3N3b3JkUmVxdWVzdCIsIGV4Y2VwdGlvbiA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wYXNzd29yZENhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobG9hZGluZ1Rhc2sub25QYXNzd29yZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVwZGF0ZVBhc3N3b3JkID0gcGFzc3dvcmQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFzc3dvcmQgaW5zdGFuY2VvZiBFcnJvcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGFzc3dvcmRDYXBhYmlsaXR5LnJlamVjdChwYXNzd29yZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wYXNzd29yZENhcGFiaWxpdHkucmVzb2x2ZSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzc3dvcmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2FkaW5nVGFzay5vblBhc3N3b3JkKHVwZGF0ZVBhc3N3b3JkLCBleGNlcHRpb24uY29kZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGFzc3dvcmRDYXBhYmlsaXR5LnJlamVjdChleCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wYXNzd29yZENhcGFiaWxpdHkucmVqZWN0KG5ldyBfdXRpbC5QYXNzd29yZEV4Y2VwdGlvbihleGNlcHRpb24ubWVzc2FnZSwgZXhjZXB0aW9uLmNvZGUpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9wYXNzd29yZENhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VIYW5kbGVyLm9uKCJEYXRhTG9hZGVkIiwgZGF0YSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX2xvYWRpbmdUYXNrJG9uUHJvZ3JlMzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIChfbG9hZGluZ1Rhc2skb25Qcm9ncmUzID0gbG9hZGluZ1Rhc2sub25Qcm9ncmVzcykgPT09IG51bGwgfHwgX2xvYWRpbmdUYXNrJG9uUHJvZ3JlMyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2xvYWRpbmdUYXNrJG9uUHJvZ3JlMy5jYWxsKGxvYWRpbmdUYXNrLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkOiBkYXRhLmxlbmd0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbDogZGF0YS5sZW5ndGgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kb3dubG9hZEluZm9DYXBhYmlsaXR5LnJlc29sdmUoZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlSGFuZGxlci5vbigiU3RhcnRSZW5kZXJQYWdlIiwgZGF0YSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kZXN0cm95ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9wYWdlQ2FjaGUpLmdldChkYXRhLnBhZ2VJbmRleCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlLl9zdGFydFJlbmRlclBhZ2UoZGF0YS50cmFuc3BhcmVuY3ksIGRhdGEuY2FjaGVLZXkpOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZUhhbmRsZXIub24oImNvbW1vbm9iaiIsIF9yZWYxMSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX2dsb2JhbFRoaXMkRm9udEluc3BlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IFtpZCwgdHlwZSwgZXhwb3J0ZWREYXRhXSA9IF9yZWYxMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbW1vbk9ianMuaGFzKGlkKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIkZvbnQiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJhbXMgPSB0aGlzLl9wYXJhbXM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgiZXJyb3IiIGluIGV4cG9ydGVkRGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhwb3J0ZWRFcnJvciA9IGV4cG9ydGVkRGF0YS5lcnJvcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgRXJyb3IgZHVyaW5nIGZvbnQgbG9hZGluZzogJHtleHBvcnRlZEVycm9yfWApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21tb25PYmpzLnJlc29sdmUoaWQsIGV4cG9ydGVkRXJyb3IpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5zcGVjdEZvbnQgPSBwYXJhbXMucGRmQnVnICYmIChfZ2xvYmFsVGhpcyRGb250SW5zcGUgPSBnbG9iYWxUaGlzLkZvbnRJbnNwZWN0b3IpICE9PSBudWxsICYmIF9nbG9iYWxUaGlzJEZvbnRJbnNwZSAhPT0gdm9pZCAwICYmIF9nbG9iYWxUaGlzJEZvbnRJbnNwZS5lbmFibGVkID8gKGZvbnQsIHVybCkgPT4gZ2xvYmFsVGhpcy5Gb250SW5zcGVjdG9yLmZvbnRBZGRlZChmb250LCB1cmwpIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZm9udCA9IG5ldyBfZm9udF9sb2FkZXIuRm9udEZhY2VPYmplY3QoZXhwb3J0ZWREYXRhLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0V2YWxTdXBwb3J0ZWQ6IHBhcmFtcy5pc0V2YWxTdXBwb3J0ZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlRm9udEZhY2U6IHBhcmFtcy5kaXNhYmxlRm9udEZhY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmVFcnJvcnM6IHBhcmFtcy5pZ25vcmVFcnJvcnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNwZWN0Rm9udAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mb250TG9hZGVyLmJpbmQoZm9udCkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtZXNzYWdlSGFuZGxlci5zZW5kV2l0aFByb21pc2UoIkZvbnRGYWxsYmFjayIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmZpbmFsbHkoKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJhbXMuZm9udEV4dHJhUHJvcGVydGllcyAmJiBmb250LmRhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250LmRhdGEgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21tb25PYmpzLnJlc29sdmUoaWQsIGZvbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiRm9udFBhdGgiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIkltYWdlIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJQYXR0ZXJuIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21tb25PYmpzLnJlc29sdmUoaWQsIGV4cG9ydGVkRGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgR290IHVua25vd24gY29tbW9uIG9iamVjdCB0eXBlICR7dHlwZX1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VIYW5kbGVyLm9uKCJvYmoiLCBfcmVmMTIgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IFtpZCwgcGFnZUluZGV4LCB0eXBlLCBpbWFnZURhdGFdID0gX3JlZjEyOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGVzdHJveWVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFnZVByb3h5ID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9wYWdlQ2FjaGUpLmdldChwYWdlSW5kZXgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhZ2VQcm94eS5vYmpzLmhhcyhpZCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJJbWFnZSI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VQcm94eS5vYmpzLnJlc29sdmUoaWQsIGltYWdlRGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbWFnZURhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBsZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW1hZ2VEYXRhLmJpdG1hcCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBpbWFnZURhdGE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoID0gd2lkdGggKiBoZWlnaHQgKiA0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX2ltYWdlRGF0YSRkYXRhOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aCA9ICgoX2ltYWdlRGF0YSRkYXRhID0gaW1hZ2VEYXRhLmRhdGEpID09PSBudWxsIHx8IF9pbWFnZURhdGEkZGF0YSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2ltYWdlRGF0YSRkYXRhLmxlbmd0aCkgfHwgMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsZW5ndGggPiBfdXRpbC5NQVhfSU1BR0VfU0laRV9UT19DQUNIRSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VQcm94eS5fbWF5YmVDbGVhbnVwQWZ0ZXJSZW5kZXIgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIlBhdHRlcm4iOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlUHJveHkub2Jqcy5yZXNvbHZlKGlkLCBpbWFnZURhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEdvdCB1bmtub3duIG9iamVjdCB0eXBlICR7dHlwZX1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VIYW5kbGVyLm9uKCJEb2NQcm9ncmVzcyIsIGRhdGEgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9sb2FkaW5nVGFzayRvblByb2dyZTQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kZXN0cm95ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoX2xvYWRpbmdUYXNrJG9uUHJvZ3JlNCA9IGxvYWRpbmdUYXNrLm9uUHJvZ3Jlc3MpID09PSBudWxsIHx8IF9sb2FkaW5nVGFzayRvblByb2dyZTQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9sb2FkaW5nVGFzayRvblByb2dyZTQuY2FsbChsb2FkaW5nVGFzaywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvYWRlZDogZGF0YS5sb2FkZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWw6IGRhdGEudG90YWwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZUhhbmRsZXIub24oIkZldGNoQnVpbHRJbkNNYXAiLCBkYXRhID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoIldvcmtlciB3YXMgZGVzdHJveWVkLiIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jTWFwUmVhZGVyRmFjdG9yeSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoIkNNYXBSZWFkZXJGYWN0b3J5IG5vdCBpbml0aWFsaXplZCwgc2VlIHRoZSBgdXNlV29ya2VyRmV0Y2hgIHBhcmFtZXRlci4iKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jTWFwUmVhZGVyRmFjdG9yeS5mZXRjaChkYXRhKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VIYW5kbGVyLm9uKCJGZXRjaFN0YW5kYXJkRm9udERhdGEiLCBkYXRhID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoIldvcmtlciB3YXMgZGVzdHJveWVkLiIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5zdGFuZGFyZEZvbnREYXRhRmFjdG9yeSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoIlN0YW5kYXJkRm9udERhdGFGYWN0b3J5IG5vdCBpbml0aWFsaXplZCwgc2VlIHRoZSBgdXNlV29ya2VyRmV0Y2hgIHBhcmFtZXRlci4iKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zdGFuZGFyZEZvbnREYXRhRmFjdG9yeS5mZXRjaChkYXRhKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldERhdGEoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VIYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiR2V0RGF0YSIsIG51bGwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzYXZlRG9jdW1lbnQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRfZnVsbFJlYWRlcjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuYW5ub3RhdGlvblN0b3JhZ2Uuc2l6ZSA8PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoInNhdmVEb2N1bWVudCBjYWxsZWQgd2hpbGUgYGFubm90YXRpb25TdG9yYWdlYCBpcyBlbXB0eSwgIiArICJwbGVhc2UgdXNlIHRoZSBnZXREYXRhLW1ldGhvZCBpbnN0ZWFkLiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VIYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiU2F2ZURvY3VtZW50IiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNQdXJlWGZhOiAhIXRoaXMuX2h0bWxGb3JYZmEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW1QYWdlczogdGhpcy5fbnVtUGFnZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uU3RvcmFnZTogdGhpcy5hbm5vdGF0aW9uU3RvcmFnZS5zZXJpYWxpemFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlbmFtZTogKChfdGhpcyRfZnVsbFJlYWRlciA9IHRoaXMuX2Z1bGxSZWFkZXIpID09PSBudWxsIHx8IF90aGlzJF9mdWxsUmVhZGVyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRfZnVsbFJlYWRlci5maWxlbmFtZSkgPz8gbnVsbAogICAgICAgICAgICAgICAgICAgICAgICB9KS5maW5hbGx5KCgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYW5ub3RhdGlvblN0b3JhZ2UucmVzZXRNb2RpZmllZCgpOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0UGFnZShwYWdlTnVtYmVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihwYWdlTnVtYmVyKSB8fCBwYWdlTnVtYmVyIDw9IDAgfHwgcGFnZU51bWJlciA+IHRoaXMuX251bVBhZ2VzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCJJbnZhbGlkIHBhZ2UgcmVxdWVzdC4iKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFnZUluZGV4ID0gcGFnZU51bWJlciAtIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWNoZWRQcm9taXNlID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9wYWdlUHJvbWlzZXMpLmdldChwYWdlSW5kZXgpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FjaGVkUHJvbWlzZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNhY2hlZFByb21pc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMubWVzc2FnZUhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJHZXRQYWdlIiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUluZGV4CiAgICAgICAgICAgICAgICAgICAgICAgIH0pLnRoZW4ocGFnZUluZm8gPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGVzdHJveWVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJUcmFuc3BvcnQgZGVzdHJveWVkIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWdlID0gbmV3IFBERlBhZ2VQcm94eShwYWdlSW5kZXgsIHBhZ2VJbmZvLCB0aGlzLCB0aGlzLl9wYXJhbXMucGRmQnVnKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfcGFnZUNhY2hlKS5zZXQocGFnZUluZGV4LCBwYWdlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwYWdlOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9wYWdlUHJvbWlzZXMpLnNldChwYWdlSW5kZXgsIHByb21pc2UpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0UGFnZUluZGV4KHJlZikgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHJlZiAhPT0gIm9iamVjdCIgfHwgcmVmID09PSBudWxsIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKHJlZi5udW0pIHx8IHJlZi5udW0gPCAwIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKHJlZi5nZW4pIHx8IHJlZi5nZW4gPCAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCJJbnZhbGlkIHBhZ2VJbmRleCByZXF1ZXN0LiIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlSGFuZGxlci5zZW5kV2l0aFByb21pc2UoIkdldFBhZ2VJbmRleCIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bTogcmVmLm51bSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbjogcmVmLmdlbgogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0QW5ub3RhdGlvbnMocGFnZUluZGV4LCBpbnRlbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZUhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJHZXRBbm5vdGF0aW9ucyIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VJbmRleCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0RmllbGRPYmplY3RzKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfY2FjaGVTaW1wbGVNZXRob2QsIF9jYWNoZVNpbXBsZU1ldGhvZDIpLmNhbGwodGhpcywgIkdldEZpZWxkT2JqZWN0cyIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBoYXNKU0FjdGlvbnMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9jYWNoZVNpbXBsZU1ldGhvZCwgX2NhY2hlU2ltcGxlTWV0aG9kMikuY2FsbCh0aGlzLCAiSGFzSlNBY3Rpb25zIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldENhbGN1bGF0aW9uT3JkZXJJZHMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VIYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiR2V0Q2FsY3VsYXRpb25PcmRlcklkcyIsIG51bGwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXREZXN0aW5hdGlvbnMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VIYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiR2V0RGVzdGluYXRpb25zIiwgbnVsbCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldERlc3RpbmF0aW9uKGlkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaWQgIT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKCJJbnZhbGlkIGRlc3RpbmF0aW9uIHJlcXVlc3QuIikpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VIYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiR2V0RGVzdGluYXRpb24iLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0UGFnZUxhYmVscygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZUhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJHZXRQYWdlTGFiZWxzIiwgbnVsbCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldFBhZ2VMYXlvdXQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VIYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiR2V0UGFnZUxheW91dCIsIG51bGwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRQYWdlTW9kZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZUhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJHZXRQYWdlTW9kZSIsIG51bGwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRWaWV3ZXJQcmVmZXJlbmNlcygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZUhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJHZXRWaWV3ZXJQcmVmZXJlbmNlcyIsIG51bGwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRPcGVuQWN0aW9uKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlSGFuZGxlci5zZW5kV2l0aFByb21pc2UoIkdldE9wZW5BY3Rpb24iLCBudWxsKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0QXR0YWNobWVudHMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VIYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiR2V0QXR0YWNobWVudHMiLCBudWxsKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0SmF2YVNjcmlwdCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZUhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJHZXRKYXZhU2NyaXB0IiwgbnVsbCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldERvY0pTQWN0aW9ucygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZUhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJHZXREb2NKU0FjdGlvbnMiLCBudWxsKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0UGFnZUpTQWN0aW9ucyhwYWdlSW5kZXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZUhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJHZXRQYWdlSlNBY3Rpb25zIiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUluZGV4CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRTdHJ1Y3RUcmVlKHBhZ2VJbmRleCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlSGFuZGxlci5zZW5kV2l0aFByb21pc2UoIkdldFN0cnVjdFRyZWUiLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlSW5kZXgKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldE91dGxpbmUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VIYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiR2V0T3V0bGluZSIsIG51bGwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRPcHRpb25hbENvbnRlbnRDb25maWcoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2VIYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiR2V0T3B0aW9uYWxDb250ZW50Q29uZmlnIiwgbnVsbCkudGhlbihyZXN1bHRzID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgX29wdGlvbmFsX2NvbnRlbnRfY29uZmlnLk9wdGlvbmFsQ29udGVudENvbmZpZyhyZXN1bHRzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldFBlcm1pc3Npb25zKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlSGFuZGxlci5zZW5kV2l0aFByb21pc2UoIkdldFBlcm1pc3Npb25zIiwgbnVsbCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldE1ldGFkYXRhKCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuYW1lID0gIkdldE1ldGFkYXRhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlZFByb21pc2UgPSBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX21ldGhvZFByb21pc2VzKS5nZXQobmFtZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYWNoZWRQcm9taXNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FjaGVkUHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwcm9taXNlID0gdGhpcy5tZXNzYWdlSGFuZGxlci5zZW5kV2l0aFByb21pc2UobmFtZSwgbnVsbCkudGhlbihyZXN1bHRzID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRfZnVsbFJlYWRlcjIsIF90aGlzJF9mdWxsUmVhZGVyMzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5mbzogcmVzdWx0c1swXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YTogcmVzdWx0c1sxXSA/IG5ldyBfbWV0YWRhdGEuTWV0YWRhdGEocmVzdWx0c1sxXSkgOiBudWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnREaXNwb3NpdGlvbkZpbGVuYW1lOiAoKF90aGlzJF9mdWxsUmVhZGVyMiA9IHRoaXMuX2Z1bGxSZWFkZXIpID09PSBudWxsIHx8IF90aGlzJF9mdWxsUmVhZGVyMiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkX2Z1bGxSZWFkZXIyLmZpbGVuYW1lKSA/PyBudWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnRMZW5ndGg6ICgoX3RoaXMkX2Z1bGxSZWFkZXIzID0gdGhpcy5fZnVsbFJlYWRlcikgPT09IG51bGwgfHwgX3RoaXMkX2Z1bGxSZWFkZXIzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRfZnVsbFJlYWRlcjMuY29udGVudExlbmd0aCkgPz8gbnVsbAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfbWV0aG9kUHJvbWlzZXMpLnNldChuYW1lLCBwcm9taXNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldE1hcmtJbmZvKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlSGFuZGxlci5zZW5kV2l0aFByb21pc2UoIkdldE1hcmtJbmZvIiwgbnVsbCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFzeW5jIHN0YXJ0Q2xlYW51cCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGtlZXBMb2FkZWRGb250cyA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMubWVzc2FnZUhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJDbGVhbnVwIiwgbnVsbCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcGFnZSBvZiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3BhZ2VDYWNoZSkudmFsdWVzKCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNsZWFudXBTdWNjZXNzZnVsID0gcGFnZS5jbGVhbnVwKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNsZWFudXBTdWNjZXNzZnVsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBzdGFydENsZWFudXA6IFBhZ2UgJHtwYWdlLnBhZ2VOdW1iZXJ9IGlzIGN1cnJlbnRseSByZW5kZXJpbmcuYCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21tb25PYmpzLmNsZWFyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgha2VlcExvYWRlZEZvbnRzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZvbnRMb2FkZXIuY2xlYXIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX21ldGhvZFByb21pc2VzKS5jbGVhcigpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbHRlckZhY3RvcnkuZGVzdHJveSh0cnVlKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGxvYWRpbmdQYXJhbXMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVBdXRvRmV0Y2gsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVYZmEKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXMuX3BhcmFtczsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJsb2FkaW5nUGFyYW1zIiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZUF1dG9GZXRjaCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuYWJsZVhmYQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2FjaGVTaW1wbGVNZXRob2QyKG5hbWUpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgZGF0YSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjYWNoZWRQcm9taXNlID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9tZXRob2RQcm9taXNlcykuZ2V0KG5hbWUpOwogICAgICAgICAgICAgICAgICAgIGlmIChjYWNoZWRQcm9taXNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWNoZWRQcm9taXNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBwcm9taXNlID0gdGhpcy5tZXNzYWdlSGFuZGxlci5zZW5kV2l0aFByb21pc2UobmFtZSwgZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9tZXRob2RQcm9taXNlcykuc2V0KG5hbWUsIHByb21pc2UpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBwcm9taXNlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgdmFyIF9vYmpzID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2Vuc3VyZU9iaiA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgY2xhc3MgUERGT2JqZWN0cyB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfZW5zdXJlT2JqKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX29ianMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IE9iamVjdC5jcmVhdGUobnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldChvYmpJZCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgY2FsbGJhY2sgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYWxsYmFjaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2JqID0gX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfZW5zdXJlT2JqLCBfZW5zdXJlT2JqMikuY2FsbCh0aGlzLCBvYmpJZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYmouY2FwYWJpbGl0eS5wcm9taXNlLnRoZW4oKCkgPT4gY2FsbGJhY2sob2JqLmRhdGEpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9iaiA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfb2Jqcylbb2JqSWRdOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIShvYmogIT09IG51bGwgJiYgb2JqICE9PSB2b2lkIDAgJiYgb2JqLmNhcGFiaWxpdHkuc2V0dGxlZCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUmVxdWVzdGluZyBvYmplY3QgdGhhdCBpc24ndCByZXNvbHZlZCB5ZXQgJHtvYmpJZH0uYCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9iai5kYXRhOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBoYXMob2JqSWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2JqID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9vYmpzKVtvYmpJZF07CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAob2JqID09PSBudWxsIHx8IG9iaiA9PT0gdm9pZCAwID8gdm9pZCAwIDogb2JqLmNhcGFiaWxpdHkuc2V0dGxlZCkgfHwgZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlc29sdmUob2JqSWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRhdGEgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9iaiA9IF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2Vuc3VyZU9iaiwgX2Vuc3VyZU9iajIpLmNhbGwodGhpcywgb2JqSWQpOwogICAgICAgICAgICAgICAgICAgICAgICBvYmouZGF0YSA9IGRhdGE7CiAgICAgICAgICAgICAgICAgICAgICAgIG9iai5jYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2xlYXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgb2JqSWQgaW4gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9vYmpzKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9kYXRhJGJpdG1hcDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9vYmpzKVtvYmpJZF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID09PSBudWxsIHx8IGRhdGEgPT09IHZvaWQgMCA/IHZvaWQgMCA6IChfZGF0YSRiaXRtYXAgPSBkYXRhLmJpdG1hcCkgPT09IG51bGwgfHwgX2RhdGEkYml0bWFwID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZGF0YSRiaXRtYXAuY2xvc2UoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX29ianMsIE9iamVjdC5jcmVhdGUobnVsbCkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9lbnN1cmVPYmoyKG9iaklkKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2JqID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9vYmpzKVtvYmpJZF07CiAgICAgICAgICAgICAgICAgICAgaWYgKG9iaikgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2JqOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9vYmpzKVtvYmpJZF0gPSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhcGFiaWxpdHk6ICgwLCBfdXRpbC5jcmVhdGVQcm9taXNlQ2FwYWJpbGl0eSkoKSwKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogbnVsbAogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBSZW5kZXJUYXNrIHsKICAgICAgICAgICAgICAgICAgICAjaW50ZXJuYWxSZW5kZXJUYXNrID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihpbnRlcm5hbFJlbmRlclRhc2spIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jaW50ZXJuYWxSZW5kZXJUYXNrID0gaW50ZXJuYWxSZW5kZXJUYXNrOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uQ29udGludWUgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgcHJvbWlzZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuI2ludGVybmFsUmVuZGVyVGFzay5jYXBhYmlsaXR5LnByb21pc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNhbmNlbCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGV4dHJhRGVsYXkgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuI2ludGVybmFsUmVuZGVyVGFzay5jYW5jZWwobnVsbCwgZXh0cmFEZWxheSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBzZXBhcmF0ZUFubm90cygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdGVBbm5vdHMKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXMuI2ludGVybmFsUmVuZGVyVGFzay5vcGVyYXRvckxpc3Q7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2VwYXJhdGVBbm5vdHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uQ2FudmFzTWFwCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSB0aGlzLiNpbnRlcm5hbFJlbmRlclRhc2s7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzZXBhcmF0ZUFubm90cy5mb3JtIHx8IHNlcGFyYXRlQW5ub3RzLmNhbnZhcyAmJiAoYW5ub3RhdGlvbkNhbnZhc01hcCA9PT0gbnVsbCB8fCBhbm5vdGF0aW9uQ2FudmFzTWFwID09PSB2b2lkIDAgPyB2b2lkIDAgOiBhbm5vdGF0aW9uQ2FudmFzTWFwLnNpemUpID4gMDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLlJlbmRlclRhc2sgPSBSZW5kZXJUYXNrOwogICAgICAgICAgICAgICAgY2xhc3MgSW50ZXJuYWxSZW5kZXJUYXNrIHsKICAgICAgICAgICAgICAgICAgICBzdGF0aWMgI2NhbnZhc0luVXNlID0gbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihfcmVmMTMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JqcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbW1vbk9ianMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uQ2FudmFzTWFwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUluZGV4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzRmFjdG9yeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlckZhY3RvcnksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgPSBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBkZkJ1ZyA9IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUNvbG9ycyA9IG51bGwKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IF9yZWYxMzsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFjayA9IGNhbGxiYWNrOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcmFtcyA9IHBhcmFtczsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vYmpzID0gb2JqczsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21tb25PYmpzID0gY29tbW9uT2JqczsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hbm5vdGF0aW9uQ2FudmFzTWFwID0gYW5ub3RhdGlvbkNhbnZhc01hcDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVyYXRvckxpc3RJZHggPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZXJhdG9yTGlzdCA9IG9wZXJhdG9yTGlzdDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGFnZUluZGV4ID0gcGFnZUluZGV4OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbnZhc0ZhY3RvcnkgPSBjYW52YXNGYWN0b3J5OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbHRlckZhY3RvcnkgPSBmaWx0ZXJGYWN0b3J5OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wZGZCdWcgPSBwZGZCdWc7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFnZUNvbG9ycyA9IHBhZ2VDb2xvcnM7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucnVubmluZyA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdyYXBoaWNzUmVhZHlDYWxsYmFjayA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ3JhcGhpY3NSZWFkeSA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl91c2VSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgPSB1c2VSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgPT09IHRydWUgJiYgdHlwZW9mIHdpbmRvdyAhPT0gInVuZGVmaW5lZCI7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FuY2VsbGVkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FwYWJpbGl0eSA9ICgwLCBfdXRpbC5jcmVhdGVQcm9taXNlQ2FwYWJpbGl0eSkoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50YXNrID0gbmV3IFJlbmRlclRhc2sodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NhbmNlbEJvdW5kID0gdGhpcy5jYW5jZWwuYmluZCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29udGludWVCb3VuZCA9IHRoaXMuX2NvbnRpbnVlLmJpbmQodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NjaGVkdWxlTmV4dEJvdW5kID0gdGhpcy5fc2NoZWR1bGVOZXh0LmJpbmQodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX25leHRCb3VuZCA9IHRoaXMuX25leHQuYmluZCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY2FudmFzID0gcGFyYW1zLmNhbnZhc0NvbnRleHQuY2FudmFzOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgY29tcGxldGVkKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jYXBhYmlsaXR5LnByb21pc2UuY2F0Y2goZnVuY3Rpb24gKCkge30pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpbml0aWFsaXplR3JhcGhpY3MoX3JlZjE0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfZ2xvYmFsVGhpcyRTdGVwcGVyTWEsIF90aGlzJGdyYXBoaWNzUmVhZHlDYTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zcGFyZW5jeSA9IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxDb250ZW50Q29uZmlnCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmMTQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmNhbmNlbGxlZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9jYW52YXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChJbnRlcm5hbFJlbmRlclRhc2suI2NhbnZhc0luVXNlLmhhcyh0aGlzLl9jYW52YXMpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDYW5ub3QgdXNlIHRoZSBzYW1lIGNhbnZhcyBkdXJpbmcgbXVsdGlwbGUgcmVuZGVyKCkgb3BlcmF0aW9ucy4gIiArICJVc2UgZGlmZmVyZW50IGNhbnZhcyBvciBlbnN1cmUgcHJldmlvdXMgb3BlcmF0aW9ucyB3ZXJlICIgKyAiY2FuY2VsbGVkIG9yIGNvbXBsZXRlZC4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIEludGVybmFsUmVuZGVyVGFzay4jY2FudmFzSW5Vc2UuYWRkKHRoaXMuX2NhbnZhcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX3BkZkJ1ZyAmJiAoX2dsb2JhbFRoaXMkU3RlcHBlck1hID0gZ2xvYmFsVGhpcy5TdGVwcGVyTWFuYWdlcikgIT09IG51bGwgJiYgX2dsb2JhbFRoaXMkU3RlcHBlck1hICE9PSB2b2lkIDAgJiYgX2dsb2JhbFRoaXMkU3RlcHBlck1hLmVuYWJsZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RlcHBlciA9IGdsb2JhbFRoaXMuU3RlcHBlck1hbmFnZXIuY3JlYXRlKHRoaXMuX3BhZ2VJbmRleCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0ZXBwZXIuaW5pdCh0aGlzLm9wZXJhdG9yTGlzdCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0ZXBwZXIubmV4dEJyZWFrUG9pbnQgPSB0aGlzLnN0ZXBwZXIuZ2V0TmV4dEJyZWFrUG9pbnQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYW52YXNDb250ZXh0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlld3BvcnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSB0aGlzLnBhcmFtczsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5nZnggPSBuZXcgX2NhbnZhcy5DYW52YXNHcmFwaGljcyhjYW52YXNDb250ZXh0LCB0aGlzLmNvbW1vbk9ianMsIHRoaXMub2JqcywgdGhpcy5jYW52YXNGYWN0b3J5LCB0aGlzLmZpbHRlckZhY3RvcnksIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbmFsQ29udGVudENvbmZpZwogICAgICAgICAgICAgICAgICAgICAgICB9LCB0aGlzLmFubm90YXRpb25DYW52YXNNYXApOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdmeC5iZWdpbkRyYXdpbmcoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlld3BvcnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc3BhcmVuY3ksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZXJhdG9yTGlzdElkeCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ3JhcGhpY3NSZWFkeSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRncmFwaGljc1JlYWR5Q2EgPSB0aGlzLmdyYXBoaWNzUmVhZHlDYWxsYmFjaykgPT09IG51bGwgfHwgX3RoaXMkZ3JhcGhpY3NSZWFkeUNhID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRncmFwaGljc1JlYWR5Q2EuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FuY2VsKCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkZ2Z4OwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgZXJyb3IgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBleHRyYURlbGF5ID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiAwOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJ1bm5pbmcgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYW5jZWxsZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkZ2Z4ID0gdGhpcy5nZngpID09PSBudWxsIHx8IF90aGlzJGdmeCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkZ2Z4LmVuZERyYXdpbmcodGhpcy5wYWdlQ29sb3JzKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2NhbnZhcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgSW50ZXJuYWxSZW5kZXJUYXNrLiNjYW52YXNJblVzZS5kZWxldGUodGhpcy5fY2FudmFzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrKGVycm9yIHx8IG5ldyBfZGlzcGxheV91dGlscy5SZW5kZXJpbmdDYW5jZWxsZWRFeGNlcHRpb24oYFJlbmRlcmluZyBjYW5jZWxsZWQsIHBhZ2UgJHt0aGlzLl9wYWdlSW5kZXggKyAxfWAsICJjYW52YXMiLCBleHRyYURlbGF5KSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIG9wZXJhdG9yTGlzdENoYW5nZWQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRzdGVwcGVyOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuZ3JhcGhpY3NSZWFkeSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmdyYXBoaWNzUmVhZHlDYWxsYmFjaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ3JhcGhpY3NSZWFkeUNhbGxiYWNrID0gdGhpcy5fY29udGludWVCb3VuZDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkc3RlcHBlciA9IHRoaXMuc3RlcHBlcikgPT09IG51bGwgfHwgX3RoaXMkc3RlcHBlciA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkc3RlcHBlci51cGRhdGVPcGVyYXRvckxpc3QodGhpcy5vcGVyYXRvckxpc3QpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5ydW5uaW5nKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29udGludWUoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2NvbnRpbnVlKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJ1bm5pbmcgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jYW5jZWxsZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy50YXNrLm9uQ29udGludWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGFzay5vbkNvbnRpbnVlKHRoaXMuX3NjaGVkdWxlTmV4dEJvdW5kKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NjaGVkdWxlTmV4dCgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9zY2hlZHVsZU5leHQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl91c2VSZXF1ZXN0QW5pbWF0aW9uRnJhbWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX25leHRCb3VuZCgpLmNhdGNoKHRoaXMuX2NhbmNlbEJvdW5kKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbih0aGlzLl9uZXh0Qm91bmQpLmNhdGNoKHRoaXMuX2NhbmNlbEJvdW5kKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhc3luYyBfbmV4dCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY2FuY2VsbGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vcGVyYXRvckxpc3RJZHggPSB0aGlzLmdmeC5leGVjdXRlT3BlcmF0b3JMaXN0KHRoaXMub3BlcmF0b3JMaXN0LCB0aGlzLm9wZXJhdG9yTGlzdElkeCwgdGhpcy5fY29udGludWVCb3VuZCwgdGhpcy5zdGVwcGVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMub3BlcmF0b3JMaXN0SWR4ID09PSB0aGlzLm9wZXJhdG9yTGlzdC5hcmdzQXJyYXkubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJ1bm5pbmcgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLm9wZXJhdG9yTGlzdC5sYXN0Q2h1bmspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdmeC5lbmREcmF3aW5nKHRoaXMucGFnZUNvbG9ycyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2NhbnZhcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJbnRlcm5hbFJlbmRlclRhc2suI2NhbnZhc0luVXNlLmRlbGV0ZSh0aGlzLl9jYW52YXMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjb25zdCB2ZXJzaW9uID0gJzMuNS4xMjInOwogICAgICAgICAgICAgICAgZXhwb3J0cy52ZXJzaW9uID0gdmVyc2lvbjsKICAgICAgICAgICAgICAgIGNvbnN0IGJ1aWxkID0gJzYyMjQ2NWRjMic7CiAgICAgICAgICAgICAgICBleHBvcnRzLmJ1aWxkID0gYnVpbGQ7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDEzOSAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLlByaW50QW5ub3RhdGlvblN0b3JhZ2UgPSBleHBvcnRzLkFubm90YXRpb25TdG9yYWdlID0gdm9pZCAwOwogICAgICAgICAgICAgICAgdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygxKTsKICAgICAgICAgICAgICAgIHZhciBfZWRpdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDApOwogICAgICAgICAgICAgICAgdmFyIF9tdXJtdXJoYXNoID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDQpOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKG9iaiwgcHJpdmF0ZVNldCkgeyBfY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbihvYmosIHByaXZhdGVTZXQpOyBwcml2YXRlU2V0LmFkZChvYmopOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyhvYmosIHByaXZhdGVNYXAsIHZhbHVlKSB7IF9jaGVja1ByaXZhdGVSZWRlY2xhcmF0aW9uKG9iaiwgcHJpdmF0ZU1hcCk7IHByaXZhdGVNYXAuc2V0KG9iaiwgdmFsdWUpOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbihvYmosIHByaXZhdGVDb2xsZWN0aW9uKSB7IGlmIChwcml2YXRlQ29sbGVjdGlvbi5oYXMob2JqKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgaW5pdGlhbGl6ZSB0aGUgc2FtZSBwcml2YXRlIGVsZW1lbnRzIHR3aWNlIG9uIGFuIG9iamVjdCIpOyB9IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVGaWVsZFNldChyZWNlaXZlciwgcHJpdmF0ZU1hcCwgdmFsdWUpIHsgdmFyIGRlc2NyaXB0b3IgPSBfY2xhc3NFeHRyYWN0RmllbGREZXNjcmlwdG9yKHJlY2VpdmVyLCBwcml2YXRlTWFwLCAic2V0Iik7IF9jbGFzc0FwcGx5RGVzY3JpcHRvclNldChyZWNlaXZlciwgZGVzY3JpcHRvciwgdmFsdWUpOyByZXR1cm4gdmFsdWU7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc0FwcGx5RGVzY3JpcHRvclNldChyZWNlaXZlciwgZGVzY3JpcHRvciwgdmFsdWUpIHsgaWYgKGRlc2NyaXB0b3Iuc2V0KSB7IGRlc2NyaXB0b3Iuc2V0LmNhbGwocmVjZWl2ZXIsIHZhbHVlKTsgfSBlbHNlIHsgaWYgKCFkZXNjcmlwdG9yLndyaXRhYmxlKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoImF0dGVtcHRlZCB0byBzZXQgcmVhZCBvbmx5IHByaXZhdGUgZmllbGQiKTsgfSBkZXNjcmlwdG9yLnZhbHVlID0gdmFsdWU7IH0gfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZU1ldGhvZEdldChyZWNlaXZlciwgcHJpdmF0ZVNldCwgZm4pIHsgaWYgKCFwcml2YXRlU2V0LmhhcyhyZWNlaXZlcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigiYXR0ZW1wdGVkIHRvIGdldCBwcml2YXRlIGZpZWxkIG9uIG5vbi1pbnN0YW5jZSIpOyB9IHJldHVybiBmbjsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHJlY2VpdmVyLCBwcml2YXRlTWFwKSB7IHZhciBkZXNjcmlwdG9yID0gX2NsYXNzRXh0cmFjdEZpZWxkRGVzY3JpcHRvcihyZWNlaXZlciwgcHJpdmF0ZU1hcCwgImdldCIpOyByZXR1cm4gX2NsYXNzQXBwbHlEZXNjcmlwdG9yR2V0KHJlY2VpdmVyLCBkZXNjcmlwdG9yKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzRXh0cmFjdEZpZWxkRGVzY3JpcHRvcihyZWNlaXZlciwgcHJpdmF0ZU1hcCwgYWN0aW9uKSB7IGlmICghcHJpdmF0ZU1hcC5oYXMocmVjZWl2ZXIpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoImF0dGVtcHRlZCB0byAiICsgYWN0aW9uICsgIiBwcml2YXRlIGZpZWxkIG9uIG5vbi1pbnN0YW5jZSIpOyB9IHJldHVybiBwcml2YXRlTWFwLmdldChyZWNlaXZlcik7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc0FwcGx5RGVzY3JpcHRvckdldChyZWNlaXZlciwgZGVzY3JpcHRvcikgeyBpZiAoZGVzY3JpcHRvci5nZXQpIHsgcmV0dXJuIGRlc2NyaXB0b3IuZ2V0LmNhbGwocmVjZWl2ZXIpOyB9IHJldHVybiBkZXNjcmlwdG9yLnZhbHVlOyB9CiAgICAgICAgICAgICAgICB2YXIgX21vZGlmaWVkID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX3N0b3JhZ2UgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfc2V0TW9kaWZpZWQgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIGNsYXNzIEFubm90YXRpb25TdG9yYWdlIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF9zZXRNb2RpZmllZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9tb2RpZmllZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9zdG9yYWdlLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBuZXcgTWFwKCkKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub25TZXRNb2RpZmllZCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub25SZXNldE1vZGlmaWVkID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vbkFubm90YXRpb25FZGl0b3IgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRWYWx1ZShrZXksIGRlZmF1bHRWYWx1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc3RvcmFnZSkuZ2V0KGtleSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGVmYXVsdFZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKGRlZmF1bHRWYWx1ZSwgdmFsdWUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRSYXdWYWx1ZShrZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc3RvcmFnZSkuZ2V0KGtleSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbW92ZShrZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9zdG9yYWdlKS5kZWxldGUoa2V5KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc3RvcmFnZSkuc2l6ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNldE1vZGlmaWVkKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm9uQW5ub3RhdGlvbkVkaXRvciA9PT0gImZ1bmN0aW9uIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCB2YWx1ZSBvZiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3N0b3JhZ2UpLnZhbHVlcygpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgX2VkaXRvci5Bbm5vdGF0aW9uRWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uQW5ub3RhdGlvbkVkaXRvcihudWxsKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZShrZXksIHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9iaiA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc3RvcmFnZSkuZ2V0KGtleSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtb2RpZmllZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgW2VudHJ5LCB2YWxdIG9mIE9iamVjdC5lbnRyaWVzKHZhbHVlKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmpbZW50cnldICE9PSB2YWwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZpZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYmpbZW50cnldID0gdmFsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGlmaWVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc3RvcmFnZSkuc2V0KGtleSwgdmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtb2RpZmllZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfc2V0TW9kaWZpZWQsIF9zZXRNb2RpZmllZDIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgX2VkaXRvci5Bbm5vdGF0aW9uRWRpdG9yICYmIHR5cGVvZiB0aGlzLm9uQW5ub3RhdGlvbkVkaXRvciA9PT0gImZ1bmN0aW9uIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vbkFubm90YXRpb25FZGl0b3IodmFsdWUuY29uc3RydWN0b3IuX3R5cGUpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGhhcyhrZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc3RvcmFnZSkuaGFzKGtleSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldEFsbCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc3RvcmFnZSkuc2l6ZSA+IDAgPyAoMCwgX3V0aWwub2JqZWN0RnJvbU1hcCkoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9zdG9yYWdlKSkgOiBudWxsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzZXRBbGwob2JqKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiBPYmplY3QuZW50cmllcyhvYmopKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFZhbHVlKGtleSwgdmFsKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgc2l6ZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc3RvcmFnZSkuc2l6ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVzZXRNb2RpZmllZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfbW9kaWZpZWQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX21vZGlmaWVkLCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMub25SZXNldE1vZGlmaWVkID09PSAiZnVuY3Rpb24iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vblJlc2V0TW9kaWZpZWQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgcHJpbnQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJpbnRBbm5vdGF0aW9uU3RvcmFnZSh0aGlzKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IHNlcmlhbGl6YWJsZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc3RvcmFnZSkuc2l6ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2xvbmUgPSBuZXcgTWFwKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3N0b3JhZ2UpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzZXJpYWxpemVkID0gdmFsIGluc3RhbmNlb2YgX2VkaXRvci5Bbm5vdGF0aW9uRWRpdG9yID8gdmFsLnNlcmlhbGl6ZSgpIDogdmFsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcmlhbGl6ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9uZS5zZXQoa2V5LCBzZXJpYWxpemVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2xvbmU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBnZXRIYXNoKG1hcCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW1hcCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICIiOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhhc2ggPSBuZXcgX211cm11cmhhc2guTXVybXVySGFzaDNfNjQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWxdIG9mIG1hcCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzaC51cGRhdGUoYCR7a2V5fToke0pTT04uc3RyaW5naWZ5KHZhbCl9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGhhc2guaGV4ZGlnZXN0KCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5Bbm5vdGF0aW9uU3RvcmFnZSA9IEFubm90YXRpb25TdG9yYWdlOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3NldE1vZGlmaWVkMigpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIV9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfbW9kaWZpZWQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfbW9kaWZpZWQsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMub25TZXRNb2RpZmllZCA9PT0gImZ1bmN0aW9uIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vblNldE1vZGlmaWVkKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBQcmludEFubm90YXRpb25TdG9yYWdlIGV4dGVuZHMgQW5ub3RhdGlvblN0b3JhZ2UgewogICAgICAgICAgICAgICAgICAgICNzZXJpYWxpemFibGUgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHBhcmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBzdXBlcigpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNzZXJpYWxpemFibGUgPSBzdHJ1Y3R1cmVkQ2xvbmUocGFyZW50LnNlcmlhbGl6YWJsZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBwcmludCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiU2hvdWxkIG5vdCBjYWxsIFByaW50QW5ub3RhdGlvblN0b3JhZ2UucHJpbnQiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IHNlcmlhbGl6YWJsZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuI3NlcmlhbGl6YWJsZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLlByaW50QW5ub3RhdGlvblN0b3JhZ2UgPSBQcmludEFubm90YXRpb25TdG9yYWdlOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxNDAgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCgogICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdHJ1ZQogICAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgICAgZXhwb3J0cy5Bbm5vdGF0aW9uRWRpdG9yID0gdm9pZCAwOwogICAgICAgICAgICAgICAgdmFyIF90b29scyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQxKTsKICAgICAgICAgICAgICAgIHZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMSk7CiAgICAgICAgICAgICAgICBjbGFzcyBBbm5vdGF0aW9uRWRpdG9yIHsKICAgICAgICAgICAgICAgICAgICAjYm91bmRGb2N1c2luID0gdGhpcy5mb2N1c2luLmJpbmQodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgI2JvdW5kRm9jdXNvdXQgPSB0aGlzLmZvY3Vzb3V0LmJpbmQodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgI2hhc0JlZW5TZWxlY3RlZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICNpc0VkaXRpbmcgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAjaXNJbkVkaXRNb2RlID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgX3VpTWFuYWdlciA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgI3pJbmRleCA9IEFubm90YXRpb25FZGl0b3IuX3pJbmRleCsrOwogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBfY29sb3JNYW5hZ2VyID0gbmV3IF90b29scy5Db2xvck1hbmFnZXIoKTsKICAgICAgICAgICAgICAgICAgICBzdGF0aWMgX3pJbmRleCA9IDE7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25zdHJ1Y3RvciA9PT0gQW5ub3RhdGlvbkVkaXRvcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQ2Fubm90IGluaXRpYWxpemUgQW5ub3RhdGlvbkVkaXRvci4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcmVudCA9IHBhcmFtZXRlcnMucGFyZW50OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlkID0gcGFyYW1ldGVycy5pZDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53aWR0aCA9IHRoaXMuaGVpZ2h0ID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYWdlSW5kZXggPSBwYXJhbWV0ZXJzLnBhcmVudC5wYWdlSW5kZXg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubmFtZSA9IHBhcmFtZXRlcnMubmFtZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl91aU1hbmFnZXIgPSBwYXJhbWV0ZXJzLnVpTWFuYWdlcjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdEaW1zOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZVdpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VIZWlnaHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZVgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZVkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXMucGFyZW50LnZpZXdwb3J0OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJvdGF0aW9uID0gcm90YXRpb247CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFnZURpbWVuc2lvbnMgPSBbcGFnZVdpZHRoLCBwYWdlSGVpZ2h0XTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYWdlVHJhbnNsYXRpb24gPSBbcGFnZVgsIHBhZ2VZXTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW3dpZHRoLCBoZWlnaHRdID0gdGhpcy5wYXJlbnREaW1lbnNpb25zOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnggPSBwYXJhbWV0ZXJzLnggLyB3aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy55ID0gcGFyYW1ldGVycy55IC8gaGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzQXR0YWNoZWRUb0RPTSA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgZ2V0IF9kZWZhdWx0TGluZUNvbG9yKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIl9kZWZhdWx0TGluZUNvbG9yIiwgdGhpcy5fY29sb3JNYW5hZ2VyLmdldEhleENvZGUoIkNhbnZhc1RleHQiKSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFkZENvbW1hbmRzKHBhcmFtcykgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl91aU1hbmFnZXIuYWRkQ29tbWFuZHMocGFyYW1zKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGN1cnJlbnRMYXllcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3VpTWFuYWdlci5jdXJyZW50TGF5ZXI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldEluQmFja2dyb3VuZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYuc3R5bGUuekluZGV4ID0gMDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0SW5Gb3JlZ3JvdW5kKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5zdHlsZS56SW5kZXggPSB0aGlzLiN6SW5kZXg7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldFBhcmVudChwYXJlbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudCAhPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYWdlSW5kZXggPSBwYXJlbnQucGFnZUluZGV4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYWdlRGltZW5zaW9ucyA9IHBhcmVudC5wYWdlRGltZW5zaW9uczsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcmVudCA9IHBhcmVudDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZm9jdXNpbihldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuI2hhc0JlZW5TZWxlY3RlZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJlbnQuc2V0U2VsZWN0ZWQodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNoYXNCZWVuU2VsZWN0ZWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmb2N1c291dChldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkcGFyZW50OwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaXNBdHRhY2hlZFRvRE9NKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQucmVsYXRlZFRhcmdldDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRhcmdldCAhPT0gbnVsbCAmJiB0YXJnZXQgIT09IHZvaWQgMCAmJiB0YXJnZXQuY2xvc2VzdChgIyR7dGhpcy5pZH1gKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghKChfdGhpcyRwYXJlbnQgPSB0aGlzLnBhcmVudCkgIT09IG51bGwgJiYgX3RoaXMkcGFyZW50ICE9PSB2b2lkIDAgJiYgX3RoaXMkcGFyZW50LmlzTXVsdGlwbGVTZWxlY3Rpb24pKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbW1pdE9yUmVtb3ZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY29tbWl0T3JSZW1vdmUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbWl0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY29tbWl0KCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZFRvQW5ub3RhdGlvblN0b3JhZ2UoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYWRkVG9Bbm5vdGF0aW9uU3RvcmFnZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdWlNYW5hZ2VyLmFkZFRvQW5ub3RhdGlvblN0b3JhZ2UodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRyYWdzdGFydChldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0ID0gdGhpcy5wYXJlbnQuZGl2LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0WCA9IGV2ZW50LmNsaWVudFggLSByZWN0Lng7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhcnRZID0gZXZlbnQuY2xpZW50WSAtIHJlY3QueTsKICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLnNldERhdGEoInRleHQvcGxhaW4iLCB0aGlzLmlkKTsKICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLmVmZmVjdEFsbG93ZWQgPSAibW92ZSI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldEF0KHgsIHksIHR4LCB0eSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbd2lkdGgsIGhlaWdodF0gPSB0aGlzLnBhcmVudERpbWVuc2lvbnM7CiAgICAgICAgICAgICAgICAgICAgICAgIFt0eCwgdHldID0gdGhpcy5zY3JlZW5Ub1BhZ2VUcmFuc2xhdGlvbih0eCwgdHkpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnggPSAoeCArIHR4KSAvIHdpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnkgPSAoeSArIHR5KSAvIGhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYuc3R5bGUubGVmdCA9IGAkezEwMCAqIHRoaXMueH0lYDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYuc3R5bGUudG9wID0gYCR7MTAwICogdGhpcy55fSVgOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGUoeCwgeSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbd2lkdGgsIGhlaWdodF0gPSB0aGlzLnBhcmVudERpbWVuc2lvbnM7CiAgICAgICAgICAgICAgICAgICAgICAgIFt4LCB5XSA9IHRoaXMuc2NyZWVuVG9QYWdlVHJhbnNsYXRpb24oeCwgeSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMueCArPSB4IC8gd2lkdGg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMueSArPSB5IC8gaGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5zdHlsZS5sZWZ0ID0gYCR7MTAwICogdGhpcy54fSVgOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5zdHlsZS50b3AgPSBgJHsxMDAgKiB0aGlzLnl9JWA7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNjcmVlblRvUGFnZVRyYW5zbGF0aW9uKHgsIHkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnBhcmVudFJvdGF0aW9uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDkwOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbeSwgLXhdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAxODA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsteCwgLXldOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAyNzA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsteSwgeF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbeCwgeV07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IHBhcmVudFNjYWxlKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdWlNYW5hZ2VyLnZpZXdQYXJhbWV0ZXJzLnJlYWxTY2FsZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IHBhcmVudFJvdGF0aW9uKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fdWlNYW5hZ2VyLnZpZXdQYXJhbWV0ZXJzLnJvdGF0aW9uOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgcGFyZW50RGltZW5zaW9ucygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhbFNjYWxlCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSB0aGlzLl91aU1hbmFnZXIudmlld1BhcmFtZXRlcnM7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFtwYWdlV2lkdGgsIHBhZ2VIZWlnaHRdID0gdGhpcy5wYWdlRGltZW5zaW9uczsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtwYWdlV2lkdGggKiByZWFsU2NhbGUsIHBhZ2VIZWlnaHQgKiByZWFsU2NhbGVdOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzZXREaW1zKHdpZHRoLCBoZWlnaHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW3BhcmVudFdpZHRoLCBwYXJlbnRIZWlnaHRdID0gdGhpcy5wYXJlbnREaW1lbnNpb25zOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5zdHlsZS53aWR0aCA9IGAkezEwMCAqIHdpZHRoIC8gcGFyZW50V2lkdGh9JWA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LnN0eWxlLmhlaWdodCA9IGAkezEwMCAqIGhlaWdodCAvIHBhcmVudEhlaWdodH0lYDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZml4RGltcygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXMuZGl2OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aAogICAgICAgICAgICAgICAgICAgICAgICB9ID0gc3R5bGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoUGVyY2VudCA9IHdpZHRoLmVuZHNXaXRoKCIlIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodFBlcmNlbnQgPSBoZWlnaHQuZW5kc1dpdGgoIiUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdpZHRoUGVyY2VudCAmJiBoZWlnaHRQZXJjZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW3BhcmVudFdpZHRoLCBwYXJlbnRIZWlnaHRdID0gdGhpcy5wYXJlbnREaW1lbnNpb25zOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXdpZHRoUGVyY2VudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUud2lkdGggPSBgJHsxMDAgKiBwYXJzZUZsb2F0KHdpZHRoKSAvIHBhcmVudFdpZHRofSVgOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGVpZ2h0UGVyY2VudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUuaGVpZ2h0ID0gYCR7MTAwICogcGFyc2VGbG9hdChoZWlnaHQpIC8gcGFyZW50SGVpZ2h0fSVgOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldEluaXRpYWxUcmFuc2xhdGlvbigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFswLCAwXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVuZGVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5zZXRBdHRyaWJ1dGUoImRhdGEtZWRpdG9yLXJvdGF0aW9uIiwgKDM2MCAtIHRoaXMucm90YXRpb24pICUgMzYwKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYuY2xhc3NOYW1lID0gdGhpcy5uYW1lOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5zZXRBdHRyaWJ1dGUoImlkIiwgdGhpcy5pZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LnNldEF0dHJpYnV0ZSgidGFiSW5kZXgiLCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRJbkZvcmVncm91bmQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYuYWRkRXZlbnRMaXN0ZW5lcigiZm9jdXNpbiIsIHRoaXMuI2JvdW5kRm9jdXNpbik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmFkZEV2ZW50TGlzdGVuZXIoImZvY3Vzb3V0IiwgdGhpcy4jYm91bmRGb2N1c291dCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFt0eCwgdHldID0gdGhpcy5nZXRJbml0aWFsVHJhbnNsYXRpb24oKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc2xhdGUodHgsIHR5KTsKICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF90b29scy5iaW5kRXZlbnRzKSh0aGlzLCB0aGlzLmRpdiwgWyJkcmFnc3RhcnQiLCAicG9pbnRlcmRvd24iXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRpdjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcG9pbnRlcmRvd24oZXZlbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNNYWMKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IF91dGlsLkZlYXR1cmVUZXN0LnBsYXRmb3JtOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXZlbnQuYnV0dG9uICE9PSAwIHx8IGV2ZW50LmN0cmxLZXkgJiYgaXNNYWMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50LmN0cmxLZXkgJiYgIWlzTWFjIHx8IGV2ZW50LnNoaWZ0S2V5IHx8IGV2ZW50Lm1ldGFLZXkgJiYgaXNNYWMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFyZW50LnRvZ2dsZVNlbGVjdGVkKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJlbnQuc2V0U2VsZWN0ZWQodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jaGFzQmVlblNlbGVjdGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0UmVjdCh0eCwgdHkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2NhbGUgPSB0aGlzLnBhcmVudFNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbcGFnZVdpZHRoLCBwYWdlSGVpZ2h0XSA9IHRoaXMucGFnZURpbWVuc2lvbnM7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFtwYWdlWCwgcGFnZVldID0gdGhpcy5wYWdlVHJhbnNsYXRpb247CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNoaWZ0WCA9IHR4IC8gc2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNoaWZ0WSA9IHR5IC8gc2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHggPSB0aGlzLnggKiBwYWdlV2lkdGg7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHkgPSB0aGlzLnkgKiBwYWdlSGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMud2lkdGggKiBwYWdlV2lkdGg7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuaGVpZ2h0ICogcGFnZUhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnJvdGF0aW9uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFt4ICsgc2hpZnRYICsgcGFnZVgsIHBhZ2VIZWlnaHQgLSB5IC0gc2hpZnRZIC0gaGVpZ2h0ICsgcGFnZVksIHggKyBzaGlmdFggKyB3aWR0aCArIHBhZ2VYLCBwYWdlSGVpZ2h0IC0geSAtIHNoaWZ0WSArIHBhZ2VZXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgOTA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFt4ICsgc2hpZnRZICsgcGFnZVgsIHBhZ2VIZWlnaHQgLSB5ICsgc2hpZnRYICsgcGFnZVksIHggKyBzaGlmdFkgKyBoZWlnaHQgKyBwYWdlWCwgcGFnZUhlaWdodCAtIHkgKyBzaGlmdFggKyB3aWR0aCArIHBhZ2VZXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTgwOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbeCAtIHNoaWZ0WCAtIHdpZHRoICsgcGFnZVgsIHBhZ2VIZWlnaHQgLSB5ICsgc2hpZnRZICsgcGFnZVksIHggLSBzaGlmdFggKyBwYWdlWCwgcGFnZUhlaWdodCAtIHkgKyBzaGlmdFkgKyBoZWlnaHQgKyBwYWdlWV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI3MDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW3ggLSBzaGlmdFkgLSBoZWlnaHQgKyBwYWdlWCwgcGFnZUhlaWdodCAtIHkgLSBzaGlmdFggLSB3aWR0aCArIHBhZ2VZLCB4IC0gc2hpZnRZICsgcGFnZVgsIHBhZ2VIZWlnaHQgLSB5IC0gc2hpZnRYICsgcGFnZVldOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgcm90YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRSZWN0SW5DdXJyZW50Q29vcmRzKHJlY3QsIHBhZ2VIZWlnaHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW3gxLCB5MSwgeDIsIHkyXSA9IHJlY3Q7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoID0geDIgLSB4MTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0geTIgLSB5MTsKICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnJvdGF0aW9uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFt4MSwgcGFnZUhlaWdodCAtIHkyLCB3aWR0aCwgaGVpZ2h0XTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgOTA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFt4MSwgcGFnZUhlaWdodCAtIHkxLCBoZWlnaHQsIHdpZHRoXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMTgwOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbeDIsIHBhZ2VIZWlnaHQgLSB5MSwgd2lkdGgsIGhlaWdodF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI3MDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW3gyLCBwYWdlSGVpZ2h0IC0geTIsIGhlaWdodCwgd2lkdGhdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgcm90YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBvbmNlQWRkZWQoKSB7fQogICAgICAgICAgICAgICAgICAgIGlzRW1wdHkoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW5hYmxlRWRpdE1vZGUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuI2lzSW5FZGl0TW9kZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRpc2FibGVFZGl0TW9kZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jaXNJbkVkaXRNb2RlID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlzSW5FZGl0TW9kZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuI2lzSW5FZGl0TW9kZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2hvdWxkR2V0S2V5Ym9hcmRFdmVudHMoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgbmVlZHNUb0JlUmVidWlsdCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGl2ICYmICF0aGlzLmlzQXR0YWNoZWRUb0RPTTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVidWlsZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJGRpdjsKICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJGRpdiA9IHRoaXMuZGl2KSA9PT0gbnVsbCB8fCBfdGhpcyRkaXYgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJGRpdi5hZGRFdmVudExpc3RlbmVyKCJmb2N1c2luIiwgdGhpcy4jYm91bmRGb2N1c2luKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2VyaWFsaXplKCkgewogICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBbiBlZGl0b3IgbXVzdCBiZSBzZXJpYWxpemFibGUiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIGRlc2VyaWFsaXplKGRhdGEsIHBhcmVudCwgdWlNYW5hZ2VyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVkaXRvciA9IG5ldyB0aGlzLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcih7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZDogcGFyZW50LmdldE5leHRJZCgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdWlNYW5hZ2VyCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3Iucm90YXRpb24gPSBkYXRhLnJvdGF0aW9uOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbcGFnZVdpZHRoLCBwYWdlSGVpZ2h0XSA9IGVkaXRvci5wYWdlRGltZW5zaW9uczsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW3gsIHksIHdpZHRoLCBoZWlnaHRdID0gZWRpdG9yLmdldFJlY3RJbkN1cnJlbnRDb29yZHMoZGF0YS5yZWN0LCBwYWdlSGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLnggPSB4IC8gcGFnZVdpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3IueSA9IHkgLyBwYWdlSGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3Iud2lkdGggPSB3aWR0aCAvIHBhZ2VXaWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLmhlaWdodCA9IGhlaWdodCAvIHBhZ2VIZWlnaHQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlZGl0b3I7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbW92ZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYucmVtb3ZlRXZlbnRMaXN0ZW5lcigiZm9jdXNpbiIsIHRoaXMuI2JvdW5kRm9jdXNpbik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LnJlbW92ZUV2ZW50TGlzdGVuZXIoImZvY3Vzb3V0IiwgdGhpcy4jYm91bmRGb2N1c291dCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbWl0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJlbnQucmVtb3ZlKHRoaXMpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzZWxlY3QoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRkaXYyOwogICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkZGl2MiA9IHRoaXMuZGl2KSA9PT0gbnVsbCB8fCBfdGhpcyRkaXYyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRkaXYyLmNsYXNzTGlzdC5hZGQoInNlbGVjdGVkRWRpdG9yIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHVuc2VsZWN0KCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkZGl2MzsKICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJGRpdjMgPSB0aGlzLmRpdikgPT09IG51bGwgfHwgX3RoaXMkZGl2MyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkZGl2My5jbGFzc0xpc3QucmVtb3ZlKCJzZWxlY3RlZEVkaXRvciIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB1cGRhdGVQYXJhbXModHlwZSwgdmFsdWUpIHt9CiAgICAgICAgICAgICAgICAgICAgZGlzYWJsZUVkaXRpbmcoKSB7fQogICAgICAgICAgICAgICAgICAgIGVuYWJsZUVkaXRpbmcoKSB7fQogICAgICAgICAgICAgICAgICAgIGdldCBwcm9wZXJ0aWVzVG9VcGRhdGUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7fTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGNvbnRlbnREaXYoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRpdjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGlzRWRpdGluZygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuI2lzRWRpdGluZzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0IGlzRWRpdGluZyh2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNpc0VkaXRpbmcgPSB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcmVudC5zZXRTZWxlY3RlZCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFyZW50LnNldEFjdGl2ZUVkaXRvcih0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFyZW50LnNldEFjdGl2ZUVkaXRvcihudWxsKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuQW5ub3RhdGlvbkVkaXRvciA9IEFubm90YXRpb25FZGl0b3I7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDE0MSAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLktleWJvYXJkTWFuYWdlciA9IGV4cG9ydHMuQ29tbWFuZE1hbmFnZXIgPSBleHBvcnRzLkNvbG9yTWFuYWdlciA9IGV4cG9ydHMuQW5ub3RhdGlvbkVkaXRvclVJTWFuYWdlciA9IHZvaWQgMDsKICAgICAgICAgICAgICAgIGV4cG9ydHMuYmluZEV2ZW50cyA9IGJpbmRFdmVudHM7CiAgICAgICAgICAgICAgICBleHBvcnRzLm9wYWNpdHlUb0hleCA9IG9wYWNpdHlUb0hleDsKICAgICAgICAgICAgICAgIHZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMSk7CiAgICAgICAgICAgICAgICB2YXIgX2Rpc3BsYXlfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0Mik7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfZGVmaW5lUHJvcGVydHkob2JqLCBrZXksIHZhbHVlKSB7IGtleSA9IF90b1Byb3BlcnR5S2V5KGtleSk7IGlmIChrZXkgaW4gb2JqKSB7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwgeyB2YWx1ZTogdmFsdWUsIGVudW1lcmFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSwgd3JpdGFibGU6IHRydWUgfSk7IH0gZWxzZSB7IG9ialtrZXldID0gdmFsdWU7IH0gcmV0dXJuIG9iajsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3RvUHJvcGVydHlLZXkoYXJnKSB7IHZhciBrZXkgPSBfdG9QcmltaXRpdmUoYXJnLCAic3RyaW5nIik7IHJldHVybiB0eXBlb2Yga2V5ID09PSAic3ltYm9sIiA/IGtleSA6IFN0cmluZyhrZXkpOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfdG9QcmltaXRpdmUoaW5wdXQsIGhpbnQpIHsgaWYgKHR5cGVvZiBpbnB1dCAhPT0gIm9iamVjdCIgfHwgaW5wdXQgPT09IG51bGwpIHJldHVybiBpbnB1dDsgdmFyIHByaW0gPSBpbnB1dFtTeW1ib2wudG9QcmltaXRpdmVdOyBpZiAocHJpbSAhPT0gdW5kZWZpbmVkKSB7IHZhciByZXMgPSBwcmltLmNhbGwoaW5wdXQsIGhpbnQgfHwgImRlZmF1bHQiKTsgaWYgKHR5cGVvZiByZXMgIT09ICJvYmplY3QiKSByZXR1cm4gcmVzOyB0aHJvdyBuZXcgVHlwZUVycm9yKCJAQHRvUHJpbWl0aXZlIG11c3QgcmV0dXJuIGEgcHJpbWl0aXZlIHZhbHVlLiIpOyB9IHJldHVybiAoaGludCA9PT0gInN0cmluZyIgPyBTdHJpbmcgOiBOdW1iZXIpKGlucHV0KTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWMob2JqLCBwcml2YXRlTWFwLCB2YWx1ZSkgeyBfY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbihvYmosIHByaXZhdGVNYXApOyBwcml2YXRlTWFwLnNldChvYmosIHZhbHVlKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHJlY2VpdmVyLCBwcml2YXRlTWFwKSB7IHZhciBkZXNjcmlwdG9yID0gX2NsYXNzRXh0cmFjdEZpZWxkRGVzY3JpcHRvcihyZWNlaXZlciwgcHJpdmF0ZU1hcCwgImdldCIpOyByZXR1cm4gX2NsYXNzQXBwbHlEZXNjcmlwdG9yR2V0KHJlY2VpdmVyLCBkZXNjcmlwdG9yKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzQXBwbHlEZXNjcmlwdG9yR2V0KHJlY2VpdmVyLCBkZXNjcmlwdG9yKSB7IGlmIChkZXNjcmlwdG9yLmdldCkgeyByZXR1cm4gZGVzY3JpcHRvci5nZXQuY2FsbChyZWNlaXZlcik7IH0gcmV0dXJuIGRlc2NyaXB0b3IudmFsdWU7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVGaWVsZFNldChyZWNlaXZlciwgcHJpdmF0ZU1hcCwgdmFsdWUpIHsgdmFyIGRlc2NyaXB0b3IgPSBfY2xhc3NFeHRyYWN0RmllbGREZXNjcmlwdG9yKHJlY2VpdmVyLCBwcml2YXRlTWFwLCAic2V0Iik7IF9jbGFzc0FwcGx5RGVzY3JpcHRvclNldChyZWNlaXZlciwgZGVzY3JpcHRvciwgdmFsdWUpOyByZXR1cm4gdmFsdWU7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc0V4dHJhY3RGaWVsZERlc2NyaXB0b3IocmVjZWl2ZXIsIHByaXZhdGVNYXAsIGFjdGlvbikgeyBpZiAoIXByaXZhdGVNYXAuaGFzKHJlY2VpdmVyKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJhdHRlbXB0ZWQgdG8gIiArIGFjdGlvbiArICIgcHJpdmF0ZSBmaWVsZCBvbiBub24taW5zdGFuY2UiKTsgfSByZXR1cm4gcHJpdmF0ZU1hcC5nZXQocmVjZWl2ZXIpOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NBcHBseURlc2NyaXB0b3JTZXQocmVjZWl2ZXIsIGRlc2NyaXB0b3IsIHZhbHVlKSB7IGlmIChkZXNjcmlwdG9yLnNldCkgeyBkZXNjcmlwdG9yLnNldC5jYWxsKHJlY2VpdmVyLCB2YWx1ZSk7IH0gZWxzZSB7IGlmICghZGVzY3JpcHRvci53cml0YWJsZSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJhdHRlbXB0ZWQgdG8gc2V0IHJlYWQgb25seSBwcml2YXRlIGZpZWxkIik7IH0gZGVzY3JpcHRvci52YWx1ZSA9IHZhbHVlOyB9IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyhvYmosIHByaXZhdGVTZXQpIHsgX2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24ob2JqLCBwcml2YXRlU2V0KTsgcHJpdmF0ZVNldC5hZGQob2JqKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24ob2JqLCBwcml2YXRlQ29sbGVjdGlvbikgeyBpZiAocHJpdmF0ZUNvbGxlY3Rpb24uaGFzKG9iaikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigiQ2Fubm90IGluaXRpYWxpemUgdGhlIHNhbWUgcHJpdmF0ZSBlbGVtZW50cyB0d2ljZSBvbiBhbiBvYmplY3QiKTsgfSB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHJlY2VpdmVyLCBwcml2YXRlU2V0LCBmbikgeyBpZiAoIXByaXZhdGVTZXQuaGFzKHJlY2VpdmVyKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJhdHRlbXB0ZWQgdG8gZ2V0IHByaXZhdGUgZmllbGQgb24gbm9uLWluc3RhbmNlIik7IH0gcmV0dXJuIGZuOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBiaW5kRXZlbnRzKG9iaiwgZWxlbWVudCwgbmFtZXMpIHsKICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgbmFtZXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKG5hbWUsIG9ialtuYW1lXS5iaW5kKG9iaikpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIG9wYWNpdHlUb0hleChvcGFjaXR5KSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE1hdGgucm91bmQoTWF0aC5taW4oMjU1LCBNYXRoLm1heCgxLCAyNTUgKiBvcGFjaXR5KSkpLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAiMCIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgSWRNYW5hZ2VyIHsKICAgICAgICAgICAgICAgICAgICAjaWQgPSAwOwogICAgICAgICAgICAgICAgICAgIGdldElkKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYCR7X3V0aWwuQW5ub3RhdGlvbkVkaXRvclByZWZpeH0ke3RoaXMuI2lkKyt9YDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBDb21tYW5kTWFuYWdlciB7CiAgICAgICAgICAgICAgICAgICAgI2NvbW1hbmRzID0gW107CiAgICAgICAgICAgICAgICAgICAgI2xvY2tlZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICNtYXhTaXplOwogICAgICAgICAgICAgICAgICAgICNwb3NpdGlvbiA9IC0xOwogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgbWF4U2l6ZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogMTI4OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNtYXhTaXplID0gbWF4U2l6ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYWRkKF9yZWYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuZG8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXN0RXhlYywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSBOYU4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdmVyd3JpdGVJZlNhbWVUeXBlID0gZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZWVwVW5kbyA9IGZhbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAobXVzdEV4ZWMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtZCgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLiNsb2NrZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzYXZlID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY21kLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5kbywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuI3Bvc2l0aW9uID09PSAtMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuI2NvbW1hbmRzLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNjb21tYW5kcy5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jcG9zaXRpb24gPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jY29tbWFuZHMucHVzaChzYXZlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAob3ZlcndyaXRlSWZTYW1lVHlwZSAmJiB0aGlzLiNjb21tYW5kc1t0aGlzLiNwb3NpdGlvbl0udHlwZSA9PT0gdHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGtlZXBVbmRvKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F2ZS51bmRvID0gdGhpcy4jY29tbWFuZHNbdGhpcy4jcG9zaXRpb25dLnVuZG87CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNjb21tYW5kc1t0aGlzLiNwb3NpdGlvbl0gPSBzYXZlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5leHQgPSB0aGlzLiNwb3NpdGlvbiArIDE7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuZXh0ID09PSB0aGlzLiNtYXhTaXplKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNjb21tYW5kcy5zcGxpY2UoMCwgMSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNwb3NpdGlvbiA9IG5leHQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobmV4dCA8IHRoaXMuI2NvbW1hbmRzLmxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuI2NvbW1hbmRzLnNwbGljZShuZXh0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNjb21tYW5kcy5wdXNoKHNhdmUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB1bmRvKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy4jcG9zaXRpb24gPT09IC0xKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jbG9ja2VkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jY29tbWFuZHNbdGhpcy4jcG9zaXRpb25dLnVuZG8oKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jbG9ja2VkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuI3Bvc2l0aW9uIC09IDE7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlZG8oKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLiNwb3NpdGlvbiA8IHRoaXMuI2NvbW1hbmRzLmxlbmd0aCAtIDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuI3Bvc2l0aW9uICs9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNsb2NrZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jY29tbWFuZHNbdGhpcy4jcG9zaXRpb25dLmNtZCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jbG9ja2VkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaGFzU29tZXRoaW5nVG9VbmRvKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy4jcG9zaXRpb24gIT09IC0xOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBoYXNTb21ldGhpbmdUb1JlZG8oKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiNwb3NpdGlvbiA8IHRoaXMuI2NvbW1hbmRzLmxlbmd0aCAtIDE7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRlc3Ryb3koKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuI2NvbW1hbmRzID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLkNvbW1hbmRNYW5hZ2VyID0gQ29tbWFuZE1hbmFnZXI7CiAgICAgICAgICAgICAgICB2YXIgX3NlcmlhbGl6ZSA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgY2xhc3MgS2V5Ym9hcmRNYW5hZ2VyIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihjYWxsYmFja3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF9zZXJpYWxpemUpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZlciA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IG5ldyBNYXAoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hbGxLZXlzID0gbmV3IFNldCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc01hYwogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3V0aWwuRmVhdHVyZVRlc3QucGxhdGZvcm07CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgW2tleXMsIGNhbGxiYWNrXSBvZiBjYWxsYmFja3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IG9mIGtleXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpc01hY0tleSA9IGtleS5zdGFydHNXaXRoKCJtYWMrIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzTWFjICYmIGlzTWFjS2V5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tzLnNldChrZXkuc2xpY2UoNCksIGNhbGxiYWNrKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hbGxLZXlzLmFkZChrZXkuc3BsaXQoIisiKS5hdCgtMSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzTWFjICYmICFpc01hY0tleSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrcy5zZXQoa2V5LCBjYWxsYmFjayk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWxsS2V5cy5hZGQoa2V5LnNwbGl0KCIrIikuYXQoLTEpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZXhlYyhzZWxmLCBldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuYWxsS2V5cy5oYXMoZXZlbnQua2V5KSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbGxiYWNrID0gdGhpcy5jYWxsYmFja3MuZ2V0KF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3NlcmlhbGl6ZSwgX3NlcmlhbGl6ZTIpLmNhbGwodGhpcywgZXZlbnQpKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjYWxsYmFjaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrLmJpbmQoc2VsZikoKTsKICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5LZXlib2FyZE1hbmFnZXIgPSBLZXlib2FyZE1hbmFnZXI7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfc2VyaWFsaXplMihldmVudCkgewogICAgICAgICAgICAgICAgICAgIGlmIChldmVudC5hbHRLZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmZXIucHVzaCgiYWx0Iik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChldmVudC5jdHJsS2V5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYnVmZmVyLnB1c2goImN0cmwiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50Lm1ldGFLZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmZXIucHVzaCgibWV0YSIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoZXZlbnQuc2hpZnRLZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmZXIucHVzaCgic2hpZnQiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdGhpcy5idWZmZXIucHVzaChldmVudC5rZXkpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHRoaXMuYnVmZmVyLmpvaW4oIisiKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmJ1ZmZlci5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBDb2xvck1hbmFnZXIgewogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBfY29sb3JzTWFwcGluZyA9IG5ldyBNYXAoW1siQ2FudmFzVGV4dCIsIFswLCAwLCAwXV0sIFsiQ2FudmFzIiwgWzI1NSwgMjU1LCAyNTVdXV0pOwogICAgICAgICAgICAgICAgICAgIGdldCBfY29sb3JzKCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb2xvcnMgPSBuZXcgTWFwKFtbIkNhbnZhc1RleHQiLCBudWxsXSwgWyJDYW52YXMiLCBudWxsXV0pOwogICAgICAgICAgICAgICAgICAgICAgICAoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q29sb3JWYWx1ZXMpKGNvbG9ycyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiX2NvbG9ycyIsIGNvbG9ycyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnZlcnQoY29sb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmdiID0gKDAsIF9kaXNwbGF5X3V0aWxzLmdldFJHQikoY29sb3IpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXdpbmRvdy5tYXRjaE1lZGlhKCIoZm9yY2VkLWNvbG9yczogYWN0aXZlKSIpLm1hdGNoZXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZ2I7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBbbmFtZSwgUkdCXSBvZiB0aGlzLl9jb2xvcnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChSR0IuZXZlcnkoKHgsIGkpID0+IHggPT09IHJnYltpXSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gQ29sb3JNYW5hZ2VyLl9jb2xvcnNNYXBwaW5nLmdldChuYW1lKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmdiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRIZXhDb2RlKG5hbWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmdiID0gdGhpcy5fY29sb3JzLmdldChuYW1lKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFyZ2IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYW1lOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBfdXRpbC5VdGlsLm1ha2VIZXhDb2xvciguLi5yZ2IpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuQ29sb3JNYW5hZ2VyID0gQ29sb3JNYW5hZ2VyOwogICAgICAgICAgICAgICAgdmFyIF9hY3RpdmVFZGl0b3IgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYWxsRWRpdG9ycyA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9hbGxMYXllcnMgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYW5ub3RhdGlvblN0b3JhZ2UgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfY29tbWFuZE1hbmFnZXIgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfY3VycmVudFBhZ2VJbmRleCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9lZGl0b3JUeXBlcyA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9lZGl0b3JzVG9SZXNjYWxlID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2V2ZW50QnVzID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2lkTWFuYWdlciA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9pc0VuYWJsZWQgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfbW9kZSA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9zZWxlY3RlZEVkaXRvcnMgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYm91bmRDb3B5ID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2JvdW5kQ3V0ID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2JvdW5kUGFzdGUgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYm91bmRLZXlkb3duID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2JvdW5kT25FZGl0aW5nQWN0aW9uID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2JvdW5kT25QYWdlQ2hhbmdpbmcgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYm91bmRPblNjYWxlQ2hhbmdpbmcgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYm91bmRPblJvdGF0aW9uQ2hhbmdpbmcgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfcHJldmlvdXNTdGF0ZXMgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfY29udGFpbmVyID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2FkZEtleWJvYXJkTWFuYWdlciA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9yZW1vdmVLZXlib2FyZE1hbmFnZXIgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIHZhciBfYWRkQ29weVBhc3RlTGlzdGVuZXJzID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICB2YXIgX3JlbW92ZUNvcHlQYXN0ZUxpc3RlbmVycyA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9kaXNwYXRjaFVwZGF0ZVN0YXRlcyA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9kaXNwYXRjaFVwZGF0ZVVJID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICB2YXIgX2VuYWJsZUFsbCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9kaXNhYmxlQWxsID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICB2YXIgX2FkZEVkaXRvclRvTGF5ZXIgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIHZhciBfaXNFbXB0eSA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9zZWxlY3RFZGl0b3JzID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICBjbGFzcyBBbm5vdGF0aW9uRWRpdG9yVUlNYW5hZ2VyIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3Rvcihjb250YWluZXIsIGV2ZW50QnVzLCBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX3NlbGVjdEVkaXRvcnMpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2lzRW1wdHkpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2FkZEVkaXRvclRvTGF5ZXIpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2Rpc2FibGVBbGwpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2VuYWJsZUFsbCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfZGlzcGF0Y2hVcGRhdGVVSSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfZGlzcGF0Y2hVcGRhdGVTdGF0ZXMpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX3JlbW92ZUNvcHlQYXN0ZUxpc3RlbmVycyk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfYWRkQ29weVBhc3RlTGlzdGVuZXJzKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF9yZW1vdmVLZXlib2FyZE1hbmFnZXIpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2FkZEtleWJvYXJkTWFuYWdlcik7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9hY3RpdmVFZGl0b3IsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG51bGwKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9hbGxFZGl0b3JzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBuZXcgTWFwKCkKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9hbGxMYXllcnMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG5ldyBNYXAoKQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2Fubm90YXRpb25TdG9yYWdlLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBudWxsCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfY29tbWFuZE1hbmFnZXIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG5ldyBDb21tYW5kTWFuYWdlcigpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfY3VycmVudFBhZ2VJbmRleCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogMAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2VkaXRvclR5cGVzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBudWxsCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfZWRpdG9yc1RvUmVzY2FsZSwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogbmV3IFNldCgpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfZXZlbnRCdXMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG51bGwKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9pZE1hbmFnZXIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG5ldyBJZE1hbmFnZXIoKQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2lzRW5hYmxlZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9tb2RlLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yVHlwZS5OT05FCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfc2VsZWN0ZWRFZGl0b3JzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBuZXcgU2V0KCkKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9ib3VuZENvcHksIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuY29weS5iaW5kKHRoaXMpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfYm91bmRDdXQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuY3V0LmJpbmQodGhpcykKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9ib3VuZFBhc3RlLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0aGlzLnBhc3RlLmJpbmQodGhpcykKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9ib3VuZEtleWRvd24sIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMua2V5ZG93bi5iaW5kKHRoaXMpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfYm91bmRPbkVkaXRpbmdBY3Rpb24sIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMub25FZGl0aW5nQWN0aW9uLmJpbmQodGhpcykKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9ib3VuZE9uUGFnZUNoYW5naW5nLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0aGlzLm9uUGFnZUNoYW5naW5nLmJpbmQodGhpcykKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9ib3VuZE9uU2NhbGVDaGFuZ2luZywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5vblNjYWxlQ2hhbmdpbmcuYmluZCh0aGlzKQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2JvdW5kT25Sb3RhdGlvbkNoYW5naW5nLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0aGlzLm9uUm90YXRpb25DaGFuZ2luZy5iaW5kKHRoaXMpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfcHJldmlvdXNTdGF0ZXMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0VkaXRpbmc6IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzRW1wdHk6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzU29tZXRoaW5nVG9VbmRvOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNTb21ldGhpbmdUb1JlZG86IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1NlbGVjdGVkRWRpdG9yOiBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2NvbnRhaW5lciwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogbnVsbAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9jb250YWluZXIsIGNvbnRhaW5lcik7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfZXZlbnRCdXMsIGV2ZW50QnVzKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ldmVudEJ1cykuX29uKCJlZGl0aW5nYWN0aW9uIiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZE9uRWRpdGluZ0FjdGlvbikpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2V2ZW50QnVzKS5fb24oInBhZ2VjaGFuZ2luZyIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRPblBhZ2VDaGFuZ2luZykpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2V2ZW50QnVzKS5fb24oInNjYWxlY2hhbmdpbmciLCBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2JvdW5kT25TY2FsZUNoYW5naW5nKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZXZlbnRCdXMpLl9vbigicm90YXRpb25jaGFuZ2luZyIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRPblJvdGF0aW9uQ2hhbmdpbmcpKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9hbm5vdGF0aW9uU3RvcmFnZSwgYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZXdQYXJhbWV0ZXJzID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhbFNjYWxlOiBfZGlzcGxheV91dGlscy5QaXhlbHNQZXJJbmNoLlBERl9UT19DU1NfVU5JVFMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3RhdGlvbjogMAogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkZXN0cm95KCkgewogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9yZW1vdmVLZXlib2FyZE1hbmFnZXIsIF9yZW1vdmVLZXlib2FyZE1hbmFnZXIyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2V2ZW50QnVzKS5fb2ZmKCJlZGl0aW5nYWN0aW9uIiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZE9uRWRpdGluZ0FjdGlvbikpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2V2ZW50QnVzKS5fb2ZmKCJwYWdlY2hhbmdpbmciLCBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2JvdW5kT25QYWdlQ2hhbmdpbmcpKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ldmVudEJ1cykuX29mZigic2NhbGVjaGFuZ2luZyIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRPblNjYWxlQ2hhbmdpbmcpKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ldmVudEJ1cykuX29mZigicm90YXRpb25jaGFuZ2luZyIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRPblJvdGF0aW9uQ2hhbmdpbmcpKTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBsYXllciBvZiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FsbExheWVycykudmFsdWVzKCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyLmRlc3Ryb3koKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FsbExheWVycykuY2xlYXIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9hbGxFZGl0b3JzKS5jbGVhcigpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2VkaXRvcnNUb1Jlc2NhbGUpLmNsZWFyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfYWN0aXZlRWRpdG9yLCBudWxsKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9zZWxlY3RlZEVkaXRvcnMpLmNsZWFyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfY29tbWFuZE1hbmFnZXIpLmRlc3Ryb3koKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgb25QYWdlQ2hhbmdpbmcoX3JlZjIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VOdW1iZXIKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IF9yZWYyOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2N1cnJlbnRQYWdlSW5kZXgsIHBhZ2VOdW1iZXIgLSAxKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZm9jdXNNYWluQ29udGFpbmVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2NvbnRhaW5lcikuZm9jdXMoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYWRkU2hvdWxkUmVzY2FsZShlZGl0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9lZGl0b3JzVG9SZXNjYWxlKS5hZGQoZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlU2hvdWxkUmVzY2FsZShlZGl0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9lZGl0b3JzVG9SZXNjYWxlKS5kZWxldGUoZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgb25TY2FsZUNoYW5naW5nKF9yZWYzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjM7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbWl0T3JSZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52aWV3UGFyYW1ldGVycy5yZWFsU2NhbGUgPSBzY2FsZSAqIF9kaXNwbGF5X3V0aWxzLlBpeGVsc1BlckluY2guUERGX1RPX0NTU19VTklUUzsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlZGl0b3Igb2YgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9lZGl0b3JzVG9SZXNjYWxlKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLm9uU2NhbGVDaGFuZ2luZygpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIG9uUm90YXRpb25DaGFuZ2luZyhfcmVmNCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZXNSb3RhdGlvbgogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbWl0T3JSZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52aWV3UGFyYW1ldGVycy5yb3RhdGlvbiA9IHBhZ2VzUm90YXRpb247CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFkZFRvQW5ub3RhdGlvblN0b3JhZ2UoZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZWRpdG9yLmlzRW1wdHkoKSAmJiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2Fubm90YXRpb25TdG9yYWdlKSAmJiAhX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9hbm5vdGF0aW9uU3RvcmFnZSkuaGFzKGVkaXRvci5pZCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYW5ub3RhdGlvblN0b3JhZ2UpLnNldFZhbHVlKGVkaXRvci5pZCwgZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb3B5KGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FjdGl2ZUVkaXRvcikpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYWN0aXZlRWRpdG9yKS5jb21taXRPclJlbW92ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5oYXNTZWxlY3Rpb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlZGl0b3JzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZWRpdG9yIG9mIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc2VsZWN0ZWRFZGl0b3JzKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFlZGl0b3IuaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9ycy5wdXNoKGVkaXRvci5zZXJpYWxpemUoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVkaXRvcnMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQuY2xpcGJvYXJkRGF0YS5zZXREYXRhKCJhcHBsaWNhdGlvbi9wZGZqcyIsIEpTT04uc3RyaW5naWZ5KGVkaXRvcnMpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY3V0KGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29weShldmVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVsZXRlKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHBhc3RlKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkYXRhID0gZXZlbnQuY2xpcGJvYXJkRGF0YS5nZXREYXRhKCJhcHBsaWNhdGlvbi9wZGZqcyIpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IEpTT04ucGFyc2UoZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYHBhc3RlOiAiJHtleC5tZXNzYWdlfSIuYCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGRhdGEpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51bnNlbGVjdEFsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsYXllciA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYWxsTGF5ZXJzKS5nZXQoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9jdXJyZW50UGFnZUluZGV4KSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdFZGl0b3JzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVkaXRvciBvZiBkYXRhKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkRWRpdG9yID0gbGF5ZXIuZGVzZXJpYWxpemUoZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2VyaWFsaXplZEVkaXRvcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0VkaXRvcnMucHVzaChkZXNlcmlhbGl6ZWRFZGl0b3IpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY21kID0gKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZWRpdG9yIG9mIG5ld0VkaXRvcnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfYWRkRWRpdG9yVG9MYXllciwgX2FkZEVkaXRvclRvTGF5ZXIyKS5jYWxsKHRoaXMsIGVkaXRvcik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3NlbGVjdEVkaXRvcnMsIF9zZWxlY3RFZGl0b3JzMikuY2FsbCh0aGlzLCBuZXdFZGl0b3JzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bmRvID0gKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZWRpdG9yIG9mIG5ld0VkaXRvcnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLnJlbW92ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZENvbW1hbmRzKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5kbywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXN0RXhlYzogdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYHBhc3RlOiAiJHtleC5tZXNzYWdlfSIuYCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAga2V5ZG93bihldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkZ2V0QWN0aXZlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoISgoX3RoaXMkZ2V0QWN0aXZlID0gdGhpcy5nZXRBY3RpdmUoKSkgIT09IG51bGwgJiYgX3RoaXMkZ2V0QWN0aXZlICE9PSB2b2lkIDAgJiYgX3RoaXMkZ2V0QWN0aXZlLnNob3VsZEdldEtleWJvYXJkRXZlbnRzKCkpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBBbm5vdGF0aW9uRWRpdG9yVUlNYW5hZ2VyLl9rZXlib2FyZE1hbmFnZXIuZXhlYyh0aGlzLCBldmVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgb25FZGl0aW5nQWN0aW9uKGRldGFpbHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFsidW5kbyIsICJyZWRvIiwgImRlbGV0ZSIsICJzZWxlY3RBbGwiXS5pbmNsdWRlcyhkZXRhaWxzLm5hbWUpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW2RldGFpbHMubmFtZV0oKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzZXRFZGl0aW5nU3RhdGUoaXNFZGl0aW5nKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0VkaXRpbmcpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2FkZEtleWJvYXJkTWFuYWdlciwgX2FkZEtleWJvYXJkTWFuYWdlcjIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9hZGRDb3B5UGFzdGVMaXN0ZW5lcnMsIF9hZGRDb3B5UGFzdGVMaXN0ZW5lcnMyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfZGlzcGF0Y2hVcGRhdGVTdGF0ZXMsIF9kaXNwYXRjaFVwZGF0ZVN0YXRlczIpLmNhbGwodGhpcywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzRWRpdGluZzogX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9tb2RlKSAhPT0gX3V0aWwuQW5ub3RhdGlvbkVkaXRvclR5cGUuTk9ORSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0VtcHR5OiBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9pc0VtcHR5LCBfaXNFbXB0eTIpLmNhbGwodGhpcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzU29tZXRoaW5nVG9VbmRvOiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2NvbW1hbmRNYW5hZ2VyKS5oYXNTb21ldGhpbmdUb1VuZG8oKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNTb21ldGhpbmdUb1JlZG86IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfY29tbWFuZE1hbmFnZXIpLmhhc1NvbWV0aGluZ1RvUmVkbygpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1NlbGVjdGVkRWRpdG9yOiBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9yZW1vdmVLZXlib2FyZE1hbmFnZXIsIF9yZW1vdmVLZXlib2FyZE1hbmFnZXIyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfcmVtb3ZlQ29weVBhc3RlTGlzdGVuZXJzLCBfcmVtb3ZlQ29weVBhc3RlTGlzdGVuZXJzMikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2Rpc3BhdGNoVXBkYXRlU3RhdGVzLCBfZGlzcGF0Y2hVcGRhdGVTdGF0ZXMyKS5jYWxsKHRoaXMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0VkaXRpbmc6IGZhbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZWdpc3RlckVkaXRvclR5cGVzKHR5cGVzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2VkaXRvclR5cGVzKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfZWRpdG9yVHlwZXMsIHR5cGVzKTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlZGl0b3JUeXBlIG9mIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZWRpdG9yVHlwZXMpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9kaXNwYXRjaFVwZGF0ZVVJLCBfZGlzcGF0Y2hVcGRhdGVVSTIpLmNhbGwodGhpcywgZWRpdG9yVHlwZS5kZWZhdWx0UHJvcGVydGllc1RvVXBkYXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRJZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfaWRNYW5hZ2VyKS5nZXRJZCgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgY3VycmVudExheWVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9hbGxMYXllcnMpLmdldChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2N1cnJlbnRQYWdlSW5kZXgpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGN1cnJlbnRQYWdlSW5kZXgoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2N1cnJlbnRQYWdlSW5kZXgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhZGRMYXllcihsYXllcikgewogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FsbExheWVycykuc2V0KGxheWVyLnBhZ2VJbmRleCwgbGF5ZXIpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9pc0VuYWJsZWQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXllci5lbmFibGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyLmRpc2FibGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZW1vdmVMYXllcihsYXllcikgewogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FsbExheWVycykuZGVsZXRlKGxheWVyLnBhZ2VJbmRleCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHVwZGF0ZU1vZGUobW9kZSkgewogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX21vZGUsIG1vZGUpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAobW9kZSA9PT0gX3V0aWwuQW5ub3RhdGlvbkVkaXRvclR5cGUuTk9ORSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRFZGl0aW5nU3RhdGUoZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfZGlzYWJsZUFsbCwgX2Rpc2FibGVBbGwyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRFZGl0aW5nU3RhdGUodHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9lbmFibGVBbGwsIF9lbmFibGVBbGwyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBsYXllciBvZiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FsbExheWVycykudmFsdWVzKCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXllci51cGRhdGVNb2RlKG1vZGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHVwZGF0ZVRvb2xiYXIobW9kZSkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAobW9kZSA9PT0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9tb2RlKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZXZlbnRCdXMpLmRpc3BhdGNoKCJzd2l0Y2hhbm5vdGF0aW9uZWRpdG9ybW9kZSIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZTogdGhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGUKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHVwZGF0ZVBhcmFtcyh0eXBlLCB2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIV9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZWRpdG9yVHlwZXMpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlZGl0b3Igb2YgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9zZWxlY3RlZEVkaXRvcnMpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3IudXBkYXRlUGFyYW1zKHR5cGUsIHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVkaXRvclR5cGUgb2YgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9lZGl0b3JUeXBlcykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvclR5cGUudXBkYXRlRGVmYXVsdFBhcmFtcyh0eXBlLCB2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0RWRpdG9ycyhwYWdlSW5kZXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZWRpdG9ycyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVkaXRvciBvZiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FsbEVkaXRvcnMpLnZhbHVlcygpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWRpdG9yLnBhZ2VJbmRleCA9PT0gcGFnZUluZGV4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9ycy5wdXNoKGVkaXRvcik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGVkaXRvcnM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldEVkaXRvcihpZCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9hbGxFZGl0b3JzKS5nZXQoaWQpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhZGRFZGl0b3IoZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYWxsRWRpdG9ycykuc2V0KGVkaXRvci5pZCwgZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlRWRpdG9yKGVkaXRvcikgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0MjsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9hbGxFZGl0b3JzKS5kZWxldGUoZWRpdG9yLmlkKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51bnNlbGVjdChlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgICAgICAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0MiA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYW5ub3RhdGlvblN0b3JhZ2UpKSA9PT0gbnVsbCB8fCBfY2xhc3NQcml2YXRlRmllbGRHZXQyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfY2xhc3NQcml2YXRlRmllbGRHZXQyLnJlbW92ZShlZGl0b3IuaWQpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzZXRBY3RpdmVFZGl0b3IoZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FjdGl2ZUVkaXRvcikgPT09IGVkaXRvcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfYWN0aXZlRWRpdG9yLCBlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9kaXNwYXRjaFVwZGF0ZVVJLCBfZGlzcGF0Y2hVcGRhdGVVSTIpLmNhbGwodGhpcywgZWRpdG9yLnByb3BlcnRpZXNUb1VwZGF0ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdG9nZ2xlU2VsZWN0ZWQoZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3NlbGVjdGVkRWRpdG9ycykuaGFzKGVkaXRvcikpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc2VsZWN0ZWRFZGl0b3JzKS5kZWxldGUoZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci51bnNlbGVjdCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfZGlzcGF0Y2hVcGRhdGVTdGF0ZXMsIF9kaXNwYXRjaFVwZGF0ZVN0YXRlczIpLmNhbGwodGhpcywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1NlbGVjdGVkRWRpdG9yOiB0aGlzLmhhc1NlbGVjdGlvbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9zZWxlY3RlZEVkaXRvcnMpLmFkZChlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3Iuc2VsZWN0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2Rpc3BhdGNoVXBkYXRlVUksIF9kaXNwYXRjaFVwZGF0ZVVJMikuY2FsbCh0aGlzLCBlZGl0b3IucHJvcGVydGllc1RvVXBkYXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfZGlzcGF0Y2hVcGRhdGVTdGF0ZXMsIF9kaXNwYXRjaFVwZGF0ZVN0YXRlczIpLmNhbGwodGhpcywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzU2VsZWN0ZWRFZGl0b3I6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldFNlbGVjdGVkKGVkaXRvcikgewogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVkIG9mIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc2VsZWN0ZWRFZGl0b3JzKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVkICE9PSBlZGl0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZC51bnNlbGVjdCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc2VsZWN0ZWRFZGl0b3JzKS5jbGVhcigpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3NlbGVjdGVkRWRpdG9ycykuYWRkKGVkaXRvcik7CiAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5zZWxlY3QoKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfZGlzcGF0Y2hVcGRhdGVVSSwgX2Rpc3BhdGNoVXBkYXRlVUkyKS5jYWxsKHRoaXMsIGVkaXRvci5wcm9wZXJ0aWVzVG9VcGRhdGUpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9kaXNwYXRjaFVwZGF0ZVN0YXRlcywgX2Rpc3BhdGNoVXBkYXRlU3RhdGVzMikuY2FsbCh0aGlzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNTZWxlY3RlZEVkaXRvcjogdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaXNTZWxlY3RlZChlZGl0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc2VsZWN0ZWRFZGl0b3JzKS5oYXMoZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdW5zZWxlY3QoZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci51bnNlbGVjdCgpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3NlbGVjdGVkRWRpdG9ycykuZGVsZXRlKGVkaXRvcik7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2Rpc3BhdGNoVXBkYXRlU3RhdGVzLCBfZGlzcGF0Y2hVcGRhdGVTdGF0ZXMyKS5jYWxsKHRoaXMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1NlbGVjdGVkRWRpdG9yOiB0aGlzLmhhc1NlbGVjdGlvbgogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGhhc1NlbGVjdGlvbigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc2VsZWN0ZWRFZGl0b3JzKS5zaXplICE9PSAwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB1bmRvKCkgewogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2NvbW1hbmRNYW5hZ2VyKS51bmRvKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2Rpc3BhdGNoVXBkYXRlU3RhdGVzLCBfZGlzcGF0Y2hVcGRhdGVTdGF0ZXMyKS5jYWxsKHRoaXMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1NvbWV0aGluZ1RvVW5kbzogX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9jb21tYW5kTWFuYWdlcikuaGFzU29tZXRoaW5nVG9VbmRvKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNTb21ldGhpbmdUb1JlZG86IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0VtcHR5OiBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9pc0VtcHR5LCBfaXNFbXB0eTIpLmNhbGwodGhpcykKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlZG8oKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfY29tbWFuZE1hbmFnZXIpLnJlZG8oKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfZGlzcGF0Y2hVcGRhdGVTdGF0ZXMsIF9kaXNwYXRjaFVwZGF0ZVN0YXRlczIpLmNhbGwodGhpcywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzU29tZXRoaW5nVG9VbmRvOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzU29tZXRoaW5nVG9SZWRvOiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2NvbW1hbmRNYW5hZ2VyKS5oYXNTb21ldGhpbmdUb1JlZG8oKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzRW1wdHk6IF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2lzRW1wdHksIF9pc0VtcHR5MikuY2FsbCh0aGlzKQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYWRkQ29tbWFuZHMocGFyYW1zKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfY29tbWFuZE1hbmFnZXIpLmFkZChwYXJhbXMpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9kaXNwYXRjaFVwZGF0ZVN0YXRlcywgX2Rpc3BhdGNoVXBkYXRlU3RhdGVzMikuY2FsbCh0aGlzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNTb21ldGhpbmdUb1VuZG86IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNTb21ldGhpbmdUb1JlZG86IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNFbXB0eTogX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfaXNFbXB0eSwgX2lzRW1wdHkyKS5jYWxsKHRoaXMpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkZWxldGUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbWl0T3JSZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmhhc1NlbGVjdGlvbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVkaXRvcnMgPSBbLi4uX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9zZWxlY3RlZEVkaXRvcnMpXTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY21kID0gKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlZGl0b3Igb2YgZWRpdG9ycykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5yZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5kbyA9ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZWRpdG9yIG9mIGVkaXRvcnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9hZGRFZGl0b3JUb0xheWVyLCBfYWRkRWRpdG9yVG9MYXllcjIpLmNhbGwodGhpcywgZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRDb21tYW5kcyh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmRvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVzdEV4ZWM6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbW1pdE9yUmVtb3ZlKCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0MzsKICAgICAgICAgICAgICAgICAgICAgICAgKF9jbGFzc1ByaXZhdGVGaWVsZEdldDMgPSBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FjdGl2ZUVkaXRvcikpID09PSBudWxsIHx8IF9jbGFzc1ByaXZhdGVGaWVsZEdldDMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9jbGFzc1ByaXZhdGVGaWVsZEdldDMuY29tbWl0T3JSZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2VsZWN0QWxsKCkgewogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVkaXRvciBvZiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3NlbGVjdGVkRWRpdG9ycykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5jb21taXQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9zZWxlY3RFZGl0b3JzLCBfc2VsZWN0RWRpdG9yczIpLmNhbGwodGhpcywgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9hbGxFZGl0b3JzKS52YWx1ZXMoKSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHVuc2VsZWN0QWxsKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9hY3RpdmVFZGl0b3IpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FjdGl2ZUVkaXRvcikuY29tbWl0T3JSZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9zZWxlY3RlZEVkaXRvcnMpLnNpemUgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVkaXRvciBvZiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3NlbGVjdGVkRWRpdG9ycykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci51bnNlbGVjdCgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfc2VsZWN0ZWRFZGl0b3JzKS5jbGVhcigpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9kaXNwYXRjaFVwZGF0ZVN0YXRlcywgX2Rpc3BhdGNoVXBkYXRlU3RhdGVzMikuY2FsbCh0aGlzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNTZWxlY3RlZEVkaXRvcjogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlzQWN0aXZlKGVkaXRvcikgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9hY3RpdmVFZGl0b3IpID09PSBlZGl0b3I7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldEFjdGl2ZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYWN0aXZlRWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0TW9kZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfbW9kZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5Bbm5vdGF0aW9uRWRpdG9yVUlNYW5hZ2VyID0gQW5ub3RhdGlvbkVkaXRvclVJTWFuYWdlcjsKICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9hZGRLZXlib2FyZE1hbmFnZXIyKCkgewogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfY29udGFpbmVyKS5hZGRFdmVudExpc3RlbmVyKCJrZXlkb3duIiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZEtleWRvd24pKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9yZW1vdmVLZXlib2FyZE1hbmFnZXIyKCkgewogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfY29udGFpbmVyKS5yZW1vdmVFdmVudExpc3RlbmVyKCJrZXlkb3duIiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZEtleWRvd24pKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9hZGRDb3B5UGFzdGVMaXN0ZW5lcnMyKCkgewogICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoImNvcHkiLCBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2JvdW5kQ29weSkpOwogICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoImN1dCIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRDdXQpKTsKICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCJwYXN0ZSIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRQYXN0ZSkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3JlbW92ZUNvcHlQYXN0ZUxpc3RlbmVyczIoKSB7CiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigiY29weSIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRDb3B5KSk7CiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigiY3V0IiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZEN1dCkpOwogICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoInBhc3RlIiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZFBhc3RlKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfZGlzcGF0Y2hVcGRhdGVTdGF0ZXMyKGRldGFpbHMpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBoYXNDaGFuZ2VkID0gT2JqZWN0LmVudHJpZXMoZGV0YWlscykuc29tZShfcmVmNSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBba2V5LCB2YWx1ZV0gPSBfcmVmNTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfcHJldmlvdXNTdGF0ZXMpW2tleV0gIT09IHZhbHVlOwogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIGlmIChoYXNDaGFuZ2VkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZXZlbnRCdXMpLmRpc3BhdGNoKCJhbm5vdGF0aW9uZWRpdG9yc3RhdGVzY2hhbmdlZCIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZTogdGhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldGFpbHM6IE9iamVjdC5hc3NpZ24oX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9wcmV2aW91c1N0YXRlcyksIGRldGFpbHMpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9kaXNwYXRjaFVwZGF0ZVVJMihkZXRhaWxzKSB7CiAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ldmVudEJ1cykuZGlzcGF0Y2goImFubm90YXRpb25lZGl0b3JwYXJhbXNjaGFuZ2VkIiwgewogICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2U6IHRoaXMsCiAgICAgICAgICAgICAgICAgICAgICAgIGRldGFpbHMKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9lbmFibGVBbGwyKCkgewogICAgICAgICAgICAgICAgICAgIGlmICghX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9pc0VuYWJsZWQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfaXNFbmFibGVkLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBsYXllciBvZiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FsbExheWVycykudmFsdWVzKCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxheWVyLmVuYWJsZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2Rpc2FibGVBbGwyKCkgewogICAgICAgICAgICAgICAgICAgIHRoaXMudW5zZWxlY3RBbGwoKTsKICAgICAgICAgICAgICAgICAgICBpZiAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9pc0VuYWJsZWQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfaXNFbmFibGVkLCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgbGF5ZXIgb2YgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9hbGxMYXllcnMpLnZhbHVlcygpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXllci5kaXNhYmxlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfYWRkRWRpdG9yVG9MYXllcjIoZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGF5ZXIgPSBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FsbExheWVycykuZ2V0KGVkaXRvci5wYWdlSW5kZXgpOwogICAgICAgICAgICAgICAgICAgIGlmIChsYXllcikgewogICAgICAgICAgICAgICAgICAgICAgICBsYXllci5hZGRPclJlYnVpbGQoZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZEVkaXRvcihlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9pc0VtcHR5MigpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9hbGxFZGl0b3JzKS5zaXplID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9hbGxFZGl0b3JzKS5zaXplID09PSAxKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZWRpdG9yIG9mIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYWxsRWRpdG9ycykudmFsdWVzKCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlZGl0b3IuaXNFbXB0eSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9zZWxlY3RFZGl0b3JzMihlZGl0b3JzKSB7CiAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9zZWxlY3RlZEVkaXRvcnMpLmNsZWFyKCk7CiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlZGl0b3Igb2YgZWRpdG9ycykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWRpdG9yLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9zZWxlY3RlZEVkaXRvcnMpLmFkZChlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3Iuc2VsZWN0KCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2Rpc3BhdGNoVXBkYXRlU3RhdGVzLCBfZGlzcGF0Y2hVcGRhdGVTdGF0ZXMyKS5jYWxsKHRoaXMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgaGFzU2VsZWN0ZWRFZGl0b3I6IHRydWUKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIF9kZWZpbmVQcm9wZXJ0eShBbm5vdGF0aW9uRWRpdG9yVUlNYW5hZ2VyLCAiX2tleWJvYXJkTWFuYWdlciIsIG5ldyBLZXlib2FyZE1hbmFnZXIoW1tbImN0cmwrYSIsICJtYWMrbWV0YSthIl0sIEFubm90YXRpb25FZGl0b3JVSU1hbmFnZXIucHJvdG90eXBlLnNlbGVjdEFsbF0sIFtbImN0cmwreiIsICJtYWMrbWV0YSt6Il0sIEFubm90YXRpb25FZGl0b3JVSU1hbmFnZXIucHJvdG90eXBlLnVuZG9dLCBbWyJjdHJsK3kiLCAiY3RybCtzaGlmdCtaIiwgIm1hYyttZXRhK3NoaWZ0K1oiXSwgQW5ub3RhdGlvbkVkaXRvclVJTWFuYWdlci5wcm90b3R5cGUucmVkb10sIFtbIkJhY2tzcGFjZSIsICJhbHQrQmFja3NwYWNlIiwgImN0cmwrQmFja3NwYWNlIiwgInNoaWZ0K0JhY2tzcGFjZSIsICJtYWMrQmFja3NwYWNlIiwgIm1hYythbHQrQmFja3NwYWNlIiwgIm1hYytjdHJsK0JhY2tzcGFjZSIsICJEZWxldGUiLCAiY3RybCtEZWxldGUiLCAic2hpZnQrRGVsZXRlIl0sIEFubm90YXRpb25FZGl0b3JVSU1hbmFnZXIucHJvdG90eXBlLmRlbGV0ZV0sIFtbIkVzY2FwZSIsICJtYWMrRXNjYXBlIl0sIEFubm90YXRpb25FZGl0b3JVSU1hbmFnZXIucHJvdG90eXBlLnVuc2VsZWN0QWxsXV0pKTsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTQyICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuU3RhdFRpbWVyID0gZXhwb3J0cy5SZW5kZXJpbmdDYW5jZWxsZWRFeGNlcHRpb24gPSBleHBvcnRzLlBpeGVsc1BlckluY2ggPSBleHBvcnRzLlBhZ2VWaWV3cG9ydCA9IGV4cG9ydHMuUERGRGF0ZVN0cmluZyA9IGV4cG9ydHMuRE9NU3RhbmRhcmRGb250RGF0YUZhY3RvcnkgPSBleHBvcnRzLkRPTVNWR0ZhY3RvcnkgPSBleHBvcnRzLkRPTUZpbHRlckZhY3RvcnkgPSBleHBvcnRzLkRPTUNhbnZhc0ZhY3RvcnkgPSBleHBvcnRzLkRPTUNNYXBSZWFkZXJGYWN0b3J5ID0gZXhwb3J0cy5Bbm5vdGF0aW9uUHJlZml4ID0gdm9pZCAwOwogICAgICAgICAgICAgICAgZXhwb3J0cy5kZXByZWNhdGVkID0gZGVwcmVjYXRlZDsKICAgICAgICAgICAgICAgIGV4cG9ydHMuZ2V0Q29sb3JWYWx1ZXMgPSBnZXRDb2xvclZhbHVlczsKICAgICAgICAgICAgICAgIGV4cG9ydHMuZ2V0Q3VycmVudFRyYW5zZm9ybSA9IGdldEN1cnJlbnRUcmFuc2Zvcm07CiAgICAgICAgICAgICAgICBleHBvcnRzLmdldEN1cnJlbnRUcmFuc2Zvcm1JbnZlcnNlID0gZ2V0Q3VycmVudFRyYW5zZm9ybUludmVyc2U7CiAgICAgICAgICAgICAgICBleHBvcnRzLmdldEZpbGVuYW1lRnJvbVVybCA9IGdldEZpbGVuYW1lRnJvbVVybDsKICAgICAgICAgICAgICAgIGV4cG9ydHMuZ2V0UGRmRmlsZW5hbWVGcm9tVXJsID0gZ2V0UGRmRmlsZW5hbWVGcm9tVXJsOwogICAgICAgICAgICAgICAgZXhwb3J0cy5nZXRSR0IgPSBnZXRSR0I7CiAgICAgICAgICAgICAgICBleHBvcnRzLmdldFhmYVBhZ2VWaWV3cG9ydCA9IGdldFhmYVBhZ2VWaWV3cG9ydDsKICAgICAgICAgICAgICAgIGV4cG9ydHMuaXNEYXRhU2NoZW1lID0gaXNEYXRhU2NoZW1lOwogICAgICAgICAgICAgICAgZXhwb3J0cy5pc1BkZkZpbGUgPSBpc1BkZkZpbGU7CiAgICAgICAgICAgICAgICBleHBvcnRzLmlzVmFsaWRGZXRjaFVybCA9IGlzVmFsaWRGZXRjaFVybDsKICAgICAgICAgICAgICAgIGV4cG9ydHMubG9hZFNjcmlwdCA9IGxvYWRTY3JpcHQ7CiAgICAgICAgICAgICAgICBleHBvcnRzLnNldExheWVyRGltZW5zaW9ucyA9IHNldExheWVyRGltZW5zaW9uczsKICAgICAgICAgICAgICAgIHZhciBfYmFzZV9mYWN0b3J5ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDMpOwogICAgICAgICAgICAgICAgdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygxKTsKICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyhvYmosIHByaXZhdGVTZXQpIHsgX2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24ob2JqLCBwcml2YXRlU2V0KTsgcHJpdmF0ZVNldC5hZGQob2JqKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWMob2JqLCBwcml2YXRlTWFwLCB2YWx1ZSkgeyBfY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbihvYmosIHByaXZhdGVNYXApOyBwcml2YXRlTWFwLnNldChvYmosIHZhbHVlKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24ob2JqLCBwcml2YXRlQ29sbGVjdGlvbikgeyBpZiAocHJpdmF0ZUNvbGxlY3Rpb24uaGFzKG9iaikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigiQ2Fubm90IGluaXRpYWxpemUgdGhlIHNhbWUgcHJpdmF0ZSBlbGVtZW50cyB0d2ljZSBvbiBhbiBvYmplY3QiKTsgfSB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHJlY2VpdmVyLCBwcml2YXRlU2V0LCBmbikgeyBpZiAoIXByaXZhdGVTZXQuaGFzKHJlY2VpdmVyKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJhdHRlbXB0ZWQgdG8gZ2V0IHByaXZhdGUgZmllbGQgb24gbm9uLWluc3RhbmNlIik7IH0gcmV0dXJuIGZuOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlRmllbGRHZXQocmVjZWl2ZXIsIHByaXZhdGVNYXApIHsgdmFyIGRlc2NyaXB0b3IgPSBfY2xhc3NFeHRyYWN0RmllbGREZXNjcmlwdG9yKHJlY2VpdmVyLCBwcml2YXRlTWFwLCAiZ2V0Iik7IHJldHVybiBfY2xhc3NBcHBseURlc2NyaXB0b3JHZXQocmVjZWl2ZXIsIGRlc2NyaXB0b3IpOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NBcHBseURlc2NyaXB0b3JHZXQocmVjZWl2ZXIsIGRlc2NyaXB0b3IpIHsgaWYgKGRlc2NyaXB0b3IuZ2V0KSB7IHJldHVybiBkZXNjcmlwdG9yLmdldC5jYWxsKHJlY2VpdmVyKTsgfSByZXR1cm4gZGVzY3JpcHRvci52YWx1ZTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHJlY2VpdmVyLCBwcml2YXRlTWFwLCB2YWx1ZSkgeyB2YXIgZGVzY3JpcHRvciA9IF9jbGFzc0V4dHJhY3RGaWVsZERlc2NyaXB0b3IocmVjZWl2ZXIsIHByaXZhdGVNYXAsICJzZXQiKTsgX2NsYXNzQXBwbHlEZXNjcmlwdG9yU2V0KHJlY2VpdmVyLCBkZXNjcmlwdG9yLCB2YWx1ZSk7IHJldHVybiB2YWx1ZTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzRXh0cmFjdEZpZWxkRGVzY3JpcHRvcihyZWNlaXZlciwgcHJpdmF0ZU1hcCwgYWN0aW9uKSB7IGlmICghcHJpdmF0ZU1hcC5oYXMocmVjZWl2ZXIpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoImF0dGVtcHRlZCB0byAiICsgYWN0aW9uICsgIiBwcml2YXRlIGZpZWxkIG9uIG5vbi1pbnN0YW5jZSIpOyB9IHJldHVybiBwcml2YXRlTWFwLmdldChyZWNlaXZlcik7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc0FwcGx5RGVzY3JpcHRvclNldChyZWNlaXZlciwgZGVzY3JpcHRvciwgdmFsdWUpIHsgaWYgKGRlc2NyaXB0b3Iuc2V0KSB7IGRlc2NyaXB0b3Iuc2V0LmNhbGwocmVjZWl2ZXIsIHZhbHVlKTsgfSBlbHNlIHsgaWYgKCFkZXNjcmlwdG9yLndyaXRhYmxlKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoImF0dGVtcHRlZCB0byBzZXQgcmVhZCBvbmx5IHByaXZhdGUgZmllbGQiKTsgfSBkZXNjcmlwdG9yLnZhbHVlID0gdmFsdWU7IH0gfQogICAgICAgICAgICAgICAgY29uc3QgU1ZHX05TID0gImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIjsKICAgICAgICAgICAgICAgIGNvbnN0IEFubm90YXRpb25QcmVmaXggPSAicGRmanNfaW50ZXJuYWxfaWRfIjsKICAgICAgICAgICAgICAgIGV4cG9ydHMuQW5ub3RhdGlvblByZWZpeCA9IEFubm90YXRpb25QcmVmaXg7CiAgICAgICAgICAgICAgICBjbGFzcyBQaXhlbHNQZXJJbmNoIHsKICAgICAgICAgICAgICAgICAgICBzdGF0aWMgQ1NTID0gOTYuMDsKICAgICAgICAgICAgICAgICAgICBzdGF0aWMgUERGID0gNzIuMDsKICAgICAgICAgICAgICAgICAgICBzdGF0aWMgUERGX1RPX0NTU19VTklUUyA9IHRoaXMuQ1NTIC8gdGhpcy5QREY7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLlBpeGVsc1BlckluY2ggPSBQaXhlbHNQZXJJbmNoOwogICAgICAgICAgICAgICAgdmFyIF9jYWNoZSA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9kZWZzID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2RvY0lkID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2RvY3VtZW50ID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2hjbUZpbHRlciA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9oY21LZXkgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfaGNtVXJsID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2lkID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2NhY2hlMiA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9kZWZzMiA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9hcHBlbmRGZUZ1bmMgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIGNsYXNzIERPTUZpbHRlckZhY3RvcnkgZXh0ZW5kcyBfYmFzZV9mYWN0b3J5LkJhc2VGaWx0ZXJGYWN0b3J5IHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvY0lkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3duZXJEb2N1bWVudCA9IGdsb2JhbFRoaXMuZG9jdW1lbnQKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDoge307CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfYXBwZW5kRmVGdW5jKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2RlZnMyLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXQ6IF9nZXRfZGVmcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldDogdm9pZCAwCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfY2FjaGUyLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXQ6IF9nZXRfY2FjaGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXQ6IHZvaWQgMAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2NhY2hlLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2b2lkIDAKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9kZWZzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2b2lkIDAKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9kb2NJZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdm9pZCAwCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfZG9jdW1lbnQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHZvaWQgMAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2hjbUZpbHRlciwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdm9pZCAwCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfaGNtS2V5LCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2b2lkIDAKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9oY21VcmwsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHZvaWQgMAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2lkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiAwCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2RvY0lkLCBkb2NJZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfZG9jdW1lbnQsIG93bmVyRG9jdW1lbnQpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhZGRGaWx0ZXIobWFwcykgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkaWQsIF90aGlzJGlkMjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFtYXBzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gIm5vbmUiOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB2YWx1ZSA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfY2FjaGUyKS5nZXQobWFwcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB0YWJsZVIsIHRhYmxlRywgdGFibGVCLCBrZXk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXBzLmxlbmd0aCA9PT0gMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWFwUiA9IG1hcHNbMF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBidWZmZXIgPSBuZXcgQXJyYXkoMjU2KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMjU2OyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidWZmZXJbaV0gPSBtYXBSW2ldIC8gMjU1OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAga2V5ID0gdGFibGVSID0gdGFibGVHID0gdGFibGVCID0gYnVmZmVyLmpvaW4oIiwiKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFttYXBSLCBtYXBHLCBtYXBCXSA9IG1hcHM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBidWZmZXJSID0gbmV3IEFycmF5KDI1Nik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBidWZmZXJHID0gbmV3IEFycmF5KDI1Nik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBidWZmZXJCID0gbmV3IEFycmF5KDI1Nik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyUltpXSA9IG1hcFJbaV0gLyAyNTU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyR1tpXSA9IG1hcEdbaV0gLyAyNTU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyQltpXSA9IG1hcEJbaV0gLyAyNTU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWJsZVIgPSBidWZmZXJSLmpvaW4oIiwiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhYmxlRyA9IGJ1ZmZlckcuam9pbigiLCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFibGVCID0gYnVmZmVyQi5qb2luKCIsIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXkgPSBgJHt0YWJsZVJ9JHt0YWJsZUd9JHt0YWJsZUJ9YDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfY2FjaGUyKS5nZXQoa2V5KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2NhY2hlMikuc2V0KG1hcHMsIHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpZCA9IGBnXyR7X2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9kb2NJZCl9X3RyYW5zZmVyX21hcF8keyhfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2lkLCAoX3RoaXMkaWQgPSBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2lkKSwgX3RoaXMkaWQyID0gX3RoaXMkaWQrKywgX3RoaXMkaWQpKSwgX3RoaXMkaWQyKX1gOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSBgdXJsKCMke2lkfSlgOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2NhY2hlMikuc2V0KG1hcHMsIHVybCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfY2FjaGUyKS5zZXQoa2V5LCB1cmwpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWx0ZXIgPSBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RvY3VtZW50KS5jcmVhdGVFbGVtZW50TlMoU1ZHX05TLCAiZmlsdGVyIiwgU1ZHX05TKTsKICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyLnNldEF0dHJpYnV0ZSgiaWQiLCBpZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlci5zZXRBdHRyaWJ1dGUoImNvbG9yLWludGVycG9sYXRpb24tZmlsdGVycyIsICJzUkdCIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZlQ29tcG9uZW50VHJhbnNmZXIgPSBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RvY3VtZW50KS5jcmVhdGVFbGVtZW50TlMoU1ZHX05TLCAiZmVDb21wb25lbnRUcmFuc2ZlciIpOwogICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIuYXBwZW5kKGZlQ29tcG9uZW50VHJhbnNmZXIpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9hcHBlbmRGZUZ1bmMsIF9hcHBlbmRGZUZ1bmMyKS5jYWxsKHRoaXMsIGZlQ29tcG9uZW50VHJhbnNmZXIsICJmZUZ1bmNSIiwgdGFibGVSKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfYXBwZW5kRmVGdW5jLCBfYXBwZW5kRmVGdW5jMikuY2FsbCh0aGlzLCBmZUNvbXBvbmVudFRyYW5zZmVyLCAiZmVGdW5jRyIsIHRhYmxlRyk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2FwcGVuZEZlRnVuYywgX2FwcGVuZEZlRnVuYzIpLmNhbGwodGhpcywgZmVDb21wb25lbnRUcmFuc2ZlciwgImZlRnVuY0IiLCB0YWJsZUIpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RlZnMyKS5hcHBlbmQoZmlsdGVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHVybDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYWRkSENNRmlsdGVyKGZnQ29sb3IsIGJnQ29sb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9jbGFzc1ByaXZhdGVGaWVsZEdldDI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGtleSA9IGAke2ZnQ29sb3J9LSR7YmdDb2xvcn1gOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9oY21LZXkpID09PSBrZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2hjbVVybCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9oY21LZXksIGtleSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfaGNtVXJsLCAibm9uZSIpOwogICAgICAgICAgICAgICAgICAgICAgICAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0MiA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfaGNtRmlsdGVyKSkgPT09IG51bGwgfHwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0MiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2NsYXNzUHJpdmF0ZUZpZWxkR2V0Mi5yZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFmZ0NvbG9yIHx8ICFiZ0NvbG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9oY21VcmwpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZGVmczIpLnN0eWxlLmNvbG9yID0gZmdDb2xvcjsKICAgICAgICAgICAgICAgICAgICAgICAgZmdDb2xvciA9IGdldENvbXB1dGVkU3R5bGUoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9kZWZzMikpLmdldFByb3BlcnR5VmFsdWUoImNvbG9yIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZnUkdCID0gZ2V0UkdCKGZnQ29sb3IpOwogICAgICAgICAgICAgICAgICAgICAgICBmZ0NvbG9yID0gX3V0aWwuVXRpbC5tYWtlSGV4Q29sb3IoLi4uZmdSR0IpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RlZnMyKS5zdHlsZS5jb2xvciA9IGJnQ29sb3I7CiAgICAgICAgICAgICAgICAgICAgICAgIGJnQ29sb3IgPSBnZXRDb21wdXRlZFN0eWxlKF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZGVmczIpKS5nZXRQcm9wZXJ0eVZhbHVlKCJjb2xvciIpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBiZ1JHQiA9IGdldFJHQihiZ0NvbG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgYmdDb2xvciA9IF91dGlsLlV0aWwubWFrZUhleENvbG9yKC4uLmJnUkdCKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9kZWZzMikuc3R5bGUuY29sb3IgPSAiIjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZnQ29sb3IgPT09ICIjMDAwMDAwIiAmJiBiZ0NvbG9yID09PSAiI2ZmZmZmZiIgfHwgZmdDb2xvciA9PT0gYmdDb2xvcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfaGNtVXJsKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXAgPSBuZXcgQXJyYXkoMjU2KTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gMjU1OyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHggPSBpIC8gMjU1OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwW2ldID0geCA8PSAwLjAzOTI4ID8geCAvIDEyLjkyIDogKCh4ICsgMC4wNTUpIC8gMS4wNTUpICoqIDIuNDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0YWJsZSA9IG1hcC5qb2luKCIsIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkID0gYGdfJHtfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RvY0lkKX1faGNtX2ZpbHRlcmA7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbHRlciA9IF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfaGNtRmlsdGVyLCBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RvY3VtZW50KS5jcmVhdGVFbGVtZW50TlMoU1ZHX05TLCAiZmlsdGVyIiwgU1ZHX05TKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlci5zZXRBdHRyaWJ1dGUoImlkIiwgaWQpOwogICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIuc2V0QXR0cmlidXRlKCJjb2xvci1pbnRlcnBvbGF0aW9uLWZpbHRlcnMiLCAic1JHQiIpOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmVDb21wb25lbnRUcmFuc2ZlciA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZG9jdW1lbnQpLmNyZWF0ZUVsZW1lbnROUyhTVkdfTlMsICJmZUNvbXBvbmVudFRyYW5zZmVyIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlci5hcHBlbmQoZmVDb21wb25lbnRUcmFuc2Zlcik7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2FwcGVuZEZlRnVuYywgX2FwcGVuZEZlRnVuYzIpLmNhbGwodGhpcywgZmVDb21wb25lbnRUcmFuc2ZlciwgImZlRnVuY1IiLCB0YWJsZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2FwcGVuZEZlRnVuYywgX2FwcGVuZEZlRnVuYzIpLmNhbGwodGhpcywgZmVDb21wb25lbnRUcmFuc2ZlciwgImZlRnVuY0ciLCB0YWJsZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2FwcGVuZEZlRnVuYywgX2FwcGVuZEZlRnVuYzIpLmNhbGwodGhpcywgZmVDb21wb25lbnRUcmFuc2ZlciwgImZlRnVuY0IiLCB0YWJsZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZlQ29sb3JNYXRyaXggPSBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RvY3VtZW50KS5jcmVhdGVFbGVtZW50TlMoU1ZHX05TLCAiZmVDb2xvck1hdHJpeCIpOwogICAgICAgICAgICAgICAgICAgICAgICBmZUNvbG9yTWF0cml4LnNldEF0dHJpYnV0ZSgidHlwZSIsICJtYXRyaXgiKTsKICAgICAgICAgICAgICAgICAgICAgICAgZmVDb2xvck1hdHJpeC5zZXRBdHRyaWJ1dGUoInZhbHVlcyIsICIwLjIxMjYgMC43MTUyIDAuMDcyMiAwIDAgMC4yMTI2IDAuNzE1MiAwLjA3MjIgMCAwIDAuMjEyNiAwLjcxNTIgMC4wNzIyIDAgMCAwIDAgMCAxIDAiKTsKICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyLmFwcGVuZChmZUNvbG9yTWF0cml4KTsKICAgICAgICAgICAgICAgICAgICAgICAgZmVDb21wb25lbnRUcmFuc2ZlciA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZG9jdW1lbnQpLmNyZWF0ZUVsZW1lbnROUyhTVkdfTlMsICJmZUNvbXBvbmVudFRyYW5zZmVyIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlci5hcHBlbmQoZmVDb21wb25lbnRUcmFuc2Zlcik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGdldFN0ZXBzID0gKGMsIG4pID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0ID0gZmdSR0JbY10gLyAyNTU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlbmQgPSBiZ1JHQltjXSAvIDI1NTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFyciA9IG5ldyBBcnJheShuICsgMSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8PSBuOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcnJbaV0gPSBzdGFydCArIGkgLyBuICogKGVuZCAtIHN0YXJ0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhcnIuam9pbigiLCIpOwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9hcHBlbmRGZUZ1bmMsIF9hcHBlbmRGZUZ1bmMyKS5jYWxsKHRoaXMsIGZlQ29tcG9uZW50VHJhbnNmZXIsICJmZUZ1bmNSIiwgZ2V0U3RlcHMoMCwgNSkpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9hcHBlbmRGZUZ1bmMsIF9hcHBlbmRGZUZ1bmMyKS5jYWxsKHRoaXMsIGZlQ29tcG9uZW50VHJhbnNmZXIsICJmZUZ1bmNHIiwgZ2V0U3RlcHMoMSwgNSkpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9hcHBlbmRGZUZ1bmMsIF9hcHBlbmRGZUZ1bmMyKS5jYWxsKHRoaXMsIGZlQ29tcG9uZW50VHJhbnNmZXIsICJmZUZ1bmNCIiwgZ2V0U3RlcHMoMiwgNSkpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RlZnMyKS5hcHBlbmQoZmlsdGVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9oY21VcmwsIGB1cmwoIyR7aWR9KWApOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9oY21VcmwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkZXN0cm95KCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQga2VlcEhDTSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChrZWVwSENNICYmIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfaGNtVXJsKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RlZnMpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RlZnMpLnBhcmVudE5vZGUucGFyZW50Tm9kZS5yZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfZGVmcywgbnVsbCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfY2FjaGUpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2NhY2hlKS5jbGVhcigpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9jYWNoZSwgbnVsbCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9pZCwgMCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5ET01GaWx0ZXJGYWN0b3J5ID0gRE9NRmlsdGVyRmFjdG9yeTsKICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9nZXRfY2FjaGUoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfY2FjaGUpIHx8IF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfY2FjaGUsIG5ldyBNYXAoKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfZ2V0X2RlZnMoKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RlZnMpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpdiA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZG9jdW1lbnQpLmNyZWF0ZUVsZW1lbnQoImRpdiIpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gZGl2OwogICAgICAgICAgICAgICAgICAgICAgICBzdHlsZS52aXNpYmlsaXR5ID0gImhpZGRlbiI7CiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlLmNvbnRhaW4gPSAic3RyaWN0IjsKICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUud2lkdGggPSBzdHlsZS5oZWlnaHQgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBzdHlsZS5wb3NpdGlvbiA9ICJhYnNvbHV0ZSI7CiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlLnRvcCA9IHN0eWxlLmxlZnQgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBzdHlsZS56SW5kZXggPSAtMTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3ZnID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9kb2N1bWVudCkuY3JlYXRlRWxlbWVudE5TKFNWR19OUywgInN2ZyIpOwogICAgICAgICAgICAgICAgICAgICAgICBzdmcuc2V0QXR0cmlidXRlKCJ3aWR0aCIsIDApOwogICAgICAgICAgICAgICAgICAgICAgICBzdmcuc2V0QXR0cmlidXRlKCJoZWlnaHQiLCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9kZWZzLCBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RvY3VtZW50KS5jcmVhdGVFbGVtZW50TlMoU1ZHX05TLCAiZGVmcyIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgZGl2LmFwcGVuZChzdmcpOwogICAgICAgICAgICAgICAgICAgICAgICBzdmcuYXBwZW5kKF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZGVmcykpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2RvY3VtZW50KS5ib2R5LmFwcGVuZChkaXYpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9kZWZzKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9hcHBlbmRGZUZ1bmMyKGZlQ29tcG9uZW50VHJhbnNmZXIsIGZ1bmMsIHRhYmxlKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZmVGdW5jID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9kb2N1bWVudCkuY3JlYXRlRWxlbWVudE5TKFNWR19OUywgZnVuYyk7CiAgICAgICAgICAgICAgICAgICAgZmVGdW5jLnNldEF0dHJpYnV0ZSgidHlwZSIsICJkaXNjcmV0ZSIpOwogICAgICAgICAgICAgICAgICAgIGZlRnVuYy5zZXRBdHRyaWJ1dGUoInRhYmxlVmFsdWVzIiwgdGFibGUpOwogICAgICAgICAgICAgICAgICAgIGZlQ29tcG9uZW50VHJhbnNmZXIuYXBwZW5kKGZlRnVuYyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBET01DYW52YXNGYWN0b3J5IGV4dGVuZHMgX2Jhc2VfZmFjdG9yeS5CYXNlQ2FudmFzRmFjdG9yeSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvd25lckRvY3VtZW50ID0gZ2xvYmFsVGhpcy5kb2N1bWVudAogICAgICAgICAgICAgICAgICAgICAgICB9ID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiB7fTsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9jdW1lbnQgPSBvd25lckRvY3VtZW50OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfY3JlYXRlQ2FudmFzKHdpZHRoLCBoZWlnaHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FudmFzID0gdGhpcy5fZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiY2FudmFzIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhcy53aWR0aCA9IHdpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICBjYW52YXMuaGVpZ2h0ID0gaGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FudmFzOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuRE9NQ2FudmFzRmFjdG9yeSA9IERPTUNhbnZhc0ZhY3Rvcnk7CiAgICAgICAgICAgICAgICBhc3luYyBmdW5jdGlvbiBmZXRjaERhdGEodXJsKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IGFzVHlwZWRBcnJheSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVmFsaWRGZXRjaFVybCh1cmwsIGRvY3VtZW50LmJhc2VVUkkpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFyZXNwb25zZS5vaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHJlc3BvbnNlLnN0YXR1c1RleHQpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhc1R5cGVkQXJyYXkgPyBuZXcgVWludDhBcnJheShhd2FpdCByZXNwb25zZS5hcnJheUJ1ZmZlcigpKSA6ICgwLCBfdXRpbC5zdHJpbmdUb0J5dGVzKShhd2FpdCByZXNwb25zZS50ZXh0KCkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3Qub3BlbigiR0VUIiwgdXJsLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFzVHlwZWRBcnJheSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdC5yZXNwb25zZVR5cGUgPSAiYXJyYXlidWZmZXIiOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3Qub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcXVlc3QucmVhZHlTdGF0ZSAhPT0gWE1MSHR0cFJlcXVlc3QuRE9ORSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXF1ZXN0LnN0YXR1cyA9PT0gMjAwIHx8IHJlcXVlc3Quc3RhdHVzID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRhdGE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFzVHlwZWRBcnJheSAmJiByZXF1ZXN0LnJlc3BvbnNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBuZXcgVWludDhBcnJheShyZXF1ZXN0LnJlc3BvbnNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFhc1R5cGVkQXJyYXkgJiYgcmVxdWVzdC5yZXNwb25zZVRleHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9ICgwLCBfdXRpbC5zdHJpbmdUb0J5dGVzKShyZXF1ZXN0LnJlc3BvbnNlVGV4dCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKHJlcXVlc3Quc3RhdHVzVGV4dCkpOwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0LnNlbmQobnVsbCk7CiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBET01DTWFwUmVhZGVyRmFjdG9yeSBleHRlbmRzIF9iYXNlX2ZhY3RvcnkuQmFzZUNNYXBSZWFkZXJGYWN0b3J5IHsKICAgICAgICAgICAgICAgICAgICBfZmV0Y2hEYXRhKHVybCwgY29tcHJlc3Npb25UeXBlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmZXRjaERhdGEodXJsLCB0aGlzLmlzQ29tcHJlc3NlZCkudGhlbihkYXRhID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY01hcERhdGE6IGRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tcHJlc3Npb25UeXBlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLkRPTUNNYXBSZWFkZXJGYWN0b3J5ID0gRE9NQ01hcFJlYWRlckZhY3Rvcnk7CiAgICAgICAgICAgICAgICBjbGFzcyBET01TdGFuZGFyZEZvbnREYXRhRmFjdG9yeSBleHRlbmRzIF9iYXNlX2ZhY3RvcnkuQmFzZVN0YW5kYXJkRm9udERhdGFGYWN0b3J5IHsKICAgICAgICAgICAgICAgICAgICBfZmV0Y2hEYXRhKHVybCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmV0Y2hEYXRhKHVybCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5ET01TdGFuZGFyZEZvbnREYXRhRmFjdG9yeSA9IERPTVN0YW5kYXJkRm9udERhdGFGYWN0b3J5OwogICAgICAgICAgICAgICAgY2xhc3MgRE9NU1ZHRmFjdG9yeSBleHRlbmRzIF9iYXNlX2ZhY3RvcnkuQmFzZVNWR0ZhY3RvcnkgewogICAgICAgICAgICAgICAgICAgIF9jcmVhdGVTVkcodHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFNWR19OUywgdHlwZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5ET01TVkdGYWN0b3J5ID0gRE9NU1ZHRmFjdG9yeTsKICAgICAgICAgICAgICAgIGNsYXNzIFBhZ2VWaWV3cG9ydCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IoX3JlZikgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlld0JveCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRYID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldFkgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9udEZsaXAgPSBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52aWV3Qm94ID0gdmlld0JveDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zY2FsZSA9IHNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJvdGF0aW9uID0gcm90YXRpb247CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub2Zmc2V0WCA9IG9mZnNldFg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub2Zmc2V0WSA9IG9mZnNldFk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNlbnRlclggPSAodmlld0JveFsyXSArIHZpZXdCb3hbMF0pIC8gMjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2VudGVyWSA9ICh2aWV3Qm94WzNdICsgdmlld0JveFsxXSkgLyAyOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcm90YXRlQSwgcm90YXRlQiwgcm90YXRlQywgcm90YXRlRDsKICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb24gJT0gMzYwOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAocm90YXRpb24gPCAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3RhdGlvbiArPSAzNjA7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChyb3RhdGlvbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAxODA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRlQSA9IC0xOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0ZUIgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0ZUMgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0ZUQgPSAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSA5MDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3RhdGVBID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3RhdGVCID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3RhdGVDID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3RhdGVEID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgMjcwOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0ZUEgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0ZUIgPSAtMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3RhdGVDID0gLTE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRlRCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRlQSA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRlQiA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRlQyA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRlRCA9IC0xOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIlBhZ2VWaWV3cG9ydDogSW52YWxpZCByb3RhdGlvbiwgbXVzdCBiZSBhIG11bHRpcGxlIG9mIDkwIGRlZ3JlZXMuIik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbnRGbGlwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3RhdGVDID0gLXJvdGF0ZUM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3RhdGVEID0gLXJvdGF0ZUQ7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG9mZnNldENhbnZhc1gsIG9mZnNldENhbnZhc1k7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB3aWR0aCwgaGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICBpZiAocm90YXRlQSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0Q2FudmFzWCA9IE1hdGguYWJzKGNlbnRlclkgLSB2aWV3Qm94WzFdKSAqIHNjYWxlICsgb2Zmc2V0WDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldENhbnZhc1kgPSBNYXRoLmFicyhjZW50ZXJYIC0gdmlld0JveFswXSkgKiBzY2FsZSArIG9mZnNldFk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCA9ICh2aWV3Qm94WzNdIC0gdmlld0JveFsxXSkgKiBzY2FsZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodCA9ICh2aWV3Qm94WzJdIC0gdmlld0JveFswXSkgKiBzY2FsZTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldENhbnZhc1ggPSBNYXRoLmFicyhjZW50ZXJYIC0gdmlld0JveFswXSkgKiBzY2FsZSArIG9mZnNldFg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRDYW52YXNZID0gTWF0aC5hYnMoY2VudGVyWSAtIHZpZXdCb3hbMV0pICogc2NhbGUgKyBvZmZzZXRZOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAodmlld0JveFsyXSAtIHZpZXdCb3hbMF0pICogc2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQgPSAodmlld0JveFszXSAtIHZpZXdCb3hbMV0pICogc2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc2Zvcm0gPSBbcm90YXRlQSAqIHNjYWxlLCByb3RhdGVCICogc2NhbGUsIHJvdGF0ZUMgKiBzY2FsZSwgcm90YXRlRCAqIHNjYWxlLCBvZmZzZXRDYW52YXNYIC0gcm90YXRlQSAqIHNjYWxlICogY2VudGVyWCAtIHJvdGF0ZUMgKiBzY2FsZSAqIGNlbnRlclksIG9mZnNldENhbnZhc1kgLSByb3RhdGVCICogc2NhbGUgKiBjZW50ZXJYIC0gcm90YXRlRCAqIHNjYWxlICogY2VudGVyWV07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2lkdGggPSB3aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCByYXdEaW1zKCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3Qm94CiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSB0aGlzOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInJhd0RpbXMiLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlV2lkdGg6IHZpZXdCb3hbMl0gLSB2aWV3Qm94WzBdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUhlaWdodDogdmlld0JveFszXSAtIHZpZXdCb3hbMV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlWDogdmlld0JveFswXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VZOiB2aWV3Qm94WzFdCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjbG9uZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlID0gdGhpcy5zY2FsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0aW9uID0gdGhpcy5yb3RhdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldFggPSB0aGlzLm9mZnNldFgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRZID0gdGhpcy5vZmZzZXRZLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9udEZsaXAgPSBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiB7fTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQYWdlVmlld3BvcnQoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlld0JveDogdGhpcy52aWV3Qm94LnNsaWNlKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0aW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0WCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldFksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb250RmxpcAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY29udmVydFRvVmlld3BvcnRQb2ludCh4LCB5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBfdXRpbC5VdGlsLmFwcGx5VHJhbnNmb3JtKFt4LCB5XSwgdGhpcy50cmFuc2Zvcm0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb252ZXJ0VG9WaWV3cG9ydFJlY3RhbmdsZShyZWN0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRvcExlZnQgPSBfdXRpbC5VdGlsLmFwcGx5VHJhbnNmb3JtKFtyZWN0WzBdLCByZWN0WzFdXSwgdGhpcy50cmFuc2Zvcm0pOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBib3R0b21SaWdodCA9IF91dGlsLlV0aWwuYXBwbHlUcmFuc2Zvcm0oW3JlY3RbMl0sIHJlY3RbM11dLCB0aGlzLnRyYW5zZm9ybSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbdG9wTGVmdFswXSwgdG9wTGVmdFsxXSwgYm90dG9tUmlnaHRbMF0sIGJvdHRvbVJpZ2h0WzFdXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY29udmVydFRvUGRmUG9pbnQoeCwgeSkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX3V0aWwuVXRpbC5hcHBseUludmVyc2VUcmFuc2Zvcm0oW3gsIHldLCB0aGlzLnRyYW5zZm9ybSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5QYWdlVmlld3BvcnQgPSBQYWdlVmlld3BvcnQ7CiAgICAgICAgICAgICAgICBjbGFzcyBSZW5kZXJpbmdDYW5jZWxsZWRFeGNlcHRpb24gZXh0ZW5kcyBfdXRpbC5CYXNlRXhjZXB0aW9uIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3Rvcihtc2csIHR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGV4dHJhRGVsYXkgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKG1zZywgIlJlbmRlcmluZ0NhbmNlbGxlZEV4Y2VwdGlvbiIpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSB0eXBlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmV4dHJhRGVsYXkgPSBleHRyYURlbGF5OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuUmVuZGVyaW5nQ2FuY2VsbGVkRXhjZXB0aW9uID0gUmVuZGVyaW5nQ2FuY2VsbGVkRXhjZXB0aW9uOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gaXNEYXRhU2NoZW1lKHVybCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IGlpID0gdXJsLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICBsZXQgaSA9IDA7CiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGkgPCBpaSAmJiB1cmxbaV0udHJpbSgpID09PSAiIikgewogICAgICAgICAgICAgICAgICAgICAgICBpKys7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiB1cmwuc3Vic3RyaW5nKGksIGkgKyA1KS50b0xvd2VyQ2FzZSgpID09PSAiZGF0YToiOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gaXNQZGZGaWxlKGZpbGVuYW1lKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBmaWxlbmFtZSA9PT0gInN0cmluZyIgJiYgL1wucGRmJC9pLnRlc3QoZmlsZW5hbWUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gZ2V0RmlsZW5hbWVGcm9tVXJsKHVybCkgewogICAgICAgICAgICAgICAgICAgIGxldCBvbmx5U3RyaXBQYXRoID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICBpZiAoIW9ubHlTdHJpcFBhdGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgW3VybF0gPSB1cmwuc3BsaXQoL1sjP10vLCAxKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHVybC5zdWJzdHJpbmcodXJsLmxhc3RJbmRleE9mKCIvIikgKyAxKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGdldFBkZkZpbGVuYW1lRnJvbVVybCh1cmwpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgZGVmYXVsdEZpbGVuYW1lID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiAiZG9jdW1lbnQucGRmIjsKICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHVybCAhPT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRlZmF1bHRGaWxlbmFtZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGlzRGF0YVNjaGVtZSh1cmwpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgnZ2V0UGRmRmlsZW5hbWVGcm9tVXJsOiBpZ25vcmUgImRhdGE6Ii1VUkwgZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnMuJyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkZWZhdWx0RmlsZW5hbWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlVVJJID0gL14oPzooPzpbXjpdKzopP1wvXC9bXi9dKyk/KFtePyNdKikoXD9bXiNdKik/KCMuKik/JC87CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVGaWxlbmFtZSA9IC9bXi8/Iz1dK1wucGRmXGIoPyEuKlwucGRmXGIpL2k7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3BsaXRVUkkgPSByZVVSSS5leGVjKHVybCk7CiAgICAgICAgICAgICAgICAgICAgbGV0IHN1Z2dlc3RlZEZpbGVuYW1lID0gcmVGaWxlbmFtZS5leGVjKHNwbGl0VVJJWzFdKSB8fCByZUZpbGVuYW1lLmV4ZWMoc3BsaXRVUklbMl0pIHx8IHJlRmlsZW5hbWUuZXhlYyhzcGxpdFVSSVszXSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKHN1Z2dlc3RlZEZpbGVuYW1lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1Z2dlc3RlZEZpbGVuYW1lID0gc3VnZ2VzdGVkRmlsZW5hbWVbMF07CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdWdnZXN0ZWRGaWxlbmFtZS5pbmNsdWRlcygiJSIpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Z2dlc3RlZEZpbGVuYW1lID0gcmVGaWxlbmFtZS5leGVjKGRlY29kZVVSSUNvbXBvbmVudChzdWdnZXN0ZWRGaWxlbmFtZSkpWzBdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXgpIHt9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN1Z2dlc3RlZEZpbGVuYW1lIHx8IGRlZmF1bHRGaWxlbmFtZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIFN0YXRUaW1lciB7CiAgICAgICAgICAgICAgICAgICAgc3RhcnRlZCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgICAgICAgICAgICAgdGltZXMgPSBbXTsKICAgICAgICAgICAgICAgICAgICB0aW1lKG5hbWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5hbWUgaW4gdGhpcy5zdGFydGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYFRpbWVyIGlzIGFscmVhZHkgcnVubmluZyBmb3IgJHtuYW1lfWApOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhcnRlZFtuYW1lXSA9IERhdGUubm93KCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHRpbWVFbmQobmFtZSkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIShuYW1lIGluIHRoaXMuc3RhcnRlZCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgVGltZXIgaGFzIG5vdCBiZWVuIHN0YXJ0ZWQgZm9yICR7bmFtZX1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRpbWVzLnB1c2goewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0OiB0aGlzLnN0YXJ0ZWRbbmFtZV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQ6IERhdGUubm93KCkKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnN0YXJ0ZWRbbmFtZV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHRvU3RyaW5nKCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvdXRCdWYgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGxvbmdlc3QgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUKICAgICAgICAgICAgICAgICAgICAgICAgfSBvZiB0aGlzLnRpbWVzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb25nZXN0ID0gTWF0aC5tYXgobmFtZS5sZW5ndGgsIGxvbmdlc3QpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kCiAgICAgICAgICAgICAgICAgICAgICAgIH0gb2YgdGhpcy50aW1lcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0QnVmLnB1c2goYCR7bmFtZS5wYWRFbmQobG9uZ2VzdCl9ICR7ZW5kIC0gc3RhcnR9bXNcbmApOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXRCdWYuam9pbigiIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5TdGF0VGltZXIgPSBTdGF0VGltZXI7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBpc1ZhbGlkRmV0Y2hVcmwodXJsLCBiYXNlVXJsKSB7CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvdG9jb2wKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGJhc2VVcmwgPyBuZXcgVVJMKHVybCwgYmFzZVVybCkgOiBuZXcgVVJMKHVybCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwcm90b2NvbCA9PT0gImh0dHA6IiB8fCBwcm90b2NvbCA9PT0gImh0dHBzOiI7CiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGxvYWRTY3JpcHQoc3JjKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IHJlbW92ZVNjcmlwdEVsZW1lbnQgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpOwogICAgICAgICAgICAgICAgICAgICAgICBzY3JpcHQuc3JjID0gc3JjOwogICAgICAgICAgICAgICAgICAgICAgICBzY3JpcHQub25sb2FkID0gZnVuY3Rpb24gKGV2dCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlbW92ZVNjcmlwdEVsZW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JpcHQucmVtb3ZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGV2dCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIHNjcmlwdC5vbmVycm9yID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihgQ2Fubm90IGxvYWQgc2NyaXB0IGF0OiAke3NjcmlwdC5zcmN9YCkpOwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAoZG9jdW1lbnQuaGVhZCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpLmFwcGVuZChzY3JpcHQpOwogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gZGVwcmVjYXRlZChkZXRhaWxzKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coIkRlcHJlY2F0ZWQgQVBJIHVzYWdlOiAiICsgZGV0YWlscyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBsZXQgcGRmRGF0ZVN0cmluZ1JlZ2V4OwogICAgICAgICAgICAgICAgY2xhc3MgUERGRGF0ZVN0cmluZyB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIHRvRGF0ZU9iamVjdChpbnB1dCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlucHV0IHx8IHR5cGVvZiBpbnB1dCAhPT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghcGRmRGF0ZVN0cmluZ1JlZ2V4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZGZEYXRlU3RyaW5nUmVnZXggPSBuZXcgUmVnRXhwKCJeRDoiICsgIihcXGR7NH0pIiArICIoXFxkezJ9KT8iICsgIihcXGR7Mn0pPyIgKyAiKFxcZHsyfSk/IiArICIoXFxkezJ9KT8iICsgIihcXGR7Mn0pPyIgKyAiKFtafCt8LV0pPyIgKyAiKFxcZHsyfSk/IiArICInPyIgKyAiKFxcZHsyfSk/IiArICInPyIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPSBwZGZEYXRlU3RyaW5nUmVnZXguZXhlYyhpbnB1dCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghbWF0Y2hlcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeWVhciA9IHBhcnNlSW50KG1hdGNoZXNbMV0sIDEwKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1vbnRoID0gcGFyc2VJbnQobWF0Y2hlc1syXSwgMTApOwogICAgICAgICAgICAgICAgICAgICAgICBtb250aCA9IG1vbnRoID49IDEgJiYgbW9udGggPD0gMTIgPyBtb250aCAtIDEgOiAwOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgZGF5ID0gcGFyc2VJbnQobWF0Y2hlc1szXSwgMTApOwogICAgICAgICAgICAgICAgICAgICAgICBkYXkgPSBkYXkgPj0gMSAmJiBkYXkgPD0gMzEgPyBkYXkgOiAxOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgaG91ciA9IHBhcnNlSW50KG1hdGNoZXNbNF0sIDEwKTsKICAgICAgICAgICAgICAgICAgICAgICAgaG91ciA9IGhvdXIgPj0gMCAmJiBob3VyIDw9IDIzID8gaG91ciA6IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtaW51dGUgPSBwYXJzZUludChtYXRjaGVzWzVdLCAxMCk7CiAgICAgICAgICAgICAgICAgICAgICAgIG1pbnV0ZSA9IG1pbnV0ZSA+PSAwICYmIG1pbnV0ZSA8PSA1OSA/IG1pbnV0ZSA6IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzZWNvbmQgPSBwYXJzZUludChtYXRjaGVzWzZdLCAxMCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHNlY29uZCA9IHNlY29uZCA+PSAwICYmIHNlY29uZCA8PSA1OSA/IHNlY29uZCA6IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuaXZlcnNhbFRpbWVSZWxhdGlvbiA9IG1hdGNoZXNbN10gfHwgIloiOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0SG91ciA9IHBhcnNlSW50KG1hdGNoZXNbOF0sIDEwKTsKICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0SG91ciA9IG9mZnNldEhvdXIgPj0gMCAmJiBvZmZzZXRIb3VyIDw9IDIzID8gb2Zmc2V0SG91ciA6IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBvZmZzZXRNaW51dGUgPSBwYXJzZUludChtYXRjaGVzWzldLCAxMCkgfHwgMDsKICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0TWludXRlID0gb2Zmc2V0TWludXRlID49IDAgJiYgb2Zmc2V0TWludXRlIDw9IDU5ID8gb2Zmc2V0TWludXRlIDogMDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVuaXZlcnNhbFRpbWVSZWxhdGlvbiA9PT0gIi0iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3VyICs9IG9mZnNldEhvdXI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW51dGUgKz0gb2Zmc2V0TWludXRlOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHVuaXZlcnNhbFRpbWVSZWxhdGlvbiA9PT0gIisiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3VyIC09IG9mZnNldEhvdXI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW51dGUgLT0gb2Zmc2V0TWludXRlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRGF0ZShEYXRlLlVUQyh5ZWFyLCBtb250aCwgZGF5LCBob3VyLCBtaW51dGUsIHNlY29uZCkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuUERGRGF0ZVN0cmluZyA9IFBERkRhdGVTdHJpbmc7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBnZXRYZmFQYWdlVmlld3BvcnQoeGZhUGFnZSwgX3JlZjIpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgewogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZSA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0aW9uID0gMAogICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmMjsKICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQKICAgICAgICAgICAgICAgICAgICB9ID0geGZhUGFnZS5hdHRyaWJ1dGVzLnN0eWxlOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHZpZXdCb3ggPSBbMCwgMCwgcGFyc2VJbnQod2lkdGgpLCBwYXJzZUludChoZWlnaHQpXTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFBhZ2VWaWV3cG9ydCh7CiAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdCb3gsCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlLAogICAgICAgICAgICAgICAgICAgICAgICByb3RhdGlvbgogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UkdCKGNvbG9yKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbG9yLnN0YXJ0c1dpdGgoIiMiKSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb2xvclJHQiA9IHBhcnNlSW50KGNvbG9yLnNsaWNlKDEpLCAxNik7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbKGNvbG9yUkdCICYgMHhmZjAwMDApID4+IDE2LCAoY29sb3JSR0IgJiAweDAwZmYwMCkgPj4gOCwgY29sb3JSR0IgJiAweDAwMDBmZl07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChjb2xvci5zdGFydHNXaXRoKCJyZ2IoIikpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbG9yLnNsaWNlKDQsIC0xKS5zcGxpdCgiLCIpLm1hcCh4ID0+IHBhcnNlSW50KHgpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbG9yLnN0YXJ0c1dpdGgoInJnYmEoIikpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbG9yLnNsaWNlKDUsIC0xKS5zcGxpdCgiLCIpLm1hcCh4ID0+IHBhcnNlSW50KHgpKS5zbGljZSgwLCAzKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBOb3QgYSB2YWxpZCBjb2xvciBmb3JtYXQ6ICIke2NvbG9yfSJgKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzAsIDAsIDBdOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gZ2V0Q29sb3JWYWx1ZXMoY29sb3JzKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3BhbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNwYW4iKTsKICAgICAgICAgICAgICAgICAgICBzcGFuLnN0eWxlLnZpc2liaWxpdHkgPSAiaGlkZGVuIjsKICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZChzcGFuKTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgY29sb3JzLmtleXMoKSkgewogICAgICAgICAgICAgICAgICAgICAgICBzcGFuLnN0eWxlLmNvbG9yID0gbmFtZTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29tcHV0ZWRDb2xvciA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHNwYW4pLmNvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICBjb2xvcnMuc2V0KG5hbWUsIGdldFJHQihjb21wdXRlZENvbG9yKSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNwYW4ucmVtb3ZlKCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBnZXRDdXJyZW50VHJhbnNmb3JtKGN0eCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgYSwKICAgICAgICAgICAgICAgICAgICAgICAgYiwKICAgICAgICAgICAgICAgICAgICAgICAgYywKICAgICAgICAgICAgICAgICAgICAgICAgZCwKICAgICAgICAgICAgICAgICAgICAgICAgZSwKICAgICAgICAgICAgICAgICAgICAgICAgZgogICAgICAgICAgICAgICAgICAgIH0gPSBjdHguZ2V0VHJhbnNmb3JtKCk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFthLCBiLCBjLCBkLCBlLCBmXTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGdldEN1cnJlbnRUcmFuc2Zvcm1JbnZlcnNlKGN0eCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgYSwKICAgICAgICAgICAgICAgICAgICAgICAgYiwKICAgICAgICAgICAgICAgICAgICAgICAgYywKICAgICAgICAgICAgICAgICAgICAgICAgZCwKICAgICAgICAgICAgICAgICAgICAgICAgZSwKICAgICAgICAgICAgICAgICAgICAgICAgZgogICAgICAgICAgICAgICAgICAgIH0gPSBjdHguZ2V0VHJhbnNmb3JtKCkuaW52ZXJ0U2VsZigpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBbYSwgYiwgYywgZCwgZSwgZl07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBzZXRMYXllckRpbWVuc2lvbnMoZGl2LCB2aWV3cG9ydCkgewogICAgICAgICAgICAgICAgICAgIGxldCBtdXN0RmxpcCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgbGV0IG11c3RSb3RhdGUgPSBhcmd1bWVudHMubGVuZ3RoID4gMyAmJiBhcmd1bWVudHNbM10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1szXSA6IHRydWU7CiAgICAgICAgICAgICAgICAgICAgaWYgKHZpZXdwb3J0IGluc3RhbmNlb2YgUGFnZVZpZXdwb3J0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VXaWR0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VIZWlnaHQKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHZpZXdwb3J0LnJhd0RpbXM7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBkaXY7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoU3RyID0gYGNhbGModmFyKC0tc2NhbGUtZmFjdG9yKSAqICR7cGFnZVdpZHRofXB4KWA7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodFN0ciA9IGBjYWxjKHZhcigtLXNjYWxlLWZhY3RvcikgKiAke3BhZ2VIZWlnaHR9cHgpYDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFtdXN0RmxpcCB8fCB2aWV3cG9ydC5yb3RhdGlvbiAlIDE4MCA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUud2lkdGggPSB3aWR0aFN0cjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlLmhlaWdodCA9IGhlaWdodFN0cjsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlLndpZHRoID0gaGVpZ2h0U3RyOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUuaGVpZ2h0ID0gd2lkdGhTdHI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKG11c3RSb3RhdGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZGl2LnNldEF0dHJpYnV0ZSgiZGF0YS1tYWluLXJvdGF0aW9uIiwgdmlld3BvcnQucm90YXRpb24pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTQzICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuQmFzZVN0YW5kYXJkRm9udERhdGFGYWN0b3J5ID0gZXhwb3J0cy5CYXNlU1ZHRmFjdG9yeSA9IGV4cG9ydHMuQmFzZUZpbHRlckZhY3RvcnkgPSBleHBvcnRzLkJhc2VDYW52YXNGYWN0b3J5ID0gZXhwb3J0cy5CYXNlQ01hcFJlYWRlckZhY3RvcnkgPSB2b2lkIDA7CiAgICAgICAgICAgICAgICB2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEpOwogICAgICAgICAgICAgICAgY2xhc3MgQmFzZUZpbHRlckZhY3RvcnkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25zdHJ1Y3RvciA9PT0gQmFzZUZpbHRlckZhY3RvcnkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIkNhbm5vdCBpbml0aWFsaXplIEJhc2VGaWx0ZXJGYWN0b3J5LiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFkZEZpbHRlcihtYXBzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAibm9uZSI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFkZEhDTUZpbHRlcihmZ0NvbG9yLCBiZ0NvbG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAibm9uZSI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRlc3Ryb3koKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBrZWVwSENNID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLkJhc2VGaWx0ZXJGYWN0b3J5ID0gQmFzZUZpbHRlckZhY3Rvcnk7CiAgICAgICAgICAgICAgICBjbGFzcyBCYXNlQ2FudmFzRmFjdG9yeSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yID09PSBCYXNlQ2FudmFzRmFjdG9yeSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQ2Fubm90IGluaXRpYWxpemUgQmFzZUNhbnZhc0ZhY3RvcnkuIik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY3JlYXRlKHdpZHRoLCBoZWlnaHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdpZHRoIDw9IDAgfHwgaGVpZ2h0IDw9IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiSW52YWxpZCBjYW52YXMgc2l6ZSIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbnZhcyA9IHRoaXMuX2NyZWF0ZUNhbnZhcyh3aWR0aCwgaGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQ6IGNhbnZhcy5nZXRDb250ZXh0KCIyZCIpCiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlc2V0KGNhbnZhc0FuZENvbnRleHQsIHdpZHRoLCBoZWlnaHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjYW52YXNBbmRDb250ZXh0LmNhbnZhcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDYW52YXMgaXMgbm90IHNwZWNpZmllZCIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3aWR0aCA8PSAwIHx8IGhlaWdodCA8PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgY2FudmFzIHNpemUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjYW52YXNBbmRDb250ZXh0LmNhbnZhcy53aWR0aCA9IHdpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICBjYW52YXNBbmRDb250ZXh0LmNhbnZhcy5oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRlc3Ryb3koY2FudmFzQW5kQ29udGV4dCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNhbnZhc0FuZENvbnRleHQuY2FudmFzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkNhbnZhcyBpcyBub3Qgc3BlY2lmaWVkIik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzQW5kQ29udGV4dC5jYW52YXMud2lkdGggPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBjYW52YXNBbmRDb250ZXh0LmNhbnZhcy5oZWlnaHQgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBjYW52YXNBbmRDb250ZXh0LmNhbnZhcyA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhc0FuZENvbnRleHQuY29udGV4dCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9jcmVhdGVDYW52YXMod2lkdGgsIGhlaWdodCkgewogICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBtZXRob2QgYF9jcmVhdGVDYW52YXNgIGNhbGxlZC4iKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLkJhc2VDYW52YXNGYWN0b3J5ID0gQmFzZUNhbnZhc0ZhY3Rvcnk7CiAgICAgICAgICAgICAgICBjbGFzcyBCYXNlQ01hcFJlYWRlckZhY3RvcnkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKF9yZWYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhc2VVcmwgPSBudWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNDb21wcmVzc2VkID0gdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uc3RydWN0b3IgPT09IEJhc2VDTWFwUmVhZGVyRmFjdG9yeSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQ2Fubm90IGluaXRpYWxpemUgQmFzZUNNYXBSZWFkZXJGYWN0b3J5LiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmFzZVVybCA9IGJhc2VVcmw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNDb21wcmVzc2VkID0gaXNDb21wcmVzc2VkOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhc3luYyBmZXRjaChfcmVmMikgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjI7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5iYXNlVXJsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBDTWFwICJiYXNlVXJsIiBwYXJhbWV0ZXIgbXVzdCBiZSBzcGVjaWZpZWQsIGVuc3VyZSB0aGF0ICcgKyAndGhlICJjTWFwVXJsIiBhbmQgImNNYXBQYWNrZWQiIEFQSSBwYXJhbWV0ZXJzIGFyZSBwcm92aWRlZC4nKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW5hbWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiQ01hcCBuYW1lIG11c3QgYmUgc3BlY2lmaWVkLiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVybCA9IHRoaXMuYmFzZVVybCArIG5hbWUgKyAodGhpcy5pc0NvbXByZXNzZWQgPyAiLmJjbWFwIiA6ICIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29tcHJlc3Npb25UeXBlID0gdGhpcy5pc0NvbXByZXNzZWQgPyBfdXRpbC5DTWFwQ29tcHJlc3Npb25UeXBlLkJJTkFSWSA6IF91dGlsLkNNYXBDb21wcmVzc2lvblR5cGUuTk9ORTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2ZldGNoRGF0YSh1cmwsIGNvbXByZXNzaW9uVHlwZSkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGxvYWQgJHt0aGlzLmlzQ29tcHJlc3NlZCA/ICJiaW5hcnkgIiA6ICIifUNNYXAgYXQ6ICR7dXJsfWApOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2ZldGNoRGF0YSh1cmwsIGNvbXByZXNzaW9uVHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBtZXRob2QgYF9mZXRjaERhdGFgIGNhbGxlZC4iKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLkJhc2VDTWFwUmVhZGVyRmFjdG9yeSA9IEJhc2VDTWFwUmVhZGVyRmFjdG9yeTsKICAgICAgICAgICAgICAgIGNsYXNzIEJhc2VTdGFuZGFyZEZvbnREYXRhRmFjdG9yeSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IoX3JlZjMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhc2VVcmwgPSBudWxsCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmMzsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uc3RydWN0b3IgPT09IEJhc2VTdGFuZGFyZEZvbnREYXRhRmFjdG9yeSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQ2Fubm90IGluaXRpYWxpemUgQmFzZVN0YW5kYXJkRm9udERhdGFGYWN0b3J5LiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmFzZVVybCA9IGJhc2VVcmw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFzeW5jIGZldGNoKF9yZWY0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlbmFtZQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5iYXNlVXJsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBzdGFuZGFyZCBmb250ICJiYXNlVXJsIiBwYXJhbWV0ZXIgbXVzdCBiZSBzcGVjaWZpZWQsIGVuc3VyZSB0aGF0ICcgKyAndGhlICJzdGFuZGFyZEZvbnREYXRhVXJsIiBBUEkgcGFyYW1ldGVyIGlzIHByb3ZpZGVkLicpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZmlsZW5hbWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiRm9udCBmaWxlbmFtZSBtdXN0IGJlIHNwZWNpZmllZC4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSBgJHt0aGlzLmJhc2VVcmx9JHtmaWxlbmFtZX1gOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZmV0Y2hEYXRhKHVybCkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5hYmxlIHRvIGxvYWQgZm9udCBkYXRhIGF0OiAke3VybH1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9mZXRjaERhdGEodXJsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIkFic3RyYWN0IG1ldGhvZCBgX2ZldGNoRGF0YWAgY2FsbGVkLiIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuQmFzZVN0YW5kYXJkRm9udERhdGFGYWN0b3J5ID0gQmFzZVN0YW5kYXJkRm9udERhdGFGYWN0b3J5OwogICAgICAgICAgICAgICAgY2xhc3MgQmFzZVNWR0ZhY3RvcnkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25zdHJ1Y3RvciA9PT0gQmFzZVNWR0ZhY3RvcnkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIkNhbm5vdCBpbml0aWFsaXplIEJhc2VTVkdGYWN0b3J5LiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNyZWF0ZSh3aWR0aCwgaGVpZ2h0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBza2lwRGltZW5zaW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3aWR0aCA8PSAwIHx8IGhlaWdodCA8PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgU1ZHIGRpbWVuc2lvbnMiKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdmcgPSB0aGlzLl9jcmVhdGVTVkcoInN2ZzpzdmciKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3ZnLnNldEF0dHJpYnV0ZSgidmVyc2lvbiIsICIxLjEiKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFza2lwRGltZW5zaW9ucykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ZnLnNldEF0dHJpYnV0ZSgid2lkdGgiLCBgJHt3aWR0aH1weGApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ZnLnNldEF0dHJpYnV0ZSgiaGVpZ2h0IiwgYCR7aGVpZ2h0fXB4YCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc3ZnLnNldEF0dHJpYnV0ZSgicHJlc2VydmVBc3BlY3RSYXRpbyIsICJub25lIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHN2Zy5zZXRBdHRyaWJ1dGUoInZpZXdCb3giLCBgMCAwICR7d2lkdGh9ICR7aGVpZ2h0fWApOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3ZnOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjcmVhdGVFbGVtZW50KHR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0eXBlICE9PSAic3RyaW5nIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJJbnZhbGlkIFNWRyBlbGVtZW50IHR5cGUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fY3JlYXRlU1ZHKHR5cGUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfY3JlYXRlU1ZHKHR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQWJzdHJhY3QgbWV0aG9kIGBfY3JlYXRlU1ZHYCBjYWxsZWQuIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5CYXNlU1ZHRmFjdG9yeSA9IEJhc2VTVkdGYWN0b3J5OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxNDQgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCgogICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdHJ1ZQogICAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgICAgZXhwb3J0cy5NdXJtdXJIYXNoM182NCA9IHZvaWQgMDsKICAgICAgICAgICAgICAgIHZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMSk7CiAgICAgICAgICAgICAgICBjb25zdCBTRUVEID0gMHhjM2QyZTFmMDsKICAgICAgICAgICAgICAgIGNvbnN0IE1BU0tfSElHSCA9IDB4ZmZmZjAwMDA7CiAgICAgICAgICAgICAgICBjb25zdCBNQVNLX0xPVyA9IDB4ZmZmZjsKICAgICAgICAgICAgICAgIGNsYXNzIE11cm11ckhhc2gzXzY0IHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihzZWVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaDEgPSBzZWVkID8gc2VlZCAmIDB4ZmZmZmZmZmYgOiBTRUVEOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmgyID0gc2VlZCA/IHNlZWQgJiAweGZmZmZmZmZmIDogU0VFRDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdXBkYXRlKGlucHV0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkYXRhLCBsZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gbmV3IFVpbnQ4QXJyYXkoaW5wdXQubGVuZ3RoICogMik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGggPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gaW5wdXQubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvZGUgPSBpbnB1dC5jaGFyQ29kZUF0KGkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb2RlIDw9IDB4ZmYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVtsZW5ndGgrK10gPSBjb2RlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFbbGVuZ3RoKytdID0gY29kZSA+Pj4gODsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVtsZW5ndGgrK10gPSBjb2RlICYgMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoKDAsIF91dGlsLmlzQXJyYXlCdWZmZXIpKGlucHV0KSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGlucHV0LnNsaWNlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGggPSBkYXRhLmJ5dGVMZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIldyb25nIGRhdGEgZm9ybWF0IGluIE11cm11ckhhc2gzXzY0X3VwZGF0ZS4gIiArICJJbnB1dCBtdXN0IGJlIGEgc3RyaW5nIG9yIGFycmF5LiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJsb2NrQ291bnRzID0gbGVuZ3RoID4+IDI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhaWxMZW5ndGggPSBsZW5ndGggLSBibG9ja0NvdW50cyAqIDQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGFVaW50MzIgPSBuZXcgVWludDMyQXJyYXkoZGF0YS5idWZmZXIsIDAsIGJsb2NrQ291bnRzKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGsxID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsyID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGgxID0gdGhpcy5oMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGgyID0gdGhpcy5oMjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgQzEgPSAweGNjOWUyZDUxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgQzIgPSAweDFiODczNTkzOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBDMV9MT1cgPSBDMSAmIE1BU0tfTE9XLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgQzJfTE9XID0gQzIgJiBNQVNLX0xPVzsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBibG9ja0NvdW50czsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaSAmIDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrMSA9IGRhdGFVaW50MzJbaV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgazEgPSBrMSAqIEMxICYgTUFTS19ISUdIIHwgazEgKiBDMV9MT1cgJiBNQVNLX0xPVzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrMSA9IGsxIDw8IDE1IHwgazEgPj4+IDE3OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsxID0gazEgKiBDMiAmIE1BU0tfSElHSCB8IGsxICogQzJfTE9XICYgTUFTS19MT1c7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaDEgXj0gazE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaDEgPSBoMSA8PCAxMyB8IGgxID4+PiAxOTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoMSA9IGgxICogNSArIDB4ZTY1NDZiNjQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsyID0gZGF0YVVpbnQzMltpXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrMiA9IGsyICogQzEgJiBNQVNLX0hJR0ggfCBrMiAqIEMxX0xPVyAmIE1BU0tfTE9XOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsyID0gazIgPDwgMTUgfCBrMiA+Pj4gMTc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgazIgPSBrMiAqIEMyICYgTUFTS19ISUdIIHwgazIgKiBDMl9MT1cgJiBNQVNLX0xPVzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoMiBePSBrMjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoMiA9IGgyIDw8IDEzIHwgaDIgPj4+IDE5OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGgyID0gaDIgKiA1ICsgMHhlNjU0NmI2NDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBrMSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodGFpbExlbmd0aCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsxIF49IGRhdGFbYmxvY2tDb3VudHMgKiA0ICsgMl0gPDwgMTY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgazEgXj0gZGF0YVtibG9ja0NvdW50cyAqIDQgKyAxXSA8PCA4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsxIF49IGRhdGFbYmxvY2tDb3VudHMgKiA0XTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrMSA9IGsxICogQzEgJiBNQVNLX0hJR0ggfCBrMSAqIEMxX0xPVyAmIE1BU0tfTE9XOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsxID0gazEgPDwgMTUgfCBrMSA+Pj4gMTc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgazEgPSBrMSAqIEMyICYgTUFTS19ISUdIIHwgazEgKiBDMl9MT1cgJiBNQVNLX0xPVzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmxvY2tDb3VudHMgJiAxKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGgxIF49IGsxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGgyIF49IGsxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmgxID0gaDE7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaDIgPSBoMjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaGV4ZGlnZXN0KCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgaDEgPSB0aGlzLmgxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaDIgPSB0aGlzLmgyOwogICAgICAgICAgICAgICAgICAgICAgICBoMSBePSBoMiA+Pj4gMTsKICAgICAgICAgICAgICAgICAgICAgICAgaDEgPSBoMSAqIDB4ZWQ1NThjY2QgJiBNQVNLX0hJR0ggfCBoMSAqIDB4OGNjZCAmIE1BU0tfTE9XOwogICAgICAgICAgICAgICAgICAgICAgICBoMiA9IGgyICogMHhmZjUxYWZkNyAmIE1BU0tfSElHSCB8ICgoaDIgPDwgMTYgfCBoMSA+Pj4gMTYpICogMHhhZmQ3ZWQ1NSAmIE1BU0tfSElHSCkgPj4+IDE2OwogICAgICAgICAgICAgICAgICAgICAgICBoMSBePSBoMiA+Pj4gMTsKICAgICAgICAgICAgICAgICAgICAgICAgaDEgPSBoMSAqIDB4MWE4NWVjNTMgJiBNQVNLX0hJR0ggfCBoMSAqIDB4ZWM1MyAmIE1BU0tfTE9XOwogICAgICAgICAgICAgICAgICAgICAgICBoMiA9IGgyICogMHhjNGNlYjlmZSAmIE1BU0tfSElHSCB8ICgoaDIgPDwgMTYgfCBoMSA+Pj4gMTYpICogMHhiOWZlMWE4NSAmIE1BU0tfSElHSCkgPj4+IDE2OwogICAgICAgICAgICAgICAgICAgICAgICBoMSBePSBoMiA+Pj4gMTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChoMSA+Pj4gMCkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDgsICIwIikgKyAoaDIgPj4+IDApLnRvU3RyaW5nKDE2KS5wYWRTdGFydCg4LCAiMCIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuTXVybXVySGFzaDNfNjQgPSBNdXJtdXJIYXNoM182NDsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTQ1ICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuRm9udExvYWRlciA9IGV4cG9ydHMuRm9udEZhY2VPYmplY3QgPSB2b2lkIDA7CiAgICAgICAgICAgICAgICB2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEpOwogICAgICAgICAgICAgICAgdmFyIF9pc19ub2RlID0gX193X3BkZmpzX3JlcXVpcmVfXygzKTsKICAgICAgICAgICAgICAgIGNsYXNzIEZvbnRMb2FkZXIgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKF9yZWYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG93bmVyRG9jdW1lbnQgPSBnbG9iYWxUaGlzLmRvY3VtZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGVFbGVtZW50ID0gbnVsbAogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9jdW1lbnQgPSBvd25lckRvY3VtZW50OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdGl2ZUZvbnRGYWNlcyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0eWxlRWxlbWVudCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZGluZ1JlcXVlc3RzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZFRlc3RGb250SWQgPSAwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhZGROYXRpdmVGb250RmFjZShuYXRpdmVGb250RmFjZSkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdGl2ZUZvbnRGYWNlcy5wdXNoKG5hdGl2ZUZvbnRGYWNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9jdW1lbnQuZm9udHMuYWRkKG5hdGl2ZUZvbnRGYWNlKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0UnVsZShydWxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5zdHlsZUVsZW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3R5bGVFbGVtZW50ID0gdGhpcy5fZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic3R5bGUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RvY3VtZW50LmRvY3VtZW50RWxlbWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgiaGVhZCIpWzBdLmFwcGVuZCh0aGlzLnN0eWxlRWxlbWVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3R5bGVTaGVldCA9IHRoaXMuc3R5bGVFbGVtZW50LnNoZWV0OwogICAgICAgICAgICAgICAgICAgICAgICBzdHlsZVNoZWV0Lmluc2VydFJ1bGUocnVsZSwgc3R5bGVTaGVldC5jc3NSdWxlcy5sZW5ndGgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjbGVhcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBuYXRpdmVGb250RmFjZSBvZiB0aGlzLm5hdGl2ZUZvbnRGYWNlcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9jdW1lbnQuZm9udHMuZGVsZXRlKG5hdGl2ZUZvbnRGYWNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hdGl2ZUZvbnRGYWNlcy5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zdHlsZUVsZW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3R5bGVFbGVtZW50LnJlbW92ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHlsZUVsZW1lbnQgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFzeW5jIGJpbmQoZm9udCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm9udC5hdHRhY2hlZCB8fCBmb250Lm1pc3NpbmdGaWxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZm9udC5hdHRhY2hlZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzRm9udExvYWRpbmdBUElTdXBwb3J0ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5hdGl2ZUZvbnRGYWNlID0gZm9udC5jcmVhdGVOYXRpdmVGb250RmFjZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5hdGl2ZUZvbnRGYWNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGROYXRpdmVGb250RmFjZShuYXRpdmVGb250RmFjZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgbmF0aXZlRm9udEZhY2UubG9hZGVkOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgRmFpbGVkIHRvIGxvYWQgZm9udCAnJHtuYXRpdmVGb250RmFjZS5mYW1pbHl9JzogJyR7ZXh9Jy5gKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udC5kaXNhYmxlRm9udEZhY2UgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBleDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcnVsZSA9IGZvbnQuY3JlYXRlRm9udEZhY2VSdWxlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChydWxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmluc2VydFJ1bGUocnVsZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5pc1N5bmNGb250TG9hZGluZ1N1cHBvcnRlZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLl9xdWV1ZUxvYWRpbmdDYWxsYmFjayhyZXNvbHZlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wcmVwYXJlRm9udExvYWRFdmVudChmb250LCByZXF1ZXN0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBpc0ZvbnRMb2FkaW5nQVBJU3VwcG9ydGVkKCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkX2RvY3VtZW50OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoYXNGb250cyA9ICEhKChfdGhpcyRfZG9jdW1lbnQgPSB0aGlzLl9kb2N1bWVudCkgIT09IG51bGwgJiYgX3RoaXMkX2RvY3VtZW50ICE9PSB2b2lkIDAgJiYgX3RoaXMkX2RvY3VtZW50LmZvbnRzKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJpc0ZvbnRMb2FkaW5nQVBJU3VwcG9ydGVkIiwgaGFzRm9udHMpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgaXNTeW5jRm9udExvYWRpbmdTdXBwb3J0ZWQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzdXBwb3J0ZWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9pc19ub2RlLmlzTm9kZUpTKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXBwb3J0ZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBuYXZpZ2F0b3IgIT09ICJ1bmRlZmluZWQiICYmIC9Nb3ppbGxhXC81LjAuKj9ydjpcZCsuKj8gR2Vja28vLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cHBvcnRlZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJpc1N5bmNGb250TG9hZGluZ1N1cHBvcnRlZCIsIHN1cHBvcnRlZCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9xdWV1ZUxvYWRpbmdDYWxsYmFjayhjYWxsYmFjaykgewogICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBjb21wbGV0ZVJlcXVlc3QoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwuYXNzZXJ0KSghcmVxdWVzdC5kb25lLCAiY29tcGxldGVSZXF1ZXN0KCkgY2Fubm90IGJlIGNhbGxlZCB0d2ljZS4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3QuZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAobG9hZGluZ1JlcXVlc3RzLmxlbmd0aCA+IDAgJiYgbG9hZGluZ1JlcXVlc3RzWzBdLmRvbmUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvdGhlclJlcXVlc3QgPSBsb2FkaW5nUmVxdWVzdHMuc2hpZnQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KG90aGVyUmVxdWVzdC5jYWxsYmFjaywgMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGluZ1JlcXVlc3RzCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSB0aGlzOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZTogZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wbGV0ZTogY29tcGxldGVSZXF1ZXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGluZ1JlcXVlc3RzLnB1c2gocmVxdWVzdCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXF1ZXN0OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgX2xvYWRUZXN0Rm9udCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGVzdEZvbnQgPSBhdG9iKCJUMVJVVHdBTEFJQUFBd0F3UTBaR0lESHRaZzRBQUFPWUFBQUFnVVpHVkUxbGt6WndBQUFFSEFBQUFCeEhSRVZHQUJRQSIgKyAiRlFBQUJEZ0FBQUFlVDFNdk1sWU5Zd2tBQUFFZ0FBQUFZR050WVhBQkRRTFVBQUFDTkFBQUFVSm9aV0ZrL3hWRkRRQUEiICsgIkFMd0FBQUEyYUdobFlRZGtBK29BQUFEMEFBQUFKR2h0ZEhnRDZBQUFBQUFFV0FBQUFBWnRZWGh3QUFKUUFBQUFBUmdBIiArICJBQUFHYm1GdFpWam1kSDRBQUFHQUFBQUFzWEJ2YzNUL2hnQXpBQUFEZUFBQUFDQUFBUUFBQUFFQUFMWlJGc1JmRHp6MSIgKyAiQUFzRDZBQUFBQURPQk9UTEFBQUFBTTRLSER3QUFBQUFBK2dESVFBQUFBZ0FBZ0FBQUFBQUFBQUJBQUFESVFBQUFGb0QiICsgIjZBQUFBQUFENkFBQkFBQUFBQUFBQUFBQUFBQUFBQUFBQVFBQVVBQUFBZ0FBQUFRRDZBSDBBQVVBQUFLS0Fyd0FBQUNNIiArICJBb29DdkFBQUFlQUFNUUVDQUFBQ0FBWUpBQUFBQUFBQUFBQUFBUUFBQUFBQUFBQUFBQUFBQUZCbVJXUUF3QUF1QUM0RCIgKyAiSVA4NEFGb0RJUUFBQUFBQUFRQUFBQUFBQUFBQUFDQUFJQUFCQUFBQURnQ3VBQUVBQUFBQUFBQUFBUUFBQUFFQUFBQUEiICsgIkFBRUFBUUFBQUFFQUFBQUFBQUlBQVFBQUFBRUFBQUFBQUFNQUFRQUFBQUVBQUFBQUFBUUFBUUFBQUFFQUFBQUFBQVVBIiArICJBUUFBQUFFQUFBQUFBQVlBQVFBQUFBTUFBUVFKQUFBQUFnQUJBQU1BQVFRSkFBRUFBZ0FCQUFNQUFRUUpBQUlBQWdBQiIgKyAiQUFNQUFRUUpBQU1BQWdBQkFBTUFBUVFKQUFRQUFnQUJBQU1BQVFRSkFBVUFBZ0FCQUFNQUFRUUpBQVlBQWdBQldBQlkiICsgIkFBQUFBQUFBQXdBQUFBTUFBQUFjQUFFQUFBQUFBRHdBQXdBQkFBQUFIQUFFQUNBQUFBQUVBQVFBQVFBQUFDNy8vd0FBIiArICJBQzcvLy8vVEFBRUFBQUFBQUFBQkJnQUFBUUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQSIgKyAiQUFBQUFBQUFBQUFBQUFBQUFBRUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEiICsgIkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBIiArICJBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQSIgKyAiQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEiICsgIkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU1BQUFBQUFBRC9nd0F5QUFBQUFRQUFBQUFBQUFBQUFBQUFBQUFBIiArICJBQUFCQUFRRUFBRUJBUUpZQUFFQkFTSDREd0Q0R3dIRUF2Z2NBL2dYQkl3TUFZdUwrbno1dFFYa0Q1ajNDQkxuRVFBQyIgKyAiQVFFQklWaFlXRmhZV0ZoWVdGaFlXRmhZV0ZoWVdGaFlXRmhZV0ZoWVdGaFlXRmhZQUFBQkFRQUFEd0FDQVFFRUUvdDMiICsgIkRvdjZmQUg2ZkFUK2ZQcDgrbndIRG9zTUN2bTFDdm0xREF6NmZCUUFBQUFBQUFBQkFBQUFBTW1KYnpFQUFBQUF6Z1RqIiArICJGUUFBQUFET0JPUXBBQUVBQUFBQUFBQUFEQUFVQUFRQUFBQUJBQUFBQWdBQkFBQUFBQUFBQUFBRDZBQUFBQUFBQUE9PSIpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIl9sb2FkVGVzdEZvbnQiLCB0ZXN0Rm9udCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9wcmVwYXJlRm9udExvYWRFdmVudChmb250LCByZXF1ZXN0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGludDMyKGRhdGEsIG9mZnNldCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRhdGEuY2hhckNvZGVBdChvZmZzZXQpIDw8IDI0IHwgZGF0YS5jaGFyQ29kZUF0KG9mZnNldCArIDEpIDw8IDE2IHwgZGF0YS5jaGFyQ29kZUF0KG9mZnNldCArIDIpIDw8IDggfCBkYXRhLmNoYXJDb2RlQXQob2Zmc2V0ICsgMykgJiAweGZmOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHNwbGljZVN0cmluZyhzLCBvZmZzZXQsIHJlbW92ZSwgaW5zZXJ0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaHVuazEgPSBzLnN1YnN0cmluZygwLCBvZmZzZXQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2h1bmsyID0gcy5zdWJzdHJpbmcob2Zmc2V0ICsgcmVtb3ZlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjaHVuazEgKyBpbnNlcnQgKyBjaHVuazI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGksIGlpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW52YXMgPSB0aGlzLl9kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJjYW52YXMiKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzLndpZHRoID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzLmhlaWdodCA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCIyZCIpOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgY2FsbGVkID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gaXNGb250UmVhZHkobmFtZSwgY2FsbGJhY2spIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgrK2NhbGxlZCA+IDMwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJMb2FkIHRlc3QgZm9udCBuZXZlciBsb2FkZWQuIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguZm9udCA9ICIzMHB4ICIgKyBuYW1lOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmZpbGxUZXh0KCIuIiwgMCwgMjApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW1hZ2VEYXRhID0gY3R4LmdldEltYWdlRGF0YSgwLCAwLCAxLCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbWFnZURhdGEuZGF0YVszXSA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjaygpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoaXNGb250UmVhZHkuYmluZChudWxsLCBuYW1lLCBjYWxsYmFjaykpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxvYWRUZXN0Rm9udElkID0gYGx0JHtEYXRlLm5vdygpfSR7dGhpcy5sb2FkVGVzdEZvbnRJZCsrfWA7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkYXRhID0gdGhpcy5fbG9hZFRlc3RGb250OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBDT01NRU5UX09GRlNFVCA9IDk3NjsKICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHNwbGljZVN0cmluZyhkYXRhLCBDT01NRU5UX09GRlNFVCwgbG9hZFRlc3RGb250SWQubGVuZ3RoLCBsb2FkVGVzdEZvbnRJZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IENGRl9DSEVDS1NVTV9PRkZTRVQgPSAxNjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgWFhYWF9WQUxVRSA9IDB4NTg1ODU4NTg7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjaGVja3N1bSA9IGludDMyKGRhdGEsIENGRl9DSEVDS1NVTV9PRkZTRVQpOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IGxvYWRUZXN0Rm9udElkLmxlbmd0aCAtIDM7IGkgPCBpaTsgaSArPSA0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVja3N1bSA9IGNoZWNrc3VtIC0gWFhYWF9WQUxVRSArIGludDMyKGxvYWRUZXN0Rm9udElkLCBpKSB8IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGkgPCBsb2FkVGVzdEZvbnRJZC5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrc3VtID0gY2hlY2tzdW0gLSBYWFhYX1ZBTFVFICsgaW50MzIobG9hZFRlc3RGb250SWQgKyAiWFhYIiwgaSkgfCAwOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBzcGxpY2VTdHJpbmcoZGF0YSwgQ0ZGX0NIRUNLU1VNX09GRlNFVCwgNCwgKDAsIF91dGlsLnN0cmluZzMyKShjaGVja3N1bSkpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSBgdXJsKGRhdGE6Zm9udC9vcGVudHlwZTtiYXNlNjQsJHtidG9hKGRhdGEpfSk7YDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcnVsZSA9IGBAZm9udC1mYWNlIHtmb250LWZhbWlseToiJHtsb2FkVGVzdEZvbnRJZH0iO3NyYzoke3VybH19YDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbnNlcnRSdWxlKHJ1bGUpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaXYgPSB0aGlzLl9kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYiKTsKICAgICAgICAgICAgICAgICAgICAgICAgZGl2LnN0eWxlLnZpc2liaWxpdHkgPSAiaGlkZGVuIjsKICAgICAgICAgICAgICAgICAgICAgICAgZGl2LnN0eWxlLndpZHRoID0gZGl2LnN0eWxlLmhlaWdodCA9ICIxMHB4IjsKICAgICAgICAgICAgICAgICAgICAgICAgZGl2LnN0eWxlLnBvc2l0aW9uID0gImFic29sdXRlIjsKICAgICAgICAgICAgICAgICAgICAgICAgZGl2LnN0eWxlLnRvcCA9IGRpdi5zdHlsZS5sZWZ0ID0gIjBweCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBbZm9udC5sb2FkZWROYW1lLCBsb2FkVGVzdEZvbnRJZF0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNwYW4gPSB0aGlzLl9kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJzcGFuIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGFuLnRleHRDb250ZW50ID0gIkhpIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwYW4uc3R5bGUuZm9udEZhbWlseSA9IG5hbWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXYuYXBwZW5kKHNwYW4pOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RvY3VtZW50LmJvZHkuYXBwZW5kKGRpdik7CiAgICAgICAgICAgICAgICAgICAgICAgIGlzRm9udFJlYWR5KGxvYWRUZXN0Rm9udElkLCAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXYucmVtb3ZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0LmNvbXBsZXRlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuRm9udExvYWRlciA9IEZvbnRMb2FkZXI7CiAgICAgICAgICAgICAgICBjbGFzcyBGb250RmFjZU9iamVjdCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IodHJhbnNsYXRlZERhdGEsIF9yZWYyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0V2YWxTdXBwb3J0ZWQgPSB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZUZvbnRGYWNlID0gZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmVFcnJvcnMgPSBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc3BlY3RGb250ID0gbnVsbAogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjI7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcGlsZWRHbHlwaHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGkgaW4gdHJhbnNsYXRlZERhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNbaV0gPSB0cmFuc2xhdGVkRGF0YVtpXTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzRXZhbFN1cHBvcnRlZCA9IGlzRXZhbFN1cHBvcnRlZCAhPT0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzYWJsZUZvbnRGYWNlID0gZGlzYWJsZUZvbnRGYWNlID09PSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlnbm9yZUVycm9ycyA9IGlnbm9yZUVycm9ycyA9PT0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faW5zcGVjdEZvbnQgPSBpbnNwZWN0Rm9udDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY3JlYXRlTmF0aXZlRm9udEZhY2UoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRfaW5zcGVjdEZvbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5kYXRhIHx8IHRoaXMuZGlzYWJsZUZvbnRGYWNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBsZXQgbmF0aXZlRm9udEZhY2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jc3NGb250SW5mbykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmF0aXZlRm9udEZhY2UgPSBuZXcgRm9udEZhY2UodGhpcy5sb2FkZWROYW1lLCB0aGlzLmRhdGEsIHt9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNzcyA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3ZWlnaHQ6IHRoaXMuY3NzRm9udEluZm8uZm9udFdlaWdodAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmNzc0ZvbnRJbmZvLml0YWxpY0FuZ2xlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3NzLnN0eWxlID0gYG9ibGlxdWUgJHt0aGlzLmNzc0ZvbnRJbmZvLml0YWxpY0FuZ2xlfWRlZ2A7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYXRpdmVGb250RmFjZSA9IG5ldyBGb250RmFjZSh0aGlzLmNzc0ZvbnRJbmZvLmZvbnRGYW1pbHksIHRoaXMuZGF0YSwgY3NzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkX2luc3BlY3RGb250ID0gdGhpcy5faW5zcGVjdEZvbnQpID09PSBudWxsIHx8IF90aGlzJF9pbnNwZWN0Rm9udCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkX2luc3BlY3RGb250LmNhbGwodGhpcywgdGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVGb250RmFjZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY3JlYXRlRm9udEZhY2VSdWxlKCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkX2luc3BlY3RGb250MjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmRhdGEgfHwgdGhpcy5kaXNhYmxlRm9udEZhY2UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSAoMCwgX3V0aWwuYnl0ZXNUb1N0cmluZykodGhpcy5kYXRhKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdXJsID0gYHVybChkYXRhOiR7dGhpcy5taW1ldHlwZX07YmFzZTY0LCR7YnRvYShkYXRhKX0pO2A7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBydWxlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY3NzRm9udEluZm8pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bGUgPSBgQGZvbnQtZmFjZSB7Zm9udC1mYW1pbHk6IiR7dGhpcy5sb2FkZWROYW1lfSI7c3JjOiR7dXJsfX1gOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNzcyA9IGBmb250LXdlaWdodDogJHt0aGlzLmNzc0ZvbnRJbmZvLmZvbnRXZWlnaHR9O2A7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jc3NGb250SW5mby5pdGFsaWNBbmdsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNzcyArPSBgZm9udC1zdHlsZTogb2JsaXF1ZSAke3RoaXMuY3NzRm9udEluZm8uaXRhbGljQW5nbGV9ZGVnO2A7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBydWxlID0gYEBmb250LWZhY2Uge2ZvbnQtZmFtaWx5OiIke3RoaXMuY3NzRm9udEluZm8uZm9udEZhbWlseX0iOyR7Y3NzfXNyYzoke3VybH19YDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkX2luc3BlY3RGb250MiA9IHRoaXMuX2luc3BlY3RGb250KSA9PT0gbnVsbCB8fCBfdGhpcyRfaW5zcGVjdEZvbnQyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRfaW5zcGVjdEZvbnQyLmNhbGwodGhpcywgdGhpcywgdXJsKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJ1bGU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldFBhdGhHZW5lcmF0b3Iob2JqcywgY2hhcmFjdGVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbXBpbGVkR2x5cGhzW2NoYXJhY3Rlcl0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29tcGlsZWRHbHlwaHNbY2hhcmFjdGVyXTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBsZXQgY21kczsKICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtZHMgPSBvYmpzLmdldCh0aGlzLmxvYWRlZE5hbWUgKyAiX3BhdGhfIiArIGNoYXJhY3Rlcik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYGdldFBhdGhHZW5lcmF0b3IgLSBpZ25vcmluZyBjaGFyYWN0ZXI6ICIke2V4fSIuYCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb21waWxlZEdseXBoc1tjaGFyYWN0ZXJdID0gZnVuY3Rpb24gKGMsIHNpemUpIHt9OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzRXZhbFN1cHBvcnRlZCAmJiBfdXRpbC5GZWF0dXJlVGVzdC5pc0V2YWxTdXBwb3J0ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGpzQnVmID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGN1cnJlbnQgb2YgY21kcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFyZ3MgPSBjdXJyZW50LmFyZ3MgIT09IHVuZGVmaW5lZCA/IGN1cnJlbnQuYXJncy5qb2luKCIsIikgOiAiIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqc0J1Zi5wdXNoKCJjLiIsIGN1cnJlbnQuY21kLCAiKCIsIGFyZ3MsICIpO1xuIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb21waWxlZEdseXBoc1tjaGFyYWN0ZXJdID0gbmV3IEZ1bmN0aW9uKCJjIiwgInNpemUiLCBqc0J1Zi5qb2luKCIiKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29tcGlsZWRHbHlwaHNbY2hhcmFjdGVyXSA9IGZ1bmN0aW9uIChjLCBzaXplKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGN1cnJlbnQgb2YgY21kcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50LmNtZCA9PT0gInNjYWxlIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LmFyZ3MgPSBbc2l6ZSwgLXNpemVdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjW2N1cnJlbnQuY21kXS5hcHBseShjLCBjdXJyZW50LmFyZ3MpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuRm9udEZhY2VPYmplY3QgPSBGb250RmFjZU9iamVjdDsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTQ2ICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuQ2FudmFzR3JhcGhpY3MgPSB2b2lkIDA7CiAgICAgICAgICAgICAgICB2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEpOwogICAgICAgICAgICAgICAgdmFyIF9kaXNwbGF5X3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDIpOwogICAgICAgICAgICAgICAgdmFyIF9wYXR0ZXJuX2hlbHBlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQ3KTsKICAgICAgICAgICAgICAgIHZhciBfaW1hZ2VfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0OCk7CiAgICAgICAgICAgICAgICB2YXIgX2lzX25vZGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDMpOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKG9iaiwgcHJpdmF0ZVNldCkgeyBfY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbihvYmosIHByaXZhdGVTZXQpOyBwcml2YXRlU2V0LmFkZChvYmopOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbihvYmosIHByaXZhdGVDb2xsZWN0aW9uKSB7IGlmIChwcml2YXRlQ29sbGVjdGlvbi5oYXMob2JqKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgaW5pdGlhbGl6ZSB0aGUgc2FtZSBwcml2YXRlIGVsZW1lbnRzIHR3aWNlIG9uIGFuIG9iamVjdCIpOyB9IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQocmVjZWl2ZXIsIHByaXZhdGVTZXQsIGZuKSB7IGlmICghcHJpdmF0ZVNldC5oYXMocmVjZWl2ZXIpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoImF0dGVtcHRlZCB0byBnZXQgcHJpdmF0ZSBmaWVsZCBvbiBub24taW5zdGFuY2UiKTsgfSByZXR1cm4gZm47IH0KICAgICAgICAgICAgICAgIGNvbnN0IE1JTl9GT05UX1NJWkUgPSAxNjsKICAgICAgICAgICAgICAgIGNvbnN0IE1BWF9GT05UX1NJWkUgPSAxMDA7CiAgICAgICAgICAgICAgICBjb25zdCBNQVhfR1JPVVBfU0laRSA9IDQwOTY7CiAgICAgICAgICAgICAgICBjb25zdCBFWEVDVVRJT05fVElNRSA9IDE1OwogICAgICAgICAgICAgICAgY29uc3QgRVhFQ1VUSU9OX1NURVBTID0gMTA7CiAgICAgICAgICAgICAgICBjb25zdCBNQVhfU0laRV9UT19DT01QSUxFID0gMTAwMDsKICAgICAgICAgICAgICAgIGNvbnN0IEZVTExfQ0hVTktfSEVJR0hUID0gMTY7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBtaXJyb3JDb250ZXh0T3BlcmF0aW9ucyhjdHgsIGRlc3RDdHgpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoY3R4Ll9yZW1vdmVNaXJyb3JpbmcpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJDb250ZXh0IGlzIGFscmVhZHkgZm9yd2FyZGluZyBvcGVyYXRpb25zLiIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjdHguX19vcmlnaW5hbFNhdmUgPSBjdHguc2F2ZTsKICAgICAgICAgICAgICAgICAgICBjdHguX19vcmlnaW5hbFJlc3RvcmUgPSBjdHgucmVzdG9yZTsKICAgICAgICAgICAgICAgICAgICBjdHguX19vcmlnaW5hbFJvdGF0ZSA9IGN0eC5yb3RhdGU7CiAgICAgICAgICAgICAgICAgICAgY3R4Ll9fb3JpZ2luYWxTY2FsZSA9IGN0eC5zY2FsZTsKICAgICAgICAgICAgICAgICAgICBjdHguX19vcmlnaW5hbFRyYW5zbGF0ZSA9IGN0eC50cmFuc2xhdGU7CiAgICAgICAgICAgICAgICAgICAgY3R4Ll9fb3JpZ2luYWxUcmFuc2Zvcm0gPSBjdHgudHJhbnNmb3JtOwogICAgICAgICAgICAgICAgICAgIGN0eC5fX29yaWdpbmFsU2V0VHJhbnNmb3JtID0gY3R4LnNldFRyYW5zZm9ybTsKICAgICAgICAgICAgICAgICAgICBjdHguX19vcmlnaW5hbFJlc2V0VHJhbnNmb3JtID0gY3R4LnJlc2V0VHJhbnNmb3JtOwogICAgICAgICAgICAgICAgICAgIGN0eC5fX29yaWdpbmFsQ2xpcCA9IGN0eC5jbGlwOwogICAgICAgICAgICAgICAgICAgIGN0eC5fX29yaWdpbmFsTW92ZVRvID0gY3R4Lm1vdmVUbzsKICAgICAgICAgICAgICAgICAgICBjdHguX19vcmlnaW5hbExpbmVUbyA9IGN0eC5saW5lVG87CiAgICAgICAgICAgICAgICAgICAgY3R4Ll9fb3JpZ2luYWxCZXppZXJDdXJ2ZVRvID0gY3R4LmJlemllckN1cnZlVG87CiAgICAgICAgICAgICAgICAgICAgY3R4Ll9fb3JpZ2luYWxSZWN0ID0gY3R4LnJlY3Q7CiAgICAgICAgICAgICAgICAgICAgY3R4Ll9fb3JpZ2luYWxDbG9zZVBhdGggPSBjdHguY2xvc2VQYXRoOwogICAgICAgICAgICAgICAgICAgIGN0eC5fX29yaWdpbmFsQmVnaW5QYXRoID0gY3R4LmJlZ2luUGF0aDsKICAgICAgICAgICAgICAgICAgICBjdHguX3JlbW92ZU1pcnJvcmluZyA9ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnNhdmUgPSBjdHguX19vcmlnaW5hbFNhdmU7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5yZXN0b3JlID0gY3R4Ll9fb3JpZ2luYWxSZXN0b3JlOwogICAgICAgICAgICAgICAgICAgICAgICBjdHgucm90YXRlID0gY3R4Ll9fb3JpZ2luYWxSb3RhdGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zY2FsZSA9IGN0eC5fX29yaWdpbmFsU2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC50cmFuc2xhdGUgPSBjdHguX19vcmlnaW5hbFRyYW5zbGF0ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnRyYW5zZm9ybSA9IGN0eC5fX29yaWdpbmFsVHJhbnNmb3JtOwogICAgICAgICAgICAgICAgICAgICAgICBjdHguc2V0VHJhbnNmb3JtID0gY3R4Ll9fb3JpZ2luYWxTZXRUcmFuc2Zvcm07CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5yZXNldFRyYW5zZm9ybSA9IGN0eC5fX29yaWdpbmFsUmVzZXRUcmFuc2Zvcm07CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5jbGlwID0gY3R4Ll9fb3JpZ2luYWxDbGlwOwogICAgICAgICAgICAgICAgICAgICAgICBjdHgubW92ZVRvID0gY3R4Ll9fb3JpZ2luYWxNb3ZlVG87CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5saW5lVG8gPSBjdHguX19vcmlnaW5hbExpbmVUbzsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmJlemllckN1cnZlVG8gPSBjdHguX19vcmlnaW5hbEJlemllckN1cnZlVG87CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5yZWN0ID0gY3R4Ll9fb3JpZ2luYWxSZWN0OwogICAgICAgICAgICAgICAgICAgICAgICBjdHguY2xvc2VQYXRoID0gY3R4Ll9fb3JpZ2luYWxDbG9zZVBhdGg7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5iZWdpblBhdGggPSBjdHguX19vcmlnaW5hbEJlZ2luUGF0aDsKICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGN0eC5fcmVtb3ZlTWlycm9yaW5nOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgY3R4LnNhdmUgPSBmdW5jdGlvbiBjdHhTYXZlKCkgewogICAgICAgICAgICAgICAgICAgICAgICBkZXN0Q3R4LnNhdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fX29yaWdpbmFsU2F2ZSgpOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgY3R4LnJlc3RvcmUgPSBmdW5jdGlvbiBjdHhSZXN0b3JlKCkgewogICAgICAgICAgICAgICAgICAgICAgICBkZXN0Q3R4LnJlc3RvcmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fX29yaWdpbmFsUmVzdG9yZSgpOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgY3R4LnRyYW5zbGF0ZSA9IGZ1bmN0aW9uIGN0eFRyYW5zbGF0ZSh4LCB5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RDdHgudHJhbnNsYXRlKHgsIHkpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fb3JpZ2luYWxUcmFuc2xhdGUoeCwgeSk7CiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICBjdHguc2NhbGUgPSBmdW5jdGlvbiBjdHhTY2FsZSh4LCB5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RDdHguc2NhbGUoeCwgeSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX19vcmlnaW5hbFNjYWxlKHgsIHkpOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgY3R4LnRyYW5zZm9ybSA9IGZ1bmN0aW9uIGN0eFRyYW5zZm9ybShhLCBiLCBjLCBkLCBlLCBmKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RDdHgudHJhbnNmb3JtKGEsIGIsIGMsIGQsIGUsIGYpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fb3JpZ2luYWxUcmFuc2Zvcm0oYSwgYiwgYywgZCwgZSwgZik7CiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICBjdHguc2V0VHJhbnNmb3JtID0gZnVuY3Rpb24gY3R4U2V0VHJhbnNmb3JtKGEsIGIsIGMsIGQsIGUsIGYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZGVzdEN0eC5zZXRUcmFuc2Zvcm0oYSwgYiwgYywgZCwgZSwgZik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX19vcmlnaW5hbFNldFRyYW5zZm9ybShhLCBiLCBjLCBkLCBlLCBmKTsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGN0eC5yZXNldFRyYW5zZm9ybSA9IGZ1bmN0aW9uIGN0eFJlc2V0VHJhbnNmb3JtKCkgewogICAgICAgICAgICAgICAgICAgICAgICBkZXN0Q3R4LnJlc2V0VHJhbnNmb3JtKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX19vcmlnaW5hbFJlc2V0VHJhbnNmb3JtKCk7CiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICBjdHgucm90YXRlID0gZnVuY3Rpb24gY3R4Um90YXRlKGFuZ2xlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RDdHgucm90YXRlKGFuZ2xlKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fX29yaWdpbmFsUm90YXRlKGFuZ2xlKTsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGN0eC5jbGlwID0gZnVuY3Rpb24gY3R4Um90YXRlKHJ1bGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZGVzdEN0eC5jbGlwKHJ1bGUpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fb3JpZ2luYWxDbGlwKHJ1bGUpOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgY3R4Lm1vdmVUbyA9IGZ1bmN0aW9uICh4LCB5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RDdHgubW92ZVRvKHgsIHkpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fb3JpZ2luYWxNb3ZlVG8oeCwgeSk7CiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICBjdHgubGluZVRvID0gZnVuY3Rpb24gKHgsIHkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZGVzdEN0eC5saW5lVG8oeCwgeSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX19vcmlnaW5hbExpbmVUbyh4LCB5KTsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGN0eC5iZXppZXJDdXJ2ZVRvID0gZnVuY3Rpb24gKGNwMXgsIGNwMXksIGNwMngsIGNwMnksIHgsIHkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZGVzdEN0eC5iZXppZXJDdXJ2ZVRvKGNwMXgsIGNwMXksIGNwMngsIGNwMnksIHgsIHkpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fb3JpZ2luYWxCZXppZXJDdXJ2ZVRvKGNwMXgsIGNwMXksIGNwMngsIGNwMnksIHgsIHkpOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgY3R4LnJlY3QgPSBmdW5jdGlvbiAoeCwgeSwgd2lkdGgsIGhlaWdodCkgewogICAgICAgICAgICAgICAgICAgICAgICBkZXN0Q3R4LnJlY3QoeCwgeSwgd2lkdGgsIGhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX19vcmlnaW5hbFJlY3QoeCwgeSwgd2lkdGgsIGhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICBjdHguY2xvc2VQYXRoID0gZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgICAgICBkZXN0Q3R4LmNsb3NlUGF0aCgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9fb3JpZ2luYWxDbG9zZVBhdGgoKTsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGN0eC5iZWdpblBhdGggPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RDdHguYmVnaW5QYXRoKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX19vcmlnaW5hbEJlZ2luUGF0aCgpOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBDYWNoZWRDYW52YXNlcyB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IoY2FudmFzRmFjdG9yeSkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbnZhc0ZhY3RvcnkgPSBjYW52YXNGYWN0b3J5OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0Q2FudmFzKGlkLCB3aWR0aCwgaGVpZ2h0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjYW52YXNFbnRyeTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY2FjaGVbaWRdICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhc0VudHJ5ID0gdGhpcy5jYWNoZVtpZF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbnZhc0ZhY3RvcnkucmVzZXQoY2FudmFzRW50cnksIHdpZHRoLCBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzRW50cnkgPSB0aGlzLmNhbnZhc0ZhY3RvcnkuY3JlYXRlKHdpZHRoLCBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYWNoZVtpZF0gPSBjYW52YXNFbnRyeTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FudmFzRW50cnk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRlbGV0ZShpZCkgewogICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5jYWNoZVtpZF07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNsZWFyKCkgewogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGlkIGluIHRoaXMuY2FjaGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbnZhc0VudHJ5ID0gdGhpcy5jYWNoZVtpZF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbnZhc0ZhY3RvcnkuZGVzdHJveShjYW52YXNFbnRyeSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5jYWNoZVtpZF07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBkcmF3SW1hZ2VBdEludGVnZXJDb29yZHMoY3R4LCBzcmNJbWcsIHNyY1gsIHNyY1ksIHNyY1csIHNyY0gsIGRlc3RYLCBkZXN0WSwgZGVzdFcsIGRlc3RIKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgW2EsIGIsIGMsIGQsIHR4LCB0eV0gPSAoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybSkoY3R4KTsKICAgICAgICAgICAgICAgICAgICBpZiAoYiA9PT0gMCAmJiBjID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRsWCA9IGRlc3RYICogYSArIHR4OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByVGxYID0gTWF0aC5yb3VuZCh0bFgpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0bFkgPSBkZXN0WSAqIGQgKyB0eTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgclRsWSA9IE1hdGgucm91bmQodGxZKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYnJYID0gKGRlc3RYICsgZGVzdFcpICogYSArIHR4OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByV2lkdGggPSBNYXRoLmFicyhNYXRoLnJvdW5kKGJyWCkgLSByVGxYKSB8fCAxOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBiclkgPSAoZGVzdFkgKyBkZXN0SCkgKiBkICsgdHk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJIZWlnaHQgPSBNYXRoLmFicyhNYXRoLnJvdW5kKGJyWSkgLSByVGxZKSB8fCAxOwogICAgICAgICAgICAgICAgICAgICAgICBjdHguc2V0VHJhbnNmb3JtKE1hdGguc2lnbihhKSwgMCwgMCwgTWF0aC5zaWduKGQpLCByVGxYLCByVGxZKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmRyYXdJbWFnZShzcmNJbWcsIHNyY1gsIHNyY1ksIHNyY1csIHNyY0gsIDAsIDAsIHJXaWR0aCwgckhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zZXRUcmFuc2Zvcm0oYSwgYiwgYywgZCwgdHgsIHR5KTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtyV2lkdGgsIHJIZWlnaHRdOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoYSA9PT0gMCAmJiBkID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRsWCA9IGRlc3RZICogYyArIHR4OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByVGxYID0gTWF0aC5yb3VuZCh0bFgpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0bFkgPSBkZXN0WCAqIGIgKyB0eTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgclRsWSA9IE1hdGgucm91bmQodGxZKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYnJYID0gKGRlc3RZICsgZGVzdEgpICogYyArIHR4OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByV2lkdGggPSBNYXRoLmFicyhNYXRoLnJvdW5kKGJyWCkgLSByVGxYKSB8fCAxOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBiclkgPSAoZGVzdFggKyBkZXN0VykgKiBiICsgdHk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJIZWlnaHQgPSBNYXRoLmFicyhNYXRoLnJvdW5kKGJyWSkgLSByVGxZKSB8fCAxOwogICAgICAgICAgICAgICAgICAgICAgICBjdHguc2V0VHJhbnNmb3JtKDAsIE1hdGguc2lnbihiKSwgTWF0aC5zaWduKGMpLCAwLCByVGxYLCByVGxZKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmRyYXdJbWFnZShzcmNJbWcsIHNyY1gsIHNyY1ksIHNyY1csIHNyY0gsIDAsIDAsIHJIZWlnaHQsIHJXaWR0aCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zZXRUcmFuc2Zvcm0oYSwgYiwgYywgZCwgdHgsIHR5KTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtySGVpZ2h0LCByV2lkdGhdOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjdHguZHJhd0ltYWdlKHNyY0ltZywgc3JjWCwgc3JjWSwgc3JjVywgc3JjSCwgZGVzdFgsIGRlc3RZLCBkZXN0VywgZGVzdEgpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHNjYWxlWCA9IE1hdGguaHlwb3QoYSwgYik7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2NhbGVZID0gTWF0aC5oeXBvdChjLCBkKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gW3NjYWxlWCAqIGRlc3RXLCBzY2FsZVkgKiBkZXN0SF07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBjb21waWxlVHlwZTNHbHlwaChpbWdEYXRhKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCwKICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0CiAgICAgICAgICAgICAgICAgICAgfSA9IGltZ0RhdGE7CiAgICAgICAgICAgICAgICAgICAgaWYgKHdpZHRoID4gTUFYX1NJWkVfVE9fQ09NUElMRSB8fCBoZWlnaHQgPiBNQVhfU0laRV9UT19DT01QSUxFKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBQT0lOVF9UT19QUk9DRVNTX0xJTUlUID0gMTAwMDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBQT0lOVF9UWVBFUyA9IG5ldyBVaW50OEFycmF5KFswLCAyLCA0LCAwLCAxLCAwLCA1LCA0LCA4LCAxMCwgMCwgOCwgMCwgMiwgMSwgMF0pOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoMSA9IHdpZHRoICsgMTsKICAgICAgICAgICAgICAgICAgICBsZXQgcG9pbnRzID0gbmV3IFVpbnQ4QXJyYXkod2lkdGgxICogKGhlaWdodCArIDEpKTsKICAgICAgICAgICAgICAgICAgICBsZXQgaSwgaiwgajA7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGluZVNpemUgPSB3aWR0aCArIDcgJiB+NzsKICAgICAgICAgICAgICAgICAgICBsZXQgZGF0YSA9IG5ldyBVaW50OEFycmF5KGxpbmVTaXplICogaGVpZ2h0KSwKICAgICAgICAgICAgICAgICAgICAgICAgcG9zID0gMDsKICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVsZW0gb2YgaW1nRGF0YS5kYXRhKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtYXNrID0gMTI4OwogICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWFzayA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFbcG9zKytdID0gZWxlbSAmIG1hc2sgPyAwIDogMjU1OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFzayA+Pj0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBsZXQgY291bnQgPSAwOwogICAgICAgICAgICAgICAgICAgIHBvcyA9IDA7CiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFbcG9zXSAhPT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICBwb2ludHNbMF0gPSAxOwogICAgICAgICAgICAgICAgICAgICAgICArK2NvdW50OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmb3IgKGogPSAxOyBqIDwgd2lkdGg7IGorKykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YVtwb3NdICE9PSBkYXRhW3BvcyArIDFdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludHNbal0gPSBkYXRhW3Bvc10gPyAyIDogMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICsrY291bnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcG9zKys7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChkYXRhW3Bvc10gIT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRzW2pdID0gMjsKICAgICAgICAgICAgICAgICAgICAgICAgKytjb3VudDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8IGhlaWdodDsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHBvcyA9IGkgKiBsaW5lU2l6ZTsKICAgICAgICAgICAgICAgICAgICAgICAgajAgPSBpICogd2lkdGgxOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YVtwb3MgLSBsaW5lU2l6ZV0gIT09IGRhdGFbcG9zXSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRzW2owXSA9IGRhdGFbcG9zXSA/IDEgOiA4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgKytjb3VudDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3VtID0gKGRhdGFbcG9zXSA/IDQgOiAwKSArIChkYXRhW3BvcyAtIGxpbmVTaXplXSA/IDggOiAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChqID0gMTsgaiA8IHdpZHRoOyBqKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bSA9IChzdW0gPj4gMikgKyAoZGF0YVtwb3MgKyAxXSA/IDQgOiAwKSArIChkYXRhW3BvcyAtIGxpbmVTaXplICsgMV0gPyA4IDogMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoUE9JTlRfVFlQRVNbc3VtXSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50c1tqMCArIGpdID0gUE9JTlRfVFlQRVNbc3VtXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICArK2NvdW50OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zKys7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFbcG9zIC0gbGluZVNpemVdICE9PSBkYXRhW3Bvc10pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50c1tqMCArIGpdID0gZGF0YVtwb3NdID8gMiA6IDQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICArK2NvdW50OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb3VudCA+IFBPSU5UX1RPX1BST0NFU1NfTElNSVQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHBvcyA9IGxpbmVTaXplICogKGhlaWdodCAtIDEpOwogICAgICAgICAgICAgICAgICAgIGowID0gaSAqIHdpZHRoMTsKICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YVtwb3NdICE9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50c1tqMF0gPSA4OwogICAgICAgICAgICAgICAgICAgICAgICArK2NvdW50OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmb3IgKGogPSAxOyBqIDwgd2lkdGg7IGorKykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YVtwb3NdICE9PSBkYXRhW3BvcyArIDFdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludHNbajAgKyBqXSA9IGRhdGFbcG9zXSA/IDQgOiA4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgKytjb3VudDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBwb3MrKzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFbcG9zXSAhPT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICBwb2ludHNbajAgKyBqXSA9IDQ7CiAgICAgICAgICAgICAgICAgICAgICAgICsrY291bnQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChjb3VudCA+IFBPSU5UX1RPX1BST0NFU1NfTElNSVQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0ZXBzID0gbmV3IEludDMyQXJyYXkoWzAsIHdpZHRoMSwgLTEsIDAsIC13aWR0aDEsIDAsIDAsIDAsIDFdKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXRoID0gbmV3IFBhdGgyRCgpOwogICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGNvdW50ICYmIGkgPD0gaGVpZ2h0OyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHAgPSBpICogd2lkdGgxOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlbmQgPSBwICsgd2lkdGg7CiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChwIDwgZW5kICYmICFwb2ludHNbcF0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHArKzsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAocCA9PT0gZW5kKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBwYXRoLm1vdmVUbyhwICUgd2lkdGgxLCBpKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcDAgPSBwOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgdHlwZSA9IHBvaW50c1twXTsKICAgICAgICAgICAgICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RlcCA9IHN0ZXBzW3R5cGVdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAgKz0gc3RlcDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gd2hpbGUgKCFwb2ludHNbcF0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcHAgPSBwb2ludHNbcF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHAgIT09IDUgJiYgcHAgIT09IDEwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50c1twXSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwcCAmIDB4MzMgKiB0eXBlID4+IDQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRzW3BdICY9IHR5cGUgPj4gMiB8IHR5cGUgPDwgMjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGgubGluZVRvKHAgJSB3aWR0aDEsIHAgLyB3aWR0aDEgfCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghcG9pbnRzW3BdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLS1jb3VudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSB3aGlsZSAocDAgIT09IHApOwogICAgICAgICAgICAgICAgICAgICAgICAtLWk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIHBvaW50cyA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZHJhd091dGxpbmUgPSBmdW5jdGlvbiAoYykgewogICAgICAgICAgICAgICAgICAgICAgICBjLnNhdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgYy5zY2FsZSgxIC8gd2lkdGgsIC0xIC8gaGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgYy50cmFuc2xhdGUoMCwgLWhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGMuZmlsbChwYXRoKTsKICAgICAgICAgICAgICAgICAgICAgICAgYy5iZWdpblBhdGgoKTsKICAgICAgICAgICAgICAgICAgICAgICAgYy5yZXN0b3JlKCk7CiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZHJhd091dGxpbmU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBDYW52YXNFeHRyYVN0YXRlIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3Rvcih3aWR0aCwgaGVpZ2h0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWxwaGFJc1NoYXBlID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZm9udFNpemUgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZvbnRTaXplU2NhbGUgPSAxOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRleHRNYXRyaXggPSBfdXRpbC5JREVOVElUWV9NQVRSSVg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGV4dE1hdHJpeFNjYWxlID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mb250TWF0cml4ID0gX3V0aWwuRk9OVF9JREVOVElUWV9NQVRSSVg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGVhZGluZyA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMueCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMueSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGluZVggPSAwOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxpbmVZID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jaGFyU3BhY2luZyA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud29yZFNwYWNpbmcgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRleHRIU2NhbGUgPSAxOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRleHRSZW5kZXJpbmdNb2RlID0gX3V0aWwuVGV4dFJlbmRlcmluZ01vZGUuRklMTDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXh0UmlzZSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsbENvbG9yID0gIiMwMDAwMDAiOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cm9rZUNvbG9yID0gIiMwMDAwMDAiOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhdHRlcm5GaWxsID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsbEFscGhhID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJva2VBbHBoYSA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGluZVdpZHRoID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVTTWFzayA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJhbnNmZXJNYXBzID0gIm5vbmUiOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0TmV3UGF0aEFuZENsaXBCb3goWzAsIDAsIHdpZHRoLCBoZWlnaHRdKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2xvbmUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNsb25lID0gT2JqZWN0LmNyZWF0ZSh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmUuY2xpcEJveCA9IHRoaXMuY2xpcEJveC5zbGljZSgpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2xvbmU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldEN1cnJlbnRQb2ludCh4LCB5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMueCA9IHg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMueSA9IHk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHVwZGF0ZVBhdGhNaW5NYXgodHJhbnNmb3JtLCB4LCB5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIFt4LCB5XSA9IF91dGlsLlV0aWwuYXBwbHlUcmFuc2Zvcm0oW3gsIHldLCB0cmFuc2Zvcm0pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1pblggPSBNYXRoLm1pbih0aGlzLm1pblgsIHgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1pblkgPSBNYXRoLm1pbih0aGlzLm1pblksIHkpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1heFggPSBNYXRoLm1heCh0aGlzLm1heFgsIHgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1heFkgPSBNYXRoLm1heCh0aGlzLm1heFksIHkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB1cGRhdGVSZWN0TWluTWF4KHRyYW5zZm9ybSwgcmVjdCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwMSA9IF91dGlsLlV0aWwuYXBwbHlUcmFuc2Zvcm0ocmVjdCwgdHJhbnNmb3JtKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcDIgPSBfdXRpbC5VdGlsLmFwcGx5VHJhbnNmb3JtKHJlY3Quc2xpY2UoMiksIHRyYW5zZm9ybSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWluWCA9IE1hdGgubWluKHRoaXMubWluWCwgcDFbMF0sIHAyWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5taW5ZID0gTWF0aC5taW4odGhpcy5taW5ZLCBwMVsxXSwgcDJbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1heFggPSBNYXRoLm1heCh0aGlzLm1heFgsIHAxWzBdLCBwMlswXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWF4WSA9IE1hdGgubWF4KHRoaXMubWF4WSwgcDFbMV0sIHAyWzFdKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdXBkYXRlU2NhbGluZ1BhdGhNaW5NYXgodHJhbnNmb3JtLCBtaW5NYXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX3V0aWwuVXRpbC5zY2FsZU1pbk1heCh0cmFuc2Zvcm0sIG1pbk1heCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWluWCA9IE1hdGgubWluKHRoaXMubWluWCwgbWluTWF4WzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXhYID0gTWF0aC5tYXgodGhpcy5tYXhYLCBtaW5NYXhbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1pblkgPSBNYXRoLm1pbih0aGlzLm1pblksIG1pbk1heFsyXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWF4WSA9IE1hdGgubWF4KHRoaXMubWF4WSwgbWluTWF4WzNdKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdXBkYXRlQ3VydmVQYXRoTWluTWF4KHRyYW5zZm9ybSwgeDAsIHkwLCB4MSwgeTEsIHgyLCB5MiwgeDMsIHkzLCBtaW5NYXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYm94ID0gX3V0aWwuVXRpbC5iZXppZXJCb3VuZGluZ0JveCh4MCwgeTAsIHgxLCB5MSwgeDIsIHkyLCB4MywgeTMpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAobWluTWF4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5NYXhbMF0gPSBNYXRoLm1pbihtaW5NYXhbMF0sIGJveFswXSwgYm94WzJdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbk1heFsxXSA9IE1hdGgubWF4KG1pbk1heFsxXSwgYm94WzBdLCBib3hbMl0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluTWF4WzJdID0gTWF0aC5taW4obWluTWF4WzJdLCBib3hbMV0sIGJveFszXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5NYXhbM10gPSBNYXRoLm1heChtaW5NYXhbM10sIGJveFsxXSwgYm94WzNdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVJlY3RNaW5NYXgodHJhbnNmb3JtLCBib3gpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRQYXRoQm91bmRpbmdCb3goKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBwYXRoVHlwZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogX3BhdHRlcm5faGVscGVyLlBhdGhUeXBlLkZJTEw7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB0cmFuc2Zvcm0gPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJveCA9IFt0aGlzLm1pblgsIHRoaXMubWluWSwgdGhpcy5tYXhYLCB0aGlzLm1heFldOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAocGF0aFR5cGUgPT09IF9wYXR0ZXJuX2hlbHBlci5QYXRoVHlwZS5TVFJPS0UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdHJhbnNmb3JtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiU3Ryb2tlIGJvdW5kaW5nIGJveCBtdXN0IGluY2x1ZGUgdHJhbnNmb3JtLiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2NhbGUgPSBfdXRpbC5VdGlsLnNpbmd1bGFyVmFsdWVEZWNvbXBvc2UyZFNjYWxlKHRyYW5zZm9ybSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB4U3Ryb2tlUGFkID0gc2NhbGVbMF0gKiB0aGlzLmxpbmVXaWR0aCAvIDI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB5U3Ryb2tlUGFkID0gc2NhbGVbMV0gKiB0aGlzLmxpbmVXaWR0aCAvIDI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib3hbMF0gLT0geFN0cm9rZVBhZDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJveFsxXSAtPSB5U3Ryb2tlUGFkOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm94WzJdICs9IHhTdHJva2VQYWQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib3hbM10gKz0geVN0cm9rZVBhZDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYm94OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB1cGRhdGVDbGlwRnJvbVBhdGgoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGludGVyc2VjdCA9IF91dGlsLlV0aWwuaW50ZXJzZWN0KHRoaXMuY2xpcEJveCwgdGhpcy5nZXRQYXRoQm91bmRpbmdCb3goKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhcnROZXdQYXRoQW5kQ2xpcEJveChpbnRlcnNlY3QgfHwgWzAsIDAsIDAsIDBdKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaXNFbXB0eUNsaXAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1pblggPT09IEluZmluaXR5OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGFydE5ld1BhdGhBbmRDbGlwQm94KGJveCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsaXBCb3ggPSBib3g7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWluWCA9IEluZmluaXR5OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1pblkgPSBJbmZpbml0eTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXhYID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXhZID0gMDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0Q2xpcHBlZFBhdGhCb3VuZGluZ0JveCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHBhdGhUeXBlID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBfcGF0dGVybl9oZWxwZXIuUGF0aFR5cGUuRklMTDsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRyYW5zZm9ybSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF91dGlsLlV0aWwuaW50ZXJzZWN0KHRoaXMuY2xpcEJveCwgdGhpcy5nZXRQYXRoQm91bmRpbmdCb3gocGF0aFR5cGUsIHRyYW5zZm9ybSkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHB1dEJpbmFyeUltYWdlRGF0YShjdHgsIGltZ0RhdGEpIHsKICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIEltYWdlRGF0YSAhPT0gInVuZGVmaW5lZCIgJiYgaW1nRGF0YSBpbnN0YW5jZW9mIEltYWdlRGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICBjdHgucHV0SW1hZ2VEYXRhKGltZ0RhdGEsIDAsIDApOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGltZ0RhdGEuaGVpZ2h0LAogICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IGltZ0RhdGEud2lkdGg7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFydGlhbENodW5rSGVpZ2h0ID0gaGVpZ2h0ICUgRlVMTF9DSFVOS19IRUlHSFQ7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZnVsbENodW5rcyA9IChoZWlnaHQgLSBwYXJ0aWFsQ2h1bmtIZWlnaHQpIC8gRlVMTF9DSFVOS19IRUlHSFQ7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdG90YWxDaHVua3MgPSBwYXJ0aWFsQ2h1bmtIZWlnaHQgPT09IDAgPyBmdWxsQ2h1bmtzIDogZnVsbENodW5rcyArIDE7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2h1bmtJbWdEYXRhID0gY3R4LmNyZWF0ZUltYWdlRGF0YSh3aWR0aCwgRlVMTF9DSFVOS19IRUlHSFQpOwogICAgICAgICAgICAgICAgICAgIGxldCBzcmNQb3MgPSAwLAogICAgICAgICAgICAgICAgICAgICAgICBkZXN0UG9zOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHNyYyA9IGltZ0RhdGEuZGF0YTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBkZXN0ID0gY2h1bmtJbWdEYXRhLmRhdGE7CiAgICAgICAgICAgICAgICAgICAgbGV0IGksIGosIHRoaXNDaHVua0hlaWdodCwgZWxlbXNJblRoaXNDaHVuazsKICAgICAgICAgICAgICAgICAgICBpZiAoaW1nRGF0YS5raW5kID09PSBfdXRpbC5JbWFnZUtpbmQuR1JBWVNDQUxFXzFCUFApIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3JjTGVuZ3RoID0gc3JjLmJ5dGVMZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlc3QzMiA9IG5ldyBVaW50MzJBcnJheShkZXN0LmJ1ZmZlciwgMCwgZGVzdC5ieXRlTGVuZ3RoID4+IDIpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkZXN0MzJEYXRhTGVuZ3RoID0gZGVzdDMyLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZnVsbFNyY0RpZmYgPSB3aWR0aCArIDcgPj4gMzsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2hpdGUgPSAweGZmZmZmZmZmOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBibGFjayA9IF91dGlsLkZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuID8gMHhmZjAwMDAwMCA6IDB4MDAwMDAwZmY7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0b3RhbENodW5rczsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzQ2h1bmtIZWlnaHQgPSBpIDwgZnVsbENodW5rcyA/IEZVTExfQ0hVTktfSEVJR0hUIDogcGFydGlhbENodW5rSGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdFBvcyA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgdGhpc0NodW5rSGVpZ2h0OyBqKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzcmNEaWZmID0gc3JjTGVuZ3RoIC0gc3JjUG9zOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBrID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBrRW5kID0gc3JjRGlmZiA+IGZ1bGxTcmNEaWZmID8gd2lkdGggOiBzcmNEaWZmICogOCAtIDc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qga0VuZFVucm9sbGVkID0ga0VuZCAmIH43OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtYXNrID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3JjQnl0ZSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICg7IGsgPCBrRW5kVW5yb2xsZWQ7IGsgKz0gOCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcmNCeXRlID0gc3JjW3NyY1BvcysrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdDMyW2Rlc3RQb3MrK10gPSBzcmNCeXRlICYgMTI4ID8gd2hpdGUgOiBibGFjazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdDMyW2Rlc3RQb3MrK10gPSBzcmNCeXRlICYgNjQgPyB3aGl0ZSA6IGJsYWNrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0MzJbZGVzdFBvcysrXSA9IHNyY0J5dGUgJiAzMiA/IHdoaXRlIDogYmxhY2s7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc3QzMltkZXN0UG9zKytdID0gc3JjQnl0ZSAmIDE2ID8gd2hpdGUgOiBibGFjazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdDMyW2Rlc3RQb3MrK10gPSBzcmNCeXRlICYgOCA/IHdoaXRlIDogYmxhY2s7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc3QzMltkZXN0UG9zKytdID0gc3JjQnl0ZSAmIDQgPyB3aGl0ZSA6IGJsYWNrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0MzJbZGVzdFBvcysrXSA9IHNyY0J5dGUgJiAyID8gd2hpdGUgOiBibGFjazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdDMyW2Rlc3RQb3MrK10gPSBzcmNCeXRlICYgMSA/IHdoaXRlIDogYmxhY2s7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoOyBrIDwga0VuZDsgaysrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXNrID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcmNCeXRlID0gc3JjW3NyY1BvcysrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sgPSAxMjg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdDMyW2Rlc3RQb3MrK10gPSBzcmNCeXRlICYgbWFzayA/IHdoaXRlIDogYmxhY2s7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2sgPj49IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGRlc3RQb3MgPCBkZXN0MzJEYXRhTGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdDMyW2Rlc3RQb3MrK10gPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnB1dEltYWdlRGF0YShjaHVua0ltZ0RhdGEsIDAsIGkgKiBGVUxMX0NIVU5LX0hFSUdIVCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGltZ0RhdGEua2luZCA9PT0gX3V0aWwuSW1hZ2VLaW5kLlJHQkFfMzJCUFApIHsKICAgICAgICAgICAgICAgICAgICAgICAgaiA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1zSW5UaGlzQ2h1bmsgPSB3aWR0aCAqIEZVTExfQ0hVTktfSEVJR0hUICogNDsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGZ1bGxDaHVua3M7IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdC5zZXQoc3JjLnN1YmFycmF5KHNyY1Bvcywgc3JjUG9zICsgZWxlbXNJblRoaXNDaHVuaykpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3JjUG9zICs9IGVsZW1zSW5UaGlzQ2h1bms7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgucHV0SW1hZ2VEYXRhKGNodW5rSW1nRGF0YSwgMCwgaik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBqICs9IEZVTExfQ0hVTktfSEVJR0hUOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpIDwgdG90YWxDaHVua3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1zSW5UaGlzQ2h1bmsgPSB3aWR0aCAqIHBhcnRpYWxDaHVua0hlaWdodCAqIDQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0LnNldChzcmMuc3ViYXJyYXkoc3JjUG9zLCBzcmNQb3MgKyBlbGVtc0luVGhpc0NodW5rKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgucHV0SW1hZ2VEYXRhKGNodW5rSW1nRGF0YSwgMCwgaik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGltZ0RhdGEua2luZCA9PT0gX3V0aWwuSW1hZ2VLaW5kLlJHQl8yNEJQUCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzQ2h1bmtIZWlnaHQgPSBGVUxMX0NIVU5LX0hFSUdIVDsKICAgICAgICAgICAgICAgICAgICAgICAgZWxlbXNJblRoaXNDaHVuayA9IHdpZHRoICogdGhpc0NodW5rSGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdG90YWxDaHVua3M7IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGkgPj0gZnVsbENodW5rcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNDaHVua0hlaWdodCA9IHBhcnRpYWxDaHVua0hlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtc0luVGhpc0NodW5rID0gd2lkdGggKiB0aGlzQ2h1bmtIZWlnaHQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0UG9zID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaiA9IGVsZW1zSW5UaGlzQ2h1bms7IGotLTspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSBzcmNbc3JjUG9zKytdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RbZGVzdFBvcysrXSA9IHNyY1tzcmNQb3MrK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdFtkZXN0UG9zKytdID0gc3JjW3NyY1BvcysrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSAyNTU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgucHV0SW1hZ2VEYXRhKGNodW5rSW1nRGF0YSwgMCwgaSAqIEZVTExfQ0hVTktfSEVJR0hUKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgYmFkIGltYWdlIGtpbmQ6ICR7aW1nRGF0YS5raW5kfWApOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHB1dEJpbmFyeUltYWdlTWFzayhjdHgsIGltZ0RhdGEpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoaW1nRGF0YS5iaXRtYXApIHsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmRyYXdJbWFnZShpbWdEYXRhLmJpdG1hcCwgMCwgMCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gaW1nRGF0YS5oZWlnaHQsCiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gaW1nRGF0YS53aWR0aDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJ0aWFsQ2h1bmtIZWlnaHQgPSBoZWlnaHQgJSBGVUxMX0NIVU5LX0hFSUdIVDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBmdWxsQ2h1bmtzID0gKGhlaWdodCAtIHBhcnRpYWxDaHVua0hlaWdodCkgLyBGVUxMX0NIVU5LX0hFSUdIVDsKICAgICAgICAgICAgICAgICAgICBjb25zdCB0b3RhbENodW5rcyA9IHBhcnRpYWxDaHVua0hlaWdodCA9PT0gMCA/IGZ1bGxDaHVua3MgOiBmdWxsQ2h1bmtzICsgMTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjaHVua0ltZ0RhdGEgPSBjdHguY3JlYXRlSW1hZ2VEYXRhKHdpZHRoLCBGVUxMX0NIVU5LX0hFSUdIVCk7CiAgICAgICAgICAgICAgICAgICAgbGV0IHNyY1BvcyA9IDA7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3JjID0gaW1nRGF0YS5kYXRhOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlc3QgPSBjaHVua0ltZ0RhdGEuZGF0YTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRvdGFsQ2h1bmtzOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGhpc0NodW5rSGVpZ2h0ID0gaSA8IGZ1bGxDaHVua3MgPyBGVUxMX0NIVU5LX0hFSUdIVCA6IHBhcnRpYWxDaHVua0hlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNyY1BvcwogICAgICAgICAgICAgICAgICAgICAgICB9ID0gKDAsIF9pbWFnZV91dGlscy5jb252ZXJ0QmxhY2tBbmRXaGl0ZVRvUkdCQSkoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3JjLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3JjUG9zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiB0aGlzQ2h1bmtIZWlnaHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25CbGFja0NvbG9yOiAwCiAgICAgICAgICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnB1dEltYWdlRGF0YShjaHVua0ltZ0RhdGEsIDAsIGkgKiBGVUxMX0NIVU5LX0hFSUdIVCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gY29weUN0eFN0YXRlKHNvdXJjZUN0eCwgZGVzdEN0eCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSBbInN0cm9rZVN0eWxlIiwgImZpbGxTdHlsZSIsICJmaWxsUnVsZSIsICJnbG9iYWxBbHBoYSIsICJsaW5lV2lkdGgiLCAibGluZUNhcCIsICJsaW5lSm9pbiIsICJtaXRlckxpbWl0IiwgImdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbiIsICJmb250IiwgImZpbHRlciJdOwogICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcHJvcGVydHkgb2YgcHJvcGVydGllcykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoc291cmNlQ3R4W3Byb3BlcnR5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0Q3R4W3Byb3BlcnR5XSA9IHNvdXJjZUN0eFtwcm9wZXJ0eV07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKHNvdXJjZUN0eC5zZXRMaW5lRGFzaCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RDdHguc2V0TGluZURhc2goc291cmNlQ3R4LmdldExpbmVEYXNoKCkpOwogICAgICAgICAgICAgICAgICAgICAgICBkZXN0Q3R4LmxpbmVEYXNoT2Zmc2V0ID0gc291cmNlQ3R4LmxpbmVEYXNoT2Zmc2V0OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHJlc2V0Q3R4VG9EZWZhdWx0KGN0eCkgewogICAgICAgICAgICAgICAgICAgIGN0eC5zdHJva2VTdHlsZSA9IGN0eC5maWxsU3R5bGUgPSAiIzAwMDAwMCI7CiAgICAgICAgICAgICAgICAgICAgY3R4LmZpbGxSdWxlID0gIm5vbnplcm8iOwogICAgICAgICAgICAgICAgICAgIGN0eC5nbG9iYWxBbHBoYSA9IDE7CiAgICAgICAgICAgICAgICAgICAgY3R4LmxpbmVXaWR0aCA9IDE7CiAgICAgICAgICAgICAgICAgICAgY3R4LmxpbmVDYXAgPSAiYnV0dCI7CiAgICAgICAgICAgICAgICAgICAgY3R4LmxpbmVKb2luID0gIm1pdGVyIjsKICAgICAgICAgICAgICAgICAgICBjdHgubWl0ZXJMaW1pdCA9IDEwOwogICAgICAgICAgICAgICAgICAgIGN0eC5nbG9iYWxDb21wb3NpdGVPcGVyYXRpb24gPSAic291cmNlLW92ZXIiOwogICAgICAgICAgICAgICAgICAgIGN0eC5mb250ID0gIjEwcHggc2Fucy1zZXJpZiI7CiAgICAgICAgICAgICAgICAgICAgaWYgKGN0eC5zZXRMaW5lRGFzaCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zZXRMaW5lRGFzaChbXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5saW5lRGFzaE9mZnNldCA9IDA7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmICghX2lzX25vZGUuaXNOb2RlSlMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmZpbHRlciA9ICJub25lIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBjb21wb3NlU01hc2tCYWNrZHJvcChieXRlcywgcjAsIGcwLCBiMCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IGJ5dGVzLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMzsgaSA8IGxlbmd0aDsgaSArPSA0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFscGhhID0gYnl0ZXNbaV07CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbHBoYSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNbaSAtIDNdID0gcjA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1tpIC0gMl0gPSBnMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzW2kgLSAxXSA9IGIwOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGFscGhhIDwgMjU1KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhbHBoYV8gPSAyNTUgLSBhbHBoYTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzW2kgLSAzXSA9IGJ5dGVzW2kgLSAzXSAqIGFscGhhICsgcjAgKiBhbHBoYV8gPj4gODsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzW2kgLSAyXSA9IGJ5dGVzW2kgLSAyXSAqIGFscGhhICsgZzAgKiBhbHBoYV8gPj4gODsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzW2kgLSAxXSA9IGJ5dGVzW2kgLSAxXSAqIGFscGhhICsgYjAgKiBhbHBoYV8gPj4gODsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGNvbXBvc2VTTWFza0FscGhhKG1hc2tEYXRhLCBsYXllckRhdGEsIHRyYW5zZmVyTWFwKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gbWFza0RhdGEubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHNjYWxlID0gMSAvIDI1NTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMzsgaSA8IGxlbmd0aDsgaSArPSA0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFscGhhID0gdHJhbnNmZXJNYXAgPyB0cmFuc2Zlck1hcFttYXNrRGF0YVtpXV0gOiBtYXNrRGF0YVtpXTsKICAgICAgICAgICAgICAgICAgICAgICAgbGF5ZXJEYXRhW2ldID0gbGF5ZXJEYXRhW2ldICogYWxwaGEgKiBzY2FsZSB8IDA7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gY29tcG9zZVNNYXNrTHVtaW5vc2l0eShtYXNrRGF0YSwgbGF5ZXJEYXRhLCB0cmFuc2Zlck1hcCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IG1hc2tEYXRhLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMzsgaSA8IGxlbmd0aDsgaSArPSA0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHkgPSBtYXNrRGF0YVtpIC0gM10gKiA3NyArIG1hc2tEYXRhW2kgLSAyXSAqIDE1MiArIG1hc2tEYXRhW2kgLSAxXSAqIDI4OwogICAgICAgICAgICAgICAgICAgICAgICBsYXllckRhdGFbaV0gPSB0cmFuc2Zlck1hcCA/IGxheWVyRGF0YVtpXSAqIHRyYW5zZmVyTWFwW3kgPj4gOF0gPj4gOCA6IGxheWVyRGF0YVtpXSAqIHkgPj4gMTY7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gZ2VuZXJpY0NvbXBvc2VTTWFzayhtYXNrQ3R4LCBsYXllckN0eCwgd2lkdGgsIGhlaWdodCwgc3VidHlwZSwgYmFja2Ryb3AsIHRyYW5zZmVyTWFwLCBsYXllck9mZnNldFgsIGxheWVyT2Zmc2V0WSwgbWFza09mZnNldFgsIG1hc2tPZmZzZXRZKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgaGFzQmFja2Ryb3AgPSAhIWJhY2tkcm9wOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHIwID0gaGFzQmFja2Ryb3AgPyBiYWNrZHJvcFswXSA6IDA7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZzAgPSBoYXNCYWNrZHJvcCA/IGJhY2tkcm9wWzFdIDogMDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBiMCA9IGhhc0JhY2tkcm9wID8gYmFja2Ryb3BbMl0gOiAwOwogICAgICAgICAgICAgICAgICAgIGxldCBjb21wb3NlRm47CiAgICAgICAgICAgICAgICAgICAgaWYgKHN1YnR5cGUgPT09ICJMdW1pbm9zaXR5IikgewogICAgICAgICAgICAgICAgICAgICAgICBjb21wb3NlRm4gPSBjb21wb3NlU01hc2tMdW1pbm9zaXR5OwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvc2VGbiA9IGNvbXBvc2VTTWFza0FscGhhOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBQSVhFTFNfVE9fUFJPQ0VTUyA9IDEwNDg1NzY7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2h1bmtTaXplID0gTWF0aC5taW4oaGVpZ2h0LCBNYXRoLmNlaWwoUElYRUxTX1RPX1BST0NFU1MgLyB3aWR0aCkpOwogICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHJvdyA9IDA7IHJvdyA8IGhlaWdodDsgcm93ICs9IGNodW5rU2l6ZSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaHVua0hlaWdodCA9IE1hdGgubWluKGNodW5rU2l6ZSwgaGVpZ2h0IC0gcm93KTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWFza0RhdGEgPSBtYXNrQ3R4LmdldEltYWdlRGF0YShsYXllck9mZnNldFggLSBtYXNrT2Zmc2V0WCwgcm93ICsgKGxheWVyT2Zmc2V0WSAtIG1hc2tPZmZzZXRZKSwgd2lkdGgsIGNodW5rSGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbGF5ZXJEYXRhID0gbGF5ZXJDdHguZ2V0SW1hZ2VEYXRhKGxheWVyT2Zmc2V0WCwgcm93ICsgbGF5ZXJPZmZzZXRZLCB3aWR0aCwgY2h1bmtIZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoaGFzQmFja2Ryb3ApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvc2VTTWFza0JhY2tkcm9wKG1hc2tEYXRhLmRhdGEsIHIwLCBnMCwgYjApOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvc2VGbihtYXNrRGF0YS5kYXRhLCBsYXllckRhdGEuZGF0YSwgdHJhbnNmZXJNYXApOwogICAgICAgICAgICAgICAgICAgICAgICBsYXllckN0eC5wdXRJbWFnZURhdGEobGF5ZXJEYXRhLCBsYXllck9mZnNldFgsIHJvdyArIGxheWVyT2Zmc2V0WSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gY29tcG9zZVNNYXNrKGN0eCwgc21hc2ssIGxheWVyQ3R4LCBsYXllckJveCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IGxheWVyT2Zmc2V0WCA9IGxheWVyQm94WzBdOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGxheWVyT2Zmc2V0WSA9IGxheWVyQm94WzFdOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGxheWVyV2lkdGggPSBsYXllckJveFsyXSAtIGxheWVyT2Zmc2V0WDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBsYXllckhlaWdodCA9IGxheWVyQm94WzNdIC0gbGF5ZXJPZmZzZXRZOwogICAgICAgICAgICAgICAgICAgIGlmIChsYXllcldpZHRoID09PSAwIHx8IGxheWVySGVpZ2h0ID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2VuZXJpY0NvbXBvc2VTTWFzayhzbWFzay5jb250ZXh0LCBsYXllckN0eCwgbGF5ZXJXaWR0aCwgbGF5ZXJIZWlnaHQsIHNtYXNrLnN1YnR5cGUsIHNtYXNrLmJhY2tkcm9wLCBzbWFzay50cmFuc2Zlck1hcCwgbGF5ZXJPZmZzZXRYLCBsYXllck9mZnNldFksIHNtYXNrLm9mZnNldFgsIHNtYXNrLm9mZnNldFkpOwogICAgICAgICAgICAgICAgICAgIGN0eC5zYXZlKCk7CiAgICAgICAgICAgICAgICAgICAgY3R4Lmdsb2JhbEFscGhhID0gMTsKICAgICAgICAgICAgICAgICAgICBjdHguZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uID0gInNvdXJjZS1vdmVyIjsKICAgICAgICAgICAgICAgICAgICBjdHguc2V0VHJhbnNmb3JtKDEsIDAsIDAsIDEsIDAsIDApOwogICAgICAgICAgICAgICAgICAgIGN0eC5kcmF3SW1hZ2UobGF5ZXJDdHguY2FudmFzLCAwLCAwKTsKICAgICAgICAgICAgICAgICAgICBjdHgucmVzdG9yZSgpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gZ2V0SW1hZ2VTbW9vdGhpbmdFbmFibGVkKHRyYW5zZm9ybSwgaW50ZXJwb2xhdGUpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBzY2FsZSA9IF91dGlsLlV0aWwuc2luZ3VsYXJWYWx1ZURlY29tcG9zZTJkU2NhbGUodHJhbnNmb3JtKTsKICAgICAgICAgICAgICAgICAgICBzY2FsZVswXSA9IE1hdGguZnJvdW5kKHNjYWxlWzBdKTsKICAgICAgICAgICAgICAgICAgICBzY2FsZVsxXSA9IE1hdGguZnJvdW5kKHNjYWxlWzFdKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBhY3R1YWxTY2FsZSA9IE1hdGguZnJvdW5kKChnbG9iYWxUaGlzLmRldmljZVBpeGVsUmF0aW8gfHwgMSkgKiBfZGlzcGxheV91dGlscy5QaXhlbHNQZXJJbmNoLlBERl9UT19DU1NfVU5JVFMpOwogICAgICAgICAgICAgICAgICAgIGlmIChpbnRlcnBvbGF0ZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnRlcnBvbGF0ZTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHNjYWxlWzBdIDw9IGFjdHVhbFNjYWxlIHx8IHNjYWxlWzFdIDw9IGFjdHVhbFNjYWxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjb25zdCBMSU5FX0NBUF9TVFlMRVMgPSBbImJ1dHQiLCAicm91bmQiLCAic3F1YXJlIl07CiAgICAgICAgICAgICAgICBjb25zdCBMSU5FX0pPSU5fU1RZTEVTID0gWyJtaXRlciIsICJyb3VuZCIsICJiZXZlbCJdOwogICAgICAgICAgICAgICAgY29uc3QgTk9STUFMX0NMSVAgPSB7fTsKICAgICAgICAgICAgICAgIGNvbnN0IEVPX0NMSVAgPSB7fTsKICAgICAgICAgICAgICAgIHZhciBfcmVzdG9yZUluaXRpYWxTdGF0ZSA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgY2xhc3MgQ2FudmFzR3JhcGhpY3MgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKGNhbnZhc0N0eCwgY29tbW9uT2Jqcywgb2JqcywgY2FudmFzRmFjdG9yeSwgZmlsdGVyRmFjdG9yeSwgX3JlZiwgYW5ub3RhdGlvbkNhbnZhc01hcCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uYWxDb250ZW50Q29uZmlnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VkQ29udGVudFN0YWNrID0gbnVsbAogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF9yZXN0b3JlSW5pdGlhbFN0YXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHggPSBjYW52YXNDdHg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudCA9IG5ldyBDYW52YXNFeHRyYVN0YXRlKHRoaXMuY3R4LmNhbnZhcy53aWR0aCwgdGhpcy5jdHguY2FudmFzLmhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RhdGVTdGFjayA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBlbmRpbmdDbGlwID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wZW5kaW5nRU9GaWxsID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy54b2JqcyA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbW9uT2JqcyA9IGNvbW1vbk9ianM7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub2JqcyA9IG9ianM7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FudmFzRmFjdG9yeSA9IGNhbnZhc0ZhY3Rvcnk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsdGVyRmFjdG9yeSA9IGZpbHRlckZhY3Rvcnk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ3JvdXBTdGFjayA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NpbmdUeXBlMyA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmFzZVRyYW5zZm9ybSA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmFzZVRyYW5zZm9ybVN0YWNrID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ3JvdXBMZXZlbCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc21hc2tTdGFjayA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNtYXNrQ291bnRlciA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGVtcFNNYXNrID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdXNwZW5kZWRDdHggPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRlbnRWaXNpYmxlID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXJrZWRDb250ZW50U3RhY2sgPSBtYXJrZWRDb250ZW50U3RhY2sgfHwgW107CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3B0aW9uYWxDb250ZW50Q29uZmlnID0gb3B0aW9uYWxDb250ZW50Q29uZmlnOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhY2hlZENhbnZhc2VzID0gbmV3IENhY2hlZENhbnZhc2VzKHRoaXMuY2FudmFzRmFjdG9yeSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FjaGVkUGF0dGVybnMgPSBuZXcgTWFwKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYW5ub3RhdGlvbkNhbnZhc01hcCA9IGFubm90YXRpb25DYW52YXNNYXA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudmlld3BvcnRTY2FsZSA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0U2NhbGVYID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vdXRwdXRTY2FsZVkgPSAxOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYWNoZWRTY2FsZUZvclN0cm9raW5nID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY2FjaGVkR2V0U2luZ2xlUGl4ZWxXaWR0aCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NhY2hlZEJpdG1hcHNNYXAgPSBuZXcgTWFwKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldE9iamVjdChkYXRhKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmYWxsYmFjayA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhID09PSAic3RyaW5nIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRhdGEuc3RhcnRzV2l0aCgiZ18iKSA/IHRoaXMuY29tbW9uT2Jqcy5nZXQoZGF0YSkgOiB0aGlzLm9ianMuZ2V0KGRhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxsYmFjazsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYmVnaW5EcmF3aW5nKF9yZWYyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3cG9ydCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zcGFyZW5jeSA9IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFja2dyb3VuZCA9IG51bGwKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IF9yZWYyOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuY3R4LmNhbnZhcy53aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5jdHguY2FudmFzLmhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2F2ZWRGaWxsU3R5bGUgPSB0aGlzLmN0eC5maWxsU3R5bGU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LmZpbGxTdHlsZSA9IGJhY2tncm91bmQgfHwgIiNmZmZmZmYiOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5maWxsUmVjdCgwLCAwLCB3aWR0aCwgaGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguZmlsbFN0eWxlID0gc2F2ZWRGaWxsU3R5bGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0cmFuc3BhcmVuY3kpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zcGFyZW50Q2FudmFzID0gdGhpcy5jYWNoZWRDYW52YXNlcy5nZXRDYW52YXMoInRyYW5zcGFyZW50Iiwgd2lkdGgsIGhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBvc2l0ZUN0eCA9IHRoaXMuY3R4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc3BhcmVudENhbnZhcyA9IHRyYW5zcGFyZW50Q2FudmFzLmNhbnZhczsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4ID0gdHJhbnNwYXJlbnRDYW52YXMuY29udGV4dDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnNhdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnRyYW5zZm9ybSguLi4oMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybSkodGhpcy5jb21wb3NpdGVDdHgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5zYXZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0Q3R4VG9EZWZhdWx0KHRoaXMuY3R4KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRyYW5zZm9ybSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHgudHJhbnNmb3JtKC4uLnRyYW5zZm9ybSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm91dHB1dFNjYWxlWCA9IHRyYW5zZm9ybVswXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3V0cHV0U2NhbGVZID0gdHJhbnNmb3JtWzBdOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnRyYW5zZm9ybSguLi52aWV3cG9ydC50cmFuc2Zvcm0pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZXdwb3J0U2NhbGUgPSB2aWV3cG9ydC5zY2FsZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5iYXNlVHJhbnNmb3JtID0gKDAsIF9kaXNwbGF5X3V0aWxzLmdldEN1cnJlbnRUcmFuc2Zvcm0pKHRoaXMuY3R4KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZXhlY3V0ZU9wZXJhdG9yTGlzdChvcGVyYXRvckxpc3QsIGV4ZWN1dGlvblN0YXJ0SWR4LCBjb250aW51ZUNhbGxiYWNrLCBzdGVwcGVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFyZ3NBcnJheSA9IG9wZXJhdG9yTGlzdC5hcmdzQXJyYXk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZuQXJyYXkgPSBvcGVyYXRvckxpc3QuZm5BcnJheTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGkgPSBleGVjdXRpb25TdGFydElkeCB8fCAwOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhcmdzQXJyYXlMZW4gPSBhcmdzQXJyYXkubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJnc0FycmF5TGVuID09PSBpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaHVua09wZXJhdGlvbnMgPSBhcmdzQXJyYXlMZW4gLSBpID4gRVhFQ1VUSU9OX1NURVBTICYmIHR5cGVvZiBjb250aW51ZUNhbGxiYWNrID09PSAiZnVuY3Rpb24iOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlbmRUaW1lID0gY2h1bmtPcGVyYXRpb25zID8gRGF0ZS5ub3coKSArIEVYRUNVVElPTl9USU1FIDogMDsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHN0ZXBzID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29tbW9uT2JqcyA9IHRoaXMuY29tbW9uT2JqczsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2JqcyA9IHRoaXMub2JqczsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZuSWQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RlcHBlciAhPT0gdW5kZWZpbmVkICYmIGkgPT09IHN0ZXBwZXIubmV4dEJyZWFrUG9pbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGVwcGVyLmJyZWFrSXQoaSwgY29udGludWVDYWxsYmFjayk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbklkID0gZm5BcnJheVtpXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmbklkICE9PSBfdXRpbC5PUFMuZGVwZW5kZW5jeSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNbZm5JZF0uYXBwbHkodGhpcywgYXJnc0FycmF5W2ldKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBkZXBPYmpJZCBvZiBhcmdzQXJyYXlbaV0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2Jqc1Bvb2wgPSBkZXBPYmpJZC5zdGFydHNXaXRoKCJnXyIpID8gY29tbW9uT2JqcyA6IG9ianM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghb2Jqc1Bvb2wuaGFzKGRlcE9iaklkKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Jqc1Bvb2wuZ2V0KGRlcE9iaklkLCBjb250aW51ZUNhbGxiYWNrKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaSsrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGkgPT09IGFyZ3NBcnJheUxlbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNodW5rT3BlcmF0aW9ucyAmJiArK3N0ZXBzID4gRVhFQ1VUSU9OX1NURVBTKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKERhdGUubm93KCkgPiBlbmRUaW1lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlQ2FsbGJhY2soKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ZXBzID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbmREcmF3aW5nKCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcGFnZUNvbG9ycyA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfcmVzdG9yZUluaXRpYWxTdGF0ZSwgX3Jlc3RvcmVJbml0aWFsU3RhdGUyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhY2hlZENhbnZhc2VzLmNsZWFyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FjaGVkUGF0dGVybnMuY2xlYXIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBjYWNoZSBvZiB0aGlzLl9jYWNoZWRCaXRtYXBzTWFwLnZhbHVlcygpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGNhbnZhcyBvZiBjYWNoZS52YWx1ZXMoKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgSFRNTENhbnZhc0VsZW1lbnQgIT09ICJ1bmRlZmluZWQiICYmIGNhbnZhcyBpbnN0YW5jZW9mIEhUTUxDYW52YXNFbGVtZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhcy53aWR0aCA9IGNhbnZhcy5oZWlnaHQgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlLmNsZWFyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY2FjaGVkQml0bWFwc01hcC5jbGVhcigpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFnZUNvbG9ycykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaGNtRmlsdGVySWQgPSB0aGlzLmZpbHRlckZhY3RvcnkuYWRkSENNRmlsdGVyKHBhZ2VDb2xvcnMuZm9yZWdyb3VuZCwgcGFnZUNvbG9ycy5iYWNrZ3JvdW5kKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChoY21GaWx0ZXJJZCAhPT0gIm5vbmUiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2F2ZWRGaWx0ZXIgPSB0aGlzLmN0eC5maWx0ZXI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguZmlsdGVyID0gaGNtRmlsdGVySWQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguZHJhd0ltYWdlKHRoaXMuY3R4LmNhbnZhcywgMCwgMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguZmlsdGVyID0gc2F2ZWRGaWx0ZXI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX3NjYWxlSW1hZ2UoaW1nLCBpbnZlcnNlVHJhbnNmb3JtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gaW1nLndpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBpbWcuaGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgd2lkdGhTY2FsZSA9IE1hdGgubWF4KE1hdGguaHlwb3QoaW52ZXJzZVRyYW5zZm9ybVswXSwgaW52ZXJzZVRyYW5zZm9ybVsxXSksIDEpOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgaGVpZ2h0U2NhbGUgPSBNYXRoLm1heChNYXRoLmh5cG90KGludmVyc2VUcmFuc2Zvcm1bMl0sIGludmVyc2VUcmFuc2Zvcm1bM10pLCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHBhaW50V2lkdGggPSB3aWR0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhaW50SGVpZ2h0ID0gaGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgdG1wQ2FudmFzSWQgPSAicHJlc2NhbGUxIjsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRtcENhbnZhcywgdG1wQ3R4OwogICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAod2lkdGhTY2FsZSA+IDIgJiYgcGFpbnRXaWR0aCA+IDEgfHwgaGVpZ2h0U2NhbGUgPiAyICYmIHBhaW50SGVpZ2h0ID4gMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG5ld1dpZHRoID0gcGFpbnRXaWR0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdIZWlnaHQgPSBwYWludEhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3aWR0aFNjYWxlID4gMiAmJiBwYWludFdpZHRoID4gMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1dpZHRoID0gcGFpbnRXaWR0aCA+PSAxNjM4NCA/IE1hdGguZmxvb3IocGFpbnRXaWR0aCAvIDIpIC0gMSB8fCAxIDogTWF0aC5jZWlsKHBhaW50V2lkdGggLyAyKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aFNjYWxlIC89IHBhaW50V2lkdGggLyBuZXdXaWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChoZWlnaHRTY2FsZSA+IDIgJiYgcGFpbnRIZWlnaHQgPiAxKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3SGVpZ2h0ID0gcGFpbnRIZWlnaHQgPj0gMTYzODQgPyBNYXRoLmZsb29yKHBhaW50SGVpZ2h0IC8gMikgLSAxIHx8IDEgOiBNYXRoLmNlaWwocGFpbnRIZWlnaHQpIC8gMjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHRTY2FsZSAvPSBwYWludEhlaWdodCAvIG5ld0hlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcENhbnZhcyA9IHRoaXMuY2FjaGVkQ2FudmFzZXMuZ2V0Q2FudmFzKHRtcENhbnZhc0lkLCBuZXdXaWR0aCwgbmV3SGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcEN0eCA9IHRtcENhbnZhcy5jb250ZXh0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wQ3R4LmNsZWFyUmVjdCgwLCAwLCBuZXdXaWR0aCwgbmV3SGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcEN0eC5kcmF3SW1hZ2UoaW1nLCAwLCAwLCBwYWludFdpZHRoLCBwYWludEhlaWdodCwgMCwgMCwgbmV3V2lkdGgsIG5ld0hlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbWcgPSB0bXBDYW52YXMuY2FudmFzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFpbnRXaWR0aCA9IG5ld1dpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFpbnRIZWlnaHQgPSBuZXdIZWlnaHQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXBDYW52YXNJZCA9IHRtcENhbnZhc0lkID09PSAicHJlc2NhbGUxIiA/ICJwcmVzY2FsZTIiIDogInByZXNjYWxlMSI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhaW50V2lkdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWludEhlaWdodAogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfY3JlYXRlTWFza0NhbnZhcyhpbWcpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0CiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBpbWc7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbGxDb2xvciA9IHRoaXMuY3VycmVudC5maWxsQ29sb3I7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzUGF0dGVybkZpbGwgPSB0aGlzLmN1cnJlbnQucGF0dGVybkZpbGw7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRUcmFuc2Zvcm0gPSAoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybSkoY3R4KTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNhY2hlLCBjYWNoZUtleSwgc2NhbGVkLCBtYXNrQ2FudmFzOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGltZy5iaXRtYXAgfHwgaW1nLmRhdGEpICYmIGltZy5jb3VudCA+IDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1haW5LZXkgPSBpbWcuYml0bWFwIHx8IGltZy5kYXRhLmJ1ZmZlcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlS2V5ID0gSlNPTi5zdHJpbmdpZnkoaXNQYXR0ZXJuRmlsbCA/IGN1cnJlbnRUcmFuc2Zvcm0gOiBbY3VycmVudFRyYW5zZm9ybS5zbGljZSgwLCA0KSwgZmlsbENvbG9yXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWNoZSA9IHRoaXMuX2NhY2hlZEJpdG1hcHNNYXAuZ2V0KG1haW5LZXkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjYWNoZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlID0gbmV3IE1hcCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NhY2hlZEJpdG1hcHNNYXAuc2V0KG1haW5LZXksIGNhY2hlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhY2hlZEltYWdlID0gY2FjaGUuZ2V0KGNhY2hlS2V5KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjYWNoZWRJbWFnZSAmJiAhaXNQYXR0ZXJuRmlsbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldFggPSBNYXRoLnJvdW5kKE1hdGgubWluKGN1cnJlbnRUcmFuc2Zvcm1bMF0sIGN1cnJlbnRUcmFuc2Zvcm1bMl0pICsgY3VycmVudFRyYW5zZm9ybVs0XSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2Zmc2V0WSA9IE1hdGgucm91bmQoTWF0aC5taW4oY3VycmVudFRyYW5zZm9ybVsxXSwgY3VycmVudFRyYW5zZm9ybVszXSkgKyBjdXJyZW50VHJhbnNmb3JtWzVdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYW52YXM6IGNhY2hlZEltYWdlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRYLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRZCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlZCA9IGNhY2hlZEltYWdlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2NhbGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrQ2FudmFzID0gdGhpcy5jYWNoZWRDYW52YXNlcy5nZXRDYW52YXMoIm1hc2tDYW52YXMiLCB3aWR0aCwgaGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1dEJpbmFyeUltYWdlTWFzayhtYXNrQ2FudmFzLmNvbnRleHQsIGltZyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1hc2tUb0NhbnZhcyA9IF91dGlsLlV0aWwudHJhbnNmb3JtKGN1cnJlbnRUcmFuc2Zvcm0sIFsxIC8gd2lkdGgsIDAsIDAsIC0xIC8gaGVpZ2h0LCAwLCAwXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tUb0NhbnZhcyA9IF91dGlsLlV0aWwudHJhbnNmb3JtKG1hc2tUb0NhbnZhcywgWzEsIDAsIDAsIDEsIDAsIC1oZWlnaHRdKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29yZDEgPSBfdXRpbC5VdGlsLmFwcGx5VHJhbnNmb3JtKFswLCAwXSwgbWFza1RvQ2FudmFzKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29yZDIgPSBfdXRpbC5VdGlsLmFwcGx5VHJhbnNmb3JtKFt3aWR0aCwgaGVpZ2h0XSwgbWFza1RvQ2FudmFzKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVjdCA9IF91dGlsLlV0aWwubm9ybWFsaXplUmVjdChbY29yZDFbMF0sIGNvcmQxWzFdLCBjb3JkMlswXSwgY29yZDJbMV1dKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZHJhd25XaWR0aCA9IE1hdGgucm91bmQocmVjdFsyXSAtIHJlY3RbMF0pIHx8IDE7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRyYXduSGVpZ2h0ID0gTWF0aC5yb3VuZChyZWN0WzNdIC0gcmVjdFsxXSkgfHwgMTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlsbENhbnZhcyA9IHRoaXMuY2FjaGVkQ2FudmFzZXMuZ2V0Q2FudmFzKCJmaWxsQ2FudmFzIiwgZHJhd25XaWR0aCwgZHJhd25IZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWxsQ3R4ID0gZmlsbENhbnZhcy5jb250ZXh0OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXRYID0gTWF0aC5taW4oY29yZDFbMF0sIGNvcmQyWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2Zmc2V0WSA9IE1hdGgubWluKGNvcmQxWzFdLCBjb3JkMlsxXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGxDdHgudHJhbnNsYXRlKC1vZmZzZXRYLCAtb2Zmc2V0WSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGxDdHgudHJhbnNmb3JtKC4uLm1hc2tUb0NhbnZhcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2NhbGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZWQgPSB0aGlzLl9zY2FsZUltYWdlKG1hc2tDYW52YXMuY2FudmFzLCAoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybUludmVyc2UpKGZpbGxDdHgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlZCA9IHNjYWxlZC5pbWc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FjaGUgJiYgaXNQYXR0ZXJuRmlsbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhY2hlLnNldChjYWNoZUtleSwgc2NhbGVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBmaWxsQ3R4LmltYWdlU21vb3RoaW5nRW5hYmxlZCA9IGdldEltYWdlU21vb3RoaW5nRW5hYmxlZCgoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybSkoZmlsbEN0eCksIGltZy5pbnRlcnBvbGF0ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGRyYXdJbWFnZUF0SW50ZWdlckNvb3JkcyhmaWxsQ3R4LCBzY2FsZWQsIDAsIDAsIHNjYWxlZC53aWR0aCwgc2NhbGVkLmhlaWdodCwgMCwgMCwgd2lkdGgsIGhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGxDdHguZ2xvYmFsQ29tcG9zaXRlT3BlcmF0aW9uID0gInNvdXJjZS1pbiI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGludmVyc2UgPSBfdXRpbC5VdGlsLnRyYW5zZm9ybSgoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybUludmVyc2UpKGZpbGxDdHgpLCBbMSwgMCwgMCwgMSwgLW9mZnNldFgsIC1vZmZzZXRZXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGxDdHguZmlsbFN0eWxlID0gaXNQYXR0ZXJuRmlsbCA/IGZpbGxDb2xvci5nZXRQYXR0ZXJuKGN0eCwgdGhpcywgaW52ZXJzZSwgX3BhdHRlcm5faGVscGVyLlBhdGhUeXBlLkZJTEwpIDogZmlsbENvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICBmaWxsQ3R4LmZpbGxSZWN0KDAsIDAsIHdpZHRoLCBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2FjaGUgJiYgIWlzUGF0dGVybkZpbGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FjaGVkQ2FudmFzZXMuZGVsZXRlKCJmaWxsQ2FudmFzIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWNoZS5zZXQoY2FjaGVLZXksIGZpbGxDYW52YXMuY2FudmFzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzOiBmaWxsQ2FudmFzLmNhbnZhcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldFg6IE1hdGgucm91bmQob2Zmc2V0WCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRZOiBNYXRoLnJvdW5kKG9mZnNldFkpCiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldExpbmVXaWR0aCh3aWR0aCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAod2lkdGggIT09IHRoaXMuY3VycmVudC5saW5lV2lkdGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NhY2hlZFNjYWxlRm9yU3Ryb2tpbmcgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5saW5lV2lkdGggPSB3aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHgubGluZVdpZHRoID0gd2lkdGg7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldExpbmVDYXAoc3R5bGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHgubGluZUNhcCA9IExJTkVfQ0FQX1NUWUxFU1tzdHlsZV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldExpbmVKb2luKHN0eWxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LmxpbmVKb2luID0gTElORV9KT0lOX1NUWUxFU1tzdHlsZV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldE1pdGVyTGltaXQobGltaXQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHgubWl0ZXJMaW1pdCA9IGxpbWl0OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzZXREYXNoKGRhc2hBcnJheSwgZGFzaFBoYXNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4OwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3R4LnNldExpbmVEYXNoICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zZXRMaW5lRGFzaChkYXNoQXJyYXkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmxpbmVEYXNoT2Zmc2V0ID0gZGFzaFBoYXNlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldFJlbmRlcmluZ0ludGVudChpbnRlbnQpIHt9CiAgICAgICAgICAgICAgICAgICAgc2V0RmxhdG5lc3MoZmxhdG5lc3MpIHt9CiAgICAgICAgICAgICAgICAgICAgc2V0R1N0YXRlKHN0YXRlcykgewogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBzdGF0ZXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoa2V5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiTFciOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldExpbmVXaWR0aCh2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIkxDIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRMaW5lQ2FwKHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiTEoiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldExpbmVKb2luKHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiTUwiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldE1pdGVyTGltaXQodmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJEIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXREYXNoKHZhbHVlWzBdLCB2YWx1ZVsxXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIlJJIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRSZW5kZXJpbmdJbnRlbnQodmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJGTCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0RmxhdG5lc3ModmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJGb250IjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRGb250KHZhbHVlWzBdLCB2YWx1ZVsxXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIkNBIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnN0cm9rZUFscGhhID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgImNhIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmZpbGxBbHBoYSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5nbG9iYWxBbHBoYSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJCTSI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbiA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJTTWFzayI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5hY3RpdmVTTWFzayA9IHZhbHVlID8gdGhpcy50ZW1wU01hc2sgOiBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRlbXBTTWFzayA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2hlY2tTTWFza1N0YXRlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIlRSIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguZmlsdGVyID0gdGhpcy5jdXJyZW50LnRyYW5zZmVyTWFwcyA9IHRoaXMuZmlsdGVyRmFjdG9yeS5hZGRGaWx0ZXIodmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgaW5TTWFza01vZGUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhIXRoaXMuc3VzcGVuZGVkQ3R4OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjaGVja1NNYXNrU3RhdGUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGluU01hc2tNb2RlID0gdGhpcy5pblNNYXNrTW9kZTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudC5hY3RpdmVTTWFzayAmJiAhaW5TTWFza01vZGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmVnaW5TTWFza01vZGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghdGhpcy5jdXJyZW50LmFjdGl2ZVNNYXNrICYmIGluU01hc2tNb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVuZFNNYXNrTW9kZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJlZ2luU01hc2tNb2RlKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5pblNNYXNrTW9kZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJiZWdpblNNYXNrTW9kZSBjYWxsZWQgd2hpbGUgYWxyZWFkeSBpbiBzbWFzayBtb2RlIik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZHJhd25XaWR0aCA9IHRoaXMuY3R4LmNhbnZhcy53aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZHJhd25IZWlnaHQgPSB0aGlzLmN0eC5jYW52YXMuaGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYWNoZUlkID0gInNtYXNrR3JvdXBBdCIgKyB0aGlzLmdyb3VwTGV2ZWw7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNjcmF0Y2hDYW52YXMgPSB0aGlzLmNhY2hlZENhbnZhc2VzLmdldENhbnZhcyhjYWNoZUlkLCBkcmF3bldpZHRoLCBkcmF3bkhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3VzcGVuZGVkQ3R4ID0gdGhpcy5jdHg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4ID0gc2NyYXRjaENhbnZhcy5jb250ZXh0OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdHggPSB0aGlzLmN0eDsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnNldFRyYW5zZm9ybSguLi4oMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybSkodGhpcy5zdXNwZW5kZWRDdHgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29weUN0eFN0YXRlKHRoaXMuc3VzcGVuZGVkQ3R4LCBjdHgpOwogICAgICAgICAgICAgICAgICAgICAgICBtaXJyb3JDb250ZXh0T3BlcmF0aW9ucyhjdHgsIHRoaXMuc3VzcGVuZGVkQ3R4KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRHU3RhdGUoW1siQk0iLCAic291cmNlLW92ZXIiXSwgWyJjYSIsIDFdLCBbIkNBIiwgMV1dKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW5kU01hc2tNb2RlKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaW5TTWFza01vZGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiZW5kU01hc2tNb2RlIGNhbGxlZCB3aGlsZSBub3QgaW4gc21hc2sgbW9kZSIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4Ll9yZW1vdmVNaXJyb3JpbmcoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29weUN0eFN0YXRlKHRoaXMuY3R4LCB0aGlzLnN1c3BlbmRlZEN0eCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4ID0gdGhpcy5zdXNwZW5kZWRDdHg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3VzcGVuZGVkQ3R4ID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY29tcG9zZShkaXJ0eUJveCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY3VycmVudC5hY3RpdmVTTWFzaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGlydHlCb3gpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpcnR5Qm94ID0gWzAsIDAsIHRoaXMuY3R4LmNhbnZhcy53aWR0aCwgdGhpcy5jdHguY2FudmFzLmhlaWdodF07CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXJ0eUJveFswXSA9IE1hdGguZmxvb3IoZGlydHlCb3hbMF0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlydHlCb3hbMV0gPSBNYXRoLmZsb29yKGRpcnR5Qm94WzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpcnR5Qm94WzJdID0gTWF0aC5jZWlsKGRpcnR5Qm94WzJdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpcnR5Qm94WzNdID0gTWF0aC5jZWlsKGRpcnR5Qm94WzNdKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzbWFzayA9IHRoaXMuY3VycmVudC5hY3RpdmVTTWFzazsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3VzcGVuZGVkQ3R4ID0gdGhpcy5zdXNwZW5kZWRDdHg7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvc2VTTWFzayhzdXNwZW5kZWRDdHgsIHNtYXNrLCB0aGlzLmN0eCwgZGlydHlCb3gpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5zYXZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAwLCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguY2xlYXJSZWN0KDAsIDAsIHRoaXMuY3R4LmNhbnZhcy53aWR0aCwgdGhpcy5jdHguY2FudmFzLmhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnJlc3RvcmUoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2F2ZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5TTWFza01vZGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcHlDdHhTdGF0ZSh0aGlzLmN0eCwgdGhpcy5zdXNwZW5kZWRDdHgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdXNwZW5kZWRDdHguc2F2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguc2F2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9sZCA9IHRoaXMuY3VycmVudDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdGF0ZVN0YWNrLnB1c2gob2xkKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50ID0gb2xkLmNsb25lKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlc3RvcmUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnN0YXRlU3RhY2subGVuZ3RoID09PSAwICYmIHRoaXMuaW5TTWFza01vZGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5kU01hc2tNb2RlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGVTdGFjay5sZW5ndGggIT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudCA9IHRoaXMuc3RhdGVTdGFjay5wb3AoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmluU01hc2tNb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdXNwZW5kZWRDdHgucmVzdG9yZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcHlDdHhTdGF0ZSh0aGlzLnN1c3BlbmRlZEN0eCwgdGhpcy5jdHgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5yZXN0b3JlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNoZWNrU01hc2tTdGF0ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wZW5kaW5nQ2xpcCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYWNoZWRTY2FsZUZvclN0cm9raW5nID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NhY2hlZEdldFNpbmdsZVBpeGVsV2lkdGggPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybShhLCBiLCBjLCBkLCBlLCBmKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnRyYW5zZm9ybShhLCBiLCBjLCBkLCBlLCBmKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY2FjaGVkU2NhbGVGb3JTdHJva2luZyA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NhY2hlZEdldFNpbmdsZVBpeGVsV2lkdGggPSBudWxsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RQYXRoKG9wcywgYXJncywgbWluTWF4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5jdXJyZW50OwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgeCA9IGN1cnJlbnQueCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBjdXJyZW50Lnk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzdGFydFgsIHN0YXJ0WTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudFRyYW5zZm9ybSA9ICgwLCBfZGlzcGxheV91dGlscy5nZXRDdXJyZW50VHJhbnNmb3JtKShjdHgpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpc1NjYWxpbmdNYXRyaXggPSBjdXJyZW50VHJhbnNmb3JtWzBdID09PSAwICYmIGN1cnJlbnRUcmFuc2Zvcm1bM10gPT09IDAgfHwgY3VycmVudFRyYW5zZm9ybVsxXSA9PT0gMCAmJiBjdXJyZW50VHJhbnNmb3JtWzJdID09PSAwOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtaW5NYXhGb3JCZXppZXIgPSBpc1NjYWxpbmdNYXRyaXggPyBtaW5NYXguc2xpY2UoMCkgOiBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaiA9IDAsIGlpID0gb3BzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAob3BzW2ldIHwgMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnJlY3RhbmdsZToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IGFyZ3NbaisrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGFyZ3NbaisrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBhcmdzW2orK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGFyZ3NbaisrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeHcgPSB4ICsgd2lkdGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHloID0geSArIGhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4Lm1vdmVUbyh4LCB5KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdpZHRoID09PSAwIHx8IGhlaWdodCA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmxpbmVUbyh4dywgeWgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmxpbmVUbyh4dywgeSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgubGluZVRvKHh3LCB5aCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgubGluZVRvKHgsIHloKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzU2NhbGluZ01hdHJpeCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC51cGRhdGVSZWN0TWluTWF4KGN1cnJlbnRUcmFuc2Zvcm0sIFt4LCB5LCB4dywgeWhdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguY2xvc2VQYXRoKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLm1vdmVUbzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IGFyZ3NbaisrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGFyZ3NbaisrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4Lm1vdmVUbyh4LCB5KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1NjYWxpbmdNYXRyaXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudXBkYXRlUGF0aE1pbk1heChjdXJyZW50VHJhbnNmb3JtLCB4LCB5KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5saW5lVG86CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBhcmdzW2orK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBhcmdzW2orK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5saW5lVG8oeCwgeSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaXNTY2FsaW5nTWF0cml4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnVwZGF0ZVBhdGhNaW5NYXgoY3VycmVudFRyYW5zZm9ybSwgeCwgeSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMuY3VydmVUbzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRYID0geDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRZID0geTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IGFyZ3NbaiArIDRdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gYXJnc1tqICsgNV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5iZXppZXJDdXJ2ZVRvKGFyZ3Nbal0sIGFyZ3NbaiArIDFdLCBhcmdzW2ogKyAyXSwgYXJnc1tqICsgM10sIHgsIHkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnVwZGF0ZUN1cnZlUGF0aE1pbk1heChjdXJyZW50VHJhbnNmb3JtLCBzdGFydFgsIHN0YXJ0WSwgYXJnc1tqXSwgYXJnc1tqICsgMV0sIGFyZ3NbaiArIDJdLCBhcmdzW2ogKyAzXSwgeCwgeSwgbWluTWF4Rm9yQmV6aWVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaiArPSA2OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5jdXJ2ZVRvMjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRYID0geDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRZID0geTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmJlemllckN1cnZlVG8oeCwgeSwgYXJnc1tqXSwgYXJnc1tqICsgMV0sIGFyZ3NbaiArIDJdLCBhcmdzW2ogKyAzXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudXBkYXRlQ3VydmVQYXRoTWluTWF4KGN1cnJlbnRUcmFuc2Zvcm0sIHN0YXJ0WCwgc3RhcnRZLCB4LCB5LCBhcmdzW2pdLCBhcmdzW2ogKyAxXSwgYXJnc1tqICsgMl0sIGFyZ3NbaiArIDNdLCBtaW5NYXhGb3JCZXppZXIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gYXJnc1tqICsgMl07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBhcmdzW2ogKyAzXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaiArPSA0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5jdXJ2ZVRvMzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRYID0geDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRZID0geTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IGFyZ3NbaiArIDJdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gYXJnc1tqICsgM107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5iZXppZXJDdXJ2ZVRvKGFyZ3Nbal0sIGFyZ3NbaiArIDFdLCB4LCB5LCB4LCB5KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC51cGRhdGVDdXJ2ZVBhdGhNaW5NYXgoY3VycmVudFRyYW5zZm9ybSwgc3RhcnRYLCBzdGFydFksIGFyZ3Nbal0sIGFyZ3NbaiArIDFdLCB4LCB5LCB4LCB5LCBtaW5NYXhGb3JCZXppZXIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqICs9IDQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmNsb3NlUGF0aDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmNsb3NlUGF0aCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNTY2FsaW5nTWF0cml4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnVwZGF0ZVNjYWxpbmdQYXRoTWluTWF4KGN1cnJlbnRUcmFuc2Zvcm0sIG1pbk1heEZvckJlemllcik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5zZXRDdXJyZW50UG9pbnQoeCwgeSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNsb3NlUGF0aCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguY2xvc2VQYXRoKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0cm9rZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvbnN1bWVQYXRoID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdHggPSB0aGlzLmN0eDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3Ryb2tlQ29sb3IgPSB0aGlzLmN1cnJlbnQuc3Ryb2tlQ29sb3I7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5nbG9iYWxBbHBoYSA9IHRoaXMuY3VycmVudC5zdHJva2VBbHBoYTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY29udGVudFZpc2libGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3Ryb2tlQ29sb3IgPT09ICJvYmplY3QiICYmIHN0cm9rZUNvbG9yICE9PSBudWxsICYmIHN0cm9rZUNvbG9yICE9PSB2b2lkIDAgJiYgc3Ryb2tlQ29sb3IuZ2V0UGF0dGVybikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zYXZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnN0cm9rZVN0eWxlID0gc3Ryb2tlQ29sb3IuZ2V0UGF0dGVybihjdHgsIHRoaXMsICgwLCBfZGlzcGxheV91dGlscy5nZXRDdXJyZW50VHJhbnNmb3JtSW52ZXJzZSkoY3R4KSwgX3BhdHRlcm5faGVscGVyLlBhdGhUeXBlLlNUUk9LRSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNjYWxlQW5kU3Ryb2tlKGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgucmVzdG9yZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc2NhbGVBbmRTdHJva2UodHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbnN1bWVQYXRoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnN1bWVQYXRoKHRoaXMuY3VycmVudC5nZXRDbGlwcGVkUGF0aEJvdW5kaW5nQm94KCkpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5nbG9iYWxBbHBoYSA9IHRoaXMuY3VycmVudC5maWxsQWxwaGE7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNsb3NlU3Ryb2tlKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsb3NlUGF0aCgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cm9rZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmaWxsKCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgY29uc3VtZVBhdGggPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWxsQ29sb3IgPSB0aGlzLmN1cnJlbnQuZmlsbENvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpc1BhdHRlcm5GaWxsID0gdGhpcy5jdXJyZW50LnBhdHRlcm5GaWxsOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgbmVlZFJlc3RvcmUgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzUGF0dGVybkZpbGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zYXZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gZmlsbENvbG9yLmdldFBhdHRlcm4oY3R4LCB0aGlzLCAoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybUludmVyc2UpKGN0eCksIF9wYXR0ZXJuX2hlbHBlci5QYXRoVHlwZS5GSUxMKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5lZWRSZXN0b3JlID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbnRlcnNlY3QgPSB0aGlzLmN1cnJlbnQuZ2V0Q2xpcHBlZFBhdGhCb3VuZGluZ0JveCgpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jb250ZW50VmlzaWJsZSAmJiBpbnRlcnNlY3QgIT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnBlbmRpbmdFT0ZpbGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguZmlsbCgiZXZlbm9kZCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGVuZGluZ0VPRmlsbCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguZmlsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuZWVkUmVzdG9yZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29uc3VtZVBhdGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29uc3VtZVBhdGgoaW50ZXJzZWN0KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlb0ZpbGwoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGVuZGluZ0VPRmlsbCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsbCgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmaWxsU3Ryb2tlKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbGwoZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cm9rZShmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29uc3VtZVBhdGgoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW9GaWxsU3Ryb2tlKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBlbmRpbmdFT0ZpbGwgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbGxTdHJva2UoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2xvc2VGaWxsU3Ryb2tlKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsb3NlUGF0aCgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbGxTdHJva2UoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2xvc2VFT0ZpbGxTdHJva2UoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGVuZGluZ0VPRmlsbCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xvc2VQYXRoKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsbFN0cm9rZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbmRQYXRoKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnN1bWVQYXRoKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNsaXAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGVuZGluZ0NsaXAgPSBOT1JNQUxfQ0xJUDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW9DbGlwKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBlbmRpbmdDbGlwID0gRU9fQ0xJUDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYmVnaW5UZXh0KCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQudGV4dE1hdHJpeCA9IF91dGlsLklERU5USVRZX01BVFJJWDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnRleHRNYXRyaXhTY2FsZSA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC54ID0gdGhpcy5jdXJyZW50LmxpbmVYID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnkgPSB0aGlzLmN1cnJlbnQubGluZVkgPSAwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbmRUZXh0KCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXRocyA9IHRoaXMucGVuZGluZ1RleHRQYXRoczsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXRocyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguYmVnaW5QYXRoKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnNhdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmJlZ2luUGF0aCgpOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHBhdGggb2YgcGF0aHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zZXRUcmFuc2Zvcm0oLi4ucGF0aC50cmFuc2Zvcm0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnRyYW5zbGF0ZShwYXRoLngsIHBhdGgueSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoLmFkZFRvUGF0aChjdHgsIHBhdGguZm9udFNpemUpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5yZXN0b3JlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5jbGlwKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5iZWdpblBhdGgoKTsKICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucGVuZGluZ1RleHRQYXRoczsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0Q2hhclNwYWNpbmcoc3BhY2luZykgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuY2hhclNwYWNpbmcgPSBzcGFjaW5nOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzZXRXb3JkU3BhY2luZyhzcGFjaW5nKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC53b3JkU3BhY2luZyA9IHNwYWNpbmc7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldEhTY2FsZShzY2FsZSkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQudGV4dEhTY2FsZSA9IHNjYWxlIC8gMTAwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzZXRMZWFkaW5nKGxlYWRpbmcpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmxlYWRpbmcgPSAtbGVhZGluZzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0Rm9udChmb250UmVmTmFtZSwgc2l6ZSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmb250T2JqID0gdGhpcy5jb21tb25PYmpzLmdldChmb250UmVmTmFtZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmN1cnJlbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZm9udE9iaikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4ndCBmaW5kIGZvbnQgZm9yICR7Zm9udFJlZk5hbWV9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5mb250TWF0cml4ID0gZm9udE9iai5mb250TWF0cml4IHx8IF91dGlsLkZPTlRfSURFTlRJVFlfTUFUUklYOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudC5mb250TWF0cml4WzBdID09PSAwIHx8IGN1cnJlbnQuZm9udE1hdHJpeFszXSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJJbnZhbGlkIGZvbnQgbWF0cml4IGZvciBmb250ICIgKyBmb250UmVmTmFtZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpemUgPCAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gLXNpemU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LmZvbnREaXJlY3Rpb24gPSAtMTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQuZm9udERpcmVjdGlvbiA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmZvbnQgPSBmb250T2JqOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuZm9udFNpemUgPSBzaXplOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm9udE9iai5pc1R5cGUzRm9udCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5hbWUgPSBmb250T2JqLmxvYWRlZE5hbWUgfHwgInNhbnMtc2VyaWYiOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgYm9sZCA9ICJub3JtYWwiOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm9udE9iai5ibGFjaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9sZCA9ICI5MDAiOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGZvbnRPYmouYm9sZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9sZCA9ICJib2xkIjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpdGFsaWMgPSBmb250T2JqLml0YWxpYyA/ICJpdGFsaWMiIDogIm5vcm1hbCI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHR5cGVmYWNlID0gYCIke25hbWV9IiwgJHtmb250T2JqLmZhbGxiYWNrTmFtZX1gOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgYnJvd3NlckZvbnRTaXplID0gc2l6ZTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpemUgPCBNSU5fRk9OVF9TSVpFKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicm93c2VyRm9udFNpemUgPSBNSU5fRk9OVF9TSVpFOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHNpemUgPiBNQVhfRk9OVF9TSVpFKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicm93c2VyRm9udFNpemUgPSBNQVhfRk9OVF9TSVpFOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5mb250U2l6ZVNjYWxlID0gc2l6ZSAvIGJyb3dzZXJGb250U2l6ZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguZm9udCA9IGAke2l0YWxpY30gJHtib2xkfSAke2Jyb3dzZXJGb250U2l6ZX1weCAke3R5cGVmYWNlfWA7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldFRleHRSZW5kZXJpbmdNb2RlKG1vZGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnRleHRSZW5kZXJpbmdNb2RlID0gbW9kZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0VGV4dFJpc2UocmlzZSkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQudGV4dFJpc2UgPSByaXNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBtb3ZlVGV4dCh4LCB5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC54ID0gdGhpcy5jdXJyZW50LmxpbmVYICs9IHg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC55ID0gdGhpcy5jdXJyZW50LmxpbmVZICs9IHk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldExlYWRpbmdNb3ZlVGV4dCh4LCB5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0TGVhZGluZygteSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubW92ZVRleHQoeCwgeSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldFRleHRNYXRyaXgoYSwgYiwgYywgZCwgZSwgZikgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQudGV4dE1hdHJpeCA9IFthLCBiLCBjLCBkLCBlLCBmXTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnRleHRNYXRyaXhTY2FsZSA9IE1hdGguaHlwb3QoYSwgYik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC54ID0gdGhpcy5jdXJyZW50LmxpbmVYID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnkgPSB0aGlzLmN1cnJlbnQubGluZVkgPSAwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBuZXh0TGluZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tb3ZlVGV4dCgwLCB0aGlzLmN1cnJlbnQubGVhZGluZyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHBhaW50Q2hhcihjaGFyYWN0ZXIsIHgsIHksIHBhdHRlcm5UcmFuc2Zvcm0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmN1cnJlbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvbnQgPSBjdXJyZW50LmZvbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRleHRSZW5kZXJpbmdNb2RlID0gY3VycmVudC50ZXh0UmVuZGVyaW5nTW9kZTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZm9udFNpemUgPSBjdXJyZW50LmZvbnRTaXplIC8gY3VycmVudC5mb250U2l6ZVNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWxsU3Ryb2tlTW9kZSA9IHRleHRSZW5kZXJpbmdNb2RlICYgX3V0aWwuVGV4dFJlbmRlcmluZ01vZGUuRklMTF9TVFJPS0VfTUFTSzsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNBZGRUb1BhdGhTZXQgPSAhISh0ZXh0UmVuZGVyaW5nTW9kZSAmIF91dGlsLlRleHRSZW5kZXJpbmdNb2RlLkFERF9UT19QQVRIX0ZMQUcpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXR0ZXJuRmlsbCA9IGN1cnJlbnQucGF0dGVybkZpbGwgJiYgIWZvbnQubWlzc2luZ0ZpbGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhZGRUb1BhdGg7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmb250LmRpc2FibGVGb250RmFjZSB8fCBpc0FkZFRvUGF0aFNldCB8fCBwYXR0ZXJuRmlsbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkVG9QYXRoID0gZm9udC5nZXRQYXRoR2VuZXJhdG9yKHRoaXMuY29tbW9uT2JqcywgY2hhcmFjdGVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm9udC5kaXNhYmxlRm9udEZhY2UgfHwgcGF0dGVybkZpbGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zYXZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgudHJhbnNsYXRlKHgsIHkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmJlZ2luUGF0aCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkVG9QYXRoKGN0eCwgZm9udFNpemUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhdHRlcm5UcmFuc2Zvcm0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguc2V0VHJhbnNmb3JtKC4uLnBhdHRlcm5UcmFuc2Zvcm0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGxTdHJva2VNb2RlID09PSBfdXRpbC5UZXh0UmVuZGVyaW5nTW9kZS5GSUxMIHx8IGZpbGxTdHJva2VNb2RlID09PSBfdXRpbC5UZXh0UmVuZGVyaW5nTW9kZS5GSUxMX1NUUk9LRSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5maWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZmlsbFN0cm9rZU1vZGUgPT09IF91dGlsLlRleHRSZW5kZXJpbmdNb2RlLlNUUk9LRSB8fCBmaWxsU3Ryb2tlTW9kZSA9PT0gX3V0aWwuVGV4dFJlbmRlcmluZ01vZGUuRklMTF9TVFJPS0UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguc3Ryb2tlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgucmVzdG9yZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGxTdHJva2VNb2RlID09PSBfdXRpbC5UZXh0UmVuZGVyaW5nTW9kZS5GSUxMIHx8IGZpbGxTdHJva2VNb2RlID09PSBfdXRpbC5UZXh0UmVuZGVyaW5nTW9kZS5GSUxMX1NUUk9LRSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5maWxsVGV4dChjaGFyYWN0ZXIsIHgsIHkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGxTdHJva2VNb2RlID09PSBfdXRpbC5UZXh0UmVuZGVyaW5nTW9kZS5TVFJPS0UgfHwgZmlsbFN0cm9rZU1vZGUgPT09IF91dGlsLlRleHRSZW5kZXJpbmdNb2RlLkZJTExfU1RST0tFKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnN0cm9rZVRleHQoY2hhcmFjdGVyLCB4LCB5KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNBZGRUb1BhdGhTZXQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhdGhzID0gdGhpcy5wZW5kaW5nVGV4dFBhdGhzIHx8ICh0aGlzLnBlbmRpbmdUZXh0UGF0aHMgPSBbXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRocy5wdXNoKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm06ICgwLCBfZGlzcGxheV91dGlscy5nZXRDdXJyZW50VHJhbnNmb3JtKShjdHgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250U2l6ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGRUb1BhdGgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBpc0ZvbnRTdWJwaXhlbEFBRW5hYmxlZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dDogY3R4CiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSB0aGlzLmNhY2hlZENhbnZhc2VzLmdldENhbnZhcygiaXNGb250U3VicGl4ZWxBQUVuYWJsZWQiLCAxMCwgMTApOwogICAgICAgICAgICAgICAgICAgICAgICBjdHguc2NhbGUoMS41LCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmZpbGxUZXh0KCJJIiwgMCwgMTApOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gY3R4LmdldEltYWdlRGF0YSgwLCAwLCAxMCwgMTApLmRhdGE7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlbmFibGVkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAzOyBpIDwgZGF0YS5sZW5ndGg7IGkgKz0gNCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGFbaV0gPiAwICYmIGRhdGFbaV0gPCAyNTUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImlzRm9udFN1YnBpeGVsQUFFbmFibGVkIiwgZW5hYmxlZCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNob3dUZXh0KGdseXBocykgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5jdXJyZW50OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmb250ID0gY3VycmVudC5mb250OwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm9udC5pc1R5cGUzRm9udCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2hvd1R5cGUzVGV4dChnbHlwaHMpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvbnRTaXplID0gY3VycmVudC5mb250U2l6ZTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZvbnRTaXplID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmb250U2l6ZVNjYWxlID0gY3VycmVudC5mb250U2l6ZVNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGFyU3BhY2luZyA9IGN1cnJlbnQuY2hhclNwYWNpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdvcmRTcGFjaW5nID0gY3VycmVudC53b3JkU3BhY2luZzsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZm9udERpcmVjdGlvbiA9IGN1cnJlbnQuZm9udERpcmVjdGlvbjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGV4dEhTY2FsZSA9IGN1cnJlbnQudGV4dEhTY2FsZSAqIGZvbnREaXJlY3Rpb247CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGdseXBoc0xlbmd0aCA9IGdseXBocy5sZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHZlcnRpY2FsID0gZm9udC52ZXJ0aWNhbDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3BhY2luZ0RpciA9IHZlcnRpY2FsID8gMSA6IC0xOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWZhdWx0Vk1ldHJpY3MgPSBmb250LmRlZmF1bHRWTWV0cmljczsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2lkdGhBZHZhbmNlU2NhbGUgPSBmb250U2l6ZSAqIGN1cnJlbnQuZm9udE1hdHJpeFswXTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2ltcGxlRmlsbFRleHQgPSBjdXJyZW50LnRleHRSZW5kZXJpbmdNb2RlID09PSBfdXRpbC5UZXh0UmVuZGVyaW5nTW9kZS5GSUxMICYmICFmb250LmRpc2FibGVGb250RmFjZSAmJiAhY3VycmVudC5wYXR0ZXJuRmlsbDsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnNhdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnRyYW5zZm9ybSguLi5jdXJyZW50LnRleHRNYXRyaXgpOwogICAgICAgICAgICAgICAgICAgICAgICBjdHgudHJhbnNsYXRlKGN1cnJlbnQueCwgY3VycmVudC55ICsgY3VycmVudC50ZXh0UmlzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmb250RGlyZWN0aW9uID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnNjYWxlKHRleHRIU2NhbGUsIC0xKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zY2FsZSh0ZXh0SFNjYWxlLCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcGF0dGVyblRyYW5zZm9ybTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnQucGF0dGVybkZpbGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zYXZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXR0ZXJuID0gY3VycmVudC5maWxsQ29sb3IuZ2V0UGF0dGVybihjdHgsIHRoaXMsICgwLCBfZGlzcGxheV91dGlscy5nZXRDdXJyZW50VHJhbnNmb3JtSW52ZXJzZSkoY3R4KSwgX3BhdHRlcm5faGVscGVyLlBhdGhUeXBlLkZJTEwpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVyblRyYW5zZm9ybSA9ICgwLCBfZGlzcGxheV91dGlscy5nZXRDdXJyZW50VHJhbnNmb3JtKShjdHgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSBwYXR0ZXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBsaW5lV2lkdGggPSBjdXJyZW50LmxpbmVXaWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2NhbGUgPSBjdXJyZW50LnRleHRNYXRyaXhTY2FsZTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNjYWxlID09PSAwIHx8IGxpbmVXaWR0aCA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlsbFN0cm9rZU1vZGUgPSBjdXJyZW50LnRleHRSZW5kZXJpbmdNb2RlICYgX3V0aWwuVGV4dFJlbmRlcmluZ01vZGUuRklMTF9TVFJPS0VfTUFTSzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmaWxsU3Ryb2tlTW9kZSA9PT0gX3V0aWwuVGV4dFJlbmRlcmluZ01vZGUuU1RST0tFIHx8IGZpbGxTdHJva2VNb2RlID09PSBfdXRpbC5UZXh0UmVuZGVyaW5nTW9kZS5GSUxMX1NUUk9LRSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVXaWR0aCA9IHRoaXMuZ2V0U2luZ2xlUGl4ZWxXaWR0aCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZVdpZHRoIC89IHNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmb250U2l6ZVNjYWxlICE9PSAxLjApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zY2FsZShmb250U2l6ZVNjYWxlLCBmb250U2l6ZVNjYWxlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVXaWR0aCAvPSBmb250U2l6ZVNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5saW5lV2lkdGggPSBsaW5lV2lkdGg7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmb250LmlzSW52YWxpZFBERmpzRm9udCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hhcnMgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCB3aWR0aCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGdseXBoIG9mIGdseXBocykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXJzLnB1c2goZ2x5cGgudW5pY29kZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggKz0gZ2x5cGgud2lkdGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguZmlsbFRleHQoY2hhcnMuam9pbigiIiksIDAsIDApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC54ICs9IHdpZHRoICogd2lkdGhBZHZhbmNlU2NhbGUgKiB0ZXh0SFNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcG9zZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBsZXQgeCA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgZ2x5cGhzTGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGdseXBoID0gZ2x5cGhzW2ldOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBnbHlwaCA9PT0gIm51bWJlciIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ICs9IHNwYWNpbmdEaXIgKiBnbHlwaCAqIGZvbnRTaXplIC8gMTAwMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZXN0b3JlTmVlZGVkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzcGFjaW5nID0gKGdseXBoLmlzU3BhY2UgPyB3b3JkU3BhY2luZyA6IDApICsgY2hhclNwYWNpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGFyYWN0ZXIgPSBnbHlwaC5mb250Q2hhcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFjY2VudCA9IGdseXBoLmFjY2VudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzY2FsZWRYLCBzY2FsZWRZOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHdpZHRoID0gZ2x5cGgud2lkdGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmVydGljYWwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB2bWV0cmljID0gZ2x5cGgudm1ldHJpYyB8fCBkZWZhdWx0Vk1ldHJpY3M7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdnggPSAtKGdseXBoLnZtZXRyaWMgPyB2bWV0cmljWzFdIDogd2lkdGggKiAwLjUpICogd2lkdGhBZHZhbmNlU2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdnkgPSB2bWV0cmljWzJdICogd2lkdGhBZHZhbmNlU2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSB2bWV0cmljID8gLXZtZXRyaWNbMF0gOiB3aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZWRYID0gdnggLyBmb250U2l6ZVNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlZFkgPSAoeCArIHZ5KSAvIGZvbnRTaXplU2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlZFggPSB4IC8gZm9udFNpemVTY2FsZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZWRZID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmb250LnJlbWVhc3VyZSAmJiB3aWR0aCA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZWFzdXJlZFdpZHRoID0gY3R4Lm1lYXN1cmVUZXh0KGNoYXJhY3Rlcikud2lkdGggKiAxMDAwIC8gZm9udFNpemUgKiBmb250U2l6ZVNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3aWR0aCA8IG1lYXN1cmVkV2lkdGggJiYgdGhpcy5pc0ZvbnRTdWJwaXhlbEFBRW5hYmxlZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGFyYWN0ZXJTY2FsZVggPSB3aWR0aCAvIG1lYXN1cmVkV2lkdGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RvcmVOZWVkZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguc2F2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguc2NhbGUoY2hhcmFjdGVyU2NhbGVYLCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVkWCAvPSBjaGFyYWN0ZXJTY2FsZVg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh3aWR0aCAhPT0gbWVhc3VyZWRXaWR0aCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZWRYICs9ICh3aWR0aCAtIG1lYXN1cmVkV2lkdGgpIC8gMjAwMCAqIGZvbnRTaXplIC8gZm9udFNpemVTY2FsZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jb250ZW50VmlzaWJsZSAmJiAoZ2x5cGguaXNJbkZvbnQgfHwgZm9udC5taXNzaW5nRmlsZSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltcGxlRmlsbFRleHQgJiYgIWFjY2VudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguZmlsbFRleHQoY2hhcmFjdGVyLCBzY2FsZWRYLCBzY2FsZWRZKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhaW50Q2hhcihjaGFyYWN0ZXIsIHNjYWxlZFgsIHNjYWxlZFksIHBhdHRlcm5UcmFuc2Zvcm0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWNjZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzY2FsZWRBY2NlbnRYID0gc2NhbGVkWCArIGZvbnRTaXplICogYWNjZW50Lm9mZnNldC54IC8gZm9udFNpemVTY2FsZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNjYWxlZEFjY2VudFkgPSBzY2FsZWRZIC0gZm9udFNpemUgKiBhY2NlbnQub2Zmc2V0LnkgLyBmb250U2l6ZVNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYWludENoYXIoYWNjZW50LmZvbnRDaGFyLCBzY2FsZWRBY2NlbnRYLCBzY2FsZWRBY2NlbnRZLCBwYXR0ZXJuVHJhbnNmb3JtKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjaGFyV2lkdGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmVydGljYWwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFyV2lkdGggPSB3aWR0aCAqIHdpZHRoQWR2YW5jZVNjYWxlIC0gc3BhY2luZyAqIGZvbnREaXJlY3Rpb247CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXJXaWR0aCA9IHdpZHRoICogd2lkdGhBZHZhbmNlU2NhbGUgKyBzcGFjaW5nICogZm9udERpcmVjdGlvbjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggKz0gY2hhcldpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3RvcmVOZWVkZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgucmVzdG9yZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2ZXJ0aWNhbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC55IC09IHg7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnggKz0geCAqIHRleHRIU2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wb3NlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNob3dUeXBlM1RleHQoZ2x5cGhzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5jdXJyZW50OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmb250ID0gY3VycmVudC5mb250OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmb250U2l6ZSA9IGN1cnJlbnQuZm9udFNpemU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvbnREaXJlY3Rpb24gPSBjdXJyZW50LmZvbnREaXJlY3Rpb247CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNwYWNpbmdEaXIgPSBmb250LnZlcnRpY2FsID8gMSA6IC0xOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGFyU3BhY2luZyA9IGN1cnJlbnQuY2hhclNwYWNpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdvcmRTcGFjaW5nID0gY3VycmVudC53b3JkU3BhY2luZzsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGV4dEhTY2FsZSA9IGN1cnJlbnQudGV4dEhTY2FsZSAqIGZvbnREaXJlY3Rpb247CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvbnRNYXRyaXggPSBjdXJyZW50LmZvbnRNYXRyaXggfHwgX3V0aWwuRk9OVF9JREVOVElUWV9NQVRSSVg7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGdseXBoc0xlbmd0aCA9IGdseXBocy5sZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzVGV4dEludmlzaWJsZSA9IGN1cnJlbnQudGV4dFJlbmRlcmluZ01vZGUgPT09IF91dGlsLlRleHRSZW5kZXJpbmdNb2RlLklOVklTSUJMRTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGksIGdseXBoLCB3aWR0aCwgc3BhY2luZ0xlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVGV4dEludmlzaWJsZSB8fCBmb250U2l6ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NhY2hlZFNjYWxlRm9yU3Ryb2tpbmcgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYWNoZWRHZXRTaW5nbGVQaXhlbFdpZHRoID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnNhdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnRyYW5zZm9ybSguLi5jdXJyZW50LnRleHRNYXRyaXgpOwogICAgICAgICAgICAgICAgICAgICAgICBjdHgudHJhbnNsYXRlKGN1cnJlbnQueCwgY3VycmVudC55KTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnNjYWxlKHRleHRIU2NhbGUsIGZvbnREaXJlY3Rpb24pOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgZ2x5cGhzTGVuZ3RoOyArK2kpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdseXBoID0gZ2x5cGhzW2ldOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBnbHlwaCA9PT0gIm51bWJlciIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGFjaW5nTGVuZ3RoID0gc3BhY2luZ0RpciAqIGdseXBoICogZm9udFNpemUgLyAxMDAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnRyYW5zbGF0ZShzcGFjaW5nTGVuZ3RoLCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnggKz0gc3BhY2luZ0xlbmd0aCAqIHRleHRIU2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzcGFjaW5nID0gKGdseXBoLmlzU3BhY2UgPyB3b3JkU3BhY2luZyA6IDApICsgY2hhclNwYWNpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvcGVyYXRvckxpc3QgPSBmb250LmNoYXJQcm9jT3BlcmF0b3JMaXN0W2dseXBoLm9wZXJhdG9yTGlzdElkXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghb3BlcmF0b3JMaXN0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBUeXBlMyBjaGFyYWN0ZXIgIiR7Z2x5cGgub3BlcmF0b3JMaXN0SWR9IiBpcyBub3QgYXZhaWxhYmxlLmApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY29udGVudFZpc2libGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NpbmdUeXBlMyA9IGdseXBoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2F2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zY2FsZShmb250U2l6ZSwgZm9udFNpemUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC50cmFuc2Zvcm0oLi4uZm9udE1hdHJpeCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5leGVjdXRlT3BlcmF0b3JMaXN0KG9wZXJhdG9yTGlzdCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXN0b3JlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1lZCA9IF91dGlsLlV0aWwuYXBwbHlUcmFuc2Zvcm0oW2dseXBoLndpZHRoLCAwXSwgZm9udE1hdHJpeCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCA9IHRyYW5zZm9ybWVkWzBdICogZm9udFNpemUgKyBzcGFjaW5nOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnRyYW5zbGF0ZSh3aWR0aCwgMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnggKz0gd2lkdGggKiB0ZXh0SFNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5yZXN0b3JlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc2luZ1R5cGUzID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0Q2hhcldpZHRoKHhXaWR0aCwgeVdpZHRoKSB7fQogICAgICAgICAgICAgICAgICAgIHNldENoYXJXaWR0aEFuZEJvdW5kcyh4V2lkdGgsIHlXaWR0aCwgbGx4LCBsbHksIHVyeCwgdXJ5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnJlY3QobGx4LCBsbHksIHVyeCAtIGxseCwgdXJ5IC0gbGx5KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguY2xpcCgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVuZFBhdGgoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0Q29sb3JOX1BhdHRlcm4oSVIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHBhdHRlcm47CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChJUlswXSA9PT0gIlRpbGluZ1BhdHRlcm4iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb2xvciA9IElSWzFdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmFzZVRyYW5zZm9ybSA9IHRoaXMuYmFzZVRyYW5zZm9ybSB8fCAoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybSkodGhpcy5jdHgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FudmFzR3JhcGhpY3NGYWN0b3J5ID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZUNhbnZhc0dyYXBoaWNzOiBjdHggPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IENhbnZhc0dyYXBoaWNzKGN0eCwgdGhpcy5jb21tb25PYmpzLCB0aGlzLm9ianMsIHRoaXMuY2FudmFzRmFjdG9yeSwgdGhpcy5maWx0ZXJGYWN0b3J5LCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25hbENvbnRlbnRDb25maWc6IHRoaXMub3B0aW9uYWxDb250ZW50Q29uZmlnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya2VkQ29udGVudFN0YWNrOiB0aGlzLm1hcmtlZENvbnRlbnRTdGFjawogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9IG5ldyBfcGF0dGVybl9oZWxwZXIuVGlsaW5nUGF0dGVybihJUiwgY29sb3IsIHRoaXMuY3R4LCBjYW52YXNHcmFwaGljc0ZhY3RvcnksIGJhc2VUcmFuc2Zvcm0pOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9IHRoaXMuX2dldFBhdHRlcm4oSVJbMV0sIElSWzJdKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0dGVybjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0U3Ryb2tlQ29sb3JOKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuc3Ryb2tlQ29sb3IgPSB0aGlzLmdldENvbG9yTl9QYXR0ZXJuKGFyZ3VtZW50cyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldEZpbGxDb2xvck4oKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5maWxsQ29sb3IgPSB0aGlzLmdldENvbG9yTl9QYXR0ZXJuKGFyZ3VtZW50cyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5wYXR0ZXJuRmlsbCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldFN0cm9rZVJHQkNvbG9yKHIsIGcsIGIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29sb3IgPSBfdXRpbC5VdGlsLm1ha2VIZXhDb2xvcihyLCBnLCBiKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguc3Ryb2tlU3R5bGUgPSBjb2xvcjsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnN0cm9rZUNvbG9yID0gY29sb3I7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldEZpbGxSR0JDb2xvcihyLCBnLCBiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbG9yID0gX3V0aWwuVXRpbC5tYWtlSGV4Q29sb3IociwgZywgYik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LmZpbGxTdHlsZSA9IGNvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuZmlsbENvbG9yID0gY29sb3I7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5wYXR0ZXJuRmlsbCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfZ2V0UGF0dGVybihvYmpJZCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgbWF0cml4ID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcGF0dGVybjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY2FjaGVkUGF0dGVybnMuaGFzKG9iaklkKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9IHRoaXMuY2FjaGVkUGF0dGVybnMuZ2V0KG9iaklkKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAoMCwgX3BhdHRlcm5faGVscGVyLmdldFNoYWRpbmdQYXR0ZXJuKSh0aGlzLmdldE9iamVjdChvYmpJZCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYWNoZWRQYXR0ZXJucy5zZXQob2JqSWQsIHBhdHRlcm4pOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRyaXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4ubWF0cml4ID0gbWF0cml4OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXR0ZXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzaGFkaW5nRmlsbChvYmpJZCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29udGVudFZpc2libGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdHggPSB0aGlzLmN0eDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zYXZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhdHRlcm4gPSB0aGlzLl9nZXRQYXR0ZXJuKG9iaklkKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9IHBhdHRlcm4uZ2V0UGF0dGVybihjdHgsIHRoaXMsICgwLCBfZGlzcGxheV91dGlscy5nZXRDdXJyZW50VHJhbnNmb3JtSW52ZXJzZSkoY3R4KSwgX3BhdHRlcm5faGVscGVyLlBhdGhUeXBlLlNIQURJTkcpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbnYgPSAoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybUludmVyc2UpKGN0eCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbnZhcyA9IGN0eC5jYW52YXM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3aWR0aCA9IGNhbnZhcy53aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGNhbnZhcy5oZWlnaHQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBibCA9IF91dGlsLlV0aWwuYXBwbHlUcmFuc2Zvcm0oWzAsIDBdLCBpbnYpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYnIgPSBfdXRpbC5VdGlsLmFwcGx5VHJhbnNmb3JtKFswLCBoZWlnaHRdLCBpbnYpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdWwgPSBfdXRpbC5VdGlsLmFwcGx5VHJhbnNmb3JtKFt3aWR0aCwgMF0sIGludik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1ciA9IF91dGlsLlV0aWwuYXBwbHlUcmFuc2Zvcm0oW3dpZHRoLCBoZWlnaHRdLCBpbnYpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeDAgPSBNYXRoLm1pbihibFswXSwgYnJbMF0sIHVsWzBdLCB1clswXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB5MCA9IE1hdGgubWluKGJsWzFdLCBiclsxXSwgdWxbMV0sIHVyWzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHgxID0gTWF0aC5tYXgoYmxbMF0sIGJyWzBdLCB1bFswXSwgdXJbMF0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeTEgPSBNYXRoLm1heChibFsxXSwgYnJbMV0sIHVsWzFdLCB1clsxXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5maWxsUmVjdCh4MCwgeTAsIHgxIC0geDAsIHkxIC0geTApOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguZmlsbFJlY3QoLTFlMTAsIC0xZTEwLCAyZTEwLCAyZTEwKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBvc2UodGhpcy5jdXJyZW50LmdldENsaXBwZWRQYXRoQm91bmRpbmdCb3goKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzdG9yZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBiZWdpbklubGluZUltYWdlKCkgewogICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJTaG91bGQgbm90IGNhbGwgYmVnaW5JbmxpbmVJbWFnZSIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBiZWdpbkltYWdlRGF0YSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiU2hvdWxkIG5vdCBjYWxsIGJlZ2luSW1hZ2VEYXRhIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHBhaW50Rm9ybVhPYmplY3RCZWdpbihtYXRyaXgsIGJib3gpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbnRlbnRWaXNpYmxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zYXZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmFzZVRyYW5zZm9ybVN0YWNrLnB1c2godGhpcy5iYXNlVHJhbnNmb3JtKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkobWF0cml4KSAmJiBtYXRyaXgubGVuZ3RoID09PSA2KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYW5zZm9ybSguLi5tYXRyaXgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmFzZVRyYW5zZm9ybSA9ICgwLCBfZGlzcGxheV91dGlscy5nZXRDdXJyZW50VHJhbnNmb3JtKSh0aGlzLmN0eCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiYm94KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3aWR0aCA9IGJib3hbMl0gLSBiYm94WzBdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gYmJveFszXSAtIGJib3hbMV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5yZWN0KGJib3hbMF0sIGJib3hbMV0sIHdpZHRoLCBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnVwZGF0ZVJlY3RNaW5NYXgoKDAsIF9kaXNwbGF5X3V0aWxzLmdldEN1cnJlbnRUcmFuc2Zvcm0pKHRoaXMuY3R4KSwgYmJveCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsaXAoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5kUGF0aCgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHBhaW50Rm9ybVhPYmplY3RFbmQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb250ZW50VmlzaWJsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzdG9yZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJhc2VUcmFuc2Zvcm0gPSB0aGlzLmJhc2VUcmFuc2Zvcm1TdGFjay5wb3AoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYmVnaW5Hcm91cChncm91cCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29udGVudFZpc2libGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNhdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5TTWFza01vZGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5kU01hc2tNb2RlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuYWN0aXZlU01hc2sgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRDdHggPSB0aGlzLmN0eDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFncm91cC5pc29sYXRlZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLmluZm8pKCJUT0RPOiBTdXBwb3J0IG5vbi1pc29sYXRlZCBncm91cHMuIik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdyb3VwLmtub2Nrb3V0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoIktub2Nrb3V0IGdyb3VwcyBub3Qgc3VwcG9ydGVkLiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRUcmFuc2Zvcm0gPSAoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybSkoY3VycmVudEN0eCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChncm91cC5tYXRyaXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRDdHgudHJhbnNmb3JtKC4uLmdyb3VwLm1hdHJpeCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFncm91cC5iYm94KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkJvdW5kaW5nIGJveCBpcyByZXF1aXJlZC4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBsZXQgYm91bmRzID0gX3V0aWwuVXRpbC5nZXRBeGlhbEFsaWduZWRCb3VuZGluZ0JveChncm91cC5iYm94LCAoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybSkoY3VycmVudEN0eCkpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW52YXNCb3VuZHMgPSBbMCwgMCwgY3VycmVudEN0eC5jYW52YXMud2lkdGgsIGN1cnJlbnRDdHguY2FudmFzLmhlaWdodF07CiAgICAgICAgICAgICAgICAgICAgICAgIGJvdW5kcyA9IF91dGlsLlV0aWwuaW50ZXJzZWN0KGJvdW5kcywgY2FudmFzQm91bmRzKSB8fCBbMCwgMCwgMCwgMF07CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldFggPSBNYXRoLmZsb29yKGJvdW5kc1swXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldFkgPSBNYXRoLmZsb29yKGJvdW5kc1sxXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkcmF3bldpZHRoID0gTWF0aC5tYXgoTWF0aC5jZWlsKGJvdW5kc1syXSkgLSBvZmZzZXRYLCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRyYXduSGVpZ2h0ID0gTWF0aC5tYXgoTWF0aC5jZWlsKGJvdW5kc1szXSkgLSBvZmZzZXRZLCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNjYWxlWCA9IDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZVkgPSAxOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZHJhd25XaWR0aCA+IE1BWF9HUk9VUF9TSVpFKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZVggPSBkcmF3bldpZHRoIC8gTUFYX0dST1VQX1NJWkU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcmF3bldpZHRoID0gTUFYX0dST1VQX1NJWkU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRyYXduSGVpZ2h0ID4gTUFYX0dST1VQX1NJWkUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlWSA9IGRyYXduSGVpZ2h0IC8gTUFYX0dST1VQX1NJWkU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcmF3bkhlaWdodCA9IE1BWF9HUk9VUF9TSVpFOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5zdGFydE5ld1BhdGhBbmRDbGlwQm94KFswLCAwLCBkcmF3bldpZHRoLCBkcmF3bkhlaWdodF0pOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgY2FjaGVJZCA9ICJncm91cEF0IiArIHRoaXMuZ3JvdXBMZXZlbDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdyb3VwLnNtYXNrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWNoZUlkICs9ICJfc21hc2tfIiArIHRoaXMuc21hc2tDb3VudGVyKysgJSAyOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNjcmF0Y2hDYW52YXMgPSB0aGlzLmNhY2hlZENhbnZhc2VzLmdldENhbnZhcyhjYWNoZUlkLCBkcmF3bldpZHRoLCBkcmF3bkhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGdyb3VwQ3R4ID0gc2NyYXRjaENhbnZhcy5jb250ZXh0OwogICAgICAgICAgICAgICAgICAgICAgICBncm91cEN0eC5zY2FsZSgxIC8gc2NhbGVYLCAxIC8gc2NhbGVZKTsKICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXBDdHgudHJhbnNsYXRlKC1vZmZzZXRYLCAtb2Zmc2V0WSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwQ3R4LnRyYW5zZm9ybSguLi5jdXJyZW50VHJhbnNmb3JtKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdyb3VwLnNtYXNrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNtYXNrU3RhY2sucHVzaCh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzOiBzY3JhdGNoQ2FudmFzLmNhbnZhcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0OiBncm91cEN0eCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRYLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldFksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVYLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlWSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJ0eXBlOiBncm91cC5zbWFzay5zdWJ0eXBlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhY2tkcm9wOiBncm91cC5zbWFzay5iYWNrZHJvcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zlck1hcDogZ3JvdXAuc21hc2sudHJhbnNmZXJNYXAgfHwgbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydFRyYW5zZm9ybUludmVyc2U6IG51bGwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudEN0eC5zZXRUcmFuc2Zvcm0oMSwgMCwgMCwgMSwgMCwgMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Q3R4LnRyYW5zbGF0ZShvZmZzZXRYLCBvZmZzZXRZKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRDdHguc2NhbGUoc2NhbGVYLCBzY2FsZVkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudEN0eC5zYXZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29weUN0eFN0YXRlKGN1cnJlbnRDdHgsIGdyb3VwQ3R4KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHggPSBncm91cEN0eDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRHU3RhdGUoW1siQk0iLCAic291cmNlLW92ZXIiXSwgWyJjYSIsIDFdLCBbIkNBIiwgMV1dKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5ncm91cFN0YWNrLnB1c2goY3VycmVudEN0eCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ3JvdXBMZXZlbCsrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbmRHcm91cChncm91cCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29udGVudFZpc2libGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmdyb3VwTGV2ZWwtLTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZ3JvdXBDdHggPSB0aGlzLmN0eDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5ncm91cFN0YWNrLnBvcCgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eCA9IGN0eDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguaW1hZ2VTbW9vdGhpbmdFbmFibGVkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChncm91cC5zbWFzaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50ZW1wU01hc2sgPSB0aGlzLnNtYXNrU3RhY2sucG9wKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc3RvcmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnJlc3RvcmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRNdHggPSAoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybSkodGhpcy5jdHgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXN0b3JlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5zYXZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5zZXRUcmFuc2Zvcm0oLi4uY3VycmVudE10eCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaXJ0eUJveCA9IF91dGlsLlV0aWwuZ2V0QXhpYWxBbGlnbmVkQm91bmRpbmdCb3goWzAsIDAsIGdyb3VwQ3R4LmNhbnZhcy53aWR0aCwgZ3JvdXBDdHguY2FudmFzLmhlaWdodF0sIGN1cnJlbnRNdHgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguZHJhd0ltYWdlKGdyb3VwQ3R4LmNhbnZhcywgMCwgMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5yZXN0b3JlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBvc2UoZGlydHlCb3gpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJlZ2luQW5ub3RhdGlvbihpZCwgcmVjdCwgdHJhbnNmb3JtLCBtYXRyaXgsIGhhc093bkNhbnZhcykgewogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9yZXN0b3JlSW5pdGlhbFN0YXRlLCBfcmVzdG9yZUluaXRpYWxTdGF0ZTIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0Q3R4VG9EZWZhdWx0KHRoaXMuY3R4KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguc2F2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNhdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuYmFzZVRyYW5zZm9ybSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguc2V0VHJhbnNmb3JtKC4uLnRoaXMuYmFzZVRyYW5zZm9ybSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVjdCkgJiYgcmVjdC5sZW5ndGggPT09IDQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gcmVjdFsyXSAtIHJlY3RbMF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHQgPSByZWN0WzNdIC0gcmVjdFsxXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChoYXNPd25DYW52YXMgJiYgdGhpcy5hbm5vdGF0aW9uQ2FudmFzTWFwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gdHJhbnNmb3JtLnNsaWNlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtWzRdIC09IHJlY3RbMF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtWzVdIC09IHJlY3RbMV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdCA9IHJlY3Quc2xpY2UoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN0WzBdID0gcmVjdFsxXSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdFsyXSA9IHdpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3RbM10gPSBoZWlnaHQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW3NjYWxlWCwgc2NhbGVZXSA9IF91dGlsLlV0aWwuc2luZ3VsYXJWYWx1ZURlY29tcG9zZTJkU2NhbGUoKDAsIF9kaXNwbGF5X3V0aWxzLmdldEN1cnJlbnRUcmFuc2Zvcm0pKHRoaXMuY3R4KSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3cG9ydFNjYWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FudmFzV2lkdGggPSBNYXRoLmNlaWwod2lkdGggKiB0aGlzLm91dHB1dFNjYWxlWCAqIHZpZXdwb3J0U2NhbGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbnZhc0hlaWdodCA9IE1hdGguY2VpbChoZWlnaHQgKiB0aGlzLm91dHB1dFNjYWxlWSAqIHZpZXdwb3J0U2NhbGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYW5ub3RhdGlvbkNhbnZhcyA9IHRoaXMuY2FudmFzRmFjdG9yeS5jcmVhdGUoY2FudmFzV2lkdGgsIGNhbnZhc0hlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYW52YXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gdGhpcy5hbm5vdGF0aW9uQ2FudmFzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYW5ub3RhdGlvbkNhbnZhc01hcC5zZXQoaWQsIGNhbnZhcyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hbm5vdGF0aW9uQ2FudmFzLnNhdmVkQ3R4ID0gdGhpcy5jdHg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHggPSBjb250ZXh0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnNldFRyYW5zZm9ybShzY2FsZVgsIDAsIDAsIC1zY2FsZVksIDAsIGhlaWdodCAqIHNjYWxlWSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzZXRDdHhUb0RlZmF1bHQodGhpcy5jdHgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNldEN0eFRvRGVmYXVsdCh0aGlzLmN0eCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHgucmVjdChyZWN0WzBdLCByZWN0WzFdLCB3aWR0aCwgaGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5jbGlwKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmRQYXRoKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50ID0gbmV3IENhbnZhc0V4dHJhU3RhdGUodGhpcy5jdHguY2FudmFzLndpZHRoLCB0aGlzLmN0eC5jYW52YXMuaGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc2Zvcm0oLi4udHJhbnNmb3JtKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc2Zvcm0oLi4ubWF0cml4KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW5kQW5ub3RhdGlvbigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuYW5ub3RhdGlvbkNhbnZhcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHggPSB0aGlzLmFubm90YXRpb25DYW52YXMuc2F2ZWRDdHg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5hbm5vdGF0aW9uQ2FudmFzLnNhdmVkQ3R4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuYW5ub3RhdGlvbkNhbnZhczsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBwYWludEltYWdlTWFza1hPYmplY3QoaW1nKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb250ZW50VmlzaWJsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvdW50ID0gaW1nLmNvdW50OwogICAgICAgICAgICAgICAgICAgICAgICBpbWcgPSB0aGlzLmdldE9iamVjdChpbWcuZGF0YSwgaW1nKTsKICAgICAgICAgICAgICAgICAgICAgICAgaW1nLmNvdW50ID0gY291bnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBnbHlwaCA9IHRoaXMucHJvY2Vzc2luZ1R5cGUzOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2x5cGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnbHlwaC5jb21waWxlZCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2x5cGguY29tcGlsZWQgPSBjb21waWxlVHlwZTNHbHlwaChpbWcpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdseXBoLmNvbXBpbGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2x5cGguY29tcGlsZWQoY3R4KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWFzayA9IHRoaXMuX2NyZWF0ZU1hc2tDYW52YXMoaW1nKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWFza0NhbnZhcyA9IG1hc2suY2FudmFzOwogICAgICAgICAgICAgICAgICAgICAgICBjdHguc2F2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICBjdHguc2V0VHJhbnNmb3JtKDEsIDAsIDAsIDEsIDAsIDApOwogICAgICAgICAgICAgICAgICAgICAgICBjdHguZHJhd0ltYWdlKG1hc2tDYW52YXMsIG1hc2sub2Zmc2V0WCwgbWFzay5vZmZzZXRZKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wb3NlKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHBhaW50SW1hZ2VNYXNrWE9iamVjdFJlcGVhdChpbWcsIHNjYWxlWCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgc2tld1ggPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBza2V3WSA9IGFyZ3VtZW50cy5sZW5ndGggPiAzICYmIGFyZ3VtZW50c1szXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzNdIDogMDsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNjYWxlWSA9IGFyZ3VtZW50cy5sZW5ndGggPiA0ID8gYXJndW1lbnRzWzRdIDogdW5kZWZpbmVkOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcG9zaXRpb25zID0gYXJndW1lbnRzLmxlbmd0aCA+IDUgPyBhcmd1bWVudHNbNV0gOiB1bmRlZmluZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb250ZW50VmlzaWJsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGltZyA9IHRoaXMuZ2V0T2JqZWN0KGltZy5kYXRhLCBpbWcpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdHggPSB0aGlzLmN0eDsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnNhdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudFRyYW5zZm9ybSA9ICgwLCBfZGlzcGxheV91dGlscy5nZXRDdXJyZW50VHJhbnNmb3JtKShjdHgpOwogICAgICAgICAgICAgICAgICAgICAgICBjdHgudHJhbnNmb3JtKHNjYWxlWCwgc2tld1gsIHNrZXdZLCBzY2FsZVksIDAsIDApOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXNrID0gdGhpcy5fY3JlYXRlTWFza0NhbnZhcyhpbWcpOwogICAgICAgICAgICAgICAgICAgICAgICBjdHguc2V0VHJhbnNmb3JtKDEsIDAsIDAsIDEsIG1hc2sub2Zmc2V0WCAtIGN1cnJlbnRUcmFuc2Zvcm1bNF0sIG1hc2sub2Zmc2V0WSAtIGN1cnJlbnRUcmFuc2Zvcm1bNV0pOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBwb3NpdGlvbnMubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdHJhbnMgPSBfdXRpbC5VdGlsLnRyYW5zZm9ybShjdXJyZW50VHJhbnNmb3JtLCBbc2NhbGVYLCBza2V3WCwgc2tld1ksIHNjYWxlWSwgcG9zaXRpb25zW2ldLCBwb3NpdGlvbnNbaSArIDFdXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbeCwgeV0gPSBfdXRpbC5VdGlsLmFwcGx5VHJhbnNmb3JtKFswLCAwXSwgdHJhbnMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmRyYXdJbWFnZShtYXNrLmNhbnZhcywgeCwgeSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnJlc3RvcmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21wb3NlKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHBhaW50SW1hZ2VNYXNrWE9iamVjdEdyb3VwKGltYWdlcykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29udGVudFZpc2libGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdHggPSB0aGlzLmN0eDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlsbENvbG9yID0gdGhpcy5jdXJyZW50LmZpbGxDb2xvcjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNQYXR0ZXJuRmlsbCA9IHRoaXMuY3VycmVudC5wYXR0ZXJuRmlsbDsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBpbWFnZSBvZiBpbWFnZXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBpbWFnZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hc2tDYW52YXMgPSB0aGlzLmNhY2hlZENhbnZhc2VzLmdldENhbnZhcygibWFza0NhbnZhcyIsIHdpZHRoLCBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWFza0N0eCA9IG1hc2tDYW52YXMuY29udGV4dDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hc2tDdHguc2F2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW1nID0gdGhpcy5nZXRPYmplY3QoZGF0YSwgaW1hZ2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHV0QmluYXJ5SW1hZ2VNYXNrKG1hc2tDdHgsIGltZyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrQ3R4Lmdsb2JhbENvbXBvc2l0ZU9wZXJhdGlvbiA9ICJzb3VyY2UtaW4iOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFza0N0eC5maWxsU3R5bGUgPSBpc1BhdHRlcm5GaWxsID8gZmlsbENvbG9yLmdldFBhdHRlcm4obWFza0N0eCwgdGhpcywgKDAsIF9kaXNwbGF5X3V0aWxzLmdldEN1cnJlbnRUcmFuc2Zvcm1JbnZlcnNlKShjdHgpLCBfcGF0dGVybl9oZWxwZXIuUGF0aFR5cGUuRklMTCkgOiBmaWxsQ29sb3I7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXNrQ3R4LmZpbGxSZWN0KDAsIDAsIHdpZHRoLCBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFza0N0eC5yZXN0b3JlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguc2F2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnRyYW5zZm9ybSguLi50cmFuc2Zvcm0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnNjYWxlKDEsIC0xKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRyYXdJbWFnZUF0SW50ZWdlckNvb3JkcyhjdHgsIG1hc2tDYW52YXMuY2FudmFzLCAwLCAwLCB3aWR0aCwgaGVpZ2h0LCAwLCAtMSwgMSwgMSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgucmVzdG9yZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcG9zZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBwYWludEltYWdlWE9iamVjdChvYmpJZCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29udGVudFZpc2libGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbWdEYXRhID0gdGhpcy5nZXRPYmplY3Qob2JqSWQpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWltZ0RhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiRGVwZW5kZW50IGltYWdlIGlzbid0IHJlYWR5IHlldCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFpbnRJbmxpbmVJbWFnZVhPYmplY3QoaW1nRGF0YSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHBhaW50SW1hZ2VYT2JqZWN0UmVwZWF0KG9iaklkLCBzY2FsZVgsIHNjYWxlWSwgcG9zaXRpb25zKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb250ZW50VmlzaWJsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGltZ0RhdGEgPSB0aGlzLmdldE9iamVjdChvYmpJZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaW1nRGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJEZXBlbmRlbnQgaW1hZ2UgaXNuJ3QgcmVhZHkgeWV0Iik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBpbWdEYXRhLndpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBpbWdEYXRhLmhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWFwID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHBvc2l0aW9ucy5sZW5ndGg7IGkgPCBpaTsgaSArPSAyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXAucHVzaCh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtOiBbc2NhbGVYLCAwLCAwLCBzY2FsZVksIHBvc2l0aW9uc1tpXSwgcG9zaXRpb25zW2kgKyAxXV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeDogMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5OiAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHc6IHdpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGg6IGhlaWdodAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYWludElubGluZUltYWdlWE9iamVjdEdyb3VwKGltZ0RhdGEsIG1hcCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFwcGx5VHJhbnNmZXJNYXBzVG9DYW52YXMoY3R4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnQudHJhbnNmZXJNYXBzICE9PSAibm9uZSIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5maWx0ZXIgPSB0aGlzLmN1cnJlbnQudHJhbnNmZXJNYXBzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmRyYXdJbWFnZShjdHguY2FudmFzLCAwLCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5maWx0ZXIgPSAibm9uZSI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN0eC5jYW52YXM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFwcGx5VHJhbnNmZXJNYXBzVG9CaXRtYXAoaW1nRGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jdXJyZW50LnRyYW5zZmVyTWFwcyA9PT0gIm5vbmUiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW1nRGF0YS5iaXRtYXA7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0bWFwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGltZ0RhdGE7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRtcENhbnZhcyA9IHRoaXMuY2FjaGVkQ2FudmFzZXMuZ2V0Q2FudmFzKCJpbmxpbmVJbWFnZSIsIHdpZHRoLCBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0bXBDdHggPSB0bXBDYW52YXMuY29udGV4dDsKICAgICAgICAgICAgICAgICAgICAgICAgdG1wQ3R4LmZpbHRlciA9IHRoaXMuY3VycmVudC50cmFuc2Zlck1hcHM7CiAgICAgICAgICAgICAgICAgICAgICAgIHRtcEN0eC5kcmF3SW1hZ2UoYml0bWFwLCAwLCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgdG1wQ3R4LmZpbHRlciA9ICJub25lIjsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRtcENhbnZhcy5jYW52YXM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHBhaW50SW5saW5lSW1hZ2VYT2JqZWN0KGltZ0RhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbnRlbnRWaXNpYmxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBpbWdEYXRhLndpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBpbWdEYXRhLmhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2F2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIV9pc19ub2RlLmlzTm9kZUpTKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguZmlsdGVyID0gIm5vbmUiOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zY2FsZSgxIC8gd2lkdGgsIC0xIC8gaGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGltZ1RvUGFpbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbWdEYXRhLmJpdG1hcCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nVG9QYWludCA9IHRoaXMuYXBwbHlUcmFuc2Zlck1hcHNUb0JpdG1hcChpbWdEYXRhKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgSFRNTEVsZW1lbnQgPT09ICJmdW5jdGlvbiIgJiYgaW1nRGF0YSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50IHx8ICFpbWdEYXRhLmRhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltZ1RvUGFpbnQgPSBpbWdEYXRhOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdG1wQ2FudmFzID0gdGhpcy5jYWNoZWRDYW52YXNlcy5nZXRDYW52YXMoImlubGluZUltYWdlIiwgd2lkdGgsIGhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0bXBDdHggPSB0bXBDYW52YXMuY29udGV4dDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1dEJpbmFyeUltYWdlRGF0YSh0bXBDdHgsIGltZ0RhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nVG9QYWludCA9IHRoaXMuYXBwbHlUcmFuc2Zlck1hcHNUb0NhbnZhcyh0bXBDdHgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNjYWxlZCA9IHRoaXMuX3NjYWxlSW1hZ2UoaW1nVG9QYWludCwgKDAsIF9kaXNwbGF5X3V0aWxzLmdldEN1cnJlbnRUcmFuc2Zvcm1JbnZlcnNlKShjdHgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmltYWdlU21vb3RoaW5nRW5hYmxlZCA9IGdldEltYWdlU21vb3RoaW5nRW5hYmxlZCgoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybSkoY3R4KSwgaW1nRGF0YS5pbnRlcnBvbGF0ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGRyYXdJbWFnZUF0SW50ZWdlckNvb3JkcyhjdHgsIHNjYWxlZC5pbWcsIDAsIDAsIHNjYWxlZC5wYWludFdpZHRoLCBzY2FsZWQucGFpbnRIZWlnaHQsIDAsIC1oZWlnaHQsIHdpZHRoLCBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBvc2UoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXN0b3JlKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHBhaW50SW5saW5lSW1hZ2VYT2JqZWN0R3JvdXAoaW1nRGF0YSwgbWFwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb250ZW50VmlzaWJsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IHRoaXMuY3R4OwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgaW1nVG9QYWludDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGltZ0RhdGEuYml0bWFwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbWdUb1BhaW50ID0gaW1nRGF0YS5iaXRtYXA7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3ID0gaW1nRGF0YS53aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGggPSBpbWdEYXRhLmhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRtcENhbnZhcyA9IHRoaXMuY2FjaGVkQ2FudmFzZXMuZ2V0Q2FudmFzKCJpbmxpbmVJbWFnZSIsIHcsIGgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdG1wQ3R4ID0gdG1wQ2FudmFzLmNvbnRleHQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdXRCaW5hcnlJbWFnZURhdGEodG1wQ3R4LCBpbWdEYXRhKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltZ1RvUGFpbnQgPSB0aGlzLmFwcGx5VHJhbnNmZXJNYXBzVG9DYW52YXModG1wQ3R4KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIG1hcCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnNhdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC50cmFuc2Zvcm0oLi4uZW50cnkudHJhbnNmb3JtKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zY2FsZSgxLCAtMSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcmF3SW1hZ2VBdEludGVnZXJDb29yZHMoY3R4LCBpbWdUb1BhaW50LCBlbnRyeS54LCBlbnRyeS55LCBlbnRyeS53LCBlbnRyeS5oLCAwLCAtMSwgMSwgMSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgucmVzdG9yZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcG9zZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBwYWludFNvbGlkQ29sb3JJbWFnZU1hc2soKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb250ZW50VmlzaWJsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LmZpbGxSZWN0KDAsIDAsIDEsIDEpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbXBvc2UoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgbWFya1BvaW50KHRhZykge30KICAgICAgICAgICAgICAgICAgICBtYXJrUG9pbnRQcm9wcyh0YWcsIHByb3BlcnRpZXMpIHt9CiAgICAgICAgICAgICAgICAgICAgYmVnaW5NYXJrZWRDb250ZW50KHRhZykgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hcmtlZENvbnRlbnRTdGFjay5wdXNoKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpc2libGU6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJlZ2luTWFya2VkQ29udGVudFByb3BzKHRhZywgcHJvcGVydGllcykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGFnID09PSAiT0MiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hcmtlZENvbnRlbnRTdGFjay5wdXNoKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aXNpYmxlOiB0aGlzLm9wdGlvbmFsQ29udGVudENvbmZpZy5pc1Zpc2libGUocHJvcGVydGllcykKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXJrZWRDb250ZW50U3RhY2sucHVzaCh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlzaWJsZTogdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250ZW50VmlzaWJsZSA9IHRoaXMuaXNDb250ZW50VmlzaWJsZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbmRNYXJrZWRDb250ZW50KCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hcmtlZENvbnRlbnRTdGFjay5wb3AoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250ZW50VmlzaWJsZSA9IHRoaXMuaXNDb250ZW50VmlzaWJsZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBiZWdpbkNvbXBhdCgpIHt9CiAgICAgICAgICAgICAgICAgICAgZW5kQ29tcGF0KCkge30KICAgICAgICAgICAgICAgICAgICBjb25zdW1lUGF0aChjbGlwQm94KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzRW1wdHkgPSB0aGlzLmN1cnJlbnQuaXNFbXB0eUNsaXAoKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucGVuZGluZ0NsaXApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC51cGRhdGVDbGlwRnJvbVBhdGgoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMucGVuZGluZ0NsaXApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcG9zZShjbGlwQm94KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdHggPSB0aGlzLmN0eDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucGVuZGluZ0NsaXApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaXNFbXB0eSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnBlbmRpbmdDbGlwID09PSBFT19DTElQKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5jbGlwKCJldmVub2RkIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmNsaXAoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBlbmRpbmdDbGlwID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuc3RhcnROZXdQYXRoQW5kQ2xpcEJveCh0aGlzLmN1cnJlbnQuY2xpcEJveCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5iZWdpblBhdGgoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0U2luZ2xlUGl4ZWxXaWR0aCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9jYWNoZWRHZXRTaW5nbGVQaXhlbFdpZHRoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtID0gKDAsIF9kaXNwbGF5X3V0aWxzLmdldEN1cnJlbnRUcmFuc2Zvcm0pKHRoaXMuY3R4KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtWzFdID09PSAwICYmIG1bMl0gPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYWNoZWRHZXRTaW5nbGVQaXhlbFdpZHRoID0gMSAvIE1hdGgubWluKE1hdGguYWJzKG1bMF0pLCBNYXRoLmFicyhtWzNdKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFic0RldCA9IE1hdGguYWJzKG1bMF0gKiBtWzNdIC0gbVsyXSAqIG1bMV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5vcm1YID0gTWF0aC5oeXBvdChtWzBdLCBtWzJdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBub3JtWSA9IE1hdGguaHlwb3QobVsxXSwgbVszXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY2FjaGVkR2V0U2luZ2xlUGl4ZWxXaWR0aCA9IE1hdGgubWF4KG5vcm1YLCBub3JtWSkgLyBhYnNEZXQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NhY2hlZEdldFNpbmdsZVBpeGVsV2lkdGg7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldFNjYWxlRm9yU3Ryb2tpbmcoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5fY2FjaGVkU2NhbGVGb3JTdHJva2luZykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVXaWR0aAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXMuY3VycmVudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG0gPSAoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybSkodGhpcy5jdHgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNjYWxlWCwgc2NhbGVZOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1bMV0gPT09IDAgJiYgbVsyXSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5vcm1YID0gTWF0aC5hYnMobVswXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgbm9ybVkgPSBNYXRoLmFicyhtWzNdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobGluZVdpZHRoID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlWCA9IDEgLyBub3JtWDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVZID0gMSAvIG5vcm1ZOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNjYWxlZFhMaW5lV2lkdGggPSBub3JtWCAqIGxpbmVXaWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2NhbGVkWUxpbmVXaWR0aCA9IG5vcm1ZICogbGluZVdpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZVggPSBzY2FsZWRYTGluZVdpZHRoIDwgMSA/IDEgLyBzY2FsZWRYTGluZVdpZHRoIDogMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVZID0gc2NhbGVkWUxpbmVXaWR0aCA8IDEgPyAxIC8gc2NhbGVkWUxpbmVXaWR0aCA6IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhYnNEZXQgPSBNYXRoLmFicyhtWzBdICogbVszXSAtIG1bMl0gKiBtWzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBub3JtWCA9IE1hdGguaHlwb3QobVswXSwgbVsxXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgbm9ybVkgPSBNYXRoLmh5cG90KG1bMl0sIG1bM10pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsaW5lV2lkdGggPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVYID0gbm9ybVkgLyBhYnNEZXQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlWSA9IG5vcm1YIC8gYWJzRGV0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJhc2VBcmVhID0gbGluZVdpZHRoICogYWJzRGV0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZVggPSBub3JtWSA+IGJhc2VBcmVhID8gbm9ybVkgLyBiYXNlQXJlYSA6IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlWSA9IG5vcm1YID4gYmFzZUFyZWEgPyBub3JtWCAvIGJhc2VBcmVhIDogMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYWNoZWRTY2FsZUZvclN0cm9raW5nID0gW3NjYWxlWCwgc2NhbGVZXTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fY2FjaGVkU2NhbGVGb3JTdHJva2luZzsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVzY2FsZUFuZFN0cm9rZShzYXZlUmVzdG9yZSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXM7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVXaWR0aAogICAgICAgICAgICAgICAgICAgICAgICB9ID0gdGhpcy5jdXJyZW50OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbc2NhbGVYLCBzY2FsZVldID0gdGhpcy5nZXRTY2FsZUZvclN0cm9raW5nKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5saW5lV2lkdGggPSBsaW5lV2lkdGggfHwgMTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNjYWxlWCA9PT0gMSAmJiBzY2FsZVkgPT09IDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zdHJva2UoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBsZXQgc2F2ZWRNYXRyaXgsIHNhdmVkRGFzaGVzLCBzYXZlZERhc2hPZmZzZXQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzYXZlUmVzdG9yZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F2ZWRNYXRyaXggPSAoMCwgX2Rpc3BsYXlfdXRpbHMuZ2V0Q3VycmVudFRyYW5zZm9ybSkoY3R4KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhdmVkRGFzaGVzID0gY3R4LmdldExpbmVEYXNoKCkuc2xpY2UoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhdmVkRGFzaE9mZnNldCA9IGN0eC5saW5lRGFzaE9mZnNldDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjdHguc2NhbGUoc2NhbGVYLCBzY2FsZVkpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzY2FsZSA9IE1hdGgubWF4KHNjYWxlWCwgc2NhbGVZKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnNldExpbmVEYXNoKGN0eC5nZXRMaW5lRGFzaCgpLm1hcCh4ID0+IHggLyBzY2FsZSkpOwogICAgICAgICAgICAgICAgICAgICAgICBjdHgubGluZURhc2hPZmZzZXQgLz0gc2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zdHJva2UoKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNhdmVSZXN0b3JlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguc2V0VHJhbnNmb3JtKC4uLnNhdmVkTWF0cml4KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zZXRMaW5lRGFzaChzYXZlZERhc2hlcyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHgubGluZURhc2hPZmZzZXQgPSBzYXZlZERhc2hPZmZzZXQ7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaXNDb250ZW50VmlzaWJsZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IHRoaXMubWFya2VkQ29udGVudFN0YWNrLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMubWFya2VkQ29udGVudFN0YWNrW2ldLnZpc2libGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5DYW52YXNHcmFwaGljcyA9IENhbnZhc0dyYXBoaWNzOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3Jlc3RvcmVJbml0aWFsU3RhdGUyKCkgewogICAgICAgICAgICAgICAgICAgIHdoaWxlICh0aGlzLnN0YXRlU3RhY2subGVuZ3RoIHx8IHRoaXMuaW5TTWFza01vZGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXN0b3JlKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnJlc3RvcmUoKTsKICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy50cmFuc3BhcmVudENhbnZhcykgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eCA9IHRoaXMuY29tcG9zaXRlQ3R4OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5zYXZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAwLCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguZHJhd0ltYWdlKHRoaXMudHJhbnNwYXJlbnRDYW52YXMsIDAsIDApOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5yZXN0b3JlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJhbnNwYXJlbnRDYW52YXMgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgb3AgaW4gX3V0aWwuT1BTKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKENhbnZhc0dyYXBoaWNzLnByb3RvdHlwZVtvcF0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgICAgICAgICBDYW52YXNHcmFwaGljcy5wcm90b3R5cGVbX3V0aWwuT1BTW29wXV0gPSBDYW52YXNHcmFwaGljcy5wcm90b3R5cGVbb3BdOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTQ3ICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuVGlsaW5nUGF0dGVybiA9IGV4cG9ydHMuUGF0aFR5cGUgPSB2b2lkIDA7CiAgICAgICAgICAgICAgICBleHBvcnRzLmdldFNoYWRpbmdQYXR0ZXJuID0gZ2V0U2hhZGluZ1BhdHRlcm47CiAgICAgICAgICAgICAgICB2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEpOwogICAgICAgICAgICAgICAgdmFyIF9kaXNwbGF5X3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDIpOwogICAgICAgICAgICAgICAgY29uc3QgUGF0aFR5cGUgPSB7CiAgICAgICAgICAgICAgICAgICAgRklMTDogIkZpbGwiLAogICAgICAgICAgICAgICAgICAgIFNUUk9LRTogIlN0cm9rZSIsCiAgICAgICAgICAgICAgICAgICAgU0hBRElORzogIlNoYWRpbmciCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgZXhwb3J0cy5QYXRoVHlwZSA9IFBhdGhUeXBlOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlCb3VuZGluZ0JveChjdHgsIGJib3gpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIWJib3gpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCB3aWR0aCA9IGJib3hbMl0gLSBiYm94WzBdOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGJib3hbM10gLSBiYm94WzFdOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlZ2lvbiA9IG5ldyBQYXRoMkQoKTsKICAgICAgICAgICAgICAgICAgICByZWdpb24ucmVjdChiYm94WzBdLCBiYm94WzFdLCB3aWR0aCwgaGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICBjdHguY2xpcChyZWdpb24pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgQmFzZVNoYWRpbmdQYXR0ZXJuIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY29uc3RydWN0b3IgPT09IEJhc2VTaGFkaW5nUGF0dGVybikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQ2Fubm90IGluaXRpYWxpemUgQmFzZVNoYWRpbmdQYXR0ZXJuLiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldFBhdHRlcm4oKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIkFic3RyYWN0IG1ldGhvZCBgZ2V0UGF0dGVybmAgY2FsbGVkLiIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIFJhZGlhbEF4aWFsU2hhZGluZ1BhdHRlcm4gZXh0ZW5kcyBCYXNlU2hhZGluZ1BhdHRlcm4gewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKElSKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3R5cGUgPSBJUlsxXTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fYmJveCA9IElSWzJdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb2xvclN0b3BzID0gSVJbM107CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3AwID0gSVJbNF07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3AxID0gSVJbNV07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3IwID0gSVJbNl07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3IxID0gSVJbN107CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWF0cml4ID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2NyZWF0ZUdyYWRpZW50KGN0eCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgZ3JhZDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX3R5cGUgPT09ICJheGlhbCIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyYWQgPSBjdHguY3JlYXRlTGluZWFyR3JhZGllbnQodGhpcy5fcDBbMF0sIHRoaXMuX3AwWzFdLCB0aGlzLl9wMVswXSwgdGhpcy5fcDFbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX3R5cGUgPT09ICJyYWRpYWwiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmFkID0gY3R4LmNyZWF0ZVJhZGlhbEdyYWRpZW50KHRoaXMuX3AwWzBdLCB0aGlzLl9wMFsxXSwgdGhpcy5fcjAsIHRoaXMuX3AxWzBdLCB0aGlzLl9wMVsxXSwgdGhpcy5fcjEpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgY29sb3JTdG9wIG9mIHRoaXMuX2NvbG9yU3RvcHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyYWQuYWRkQ29sb3JTdG9wKGNvbG9yU3RvcFswXSwgY29sb3JTdG9wWzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZ3JhZDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0UGF0dGVybihjdHgsIG93bmVyLCBpbnZlcnNlLCBwYXRoVHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcGF0dGVybjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhdGhUeXBlID09PSBQYXRoVHlwZS5TVFJPS0UgfHwgcGF0aFR5cGUgPT09IFBhdGhUeXBlLkZJTEwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG93bmVyQkJveCA9IG93bmVyLmN1cnJlbnQuZ2V0Q2xpcHBlZFBhdGhCb3VuZGluZ0JveChwYXRoVHlwZSwgKDAsIF9kaXNwbGF5X3V0aWxzLmdldEN1cnJlbnRUcmFuc2Zvcm0pKGN0eCkpIHx8IFswLCAwLCAwLCAwXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gTWF0aC5jZWlsKG93bmVyQkJveFsyXSAtIG93bmVyQkJveFswXSkgfHwgMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IE1hdGguY2VpbChvd25lckJCb3hbM10gLSBvd25lckJCb3hbMV0pIHx8IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0bXBDYW52YXMgPSBvd25lci5jYWNoZWRDYW52YXNlcy5nZXRDYW52YXMoInBhdHRlcm4iLCB3aWR0aCwgaGVpZ2h0LCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRtcEN0eCA9IHRtcENhbnZhcy5jb250ZXh0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wQ3R4LmNsZWFyUmVjdCgwLCAwLCB0bXBDdHguY2FudmFzLndpZHRoLCB0bXBDdHguY2FudmFzLmhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXBDdHguYmVnaW5QYXRoKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXBDdHgucmVjdCgwLCAwLCB0bXBDdHguY2FudmFzLndpZHRoLCB0bXBDdHguY2FudmFzLmhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXBDdHgudHJhbnNsYXRlKC1vd25lckJCb3hbMF0sIC1vd25lckJCb3hbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW52ZXJzZSA9IF91dGlsLlV0aWwudHJhbnNmb3JtKGludmVyc2UsIFsxLCAwLCAwLCAxLCBvd25lckJCb3hbMF0sIG93bmVyQkJveFsxXV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wQ3R4LnRyYW5zZm9ybSguLi5vd25lci5iYXNlVHJhbnNmb3JtKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLm1hdHJpeCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRtcEN0eC50cmFuc2Zvcm0oLi4udGhpcy5tYXRyaXgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlCb3VuZGluZ0JveCh0bXBDdHgsIHRoaXMuX2Jib3gpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdG1wQ3R4LmZpbGxTdHlsZSA9IHRoaXMuX2NyZWF0ZUdyYWRpZW50KHRtcEN0eCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXBDdHguZmlsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9IGN0eC5jcmVhdGVQYXR0ZXJuKHRtcENhbnZhcy5jYW52YXMsICJuby1yZXBlYXQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRvbU1hdHJpeCA9IG5ldyBET01NYXRyaXgoaW52ZXJzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuLnNldFRyYW5zZm9ybShkb21NYXRyaXgpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlCb3VuZGluZ0JveChjdHgsIHRoaXMuX2Jib3gpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9IHRoaXMuX2NyZWF0ZUdyYWRpZW50KGN0eCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdHRlcm47CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gZHJhd1RyaWFuZ2xlKGRhdGEsIGNvbnRleHQsIHAxLCBwMiwgcDMsIGMxLCBjMiwgYzMpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjb29yZHMgPSBjb250ZXh0LmNvb3JkcywKICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JzID0gY29udGV4dC5jb2xvcnM7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgYnl0ZXMgPSBkYXRhLmRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgIHJvd1NpemUgPSBkYXRhLndpZHRoICogNDsKICAgICAgICAgICAgICAgICAgICBsZXQgdG1wOwogICAgICAgICAgICAgICAgICAgIGlmIChjb29yZHNbcDEgKyAxXSA+IGNvb3Jkc1twMiArIDFdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRtcCA9IHAxOwogICAgICAgICAgICAgICAgICAgICAgICBwMSA9IHAyOwogICAgICAgICAgICAgICAgICAgICAgICBwMiA9IHRtcDsKICAgICAgICAgICAgICAgICAgICAgICAgdG1wID0gYzE7CiAgICAgICAgICAgICAgICAgICAgICAgIGMxID0gYzI7CiAgICAgICAgICAgICAgICAgICAgICAgIGMyID0gdG1wOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoY29vcmRzW3AyICsgMV0gPiBjb29yZHNbcDMgKyAxXSkgewogICAgICAgICAgICAgICAgICAgICAgICB0bXAgPSBwMjsKICAgICAgICAgICAgICAgICAgICAgICAgcDIgPSBwMzsKICAgICAgICAgICAgICAgICAgICAgICAgcDMgPSB0bXA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRtcCA9IGMyOwogICAgICAgICAgICAgICAgICAgICAgICBjMiA9IGMzOwogICAgICAgICAgICAgICAgICAgICAgICBjMyA9IHRtcDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGNvb3Jkc1twMSArIDFdID4gY29vcmRzW3AyICsgMV0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgdG1wID0gcDE7CiAgICAgICAgICAgICAgICAgICAgICAgIHAxID0gcDI7CiAgICAgICAgICAgICAgICAgICAgICAgIHAyID0gdG1wOwogICAgICAgICAgICAgICAgICAgICAgICB0bXAgPSBjMTsKICAgICAgICAgICAgICAgICAgICAgICAgYzEgPSBjMjsKICAgICAgICAgICAgICAgICAgICAgICAgYzIgPSB0bXA7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IHgxID0gKGNvb3Jkc1twMV0gKyBjb250ZXh0Lm9mZnNldFgpICogY29udGV4dC5zY2FsZVg7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgeTEgPSAoY29vcmRzW3AxICsgMV0gKyBjb250ZXh0Lm9mZnNldFkpICogY29udGV4dC5zY2FsZVk7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgeDIgPSAoY29vcmRzW3AyXSArIGNvbnRleHQub2Zmc2V0WCkgKiBjb250ZXh0LnNjYWxlWDsKICAgICAgICAgICAgICAgICAgICBjb25zdCB5MiA9IChjb29yZHNbcDIgKyAxXSArIGNvbnRleHQub2Zmc2V0WSkgKiBjb250ZXh0LnNjYWxlWTsKICAgICAgICAgICAgICAgICAgICBjb25zdCB4MyA9IChjb29yZHNbcDNdICsgY29udGV4dC5vZmZzZXRYKSAqIGNvbnRleHQuc2NhbGVYOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHkzID0gKGNvb3Jkc1twMyArIDFdICsgY29udGV4dC5vZmZzZXRZKSAqIGNvbnRleHQuc2NhbGVZOwogICAgICAgICAgICAgICAgICAgIGlmICh5MSA+PSB5MykgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IGMxciA9IGNvbG9yc1tjMV0sCiAgICAgICAgICAgICAgICAgICAgICAgIGMxZyA9IGNvbG9yc1tjMSArIDFdLAogICAgICAgICAgICAgICAgICAgICAgICBjMWIgPSBjb2xvcnNbYzEgKyAyXTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjMnIgPSBjb2xvcnNbYzJdLAogICAgICAgICAgICAgICAgICAgICAgICBjMmcgPSBjb2xvcnNbYzIgKyAxXSwKICAgICAgICAgICAgICAgICAgICAgICAgYzJiID0gY29sb3JzW2MyICsgMl07CiAgICAgICAgICAgICAgICAgICAgY29uc3QgYzNyID0gY29sb3JzW2MzXSwKICAgICAgICAgICAgICAgICAgICAgICAgYzNnID0gY29sb3JzW2MzICsgMV0sCiAgICAgICAgICAgICAgICAgICAgICAgIGMzYiA9IGNvbG9yc1tjMyArIDJdOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IG1pblkgPSBNYXRoLnJvdW5kKHkxKSwKICAgICAgICAgICAgICAgICAgICAgICAgbWF4WSA9IE1hdGgucm91bmQoeTMpOwogICAgICAgICAgICAgICAgICAgIGxldCB4YSwgY2FyLCBjYWcsIGNhYjsKICAgICAgICAgICAgICAgICAgICBsZXQgeGIsIGNiciwgY2JnLCBjYmI7CiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgeSA9IG1pblk7IHkgPD0gbWF4WTsgeSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh5IDwgeTIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHkgPCB5MSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrID0gKHkxIC0geSkgLyAoeTEgLSB5Mik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4YSA9IHgxIC0gKHgxIC0geDIpICogazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhciA9IGMxciAtIChjMXIgLSBjMnIpICogazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhZyA9IGMxZyAtIChjMWcgLSBjMmcpICogazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhYiA9IGMxYiAtIChjMWIgLSBjMmIpICogazsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHkgPiB5MykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsgPSAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh5MiA9PT0geTMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgayA9ICh5MiAtIHkpIC8gKHkyIC0geTMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgeGEgPSB4MiAtICh4MiAtIHgzKSAqIGs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXIgPSBjMnIgLSAoYzJyIC0gYzNyKSAqIGs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWcgPSBjMmcgLSAoYzJnIC0gYzNnKSAqIGs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWIgPSBjMmIgLSAoYzJiIC0gYzNiKSAqIGs7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGs7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh5IDwgeTEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHkgPiB5MykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgayA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrID0gKHkxIC0geSkgLyAoeTEgLSB5Myk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgeGIgPSB4MSAtICh4MSAtIHgzKSAqIGs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNiciA9IGMxciAtIChjMXIgLSBjM3IpICogazsKICAgICAgICAgICAgICAgICAgICAgICAgY2JnID0gYzFnIC0gKGMxZyAtIGMzZykgKiBrOwogICAgICAgICAgICAgICAgICAgICAgICBjYmIgPSBjMWIgLSAoYzFiIC0gYzNiKSAqIGs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHgxXyA9IE1hdGgucm91bmQoTWF0aC5taW4oeGEsIHhiKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHgyXyA9IE1hdGgucm91bmQoTWF0aC5tYXgoeGEsIHhiKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBqID0gcm93U2l6ZSAqIHkgKyB4MV8gKiA0OwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCB4ID0geDFfOyB4IDw9IHgyXzsgeCsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrID0gKHhhIC0geCkgLyAoeGEgLSB4Yik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoayA8IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoayA+IDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzW2orK10gPSBjYXIgLSAoY2FyIC0gY2JyKSAqIGsgfCAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNbaisrXSA9IGNhZyAtIChjYWcgLSBjYmcpICogayB8IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1tqKytdID0gY2FiIC0gKGNhYiAtIGNiYikgKiBrIHwgMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzW2orK10gPSAyNTU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBkcmF3RmlndXJlKGRhdGEsIGZpZ3VyZSwgY29udGV4dCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHBzID0gZmlndXJlLmNvb3JkczsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjcyA9IGZpZ3VyZS5jb2xvcnM7CiAgICAgICAgICAgICAgICAgICAgbGV0IGksIGlpOwogICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZmlndXJlLnR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAibGF0dGljZSI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB2ZXJ0aWNlc1BlclJvdyA9IGZpZ3VyZS52ZXJ0aWNlc1BlclJvdzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJvd3MgPSBNYXRoLmZsb29yKHBzLmxlbmd0aCAvIHZlcnRpY2VzUGVyUm93KSAtIDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb2xzID0gdmVydGljZXNQZXJSb3cgLSAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHJvd3M7IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBxID0gaSAqIHZlcnRpY2VzUGVyUm93OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgY29sczsgaisrLCBxKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJhd1RyaWFuZ2xlKGRhdGEsIGNvbnRleHQsIHBzW3FdLCBwc1txICsgMV0sIHBzW3EgKyB2ZXJ0aWNlc1BlclJvd10sIGNzW3FdLCBjc1txICsgMV0sIGNzW3EgKyB2ZXJ0aWNlc1BlclJvd10pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcmF3VHJpYW5nbGUoZGF0YSwgY29udGV4dCwgcHNbcSArIHZlcnRpY2VzUGVyUm93ICsgMV0sIHBzW3EgKyAxXSwgcHNbcSArIHZlcnRpY2VzUGVyUm93XSwgY3NbcSArIHZlcnRpY2VzUGVyUm93ICsgMV0sIGNzW3EgKyAxXSwgY3NbcSArIHZlcnRpY2VzUGVyUm93XSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgInRyaWFuZ2xlcyI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IHBzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcmF3VHJpYW5nbGUoZGF0YSwgY29udGV4dCwgcHNbaV0sIHBzW2kgKyAxXSwgcHNbaSArIDJdLCBjc1tpXSwgY3NbaSArIDFdLCBjc1tpICsgMl0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoImlsbGVnYWwgZmlndXJlIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgTWVzaFNoYWRpbmdQYXR0ZXJuIGV4dGVuZHMgQmFzZVNoYWRpbmdQYXR0ZXJuIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihJUikgewogICAgICAgICAgICAgICAgICAgICAgICBzdXBlcigpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb29yZHMgPSBJUlsyXTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29sb3JzID0gSVJbM107CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2ZpZ3VyZXMgPSBJUls0XTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fYm91bmRzID0gSVJbNV07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Jib3ggPSBJUls3XTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fYmFja2dyb3VuZCA9IElSWzhdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hdHJpeCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9jcmVhdGVNZXNoQ2FudmFzKGNvbWJpbmVkU2NhbGUsIGJhY2tncm91bmRDb2xvciwgY2FjaGVkQ2FudmFzZXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgRVhQRUNURURfU0NBTEUgPSAxLjE7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IE1BWF9QQVRURVJOX1NJWkUgPSAzMDAwOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBCT1JERVJfU0laRSA9IDI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldFggPSBNYXRoLmZsb29yKHRoaXMuX2JvdW5kc1swXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldFkgPSBNYXRoLmZsb29yKHRoaXMuX2JvdW5kc1sxXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJvdW5kc1dpZHRoID0gTWF0aC5jZWlsKHRoaXMuX2JvdW5kc1syXSkgLSBvZmZzZXRYOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBib3VuZHNIZWlnaHQgPSBNYXRoLmNlaWwodGhpcy5fYm91bmRzWzNdKSAtIG9mZnNldFk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gTWF0aC5taW4oTWF0aC5jZWlsKE1hdGguYWJzKGJvdW5kc1dpZHRoICogY29tYmluZWRTY2FsZVswXSAqIEVYUEVDVEVEX1NDQUxFKSksIE1BWF9QQVRURVJOX1NJWkUpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBNYXRoLm1pbihNYXRoLmNlaWwoTWF0aC5hYnMoYm91bmRzSGVpZ2h0ICogY29tYmluZWRTY2FsZVsxXSAqIEVYUEVDVEVEX1NDQUxFKSksIE1BWF9QQVRURVJOX1NJWkUpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzY2FsZVggPSBib3VuZHNXaWR0aCAvIHdpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzY2FsZVkgPSBib3VuZHNIZWlnaHQgLyBoZWlnaHQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb29yZHM6IHRoaXMuX2Nvb3JkcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yczogdGhpcy5fY29sb3JzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0WDogLW9mZnNldFgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRZOiAtb2Zmc2V0WSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlWDogMSAvIHNjYWxlWCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlWTogMSAvIHNjYWxlWQogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWRkZWRXaWR0aCA9IHdpZHRoICsgQk9SREVSX1NJWkUgKiAyOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWRkZWRIZWlnaHQgPSBoZWlnaHQgKyBCT1JERVJfU0laRSAqIDI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRtcENhbnZhcyA9IGNhY2hlZENhbnZhc2VzLmdldENhbnZhcygibWVzaCIsIHBhZGRlZFdpZHRoLCBwYWRkZWRIZWlnaHQsIGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdG1wQ3R4ID0gdG1wQ2FudmFzLmNvbnRleHQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSB0bXBDdHguY3JlYXRlSW1hZ2VEYXRhKHdpZHRoLCBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmFja2dyb3VuZENvbG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBieXRlcyA9IGRhdGEuZGF0YTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGJ5dGVzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1tpXSA9IGJhY2tncm91bmRDb2xvclswXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlc1tpICsgMV0gPSBiYWNrZ3JvdW5kQ29sb3JbMV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZXNbaSArIDJdID0gYmFja2dyb3VuZENvbG9yWzJdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5dGVzW2kgKyAzXSA9IDI1NTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpZ3VyZSBvZiB0aGlzLl9maWd1cmVzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcmF3RmlndXJlKGRhdGEsIGZpZ3VyZSwgY29udGV4dCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdG1wQ3R4LnB1dEltYWdlRGF0YShkYXRhLCBCT1JERVJfU0laRSwgQk9SREVSX1NJWkUpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW52YXMgPSB0bXBDYW52YXMuY2FudmFzOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0WDogb2Zmc2V0WCAtIEJPUkRFUl9TSVpFICogc2NhbGVYLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0WTogb2Zmc2V0WSAtIEJPUkRFUl9TSVpFICogc2NhbGVZLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVYLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVZCiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldFBhdHRlcm4oY3R4LCBvd25lciwgaW52ZXJzZSwgcGF0aFR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlCb3VuZGluZ0JveChjdHgsIHRoaXMuX2Jib3gpOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgc2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXRoVHlwZSA9PT0gUGF0aFR5cGUuU0hBRElORykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSBfdXRpbC5VdGlsLnNpbmd1bGFyVmFsdWVEZWNvbXBvc2UyZFNjYWxlKCgwLCBfZGlzcGxheV91dGlscy5nZXRDdXJyZW50VHJhbnNmb3JtKShjdHgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlID0gX3V0aWwuVXRpbC5zaW5ndWxhclZhbHVlRGVjb21wb3NlMmRTY2FsZShvd25lci5iYXNlVHJhbnNmb3JtKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLm1hdHJpeCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hdHJpeFNjYWxlID0gX3V0aWwuVXRpbC5zaW5ndWxhclZhbHVlRGVjb21wb3NlMmRTY2FsZSh0aGlzLm1hdHJpeCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSBbc2NhbGVbMF0gKiBtYXRyaXhTY2FsZVswXSwgc2NhbGVbMV0gKiBtYXRyaXhTY2FsZVsxXV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGVtcG9yYXJ5UGF0dGVybkNhbnZhcyA9IHRoaXMuX2NyZWF0ZU1lc2hDYW52YXMoc2NhbGUsIHBhdGhUeXBlID09PSBQYXRoVHlwZS5TSEFESU5HID8gbnVsbCA6IHRoaXMuX2JhY2tncm91bmQsIG93bmVyLmNhY2hlZENhbnZhc2VzKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhdGhUeXBlICE9PSBQYXRoVHlwZS5TSEFESU5HKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguc2V0VHJhbnNmb3JtKC4uLm93bmVyLmJhc2VUcmFuc2Zvcm0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMubWF0cml4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnRyYW5zZm9ybSguLi50aGlzLm1hdHJpeCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY3R4LnRyYW5zbGF0ZSh0ZW1wb3JhcnlQYXR0ZXJuQ2FudmFzLm9mZnNldFgsIHRlbXBvcmFyeVBhdHRlcm5DYW52YXMub2Zmc2V0WSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eC5zY2FsZSh0ZW1wb3JhcnlQYXR0ZXJuQ2FudmFzLnNjYWxlWCwgdGVtcG9yYXJ5UGF0dGVybkNhbnZhcy5zY2FsZVkpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3R4LmNyZWF0ZVBhdHRlcm4odGVtcG9yYXJ5UGF0dGVybkNhbnZhcy5jYW52YXMsICJuby1yZXBlYXQiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBEdW1teVNoYWRpbmdQYXR0ZXJuIGV4dGVuZHMgQmFzZVNoYWRpbmdQYXR0ZXJuIHsKICAgICAgICAgICAgICAgICAgICBnZXRQYXR0ZXJuKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gImhvdHBpbmsiOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGdldFNoYWRpbmdQYXR0ZXJuKElSKSB7CiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChJUlswXSkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJSYWRpYWxBeGlhbCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFJhZGlhbEF4aWFsU2hhZGluZ1BhdHRlcm4oSVIpOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJNZXNoIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgTWVzaFNoYWRpbmdQYXR0ZXJuKElSKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiRHVtbXkiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBEdW1teVNoYWRpbmdQYXR0ZXJuKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBJUiB0eXBlOiAke0lSWzBdfWApOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY29uc3QgUGFpbnRUeXBlID0gewogICAgICAgICAgICAgICAgICAgIENPTE9SRUQ6IDEsCiAgICAgICAgICAgICAgICAgICAgVU5DT0xPUkVEOiAyCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgY2xhc3MgVGlsaW5nUGF0dGVybiB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIGdldCBNQVhfUEFUVEVSTl9TSVpFKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIk1BWF9QQVRURVJOX1NJWkUiLCAzMDAwKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IoSVIsIGNvbG9yLCBjdHgsIGNhbnZhc0dyYXBoaWNzRmFjdG9yeSwgYmFzZVRyYW5zZm9ybSkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9wZXJhdG9yTGlzdCA9IElSWzJdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hdHJpeCA9IElSWzNdIHx8IFsxLCAwLCAwLCAxLCAwLCAwXTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5iYm94ID0gSVJbNF07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMueHN0ZXAgPSBJUls1XTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy55c3RlcCA9IElSWzZdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhaW50VHlwZSA9IElSWzddOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRpbGluZ1R5cGUgPSBJUls4XTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb2xvciA9IGNvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eCA9IGN0eDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYW52YXNHcmFwaGljc0ZhY3RvcnkgPSBjYW52YXNHcmFwaGljc0ZhY3Rvcnk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmFzZVRyYW5zZm9ybSA9IGJhc2VUcmFuc2Zvcm07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNyZWF0ZVBhdHRlcm5DYW52YXMob3duZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3BlcmF0b3JMaXN0ID0gdGhpcy5vcGVyYXRvckxpc3Q7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJib3ggPSB0aGlzLmJib3g7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHhzdGVwID0gdGhpcy54c3RlcDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeXN0ZXAgPSB0aGlzLnlzdGVwOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWludFR5cGUgPSB0aGlzLnBhaW50VHlwZTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGlsaW5nVHlwZSA9IHRoaXMudGlsaW5nVHlwZTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY29sb3IgPSB0aGlzLmNvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW52YXNHcmFwaGljc0ZhY3RvcnkgPSB0aGlzLmNhbnZhc0dyYXBoaWNzRmFjdG9yeTsKICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLmluZm8pKCJUaWxpbmdUeXBlOiAiICsgdGlsaW5nVHlwZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHgwID0gYmJveFswXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkwID0gYmJveFsxXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHgxID0gYmJveFsyXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkxID0gYmJveFszXTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWF0cml4U2NhbGUgPSBfdXRpbC5VdGlsLnNpbmd1bGFyVmFsdWVEZWNvbXBvc2UyZFNjYWxlKHRoaXMubWF0cml4KTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VyTWF0cml4U2NhbGUgPSBfdXRpbC5VdGlsLnNpbmd1bGFyVmFsdWVEZWNvbXBvc2UyZFNjYWxlKHRoaXMuYmFzZVRyYW5zZm9ybSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbWJpbmVkU2NhbGUgPSBbbWF0cml4U2NhbGVbMF0gKiBjdXJNYXRyaXhTY2FsZVswXSwgbWF0cml4U2NhbGVbMV0gKiBjdXJNYXRyaXhTY2FsZVsxXV07CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpbXggPSB0aGlzLmdldFNpemVBbmRTY2FsZSh4c3RlcCwgdGhpcy5jdHguY2FudmFzLndpZHRoLCBjb21iaW5lZFNjYWxlWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGlteSA9IHRoaXMuZ2V0U2l6ZUFuZFNjYWxlKHlzdGVwLCB0aGlzLmN0eC5jYW52YXMuaGVpZ2h0LCBjb21iaW5lZFNjYWxlWzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdG1wQ2FudmFzID0gb3duZXIuY2FjaGVkQ2FudmFzZXMuZ2V0Q2FudmFzKCJwYXR0ZXJuIiwgZGlteC5zaXplLCBkaW15LnNpemUsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0bXBDdHggPSB0bXBDYW52YXMuY29udGV4dDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZ3JhcGhpY3MgPSBjYW52YXNHcmFwaGljc0ZhY3RvcnkuY3JlYXRlQ2FudmFzR3JhcGhpY3ModG1wQ3R4KTsKICAgICAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MuZ3JvdXBMZXZlbCA9IG93bmVyLmdyb3VwTGV2ZWw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0RmlsbEFuZFN0cm9rZVN0eWxlVG9Db250ZXh0KGdyYXBoaWNzLCBwYWludFR5cGUsIGNvbG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFkanVzdGVkWDAgPSB4MDsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFkanVzdGVkWTAgPSB5MDsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFkanVzdGVkWDEgPSB4MTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGFkanVzdGVkWTEgPSB5MTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHgwIDwgMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRqdXN0ZWRYMCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGp1c3RlZFgxICs9IE1hdGguYWJzKHgwKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoeTAgPCAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZGp1c3RlZFkwID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkanVzdGVkWTEgKz0gTWF0aC5hYnMoeTApOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRtcEN0eC50cmFuc2xhdGUoLShkaW14LnNjYWxlICogYWRqdXN0ZWRYMCksIC0oZGlteS5zY2FsZSAqIGFkanVzdGVkWTApKTsKICAgICAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MudHJhbnNmb3JtKGRpbXguc2NhbGUsIDAsIDAsIGRpbXkuc2NhbGUsIDAsIDApOwogICAgICAgICAgICAgICAgICAgICAgICB0bXBDdHguc2F2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsaXBCYm94KGdyYXBoaWNzLCBhZGp1c3RlZFgwLCBhZGp1c3RlZFkwLCBhZGp1c3RlZFgxLCBhZGp1c3RlZFkxKTsKICAgICAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MuYmFzZVRyYW5zZm9ybSA9ICgwLCBfZGlzcGxheV91dGlscy5nZXRDdXJyZW50VHJhbnNmb3JtKShncmFwaGljcy5jdHgpOwogICAgICAgICAgICAgICAgICAgICAgICBncmFwaGljcy5leGVjdXRlT3BlcmF0b3JMaXN0KG9wZXJhdG9yTGlzdCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGdyYXBoaWNzLmVuZERyYXdpbmcoKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhczogdG1wQ2FudmFzLmNhbnZhcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlWDogZGlteC5zY2FsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlWTogZGlteS5zY2FsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldFg6IGFkanVzdGVkWDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRZOiBhZGp1c3RlZFkwCiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldFNpemVBbmRTY2FsZShzdGVwLCByZWFsT3V0cHV0U2l6ZSwgc2NhbGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3RlcCA9IE1hdGguYWJzKHN0ZXApOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXhTaXplID0gTWF0aC5tYXgoVGlsaW5nUGF0dGVybi5NQVhfUEFUVEVSTl9TSVpFLCByZWFsT3V0cHV0U2l6ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzaXplID0gTWF0aC5jZWlsKHN0ZXAgKiBzY2FsZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaXplID49IG1heFNpemUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSBtYXhTaXplOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSBzaXplIC8gc3RlcDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplCiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNsaXBCYm94KGdyYXBoaWNzLCB4MCwgeTAsIHgxLCB5MSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBiYm94V2lkdGggPSB4MSAtIHgwOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBiYm94SGVpZ2h0ID0geTEgLSB5MDsKICAgICAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MuY3R4LnJlY3QoeDAsIHkwLCBiYm94V2lkdGgsIGJib3hIZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICBncmFwaGljcy5jdXJyZW50LnVwZGF0ZVJlY3RNaW5NYXgoKDAsIF9kaXNwbGF5X3V0aWxzLmdldEN1cnJlbnRUcmFuc2Zvcm0pKGdyYXBoaWNzLmN0eCksIFt4MCwgeTAsIHgxLCB5MV0pOwogICAgICAgICAgICAgICAgICAgICAgICBncmFwaGljcy5jbGlwKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGdyYXBoaWNzLmVuZFBhdGgoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0RmlsbEFuZFN0cm9rZVN0eWxlVG9Db250ZXh0KGdyYXBoaWNzLCBwYWludFR5cGUsIGNvbG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSBncmFwaGljcy5jdHgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50ID0gZ3JhcGhpY3MuY3VycmVudDsKICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChwYWludFR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgUGFpbnRUeXBlLkNPTE9SRUQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3R4ID0gdGhpcy5jdHg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dC5maWxsU3R5bGUgPSBjdHguZmlsbFN0eWxlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQuc3Ryb2tlU3R5bGUgPSBjdHguc3Ryb2tlU3R5bGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5maWxsQ29sb3IgPSBjdHguZmlsbFN0eWxlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQuc3Ryb2tlQ29sb3IgPSBjdHguc3Ryb2tlU3R5bGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFBhaW50VHlwZS5VTkNPTE9SRUQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3NzQ29sb3IgPSBfdXRpbC5VdGlsLm1ha2VIZXhDb2xvcihjb2xvclswXSwgY29sb3JbMV0sIGNvbG9yWzJdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LmZpbGxTdHlsZSA9IGNzc0NvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRleHQuc3Ryb2tlU3R5bGUgPSBjc3NDb2xvcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LmZpbGxDb2xvciA9IGNzc0NvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQuc3Ryb2tlQ29sb3IgPSBjc3NDb2xvcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBVbnN1cHBvcnRlZCBwYWludCB0eXBlOiAke3BhaW50VHlwZX1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRQYXR0ZXJuKGN0eCwgb3duZXIsIGludmVyc2UsIHBhdGhUeXBlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtYXRyaXggPSBpbnZlcnNlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAocGF0aFR5cGUgIT09IFBhdGhUeXBlLlNIQURJTkcpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdHJpeCA9IF91dGlsLlV0aWwudHJhbnNmb3JtKG1hdHJpeCwgb3duZXIuYmFzZVRyYW5zZm9ybSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5tYXRyaXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRyaXggPSBfdXRpbC5VdGlsLnRyYW5zZm9ybShtYXRyaXgsIHRoaXMubWF0cml4KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZW1wb3JhcnlQYXR0ZXJuQ2FudmFzID0gdGhpcy5jcmVhdGVQYXR0ZXJuQ2FudmFzKG93bmVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRvbU1hdHJpeCA9IG5ldyBET01NYXRyaXgobWF0cml4KTsKICAgICAgICAgICAgICAgICAgICAgICAgZG9tTWF0cml4ID0gZG9tTWF0cml4LnRyYW5zbGF0ZSh0ZW1wb3JhcnlQYXR0ZXJuQ2FudmFzLm9mZnNldFgsIHRlbXBvcmFyeVBhdHRlcm5DYW52YXMub2Zmc2V0WSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGRvbU1hdHJpeCA9IGRvbU1hdHJpeC5zY2FsZSgxIC8gdGVtcG9yYXJ5UGF0dGVybkNhbnZhcy5zY2FsZVgsIDEgLyB0ZW1wb3JhcnlQYXR0ZXJuQ2FudmFzLnNjYWxlWSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhdHRlcm4gPSBjdHguY3JlYXRlUGF0dGVybih0ZW1wb3JhcnlQYXR0ZXJuQ2FudmFzLmNhbnZhcywgInJlcGVhdCIpOwogICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuLnNldFRyYW5zZm9ybShkb21NYXRyaXgpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0dGVybjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLlRpbGluZ1BhdHRlcm4gPSBUaWxpbmdQYXR0ZXJuOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxNDggKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCgogICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdHJ1ZQogICAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgICAgZXhwb3J0cy5jb252ZXJ0QmxhY2tBbmRXaGl0ZVRvUkdCQSA9IGNvbnZlcnRCbGFja0FuZFdoaXRlVG9SR0JBOwogICAgICAgICAgICAgICAgZXhwb3J0cy5jb252ZXJ0VG9SR0JBID0gY29udmVydFRvUkdCQTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuZ3JheVRvUkdCQSA9IGdyYXlUb1JHQkE7CiAgICAgICAgICAgICAgICB2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEpOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gY29udmVydFRvUkdCQShwYXJhbXMpIHsKICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHBhcmFtcy5raW5kKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuSW1hZ2VLaW5kLkdSQVlTQ0FMRV8xQlBQOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbnZlcnRCbGFja0FuZFdoaXRlVG9SR0JBKHBhcmFtcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuSW1hZ2VLaW5kLlJHQl8yNEJQUDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjb252ZXJ0UkdCVG9SR0JBKHBhcmFtcyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gY29udmVydEJsYWNrQW5kV2hpdGVUb1JHQkEoX3JlZikgewogICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgIHNyYywKICAgICAgICAgICAgICAgICAgICAgICAgc3JjUG9zID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgZGVzdCwKICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodCwKICAgICAgICAgICAgICAgICAgICAgICAgbm9uQmxhY2tDb2xvciA9IDB4ZmZmZmZmZmYsCiAgICAgICAgICAgICAgICAgICAgICAgIGludmVyc2VEZWNvZGUgPSBmYWxzZQogICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGJsYWNrID0gX3V0aWwuRmVhdHVyZVRlc3QuaXNMaXR0bGVFbmRpYW4gPyAweGZmMDAwMDAwIDogMHgwMDAwMDBmZjsKICAgICAgICAgICAgICAgICAgICBjb25zdCBbemVyb01hcHBpbmcsIG9uZU1hcHBpbmddID0gaW52ZXJzZURlY29kZSA/IFtub25CbGFja0NvbG9yLCBibGFja10gOiBbYmxhY2ssIG5vbkJsYWNrQ29sb3JdOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoSW5Tb3VyY2UgPSB3aWR0aCA+PiAzOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoUmVtYWluZGVyID0gd2lkdGggJiA3OwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHNyY0xlbmd0aCA9IHNyYy5sZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgZGVzdCA9IG5ldyBVaW50MzJBcnJheShkZXN0LmJ1ZmZlcik7CiAgICAgICAgICAgICAgICAgICAgbGV0IGRlc3RQb3MgPSAwOwogICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaGVpZ2h0OyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBtYXggPSBzcmNQb3MgKyB3aWR0aEluU291cmNlOyBzcmNQb3MgPCBtYXg7IHNyY1BvcysrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlbGVtID0gc3JjUG9zIDwgc3JjTGVuZ3RoID8gc3JjW3NyY1Bvc10gOiAyNTU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMDAwMDAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RbZGVzdFBvcysrXSA9IGVsZW0gJiAwYjEwMDAwMDAgPyBvbmVNYXBwaW5nIDogemVyb01hcHBpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMDAwMDAgPyBvbmVNYXBwaW5nIDogemVyb01hcHBpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMDAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RbZGVzdFBvcysrXSA9IGVsZW0gJiAwYjEwMDAgPyBvbmVNYXBwaW5nIDogemVyb01hcHBpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMDAgPyBvbmVNYXBwaW5nIDogemVyb01hcHBpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RbZGVzdFBvcysrXSA9IGVsZW0gJiAwYjEgPyBvbmVNYXBwaW5nIDogemVyb01hcHBpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdpZHRoUmVtYWluZGVyID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlbGVtID0gc3JjUG9zIDwgc3JjTGVuZ3RoID8gc3JjW3NyY1BvcysrXSA6IDI1NTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB3aWR0aFJlbWFpbmRlcjsgaisrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMSA8PCA3IC0gaiA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICBzcmNQb3MsCiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RQb3MKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gY29udmVydFJHQlRvUkdCQShfcmVmMikgewogICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgIHNyYywKICAgICAgICAgICAgICAgICAgICAgICAgc3JjUG9zID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgZGVzdCwKICAgICAgICAgICAgICAgICAgICAgICAgZGVzdFBvcyA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQKICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjI7CiAgICAgICAgICAgICAgICAgICAgbGV0IGkgPSAwOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGxlbjMyID0gc3JjLmxlbmd0aCA+PiAyOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHNyYzMyID0gbmV3IFVpbnQzMkFycmF5KHNyYy5idWZmZXIsIHNyY1BvcywgbGVuMzIpOwogICAgICAgICAgICAgICAgICAgIGlmIChfdXRpbC5GZWF0dXJlVGVzdC5pc0xpdHRsZUVuZGlhbikgewogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKDsgaSA8IGxlbjMyIC0gMjsgaSArPSAzLCBkZXN0UG9zICs9IDQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHMxID0gc3JjMzJbaV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzMiA9IHNyYzMyW2kgKyAxXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHMzID0gc3JjMzJbaSArIDJdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdFtkZXN0UG9zXSA9IHMxIHwgMHhmZjAwMDAwMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RbZGVzdFBvcyArIDFdID0gczEgPj4+IDI0IHwgczIgPDwgOCB8IDB4ZmYwMDAwMDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0W2Rlc3RQb3MgKyAyXSA9IHMyID4+PiAxNiB8IHMzIDw8IDE2IHwgMHhmZjAwMDAwMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RbZGVzdFBvcyArIDNdID0gczMgPj4+IDggfCAweGZmMDAwMDAwOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSBpICogNCwgamogPSBzcmMubGVuZ3RoOyBqIDwgamo7IGogKz0gMykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdFtkZXN0UG9zKytdID0gc3JjW2pdIHwgc3JjW2ogKyAxXSA8PCA4IHwgc3JjW2ogKyAyXSA8PCAxNiB8IDB4ZmYwMDAwMDA7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKDsgaSA8IGxlbjMyIC0gMjsgaSArPSAzLCBkZXN0UG9zICs9IDQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHMxID0gc3JjMzJbaV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzMiA9IHNyYzMyW2kgKyAxXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHMzID0gc3JjMzJbaSArIDJdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdFtkZXN0UG9zXSA9IHMxIHwgMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RbZGVzdFBvcyArIDFdID0gczEgPDwgMjQgfCBzMiA+Pj4gOCB8IDB4ZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0W2Rlc3RQb3MgKyAyXSA9IHMyIDw8IDE2IHwgczMgPj4+IDE2IHwgMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RbZGVzdFBvcyArIDNdID0gczMgPDwgOCB8IDB4ZmY7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IGkgKiA0LCBqaiA9IHNyYy5sZW5ndGg7IGogPCBqajsgaiArPSAzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSBzcmNbal0gPDwgMjQgfCBzcmNbaiArIDFdIDw8IDE2IHwgc3JjW2ogKyAyXSA8PCA4IHwgMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICBzcmNQb3MsCiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RQb3MKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gZ3JheVRvUkdCQShzcmMsIGRlc3QpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoX3V0aWwuRmVhdHVyZVRlc3QuaXNMaXR0bGVFbmRpYW4pIHsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gc3JjLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc3RbaV0gPSBzcmNbaV0gKiAweDEwMTAxIHwgMHhmZjAwMDAwMDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHNyYy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0W2ldID0gc3JjW2ldICogMHgxMDEwMTAwIHwgMHgwMDAwMDBmZjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTQ5ICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMpID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuR2xvYmFsV29ya2VyT3B0aW9ucyA9IHZvaWQgMDsKICAgICAgICAgICAgICAgIGNvbnN0IEdsb2JhbFdvcmtlck9wdGlvbnMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgICAgICAgICAgZXhwb3J0cy5HbG9iYWxXb3JrZXJPcHRpb25zID0gR2xvYmFsV29ya2VyT3B0aW9uczsKICAgICAgICAgICAgICAgIEdsb2JhbFdvcmtlck9wdGlvbnMud29ya2VyUG9ydCA9IG51bGw7CiAgICAgICAgICAgICAgICBHbG9iYWxXb3JrZXJPcHRpb25zLndvcmtlclNyYyA9ICIiOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxNTAgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCgogICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdHJ1ZQogICAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgICAgZXhwb3J0cy5NZXNzYWdlSGFuZGxlciA9IHZvaWQgMDsKICAgICAgICAgICAgICAgIHZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMSk7CiAgICAgICAgICAgICAgICBjb25zdCBDYWxsYmFja0tpbmQgPSB7CiAgICAgICAgICAgICAgICAgICAgVU5LTk9XTjogMCwKICAgICAgICAgICAgICAgICAgICBEQVRBOiAxLAogICAgICAgICAgICAgICAgICAgIEVSUk9SOiAyCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgY29uc3QgU3RyZWFtS2luZCA9IHsKICAgICAgICAgICAgICAgICAgICBVTktOT1dOOiAwLAogICAgICAgICAgICAgICAgICAgIENBTkNFTDogMSwKICAgICAgICAgICAgICAgICAgICBDQU5DRUxfQ09NUExFVEU6IDIsCiAgICAgICAgICAgICAgICAgICAgQ0xPU0U6IDMsCiAgICAgICAgICAgICAgICAgICAgRU5RVUVVRTogNCwKICAgICAgICAgICAgICAgICAgICBFUlJPUjogNSwKICAgICAgICAgICAgICAgICAgICBQVUxMOiA2LAogICAgICAgICAgICAgICAgICAgIFBVTExfQ09NUExFVEU6IDcsCiAgICAgICAgICAgICAgICAgICAgU1RBUlRfQ09NUExFVEU6IDgKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBmdW5jdGlvbiB3cmFwUmVhc29uKHJlYXNvbikgewogICAgICAgICAgICAgICAgICAgIGlmICghKHJlYXNvbiBpbnN0YW5jZW9mIEVycm9yIHx8IHR5cGVvZiByZWFzb24gPT09ICJvYmplY3QiICYmIHJlYXNvbiAhPT0gbnVsbCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgnd3JhcFJlYXNvbjogRXhwZWN0ZWQgInJlYXNvbiIgdG8gYmUgYSAocG9zc2libHkgY2xvbmVkKSBFcnJvci4nKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChyZWFzb24ubmFtZSkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJBYm9ydEV4Y2VwdGlvbiI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IF91dGlsLkFib3J0RXhjZXB0aW9uKHJlYXNvbi5tZXNzYWdlKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiTWlzc2luZ1BERkV4Y2VwdGlvbiI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IF91dGlsLk1pc3NpbmdQREZFeGNlcHRpb24ocmVhc29uLm1lc3NhZ2UpOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJQYXNzd29yZEV4Y2VwdGlvbiI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IF91dGlsLlBhc3N3b3JkRXhjZXB0aW9uKHJlYXNvbi5tZXNzYWdlLCByZWFzb24uY29kZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIlVuZXhwZWN0ZWRSZXNwb25zZUV4Y2VwdGlvbiI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IF91dGlsLlVuZXhwZWN0ZWRSZXNwb25zZUV4Y2VwdGlvbihyZWFzb24ubWVzc2FnZSwgcmVhc29uLnN0YXR1cyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIlVua25vd25FcnJvckV4Y2VwdGlvbiI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IF91dGlsLlVua25vd25FcnJvckV4Y2VwdGlvbihyZWFzb24ubWVzc2FnZSwgcmVhc29uLmRldGFpbHMpOwogICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBfdXRpbC5Vbmtub3duRXJyb3JFeGNlcHRpb24ocmVhc29uLm1lc3NhZ2UsIHJlYXNvbi50b1N0cmluZygpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBNZXNzYWdlSGFuZGxlciB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3Ioc291cmNlTmFtZSwgdGFyZ2V0TmFtZSwgY29tT2JqKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc291cmNlTmFtZSA9IHNvdXJjZU5hbWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGFyZ2V0TmFtZSA9IHRhcmdldE5hbWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tT2JqID0gY29tT2JqOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrSWQgPSAxOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbUlkID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1TaW5rcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtQ29udHJvbGxlcnMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3Rpb25IYW5kbGVyID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fb25Db21PYmpPbk1lc3NhZ2UgPSBldmVudCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gZXZlbnQuZGF0YTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnRhcmdldE5hbWUgIT09IHRoaXMuc291cmNlTmFtZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnN0cmVhbSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3NTdHJlYW1NZXNzYWdlKGRhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmNhbGxiYWNrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FsbGJhY2tJZCA9IGRhdGEuY2FsbGJhY2tJZDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYXBhYmlsaXR5ID0gdGhpcy5jYWxsYmFja0NhcGFiaWxpdGllc1tjYWxsYmFja0lkXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNhcGFiaWxpdHkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgcmVzb2x2ZSBjYWxsYmFjayAke2NhbGxiYWNrSWR9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzW2NhbGxiYWNrSWRdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmNhbGxiYWNrID09PSBDYWxsYmFja0tpbmQuREFUQSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXBhYmlsaXR5LnJlc29sdmUoZGF0YS5kYXRhKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGEuY2FsbGJhY2sgPT09IENhbGxiYWNrS2luZC5FUlJPUikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXBhYmlsaXR5LnJlamVjdCh3cmFwUmVhc29uKGRhdGEucmVhc29uKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJVbmV4cGVjdGVkIGNhbGxiYWNrIGNhc2UiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYWN0aW9uID0gdGhpcy5hY3Rpb25IYW5kbGVyW2RhdGEuYWN0aW9uXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYWN0aW9uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGFjdGlvbiBmcm9tIHdvcmtlcjogJHtkYXRhLmFjdGlvbn1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmNhbGxiYWNrSWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYlNvdXJjZU5hbWUgPSB0aGlzLnNvdXJjZU5hbWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2JUYXJnZXROYW1lID0gZGF0YS5zb3VyY2VOYW1lOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoYWN0aW9uKGRhdGEuZGF0YSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlTmFtZTogY2JTb3VyY2VOYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TmFtZTogY2JUYXJnZXROYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2s6IENhbGxiYWNrS2luZC5EQVRBLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2tJZDogZGF0YS5jYWxsYmFja0lkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YTogcmVzdWx0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU5hbWU6IGNiU291cmNlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldE5hbWU6IGNiVGFyZ2V0TmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrOiBDYWxsYmFja0tpbmQuRVJST1IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFja0lkOiBkYXRhLmNhbGxiYWNrSWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFzb246IHdyYXBSZWFzb24ocmVhc29uKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5zdHJlYW1JZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZVN0cmVhbVNpbmsoZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uKGRhdGEuZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbU9iai5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwgdGhpcy5fb25Db21PYmpPbk1lc3NhZ2UpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBvbihhY3Rpb25OYW1lLCBoYW5kbGVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFoID0gdGhpcy5hY3Rpb25IYW5kbGVyOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWhbYWN0aW9uTmFtZV0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlcmUgaXMgYWxyZWFkeSBhbiBhY3Rpb25OYW1lIGNhbGxlZCAiJHthY3Rpb25OYW1lfSJgKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBhaFthY3Rpb25OYW1lXSA9IGhhbmRsZXI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNlbmQoYWN0aW9uTmFtZSwgZGF0YSwgdHJhbnNmZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU5hbWU6IHRoaXMuc291cmNlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldE5hbWU6IHRoaXMudGFyZ2V0TmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbjogYWN0aW9uTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEKICAgICAgICAgICAgICAgICAgICAgICAgfSwgdHJhbnNmZXJzKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2VuZFdpdGhQcm9taXNlKGFjdGlvbk5hbWUsIGRhdGEsIHRyYW5zZmVycykgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYWxsYmFja0lkID0gdGhpcy5jYWxsYmFja0lkKys7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tDYXBhYmlsaXRpZXNbY2FsbGJhY2tJZF0gPSBjYXBhYmlsaXR5OwogICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU5hbWU6IHRoaXMuc291cmNlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXROYW1lOiB0aGlzLnRhcmdldE5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBhY3Rpb25OYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrSWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgdHJhbnNmZXJzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcGFiaWxpdHkucmVqZWN0KGV4KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzZW5kV2l0aFN0cmVhbShhY3Rpb25OYW1lLCBkYXRhLCBxdWV1ZWluZ1N0cmF0ZWd5LCB0cmFuc2ZlcnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyZWFtSWQgPSB0aGlzLnN0cmVhbUlkKyssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VOYW1lID0gdGhpcy5zb3VyY2VOYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TmFtZSA9IHRoaXMudGFyZ2V0TmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbU9iaiA9IHRoaXMuY29tT2JqOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFJlYWRhYmxlU3RyZWFtKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0OiBjb250cm9sbGVyID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGFydENhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1Db250cm9sbGVyc1tzdHJlYW1JZF0gPSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2xsZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0Q2FsbDogc3RhcnRDYXBhYmlsaXR5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdWxsQ2FsbDogbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FuY2VsQ2FsbDogbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNDbG9zZWQ6IGZhbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb246IGFjdGlvbk5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpcmVkU2l6ZTogY29udHJvbGxlci5kZXNpcmVkU2l6ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIHRyYW5zZmVycyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0YXJ0Q2FwYWJpbGl0eS5wcm9taXNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1bGw6IGNvbnRyb2xsZXIgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHB1bGxDYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdLnB1bGxDYWxsID0gcHVsbENhcGFiaWxpdHk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLlBVTEwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpcmVkU2l6ZTogY29udHJvbGxlci5kZXNpcmVkU2l6ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwdWxsQ2FwYWJpbGl0eS5wcm9taXNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbmNlbDogcmVhc29uID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwuYXNzZXJ0KShyZWFzb24gaW5zdGFuY2VvZiBFcnJvciwgImNhbmNlbCBtdXN0IGhhdmUgYSB2YWxpZCByZWFzb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYW5jZWxDYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdLmNhbmNlbENhbGwgPSBjYW5jZWxDYXBhYmlsaXR5OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdLmlzQ2xvc2VkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuQ0FOQ0VMLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uOiB3cmFwUmVhc29uKHJlYXNvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FuY2VsQ2FwYWJpbGl0eS5wcm9taXNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9LCBxdWV1ZWluZ1N0cmF0ZWd5KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2NyZWF0ZVN0cmVhbVNpbmsoZGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1JZCA9IGRhdGEuc3RyZWFtSWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VOYW1lID0gdGhpcy5zb3VyY2VOYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TmFtZSA9IGRhdGEuc291cmNlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbU9iaiA9IHRoaXMuY29tT2JqOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzZWxmID0gdGhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjdGlvbiA9IHRoaXMuYWN0aW9uSGFuZGxlcltkYXRhLmFjdGlvbl07CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cmVhbVNpbmsgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbnF1ZXVlKGNodW5rKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNpemUgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRyYW5zZmVycyA9IGFyZ3VtZW50cy5sZW5ndGggPiAyID8gYXJndW1lbnRzWzJdIDogdW5kZWZpbmVkOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzQ2FuY2VsbGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbGFzdERlc2lyZWRTaXplID0gdGhpcy5kZXNpcmVkU2l6ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlc2lyZWRTaXplIC09IHNpemU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3REZXNpcmVkU2l6ZSA+IDAgJiYgdGhpcy5kZXNpcmVkU2l6ZSA8PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2lua0NhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVhZHkgPSB0aGlzLnNpbmtDYXBhYmlsaXR5LnByb21pc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5FTlFVRVVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2h1bmsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCB0cmFuc2ZlcnMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzQ2FuY2VsbGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0NhbmNlbGxlZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLkNMT1NFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBzZWxmLnN0cmVhbVNpbmtzW3N0cmVhbUlkXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcihyZWFzb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwuYXNzZXJ0KShyZWFzb24gaW5zdGFuY2VvZiBFcnJvciwgImVycm9yIG11c3QgaGF2ZSBhIHZhbGlkIHJlYXNvbiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzQ2FuY2VsbGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0NhbmNlbGxlZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLkVSUk9SLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhc29uOiB3cmFwUmVhc29uKHJlYXNvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW5rQ2FwYWJpbGl0eTogKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb25QdWxsOiBudWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb25DYW5jZWw6IG51bGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0NhbmNlbGxlZDogZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpcmVkU2l6ZTogZGF0YS5kZXNpcmVkU2l6ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWR5OiBudWxsCiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbVNpbmsuc2lua0NhcGFiaWxpdHkucmVzb2x2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1TaW5rLnJlYWR5ID0gc3RyZWFtU2luay5zaW5rQ2FwYWJpbGl0eS5wcm9taXNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbVNpbmtzW3N0cmVhbUlkXSA9IHN0cmVhbVNpbms7CiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGFjdGlvbihkYXRhLmRhdGEsIHN0cmVhbVNpbmspKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuU1RBUlRfQ09NUExFVEUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2VzczogdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5TVEFSVF9DT01QTEVURSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFzb246IHdyYXBSZWFzb24ocmVhc29uKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfcHJvY2Vzc1N0cmVhbU1lc3NhZ2UoZGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1JZCA9IGRhdGEuc3RyZWFtSWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VOYW1lID0gdGhpcy5zb3VyY2VOYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TmFtZSA9IGRhdGEuc291cmNlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbU9iaiA9IHRoaXMuY29tT2JqOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1Db250cm9sbGVyID0gdGhpcy5zdHJlYW1Db250cm9sbGVyc1tzdHJlYW1JZF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1TaW5rID0gdGhpcy5zdHJlYW1TaW5rc1tzdHJlYW1JZF07CiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZGF0YS5zdHJlYW0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU3RyZWFtS2luZC5TVEFSVF9DT01QTEVURToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5zdWNjZXNzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUNvbnRyb2xsZXIuc3RhcnRDYWxsLnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1Db250cm9sbGVyLnN0YXJ0Q2FsbC5yZWplY3Qod3JhcFJlYXNvbihkYXRhLnJlYXNvbikpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU3RyZWFtS2luZC5QVUxMX0NPTVBMRVRFOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnN1Y2Nlc3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtQ29udHJvbGxlci5wdWxsQ2FsbC5yZXNvbHZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtQ29udHJvbGxlci5wdWxsQ2FsbC5yZWplY3Qod3JhcFJlYXNvbihkYXRhLnJlYXNvbikpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgU3RyZWFtS2luZC5QVUxMOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc3RyZWFtU2luaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuUFVMTF9DT01QTEVURSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2VzczogdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdHJlYW1TaW5rLmRlc2lyZWRTaXplIDw9IDAgJiYgZGF0YS5kZXNpcmVkU2l6ZSA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtU2luay5zaW5rQ2FwYWJpbGl0eS5yZXNvbHZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbVNpbmsuZGVzaXJlZFNpemUgPSBkYXRhLmRlc2lyZWRTaXplOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoc3RyZWFtU2luay5vblB1bGwgJiYgc3RyZWFtU2luay5vblB1bGwoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5QVUxMX0NPTVBMRVRFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWNjZXNzOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLlBVTExfQ09NUExFVEUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogd3JhcFJlYXNvbihyZWFzb24pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTdHJlYW1LaW5kLkVOUVVFVUU6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLmFzc2VydCkoc3RyZWFtQ29udHJvbGxlciwgImVucXVldWUgc2hvdWxkIGhhdmUgc3RyZWFtIGNvbnRyb2xsZXIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RyZWFtQ29udHJvbGxlci5pc0Nsb3NlZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtQ29udHJvbGxlci5jb250cm9sbGVyLmVucXVldWUoZGF0YS5jaHVuayk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFN0cmVhbUtpbmQuQ0xPU0U6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLmFzc2VydCkoc3RyZWFtQ29udHJvbGxlciwgImNsb3NlIHNob3VsZCBoYXZlIHN0cmVhbSBjb250cm9sbGVyIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0cmVhbUNvbnRyb2xsZXIuaXNDbG9zZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUNvbnRyb2xsZXIuaXNDbG9zZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUNvbnRyb2xsZXIuY29udHJvbGxlci5jbG9zZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RlbGV0ZVN0cmVhbUNvbnRyb2xsZXIoc3RyZWFtQ29udHJvbGxlciwgc3RyZWFtSWQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBTdHJlYW1LaW5kLkVSUk9SOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC5hc3NlcnQpKHN0cmVhbUNvbnRyb2xsZXIsICJlcnJvciBzaG91bGQgaGF2ZSBzdHJlYW0gY29udHJvbGxlciIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUNvbnRyb2xsZXIuY29udHJvbGxlci5lcnJvcih3cmFwUmVhc29uKGRhdGEucmVhc29uKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGVsZXRlU3RyZWFtQ29udHJvbGxlcihzdHJlYW1Db250cm9sbGVyLCBzdHJlYW1JZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFN0cmVhbUtpbmQuQ0FOQ0VMX0NPTVBMRVRFOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnN1Y2Nlc3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtQ29udHJvbGxlci5jYW5jZWxDYWxsLnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1Db250cm9sbGVyLmNhbmNlbENhbGwucmVqZWN0KHdyYXBSZWFzb24oZGF0YS5yZWFzb24pKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGVsZXRlU3RyZWFtQ29udHJvbGxlcihzdHJlYW1Db250cm9sbGVyLCBzdHJlYW1JZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFN0cmVhbUtpbmQuQ0FOQ0VMOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc3RyZWFtU2luaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShzdHJlYW1TaW5rLm9uQ2FuY2VsICYmIHN0cmVhbVNpbmsub25DYW5jZWwod3JhcFJlYXNvbihkYXRhLnJlYXNvbikpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLkNBTkNFTF9DT01QTEVURSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VjY2VzczogdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5DQU5DRUxfQ09NUExFVEUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYXNvbjogd3JhcFJlYXNvbihyZWFzb24pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbVNpbmsuc2lua0NhcGFiaWxpdHkucmVqZWN0KHdyYXBSZWFzb24oZGF0YS5yZWFzb24pKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJlYW1TaW5rLmlzQ2FuY2VsbGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW1TaW5rc1tzdHJlYW1JZF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiVW5leHBlY3RlZCBzdHJlYW0gY2FzZSIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFzeW5jIF9kZWxldGVTdHJlYW1Db250cm9sbGVyKHN0cmVhbUNvbnRyb2xsZXIsIHN0cmVhbUlkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChbc3RyZWFtQ29udHJvbGxlci5zdGFydENhbGwgJiYgc3RyZWFtQ29udHJvbGxlci5zdGFydENhbGwucHJvbWlzZSwgc3RyZWFtQ29udHJvbGxlci5wdWxsQ2FsbCAmJiBzdHJlYW1Db250cm9sbGVyLnB1bGxDYWxsLnByb21pc2UsIHN0cmVhbUNvbnRyb2xsZXIuY2FuY2VsQ2FsbCAmJiBzdHJlYW1Db250cm9sbGVyLmNhbmNlbENhbGwucHJvbWlzZV0pOwogICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW1Db250cm9sbGVyc1tzdHJlYW1JZF07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRlc3Ryb3koKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tT2JqLnJlbW92ZUV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCB0aGlzLl9vbkNvbU9iak9uTWVzc2FnZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5NZXNzYWdlSGFuZGxlciA9IE1lc3NhZ2VIYW5kbGVyOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxNTEgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCgogICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdHJ1ZQogICAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgICAgZXhwb3J0cy5NZXRhZGF0YSA9IHZvaWQgMDsKICAgICAgICAgICAgICAgIHZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMSk7CiAgICAgICAgICAgICAgICBjbGFzcyBNZXRhZGF0YSB7CiAgICAgICAgICAgICAgICAgICAgI21ldGFkYXRhTWFwOwogICAgICAgICAgICAgICAgICAgICNkYXRhOwogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKF9yZWYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcnNlZERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdEYXRhCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNtZXRhZGF0YU1hcCA9IHBhcnNlZERhdGE7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuI2RhdGEgPSByYXdEYXRhOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRSYXcoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiNkYXRhOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQobmFtZSkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy4jbWV0YWRhdGFNYXAuZ2V0KG5hbWUpID8/IG51bGw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldEFsbCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICgwLCBfdXRpbC5vYmplY3RGcm9tTWFwKSh0aGlzLiNtZXRhZGF0YU1hcCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGhhcyhuYW1lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiNtZXRhZGF0YU1hcC5oYXMobmFtZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5NZXRhZGF0YSA9IE1ldGFkYXRhOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxNTIgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCgogICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdHJ1ZQogICAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgICAgZXhwb3J0cy5PcHRpb25hbENvbnRlbnRDb25maWcgPSB2b2lkIDA7CiAgICAgICAgICAgICAgICB2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEpOwogICAgICAgICAgICAgICAgdmFyIF9tdXJtdXJoYXNoID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDQpOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKG9iaiwgcHJpdmF0ZVNldCkgeyBfY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbihvYmosIHByaXZhdGVTZXQpOyBwcml2YXRlU2V0LmFkZChvYmopOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyhvYmosIHByaXZhdGVNYXAsIHZhbHVlKSB7IF9jaGVja1ByaXZhdGVSZWRlY2xhcmF0aW9uKG9iaiwgcHJpdmF0ZU1hcCk7IHByaXZhdGVNYXAuc2V0KG9iaiwgdmFsdWUpOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbihvYmosIHByaXZhdGVDb2xsZWN0aW9uKSB7IGlmIChwcml2YXRlQ29sbGVjdGlvbi5oYXMob2JqKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgaW5pdGlhbGl6ZSB0aGUgc2FtZSBwcml2YXRlIGVsZW1lbnRzIHR3aWNlIG9uIGFuIG9iamVjdCIpOyB9IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQocmVjZWl2ZXIsIHByaXZhdGVTZXQsIGZuKSB7IGlmICghcHJpdmF0ZVNldC5oYXMocmVjZWl2ZXIpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoImF0dGVtcHRlZCB0byBnZXQgcHJpdmF0ZSBmaWVsZCBvbiBub24taW5zdGFuY2UiKTsgfSByZXR1cm4gZm47IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVGaWVsZEdldChyZWNlaXZlciwgcHJpdmF0ZU1hcCkgeyB2YXIgZGVzY3JpcHRvciA9IF9jbGFzc0V4dHJhY3RGaWVsZERlc2NyaXB0b3IocmVjZWl2ZXIsIHByaXZhdGVNYXAsICJnZXQiKTsgcmV0dXJuIF9jbGFzc0FwcGx5RGVzY3JpcHRvckdldChyZWNlaXZlciwgZGVzY3JpcHRvcik7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc0FwcGx5RGVzY3JpcHRvckdldChyZWNlaXZlciwgZGVzY3JpcHRvcikgeyBpZiAoZGVzY3JpcHRvci5nZXQpIHsgcmV0dXJuIGRlc2NyaXB0b3IuZ2V0LmNhbGwocmVjZWl2ZXIpOyB9IHJldHVybiBkZXNjcmlwdG9yLnZhbHVlOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlRmllbGRTZXQocmVjZWl2ZXIsIHByaXZhdGVNYXAsIHZhbHVlKSB7IHZhciBkZXNjcmlwdG9yID0gX2NsYXNzRXh0cmFjdEZpZWxkRGVzY3JpcHRvcihyZWNlaXZlciwgcHJpdmF0ZU1hcCwgInNldCIpOyBfY2xhc3NBcHBseURlc2NyaXB0b3JTZXQocmVjZWl2ZXIsIGRlc2NyaXB0b3IsIHZhbHVlKTsgcmV0dXJuIHZhbHVlOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NFeHRyYWN0RmllbGREZXNjcmlwdG9yKHJlY2VpdmVyLCBwcml2YXRlTWFwLCBhY3Rpb24pIHsgaWYgKCFwcml2YXRlTWFwLmhhcyhyZWNlaXZlcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigiYXR0ZW1wdGVkIHRvICIgKyBhY3Rpb24gKyAiIHByaXZhdGUgZmllbGQgb24gbm9uLWluc3RhbmNlIik7IH0gcmV0dXJuIHByaXZhdGVNYXAuZ2V0KHJlY2VpdmVyKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzQXBwbHlEZXNjcmlwdG9yU2V0KHJlY2VpdmVyLCBkZXNjcmlwdG9yLCB2YWx1ZSkgeyBpZiAoZGVzY3JpcHRvci5zZXQpIHsgZGVzY3JpcHRvci5zZXQuY2FsbChyZWNlaXZlciwgdmFsdWUpOyB9IGVsc2UgeyBpZiAoIWRlc2NyaXB0b3Iud3JpdGFibGUpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigiYXR0ZW1wdGVkIHRvIHNldCByZWFkIG9ubHkgcHJpdmF0ZSBmaWVsZCIpOyB9IGRlc2NyaXB0b3IudmFsdWUgPSB2YWx1ZTsgfSB9CiAgICAgICAgICAgICAgICBjb25zdCBJTlRFUk5BTCA9IFN5bWJvbCgiSU5URVJOQUwiKTsKICAgICAgICAgICAgICAgIGNsYXNzIE9wdGlvbmFsQ29udGVudEdyb3VwIHsKICAgICAgICAgICAgICAgICAgICAjdmlzaWJsZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IobmFtZSwgaW50ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW50ZW50ID0gaW50ZW50OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgdmlzaWJsZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuI3Zpc2libGU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9zZXRWaXNpYmxlKGludGVybmFsLCB2aXNpYmxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnRlcm5hbCAhPT0gSU5URVJOQUwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIkludGVybmFsIG1ldGhvZCBgX3NldFZpc2libGVgIGNhbGxlZC4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiN2aXNpYmxlID0gdmlzaWJsZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB2YXIgX2NhY2hlZEdldEhhc2ggPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfZ3JvdXBzID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2luaXRpYWxIYXNoID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX29yZGVyID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2V2YWx1YXRlVmlzaWJpbGl0eUV4cHJlc3Npb24gPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIGNsYXNzIE9wdGlvbmFsQ29udGVudENvbmZpZyB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IoZGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2V2YWx1YXRlVmlzaWJpbGl0eUV4cHJlc3Npb24pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfY2FjaGVkR2V0SGFzaCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogbnVsbAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2dyb3VwcywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogbmV3IE1hcCgpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfaW5pdGlhbEhhc2gsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG51bGwKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9vcmRlciwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogbnVsbAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5uYW1lID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jcmVhdG9yID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEgPT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5hbWUgPSBkYXRhLm5hbWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3JlYXRvciA9IGRhdGEuY3JlYXRvcjsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9vcmRlciwgZGF0YS5vcmRlcik7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZ3JvdXAgb2YgZGF0YS5ncm91cHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZ3JvdXBzKS5zZXQoZ3JvdXAuaWQsIG5ldyBPcHRpb25hbENvbnRlbnRHcm91cChncm91cC5uYW1lLCBncm91cC5pbnRlbnQpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5iYXNlU3RhdGUgPT09ICJPRkYiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGdyb3VwIG9mIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZ3JvdXBzKS52YWx1ZXMoKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLl9zZXRWaXNpYmxlKElOVEVSTkFMLCBmYWxzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBvbiBvZiBkYXRhLm9uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2dyb3VwcykuZ2V0KG9uKS5fc2V0VmlzaWJsZShJTlRFUk5BTCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBvZmYgb2YgZGF0YS5vZmYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZ3JvdXBzKS5nZXQob2ZmKS5fc2V0VmlzaWJsZShJTlRFUk5BTCwgZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfaW5pdGlhbEhhc2gsIHRoaXMuZ2V0SGFzaCgpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaXNWaXNpYmxlKGdyb3VwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2dyb3Vwcykuc2l6ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFncm91cCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJPcHRpb25hbCBjb250ZW50IGdyb3VwIG5vdCBkZWZpbmVkLiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdyb3VwLnR5cGUgPT09ICJPQ0ciKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIV9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZ3JvdXBzKS5oYXMoZ3JvdXAuaWQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBPcHRpb25hbCBjb250ZW50IGdyb3VwIG5vdCBmb3VuZDogJHtncm91cC5pZH1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2dyb3VwcykuZ2V0KGdyb3VwLmlkKS52aXNpYmxlOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGdyb3VwLnR5cGUgPT09ICJPQ01EIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdyb3VwLmV4cHJlc3Npb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfZXZhbHVhdGVWaXNpYmlsaXR5RXhwcmVzc2lvbiwgX2V2YWx1YXRlVmlzaWJpbGl0eUV4cHJlc3Npb24yKS5jYWxsKHRoaXMsIGdyb3VwLmV4cHJlc3Npb24pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFncm91cC5wb2xpY3kgfHwgZ3JvdXAucG9saWN5ID09PSAiQW55T24iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBpZCBvZiBncm91cC5pZHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2dyb3VwcykuaGFzKGlkKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBPcHRpb25hbCBjb250ZW50IGdyb3VwIG5vdCBmb3VuZDogJHtpZH1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2dyb3VwcykuZ2V0KGlkKS52aXNpYmxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGdyb3VwLnBvbGljeSA9PT0gIkFsbE9uIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaWQgb2YgZ3JvdXAuaWRzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ncm91cHMpLmhhcyhpZCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgT3B0aW9uYWwgY29udGVudCBncm91cCBub3QgZm91bmQ6ICR7aWR9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIV9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZ3JvdXBzKS5nZXQoaWQpLnZpc2libGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZ3JvdXAucG9saWN5ID09PSAiQW55T2ZmIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaWQgb2YgZ3JvdXAuaWRzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ncm91cHMpLmhhcyhpZCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgT3B0aW9uYWwgY29udGVudCBncm91cCBub3QgZm91bmQ6ICR7aWR9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIV9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZ3JvdXBzKS5nZXQoaWQpLnZpc2libGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZ3JvdXAucG9saWN5ID09PSAiQWxsT2ZmIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaWQgb2YgZ3JvdXAuaWRzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ncm91cHMpLmhhcyhpZCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgT3B0aW9uYWwgY29udGVudCBncm91cCBub3QgZm91bmQ6ICR7aWR9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ncm91cHMpLmdldChpZCkudmlzaWJsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBVbmtub3duIG9wdGlvbmFsIGNvbnRlbnQgcG9saWN5ICR7Z3JvdXAucG9saWN5fS5gKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgVW5rbm93biBncm91cCB0eXBlICR7Z3JvdXAudHlwZX0uYCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzZXRWaXNpYmlsaXR5KGlkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB2aXNpYmxlID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIV9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZ3JvdXBzKS5oYXMoaWQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYE9wdGlvbmFsIGNvbnRlbnQgZ3JvdXAgbm90IGZvdW5kOiAke2lkfWApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZ3JvdXBzKS5nZXQoaWQpLl9zZXRWaXNpYmxlKElOVEVSTkFMLCAhIXZpc2libGUpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2NhY2hlZEdldEhhc2gsIG51bGwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgaGFzSW5pdGlhbFZpc2liaWxpdHkoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEhhc2goKSA9PT0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9pbml0aWFsSGFzaCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldE9yZGVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIV9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZ3JvdXBzKS5zaXplKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9vcmRlcikpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX29yZGVyKS5zbGljZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbLi4uX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ncm91cHMpLmtleXMoKV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldEdyb3VwcygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZ3JvdXBzKS5zaXplID4gMCA/ICgwLCBfdXRpbC5vYmplY3RGcm9tTWFwKShfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2dyb3VwcykpIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0R3JvdXAoaWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZ3JvdXBzKS5nZXQoaWQpIHx8IG51bGw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldEhhc2goKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2NhY2hlZEdldEhhc2gpICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9jYWNoZWRHZXRIYXNoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoYXNoID0gbmV3IF9tdXJtdXJoYXNoLk11cm11ckhhc2gzXzY0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgW2lkLCBncm91cF0gb2YgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ncm91cHMpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNoLnVwZGF0ZShgJHtpZH06JHtncm91cC52aXNpYmxlfWApOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2NhY2hlZEdldEhhc2gsIGhhc2guaGV4ZGlnZXN0KCkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuT3B0aW9uYWxDb250ZW50Q29uZmlnID0gT3B0aW9uYWxDb250ZW50Q29uZmlnOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2V2YWx1YXRlVmlzaWJpbGl0eUV4cHJlc3Npb24yKGFycmF5KSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGVuZ3RoID0gYXJyYXkubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIGlmIChsZW5ndGggPCAyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBvcGVyYXRvciA9IGFycmF5WzBdOwogICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IGFycmF5W2ldOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhdGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGVsZW1lbnQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZSA9IF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2V2YWx1YXRlVmlzaWJpbGl0eUV4cHJlc3Npb24sIF9ldmFsdWF0ZVZpc2liaWxpdHlFeHByZXNzaW9uMikuY2FsbCh0aGlzLCBlbGVtZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2dyb3VwcykuaGFzKGVsZW1lbnQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZSA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZ3JvdXBzKS5nZXQoZWxlbWVudCkudmlzaWJsZTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgT3B0aW9uYWwgY29udGVudCBncm91cCBub3QgZm91bmQ6ICR7ZWxlbWVudH1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAob3BlcmF0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIkFuZCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzdGF0ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiT3IiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGF0ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJOb3QiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhc3RhdGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiBvcGVyYXRvciA9PT0gIkFuZCI7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDE1MyAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLlBERkRhdGFUcmFuc3BvcnRTdHJlYW0gPSB2b2lkIDA7CiAgICAgICAgICAgICAgICB2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEpOwogICAgICAgICAgICAgICAgdmFyIF9kaXNwbGF5X3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDIpOwogICAgICAgICAgICAgICAgY2xhc3MgUERGRGF0YVRyYW5zcG9ydFN0cmVhbSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IoX3JlZiwgcGRmRGF0YVJhbmdlVHJhbnNwb3J0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsRGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzaXZlRG9uZSA9IGZhbHNlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudERpc3Bvc2l0aW9uRmlsZW5hbWUgPSBudWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZVJhbmdlID0gZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlU3RyZWFtID0gZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IF9yZWY7CiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC5hc3NlcnQpKHBkZkRhdGFSYW5nZVRyYW5zcG9ydCwgJ1BERkRhdGFUcmFuc3BvcnRTdHJlYW0gLSBtaXNzaW5nIHJlcXVpcmVkICJwZGZEYXRhUmFuZ2VUcmFuc3BvcnQiIGFyZ3VtZW50LicpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9xdWV1ZWRDaHVua3MgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcHJvZ3Jlc3NpdmVEb25lID0gcHJvZ3Jlc3NpdmVEb25lOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb250ZW50RGlzcG9zaXRpb25GaWxlbmFtZSA9IGNvbnRlbnREaXNwb3NpdGlvbkZpbGVuYW1lOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGluaXRpYWxEYXRhID09PSBudWxsIHx8IGluaXRpYWxEYXRhID09PSB2b2lkIDAgPyB2b2lkIDAgOiBpbml0aWFsRGF0YS5sZW5ndGgpID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYnVmZmVyID0gaW5pdGlhbERhdGEgaW5zdGFuY2VvZiBVaW50OEFycmF5ICYmIGluaXRpYWxEYXRhLmJ5dGVMZW5ndGggPT09IGluaXRpYWxEYXRhLmJ1ZmZlci5ieXRlTGVuZ3RoID8gaW5pdGlhbERhdGEuYnVmZmVyIDogbmV3IFVpbnQ4QXJyYXkoaW5pdGlhbERhdGEpLmJ1ZmZlcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3F1ZXVlZENodW5rcy5wdXNoKGJ1ZmZlcik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGRmRGF0YVJhbmdlVHJhbnNwb3J0ID0gcGRmRGF0YVJhbmdlVHJhbnNwb3J0OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9pc1N0cmVhbWluZ1N1cHBvcnRlZCA9ICFkaXNhYmxlU3RyZWFtOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9pc1JhbmdlU3VwcG9ydGVkID0gIWRpc2FibGVSYW5nZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29udGVudExlbmd0aCA9IGxlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXIgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yYW5nZVJlYWRlcnMgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGRmRGF0YVJhbmdlVHJhbnNwb3J0LmFkZFJhbmdlTGlzdGVuZXIoKGJlZ2luLCBjaHVuaykgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fb25SZWNlaXZlRGF0YSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVnaW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2h1bmsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGRmRGF0YVJhbmdlVHJhbnNwb3J0LmFkZFByb2dyZXNzTGlzdGVuZXIoKGxvYWRlZCwgdG90YWwpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX29uUHJvZ3Jlc3MoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvYWRlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3RhbAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wZGZEYXRhUmFuZ2VUcmFuc3BvcnQuYWRkUHJvZ3Jlc3NpdmVSZWFkTGlzdGVuZXIoY2h1bmsgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fb25SZWNlaXZlRGF0YSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2h1bmsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGRmRGF0YVJhbmdlVHJhbnNwb3J0LmFkZFByb2dyZXNzaXZlRG9uZUxpc3RlbmVyKCgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX29uUHJvZ3Jlc3NpdmVEb25lKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wZGZEYXRhUmFuZ2VUcmFuc3BvcnQudHJhbnNwb3J0UmVhZHkoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX29uUmVjZWl2ZURhdGEoX3JlZjIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2h1bmsKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IF9yZWYyOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBidWZmZXIgPSBjaHVuayBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkgJiYgY2h1bmsuYnl0ZUxlbmd0aCA9PT0gY2h1bmsuYnVmZmVyLmJ5dGVMZW5ndGggPyBjaHVuay5idWZmZXIgOiBuZXcgVWludDhBcnJheShjaHVuaykuYnVmZmVyOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmVnaW4gPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXIuX2VucXVldWUoYnVmZmVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcXVldWVkQ2h1bmtzLnB1c2goYnVmZmVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvdW5kID0gdGhpcy5fcmFuZ2VSZWFkZXJzLnNvbWUoZnVuY3Rpb24gKHJhbmdlUmVhZGVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJhbmdlUmVhZGVyLl9iZWdpbiAhPT0gYmVnaW4pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5nZVJlYWRlci5fZW5xdWV1ZShidWZmZXIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwuYXNzZXJ0KShmb3VuZCwgIl9vblJlY2VpdmVEYXRhIC0gbm8gYFBERkRhdGFUcmFuc3BvcnRTdHJlYW1SYW5nZVJlYWRlcmAgaW5zdGFuY2UgZm91bmQuIik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IF9wcm9ncmVzc2l2ZURhdGFMZW5ndGgoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRfZnVsbFJlcXVlc3RSZWE7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoKF90aGlzJF9mdWxsUmVxdWVzdFJlYSA9IHRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyKSA9PT0gbnVsbCB8fCBfdGhpcyRfZnVsbFJlcXVlc3RSZWEgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJF9mdWxsUmVxdWVzdFJlYS5fbG9hZGVkKSA/PyAwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfb25Qcm9ncmVzcyhldnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV2dC50b3RhbCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkX3JhbmdlUmVhZGVycyQsIF90aGlzJF9yYW5nZVJlYWRlcnMkJDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRfcmFuZ2VSZWFkZXJzJCA9IHRoaXMuX3JhbmdlUmVhZGVyc1swXSkgPT09IG51bGwgfHwgX3RoaXMkX3JhbmdlUmVhZGVycyQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IChfdGhpcyRfcmFuZ2VSZWFkZXJzJCQgPSBfdGhpcyRfcmFuZ2VSZWFkZXJzJC5vblByb2dyZXNzKSA9PT0gbnVsbCB8fCBfdGhpcyRfcmFuZ2VSZWFkZXJzJCQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJF9yYW5nZVJlYWRlcnMkJC5jYWxsKF90aGlzJF9yYW5nZVJlYWRlcnMkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkOiBldnQubG9hZGVkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRfZnVsbFJlcXVlc3RSZWEyLCBfdGhpcyRfZnVsbFJlcXVlc3RSZWEzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJF9mdWxsUmVxdWVzdFJlYTIgPSB0aGlzLl9mdWxsUmVxdWVzdFJlYWRlcikgPT09IG51bGwgfHwgX3RoaXMkX2Z1bGxSZXF1ZXN0UmVhMiA9PT0gdm9pZCAwID8gdm9pZCAwIDogKF90aGlzJF9mdWxsUmVxdWVzdFJlYTMgPSBfdGhpcyRfZnVsbFJlcXVlc3RSZWEyLm9uUHJvZ3Jlc3MpID09PSBudWxsIHx8IF90aGlzJF9mdWxsUmVxdWVzdFJlYTMgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJF9mdWxsUmVxdWVzdFJlYTMuY2FsbChfdGhpcyRfZnVsbFJlcXVlc3RSZWEyLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkOiBldnQubG9hZGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsOiBldnQudG90YWwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9vblByb2dyZXNzaXZlRG9uZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJF9mdWxsUmVxdWVzdFJlYTQ7CiAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRfZnVsbFJlcXVlc3RSZWE0ID0gdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXIpID09PSBudWxsIHx8IF90aGlzJF9mdWxsUmVxdWVzdFJlYTQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJF9mdWxsUmVxdWVzdFJlYTQucHJvZ3Jlc3NpdmVEb25lKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Byb2dyZXNzaXZlRG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9yZW1vdmVSYW5nZVJlYWRlcihyZWFkZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaSA9IHRoaXMuX3JhbmdlUmVhZGVycy5pbmRleE9mKHJlYWRlcik7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpID49IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JhbmdlUmVhZGVycy5zcGxpY2UoaSwgMSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0RnVsbFJlYWRlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLmFzc2VydCkoIXRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyLCAiUERGRGF0YVRyYW5zcG9ydFN0cmVhbS5nZXRGdWxsUmVhZGVyIGNhbiBvbmx5IGJlIGNhbGxlZCBvbmNlLiIpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBxdWV1ZWRDaHVua3MgPSB0aGlzLl9xdWV1ZWRDaHVua3M7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3F1ZXVlZENodW5rcyA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUERGRGF0YVRyYW5zcG9ydFN0cmVhbVJlYWRlcih0aGlzLCBxdWV1ZWRDaHVua3MsIHRoaXMuX3Byb2dyZXNzaXZlRG9uZSwgdGhpcy5fY29udGVudERpc3Bvc2l0aW9uRmlsZW5hbWUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRSYW5nZVJlYWRlcihiZWdpbiwgZW5kKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbmQgPD0gdGhpcy5fcHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWFkZXIgPSBuZXcgUERGRGF0YVRyYW5zcG9ydFN0cmVhbVJhbmdlUmVhZGVyKHRoaXMsIGJlZ2luLCBlbmQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wZGZEYXRhUmFuZ2VUcmFuc3BvcnQucmVxdWVzdERhdGFSYW5nZShiZWdpbiwgZW5kKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmFuZ2VSZWFkZXJzLnB1c2gocmVhZGVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlYWRlcjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FuY2VsQWxsUmVxdWVzdHMocmVhc29uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRfZnVsbFJlcXVlc3RSZWE1OwogICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkX2Z1bGxSZXF1ZXN0UmVhNSA9IHRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyKSA9PT0gbnVsbCB8fCBfdGhpcyRfZnVsbFJlcXVlc3RSZWE1ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRfZnVsbFJlcXVlc3RSZWE1LmNhbmNlbChyZWFzb24pOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHJlYWRlciBvZiB0aGlzLl9yYW5nZVJlYWRlcnMuc2xpY2UoMCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRlci5jYW5jZWwocmVhc29uKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wZGZEYXRhUmFuZ2VUcmFuc3BvcnQuYWJvcnQoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLlBERkRhdGFUcmFuc3BvcnRTdHJlYW0gPSBQREZEYXRhVHJhbnNwb3J0U3RyZWFtOwogICAgICAgICAgICAgICAgY2xhc3MgUERGRGF0YVRyYW5zcG9ydFN0cmVhbVJlYWRlciB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3Ioc3RyZWFtLCBxdWV1ZWRDaHVua3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHByb2dyZXNzaXZlRG9uZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb250ZW50RGlzcG9zaXRpb25GaWxlbmFtZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAzICYmIGFyZ3VtZW50c1szXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzNdIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RyZWFtID0gc3RyZWFtOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kb25lID0gcHJvZ3Jlc3NpdmVEb25lIHx8IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9maWxlbmFtZSA9ICgwLCBfZGlzcGxheV91dGlscy5pc1BkZkZpbGUpKGNvbnRlbnREaXNwb3NpdGlvbkZpbGVuYW1lKSA/IGNvbnRlbnREaXNwb3NpdGlvbkZpbGVuYW1lIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcXVldWVkQ2h1bmtzID0gcXVldWVkQ2h1bmtzIHx8IFtdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZWQgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGNodW5rIG9mIHRoaXMuX3F1ZXVlZENodW5rcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVkICs9IGNodW5rLmJ5dGVMZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVxdWVzdHMgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faGVhZGVyc1JlYWR5ID0gUHJvbWlzZS5yZXNvbHZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmVhbS5fZnVsbFJlcXVlc3RSZWFkZXIgPSB0aGlzOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uUHJvZ3Jlc3MgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfZW5xdWV1ZShjaHVuaykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fZG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9yZXF1ZXN0cy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXF1ZXN0Q2FwYWJpbGl0eSA9IHRoaXMuX3JlcXVlc3RzLnNoaWZ0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0Q2FwYWJpbGl0eS5yZXNvbHZlKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogY2h1bmssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcXVldWVkQ2h1bmtzLnB1c2goY2h1bmspOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRlZCArPSBjaHVuay5ieXRlTGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgaGVhZGVyc1JlYWR5KCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5faGVhZGVyc1JlYWR5OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgZmlsZW5hbWUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9maWxlbmFtZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGlzUmFuZ2VTdXBwb3J0ZWQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9zdHJlYW0uX2lzUmFuZ2VTdXBwb3J0ZWQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBpc1N0cmVhbWluZ1N1cHBvcnRlZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3N0cmVhbS5faXNTdHJlYW1pbmdTdXBwb3J0ZWQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBjb250ZW50TGVuZ3RoKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fc3RyZWFtLl9jb250ZW50TGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhc3luYyByZWFkKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fcXVldWVkQ2h1bmtzLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNodW5rID0gdGhpcy5fcXVldWVkQ2h1bmtzLnNoaWZ0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBjaHVuaywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lOiBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fZG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdW5kZWZpbmVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmU6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVxdWVzdENhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlcXVlc3RzLnB1c2gocmVxdWVzdENhcGFiaWxpdHkpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVxdWVzdENhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FuY2VsKHJlYXNvbikgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCByZXF1ZXN0Q2FwYWJpbGl0eSBvZiB0aGlzLl9yZXF1ZXN0cykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdENhcGFiaWxpdHkucmVzb2x2ZSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHVuZGVmaW5lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZXF1ZXN0cy5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBwcm9ncmVzc2l2ZURvbmUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9kb25lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgUERGRGF0YVRyYW5zcG9ydFN0cmVhbVJhbmdlUmVhZGVyIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihzdHJlYW0sIGJlZ2luLCBlbmQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RyZWFtID0gc3RyZWFtOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9iZWdpbiA9IGJlZ2luOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9lbmQgPSBlbmQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3F1ZXVlZENodW5rID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVxdWVzdHMgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9uZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uUHJvZ3Jlc3MgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfZW5xdWV1ZShjaHVuaykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fZG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9yZXF1ZXN0cy5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3F1ZXVlZENodW5rID0gY2h1bms7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXF1ZXN0c0NhcGFiaWxpdHkgPSB0aGlzLl9yZXF1ZXN0cy5zaGlmdCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdHNDYXBhYmlsaXR5LnJlc29sdmUoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBjaHVuaywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lOiBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHJlcXVlc3RDYXBhYmlsaXR5IG9mIHRoaXMuX3JlcXVlc3RzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdENhcGFiaWxpdHkucmVzb2x2ZSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB1bmRlZmluZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmU6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlcXVlc3RzLmxlbmd0aCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3N0cmVhbS5fcmVtb3ZlUmFuZ2VSZWFkZXIodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBpc1N0cmVhbWluZ1N1cHBvcnRlZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhc3luYyByZWFkKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fcXVldWVkQ2h1bmspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNodW5rID0gdGhpcy5fcXVldWVkQ2h1bms7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9xdWV1ZWRDaHVuayA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBjaHVuaywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lOiBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fZG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdW5kZWZpbmVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmU6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVxdWVzdENhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlcXVlc3RzLnB1c2gocmVxdWVzdENhcGFiaWxpdHkpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVxdWVzdENhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FuY2VsKHJlYXNvbikgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCByZXF1ZXN0Q2FwYWJpbGl0eSBvZiB0aGlzLl9yZXF1ZXN0cykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdENhcGFiaWxpdHkucmVzb2x2ZSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHVuZGVmaW5lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZXF1ZXN0cy5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdHJlYW0uX3JlbW92ZVJhbmdlUmVhZGVyKHRoaXMpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTU0ICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMpID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuWGZhVGV4dCA9IHZvaWQgMDsKICAgICAgICAgICAgICAgIGNsYXNzIFhmYVRleHQgewogICAgICAgICAgICAgICAgICAgIHN0YXRpYyB0ZXh0Q29udGVudCh4ZmEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXRlbXMgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3V0cHV0ID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZXM6IE9iamVjdC5jcmVhdGUobnVsbCkKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gd2Fsayhub2RlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX25vZGUkYXR0cmlidXRlczsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghbm9kZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzdHIgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmFtZSA9IG5vZGUubmFtZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuYW1lID09PSAiI3RleHQiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyID0gbm9kZS52YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIVhmYVRleHQuc2hvdWxkQnVpbGRUZXh0KG5hbWUpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChub2RlICE9PSBudWxsICYmIG5vZGUgIT09IHZvaWQgMCAmJiAoX25vZGUkYXR0cmlidXRlcyA9IG5vZGUuYXR0cmlidXRlcykgIT09IG51bGwgJiYgX25vZGUkYXR0cmlidXRlcyAhPT0gdm9pZCAwICYmIF9ub2RlJGF0dHJpYnV0ZXMudGV4dENvbnRlbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHIgPSBub2RlLmF0dHJpYnV0ZXMudGV4dENvbnRlbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG5vZGUudmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHIgPSBub2RlLnZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0ciAhPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1zLnB1c2goewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghbm9kZS5jaGlsZHJlbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgY2hpbGQgb2Ygbm9kZS5jaGlsZHJlbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsoY2hpbGQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsoeGZhKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIHNob3VsZEJ1aWxkVGV4dChuYW1lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAhKG5hbWUgPT09ICJ0ZXh0YXJlYSIgfHwgbmFtZSA9PT0gImlucHV0IiB8fCBuYW1lID09PSAib3B0aW9uIiB8fCBuYW1lID09PSAic2VsZWN0Iik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5YZmFUZXh0ID0gWGZhVGV4dDsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTU1ICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuTm9kZVN0YW5kYXJkRm9udERhdGFGYWN0b3J5ID0gZXhwb3J0cy5Ob2RlRmlsdGVyRmFjdG9yeSA9IGV4cG9ydHMuTm9kZUNhbnZhc0ZhY3RvcnkgPSBleHBvcnRzLk5vZGVDTWFwUmVhZGVyRmFjdG9yeSA9IHZvaWQgMDsKICAgICAgICAgICAgICAgIHZhciBfYmFzZV9mYWN0b3J5ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDMpOwogICAgICAgICAgICAgICAgOwogICAgICAgICAgICAgICAgY29uc3QgZmV0Y2hEYXRhID0gZnVuY3Rpb24gKHVybCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZzID0gcmVxdWlyZSgiZnMiKTsKICAgICAgICAgICAgICAgICAgICAgICAgZnMucmVhZEZpbGUodXJsLCAoZXJyb3IsIGRhdGEpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvciB8fCAhZGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoZXJyb3IpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG5ldyBVaW50OEFycmF5KGRhdGEpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgY2xhc3MgTm9kZUZpbHRlckZhY3RvcnkgZXh0ZW5kcyBfYmFzZV9mYWN0b3J5LkJhc2VGaWx0ZXJGYWN0b3J5IHt9CiAgICAgICAgICAgICAgICBleHBvcnRzLk5vZGVGaWx0ZXJGYWN0b3J5ID0gTm9kZUZpbHRlckZhY3Rvcnk7CiAgICAgICAgICAgICAgICBjbGFzcyBOb2RlQ2FudmFzRmFjdG9yeSBleHRlbmRzIF9iYXNlX2ZhY3RvcnkuQmFzZUNhbnZhc0ZhY3RvcnkgewogICAgICAgICAgICAgICAgICAgIF9jcmVhdGVDYW52YXMod2lkdGgsIGhlaWdodCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBDYW52YXMgPSByZXF1aXJlKCJjYW52YXMiKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIENhbnZhcy5jcmVhdGVDYW52YXMod2lkdGgsIGhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5Ob2RlQ2FudmFzRmFjdG9yeSA9IE5vZGVDYW52YXNGYWN0b3J5OwogICAgICAgICAgICAgICAgY2xhc3MgTm9kZUNNYXBSZWFkZXJGYWN0b3J5IGV4dGVuZHMgX2Jhc2VfZmFjdG9yeS5CYXNlQ01hcFJlYWRlckZhY3RvcnkgewogICAgICAgICAgICAgICAgICAgIF9mZXRjaERhdGEodXJsLCBjb21wcmVzc2lvblR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZldGNoRGF0YSh1cmwpLnRoZW4oZGF0YSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNNYXBEYXRhOiBkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXByZXNzaW9uVHlwZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5Ob2RlQ01hcFJlYWRlckZhY3RvcnkgPSBOb2RlQ01hcFJlYWRlckZhY3Rvcnk7CiAgICAgICAgICAgICAgICBjbGFzcyBOb2RlU3RhbmRhcmRGb250RGF0YUZhY3RvcnkgZXh0ZW5kcyBfYmFzZV9mYWN0b3J5LkJhc2VTdGFuZGFyZEZvbnREYXRhRmFjdG9yeSB7CiAgICAgICAgICAgICAgICAgICAgX2ZldGNoRGF0YSh1cmwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZldGNoRGF0YSh1cmwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuTm9kZVN0YW5kYXJkRm9udERhdGFGYWN0b3J5ID0gTm9kZVN0YW5kYXJkRm9udERhdGFGYWN0b3J5OwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxNTYgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCgogICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdHJ1ZQogICAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgICAgZXhwb3J0cy5QREZOb2RlU3RyZWFtID0gdm9pZCAwOwogICAgICAgICAgICAgICAgdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygxKTsKICAgICAgICAgICAgICAgIHZhciBfbmV0d29ya191dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTU3KTsKICAgICAgICAgICAgICAgIDsKICAgICAgICAgICAgICAgIGNvbnN0IGZzID0gcmVxdWlyZSgiZnMiKTsKICAgICAgICAgICAgICAgIGNvbnN0IGh0dHAgPSByZXF1aXJlKCJodHRwIik7CiAgICAgICAgICAgICAgICBjb25zdCBodHRwcyA9IHJlcXVpcmUoImh0dHBzIik7CiAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSByZXF1aXJlKCJ1cmwiKTsKICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVVcmlSZWdleCA9IC9eZmlsZTpcL1wvXC9bYS16QS1aXTpcLy87CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVVybChzb3VyY2VVcmwpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJzZWRVcmwgPSB1cmwucGFyc2Uoc291cmNlVXJsKTsKICAgICAgICAgICAgICAgICAgICBpZiAocGFyc2VkVXJsLnByb3RvY29sID09PSAiZmlsZToiIHx8IHBhcnNlZFVybC5ob3N0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXJzZWRVcmw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmICgvXlthLXpdOlsvXFxdL2kudGVzdChzb3VyY2VVcmwpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB1cmwucGFyc2UoYGZpbGU6Ly8vJHtzb3VyY2VVcmx9YCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmICghcGFyc2VkVXJsLmhvc3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcGFyc2VkVXJsLnByb3RvY29sID0gImZpbGU6IjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhcnNlZFVybDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIFBERk5vZGVTdHJlYW0gewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHNvdXJjZSkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNvdXJjZSA9IHNvdXJjZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51cmwgPSBwYXJzZVVybChzb3VyY2UudXJsKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0h0dHAgPSB0aGlzLnVybC5wcm90b2NvbCA9PT0gImh0dHA6IiB8fCB0aGlzLnVybC5wcm90b2NvbCA9PT0gImh0dHBzOiI7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNGc1VybCA9IHRoaXMudXJsLnByb3RvY29sID09PSAiZmlsZToiOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmh0dHBIZWFkZXJzID0gdGhpcy5pc0h0dHAgJiYgc291cmNlLmh0dHBIZWFkZXJzIHx8IHt9OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9mdWxsUmVxdWVzdFJlYWRlciA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JhbmdlUmVxdWVzdFJlYWRlcnMgPSBbXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IF9wcm9ncmVzc2l2ZURhdGFMZW5ndGgoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRfZnVsbFJlcXVlc3RSZWE7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoKF90aGlzJF9mdWxsUmVxdWVzdFJlYSA9IHRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyKSA9PT0gbnVsbCB8fCBfdGhpcyRfZnVsbFJlcXVlc3RSZWEgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJF9mdWxsUmVxdWVzdFJlYS5fbG9hZGVkKSA/PyAwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRGdWxsUmVhZGVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwuYXNzZXJ0KSghdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXIsICJQREZOb2RlU3RyZWFtLmdldEZ1bGxSZWFkZXIgY2FuIG9ubHkgYmUgY2FsbGVkIG9uY2UuIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyID0gdGhpcy5pc0ZzVXJsID8gbmV3IFBERk5vZGVTdHJlYW1Gc0Z1bGxSZWFkZXIodGhpcykgOiBuZXcgUERGTm9kZVN0cmVhbUZ1bGxSZWFkZXIodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9mdWxsUmVxdWVzdFJlYWRlcjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0UmFuZ2VSZWFkZXIoc3RhcnQsIGVuZCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZW5kIDw9IHRoaXMuX3Byb2dyZXNzaXZlRGF0YUxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2VSZWFkZXIgPSB0aGlzLmlzRnNVcmwgPyBuZXcgUERGTm9kZVN0cmVhbUZzUmFuZ2VSZWFkZXIodGhpcywgc3RhcnQsIGVuZCkgOiBuZXcgUERGTm9kZVN0cmVhbVJhbmdlUmVhZGVyKHRoaXMsIHN0YXJ0LCBlbmQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yYW5nZVJlcXVlc3RSZWFkZXJzLnB1c2gocmFuZ2VSZWFkZXIpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmFuZ2VSZWFkZXI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNhbmNlbEFsbFJlcXVlc3RzKHJlYXNvbikgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkX2Z1bGxSZXF1ZXN0UmVhMjsKICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJF9mdWxsUmVxdWVzdFJlYTIgPSB0aGlzLl9mdWxsUmVxdWVzdFJlYWRlcikgPT09IG51bGwgfHwgX3RoaXMkX2Z1bGxSZXF1ZXN0UmVhMiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkX2Z1bGxSZXF1ZXN0UmVhMi5jYW5jZWwocmVhc29uKTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCByZWFkZXIgb2YgdGhpcy5fcmFuZ2VSZXF1ZXN0UmVhZGVycy5zbGljZSgwKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGVyLmNhbmNlbChyZWFzb24pOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5QREZOb2RlU3RyZWFtID0gUERGTm9kZVN0cmVhbTsKICAgICAgICAgICAgICAgIGNsYXNzIEJhc2VGdWxsUmVhZGVyIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihzdHJlYW0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdXJsID0gc3RyZWFtLnVybDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9uZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdG9yZWRFcnJvciA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub25Qcm9ncmVzcyA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IHN0cmVhbS5zb3VyY2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRlbnRMZW5ndGggPSBzb3VyY2UubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZWQgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9maWxlbmFtZSA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Rpc2FibGVSYW5nZSA9IHNvdXJjZS5kaXNhYmxlUmFuZ2UgfHwgZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JhbmdlQ2h1bmtTaXplID0gc291cmNlLnJhbmdlQ2h1bmtTaXplOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX3JhbmdlQ2h1bmtTaXplICYmICF0aGlzLl9kaXNhYmxlUmFuZ2UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Rpc2FibGVSYW5nZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faXNTdHJlYW1pbmdTdXBwb3J0ZWQgPSAhc291cmNlLmRpc2FibGVTdHJlYW07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2lzUmFuZ2VTdXBwb3J0ZWQgPSAhc291cmNlLmRpc2FibGVSYW5nZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZGFibGVTdHJlYW0gPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWFkQ2FwYWJpbGl0eSA9ICgwLCBfdXRpbC5jcmVhdGVQcm9taXNlQ2FwYWJpbGl0eSkoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faGVhZGVyc0NhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBoZWFkZXJzUmVhZHkoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9oZWFkZXJzQ2FwYWJpbGl0eS5wcm9taXNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgZmlsZW5hbWUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9maWxlbmFtZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGNvbnRlbnRMZW5ndGgoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9jb250ZW50TGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgaXNSYW5nZVN1cHBvcnRlZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzUmFuZ2VTdXBwb3J0ZWQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBpc1N0cmVhbWluZ1N1cHBvcnRlZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzU3RyZWFtaW5nU3VwcG9ydGVkOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhc3luYyByZWFkKCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkb25Qcm9ncmVzczsKICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5fcmVhZENhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2RvbmUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHVuZGVmaW5lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9zdG9yZWRFcnJvcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgdGhpcy5fc3RvcmVkRXJyb3I7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2h1bmsgPSB0aGlzLl9yZWFkYWJsZVN0cmVhbS5yZWFkKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaHVuayA9PT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZENhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZWFkKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVkICs9IGNodW5rLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJG9uUHJvZ3Jlc3MgPSB0aGlzLm9uUHJvZ3Jlc3MpID09PSBudWxsIHx8IF90aGlzJG9uUHJvZ3Jlc3MgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJG9uUHJvZ3Jlc3MuY2FsbCh0aGlzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2FkZWQ6IHRoaXMuX2xvYWRlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsOiB0aGlzLl9jb250ZW50TGVuZ3RoCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBidWZmZXIgPSBuZXcgVWludDhBcnJheShjaHVuaykuYnVmZmVyOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGJ1ZmZlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmU6IGZhbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNhbmNlbChyZWFzb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9yZWFkYWJsZVN0cmVhbSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZXJyb3IocmVhc29uKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWFkYWJsZVN0cmVhbS5kZXN0cm95KHJlYXNvbik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9lcnJvcihyZWFzb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RvcmVkRXJyb3IgPSByZWFzb247CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRDYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX3NldFJlYWRhYmxlU3RyZWFtKHJlYWRhYmxlU3RyZWFtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRhYmxlU3RyZWFtID0gcmVhZGFibGVTdHJlYW07CiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlU3RyZWFtLm9uKCJyZWFkYWJsZSIsICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRDYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlU3RyZWFtLm9uKCJlbmQiLCAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkYWJsZVN0cmVhbS5kZXN0cm95KCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRDYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlU3RyZWFtLm9uKCJlcnJvciIsIHJlYXNvbiA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9lcnJvcihyZWFzb24pOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9pc1N0cmVhbWluZ1N1cHBvcnRlZCAmJiB0aGlzLl9pc1JhbmdlU3VwcG9ydGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9lcnJvcihuZXcgX3V0aWwuQWJvcnRFeGNlcHRpb24oInN0cmVhbWluZyBpcyBkaXNhYmxlZCIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fc3RvcmVkRXJyb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRhYmxlU3RyZWFtLmRlc3Ryb3kodGhpcy5fc3RvcmVkRXJyb3IpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgQmFzZVJhbmdlUmVhZGVyIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihzdHJlYW0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdXJsID0gc3RyZWFtLnVybDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9uZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdG9yZWRFcnJvciA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub25Qcm9ncmVzcyA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRlZCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRhYmxlU3RyZWFtID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZENhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IHN0cmVhbS5zb3VyY2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2lzU3RyZWFtaW5nU3VwcG9ydGVkID0gIXNvdXJjZS5kaXNhYmxlU3RyZWFtOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgaXNTdHJlYW1pbmdTdXBwb3J0ZWQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9pc1N0cmVhbWluZ1N1cHBvcnRlZDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYXN5bmMgcmVhZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJG9uUHJvZ3Jlc3MyOwogICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9yZWFkQ2FwYWJpbGl0eS5wcm9taXNlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fZG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdW5kZWZpbmVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmU6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX3N0b3JlZEVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyB0aGlzLl9zdG9yZWRFcnJvcjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaHVuayA9IHRoaXMuX3JlYWRhYmxlU3RyZWFtLnJlYWQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNodW5rID09PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWFkQ2FwYWJpbGl0eSA9ICgwLCBfdXRpbC5jcmVhdGVQcm9taXNlQ2FwYWJpbGl0eSkoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJlYWQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZWQgKz0gY2h1bmsubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkb25Qcm9ncmVzczIgPSB0aGlzLm9uUHJvZ3Jlc3MpID09PSBudWxsIHx8IF90aGlzJG9uUHJvZ3Jlc3MyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRvblByb2dyZXNzMi5jYWxsKHRoaXMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvYWRlZDogdGhpcy5fbG9hZGVkCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBidWZmZXIgPSBuZXcgVWludDhBcnJheShjaHVuaykuYnVmZmVyOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGJ1ZmZlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmU6IGZhbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNhbmNlbChyZWFzb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9yZWFkYWJsZVN0cmVhbSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZXJyb3IocmVhc29uKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWFkYWJsZVN0cmVhbS5kZXN0cm95KHJlYXNvbik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9lcnJvcihyZWFzb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RvcmVkRXJyb3IgPSByZWFzb247CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRDYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX3NldFJlYWRhYmxlU3RyZWFtKHJlYWRhYmxlU3RyZWFtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRhYmxlU3RyZWFtID0gcmVhZGFibGVTdHJlYW07CiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlU3RyZWFtLm9uKCJyZWFkYWJsZSIsICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRDYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlU3RyZWFtLm9uKCJlbmQiLCAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkYWJsZVN0cmVhbS5kZXN0cm95KCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRDYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRhYmxlU3RyZWFtLm9uKCJlcnJvciIsIHJlYXNvbiA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9lcnJvcihyZWFzb24pOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX3N0b3JlZEVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWFkYWJsZVN0cmVhbS5kZXN0cm95KHRoaXMuX3N0b3JlZEVycm9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZVJlcXVlc3RPcHRpb25zKHBhcnNlZFVybCwgaGVhZGVycykgewogICAgICAgICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICAgICAgICAgIHByb3RvY29sOiBwYXJzZWRVcmwucHJvdG9jb2wsCiAgICAgICAgICAgICAgICAgICAgICAgIGF1dGg6IHBhcnNlZFVybC5hdXRoLAogICAgICAgICAgICAgICAgICAgICAgICBob3N0OiBwYXJzZWRVcmwuaG9zdG5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgIHBvcnQ6IHBhcnNlZFVybC5wb3J0LAogICAgICAgICAgICAgICAgICAgICAgICBwYXRoOiBwYXJzZWRVcmwucGF0aCwKICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kOiAiR0VUIiwKICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVycwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBQREZOb2RlU3RyZWFtRnVsbFJlYWRlciBleHRlbmRzIEJhc2VGdWxsUmVhZGVyIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihzdHJlYW0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIoc3RyZWFtKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaGFuZGxlUmVzcG9uc2UgPSByZXNwb25zZSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzQ29kZSA9PT0gNDA0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgX3V0aWwuTWlzc2luZ1BERkV4Y2VwdGlvbihgTWlzc2luZyBQREYgIiR7dGhpcy5fdXJsfSIuYCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RvcmVkRXJyb3IgPSBlcnJvcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9oZWFkZXJzQ2FwYWJpbGl0eS5yZWplY3QoZXJyb3IpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2hlYWRlcnNDYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFJlYWRhYmxlU3RyZWFtKHJlc3BvbnNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGdldFJlc3BvbnNlSGVhZGVyID0gbmFtZSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3JlYWRhYmxlU3RyZWFtLmhlYWRlcnNbbmFtZS50b0xvd2VyQ2FzZSgpXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3dSYW5nZVJlcXVlc3RzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1Z2dlc3RlZExlbmd0aAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA9ICgwLCBfbmV0d29ya191dGlscy52YWxpZGF0ZVJhbmdlUmVxdWVzdENhcGFiaWxpdGllcykoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFJlc3BvbnNlSGVhZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzSHR0cDogc3RyZWFtLmlzSHR0cCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5nZUNodW5rU2l6ZTogdGhpcy5fcmFuZ2VDaHVua1NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZVJhbmdlOiB0aGlzLl9kaXNhYmxlUmFuZ2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faXNSYW5nZVN1cHBvcnRlZCA9IGFsbG93UmFuZ2VSZXF1ZXN0czsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRlbnRMZW5ndGggPSBzdWdnZXN0ZWRMZW5ndGggfHwgdGhpcy5fY29udGVudExlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2ZpbGVuYW1lID0gKDAsIF9uZXR3b3JrX3V0aWxzLmV4dHJhY3RGaWxlbmFtZUZyb21IZWFkZXIpKGdldFJlc3BvbnNlSGVhZGVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVxdWVzdCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl91cmwucHJvdG9jb2wgPT09ICJodHRwOiIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlcXVlc3QgPSBodHRwLnJlcXVlc3QoY3JlYXRlUmVxdWVzdE9wdGlvbnModGhpcy5fdXJsLCBzdHJlYW0uaHR0cEhlYWRlcnMpLCBoYW5kbGVSZXNwb25zZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZXF1ZXN0ID0gaHR0cHMucmVxdWVzdChjcmVhdGVSZXF1ZXN0T3B0aW9ucyh0aGlzLl91cmwsIHN0cmVhbS5odHRwSGVhZGVycyksIGhhbmRsZVJlc3BvbnNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZXF1ZXN0Lm9uKCJlcnJvciIsIHJlYXNvbiA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdG9yZWRFcnJvciA9IHJlYXNvbjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2hlYWRlcnNDYXBhYmlsaXR5LnJlamVjdChyZWFzb24pOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVxdWVzdC5lbmQoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBQREZOb2RlU3RyZWFtUmFuZ2VSZWFkZXIgZXh0ZW5kcyBCYXNlUmFuZ2VSZWFkZXIgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHN0cmVhbSwgc3RhcnQsIGVuZCkgewogICAgICAgICAgICAgICAgICAgICAgICBzdXBlcihzdHJlYW0pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9odHRwSGVhZGVycyA9IHt9OwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHByb3BlcnR5IGluIHN0cmVhbS5odHRwSGVhZGVycykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBzdHJlYW0uaHR0cEhlYWRlcnNbcHJvcGVydHldOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2h0dHBIZWFkZXJzW3Byb3BlcnR5XSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2h0dHBIZWFkZXJzLlJhbmdlID0gYGJ5dGVzPSR7c3RhcnR9LSR7ZW5kIC0gMX1gOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoYW5kbGVSZXNwb25zZSA9IHJlc3BvbnNlID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXNDb2RlID09PSA0MDQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBfdXRpbC5NaXNzaW5nUERGRXhjZXB0aW9uKGBNaXNzaW5nIFBERiAiJHt0aGlzLl91cmx9Ii5gKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdG9yZWRFcnJvciA9IGVycm9yOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFJlYWRhYmxlU3RyZWFtKHJlc3BvbnNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVxdWVzdCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl91cmwucHJvdG9jb2wgPT09ICJodHRwOiIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlcXVlc3QgPSBodHRwLnJlcXVlc3QoY3JlYXRlUmVxdWVzdE9wdGlvbnModGhpcy5fdXJsLCB0aGlzLl9odHRwSGVhZGVycyksIGhhbmRsZVJlc3BvbnNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlcXVlc3QgPSBodHRwcy5yZXF1ZXN0KGNyZWF0ZVJlcXVlc3RPcHRpb25zKHRoaXMuX3VybCwgdGhpcy5faHR0cEhlYWRlcnMpLCBoYW5kbGVSZXNwb25zZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVxdWVzdC5vbigiZXJyb3IiLCByZWFzb24gPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RvcmVkRXJyb3IgPSByZWFzb247CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZXF1ZXN0LmVuZCgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIFBERk5vZGVTdHJlYW1Gc0Z1bGxSZWFkZXIgZXh0ZW5kcyBCYXNlRnVsbFJlYWRlciB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3Ioc3RyZWFtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKHN0cmVhbSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBwYXRoID0gZGVjb2RlVVJJQ29tcG9uZW50KHRoaXMuX3VybC5wYXRoKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGVVcmlSZWdleC50ZXN0KHRoaXMuX3VybC5ocmVmKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aCA9IHBhdGgucmVwbGFjZSgvXlwvLywgIiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGZzLmxzdGF0KHBhdGgsIChlcnJvciwgc3RhdCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09ICJFTk9FTlQiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yID0gbmV3IF91dGlsLk1pc3NpbmdQREZFeGNlcHRpb24oYE1pc3NpbmcgUERGICIke3BhdGh9Ii5gKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RvcmVkRXJyb3IgPSBlcnJvcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9oZWFkZXJzQ2FwYWJpbGl0eS5yZWplY3QoZXJyb3IpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRlbnRMZW5ndGggPSBzdGF0LnNpemU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRSZWFkYWJsZVN0cmVhbShmcy5jcmVhdGVSZWFkU3RyZWFtKHBhdGgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2hlYWRlcnNDYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgUERGTm9kZVN0cmVhbUZzUmFuZ2VSZWFkZXIgZXh0ZW5kcyBCYXNlUmFuZ2VSZWFkZXIgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHN0cmVhbSwgc3RhcnQsIGVuZCkgewogICAgICAgICAgICAgICAgICAgICAgICBzdXBlcihzdHJlYW0pOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcGF0aCA9IGRlY29kZVVSSUNvbXBvbmVudCh0aGlzLl91cmwucGF0aCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmaWxlVXJpUmVnZXgudGVzdCh0aGlzLl91cmwuaHJlZikpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGggPSBwYXRoLnJlcGxhY2UoL15cLy8sICIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRSZWFkYWJsZVN0cmVhbShmcy5jcmVhdGVSZWFkU3RyZWFtKHBhdGgsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kOiBlbmQgLSAxCiAgICAgICAgICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDE1NyAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLmNyZWF0ZVJlc3BvbnNlU3RhdHVzRXJyb3IgPSBjcmVhdGVSZXNwb25zZVN0YXR1c0Vycm9yOwogICAgICAgICAgICAgICAgZXhwb3J0cy5leHRyYWN0RmlsZW5hbWVGcm9tSGVhZGVyID0gZXh0cmFjdEZpbGVuYW1lRnJvbUhlYWRlcjsKICAgICAgICAgICAgICAgIGV4cG9ydHMudmFsaWRhdGVSYW5nZVJlcXVlc3RDYXBhYmlsaXRpZXMgPSB2YWxpZGF0ZVJhbmdlUmVxdWVzdENhcGFiaWxpdGllczsKICAgICAgICAgICAgICAgIGV4cG9ydHMudmFsaWRhdGVSZXNwb25zZVN0YXR1cyA9IHZhbGlkYXRlUmVzcG9uc2VTdGF0dXM7CiAgICAgICAgICAgICAgICB2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEpOwogICAgICAgICAgICAgICAgdmFyIF9jb250ZW50X2Rpc3Bvc2l0aW9uID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTgpOwogICAgICAgICAgICAgICAgdmFyIF9kaXNwbGF5X3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDIpOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gdmFsaWRhdGVSYW5nZVJlcXVlc3RDYXBhYmlsaXRpZXMoX3JlZikgewogICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgIGdldFJlc3BvbnNlSGVhZGVyLAogICAgICAgICAgICAgICAgICAgICAgICBpc0h0dHAsCiAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlQ2h1bmtTaXplLAogICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlUmFuZ2UKICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjsKICAgICAgICAgICAgICAgICAgICBjb25zdCByZXR1cm5WYWx1ZXMgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93UmFuZ2VSZXF1ZXN0czogZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgIHN1Z2dlc3RlZExlbmd0aDogdW5kZWZpbmVkCiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBsZW5ndGggPSBwYXJzZUludChnZXRSZXNwb25zZUhlYWRlcigiQ29udGVudC1MZW5ndGgiKSwgMTApOwogICAgICAgICAgICAgICAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihsZW5ndGgpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXR1cm5WYWx1ZXM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVyblZhbHVlcy5zdWdnZXN0ZWRMZW5ndGggPSBsZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgaWYgKGxlbmd0aCA8PSAyICogcmFuZ2VDaHVua1NpemUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJldHVyblZhbHVlczsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKGRpc2FibGVSYW5nZSB8fCAhaXNIdHRwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXR1cm5WYWx1ZXM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChnZXRSZXNwb25zZUhlYWRlcigiQWNjZXB0LVJhbmdlcyIpICE9PSAiYnl0ZXMiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXR1cm5WYWx1ZXM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRlbnRFbmNvZGluZyA9IGdldFJlc3BvbnNlSGVhZGVyKCJDb250ZW50LUVuY29kaW5nIikgfHwgImlkZW50aXR5IjsKICAgICAgICAgICAgICAgICAgICBpZiAoY29udGVudEVuY29kaW5nICE9PSAiaWRlbnRpdHkiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXR1cm5WYWx1ZXM7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVyblZhbHVlcy5hbGxvd1JhbmdlUmVxdWVzdHMgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIHJldHVybiByZXR1cm5WYWx1ZXM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBleHRyYWN0RmlsZW5hbWVGcm9tSGVhZGVyKGdldFJlc3BvbnNlSGVhZGVyKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29udGVudERpc3Bvc2l0aW9uID0gZ2V0UmVzcG9uc2VIZWFkZXIoIkNvbnRlbnQtRGlzcG9zaXRpb24iKTsKICAgICAgICAgICAgICAgICAgICBpZiAoY29udGVudERpc3Bvc2l0aW9uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaWxlbmFtZSA9ICgwLCBfY29udGVudF9kaXNwb3NpdGlvbi5nZXRGaWxlbmFtZUZyb21Db250ZW50RGlzcG9zaXRpb25IZWFkZXIpKGNvbnRlbnREaXNwb3NpdGlvbik7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmaWxlbmFtZS5pbmNsdWRlcygiJSIpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lID0gZGVjb2RlVVJJQ29tcG9uZW50KGZpbGVuYW1lKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7fQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoMCwgX2Rpc3BsYXlfdXRpbHMuaXNQZGZGaWxlKShmaWxlbmFtZSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmaWxlbmFtZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZVJlc3BvbnNlU3RhdHVzRXJyb3Ioc3RhdHVzLCB1cmwpIHsKICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHVzID09PSA0MDQgfHwgc3RhdHVzID09PSAwICYmIHVybC5zdGFydHNXaXRoKCJmaWxlOiIpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgX3V0aWwuTWlzc2luZ1BERkV4Y2VwdGlvbignTWlzc2luZyBQREYgIicgKyB1cmwgKyAnIi4nKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBfdXRpbC5VbmV4cGVjdGVkUmVzcG9uc2VFeGNlcHRpb24oYFVuZXhwZWN0ZWQgc2VydmVyIHJlc3BvbnNlICgke3N0YXR1c30pIHdoaWxlIHJldHJpZXZpbmcgUERGICIke3VybH0iLmAsIHN0YXR1cyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiB2YWxpZGF0ZVJlc3BvbnNlU3RhdHVzKHN0YXR1cykgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBzdGF0dXMgPT09IDIwMCB8fCBzdGF0dXMgPT09IDIwNjsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTU4ICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuZ2V0RmlsZW5hbWVGcm9tQ29udGVudERpc3Bvc2l0aW9uSGVhZGVyID0gZ2V0RmlsZW5hbWVGcm9tQ29udGVudERpc3Bvc2l0aW9uSGVhZGVyOwogICAgICAgICAgICAgICAgdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygxKTsKICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGdldEZpbGVuYW1lRnJvbUNvbnRlbnREaXNwb3NpdGlvbkhlYWRlcihjb250ZW50RGlzcG9zaXRpb24pIHsKICAgICAgICAgICAgICAgICAgICBsZXQgbmVlZHNFbmNvZGluZ0ZpeHVwID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBsZXQgdG1wID0gdG9QYXJhbVJlZ0V4cCgiZmlsZW5hbWVcXCoiLCAiaSIpLmV4ZWMoY29udGVudERpc3Bvc2l0aW9uKTsKICAgICAgICAgICAgICAgICAgICBpZiAodG1wKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRtcCA9IHRtcFsxXTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGZpbGVuYW1lID0gcmZjMjYxNnVucXVvdGUodG1wKTsKICAgICAgICAgICAgICAgICAgICAgICAgZmlsZW5hbWUgPSB1bmVzY2FwZShmaWxlbmFtZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lID0gcmZjNTk4N2RlY29kZShmaWxlbmFtZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lID0gcmZjMjA0N2RlY29kZShmaWxlbmFtZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmaXh1cEVuY29kaW5nKGZpbGVuYW1lKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdG1wID0gcmZjMjIzMWdldHBhcmFtKGNvbnRlbnREaXNwb3NpdGlvbik7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRtcCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWxlbmFtZSA9IHJmYzIwNDdkZWNvZGUodG1wKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZpeHVwRW5jb2RpbmcoZmlsZW5hbWUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB0bXAgPSB0b1BhcmFtUmVnRXhwKCJmaWxlbmFtZSIsICJpIikuZXhlYyhjb250ZW50RGlzcG9zaXRpb24pOwogICAgICAgICAgICAgICAgICAgIGlmICh0bXApIHsKICAgICAgICAgICAgICAgICAgICAgICAgdG1wID0gdG1wWzFdOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmlsZW5hbWUgPSByZmMyNjE2dW5xdW90ZSh0bXApOwogICAgICAgICAgICAgICAgICAgICAgICBmaWxlbmFtZSA9IHJmYzIwNDdkZWNvZGUoZmlsZW5hbWUpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZml4dXBFbmNvZGluZyhmaWxlbmFtZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHRvUGFyYW1SZWdFeHAoYXR0cmlidXRlUGF0dGVybiwgZmxhZ3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBSZWdFeHAoIig/Ol58OylcXHMqIiArIGF0dHJpYnV0ZVBhdHRlcm4gKyAiXFxzKj1cXHMqIiArICIoIiArICdbXiI7XFxzXVteO1xcc10qJyArICJ8IiArICciKD86W14iXFxcXF18XFxcXCI/KSsiPycgKyAiKSIsIGZsYWdzKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gdGV4dGRlY29kZShlbmNvZGluZywgdmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVuY29kaW5nKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIS9eW1x4MDAtXHhGRl0rJC8udGVzdCh2YWx1ZSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoZW5jb2RpbmcsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmF0YWw6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBidWZmZXIgPSAoMCwgX3V0aWwuc3RyaW5nVG9CeXRlcykodmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gZGVjb2Rlci5kZWNvZGUoYnVmZmVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZWVkc0VuY29kaW5nRml4dXAgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBmaXh1cEVuY29kaW5nKHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuZWVkc0VuY29kaW5nRml4dXAgJiYgL1tceDgwLVx4ZmZdLy50ZXN0KHZhbHVlKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB0ZXh0ZGVjb2RlKCJ1dGYtOCIsIHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuZWVkc0VuY29kaW5nRml4dXApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRleHRkZWNvZGUoImlzby04ODU5LTEiLCB2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiByZmMyMjMxZ2V0cGFyYW0oY29udGVudERpc3Bvc2l0aW9uU3RyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1hdGNoOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpdGVyID0gdG9QYXJhbVJlZ0V4cCgiZmlsZW5hbWVcXCooKD8hMFxcZClcXGQrKShcXCo/KSIsICJpZyIpOwogICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoKG1hdGNoID0gaXRlci5leGVjKGNvbnRlbnREaXNwb3NpdGlvblN0cikpICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgWywgbiwgcXVvdCwgcGFydF0gPSBtYXRjaDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSBwYXJzZUludChuLCAxMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobiBpbiBtYXRjaGVzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG4gPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlc1tuXSA9IFtxdW90LCBwYXJ0XTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJ0cyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBuID0gMDsgbiA8IG1hdGNoZXMubGVuZ3RoOyArK24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghKG4gaW4gbWF0Y2hlcykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBbcXVvdCwgcGFydF0gPSBtYXRjaGVzW25dOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFydCA9IHJmYzI2MTZ1bnF1b3RlKHBhcnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHF1b3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdW5lc2NhcGUocGFydCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG4gPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFydCA9IHJmYzU5ODdkZWNvZGUocGFydCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFydHMucHVzaChwYXJ0KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGFydHMuam9pbigiIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHJmYzI2MTZ1bnF1b3RlKHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZS5zdGFydHNXaXRoKCciJykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhcnRzID0gdmFsdWUuc2xpY2UoMSkuc3BsaXQoJ1xcIicpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7ICsraSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHF1b3RpbmRleCA9IHBhcnRzW2ldLmluZGV4T2YoJyInKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocXVvdGluZGV4ICE9PSAtMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJ0c1tpXSA9IHBhcnRzW2ldLnNsaWNlKDAsIHF1b3RpbmRleCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcnRzLmxlbmd0aCA9IGkgKyAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJ0c1tpXSA9IHBhcnRzW2ldLnJlcGxhY2VBbGwoL1xcKC4pL2csICIkMSIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBwYXJ0cy5qb2luKCciJyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiByZmM1OTg3ZGVjb2RlKGV4dHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVuY29kaW5nZW5kID0gZXh0dmFsdWUuaW5kZXhPZigiJyIpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZW5jb2RpbmdlbmQgPT09IC0xKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXh0dmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5jb2RpbmcgPSBleHR2YWx1ZS5zbGljZSgwLCBlbmNvZGluZ2VuZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxhbmd2YWx1ZSA9IGV4dHZhbHVlLnNsaWNlKGVuY29kaW5nZW5kICsgMSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gbGFuZ3ZhbHVlLnJlcGxhY2UoL15bXiddKicvLCAiIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0ZXh0ZGVjb2RlKGVuY29kaW5nLCB2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHJmYzIwNDdkZWNvZGUodmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF2YWx1ZS5zdGFydHNXaXRoKCI9PyIpIHx8IC9bXHgwMC1ceDE5XHg4MC1ceGZmXS8udGVzdCh2YWx1ZSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUucmVwbGFjZUFsbCgvPVw/KFtcdy1dKilcPyhbUXFCYl0pXD8oKD86W14/XXxcPyg/IT0pKSopXD89L2csIGZ1bmN0aW9uIChtYXRjaGVzLCBjaGFyc2V0LCBlbmNvZGluZywgdGV4dCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVuY29kaW5nID09PSAicSIgfHwgZW5jb2RpbmcgPT09ICJRIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSB0ZXh0LnJlcGxhY2VBbGwoIl8iLCAiICIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQgPSB0ZXh0LnJlcGxhY2VBbGwoLz0oWzAtOWEtZkEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgaGV4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKHBhcnNlSW50KGhleCwgMTYpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGV4dGRlY29kZShjaGFyc2V0LCB0ZXh0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dCA9IGF0b2IodGV4dCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRleHRkZWNvZGUoY2hhcnNldCwgdGV4dCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gIiI7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDE1OSAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLlBERk5ldHdvcmtTdHJlYW0gPSB2b2lkIDA7CiAgICAgICAgICAgICAgICB2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEpOwogICAgICAgICAgICAgICAgdmFyIF9uZXR3b3JrX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTcpOwogICAgICAgICAgICAgICAgOwogICAgICAgICAgICAgICAgY29uc3QgT0tfUkVTUE9OU0UgPSAyMDA7CiAgICAgICAgICAgICAgICBjb25zdCBQQVJUSUFMX0NPTlRFTlRfUkVTUE9OU0UgPSAyMDY7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBnZXRBcnJheUJ1ZmZlcih4aHIpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0geGhyLnJlc3BvbnNlOwogICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YSAhPT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRhdGE7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiAoMCwgX3V0aWwuc3RyaW5nVG9CeXRlcykoZGF0YSkuYnVmZmVyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgTmV0d29ya01hbmFnZXIgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHVybCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgYXJncyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudXJsID0gdXJsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzSHR0cCA9IC9eaHR0cHM/Oi9pLnRlc3QodXJsKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5odHRwSGVhZGVycyA9IHRoaXMuaXNIdHRwICYmIGFyZ3MuaHR0cEhlYWRlcnMgfHwgT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53aXRoQ3JlZGVudGlhbHMgPSBhcmdzLndpdGhDcmVkZW50aWFscyB8fCBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5nZXRYaHIgPSBhcmdzLmdldFhociB8fCBmdW5jdGlvbiBOZXR3b3JrTWFuYWdlcl9nZXRYaHIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VyclhocklkID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wZW5kaW5nUmVxdWVzdHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXF1ZXN0UmFuZ2UoYmVnaW4sIGVuZCwgbGlzdGVuZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFyZ3MgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZAogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHByb3AgaW4gbGlzdGVuZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmdzW3Byb3BdID0gbGlzdGVuZXJzW3Byb3BdOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJlcXVlc3QoYXJncyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlcXVlc3RGdWxsKGxpc3RlbmVycykgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZXF1ZXN0KGxpc3RlbmVycyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlcXVlc3QoYXJncykgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB4aHIgPSB0aGlzLmdldFhocigpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB4aHJJZCA9IHRoaXMuY3VyclhocklkKys7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBlbmRpbmdSZXF1ZXN0ID0gdGhpcy5wZW5kaW5nUmVxdWVzdHNbeGhySWRdID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgeGhyCiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIHhoci5vcGVuKCJHRVQiLCB0aGlzLnVybCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHhoci53aXRoQ3JlZGVudGlhbHMgPSB0aGlzLndpdGhDcmVkZW50aWFsczsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBwcm9wZXJ0eSBpbiB0aGlzLmh0dHBIZWFkZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMuaHR0cEhlYWRlcnNbcHJvcGVydHldOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKHByb3BlcnR5LCB2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNIdHRwICYmICJiZWdpbiIgaW4gYXJncyAmJiAiZW5kIiBpbiBhcmdzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcigiUmFuZ2UiLCBgYnl0ZXM9JHthcmdzLmJlZ2lufS0ke2FyZ3MuZW5kIC0gMX1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlbmRpbmdSZXF1ZXN0LmV4cGVjdGVkU3RhdHVzID0gUEFSVElBTF9DT05URU5UX1JFU1BPTlNFOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVuZGluZ1JlcXVlc3QuZXhwZWN0ZWRTdGF0dXMgPSBPS19SRVNQT05TRTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB4aHIucmVzcG9uc2VUeXBlID0gImFycmF5YnVmZmVyIjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3Mub25FcnJvcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgeGhyLm9uZXJyb3IgPSBmdW5jdGlvbiAoZXZ0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJncy5vbkVycm9yKHhoci5zdGF0dXMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB4aHIub25yZWFkeXN0YXRlY2hhbmdlID0gdGhpcy5vblN0YXRlQ2hhbmdlLmJpbmQodGhpcywgeGhySWQpOwogICAgICAgICAgICAgICAgICAgICAgICB4aHIub25wcm9ncmVzcyA9IHRoaXMub25Qcm9ncmVzcy5iaW5kKHRoaXMsIHhocklkKTsKICAgICAgICAgICAgICAgICAgICAgICAgcGVuZGluZ1JlcXVlc3Qub25IZWFkZXJzUmVjZWl2ZWQgPSBhcmdzLm9uSGVhZGVyc1JlY2VpdmVkOwogICAgICAgICAgICAgICAgICAgICAgICBwZW5kaW5nUmVxdWVzdC5vbkRvbmUgPSBhcmdzLm9uRG9uZTsKICAgICAgICAgICAgICAgICAgICAgICAgcGVuZGluZ1JlcXVlc3Qub25FcnJvciA9IGFyZ3Mub25FcnJvcjsKICAgICAgICAgICAgICAgICAgICAgICAgcGVuZGluZ1JlcXVlc3Qub25Qcm9ncmVzcyA9IGFyZ3Mub25Qcm9ncmVzczsKICAgICAgICAgICAgICAgICAgICAgICAgeGhyLnNlbmQobnVsbCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB4aHJJZDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgb25Qcm9ncmVzcyh4aHJJZCwgZXZ0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfcGVuZGluZ1JlcXVlc3Qkb25Qcm87CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBlbmRpbmdSZXF1ZXN0ID0gdGhpcy5wZW5kaW5nUmVxdWVzdHNbeGhySWRdOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXBlbmRpbmdSZXF1ZXN0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgKF9wZW5kaW5nUmVxdWVzdCRvblBybyA9IHBlbmRpbmdSZXF1ZXN0Lm9uUHJvZ3Jlc3MpID09PSBudWxsIHx8IF9wZW5kaW5nUmVxdWVzdCRvblBybyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3BlbmRpbmdSZXF1ZXN0JG9uUHJvLmNhbGwocGVuZGluZ1JlcXVlc3QsIGV2dCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIG9uU3RhdGVDaGFuZ2UoeGhySWQsIGV2dCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwZW5kaW5nUmVxdWVzdCA9IHRoaXMucGVuZGluZ1JlcXVlc3RzW3hocklkXTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFwZW5kaW5nUmVxdWVzdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHhociA9IHBlbmRpbmdSZXF1ZXN0LnhocjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlID49IDIgJiYgcGVuZGluZ1JlcXVlc3Qub25IZWFkZXJzUmVjZWl2ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlbmRpbmdSZXF1ZXN0Lm9uSGVhZGVyc1JlY2VpdmVkKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgcGVuZGluZ1JlcXVlc3Qub25IZWFkZXJzUmVjZWl2ZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlICE9PSA0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEoeGhySWQgaW4gdGhpcy5wZW5kaW5nUmVxdWVzdHMpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucGVuZGluZ1JlcXVlc3RzW3hocklkXTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHhoci5zdGF0dXMgPT09IDAgJiYgdGhpcy5pc0h0dHApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfcGVuZGluZ1JlcXVlc3Qkb25FcnI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoX3BlbmRpbmdSZXF1ZXN0JG9uRXJyID0gcGVuZGluZ1JlcXVlc3Qub25FcnJvcikgPT09IG51bGwgfHwgX3BlbmRpbmdSZXF1ZXN0JG9uRXJyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfcGVuZGluZ1JlcXVlc3Qkb25FcnIuY2FsbChwZW5kaW5nUmVxdWVzdCwgeGhyLnN0YXR1cyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeGhyU3RhdHVzID0geGhyLnN0YXR1cyB8fCBPS19SRVNQT05TRTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2tfcmVzcG9uc2Vfb25fcmFuZ2VfcmVxdWVzdCA9IHhoclN0YXR1cyA9PT0gT0tfUkVTUE9OU0UgJiYgcGVuZGluZ1JlcXVlc3QuZXhwZWN0ZWRTdGF0dXMgPT09IFBBUlRJQUxfQ09OVEVOVF9SRVNQT05TRTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFva19yZXNwb25zZV9vbl9yYW5nZV9yZXF1ZXN0ICYmIHhoclN0YXR1cyAhPT0gcGVuZGluZ1JlcXVlc3QuZXhwZWN0ZWRTdGF0dXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfcGVuZGluZ1JlcXVlc3Qkb25FcnIyOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgKF9wZW5kaW5nUmVxdWVzdCRvbkVycjIgPSBwZW5kaW5nUmVxdWVzdC5vbkVycm9yKSA9PT0gbnVsbCB8fCBfcGVuZGluZ1JlcXVlc3Qkb25FcnIyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfcGVuZGluZ1JlcXVlc3Qkb25FcnIyLmNhbGwocGVuZGluZ1JlcXVlc3QsIHhoci5zdGF0dXMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNodW5rID0gZ2V0QXJyYXlCdWZmZXIoeGhyKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHhoclN0YXR1cyA9PT0gUEFSVElBTF9DT05URU5UX1JFU1BPTlNFKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByYW5nZUhlYWRlciA9IHhoci5nZXRSZXNwb25zZUhlYWRlcigiQ29udGVudC1SYW5nZSIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWF0Y2hlcyA9IC9ieXRlcyAoXGQrKS0oXGQrKVwvKFxkKykvLmV4ZWMocmFuZ2VIZWFkZXIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVuZGluZ1JlcXVlc3Qub25Eb25lKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogcGFyc2VJbnQobWF0Y2hlc1sxXSwgMTApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNodW5rCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjaHVuaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGVuZGluZ1JlcXVlc3Qub25Eb25lKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZWdpbjogMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaHVuawogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3BlbmRpbmdSZXF1ZXN0JG9uRXJyMzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIChfcGVuZGluZ1JlcXVlc3Qkb25FcnIzID0gcGVuZGluZ1JlcXVlc3Qub25FcnJvcikgPT09IG51bGwgfHwgX3BlbmRpbmdSZXF1ZXN0JG9uRXJyMyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3BlbmRpbmdSZXF1ZXN0JG9uRXJyMy5jYWxsKHBlbmRpbmdSZXF1ZXN0LCB4aHIuc3RhdHVzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRSZXF1ZXN0WGhyKHhocklkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBlbmRpbmdSZXF1ZXN0c1t4aHJJZF0ueGhyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpc1BlbmRpbmdSZXF1ZXN0KHhocklkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB4aHJJZCBpbiB0aGlzLnBlbmRpbmdSZXF1ZXN0czsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYWJvcnRSZXF1ZXN0KHhocklkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHhociA9IHRoaXMucGVuZGluZ1JlcXVlc3RzW3hocklkXS54aHI7CiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnBlbmRpbmdSZXF1ZXN0c1t4aHJJZF07CiAgICAgICAgICAgICAgICAgICAgICAgIHhoci5hYm9ydCgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIFBERk5ldHdvcmtTdHJlYW0gewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHNvdXJjZSkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zb3VyY2UgPSBzb3VyY2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX21hbmFnZXIgPSBuZXcgTmV0d29ya01hbmFnZXIoc291cmNlLnVybCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaHR0cEhlYWRlcnM6IHNvdXJjZS5odHRwSGVhZGVycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpdGhDcmVkZW50aWFsczogc291cmNlLndpdGhDcmVkZW50aWFscwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmFuZ2VDaHVua1NpemUgPSBzb3VyY2UucmFuZ2VDaHVua1NpemU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmFuZ2VSZXF1ZXN0UmVhZGVycyA9IFtdOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfb25SYW5nZVJlcXVlc3RSZWFkZXJDbG9zZWQocmVhZGVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGkgPSB0aGlzLl9yYW5nZVJlcXVlc3RSZWFkZXJzLmluZGV4T2YocmVhZGVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGkgPj0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmFuZ2VSZXF1ZXN0UmVhZGVycy5zcGxpY2UoaSwgMSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0RnVsbFJlYWRlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLmFzc2VydCkoIXRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyLCAiUERGTmV0d29ya1N0cmVhbS5nZXRGdWxsUmVhZGVyIGNhbiBvbmx5IGJlIGNhbGxlZCBvbmNlLiIpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9mdWxsUmVxdWVzdFJlYWRlciA9IG5ldyBQREZOZXR3b3JrU3RyZWFtRnVsbFJlcXVlc3RSZWFkZXIodGhpcy5fbWFuYWdlciwgdGhpcy5fc291cmNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXRSYW5nZVJlYWRlcihiZWdpbiwgZW5kKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlYWRlciA9IG5ldyBQREZOZXR3b3JrU3RyZWFtUmFuZ2VSZXF1ZXN0UmVhZGVyKHRoaXMuX21hbmFnZXIsIGJlZ2luLCBlbmQpOwogICAgICAgICAgICAgICAgICAgICAgICByZWFkZXIub25DbG9zZWQgPSB0aGlzLl9vblJhbmdlUmVxdWVzdFJlYWRlckNsb3NlZC5iaW5kKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yYW5nZVJlcXVlc3RSZWFkZXJzLnB1c2gocmVhZGVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlYWRlcjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FuY2VsQWxsUmVxdWVzdHMocmVhc29uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRfZnVsbFJlcXVlc3RSZWE7CiAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRfZnVsbFJlcXVlc3RSZWEgPSB0aGlzLl9mdWxsUmVxdWVzdFJlYWRlcikgPT09IG51bGwgfHwgX3RoaXMkX2Z1bGxSZXF1ZXN0UmVhID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRfZnVsbFJlcXVlc3RSZWEuY2FuY2VsKHJlYXNvbik7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcmVhZGVyIG9mIHRoaXMuX3JhbmdlUmVxdWVzdFJlYWRlcnMuc2xpY2UoMCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRlci5jYW5jZWwocmVhc29uKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuUERGTmV0d29ya1N0cmVhbSA9IFBERk5ldHdvcmtTdHJlYW07CiAgICAgICAgICAgICAgICBjbGFzcyBQREZOZXR3b3JrU3RyZWFtRnVsbFJlcXVlc3RSZWFkZXIgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKG1hbmFnZXIsIHNvdXJjZSkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9tYW5hZ2VyID0gbWFuYWdlcjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJncyA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uSGVhZGVyc1JlY2VpdmVkOiB0aGlzLl9vbkhlYWRlcnNSZWNlaXZlZC5iaW5kKHRoaXMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb25Eb25lOiB0aGlzLl9vbkRvbmUuYmluZCh0aGlzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uRXJyb3I6IHRoaXMuX29uRXJyb3IuYmluZCh0aGlzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uUHJvZ3Jlc3M6IHRoaXMuX29uUHJvZ3Jlc3MuYmluZCh0aGlzKQogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl91cmwgPSBzb3VyY2UudXJsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9mdWxsUmVxdWVzdElkID0gbWFuYWdlci5yZXF1ZXN0RnVsbChhcmdzKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faGVhZGVyc1JlY2VpdmVkQ2FwYWJpbGl0eSA9ICgwLCBfdXRpbC5jcmVhdGVQcm9taXNlQ2FwYWJpbGl0eSkoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGlzYWJsZVJhbmdlID0gc291cmNlLmRpc2FibGVSYW5nZSB8fCBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29udGVudExlbmd0aCA9IHNvdXJjZS5sZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JhbmdlQ2h1bmtTaXplID0gc291cmNlLnJhbmdlQ2h1bmtTaXplOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX3JhbmdlQ2h1bmtTaXplICYmICF0aGlzLl9kaXNhYmxlUmFuZ2UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Rpc2FibGVSYW5nZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faXNTdHJlYW1pbmdTdXBwb3J0ZWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faXNSYW5nZVN1cHBvcnRlZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYWNoZWRDaHVua3MgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVxdWVzdHMgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9uZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdG9yZWRFcnJvciA9IHVuZGVmaW5lZDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZmlsZW5hbWUgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uUHJvZ3Jlc3MgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfb25IZWFkZXJzUmVjZWl2ZWQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZ1bGxSZXF1ZXN0WGhySWQgPSB0aGlzLl9mdWxsUmVxdWVzdElkOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmdWxsUmVxdWVzdFhociA9IHRoaXMuX21hbmFnZXIuZ2V0UmVxdWVzdFhocihmdWxsUmVxdWVzdFhocklkKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZ2V0UmVzcG9uc2VIZWFkZXIgPSBuYW1lID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmdWxsUmVxdWVzdFhoci5nZXRSZXNwb25zZUhlYWRlcihuYW1lKTsKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsb3dSYW5nZVJlcXVlc3RzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGVkTGVuZ3RoCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSAoMCwgX25ldHdvcmtfdXRpbHMudmFsaWRhdGVSYW5nZVJlcXVlc3RDYXBhYmlsaXRpZXMpKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldFJlc3BvbnNlSGVhZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNIdHRwOiB0aGlzLl9tYW5hZ2VyLmlzSHR0cCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhbmdlQ2h1bmtTaXplOiB0aGlzLl9yYW5nZUNodW5rU2l6ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVSYW5nZTogdGhpcy5fZGlzYWJsZVJhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWxsb3dSYW5nZVJlcXVlc3RzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9pc1JhbmdlU3VwcG9ydGVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb250ZW50TGVuZ3RoID0gc3VnZ2VzdGVkTGVuZ3RoIHx8IHRoaXMuX2NvbnRlbnRMZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2ZpbGVuYW1lID0gKDAsIF9uZXR3b3JrX3V0aWxzLmV4dHJhY3RGaWxlbmFtZUZyb21IZWFkZXIpKGdldFJlc3BvbnNlSGVhZGVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzUmFuZ2VTdXBwb3J0ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX21hbmFnZXIuYWJvcnRSZXF1ZXN0KGZ1bGxSZXF1ZXN0WGhySWQpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2hlYWRlcnNSZWNlaXZlZENhcGFiaWxpdHkucmVzb2x2ZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfb25Eb25lKGRhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9yZXF1ZXN0cy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVxdWVzdENhcGFiaWxpdHkgPSB0aGlzLl9yZXF1ZXN0cy5zaGlmdCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RDYXBhYmlsaXR5LnJlc29sdmUoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZGF0YS5jaHVuaywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY2FjaGVkQ2h1bmtzLnB1c2goZGF0YS5jaHVuayk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9jYWNoZWRDaHVua3MubGVuZ3RoID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcmVxdWVzdENhcGFiaWxpdHkgb2YgdGhpcy5fcmVxdWVzdHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVlc3RDYXBhYmlsaXR5LnJlc29sdmUoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB1bmRlZmluZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZTogdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVxdWVzdHMubGVuZ3RoID0gMDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX29uRXJyb3Ioc3RhdHVzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3N0b3JlZEVycm9yID0gKDAsIF9uZXR3b3JrX3V0aWxzLmNyZWF0ZVJlc3BvbnNlU3RhdHVzRXJyb3IpKHN0YXR1cywgdGhpcy5fdXJsKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faGVhZGVyc1JlY2VpdmVkQ2FwYWJpbGl0eS5yZWplY3QodGhpcy5fc3RvcmVkRXJyb3IpOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHJlcXVlc3RDYXBhYmlsaXR5IG9mIHRoaXMuX3JlcXVlc3RzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0Q2FwYWJpbGl0eS5yZWplY3QodGhpcy5fc3RvcmVkRXJyb3IpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlcXVlc3RzLmxlbmd0aCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NhY2hlZENodW5rcy5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfb25Qcm9ncmVzcyhldnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJG9uUHJvZ3Jlc3M7CiAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRvblByb2dyZXNzID0gdGhpcy5vblByb2dyZXNzKSA9PT0gbnVsbCB8fCBfdGhpcyRvblByb2dyZXNzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRvblByb2dyZXNzLmNhbGwodGhpcywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkOiBldnQubG9hZGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWw6IGV2dC5sZW5ndGhDb21wdXRhYmxlID8gZXZ0LnRvdGFsIDogdGhpcy5fY29udGVudExlbmd0aAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGZpbGVuYW1lKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZmlsZW5hbWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBpc1JhbmdlU3VwcG9ydGVkKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5faXNSYW5nZVN1cHBvcnRlZDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGlzU3RyZWFtaW5nU3VwcG9ydGVkKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5faXNTdHJlYW1pbmdTdXBwb3J0ZWQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBjb250ZW50TGVuZ3RoKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fY29udGVudExlbmd0aDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGhlYWRlcnNSZWFkeSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2hlYWRlcnNSZWNlaXZlZENhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYXN5bmMgcmVhZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX3N0b3JlZEVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyB0aGlzLl9zdG9yZWRFcnJvcjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fY2FjaGVkQ2h1bmtzLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNodW5rID0gdGhpcy5fY2FjaGVkQ2h1bmtzLnNoaWZ0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBjaHVuaywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lOiBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fZG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdW5kZWZpbmVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmU6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVxdWVzdENhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlcXVlc3RzLnB1c2gocmVxdWVzdENhcGFiaWxpdHkpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVxdWVzdENhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FuY2VsKHJlYXNvbikgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faGVhZGVyc1JlY2VpdmVkQ2FwYWJpbGl0eS5yZWplY3QocmVhc29uKTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCByZXF1ZXN0Q2FwYWJpbGl0eSBvZiB0aGlzLl9yZXF1ZXN0cykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdENhcGFiaWxpdHkucmVzb2x2ZSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHVuZGVmaW5lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZXF1ZXN0cy5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fbWFuYWdlci5pc1BlbmRpbmdSZXF1ZXN0KHRoaXMuX2Z1bGxSZXF1ZXN0SWQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9tYW5hZ2VyLmFib3J0UmVxdWVzdCh0aGlzLl9mdWxsUmVxdWVzdElkKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9mdWxsUmVxdWVzdFJlYWRlciA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgUERGTmV0d29ya1N0cmVhbVJhbmdlUmVxdWVzdFJlYWRlciB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IobWFuYWdlciwgYmVnaW4sIGVuZCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9tYW5hZ2VyID0gbWFuYWdlcjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXJncyA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uRG9uZTogdGhpcy5fb25Eb25lLmJpbmQodGhpcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkVycm9yOiB0aGlzLl9vbkVycm9yLmJpbmQodGhpcyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvblByb2dyZXNzOiB0aGlzLl9vblByb2dyZXNzLmJpbmQodGhpcykKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdXJsID0gbWFuYWdlci51cmw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlcXVlc3RJZCA9IG1hbmFnZXIucmVxdWVzdFJhbmdlKGJlZ2luLCBlbmQsIGFyZ3MpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZXF1ZXN0cyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9xdWV1ZWRDaHVuayA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2RvbmUgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RvcmVkRXJyb3IgPSB1bmRlZmluZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub25Qcm9ncmVzcyA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub25DbG9zZWQgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfY2xvc2UoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRvbkNsb3NlZDsKICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJG9uQ2xvc2VkID0gdGhpcy5vbkNsb3NlZCkgPT09IG51bGwgfHwgX3RoaXMkb25DbG9zZWQgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJG9uQ2xvc2VkLmNhbGwodGhpcywgdGhpcyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9vbkRvbmUoZGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaHVuayA9IGRhdGEuY2h1bms7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9yZXF1ZXN0cy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXF1ZXN0Q2FwYWJpbGl0eSA9IHRoaXMuX3JlcXVlc3RzLnNoaWZ0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0Q2FwYWJpbGl0eS5yZXNvbHZlKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogY2h1bmssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcXVldWVkQ2h1bmsgPSBjaHVuazsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCByZXF1ZXN0Q2FwYWJpbGl0eSBvZiB0aGlzLl9yZXF1ZXN0cykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdENhcGFiaWxpdHkucmVzb2x2ZSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHVuZGVmaW5lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZXF1ZXN0cy5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jbG9zZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfb25FcnJvcihzdGF0dXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc3RvcmVkRXJyb3IgPSAoMCwgX25ldHdvcmtfdXRpbHMuY3JlYXRlUmVzcG9uc2VTdGF0dXNFcnJvcikoc3RhdHVzLCB0aGlzLl91cmwpOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHJlcXVlc3RDYXBhYmlsaXR5IG9mIHRoaXMuX3JlcXVlc3RzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1ZXN0Q2FwYWJpbGl0eS5yZWplY3QodGhpcy5fc3RvcmVkRXJyb3IpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlcXVlc3RzLmxlbmd0aCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3F1ZXVlZENodW5rID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX29uUHJvZ3Jlc3MoZXZ0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5pc1N0cmVhbWluZ1N1cHBvcnRlZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJG9uUHJvZ3Jlc3MyOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJG9uUHJvZ3Jlc3MyID0gdGhpcy5vblByb2dyZXNzKSA9PT0gbnVsbCB8fCBfdGhpcyRvblByb2dyZXNzMiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkb25Qcm9ncmVzczIuY2FsbCh0aGlzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkOiBldnQubG9hZGVkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgaXNTdHJlYW1pbmdTdXBwb3J0ZWQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYXN5bmMgcmVhZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX3N0b3JlZEVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyB0aGlzLl9zdG9yZWRFcnJvcjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fcXVldWVkQ2h1bmsgIT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNodW5rID0gdGhpcy5fcXVldWVkQ2h1bms7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9xdWV1ZWRDaHVuayA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBjaHVuaywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lOiBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fZG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdW5kZWZpbmVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmU6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVxdWVzdENhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlcXVlc3RzLnB1c2gocmVxdWVzdENhcGFiaWxpdHkpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVxdWVzdENhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FuY2VsKHJlYXNvbikgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kb25lID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCByZXF1ZXN0Q2FwYWJpbGl0eSBvZiB0aGlzLl9yZXF1ZXN0cykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdENhcGFiaWxpdHkucmVzb2x2ZSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHVuZGVmaW5lZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZXF1ZXN0cy5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fbWFuYWdlci5pc1BlbmRpbmdSZXF1ZXN0KHRoaXMuX3JlcXVlc3RJZCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX21hbmFnZXIuYWJvcnRSZXF1ZXN0KHRoaXMuX3JlcXVlc3RJZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY2xvc2UoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDE2MCAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLlBERkZldGNoU3RyZWFtID0gdm9pZCAwOwogICAgICAgICAgICAgICAgdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygxKTsKICAgICAgICAgICAgICAgIHZhciBfbmV0d29ya191dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTU3KTsKICAgICAgICAgICAgICAgIDsKICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUZldGNoT3B0aW9ucyhoZWFkZXJzLCB3aXRoQ3JlZGVudGlhbHMsIGFib3J0Q29udHJvbGxlcikgewogICAgICAgICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZDogIkdFVCIsCiAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlcnMsCiAgICAgICAgICAgICAgICAgICAgICAgIHNpZ25hbDogYWJvcnRDb250cm9sbGVyLnNpZ25hbCwKICAgICAgICAgICAgICAgICAgICAgICAgbW9kZTogImNvcnMiLAogICAgICAgICAgICAgICAgICAgICAgICBjcmVkZW50aWFsczogd2l0aENyZWRlbnRpYWxzID8gImluY2x1ZGUiIDogInNhbWUtb3JpZ2luIiwKICAgICAgICAgICAgICAgICAgICAgICAgcmVkaXJlY3Q6ICJmb2xsb3ciCiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUhlYWRlcnMoaHR0cEhlYWRlcnMpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWFkZXJzID0gbmV3IEhlYWRlcnMoKTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHByb3BlcnR5IGluIGh0dHBIZWFkZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gaHR0cEhlYWRlcnNbcHJvcGVydHldOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVycy5hcHBlbmQocHJvcGVydHksIHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGhlYWRlcnM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBnZXRBcnJheUJ1ZmZlcih2YWwpIHsKICAgICAgICAgICAgICAgICAgICBpZiAodmFsIGluc3RhbmNlb2YgVWludDhBcnJheSkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsLmJ1ZmZlcjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbCBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgZ2V0QXJyYXlCdWZmZXIgLSB1bmV4cGVjdGVkIGRhdGEgZm9ybWF0OiAke3ZhbH1gKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkodmFsKS5idWZmZXI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBQREZGZXRjaFN0cmVhbSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3Ioc291cmNlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc291cmNlID0gc291cmNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzSHR0cCA9IC9eaHR0cHM/Oi9pLnRlc3Qoc291cmNlLnVybCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaHR0cEhlYWRlcnMgPSB0aGlzLmlzSHR0cCAmJiBzb3VyY2UuaHR0cEhlYWRlcnMgfHwge307CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmFuZ2VSZXF1ZXN0UmVhZGVycyA9IFtdOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgX3Byb2dyZXNzaXZlRGF0YUxlbmd0aCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJF9mdWxsUmVxdWVzdFJlYTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICgoX3RoaXMkX2Z1bGxSZXF1ZXN0UmVhID0gdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXIpID09PSBudWxsIHx8IF90aGlzJF9mdWxsUmVxdWVzdFJlYSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkX2Z1bGxSZXF1ZXN0UmVhLl9sb2FkZWQpID8/IDA7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldEZ1bGxSZWFkZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC5hc3NlcnQpKCF0aGlzLl9mdWxsUmVxdWVzdFJlYWRlciwgIlBERkZldGNoU3RyZWFtLmdldEZ1bGxSZWFkZXIgY2FuIG9ubHkgYmUgY2FsbGVkIG9uY2UuIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyID0gbmV3IFBERkZldGNoU3RyZWFtUmVhZGVyKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldFJhbmdlUmVhZGVyKGJlZ2luLCBlbmQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVuZCA8PSB0aGlzLl9wcm9ncmVzc2l2ZURhdGFMZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlYWRlciA9IG5ldyBQREZGZXRjaFN0cmVhbVJhbmdlUmVhZGVyKHRoaXMsIGJlZ2luLCBlbmQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yYW5nZVJlcXVlc3RSZWFkZXJzLnB1c2gocmVhZGVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlYWRlcjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FuY2VsQWxsUmVxdWVzdHMocmVhc29uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRfZnVsbFJlcXVlc3RSZWEyOwogICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkX2Z1bGxSZXF1ZXN0UmVhMiA9IHRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyKSA9PT0gbnVsbCB8fCBfdGhpcyRfZnVsbFJlcXVlc3RSZWEyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRfZnVsbFJlcXVlc3RSZWEyLmNhbmNlbChyZWFzb24pOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHJlYWRlciBvZiB0aGlzLl9yYW5nZVJlcXVlc3RSZWFkZXJzLnNsaWNlKDApKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkZXIuY2FuY2VsKHJlYXNvbik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLlBERkZldGNoU3RyZWFtID0gUERGRmV0Y2hTdHJlYW07CiAgICAgICAgICAgICAgICBjbGFzcyBQREZGZXRjaFN0cmVhbVJlYWRlciB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3Ioc3RyZWFtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3N0cmVhbSA9IHN0cmVhbTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZGVyID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVkID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZmlsZW5hbWUgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2UgPSBzdHJlYW0uc291cmNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl93aXRoQ3JlZGVudGlhbHMgPSBzb3VyY2Uud2l0aENyZWRlbnRpYWxzIHx8IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb250ZW50TGVuZ3RoID0gc291cmNlLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faGVhZGVyc0NhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Rpc2FibGVSYW5nZSA9IHNvdXJjZS5kaXNhYmxlUmFuZ2UgfHwgZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JhbmdlQ2h1bmtTaXplID0gc291cmNlLnJhbmdlQ2h1bmtTaXplOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX3JhbmdlQ2h1bmtTaXplICYmICF0aGlzLl9kaXNhYmxlUmFuZ2UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Rpc2FibGVSYW5nZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fYWJvcnRDb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9pc1N0cmVhbWluZ1N1cHBvcnRlZCA9ICFzb3VyY2UuZGlzYWJsZVN0cmVhbTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faXNSYW5nZVN1cHBvcnRlZCA9ICFzb3VyY2UuZGlzYWJsZVJhbmdlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9oZWFkZXJzID0gY3JlYXRlSGVhZGVycyh0aGlzLl9zdHJlYW0uaHR0cEhlYWRlcnMpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSBzb3VyY2UudXJsOwogICAgICAgICAgICAgICAgICAgICAgICBmZXRjaCh1cmwsIGNyZWF0ZUZldGNoT3B0aW9ucyh0aGlzLl9oZWFkZXJzLCB0aGlzLl93aXRoQ3JlZGVudGlhbHMsIHRoaXMuX2Fib3J0Q29udHJvbGxlcikpLnRoZW4ocmVzcG9uc2UgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEoMCwgX25ldHdvcmtfdXRpbHMudmFsaWRhdGVSZXNwb25zZVN0YXR1cykocmVzcG9uc2Uuc3RhdHVzKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICgwLCBfbmV0d29ya191dGlscy5jcmVhdGVSZXNwb25zZVN0YXR1c0Vycm9yKShyZXNwb25zZS5zdGF0dXMsIHVybCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWFkZXIgPSByZXNwb25zZS5ib2R5LmdldFJlYWRlcigpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faGVhZGVyc0NhcGFiaWxpdHkucmVzb2x2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZ2V0UmVzcG9uc2VIZWFkZXIgPSBuYW1lID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuaGVhZGVycy5nZXQobmFtZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsbG93UmFuZ2VSZXF1ZXN0cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWdnZXN0ZWRMZW5ndGgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gPSAoMCwgX25ldHdvcmtfdXRpbHMudmFsaWRhdGVSYW5nZVJlcXVlc3RDYXBhYmlsaXRpZXMpKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRSZXNwb25zZUhlYWRlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0h0dHA6IHRoaXMuX3N0cmVhbS5pc0h0dHAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZ2VDaHVua1NpemU6IHRoaXMuX3JhbmdlQ2h1bmtTaXplLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc2FibGVSYW5nZTogdGhpcy5fZGlzYWJsZVJhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2lzUmFuZ2VTdXBwb3J0ZWQgPSBhbGxvd1JhbmdlUmVxdWVzdHM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb250ZW50TGVuZ3RoID0gc3VnZ2VzdGVkTGVuZ3RoIHx8IHRoaXMuX2NvbnRlbnRMZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9maWxlbmFtZSA9ICgwLCBfbmV0d29ya191dGlscy5leHRyYWN0RmlsZW5hbWVGcm9tSGVhZGVyKShnZXRSZXNwb25zZUhlYWRlcik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX2lzU3RyZWFtaW5nU3VwcG9ydGVkICYmIHRoaXMuX2lzUmFuZ2VTdXBwb3J0ZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbmNlbChuZXcgX3V0aWwuQWJvcnRFeGNlcHRpb24oIlN0cmVhbWluZyBpcyBkaXNhYmxlZC4iKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKHRoaXMuX2hlYWRlcnNDYXBhYmlsaXR5LnJlamVjdCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub25Qcm9ncmVzcyA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBoZWFkZXJzUmVhZHkoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9oZWFkZXJzQ2FwYWJpbGl0eS5wcm9taXNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgZmlsZW5hbWUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9maWxlbmFtZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IGNvbnRlbnRMZW5ndGgoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9jb250ZW50TGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgaXNSYW5nZVN1cHBvcnRlZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzUmFuZ2VTdXBwb3J0ZWQ7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBpc1N0cmVhbWluZ1N1cHBvcnRlZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzU3RyZWFtaW5nU3VwcG9ydGVkOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhc3luYyByZWFkKCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkb25Qcm9ncmVzczsKICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5faGVhZGVyc0NhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBhd2FpdCB0aGlzLl9yZWFkZXIucmVhZCgpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9uZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRlZCArPSB2YWx1ZS5ieXRlTGVuZ3RoOwogICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkb25Qcm9ncmVzcyA9IHRoaXMub25Qcm9ncmVzcykgPT09IG51bGwgfHwgX3RoaXMkb25Qcm9ncmVzcyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkb25Qcm9ncmVzcy5jYWxsKHRoaXMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvYWRlZDogdGhpcy5fbG9hZGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdG90YWw6IHRoaXMuX2NvbnRlbnRMZW5ndGgKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZ2V0QXJyYXlCdWZmZXIodmFsdWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FuY2VsKHJlYXNvbikgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkX3JlYWRlcjsKICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJF9yZWFkZXIgPSB0aGlzLl9yZWFkZXIpID09PSBudWxsIHx8IF90aGlzJF9yZWFkZXIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJF9yZWFkZXIuY2FuY2VsKHJlYXNvbik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Fib3J0Q29udHJvbGxlci5hYm9ydCgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIFBERkZldGNoU3RyZWFtUmFuZ2VSZWFkZXIgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHN0cmVhbSwgYmVnaW4sIGVuZCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zdHJlYW0gPSBzdHJlYW07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRlciA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRlZCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZSA9IHN0cmVhbS5zb3VyY2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3dpdGhDcmVkZW50aWFscyA9IHNvdXJjZS53aXRoQ3JlZGVudGlhbHMgfHwgZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRDYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9pc1N0cmVhbWluZ1N1cHBvcnRlZCA9ICFzb3VyY2UuZGlzYWJsZVN0cmVhbTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fYWJvcnRDb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9oZWFkZXJzID0gY3JlYXRlSGVhZGVycyh0aGlzLl9zdHJlYW0uaHR0cEhlYWRlcnMpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9oZWFkZXJzLmFwcGVuZCgiUmFuZ2UiLCBgYnl0ZXM9JHtiZWdpbn0tJHtlbmQgLSAxfWApOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1cmwgPSBzb3VyY2UudXJsOwogICAgICAgICAgICAgICAgICAgICAgICBmZXRjaCh1cmwsIGNyZWF0ZUZldGNoT3B0aW9ucyh0aGlzLl9oZWFkZXJzLCB0aGlzLl93aXRoQ3JlZGVudGlhbHMsIHRoaXMuX2Fib3J0Q29udHJvbGxlcikpLnRoZW4ocmVzcG9uc2UgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEoMCwgX25ldHdvcmtfdXRpbHMudmFsaWRhdGVSZXNwb25zZVN0YXR1cykocmVzcG9uc2Uuc3RhdHVzKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICgwLCBfbmV0d29ya191dGlscy5jcmVhdGVSZXNwb25zZVN0YXR1c0Vycm9yKShyZXNwb25zZS5zdGF0dXMsIHVybCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWFkQ2FwYWJpbGl0eS5yZXNvbHZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZWFkZXIgPSByZXNwb25zZS5ib2R5LmdldFJlYWRlcigpOwogICAgICAgICAgICAgICAgICAgICAgICB9KS5jYXRjaCh0aGlzLl9yZWFkQ2FwYWJpbGl0eS5yZWplY3QpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uUHJvZ3Jlc3MgPSBudWxsOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgaXNTdHJlYW1pbmdTdXBwb3J0ZWQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9pc1N0cmVhbWluZ1N1cHBvcnRlZDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYXN5bmMgcmVhZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJG9uUHJvZ3Jlc3MyOwogICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9yZWFkQ2FwYWJpbGl0eS5wcm9taXNlOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmUKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGF3YWl0IHRoaXMuX3JlYWRlci5yZWFkKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb25lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbmUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVkICs9IHZhbHVlLmJ5dGVMZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRvblByb2dyZXNzMiA9IHRoaXMub25Qcm9ncmVzcykgPT09IG51bGwgfHwgX3RoaXMkb25Qcm9ncmVzczIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJG9uUHJvZ3Jlc3MyLmNhbGwodGhpcywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZGVkOiB0aGlzLl9sb2FkZWQKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZ2V0QXJyYXlCdWZmZXIodmFsdWUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FuY2VsKHJlYXNvbikgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkX3JlYWRlcjI7CiAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRfcmVhZGVyMiA9IHRoaXMuX3JlYWRlcikgPT09IG51bGwgfHwgX3RoaXMkX3JlYWRlcjIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJF9yZWFkZXIyLmNhbmNlbChyZWFzb24pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9hYm9ydENvbnRyb2xsZXIuYWJvcnQoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDE2MSAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLlRleHRMYXllclJlbmRlclRhc2sgPSB2b2lkIDA7CiAgICAgICAgICAgICAgICBleHBvcnRzLnJlbmRlclRleHRMYXllciA9IHJlbmRlclRleHRMYXllcjsKICAgICAgICAgICAgICAgIGV4cG9ydHMudXBkYXRlVGV4dExheWVyID0gdXBkYXRlVGV4dExheWVyOwogICAgICAgICAgICAgICAgdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygxKTsKICAgICAgICAgICAgICAgIHZhciBfZGlzcGxheV91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQyKTsKICAgICAgICAgICAgICAgIGNvbnN0IE1BWF9URVhUX0RJVlNfVE9fUkVOREVSID0gMTAwMDAwOwogICAgICAgICAgICAgICAgY29uc3QgREVGQVVMVF9GT05UX1NJWkUgPSAzMDsKICAgICAgICAgICAgICAgIGNvbnN0IERFRkFVTFRfRk9OVF9BU0NFTlQgPSAwLjg7CiAgICAgICAgICAgICAgICBjb25zdCBhc2NlbnRDYWNoZSA9IG5ldyBNYXAoKTsKICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGdldEN0eChzaXplLCBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCkgewogICAgICAgICAgICAgICAgICAgIGxldCBjdHg7CiAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkICYmIF91dGlsLkZlYXR1cmVUZXN0LmlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eCA9IG5ldyBPZmZzY3JlZW5DYW52YXMoc2l6ZSwgc2l6ZSkuZ2V0Q29udGV4dCgiMmQiLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHBoYTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiY2FudmFzIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhcy53aWR0aCA9IGNhbnZhcy5oZWlnaHQgPSBzaXplOwogICAgICAgICAgICAgICAgICAgICAgICBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgiMmQiLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHBoYTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiBjdHg7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBnZXRBc2NlbnQoZm9udEZhbWlseSwgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjYWNoZWRBc2NlbnQgPSBhc2NlbnRDYWNoZS5nZXQoZm9udEZhbWlseSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKGNhY2hlZEFzY2VudCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FjaGVkQXNjZW50OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBjdHggPSBnZXRDdHgoREVGQVVMVF9GT05UX1NJWkUsIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKTsKICAgICAgICAgICAgICAgICAgICBjdHguZm9udCA9IGAke0RFRkFVTFRfRk9OVF9TSVpFfXB4ICR7Zm9udEZhbWlseX1gOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IG1ldHJpY3MgPSBjdHgubWVhc3VyZVRleHQoIiIpOwogICAgICAgICAgICAgICAgICAgIGxldCBhc2NlbnQgPSBtZXRyaWNzLmZvbnRCb3VuZGluZ0JveEFzY2VudDsKICAgICAgICAgICAgICAgICAgICBsZXQgZGVzY2VudCA9IE1hdGguYWJzKG1ldHJpY3MuZm9udEJvdW5kaW5nQm94RGVzY2VudCk7CiAgICAgICAgICAgICAgICAgICAgaWYgKGFzY2VudCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByYXRpbyA9IGFzY2VudCAvIChhc2NlbnQgKyBkZXNjZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgYXNjZW50Q2FjaGUuc2V0KGZvbnRGYW1pbHksIHJhdGlvKTsKICAgICAgICAgICAgICAgICAgICAgICAgY3R4LmNhbnZhcy53aWR0aCA9IGN0eC5jYW52YXMuaGVpZ2h0ID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJhdGlvOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSAicmVkIjsKICAgICAgICAgICAgICAgICAgICBjdHguY2xlYXJSZWN0KDAsIDAsIERFRkFVTFRfRk9OVF9TSVpFLCBERUZBVUxUX0ZPTlRfU0laRSk7CiAgICAgICAgICAgICAgICAgICAgY3R4LnN0cm9rZVRleHQoImciLCAwLCAwKTsKICAgICAgICAgICAgICAgICAgICBsZXQgcGl4ZWxzID0gY3R4LmdldEltYWdlRGF0YSgwLCAwLCBERUZBVUxUX0ZPTlRfU0laRSwgREVGQVVMVF9GT05UX1NJWkUpLmRhdGE7CiAgICAgICAgICAgICAgICAgICAgZGVzY2VudCA9IDA7CiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IHBpeGVscy5sZW5ndGggLSAxIC0gMzsgaSA+PSAwOyBpIC09IDQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBpeGVsc1tpXSA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbnQgPSBNYXRoLmNlaWwoaSAvIDQgLyBERUZBVUxUX0ZPTlRfU0laRSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjdHguY2xlYXJSZWN0KDAsIDAsIERFRkFVTFRfRk9OVF9TSVpFLCBERUZBVUxUX0ZPTlRfU0laRSk7CiAgICAgICAgICAgICAgICAgICAgY3R4LnN0cm9rZVRleHQoIkEiLCAwLCBERUZBVUxUX0ZPTlRfU0laRSk7CiAgICAgICAgICAgICAgICAgICAgcGl4ZWxzID0gY3R4LmdldEltYWdlRGF0YSgwLCAwLCBERUZBVUxUX0ZPTlRfU0laRSwgREVGQVVMVF9GT05UX1NJWkUpLmRhdGE7CiAgICAgICAgICAgICAgICAgICAgYXNjZW50ID0gMDsKICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBwaXhlbHMubGVuZ3RoOyBpIDwgaWk7IGkgKz0gNCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAocGl4ZWxzW2ldID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNjZW50ID0gREVGQVVMVF9GT05UX1NJWkUgLSBNYXRoLmZsb29yKGkgLyA0IC8gREVGQVVMVF9GT05UX1NJWkUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY3R4LmNhbnZhcy53aWR0aCA9IGN0eC5jYW52YXMuaGVpZ2h0ID0gMDsKICAgICAgICAgICAgICAgICAgICBpZiAoYXNjZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJhdGlvID0gYXNjZW50IC8gKGFzY2VudCArIGRlc2NlbnQpOwogICAgICAgICAgICAgICAgICAgICAgICBhc2NlbnRDYWNoZS5zZXQoZm9udEZhbWlseSwgcmF0aW8pOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmF0aW87CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFzY2VudENhY2hlLnNldChmb250RmFtaWx5LCBERUZBVUxUX0ZPTlRfQVNDRU5UKTsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gREVGQVVMVF9GT05UX0FTQ0VOVDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFRleHQodGFzaywgZ2VvbSwgc3R5bGVzKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGV4dERpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNwYW4iKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXh0RGl2UHJvcGVydGllcyA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgYW5nbGU6IDAsCiAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhc1dpZHRoOiAwLAogICAgICAgICAgICAgICAgICAgICAgICBoYXNUZXh0OiBnZW9tLnN0ciAhPT0gIiIsCiAgICAgICAgICAgICAgICAgICAgICAgIGhhc0VPTDogZ2VvbS5oYXNFT0wsCiAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRTaXplOiAwCiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICB0YXNrLl90ZXh0RGl2cy5wdXNoKHRleHREaXYpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHR4ID0gX3V0aWwuVXRpbC50cmFuc2Zvcm0odGFzay5fdHJhbnNmb3JtLCBnZW9tLnRyYW5zZm9ybSk7CiAgICAgICAgICAgICAgICAgICAgbGV0IGFuZ2xlID0gTWF0aC5hdGFuMih0eFsxXSwgdHhbMF0pOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0eWxlID0gc3R5bGVzW2dlb20uZm9udE5hbWVdOwogICAgICAgICAgICAgICAgICAgIGlmIChzdHlsZS52ZXJ0aWNhbCkgewogICAgICAgICAgICAgICAgICAgICAgICBhbmdsZSArPSBNYXRoLlBJIC8gMjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZm9udEhlaWdodCA9IE1hdGguaHlwb3QodHhbMl0sIHR4WzNdKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBmb250QXNjZW50ID0gZm9udEhlaWdodCAqIGdldEFzY2VudChzdHlsZS5mb250RmFtaWx5LCB0YXNrLl9pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCk7CiAgICAgICAgICAgICAgICAgICAgbGV0IGxlZnQsIHRvcDsKICAgICAgICAgICAgICAgICAgICBpZiAoYW5nbGUgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCA9IHR4WzRdOwogICAgICAgICAgICAgICAgICAgICAgICB0b3AgPSB0eFs1XSAtIGZvbnRBc2NlbnQ7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCA9IHR4WzRdICsgZm9udEFzY2VudCAqIE1hdGguc2luKGFuZ2xlKTsKICAgICAgICAgICAgICAgICAgICAgICAgdG9wID0gdHhbNV0gLSBmb250QXNjZW50ICogTWF0aC5jb3MoYW5nbGUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBzY2FsZUZhY3RvclN0ciA9ICJjYWxjKHZhcigtLXNjYWxlLWZhY3RvcikqIjsKICAgICAgICAgICAgICAgICAgICBjb25zdCBkaXZTdHlsZSA9IHRleHREaXYuc3R5bGU7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRhc2suX2NvbnRhaW5lciA9PT0gdGFzay5fcm9vdENvbnRhaW5lcikgewogICAgICAgICAgICAgICAgICAgICAgICBkaXZTdHlsZS5sZWZ0ID0gYCR7KDEwMCAqIGxlZnQgLyB0YXNrLl9wYWdlV2lkdGgpLnRvRml4ZWQoMil9JWA7CiAgICAgICAgICAgICAgICAgICAgICAgIGRpdlN0eWxlLnRvcCA9IGAkeygxMDAgKiB0b3AgLyB0YXNrLl9wYWdlSGVpZ2h0KS50b0ZpeGVkKDIpfSVgOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRpdlN0eWxlLmxlZnQgPSBgJHtzY2FsZUZhY3RvclN0cn0ke2xlZnQudG9GaXhlZCgyKX1weClgOwogICAgICAgICAgICAgICAgICAgICAgICBkaXZTdHlsZS50b3AgPSBgJHtzY2FsZUZhY3RvclN0cn0ke3RvcC50b0ZpeGVkKDIpfXB4KWA7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRpdlN0eWxlLmZvbnRTaXplID0gYCR7c2NhbGVGYWN0b3JTdHJ9JHtmb250SGVpZ2h0LnRvRml4ZWQoMil9cHgpYDsKICAgICAgICAgICAgICAgICAgICBkaXZTdHlsZS5mb250RmFtaWx5ID0gc3R5bGUuZm9udEZhbWlseTsKICAgICAgICAgICAgICAgICAgICB0ZXh0RGl2UHJvcGVydGllcy5mb250U2l6ZSA9IGZvbnRIZWlnaHQ7CiAgICAgICAgICAgICAgICAgICAgdGV4dERpdi5zZXRBdHRyaWJ1dGUoInJvbGUiLCAicHJlc2VudGF0aW9uIik7CiAgICAgICAgICAgICAgICAgICAgdGV4dERpdi50ZXh0Q29udGVudCA9IGdlb20uc3RyOwogICAgICAgICAgICAgICAgICAgIHRleHREaXYuZGlyID0gZ2VvbS5kaXI7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRhc2suX2ZvbnRJbnNwZWN0b3JFbmFibGVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRleHREaXYuZGF0YXNldC5mb250TmFtZSA9IGdlb20uZm9udE5hbWU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmIChhbmdsZSAhPT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICB0ZXh0RGl2UHJvcGVydGllcy5hbmdsZSA9IGFuZ2xlICogKDE4MCAvIE1hdGguUEkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBsZXQgc2hvdWxkU2NhbGVUZXh0ID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgaWYgKGdlb20uc3RyLmxlbmd0aCA+IDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc2hvdWxkU2NhbGVUZXh0ID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGdlb20uc3RyICE9PSAiICIgJiYgZ2VvbS50cmFuc2Zvcm1bMF0gIT09IGdlb20udHJhbnNmb3JtWzNdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFic1NjYWxlWCA9IE1hdGguYWJzKGdlb20udHJhbnNmb3JtWzBdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFic1NjYWxlWSA9IE1hdGguYWJzKGdlb20udHJhbnNmb3JtWzNdKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFic1NjYWxlWCAhPT0gYWJzU2NhbGVZICYmIE1hdGgubWF4KGFic1NjYWxlWCwgYWJzU2NhbGVZKSAvIE1hdGgubWluKGFic1NjYWxlWCwgYWJzU2NhbGVZKSA+IDEuNSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvdWxkU2NhbGVUZXh0ID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkU2NhbGVUZXh0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRleHREaXZQcm9wZXJ0aWVzLmNhbnZhc1dpZHRoID0gc3R5bGUudmVydGljYWwgPyBnZW9tLmhlaWdodCA6IGdlb20ud2lkdGg7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHRhc2suX3RleHREaXZQcm9wZXJ0aWVzLnNldCh0ZXh0RGl2LCB0ZXh0RGl2UHJvcGVydGllcyk7CiAgICAgICAgICAgICAgICAgICAgaWYgKHRhc2suX2lzUmVhZGFibGVTdHJlYW0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGFzay5fbGF5b3V0VGV4dCh0ZXh0RGl2KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBsYXlvdXQocGFyYW1zKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICBkaXYsCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlLAogICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLAogICAgICAgICAgICAgICAgICAgICAgICBjdHgsCiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZGb250U2l6ZSwKICAgICAgICAgICAgICAgICAgICAgICAgcHJldkZvbnRGYW1pbHkKICAgICAgICAgICAgICAgICAgICB9ID0gcGFyYW1zOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUKICAgICAgICAgICAgICAgICAgICB9ID0gZGl2OwogICAgICAgICAgICAgICAgICAgIGxldCB0cmFuc2Zvcm0gPSAiIjsKICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5jYW52YXNXaWR0aCAhPT0gMCAmJiBwcm9wZXJ0aWVzLmhhc1RleHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udEZhbWlseQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gc3R5bGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbnZhc1dpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udFNpemUKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHByb3BlcnRpZXM7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcmV2Rm9udFNpemUgIT09IGZvbnRTaXplIHx8IHByZXZGb250RmFtaWx5ICE9PSBmb250RmFtaWx5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdHguZm9udCA9IGAke2ZvbnRTaXplICogc2NhbGV9cHggJHtmb250RmFtaWx5fWA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJhbXMucHJldkZvbnRTaXplID0gZm9udFNpemU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJhbXMucHJldkZvbnRGYW1pbHkgPSBmb250RmFtaWx5OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBjdHgubWVhc3VyZVRleHQoZGl2LnRleHRDb250ZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdpZHRoID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtID0gYHNjYWxlWCgke2NhbnZhc1dpZHRoICogc2NhbGUgLyB3aWR0aH0pYDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5hbmdsZSAhPT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2Zvcm0gPSBgcm90YXRlKCR7cHJvcGVydGllcy5hbmdsZX1kZWcpICR7dHJhbnNmb3JtfWA7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmICh0cmFuc2Zvcm0ubGVuZ3RoID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICBzdHlsZS50cmFuc2Zvcm0gPSB0cmFuc2Zvcm07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyKHRhc2spIHsKICAgICAgICAgICAgICAgICAgICBpZiAodGFzay5fY2FuY2VsZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXh0RGl2cyA9IHRhc2suX3RleHREaXZzOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhcGFiaWxpdHkgPSB0YXNrLl9jYXBhYmlsaXR5OwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHRleHREaXZzTGVuZ3RoID0gdGV4dERpdnMubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIGlmICh0ZXh0RGl2c0xlbmd0aCA+IE1BWF9URVhUX0RJVlNfVE9fUkVOREVSKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNhcGFiaWxpdHkucmVzb2x2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmICghdGFzay5faXNSZWFkYWJsZVN0cmVhbSkgewogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHRleHREaXYgb2YgdGV4dERpdnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhc2suX2xheW91dFRleHQodGV4dERpdik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FwYWJpbGl0eS5yZXNvbHZlKCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBUZXh0TGF5ZXJSZW5kZXJUYXNrIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihfcmVmKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfZ2xvYmFsVGhpcyRGb250SW5zcGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0Q29udGVudFNvdXJjZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdwb3J0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dERpdnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0RGl2UHJvcGVydGllcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHRDb250ZW50SXRlbXNTdHIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZAogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdGV4dENvbnRlbnRTb3VyY2UgPSB0ZXh0Q29udGVudFNvdXJjZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5faXNSZWFkYWJsZVN0cmVhbSA9IHRleHRDb250ZW50U291cmNlIGluc3RhbmNlb2YgUmVhZGFibGVTdHJlYW07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lciA9IHRoaXMuX3Jvb3RDb250YWluZXIgPSBjb250YWluZXI7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3RleHREaXZzID0gdGV4dERpdnMgfHwgW107CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3RleHRDb250ZW50SXRlbXNTdHIgPSB0ZXh0Q29udGVudEl0ZW1zU3RyIHx8IFtdOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCA9IGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9mb250SW5zcGVjdG9yRW5hYmxlZCA9ICEhKChfZ2xvYmFsVGhpcyRGb250SW5zcGUgPSBnbG9iYWxUaGlzLkZvbnRJbnNwZWN0b3IpICE9PSBudWxsICYmIF9nbG9iYWxUaGlzJEZvbnRJbnNwZSAhPT0gdm9pZCAwICYmIF9nbG9iYWxUaGlzJEZvbnRJbnNwZS5lbmFibGVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZGVyID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdGV4dERpdlByb3BlcnRpZXMgPSB0ZXh0RGl2UHJvcGVydGllcyB8fCBuZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYW5jZWxlZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9sYXlvdXRUZXh0UGFyYW1zID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldkZvbnRTaXplOiBudWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldkZvbnRGYW1pbHk6IG51bGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXY6IG51bGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZTogdmlld3BvcnQuc2NhbGUgKiAoZ2xvYmFsVGhpcy5kZXZpY2VQaXhlbFJhdGlvIHx8IDEpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczogbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eDogZ2V0Q3R4KDAsIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKQogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlV2lkdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlSGVpZ2h0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZVgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlWQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gdmlld3BvcnQucmF3RGltczsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdHJhbnNmb3JtID0gWzEsIDAsIDAsIC0xLCAtcGFnZVgsIHBhZ2VZICsgcGFnZUhlaWdodF07CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3BhZ2VXaWR0aCA9IHBhZ2VXaWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGFnZUhlaWdodCA9IHBhZ2VIZWlnaHQ7CiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfZGlzcGxheV91dGlscy5zZXRMYXllckRpbWVuc2lvbnMpKGNvbnRhaW5lciwgdmlld3BvcnQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYXBhYmlsaXR5LnByb21pc2UuZmluYWxseSgoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9sYXlvdXRUZXh0UGFyYW1zID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgfSkuY2F0Y2goKCkgPT4ge30pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgcHJvbWlzZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FuY2VsKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jYW5jZWxlZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9yZWFkZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRlci5jYW5jZWwobmV3IF91dGlsLkFib3J0RXhjZXB0aW9uKCJUZXh0TGF5ZXIgdGFzayBjYW5jZWxsZWQuIikpLmNhdGNoKCgpID0+IHt9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlYWRlciA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY2FwYWJpbGl0eS5yZWplY3QobmV3IF91dGlsLkFib3J0RXhjZXB0aW9uKCJUZXh0TGF5ZXIgdGFzayBjYW5jZWxsZWQuIikpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfcHJvY2Vzc0l0ZW1zKGl0ZW1zLCBzdHlsZUNhY2hlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGl0ZW0uc3RyID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXRlbS50eXBlID09PSAiYmVnaW5NYXJrZWRDb250ZW50UHJvcHMiIHx8IGl0ZW0udHlwZSA9PT0gImJlZ2luTWFya2VkQ29udGVudCIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFyZW50ID0gdGhpcy5fY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJzcGFuIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lci5jbGFzc0xpc3QuYWRkKCJtYXJrZWRDb250ZW50Iik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpdGVtLmlkICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb250YWluZXIuc2V0QXR0cmlidXRlKCJpZCIsIGAke2l0ZW0uaWR9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50LmFwcGVuZCh0aGlzLl9jb250YWluZXIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXRlbS50eXBlID09PSAiZW5kTWFya2VkQ29udGVudCIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyLnBhcmVudE5vZGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdGV4dENvbnRlbnRJdGVtc1N0ci5wdXNoKGl0ZW0uc3RyKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGVuZFRleHQodGhpcywgaXRlbSwgc3R5bGVDYWNoZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2xheW91dFRleHQodGV4dERpdikgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZXh0RGl2UHJvcGVydGllcyA9IHRoaXMuX2xheW91dFRleHRQYXJhbXMucHJvcGVydGllcyA9IHRoaXMuX3RleHREaXZQcm9wZXJ0aWVzLmdldCh0ZXh0RGl2KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbGF5b3V0VGV4dFBhcmFtcy5kaXYgPSB0ZXh0RGl2OwogICAgICAgICAgICAgICAgICAgICAgICBsYXlvdXQodGhpcy5fbGF5b3V0VGV4dFBhcmFtcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXh0RGl2UHJvcGVydGllcy5oYXNUZXh0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb250YWluZXIuYXBwZW5kKHRleHREaXYpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0ZXh0RGl2UHJvcGVydGllcy5oYXNFT0wpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYnIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyLnNldEF0dHJpYnV0ZSgicm9sZSIsICJwcmVzZW50YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NvbnRhaW5lci5hcHBlbmQoYnIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9yZW5kZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzdHlsZUNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2lzUmVhZGFibGVTdHJlYW0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHB1bXAgPSAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZGVyLnJlYWQoKS50aGVuKF9yZWYyID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9uZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3JlZjI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb25lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKHN0eWxlQ2FjaGUsIHZhbHVlLnN0eWxlcyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3NJdGVtcyh2YWx1ZS5pdGVtcywgc3R5bGVDYWNoZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1bXAoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBjYXBhYmlsaXR5LnJlamVjdCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVhZGVyID0gdGhpcy5fdGV4dENvbnRlbnRTb3VyY2UuZ2V0UmVhZGVyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwdW1wKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5fdGV4dENvbnRlbnRTb3VyY2UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZXMKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gPSB0aGlzLl90ZXh0Q29udGVudFNvdXJjZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3NJdGVtcyhpdGVtcywgc3R5bGVzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcGFiaWxpdHkucmVzb2x2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyAidGV4dENvbnRlbnRTb3VyY2UiIHBhcmFtZXRlciBzcGVjaWZpZWQuJyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY2FwYWJpbGl0eS5wcm9taXNlLnRoZW4oKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGVDYWNoZSA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXIodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0sIHRoaXMuX2NhcGFiaWxpdHkucmVqZWN0KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLlRleHRMYXllclJlbmRlclRhc2sgPSBUZXh0TGF5ZXJSZW5kZXJUYXNrOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGV4dExheWVyKHBhcmFtcykgewogICAgICAgICAgICAgICAgICAgIGlmICghcGFyYW1zLnRleHRDb250ZW50U291cmNlICYmIChwYXJhbXMudGV4dENvbnRlbnQgfHwgcGFyYW1zLnRleHRDb250ZW50U3RyZWFtKSkgewogICAgICAgICAgICAgICAgICAgICAgICAoMCwgX2Rpc3BsYXlfdXRpbHMuZGVwcmVjYXRlZCkoIlRoZSBUZXh0TGF5ZXJSZW5kZXIgYHRleHRDb250ZW50YC9gdGV4dENvbnRlbnRTdHJlYW1gIHBhcmFtZXRlcnMgIiArICJ3aWxsIGJlIHJlbW92ZWQgaW4gdGhlIGZ1dHVyZSwgcGxlYXNlIHVzZSBgdGV4dENvbnRlbnRTb3VyY2VgIGluc3RlYWQuIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtcy50ZXh0Q29udGVudFNvdXJjZSA9IHBhcmFtcy50ZXh0Q29udGVudCB8fCBwYXJhbXMudGV4dENvbnRlbnRTdHJlYW07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyLAogICAgICAgICAgICAgICAgICAgICAgICB2aWV3cG9ydAogICAgICAgICAgICAgICAgICAgIH0gPSBwYXJhbXM7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKGNvbnRhaW5lcik7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmlzaWJpbGl0eSA9IHN0eWxlLmdldFByb3BlcnR5VmFsdWUoInZpc2liaWxpdHkiKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBzY2FsZUZhY3RvciA9IHBhcnNlRmxvYXQoc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSgiLS1zY2FsZS1mYWN0b3IiKSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKHZpc2liaWxpdHkgPT09ICJ2aXNpYmxlIiAmJiAoIXNjYWxlRmFjdG9yIHx8IE1hdGguYWJzKHNjYWxlRmFjdG9yIC0gdmlld3BvcnQuc2NhbGUpID4gMWUtMTUpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoIlRoZSBgLS1zY2FsZS1mYWN0b3JgIENTUy12YXJpYWJsZSBtdXN0IGJlIHNldCwgIiArICJ0byB0aGUgc2FtZSB2YWx1ZSBhcyBgdmlld3BvcnQuc2NhbGVgLCAiICsgImVpdGhlciBvbiB0aGUgYGNvbnRhaW5lcmAtZWxlbWVudCBpdHNlbGYgb3IgaGlnaGVyIHVwIGluIHRoZSBET00uIik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBuZXcgVGV4dExheWVyUmVuZGVyVGFzayhwYXJhbXMpOwogICAgICAgICAgICAgICAgICAgIHRhc2suX3JlbmRlcigpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiB0YXNrOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlVGV4dExheWVyKF9yZWYzKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyLAogICAgICAgICAgICAgICAgICAgICAgICB2aWV3cG9ydCwKICAgICAgICAgICAgICAgICAgICAgICAgdGV4dERpdnMsCiAgICAgICAgICAgICAgICAgICAgICAgIHRleHREaXZQcm9wZXJ0aWVzLAogICAgICAgICAgICAgICAgICAgICAgICBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCwKICAgICAgICAgICAgICAgICAgICAgICAgbXVzdFJvdGF0ZSA9IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgIG11c3RSZXNjYWxlID0gdHJ1ZQogICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmMzsKICAgICAgICAgICAgICAgICAgICBpZiAobXVzdFJvdGF0ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAoMCwgX2Rpc3BsYXlfdXRpbHMuc2V0TGF5ZXJEaW1lbnNpb25zKShjb250YWluZXIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0aW9uOiB2aWV3cG9ydC5yb3RhdGlvbgogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKG11c3RSZXNjYWxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IGdldEN0eCgwLCBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNjYWxlID0gdmlld3BvcnQuc2NhbGUgKiAoZ2xvYmFsVGhpcy5kZXZpY2VQaXhlbFJhdGlvIHx8IDEpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJhbXMgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2Rm9udFNpemU6IG51bGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2Rm9udEZhbWlseTogbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpdjogbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczogbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN0eAogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGRpdiBvZiB0ZXh0RGl2cykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zLnByb3BlcnRpZXMgPSB0ZXh0RGl2UHJvcGVydGllcy5nZXQoZGl2KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtcy5kaXYgPSBkaXY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXlvdXQocGFyYW1zKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTYyICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuQW5ub3RhdGlvbkVkaXRvckxheWVyID0gdm9pZCAwOwogICAgICAgICAgICAgICAgdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygxKTsKICAgICAgICAgICAgICAgIHZhciBfdG9vbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MSk7CiAgICAgICAgICAgICAgICB2YXIgX2ZyZWV0ZXh0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNjMpOwogICAgICAgICAgICAgICAgdmFyIF9pbmsgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE2NCk7CiAgICAgICAgICAgICAgICB2YXIgX2Rpc3BsYXlfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0Mik7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWMob2JqLCBwcml2YXRlU2V0KSB7IF9jaGVja1ByaXZhdGVSZWRlY2xhcmF0aW9uKG9iaiwgcHJpdmF0ZVNldCk7IHByaXZhdGVTZXQuYWRkKG9iaik7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwgdmFsdWUpIHsga2V5ID0gX3RvUHJvcGVydHlLZXkoa2V5KTsgaWYgKGtleSBpbiBvYmopIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwga2V5LCB7IHZhbHVlOiB2YWx1ZSwgZW51bWVyYWJsZTogdHJ1ZSwgY29uZmlndXJhYmxlOiB0cnVlLCB3cml0YWJsZTogdHJ1ZSB9KTsgfSBlbHNlIHsgb2JqW2tleV0gPSB2YWx1ZTsgfSByZXR1cm4gb2JqOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfdG9Qcm9wZXJ0eUtleShhcmcpIHsgdmFyIGtleSA9IF90b1ByaW1pdGl2ZShhcmcsICJzdHJpbmciKTsgcmV0dXJuIHR5cGVvZiBrZXkgPT09ICJzeW1ib2wiID8ga2V5IDogU3RyaW5nKGtleSk7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF90b1ByaW1pdGl2ZShpbnB1dCwgaGludCkgeyBpZiAodHlwZW9mIGlucHV0ICE9PSAib2JqZWN0IiB8fCBpbnB1dCA9PT0gbnVsbCkgcmV0dXJuIGlucHV0OyB2YXIgcHJpbSA9IGlucHV0W1N5bWJvbC50b1ByaW1pdGl2ZV07IGlmIChwcmltICE9PSB1bmRlZmluZWQpIHsgdmFyIHJlcyA9IHByaW0uY2FsbChpbnB1dCwgaGludCB8fCAiZGVmYXVsdCIpOyBpZiAodHlwZW9mIHJlcyAhPT0gIm9iamVjdCIpIHJldHVybiByZXM7IHRocm93IG5ldyBUeXBlRXJyb3IoIkBAdG9QcmltaXRpdmUgbXVzdCByZXR1cm4gYSBwcmltaXRpdmUgdmFsdWUuIik7IH0gcmV0dXJuIChoaW50ID09PSAic3RyaW5nIiA/IFN0cmluZyA6IE51bWJlcikoaW5wdXQpOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyhvYmosIHByaXZhdGVNYXAsIHZhbHVlKSB7IF9jaGVja1ByaXZhdGVSZWRlY2xhcmF0aW9uKG9iaiwgcHJpdmF0ZU1hcCk7IHByaXZhdGVNYXAuc2V0KG9iaiwgdmFsdWUpOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2hlY2tQcml2YXRlUmVkZWNsYXJhdGlvbihvYmosIHByaXZhdGVDb2xsZWN0aW9uKSB7IGlmIChwcml2YXRlQ29sbGVjdGlvbi5oYXMob2JqKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgaW5pdGlhbGl6ZSB0aGUgc2FtZSBwcml2YXRlIGVsZW1lbnRzIHR3aWNlIG9uIGFuIG9iamVjdCIpOyB9IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQocmVjZWl2ZXIsIHByaXZhdGVTZXQsIGZuKSB7IGlmICghcHJpdmF0ZVNldC5oYXMocmVjZWl2ZXIpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoImF0dGVtcHRlZCB0byBnZXQgcHJpdmF0ZSBmaWVsZCBvbiBub24taW5zdGFuY2UiKTsgfSByZXR1cm4gZm47IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVGaWVsZEdldChyZWNlaXZlciwgcHJpdmF0ZU1hcCkgeyB2YXIgZGVzY3JpcHRvciA9IF9jbGFzc0V4dHJhY3RGaWVsZERlc2NyaXB0b3IocmVjZWl2ZXIsIHByaXZhdGVNYXAsICJnZXQiKTsgcmV0dXJuIF9jbGFzc0FwcGx5RGVzY3JpcHRvckdldChyZWNlaXZlciwgZGVzY3JpcHRvcik7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc0FwcGx5RGVzY3JpcHRvckdldChyZWNlaXZlciwgZGVzY3JpcHRvcikgeyBpZiAoZGVzY3JpcHRvci5nZXQpIHsgcmV0dXJuIGRlc2NyaXB0b3IuZ2V0LmNhbGwocmVjZWl2ZXIpOyB9IHJldHVybiBkZXNjcmlwdG9yLnZhbHVlOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlRmllbGRTZXQocmVjZWl2ZXIsIHByaXZhdGVNYXAsIHZhbHVlKSB7IHZhciBkZXNjcmlwdG9yID0gX2NsYXNzRXh0cmFjdEZpZWxkRGVzY3JpcHRvcihyZWNlaXZlciwgcHJpdmF0ZU1hcCwgInNldCIpOyBfY2xhc3NBcHBseURlc2NyaXB0b3JTZXQocmVjZWl2ZXIsIGRlc2NyaXB0b3IsIHZhbHVlKTsgcmV0dXJuIHZhbHVlOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NFeHRyYWN0RmllbGREZXNjcmlwdG9yKHJlY2VpdmVyLCBwcml2YXRlTWFwLCBhY3Rpb24pIHsgaWYgKCFwcml2YXRlTWFwLmhhcyhyZWNlaXZlcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigiYXR0ZW1wdGVkIHRvICIgKyBhY3Rpb24gKyAiIHByaXZhdGUgZmllbGQgb24gbm9uLWluc3RhbmNlIik7IH0gcmV0dXJuIHByaXZhdGVNYXAuZ2V0KHJlY2VpdmVyKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzQXBwbHlEZXNjcmlwdG9yU2V0KHJlY2VpdmVyLCBkZXNjcmlwdG9yLCB2YWx1ZSkgeyBpZiAoZGVzY3JpcHRvci5zZXQpIHsgZGVzY3JpcHRvci5zZXQuY2FsbChyZWNlaXZlciwgdmFsdWUpOyB9IGVsc2UgeyBpZiAoIWRlc2NyaXB0b3Iud3JpdGFibGUpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigiYXR0ZW1wdGVkIHRvIHNldCByZWFkIG9ubHkgcHJpdmF0ZSBmaWVsZCIpOyB9IGRlc2NyaXB0b3IudmFsdWUgPSB2YWx1ZTsgfSB9CiAgICAgICAgICAgICAgICB2YXIgX2FjY2Vzc2liaWxpdHlNYW5hZ2VyID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2FsbG93Q2xpY2sgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYm91bmRQb2ludGVydXAgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYm91bmRQb2ludGVyZG93biA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9lZGl0b3JzID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2hhZFBvaW50ZXJEb3duID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2lzQ2xlYW5pbmdVcCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF91aU1hbmFnZXIgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfY2hhbmdlUGFyZW50ID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICB2YXIgX2NyZWF0ZU5ld0VkaXRvciA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9jcmVhdGVBbmRBZGROZXdFZGl0b3IgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIHZhciBfY2xlYW51cCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgY2xhc3MgQW5ub3RhdGlvbkVkaXRvckxheWVyIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfY2xlYW51cCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfY3JlYXRlQW5kQWRkTmV3RWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF9jcmVhdGVOZXdFZGl0b3IpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2NoYW5nZVBhcmVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9hY2Nlc3NpYmlsaXR5TWFuYWdlciwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdm9pZCAwCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfYWxsb3dDbGljaywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9ib3VuZFBvaW50ZXJ1cCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5wb2ludGVydXAuYmluZCh0aGlzKQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2JvdW5kUG9pbnRlcmRvd24sIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMucG9pbnRlcmRvd24uYmluZCh0aGlzKQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2VkaXRvcnMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG5ldyBNYXAoKQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2hhZFBvaW50ZXJEb3duLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2lzQ2xlYW5pbmdVcCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF91aU1hbmFnZXIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHZvaWQgMAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFBbm5vdGF0aW9uRWRpdG9yTGF5ZXIuX2luaXRpYWxpemVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBBbm5vdGF0aW9uRWRpdG9yTGF5ZXIuX2luaXRpYWxpemVkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9mcmVldGV4dC5GcmVlVGV4dEVkaXRvci5pbml0aWFsaXplKG9wdGlvbnMubDEwbik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfaW5rLklua0VkaXRvci5pbml0aWFsaXplKG9wdGlvbnMubDEwbik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy51aU1hbmFnZXIucmVnaXN0ZXJFZGl0b3JUeXBlcyhbX2ZyZWV0ZXh0LkZyZWVUZXh0RWRpdG9yLCBfaW5rLklua0VkaXRvcl0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX3VpTWFuYWdlciwgb3B0aW9ucy51aU1hbmFnZXIpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhZ2VJbmRleCA9IG9wdGlvbnMucGFnZUluZGV4OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdiA9IG9wdGlvbnMuZGl2OwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2FjY2Vzc2liaWxpdHlNYW5hZ2VyLCBvcHRpb25zLmFjY2Vzc2liaWxpdHlNYW5hZ2VyKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLmFkZExheWVyKHRoaXMpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBnZXQgaXNFbXB0eSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZWRpdG9ycykuc2l6ZSA9PT0gMDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdXBkYXRlVG9vbGJhcihtb2RlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfdWlNYW5hZ2VyKS51cGRhdGVUb29sYmFyKG1vZGUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB1cGRhdGVNb2RlKCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgbW9kZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLmdldE1vZGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfY2xlYW51cCwgX2NsZWFudXAyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAobW9kZSA9PT0gX3V0aWwuQW5ub3RhdGlvbkVkaXRvclR5cGUuSU5LKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZElua0VkaXRvcklmTmVlZGVkKGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzYWJsZUNsaWNrKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZUNsaWNrKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLnVuc2VsZWN0QWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtb2RlICE9PSBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yVHlwZS5OT05FKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5jbGFzc0xpc3QudG9nZ2xlKCJmcmVlVGV4dEVkaXRpbmciLCBtb2RlID09PSBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yVHlwZS5GUkVFVEVYVCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5jbGFzc0xpc3QudG9nZ2xlKCJpbmtFZGl0aW5nIiwgbW9kZSA9PT0gX3V0aWwuQW5ub3RhdGlvbkVkaXRvclR5cGUuSU5LKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmhpZGRlbiA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFkZElua0VkaXRvcklmTmVlZGVkKGlzQ29tbWl0dGluZykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzQ29tbWl0dGluZyAmJiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3VpTWFuYWdlcikuZ2V0TW9kZSgpICE9PSBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yVHlwZS5JTkspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlzQ29tbWl0dGluZykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlZGl0b3Igb2YgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9lZGl0b3JzKS52YWx1ZXMoKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlZGl0b3IuaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5zZXRJbkJhY2tncm91bmQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlZGl0b3IgPSBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9jcmVhdGVBbmRBZGROZXdFZGl0b3IsIF9jcmVhdGVBbmRBZGROZXdFZGl0b3IyKS5jYWxsKHRoaXMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mZnNldFg6IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRZOiAwCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3Iuc2V0SW5CYWNrZ3JvdW5kKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldEVkaXRpbmdTdGF0ZShpc0VkaXRpbmcpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLnNldEVkaXRpbmdTdGF0ZShpc0VkaXRpbmcpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhZGRDb21tYW5kcyhwYXJhbXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLmFkZENvbW1hbmRzKHBhcmFtcyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVuYWJsZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYuc3R5bGUucG9pbnRlckV2ZW50cyA9ICJhdXRvIjsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlZGl0b3Igb2YgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9lZGl0b3JzKS52YWx1ZXMoKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLmVuYWJsZUVkaXRpbmcoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkaXNhYmxlKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5zdHlsZS5wb2ludGVyRXZlbnRzID0gIm5vbmUiOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVkaXRvciBvZiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2VkaXRvcnMpLnZhbHVlcygpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3IuZGlzYWJsZUVkaXRpbmcoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9jbGVhbnVwLCBfY2xlYW51cDIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzRW1wdHkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmhpZGRlbiA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0QWN0aXZlRWRpdG9yKGVkaXRvcikgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50QWN0aXZlID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLmdldEFjdGl2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudEFjdGl2ZSA9PT0gZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLnNldEFjdGl2ZUVkaXRvcihlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbmFibGVDbGljaygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYuYWRkRXZlbnRMaXN0ZW5lcigicG9pbnRlcmRvd24iLCBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2JvdW5kUG9pbnRlcmRvd24pKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYuYWRkRXZlbnRMaXN0ZW5lcigicG9pbnRlcnVwIiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZFBvaW50ZXJ1cCkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkaXNhYmxlQ2xpY2soKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LnJlbW92ZUV2ZW50TGlzdGVuZXIoInBvaW50ZXJkb3duIiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZFBvaW50ZXJkb3duKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LnJlbW92ZUV2ZW50TGlzdGVuZXIoInBvaW50ZXJ1cCIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRQb2ludGVydXApKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYXR0YWNoKGVkaXRvcikgewogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2VkaXRvcnMpLnNldChlZGl0b3IuaWQsIGVkaXRvcik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRldGFjaChlZGl0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9jbGFzc1ByaXZhdGVGaWVsZEdldDI7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZWRpdG9ycykuZGVsZXRlKGVkaXRvci5pZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIChfY2xhc3NQcml2YXRlRmllbGRHZXQyID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9hY2Nlc3NpYmlsaXR5TWFuYWdlcikpID09PSBudWxsIHx8IF9jbGFzc1ByaXZhdGVGaWVsZEdldDIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9jbGFzc1ByaXZhdGVGaWVsZEdldDIucmVtb3ZlUG9pbnRlckluVGV4dExheWVyKGVkaXRvci5jb250ZW50RGl2KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlKGVkaXRvcikgewogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3VpTWFuYWdlcikucmVtb3ZlRWRpdG9yKGVkaXRvcik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGV0YWNoKGVkaXRvcik7CiAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5kaXYuc3R5bGUuZGlzcGxheSA9ICJub25lIjsKICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3IuZGl2LnN0eWxlLmRpc3BsYXkgPSAiIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5kaXYucmVtb3ZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3IuaXNBdHRhY2hlZFRvRE9NID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gZG9jdW1lbnQuYm9keSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfdWlNYW5hZ2VyKS5mb2N1c01haW5Db250YWluZXIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSwgMCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9pc0NsZWFuaW5nVXApKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZElua0VkaXRvcklmTmVlZGVkKGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhZGQoZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2NoYW5nZVBhcmVudCwgX2NoYW5nZVBhcmVudDIpLmNhbGwodGhpcywgZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLmFkZEVkaXRvcihlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmF0dGFjaChlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWVkaXRvci5pc0F0dGFjaGVkVG9ET00pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpdiA9IGVkaXRvci5yZW5kZXIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmFwcGVuZChkaXYpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLmlzQXR0YWNoZWRUb0RPTSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tb3ZlRWRpdG9ySW5ET00oZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLm9uY2VBZGRlZCgpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3VpTWFuYWdlcikuYWRkVG9Bbm5vdGF0aW9uU3RvcmFnZShlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBtb3ZlRWRpdG9ySW5ET00oZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfY2xhc3NQcml2YXRlRmllbGRHZXQzOwogICAgICAgICAgICAgICAgICAgICAgICAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0MyA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYWNjZXNzaWJpbGl0eU1hbmFnZXIpKSA9PT0gbnVsbCB8fCBfY2xhc3NQcml2YXRlRmllbGRHZXQzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfY2xhc3NQcml2YXRlRmllbGRHZXQzLm1vdmVFbGVtZW50SW5ET00odGhpcy5kaXYsIGVkaXRvci5kaXYsIGVkaXRvci5jb250ZW50RGl2LCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYWRkT3JSZWJ1aWxkKGVkaXRvcikgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWRpdG9yLm5lZWRzVG9CZVJlYnVpbHQoKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLnJlYnVpbGQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkKGVkaXRvcik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgYWRkQU5ld0VkaXRvcihlZGl0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY21kID0gKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRPclJlYnVpbGQoZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdW5kbyA9ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5yZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRDb21tYW5kcyh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmRvLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVzdEV4ZWM6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGFkZFVuZG9hYmxlRWRpdG9yKGVkaXRvcikgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjbWQgPSAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZE9yUmVidWlsZChlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bmRvID0gKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLnJlbW92ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZENvbW1hbmRzKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNtZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuZG8sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXN0RXhlYzogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldE5leHRJZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfdWlNYW5hZ2VyKS5nZXRJZCgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkZXNlcmlhbGl6ZShkYXRhKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZGF0YS5hbm5vdGF0aW9uVHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yVHlwZS5GUkVFVEVYVDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2ZyZWV0ZXh0LkZyZWVUZXh0RWRpdG9yLmRlc2VyaWFsaXplKGRhdGEsIHRoaXMsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfdWlNYW5hZ2VyKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25FZGl0b3JUeXBlLklOSzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2luay5JbmtFZGl0b3IuZGVzZXJpYWxpemUoZGF0YSwgdGhpcywgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0U2VsZWN0ZWQoZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfdWlNYW5hZ2VyKS5zZXRTZWxlY3RlZChlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB0b2dnbGVTZWxlY3RlZChlZGl0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLnRvZ2dsZVNlbGVjdGVkKGVkaXRvcik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlzU2VsZWN0ZWQoZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3VpTWFuYWdlcikuaXNTZWxlY3RlZChlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB1bnNlbGVjdChlZGl0b3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLnVuc2VsZWN0KGVkaXRvcik7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHBvaW50ZXJ1cChldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc01hYwogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3V0aWwuRmVhdHVyZVRlc3QucGxhdGZvcm07CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudC5idXR0b24gIT09IDAgfHwgZXZlbnQuY3RybEtleSAmJiBpc01hYykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudC50YXJnZXQgIT09IHRoaXMuZGl2KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2hhZFBvaW50ZXJEb3duKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfaGFkUG9pbnRlckRvd24sIGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FsbG93Q2xpY2spKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2FsbG93Q2xpY2ssIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2NyZWF0ZUFuZEFkZE5ld0VkaXRvciwgX2NyZWF0ZUFuZEFkZE5ld0VkaXRvcjIpLmNhbGwodGhpcywgZXZlbnQpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBwb2ludGVyZG93bihldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc01hYwogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3V0aWwuRmVhdHVyZVRlc3QucGxhdGZvcm07CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudC5idXR0b24gIT09IDAgfHwgZXZlbnQuY3RybEtleSAmJiBpc01hYykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudC50YXJnZXQgIT09IHRoaXMuZGl2KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9oYWRQb2ludGVyRG93biwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVkaXRvciA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfdWlNYW5hZ2VyKS5nZXRBY3RpdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9hbGxvd0NsaWNrLCAhZWRpdG9yIHx8IGVkaXRvci5pc0VtcHR5KCkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkcm9wKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkID0gZXZlbnQuZGF0YVRyYW5zZmVyLmdldERhdGEoInRleHQvcGxhaW4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZWRpdG9yID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLmdldEVkaXRvcihpZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZWRpdG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAibW92ZSI7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2NoYW5nZVBhcmVudCwgX2NoYW5nZVBhcmVudDIpLmNhbGwodGhpcywgZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVjdCA9IHRoaXMuZGl2LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlbmRYID0gZXZlbnQuY2xpZW50WCAtIHJlY3QueDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZW5kWSA9IGV2ZW50LmNsaWVudFkgLSByZWN0Lnk7CiAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci50cmFuc2xhdGUoZW5kWCAtIGVkaXRvci5zdGFydFgsIGVuZFkgLSBlZGl0b3Iuc3RhcnRZKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tb3ZlRWRpdG9ySW5ET00oZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLmRpdi5mb2N1cygpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkcmFnb3ZlcihldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkZXN0cm95KCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0NDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCgoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0NCA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfdWlNYW5hZ2VyKS5nZXRBY3RpdmUoKSkgPT09IG51bGwgfHwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0NCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2NsYXNzUHJpdmF0ZUZpZWxkR2V0NC5wYXJlbnQpID09PSB0aGlzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3VpTWFuYWdlcikuc2V0QWN0aXZlRWRpdG9yKG51bGwpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZWRpdG9yIG9mIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZWRpdG9ycykudmFsdWVzKCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfY2xhc3NQcml2YXRlRmllbGRHZXQ1OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgKF9jbGFzc1ByaXZhdGVGaWVsZEdldDUgPSBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FjY2Vzc2liaWxpdHlNYW5hZ2VyKSkgPT09IG51bGwgfHwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0NSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2NsYXNzUHJpdmF0ZUZpZWxkR2V0NS5yZW1vdmVQb2ludGVySW5UZXh0TGF5ZXIoZWRpdG9yLmNvbnRlbnREaXYpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLnNldFBhcmVudChudWxsKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5pc0F0dGFjaGVkVG9ET00gPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5kaXYucmVtb3ZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2VkaXRvcnMpLmNsZWFyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfdWlNYW5hZ2VyKS5yZW1vdmVMYXllcih0aGlzKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVuZGVyKF9yZWYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdwb3J0CiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZpZXdwb3J0ID0gdmlld3BvcnQ7CiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfZGlzcGxheV91dGlscy5zZXRMYXllckRpbWVuc2lvbnMpKHRoaXMuZGl2LCB2aWV3cG9ydCk7CiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdG9vbHMuYmluZEV2ZW50cykodGhpcywgdGhpcy5kaXYsIFsiZHJhZ292ZXIiLCAiZHJvcCJdKTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlZGl0b3Igb2YgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLmdldEVkaXRvcnModGhpcy5wYWdlSW5kZXgpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZChlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlTW9kZSgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB1cGRhdGUoX3JlZjIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdwb3J0CiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmMjsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLmNvbW1pdE9yUmVtb3ZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudmlld3BvcnQgPSB2aWV3cG9ydDsKICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF9kaXNwbGF5X3V0aWxzLnNldExheWVyRGltZW5zaW9ucykodGhpcy5kaXYsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0aW9uOiB2aWV3cG9ydC5yb3RhdGlvbgogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51cGRhdGVNb2RlKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBwYWdlRGltZW5zaW9ucygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZVdpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUhlaWdodAogICAgICAgICAgICAgICAgICAgICAgICB9ID0gdGhpcy52aWV3cG9ydC5yYXdEaW1zOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW3BhZ2VXaWR0aCwgcGFnZUhlaWdodF07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5Bbm5vdGF0aW9uRWRpdG9yTGF5ZXIgPSBBbm5vdGF0aW9uRWRpdG9yTGF5ZXI7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2hhbmdlUGFyZW50MihlZGl0b3IpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgX2VkaXRvciRwYXJlbnQ7CiAgICAgICAgICAgICAgICAgICAgaWYgKGVkaXRvci5wYXJlbnQgPT09IHRoaXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB0aGlzLmF0dGFjaChlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgIChfZWRpdG9yJHBhcmVudCA9IGVkaXRvci5wYXJlbnQpID09PSBudWxsIHx8IF9lZGl0b3IkcGFyZW50ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfZWRpdG9yJHBhcmVudC5kZXRhY2goZWRpdG9yKTsKICAgICAgICAgICAgICAgICAgICBlZGl0b3Iuc2V0UGFyZW50KHRoaXMpOwogICAgICAgICAgICAgICAgICAgIGlmIChlZGl0b3IuZGl2ICYmIGVkaXRvci5pc0F0dGFjaGVkVG9ET00pIHsKICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLmRpdi5yZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYuYXBwZW5kKGVkaXRvci5kaXYpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jcmVhdGVOZXdFZGl0b3IyKHBhcmFtcykgewogICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpLmdldE1vZGUoKSkgewogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25FZGl0b3JUeXBlLkZSRUVURVhUOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBfZnJlZXRleHQuRnJlZVRleHRFZGl0b3IocGFyYW1zKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yVHlwZS5JTks6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IF9pbmsuSW5rRWRpdG9yKHBhcmFtcyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NyZWF0ZUFuZEFkZE5ld0VkaXRvcjIoZXZlbnQpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBpZCA9IHRoaXMuZ2V0TmV4dElkKCk7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgZWRpdG9yID0gX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfY3JlYXRlTmV3RWRpdG9yLCBfY3JlYXRlTmV3RWRpdG9yMikuY2FsbCh0aGlzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudDogdGhpcywKICAgICAgICAgICAgICAgICAgICAgICAgaWQsCiAgICAgICAgICAgICAgICAgICAgICAgIHg6IGV2ZW50Lm9mZnNldFgsCiAgICAgICAgICAgICAgICAgICAgICAgIHk6IGV2ZW50Lm9mZnNldFksCiAgICAgICAgICAgICAgICAgICAgICAgIHVpTWFuYWdlcjogX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF91aU1hbmFnZXIpCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKGVkaXRvcikgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZChlZGl0b3IpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gZWRpdG9yOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsZWFudXAyKCkgewogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfaXNDbGVhbmluZ1VwLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGVkaXRvciBvZiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2VkaXRvcnMpLnZhbHVlcygpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlZGl0b3IuaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3IucmVtb3ZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9pc0NsZWFuaW5nVXAsIGZhbHNlKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIF9kZWZpbmVQcm9wZXJ0eShBbm5vdGF0aW9uRWRpdG9yTGF5ZXIsICJfaW5pdGlhbGl6ZWQiLCBmYWxzZSk7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDE2MyAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLkZyZWVUZXh0RWRpdG9yID0gdm9pZCAwOwogICAgICAgICAgICAgICAgdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygxKTsKICAgICAgICAgICAgICAgIHZhciBfdG9vbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MSk7CiAgICAgICAgICAgICAgICB2YXIgX2VkaXRvciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQwKTsKICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyhvYmosIHByaXZhdGVTZXQpIHsgX2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24ob2JqLCBwcml2YXRlU2V0KTsgcHJpdmF0ZVNldC5hZGQob2JqKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnR5KG9iaiwga2V5LCB2YWx1ZSkgeyBrZXkgPSBfdG9Qcm9wZXJ0eUtleShrZXkpOyBpZiAoa2V5IGluIG9iaikgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXksIHsgdmFsdWU6IHZhbHVlLCBlbnVtZXJhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUsIHdyaXRhYmxlOiB0cnVlIH0pOyB9IGVsc2UgeyBvYmpba2V5XSA9IHZhbHVlOyB9IHJldHVybiBvYmo7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF90b1Byb3BlcnR5S2V5KGFyZykgeyB2YXIga2V5ID0gX3RvUHJpbWl0aXZlKGFyZywgInN0cmluZyIpOyByZXR1cm4gdHlwZW9mIGtleSA9PT0gInN5bWJvbCIgPyBrZXkgOiBTdHJpbmcoa2V5KTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3RvUHJpbWl0aXZlKGlucHV0LCBoaW50KSB7IGlmICh0eXBlb2YgaW5wdXQgIT09ICJvYmplY3QiIHx8IGlucHV0ID09PSBudWxsKSByZXR1cm4gaW5wdXQ7IHZhciBwcmltID0gaW5wdXRbU3ltYm9sLnRvUHJpbWl0aXZlXTsgaWYgKHByaW0gIT09IHVuZGVmaW5lZCkgeyB2YXIgcmVzID0gcHJpbS5jYWxsKGlucHV0LCBoaW50IHx8ICJkZWZhdWx0Iik7IGlmICh0eXBlb2YgcmVzICE9PSAib2JqZWN0IikgcmV0dXJuIHJlczsgdGhyb3cgbmV3IFR5cGVFcnJvcigiQEB0b1ByaW1pdGl2ZSBtdXN0IHJldHVybiBhIHByaW1pdGl2ZSB2YWx1ZS4iKTsgfSByZXR1cm4gKGhpbnQgPT09ICJzdHJpbmciID8gU3RyaW5nIDogTnVtYmVyKShpbnB1dCk7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKG9iaiwgcHJpdmF0ZU1hcCwgdmFsdWUpIHsgX2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24ob2JqLCBwcml2YXRlTWFwKTsgcHJpdmF0ZU1hcC5zZXQob2JqLCB2YWx1ZSk7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jaGVja1ByaXZhdGVSZWRlY2xhcmF0aW9uKG9iaiwgcHJpdmF0ZUNvbGxlY3Rpb24pIHsgaWYgKHByaXZhdGVDb2xsZWN0aW9uLmhhcyhvYmopKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoIkNhbm5vdCBpbml0aWFsaXplIHRoZSBzYW1lIHByaXZhdGUgZWxlbWVudHMgdHdpY2Ugb24gYW4gb2JqZWN0Iik7IH0gfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHJlY2VpdmVyLCBwcml2YXRlTWFwKSB7IHZhciBkZXNjcmlwdG9yID0gX2NsYXNzRXh0cmFjdEZpZWxkRGVzY3JpcHRvcihyZWNlaXZlciwgcHJpdmF0ZU1hcCwgImdldCIpOyByZXR1cm4gX2NsYXNzQXBwbHlEZXNjcmlwdG9yR2V0KHJlY2VpdmVyLCBkZXNjcmlwdG9yKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzQXBwbHlEZXNjcmlwdG9yR2V0KHJlY2VpdmVyLCBkZXNjcmlwdG9yKSB7IGlmIChkZXNjcmlwdG9yLmdldCkgeyByZXR1cm4gZGVzY3JpcHRvci5nZXQuY2FsbChyZWNlaXZlcik7IH0gcmV0dXJuIGRlc2NyaXB0b3IudmFsdWU7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQocmVjZWl2ZXIsIHByaXZhdGVTZXQsIGZuKSB7IGlmICghcHJpdmF0ZVNldC5oYXMocmVjZWl2ZXIpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoImF0dGVtcHRlZCB0byBnZXQgcHJpdmF0ZSBmaWVsZCBvbiBub24taW5zdGFuY2UiKTsgfSByZXR1cm4gZm47IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVGaWVsZFNldChyZWNlaXZlciwgcHJpdmF0ZU1hcCwgdmFsdWUpIHsgdmFyIGRlc2NyaXB0b3IgPSBfY2xhc3NFeHRyYWN0RmllbGREZXNjcmlwdG9yKHJlY2VpdmVyLCBwcml2YXRlTWFwLCAic2V0Iik7IF9jbGFzc0FwcGx5RGVzY3JpcHRvclNldChyZWNlaXZlciwgZGVzY3JpcHRvciwgdmFsdWUpOyByZXR1cm4gdmFsdWU7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc0V4dHJhY3RGaWVsZERlc2NyaXB0b3IocmVjZWl2ZXIsIHByaXZhdGVNYXAsIGFjdGlvbikgeyBpZiAoIXByaXZhdGVNYXAuaGFzKHJlY2VpdmVyKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJhdHRlbXB0ZWQgdG8gIiArIGFjdGlvbiArICIgcHJpdmF0ZSBmaWVsZCBvbiBub24taW5zdGFuY2UiKTsgfSByZXR1cm4gcHJpdmF0ZU1hcC5nZXQocmVjZWl2ZXIpOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NBcHBseURlc2NyaXB0b3JTZXQocmVjZWl2ZXIsIGRlc2NyaXB0b3IsIHZhbHVlKSB7IGlmIChkZXNjcmlwdG9yLnNldCkgeyBkZXNjcmlwdG9yLnNldC5jYWxsKHJlY2VpdmVyLCB2YWx1ZSk7IH0gZWxzZSB7IGlmICghZGVzY3JpcHRvci53cml0YWJsZSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJhdHRlbXB0ZWQgdG8gc2V0IHJlYWQgb25seSBwcml2YXRlIGZpZWxkIik7IH0gZGVzY3JpcHRvci52YWx1ZSA9IHZhbHVlOyB9IH0KICAgICAgICAgICAgICAgIHZhciBfYm91bmRFZGl0b3JEaXZCbHVyID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2JvdW5kRWRpdG9yRGl2Rm9jdXMgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYm91bmRFZGl0b3JEaXZJbnB1dCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9ib3VuZEVkaXRvckRpdktleWRvd24gPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfY29sb3IgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfY29udGVudCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9lZGl0b3JEaXZJZCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9oYXNBbHJlYWR5QmVlbkNvbW1pdHRlZCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9mb250U2l6ZSA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF91cGRhdGVGb250U2l6ZSA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF91cGRhdGVDb2xvciA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9leHRyYWN0VGV4dCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9zZXRFZGl0b3JEaW1lbnNpb25zID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICBjbGFzcyBGcmVlVGV4dEVkaXRvciBleHRlbmRzIF9lZGl0b3IuQW5ub3RhdGlvbkVkaXRvciB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLnBhcmFtcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICJmcmVlVGV4dEVkaXRvciIKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfc2V0RWRpdG9yRGltZW5zaW9ucyk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfZXh0cmFjdFRleHQpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX3VwZGF0ZUNvbG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF91cGRhdGVGb250U2l6ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9ib3VuZEVkaXRvckRpdkJsdXIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuZWRpdG9yRGl2Qmx1ci5iaW5kKHRoaXMpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfYm91bmRFZGl0b3JEaXZGb2N1cywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5lZGl0b3JEaXZGb2N1cy5iaW5kKHRoaXMpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfYm91bmRFZGl0b3JEaXZJbnB1dCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5lZGl0b3JEaXZJbnB1dC5iaW5kKHRoaXMpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfYm91bmRFZGl0b3JEaXZLZXlkb3duLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0aGlzLmVkaXRvckRpdktleWRvd24uYmluZCh0aGlzKQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2NvbG9yLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2b2lkIDAKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9jb250ZW50LCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiAiIgogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2VkaXRvckRpdklkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBgJHt0aGlzLmlkfS1lZGl0b3JgCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfaGFzQWxyZWFkeUJlZW5Db21taXR0ZWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGZhbHNlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfZm9udFNpemUsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHZvaWQgMAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9jb2xvciwgcGFyYW1zLmNvbG9yIHx8IEZyZWVUZXh0RWRpdG9yLl9kZWZhdWx0Q29sb3IgfHwgX2VkaXRvci5Bbm5vdGF0aW9uRWRpdG9yLl9kZWZhdWx0TGluZUNvbG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9mb250U2l6ZSwgcGFyYW1zLmZvbnRTaXplIHx8IEZyZWVUZXh0RWRpdG9yLl9kZWZhdWx0Rm9udFNpemUpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgaW5pdGlhbGl6ZShsMTBuKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2wxMG5Qcm9taXNlID0gbmV3IE1hcChbImZyZWVfdGV4dDJfZGVmYXVsdF9jb250ZW50IiwgImVkaXRvcl9mcmVlX3RleHQyX2FyaWFfbGFiZWwiXS5tYXAoc3RyID0+IFtzdHIsIGwxMG4uZ2V0KHN0cildKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0eWxlID0gZ2V0Q29tcHV0ZWRTdHlsZShkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9pbnRlcm5hbFBhZGRpbmcgPSBwYXJzZUZsb2F0KHN0eWxlLmdldFByb3BlcnR5VmFsdWUoIi0tZnJlZXRleHQtcGFkZGluZyIpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIHVwZGF0ZURlZmF1bHRQYXJhbXModHlwZSwgdmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25FZGl0b3JQYXJhbXNUeXBlLkZSRUVURVhUX1NJWkU6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRnJlZVRleHRFZGl0b3IuX2RlZmF1bHRGb250U2l6ZSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZS5GUkVFVEVYVF9DT0xPUjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGcmVlVGV4dEVkaXRvci5fZGVmYXVsdENvbG9yID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdXBkYXRlUGFyYW1zKHR5cGUsIHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZS5GUkVFVEVYVF9TSVpFOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3VwZGF0ZUZvbnRTaXplLCBfdXBkYXRlRm9udFNpemUyKS5jYWxsKHRoaXMsIHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuQW5ub3RhdGlvbkVkaXRvclBhcmFtc1R5cGUuRlJFRVRFWFRfQ09MT1I6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfdXBkYXRlQ29sb3IsIF91cGRhdGVDb2xvcjIpLmNhbGwodGhpcywgdmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBnZXQgZGVmYXVsdFByb3BlcnRpZXNUb1VwZGF0ZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtbX3V0aWwuQW5ub3RhdGlvbkVkaXRvclBhcmFtc1R5cGUuRlJFRVRFWFRfU0laRSwgRnJlZVRleHRFZGl0b3IuX2RlZmF1bHRGb250U2l6ZV0sIFtfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZS5GUkVFVEVYVF9DT0xPUiwgRnJlZVRleHRFZGl0b3IuX2RlZmF1bHRDb2xvciB8fCBfZWRpdG9yLkFubm90YXRpb25FZGl0b3IuX2RlZmF1bHRMaW5lQ29sb3JdXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IHByb3BlcnRpZXNUb1VwZGF0ZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtbX3V0aWwuQW5ub3RhdGlvbkVkaXRvclBhcmFtc1R5cGUuRlJFRVRFWFRfU0laRSwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9mb250U2l6ZSldLCBbX3V0aWwuQW5ub3RhdGlvbkVkaXRvclBhcmFtc1R5cGUuRlJFRVRFWFRfQ09MT1IsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfY29sb3IpXV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldEluaXRpYWxUcmFuc2xhdGlvbigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2NhbGUgPSB0aGlzLnBhcmVudFNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWy1GcmVlVGV4dEVkaXRvci5faW50ZXJuYWxQYWRkaW5nICogc2NhbGUsIC0oRnJlZVRleHRFZGl0b3IuX2ludGVybmFsUGFkZGluZyArIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZm9udFNpemUpKSAqIHNjYWxlXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVidWlsZCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIucmVidWlsZCgpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kaXYgPT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaXNBdHRhY2hlZFRvRE9NKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcmVudC5hZGQodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZW5hYmxlRWRpdE1vZGUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzSW5FZGl0TW9kZSgpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJlbnQuc2V0RWRpdGluZ1N0YXRlKGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJlbnQudXBkYXRlVG9vbGJhcihfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yVHlwZS5GUkVFVEVYVCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyLmVuYWJsZUVkaXRNb2RlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3ZlcmxheURpdi5jbGFzc0xpc3QucmVtb3ZlKCJlbmFibGVkIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWRpdG9yRGl2LmNvbnRlbnRFZGl0YWJsZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmRyYWdnYWJsZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5yZW1vdmVBdHRyaWJ1dGUoImFyaWEtYWN0aXZlZGVzY2VuZGFudCIpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVkaXRvckRpdi5hZGRFdmVudExpc3RlbmVyKCJrZXlkb3duIiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZEVkaXRvckRpdktleWRvd24pKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3JEaXYuYWRkRXZlbnRMaXN0ZW5lcigiZm9jdXMiLCBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2JvdW5kRWRpdG9yRGl2Rm9jdXMpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3JEaXYuYWRkRXZlbnRMaXN0ZW5lcigiYmx1ciIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRFZGl0b3JEaXZCbHVyKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWRpdG9yRGl2LmFkZEV2ZW50TGlzdGVuZXIoImlucHV0IiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZEVkaXRvckRpdklucHV0KSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRpc2FibGVFZGl0TW9kZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzSW5FZGl0TW9kZSgpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJlbnQuc2V0RWRpdGluZ1N0YXRlKHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICBzdXBlci5kaXNhYmxlRWRpdE1vZGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vdmVybGF5RGl2LmNsYXNzTGlzdC5hZGQoImVuYWJsZWQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3JEaXYuY29udGVudEVkaXRhYmxlID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LnNldEF0dHJpYnV0ZSgiYXJpYS1hY3RpdmVkZXNjZW5kYW50IiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9lZGl0b3JEaXZJZCkpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5kcmFnZ2FibGUgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVkaXRvckRpdi5yZW1vdmVFdmVudExpc3RlbmVyKCJrZXlkb3duIiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZEVkaXRvckRpdktleWRvd24pKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3JEaXYucmVtb3ZlRXZlbnRMaXN0ZW5lcigiZm9jdXMiLCBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2JvdW5kRWRpdG9yRGl2Rm9jdXMpKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3JEaXYucmVtb3ZlRXZlbnRMaXN0ZW5lcigiYmx1ciIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRFZGl0b3JEaXZCbHVyKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWRpdG9yRGl2LnJlbW92ZUV2ZW50TGlzdGVuZXIoImlucHV0IiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZEVkaXRvckRpdklucHV0KSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmZvY3VzKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZlbnRTY3JvbGw6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNFZGl0aW5nID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFyZW50LmRpdi5jbGFzc0xpc3QuYWRkKCJmcmVlVGV4dEVkaXRpbmciKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZm9jdXNpbihldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBzdXBlci5mb2N1c2luKGV2ZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50LnRhcmdldCAhPT0gdGhpcy5lZGl0b3JEaXYpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWRpdG9yRGl2LmZvY3VzKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgb25jZUFkZGVkKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy53aWR0aCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlRWRpdE1vZGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3JEaXYuZm9jdXMoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaXNFbXB0eSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICF0aGlzLmVkaXRvckRpdiB8fCB0aGlzLmVkaXRvckRpdi5pbm5lclRleHQudHJpbSgpID09PSAiIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzRWRpdGluZyA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcmVudC5zZXRFZGl0aW5nU3RhdGUodHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFyZW50LmRpdi5jbGFzc0xpc3QuYWRkKCJmcmVlVGV4dEVkaXRpbmciKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIucmVtb3ZlKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbW1pdCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzSW5FZGl0TW9kZSgpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIuY29tbWl0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9oYXNBbHJlYWR5QmVlbkNvbW1pdHRlZCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfaGFzQWxyZWFkeUJlZW5Db21taXR0ZWQsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYXJlbnQuYWRkVW5kb2FibGVFZGl0b3IodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXNhYmxlRWRpdE1vZGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9jb250ZW50LCBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9leHRyYWN0VGV4dCwgX2V4dHJhY3RUZXh0MikuY2FsbCh0aGlzKS50cmltRW5kKCkpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9zZXRFZGl0b3JEaW1lbnNpb25zLCBfc2V0RWRpdG9yRGltZW5zaW9uczIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNob3VsZEdldEtleWJvYXJkRXZlbnRzKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5pc0luRWRpdE1vZGUoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZGJsY2xpY2soZXZlbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmFibGVFZGl0TW9kZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVkaXRvckRpdi5mb2N1cygpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBrZXlkb3duKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudC50YXJnZXQgPT09IHRoaXMuZGl2ICYmIGV2ZW50LmtleSA9PT0gIkVudGVyIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmFibGVFZGl0TW9kZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3JEaXYuZm9jdXMoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlZGl0b3JEaXZLZXlkb3duKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIEZyZWVUZXh0RWRpdG9yLl9rZXlib2FyZE1hbmFnZXIuZXhlYyh0aGlzLCBldmVudCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGVkaXRvckRpdkZvY3VzKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNFZGl0aW5nID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZWRpdG9yRGl2Qmx1cihldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlzRWRpdGluZyA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlZGl0b3JEaXZJbnB1dChldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcmVudC5kaXYuY2xhc3NMaXN0LnRvZ2dsZSgiZnJlZVRleHRFZGl0aW5nIiwgdGhpcy5pc0VtcHR5KCkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBkaXNhYmxlRWRpdGluZygpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3JEaXYuc2V0QXR0cmlidXRlKCJyb2xlIiwgImNvbW1lbnQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3JEaXYucmVtb3ZlQXR0cmlidXRlKCJhcmlhLW11bHRpbGluZSIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbmFibGVFZGl0aW5nKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVkaXRvckRpdi5zZXRBdHRyaWJ1dGUoInJvbGUiLCAidGV4dGJveCIpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVkaXRvckRpdi5zZXRBdHRyaWJ1dGUoImFyaWEtbXVsdGlsaW5lIiwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbmRlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGl2KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kaXY7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGJhc2VYLCBiYXNlWTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkdGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhc2VYID0gdGhpcy54OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFzZVkgPSB0aGlzLnk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIucmVuZGVyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWRpdG9yRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2Iik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWRpdG9yRGl2LmNsYXNzTmFtZSA9ICJpbnRlcm5hbCI7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZWRpdG9yRGl2LnNldEF0dHJpYnV0ZSgiaWQiLCBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2VkaXRvckRpdklkKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlRWRpdGluZygpOwogICAgICAgICAgICAgICAgICAgICAgICBGcmVlVGV4dEVkaXRvci5fbDEwblByb21pc2UuZ2V0KCJlZGl0b3JfZnJlZV90ZXh0Ml9hcmlhX2xhYmVsIikudGhlbihtc2cgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJGVkaXRvckRpdjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoX3RoaXMkZWRpdG9yRGl2ID0gdGhpcy5lZGl0b3JEaXYpID09PSBudWxsIHx8IF90aGlzJGVkaXRvckRpdiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkZWRpdG9yRGl2LnNldEF0dHJpYnV0ZSgiYXJpYS1sYWJlbCIsIG1zZyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBGcmVlVGV4dEVkaXRvci5fbDEwblByb21pc2UuZ2V0KCJmcmVlX3RleHQyX2RlZmF1bHRfY29udGVudCIpLnRoZW4obXNnID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRlZGl0b3JEaXYyOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChfdGhpcyRlZGl0b3JEaXYyID0gdGhpcy5lZGl0b3JEaXYpID09PSBudWxsIHx8IF90aGlzJGVkaXRvckRpdjIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJGVkaXRvckRpdjIuc2V0QXR0cmlidXRlKCJkZWZhdWx0LWNvbnRlbnQiLCBtc2cpOwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3JEaXYuY29udGVudEVkaXRhYmxlID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXMuZWRpdG9yRGl2OwogICAgICAgICAgICAgICAgICAgICAgICBzdHlsZS5mb250U2l6ZSA9IGBjYWxjKCR7X2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9mb250U2l6ZSl9cHggKiB2YXIoLS1zY2FsZS1mYWN0b3IpKWA7CiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlLmNvbG9yID0gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9jb2xvcik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmFwcGVuZCh0aGlzLmVkaXRvckRpdik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3ZlcmxheURpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm92ZXJsYXlEaXYuY2xhc3NMaXN0LmFkZCgib3ZlcmxheSIsICJlbmFibGVkIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmFwcGVuZCh0aGlzLm92ZXJsYXlEaXYpOwogICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3Rvb2xzLmJpbmRFdmVudHMpKHRoaXMsIHRoaXMuZGl2LCBbImRibGNsaWNrIiwgImtleWRvd24iXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLndpZHRoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbcGFyZW50V2lkdGgsIHBhcmVudEhlaWdodF0gPSB0aGlzLnBhcmVudERpbWVuc2lvbnM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEF0KGJhc2VYICogcGFyZW50V2lkdGgsIGJhc2VZICogcGFyZW50SGVpZ2h0LCB0aGlzLndpZHRoICogcGFyZW50V2lkdGgsIHRoaXMuaGVpZ2h0ICogcGFyZW50SGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgbGluZSBvZiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2NvbnRlbnQpLnNwbGl0KCJcbiIpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2Iik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGl2LmFwcGVuZChsaW5lID8gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUobGluZSkgOiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJiciIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVkaXRvckRpdi5hcHBlbmQoZGl2KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmRyYWdnYWJsZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVkaXRvckRpdi5jb250ZW50RWRpdGFibGUgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmRyYWdnYWJsZSA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3JEaXYuY29udGVudEVkaXRhYmxlID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kaXY7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBjb250ZW50RGl2KCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lZGl0b3JEaXY7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBkZXNlcmlhbGl6ZShkYXRhLCBwYXJlbnQsIHVpTWFuYWdlcikgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlZGl0b3IgPSBzdXBlci5kZXNlcmlhbGl6ZShkYXRhLCBwYXJlbnQsIHVpTWFuYWdlcik7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldChlZGl0b3IsIF9mb250U2l6ZSwgZGF0YS5mb250U2l6ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldChlZGl0b3IsIF9jb2xvciwgX3V0aWwuVXRpbC5tYWtlSGV4Q29sb3IoLi4uZGF0YS5jb2xvcikpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQoZWRpdG9yLCBfY29udGVudCwgZGF0YS52YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBlZGl0b3I7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNlcmlhbGl6ZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNFbXB0eSgpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWRkaW5nID0gRnJlZVRleHRFZGl0b3IuX2ludGVybmFsUGFkZGluZyAqIHRoaXMucGFyZW50U2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlY3QgPSB0aGlzLmdldFJlY3QocGFkZGluZywgcGFkZGluZyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbG9yID0gX2VkaXRvci5Bbm5vdGF0aW9uRWRpdG9yLl9jb2xvck1hbmFnZXIuY29udmVydCh0aGlzLmlzQXR0YWNoZWRUb0RPTSA/IGdldENvbXB1dGVkU3R5bGUodGhpcy5lZGl0b3JEaXYpLmNvbG9yIDogX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9jb2xvcikpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvblR5cGU6IF91dGlsLkFubm90YXRpb25FZGl0b3JUeXBlLkZSRUVURVhULAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250U2l6ZTogX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9mb250U2l6ZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9jb250ZW50KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VJbmRleDogdGhpcy5wYWdlSW5kZXgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb246IHRoaXMucm90YXRpb24KICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLkZyZWVUZXh0RWRpdG9yID0gRnJlZVRleHRFZGl0b3I7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfdXBkYXRlRm9udFNpemUyKGZvbnRTaXplKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2V0Rm9udHNpemUgPSBzaXplID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lZGl0b3JEaXYuc3R5bGUuZm9udFNpemUgPSBgY2FsYygke3NpemV9cHggKiB2YXIoLS1zY2FsZS1mYWN0b3IpKWA7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJhbnNsYXRlKDAsIC0oc2l6ZSAtIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZm9udFNpemUpKSAqIHRoaXMucGFyZW50U2NhbGUpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2ZvbnRTaXplLCBzaXplKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfc2V0RWRpdG9yRGltZW5zaW9ucywgX3NldEVkaXRvckRpbWVuc2lvbnMyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2F2ZWRGb250c2l6ZSA9IF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZm9udFNpemUpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkQ29tbWFuZHMoewogICAgICAgICAgICAgICAgICAgICAgICBjbWQ6ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldEZvbnRzaXplKGZvbnRTaXplKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgdW5kbzogKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0Rm9udHNpemUoc2F2ZWRGb250c2l6ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgIG11c3RFeGVjOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZS5GUkVFVEVYVF9TSVpFLAogICAgICAgICAgICAgICAgICAgICAgICBvdmVyd3JpdGVJZlNhbWVUeXBlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICBrZWVwVW5kbzogdHJ1ZQogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3VwZGF0ZUNvbG9yMihjb2xvcikgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHNhdmVkQ29sb3IgPSBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2NvbG9yKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZENvbW1hbmRzKHsKICAgICAgICAgICAgICAgICAgICAgICAgY21kOiAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2NvbG9yLCB0aGlzLmVkaXRvckRpdi5zdHlsZS5jb2xvciA9IGNvbG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgdW5kbzogKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9jb2xvciwgdGhpcy5lZGl0b3JEaXYuc3R5bGUuY29sb3IgPSBzYXZlZENvbG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgbXVzdEV4ZWM6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IF91dGlsLkFubm90YXRpb25FZGl0b3JQYXJhbXNUeXBlLkZSRUVURVhUX0NPTE9SLAogICAgICAgICAgICAgICAgICAgICAgICBvdmVyd3JpdGVJZlNhbWVUeXBlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICBrZWVwVW5kbzogdHJ1ZQogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2V4dHJhY3RUZXh0MigpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBkaXZzID0gdGhpcy5lZGl0b3JEaXYuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImRpdiIpOwogICAgICAgICAgICAgICAgICAgIGlmIChkaXZzLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lZGl0b3JEaXYuaW5uZXJUZXh0OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBidWZmZXIgPSBbXTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGRpdiBvZiBkaXZzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlci5wdXNoKGRpdi5pbm5lclRleHQucmVwbGFjZSgvXHJcbj98XG4vLCAiIikpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gYnVmZmVyLmpvaW4oIlxuIik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfc2V0RWRpdG9yRGltZW5zaW9uczIoKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgW3BhcmVudFdpZHRoLCBwYXJlbnRIZWlnaHRdID0gdGhpcy5wYXJlbnREaW1lbnNpb25zOwogICAgICAgICAgICAgICAgICAgIGxldCByZWN0OwogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzQXR0YWNoZWRUb0RPTSkgewogICAgICAgICAgICAgICAgICAgICAgICByZWN0ID0gdGhpcy5kaXYuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudExheWVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGl2CiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSB0aGlzOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzYXZlZERpc3BsYXkgPSBkaXYuc3R5bGUuZGlzcGxheTsKICAgICAgICAgICAgICAgICAgICAgICAgZGl2LnN0eWxlLmRpc3BsYXkgPSAiaGlkZGVuIjsKICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudExheWVyLmRpdi5hcHBlbmQodGhpcy5kaXYpOwogICAgICAgICAgICAgICAgICAgICAgICByZWN0ID0gZGl2LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOwogICAgICAgICAgICAgICAgICAgICAgICBkaXYucmVtb3ZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGRpdi5zdHlsZS5kaXNwbGF5ID0gc2F2ZWREaXNwbGF5OwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB0aGlzLndpZHRoID0gcmVjdC53aWR0aCAvIHBhcmVudFdpZHRoOwogICAgICAgICAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gcmVjdC5oZWlnaHQgLyBwYXJlbnRIZWlnaHQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBfZGVmaW5lUHJvcGVydHkoRnJlZVRleHRFZGl0b3IsICJfZnJlZVRleHREZWZhdWx0Q29udGVudCIsICIiKTsKICAgICAgICAgICAgICAgIF9kZWZpbmVQcm9wZXJ0eShGcmVlVGV4dEVkaXRvciwgIl9sMTBuUHJvbWlzZSIsIHZvaWQgMCk7CiAgICAgICAgICAgICAgICBfZGVmaW5lUHJvcGVydHkoRnJlZVRleHRFZGl0b3IsICJfaW50ZXJuYWxQYWRkaW5nIiwgMCk7CiAgICAgICAgICAgICAgICBfZGVmaW5lUHJvcGVydHkoRnJlZVRleHRFZGl0b3IsICJfZGVmYXVsdENvbG9yIiwgbnVsbCk7CiAgICAgICAgICAgICAgICBfZGVmaW5lUHJvcGVydHkoRnJlZVRleHRFZGl0b3IsICJfZGVmYXVsdEZvbnRTaXplIiwgMTApOwogICAgICAgICAgICAgICAgX2RlZmluZVByb3BlcnR5KEZyZWVUZXh0RWRpdG9yLCAiX2tleWJvYXJkTWFuYWdlciIsIG5ldyBfdG9vbHMuS2V5Ym9hcmRNYW5hZ2VyKFtbWyJjdHJsK0VudGVyIiwgIm1hYyttZXRhK0VudGVyIiwgIkVzY2FwZSIsICJtYWMrRXNjYXBlIl0sIEZyZWVUZXh0RWRpdG9yLnByb3RvdHlwZS5jb21taXRPclJlbW92ZV1dKSk7CiAgICAgICAgICAgICAgICBfZGVmaW5lUHJvcGVydHkoRnJlZVRleHRFZGl0b3IsICJfdHlwZSIsICJmcmVldGV4dCIpOwoKICAgICAgICAgICAgICAgIC8qKiovIH0pLAogICAgICAgICAgICAvKiAxNjQgKi8KICAgICAgICAgICAgLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCgogICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdHJ1ZQogICAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgICAgZXhwb3J0cy5JbmtFZGl0b3IgPSB2b2lkIDA7CiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgImZpdEN1cnZlIiwgKHsKICAgICAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gX3BkZmpzRml0Q3VydmUuZml0Q3VydmU7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgICAgdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygxKTsKICAgICAgICAgICAgICAgIHZhciBfZWRpdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDApOwogICAgICAgICAgICAgICAgdmFyIF9wZGZqc0ZpdEN1cnZlID0gX193X3BkZmpzX3JlcXVpcmVfXygxNjUpOwogICAgICAgICAgICAgICAgdmFyIF90b29scyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQxKTsKICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyhvYmosIHByaXZhdGVTZXQpIHsgX2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24ob2JqLCBwcml2YXRlU2V0KTsgcHJpdmF0ZVNldC5hZGQob2JqKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnR5KG9iaiwga2V5LCB2YWx1ZSkgeyBrZXkgPSBfdG9Qcm9wZXJ0eUtleShrZXkpOyBpZiAoa2V5IGluIG9iaikgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqLCBrZXksIHsgdmFsdWU6IHZhbHVlLCBlbnVtZXJhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUsIHdyaXRhYmxlOiB0cnVlIH0pOyB9IGVsc2UgeyBvYmpba2V5XSA9IHZhbHVlOyB9IHJldHVybiBvYmo7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF90b1Byb3BlcnR5S2V5KGFyZykgeyB2YXIga2V5ID0gX3RvUHJpbWl0aXZlKGFyZywgInN0cmluZyIpOyByZXR1cm4gdHlwZW9mIGtleSA9PT0gInN5bWJvbCIgPyBrZXkgOiBTdHJpbmcoa2V5KTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3RvUHJpbWl0aXZlKGlucHV0LCBoaW50KSB7IGlmICh0eXBlb2YgaW5wdXQgIT09ICJvYmplY3QiIHx8IGlucHV0ID09PSBudWxsKSByZXR1cm4gaW5wdXQ7IHZhciBwcmltID0gaW5wdXRbU3ltYm9sLnRvUHJpbWl0aXZlXTsgaWYgKHByaW0gIT09IHVuZGVmaW5lZCkgeyB2YXIgcmVzID0gcHJpbS5jYWxsKGlucHV0LCBoaW50IHx8ICJkZWZhdWx0Iik7IGlmICh0eXBlb2YgcmVzICE9PSAib2JqZWN0IikgcmV0dXJuIHJlczsgdGhyb3cgbmV3IFR5cGVFcnJvcigiQEB0b1ByaW1pdGl2ZSBtdXN0IHJldHVybiBhIHByaW1pdGl2ZSB2YWx1ZS4iKTsgfSByZXR1cm4gKGhpbnQgPT09ICJzdHJpbmciID8gU3RyaW5nIDogTnVtYmVyKShpbnB1dCk7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKG9iaiwgcHJpdmF0ZU1hcCwgdmFsdWUpIHsgX2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24ob2JqLCBwcml2YXRlTWFwKTsgcHJpdmF0ZU1hcC5zZXQob2JqLCB2YWx1ZSk7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jaGVja1ByaXZhdGVSZWRlY2xhcmF0aW9uKG9iaiwgcHJpdmF0ZUNvbGxlY3Rpb24pIHsgaWYgKHByaXZhdGVDb2xsZWN0aW9uLmhhcyhvYmopKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoIkNhbm5vdCBpbml0aWFsaXplIHRoZSBzYW1lIHByaXZhdGUgZWxlbWVudHMgdHdpY2Ugb24gYW4gb2JqZWN0Iik7IH0gfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzU3RhdGljUHJpdmF0ZU1ldGhvZEdldChyZWNlaXZlciwgY2xhc3NDb25zdHJ1Y3RvciwgbWV0aG9kKSB7IF9jbGFzc0NoZWNrUHJpdmF0ZVN0YXRpY0FjY2VzcyhyZWNlaXZlciwgY2xhc3NDb25zdHJ1Y3Rvcik7IHJldHVybiBtZXRob2Q7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc0NoZWNrUHJpdmF0ZVN0YXRpY0FjY2VzcyhyZWNlaXZlciwgY2xhc3NDb25zdHJ1Y3RvcikgeyBpZiAocmVjZWl2ZXIgIT09IGNsYXNzQ29uc3RydWN0b3IpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigiUHJpdmF0ZSBzdGF0aWMgYWNjZXNzIG9mIHdyb25nIHByb3ZlbmFuY2UiKTsgfSB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlRmllbGRTZXQocmVjZWl2ZXIsIHByaXZhdGVNYXAsIHZhbHVlKSB7IHZhciBkZXNjcmlwdG9yID0gX2NsYXNzRXh0cmFjdEZpZWxkRGVzY3JpcHRvcihyZWNlaXZlciwgcHJpdmF0ZU1hcCwgInNldCIpOyBfY2xhc3NBcHBseURlc2NyaXB0b3JTZXQocmVjZWl2ZXIsIGRlc2NyaXB0b3IsIHZhbHVlKTsgcmV0dXJuIHZhbHVlOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NBcHBseURlc2NyaXB0b3JTZXQocmVjZWl2ZXIsIGRlc2NyaXB0b3IsIHZhbHVlKSB7IGlmIChkZXNjcmlwdG9yLnNldCkgeyBkZXNjcmlwdG9yLnNldC5jYWxsKHJlY2VpdmVyLCB2YWx1ZSk7IH0gZWxzZSB7IGlmICghZGVzY3JpcHRvci53cml0YWJsZSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJhdHRlbXB0ZWQgdG8gc2V0IHJlYWQgb25seSBwcml2YXRlIGZpZWxkIik7IH0gZGVzY3JpcHRvci52YWx1ZSA9IHZhbHVlOyB9IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVGaWVsZEdldChyZWNlaXZlciwgcHJpdmF0ZU1hcCkgeyB2YXIgZGVzY3JpcHRvciA9IF9jbGFzc0V4dHJhY3RGaWVsZERlc2NyaXB0b3IocmVjZWl2ZXIsIHByaXZhdGVNYXAsICJnZXQiKTsgcmV0dXJuIF9jbGFzc0FwcGx5RGVzY3JpcHRvckdldChyZWNlaXZlciwgZGVzY3JpcHRvcik7IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc0V4dHJhY3RGaWVsZERlc2NyaXB0b3IocmVjZWl2ZXIsIHByaXZhdGVNYXAsIGFjdGlvbikgeyBpZiAoIXByaXZhdGVNYXAuaGFzKHJlY2VpdmVyKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJhdHRlbXB0ZWQgdG8gIiArIGFjdGlvbiArICIgcHJpdmF0ZSBmaWVsZCBvbiBub24taW5zdGFuY2UiKTsgfSByZXR1cm4gcHJpdmF0ZU1hcC5nZXQocmVjZWl2ZXIpOyB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NBcHBseURlc2NyaXB0b3JHZXQocmVjZWl2ZXIsIGRlc2NyaXB0b3IpIHsgaWYgKGRlc2NyaXB0b3IuZ2V0KSB7IHJldHVybiBkZXNjcmlwdG9yLmdldC5jYWxsKHJlY2VpdmVyKTsgfSByZXR1cm4gZGVzY3JpcHRvci52YWx1ZTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzUHJpdmF0ZU1ldGhvZEdldChyZWNlaXZlciwgcHJpdmF0ZVNldCwgZm4pIHsgaWYgKCFwcml2YXRlU2V0LmhhcyhyZWNlaXZlcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigiYXR0ZW1wdGVkIHRvIGdldCBwcml2YXRlIGZpZWxkIG9uIG5vbi1pbnN0YW5jZSIpOyB9IHJldHVybiBmbjsgfQogICAgICAgICAgICAgICAgY29uc3QgUkVTSVpFUl9TSVpFID0gMTY7CiAgICAgICAgICAgICAgICB2YXIgX2FzcGVjdFJhdGlvID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2Jhc2VIZWlnaHQgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYmFzZVdpZHRoID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2JvdW5kQ2FudmFzUG9pbnRlcm1vdmUgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYm91bmRDYW52YXNQb2ludGVybGVhdmUgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYm91bmRDYW52YXNQb2ludGVydXAgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfYm91bmRDYW52YXNQb2ludGVyZG93biA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9kaXNhYmxlRWRpdGluZyA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9pc0NhbnZhc0luaXRpYWxpemVkID0gLyojX19QVVJFX18qL25ldyBXZWFrTWFwKCk7CiAgICAgICAgICAgICAgICB2YXIgX2xhc3RQb2ludCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9vYnNlcnZlciA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9yZWFsV2lkdGggPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtNYXAoKTsKICAgICAgICAgICAgICAgIHZhciBfcmVhbEhlaWdodCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF9yZXF1ZXN0RnJhbWVDYWxsYmFjayA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha01hcCgpOwogICAgICAgICAgICAgICAgdmFyIF91cGRhdGVUaGlja25lc3MgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIHZhciBfdXBkYXRlQ29sb3IgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIHZhciBfdXBkYXRlT3BhY2l0eSA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9nZXRJbml0aWFsQkJveCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9zZXRTdHJva2UgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIHZhciBfc3RhcnREcmF3aW5nID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICB2YXIgX2RyYXcgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIHZhciBfc3RvcERyYXdpbmcgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIHZhciBfcmVkcmF3ID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICB2YXIgX2VuZERyYXdpbmcgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIHZhciBfY3JlYXRlQ2FudmFzID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICB2YXIgX2NyZWF0ZU9ic2VydmVyID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICB2YXIgX3NldENhbnZhc0RpbXMgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIHZhciBfc2V0U2NhbGVGYWN0b3IgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIHZhciBfdXBkYXRlVHJhbnNmb3JtID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICB2YXIgX3NlcmlhbGl6ZVBhdGhzID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICB2YXIgX2V4dHJhY3RQb2ludHNPbkJlemllciA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9pc0FsbW9zdEZsYXQgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIHZhciBfZ2V0QmJveCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9nZXRQYWRkaW5nID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICB2YXIgX2ZpdFRvQ29udGVudCA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9zZXRNaW5EaW1zID0gLyojX19QVVJFX18qL25ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICBjbGFzcyBJbmtFZGl0b3IgZXh0ZW5kcyBfZWRpdG9yLkFubm90YXRpb25FZGl0b3IgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgICAgICAgICAgICAgICAgICAgICBzdXBlcih7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5wYXJhbXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAiaW5rRWRpdG9yIgogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF9zZXRNaW5EaW1zKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF9maXRUb0NvbnRlbnQpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2dldFBhZGRpbmcpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2dldEJib3gpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2lzQWxtb3N0RmxhdCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfZXh0cmFjdFBvaW50c09uQmV6aWVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF9zZXJpYWxpemVQYXRocyk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfdXBkYXRlVHJhbnNmb3JtKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF9zZXRTY2FsZUZhY3Rvcik7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfc2V0Q2FudmFzRGltcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfY3JlYXRlT2JzZXJ2ZXIpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2NyZWF0ZUNhbnZhcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfZW5kRHJhd2luZyk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfcmVkcmF3KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF9zdG9wRHJhd2luZyk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfZHJhdyk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfc3RhcnREcmF3aW5nKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF9zZXRTdHJva2UpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2dldEluaXRpYWxCQm94KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF91cGRhdGVPcGFjaXR5KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEluaXRTcGVjKHRoaXMsIF91cGRhdGVDb2xvcik7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfdXBkYXRlVGhpY2tuZXNzKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2FzcGVjdFJhdGlvLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiAwCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfYmFzZUhlaWdodCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogMAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2Jhc2VXaWR0aCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogMAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2JvdW5kQ2FudmFzUG9pbnRlcm1vdmUsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuY2FudmFzUG9pbnRlcm1vdmUuYmluZCh0aGlzKQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2JvdW5kQ2FudmFzUG9pbnRlcmxlYXZlLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0aGlzLmNhbnZhc1BvaW50ZXJsZWF2ZS5iaW5kKHRoaXMpCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfYm91bmRDYW52YXNQb2ludGVydXAsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuY2FudmFzUG9pbnRlcnVwLmJpbmQodGhpcykKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9ib3VuZENhbnZhc1BvaW50ZXJkb3duLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0aGlzLmNhbnZhc1BvaW50ZXJkb3duLmJpbmQodGhpcykKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9kaXNhYmxlRWRpdGluZywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEluaXRTcGVjKHRoaXMsIF9pc0NhbnZhc0luaXRpYWxpemVkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX2xhc3RQb2ludCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogbnVsbAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX29ic2VydmVyLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBudWxsCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfcmVhbFdpZHRoLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiAwCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRJbml0U3BlYyh0aGlzLCBfcmVhbEhlaWdodCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogMAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkSW5pdFNwZWModGhpcywgX3JlcXVlc3RGcmFtZUNhbGxiYWNrLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBudWxsCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbG9yID0gcGFyYW1zLmNvbG9yIHx8IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGhpY2tuZXNzID0gcGFyYW1zLnRoaWNrbmVzcyB8fCBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9wYWNpdHkgPSBwYXJhbXMub3BhY2l0eSB8fCBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhdGhzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmV6aWVyUGF0aDJEID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFBhdGggPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zY2FsZUZhY3RvciA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJhbnNsYXRpb25YID0gdGhpcy50cmFuc2xhdGlvblkgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnggPSAwOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnkgPSAwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgaW5pdGlhbGl6ZShsMTBuKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2wxMG5Qcm9taXNlID0gbmV3IE1hcChbImVkaXRvcl9pbmtfY2FudmFzX2FyaWFfbGFiZWwiLCAiZWRpdG9yX2luazJfYXJpYV9sYWJlbCJdLm1hcChzdHIgPT4gW3N0ciwgbDEwbi5nZXQoc3RyKV0pKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIHVwZGF0ZURlZmF1bHRQYXJhbXModHlwZSwgdmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25FZGl0b3JQYXJhbXNUeXBlLklOS19USElDS05FU1M6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5rRWRpdG9yLl9kZWZhdWx0VGhpY2tuZXNzID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25FZGl0b3JQYXJhbXNUeXBlLklOS19DT0xPUjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJbmtFZGl0b3IuX2RlZmF1bHRDb2xvciA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZS5JTktfT1BBQ0lUWToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJbmtFZGl0b3IuX2RlZmF1bHRPcGFjaXR5ID0gdmFsdWUgLyAxMDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdXBkYXRlUGFyYW1zKHR5cGUsIHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZS5JTktfVEhJQ0tORVNTOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3VwZGF0ZVRoaWNrbmVzcywgX3VwZGF0ZVRoaWNrbmVzczIpLmNhbGwodGhpcywgdmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZS5JTktfQ09MT1I6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfdXBkYXRlQ29sb3IsIF91cGRhdGVDb2xvcjIpLmNhbGwodGhpcywgdmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZS5JTktfT1BBQ0lUWToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF91cGRhdGVPcGFjaXR5LCBfdXBkYXRlT3BhY2l0eTIpLmNhbGwodGhpcywgdmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBnZXQgZGVmYXVsdFByb3BlcnRpZXNUb1VwZGF0ZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtbX3V0aWwuQW5ub3RhdGlvbkVkaXRvclBhcmFtc1R5cGUuSU5LX1RISUNLTkVTUywgSW5rRWRpdG9yLl9kZWZhdWx0VGhpY2tuZXNzXSwgW191dGlsLkFubm90YXRpb25FZGl0b3JQYXJhbXNUeXBlLklOS19DT0xPUiwgSW5rRWRpdG9yLl9kZWZhdWx0Q29sb3IgfHwgX2VkaXRvci5Bbm5vdGF0aW9uRWRpdG9yLl9kZWZhdWx0TGluZUNvbG9yXSwgW191dGlsLkFubm90YXRpb25FZGl0b3JQYXJhbXNUeXBlLklOS19PUEFDSVRZLCBNYXRoLnJvdW5kKElua0VkaXRvci5fZGVmYXVsdE9wYWNpdHkgKiAxMDApXV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGdldCBwcm9wZXJ0aWVzVG9VcGRhdGUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbW191dGlsLkFubm90YXRpb25FZGl0b3JQYXJhbXNUeXBlLklOS19USElDS05FU1MsIHRoaXMudGhpY2tuZXNzIHx8IElua0VkaXRvci5fZGVmYXVsdFRoaWNrbmVzc10sIFtfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZS5JTktfQ09MT1IsIHRoaXMuY29sb3IgfHwgSW5rRWRpdG9yLl9kZWZhdWx0Q29sb3IgfHwgX2VkaXRvci5Bbm5vdGF0aW9uRWRpdG9yLl9kZWZhdWx0TGluZUNvbG9yXSwgW191dGlsLkFubm90YXRpb25FZGl0b3JQYXJhbXNUeXBlLklOS19PUEFDSVRZLCBNYXRoLnJvdW5kKDEwMCAqICh0aGlzLm9wYWNpdHkgPz8gSW5rRWRpdG9yLl9kZWZhdWx0T3BhY2l0eSkpXV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlYnVpbGQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyLnJlYnVpbGQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGl2ID09PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNhbnZhcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfY3JlYXRlQ2FudmFzLCBfY3JlYXRlQ2FudmFzMikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2NyZWF0ZU9ic2VydmVyLCBfY3JlYXRlT2JzZXJ2ZXIyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5pc0F0dGFjaGVkVG9ET00pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFyZW50LmFkZCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3NldENhbnZhc0RpbXMsIF9zZXRDYW52YXNEaW1zMikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9maXRUb0NvbnRlbnQsIF9maXRUb0NvbnRlbnQyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZW1vdmUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmNhbnZhcyA9PT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tbWl0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYW52YXMud2lkdGggPSB0aGlzLmNhbnZhcy5oZWlnaHQgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbnZhcy5yZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYW52YXMgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX29ic2VydmVyKS5kaXNjb25uZWN0KCk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfb2JzZXJ2ZXIsIG51bGwpOwogICAgICAgICAgICAgICAgICAgICAgICBzdXBlci5yZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0UGFyZW50KHBhcmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMucGFyZW50ICYmIHBhcmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdWlNYW5hZ2VyLnJlbW92ZVNob3VsZFJlc2NhbGUodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5wYXJlbnQgJiYgcGFyZW50ID09PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl91aU1hbmFnZXIuYWRkU2hvdWxkUmVzY2FsZSh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBzdXBlci5zZXRQYXJlbnQocGFyZW50KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgb25TY2FsZUNoYW5naW5nKCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbcGFyZW50V2lkdGgsIHBhcmVudEhlaWdodF0gPSB0aGlzLnBhcmVudERpbWVuc2lvbnM7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy53aWR0aCAqIHBhcmVudFdpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHQgPSB0aGlzLmhlaWdodCAqIHBhcmVudEhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXREaW1lbnNpb25zKHdpZHRoLCBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBlbmFibGVFZGl0TW9kZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZGlzYWJsZUVkaXRpbmcpIHx8IHRoaXMuY2FudmFzID09PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIuZW5hYmxlRWRpdE1vZGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYuZHJhZ2dhYmxlID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoInBvaW50ZXJkb3duIiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZENhbnZhc1BvaW50ZXJkb3duKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoInBvaW50ZXJ1cCIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRDYW52YXNQb2ludGVydXApKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZGlzYWJsZUVkaXRNb2RlKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaXNJbkVkaXRNb2RlKCkgfHwgdGhpcy5jYW52YXMgPT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBzdXBlci5kaXNhYmxlRWRpdE1vZGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYuZHJhZ2dhYmxlID0gIXRoaXMuaXNFbXB0eSgpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5jbGFzc0xpc3QucmVtb3ZlKCJlZGl0aW5nIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FudmFzLnJlbW92ZUV2ZW50TGlzdGVuZXIoInBvaW50ZXJkb3duIiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZENhbnZhc1BvaW50ZXJkb3duKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FudmFzLnJlbW92ZUV2ZW50TGlzdGVuZXIoInBvaW50ZXJ1cCIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRDYW52YXNQb2ludGVydXApKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgb25jZUFkZGVkKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5kcmFnZ2FibGUgPSAhdGhpcy5pc0VtcHR5KCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlzRW1wdHkoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBhdGhzLmxlbmd0aCA9PT0gMCB8fCB0aGlzLnBhdGhzLmxlbmd0aCA9PT0gMSAmJiB0aGlzLnBhdGhzWzBdLmxlbmd0aCA9PT0gMDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY29tbWl0KCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9kaXNhYmxlRWRpdGluZykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBzdXBlci5jb21taXQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc0VkaXRpbmcgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXNhYmxlRWRpdE1vZGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRJbkZvcmVncm91bmQoKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9kaXNhYmxlRWRpdGluZywgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmNsYXNzTGlzdC5hZGQoImRpc2FibGVkIik7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2ZpdFRvQ29udGVudCwgX2ZpdFRvQ29udGVudDIpLmNhbGwodGhpcywgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFyZW50LmFkZElua0VkaXRvcklmTmVlZGVkKHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcmVudC5tb3ZlRWRpdG9ySW5ET00odGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmZvY3VzKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZlbnRTY3JvbGw6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGZvY3VzaW4oZXZlbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIuZm9jdXNpbihldmVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlRWRpdE1vZGUoKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FudmFzUG9pbnRlcmRvd24oZXZlbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50LmJ1dHRvbiAhPT0gMCB8fCAhdGhpcy5pc0luRWRpdE1vZGUoKSB8fCBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2Rpc2FibGVFZGl0aW5nKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0SW5Gb3JlZ3JvdW5kKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudC50eXBlICE9PSAibW91c2UiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5mb2N1cygpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbnZhcy5hZGRFdmVudExpc3RlbmVyKCJwb2ludGVybGVhdmUiLCBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2JvdW5kQ2FudmFzUG9pbnRlcmxlYXZlKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FudmFzLmFkZEV2ZW50TGlzdGVuZXIoInBvaW50ZXJtb3ZlIiwgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9ib3VuZENhbnZhc1BvaW50ZXJtb3ZlKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3N0YXJ0RHJhd2luZywgX3N0YXJ0RHJhd2luZzIpLmNhbGwodGhpcywgZXZlbnQub2Zmc2V0WCwgZXZlbnQub2Zmc2V0WSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNhbnZhc1BvaW50ZXJtb3ZlKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9kcmF3LCBfZHJhdzIpLmNhbGwodGhpcywgZXZlbnQub2Zmc2V0WCwgZXZlbnQub2Zmc2V0WSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNhbnZhc1BvaW50ZXJ1cChldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXZlbnQuYnV0dG9uICE9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNJbkVkaXRNb2RlKCkgJiYgdGhpcy5jdXJyZW50UGF0aC5sZW5ndGggIT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfZW5kRHJhd2luZywgX2VuZERyYXdpbmcyKS5jYWxsKHRoaXMsIGV2ZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0SW5CYWNrZ3JvdW5kKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY2FudmFzUG9pbnRlcmxlYXZlKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2VuZERyYXdpbmcsIF9lbmREcmF3aW5nMikuY2FsbCh0aGlzLCBldmVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0SW5CYWNrZ3JvdW5kKCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbmRlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGl2KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kaXY7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGJhc2VYLCBiYXNlWTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMud2lkdGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhc2VYID0gdGhpcy54OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFzZVkgPSB0aGlzLnk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIucmVuZGVyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIElua0VkaXRvci5fbDEwblByb21pc2UuZ2V0KCJlZGl0b3JfaW5rMl9hcmlhX2xhYmVsIikudGhlbihtc2cgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJGRpdjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoX3RoaXMkZGl2ID0gdGhpcy5kaXYpID09PSBudWxsIHx8IF90aGlzJGRpdiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkZGl2LnNldEF0dHJpYnV0ZSgiYXJpYS1sYWJlbCIsIG1zZyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbeCwgeSwgdywgaF0gPSBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9nZXRJbml0aWFsQkJveCwgX2dldEluaXRpYWxCQm94MikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRBdCh4LCB5LCAwLCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXREaW1zKHcsIGgpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9jcmVhdGVDYW52YXMsIF9jcmVhdGVDYW52YXMyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy53aWR0aCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW3BhcmVudFdpZHRoLCBwYXJlbnRIZWlnaHRdID0gdGhpcy5wYXJlbnREaW1lbnNpb25zOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRBdChiYXNlWCAqIHBhcmVudFdpZHRoLCBiYXNlWSAqIHBhcmVudEhlaWdodCwgdGhpcy53aWR0aCAqIHBhcmVudFdpZHRoLCB0aGlzLmhlaWdodCAqIHBhcmVudEhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2lzQ2FudmFzSW5pdGlhbGl6ZWQsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfc2V0Q2FudmFzRGltcywgX3NldENhbnZhc0RpbXMyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXREaW1zKHRoaXMud2lkdGggKiBwYXJlbnRXaWR0aCwgdGhpcy5oZWlnaHQgKiBwYXJlbnRIZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfcmVkcmF3LCBfcmVkcmF3MikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3NldE1pbkRpbXMsIF9zZXRNaW5EaW1zMikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGl2LmNsYXNzTGlzdC5hZGQoImRpc2FibGVkIik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpdi5jbGFzc0xpc3QuYWRkKCJlZGl0aW5nIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVuYWJsZUVkaXRNb2RlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfY3JlYXRlT2JzZXJ2ZXIsIF9jcmVhdGVPYnNlcnZlcjIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRpdjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0RGltZW5zaW9ucyh3aWR0aCwgaGVpZ2h0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJvdW5kZWRXaWR0aCA9IE1hdGgucm91bmQod2lkdGgpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByb3VuZGVkSGVpZ2h0ID0gTWF0aC5yb3VuZChoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9yZWFsV2lkdGgpID09PSByb3VuZGVkV2lkdGggJiYgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9yZWFsSGVpZ2h0KSA9PT0gcm91bmRlZEhlaWdodCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfcmVhbFdpZHRoLCByb3VuZGVkV2lkdGgpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX3JlYWxIZWlnaHQsIHJvdW5kZWRIZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbnZhcy5zdHlsZS52aXNpYmlsaXR5ID0gImhpZGRlbiI7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FzcGVjdFJhdGlvKSAmJiBNYXRoLmFicyhfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2FzcGVjdFJhdGlvKSAtIHdpZHRoIC8gaGVpZ2h0KSA+IDFlLTIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodCA9IE1hdGguY2VpbCh3aWR0aCAvIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYXNwZWN0UmF0aW8pKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0RGltcyh3aWR0aCwgaGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbcGFyZW50V2lkdGgsIHBhcmVudEhlaWdodF0gPSB0aGlzLnBhcmVudERpbWVuc2lvbnM7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMud2lkdGggPSB3aWR0aCAvIHBhcmVudFdpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhlaWdodCA9IGhlaWdodCAvIHBhcmVudEhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfZGlzYWJsZUVkaXRpbmcpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9zZXRTY2FsZUZhY3RvciwgX3NldFNjYWxlRmFjdG9yMikuY2FsbCh0aGlzLCB3aWR0aCwgaGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9zZXRDYW52YXNEaW1zLCBfc2V0Q2FudmFzRGltczIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3JlZHJhdywgX3JlZHJhdzIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FudmFzLnN0eWxlLnZpc2liaWxpdHkgPSAidmlzaWJsZSI7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZml4RGltcygpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgZGVzZXJpYWxpemUoZGF0YSwgcGFyZW50LCB1aU1hbmFnZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZWRpdG9yID0gc3VwZXIuZGVzZXJpYWxpemUoZGF0YSwgcGFyZW50LCB1aU1hbmFnZXIpOwogICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3IudGhpY2tuZXNzID0gZGF0YS50aGlja25lc3M7CiAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5jb2xvciA9IF91dGlsLlV0aWwubWFrZUhleENvbG9yKC4uLmRhdGEuY29sb3IpOwogICAgICAgICAgICAgICAgICAgICAgICBlZGl0b3Iub3BhY2l0eSA9IGRhdGEub3BhY2l0eTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW3BhZ2VXaWR0aCwgcGFnZUhlaWdodF0gPSBlZGl0b3IucGFnZURpbWVuc2lvbnM7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gZWRpdG9yLndpZHRoICogcGFnZVdpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBlZGl0b3IuaGVpZ2h0ICogcGFnZUhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2NhbGVGYWN0b3IgPSBlZGl0b3IucGFyZW50U2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhZGRpbmcgPSBkYXRhLnRoaWNrbmVzcyAvIDI7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldChlZGl0b3IsIF9hc3BlY3RSYXRpbywgd2lkdGggLyBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQoZWRpdG9yLCBfZGlzYWJsZUVkaXRpbmcsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQoZWRpdG9yLCBfcmVhbFdpZHRoLCBNYXRoLnJvdW5kKHdpZHRoKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldChlZGl0b3IsIF9yZWFsSGVpZ2h0LCBNYXRoLnJvdW5kKGhlaWdodCkpOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlemllcgogICAgICAgICAgICAgICAgICAgICAgICB9IG9mIGRhdGEucGF0aHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhdGggPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkaXRvci5wYXRocy5wdXNoKHBhdGgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHAwID0gc2NhbGVGYWN0b3IgKiAoYmV6aWVyWzBdIC0gcGFkZGluZyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgcDEgPSBzY2FsZUZhY3RvciAqIChoZWlnaHQgLSBiZXppZXJbMV0gLSBwYWRkaW5nKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAyLCBpaSA9IGJlemllci5sZW5ndGg7IGkgPCBpaTsgaSArPSA2KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcDEwID0gc2NhbGVGYWN0b3IgKiAoYmV6aWVyW2ldIC0gcGFkZGluZyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcDExID0gc2NhbGVGYWN0b3IgKiAoaGVpZ2h0IC0gYmV6aWVyW2kgKyAxXSAtIHBhZGRpbmcpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHAyMCA9IHNjYWxlRmFjdG9yICogKGJlemllcltpICsgMl0gLSBwYWRkaW5nKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwMjEgPSBzY2FsZUZhY3RvciAqIChoZWlnaHQgLSBiZXppZXJbaSArIDNdIC0gcGFkZGluZyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcDMwID0gc2NhbGVGYWN0b3IgKiAoYmV6aWVyW2kgKyA0XSAtIHBhZGRpbmcpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHAzMSA9IHNjYWxlRmFjdG9yICogKGhlaWdodCAtIGJlemllcltpICsgNV0gLSBwYWRkaW5nKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRoLnB1c2goW1twMCwgcDFdLCBbcDEwLCBwMTFdLCBbcDIwLCBwMjFdLCBbcDMwLCBwMzFdXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcDAgPSBwMzA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcDEgPSBwMzE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXRoMkQgPSBfY2xhc3NTdGF0aWNQcml2YXRlTWV0aG9kR2V0KHRoaXMsIElua0VkaXRvciwgX2J1aWxkUGF0aDJEKS5jYWxsKHRoaXMsIHBhdGgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWRpdG9yLmJlemllclBhdGgyRC5wdXNoKHBhdGgyRCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmJveCA9IF9jbGFzc1ByaXZhdGVNZXRob2RHZXQoZWRpdG9yLCBfZ2V0QmJveCwgX2dldEJib3gyKS5jYWxsKGVkaXRvcik7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldChlZGl0b3IsIF9iYXNlV2lkdGgsIE1hdGgubWF4KFJFU0laRVJfU0laRSwgYmJveFsyXSAtIGJib3hbMF0pKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KGVkaXRvciwgX2Jhc2VIZWlnaHQsIE1hdGgubWF4KFJFU0laRVJfU0laRSwgYmJveFszXSAtIGJib3hbMV0pKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldChlZGl0b3IsIF9zZXRTY2FsZUZhY3RvciwgX3NldFNjYWxlRmFjdG9yMikuY2FsbChlZGl0b3IsIHdpZHRoLCBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZWRpdG9yOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzZXJpYWxpemUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVjdCA9IHRoaXMuZ2V0UmVjdCgwLCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5yb3RhdGlvbiAlIDE4MCA9PT0gMCA/IHJlY3RbM10gLSByZWN0WzFdIDogcmVjdFsyXSAtIHJlY3RbMF07CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbG9yID0gX2VkaXRvci5Bbm5vdGF0aW9uRWRpdG9yLl9jb2xvck1hbmFnZXIuY29udmVydCh0aGlzLmN0eC5zdHJva2VTdHlsZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uVHlwZTogX3V0aWwuQW5ub3RhdGlvbkVkaXRvclR5cGUuSU5LLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlja25lc3M6IHRoaXMudGhpY2tuZXNzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogdGhpcy5vcGFjaXR5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0aHM6IF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3NlcmlhbGl6ZVBhdGhzLCBfc2VyaWFsaXplUGF0aHMyKS5jYWxsKHRoaXMsIHRoaXMuc2NhbGVGYWN0b3IgLyB0aGlzLnBhcmVudFNjYWxlLCB0aGlzLnRyYW5zbGF0aW9uWCwgdGhpcy50cmFuc2xhdGlvblksIGhlaWdodCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlSW5kZXg6IHRoaXMucGFnZUluZGV4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0aW9uOiB0aGlzLnJvdGF0aW9uCiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZXhwb3J0cy5JbmtFZGl0b3IgPSBJbmtFZGl0b3I7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfdXBkYXRlVGhpY2tuZXNzMih0aGlja25lc3MpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBzYXZlZFRoaWNrbmVzcyA9IHRoaXMudGhpY2tuZXNzOwogICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkQ29tbWFuZHMoewogICAgICAgICAgICAgICAgICAgICAgICBjbWQ6ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGhpY2tuZXNzID0gdGhpY2tuZXNzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfZml0VG9Db250ZW50LCBfZml0VG9Db250ZW50MikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgdW5kbzogKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50aGlja25lc3MgPSBzYXZlZFRoaWNrbmVzczsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2ZpdFRvQ29udGVudCwgX2ZpdFRvQ29udGVudDIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgIG11c3RFeGVjOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZS5JTktfVEhJQ0tORVNTLAogICAgICAgICAgICAgICAgICAgICAgICBvdmVyd3JpdGVJZlNhbWVUeXBlOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICBrZWVwVW5kbzogdHJ1ZQogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3VwZGF0ZUNvbG9yMihjb2xvcikgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHNhdmVkQ29sb3IgPSB0aGlzLmNvbG9yOwogICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkQ29tbWFuZHMoewogICAgICAgICAgICAgICAgICAgICAgICBjbWQ6ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29sb3IgPSBjb2xvcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3JlZHJhdywgX3JlZHJhdzIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgIHVuZG86ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29sb3IgPSBzYXZlZENvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfcmVkcmF3LCBfcmVkcmF3MikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgbXVzdEV4ZWM6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IF91dGlsLkFubm90YXRpb25FZGl0b3JQYXJhbXNUeXBlLklOS19DT0xPUiwKICAgICAgICAgICAgICAgICAgICAgICAgb3ZlcndyaXRlSWZTYW1lVHlwZTogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAga2VlcFVuZG86IHRydWUKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF91cGRhdGVPcGFjaXR5MihvcGFjaXR5KSB7CiAgICAgICAgICAgICAgICAgICAgb3BhY2l0eSAvPSAxMDA7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2F2ZWRPcGFjaXR5ID0gdGhpcy5vcGFjaXR5OwogICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkQ29tbWFuZHMoewogICAgICAgICAgICAgICAgICAgICAgICBjbWQ6ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3BhY2l0eSA9IG9wYWNpdHk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9yZWRyYXcsIF9yZWRyYXcyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICB1bmRvOiAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9wYWNpdHkgPSBzYXZlZE9wYWNpdHk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9yZWRyYXcsIF9yZWRyYXcyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICBtdXN0RXhlYzogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogX3V0aWwuQW5ub3RhdGlvbkVkaXRvclBhcmFtc1R5cGUuSU5LX09QQUNJVFksCiAgICAgICAgICAgICAgICAgICAgICAgIG92ZXJ3cml0ZUlmU2FtZVR5cGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgIGtlZXBVbmRvOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfZ2V0SW5pdGlhbEJCb3gyKCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Um90YXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudERpbWVuc2lvbnM6IFt3aWR0aCwgaGVpZ2h0XQogICAgICAgICAgICAgICAgICAgIH0gPSB0aGlzOwogICAgICAgICAgICAgICAgICAgIHN3aXRjaCAocGFyZW50Um90YXRpb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSA5MDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMCwgaGVpZ2h0LCBoZWlnaHQsIHdpZHRoXTsKICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAxODA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW3dpZHRoLCBoZWlnaHQsIHdpZHRoLCBoZWlnaHRdOwogICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDI3MDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbd2lkdGgsIDAsIGhlaWdodCwgd2lkdGhdOwogICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFswLCAwLCB3aWR0aCwgaGVpZ2h0XTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfc2V0U3Ryb2tlMigpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgIGN0eCwKICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IsCiAgICAgICAgICAgICAgICAgICAgICAgIG9wYWNpdHksCiAgICAgICAgICAgICAgICAgICAgICAgIHRoaWNrbmVzcywKICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50U2NhbGUsCiAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlRmFjdG9yCiAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXM7CiAgICAgICAgICAgICAgICAgICAgY3R4LmxpbmVXaWR0aCA9IHRoaWNrbmVzcyAqIHBhcmVudFNjYWxlIC8gc2NhbGVGYWN0b3I7CiAgICAgICAgICAgICAgICAgICAgY3R4LmxpbmVDYXAgPSAicm91bmQiOwogICAgICAgICAgICAgICAgICAgIGN0eC5saW5lSm9pbiA9ICJyb3VuZCI7CiAgICAgICAgICAgICAgICAgICAgY3R4Lm1pdGVyTGltaXQgPSAxMDsKICAgICAgICAgICAgICAgICAgICBjdHguc3Ryb2tlU3R5bGUgPSBgJHtjb2xvcn0keygwLCBfdG9vbHMub3BhY2l0eVRvSGV4KShvcGFjaXR5KX1gOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3N0YXJ0RHJhd2luZzIoeCwgeSkgewogICAgICAgICAgICAgICAgICAgIHRoaXMuaXNFZGl0aW5nID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICBpZiAoIV9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfaXNDYW52YXNJbml0aWFsaXplZCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9pc0NhbnZhc0luaXRpYWxpemVkLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfc2V0Q2FudmFzRGltcywgX3NldENhbnZhc0RpbXMyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRoaWNrbmVzcyB8fD0gSW5rRWRpdG9yLl9kZWZhdWx0VGhpY2tuZXNzOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbG9yIHx8PSBJbmtFZGl0b3IuX2RlZmF1bHRDb2xvciB8fCBfZWRpdG9yLkFubm90YXRpb25FZGl0b3IuX2RlZmF1bHRMaW5lQ29sb3I7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3BhY2l0eSA/Pz0gSW5rRWRpdG9yLl9kZWZhdWx0T3BhY2l0eTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50UGF0aC5wdXNoKFt4LCB5XSk7CiAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9sYXN0UG9pbnQsIG51bGwpOwogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3NldFN0cm9rZSwgX3NldFN0cm9rZTIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguYmVnaW5QYXRoKCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHgubW92ZVRvKHgsIHkpOwogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfcmVxdWVzdEZyYW1lQ2FsbGJhY2ssICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX3JlcXVlc3RGcmFtZUNhbGxiYWNrKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2xhc3RQb2ludCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnNldFRyYW5zZm9ybSgxLCAwLCAwLCAxLCAwLCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5jbGVhclJlY3QoMCwgMCwgdGhpcy5jYW52YXMud2lkdGgsIHRoaXMuY2FudmFzLmhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3JlZHJhdywgX3JlZHJhdzIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eC5saW5lVG8oLi4uX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9sYXN0UG9pbnQpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfbGFzdFBvaW50LCBudWxsKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3R4LnN0cm9rZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9yZXF1ZXN0RnJhbWVDYWxsYmFjaykpOwogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9yZXF1ZXN0RnJhbWVDYWxsYmFjaykpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2RyYXcyKHgsIHkpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBbbGFzdFgsIGxhc3RZXSA9IHRoaXMuY3VycmVudFBhdGguYXQoLTEpOwogICAgICAgICAgICAgICAgICAgIGlmICh4ID09PSBsYXN0WCAmJiB5ID09PSBsYXN0WSkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFBhdGgucHVzaChbeCwgeV0pOwogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfbGFzdFBvaW50LCBbeCwgeV0pOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3N0b3BEcmF3aW5nMih4LCB5KSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguY2xvc2VQYXRoKCk7CiAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9yZXF1ZXN0RnJhbWVDYWxsYmFjaywgbnVsbCk7CiAgICAgICAgICAgICAgICAgICAgeCA9IE1hdGgubWluKE1hdGgubWF4KHgsIDApLCB0aGlzLmNhbnZhcy53aWR0aCk7CiAgICAgICAgICAgICAgICAgICAgeSA9IE1hdGgubWluKE1hdGgubWF4KHksIDApLCB0aGlzLmNhbnZhcy5oZWlnaHQpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IFtsYXN0WCwgbGFzdFldID0gdGhpcy5jdXJyZW50UGF0aC5hdCgtMSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKHggIT09IGxhc3RYIHx8IHkgIT09IGxhc3RZKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudFBhdGgucHVzaChbeCwgeV0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBsZXQgYmV6aWVyOwogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnRQYXRoLmxlbmd0aCAhPT0gMSkgewogICAgICAgICAgICAgICAgICAgICAgICBiZXppZXIgPSAoMCwgX3BkZmpzRml0Q3VydmUuZml0Q3VydmUpKHRoaXMuY3VycmVudFBhdGgsIDMwLCBudWxsKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB4eSA9IFt4LCB5XTsKICAgICAgICAgICAgICAgICAgICAgICAgYmV6aWVyID0gW1t4eSwgeHkuc2xpY2UoKSwgeHkuc2xpY2UoKSwgeHldXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGF0aDJEID0gX2NsYXNzU3RhdGljUHJpdmF0ZU1ldGhvZEdldChJbmtFZGl0b3IsIElua0VkaXRvciwgX2J1aWxkUGF0aDJEKS5jYWxsKElua0VkaXRvciwgYmV6aWVyKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRQYXRoLmxlbmd0aCA9IDA7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgY21kID0gKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhdGhzLnB1c2goYmV6aWVyKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5iZXppZXJQYXRoMkQucHVzaChwYXRoMkQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlYnVpbGQoKTsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuZG8gPSAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGF0aHMucG9wKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmV6aWVyUGF0aDJELnBvcCgpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5wYXRocy5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY2FudmFzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfY3JlYXRlQ2FudmFzLCBfY3JlYXRlQ2FudmFzMikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9jcmVhdGVPYnNlcnZlciwgX2NyZWF0ZU9ic2VydmVyMikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2ZpdFRvQ29udGVudCwgX2ZpdFRvQ29udGVudDIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkQ29tbWFuZHMoewogICAgICAgICAgICAgICAgICAgICAgICBjbWQsCiAgICAgICAgICAgICAgICAgICAgICAgIHVuZG8sCiAgICAgICAgICAgICAgICAgICAgICAgIG11c3RFeGVjOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfcmVkcmF3MigpIHsKICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5pc0VtcHR5KCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfdXBkYXRlVHJhbnNmb3JtLCBfdXBkYXRlVHJhbnNmb3JtMikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9zZXRTdHJva2UsIF9zZXRTdHJva2UyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgY2FudmFzLAogICAgICAgICAgICAgICAgICAgICAgICBjdHgKICAgICAgICAgICAgICAgICAgICB9ID0gdGhpczsKICAgICAgICAgICAgICAgICAgICBjdHguc2V0VHJhbnNmb3JtKDEsIDAsIDAsIDEsIDAsIDApOwogICAgICAgICAgICAgICAgICAgIGN0eC5jbGVhclJlY3QoMCwgMCwgY2FudmFzLndpZHRoLCBjYW52YXMuaGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF91cGRhdGVUcmFuc2Zvcm0sIF91cGRhdGVUcmFuc2Zvcm0yKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcGF0aCBvZiB0aGlzLmJlemllclBhdGgyRCkgewogICAgICAgICAgICAgICAgICAgICAgICBjdHguc3Ryb2tlKHBhdGgpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9lbmREcmF3aW5nMihldmVudCkgewogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3N0b3BEcmF3aW5nLCBfc3RvcERyYXdpbmcyKS5jYWxsKHRoaXMsIGV2ZW50Lm9mZnNldFgsIGV2ZW50Lm9mZnNldFkpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY2FudmFzLnJlbW92ZUV2ZW50TGlzdGVuZXIoInBvaW50ZXJsZWF2ZSIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRDYW52YXNQb2ludGVybGVhdmUpKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbnZhcy5yZW1vdmVFdmVudExpc3RlbmVyKCJwb2ludGVybW92ZSIsIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYm91bmRDYW52YXNQb2ludGVybW92ZSkpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkVG9Bbm5vdGF0aW9uU3RvcmFnZSgpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NyZWF0ZUNhbnZhczIoKSB7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJjYW52YXMiKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbnZhcy53aWR0aCA9IHRoaXMuY2FudmFzLmhlaWdodCA9IDA7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jYW52YXMuY2xhc3NOYW1lID0gImlua0VkaXRvckNhbnZhcyI7CiAgICAgICAgICAgICAgICAgICAgSW5rRWRpdG9yLl9sMTBuUHJvbWlzZS5nZXQoImVkaXRvcl9pbmtfY2FudmFzX2FyaWFfbGFiZWwiKS50aGVuKG1zZyA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRjYW52YXM7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAoX3RoaXMkY2FudmFzID0gdGhpcy5jYW52YXMpID09PSBudWxsIHx8IF90aGlzJGNhbnZhcyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkY2FudmFzLnNldEF0dHJpYnV0ZSgiYXJpYS1sYWJlbCIsIG1zZyk7CiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXYuYXBwZW5kKHRoaXMuY2FudmFzKTsKICAgICAgICAgICAgICAgICAgICB0aGlzLmN0eCA9IHRoaXMuY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY3JlYXRlT2JzZXJ2ZXIyKCkgewogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfb2JzZXJ2ZXIsIG5ldyBSZXNpemVPYnNlcnZlcihlbnRyaWVzID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVjdCA9IGVudHJpZXNbMF0uY29udGVudFJlY3Q7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZWN0LndpZHRoICYmIHJlY3QuaGVpZ2h0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldERpbWVuc2lvbnMocmVjdC53aWR0aCwgcmVjdC5oZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfb2JzZXJ2ZXIpLm9ic2VydmUodGhpcy5kaXYpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3NldENhbnZhc0RpbXMyKCkgewogICAgICAgICAgICAgICAgICAgIGlmICghX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9pc0NhbnZhc0luaXRpYWxpemVkKSkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGNvbnN0IFtwYXJlbnRXaWR0aCwgcGFyZW50SGVpZ2h0XSA9IHRoaXMucGFyZW50RGltZW5zaW9uczsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbnZhcy53aWR0aCA9IE1hdGguY2VpbCh0aGlzLndpZHRoICogcGFyZW50V2lkdGgpOwogICAgICAgICAgICAgICAgICAgIHRoaXMuY2FudmFzLmhlaWdodCA9IE1hdGguY2VpbCh0aGlzLmhlaWdodCAqIHBhcmVudEhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfdXBkYXRlVHJhbnNmb3JtLCBfdXBkYXRlVHJhbnNmb3JtMikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9zZXRTY2FsZUZhY3RvcjIod2lkdGgsIGhlaWdodCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhZGRpbmcgPSBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9nZXRQYWRkaW5nLCBfZ2V0UGFkZGluZzIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2NhbGVGYWN0b3JXID0gKHdpZHRoIC0gcGFkZGluZykgLyBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2Jhc2VXaWR0aCk7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2NhbGVGYWN0b3JIID0gKGhlaWdodCAtIHBhZGRpbmcpIC8gX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9iYXNlSGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICB0aGlzLnNjYWxlRmFjdG9yID0gTWF0aC5taW4oc2NhbGVGYWN0b3JXLCBzY2FsZUZhY3RvckgpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3VwZGF0ZVRyYW5zZm9ybTIoKSB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFkZGluZyA9IF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2dldFBhZGRpbmcsIF9nZXRQYWRkaW5nMikuY2FsbCh0aGlzKSAvIDI7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5jdHguc2V0VHJhbnNmb3JtKHRoaXMuc2NhbGVGYWN0b3IsIDAsIDAsIHRoaXMuc2NhbGVGYWN0b3IsIHRoaXMudHJhbnNsYXRpb25YICogdGhpcy5zY2FsZUZhY3RvciArIHBhZGRpbmcsIHRoaXMudHJhbnNsYXRpb25ZICogdGhpcy5zY2FsZUZhY3RvciArIHBhZGRpbmcpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2J1aWxkUGF0aDJEKGJlemllcikgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhdGgyRCA9IG5ldyBQYXRoMkQoKTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBiZXppZXIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbZmlyc3QsIGNvbnRyb2wxLCBjb250cm9sMiwgc2Vjb25kXSA9IGJlemllcltpXTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGkgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGgyRC5tb3ZlVG8oLi4uZmlyc3QpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGgyRC5iZXppZXJDdXJ2ZVRvKGNvbnRyb2wxWzBdLCBjb250cm9sMVsxXSwgY29udHJvbDJbMF0sIGNvbnRyb2wyWzFdLCBzZWNvbmRbMF0sIHNlY29uZFsxXSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRoMkQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfc2VyaWFsaXplUGF0aHMyKHMsIHR4LCB0eSwgaCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IE5VTUJFUl9PRl9QT0lOVFNfT05fQkVaSUVSX0NVUlZFID0gNDsKICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXRocyA9IFtdOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhZGRpbmcgPSB0aGlzLnRoaWNrbmVzcyAvIDI7CiAgICAgICAgICAgICAgICAgICAgbGV0IGJ1ZmZlciwgcG9pbnRzOwogICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgYmV6aWVyIG9mIHRoaXMucGF0aHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50cyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBiZXppZXIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW2ZpcnN0LCBjb250cm9sMSwgY29udHJvbDIsIHNlY29uZF0gPSBiZXppZXJbaV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwMTAgPSBzICogKGZpcnN0WzBdICsgdHgpICsgcGFkZGluZzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHAxMSA9IGggLSBzICogKGZpcnN0WzFdICsgdHkpIC0gcGFkZGluZzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHAyMCA9IHMgKiAoY29udHJvbDFbMF0gKyB0eCkgKyBwYWRkaW5nOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcDIxID0gaCAtIHMgKiAoY29udHJvbDFbMV0gKyB0eSkgLSBwYWRkaW5nOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcDMwID0gcyAqIChjb250cm9sMlswXSArIHR4KSArIHBhZGRpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwMzEgPSBoIC0gcyAqIChjb250cm9sMlsxXSArIHR5KSAtIHBhZGRpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwNDAgPSBzICogKHNlY29uZFswXSArIHR4KSArIHBhZGRpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwNDEgPSBoIC0gcyAqIChzZWNvbmRbMV0gKyB0eSkgLSBwYWRkaW5nOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGkgPT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidWZmZXIucHVzaChwMTAsIHAxMSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRzLnB1c2gocDEwLCBwMTEpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyLnB1c2gocDIwLCBwMjEsIHAzMCwgcDMxLCBwNDAsIHA0MSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9leHRyYWN0UG9pbnRzT25CZXppZXIsIF9leHRyYWN0UG9pbnRzT25CZXppZXIyKS5jYWxsKHRoaXMsIHAxMCwgcDExLCBwMjAsIHAyMSwgcDMwLCBwMzEsIHA0MCwgcDQxLCBOVU1CRVJfT0ZfUE9JTlRTX09OX0JFWklFUl9DVVJWRSwgcG9pbnRzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBwYXRocy5wdXNoKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlemllcjogYnVmZmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRzCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0aHM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfZXh0cmFjdFBvaW50c09uQmV6aWVyMihwMTAsIHAxMSwgcDIwLCBwMjEsIHAzMCwgcDMxLCBwNDAsIHA0MSwgbiwgcG9pbnRzKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX2lzQWxtb3N0RmxhdCwgX2lzQWxtb3N0RmxhdDIpLmNhbGwodGhpcywgcDEwLCBwMTEsIHAyMCwgcDIxLCBwMzAsIHAzMSwgcDQwLCBwNDEpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50cy5wdXNoKHA0MCwgcDQxKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IG4gLSAxOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdCA9IGkgLyBuOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtdCA9IDEgLSB0OwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcTEwID0gdCAqIHAxMCArIG10ICogcDIwOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcTExID0gdCAqIHAxMSArIG10ICogcDIxOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcTIwID0gdCAqIHAyMCArIG10ICogcDMwOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcTIxID0gdCAqIHAyMSArIG10ICogcDMxOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBxMzAgPSB0ICogcDMwICsgbXQgKiBwNDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHEzMSA9IHQgKiBwMzEgKyBtdCAqIHA0MTsKICAgICAgICAgICAgICAgICAgICAgICAgcTEwID0gdCAqIHExMCArIG10ICogcTIwOwogICAgICAgICAgICAgICAgICAgICAgICBxMTEgPSB0ICogcTExICsgbXQgKiBxMjE7CiAgICAgICAgICAgICAgICAgICAgICAgIHEyMCA9IHQgKiBxMjAgKyBtdCAqIHEzMDsKICAgICAgICAgICAgICAgICAgICAgICAgcTIxID0gdCAqIHEyMSArIG10ICogcTMxOwogICAgICAgICAgICAgICAgICAgICAgICBxMTAgPSB0ICogcTEwICsgbXQgKiBxMjA7CiAgICAgICAgICAgICAgICAgICAgICAgIHExMSA9IHQgKiBxMTEgKyBtdCAqIHEyMTsKICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRzLnB1c2gocTEwLCBxMTEpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBwb2ludHMucHVzaChwNDAsIHA0MSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfaXNBbG1vc3RGbGF0MihwMTAsIHAxMSwgcDIwLCBwMjEsIHAzMCwgcDMxLCBwNDAsIHA0MSkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHRvbCA9IDEwOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGF4ID0gKDMgKiBwMjAgLSAyICogcDEwIC0gcDQwKSAqKiAyOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGF5ID0gKDMgKiBwMjEgLSAyICogcDExIC0gcDQxKSAqKiAyOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGJ4ID0gKDMgKiBwMzAgLSBwMTAgLSAyICogcDQwKSAqKiAyOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGJ5ID0gKDMgKiBwMzEgLSBwMTEgLSAyICogcDQxKSAqKiAyOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBNYXRoLm1heChheCwgYngpICsgTWF0aC5tYXgoYXksIGJ5KSA8PSB0b2w7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfZ2V0QmJveDIoKSB7CiAgICAgICAgICAgICAgICAgICAgbGV0IHhNaW4gPSBJbmZpbml0eTsKICAgICAgICAgICAgICAgICAgICBsZXQgeE1heCA9IC1JbmZpbml0eTsKICAgICAgICAgICAgICAgICAgICBsZXQgeU1pbiA9IEluZmluaXR5OwogICAgICAgICAgICAgICAgICAgIGxldCB5TWF4ID0gLUluZmluaXR5OwogICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcGF0aCBvZiB0aGlzLnBhdGhzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgW2ZpcnN0LCBjb250cm9sMSwgY29udHJvbDIsIHNlY29uZF0gb2YgcGF0aCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmJveCA9IF91dGlsLlV0aWwuYmV6aWVyQm91bmRpbmdCb3goLi4uZmlyc3QsIC4uLmNvbnRyb2wxLCAuLi5jb250cm9sMiwgLi4uc2Vjb25kKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhNaW4gPSBNYXRoLm1pbih4TWluLCBiYm94WzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHlNaW4gPSBNYXRoLm1pbih5TWluLCBiYm94WzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhNYXggPSBNYXRoLm1heCh4TWF4LCBiYm94WzJdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHlNYXggPSBNYXRoLm1heCh5TWF4LCBiYm94WzNdKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gW3hNaW4sIHlNaW4sIHhNYXgsIHlNYXhdOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2dldFBhZGRpbmcyKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2Rpc2FibGVFZGl0aW5nKSA/IE1hdGguY2VpbCh0aGlzLnRoaWNrbmVzcyAqIHRoaXMucGFyZW50U2NhbGUpIDogMDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9maXRUb0NvbnRlbnQyKCkgewogICAgICAgICAgICAgICAgICAgIGxldCBmaXJzdFRpbWUgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzRW1wdHkoKSkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGlmICghX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9kaXNhYmxlRWRpdGluZykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfcmVkcmF3LCBfcmVkcmF3MikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBiYm94ID0gX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfZ2V0QmJveCwgX2dldEJib3gyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhZGRpbmcgPSBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9nZXRQYWRkaW5nLCBfZ2V0UGFkZGluZzIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9iYXNlV2lkdGgsIE1hdGgubWF4KFJFU0laRVJfU0laRSwgYmJveFsyXSAtIGJib3hbMF0pKTsKICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX2Jhc2VIZWlnaHQsIE1hdGgubWF4KFJFU0laRVJfU0laRSwgYmJveFszXSAtIGJib3hbMV0pKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCB3aWR0aCA9IE1hdGguY2VpbChwYWRkaW5nICsgX2NsYXNzUHJpdmF0ZUZpZWxkR2V0KHRoaXMsIF9iYXNlV2lkdGgpICogdGhpcy5zY2FsZUZhY3Rvcik7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gTWF0aC5jZWlsKHBhZGRpbmcgKyBfY2xhc3NQcml2YXRlRmllbGRHZXQodGhpcywgX2Jhc2VIZWlnaHQpICogdGhpcy5zY2FsZUZhY3Rvcik7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgW3BhcmVudFdpZHRoLCBwYXJlbnRIZWlnaHRdID0gdGhpcy5wYXJlbnREaW1lbnNpb25zOwogICAgICAgICAgICAgICAgICAgIHRoaXMud2lkdGggPSB3aWR0aCAvIHBhcmVudFdpZHRoOwogICAgICAgICAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID0gaGVpZ2h0IC8gcGFyZW50SGVpZ2h0OwogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVGaWVsZFNldCh0aGlzLCBfYXNwZWN0UmF0aW8sIHdpZHRoIC8gaGVpZ2h0KTsKICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9zZXRNaW5EaW1zLCBfc2V0TWluRGltczIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcHJldlRyYW5zbGF0aW9uWCA9IHRoaXMudHJhbnNsYXRpb25YOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHByZXZUcmFuc2xhdGlvblkgPSB0aGlzLnRyYW5zbGF0aW9uWTsKICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYW5zbGF0aW9uWCA9IC1iYm94WzBdOwogICAgICAgICAgICAgICAgICAgIHRoaXMudHJhbnNsYXRpb25ZID0gLWJib3hbMV07CiAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfc2V0Q2FudmFzRGltcywgX3NldENhbnZhc0RpbXMyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3JlZHJhdywgX3JlZHJhdzIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHRoaXMsIF9yZWFsV2lkdGgsIHdpZHRoKTsKICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlRmllbGRTZXQodGhpcywgX3JlYWxIZWlnaHQsIGhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXREaW1zKHdpZHRoLCBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuc2NhbGVkUGFkZGluZyA9IGZpcnN0VGltZSA/IHBhZGRpbmcgLyB0aGlzLnNjYWxlRmFjdG9yIC8gMiA6IDA7CiAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc2xhdGUocHJldlRyYW5zbGF0aW9uWCAtIHRoaXMudHJhbnNsYXRpb25YIC0gdW5zY2FsZWRQYWRkaW5nLCBwcmV2VHJhbnNsYXRpb25ZIC0gdGhpcy50cmFuc2xhdGlvblkgLSB1bnNjYWxlZFBhZGRpbmcpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX3NldE1pbkRpbXMyKCkgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUKICAgICAgICAgICAgICAgICAgICB9ID0gdGhpcy5kaXY7CiAgICAgICAgICAgICAgICAgICAgaWYgKF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYXNwZWN0UmF0aW8pID49IDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUubWluSGVpZ2h0ID0gYCR7UkVTSVpFUl9TSVpFfXB4YDsKICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUubWluV2lkdGggPSBgJHtNYXRoLnJvdW5kKF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYXNwZWN0UmF0aW8pICogUkVTSVpFUl9TSVpFKX1weGA7CiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUubWluV2lkdGggPSBgJHtSRVNJWkVSX1NJWkV9cHhgOwogICAgICAgICAgICAgICAgICAgICAgICBzdHlsZS5taW5IZWlnaHQgPSBgJHtNYXRoLnJvdW5kKFJFU0laRVJfU0laRSAvIF9jbGFzc1ByaXZhdGVGaWVsZEdldCh0aGlzLCBfYXNwZWN0UmF0aW8pKX1weGA7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgX2RlZmluZVByb3BlcnR5KElua0VkaXRvciwgIl9kZWZhdWx0Q29sb3IiLCBudWxsKTsKICAgICAgICAgICAgICAgIF9kZWZpbmVQcm9wZXJ0eShJbmtFZGl0b3IsICJfZGVmYXVsdE9wYWNpdHkiLCAxKTsKICAgICAgICAgICAgICAgIF9kZWZpbmVQcm9wZXJ0eShJbmtFZGl0b3IsICJfZGVmYXVsdFRoaWNrbmVzcyIsIDEpOwogICAgICAgICAgICAgICAgX2RlZmluZVByb3BlcnR5KElua0VkaXRvciwgIl9sMTBuUHJvbWlzZSIsIHZvaWQgMCk7CiAgICAgICAgICAgICAgICBfZGVmaW5lUHJvcGVydHkoSW5rRWRpdG9yLCAiX3R5cGUiLCAiaW5rIik7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDE2NSAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLmZpdEN1cnZlID0gdm9pZCAwOwogICAgICAgICAgICAgICAgY29uc3QgZml0Q3VydmUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE2Nik7CiAgICAgICAgICAgICAgICBleHBvcnRzLmZpdEN1cnZlID0gZml0Q3VydmU7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDE2NiAqLwogICAgICAgICAgICAvKioqLyAoKG1vZHVsZSkgPT4gewoKICAgICAgICAgICAgICAgICJ1c2Ugc3RyaWN0IjsKCgogICAgICAgICAgICAgICAgZnVuY3Rpb24gZml0Q3VydmUocG9pbnRzLCBtYXhFcnJvciwgcHJvZ3Jlc3NDYWxsYmFjaykgewogICAgICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShwb2ludHMpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoIkZpcnN0IGFyZ3VtZW50IHNob3VsZCBiZSBhbiBhcnJheSIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBwb2ludHMuZm9yRWFjaChwb2ludCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShwb2ludCkgfHwgcG9pbnQuc29tZShpdGVtID0+IHR5cGVvZiBpdGVtICE9PSAnbnVtYmVyJykgfHwgcG9pbnQubGVuZ3RoICE9PSBwb2ludHNbMF0ubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcigiRWFjaCBwb2ludCBzaG91bGQgYmUgYW4gYXJyYXkgb2YgbnVtYmVycy4gRWFjaCBwb2ludCBzaG91bGQgaGF2ZSB0aGUgc2FtZSBhbW91bnQgb2YgbnVtYmVycy4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIHBvaW50cyA9IHBvaW50cy5maWx0ZXIoKHBvaW50LCBpKSA9PiBpID09PSAwIHx8ICFwb2ludC5ldmVyeSgodmFsLCBqKSA9PiB2YWwgPT09IHBvaW50c1tpIC0gMV1bal0pKTsKICAgICAgICAgICAgICAgICAgICBpZiAocG9pbnRzLmxlbmd0aCA8IDIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtdOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjb25zdCBsZW4gPSBwb2ludHMubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGxlZnRUYW5nZW50ID0gY3JlYXRlVGFuZ2VudChwb2ludHNbMV0sIHBvaW50c1swXSk7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmlnaHRUYW5nZW50ID0gY3JlYXRlVGFuZ2VudChwb2ludHNbbGVuIC0gMl0sIHBvaW50c1tsZW4gLSAxXSk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZpdEN1YmljKHBvaW50cywgbGVmdFRhbmdlbnQsIHJpZ2h0VGFuZ2VudCwgbWF4RXJyb3IsIHByb2dyZXNzQ2FsbGJhY2spOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gZml0Q3ViaWMocG9pbnRzLCBsZWZ0VGFuZ2VudCwgcmlnaHRUYW5nZW50LCBlcnJvciwgcHJvZ3Jlc3NDYWxsYmFjaykgewogICAgICAgICAgICAgICAgICAgIGNvbnN0IE1heEl0ZXJhdGlvbnMgPSAyMDsKICAgICAgICAgICAgICAgICAgICB2YXIgYmV6Q3VydmUsIHUsIHVQcmltZSwgbWF4RXJyb3IsIHByZXZFcnIsIHNwbGl0UG9pbnQsIHByZXZTcGxpdCwgY2VudGVyVmVjdG9yLCB0b0NlbnRlclRhbmdlbnQsIGZyb21DZW50ZXJUYW5nZW50LCBiZXppZXJzLCBkaXN0LCBpOwogICAgICAgICAgICAgICAgICAgIGlmIChwb2ludHMubGVuZ3RoID09PSAyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGRpc3QgPSBtYXRocy52ZWN0b3JMZW4obWF0aHMuc3VidHJhY3QocG9pbnRzWzBdLCBwb2ludHNbMV0pKSAvIDMuMDsKICAgICAgICAgICAgICAgICAgICAgICAgYmV6Q3VydmUgPSBbcG9pbnRzWzBdLCBtYXRocy5hZGRBcnJheXMocG9pbnRzWzBdLCBtYXRocy5tdWxJdGVtcyhsZWZ0VGFuZ2VudCwgZGlzdCkpLCBtYXRocy5hZGRBcnJheXMocG9pbnRzWzFdLCBtYXRocy5tdWxJdGVtcyhyaWdodFRhbmdlbnQsIGRpc3QpKSwgcG9pbnRzWzFdXTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtiZXpDdXJ2ZV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHUgPSBjaG9yZExlbmd0aFBhcmFtZXRlcml6ZShwb2ludHMpOwogICAgICAgICAgICAgICAgICAgIFtiZXpDdXJ2ZSwgbWF4RXJyb3IsIHNwbGl0UG9pbnRdID0gZ2VuZXJhdGVBbmRSZXBvcnQocG9pbnRzLCB1LCB1LCBsZWZ0VGFuZ2VudCwgcmlnaHRUYW5nZW50LCBwcm9ncmVzc0NhbGxiYWNrKTsKICAgICAgICAgICAgICAgICAgICBpZiAobWF4RXJyb3IgPT09IDAgfHwgbWF4RXJyb3IgPCBlcnJvcikgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gW2JlekN1cnZlXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKG1heEVycm9yIDwgZXJyb3IgKiBlcnJvcikgewogICAgICAgICAgICAgICAgICAgICAgICB1UHJpbWUgPSB1OwogICAgICAgICAgICAgICAgICAgICAgICBwcmV2RXJyID0gbWF4RXJyb3I7CiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZTcGxpdCA9IHNwbGl0UG9pbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBNYXhJdGVyYXRpb25zOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVQcmltZSA9IHJlcGFyYW1ldGVyaXplKGJlekN1cnZlLCBwb2ludHMsIHVQcmltZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbYmV6Q3VydmUsIG1heEVycm9yLCBzcGxpdFBvaW50XSA9IGdlbmVyYXRlQW5kUmVwb3J0KHBvaW50cywgdSwgdVByaW1lLCBsZWZ0VGFuZ2VudCwgcmlnaHRUYW5nZW50LCBwcm9ncmVzc0NhbGxiYWNrKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXhFcnJvciA8IGVycm9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtiZXpDdXJ2ZV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHNwbGl0UG9pbnQgPT09IHByZXZTcGxpdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnJDaGFuZ2UgPSBtYXhFcnJvciAvIHByZXZFcnI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVyckNoYW5nZSA+IC45OTk5ICYmIGVyckNoYW5nZSA8IDEuMDAwMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2RXJyID0gbWF4RXJyb3I7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2U3BsaXQgPSBzcGxpdFBvaW50OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGJlemllcnMgPSBbXTsKICAgICAgICAgICAgICAgICAgICBjZW50ZXJWZWN0b3IgPSBtYXRocy5zdWJ0cmFjdChwb2ludHNbc3BsaXRQb2ludCAtIDFdLCBwb2ludHNbc3BsaXRQb2ludCArIDFdKTsKICAgICAgICAgICAgICAgICAgICBpZiAoY2VudGVyVmVjdG9yLmV2ZXJ5KHZhbCA9PiB2YWwgPT09IDApKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNlbnRlclZlY3RvciA9IG1hdGhzLnN1YnRyYWN0KHBvaW50c1tzcGxpdFBvaW50IC0gMV0sIHBvaW50c1tzcGxpdFBvaW50XSk7CiAgICAgICAgICAgICAgICAgICAgICAgIFtjZW50ZXJWZWN0b3JbMF0sIGNlbnRlclZlY3RvclsxXV0gPSBbLWNlbnRlclZlY3RvclsxXSwgY2VudGVyVmVjdG9yWzBdXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdG9DZW50ZXJUYW5nZW50ID0gbWF0aHMubm9ybWFsaXplKGNlbnRlclZlY3Rvcik7CiAgICAgICAgICAgICAgICAgICAgZnJvbUNlbnRlclRhbmdlbnQgPSBtYXRocy5tdWxJdGVtcyh0b0NlbnRlclRhbmdlbnQsIC0xKTsKICAgICAgICAgICAgICAgICAgICBiZXppZXJzID0gYmV6aWVycy5jb25jYXQoZml0Q3ViaWMocG9pbnRzLnNsaWNlKDAsIHNwbGl0UG9pbnQgKyAxKSwgbGVmdFRhbmdlbnQsIHRvQ2VudGVyVGFuZ2VudCwgZXJyb3IsIHByb2dyZXNzQ2FsbGJhY2spKTsKICAgICAgICAgICAgICAgICAgICBiZXppZXJzID0gYmV6aWVycy5jb25jYXQoZml0Q3ViaWMocG9pbnRzLnNsaWNlKHNwbGl0UG9pbnQpLCBmcm9tQ2VudGVyVGFuZ2VudCwgcmlnaHRUYW5nZW50LCBlcnJvciwgcHJvZ3Jlc3NDYWxsYmFjaykpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBiZXppZXJzOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gZ2VuZXJhdGVBbmRSZXBvcnQocG9pbnRzLCBwYXJhbXNPcmlnLCBwYXJhbXNQcmltZSwgbGVmdFRhbmdlbnQsIHJpZ2h0VGFuZ2VudCwgcHJvZ3Jlc3NDYWxsYmFjaykgewogICAgICAgICAgICAgICAgICAgIHZhciBiZXpDdXJ2ZSwgbWF4RXJyb3IsIHNwbGl0UG9pbnQ7CiAgICAgICAgICAgICAgICAgICAgYmV6Q3VydmUgPSBnZW5lcmF0ZUJlemllcihwb2ludHMsIHBhcmFtc1ByaW1lLCBsZWZ0VGFuZ2VudCwgcmlnaHRUYW5nZW50LCBwcm9ncmVzc0NhbGxiYWNrKTsKICAgICAgICAgICAgICAgICAgICBbbWF4RXJyb3IsIHNwbGl0UG9pbnRdID0gY29tcHV0ZU1heEVycm9yKHBvaW50cywgYmV6Q3VydmUsIHBhcmFtc09yaWcpOwogICAgICAgICAgICAgICAgICAgIGlmIChwcm9ncmVzc0NhbGxiYWNrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzQ2FsbGJhY2soewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmV6OiBiZXpDdXJ2ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50czogcG9pbnRzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zOiBwYXJhbXNPcmlnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4RXJyOiBtYXhFcnJvciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heFBvaW50OiBzcGxpdFBvaW50CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gW2JlekN1cnZlLCBtYXhFcnJvciwgc3BsaXRQb2ludF07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBnZW5lcmF0ZUJlemllcihwb2ludHMsIHBhcmFtZXRlcnMsIGxlZnRUYW5nZW50LCByaWdodFRhbmdlbnQpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgYmV6Q3VydmUsCiAgICAgICAgICAgICAgICAgICAgICAgIEEsCiAgICAgICAgICAgICAgICAgICAgICAgIGEsCiAgICAgICAgICAgICAgICAgICAgICAgIEMsCiAgICAgICAgICAgICAgICAgICAgICAgIFgsCiAgICAgICAgICAgICAgICAgICAgICAgIGRldF9DMF9DMSwKICAgICAgICAgICAgICAgICAgICAgICAgZGV0X0MwX1gsCiAgICAgICAgICAgICAgICAgICAgICAgIGRldF9YX0MxLAogICAgICAgICAgICAgICAgICAgICAgICBhbHBoYV9sLAogICAgICAgICAgICAgICAgICAgICAgICBhbHBoYV9yLAogICAgICAgICAgICAgICAgICAgICAgICBlcHNpbG9uLAogICAgICAgICAgICAgICAgICAgICAgICBzZWdMZW5ndGgsCiAgICAgICAgICAgICAgICAgICAgICAgIGksCiAgICAgICAgICAgICAgICAgICAgICAgIGxlbiwKICAgICAgICAgICAgICAgICAgICAgICAgdG1wLAogICAgICAgICAgICAgICAgICAgICAgICB1LAogICAgICAgICAgICAgICAgICAgICAgICB1eCwKICAgICAgICAgICAgICAgICAgICAgICAgZmlyc3RQb2ludCA9IHBvaW50c1swXSwKICAgICAgICAgICAgICAgICAgICAgICAgbGFzdFBvaW50ID0gcG9pbnRzW3BvaW50cy5sZW5ndGggLSAxXTsKICAgICAgICAgICAgICAgICAgICBiZXpDdXJ2ZSA9IFtmaXJzdFBvaW50LCBudWxsLCBudWxsLCBsYXN0UG9pbnRdOwogICAgICAgICAgICAgICAgICAgIEEgPSBtYXRocy56ZXJvc19YeDJ4MihwYXJhbWV0ZXJzLmxlbmd0aCk7CiAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMCwgbGVuID0gcGFyYW1ldGVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICB1ID0gcGFyYW1ldGVyc1tpXTsKICAgICAgICAgICAgICAgICAgICAgICAgdXggPSAxIC0gdTsKICAgICAgICAgICAgICAgICAgICAgICAgYSA9IEFbaV07CiAgICAgICAgICAgICAgICAgICAgICAgIGFbMF0gPSBtYXRocy5tdWxJdGVtcyhsZWZ0VGFuZ2VudCwgMyAqIHUgKiAodXggKiB1eCkpOwogICAgICAgICAgICAgICAgICAgICAgICBhWzFdID0gbWF0aHMubXVsSXRlbXMocmlnaHRUYW5nZW50LCAzICogdXggKiAodSAqIHUpKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgQyA9IFtbMCwgMF0sIFswLCAwXV07CiAgICAgICAgICAgICAgICAgICAgWCA9IFswLCAwXTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwLCBsZW4gPSBwb2ludHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgdSA9IHBhcmFtZXRlcnNbaV07CiAgICAgICAgICAgICAgICAgICAgICAgIGEgPSBBW2ldOwogICAgICAgICAgICAgICAgICAgICAgICBDWzBdWzBdICs9IG1hdGhzLmRvdChhWzBdLCBhWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgQ1swXVsxXSArPSBtYXRocy5kb3QoYVswXSwgYVsxXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIENbMV1bMF0gKz0gbWF0aHMuZG90KGFbMF0sIGFbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICBDWzFdWzFdICs9IG1hdGhzLmRvdChhWzFdLCBhWzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgdG1wID0gbWF0aHMuc3VidHJhY3QocG9pbnRzW2ldLCBiZXppZXIucShbZmlyc3RQb2ludCwgZmlyc3RQb2ludCwgbGFzdFBvaW50LCBsYXN0UG9pbnRdLCB1KSk7CiAgICAgICAgICAgICAgICAgICAgICAgIFhbMF0gKz0gbWF0aHMuZG90KGFbMF0sIHRtcCk7CiAgICAgICAgICAgICAgICAgICAgICAgIFhbMV0gKz0gbWF0aHMuZG90KGFbMV0sIHRtcCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGRldF9DMF9DMSA9IENbMF1bMF0gKiBDWzFdWzFdIC0gQ1sxXVswXSAqIENbMF1bMV07CiAgICAgICAgICAgICAgICAgICAgZGV0X0MwX1ggPSBDWzBdWzBdICogWFsxXSAtIENbMV1bMF0gKiBYWzBdOwogICAgICAgICAgICAgICAgICAgIGRldF9YX0MxID0gWFswXSAqIENbMV1bMV0gLSBYWzFdICogQ1swXVsxXTsKICAgICAgICAgICAgICAgICAgICBhbHBoYV9sID0gZGV0X0MwX0MxID09PSAwID8gMCA6IGRldF9YX0MxIC8gZGV0X0MwX0MxOwogICAgICAgICAgICAgICAgICAgIGFscGhhX3IgPSBkZXRfQzBfQzEgPT09IDAgPyAwIDogZGV0X0MwX1ggLyBkZXRfQzBfQzE7CiAgICAgICAgICAgICAgICAgICAgc2VnTGVuZ3RoID0gbWF0aHMudmVjdG9yTGVuKG1hdGhzLnN1YnRyYWN0KGZpcnN0UG9pbnQsIGxhc3RQb2ludCkpOwogICAgICAgICAgICAgICAgICAgIGVwc2lsb24gPSAxLjBlLTYgKiBzZWdMZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgaWYgKGFscGhhX2wgPCBlcHNpbG9uIHx8IGFscGhhX3IgPCBlcHNpbG9uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJlekN1cnZlWzFdID0gbWF0aHMuYWRkQXJyYXlzKGZpcnN0UG9pbnQsIG1hdGhzLm11bEl0ZW1zKGxlZnRUYW5nZW50LCBzZWdMZW5ndGggLyAzLjApKTsKICAgICAgICAgICAgICAgICAgICAgICAgYmV6Q3VydmVbMl0gPSBtYXRocy5hZGRBcnJheXMobGFzdFBvaW50LCBtYXRocy5tdWxJdGVtcyhyaWdodFRhbmdlbnQsIHNlZ0xlbmd0aCAvIDMuMCkpOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJlekN1cnZlWzFdID0gbWF0aHMuYWRkQXJyYXlzKGZpcnN0UG9pbnQsIG1hdGhzLm11bEl0ZW1zKGxlZnRUYW5nZW50LCBhbHBoYV9sKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGJlekN1cnZlWzJdID0gbWF0aHMuYWRkQXJyYXlzKGxhc3RQb2ludCwgbWF0aHMubXVsSXRlbXMocmlnaHRUYW5nZW50LCBhbHBoYV9yKSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJldHVybiBiZXpDdXJ2ZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIDsKICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGFyYW1ldGVyaXplKGJlemllciwgcG9pbnRzLCBwYXJhbWV0ZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhcmFtZXRlcnMubWFwKChwLCBpKSA9PiBuZXd0b25SYXBoc29uUm9vdEZpbmQoYmV6aWVyLCBwb2ludHNbaV0sIHApKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIDsKICAgICAgICAgICAgICAgIGZ1bmN0aW9uIG5ld3RvblJhcGhzb25Sb290RmluZChiZXosIHBvaW50LCB1KSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIGQgPSBtYXRocy5zdWJ0cmFjdChiZXppZXIucShiZXosIHUpLCBwb2ludCksCiAgICAgICAgICAgICAgICAgICAgICAgIHFwcmltZSA9IGJlemllci5xcHJpbWUoYmV6LCB1KSwKICAgICAgICAgICAgICAgICAgICAgICAgbnVtZXJhdG9yID0gbWF0aHMubXVsTWF0cml4KGQsIHFwcmltZSksCiAgICAgICAgICAgICAgICAgICAgICAgIGRlbm9taW5hdG9yID0gbWF0aHMuc3VtKG1hdGhzLnNxdWFyZUl0ZW1zKHFwcmltZSkpICsgMiAqIG1hdGhzLm11bE1hdHJpeChkLCBiZXppZXIucXByaW1lcHJpbWUoYmV6LCB1KSk7CiAgICAgICAgICAgICAgICAgICAgaWYgKGRlbm9taW5hdG9yID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB1OwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB1IC0gbnVtZXJhdG9yIC8gZGVub21pbmF0b3I7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gY2hvcmRMZW5ndGhQYXJhbWV0ZXJpemUocG9pbnRzKSB7CiAgICAgICAgICAgICAgICAgICAgdmFyIHUgPSBbXSwKICAgICAgICAgICAgICAgICAgICAgICAgY3VyclUsCiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZVLAogICAgICAgICAgICAgICAgICAgICAgICBwcmV2UDsKICAgICAgICAgICAgICAgICAgICBwb2ludHMuZm9yRWFjaCgocCwgaSkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICBjdXJyVSA9IGkgPyBwcmV2VSArIG1hdGhzLnZlY3RvckxlbihtYXRocy5zdWJ0cmFjdChwLCBwcmV2UCkpIDogMDsKICAgICAgICAgICAgICAgICAgICAgICAgdS5wdXNoKGN1cnJVKTsKICAgICAgICAgICAgICAgICAgICAgICAgcHJldlUgPSBjdXJyVTsKICAgICAgICAgICAgICAgICAgICAgICAgcHJldlAgPSBwOwogICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIHUgPSB1Lm1hcCh4ID0+IHggLyBwcmV2VSk7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICA7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBjb21wdXRlTWF4RXJyb3IocG9pbnRzLCBiZXosIHBhcmFtZXRlcnMpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgZGlzdCwgbWF4RGlzdCwgc3BsaXRQb2ludCwgdiwgaSwgY291bnQsIHBvaW50LCB0OwogICAgICAgICAgICAgICAgICAgIG1heERpc3QgPSAwOwogICAgICAgICAgICAgICAgICAgIHNwbGl0UG9pbnQgPSBNYXRoLmZsb29yKHBvaW50cy5sZW5ndGggLyAyKTsKICAgICAgICAgICAgICAgICAgICBjb25zdCB0X2Rpc3RNYXAgPSBtYXBUdG9SZWxhdGl2ZURpc3RhbmNlcyhiZXosIDEwKTsKICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwLCBjb3VudCA9IHBvaW50cy5sZW5ndGg7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50ID0gcG9pbnRzW2ldOwogICAgICAgICAgICAgICAgICAgICAgICB0ID0gZmluZF90KGJleiwgcGFyYW1ldGVyc1tpXSwgdF9kaXN0TWFwLCAxMCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHYgPSBtYXRocy5zdWJ0cmFjdChiZXppZXIucShiZXosIHQpLCBwb2ludCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGRpc3QgPSB2WzBdICogdlswXSArIHZbMV0gKiB2WzFdOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGlzdCA+IG1heERpc3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heERpc3QgPSBkaXN0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BsaXRQb2ludCA9IGk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFttYXhEaXN0LCBzcGxpdFBvaW50XTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIDsKICAgICAgICAgICAgICAgIHZhciBtYXBUdG9SZWxhdGl2ZURpc3RhbmNlcyA9IGZ1bmN0aW9uIChiZXosIEJfcGFydHMpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgQl90X2N1cnI7CiAgICAgICAgICAgICAgICAgICAgdmFyIEJfdF9kaXN0ID0gWzBdOwogICAgICAgICAgICAgICAgICAgIHZhciBCX3RfcHJldiA9IGJlelswXTsKICAgICAgICAgICAgICAgICAgICB2YXIgc3VtTGVuID0gMDsKICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8PSBCX3BhcnRzOyBpKyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgQl90X2N1cnIgPSBiZXppZXIucShiZXosIGkgLyBCX3BhcnRzKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3VtTGVuICs9IG1hdGhzLnZlY3RvckxlbihtYXRocy5zdWJ0cmFjdChCX3RfY3VyciwgQl90X3ByZXYpKTsKICAgICAgICAgICAgICAgICAgICAgICAgQl90X2Rpc3QucHVzaChzdW1MZW4pOwogICAgICAgICAgICAgICAgICAgICAgICBCX3RfcHJldiA9IEJfdF9jdXJyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBCX3RfZGlzdCA9IEJfdF9kaXN0Lm1hcCh4ID0+IHggLyBzdW1MZW4pOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBCX3RfZGlzdDsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBmaW5kX3QoYmV6LCBwYXJhbSwgdF9kaXN0TWFwLCBCX3BhcnRzKSB7CiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmFtIDwgMCkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmFtID4gMSkgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbk1heCwgbGVuTWluLCB0TWF4LCB0TWluLCB0OwogICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDw9IEJfcGFydHM7IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFyYW0gPD0gdF9kaXN0TWFwW2ldKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0TWluID0gKGkgLSAxKSAvIEJfcGFydHM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0TWF4ID0gaSAvIEJfcGFydHM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5NaW4gPSB0X2Rpc3RNYXBbaSAtIDFdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVuTWF4ID0gdF9kaXN0TWFwW2ldOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdCA9IChwYXJhbSAtIGxlbk1pbikgLyAobGVuTWF4IC0gbGVuTWluKSAqICh0TWF4IC0gdE1pbikgKyB0TWluOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVUYW5nZW50KHBvaW50QSwgcG9pbnRCKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hdGhzLm5vcm1hbGl6ZShtYXRocy5zdWJ0cmFjdChwb2ludEEsIHBvaW50QikpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgbWF0aHMgewogICAgICAgICAgICAgICAgICAgIHN0YXRpYyB6ZXJvc19YeDJ4Mih4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB6cyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoeC0tKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB6cy5wdXNoKFswLCAwXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHpzOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgbXVsSXRlbXMoaXRlbXMsIG11bHRpcGxpZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW1zLm1hcCh4ID0+IHggKiBtdWx0aXBsaWVyKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIG11bE1hdHJpeChtMSwgbTIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG0xLnJlZHVjZSgoc3VtLCB4MSwgaSkgPT4gc3VtICsgeDEgKiBtMltpXSwgMCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBzdWJ0cmFjdChhcnIxLCBhcnIyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhcnIxLm1hcCgoeDEsIGkpID0+IHgxIC0gYXJyMltpXSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBhZGRBcnJheXMoYXJyMSwgYXJyMikgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXJyMS5tYXAoKHgxLCBpKSA9PiB4MSArIGFycjJbaV0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgYWRkSXRlbXMoaXRlbXMsIGFkZGl0aW9uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpdGVtcy5tYXAoeCA9PiB4ICsgYWRkaXRpb24pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgc3VtKGl0ZW1zKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpdGVtcy5yZWR1Y2UoKHN1bSwgeCkgPT4gc3VtICsgeCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBkb3QobTEsIG0yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXRocy5tdWxNYXRyaXgobTEsIG0yKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIHZlY3Rvckxlbih2KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBNYXRoLmh5cG90KC4uLnYpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgZGl2SXRlbXMoaXRlbXMsIGRpdmlzb3IpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW1zLm1hcCh4ID0+IHggLyBkaXZpc29yKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIHNxdWFyZUl0ZW1zKGl0ZW1zKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpdGVtcy5tYXAoeCA9PiB4ICogeCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBub3JtYWxpemUodikgewogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kaXZJdGVtcyh2LCB0aGlzLnZlY3Rvckxlbih2KSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgYmV6aWVyIHsKICAgICAgICAgICAgICAgICAgICBzdGF0aWMgcShjdHJsUG9seSwgdCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHggPSAxLjAgLSB0OwogICAgICAgICAgICAgICAgICAgICAgICB2YXIgcEEgPSBtYXRocy5tdWxJdGVtcyhjdHJsUG9seVswXSwgdHggKiB0eCAqIHR4KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBCID0gbWF0aHMubXVsSXRlbXMoY3RybFBvbHlbMV0sIDMgKiB0eCAqIHR4ICogdCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwQyA9IG1hdGhzLm11bEl0ZW1zKGN0cmxQb2x5WzJdLCAzICogdHggKiB0ICogdCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwRCA9IG1hdGhzLm11bEl0ZW1zKGN0cmxQb2x5WzNdLCB0ICogdCAqIHQpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWF0aHMuYWRkQXJyYXlzKG1hdGhzLmFkZEFycmF5cyhwQSwgcEIpLCBtYXRocy5hZGRBcnJheXMocEMsIHBEKSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBxcHJpbWUoY3RybFBvbHksIHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHR4ID0gMS4wIC0gdDsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHBBID0gbWF0aHMubXVsSXRlbXMobWF0aHMuc3VidHJhY3QoY3RybFBvbHlbMV0sIGN0cmxQb2x5WzBdKSwgMyAqIHR4ICogdHgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcEIgPSBtYXRocy5tdWxJdGVtcyhtYXRocy5zdWJ0cmFjdChjdHJsUG9seVsyXSwgY3RybFBvbHlbMV0pLCA2ICogdHggKiB0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBDID0gbWF0aHMubXVsSXRlbXMobWF0aHMuc3VidHJhY3QoY3RybFBvbHlbM10sIGN0cmxQb2x5WzJdKSwgMyAqIHQgKiB0KTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hdGhzLmFkZEFycmF5cyhtYXRocy5hZGRBcnJheXMocEEsIHBCKSwgcEMpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgcXByaW1lcHJpbWUoY3RybFBvbHksIHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hdGhzLmFkZEFycmF5cyhtYXRocy5tdWxJdGVtcyhtYXRocy5hZGRBcnJheXMobWF0aHMuc3VidHJhY3QoY3RybFBvbHlbMl0sIG1hdGhzLm11bEl0ZW1zKGN0cmxQb2x5WzFdLCAyKSksIGN0cmxQb2x5WzBdKSwgNiAqICgxLjAgLSB0KSksIG1hdGhzLm11bEl0ZW1zKG1hdGhzLmFkZEFycmF5cyhtYXRocy5zdWJ0cmFjdChjdHJsUG9seVszXSwgbWF0aHMubXVsSXRlbXMoY3RybFBvbHlbMl0sIDIpKSwgY3RybFBvbHlbMV0pLCA2ICogdCkpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZml0Q3VydmU7CiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cy5maXRDdWJpYyA9IGZpdEN1YmljOwogICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMuY3JlYXRlVGFuZ2VudCA9IGNyZWF0ZVRhbmdlbnQ7CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDE2NyAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLkFubm90YXRpb25MYXllciA9IHZvaWQgMDsKICAgICAgICAgICAgICAgIHZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMSk7CiAgICAgICAgICAgICAgICB2YXIgX2Rpc3BsYXlfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0Mik7CiAgICAgICAgICAgICAgICB2YXIgX2Fubm90YXRpb25fc3RvcmFnZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTM5KTsKICAgICAgICAgICAgICAgIHZhciBfc2NyaXB0aW5nX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNjgpOwogICAgICAgICAgICAgICAgdmFyIF94ZmFfbGF5ZXIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE2OSk7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NTdGF0aWNQcml2YXRlTWV0aG9kR2V0KHJlY2VpdmVyLCBjbGFzc0NvbnN0cnVjdG9yLCBtZXRob2QpIHsgX2NsYXNzQ2hlY2tQcml2YXRlU3RhdGljQWNjZXNzKHJlY2VpdmVyLCBjbGFzc0NvbnN0cnVjdG9yKTsgcmV0dXJuIG1ldGhvZDsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NsYXNzQ2hlY2tQcml2YXRlU3RhdGljQWNjZXNzKHJlY2VpdmVyLCBjbGFzc0NvbnN0cnVjdG9yKSB7IGlmIChyZWNlaXZlciAhPT0gY2xhc3NDb25zdHJ1Y3RvcikgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJQcml2YXRlIHN0YXRpYyBhY2Nlc3Mgb2Ygd3JvbmcgcHJvdmVuYW5jZSIpOyB9IH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyhvYmosIHByaXZhdGVTZXQpIHsgX2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24ob2JqLCBwcml2YXRlU2V0KTsgcHJpdmF0ZVNldC5hZGQob2JqKTsgfQogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2NoZWNrUHJpdmF0ZVJlZGVjbGFyYXRpb24ob2JqLCBwcml2YXRlQ29sbGVjdGlvbikgeyBpZiAocHJpdmF0ZUNvbGxlY3Rpb24uaGFzKG9iaikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcigiQ2Fubm90IGluaXRpYWxpemUgdGhlIHNhbWUgcHJpdmF0ZSBlbGVtZW50cyB0d2ljZSBvbiBhbiBvYmplY3QiKTsgfSB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHJlY2VpdmVyLCBwcml2YXRlU2V0LCBmbikgeyBpZiAoIXByaXZhdGVTZXQuaGFzKHJlY2VpdmVyKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKCJhdHRlbXB0ZWQgdG8gZ2V0IHByaXZhdGUgZmllbGQgb24gbm9uLWluc3RhbmNlIik7IH0gcmV0dXJuIGZuOyB9CiAgICAgICAgICAgICAgICBjb25zdCBERUZBVUxUX1RBQl9JTkRFWCA9IDEwMDA7CiAgICAgICAgICAgICAgICBjb25zdCBERUZBVUxUX0ZPTlRfU0laRSA9IDk7CiAgICAgICAgICAgICAgICBjb25zdCBHZXRFbGVtZW50c0J5TmFtZVNldCA9IG5ldyBXZWFrU2V0KCk7CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBnZXRSZWN0RGltcyhyZWN0KSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IHJlY3RbMl0gLSByZWN0WzBdLAogICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHJlY3RbM10gLSByZWN0WzFdCiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIEFubm90YXRpb25FbGVtZW50RmFjdG9yeSB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIGNyZWF0ZShwYXJhbWV0ZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN1YnR5cGUgPSBwYXJhbWV0ZXJzLmRhdGEuYW5ub3RhdGlvblR5cGU7CiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoc3VidHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uVHlwZS5MSU5LOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgTGlua0Fubm90YXRpb25FbGVtZW50KHBhcmFtZXRlcnMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uVHlwZS5URVhUOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVGV4dEFubm90YXRpb25FbGVtZW50KHBhcmFtZXRlcnMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uVHlwZS5XSURHRVQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmllbGRUeXBlID0gcGFyYW1ldGVycy5kYXRhLmZpZWxkVHlwZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGZpZWxkVHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJUeCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFRleHRXaWRnZXRBbm5vdGF0aW9uRWxlbWVudChwYXJhbWV0ZXJzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiQnRuIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXJhbWV0ZXJzLmRhdGEucmFkaW9CdXR0b24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFJhZGlvQnV0dG9uV2lkZ2V0QW5ub3RhdGlvbkVsZW1lbnQocGFyYW1ldGVycyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBhcmFtZXRlcnMuZGF0YS5jaGVja0JveCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQ2hlY2tib3hXaWRnZXRBbm5vdGF0aW9uRWxlbWVudChwYXJhbWV0ZXJzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUHVzaEJ1dHRvbldpZGdldEFubm90YXRpb25FbGVtZW50KHBhcmFtZXRlcnMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJDaCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IENob2ljZVdpZGdldEFubm90YXRpb25FbGVtZW50KHBhcmFtZXRlcnMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFdpZGdldEFubm90YXRpb25FbGVtZW50KHBhcmFtZXRlcnMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uVHlwZS5QT1BVUDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFBvcHVwQW5ub3RhdGlvbkVsZW1lbnQocGFyYW1ldGVycyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25UeXBlLkZSRUVURVhUOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRnJlZVRleHRBbm5vdGF0aW9uRWxlbWVudChwYXJhbWV0ZXJzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuQW5ub3RhdGlvblR5cGUuTElORToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IExpbmVBbm5vdGF0aW9uRWxlbWVudChwYXJhbWV0ZXJzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuQW5ub3RhdGlvblR5cGUuU1FVQVJFOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU3F1YXJlQW5ub3RhdGlvbkVsZW1lbnQocGFyYW1ldGVycyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25UeXBlLkNJUkNMRToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IENpcmNsZUFubm90YXRpb25FbGVtZW50KHBhcmFtZXRlcnMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uVHlwZS5QT0xZTElORToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFBvbHlsaW5lQW5ub3RhdGlvbkVsZW1lbnQocGFyYW1ldGVycyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25UeXBlLkNBUkVUOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQ2FyZXRBbm5vdGF0aW9uRWxlbWVudChwYXJhbWV0ZXJzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuQW5ub3RhdGlvblR5cGUuSU5LOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgSW5rQW5ub3RhdGlvbkVsZW1lbnQocGFyYW1ldGVycyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25UeXBlLlBPTFlHT046CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQb2x5Z29uQW5ub3RhdGlvbkVsZW1lbnQocGFyYW1ldGVycyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25UeXBlLkhJR0hMSUdIVDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEhpZ2hsaWdodEFubm90YXRpb25FbGVtZW50KHBhcmFtZXRlcnMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uVHlwZS5VTkRFUkxJTkU6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBVbmRlcmxpbmVBbm5vdGF0aW9uRWxlbWVudChwYXJhbWV0ZXJzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuQW5ub3RhdGlvblR5cGUuU1FVSUdHTFk6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTcXVpZ2dseUFubm90YXRpb25FbGVtZW50KHBhcmFtZXRlcnMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uVHlwZS5TVFJJS0VPVVQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTdHJpa2VPdXRBbm5vdGF0aW9uRWxlbWVudChwYXJhbWV0ZXJzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuQW5ub3RhdGlvblR5cGUuU1RBTVA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTdGFtcEFubm90YXRpb25FbGVtZW50KHBhcmFtZXRlcnMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uVHlwZS5GSUxFQVRUQUNITUVOVDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEZpbGVBdHRhY2htZW50QW5ub3RhdGlvbkVsZW1lbnQocGFyYW1ldGVycyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgQW5ub3RhdGlvbkVsZW1lbnQocGFyYW1ldGVycyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBBbm5vdGF0aW9uRWxlbWVudCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNSZW5kZXJhYmxlID0gZmFsc2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmVCb3JkZXIgPSBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZVF1YWRyaWxhdGVyYWxzID0gZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXNSZW5kZXJhYmxlID0gaXNSZW5kZXJhYmxlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGEgPSBwYXJhbWV0ZXJzLmRhdGE7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGF5ZXIgPSBwYXJhbWV0ZXJzLmxheWVyOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhZ2UgPSBwYXJhbWV0ZXJzLnBhZ2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudmlld3BvcnQgPSBwYXJhbWV0ZXJzLnZpZXdwb3J0OwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxpbmtTZXJ2aWNlID0gcGFyYW1ldGVycy5saW5rU2VydmljZTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kb3dubG9hZE1hbmFnZXIgPSBwYXJhbWV0ZXJzLmRvd25sb2FkTWFuYWdlcjsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbWFnZVJlc291cmNlc1BhdGggPSBwYXJhbWV0ZXJzLmltYWdlUmVzb3VyY2VzUGF0aDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJGb3JtcyA9IHBhcmFtZXRlcnMucmVuZGVyRm9ybXM7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3ZnRmFjdG9yeSA9IHBhcmFtZXRlcnMuc3ZnRmFjdG9yeTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hbm5vdGF0aW9uU3RvcmFnZSA9IHBhcmFtZXRlcnMuYW5ub3RhdGlvblN0b3JhZ2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlU2NyaXB0aW5nID0gcGFyYW1ldGVycy5lbmFibGVTY3JpcHRpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGFzSlNBY3Rpb25zID0gcGFyYW1ldGVycy5oYXNKU0FjdGlvbnM7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2ZpZWxkT2JqZWN0cyA9IHBhcmFtZXRlcnMuZmllbGRPYmplY3RzOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNSZW5kZXJhYmxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lciA9IHRoaXMuX2NyZWF0ZUNvbnRhaW5lcihpZ25vcmVCb3JkZXIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjcmVhdGVRdWFkcmlsYXRlcmFscykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5xdWFkcmlsYXRlcmFscyA9IHRoaXMuX2NyZWF0ZVF1YWRyaWxhdGVyYWxzKGlnbm9yZUJvcmRlcik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2NyZWF0ZUNvbnRhaW5lcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGlnbm9yZUJvcmRlciA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlld3BvcnQKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXM7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNlY3Rpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyLnNldEF0dHJpYnV0ZSgiZGF0YS1hbm5vdGF0aW9uLWlkIiwgZGF0YS5pZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLm5vUm90YXRlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXIuY2xhc3NMaXN0LmFkZCgibm9yb3RhdGUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlV2lkdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlSGVpZ2h0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZVgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlWQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gdmlld3BvcnQucmF3RGltczsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGdldFJlY3REaW1zKGRhdGEucmVjdCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlY3QgPSBfdXRpbC5VdGlsLm5vcm1hbGl6ZVJlY3QoW2RhdGEucmVjdFswXSwgcGFnZS52aWV3WzNdIC0gZGF0YS5yZWN0WzFdICsgcGFnZS52aWV3WzFdLCBkYXRhLnJlY3RbMl0sIHBhZ2Uudmlld1szXSAtIGRhdGEucmVjdFszXSArIHBhZ2Uudmlld1sxXV0pOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWlnbm9yZUJvcmRlciAmJiBkYXRhLmJvcmRlclN0eWxlLndpZHRoID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyLnN0eWxlLmJvcmRlcldpZHRoID0gYCR7ZGF0YS5ib3JkZXJTdHlsZS53aWR0aH1weGA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBob3Jpem9udGFsUmFkaXVzID0gZGF0YS5ib3JkZXJTdHlsZS5ob3Jpem9udGFsQ29ybmVyUmFkaXVzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdmVydGljYWxSYWRpdXMgPSBkYXRhLmJvcmRlclN0eWxlLnZlcnRpY2FsQ29ybmVyUmFkaXVzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhvcml6b250YWxSYWRpdXMgPiAwIHx8IHZlcnRpY2FsUmFkaXVzID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJhZGl1cyA9IGBjYWxjKCR7aG9yaXpvbnRhbFJhZGl1c31weCAqIHZhcigtLXNjYWxlLWZhY3RvcikpIC8gY2FsYygke3ZlcnRpY2FsUmFkaXVzfXB4ICogdmFyKC0tc2NhbGUtZmFjdG9yKSlgOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lci5zdHlsZS5ib3JkZXJSYWRpdXMgPSByYWRpdXM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMgaW5zdGFuY2VvZiBSYWRpb0J1dHRvbldpZGdldEFubm90YXRpb25FbGVtZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFkaXVzID0gYGNhbGMoJHt3aWR0aH1weCAqIHZhcigtLXNjYWxlLWZhY3RvcikpIC8gY2FsYygke2hlaWdodH1weCAqIHZhcigtLXNjYWxlLWZhY3RvcikpYDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXIuc3R5bGUuYm9yZGVyUmFkaXVzID0gcmFkaXVzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChkYXRhLmJvcmRlclN0eWxlLnN0eWxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlLlNPTElEOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXIuc3R5bGUuYm9yZGVyU3R5bGUgPSAic29saWQiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25Cb3JkZXJTdHlsZVR5cGUuREFTSEVEOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXIuc3R5bGUuYm9yZGVyU3R5bGUgPSAiZGFzaGVkIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlLkJFVkVMRUQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiVW5pbXBsZW1lbnRlZCBib3JkZXIgc3R5bGU6IGJldmVsZWQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlLklOU0VUOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoIlVuaW1wbGVtZW50ZWQgYm9yZGVyIHN0eWxlOiBpbnNldCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25Cb3JkZXJTdHlsZVR5cGUuVU5ERVJMSU5FOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXIuc3R5bGUuYm9yZGVyQm90dG9tU3R5bGUgPSAic29saWQiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJvcmRlckNvbG9yID0gZGF0YS5ib3JkZXJDb2xvciB8fCBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJvcmRlckNvbG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyLnN0eWxlLmJvcmRlckNvbG9yID0gX3V0aWwuVXRpbC5tYWtlSGV4Q29sb3IoYm9yZGVyQ29sb3JbMF0gfCAwLCBib3JkZXJDb2xvclsxXSB8IDAsIGJvcmRlckNvbG9yWzJdIHwgMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lci5zdHlsZS5ib3JkZXJXaWR0aCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyLnN0eWxlLmxlZnQgPSBgJHsxMDAgKiAocmVjdFswXSAtIHBhZ2VYKSAvIHBhZ2VXaWR0aH0lYDsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyLnN0eWxlLnRvcCA9IGAkezEwMCAqIChyZWN0WzFdIC0gcGFnZVkpIC8gcGFnZUhlaWdodH0lYDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb24KICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGRhdGE7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLmhhc093bkNhbnZhcyB8fCByb3RhdGlvbiA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyLnN0eWxlLndpZHRoID0gYCR7MTAwICogd2lkdGggLyBwYWdlV2lkdGh9JWA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXIuc3R5bGUuaGVpZ2h0ID0gYCR7MTAwICogaGVpZ2h0IC8gcGFnZUhlaWdodH0lYDsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0Um90YXRpb24ocm90YXRpb24sIGNvbnRhaW5lcik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbnRhaW5lcjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc2V0Um90YXRpb24oYW5nbGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvbnRhaW5lciA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogdGhpcy5jb250YWluZXI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VXaWR0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VIZWlnaHQKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXMudmlld3BvcnQucmF3RGltczsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGdldFJlY3REaW1zKHRoaXMuZGF0YS5yZWN0KTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGVsZW1lbnRXaWR0aCwgZWxlbWVudEhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFuZ2xlICUgMTgwID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50V2lkdGggPSAxMDAgKiB3aWR0aCAvIHBhZ2VXaWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRIZWlnaHQgPSAxMDAgKiBoZWlnaHQgLyBwYWdlSGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudFdpZHRoID0gMTAwICogaGVpZ2h0IC8gcGFnZVdpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudEhlaWdodCA9IDEwMCAqIHdpZHRoIC8gcGFnZUhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXIuc3R5bGUud2lkdGggPSBgJHtlbGVtZW50V2lkdGh9JWA7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lci5zdHlsZS5oZWlnaHQgPSBgJHtlbGVtZW50SGVpZ2h0fSVgOwogICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXIuc2V0QXR0cmlidXRlKCJkYXRhLW1haW4tcm90YXRpb24iLCAoMzYwIC0gYW5nbGUpICUgMzYwKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgZ2V0IF9jb21tb25BY3Rpb25zKCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzZXRDb2xvciA9IChqc05hbWUsIHN0eWxlTmFtZSwgZXZlbnQpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbG9yID0gZXZlbnQuZGV0YWlsW2pzTmFtZV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudC50YXJnZXQuc3R5bGVbc3R5bGVOYW1lXSA9IF9zY3JpcHRpbmdfdXRpbHMuQ29sb3JDb252ZXJ0ZXJzW2Ake2NvbG9yWzBdfV9IVE1MYF0oY29sb3Iuc2xpY2UoMSkpOwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIl9jb21tb25BY3Rpb25zIiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhpZGRlbiA9IGV2ZW50LmRldGFpbC5kaXNwbGF5ICUgMiA9PT0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5zdHlsZS52aXNpYmlsaXR5ID0gaGlkZGVuID8gImhpZGRlbiIgOiAidmlzaWJsZSI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hbm5vdGF0aW9uU3RvcmFnZS5zZXRWYWx1ZSh0aGlzLmRhdGEuaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGlkZGVuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmludDogZXZlbnQuZGV0YWlsLmRpc3BsYXkgPT09IDAgfHwgZXZlbnQuZGV0YWlsLmRpc3BsYXkgPT09IDMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmludDogZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYW5ub3RhdGlvblN0b3JhZ2Uuc2V0VmFsdWUodGhpcy5kYXRhLmlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByaW50OiBldmVudC5kZXRhaWwucHJpbnQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWRkZW46IGV2ZW50ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5zdHlsZS52aXNpYmlsaXR5ID0gZXZlbnQuZGV0YWlsLmhpZGRlbiA/ICJoaWRkZW4iIDogInZpc2libGUiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYW5ub3RhdGlvblN0b3JhZ2Uuc2V0VmFsdWUodGhpcy5kYXRhLmlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZGRlbjogZXZlbnQuZGV0YWlsLmhpZGRlbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvY3VzOiBldmVudCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiBldmVudC50YXJnZXQuZm9jdXMoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2ZW50U2Nyb2xsOiBmYWxzZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VyTmFtZTogZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnRhcmdldC50aXRsZSA9IGV2ZW50LmRldGFpbC51c2VyTmFtZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkb25seTogZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudC5kZXRhaWwucmVhZG9ubHkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQudGFyZ2V0LnNldEF0dHJpYnV0ZSgicmVhZG9ubHkiLCAiIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQudGFyZ2V0LnJlbW92ZUF0dHJpYnV0ZSgicmVhZG9ubHkiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWlyZWQ6IGV2ZW50ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRSZXF1aXJlZChldmVudC50YXJnZXQsIGV2ZW50LmRldGFpbC5yZXF1aXJlZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmdDb2xvcjogZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldENvbG9yKCJiZ0NvbG9yIiwgImJhY2tncm91bmRDb2xvciIsIGV2ZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsQ29sb3I6IGV2ZW50ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXRDb2xvcigiZmlsbENvbG9yIiwgImJhY2tncm91bmRDb2xvciIsIGV2ZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZ0NvbG9yOiBldmVudCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0Q29sb3IoImZnQ29sb3IiLCAiY29sb3IiLCBldmVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dENvbG9yOiBldmVudCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0Q29sb3IoInRleHRDb2xvciIsICJjb2xvciIsIGV2ZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBib3JkZXJDb2xvcjogZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldENvbG9yKCJib3JkZXJDb2xvciIsICJib3JkZXJDb2xvciIsIGV2ZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2VDb2xvcjogZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldENvbG9yKCJzdHJva2VDb2xvciIsICJib3JkZXJDb2xvciIsIGV2ZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3RhdGlvbjogZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFuZ2xlID0gZXZlbnQuZGV0YWlsLnJvdGF0aW9uOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0Um90YXRpb24oYW5nbGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYW5ub3RhdGlvblN0b3JhZ2Uuc2V0VmFsdWUodGhpcy5kYXRhLmlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0aW9uOiBhbmdsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2Rpc3BhdGNoRXZlbnRGcm9tU2FuZGJveChhY3Rpb25zLCBqc0V2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbW1vbkFjdGlvbnMgPSB0aGlzLl9jb21tb25BY3Rpb25zOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmtleXMoanNFdmVudC5kZXRhaWwpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhY3Rpb24gPSBhY3Rpb25zW25hbWVdIHx8IGNvbW1vbkFjdGlvbnNbbmFtZV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb24gPT09IG51bGwgfHwgYWN0aW9uID09PSB2b2lkIDAgPyB2b2lkIDAgOiBhY3Rpb24oanNFdmVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX3NldERlZmF1bHRQcm9wZXJ0aWVzRnJvbUpTKGVsZW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmVuYWJsZVNjcmlwdGluZykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0b3JlZERhdGEgPSB0aGlzLmFubm90YXRpb25TdG9yYWdlLmdldFJhd1ZhbHVlKHRoaXMuZGF0YS5pZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc3RvcmVkRGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbW1vbkFjdGlvbnMgPSB0aGlzLl9jb21tb25BY3Rpb25zOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IFthY3Rpb25OYW1lLCBkZXRhaWxdIG9mIE9iamVjdC5lbnRyaWVzKHN0b3JlZERhdGEpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhY3Rpb24gPSBjb21tb25BY3Rpb25zW2FjdGlvbk5hbWVdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFjdGlvbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV2ZW50UHJveHkgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldGFpbDogewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2FjdGlvbk5hbWVdOiBkZXRhaWwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0OiBlbGVtZW50CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb24oZXZlbnRQcm94eSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHN0b3JlZERhdGFbYWN0aW9uTmFtZV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2NyZWF0ZVF1YWRyaWxhdGVyYWxzKCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgaWdub3JlQm9yZGVyID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmRhdGEucXVhZFBvaW50cykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcXVhZHJpbGF0ZXJhbHMgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2F2ZWRSZWN0ID0gdGhpcy5kYXRhLnJlY3Q7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcXVhZFBvaW50IG9mIHRoaXMuZGF0YS5xdWFkUG9pbnRzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGEucmVjdCA9IFtxdWFkUG9pbnRbMl0ueCwgcXVhZFBvaW50WzJdLnksIHF1YWRQb2ludFsxXS54LCBxdWFkUG9pbnRbMV0ueV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBxdWFkcmlsYXRlcmFscy5wdXNoKHRoaXMuX2NyZWF0ZUNvbnRhaW5lcihpZ25vcmVCb3JkZXIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGEucmVjdCA9IHNhdmVkUmVjdDsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHF1YWRyaWxhdGVyYWxzOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfY3JlYXRlUG9wdXAodHJpZ2dlciwgZGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgY29udGFpbmVyID0gdGhpcy5jb250YWluZXI7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnF1YWRyaWxhdGVyYWxzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyID0gdHJpZ2dlciB8fCB0aGlzLnF1YWRyaWxhdGVyYWxzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyID0gdGhpcy5xdWFkcmlsYXRlcmFsc1swXTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRyaWdnZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyaWdnZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyaWdnZXIuY2xhc3NMaXN0LmFkZCgicG9wdXBUcmlnZ2VyQXJlYSIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyLmFwcGVuZCh0cmlnZ2VyKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb3B1cEVsZW1lbnQgPSBuZXcgUG9wdXBFbGVtZW50KHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyaWdnZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcjogZGF0YS5jb2xvciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlT2JqOiBkYXRhLnRpdGxlT2JqLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZpY2F0aW9uRGF0ZTogZGF0YS5tb2RpZmljYXRpb25EYXRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudHNPYmo6IGRhdGEuY29udGVudHNPYmosCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByaWNoVGV4dDogZGF0YS5yaWNoVGV4dCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZGVXcmFwcGVyOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb3B1cCA9IHBvcHVwRWxlbWVudC5yZW5kZXIoKTsKICAgICAgICAgICAgICAgICAgICAgICAgcG9wdXAuc3R5bGUubGVmdCA9ICIxMDAlIjsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyLmFwcGVuZChwb3B1cCk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9yZW5kZXJRdWFkcmlsYXRlcmFscyhjbGFzc05hbWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBxdWFkcmlsYXRlcmFsIG9mIHRoaXMucXVhZHJpbGF0ZXJhbHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHF1YWRyaWxhdGVyYWwuY2xhc3NMaXN0LmFkZChjbGFzc05hbWUpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnF1YWRyaWxhdGVyYWxzOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZW5kZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIkFic3RyYWN0IG1ldGhvZCBgQW5ub3RhdGlvbkVsZW1lbnQucmVuZGVyYCBjYWxsZWQiKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2dldEVsZW1lbnRzQnlOYW1lKG5hbWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNraXBJZCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmllbGRzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLl9maWVsZE9iamVjdHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpZWxkT2JqID0gdGhpcy5fZmllbGRPYmplY3RzW25hbWVdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpZWxkT2JqKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBvcnRWYWx1ZXMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IG9mIGZpZWxkT2JqKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYWdlID09PSAtMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlkID09PSBza2lwSWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4cG9ydFZhbHVlID0gdHlwZW9mIGV4cG9ydFZhbHVlcyA9PT0gInN0cmluZyIgPyBleHBvcnRWYWx1ZXMgOiBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihgW2RhdGEtZWxlbWVudC1pZD0iJHtpZH0iXWApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tRWxlbWVudCAmJiAhR2V0RWxlbWVudHNCeU5hbWVTZXQuaGFzKGRvbUVsZW1lbnQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYF9nZXRFbGVtZW50c0J5TmFtZSAtIGVsZW1lbnQgbm90IGFsbG93ZWQ6ICR7aWR9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHMucHVzaCh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cG9ydFZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tRWxlbWVudAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmllbGRzOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZG9tRWxlbWVudCBvZiBkb2N1bWVudC5nZXRFbGVtZW50c0J5TmFtZShuYW1lKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cG9ydFZhbHVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gZG9tRWxlbWVudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkID0gZG9tRWxlbWVudC5nZXRBdHRyaWJ1dGUoImRhdGEtZWxlbWVudC1pZCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlkID09PSBza2lwSWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghR2V0RWxlbWVudHNCeU5hbWVTZXQuaGFzKGRvbUVsZW1lbnQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZHMucHVzaCh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwb3J0VmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZG9tRWxlbWVudAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZpZWxkczsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB2YXIgX3NldEludGVybmFsTGluayA9IC8qI19fUFVSRV9fKi9uZXcgV2Vha1NldCgpOwogICAgICAgICAgICAgICAgdmFyIF9iaW5kU2V0T0NHU3RhdGUgPSAvKiNfX1BVUkVfXyovbmV3IFdlYWtTZXQoKTsKICAgICAgICAgICAgICAgIGNsYXNzIExpbmtBbm5vdGF0aW9uRWxlbWVudCBleHRlbmRzIEFubm90YXRpb25FbGVtZW50IHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihwYXJhbWV0ZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBvcHRpb25zID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICBzdXBlcihwYXJhbWV0ZXJzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1JlbmRlcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmVCb3JkZXI6ICEhKG9wdGlvbnMgIT09IG51bGwgJiYgb3B0aW9ucyAhPT0gdm9pZCAwICYmIG9wdGlvbnMuaWdub3JlQm9yZGVyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZVF1YWRyaWxhdGVyYWxzOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kSW5pdFNwZWModGhpcywgX2JpbmRTZXRPQ0dTdGF0ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RJbml0U3BlYyh0aGlzLCBfc2V0SW50ZXJuYWxMaW5rKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc1Rvb2x0aXBPbmx5ID0gcGFyYW1ldGVycy5kYXRhLmlzVG9vbHRpcE9ubHk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbmRlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmtTZXJ2aWNlCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSB0aGlzOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYSIpOwogICAgICAgICAgICAgICAgICAgICAgICBsaW5rLnNldEF0dHJpYnV0ZSgiZGF0YS1lbGVtZW50LWlkIiwgZGF0YS5pZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBpc0JvdW5kID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnVybCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlua1NlcnZpY2UuYWRkTGlua0F0dHJpYnV0ZXMobGluaywgZGF0YS51cmwsIGRhdGEubmV3V2luZG93KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzQm91bmQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGEuYWN0aW9uKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9iaW5kTmFtZWRBY3Rpb24obGluaywgZGF0YS5hY3Rpb24pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNCb3VuZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZGF0YS5hdHRhY2htZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9iaW5kQXR0YWNobWVudChsaW5rLCBkYXRhLmF0dGFjaG1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNCb3VuZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZGF0YS5zZXRPQ0dTdGF0ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfYmluZFNldE9DR1N0YXRlLCBfYmluZFNldE9DR1N0YXRlMikuY2FsbCh0aGlzLCBsaW5rLCBkYXRhLnNldE9DR1N0YXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzQm91bmQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGEuZGVzdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fYmluZExpbmsobGluaywgZGF0YS5kZXN0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzQm91bmQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEuYWN0aW9ucyAmJiAoZGF0YS5hY3Rpb25zLkFjdGlvbiB8fCBkYXRhLmFjdGlvbnNbIk1vdXNlIFVwIl0gfHwgZGF0YS5hY3Rpb25zWyJNb3VzZSBEb3duIl0pICYmIHRoaXMuZW5hYmxlU2NyaXB0aW5nICYmIHRoaXMuaGFzSlNBY3Rpb25zKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fYmluZEpTQWN0aW9uKGxpbmssIGRhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzQm91bmQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEucmVzZXRGb3JtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fYmluZFJlc2V0Rm9ybUFjdGlvbihsaW5rLCBkYXRhLnJlc2V0Rm9ybSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNCb3VuZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaXNUb29sdGlwT25seSAmJiAhaXNCb3VuZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2JpbmRMaW5rKGxpbmssICIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0JvdW5kID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5xdWFkcmlsYXRlcmFscykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3JlbmRlclF1YWRyaWxhdGVyYWxzKCJsaW5rQW5ub3RhdGlvbiIpLm1hcCgocXVhZHJpbGF0ZXJhbCwgaW5kZXgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsaW5rRWxlbWVudCA9IGluZGV4ID09PSAwID8gbGluayA6IGxpbmsuY2xvbmVOb2RlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcXVhZHJpbGF0ZXJhbC5hcHBlbmQobGlua0VsZW1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBxdWFkcmlsYXRlcmFsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250YWluZXIuY2xhc3NMaXN0LmFkZCgibGlua0Fubm90YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzQm91bmQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmFwcGVuZChsaW5rKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb250YWluZXI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9iaW5kTGluayhsaW5rLCBkZXN0aW5hdGlvbikgewogICAgICAgICAgICAgICAgICAgICAgICBsaW5rLmhyZWYgPSB0aGlzLmxpbmtTZXJ2aWNlLmdldERlc3RpbmF0aW9uSGFzaChkZXN0aW5hdGlvbik7CiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmsub25jbGljayA9ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkZXN0aW5hdGlvbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGlua1NlcnZpY2UuZ29Ub0Rlc3RpbmF0aW9uKGRlc3RpbmF0aW9uKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRlc3RpbmF0aW9uIHx8IGRlc3RpbmF0aW9uID09PSAiIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfc2V0SW50ZXJuYWxMaW5rLCBfc2V0SW50ZXJuYWxMaW5rMikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfYmluZE5hbWVkQWN0aW9uKGxpbmssIGFjdGlvbikgewogICAgICAgICAgICAgICAgICAgICAgICBsaW5rLmhyZWYgPSB0aGlzLmxpbmtTZXJ2aWNlLmdldEFuY2hvclVybCgiIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmsub25jbGljayA9ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGlua1NlcnZpY2UuZXhlY3V0ZU5hbWVkQWN0aW9uKGFjdGlvbik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3NldEludGVybmFsTGluaywgX3NldEludGVybmFsTGluazIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9iaW5kQXR0YWNobWVudChsaW5rLCBhdHRhY2htZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmsuaHJlZiA9IHRoaXMubGlua1NlcnZpY2UuZ2V0QW5jaG9yVXJsKCIiKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGluay5vbmNsaWNrID0gKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJGRvd25sb2FkTWFuYWdlcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRkb3dubG9hZE1hbmFnZXIgPSB0aGlzLmRvd25sb2FkTWFuYWdlcikgPT09IG51bGwgfHwgX3RoaXMkZG93bmxvYWRNYW5hZ2VyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRkb3dubG9hZE1hbmFnZXIub3Blbk9yRG93bmxvYWREYXRhKHRoaXMuY29udGFpbmVyLCBhdHRhY2htZW50LmNvbnRlbnQsIGF0dGFjaG1lbnQuZmlsZW5hbWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NQcml2YXRlTWV0aG9kR2V0KHRoaXMsIF9zZXRJbnRlcm5hbExpbmssIF9zZXRJbnRlcm5hbExpbmsyKS5jYWxsKHRoaXMpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfYmluZEpTQWN0aW9uKGxpbmssIGRhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGluay5ocmVmID0gdGhpcy5saW5rU2VydmljZS5nZXRBbmNob3JVcmwoIiIpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXAgPSBuZXcgTWFwKFtbIkFjdGlvbiIsICJvbmNsaWNrIl0sIFsiTW91c2UgVXAiLCAib25tb3VzZXVwIl0sIFsiTW91c2UgRG93biIsICJvbm1vdXNlZG93biJdXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyhkYXRhLmFjdGlvbnMpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBqc05hbWUgPSBtYXAuZ2V0KG5hbWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFqc05hbWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmtbanNOYW1lXSA9ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkbGlua1NlcnZpY2UkZXZlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRsaW5rU2VydmljZSRldmUgPSB0aGlzLmxpbmtTZXJ2aWNlLmV2ZW50QnVzKSA9PT0gbnVsbCB8fCBfdGhpcyRsaW5rU2VydmljZSRldmUgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJGxpbmtTZXJ2aWNlJGV2ZS5kaXNwYXRjaCgiZGlzcGF0Y2hldmVudGluc2FuZGJveCIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlOiB0aGlzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXRhaWw6IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkOiBkYXRhLmlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWxpbmsub25jbGljaykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluay5vbmNsaWNrID0gKCkgPT4gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzUHJpdmF0ZU1ldGhvZEdldCh0aGlzLCBfc2V0SW50ZXJuYWxMaW5rLCBfc2V0SW50ZXJuYWxMaW5rMikuY2FsbCh0aGlzKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX2JpbmRSZXNldEZvcm1BY3Rpb24obGluaywgcmVzZXRGb3JtKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG90aGVyQ2xpY2tBY3Rpb24gPSBsaW5rLm9uY2xpY2s7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghb3RoZXJDbGlja0FjdGlvbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluay5ocmVmID0gdGhpcy5saW5rU2VydmljZS5nZXRBbmNob3JVcmwoIiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3NldEludGVybmFsTGluaywgX3NldEludGVybmFsTGluazIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5fZmllbGRPYmplY3RzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYF9iaW5kUmVzZXRGb3JtQWN0aW9uIC0gInJlc2V0Rm9ybSIgYWN0aW9uIG5vdCBzdXBwb3J0ZWQsIGAgKyAiZW5zdXJlIHRoYXQgdGhlIGBmaWVsZE9iamVjdHNgIHBhcmFtZXRlciBpcyBwcm92aWRlZC4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghb3RoZXJDbGlja0FjdGlvbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmsub25jbGljayA9ICgpID0+IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmsub25jbGljayA9ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG90aGVyQ2xpY2tBY3Rpb24gPT09IG51bGwgfHwgb3RoZXJDbGlja0FjdGlvbiA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3RoZXJDbGlja0FjdGlvbigpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkczogcmVzZXRGb3JtRmllbGRzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZnM6IHJlc2V0Rm9ybVJlZnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHJlc2V0Rm9ybTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFsbEZpZWxkcyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlc2V0Rm9ybUZpZWxkcy5sZW5ndGggIT09IDAgfHwgcmVzZXRGb3JtUmVmcy5sZW5ndGggIT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWVsZElkcyA9IG5ldyBTZXQocmVzZXRGb3JtUmVmcyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBmaWVsZE5hbWUgb2YgcmVzZXRGb3JtRmllbGRzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpZWxkcyA9IHRoaXMuX2ZpZWxkT2JqZWN0c1tmaWVsZE5hbWVdIHx8IFtdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gb2YgZmllbGRzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZElkcy5hZGQoaWQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZmllbGRzIG9mIE9iamVjdC52YWx1ZXModGhpcy5fZmllbGRPYmplY3RzKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIGZpZWxkcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpZWxkSWRzLmhhcyhmaWVsZC5pZCkgPT09IGluY2x1ZGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxGaWVsZHMucHVzaChmaWVsZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZmllbGRzIG9mIE9iamVjdC52YWx1ZXModGhpcy5fZmllbGRPYmplY3RzKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxGaWVsZHMucHVzaCguLi5maWVsZHMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0b3JhZ2UgPSB0aGlzLmFubm90YXRpb25TdG9yYWdlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYWxsSWRzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIGFsbEZpZWxkcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gZmllbGQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsSWRzLnB1c2goaWQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZmllbGQudHlwZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJ0ZXh0IjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBmaWVsZC5kZWZhdWx0VmFsdWUgfHwgIiI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9yYWdlLnNldFZhbHVlKGlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiY2hlY2tib3giOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJyYWRpb2J1dHRvbiI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gZmllbGQuZGVmYXVsdFZhbHVlID09PSBmaWVsZC5leHBvcnRWYWx1ZXM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9yYWdlLnNldFZhbHVlKGlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiY29tYm9ib3giOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJsaXN0Ym94IjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBmaWVsZC5kZWZhdWx0VmFsdWUgfHwgIiI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9yYWdlLnNldFZhbHVlKGlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihgW2RhdGEtZWxlbWVudC1pZD0iJHtpZH0iXWApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZG9tRWxlbWVudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFHZXRFbGVtZW50c0J5TmFtZVNldC5oYXMoZG9tRWxlbWVudCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBfYmluZFJlc2V0Rm9ybUFjdGlvbiAtIGVsZW1lbnQgbm90IGFsbG93ZWQ6ICR7aWR9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb21FbGVtZW50LmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCJyZXNldGZvcm0iKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5lbmFibGVTY3JpcHRpbmcpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkbGlua1NlcnZpY2UkZXZlMjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkbGlua1NlcnZpY2UkZXZlMiA9IHRoaXMubGlua1NlcnZpY2UuZXZlbnRCdXMpID09PSBudWxsIHx8IF90aGlzJGxpbmtTZXJ2aWNlJGV2ZTIgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJGxpbmtTZXJ2aWNlJGV2ZTIuZGlzcGF0Y2goImRpc3BhdGNoZXZlbnRpbnNhbmRib3giLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZTogdGhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV0YWlsOiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZDogImFwcCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZHM6IGFsbElkcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICJSZXNldEZvcm0iCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfc2V0SW50ZXJuYWxMaW5rMigpIHsKICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5zZXRBdHRyaWJ1dGUoImRhdGEtaW50ZXJuYWwtbGluayIsICIiKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGZ1bmN0aW9uIF9iaW5kU2V0T0NHU3RhdGUyKGxpbmssIGFjdGlvbikgewogICAgICAgICAgICAgICAgICAgIGxpbmsuaHJlZiA9IHRoaXMubGlua1NlcnZpY2UuZ2V0QW5jaG9yVXJsKCIiKTsKICAgICAgICAgICAgICAgICAgICBsaW5rLm9uY2xpY2sgPSAoKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGlua1NlcnZpY2UuZXhlY3V0ZVNldE9DR1N0YXRlKGFjdGlvbik7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIF9jbGFzc1ByaXZhdGVNZXRob2RHZXQodGhpcywgX3NldEludGVybmFsTGluaywgX3NldEludGVybmFsTGluazIpLmNhbGwodGhpcyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBUZXh0QW5ub3RhdGlvbkVsZW1lbnQgZXh0ZW5kcyBBbm5vdGF0aW9uRWxlbWVudCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3BhcmFtZXRlcnMkZGF0YSR0aXRsLCBfcGFyYW1ldGVycyRkYXRhJGNvbnQsIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNSZW5kZXJhYmxlID0gISEocGFyYW1ldGVycy5kYXRhLmhhc1BvcHVwIHx8IChfcGFyYW1ldGVycyRkYXRhJHRpdGwgPSBwYXJhbWV0ZXJzLmRhdGEudGl0bGVPYmopICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bCAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bC5zdHIgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkY29udCA9IHBhcmFtZXRlcnMuZGF0YS5jb250ZW50c09iaikgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSRjb250ICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSRjb250LnN0ciB8fCAoX3BhcmFtZXRlcnMkZGF0YSRyaWNoID0gcGFyYW1ldGVycy5kYXRhLnJpY2hUZXh0KSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJHJpY2ggIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJHJpY2guc3RyKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIocGFyYW1ldGVycywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNSZW5kZXJhYmxlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZW5kZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoInRleHRBbm5vdGF0aW9uIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGltYWdlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiaW1nIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGltYWdlLnNyYyA9IHRoaXMuaW1hZ2VSZXNvdXJjZXNQYXRoICsgImFubm90YXRpb24tIiArIHRoaXMuZGF0YS5uYW1lLnRvTG93ZXJDYXNlKCkgKyAiLnN2ZyI7CiAgICAgICAgICAgICAgICAgICAgICAgIGltYWdlLmFsdCA9ICJbe3t0eXBlfX0gQW5ub3RhdGlvbl0iOwogICAgICAgICAgICAgICAgICAgICAgICBpbWFnZS5kYXRhc2V0LmwxMG5JZCA9ICJ0ZXh0X2Fubm90YXRpb25fdHlwZSI7CiAgICAgICAgICAgICAgICAgICAgICAgIGltYWdlLmRhdGFzZXQubDEwbkFyZ3MgPSBKU09OLnN0cmluZ2lmeSh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiB0aGlzLmRhdGEubmFtZQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmRhdGEuaGFzUG9wdXApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZVBvcHVwKGltYWdlLCB0aGlzLmRhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmFwcGVuZChpbWFnZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRhaW5lcjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBXaWRnZXRBbm5vdGF0aW9uRWxlbWVudCBleHRlbmRzIEFubm90YXRpb25FbGVtZW50IHsKICAgICAgICAgICAgICAgICAgICByZW5kZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRhdGEuYWx0ZXJuYXRpdmVUZXh0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci50aXRsZSA9IHRoaXMuZGF0YS5hbHRlcm5hdGl2ZVRleHQ7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfZ2V0S2V5TW9kaWZpZXIoZXZlbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNXaW4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc01hYwogICAgICAgICAgICAgICAgICAgICAgICB9ID0gX3V0aWwuRmVhdHVyZVRlc3QucGxhdGZvcm07CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpc1dpbiAmJiBldmVudC5jdHJsS2V5IHx8IGlzTWFjICYmIGV2ZW50Lm1ldGFLZXk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9zZXRFdmVudExpc3RlbmVyKGVsZW1lbnQsIGJhc2VOYW1lLCBldmVudE5hbWUsIHZhbHVlR2V0dGVyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiYXNlTmFtZS5pbmNsdWRlcygibW91c2UiKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGJhc2VOYW1lLCBldmVudCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJGxpbmtTZXJ2aWNlJGV2ZTM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJGxpbmtTZXJ2aWNlJGV2ZTMgPSB0aGlzLmxpbmtTZXJ2aWNlLmV2ZW50QnVzKSA9PT0gbnVsbCB8fCBfdGhpcyRsaW5rU2VydmljZSRldmUzID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRsaW5rU2VydmljZSRldmUzLmRpc3BhdGNoKCJkaXNwYXRjaGV2ZW50aW5zYW5kYm94IiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2U6IHRoaXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldGFpbDogewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IHRoaXMuZGF0YS5pZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IGV2ZW50TmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZUdldHRlcihldmVudCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaGlmdDogZXZlbnQuc2hpZnRLZXksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RpZmllcjogdGhpcy5fZ2V0S2V5TW9kaWZpZXIoZXZlbnQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGJhc2VOYW1lLCBldmVudCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJGxpbmtTZXJ2aWNlJGV2ZTQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJGxpbmtTZXJ2aWNlJGV2ZTQgPSB0aGlzLmxpbmtTZXJ2aWNlLmV2ZW50QnVzKSA9PT0gbnVsbCB8fCBfdGhpcyRsaW5rU2VydmljZSRldmU0ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRsaW5rU2VydmljZSRldmU0LmRpc3BhdGNoKCJkaXNwYXRjaGV2ZW50aW5zYW5kYm94IiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2U6IHRoaXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldGFpbDogewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IHRoaXMuZGF0YS5pZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IGV2ZW50TmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZUdldHRlcihldmVudCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX3NldEV2ZW50TGlzdGVuZXJzKGVsZW1lbnQsIG5hbWVzLCBnZXR0ZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBbYmFzZU5hbWUsIGV2ZW50TmFtZV0gb2YgbmFtZXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRkYXRhJGFjdGlvbnM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXZlbnROYW1lID09PSAiQWN0aW9uIiB8fCAoX3RoaXMkZGF0YSRhY3Rpb25zID0gdGhpcy5kYXRhLmFjdGlvbnMpICE9PSBudWxsICYmIF90aGlzJGRhdGEkYWN0aW9ucyAhPT0gdm9pZCAwICYmIF90aGlzJGRhdGEkYWN0aW9uc1tldmVudE5hbWVdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0RXZlbnRMaXN0ZW5lcihlbGVtZW50LCBiYXNlTmFtZSwgZXZlbnROYW1lLCBnZXR0ZXIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9zZXRCYWNrZ3JvdW5kQ29sb3IoZWxlbWVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb2xvciA9IHRoaXMuZGF0YS5iYWNrZ3JvdW5kQ29sb3IgfHwgbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBjb2xvciA9PT0gbnVsbCA/ICJ0cmFuc3BhcmVudCIgOiBfdXRpbC5VdGlsLm1ha2VIZXhDb2xvcihjb2xvclswXSwgY29sb3JbMV0sIGNvbG9yWzJdKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX3NldFRleHRTdHlsZShlbGVtZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFRFWFRfQUxJR05NRU5UID0gWyJsZWZ0IiwgImNlbnRlciIsICJyaWdodCJdOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb250Q29sb3IKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGE7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvbnRTaXplID0gdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YS5mb250U2l6ZSB8fCBERUZBVUxUX0ZPTlRfU0laRTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3R5bGUgPSBlbGVtZW50LnN0eWxlOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgY29tcHV0ZWRGb250U2l6ZTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgQk9SREVSX1NJWkUgPSAyOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByb3VuZFRvT25lRGVjaW1hbCA9IHggPT4gTWF0aC5yb3VuZCgxMCAqIHgpIC8gMTA7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRhdGEubXVsdGlMaW5lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBNYXRoLmFicyh0aGlzLmRhdGEucmVjdFszXSAtIHRoaXMuZGF0YS5yZWN0WzFdIC0gQk9SREVSX1NJWkUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbnVtYmVyT2ZMaW5lcyA9IE1hdGgucm91bmQoaGVpZ2h0IC8gKF91dGlsLkxJTkVfRkFDVE9SICogZm9udFNpemUpKSB8fCAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbGluZUhlaWdodCA9IGhlaWdodCAvIG51bWJlck9mTGluZXM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21wdXRlZEZvbnRTaXplID0gTWF0aC5taW4oZm9udFNpemUsIHJvdW5kVG9PbmVEZWNpbWFsKGxpbmVIZWlnaHQgLyBfdXRpbC5MSU5FX0ZBQ1RPUikpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gTWF0aC5hYnModGhpcy5kYXRhLnJlY3RbM10gLSB0aGlzLmRhdGEucmVjdFsxXSAtIEJPUkRFUl9TSVpFKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXB1dGVkRm9udFNpemUgPSBNYXRoLm1pbihmb250U2l6ZSwgcm91bmRUb09uZURlY2ltYWwoaGVpZ2h0IC8gX3V0aWwuTElORV9GQUNUT1IpKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBzdHlsZS5mb250U2l6ZSA9IGBjYWxjKCR7Y29tcHV0ZWRGb250U2l6ZX1weCAqIHZhcigtLXNjYWxlLWZhY3RvcikpYDsKICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGUuY29sb3IgPSBfdXRpbC5VdGlsLm1ha2VIZXhDb2xvcihmb250Q29sb3JbMF0sIGZvbnRDb2xvclsxXSwgZm9udENvbG9yWzJdKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGF0YS50ZXh0QWxpZ25tZW50ICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHlsZS50ZXh0QWxpZ24gPSBURVhUX0FMSUdOTUVOVFt0aGlzLmRhdGEudGV4dEFsaWdubWVudF07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgX3NldFJlcXVpcmVkKGVsZW1lbnQsIGlzUmVxdWlyZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzUmVxdWlyZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCJyZXF1aXJlZCIsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoInJlcXVpcmVkIik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoImFyaWEtcmVxdWlyZWQiLCBpc1JlcXVpcmVkKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBUZXh0V2lkZ2V0QW5ub3RhdGlvbkVsZW1lbnQgZXh0ZW5kcyBXaWRnZXRBbm5vdGF0aW9uRWxlbWVudCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpc1JlbmRlcmFibGUgPSBwYXJhbWV0ZXJzLnJlbmRlckZvcm1zIHx8ICFwYXJhbWV0ZXJzLmRhdGEuaGFzQXBwZWFyYW5jZSAmJiAhIXBhcmFtZXRlcnMuZGF0YS5maWVsZFZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICBzdXBlcihwYXJhbWV0ZXJzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1JlbmRlcmFibGUKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHNldFByb3BlcnR5T25TaWJsaW5ncyhiYXNlLCBrZXksIHZhbHVlLCBrZXlJblN0b3JhZ2UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RvcmFnZSA9IHRoaXMuYW5ub3RhdGlvblN0b3JhZ2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiB0aGlzLl9nZXRFbGVtZW50c0J5TmFtZShiYXNlLm5hbWUsIGJhc2UuaWQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC5kb21FbGVtZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5kb21FbGVtZW50W2tleV0gPSB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JhZ2Uuc2V0VmFsdWUoZWxlbWVudC5pZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtrZXlJblN0b3JhZ2VdOiB2YWx1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVuZGVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdG9yYWdlID0gdGhpcy5hbm5vdGF0aW9uU3RvcmFnZTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaWQgPSB0aGlzLmRhdGEuaWQ7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoInRleHRXaWRnZXRBbm5vdGF0aW9uIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlbGVtZW50ID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucmVuZGVyRm9ybXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0b3JlZERhdGEgPSBzdG9yYWdlLmdldFZhbHVlKGlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuZGF0YS5maWVsZFZhbHVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCB0ZXh0Q29udGVudCA9IHN0b3JlZERhdGEuZm9ybWF0dGVkVmFsdWUgfHwgc3RvcmVkRGF0YS52YWx1ZSB8fCAiIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1heExlbiA9IHN0b3JhZ2UuZ2V0VmFsdWUoaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFyTGltaXQ6IHRoaXMuZGF0YS5tYXhMZW4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLmNoYXJMaW1pdDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXhMZW4gJiYgdGV4dENvbnRlbnQubGVuZ3RoID4gbWF4TGVuKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dENvbnRlbnQgPSB0ZXh0Q29udGVudC5zbGljZSgwLCBtYXhMZW4pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZWxlbWVudERhdGEgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlclZhbHVlOiB0ZXh0Q29udGVudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZWRWYWx1ZTogbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0Q29tbWl0dGVkVmFsdWU6IG51bGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tbWl0S2V5OiAxCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGF0YS5tdWx0aUxpbmUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgidGV4dGFyZWEiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnRleHRDb250ZW50ID0gdGV4dENvbnRlbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZGF0YS5kb05vdFNjcm9sbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnN0eWxlLm92ZXJmbG93WSA9ICJoaWRkZW4iOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImlucHV0Iik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC50eXBlID0gInRleHQiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCJ2YWx1ZSIsIHRleHRDb250ZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kYXRhLmRvTm90U2Nyb2xsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc3R5bGUub3ZlcmZsb3dYID0gImhpZGRlbiI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgR2V0RWxlbWVudHNCeU5hbWVTZXQuYWRkKGVsZW1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoImRhdGEtZWxlbWVudC1pZCIsIGlkKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuZGlzYWJsZWQgPSB0aGlzLmRhdGEucmVhZE9ubHk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50Lm5hbWUgPSB0aGlzLmRhdGEuZmllbGROYW1lOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC50YWJJbmRleCA9IERFRkFVTFRfVEFCX0lOREVYOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0UmVxdWlyZWQoZWxlbWVudCwgdGhpcy5kYXRhLnJlcXVpcmVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXhMZW4pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50Lm1heExlbmd0aCA9IG1heExlbjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigiaW5wdXQiLCBldmVudCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmFnZS5zZXRWYWx1ZShpZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZXZlbnQudGFyZ2V0LnZhbHVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRQcm9wZXJ0eU9uU2libGluZ3MoZWxlbWVudCwgInZhbHVlIiwgZXZlbnQudGFyZ2V0LnZhbHVlLCAidmFsdWUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCJyZXNldGZvcm0iLCBldmVudCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVmYXVsdFZhbHVlID0gdGhpcy5kYXRhLmRlZmF1bHRGaWVsZFZhbHVlID8/ICIiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQudmFsdWUgPSBlbGVtZW50RGF0YS51c2VyVmFsdWUgPSBkZWZhdWx0VmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudERhdGEuZm9ybWF0dGVkVmFsdWUgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgYmx1ckxpc3RlbmVyID0gZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0dGVkVmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gZWxlbWVudERhdGE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZvcm1hdHRlZFZhbHVlICE9PSBudWxsICYmIGZvcm1hdHRlZFZhbHVlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQudGFyZ2V0LnZhbHVlID0gZm9ybWF0dGVkVmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnRhcmdldC5zY3JvbGxMZWZ0ID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5lbmFibGVTY3JpcHRpbmcgJiYgdGhpcy5oYXNKU0FjdGlvbnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkZGF0YSRhY3Rpb25zMjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoImZvY3VzIiwgZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGV2ZW50OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudERhdGEudXNlclZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQudmFsdWUgPSBlbGVtZW50RGF0YS51c2VyVmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudERhdGEubGFzdENvbW1pdHRlZFZhbHVlID0gdGFyZ2V0LnZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50RGF0YS5jb21taXRLZXkgPSAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigidXBkYXRlZnJvbXNhbmRib3giLCBqc0V2ZW50ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYWN0aW9ucyA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudERhdGEudXNlclZhbHVlID0gZXZlbnQuZGV0YWlsLnZhbHVlID8/ICIiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JhZ2Uuc2V0VmFsdWUoaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGVsZW1lbnREYXRhLnVzZXJWYWx1ZS50b1N0cmluZygpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQudGFyZ2V0LnZhbHVlID0gZWxlbWVudERhdGEudXNlclZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1hdHRlZFZhbHVlKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZWRWYWx1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBldmVudC5kZXRhaWw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudERhdGEuZm9ybWF0dGVkVmFsdWUgPSBmb3JtYXR0ZWRWYWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm9ybWF0dGVkVmFsdWUgIT09IG51bGwgJiYgZm9ybWF0dGVkVmFsdWUgIT09IHVuZGVmaW5lZCAmJiBldmVudC50YXJnZXQgIT09IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQudGFyZ2V0LnZhbHVlID0gZm9ybWF0dGVkVmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JhZ2Uuc2V0VmFsdWUoaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0dGVkVmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxSYW5nZShldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnRhcmdldC5zZXRTZWxlY3Rpb25SYW5nZSguLi5ldmVudC5kZXRhaWwuc2VsUmFuZ2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXJMaW1pdDogZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRsaW5rU2VydmljZSRldmU1OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhckxpbWl0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGV2ZW50LmRldGFpbDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBldmVudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hhckxpbWl0ID09PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldC5yZW1vdmVBdHRyaWJ1dGUoIm1heExlbmd0aCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldC5zZXRBdHRyaWJ1dGUoIm1heExlbmd0aCIsIGNoYXJMaW1pdCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHZhbHVlID0gZWxlbWVudERhdGEudXNlclZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdmFsdWUgfHwgdmFsdWUubGVuZ3RoIDw9IGNoYXJMaW1pdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc2xpY2UoMCwgY2hhckxpbWl0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQudmFsdWUgPSBlbGVtZW50RGF0YS51c2VyVmFsdWUgPSB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9yYWdlLnNldFZhbHVlKGlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJGxpbmtTZXJ2aWNlJGV2ZTUgPSB0aGlzLmxpbmtTZXJ2aWNlLmV2ZW50QnVzKSA9PT0gbnVsbCB8fCBfdGhpcyRsaW5rU2VydmljZSRldmU1ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRsaW5rU2VydmljZSRldmU1LmRpc3BhdGNoKCJkaXNwYXRjaGV2ZW50aW5zYW5kYm94IiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2U6IHRoaXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldGFpbDogewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAiS2V5c3Ryb2tlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lsbENvbW1pdDogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbW1pdEtleTogMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbFN0YXJ0OiB0YXJnZXQuc2VsZWN0aW9uU3RhcnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxFbmQ6IHRhcmdldC5zZWxlY3Rpb25FbmQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9kaXNwYXRjaEV2ZW50RnJvbVNhbmRib3goYWN0aW9ucywganNFdmVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCJrZXlkb3duIiwgZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkbGlua1NlcnZpY2UkZXZlNjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudERhdGEuY29tbWl0S2V5ID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvbW1pdEtleSA9IC0xOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXZlbnQua2V5ID09PSAiRXNjYXBlIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tbWl0S2V5ID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChldmVudC5rZXkgPT09ICJFbnRlciIgJiYgIXRoaXMuZGF0YS5tdWx0aUxpbmUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbW1pdEtleSA9IDI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZXZlbnQua2V5ID09PSAiVGFiIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudERhdGEuY29tbWl0S2V5ID0gMzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29tbWl0S2V5ID09PSAtMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBldmVudC50YXJnZXQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50RGF0YS5sYXN0Q29tbWl0dGVkVmFsdWUgPT09IHZhbHVlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudERhdGEubGFzdENvbW1pdHRlZFZhbHVlID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnREYXRhLnVzZXJWYWx1ZSA9IHZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkbGlua1NlcnZpY2UkZXZlNiA9IHRoaXMubGlua1NlcnZpY2UuZXZlbnRCdXMpID09PSBudWxsIHx8IF90aGlzJGxpbmtTZXJ2aWNlJGV2ZTYgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF90aGlzJGxpbmtTZXJ2aWNlJGV2ZTYuZGlzcGF0Y2goImRpc3BhdGNoZXZlbnRpbnNhbmRib3giLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2U6IHRoaXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXRhaWw6IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAiS2V5c3Ryb2tlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWxsQ29tbWl0OiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbW1pdEtleSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxTdGFydDogZXZlbnQudGFyZ2V0LnNlbGVjdGlvblN0YXJ0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbEVuZDogZXZlbnQudGFyZ2V0LnNlbGVjdGlvbkVuZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBfYmx1ckxpc3RlbmVyID0gYmx1ckxpc3RlbmVyOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJsdXJMaXN0ZW5lciA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCJibHVyIiwgZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWV2ZW50LnJlbGF0ZWRUYXJnZXQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gZXZlbnQudGFyZ2V0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50RGF0YS51c2VyVmFsdWUgPSB2YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnREYXRhLmxhc3RDb21taXR0ZWRWYWx1ZSAhPT0gdmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRsaW5rU2VydmljZSRldmU3OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJGxpbmtTZXJ2aWNlJGV2ZTcgPSB0aGlzLmxpbmtTZXJ2aWNlLmV2ZW50QnVzKSA9PT0gbnVsbCB8fCBfdGhpcyRsaW5rU2VydmljZSRldmU3ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRsaW5rU2VydmljZSRldmU3LmRpc3BhdGNoKCJkaXNwYXRjaGV2ZW50aW5zYW5kYm94IiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZTogdGhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXRhaWw6IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICJLZXlzdHJva2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lsbENvbW1pdDogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tbWl0S2V5OiBlbGVtZW50RGF0YS5jb21taXRLZXksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbFN0YXJ0OiBldmVudC50YXJnZXQuc2VsZWN0aW9uU3RhcnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbEVuZDogZXZlbnQudGFyZ2V0LnNlbGVjdGlvbkVuZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9ibHVyTGlzdGVuZXIoZXZlbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoX3RoaXMkZGF0YSRhY3Rpb25zMiA9IHRoaXMuZGF0YS5hY3Rpb25zKSAhPT0gbnVsbCAmJiBfdGhpcyRkYXRhJGFjdGlvbnMyICE9PSB2b2lkIDAgJiYgX3RoaXMkZGF0YSRhY3Rpb25zMi5LZXlzdHJva2UpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCJiZWZvcmVpbnB1dCIsIGV2ZW50ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRsaW5rU2VydmljZSRldmU4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudERhdGEubGFzdENvbW1pdHRlZFZhbHVlID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGV2ZW50OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGlvblN0YXJ0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGlvbkVuZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRhcmdldDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzZWxTdGFydCA9IHNlbGVjdGlvblN0YXJ0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbEVuZCA9IHNlbGVjdGlvbkVuZDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZXZlbnQuaW5wdXRUeXBlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiZGVsZXRlV29yZEJhY2t3YXJkIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoID0gdmFsdWUuc3Vic3RyaW5nKDAsIHNlbGVjdGlvblN0YXJ0KS5tYXRjaCgvXHcqW15cd10qJC8pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbFN0YXJ0IC09IG1hdGNoWzBdLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiZGVsZXRlV29yZEZvcndhcmQiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWF0Y2ggPSB2YWx1ZS5zdWJzdHJpbmcoc2VsZWN0aW9uU3RhcnQpLm1hdGNoKC9eW15cd10qXHcqLyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsRW5kICs9IG1hdGNoWzBdLmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiZGVsZXRlQ29udGVudEJhY2t3YXJkIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGVjdGlvblN0YXJ0ID09PSBzZWxlY3Rpb25FbmQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbFN0YXJ0IC09IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiZGVsZXRlQ29udGVudEZvcndhcmQiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZWN0aW9uU3RhcnQgPT09IHNlbGVjdGlvbkVuZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsRW5kICs9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJGxpbmtTZXJ2aWNlJGV2ZTggPSB0aGlzLmxpbmtTZXJ2aWNlLmV2ZW50QnVzKSA9PT0gbnVsbCB8fCBfdGhpcyRsaW5rU2VydmljZSRldmU4ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRsaW5rU2VydmljZSRldmU4LmRpc3BhdGNoKCJkaXNwYXRjaGV2ZW50aW5zYW5kYm94IiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZTogdGhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXRhaWw6IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6ICJLZXlzdHJva2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhbmdlOiBkYXRhIHx8ICIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWxsQ29tbWl0OiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsU3RhcnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbEVuZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0RXZlbnRMaXN0ZW5lcnMoZWxlbWVudCwgW1siZm9jdXMiLCAiRm9jdXMiXSwgWyJibHVyIiwgIkJsdXIiXSwgWyJtb3VzZWRvd24iLCAiTW91c2UgRG93biJdLCBbIm1vdXNlZW50ZXIiLCAiTW91c2UgRW50ZXIiXSwgWyJtb3VzZWxlYXZlIiwgIk1vdXNlIEV4aXQiXSwgWyJtb3VzZXVwIiwgIk1vdXNlIFVwIl1dLCBldmVudCA9PiBldmVudC50YXJnZXQudmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJsdXJMaXN0ZW5lcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigiYmx1ciIsIGJsdXJMaXN0ZW5lcik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kYXRhLmNvbWIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWVsZFdpZHRoID0gdGhpcy5kYXRhLnJlY3RbMl0gLSB0aGlzLmRhdGEucmVjdFswXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb21iV2lkdGggPSBmaWVsZFdpZHRoIC8gbWF4TGVuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZCgiY29tYiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc3R5bGUubGV0dGVyU3BhY2luZyA9IGBjYWxjKCR7Y29tYldpZHRofXB4ICogdmFyKC0tc2NhbGUtZmFjdG9yKSAtIDFjaClgOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC50ZXh0Q29udGVudCA9IHRoaXMuZGF0YS5maWVsZFZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zdHlsZS52ZXJ0aWNhbEFsaWduID0gIm1pZGRsZSI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAidGFibGUtY2VsbCI7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0VGV4dFN0eWxlKGVsZW1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRCYWNrZ3JvdW5kQ29sb3IoZWxlbWVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldERlZmF1bHRQcm9wZXJ0aWVzRnJvbUpTKGVsZW1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5hcHBlbmQoZWxlbWVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRhaW5lcjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBDaGVja2JveFdpZGdldEFubm90YXRpb25FbGVtZW50IGV4dGVuZHMgV2lkZ2V0QW5ub3RhdGlvbkVsZW1lbnQgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHBhcmFtZXRlcnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIocGFyYW1ldGVycywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNSZW5kZXJhYmxlOiBwYXJhbWV0ZXJzLnJlbmRlckZvcm1zCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZW5kZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0b3JhZ2UgPSB0aGlzLmFubm90YXRpb25TdG9yYWdlOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gdGhpcy5kYXRhOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpZCA9IGRhdGEuaWQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB2YWx1ZSA9IHN0b3JhZ2UuZ2V0VmFsdWUoaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBkYXRhLmV4cG9ydFZhbHVlID09PSBkYXRhLmZpZWxkVmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgfSkudmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlICE9PSAiT2ZmIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JhZ2Uuc2V0VmFsdWUoaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250YWluZXIuY2xhc3NMaXN0LmFkZCgiYnV0dG9uV2lkZ2V0QW5ub3RhdGlvbiIsICJjaGVja0JveCIpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiaW5wdXQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgR2V0RWxlbWVudHNCeU5hbWVTZXQuYWRkKGVsZW1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgiZGF0YS1lbGVtZW50LWlkIiwgaWQpOwogICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmRpc2FibGVkID0gZGF0YS5yZWFkT25seTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0UmVxdWlyZWQoZWxlbWVudCwgdGhpcy5kYXRhLnJlcXVpcmVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC50eXBlID0gImNoZWNrYm94IjsKICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5uYW1lID0gZGF0YS5maWVsZE5hbWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoImNoZWNrZWQiLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgiZXhwb3J0VmFsdWUiLCBkYXRhLmV4cG9ydFZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC50YWJJbmRleCA9IERFRkFVTFRfVEFCX0lOREVYOwogICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoImNoYW5nZSIsIGV2ZW50ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrZWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBldmVudC50YXJnZXQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGNoZWNrYm94IG9mIHRoaXMuX2dldEVsZW1lbnRzQnlOYW1lKG5hbWUsIGlkKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1ckNoZWNrZWQgPSBjaGVja2VkICYmIGNoZWNrYm94LmV4cG9ydFZhbHVlID09PSBkYXRhLmV4cG9ydFZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGVja2JveC5kb21FbGVtZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoZWNrYm94LmRvbUVsZW1lbnQuY2hlY2tlZCA9IGN1ckNoZWNrZWQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JhZ2Uuc2V0VmFsdWUoY2hlY2tib3guaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGN1ckNoZWNrZWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JhZ2Uuc2V0VmFsdWUoaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogY2hlY2tlZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoInJlc2V0Zm9ybSIsIGV2ZW50ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IGRhdGEuZGVmYXVsdEZpZWxkVmFsdWUgfHwgIk9mZiI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudC50YXJnZXQuY2hlY2tlZCA9IGRlZmF1bHRWYWx1ZSA9PT0gZGF0YS5leHBvcnRWYWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmVuYWJsZVNjcmlwdGluZyAmJiB0aGlzLmhhc0pTQWN0aW9ucykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCJ1cGRhdGVmcm9tc2FuZGJveCIsIGpzRXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFjdGlvbnMgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudC50YXJnZXQuY2hlY2tlZCA9IGV2ZW50LmRldGFpbC52YWx1ZSAhPT0gIk9mZiI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9yYWdlLnNldFZhbHVlKGlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGV2ZW50LnRhcmdldC5jaGVja2VkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGlzcGF0Y2hFdmVudEZyb21TYW5kYm94KGFjdGlvbnMsIGpzRXZlbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRFdmVudExpc3RlbmVycyhlbGVtZW50LCBbWyJjaGFuZ2UiLCAiVmFsaWRhdGUiXSwgWyJjaGFuZ2UiLCAiQWN0aW9uIl0sIFsiZm9jdXMiLCAiRm9jdXMiXSwgWyJibHVyIiwgIkJsdXIiXSwgWyJtb3VzZWRvd24iLCAiTW91c2UgRG93biJdLCBbIm1vdXNlZW50ZXIiLCAiTW91c2UgRW50ZXIiXSwgWyJtb3VzZWxlYXZlIiwgIk1vdXNlIEV4aXQiXSwgWyJtb3VzZXVwIiwgIk1vdXNlIFVwIl1dLCBldmVudCA9PiBldmVudC50YXJnZXQuY2hlY2tlZCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0QmFja2dyb3VuZENvbG9yKGVsZW1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXREZWZhdWx0UHJvcGVydGllc0Zyb21KUyhlbGVtZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250YWluZXIuYXBwZW5kKGVsZW1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb250YWluZXI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgUmFkaW9CdXR0b25XaWRnZXRBbm5vdGF0aW9uRWxlbWVudCBleHRlbmRzIFdpZGdldEFubm90YXRpb25FbGVtZW50IHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihwYXJhbWV0ZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKHBhcmFtZXRlcnMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzUmVuZGVyYWJsZTogcGFyYW1ldGVycy5yZW5kZXJGb3JtcwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVuZGVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5jbGFzc0xpc3QuYWRkKCJidXR0b25XaWRnZXRBbm5vdGF0aW9uIiwgInJhZGlvQnV0dG9uIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0b3JhZ2UgPSB0aGlzLmFubm90YXRpb25TdG9yYWdlOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gdGhpcy5kYXRhOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpZCA9IGRhdGEuaWQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB2YWx1ZSA9IHN0b3JhZ2UuZ2V0VmFsdWUoaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBkYXRhLmZpZWxkVmFsdWUgPT09IGRhdGEuYnV0dG9uVmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgfSkudmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlICE9PSBkYXRhLmJ1dHRvblZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmFnZS5zZXRWYWx1ZShpZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiaW5wdXQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgR2V0RWxlbWVudHNCeU5hbWVTZXQuYWRkKGVsZW1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgiZGF0YS1lbGVtZW50LWlkIiwgaWQpOwogICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmRpc2FibGVkID0gZGF0YS5yZWFkT25seTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0UmVxdWlyZWQoZWxlbWVudCwgdGhpcy5kYXRhLnJlcXVpcmVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC50eXBlID0gInJhZGlvIjsKICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5uYW1lID0gZGF0YS5maWVsZE5hbWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoImNoZWNrZWQiLCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnRhYkluZGV4ID0gREVGQVVMVF9UQUJfSU5ERVg7CiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigiY2hhbmdlIiwgZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tlZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGV2ZW50LnRhcmdldDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcmFkaW8gb2YgdGhpcy5fZ2V0RWxlbWVudHNCeU5hbWUobmFtZSwgaWQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmFnZS5zZXRWYWx1ZShyYWRpby5pZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZmFsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JhZ2Uuc2V0VmFsdWUoaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogY2hlY2tlZAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoInJlc2V0Zm9ybSIsIGV2ZW50ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IGRhdGEuZGVmYXVsdEZpZWxkVmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudC50YXJnZXQuY2hlY2tlZCA9IGRlZmF1bHRWYWx1ZSAhPT0gbnVsbCAmJiBkZWZhdWx0VmFsdWUgIT09IHVuZGVmaW5lZCAmJiBkZWZhdWx0VmFsdWUgPT09IGRhdGEuYnV0dG9uVmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5lbmFibGVTY3JpcHRpbmcgJiYgdGhpcy5oYXNKU0FjdGlvbnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBkZkJ1dHRvblZhbHVlID0gZGF0YS5idXR0b25WYWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigidXBkYXRlZnJvbXNhbmRib3giLCBqc0V2ZW50ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhY3Rpb25zID0gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hlY2tlZCA9IHBkZkJ1dHRvblZhbHVlID09PSBldmVudC5kZXRhaWwudmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHJhZGlvIG9mIHRoaXMuX2dldEVsZW1lbnRzQnlOYW1lKGV2ZW50LnRhcmdldC5uYW1lKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1ckNoZWNrZWQgPSBjaGVja2VkICYmIHJhZGlvLmlkID09PSBpZDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmFkaW8uZG9tRWxlbWVudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYWRpby5kb21FbGVtZW50LmNoZWNrZWQgPSBjdXJDaGVja2VkOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9yYWdlLnNldFZhbHVlKHJhZGlvLmlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBjdXJDaGVja2VkCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Rpc3BhdGNoRXZlbnRGcm9tU2FuZGJveChhY3Rpb25zLCBqc0V2ZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0RXZlbnRMaXN0ZW5lcnMoZWxlbWVudCwgW1siY2hhbmdlIiwgIlZhbGlkYXRlIl0sIFsiY2hhbmdlIiwgIkFjdGlvbiJdLCBbImZvY3VzIiwgIkZvY3VzIl0sIFsiYmx1ciIsICJCbHVyIl0sIFsibW91c2Vkb3duIiwgIk1vdXNlIERvd24iXSwgWyJtb3VzZWVudGVyIiwgIk1vdXNlIEVudGVyIl0sIFsibW91c2VsZWF2ZSIsICJNb3VzZSBFeGl0Il0sIFsibW91c2V1cCIsICJNb3VzZSBVcCJdXSwgZXZlbnQgPT4gZXZlbnQudGFyZ2V0LmNoZWNrZWQpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldEJhY2tncm91bmRDb2xvcihlbGVtZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0RGVmYXVsdFByb3BlcnRpZXNGcm9tSlMoZWxlbWVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmFwcGVuZChlbGVtZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIFB1c2hCdXR0b25XaWRnZXRBbm5vdGF0aW9uRWxlbWVudCBleHRlbmRzIExpbmtBbm5vdGF0aW9uRWxlbWVudCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICBzdXBlcihwYXJhbWV0ZXJzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmVCb3JkZXI6IHBhcmFtZXRlcnMuZGF0YS5oYXNBcHBlYXJhbmNlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZW5kZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IHN1cGVyLnJlbmRlcigpOwogICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXIuY2xhc3NMaXN0LmFkZCgiYnV0dG9uV2lkZ2V0QW5ub3RhdGlvbiIsICJwdXNoQnV0dG9uIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRhdGEuYWx0ZXJuYXRpdmVUZXh0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXIudGl0bGUgPSB0aGlzLmRhdGEuYWx0ZXJuYXRpdmVUZXh0OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpbmtFbGVtZW50ID0gY29udGFpbmVyLmxhc3RDaGlsZDsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZW5hYmxlU2NyaXB0aW5nICYmIHRoaXMuaGFzSlNBY3Rpb25zICYmIGxpbmtFbGVtZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXREZWZhdWx0UHJvcGVydGllc0Zyb21KUyhsaW5rRWxlbWVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5rRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCJ1cGRhdGVmcm9tc2FuZGJveCIsIGpzRXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Rpc3BhdGNoRXZlbnRGcm9tU2FuZGJveCh7fSwganNFdmVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIENob2ljZVdpZGdldEFubm90YXRpb25FbGVtZW50IGV4dGVuZHMgV2lkZ2V0QW5ub3RhdGlvbkVsZW1lbnQgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHBhcmFtZXRlcnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIocGFyYW1ldGVycywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNSZW5kZXJhYmxlOiBwYXJhbWV0ZXJzLnJlbmRlckZvcm1zCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZW5kZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoImNob2ljZVdpZGdldEFubm90YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RvcmFnZSA9IHRoaXMuYW5ub3RhdGlvblN0b3JhZ2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkID0gdGhpcy5kYXRhLmlkOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdG9yZWREYXRhID0gc3RvcmFnZS5nZXRWYWx1ZShpZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuZGF0YS5maWVsZFZhbHVlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzZWxlY3RFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2VsZWN0Iik7CiAgICAgICAgICAgICAgICAgICAgICAgIEdldEVsZW1lbnRzQnlOYW1lU2V0LmFkZChzZWxlY3RFbGVtZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC5zZXRBdHRyaWJ1dGUoImRhdGEtZWxlbWVudC1pZCIsIGlkKTsKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC5kaXNhYmxlZCA9IHRoaXMuZGF0YS5yZWFkT25seTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0UmVxdWlyZWQoc2VsZWN0RWxlbWVudCwgdGhpcy5kYXRhLnJlcXVpcmVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC5uYW1lID0gdGhpcy5kYXRhLmZpZWxkTmFtZTsKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC50YWJJbmRleCA9IERFRkFVTFRfVEFCX0lOREVYOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgYWRkQW5FbXB0eUVudHJ5ID0gdGhpcy5kYXRhLmNvbWJvICYmIHRoaXMuZGF0YS5vcHRpb25zLmxlbmd0aCA+IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5kYXRhLmNvbWJvKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RFbGVtZW50LnNpemUgPSB0aGlzLmRhdGEub3B0aW9ucy5sZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kYXRhLm11bHRpU2VsZWN0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC5tdWx0aXBsZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCJyZXNldGZvcm0iLCBldmVudCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWZhdWx0VmFsdWUgPSB0aGlzLmRhdGEuZGVmYXVsdEZpZWxkVmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG9wdGlvbiBvZiBzZWxlY3RFbGVtZW50Lm9wdGlvbnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb24uc2VsZWN0ZWQgPSBvcHRpb24udmFsdWUgPT09IGRlZmF1bHRWYWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgb3B0aW9uIG9mIHRoaXMuZGF0YS5vcHRpb25zKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvcHRpb25FbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgib3B0aW9uIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25FbGVtZW50LnRleHRDb250ZW50ID0gb3B0aW9uLmRpc3BsYXlWYWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbkVsZW1lbnQudmFsdWUgPSBvcHRpb24uZXhwb3J0VmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RvcmVkRGF0YS52YWx1ZS5pbmNsdWRlcyhvcHRpb24uZXhwb3J0VmFsdWUpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uRWxlbWVudC5zZXRBdHRyaWJ1dGUoInNlbGVjdGVkIiwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWRkQW5FbXB0eUVudHJ5ID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RFbGVtZW50LmFwcGVuZChvcHRpb25FbGVtZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcmVtb3ZlRW1wdHlFbnRyeSA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhZGRBbkVtcHR5RW50cnkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5vbmVPcHRpb25FbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgib3B0aW9uIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25lT3B0aW9uRWxlbWVudC52YWx1ZSA9ICIgIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbmVPcHRpb25FbGVtZW50LnNldEF0dHJpYnV0ZSgiaGlkZGVuIiwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25lT3B0aW9uRWxlbWVudC5zZXRBdHRyaWJ1dGUoInNlbGVjdGVkIiwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RFbGVtZW50LnByZXBlbmQobm9uZU9wdGlvbkVsZW1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlRW1wdHlFbnRyeSA9ICgpID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25lT3B0aW9uRWxlbWVudC5yZW1vdmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoImlucHV0IiwgcmVtb3ZlRW1wdHlFbnRyeSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlRW1wdHlFbnRyeSA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCJpbnB1dCIsIHJlbW92ZUVtcHR5RW50cnkpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGdldFZhbHVlID0gaXNFeHBvcnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmFtZSA9IGlzRXhwb3J0ID8gInZhbHVlIiA6ICJ0ZXh0Q29udGVudCI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHNlbGVjdEVsZW1lbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW11bHRpcGxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMuc2VsZWN0ZWRJbmRleCA9PT0gLTEgPyBudWxsIDogb3B0aW9uc1tvcHRpb25zLnNlbGVjdGVkSW5kZXhdW25hbWVdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5maWx0ZXIuY2FsbChvcHRpb25zLCBvcHRpb24gPT4gb3B0aW9uLnNlbGVjdGVkKS5tYXAob3B0aW9uID0+IG9wdGlvbltuYW1lXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzZWxlY3RlZFZhbHVlcyA9IGdldFZhbHVlKGZhbHNlKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZ2V0SXRlbXMgPSBldmVudCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvcHRpb25zID0gZXZlbnQudGFyZ2V0Lm9wdGlvbnM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLm1hcC5jYWxsKG9wdGlvbnMsIG9wdGlvbiA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlzcGxheVZhbHVlOiBvcHRpb24udGV4dENvbnRlbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cG9ydFZhbHVlOiBvcHRpb24udmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmVuYWJsZVNjcmlwdGluZyAmJiB0aGlzLmhhc0pTQWN0aW9ucykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCJ1cGRhdGVmcm9tc2FuZGJveCIsIGpzRXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFjdGlvbnMgPSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3JlbW92ZUVtcHR5RW50cnk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoX3JlbW92ZUVtcHR5RW50cnkgPSByZW1vdmVFbXB0eUVudHJ5KSA9PT0gbnVsbCB8fCBfcmVtb3ZlRW1wdHlFbnRyeSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3JlbW92ZUVtcHR5RW50cnkoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gZXZlbnQuZGV0YWlsLnZhbHVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWVzID0gbmV3IFNldChBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlIDogW3ZhbHVlXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG9wdGlvbiBvZiBzZWxlY3RFbGVtZW50Lm9wdGlvbnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb24uc2VsZWN0ZWQgPSB2YWx1ZXMuaGFzKG9wdGlvbi52YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9yYWdlLnNldFZhbHVlKGlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGdldFZhbHVlKHRydWUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkVmFsdWVzID0gZ2V0VmFsdWUoZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXBsZVNlbGVjdGlvbihldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC5tdWx0aXBsZSA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZShldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHNlbGVjdEVsZW1lbnQub3B0aW9uczsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gZXZlbnQuZGV0YWlsLnJlbW92ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnNbaW5kZXhdLnNlbGVjdGVkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RFbGVtZW50LnJlbW92ZShpbmRleCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaSA9IEFycmF5LnByb3RvdHlwZS5maW5kSW5kZXguY2FsbChvcHRpb25zLCBvcHRpb24gPT4gb3B0aW9uLnNlbGVjdGVkKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaSA9PT0gLTEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uc1swXS5zZWxlY3RlZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmFnZS5zZXRWYWx1ZShpZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBnZXRWYWx1ZSh0cnVlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtczogZ2V0SXRlbXMoZXZlbnQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkVmFsdWVzID0gZ2V0VmFsdWUoZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGVhcihldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNlbGVjdEVsZW1lbnQubGVuZ3RoICE9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC5yZW1vdmUoMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9yYWdlLnNldFZhbHVlKGlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG51bGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbXM6IFtdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkVmFsdWVzID0gZ2V0VmFsdWUoZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnQoZXZlbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXNwbGF5VmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwb3J0VmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBldmVudC5kZXRhaWwuaW5zZXJ0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0Q2hpbGQgPSBzZWxlY3RFbGVtZW50LmNoaWxkcmVuW2luZGV4XTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9wdGlvbkVsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJvcHRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbkVsZW1lbnQudGV4dENvbnRlbnQgPSBkaXNwbGF5VmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25FbGVtZW50LnZhbHVlID0gZXhwb3J0VmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZWN0Q2hpbGQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RDaGlsZC5iZWZvcmUob3B0aW9uRWxlbWVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdEVsZW1lbnQuYXBwZW5kKG9wdGlvbkVsZW1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmFnZS5zZXRWYWx1ZShpZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBnZXRWYWx1ZSh0cnVlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtczogZ2V0SXRlbXMoZXZlbnQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkVmFsdWVzID0gZ2V0VmFsdWUoZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtcyhldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1zCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gZXZlbnQuZGV0YWlsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNlbGVjdEVsZW1lbnQubGVuZ3RoICE9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC5yZW1vdmUoMCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3BsYXlWYWx1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwb3J0VmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gaXRlbTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvcHRpb25FbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgib3B0aW9uIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9uRWxlbWVudC50ZXh0Q29udGVudCA9IGRpc3BsYXlWYWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25FbGVtZW50LnZhbHVlID0gZXhwb3J0VmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0RWxlbWVudC5hcHBlbmQob3B0aW9uRWxlbWVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZWN0RWxlbWVudC5vcHRpb25zLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RFbGVtZW50Lm9wdGlvbnNbMF0uc2VsZWN0ZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmFnZS5zZXRWYWx1ZShpZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBnZXRWYWx1ZSh0cnVlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtczogZ2V0SXRlbXMoZXZlbnQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkVmFsdWVzID0gZ2V0VmFsdWUoZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2VzKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbmRpY2VzID0gbmV3IFNldChldmVudC5kZXRhaWwuaW5kaWNlcyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG9wdGlvbiBvZiBldmVudC50YXJnZXQub3B0aW9ucykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbi5zZWxlY3RlZCA9IGluZGljZXMuaGFzKG9wdGlvbi5pbmRleCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9yYWdlLnNldFZhbHVlKGlkLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGdldFZhbHVlKHRydWUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdGVkVmFsdWVzID0gZ2V0VmFsdWUoZmFsc2UpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlZGl0YWJsZShldmVudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQudGFyZ2V0LmRpc2FibGVkID0gIWV2ZW50LmRldGFpbC5lZGl0YWJsZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGlzcGF0Y2hFdmVudEZyb21TYW5kYm94KGFjdGlvbnMsIGpzRXZlbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoImlucHV0IiwgZXZlbnQgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRsaW5rU2VydmljZSRldmU5OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4cG9ydFZhbHVlID0gZ2V0VmFsdWUodHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmFnZS5zZXRWYWx1ZShpZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZXhwb3J0VmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRsaW5rU2VydmljZSRldmU5ID0gdGhpcy5saW5rU2VydmljZS5ldmVudEJ1cykgPT09IG51bGwgfHwgX3RoaXMkbGlua1NlcnZpY2UkZXZlOSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkbGlua1NlcnZpY2UkZXZlOS5kaXNwYXRjaCgiZGlzcGF0Y2hldmVudGluc2FuZGJveCIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlOiB0aGlzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXRhaWw6IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogIktleXN0cm9rZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogc2VsZWN0ZWRWYWx1ZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGFuZ2VFeDogZXhwb3J0VmFsdWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWxsQ29tbWl0OiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbW1pdEtleTogMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleURvd246IGZhbHNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0RXZlbnRMaXN0ZW5lcnMoc2VsZWN0RWxlbWVudCwgW1siZm9jdXMiLCAiRm9jdXMiXSwgWyJibHVyIiwgIkJsdXIiXSwgWyJtb3VzZWRvd24iLCAiTW91c2UgRG93biJdLCBbIm1vdXNlZW50ZXIiLCAiTW91c2UgRW50ZXIiXSwgWyJtb3VzZWxlYXZlIiwgIk1vdXNlIEV4aXQiXSwgWyJtb3VzZXVwIiwgIk1vdXNlIFVwIl0sIFsiaW5wdXQiLCAiQWN0aW9uIl0sIFsiaW5wdXQiLCAiVmFsaWRhdGUiXV0sIGV2ZW50ID0+IGV2ZW50LnRhcmdldC52YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoImlucHV0IiwgZnVuY3Rpb24gKGV2ZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmFnZS5zZXRWYWx1ZShpZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZ2V0VmFsdWUodHJ1ZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRhdGEuY29tYm8pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFRleHRTdHlsZShzZWxlY3RFbGVtZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHt9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldEJhY2tncm91bmRDb2xvcihzZWxlY3RFbGVtZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0RGVmYXVsdFByb3BlcnRpZXNGcm9tSlMoc2VsZWN0RWxlbWVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmFwcGVuZChzZWxlY3RFbGVtZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIFBvcHVwQW5ub3RhdGlvbkVsZW1lbnQgZXh0ZW5kcyBBbm5vdGF0aW9uRWxlbWVudCB7CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIElHTk9SRV9UWVBFUyA9IG5ldyBTZXQoWyJMaW5lIiwgIlNxdWFyZSIsICJDaXJjbGUiLCAiUG9seUxpbmUiLCAiUG9seWdvbiIsICJJbmsiXSk7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX2RhdGEkdGl0bGVPYmosIF9kYXRhJGNvbnRlbnRzT2JqLCBfZGF0YSRyaWNoVGV4dDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YQogICAgICAgICAgICAgICAgICAgICAgICB9ID0gcGFyYW1ldGVyczsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNSZW5kZXJhYmxlID0gIVBvcHVwQW5ub3RhdGlvbkVsZW1lbnQuSUdOT1JFX1RZUEVTLmhhcyhkYXRhLnBhcmVudFR5cGUpICYmICEhKChfZGF0YSR0aXRsZU9iaiA9IGRhdGEudGl0bGVPYmopICE9PSBudWxsICYmIF9kYXRhJHRpdGxlT2JqICE9PSB2b2lkIDAgJiYgX2RhdGEkdGl0bGVPYmouc3RyIHx8IChfZGF0YSRjb250ZW50c09iaiA9IGRhdGEuY29udGVudHNPYmopICE9PSBudWxsICYmIF9kYXRhJGNvbnRlbnRzT2JqICE9PSB2b2lkIDAgJiYgX2RhdGEkY29udGVudHNPYmouc3RyIHx8IChfZGF0YSRyaWNoVGV4dCA9IGRhdGEucmljaFRleHQpICE9PSBudWxsICYmIF9kYXRhJHJpY2hUZXh0ICE9PSB2b2lkIDAgJiYgX2RhdGEkcmljaFRleHQuc3RyKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIocGFyYW1ldGVycywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNSZW5kZXJhYmxlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZW5kZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoInBvcHVwQW5ub3RhdGlvbiIpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJlbnRFbGVtZW50cyA9IHRoaXMubGF5ZXIucXVlcnlTZWxlY3RvckFsbChgW2RhdGEtYW5ub3RhdGlvbi1pZD0iJHt0aGlzLmRhdGEucGFyZW50SWR9Il1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudEVsZW1lbnRzLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvcHVwID0gbmV3IFBvcHVwRWxlbWVudCh7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXI6IHRoaXMuY29udGFpbmVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlcjogQXJyYXkuZnJvbShwYXJlbnRFbGVtZW50cyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcjogdGhpcy5kYXRhLmNvbG9yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGVPYmo6IHRoaXMuZGF0YS50aXRsZU9iaiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGlmaWNhdGlvbkRhdGU6IHRoaXMuZGF0YS5tb2RpZmljYXRpb25EYXRlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudHNPYmo6IHRoaXMuZGF0YS5jb250ZW50c09iaiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJpY2hUZXh0OiB0aGlzLmRhdGEucmljaFRleHQKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhZ2UgPSB0aGlzLnBhZ2U7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlY3QgPSBfdXRpbC5VdGlsLm5vcm1hbGl6ZVJlY3QoW3RoaXMuZGF0YS5wYXJlbnRSZWN0WzBdLCBwYWdlLnZpZXdbM10gLSB0aGlzLmRhdGEucGFyZW50UmVjdFsxXSArIHBhZ2Uudmlld1sxXSwgdGhpcy5kYXRhLnBhcmVudFJlY3RbMl0sIHBhZ2Uudmlld1szXSAtIHRoaXMuZGF0YS5wYXJlbnRSZWN0WzNdICsgcGFnZS52aWV3WzFdXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvcHVwTGVmdCA9IHJlY3RbMF0gKyB0aGlzLmRhdGEucGFyZW50UmVjdFsyXSAtIHRoaXMuZGF0YS5wYXJlbnRSZWN0WzBdOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb3B1cFRvcCA9IHJlY3RbMV07CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VXaWR0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VIZWlnaHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlWCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VZCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSB0aGlzLnZpZXdwb3J0LnJhd0RpbXM7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLnN0eWxlLmxlZnQgPSBgJHsxMDAgKiAocG9wdXBMZWZ0IC0gcGFnZVgpIC8gcGFnZVdpZHRofSVgOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5zdHlsZS50b3AgPSBgJHsxMDAgKiAocG9wdXBUb3AgLSBwYWdlWSkgLyBwYWdlSGVpZ2h0fSVgOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5hcHBlbmQocG9wdXAucmVuZGVyKCkpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb250YWluZXI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgUG9wdXBFbGVtZW50IHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihwYXJhbWV0ZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyID0gcGFyYW1ldGVycy5jb250YWluZXI7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJpZ2dlciA9IHBhcmFtZXRlcnMudHJpZ2dlcjsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb2xvciA9IHBhcmFtZXRlcnMuY29sb3I7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGl0bGVPYmogPSBwYXJhbWV0ZXJzLnRpdGxlT2JqOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1vZGlmaWNhdGlvbkRhdGUgPSBwYXJhbWV0ZXJzLm1vZGlmaWNhdGlvbkRhdGU7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGVudHNPYmogPSBwYXJhbWV0ZXJzLmNvbnRlbnRzT2JqOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJpY2hUZXh0ID0gcGFyYW1ldGVycy5yaWNoVGV4dDsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWRlV3JhcHBlciA9IHBhcmFtZXRlcnMuaGlkZVdyYXBwZXIgfHwgZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGlubmVkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbmRlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJHJpY2hUZXh0LCBfdGhpcyRjb250ZW50c09iajsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgQkFDS0dST1VORF9FTkxJR0hUID0gMC43OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3cmFwcGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2Iik7CiAgICAgICAgICAgICAgICAgICAgICAgIHdyYXBwZXIuY2xhc3NMaXN0LmFkZCgicG9wdXBXcmFwcGVyIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGlkZUVsZW1lbnQgPSB0aGlzLmhpZGVXcmFwcGVyID8gd3JhcHBlciA6IHRoaXMuY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZGVFbGVtZW50LmhpZGRlbiA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvcHVwID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiZGl2Iik7CiAgICAgICAgICAgICAgICAgICAgICAgIHBvcHVwLmNsYXNzTGlzdC5hZGQoInBvcHVwIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbG9yID0gdGhpcy5jb2xvcjsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvbG9yKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByID0gQkFDS0dST1VORF9FTkxJR0hUICogKDI1NSAtIGNvbG9yWzBdKSArIGNvbG9yWzBdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZyA9IEJBQ0tHUk9VTkRfRU5MSUdIVCAqICgyNTUgLSBjb2xvclsxXSkgKyBjb2xvclsxXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGIgPSBCQUNLR1JPVU5EX0VOTElHSFQgKiAoMjU1IC0gY29sb3JbMl0pICsgY29sb3JbMl07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3B1cC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBfdXRpbC5VdGlsLm1ha2VIZXhDb2xvcihyIHwgMCwgZyB8IDAsIGIgfCAwKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0aXRsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImgxIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlLmRpciA9IHRoaXMudGl0bGVPYmouZGlyOwogICAgICAgICAgICAgICAgICAgICAgICB0aXRsZS50ZXh0Q29udGVudCA9IHRoaXMudGl0bGVPYmouc3RyOwogICAgICAgICAgICAgICAgICAgICAgICBwb3B1cC5hcHBlbmQodGl0bGUpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRlT2JqZWN0ID0gX2Rpc3BsYXlfdXRpbHMuUERGRGF0ZVN0cmluZy50b0RhdGVPYmplY3QodGhpcy5tb2RpZmljYXRpb25EYXRlKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGVPYmplY3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1vZGlmaWNhdGlvbkRhdGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJzcGFuIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RpZmljYXRpb25EYXRlLmNsYXNzTGlzdC5hZGQoInBvcHVwRGF0ZSIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZpY2F0aW9uRGF0ZS50ZXh0Q29udGVudCA9ICJ7e2RhdGV9fSwge3t0aW1lfX0iOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kaWZpY2F0aW9uRGF0ZS5kYXRhc2V0LmwxMG5JZCA9ICJhbm5vdGF0aW9uX2RhdGVfc3RyaW5nIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGlmaWNhdGlvbkRhdGUuZGF0YXNldC5sMTBuQXJncyA9IEpTT04uc3RyaW5naWZ5KHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRlOiBkYXRlT2JqZWN0LnRvTG9jYWxlRGF0ZVN0cmluZygpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWU6IGRhdGVPYmplY3QudG9Mb2NhbGVUaW1lU3RyaW5nKCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wdXAuYXBwZW5kKG1vZGlmaWNhdGlvbkRhdGUpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoX3RoaXMkcmljaFRleHQgPSB0aGlzLnJpY2hUZXh0KSAhPT0gbnVsbCAmJiBfdGhpcyRyaWNoVGV4dCAhPT0gdm9pZCAwICYmIF90aGlzJHJpY2hUZXh0LnN0ciAmJiAoISgoX3RoaXMkY29udGVudHNPYmogPSB0aGlzLmNvbnRlbnRzT2JqKSAhPT0gbnVsbCAmJiBfdGhpcyRjb250ZW50c09iaiAhPT0gdm9pZCAwICYmIF90aGlzJGNvbnRlbnRzT2JqLnN0cikgfHwgdGhpcy5jb250ZW50c09iai5zdHIgPT09IHRoaXMucmljaFRleHQuc3RyKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgX3hmYV9sYXllci5YZmFMYXllci5yZW5kZXIoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhmYUh0bWw6IHRoaXMucmljaFRleHQuaHRtbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlbnQ6ICJyaWNoVGV4dCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGl2OiBwb3B1cAogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3B1cC5sYXN0Q2hpbGQuY2xhc3NMaXN0LmFkZCgicmljaFRleHQiLCAicG9wdXBDb250ZW50Iik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjb250ZW50cyA9IHRoaXMuX2Zvcm1hdENvbnRlbnRzKHRoaXMuY29udGVudHNPYmopOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9wdXAuYXBwZW5kKGNvbnRlbnRzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy50cmlnZ2VyKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyID0gW3RoaXMudHJpZ2dlcl07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHRoaXMudHJpZ2dlcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCJjbGljayIsIHRoaXMuX3RvZ2dsZS5iaW5kKHRoaXMpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigibW91c2VvdmVyIiwgdGhpcy5fc2hvdy5iaW5kKHRoaXMsIGZhbHNlKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoIm1vdXNlb3V0IiwgdGhpcy5faGlkZS5iaW5kKHRoaXMsIGZhbHNlKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcG9wdXAuYWRkRXZlbnRMaXN0ZW5lcigiY2xpY2siLCB0aGlzLl9oaWRlLmJpbmQodGhpcywgdHJ1ZSkpOwogICAgICAgICAgICAgICAgICAgICAgICB3cmFwcGVyLmFwcGVuZChwb3B1cCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3cmFwcGVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfZm9ybWF0Q29udGVudHMoX3JlZikgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlyCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgicCIpOwogICAgICAgICAgICAgICAgICAgICAgICBwLmNsYXNzTGlzdC5hZGQoInBvcHVwQ29udGVudCIpOwogICAgICAgICAgICAgICAgICAgICAgICBwLmRpciA9IGRpcjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbGluZXMgPSBzdHIuc3BsaXQoLyg/OlxyXG4/fFxuKS8pOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBsaW5lcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBsaW5lID0gbGluZXNbaV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwLmFwcGVuZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShsaW5lKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaSA8IGlpIC0gMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAuYXBwZW5kKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImJyIikpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfdG9nZ2xlKCkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5waW5uZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2hpZGUodHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zaG93KHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9zaG93KCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcGluID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBpbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5waW5uZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmhpZGVFbGVtZW50LmhpZGRlbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWRlRWxlbWVudC5oaWRkZW4gPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLnN0eWxlLnpJbmRleCA9IHBhcnNlSW50KHRoaXMuY29udGFpbmVyLnN0eWxlLnpJbmRleCkgKyAxMDAwOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIF9oaWRlKCkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgdW5waW4gPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1bnBpbikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5waW5uZWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaGlkZUVsZW1lbnQuaGlkZGVuICYmICF0aGlzLnBpbm5lZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWRlRWxlbWVudC5oaWRkZW4gPSB0cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250YWluZXIuc3R5bGUuekluZGV4ID0gcGFyc2VJbnQodGhpcy5jb250YWluZXIuc3R5bGUuekluZGV4KSAtIDEwMDA7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBGcmVlVGV4dEFubm90YXRpb25FbGVtZW50IGV4dGVuZHMgQW5ub3RhdGlvbkVsZW1lbnQgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHBhcmFtZXRlcnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDIsIF9wYXJhbWV0ZXJzJGRhdGEkY29udDIsIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzUmVuZGVyYWJsZSA9ICEhKHBhcmFtZXRlcnMuZGF0YS5oYXNQb3B1cCB8fCAoX3BhcmFtZXRlcnMkZGF0YSR0aXRsMiA9IHBhcmFtZXRlcnMuZGF0YS50aXRsZU9iaikgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSR0aXRsMiAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDIuc3RyIHx8IChfcGFyYW1ldGVycyRkYXRhJGNvbnQyID0gcGFyYW1ldGVycy5kYXRhLmNvbnRlbnRzT2JqKSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJGNvbnQyICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSRjb250Mi5zdHIgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkcmljaDIgPSBwYXJhbWV0ZXJzLmRhdGEucmljaFRleHQpICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDIgIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJHJpY2gyLnN0cik7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKHBhcmFtZXRlcnMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzUmVuZGVyYWJsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZUJvcmRlcjogdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXh0Q29udGVudCA9IHBhcmFtZXRlcnMuZGF0YS50ZXh0Q29udGVudDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVuZGVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5jbGFzc0xpc3QuYWRkKCJmcmVlVGV4dEFubm90YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMudGV4dENvbnRlbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuY2xhc3NMaXN0LmFkZCgiYW5ub3RhdGlvblRleHRDb250ZW50Iik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50LnNldEF0dHJpYnV0ZSgicm9sZSIsICJjb21tZW50Iik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGxpbmUgb2YgdGhpcy50ZXh0Q29udGVudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpbmVTcGFuID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic3BhbiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVTcGFuLnRleHRDb250ZW50ID0gbGluZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50LmFwcGVuZChsaW5lU3Bhbik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5hcHBlbmQoY29udGVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmRhdGEuaGFzUG9wdXApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZVBvcHVwKG51bGwsIHRoaXMuZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIExpbmVBbm5vdGF0aW9uRWxlbWVudCBleHRlbmRzIEFubm90YXRpb25FbGVtZW50IHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihwYXJhbWV0ZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfcGFyYW1ldGVycyRkYXRhJHRpdGwzLCBfcGFyYW1ldGVycyRkYXRhJGNvbnQzLCBfcGFyYW1ldGVycyRkYXRhJHJpY2gzOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpc1JlbmRlcmFibGUgPSAhIShwYXJhbWV0ZXJzLmRhdGEuaGFzUG9wdXAgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDMgPSBwYXJhbWV0ZXJzLmRhdGEudGl0bGVPYmopICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDMgIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJHRpdGwzLnN0ciB8fCAoX3BhcmFtZXRlcnMkZGF0YSRjb250MyA9IHBhcmFtZXRlcnMuZGF0YS5jb250ZW50c09iaikgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSRjb250MyAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkY29udDMuc3RyIHx8IChfcGFyYW1ldGVycyRkYXRhJHJpY2gzID0gcGFyYW1ldGVycy5kYXRhLnJpY2hUZXh0KSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJHJpY2gzICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSRyaWNoMy5zdHIpOwogICAgICAgICAgICAgICAgICAgICAgICBzdXBlcihwYXJhbWV0ZXJzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1JlbmRlcmFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmVCb3JkZXI6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbmRlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250YWluZXIuY2xhc3NMaXN0LmFkZCgibGluZUFubm90YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IHRoaXMuZGF0YTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGdldFJlY3REaW1zKGRhdGEucmVjdCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN2ZyA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGUod2lkdGgsIGhlaWdodCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpbmUgPSB0aGlzLnN2Z0ZhY3RvcnkuY3JlYXRlRWxlbWVudCgic3ZnOmxpbmUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGluZS5zZXRBdHRyaWJ1dGUoIngxIiwgZGF0YS5yZWN0WzJdIC0gZGF0YS5saW5lQ29vcmRpbmF0ZXNbMF0pOwogICAgICAgICAgICAgICAgICAgICAgICBsaW5lLnNldEF0dHJpYnV0ZSgieTEiLCBkYXRhLnJlY3RbM10gLSBkYXRhLmxpbmVDb29yZGluYXRlc1sxXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxpbmUuc2V0QXR0cmlidXRlKCJ4MiIsIGRhdGEucmVjdFsyXSAtIGRhdGEubGluZUNvb3JkaW5hdGVzWzJdKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGluZS5zZXRBdHRyaWJ1dGUoInkyIiwgZGF0YS5yZWN0WzNdIC0gZGF0YS5saW5lQ29vcmRpbmF0ZXNbM10pOwogICAgICAgICAgICAgICAgICAgICAgICBsaW5lLnNldEF0dHJpYnV0ZSgic3Ryb2tlLXdpZHRoIiwgZGF0YS5ib3JkZXJTdHlsZS53aWR0aCB8fCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGluZS5zZXRBdHRyaWJ1dGUoInN0cm9rZSIsICJ0cmFuc3BhcmVudCIpOwogICAgICAgICAgICAgICAgICAgICAgICBsaW5lLnNldEF0dHJpYnV0ZSgiZmlsbCIsICJ0cmFuc3BhcmVudCIpOwogICAgICAgICAgICAgICAgICAgICAgICBzdmcuYXBwZW5kKGxpbmUpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5hcHBlbmQoc3ZnKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY3JlYXRlUG9wdXAobGluZSwgZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRhaW5lcjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBTcXVhcmVBbm5vdGF0aW9uRWxlbWVudCBleHRlbmRzIEFubm90YXRpb25FbGVtZW50IHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihwYXJhbWV0ZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfcGFyYW1ldGVycyRkYXRhJHRpdGw0LCBfcGFyYW1ldGVycyRkYXRhJGNvbnQ0LCBfcGFyYW1ldGVycyRkYXRhJHJpY2g0OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpc1JlbmRlcmFibGUgPSAhIShwYXJhbWV0ZXJzLmRhdGEuaGFzUG9wdXAgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDQgPSBwYXJhbWV0ZXJzLmRhdGEudGl0bGVPYmopICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDQgIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJHRpdGw0LnN0ciB8fCAoX3BhcmFtZXRlcnMkZGF0YSRjb250NCA9IHBhcmFtZXRlcnMuZGF0YS5jb250ZW50c09iaikgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSRjb250NCAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkY29udDQuc3RyIHx8IChfcGFyYW1ldGVycyRkYXRhJHJpY2g0ID0gcGFyYW1ldGVycy5kYXRhLnJpY2hUZXh0KSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJHJpY2g0ICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSRyaWNoNC5zdHIpOwogICAgICAgICAgICAgICAgICAgICAgICBzdXBlcihwYXJhbWV0ZXJzLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1JlbmRlcmFibGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmVCb3JkZXI6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbmRlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250YWluZXIuY2xhc3NMaXN0LmFkZCgic3F1YXJlQW5ub3RhdGlvbiIpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gdGhpcy5kYXRhOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodAogICAgICAgICAgICAgICAgICAgICAgICB9ID0gZ2V0UmVjdERpbXMoZGF0YS5yZWN0KTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3ZnID0gdGhpcy5zdmdGYWN0b3J5LmNyZWF0ZSh3aWR0aCwgaGVpZ2h0LCB0cnVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYm9yZGVyV2lkdGggPSBkYXRhLmJvcmRlclN0eWxlLndpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzcXVhcmUgPSB0aGlzLnN2Z0ZhY3RvcnkuY3JlYXRlRWxlbWVudCgic3ZnOnJlY3QiKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3F1YXJlLnNldEF0dHJpYnV0ZSgieCIsIGJvcmRlcldpZHRoIC8gMik7CiAgICAgICAgICAgICAgICAgICAgICAgIHNxdWFyZS5zZXRBdHRyaWJ1dGUoInkiLCBib3JkZXJXaWR0aCAvIDIpOwogICAgICAgICAgICAgICAgICAgICAgICBzcXVhcmUuc2V0QXR0cmlidXRlKCJ3aWR0aCIsIHdpZHRoIC0gYm9yZGVyV2lkdGgpOwogICAgICAgICAgICAgICAgICAgICAgICBzcXVhcmUuc2V0QXR0cmlidXRlKCJoZWlnaHQiLCBoZWlnaHQgLSBib3JkZXJXaWR0aCk7CiAgICAgICAgICAgICAgICAgICAgICAgIHNxdWFyZS5zZXRBdHRyaWJ1dGUoInN0cm9rZS13aWR0aCIsIGJvcmRlcldpZHRoIHx8IDEpOwogICAgICAgICAgICAgICAgICAgICAgICBzcXVhcmUuc2V0QXR0cmlidXRlKCJzdHJva2UiLCAidHJhbnNwYXJlbnQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3F1YXJlLnNldEF0dHJpYnV0ZSgiZmlsbCIsICJ0cmFuc3BhcmVudCIpOwogICAgICAgICAgICAgICAgICAgICAgICBzdmcuYXBwZW5kKHNxdWFyZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmFwcGVuZChzdmcpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jcmVhdGVQb3B1cChzcXVhcmUsIGRhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb250YWluZXI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgQ2lyY2xlQW5ub3RhdGlvbkVsZW1lbnQgZXh0ZW5kcyBBbm5vdGF0aW9uRWxlbWVudCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3BhcmFtZXRlcnMkZGF0YSR0aXRsNSwgX3BhcmFtZXRlcnMkZGF0YSRjb250NSwgX3BhcmFtZXRlcnMkZGF0YSRyaWNoNTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNSZW5kZXJhYmxlID0gISEocGFyYW1ldGVycy5kYXRhLmhhc1BvcHVwIHx8IChfcGFyYW1ldGVycyRkYXRhJHRpdGw1ID0gcGFyYW1ldGVycy5kYXRhLnRpdGxlT2JqKSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJHRpdGw1ICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSR0aXRsNS5zdHIgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkY29udDUgPSBwYXJhbWV0ZXJzLmRhdGEuY29udGVudHNPYmopICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkY29udDUgIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJGNvbnQ1LnN0ciB8fCAoX3BhcmFtZXRlcnMkZGF0YSRyaWNoNSA9IHBhcmFtZXRlcnMuZGF0YS5yaWNoVGV4dCkgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSRyaWNoNSAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDUuc3RyKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIocGFyYW1ldGVycywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNSZW5kZXJhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlQm9yZGVyOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZW5kZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoImNpcmNsZUFubm90YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IHRoaXMuZGF0YTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGdldFJlY3REaW1zKGRhdGEucmVjdCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN2ZyA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGUod2lkdGgsIGhlaWdodCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJvcmRlcldpZHRoID0gZGF0YS5ib3JkZXJTdHlsZS53aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2lyY2xlID0gdGhpcy5zdmdGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoInN2ZzplbGxpcHNlIik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNpcmNsZS5zZXRBdHRyaWJ1dGUoImN4Iiwgd2lkdGggLyAyKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2lyY2xlLnNldEF0dHJpYnV0ZSgiY3kiLCBoZWlnaHQgLyAyKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2lyY2xlLnNldEF0dHJpYnV0ZSgicngiLCB3aWR0aCAvIDIgLSBib3JkZXJXaWR0aCAvIDIpOwogICAgICAgICAgICAgICAgICAgICAgICBjaXJjbGUuc2V0QXR0cmlidXRlKCJyeSIsIGhlaWdodCAvIDIgLSBib3JkZXJXaWR0aCAvIDIpOwogICAgICAgICAgICAgICAgICAgICAgICBjaXJjbGUuc2V0QXR0cmlidXRlKCJzdHJva2Utd2lkdGgiLCBib3JkZXJXaWR0aCB8fCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgY2lyY2xlLnNldEF0dHJpYnV0ZSgic3Ryb2tlIiwgInRyYW5zcGFyZW50Iik7CiAgICAgICAgICAgICAgICAgICAgICAgIGNpcmNsZS5zZXRBdHRyaWJ1dGUoImZpbGwiLCAidHJhbnNwYXJlbnQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3ZnLmFwcGVuZChjaXJjbGUpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5hcHBlbmQoc3ZnKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY3JlYXRlUG9wdXAoY2lyY2xlLCBkYXRhKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIFBvbHlsaW5lQW5ub3RhdGlvbkVsZW1lbnQgZXh0ZW5kcyBBbm5vdGF0aW9uRWxlbWVudCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3BhcmFtZXRlcnMkZGF0YSR0aXRsNiwgX3BhcmFtZXRlcnMkZGF0YSRjb250NiwgX3BhcmFtZXRlcnMkZGF0YSRyaWNoNjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNSZW5kZXJhYmxlID0gISEocGFyYW1ldGVycy5kYXRhLmhhc1BvcHVwIHx8IChfcGFyYW1ldGVycyRkYXRhJHRpdGw2ID0gcGFyYW1ldGVycy5kYXRhLnRpdGxlT2JqKSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJHRpdGw2ICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSR0aXRsNi5zdHIgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkY29udDYgPSBwYXJhbWV0ZXJzLmRhdGEuY29udGVudHNPYmopICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkY29udDYgIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJGNvbnQ2LnN0ciB8fCAoX3BhcmFtZXRlcnMkZGF0YSRyaWNoNiA9IHBhcmFtZXRlcnMuZGF0YS5yaWNoVGV4dCkgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSRyaWNoNiAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDYuc3RyKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIocGFyYW1ldGVycywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNSZW5kZXJhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlQm9yZGVyOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lckNsYXNzTmFtZSA9ICJwb2x5bGluZUFubm90YXRpb24iOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN2Z0VsZW1lbnROYW1lID0gInN2Zzpwb2x5bGluZSI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbmRlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250YWluZXIuY2xhc3NMaXN0LmFkZCh0aGlzLmNvbnRhaW5lckNsYXNzTmFtZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLmRhdGE7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0CiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBnZXRSZWN0RGltcyhkYXRhLnJlY3QpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdmcgPSB0aGlzLnN2Z0ZhY3RvcnkuY3JlYXRlKHdpZHRoLCBoZWlnaHQsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgcG9pbnRzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgY29vcmRpbmF0ZSBvZiBkYXRhLnZlcnRpY2VzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB4ID0gY29vcmRpbmF0ZS54IC0gZGF0YS5yZWN0WzBdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeSA9IGRhdGEucmVjdFszXSAtIGNvb3JkaW5hdGUueTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50cy5wdXNoKHggKyAiLCIgKyB5KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBwb2ludHMgPSBwb2ludHMuam9pbigiICIpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb2x5bGluZSA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGVFbGVtZW50KHRoaXMuc3ZnRWxlbWVudE5hbWUpOwogICAgICAgICAgICAgICAgICAgICAgICBwb2x5bGluZS5zZXRBdHRyaWJ1dGUoInBvaW50cyIsIHBvaW50cyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHBvbHlsaW5lLnNldEF0dHJpYnV0ZSgic3Ryb2tlLXdpZHRoIiwgZGF0YS5ib3JkZXJTdHlsZS53aWR0aCB8fCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgcG9seWxpbmUuc2V0QXR0cmlidXRlKCJzdHJva2UiLCAidHJhbnNwYXJlbnQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgcG9seWxpbmUuc2V0QXR0cmlidXRlKCJmaWxsIiwgInRyYW5zcGFyZW50Iik7CiAgICAgICAgICAgICAgICAgICAgICAgIHN2Zy5hcHBlbmQocG9seWxpbmUpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5hcHBlbmQoc3ZnKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY3JlYXRlUG9wdXAocG9seWxpbmUsIGRhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb250YWluZXI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgUG9seWdvbkFubm90YXRpb25FbGVtZW50IGV4dGVuZHMgUG9seWxpbmVBbm5vdGF0aW9uRWxlbWVudCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICBzdXBlcihwYXJhbWV0ZXJzKTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250YWluZXJDbGFzc05hbWUgPSAicG9seWdvbkFubm90YXRpb24iOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN2Z0VsZW1lbnROYW1lID0gInN2Zzpwb2x5Z29uIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBDYXJldEFubm90YXRpb25FbGVtZW50IGV4dGVuZHMgQW5ub3RhdGlvbkVsZW1lbnQgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHBhcmFtZXRlcnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDcsIF9wYXJhbWV0ZXJzJGRhdGEkY29udDcsIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDc7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzUmVuZGVyYWJsZSA9ICEhKHBhcmFtZXRlcnMuZGF0YS5oYXNQb3B1cCB8fCAoX3BhcmFtZXRlcnMkZGF0YSR0aXRsNyA9IHBhcmFtZXRlcnMuZGF0YS50aXRsZU9iaikgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSR0aXRsNyAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDcuc3RyIHx8IChfcGFyYW1ldGVycyRkYXRhJGNvbnQ3ID0gcGFyYW1ldGVycy5kYXRhLmNvbnRlbnRzT2JqKSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJGNvbnQ3ICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSRjb250Ny5zdHIgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkcmljaDcgPSBwYXJhbWV0ZXJzLmRhdGEucmljaFRleHQpICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDcgIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJHJpY2g3LnN0cik7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKHBhcmFtZXRlcnMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzUmVuZGVyYWJsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZUJvcmRlcjogdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVuZGVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5jbGFzc0xpc3QuYWRkKCJjYXJldEFubm90YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmRhdGEuaGFzUG9wdXApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZVBvcHVwKG51bGwsIHRoaXMuZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIElua0Fubm90YXRpb25FbGVtZW50IGV4dGVuZHMgQW5ub3RhdGlvbkVsZW1lbnQgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHBhcmFtZXRlcnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDgsIF9wYXJhbWV0ZXJzJGRhdGEkY29udDgsIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDg7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzUmVuZGVyYWJsZSA9ICEhKHBhcmFtZXRlcnMuZGF0YS5oYXNQb3B1cCB8fCAoX3BhcmFtZXRlcnMkZGF0YSR0aXRsOCA9IHBhcmFtZXRlcnMuZGF0YS50aXRsZU9iaikgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSR0aXRsOCAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDguc3RyIHx8IChfcGFyYW1ldGVycyRkYXRhJGNvbnQ4ID0gcGFyYW1ldGVycy5kYXRhLmNvbnRlbnRzT2JqKSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJGNvbnQ4ICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSRjb250OC5zdHIgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkcmljaDggPSBwYXJhbWV0ZXJzLmRhdGEucmljaFRleHQpICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDggIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJHJpY2g4LnN0cik7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKHBhcmFtZXRlcnMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzUmVuZGVyYWJsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZUJvcmRlcjogdHJ1ZQogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250YWluZXJDbGFzc05hbWUgPSAiaW5rQW5ub3RhdGlvbiI7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3ZnRWxlbWVudE5hbWUgPSAic3ZnOnBvbHlsaW5lIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVuZGVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5jbGFzc0xpc3QuYWRkKHRoaXMuY29udGFpbmVyQ2xhc3NOYW1lKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IHRoaXMuZGF0YTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGdldFJlY3REaW1zKGRhdGEucmVjdCk7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN2ZyA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGUod2lkdGgsIGhlaWdodCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaW5rTGlzdCBvZiBkYXRhLmlua0xpc3RzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgcG9pbnRzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGNvb3JkaW5hdGUgb2YgaW5rTGlzdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHggPSBjb29yZGluYXRlLnggLSBkYXRhLnJlY3RbMF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeSA9IGRhdGEucmVjdFszXSAtIGNvb3JkaW5hdGUueTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludHMucHVzaChgJHt4fSwke3l9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludHMgPSBwb2ludHMuam9pbigiICIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9seWxpbmUgPSB0aGlzLnN2Z0ZhY3RvcnkuY3JlYXRlRWxlbWVudCh0aGlzLnN2Z0VsZW1lbnROYW1lKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvbHlsaW5lLnNldEF0dHJpYnV0ZSgicG9pbnRzIiwgcG9pbnRzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvbHlsaW5lLnNldEF0dHJpYnV0ZSgic3Ryb2tlLXdpZHRoIiwgZGF0YS5ib3JkZXJTdHlsZS53aWR0aCB8fCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvbHlsaW5lLnNldEF0dHJpYnV0ZSgic3Ryb2tlIiwgInRyYW5zcGFyZW50Iik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2x5bGluZS5zZXRBdHRyaWJ1dGUoImZpbGwiLCAidHJhbnNwYXJlbnQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZVBvcHVwKHBvbHlsaW5lLCBkYXRhKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN2Zy5hcHBlbmQocG9seWxpbmUpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmFwcGVuZChzdmcpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb250YWluZXI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgSGlnaGxpZ2h0QW5ub3RhdGlvbkVsZW1lbnQgZXh0ZW5kcyBBbm5vdGF0aW9uRWxlbWVudCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3BhcmFtZXRlcnMkZGF0YSR0aXRsOSwgX3BhcmFtZXRlcnMkZGF0YSRjb250OSwgX3BhcmFtZXRlcnMkZGF0YSRyaWNoOTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNSZW5kZXJhYmxlID0gISEocGFyYW1ldGVycy5kYXRhLmhhc1BvcHVwIHx8IChfcGFyYW1ldGVycyRkYXRhJHRpdGw5ID0gcGFyYW1ldGVycy5kYXRhLnRpdGxlT2JqKSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJHRpdGw5ICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSR0aXRsOS5zdHIgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkY29udDkgPSBwYXJhbWV0ZXJzLmRhdGEuY29udGVudHNPYmopICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkY29udDkgIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJGNvbnQ5LnN0ciB8fCAoX3BhcmFtZXRlcnMkZGF0YSRyaWNoOSA9IHBhcmFtZXRlcnMuZGF0YS5yaWNoVGV4dCkgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSRyaWNoOSAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDkuc3RyKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIocGFyYW1ldGVycywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNSZW5kZXJhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlQm9yZGVyOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlUXVhZHJpbGF0ZXJhbHM6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbmRlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmRhdGEuaGFzUG9wdXApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZVBvcHVwKG51bGwsIHRoaXMuZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucXVhZHJpbGF0ZXJhbHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9yZW5kZXJRdWFkcmlsYXRlcmFscygiaGlnaGxpZ2h0QW5ub3RhdGlvbiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoImhpZ2hsaWdodEFubm90YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIFVuZGVybGluZUFubm90YXRpb25FbGVtZW50IGV4dGVuZHMgQW5ub3RhdGlvbkVsZW1lbnQgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHBhcmFtZXRlcnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDEwLCBfcGFyYW1ldGVycyRkYXRhJGNvbnQxMCwgX3BhcmFtZXRlcnMkZGF0YSRyaWNoMTA7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzUmVuZGVyYWJsZSA9ICEhKHBhcmFtZXRlcnMuZGF0YS5oYXNQb3B1cCB8fCAoX3BhcmFtZXRlcnMkZGF0YSR0aXRsMTAgPSBwYXJhbWV0ZXJzLmRhdGEudGl0bGVPYmopICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDEwICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSR0aXRsMTAuc3RyIHx8IChfcGFyYW1ldGVycyRkYXRhJGNvbnQxMCA9IHBhcmFtZXRlcnMuZGF0YS5jb250ZW50c09iaikgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSRjb250MTAgIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJGNvbnQxMC5zdHIgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkcmljaDEwID0gcGFyYW1ldGVycy5kYXRhLnJpY2hUZXh0KSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJHJpY2gxMCAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDEwLnN0cik7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKHBhcmFtZXRlcnMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzUmVuZGVyYWJsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZUJvcmRlcjogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZVF1YWRyaWxhdGVyYWxzOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZW5kZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5kYXRhLmhhc1BvcHVwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jcmVhdGVQb3B1cChudWxsLCB0aGlzLmRhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnF1YWRyaWxhdGVyYWxzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcmVuZGVyUXVhZHJpbGF0ZXJhbHMoInVuZGVybGluZUFubm90YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5jbGFzc0xpc3QuYWRkKCJ1bmRlcmxpbmVBbm5vdGF0aW9uIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRhaW5lcjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBTcXVpZ2dseUFubm90YXRpb25FbGVtZW50IGV4dGVuZHMgQW5ub3RhdGlvbkVsZW1lbnQgewogICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKHBhcmFtZXRlcnMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDExLCBfcGFyYW1ldGVycyRkYXRhJGNvbnQxMSwgX3BhcmFtZXRlcnMkZGF0YSRyaWNoMTE7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzUmVuZGVyYWJsZSA9ICEhKHBhcmFtZXRlcnMuZGF0YS5oYXNQb3B1cCB8fCAoX3BhcmFtZXRlcnMkZGF0YSR0aXRsMTEgPSBwYXJhbWV0ZXJzLmRhdGEudGl0bGVPYmopICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkdGl0bDExICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSR0aXRsMTEuc3RyIHx8IChfcGFyYW1ldGVycyRkYXRhJGNvbnQxMSA9IHBhcmFtZXRlcnMuZGF0YS5jb250ZW50c09iaikgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSRjb250MTEgIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJGNvbnQxMS5zdHIgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkcmljaDExID0gcGFyYW1ldGVycy5kYXRhLnJpY2hUZXh0KSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJHJpY2gxMSAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDExLnN0cik7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1cGVyKHBhcmFtZXRlcnMsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzUmVuZGVyYWJsZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZUJvcmRlcjogdHJ1ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyZWF0ZVF1YWRyaWxhdGVyYWxzOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZW5kZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5kYXRhLmhhc1BvcHVwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jcmVhdGVQb3B1cChudWxsLCB0aGlzLmRhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnF1YWRyaWxhdGVyYWxzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcmVuZGVyUXVhZHJpbGF0ZXJhbHMoInNxdWlnZ2x5QW5ub3RhdGlvbiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoInNxdWlnZ2x5QW5ub3RhdGlvbiIpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb250YWluZXI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgU3RyaWtlT3V0QW5ub3RhdGlvbkVsZW1lbnQgZXh0ZW5kcyBBbm5vdGF0aW9uRWxlbWVudCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3BhcmFtZXRlcnMkZGF0YSR0aXRsMTIsIF9wYXJhbWV0ZXJzJGRhdGEkY29udDEyLCBfcGFyYW1ldGVycyRkYXRhJHJpY2gxMjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNSZW5kZXJhYmxlID0gISEocGFyYW1ldGVycy5kYXRhLmhhc1BvcHVwIHx8IChfcGFyYW1ldGVycyRkYXRhJHRpdGwxMiA9IHBhcmFtZXRlcnMuZGF0YS50aXRsZU9iaikgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSR0aXRsMTIgIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJHRpdGwxMi5zdHIgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkY29udDEyID0gcGFyYW1ldGVycy5kYXRhLmNvbnRlbnRzT2JqKSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJGNvbnQxMiAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkY29udDEyLnN0ciB8fCAoX3BhcmFtZXRlcnMkZGF0YSRyaWNoMTIgPSBwYXJhbWV0ZXJzLmRhdGEucmljaFRleHQpICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDEyICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSRyaWNoMTIuc3RyKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIocGFyYW1ldGVycywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNSZW5kZXJhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlQm9yZGVyOiB0cnVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlUXVhZHJpbGF0ZXJhbHM6IHRydWUKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHJlbmRlcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmRhdGEuaGFzUG9wdXApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZVBvcHVwKG51bGwsIHRoaXMuZGF0YSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucXVhZHJpbGF0ZXJhbHMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9yZW5kZXJRdWFkcmlsYXRlcmFscygic3RyaWtlb3V0QW5ub3RhdGlvbiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoInN0cmlrZW91dEFubm90YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNsYXNzIFN0YW1wQW5ub3RhdGlvbkVsZW1lbnQgZXh0ZW5kcyBBbm5vdGF0aW9uRWxlbWVudCB7CiAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0b3IocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3BhcmFtZXRlcnMkZGF0YSR0aXRsMTMsIF9wYXJhbWV0ZXJzJGRhdGEkY29udDEzLCBfcGFyYW1ldGVycyRkYXRhJHJpY2gxMzsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNSZW5kZXJhYmxlID0gISEocGFyYW1ldGVycy5kYXRhLmhhc1BvcHVwIHx8IChfcGFyYW1ldGVycyRkYXRhJHRpdGwxMyA9IHBhcmFtZXRlcnMuZGF0YS50aXRsZU9iaikgIT09IG51bGwgJiYgX3BhcmFtZXRlcnMkZGF0YSR0aXRsMTMgIT09IHZvaWQgMCAmJiBfcGFyYW1ldGVycyRkYXRhJHRpdGwxMy5zdHIgfHwgKF9wYXJhbWV0ZXJzJGRhdGEkY29udDEzID0gcGFyYW1ldGVycy5kYXRhLmNvbnRlbnRzT2JqKSAhPT0gbnVsbCAmJiBfcGFyYW1ldGVycyRkYXRhJGNvbnQxMyAhPT0gdm9pZCAwICYmIF9wYXJhbWV0ZXJzJGRhdGEkY29udDEzLnN0ciB8fCAoX3BhcmFtZXRlcnMkZGF0YSRyaWNoMTMgPSBwYXJhbWV0ZXJzLmRhdGEucmljaFRleHQpICE9PSBudWxsICYmIF9wYXJhbWV0ZXJzJGRhdGEkcmljaDEzICE9PSB2b2lkIDAgJiYgX3BhcmFtZXRlcnMkZGF0YSRyaWNoMTMuc3RyKTsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIocGFyYW1ldGVycywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNSZW5kZXJhYmxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlQm9yZGVyOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICByZW5kZXIoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoInN0YW1wQW5ub3RhdGlvbiIpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuZGF0YS5oYXNQb3B1cCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY3JlYXRlUG9wdXAobnVsbCwgdGhpcy5kYXRhKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jb250YWluZXI7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY2xhc3MgRmlsZUF0dGFjaG1lbnRBbm5vdGF0aW9uRWxlbWVudCBleHRlbmRzIEFubm90YXRpb25FbGVtZW50IHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcihwYXJhbWV0ZXJzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRsaW5rU2VydmljZSRldmUxMDsKICAgICAgICAgICAgICAgICAgICAgICAgc3VwZXIocGFyYW1ldGVycywgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNSZW5kZXJhYmxlOiB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlbmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IHRoaXMuZGF0YS5maWxlOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbGVuYW1lID0gKDAsIF9kaXNwbGF5X3V0aWxzLmdldEZpbGVuYW1lRnJvbVVybCkoZmlsZW5hbWUsIHRydWUpOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRlbnQgPSBjb250ZW50OwogICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkbGlua1NlcnZpY2UkZXZlMTAgPSB0aGlzLmxpbmtTZXJ2aWNlLmV2ZW50QnVzKSA9PT0gbnVsbCB8fCBfdGhpcyRsaW5rU2VydmljZSRldmUxMCA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkbGlua1NlcnZpY2UkZXZlMTAuZGlzcGF0Y2goImZpbGVhdHRhY2htZW50YW5ub3RhdGlvbiIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZTogdGhpcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudAogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgcmVuZGVyKCkgewogICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3RoaXMkZGF0YSR0aXRsZU9iaiwgX3RoaXMkZGF0YSRjb250ZW50c09iOwogICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbnRhaW5lci5jbGFzc0xpc3QuYWRkKCJmaWxlQXR0YWNobWVudEFubm90YXRpb24iKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRyaWdnZXI7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmRhdGEuaGFzQXBwZWFyYW5jZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImRpdiIpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImltZyIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlci5zcmMgPSBgJHt0aGlzLmltYWdlUmVzb3VyY2VzUGF0aH1hbm5vdGF0aW9uLSR7L3BhcGVyY2xpcC9pLnRlc3QodGhpcy5kYXRhLm5hbWUpID8gInBhcGVyY2xpcCIgOiAicHVzaHBpbiJ9LnN2Z2A7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlci5jbGFzc0xpc3QuYWRkKCJwb3B1cFRyaWdnZXJBcmVhIik7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyaWdnZXIuYWRkRXZlbnRMaXN0ZW5lcigiZGJsY2xpY2siLCB0aGlzLl9kb3dubG9hZC5iaW5kKHRoaXMpKTsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmRhdGEuaGFzUG9wdXAgJiYgKChfdGhpcyRkYXRhJHRpdGxlT2JqID0gdGhpcy5kYXRhLnRpdGxlT2JqKSAhPT0gbnVsbCAmJiBfdGhpcyRkYXRhJHRpdGxlT2JqICE9PSB2b2lkIDAgJiYgX3RoaXMkZGF0YSR0aXRsZU9iai5zdHIgfHwgKF90aGlzJGRhdGEkY29udGVudHNPYiA9IHRoaXMuZGF0YS5jb250ZW50c09iaikgIT09IG51bGwgJiYgX3RoaXMkZGF0YSRjb250ZW50c09iICE9PSB2b2lkIDAgJiYgX3RoaXMkZGF0YSRjb250ZW50c09iLnN0ciB8fCB0aGlzLmRhdGEucmljaFRleHQpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jcmVhdGVQb3B1cCh0cmlnZ2VyLCB0aGlzLmRhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29udGFpbmVyLmFwcGVuZCh0cmlnZ2VyKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29udGFpbmVyOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBfZG93bmxvYWQoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRkb3dubG9hZE1hbmFnZXIyOwogICAgICAgICAgICAgICAgICAgICAgICAoX3RoaXMkZG93bmxvYWRNYW5hZ2VyMiA9IHRoaXMuZG93bmxvYWRNYW5hZ2VyKSA9PT0gbnVsbCB8fCBfdGhpcyRkb3dubG9hZE1hbmFnZXIyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRkb3dubG9hZE1hbmFnZXIyLm9wZW5PckRvd25sb2FkRGF0YSh0aGlzLmNvbnRhaW5lciwgdGhpcy5jb250ZW50LCB0aGlzLmZpbGVuYW1lKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBBbm5vdGF0aW9uTGF5ZXIgewogICAgICAgICAgICAgICAgICAgIHN0YXRpYyByZW5kZXIocGFyYW1zKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFubm90YXRpb25zLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGl2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmlld3BvcnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhY2Nlc3NpYmlsaXR5TWFuYWdlcgogICAgICAgICAgICAgICAgICAgICAgICB9ID0gcGFyYW1zOwogICAgICAgICAgICAgICAgICAgICAgICAoMCwgX2Rpc3BsYXlfdXRpbHMuc2V0TGF5ZXJEaW1lbnNpb25zKShkaXYsIHZpZXdwb3J0KTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZWxlbWVudFBhcmFtcyA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IG51bGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXllcjogZGl2LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFnZTogcGFyYW1zLnBhZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3cG9ydCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmtTZXJ2aWNlOiBwYXJhbXMubGlua1NlcnZpY2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb3dubG9hZE1hbmFnZXI6IHBhcmFtcy5kb3dubG9hZE1hbmFnZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbWFnZVJlc291cmNlc1BhdGg6IHBhcmFtcy5pbWFnZVJlc291cmNlc1BhdGggfHwgIiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJGb3JtczogcGFyYW1zLnJlbmRlckZvcm1zICE9PSBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN2Z0ZhY3Rvcnk6IG5ldyBfZGlzcGxheV91dGlscy5ET01TVkdGYWN0b3J5KCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uU3RvcmFnZTogcGFyYW1zLmFubm90YXRpb25TdG9yYWdlIHx8IG5ldyBfYW5ub3RhdGlvbl9zdG9yYWdlLkFubm90YXRpb25TdG9yYWdlKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmFibGVTY3JpcHRpbmc6IHBhcmFtcy5lbmFibGVTY3JpcHRpbmcgPT09IHRydWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNKU0FjdGlvbnM6IHBhcmFtcy5oYXNKU0FjdGlvbnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZE9iamVjdHM6IHBhcmFtcy5maWVsZE9iamVjdHMKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHpJbmRleCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZGF0YSBvZiBhbm5vdGF0aW9ucykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEubm9IVE1MKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5hbm5vdGF0aW9uVHlwZSAhPT0gX3V0aWwuQW5ub3RhdGlvblR5cGUuUE9QVVApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gZ2V0UmVjdERpbXMoZGF0YS5yZWN0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAod2lkdGggPD0gMCB8fCBoZWlnaHQgPD0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50UGFyYW1zLmRhdGEgPSBkYXRhOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IEFubm90YXRpb25FbGVtZW50RmFjdG9yeS5jcmVhdGUoZWxlbWVudFBhcmFtcyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWVsZW1lbnQuaXNSZW5kZXJhYmxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZW5kZXJlZCA9IGVsZW1lbnQucmVuZGVyKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5oaWRkZW4pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJlZC5zdHlsZS52aXNpYmlsaXR5ID0gImhpZGRlbiI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShyZW5kZXJlZCkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHJlbmRlcmVkRWxlbWVudCBvZiByZW5kZXJlZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEVsZW1lbnQuc3R5bGUuekluZGV4ID0gekluZGV4Kys7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1N0YXRpY1ByaXZhdGVNZXRob2RHZXQoQW5ub3RhdGlvbkxheWVyLCBBbm5vdGF0aW9uTGF5ZXIsIF9hcHBlbmRFbGVtZW50KS5jYWxsKEFubm90YXRpb25MYXllciwgcmVuZGVyZWRFbGVtZW50LCBkYXRhLmlkLCBkaXYsIGFjY2Vzc2liaWxpdHlNYW5hZ2VyKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkLnN0eWxlLnpJbmRleCA9IHpJbmRleCsrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50IGluc3RhbmNlb2YgUG9wdXBBbm5vdGF0aW9uRWxlbWVudCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXYucHJlcGVuZChyZW5kZXJlZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsYXNzU3RhdGljUHJpdmF0ZU1ldGhvZEdldChBbm5vdGF0aW9uTGF5ZXIsIEFubm90YXRpb25MYXllciwgX2FwcGVuZEVsZW1lbnQpLmNhbGwoQW5ub3RhdGlvbkxheWVyLCByZW5kZXJlZCwgZGF0YS5pZCwgZGl2LCBhY2Nlc3NpYmlsaXR5TWFuYWdlcik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9jbGFzc1N0YXRpY1ByaXZhdGVNZXRob2RHZXQodGhpcywgQW5ub3RhdGlvbkxheWVyLCBfc2V0QW5ub3RhdGlvbkNhbnZhc01hcCkuY2FsbCh0aGlzLCBkaXYsIHBhcmFtcy5hbm5vdGF0aW9uQ2FudmFzTWFwKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIHVwZGF0ZShwYXJhbXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5ub3RhdGlvbkNhbnZhc01hcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpdiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdwb3J0CiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBwYXJhbXM7CiAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfZGlzcGxheV91dGlscy5zZXRMYXllckRpbWVuc2lvbnMpKGRpdiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb246IHZpZXdwb3J0LnJvdGF0aW9uCiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICBfY2xhc3NTdGF0aWNQcml2YXRlTWV0aG9kR2V0KHRoaXMsIEFubm90YXRpb25MYXllciwgX3NldEFubm90YXRpb25DYW52YXNNYXApLmNhbGwodGhpcywgZGl2LCBhbm5vdGF0aW9uQ2FudmFzTWFwKTsKICAgICAgICAgICAgICAgICAgICAgICAgZGl2LmhpZGRlbiA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuQW5ub3RhdGlvbkxheWVyID0gQW5ub3RhdGlvbkxheWVyOwogICAgICAgICAgICAgICAgZnVuY3Rpb24gX2FwcGVuZEVsZW1lbnQoZWxlbWVudCwgaWQsIGRpdiwgYWNjZXNzaWJpbGl0eU1hbmFnZXIpIHsKICAgICAgICAgICAgICAgICAgICBjb25zdCBjb250ZW50RWxlbWVudCA9IGVsZW1lbnQuZmlyc3RDaGlsZCB8fCBlbGVtZW50OwogICAgICAgICAgICAgICAgICAgIGNvbnRlbnRFbGVtZW50LmlkID0gYCR7X2Rpc3BsYXlfdXRpbHMuQW5ub3RhdGlvblByZWZpeH0ke2lkfWA7CiAgICAgICAgICAgICAgICAgICAgZGl2LmFwcGVuZChlbGVtZW50KTsKICAgICAgICAgICAgICAgICAgICBhY2Nlc3NpYmlsaXR5TWFuYWdlciA9PT0gbnVsbCB8fCBhY2Nlc3NpYmlsaXR5TWFuYWdlciA9PT0gdm9pZCAwID8gdm9pZCAwIDogYWNjZXNzaWJpbGl0eU1hbmFnZXIubW92ZUVsZW1lbnRJbkRPTShkaXYsIGVsZW1lbnQsIGNvbnRlbnRFbGVtZW50LCBmYWxzZSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfc2V0QW5ub3RhdGlvbkNhbnZhc01hcChkaXYsIGFubm90YXRpb25DYW52YXNNYXApIHsKICAgICAgICAgICAgICAgICAgICBpZiAoIWFubm90YXRpb25DYW52YXNNYXApIHsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IFtpZCwgY2FudmFzXSBvZiBhbm5vdGF0aW9uQ2FudmFzTWFwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSBkaXYucXVlcnlTZWxlY3RvcihgW2RhdGEtYW5ub3RhdGlvbi1pZD0iJHtpZH0iXWApOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWVsZW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpcnN0Q2hpbGQKICAgICAgICAgICAgICAgICAgICAgICAgfSA9IGVsZW1lbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZmlyc3RDaGlsZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5hcHBlbmQoY2FudmFzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChmaXJzdENoaWxkLm5vZGVOYW1lID09PSAiQ0FOVkFTIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlyc3RDaGlsZC5yZXBsYWNlV2l0aChjYW52YXMpOwogICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlyc3RDaGlsZC5iZWZvcmUoY2FudmFzKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBhbm5vdGF0aW9uQ2FudmFzTWFwLmNsZWFyKCk7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgLyoqKi8gfSksCiAgICAgICAgICAgIC8qIDE2OCAqLwogICAgICAgICAgICAvKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzKSA9PiB7CgogICAgICAgICAgICAgICAgInVzZSBzdHJpY3QiOwoKCiAgICAgICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlCiAgICAgICAgICAgICAgICB9KSk7CiAgICAgICAgICAgICAgICBleHBvcnRzLkNvbG9yQ29udmVydGVycyA9IHZvaWQgMDsKICAgICAgICAgICAgICAgIGZ1bmN0aW9uIG1ha2VDb2xvckNvbXAobikgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKE1hdGgubWF4KDAsIE1hdGgubWluKDEsIG4pKSAqIDI1NSkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsICIwIik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjbGFzcyBDb2xvckNvbnZlcnRlcnMgewogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBDTVlLX0coX3JlZikgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgW2MsIHksIG0sIGtdID0gX3JlZjsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsiRyIsIDEgLSBNYXRoLm1pbigxLCAwLjMgKiBjICsgMC41OSAqIG0gKyAwLjExICogeSArIGspXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIEdfQ01ZSyhfcmVmMikgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgW2ddID0gX3JlZjI7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbIkNNWUsiLCAwLCAwLCAwLCAxIC0gZ107CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBHX1JHQihfcmVmMykgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgW2ddID0gX3JlZjM7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbIlJHQiIsIGcsIGcsIGddOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgR19IVE1MKF9yZWY0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBbZ10gPSBfcmVmNDsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgRyA9IG1ha2VDb2xvckNvbXAoZyk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBgIyR7R30ke0d9JHtHfWA7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBSR0JfRyhfcmVmNSkgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgW3IsIGcsIGJdID0gX3JlZjU7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbIkciLCAwLjMgKiByICsgMC41OSAqIGcgKyAwLjExICogYl07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBSR0JfSFRNTChfcmVmNikgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgW3IsIGcsIGJdID0gX3JlZjY7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFIgPSBtYWtlQ29sb3JDb21wKHIpOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBHID0gbWFrZUNvbG9yQ29tcChnKTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgQiA9IG1ha2VDb2xvckNvbXAoYik7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBgIyR7Un0ke0d9JHtCfWA7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBUX0hUTUwoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAiIzAwMDAwMDAwIjsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIENNWUtfUkdCKF9yZWY3KSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBbYywgeSwgbSwga10gPSBfcmVmNzsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsiUkdCIiwgMSAtIE1hdGgubWluKDEsIGMgKyBrKSwgMSAtIE1hdGgubWluKDEsIG0gKyBrKSwgMSAtIE1hdGgubWluKDEsIHkgKyBrKV07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBDTVlLX0hUTUwoY29tcG9uZW50cykgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZ2IgPSB0aGlzLkNNWUtfUkdCKGNvbXBvbmVudHMpLnNsaWNlKDEpOwogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5SR0JfSFRNTChyZ2IpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBzdGF0aWMgUkdCX0NNWUsoX3JlZjgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IFtyLCBnLCBiXSA9IF9yZWY4OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjID0gMSAtIHI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG0gPSAxIC0gZzsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeSA9IDEgLSBiOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBrID0gTWF0aC5taW4oYywgbSwgeSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbIkNNWUsiLCBjLCBtLCB5LCBrXTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBleHBvcnRzLkNvbG9yQ29udmVydGVycyA9IENvbG9yQ29udmVydGVyczsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTY5ICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuWGZhTGF5ZXIgPSB2b2lkIDA7CiAgICAgICAgICAgICAgICB2YXIgX3hmYV90ZXh0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTQpOwogICAgICAgICAgICAgICAgY2xhc3MgWGZhTGF5ZXIgewogICAgICAgICAgICAgICAgICAgIHN0YXRpYyBzZXR1cFN0b3JhZ2UoaHRtbCwgaWQsIGVsZW1lbnQsIHN0b3JhZ2UsIGludGVudCkgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdG9yZWREYXRhID0gc3RvcmFnZS5nZXRWYWx1ZShpZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG51bGwKICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZWxlbWVudC5uYW1lKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJ0ZXh0YXJlYSI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0b3JlZERhdGEudmFsdWUgIT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbC50ZXh0Q29udGVudCA9IHN0b3JlZERhdGEudmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnRlbnQgPT09ICJwcmludCIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0bWwuYWRkRXZlbnRMaXN0ZW5lcigiaW5wdXQiLCBldmVudCA9PiB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JhZ2Uuc2V0VmFsdWUoaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBldmVudC50YXJnZXQudmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJpbnB1dCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQuYXR0cmlidXRlcy50eXBlID09PSAicmFkaW8iIHx8IGVsZW1lbnQuYXR0cmlidXRlcy50eXBlID09PSAiY2hlY2tib3giKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdG9yZWREYXRhLnZhbHVlID09PSBlbGVtZW50LmF0dHJpYnV0ZXMueGZhT24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0bWwuc2V0QXR0cmlidXRlKCJjaGVja2VkIiwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc3RvcmVkRGF0YS52YWx1ZSA9PT0gZWxlbWVudC5hdHRyaWJ1dGVzLnhmYU9mZikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbC5yZW1vdmVBdHRyaWJ1dGUoImNoZWNrZWQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW50ZW50ID09PSAicHJpbnQiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBodG1sLmFkZEV2ZW50TGlzdGVuZXIoImNoYW5nZSIsIGV2ZW50ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JhZ2Uuc2V0VmFsdWUoaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZXZlbnQudGFyZ2V0LmNoZWNrZWQgPyBldmVudC50YXJnZXQuZ2V0QXR0cmlidXRlKCJ4ZmFPbiIpIDogZXZlbnQudGFyZ2V0LmdldEF0dHJpYnV0ZSgieGZhT2ZmIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RvcmVkRGF0YS52YWx1ZSAhPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbC5zZXRBdHRyaWJ1dGUoInZhbHVlIiwgc3RvcmVkRGF0YS52YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGludGVudCA9PT0gInByaW50IikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbC5hZGRFdmVudExpc3RlbmVyKCJpbnB1dCIsIGV2ZW50ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3JhZ2Uuc2V0VmFsdWUoaWQsIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZXZlbnQudGFyZ2V0LnZhbHVlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAic2VsZWN0IjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RvcmVkRGF0YS52YWx1ZSAhPT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG9wdGlvbiBvZiBlbGVtZW50LmNoaWxkcmVuKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9uLmF0dHJpYnV0ZXMudmFsdWUgPT09IHN0b3JlZERhdGEudmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb24uYXR0cmlidXRlcy5zZWxlY3RlZCA9IHRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbC5hZGRFdmVudExpc3RlbmVyKCJpbnB1dCIsIGV2ZW50ID0+IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IGV2ZW50LnRhcmdldC5vcHRpb25zOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IG9wdGlvbnMuc2VsZWN0ZWRJbmRleCA9PT0gLTEgPyAiIiA6IG9wdGlvbnNbb3B0aW9ucy5zZWxlY3RlZEluZGV4XS52YWx1ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmFnZS5zZXRWYWx1ZShpZCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgc3RhdGljIHNldEF0dHJpYnV0ZXMoX3JlZikgewogICAgICAgICAgICAgICAgICAgICAgICBsZXQgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdG9yYWdlID0gbnVsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVudCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmtTZXJ2aWNlCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBfcmVmOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzCiAgICAgICAgICAgICAgICAgICAgICAgIH0gPSBlbGVtZW50OwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpc0hUTUxBbmNob3JFbGVtZW50ID0gaHRtbCBpbnN0YW5jZW9mIEhUTUxBbmNob3JFbGVtZW50OwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0cmlidXRlcy50eXBlID09PSAicmFkaW8iKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzLm5hbWUgPSBgJHthdHRyaWJ1dGVzLm5hbWV9LSR7aW50ZW50fWA7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoYXR0cmlidXRlcykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGtleSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgImNsYXNzIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlLmxlbmd0aCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbC5zZXRBdHRyaWJ1dGUoa2V5LCB2YWx1ZS5qb2luKCIgIikpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgImRhdGFJZCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgImlkIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbC5zZXRBdHRyaWJ1dGUoImRhdGEtZWxlbWVudC1pZCIsIHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAic3R5bGUiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKGh0bWwuc3R5bGUsIHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAidGV4dENvbnRlbnQiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBodG1sLnRleHRDb250ZW50ID0gdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaXNIVE1MQW5jaG9yRWxlbWVudCB8fCBrZXkgIT09ICJocmVmIiAmJiBrZXkgIT09ICJuZXdXaW5kb3ciKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBodG1sLnNldEF0dHJpYnV0ZShrZXksIHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hUTUxBbmNob3JFbGVtZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5rU2VydmljZS5hZGRMaW5rQXR0cmlidXRlcyhodG1sLCBhdHRyaWJ1dGVzLmhyZWYsIGF0dHJpYnV0ZXMubmV3V2luZG93KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3RvcmFnZSAmJiBhdHRyaWJ1dGVzLmRhdGFJZCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXR1cFN0b3JhZ2UoaHRtbCwgYXR0cmlidXRlcy5kYXRhSWQsIGVsZW1lbnQsIHN0b3JhZ2UpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyByZW5kZXIocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdG9yYWdlID0gcGFyYW1ldGVycy5hbm5vdGF0aW9uU3RvcmFnZTsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbGlua1NlcnZpY2UgPSBwYXJhbWV0ZXJzLmxpbmtTZXJ2aWNlOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByb290ID0gcGFyYW1ldGVycy54ZmFIdG1sOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbnRlbnQgPSBwYXJhbWV0ZXJzLmludGVudCB8fCAiZGlzcGxheSI7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJvb3RIdG1sID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChyb290Lm5hbWUpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAocm9vdC5hdHRyaWJ1dGVzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZXMoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh0bWw6IHJvb3RIdG1sLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQ6IHJvb3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmtTZXJ2aWNlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGFjayA9IFtbcm9vdCwgLTEsIHJvb3RIdG1sXV07CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJvb3REaXYgPSBwYXJhbWV0ZXJzLmRpdjsKICAgICAgICAgICAgICAgICAgICAgICAgcm9vdERpdi5hcHBlbmQocm9vdEh0bWwpOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFyYW1ldGVycy52aWV3cG9ydCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdHJhbnNmb3JtID0gYG1hdHJpeCgke3BhcmFtZXRlcnMudmlld3BvcnQudHJhbnNmb3JtLmpvaW4oIiwiKX0pYDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3REaXYuc3R5bGUudHJhbnNmb3JtID0gdHJhbnNmb3JtOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbnRlbnQgIT09ICJyaWNoVGV4dCIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3REaXYuc2V0QXR0cmlidXRlKCJjbGFzcyIsICJ4ZmFMYXllciB4ZmFGb250Iik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGV4dERpdnMgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfY2hpbGQkYXR0cmlidXRlczsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFtwYXJlbnQsIGksIGh0bWxdID0gc3RhY2suYXQoLTEpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGkgKyAxID09PSBwYXJlbnQuY2hpbGRyZW4ubGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhY2sucG9wKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGlsZCA9IHBhcmVudC5jaGlsZHJlblsrK3N0YWNrLmF0KC0xKVsxXV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQgPT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ID0gY2hpbGQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobmFtZSA9PT0gIiN0ZXh0IikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5vZGUgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShjaGlsZC52YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dERpdnMucHVzaChub2RlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBodG1sLmFwcGVuZChub2RlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjaGlsZEh0bWw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQgIT09IG51bGwgJiYgY2hpbGQgIT09IHZvaWQgMCAmJiAoX2NoaWxkJGF0dHJpYnV0ZXMgPSBjaGlsZC5hdHRyaWJ1dGVzKSAhPT0gbnVsbCAmJiBfY2hpbGQkYXR0cmlidXRlcyAhPT0gdm9pZCAwICYmIF9jaGlsZCRhdHRyaWJ1dGVzLnhtbG5zKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRIdG1sID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKGNoaWxkLmF0dHJpYnV0ZXMueG1sbnMsIG5hbWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZEh0bWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KG5hbWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbC5hcHBlbmQoY2hpbGRIdG1sKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5hdHRyaWJ1dGVzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRBdHRyaWJ1dGVzKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaHRtbDogY2hpbGRIdG1sLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50OiBjaGlsZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmFnZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZW50LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5rU2VydmljZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmNoaWxkcmVuICYmIGNoaWxkLmNoaWxkcmVuLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFjay5wdXNoKFtjaGlsZCwgLTEsIGNoaWxkSHRtbF0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjaGlsZC52YWx1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5vZGUgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShjaGlsZC52YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF94ZmFfdGV4dC5YZmFUZXh0LnNob3VsZEJ1aWxkVGV4dChuYW1lKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0RGl2cy5wdXNoKG5vZGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZEh0bWwuYXBwZW5kKG5vZGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZWwgb2Ygcm9vdERpdi5xdWVyeVNlbGVjdG9yQWxsKCIueGZhTm9uSW50ZXJhY3RpdmUgaW5wdXQsIC54ZmFOb25JbnRlcmFjdGl2ZSB0ZXh0YXJlYSIpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoInJlYWRPbmx5IiwgdHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHREaXZzCiAgICAgICAgICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIHN0YXRpYyB1cGRhdGUocGFyYW1ldGVycykgewogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm0gPSBgbWF0cml4KCR7cGFyYW1ldGVycy52aWV3cG9ydC50cmFuc2Zvcm0uam9pbigiLCIpfSlgOwogICAgICAgICAgICAgICAgICAgICAgICBwYXJhbWV0ZXJzLmRpdi5zdHlsZS50cmFuc2Zvcm0gPSB0cmFuc2Zvcm07CiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlcnMuZGl2LmhpZGRlbiA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGV4cG9ydHMuWGZhTGF5ZXIgPSBYZmFMYXllcjsKCiAgICAgICAgICAgICAgICAvKioqLyB9KSwKICAgICAgICAgICAgLyogMTcwICovCiAgICAgICAgICAgIC8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiAgICAgICAgICAgICAgICAidXNlIHN0cmljdCI7CgoKICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgIGV4cG9ydHMuU1ZHR3JhcGhpY3MgPSB2b2lkIDA7CiAgICAgICAgICAgICAgICB2YXIgX2Rpc3BsYXlfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0Mik7CiAgICAgICAgICAgICAgICB2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEpOwogICAgICAgICAgICAgICAgdmFyIF9pc19ub2RlID0gX193X3BkZmpzX3JlcXVpcmVfXygzKTsKICAgICAgICAgICAgICAgIGxldCBTVkdHcmFwaGljcyA9IGNsYXNzIHsKICAgICAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcigpIHsKICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiTm90IGltcGxlbWVudGVkOiBTVkdHcmFwaGljcyIpOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBleHBvcnRzLlNWR0dyYXBoaWNzID0gU1ZHR3JhcGhpY3M7CiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgY29uc3QgU1ZHX0RFRkFVTFRTID0gewogICAgICAgICAgICAgICAgICAgICAgICBmb250U3R5bGU6ICJub3JtYWwiLAogICAgICAgICAgICAgICAgICAgICAgICBmb250V2VpZ2h0OiAibm9ybWFsIiwKICAgICAgICAgICAgICAgICAgICAgICAgZmlsbENvbG9yOiAiIzAwMDAwMCIKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGNvbnN0IFhNTF9OUyA9ICJodHRwOi8vd3d3LnczLm9yZy9YTUwvMTk5OC9uYW1lc3BhY2UiOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IFhMSU5LX05TID0gImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IExJTkVfQ0FQX1NUWUxFUyA9IFsiYnV0dCIsICJyb3VuZCIsICJzcXVhcmUiXTsKICAgICAgICAgICAgICAgICAgICBjb25zdCBMSU5FX0pPSU5fU1RZTEVTID0gWyJtaXRlciIsICJyb3VuZCIsICJiZXZlbCJdOwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGNyZWF0ZU9iamVjdFVSTCA9IGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb250ZW50VHlwZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogIiI7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmb3JjZURhdGFTY2hlbWEgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICBpZiAoVVJMLmNyZWF0ZU9iamVjdFVSTCAmJiB0eXBlb2YgQmxvYiAhPT0gInVuZGVmaW5lZCIgJiYgIWZvcmNlRGF0YVNjaGVtYSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFVSTC5jcmVhdGVPYmplY3RVUkwobmV3IEJsb2IoW2RhdGFdLCB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogY29udGVudFR5cGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaWdpdHMgPSAiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLz0iOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgYnVmZmVyID0gYGRhdGE6JHtjb250ZW50VHlwZX07YmFzZTY0LGA7CiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGRhdGEubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYjEgPSBkYXRhW2ldICYgMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGIyID0gZGF0YVtpICsgMV0gJiAweGZmOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYjMgPSBkYXRhW2kgKyAyXSAmIDB4ZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkMSA9IGIxID4+IDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZDIgPSAoYjEgJiAzKSA8PCA0IHwgYjIgPj4gNDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGQzID0gaSArIDEgPCBpaSA/IChiMiAmIDB4ZikgPDwgMiB8IGIzID4+IDYgOiA2NDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGQ0ID0gaSArIDIgPCBpaSA/IGIzICYgMHgzZiA6IDY0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyICs9IGRpZ2l0c1tkMV0gKyBkaWdpdHNbZDJdICsgZGlnaXRzW2QzXSArIGRpZ2l0c1tkNF07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGJ1ZmZlcjsKICAgICAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnZlcnRJbWdEYXRhVG9QbmcgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFBOR19IRUFERVIgPSBuZXcgVWludDhBcnJheShbMHg4OSwgMHg1MCwgMHg0ZSwgMHg0NywgMHgwZCwgMHgwYSwgMHgxYSwgMHgwYV0pOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBDSFVOS19XUkFQUEVSX1NJWkUgPSAxMjsKICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3JjVGFibGUgPSBuZXcgSW50MzJBcnJheSgyNTYpOwogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgYyA9IGk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBoID0gMDsgaCA8IDg7IGgrKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjICYgMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjID0gMHhlZGI4ODMyMCBeIGMgPj4gMSAmIDB4N2ZmZmZmZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYyA9IGMgPj4gMSAmIDB4N2ZmZmZmZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JjVGFibGVbaV0gPSBjOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGNyYzMyKGRhdGEsIHN0YXJ0LCBlbmQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjcmMgPSAtMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYSA9IChjcmMgXiBkYXRhW2ldKSAmIDB4ZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYiA9IGNyY1RhYmxlW2FdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNyYyA9IGNyYyA+Pj4gOCBeIGI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3JjIF4gLTE7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gd3JpdGVQbmdDaHVuayh0eXBlLCBib2R5LCBkYXRhLCBvZmZzZXQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBwID0gb2Zmc2V0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbGVuID0gYm9keS5sZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhW3BdID0gbGVuID4+IDI0ICYgMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFbcCArIDFdID0gbGVuID4+IDE2ICYgMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFbcCArIDJdID0gbGVuID4+IDggJiAweGZmOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVtwICsgM10gPSBsZW4gJiAweGZmOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcCArPSA0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVtwXSA9IHR5cGUuY2hhckNvZGVBdCgwKSAmIDB4ZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhW3AgKyAxXSA9IHR5cGUuY2hhckNvZGVBdCgxKSAmIDB4ZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhW3AgKyAyXSA9IHR5cGUuY2hhckNvZGVBdCgyKSAmIDB4ZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhW3AgKyAzXSA9IHR5cGUuY2hhckNvZGVBdCgzKSAmIDB4ZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwICs9IDQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLnNldChib2R5LCBwKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAgKz0gYm9keS5sZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjcmMgPSBjcmMzMihkYXRhLCBvZmZzZXQgKyA0LCBwKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFbcF0gPSBjcmMgPj4gMjQgJiAweGZmOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVtwICsgMV0gPSBjcmMgPj4gMTYgJiAweGZmOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVtwICsgMl0gPSBjcmMgPj4gOCAmIDB4ZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhW3AgKyAzXSA9IGNyYyAmIDB4ZmY7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gYWRsZXIzMihkYXRhLCBzdGFydCwgZW5kKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgYSA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgYiA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGEgPSAoYSArIChkYXRhW2ldICYgMHhmZikpICUgNjU1MjE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYiA9IChiICsgYSkgJSA2NTUyMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBiIDw8IDE2IHwgYTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBkZWZsYXRlU3luYyhsaXRlcmFscykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfaXNfbm9kZS5pc05vZGVKUykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkZWZsYXRlU3luY1VuY29tcHJlc3NlZChsaXRlcmFscyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBpbnB1dDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFyc2VJbnQocHJvY2Vzcy52ZXJzaW9ucy5ub2RlKSA+PSA4KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlucHV0ID0gbGl0ZXJhbHM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQgPSBCdWZmZXIuZnJvbShsaXRlcmFscyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG91dHB1dCA9IHJlcXVpcmUoInpsaWIiKS5kZWZsYXRlU3luYyhpbnB1dCwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbDogOQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXRwdXQgaW5zdGFuY2VvZiBVaW50OEFycmF5ID8gb3V0cHV0IDogbmV3IFVpbnQ4QXJyYXkob3V0cHV0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoIk5vdCBjb21wcmVzc2luZyBQTkcgYmVjYXVzZSB6bGliLmRlZmxhdGVTeW5jIGlzIHVuYXZhaWxhYmxlOiAiICsgZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGVmbGF0ZVN5bmNVbmNvbXByZXNzZWQobGl0ZXJhbHMpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGRlZmxhdGVTeW5jVW5jb21wcmVzc2VkKGxpdGVyYWxzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgbGVuID0gbGl0ZXJhbHMubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWF4QmxvY2tMZW5ndGggPSAweGZmZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWZsYXRlQmxvY2tzID0gTWF0aC5jZWlsKGxlbiAvIG1heEJsb2NrTGVuZ3RoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkYXQgPSBuZXcgVWludDhBcnJheSgyICsgbGVuICsgZGVmbGF0ZUJsb2NrcyAqIDUgKyA0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBwaSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGF0W3BpKytdID0gMHg3ODsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYXRbcGkrK10gPSAweDljOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHBvcyA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAobGVuID4gbWF4QmxvY2tMZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGF0W3BpKytdID0gMHgwMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGF0W3BpKytdID0gMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGF0W3BpKytdID0gMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGF0W3BpKytdID0gMHgwMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGF0W3BpKytdID0gMHgwMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGF0LnNldChsaXRlcmFscy5zdWJhcnJheShwb3MsIHBvcyArIG1heEJsb2NrTGVuZ3RoKSwgcGkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBpICs9IG1heEJsb2NrTGVuZ3RoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvcyArPSBtYXhCbG9ja0xlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW4gLT0gbWF4QmxvY2tMZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGF0W3BpKytdID0gMHgwMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYXRbcGkrK10gPSBsZW4gJiAweGZmOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRhdFtwaSsrXSA9IGxlbiA+PiA4ICYgMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYXRbcGkrK10gPSB+bGVuICYgMHhmZmZmICYgMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYXRbcGkrK10gPSAofmxlbiAmIDB4ZmZmZikgPj4gOCAmIDB4ZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGF0LnNldChsaXRlcmFscy5zdWJhcnJheShwb3MpLCBwaSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwaSArPSBsaXRlcmFscy5sZW5ndGggLSBwb3M7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhZGxlciA9IGFkbGVyMzIobGl0ZXJhbHMsIDAsIGxpdGVyYWxzLmxlbmd0aCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZGF0W3BpKytdID0gYWRsZXIgPj4gMjQgJiAweGZmOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWRhdFtwaSsrXSA9IGFkbGVyID4+IDE2ICYgMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYXRbcGkrK10gPSBhZGxlciA+PiA4ICYgMHhmZjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkYXRbcGkrK10gPSBhZGxlciAmIDB4ZmY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaWRhdDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBlbmNvZGUoaW1nRGF0YSwga2luZCwgZm9yY2VEYXRhU2NoZW1hLCBpc01hc2spIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gaW1nRGF0YS53aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGltZ0RhdGEuaGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGJpdERlcHRoLCBjb2xvclR5cGUsIGxpbmVTaXplOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYnl0ZXMgPSBpbWdEYXRhLmRhdGE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGtpbmQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkltYWdlS2luZC5HUkFZU0NBTEVfMUJQUDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3JUeXBlID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYml0RGVwdGggPSAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lU2l6ZSA9IHdpZHRoICsgNyA+PiAzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLkltYWdlS2luZC5SR0JfMjRCUFA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yVHlwZSA9IDI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpdERlcHRoID0gODsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZVNpemUgPSB3aWR0aCAqIDM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuSW1hZ2VLaW5kLlJHQkFfMzJCUFA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yVHlwZSA9IDY7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJpdERlcHRoID0gODsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZVNpemUgPSB3aWR0aCAqIDQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiaW52YWxpZCBmb3JtYXQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpdGVyYWxzID0gbmV3IFVpbnQ4QXJyYXkoKDEgKyBsaW5lU2l6ZSkgKiBoZWlnaHQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG9mZnNldExpdGVyYWxzID0gMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRCeXRlcyA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IGhlaWdodDsgKyt5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGl0ZXJhbHNbb2Zmc2V0TGl0ZXJhbHMrK10gPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpdGVyYWxzLnNldChieXRlcy5zdWJhcnJheShvZmZzZXRCeXRlcywgb2Zmc2V0Qnl0ZXMgKyBsaW5lU2l6ZSksIG9mZnNldExpdGVyYWxzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRCeXRlcyArPSBsaW5lU2l6ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRMaXRlcmFscyArPSBsaW5lU2l6ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChraW5kID09PSBfdXRpbC5JbWFnZUtpbmQuR1JBWVNDQUxFXzFCUFAgJiYgaXNNYXNrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0TGl0ZXJhbHMgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0TGl0ZXJhbHMrKzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW5lU2l6ZTsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXRlcmFsc1tvZmZzZXRMaXRlcmFscysrXSBePSAweGZmOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaWhkciA9IG5ldyBVaW50OEFycmF5KFt3aWR0aCA+PiAyNCAmIDB4ZmYsIHdpZHRoID4+IDE2ICYgMHhmZiwgd2lkdGggPj4gOCAmIDB4ZmYsIHdpZHRoICYgMHhmZiwgaGVpZ2h0ID4+IDI0ICYgMHhmZiwgaGVpZ2h0ID4+IDE2ICYgMHhmZiwgaGVpZ2h0ID4+IDggJiAweGZmLCBoZWlnaHQgJiAweGZmLCBiaXREZXB0aCwgY29sb3JUeXBlLCAweDAwLCAweDAwLCAweDAwXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpZGF0ID0gZGVmbGF0ZVN5bmMobGl0ZXJhbHMpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcG5nTGVuZ3RoID0gUE5HX0hFQURFUi5sZW5ndGggKyBDSFVOS19XUkFQUEVSX1NJWkUgKiAzICsgaWhkci5sZW5ndGggKyBpZGF0Lmxlbmd0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBuZXcgVWludDhBcnJheShwbmdMZW5ndGgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG9mZnNldCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhLnNldChQTkdfSEVBREVSLCBvZmZzZXQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ICs9IFBOR19IRUFERVIubGVuZ3RoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgd3JpdGVQbmdDaHVuaygiSUhEUiIsIGloZHIsIGRhdGEsIG9mZnNldCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQgKz0gQ0hVTktfV1JBUFBFUl9TSVpFICsgaWhkci5sZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0ZVBuZ0NodW5rKCJJREFUQSIsIGlkYXQsIGRhdGEsIG9mZnNldCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQgKz0gQ0hVTktfV1JBUFBFUl9TSVpFICsgaWRhdC5sZW5ndGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3cml0ZVBuZ0NodW5rKCJJRU5EIiwgbmV3IFVpbnQ4QXJyYXkoMCksIGRhdGEsIG9mZnNldCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3JlYXRlT2JqZWN0VVJMKGRhdGEsICJpbWFnZS9wbmciLCBmb3JjZURhdGFTY2hlbWEpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBjb252ZXJ0SW1nRGF0YVRvUG5nKGltZ0RhdGEsIGZvcmNlRGF0YVNjaGVtYSwgaXNNYXNrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBraW5kID0gaW1nRGF0YS5raW5kID09PSB1bmRlZmluZWQgPyBfdXRpbC5JbWFnZUtpbmQuR1JBWVNDQUxFXzFCUFAgOiBpbWdEYXRhLmtpbmQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZW5jb2RlKGltZ0RhdGEsIGtpbmQsIGZvcmNlRGF0YVNjaGVtYSwgaXNNYXNrKTsKICAgICAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgICAgICB9KCk7CiAgICAgICAgICAgICAgICAgICAgY2xhc3MgU1ZHRXh0cmFTdGF0ZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mb250U2l6ZVNjYWxlID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZm9udFdlaWdodCA9IFNWR19ERUZBVUxUUy5mb250V2VpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mb250U2l6ZSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRleHRNYXRyaXggPSBfdXRpbC5JREVOVElUWV9NQVRSSVg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZvbnRNYXRyaXggPSBfdXRpbC5GT05UX0lERU5USVRZX01BVFJJWDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGVhZGluZyA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRleHRSZW5kZXJpbmdNb2RlID0gX3V0aWwuVGV4dFJlbmRlcmluZ01vZGUuRklMTDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGV4dE1hdHJpeFNjYWxlID0gMTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMueCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnkgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5saW5lWCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxpbmVZID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2hhclNwYWNpbmcgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53b3JkU3BhY2luZyA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRleHRIU2NhbGUgPSAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXh0UmlzZSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbGxDb2xvciA9IFNWR19ERUZBVUxUUy5maWxsQ29sb3I7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cm9rZUNvbG9yID0gIiMwMDAwMDAiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWxsQWxwaGEgPSAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJva2VBbHBoYSA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxpbmVXaWR0aCA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxpbmVKb2luID0gIiI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxpbmVDYXAgPSAiIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWl0ZXJMaW1pdCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRhc2hBcnJheSA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXNoUGhhc2UgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZXBlbmRlbmNpZXMgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWN0aXZlQ2xpcFVybCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsaXBHcm91cCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1hc2tJZCA9ICIiOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNsb25lKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5jcmVhdGUodGhpcyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc2V0Q3VycmVudFBvaW50KHgsIHkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMueCA9IHg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnkgPSB5OwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIG9wTGlzdFRvVHJlZShvcExpc3QpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG9wVHJlZSA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0bXAgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBvcExpc3RFbGVtZW50IG9mIG9wTGlzdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wTGlzdEVsZW1lbnQuZm4gPT09ICJzYXZlIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wVHJlZS5wdXNoKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm5JZDogOTIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZuOiAiZ3JvdXAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtczogW10KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bXAucHVzaChvcFRyZWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wVHJlZSA9IG9wVHJlZS5hdCgtMSkuaXRlbXM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3BMaXN0RWxlbWVudC5mbiA9PT0gInJlc3RvcmUiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3BUcmVlID0gdG1wLnBvcCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcFRyZWUucHVzaChvcExpc3RFbGVtZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3BUcmVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBwZih2YWx1ZSkgewogICAgICAgICAgICAgICAgICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcih2YWx1ZSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS50b1N0cmluZygpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHMgPSB2YWx1ZS50b0ZpeGVkKDEwKTsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGkgPSBzLmxlbmd0aCAtIDE7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzW2ldICE9PSAiMCIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGktLTsKICAgICAgICAgICAgICAgICAgICAgICAgfSB3aGlsZSAoc1tpXSA9PT0gIjAiKTsKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMuc3Vic3RyaW5nKDAsIHNbaV0gPT09ICIuIiA/IGkgOiBpICsgMSk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHBtKG0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1bNF0gPT09IDAgJiYgbVs1XSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1bMV0gPT09IDAgJiYgbVsyXSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtWzBdID09PSAxICYmIG1bM10gPT09IDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICIiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYHNjYWxlKCR7cGYobVswXSl9ICR7cGYobVszXSl9KWA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobVswXSA9PT0gbVszXSAmJiBtWzFdID09PSAtbVsyXSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGEgPSBNYXRoLmFjb3MobVswXSkgKiAxODAgLyBNYXRoLlBJOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBgcm90YXRlKCR7cGYoYSl9KWA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobVswXSA9PT0gMSAmJiBtWzFdID09PSAwICYmIG1bMl0gPT09IDAgJiYgbVszXSA9PT0gMSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBgdHJhbnNsYXRlKCR7cGYobVs0XSl9ICR7cGYobVs1XSl9KWA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGBtYXRyaXgoJHtwZihtWzBdKX0gJHtwZihtWzFdKX0gJHtwZihtWzJdKX0gJHtwZihtWzNdKX0gJHtwZihtWzRdKX0gYCArIGAke3BmKG1bNV0pfSlgOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBsZXQgY2xpcENvdW50ID0gMDsKICAgICAgICAgICAgICAgICAgICBsZXQgbWFza0NvdW50ID0gMDsKICAgICAgICAgICAgICAgICAgICBsZXQgc2hhZGluZ0NvdW50ID0gMDsKICAgICAgICAgICAgICAgICAgICBleHBvcnRzLlNWR0dyYXBoaWNzID0gU1ZHR3JhcGhpY3MgPSBjbGFzcyB7CiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0cnVjdG9yKGNvbW1vbk9ianMsIG9ianMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmb3JjZURhdGFTY2hlbWEgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IGZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF9kaXNwbGF5X3V0aWxzLmRlcHJlY2F0ZWQpKCJUaGUgU1ZHIGJhY2stZW5kIGlzIG5vIGxvbmdlciBtYWludGFpbmVkIGFuZCAqbWF5KiBiZSByZW1vdmVkIGluIHRoZSBmdXR1cmUuIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN2Z0ZhY3RvcnkgPSBuZXcgX2Rpc3BsYXlfdXRpbHMuRE9NU1ZHRmFjdG9yeSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50ID0gbmV3IFNWR0V4dHJhU3RhdGUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJhbnNmb3JtTWF0cml4ID0gX3V0aWwuSURFTlRJVFlfTUFUUklYOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc2Zvcm1TdGFjayA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5leHRyYVN0YWNrID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNvbW1vbk9ianMgPSBjb21tb25PYmpzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vYmpzID0gb2JqczsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGVuZGluZ0NsaXAgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wZW5kaW5nRU9GaWxsID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVtYmVkRm9udHMgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW1iZWRkZWRGb250cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNzc1N0eWxlID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZm9yY2VEYXRhU2NoZW1hID0gISFmb3JjZURhdGFTY2hlbWE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9vcGVyYXRvcklkTWFwcGluZyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBvcCBpbiBfdXRpbC5PUFMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9vcGVyYXRvcklkTWFwcGluZ1tfdXRpbC5PUFNbb3BdXSA9IG9wOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGdldE9iamVjdChkYXRhKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZmFsbGJhY2sgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRhdGEgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRhdGEuc3RhcnRzV2l0aCgiZ18iKSA/IHRoaXMuY29tbW9uT2Jqcy5nZXQoZGF0YSkgOiB0aGlzLm9ianMuZ2V0KGRhdGEpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbGxiYWNrOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHNhdmUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYW5zZm9ybVN0YWNrLnB1c2godGhpcy50cmFuc2Zvcm1NYXRyaXgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2xkID0gdGhpcy5jdXJyZW50OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5leHRyYVN0YWNrLnB1c2gob2xkKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudCA9IG9sZC5jbG9uZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3RvcmUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYW5zZm9ybU1hdHJpeCA9IHRoaXMudHJhbnNmb3JtU3RhY2sucG9wKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQgPSB0aGlzLmV4dHJhU3RhY2sucG9wKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBlbmRpbmdDbGlwID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudGdycCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAoaXRlbXMpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2F2ZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5leGVjdXRlT3BUcmVlKGl0ZW1zKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzdG9yZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGxvYWREZXBlbmRlbmNpZXMob3BlcmF0b3JMaXN0KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmbkFycmF5ID0gb3BlcmF0b3JMaXN0LmZuQXJyYXk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhcmdzQXJyYXkgPSBvcGVyYXRvckxpc3QuYXJnc0FycmF5OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZm5BcnJheS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZuQXJyYXlbaV0gIT09IF91dGlsLk9QUy5kZXBlbmRlbmN5KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG9iaiBvZiBhcmdzQXJyYXlbaV0pIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2Jqc1Bvb2wgPSBvYmouc3RhcnRzV2l0aCgiZ18iKSA/IHRoaXMuY29tbW9uT2JqcyA6IHRoaXMub2JqczsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcHJvbWlzZSA9IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2Jqc1Bvb2wuZ2V0KG9iaiwgcmVzb2x2ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuZGVwZW5kZW5jaWVzLnB1c2gocHJvbWlzZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHRoaXMuY3VycmVudC5kZXBlbmRlbmNpZXMpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybShhLCBiLCBjLCBkLCBlLCBmKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1NYXRyaXggPSBbYSwgYiwgYywgZCwgZSwgZl07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYW5zZm9ybU1hdHJpeCA9IF91dGlsLlV0aWwudHJhbnNmb3JtKHRoaXMudHJhbnNmb3JtTWF0cml4LCB0cmFuc2Zvcm1NYXRyaXgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50Z3JwID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBnZXRTVkcob3BlcmF0b3JMaXN0LCB2aWV3cG9ydCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52aWV3cG9ydCA9IHZpZXdwb3J0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3ZnRWxlbWVudCA9IHRoaXMuX2luaXRpYWxpemUodmlld3BvcnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9hZERlcGVuZGVuY2llcyhvcGVyYXRvckxpc3QpLnRoZW4oKCkgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMudHJhbnNmb3JtTWF0cml4ID0gX3V0aWwuSURFTlRJVFlfTUFUUklYOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZXhlY3V0ZU9wVHJlZSh0aGlzLmNvbnZlcnRPcExpc3Qob3BlcmF0b3JMaXN0KSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN2Z0VsZW1lbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjb252ZXJ0T3BMaXN0KG9wZXJhdG9yTGlzdCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb3BlcmF0b3JJZE1hcHBpbmcgPSB0aGlzLl9vcGVyYXRvcklkTWFwcGluZzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFyZ3NBcnJheSA9IG9wZXJhdG9yTGlzdC5hcmdzQXJyYXk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmbkFycmF5ID0gb3BlcmF0b3JMaXN0LmZuQXJyYXk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvcExpc3QgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGZuQXJyYXkubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZuSWQgPSBmbkFycmF5W2ldOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wTGlzdC5wdXNoKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm5JZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm46IG9wZXJhdG9ySWRNYXBwaW5nW2ZuSWRdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmdzOiBhcmdzQXJyYXlbaV0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvcExpc3RUb1RyZWUob3BMaXN0KTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBleGVjdXRlT3BUcmVlKG9wVHJlZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBvcFRyZWVFbGVtZW50IG9mIG9wVHJlZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZuID0gb3BUcmVlRWxlbWVudC5mbjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmbklkID0gb3BUcmVlRWxlbWVudC5mbklkOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGFyZ3MgPSBvcFRyZWVFbGVtZW50LmFyZ3M7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChmbklkIHwgMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5iZWdpblRleHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJlZ2luVGV4dCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmRlcGVuZGVuY3k6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0TGVhZGluZzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0TGVhZGluZyhhcmdzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRMZWFkaW5nTW92ZVRleHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldExlYWRpbmdNb3ZlVGV4dChhcmdzWzBdLCBhcmdzWzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRGb250OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRGb250KGFyZ3MpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNob3dUZXh0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zaG93VGV4dChhcmdzWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zaG93U3BhY2VkVGV4dDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2hvd1RleHQoYXJnc1swXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMuZW5kVGV4dDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5kVGV4dCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLm1vdmVUZXh0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tb3ZlVGV4dChhcmdzWzBdLCBhcmdzWzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRDaGFyU3BhY2luZzoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0Q2hhclNwYWNpbmcoYXJnc1swXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0V29yZFNwYWNpbmc6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFdvcmRTcGFjaW5nKGFyZ3NbMF0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldEhTY2FsZToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0SFNjYWxlKGFyZ3NbMF0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldFRleHRNYXRyaXg6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFRleHRNYXRyaXgoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSwgYXJnc1s0XSwgYXJnc1s1XSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0VGV4dFJpc2U6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFRleHRSaXNlKGFyZ3NbMF0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldFRleHRSZW5kZXJpbmdNb2RlOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRUZXh0UmVuZGVyaW5nTW9kZShhcmdzWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRMaW5lV2lkdGg6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldExpbmVXaWR0aChhcmdzWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRMaW5lSm9pbjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0TGluZUpvaW4oYXJnc1swXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0TGluZUNhcDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0TGluZUNhcChhcmdzWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRNaXRlckxpbWl0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRNaXRlckxpbWl0KGFyZ3NbMF0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldEZpbGxSR0JDb2xvcjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0RmlsbFJHQkNvbG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldFN0cm9rZVJHQkNvbG9yOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTdHJva2VSR0JDb2xvcihhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRTdHJva2VDb2xvck46CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFN0cm9rZUNvbG9yTihhcmdzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRGaWxsQ29sb3JOOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRGaWxsQ29sb3JOKGFyZ3MpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNoYWRpbmdGaWxsOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zaGFkaW5nRmlsbChhcmdzWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXREYXNoOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXREYXNoKGFyZ3NbMF0sIGFyZ3NbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldFJlbmRlcmluZ0ludGVudDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UmVuZGVyaW5nSW50ZW50KGFyZ3NbMF0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldEZsYXRuZXNzOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRGbGF0bmVzcyhhcmdzWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRHU3RhdGU6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEdTdGF0ZShhcmdzWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5maWxsOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maWxsKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMuZW9GaWxsOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lb0ZpbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zdHJva2U6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN0cm9rZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmZpbGxTdHJva2U6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbGxTdHJva2UoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5lb0ZpbGxTdHJva2U6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVvRmlsbFN0cm9rZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmNsaXA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsaXAoIm5vbnplcm8iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5lb0NsaXA6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsaXAoImV2ZW5vZGQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5wYWludFNvbGlkQ29sb3JJbWFnZU1hc2s6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhaW50U29saWRDb2xvckltYWdlTWFzaygpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnBhaW50SW1hZ2VYT2JqZWN0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYWludEltYWdlWE9iamVjdChhcmdzWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5wYWludElubGluZUltYWdlWE9iamVjdDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFpbnRJbmxpbmVJbWFnZVhPYmplY3QoYXJnc1swXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMucGFpbnRJbWFnZU1hc2tYT2JqZWN0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYWludEltYWdlTWFza1hPYmplY3QoYXJnc1swXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMucGFpbnRGb3JtWE9iamVjdEJlZ2luOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYWludEZvcm1YT2JqZWN0QmVnaW4oYXJnc1swXSwgYXJnc1sxXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMucGFpbnRGb3JtWE9iamVjdEVuZDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFpbnRGb3JtWE9iamVjdEVuZCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmNsb3NlUGF0aDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xvc2VQYXRoKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMuY2xvc2VTdHJva2U6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsb3NlU3Ryb2tlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMuY2xvc2VGaWxsU3Ryb2tlOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbG9zZUZpbGxTdHJva2UoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5jbG9zZUVPRmlsbFN0cm9rZToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xvc2VFT0ZpbGxTdHJva2UoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5uZXh0TGluZToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubmV4dExpbmUoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy50cmFuc2Zvcm06CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnRyYW5zZm9ybShhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdLCBhcmdzWzNdLCBhcmdzWzRdLCBhcmdzWzVdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5jb25zdHJ1Y3RQYXRoOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3RQYXRoKGFyZ3NbMF0sIGFyZ3NbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmVuZFBhdGg6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVuZFBhdGgoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIDkyOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5ncm91cChvcFRyZWVFbGVtZW50Lml0ZW1zKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBVbmltcGxlbWVudGVkIG9wZXJhdG9yICR7Zm59YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc2V0V29yZFNwYWNpbmcod29yZFNwYWNpbmcpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC53b3JkU3BhY2luZyA9IHdvcmRTcGFjaW5nOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHNldENoYXJTcGFjaW5nKGNoYXJTcGFjaW5nKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuY2hhclNwYWNpbmcgPSBjaGFyU3BhY2luZzsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBuZXh0TGluZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubW92ZVRleHQoMCwgdGhpcy5jdXJyZW50LmxlYWRpbmcpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRleHRNYXRyaXgoYSwgYiwgYywgZCwgZSwgZikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMuY3VycmVudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudGV4dE1hdHJpeCA9IGN1cnJlbnQubGluZU1hdHJpeCA9IFthLCBiLCBjLCBkLCBlLCBmXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudGV4dE1hdHJpeFNjYWxlID0gTWF0aC5oeXBvdChhLCBiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQueCA9IGN1cnJlbnQubGluZVggPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC55ID0gY3VycmVudC5saW5lWSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Lnhjb29yZHMgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQueWNvb3JkcyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC50c3BhbiA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGVFbGVtZW50KCJzdmc6dHNwYW4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudHNwYW4uc2V0QXR0cmlidXRlTlMobnVsbCwgImZvbnQtZmFtaWx5IiwgY3VycmVudC5mb250RmFtaWx5KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudHNwYW4uc2V0QXR0cmlidXRlTlMobnVsbCwgImZvbnQtc2l6ZSIsIGAke3BmKGN1cnJlbnQuZm9udFNpemUpfXB4YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnRzcGFuLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ5IiwgcGYoLWN1cnJlbnQueSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC50eHRFbGVtZW50ID0gdGhpcy5zdmdGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoInN2Zzp0ZXh0Iik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnR4dEVsZW1lbnQuYXBwZW5kKGN1cnJlbnQudHNwYW4pOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGJlZ2luVGV4dCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmN1cnJlbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnggPSBjdXJyZW50LmxpbmVYID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQueSA9IGN1cnJlbnQubGluZVkgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC50ZXh0TWF0cml4ID0gX3V0aWwuSURFTlRJVFlfTUFUUklYOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5saW5lTWF0cml4ID0gX3V0aWwuSURFTlRJVFlfTUFUUklYOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC50ZXh0TWF0cml4U2NhbGUgPSAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC50c3BhbiA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGVFbGVtZW50KCJzdmc6dHNwYW4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudHh0RWxlbWVudCA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGVFbGVtZW50KCJzdmc6dGV4dCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC50eHRncnAgPSB0aGlzLnN2Z0ZhY3RvcnkuY3JlYXRlRWxlbWVudCgic3ZnOmciKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQueGNvb3JkcyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC55Y29vcmRzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgbW92ZVRleHQoeCwgeSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMuY3VycmVudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQueCA9IGN1cnJlbnQubGluZVggKz0geDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQueSA9IGN1cnJlbnQubGluZVkgKz0geTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQueGNvb3JkcyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC55Y29vcmRzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnRzcGFuID0gdGhpcy5zdmdGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoInN2Zzp0c3BhbiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC50c3Bhbi5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZm9udC1mYW1pbHkiLCBjdXJyZW50LmZvbnRGYW1pbHkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC50c3Bhbi5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZm9udC1zaXplIiwgYCR7cGYoY3VycmVudC5mb250U2l6ZSl9cHhgKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudHNwYW4uc2V0QXR0cmlidXRlTlMobnVsbCwgInkiLCBwZigtY3VycmVudC55KSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc2hvd1RleHQoZ2x5cGhzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5jdXJyZW50OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZm9udCA9IGN1cnJlbnQuZm9udDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvbnRTaXplID0gY3VycmVudC5mb250U2l6ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmb250U2l6ZSA9PT0gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvbnRTaXplU2NhbGUgPSBjdXJyZW50LmZvbnRTaXplU2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGFyU3BhY2luZyA9IGN1cnJlbnQuY2hhclNwYWNpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3b3JkU3BhY2luZyA9IGN1cnJlbnQud29yZFNwYWNpbmc7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmb250RGlyZWN0aW9uID0gY3VycmVudC5mb250RGlyZWN0aW9uOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGV4dEhTY2FsZSA9IGN1cnJlbnQudGV4dEhTY2FsZSAqIGZvbnREaXJlY3Rpb247CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB2ZXJ0aWNhbCA9IGZvbnQudmVydGljYWw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzcGFjaW5nRGlyID0gdmVydGljYWwgPyAxIDogLTE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWZhdWx0Vk1ldHJpY3MgPSBmb250LmRlZmF1bHRWTWV0cmljczsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoQWR2YW5jZVNjYWxlID0gZm9udFNpemUgKiBjdXJyZW50LmZvbnRNYXRyaXhbMF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgeCA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGdseXBoIG9mIGdseXBocykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnbHlwaCA9PT0gbnVsbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ICs9IGZvbnREaXJlY3Rpb24gKiB3b3JkU3BhY2luZzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZ2x5cGggPT09ICJudW1iZXIiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggKz0gc3BhY2luZ0RpciAqIGdseXBoICogZm9udFNpemUgLyAxMDAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3BhY2luZyA9IChnbHlwaC5pc1NwYWNlID8gd29yZFNwYWNpbmcgOiAwKSArIGNoYXJTcGFjaW5nOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNoYXJhY3RlciA9IGdseXBoLmZvbnRDaGFyOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzY2FsZWRYLCBzY2FsZWRZOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCB3aWR0aCA9IGdseXBoLndpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2ZXJ0aWNhbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgdng7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHZtZXRyaWMgPSBnbHlwaC52bWV0cmljIHx8IGRlZmF1bHRWTWV0cmljczsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdnggPSBnbHlwaC52bWV0cmljID8gdm1ldHJpY1sxXSA6IHdpZHRoICogMC41OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2eCA9IC12eCAqIHdpZHRoQWR2YW5jZVNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB2eSA9IHZtZXRyaWNbMl0gKiB3aWR0aEFkdmFuY2VTY2FsZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSB2bWV0cmljID8gLXZtZXRyaWNbMF0gOiB3aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVkWCA9IHZ4IC8gZm9udFNpemVTY2FsZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVkWSA9ICh4ICsgdnkpIC8gZm9udFNpemVTY2FsZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZWRYID0geCAvIGZvbnRTaXplU2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlZFkgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2x5cGguaXNJbkZvbnQgfHwgZm9udC5taXNzaW5nRmlsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Lnhjb29yZHMucHVzaChjdXJyZW50LnggKyBzY2FsZWRYKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZlcnRpY2FsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Lnljb29yZHMucHVzaCgtY3VycmVudC55ICsgc2NhbGVkWSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC50c3Bhbi50ZXh0Q29udGVudCArPSBjaGFyYWN0ZXI7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHt9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNoYXJXaWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodmVydGljYWwpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hhcldpZHRoID0gd2lkdGggKiB3aWR0aEFkdmFuY2VTY2FsZSAtIHNwYWNpbmcgKiBmb250RGlyZWN0aW9uOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNoYXJXaWR0aCA9IHdpZHRoICogd2lkdGhBZHZhbmNlU2NhbGUgKyBzcGFjaW5nICogZm9udERpcmVjdGlvbjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCArPSBjaGFyV2lkdGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnRzcGFuLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ4IiwgY3VycmVudC54Y29vcmRzLm1hcChwZikuam9pbigiICIpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh2ZXJ0aWNhbCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudHNwYW4uc2V0QXR0cmlidXRlTlMobnVsbCwgInkiLCBjdXJyZW50Lnljb29yZHMubWFwKHBmKS5qb2luKCIgIikpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnRzcGFuLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ5IiwgcGYoLWN1cnJlbnQueSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHZlcnRpY2FsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC55IC09IHg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQueCArPSB4ICogdGV4dEhTY2FsZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudHNwYW4uc2V0QXR0cmlidXRlTlMobnVsbCwgImZvbnQtZmFtaWx5IiwgY3VycmVudC5mb250RmFtaWx5KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudHNwYW4uc2V0QXR0cmlidXRlTlMobnVsbCwgImZvbnQtc2l6ZSIsIGAke3BmKGN1cnJlbnQuZm9udFNpemUpfXB4YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudC5mb250U3R5bGUgIT09IFNWR19ERUZBVUxUUy5mb250U3R5bGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnRzcGFuLnNldEF0dHJpYnV0ZU5TKG51bGwsICJmb250LXN0eWxlIiwgY3VycmVudC5mb250U3R5bGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnQuZm9udFdlaWdodCAhPT0gU1ZHX0RFRkFVTFRTLmZvbnRXZWlnaHQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnRzcGFuLnNldEF0dHJpYnV0ZU5TKG51bGwsICJmb250LXdlaWdodCIsIGN1cnJlbnQuZm9udFdlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWxsU3Ryb2tlTW9kZSA9IGN1cnJlbnQudGV4dFJlbmRlcmluZ01vZGUgJiBfdXRpbC5UZXh0UmVuZGVyaW5nTW9kZS5GSUxMX1NUUk9LRV9NQVNLOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZpbGxTdHJva2VNb2RlID09PSBfdXRpbC5UZXh0UmVuZGVyaW5nTW9kZS5GSUxMIHx8IGZpbGxTdHJva2VNb2RlID09PSBfdXRpbC5UZXh0UmVuZGVyaW5nTW9kZS5GSUxMX1NUUk9LRSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50LmZpbGxDb2xvciAhPT0gU1ZHX0RFRkFVTFRTLmZpbGxDb2xvcikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnRzcGFuLnNldEF0dHJpYnV0ZU5TKG51bGwsICJmaWxsIiwgY3VycmVudC5maWxsQ29sb3IpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudC5maWxsQWxwaGEgPCAxKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudHNwYW4uc2V0QXR0cmlidXRlTlMobnVsbCwgImZpbGwtb3BhY2l0eSIsIGN1cnJlbnQuZmlsbEFscGhhKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnQudGV4dFJlbmRlcmluZ01vZGUgPT09IF91dGlsLlRleHRSZW5kZXJpbmdNb2RlLkFERF9UT19QQVRIKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC50c3Bhbi5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZmlsbCIsICJ0cmFuc3BhcmVudCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnRzcGFuLnNldEF0dHJpYnV0ZU5TKG51bGwsICJmaWxsIiwgIm5vbmUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmaWxsU3Ryb2tlTW9kZSA9PT0gX3V0aWwuVGV4dFJlbmRlcmluZ01vZGUuU1RST0tFIHx8IGZpbGxTdHJva2VNb2RlID09PSBfdXRpbC5UZXh0UmVuZGVyaW5nTW9kZS5GSUxMX1NUUk9LRSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpbmVXaWR0aFNjYWxlID0gMSAvIChjdXJyZW50LnRleHRNYXRyaXhTY2FsZSB8fCAxKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRTdHJva2VBdHRyaWJ1dGVzKGN1cnJlbnQudHNwYW4sIGxpbmVXaWR0aFNjYWxlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCB0ZXh0TWF0cml4ID0gY3VycmVudC50ZXh0TWF0cml4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnQudGV4dFJpc2UgIT09IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0TWF0cml4ID0gdGV4dE1hdHJpeC5zbGljZSgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHRNYXRyaXhbNV0gKz0gY3VycmVudC50ZXh0UmlzZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudHh0RWxlbWVudC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAidHJhbnNmb3JtIiwgYCR7cG0odGV4dE1hdHJpeCl9IHNjYWxlKCR7cGYodGV4dEhTY2FsZSl9LCAtMSlgKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudHh0RWxlbWVudC5zZXRBdHRyaWJ1dGVOUyhYTUxfTlMsICJ4bWw6c3BhY2UiLCAicHJlc2VydmUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQudHh0RWxlbWVudC5hcHBlbmQoY3VycmVudC50c3Bhbik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnR4dGdycC5hcHBlbmQoY3VycmVudC50eHRFbGVtZW50KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Vuc3VyZVRyYW5zZm9ybUdyb3VwKCkuYXBwZW5kKGN1cnJlbnQudHh0RWxlbWVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc2V0TGVhZGluZ01vdmVUZXh0KHgsIHkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0TGVhZGluZygteSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1vdmVUZXh0KHgsIHkpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGFkZEZvbnRTdHlsZShmb250T2JqKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWZvbnRPYmouZGF0YSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiYWRkRm9udFN0eWxlOiBObyBmb250IGRhdGEgYXZhaWxhYmxlLCAiICsgJ2Vuc3VyZSB0aGF0IHRoZSAiZm9udEV4dHJhUHJvcGVydGllcyIgQVBJIHBhcmFtZXRlciBpcyBzZXQuJyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY3NzU3R5bGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNzc1N0eWxlID0gdGhpcy5zdmdGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoInN2ZzpzdHlsZSIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3NzU3R5bGUuc2V0QXR0cmlidXRlTlMobnVsbCwgInR5cGUiLCAidGV4dC9jc3MiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlZnMuYXBwZW5kKHRoaXMuY3NzU3R5bGUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdXJsID0gY3JlYXRlT2JqZWN0VVJMKGZvbnRPYmouZGF0YSwgZm9udE9iai5taW1ldHlwZSwgdGhpcy5mb3JjZURhdGFTY2hlbWEpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jc3NTdHlsZS50ZXh0Q29udGVudCArPSBgQGZvbnQtZmFjZSB7IGZvbnQtZmFtaWx5OiAiJHtmb250T2JqLmxvYWRlZE5hbWV9IjtgICsgYCBzcmM6IHVybCgke3VybH0pOyB9XG5gOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHNldEZvbnQoZGV0YWlscykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMuY3VycmVudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvbnRPYmogPSB0aGlzLmNvbW1vbk9ianMuZ2V0KGRldGFpbHNbMF0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHNpemUgPSBkZXRhaWxzWzFdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5mb250ID0gZm9udE9iajsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmVtYmVkRm9udHMgJiYgIWZvbnRPYmoubWlzc2luZ0ZpbGUgJiYgIXRoaXMuZW1iZWRkZWRGb250c1tmb250T2JqLmxvYWRlZE5hbWVdKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRGb250U3R5bGUoZm9udE9iaik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbWJlZGRlZEZvbnRzW2ZvbnRPYmoubG9hZGVkTmFtZV0gPSBmb250T2JqOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5mb250TWF0cml4ID0gZm9udE9iai5mb250TWF0cml4IHx8IF91dGlsLkZPTlRfSURFTlRJVFlfTUFUUklYOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGJvbGQgPSAibm9ybWFsIjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmb250T2JqLmJsYWNrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9sZCA9ICI5MDAiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChmb250T2JqLmJvbGQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib2xkID0gImJvbGQiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXRhbGljID0gZm9udE9iai5pdGFsaWMgPyAiaXRhbGljIiA6ICJub3JtYWwiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpemUgPCAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IC1zaXplOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQuZm9udERpcmVjdGlvbiA9IC0xOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LmZvbnREaXJlY3Rpb24gPSAxOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5mb250U2l6ZSA9IHNpemU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LmZvbnRGYW1pbHkgPSBmb250T2JqLmxvYWRlZE5hbWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LmZvbnRXZWlnaHQgPSBib2xkOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5mb250U3R5bGUgPSBpdGFsaWM7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LnRzcGFuID0gdGhpcy5zdmdGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoInN2Zzp0c3BhbiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC50c3Bhbi5zZXRBdHRyaWJ1dGVOUyhudWxsLCAieSIsIHBmKC1jdXJyZW50LnkpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQueGNvb3JkcyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC55Y29vcmRzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZW5kVGV4dCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfY3VycmVudCR0eHRFbGVtZW50OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMuY3VycmVudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50LnRleHRSZW5kZXJpbmdNb2RlICYgX3V0aWwuVGV4dFJlbmRlcmluZ01vZGUuQUREX1RPX1BBVEhfRkxBRyAmJiAoX2N1cnJlbnQkdHh0RWxlbWVudCA9IGN1cnJlbnQudHh0RWxlbWVudCkgIT09IG51bGwgJiYgX2N1cnJlbnQkdHh0RWxlbWVudCAhPT0gdm9pZCAwICYmIF9jdXJyZW50JHR4dEVsZW1lbnQuaGFzQ2hpbGROb2RlcygpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5lbGVtZW50ID0gY3VycmVudC50eHRFbGVtZW50OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xpcCgibm9uemVybyIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW5kUGF0aCgpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHNldExpbmVXaWR0aCh3aWR0aCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdpZHRoID4gMCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5saW5lV2lkdGggPSB3aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBzZXRMaW5lQ2FwKHN0eWxlKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQubGluZUNhcCA9IExJTkVfQ0FQX1NUWUxFU1tzdHlsZV07CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc2V0TGluZUpvaW4oc3R5bGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5saW5lSm9pbiA9IExJTkVfSk9JTl9TVFlMRVNbc3R5bGVdOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHNldE1pdGVyTGltaXQobGltaXQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5taXRlckxpbWl0ID0gbGltaXQ7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc2V0U3Ryb2tlQWxwaGEoc3Ryb2tlQWxwaGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5zdHJva2VBbHBoYSA9IHN0cm9rZUFscGhhOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHNldFN0cm9rZVJHQkNvbG9yKHIsIGcsIGIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5zdHJva2VDb2xvciA9IF91dGlsLlV0aWwubWFrZUhleENvbG9yKHIsIGcsIGIpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHNldEZpbGxBbHBoYShmaWxsQWxwaGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5maWxsQWxwaGEgPSBmaWxsQWxwaGE7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc2V0RmlsbFJHQkNvbG9yKHIsIGcsIGIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5maWxsQ29sb3IgPSBfdXRpbC5VdGlsLm1ha2VIZXhDb2xvcihyLCBnLCBiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC50c3BhbiA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGVFbGVtZW50KCJzdmc6dHNwYW4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC54Y29vcmRzID0gW107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQueWNvb3JkcyA9IFtdOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHNldFN0cm9rZUNvbG9yTihhcmdzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuc3Ryb2tlQ29sb3IgPSB0aGlzLl9tYWtlQ29sb3JOX1BhdHRlcm4oYXJncyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc2V0RmlsbENvbG9yTihhcmdzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuZmlsbENvbG9yID0gdGhpcy5fbWFrZUNvbG9yTl9QYXR0ZXJuKGFyZ3MpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHNoYWRpbmdGaWxsKGFyZ3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy52aWV3cG9ydC53aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMudmlld3BvcnQuaGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW52ID0gX3V0aWwuVXRpbC5pbnZlcnNlVHJhbnNmb3JtKHRoaXMudHJhbnNmb3JtTWF0cml4KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJsID0gX3V0aWwuVXRpbC5hcHBseVRyYW5zZm9ybShbMCwgMF0sIGludik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBiciA9IF91dGlsLlV0aWwuYXBwbHlUcmFuc2Zvcm0oWzAsIGhlaWdodF0sIGludik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bCA9IF91dGlsLlV0aWwuYXBwbHlUcmFuc2Zvcm0oW3dpZHRoLCAwXSwgaW52KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVyID0gX3V0aWwuVXRpbC5hcHBseVRyYW5zZm9ybShbd2lkdGgsIGhlaWdodF0sIGludik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB4MCA9IE1hdGgubWluKGJsWzBdLCBiclswXSwgdWxbMF0sIHVyWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHkwID0gTWF0aC5taW4oYmxbMV0sIGJyWzFdLCB1bFsxXSwgdXJbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeDEgPSBNYXRoLm1heChibFswXSwgYnJbMF0sIHVsWzBdLCB1clswXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB5MSA9IE1hdGgubWF4KGJsWzFdLCBiclsxXSwgdWxbMV0sIHVyWzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlY3QgPSB0aGlzLnN2Z0ZhY3RvcnkuY3JlYXRlRWxlbWVudCgic3ZnOnJlY3QiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgIngiLCB4MCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN0LnNldEF0dHJpYnV0ZU5TKG51bGwsICJ5IiwgeTApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAid2lkdGgiLCB4MSAtIHgwKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgImhlaWdodCIsIHkxIC0geTApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZmlsbCIsIHRoaXMuX21ha2VTaGFkaW5nUGF0dGVybihhcmdzKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5jdXJyZW50LmZpbGxBbHBoYSA8IDEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN0LnNldEF0dHJpYnV0ZU5TKG51bGwsICJmaWxsLW9wYWNpdHkiLCB0aGlzLmN1cnJlbnQuZmlsbEFscGhhKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2Vuc3VyZVRyYW5zZm9ybUdyb3VwKCkuYXBwZW5kKHJlY3QpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9tYWtlQ29sb3JOX1BhdHRlcm4oYXJncykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3NbMF0gPT09ICJUaWxpbmdQYXR0ZXJuIikgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9tYWtlVGlsaW5nUGF0dGVybihhcmdzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9tYWtlU2hhZGluZ1BhdHRlcm4oYXJncyk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgX21ha2VUaWxpbmdQYXR0ZXJuKGFyZ3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbG9yID0gYXJnc1sxXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9wZXJhdG9yTGlzdCA9IGFyZ3NbMl07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXRyaXggPSBhcmdzWzNdIHx8IF91dGlsLklERU5USVRZX01BVFJJWDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFt4MCwgeTAsIHgxLCB5MV0gPSBhcmdzWzRdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeHN0ZXAgPSBhcmdzWzVdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeXN0ZXAgPSBhcmdzWzZdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFpbnRUeXBlID0gYXJnc1s3XTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRpbGluZ0lkID0gYHNoYWRpbmcke3NoYWRpbmdDb3VudCsrfWA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbdHgwLCB0eTAsIHR4MSwgdHkxXSA9IF91dGlsLlV0aWwubm9ybWFsaXplUmVjdChbLi4uX3V0aWwuVXRpbC5hcHBseVRyYW5zZm9ybShbeDAsIHkwXSwgbWF0cml4KSwgLi4uX3V0aWwuVXRpbC5hcHBseVRyYW5zZm9ybShbeDEsIHkxXSwgbWF0cml4KV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW3hzY2FsZSwgeXNjYWxlXSA9IF91dGlsLlV0aWwuc2luZ3VsYXJWYWx1ZURlY29tcG9zZTJkU2NhbGUobWF0cml4KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHR4c3RlcCA9IHhzdGVwICogeHNjYWxlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdHlzdGVwID0geXN0ZXAgKiB5c2NhbGU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0aWxpbmcgPSB0aGlzLnN2Z0ZhY3RvcnkuY3JlYXRlRWxlbWVudCgic3ZnOnBhdHRlcm4iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbGluZy5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiaWQiLCB0aWxpbmdJZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWxpbmcuc2V0QXR0cmlidXRlTlMobnVsbCwgInBhdHRlcm5Vbml0cyIsICJ1c2VyU3BhY2VPblVzZSIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlsaW5nLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ3aWR0aCIsIHR4c3RlcCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWxpbmcuc2V0QXR0cmlidXRlTlMobnVsbCwgImhlaWdodCIsIHR5c3RlcCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWxpbmcuc2V0QXR0cmlidXRlTlMobnVsbCwgIngiLCBgJHt0eDB9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWxpbmcuc2V0QXR0cmlidXRlTlMobnVsbCwgInkiLCBgJHt0eTB9YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdmcgPSB0aGlzLnN2ZzsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybU1hdHJpeCA9IHRoaXMudHJhbnNmb3JtTWF0cml4OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlsbENvbG9yID0gdGhpcy5jdXJyZW50LmZpbGxDb2xvcjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cm9rZUNvbG9yID0gdGhpcy5jdXJyZW50LnN0cm9rZUNvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmJveCA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGUodHgxIC0gdHgwLCB0eTEgLSB0eTApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdmcgPSBiYm94OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc2Zvcm1NYXRyaXggPSBtYXRyaXg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFpbnRUeXBlID09PSAyKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3NzQ29sb3IgPSBfdXRpbC5VdGlsLm1ha2VIZXhDb2xvciguLi5jb2xvcik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmZpbGxDb2xvciA9IGNzc0NvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5zdHJva2VDb2xvciA9IGNzc0NvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5leGVjdXRlT3BUcmVlKHRoaXMuY29udmVydE9wTGlzdChvcGVyYXRvckxpc3QpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3ZnID0gc3ZnOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc2Zvcm1NYXRyaXggPSB0cmFuc2Zvcm1NYXRyaXg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnQuZmlsbENvbG9yID0gZmlsbENvbG9yOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnN0cm9rZUNvbG9yID0gc3Ryb2tlQ29sb3I7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWxpbmcuYXBwZW5kKGJib3guY2hpbGROb2Rlc1swXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlZnMuYXBwZW5kKHRpbGluZyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYHVybCgjJHt0aWxpbmdJZH0pYDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBfbWFrZVNoYWRpbmdQYXR0ZXJuKGFyZ3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYXJncyA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmdzID0gdGhpcy5vYmpzLmdldChhcmdzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoYXJnc1swXSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIlJhZGlhbEF4aWFsIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2hhZGluZ0lkID0gYHNoYWRpbmcke3NoYWRpbmdDb3VudCsrfWA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbG9yU3RvcHMgPSBhcmdzWzNdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZ3JhZGllbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoYXJnc1sxXSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiYXhpYWwiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvaW50MCA9IGFyZ3NbNF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9pbnQxID0gYXJnc1s1XTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmFkaWVudCA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGVFbGVtZW50KCJzdmc6bGluZWFyR3JhZGllbnQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmFkaWVudC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiaWQiLCBzaGFkaW5nSWQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyYWRpZW50LnNldEF0dHJpYnV0ZU5TKG51bGwsICJncmFkaWVudFVuaXRzIiwgInVzZXJTcGFjZU9uVXNlIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JhZGllbnQuc2V0QXR0cmlidXRlTlMobnVsbCwgIngxIiwgcG9pbnQwWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmFkaWVudC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAieTEiLCBwb2ludDBbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyYWRpZW50LnNldEF0dHJpYnV0ZU5TKG51bGwsICJ4MiIsIHBvaW50MVswXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JhZGllbnQuc2V0QXR0cmlidXRlTlMobnVsbCwgInkyIiwgcG9pbnQxWzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgInJhZGlhbCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZm9jYWxQb2ludCA9IGFyZ3NbNF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2lyY2xlUG9pbnQgPSBhcmdzWzVdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZvY2FsUmFkaXVzID0gYXJnc1s2XTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjaXJjbGVSYWRpdXMgPSBhcmdzWzddOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyYWRpZW50ID0gdGhpcy5zdmdGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoInN2ZzpyYWRpYWxHcmFkaWVudCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyYWRpZW50LnNldEF0dHJpYnV0ZU5TKG51bGwsICJpZCIsIHNoYWRpbmdJZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JhZGllbnQuc2V0QXR0cmlidXRlTlMobnVsbCwgImdyYWRpZW50VW5pdHMiLCAidXNlclNwYWNlT25Vc2UiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmFkaWVudC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiY3giLCBjaXJjbGVQb2ludFswXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JhZGllbnQuc2V0QXR0cmlidXRlTlMobnVsbCwgImN5IiwgY2lyY2xlUG9pbnRbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyYWRpZW50LnNldEF0dHJpYnV0ZU5TKG51bGwsICJyIiwgY2lyY2xlUmFkaXVzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmFkaWVudC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZngiLCBmb2NhbFBvaW50WzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmFkaWVudC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZnkiLCBmb2NhbFBvaW50WzFdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmFkaWVudC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZnIiLCBmb2NhbFJhZGl1cyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBSYWRpYWxBeGlhbCB0eXBlOiAke2FyZ3NbMV19YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBjb2xvclN0b3Agb2YgY29sb3JTdG9wcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RvcCA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGVFbGVtZW50KCJzdmc6c3RvcCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAib2Zmc2V0IiwgY29sb3JTdG9wWzBdKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3Auc2V0QXR0cmlidXRlTlMobnVsbCwgInN0b3AtY29sb3IiLCBjb2xvclN0b3BbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JhZGllbnQuYXBwZW5kKHN0b3ApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVmcy5hcHBlbmQoZ3JhZGllbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYHVybCgjJHtzaGFkaW5nSWR9KWA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiTWVzaCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiVW5pbXBsZW1lbnRlZCBwYXR0ZXJuIE1lc2giKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiRHVtbXkiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gImhvdHBpbmsiOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBJUiB0eXBlOiAke2FyZ3NbMF19YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc2V0RGFzaChkYXNoQXJyYXksIGRhc2hQaGFzZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmRhc2hBcnJheSA9IGRhc2hBcnJheTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5kYXNoUGhhc2UgPSBkYXNoUGhhc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RydWN0UGF0aChvcHMsIGFyZ3MpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmN1cnJlbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgeCA9IGN1cnJlbnQueCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gY3VycmVudC55OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGQgPSBbXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBqID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgb3Agb2Ygb3BzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChvcCB8IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMucmVjdGFuZ2xlOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IGFyZ3NbaisrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBhcmdzW2orK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3aWR0aCA9IGFyZ3NbaisrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGFyZ3NbaisrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHh3ID0geCArIHdpZHRoOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeWggPSB5ICsgaGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZC5wdXNoKCJNIiwgcGYoeCksIHBmKHkpLCAiTCIsIHBmKHh3KSwgcGYoeSksICJMIiwgcGYoeHcpLCBwZih5aCksICJMIiwgcGYoeCksIHBmKHloKSwgIloiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5tb3ZlVG86CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gYXJnc1tqKytdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGFyZ3NbaisrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGQucHVzaCgiTSIsIHBmKHgpLCBwZih5KSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBfdXRpbC5PUFMubGluZVRvOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IGFyZ3NbaisrXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBhcmdzW2orK107CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnB1c2goIkwiLCBwZih4KSwgcGYoeSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmN1cnZlVG86CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gYXJnc1tqICsgNF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gYXJnc1tqICsgNV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkLnB1c2goIkMiLCBwZihhcmdzW2pdKSwgcGYoYXJnc1tqICsgMV0pLCBwZihhcmdzW2ogKyAyXSksIHBmKGFyZ3NbaiArIDNdKSwgcGYoeCksIHBmKHkpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGogKz0gNjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIF91dGlsLk9QUy5jdXJ2ZVRvMjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGQucHVzaCgiQyIsIHBmKHgpLCBwZih5KSwgcGYoYXJnc1tqXSksIHBmKGFyZ3NbaiArIDFdKSwgcGYoYXJnc1tqICsgMl0pLCBwZihhcmdzW2ogKyAzXSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IGFyZ3NbaiArIDJdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGFyZ3NbaiArIDNdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaiArPSA0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmN1cnZlVG8zOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IGFyZ3NbaiArIDJdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IGFyZ3NbaiArIDNdOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZC5wdXNoKCJDIiwgcGYoYXJnc1tqXSksIHBmKGFyZ3NbaiArIDFdKSwgcGYoeCksIHBmKHkpLCBwZih4KSwgcGYoeSkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaiArPSA0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmNsb3NlUGF0aDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGQucHVzaCgiWiIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZCA9IGQuam9pbigiICIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnQucGF0aCAmJiBvcHMubGVuZ3RoID4gMCAmJiBvcHNbMF0gIT09IF91dGlsLk9QUy5yZWN0YW5nbGUgJiYgb3BzWzBdICE9PSBfdXRpbC5PUFMubW92ZVRvKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZCA9IGN1cnJlbnQucGF0aC5nZXRBdHRyaWJ1dGVOUyhudWxsLCAiZCIpICsgZDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5wYXRoID0gdGhpcy5zdmdGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoInN2ZzpwYXRoIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZW5zdXJlVHJhbnNmb3JtR3JvdXAoKS5hcHBlbmQoY3VycmVudC5wYXRoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQucGF0aC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZCIsIGQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5wYXRoLnNldEF0dHJpYnV0ZU5TKG51bGwsICJmaWxsIiwgIm5vbmUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQuZWxlbWVudCA9IGN1cnJlbnQucGF0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQuc2V0Q3VycmVudFBvaW50KHgsIHkpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGVuZFBhdGgoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5jdXJyZW50OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5wYXRoID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5wZW5kaW5nQ2xpcCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY3VycmVudC5lbGVtZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wZW5kaW5nQ2xpcCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2xpcElkID0gYGNsaXBwYXRoJHtjbGlwQ291bnQrK31gOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2xpcFBhdGggPSB0aGlzLnN2Z0ZhY3RvcnkuY3JlYXRlRWxlbWVudCgic3ZnOmNsaXBQYXRoIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGlwUGF0aC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiaWQiLCBjbGlwSWQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcFBhdGguc2V0QXR0cmlidXRlTlMobnVsbCwgInRyYW5zZm9ybSIsIHBtKHRoaXMudHJhbnNmb3JtTWF0cml4KSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjbGlwRWxlbWVudCA9IGN1cnJlbnQuZWxlbWVudC5jbG9uZU5vZGUodHJ1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5wZW5kaW5nQ2xpcCA9PT0gImV2ZW5vZGQiKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcEVsZW1lbnQuc2V0QXR0cmlidXRlTlMobnVsbCwgImNsaXAtcnVsZSIsICJldmVub2RkIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaXBFbGVtZW50LnNldEF0dHJpYnV0ZU5TKG51bGwsICJjbGlwLXJ1bGUiLCAibm9uemVybyIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wZW5kaW5nQ2xpcCA9IG51bGw7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGlwUGF0aC5hcHBlbmQoY2xpcEVsZW1lbnQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWZzLmFwcGVuZChjbGlwUGF0aCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudC5hY3RpdmVDbGlwVXJsKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5jbGlwR3JvdXAgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcHJldiBvZiB0aGlzLmV4dHJhU3RhY2spIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldi5jbGlwR3JvdXAgPSBudWxsOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGlwUGF0aC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiY2xpcC1wYXRoIiwgY3VycmVudC5hY3RpdmVDbGlwVXJsKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQuYWN0aXZlQ2xpcFVybCA9IGB1cmwoIyR7Y2xpcElkfSlgOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50Z3JwID0gbnVsbDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBjbGlwKHR5cGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGVuZGluZ0NsaXAgPSB0eXBlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlUGF0aCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmN1cnJlbnQ7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudC5wYXRoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZCA9IGAke2N1cnJlbnQucGF0aC5nZXRBdHRyaWJ1dGVOUyhudWxsLCAiZCIpfVpgOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnQucGF0aC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZCIsIGQpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHNldExlYWRpbmcobGVhZGluZykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmxlYWRpbmcgPSAtbGVhZGluZzsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBzZXRUZXh0UmlzZSh0ZXh0UmlzZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnRleHRSaXNlID0gdGV4dFJpc2U7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGV4dFJlbmRlcmluZ01vZGUodGV4dFJlbmRlcmluZ01vZGUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC50ZXh0UmVuZGVyaW5nTW9kZSA9IHRleHRSZW5kZXJpbmdNb2RlOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIHNldEhTY2FsZShzY2FsZSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LnRleHRIU2NhbGUgPSBzY2FsZSAvIDEwMDsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBzZXRSZW5kZXJpbmdJbnRlbnQoaW50ZW50KSB7fQogICAgICAgICAgICAgICAgICAgICAgICBzZXRGbGF0bmVzcyhmbGF0bmVzcykge30KICAgICAgICAgICAgICAgICAgICAgICAgc2V0R1N0YXRlKHN0YXRlcykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2Ygc3RhdGVzKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChrZXkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiTFciOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRMaW5lV2lkdGgodmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIkxDIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0TGluZUNhcCh2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiTEoiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRMaW5lSm9pbih2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiTUwiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRNaXRlckxpbWl0KHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJEIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0RGFzaCh2YWx1ZVswXSwgdmFsdWVbMV0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgIlJJIjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UmVuZGVyaW5nSW50ZW50KHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJGTCI6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEZsYXRuZXNzKHZhbHVlKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICJGb250IjoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0Rm9udCh2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiQ0EiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTdHJva2VBbHBoYSh2YWx1ZSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAiY2EiOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRGaWxsQWxwaGEodmFsdWUpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYFVuaW1wbGVtZW50ZWQgZ3JhcGhpYyBzdGF0ZSBvcGVyYXRvciAke2tleX1gKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBmaWxsKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMuY3VycmVudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50LmVsZW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50LmVsZW1lbnQuc2V0QXR0cmlidXRlTlMobnVsbCwgImZpbGwiLCBjdXJyZW50LmZpbGxDb2xvcik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5lbGVtZW50LnNldEF0dHJpYnV0ZU5TKG51bGwsICJmaWxsLW9wYWNpdHkiLCBjdXJyZW50LmZpbGxBbHBoYSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5lbmRQYXRoKCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMuY3VycmVudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50LmVsZW1lbnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRTdHJva2VBdHRyaWJ1dGVzKGN1cnJlbnQuZWxlbWVudCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudC5lbGVtZW50LnNldEF0dHJpYnV0ZU5TKG51bGwsICJmaWxsIiwgIm5vbmUiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVuZFBhdGgoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBfc2V0U3Ryb2tlQXR0cmlidXRlcyhlbGVtZW50KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgbGluZVdpZHRoU2NhbGUgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IDE7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5jdXJyZW50OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGRhc2hBcnJheSA9IGN1cnJlbnQuZGFzaEFycmF5OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxpbmVXaWR0aFNjYWxlICE9PSAxICYmIGRhc2hBcnJheS5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGFzaEFycmF5ID0gZGFzaEFycmF5Lm1hcChmdW5jdGlvbiAodmFsdWUpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxpbmVXaWR0aFNjYWxlICogdmFsdWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZU5TKG51bGwsICJzdHJva2UiLCBjdXJyZW50LnN0cm9rZUNvbG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlTlMobnVsbCwgInN0cm9rZS1vcGFjaXR5IiwgY3VycmVudC5zdHJva2VBbHBoYSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZU5TKG51bGwsICJzdHJva2UtbWl0ZXJsaW1pdCIsIHBmKGN1cnJlbnQubWl0ZXJMaW1pdCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAic3Ryb2tlLWxpbmVjYXAiLCBjdXJyZW50LmxpbmVDYXApOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAic3Ryb2tlLWxpbmVqb2luIiwgY3VycmVudC5saW5lSm9pbik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZU5TKG51bGwsICJzdHJva2Utd2lkdGgiLCBwZihsaW5lV2lkdGhTY2FsZSAqIGN1cnJlbnQubGluZVdpZHRoKSArICJweCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAic3Ryb2tlLWRhc2hhcnJheSIsIGRhc2hBcnJheS5tYXAocGYpLmpvaW4oIiAiKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZU5TKG51bGwsICJzdHJva2UtZGFzaG9mZnNldCIsIHBmKGxpbmVXaWR0aFNjYWxlICogY3VycmVudC5kYXNoUGhhc2UpICsgInB4Iik7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgZW9GaWxsKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90aGlzJGN1cnJlbnQkZWxlbWVudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIChfdGhpcyRjdXJyZW50JGVsZW1lbnQgPSB0aGlzLmN1cnJlbnQuZWxlbWVudCkgPT09IG51bGwgfHwgX3RoaXMkY3VycmVudCRlbGVtZW50ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfdGhpcyRjdXJyZW50JGVsZW1lbnQuc2V0QXR0cmlidXRlTlMobnVsbCwgImZpbGwtcnVsZSIsICJldmVub2RkIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZpbGwoKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBmaWxsU3Ryb2tlKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJva2UoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsbCgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGVvRmlsbFN0cm9rZSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfdGhpcyRjdXJyZW50JGVsZW1lbnQyOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgKF90aGlzJGN1cnJlbnQkZWxlbWVudDIgPSB0aGlzLmN1cnJlbnQuZWxlbWVudCkgPT09IG51bGwgfHwgX3RoaXMkY3VycmVudCRlbGVtZW50MiA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3RoaXMkY3VycmVudCRlbGVtZW50Mi5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZmlsbC1ydWxlIiwgImV2ZW5vZGQiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsbFN0cm9rZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlU3Ryb2tlKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbG9zZVBhdGgoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3Ryb2tlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2VGaWxsU3Ryb2tlKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbG9zZVBhdGgoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmlsbFN0cm9rZSgpOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlRU9GaWxsU3Ryb2tlKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jbG9zZVBhdGgoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZW9GaWxsU3Ryb2tlKCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcGFpbnRTb2xpZENvbG9ySW1hZ2VNYXNrKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVjdCA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGVFbGVtZW50KCJzdmc6cmVjdCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAieCIsICIwIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN0LnNldEF0dHJpYnV0ZU5TKG51bGwsICJ5IiwgIjAiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgIndpZHRoIiwgIjFweCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiaGVpZ2h0IiwgIjFweCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiZmlsbCIsIHRoaXMuY3VycmVudC5maWxsQ29sb3IpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZW5zdXJlVHJhbnNmb3JtR3JvdXAoKS5hcHBlbmQocmVjdCk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcGFpbnRJbWFnZVhPYmplY3Qob2JqSWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGltZ0RhdGEgPSB0aGlzLmdldE9iamVjdChvYmpJZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWltZ0RhdGEpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYERlcGVuZGVudCBpbWFnZSB3aXRoIG9iamVjdCBJRCAke29iaklkfSBpcyBub3QgcmVhZHkgeWV0YCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wYWludElubGluZUltYWdlWE9iamVjdChpbWdEYXRhKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBwYWludElubGluZUltYWdlWE9iamVjdChpbWdEYXRhLCBtYXNrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB3aWR0aCA9IGltZ0RhdGEud2lkdGg7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBpbWdEYXRhLmhlaWdodDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGltZ1NyYyA9IGNvbnZlcnRJbWdEYXRhVG9QbmcoaW1nRGF0YSwgdGhpcy5mb3JjZURhdGFTY2hlbWEsICEhbWFzayk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjbGlwcmVjdCA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGVFbGVtZW50KCJzdmc6cmVjdCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgIngiLCAiMCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgInkiLCAiMCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgIndpZHRoIiwgcGYod2lkdGgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaXByZWN0LnNldEF0dHJpYnV0ZU5TKG51bGwsICJoZWlnaHQiLCBwZihoZWlnaHQpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudC5lbGVtZW50ID0gY2xpcHJlY3Q7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsaXAoIm5vbnplcm8iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGltZ0VsID0gdGhpcy5zdmdGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoInN2ZzppbWFnZSIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nRWwuc2V0QXR0cmlidXRlTlMoWExJTktfTlMsICJ4bGluazpocmVmIiwgaW1nU3JjKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltZ0VsLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ4IiwgIjAiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltZ0VsLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ5IiwgcGYoLWhlaWdodCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nRWwuc2V0QXR0cmlidXRlTlMobnVsbCwgIndpZHRoIiwgcGYod2lkdGgpICsgInB4Iik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbWdFbC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiaGVpZ2h0IiwgcGYoaGVpZ2h0KSArICJweCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nRWwuc2V0QXR0cmlidXRlTlMobnVsbCwgInRyYW5zZm9ybSIsIGBzY2FsZSgke3BmKDEgLyB3aWR0aCl9ICR7cGYoLTEgLyBoZWlnaHQpfSlgKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXNrKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFzay5hcHBlbmQoaW1nRWwpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9lbnN1cmVUcmFuc2Zvcm1Hcm91cCgpLmFwcGVuZChpbWdFbCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcGFpbnRJbWFnZU1hc2tYT2JqZWN0KGltZykgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW1nRGF0YSA9IHRoaXMuZ2V0T2JqZWN0KGltZy5kYXRhLCBpbWcpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGltZ0RhdGEuYml0bWFwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJwYWludEltYWdlTWFza1hPYmplY3Q6IEltYWdlQml0bWFwIHN1cHBvcnQgaXMgbm90IGltcGxlbWVudGVkLCAiICsgImVuc3VyZSB0aGF0IHRoZSBgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWRgIEFQSSBwYXJhbWV0ZXIgaXMgZGlzYWJsZWQuIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudCA9IHRoaXMuY3VycmVudDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gaW1nRGF0YS53aWR0aDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGltZ0RhdGEuaGVpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmlsbENvbG9yID0gY3VycmVudC5maWxsQ29sb3I7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50Lm1hc2tJZCA9IGBtYXNrJHttYXNrQ291bnQrK31gOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWFzayA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGVFbGVtZW50KCJzdmc6bWFzayIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFzay5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiaWQiLCBjdXJyZW50Lm1hc2tJZCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0ID0gdGhpcy5zdmdGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoInN2ZzpyZWN0Iik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN0LnNldEF0dHJpYnV0ZU5TKG51bGwsICJ4IiwgIjAiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgInkiLCAiMCIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAid2lkdGgiLCBwZih3aWR0aCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiaGVpZ2h0IiwgcGYoaGVpZ2h0KSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN0LnNldEF0dHJpYnV0ZU5TKG51bGwsICJmaWxsIiwgZmlsbENvbG9yKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgIm1hc2siLCBgdXJsKCMke2N1cnJlbnQubWFza0lkfSlgKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVmcy5hcHBlbmQobWFzayk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9lbnN1cmVUcmFuc2Zvcm1Hcm91cCgpLmFwcGVuZChyZWN0KTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGFpbnRJbmxpbmVJbWFnZVhPYmplY3QoaW1nRGF0YSwgbWFzayk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgcGFpbnRGb3JtWE9iamVjdEJlZ2luKG1hdHJpeCwgYmJveCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkobWF0cml4KSAmJiBtYXRyaXgubGVuZ3RoID09PSA2KSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50cmFuc2Zvcm0obWF0cml4WzBdLCBtYXRyaXhbMV0sIG1hdHJpeFsyXSwgbWF0cml4WzNdLCBtYXRyaXhbNF0sIG1hdHJpeFs1XSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmJveCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHdpZHRoID0gYmJveFsyXSAtIGJib3hbMF07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaGVpZ2h0ID0gYmJveFszXSAtIGJib3hbMV07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2xpcHJlY3QgPSB0aGlzLnN2Z0ZhY3RvcnkuY3JlYXRlRWxlbWVudCgic3ZnOnJlY3QiKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGlwcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAieCIsIGJib3hbMF0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaXByZWN0LnNldEF0dHJpYnV0ZU5TKG51bGwsICJ5IiwgYmJveFsxXSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcHJlY3Quc2V0QXR0cmlidXRlTlMobnVsbCwgIndpZHRoIiwgcGYod2lkdGgpKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGlwcmVjdC5zZXRBdHRyaWJ1dGVOUyhudWxsLCAiaGVpZ2h0IiwgcGYoaGVpZ2h0KSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmVsZW1lbnQgPSBjbGlwcmVjdDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsaXAoIm5vbnplcm8iKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVuZFBhdGgoKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBwYWludEZvcm1YT2JqZWN0RW5kKCkge30KICAgICAgICAgICAgICAgICAgICAgICAgX2luaXRpYWxpemUodmlld3BvcnQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN2ZyA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGUodmlld3BvcnQud2lkdGgsIHZpZXdwb3J0LmhlaWdodCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkZWZpbml0aW9ucyA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGVFbGVtZW50KCJzdmc6ZGVmcyIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ZnLmFwcGVuZChkZWZpbml0aW9ucyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlZnMgPSBkZWZpbml0aW9uczsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJvb3RHcm91cCA9IHRoaXMuc3ZnRmFjdG9yeS5jcmVhdGVFbGVtZW50KCJzdmc6ZyIpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEdyb3VwLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ0cmFuc2Zvcm0iLCBwbSh2aWV3cG9ydC50cmFuc2Zvcm0pKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN2Zy5hcHBlbmQocm9vdEdyb3VwKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3ZnID0gcm9vdEdyb3VwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN2ZzsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICBfZW5zdXJlQ2xpcEdyb3VwKCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmN1cnJlbnQuY2xpcEdyb3VwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2xpcEdyb3VwID0gdGhpcy5zdmdGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoInN2ZzpnIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xpcEdyb3VwLnNldEF0dHJpYnV0ZU5TKG51bGwsICJjbGlwLXBhdGgiLCB0aGlzLmN1cnJlbnQuYWN0aXZlQ2xpcFVybCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdmcuYXBwZW5kKGNsaXBHcm91cCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50LmNsaXBHcm91cCA9IGNsaXBHcm91cDsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmN1cnJlbnQuY2xpcEdyb3VwOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIF9lbnN1cmVUcmFuc2Zvcm1Hcm91cCgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy50Z3JwKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50Z3JwID0gdGhpcy5zdmdGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoInN2ZzpnIik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy50Z3JwLnNldEF0dHJpYnV0ZU5TKG51bGwsICJ0cmFuc2Zvcm0iLCBwbSh0aGlzLnRyYW5zZm9ybU1hdHJpeCkpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmN1cnJlbnQuYWN0aXZlQ2xpcFVybCkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9lbnN1cmVDbGlwR3JvdXAoKS5hcHBlbmQodGhpcy50Z3JwKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN2Zy5hcHBlbmQodGhpcy50Z3JwKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy50Z3JwOwogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvKioqLyB9KQogICAgICAgICAgICAvKioqKioqLyAJXSk7CiAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KICAgICAgICAvKioqKioqLyAJLy8gVGhlIG1vZHVsZSBjYWNoZQogICAgICAgIC8qKioqKiovIAl2YXIgX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fID0ge307CiAgICAgICAgLyoqKioqKi8KICAgICAgICAvKioqKioqLyAJLy8gVGhlIHJlcXVpcmUgZnVuY3Rpb24KICAgICAgICAvKioqKioqLyAJZnVuY3Rpb24gX193X3BkZmpzX3JlcXVpcmVfXyhtb2R1bGVJZCkgewogICAgICAgICAgICAvKioqKioqLyAJCS8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZQogICAgICAgICAgICAvKioqKioqLyAJCXZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdOwogICAgICAgICAgICAvKioqKioqLyAJCWlmIChjYWNoZWRNb2R1bGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgICAgLyoqKioqKi8gCQkJcmV0dXJuIGNhY2hlZE1vZHVsZS5leHBvcnRzOwogICAgICAgICAgICAgICAgLyoqKioqKi8gCQl9CiAgICAgICAgICAgIC8qKioqKiovIAkJLy8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSkKICAgICAgICAgICAgLyoqKioqKi8gCQl2YXIgbW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXSA9IHsKICAgICAgICAgICAgICAgIC8qKioqKiovIAkJCS8vIG5vIG1vZHVsZS5pZCBuZWVkZWQKICAgICAgICAgICAgICAgIC8qKioqKiovIAkJCS8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkCiAgICAgICAgICAgICAgICAvKioqKioqLyAJCQlleHBvcnRzOiB7fQogICAgICAgICAgICAgICAgLyoqKioqKi8gCQl9OwogICAgICAgICAgICAvKioqKioqLwogICAgICAgICAgICAvKioqKioqLyAJCS8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvbgogICAgICAgICAgICAvKioqKioqLyAJCV9fd2VicGFja19tb2R1bGVzX19bbW9kdWxlSWRdKG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pOwogICAgICAgICAgICAvKioqKioqLwogICAgICAgICAgICAvKioqKioqLyAJCS8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlCiAgICAgICAgICAgIC8qKioqKiovIAkJcmV0dXJuIG1vZHVsZS5leHBvcnRzOwogICAgICAgICAgICAvKioqKioqLyAJfQogICAgICAgIC8qKioqKiovCiAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KICAgICAgICB2YXIgX193ZWJwYWNrX2V4cG9ydHNfXyA9IHt9OwovLyBUaGlzIGVudHJ5IG5lZWQgdG8gYmUgd3JhcHBlZCBpbiBhbiBJSUZFIGJlY2F1c2UgaXQgbmVlZCB0byBiZSBpbiBzdHJpY3QgbW9kZS4KICAgICAgICAoKCkgPT4gewogICAgICAgICAgICAidXNlIHN0cmljdCI7CiAgICAgICAgICAgIHZhciBleHBvcnRzID0gX193ZWJwYWNrX2V4cG9ydHNfXzsKCgogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogICAgICAgICAgICAgICAgdmFsdWU6IHRydWUKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIkFib3J0RXhjZXB0aW9uIiwgKHsKICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gX3V0aWwuQWJvcnRFeGNlcHRpb247CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJBbm5vdGF0aW9uRWRpdG9yTGF5ZXIiLCAoewogICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfYW5ub3RhdGlvbl9lZGl0b3JfbGF5ZXIuQW5ub3RhdGlvbkVkaXRvckxheWVyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiQW5ub3RhdGlvbkVkaXRvclBhcmFtc1R5cGUiLCAoewogICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSkpOwogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIkFubm90YXRpb25FZGl0b3JUeXBlIiwgKHsKICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gX3V0aWwuQW5ub3RhdGlvbkVkaXRvclR5cGU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJBbm5vdGF0aW9uRWRpdG9yVUlNYW5hZ2VyIiwgKHsKICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gX3Rvb2xzLkFubm90YXRpb25FZGl0b3JVSU1hbmFnZXI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJBbm5vdGF0aW9uTGF5ZXIiLCAoewogICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfYW5ub3RhdGlvbl9sYXllci5Bbm5vdGF0aW9uTGF5ZXI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJBbm5vdGF0aW9uTW9kZSIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF91dGlsLkFubm90YXRpb25Nb2RlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiQ01hcENvbXByZXNzaW9uVHlwZSIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF91dGlsLkNNYXBDb21wcmVzc2lvblR5cGU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJGZWF0dXJlVGVzdCIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF91dGlsLkZlYXR1cmVUZXN0OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiR2xvYmFsV29ya2VyT3B0aW9ucyIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF93b3JrZXJfb3B0aW9ucy5HbG9iYWxXb3JrZXJPcHRpb25zOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiSW52YWxpZFBERkV4Y2VwdGlvbiIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF91dGlsLkludmFsaWRQREZFeGNlcHRpb247CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJNaXNzaW5nUERGRXhjZXB0aW9uIiwgKHsKICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gX3V0aWwuTWlzc2luZ1BERkV4Y2VwdGlvbjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSkpOwogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIk9QUyIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF91dGlsLk9QUzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSkpOwogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIlBERkRhdGFSYW5nZVRyYW5zcG9ydCIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9hcGkuUERGRGF0YVJhbmdlVHJhbnNwb3J0OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiUERGRGF0ZVN0cmluZyIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9kaXNwbGF5X3V0aWxzLlBERkRhdGVTdHJpbmc7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJQREZXb3JrZXIiLCAoewogICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfYXBpLlBERldvcmtlcjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSkpOwogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIlBhc3N3b3JkUmVzcG9uc2VzIiwgKHsKICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gX3V0aWwuUGFzc3dvcmRSZXNwb25zZXM7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJQZXJtaXNzaW9uRmxhZyIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF91dGlsLlBlcm1pc3Npb25GbGFnOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiUGl4ZWxzUGVySW5jaCIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9kaXNwbGF5X3V0aWxzLlBpeGVsc1BlckluY2g7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJSZW5kZXJpbmdDYW5jZWxsZWRFeGNlcHRpb24iLCAoewogICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfZGlzcGxheV91dGlscy5SZW5kZXJpbmdDYW5jZWxsZWRFeGNlcHRpb247CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJTVkdHcmFwaGljcyIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9zdmcuU1ZHR3JhcGhpY3M7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJVbmV4cGVjdGVkUmVzcG9uc2VFeGNlcHRpb24iLCAoewogICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfdXRpbC5VbmV4cGVjdGVkUmVzcG9uc2VFeGNlcHRpb247CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJVdGlsIiwgKHsKICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gX3V0aWwuVXRpbDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSkpOwogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIlZlcmJvc2l0eUxldmVsIiwgKHsKICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gX3V0aWwuVmVyYm9zaXR5TGV2ZWw7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJYZmFMYXllciIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF94ZmFfbGF5ZXIuWGZhTGF5ZXI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJidWlsZCIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9hcGkuYnVpbGQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJjcmVhdGVQcm9taXNlQ2FwYWJpbGl0eSIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5OwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiY3JlYXRlVmFsaWRBYnNvbHV0ZVVybCIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF91dGlsLmNyZWF0ZVZhbGlkQWJzb2x1dGVVcmw7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJnZXREb2N1bWVudCIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9hcGkuZ2V0RG9jdW1lbnQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJnZXRGaWxlbmFtZUZyb21VcmwiLCAoewogICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfZGlzcGxheV91dGlscy5nZXRGaWxlbmFtZUZyb21Vcmw7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJnZXRQZGZGaWxlbmFtZUZyb21VcmwiLCAoewogICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfZGlzcGxheV91dGlscy5nZXRQZGZGaWxlbmFtZUZyb21Vcmw7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJnZXRYZmFQYWdlVmlld3BvcnQiLCAoewogICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfZGlzcGxheV91dGlscy5nZXRYZmFQYWdlVmlld3BvcnQ7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJpc0RhdGFTY2hlbWUiLCAoewogICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfZGlzcGxheV91dGlscy5pc0RhdGFTY2hlbWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJpc1BkZkZpbGUiLCAoewogICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfZGlzcGxheV91dGlscy5pc1BkZkZpbGU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJsb2FkU2NyaXB0IiwgKHsKICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsCiAgICAgICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2Rpc3BsYXlfdXRpbHMubG9hZFNjcmlwdDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSkpOwogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgInJlbmRlclRleHRMYXllciIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF90ZXh0X2xheWVyLnJlbmRlclRleHRMYXllcjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSkpOwogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgInNldExheWVyRGltZW5zaW9ucyIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF9kaXNwbGF5X3V0aWxzLnNldExheWVyRGltZW5zaW9uczsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSkpOwogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgInNoYWRvdyIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF91dGlsLnNoYWRvdzsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSkpOwogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgInVwZGF0ZVRleHRMYXllciIsICh7CiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLAogICAgICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF90ZXh0X2xheWVyLnVwZGF0ZVRleHRMYXllcjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSkpOwogICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgInZlcnNpb24iLCAoewogICAgICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBfYXBpLnZlcnNpb247CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygxKTsKICAgICAgICAgICAgdmFyIF9hcGkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzOCk7CiAgICAgICAgICAgIHZhciBfZGlzcGxheV91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQyKTsKICAgICAgICAgICAgdmFyIF90ZXh0X2xheWVyID0gX193X3BkZmpzX3JlcXVpcmVfXygxNjEpOwogICAgICAgICAgICB2YXIgX2Fubm90YXRpb25fZWRpdG9yX2xheWVyID0gX193X3BkZmpzX3JlcXVpcmVfXygxNjIpOwogICAgICAgICAgICB2YXIgX3Rvb2xzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDEpOwogICAgICAgICAgICB2YXIgX2Fubm90YXRpb25fbGF5ZXIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE2Nyk7CiAgICAgICAgICAgIHZhciBfd29ya2VyX29wdGlvbnMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0OSk7CiAgICAgICAgICAgIHZhciBfc3ZnID0gX193X3BkZmpzX3JlcXVpcmVfXygxNzApOwogICAgICAgICAgICB2YXIgX3hmYV9sYXllciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTY5KTsKICAgICAgICAgICAgY29uc3QgcGRmanNWZXJzaW9uID0gJzMuNS4xMjInOwogICAgICAgICAgICBjb25zdCBwZGZqc0J1aWxkID0gJzYyMjQ2NWRjMic7CiAgICAgICAgfSkoKTsKCiAgICAgICAgLyoqKioqKi8gCXJldHVybiBfX3dlYnBhY2tfZXhwb3J0c19fOwogICAgICAgIC8qKioqKiovIH0pKCkKICAgICAgICA7Cn0pOwovLyMgc291cmNlTWFwcGluZ1VSTD1wZGYuanMubWFw",h="LyoqCiAqIEBsaWNzdGFydCBUaGUgZm9sbG93aW5nIGlzIHRoZSBlbnRpcmUgbGljZW5zZSBub3RpY2UgZm9yIHRoZQogKiBKYXZhU2NyaXB0IGNvZGUgaW4gdGhpcyBwYWdlCiAqCiAqIENvcHlyaWdodCAyMDIzIE1vemlsbGEgRm91bmRhdGlvbgogKgogKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLgogKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKICoKICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKgogKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICJBUyBJUyIgQkFTSVMsCiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgogKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLgogKgogKiBAbGljZW5kIFRoZSBhYm92ZSBpcyB0aGUgZW50aXJlIGxpY2Vuc2Ugbm90aWNlIGZvciB0aGUKICogSmF2YVNjcmlwdCBjb2RlIGluIHRoaXMgcGFnZQogKi8KCihmdW5jdGlvbiB3ZWJwYWNrVW5pdmVyc2FsTW9kdWxlRGVmaW5pdGlvbihyb290LCBmYWN0b3J5KSB7CglpZih0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcpCgkJbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCk7CgllbHNlIGlmKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkKCQlkZWZpbmUoInBkZmpzLWRpc3QvYnVpbGQvcGRmLndvcmtlciIsIFtdLCBmYWN0b3J5KTsKCWVsc2UgaWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnKQoJCWV4cG9ydHNbInBkZmpzLWRpc3QvYnVpbGQvcGRmLndvcmtlciJdID0gZmFjdG9yeSgpOwoJZWxzZQoJCXJvb3RbInBkZmpzLWRpc3QvYnVpbGQvcGRmLndvcmtlciJdID0gcm9vdC5wZGZqc1dvcmtlciA9IGZhY3RvcnkoKTsKfSkoZ2xvYmFsVGhpcywgKCkgPT4gewpyZXR1cm4gLyoqKioqKi8gKCgpID0+IHsgLy8gd2VicGFja0Jvb3RzdHJhcAovKioqKioqLyAJdmFyIF9fd2VicGFja19tb2R1bGVzX18gPSAoWwovKiAwICovLAovKiAxICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5Xb3JrZXJUYXNrID0gZXhwb3J0cy5Xb3JrZXJNZXNzYWdlSGFuZGxlciA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX3ByaW1pdGl2ZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MCk7CnZhciBfcGRmX21hbmFnZXIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0Mik7CnZhciBfY2xlYW51cF9oZWxwZXIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIwNik7CnZhciBfd3JpdGVyID0gX193X3BkZmpzX3JlcXVpcmVfXygyMDApOwp2YXIgX2lzX25vZGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQpOwp2YXIgX21lc3NhZ2VfaGFuZGxlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMjM3KTsKdmFyIF93b3JrZXJfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygyMzgpOwpjbGFzcyBXb3JrZXJUYXNrIHsKICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICB0aGlzLm5hbWUgPSBuYW1lOwogICAgdGhpcy50ZXJtaW5hdGVkID0gZmFsc2U7CiAgICB0aGlzLl9jYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogIH0KICBnZXQgZmluaXNoZWQoKSB7CiAgICByZXR1cm4gdGhpcy5fY2FwYWJpbGl0eS5wcm9taXNlOwogIH0KICBmaW5pc2goKSB7CiAgICB0aGlzLl9jYXBhYmlsaXR5LnJlc29sdmUoKTsKICB9CiAgdGVybWluYXRlKCkgewogICAgdGhpcy50ZXJtaW5hdGVkID0gdHJ1ZTsKICB9CiAgZW5zdXJlTm90VGVybWluYXRlZCgpIHsKICAgIGlmICh0aGlzLnRlcm1pbmF0ZWQpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJXb3JrZXIgdGFzayB3YXMgdGVybWluYXRlZCIpOwogICAgfQogIH0KfQpleHBvcnRzLldvcmtlclRhc2sgPSBXb3JrZXJUYXNrOwpjbGFzcyBXb3JrZXJNZXNzYWdlSGFuZGxlciB7CiAgc3RhdGljIHNldHVwKGhhbmRsZXIsIHBvcnQpIHsKICAgIGxldCB0ZXN0TWVzc2FnZVByb2Nlc3NlZCA9IGZhbHNlOwogICAgaGFuZGxlci5vbigidGVzdCIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIGlmICh0ZXN0TWVzc2FnZVByb2Nlc3NlZCkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICB0ZXN0TWVzc2FnZVByb2Nlc3NlZCA9IHRydWU7CiAgICAgIGhhbmRsZXIuc2VuZCgidGVzdCIsIGRhdGEgaW5zdGFuY2VvZiBVaW50OEFycmF5KTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiY29uZmlndXJlIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgKDAsIF91dGlsLnNldFZlcmJvc2l0eUxldmVsKShkYXRhLnZlcmJvc2l0eSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldERvY1JlcXVlc3QiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gV29ya2VyTWVzc2FnZUhhbmRsZXIuY3JlYXRlRG9jdW1lbnRIYW5kbGVyKGRhdGEsIHBvcnQpOwogICAgfSk7CiAgfQogIHN0YXRpYyBjcmVhdGVEb2N1bWVudEhhbmRsZXIoZG9jUGFyYW1zLCBwb3J0KSB7CiAgICBsZXQgcGRmTWFuYWdlcjsKICAgIGxldCB0ZXJtaW5hdGVkID0gZmFsc2U7CiAgICBsZXQgY2FuY2VsWEhScyA9IG51bGw7CiAgICBjb25zdCBXb3JrZXJUYXNrcyA9IG5ldyBTZXQoKTsKICAgIGNvbnN0IHZlcmJvc2l0eSA9ICgwLCBfdXRpbC5nZXRWZXJib3NpdHlMZXZlbCkoKTsKICAgIGNvbnN0IHsKICAgICAgZG9jSWQsCiAgICAgIGFwaVZlcnNpb24KICAgIH0gPSBkb2NQYXJhbXM7CiAgICBjb25zdCB3b3JrZXJWZXJzaW9uID0gJzMuNS4xMjInOwogICAgaWYgKGFwaVZlcnNpb24gIT09IHdvcmtlclZlcnNpb24pIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgQVBJIHZlcnNpb24gIiR7YXBpVmVyc2lvbn0iIGRvZXMgbm90IG1hdGNoIGAgKyBgdGhlIFdvcmtlciB2ZXJzaW9uICIke3dvcmtlclZlcnNpb259Ii5gKTsKICAgIH0KICAgIGNvbnN0IGVudW1lcmFibGVQcm9wZXJ0aWVzID0gW107CiAgICBmb3IgKGNvbnN0IHByb3BlcnR5IGluIFtdKSB7CiAgICAgIGVudW1lcmFibGVQcm9wZXJ0aWVzLnB1c2gocHJvcGVydHkpOwogICAgfQogICAgaWYgKGVudW1lcmFibGVQcm9wZXJ0aWVzLmxlbmd0aCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIlRoZSBgQXJyYXkucHJvdG90eXBlYCBjb250YWlucyB1bmV4cGVjdGVkIGVudW1lcmFibGUgcHJvcGVydGllczogIiArIGVudW1lcmFibGVQcm9wZXJ0aWVzLmpvaW4oIiwgIikgKyAiOyB0aHVzIGJyZWFraW5nIGUuZy4gYGZvci4uLmluYCBpdGVyYXRpb24gb2YgYEFycmF5YHMuIik7CiAgICB9CiAgICBpZiAodHlwZW9mIFJlYWRhYmxlU3RyZWFtID09PSAidW5kZWZpbmVkIikgewogICAgICBjb25zdCBwYXJ0aWFsTXNnID0gIlRoZSBicm93c2VyL2Vudmlyb25tZW50IGxhY2tzIG5hdGl2ZSBzdXBwb3J0IGZvciBjcml0aWNhbCAiICsgImZ1bmN0aW9uYWxpdHkgdXNlZCBieSB0aGUgUERGLmpzIGxpYnJhcnkgKGUuZy4gYFJlYWRhYmxlU3RyZWFtYCk7ICI7CiAgICAgIGlmIChfaXNfbm9kZS5pc05vZGVKUykgewogICAgICAgIHRocm93IG5ldyBFcnJvcihwYXJ0aWFsTXNnICsgInBsZWFzZSB1c2UgYSBgbGVnYWN5YC1idWlsZCBpbnN0ZWFkLiIpOwogICAgICB9CiAgICAgIHRocm93IG5ldyBFcnJvcihwYXJ0aWFsTXNnICsgInBsZWFzZSB1cGRhdGUgdG8gYSBzdXBwb3J0ZWQgYnJvd3Nlci4iKTsKICAgIH0KICAgIGNvbnN0IHdvcmtlckhhbmRsZXJOYW1lID0gZG9jSWQgKyAiX3dvcmtlciI7CiAgICBsZXQgaGFuZGxlciA9IG5ldyBfbWVzc2FnZV9oYW5kbGVyLk1lc3NhZ2VIYW5kbGVyKHdvcmtlckhhbmRsZXJOYW1lLCBkb2NJZCwgcG9ydCk7CiAgICBmdW5jdGlvbiBlbnN1cmVOb3RUZXJtaW5hdGVkKCkgewogICAgICBpZiAodGVybWluYXRlZCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiV29ya2VyIHdhcyB0ZXJtaW5hdGVkIik7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIHN0YXJ0V29ya2VyVGFzayh0YXNrKSB7CiAgICAgIFdvcmtlclRhc2tzLmFkZCh0YXNrKTsKICAgIH0KICAgIGZ1bmN0aW9uIGZpbmlzaFdvcmtlclRhc2sodGFzaykgewogICAgICB0YXNrLmZpbmlzaCgpOwogICAgICBXb3JrZXJUYXNrcy5kZWxldGUodGFzayk7CiAgICB9CiAgICBhc3luYyBmdW5jdGlvbiBsb2FkRG9jdW1lbnQocmVjb3ZlcnlNb2RlKSB7CiAgICAgIGF3YWl0IHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJjaGVja0hlYWRlciIpOwogICAgICBhd2FpdCBwZGZNYW5hZ2VyLmVuc3VyZURvYygicGFyc2VTdGFydFhSZWYiKTsKICAgICAgYXdhaXQgcGRmTWFuYWdlci5lbnN1cmVEb2MoInBhcnNlIiwgW3JlY292ZXJ5TW9kZV0pOwogICAgICBhd2FpdCBwZGZNYW5hZ2VyLmVuc3VyZURvYygiY2hlY2tGaXJzdFBhZ2UiLCBbcmVjb3ZlcnlNb2RlXSk7CiAgICAgIGF3YWl0IHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJjaGVja0xhc3RQYWdlIiwgW3JlY292ZXJ5TW9kZV0pOwogICAgICBjb25zdCBpc1B1cmVYZmEgPSBhd2FpdCBwZGZNYW5hZ2VyLmVuc3VyZURvYygiaXNQdXJlWGZhIik7CiAgICAgIGlmIChpc1B1cmVYZmEpIHsKICAgICAgICBjb25zdCB0YXNrID0gbmV3IFdvcmtlclRhc2soImxvYWRYZmFGb250cyIpOwogICAgICAgIHN0YXJ0V29ya2VyVGFzayh0YXNrKTsKICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChbcGRmTWFuYWdlci5sb2FkWGZhRm9udHMoaGFuZGxlciwgdGFzaykuY2F0Y2gocmVhc29uID0+IHt9KS50aGVuKCgpID0+IGZpbmlzaFdvcmtlclRhc2sodGFzaykpLCBwZGZNYW5hZ2VyLmxvYWRYZmFJbWFnZXMoKV0pOwogICAgICB9CiAgICAgIGNvbnN0IFtudW1QYWdlcywgZmluZ2VycHJpbnRzXSA9IGF3YWl0IFByb21pc2UuYWxsKFtwZGZNYW5hZ2VyLmVuc3VyZURvYygibnVtUGFnZXMiKSwgcGRmTWFuYWdlci5lbnN1cmVEb2MoImZpbmdlcnByaW50cyIpXSk7CiAgICAgIGNvbnN0IGh0bWxGb3JYZmEgPSBpc1B1cmVYZmEgPyBhd2FpdCBwZGZNYW5hZ2VyLmVuc3VyZURvYygiaHRtbEZvclhmYSIpIDogbnVsbDsKICAgICAgcmV0dXJuIHsKICAgICAgICBudW1QYWdlcywKICAgICAgICBmaW5nZXJwcmludHMsCiAgICAgICAgaHRtbEZvclhmYQogICAgICB9OwogICAgfQogICAgZnVuY3Rpb24gZ2V0UGRmTWFuYWdlcihfcmVmKSB7CiAgICAgIGxldCB7CiAgICAgICAgZGF0YSwKICAgICAgICBwYXNzd29yZCwKICAgICAgICBkaXNhYmxlQXV0b0ZldGNoLAogICAgICAgIHJhbmdlQ2h1bmtTaXplLAogICAgICAgIGxlbmd0aCwKICAgICAgICBkb2NCYXNlVXJsLAogICAgICAgIGVuYWJsZVhmYSwKICAgICAgICBldmFsdWF0b3JPcHRpb25zCiAgICAgIH0gPSBfcmVmOwogICAgICBjb25zdCBwZGZNYW5hZ2VyQXJncyA9IHsKICAgICAgICBzb3VyY2U6IG51bGwsCiAgICAgICAgZGlzYWJsZUF1dG9GZXRjaCwKICAgICAgICBkb2NCYXNlVXJsLAogICAgICAgIGRvY0lkLAogICAgICAgIGVuYWJsZVhmYSwKICAgICAgICBldmFsdWF0b3JPcHRpb25zLAogICAgICAgIGhhbmRsZXIsCiAgICAgICAgbGVuZ3RoLAogICAgICAgIHBhc3N3b3JkLAogICAgICAgIHJhbmdlQ2h1bmtTaXplCiAgICAgIH07CiAgICAgIGNvbnN0IHBkZk1hbmFnZXJDYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogICAgICBsZXQgbmV3UGRmTWFuYWdlcjsKICAgICAgaWYgKGRhdGEpIHsKICAgICAgICB0cnkgewogICAgICAgICAgcGRmTWFuYWdlckFyZ3Muc291cmNlID0gZGF0YTsKICAgICAgICAgIG5ld1BkZk1hbmFnZXIgPSBuZXcgX3BkZl9tYW5hZ2VyLkxvY2FsUGRmTWFuYWdlcihwZGZNYW5hZ2VyQXJncyk7CiAgICAgICAgICBwZGZNYW5hZ2VyQ2FwYWJpbGl0eS5yZXNvbHZlKG5ld1BkZk1hbmFnZXIpOwogICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICBwZGZNYW5hZ2VyQ2FwYWJpbGl0eS5yZWplY3QoZXgpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gcGRmTWFuYWdlckNhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgfQogICAgICBsZXQgcGRmU3RyZWFtLAogICAgICAgIGNhY2hlZENodW5rcyA9IFtdOwogICAgICB0cnkgewogICAgICAgIHBkZlN0cmVhbSA9IG5ldyBfd29ya2VyX3N0cmVhbS5QREZXb3JrZXJTdHJlYW0oaGFuZGxlcik7CiAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgcGRmTWFuYWdlckNhcGFiaWxpdHkucmVqZWN0KGV4KTsKICAgICAgICByZXR1cm4gcGRmTWFuYWdlckNhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgfQogICAgICBjb25zdCBmdWxsUmVxdWVzdCA9IHBkZlN0cmVhbS5nZXRGdWxsUmVhZGVyKCk7CiAgICAgIGZ1bGxSZXF1ZXN0LmhlYWRlcnNSZWFkeS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICBpZiAoIWZ1bGxSZXF1ZXN0LmlzUmFuZ2VTdXBwb3J0ZWQpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgcGRmTWFuYWdlckFyZ3Muc291cmNlID0gcGRmU3RyZWFtOwogICAgICAgIHBkZk1hbmFnZXJBcmdzLmxlbmd0aCA9IGZ1bGxSZXF1ZXN0LmNvbnRlbnRMZW5ndGg7CiAgICAgICAgcGRmTWFuYWdlckFyZ3MuZGlzYWJsZUF1dG9GZXRjaCA9IHBkZk1hbmFnZXJBcmdzLmRpc2FibGVBdXRvRmV0Y2ggfHwgZnVsbFJlcXVlc3QuaXNTdHJlYW1pbmdTdXBwb3J0ZWQ7CiAgICAgICAgbmV3UGRmTWFuYWdlciA9IG5ldyBfcGRmX21hbmFnZXIuTmV0d29ya1BkZk1hbmFnZXIocGRmTWFuYWdlckFyZ3MpOwogICAgICAgIGZvciAoY29uc3QgY2h1bmsgb2YgY2FjaGVkQ2h1bmtzKSB7CiAgICAgICAgICBuZXdQZGZNYW5hZ2VyLnNlbmRQcm9ncmVzc2l2ZURhdGEoY2h1bmspOwogICAgICAgIH0KICAgICAgICBjYWNoZWRDaHVua3MgPSBbXTsKICAgICAgICBwZGZNYW5hZ2VyQ2FwYWJpbGl0eS5yZXNvbHZlKG5ld1BkZk1hbmFnZXIpOwogICAgICAgIGNhbmNlbFhIUnMgPSBudWxsOwogICAgICB9KS5jYXRjaChmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgcGRmTWFuYWdlckNhcGFiaWxpdHkucmVqZWN0KHJlYXNvbik7CiAgICAgICAgY2FuY2VsWEhScyA9IG51bGw7CiAgICAgIH0pOwogICAgICBsZXQgbG9hZGVkID0gMDsKICAgICAgY29uc3QgZmx1c2hDaHVua3MgPSBmdW5jdGlvbiAoKSB7CiAgICAgICAgY29uc3QgcGRmRmlsZSA9ICgwLCBfY29yZV91dGlscy5hcnJheUJ1ZmZlcnNUb0J5dGVzKShjYWNoZWRDaHVua3MpOwogICAgICAgIGlmIChsZW5ndGggJiYgcGRmRmlsZS5sZW5ndGggIT09IGxlbmd0aCkgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJyZXBvcnRlZCBIVFRQIGxlbmd0aCBpcyBkaWZmZXJlbnQgZnJvbSBhY3R1YWwiKTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHBkZk1hbmFnZXJBcmdzLnNvdXJjZSA9IHBkZkZpbGU7CiAgICAgICAgICBuZXdQZGZNYW5hZ2VyID0gbmV3IF9wZGZfbWFuYWdlci5Mb2NhbFBkZk1hbmFnZXIocGRmTWFuYWdlckFyZ3MpOwogICAgICAgICAgcGRmTWFuYWdlckNhcGFiaWxpdHkucmVzb2x2ZShuZXdQZGZNYW5hZ2VyKTsKICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgcGRmTWFuYWdlckNhcGFiaWxpdHkucmVqZWN0KGV4KTsKICAgICAgICB9CiAgICAgICAgY2FjaGVkQ2h1bmtzID0gW107CiAgICAgIH07CiAgICAgIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICBjb25zdCByZWFkQ2h1bmsgPSBmdW5jdGlvbiAoX3JlZjIpIHsKICAgICAgICAgIGxldCB7CiAgICAgICAgICAgIHZhbHVlLAogICAgICAgICAgICBkb25lCiAgICAgICAgICB9ID0gX3JlZjI7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBlbnN1cmVOb3RUZXJtaW5hdGVkKCk7CiAgICAgICAgICAgIGlmIChkb25lKSB7CiAgICAgICAgICAgICAgaWYgKCFuZXdQZGZNYW5hZ2VyKSB7CiAgICAgICAgICAgICAgICBmbHVzaENodW5rcygpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjYW5jZWxYSFJzID0gbnVsbDsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbG9hZGVkICs9IHZhbHVlLmJ5dGVMZW5ndGg7CiAgICAgICAgICAgIGlmICghZnVsbFJlcXVlc3QuaXNTdHJlYW1pbmdTdXBwb3J0ZWQpIHsKICAgICAgICAgICAgICBoYW5kbGVyLnNlbmQoIkRvY1Byb2dyZXNzIiwgewogICAgICAgICAgICAgICAgbG9hZGVkLAogICAgICAgICAgICAgICAgdG90YWw6IE1hdGgubWF4KGxvYWRlZCwgZnVsbFJlcXVlc3QuY29udGVudExlbmd0aCB8fCAwKQogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChuZXdQZGZNYW5hZ2VyKSB7CiAgICAgICAgICAgICAgbmV3UGRmTWFuYWdlci5zZW5kUHJvZ3Jlc3NpdmVEYXRhKHZhbHVlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBjYWNoZWRDaHVua3MucHVzaCh2YWx1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZnVsbFJlcXVlc3QucmVhZCgpLnRoZW4ocmVhZENodW5rLCByZWplY3QpOwogICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICByZWplY3QoZSk7CiAgICAgICAgICB9CiAgICAgICAgfTsKICAgICAgICBmdWxsUmVxdWVzdC5yZWFkKCkudGhlbihyZWFkQ2h1bmssIHJlamVjdCk7CiAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlKSB7CiAgICAgICAgcGRmTWFuYWdlckNhcGFiaWxpdHkucmVqZWN0KGUpOwogICAgICAgIGNhbmNlbFhIUnMgPSBudWxsOwogICAgICB9KTsKICAgICAgY2FuY2VsWEhScyA9IGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICBwZGZTdHJlYW0uY2FuY2VsQWxsUmVxdWVzdHMocmVhc29uKTsKICAgICAgfTsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXJDYXBhYmlsaXR5LnByb21pc2U7CiAgICB9CiAgICBmdW5jdGlvbiBzZXR1cERvYyhkYXRhKSB7CiAgICAgIGZ1bmN0aW9uIG9uU3VjY2Vzcyhkb2MpIHsKICAgICAgICBlbnN1cmVOb3RUZXJtaW5hdGVkKCk7CiAgICAgICAgaGFuZGxlci5zZW5kKCJHZXREb2MiLCB7CiAgICAgICAgICBwZGZJbmZvOiBkb2MKICAgICAgICB9KTsKICAgICAgfQogICAgICBmdW5jdGlvbiBvbkZhaWx1cmUoZXgpIHsKICAgICAgICBlbnN1cmVOb3RUZXJtaW5hdGVkKCk7CiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgX3V0aWwuUGFzc3dvcmRFeGNlcHRpb24pIHsKICAgICAgICAgIGNvbnN0IHRhc2sgPSBuZXcgV29ya2VyVGFzayhgUGFzc3dvcmRFeGNlcHRpb246IHJlc3BvbnNlICR7ZXguY29kZX1gKTsKICAgICAgICAgIHN0YXJ0V29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgIGhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJQYXNzd29yZFJlcXVlc3QiLCBleCkudGhlbihmdW5jdGlvbiAoX3JlZjMpIHsKICAgICAgICAgICAgbGV0IHsKICAgICAgICAgICAgICBwYXNzd29yZAogICAgICAgICAgICB9ID0gX3JlZjM7CiAgICAgICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICAgIHBkZk1hbmFnZXIudXBkYXRlUGFzc3dvcmQocGFzc3dvcmQpOwogICAgICAgICAgICBwZGZNYW5hZ2VyUmVhZHkoKTsKICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgZmluaXNoV29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgICAgaGFuZGxlci5zZW5kKCJEb2NFeGNlcHRpb24iLCBleCk7CiAgICAgICAgICB9KTsKICAgICAgICB9IGVsc2UgaWYgKGV4IGluc3RhbmNlb2YgX3V0aWwuSW52YWxpZFBERkV4Y2VwdGlvbiB8fCBleCBpbnN0YW5jZW9mIF91dGlsLk1pc3NpbmdQREZFeGNlcHRpb24gfHwgZXggaW5zdGFuY2VvZiBfdXRpbC5VbmV4cGVjdGVkUmVzcG9uc2VFeGNlcHRpb24gfHwgZXggaW5zdGFuY2VvZiBfdXRpbC5Vbmtub3duRXJyb3JFeGNlcHRpb24pIHsKICAgICAgICAgIGhhbmRsZXIuc2VuZCgiRG9jRXhjZXB0aW9uIiwgZXgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBoYW5kbGVyLnNlbmQoIkRvY0V4Y2VwdGlvbiIsIG5ldyBfdXRpbC5Vbmtub3duRXJyb3JFeGNlcHRpb24oZXgubWVzc2FnZSwgZXgudG9TdHJpbmcoKSkpOwogICAgICAgIH0KICAgICAgfQogICAgICBmdW5jdGlvbiBwZGZNYW5hZ2VyUmVhZHkoKSB7CiAgICAgICAgZW5zdXJlTm90VGVybWluYXRlZCgpOwogICAgICAgIGxvYWREb2N1bWVudChmYWxzZSkudGhlbihvblN1Y2Nlc3MsIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgIGVuc3VyZU5vdFRlcm1pbmF0ZWQoKTsKICAgICAgICAgIGlmICghKHJlYXNvbiBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLlhSZWZQYXJzZUV4Y2VwdGlvbikpIHsKICAgICAgICAgICAgb25GYWlsdXJlKHJlYXNvbik7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgIHBkZk1hbmFnZXIucmVxdWVzdExvYWRlZFN0cmVhbSgpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgICBlbnN1cmVOb3RUZXJtaW5hdGVkKCk7CiAgICAgICAgICAgIGxvYWREb2N1bWVudCh0cnVlKS50aGVuKG9uU3VjY2Vzcywgb25GYWlsdXJlKTsKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICB9CiAgICAgIGVuc3VyZU5vdFRlcm1pbmF0ZWQoKTsKICAgICAgZ2V0UGRmTWFuYWdlcihkYXRhKS50aGVuKGZ1bmN0aW9uIChuZXdQZGZNYW5hZ2VyKSB7CiAgICAgICAgaWYgKHRlcm1pbmF0ZWQpIHsKICAgICAgICAgIG5ld1BkZk1hbmFnZXIudGVybWluYXRlKG5ldyBfdXRpbC5BYm9ydEV4Y2VwdGlvbigiV29ya2VyIHdhcyB0ZXJtaW5hdGVkLiIpKTsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiV29ya2VyIHdhcyB0ZXJtaW5hdGVkIik7CiAgICAgICAgfQogICAgICAgIHBkZk1hbmFnZXIgPSBuZXdQZGZNYW5hZ2VyOwogICAgICAgIHBkZk1hbmFnZXIucmVxdWVzdExvYWRlZFN0cmVhbSh0cnVlKS50aGVuKHN0cmVhbSA9PiB7CiAgICAgICAgICBoYW5kbGVyLnNlbmQoIkRhdGFMb2FkZWQiLCB7CiAgICAgICAgICAgIGxlbmd0aDogc3RyZWFtLmJ5dGVzLmJ5dGVMZW5ndGgKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICB9KS50aGVuKHBkZk1hbmFnZXJSZWFkeSwgb25GYWlsdXJlKTsKICAgIH0KICAgIGhhbmRsZXIub24oIkdldFBhZ2UiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5nZXRQYWdlKGRhdGEucGFnZUluZGV4KS50aGVuKGZ1bmN0aW9uIChwYWdlKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtwZGZNYW5hZ2VyLmVuc3VyZShwYWdlLCAicm90YXRlIiksIHBkZk1hbmFnZXIuZW5zdXJlKHBhZ2UsICJyZWYiKSwgcGRmTWFuYWdlci5lbnN1cmUocGFnZSwgInVzZXJVbml0IiksIHBkZk1hbmFnZXIuZW5zdXJlKHBhZ2UsICJ2aWV3IildKS50aGVuKGZ1bmN0aW9uIChfcmVmNCkgewogICAgICAgICAgbGV0IFtyb3RhdGUsIHJlZiwgdXNlclVuaXQsIHZpZXddID0gX3JlZjQ7CiAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICByb3RhdGUsCiAgICAgICAgICAgIHJlZiwKICAgICAgICAgICAgdXNlclVuaXQsCiAgICAgICAgICAgIHZpZXcKICAgICAgICAgIH07CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRQYWdlSW5kZXgiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICBjb25zdCBwYWdlUmVmID0gX3ByaW1pdGl2ZXMuUmVmLmdldChkYXRhLm51bSwgZGF0YS5nZW4pOwogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJnZXRQYWdlSW5kZXgiLCBbcGFnZVJlZl0pOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXREZXN0aW5hdGlvbnMiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJkZXN0aW5hdGlvbnMiKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0RGVzdGluYXRpb24iLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJnZXREZXN0aW5hdGlvbiIsIFtkYXRhLmlkXSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldFBhZ2VMYWJlbHMiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJwYWdlTGFiZWxzIik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldFBhZ2VMYXlvdXQiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJwYWdlTGF5b3V0Iik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldFBhZ2VNb2RlIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygicGFnZU1vZGUiKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0Vmlld2VyUHJlZmVyZW5jZXMiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJ2aWV3ZXJQcmVmZXJlbmNlcyIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRPcGVuQWN0aW9uIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygib3BlbkFjdGlvbiIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRBdHRhY2htZW50cyIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImF0dGFjaG1lbnRzIik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldEphdmFTY3JpcHQiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJqYXZhU2NyaXB0Iik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldERvY0pTQWN0aW9ucyIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImpzQWN0aW9ucyIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRQYWdlSlNBY3Rpb25zIiwgZnVuY3Rpb24gKF9yZWY1KSB7CiAgICAgIGxldCB7CiAgICAgICAgcGFnZUluZGV4CiAgICAgIH0gPSBfcmVmNTsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZ2V0UGFnZShwYWdlSW5kZXgpLnRoZW4oZnVuY3Rpb24gKHBhZ2UpIHsKICAgICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmUocGFnZSwgImpzQWN0aW9ucyIpOwogICAgICB9KTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0T3V0bGluZSIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImRvY3VtZW50T3V0bGluZSIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRPcHRpb25hbENvbnRlbnRDb25maWciLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJvcHRpb25hbENvbnRlbnRDb25maWciKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0UGVybWlzc2lvbnMiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJwZXJtaXNzaW9ucyIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRNZXRhZGF0YSIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBQcm9taXNlLmFsbChbcGRmTWFuYWdlci5lbnN1cmVEb2MoImRvY3VtZW50SW5mbyIpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coIm1ldGFkYXRhIildKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0TWFya0luZm8iLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJtYXJrSW5mbyIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXREYXRhIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIucmVxdWVzdExvYWRlZFN0cmVhbSgpLnRoZW4oZnVuY3Rpb24gKHN0cmVhbSkgewogICAgICAgIHJldHVybiBzdHJlYW0uYnl0ZXM7CiAgICAgIH0pOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRBbm5vdGF0aW9ucyIsIGZ1bmN0aW9uIChfcmVmNikgewogICAgICBsZXQgewogICAgICAgIHBhZ2VJbmRleCwKICAgICAgICBpbnRlbnQKICAgICAgfSA9IF9yZWY2OwogICAgICByZXR1cm4gcGRmTWFuYWdlci5nZXRQYWdlKHBhZ2VJbmRleCkudGhlbihmdW5jdGlvbiAocGFnZSkgewogICAgICAgIGNvbnN0IHRhc2sgPSBuZXcgV29ya2VyVGFzayhgR2V0QW5ub3RhdGlvbnM6IHBhZ2UgJHtwYWdlSW5kZXh9YCk7CiAgICAgICAgc3RhcnRXb3JrZXJUYXNrKHRhc2spOwogICAgICAgIHJldHVybiBwYWdlLmdldEFubm90YXRpb25zRGF0YShoYW5kbGVyLCB0YXNrLCBpbnRlbnQpLnRoZW4oZGF0YSA9PiB7CiAgICAgICAgICBmaW5pc2hXb3JrZXJUYXNrKHRhc2spOwogICAgICAgICAgcmV0dXJuIGRhdGE7CiAgICAgICAgfSwgcmVhc29uID0+IHsKICAgICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICB0aHJvdyByZWFzb247CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRGaWVsZE9iamVjdHMiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVEb2MoImZpZWxkT2JqZWN0cyIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJIYXNKU0FjdGlvbnMiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVEb2MoImhhc0pTQWN0aW9ucyIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRDYWxjdWxhdGlvbk9yZGVySWRzIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJjYWxjdWxhdGlvbk9yZGVySWRzIik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIlNhdmVEb2N1bWVudCIsIGZ1bmN0aW9uIChfcmVmNykgewogICAgICBsZXQgewogICAgICAgIGlzUHVyZVhmYSwKICAgICAgICBudW1QYWdlcywKICAgICAgICBhbm5vdGF0aW9uU3RvcmFnZSwKICAgICAgICBmaWxlbmFtZQogICAgICB9ID0gX3JlZjc7CiAgICAgIGNvbnN0IHByb21pc2VzID0gW3BkZk1hbmFnZXIucmVxdWVzdExvYWRlZFN0cmVhbSgpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImFjcm9Gb3JtIiksIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiYWNyb0Zvcm1SZWYiKSwgcGRmTWFuYWdlci5lbnN1cmVEb2MoInhyZWYiKSwgcGRmTWFuYWdlci5lbnN1cmVEb2MoInN0YXJ0WFJlZiIpXTsKICAgICAgY29uc3QgbmV3QW5ub3RhdGlvbnNCeVBhZ2UgPSAhaXNQdXJlWGZhID8gKDAsIF9jb3JlX3V0aWxzLmdldE5ld0Fubm90YXRpb25zTWFwKShhbm5vdGF0aW9uU3RvcmFnZSkgOiBudWxsOwogICAgICBpZiAobmV3QW5ub3RhdGlvbnNCeVBhZ2UpIHsKICAgICAgICBmb3IgKGNvbnN0IFtwYWdlSW5kZXgsIGFubm90YXRpb25zXSBvZiBuZXdBbm5vdGF0aW9uc0J5UGFnZSkgewogICAgICAgICAgcHJvbWlzZXMucHVzaChwZGZNYW5hZ2VyLmdldFBhZ2UocGFnZUluZGV4KS50aGVuKHBhZ2UgPT4gewogICAgICAgICAgICBjb25zdCB0YXNrID0gbmV3IFdvcmtlclRhc2soYFNhdmUgKGVkaXRvcik6IHBhZ2UgJHtwYWdlSW5kZXh9YCk7CiAgICAgICAgICAgIHJldHVybiBwYWdlLnNhdmVOZXdBbm5vdGF0aW9ucyhoYW5kbGVyLCB0YXNrLCBhbm5vdGF0aW9ucykuZmluYWxseShmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgZmluaXNoV29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChpc1B1cmVYZmEpIHsKICAgICAgICBwcm9taXNlcy5wdXNoKHBkZk1hbmFnZXIuc2VyaWFsaXplWGZhRGF0YShhbm5vdGF0aW9uU3RvcmFnZSkpOwogICAgICB9IGVsc2UgewogICAgICAgIGZvciAobGV0IHBhZ2VJbmRleCA9IDA7IHBhZ2VJbmRleCA8IG51bVBhZ2VzOyBwYWdlSW5kZXgrKykgewogICAgICAgICAgcHJvbWlzZXMucHVzaChwZGZNYW5hZ2VyLmdldFBhZ2UocGFnZUluZGV4KS50aGVuKGZ1bmN0aW9uIChwYWdlKSB7CiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBuZXcgV29ya2VyVGFzayhgU2F2ZTogcGFnZSAke3BhZ2VJbmRleH1gKTsKICAgICAgICAgICAgcmV0dXJuIHBhZ2Uuc2F2ZShoYW5kbGVyLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSkuZmluYWxseShmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgZmluaXNoV29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbihmdW5jdGlvbiAoX3JlZjgpIHsKICAgICAgICBsZXQgW3N0cmVhbSwgYWNyb0Zvcm0sIGFjcm9Gb3JtUmVmLCB4cmVmLCBzdGFydFhSZWYsIC4uLnJlZnNdID0gX3JlZjg7CiAgICAgICAgbGV0IG5ld1JlZnMgPSBbXTsKICAgICAgICBsZXQgeGZhRGF0YSA9IG51bGw7CiAgICAgICAgaWYgKGlzUHVyZVhmYSkgewogICAgICAgICAgeGZhRGF0YSA9IHJlZnNbMF07CiAgICAgICAgICBpZiAoIXhmYURhdGEpIHsKICAgICAgICAgICAgcmV0dXJuIHN0cmVhbS5ieXRlczsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgbmV3UmVmcyA9IHJlZnMuZmxhdCgyKTsKICAgICAgICAgIGlmIChuZXdSZWZzLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgICByZXR1cm4gc3RyZWFtLmJ5dGVzOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb25zdCBuZWVkQXBwZWFyYW5jZXMgPSBhY3JvRm9ybVJlZiAmJiBhY3JvRm9ybSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QgJiYgbmV3UmVmcy5zb21lKHJlZiA9PiByZWYubmVlZEFwcGVhcmFuY2VzKTsKICAgICAgICBjb25zdCB4ZmEgPSBhY3JvRm9ybSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QgJiYgYWNyb0Zvcm0uZ2V0KCJYRkEiKSB8fCBudWxsOwogICAgICAgIGxldCB4ZmFEYXRhc2V0c1JlZiA9IG51bGw7CiAgICAgICAgbGV0IGhhc1hmYURhdGFzZXRzRW50cnkgPSBmYWxzZTsKICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh4ZmEpKSB7CiAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB4ZmEubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICAgICAgICBpZiAoeGZhW2ldID09PSAiZGF0YXNldHMiKSB7CiAgICAgICAgICAgICAgeGZhRGF0YXNldHNSZWYgPSB4ZmFbaSArIDFdOwogICAgICAgICAgICAgIGhhc1hmYURhdGFzZXRzRW50cnkgPSB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoeGZhRGF0YXNldHNSZWYgPT09IG51bGwpIHsKICAgICAgICAgICAgeGZhRGF0YXNldHNSZWYgPSB4cmVmLmdldE5ld1RlbXBvcmFyeVJlZigpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoeGZhKSB7CiAgICAgICAgICAoMCwgX3V0aWwud2FybikoIlVuc3VwcG9ydGVkIFhGQSB0eXBlLiIpOwogICAgICAgIH0KICAgICAgICBsZXQgbmV3WHJlZkluZm8gPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgIGlmICh4cmVmLnRyYWlsZXIpIHsKICAgICAgICAgIGNvbnN0IGluZm9PYmogPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgICAgY29uc3QgeHJlZkluZm8gPSB4cmVmLnRyYWlsZXIuZ2V0KCJJbmZvIikgfHwgbnVsbDsKICAgICAgICAgIGlmICh4cmVmSW5mbyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpIHsKICAgICAgICAgICAgeHJlZkluZm8uZm9yRWFjaCgoa2V5LCB2YWx1ZSkgPT4gewogICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgICAgICBpbmZvT2JqW2tleV0gPSAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKHZhbHVlKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgbGFzdFhSZWZTdHJlYW1Qb3MgPSB4cmVmLmxhc3RYUmVmU3RyZWFtUG9zOwogICAgICAgICAgbmV3WHJlZkluZm8gPSB7CiAgICAgICAgICAgIHJvb3RSZWY6IHhyZWYudHJhaWxlci5nZXRSYXcoIlJvb3QiKSB8fCBudWxsLAogICAgICAgICAgICBlbmNyeXB0UmVmOiB4cmVmLnRyYWlsZXIuZ2V0UmF3KCJFbmNyeXB0IikgfHwgbnVsbCwKICAgICAgICAgICAgbmV3UmVmOiB4cmVmLmdldE5ld1RlbXBvcmFyeVJlZigpLAogICAgICAgICAgICBpbmZvUmVmOiB4cmVmLnRyYWlsZXIuZ2V0UmF3KCJJbmZvIikgfHwgbnVsbCwKICAgICAgICAgICAgaW5mbzogaW5mb09iaiwKICAgICAgICAgICAgZmlsZUlkczogeHJlZi50cmFpbGVyLmdldCgiSUQiKSB8fCBudWxsLAogICAgICAgICAgICBzdGFydFhSZWY6IGxhc3RYUmVmU3RyZWFtUG9zID09PSBudWxsID8gc3RhcnRYUmVmIDogbGFzdFhSZWZTdHJlYW1Qb3MsCiAgICAgICAgICAgIGZpbGVuYW1lCiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICB0cnkgewogICAgICAgICAgcmV0dXJuICgwLCBfd3JpdGVyLmluY3JlbWVudGFsVXBkYXRlKSh7CiAgICAgICAgICAgIG9yaWdpbmFsRGF0YTogc3RyZWFtLmJ5dGVzLAogICAgICAgICAgICB4cmVmSW5mbzogbmV3WHJlZkluZm8sCiAgICAgICAgICAgIG5ld1JlZnMsCiAgICAgICAgICAgIHhyZWYsCiAgICAgICAgICAgIGhhc1hmYTogISF4ZmEsCiAgICAgICAgICAgIHhmYURhdGFzZXRzUmVmLAogICAgICAgICAgICBoYXNYZmFEYXRhc2V0c0VudHJ5LAogICAgICAgICAgICBuZWVkQXBwZWFyYW5jZXMsCiAgICAgICAgICAgIGFjcm9Gb3JtUmVmLAogICAgICAgICAgICBhY3JvRm9ybSwKICAgICAgICAgICAgeGZhRGF0YQogICAgICAgICAgfSk7CiAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgIHhyZWYucmVzZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRPcGVyYXRvckxpc3QiLCBmdW5jdGlvbiAoZGF0YSwgc2luaykgewogICAgICBjb25zdCBwYWdlSW5kZXggPSBkYXRhLnBhZ2VJbmRleDsKICAgICAgcGRmTWFuYWdlci5nZXRQYWdlKHBhZ2VJbmRleCkudGhlbihmdW5jdGlvbiAocGFnZSkgewogICAgICAgIGNvbnN0IHRhc2sgPSBuZXcgV29ya2VyVGFzayhgR2V0T3BlcmF0b3JMaXN0OiBwYWdlICR7cGFnZUluZGV4fWApOwogICAgICAgIHN0YXJ0V29ya2VyVGFzayh0YXNrKTsKICAgICAgICBjb25zdCBzdGFydCA9IHZlcmJvc2l0eSA+PSBfdXRpbC5WZXJib3NpdHlMZXZlbC5JTkZPUyA/IERhdGUubm93KCkgOiAwOwogICAgICAgIHBhZ2UuZ2V0T3BlcmF0b3JMaXN0KHsKICAgICAgICAgIGhhbmRsZXIsCiAgICAgICAgICBzaW5rLAogICAgICAgICAgdGFzaywKICAgICAgICAgIGludGVudDogZGF0YS5pbnRlbnQsCiAgICAgICAgICBjYWNoZUtleTogZGF0YS5jYWNoZUtleSwKICAgICAgICAgIGFubm90YXRpb25TdG9yYWdlOiBkYXRhLmFubm90YXRpb25TdG9yYWdlCiAgICAgICAgfSkudGhlbihmdW5jdGlvbiAob3BlcmF0b3JMaXN0SW5mbykgewogICAgICAgICAgZmluaXNoV29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgIGlmIChzdGFydCkgewogICAgICAgICAgICAoMCwgX3V0aWwuaW5mbykoYHBhZ2U9JHtwYWdlSW5kZXggKyAxfSAtIGdldE9wZXJhdG9yTGlzdDogdGltZT1gICsgYCR7RGF0ZS5ub3coKSAtIHN0YXJ0fW1zLCBsZW49JHtvcGVyYXRvckxpc3RJbmZvLmxlbmd0aH1gKTsKICAgICAgICAgIH0KICAgICAgICAgIHNpbmsuY2xvc2UoKTsKICAgICAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICBmaW5pc2hXb3JrZXJUYXNrKHRhc2spOwogICAgICAgICAgaWYgKHRhc2sudGVybWluYXRlZCkgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CiAgICAgICAgICBzaW5rLmVycm9yKHJlYXNvbik7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRUZXh0Q29udGVudCIsIGZ1bmN0aW9uIChkYXRhLCBzaW5rKSB7CiAgICAgIGNvbnN0IHBhZ2VJbmRleCA9IGRhdGEucGFnZUluZGV4OwogICAgICBwZGZNYW5hZ2VyLmdldFBhZ2UocGFnZUluZGV4KS50aGVuKGZ1bmN0aW9uIChwYWdlKSB7CiAgICAgICAgY29uc3QgdGFzayA9IG5ldyBXb3JrZXJUYXNrKCJHZXRUZXh0Q29udGVudDogcGFnZSAiICsgcGFnZUluZGV4KTsKICAgICAgICBzdGFydFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgY29uc3Qgc3RhcnQgPSB2ZXJib3NpdHkgPj0gX3V0aWwuVmVyYm9zaXR5TGV2ZWwuSU5GT1MgPyBEYXRlLm5vdygpIDogMDsKICAgICAgICBwYWdlLmV4dHJhY3RUZXh0Q29udGVudCh7CiAgICAgICAgICBoYW5kbGVyLAogICAgICAgICAgdGFzaywKICAgICAgICAgIHNpbmssCiAgICAgICAgICBpbmNsdWRlTWFya2VkQ29udGVudDogZGF0YS5pbmNsdWRlTWFya2VkQ29udGVudCwKICAgICAgICAgIGNvbWJpbmVUZXh0SXRlbXM6IGRhdGEuY29tYmluZVRleHRJdGVtcwogICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgZmluaXNoV29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgIGlmIChzdGFydCkgewogICAgICAgICAgICAoMCwgX3V0aWwuaW5mbykoYHBhZ2U9JHtwYWdlSW5kZXggKyAxfSAtIGdldFRleHRDb250ZW50OiB0aW1lPWAgKyBgJHtEYXRlLm5vdygpIC0gc3RhcnR9bXNgKTsKICAgICAgICAgIH0KICAgICAgICAgIHNpbmsuY2xvc2UoKTsKICAgICAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICBmaW5pc2hXb3JrZXJUYXNrKHRhc2spOwogICAgICAgICAgaWYgKHRhc2sudGVybWluYXRlZCkgewogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CiAgICAgICAgICBzaW5rLmVycm9yKHJlYXNvbik7CiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRTdHJ1Y3RUcmVlIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZ2V0UGFnZShkYXRhLnBhZ2VJbmRleCkudGhlbihmdW5jdGlvbiAocGFnZSkgewogICAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZShwYWdlLCAiZ2V0U3RydWN0VHJlZSIpOwogICAgICB9KTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiRm9udEZhbGxiYWNrIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZm9udEZhbGxiYWNrKGRhdGEuaWQsIGhhbmRsZXIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJDbGVhbnVwIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuY2xlYW51cCh0cnVlKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiVGVybWluYXRlIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgdGVybWluYXRlZCA9IHRydWU7CiAgICAgIGNvbnN0IHdhaXRPbiA9IFtdOwogICAgICBpZiAocGRmTWFuYWdlcikgewogICAgICAgIHBkZk1hbmFnZXIudGVybWluYXRlKG5ldyBfdXRpbC5BYm9ydEV4Y2VwdGlvbigiV29ya2VyIHdhcyB0ZXJtaW5hdGVkLiIpKTsKICAgICAgICBjb25zdCBjbGVhbnVwUHJvbWlzZSA9IHBkZk1hbmFnZXIuY2xlYW51cCgpOwogICAgICAgIHdhaXRPbi5wdXNoKGNsZWFudXBQcm9taXNlKTsKICAgICAgICBwZGZNYW5hZ2VyID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICAoMCwgX2NsZWFudXBfaGVscGVyLmNsZWFyR2xvYmFsQ2FjaGVzKSgpOwogICAgICB9CiAgICAgIGlmIChjYW5jZWxYSFJzKSB7CiAgICAgICAgY2FuY2VsWEhScyhuZXcgX3V0aWwuQWJvcnRFeGNlcHRpb24oIldvcmtlciB3YXMgdGVybWluYXRlZC4iKSk7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCB0YXNrIG9mIFdvcmtlclRhc2tzKSB7CiAgICAgICAgd2FpdE9uLnB1c2godGFzay5maW5pc2hlZCk7CiAgICAgICAgdGFzay50ZXJtaW5hdGUoKTsKICAgICAgfQogICAgICByZXR1cm4gUHJvbWlzZS5hbGwod2FpdE9uKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICBoYW5kbGVyLmRlc3Ryb3koKTsKICAgICAgICBoYW5kbGVyID0gbnVsbDsKICAgICAgfSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIlJlYWR5IiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgc2V0dXBEb2MoZG9jUGFyYW1zKTsKICAgICAgZG9jUGFyYW1zID0gbnVsbDsKICAgIH0pOwogICAgcmV0dXJuIHdvcmtlckhhbmRsZXJOYW1lOwogIH0KICBzdGF0aWMgaW5pdGlhbGl6ZUZyb21Qb3J0KHBvcnQpIHsKICAgIGNvbnN0IGhhbmRsZXIgPSBuZXcgX21lc3NhZ2VfaGFuZGxlci5NZXNzYWdlSGFuZGxlcigid29ya2VyIiwgIm1haW4iLCBwb3J0KTsKICAgIFdvcmtlck1lc3NhZ2VIYW5kbGVyLnNldHVwKGhhbmRsZXIsIHBvcnQpOwogICAgaGFuZGxlci5zZW5kKCJyZWFkeSIsIG51bGwpOwogIH0KfQpleHBvcnRzLldvcmtlck1lc3NhZ2VIYW5kbGVyID0gV29ya2VyTWVzc2FnZUhhbmRsZXI7CmZ1bmN0aW9uIGlzTWVzc2FnZVBvcnQobWF5YmVQb3J0KSB7CiAgcmV0dXJuIHR5cGVvZiBtYXliZVBvcnQucG9zdE1lc3NhZ2UgPT09ICJmdW5jdGlvbiIgJiYgIm9ubWVzc2FnZSIgaW4gbWF5YmVQb3J0Owp9CmlmICh0eXBlb2Ygd2luZG93ID09PSAidW5kZWZpbmVkIiAmJiAhX2lzX25vZGUuaXNOb2RlSlMgJiYgdHlwZW9mIHNlbGYgIT09ICJ1bmRlZmluZWQiICYmIGlzTWVzc2FnZVBvcnQoc2VsZikpIHsKICBXb3JrZXJNZXNzYWdlSGFuZGxlci5pbml0aWFsaXplRnJvbVBvcnQoc2VsZik7Cn0KCi8qKiovIH0pLAovKiAyICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5WZXJib3NpdHlMZXZlbCA9IGV4cG9ydHMuVXRpbCA9IGV4cG9ydHMuVW5rbm93bkVycm9yRXhjZXB0aW9uID0gZXhwb3J0cy5VbmV4cGVjdGVkUmVzcG9uc2VFeGNlcHRpb24gPSBleHBvcnRzLlRleHRSZW5kZXJpbmdNb2RlID0gZXhwb3J0cy5SZW5kZXJpbmdJbnRlbnRGbGFnID0gZXhwb3J0cy5QZXJtaXNzaW9uRmxhZyA9IGV4cG9ydHMuUGFzc3dvcmRSZXNwb25zZXMgPSBleHBvcnRzLlBhc3N3b3JkRXhjZXB0aW9uID0gZXhwb3J0cy5QYWdlQWN0aW9uRXZlbnRUeXBlID0gZXhwb3J0cy5PUFMgPSBleHBvcnRzLk1pc3NpbmdQREZFeGNlcHRpb24gPSBleHBvcnRzLk1BWF9JTUFHRV9TSVpFX1RPX0NBQ0hFID0gZXhwb3J0cy5MSU5FX0ZBQ1RPUiA9IGV4cG9ydHMuTElORV9ERVNDRU5UX0ZBQ1RPUiA9IGV4cG9ydHMuSW52YWxpZFBERkV4Y2VwdGlvbiA9IGV4cG9ydHMuSW1hZ2VLaW5kID0gZXhwb3J0cy5JREVOVElUWV9NQVRSSVggPSBleHBvcnRzLkZvcm1hdEVycm9yID0gZXhwb3J0cy5GZWF0dXJlVGVzdCA9IGV4cG9ydHMuRk9OVF9JREVOVElUWV9NQVRSSVggPSBleHBvcnRzLkRvY3VtZW50QWN0aW9uRXZlbnRUeXBlID0gZXhwb3J0cy5DTWFwQ29tcHJlc3Npb25UeXBlID0gZXhwb3J0cy5CYXNlRXhjZXB0aW9uID0gZXhwb3J0cy5CQVNFTElORV9GQUNUT1IgPSBleHBvcnRzLkFubm90YXRpb25UeXBlID0gZXhwb3J0cy5Bbm5vdGF0aW9uU3RhdGVNb2RlbFR5cGUgPSBleHBvcnRzLkFubm90YXRpb25SZXZpZXdTdGF0ZSA9IGV4cG9ydHMuQW5ub3RhdGlvblJlcGx5VHlwZSA9IGV4cG9ydHMuQW5ub3RhdGlvbk1vZGUgPSBleHBvcnRzLkFubm90YXRpb25NYXJrZWRTdGF0ZSA9IGV4cG9ydHMuQW5ub3RhdGlvbkZsYWcgPSBleHBvcnRzLkFubm90YXRpb25GaWVsZEZsYWcgPSBleHBvcnRzLkFubm90YXRpb25FZGl0b3JUeXBlID0gZXhwb3J0cy5Bbm5vdGF0aW9uRWRpdG9yUHJlZml4ID0gZXhwb3J0cy5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZSA9IGV4cG9ydHMuQW5ub3RhdGlvbkJvcmRlclN0eWxlVHlwZSA9IGV4cG9ydHMuQW5ub3RhdGlvbkFjdGlvbkV2ZW50VHlwZSA9IGV4cG9ydHMuQWJvcnRFeGNlcHRpb24gPSB2b2lkIDA7CmV4cG9ydHMuYXNzZXJ0ID0gYXNzZXJ0OwpleHBvcnRzLmJ5dGVzVG9TdHJpbmcgPSBieXRlc1RvU3RyaW5nOwpleHBvcnRzLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5ID0gY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHk7CmV4cG9ydHMuY3JlYXRlVmFsaWRBYnNvbHV0ZVVybCA9IGNyZWF0ZVZhbGlkQWJzb2x1dGVVcmw7CmV4cG9ydHMuZ2V0TW9kaWZpY2F0aW9uRGF0ZSA9IGdldE1vZGlmaWNhdGlvbkRhdGU7CmV4cG9ydHMuZ2V0VmVyYm9zaXR5TGV2ZWwgPSBnZXRWZXJib3NpdHlMZXZlbDsKZXhwb3J0cy5pbmZvID0gaW5mbzsKZXhwb3J0cy5pc0FycmF5QnVmZmVyID0gaXNBcnJheUJ1ZmZlcjsKZXhwb3J0cy5pc0FycmF5RXF1YWwgPSBpc0FycmF5RXF1YWw7CmV4cG9ydHMub2JqZWN0RnJvbU1hcCA9IG9iamVjdEZyb21NYXA7CmV4cG9ydHMub2JqZWN0U2l6ZSA9IG9iamVjdFNpemU7CmV4cG9ydHMuc2V0VmVyYm9zaXR5TGV2ZWwgPSBzZXRWZXJib3NpdHlMZXZlbDsKZXhwb3J0cy5zaGFkb3cgPSBzaGFkb3c7CmV4cG9ydHMuc3RyaW5nMzIgPSBzdHJpbmczMjsKZXhwb3J0cy5zdHJpbmdUb0J5dGVzID0gc3RyaW5nVG9CeXRlczsKZXhwb3J0cy5zdHJpbmdUb1BERlN0cmluZyA9IHN0cmluZ1RvUERGU3RyaW5nOwpleHBvcnRzLnN0cmluZ1RvVVRGOFN0cmluZyA9IHN0cmluZ1RvVVRGOFN0cmluZzsKZXhwb3J0cy51bnJlYWNoYWJsZSA9IHVucmVhY2hhYmxlOwpleHBvcnRzLnV0ZjhTdHJpbmdUb1N0cmluZyA9IHV0ZjhTdHJpbmdUb1N0cmluZzsKZXhwb3J0cy53YXJuID0gd2FybjsKaWYgKCFnbG9iYWxUaGlzLl9wZGZqc0NvbXBhdGliaWxpdHlDaGVja2VkKSB7CiAgZ2xvYmFsVGhpcy5fcGRmanNDb21wYXRpYmlsaXR5Q2hlY2tlZCA9IHRydWU7CiAgX193X3BkZmpzX3JlcXVpcmVfXygzKTsKfQpjb25zdCBJREVOVElUWV9NQVRSSVggPSBbMSwgMCwgMCwgMSwgMCwgMF07CmV4cG9ydHMuSURFTlRJVFlfTUFUUklYID0gSURFTlRJVFlfTUFUUklYOwpjb25zdCBGT05UX0lERU5USVRZX01BVFJJWCA9IFswLjAwMSwgMCwgMCwgMC4wMDEsIDAsIDBdOwpleHBvcnRzLkZPTlRfSURFTlRJVFlfTUFUUklYID0gRk9OVF9JREVOVElUWV9NQVRSSVg7CmNvbnN0IE1BWF9JTUFHRV9TSVpFX1RPX0NBQ0hFID0gMTBlNjsKZXhwb3J0cy5NQVhfSU1BR0VfU0laRV9UT19DQUNIRSA9IE1BWF9JTUFHRV9TSVpFX1RPX0NBQ0hFOwpjb25zdCBMSU5FX0ZBQ1RPUiA9IDEuMzU7CmV4cG9ydHMuTElORV9GQUNUT1IgPSBMSU5FX0ZBQ1RPUjsKY29uc3QgTElORV9ERVNDRU5UX0ZBQ1RPUiA9IDAuMzU7CmV4cG9ydHMuTElORV9ERVNDRU5UX0ZBQ1RPUiA9IExJTkVfREVTQ0VOVF9GQUNUT1I7CmNvbnN0IEJBU0VMSU5FX0ZBQ1RPUiA9IExJTkVfREVTQ0VOVF9GQUNUT1IgLyBMSU5FX0ZBQ1RPUjsKZXhwb3J0cy5CQVNFTElORV9GQUNUT1IgPSBCQVNFTElORV9GQUNUT1I7CmNvbnN0IFJlbmRlcmluZ0ludGVudEZsYWcgPSB7CiAgQU5ZOiAweDAxLAogIERJU1BMQVk6IDB4MDIsCiAgUFJJTlQ6IDB4MDQsCiAgU0FWRTogMHgwOCwKICBBTk5PVEFUSU9OU19GT1JNUzogMHgxMCwKICBBTk5PVEFUSU9OU19TVE9SQUdFOiAweDIwLAogIEFOTk9UQVRJT05TX0RJU0FCTEU6IDB4NDAsCiAgT1BMSVNUOiAweDEwMAp9OwpleHBvcnRzLlJlbmRlcmluZ0ludGVudEZsYWcgPSBSZW5kZXJpbmdJbnRlbnRGbGFnOwpjb25zdCBBbm5vdGF0aW9uTW9kZSA9IHsKICBESVNBQkxFOiAwLAogIEVOQUJMRTogMSwKICBFTkFCTEVfRk9STVM6IDIsCiAgRU5BQkxFX1NUT1JBR0U6IDMKfTsKZXhwb3J0cy5Bbm5vdGF0aW9uTW9kZSA9IEFubm90YXRpb25Nb2RlOwpjb25zdCBBbm5vdGF0aW9uRWRpdG9yUHJlZml4ID0gInBkZmpzX2ludGVybmFsX2VkaXRvcl8iOwpleHBvcnRzLkFubm90YXRpb25FZGl0b3JQcmVmaXggPSBBbm5vdGF0aW9uRWRpdG9yUHJlZml4Owpjb25zdCBBbm5vdGF0aW9uRWRpdG9yVHlwZSA9IHsKICBESVNBQkxFOiAtMSwKICBOT05FOiAwLAogIEZSRUVURVhUOiAzLAogIElOSzogMTUKfTsKZXhwb3J0cy5Bbm5vdGF0aW9uRWRpdG9yVHlwZSA9IEFubm90YXRpb25FZGl0b3JUeXBlOwpjb25zdCBBbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZSA9IHsKICBGUkVFVEVYVF9TSVpFOiAxLAogIEZSRUVURVhUX0NPTE9SOiAyLAogIEZSRUVURVhUX09QQUNJVFk6IDMsCiAgSU5LX0NPTE9SOiAxMSwKICBJTktfVEhJQ0tORVNTOiAxMiwKICBJTktfT1BBQ0lUWTogMTMKfTsKZXhwb3J0cy5Bbm5vdGF0aW9uRWRpdG9yUGFyYW1zVHlwZSA9IEFubm90YXRpb25FZGl0b3JQYXJhbXNUeXBlOwpjb25zdCBQZXJtaXNzaW9uRmxhZyA9IHsKICBQUklOVDogMHgwNCwKICBNT0RJRllfQ09OVEVOVFM6IDB4MDgsCiAgQ09QWTogMHgxMCwKICBNT0RJRllfQU5OT1RBVElPTlM6IDB4MjAsCiAgRklMTF9JTlRFUkFDVElWRV9GT1JNUzogMHgxMDAsCiAgQ09QWV9GT1JfQUNDRVNTSUJJTElUWTogMHgyMDAsCiAgQVNTRU1CTEU6IDB4NDAwLAogIFBSSU5UX0hJR0hfUVVBTElUWTogMHg4MDAKfTsKZXhwb3J0cy5QZXJtaXNzaW9uRmxhZyA9IFBlcm1pc3Npb25GbGFnOwpjb25zdCBUZXh0UmVuZGVyaW5nTW9kZSA9IHsKICBGSUxMOiAwLAogIFNUUk9LRTogMSwKICBGSUxMX1NUUk9LRTogMiwKICBJTlZJU0lCTEU6IDMsCiAgRklMTF9BRERfVE9fUEFUSDogNCwKICBTVFJPS0VfQUREX1RPX1BBVEg6IDUsCiAgRklMTF9TVFJPS0VfQUREX1RPX1BBVEg6IDYsCiAgQUREX1RPX1BBVEg6IDcsCiAgRklMTF9TVFJPS0VfTUFTSzogMywKICBBRERfVE9fUEFUSF9GTEFHOiA0Cn07CmV4cG9ydHMuVGV4dFJlbmRlcmluZ01vZGUgPSBUZXh0UmVuZGVyaW5nTW9kZTsKY29uc3QgSW1hZ2VLaW5kID0gewogIEdSQVlTQ0FMRV8xQlBQOiAxLAogIFJHQl8yNEJQUDogMiwKICBSR0JBXzMyQlBQOiAzCn07CmV4cG9ydHMuSW1hZ2VLaW5kID0gSW1hZ2VLaW5kOwpjb25zdCBBbm5vdGF0aW9uVHlwZSA9IHsKICBURVhUOiAxLAogIExJTks6IDIsCiAgRlJFRVRFWFQ6IDMsCiAgTElORTogNCwKICBTUVVBUkU6IDUsCiAgQ0lSQ0xFOiA2LAogIFBPTFlHT046IDcsCiAgUE9MWUxJTkU6IDgsCiAgSElHSExJR0hUOiA5LAogIFVOREVSTElORTogMTAsCiAgU1FVSUdHTFk6IDExLAogIFNUUklLRU9VVDogMTIsCiAgU1RBTVA6IDEzLAogIENBUkVUOiAxNCwKICBJTks6IDE1LAogIFBPUFVQOiAxNiwKICBGSUxFQVRUQUNITUVOVDogMTcsCiAgU09VTkQ6IDE4LAogIE1PVklFOiAxOSwKICBXSURHRVQ6IDIwLAogIFNDUkVFTjogMjEsCiAgUFJJTlRFUk1BUks6IDIyLAogIFRSQVBORVQ6IDIzLAogIFdBVEVSTUFSSzogMjQsCiAgVEhSRUVEOiAyNSwKICBSRURBQ1Q6IDI2Cn07CmV4cG9ydHMuQW5ub3RhdGlvblR5cGUgPSBBbm5vdGF0aW9uVHlwZTsKY29uc3QgQW5ub3RhdGlvblN0YXRlTW9kZWxUeXBlID0gewogIE1BUktFRDogIk1hcmtlZCIsCiAgUkVWSUVXOiAiUmV2aWV3Igp9OwpleHBvcnRzLkFubm90YXRpb25TdGF0ZU1vZGVsVHlwZSA9IEFubm90YXRpb25TdGF0ZU1vZGVsVHlwZTsKY29uc3QgQW5ub3RhdGlvbk1hcmtlZFN0YXRlID0gewogIE1BUktFRDogIk1hcmtlZCIsCiAgVU5NQVJLRUQ6ICJVbm1hcmtlZCIKfTsKZXhwb3J0cy5Bbm5vdGF0aW9uTWFya2VkU3RhdGUgPSBBbm5vdGF0aW9uTWFya2VkU3RhdGU7CmNvbnN0IEFubm90YXRpb25SZXZpZXdTdGF0ZSA9IHsKICBBQ0NFUFRFRDogIkFjY2VwdGVkIiwKICBSRUpFQ1RFRDogIlJlamVjdGVkIiwKICBDQU5DRUxMRUQ6ICJDYW5jZWxsZWQiLAogIENPTVBMRVRFRDogIkNvbXBsZXRlZCIsCiAgTk9ORTogIk5vbmUiCn07CmV4cG9ydHMuQW5ub3RhdGlvblJldmlld1N0YXRlID0gQW5ub3RhdGlvblJldmlld1N0YXRlOwpjb25zdCBBbm5vdGF0aW9uUmVwbHlUeXBlID0gewogIEdST1VQOiAiR3JvdXAiLAogIFJFUExZOiAiUiIKfTsKZXhwb3J0cy5Bbm5vdGF0aW9uUmVwbHlUeXBlID0gQW5ub3RhdGlvblJlcGx5VHlwZTsKY29uc3QgQW5ub3RhdGlvbkZsYWcgPSB7CiAgSU5WSVNJQkxFOiAweDAxLAogIEhJRERFTjogMHgwMiwKICBQUklOVDogMHgwNCwKICBOT1pPT006IDB4MDgsCiAgTk9ST1RBVEU6IDB4MTAsCiAgTk9WSUVXOiAweDIwLAogIFJFQURPTkxZOiAweDQwLAogIExPQ0tFRDogMHg4MCwKICBUT0dHTEVOT1ZJRVc6IDB4MTAwLAogIExPQ0tFRENPTlRFTlRTOiAweDIwMAp9OwpleHBvcnRzLkFubm90YXRpb25GbGFnID0gQW5ub3RhdGlvbkZsYWc7CmNvbnN0IEFubm90YXRpb25GaWVsZEZsYWcgPSB7CiAgUkVBRE9OTFk6IDB4MDAwMDAwMSwKICBSRVFVSVJFRDogMHgwMDAwMDAyLAogIE5PRVhQT1JUOiAweDAwMDAwMDQsCiAgTVVMVElMSU5FOiAweDAwMDEwMDAsCiAgUEFTU1dPUkQ6IDB4MDAwMjAwMCwKICBOT1RPR0dMRVRPT0ZGOiAweDAwMDQwMDAsCiAgUkFESU86IDB4MDAwODAwMCwKICBQVVNIQlVUVE9OOiAweDAwMTAwMDAsCiAgQ09NQk86IDB4MDAyMDAwMCwKICBFRElUOiAweDAwNDAwMDAsCiAgU09SVDogMHgwMDgwMDAwLAogIEZJTEVTRUxFQ1Q6IDB4MDEwMDAwMCwKICBNVUxUSVNFTEVDVDogMHgwMjAwMDAwLAogIERPTk9UU1BFTExDSEVDSzogMHgwNDAwMDAwLAogIERPTk9UU0NST0xMOiAweDA4MDAwMDAsCiAgQ09NQjogMHgxMDAwMDAwLAogIFJJQ0hURVhUOiAweDIwMDAwMDAsCiAgUkFESU9TSU5VTklTT046IDB4MjAwMDAwMCwKICBDT01NSVRPTlNFTENIQU5HRTogMHg0MDAwMDAwCn07CmV4cG9ydHMuQW5ub3RhdGlvbkZpZWxkRmxhZyA9IEFubm90YXRpb25GaWVsZEZsYWc7CmNvbnN0IEFubm90YXRpb25Cb3JkZXJTdHlsZVR5cGUgPSB7CiAgU09MSUQ6IDEsCiAgREFTSEVEOiAyLAogIEJFVkVMRUQ6IDMsCiAgSU5TRVQ6IDQsCiAgVU5ERVJMSU5FOiA1Cn07CmV4cG9ydHMuQW5ub3RhdGlvbkJvcmRlclN0eWxlVHlwZSA9IEFubm90YXRpb25Cb3JkZXJTdHlsZVR5cGU7CmNvbnN0IEFubm90YXRpb25BY3Rpb25FdmVudFR5cGUgPSB7CiAgRTogIk1vdXNlIEVudGVyIiwKICBYOiAiTW91c2UgRXhpdCIsCiAgRDogIk1vdXNlIERvd24iLAogIFU6ICJNb3VzZSBVcCIsCiAgRm86ICJGb2N1cyIsCiAgQmw6ICJCbHVyIiwKICBQTzogIlBhZ2VPcGVuIiwKICBQQzogIlBhZ2VDbG9zZSIsCiAgUFY6ICJQYWdlVmlzaWJsZSIsCiAgUEk6ICJQYWdlSW52aXNpYmxlIiwKICBLOiAiS2V5c3Ryb2tlIiwKICBGOiAiRm9ybWF0IiwKICBWOiAiVmFsaWRhdGUiLAogIEM6ICJDYWxjdWxhdGUiCn07CmV4cG9ydHMuQW5ub3RhdGlvbkFjdGlvbkV2ZW50VHlwZSA9IEFubm90YXRpb25BY3Rpb25FdmVudFR5cGU7CmNvbnN0IERvY3VtZW50QWN0aW9uRXZlbnRUeXBlID0gewogIFdDOiAiV2lsbENsb3NlIiwKICBXUzogIldpbGxTYXZlIiwKICBEUzogIkRpZFNhdmUiLAogIFdQOiAiV2lsbFByaW50IiwKICBEUDogIkRpZFByaW50Igp9OwpleHBvcnRzLkRvY3VtZW50QWN0aW9uRXZlbnRUeXBlID0gRG9jdW1lbnRBY3Rpb25FdmVudFR5cGU7CmNvbnN0IFBhZ2VBY3Rpb25FdmVudFR5cGUgPSB7CiAgTzogIlBhZ2VPcGVuIiwKICBDOiAiUGFnZUNsb3NlIgp9OwpleHBvcnRzLlBhZ2VBY3Rpb25FdmVudFR5cGUgPSBQYWdlQWN0aW9uRXZlbnRUeXBlOwpjb25zdCBWZXJib3NpdHlMZXZlbCA9IHsKICBFUlJPUlM6IDAsCiAgV0FSTklOR1M6IDEsCiAgSU5GT1M6IDUKfTsKZXhwb3J0cy5WZXJib3NpdHlMZXZlbCA9IFZlcmJvc2l0eUxldmVsOwpjb25zdCBDTWFwQ29tcHJlc3Npb25UeXBlID0gewogIE5PTkU6IDAsCiAgQklOQVJZOiAxCn07CmV4cG9ydHMuQ01hcENvbXByZXNzaW9uVHlwZSA9IENNYXBDb21wcmVzc2lvblR5cGU7CmNvbnN0IE9QUyA9IHsKICBkZXBlbmRlbmN5OiAxLAogIHNldExpbmVXaWR0aDogMiwKICBzZXRMaW5lQ2FwOiAzLAogIHNldExpbmVKb2luOiA0LAogIHNldE1pdGVyTGltaXQ6IDUsCiAgc2V0RGFzaDogNiwKICBzZXRSZW5kZXJpbmdJbnRlbnQ6IDcsCiAgc2V0RmxhdG5lc3M6IDgsCiAgc2V0R1N0YXRlOiA5LAogIHNhdmU6IDEwLAogIHJlc3RvcmU6IDExLAogIHRyYW5zZm9ybTogMTIsCiAgbW92ZVRvOiAxMywKICBsaW5lVG86IDE0LAogIGN1cnZlVG86IDE1LAogIGN1cnZlVG8yOiAxNiwKICBjdXJ2ZVRvMzogMTcsCiAgY2xvc2VQYXRoOiAxOCwKICByZWN0YW5nbGU6IDE5LAogIHN0cm9rZTogMjAsCiAgY2xvc2VTdHJva2U6IDIxLAogIGZpbGw6IDIyLAogIGVvRmlsbDogMjMsCiAgZmlsbFN0cm9rZTogMjQsCiAgZW9GaWxsU3Ryb2tlOiAyNSwKICBjbG9zZUZpbGxTdHJva2U6IDI2LAogIGNsb3NlRU9GaWxsU3Ryb2tlOiAyNywKICBlbmRQYXRoOiAyOCwKICBjbGlwOiAyOSwKICBlb0NsaXA6IDMwLAogIGJlZ2luVGV4dDogMzEsCiAgZW5kVGV4dDogMzIsCiAgc2V0Q2hhclNwYWNpbmc6IDMzLAogIHNldFdvcmRTcGFjaW5nOiAzNCwKICBzZXRIU2NhbGU6IDM1LAogIHNldExlYWRpbmc6IDM2LAogIHNldEZvbnQ6IDM3LAogIHNldFRleHRSZW5kZXJpbmdNb2RlOiAzOCwKICBzZXRUZXh0UmlzZTogMzksCiAgbW92ZVRleHQ6IDQwLAogIHNldExlYWRpbmdNb3ZlVGV4dDogNDEsCiAgc2V0VGV4dE1hdHJpeDogNDIsCiAgbmV4dExpbmU6IDQzLAogIHNob3dUZXh0OiA0NCwKICBzaG93U3BhY2VkVGV4dDogNDUsCiAgbmV4dExpbmVTaG93VGV4dDogNDYsCiAgbmV4dExpbmVTZXRTcGFjaW5nU2hvd1RleHQ6IDQ3LAogIHNldENoYXJXaWR0aDogNDgsCiAgc2V0Q2hhcldpZHRoQW5kQm91bmRzOiA0OSwKICBzZXRTdHJva2VDb2xvclNwYWNlOiA1MCwKICBzZXRGaWxsQ29sb3JTcGFjZTogNTEsCiAgc2V0U3Ryb2tlQ29sb3I6IDUyLAogIHNldFN0cm9rZUNvbG9yTjogNTMsCiAgc2V0RmlsbENvbG9yOiA1NCwKICBzZXRGaWxsQ29sb3JOOiA1NSwKICBzZXRTdHJva2VHcmF5OiA1NiwKICBzZXRGaWxsR3JheTogNTcsCiAgc2V0U3Ryb2tlUkdCQ29sb3I6IDU4LAogIHNldEZpbGxSR0JDb2xvcjogNTksCiAgc2V0U3Ryb2tlQ01ZS0NvbG9yOiA2MCwKICBzZXRGaWxsQ01ZS0NvbG9yOiA2MSwKICBzaGFkaW5nRmlsbDogNjIsCiAgYmVnaW5JbmxpbmVJbWFnZTogNjMsCiAgYmVnaW5JbWFnZURhdGE6IDY0LAogIGVuZElubGluZUltYWdlOiA2NSwKICBwYWludFhPYmplY3Q6IDY2LAogIG1hcmtQb2ludDogNjcsCiAgbWFya1BvaW50UHJvcHM6IDY4LAogIGJlZ2luTWFya2VkQ29udGVudDogNjksCiAgYmVnaW5NYXJrZWRDb250ZW50UHJvcHM6IDcwLAogIGVuZE1hcmtlZENvbnRlbnQ6IDcxLAogIGJlZ2luQ29tcGF0OiA3MiwKICBlbmRDb21wYXQ6IDczLAogIHBhaW50Rm9ybVhPYmplY3RCZWdpbjogNzQsCiAgcGFpbnRGb3JtWE9iamVjdEVuZDogNzUsCiAgYmVnaW5Hcm91cDogNzYsCiAgZW5kR3JvdXA6IDc3LAogIGJlZ2luQW5ub3RhdGlvbjogODAsCiAgZW5kQW5ub3RhdGlvbjogODEsCiAgcGFpbnRJbWFnZU1hc2tYT2JqZWN0OiA4MywKICBwYWludEltYWdlTWFza1hPYmplY3RHcm91cDogODQsCiAgcGFpbnRJbWFnZVhPYmplY3Q6IDg1LAogIHBhaW50SW5saW5lSW1hZ2VYT2JqZWN0OiA4NiwKICBwYWludElubGluZUltYWdlWE9iamVjdEdyb3VwOiA4NywKICBwYWludEltYWdlWE9iamVjdFJlcGVhdDogODgsCiAgcGFpbnRJbWFnZU1hc2tYT2JqZWN0UmVwZWF0OiA4OSwKICBwYWludFNvbGlkQ29sb3JJbWFnZU1hc2s6IDkwLAogIGNvbnN0cnVjdFBhdGg6IDkxCn07CmV4cG9ydHMuT1BTID0gT1BTOwpjb25zdCBQYXNzd29yZFJlc3BvbnNlcyA9IHsKICBORUVEX1BBU1NXT1JEOiAxLAogIElOQ09SUkVDVF9QQVNTV09SRDogMgp9OwpleHBvcnRzLlBhc3N3b3JkUmVzcG9uc2VzID0gUGFzc3dvcmRSZXNwb25zZXM7CmxldCB2ZXJib3NpdHkgPSBWZXJib3NpdHlMZXZlbC5XQVJOSU5HUzsKZnVuY3Rpb24gc2V0VmVyYm9zaXR5TGV2ZWwobGV2ZWwpIHsKICBpZiAoTnVtYmVyLmlzSW50ZWdlcihsZXZlbCkpIHsKICAgIHZlcmJvc2l0eSA9IGxldmVsOwogIH0KfQpmdW5jdGlvbiBnZXRWZXJib3NpdHlMZXZlbCgpIHsKICByZXR1cm4gdmVyYm9zaXR5Owp9CmZ1bmN0aW9uIGluZm8obXNnKSB7CiAgaWYgKHZlcmJvc2l0eSA+PSBWZXJib3NpdHlMZXZlbC5JTkZPUykgewogICAgY29uc29sZS5sb2coYEluZm86ICR7bXNnfWApOwogIH0KfQpmdW5jdGlvbiB3YXJuKG1zZykgewogIGlmICh2ZXJib3NpdHkgPj0gVmVyYm9zaXR5TGV2ZWwuV0FSTklOR1MpIHsKICAgIGNvbnNvbGUubG9nKGBXYXJuaW5nOiAke21zZ31gKTsKICB9Cn0KZnVuY3Rpb24gdW5yZWFjaGFibGUobXNnKSB7CiAgdGhyb3cgbmV3IEVycm9yKG1zZyk7Cn0KZnVuY3Rpb24gYXNzZXJ0KGNvbmQsIG1zZykgewogIGlmICghY29uZCkgewogICAgdW5yZWFjaGFibGUobXNnKTsKICB9Cn0KZnVuY3Rpb24gX2lzVmFsaWRQcm90b2NvbCh1cmwpIHsKICBpZiAoIXVybCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBzd2l0Y2ggKHVybC5wcm90b2NvbCkgewogICAgY2FzZSAiaHR0cDoiOgogICAgY2FzZSAiaHR0cHM6IjoKICAgIGNhc2UgImZ0cDoiOgogICAgY2FzZSAibWFpbHRvOiI6CiAgICBjYXNlICJ0ZWw6IjoKICAgICAgcmV0dXJuIHRydWU7CiAgICBkZWZhdWx0OgogICAgICByZXR1cm4gZmFsc2U7CiAgfQp9CmZ1bmN0aW9uIGNyZWF0ZVZhbGlkQWJzb2x1dGVVcmwodXJsKSB7CiAgbGV0IGJhc2VVcmwgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IG51bGw7CiAgbGV0IG9wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IG51bGw7CiAgaWYgKCF1cmwpIHsKICAgIHJldHVybiBudWxsOwogIH0KICB0cnkgewogICAgaWYgKG9wdGlvbnMgJiYgdHlwZW9mIHVybCA9PT0gInN0cmluZyIpIHsKICAgICAgaWYgKG9wdGlvbnMuYWRkRGVmYXVsdFByb3RvY29sICYmIHVybC5zdGFydHNXaXRoKCJ3d3cuIikpIHsKICAgICAgICBjb25zdCBkb3RzID0gdXJsLm1hdGNoKC9cLi9nKTsKICAgICAgICBpZiAoZG90cyAmJiBkb3RzLmxlbmd0aCA+PSAyKSB7CiAgICAgICAgICB1cmwgPSBgaHR0cDovLyR7dXJsfWA7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChvcHRpb25zLnRyeUNvbnZlcnRFbmNvZGluZykgewogICAgICAgIHRyeSB7CiAgICAgICAgICB1cmwgPSBzdHJpbmdUb1VURjhTdHJpbmcodXJsKTsKICAgICAgICB9IGNhdGNoIChleCkge30KICAgICAgfQogICAgfQogICAgY29uc3QgYWJzb2x1dGVVcmwgPSBiYXNlVXJsID8gbmV3IFVSTCh1cmwsIGJhc2VVcmwpIDogbmV3IFVSTCh1cmwpOwogICAgaWYgKF9pc1ZhbGlkUHJvdG9jb2woYWJzb2x1dGVVcmwpKSB7CiAgICAgIHJldHVybiBhYnNvbHV0ZVVybDsKICAgIH0KICB9IGNhdGNoIChleCkge30KICByZXR1cm4gbnVsbDsKfQpmdW5jdGlvbiBzaGFkb3cob2JqLCBwcm9wLCB2YWx1ZSkgewogIGxldCBub25TZXJpYWxpemFibGUgPSBhcmd1bWVudHMubGVuZ3RoID4gMyAmJiBhcmd1bWVudHNbM10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1szXSA6IGZhbHNlOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIHByb3AsIHsKICAgIHZhbHVlLAogICAgZW51bWVyYWJsZTogIW5vblNlcmlhbGl6YWJsZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgIHdyaXRhYmxlOiBmYWxzZQogIH0pOwogIHJldHVybiB2YWx1ZTsKfQpjb25zdCBCYXNlRXhjZXB0aW9uID0gZnVuY3Rpb24gQmFzZUV4Y2VwdGlvbkNsb3N1cmUoKSB7CiAgZnVuY3Rpb24gQmFzZUV4Y2VwdGlvbihtZXNzYWdlLCBuYW1lKSB7CiAgICBpZiAodGhpcy5jb25zdHJ1Y3RvciA9PT0gQmFzZUV4Y2VwdGlvbikgewogICAgICB1bnJlYWNoYWJsZSgiQ2Fubm90IGluaXRpYWxpemUgQmFzZUV4Y2VwdGlvbi4iKTsKICAgIH0KICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7CiAgICB0aGlzLm5hbWUgPSBuYW1lOwogIH0KICBCYXNlRXhjZXB0aW9uLnByb3RvdHlwZSA9IG5ldyBFcnJvcigpOwogIEJhc2VFeGNlcHRpb24uY29uc3RydWN0b3IgPSBCYXNlRXhjZXB0aW9uOwogIHJldHVybiBCYXNlRXhjZXB0aW9uOwp9KCk7CmV4cG9ydHMuQmFzZUV4Y2VwdGlvbiA9IEJhc2VFeGNlcHRpb247CmNsYXNzIFBhc3N3b3JkRXhjZXB0aW9uIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnLCBjb2RlKSB7CiAgICBzdXBlcihtc2csICJQYXNzd29yZEV4Y2VwdGlvbiIpOwogICAgdGhpcy5jb2RlID0gY29kZTsKICB9Cn0KZXhwb3J0cy5QYXNzd29yZEV4Y2VwdGlvbiA9IFBhc3N3b3JkRXhjZXB0aW9uOwpjbGFzcyBVbmtub3duRXJyb3JFeGNlcHRpb24gZXh0ZW5kcyBCYXNlRXhjZXB0aW9uIHsKICBjb25zdHJ1Y3Rvcihtc2csIGRldGFpbHMpIHsKICAgIHN1cGVyKG1zZywgIlVua25vd25FcnJvckV4Y2VwdGlvbiIpOwogICAgdGhpcy5kZXRhaWxzID0gZGV0YWlsczsKICB9Cn0KZXhwb3J0cy5Vbmtub3duRXJyb3JFeGNlcHRpb24gPSBVbmtub3duRXJyb3JFeGNlcHRpb247CmNsYXNzIEludmFsaWRQREZFeGNlcHRpb24gZXh0ZW5kcyBCYXNlRXhjZXB0aW9uIHsKICBjb25zdHJ1Y3Rvcihtc2cpIHsKICAgIHN1cGVyKG1zZywgIkludmFsaWRQREZFeGNlcHRpb24iKTsKICB9Cn0KZXhwb3J0cy5JbnZhbGlkUERGRXhjZXB0aW9uID0gSW52YWxpZFBERkV4Y2VwdGlvbjsKY2xhc3MgTWlzc2luZ1BERkV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZykgewogICAgc3VwZXIobXNnLCAiTWlzc2luZ1BERkV4Y2VwdGlvbiIpOwogIH0KfQpleHBvcnRzLk1pc3NpbmdQREZFeGNlcHRpb24gPSBNaXNzaW5nUERGRXhjZXB0aW9uOwpjbGFzcyBVbmV4cGVjdGVkUmVzcG9uc2VFeGNlcHRpb24gZXh0ZW5kcyBCYXNlRXhjZXB0aW9uIHsKICBjb25zdHJ1Y3Rvcihtc2csIHN0YXR1cykgewogICAgc3VwZXIobXNnLCAiVW5leHBlY3RlZFJlc3BvbnNlRXhjZXB0aW9uIik7CiAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICB9Cn0KZXhwb3J0cy5VbmV4cGVjdGVkUmVzcG9uc2VFeGNlcHRpb24gPSBVbmV4cGVjdGVkUmVzcG9uc2VFeGNlcHRpb247CmNsYXNzIEZvcm1hdEVycm9yIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnKSB7CiAgICBzdXBlcihtc2csICJGb3JtYXRFcnJvciIpOwogIH0KfQpleHBvcnRzLkZvcm1hdEVycm9yID0gRm9ybWF0RXJyb3I7CmNsYXNzIEFib3J0RXhjZXB0aW9uIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnKSB7CiAgICBzdXBlcihtc2csICJBYm9ydEV4Y2VwdGlvbiIpOwogIH0KfQpleHBvcnRzLkFib3J0RXhjZXB0aW9uID0gQWJvcnRFeGNlcHRpb247CmZ1bmN0aW9uIGJ5dGVzVG9TdHJpbmcoYnl0ZXMpIHsKICBpZiAodHlwZW9mIGJ5dGVzICE9PSAib2JqZWN0IiB8fCBieXRlcyA9PT0gbnVsbCB8fCBieXRlcy5sZW5ndGggPT09IHVuZGVmaW5lZCkgewogICAgdW5yZWFjaGFibGUoIkludmFsaWQgYXJndW1lbnQgZm9yIGJ5dGVzVG9TdHJpbmciKTsKICB9CiAgY29uc3QgbGVuZ3RoID0gYnl0ZXMubGVuZ3RoOwogIGNvbnN0IE1BWF9BUkdVTUVOVF9DT1VOVCA9IDgxOTI7CiAgaWYgKGxlbmd0aCA8IE1BWF9BUkdVTUVOVF9DT1VOVCkgewogICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgYnl0ZXMpOwogIH0KICBjb25zdCBzdHJCdWYgPSBbXTsKICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSBNQVhfQVJHVU1FTlRfQ09VTlQpIHsKICAgIGNvbnN0IGNodW5rRW5kID0gTWF0aC5taW4oaSArIE1BWF9BUkdVTUVOVF9DT1VOVCwgbGVuZ3RoKTsKICAgIGNvbnN0IGNodW5rID0gYnl0ZXMuc3ViYXJyYXkoaSwgY2h1bmtFbmQpOwogICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBjaHVuaykpOwogIH0KICByZXR1cm4gc3RyQnVmLmpvaW4oIiIpOwp9CmZ1bmN0aW9uIHN0cmluZ1RvQnl0ZXMoc3RyKSB7CiAgaWYgKHR5cGVvZiBzdHIgIT09ICJzdHJpbmciKSB7CiAgICB1bnJlYWNoYWJsZSgiSW52YWxpZCBhcmd1bWVudCBmb3Igc3RyaW5nVG9CeXRlcyIpOwogIH0KICBjb25zdCBsZW5ndGggPSBzdHIubGVuZ3RoOwogIGNvbnN0IGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoKTsKICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICBieXRlc1tpXSA9IHN0ci5jaGFyQ29kZUF0KGkpICYgMHhmZjsKICB9CiAgcmV0dXJuIGJ5dGVzOwp9CmZ1bmN0aW9uIHN0cmluZzMyKHZhbHVlKSB7CiAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUodmFsdWUgPj4gMjQgJiAweGZmLCB2YWx1ZSA+PiAxNiAmIDB4ZmYsIHZhbHVlID4+IDggJiAweGZmLCB2YWx1ZSAmIDB4ZmYpOwp9CmZ1bmN0aW9uIG9iamVjdFNpemUob2JqKSB7CiAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikubGVuZ3RoOwp9CmZ1bmN0aW9uIG9iamVjdEZyb21NYXAobWFwKSB7CiAgY29uc3Qgb2JqID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBtYXApIHsKICAgIG9ialtrZXldID0gdmFsdWU7CiAgfQogIHJldHVybiBvYmo7Cn0KZnVuY3Rpb24gaXNMaXR0bGVFbmRpYW4oKSB7CiAgY29uc3QgYnVmZmVyOCA9IG5ldyBVaW50OEFycmF5KDQpOwogIGJ1ZmZlcjhbMF0gPSAxOwogIGNvbnN0IHZpZXczMiA9IG5ldyBVaW50MzJBcnJheShidWZmZXI4LmJ1ZmZlciwgMCwgMSk7CiAgcmV0dXJuIHZpZXczMlswXSA9PT0gMTsKfQpmdW5jdGlvbiBpc0V2YWxTdXBwb3J0ZWQoKSB7CiAgdHJ5IHsKICAgIG5ldyBGdW5jdGlvbigiIik7CiAgICByZXR1cm4gdHJ1ZTsKICB9IGNhdGNoIChlKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9CmNsYXNzIEZlYXR1cmVUZXN0IHsKICBzdGF0aWMgZ2V0IGlzTGl0dGxlRW5kaWFuKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiaXNMaXR0bGVFbmRpYW4iLCBpc0xpdHRsZUVuZGlhbigpKTsKICB9CiAgc3RhdGljIGdldCBpc0V2YWxTdXBwb3J0ZWQoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJpc0V2YWxTdXBwb3J0ZWQiLCBpc0V2YWxTdXBwb3J0ZWQoKSk7CiAgfQogIHN0YXRpYyBnZXQgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCIsIHR5cGVvZiBPZmZzY3JlZW5DYW52YXMgIT09ICJ1bmRlZmluZWQiKTsKICB9CiAgc3RhdGljIGdldCBwbGF0Zm9ybSgpIHsKICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yID09PSAidW5kZWZpbmVkIikgewogICAgICByZXR1cm4gc2hhZG93KHRoaXMsICJwbGF0Zm9ybSIsIHsKICAgICAgICBpc1dpbjogZmFsc2UsCiAgICAgICAgaXNNYWM6IGZhbHNlCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAicGxhdGZvcm0iLCB7CiAgICAgIGlzV2luOiBuYXZpZ2F0b3IucGxhdGZvcm0uaW5jbHVkZXMoIldpbiIpLAogICAgICBpc01hYzogbmF2aWdhdG9yLnBsYXRmb3JtLmluY2x1ZGVzKCJNYWMiKQogICAgfSk7CiAgfQp9CmV4cG9ydHMuRmVhdHVyZVRlc3QgPSBGZWF0dXJlVGVzdDsKY29uc3QgaGV4TnVtYmVycyA9IFsuLi5BcnJheSgyNTYpLmtleXMoKV0ubWFwKG4gPT4gbi50b1N0cmluZygxNikucGFkU3RhcnQoMiwgIjAiKSk7CmNsYXNzIFV0aWwgewogIHN0YXRpYyBtYWtlSGV4Q29sb3IociwgZywgYikgewogICAgcmV0dXJuIGAjJHtoZXhOdW1iZXJzW3JdfSR7aGV4TnVtYmVyc1tnXX0ke2hleE51bWJlcnNbYl19YDsKICB9CiAgc3RhdGljIHNjYWxlTWluTWF4KHRyYW5zZm9ybSwgbWluTWF4KSB7CiAgICBsZXQgdGVtcDsKICAgIGlmICh0cmFuc2Zvcm1bMF0pIHsKICAgICAgaWYgKHRyYW5zZm9ybVswXSA8IDApIHsKICAgICAgICB0ZW1wID0gbWluTWF4WzBdOwogICAgICAgIG1pbk1heFswXSA9IG1pbk1heFsxXTsKICAgICAgICBtaW5NYXhbMV0gPSB0ZW1wOwogICAgICB9CiAgICAgIG1pbk1heFswXSAqPSB0cmFuc2Zvcm1bMF07CiAgICAgIG1pbk1heFsxXSAqPSB0cmFuc2Zvcm1bMF07CiAgICAgIGlmICh0cmFuc2Zvcm1bM10gPCAwKSB7CiAgICAgICAgdGVtcCA9IG1pbk1heFsyXTsKICAgICAgICBtaW5NYXhbMl0gPSBtaW5NYXhbM107CiAgICAgICAgbWluTWF4WzNdID0gdGVtcDsKICAgICAgfQogICAgICBtaW5NYXhbMl0gKj0gdHJhbnNmb3JtWzNdOwogICAgICBtaW5NYXhbM10gKj0gdHJhbnNmb3JtWzNdOwogICAgfSBlbHNlIHsKICAgICAgdGVtcCA9IG1pbk1heFswXTsKICAgICAgbWluTWF4WzBdID0gbWluTWF4WzJdOwogICAgICBtaW5NYXhbMl0gPSB0ZW1wOwogICAgICB0ZW1wID0gbWluTWF4WzFdOwogICAgICBtaW5NYXhbMV0gPSBtaW5NYXhbM107CiAgICAgIG1pbk1heFszXSA9IHRlbXA7CiAgICAgIGlmICh0cmFuc2Zvcm1bMV0gPCAwKSB7CiAgICAgICAgdGVtcCA9IG1pbk1heFsyXTsKICAgICAgICBtaW5NYXhbMl0gPSBtaW5NYXhbM107CiAgICAgICAgbWluTWF4WzNdID0gdGVtcDsKICAgICAgfQogICAgICBtaW5NYXhbMl0gKj0gdHJhbnNmb3JtWzFdOwogICAgICBtaW5NYXhbM10gKj0gdHJhbnNmb3JtWzFdOwogICAgICBpZiAodHJhbnNmb3JtWzJdIDwgMCkgewogICAgICAgIHRlbXAgPSBtaW5NYXhbMF07CiAgICAgICAgbWluTWF4WzBdID0gbWluTWF4WzFdOwogICAgICAgIG1pbk1heFsxXSA9IHRlbXA7CiAgICAgIH0KICAgICAgbWluTWF4WzBdICo9IHRyYW5zZm9ybVsyXTsKICAgICAgbWluTWF4WzFdICo9IHRyYW5zZm9ybVsyXTsKICAgIH0KICAgIG1pbk1heFswXSArPSB0cmFuc2Zvcm1bNF07CiAgICBtaW5NYXhbMV0gKz0gdHJhbnNmb3JtWzRdOwogICAgbWluTWF4WzJdICs9IHRyYW5zZm9ybVs1XTsKICAgIG1pbk1heFszXSArPSB0cmFuc2Zvcm1bNV07CiAgfQogIHN0YXRpYyB0cmFuc2Zvcm0obTEsIG0yKSB7CiAgICByZXR1cm4gW20xWzBdICogbTJbMF0gKyBtMVsyXSAqIG0yWzFdLCBtMVsxXSAqIG0yWzBdICsgbTFbM10gKiBtMlsxXSwgbTFbMF0gKiBtMlsyXSArIG0xWzJdICogbTJbM10sIG0xWzFdICogbTJbMl0gKyBtMVszXSAqIG0yWzNdLCBtMVswXSAqIG0yWzRdICsgbTFbMl0gKiBtMls1XSArIG0xWzRdLCBtMVsxXSAqIG0yWzRdICsgbTFbM10gKiBtMls1XSArIG0xWzVdXTsKICB9CiAgc3RhdGljIGFwcGx5VHJhbnNmb3JtKHAsIG0pIHsKICAgIGNvbnN0IHh0ID0gcFswXSAqIG1bMF0gKyBwWzFdICogbVsyXSArIG1bNF07CiAgICBjb25zdCB5dCA9IHBbMF0gKiBtWzFdICsgcFsxXSAqIG1bM10gKyBtWzVdOwogICAgcmV0dXJuIFt4dCwgeXRdOwogIH0KICBzdGF0aWMgYXBwbHlJbnZlcnNlVHJhbnNmb3JtKHAsIG0pIHsKICAgIGNvbnN0IGQgPSBtWzBdICogbVszXSAtIG1bMV0gKiBtWzJdOwogICAgY29uc3QgeHQgPSAocFswXSAqIG1bM10gLSBwWzFdICogbVsyXSArIG1bMl0gKiBtWzVdIC0gbVs0XSAqIG1bM10pIC8gZDsKICAgIGNvbnN0IHl0ID0gKC1wWzBdICogbVsxXSArIHBbMV0gKiBtWzBdICsgbVs0XSAqIG1bMV0gLSBtWzVdICogbVswXSkgLyBkOwogICAgcmV0dXJuIFt4dCwgeXRdOwogIH0KICBzdGF0aWMgZ2V0QXhpYWxBbGlnbmVkQm91bmRpbmdCb3gociwgbSkgewogICAgY29uc3QgcDEgPSBVdGlsLmFwcGx5VHJhbnNmb3JtKHIsIG0pOwogICAgY29uc3QgcDIgPSBVdGlsLmFwcGx5VHJhbnNmb3JtKHIuc2xpY2UoMiwgNCksIG0pOwogICAgY29uc3QgcDMgPSBVdGlsLmFwcGx5VHJhbnNmb3JtKFtyWzBdLCByWzNdXSwgbSk7CiAgICBjb25zdCBwNCA9IFV0aWwuYXBwbHlUcmFuc2Zvcm0oW3JbMl0sIHJbMV1dLCBtKTsKICAgIHJldHVybiBbTWF0aC5taW4ocDFbMF0sIHAyWzBdLCBwM1swXSwgcDRbMF0pLCBNYXRoLm1pbihwMVsxXSwgcDJbMV0sIHAzWzFdLCBwNFsxXSksIE1hdGgubWF4KHAxWzBdLCBwMlswXSwgcDNbMF0sIHA0WzBdKSwgTWF0aC5tYXgocDFbMV0sIHAyWzFdLCBwM1sxXSwgcDRbMV0pXTsKICB9CiAgc3RhdGljIGludmVyc2VUcmFuc2Zvcm0obSkgewogICAgY29uc3QgZCA9IG1bMF0gKiBtWzNdIC0gbVsxXSAqIG1bMl07CiAgICByZXR1cm4gW21bM10gLyBkLCAtbVsxXSAvIGQsIC1tWzJdIC8gZCwgbVswXSAvIGQsIChtWzJdICogbVs1XSAtIG1bNF0gKiBtWzNdKSAvIGQsIChtWzRdICogbVsxXSAtIG1bNV0gKiBtWzBdKSAvIGRdOwogIH0KICBzdGF0aWMgc2luZ3VsYXJWYWx1ZURlY29tcG9zZTJkU2NhbGUobSkgewogICAgY29uc3QgdHJhbnNwb3NlID0gW21bMF0sIG1bMl0sIG1bMV0sIG1bM11dOwogICAgY29uc3QgYSA9IG1bMF0gKiB0cmFuc3Bvc2VbMF0gKyBtWzFdICogdHJhbnNwb3NlWzJdOwogICAgY29uc3QgYiA9IG1bMF0gKiB0cmFuc3Bvc2VbMV0gKyBtWzFdICogdHJhbnNwb3NlWzNdOwogICAgY29uc3QgYyA9IG1bMl0gKiB0cmFuc3Bvc2VbMF0gKyBtWzNdICogdHJhbnNwb3NlWzJdOwogICAgY29uc3QgZCA9IG1bMl0gKiB0cmFuc3Bvc2VbMV0gKyBtWzNdICogdHJhbnNwb3NlWzNdOwogICAgY29uc3QgZmlyc3QgPSAoYSArIGQpIC8gMjsKICAgIGNvbnN0IHNlY29uZCA9IE1hdGguc3FydCgoYSArIGQpICoqIDIgLSA0ICogKGEgKiBkIC0gYyAqIGIpKSAvIDI7CiAgICBjb25zdCBzeCA9IGZpcnN0ICsgc2Vjb25kIHx8IDE7CiAgICBjb25zdCBzeSA9IGZpcnN0IC0gc2Vjb25kIHx8IDE7CiAgICByZXR1cm4gW01hdGguc3FydChzeCksIE1hdGguc3FydChzeSldOwogIH0KICBzdGF0aWMgbm9ybWFsaXplUmVjdChyZWN0KSB7CiAgICBjb25zdCByID0gcmVjdC5zbGljZSgwKTsKICAgIGlmIChyZWN0WzBdID4gcmVjdFsyXSkgewogICAgICByWzBdID0gcmVjdFsyXTsKICAgICAgclsyXSA9IHJlY3RbMF07CiAgICB9CiAgICBpZiAocmVjdFsxXSA+IHJlY3RbM10pIHsKICAgICAgclsxXSA9IHJlY3RbM107CiAgICAgIHJbM10gPSByZWN0WzFdOwogICAgfQogICAgcmV0dXJuIHI7CiAgfQogIHN0YXRpYyBpbnRlcnNlY3QocmVjdDEsIHJlY3QyKSB7CiAgICBjb25zdCB4TG93ID0gTWF0aC5tYXgoTWF0aC5taW4ocmVjdDFbMF0sIHJlY3QxWzJdKSwgTWF0aC5taW4ocmVjdDJbMF0sIHJlY3QyWzJdKSk7CiAgICBjb25zdCB4SGlnaCA9IE1hdGgubWluKE1hdGgubWF4KHJlY3QxWzBdLCByZWN0MVsyXSksIE1hdGgubWF4KHJlY3QyWzBdLCByZWN0MlsyXSkpOwogICAgaWYgKHhMb3cgPiB4SGlnaCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHlMb3cgPSBNYXRoLm1heChNYXRoLm1pbihyZWN0MVsxXSwgcmVjdDFbM10pLCBNYXRoLm1pbihyZWN0MlsxXSwgcmVjdDJbM10pKTsKICAgIGNvbnN0IHlIaWdoID0gTWF0aC5taW4oTWF0aC5tYXgocmVjdDFbMV0sIHJlY3QxWzNdKSwgTWF0aC5tYXgocmVjdDJbMV0sIHJlY3QyWzNdKSk7CiAgICBpZiAoeUxvdyA+IHlIaWdoKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgcmV0dXJuIFt4TG93LCB5TG93LCB4SGlnaCwgeUhpZ2hdOwogIH0KICBzdGF0aWMgYmV6aWVyQm91bmRpbmdCb3goeDAsIHkwLCB4MSwgeTEsIHgyLCB5MiwgeDMsIHkzKSB7CiAgICBjb25zdCB0dmFsdWVzID0gW10sCiAgICAgIGJvdW5kcyA9IFtbXSwgW11dOwogICAgbGV0IGEsIGIsIGMsIHQsIHQxLCB0MiwgYjJhYywgc3FydGIyYWM7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI7ICsraSkgewogICAgICBpZiAoaSA9PT0gMCkgewogICAgICAgIGIgPSA2ICogeDAgLSAxMiAqIHgxICsgNiAqIHgyOwogICAgICAgIGEgPSAtMyAqIHgwICsgOSAqIHgxIC0gOSAqIHgyICsgMyAqIHgzOwogICAgICAgIGMgPSAzICogeDEgLSAzICogeDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYiA9IDYgKiB5MCAtIDEyICogeTEgKyA2ICogeTI7CiAgICAgICAgYSA9IC0zICogeTAgKyA5ICogeTEgLSA5ICogeTIgKyAzICogeTM7CiAgICAgICAgYyA9IDMgKiB5MSAtIDMgKiB5MDsKICAgICAgfQogICAgICBpZiAoTWF0aC5hYnMoYSkgPCAxZS0xMikgewogICAgICAgIGlmIChNYXRoLmFicyhiKSA8IDFlLTEyKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgdCA9IC1jIC8gYjsKICAgICAgICBpZiAoMCA8IHQgJiYgdCA8IDEpIHsKICAgICAgICAgIHR2YWx1ZXMucHVzaCh0KTsKICAgICAgICB9CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgYjJhYyA9IGIgKiBiIC0gNCAqIGMgKiBhOwogICAgICBzcXJ0YjJhYyA9IE1hdGguc3FydChiMmFjKTsKICAgICAgaWYgKGIyYWMgPCAwKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgdDEgPSAoLWIgKyBzcXJ0YjJhYykgLyAoMiAqIGEpOwogICAgICBpZiAoMCA8IHQxICYmIHQxIDwgMSkgewogICAgICAgIHR2YWx1ZXMucHVzaCh0MSk7CiAgICAgIH0KICAgICAgdDIgPSAoLWIgLSBzcXJ0YjJhYykgLyAoMiAqIGEpOwogICAgICBpZiAoMCA8IHQyICYmIHQyIDwgMSkgewogICAgICAgIHR2YWx1ZXMucHVzaCh0Mik7CiAgICAgIH0KICAgIH0KICAgIGxldCBqID0gdHZhbHVlcy5sZW5ndGgsCiAgICAgIG10OwogICAgY29uc3QgamxlbiA9IGo7CiAgICB3aGlsZSAoai0tKSB7CiAgICAgIHQgPSB0dmFsdWVzW2pdOwogICAgICBtdCA9IDEgLSB0OwogICAgICBib3VuZHNbMF1bal0gPSBtdCAqIG10ICogbXQgKiB4MCArIDMgKiBtdCAqIG10ICogdCAqIHgxICsgMyAqIG10ICogdCAqIHQgKiB4MiArIHQgKiB0ICogdCAqIHgzOwogICAgICBib3VuZHNbMV1bal0gPSBtdCAqIG10ICogbXQgKiB5MCArIDMgKiBtdCAqIG10ICogdCAqIHkxICsgMyAqIG10ICogdCAqIHQgKiB5MiArIHQgKiB0ICogdCAqIHkzOwogICAgfQogICAgYm91bmRzWzBdW2psZW5dID0geDA7CiAgICBib3VuZHNbMV1bamxlbl0gPSB5MDsKICAgIGJvdW5kc1swXVtqbGVuICsgMV0gPSB4MzsKICAgIGJvdW5kc1sxXVtqbGVuICsgMV0gPSB5MzsKICAgIGJvdW5kc1swXS5sZW5ndGggPSBib3VuZHNbMV0ubGVuZ3RoID0gamxlbiArIDI7CiAgICByZXR1cm4gW01hdGgubWluKC4uLmJvdW5kc1swXSksIE1hdGgubWluKC4uLmJvdW5kc1sxXSksIE1hdGgubWF4KC4uLmJvdW5kc1swXSksIE1hdGgubWF4KC4uLmJvdW5kc1sxXSldOwogIH0KfQpleHBvcnRzLlV0aWwgPSBVdGlsOwpjb25zdCBQREZTdHJpbmdUcmFuc2xhdGVUYWJsZSA9IFswLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAweDJkOCwgMHgyYzcsIDB4MmM2LCAweDJkOSwgMHgyZGQsIDB4MmRiLCAweDJkYSwgMHgyZGMsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDB4MjAyMiwgMHgyMDIwLCAweDIwMjEsIDB4MjAyNiwgMHgyMDE0LCAweDIwMTMsIDB4MTkyLCAweDIwNDQsIDB4MjAzOSwgMHgyMDNhLCAweDIyMTIsIDB4MjAzMCwgMHgyMDFlLCAweDIwMWMsIDB4MjAxZCwgMHgyMDE4LCAweDIwMTksIDB4MjAxYSwgMHgyMTIyLCAweGZiMDEsIDB4ZmIwMiwgMHgxNDEsIDB4MTUyLCAweDE2MCwgMHgxNzgsIDB4MTdkLCAweDEzMSwgMHgxNDIsIDB4MTUzLCAweDE2MSwgMHgxN2UsIDAsIDB4MjBhY107CmZ1bmN0aW9uIHN0cmluZ1RvUERGU3RyaW5nKHN0cikgewogIGlmIChzdHJbMF0gPj0gIlx4RUYiKSB7CiAgICBsZXQgZW5jb2Rpbmc7CiAgICBpZiAoc3RyWzBdID09PSAiXHhGRSIgJiYgc3RyWzFdID09PSAiXHhGRiIpIHsKICAgICAgZW5jb2RpbmcgPSAidXRmLTE2YmUiOwogICAgfSBlbHNlIGlmIChzdHJbMF0gPT09ICJceEZGIiAmJiBzdHJbMV0gPT09ICJceEZFIikgewogICAgICBlbmNvZGluZyA9ICJ1dGYtMTZsZSI7CiAgICB9IGVsc2UgaWYgKHN0clswXSA9PT0gIlx4RUYiICYmIHN0clsxXSA9PT0gIlx4QkIiICYmIHN0clsyXSA9PT0gIlx4QkYiKSB7CiAgICAgIGVuY29kaW5nID0gInV0Zi04IjsKICAgIH0KICAgIGlmIChlbmNvZGluZykgewogICAgICB0cnkgewogICAgICAgIGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoZW5jb2RpbmcsIHsKICAgICAgICAgIGZhdGFsOiB0cnVlCiAgICAgICAgfSk7CiAgICAgICAgY29uc3QgYnVmZmVyID0gc3RyaW5nVG9CeXRlcyhzdHIpOwogICAgICAgIHJldHVybiBkZWNvZGVyLmRlY29kZShidWZmZXIpOwogICAgICB9IGNhdGNoIChleCkgewogICAgICAgIHdhcm4oYHN0cmluZ1RvUERGU3RyaW5nOiAiJHtleH0iLmApOwogICAgICB9CiAgICB9CiAgfQogIGNvbnN0IHN0ckJ1ZiA9IFtdOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IHN0ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCBjb2RlID0gUERGU3RyaW5nVHJhbnNsYXRlVGFibGVbc3RyLmNoYXJDb2RlQXQoaSldOwogICAgc3RyQnVmLnB1c2goY29kZSA/IFN0cmluZy5mcm9tQ2hhckNvZGUoY29kZSkgOiBzdHIuY2hhckF0KGkpKTsKICB9CiAgcmV0dXJuIHN0ckJ1Zi5qb2luKCIiKTsKfQpmdW5jdGlvbiBzdHJpbmdUb1VURjhTdHJpbmcoc3RyKSB7CiAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChlc2NhcGUoc3RyKSk7Cn0KZnVuY3Rpb24gdXRmOFN0cmluZ1RvU3RyaW5nKHN0cikgewogIHJldHVybiB1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoc3RyKSk7Cn0KZnVuY3Rpb24gaXNBcnJheUJ1ZmZlcih2KSB7CiAgcmV0dXJuIHR5cGVvZiB2ID09PSAib2JqZWN0IiAmJiB2ICE9PSBudWxsICYmIHYuYnl0ZUxlbmd0aCAhPT0gdW5kZWZpbmVkOwp9CmZ1bmN0aW9uIGlzQXJyYXlFcXVhbChhcnIxLCBhcnIyKSB7CiAgaWYgKGFycjEubGVuZ3RoICE9PSBhcnIyLmxlbmd0aCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBmb3IgKGxldCBpID0gMCwgaWkgPSBhcnIxLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGlmIChhcnIxW2ldICE9PSBhcnIyW2ldKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9CiAgcmV0dXJuIHRydWU7Cn0KZnVuY3Rpb24gZ2V0TW9kaWZpY2F0aW9uRGF0ZSgpIHsKICBsZXQgZGF0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbmV3IERhdGUoKTsKICBjb25zdCBidWZmZXIgPSBbZGF0ZS5nZXRVVENGdWxsWWVhcigpLnRvU3RyaW5nKCksIChkYXRlLmdldFVUQ01vbnRoKCkgKyAxKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIiksIGRhdGUuZ2V0VVRDRGF0ZSgpLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgIjAiKSwgZGF0ZS5nZXRVVENIb3VycygpLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgIjAiKSwgZGF0ZS5nZXRVVENNaW51dGVzKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAiMCIpLCBkYXRlLmdldFVUQ1NlY29uZHMoKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIildOwogIHJldHVybiBidWZmZXIuam9pbigiIik7Cn0KZnVuY3Rpb24gY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkoKSB7CiAgY29uc3QgY2FwYWJpbGl0eSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgbGV0IGlzU2V0dGxlZCA9IGZhbHNlOwogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjYXBhYmlsaXR5LCAic2V0dGxlZCIsIHsKICAgIGdldCgpIHsKICAgICAgcmV0dXJuIGlzU2V0dGxlZDsKICAgIH0KICB9KTsKICBjYXBhYmlsaXR5LnByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7CiAgICBjYXBhYmlsaXR5LnJlc29sdmUgPSBmdW5jdGlvbiAoZGF0YSkgewogICAgICBpc1NldHRsZWQgPSB0cnVlOwogICAgICByZXNvbHZlKGRhdGEpOwogICAgfTsKICAgIGNhcGFiaWxpdHkucmVqZWN0ID0gZnVuY3Rpb24gKHJlYXNvbikgewogICAgICBpc1NldHRsZWQgPSB0cnVlOwogICAgICByZWplY3QocmVhc29uKTsKICAgIH07CiAgfSk7CiAgcmV0dXJuIGNhcGFiaWxpdHk7Cn0KCi8qKiovIH0pLAovKiAzICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCnZhciBfaXNfbm9kZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNCk7CihmdW5jdGlvbiBjaGVja0RPTU1hdHJpeCgpIHsKICBpZiAoZ2xvYmFsVGhpcy5ET01NYXRyaXggfHwgIV9pc19ub2RlLmlzTm9kZUpTKSB7CiAgICByZXR1cm47CiAgfQogIGdsb2JhbFRoaXMuRE9NTWF0cml4ID0gcmVxdWlyZSgiY2FudmFzIikuRE9NTWF0cml4Owp9KSgpOwooZnVuY3Rpb24gY2hlY2tQYXRoMkQoKSB7CiAgaWYgKGdsb2JhbFRoaXMuUGF0aDJEIHx8ICFfaXNfbm9kZS5pc05vZGVKUykgewogICAgcmV0dXJuOwogIH0KICBjb25zdCB7CiAgICBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQKICB9ID0gcmVxdWlyZSgiY2FudmFzIik7CiAgY29uc3QgewogICAgcG9seWZpbGxQYXRoMkQKICB9ID0gcmVxdWlyZSgicGF0aDJkLXBvbHlmaWxsIik7CiAgZ2xvYmFsVGhpcy5DYW52YXNSZW5kZXJpbmdDb250ZXh0MkQgPSBDYW52YXNSZW5kZXJpbmdDb250ZXh0MkQ7CiAgcG9seWZpbGxQYXRoMkQoZ2xvYmFsVGhpcyk7Cn0pKCk7CihmdW5jdGlvbiBjaGVja1JlYWRhYmxlU3RyZWFtKCkgewogIGlmIChnbG9iYWxUaGlzLlJlYWRhYmxlU3RyZWFtIHx8ICFfaXNfbm9kZS5pc05vZGVKUykgewogICAgcmV0dXJuOwogIH0KICBnbG9iYWxUaGlzLlJlYWRhYmxlU3RyZWFtID0gcmVxdWlyZSgid2ViLXN0cmVhbXMtcG9seWZpbGwvZGlzdC9wb255ZmlsbC5qcyIpLlJlYWRhYmxlU3RyZWFtOwp9KSgpOwooZnVuY3Rpb24gY2hlY2tBcnJheUF0KCkgewogIGlmIChBcnJheS5wcm90b3R5cGUuYXQpIHsKICAgIHJldHVybjsKICB9CiAgX193X3BkZmpzX3JlcXVpcmVfXyg1KTsKfSkoKTsKKGZ1bmN0aW9uIGNoZWNrVHlwZWRBcnJheUF0KCkgewogIGlmIChVaW50OEFycmF5LnByb3RvdHlwZS5hdCkgewogICAgcmV0dXJuOwogIH0KICBfX3dfcGRmanNfcmVxdWlyZV9fKDc5KTsKfSkoKTsKKGZ1bmN0aW9uIGNoZWNrU3RydWN0dXJlZENsb25lKCkgewogIGlmIChnbG9iYWxUaGlzLnN0cnVjdHVyZWRDbG9uZSkgewogICAgcmV0dXJuOwogIH0KICBfX3dfcGRmanNfcmVxdWlyZV9fKDkxKTsKfSkoKTsKCi8qKiovIH0pLAovKiA0ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMpID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5pc05vZGVKUyA9IHZvaWQgMDsKY29uc3QgaXNOb2RlSlMgPSB0eXBlb2YgcHJvY2VzcyA9PT0gIm9iamVjdCIgJiYgcHJvY2VzcyArICIiID09PSAiW29iamVjdCBwcm9jZXNzXSIgJiYgIXByb2Nlc3MudmVyc2lvbnMubncgJiYgIShwcm9jZXNzLnZlcnNpb25zLmVsZWN0cm9uICYmIHByb2Nlc3MudHlwZSAmJiBwcm9jZXNzLnR5cGUgIT09ICJicm93c2VyIik7CmV4cG9ydHMuaXNOb2RlSlMgPSBpc05vZGVKUzsKCi8qKiovIH0pLAovKiA1ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCl9fd19wZGZqc19yZXF1aXJlX18oNik7CnZhciBlbnRyeVVuYmluZCA9IF9fd19wZGZqc19yZXF1aXJlX18oNzgpOwptb2R1bGUuZXhwb3J0cyA9IGVudHJ5VW5iaW5kKCdBcnJheScsICdhdCcpOwoKLyoqKi8gfSksCi8qIDYgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7Cgp2YXIgJCA9IF9fd19wZGZqc19yZXF1aXJlX18oNyk7CnZhciB0b09iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oNDQpOwp2YXIgbGVuZ3RoT2ZBcnJheUxpa2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDY4KTsKdmFyIHRvSW50ZWdlck9ySW5maW5pdHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDY2KTsKdmFyIGFkZFRvVW5zY29wYWJsZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDczKTsKJCh7CiB0YXJnZXQ6ICdBcnJheScsCiBwcm90bzogdHJ1ZQp9LCB7CiBhdDogZnVuY3Rpb24gYXQoaW5kZXgpIHsKICB2YXIgTyA9IHRvT2JqZWN0KHRoaXMpOwogIHZhciBsZW4gPSBsZW5ndGhPZkFycmF5TGlrZShPKTsKICB2YXIgcmVsYXRpdmVJbmRleCA9IHRvSW50ZWdlck9ySW5maW5pdHkoaW5kZXgpOwogIHZhciBrID0gcmVsYXRpdmVJbmRleCA+PSAwID8gcmVsYXRpdmVJbmRleCA6IGxlbiArIHJlbGF0aXZlSW5kZXg7CiAgcmV0dXJuIGsgPCAwIHx8IGsgPj0gbGVuID8gdW5kZWZpbmVkIDogT1trXTsKIH0KfSk7CmFkZFRvVW5zY29wYWJsZXMoJ2F0Jyk7CgovKioqLyB9KSwKLyogNyAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgZ2xvYmFsID0gX193X3BkZmpzX3JlcXVpcmVfXyg4KTsKdmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvciA9IChfX3dfcGRmanNfcmVxdWlyZV9fKDkpLmYpOwp2YXIgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5ID0gX193X3BkZmpzX3JlcXVpcmVfXyg0OCk7CnZhciBkZWZpbmVCdWlsdEluID0gX193X3BkZmpzX3JlcXVpcmVfXyg1Mik7CnZhciBkZWZpbmVHbG9iYWxQcm9wZXJ0eSA9IF9fd19wZGZqc19yZXF1aXJlX18oNDIpOwp2YXIgY29weUNvbnN0cnVjdG9yUHJvcGVydGllcyA9IF9fd19wZGZqc19yZXF1aXJlX18oNjApOwp2YXIgaXNGb3JjZWQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDcyKTsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob3B0aW9ucywgc291cmNlKSB7CiB2YXIgVEFSR0VUID0gb3B0aW9ucy50YXJnZXQ7CiB2YXIgR0xPQkFMID0gb3B0aW9ucy5nbG9iYWw7CiB2YXIgU1RBVElDID0gb3B0aW9ucy5zdGF0OwogdmFyIEZPUkNFRCwgdGFyZ2V0LCBrZXksIHRhcmdldFByb3BlcnR5LCBzb3VyY2VQcm9wZXJ0eSwgZGVzY3JpcHRvcjsKIGlmIChHTE9CQUwpIHsKICB0YXJnZXQgPSBnbG9iYWw7CiB9IGVsc2UgaWYgKFNUQVRJQykgewogIHRhcmdldCA9IGdsb2JhbFtUQVJHRVRdIHx8IGRlZmluZUdsb2JhbFByb3BlcnR5KFRBUkdFVCwge30pOwogfSBlbHNlIHsKICB0YXJnZXQgPSAoZ2xvYmFsW1RBUkdFVF0gfHwge30pLnByb3RvdHlwZTsKIH0KIGlmICh0YXJnZXQpCiAgZm9yIChrZXkgaW4gc291cmNlKSB7CiAgIHNvdXJjZVByb3BlcnR5ID0gc291cmNlW2tleV07CiAgIGlmIChvcHRpb25zLmRvbnRDYWxsR2V0U2V0KSB7CiAgICBkZXNjcmlwdG9yID0gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KTsKICAgIHRhcmdldFByb3BlcnR5ID0gZGVzY3JpcHRvciAmJiBkZXNjcmlwdG9yLnZhbHVlOwogICB9IGVsc2UKICAgIHRhcmdldFByb3BlcnR5ID0gdGFyZ2V0W2tleV07CiAgIEZPUkNFRCA9IGlzRm9yY2VkKEdMT0JBTCA/IGtleSA6IFRBUkdFVCArIChTVEFUSUMgPyAnLicgOiAnIycpICsga2V5LCBvcHRpb25zLmZvcmNlZCk7CiAgIGlmICghRk9SQ0VEICYmIHRhcmdldFByb3BlcnR5ICE9PSB1bmRlZmluZWQpIHsKICAgIGlmICh0eXBlb2Ygc291cmNlUHJvcGVydHkgPT0gdHlwZW9mIHRhcmdldFByb3BlcnR5KQogICAgIGNvbnRpbnVlOwogICAgY29weUNvbnN0cnVjdG9yUHJvcGVydGllcyhzb3VyY2VQcm9wZXJ0eSwgdGFyZ2V0UHJvcGVydHkpOwogICB9CiAgIGlmIChvcHRpb25zLnNoYW0gfHwgdGFyZ2V0UHJvcGVydHkgJiYgdGFyZ2V0UHJvcGVydHkuc2hhbSkgewogICAgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KHNvdXJjZVByb3BlcnR5LCAnc2hhbScsIHRydWUpOwogICB9CiAgIGRlZmluZUJ1aWx0SW4odGFyZ2V0LCBrZXksIHNvdXJjZVByb3BlcnR5LCBvcHRpb25zKTsKICB9Cn07CgovKioqLyB9KSwKLyogOCAqLwovKioqLyAoKG1vZHVsZSkgPT4gewoKdmFyIGNoZWNrID0gZnVuY3Rpb24gKGl0KSB7CiByZXR1cm4gaXQgJiYgaXQuTWF0aCA9PSBNYXRoICYmIGl0Owp9Owptb2R1bGUuZXhwb3J0cyA9IGNoZWNrKHR5cGVvZiBnbG9iYWxUaGlzID09ICdvYmplY3QnICYmIGdsb2JhbFRoaXMpIHx8IGNoZWNrKHR5cGVvZiB3aW5kb3cgPT0gJ29iamVjdCcgJiYgd2luZG93KSB8fCBjaGVjayh0eXBlb2Ygc2VsZiA9PSAnb2JqZWN0JyAmJiBzZWxmKSB8fCBjaGVjayh0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbCkgfHwgKGZ1bmN0aW9uICgpIHsKIHJldHVybiB0aGlzOwp9KCkpIHx8IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7CgovKioqLyB9KSwKLyogOSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgREVTQ1JJUFRPUlMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwKTsKdmFyIGNhbGwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyKTsKdmFyIHByb3BlcnR5SXNFbnVtZXJhYmxlTW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXygxNCk7CnZhciBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1KTsKdmFyIHRvSW5kZXhlZE9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTYpOwp2YXIgdG9Qcm9wZXJ0eUtleSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjIpOwp2YXIgaGFzT3duID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Myk7CnZhciBJRThfRE9NX0RFRklORSA9IF9fd19wZGZqc19yZXF1aXJlX18oNDYpOwp2YXIgJGdldE93blByb3BlcnR5RGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7CmV4cG9ydHMuZiA9IERFU0NSSVBUT1JTID8gJGdldE93blByb3BlcnR5RGVzY3JpcHRvciA6IGZ1bmN0aW9uIGdldE93blByb3BlcnR5RGVzY3JpcHRvcihPLCBQKSB7CiBPID0gdG9JbmRleGVkT2JqZWN0KE8pOwogUCA9IHRvUHJvcGVydHlLZXkoUCk7CiBpZiAoSUU4X0RPTV9ERUZJTkUpCiAgdHJ5IHsKICAgcmV0dXJuICRnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoTywgUCk7CiAgfSBjYXRjaCAoZXJyb3IpIHsKICB9CiBpZiAoaGFzT3duKE8sIFApKQogIHJldHVybiBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IoIWNhbGwocHJvcGVydHlJc0VudW1lcmFibGVNb2R1bGUuZiwgTywgUCksIE9bUF0pOwp9OwoKLyoqKi8gfSksCi8qIDEwICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEpOwptb2R1bGUuZXhwb3J0cyA9ICFmYWlscyhmdW5jdGlvbiAoKSB7CiByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCAxLCB7CiAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgIHJldHVybiA3OwogIH0KIH0pWzFdICE9IDc7Cn0pOwoKLyoqKi8gfSksCi8qIDExICovCi8qKiovICgobW9kdWxlKSA9PiB7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChleGVjKSB7CiB0cnkgewogIHJldHVybiAhIWV4ZWMoKTsKIH0gY2F0Y2ggKGVycm9yKSB7CiAgcmV0dXJuIHRydWU7CiB9Cn07CgovKioqLyB9KSwKLyogMTIgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIE5BVElWRV9CSU5EID0gX193X3BkZmpzX3JlcXVpcmVfXygxMyk7CnZhciBjYWxsID0gRnVuY3Rpb24ucHJvdG90eXBlLmNhbGw7Cm1vZHVsZS5leHBvcnRzID0gTkFUSVZFX0JJTkQgPyBjYWxsLmJpbmQoY2FsbCkgOiBmdW5jdGlvbiAoKSB7CiByZXR1cm4gY2FsbC5hcHBseShjYWxsLCBhcmd1bWVudHMpOwp9OwoKLyoqKi8gfSksCi8qIDEzICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEpOwptb2R1bGUuZXhwb3J0cyA9ICFmYWlscyhmdW5jdGlvbiAoKSB7CiB2YXIgdGVzdCA9IGZ1bmN0aW9uICgpIHsKIH0uYmluZCgpOwogcmV0dXJuIHR5cGVvZiB0ZXN0ICE9ICdmdW5jdGlvbicgfHwgdGVzdC5oYXNPd25Qcm9wZXJ0eSgncHJvdG90eXBlJyk7Cn0pOwoKLyoqKi8gfSksCi8qIDE0ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMpID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCnZhciAkcHJvcGVydHlJc0VudW1lcmFibGUgPSB7fS5wcm9wZXJ0eUlzRW51bWVyYWJsZTsKdmFyIGdldE93blByb3BlcnR5RGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7CnZhciBOQVNIT1JOX0JVRyA9IGdldE93blByb3BlcnR5RGVzY3JpcHRvciAmJiAhJHByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwoeyAxOiAyIH0sIDEpOwpleHBvcnRzLmYgPSBOQVNIT1JOX0JVRyA/IGZ1bmN0aW9uIHByb3BlcnR5SXNFbnVtZXJhYmxlKFYpIHsKIHZhciBkZXNjcmlwdG9yID0gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRoaXMsIFYpOwogcmV0dXJuICEhZGVzY3JpcHRvciAmJiBkZXNjcmlwdG9yLmVudW1lcmFibGU7Cn0gOiAkcHJvcGVydHlJc0VudW1lcmFibGU7CgovKioqLyB9KSwKLyogMTUgKi8KLyoqKi8gKChtb2R1bGUpID0+IHsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGJpdG1hcCwgdmFsdWUpIHsKIHJldHVybiB7CiAgZW51bWVyYWJsZTogIShiaXRtYXAgJiAxKSwKICBjb25maWd1cmFibGU6ICEoYml0bWFwICYgMiksCiAgd3JpdGFibGU6ICEoYml0bWFwICYgNCksCiAgdmFsdWU6IHZhbHVlCiB9Owp9OwoKLyoqKi8gfSksCi8qIDE2ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBJbmRleGVkT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNyk7CnZhciByZXF1aXJlT2JqZWN0Q29lcmNpYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyMCk7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7CiByZXR1cm4gSW5kZXhlZE9iamVjdChyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKGl0KSk7Cn07CgovKioqLyB9KSwKLyogMTcgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxOCk7CnZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEpOwp2YXIgY2xhc3NvZiA9IF9fd19wZGZqc19yZXF1aXJlX18oMTkpOwp2YXIgJE9iamVjdCA9IE9iamVjdDsKdmFyIHNwbGl0ID0gdW5jdXJyeVRoaXMoJycuc3BsaXQpOwptb2R1bGUuZXhwb3J0cyA9IGZhaWxzKGZ1bmN0aW9uICgpIHsKIHJldHVybiAhJE9iamVjdCgneicpLnByb3BlcnR5SXNFbnVtZXJhYmxlKDApOwp9KSA/IGZ1bmN0aW9uIChpdCkgewogcmV0dXJuIGNsYXNzb2YoaXQpID09ICdTdHJpbmcnID8gc3BsaXQoaXQsICcnKSA6ICRPYmplY3QoaXQpOwp9IDogJE9iamVjdDsKCi8qKiovIH0pLAovKiAxOCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgTkFUSVZFX0JJTkQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzKTsKdmFyIEZ1bmN0aW9uUHJvdG90eXBlID0gRnVuY3Rpb24ucHJvdG90eXBlOwp2YXIgY2FsbCA9IEZ1bmN0aW9uUHJvdG90eXBlLmNhbGw7CnZhciB1bmN1cnJ5VGhpc1dpdGhCaW5kID0gTkFUSVZFX0JJTkQgJiYgRnVuY3Rpb25Qcm90b3R5cGUuYmluZC5iaW5kKGNhbGwsIGNhbGwpOwptb2R1bGUuZXhwb3J0cyA9IE5BVElWRV9CSU5EID8gdW5jdXJyeVRoaXNXaXRoQmluZCA6IGZ1bmN0aW9uIChmbikgewogcmV0dXJuIGZ1bmN0aW9uICgpIHsKICByZXR1cm4gY2FsbC5hcHBseShmbiwgYXJndW1lbnRzKTsKIH07Cn07CgovKioqLyB9KSwKLyogMTkgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxOCk7CnZhciB0b1N0cmluZyA9IHVuY3VycnlUaGlzKHt9LnRvU3RyaW5nKTsKdmFyIHN0cmluZ1NsaWNlID0gdW5jdXJyeVRoaXMoJycuc2xpY2UpOwptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkgewogcmV0dXJuIHN0cmluZ1NsaWNlKHRvU3RyaW5nKGl0KSwgOCwgLTEpOwp9OwoKLyoqKi8gfSksCi8qIDIwICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBpc051bGxPclVuZGVmaW5lZCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjEpOwp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKIGlmIChpc051bGxPclVuZGVmaW5lZChpdCkpCiAgdGhyb3cgJFR5cGVFcnJvcigiQ2FuJ3QgY2FsbCBtZXRob2Qgb24gIiArIGl0KTsKIHJldHVybiBpdDsKfTsKCi8qKiovIH0pLAovKiAyMSAqLwovKioqLyAoKG1vZHVsZSkgPT4gewoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKIHJldHVybiBpdCA9PT0gbnVsbCB8fCBpdCA9PT0gdW5kZWZpbmVkOwp9OwoKLyoqKi8gfSksCi8qIDIyICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciB0b1ByaW1pdGl2ZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjMpOwp2YXIgaXNTeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI3KTsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKIHZhciBrZXkgPSB0b1ByaW1pdGl2ZShhcmd1bWVudCwgJ3N0cmluZycpOwogcmV0dXJuIGlzU3ltYm9sKGtleSkgPyBrZXkgOiBrZXkgKyAnJzsKfTsKCi8qKiovIH0pLAovKiAyMyAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgY2FsbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTIpOwp2YXIgaXNPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI0KTsKdmFyIGlzU3ltYm9sID0gX193X3BkZmpzX3JlcXVpcmVfXygyNyk7CnZhciBnZXRNZXRob2QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM0KTsKdmFyIG9yZGluYXJ5VG9QcmltaXRpdmUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM3KTsKdmFyIHdlbGxLbm93blN5bWJvbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMzgpOwp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKdmFyIFRPX1BSSU1JVElWRSA9IHdlbGxLbm93blN5bWJvbCgndG9QcmltaXRpdmUnKTsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaW5wdXQsIHByZWYpIHsKIGlmICghaXNPYmplY3QoaW5wdXQpIHx8IGlzU3ltYm9sKGlucHV0KSkKICByZXR1cm4gaW5wdXQ7CiB2YXIgZXhvdGljVG9QcmltID0gZ2V0TWV0aG9kKGlucHV0LCBUT19QUklNSVRJVkUpOwogdmFyIHJlc3VsdDsKIGlmIChleG90aWNUb1ByaW0pIHsKICBpZiAocHJlZiA9PT0gdW5kZWZpbmVkKQogICBwcmVmID0gJ2RlZmF1bHQnOwogIHJlc3VsdCA9IGNhbGwoZXhvdGljVG9QcmltLCBpbnB1dCwgcHJlZik7CiAgaWYgKCFpc09iamVjdChyZXN1bHQpIHx8IGlzU3ltYm9sKHJlc3VsdCkpCiAgIHJldHVybiByZXN1bHQ7CiAgdGhyb3cgJFR5cGVFcnJvcigiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlIik7CiB9CiBpZiAocHJlZiA9PT0gdW5kZWZpbmVkKQogIHByZWYgPSAnbnVtYmVyJzsKIHJldHVybiBvcmRpbmFyeVRvUHJpbWl0aXZlKGlucHV0LCBwcmVmKTsKfTsKCi8qKiovIH0pLAovKiAyNCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgaXNDYWxsYWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjUpOwp2YXIgJGRvY3VtZW50QWxsID0gX193X3BkZmpzX3JlcXVpcmVfXygyNik7CnZhciBkb2N1bWVudEFsbCA9ICRkb2N1bWVudEFsbC5hbGw7Cm1vZHVsZS5leHBvcnRzID0gJGRvY3VtZW50QWxsLklTX0hUTUxEREEgPyBmdW5jdGlvbiAoaXQpIHsKIHJldHVybiB0eXBlb2YgaXQgPT0gJ29iamVjdCcgPyBpdCAhPT0gbnVsbCA6IGlzQ2FsbGFibGUoaXQpIHx8IGl0ID09PSBkb2N1bWVudEFsbDsKfSA6IGZ1bmN0aW9uIChpdCkgewogcmV0dXJuIHR5cGVvZiBpdCA9PSAnb2JqZWN0JyA/IGl0ICE9PSBudWxsIDogaXNDYWxsYWJsZShpdCk7Cn07CgovKioqLyB9KSwKLyogMjUgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyICRkb2N1bWVudEFsbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjYpOwp2YXIgZG9jdW1lbnRBbGwgPSAkZG9jdW1lbnRBbGwuYWxsOwptb2R1bGUuZXhwb3J0cyA9ICRkb2N1bWVudEFsbC5JU19IVE1MRERBID8gZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiByZXR1cm4gdHlwZW9mIGFyZ3VtZW50ID09ICdmdW5jdGlvbicgfHwgYXJndW1lbnQgPT09IGRvY3VtZW50QWxsOwp9IDogZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiByZXR1cm4gdHlwZW9mIGFyZ3VtZW50ID09ICdmdW5jdGlvbic7Cn07CgovKioqLyB9KSwKLyogMjYgKi8KLyoqKi8gKChtb2R1bGUpID0+IHsKCnZhciBkb2N1bWVudEFsbCA9IHR5cGVvZiBkb2N1bWVudCA9PSAnb2JqZWN0JyAmJiBkb2N1bWVudC5hbGw7CnZhciBJU19IVE1MRERBID0gdHlwZW9mIGRvY3VtZW50QWxsID09ICd1bmRlZmluZWQnICYmIGRvY3VtZW50QWxsICE9PSB1bmRlZmluZWQ7Cm1vZHVsZS5leHBvcnRzID0gewogYWxsOiBkb2N1bWVudEFsbCwKIElTX0hUTUxEREE6IElTX0hUTUxEREEKfTsKCi8qKiovIH0pLAovKiAyNyAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgZ2V0QnVpbHRJbiA9IF9fd19wZGZqc19yZXF1aXJlX18oMjgpOwp2YXIgaXNDYWxsYWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjUpOwp2YXIgaXNQcm90b3R5cGVPZiA9IF9fd19wZGZqc19yZXF1aXJlX18oMjkpOwp2YXIgVVNFX1NZTUJPTF9BU19VSUQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDMwKTsKdmFyICRPYmplY3QgPSBPYmplY3Q7Cm1vZHVsZS5leHBvcnRzID0gVVNFX1NZTUJPTF9BU19VSUQgPyBmdW5jdGlvbiAoaXQpIHsKIHJldHVybiB0eXBlb2YgaXQgPT0gJ3N5bWJvbCc7Cn0gOiBmdW5jdGlvbiAoaXQpIHsKIHZhciAkU3ltYm9sID0gZ2V0QnVpbHRJbignU3ltYm9sJyk7CiByZXR1cm4gaXNDYWxsYWJsZSgkU3ltYm9sKSAmJiBpc1Byb3RvdHlwZU9mKCRTeW1ib2wucHJvdG90eXBlLCAkT2JqZWN0KGl0KSk7Cn07CgovKioqLyB9KSwKLyogMjggKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGdsb2JhbCA9IF9fd19wZGZqc19yZXF1aXJlX18oOCk7CnZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNSk7CnZhciBhRnVuY3Rpb24gPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKIHJldHVybiBpc0NhbGxhYmxlKGFyZ3VtZW50KSA/IGFyZ3VtZW50IDogdW5kZWZpbmVkOwp9Owptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChuYW1lc3BhY2UsIG1ldGhvZCkgewogcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPCAyID8gYUZ1bmN0aW9uKGdsb2JhbFtuYW1lc3BhY2VdKSA6IGdsb2JhbFtuYW1lc3BhY2VdICYmIGdsb2JhbFtuYW1lc3BhY2VdW21ldGhvZF07Cn07CgovKioqLyB9KSwKLyogMjkgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxOCk7Cm1vZHVsZS5leHBvcnRzID0gdW5jdXJyeVRoaXMoe30uaXNQcm90b3R5cGVPZik7CgovKioqLyB9KSwKLyogMzAgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIE5BVElWRV9TWU1CT0wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDMxKTsKbW9kdWxlLmV4cG9ydHMgPSBOQVRJVkVfU1lNQk9MICYmICFTeW1ib2wuc2hhbSAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09ICdzeW1ib2wnOwoKLyoqKi8gfSksCi8qIDMxICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBWOF9WRVJTSU9OID0gX193X3BkZmpzX3JlcXVpcmVfXygzMik7CnZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEpOwptb2R1bGUuZXhwb3J0cyA9ICEhT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyAmJiAhZmFpbHMoZnVuY3Rpb24gKCkgewogdmFyIHN5bWJvbCA9IFN5bWJvbCgpOwogcmV0dXJuICFTdHJpbmcoc3ltYm9sKSB8fCAhKE9iamVjdChzeW1ib2wpIGluc3RhbmNlb2YgU3ltYm9sKSB8fCAhU3ltYm9sLnNoYW0gJiYgVjhfVkVSU0lPTiAmJiBWOF9WRVJTSU9OIDwgNDE7Cn0pOwoKLyoqKi8gfSksCi8qIDMyICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBnbG9iYWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDgpOwp2YXIgdXNlckFnZW50ID0gX193X3BkZmpzX3JlcXVpcmVfXygzMyk7CnZhciBwcm9jZXNzID0gZ2xvYmFsLnByb2Nlc3M7CnZhciBEZW5vID0gZ2xvYmFsLkRlbm87CnZhciB2ZXJzaW9ucyA9IHByb2Nlc3MgJiYgcHJvY2Vzcy52ZXJzaW9ucyB8fCBEZW5vICYmIERlbm8udmVyc2lvbjsKdmFyIHY4ID0gdmVyc2lvbnMgJiYgdmVyc2lvbnMudjg7CnZhciBtYXRjaCwgdmVyc2lvbjsKaWYgKHY4KSB7CiBtYXRjaCA9IHY4LnNwbGl0KCcuJyk7CiB2ZXJzaW9uID0gbWF0Y2hbMF0gPiAwICYmIG1hdGNoWzBdIDwgNCA/IDEgOiArKG1hdGNoWzBdICsgbWF0Y2hbMV0pOwp9CmlmICghdmVyc2lvbiAmJiB1c2VyQWdlbnQpIHsKIG1hdGNoID0gdXNlckFnZW50Lm1hdGNoKC9FZGdlXC8oXGQrKS8pOwogaWYgKCFtYXRjaCB8fCBtYXRjaFsxXSA+PSA3NCkgewogIG1hdGNoID0gdXNlckFnZW50Lm1hdGNoKC9DaHJvbWVcLyhcZCspLyk7CiAgaWYgKG1hdGNoKQogICB2ZXJzaW9uID0gK21hdGNoWzFdOwogfQp9Cm1vZHVsZS5leHBvcnRzID0gdmVyc2lvbjsKCi8qKiovIH0pLAovKiAzMyAqLwovKioqLyAoKG1vZHVsZSkgPT4gewoKbW9kdWxlLmV4cG9ydHMgPSB0eXBlb2YgbmF2aWdhdG9yICE9ICd1bmRlZmluZWQnICYmIFN0cmluZyhuYXZpZ2F0b3IudXNlckFnZW50KSB8fCAnJzsKCi8qKiovIH0pLAovKiAzNCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgYUNhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygzNSk7CnZhciBpc051bGxPclVuZGVmaW5lZCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjEpOwptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChWLCBQKSB7CiB2YXIgZnVuYyA9IFZbUF07CiByZXR1cm4gaXNOdWxsT3JVbmRlZmluZWQoZnVuYykgPyB1bmRlZmluZWQgOiBhQ2FsbGFibGUoZnVuYyk7Cn07CgovKioqLyB9KSwKLyogMzUgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI1KTsKdmFyIHRyeVRvU3RyaW5nID0gX193X3BkZmpzX3JlcXVpcmVfXygzNik7CnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCkgewogaWYgKGlzQ2FsbGFibGUoYXJndW1lbnQpKQogIHJldHVybiBhcmd1bWVudDsKIHRocm93ICRUeXBlRXJyb3IodHJ5VG9TdHJpbmcoYXJndW1lbnQpICsgJyBpcyBub3QgYSBmdW5jdGlvbicpOwp9OwoKLyoqKi8gfSksCi8qIDM2ICovCi8qKiovICgobW9kdWxlKSA9PiB7Cgp2YXIgJFN0cmluZyA9IFN0cmluZzsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKIHRyeSB7CiAgcmV0dXJuICRTdHJpbmcoYXJndW1lbnQpOwogfSBjYXRjaCAoZXJyb3IpIHsKICByZXR1cm4gJ09iamVjdCc7CiB9Cn07CgovKioqLyB9KSwKLyogMzcgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGNhbGwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyKTsKdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI1KTsKdmFyIGlzT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyNCk7CnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpbnB1dCwgcHJlZikgewogdmFyIGZuLCB2YWw7CiBpZiAocHJlZiA9PT0gJ3N0cmluZycgJiYgaXNDYWxsYWJsZShmbiA9IGlucHV0LnRvU3RyaW5nKSAmJiAhaXNPYmplY3QodmFsID0gY2FsbChmbiwgaW5wdXQpKSkKICByZXR1cm4gdmFsOwogaWYgKGlzQ2FsbGFibGUoZm4gPSBpbnB1dC52YWx1ZU9mKSAmJiAhaXNPYmplY3QodmFsID0gY2FsbChmbiwgaW5wdXQpKSkKICByZXR1cm4gdmFsOwogaWYgKHByZWYgIT09ICdzdHJpbmcnICYmIGlzQ2FsbGFibGUoZm4gPSBpbnB1dC50b1N0cmluZykgJiYgIWlzT2JqZWN0KHZhbCA9IGNhbGwoZm4sIGlucHV0KSkpCiAgcmV0dXJuIHZhbDsKIHRocm93ICRUeXBlRXJyb3IoIkNhbid0IGNvbnZlcnQgb2JqZWN0IHRvIHByaW1pdGl2ZSB2YWx1ZSIpOwp9OwoKLyoqKi8gfSksCi8qIDM4ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBnbG9iYWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDgpOwp2YXIgc2hhcmVkID0gX193X3BkZmpzX3JlcXVpcmVfXygzOSk7CnZhciBoYXNPd24gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQzKTsKdmFyIHVpZCA9IF9fd19wZGZqc19yZXF1aXJlX18oNDUpOwp2YXIgTkFUSVZFX1NZTUJPTCA9IF9fd19wZGZqc19yZXF1aXJlX18oMzEpOwp2YXIgVVNFX1NZTUJPTF9BU19VSUQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDMwKTsKdmFyIFN5bWJvbCA9IGdsb2JhbC5TeW1ib2w7CnZhciBXZWxsS25vd25TeW1ib2xzU3RvcmUgPSBzaGFyZWQoJ3drcycpOwp2YXIgY3JlYXRlV2VsbEtub3duU3ltYm9sID0gVVNFX1NZTUJPTF9BU19VSUQgPyBTeW1ib2xbJ2ZvciddIHx8IFN5bWJvbCA6IFN5bWJvbCAmJiBTeW1ib2wud2l0aG91dFNldHRlciB8fCB1aWQ7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG5hbWUpIHsKIGlmICghaGFzT3duKFdlbGxLbm93blN5bWJvbHNTdG9yZSwgbmFtZSkpIHsKICBXZWxsS25vd25TeW1ib2xzU3RvcmVbbmFtZV0gPSBOQVRJVkVfU1lNQk9MICYmIGhhc093bihTeW1ib2wsIG5hbWUpID8gU3ltYm9sW25hbWVdIDogY3JlYXRlV2VsbEtub3duU3ltYm9sKCdTeW1ib2wuJyArIG5hbWUpOwogfQogcmV0dXJuIFdlbGxLbm93blN5bWJvbHNTdG9yZVtuYW1lXTsKfTsKCi8qKiovIH0pLAovKiAzOSAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgSVNfUFVSRSA9IF9fd19wZGZqc19yZXF1aXJlX18oNDApOwp2YXIgc3RvcmUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQxKTsKKG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHsKIHJldHVybiBzdG9yZVtrZXldIHx8IChzdG9yZVtrZXldID0gdmFsdWUgIT09IHVuZGVmaW5lZCA/IHZhbHVlIDoge30pOwp9KSgndmVyc2lvbnMnLCBbXSkucHVzaCh7CiB2ZXJzaW9uOiAnMy4yOS4xJywKIG1vZGU6IElTX1BVUkUgPyAncHVyZScgOiAnZ2xvYmFsJywKIGNvcHlyaWdodDogJ8KpIDIwMTQtMjAyMyBEZW5pcyBQdXNoa2FyZXYgKHpsb2lyb2NrLnJ1KScsCiBsaWNlbnNlOiAnaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvYmxvYi92My4yOS4xL0xJQ0VOU0UnLAogc291cmNlOiAnaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMnCn0pOwoKLyoqKi8gfSksCi8qIDQwICovCi8qKiovICgobW9kdWxlKSA9PiB7Cgptb2R1bGUuZXhwb3J0cyA9IGZhbHNlOwoKLyoqKi8gfSksCi8qIDQxICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBnbG9iYWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDgpOwp2YXIgZGVmaW5lR2xvYmFsUHJvcGVydHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQyKTsKdmFyIFNIQVJFRCA9ICdfX2NvcmUtanNfc2hhcmVkX18nOwp2YXIgc3RvcmUgPSBnbG9iYWxbU0hBUkVEXSB8fCBkZWZpbmVHbG9iYWxQcm9wZXJ0eShTSEFSRUQsIHt9KTsKbW9kdWxlLmV4cG9ydHMgPSBzdG9yZTsKCi8qKiovIH0pLAovKiA0MiAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgZ2xvYmFsID0gX193X3BkZmpzX3JlcXVpcmVfXyg4KTsKdmFyIGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5Owptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7CiB0cnkgewogIGRlZmluZVByb3BlcnR5KGdsb2JhbCwga2V5LCB7CiAgIHZhbHVlOiB2YWx1ZSwKICAgY29uZmlndXJhYmxlOiB0cnVlLAogICB3cml0YWJsZTogdHJ1ZQogIH0pOwogfSBjYXRjaCAoZXJyb3IpIHsKICBnbG9iYWxba2V5XSA9IHZhbHVlOwogfQogcmV0dXJuIHZhbHVlOwp9OwoKLyoqKi8gfSksCi8qIDQzICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTgpOwp2YXIgdG9PYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ0KTsKdmFyIGhhc093blByb3BlcnR5ID0gdW5jdXJyeVRoaXMoe30uaGFzT3duUHJvcGVydHkpOwptb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5oYXNPd24gfHwgZnVuY3Rpb24gaGFzT3duKGl0LCBrZXkpIHsKIHJldHVybiBoYXNPd25Qcm9wZXJ0eSh0b09iamVjdChpdCksIGtleSk7Cn07CgovKioqLyB9KSwKLyogNDQgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIHJlcXVpcmVPYmplY3RDb2VyY2libGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIwKTsKdmFyICRPYmplY3QgPSBPYmplY3Q7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiByZXR1cm4gJE9iamVjdChyZXF1aXJlT2JqZWN0Q29lcmNpYmxlKGFyZ3VtZW50KSk7Cn07CgovKioqLyB9KSwKLyogNDUgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxOCk7CnZhciBpZCA9IDA7CnZhciBwb3N0Zml4ID0gTWF0aC5yYW5kb20oKTsKdmFyIHRvU3RyaW5nID0gdW5jdXJyeVRoaXMoMS4wLnRvU3RyaW5nKTsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5KSB7CiByZXR1cm4gJ1N5bWJvbCgnICsgKGtleSA9PT0gdW5kZWZpbmVkID8gJycgOiBrZXkpICsgJylfJyArIHRvU3RyaW5nKCsraWQgKyBwb3N0Zml4LCAzNik7Cn07CgovKioqLyB9KSwKLyogNDYgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIERFU0NSSVBUT1JTID0gX193X3BkZmpzX3JlcXVpcmVfXygxMCk7CnZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEpOwp2YXIgY3JlYXRlRWxlbWVudCA9IF9fd19wZGZqc19yZXF1aXJlX18oNDcpOwptb2R1bGUuZXhwb3J0cyA9ICFERVNDUklQVE9SUyAmJiAhZmFpbHMoZnVuY3Rpb24gKCkgewogcmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjcmVhdGVFbGVtZW50KCdkaXYnKSwgJ2EnLCB7CiAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgIHJldHVybiA3OwogIH0KIH0pLmEgIT0gNzsKfSk7CgovKioqLyB9KSwKLyogNDcgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGdsb2JhbCA9IF9fd19wZGZqc19yZXF1aXJlX18oOCk7CnZhciBpc09iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjQpOwp2YXIgZG9jdW1lbnQgPSBnbG9iYWwuZG9jdW1lbnQ7CnZhciBFWElTVFMgPSBpc09iamVjdChkb2N1bWVudCkgJiYgaXNPYmplY3QoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCk7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7CiByZXR1cm4gRVhJU1RTID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChpdCkgOiB7fTsKfTsKCi8qKiovIH0pLAovKiA0OCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgREVTQ1JJUFRPUlMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwKTsKdmFyIGRlZmluZVByb3BlcnR5TW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXyg0OSk7CnZhciBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1KTsKbW9kdWxlLmV4cG9ydHMgPSBERVNDUklQVE9SUyA/IGZ1bmN0aW9uIChvYmplY3QsIGtleSwgdmFsdWUpIHsKIHJldHVybiBkZWZpbmVQcm9wZXJ0eU1vZHVsZS5mKG9iamVjdCwga2V5LCBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IoMSwgdmFsdWUpKTsKfSA6IGZ1bmN0aW9uIChvYmplY3QsIGtleSwgdmFsdWUpIHsKIG9iamVjdFtrZXldID0gdmFsdWU7CiByZXR1cm4gb2JqZWN0Owp9OwoKLyoqKi8gfSksCi8qIDQ5ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBERVNDUklQVE9SUyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTApOwp2YXIgSUU4X0RPTV9ERUZJTkUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ2KTsKdmFyIFY4X1BST1RPVFlQRV9ERUZJTkVfQlVHID0gX193X3BkZmpzX3JlcXVpcmVfXyg1MCk7CnZhciBhbk9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oNTEpOwp2YXIgdG9Qcm9wZXJ0eUtleSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjIpOwp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKdmFyICRkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTsKdmFyICRnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yOwp2YXIgRU5VTUVSQUJMRSA9ICdlbnVtZXJhYmxlJzsKdmFyIENPTkZJR1VSQUJMRSA9ICdjb25maWd1cmFibGUnOwp2YXIgV1JJVEFCTEUgPSAnd3JpdGFibGUnOwpleHBvcnRzLmYgPSBERVNDUklQVE9SUyA/IFY4X1BST1RPVFlQRV9ERUZJTkVfQlVHID8gZnVuY3Rpb24gZGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcykgewogYW5PYmplY3QoTyk7CiBQID0gdG9Qcm9wZXJ0eUtleShQKTsKIGFuT2JqZWN0KEF0dHJpYnV0ZXMpOwogaWYgKHR5cGVvZiBPID09PSAnZnVuY3Rpb24nICYmIFAgPT09ICdwcm90b3R5cGUnICYmICd2YWx1ZScgaW4gQXR0cmlidXRlcyAmJiBXUklUQUJMRSBpbiBBdHRyaWJ1dGVzICYmICFBdHRyaWJ1dGVzW1dSSVRBQkxFXSkgewogIHZhciBjdXJyZW50ID0gJGdldE93blByb3BlcnR5RGVzY3JpcHRvcihPLCBQKTsKICBpZiAoY3VycmVudCAmJiBjdXJyZW50W1dSSVRBQkxFXSkgewogICBPW1BdID0gQXR0cmlidXRlcy52YWx1ZTsKICAgQXR0cmlidXRlcyA9IHsKICAgIGNvbmZpZ3VyYWJsZTogQ09ORklHVVJBQkxFIGluIEF0dHJpYnV0ZXMgPyBBdHRyaWJ1dGVzW0NPTkZJR1VSQUJMRV0gOiBjdXJyZW50W0NPTkZJR1VSQUJMRV0sCiAgICBlbnVtZXJhYmxlOiBFTlVNRVJBQkxFIGluIEF0dHJpYnV0ZXMgPyBBdHRyaWJ1dGVzW0VOVU1FUkFCTEVdIDogY3VycmVudFtFTlVNRVJBQkxFXSwKICAgIHdyaXRhYmxlOiBmYWxzZQogICB9OwogIH0KIH0KIHJldHVybiAkZGVmaW5lUHJvcGVydHkoTywgUCwgQXR0cmlidXRlcyk7Cn0gOiAkZGVmaW5lUHJvcGVydHkgOiBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShPLCBQLCBBdHRyaWJ1dGVzKSB7CiBhbk9iamVjdChPKTsKIFAgPSB0b1Byb3BlcnR5S2V5KFApOwogYW5PYmplY3QoQXR0cmlidXRlcyk7CiBpZiAoSUU4X0RPTV9ERUZJTkUpCiAgdHJ5IHsKICAgcmV0dXJuICRkZWZpbmVQcm9wZXJ0eShPLCBQLCBBdHRyaWJ1dGVzKTsKICB9IGNhdGNoIChlcnJvcikgewogIH0KIGlmICgnZ2V0JyBpbiBBdHRyaWJ1dGVzIHx8ICdzZXQnIGluIEF0dHJpYnV0ZXMpCiAgdGhyb3cgJFR5cGVFcnJvcignQWNjZXNzb3JzIG5vdCBzdXBwb3J0ZWQnKTsKIGlmICgndmFsdWUnIGluIEF0dHJpYnV0ZXMpCiAgT1tQXSA9IEF0dHJpYnV0ZXMudmFsdWU7CiByZXR1cm4gTzsKfTsKCi8qKiovIH0pLAovKiA1MCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgREVTQ1JJUFRPUlMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwKTsKdmFyIGZhaWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMSk7Cm1vZHVsZS5leHBvcnRzID0gREVTQ1JJUFRPUlMgJiYgZmFpbHMoZnVuY3Rpb24gKCkgewogcmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShmdW5jdGlvbiAoKSB7CiB9LCAncHJvdG90eXBlJywgewogIHZhbHVlOiA0MiwKICB3cml0YWJsZTogZmFsc2UKIH0pLnByb3RvdHlwZSAhPSA0MjsKfSk7CgovKioqLyB9KSwKLyogNTEgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGlzT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyNCk7CnZhciAkU3RyaW5nID0gU3RyaW5nOwp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKIGlmIChpc09iamVjdChhcmd1bWVudCkpCiAgcmV0dXJuIGFyZ3VtZW50OwogdGhyb3cgJFR5cGVFcnJvcigkU3RyaW5nKGFyZ3VtZW50KSArICcgaXMgbm90IGFuIG9iamVjdCcpOwp9OwoKLyoqKi8gfSksCi8qIDUyICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNSk7CnZhciBkZWZpbmVQcm9wZXJ0eU1vZHVsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNDkpOwp2YXIgbWFrZUJ1aWx0SW4gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDUzKTsKdmFyIGRlZmluZUdsb2JhbFByb3BlcnR5ID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Mik7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKE8sIGtleSwgdmFsdWUsIG9wdGlvbnMpIHsKIGlmICghb3B0aW9ucykKICBvcHRpb25zID0ge307CiB2YXIgc2ltcGxlID0gb3B0aW9ucy5lbnVtZXJhYmxlOwogdmFyIG5hbWUgPSBvcHRpb25zLm5hbWUgIT09IHVuZGVmaW5lZCA/IG9wdGlvbnMubmFtZSA6IGtleTsKIGlmIChpc0NhbGxhYmxlKHZhbHVlKSkKICBtYWtlQnVpbHRJbih2YWx1ZSwgbmFtZSwgb3B0aW9ucyk7CiBpZiAob3B0aW9ucy5nbG9iYWwpIHsKICBpZiAoc2ltcGxlKQogICBPW2tleV0gPSB2YWx1ZTsKICBlbHNlCiAgIGRlZmluZUdsb2JhbFByb3BlcnR5KGtleSwgdmFsdWUpOwogfSBlbHNlIHsKICB0cnkgewogICBpZiAoIW9wdGlvbnMudW5zYWZlKQogICAgZGVsZXRlIE9ba2V5XTsKICAgZWxzZSBpZiAoT1trZXldKQogICAgc2ltcGxlID0gdHJ1ZTsKICB9IGNhdGNoIChlcnJvcikgewogIH0KICBpZiAoc2ltcGxlKQogICBPW2tleV0gPSB2YWx1ZTsKICBlbHNlCiAgIGRlZmluZVByb3BlcnR5TW9kdWxlLmYoTywga2V5LCB7CiAgICB2YWx1ZTogdmFsdWUsCiAgICBlbnVtZXJhYmxlOiBmYWxzZSwKICAgIGNvbmZpZ3VyYWJsZTogIW9wdGlvbnMubm9uQ29uZmlndXJhYmxlLAogICAgd3JpdGFibGU6ICFvcHRpb25zLm5vbldyaXRhYmxlCiAgIH0pOwogfQogcmV0dXJuIE87Cn07CgovKioqLyB9KSwKLyogNTMgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxOCk7CnZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEpOwp2YXIgaXNDYWxsYWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjUpOwp2YXIgaGFzT3duID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Myk7CnZhciBERVNDUklQVE9SUyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTApOwp2YXIgQ09ORklHVVJBQkxFX0ZVTkNUSU9OX05BTUUgPSAoX193X3BkZmpzX3JlcXVpcmVfXyg1NCkuQ09ORklHVVJBQkxFKTsKdmFyIGluc3BlY3RTb3VyY2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDU1KTsKdmFyIEludGVybmFsU3RhdGVNb2R1bGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDU2KTsKdmFyIGVuZm9yY2VJbnRlcm5hbFN0YXRlID0gSW50ZXJuYWxTdGF0ZU1vZHVsZS5lbmZvcmNlOwp2YXIgZ2V0SW50ZXJuYWxTdGF0ZSA9IEludGVybmFsU3RhdGVNb2R1bGUuZ2V0Owp2YXIgJFN0cmluZyA9IFN0cmluZzsKdmFyIGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5Owp2YXIgc3RyaW5nU2xpY2UgPSB1bmN1cnJ5VGhpcygnJy5zbGljZSk7CnZhciByZXBsYWNlID0gdW5jdXJyeVRoaXMoJycucmVwbGFjZSk7CnZhciBqb2luID0gdW5jdXJyeVRoaXMoW10uam9pbik7CnZhciBDT05GSUdVUkFCTEVfTEVOR1RIID0gREVTQ1JJUFRPUlMgJiYgIWZhaWxzKGZ1bmN0aW9uICgpIHsKIHJldHVybiBkZWZpbmVQcm9wZXJ0eShmdW5jdGlvbiAoKSB7CiB9LCAnbGVuZ3RoJywgeyB2YWx1ZTogOCB9KS5sZW5ndGggIT09IDg7Cn0pOwp2YXIgVEVNUExBVEUgPSBTdHJpbmcoU3RyaW5nKS5zcGxpdCgnU3RyaW5nJyk7CnZhciBtYWtlQnVpbHRJbiA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlLCBuYW1lLCBvcHRpb25zKSB7CiBpZiAoc3RyaW5nU2xpY2UoJFN0cmluZyhuYW1lKSwgMCwgNykgPT09ICdTeW1ib2woJykgewogIG5hbWUgPSAnWycgKyByZXBsYWNlKCRTdHJpbmcobmFtZSksIC9eU3ltYm9sXCgoW14pXSopXCkvLCAnJDEnKSArICddJzsKIH0KIGlmIChvcHRpb25zICYmIG9wdGlvbnMuZ2V0dGVyKQogIG5hbWUgPSAnZ2V0ICcgKyBuYW1lOwogaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5zZXR0ZXIpCiAgbmFtZSA9ICdzZXQgJyArIG5hbWU7CiBpZiAoIWhhc093bih2YWx1ZSwgJ25hbWUnKSB8fCBDT05GSUdVUkFCTEVfRlVOQ1RJT05fTkFNRSAmJiB2YWx1ZS5uYW1lICE9PSBuYW1lKSB7CiAgaWYgKERFU0NSSVBUT1JTKQogICBkZWZpbmVQcm9wZXJ0eSh2YWx1ZSwgJ25hbWUnLCB7CiAgICB2YWx1ZTogbmFtZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZQogICB9KTsKICBlbHNlCiAgIHZhbHVlLm5hbWUgPSBuYW1lOwogfQogaWYgKENPTkZJR1VSQUJMRV9MRU5HVEggJiYgb3B0aW9ucyAmJiBoYXNPd24ob3B0aW9ucywgJ2FyaXR5JykgJiYgdmFsdWUubGVuZ3RoICE9PSBvcHRpb25zLmFyaXR5KSB7CiAgZGVmaW5lUHJvcGVydHkodmFsdWUsICdsZW5ndGgnLCB7IHZhbHVlOiBvcHRpb25zLmFyaXR5IH0pOwogfQogdHJ5IHsKICBpZiAob3B0aW9ucyAmJiBoYXNPd24ob3B0aW9ucywgJ2NvbnN0cnVjdG9yJykgJiYgb3B0aW9ucy5jb25zdHJ1Y3RvcikgewogICBpZiAoREVTQ1JJUFRPUlMpCiAgICBkZWZpbmVQcm9wZXJ0eSh2YWx1ZSwgJ3Byb3RvdHlwZScsIHsgd3JpdGFibGU6IGZhbHNlIH0pOwogIH0gZWxzZSBpZiAodmFsdWUucHJvdG90eXBlKQogICB2YWx1ZS5wcm90b3R5cGUgPSB1bmRlZmluZWQ7CiB9IGNhdGNoIChlcnJvcikgewogfQogdmFyIHN0YXRlID0gZW5mb3JjZUludGVybmFsU3RhdGUodmFsdWUpOwogaWYgKCFoYXNPd24oc3RhdGUsICdzb3VyY2UnKSkgewogIHN0YXRlLnNvdXJjZSA9IGpvaW4oVEVNUExBVEUsIHR5cGVvZiBuYW1lID09ICdzdHJpbmcnID8gbmFtZSA6ICcnKTsKIH0KIHJldHVybiB2YWx1ZTsKfTsKRnVuY3Rpb24ucHJvdG90eXBlLnRvU3RyaW5nID0gbWFrZUJ1aWx0SW4oZnVuY3Rpb24gdG9TdHJpbmcoKSB7CiByZXR1cm4gaXNDYWxsYWJsZSh0aGlzKSAmJiBnZXRJbnRlcm5hbFN0YXRlKHRoaXMpLnNvdXJjZSB8fCBpbnNwZWN0U291cmNlKHRoaXMpOwp9LCAndG9TdHJpbmcnKTsKCi8qKiovIH0pLAovKiA1NCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgREVTQ1JJUFRPUlMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwKTsKdmFyIGhhc093biA9IF9fd19wZGZqc19yZXF1aXJlX18oNDMpOwp2YXIgRnVuY3Rpb25Qcm90b3R5cGUgPSBGdW5jdGlvbi5wcm90b3R5cGU7CnZhciBnZXREZXNjcmlwdG9yID0gREVTQ1JJUFRPUlMgJiYgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcjsKdmFyIEVYSVNUUyA9IGhhc093bihGdW5jdGlvblByb3RvdHlwZSwgJ25hbWUnKTsKdmFyIFBST1BFUiA9IEVYSVNUUyAmJiBmdW5jdGlvbiBzb21ldGhpbmcoKSB7Cn0ubmFtZSA9PT0gJ3NvbWV0aGluZyc7CnZhciBDT05GSUdVUkFCTEUgPSBFWElTVFMgJiYgKCFERVNDUklQVE9SUyB8fCBERVNDUklQVE9SUyAmJiBnZXREZXNjcmlwdG9yKEZ1bmN0aW9uUHJvdG90eXBlLCAnbmFtZScpLmNvbmZpZ3VyYWJsZSk7Cm1vZHVsZS5leHBvcnRzID0gewogRVhJU1RTOiBFWElTVFMsCiBQUk9QRVI6IFBST1BFUiwKIENPTkZJR1VSQUJMRTogQ09ORklHVVJBQkxFCn07CgovKioqLyB9KSwKLyogNTUgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxOCk7CnZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNSk7CnZhciBzdG9yZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNDEpOwp2YXIgZnVuY3Rpb25Ub1N0cmluZyA9IHVuY3VycnlUaGlzKEZ1bmN0aW9uLnRvU3RyaW5nKTsKaWYgKCFpc0NhbGxhYmxlKHN0b3JlLmluc3BlY3RTb3VyY2UpKSB7CiBzdG9yZS5pbnNwZWN0U291cmNlID0gZnVuY3Rpb24gKGl0KSB7CiAgcmV0dXJuIGZ1bmN0aW9uVG9TdHJpbmcoaXQpOwogfTsKfQptb2R1bGUuZXhwb3J0cyA9IHN0b3JlLmluc3BlY3RTb3VyY2U7CgovKioqLyB9KSwKLyogNTYgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIE5BVElWRV9XRUFLX01BUCA9IF9fd19wZGZqc19yZXF1aXJlX18oNTcpOwp2YXIgZ2xvYmFsID0gX193X3BkZmpzX3JlcXVpcmVfXyg4KTsKdmFyIGlzT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyNCk7CnZhciBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ4KTsKdmFyIGhhc093biA9IF9fd19wZGZqc19yZXF1aXJlX18oNDMpOwp2YXIgc2hhcmVkID0gX193X3BkZmpzX3JlcXVpcmVfXyg0MSk7CnZhciBzaGFyZWRLZXkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDU4KTsKdmFyIGhpZGRlbktleXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDU5KTsKdmFyIE9CSkVDVF9BTFJFQURZX0lOSVRJQUxJWkVEID0gJ09iamVjdCBhbHJlYWR5IGluaXRpYWxpemVkJzsKdmFyIFR5cGVFcnJvciA9IGdsb2JhbC5UeXBlRXJyb3I7CnZhciBXZWFrTWFwID0gZ2xvYmFsLldlYWtNYXA7CnZhciBzZXQsIGdldCwgaGFzOwp2YXIgZW5mb3JjZSA9IGZ1bmN0aW9uIChpdCkgewogcmV0dXJuIGhhcyhpdCkgPyBnZXQoaXQpIDogc2V0KGl0LCB7fSk7Cn07CnZhciBnZXR0ZXJGb3IgPSBmdW5jdGlvbiAoVFlQRSkgewogcmV0dXJuIGZ1bmN0aW9uIChpdCkgewogIHZhciBzdGF0ZTsKICBpZiAoIWlzT2JqZWN0KGl0KSB8fCAoc3RhdGUgPSBnZXQoaXQpKS50eXBlICE9PSBUWVBFKSB7CiAgIHRocm93IFR5cGVFcnJvcignSW5jb21wYXRpYmxlIHJlY2VpdmVyLCAnICsgVFlQRSArICcgcmVxdWlyZWQnKTsKICB9CiAgcmV0dXJuIHN0YXRlOwogfTsKfTsKaWYgKE5BVElWRV9XRUFLX01BUCB8fCBzaGFyZWQuc3RhdGUpIHsKIHZhciBzdG9yZSA9IHNoYXJlZC5zdGF0ZSB8fCAoc2hhcmVkLnN0YXRlID0gbmV3IFdlYWtNYXAoKSk7CiBzdG9yZS5nZXQgPSBzdG9yZS5nZXQ7CiBzdG9yZS5oYXMgPSBzdG9yZS5oYXM7CiBzdG9yZS5zZXQgPSBzdG9yZS5zZXQ7CiBzZXQgPSBmdW5jdGlvbiAoaXQsIG1ldGFkYXRhKSB7CiAgaWYgKHN0b3JlLmhhcyhpdCkpCiAgIHRocm93IFR5cGVFcnJvcihPQkpFQ1RfQUxSRUFEWV9JTklUSUFMSVpFRCk7CiAgbWV0YWRhdGEuZmFjYWRlID0gaXQ7CiAgc3RvcmUuc2V0KGl0LCBtZXRhZGF0YSk7CiAgcmV0dXJuIG1ldGFkYXRhOwogfTsKIGdldCA9IGZ1bmN0aW9uIChpdCkgewogIHJldHVybiBzdG9yZS5nZXQoaXQpIHx8IHt9OwogfTsKIGhhcyA9IGZ1bmN0aW9uIChpdCkgewogIHJldHVybiBzdG9yZS5oYXMoaXQpOwogfTsKfSBlbHNlIHsKIHZhciBTVEFURSA9IHNoYXJlZEtleSgnc3RhdGUnKTsKIGhpZGRlbktleXNbU1RBVEVdID0gdHJ1ZTsKIHNldCA9IGZ1bmN0aW9uIChpdCwgbWV0YWRhdGEpIHsKICBpZiAoaGFzT3duKGl0LCBTVEFURSkpCiAgIHRocm93IFR5cGVFcnJvcihPQkpFQ1RfQUxSRUFEWV9JTklUSUFMSVpFRCk7CiAgbWV0YWRhdGEuZmFjYWRlID0gaXQ7CiAgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KGl0LCBTVEFURSwgbWV0YWRhdGEpOwogIHJldHVybiBtZXRhZGF0YTsKIH07CiBnZXQgPSBmdW5jdGlvbiAoaXQpIHsKICByZXR1cm4gaGFzT3duKGl0LCBTVEFURSkgPyBpdFtTVEFURV0gOiB7fTsKIH07CiBoYXMgPSBmdW5jdGlvbiAoaXQpIHsKICByZXR1cm4gaGFzT3duKGl0LCBTVEFURSk7CiB9Owp9Cm1vZHVsZS5leHBvcnRzID0gewogc2V0OiBzZXQsCiBnZXQ6IGdldCwKIGhhczogaGFzLAogZW5mb3JjZTogZW5mb3JjZSwKIGdldHRlckZvcjogZ2V0dGVyRm9yCn07CgovKioqLyB9KSwKLyogNTcgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGdsb2JhbCA9IF9fd19wZGZqc19yZXF1aXJlX18oOCk7CnZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNSk7CnZhciBXZWFrTWFwID0gZ2xvYmFsLldlYWtNYXA7Cm1vZHVsZS5leHBvcnRzID0gaXNDYWxsYWJsZShXZWFrTWFwKSAmJiAvbmF0aXZlIGNvZGUvLnRlc3QoU3RyaW5nKFdlYWtNYXApKTsKCi8qKiovIH0pLAovKiA1OCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgc2hhcmVkID0gX193X3BkZmpzX3JlcXVpcmVfXygzOSk7CnZhciB1aWQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ1KTsKdmFyIGtleXMgPSBzaGFyZWQoJ2tleXMnKTsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5KSB7CiByZXR1cm4ga2V5c1trZXldIHx8IChrZXlzW2tleV0gPSB1aWQoa2V5KSk7Cn07CgovKioqLyB9KSwKLyogNTkgKi8KLyoqKi8gKChtb2R1bGUpID0+IHsKCm1vZHVsZS5leHBvcnRzID0ge307CgovKioqLyB9KSwKLyogNjAgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGhhc093biA9IF9fd19wZGZqc19yZXF1aXJlX18oNDMpOwp2YXIgb3duS2V5cyA9IF9fd19wZGZqc19yZXF1aXJlX18oNjEpOwp2YXIgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yTW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXyg5KTsKdmFyIGRlZmluZVByb3BlcnR5TW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXyg0OSk7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHRhcmdldCwgc291cmNlLCBleGNlcHRpb25zKSB7CiB2YXIga2V5cyA9IG93bktleXMoc291cmNlKTsKIHZhciBkZWZpbmVQcm9wZXJ0eSA9IGRlZmluZVByb3BlcnR5TW9kdWxlLmY7CiB2YXIgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yTW9kdWxlLmY7CiBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICB2YXIga2V5ID0ga2V5c1tpXTsKICBpZiAoIWhhc093bih0YXJnZXQsIGtleSkgJiYgIShleGNlcHRpb25zICYmIGhhc093bihleGNlcHRpb25zLCBrZXkpKSkgewogICBkZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHNvdXJjZSwga2V5KSk7CiAgfQogfQp9OwoKLyoqKi8gfSksCi8qIDYxICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBnZXRCdWlsdEluID0gX193X3BkZmpzX3JlcXVpcmVfXygyOCk7CnZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTgpOwp2YXIgZ2V0T3duUHJvcGVydHlOYW1lc01vZHVsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNjIpOwp2YXIgZ2V0T3duUHJvcGVydHlTeW1ib2xzTW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXyg3MSk7CnZhciBhbk9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oNTEpOwp2YXIgY29uY2F0ID0gdW5jdXJyeVRoaXMoW10uY29uY2F0KTsKbW9kdWxlLmV4cG9ydHMgPSBnZXRCdWlsdEluKCdSZWZsZWN0JywgJ293bktleXMnKSB8fCBmdW5jdGlvbiBvd25LZXlzKGl0KSB7CiB2YXIga2V5cyA9IGdldE93blByb3BlcnR5TmFtZXNNb2R1bGUuZihhbk9iamVjdChpdCkpOwogdmFyIGdldE93blByb3BlcnR5U3ltYm9scyA9IGdldE93blByb3BlcnR5U3ltYm9sc01vZHVsZS5mOwogcmV0dXJuIGdldE93blByb3BlcnR5U3ltYm9scyA/IGNvbmNhdChrZXlzLCBnZXRPd25Qcm9wZXJ0eVN5bWJvbHMoaXQpKSA6IGtleXM7Cn07CgovKioqLyB9KSwKLyogNjIgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGludGVybmFsT2JqZWN0S2V5cyA9IF9fd19wZGZqc19yZXF1aXJlX18oNjMpOwp2YXIgZW51bUJ1Z0tleXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDcwKTsKdmFyIGhpZGRlbktleXMgPSBlbnVtQnVnS2V5cy5jb25jYXQoJ2xlbmd0aCcsICdwcm90b3R5cGUnKTsKZXhwb3J0cy5mID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMgfHwgZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlOYW1lcyhPKSB7CiByZXR1cm4gaW50ZXJuYWxPYmplY3RLZXlzKE8sIGhpZGRlbktleXMpOwp9OwoKLyoqKi8gfSksCi8qIDYzICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTgpOwp2YXIgaGFzT3duID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Myk7CnZhciB0b0luZGV4ZWRPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE2KTsKdmFyIGluZGV4T2YgPSAoX193X3BkZmpzX3JlcXVpcmVfXyg2NCkuaW5kZXhPZik7CnZhciBoaWRkZW5LZXlzID0gX193X3BkZmpzX3JlcXVpcmVfXyg1OSk7CnZhciBwdXNoID0gdW5jdXJyeVRoaXMoW10ucHVzaCk7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9iamVjdCwgbmFtZXMpIHsKIHZhciBPID0gdG9JbmRleGVkT2JqZWN0KG9iamVjdCk7CiB2YXIgaSA9IDA7CiB2YXIgcmVzdWx0ID0gW107CiB2YXIga2V5OwogZm9yIChrZXkgaW4gTykKICAhaGFzT3duKGhpZGRlbktleXMsIGtleSkgJiYgaGFzT3duKE8sIGtleSkgJiYgcHVzaChyZXN1bHQsIGtleSk7CiB3aGlsZSAobmFtZXMubGVuZ3RoID4gaSkKICBpZiAoaGFzT3duKE8sIGtleSA9IG5hbWVzW2krK10pKSB7CiAgIH5pbmRleE9mKHJlc3VsdCwga2V5KSB8fCBwdXNoKHJlc3VsdCwga2V5KTsKICB9CiByZXR1cm4gcmVzdWx0Owp9OwoKLyoqKi8gfSksCi8qIDY0ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciB0b0luZGV4ZWRPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE2KTsKdmFyIHRvQWJzb2x1dGVJbmRleCA9IF9fd19wZGZqc19yZXF1aXJlX18oNjUpOwp2YXIgbGVuZ3RoT2ZBcnJheUxpa2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDY4KTsKdmFyIGNyZWF0ZU1ldGhvZCA9IGZ1bmN0aW9uIChJU19JTkNMVURFUykgewogcmV0dXJuIGZ1bmN0aW9uICgkdGhpcywgZWwsIGZyb21JbmRleCkgewogIHZhciBPID0gdG9JbmRleGVkT2JqZWN0KCR0aGlzKTsKICB2YXIgbGVuZ3RoID0gbGVuZ3RoT2ZBcnJheUxpa2UoTyk7CiAgdmFyIGluZGV4ID0gdG9BYnNvbHV0ZUluZGV4KGZyb21JbmRleCwgbGVuZ3RoKTsKICB2YXIgdmFsdWU7CiAgaWYgKElTX0lOQ0xVREVTICYmIGVsICE9IGVsKQogICB3aGlsZSAobGVuZ3RoID4gaW5kZXgpIHsKICAgIHZhbHVlID0gT1tpbmRleCsrXTsKICAgIGlmICh2YWx1ZSAhPSB2YWx1ZSkKICAgICByZXR1cm4gdHJ1ZTsKICAgfQogIGVsc2UKICAgZm9yICg7IGxlbmd0aCA+IGluZGV4OyBpbmRleCsrKSB7CiAgICBpZiAoKElTX0lOQ0xVREVTIHx8IGluZGV4IGluIE8pICYmIE9baW5kZXhdID09PSBlbCkKICAgICByZXR1cm4gSVNfSU5DTFVERVMgfHwgaW5kZXggfHwgMDsKICAgfQogIHJldHVybiAhSVNfSU5DTFVERVMgJiYgLTE7CiB9Owp9Owptb2R1bGUuZXhwb3J0cyA9IHsKIGluY2x1ZGVzOiBjcmVhdGVNZXRob2QodHJ1ZSksCiBpbmRleE9mOiBjcmVhdGVNZXRob2QoZmFsc2UpCn07CgovKioqLyB9KSwKLyogNjUgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIHRvSW50ZWdlck9ySW5maW5pdHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDY2KTsKdmFyIG1heCA9IE1hdGgubWF4Owp2YXIgbWluID0gTWF0aC5taW47Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGluZGV4LCBsZW5ndGgpIHsKIHZhciBpbnRlZ2VyID0gdG9JbnRlZ2VyT3JJbmZpbml0eShpbmRleCk7CiByZXR1cm4gaW50ZWdlciA8IDAgPyBtYXgoaW50ZWdlciArIGxlbmd0aCwgMCkgOiBtaW4oaW50ZWdlciwgbGVuZ3RoKTsKfTsKCi8qKiovIH0pLAovKiA2NiAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgdHJ1bmMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDY3KTsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKIHZhciBudW1iZXIgPSArYXJndW1lbnQ7CiByZXR1cm4gbnVtYmVyICE9PSBudW1iZXIgfHwgbnVtYmVyID09PSAwID8gMCA6IHRydW5jKG51bWJlcik7Cn07CgovKioqLyB9KSwKLyogNjcgKi8KLyoqKi8gKChtb2R1bGUpID0+IHsKCnZhciBjZWlsID0gTWF0aC5jZWlsOwp2YXIgZmxvb3IgPSBNYXRoLmZsb29yOwptb2R1bGUuZXhwb3J0cyA9IE1hdGgudHJ1bmMgfHwgZnVuY3Rpb24gdHJ1bmMoeCkgewogdmFyIG4gPSAreDsKIHJldHVybiAobiA+IDAgPyBmbG9vciA6IGNlaWwpKG4pOwp9OwoKLyoqKi8gfSksCi8qIDY4ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciB0b0xlbmd0aCA9IF9fd19wZGZqc19yZXF1aXJlX18oNjkpOwptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmopIHsKIHJldHVybiB0b0xlbmd0aChvYmoubGVuZ3RoKTsKfTsKCi8qKiovIH0pLAovKiA2OSAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgdG9JbnRlZ2VyT3JJbmZpbml0eSA9IF9fd19wZGZqc19yZXF1aXJlX18oNjYpOwp2YXIgbWluID0gTWF0aC5taW47Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiByZXR1cm4gYXJndW1lbnQgPiAwID8gbWluKHRvSW50ZWdlck9ySW5maW5pdHkoYXJndW1lbnQpLCAweDFGRkZGRkZGRkZGRkZGKSA6IDA7Cn07CgovKioqLyB9KSwKLyogNzAgKi8KLyoqKi8gKChtb2R1bGUpID0+IHsKCm1vZHVsZS5leHBvcnRzID0gWwogJ2NvbnN0cnVjdG9yJywKICdoYXNPd25Qcm9wZXJ0eScsCiAnaXNQcm90b3R5cGVPZicsCiAncHJvcGVydHlJc0VudW1lcmFibGUnLAogJ3RvTG9jYWxlU3RyaW5nJywKICd0b1N0cmluZycsCiAndmFsdWVPZicKXTsKCi8qKiovIH0pLAovKiA3MSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzKSA9PiB7CgpleHBvcnRzLmYgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzOwoKLyoqKi8gfSksCi8qIDcyICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEpOwp2YXIgaXNDYWxsYWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjUpOwp2YXIgcmVwbGFjZW1lbnQgPSAvI3xcLnByb3RvdHlwZVwuLzsKdmFyIGlzRm9yY2VkID0gZnVuY3Rpb24gKGZlYXR1cmUsIGRldGVjdGlvbikgewogdmFyIHZhbHVlID0gZGF0YVtub3JtYWxpemUoZmVhdHVyZSldOwogcmV0dXJuIHZhbHVlID09IFBPTFlGSUxMID8gdHJ1ZSA6IHZhbHVlID09IE5BVElWRSA/IGZhbHNlIDogaXNDYWxsYWJsZShkZXRlY3Rpb24pID8gZmFpbHMoZGV0ZWN0aW9uKSA6ICEhZGV0ZWN0aW9uOwp9Owp2YXIgbm9ybWFsaXplID0gaXNGb3JjZWQubm9ybWFsaXplID0gZnVuY3Rpb24gKHN0cmluZykgewogcmV0dXJuIFN0cmluZyhzdHJpbmcpLnJlcGxhY2UocmVwbGFjZW1lbnQsICcuJykudG9Mb3dlckNhc2UoKTsKfTsKdmFyIGRhdGEgPSBpc0ZvcmNlZC5kYXRhID0ge307CnZhciBOQVRJVkUgPSBpc0ZvcmNlZC5OQVRJVkUgPSAnTic7CnZhciBQT0xZRklMTCA9IGlzRm9yY2VkLlBPTFlGSUxMID0gJ1AnOwptb2R1bGUuZXhwb3J0cyA9IGlzRm9yY2VkOwoKLyoqKi8gfSksCi8qIDczICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM4KTsKdmFyIGNyZWF0ZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNzQpOwp2YXIgZGVmaW5lUHJvcGVydHkgPSAoX193X3BkZmpzX3JlcXVpcmVfXyg0OSkuZik7CnZhciBVTlNDT1BBQkxFUyA9IHdlbGxLbm93blN5bWJvbCgndW5zY29wYWJsZXMnKTsKdmFyIEFycmF5UHJvdG90eXBlID0gQXJyYXkucHJvdG90eXBlOwppZiAoQXJyYXlQcm90b3R5cGVbVU5TQ09QQUJMRVNdID09IHVuZGVmaW5lZCkgewogZGVmaW5lUHJvcGVydHkoQXJyYXlQcm90b3R5cGUsIFVOU0NPUEFCTEVTLCB7CiAgY29uZmlndXJhYmxlOiB0cnVlLAogIHZhbHVlOiBjcmVhdGUobnVsbCkKIH0pOwp9Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSkgewogQXJyYXlQcm90b3R5cGVbVU5TQ09QQUJMRVNdW2tleV0gPSB0cnVlOwp9OwoKLyoqKi8gfSksCi8qIDc0ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBhbk9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oNTEpOwp2YXIgZGVmaW5lUHJvcGVydGllc01vZHVsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNzUpOwp2YXIgZW51bUJ1Z0tleXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDcwKTsKdmFyIGhpZGRlbktleXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDU5KTsKdmFyIGh0bWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDc3KTsKdmFyIGRvY3VtZW50Q3JlYXRlRWxlbWVudCA9IF9fd19wZGZqc19yZXF1aXJlX18oNDcpOwp2YXIgc2hhcmVkS2V5ID0gX193X3BkZmpzX3JlcXVpcmVfXyg1OCk7CnZhciBHVCA9ICc+JzsKdmFyIExUID0gJzwnOwp2YXIgUFJPVE9UWVBFID0gJ3Byb3RvdHlwZSc7CnZhciBTQ1JJUFQgPSAnc2NyaXB0JzsKdmFyIElFX1BST1RPID0gc2hhcmVkS2V5KCdJRV9QUk9UTycpOwp2YXIgRW1wdHlDb25zdHJ1Y3RvciA9IGZ1bmN0aW9uICgpIHsKfTsKdmFyIHNjcmlwdFRhZyA9IGZ1bmN0aW9uIChjb250ZW50KSB7CiByZXR1cm4gTFQgKyBTQ1JJUFQgKyBHVCArIGNvbnRlbnQgKyBMVCArICcvJyArIFNDUklQVCArIEdUOwp9Owp2YXIgTnVsbFByb3RvT2JqZWN0VmlhQWN0aXZlWCA9IGZ1bmN0aW9uIChhY3RpdmVYRG9jdW1lbnQpIHsKIGFjdGl2ZVhEb2N1bWVudC53cml0ZShzY3JpcHRUYWcoJycpKTsKIGFjdGl2ZVhEb2N1bWVudC5jbG9zZSgpOwogdmFyIHRlbXAgPSBhY3RpdmVYRG9jdW1lbnQucGFyZW50V2luZG93Lk9iamVjdDsKIGFjdGl2ZVhEb2N1bWVudCA9IG51bGw7CiByZXR1cm4gdGVtcDsKfTsKdmFyIE51bGxQcm90b09iamVjdFZpYUlGcmFtZSA9IGZ1bmN0aW9uICgpIHsKIHZhciBpZnJhbWUgPSBkb2N1bWVudENyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpOwogdmFyIEpTID0gJ2phdmEnICsgU0NSSVBUICsgJzonOwogdmFyIGlmcmFtZURvY3VtZW50OwogaWZyYW1lLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7CiBodG1sLmFwcGVuZENoaWxkKGlmcmFtZSk7CiBpZnJhbWUuc3JjID0gU3RyaW5nKEpTKTsKIGlmcmFtZURvY3VtZW50ID0gaWZyYW1lLmNvbnRlbnRXaW5kb3cuZG9jdW1lbnQ7CiBpZnJhbWVEb2N1bWVudC5vcGVuKCk7CiBpZnJhbWVEb2N1bWVudC53cml0ZShzY3JpcHRUYWcoJ2RvY3VtZW50LkY9T2JqZWN0JykpOwogaWZyYW1lRG9jdW1lbnQuY2xvc2UoKTsKIHJldHVybiBpZnJhbWVEb2N1bWVudC5GOwp9Owp2YXIgYWN0aXZlWERvY3VtZW50Owp2YXIgTnVsbFByb3RvT2JqZWN0ID0gZnVuY3Rpb24gKCkgewogdHJ5IHsKICBhY3RpdmVYRG9jdW1lbnQgPSBuZXcgQWN0aXZlWE9iamVjdCgnaHRtbGZpbGUnKTsKIH0gY2F0Y2ggKGVycm9yKSB7CiB9CiBOdWxsUHJvdG9PYmplY3QgPSB0eXBlb2YgZG9jdW1lbnQgIT0gJ3VuZGVmaW5lZCcgPyBkb2N1bWVudC5kb21haW4gJiYgYWN0aXZlWERvY3VtZW50ID8gTnVsbFByb3RvT2JqZWN0VmlhQWN0aXZlWChhY3RpdmVYRG9jdW1lbnQpIDogTnVsbFByb3RvT2JqZWN0VmlhSUZyYW1lKCkgOiBOdWxsUHJvdG9PYmplY3RWaWFBY3RpdmVYKGFjdGl2ZVhEb2N1bWVudCk7CiB2YXIgbGVuZ3RoID0gZW51bUJ1Z0tleXMubGVuZ3RoOwogd2hpbGUgKGxlbmd0aC0tKQogIGRlbGV0ZSBOdWxsUHJvdG9PYmplY3RbUFJPVE9UWVBFXVtlbnVtQnVnS2V5c1tsZW5ndGhdXTsKIHJldHVybiBOdWxsUHJvdG9PYmplY3QoKTsKfTsKaGlkZGVuS2V5c1tJRV9QUk9UT10gPSB0cnVlOwptb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5jcmVhdGUgfHwgZnVuY3Rpb24gY3JlYXRlKE8sIFByb3BlcnRpZXMpIHsKIHZhciByZXN1bHQ7CiBpZiAoTyAhPT0gbnVsbCkgewogIEVtcHR5Q29uc3RydWN0b3JbUFJPVE9UWVBFXSA9IGFuT2JqZWN0KE8pOwogIHJlc3VsdCA9IG5ldyBFbXB0eUNvbnN0cnVjdG9yKCk7CiAgRW1wdHlDb25zdHJ1Y3RvcltQUk9UT1RZUEVdID0gbnVsbDsKICByZXN1bHRbSUVfUFJPVE9dID0gTzsKIH0gZWxzZQogIHJlc3VsdCA9IE51bGxQcm90b09iamVjdCgpOwogcmV0dXJuIFByb3BlcnRpZXMgPT09IHVuZGVmaW5lZCA/IHJlc3VsdCA6IGRlZmluZVByb3BlcnRpZXNNb2R1bGUuZihyZXN1bHQsIFByb3BlcnRpZXMpOwp9OwoKLyoqKi8gfSksCi8qIDc1ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBERVNDUklQVE9SUyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTApOwp2YXIgVjhfUFJPVE9UWVBFX0RFRklORV9CVUcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDUwKTsKdmFyIGRlZmluZVByb3BlcnR5TW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXyg0OSk7CnZhciBhbk9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oNTEpOwp2YXIgdG9JbmRleGVkT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNik7CnZhciBvYmplY3RLZXlzID0gX193X3BkZmpzX3JlcXVpcmVfXyg3Nik7CmV4cG9ydHMuZiA9IERFU0NSSVBUT1JTICYmICFWOF9QUk9UT1RZUEVfREVGSU5FX0JVRyA/IE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzIDogZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyhPLCBQcm9wZXJ0aWVzKSB7CiBhbk9iamVjdChPKTsKIHZhciBwcm9wcyA9IHRvSW5kZXhlZE9iamVjdChQcm9wZXJ0aWVzKTsKIHZhciBrZXlzID0gb2JqZWN0S2V5cyhQcm9wZXJ0aWVzKTsKIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDsKIHZhciBpbmRleCA9IDA7CiB2YXIga2V5Owogd2hpbGUgKGxlbmd0aCA+IGluZGV4KQogIGRlZmluZVByb3BlcnR5TW9kdWxlLmYoTywga2V5ID0ga2V5c1tpbmRleCsrXSwgcHJvcHNba2V5XSk7CiByZXR1cm4gTzsKfTsKCi8qKiovIH0pLAovKiA3NiAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgaW50ZXJuYWxPYmplY3RLZXlzID0gX193X3BkZmpzX3JlcXVpcmVfXyg2Myk7CnZhciBlbnVtQnVnS2V5cyA9IF9fd19wZGZqc19yZXF1aXJlX18oNzApOwptb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5rZXlzIHx8IGZ1bmN0aW9uIGtleXMoTykgewogcmV0dXJuIGludGVybmFsT2JqZWN0S2V5cyhPLCBlbnVtQnVnS2V5cyk7Cn07CgovKioqLyB9KSwKLyogNzcgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGdldEJ1aWx0SW4gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI4KTsKbW9kdWxlLmV4cG9ydHMgPSBnZXRCdWlsdEluKCdkb2N1bWVudCcsICdkb2N1bWVudEVsZW1lbnQnKTsKCi8qKiovIH0pLAovKiA3OCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgZ2xvYmFsID0gX193X3BkZmpzX3JlcXVpcmVfXyg4KTsKdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxOCk7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKENPTlNUUlVDVE9SLCBNRVRIT0QpIHsKIHJldHVybiB1bmN1cnJ5VGhpcyhnbG9iYWxbQ09OU1RSVUNUT1JdLnByb3RvdHlwZVtNRVRIT0RdKTsKfTsKCi8qKiovIH0pLAovKiA3OSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCl9fd19wZGZqc19yZXF1aXJlX18oODApOwoKLyoqKi8gfSksCi8qIDgwICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKdmFyIEFycmF5QnVmZmVyVmlld0NvcmUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDgxKTsKdmFyIGxlbmd0aE9mQXJyYXlMaWtlID0gX193X3BkZmpzX3JlcXVpcmVfXyg2OCk7CnZhciB0b0ludGVnZXJPckluZmluaXR5ID0gX193X3BkZmpzX3JlcXVpcmVfXyg2Nik7CnZhciBhVHlwZWRBcnJheSA9IEFycmF5QnVmZmVyVmlld0NvcmUuYVR5cGVkQXJyYXk7CnZhciBleHBvcnRUeXBlZEFycmF5TWV0aG9kID0gQXJyYXlCdWZmZXJWaWV3Q29yZS5leHBvcnRUeXBlZEFycmF5TWV0aG9kOwpleHBvcnRUeXBlZEFycmF5TWV0aG9kKCdhdCcsIGZ1bmN0aW9uIGF0KGluZGV4KSB7CiB2YXIgTyA9IGFUeXBlZEFycmF5KHRoaXMpOwogdmFyIGxlbiA9IGxlbmd0aE9mQXJyYXlMaWtlKE8pOwogdmFyIHJlbGF0aXZlSW5kZXggPSB0b0ludGVnZXJPckluZmluaXR5KGluZGV4KTsKIHZhciBrID0gcmVsYXRpdmVJbmRleCA+PSAwID8gcmVsYXRpdmVJbmRleCA6IGxlbiArIHJlbGF0aXZlSW5kZXg7CiByZXR1cm4gayA8IDAgfHwgayA+PSBsZW4gPyB1bmRlZmluZWQgOiBPW2tdOwp9KTsKCi8qKiovIH0pLAovKiA4MSAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7Cgp2YXIgTkFUSVZFX0FSUkFZX0JVRkZFUiA9IF9fd19wZGZqc19yZXF1aXJlX18oODIpOwp2YXIgREVTQ1JJUFRPUlMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwKTsKdmFyIGdsb2JhbCA9IF9fd19wZGZqc19yZXF1aXJlX18oOCk7CnZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNSk7CnZhciBpc09iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjQpOwp2YXIgaGFzT3duID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Myk7CnZhciBjbGFzc29mID0gX193X3BkZmpzX3JlcXVpcmVfXyg4Myk7CnZhciB0cnlUb1N0cmluZyA9IF9fd19wZGZqc19yZXF1aXJlX18oMzYpOwp2YXIgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5ID0gX193X3BkZmpzX3JlcXVpcmVfXyg0OCk7CnZhciBkZWZpbmVCdWlsdEluID0gX193X3BkZmpzX3JlcXVpcmVfXyg1Mik7CnZhciBkZWZpbmVCdWlsdEluQWNjZXNzb3IgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDg1KTsKdmFyIGlzUHJvdG90eXBlT2YgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI5KTsKdmFyIGdldFByb3RvdHlwZU9mID0gX193X3BkZmpzX3JlcXVpcmVfXyg4Nik7CnZhciBzZXRQcm90b3R5cGVPZiA9IF9fd19wZGZqc19yZXF1aXJlX18oODgpOwp2YXIgd2VsbEtub3duU3ltYm9sID0gX193X3BkZmpzX3JlcXVpcmVfXygzOCk7CnZhciB1aWQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ1KTsKdmFyIEludGVybmFsU3RhdGVNb2R1bGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDU2KTsKdmFyIGVuZm9yY2VJbnRlcm5hbFN0YXRlID0gSW50ZXJuYWxTdGF0ZU1vZHVsZS5lbmZvcmNlOwp2YXIgZ2V0SW50ZXJuYWxTdGF0ZSA9IEludGVybmFsU3RhdGVNb2R1bGUuZ2V0Owp2YXIgSW50OEFycmF5ID0gZ2xvYmFsLkludDhBcnJheTsKdmFyIEludDhBcnJheVByb3RvdHlwZSA9IEludDhBcnJheSAmJiBJbnQ4QXJyYXkucHJvdG90eXBlOwp2YXIgVWludDhDbGFtcGVkQXJyYXkgPSBnbG9iYWwuVWludDhDbGFtcGVkQXJyYXk7CnZhciBVaW50OENsYW1wZWRBcnJheVByb3RvdHlwZSA9IFVpbnQ4Q2xhbXBlZEFycmF5ICYmIFVpbnQ4Q2xhbXBlZEFycmF5LnByb3RvdHlwZTsKdmFyIFR5cGVkQXJyYXkgPSBJbnQ4QXJyYXkgJiYgZ2V0UHJvdG90eXBlT2YoSW50OEFycmF5KTsKdmFyIFR5cGVkQXJyYXlQcm90b3R5cGUgPSBJbnQ4QXJyYXlQcm90b3R5cGUgJiYgZ2V0UHJvdG90eXBlT2YoSW50OEFycmF5UHJvdG90eXBlKTsKdmFyIE9iamVjdFByb3RvdHlwZSA9IE9iamVjdC5wcm90b3R5cGU7CnZhciBUeXBlRXJyb3IgPSBnbG9iYWwuVHlwZUVycm9yOwp2YXIgVE9fU1RSSU5HX1RBRyA9IHdlbGxLbm93blN5bWJvbCgndG9TdHJpbmdUYWcnKTsKdmFyIFRZUEVEX0FSUkFZX1RBRyA9IHVpZCgnVFlQRURfQVJSQVlfVEFHJyk7CnZhciBUWVBFRF9BUlJBWV9DT05TVFJVQ1RPUiA9ICdUeXBlZEFycmF5Q29uc3RydWN0b3InOwp2YXIgTkFUSVZFX0FSUkFZX0JVRkZFUl9WSUVXUyA9IE5BVElWRV9BUlJBWV9CVUZGRVIgJiYgISFzZXRQcm90b3R5cGVPZiAmJiBjbGFzc29mKGdsb2JhbC5vcGVyYSkgIT09ICdPcGVyYSc7CnZhciBUWVBFRF9BUlJBWV9UQUdfUkVRVUlSRUQgPSBmYWxzZTsKdmFyIE5BTUUsIENvbnN0cnVjdG9yLCBQcm90b3R5cGU7CnZhciBUeXBlZEFycmF5Q29uc3RydWN0b3JzTGlzdCA9IHsKIEludDhBcnJheTogMSwKIFVpbnQ4QXJyYXk6IDEsCiBVaW50OENsYW1wZWRBcnJheTogMSwKIEludDE2QXJyYXk6IDIsCiBVaW50MTZBcnJheTogMiwKIEludDMyQXJyYXk6IDQsCiBVaW50MzJBcnJheTogNCwKIEZsb2F0MzJBcnJheTogNCwKIEZsb2F0NjRBcnJheTogOAp9Owp2YXIgQmlnSW50QXJyYXlDb25zdHJ1Y3RvcnNMaXN0ID0gewogQmlnSW50NjRBcnJheTogOCwKIEJpZ1VpbnQ2NEFycmF5OiA4Cn07CnZhciBpc1ZpZXcgPSBmdW5jdGlvbiBpc1ZpZXcoaXQpIHsKIGlmICghaXNPYmplY3QoaXQpKQogIHJldHVybiBmYWxzZTsKIHZhciBrbGFzcyA9IGNsYXNzb2YoaXQpOwogcmV0dXJuIGtsYXNzID09PSAnRGF0YVZpZXcnIHx8IGhhc093bihUeXBlZEFycmF5Q29uc3RydWN0b3JzTGlzdCwga2xhc3MpIHx8IGhhc093bihCaWdJbnRBcnJheUNvbnN0cnVjdG9yc0xpc3QsIGtsYXNzKTsKfTsKdmFyIGdldFR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IGZ1bmN0aW9uIChpdCkgewogdmFyIHByb3RvID0gZ2V0UHJvdG90eXBlT2YoaXQpOwogaWYgKCFpc09iamVjdChwcm90bykpCiAgcmV0dXJuOwogdmFyIHN0YXRlID0gZ2V0SW50ZXJuYWxTdGF0ZShwcm90byk7CiByZXR1cm4gc3RhdGUgJiYgaGFzT3duKHN0YXRlLCBUWVBFRF9BUlJBWV9DT05TVFJVQ1RPUikgPyBzdGF0ZVtUWVBFRF9BUlJBWV9DT05TVFJVQ1RPUl0gOiBnZXRUeXBlZEFycmF5Q29uc3RydWN0b3IocHJvdG8pOwp9Owp2YXIgaXNUeXBlZEFycmF5ID0gZnVuY3Rpb24gKGl0KSB7CiBpZiAoIWlzT2JqZWN0KGl0KSkKICByZXR1cm4gZmFsc2U7CiB2YXIga2xhc3MgPSBjbGFzc29mKGl0KTsKIHJldHVybiBoYXNPd24oVHlwZWRBcnJheUNvbnN0cnVjdG9yc0xpc3QsIGtsYXNzKSB8fCBoYXNPd24oQmlnSW50QXJyYXlDb25zdHJ1Y3RvcnNMaXN0LCBrbGFzcyk7Cn07CnZhciBhVHlwZWRBcnJheSA9IGZ1bmN0aW9uIChpdCkgewogaWYgKGlzVHlwZWRBcnJheShpdCkpCiAgcmV0dXJuIGl0OwogdGhyb3cgVHlwZUVycm9yKCdUYXJnZXQgaXMgbm90IGEgdHlwZWQgYXJyYXknKTsKfTsKdmFyIGFUeXBlZEFycmF5Q29uc3RydWN0b3IgPSBmdW5jdGlvbiAoQykgewogaWYgKGlzQ2FsbGFibGUoQykgJiYgKCFzZXRQcm90b3R5cGVPZiB8fCBpc1Byb3RvdHlwZU9mKFR5cGVkQXJyYXksIEMpKSkKICByZXR1cm4gQzsKIHRocm93IFR5cGVFcnJvcih0cnlUb1N0cmluZyhDKSArICcgaXMgbm90IGEgdHlwZWQgYXJyYXkgY29uc3RydWN0b3InKTsKfTsKdmFyIGV4cG9ydFR5cGVkQXJyYXlNZXRob2QgPSBmdW5jdGlvbiAoS0VZLCBwcm9wZXJ0eSwgZm9yY2VkLCBvcHRpb25zKSB7CiBpZiAoIURFU0NSSVBUT1JTKQogIHJldHVybjsKIGlmIChmb3JjZWQpCiAgZm9yICh2YXIgQVJSQVkgaW4gVHlwZWRBcnJheUNvbnN0cnVjdG9yc0xpc3QpIHsKICAgdmFyIFR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IGdsb2JhbFtBUlJBWV07CiAgIGlmIChUeXBlZEFycmF5Q29uc3RydWN0b3IgJiYgaGFzT3duKFR5cGVkQXJyYXlDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIEtFWSkpCiAgICB0cnkgewogICAgIGRlbGV0ZSBUeXBlZEFycmF5Q29uc3RydWN0b3IucHJvdG90eXBlW0tFWV07CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgIHRyeSB7CiAgICAgIFR5cGVkQXJyYXlDb25zdHJ1Y3Rvci5wcm90b3R5cGVbS0VZXSA9IHByb3BlcnR5OwogICAgIH0gY2F0Y2ggKGVycm9yMikgewogICAgIH0KICAgIH0KICB9CiBpZiAoIVR5cGVkQXJyYXlQcm90b3R5cGVbS0VZXSB8fCBmb3JjZWQpIHsKICBkZWZpbmVCdWlsdEluKFR5cGVkQXJyYXlQcm90b3R5cGUsIEtFWSwgZm9yY2VkID8gcHJvcGVydHkgOiBOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTICYmIEludDhBcnJheVByb3RvdHlwZVtLRVldIHx8IHByb3BlcnR5LCBvcHRpb25zKTsKIH0KfTsKdmFyIGV4cG9ydFR5cGVkQXJyYXlTdGF0aWNNZXRob2QgPSBmdW5jdGlvbiAoS0VZLCBwcm9wZXJ0eSwgZm9yY2VkKSB7CiB2YXIgQVJSQVksIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcjsKIGlmICghREVTQ1JJUFRPUlMpCiAgcmV0dXJuOwogaWYgKHNldFByb3RvdHlwZU9mKSB7CiAgaWYgKGZvcmNlZCkKICAgZm9yIChBUlJBWSBpbiBUeXBlZEFycmF5Q29uc3RydWN0b3JzTGlzdCkgewogICAgVHlwZWRBcnJheUNvbnN0cnVjdG9yID0gZ2xvYmFsW0FSUkFZXTsKICAgIGlmIChUeXBlZEFycmF5Q29uc3RydWN0b3IgJiYgaGFzT3duKFR5cGVkQXJyYXlDb25zdHJ1Y3RvciwgS0VZKSkKICAgICB0cnkgewogICAgICBkZWxldGUgVHlwZWRBcnJheUNvbnN0cnVjdG9yW0tFWV07CiAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICB9CiAgIH0KICBpZiAoIVR5cGVkQXJyYXlbS0VZXSB8fCBmb3JjZWQpIHsKICAgdHJ5IHsKICAgIHJldHVybiBkZWZpbmVCdWlsdEluKFR5cGVkQXJyYXksIEtFWSwgZm9yY2VkID8gcHJvcGVydHkgOiBOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTICYmIFR5cGVkQXJyYXlbS0VZXSB8fCBwcm9wZXJ0eSk7CiAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgIH0KICB9IGVsc2UKICAgcmV0dXJuOwogfQogZm9yIChBUlJBWSBpbiBUeXBlZEFycmF5Q29uc3RydWN0b3JzTGlzdCkgewogIFR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IGdsb2JhbFtBUlJBWV07CiAgaWYgKFR5cGVkQXJyYXlDb25zdHJ1Y3RvciAmJiAoIVR5cGVkQXJyYXlDb25zdHJ1Y3RvcltLRVldIHx8IGZvcmNlZCkpIHsKICAgZGVmaW5lQnVpbHRJbihUeXBlZEFycmF5Q29uc3RydWN0b3IsIEtFWSwgcHJvcGVydHkpOwogIH0KIH0KfTsKZm9yIChOQU1FIGluIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnNMaXN0KSB7CiBDb25zdHJ1Y3RvciA9IGdsb2JhbFtOQU1FXTsKIFByb3RvdHlwZSA9IENvbnN0cnVjdG9yICYmIENvbnN0cnVjdG9yLnByb3RvdHlwZTsKIGlmIChQcm90b3R5cGUpCiAgZW5mb3JjZUludGVybmFsU3RhdGUoUHJvdG90eXBlKVtUWVBFRF9BUlJBWV9DT05TVFJVQ1RPUl0gPSBDb25zdHJ1Y3RvcjsKIGVsc2UKICBOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTID0gZmFsc2U7Cn0KZm9yIChOQU1FIGluIEJpZ0ludEFycmF5Q29uc3RydWN0b3JzTGlzdCkgewogQ29uc3RydWN0b3IgPSBnbG9iYWxbTkFNRV07CiBQcm90b3R5cGUgPSBDb25zdHJ1Y3RvciAmJiBDb25zdHJ1Y3Rvci5wcm90b3R5cGU7CiBpZiAoUHJvdG90eXBlKQogIGVuZm9yY2VJbnRlcm5hbFN0YXRlKFByb3RvdHlwZSlbVFlQRURfQVJSQVlfQ09OU1RSVUNUT1JdID0gQ29uc3RydWN0b3I7Cn0KaWYgKCFOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTIHx8ICFpc0NhbGxhYmxlKFR5cGVkQXJyYXkpIHx8IFR5cGVkQXJyYXkgPT09IEZ1bmN0aW9uLnByb3RvdHlwZSkgewogVHlwZWRBcnJheSA9IGZ1bmN0aW9uIFR5cGVkQXJyYXkoKSB7CiAgdGhyb3cgVHlwZUVycm9yKCdJbmNvcnJlY3QgaW52b2NhdGlvbicpOwogfTsKIGlmIChOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTKQogIGZvciAoTkFNRSBpbiBUeXBlZEFycmF5Q29uc3RydWN0b3JzTGlzdCkgewogICBpZiAoZ2xvYmFsW05BTUVdKQogICAgc2V0UHJvdG90eXBlT2YoZ2xvYmFsW05BTUVdLCBUeXBlZEFycmF5KTsKICB9Cn0KaWYgKCFOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTIHx8ICFUeXBlZEFycmF5UHJvdG90eXBlIHx8IFR5cGVkQXJyYXlQcm90b3R5cGUgPT09IE9iamVjdFByb3RvdHlwZSkgewogVHlwZWRBcnJheVByb3RvdHlwZSA9IFR5cGVkQXJyYXkucHJvdG90eXBlOwogaWYgKE5BVElWRV9BUlJBWV9CVUZGRVJfVklFV1MpCiAgZm9yIChOQU1FIGluIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnNMaXN0KSB7CiAgIGlmIChnbG9iYWxbTkFNRV0pCiAgICBzZXRQcm90b3R5cGVPZihnbG9iYWxbTkFNRV0ucHJvdG90eXBlLCBUeXBlZEFycmF5UHJvdG90eXBlKTsKICB9Cn0KaWYgKE5BVElWRV9BUlJBWV9CVUZGRVJfVklFV1MgJiYgZ2V0UHJvdG90eXBlT2YoVWludDhDbGFtcGVkQXJyYXlQcm90b3R5cGUpICE9PSBUeXBlZEFycmF5UHJvdG90eXBlKSB7CiBzZXRQcm90b3R5cGVPZihVaW50OENsYW1wZWRBcnJheVByb3RvdHlwZSwgVHlwZWRBcnJheVByb3RvdHlwZSk7Cn0KaWYgKERFU0NSSVBUT1JTICYmICFoYXNPd24oVHlwZWRBcnJheVByb3RvdHlwZSwgVE9fU1RSSU5HX1RBRykpIHsKIFRZUEVEX0FSUkFZX1RBR19SRVFVSVJFRCA9IHRydWU7CiBkZWZpbmVCdWlsdEluQWNjZXNzb3IoVHlwZWRBcnJheVByb3RvdHlwZSwgVE9fU1RSSU5HX1RBRywgewogIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICBnZXQ6IGZ1bmN0aW9uICgpIHsKICAgcmV0dXJuIGlzT2JqZWN0KHRoaXMpID8gdGhpc1tUWVBFRF9BUlJBWV9UQUddIDogdW5kZWZpbmVkOwogIH0KIH0pOwogZm9yIChOQU1FIGluIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnNMaXN0KQogIGlmIChnbG9iYWxbTkFNRV0pIHsKICAgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KGdsb2JhbFtOQU1FXSwgVFlQRURfQVJSQVlfVEFHLCBOQU1FKTsKICB9Cn0KbW9kdWxlLmV4cG9ydHMgPSB7CiBOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTOiBOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTLAogVFlQRURfQVJSQVlfVEFHOiBUWVBFRF9BUlJBWV9UQUdfUkVRVUlSRUQgJiYgVFlQRURfQVJSQVlfVEFHLAogYVR5cGVkQXJyYXk6IGFUeXBlZEFycmF5LAogYVR5cGVkQXJyYXlDb25zdHJ1Y3RvcjogYVR5cGVkQXJyYXlDb25zdHJ1Y3RvciwKIGV4cG9ydFR5cGVkQXJyYXlNZXRob2Q6IGV4cG9ydFR5cGVkQXJyYXlNZXRob2QsCiBleHBvcnRUeXBlZEFycmF5U3RhdGljTWV0aG9kOiBleHBvcnRUeXBlZEFycmF5U3RhdGljTWV0aG9kLAogZ2V0VHlwZWRBcnJheUNvbnN0cnVjdG9yOiBnZXRUeXBlZEFycmF5Q29uc3RydWN0b3IsCiBpc1ZpZXc6IGlzVmlldywKIGlzVHlwZWRBcnJheTogaXNUeXBlZEFycmF5LAogVHlwZWRBcnJheTogVHlwZWRBcnJheSwKIFR5cGVkQXJyYXlQcm90b3R5cGU6IFR5cGVkQXJyYXlQcm90b3R5cGUKfTsKCi8qKiovIH0pLAovKiA4MiAqLwovKioqLyAoKG1vZHVsZSkgPT4gewoKbW9kdWxlLmV4cG9ydHMgPSB0eXBlb2YgQXJyYXlCdWZmZXIgIT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIERhdGFWaWV3ICE9ICd1bmRlZmluZWQnOwoKLyoqKi8gfSksCi8qIDgzICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBUT19TVFJJTkdfVEFHX1NVUFBPUlQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDg0KTsKdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI1KTsKdmFyIGNsYXNzb2ZSYXcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE5KTsKdmFyIHdlbGxLbm93blN5bWJvbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMzgpOwp2YXIgVE9fU1RSSU5HX1RBRyA9IHdlbGxLbm93blN5bWJvbCgndG9TdHJpbmdUYWcnKTsKdmFyICRPYmplY3QgPSBPYmplY3Q7CnZhciBDT1JSRUNUX0FSR1VNRU5UUyA9IGNsYXNzb2ZSYXcoKGZ1bmN0aW9uICgpIHsKIHJldHVybiBhcmd1bWVudHM7Cn0oKSkpID09ICdBcmd1bWVudHMnOwp2YXIgdHJ5R2V0ID0gZnVuY3Rpb24gKGl0LCBrZXkpIHsKIHRyeSB7CiAgcmV0dXJuIGl0W2tleV07CiB9IGNhdGNoIChlcnJvcikgewogfQp9Owptb2R1bGUuZXhwb3J0cyA9IFRPX1NUUklOR19UQUdfU1VQUE9SVCA/IGNsYXNzb2ZSYXcgOiBmdW5jdGlvbiAoaXQpIHsKIHZhciBPLCB0YWcsIHJlc3VsdDsKIHJldHVybiBpdCA9PT0gdW5kZWZpbmVkID8gJ1VuZGVmaW5lZCcgOiBpdCA9PT0gbnVsbCA/ICdOdWxsJyA6IHR5cGVvZiAodGFnID0gdHJ5R2V0KE8gPSAkT2JqZWN0KGl0KSwgVE9fU1RSSU5HX1RBRykpID09ICdzdHJpbmcnID8gdGFnIDogQ09SUkVDVF9BUkdVTUVOVFMgPyBjbGFzc29mUmF3KE8pIDogKHJlc3VsdCA9IGNsYXNzb2ZSYXcoTykpID09ICdPYmplY3QnICYmIGlzQ2FsbGFibGUoTy5jYWxsZWUpID8gJ0FyZ3VtZW50cycgOiByZXN1bHQ7Cn07CgovKioqLyB9KSwKLyogODQgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIHdlbGxLbm93blN5bWJvbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMzgpOwp2YXIgVE9fU1RSSU5HX1RBRyA9IHdlbGxLbm93blN5bWJvbCgndG9TdHJpbmdUYWcnKTsKdmFyIHRlc3QgPSB7fTsKdGVzdFtUT19TVFJJTkdfVEFHXSA9ICd6JzsKbW9kdWxlLmV4cG9ydHMgPSBTdHJpbmcodGVzdCkgPT09ICdbb2JqZWN0IHpdJzsKCi8qKiovIH0pLAovKiA4NSAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgbWFrZUJ1aWx0SW4gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDUzKTsKdmFyIGRlZmluZVByb3BlcnR5ID0gX193X3BkZmpzX3JlcXVpcmVfXyg0OSk7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHRhcmdldCwgbmFtZSwgZGVzY3JpcHRvcikgewogaWYgKGRlc2NyaXB0b3IuZ2V0KQogIG1ha2VCdWlsdEluKGRlc2NyaXB0b3IuZ2V0LCBuYW1lLCB7IGdldHRlcjogdHJ1ZSB9KTsKIGlmIChkZXNjcmlwdG9yLnNldCkKICBtYWtlQnVpbHRJbihkZXNjcmlwdG9yLnNldCwgbmFtZSwgeyBzZXR0ZXI6IHRydWUgfSk7CiByZXR1cm4gZGVmaW5lUHJvcGVydHkuZih0YXJnZXQsIG5hbWUsIGRlc2NyaXB0b3IpOwp9OwoKLyoqKi8gfSksCi8qIDg2ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBoYXNPd24gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQzKTsKdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI1KTsKdmFyIHRvT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXyg0NCk7CnZhciBzaGFyZWRLZXkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDU4KTsKdmFyIENPUlJFQ1RfUFJPVE9UWVBFX0dFVFRFUiA9IF9fd19wZGZqc19yZXF1aXJlX18oODcpOwp2YXIgSUVfUFJPVE8gPSBzaGFyZWRLZXkoJ0lFX1BST1RPJyk7CnZhciAkT2JqZWN0ID0gT2JqZWN0Owp2YXIgT2JqZWN0UHJvdG90eXBlID0gJE9iamVjdC5wcm90b3R5cGU7Cm1vZHVsZS5leHBvcnRzID0gQ09SUkVDVF9QUk9UT1RZUEVfR0VUVEVSID8gJE9iamVjdC5nZXRQcm90b3R5cGVPZiA6IGZ1bmN0aW9uIChPKSB7CiB2YXIgb2JqZWN0ID0gdG9PYmplY3QoTyk7CiBpZiAoaGFzT3duKG9iamVjdCwgSUVfUFJPVE8pKQogIHJldHVybiBvYmplY3RbSUVfUFJPVE9dOwogdmFyIGNvbnN0cnVjdG9yID0gb2JqZWN0LmNvbnN0cnVjdG9yOwogaWYgKGlzQ2FsbGFibGUoY29uc3RydWN0b3IpICYmIG9iamVjdCBpbnN0YW5jZW9mIGNvbnN0cnVjdG9yKSB7CiAgcmV0dXJuIGNvbnN0cnVjdG9yLnByb3RvdHlwZTsKIH0KIHJldHVybiBvYmplY3QgaW5zdGFuY2VvZiAkT2JqZWN0ID8gT2JqZWN0UHJvdG90eXBlIDogbnVsbDsKfTsKCi8qKiovIH0pLAovKiA4NyAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExKTsKbW9kdWxlLmV4cG9ydHMgPSAhZmFpbHMoZnVuY3Rpb24gKCkgewogZnVuY3Rpb24gRigpIHsKIH0KIEYucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gbnVsbDsKIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YobmV3IEYoKSkgIT09IEYucHJvdG90eXBlOwp9KTsKCi8qKiovIH0pLAovKiA4OCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgdW5jdXJyeVRoaXNBY2Nlc3NvciA9IF9fd19wZGZqc19yZXF1aXJlX18oODkpOwp2YXIgYW5PYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDUxKTsKdmFyIGFQb3NzaWJsZVByb3RvdHlwZSA9IF9fd19wZGZqc19yZXF1aXJlX18oOTApOwptb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCAoJ19fcHJvdG9fXycgaW4ge30gPyAoZnVuY3Rpb24gKCkgewogdmFyIENPUlJFQ1RfU0VUVEVSID0gZmFsc2U7CiB2YXIgdGVzdCA9IHt9OwogdmFyIHNldHRlcjsKIHRyeSB7CiAgc2V0dGVyID0gdW5jdXJyeVRoaXNBY2Nlc3NvcihPYmplY3QucHJvdG90eXBlLCAnX19wcm90b19fJywgJ3NldCcpOwogIHNldHRlcih0ZXN0LCBbXSk7CiAgQ09SUkVDVF9TRVRURVIgPSB0ZXN0IGluc3RhbmNlb2YgQXJyYXk7CiB9IGNhdGNoIChlcnJvcikgewogfQogcmV0dXJuIGZ1bmN0aW9uIHNldFByb3RvdHlwZU9mKE8sIHByb3RvKSB7CiAgYW5PYmplY3QoTyk7CiAgYVBvc3NpYmxlUHJvdG90eXBlKHByb3RvKTsKICBpZiAoQ09SUkVDVF9TRVRURVIpCiAgIHNldHRlcihPLCBwcm90byk7CiAgZWxzZQogICBPLl9fcHJvdG9fXyA9IHByb3RvOwogIHJldHVybiBPOwogfTsKfSgpKSA6IHVuZGVmaW5lZCk7CgovKioqLyB9KSwKLyogODkgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxOCk7CnZhciBhQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM1KTsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqZWN0LCBrZXksIG1ldGhvZCkgewogdHJ5IHsKICByZXR1cm4gdW5jdXJyeVRoaXMoYUNhbGxhYmxlKE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBrZXkpW21ldGhvZF0pKTsKIH0gY2F0Y2ggKGVycm9yKSB7CiB9Cn07CgovKioqLyB9KSwKLyogOTAgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI1KTsKdmFyICRTdHJpbmcgPSBTdHJpbmc7CnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCkgewogaWYgKHR5cGVvZiBhcmd1bWVudCA9PSAnb2JqZWN0JyB8fCBpc0NhbGxhYmxlKGFyZ3VtZW50KSkKICByZXR1cm4gYXJndW1lbnQ7CiB0aHJvdyAkVHlwZUVycm9yKCJDYW4ndCBzZXQgIiArICRTdHJpbmcoYXJndW1lbnQpICsgJyBhcyBhIHByb3RvdHlwZScpOwp9OwoKLyoqKi8gfSksCi8qIDkxICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCl9fd19wZGZqc19yZXF1aXJlX18oOTIpOwpfX3dfcGRmanNfcmVxdWlyZV9fKDk5KTsKX193X3BkZmpzX3JlcXVpcmVfXygxMDEpOwpfX3dfcGRmanNfcmVxdWlyZV9fKDEyNCk7Cl9fd19wZGZqc19yZXF1aXJlX18oMTI2KTsKdmFyIHBhdGggPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzOCk7Cm1vZHVsZS5leHBvcnRzID0gcGF0aC5zdHJ1Y3R1cmVkQ2xvbmU7CgovKioqLyB9KSwKLyogOTIgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKdmFyIHRvSW5kZXhlZE9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTYpOwp2YXIgYWRkVG9VbnNjb3BhYmxlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oNzMpOwp2YXIgSXRlcmF0b3JzID0gX193X3BkZmpzX3JlcXVpcmVfXyg5Myk7CnZhciBJbnRlcm5hbFN0YXRlTW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXyg1Nik7CnZhciBkZWZpbmVQcm9wZXJ0eSA9IChfX3dfcGRmanNfcmVxdWlyZV9fKDQ5KS5mKTsKdmFyIGRlZmluZUl0ZXJhdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXyg5NCk7CnZhciBjcmVhdGVJdGVyUmVzdWx0T2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXyg5OCk7CnZhciBJU19QVVJFID0gX193X3BkZmpzX3JlcXVpcmVfXyg0MCk7CnZhciBERVNDUklQVE9SUyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTApOwp2YXIgQVJSQVlfSVRFUkFUT1IgPSAnQXJyYXkgSXRlcmF0b3InOwp2YXIgc2V0SW50ZXJuYWxTdGF0ZSA9IEludGVybmFsU3RhdGVNb2R1bGUuc2V0Owp2YXIgZ2V0SW50ZXJuYWxTdGF0ZSA9IEludGVybmFsU3RhdGVNb2R1bGUuZ2V0dGVyRm9yKEFSUkFZX0lURVJBVE9SKTsKbW9kdWxlLmV4cG9ydHMgPSBkZWZpbmVJdGVyYXRvcihBcnJheSwgJ0FycmF5JywgZnVuY3Rpb24gKGl0ZXJhdGVkLCBraW5kKSB7CiBzZXRJbnRlcm5hbFN0YXRlKHRoaXMsIHsKICB0eXBlOiBBUlJBWV9JVEVSQVRPUiwKICB0YXJnZXQ6IHRvSW5kZXhlZE9iamVjdChpdGVyYXRlZCksCiAgaW5kZXg6IDAsCiAga2luZDoga2luZAogfSk7Cn0sIGZ1bmN0aW9uICgpIHsKIHZhciBzdGF0ZSA9IGdldEludGVybmFsU3RhdGUodGhpcyk7CiB2YXIgdGFyZ2V0ID0gc3RhdGUudGFyZ2V0OwogdmFyIGtpbmQgPSBzdGF0ZS5raW5kOwogdmFyIGluZGV4ID0gc3RhdGUuaW5kZXgrKzsKIGlmICghdGFyZ2V0IHx8IGluZGV4ID49IHRhcmdldC5sZW5ndGgpIHsKICBzdGF0ZS50YXJnZXQgPSB1bmRlZmluZWQ7CiAgcmV0dXJuIGNyZWF0ZUl0ZXJSZXN1bHRPYmplY3QodW5kZWZpbmVkLCB0cnVlKTsKIH0KIGlmIChraW5kID09ICdrZXlzJykKICByZXR1cm4gY3JlYXRlSXRlclJlc3VsdE9iamVjdChpbmRleCwgZmFsc2UpOwogaWYgKGtpbmQgPT0gJ3ZhbHVlcycpCiAgcmV0dXJuIGNyZWF0ZUl0ZXJSZXN1bHRPYmplY3QodGFyZ2V0W2luZGV4XSwgZmFsc2UpOwogcmV0dXJuIGNyZWF0ZUl0ZXJSZXN1bHRPYmplY3QoWwogIGluZGV4LAogIHRhcmdldFtpbmRleF0KIF0sIGZhbHNlKTsKfSwgJ3ZhbHVlcycpOwp2YXIgdmFsdWVzID0gSXRlcmF0b3JzLkFyZ3VtZW50cyA9IEl0ZXJhdG9ycy5BcnJheTsKYWRkVG9VbnNjb3BhYmxlcygna2V5cycpOwphZGRUb1Vuc2NvcGFibGVzKCd2YWx1ZXMnKTsKYWRkVG9VbnNjb3BhYmxlcygnZW50cmllcycpOwppZiAoIUlTX1BVUkUgJiYgREVTQ1JJUFRPUlMgJiYgdmFsdWVzLm5hbWUgIT09ICd2YWx1ZXMnKQogdHJ5IHsKICBkZWZpbmVQcm9wZXJ0eSh2YWx1ZXMsICduYW1lJywgeyB2YWx1ZTogJ3ZhbHVlcycgfSk7CiB9IGNhdGNoIChlcnJvcikgewogfQoKLyoqKi8gfSksCi8qIDkzICovCi8qKiovICgobW9kdWxlKSA9PiB7Cgptb2R1bGUuZXhwb3J0cyA9IHt9OwoKLyoqKi8gfSksCi8qIDk0ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCnZhciAkID0gX193X3BkZmpzX3JlcXVpcmVfXyg3KTsKdmFyIGNhbGwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyKTsKdmFyIElTX1BVUkUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQwKTsKdmFyIEZ1bmN0aW9uTmFtZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNTQpOwp2YXIgaXNDYWxsYWJsZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjUpOwp2YXIgY3JlYXRlSXRlcmF0b3JDb25zdHJ1Y3RvciA9IF9fd19wZGZqc19yZXF1aXJlX18oOTUpOwp2YXIgZ2V0UHJvdG90eXBlT2YgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDg2KTsKdmFyIHNldFByb3RvdHlwZU9mID0gX193X3BkZmpzX3JlcXVpcmVfXyg4OCk7CnZhciBzZXRUb1N0cmluZ1RhZyA9IF9fd19wZGZqc19yZXF1aXJlX18oOTcpOwp2YXIgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5ID0gX193X3BkZmpzX3JlcXVpcmVfXyg0OCk7CnZhciBkZWZpbmVCdWlsdEluID0gX193X3BkZmpzX3JlcXVpcmVfXyg1Mik7CnZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM4KTsKdmFyIEl0ZXJhdG9ycyA9IF9fd19wZGZqc19yZXF1aXJlX18oOTMpOwp2YXIgSXRlcmF0b3JzQ29yZSA9IF9fd19wZGZqc19yZXF1aXJlX18oOTYpOwp2YXIgUFJPUEVSX0ZVTkNUSU9OX05BTUUgPSBGdW5jdGlvbk5hbWUuUFJPUEVSOwp2YXIgQ09ORklHVVJBQkxFX0ZVTkNUSU9OX05BTUUgPSBGdW5jdGlvbk5hbWUuQ09ORklHVVJBQkxFOwp2YXIgSXRlcmF0b3JQcm90b3R5cGUgPSBJdGVyYXRvcnNDb3JlLkl0ZXJhdG9yUHJvdG90eXBlOwp2YXIgQlVHR1lfU0FGQVJJX0lURVJBVE9SUyA9IEl0ZXJhdG9yc0NvcmUuQlVHR1lfU0FGQVJJX0lURVJBVE9SUzsKdmFyIElURVJBVE9SID0gd2VsbEtub3duU3ltYm9sKCdpdGVyYXRvcicpOwp2YXIgS0VZUyA9ICdrZXlzJzsKdmFyIFZBTFVFUyA9ICd2YWx1ZXMnOwp2YXIgRU5UUklFUyA9ICdlbnRyaWVzJzsKdmFyIHJldHVyblRoaXMgPSBmdW5jdGlvbiAoKSB7CiByZXR1cm4gdGhpczsKfTsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoSXRlcmFibGUsIE5BTUUsIEl0ZXJhdG9yQ29uc3RydWN0b3IsIG5leHQsIERFRkFVTFQsIElTX1NFVCwgRk9SQ0VEKSB7CiBjcmVhdGVJdGVyYXRvckNvbnN0cnVjdG9yKEl0ZXJhdG9yQ29uc3RydWN0b3IsIE5BTUUsIG5leHQpOwogdmFyIGdldEl0ZXJhdGlvbk1ldGhvZCA9IGZ1bmN0aW9uIChLSU5EKSB7CiAgaWYgKEtJTkQgPT09IERFRkFVTFQgJiYgZGVmYXVsdEl0ZXJhdG9yKQogICByZXR1cm4gZGVmYXVsdEl0ZXJhdG9yOwogIGlmICghQlVHR1lfU0FGQVJJX0lURVJBVE9SUyAmJiBLSU5EIGluIEl0ZXJhYmxlUHJvdG90eXBlKQogICByZXR1cm4gSXRlcmFibGVQcm90b3R5cGVbS0lORF07CiAgc3dpdGNoIChLSU5EKSB7CiAgY2FzZSBLRVlTOgogICByZXR1cm4gZnVuY3Rpb24ga2V5cygpIHsKICAgIHJldHVybiBuZXcgSXRlcmF0b3JDb25zdHJ1Y3Rvcih0aGlzLCBLSU5EKTsKICAgfTsKICBjYXNlIFZBTFVFUzoKICAgcmV0dXJuIGZ1bmN0aW9uIHZhbHVlcygpIHsKICAgIHJldHVybiBuZXcgSXRlcmF0b3JDb25zdHJ1Y3Rvcih0aGlzLCBLSU5EKTsKICAgfTsKICBjYXNlIEVOVFJJRVM6CiAgIHJldHVybiBmdW5jdGlvbiBlbnRyaWVzKCkgewogICAgcmV0dXJuIG5ldyBJdGVyYXRvckNvbnN0cnVjdG9yKHRoaXMsIEtJTkQpOwogICB9OwogIH0KICByZXR1cm4gZnVuY3Rpb24gKCkgewogICByZXR1cm4gbmV3IEl0ZXJhdG9yQ29uc3RydWN0b3IodGhpcyk7CiAgfTsKIH07CiB2YXIgVE9fU1RSSU5HX1RBRyA9IE5BTUUgKyAnIEl0ZXJhdG9yJzsKIHZhciBJTkNPUlJFQ1RfVkFMVUVTX05BTUUgPSBmYWxzZTsKIHZhciBJdGVyYWJsZVByb3RvdHlwZSA9IEl0ZXJhYmxlLnByb3RvdHlwZTsKIHZhciBuYXRpdmVJdGVyYXRvciA9IEl0ZXJhYmxlUHJvdG90eXBlW0lURVJBVE9SXSB8fCBJdGVyYWJsZVByb3RvdHlwZVsnQEBpdGVyYXRvciddIHx8IERFRkFVTFQgJiYgSXRlcmFibGVQcm90b3R5cGVbREVGQVVMVF07CiB2YXIgZGVmYXVsdEl0ZXJhdG9yID0gIUJVR0dZX1NBRkFSSV9JVEVSQVRPUlMgJiYgbmF0aXZlSXRlcmF0b3IgfHwgZ2V0SXRlcmF0aW9uTWV0aG9kKERFRkFVTFQpOwogdmFyIGFueU5hdGl2ZUl0ZXJhdG9yID0gTkFNRSA9PSAnQXJyYXknID8gSXRlcmFibGVQcm90b3R5cGUuZW50cmllcyB8fCBuYXRpdmVJdGVyYXRvciA6IG5hdGl2ZUl0ZXJhdG9yOwogdmFyIEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZSwgbWV0aG9kcywgS0VZOwogaWYgKGFueU5hdGl2ZUl0ZXJhdG9yKSB7CiAgQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlID0gZ2V0UHJvdG90eXBlT2YoYW55TmF0aXZlSXRlcmF0b3IuY2FsbChuZXcgSXRlcmFibGUoKSkpOwogIGlmIChDdXJyZW50SXRlcmF0b3JQcm90b3R5cGUgIT09IE9iamVjdC5wcm90b3R5cGUgJiYgQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlLm5leHQpIHsKICAgaWYgKCFJU19QVVJFICYmIGdldFByb3RvdHlwZU9mKEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZSkgIT09IEl0ZXJhdG9yUHJvdG90eXBlKSB7CiAgICBpZiAoc2V0UHJvdG90eXBlT2YpIHsKICAgICBzZXRQcm90b3R5cGVPZihDdXJyZW50SXRlcmF0b3JQcm90b3R5cGUsIEl0ZXJhdG9yUHJvdG90eXBlKTsKICAgIH0gZWxzZSBpZiAoIWlzQ2FsbGFibGUoQ3VycmVudEl0ZXJhdG9yUHJvdG90eXBlW0lURVJBVE9SXSkpIHsKICAgICBkZWZpbmVCdWlsdEluKEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZSwgSVRFUkFUT1IsIHJldHVyblRoaXMpOwogICAgfQogICB9CiAgIHNldFRvU3RyaW5nVGFnKEN1cnJlbnRJdGVyYXRvclByb3RvdHlwZSwgVE9fU1RSSU5HX1RBRywgdHJ1ZSwgdHJ1ZSk7CiAgIGlmIChJU19QVVJFKQogICAgSXRlcmF0b3JzW1RPX1NUUklOR19UQUddID0gcmV0dXJuVGhpczsKICB9CiB9CiBpZiAoUFJPUEVSX0ZVTkNUSU9OX05BTUUgJiYgREVGQVVMVCA9PSBWQUxVRVMgJiYgbmF0aXZlSXRlcmF0b3IgJiYgbmF0aXZlSXRlcmF0b3IubmFtZSAhPT0gVkFMVUVTKSB7CiAgaWYgKCFJU19QVVJFICYmIENPTkZJR1VSQUJMRV9GVU5DVElPTl9OQU1FKSB7CiAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShJdGVyYWJsZVByb3RvdHlwZSwgJ25hbWUnLCBWQUxVRVMpOwogIH0gZWxzZSB7CiAgIElOQ09SUkVDVF9WQUxVRVNfTkFNRSA9IHRydWU7CiAgIGRlZmF1bHRJdGVyYXRvciA9IGZ1bmN0aW9uIHZhbHVlcygpIHsKICAgIHJldHVybiBjYWxsKG5hdGl2ZUl0ZXJhdG9yLCB0aGlzKTsKICAgfTsKICB9CiB9CiBpZiAoREVGQVVMVCkgewogIG1ldGhvZHMgPSB7CiAgIHZhbHVlczogZ2V0SXRlcmF0aW9uTWV0aG9kKFZBTFVFUyksCiAgIGtleXM6IElTX1NFVCA/IGRlZmF1bHRJdGVyYXRvciA6IGdldEl0ZXJhdGlvbk1ldGhvZChLRVlTKSwKICAgZW50cmllczogZ2V0SXRlcmF0aW9uTWV0aG9kKEVOVFJJRVMpCiAgfTsKICBpZiAoRk9SQ0VEKQogICBmb3IgKEtFWSBpbiBtZXRob2RzKSB7CiAgICBpZiAoQlVHR1lfU0FGQVJJX0lURVJBVE9SUyB8fCBJTkNPUlJFQ1RfVkFMVUVTX05BTUUgfHwgIShLRVkgaW4gSXRlcmFibGVQcm90b3R5cGUpKSB7CiAgICAgZGVmaW5lQnVpbHRJbihJdGVyYWJsZVByb3RvdHlwZSwgS0VZLCBtZXRob2RzW0tFWV0pOwogICAgfQogICB9CiAgZWxzZQogICAkKHsKICAgIHRhcmdldDogTkFNRSwKICAgIHByb3RvOiB0cnVlLAogICAgZm9yY2VkOiBCVUdHWV9TQUZBUklfSVRFUkFUT1JTIHx8IElOQ09SUkVDVF9WQUxVRVNfTkFNRQogICB9LCBtZXRob2RzKTsKIH0KIGlmICgoIUlTX1BVUkUgfHwgRk9SQ0VEKSAmJiBJdGVyYWJsZVByb3RvdHlwZVtJVEVSQVRPUl0gIT09IGRlZmF1bHRJdGVyYXRvcikgewogIGRlZmluZUJ1aWx0SW4oSXRlcmFibGVQcm90b3R5cGUsIElURVJBVE9SLCBkZWZhdWx0SXRlcmF0b3IsIHsgbmFtZTogREVGQVVMVCB9KTsKIH0KIEl0ZXJhdG9yc1tOQU1FXSA9IGRlZmF1bHRJdGVyYXRvcjsKIHJldHVybiBtZXRob2RzOwp9OwoKLyoqKi8gfSksCi8qIDk1ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCnZhciBJdGVyYXRvclByb3RvdHlwZSA9IChfX3dfcGRmanNfcmVxdWlyZV9fKDk2KS5JdGVyYXRvclByb3RvdHlwZSk7CnZhciBjcmVhdGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDc0KTsKdmFyIGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTUpOwp2YXIgc2V0VG9TdHJpbmdUYWcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDk3KTsKdmFyIEl0ZXJhdG9ycyA9IF9fd19wZGZqc19yZXF1aXJlX18oOTMpOwp2YXIgcmV0dXJuVGhpcyA9IGZ1bmN0aW9uICgpIHsKIHJldHVybiB0aGlzOwp9Owptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChJdGVyYXRvckNvbnN0cnVjdG9yLCBOQU1FLCBuZXh0LCBFTlVNRVJBQkxFX05FWFQpIHsKIHZhciBUT19TVFJJTkdfVEFHID0gTkFNRSArICcgSXRlcmF0b3InOwogSXRlcmF0b3JDb25zdHJ1Y3Rvci5wcm90b3R5cGUgPSBjcmVhdGUoSXRlcmF0b3JQcm90b3R5cGUsIHsgbmV4dDogY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yKCshRU5VTUVSQUJMRV9ORVhULCBuZXh0KSB9KTsKIHNldFRvU3RyaW5nVGFnKEl0ZXJhdG9yQ29uc3RydWN0b3IsIFRPX1NUUklOR19UQUcsIGZhbHNlLCB0cnVlKTsKIEl0ZXJhdG9yc1tUT19TVFJJTkdfVEFHXSA9IHJldHVyblRoaXM7CiByZXR1cm4gSXRlcmF0b3JDb25zdHJ1Y3RvcjsKfTsKCi8qKiovIH0pLAovKiA5NiAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7Cgp2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExKTsKdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI1KTsKdmFyIGlzT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyNCk7CnZhciBjcmVhdGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDc0KTsKdmFyIGdldFByb3RvdHlwZU9mID0gX193X3BkZmpzX3JlcXVpcmVfXyg4Nik7CnZhciBkZWZpbmVCdWlsdEluID0gX193X3BkZmpzX3JlcXVpcmVfXyg1Mik7CnZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM4KTsKdmFyIElTX1BVUkUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQwKTsKdmFyIElURVJBVE9SID0gd2VsbEtub3duU3ltYm9sKCdpdGVyYXRvcicpOwp2YXIgQlVHR1lfU0FGQVJJX0lURVJBVE9SUyA9IGZhbHNlOwp2YXIgSXRlcmF0b3JQcm90b3R5cGUsIFByb3RvdHlwZU9mQXJyYXlJdGVyYXRvclByb3RvdHlwZSwgYXJyYXlJdGVyYXRvcjsKaWYgKFtdLmtleXMpIHsKIGFycmF5SXRlcmF0b3IgPSBbXS5rZXlzKCk7CiBpZiAoISgnbmV4dCcgaW4gYXJyYXlJdGVyYXRvcikpCiAgQlVHR1lfU0FGQVJJX0lURVJBVE9SUyA9IHRydWU7CiBlbHNlIHsKICBQcm90b3R5cGVPZkFycmF5SXRlcmF0b3JQcm90b3R5cGUgPSBnZXRQcm90b3R5cGVPZihnZXRQcm90b3R5cGVPZihhcnJheUl0ZXJhdG9yKSk7CiAgaWYgKFByb3RvdHlwZU9mQXJyYXlJdGVyYXRvclByb3RvdHlwZSAhPT0gT2JqZWN0LnByb3RvdHlwZSkKICAgSXRlcmF0b3JQcm90b3R5cGUgPSBQcm90b3R5cGVPZkFycmF5SXRlcmF0b3JQcm90b3R5cGU7CiB9Cn0KdmFyIE5FV19JVEVSQVRPUl9QUk9UT1RZUEUgPSAhaXNPYmplY3QoSXRlcmF0b3JQcm90b3R5cGUpIHx8IGZhaWxzKGZ1bmN0aW9uICgpIHsKIHZhciB0ZXN0ID0ge307CiByZXR1cm4gSXRlcmF0b3JQcm90b3R5cGVbSVRFUkFUT1JdLmNhbGwodGVzdCkgIT09IHRlc3Q7Cn0pOwppZiAoTkVXX0lURVJBVE9SX1BST1RPVFlQRSkKIEl0ZXJhdG9yUHJvdG90eXBlID0ge307CmVsc2UgaWYgKElTX1BVUkUpCiBJdGVyYXRvclByb3RvdHlwZSA9IGNyZWF0ZShJdGVyYXRvclByb3RvdHlwZSk7CmlmICghaXNDYWxsYWJsZShJdGVyYXRvclByb3RvdHlwZVtJVEVSQVRPUl0pKSB7CiBkZWZpbmVCdWlsdEluKEl0ZXJhdG9yUHJvdG90eXBlLCBJVEVSQVRPUiwgZnVuY3Rpb24gKCkgewogIHJldHVybiB0aGlzOwogfSk7Cn0KbW9kdWxlLmV4cG9ydHMgPSB7CiBJdGVyYXRvclByb3RvdHlwZTogSXRlcmF0b3JQcm90b3R5cGUsCiBCVUdHWV9TQUZBUklfSVRFUkFUT1JTOiBCVUdHWV9TQUZBUklfSVRFUkFUT1JTCn07CgovKioqLyB9KSwKLyogOTcgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGRlZmluZVByb3BlcnR5ID0gKF9fd19wZGZqc19yZXF1aXJlX18oNDkpLmYpOwp2YXIgaGFzT3duID0gX193X3BkZmpzX3JlcXVpcmVfXyg0Myk7CnZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM4KTsKdmFyIFRPX1NUUklOR19UQUcgPSB3ZWxsS25vd25TeW1ib2woJ3RvU3RyaW5nVGFnJyk7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHRhcmdldCwgVEFHLCBTVEFUSUMpIHsKIGlmICh0YXJnZXQgJiYgIVNUQVRJQykKICB0YXJnZXQgPSB0YXJnZXQucHJvdG90eXBlOwogaWYgKHRhcmdldCAmJiAhaGFzT3duKHRhcmdldCwgVE9fU1RSSU5HX1RBRykpIHsKICBkZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIFRPX1NUUklOR19UQUcsIHsKICAgY29uZmlndXJhYmxlOiB0cnVlLAogICB2YWx1ZTogVEFHCiAgfSk7CiB9Cn07CgovKioqLyB9KSwKLyogOTggKi8KLyoqKi8gKChtb2R1bGUpID0+IHsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlLCBkb25lKSB7CiByZXR1cm4gewogIHZhbHVlOiB2YWx1ZSwKICBkb25lOiBkb25lCiB9Owp9OwoKLyoqKi8gfSksCi8qIDk5ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIFRPX1NUUklOR19UQUdfU1VQUE9SVCA9IF9fd19wZGZqc19yZXF1aXJlX18oODQpOwp2YXIgZGVmaW5lQnVpbHRJbiA9IF9fd19wZGZqc19yZXF1aXJlX18oNTIpOwp2YXIgdG9TdHJpbmcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwMCk7CmlmICghVE9fU1RSSU5HX1RBR19TVVBQT1JUKSB7CiBkZWZpbmVCdWlsdEluKE9iamVjdC5wcm90b3R5cGUsICd0b1N0cmluZycsIHRvU3RyaW5nLCB7IHVuc2FmZTogdHJ1ZSB9KTsKfQoKLyoqKi8gfSksCi8qIDEwMCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7Cgp2YXIgVE9fU1RSSU5HX1RBR19TVVBQT1JUID0gX193X3BkZmpzX3JlcXVpcmVfXyg4NCk7CnZhciBjbGFzc29mID0gX193X3BkZmpzX3JlcXVpcmVfXyg4Myk7Cm1vZHVsZS5leHBvcnRzID0gVE9fU1RSSU5HX1RBR19TVVBQT1JUID8ge30udG9TdHJpbmcgOiBmdW5jdGlvbiB0b1N0cmluZygpIHsKIHJldHVybiAnW29iamVjdCAnICsgY2xhc3NvZih0aGlzKSArICddJzsKfTsKCi8qKiovIH0pLAovKiAxMDEgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgpfX3dfcGRmanNfcmVxdWlyZV9fKDEwMik7CgovKioqLyB9KSwKLyogMTAyICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKdmFyIGNvbGxlY3Rpb24gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwMyk7CnZhciBjb2xsZWN0aW9uU3Ryb25nID0gX193X3BkZmpzX3JlcXVpcmVfXygxMjEpOwpjb2xsZWN0aW9uKCdNYXAnLCBmdW5jdGlvbiAoaW5pdCkgewogcmV0dXJuIGZ1bmN0aW9uIE1hcCgpIHsKICByZXR1cm4gaW5pdCh0aGlzLCBhcmd1bWVudHMubGVuZ3RoID8gYXJndW1lbnRzWzBdIDogdW5kZWZpbmVkKTsKIH07Cn0sIGNvbGxlY3Rpb25TdHJvbmcpOwoKLyoqKi8gfSksCi8qIDEwMyAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7Cgp2YXIgJCA9IF9fd19wZGZqc19yZXF1aXJlX18oNyk7CnZhciBnbG9iYWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDgpOwp2YXIgdW5jdXJyeVRoaXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE4KTsKdmFyIGlzRm9yY2VkID0gX193X3BkZmpzX3JlcXVpcmVfXyg3Mik7CnZhciBkZWZpbmVCdWlsdEluID0gX193X3BkZmpzX3JlcXVpcmVfXyg1Mik7CnZhciBJbnRlcm5hbE1ldGFkYXRhTW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXygxMDQpOwp2YXIgaXRlcmF0ZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTExKTsKdmFyIGFuSW5zdGFuY2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExOCk7CnZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNSk7CnZhciBpc051bGxPclVuZGVmaW5lZCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjEpOwp2YXIgaXNPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI0KTsKdmFyIGZhaWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMSk7CnZhciBjaGVja0NvcnJlY3RuZXNzT2ZJdGVyYXRpb24gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExOSk7CnZhciBzZXRUb1N0cmluZ1RhZyA9IF9fd19wZGZqc19yZXF1aXJlX18oOTcpOwp2YXIgaW5oZXJpdElmUmVxdWlyZWQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyMCk7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKENPTlNUUlVDVE9SX05BTUUsIHdyYXBwZXIsIGNvbW1vbikgewogdmFyIElTX01BUCA9IENPTlNUUlVDVE9SX05BTUUuaW5kZXhPZignTWFwJykgIT09IC0xOwogdmFyIElTX1dFQUsgPSBDT05TVFJVQ1RPUl9OQU1FLmluZGV4T2YoJ1dlYWsnKSAhPT0gLTE7CiB2YXIgQURERVIgPSBJU19NQVAgPyAnc2V0JyA6ICdhZGQnOwogdmFyIE5hdGl2ZUNvbnN0cnVjdG9yID0gZ2xvYmFsW0NPTlNUUlVDVE9SX05BTUVdOwogdmFyIE5hdGl2ZVByb3RvdHlwZSA9IE5hdGl2ZUNvbnN0cnVjdG9yICYmIE5hdGl2ZUNvbnN0cnVjdG9yLnByb3RvdHlwZTsKIHZhciBDb25zdHJ1Y3RvciA9IE5hdGl2ZUNvbnN0cnVjdG9yOwogdmFyIGV4cG9ydGVkID0ge307CiB2YXIgZml4TWV0aG9kID0gZnVuY3Rpb24gKEtFWSkgewogIHZhciB1bmN1cnJpZWROYXRpdmVNZXRob2QgPSB1bmN1cnJ5VGhpcyhOYXRpdmVQcm90b3R5cGVbS0VZXSk7CiAgZGVmaW5lQnVpbHRJbihOYXRpdmVQcm90b3R5cGUsIEtFWSwgS0VZID09ICdhZGQnID8gZnVuY3Rpb24gYWRkKHZhbHVlKSB7CiAgIHVuY3VycmllZE5hdGl2ZU1ldGhvZCh0aGlzLCB2YWx1ZSA9PT0gMCA/IDAgOiB2YWx1ZSk7CiAgIHJldHVybiB0aGlzOwogIH0gOiBLRVkgPT0gJ2RlbGV0ZScgPyBmdW5jdGlvbiAoa2V5KSB7CiAgIHJldHVybiBJU19XRUFLICYmICFpc09iamVjdChrZXkpID8gZmFsc2UgOiB1bmN1cnJpZWROYXRpdmVNZXRob2QodGhpcywga2V5ID09PSAwID8gMCA6IGtleSk7CiAgfSA6IEtFWSA9PSAnZ2V0JyA/IGZ1bmN0aW9uIGdldChrZXkpIHsKICAgcmV0dXJuIElTX1dFQUsgJiYgIWlzT2JqZWN0KGtleSkgPyB1bmRlZmluZWQgOiB1bmN1cnJpZWROYXRpdmVNZXRob2QodGhpcywga2V5ID09PSAwID8gMCA6IGtleSk7CiAgfSA6IEtFWSA9PSAnaGFzJyA/IGZ1bmN0aW9uIGhhcyhrZXkpIHsKICAgcmV0dXJuIElTX1dFQUsgJiYgIWlzT2JqZWN0KGtleSkgPyBmYWxzZSA6IHVuY3VycmllZE5hdGl2ZU1ldGhvZCh0aGlzLCBrZXkgPT09IDAgPyAwIDoga2V5KTsKICB9IDogZnVuY3Rpb24gc2V0KGtleSwgdmFsdWUpIHsKICAgdW5jdXJyaWVkTmF0aXZlTWV0aG9kKHRoaXMsIGtleSA9PT0gMCA/IDAgOiBrZXksIHZhbHVlKTsKICAgcmV0dXJuIHRoaXM7CiAgfSk7CiB9OwogdmFyIFJFUExBQ0UgPSBpc0ZvcmNlZChDT05TVFJVQ1RPUl9OQU1FLCAhaXNDYWxsYWJsZShOYXRpdmVDb25zdHJ1Y3RvcikgfHwgIShJU19XRUFLIHx8IE5hdGl2ZVByb3RvdHlwZS5mb3JFYWNoICYmICFmYWlscyhmdW5jdGlvbiAoKSB7CiAgbmV3IE5hdGl2ZUNvbnN0cnVjdG9yKCkuZW50cmllcygpLm5leHQoKTsKIH0pKSk7CiBpZiAoUkVQTEFDRSkgewogIENvbnN0cnVjdG9yID0gY29tbW9uLmdldENvbnN0cnVjdG9yKHdyYXBwZXIsIENPTlNUUlVDVE9SX05BTUUsIElTX01BUCwgQURERVIpOwogIEludGVybmFsTWV0YWRhdGFNb2R1bGUuZW5hYmxlKCk7CiB9IGVsc2UgaWYgKGlzRm9yY2VkKENPTlNUUlVDVE9SX05BTUUsIHRydWUpKSB7CiAgdmFyIGluc3RhbmNlID0gbmV3IENvbnN0cnVjdG9yKCk7CiAgdmFyIEhBU05UX0NIQUlOSU5HID0gaW5zdGFuY2VbQURERVJdKElTX1dFQUsgPyB7fSA6IC0wLCAxKSAhPSBpbnN0YW5jZTsKICB2YXIgVEhST1dTX09OX1BSSU1JVElWRVMgPSBmYWlscyhmdW5jdGlvbiAoKSB7CiAgIGluc3RhbmNlLmhhcygxKTsKICB9KTsKICB2YXIgQUNDRVBUX0lURVJBQkxFUyA9IGNoZWNrQ29ycmVjdG5lc3NPZkl0ZXJhdGlvbihmdW5jdGlvbiAoaXRlcmFibGUpIHsKICAgbmV3IE5hdGl2ZUNvbnN0cnVjdG9yKGl0ZXJhYmxlKTsKICB9KTsKICB2YXIgQlVHR1lfWkVSTyA9ICFJU19XRUFLICYmIGZhaWxzKGZ1bmN0aW9uICgpIHsKICAgdmFyICRpbnN0YW5jZSA9IG5ldyBOYXRpdmVDb25zdHJ1Y3RvcigpOwogICB2YXIgaW5kZXggPSA1OwogICB3aGlsZSAoaW5kZXgtLSkKICAgICRpbnN0YW5jZVtBRERFUl0oaW5kZXgsIGluZGV4KTsKICAgcmV0dXJuICEkaW5zdGFuY2UuaGFzKC0wKTsKICB9KTsKICBpZiAoIUFDQ0VQVF9JVEVSQUJMRVMpIHsKICAgQ29uc3RydWN0b3IgPSB3cmFwcGVyKGZ1bmN0aW9uIChkdW1teSwgaXRlcmFibGUpIHsKICAgIGFuSW5zdGFuY2UoZHVtbXksIE5hdGl2ZVByb3RvdHlwZSk7CiAgICB2YXIgdGhhdCA9IGluaGVyaXRJZlJlcXVpcmVkKG5ldyBOYXRpdmVDb25zdHJ1Y3RvcigpLCBkdW1teSwgQ29uc3RydWN0b3IpOwogICAgaWYgKCFpc051bGxPclVuZGVmaW5lZChpdGVyYWJsZSkpCiAgICAgaXRlcmF0ZShpdGVyYWJsZSwgdGhhdFtBRERFUl0sIHsKICAgICAgdGhhdDogdGhhdCwKICAgICAgQVNfRU5UUklFUzogSVNfTUFQCiAgICAgfSk7CiAgICByZXR1cm4gdGhhdDsKICAgfSk7CiAgIENvbnN0cnVjdG9yLnByb3RvdHlwZSA9IE5hdGl2ZVByb3RvdHlwZTsKICAgTmF0aXZlUHJvdG90eXBlLmNvbnN0cnVjdG9yID0gQ29uc3RydWN0b3I7CiAgfQogIGlmIChUSFJPV1NfT05fUFJJTUlUSVZFUyB8fCBCVUdHWV9aRVJPKSB7CiAgIGZpeE1ldGhvZCgnZGVsZXRlJyk7CiAgIGZpeE1ldGhvZCgnaGFzJyk7CiAgIElTX01BUCAmJiBmaXhNZXRob2QoJ2dldCcpOwogIH0KICBpZiAoQlVHR1lfWkVSTyB8fCBIQVNOVF9DSEFJTklORykKICAgZml4TWV0aG9kKEFEREVSKTsKICBpZiAoSVNfV0VBSyAmJiBOYXRpdmVQcm90b3R5cGUuY2xlYXIpCiAgIGRlbGV0ZSBOYXRpdmVQcm90b3R5cGUuY2xlYXI7CiB9CiBleHBvcnRlZFtDT05TVFJVQ1RPUl9OQU1FXSA9IENvbnN0cnVjdG9yOwogJCh7CiAgZ2xvYmFsOiB0cnVlLAogIGNvbnN0cnVjdG9yOiB0cnVlLAogIGZvcmNlZDogQ29uc3RydWN0b3IgIT0gTmF0aXZlQ29uc3RydWN0b3IKIH0sIGV4cG9ydGVkKTsKIHNldFRvU3RyaW5nVGFnKENvbnN0cnVjdG9yLCBDT05TVFJVQ1RPUl9OQU1FKTsKIGlmICghSVNfV0VBSykKICBjb21tb24uc2V0U3Ryb25nKENvbnN0cnVjdG9yLCBDT05TVFJVQ1RPUl9OQU1FLCBJU19NQVApOwogcmV0dXJuIENvbnN0cnVjdG9yOwp9OwoKLyoqKi8gfSksCi8qIDEwNCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgJCA9IF9fd19wZGZqc19yZXF1aXJlX18oNyk7CnZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTgpOwp2YXIgaGlkZGVuS2V5cyA9IF9fd19wZGZqc19yZXF1aXJlX18oNTkpOwp2YXIgaXNPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI0KTsKdmFyIGhhc093biA9IF9fd19wZGZqc19yZXF1aXJlX18oNDMpOwp2YXIgZGVmaW5lUHJvcGVydHkgPSAoX193X3BkZmpzX3JlcXVpcmVfXyg0OSkuZik7CnZhciBnZXRPd25Qcm9wZXJ0eU5hbWVzTW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXyg2Mik7CnZhciBnZXRPd25Qcm9wZXJ0eU5hbWVzRXh0ZXJuYWxNb2R1bGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwNSk7CnZhciBpc0V4dGVuc2libGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwOCk7CnZhciB1aWQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQ1KTsKdmFyIEZSRUVaSU5HID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTApOwp2YXIgUkVRVUlSRUQgPSBmYWxzZTsKdmFyIE1FVEFEQVRBID0gdWlkKCdtZXRhJyk7CnZhciBpZCA9IDA7CnZhciBzZXRNZXRhZGF0YSA9IGZ1bmN0aW9uIChpdCkgewogZGVmaW5lUHJvcGVydHkoaXQsIE1FVEFEQVRBLCB7CiAgdmFsdWU6IHsKICAgb2JqZWN0SUQ6ICdPJyArIGlkKyssCiAgIHdlYWtEYXRhOiB7fQogIH0KIH0pOwp9Owp2YXIgZmFzdEtleSA9IGZ1bmN0aW9uIChpdCwgY3JlYXRlKSB7CiBpZiAoIWlzT2JqZWN0KGl0KSkKICByZXR1cm4gdHlwZW9mIGl0ID09ICdzeW1ib2wnID8gaXQgOiAodHlwZW9mIGl0ID09ICdzdHJpbmcnID8gJ1MnIDogJ1AnKSArIGl0OwogaWYgKCFoYXNPd24oaXQsIE1FVEFEQVRBKSkgewogIGlmICghaXNFeHRlbnNpYmxlKGl0KSkKICAgcmV0dXJuICdGJzsKICBpZiAoIWNyZWF0ZSkKICAgcmV0dXJuICdFJzsKICBzZXRNZXRhZGF0YShpdCk7CiB9CiByZXR1cm4gaXRbTUVUQURBVEFdLm9iamVjdElEOwp9Owp2YXIgZ2V0V2Vha0RhdGEgPSBmdW5jdGlvbiAoaXQsIGNyZWF0ZSkgewogaWYgKCFoYXNPd24oaXQsIE1FVEFEQVRBKSkgewogIGlmICghaXNFeHRlbnNpYmxlKGl0KSkKICAgcmV0dXJuIHRydWU7CiAgaWYgKCFjcmVhdGUpCiAgIHJldHVybiBmYWxzZTsKICBzZXRNZXRhZGF0YShpdCk7CiB9CiByZXR1cm4gaXRbTUVUQURBVEFdLndlYWtEYXRhOwp9Owp2YXIgb25GcmVlemUgPSBmdW5jdGlvbiAoaXQpIHsKIGlmIChGUkVFWklORyAmJiBSRVFVSVJFRCAmJiBpc0V4dGVuc2libGUoaXQpICYmICFoYXNPd24oaXQsIE1FVEFEQVRBKSkKICBzZXRNZXRhZGF0YShpdCk7CiByZXR1cm4gaXQ7Cn07CnZhciBlbmFibGUgPSBmdW5jdGlvbiAoKSB7CiBtZXRhLmVuYWJsZSA9IGZ1bmN0aW9uICgpIHsKIH07CiBSRVFVSVJFRCA9IHRydWU7CiB2YXIgZ2V0T3duUHJvcGVydHlOYW1lcyA9IGdldE93blByb3BlcnR5TmFtZXNNb2R1bGUuZjsKIHZhciBzcGxpY2UgPSB1bmN1cnJ5VGhpcyhbXS5zcGxpY2UpOwogdmFyIHRlc3QgPSB7fTsKIHRlc3RbTUVUQURBVEFdID0gMTsKIGlmIChnZXRPd25Qcm9wZXJ0eU5hbWVzKHRlc3QpLmxlbmd0aCkgewogIGdldE93blByb3BlcnR5TmFtZXNNb2R1bGUuZiA9IGZ1bmN0aW9uIChpdCkgewogICB2YXIgcmVzdWx0ID0gZ2V0T3duUHJvcGVydHlOYW1lcyhpdCk7CiAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSByZXN1bHQubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgIGlmIChyZXN1bHRbaV0gPT09IE1FVEFEQVRBKSB7CiAgICAgc3BsaWNlKHJlc3VsdCwgaSwgMSk7CiAgICAgYnJlYWs7CiAgICB9CiAgIH0KICAgcmV0dXJuIHJlc3VsdDsKICB9OwogICQoewogICB0YXJnZXQ6ICdPYmplY3QnLAogICBzdGF0OiB0cnVlLAogICBmb3JjZWQ6IHRydWUKICB9LCB7IGdldE93blByb3BlcnR5TmFtZXM6IGdldE93blByb3BlcnR5TmFtZXNFeHRlcm5hbE1vZHVsZS5mIH0pOwogfQp9Owp2YXIgbWV0YSA9IG1vZHVsZS5leHBvcnRzID0gewogZW5hYmxlOiBlbmFibGUsCiBmYXN0S2V5OiBmYXN0S2V5LAogZ2V0V2Vha0RhdGE6IGdldFdlYWtEYXRhLAogb25GcmVlemU6IG9uRnJlZXplCn07CmhpZGRlbktleXNbTUVUQURBVEFdID0gdHJ1ZTsKCi8qKiovIH0pLAovKiAxMDUgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGNsYXNzb2YgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE5KTsKdmFyIHRvSW5kZXhlZE9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTYpOwp2YXIgJGdldE93blByb3BlcnR5TmFtZXMgPSAoX193X3BkZmpzX3JlcXVpcmVfXyg2MikuZik7CnZhciBhcnJheVNsaWNlID0gX193X3BkZmpzX3JlcXVpcmVfXygxMDYpOwp2YXIgd2luZG93TmFtZXMgPSB0eXBlb2Ygd2luZG93ID09ICdvYmplY3QnICYmIHdpbmRvdyAmJiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyA/IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHdpbmRvdykgOiBbXTsKdmFyIGdldFdpbmRvd05hbWVzID0gZnVuY3Rpb24gKGl0KSB7CiB0cnkgewogIHJldHVybiAkZ2V0T3duUHJvcGVydHlOYW1lcyhpdCk7CiB9IGNhdGNoIChlcnJvcikgewogIHJldHVybiBhcnJheVNsaWNlKHdpbmRvd05hbWVzKTsKIH0KfTsKbW9kdWxlLmV4cG9ydHMuZiA9IGZ1bmN0aW9uIGdldE93blByb3BlcnR5TmFtZXMoaXQpIHsKIHJldHVybiB3aW5kb3dOYW1lcyAmJiBjbGFzc29mKGl0KSA9PSAnV2luZG93JyA/IGdldFdpbmRvd05hbWVzKGl0KSA6ICRnZXRPd25Qcm9wZXJ0eU5hbWVzKHRvSW5kZXhlZE9iamVjdChpdCkpOwp9OwoKLyoqKi8gfSksCi8qIDEwNiAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgdG9BYnNvbHV0ZUluZGV4ID0gX193X3BkZmpzX3JlcXVpcmVfXyg2NSk7CnZhciBsZW5ndGhPZkFycmF5TGlrZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNjgpOwp2YXIgY3JlYXRlUHJvcGVydHkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwNyk7CnZhciAkQXJyYXkgPSBBcnJheTsKdmFyIG1heCA9IE1hdGgubWF4Owptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChPLCBzdGFydCwgZW5kKSB7CiB2YXIgbGVuZ3RoID0gbGVuZ3RoT2ZBcnJheUxpa2UoTyk7CiB2YXIgayA9IHRvQWJzb2x1dGVJbmRleChzdGFydCwgbGVuZ3RoKTsKIHZhciBmaW4gPSB0b0Fic29sdXRlSW5kZXgoZW5kID09PSB1bmRlZmluZWQgPyBsZW5ndGggOiBlbmQsIGxlbmd0aCk7CiB2YXIgcmVzdWx0ID0gJEFycmF5KG1heChmaW4gLSBrLCAwKSk7CiBmb3IgKHZhciBuID0gMDsgayA8IGZpbjsgaysrLCBuKyspCiAgY3JlYXRlUHJvcGVydHkocmVzdWx0LCBuLCBPW2tdKTsKIHJlc3VsdC5sZW5ndGggPSBuOwogcmV0dXJuIHJlc3VsdDsKfTsKCi8qKiovIH0pLAovKiAxMDcgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKdmFyIHRvUHJvcGVydHlLZXkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIyKTsKdmFyIGRlZmluZVByb3BlcnR5TW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXyg0OSk7CnZhciBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1KTsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqZWN0LCBrZXksIHZhbHVlKSB7CiB2YXIgcHJvcGVydHlLZXkgPSB0b1Byb3BlcnR5S2V5KGtleSk7CiBpZiAocHJvcGVydHlLZXkgaW4gb2JqZWN0KQogIGRlZmluZVByb3BlcnR5TW9kdWxlLmYob2JqZWN0LCBwcm9wZXJ0eUtleSwgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yKDAsIHZhbHVlKSk7CiBlbHNlCiAgb2JqZWN0W3Byb3BlcnR5S2V5XSA9IHZhbHVlOwp9OwoKLyoqKi8gfSksCi8qIDEwOCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExKTsKdmFyIGlzT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyNCk7CnZhciBjbGFzc29mID0gX193X3BkZmpzX3JlcXVpcmVfXygxOSk7CnZhciBBUlJBWV9CVUZGRVJfTk9OX0VYVEVOU0lCTEUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEwOSk7CnZhciAkaXNFeHRlbnNpYmxlID0gT2JqZWN0LmlzRXh0ZW5zaWJsZTsKdmFyIEZBSUxTX09OX1BSSU1JVElWRVMgPSBmYWlscyhmdW5jdGlvbiAoKSB7CiAkaXNFeHRlbnNpYmxlKDEpOwp9KTsKbW9kdWxlLmV4cG9ydHMgPSBGQUlMU19PTl9QUklNSVRJVkVTIHx8IEFSUkFZX0JVRkZFUl9OT05fRVhURU5TSUJMRSA/IGZ1bmN0aW9uIGlzRXh0ZW5zaWJsZShpdCkgewogaWYgKCFpc09iamVjdChpdCkpCiAgcmV0dXJuIGZhbHNlOwogaWYgKEFSUkFZX0JVRkZFUl9OT05fRVhURU5TSUJMRSAmJiBjbGFzc29mKGl0KSA9PSAnQXJyYXlCdWZmZXInKQogIHJldHVybiBmYWxzZTsKIHJldHVybiAkaXNFeHRlbnNpYmxlID8gJGlzRXh0ZW5zaWJsZShpdCkgOiB0cnVlOwp9IDogJGlzRXh0ZW5zaWJsZTsKCi8qKiovIH0pLAovKiAxMDkgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIGZhaWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMSk7Cm1vZHVsZS5leHBvcnRzID0gZmFpbHMoZnVuY3Rpb24gKCkgewogaWYgKHR5cGVvZiBBcnJheUJ1ZmZlciA9PSAnZnVuY3Rpb24nKSB7CiAgdmFyIGJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcig4KTsKICBpZiAoT2JqZWN0LmlzRXh0ZW5zaWJsZShidWZmZXIpKQogICBPYmplY3QuZGVmaW5lUHJvcGVydHkoYnVmZmVyLCAnYScsIHsgdmFsdWU6IDggfSk7CiB9Cn0pOwoKLyoqKi8gfSksCi8qIDExMCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExKTsKbW9kdWxlLmV4cG9ydHMgPSAhZmFpbHMoZnVuY3Rpb24gKCkgewogcmV0dXJuIE9iamVjdC5pc0V4dGVuc2libGUoT2JqZWN0LnByZXZlbnRFeHRlbnNpb25zKHt9KSk7Cn0pOwoKLyoqKi8gfSksCi8qIDExMSAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgYmluZCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEyKTsKdmFyIGNhbGwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyKTsKdmFyIGFuT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXyg1MSk7CnZhciB0cnlUb1N0cmluZyA9IF9fd19wZGZqc19yZXF1aXJlX18oMzYpOwp2YXIgaXNBcnJheUl0ZXJhdG9yTWV0aG9kID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTQpOwp2YXIgbGVuZ3RoT2ZBcnJheUxpa2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDY4KTsKdmFyIGlzUHJvdG90eXBlT2YgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI5KTsKdmFyIGdldEl0ZXJhdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTUpOwp2YXIgZ2V0SXRlcmF0b3JNZXRob2QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExNik7CnZhciBpdGVyYXRvckNsb3NlID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTcpOwp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKdmFyIFJlc3VsdCA9IGZ1bmN0aW9uIChzdG9wcGVkLCByZXN1bHQpIHsKIHRoaXMuc3RvcHBlZCA9IHN0b3BwZWQ7CiB0aGlzLnJlc3VsdCA9IHJlc3VsdDsKfTsKdmFyIFJlc3VsdFByb3RvdHlwZSA9IFJlc3VsdC5wcm90b3R5cGU7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0ZXJhYmxlLCB1bmJvdW5kRnVuY3Rpb24sIG9wdGlvbnMpIHsKIHZhciB0aGF0ID0gb3B0aW9ucyAmJiBvcHRpb25zLnRoYXQ7CiB2YXIgQVNfRU5UUklFUyA9ICEhKG9wdGlvbnMgJiYgb3B0aW9ucy5BU19FTlRSSUVTKTsKIHZhciBJU19SRUNPUkQgPSAhIShvcHRpb25zICYmIG9wdGlvbnMuSVNfUkVDT1JEKTsKIHZhciBJU19JVEVSQVRPUiA9ICEhKG9wdGlvbnMgJiYgb3B0aW9ucy5JU19JVEVSQVRPUik7CiB2YXIgSU5URVJSVVBURUQgPSAhIShvcHRpb25zICYmIG9wdGlvbnMuSU5URVJSVVBURUQpOwogdmFyIGZuID0gYmluZCh1bmJvdW5kRnVuY3Rpb24sIHRoYXQpOwogdmFyIGl0ZXJhdG9yLCBpdGVyRm4sIGluZGV4LCBsZW5ndGgsIHJlc3VsdCwgbmV4dCwgc3RlcDsKIHZhciBzdG9wID0gZnVuY3Rpb24gKGNvbmRpdGlvbikgewogIGlmIChpdGVyYXRvcikKICAgaXRlcmF0b3JDbG9zZShpdGVyYXRvciwgJ25vcm1hbCcsIGNvbmRpdGlvbik7CiAgcmV0dXJuIG5ldyBSZXN1bHQodHJ1ZSwgY29uZGl0aW9uKTsKIH07CiB2YXIgY2FsbEZuID0gZnVuY3Rpb24gKHZhbHVlKSB7CiAgaWYgKEFTX0VOVFJJRVMpIHsKICAgYW5PYmplY3QodmFsdWUpOwogICByZXR1cm4gSU5URVJSVVBURUQgPyBmbih2YWx1ZVswXSwgdmFsdWVbMV0sIHN0b3ApIDogZm4odmFsdWVbMF0sIHZhbHVlWzFdKTsKICB9CiAgcmV0dXJuIElOVEVSUlVQVEVEID8gZm4odmFsdWUsIHN0b3ApIDogZm4odmFsdWUpOwogfTsKIGlmIChJU19SRUNPUkQpIHsKICBpdGVyYXRvciA9IGl0ZXJhYmxlLml0ZXJhdG9yOwogfSBlbHNlIGlmIChJU19JVEVSQVRPUikgewogIGl0ZXJhdG9yID0gaXRlcmFibGU7CiB9IGVsc2UgewogIGl0ZXJGbiA9IGdldEl0ZXJhdG9yTWV0aG9kKGl0ZXJhYmxlKTsKICBpZiAoIWl0ZXJGbikKICAgdGhyb3cgJFR5cGVFcnJvcih0cnlUb1N0cmluZyhpdGVyYWJsZSkgKyAnIGlzIG5vdCBpdGVyYWJsZScpOwogIGlmIChpc0FycmF5SXRlcmF0b3JNZXRob2QoaXRlckZuKSkgewogICBmb3IgKGluZGV4ID0gMCwgbGVuZ3RoID0gbGVuZ3RoT2ZBcnJheUxpa2UoaXRlcmFibGUpOyBsZW5ndGggPiBpbmRleDsgaW5kZXgrKykgewogICAgcmVzdWx0ID0gY2FsbEZuKGl0ZXJhYmxlW2luZGV4XSk7CiAgICBpZiAocmVzdWx0ICYmIGlzUHJvdG90eXBlT2YoUmVzdWx0UHJvdG90eXBlLCByZXN1bHQpKQogICAgIHJldHVybiByZXN1bHQ7CiAgIH0KICAgcmV0dXJuIG5ldyBSZXN1bHQoZmFsc2UpOwogIH0KICBpdGVyYXRvciA9IGdldEl0ZXJhdG9yKGl0ZXJhYmxlLCBpdGVyRm4pOwogfQogbmV4dCA9IElTX1JFQ09SRCA/IGl0ZXJhYmxlLm5leHQgOiBpdGVyYXRvci5uZXh0Owogd2hpbGUgKCEoc3RlcCA9IGNhbGwobmV4dCwgaXRlcmF0b3IpKS5kb25lKSB7CiAgdHJ5IHsKICAgcmVzdWx0ID0gY2FsbEZuKHN0ZXAudmFsdWUpOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgIGl0ZXJhdG9yQ2xvc2UoaXRlcmF0b3IsICd0aHJvdycsIGVycm9yKTsKICB9CiAgaWYgKHR5cGVvZiByZXN1bHQgPT0gJ29iamVjdCcgJiYgcmVzdWx0ICYmIGlzUHJvdG90eXBlT2YoUmVzdWx0UHJvdG90eXBlLCByZXN1bHQpKQogICByZXR1cm4gcmVzdWx0OwogfQogcmV0dXJuIG5ldyBSZXN1bHQoZmFsc2UpOwp9OwoKLyoqKi8gfSksCi8qIDExMiAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgdW5jdXJyeVRoaXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExMyk7CnZhciBhQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM1KTsKdmFyIE5BVElWRV9CSU5EID0gX193X3BkZmpzX3JlcXVpcmVfXygxMyk7CnZhciBiaW5kID0gdW5jdXJyeVRoaXModW5jdXJyeVRoaXMuYmluZCk7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGZuLCB0aGF0KSB7CiBhQ2FsbGFibGUoZm4pOwogcmV0dXJuIHRoYXQgPT09IHVuZGVmaW5lZCA/IGZuIDogTkFUSVZFX0JJTkQgPyBiaW5kKGZuLCB0aGF0KSA6IGZ1bmN0aW9uICgpIHsKICByZXR1cm4gZm4uYXBwbHkodGhhdCwgYXJndW1lbnRzKTsKIH07Cn07CgovKioqLyB9KSwKLyogMTEzICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBjbGFzc29mUmF3ID0gX193X3BkZmpzX3JlcXVpcmVfXygxOSk7CnZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTgpOwptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChmbikgewogaWYgKGNsYXNzb2ZSYXcoZm4pID09PSAnRnVuY3Rpb24nKQogIHJldHVybiB1bmN1cnJ5VGhpcyhmbik7Cn07CgovKioqLyB9KSwKLyogMTE0ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM4KTsKdmFyIEl0ZXJhdG9ycyA9IF9fd19wZGZqc19yZXF1aXJlX18oOTMpOwp2YXIgSVRFUkFUT1IgPSB3ZWxsS25vd25TeW1ib2woJ2l0ZXJhdG9yJyk7CnZhciBBcnJheVByb3RvdHlwZSA9IEFycmF5LnByb3RvdHlwZTsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKIHJldHVybiBpdCAhPT0gdW5kZWZpbmVkICYmIChJdGVyYXRvcnMuQXJyYXkgPT09IGl0IHx8IEFycmF5UHJvdG90eXBlW0lURVJBVE9SXSA9PT0gaXQpOwp9OwoKLyoqKi8gfSksCi8qIDExNSAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgY2FsbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTIpOwp2YXIgYUNhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygzNSk7CnZhciBhbk9iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oNTEpOwp2YXIgdHJ5VG9TdHJpbmcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM2KTsKdmFyIGdldEl0ZXJhdG9yTWV0aG9kID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTYpOwp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQsIHVzaW5nSXRlcmF0b3IpIHsKIHZhciBpdGVyYXRvck1ldGhvZCA9IGFyZ3VtZW50cy5sZW5ndGggPCAyID8gZ2V0SXRlcmF0b3JNZXRob2QoYXJndW1lbnQpIDogdXNpbmdJdGVyYXRvcjsKIGlmIChhQ2FsbGFibGUoaXRlcmF0b3JNZXRob2QpKQogIHJldHVybiBhbk9iamVjdChjYWxsKGl0ZXJhdG9yTWV0aG9kLCBhcmd1bWVudCkpOwogdGhyb3cgJFR5cGVFcnJvcih0cnlUb1N0cmluZyhhcmd1bWVudCkgKyAnIGlzIG5vdCBpdGVyYWJsZScpOwp9OwoKLyoqKi8gfSksCi8qIDExNiAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgY2xhc3NvZiA9IF9fd19wZGZqc19yZXF1aXJlX18oODMpOwp2YXIgZ2V0TWV0aG9kID0gX193X3BkZmpzX3JlcXVpcmVfXygzNCk7CnZhciBpc051bGxPclVuZGVmaW5lZCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjEpOwp2YXIgSXRlcmF0b3JzID0gX193X3BkZmpzX3JlcXVpcmVfXyg5Myk7CnZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM4KTsKdmFyIElURVJBVE9SID0gd2VsbEtub3duU3ltYm9sKCdpdGVyYXRvcicpOwptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkgewogaWYgKCFpc051bGxPclVuZGVmaW5lZChpdCkpCiAgcmV0dXJuIGdldE1ldGhvZChpdCwgSVRFUkFUT1IpIHx8IGdldE1ldGhvZChpdCwgJ0BAaXRlcmF0b3InKSB8fCBJdGVyYXRvcnNbY2xhc3NvZihpdCldOwp9OwoKLyoqKi8gfSksCi8qIDExNyAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgY2FsbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTIpOwp2YXIgYW5PYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDUxKTsKdmFyIGdldE1ldGhvZCA9IF9fd19wZGZqc19yZXF1aXJlX18oMzQpOwptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdGVyYXRvciwga2luZCwgdmFsdWUpIHsKIHZhciBpbm5lclJlc3VsdCwgaW5uZXJFcnJvcjsKIGFuT2JqZWN0KGl0ZXJhdG9yKTsKIHRyeSB7CiAgaW5uZXJSZXN1bHQgPSBnZXRNZXRob2QoaXRlcmF0b3IsICdyZXR1cm4nKTsKICBpZiAoIWlubmVyUmVzdWx0KSB7CiAgIGlmIChraW5kID09PSAndGhyb3cnKQogICAgdGhyb3cgdmFsdWU7CiAgIHJldHVybiB2YWx1ZTsKICB9CiAgaW5uZXJSZXN1bHQgPSBjYWxsKGlubmVyUmVzdWx0LCBpdGVyYXRvcik7CiB9IGNhdGNoIChlcnJvcikgewogIGlubmVyRXJyb3IgPSB0cnVlOwogIGlubmVyUmVzdWx0ID0gZXJyb3I7CiB9CiBpZiAoa2luZCA9PT0gJ3Rocm93JykKICB0aHJvdyB2YWx1ZTsKIGlmIChpbm5lckVycm9yKQogIHRocm93IGlubmVyUmVzdWx0OwogYW5PYmplY3QoaW5uZXJSZXN1bHQpOwogcmV0dXJuIHZhbHVlOwp9OwoKLyoqKi8gfSksCi8qIDExOCAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgaXNQcm90b3R5cGVPZiA9IF9fd19wZGZqc19yZXF1aXJlX18oMjkpOwp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQsIFByb3RvdHlwZSkgewogaWYgKGlzUHJvdG90eXBlT2YoUHJvdG90eXBlLCBpdCkpCiAgcmV0dXJuIGl0OwogdGhyb3cgJFR5cGVFcnJvcignSW5jb3JyZWN0IGludm9jYXRpb24nKTsKfTsKCi8qKiovIH0pLAovKiAxMTkgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIHdlbGxLbm93blN5bWJvbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMzgpOwp2YXIgSVRFUkFUT1IgPSB3ZWxsS25vd25TeW1ib2woJ2l0ZXJhdG9yJyk7CnZhciBTQUZFX0NMT1NJTkcgPSBmYWxzZTsKdHJ5IHsKIHZhciBjYWxsZWQgPSAwOwogdmFyIGl0ZXJhdG9yV2l0aFJldHVybiA9IHsKICBuZXh0OiBmdW5jdGlvbiAoKSB7CiAgIHJldHVybiB7IGRvbmU6ICEhY2FsbGVkKysgfTsKICB9LAogICdyZXR1cm4nOiBmdW5jdGlvbiAoKSB7CiAgIFNBRkVfQ0xPU0lORyA9IHRydWU7CiAgfQogfTsKIGl0ZXJhdG9yV2l0aFJldHVybltJVEVSQVRPUl0gPSBmdW5jdGlvbiAoKSB7CiAgcmV0dXJuIHRoaXM7CiB9OwogQXJyYXkuZnJvbShpdGVyYXRvcldpdGhSZXR1cm4sIGZ1bmN0aW9uICgpIHsKICB0aHJvdyAyOwogfSk7Cn0gY2F0Y2ggKGVycm9yKSB7Cn0KbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZXhlYywgU0tJUF9DTE9TSU5HKSB7CiBpZiAoIVNLSVBfQ0xPU0lORyAmJiAhU0FGRV9DTE9TSU5HKQogIHJldHVybiBmYWxzZTsKIHZhciBJVEVSQVRJT05fU1VQUE9SVCA9IGZhbHNlOwogdHJ5IHsKICB2YXIgb2JqZWN0ID0ge307CiAgb2JqZWN0W0lURVJBVE9SXSA9IGZ1bmN0aW9uICgpIHsKICAgcmV0dXJuIHsKICAgIG5leHQ6IGZ1bmN0aW9uICgpIHsKICAgICByZXR1cm4geyBkb25lOiBJVEVSQVRJT05fU1VQUE9SVCA9IHRydWUgfTsKICAgIH0KICAgfTsKICB9OwogIGV4ZWMob2JqZWN0KTsKIH0gY2F0Y2ggKGVycm9yKSB7CiB9CiByZXR1cm4gSVRFUkFUSU9OX1NVUFBPUlQ7Cn07CgovKioqLyB9KSwKLyogMTIwICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNSk7CnZhciBpc09iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjQpOwp2YXIgc2V0UHJvdG90eXBlT2YgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDg4KTsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoJHRoaXMsIGR1bW15LCBXcmFwcGVyKSB7CiB2YXIgTmV3VGFyZ2V0LCBOZXdUYXJnZXRQcm90b3R5cGU7CiBpZiAoc2V0UHJvdG90eXBlT2YgJiYgaXNDYWxsYWJsZShOZXdUYXJnZXQgPSBkdW1teS5jb25zdHJ1Y3RvcikgJiYgTmV3VGFyZ2V0ICE9PSBXcmFwcGVyICYmIGlzT2JqZWN0KE5ld1RhcmdldFByb3RvdHlwZSA9IE5ld1RhcmdldC5wcm90b3R5cGUpICYmIE5ld1RhcmdldFByb3RvdHlwZSAhPT0gV3JhcHBlci5wcm90b3R5cGUpCiAgc2V0UHJvdG90eXBlT2YoJHRoaXMsIE5ld1RhcmdldFByb3RvdHlwZSk7CiByZXR1cm4gJHRoaXM7Cn07CgovKioqLyB9KSwKLyogMTIxICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCnZhciBjcmVhdGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDc0KTsKdmFyIGRlZmluZUJ1aWx0SW5BY2Nlc3NvciA9IF9fd19wZGZqc19yZXF1aXJlX18oODUpOwp2YXIgZGVmaW5lQnVpbHRJbnMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyMik7CnZhciBiaW5kID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTIpOwp2YXIgYW5JbnN0YW5jZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTE4KTsKdmFyIGlzTnVsbE9yVW5kZWZpbmVkID0gX193X3BkZmpzX3JlcXVpcmVfXygyMSk7CnZhciBpdGVyYXRlID0gX193X3BkZmpzX3JlcXVpcmVfXygxMTEpOwp2YXIgZGVmaW5lSXRlcmF0b3IgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDk0KTsKdmFyIGNyZWF0ZUl0ZXJSZXN1bHRPYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDk4KTsKdmFyIHNldFNwZWNpZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyMyk7CnZhciBERVNDUklQVE9SUyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTApOwp2YXIgZmFzdEtleSA9IChfX3dfcGRmanNfcmVxdWlyZV9fKDEwNCkuZmFzdEtleSk7CnZhciBJbnRlcm5hbFN0YXRlTW9kdWxlID0gX193X3BkZmpzX3JlcXVpcmVfXyg1Nik7CnZhciBzZXRJbnRlcm5hbFN0YXRlID0gSW50ZXJuYWxTdGF0ZU1vZHVsZS5zZXQ7CnZhciBpbnRlcm5hbFN0YXRlR2V0dGVyRm9yID0gSW50ZXJuYWxTdGF0ZU1vZHVsZS5nZXR0ZXJGb3I7Cm1vZHVsZS5leHBvcnRzID0gewogZ2V0Q29uc3RydWN0b3I6IGZ1bmN0aW9uICh3cmFwcGVyLCBDT05TVFJVQ1RPUl9OQU1FLCBJU19NQVAsIEFEREVSKSB7CiAgdmFyIENvbnN0cnVjdG9yID0gd3JhcHBlcihmdW5jdGlvbiAodGhhdCwgaXRlcmFibGUpIHsKICAgYW5JbnN0YW5jZSh0aGF0LCBQcm90b3R5cGUpOwogICBzZXRJbnRlcm5hbFN0YXRlKHRoYXQsIHsKICAgIHR5cGU6IENPTlNUUlVDVE9SX05BTUUsCiAgICBpbmRleDogY3JlYXRlKG51bGwpLAogICAgZmlyc3Q6IHVuZGVmaW5lZCwKICAgIGxhc3Q6IHVuZGVmaW5lZCwKICAgIHNpemU6IDAKICAgfSk7CiAgIGlmICghREVTQ1JJUFRPUlMpCiAgICB0aGF0LnNpemUgPSAwOwogICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKGl0ZXJhYmxlKSkKICAgIGl0ZXJhdGUoaXRlcmFibGUsIHRoYXRbQURERVJdLCB7CiAgICAgdGhhdDogdGhhdCwKICAgICBBU19FTlRSSUVTOiBJU19NQVAKICAgIH0pOwogIH0pOwogIHZhciBQcm90b3R5cGUgPSBDb25zdHJ1Y3Rvci5wcm90b3R5cGU7CiAgdmFyIGdldEludGVybmFsU3RhdGUgPSBpbnRlcm5hbFN0YXRlR2V0dGVyRm9yKENPTlNUUlVDVE9SX05BTUUpOwogIHZhciBkZWZpbmUgPSBmdW5jdGlvbiAodGhhdCwga2V5LCB2YWx1ZSkgewogICB2YXIgc3RhdGUgPSBnZXRJbnRlcm5hbFN0YXRlKHRoYXQpOwogICB2YXIgZW50cnkgPSBnZXRFbnRyeSh0aGF0LCBrZXkpOwogICB2YXIgcHJldmlvdXMsIGluZGV4OwogICBpZiAoZW50cnkpIHsKICAgIGVudHJ5LnZhbHVlID0gdmFsdWU7CiAgIH0gZWxzZSB7CiAgICBzdGF0ZS5sYXN0ID0gZW50cnkgPSB7CiAgICAgaW5kZXg6IGluZGV4ID0gZmFzdEtleShrZXksIHRydWUpLAogICAgIGtleToga2V5LAogICAgIHZhbHVlOiB2YWx1ZSwKICAgICBwcmV2aW91czogcHJldmlvdXMgPSBzdGF0ZS5sYXN0LAogICAgIG5leHQ6IHVuZGVmaW5lZCwKICAgICByZW1vdmVkOiBmYWxzZQogICAgfTsKICAgIGlmICghc3RhdGUuZmlyc3QpCiAgICAgc3RhdGUuZmlyc3QgPSBlbnRyeTsKICAgIGlmIChwcmV2aW91cykKICAgICBwcmV2aW91cy5uZXh0ID0gZW50cnk7CiAgICBpZiAoREVTQ1JJUFRPUlMpCiAgICAgc3RhdGUuc2l6ZSsrOwogICAgZWxzZQogICAgIHRoYXQuc2l6ZSsrOwogICAgaWYgKGluZGV4ICE9PSAnRicpCiAgICAgc3RhdGUuaW5kZXhbaW5kZXhdID0gZW50cnk7CiAgIH0KICAgcmV0dXJuIHRoYXQ7CiAgfTsKICB2YXIgZ2V0RW50cnkgPSBmdW5jdGlvbiAodGhhdCwga2V5KSB7CiAgIHZhciBzdGF0ZSA9IGdldEludGVybmFsU3RhdGUodGhhdCk7CiAgIHZhciBpbmRleCA9IGZhc3RLZXkoa2V5KTsKICAgdmFyIGVudHJ5OwogICBpZiAoaW5kZXggIT09ICdGJykKICAgIHJldHVybiBzdGF0ZS5pbmRleFtpbmRleF07CiAgIGZvciAoZW50cnkgPSBzdGF0ZS5maXJzdDsgZW50cnk7IGVudHJ5ID0gZW50cnkubmV4dCkgewogICAgaWYgKGVudHJ5LmtleSA9PSBrZXkpCiAgICAgcmV0dXJuIGVudHJ5OwogICB9CiAgfTsKICBkZWZpbmVCdWlsdElucyhQcm90b3R5cGUsIHsKICAgY2xlYXI6IGZ1bmN0aW9uIGNsZWFyKCkgewogICAgdmFyIHRoYXQgPSB0aGlzOwogICAgdmFyIHN0YXRlID0gZ2V0SW50ZXJuYWxTdGF0ZSh0aGF0KTsKICAgIHZhciBkYXRhID0gc3RhdGUuaW5kZXg7CiAgICB2YXIgZW50cnkgPSBzdGF0ZS5maXJzdDsKICAgIHdoaWxlIChlbnRyeSkgewogICAgIGVudHJ5LnJlbW92ZWQgPSB0cnVlOwogICAgIGlmIChlbnRyeS5wcmV2aW91cykKICAgICAgZW50cnkucHJldmlvdXMgPSBlbnRyeS5wcmV2aW91cy5uZXh0ID0gdW5kZWZpbmVkOwogICAgIGRlbGV0ZSBkYXRhW2VudHJ5LmluZGV4XTsKICAgICBlbnRyeSA9IGVudHJ5Lm5leHQ7CiAgICB9CiAgICBzdGF0ZS5maXJzdCA9IHN0YXRlLmxhc3QgPSB1bmRlZmluZWQ7CiAgICBpZiAoREVTQ1JJUFRPUlMpCiAgICAgc3RhdGUuc2l6ZSA9IDA7CiAgICBlbHNlCiAgICAgdGhhdC5zaXplID0gMDsKICAgfSwKICAgJ2RlbGV0ZSc6IGZ1bmN0aW9uIChrZXkpIHsKICAgIHZhciB0aGF0ID0gdGhpczsKICAgIHZhciBzdGF0ZSA9IGdldEludGVybmFsU3RhdGUodGhhdCk7CiAgICB2YXIgZW50cnkgPSBnZXRFbnRyeSh0aGF0LCBrZXkpOwogICAgaWYgKGVudHJ5KSB7CiAgICAgdmFyIG5leHQgPSBlbnRyeS5uZXh0OwogICAgIHZhciBwcmV2ID0gZW50cnkucHJldmlvdXM7CiAgICAgZGVsZXRlIHN0YXRlLmluZGV4W2VudHJ5LmluZGV4XTsKICAgICBlbnRyeS5yZW1vdmVkID0gdHJ1ZTsKICAgICBpZiAocHJldikKICAgICAgcHJldi5uZXh0ID0gbmV4dDsKICAgICBpZiAobmV4dCkKICAgICAgbmV4dC5wcmV2aW91cyA9IHByZXY7CiAgICAgaWYgKHN0YXRlLmZpcnN0ID09IGVudHJ5KQogICAgICBzdGF0ZS5maXJzdCA9IG5leHQ7CiAgICAgaWYgKHN0YXRlLmxhc3QgPT0gZW50cnkpCiAgICAgIHN0YXRlLmxhc3QgPSBwcmV2OwogICAgIGlmIChERVNDUklQVE9SUykKICAgICAgc3RhdGUuc2l6ZS0tOwogICAgIGVsc2UKICAgICAgdGhhdC5zaXplLS07CiAgICB9CiAgICByZXR1cm4gISFlbnRyeTsKICAgfSwKICAgZm9yRWFjaDogZnVuY3Rpb24gZm9yRWFjaChjYWxsYmFja2ZuKSB7CiAgICB2YXIgc3RhdGUgPSBnZXRJbnRlcm5hbFN0YXRlKHRoaXMpOwogICAgdmFyIGJvdW5kRnVuY3Rpb24gPSBiaW5kKGNhbGxiYWNrZm4sIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkKTsKICAgIHZhciBlbnRyeTsKICAgIHdoaWxlIChlbnRyeSA9IGVudHJ5ID8gZW50cnkubmV4dCA6IHN0YXRlLmZpcnN0KSB7CiAgICAgYm91bmRGdW5jdGlvbihlbnRyeS52YWx1ZSwgZW50cnkua2V5LCB0aGlzKTsKICAgICB3aGlsZSAoZW50cnkgJiYgZW50cnkucmVtb3ZlZCkKICAgICAgZW50cnkgPSBlbnRyeS5wcmV2aW91czsKICAgIH0KICAgfSwKICAgaGFzOiBmdW5jdGlvbiBoYXMoa2V5KSB7CiAgICByZXR1cm4gISFnZXRFbnRyeSh0aGlzLCBrZXkpOwogICB9CiAgfSk7CiAgZGVmaW5lQnVpbHRJbnMoUHJvdG90eXBlLCBJU19NQVAgPyB7CiAgIGdldDogZnVuY3Rpb24gZ2V0KGtleSkgewogICAgdmFyIGVudHJ5ID0gZ2V0RW50cnkodGhpcywga2V5KTsKICAgIHJldHVybiBlbnRyeSAmJiBlbnRyeS52YWx1ZTsKICAgfSwKICAgc2V0OiBmdW5jdGlvbiBzZXQoa2V5LCB2YWx1ZSkgewogICAgcmV0dXJuIGRlZmluZSh0aGlzLCBrZXkgPT09IDAgPyAwIDoga2V5LCB2YWx1ZSk7CiAgIH0KICB9IDogewogICBhZGQ6IGZ1bmN0aW9uIGFkZCh2YWx1ZSkgewogICAgcmV0dXJuIGRlZmluZSh0aGlzLCB2YWx1ZSA9IHZhbHVlID09PSAwID8gMCA6IHZhbHVlLCB2YWx1ZSk7CiAgIH0KICB9KTsKICBpZiAoREVTQ1JJUFRPUlMpCiAgIGRlZmluZUJ1aWx0SW5BY2Nlc3NvcihQcm90b3R5cGUsICdzaXplJywgewogICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgcmV0dXJuIGdldEludGVybmFsU3RhdGUodGhpcykuc2l6ZTsKICAgIH0KICAgfSk7CiAgcmV0dXJuIENvbnN0cnVjdG9yOwogfSwKIHNldFN0cm9uZzogZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBDT05TVFJVQ1RPUl9OQU1FLCBJU19NQVApIHsKICB2YXIgSVRFUkFUT1JfTkFNRSA9IENPTlNUUlVDVE9SX05BTUUgKyAnIEl0ZXJhdG9yJzsKICB2YXIgZ2V0SW50ZXJuYWxDb2xsZWN0aW9uU3RhdGUgPSBpbnRlcm5hbFN0YXRlR2V0dGVyRm9yKENPTlNUUlVDVE9SX05BTUUpOwogIHZhciBnZXRJbnRlcm5hbEl0ZXJhdG9yU3RhdGUgPSBpbnRlcm5hbFN0YXRlR2V0dGVyRm9yKElURVJBVE9SX05BTUUpOwogIGRlZmluZUl0ZXJhdG9yKENvbnN0cnVjdG9yLCBDT05TVFJVQ1RPUl9OQU1FLCBmdW5jdGlvbiAoaXRlcmF0ZWQsIGtpbmQpIHsKICAgc2V0SW50ZXJuYWxTdGF0ZSh0aGlzLCB7CiAgICB0eXBlOiBJVEVSQVRPUl9OQU1FLAogICAgdGFyZ2V0OiBpdGVyYXRlZCwKICAgIHN0YXRlOiBnZXRJbnRlcm5hbENvbGxlY3Rpb25TdGF0ZShpdGVyYXRlZCksCiAgICBraW5kOiBraW5kLAogICAgbGFzdDogdW5kZWZpbmVkCiAgIH0pOwogIH0sIGZ1bmN0aW9uICgpIHsKICAgdmFyIHN0YXRlID0gZ2V0SW50ZXJuYWxJdGVyYXRvclN0YXRlKHRoaXMpOwogICB2YXIga2luZCA9IHN0YXRlLmtpbmQ7CiAgIHZhciBlbnRyeSA9IHN0YXRlLmxhc3Q7CiAgIHdoaWxlIChlbnRyeSAmJiBlbnRyeS5yZW1vdmVkKQogICAgZW50cnkgPSBlbnRyeS5wcmV2aW91czsKICAgaWYgKCFzdGF0ZS50YXJnZXQgfHwgIShzdGF0ZS5sYXN0ID0gZW50cnkgPSBlbnRyeSA/IGVudHJ5Lm5leHQgOiBzdGF0ZS5zdGF0ZS5maXJzdCkpIHsKICAgIHN0YXRlLnRhcmdldCA9IHVuZGVmaW5lZDsKICAgIHJldHVybiBjcmVhdGVJdGVyUmVzdWx0T2JqZWN0KHVuZGVmaW5lZCwgdHJ1ZSk7CiAgIH0KICAgaWYgKGtpbmQgPT0gJ2tleXMnKQogICAgcmV0dXJuIGNyZWF0ZUl0ZXJSZXN1bHRPYmplY3QoZW50cnkua2V5LCBmYWxzZSk7CiAgIGlmIChraW5kID09ICd2YWx1ZXMnKQogICAgcmV0dXJuIGNyZWF0ZUl0ZXJSZXN1bHRPYmplY3QoZW50cnkudmFsdWUsIGZhbHNlKTsKICAgcmV0dXJuIGNyZWF0ZUl0ZXJSZXN1bHRPYmplY3QoWwogICAgZW50cnkua2V5LAogICAgZW50cnkudmFsdWUKICAgXSwgZmFsc2UpOwogIH0sIElTX01BUCA/ICdlbnRyaWVzJyA6ICd2YWx1ZXMnLCAhSVNfTUFQLCB0cnVlKTsKICBzZXRTcGVjaWVzKENPTlNUUlVDVE9SX05BTUUpOwogfQp9OwoKLyoqKi8gfSksCi8qIDEyMiAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7Cgp2YXIgZGVmaW5lQnVpbHRJbiA9IF9fd19wZGZqc19yZXF1aXJlX18oNTIpOwptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh0YXJnZXQsIHNyYywgb3B0aW9ucykgewogZm9yICh2YXIga2V5IGluIHNyYykKICBkZWZpbmVCdWlsdEluKHRhcmdldCwga2V5LCBzcmNba2V5XSwgb3B0aW9ucyk7CiByZXR1cm4gdGFyZ2V0Owp9OwoKLyoqKi8gfSksCi8qIDEyMyAqLwovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7Cgp2YXIgZ2V0QnVpbHRJbiA9IF9fd19wZGZqc19yZXF1aXJlX18oMjgpOwp2YXIgZGVmaW5lQnVpbHRJbkFjY2Vzc29yID0gX193X3BkZmpzX3JlcXVpcmVfXyg4NSk7CnZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDM4KTsKdmFyIERFU0NSSVBUT1JTID0gX193X3BkZmpzX3JlcXVpcmVfXygxMCk7CnZhciBTUEVDSUVTID0gd2VsbEtub3duU3ltYm9sKCdzcGVjaWVzJyk7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKENPTlNUUlVDVE9SX05BTUUpIHsKIHZhciBDb25zdHJ1Y3RvciA9IGdldEJ1aWx0SW4oQ09OU1RSVUNUT1JfTkFNRSk7CiBpZiAoREVTQ1JJUFRPUlMgJiYgQ29uc3RydWN0b3IgJiYgIUNvbnN0cnVjdG9yW1NQRUNJRVNdKSB7CiAgZGVmaW5lQnVpbHRJbkFjY2Vzc29yKENvbnN0cnVjdG9yLCBTUEVDSUVTLCB7CiAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICByZXR1cm4gdGhpczsKICAgfQogIH0pOwogfQp9OwoKLyoqKi8gfSksCi8qIDEyNCAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCl9fd19wZGZqc19yZXF1aXJlX18oMTI1KTsKCi8qKiovIH0pLAovKiAxMjUgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7Cgp2YXIgY29sbGVjdGlvbiA9IF9fd19wZGZqc19yZXF1aXJlX18oMTAzKTsKdmFyIGNvbGxlY3Rpb25TdHJvbmcgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyMSk7CmNvbGxlY3Rpb24oJ1NldCcsIGZ1bmN0aW9uIChpbml0KSB7CiByZXR1cm4gZnVuY3Rpb24gU2V0KCkgewogIHJldHVybiBpbml0KHRoaXMsIGFyZ3VtZW50cy5sZW5ndGggPyBhcmd1bWVudHNbMF0gOiB1bmRlZmluZWQpOwogfTsKfSwgY29sbGVjdGlvblN0cm9uZyk7CgovKioqLyB9KSwKLyogMTI2ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIElTX1BVUkUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQwKTsKdmFyICQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDcpOwp2YXIgZ2xvYmFsID0gX193X3BkZmpzX3JlcXVpcmVfXyg4KTsKdmFyIGdldEJ1aWx0aW4gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI4KTsKdmFyIHVuY3VycnlUaGlzID0gX193X3BkZmpzX3JlcXVpcmVfXygxOCk7CnZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEpOwp2YXIgdWlkID0gX193X3BkZmpzX3JlcXVpcmVfXyg0NSk7CnZhciBpc0NhbGxhYmxlID0gX193X3BkZmpzX3JlcXVpcmVfXygyNSk7CnZhciBpc0NvbnN0cnVjdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXygxMjcpOwp2YXIgaXNOdWxsT3JVbmRlZmluZWQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxKTsKdmFyIGlzT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyNCk7CnZhciBpc1N5bWJvbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjcpOwp2YXIgaXRlcmF0ZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTExKTsKdmFyIGFuT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXyg1MSk7CnZhciBjbGFzc29mID0gX193X3BkZmpzX3JlcXVpcmVfXyg4Myk7CnZhciBoYXNPd24gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQzKTsKdmFyIGNyZWF0ZVByb3BlcnR5ID0gX193X3BkZmpzX3JlcXVpcmVfXygxMDcpOwp2YXIgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5ID0gX193X3BkZmpzX3JlcXVpcmVfXyg0OCk7CnZhciBsZW5ndGhPZkFycmF5TGlrZSA9IF9fd19wZGZqc19yZXF1aXJlX18oNjgpOwp2YXIgdmFsaWRhdGVBcmd1bWVudHNMZW5ndGggPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEyOCk7CnZhciBnZXRSZWdFeHBGbGFncyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTI5KTsKdmFyIE1hcEhlbHBlcnMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzMSk7CnZhciBTZXRIZWxwZXJzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzIpOwp2YXIgRVJST1JfU1RBQ0tfSU5TVEFMTEFCTEUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzMyk7CnZhciBQUk9QRVJfVFJBTlNGRVIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzNCk7CnZhciBPYmplY3QgPSBnbG9iYWwuT2JqZWN0Owp2YXIgQXJyYXkgPSBnbG9iYWwuQXJyYXk7CnZhciBEYXRlID0gZ2xvYmFsLkRhdGU7CnZhciBFcnJvciA9IGdsb2JhbC5FcnJvcjsKdmFyIEV2YWxFcnJvciA9IGdsb2JhbC5FdmFsRXJyb3I7CnZhciBSYW5nZUVycm9yID0gZ2xvYmFsLlJhbmdlRXJyb3I7CnZhciBSZWZlcmVuY2VFcnJvciA9IGdsb2JhbC5SZWZlcmVuY2VFcnJvcjsKdmFyIFN5bnRheEVycm9yID0gZ2xvYmFsLlN5bnRheEVycm9yOwp2YXIgVHlwZUVycm9yID0gZ2xvYmFsLlR5cGVFcnJvcjsKdmFyIFVSSUVycm9yID0gZ2xvYmFsLlVSSUVycm9yOwp2YXIgUGVyZm9ybWFuY2VNYXJrID0gZ2xvYmFsLlBlcmZvcm1hbmNlTWFyazsKdmFyIFdlYkFzc2VtYmx5ID0gZ2xvYmFsLldlYkFzc2VtYmx5Owp2YXIgQ29tcGlsZUVycm9yID0gV2ViQXNzZW1ibHkgJiYgV2ViQXNzZW1ibHkuQ29tcGlsZUVycm9yIHx8IEVycm9yOwp2YXIgTGlua0Vycm9yID0gV2ViQXNzZW1ibHkgJiYgV2ViQXNzZW1ibHkuTGlua0Vycm9yIHx8IEVycm9yOwp2YXIgUnVudGltZUVycm9yID0gV2ViQXNzZW1ibHkgJiYgV2ViQXNzZW1ibHkuUnVudGltZUVycm9yIHx8IEVycm9yOwp2YXIgRE9NRXhjZXB0aW9uID0gZ2V0QnVpbHRpbignRE9NRXhjZXB0aW9uJyk7CnZhciBNYXAgPSBNYXBIZWxwZXJzLk1hcDsKdmFyIG1hcEhhcyA9IE1hcEhlbHBlcnMuaGFzOwp2YXIgbWFwR2V0ID0gTWFwSGVscGVycy5nZXQ7CnZhciBtYXBTZXQgPSBNYXBIZWxwZXJzLnNldDsKdmFyIFNldCA9IFNldEhlbHBlcnMuU2V0Owp2YXIgc2V0QWRkID0gU2V0SGVscGVycy5hZGQ7CnZhciBvYmplY3RLZXlzID0gZ2V0QnVpbHRpbignT2JqZWN0JywgJ2tleXMnKTsKdmFyIHB1c2ggPSB1bmN1cnJ5VGhpcyhbXS5wdXNoKTsKdmFyIHRoaXNCb29sZWFuVmFsdWUgPSB1bmN1cnJ5VGhpcyh0cnVlLnZhbHVlT2YpOwp2YXIgdGhpc051bWJlclZhbHVlID0gdW5jdXJyeVRoaXMoMS4wLnZhbHVlT2YpOwp2YXIgdGhpc1N0cmluZ1ZhbHVlID0gdW5jdXJyeVRoaXMoJycudmFsdWVPZik7CnZhciB0aGlzVGltZVZhbHVlID0gdW5jdXJyeVRoaXMoRGF0ZS5wcm90b3R5cGUuZ2V0VGltZSk7CnZhciBQRVJGT1JNQU5DRV9NQVJLID0gdWlkKCdzdHJ1Y3R1cmVkQ2xvbmUnKTsKdmFyIERBVEFfQ0xPTkVfRVJST1IgPSAnRGF0YUNsb25lRXJyb3InOwp2YXIgVFJBTlNGRVJSSU5HID0gJ1RyYW5zZmVycmluZyc7CnZhciBjaGVja0Jhc2ljU2VtYW50aWMgPSBmdW5jdGlvbiAoc3RydWN0dXJlZENsb25lSW1wbGVtZW50YXRpb24pIHsKIHJldHVybiAhZmFpbHMoZnVuY3Rpb24gKCkgewogIHZhciBzZXQxID0gbmV3IGdsb2JhbC5TZXQoWzddKTsKICB2YXIgc2V0MiA9IHN0cnVjdHVyZWRDbG9uZUltcGxlbWVudGF0aW9uKHNldDEpOwogIHZhciBudW1iZXIgPSBzdHJ1Y3R1cmVkQ2xvbmVJbXBsZW1lbnRhdGlvbihPYmplY3QoNykpOwogIHJldHVybiBzZXQyID09IHNldDEgfHwgIXNldDIuaGFzKDcpIHx8IHR5cGVvZiBudW1iZXIgIT0gJ29iamVjdCcgfHwgbnVtYmVyICE9IDc7CiB9KSAmJiBzdHJ1Y3R1cmVkQ2xvbmVJbXBsZW1lbnRhdGlvbjsKfTsKdmFyIGNoZWNrRXJyb3JzQ2xvbmluZyA9IGZ1bmN0aW9uIChzdHJ1Y3R1cmVkQ2xvbmVJbXBsZW1lbnRhdGlvbiwgJEVycm9yKSB7CiByZXR1cm4gIWZhaWxzKGZ1bmN0aW9uICgpIHsKICB2YXIgZXJyb3IgPSBuZXcgJEVycm9yKCk7CiAgdmFyIHRlc3QgPSBzdHJ1Y3R1cmVkQ2xvbmVJbXBsZW1lbnRhdGlvbih7CiAgIGE6IGVycm9yLAogICBiOiBlcnJvcgogIH0pOwogIHJldHVybiAhKHRlc3QgJiYgdGVzdC5hID09PSB0ZXN0LmIgJiYgdGVzdC5hIGluc3RhbmNlb2YgJEVycm9yICYmIHRlc3QuYS5zdGFjayA9PT0gZXJyb3Iuc3RhY2spOwogfSk7Cn07CnZhciBjaGVja05ld0Vycm9yc0Nsb25pbmdTZW1hbnRpYyA9IGZ1bmN0aW9uIChzdHJ1Y3R1cmVkQ2xvbmVJbXBsZW1lbnRhdGlvbikgewogcmV0dXJuICFmYWlscyhmdW5jdGlvbiAoKSB7CiAgdmFyIHRlc3QgPSBzdHJ1Y3R1cmVkQ2xvbmVJbXBsZW1lbnRhdGlvbihuZXcgZ2xvYmFsLkFnZ3JlZ2F0ZUVycm9yKFsxXSwgUEVSRk9STUFOQ0VfTUFSSywgeyBjYXVzZTogMyB9KSk7CiAgcmV0dXJuIHRlc3QubmFtZSAhPSAnQWdncmVnYXRlRXJyb3InIHx8IHRlc3QuZXJyb3JzWzBdICE9IDEgfHwgdGVzdC5tZXNzYWdlICE9IFBFUkZPUk1BTkNFX01BUksgfHwgdGVzdC5jYXVzZSAhPSAzOwogfSk7Cn07CnZhciBuYXRpdmVTdHJ1Y3R1cmVkQ2xvbmUgPSBnbG9iYWwuc3RydWN0dXJlZENsb25lOwp2YXIgRk9SQ0VEX1JFUExBQ0VNRU5UID0gSVNfUFVSRSB8fCAhY2hlY2tFcnJvcnNDbG9uaW5nKG5hdGl2ZVN0cnVjdHVyZWRDbG9uZSwgRXJyb3IpIHx8ICFjaGVja0Vycm9yc0Nsb25pbmcobmF0aXZlU3RydWN0dXJlZENsb25lLCBET01FeGNlcHRpb24pIHx8ICFjaGVja05ld0Vycm9yc0Nsb25pbmdTZW1hbnRpYyhuYXRpdmVTdHJ1Y3R1cmVkQ2xvbmUpOwp2YXIgc3RydWN0dXJlZENsb25lRnJvbU1hcmsgPSAhbmF0aXZlU3RydWN0dXJlZENsb25lICYmIGNoZWNrQmFzaWNTZW1hbnRpYyhmdW5jdGlvbiAodmFsdWUpIHsKIHJldHVybiBuZXcgUGVyZm9ybWFuY2VNYXJrKFBFUkZPUk1BTkNFX01BUkssIHsgZGV0YWlsOiB2YWx1ZSB9KS5kZXRhaWw7Cn0pOwp2YXIgbmF0aXZlUmVzdHJpY3RlZFN0cnVjdHVyZWRDbG9uZSA9IGNoZWNrQmFzaWNTZW1hbnRpYyhuYXRpdmVTdHJ1Y3R1cmVkQ2xvbmUpIHx8IHN0cnVjdHVyZWRDbG9uZUZyb21NYXJrOwp2YXIgdGhyb3dVbmNsb25lYWJsZSA9IGZ1bmN0aW9uICh0eXBlKSB7CiB0aHJvdyBuZXcgRE9NRXhjZXB0aW9uKCdVbmNsb25lYWJsZSB0eXBlOiAnICsgdHlwZSwgREFUQV9DTE9ORV9FUlJPUik7Cn07CnZhciB0aHJvd1VucG9seWZpbGxhYmxlID0gZnVuY3Rpb24gKHR5cGUsIGFjdGlvbikgewogdGhyb3cgbmV3IERPTUV4Y2VwdGlvbigoYWN0aW9uIHx8ICdDbG9uaW5nJykgKyAnIG9mICcgKyB0eXBlICsgJyBjYW5ub3QgYmUgcHJvcGVybHkgcG9seWZpbGxlZCBpbiB0aGlzIGVuZ2luZScsIERBVEFfQ0xPTkVfRVJST1IpOwp9Owp2YXIgY3JlYXRlRGF0YVRyYW5zZmVyID0gZnVuY3Rpb24gKCkgewogdmFyIGRhdGFUcmFuc2ZlcjsKIHRyeSB7CiAgZGF0YVRyYW5zZmVyID0gbmV3IGdsb2JhbC5EYXRhVHJhbnNmZXIoKTsKIH0gY2F0Y2ggKGVycm9yKSB7CiAgdHJ5IHsKICAgZGF0YVRyYW5zZmVyID0gbmV3IGdsb2JhbC5DbGlwYm9hcmRFdmVudCgnJykuY2xpcGJvYXJkRGF0YTsKICB9IGNhdGNoIChlcnJvcjIpIHsKICB9CiB9CiByZXR1cm4gZGF0YVRyYW5zZmVyICYmIGRhdGFUcmFuc2Zlci5pdGVtcyAmJiBkYXRhVHJhbnNmZXIuZmlsZXMgPyBkYXRhVHJhbnNmZXIgOiBudWxsOwp9Owp2YXIgc3RydWN0dXJlZENsb25lSW50ZXJuYWwgPSBmdW5jdGlvbiAodmFsdWUsIG1hcCkgewogaWYgKGlzU3ltYm9sKHZhbHVlKSkKICB0aHJvd1VuY2xvbmVhYmxlKCdTeW1ib2wnKTsKIGlmICghaXNPYmplY3QodmFsdWUpKQogIHJldHVybiB2YWx1ZTsKIGlmIChtYXApIHsKICBpZiAobWFwSGFzKG1hcCwgdmFsdWUpKQogICByZXR1cm4gbWFwR2V0KG1hcCwgdmFsdWUpOwogfSBlbHNlCiAgbWFwID0gbmV3IE1hcCgpOwogdmFyIHR5cGUgPSBjbGFzc29mKHZhbHVlKTsKIHZhciBkZWVwID0gZmFsc2U7CiB2YXIgQywgbmFtZSwgY2xvbmVkLCBkYXRhVHJhbnNmZXIsIGksIGxlbmd0aCwga2V5cywga2V5LCBzb3VyY2UsIHRhcmdldCwgb3B0aW9uczsKIHN3aXRjaCAodHlwZSkgewogY2FzZSAnQXJyYXknOgogIGNsb25lZCA9IEFycmF5KGxlbmd0aE9mQXJyYXlMaWtlKHZhbHVlKSk7CiAgZGVlcCA9IHRydWU7CiAgYnJlYWs7CiBjYXNlICdPYmplY3QnOgogIGNsb25lZCA9IHt9OwogIGRlZXAgPSB0cnVlOwogIGJyZWFrOwogY2FzZSAnTWFwJzoKICBjbG9uZWQgPSBuZXcgTWFwKCk7CiAgZGVlcCA9IHRydWU7CiAgYnJlYWs7CiBjYXNlICdTZXQnOgogIGNsb25lZCA9IG5ldyBTZXQoKTsKICBkZWVwID0gdHJ1ZTsKICBicmVhazsKIGNhc2UgJ1JlZ0V4cCc6CiAgY2xvbmVkID0gbmV3IFJlZ0V4cCh2YWx1ZS5zb3VyY2UsIGdldFJlZ0V4cEZsYWdzKHZhbHVlKSk7CiAgYnJlYWs7CiBjYXNlICdFcnJvcic6CiAgbmFtZSA9IHZhbHVlLm5hbWU7CiAgc3dpdGNoIChuYW1lKSB7CiAgY2FzZSAnQWdncmVnYXRlRXJyb3InOgogICBjbG9uZWQgPSBnZXRCdWlsdGluKCdBZ2dyZWdhdGVFcnJvcicpKFtdKTsKICAgYnJlYWs7CiAgY2FzZSAnRXZhbEVycm9yJzoKICAgY2xvbmVkID0gRXZhbEVycm9yKCk7CiAgIGJyZWFrOwogIGNhc2UgJ1JhbmdlRXJyb3InOgogICBjbG9uZWQgPSBSYW5nZUVycm9yKCk7CiAgIGJyZWFrOwogIGNhc2UgJ1JlZmVyZW5jZUVycm9yJzoKICAgY2xvbmVkID0gUmVmZXJlbmNlRXJyb3IoKTsKICAgYnJlYWs7CiAgY2FzZSAnU3ludGF4RXJyb3InOgogICBjbG9uZWQgPSBTeW50YXhFcnJvcigpOwogICBicmVhazsKICBjYXNlICdUeXBlRXJyb3InOgogICBjbG9uZWQgPSBUeXBlRXJyb3IoKTsKICAgYnJlYWs7CiAgY2FzZSAnVVJJRXJyb3InOgogICBjbG9uZWQgPSBVUklFcnJvcigpOwogICBicmVhazsKICBjYXNlICdDb21waWxlRXJyb3InOgogICBjbG9uZWQgPSBDb21waWxlRXJyb3IoKTsKICAgYnJlYWs7CiAgY2FzZSAnTGlua0Vycm9yJzoKICAgY2xvbmVkID0gTGlua0Vycm9yKCk7CiAgIGJyZWFrOwogIGNhc2UgJ1J1bnRpbWVFcnJvcic6CiAgIGNsb25lZCA9IFJ1bnRpbWVFcnJvcigpOwogICBicmVhazsKICBkZWZhdWx0OgogICBjbG9uZWQgPSBFcnJvcigpOwogIH0KICBkZWVwID0gdHJ1ZTsKICBicmVhazsKIGNhc2UgJ0RPTUV4Y2VwdGlvbic6CiAgY2xvbmVkID0gbmV3IERPTUV4Y2VwdGlvbih2YWx1ZS5tZXNzYWdlLCB2YWx1ZS5uYW1lKTsKICBkZWVwID0gdHJ1ZTsKICBicmVhazsKIGNhc2UgJ0RhdGFWaWV3JzoKIGNhc2UgJ0ludDhBcnJheSc6CiBjYXNlICdVaW50OEFycmF5JzoKIGNhc2UgJ1VpbnQ4Q2xhbXBlZEFycmF5JzoKIGNhc2UgJ0ludDE2QXJyYXknOgogY2FzZSAnVWludDE2QXJyYXknOgogY2FzZSAnSW50MzJBcnJheSc6CiBjYXNlICdVaW50MzJBcnJheSc6CiBjYXNlICdGbG9hdDMyQXJyYXknOgogY2FzZSAnRmxvYXQ2NEFycmF5JzoKIGNhc2UgJ0JpZ0ludDY0QXJyYXknOgogY2FzZSAnQmlnVWludDY0QXJyYXknOgogIEMgPSBnbG9iYWxbdHlwZV07CiAgaWYgKCFpc09iamVjdChDKSkKICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlKTsKICBjbG9uZWQgPSBuZXcgQyhzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbCh2YWx1ZS5idWZmZXIsIG1hcCksIHZhbHVlLmJ5dGVPZmZzZXQsIHR5cGUgPT09ICdEYXRhVmlldycgPyB2YWx1ZS5ieXRlTGVuZ3RoIDogdmFsdWUubGVuZ3RoKTsKICBicmVhazsKIGNhc2UgJ0RPTVF1YWQnOgogIHRyeSB7CiAgIGNsb25lZCA9IG5ldyBET01RdWFkKHN0cnVjdHVyZWRDbG9uZUludGVybmFsKHZhbHVlLnAxLCBtYXApLCBzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbCh2YWx1ZS5wMiwgbWFwKSwgc3RydWN0dXJlZENsb25lSW50ZXJuYWwodmFsdWUucDMsIG1hcCksIHN0cnVjdHVyZWRDbG9uZUludGVybmFsKHZhbHVlLnA0LCBtYXApKTsKICB9IGNhdGNoIChlcnJvcikgewogICBpZiAobmF0aXZlUmVzdHJpY3RlZFN0cnVjdHVyZWRDbG9uZSkgewogICAgY2xvbmVkID0gbmF0aXZlUmVzdHJpY3RlZFN0cnVjdHVyZWRDbG9uZSh2YWx1ZSk7CiAgIH0gZWxzZQogICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlKTsKICB9CiAgYnJlYWs7CiBjYXNlICdGaWxlTGlzdCc6CiAgZGF0YVRyYW5zZmVyID0gY3JlYXRlRGF0YVRyYW5zZmVyKCk7CiAgaWYgKGRhdGFUcmFuc2ZlcikgewogICBmb3IgKGkgPSAwLCBsZW5ndGggPSBsZW5ndGhPZkFycmF5TGlrZSh2YWx1ZSk7IGkgPCBsZW5ndGg7IGkrKykgewogICAgZGF0YVRyYW5zZmVyLml0ZW1zLmFkZChzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbCh2YWx1ZVtpXSwgbWFwKSk7CiAgIH0KICAgY2xvbmVkID0gZGF0YVRyYW5zZmVyLmZpbGVzOwogIH0gZWxzZSBpZiAobmF0aXZlUmVzdHJpY3RlZFN0cnVjdHVyZWRDbG9uZSkgewogICBjbG9uZWQgPSBuYXRpdmVSZXN0cmljdGVkU3RydWN0dXJlZENsb25lKHZhbHVlKTsKICB9IGVsc2UKICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlKTsKICBicmVhazsKIGNhc2UgJ0ltYWdlRGF0YSc6CiAgdHJ5IHsKICAgY2xvbmVkID0gbmV3IEltYWdlRGF0YShzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbCh2YWx1ZS5kYXRhLCBtYXApLCB2YWx1ZS53aWR0aCwgdmFsdWUuaGVpZ2h0LCB7IGNvbG9yU3BhY2U6IHZhbHVlLmNvbG9yU3BhY2UgfSk7CiAgfSBjYXRjaCAoZXJyb3IpIHsKICAgaWYgKG5hdGl2ZVJlc3RyaWN0ZWRTdHJ1Y3R1cmVkQ2xvbmUpIHsKICAgIGNsb25lZCA9IG5hdGl2ZVJlc3RyaWN0ZWRTdHJ1Y3R1cmVkQ2xvbmUodmFsdWUpOwogICB9IGVsc2UKICAgIHRocm93VW5wb2x5ZmlsbGFibGUodHlwZSk7CiAgfQogIGJyZWFrOwogZGVmYXVsdDoKICBpZiAobmF0aXZlUmVzdHJpY3RlZFN0cnVjdHVyZWRDbG9uZSkgewogICBjbG9uZWQgPSBuYXRpdmVSZXN0cmljdGVkU3RydWN0dXJlZENsb25lKHZhbHVlKTsKICB9IGVsc2UKICAgc3dpdGNoICh0eXBlKSB7CiAgIGNhc2UgJ0JpZ0ludCc6CiAgICBjbG9uZWQgPSBPYmplY3QodmFsdWUudmFsdWVPZigpKTsKICAgIGJyZWFrOwogICBjYXNlICdCb29sZWFuJzoKICAgIGNsb25lZCA9IE9iamVjdCh0aGlzQm9vbGVhblZhbHVlKHZhbHVlKSk7CiAgICBicmVhazsKICAgY2FzZSAnTnVtYmVyJzoKICAgIGNsb25lZCA9IE9iamVjdCh0aGlzTnVtYmVyVmFsdWUodmFsdWUpKTsKICAgIGJyZWFrOwogICBjYXNlICdTdHJpbmcnOgogICAgY2xvbmVkID0gT2JqZWN0KHRoaXNTdHJpbmdWYWx1ZSh2YWx1ZSkpOwogICAgYnJlYWs7CiAgIGNhc2UgJ0RhdGUnOgogICAgY2xvbmVkID0gbmV3IERhdGUodGhpc1RpbWVWYWx1ZSh2YWx1ZSkpOwogICAgYnJlYWs7CiAgIGNhc2UgJ0FycmF5QnVmZmVyJzoKICAgIEMgPSBnbG9iYWwuRGF0YVZpZXc7CiAgICBpZiAoIUMgJiYgdHlwZW9mIHZhbHVlLnNsaWNlICE9ICdmdW5jdGlvbicpCiAgICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlKTsKICAgIHRyeSB7CiAgICAgaWYgKHR5cGVvZiB2YWx1ZS5zbGljZSA9PSAnZnVuY3Rpb24nICYmICF2YWx1ZS5yZXNpemFibGUpIHsKICAgICAgY2xvbmVkID0gdmFsdWUuc2xpY2UoMCk7CiAgICAgfSBlbHNlIHsKICAgICAgbGVuZ3RoID0gdmFsdWUuYnl0ZUxlbmd0aDsKICAgICAgb3B0aW9ucyA9ICdtYXhCeXRlTGVuZ3RoJyBpbiB2YWx1ZSA/IHsgbWF4Qnl0ZUxlbmd0aDogdmFsdWUubWF4Qnl0ZUxlbmd0aCB9IDogdW5kZWZpbmVkOwogICAgICBjbG9uZWQgPSBuZXcgQXJyYXlCdWZmZXIobGVuZ3RoLCBvcHRpb25zKTsKICAgICAgc291cmNlID0gbmV3IEModmFsdWUpOwogICAgICB0YXJnZXQgPSBuZXcgQyhjbG9uZWQpOwogICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgIHRhcmdldC5zZXRVaW50OChpLCBzb3VyY2UuZ2V0VWludDgoaSkpOwogICAgICB9CiAgICAgfQogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICB0aHJvdyBuZXcgRE9NRXhjZXB0aW9uKCdBcnJheUJ1ZmZlciBpcyBkZXRhY2hlZCcsIERBVEFfQ0xPTkVfRVJST1IpOwogICAgfQogICAgYnJlYWs7CiAgIGNhc2UgJ1NoYXJlZEFycmF5QnVmZmVyJzoKICAgIGNsb25lZCA9IHZhbHVlOwogICAgYnJlYWs7CiAgIGNhc2UgJ0Jsb2InOgogICAgdHJ5IHsKICAgICBjbG9uZWQgPSB2YWx1ZS5zbGljZSgwLCB2YWx1ZS5zaXplLCB2YWx1ZS50eXBlKTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlKTsKICAgIH0KICAgIGJyZWFrOwogICBjYXNlICdET01Qb2ludCc6CiAgIGNhc2UgJ0RPTVBvaW50UmVhZE9ubHknOgogICAgQyA9IGdsb2JhbFt0eXBlXTsKICAgIHRyeSB7CiAgICAgY2xvbmVkID0gQy5mcm9tUG9pbnQgPyBDLmZyb21Qb2ludCh2YWx1ZSkgOiBuZXcgQyh2YWx1ZS54LCB2YWx1ZS55LCB2YWx1ZS56LCB2YWx1ZS53KTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlKTsKICAgIH0KICAgIGJyZWFrOwogICBjYXNlICdET01SZWN0JzoKICAgY2FzZSAnRE9NUmVjdFJlYWRPbmx5JzoKICAgIEMgPSBnbG9iYWxbdHlwZV07CiAgICB0cnkgewogICAgIGNsb25lZCA9IEMuZnJvbVJlY3QgPyBDLmZyb21SZWN0KHZhbHVlKSA6IG5ldyBDKHZhbHVlLngsIHZhbHVlLnksIHZhbHVlLndpZHRoLCB2YWx1ZS5oZWlnaHQpOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICB0aHJvd1VucG9seWZpbGxhYmxlKHR5cGUpOwogICAgfQogICAgYnJlYWs7CiAgIGNhc2UgJ0RPTU1hdHJpeCc6CiAgIGNhc2UgJ0RPTU1hdHJpeFJlYWRPbmx5JzoKICAgIEMgPSBnbG9iYWxbdHlwZV07CiAgICB0cnkgewogICAgIGNsb25lZCA9IEMuZnJvbU1hdHJpeCA/IEMuZnJvbU1hdHJpeCh2YWx1ZSkgOiBuZXcgQyh2YWx1ZSk7CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgIHRocm93VW5wb2x5ZmlsbGFibGUodHlwZSk7CiAgICB9CiAgICBicmVhazsKICAgY2FzZSAnQXVkaW9EYXRhJzoKICAgY2FzZSAnVmlkZW9GcmFtZSc6CiAgICBpZiAoIWlzQ2FsbGFibGUodmFsdWUuY2xvbmUpKQogICAgIHRocm93VW5wb2x5ZmlsbGFibGUodHlwZSk7CiAgICB0cnkgewogICAgIGNsb25lZCA9IHZhbHVlLmNsb25lKCk7CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgIHRocm93VW5jbG9uZWFibGUodHlwZSk7CiAgICB9CiAgICBicmVhazsKICAgY2FzZSAnRmlsZSc6CiAgICB0cnkgewogICAgIGNsb25lZCA9IG5ldyBGaWxlKFt2YWx1ZV0sIHZhbHVlLm5hbWUsIHZhbHVlKTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlKTsKICAgIH0KICAgIGJyZWFrOwogICBjYXNlICdDcm9wVGFyZ2V0JzoKICAgY2FzZSAnQ3J5cHRvS2V5JzoKICAgY2FzZSAnRmlsZVN5c3RlbURpcmVjdG9yeUhhbmRsZSc6CiAgIGNhc2UgJ0ZpbGVTeXN0ZW1GaWxlSGFuZGxlJzoKICAgY2FzZSAnRmlsZVN5c3RlbUhhbmRsZSc6CiAgIGNhc2UgJ0dQVUNvbXBpbGF0aW9uSW5mbyc6CiAgIGNhc2UgJ0dQVUNvbXBpbGF0aW9uTWVzc2FnZSc6CiAgIGNhc2UgJ0ltYWdlQml0bWFwJzoKICAgY2FzZSAnUlRDQ2VydGlmaWNhdGUnOgogICBjYXNlICdXZWJBc3NlbWJseS5Nb2R1bGUnOgogICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlKTsKICAgZGVmYXVsdDoKICAgIHRocm93VW5jbG9uZWFibGUodHlwZSk7CiAgIH0KIH0KIG1hcFNldChtYXAsIHZhbHVlLCBjbG9uZWQpOwogaWYgKGRlZXApCiAgc3dpdGNoICh0eXBlKSB7CiAgY2FzZSAnQXJyYXknOgogIGNhc2UgJ09iamVjdCc6CiAgIGtleXMgPSBvYmplY3RLZXlzKHZhbHVlKTsKICAgZm9yIChpID0gMCwgbGVuZ3RoID0gbGVuZ3RoT2ZBcnJheUxpa2Uoa2V5cyk7IGkgPCBsZW5ndGg7IGkrKykgewogICAga2V5ID0ga2V5c1tpXTsKICAgIGNyZWF0ZVByb3BlcnR5KGNsb25lZCwga2V5LCBzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbCh2YWx1ZVtrZXldLCBtYXApKTsKICAgfQogICBicmVhazsKICBjYXNlICdNYXAnOgogICB2YWx1ZS5mb3JFYWNoKGZ1bmN0aW9uICh2LCBrKSB7CiAgICBtYXBTZXQoY2xvbmVkLCBzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbChrLCBtYXApLCBzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbCh2LCBtYXApKTsKICAgfSk7CiAgIGJyZWFrOwogIGNhc2UgJ1NldCc6CiAgIHZhbHVlLmZvckVhY2goZnVuY3Rpb24gKHYpIHsKICAgIHNldEFkZChjbG9uZWQsIHN0cnVjdHVyZWRDbG9uZUludGVybmFsKHYsIG1hcCkpOwogICB9KTsKICAgYnJlYWs7CiAgY2FzZSAnRXJyb3InOgogICBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoY2xvbmVkLCAnbWVzc2FnZScsIHN0cnVjdHVyZWRDbG9uZUludGVybmFsKHZhbHVlLm1lc3NhZ2UsIG1hcCkpOwogICBpZiAoaGFzT3duKHZhbHVlLCAnY2F1c2UnKSkgewogICAgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KGNsb25lZCwgJ2NhdXNlJywgc3RydWN0dXJlZENsb25lSW50ZXJuYWwodmFsdWUuY2F1c2UsIG1hcCkpOwogICB9CiAgIGlmIChuYW1lID09ICdBZ2dyZWdhdGVFcnJvcicpIHsKICAgIGNsb25lZC5lcnJvcnMgPSBzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbCh2YWx1ZS5lcnJvcnMsIG1hcCk7CiAgIH0KICBjYXNlICdET01FeGNlcHRpb24nOgogICBpZiAoRVJST1JfU1RBQ0tfSU5TVEFMTEFCTEUpIHsKICAgIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eShjbG9uZWQsICdzdGFjaycsIHN0cnVjdHVyZWRDbG9uZUludGVybmFsKHZhbHVlLnN0YWNrLCBtYXApKTsKICAgfQogIH0KIHJldHVybiBjbG9uZWQ7Cn07CnZhciB0cnlUb1RyYW5zZmVyID0gZnVuY3Rpb24gKHJhd1RyYW5zZmVyLCBtYXApIHsKIGlmICghaXNPYmplY3QocmF3VHJhbnNmZXIpKQogIHRocm93IFR5cGVFcnJvcignVHJhbnNmZXIgb3B0aW9uIGNhbm5vdCBiZSBjb252ZXJ0ZWQgdG8gYSBzZXF1ZW5jZScpOwogdmFyIHRyYW5zZmVyID0gW107CiBpdGVyYXRlKHJhd1RyYW5zZmVyLCBmdW5jdGlvbiAodmFsdWUpIHsKICBwdXNoKHRyYW5zZmVyLCBhbk9iamVjdCh2YWx1ZSkpOwogfSk7CiB2YXIgaSA9IDA7CiB2YXIgbGVuZ3RoID0gbGVuZ3RoT2ZBcnJheUxpa2UodHJhbnNmZXIpOwogdmFyIHZhbHVlLCB0eXBlLCBDLCB0cmFuc2ZlcnJlZEFycmF5LCB0cmFuc2ZlcnJlZCwgY2FudmFzLCBjb250ZXh0OwogaWYgKFBST1BFUl9UUkFOU0ZFUikgewogIHRyYW5zZmVycmVkQXJyYXkgPSBuYXRpdmVTdHJ1Y3R1cmVkQ2xvbmUodHJhbnNmZXIsIHsgdHJhbnNmZXI6IHRyYW5zZmVyIH0pOwogIHdoaWxlIChpIDwgbGVuZ3RoKQogICBtYXBTZXQobWFwLCB0cmFuc2ZlcltpXSwgdHJhbnNmZXJyZWRBcnJheVtpKytdKTsKIH0gZWxzZQogIHdoaWxlIChpIDwgbGVuZ3RoKSB7CiAgIHZhbHVlID0gdHJhbnNmZXJbaSsrXTsKICAgaWYgKG1hcEhhcyhtYXAsIHZhbHVlKSkKICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ0R1cGxpY2F0ZSB0cmFuc2ZlcmFibGUnLCBEQVRBX0NMT05FX0VSUk9SKTsKICAgdHlwZSA9IGNsYXNzb2YodmFsdWUpOwogICBzd2l0Y2ggKHR5cGUpIHsKICAgY2FzZSAnSW1hZ2VCaXRtYXAnOgogICAgQyA9IGdsb2JhbC5PZmZzY3JlZW5DYW52YXM7CiAgICBpZiAoIWlzQ29uc3RydWN0b3IoQykpCiAgICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlLCBUUkFOU0ZFUlJJTkcpOwogICAgdHJ5IHsKICAgICBjYW52YXMgPSBuZXcgQyh2YWx1ZS53aWR0aCwgdmFsdWUuaGVpZ2h0KTsKICAgICBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJ2JpdG1hcHJlbmRlcmVyJyk7CiAgICAgY29udGV4dC50cmFuc2ZlckZyb21JbWFnZUJpdG1hcCh2YWx1ZSk7CiAgICAgdHJhbnNmZXJyZWQgPSBjYW52YXMudHJhbnNmZXJUb0ltYWdlQml0bWFwKCk7CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgfQogICAgYnJlYWs7CiAgIGNhc2UgJ0F1ZGlvRGF0YSc6CiAgIGNhc2UgJ1ZpZGVvRnJhbWUnOgogICAgaWYgKCFpc0NhbGxhYmxlKHZhbHVlLmNsb25lKSB8fCAhaXNDYWxsYWJsZSh2YWx1ZS5jbG9zZSkpCiAgICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlLCBUUkFOU0ZFUlJJTkcpOwogICAgdHJ5IHsKICAgICB0cmFuc2ZlcnJlZCA9IHZhbHVlLmNsb25lKCk7CiAgICAgdmFsdWUuY2xvc2UoKTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICB9CiAgICBicmVhazsKICAgY2FzZSAnQXJyYXlCdWZmZXInOgogICAgaWYgKCFpc0NhbGxhYmxlKHZhbHVlLnRyYW5zZmVyKSkKICAgICB0aHJvd1VucG9seWZpbGxhYmxlKHR5cGUsIFRSQU5TRkVSUklORyk7CiAgICB0cmFuc2ZlcnJlZCA9IHZhbHVlLnRyYW5zZmVyKCk7CiAgICBicmVhazsKICAgY2FzZSAnTWVkaWFTb3VyY2VIYW5kbGUnOgogICBjYXNlICdNZXNzYWdlUG9ydCc6CiAgIGNhc2UgJ09mZnNjcmVlbkNhbnZhcyc6CiAgIGNhc2UgJ1JlYWRhYmxlU3RyZWFtJzoKICAgY2FzZSAnVHJhbnNmb3JtU3RyZWFtJzoKICAgY2FzZSAnV3JpdGFibGVTdHJlYW0nOgogICAgdGhyb3dVbnBvbHlmaWxsYWJsZSh0eXBlLCBUUkFOU0ZFUlJJTkcpOwogICB9CiAgIGlmICh0cmFuc2ZlcnJlZCA9PT0gdW5kZWZpbmVkKQogICAgdGhyb3cgbmV3IERPTUV4Y2VwdGlvbignVGhpcyBvYmplY3QgY2Fubm90IGJlIHRyYW5zZmVycmVkOiAnICsgdHlwZSwgREFUQV9DTE9ORV9FUlJPUik7CiAgIG1hcFNldChtYXAsIHZhbHVlLCB0cmFuc2ZlcnJlZCk7CiAgfQp9OwokKHsKIGdsb2JhbDogdHJ1ZSwKIGVudW1lcmFibGU6IHRydWUsCiBzaGFtOiAhUFJPUEVSX1RSQU5TRkVSLAogZm9yY2VkOiBGT1JDRURfUkVQTEFDRU1FTlQKfSwgewogc3RydWN0dXJlZENsb25lOiBmdW5jdGlvbiBzdHJ1Y3R1cmVkQ2xvbmUodmFsdWUpIHsKICB2YXIgb3B0aW9ucyA9IHZhbGlkYXRlQXJndW1lbnRzTGVuZ3RoKGFyZ3VtZW50cy5sZW5ndGgsIDEpID4gMSAmJiAhaXNOdWxsT3JVbmRlZmluZWQoYXJndW1lbnRzWzFdKSA/IGFuT2JqZWN0KGFyZ3VtZW50c1sxXSkgOiB1bmRlZmluZWQ7CiAgdmFyIHRyYW5zZmVyID0gb3B0aW9ucyA/IG9wdGlvbnMudHJhbnNmZXIgOiB1bmRlZmluZWQ7CiAgdmFyIG1hcDsKICBpZiAodHJhbnNmZXIgIT09IHVuZGVmaW5lZCkgewogICBtYXAgPSBuZXcgTWFwKCk7CiAgIHRyeVRvVHJhbnNmZXIodHJhbnNmZXIsIG1hcCk7CiAgfQogIHJldHVybiBzdHJ1Y3R1cmVkQ2xvbmVJbnRlcm5hbCh2YWx1ZSwgbWFwKTsKIH0KfSk7CgovKioqLyB9KSwKLyogMTI3ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTgpOwp2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExKTsKdmFyIGlzQ2FsbGFibGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI1KTsKdmFyIGNsYXNzb2YgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDgzKTsKdmFyIGdldEJ1aWx0SW4gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI4KTsKdmFyIGluc3BlY3RTb3VyY2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDU1KTsKdmFyIG5vb3AgPSBmdW5jdGlvbiAoKSB7Cn07CnZhciBlbXB0eSA9IFtdOwp2YXIgY29uc3RydWN0ID0gZ2V0QnVpbHRJbignUmVmbGVjdCcsICdjb25zdHJ1Y3QnKTsKdmFyIGNvbnN0cnVjdG9yUmVnRXhwID0gL15ccyooPzpjbGFzc3xmdW5jdGlvbilcYi87CnZhciBleGVjID0gdW5jdXJyeVRoaXMoY29uc3RydWN0b3JSZWdFeHAuZXhlYyk7CnZhciBJTkNPUlJFQ1RfVE9fU1RSSU5HID0gIWNvbnN0cnVjdG9yUmVnRXhwLmV4ZWMobm9vcCk7CnZhciBpc0NvbnN0cnVjdG9yTW9kZXJuID0gZnVuY3Rpb24gaXNDb25zdHJ1Y3Rvcihhcmd1bWVudCkgewogaWYgKCFpc0NhbGxhYmxlKGFyZ3VtZW50KSkKICByZXR1cm4gZmFsc2U7CiB0cnkgewogIGNvbnN0cnVjdChub29wLCBlbXB0eSwgYXJndW1lbnQpOwogIHJldHVybiB0cnVlOwogfSBjYXRjaCAoZXJyb3IpIHsKICByZXR1cm4gZmFsc2U7CiB9Cn07CnZhciBpc0NvbnN0cnVjdG9yTGVnYWN5ID0gZnVuY3Rpb24gaXNDb25zdHJ1Y3Rvcihhcmd1bWVudCkgewogaWYgKCFpc0NhbGxhYmxlKGFyZ3VtZW50KSkKICByZXR1cm4gZmFsc2U7CiBzd2l0Y2ggKGNsYXNzb2YoYXJndW1lbnQpKSB7CiBjYXNlICdBc3luY0Z1bmN0aW9uJzoKIGNhc2UgJ0dlbmVyYXRvckZ1bmN0aW9uJzoKIGNhc2UgJ0FzeW5jR2VuZXJhdG9yRnVuY3Rpb24nOgogIHJldHVybiBmYWxzZTsKIH0KIHRyeSB7CiAgcmV0dXJuIElOQ09SUkVDVF9UT19TVFJJTkcgfHwgISFleGVjKGNvbnN0cnVjdG9yUmVnRXhwLCBpbnNwZWN0U291cmNlKGFyZ3VtZW50KSk7CiB9IGNhdGNoIChlcnJvcikgewogIHJldHVybiB0cnVlOwogfQp9Owppc0NvbnN0cnVjdG9yTGVnYWN5LnNoYW0gPSB0cnVlOwptb2R1bGUuZXhwb3J0cyA9ICFjb25zdHJ1Y3QgfHwgZmFpbHMoZnVuY3Rpb24gKCkgewogdmFyIGNhbGxlZDsKIHJldHVybiBpc0NvbnN0cnVjdG9yTW9kZXJuKGlzQ29uc3RydWN0b3JNb2Rlcm4uY2FsbCkgfHwgIWlzQ29uc3RydWN0b3JNb2Rlcm4oT2JqZWN0KSB8fCAhaXNDb25zdHJ1Y3Rvck1vZGVybihmdW5jdGlvbiAoKSB7CiAgY2FsbGVkID0gdHJ1ZTsKIH0pIHx8IGNhbGxlZDsKfSkgPyBpc0NvbnN0cnVjdG9yTGVnYWN5IDogaXNDb25zdHJ1Y3Rvck1vZGVybjsKCi8qKiovIH0pLAovKiAxMjggKi8KLyoqKi8gKChtb2R1bGUpID0+IHsKCnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChwYXNzZWQsIHJlcXVpcmVkKSB7CiBpZiAocGFzc2VkIDwgcmVxdWlyZWQpCiAgdGhyb3cgJFR5cGVFcnJvcignTm90IGVub3VnaCBhcmd1bWVudHMnKTsKIHJldHVybiBwYXNzZWQ7Cn07CgovKioqLyB9KSwKLyogMTI5ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBjYWxsID0gX193X3BkZmpzX3JlcXVpcmVfXygxMik7CnZhciBoYXNPd24gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDQzKTsKdmFyIGlzUHJvdG90eXBlT2YgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDI5KTsKdmFyIHJlZ0V4cEZsYWdzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzApOwp2YXIgUmVnRXhwUHJvdG90eXBlID0gUmVnRXhwLnByb3RvdHlwZTsKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoUikgewogdmFyIGZsYWdzID0gUi5mbGFnczsKIHJldHVybiBmbGFncyA9PT0gdW5kZWZpbmVkICYmICEoJ2ZsYWdzJyBpbiBSZWdFeHBQcm90b3R5cGUpICYmICFoYXNPd24oUiwgJ2ZsYWdzJykgJiYgaXNQcm90b3R5cGVPZihSZWdFeHBQcm90b3R5cGUsIFIpID8gY2FsbChyZWdFeHBGbGFncywgUikgOiBmbGFnczsKfTsKCi8qKiovIH0pLAovKiAxMzAgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKdmFyIGFuT2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXyg1MSk7Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkgewogdmFyIHRoYXQgPSBhbk9iamVjdCh0aGlzKTsKIHZhciByZXN1bHQgPSAnJzsKIGlmICh0aGF0Lmhhc0luZGljZXMpCiAgcmVzdWx0ICs9ICdkJzsKIGlmICh0aGF0Lmdsb2JhbCkKICByZXN1bHQgKz0gJ2cnOwogaWYgKHRoYXQuaWdub3JlQ2FzZSkKICByZXN1bHQgKz0gJ2knOwogaWYgKHRoYXQubXVsdGlsaW5lKQogIHJlc3VsdCArPSAnbSc7CiBpZiAodGhhdC5kb3RBbGwpCiAgcmVzdWx0ICs9ICdzJzsKIGlmICh0aGF0LnVuaWNvZGUpCiAgcmVzdWx0ICs9ICd1JzsKIGlmICh0aGF0LnVuaWNvZGVTZXRzKQogIHJlc3VsdCArPSAndic7CiBpZiAodGhhdC5zdGlja3kpCiAgcmVzdWx0ICs9ICd5JzsKIHJldHVybiByZXN1bHQ7Cn07CgovKioqLyB9KSwKLyogMTMxICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTgpOwp2YXIgTWFwUHJvdG90eXBlID0gTWFwLnByb3RvdHlwZTsKbW9kdWxlLmV4cG9ydHMgPSB7CiBNYXA6IE1hcCwKIHNldDogdW5jdXJyeVRoaXMoTWFwUHJvdG90eXBlLnNldCksCiBnZXQ6IHVuY3VycnlUaGlzKE1hcFByb3RvdHlwZS5nZXQpLAogaGFzOiB1bmN1cnJ5VGhpcyhNYXBQcm90b3R5cGUuaGFzKSwKIHJlbW92ZTogdW5jdXJyeVRoaXMoTWFwUHJvdG90eXBlWydkZWxldGUnXSksCiBwcm90bzogTWFwUHJvdG90eXBlCn07CgovKioqLyB9KSwKLyogMTMyICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciB1bmN1cnJ5VGhpcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTgpOwp2YXIgU2V0UHJvdG90eXBlID0gU2V0LnByb3RvdHlwZTsKbW9kdWxlLmV4cG9ydHMgPSB7CiBTZXQ6IFNldCwKIGFkZDogdW5jdXJyeVRoaXMoU2V0UHJvdG90eXBlLmFkZCksCiBoYXM6IHVuY3VycnlUaGlzKFNldFByb3RvdHlwZS5oYXMpLAogcmVtb3ZlOiB1bmN1cnJ5VGhpcyhTZXRQcm90b3R5cGVbJ2RlbGV0ZSddKSwKIHByb3RvOiBTZXRQcm90b3R5cGUsCiAkaGFzOiBTZXRQcm90b3R5cGUuaGFzLAogJGtleXM6IFNldFByb3RvdHlwZS5rZXlzCn07CgovKioqLyB9KSwKLyogMTMzICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBmYWlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTEpOwp2YXIgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXygxNSk7Cm1vZHVsZS5leHBvcnRzID0gIWZhaWxzKGZ1bmN0aW9uICgpIHsKIHZhciBlcnJvciA9IEVycm9yKCdhJyk7CiBpZiAoISgnc3RhY2snIGluIGVycm9yKSkKICByZXR1cm4gdHJ1ZTsKIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlcnJvciwgJ3N0YWNrJywgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yKDEsIDcpKTsKIHJldHVybiBlcnJvci5zdGFjayAhPT0gNzsKfSk7CgovKioqLyB9KSwKLyogMTM0ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBnbG9iYWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDgpOwp2YXIgZmFpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDExKTsKdmFyIFY4ID0gX193X3BkZmpzX3JlcXVpcmVfXygzMik7CnZhciBJU19CUk9XU0VSID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzUpOwp2YXIgSVNfREVOTyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTM2KTsKdmFyIElTX05PREUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzNyk7CnZhciBzdHJ1Y3R1cmVkQ2xvbmUgPSBnbG9iYWwuc3RydWN0dXJlZENsb25lOwptb2R1bGUuZXhwb3J0cyA9ICEhc3RydWN0dXJlZENsb25lICYmICFmYWlscyhmdW5jdGlvbiAoKSB7CiBpZiAoSVNfREVOTyAmJiBWOCA+IDkyIHx8IElTX05PREUgJiYgVjggPiA5NCB8fCBJU19CUk9XU0VSICYmIFY4ID4gOTcpCiAgcmV0dXJuIGZhbHNlOwogdmFyIGJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcig4KTsKIHZhciBjbG9uZSA9IHN0cnVjdHVyZWRDbG9uZShidWZmZXIsIHsgdHJhbnNmZXI6IFtidWZmZXJdIH0pOwogcmV0dXJuIGJ1ZmZlci5ieXRlTGVuZ3RoICE9IDAgfHwgY2xvbmUuYnl0ZUxlbmd0aCAhPSA4Owp9KTsKCi8qKiovIH0pLAovKiAxMzUgKi8KLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKdmFyIElTX0RFTk8gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzNik7CnZhciBJU19OT0RFID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzcpOwptb2R1bGUuZXhwb3J0cyA9ICFJU19ERU5PICYmICFJU19OT0RFICYmIHR5cGVvZiB3aW5kb3cgPT0gJ29iamVjdCcgJiYgdHlwZW9mIGRvY3VtZW50ID09ICdvYmplY3QnOwoKLyoqKi8gfSksCi8qIDEzNiAqLwovKioqLyAoKG1vZHVsZSkgPT4gewoKbW9kdWxlLmV4cG9ydHMgPSB0eXBlb2YgRGVubyA9PSAnb2JqZWN0JyAmJiBEZW5vICYmIHR5cGVvZiBEZW5vLnZlcnNpb24gPT0gJ29iamVjdCc7CgovKioqLyB9KSwKLyogMTM3ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBjbGFzc29mID0gX193X3BkZmpzX3JlcXVpcmVfXygxOSk7Cm1vZHVsZS5leHBvcnRzID0gdHlwZW9mIHByb2Nlc3MgIT0gJ3VuZGVmaW5lZCcgJiYgY2xhc3NvZihwcm9jZXNzKSA9PSAncHJvY2Vzcyc7CgovKioqLyB9KSwKLyogMTM4ICovCi8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCnZhciBnbG9iYWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDgpOwptb2R1bGUuZXhwb3J0cyA9IGdsb2JhbDsKCi8qKiovIH0pLAovKiAxMzkgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlhSZWZQYXJzZUV4Y2VwdGlvbiA9IGV4cG9ydHMuWFJlZkVudHJ5RXhjZXB0aW9uID0gZXhwb3J0cy5QYXJzZXJFT0ZFeGNlcHRpb24gPSBleHBvcnRzLlBERl9WRVJTSU9OX1JFR0VYUCA9IGV4cG9ydHMuTWlzc2luZ0RhdGFFeGNlcHRpb24gPSB2b2lkIDA7CmV4cG9ydHMuYXJyYXlCdWZmZXJzVG9CeXRlcyA9IGFycmF5QnVmZmVyc1RvQnl0ZXM7CmV4cG9ydHMuY29sbGVjdEFjdGlvbnMgPSBjb2xsZWN0QWN0aW9uczsKZXhwb3J0cy5lbmNvZGVUb1htbFN0cmluZyA9IGVuY29kZVRvWG1sU3RyaW5nOwpleHBvcnRzLmVzY2FwZVBERk5hbWUgPSBlc2NhcGVQREZOYW1lOwpleHBvcnRzLmVzY2FwZVN0cmluZyA9IGVzY2FwZVN0cmluZzsKZXhwb3J0cy5nZXRBcnJheUxvb2t1cFRhYmxlRmFjdG9yeSA9IGdldEFycmF5TG9va3VwVGFibGVGYWN0b3J5OwpleHBvcnRzLmdldEluaGVyaXRhYmxlUHJvcGVydHkgPSBnZXRJbmhlcml0YWJsZVByb3BlcnR5OwpleHBvcnRzLmdldExvb2t1cFRhYmxlRmFjdG9yeSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeTsKZXhwb3J0cy5nZXROZXdBbm5vdGF0aW9uc01hcCA9IGdldE5ld0Fubm90YXRpb25zTWFwOwpleHBvcnRzLmdldFJvdGF0aW9uTWF0cml4ID0gZ2V0Um90YXRpb25NYXRyaXg7CmV4cG9ydHMuaXNBc2NpaSA9IGlzQXNjaWk7CmV4cG9ydHMuaXNXaGl0ZVNwYWNlID0gaXNXaGl0ZVNwYWNlOwpleHBvcnRzLmxvZzIgPSBsb2cyOwpleHBvcnRzLm51bWJlclRvU3RyaW5nID0gbnVtYmVyVG9TdHJpbmc7CmV4cG9ydHMucGFyc2VYRkFQYXRoID0gcGFyc2VYRkFQYXRoOwpleHBvcnRzLnJlYWRJbnQ4ID0gcmVhZEludDg7CmV4cG9ydHMucmVhZFVpbnQxNiA9IHJlYWRVaW50MTY7CmV4cG9ydHMucmVhZFVpbnQzMiA9IHJlYWRVaW50MzI7CmV4cG9ydHMucmVjb3ZlckpzVVJMID0gcmVjb3ZlckpzVVJMOwpleHBvcnRzLnN0cmluZ1RvVVRGMTZIZXhTdHJpbmcgPSBzdHJpbmdUb1VURjE2SGV4U3RyaW5nOwpleHBvcnRzLnN0cmluZ1RvVVRGMTZTdHJpbmcgPSBzdHJpbmdUb1VURjE2U3RyaW5nOwpleHBvcnRzLnRvUm9tYW5OdW1lcmFscyA9IHRvUm9tYW5OdW1lcmFsczsKZXhwb3J0cy52YWxpZGF0ZUNTU0ZvbnQgPSB2YWxpZGF0ZUNTU0ZvbnQ7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CnZhciBfcHJpbWl0aXZlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQwKTsKdmFyIF9iYXNlX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQxKTsKY29uc3QgUERGX1ZFUlNJT05fUkVHRVhQID0gL15bMS05XVwuXGQkLzsKZXhwb3J0cy5QREZfVkVSU0lPTl9SRUdFWFAgPSBQREZfVkVSU0lPTl9SRUdFWFA7CmZ1bmN0aW9uIGdldExvb2t1cFRhYmxlRmFjdG9yeShpbml0aWFsaXplcikgewogIGxldCBsb29rdXA7CiAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgIGlmIChpbml0aWFsaXplcikgewogICAgICBsb29rdXAgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBpbml0aWFsaXplcihsb29rdXApOwogICAgICBpbml0aWFsaXplciA9IG51bGw7CiAgICB9CiAgICByZXR1cm4gbG9va3VwOwogIH07Cn0KZnVuY3Rpb24gZ2V0QXJyYXlMb29rdXBUYWJsZUZhY3RvcnkoaW5pdGlhbGl6ZXIpIHsKICBsZXQgbG9va3VwOwogIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICBpZiAoaW5pdGlhbGl6ZXIpIHsKICAgICAgbGV0IGFyciA9IGluaXRpYWxpemVyKCk7CiAgICAgIGluaXRpYWxpemVyID0gbnVsbDsKICAgICAgbG9va3VwID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gYXJyLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgICBsb29rdXBbYXJyW2ldXSA9IGFycltpICsgMV07CiAgICAgIH0KICAgICAgYXJyID0gbnVsbDsKICAgIH0KICAgIHJldHVybiBsb29rdXA7CiAgfTsKfQpjbGFzcyBNaXNzaW5nRGF0YUV4Y2VwdGlvbiBleHRlbmRzIF91dGlsLkJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKGJlZ2luLCBlbmQpIHsKICAgIHN1cGVyKGBNaXNzaW5nIGRhdGEgWyR7YmVnaW59LCAke2VuZH0pYCwgIk1pc3NpbmdEYXRhRXhjZXB0aW9uIik7CiAgICB0aGlzLmJlZ2luID0gYmVnaW47CiAgICB0aGlzLmVuZCA9IGVuZDsKICB9Cn0KZXhwb3J0cy5NaXNzaW5nRGF0YUV4Y2VwdGlvbiA9IE1pc3NpbmdEYXRhRXhjZXB0aW9uOwpjbGFzcyBQYXJzZXJFT0ZFeGNlcHRpb24gZXh0ZW5kcyBfdXRpbC5CYXNlRXhjZXB0aW9uIHsKICBjb25zdHJ1Y3Rvcihtc2cpIHsKICAgIHN1cGVyKG1zZywgIlBhcnNlckVPRkV4Y2VwdGlvbiIpOwogIH0KfQpleHBvcnRzLlBhcnNlckVPRkV4Y2VwdGlvbiA9IFBhcnNlckVPRkV4Y2VwdGlvbjsKY2xhc3MgWFJlZkVudHJ5RXhjZXB0aW9uIGV4dGVuZHMgX3V0aWwuQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnKSB7CiAgICBzdXBlcihtc2csICJYUmVmRW50cnlFeGNlcHRpb24iKTsKICB9Cn0KZXhwb3J0cy5YUmVmRW50cnlFeGNlcHRpb24gPSBYUmVmRW50cnlFeGNlcHRpb247CmNsYXNzIFhSZWZQYXJzZUV4Y2VwdGlvbiBleHRlbmRzIF91dGlsLkJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZykgewogICAgc3VwZXIobXNnLCAiWFJlZlBhcnNlRXhjZXB0aW9uIik7CiAgfQp9CmV4cG9ydHMuWFJlZlBhcnNlRXhjZXB0aW9uID0gWFJlZlBhcnNlRXhjZXB0aW9uOwpmdW5jdGlvbiBhcnJheUJ1ZmZlcnNUb0J5dGVzKGFycikgewogIGNvbnN0IGxlbmd0aCA9IGFyci5sZW5ndGg7CiAgaWYgKGxlbmd0aCA9PT0gMCkgewogICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KDApOwogIH0KICBpZiAobGVuZ3RoID09PSAxKSB7CiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYXJyWzBdKTsKICB9CiAgbGV0IGRhdGFMZW5ndGggPSAwOwogIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgIGRhdGFMZW5ndGggKz0gYXJyW2ldLmJ5dGVMZW5ndGg7CiAgfQogIGNvbnN0IGRhdGEgPSBuZXcgVWludDhBcnJheShkYXRhTGVuZ3RoKTsKICBsZXQgcG9zID0gMDsKICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICBjb25zdCBpdGVtID0gbmV3IFVpbnQ4QXJyYXkoYXJyW2ldKTsKICAgIGRhdGEuc2V0KGl0ZW0sIHBvcyk7CiAgICBwb3MgKz0gaXRlbS5ieXRlTGVuZ3RoOwogIH0KICByZXR1cm4gZGF0YTsKfQpmdW5jdGlvbiBnZXRJbmhlcml0YWJsZVByb3BlcnR5KF9yZWYpIHsKICBsZXQgewogICAgZGljdCwKICAgIGtleSwKICAgIGdldEFycmF5ID0gZmFsc2UsCiAgICBzdG9wV2hlbkZvdW5kID0gdHJ1ZQogIH0gPSBfcmVmOwogIGxldCB2YWx1ZXM7CiAgY29uc3QgdmlzaXRlZCA9IG5ldyBfcHJpbWl0aXZlcy5SZWZTZXQoKTsKICB3aGlsZSAoZGljdCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QgJiYgIShkaWN0Lm9iaklkICYmIHZpc2l0ZWQuaGFzKGRpY3Qub2JqSWQpKSkgewogICAgaWYgKGRpY3Qub2JqSWQpIHsKICAgICAgdmlzaXRlZC5wdXQoZGljdC5vYmpJZCk7CiAgICB9CiAgICBjb25zdCB2YWx1ZSA9IGdldEFycmF5ID8gZGljdC5nZXRBcnJheShrZXkpIDogZGljdC5nZXQoa2V5KTsKICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmIChzdG9wV2hlbkZvdW5kKSB7CiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICB9CiAgICAgIGlmICghdmFsdWVzKSB7CiAgICAgICAgdmFsdWVzID0gW107CiAgICAgIH0KICAgICAgdmFsdWVzLnB1c2godmFsdWUpOwogICAgfQogICAgZGljdCA9IGRpY3QuZ2V0KCJQYXJlbnQiKTsKICB9CiAgcmV0dXJuIHZhbHVlczsKfQpjb25zdCBST01BTl9OVU1CRVJfTUFQID0gWyIiLCAiQyIsICJDQyIsICJDQ0MiLCAiQ0QiLCAiRCIsICJEQyIsICJEQ0MiLCAiRENDQyIsICJDTSIsICIiLCAiWCIsICJYWCIsICJYWFgiLCAiWEwiLCAiTCIsICJMWCIsICJMWFgiLCAiTFhYWCIsICJYQyIsICIiLCAiSSIsICJJSSIsICJJSUkiLCAiSVYiLCAiViIsICJWSSIsICJWSUkiLCAiVklJSSIsICJJWCJdOwpmdW5jdGlvbiB0b1JvbWFuTnVtZXJhbHMobnVtYmVyKSB7CiAgbGV0IGxvd2VyQ2FzZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogZmFsc2U7CiAgKDAsIF91dGlsLmFzc2VydCkoTnVtYmVyLmlzSW50ZWdlcihudW1iZXIpICYmIG51bWJlciA+IDAsICJUaGUgbnVtYmVyIHNob3VsZCBiZSBhIHBvc2l0aXZlIGludGVnZXIuIik7CiAgY29uc3Qgcm9tYW5CdWYgPSBbXTsKICBsZXQgcG9zOwogIHdoaWxlIChudW1iZXIgPj0gMTAwMCkgewogICAgbnVtYmVyIC09IDEwMDA7CiAgICByb21hbkJ1Zi5wdXNoKCJNIik7CiAgfQogIHBvcyA9IG51bWJlciAvIDEwMCB8IDA7CiAgbnVtYmVyICU9IDEwMDsKICByb21hbkJ1Zi5wdXNoKFJPTUFOX05VTUJFUl9NQVBbcG9zXSk7CiAgcG9zID0gbnVtYmVyIC8gMTAgfCAwOwogIG51bWJlciAlPSAxMDsKICByb21hbkJ1Zi5wdXNoKFJPTUFOX05VTUJFUl9NQVBbMTAgKyBwb3NdKTsKICByb21hbkJ1Zi5wdXNoKFJPTUFOX05VTUJFUl9NQVBbMjAgKyBudW1iZXJdKTsKICBjb25zdCByb21hblN0ciA9IHJvbWFuQnVmLmpvaW4oIiIpOwogIHJldHVybiBsb3dlckNhc2UgPyByb21hblN0ci50b0xvd2VyQ2FzZSgpIDogcm9tYW5TdHI7Cn0KZnVuY3Rpb24gbG9nMih4KSB7CiAgaWYgKHggPD0gMCkgewogICAgcmV0dXJuIDA7CiAgfQogIHJldHVybiBNYXRoLmNlaWwoTWF0aC5sb2cyKHgpKTsKfQpmdW5jdGlvbiByZWFkSW50OChkYXRhLCBvZmZzZXQpIHsKICByZXR1cm4gZGF0YVtvZmZzZXRdIDw8IDI0ID4+IDI0Owp9CmZ1bmN0aW9uIHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KSB7CiAgcmV0dXJuIGRhdGFbb2Zmc2V0XSA8PCA4IHwgZGF0YVtvZmZzZXQgKyAxXTsKfQpmdW5jdGlvbiByZWFkVWludDMyKGRhdGEsIG9mZnNldCkgewogIHJldHVybiAoZGF0YVtvZmZzZXRdIDw8IDI0IHwgZGF0YVtvZmZzZXQgKyAxXSA8PCAxNiB8IGRhdGFbb2Zmc2V0ICsgMl0gPDwgOCB8IGRhdGFbb2Zmc2V0ICsgM10pID4+PiAwOwp9CmZ1bmN0aW9uIGlzV2hpdGVTcGFjZShjaCkgewogIHJldHVybiBjaCA9PT0gMHgyMCB8fCBjaCA9PT0gMHgwOSB8fCBjaCA9PT0gMHgwZCB8fCBjaCA9PT0gMHgwYTsKfQpmdW5jdGlvbiBwYXJzZVhGQVBhdGgocGF0aCkgewogIGNvbnN0IHBvc2l0aW9uUGF0dGVybiA9IC8oLispXFsoXGQrKVxdJC87CiAgcmV0dXJuIHBhdGguc3BsaXQoIi4iKS5tYXAoY29tcG9uZW50ID0+IHsKICAgIGNvbnN0IG0gPSBjb21wb25lbnQubWF0Y2gocG9zaXRpb25QYXR0ZXJuKTsKICAgIGlmIChtKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgbmFtZTogbVsxXSwKICAgICAgICBwb3M6IHBhcnNlSW50KG1bMl0sIDEwKQogICAgICB9OwogICAgfQogICAgcmV0dXJuIHsKICAgICAgbmFtZTogY29tcG9uZW50LAogICAgICBwb3M6IDAKICAgIH07CiAgfSk7Cn0KZnVuY3Rpb24gZXNjYXBlUERGTmFtZShzdHIpIHsKICBjb25zdCBidWZmZXIgPSBbXTsKICBsZXQgc3RhcnQgPSAwOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IHN0ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCBjaGFyID0gc3RyLmNoYXJDb2RlQXQoaSk7CiAgICBpZiAoY2hhciA8IDB4MjEgfHwgY2hhciA+IDB4N2UgfHwgY2hhciA9PT0gMHgyMyB8fCBjaGFyID09PSAweDI4IHx8IGNoYXIgPT09IDB4MjkgfHwgY2hhciA9PT0gMHgzYyB8fCBjaGFyID09PSAweDNlIHx8IGNoYXIgPT09IDB4NWIgfHwgY2hhciA9PT0gMHg1ZCB8fCBjaGFyID09PSAweDdiIHx8IGNoYXIgPT09IDB4N2QgfHwgY2hhciA9PT0gMHgyZiB8fCBjaGFyID09PSAweDI1KSB7CiAgICAgIGlmIChzdGFydCA8IGkpIHsKICAgICAgICBidWZmZXIucHVzaChzdHIuc3Vic3RyaW5nKHN0YXJ0LCBpKSk7CiAgICAgIH0KICAgICAgYnVmZmVyLnB1c2goYCMke2NoYXIudG9TdHJpbmcoMTYpfWApOwogICAgICBzdGFydCA9IGkgKyAxOwogICAgfQogIH0KICBpZiAoYnVmZmVyLmxlbmd0aCA9PT0gMCkgewogICAgcmV0dXJuIHN0cjsKICB9CiAgaWYgKHN0YXJ0IDwgc3RyLmxlbmd0aCkgewogICAgYnVmZmVyLnB1c2goc3RyLnN1YnN0cmluZyhzdGFydCwgc3RyLmxlbmd0aCkpOwogIH0KICByZXR1cm4gYnVmZmVyLmpvaW4oIiIpOwp9CmZ1bmN0aW9uIGVzY2FwZVN0cmluZyhzdHIpIHsKICByZXR1cm4gc3RyLnJlcGxhY2VBbGwoLyhbKClcXFxuXHJdKS9nLCBtYXRjaCA9PiB7CiAgICBpZiAobWF0Y2ggPT09ICJcbiIpIHsKICAgICAgcmV0dXJuICJcXG4iOwogICAgfSBlbHNlIGlmIChtYXRjaCA9PT0gIlxyIikgewogICAgICByZXR1cm4gIlxcciI7CiAgICB9CiAgICByZXR1cm4gYFxcJHttYXRjaH1gOwogIH0pOwp9CmZ1bmN0aW9uIF9jb2xsZWN0SlMoZW50cnksIHhyZWYsIGxpc3QsIHBhcmVudHMpIHsKICBpZiAoIWVudHJ5KSB7CiAgICByZXR1cm47CiAgfQogIGxldCBwYXJlbnQgPSBudWxsOwogIGlmIChlbnRyeSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgaWYgKHBhcmVudHMuaGFzKGVudHJ5KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBwYXJlbnQgPSBlbnRyeTsKICAgIHBhcmVudHMucHV0KHBhcmVudCk7CiAgICBlbnRyeSA9IHhyZWYuZmV0Y2goZW50cnkpOwogIH0KICBpZiAoQXJyYXkuaXNBcnJheShlbnRyeSkpIHsKICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBlbnRyeSkgewogICAgICBfY29sbGVjdEpTKGVsZW1lbnQsIHhyZWYsIGxpc3QsIHBhcmVudHMpOwogICAgfQogIH0gZWxzZSBpZiAoZW50cnkgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICBpZiAoKDAsIF9wcmltaXRpdmVzLmlzTmFtZSkoZW50cnkuZ2V0KCJTIiksICJKYXZhU2NyaXB0IikpIHsKICAgICAgY29uc3QganMgPSBlbnRyeS5nZXQoIkpTIik7CiAgICAgIGxldCBjb2RlOwogICAgICBpZiAoanMgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkgewogICAgICAgIGNvZGUgPSBqcy5nZXRTdHJpbmcoKTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YganMgPT09ICJzdHJpbmciKSB7CiAgICAgICAgY29kZSA9IGpzOwogICAgICB9CiAgICAgIGNvZGUgPSBjb2RlICYmICgwLCBfdXRpbC5zdHJpbmdUb1BERlN0cmluZykoY29kZSkucmVwbGFjZUFsbCgiXHgwMCIsICIiKTsKICAgICAgaWYgKGNvZGUpIHsKICAgICAgICBsaXN0LnB1c2goY29kZSk7CiAgICAgIH0KICAgIH0KICAgIF9jb2xsZWN0SlMoZW50cnkuZ2V0UmF3KCJOZXh0IiksIHhyZWYsIGxpc3QsIHBhcmVudHMpOwogIH0KICBpZiAocGFyZW50KSB7CiAgICBwYXJlbnRzLnJlbW92ZShwYXJlbnQpOwogIH0KfQpmdW5jdGlvbiBjb2xsZWN0QWN0aW9ucyh4cmVmLCBkaWN0LCBldmVudFR5cGUpIHsKICBjb25zdCBhY3Rpb25zID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBjb25zdCBhZGRpdGlvbmFsQWN0aW9uc0RpY3RzID0gZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7CiAgICBkaWN0LAogICAga2V5OiAiQUEiLAogICAgc3RvcFdoZW5Gb3VuZDogZmFsc2UKICB9KTsKICBpZiAoYWRkaXRpb25hbEFjdGlvbnNEaWN0cykgewogICAgZm9yIChsZXQgaSA9IGFkZGl0aW9uYWxBY3Rpb25zRGljdHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHsKICAgICAgY29uc3QgYWRkaXRpb25hbEFjdGlvbnMgPSBhZGRpdGlvbmFsQWN0aW9uc0RpY3RzW2ldOwogICAgICBpZiAoIShhZGRpdGlvbmFsQWN0aW9ucyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBrZXkgb2YgYWRkaXRpb25hbEFjdGlvbnMuZ2V0S2V5cygpKSB7CiAgICAgICAgY29uc3QgYWN0aW9uID0gZXZlbnRUeXBlW2tleV07CiAgICAgICAgaWYgKCFhY3Rpb24pIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBhY3Rpb25EaWN0ID0gYWRkaXRpb25hbEFjdGlvbnMuZ2V0UmF3KGtleSk7CiAgICAgICAgY29uc3QgcGFyZW50cyA9IG5ldyBfcHJpbWl0aXZlcy5SZWZTZXQoKTsKICAgICAgICBjb25zdCBsaXN0ID0gW107CiAgICAgICAgX2NvbGxlY3RKUyhhY3Rpb25EaWN0LCB4cmVmLCBsaXN0LCBwYXJlbnRzKTsKICAgICAgICBpZiAobGlzdC5sZW5ndGggPiAwKSB7CiAgICAgICAgICBhY3Rpb25zW2FjdGlvbl0gPSBsaXN0OwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICBpZiAoZGljdC5oYXMoIkEiKSkgewogICAgY29uc3QgYWN0aW9uRGljdCA9IGRpY3QuZ2V0KCJBIik7CiAgICBjb25zdCBwYXJlbnRzID0gbmV3IF9wcmltaXRpdmVzLlJlZlNldCgpOwogICAgY29uc3QgbGlzdCA9IFtdOwogICAgX2NvbGxlY3RKUyhhY3Rpb25EaWN0LCB4cmVmLCBsaXN0LCBwYXJlbnRzKTsKICAgIGlmIChsaXN0Lmxlbmd0aCA+IDApIHsKICAgICAgYWN0aW9ucy5BY3Rpb24gPSBsaXN0OwogICAgfQogIH0KICByZXR1cm4gKDAsIF91dGlsLm9iamVjdFNpemUpKGFjdGlvbnMpID4gMCA/IGFjdGlvbnMgOiBudWxsOwp9CmNvbnN0IFhNTEVudGl0aWVzID0gewogIDB4M2M6ICImbHQ7IiwKICAweDNlOiAiJmd0OyIsCiAgMHgyNjogIiZhbXA7IiwKICAweDIyOiAiJnF1b3Q7IiwKICAweDI3OiAiJmFwb3M7Igp9OwpmdW5jdGlvbiBlbmNvZGVUb1htbFN0cmluZyhzdHIpIHsKICBjb25zdCBidWZmZXIgPSBbXTsKICBsZXQgc3RhcnQgPSAwOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IHN0ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCBjaGFyID0gc3RyLmNvZGVQb2ludEF0KGkpOwogICAgaWYgKDB4MjAgPD0gY2hhciAmJiBjaGFyIDw9IDB4N2UpIHsKICAgICAgY29uc3QgZW50aXR5ID0gWE1MRW50aXRpZXNbY2hhcl07CiAgICAgIGlmIChlbnRpdHkpIHsKICAgICAgICBpZiAoc3RhcnQgPCBpKSB7CiAgICAgICAgICBidWZmZXIucHVzaChzdHIuc3Vic3RyaW5nKHN0YXJ0LCBpKSk7CiAgICAgICAgfQogICAgICAgIGJ1ZmZlci5wdXNoKGVudGl0eSk7CiAgICAgICAgc3RhcnQgPSBpICsgMTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgaWYgKHN0YXJ0IDwgaSkgewogICAgICAgIGJ1ZmZlci5wdXNoKHN0ci5zdWJzdHJpbmcoc3RhcnQsIGkpKTsKICAgICAgfQogICAgICBidWZmZXIucHVzaChgJiN4JHtjaGFyLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpfTtgKTsKICAgICAgaWYgKGNoYXIgPiAweGQ3ZmYgJiYgKGNoYXIgPCAweGUwMDAgfHwgY2hhciA+IDB4ZmZmZCkpIHsKICAgICAgICBpKys7CiAgICAgIH0KICAgICAgc3RhcnQgPSBpICsgMTsKICAgIH0KICB9CiAgaWYgKGJ1ZmZlci5sZW5ndGggPT09IDApIHsKICAgIHJldHVybiBzdHI7CiAgfQogIGlmIChzdGFydCA8IHN0ci5sZW5ndGgpIHsKICAgIGJ1ZmZlci5wdXNoKHN0ci5zdWJzdHJpbmcoc3RhcnQsIHN0ci5sZW5ndGgpKTsKICB9CiAgcmV0dXJuIGJ1ZmZlci5qb2luKCIiKTsKfQpmdW5jdGlvbiB2YWxpZGF0ZUNTU0ZvbnQoY3NzRm9udEluZm8pIHsKICBjb25zdCBERUZBVUxUX0NTU19GT05UX09CTElRVUUgPSAiMTQiOwogIGNvbnN0IERFRkFVTFRfQ1NTX0ZPTlRfV0VJR0hUID0gIjQwMCI7CiAgY29uc3QgQ1NTX0ZPTlRfV0VJR0hUX1ZBTFVFUyA9IG5ldyBTZXQoWyIxMDAiLCAiMjAwIiwgIjMwMCIsICI0MDAiLCAiNTAwIiwgIjYwMCIsICI3MDAiLCAiODAwIiwgIjkwMCIsICIxMDAwIiwgIm5vcm1hbCIsICJib2xkIiwgImJvbGRlciIsICJsaWdodGVyIl0pOwogIGNvbnN0IHsKICAgIGZvbnRGYW1pbHksCiAgICBmb250V2VpZ2h0LAogICAgaXRhbGljQW5nbGUKICB9ID0gY3NzRm9udEluZm87CiAgY29uc3QgbSA9IC9eKCJ8JykuKigifCcpJC8uZXhlYyhmb250RmFtaWx5KTsKICBpZiAobSAmJiBtWzFdID09PSBtWzJdKSB7CiAgICBjb25zdCByZSA9IG5ldyBSZWdFeHAoYFteXFxcXF0ke21bMV19YCk7CiAgICBpZiAocmUudGVzdChmb250RmFtaWx5LnNsaWNlKDEsIC0xKSkpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKGBYRkEgLSBGb250RmFtaWx5IGNvbnRhaW5zIHVuZXNjYXBlZCAke21bMV19OiAke2ZvbnRGYW1pbHl9LmApOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgfSBlbHNlIHsKICAgIGZvciAoY29uc3QgaWRlbnQgb2YgZm9udEZhbWlseS5zcGxpdCgvWyBcdF0rLykpIHsKICAgICAgaWYgKC9eKFxkfCgtKFxkfC0pKSkvLnRlc3QoaWRlbnQpIHx8ICEvXltcdy1cXF0rJC8udGVzdChpZGVudCkpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYFhGQSAtIEZvbnRGYW1pbHkgY29udGFpbnMgaW52YWxpZCA8Y3VzdG9tLWlkZW50PjogJHtmb250RmFtaWx5fS5gKTsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH0KICB9CiAgY29uc3Qgd2VpZ2h0ID0gZm9udFdlaWdodCA/IGZvbnRXZWlnaHQudG9TdHJpbmcoKSA6ICIiOwogIGNzc0ZvbnRJbmZvLmZvbnRXZWlnaHQgPSBDU1NfRk9OVF9XRUlHSFRfVkFMVUVTLmhhcyh3ZWlnaHQpID8gd2VpZ2h0IDogREVGQVVMVF9DU1NfRk9OVF9XRUlHSFQ7CiAgY29uc3QgYW5nbGUgPSBwYXJzZUZsb2F0KGl0YWxpY0FuZ2xlKTsKICBjc3NGb250SW5mby5pdGFsaWNBbmdsZSA9IGlzTmFOKGFuZ2xlKSB8fCBhbmdsZSA8IC05MCB8fCBhbmdsZSA+IDkwID8gREVGQVVMVF9DU1NfRk9OVF9PQkxJUVVFIDogaXRhbGljQW5nbGUudG9TdHJpbmcoKTsKICByZXR1cm4gdHJ1ZTsKfQpmdW5jdGlvbiByZWNvdmVySnNVUkwoc3RyKSB7CiAgY29uc3QgVVJMX09QRU5fTUVUSE9EUyA9IFsiYXBwLmxhdW5jaFVSTCIsICJ3aW5kb3cub3BlbiIsICJ4ZmEuaG9zdC5nb3RvVVJMIl07CiAgY29uc3QgcmVnZXggPSBuZXcgUmVnRXhwKCJeXFxzKigiICsgVVJMX09QRU5fTUVUSE9EUy5qb2luKCJ8IikucmVwbGFjZUFsbCgiLiIsICJcXC4iKSArICIpXFwoKD86J3xcIikoW14nXCJdKikoPzonfFwiKSg/OixcXHMqKFxcdyspXFwpfFxcKSkiLCAiaSIpOwogIGNvbnN0IGpzVXJsID0gcmVnZXguZXhlYyhzdHIpOwogIGlmIChqc1VybCAmJiBqc1VybFsyXSkgewogICAgY29uc3QgdXJsID0ganNVcmxbMl07CiAgICBsZXQgbmV3V2luZG93ID0gZmFsc2U7CiAgICBpZiAoanNVcmxbM10gPT09ICJ0cnVlIiAmJiBqc1VybFsxXSA9PT0gImFwcC5sYXVuY2hVUkwiKSB7CiAgICAgIG5ld1dpbmRvdyA9IHRydWU7CiAgICB9CiAgICByZXR1cm4gewogICAgICB1cmwsCiAgICAgIG5ld1dpbmRvdwogICAgfTsKICB9CiAgcmV0dXJuIG51bGw7Cn0KZnVuY3Rpb24gbnVtYmVyVG9TdHJpbmcodmFsdWUpIHsKICBpZiAoTnVtYmVyLmlzSW50ZWdlcih2YWx1ZSkpIHsKICAgIHJldHVybiB2YWx1ZS50b1N0cmluZygpOwogIH0KICBjb25zdCByb3VuZGVkVmFsdWUgPSBNYXRoLnJvdW5kKHZhbHVlICogMTAwKTsKICBpZiAocm91bmRlZFZhbHVlICUgMTAwID09PSAwKSB7CiAgICByZXR1cm4gKHJvdW5kZWRWYWx1ZSAvIDEwMCkudG9TdHJpbmcoKTsKICB9CiAgaWYgKHJvdW5kZWRWYWx1ZSAlIDEwID09PSAwKSB7CiAgICByZXR1cm4gdmFsdWUudG9GaXhlZCgxKTsKICB9CiAgcmV0dXJuIHZhbHVlLnRvRml4ZWQoMik7Cn0KZnVuY3Rpb24gZ2V0TmV3QW5ub3RhdGlvbnNNYXAoYW5ub3RhdGlvblN0b3JhZ2UpIHsKICBpZiAoIWFubm90YXRpb25TdG9yYWdlKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgY29uc3QgbmV3QW5ub3RhdGlvbnNCeVBhZ2UgPSBuZXcgTWFwKCk7CiAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIGlmICgha2V5LnN0YXJ0c1dpdGgoX3V0aWwuQW5ub3RhdGlvbkVkaXRvclByZWZpeCkpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBsZXQgYW5ub3RhdGlvbnMgPSBuZXdBbm5vdGF0aW9uc0J5UGFnZS5nZXQodmFsdWUucGFnZUluZGV4KTsKICAgIGlmICghYW5ub3RhdGlvbnMpIHsKICAgICAgYW5ub3RhdGlvbnMgPSBbXTsKICAgICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2Uuc2V0KHZhbHVlLnBhZ2VJbmRleCwgYW5ub3RhdGlvbnMpOwogICAgfQogICAgYW5ub3RhdGlvbnMucHVzaCh2YWx1ZSk7CiAgfQogIHJldHVybiBuZXdBbm5vdGF0aW9uc0J5UGFnZS5zaXplID4gMCA/IG5ld0Fubm90YXRpb25zQnlQYWdlIDogbnVsbDsKfQpmdW5jdGlvbiBpc0FzY2lpKHN0cikgewogIHJldHVybiAvXltceDAwLVx4N0ZdKiQvLnRlc3Qoc3RyKTsKfQpmdW5jdGlvbiBzdHJpbmdUb1VURjE2SGV4U3RyaW5nKHN0cikgewogIGNvbnN0IGJ1ZiA9IFtdOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IHN0ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCBjaGFyID0gc3RyLmNoYXJDb2RlQXQoaSk7CiAgICBidWYucHVzaCgoY2hhciA+PiA4ICYgMHhmZikudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsICIwIiksIChjaGFyICYgMHhmZikudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsICIwIikpOwogIH0KICByZXR1cm4gYnVmLmpvaW4oIiIpOwp9CmZ1bmN0aW9uIHN0cmluZ1RvVVRGMTZTdHJpbmcoc3RyKSB7CiAgbGV0IGJpZ0VuZGlhbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogZmFsc2U7CiAgY29uc3QgYnVmID0gW107CiAgaWYgKGJpZ0VuZGlhbikgewogICAgYnVmLnB1c2goIlx4RkVceEZGIik7CiAgfQogIGZvciAobGV0IGkgPSAwLCBpaSA9IHN0ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCBjaGFyID0gc3RyLmNoYXJDb2RlQXQoaSk7CiAgICBidWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNoYXIgPj4gOCAmIDB4ZmYpLCBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoYXIgJiAweGZmKSk7CiAgfQogIHJldHVybiBidWYuam9pbigiIik7Cn0KZnVuY3Rpb24gZ2V0Um90YXRpb25NYXRyaXgocm90YXRpb24sIHdpZHRoLCBoZWlnaHQpIHsKICBzd2l0Y2ggKHJvdGF0aW9uKSB7CiAgICBjYXNlIDkwOgogICAgICByZXR1cm4gWzAsIDEsIC0xLCAwLCB3aWR0aCwgMF07CiAgICBjYXNlIDE4MDoKICAgICAgcmV0dXJuIFstMSwgMCwgMCwgLTEsIHdpZHRoLCBoZWlnaHRdOwogICAgY2FzZSAyNzA6CiAgICAgIHJldHVybiBbMCwgLTEsIDEsIDAsIDAsIGhlaWdodF07CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgcm90YXRpb24iKTsKICB9Cn0KCi8qKiovIH0pLAovKiAxNDAgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlJlZlNldENhY2hlID0gZXhwb3J0cy5SZWZTZXQgPSBleHBvcnRzLlJlZiA9IGV4cG9ydHMuTmFtZSA9IGV4cG9ydHMuRU9GID0gZXhwb3J0cy5EaWN0ID0gZXhwb3J0cy5DbWQgPSBleHBvcnRzLkNJUkNVTEFSX1JFRiA9IHZvaWQgMDsKZXhwb3J0cy5jbGVhclByaW1pdGl2ZUNhY2hlcyA9IGNsZWFyUHJpbWl0aXZlQ2FjaGVzOwpleHBvcnRzLmlzQ21kID0gaXNDbWQ7CmV4cG9ydHMuaXNEaWN0ID0gaXNEaWN0OwpleHBvcnRzLmlzTmFtZSA9IGlzTmFtZTsKZXhwb3J0cy5pc1JlZnNFcXVhbCA9IGlzUmVmc0VxdWFsOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpjb25zdCBDSVJDVUxBUl9SRUYgPSBTeW1ib2woIkNJUkNVTEFSX1JFRiIpOwpleHBvcnRzLkNJUkNVTEFSX1JFRiA9IENJUkNVTEFSX1JFRjsKY29uc3QgRU9GID0gU3ltYm9sKCJFT0YiKTsKZXhwb3J0cy5FT0YgPSBFT0Y7CmNvbnN0IE5hbWUgPSBmdW5jdGlvbiBOYW1lQ2xvc3VyZSgpIHsKICBsZXQgbmFtZUNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBjbGFzcyBOYW1lIHsKICAgIGNvbnN0cnVjdG9yKG5hbWUpIHsKICAgICAgdGhpcy5uYW1lID0gbmFtZTsKICAgIH0KICAgIHN0YXRpYyBnZXQobmFtZSkgewogICAgICByZXR1cm4gbmFtZUNhY2hlW25hbWVdIHx8IChuYW1lQ2FjaGVbbmFtZV0gPSBuZXcgTmFtZShuYW1lKSk7CiAgICB9CiAgICBzdGF0aWMgX2NsZWFyQ2FjaGUoKSB7CiAgICAgIG5hbWVDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB9CiAgfQogIHJldHVybiBOYW1lOwp9KCk7CmV4cG9ydHMuTmFtZSA9IE5hbWU7CmNvbnN0IENtZCA9IGZ1bmN0aW9uIENtZENsb3N1cmUoKSB7CiAgbGV0IGNtZENhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBjbGFzcyBDbWQgewogICAgY29uc3RydWN0b3IoY21kKSB7CiAgICAgIHRoaXMuY21kID0gY21kOwogICAgfQogICAgc3RhdGljIGdldChjbWQpIHsKICAgICAgcmV0dXJuIGNtZENhY2hlW2NtZF0gfHwgKGNtZENhY2hlW2NtZF0gPSBuZXcgQ21kKGNtZCkpOwogICAgfQogICAgc3RhdGljIF9jbGVhckNhY2hlKCkgewogICAgICBjbWRDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB9CiAgfQogIHJldHVybiBDbWQ7Cn0oKTsKZXhwb3J0cy5DbWQgPSBDbWQ7CmNvbnN0IG5vblNlcmlhbGl6YWJsZSA9IGZ1bmN0aW9uIG5vblNlcmlhbGl6YWJsZUNsb3N1cmUoKSB7CiAgcmV0dXJuIG5vblNlcmlhbGl6YWJsZTsKfTsKY2xhc3MgRGljdCB7CiAgY29uc3RydWN0b3IoKSB7CiAgICBsZXQgeHJlZiA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbnVsbDsKICAgIHRoaXMuX21hcCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB0aGlzLnhyZWYgPSB4cmVmOwogICAgdGhpcy5vYmpJZCA9IG51bGw7CiAgICB0aGlzLnN1cHByZXNzRW5jcnlwdGlvbiA9IGZhbHNlOwogICAgdGhpcy5fX25vblNlcmlhbGl6YWJsZV9fID0gbm9uU2VyaWFsaXphYmxlOwogIH0KICBhc3NpZ25YcmVmKG5ld1hyZWYpIHsKICAgIHRoaXMueHJlZiA9IG5ld1hyZWY7CiAgfQogIGdldCBzaXplKCkgewogICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuX21hcCkubGVuZ3RoOwogIH0KICBnZXQoa2V5MSwga2V5Miwga2V5MykgewogICAgbGV0IHZhbHVlID0gdGhpcy5fbWFwW2tleTFdOwogICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgJiYga2V5MiAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHZhbHVlID0gdGhpcy5fbWFwW2tleTJdOwogICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiBrZXkzICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB2YWx1ZSA9IHRoaXMuX21hcFtrZXkzXTsKICAgICAgfQogICAgfQogICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgUmVmICYmIHRoaXMueHJlZikgewogICAgICByZXR1cm4gdGhpcy54cmVmLmZldGNoKHZhbHVlLCB0aGlzLnN1cHByZXNzRW5jcnlwdGlvbik7CiAgICB9CiAgICByZXR1cm4gdmFsdWU7CiAgfQogIGFzeW5jIGdldEFzeW5jKGtleTEsIGtleTIsIGtleTMpIHsKICAgIGxldCB2YWx1ZSA9IHRoaXMuX21hcFtrZXkxXTsKICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIGtleTIgIT09IHVuZGVmaW5lZCkgewogICAgICB2YWx1ZSA9IHRoaXMuX21hcFtrZXkyXTsKICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgJiYga2V5MyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdmFsdWUgPSB0aGlzLl9tYXBba2V5M107CiAgICAgIH0KICAgIH0KICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFJlZiAmJiB0aGlzLnhyZWYpIHsKICAgICAgcmV0dXJuIHRoaXMueHJlZi5mZXRjaEFzeW5jKHZhbHVlLCB0aGlzLnN1cHByZXNzRW5jcnlwdGlvbik7CiAgICB9CiAgICByZXR1cm4gdmFsdWU7CiAgfQogIGdldEFycmF5KGtleTEsIGtleTIsIGtleTMpIHsKICAgIGxldCB2YWx1ZSA9IHRoaXMuX21hcFtrZXkxXTsKICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIGtleTIgIT09IHVuZGVmaW5lZCkgewogICAgICB2YWx1ZSA9IHRoaXMuX21hcFtrZXkyXTsKICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgJiYga2V5MyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdmFsdWUgPSB0aGlzLl9tYXBba2V5M107CiAgICAgIH0KICAgIH0KICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFJlZiAmJiB0aGlzLnhyZWYpIHsKICAgICAgdmFsdWUgPSB0aGlzLnhyZWYuZmV0Y2godmFsdWUsIHRoaXMuc3VwcHJlc3NFbmNyeXB0aW9uKTsKICAgIH0KICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkgewogICAgICB2YWx1ZSA9IHZhbHVlLnNsaWNlKCk7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHZhbHVlLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBpZiAodmFsdWVbaV0gaW5zdGFuY2VvZiBSZWYgJiYgdGhpcy54cmVmKSB7CiAgICAgICAgICB2YWx1ZVtpXSA9IHRoaXMueHJlZi5mZXRjaCh2YWx1ZVtpXSwgdGhpcy5zdXBwcmVzc0VuY3J5cHRpb24pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIHZhbHVlOwogIH0KICBnZXRSYXcoa2V5KSB7CiAgICByZXR1cm4gdGhpcy5fbWFwW2tleV07CiAgfQogIGdldEtleXMoKSB7CiAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy5fbWFwKTsKICB9CiAgZ2V0UmF3VmFsdWVzKCkgewogICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5fbWFwKTsKICB9CiAgc2V0KGtleSwgdmFsdWUpIHsKICAgIHRoaXMuX21hcFtrZXldID0gdmFsdWU7CiAgfQogIGhhcyhrZXkpIHsKICAgIHJldHVybiB0aGlzLl9tYXBba2V5XSAhPT0gdW5kZWZpbmVkOwogIH0KICBmb3JFYWNoKGNhbGxiYWNrKSB7CiAgICBmb3IgKGNvbnN0IGtleSBpbiB0aGlzLl9tYXApIHsKICAgICAgY2FsbGJhY2soa2V5LCB0aGlzLmdldChrZXkpKTsKICAgIH0KICB9CiAgc3RhdGljIGdldCBlbXB0eSgpIHsKICAgIGNvbnN0IGVtcHR5RGljdCA9IG5ldyBEaWN0KG51bGwpOwogICAgZW1wdHlEaWN0LnNldCA9IChrZXksIHZhbHVlKSA9PiB7CiAgICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIlNob3VsZCBub3QgY2FsbCBgc2V0YCBvbiB0aGUgZW1wdHkgZGljdGlvbmFyeS4iKTsKICAgIH07CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImVtcHR5IiwgZW1wdHlEaWN0KTsKICB9CiAgc3RhdGljIG1lcmdlKF9yZWYpIHsKICAgIGxldCB7CiAgICAgIHhyZWYsCiAgICAgIGRpY3RBcnJheSwKICAgICAgbWVyZ2VTdWJEaWN0cyA9IGZhbHNlCiAgICB9ID0gX3JlZjsKICAgIGNvbnN0IG1lcmdlZERpY3QgPSBuZXcgRGljdCh4cmVmKSwKICAgICAgcHJvcGVydGllcyA9IG5ldyBNYXAoKTsKICAgIGZvciAoY29uc3QgZGljdCBvZiBkaWN0QXJyYXkpIHsKICAgICAgaWYgKCEoZGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoZGljdC5fbWFwKSkgewogICAgICAgIGxldCBwcm9wZXJ0eSA9IHByb3BlcnRpZXMuZ2V0KGtleSk7CiAgICAgICAgaWYgKHByb3BlcnR5ID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHByb3BlcnR5ID0gW107CiAgICAgICAgICBwcm9wZXJ0aWVzLnNldChrZXksIHByb3BlcnR5KTsKICAgICAgICB9IGVsc2UgaWYgKCFtZXJnZVN1YkRpY3RzIHx8ICEodmFsdWUgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIHByb3BlcnR5LnB1c2godmFsdWUpOwogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IFtuYW1lLCB2YWx1ZXNdIG9mIHByb3BlcnRpZXMpIHsKICAgICAgaWYgKHZhbHVlcy5sZW5ndGggPT09IDEgfHwgISh2YWx1ZXNbMF0gaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgIG1lcmdlZERpY3QuX21hcFtuYW1lXSA9IHZhbHVlc1swXTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBzdWJEaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICAgIGZvciAoY29uc3QgZGljdCBvZiB2YWx1ZXMpIHsKICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhkaWN0Ll9tYXApKSB7CiAgICAgICAgICBpZiAoc3ViRGljdC5fbWFwW2tleV0gPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBzdWJEaWN0Ll9tYXBba2V5XSA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoc3ViRGljdC5zaXplID4gMCkgewogICAgICAgIG1lcmdlZERpY3QuX21hcFtuYW1lXSA9IHN1YkRpY3Q7CiAgICAgIH0KICAgIH0KICAgIHByb3BlcnRpZXMuY2xlYXIoKTsKICAgIHJldHVybiBtZXJnZWREaWN0LnNpemUgPiAwID8gbWVyZ2VkRGljdCA6IERpY3QuZW1wdHk7CiAgfQp9CmV4cG9ydHMuRGljdCA9IERpY3Q7CmNvbnN0IFJlZiA9IGZ1bmN0aW9uIFJlZkNsb3N1cmUoKSB7CiAgbGV0IHJlZkNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBjbGFzcyBSZWYgewogICAgY29uc3RydWN0b3IobnVtLCBnZW4pIHsKICAgICAgdGhpcy5udW0gPSBudW07CiAgICAgIHRoaXMuZ2VuID0gZ2VuOwogICAgfQogICAgdG9TdHJpbmcoKSB7CiAgICAgIGlmICh0aGlzLmdlbiA9PT0gMCkgewogICAgICAgIHJldHVybiBgJHt0aGlzLm51bX1SYDsKICAgICAgfQogICAgICByZXR1cm4gYCR7dGhpcy5udW19UiR7dGhpcy5nZW59YDsKICAgIH0KICAgIHN0YXRpYyBnZXQobnVtLCBnZW4pIHsKICAgICAgY29uc3Qga2V5ID0gZ2VuID09PSAwID8gYCR7bnVtfVJgIDogYCR7bnVtfVIke2dlbn1gOwogICAgICByZXR1cm4gcmVmQ2FjaGVba2V5XSB8fCAocmVmQ2FjaGVba2V5XSA9IG5ldyBSZWYobnVtLCBnZW4pKTsKICAgIH0KICAgIHN0YXRpYyBfY2xlYXJDYWNoZSgpIHsKICAgICAgcmVmQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgfQogIH0KICByZXR1cm4gUmVmOwp9KCk7CmV4cG9ydHMuUmVmID0gUmVmOwpjbGFzcyBSZWZTZXQgewogIGNvbnN0cnVjdG9yKCkgewogICAgbGV0IHBhcmVudCA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbnVsbDsKICAgIHRoaXMuX3NldCA9IG5ldyBTZXQocGFyZW50ICYmIHBhcmVudC5fc2V0KTsKICB9CiAgaGFzKHJlZikgewogICAgcmV0dXJuIHRoaXMuX3NldC5oYXMocmVmLnRvU3RyaW5nKCkpOwogIH0KICBwdXQocmVmKSB7CiAgICB0aGlzLl9zZXQuYWRkKHJlZi50b1N0cmluZygpKTsKICB9CiAgcmVtb3ZlKHJlZikgewogICAgdGhpcy5fc2V0LmRlbGV0ZShyZWYudG9TdHJpbmcoKSk7CiAgfQogIFtTeW1ib2wuaXRlcmF0b3JdKCkgewogICAgcmV0dXJuIHRoaXMuX3NldC52YWx1ZXMoKTsKICB9CiAgY2xlYXIoKSB7CiAgICB0aGlzLl9zZXQuY2xlYXIoKTsKICB9Cn0KZXhwb3J0cy5SZWZTZXQgPSBSZWZTZXQ7CmNsYXNzIFJlZlNldENhY2hlIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMuX21hcCA9IG5ldyBNYXAoKTsKICB9CiAgZ2V0IHNpemUoKSB7CiAgICByZXR1cm4gdGhpcy5fbWFwLnNpemU7CiAgfQogIGdldChyZWYpIHsKICAgIHJldHVybiB0aGlzLl9tYXAuZ2V0KHJlZi50b1N0cmluZygpKTsKICB9CiAgaGFzKHJlZikgewogICAgcmV0dXJuIHRoaXMuX21hcC5oYXMocmVmLnRvU3RyaW5nKCkpOwogIH0KICBwdXQocmVmLCBvYmopIHsKICAgIHRoaXMuX21hcC5zZXQocmVmLnRvU3RyaW5nKCksIG9iaik7CiAgfQogIHB1dEFsaWFzKHJlZiwgYWxpYXNSZWYpIHsKICAgIHRoaXMuX21hcC5zZXQocmVmLnRvU3RyaW5nKCksIHRoaXMuZ2V0KGFsaWFzUmVmKSk7CiAgfQogIFtTeW1ib2wuaXRlcmF0b3JdKCkgewogICAgcmV0dXJuIHRoaXMuX21hcC52YWx1ZXMoKTsKICB9CiAgY2xlYXIoKSB7CiAgICB0aGlzLl9tYXAuY2xlYXIoKTsKICB9Cn0KZXhwb3J0cy5SZWZTZXRDYWNoZSA9IFJlZlNldENhY2hlOwpmdW5jdGlvbiBpc05hbWUodiwgbmFtZSkgewogIHJldHVybiB2IGluc3RhbmNlb2YgTmFtZSAmJiAobmFtZSA9PT0gdW5kZWZpbmVkIHx8IHYubmFtZSA9PT0gbmFtZSk7Cn0KZnVuY3Rpb24gaXNDbWQodiwgY21kKSB7CiAgcmV0dXJuIHYgaW5zdGFuY2VvZiBDbWQgJiYgKGNtZCA9PT0gdW5kZWZpbmVkIHx8IHYuY21kID09PSBjbWQpOwp9CmZ1bmN0aW9uIGlzRGljdCh2LCB0eXBlKSB7CiAgcmV0dXJuIHYgaW5zdGFuY2VvZiBEaWN0ICYmICh0eXBlID09PSB1bmRlZmluZWQgfHwgaXNOYW1lKHYuZ2V0KCJUeXBlIiksIHR5cGUpKTsKfQpmdW5jdGlvbiBpc1JlZnNFcXVhbCh2MSwgdjIpIHsKICByZXR1cm4gdjEubnVtID09PSB2Mi5udW0gJiYgdjEuZ2VuID09PSB2Mi5nZW47Cn0KZnVuY3Rpb24gY2xlYXJQcmltaXRpdmVDYWNoZXMoKSB7CiAgQ21kLl9jbGVhckNhY2hlKCk7CiAgTmFtZS5fY2xlYXJDYWNoZSgpOwogIFJlZi5fY2xlYXJDYWNoZSgpOwp9CgovKioqLyB9KSwKLyogMTQxICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5CYXNlU3RyZWFtID0gdm9pZCAwOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpjbGFzcyBCYXNlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yID09PSBCYXNlU3RyZWFtKSB7CiAgICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIkNhbm5vdCBpbml0aWFsaXplIEJhc2VTdHJlYW0uIik7CiAgICB9CiAgfQogIGdldCBsZW5ndGgoKSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBnZXR0ZXIgYGxlbmd0aGAgYWNjZXNzZWQiKTsKICB9CiAgZ2V0IGlzRW1wdHkoKSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBnZXR0ZXIgYGlzRW1wdHlgIGFjY2Vzc2VkIik7CiAgfQogIGdldCBpc0RhdGFMb2FkZWQoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImlzRGF0YUxvYWRlZCIsIHRydWUpOwogIH0KICBnZXRCeXRlKCkgewogICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQWJzdHJhY3QgbWV0aG9kIGBnZXRCeXRlYCBjYWxsZWQiKTsKICB9CiAgZ2V0Qnl0ZXMobGVuZ3RoKSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBtZXRob2QgYGdldEJ5dGVzYCBjYWxsZWQiKTsKICB9CiAgcGVla0J5dGUoKSB7CiAgICBjb25zdCBwZWVrZWRCeXRlID0gdGhpcy5nZXRCeXRlKCk7CiAgICBpZiAocGVla2VkQnl0ZSAhPT0gLTEpIHsKICAgICAgdGhpcy5wb3MtLTsKICAgIH0KICAgIHJldHVybiBwZWVrZWRCeXRlOwogIH0KICBwZWVrQnl0ZXMobGVuZ3RoKSB7CiAgICBjb25zdCBieXRlcyA9IHRoaXMuZ2V0Qnl0ZXMobGVuZ3RoKTsKICAgIHRoaXMucG9zIC09IGJ5dGVzLmxlbmd0aDsKICAgIHJldHVybiBieXRlczsKICB9CiAgZ2V0VWludDE2KCkgewogICAgY29uc3QgYjAgPSB0aGlzLmdldEJ5dGUoKTsKICAgIGNvbnN0IGIxID0gdGhpcy5nZXRCeXRlKCk7CiAgICBpZiAoYjAgPT09IC0xIHx8IGIxID09PSAtMSkgewogICAgICByZXR1cm4gLTE7CiAgICB9CiAgICByZXR1cm4gKGIwIDw8IDgpICsgYjE7CiAgfQogIGdldEludDMyKCkgewogICAgY29uc3QgYjAgPSB0aGlzLmdldEJ5dGUoKTsKICAgIGNvbnN0IGIxID0gdGhpcy5nZXRCeXRlKCk7CiAgICBjb25zdCBiMiA9IHRoaXMuZ2V0Qnl0ZSgpOwogICAgY29uc3QgYjMgPSB0aGlzLmdldEJ5dGUoKTsKICAgIHJldHVybiAoYjAgPDwgMjQpICsgKGIxIDw8IDE2KSArIChiMiA8PCA4KSArIGIzOwogIH0KICBnZXRCeXRlUmFuZ2UoYmVnaW4sIGVuZCkgewogICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQWJzdHJhY3QgbWV0aG9kIGBnZXRCeXRlUmFuZ2VgIGNhbGxlZCIpOwogIH0KICBnZXRTdHJpbmcobGVuZ3RoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLmJ5dGVzVG9TdHJpbmcpKHRoaXMuZ2V0Qnl0ZXMobGVuZ3RoKSk7CiAgfQogIHNraXAobikgewogICAgdGhpcy5wb3MgKz0gbiB8fCAxOwogIH0KICByZXNldCgpIHsKICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIkFic3RyYWN0IG1ldGhvZCBgcmVzZXRgIGNhbGxlZCIpOwogIH0KICBtb3ZlU3RhcnQoKSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBtZXRob2QgYG1vdmVTdGFydGAgY2FsbGVkIik7CiAgfQogIG1ha2VTdWJTdHJlYW0oc3RhcnQsIGxlbmd0aCkgewogICAgbGV0IGRpY3QgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IG51bGw7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBtZXRob2QgYG1ha2VTdWJTdHJlYW1gIGNhbGxlZCIpOwogIH0KICBnZXRCYXNlU3RyZWFtcygpIHsKICAgIHJldHVybiBudWxsOwogIH0KfQpleHBvcnRzLkJhc2VTdHJlYW0gPSBCYXNlU3RyZWFtOwoKLyoqKi8gfSksCi8qIDE0MiAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuTmV0d29ya1BkZk1hbmFnZXIgPSBleHBvcnRzLkxvY2FsUGRmTWFuYWdlciA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9jaHVua2VkX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQzKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX2RvY3VtZW50ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDUpOwp2YXIgX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQ0KTsKZnVuY3Rpb24gcGFyc2VEb2NCYXNlVXJsKHVybCkgewogIGlmICh1cmwpIHsKICAgIGNvbnN0IGFic29sdXRlVXJsID0gKDAsIF91dGlsLmNyZWF0ZVZhbGlkQWJzb2x1dGVVcmwpKHVybCk7CiAgICBpZiAoYWJzb2x1dGVVcmwpIHsKICAgICAgcmV0dXJuIGFic29sdXRlVXJsLmhyZWY7CiAgICB9CiAgICAoMCwgX3V0aWwud2FybikoYEludmFsaWQgYWJzb2x1dGUgZG9jQmFzZVVybDogIiR7dXJsfSIuYCk7CiAgfQogIHJldHVybiBudWxsOwp9CmNsYXNzIEJhc2VQZGZNYW5hZ2VyIHsKICBjb25zdHJ1Y3RvcihhcmdzKSB7CiAgICBpZiAodGhpcy5jb25zdHJ1Y3RvciA9PT0gQmFzZVBkZk1hbmFnZXIpIHsKICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQ2Fubm90IGluaXRpYWxpemUgQmFzZVBkZk1hbmFnZXIuIik7CiAgICB9CiAgICB0aGlzLl9kb2NCYXNlVXJsID0gcGFyc2VEb2NCYXNlVXJsKGFyZ3MuZG9jQmFzZVVybCk7CiAgICB0aGlzLl9kb2NJZCA9IGFyZ3MuZG9jSWQ7CiAgICB0aGlzLl9wYXNzd29yZCA9IGFyZ3MucGFzc3dvcmQ7CiAgICB0aGlzLmVuYWJsZVhmYSA9IGFyZ3MuZW5hYmxlWGZhOwogICAgYXJncy5ldmFsdWF0b3JPcHRpb25zLmlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkID0gYXJncy5ldmFsdWF0b3JPcHRpb25zLmlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkICYmIF91dGlsLkZlYXR1cmVUZXN0LmlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkOwogICAgdGhpcy5ldmFsdWF0b3JPcHRpb25zID0gYXJncy5ldmFsdWF0b3JPcHRpb25zOwogIH0KICBnZXQgZG9jSWQoKSB7CiAgICByZXR1cm4gdGhpcy5fZG9jSWQ7CiAgfQogIGdldCBwYXNzd29yZCgpIHsKICAgIHJldHVybiB0aGlzLl9wYXNzd29yZDsKICB9CiAgZ2V0IGRvY0Jhc2VVcmwoKSB7CiAgICBjb25zdCBjYXRhbG9nID0gdGhpcy5wZGZEb2N1bWVudC5jYXRhbG9nOwogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJkb2NCYXNlVXJsIiwgY2F0YWxvZy5iYXNlVXJsIHx8IHRoaXMuX2RvY0Jhc2VVcmwpOwogIH0KICBlbnN1cmVEb2MocHJvcCwgYXJncykgewogICAgcmV0dXJuIHRoaXMuZW5zdXJlKHRoaXMucGRmRG9jdW1lbnQsIHByb3AsIGFyZ3MpOwogIH0KICBlbnN1cmVYUmVmKHByb3AsIGFyZ3MpIHsKICAgIHJldHVybiB0aGlzLmVuc3VyZSh0aGlzLnBkZkRvY3VtZW50LnhyZWYsIHByb3AsIGFyZ3MpOwogIH0KICBlbnN1cmVDYXRhbG9nKHByb3AsIGFyZ3MpIHsKICAgIHJldHVybiB0aGlzLmVuc3VyZSh0aGlzLnBkZkRvY3VtZW50LmNhdGFsb2csIHByb3AsIGFyZ3MpOwogIH0KICBnZXRQYWdlKHBhZ2VJbmRleCkgewogICAgcmV0dXJuIHRoaXMucGRmRG9jdW1lbnQuZ2V0UGFnZShwYWdlSW5kZXgpOwogIH0KICBmb250RmFsbGJhY2soaWQsIGhhbmRsZXIpIHsKICAgIHJldHVybiB0aGlzLnBkZkRvY3VtZW50LmZvbnRGYWxsYmFjayhpZCwgaGFuZGxlcik7CiAgfQogIGxvYWRYZmFGb250cyhoYW5kbGVyLCB0YXNrKSB7CiAgICByZXR1cm4gdGhpcy5wZGZEb2N1bWVudC5sb2FkWGZhRm9udHMoaGFuZGxlciwgdGFzayk7CiAgfQogIGxvYWRYZmFJbWFnZXMoKSB7CiAgICByZXR1cm4gdGhpcy5wZGZEb2N1bWVudC5sb2FkWGZhSW1hZ2VzKCk7CiAgfQogIHNlcmlhbGl6ZVhmYURhdGEoYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIHJldHVybiB0aGlzLnBkZkRvY3VtZW50LnNlcmlhbGl6ZVhmYURhdGEoYW5ub3RhdGlvblN0b3JhZ2UpOwogIH0KICBjbGVhbnVwKCkgewogICAgbGV0IG1hbnVhbGx5VHJpZ2dlcmVkID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBmYWxzZTsKICAgIHJldHVybiB0aGlzLnBkZkRvY3VtZW50LmNsZWFudXAobWFudWFsbHlUcmlnZ2VyZWQpOwogIH0KICBhc3luYyBlbnN1cmUob2JqLCBwcm9wLCBhcmdzKSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBtZXRob2QgYGVuc3VyZWAgY2FsbGVkIik7CiAgfQogIHJlcXVlc3RSYW5nZShiZWdpbiwgZW5kKSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBtZXRob2QgYHJlcXVlc3RSYW5nZWAgY2FsbGVkIik7CiAgfQogIHJlcXVlc3RMb2FkZWRTdHJlYW0oKSB7CiAgICBsZXQgbm9GZXRjaCA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogZmFsc2U7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBtZXRob2QgYHJlcXVlc3RMb2FkZWRTdHJlYW1gIGNhbGxlZCIpOwogIH0KICBzZW5kUHJvZ3Jlc3NpdmVEYXRhKGNodW5rKSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBtZXRob2QgYHNlbmRQcm9ncmVzc2l2ZURhdGFgIGNhbGxlZCIpOwogIH0KICB1cGRhdGVQYXNzd29yZChwYXNzd29yZCkgewogICAgdGhpcy5fcGFzc3dvcmQgPSBwYXNzd29yZDsKICB9CiAgdGVybWluYXRlKHJlYXNvbikgewogICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQWJzdHJhY3QgbWV0aG9kIGB0ZXJtaW5hdGVgIGNhbGxlZCIpOwogIH0KfQpjbGFzcyBMb2NhbFBkZk1hbmFnZXIgZXh0ZW5kcyBCYXNlUGRmTWFuYWdlciB7CiAgY29uc3RydWN0b3IoYXJncykgewogICAgc3VwZXIoYXJncyk7CiAgICBjb25zdCBzdHJlYW0gPSBuZXcgX3N0cmVhbS5TdHJlYW0oYXJncy5zb3VyY2UpOwogICAgdGhpcy5wZGZEb2N1bWVudCA9IG5ldyBfZG9jdW1lbnQuUERGRG9jdW1lbnQodGhpcywgc3RyZWFtKTsKICAgIHRoaXMuX2xvYWRlZFN0cmVhbVByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoc3RyZWFtKTsKICB9CiAgYXN5bmMgZW5zdXJlKG9iaiwgcHJvcCwgYXJncykgewogICAgY29uc3QgdmFsdWUgPSBvYmpbcHJvcF07CiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAiZnVuY3Rpb24iKSB7CiAgICAgIHJldHVybiB2YWx1ZS5hcHBseShvYmosIGFyZ3MpOwogICAgfQogICAgcmV0dXJuIHZhbHVlOwogIH0KICByZXF1ZXN0UmFuZ2UoYmVnaW4sIGVuZCkgewogICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpOwogIH0KICByZXF1ZXN0TG9hZGVkU3RyZWFtKCkgewogICAgbGV0IG5vRmV0Y2ggPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgcmV0dXJuIHRoaXMuX2xvYWRlZFN0cmVhbVByb21pc2U7CiAgfQogIHRlcm1pbmF0ZShyZWFzb24pIHt9Cn0KZXhwb3J0cy5Mb2NhbFBkZk1hbmFnZXIgPSBMb2NhbFBkZk1hbmFnZXI7CmNsYXNzIE5ldHdvcmtQZGZNYW5hZ2VyIGV4dGVuZHMgQmFzZVBkZk1hbmFnZXIgewogIGNvbnN0cnVjdG9yKGFyZ3MpIHsKICAgIHN1cGVyKGFyZ3MpOwogICAgdGhpcy5zdHJlYW1NYW5hZ2VyID0gbmV3IF9jaHVua2VkX3N0cmVhbS5DaHVua2VkU3RyZWFtTWFuYWdlcihhcmdzLnNvdXJjZSwgewogICAgICBtc2dIYW5kbGVyOiBhcmdzLmhhbmRsZXIsCiAgICAgIGxlbmd0aDogYXJncy5sZW5ndGgsCiAgICAgIGRpc2FibGVBdXRvRmV0Y2g6IGFyZ3MuZGlzYWJsZUF1dG9GZXRjaCwKICAgICAgcmFuZ2VDaHVua1NpemU6IGFyZ3MucmFuZ2VDaHVua1NpemUKICAgIH0pOwogICAgdGhpcy5wZGZEb2N1bWVudCA9IG5ldyBfZG9jdW1lbnQuUERGRG9jdW1lbnQodGhpcywgdGhpcy5zdHJlYW1NYW5hZ2VyLmdldFN0cmVhbSgpKTsKICB9CiAgYXN5bmMgZW5zdXJlKG9iaiwgcHJvcCwgYXJncykgewogICAgdHJ5IHsKICAgICAgY29uc3QgdmFsdWUgPSBvYmpbcHJvcF07CiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgICByZXR1cm4gdmFsdWUuYXBwbHkob2JqLCBhcmdzKTsKICAgICAgfQogICAgICByZXR1cm4gdmFsdWU7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoIShleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSkgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIGF3YWl0IHRoaXMucmVxdWVzdFJhbmdlKGV4LmJlZ2luLCBleC5lbmQpOwogICAgICByZXR1cm4gdGhpcy5lbnN1cmUob2JqLCBwcm9wLCBhcmdzKTsKICAgIH0KICB9CiAgcmVxdWVzdFJhbmdlKGJlZ2luLCBlbmQpIHsKICAgIHJldHVybiB0aGlzLnN0cmVhbU1hbmFnZXIucmVxdWVzdFJhbmdlKGJlZ2luLCBlbmQpOwogIH0KICByZXF1ZXN0TG9hZGVkU3RyZWFtKCkgewogICAgbGV0IG5vRmV0Y2ggPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgcmV0dXJuIHRoaXMuc3RyZWFtTWFuYWdlci5yZXF1ZXN0QWxsQ2h1bmtzKG5vRmV0Y2gpOwogIH0KICBzZW5kUHJvZ3Jlc3NpdmVEYXRhKGNodW5rKSB7CiAgICB0aGlzLnN0cmVhbU1hbmFnZXIub25SZWNlaXZlRGF0YSh7CiAgICAgIGNodW5rCiAgICB9KTsKICB9CiAgdGVybWluYXRlKHJlYXNvbikgewogICAgdGhpcy5zdHJlYW1NYW5hZ2VyLmFib3J0KHJlYXNvbik7CiAgfQp9CmV4cG9ydHMuTmV0d29ya1BkZk1hbmFnZXIgPSBOZXR3b3JrUGRmTWFuYWdlcjsKCi8qKiovIH0pLAovKiAxNDMgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLkNodW5rZWRTdHJlYW1NYW5hZ2VyID0gZXhwb3J0cy5DaHVua2VkU3RyZWFtID0gdm9pZCAwOwp2YXIgX2NvcmVfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzOSk7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CnZhciBfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDQpOwpjbGFzcyBDaHVua2VkU3RyZWFtIGV4dGVuZHMgX3N0cmVhbS5TdHJlYW0gewogIGNvbnN0cnVjdG9yKGxlbmd0aCwgY2h1bmtTaXplLCBtYW5hZ2VyKSB7CiAgICBzdXBlcihuZXcgVWludDhBcnJheShsZW5ndGgpLCAwLCBsZW5ndGgsIG51bGwpOwogICAgdGhpcy5jaHVua1NpemUgPSBjaHVua1NpemU7CiAgICB0aGlzLl9sb2FkZWRDaHVua3MgPSBuZXcgU2V0KCk7CiAgICB0aGlzLm51bUNodW5rcyA9IE1hdGguY2VpbChsZW5ndGggLyBjaHVua1NpemUpOwogICAgdGhpcy5tYW5hZ2VyID0gbWFuYWdlcjsKICAgIHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoID0gMDsKICAgIHRoaXMubGFzdFN1Y2Nlc3NmdWxFbnN1cmVCeXRlQ2h1bmsgPSAtMTsKICB9CiAgZ2V0TWlzc2luZ0NodW5rcygpIHsKICAgIGNvbnN0IGNodW5rcyA9IFtdOwogICAgZm9yIChsZXQgY2h1bmsgPSAwLCBuID0gdGhpcy5udW1DaHVua3M7IGNodW5rIDwgbjsgKytjaHVuaykgewogICAgICBpZiAoIXRoaXMuX2xvYWRlZENodW5rcy5oYXMoY2h1bmspKSB7CiAgICAgICAgY2h1bmtzLnB1c2goY2h1bmspOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gY2h1bmtzOwogIH0KICBnZXQgbnVtQ2h1bmtzTG9hZGVkKCkgewogICAgcmV0dXJuIHRoaXMuX2xvYWRlZENodW5rcy5zaXplOwogIH0KICBnZXQgaXNEYXRhTG9hZGVkKCkgewogICAgcmV0dXJuIHRoaXMubnVtQ2h1bmtzTG9hZGVkID09PSB0aGlzLm51bUNodW5rczsKICB9CiAgb25SZWNlaXZlRGF0YShiZWdpbiwgY2h1bmspIHsKICAgIGNvbnN0IGNodW5rU2l6ZSA9IHRoaXMuY2h1bmtTaXplOwogICAgaWYgKGJlZ2luICUgY2h1bmtTaXplICE9PSAwKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcihgQmFkIGJlZ2luIG9mZnNldDogJHtiZWdpbn1gKTsKICAgIH0KICAgIGNvbnN0IGVuZCA9IGJlZ2luICsgY2h1bmsuYnl0ZUxlbmd0aDsKICAgIGlmIChlbmQgJSBjaHVua1NpemUgIT09IDAgJiYgZW5kICE9PSB0aGlzLmJ5dGVzLmxlbmd0aCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYEJhZCBlbmQgb2Zmc2V0OiAke2VuZH1gKTsKICAgIH0KICAgIHRoaXMuYnl0ZXMuc2V0KG5ldyBVaW50OEFycmF5KGNodW5rKSwgYmVnaW4pOwogICAgY29uc3QgYmVnaW5DaHVuayA9IE1hdGguZmxvb3IoYmVnaW4gLyBjaHVua1NpemUpOwogICAgY29uc3QgZW5kQ2h1bmsgPSBNYXRoLmZsb29yKChlbmQgLSAxKSAvIGNodW5rU2l6ZSkgKyAxOwogICAgZm9yIChsZXQgY3VyQ2h1bmsgPSBiZWdpbkNodW5rOyBjdXJDaHVuayA8IGVuZENodW5rOyArK2N1ckNodW5rKSB7CiAgICAgIHRoaXMuX2xvYWRlZENodW5rcy5hZGQoY3VyQ2h1bmspOwogICAgfQogIH0KICBvblJlY2VpdmVQcm9ncmVzc2l2ZURhdGEoZGF0YSkgewogICAgbGV0IHBvc2l0aW9uID0gdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGg7CiAgICBjb25zdCBiZWdpbkNodW5rID0gTWF0aC5mbG9vcihwb3NpdGlvbiAvIHRoaXMuY2h1bmtTaXplKTsKICAgIHRoaXMuYnl0ZXMuc2V0KG5ldyBVaW50OEFycmF5KGRhdGEpLCBwb3NpdGlvbik7CiAgICBwb3NpdGlvbiArPSBkYXRhLmJ5dGVMZW5ndGg7CiAgICB0aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aCA9IHBvc2l0aW9uOwogICAgY29uc3QgZW5kQ2h1bmsgPSBwb3NpdGlvbiA+PSB0aGlzLmVuZCA/IHRoaXMubnVtQ2h1bmtzIDogTWF0aC5mbG9vcihwb3NpdGlvbiAvIHRoaXMuY2h1bmtTaXplKTsKICAgIGZvciAobGV0IGN1ckNodW5rID0gYmVnaW5DaHVuazsgY3VyQ2h1bmsgPCBlbmRDaHVuazsgKytjdXJDaHVuaykgewogICAgICB0aGlzLl9sb2FkZWRDaHVua3MuYWRkKGN1ckNodW5rKTsKICAgIH0KICB9CiAgZW5zdXJlQnl0ZShwb3MpIHsKICAgIGlmIChwb3MgPCB0aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aCkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBjaHVuayA9IE1hdGguZmxvb3IocG9zIC8gdGhpcy5jaHVua1NpemUpOwogICAgaWYgKGNodW5rID4gdGhpcy5udW1DaHVua3MpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKGNodW5rID09PSB0aGlzLmxhc3RTdWNjZXNzZnVsRW5zdXJlQnl0ZUNodW5rKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICghdGhpcy5fbG9hZGVkQ2h1bmtzLmhhcyhjaHVuaykpIHsKICAgICAgdGhyb3cgbmV3IF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKHBvcywgcG9zICsgMSk7CiAgICB9CiAgICB0aGlzLmxhc3RTdWNjZXNzZnVsRW5zdXJlQnl0ZUNodW5rID0gY2h1bms7CiAgfQogIGVuc3VyZVJhbmdlKGJlZ2luLCBlbmQpIHsKICAgIGlmIChiZWdpbiA+PSBlbmQpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKGVuZCA8PSB0aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aCkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBiZWdpbkNodW5rID0gTWF0aC5mbG9vcihiZWdpbiAvIHRoaXMuY2h1bmtTaXplKTsKICAgIGlmIChiZWdpbkNodW5rID4gdGhpcy5udW1DaHVua3MpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgZW5kQ2h1bmsgPSBNYXRoLm1pbihNYXRoLmZsb29yKChlbmQgLSAxKSAvIHRoaXMuY2h1bmtTaXplKSArIDEsIHRoaXMubnVtQ2h1bmtzKTsKICAgIGZvciAobGV0IGNodW5rID0gYmVnaW5DaHVuazsgY2h1bmsgPCBlbmRDaHVuazsgKytjaHVuaykgewogICAgICBpZiAoIXRoaXMuX2xvYWRlZENodW5rcy5oYXMoY2h1bmspKSB7CiAgICAgICAgdGhyb3cgbmV3IF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKGJlZ2luLCBlbmQpOwogICAgICB9CiAgICB9CiAgfQogIG5leHRFbXB0eUNodW5rKGJlZ2luQ2h1bmspIHsKICAgIGNvbnN0IG51bUNodW5rcyA9IHRoaXMubnVtQ2h1bmtzOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1DaHVua3M7ICsraSkgewogICAgICBjb25zdCBjaHVuayA9IChiZWdpbkNodW5rICsgaSkgJSBudW1DaHVua3M7CiAgICAgIGlmICghdGhpcy5fbG9hZGVkQ2h1bmtzLmhhcyhjaHVuaykpIHsKICAgICAgICByZXR1cm4gY2h1bms7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICBoYXNDaHVuayhjaHVuaykgewogICAgcmV0dXJuIHRoaXMuX2xvYWRlZENodW5rcy5oYXMoY2h1bmspOwogIH0KICBnZXRCeXRlKCkgewogICAgY29uc3QgcG9zID0gdGhpcy5wb3M7CiAgICBpZiAocG9zID49IHRoaXMuZW5kKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGlmIChwb3MgPj0gdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgpIHsKICAgICAgdGhpcy5lbnN1cmVCeXRlKHBvcyk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5ieXRlc1t0aGlzLnBvcysrXTsKICB9CiAgZ2V0Qnl0ZXMobGVuZ3RoKSB7CiAgICBjb25zdCBieXRlcyA9IHRoaXMuYnl0ZXM7CiAgICBjb25zdCBwb3MgPSB0aGlzLnBvczsKICAgIGNvbnN0IHN0ckVuZCA9IHRoaXMuZW5kOwogICAgaWYgKCFsZW5ndGgpIHsKICAgICAgaWYgKHN0ckVuZCA+IHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoKSB7CiAgICAgICAgdGhpcy5lbnN1cmVSYW5nZShwb3MsIHN0ckVuZCk7CiAgICAgIH0KICAgICAgcmV0dXJuIGJ5dGVzLnN1YmFycmF5KHBvcywgc3RyRW5kKTsKICAgIH0KICAgIGxldCBlbmQgPSBwb3MgKyBsZW5ndGg7CiAgICBpZiAoZW5kID4gc3RyRW5kKSB7CiAgICAgIGVuZCA9IHN0ckVuZDsKICAgIH0KICAgIGlmIChlbmQgPiB0aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aCkgewogICAgICB0aGlzLmVuc3VyZVJhbmdlKHBvcywgZW5kKTsKICAgIH0KICAgIHRoaXMucG9zID0gZW5kOwogICAgcmV0dXJuIGJ5dGVzLnN1YmFycmF5KHBvcywgZW5kKTsKICB9CiAgZ2V0Qnl0ZVJhbmdlKGJlZ2luLCBlbmQpIHsKICAgIGlmIChiZWdpbiA8IDApIHsKICAgICAgYmVnaW4gPSAwOwogICAgfQogICAgaWYgKGVuZCA+IHRoaXMuZW5kKSB7CiAgICAgIGVuZCA9IHRoaXMuZW5kOwogICAgfQogICAgaWYgKGVuZCA+IHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoKSB7CiAgICAgIHRoaXMuZW5zdXJlUmFuZ2UoYmVnaW4sIGVuZCk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5ieXRlcy5zdWJhcnJheShiZWdpbiwgZW5kKTsKICB9CiAgbWFrZVN1YlN0cmVhbShzdGFydCwgbGVuZ3RoKSB7CiAgICBsZXQgZGljdCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogbnVsbDsKICAgIGlmIChsZW5ndGgpIHsKICAgICAgaWYgKHN0YXJ0ICsgbGVuZ3RoID4gdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgpIHsKICAgICAgICB0aGlzLmVuc3VyZVJhbmdlKHN0YXJ0LCBzdGFydCArIGxlbmd0aCk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGlmIChzdGFydCA+PSB0aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aCkgewogICAgICAgIHRoaXMuZW5zdXJlQnl0ZShzdGFydCk7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIENodW5rZWRTdHJlYW1TdWJzdHJlYW0oKSB7fQogICAgQ2h1bmtlZFN0cmVhbVN1YnN0cmVhbS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHRoaXMpOwogICAgQ2h1bmtlZFN0cmVhbVN1YnN0cmVhbS5wcm90b3R5cGUuZ2V0TWlzc2luZ0NodW5rcyA9IGZ1bmN0aW9uICgpIHsKICAgICAgY29uc3QgY2h1bmtTaXplID0gdGhpcy5jaHVua1NpemU7CiAgICAgIGNvbnN0IGJlZ2luQ2h1bmsgPSBNYXRoLmZsb29yKHRoaXMuc3RhcnQgLyBjaHVua1NpemUpOwogICAgICBjb25zdCBlbmRDaHVuayA9IE1hdGguZmxvb3IoKHRoaXMuZW5kIC0gMSkgLyBjaHVua1NpemUpICsgMTsKICAgICAgY29uc3QgbWlzc2luZ0NodW5rcyA9IFtdOwogICAgICBmb3IgKGxldCBjaHVuayA9IGJlZ2luQ2h1bms7IGNodW5rIDwgZW5kQ2h1bms7ICsrY2h1bmspIHsKICAgICAgICBpZiAoIXRoaXMuX2xvYWRlZENodW5rcy5oYXMoY2h1bmspKSB7CiAgICAgICAgICBtaXNzaW5nQ2h1bmtzLnB1c2goY2h1bmspOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbWlzc2luZ0NodW5rczsKICAgIH07CiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQ2h1bmtlZFN0cmVhbVN1YnN0cmVhbS5wcm90b3R5cGUsICJpc0RhdGFMb2FkZWQiLCB7CiAgICAgIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5udW1DaHVua3NMb2FkZWQgPT09IHRoaXMubnVtQ2h1bmtzKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TWlzc2luZ0NodW5rcygpLmxlbmd0aCA9PT0gMDsKICAgICAgfSwKICAgICAgY29uZmlndXJhYmxlOiB0cnVlCiAgICB9KTsKICAgIGNvbnN0IHN1YlN0cmVhbSA9IG5ldyBDaHVua2VkU3RyZWFtU3Vic3RyZWFtKCk7CiAgICBzdWJTdHJlYW0ucG9zID0gc3ViU3RyZWFtLnN0YXJ0ID0gc3RhcnQ7CiAgICBzdWJTdHJlYW0uZW5kID0gc3RhcnQgKyBsZW5ndGggfHwgdGhpcy5lbmQ7CiAgICBzdWJTdHJlYW0uZGljdCA9IGRpY3Q7CiAgICByZXR1cm4gc3ViU3RyZWFtOwogIH0KICBnZXRCYXNlU3RyZWFtcygpIHsKICAgIHJldHVybiBbdGhpc107CiAgfQp9CmV4cG9ydHMuQ2h1bmtlZFN0cmVhbSA9IENodW5rZWRTdHJlYW07CmNsYXNzIENodW5rZWRTdHJlYW1NYW5hZ2VyIHsKICBjb25zdHJ1Y3RvcihwZGZOZXR3b3JrU3RyZWFtLCBhcmdzKSB7CiAgICB0aGlzLmxlbmd0aCA9IGFyZ3MubGVuZ3RoOwogICAgdGhpcy5jaHVua1NpemUgPSBhcmdzLnJhbmdlQ2h1bmtTaXplOwogICAgdGhpcy5zdHJlYW0gPSBuZXcgQ2h1bmtlZFN0cmVhbSh0aGlzLmxlbmd0aCwgdGhpcy5jaHVua1NpemUsIHRoaXMpOwogICAgdGhpcy5wZGZOZXR3b3JrU3RyZWFtID0gcGRmTmV0d29ya1N0cmVhbTsKICAgIHRoaXMuZGlzYWJsZUF1dG9GZXRjaCA9IGFyZ3MuZGlzYWJsZUF1dG9GZXRjaDsKICAgIHRoaXMubXNnSGFuZGxlciA9IGFyZ3MubXNnSGFuZGxlcjsKICAgIHRoaXMuY3VyclJlcXVlc3RJZCA9IDA7CiAgICB0aGlzLl9jaHVua3NOZWVkZWRCeVJlcXVlc3QgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9yZXF1ZXN0c0J5Q2h1bmsgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9wcm9taXNlc0J5UmVxdWVzdCA9IG5ldyBNYXAoKTsKICAgIHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoID0gMDsKICAgIHRoaXMuYWJvcnRlZCA9IGZhbHNlOwogICAgdGhpcy5fbG9hZGVkU3RyZWFtQ2FwYWJpbGl0eSA9ICgwLCBfdXRpbC5jcmVhdGVQcm9taXNlQ2FwYWJpbGl0eSkoKTsKICB9CiAgc2VuZFJlcXVlc3QoYmVnaW4sIGVuZCkgewogICAgY29uc3QgcmFuZ2VSZWFkZXIgPSB0aGlzLnBkZk5ldHdvcmtTdHJlYW0uZ2V0UmFuZ2VSZWFkZXIoYmVnaW4sIGVuZCk7CiAgICBpZiAoIXJhbmdlUmVhZGVyLmlzU3RyZWFtaW5nU3VwcG9ydGVkKSB7CiAgICAgIHJhbmdlUmVhZGVyLm9uUHJvZ3Jlc3MgPSB0aGlzLm9uUHJvZ3Jlc3MuYmluZCh0aGlzKTsKICAgIH0KICAgIGxldCBjaHVua3MgPSBbXSwKICAgICAgbG9hZGVkID0gMDsKICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAgIGNvbnN0IHJlYWRDaHVuayA9IF9yZWYgPT4gewogICAgICAgIGxldCB7CiAgICAgICAgICB2YWx1ZSwKICAgICAgICAgIGRvbmUKICAgICAgICB9ID0gX3JlZjsKICAgICAgICB0cnkgewogICAgICAgICAgaWYgKGRvbmUpIHsKICAgICAgICAgICAgY29uc3QgY2h1bmtEYXRhID0gKDAsIF9jb3JlX3V0aWxzLmFycmF5QnVmZmVyc1RvQnl0ZXMpKGNodW5rcyk7CiAgICAgICAgICAgIGNodW5rcyA9IG51bGw7CiAgICAgICAgICAgIHJlc29sdmUoY2h1bmtEYXRhKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgfQogICAgICAgICAgbG9hZGVkICs9IHZhbHVlLmJ5dGVMZW5ndGg7CiAgICAgICAgICBpZiAocmFuZ2VSZWFkZXIuaXNTdHJlYW1pbmdTdXBwb3J0ZWQpIHsKICAgICAgICAgICAgdGhpcy5vblByb2dyZXNzKHsKICAgICAgICAgICAgICBsb2FkZWQKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBjaHVua3MucHVzaCh2YWx1ZSk7CiAgICAgICAgICByYW5nZVJlYWRlci5yZWFkKCkudGhlbihyZWFkQ2h1bmssIHJlamVjdCk7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgcmVqZWN0KGUpOwogICAgICAgIH0KICAgICAgfTsKICAgICAgcmFuZ2VSZWFkZXIucmVhZCgpLnRoZW4ocmVhZENodW5rLCByZWplY3QpOwogICAgfSkudGhlbihkYXRhID0+IHsKICAgICAgaWYgKHRoaXMuYWJvcnRlZCkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICB0aGlzLm9uUmVjZWl2ZURhdGEoewogICAgICAgIGNodW5rOiBkYXRhLAogICAgICAgIGJlZ2luCiAgICAgIH0pOwogICAgfSk7CiAgfQogIHJlcXVlc3RBbGxDaHVua3MoKSB7CiAgICBsZXQgbm9GZXRjaCA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogZmFsc2U7CiAgICBpZiAoIW5vRmV0Y2gpIHsKICAgICAgY29uc3QgbWlzc2luZ0NodW5rcyA9IHRoaXMuc3RyZWFtLmdldE1pc3NpbmdDaHVua3MoKTsKICAgICAgdGhpcy5fcmVxdWVzdENodW5rcyhtaXNzaW5nQ2h1bmtzKTsKICAgIH0KICAgIHJldHVybiB0aGlzLl9sb2FkZWRTdHJlYW1DYXBhYmlsaXR5LnByb21pc2U7CiAgfQogIF9yZXF1ZXN0Q2h1bmtzKGNodW5rcykgewogICAgY29uc3QgcmVxdWVzdElkID0gdGhpcy5jdXJyUmVxdWVzdElkKys7CiAgICBjb25zdCBjaHVua3NOZWVkZWQgPSBuZXcgU2V0KCk7CiAgICB0aGlzLl9jaHVua3NOZWVkZWRCeVJlcXVlc3Quc2V0KHJlcXVlc3RJZCwgY2h1bmtzTmVlZGVkKTsKICAgIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzKSB7CiAgICAgIGlmICghdGhpcy5zdHJlYW0uaGFzQ2h1bmsoY2h1bmspKSB7CiAgICAgICAgY2h1bmtzTmVlZGVkLmFkZChjaHVuayk7CiAgICAgIH0KICAgIH0KICAgIGlmIChjaHVua3NOZWVkZWQuc2l6ZSA9PT0gMCkgewogICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7CiAgICB9CiAgICBjb25zdCBjYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogICAgdGhpcy5fcHJvbWlzZXNCeVJlcXVlc3Quc2V0KHJlcXVlc3RJZCwgY2FwYWJpbGl0eSk7CiAgICBjb25zdCBjaHVua3NUb1JlcXVlc3QgPSBbXTsKICAgIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzTmVlZGVkKSB7CiAgICAgIGxldCByZXF1ZXN0SWRzID0gdGhpcy5fcmVxdWVzdHNCeUNodW5rLmdldChjaHVuayk7CiAgICAgIGlmICghcmVxdWVzdElkcykgewogICAgICAgIHJlcXVlc3RJZHMgPSBbXTsKICAgICAgICB0aGlzLl9yZXF1ZXN0c0J5Q2h1bmsuc2V0KGNodW5rLCByZXF1ZXN0SWRzKTsKICAgICAgICBjaHVua3NUb1JlcXVlc3QucHVzaChjaHVuayk7CiAgICAgIH0KICAgICAgcmVxdWVzdElkcy5wdXNoKHJlcXVlc3RJZCk7CiAgICB9CiAgICBpZiAoY2h1bmtzVG9SZXF1ZXN0Lmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgZ3JvdXBlZENodW5rc1RvUmVxdWVzdCA9IHRoaXMuZ3JvdXBDaHVua3MoY2h1bmtzVG9SZXF1ZXN0KTsKICAgICAgZm9yIChjb25zdCBncm91cGVkQ2h1bmsgb2YgZ3JvdXBlZENodW5rc1RvUmVxdWVzdCkgewogICAgICAgIGNvbnN0IGJlZ2luID0gZ3JvdXBlZENodW5rLmJlZ2luQ2h1bmsgKiB0aGlzLmNodW5rU2l6ZTsKICAgICAgICBjb25zdCBlbmQgPSBNYXRoLm1pbihncm91cGVkQ2h1bmsuZW5kQ2h1bmsgKiB0aGlzLmNodW5rU2l6ZSwgdGhpcy5sZW5ndGgpOwogICAgICAgIHRoaXMuc2VuZFJlcXVlc3QoYmVnaW4sIGVuZCkuY2F0Y2goY2FwYWJpbGl0eS5yZWplY3QpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlLmNhdGNoKHJlYXNvbiA9PiB7CiAgICAgIGlmICh0aGlzLmFib3J0ZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhyb3cgcmVhc29uOwogICAgfSk7CiAgfQogIGdldFN0cmVhbSgpIHsKICAgIHJldHVybiB0aGlzLnN0cmVhbTsKICB9CiAgcmVxdWVzdFJhbmdlKGJlZ2luLCBlbmQpIHsKICAgIGVuZCA9IE1hdGgubWluKGVuZCwgdGhpcy5sZW5ndGgpOwogICAgY29uc3QgYmVnaW5DaHVuayA9IHRoaXMuZ2V0QmVnaW5DaHVuayhiZWdpbik7CiAgICBjb25zdCBlbmRDaHVuayA9IHRoaXMuZ2V0RW5kQ2h1bmsoZW5kKTsKICAgIGNvbnN0IGNodW5rcyA9IFtdOwogICAgZm9yIChsZXQgY2h1bmsgPSBiZWdpbkNodW5rOyBjaHVuayA8IGVuZENodW5rOyArK2NodW5rKSB7CiAgICAgIGNodW5rcy5wdXNoKGNodW5rKTsKICAgIH0KICAgIHJldHVybiB0aGlzLl9yZXF1ZXN0Q2h1bmtzKGNodW5rcyk7CiAgfQogIHJlcXVlc3RSYW5nZXMoKSB7CiAgICBsZXQgcmFuZ2VzID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBbXTsKICAgIGNvbnN0IGNodW5rc1RvUmVxdWVzdCA9IFtdOwogICAgZm9yIChjb25zdCByYW5nZSBvZiByYW5nZXMpIHsKICAgICAgY29uc3QgYmVnaW5DaHVuayA9IHRoaXMuZ2V0QmVnaW5DaHVuayhyYW5nZS5iZWdpbik7CiAgICAgIGNvbnN0IGVuZENodW5rID0gdGhpcy5nZXRFbmRDaHVuayhyYW5nZS5lbmQpOwogICAgICBmb3IgKGxldCBjaHVuayA9IGJlZ2luQ2h1bms7IGNodW5rIDwgZW5kQ2h1bms7ICsrY2h1bmspIHsKICAgICAgICBpZiAoIWNodW5rc1RvUmVxdWVzdC5pbmNsdWRlcyhjaHVuaykpIHsKICAgICAgICAgIGNodW5rc1RvUmVxdWVzdC5wdXNoKGNodW5rKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGNodW5rc1RvUmVxdWVzdC5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7CiAgICAgIHJldHVybiBhIC0gYjsKICAgIH0pOwogICAgcmV0dXJuIHRoaXMuX3JlcXVlc3RDaHVua3MoY2h1bmtzVG9SZXF1ZXN0KTsKICB9CiAgZ3JvdXBDaHVua3MoY2h1bmtzKSB7CiAgICBjb25zdCBncm91cGVkQ2h1bmtzID0gW107CiAgICBsZXQgYmVnaW5DaHVuayA9IC0xOwogICAgbGV0IHByZXZDaHVuayA9IC0xOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gY2h1bmtzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgICAgY29uc3QgY2h1bmsgPSBjaHVua3NbaV07CiAgICAgIGlmIChiZWdpbkNodW5rIDwgMCkgewogICAgICAgIGJlZ2luQ2h1bmsgPSBjaHVuazsKICAgICAgfQogICAgICBpZiAocHJldkNodW5rID49IDAgJiYgcHJldkNodW5rICsgMSAhPT0gY2h1bmspIHsKICAgICAgICBncm91cGVkQ2h1bmtzLnB1c2goewogICAgICAgICAgYmVnaW5DaHVuaywKICAgICAgICAgIGVuZENodW5rOiBwcmV2Q2h1bmsgKyAxCiAgICAgICAgfSk7CiAgICAgICAgYmVnaW5DaHVuayA9IGNodW5rOwogICAgICB9CiAgICAgIGlmIChpICsgMSA9PT0gY2h1bmtzLmxlbmd0aCkgewogICAgICAgIGdyb3VwZWRDaHVua3MucHVzaCh7CiAgICAgICAgICBiZWdpbkNodW5rLAogICAgICAgICAgZW5kQ2h1bms6IGNodW5rICsgMQogICAgICAgIH0pOwogICAgICB9CiAgICAgIHByZXZDaHVuayA9IGNodW5rOwogICAgfQogICAgcmV0dXJuIGdyb3VwZWRDaHVua3M7CiAgfQogIG9uUHJvZ3Jlc3MoYXJncykgewogICAgdGhpcy5tc2dIYW5kbGVyLnNlbmQoIkRvY1Byb2dyZXNzIiwgewogICAgICBsb2FkZWQ6IHRoaXMuc3RyZWFtLm51bUNodW5rc0xvYWRlZCAqIHRoaXMuY2h1bmtTaXplICsgYXJncy5sb2FkZWQsCiAgICAgIHRvdGFsOiB0aGlzLmxlbmd0aAogICAgfSk7CiAgfQogIG9uUmVjZWl2ZURhdGEoYXJncykgewogICAgY29uc3QgY2h1bmsgPSBhcmdzLmNodW5rOwogICAgY29uc3QgaXNQcm9ncmVzc2l2ZSA9IGFyZ3MuYmVnaW4gPT09IHVuZGVmaW5lZDsKICAgIGNvbnN0IGJlZ2luID0gaXNQcm9ncmVzc2l2ZSA/IHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoIDogYXJncy5iZWdpbjsKICAgIGNvbnN0IGVuZCA9IGJlZ2luICsgY2h1bmsuYnl0ZUxlbmd0aDsKICAgIGNvbnN0IGJlZ2luQ2h1bmsgPSBNYXRoLmZsb29yKGJlZ2luIC8gdGhpcy5jaHVua1NpemUpOwogICAgY29uc3QgZW5kQ2h1bmsgPSBlbmQgPCB0aGlzLmxlbmd0aCA/IE1hdGguZmxvb3IoZW5kIC8gdGhpcy5jaHVua1NpemUpIDogTWF0aC5jZWlsKGVuZCAvIHRoaXMuY2h1bmtTaXplKTsKICAgIGlmIChpc1Byb2dyZXNzaXZlKSB7CiAgICAgIHRoaXMuc3RyZWFtLm9uUmVjZWl2ZVByb2dyZXNzaXZlRGF0YShjaHVuayk7CiAgICAgIHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoID0gZW5kOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5zdHJlYW0ub25SZWNlaXZlRGF0YShiZWdpbiwgY2h1bmspOwogICAgfQogICAgaWYgKHRoaXMuc3RyZWFtLmlzRGF0YUxvYWRlZCkgewogICAgICB0aGlzLl9sb2FkZWRTdHJlYW1DYXBhYmlsaXR5LnJlc29sdmUodGhpcy5zdHJlYW0pOwogICAgfQogICAgY29uc3QgbG9hZGVkUmVxdWVzdHMgPSBbXTsKICAgIGZvciAobGV0IGN1ckNodW5rID0gYmVnaW5DaHVuazsgY3VyQ2h1bmsgPCBlbmRDaHVuazsgKytjdXJDaHVuaykgewogICAgICBjb25zdCByZXF1ZXN0SWRzID0gdGhpcy5fcmVxdWVzdHNCeUNodW5rLmdldChjdXJDaHVuayk7CiAgICAgIGlmICghcmVxdWVzdElkcykgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHRoaXMuX3JlcXVlc3RzQnlDaHVuay5kZWxldGUoY3VyQ2h1bmspOwogICAgICBmb3IgKGNvbnN0IHJlcXVlc3RJZCBvZiByZXF1ZXN0SWRzKSB7CiAgICAgICAgY29uc3QgY2h1bmtzTmVlZGVkID0gdGhpcy5fY2h1bmtzTmVlZGVkQnlSZXF1ZXN0LmdldChyZXF1ZXN0SWQpOwogICAgICAgIGlmIChjaHVua3NOZWVkZWQuaGFzKGN1ckNodW5rKSkgewogICAgICAgICAgY2h1bmtzTmVlZGVkLmRlbGV0ZShjdXJDaHVuayk7CiAgICAgICAgfQogICAgICAgIGlmIChjaHVua3NOZWVkZWQuc2l6ZSA+IDApIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBsb2FkZWRSZXF1ZXN0cy5wdXNoKHJlcXVlc3RJZCk7CiAgICAgIH0KICAgIH0KICAgIGlmICghdGhpcy5kaXNhYmxlQXV0b0ZldGNoICYmIHRoaXMuX3JlcXVlc3RzQnlDaHVuay5zaXplID09PSAwKSB7CiAgICAgIGxldCBuZXh0RW1wdHlDaHVuazsKICAgICAgaWYgKHRoaXMuc3RyZWFtLm51bUNodW5rc0xvYWRlZCA9PT0gMSkgewogICAgICAgIGNvbnN0IGxhc3RDaHVuayA9IHRoaXMuc3RyZWFtLm51bUNodW5rcyAtIDE7CiAgICAgICAgaWYgKCF0aGlzLnN0cmVhbS5oYXNDaHVuayhsYXN0Q2h1bmspKSB7CiAgICAgICAgICBuZXh0RW1wdHlDaHVuayA9IGxhc3RDaHVuazsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmV4dEVtcHR5Q2h1bmsgPSB0aGlzLnN0cmVhbS5uZXh0RW1wdHlDaHVuayhlbmRDaHVuayk7CiAgICAgIH0KICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIobmV4dEVtcHR5Q2h1bmspKSB7CiAgICAgICAgdGhpcy5fcmVxdWVzdENodW5rcyhbbmV4dEVtcHR5Q2h1bmtdKTsKICAgICAgfQogICAgfQogICAgZm9yIChjb25zdCByZXF1ZXN0SWQgb2YgbG9hZGVkUmVxdWVzdHMpIHsKICAgICAgY29uc3QgY2FwYWJpbGl0eSA9IHRoaXMuX3Byb21pc2VzQnlSZXF1ZXN0LmdldChyZXF1ZXN0SWQpOwogICAgICB0aGlzLl9wcm9taXNlc0J5UmVxdWVzdC5kZWxldGUocmVxdWVzdElkKTsKICAgICAgY2FwYWJpbGl0eS5yZXNvbHZlKCk7CiAgICB9CiAgICB0aGlzLm1zZ0hhbmRsZXIuc2VuZCgiRG9jUHJvZ3Jlc3MiLCB7CiAgICAgIGxvYWRlZDogdGhpcy5zdHJlYW0ubnVtQ2h1bmtzTG9hZGVkICogdGhpcy5jaHVua1NpemUsCiAgICAgIHRvdGFsOiB0aGlzLmxlbmd0aAogICAgfSk7CiAgfQogIG9uRXJyb3IoZXJyKSB7CiAgICB0aGlzLl9sb2FkZWRTdHJlYW1DYXBhYmlsaXR5LnJlamVjdChlcnIpOwogIH0KICBnZXRCZWdpbkNodW5rKGJlZ2luKSB7CiAgICByZXR1cm4gTWF0aC5mbG9vcihiZWdpbiAvIHRoaXMuY2h1bmtTaXplKTsKICB9CiAgZ2V0RW5kQ2h1bmsoZW5kKSB7CiAgICByZXR1cm4gTWF0aC5mbG9vcigoZW5kIC0gMSkgLyB0aGlzLmNodW5rU2l6ZSkgKyAxOwogIH0KICBhYm9ydChyZWFzb24pIHsKICAgIHRoaXMuYWJvcnRlZCA9IHRydWU7CiAgICBpZiAodGhpcy5wZGZOZXR3b3JrU3RyZWFtKSB7CiAgICAgIHRoaXMucGRmTmV0d29ya1N0cmVhbS5jYW5jZWxBbGxSZXF1ZXN0cyhyZWFzb24pOwogICAgfQogICAgZm9yIChjb25zdCBjYXBhYmlsaXR5IG9mIHRoaXMuX3Byb21pc2VzQnlSZXF1ZXN0LnZhbHVlcygpKSB7CiAgICAgIGNhcGFiaWxpdHkucmVqZWN0KHJlYXNvbik7CiAgICB9CiAgfQp9CmV4cG9ydHMuQ2h1bmtlZFN0cmVhbU1hbmFnZXIgPSBDaHVua2VkU3RyZWFtTWFuYWdlcjsKCi8qKiovIH0pLAovKiAxNDQgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlN0cmluZ1N0cmVhbSA9IGV4cG9ydHMuU3RyZWFtID0gZXhwb3J0cy5OdWxsU3RyZWFtID0gdm9pZCAwOwp2YXIgX2Jhc2Vfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDEpOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpjbGFzcyBTdHJlYW0gZXh0ZW5kcyBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSB7CiAgY29uc3RydWN0b3IoYXJyYXlCdWZmZXIsIHN0YXJ0LCBsZW5ndGgsIGRpY3QpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLmJ5dGVzID0gYXJyYXlCdWZmZXIgaW5zdGFuY2VvZiBVaW50OEFycmF5ID8gYXJyYXlCdWZmZXIgOiBuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcik7CiAgICB0aGlzLnN0YXJ0ID0gc3RhcnQgfHwgMDsKICAgIHRoaXMucG9zID0gdGhpcy5zdGFydDsKICAgIHRoaXMuZW5kID0gc3RhcnQgKyBsZW5ndGggfHwgdGhpcy5ieXRlcy5sZW5ndGg7CiAgICB0aGlzLmRpY3QgPSBkaWN0OwogIH0KICBnZXQgbGVuZ3RoKCkgewogICAgcmV0dXJuIHRoaXMuZW5kIC0gdGhpcy5zdGFydDsKICB9CiAgZ2V0IGlzRW1wdHkoKSB7CiAgICByZXR1cm4gdGhpcy5sZW5ndGggPT09IDA7CiAgfQogIGdldEJ5dGUoKSB7CiAgICBpZiAodGhpcy5wb3MgPj0gdGhpcy5lbmQpIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgcmV0dXJuIHRoaXMuYnl0ZXNbdGhpcy5wb3MrK107CiAgfQogIGdldEJ5dGVzKGxlbmd0aCkgewogICAgY29uc3QgYnl0ZXMgPSB0aGlzLmJ5dGVzOwogICAgY29uc3QgcG9zID0gdGhpcy5wb3M7CiAgICBjb25zdCBzdHJFbmQgPSB0aGlzLmVuZDsKICAgIGlmICghbGVuZ3RoKSB7CiAgICAgIHJldHVybiBieXRlcy5zdWJhcnJheShwb3MsIHN0ckVuZCk7CiAgICB9CiAgICBsZXQgZW5kID0gcG9zICsgbGVuZ3RoOwogICAgaWYgKGVuZCA+IHN0ckVuZCkgewogICAgICBlbmQgPSBzdHJFbmQ7CiAgICB9CiAgICB0aGlzLnBvcyA9IGVuZDsKICAgIHJldHVybiBieXRlcy5zdWJhcnJheShwb3MsIGVuZCk7CiAgfQogIGdldEJ5dGVSYW5nZShiZWdpbiwgZW5kKSB7CiAgICBpZiAoYmVnaW4gPCAwKSB7CiAgICAgIGJlZ2luID0gMDsKICAgIH0KICAgIGlmIChlbmQgPiB0aGlzLmVuZCkgewogICAgICBlbmQgPSB0aGlzLmVuZDsKICAgIH0KICAgIHJldHVybiB0aGlzLmJ5dGVzLnN1YmFycmF5KGJlZ2luLCBlbmQpOwogIH0KICByZXNldCgpIHsKICAgIHRoaXMucG9zID0gdGhpcy5zdGFydDsKICB9CiAgbW92ZVN0YXJ0KCkgewogICAgdGhpcy5zdGFydCA9IHRoaXMucG9zOwogIH0KICBtYWtlU3ViU3RyZWFtKHN0YXJ0LCBsZW5ndGgpIHsKICAgIGxldCBkaWN0ID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBudWxsOwogICAgcmV0dXJuIG5ldyBTdHJlYW0odGhpcy5ieXRlcy5idWZmZXIsIHN0YXJ0LCBsZW5ndGgsIGRpY3QpOwogIH0KfQpleHBvcnRzLlN0cmVhbSA9IFN0cmVhbTsKY2xhc3MgU3RyaW5nU3RyZWFtIGV4dGVuZHMgU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHIpIHsKICAgIHN1cGVyKCgwLCBfdXRpbC5zdHJpbmdUb0J5dGVzKShzdHIpKTsKICB9Cn0KZXhwb3J0cy5TdHJpbmdTdHJlYW0gPSBTdHJpbmdTdHJlYW07CmNsYXNzIE51bGxTdHJlYW0gZXh0ZW5kcyBTdHJlYW0gewogIGNvbnN0cnVjdG9yKCkgewogICAgc3VwZXIobmV3IFVpbnQ4QXJyYXkoMCkpOwogIH0KfQpleHBvcnRzLk51bGxTdHJlYW0gPSBOdWxsU3RyZWFtOwoKLyoqKi8gfSksCi8qIDE0NSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuUGFnZSA9IGV4cG9ydHMuUERGRG9jdW1lbnQgPSB2b2lkIDA7CnZhciBfYW5ub3RhdGlvbiA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQ2KTsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX3ByaW1pdGl2ZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MCk7CnZhciBfeGZhX2ZvbnRzID0gX193X3BkZmpzX3JlcXVpcmVfXygxODYpOwp2YXIgX2Jhc2Vfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDEpOwp2YXIgX2NyeXB0byA9IF9fd19wZGZqc19yZXF1aXJlX18oMjAyKTsKdmFyIF9jYXRhbG9nID0gX193X3BkZmpzX3JlcXVpcmVfXygyMDQpOwp2YXIgX2NsZWFudXBfaGVscGVyID0gX193X3BkZmpzX3JlcXVpcmVfXygyMDYpOwp2YXIgX2RhdGFzZXRfcmVhZGVyID0gX193X3BkZmpzX3JlcXVpcmVfXygyMzUpOwp2YXIgX3BhcnNlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTUxKTsKdmFyIF9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0NCk7CnZhciBfb2JqZWN0X2xvYWRlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMjEwKTsKdmFyIF9vcGVyYXRvcl9saXN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxOTgpOwp2YXIgX2V2YWx1YXRvciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQ5KTsKdmFyIF9kZWNvZGVfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTMpOwp2YXIgX3N0cnVjdF90cmVlID0gX193X3BkZmpzX3JlcXVpcmVfXygyMDkpOwp2YXIgX3dyaXRlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMjAwKTsKdmFyIF9mYWN0b3J5ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTEpOwp2YXIgX3hyZWYgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIzNik7CmNvbnN0IERFRkFVTFRfVVNFUl9VTklUID0gMS4wOwpjb25zdCBMRVRURVJfU0laRV9NRURJQUJPWCA9IFswLCAwLCA2MTIsIDc5Ml07CmNsYXNzIFBhZ2UgewogIGNvbnN0cnVjdG9yKF9yZWYpIHsKICAgIGxldCB7CiAgICAgIHBkZk1hbmFnZXIsCiAgICAgIHhyZWYsCiAgICAgIHBhZ2VJbmRleCwKICAgICAgcGFnZURpY3QsCiAgICAgIHJlZiwKICAgICAgZ2xvYmFsSWRGYWN0b3J5LAogICAgICBmb250Q2FjaGUsCiAgICAgIGJ1aWx0SW5DTWFwQ2FjaGUsCiAgICAgIHN0YW5kYXJkRm9udERhdGFDYWNoZSwKICAgICAgZ2xvYmFsSW1hZ2VDYWNoZSwKICAgICAgbm9uQmxlbmRNb2Rlc1NldCwKICAgICAgeGZhRmFjdG9yeQogICAgfSA9IF9yZWY7CiAgICB0aGlzLnBkZk1hbmFnZXIgPSBwZGZNYW5hZ2VyOwogICAgdGhpcy5wYWdlSW5kZXggPSBwYWdlSW5kZXg7CiAgICB0aGlzLnBhZ2VEaWN0ID0gcGFnZURpY3Q7CiAgICB0aGlzLnhyZWYgPSB4cmVmOwogICAgdGhpcy5yZWYgPSByZWY7CiAgICB0aGlzLmZvbnRDYWNoZSA9IGZvbnRDYWNoZTsKICAgIHRoaXMuYnVpbHRJbkNNYXBDYWNoZSA9IGJ1aWx0SW5DTWFwQ2FjaGU7CiAgICB0aGlzLnN0YW5kYXJkRm9udERhdGFDYWNoZSA9IHN0YW5kYXJkRm9udERhdGFDYWNoZTsKICAgIHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZSA9IGdsb2JhbEltYWdlQ2FjaGU7CiAgICB0aGlzLm5vbkJsZW5kTW9kZXNTZXQgPSBub25CbGVuZE1vZGVzU2V0OwogICAgdGhpcy5ldmFsdWF0b3JPcHRpb25zID0gcGRmTWFuYWdlci5ldmFsdWF0b3JPcHRpb25zOwogICAgdGhpcy5yZXNvdXJjZXNQcm9taXNlID0gbnVsbDsKICAgIHRoaXMueGZhRmFjdG9yeSA9IHhmYUZhY3Rvcnk7CiAgICBjb25zdCBpZENvdW50ZXJzID0gewogICAgICBvYmo6IDAKICAgIH07CiAgICB0aGlzLl9sb2NhbElkRmFjdG9yeSA9IGNsYXNzIGV4dGVuZHMgZ2xvYmFsSWRGYWN0b3J5IHsKICAgICAgc3RhdGljIGNyZWF0ZU9iaklkKCkgewogICAgICAgIHJldHVybiBgcCR7cGFnZUluZGV4fV8keysraWRDb3VudGVycy5vYmp9YDsKICAgICAgfQogICAgICBzdGF0aWMgZ2V0UGFnZU9iaklkKCkgewogICAgICAgIHJldHVybiBgcGFnZSR7cmVmLnRvU3RyaW5nKCl9YDsKICAgICAgfQogICAgfTsKICB9CiAgX2dldEluaGVyaXRhYmxlUHJvcGVydHkoa2V5KSB7CiAgICBsZXQgZ2V0QXJyYXkgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IGZhbHNlOwogICAgY29uc3QgdmFsdWUgPSAoMCwgX2NvcmVfdXRpbHMuZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSkoewogICAgICBkaWN0OiB0aGlzLnBhZ2VEaWN0LAogICAgICBrZXksCiAgICAgIGdldEFycmF5LAogICAgICBzdG9wV2hlbkZvdW5kOiBmYWxzZQogICAgfSk7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkodmFsdWUpKSB7CiAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0KICAgIGlmICh2YWx1ZS5sZW5ndGggPT09IDEgfHwgISh2YWx1ZVswXSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybiB2YWx1ZVswXTsKICAgIH0KICAgIHJldHVybiBfcHJpbWl0aXZlcy5EaWN0Lm1lcmdlKHsKICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICBkaWN0QXJyYXk6IHZhbHVlCiAgICB9KTsKICB9CiAgZ2V0IGNvbnRlbnQoKSB7CiAgICByZXR1cm4gdGhpcy5wYWdlRGljdC5nZXRBcnJheSgiQ29udGVudHMiKTsKICB9CiAgZ2V0IHJlc291cmNlcygpIHsKICAgIGNvbnN0IHJlc291cmNlcyA9IHRoaXMuX2dldEluaGVyaXRhYmxlUHJvcGVydHkoIlJlc291cmNlcyIpOwogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJyZXNvdXJjZXMiLCByZXNvdXJjZXMgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0ID8gcmVzb3VyY2VzIDogX3ByaW1pdGl2ZXMuRGljdC5lbXB0eSk7CiAgfQogIF9nZXRCb3VuZGluZ0JveChuYW1lKSB7CiAgICBpZiAodGhpcy54ZmFEYXRhKSB7CiAgICAgIHJldHVybiB0aGlzLnhmYURhdGEuYmJveDsKICAgIH0KICAgIGxldCBib3ggPSB0aGlzLl9nZXRJbmhlcml0YWJsZVByb3BlcnR5KG5hbWUsIHRydWUpOwogICAgaWYgKEFycmF5LmlzQXJyYXkoYm94KSAmJiBib3gubGVuZ3RoID09PSA0KSB7CiAgICAgIGJveCA9IF91dGlsLlV0aWwubm9ybWFsaXplUmVjdChib3gpOwogICAgICBpZiAoYm94WzJdIC0gYm94WzBdID4gMCAmJiBib3hbM10gLSBib3hbMV0gPiAwKSB7CiAgICAgICAgcmV0dXJuIGJveDsKICAgICAgfQogICAgICAoMCwgX3V0aWwud2FybikoYEVtcHR5LCBvciBpbnZhbGlkLCAvJHtuYW1lfSBlbnRyeS5gKTsKICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICBnZXQgbWVkaWFCb3goKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIm1lZGlhQm94IiwgdGhpcy5fZ2V0Qm91bmRpbmdCb3goIk1lZGlhQm94IikgfHwgTEVUVEVSX1NJWkVfTUVESUFCT1gpOwogIH0KICBnZXQgY3JvcEJveCgpIHsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiY3JvcEJveCIsIHRoaXMuX2dldEJvdW5kaW5nQm94KCJDcm9wQm94IikgfHwgdGhpcy5tZWRpYUJveCk7CiAgfQogIGdldCB1c2VyVW5pdCgpIHsKICAgIGxldCBvYmogPSB0aGlzLnBhZ2VEaWN0LmdldCgiVXNlclVuaXQiKTsKICAgIGlmICh0eXBlb2Ygb2JqICE9PSAibnVtYmVyIiB8fCBvYmogPD0gMCkgewogICAgICBvYmogPSBERUZBVUxUX1VTRVJfVU5JVDsKICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAidXNlclVuaXQiLCBvYmopOwogIH0KICBnZXQgdmlldygpIHsKICAgIGNvbnN0IHsKICAgICAgY3JvcEJveCwKICAgICAgbWVkaWFCb3gKICAgIH0gPSB0aGlzOwogICAgaWYgKGNyb3BCb3ggIT09IG1lZGlhQm94ICYmICEoMCwgX3V0aWwuaXNBcnJheUVxdWFsKShjcm9wQm94LCBtZWRpYUJveCkpIHsKICAgICAgY29uc3QgYm94ID0gX3V0aWwuVXRpbC5pbnRlcnNlY3QoY3JvcEJveCwgbWVkaWFCb3gpOwogICAgICBpZiAoYm94ICYmIGJveFsyXSAtIGJveFswXSA+IDAgJiYgYm94WzNdIC0gYm94WzFdID4gMCkgewogICAgICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAidmlldyIsIGJveCk7CiAgICAgIH0KICAgICAgKDAsIF91dGlsLndhcm4pKCJFbXB0eSAvQ3JvcEJveCBhbmQgL01lZGlhQm94IGludGVyc2VjdGlvbi4iKTsKICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAidmlldyIsIG1lZGlhQm94KTsKICB9CiAgZ2V0IHJvdGF0ZSgpIHsKICAgIGxldCByb3RhdGUgPSB0aGlzLl9nZXRJbmhlcml0YWJsZVByb3BlcnR5KCJSb3RhdGUiKSB8fCAwOwogICAgaWYgKHJvdGF0ZSAlIDkwICE9PSAwKSB7CiAgICAgIHJvdGF0ZSA9IDA7CiAgICB9IGVsc2UgaWYgKHJvdGF0ZSA+PSAzNjApIHsKICAgICAgcm90YXRlICU9IDM2MDsKICAgIH0gZWxzZSBpZiAocm90YXRlIDwgMCkgewogICAgICByb3RhdGUgPSAocm90YXRlICUgMzYwICsgMzYwKSAlIDM2MDsKICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAicm90YXRlIiwgcm90YXRlKTsKICB9CiAgX29uU3ViU3RyZWFtRXJyb3IocmVhc29uLCBvYmpJZCkgewogICAgaWYgKHRoaXMuZXZhbHVhdG9yT3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKGBnZXRDb250ZW50U3RyZWFtIC0gaWdub3Jpbmcgc3ViLXN0cmVhbSAoJHtvYmpJZH0pOiAiJHtyZWFzb259Ii5gKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhyb3cgcmVhc29uOwogIH0KICBnZXRDb250ZW50U3RyZWFtKCkgewogICAgcmV0dXJuIHRoaXMucGRmTWFuYWdlci5lbnN1cmUodGhpcywgImNvbnRlbnQiKS50aGVuKGNvbnRlbnQgPT4gewogICAgICBpZiAoY29udGVudCBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSB7CiAgICAgICAgcmV0dXJuIGNvbnRlbnQ7CiAgICAgIH0KICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29udGVudCkpIHsKICAgICAgICByZXR1cm4gbmV3IF9kZWNvZGVfc3RyZWFtLlN0cmVhbXNTZXF1ZW5jZVN0cmVhbShjb250ZW50LCB0aGlzLl9vblN1YlN0cmVhbUVycm9yLmJpbmQodGhpcykpOwogICAgICB9CiAgICAgIHJldHVybiBuZXcgX3N0cmVhbS5OdWxsU3RyZWFtKCk7CiAgICB9KTsKICB9CiAgZ2V0IHhmYURhdGEoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInhmYURhdGEiLCB0aGlzLnhmYUZhY3RvcnkgPyB7CiAgICAgIGJib3g6IHRoaXMueGZhRmFjdG9yeS5nZXRCb3VuZGluZ0JveCh0aGlzLnBhZ2VJbmRleCkKICAgIH0gOiBudWxsKTsKICB9CiAgYXN5bmMgc2F2ZU5ld0Fubm90YXRpb25zKGhhbmRsZXIsIHRhc2ssIGFubm90YXRpb25zKSB7CiAgICBpZiAodGhpcy54ZmFGYWN0b3J5KSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiWEZBOiBDYW5ub3Qgc2F2ZSBuZXcgYW5ub3RhdGlvbnMuIik7CiAgICB9CiAgICBjb25zdCBwYXJ0aWFsRXZhbHVhdG9yID0gbmV3IF9ldmFsdWF0b3IuUGFydGlhbEV2YWx1YXRvcih7CiAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgaGFuZGxlciwKICAgICAgcGFnZUluZGV4OiB0aGlzLnBhZ2VJbmRleCwKICAgICAgaWRGYWN0b3J5OiB0aGlzLl9sb2NhbElkRmFjdG9yeSwKICAgICAgZm9udENhY2hlOiB0aGlzLmZvbnRDYWNoZSwKICAgICAgYnVpbHRJbkNNYXBDYWNoZTogdGhpcy5idWlsdEluQ01hcENhY2hlLAogICAgICBzdGFuZGFyZEZvbnREYXRhQ2FjaGU6IHRoaXMuc3RhbmRhcmRGb250RGF0YUNhY2hlLAogICAgICBnbG9iYWxJbWFnZUNhY2hlOiB0aGlzLmdsb2JhbEltYWdlQ2FjaGUsCiAgICAgIG9wdGlvbnM6IHRoaXMuZXZhbHVhdG9yT3B0aW9ucwogICAgfSk7CiAgICBjb25zdCBwYWdlRGljdCA9IHRoaXMucGFnZURpY3Q7CiAgICBjb25zdCBhbm5vdGF0aW9uc0FycmF5ID0gdGhpcy5hbm5vdGF0aW9ucy5zbGljZSgpOwogICAgY29uc3QgbmV3RGF0YSA9IGF3YWl0IF9hbm5vdGF0aW9uLkFubm90YXRpb25GYWN0b3J5LnNhdmVOZXdBbm5vdGF0aW9ucyhwYXJ0aWFsRXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9ucyk7CiAgICBmb3IgKGNvbnN0IHsKICAgICAgcmVmCiAgICB9IG9mIG5ld0RhdGEuYW5ub3RhdGlvbnMpIHsKICAgICAgYW5ub3RhdGlvbnNBcnJheS5wdXNoKHJlZik7CiAgICB9CiAgICBjb25zdCBzYXZlZERpY3QgPSBwYWdlRGljdC5nZXQoIkFubm90cyIpOwogICAgcGFnZURpY3Quc2V0KCJBbm5vdHMiLCBhbm5vdGF0aW9uc0FycmF5KTsKICAgIGNvbnN0IGJ1ZmZlciA9IFtdOwogICAgbGV0IHRyYW5zZm9ybSA9IG51bGw7CiAgICBpZiAodGhpcy54cmVmLmVuY3J5cHQpIHsKICAgICAgdHJhbnNmb3JtID0gdGhpcy54cmVmLmVuY3J5cHQuY3JlYXRlQ2lwaGVyVHJhbnNmb3JtKHRoaXMucmVmLm51bSwgdGhpcy5yZWYuZ2VuKTsKICAgIH0KICAgICgwLCBfd3JpdGVyLndyaXRlT2JqZWN0KSh0aGlzLnJlZiwgcGFnZURpY3QsIGJ1ZmZlciwgdHJhbnNmb3JtKTsKICAgIGlmIChzYXZlZERpY3QpIHsKICAgICAgcGFnZURpY3Quc2V0KCJBbm5vdHMiLCBzYXZlZERpY3QpOwogICAgfQogICAgY29uc3Qgb2JqZWN0cyA9IG5ld0RhdGEuZGVwZW5kZW5jaWVzOwogICAgb2JqZWN0cy5wdXNoKHsKICAgICAgcmVmOiB0aGlzLnJlZiwKICAgICAgZGF0YTogYnVmZmVyLmpvaW4oIiIpCiAgICB9LCAuLi5uZXdEYXRhLmFubm90YXRpb25zKTsKICAgIHJldHVybiBvYmplY3RzOwogIH0KICBzYXZlKGhhbmRsZXIsIHRhc2ssIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBjb25zdCBwYXJ0aWFsRXZhbHVhdG9yID0gbmV3IF9ldmFsdWF0b3IuUGFydGlhbEV2YWx1YXRvcih7CiAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgaGFuZGxlciwKICAgICAgcGFnZUluZGV4OiB0aGlzLnBhZ2VJbmRleCwKICAgICAgaWRGYWN0b3J5OiB0aGlzLl9sb2NhbElkRmFjdG9yeSwKICAgICAgZm9udENhY2hlOiB0aGlzLmZvbnRDYWNoZSwKICAgICAgYnVpbHRJbkNNYXBDYWNoZTogdGhpcy5idWlsdEluQ01hcENhY2hlLAogICAgICBzdGFuZGFyZEZvbnREYXRhQ2FjaGU6IHRoaXMuc3RhbmRhcmRGb250RGF0YUNhY2hlLAogICAgICBnbG9iYWxJbWFnZUNhY2hlOiB0aGlzLmdsb2JhbEltYWdlQ2FjaGUsCiAgICAgIG9wdGlvbnM6IHRoaXMuZXZhbHVhdG9yT3B0aW9ucwogICAgfSk7CiAgICByZXR1cm4gdGhpcy5fcGFyc2VkQW5ub3RhdGlvbnMudGhlbihmdW5jdGlvbiAoYW5ub3RhdGlvbnMpIHsKICAgICAgY29uc3QgbmV3UmVmc1Byb21pc2VzID0gW107CiAgICAgIGZvciAoY29uc3QgYW5ub3RhdGlvbiBvZiBhbm5vdGF0aW9ucykgewogICAgICAgIGlmICghYW5ub3RhdGlvbi5tdXN0QmVQcmludGVkKGFubm90YXRpb25TdG9yYWdlKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIG5ld1JlZnNQcm9taXNlcy5wdXNoKGFubm90YXRpb24uc2F2ZShwYXJ0aWFsRXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSkuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJzYXZlIC0gaWdub3JpbmcgYW5ub3RhdGlvbiBkYXRhIGR1cmluZyAiICsgYCIke3Rhc2submFtZX0iIHRhc2s6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfSkpOwogICAgICB9CiAgICAgIHJldHVybiBQcm9taXNlLmFsbChuZXdSZWZzUHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24gKG5ld1JlZnMpIHsKICAgICAgICByZXR1cm4gbmV3UmVmcy5maWx0ZXIobmV3UmVmID0+ICEhbmV3UmVmKTsKICAgICAgfSk7CiAgICB9KTsKICB9CiAgbG9hZFJlc291cmNlcyhrZXlzKSB7CiAgICBpZiAoIXRoaXMucmVzb3VyY2VzUHJvbWlzZSkgewogICAgICB0aGlzLnJlc291cmNlc1Byb21pc2UgPSB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlKHRoaXMsICJyZXNvdXJjZXMiKTsKICAgIH0KICAgIHJldHVybiB0aGlzLnJlc291cmNlc1Byb21pc2UudGhlbigoKSA9PiB7CiAgICAgIGNvbnN0IG9iamVjdExvYWRlciA9IG5ldyBfb2JqZWN0X2xvYWRlci5PYmplY3RMb2FkZXIodGhpcy5yZXNvdXJjZXMsIGtleXMsIHRoaXMueHJlZik7CiAgICAgIHJldHVybiBvYmplY3RMb2FkZXIubG9hZCgpOwogICAgfSk7CiAgfQogIGdldE9wZXJhdG9yTGlzdChfcmVmMikgewogICAgbGV0IHsKICAgICAgaGFuZGxlciwKICAgICAgc2luaywKICAgICAgdGFzaywKICAgICAgaW50ZW50LAogICAgICBjYWNoZUtleSwKICAgICAgYW5ub3RhdGlvblN0b3JhZ2UgPSBudWxsCiAgICB9ID0gX3JlZjI7CiAgICBjb25zdCBjb250ZW50U3RyZWFtUHJvbWlzZSA9IHRoaXMuZ2V0Q29udGVudFN0cmVhbSgpOwogICAgY29uc3QgcmVzb3VyY2VzUHJvbWlzZSA9IHRoaXMubG9hZFJlc291cmNlcyhbIkNvbG9yU3BhY2UiLCAiRXh0R1N0YXRlIiwgIkZvbnQiLCAiUGF0dGVybiIsICJQcm9wZXJ0aWVzIiwgIlNoYWRpbmciLCAiWE9iamVjdCJdKTsKICAgIGNvbnN0IHBhcnRpYWxFdmFsdWF0b3IgPSBuZXcgX2V2YWx1YXRvci5QYXJ0aWFsRXZhbHVhdG9yKHsKICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICBoYW5kbGVyLAogICAgICBwYWdlSW5kZXg6IHRoaXMucGFnZUluZGV4LAogICAgICBpZEZhY3Rvcnk6IHRoaXMuX2xvY2FsSWRGYWN0b3J5LAogICAgICBmb250Q2FjaGU6IHRoaXMuZm9udENhY2hlLAogICAgICBidWlsdEluQ01hcENhY2hlOiB0aGlzLmJ1aWx0SW5DTWFwQ2FjaGUsCiAgICAgIHN0YW5kYXJkRm9udERhdGFDYWNoZTogdGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUsCiAgICAgIGdsb2JhbEltYWdlQ2FjaGU6IHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZSwKICAgICAgb3B0aW9uczogdGhpcy5ldmFsdWF0b3JPcHRpb25zCiAgICB9KTsKICAgIGNvbnN0IG5ld0Fubm90YXRpb25zQnlQYWdlID0gIXRoaXMueGZhRmFjdG9yeSA/ICgwLCBfY29yZV91dGlscy5nZXROZXdBbm5vdGF0aW9uc01hcCkoYW5ub3RhdGlvblN0b3JhZ2UpIDogbnVsbDsKICAgIGxldCBuZXdBbm5vdGF0aW9uc1Byb21pc2UgPSBQcm9taXNlLnJlc29sdmUobnVsbCk7CiAgICBpZiAobmV3QW5ub3RhdGlvbnNCeVBhZ2UpIHsKICAgICAgY29uc3QgbmV3QW5ub3RhdGlvbnMgPSBuZXdBbm5vdGF0aW9uc0J5UGFnZS5nZXQodGhpcy5wYWdlSW5kZXgpOwogICAgICBpZiAobmV3QW5ub3RhdGlvbnMpIHsKICAgICAgICBuZXdBbm5vdGF0aW9uc1Byb21pc2UgPSBfYW5ub3RhdGlvbi5Bbm5vdGF0aW9uRmFjdG9yeS5wcmludE5ld0Fubm90YXRpb25zKHBhcnRpYWxFdmFsdWF0b3IsIHRhc2ssIG5ld0Fubm90YXRpb25zKTsKICAgICAgfQogICAgfQogICAgY29uc3QgZGF0YVByb21pc2VzID0gUHJvbWlzZS5hbGwoW2NvbnRlbnRTdHJlYW1Qcm9taXNlLCByZXNvdXJjZXNQcm9taXNlXSk7CiAgICBjb25zdCBwYWdlTGlzdFByb21pc2UgPSBkYXRhUHJvbWlzZXMudGhlbihfcmVmMyA9PiB7CiAgICAgIGxldCBbY29udGVudFN0cmVhbV0gPSBfcmVmMzsKICAgICAgY29uc3Qgb3BMaXN0ID0gbmV3IF9vcGVyYXRvcl9saXN0Lk9wZXJhdG9yTGlzdChpbnRlbnQsIHNpbmspOwogICAgICBoYW5kbGVyLnNlbmQoIlN0YXJ0UmVuZGVyUGFnZSIsIHsKICAgICAgICB0cmFuc3BhcmVuY3k6IHBhcnRpYWxFdmFsdWF0b3IuaGFzQmxlbmRNb2Rlcyh0aGlzLnJlc291cmNlcywgdGhpcy5ub25CbGVuZE1vZGVzU2V0KSwKICAgICAgICBwYWdlSW5kZXg6IHRoaXMucGFnZUluZGV4LAogICAgICAgIGNhY2hlS2V5CiAgICAgIH0pOwogICAgICByZXR1cm4gcGFydGlhbEV2YWx1YXRvci5nZXRPcGVyYXRvckxpc3QoewogICAgICAgIHN0cmVhbTogY29udGVudFN0cmVhbSwKICAgICAgICB0YXNrLAogICAgICAgIHJlc291cmNlczogdGhpcy5yZXNvdXJjZXMsCiAgICAgICAgb3BlcmF0b3JMaXN0OiBvcExpc3QKICAgICAgfSkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIG9wTGlzdDsKICAgICAgfSk7CiAgICB9KTsKICAgIHJldHVybiBQcm9taXNlLmFsbChbcGFnZUxpc3RQcm9taXNlLCB0aGlzLl9wYXJzZWRBbm5vdGF0aW9ucywgbmV3QW5ub3RhdGlvbnNQcm9taXNlXSkudGhlbihmdW5jdGlvbiAoX3JlZjQpIHsKICAgICAgbGV0IFtwYWdlT3BMaXN0LCBhbm5vdGF0aW9ucywgbmV3QW5ub3RhdGlvbnNdID0gX3JlZjQ7CiAgICAgIGlmIChuZXdBbm5vdGF0aW9ucykgewogICAgICAgIGFubm90YXRpb25zID0gYW5ub3RhdGlvbnMuY29uY2F0KG5ld0Fubm90YXRpb25zKTsKICAgICAgfQogICAgICBpZiAoYW5ub3RhdGlvbnMubGVuZ3RoID09PSAwIHx8IGludGVudCAmIF91dGlsLlJlbmRlcmluZ0ludGVudEZsYWcuQU5OT1RBVElPTlNfRElTQUJMRSkgewogICAgICAgIHBhZ2VPcExpc3QuZmx1c2godHJ1ZSk7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGxlbmd0aDogcGFnZU9wTGlzdC50b3RhbExlbmd0aAogICAgICAgIH07CiAgICAgIH0KICAgICAgY29uc3QgcmVuZGVyRm9ybXMgPSAhIShpbnRlbnQgJiBfdXRpbC5SZW5kZXJpbmdJbnRlbnRGbGFnLkFOTk9UQVRJT05TX0ZPUk1TKSwKICAgICAgICBpbnRlbnRBbnkgPSAhIShpbnRlbnQgJiBfdXRpbC5SZW5kZXJpbmdJbnRlbnRGbGFnLkFOWSksCiAgICAgICAgaW50ZW50RGlzcGxheSA9ICEhKGludGVudCAmIF91dGlsLlJlbmRlcmluZ0ludGVudEZsYWcuRElTUExBWSksCiAgICAgICAgaW50ZW50UHJpbnQgPSAhIShpbnRlbnQgJiBfdXRpbC5SZW5kZXJpbmdJbnRlbnRGbGFnLlBSSU5UKTsKICAgICAgY29uc3Qgb3BMaXN0UHJvbWlzZXMgPSBbXTsKICAgICAgZm9yIChjb25zdCBhbm5vdGF0aW9uIG9mIGFubm90YXRpb25zKSB7CiAgICAgICAgaWYgKGludGVudEFueSB8fCBpbnRlbnREaXNwbGF5ICYmIGFubm90YXRpb24ubXVzdEJlVmlld2VkKGFubm90YXRpb25TdG9yYWdlKSB8fCBpbnRlbnRQcmludCAmJiBhbm5vdGF0aW9uLm11c3RCZVByaW50ZWQoYW5ub3RhdGlvblN0b3JhZ2UpKSB7CiAgICAgICAgICBvcExpc3RQcm9taXNlcy5wdXNoKGFubm90YXRpb24uZ2V0T3BlcmF0b3JMaXN0KHBhcnRpYWxFdmFsdWF0b3IsIHRhc2ssIGludGVudCwgcmVuZGVyRm9ybXMsIGFubm90YXRpb25TdG9yYWdlKS5jYXRjaChmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgYW5ub3RhdGlvbiBkYXRhIGR1cmluZyAiICsgYCIke3Rhc2submFtZX0iIHRhc2s6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgICByZXR1cm4gewogICAgICAgICAgICAgIG9wTGlzdDogbnVsbCwKICAgICAgICAgICAgICBzZXBhcmF0ZUZvcm06IGZhbHNlLAogICAgICAgICAgICAgIHNlcGFyYXRlQ2FudmFzOiBmYWxzZQogICAgICAgICAgICB9OwogICAgICAgICAgfSkpOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gUHJvbWlzZS5hbGwob3BMaXN0UHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24gKG9wTGlzdHMpIHsKICAgICAgICBsZXQgZm9ybSA9IGZhbHNlLAogICAgICAgICAgY2FudmFzID0gZmFsc2U7CiAgICAgICAgZm9yIChjb25zdCB7CiAgICAgICAgICBvcExpc3QsCiAgICAgICAgICBzZXBhcmF0ZUZvcm0sCiAgICAgICAgICBzZXBhcmF0ZUNhbnZhcwogICAgICAgIH0gb2Ygb3BMaXN0cykgewogICAgICAgICAgcGFnZU9wTGlzdC5hZGRPcExpc3Qob3BMaXN0KTsKICAgICAgICAgIGlmIChzZXBhcmF0ZUZvcm0pIHsKICAgICAgICAgICAgZm9ybSA9IHNlcGFyYXRlRm9ybTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChzZXBhcmF0ZUNhbnZhcykgewogICAgICAgICAgICBjYW52YXMgPSBzZXBhcmF0ZUNhbnZhczsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcGFnZU9wTGlzdC5mbHVzaCh0cnVlLCB7CiAgICAgICAgICBmb3JtLAogICAgICAgICAgY2FudmFzCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIGxlbmd0aDogcGFnZU9wTGlzdC50b3RhbExlbmd0aAogICAgICAgIH07CiAgICAgIH0pOwogICAgfSk7CiAgfQogIGV4dHJhY3RUZXh0Q29udGVudChfcmVmNSkgewogICAgbGV0IHsKICAgICAgaGFuZGxlciwKICAgICAgdGFzaywKICAgICAgaW5jbHVkZU1hcmtlZENvbnRlbnQsCiAgICAgIHNpbmssCiAgICAgIGNvbWJpbmVUZXh0SXRlbXMKICAgIH0gPSBfcmVmNTsKICAgIGNvbnN0IGNvbnRlbnRTdHJlYW1Qcm9taXNlID0gdGhpcy5nZXRDb250ZW50U3RyZWFtKCk7CiAgICBjb25zdCByZXNvdXJjZXNQcm9taXNlID0gdGhpcy5sb2FkUmVzb3VyY2VzKFsiRXh0R1N0YXRlIiwgIkZvbnQiLCAiUHJvcGVydGllcyIsICJYT2JqZWN0Il0pOwogICAgY29uc3QgZGF0YVByb21pc2VzID0gUHJvbWlzZS5hbGwoW2NvbnRlbnRTdHJlYW1Qcm9taXNlLCByZXNvdXJjZXNQcm9taXNlXSk7CiAgICByZXR1cm4gZGF0YVByb21pc2VzLnRoZW4oX3JlZjYgPT4gewogICAgICBsZXQgW2NvbnRlbnRTdHJlYW1dID0gX3JlZjY7CiAgICAgIGNvbnN0IHBhcnRpYWxFdmFsdWF0b3IgPSBuZXcgX2V2YWx1YXRvci5QYXJ0aWFsRXZhbHVhdG9yKHsKICAgICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgICAgaGFuZGxlciwKICAgICAgICBwYWdlSW5kZXg6IHRoaXMucGFnZUluZGV4LAogICAgICAgIGlkRmFjdG9yeTogdGhpcy5fbG9jYWxJZEZhY3RvcnksCiAgICAgICAgZm9udENhY2hlOiB0aGlzLmZvbnRDYWNoZSwKICAgICAgICBidWlsdEluQ01hcENhY2hlOiB0aGlzLmJ1aWx0SW5DTWFwQ2FjaGUsCiAgICAgICAgc3RhbmRhcmRGb250RGF0YUNhY2hlOiB0aGlzLnN0YW5kYXJkRm9udERhdGFDYWNoZSwKICAgICAgICBnbG9iYWxJbWFnZUNhY2hlOiB0aGlzLmdsb2JhbEltYWdlQ2FjaGUsCiAgICAgICAgb3B0aW9uczogdGhpcy5ldmFsdWF0b3JPcHRpb25zCiAgICAgIH0pOwogICAgICByZXR1cm4gcGFydGlhbEV2YWx1YXRvci5nZXRUZXh0Q29udGVudCh7CiAgICAgICAgc3RyZWFtOiBjb250ZW50U3RyZWFtLAogICAgICAgIHRhc2ssCiAgICAgICAgcmVzb3VyY2VzOiB0aGlzLnJlc291cmNlcywKICAgICAgICBpbmNsdWRlTWFya2VkQ29udGVudCwKICAgICAgICBjb21iaW5lVGV4dEl0ZW1zLAogICAgICAgIHNpbmssCiAgICAgICAgdmlld0JveDogdGhpcy52aWV3CiAgICAgIH0pOwogICAgfSk7CiAgfQogIGFzeW5jIGdldFN0cnVjdFRyZWUoKSB7CiAgICBjb25zdCBzdHJ1Y3RUcmVlUm9vdCA9IGF3YWl0IHRoaXMucGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJzdHJ1Y3RUcmVlUm9vdCIpOwogICAgaWYgKCFzdHJ1Y3RUcmVlUm9vdCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHN0cnVjdFRyZWUgPSBhd2FpdCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlKHRoaXMsICJfcGFyc2VTdHJ1Y3RUcmVlIiwgW3N0cnVjdFRyZWVSb290XSk7CiAgICByZXR1cm4gc3RydWN0VHJlZS5zZXJpYWxpemFibGU7CiAgfQogIF9wYXJzZVN0cnVjdFRyZWUoc3RydWN0VHJlZVJvb3QpIHsKICAgIGNvbnN0IHRyZWUgPSBuZXcgX3N0cnVjdF90cmVlLlN0cnVjdFRyZWVQYWdlKHN0cnVjdFRyZWVSb290LCB0aGlzLnBhZ2VEaWN0KTsKICAgIHRyZWUucGFyc2UoKTsKICAgIHJldHVybiB0cmVlOwogIH0KICBhc3luYyBnZXRBbm5vdGF0aW9uc0RhdGEoaGFuZGxlciwgdGFzaywgaW50ZW50KSB7CiAgICBjb25zdCBhbm5vdGF0aW9ucyA9IGF3YWl0IHRoaXMuX3BhcnNlZEFubm90YXRpb25zOwogICAgaWYgKGFubm90YXRpb25zLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gW107CiAgICB9CiAgICBjb25zdCB0ZXh0Q29udGVudFByb21pc2VzID0gW107CiAgICBjb25zdCBhbm5vdGF0aW9uc0RhdGEgPSBbXTsKICAgIGxldCBwYXJ0aWFsRXZhbHVhdG9yOwogICAgY29uc3QgaW50ZW50QW55ID0gISEoaW50ZW50ICYgX3V0aWwuUmVuZGVyaW5nSW50ZW50RmxhZy5BTlkpLAogICAgICBpbnRlbnREaXNwbGF5ID0gISEoaW50ZW50ICYgX3V0aWwuUmVuZGVyaW5nSW50ZW50RmxhZy5ESVNQTEFZKSwKICAgICAgaW50ZW50UHJpbnQgPSAhIShpbnRlbnQgJiBfdXRpbC5SZW5kZXJpbmdJbnRlbnRGbGFnLlBSSU5UKTsKICAgIGZvciAoY29uc3QgYW5ub3RhdGlvbiBvZiBhbm5vdGF0aW9ucykgewogICAgICBjb25zdCBpc1Zpc2libGUgPSBpbnRlbnRBbnkgfHwgaW50ZW50RGlzcGxheSAmJiBhbm5vdGF0aW9uLnZpZXdhYmxlOwogICAgICBpZiAoaXNWaXNpYmxlIHx8IGludGVudFByaW50ICYmIGFubm90YXRpb24ucHJpbnRhYmxlKSB7CiAgICAgICAgYW5ub3RhdGlvbnNEYXRhLnB1c2goYW5ub3RhdGlvbi5kYXRhKTsKICAgICAgfQogICAgICBpZiAoYW5ub3RhdGlvbi5oYXNUZXh0Q29udGVudCAmJiBpc1Zpc2libGUpIHsKICAgICAgICBpZiAoIXBhcnRpYWxFdmFsdWF0b3IpIHsKICAgICAgICAgIHBhcnRpYWxFdmFsdWF0b3IgPSBuZXcgX2V2YWx1YXRvci5QYXJ0aWFsRXZhbHVhdG9yKHsKICAgICAgICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICAgICAgICBoYW5kbGVyLAogICAgICAgICAgICBwYWdlSW5kZXg6IHRoaXMucGFnZUluZGV4LAogICAgICAgICAgICBpZEZhY3Rvcnk6IHRoaXMuX2xvY2FsSWRGYWN0b3J5LAogICAgICAgICAgICBmb250Q2FjaGU6IHRoaXMuZm9udENhY2hlLAogICAgICAgICAgICBidWlsdEluQ01hcENhY2hlOiB0aGlzLmJ1aWx0SW5DTWFwQ2FjaGUsCiAgICAgICAgICAgIHN0YW5kYXJkRm9udERhdGFDYWNoZTogdGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUsCiAgICAgICAgICAgIGdsb2JhbEltYWdlQ2FjaGU6IHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZSwKICAgICAgICAgICAgb3B0aW9uczogdGhpcy5ldmFsdWF0b3JPcHRpb25zCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgdGV4dENvbnRlbnRQcm9taXNlcy5wdXNoKGFubm90YXRpb24uZXh0cmFjdFRleHRDb250ZW50KHBhcnRpYWxFdmFsdWF0b3IsIHRhc2ssIHRoaXMudmlldykuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBnZXRBbm5vdGF0aW9uc0RhdGEgLSBpZ25vcmluZyB0ZXh0Q29udGVudCBkdXJpbmcgIiR7dGFzay5uYW1lfSIgdGFzazogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgfSkpOwogICAgICB9CiAgICB9CiAgICBhd2FpdCBQcm9taXNlLmFsbCh0ZXh0Q29udGVudFByb21pc2VzKTsKICAgIHJldHVybiBhbm5vdGF0aW9uc0RhdGE7CiAgfQogIGdldCBhbm5vdGF0aW9ucygpIHsKICAgIGNvbnN0IGFubm90cyA9IHRoaXMuX2dldEluaGVyaXRhYmxlUHJvcGVydHkoIkFubm90cyIpOwogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJhbm5vdGF0aW9ucyIsIEFycmF5LmlzQXJyYXkoYW5ub3RzKSA/IGFubm90cyA6IFtdKTsKICB9CiAgZ2V0IF9wYXJzZWRBbm5vdGF0aW9ucygpIHsKICAgIGNvbnN0IHBhcnNlZEFubm90YXRpb25zID0gdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZSh0aGlzLCAiYW5ub3RhdGlvbnMiKS50aGVuKCgpID0+IHsKICAgICAgY29uc3QgYW5ub3RhdGlvblByb21pc2VzID0gW107CiAgICAgIGZvciAoY29uc3QgYW5ub3RhdGlvblJlZiBvZiB0aGlzLmFubm90YXRpb25zKSB7CiAgICAgICAgYW5ub3RhdGlvblByb21pc2VzLnB1c2goX2Fubm90YXRpb24uQW5ub3RhdGlvbkZhY3RvcnkuY3JlYXRlKHRoaXMueHJlZiwgYW5ub3RhdGlvblJlZiwgdGhpcy5wZGZNYW5hZ2VyLCB0aGlzLl9sb2NhbElkRmFjdG9yeSwgZmFsc2UpLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgX3BhcnNlZEFubm90YXRpb25zOiAiJHtyZWFzb259Ii5gKTsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0pKTsKICAgICAgfQogICAgICByZXR1cm4gUHJvbWlzZS5hbGwoYW5ub3RhdGlvblByb21pc2VzKS50aGVuKGZ1bmN0aW9uIChhbm5vdGF0aW9ucykgewogICAgICAgIGlmIChhbm5vdGF0aW9ucy5sZW5ndGggPT09IDApIHsKICAgICAgICAgIHJldHVybiBhbm5vdGF0aW9uczsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc29ydGVkQW5ub3RhdGlvbnMgPSBbXTsKICAgICAgICBsZXQgcG9wdXBBbm5vdGF0aW9uczsKICAgICAgICBmb3IgKGNvbnN0IGFubm90YXRpb24gb2YgYW5ub3RhdGlvbnMpIHsKICAgICAgICAgIGlmICghYW5ub3RhdGlvbikgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChhbm5vdGF0aW9uIGluc3RhbmNlb2YgX2Fubm90YXRpb24uUG9wdXBBbm5vdGF0aW9uKSB7CiAgICAgICAgICAgIGlmICghcG9wdXBBbm5vdGF0aW9ucykgewogICAgICAgICAgICAgIHBvcHVwQW5ub3RhdGlvbnMgPSBbXTsKICAgICAgICAgICAgfQogICAgICAgICAgICBwb3B1cEFubm90YXRpb25zLnB1c2goYW5ub3RhdGlvbik7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgc29ydGVkQW5ub3RhdGlvbnMucHVzaChhbm5vdGF0aW9uKTsKICAgICAgICB9CiAgICAgICAgaWYgKHBvcHVwQW5ub3RhdGlvbnMpIHsKICAgICAgICAgIHNvcnRlZEFubm90YXRpb25zLnB1c2goLi4ucG9wdXBBbm5vdGF0aW9ucyk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzb3J0ZWRBbm5vdGF0aW9uczsKICAgICAgfSk7CiAgICB9KTsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiX3BhcnNlZEFubm90YXRpb25zIiwgcGFyc2VkQW5ub3RhdGlvbnMpOwogIH0KICBnZXQganNBY3Rpb25zKCkgewogICAgY29uc3QgYWN0aW9ucyA9ICgwLCBfY29yZV91dGlscy5jb2xsZWN0QWN0aW9ucykodGhpcy54cmVmLCB0aGlzLnBhZ2VEaWN0LCBfdXRpbC5QYWdlQWN0aW9uRXZlbnRUeXBlKTsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAianNBY3Rpb25zIiwgYWN0aW9ucyk7CiAgfQp9CmV4cG9ydHMuUGFnZSA9IFBhZ2U7CmNvbnN0IFBERl9IRUFERVJfU0lHTkFUVVJFID0gbmV3IFVpbnQ4QXJyYXkoWzB4MjUsIDB4NTAsIDB4NDQsIDB4NDYsIDB4MmRdKTsKY29uc3QgU1RBUlRYUkVGX1NJR05BVFVSRSA9IG5ldyBVaW50OEFycmF5KFsweDczLCAweDc0LCAweDYxLCAweDcyLCAweDc0LCAweDc4LCAweDcyLCAweDY1LCAweDY2XSk7CmNvbnN0IEVORE9CSl9TSUdOQVRVUkUgPSBuZXcgVWludDhBcnJheShbMHg2NSwgMHg2ZSwgMHg2NCwgMHg2ZiwgMHg2MiwgMHg2YV0pOwpjb25zdCBGSU5HRVJQUklOVF9GSVJTVF9CWVRFUyA9IDEwMjQ7CmNvbnN0IEVNUFRZX0ZJTkdFUlBSSU5UID0gIlx4MDBceDAwXHgwMFx4MDBceDAwXHgwMFx4MDBceDAwXHgwMFx4MDBceDAwXHgwMFx4MDBceDAwXHgwMFx4MDAiOwpmdW5jdGlvbiBmaW5kKHN0cmVhbSwgc2lnbmF0dXJlKSB7CiAgbGV0IGxpbWl0ID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiAxMDI0OwogIGxldCBiYWNrd2FyZHMgPSBhcmd1bWVudHMubGVuZ3RoID4gMyAmJiBhcmd1bWVudHNbM10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1szXSA6IGZhbHNlOwogIGNvbnN0IHNpZ25hdHVyZUxlbmd0aCA9IHNpZ25hdHVyZS5sZW5ndGg7CiAgY29uc3Qgc2NhbkJ5dGVzID0gc3RyZWFtLnBlZWtCeXRlcyhsaW1pdCk7CiAgY29uc3Qgc2Nhbkxlbmd0aCA9IHNjYW5CeXRlcy5sZW5ndGggLSBzaWduYXR1cmVMZW5ndGg7CiAgaWYgKHNjYW5MZW5ndGggPD0gMCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBpZiAoYmFja3dhcmRzKSB7CiAgICBjb25zdCBzaWduYXR1cmVFbmQgPSBzaWduYXR1cmVMZW5ndGggLSAxOwogICAgbGV0IHBvcyA9IHNjYW5CeXRlcy5sZW5ndGggLSAxOwogICAgd2hpbGUgKHBvcyA+PSBzaWduYXR1cmVFbmQpIHsKICAgICAgbGV0IGogPSAwOwogICAgICB3aGlsZSAoaiA8IHNpZ25hdHVyZUxlbmd0aCAmJiBzY2FuQnl0ZXNbcG9zIC0gal0gPT09IHNpZ25hdHVyZVtzaWduYXR1cmVFbmQgLSBqXSkgewogICAgICAgIGorKzsKICAgICAgfQogICAgICBpZiAoaiA+PSBzaWduYXR1cmVMZW5ndGgpIHsKICAgICAgICBzdHJlYW0ucG9zICs9IHBvcyAtIHNpZ25hdHVyZUVuZDsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBwb3MtLTsKICAgIH0KICB9IGVsc2UgewogICAgbGV0IHBvcyA9IDA7CiAgICB3aGlsZSAocG9zIDw9IHNjYW5MZW5ndGgpIHsKICAgICAgbGV0IGogPSAwOwogICAgICB3aGlsZSAoaiA8IHNpZ25hdHVyZUxlbmd0aCAmJiBzY2FuQnl0ZXNbcG9zICsgal0gPT09IHNpZ25hdHVyZVtqXSkgewogICAgICAgIGorKzsKICAgICAgfQogICAgICBpZiAoaiA+PSBzaWduYXR1cmVMZW5ndGgpIHsKICAgICAgICBzdHJlYW0ucG9zICs9IHBvczsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBwb3MrKzsKICAgIH0KICB9CiAgcmV0dXJuIGZhbHNlOwp9CmNsYXNzIFBERkRvY3VtZW50IHsKICBjb25zdHJ1Y3RvcihwZGZNYW5hZ2VyLCBzdHJlYW0pIHsKICAgIGlmIChzdHJlYW0ubGVuZ3RoIDw9IDApIHsKICAgICAgdGhyb3cgbmV3IF91dGlsLkludmFsaWRQREZFeGNlcHRpb24oIlRoZSBQREYgZmlsZSBpcyBlbXB0eSwgaS5lLiBpdHMgc2l6ZSBpcyB6ZXJvIGJ5dGVzLiIpOwogICAgfQogICAgdGhpcy5wZGZNYW5hZ2VyID0gcGRmTWFuYWdlcjsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy54cmVmID0gbmV3IF94cmVmLlhSZWYoc3RyZWFtLCBwZGZNYW5hZ2VyKTsKICAgIHRoaXMuX3BhZ2VQcm9taXNlcyA9IG5ldyBNYXAoKTsKICAgIHRoaXMuX3ZlcnNpb24gPSBudWxsOwogICAgY29uc3QgaWRDb3VudGVycyA9IHsKICAgICAgZm9udDogMAogICAgfTsKICAgIHRoaXMuX2dsb2JhbElkRmFjdG9yeSA9IGNsYXNzIHsKICAgICAgc3RhdGljIGdldERvY0lkKCkgewogICAgICAgIHJldHVybiBgZ18ke3BkZk1hbmFnZXIuZG9jSWR9YDsKICAgICAgfQogICAgICBzdGF0aWMgY3JlYXRlRm9udElkKCkgewogICAgICAgIHJldHVybiBgZiR7KytpZENvdW50ZXJzLmZvbnR9YDsKICAgICAgfQogICAgICBzdGF0aWMgY3JlYXRlT2JqSWQoKSB7CiAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQWJzdHJhY3QgbWV0aG9kIGBjcmVhdGVPYmpJZGAgY2FsbGVkLiIpOwogICAgICB9CiAgICAgIHN0YXRpYyBnZXRQYWdlT2JqSWQoKSB7CiAgICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQWJzdHJhY3QgbWV0aG9kIGBnZXRQYWdlT2JqSWRgIGNhbGxlZC4iKTsKICAgICAgfQogICAgfTsKICB9CiAgcGFyc2UocmVjb3ZlcnlNb2RlKSB7CiAgICB0aGlzLnhyZWYucGFyc2UocmVjb3ZlcnlNb2RlKTsKICAgIHRoaXMuY2F0YWxvZyA9IG5ldyBfY2F0YWxvZy5DYXRhbG9nKHRoaXMucGRmTWFuYWdlciwgdGhpcy54cmVmKTsKICB9CiAgZ2V0IGxpbmVhcml6YXRpb24oKSB7CiAgICBsZXQgbGluZWFyaXphdGlvbiA9IG51bGw7CiAgICB0cnkgewogICAgICBsaW5lYXJpemF0aW9uID0gX3BhcnNlci5MaW5lYXJpemF0aW9uLmNyZWF0ZSh0aGlzLnN0cmVhbSk7CiAgICB9IGNhdGNoIChlcnIpIHsKICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXJyOwogICAgICB9CiAgICAgICgwLCBfdXRpbC5pbmZvKShlcnIpOwogICAgfQogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJsaW5lYXJpemF0aW9uIiwgbGluZWFyaXphdGlvbik7CiAgfQogIGdldCBzdGFydFhSZWYoKSB7CiAgICBjb25zdCBzdHJlYW0gPSB0aGlzLnN0cmVhbTsKICAgIGxldCBzdGFydFhSZWYgPSAwOwogICAgaWYgKHRoaXMubGluZWFyaXphdGlvbikgewogICAgICBzdHJlYW0ucmVzZXQoKTsKICAgICAgaWYgKGZpbmQoc3RyZWFtLCBFTkRPQkpfU0lHTkFUVVJFKSkgewogICAgICAgIHN0YXJ0WFJlZiA9IHN0cmVhbS5wb3MgKyA2IC0gc3RyZWFtLnN0YXJ0OwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBzdGVwID0gMTAyNDsKICAgICAgY29uc3Qgc3RhcnRYUmVmTGVuZ3RoID0gU1RBUlRYUkVGX1NJR05BVFVSRS5sZW5ndGg7CiAgICAgIGxldCBmb3VuZCA9IGZhbHNlLAogICAgICAgIHBvcyA9IHN0cmVhbS5lbmQ7CiAgICAgIHdoaWxlICghZm91bmQgJiYgcG9zID4gMCkgewogICAgICAgIHBvcyAtPSBzdGVwIC0gc3RhcnRYUmVmTGVuZ3RoOwogICAgICAgIGlmIChwb3MgPCAwKSB7CiAgICAgICAgICBwb3MgPSAwOwogICAgICAgIH0KICAgICAgICBzdHJlYW0ucG9zID0gcG9zOwogICAgICAgIGZvdW5kID0gZmluZChzdHJlYW0sIFNUQVJUWFJFRl9TSUdOQVRVUkUsIHN0ZXAsIHRydWUpOwogICAgICB9CiAgICAgIGlmIChmb3VuZCkgewogICAgICAgIHN0cmVhbS5za2lwKDkpOwogICAgICAgIGxldCBjaDsKICAgICAgICBkbyB7CiAgICAgICAgICBjaCA9IHN0cmVhbS5nZXRCeXRlKCk7CiAgICAgICAgfSB3aGlsZSAoKDAsIF9jb3JlX3V0aWxzLmlzV2hpdGVTcGFjZSkoY2gpKTsKICAgICAgICBsZXQgc3RyID0gIiI7CiAgICAgICAgd2hpbGUgKGNoID49IDB4MjAgJiYgY2ggPD0gMHgzOSkgewogICAgICAgICAgc3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpOwogICAgICAgICAgY2ggPSBzdHJlYW0uZ2V0Qnl0ZSgpOwogICAgICAgIH0KICAgICAgICBzdGFydFhSZWYgPSBwYXJzZUludChzdHIsIDEwKTsKICAgICAgICBpZiAoaXNOYU4oc3RhcnRYUmVmKSkgewogICAgICAgICAgc3RhcnRYUmVmID0gMDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAic3RhcnRYUmVmIiwgc3RhcnRYUmVmKTsKICB9CiAgY2hlY2tIZWFkZXIoKSB7CiAgICBjb25zdCBzdHJlYW0gPSB0aGlzLnN0cmVhbTsKICAgIHN0cmVhbS5yZXNldCgpOwogICAgaWYgKCFmaW5kKHN0cmVhbSwgUERGX0hFQURFUl9TSUdOQVRVUkUpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHN0cmVhbS5tb3ZlU3RhcnQoKTsKICAgIHN0cmVhbS5za2lwKFBERl9IRUFERVJfU0lHTkFUVVJFLmxlbmd0aCk7CiAgICBsZXQgdmVyc2lvbiA9ICIiLAogICAgICBjaDsKICAgIHdoaWxlICgoY2ggPSBzdHJlYW0uZ2V0Qnl0ZSgpKSA+IDB4MjAgJiYgdmVyc2lvbi5sZW5ndGggPCA3KSB7CiAgICAgIHZlcnNpb24gKz0gU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICB9CiAgICBpZiAoX2NvcmVfdXRpbHMuUERGX1ZFUlNJT05fUkVHRVhQLnRlc3QodmVyc2lvbikpIHsKICAgICAgdGhpcy5fdmVyc2lvbiA9IHZlcnNpb247CiAgICB9IGVsc2UgewogICAgICAoMCwgX3V0aWwud2FybikoYEludmFsaWQgUERGIGhlYWRlciB2ZXJzaW9uOiAke3ZlcnNpb259YCk7CiAgICB9CiAgfQogIHBhcnNlU3RhcnRYUmVmKCkgewogICAgdGhpcy54cmVmLnNldFN0YXJ0WFJlZih0aGlzLnN0YXJ0WFJlZik7CiAgfQogIGdldCBudW1QYWdlcygpIHsKICAgIGxldCBudW0gPSAwOwogICAgaWYgKHRoaXMuY2F0YWxvZy5oYXNBY3R1YWxOdW1QYWdlcykgewogICAgICBudW0gPSB0aGlzLmNhdGFsb2cubnVtUGFnZXM7CiAgICB9IGVsc2UgaWYgKHRoaXMueGZhRmFjdG9yeSkgewogICAgICBudW0gPSB0aGlzLnhmYUZhY3RvcnkuZ2V0TnVtUGFnZXMoKTsKICAgIH0gZWxzZSBpZiAodGhpcy5saW5lYXJpemF0aW9uKSB7CiAgICAgIG51bSA9IHRoaXMubGluZWFyaXphdGlvbi5udW1QYWdlczsKICAgIH0gZWxzZSB7CiAgICAgIG51bSA9IHRoaXMuY2F0YWxvZy5udW1QYWdlczsKICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAibnVtUGFnZXMiLCBudW0pOwogIH0KICBfaGFzT25seURvY3VtZW50U2lnbmF0dXJlcyhmaWVsZHMpIHsKICAgIGxldCByZWN1cnNpb25EZXB0aCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogMDsKICAgIGNvbnN0IFJFQ1VSU0lPTl9MSU1JVCA9IDEwOwogICAgaWYgKCFBcnJheS5pc0FycmF5KGZpZWxkcykpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgcmV0dXJuIGZpZWxkcy5ldmVyeShmaWVsZCA9PiB7CiAgICAgIGZpZWxkID0gdGhpcy54cmVmLmZldGNoSWZSZWYoZmllbGQpOwogICAgICBpZiAoIShmaWVsZCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChmaWVsZC5oYXMoIktpZHMiKSkgewogICAgICAgIGlmICgrK3JlY3Vyc2lvbkRlcHRoID4gUkVDVVJTSU9OX0xJTUlUKSB7CiAgICAgICAgICAoMCwgX3V0aWwud2FybikoIl9oYXNPbmx5RG9jdW1lbnRTaWduYXR1cmVzOiBtYXhpbXVtIHJlY3Vyc2lvbiBkZXB0aCByZWFjaGVkIik7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzLl9oYXNPbmx5RG9jdW1lbnRTaWduYXR1cmVzKGZpZWxkLmdldCgiS2lkcyIpLCByZWN1cnNpb25EZXB0aCk7CiAgICAgIH0KICAgICAgY29uc3QgaXNTaWduYXR1cmUgPSAoMCwgX3ByaW1pdGl2ZXMuaXNOYW1lKShmaWVsZC5nZXQoIkZUIiksICJTaWciKTsKICAgICAgY29uc3QgcmVjdGFuZ2xlID0gZmllbGQuZ2V0KCJSZWN0Iik7CiAgICAgIGNvbnN0IGlzSW52aXNpYmxlID0gQXJyYXkuaXNBcnJheShyZWN0YW5nbGUpICYmIHJlY3RhbmdsZS5ldmVyeSh2YWx1ZSA9PiB2YWx1ZSA9PT0gMCk7CiAgICAgIHJldHVybiBpc1NpZ25hdHVyZSAmJiBpc0ludmlzaWJsZTsKICAgIH0pOwogIH0KICBnZXQgX3hmYVN0cmVhbXMoKSB7CiAgICBjb25zdCBhY3JvRm9ybSA9IHRoaXMuY2F0YWxvZy5hY3JvRm9ybTsKICAgIGlmICghYWNyb0Zvcm0pIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCB4ZmEgPSBhY3JvRm9ybS5nZXQoIlhGQSIpOwogICAgY29uc3QgZW50cmllcyA9IHsKICAgICAgInhkcDp4ZHAiOiAiIiwKICAgICAgdGVtcGxhdGU6ICIiLAogICAgICBkYXRhc2V0czogIiIsCiAgICAgIGNvbmZpZzogIiIsCiAgICAgIGNvbm5lY3Rpb25TZXQ6ICIiLAogICAgICBsb2NhbGVTZXQ6ICIiLAogICAgICBzdHlsZXNoZWV0OiAiIiwKICAgICAgIi94ZHA6eGRwIjogIiIKICAgIH07CiAgICBpZiAoeGZhIGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0gJiYgIXhmYS5pc0VtcHR5KSB7CiAgICAgIGVudHJpZXNbInhkcDp4ZHAiXSA9IHhmYTsKICAgICAgcmV0dXJuIGVudHJpZXM7CiAgICB9CiAgICBpZiAoIUFycmF5LmlzQXJyYXkoeGZhKSB8fCB4ZmEubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgZm9yIChsZXQgaSA9IDAsIGlpID0geGZhLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgbGV0IG5hbWU7CiAgICAgIGlmIChpID09PSAwKSB7CiAgICAgICAgbmFtZSA9ICJ4ZHA6eGRwIjsKICAgICAgfSBlbHNlIGlmIChpID09PSBpaSAtIDIpIHsKICAgICAgICBuYW1lID0gIi94ZHA6eGRwIjsKICAgICAgfSBlbHNlIHsKICAgICAgICBuYW1lID0geGZhW2ldOwogICAgICB9CiAgICAgIGlmICghZW50cmllcy5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZih4ZmFbaSArIDFdKTsKICAgICAgaWYgKCEoZGF0YSBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSB8fCBkYXRhLmlzRW1wdHkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBlbnRyaWVzW25hbWVdID0gZGF0YTsKICAgIH0KICAgIHJldHVybiBlbnRyaWVzOwogIH0KICBnZXQgeGZhRGF0YXNldHMoKSB7CiAgICBjb25zdCBzdHJlYW1zID0gdGhpcy5feGZhU3RyZWFtczsKICAgIGlmICghc3RyZWFtcykgewogICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInhmYURhdGFzZXRzIiwgbnVsbCk7CiAgICB9CiAgICBmb3IgKGNvbnN0IGtleSBvZiBbImRhdGFzZXRzIiwgInhkcDp4ZHAiXSkgewogICAgICBjb25zdCBzdHJlYW0gPSBzdHJlYW1zW2tleV07CiAgICAgIGlmICghc3RyZWFtKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgdHJ5IHsKICAgICAgICBjb25zdCBzdHIgPSAoMCwgX3V0aWwuc3RyaW5nVG9VVEY4U3RyaW5nKShzdHJlYW0uZ2V0U3RyaW5nKCkpOwogICAgICAgIGNvbnN0IGRhdGEgPSB7CiAgICAgICAgICBba2V5XTogc3RyCiAgICAgICAgfTsKICAgICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInhmYURhdGFzZXRzIiwgbmV3IF9kYXRhc2V0X3JlYWRlci5EYXRhc2V0UmVhZGVyKGRhdGEpKTsKICAgICAgfSBjYXRjaCAoXykgewogICAgICAgICgwLCBfdXRpbC53YXJuKSgiWEZBIC0gSW52YWxpZCB1dGYtOCBzdHJpbmcuIik7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAieGZhRGF0YXNldHMiLCBudWxsKTsKICB9CiAgZ2V0IHhmYURhdGEoKSB7CiAgICBjb25zdCBzdHJlYW1zID0gdGhpcy5feGZhU3RyZWFtczsKICAgIGlmICghc3RyZWFtcykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IGRhdGEgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgZm9yIChjb25zdCBba2V5LCBzdHJlYW1dIG9mIE9iamVjdC5lbnRyaWVzKHN0cmVhbXMpKSB7CiAgICAgIGlmICghc3RyZWFtKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgdHJ5IHsKICAgICAgICBkYXRhW2tleV0gPSAoMCwgX3V0aWwuc3RyaW5nVG9VVEY4U3RyaW5nKShzdHJlYW0uZ2V0U3RyaW5nKCkpOwogICAgICB9IGNhdGNoIChfKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKCJYRkEgLSBJbnZhbGlkIHV0Zi04IHN0cmluZy4iKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGRhdGE7CiAgfQogIGdldCB4ZmFGYWN0b3J5KCkgewogICAgbGV0IGRhdGE7CiAgICBpZiAodGhpcy5wZGZNYW5hZ2VyLmVuYWJsZVhmYSAmJiB0aGlzLmNhdGFsb2cubmVlZHNSZW5kZXJpbmcgJiYgdGhpcy5mb3JtSW5mby5oYXNYZmEgJiYgIXRoaXMuZm9ybUluZm8uaGFzQWNyb0Zvcm0pIHsKICAgICAgZGF0YSA9IHRoaXMueGZhRGF0YTsKICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAieGZhRmFjdG9yeSIsIGRhdGEgPyBuZXcgX2ZhY3RvcnkuWEZBRmFjdG9yeShkYXRhKSA6IG51bGwpOwogIH0KICBnZXQgaXNQdXJlWGZhKCkgewogICAgcmV0dXJuIHRoaXMueGZhRmFjdG9yeSA/IHRoaXMueGZhRmFjdG9yeS5pc1ZhbGlkKCkgOiBmYWxzZTsKICB9CiAgZ2V0IGh0bWxGb3JYZmEoKSB7CiAgICByZXR1cm4gdGhpcy54ZmFGYWN0b3J5ID8gdGhpcy54ZmFGYWN0b3J5LmdldFBhZ2VzKCkgOiBudWxsOwogIH0KICBhc3luYyBsb2FkWGZhSW1hZ2VzKCkgewogICAgY29uc3QgeGZhSW1hZ2VzRGljdCA9IGF3YWl0IHRoaXMucGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJ4ZmFJbWFnZXMiKTsKICAgIGlmICgheGZhSW1hZ2VzRGljdCkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBrZXlzID0geGZhSW1hZ2VzRGljdC5nZXRLZXlzKCk7CiAgICBjb25zdCBvYmplY3RMb2FkZXIgPSBuZXcgX29iamVjdF9sb2FkZXIuT2JqZWN0TG9hZGVyKHhmYUltYWdlc0RpY3QsIGtleXMsIHRoaXMueHJlZik7CiAgICBhd2FpdCBvYmplY3RMb2FkZXIubG9hZCgpOwogICAgY29uc3QgeGZhSW1hZ2VzID0gbmV3IE1hcCgpOwogICAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykgewogICAgICBjb25zdCBzdHJlYW0gPSB4ZmFJbWFnZXNEaWN0LmdldChrZXkpOwogICAgICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0pIHsKICAgICAgICB4ZmFJbWFnZXMuc2V0KGtleSwgc3RyZWFtLmdldEJ5dGVzKCkpOwogICAgICB9CiAgICB9CiAgICB0aGlzLnhmYUZhY3Rvcnkuc2V0SW1hZ2VzKHhmYUltYWdlcyk7CiAgfQogIGFzeW5jIGxvYWRYZmFGb250cyhoYW5kbGVyLCB0YXNrKSB7CiAgICBjb25zdCBhY3JvRm9ybSA9IGF3YWl0IHRoaXMucGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJhY3JvRm9ybSIpOwogICAgaWYgKCFhY3JvRm9ybSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCByZXNvdXJjZXMgPSBhd2FpdCBhY3JvRm9ybS5nZXRBc3luYygiRFIiKTsKICAgIGlmICghKHJlc291cmNlcyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG9iamVjdExvYWRlciA9IG5ldyBfb2JqZWN0X2xvYWRlci5PYmplY3RMb2FkZXIocmVzb3VyY2VzLCBbIkZvbnQiXSwgdGhpcy54cmVmKTsKICAgIGF3YWl0IG9iamVjdExvYWRlci5sb2FkKCk7CiAgICBjb25zdCBmb250UmVzID0gcmVzb3VyY2VzLmdldCgiRm9udCIpOwogICAgaWYgKCEoZm9udFJlcyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG9wdGlvbnMgPSBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobnVsbCksIHRoaXMucGRmTWFuYWdlci5ldmFsdWF0b3JPcHRpb25zKTsKICAgIG9wdGlvbnMudXNlU3lzdGVtRm9udHMgPSBmYWxzZTsKICAgIGNvbnN0IHBhcnRpYWxFdmFsdWF0b3IgPSBuZXcgX2V2YWx1YXRvci5QYXJ0aWFsRXZhbHVhdG9yKHsKICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICBoYW5kbGVyLAogICAgICBwYWdlSW5kZXg6IC0xLAogICAgICBpZEZhY3Rvcnk6IHRoaXMuX2dsb2JhbElkRmFjdG9yeSwKICAgICAgZm9udENhY2hlOiB0aGlzLmNhdGFsb2cuZm9udENhY2hlLAogICAgICBidWlsdEluQ01hcENhY2hlOiB0aGlzLmNhdGFsb2cuYnVpbHRJbkNNYXBDYWNoZSwKICAgICAgc3RhbmRhcmRGb250RGF0YUNhY2hlOiB0aGlzLmNhdGFsb2cuc3RhbmRhcmRGb250RGF0YUNhY2hlLAogICAgICBvcHRpb25zCiAgICB9KTsKICAgIGNvbnN0IG9wZXJhdG9yTGlzdCA9IG5ldyBfb3BlcmF0b3JfbGlzdC5PcGVyYXRvckxpc3QoKTsKICAgIGNvbnN0IHBkZkZvbnRzID0gW107CiAgICBjb25zdCBpbml0aWFsU3RhdGUgPSB7CiAgICAgIGdldCBmb250KCkgewogICAgICAgIHJldHVybiBwZGZGb250cy5hdCgtMSk7CiAgICAgIH0sCiAgICAgIHNldCBmb250KGZvbnQpIHsKICAgICAgICBwZGZGb250cy5wdXNoKGZvbnQpOwogICAgICB9LAogICAgICBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgfTsKICAgIGNvbnN0IGZvbnRzID0gbmV3IE1hcCgpOwogICAgZm9udFJlcy5mb3JFYWNoKChmb250TmFtZSwgZm9udCkgPT4gewogICAgICBmb250cy5zZXQoZm9udE5hbWUsIGZvbnQpOwogICAgfSk7CiAgICBjb25zdCBwcm9taXNlcyA9IFtdOwogICAgZm9yIChjb25zdCBbZm9udE5hbWUsIGZvbnRdIG9mIGZvbnRzKSB7CiAgICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBmb250LmdldCgiRm9udERlc2NyaXB0b3IiKTsKICAgICAgaWYgKCEoZGVzY3JpcHRvciBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgbGV0IGZvbnRGYW1pbHkgPSBkZXNjcmlwdG9yLmdldCgiRm9udEZhbWlseSIpOwogICAgICBmb250RmFtaWx5ID0gZm9udEZhbWlseS5yZXBsYWNlQWxsKC9bIF0rKFxkKS9nLCAiJDEiKTsKICAgICAgY29uc3QgZm9udFdlaWdodCA9IGRlc2NyaXB0b3IuZ2V0KCJGb250V2VpZ2h0Iik7CiAgICAgIGNvbnN0IGl0YWxpY0FuZ2xlID0gLWRlc2NyaXB0b3IuZ2V0KCJJdGFsaWNBbmdsZSIpOwogICAgICBjb25zdCBjc3NGb250SW5mbyA9IHsKICAgICAgICBmb250RmFtaWx5LAogICAgICAgIGZvbnRXZWlnaHQsCiAgICAgICAgaXRhbGljQW5nbGUKICAgICAgfTsKICAgICAgaWYgKCEoMCwgX2NvcmVfdXRpbHMudmFsaWRhdGVDU1NGb250KShjc3NGb250SW5mbykpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBwcm9taXNlcy5wdXNoKHBhcnRpYWxFdmFsdWF0b3IuaGFuZGxlU2V0Rm9udChyZXNvdXJjZXMsIFtfcHJpbWl0aXZlcy5OYW1lLmdldChmb250TmFtZSksIDFdLCBudWxsLCBvcGVyYXRvckxpc3QsIHRhc2ssIGluaXRpYWxTdGF0ZSwgbnVsbCwgY3NzRm9udEluZm8pLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYGxvYWRYZmFGb250czogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0pKTsKICAgIH0KICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTsKICAgIGNvbnN0IG1pc3NpbmdGb250cyA9IHRoaXMueGZhRmFjdG9yeS5zZXRGb250cyhwZGZGb250cyk7CiAgICBpZiAoIW1pc3NpbmdGb250cykgewogICAgICByZXR1cm47CiAgICB9CiAgICBvcHRpb25zLmlnbm9yZUVycm9ycyA9IHRydWU7CiAgICBwcm9taXNlcy5sZW5ndGggPSAwOwogICAgcGRmRm9udHMubGVuZ3RoID0gMDsKICAgIGNvbnN0IHJlYWxseU1pc3NpbmdGb250cyA9IG5ldyBTZXQoKTsKICAgIGZvciAoY29uc3QgbWlzc2luZyBvZiBtaXNzaW5nRm9udHMpIHsKICAgICAgaWYgKCEoMCwgX3hmYV9mb250cy5nZXRYZmFGb250TmFtZSkoYCR7bWlzc2luZ30tUmVndWxhcmApKSB7CiAgICAgICAgcmVhbGx5TWlzc2luZ0ZvbnRzLmFkZChtaXNzaW5nKTsKICAgICAgfQogICAgfQogICAgaWYgKHJlYWxseU1pc3NpbmdGb250cy5zaXplKSB7CiAgICAgIG1pc3NpbmdGb250cy5wdXNoKCJQZGZKUy1GYWxsYmFjayIpOwogICAgfQogICAgZm9yIChjb25zdCBtaXNzaW5nIG9mIG1pc3NpbmdGb250cykgewogICAgICBpZiAocmVhbGx5TWlzc2luZ0ZvbnRzLmhhcyhtaXNzaW5nKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGZvciAoY29uc3QgZm9udEluZm8gb2YgW3sKICAgICAgICBuYW1lOiAiUmVndWxhciIsCiAgICAgICAgZm9udFdlaWdodDogNDAwLAogICAgICAgIGl0YWxpY0FuZ2xlOiAwCiAgICAgIH0sIHsKICAgICAgICBuYW1lOiAiQm9sZCIsCiAgICAgICAgZm9udFdlaWdodDogNzAwLAogICAgICAgIGl0YWxpY0FuZ2xlOiAwCiAgICAgIH0sIHsKICAgICAgICBuYW1lOiAiSXRhbGljIiwKICAgICAgICBmb250V2VpZ2h0OiA0MDAsCiAgICAgICAgaXRhbGljQW5nbGU6IDEyCiAgICAgIH0sIHsKICAgICAgICBuYW1lOiAiQm9sZEl0YWxpYyIsCiAgICAgICAgZm9udFdlaWdodDogNzAwLAogICAgICAgIGl0YWxpY0FuZ2xlOiAxMgogICAgICB9XSkgewogICAgICAgIGNvbnN0IG5hbWUgPSBgJHttaXNzaW5nfS0ke2ZvbnRJbmZvLm5hbWV9YDsKICAgICAgICBjb25zdCBkaWN0ID0gKDAsIF94ZmFfZm9udHMuZ2V0WGZhRm9udERpY3QpKG5hbWUpOwogICAgICAgIHByb21pc2VzLnB1c2gocGFydGlhbEV2YWx1YXRvci5oYW5kbGVTZXRGb250KHJlc291cmNlcywgW19wcmltaXRpdmVzLk5hbWUuZ2V0KG5hbWUpLCAxXSwgbnVsbCwgb3BlcmF0b3JMaXN0LCB0YXNrLCBpbml0aWFsU3RhdGUsIGRpY3QsIHsKICAgICAgICAgIGZvbnRGYW1pbHk6IG1pc3NpbmcsCiAgICAgICAgICBmb250V2VpZ2h0OiBmb250SW5mby5mb250V2VpZ2h0LAogICAgICAgICAgaXRhbGljQW5nbGU6IGZvbnRJbmZvLml0YWxpY0FuZ2xlCiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBsb2FkWGZhRm9udHM6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfSkpOwogICAgICB9CiAgICB9CiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7CiAgICB0aGlzLnhmYUZhY3RvcnkuYXBwZW5kRm9udHMocGRmRm9udHMsIHJlYWxseU1pc3NpbmdGb250cyk7CiAgfQogIGFzeW5jIHNlcmlhbGl6ZVhmYURhdGEoYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIHJldHVybiB0aGlzLnhmYUZhY3RvcnkgPyB0aGlzLnhmYUZhY3Rvcnkuc2VyaWFsaXplRGF0YShhbm5vdGF0aW9uU3RvcmFnZSkgOiBudWxsOwogIH0KICBnZXQgdmVyc2lvbigpIHsKICAgIHJldHVybiB0aGlzLmNhdGFsb2cudmVyc2lvbiB8fCB0aGlzLl92ZXJzaW9uOwogIH0KICBnZXQgZm9ybUluZm8oKSB7CiAgICBjb25zdCBmb3JtSW5mbyA9IHsKICAgICAgaGFzRmllbGRzOiBmYWxzZSwKICAgICAgaGFzQWNyb0Zvcm06IGZhbHNlLAogICAgICBoYXNYZmE6IGZhbHNlLAogICAgICBoYXNTaWduYXR1cmVzOiBmYWxzZQogICAgfTsKICAgIGNvbnN0IGFjcm9Gb3JtID0gdGhpcy5jYXRhbG9nLmFjcm9Gb3JtOwogICAgaWYgKCFhY3JvRm9ybSkgewogICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImZvcm1JbmZvIiwgZm9ybUluZm8pOwogICAgfQogICAgdHJ5IHsKICAgICAgY29uc3QgZmllbGRzID0gYWNyb0Zvcm0uZ2V0KCJGaWVsZHMiKTsKICAgICAgY29uc3QgaGFzRmllbGRzID0gQXJyYXkuaXNBcnJheShmaWVsZHMpICYmIGZpZWxkcy5sZW5ndGggPiAwOwogICAgICBmb3JtSW5mby5oYXNGaWVsZHMgPSBoYXNGaWVsZHM7CiAgICAgIGNvbnN0IHhmYSA9IGFjcm9Gb3JtLmdldCgiWEZBIik7CiAgICAgIGZvcm1JbmZvLmhhc1hmYSA9IEFycmF5LmlzQXJyYXkoeGZhKSAmJiB4ZmEubGVuZ3RoID4gMCB8fCB4ZmEgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSAmJiAheGZhLmlzRW1wdHk7CiAgICAgIGNvbnN0IHNpZ0ZsYWdzID0gYWNyb0Zvcm0uZ2V0KCJTaWdGbGFncyIpOwogICAgICBjb25zdCBoYXNTaWduYXR1cmVzID0gISEoc2lnRmxhZ3MgJiAweDEpOwogICAgICBjb25zdCBoYXNPbmx5RG9jdW1lbnRTaWduYXR1cmVzID0gaGFzU2lnbmF0dXJlcyAmJiB0aGlzLl9oYXNPbmx5RG9jdW1lbnRTaWduYXR1cmVzKGZpZWxkcyk7CiAgICAgIGZvcm1JbmZvLmhhc0Fjcm9Gb3JtID0gaGFzRmllbGRzICYmICFoYXNPbmx5RG9jdW1lbnRTaWduYXR1cmVzOwogICAgICBmb3JtSW5mby5oYXNTaWduYXR1cmVzID0gaGFzU2lnbmF0dXJlczsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgKDAsIF91dGlsLndhcm4pKGBDYW5ub3QgZmV0Y2ggZm9ybSBpbmZvcm1hdGlvbjogIiR7ZXh9Ii5gKTsKICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiZm9ybUluZm8iLCBmb3JtSW5mbyk7CiAgfQogIGdldCBkb2N1bWVudEluZm8oKSB7CiAgICBjb25zdCBkb2NJbmZvID0gewogICAgICBQREZGb3JtYXRWZXJzaW9uOiB0aGlzLnZlcnNpb24sCiAgICAgIExhbmd1YWdlOiB0aGlzLmNhdGFsb2cubGFuZywKICAgICAgRW5jcnlwdEZpbHRlck5hbWU6IHRoaXMueHJlZi5lbmNyeXB0ID8gdGhpcy54cmVmLmVuY3J5cHQuZmlsdGVyTmFtZSA6IG51bGwsCiAgICAgIElzTGluZWFyaXplZDogISF0aGlzLmxpbmVhcml6YXRpb24sCiAgICAgIElzQWNyb0Zvcm1QcmVzZW50OiB0aGlzLmZvcm1JbmZvLmhhc0Fjcm9Gb3JtLAogICAgICBJc1hGQVByZXNlbnQ6IHRoaXMuZm9ybUluZm8uaGFzWGZhLAogICAgICBJc0NvbGxlY3Rpb25QcmVzZW50OiAhIXRoaXMuY2F0YWxvZy5jb2xsZWN0aW9uLAogICAgICBJc1NpZ25hdHVyZXNQcmVzZW50OiB0aGlzLmZvcm1JbmZvLmhhc1NpZ25hdHVyZXMKICAgIH07CiAgICBsZXQgaW5mb0RpY3Q7CiAgICB0cnkgewogICAgICBpbmZvRGljdCA9IHRoaXMueHJlZi50cmFpbGVyLmdldCgiSW5mbyIpOwogICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBfY29yZV91dGlscy5NaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGVycjsKICAgICAgfQogICAgICAoMCwgX3V0aWwuaW5mbykoIlRoZSBkb2N1bWVudCBpbmZvcm1hdGlvbiBkaWN0aW9uYXJ5IGlzIGludmFsaWQuIik7CiAgICB9CiAgICBpZiAoIShpbmZvRGljdCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiZG9jdW1lbnRJbmZvIiwgZG9jSW5mbyk7CiAgICB9CiAgICBmb3IgKGNvbnN0IGtleSBvZiBpbmZvRGljdC5nZXRLZXlzKCkpIHsKICAgICAgY29uc3QgdmFsdWUgPSBpbmZvRGljdC5nZXQoa2V5KTsKICAgICAgc3dpdGNoIChrZXkpIHsKICAgICAgICBjYXNlICJUaXRsZSI6CiAgICAgICAgY2FzZSAiQXV0aG9yIjoKICAgICAgICBjYXNlICJTdWJqZWN0IjoKICAgICAgICBjYXNlICJLZXl3b3JkcyI6CiAgICAgICAgY2FzZSAiQ3JlYXRvciI6CiAgICAgICAgY2FzZSAiUHJvZHVjZXIiOgogICAgICAgIGNhc2UgIkNyZWF0aW9uRGF0ZSI6CiAgICAgICAgY2FzZSAiTW9kRGF0ZSI6CiAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAic3RyaW5nIikgewogICAgICAgICAgICBkb2NJbmZvW2tleV0gPSAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKHZhbHVlKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJUcmFwcGVkIjoKICAgICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgICAgICAgZG9jSW5mb1trZXldID0gdmFsdWU7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIGxldCBjdXN0b21WYWx1ZTsKICAgICAgICAgIHN3aXRjaCAodHlwZW9mIHZhbHVlKSB7CiAgICAgICAgICAgIGNhc2UgInN0cmluZyI6CiAgICAgICAgICAgICAgY3VzdG9tVmFsdWUgPSAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKHZhbHVlKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAibnVtYmVyIjoKICAgICAgICAgICAgY2FzZSAiYm9vbGVhbiI6CiAgICAgICAgICAgICAgY3VzdG9tVmFsdWUgPSB2YWx1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgICAgICAgICAgICBjdXN0b21WYWx1ZSA9IHZhbHVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChjdXN0b21WYWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgQmFkIHZhbHVlLCBmb3IgY3VzdG9tIGtleSAiJHtrZXl9IiwgaW4gSW5mbzogJHt2YWx1ZX0uYCk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCFkb2NJbmZvLkN1c3RvbSkgewogICAgICAgICAgICBkb2NJbmZvLkN1c3RvbSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgICB9CiAgICAgICAgICBkb2NJbmZvLkN1c3RvbVtrZXldID0gY3VzdG9tVmFsdWU7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICAoMCwgX3V0aWwud2FybikoYEJhZCB2YWx1ZSwgZm9yIGtleSAiJHtrZXl9IiwgaW4gSW5mbzogJHt2YWx1ZX0uYCk7CiAgICB9CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImRvY3VtZW50SW5mbyIsIGRvY0luZm8pOwogIH0KICBnZXQgZmluZ2VycHJpbnRzKCkgewogICAgZnVuY3Rpb24gdmFsaWRhdGUoZGF0YSkgewogICAgICByZXR1cm4gdHlwZW9mIGRhdGEgPT09ICJzdHJpbmciICYmIGRhdGEubGVuZ3RoID4gMCAmJiBkYXRhICE9PSBFTVBUWV9GSU5HRVJQUklOVDsKICAgIH0KICAgIGZ1bmN0aW9uIGhleFN0cmluZyhoYXNoKSB7CiAgICAgIGNvbnN0IGJ1ZiA9IFtdOwogICAgICBmb3IgKGNvbnN0IG51bSBvZiBoYXNoKSB7CiAgICAgICAgY29uc3QgaGV4ID0gbnVtLnRvU3RyaW5nKDE2KTsKICAgICAgICBidWYucHVzaChoZXgucGFkU3RhcnQoMiwgIjAiKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIGJ1Zi5qb2luKCIiKTsKICAgIH0KICAgIGNvbnN0IGlkQXJyYXkgPSB0aGlzLnhyZWYudHJhaWxlci5nZXQoIklEIik7CiAgICBsZXQgaGFzaE9yaWdpbmFsLCBoYXNoTW9kaWZpZWQ7CiAgICBpZiAoQXJyYXkuaXNBcnJheShpZEFycmF5KSAmJiB2YWxpZGF0ZShpZEFycmF5WzBdKSkgewogICAgICBoYXNoT3JpZ2luYWwgPSAoMCwgX3V0aWwuc3RyaW5nVG9CeXRlcykoaWRBcnJheVswXSk7CiAgICAgIGlmIChpZEFycmF5WzFdICE9PSBpZEFycmF5WzBdICYmIHZhbGlkYXRlKGlkQXJyYXlbMV0pKSB7CiAgICAgICAgaGFzaE1vZGlmaWVkID0gKDAsIF91dGlsLnN0cmluZ1RvQnl0ZXMpKGlkQXJyYXlbMV0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBoYXNoT3JpZ2luYWwgPSAoMCwgX2NyeXB0by5jYWxjdWxhdGVNRDUpKHRoaXMuc3RyZWFtLmdldEJ5dGVSYW5nZSgwLCBGSU5HRVJQUklOVF9GSVJTVF9CWVRFUyksIDAsIEZJTkdFUlBSSU5UX0ZJUlNUX0JZVEVTKTsKICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiZmluZ2VycHJpbnRzIiwgW2hleFN0cmluZyhoYXNoT3JpZ2luYWwpLCBoYXNoTW9kaWZpZWQgPyBoZXhTdHJpbmcoaGFzaE1vZGlmaWVkKSA6IG51bGxdKTsKICB9CiAgYXN5bmMgX2dldExpbmVhcml6YXRpb25QYWdlKHBhZ2VJbmRleCkgewogICAgY29uc3QgewogICAgICBjYXRhbG9nLAogICAgICBsaW5lYXJpemF0aW9uLAogICAgICB4cmVmCiAgICB9ID0gdGhpczsKICAgIGNvbnN0IHJlZiA9IF9wcmltaXRpdmVzLlJlZi5nZXQobGluZWFyaXphdGlvbi5vYmplY3ROdW1iZXJGaXJzdCwgMCk7CiAgICB0cnkgewogICAgICBjb25zdCBvYmogPSBhd2FpdCB4cmVmLmZldGNoQXN5bmMocmVmKTsKICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpIHsKICAgICAgICBsZXQgdHlwZSA9IG9iai5nZXRSYXcoIlR5cGUiKTsKICAgICAgICBpZiAodHlwZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgICAgdHlwZSA9IGF3YWl0IHhyZWYuZmV0Y2hBc3luYyh0eXBlKTsKICAgICAgICB9CiAgICAgICAgaWYgKCgwLCBfcHJpbWl0aXZlcy5pc05hbWUpKHR5cGUsICJQYWdlIikgfHwgIW9iai5oYXMoIlR5cGUiKSAmJiAhb2JqLmhhcygiS2lkcyIpKSB7CiAgICAgICAgICBpZiAoIWNhdGFsb2cucGFnZUtpZHNDb3VudENhY2hlLmhhcyhyZWYpKSB7CiAgICAgICAgICAgIGNhdGFsb2cucGFnZUtpZHNDb3VudENhY2hlLnB1dChyZWYsIDEpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCFjYXRhbG9nLnBhZ2VJbmRleENhY2hlLmhhcyhyZWYpKSB7CiAgICAgICAgICAgIGNhdGFsb2cucGFnZUluZGV4Q2FjaGUucHV0KHJlZiwgMCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gW29iaiwgcmVmXTsKICAgICAgICB9CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJUaGUgTGluZWFyaXphdGlvbiBkaWN0aW9uYXJ5IGRvZXNuJ3QgcG9pbnQgdG8gYSB2YWxpZCBQYWdlIGRpY3Rpb25hcnkuIik7CiAgICB9IGNhdGNoIChyZWFzb24pIHsKICAgICAgKDAsIF91dGlsLndhcm4pKGBfZ2V0TGluZWFyaXphdGlvblBhZ2U6ICIke3JlYXNvbi5tZXNzYWdlfSIuYCk7CiAgICAgIHJldHVybiBjYXRhbG9nLmdldFBhZ2VEaWN0KHBhZ2VJbmRleCk7CiAgICB9CiAgfQogIGdldFBhZ2UocGFnZUluZGV4KSB7CiAgICBjb25zdCBjYWNoZWRQcm9taXNlID0gdGhpcy5fcGFnZVByb21pc2VzLmdldChwYWdlSW5kZXgpOwogICAgaWYgKGNhY2hlZFByb21pc2UpIHsKICAgICAgcmV0dXJuIGNhY2hlZFByb21pc2U7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIGNhdGFsb2csCiAgICAgIGxpbmVhcml6YXRpb24sCiAgICAgIHhmYUZhY3RvcnkKICAgIH0gPSB0aGlzOwogICAgbGV0IHByb21pc2U7CiAgICBpZiAoeGZhRmFjdG9yeSkgewogICAgICBwcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKFtfcHJpbWl0aXZlcy5EaWN0LmVtcHR5LCBudWxsXSk7CiAgICB9IGVsc2UgaWYgKGxpbmVhcml6YXRpb24gJiYgbGluZWFyaXphdGlvbi5wYWdlRmlyc3QgPT09IHBhZ2VJbmRleCkgewogICAgICBwcm9taXNlID0gdGhpcy5fZ2V0TGluZWFyaXphdGlvblBhZ2UocGFnZUluZGV4KTsKICAgIH0gZWxzZSB7CiAgICAgIHByb21pc2UgPSBjYXRhbG9nLmdldFBhZ2VEaWN0KHBhZ2VJbmRleCk7CiAgICB9CiAgICBwcm9taXNlID0gcHJvbWlzZS50aGVuKF9yZWY3ID0+IHsKICAgICAgbGV0IFtwYWdlRGljdCwgcmVmXSA9IF9yZWY3OwogICAgICByZXR1cm4gbmV3IFBhZ2UoewogICAgICAgIHBkZk1hbmFnZXI6IHRoaXMucGRmTWFuYWdlciwKICAgICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgICAgcGFnZUluZGV4LAogICAgICAgIHBhZ2VEaWN0LAogICAgICAgIHJlZiwKICAgICAgICBnbG9iYWxJZEZhY3Rvcnk6IHRoaXMuX2dsb2JhbElkRmFjdG9yeSwKICAgICAgICBmb250Q2FjaGU6IGNhdGFsb2cuZm9udENhY2hlLAogICAgICAgIGJ1aWx0SW5DTWFwQ2FjaGU6IGNhdGFsb2cuYnVpbHRJbkNNYXBDYWNoZSwKICAgICAgICBzdGFuZGFyZEZvbnREYXRhQ2FjaGU6IGNhdGFsb2cuc3RhbmRhcmRGb250RGF0YUNhY2hlLAogICAgICAgIGdsb2JhbEltYWdlQ2FjaGU6IGNhdGFsb2cuZ2xvYmFsSW1hZ2VDYWNoZSwKICAgICAgICBub25CbGVuZE1vZGVzU2V0OiBjYXRhbG9nLm5vbkJsZW5kTW9kZXNTZXQsCiAgICAgICAgeGZhRmFjdG9yeQogICAgICB9KTsKICAgIH0pOwogICAgdGhpcy5fcGFnZVByb21pc2VzLnNldChwYWdlSW5kZXgsIHByb21pc2UpOwogICAgcmV0dXJuIHByb21pc2U7CiAgfQogIGFzeW5jIGNoZWNrRmlyc3RQYWdlKCkgewogICAgbGV0IHJlY292ZXJ5TW9kZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogZmFsc2U7CiAgICBpZiAocmVjb3ZlcnlNb2RlKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRyeSB7CiAgICAgIGF3YWl0IHRoaXMuZ2V0UGFnZSgwKTsKICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgX2NvcmVfdXRpbHMuWFJlZkVudHJ5RXhjZXB0aW9uKSB7CiAgICAgICAgdGhpcy5fcGFnZVByb21pc2VzLmRlbGV0ZSgwKTsKICAgICAgICBhd2FpdCB0aGlzLmNsZWFudXAoKTsKICAgICAgICB0aHJvdyBuZXcgX2NvcmVfdXRpbHMuWFJlZlBhcnNlRXhjZXB0aW9uKCk7CiAgICAgIH0KICAgIH0KICB9CiAgYXN5bmMgY2hlY2tMYXN0UGFnZSgpIHsKICAgIGxldCByZWNvdmVyeU1vZGUgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgY29uc3QgewogICAgICBjYXRhbG9nLAogICAgICBwZGZNYW5hZ2VyCiAgICB9ID0gdGhpczsKICAgIGNhdGFsb2cuc2V0QWN0dWFsTnVtUGFnZXMoKTsKICAgIGxldCBudW1QYWdlczsKICAgIHRyeSB7CiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFtwZGZNYW5hZ2VyLmVuc3VyZURvYygieGZhRmFjdG9yeSIpLCBwZGZNYW5hZ2VyLmVuc3VyZURvYygibGluZWFyaXphdGlvbiIpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coIm51bVBhZ2VzIildKTsKICAgICAgaWYgKHRoaXMueGZhRmFjdG9yeSkgewogICAgICAgIHJldHVybjsKICAgICAgfSBlbHNlIGlmICh0aGlzLmxpbmVhcml6YXRpb24pIHsKICAgICAgICBudW1QYWdlcyA9IHRoaXMubGluZWFyaXphdGlvbi5udW1QYWdlczsKICAgICAgfSBlbHNlIHsKICAgICAgICBudW1QYWdlcyA9IGNhdGFsb2cubnVtUGFnZXM7CiAgICAgIH0KICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKG51bVBhZ2VzKSkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiUGFnZSBjb3VudCBpcyBub3QgYW4gaW50ZWdlci4iKTsKICAgICAgfSBlbHNlIGlmIChudW1QYWdlcyA8PSAxKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGF3YWl0IHRoaXMuZ2V0UGFnZShudW1QYWdlcyAtIDEpOwogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIHRoaXMuX3BhZ2VQcm9taXNlcy5kZWxldGUobnVtUGFnZXMgLSAxKTsKICAgICAgYXdhaXQgdGhpcy5jbGVhbnVwKCk7CiAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBfY29yZV91dGlscy5YUmVmRW50cnlFeGNlcHRpb24gJiYgIXJlY292ZXJ5TW9kZSkgewogICAgICAgIHRocm93IG5ldyBfY29yZV91dGlscy5YUmVmUGFyc2VFeGNlcHRpb24oKTsKICAgICAgfQogICAgICAoMCwgX3V0aWwud2FybikoYGNoZWNrTGFzdFBhZ2UgLSBpbnZhbGlkIC9QYWdlcyB0cmVlIC9Db3VudDogJHtudW1QYWdlc30uYCk7CiAgICAgIGxldCBwYWdlc1RyZWU7CiAgICAgIHRyeSB7CiAgICAgICAgcGFnZXNUcmVlID0gYXdhaXQgY2F0YWxvZy5nZXRBbGxQYWdlRGljdHMocmVjb3ZlcnlNb2RlKTsKICAgICAgfSBjYXRjaCAocmVhc29uQWxsKSB7CiAgICAgICAgaWYgKHJlYXNvbkFsbCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLlhSZWZFbnRyeUV4Y2VwdGlvbiAmJiAhcmVjb3ZlcnlNb2RlKSB7CiAgICAgICAgICB0aHJvdyBuZXcgX2NvcmVfdXRpbHMuWFJlZlBhcnNlRXhjZXB0aW9uKCk7CiAgICAgICAgfQogICAgICAgIGNhdGFsb2cuc2V0QWN0dWFsTnVtUGFnZXMoMSk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGZvciAoY29uc3QgW3BhZ2VJbmRleCwgW3BhZ2VEaWN0LCByZWZdXSBvZiBwYWdlc1RyZWUpIHsKICAgICAgICBsZXQgcHJvbWlzZTsKICAgICAgICBpZiAocGFnZURpY3QgaW5zdGFuY2VvZiBFcnJvcikgewogICAgICAgICAgcHJvbWlzZSA9IFByb21pc2UucmVqZWN0KHBhZ2VEaWN0KTsKICAgICAgICAgIHByb21pc2UuY2F0Y2goKCkgPT4ge30pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBwcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKG5ldyBQYWdlKHsKICAgICAgICAgICAgcGRmTWFuYWdlciwKICAgICAgICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICAgICAgICBwYWdlSW5kZXgsCiAgICAgICAgICAgIHBhZ2VEaWN0LAogICAgICAgICAgICByZWYsCiAgICAgICAgICAgIGdsb2JhbElkRmFjdG9yeTogdGhpcy5fZ2xvYmFsSWRGYWN0b3J5LAogICAgICAgICAgICBmb250Q2FjaGU6IGNhdGFsb2cuZm9udENhY2hlLAogICAgICAgICAgICBidWlsdEluQ01hcENhY2hlOiBjYXRhbG9nLmJ1aWx0SW5DTWFwQ2FjaGUsCiAgICAgICAgICAgIHN0YW5kYXJkRm9udERhdGFDYWNoZTogY2F0YWxvZy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUsCiAgICAgICAgICAgIGdsb2JhbEltYWdlQ2FjaGU6IGNhdGFsb2cuZ2xvYmFsSW1hZ2VDYWNoZSwKICAgICAgICAgICAgbm9uQmxlbmRNb2Rlc1NldDogY2F0YWxvZy5ub25CbGVuZE1vZGVzU2V0LAogICAgICAgICAgICB4ZmFGYWN0b3J5OiBudWxsCiAgICAgICAgICB9KSk7CiAgICAgICAgfQogICAgICAgIHRoaXMuX3BhZ2VQcm9taXNlcy5zZXQocGFnZUluZGV4LCBwcm9taXNlKTsKICAgICAgfQogICAgICBjYXRhbG9nLnNldEFjdHVhbE51bVBhZ2VzKHBhZ2VzVHJlZS5zaXplKTsKICAgIH0KICB9CiAgZm9udEZhbGxiYWNrKGlkLCBoYW5kbGVyKSB7CiAgICByZXR1cm4gdGhpcy5jYXRhbG9nLmZvbnRGYWxsYmFjayhpZCwgaGFuZGxlcik7CiAgfQogIGFzeW5jIGNsZWFudXAoKSB7CiAgICBsZXQgbWFudWFsbHlUcmlnZ2VyZWQgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgcmV0dXJuIHRoaXMuY2F0YWxvZyA/IHRoaXMuY2F0YWxvZy5jbGVhbnVwKG1hbnVhbGx5VHJpZ2dlcmVkKSA6ICgwLCBfY2xlYW51cF9oZWxwZXIuY2xlYXJHbG9iYWxDYWNoZXMpKCk7CiAgfQogIF9jb2xsZWN0RmllbGRPYmplY3RzKG5hbWUsIGZpZWxkUmVmLCBwcm9taXNlcykgewogICAgY29uc3QgZmllbGQgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihmaWVsZFJlZik7CiAgICBpZiAoZmllbGQuaGFzKCJUIikpIHsKICAgICAgY29uc3QgcGFydE5hbWUgPSAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGZpZWxkLmdldCgiVCIpKTsKICAgICAgaWYgKG5hbWUgPT09ICIiKSB7CiAgICAgICAgbmFtZSA9IHBhcnROYW1lOwogICAgICB9IGVsc2UgewogICAgICAgIG5hbWUgPSBgJHtuYW1lfS4ke3BhcnROYW1lfWA7CiAgICAgIH0KICAgIH0KICAgIGlmICghcHJvbWlzZXMuaGFzKG5hbWUpKSB7CiAgICAgIHByb21pc2VzLnNldChuYW1lLCBbXSk7CiAgICB9CiAgICBwcm9taXNlcy5nZXQobmFtZSkucHVzaChfYW5ub3RhdGlvbi5Bbm5vdGF0aW9uRmFjdG9yeS5jcmVhdGUodGhpcy54cmVmLCBmaWVsZFJlZiwgdGhpcy5wZGZNYW5hZ2VyLCB0aGlzLl9sb2NhbElkRmFjdG9yeSwgdHJ1ZSkudGhlbihhbm5vdGF0aW9uID0+IGFubm90YXRpb24gJiYgYW5ub3RhdGlvbi5nZXRGaWVsZE9iamVjdCgpKS5jYXRjaChmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKShgX2NvbGxlY3RGaWVsZE9iamVjdHM6ICIke3JlYXNvbn0iLmApOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0pKTsKICAgIGlmIChmaWVsZC5oYXMoIktpZHMiKSkgewogICAgICBjb25zdCBraWRzID0gZmllbGQuZ2V0KCJLaWRzIik7CiAgICAgIGZvciAoY29uc3Qga2lkIG9mIGtpZHMpIHsKICAgICAgICB0aGlzLl9jb2xsZWN0RmllbGRPYmplY3RzKG5hbWUsIGtpZCwgcHJvbWlzZXMpOwogICAgICB9CiAgICB9CiAgfQogIGdldCBmaWVsZE9iamVjdHMoKSB7CiAgICBpZiAoIXRoaXMuZm9ybUluZm8uaGFzRmllbGRzKSB7CiAgICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiZmllbGRPYmplY3RzIiwgUHJvbWlzZS5yZXNvbHZlKG51bGwpKTsKICAgIH0KICAgIGNvbnN0IGFsbEZpZWxkcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBjb25zdCBmaWVsZFByb21pc2VzID0gbmV3IE1hcCgpOwogICAgZm9yIChjb25zdCBmaWVsZFJlZiBvZiB0aGlzLmNhdGFsb2cuYWNyb0Zvcm0uZ2V0KCJGaWVsZHMiKSkgewogICAgICB0aGlzLl9jb2xsZWN0RmllbGRPYmplY3RzKCIiLCBmaWVsZFJlZiwgZmllbGRQcm9taXNlcyk7CiAgICB9CiAgICBjb25zdCBhbGxQcm9taXNlcyA9IFtdOwogICAgZm9yIChjb25zdCBbbmFtZSwgcHJvbWlzZXNdIG9mIGZpZWxkUHJvbWlzZXMpIHsKICAgICAgYWxsUHJvbWlzZXMucHVzaChQcm9taXNlLmFsbChwcm9taXNlcykudGhlbihmaWVsZHMgPT4gewogICAgICAgIGZpZWxkcyA9IGZpZWxkcy5maWx0ZXIoZmllbGQgPT4gISFmaWVsZCk7CiAgICAgICAgaWYgKGZpZWxkcy5sZW5ndGggPiAwKSB7CiAgICAgICAgICBhbGxGaWVsZHNbbmFtZV0gPSBmaWVsZHM7CiAgICAgICAgfQogICAgICB9KSk7CiAgICB9CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImZpZWxkT2JqZWN0cyIsIFByb21pc2UuYWxsKGFsbFByb21pc2VzKS50aGVuKCgpID0+IGFsbEZpZWxkcykpOwogIH0KICBnZXQgaGFzSlNBY3Rpb25zKCkgewogICAgY29uc3QgcHJvbWlzZSA9IHRoaXMucGRmTWFuYWdlci5lbnN1cmVEb2MoIl9wYXJzZUhhc0pTQWN0aW9ucyIpOwogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJoYXNKU0FjdGlvbnMiLCBwcm9taXNlKTsKICB9CiAgYXN5bmMgX3BhcnNlSGFzSlNBY3Rpb25zKCkgewogICAgY29uc3QgW2NhdGFsb2dKc0FjdGlvbnMsIGZpZWxkT2JqZWN0c10gPSBhd2FpdCBQcm9taXNlLmFsbChbdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImpzQWN0aW9ucyIpLCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlRG9jKCJmaWVsZE9iamVjdHMiKV0pOwogICAgaWYgKGNhdGFsb2dKc0FjdGlvbnMpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBpZiAoZmllbGRPYmplY3RzKSB7CiAgICAgIHJldHVybiBPYmplY3QudmFsdWVzKGZpZWxkT2JqZWN0cykuc29tZShmaWVsZE9iamVjdCA9PiBmaWVsZE9iamVjdC5zb21lKG9iamVjdCA9PiBvYmplY3QuYWN0aW9ucyAhPT0gbnVsbCkpOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KICBnZXQgY2FsY3VsYXRpb25PcmRlcklkcygpIHsKICAgIGNvbnN0IGFjcm9Gb3JtID0gdGhpcy5jYXRhbG9nLmFjcm9Gb3JtOwogICAgaWYgKCFhY3JvRm9ybSB8fCAhYWNyb0Zvcm0uaGFzKCJDTyIpKSB7CiAgICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiY2FsY3VsYXRpb25PcmRlcklkcyIsIG51bGwpOwogICAgfQogICAgY29uc3QgY2FsY3VsYXRpb25PcmRlciA9IGFjcm9Gb3JtLmdldCgiQ08iKTsKICAgIGlmICghQXJyYXkuaXNBcnJheShjYWxjdWxhdGlvbk9yZGVyKSB8fCBjYWxjdWxhdGlvbk9yZGVyLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImNhbGN1bGF0aW9uT3JkZXJJZHMiLCBudWxsKTsKICAgIH0KICAgIGNvbnN0IGlkcyA9IFtdOwogICAgZm9yIChjb25zdCBpZCBvZiBjYWxjdWxhdGlvbk9yZGVyKSB7CiAgICAgIGlmIChpZCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgIGlkcy5wdXNoKGlkLnRvU3RyaW5nKCkpOwogICAgICB9CiAgICB9CiAgICBpZiAoaWRzLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImNhbGN1bGF0aW9uT3JkZXJJZHMiLCBudWxsKTsKICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiY2FsY3VsYXRpb25PcmRlcklkcyIsIGlkcyk7CiAgfQp9CmV4cG9ydHMuUERGRG9jdW1lbnQgPSBQREZEb2N1bWVudDsKCi8qKiovIH0pLAovKiAxNDYgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlBvcHVwQW5ub3RhdGlvbiA9IGV4cG9ydHMuTWFya3VwQW5ub3RhdGlvbiA9IGV4cG9ydHMuQW5ub3RhdGlvbkZhY3RvcnkgPSBleHBvcnRzLkFubm90YXRpb25Cb3JkZXJTdHlsZSA9IGV4cG9ydHMuQW5ub3RhdGlvbiA9IHZvaWQgMDsKZXhwb3J0cy5nZXRRdWFkUG9pbnRzID0gZ2V0UXVhZFBvaW50czsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX2RlZmF1bHRfYXBwZWFyYW5jZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQ3KTsKdmFyIF9wcmltaXRpdmVzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDApOwp2YXIgX3dyaXRlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMjAwKTsKdmFyIF9iYXNlX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQxKTsKdmFyIF9iaWRpID0gX193X3BkZmpzX3JlcXVpcmVfXygxOTUpOwp2YXIgX2NhdGFsb2cgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIwNCk7CnZhciBfY29sb3JzcGFjZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQ4KTsKdmFyIF9maWxlX3NwZWMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIwNyk7CnZhciBfb2JqZWN0X2xvYWRlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMjEwKTsKdmFyIF9vcGVyYXRvcl9saXN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxOTgpOwp2YXIgX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQ0KTsKdmFyIF9mYWN0b3J5ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTEpOwpjbGFzcyBBbm5vdGF0aW9uRmFjdG9yeSB7CiAgc3RhdGljIGNyZWF0ZSh4cmVmLCByZWYsIHBkZk1hbmFnZXIsIGlkRmFjdG9yeSwgY29sbGVjdEZpZWxkcykgewogICAgcmV0dXJuIFByb21pc2UuYWxsKFtwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImFjcm9Gb3JtIiksIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiYmFzZVVybCIpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImF0dGFjaG1lbnRzIiksIHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJ4ZmFEYXRhc2V0cyIpLCBjb2xsZWN0RmllbGRzID8gdGhpcy5fZ2V0UGFnZUluZGV4KHhyZWYsIHJlZiwgcGRmTWFuYWdlcikgOiAtMV0pLnRoZW4oX3JlZiA9PiB7CiAgICAgIGxldCBbYWNyb0Zvcm0sIGJhc2VVcmwsIGF0dGFjaG1lbnRzLCB4ZmFEYXRhc2V0cywgcGFnZUluZGV4XSA9IF9yZWY7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZSh0aGlzLCAiX2NyZWF0ZSIsIFt4cmVmLCByZWYsIHBkZk1hbmFnZXIsIGlkRmFjdG9yeSwgYWNyb0Zvcm0sIGF0dGFjaG1lbnRzLCB4ZmFEYXRhc2V0cywgY29sbGVjdEZpZWxkcywgcGFnZUluZGV4XSk7CiAgICB9KTsKICB9CiAgc3RhdGljIF9jcmVhdGUoeHJlZiwgcmVmLCBwZGZNYW5hZ2VyLCBpZEZhY3RvcnksIGFjcm9Gb3JtKSB7CiAgICBsZXQgYXR0YWNobWVudHMgPSBhcmd1bWVudHMubGVuZ3RoID4gNSAmJiBhcmd1bWVudHNbNV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1s1XSA6IG51bGw7CiAgICBsZXQgeGZhRGF0YXNldHMgPSBhcmd1bWVudHMubGVuZ3RoID4gNiA/IGFyZ3VtZW50c1s2XSA6IHVuZGVmaW5lZDsKICAgIGxldCBjb2xsZWN0RmllbGRzID0gYXJndW1lbnRzLmxlbmd0aCA+IDcgPyBhcmd1bWVudHNbN10gOiB1bmRlZmluZWQ7CiAgICBsZXQgcGFnZUluZGV4ID0gYXJndW1lbnRzLmxlbmd0aCA+IDggJiYgYXJndW1lbnRzWzhdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbOF0gOiAtMTsKICAgIGNvbnN0IGRpY3QgPSB4cmVmLmZldGNoSWZSZWYocmVmKTsKICAgIGlmICghKGRpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfQogICAgY29uc3QgaWQgPSByZWYgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYgPyByZWYudG9TdHJpbmcoKSA6IGBhbm5vdF8ke2lkRmFjdG9yeS5jcmVhdGVPYmpJZCgpfWA7CiAgICBsZXQgc3VidHlwZSA9IGRpY3QuZ2V0KCJTdWJ0eXBlIik7CiAgICBzdWJ0eXBlID0gc3VidHlwZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUgPyBzdWJ0eXBlLm5hbWUgOiBudWxsOwogICAgY29uc3QgYWNyb0Zvcm1EaWN0ID0gYWNyb0Zvcm0gaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0ID8gYWNyb0Zvcm0gOiBfcHJpbWl0aXZlcy5EaWN0LmVtcHR5OwogICAgY29uc3QgcGFyYW1ldGVycyA9IHsKICAgICAgeHJlZiwKICAgICAgcmVmLAogICAgICBkaWN0LAogICAgICBzdWJ0eXBlLAogICAgICBpZCwKICAgICAgcGRmTWFuYWdlciwKICAgICAgYWNyb0Zvcm06IGFjcm9Gb3JtRGljdCwKICAgICAgYXR0YWNobWVudHMsCiAgICAgIHhmYURhdGFzZXRzLAogICAgICBjb2xsZWN0RmllbGRzLAogICAgICBuZWVkQXBwZWFyYW5jZXM6ICFjb2xsZWN0RmllbGRzICYmIGFjcm9Gb3JtRGljdC5nZXQoIk5lZWRBcHBlYXJhbmNlcyIpID09PSB0cnVlLAogICAgICBwYWdlSW5kZXgsCiAgICAgIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkOiBwZGZNYW5hZ2VyLmV2YWx1YXRvck9wdGlvbnMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQKICAgIH07CiAgICBzd2l0Y2ggKHN1YnR5cGUpIHsKICAgICAgY2FzZSAiTGluayI6CiAgICAgICAgcmV0dXJuIG5ldyBMaW5rQW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiVGV4dCI6CiAgICAgICAgcmV0dXJuIG5ldyBUZXh0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiV2lkZ2V0IjoKICAgICAgICBsZXQgZmllbGRUeXBlID0gKDAsIF9jb3JlX3V0aWxzLmdldEluaGVyaXRhYmxlUHJvcGVydHkpKHsKICAgICAgICAgIGRpY3QsCiAgICAgICAgICBrZXk6ICJGVCIKICAgICAgICB9KTsKICAgICAgICBmaWVsZFR5cGUgPSBmaWVsZFR5cGUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lID8gZmllbGRUeXBlLm5hbWUgOiBudWxsOwogICAgICAgIHN3aXRjaCAoZmllbGRUeXBlKSB7CiAgICAgICAgICBjYXNlICJUeCI6CiAgICAgICAgICAgIHJldHVybiBuZXcgVGV4dFdpZGdldEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgICAgICBjYXNlICJCdG4iOgogICAgICAgICAgICByZXR1cm4gbmV3IEJ1dHRvbldpZGdldEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgICAgICBjYXNlICJDaCI6CiAgICAgICAgICAgIHJldHVybiBuZXcgQ2hvaWNlV2lkZ2V0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgICAgIGNhc2UgIlNpZyI6CiAgICAgICAgICAgIHJldHVybiBuZXcgU2lnbmF0dXJlV2lkZ2V0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgICB9CiAgICAgICAgKDAsIF91dGlsLndhcm4pKGBVbmltcGxlbWVudGVkIHdpZGdldCBmaWVsZCB0eXBlICIke2ZpZWxkVHlwZX0iLCBgICsgImZhbGxpbmcgYmFjayB0byBiYXNlIGZpZWxkIHR5cGUuIik7CiAgICAgICAgcmV0dXJuIG5ldyBXaWRnZXRBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJQb3B1cCI6CiAgICAgICAgcmV0dXJuIG5ldyBQb3B1cEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIkZyZWVUZXh0IjoKICAgICAgICByZXR1cm4gbmV3IEZyZWVUZXh0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiTGluZSI6CiAgICAgICAgcmV0dXJuIG5ldyBMaW5lQW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiU3F1YXJlIjoKICAgICAgICByZXR1cm4gbmV3IFNxdWFyZUFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIkNpcmNsZSI6CiAgICAgICAgcmV0dXJuIG5ldyBDaXJjbGVBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJQb2x5TGluZSI6CiAgICAgICAgcmV0dXJuIG5ldyBQb2x5bGluZUFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIlBvbHlnb24iOgogICAgICAgIHJldHVybiBuZXcgUG9seWdvbkFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIkNhcmV0IjoKICAgICAgICByZXR1cm4gbmV3IENhcmV0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiSW5rIjoKICAgICAgICByZXR1cm4gbmV3IElua0Fubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIkhpZ2hsaWdodCI6CiAgICAgICAgcmV0dXJuIG5ldyBIaWdobGlnaHRBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJVbmRlcmxpbmUiOgogICAgICAgIHJldHVybiBuZXcgVW5kZXJsaW5lQW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiU3F1aWdnbHkiOgogICAgICAgIHJldHVybiBuZXcgU3F1aWdnbHlBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJTdHJpa2VPdXQiOgogICAgICAgIHJldHVybiBuZXcgU3RyaWtlT3V0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiU3RhbXAiOgogICAgICAgIHJldHVybiBuZXcgU3RhbXBBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJGaWxlQXR0YWNobWVudCI6CiAgICAgICAgcmV0dXJuIG5ldyBGaWxlQXR0YWNobWVudEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgaWYgKCFjb2xsZWN0RmllbGRzKSB7CiAgICAgICAgICBpZiAoIXN1YnR5cGUpIHsKICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJBbm5vdGF0aW9uIGlzIG1pc3NpbmcgdGhlIHJlcXVpcmVkIC9TdWJ0eXBlLiIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBVbmltcGxlbWVudGVkIGFubm90YXRpb24gdHlwZSAiJHtzdWJ0eXBlfSIsIGAgKyAiZmFsbGluZyBiYWNrIHRvIGJhc2UgYW5ub3RhdGlvbi4iKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgfQogIH0KICBzdGF0aWMgYXN5bmMgX2dldFBhZ2VJbmRleCh4cmVmLCByZWYsIHBkZk1hbmFnZXIpIHsKICAgIHRyeSB7CiAgICAgIGNvbnN0IGFubm90RGljdCA9IGF3YWl0IHhyZWYuZmV0Y2hJZlJlZkFzeW5jKHJlZik7CiAgICAgIGlmICghKGFubm90RGljdCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgICAgcmV0dXJuIC0xOwogICAgICB9CiAgICAgIGNvbnN0IHBhZ2VSZWYgPSBhbm5vdERpY3QuZ2V0UmF3KCJQIik7CiAgICAgIGlmICghKHBhZ2VSZWYgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpKSB7CiAgICAgICAgcmV0dXJuIC0xOwogICAgICB9CiAgICAgIGNvbnN0IHBhZ2VJbmRleCA9IGF3YWl0IHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiZ2V0UGFnZUluZGV4IiwgW3BhZ2VSZWZdKTsKICAgICAgcmV0dXJuIHBhZ2VJbmRleDsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICgwLCBfdXRpbC53YXJuKShgX2dldFBhZ2VJbmRleDogIiR7ZXh9Ii5gKTsKICAgICAgcmV0dXJuIC0xOwogICAgfQogIH0KICBzdGF0aWMgYXN5bmMgc2F2ZU5ld0Fubm90YXRpb25zKGV2YWx1YXRvciwgdGFzaywgYW5ub3RhdGlvbnMpIHsKICAgIGNvbnN0IHhyZWYgPSBldmFsdWF0b3IueHJlZjsKICAgIGxldCBiYXNlRm9udFJlZjsKICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9IFtdOwogICAgY29uc3QgcHJvbWlzZXMgPSBbXTsKICAgIGZvciAoY29uc3QgYW5ub3RhdGlvbiBvZiBhbm5vdGF0aW9ucykgewogICAgICBzd2l0Y2ggKGFubm90YXRpb24uYW5ub3RhdGlvblR5cGUpIHsKICAgICAgICBjYXNlIF91dGlsLkFubm90YXRpb25FZGl0b3JUeXBlLkZSRUVURVhUOgogICAgICAgICAgaWYgKCFiYXNlRm9udFJlZikgewogICAgICAgICAgICBjb25zdCBiYXNlRm9udCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHhyZWYpOwogICAgICAgICAgICBiYXNlRm9udC5zZXQoIkJhc2VGb250IiwgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIkhlbHZldGljYSIpKTsKICAgICAgICAgICAgYmFzZUZvbnQuc2V0KCJUeXBlIiwgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIkZvbnQiKSk7CiAgICAgICAgICAgIGJhc2VGb250LnNldCgiU3VidHlwZSIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJUeXBlMSIpKTsKICAgICAgICAgICAgYmFzZUZvbnQuc2V0KCJFbmNvZGluZyIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJXaW5BbnNpRW5jb2RpbmciKSk7CiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlciA9IFtdOwogICAgICAgICAgICBiYXNlRm9udFJlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICAgICAgICAgICgwLCBfd3JpdGVyLndyaXRlT2JqZWN0KShiYXNlRm9udFJlZiwgYmFzZUZvbnQsIGJ1ZmZlciwgbnVsbCk7CiAgICAgICAgICAgIGRlcGVuZGVuY2llcy5wdXNoKHsKICAgICAgICAgICAgICByZWY6IGJhc2VGb250UmVmLAogICAgICAgICAgICAgIGRhdGE6IGJ1ZmZlci5qb2luKCIiKQogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIHByb21pc2VzLnB1c2goRnJlZVRleHRBbm5vdGF0aW9uLmNyZWF0ZU5ld0Fubm90YXRpb24oeHJlZiwgYW5ub3RhdGlvbiwgZGVwZW5kZW5jaWVzLCB7CiAgICAgICAgICAgIGV2YWx1YXRvciwKICAgICAgICAgICAgdGFzaywKICAgICAgICAgICAgYmFzZUZvbnRSZWYKICAgICAgICAgIH0pKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgX3V0aWwuQW5ub3RhdGlvbkVkaXRvclR5cGUuSU5LOgogICAgICAgICAgcHJvbWlzZXMucHVzaChJbmtBbm5vdGF0aW9uLmNyZWF0ZU5ld0Fubm90YXRpb24oeHJlZiwgYW5ub3RhdGlvbiwgZGVwZW5kZW5jaWVzKSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7CiAgICAgIGFubm90YXRpb25zOiBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyksCiAgICAgIGRlcGVuZGVuY2llcwogICAgfTsKICB9CiAgc3RhdGljIGFzeW5jIHByaW50TmV3QW5ub3RhdGlvbnMoZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9ucykgewogICAgaWYgKCFhbm5vdGF0aW9ucykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHhyZWYgPSBldmFsdWF0b3IueHJlZjsKICAgIGNvbnN0IHsKICAgICAgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQKICAgIH0gPSBldmFsdWF0b3Iub3B0aW9uczsKICAgIGNvbnN0IHByb21pc2VzID0gW107CiAgICBmb3IgKGNvbnN0IGFubm90YXRpb24gb2YgYW5ub3RhdGlvbnMpIHsKICAgICAgc3dpdGNoIChhbm5vdGF0aW9uLmFubm90YXRpb25UeXBlKSB7CiAgICAgICAgY2FzZSBfdXRpbC5Bbm5vdGF0aW9uRWRpdG9yVHlwZS5GUkVFVEVYVDoKICAgICAgICAgIHByb21pc2VzLnB1c2goRnJlZVRleHRBbm5vdGF0aW9uLmNyZWF0ZU5ld1ByaW50QW5ub3RhdGlvbih4cmVmLCBhbm5vdGF0aW9uLCB7CiAgICAgICAgICAgIGV2YWx1YXRvciwKICAgICAgICAgICAgdGFzaywKICAgICAgICAgICAgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQKICAgICAgICAgIH0pKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgX3V0aWwuQW5ub3RhdGlvbkVkaXRvclR5cGUuSU5LOgogICAgICAgICAgcHJvbWlzZXMucHVzaChJbmtBbm5vdGF0aW9uLmNyZWF0ZU5ld1ByaW50QW5ub3RhdGlvbih4cmVmLCBhbm5vdGF0aW9uLCB7CiAgICAgICAgICAgIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkCiAgICAgICAgICB9KSk7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTsKICB9Cn0KZXhwb3J0cy5Bbm5vdGF0aW9uRmFjdG9yeSA9IEFubm90YXRpb25GYWN0b3J5OwpmdW5jdGlvbiBnZXRSZ2JDb2xvcihjb2xvcikgewogIGxldCBkZWZhdWx0Q29sb3IgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IG5ldyBVaW50OENsYW1wZWRBcnJheSgzKTsKICBpZiAoIUFycmF5LmlzQXJyYXkoY29sb3IpKSB7CiAgICByZXR1cm4gZGVmYXVsdENvbG9yOwogIH0KICBjb25zdCByZ2JDb2xvciA9IGRlZmF1bHRDb2xvciB8fCBuZXcgVWludDhDbGFtcGVkQXJyYXkoMyk7CiAgc3dpdGNoIChjb2xvci5sZW5ndGgpIHsKICAgIGNhc2UgMDoKICAgICAgcmV0dXJuIG51bGw7CiAgICBjYXNlIDE6CiAgICAgIF9jb2xvcnNwYWNlLkNvbG9yU3BhY2Uuc2luZ2xldG9ucy5ncmF5LmdldFJnYkl0ZW0oY29sb3IsIDAsIHJnYkNvbG9yLCAwKTsKICAgICAgcmV0dXJuIHJnYkNvbG9yOwogICAgY2FzZSAzOgogICAgICBfY29sb3JzcGFjZS5Db2xvclNwYWNlLnNpbmdsZXRvbnMucmdiLmdldFJnYkl0ZW0oY29sb3IsIDAsIHJnYkNvbG9yLCAwKTsKICAgICAgcmV0dXJuIHJnYkNvbG9yOwogICAgY2FzZSA0OgogICAgICBfY29sb3JzcGFjZS5Db2xvclNwYWNlLnNpbmdsZXRvbnMuY215ay5nZXRSZ2JJdGVtKGNvbG9yLCAwLCByZ2JDb2xvciwgMCk7CiAgICAgIHJldHVybiByZ2JDb2xvcjsKICAgIGRlZmF1bHQ6CiAgICAgIHJldHVybiBkZWZhdWx0Q29sb3I7CiAgfQp9CmZ1bmN0aW9uIGdldFBkZkNvbG9yQXJyYXkoY29sb3IpIHsKICByZXR1cm4gQXJyYXkuZnJvbShjb2xvciwgYyA9PiBjIC8gMjU1KTsKfQpmdW5jdGlvbiBnZXRRdWFkUG9pbnRzKGRpY3QsIHJlY3QpIHsKICBjb25zdCBxdWFkUG9pbnRzID0gZGljdC5nZXRBcnJheSgiUXVhZFBvaW50cyIpOwogIGlmICghQXJyYXkuaXNBcnJheShxdWFkUG9pbnRzKSB8fCBxdWFkUG9pbnRzLmxlbmd0aCA9PT0gMCB8fCBxdWFkUG9pbnRzLmxlbmd0aCAlIDggPiAwKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgY29uc3QgcXVhZFBvaW50c0xpc3RzID0gW107CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gcXVhZFBvaW50cy5sZW5ndGggLyA4OyBpIDwgaWk7IGkrKykgewogICAgbGV0IG1pblggPSBJbmZpbml0eSwKICAgICAgbWF4WCA9IC1JbmZpbml0eSwKICAgICAgbWluWSA9IEluZmluaXR5LAogICAgICBtYXhZID0gLUluZmluaXR5OwogICAgZm9yIChsZXQgaiA9IGkgKiA4LCBqaiA9IGkgKiA4ICsgODsgaiA8IGpqOyBqICs9IDIpIHsKICAgICAgY29uc3QgeCA9IHF1YWRQb2ludHNbal07CiAgICAgIGNvbnN0IHkgPSBxdWFkUG9pbnRzW2ogKyAxXTsKICAgICAgbWluWCA9IE1hdGgubWluKHgsIG1pblgpOwogICAgICBtYXhYID0gTWF0aC5tYXgoeCwgbWF4WCk7CiAgICAgIG1pblkgPSBNYXRoLm1pbih5LCBtaW5ZKTsKICAgICAgbWF4WSA9IE1hdGgubWF4KHksIG1heFkpOwogICAgfQogICAgaWYgKHJlY3QgIT09IG51bGwgJiYgKG1pblggPCByZWN0WzBdIHx8IG1heFggPiByZWN0WzJdIHx8IG1pblkgPCByZWN0WzFdIHx8IG1heFkgPiByZWN0WzNdKSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIHF1YWRQb2ludHNMaXN0cy5wdXNoKFt7CiAgICAgIHg6IG1pblgsCiAgICAgIHk6IG1heFkKICAgIH0sIHsKICAgICAgeDogbWF4WCwKICAgICAgeTogbWF4WQogICAgfSwgewogICAgICB4OiBtaW5YLAogICAgICB5OiBtaW5ZCiAgICB9LCB7CiAgICAgIHg6IG1heFgsCiAgICAgIHk6IG1pblkKICAgIH1dKTsKICB9CiAgcmV0dXJuIHF1YWRQb2ludHNMaXN0czsKfQpmdW5jdGlvbiBnZXRUcmFuc2Zvcm1NYXRyaXgocmVjdCwgYmJveCwgbWF0cml4KSB7CiAgY29uc3QgW21pblgsIG1pblksIG1heFgsIG1heFldID0gX3V0aWwuVXRpbC5nZXRBeGlhbEFsaWduZWRCb3VuZGluZ0JveChiYm94LCBtYXRyaXgpOwogIGlmIChtaW5YID09PSBtYXhYIHx8IG1pblkgPT09IG1heFkpIHsKICAgIHJldHVybiBbMSwgMCwgMCwgMSwgcmVjdFswXSwgcmVjdFsxXV07CiAgfQogIGNvbnN0IHhSYXRpbyA9IChyZWN0WzJdIC0gcmVjdFswXSkgLyAobWF4WCAtIG1pblgpOwogIGNvbnN0IHlSYXRpbyA9IChyZWN0WzNdIC0gcmVjdFsxXSkgLyAobWF4WSAtIG1pblkpOwogIHJldHVybiBbeFJhdGlvLCAwLCAwLCB5UmF0aW8sIHJlY3RbMF0gLSBtaW5YICogeFJhdGlvLCByZWN0WzFdIC0gbWluWSAqIHlSYXRpb107Cn0KY2xhc3MgQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBjb25zdCB7CiAgICAgIGRpY3QsCiAgICAgIHhyZWYKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLnNldFRpdGxlKGRpY3QuZ2V0KCJUIikpOwogICAgdGhpcy5zZXRDb250ZW50cyhkaWN0LmdldCgiQ29udGVudHMiKSk7CiAgICB0aGlzLnNldE1vZGlmaWNhdGlvbkRhdGUoZGljdC5nZXQoIk0iKSk7CiAgICB0aGlzLnNldEZsYWdzKGRpY3QuZ2V0KCJGIikpOwogICAgdGhpcy5zZXRSZWN0YW5nbGUoZGljdC5nZXRBcnJheSgiUmVjdCIpKTsKICAgIHRoaXMuc2V0Q29sb3IoZGljdC5nZXRBcnJheSgiQyIpKTsKICAgIHRoaXMuc2V0Qm9yZGVyU3R5bGUoZGljdCk7CiAgICB0aGlzLnNldEFwcGVhcmFuY2UoZGljdCk7CiAgICB0aGlzLnNldE9wdGlvbmFsQ29udGVudChkaWN0KTsKICAgIGNvbnN0IE1LID0gZGljdC5nZXQoIk1LIik7CiAgICB0aGlzLnNldEJvcmRlckFuZEJhY2tncm91bmRDb2xvcnMoTUspOwogICAgdGhpcy5zZXRSb3RhdGlvbihNSyk7CiAgICB0aGlzLl9zdHJlYW1zID0gW107CiAgICBpZiAodGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmFwcGVhcmFuY2UpOwogICAgfQogICAgY29uc3QgaXNMb2NrZWQgPSAhISh0aGlzLmZsYWdzICYgX3V0aWwuQW5ub3RhdGlvbkZsYWcuTE9DS0VEKTsKICAgIGNvbnN0IGlzQ29udGVudExvY2tlZCA9ICEhKHRoaXMuZmxhZ3MgJiBfdXRpbC5Bbm5vdGF0aW9uRmxhZy5MT0NLRURDT05URU5UUyk7CiAgICB0aGlzLmRhdGEgPSB7CiAgICAgIGFubm90YXRpb25GbGFnczogdGhpcy5mbGFncywKICAgICAgYm9yZGVyU3R5bGU6IHRoaXMuYm9yZGVyU3R5bGUsCiAgICAgIGNvbG9yOiB0aGlzLmNvbG9yLAogICAgICBiYWNrZ3JvdW5kQ29sb3I6IHRoaXMuYmFja2dyb3VuZENvbG9yLAogICAgICBib3JkZXJDb2xvcjogdGhpcy5ib3JkZXJDb2xvciwKICAgICAgcm90YXRpb246IHRoaXMucm90YXRpb24sCiAgICAgIGNvbnRlbnRzT2JqOiB0aGlzLl9jb250ZW50cywKICAgICAgaGFzQXBwZWFyYW5jZTogISF0aGlzLmFwcGVhcmFuY2UsCiAgICAgIGlkOiBwYXJhbXMuaWQsCiAgICAgIG1vZGlmaWNhdGlvbkRhdGU6IHRoaXMubW9kaWZpY2F0aW9uRGF0ZSwKICAgICAgcmVjdDogdGhpcy5yZWN0YW5nbGUsCiAgICAgIHN1YnR5cGU6IHBhcmFtcy5zdWJ0eXBlLAogICAgICBoYXNPd25DYW52YXM6IGZhbHNlLAogICAgICBub1JvdGF0ZTogISEodGhpcy5mbGFncyAmIF91dGlsLkFubm90YXRpb25GbGFnLk5PUk9UQVRFKSwKICAgICAgbm9IVE1MOiBpc0xvY2tlZCAmJiBpc0NvbnRlbnRMb2NrZWQKICAgIH07CiAgICBpZiAocGFyYW1zLmNvbGxlY3RGaWVsZHMpIHsKICAgICAgY29uc3Qga2lkcyA9IGRpY3QuZ2V0KCJLaWRzIik7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KGtpZHMpKSB7CiAgICAgICAgY29uc3Qga2lkSWRzID0gW107CiAgICAgICAgZm9yIChjb25zdCBraWQgb2Yga2lkcykgewogICAgICAgICAgaWYgKGtpZCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgICAgICBraWRJZHMucHVzaChraWQudG9TdHJpbmcoKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChraWRJZHMubGVuZ3RoICE9PSAwKSB7CiAgICAgICAgICB0aGlzLmRhdGEua2lkSWRzID0ga2lkSWRzOwogICAgICAgIH0KICAgICAgfQogICAgICB0aGlzLmRhdGEuYWN0aW9ucyA9ICgwLCBfY29yZV91dGlscy5jb2xsZWN0QWN0aW9ucykoeHJlZiwgZGljdCwgX3V0aWwuQW5ub3RhdGlvbkFjdGlvbkV2ZW50VHlwZSk7CiAgICAgIHRoaXMuZGF0YS5maWVsZE5hbWUgPSB0aGlzLl9jb25zdHJ1Y3RGaWVsZE5hbWUoZGljdCk7CiAgICAgIHRoaXMuZGF0YS5wYWdlSW5kZXggPSBwYXJhbXMucGFnZUluZGV4OwogICAgfQogICAgdGhpcy5faXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgPSBwYXJhbXMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQ7CiAgICB0aGlzLl9mYWxsYmFja0ZvbnREaWN0ID0gbnVsbDsKICAgIHRoaXMuX25lZWRBcHBlYXJhbmNlcyA9IGZhbHNlOwogIH0KICBfaGFzRmxhZyhmbGFncywgZmxhZykgewogICAgcmV0dXJuICEhKGZsYWdzICYgZmxhZyk7CiAgfQogIF9pc1ZpZXdhYmxlKGZsYWdzKSB7CiAgICByZXR1cm4gIXRoaXMuX2hhc0ZsYWcoZmxhZ3MsIF91dGlsLkFubm90YXRpb25GbGFnLklOVklTSUJMRSkgJiYgIXRoaXMuX2hhc0ZsYWcoZmxhZ3MsIF91dGlsLkFubm90YXRpb25GbGFnLk5PVklFVyk7CiAgfQogIF9pc1ByaW50YWJsZShmbGFncykgewogICAgcmV0dXJuIHRoaXMuX2hhc0ZsYWcoZmxhZ3MsIF91dGlsLkFubm90YXRpb25GbGFnLlBSSU5UKSAmJiAhdGhpcy5faGFzRmxhZyhmbGFncywgX3V0aWwuQW5ub3RhdGlvbkZsYWcuSU5WSVNJQkxFKTsKICB9CiAgbXVzdEJlVmlld2VkKGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBjb25zdCBzdG9yYWdlRW50cnkgPSBhbm5vdGF0aW9uU3RvcmFnZSAmJiBhbm5vdGF0aW9uU3RvcmFnZS5nZXQodGhpcy5kYXRhLmlkKTsKICAgIGlmIChzdG9yYWdlRW50cnkgJiYgc3RvcmFnZUVudHJ5LmhpZGRlbiAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiAhc3RvcmFnZUVudHJ5LmhpZGRlbjsKICAgIH0KICAgIHJldHVybiB0aGlzLnZpZXdhYmxlICYmICF0aGlzLl9oYXNGbGFnKHRoaXMuZmxhZ3MsIF91dGlsLkFubm90YXRpb25GbGFnLkhJRERFTik7CiAgfQogIG11c3RCZVByaW50ZWQoYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIGNvbnN0IHN0b3JhZ2VFbnRyeSA9IGFubm90YXRpb25TdG9yYWdlICYmIGFubm90YXRpb25TdG9yYWdlLmdldCh0aGlzLmRhdGEuaWQpOwogICAgaWYgKHN0b3JhZ2VFbnRyeSAmJiBzdG9yYWdlRW50cnkucHJpbnQgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gc3RvcmFnZUVudHJ5LnByaW50OwogICAgfQogICAgcmV0dXJuIHRoaXMucHJpbnRhYmxlOwogIH0KICBnZXQgdmlld2FibGUoKSB7CiAgICBpZiAodGhpcy5kYXRhLnF1YWRQb2ludHMgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKHRoaXMuZmxhZ3MgPT09IDApIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICByZXR1cm4gdGhpcy5faXNWaWV3YWJsZSh0aGlzLmZsYWdzKTsKICB9CiAgZ2V0IHByaW50YWJsZSgpIHsKICAgIGlmICh0aGlzLmRhdGEucXVhZFBvaW50cyA9PT0gbnVsbCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpcy5mbGFncyA9PT0gMCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICByZXR1cm4gdGhpcy5faXNQcmludGFibGUodGhpcy5mbGFncyk7CiAgfQogIF9wYXJzZVN0cmluZ0hlbHBlcihkYXRhKSB7CiAgICBjb25zdCBzdHIgPSB0eXBlb2YgZGF0YSA9PT0gInN0cmluZyIgPyAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGRhdGEpIDogIiI7CiAgICBjb25zdCBkaXIgPSBzdHIgJiYgKDAsIF9iaWRpLmJpZGkpKHN0cikuZGlyID09PSAicnRsIiA/ICJydGwiIDogImx0ciI7CiAgICByZXR1cm4gewogICAgICBzdHIsCiAgICAgIGRpcgogICAgfTsKICB9CiAgc2V0RGVmYXVsdEFwcGVhcmFuY2UocGFyYW1zKSB7CiAgICBjb25zdCBkZWZhdWx0QXBwZWFyYW5jZSA9ICgwLCBfY29yZV91dGlscy5nZXRJbmhlcml0YWJsZVByb3BlcnR5KSh7CiAgICAgIGRpY3Q6IHBhcmFtcy5kaWN0LAogICAgICBrZXk6ICJEQSIKICAgIH0pIHx8IHBhcmFtcy5hY3JvRm9ybS5nZXQoIkRBIik7CiAgICB0aGlzLl9kZWZhdWx0QXBwZWFyYW5jZSA9IHR5cGVvZiBkZWZhdWx0QXBwZWFyYW5jZSA9PT0gInN0cmluZyIgPyBkZWZhdWx0QXBwZWFyYW5jZSA6ICIiOwogICAgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YSA9ICgwLCBfZGVmYXVsdF9hcHBlYXJhbmNlLnBhcnNlRGVmYXVsdEFwcGVhcmFuY2UpKHRoaXMuX2RlZmF1bHRBcHBlYXJhbmNlKTsKICB9CiAgc2V0VGl0bGUodGl0bGUpIHsKICAgIHRoaXMuX3RpdGxlID0gdGhpcy5fcGFyc2VTdHJpbmdIZWxwZXIodGl0bGUpOwogIH0KICBzZXRDb250ZW50cyhjb250ZW50cykgewogICAgdGhpcy5fY29udGVudHMgPSB0aGlzLl9wYXJzZVN0cmluZ0hlbHBlcihjb250ZW50cyk7CiAgfQogIHNldE1vZGlmaWNhdGlvbkRhdGUobW9kaWZpY2F0aW9uRGF0ZSkgewogICAgdGhpcy5tb2RpZmljYXRpb25EYXRlID0gdHlwZW9mIG1vZGlmaWNhdGlvbkRhdGUgPT09ICJzdHJpbmciID8gbW9kaWZpY2F0aW9uRGF0ZSA6IG51bGw7CiAgfQogIHNldEZsYWdzKGZsYWdzKSB7CiAgICB0aGlzLmZsYWdzID0gTnVtYmVyLmlzSW50ZWdlcihmbGFncykgJiYgZmxhZ3MgPiAwID8gZmxhZ3MgOiAwOwogIH0KICBoYXNGbGFnKGZsYWcpIHsKICAgIHJldHVybiB0aGlzLl9oYXNGbGFnKHRoaXMuZmxhZ3MsIGZsYWcpOwogIH0KICBzZXRSZWN0YW5nbGUocmVjdGFuZ2xlKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheShyZWN0YW5nbGUpICYmIHJlY3RhbmdsZS5sZW5ndGggPT09IDQpIHsKICAgICAgdGhpcy5yZWN0YW5nbGUgPSBfdXRpbC5VdGlsLm5vcm1hbGl6ZVJlY3QocmVjdGFuZ2xlKTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMucmVjdGFuZ2xlID0gWzAsIDAsIDAsIDBdOwogICAgfQogIH0KICBzZXRDb2xvcihjb2xvcikgewogICAgdGhpcy5jb2xvciA9IGdldFJnYkNvbG9yKGNvbG9yKTsKICB9CiAgc2V0TGluZUVuZGluZ3MobGluZUVuZGluZ3MpIHsKICAgIHRoaXMubGluZUVuZGluZ3MgPSBbIk5vbmUiLCAiTm9uZSJdOwogICAgaWYgKEFycmF5LmlzQXJyYXkobGluZUVuZGluZ3MpICYmIGxpbmVFbmRpbmdzLmxlbmd0aCA9PT0gMikgewogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI7IGkrKykgewogICAgICAgIGNvbnN0IG9iaiA9IGxpbmVFbmRpbmdzW2ldOwogICAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgICAgICBzd2l0Y2ggKG9iai5uYW1lKSB7CiAgICAgICAgICAgIGNhc2UgIk5vbmUiOgogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICBjYXNlICJTcXVhcmUiOgogICAgICAgICAgICBjYXNlICJDaXJjbGUiOgogICAgICAgICAgICBjYXNlICJEaWFtb25kIjoKICAgICAgICAgICAgY2FzZSAiT3BlbkFycm93IjoKICAgICAgICAgICAgY2FzZSAiQ2xvc2VkQXJyb3ciOgogICAgICAgICAgICBjYXNlICJCdXR0IjoKICAgICAgICAgICAgY2FzZSAiUk9wZW5BcnJvdyI6CiAgICAgICAgICAgIGNhc2UgIlJDbG9zZWRBcnJvdyI6CiAgICAgICAgICAgIGNhc2UgIlNsYXNoIjoKICAgICAgICAgICAgICB0aGlzLmxpbmVFbmRpbmdzW2ldID0gb2JqLm5hbWU7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgICgwLCBfdXRpbC53YXJuKShgSWdub3JpbmcgaW52YWxpZCBsaW5lRW5kaW5nOiAke29ian1gKTsKICAgICAgfQogICAgfQogIH0KICBzZXRSb3RhdGlvbihtaykgewogICAgdGhpcy5yb3RhdGlvbiA9IDA7CiAgICBpZiAobWsgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgIGxldCBhbmdsZSA9IG1rLmdldCgiUiIpIHx8IDA7CiAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKGFuZ2xlKSAmJiBhbmdsZSAhPT0gMCkgewogICAgICAgIGFuZ2xlICU9IDM2MDsKICAgICAgICBpZiAoYW5nbGUgPCAwKSB7CiAgICAgICAgICBhbmdsZSArPSAzNjA7CiAgICAgICAgfQogICAgICAgIGlmIChhbmdsZSAlIDkwID09PSAwKSB7CiAgICAgICAgICB0aGlzLnJvdGF0aW9uID0gYW5nbGU7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQogIHNldEJvcmRlckFuZEJhY2tncm91bmRDb2xvcnMobWspIHsKICAgIGlmIChtayBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpIHsKICAgICAgdGhpcy5ib3JkZXJDb2xvciA9IGdldFJnYkNvbG9yKG1rLmdldEFycmF5KCJCQyIpLCBudWxsKTsKICAgICAgdGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSBnZXRSZ2JDb2xvcihtay5nZXRBcnJheSgiQkciKSwgbnVsbCk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmJvcmRlckNvbG9yID0gdGhpcy5iYWNrZ3JvdW5kQ29sb3IgPSBudWxsOwogICAgfQogIH0KICBzZXRCb3JkZXJTdHlsZShib3JkZXJTdHlsZSkgewogICAgdGhpcy5ib3JkZXJTdHlsZSA9IG5ldyBBbm5vdGF0aW9uQm9yZGVyU3R5bGUoKTsKICAgIGlmICghKGJvcmRlclN0eWxlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKGJvcmRlclN0eWxlLmhhcygiQlMiKSkgewogICAgICBjb25zdCBkaWN0ID0gYm9yZGVyU3R5bGUuZ2V0KCJCUyIpOwogICAgICBjb25zdCBkaWN0VHlwZSA9IGRpY3QuZ2V0KCJUeXBlIik7CiAgICAgIGlmICghZGljdFR5cGUgfHwgKDAsIF9wcmltaXRpdmVzLmlzTmFtZSkoZGljdFR5cGUsICJCb3JkZXIiKSkgewogICAgICAgIHRoaXMuYm9yZGVyU3R5bGUuc2V0V2lkdGgoZGljdC5nZXQoIlciKSwgdGhpcy5yZWN0YW5nbGUpOwogICAgICAgIHRoaXMuYm9yZGVyU3R5bGUuc2V0U3R5bGUoZGljdC5nZXQoIlMiKSk7CiAgICAgICAgdGhpcy5ib3JkZXJTdHlsZS5zZXREYXNoQXJyYXkoZGljdC5nZXRBcnJheSgiRCIpKTsKICAgICAgfQogICAgfSBlbHNlIGlmIChib3JkZXJTdHlsZS5oYXMoIkJvcmRlciIpKSB7CiAgICAgIGNvbnN0IGFycmF5ID0gYm9yZGVyU3R5bGUuZ2V0QXJyYXkoIkJvcmRlciIpOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShhcnJheSkgJiYgYXJyYXkubGVuZ3RoID49IDMpIHsKICAgICAgICB0aGlzLmJvcmRlclN0eWxlLnNldEhvcml6b250YWxDb3JuZXJSYWRpdXMoYXJyYXlbMF0pOwogICAgICAgIHRoaXMuYm9yZGVyU3R5bGUuc2V0VmVydGljYWxDb3JuZXJSYWRpdXMoYXJyYXlbMV0pOwogICAgICAgIHRoaXMuYm9yZGVyU3R5bGUuc2V0V2lkdGgoYXJyYXlbMl0sIHRoaXMucmVjdGFuZ2xlKTsKICAgICAgICBpZiAoYXJyYXkubGVuZ3RoID09PSA0KSB7CiAgICAgICAgICB0aGlzLmJvcmRlclN0eWxlLnNldERhc2hBcnJheShhcnJheVszXSwgdHJ1ZSk7CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmJvcmRlclN0eWxlLnNldFdpZHRoKDApOwogICAgfQogIH0KICBzZXRBcHBlYXJhbmNlKGRpY3QpIHsKICAgIHRoaXMuYXBwZWFyYW5jZSA9IG51bGw7CiAgICBjb25zdCBhcHBlYXJhbmNlU3RhdGVzID0gZGljdC5nZXQoIkFQIik7CiAgICBpZiAoIShhcHBlYXJhbmNlU3RhdGVzIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgbm9ybWFsQXBwZWFyYW5jZVN0YXRlID0gYXBwZWFyYW5jZVN0YXRlcy5nZXQoIk4iKTsKICAgIGlmIChub3JtYWxBcHBlYXJhbmNlU3RhdGUgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkgewogICAgICB0aGlzLmFwcGVhcmFuY2UgPSBub3JtYWxBcHBlYXJhbmNlU3RhdGU7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICghKG5vcm1hbEFwcGVhcmFuY2VTdGF0ZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGFzID0gZGljdC5nZXQoIkFTIik7CiAgICBpZiAoIShhcyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHx8ICFub3JtYWxBcHBlYXJhbmNlU3RhdGUuaGFzKGFzLm5hbWUpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGFwcGVhcmFuY2UgPSBub3JtYWxBcHBlYXJhbmNlU3RhdGUuZ2V0KGFzLm5hbWUpOwogICAgaWYgKGFwcGVhcmFuY2UgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkgewogICAgICB0aGlzLmFwcGVhcmFuY2UgPSBhcHBlYXJhbmNlOwogICAgfQogIH0KICBzZXRPcHRpb25hbENvbnRlbnQoZGljdCkgewogICAgdGhpcy5vYyA9IG51bGw7CiAgICBjb25zdCBvYyA9IGRpY3QuZ2V0KCJPQyIpOwogICAgaWYgKG9jIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICAoMCwgX3V0aWwud2FybikoInNldE9wdGlvbmFsQ29udGVudDogU3VwcG9ydCBmb3IgL05hbWUtZW50cnkgaXMgbm90IGltcGxlbWVudGVkLiIpOwogICAgfSBlbHNlIGlmIChvYyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpIHsKICAgICAgdGhpcy5vYyA9IG9jOwogICAgfQogIH0KICBsb2FkUmVzb3VyY2VzKGtleXMsIGFwcGVhcmFuY2UpIHsKICAgIHJldHVybiBhcHBlYXJhbmNlLmRpY3QuZ2V0QXN5bmMoIlJlc291cmNlcyIpLnRoZW4ocmVzb3VyY2VzID0+IHsKICAgICAgaWYgKCFyZXNvdXJjZXMpIHsKICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgICB9CiAgICAgIGNvbnN0IG9iamVjdExvYWRlciA9IG5ldyBfb2JqZWN0X2xvYWRlci5PYmplY3RMb2FkZXIocmVzb3VyY2VzLCBrZXlzLCByZXNvdXJjZXMueHJlZik7CiAgICAgIHJldHVybiBvYmplY3RMb2FkZXIubG9hZCgpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiByZXNvdXJjZXM7CiAgICAgIH0pOwogICAgfSk7CiAgfQogIGFzeW5jIGdldE9wZXJhdG9yTGlzdChldmFsdWF0b3IsIHRhc2ssIGludGVudCwgcmVuZGVyRm9ybXMsIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBjb25zdCBkYXRhID0gdGhpcy5kYXRhOwogICAgbGV0IGFwcGVhcmFuY2UgPSB0aGlzLmFwcGVhcmFuY2U7CiAgICBjb25zdCBpc1VzaW5nT3duQ2FudmFzID0gISEodGhpcy5kYXRhLmhhc093bkNhbnZhcyAmJiBpbnRlbnQgJiBfdXRpbC5SZW5kZXJpbmdJbnRlbnRGbGFnLkRJU1BMQVkpOwogICAgaWYgKCFhcHBlYXJhbmNlKSB7CiAgICAgIGlmICghaXNVc2luZ093bkNhbnZhcykgewogICAgICAgIHJldHVybiB7CiAgICAgICAgICBvcExpc3Q6IG5ldyBfb3BlcmF0b3JfbGlzdC5PcGVyYXRvckxpc3QoKSwKICAgICAgICAgIHNlcGFyYXRlRm9ybTogZmFsc2UsCiAgICAgICAgICBzZXBhcmF0ZUNhbnZhczogZmFsc2UKICAgICAgICB9OwogICAgICB9CiAgICAgIGFwcGVhcmFuY2UgPSBuZXcgX3N0cmVhbS5TdHJpbmdTdHJlYW0oIiIpOwogICAgICBhcHBlYXJhbmNlLmRpY3QgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdCgpOwogICAgfQogICAgY29uc3QgYXBwZWFyYW5jZURpY3QgPSBhcHBlYXJhbmNlLmRpY3Q7CiAgICBjb25zdCByZXNvdXJjZXMgPSBhd2FpdCB0aGlzLmxvYWRSZXNvdXJjZXMoWyJFeHRHU3RhdGUiLCAiQ29sb3JTcGFjZSIsICJQYXR0ZXJuIiwgIlNoYWRpbmciLCAiWE9iamVjdCIsICJGb250Il0sIGFwcGVhcmFuY2UpOwogICAgY29uc3QgYmJveCA9IGFwcGVhcmFuY2VEaWN0LmdldEFycmF5KCJCQm94IikgfHwgWzAsIDAsIDEsIDFdOwogICAgY29uc3QgbWF0cml4ID0gYXBwZWFyYW5jZURpY3QuZ2V0QXJyYXkoIk1hdHJpeCIpIHx8IFsxLCAwLCAwLCAxLCAwLCAwXTsKICAgIGNvbnN0IHRyYW5zZm9ybSA9IGdldFRyYW5zZm9ybU1hdHJpeChkYXRhLnJlY3QsIGJib3gsIG1hdHJpeCk7CiAgICBjb25zdCBvcExpc3QgPSBuZXcgX29wZXJhdG9yX2xpc3QuT3BlcmF0b3JMaXN0KCk7CiAgICBsZXQgb3B0aW9uYWxDb250ZW50OwogICAgaWYgKHRoaXMub2MpIHsKICAgICAgb3B0aW9uYWxDb250ZW50ID0gYXdhaXQgZXZhbHVhdG9yLnBhcnNlTWFya2VkQ29udGVudFByb3BzKHRoaXMub2MsIG51bGwpOwogICAgfQogICAgaWYgKG9wdGlvbmFsQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIG9wTGlzdC5hZGRPcChfdXRpbC5PUFMuYmVnaW5NYXJrZWRDb250ZW50UHJvcHMsIFsiT0MiLCBvcHRpb25hbENvbnRlbnRdKTsKICAgIH0KICAgIG9wTGlzdC5hZGRPcChfdXRpbC5PUFMuYmVnaW5Bbm5vdGF0aW9uLCBbZGF0YS5pZCwgZGF0YS5yZWN0LCB0cmFuc2Zvcm0sIG1hdHJpeCwgaXNVc2luZ093bkNhbnZhc10pOwogICAgYXdhaXQgZXZhbHVhdG9yLmdldE9wZXJhdG9yTGlzdCh7CiAgICAgIHN0cmVhbTogYXBwZWFyYW5jZSwKICAgICAgdGFzaywKICAgICAgcmVzb3VyY2VzLAogICAgICBvcGVyYXRvckxpc3Q6IG9wTGlzdCwKICAgICAgZmFsbGJhY2tGb250RGljdDogdGhpcy5fZmFsbGJhY2tGb250RGljdAogICAgfSk7CiAgICBvcExpc3QuYWRkT3AoX3V0aWwuT1BTLmVuZEFubm90YXRpb24sIFtdKTsKICAgIGlmIChvcHRpb25hbENvbnRlbnQgIT09IHVuZGVmaW5lZCkgewogICAgICBvcExpc3QuYWRkT3AoX3V0aWwuT1BTLmVuZE1hcmtlZENvbnRlbnQsIFtdKTsKICAgIH0KICAgIHRoaXMucmVzZXQoKTsKICAgIHJldHVybiB7CiAgICAgIG9wTGlzdCwKICAgICAgc2VwYXJhdGVGb3JtOiBmYWxzZSwKICAgICAgc2VwYXJhdGVDYW52YXM6IGlzVXNpbmdPd25DYW52YXMKICAgIH07CiAgfQogIGFzeW5jIHNhdmUoZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGdldCBoYXNUZXh0Q29udGVudCgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgYXN5bmMgZXh0cmFjdFRleHRDb250ZW50KGV2YWx1YXRvciwgdGFzaywgdmlld0JveCkgewogICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgcmVzb3VyY2VzID0gYXdhaXQgdGhpcy5sb2FkUmVzb3VyY2VzKFsiRXh0R1N0YXRlIiwgIkZvbnQiLCAiUHJvcGVydGllcyIsICJYT2JqZWN0Il0sIHRoaXMuYXBwZWFyYW5jZSk7CiAgICBjb25zdCB0ZXh0ID0gW107CiAgICBjb25zdCBidWZmZXIgPSBbXTsKICAgIGNvbnN0IHNpbmsgPSB7CiAgICAgIGRlc2lyZWRTaXplOiBNYXRoLkluZmluaXR5LAogICAgICByZWFkeTogdHJ1ZSwKICAgICAgZW5xdWV1ZShjaHVuaywgc2l6ZSkgewogICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBjaHVuay5pdGVtcykgewogICAgICAgICAgYnVmZmVyLnB1c2goaXRlbS5zdHIpOwogICAgICAgICAgaWYgKGl0ZW0uaGFzRU9MKSB7CiAgICAgICAgICAgIHRleHQucHVzaChidWZmZXIuam9pbigiIikpOwogICAgICAgICAgICBidWZmZXIubGVuZ3RoID0gMDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH07CiAgICBhd2FpdCBldmFsdWF0b3IuZ2V0VGV4dENvbnRlbnQoewogICAgICBzdHJlYW06IHRoaXMuYXBwZWFyYW5jZSwKICAgICAgdGFzaywKICAgICAgcmVzb3VyY2VzLAogICAgICBpbmNsdWRlTWFya2VkQ29udGVudDogdHJ1ZSwKICAgICAgY29tYmluZVRleHRJdGVtczogdHJ1ZSwKICAgICAgc2luaywKICAgICAgdmlld0JveAogICAgfSk7CiAgICB0aGlzLnJlc2V0KCk7CiAgICBpZiAoYnVmZmVyLmxlbmd0aCkgewogICAgICB0ZXh0LnB1c2goYnVmZmVyLmpvaW4oIiIpKTsKICAgIH0KICAgIGlmICh0ZXh0Lmxlbmd0aCA+IDApIHsKICAgICAgdGhpcy5kYXRhLnRleHRDb250ZW50ID0gdGV4dDsKICAgIH0KICB9CiAgZ2V0RmllbGRPYmplY3QoKSB7CiAgICBpZiAodGhpcy5kYXRhLmtpZElkcykgewogICAgICByZXR1cm4gewogICAgICAgIGlkOiB0aGlzLmRhdGEuaWQsCiAgICAgICAgYWN0aW9uczogdGhpcy5kYXRhLmFjdGlvbnMsCiAgICAgICAgbmFtZTogdGhpcy5kYXRhLmZpZWxkTmFtZSwKICAgICAgICBzdHJva2VDb2xvcjogdGhpcy5kYXRhLmJvcmRlckNvbG9yLAogICAgICAgIGZpbGxDb2xvcjogdGhpcy5kYXRhLmJhY2tncm91bmRDb2xvciwKICAgICAgICB0eXBlOiAiIiwKICAgICAgICBraWRJZHM6IHRoaXMuZGF0YS5raWRJZHMsCiAgICAgICAgcGFnZTogdGhpcy5kYXRhLnBhZ2VJbmRleCwKICAgICAgICByb3RhdGlvbjogdGhpcy5yb3RhdGlvbgogICAgICB9OwogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogIHJlc2V0KCkgewogICAgZm9yIChjb25zdCBzdHJlYW0gb2YgdGhpcy5fc3RyZWFtcykgewogICAgICBzdHJlYW0ucmVzZXQoKTsKICAgIH0KICB9CiAgX2NvbnN0cnVjdEZpZWxkTmFtZShkaWN0KSB7CiAgICBpZiAoIWRpY3QuaGFzKCJUIikgJiYgIWRpY3QuaGFzKCJQYXJlbnQiKSkgewogICAgICAoMCwgX3V0aWwud2FybikoIlVua25vd24gZmllbGQgbmFtZSwgZmFsbGluZyBiYWNrIHRvIGVtcHR5IGZpZWxkIG5hbWUuIik7CiAgICAgIHJldHVybiAiIjsKICAgIH0KICAgIGlmICghZGljdC5oYXMoIlBhcmVudCIpKSB7CiAgICAgIHJldHVybiAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGRpY3QuZ2V0KCJUIikpOwogICAgfQogICAgY29uc3QgZmllbGROYW1lID0gW107CiAgICBpZiAoZGljdC5oYXMoIlQiKSkgewogICAgICBmaWVsZE5hbWUudW5zaGlmdCgoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGRpY3QuZ2V0KCJUIikpKTsKICAgIH0KICAgIGxldCBsb29wRGljdCA9IGRpY3Q7CiAgICBjb25zdCB2aXNpdGVkID0gbmV3IF9wcmltaXRpdmVzLlJlZlNldCgpOwogICAgaWYgKGRpY3Qub2JqSWQpIHsKICAgICAgdmlzaXRlZC5wdXQoZGljdC5vYmpJZCk7CiAgICB9CiAgICB3aGlsZSAobG9vcERpY3QuaGFzKCJQYXJlbnQiKSkgewogICAgICBsb29wRGljdCA9IGxvb3BEaWN0LmdldCgiUGFyZW50Iik7CiAgICAgIGlmICghKGxvb3BEaWN0IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgfHwgbG9vcERpY3Qub2JqSWQgJiYgdmlzaXRlZC5oYXMobG9vcERpY3Qub2JqSWQpKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKGxvb3BEaWN0Lm9iaklkKSB7CiAgICAgICAgdmlzaXRlZC5wdXQobG9vcERpY3Qub2JqSWQpOwogICAgICB9CiAgICAgIGlmIChsb29wRGljdC5oYXMoIlQiKSkgewogICAgICAgIGNvbnN0IHQgPSAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGxvb3BEaWN0LmdldCgiVCIpKTsKICAgICAgICBpZiAoIXQuc3RhcnRzV2l0aCgiIyIpKSB7CiAgICAgICAgICBmaWVsZE5hbWUudW5zaGlmdCh0KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBmaWVsZE5hbWUuam9pbigiLiIpOwogIH0KfQpleHBvcnRzLkFubm90YXRpb24gPSBBbm5vdGF0aW9uOwpjbGFzcyBBbm5vdGF0aW9uQm9yZGVyU3R5bGUgewogIGNvbnN0cnVjdG9yKCkgewogICAgdGhpcy53aWR0aCA9IDE7CiAgICB0aGlzLnN0eWxlID0gX3V0aWwuQW5ub3RhdGlvbkJvcmRlclN0eWxlVHlwZS5TT0xJRDsKICAgIHRoaXMuZGFzaEFycmF5ID0gWzNdOwogICAgdGhpcy5ob3Jpem9udGFsQ29ybmVyUmFkaXVzID0gMDsKICAgIHRoaXMudmVydGljYWxDb3JuZXJSYWRpdXMgPSAwOwogIH0KICBzZXRXaWR0aCh3aWR0aCkgewogICAgbGV0IHJlY3QgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IFswLCAwLCAwLCAwXTsKICAgIGlmICh3aWR0aCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgdGhpcy53aWR0aCA9IDA7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0eXBlb2Ygd2lkdGggPT09ICJudW1iZXIiKSB7CiAgICAgIGlmICh3aWR0aCA+IDApIHsKICAgICAgICBjb25zdCBtYXhXaWR0aCA9IChyZWN0WzJdIC0gcmVjdFswXSkgLyAyOwogICAgICAgIGNvbnN0IG1heEhlaWdodCA9IChyZWN0WzNdIC0gcmVjdFsxXSkgLyAyOwogICAgICAgIGlmIChtYXhXaWR0aCA+IDAgJiYgbWF4SGVpZ2h0ID4gMCAmJiAod2lkdGggPiBtYXhXaWR0aCB8fCB3aWR0aCA+IG1heEhlaWdodCkpIHsKICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgQW5ub3RhdGlvbkJvcmRlclN0eWxlLnNldFdpZHRoIC0gaWdub3Jpbmcgd2lkdGg6ICR7d2lkdGh9YCk7CiAgICAgICAgICB3aWR0aCA9IDE7CiAgICAgICAgfQogICAgICB9CiAgICAgIHRoaXMud2lkdGggPSB3aWR0aDsKICAgIH0KICB9CiAgc2V0U3R5bGUoc3R5bGUpIHsKICAgIGlmICghKHN0eWxlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgc3dpdGNoIChzdHlsZS5uYW1lKSB7CiAgICAgIGNhc2UgIlMiOgogICAgICAgIHRoaXMuc3R5bGUgPSBfdXRpbC5Bbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlLlNPTElEOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJEIjoKICAgICAgICB0aGlzLnN0eWxlID0gX3V0aWwuQW5ub3RhdGlvbkJvcmRlclN0eWxlVHlwZS5EQVNIRUQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIkIiOgogICAgICAgIHRoaXMuc3R5bGUgPSBfdXRpbC5Bbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlLkJFVkVMRUQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIkkiOgogICAgICAgIHRoaXMuc3R5bGUgPSBfdXRpbC5Bbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlLklOU0VUOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJVIjoKICAgICAgICB0aGlzLnN0eWxlID0gX3V0aWwuQW5ub3RhdGlvbkJvcmRlclN0eWxlVHlwZS5VTkRFUkxJTkU7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgYnJlYWs7CiAgICB9CiAgfQogIHNldERhc2hBcnJheShkYXNoQXJyYXkpIHsKICAgIGxldCBmb3JjZVN0eWxlID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBmYWxzZTsKICAgIGlmIChBcnJheS5pc0FycmF5KGRhc2hBcnJheSkgJiYgZGFzaEFycmF5Lmxlbmd0aCA+IDApIHsKICAgICAgbGV0IGlzVmFsaWQgPSB0cnVlOwogICAgICBsZXQgYWxsWmVyb3MgPSB0cnVlOwogICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZGFzaEFycmF5KSB7CiAgICAgICAgY29uc3QgdmFsaWROdW1iZXIgPSArZWxlbWVudCA+PSAwOwogICAgICAgIGlmICghdmFsaWROdW1iZXIpIHsKICAgICAgICAgIGlzVmFsaWQgPSBmYWxzZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0gZWxzZSBpZiAoZWxlbWVudCA+IDApIHsKICAgICAgICAgIGFsbFplcm9zID0gZmFsc2U7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChpc1ZhbGlkICYmICFhbGxaZXJvcykgewogICAgICAgIHRoaXMuZGFzaEFycmF5ID0gZGFzaEFycmF5OwogICAgICAgIGlmIChmb3JjZVN0eWxlKSB7CiAgICAgICAgICB0aGlzLnNldFN0eWxlKF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJEIikpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLndpZHRoID0gMDsKICAgICAgfQogICAgfSBlbHNlIGlmIChkYXNoQXJyYXkpIHsKICAgICAgdGhpcy53aWR0aCA9IDA7CiAgICB9CiAgfQogIHNldEhvcml6b250YWxDb3JuZXJSYWRpdXMocmFkaXVzKSB7CiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihyYWRpdXMpKSB7CiAgICAgIHRoaXMuaG9yaXpvbnRhbENvcm5lclJhZGl1cyA9IHJhZGl1czsKICAgIH0KICB9CiAgc2V0VmVydGljYWxDb3JuZXJSYWRpdXMocmFkaXVzKSB7CiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihyYWRpdXMpKSB7CiAgICAgIHRoaXMudmVydGljYWxDb3JuZXJSYWRpdXMgPSByYWRpdXM7CiAgICB9CiAgfQp9CmV4cG9ydHMuQW5ub3RhdGlvbkJvcmRlclN0eWxlID0gQW5ub3RhdGlvbkJvcmRlclN0eWxlOwpjbGFzcyBNYXJrdXBBbm5vdGF0aW9uIGV4dGVuZHMgQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0CiAgICB9ID0gcGFyYW1zOwogICAgaWYgKGRpY3QuaGFzKCJJUlQiKSkgewogICAgICBjb25zdCByYXdJUlQgPSBkaWN0LmdldFJhdygiSVJUIik7CiAgICAgIHRoaXMuZGF0YS5pblJlcGx5VG8gPSByYXdJUlQgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYgPyByYXdJUlQudG9TdHJpbmcoKSA6IG51bGw7CiAgICAgIGNvbnN0IHJ0ID0gZGljdC5nZXQoIlJUIik7CiAgICAgIHRoaXMuZGF0YS5yZXBseVR5cGUgPSBydCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUgPyBydC5uYW1lIDogX3V0aWwuQW5ub3RhdGlvblJlcGx5VHlwZS5SRVBMWTsKICAgIH0KICAgIGlmICh0aGlzLmRhdGEucmVwbHlUeXBlID09PSBfdXRpbC5Bbm5vdGF0aW9uUmVwbHlUeXBlLkdST1VQKSB7CiAgICAgIGNvbnN0IHBhcmVudCA9IGRpY3QuZ2V0KCJJUlQiKTsKICAgICAgdGhpcy5zZXRUaXRsZShwYXJlbnQuZ2V0KCJUIikpOwogICAgICB0aGlzLmRhdGEudGl0bGVPYmogPSB0aGlzLl90aXRsZTsKICAgICAgdGhpcy5zZXRDb250ZW50cyhwYXJlbnQuZ2V0KCJDb250ZW50cyIpKTsKICAgICAgdGhpcy5kYXRhLmNvbnRlbnRzT2JqID0gdGhpcy5fY29udGVudHM7CiAgICAgIGlmICghcGFyZW50LmhhcygiQ3JlYXRpb25EYXRlIikpIHsKICAgICAgICB0aGlzLmRhdGEuY3JlYXRpb25EYXRlID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnNldENyZWF0aW9uRGF0ZShwYXJlbnQuZ2V0KCJDcmVhdGlvbkRhdGUiKSk7CiAgICAgICAgdGhpcy5kYXRhLmNyZWF0aW9uRGF0ZSA9IHRoaXMuY3JlYXRpb25EYXRlOwogICAgICB9CiAgICAgIGlmICghcGFyZW50LmhhcygiTSIpKSB7CiAgICAgICAgdGhpcy5kYXRhLm1vZGlmaWNhdGlvbkRhdGUgPSBudWxsOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuc2V0TW9kaWZpY2F0aW9uRGF0ZShwYXJlbnQuZ2V0KCJNIikpOwogICAgICAgIHRoaXMuZGF0YS5tb2RpZmljYXRpb25EYXRlID0gdGhpcy5tb2RpZmljYXRpb25EYXRlOwogICAgICB9CiAgICAgIHRoaXMuZGF0YS5oYXNQb3B1cCA9IHBhcmVudC5oYXMoIlBvcHVwIik7CiAgICAgIGlmICghcGFyZW50LmhhcygiQyIpKSB7CiAgICAgICAgdGhpcy5kYXRhLmNvbG9yID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnNldENvbG9yKHBhcmVudC5nZXRBcnJheSgiQyIpKTsKICAgICAgICB0aGlzLmRhdGEuY29sb3IgPSB0aGlzLmNvbG9yOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEudGl0bGVPYmogPSB0aGlzLl90aXRsZTsKICAgICAgdGhpcy5zZXRDcmVhdGlvbkRhdGUoZGljdC5nZXQoIkNyZWF0aW9uRGF0ZSIpKTsKICAgICAgdGhpcy5kYXRhLmNyZWF0aW9uRGF0ZSA9IHRoaXMuY3JlYXRpb25EYXRlOwogICAgICB0aGlzLmRhdGEuaGFzUG9wdXAgPSBkaWN0LmhhcygiUG9wdXAiKTsKICAgICAgaWYgKCFkaWN0LmhhcygiQyIpKSB7CiAgICAgICAgdGhpcy5kYXRhLmNvbG9yID0gbnVsbDsKICAgICAgfQogICAgfQogICAgaWYgKGRpY3QuaGFzKCJSQyIpKSB7CiAgICAgIHRoaXMuZGF0YS5yaWNoVGV4dCA9IF9mYWN0b3J5LlhGQUZhY3RvcnkuZ2V0UmljaFRleHRBc0h0bWwoZGljdC5nZXQoIlJDIikpOwogICAgfQogIH0KICBzZXRDcmVhdGlvbkRhdGUoY3JlYXRpb25EYXRlKSB7CiAgICB0aGlzLmNyZWF0aW9uRGF0ZSA9IHR5cGVvZiBjcmVhdGlvbkRhdGUgPT09ICJzdHJpbmciID8gY3JlYXRpb25EYXRlIDogbnVsbDsKICB9CiAgX3NldERlZmF1bHRBcHBlYXJhbmNlKF9yZWYyKSB7CiAgICBsZXQgewogICAgICB4cmVmLAogICAgICBleHRyYSwKICAgICAgc3Ryb2tlQ29sb3IsCiAgICAgIGZpbGxDb2xvciwKICAgICAgYmxlbmRNb2RlLAogICAgICBzdHJva2VBbHBoYSwKICAgICAgZmlsbEFscGhhLAogICAgICBwb2ludHNDYWxsYmFjawogICAgfSA9IF9yZWYyOwogICAgbGV0IG1pblggPSBOdW1iZXIuTUFYX1ZBTFVFOwogICAgbGV0IG1pblkgPSBOdW1iZXIuTUFYX1ZBTFVFOwogICAgbGV0IG1heFggPSBOdW1iZXIuTUlOX1ZBTFVFOwogICAgbGV0IG1heFkgPSBOdW1iZXIuTUlOX1ZBTFVFOwogICAgY29uc3QgYnVmZmVyID0gWyJxIl07CiAgICBpZiAoZXh0cmEpIHsKICAgICAgYnVmZmVyLnB1c2goZXh0cmEpOwogICAgfQogICAgaWYgKHN0cm9rZUNvbG9yKSB7CiAgICAgIGJ1ZmZlci5wdXNoKGAke3N0cm9rZUNvbG9yWzBdfSAke3N0cm9rZUNvbG9yWzFdfSAke3N0cm9rZUNvbG9yWzJdfSBSR2ApOwogICAgfQogICAgaWYgKGZpbGxDb2xvcikgewogICAgICBidWZmZXIucHVzaChgJHtmaWxsQ29sb3JbMF19ICR7ZmlsbENvbG9yWzFdfSAke2ZpbGxDb2xvclsyXX0gcmdgKTsKICAgIH0KICAgIGxldCBwb2ludHNBcnJheSA9IHRoaXMuZGF0YS5xdWFkUG9pbnRzOwogICAgaWYgKCFwb2ludHNBcnJheSkgewogICAgICBwb2ludHNBcnJheSA9IFtbewogICAgICAgIHg6IHRoaXMucmVjdGFuZ2xlWzBdLAogICAgICAgIHk6IHRoaXMucmVjdGFuZ2xlWzNdCiAgICAgIH0sIHsKICAgICAgICB4OiB0aGlzLnJlY3RhbmdsZVsyXSwKICAgICAgICB5OiB0aGlzLnJlY3RhbmdsZVszXQogICAgICB9LCB7CiAgICAgICAgeDogdGhpcy5yZWN0YW5nbGVbMF0sCiAgICAgICAgeTogdGhpcy5yZWN0YW5nbGVbMV0KICAgICAgfSwgewogICAgICAgIHg6IHRoaXMucmVjdGFuZ2xlWzJdLAogICAgICAgIHk6IHRoaXMucmVjdGFuZ2xlWzFdCiAgICAgIH1dXTsKICAgIH0KICAgIGZvciAoY29uc3QgcG9pbnRzIG9mIHBvaW50c0FycmF5KSB7CiAgICAgIGNvbnN0IFttWCwgTVgsIG1ZLCBNWV0gPSBwb2ludHNDYWxsYmFjayhidWZmZXIsIHBvaW50cyk7CiAgICAgIG1pblggPSBNYXRoLm1pbihtaW5YLCBtWCk7CiAgICAgIG1heFggPSBNYXRoLm1heChtYXhYLCBNWCk7CiAgICAgIG1pblkgPSBNYXRoLm1pbihtaW5ZLCBtWSk7CiAgICAgIG1heFkgPSBNYXRoLm1heChtYXhZLCBNWSk7CiAgICB9CiAgICBidWZmZXIucHVzaCgiUSIpOwogICAgY29uc3QgZm9ybURpY3QgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdCh4cmVmKTsKICAgIGNvbnN0IGFwcGVhcmFuY2VTdHJlYW1EaWN0ID0gbmV3IF9wcmltaXRpdmVzLkRpY3QoeHJlZik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlN1YnR5cGUiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiRm9ybSIpKTsKICAgIGNvbnN0IGFwcGVhcmFuY2VTdHJlYW0gPSBuZXcgX3N0cmVhbS5TdHJpbmdTdHJlYW0oYnVmZmVyLmpvaW4oIiAiKSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtLmRpY3QgPSBhcHBlYXJhbmNlU3RyZWFtRGljdDsKICAgIGZvcm1EaWN0LnNldCgiRm0wIiwgYXBwZWFyYW5jZVN0cmVhbSk7CiAgICBjb25zdCBnc0RpY3QgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdCh4cmVmKTsKICAgIGlmIChibGVuZE1vZGUpIHsKICAgICAgZ3NEaWN0LnNldCgiQk0iLCBfcHJpbWl0aXZlcy5OYW1lLmdldChibGVuZE1vZGUpKTsKICAgIH0KICAgIGlmICh0eXBlb2Ygc3Ryb2tlQWxwaGEgPT09ICJudW1iZXIiKSB7CiAgICAgIGdzRGljdC5zZXQoIkNBIiwgc3Ryb2tlQWxwaGEpOwogICAgfQogICAgaWYgKHR5cGVvZiBmaWxsQWxwaGEgPT09ICJudW1iZXIiKSB7CiAgICAgIGdzRGljdC5zZXQoImNhIiwgZmlsbEFscGhhKTsKICAgIH0KICAgIGNvbnN0IHN0YXRlRGljdCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHhyZWYpOwogICAgc3RhdGVEaWN0LnNldCgiR1MwIiwgZ3NEaWN0KTsKICAgIGNvbnN0IHJlc291cmNlcyA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHhyZWYpOwogICAgcmVzb3VyY2VzLnNldCgiRXh0R1N0YXRlIiwgc3RhdGVEaWN0KTsKICAgIHJlc291cmNlcy5zZXQoIlhPYmplY3QiLCBmb3JtRGljdCk7CiAgICBjb25zdCBhcHBlYXJhbmNlRGljdCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHhyZWYpOwogICAgYXBwZWFyYW5jZURpY3Quc2V0KCJSZXNvdXJjZXMiLCByZXNvdXJjZXMpOwogICAgY29uc3QgYmJveCA9IHRoaXMuZGF0YS5yZWN0ID0gW21pblgsIG1pblksIG1heFgsIG1heFldOwogICAgYXBwZWFyYW5jZURpY3Quc2V0KCJCQm94IiwgYmJveCk7CiAgICB0aGlzLmFwcGVhcmFuY2UgPSBuZXcgX3N0cmVhbS5TdHJpbmdTdHJlYW0oIi9HUzAgZ3MgL0ZtMCBEbyIpOwogICAgdGhpcy5hcHBlYXJhbmNlLmRpY3QgPSBhcHBlYXJhbmNlRGljdDsKICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmFwcGVhcmFuY2UsIGFwcGVhcmFuY2VTdHJlYW0pOwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlTmV3QW5ub3RhdGlvbih4cmVmLCBhbm5vdGF0aW9uLCBkZXBlbmRlbmNpZXMsIHBhcmFtcykgewogICAgY29uc3QgYW5ub3RhdGlvblJlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICBjb25zdCBhcCA9IGF3YWl0IHRoaXMuY3JlYXRlTmV3QXBwZWFyYW5jZVN0cmVhbShhbm5vdGF0aW9uLCB4cmVmLCBwYXJhbXMpOwogICAgY29uc3QgYnVmZmVyID0gW107CiAgICBsZXQgYW5ub3RhdGlvbkRpY3Q7CiAgICBpZiAoYXApIHsKICAgICAgY29uc3QgYXBSZWYgPSB4cmVmLmdldE5ld1RlbXBvcmFyeVJlZigpOwogICAgICBhbm5vdGF0aW9uRGljdCA9IHRoaXMuY3JlYXRlTmV3RGljdChhbm5vdGF0aW9uLCB4cmVmLCB7CiAgICAgICAgYXBSZWYKICAgICAgfSk7CiAgICAgIGNvbnN0IHRyYW5zZm9ybSA9IHhyZWYuZW5jcnlwdCA/IHhyZWYuZW5jcnlwdC5jcmVhdGVDaXBoZXJUcmFuc2Zvcm0oYXBSZWYubnVtLCBhcFJlZi5nZW4pIDogbnVsbDsKICAgICAgKDAsIF93cml0ZXIud3JpdGVPYmplY3QpKGFwUmVmLCBhcCwgYnVmZmVyLCB0cmFuc2Zvcm0pOwogICAgICBkZXBlbmRlbmNpZXMucHVzaCh7CiAgICAgICAgcmVmOiBhcFJlZiwKICAgICAgICBkYXRhOiBidWZmZXIuam9pbigiIikKICAgICAgfSk7CiAgICB9IGVsc2UgewogICAgICBhbm5vdGF0aW9uRGljdCA9IHRoaXMuY3JlYXRlTmV3RGljdChhbm5vdGF0aW9uLCB4cmVmLCB7fSk7CiAgICB9CiAgICBidWZmZXIubGVuZ3RoID0gMDsKICAgIGNvbnN0IHRyYW5zZm9ybSA9IHhyZWYuZW5jcnlwdCA/IHhyZWYuZW5jcnlwdC5jcmVhdGVDaXBoZXJUcmFuc2Zvcm0oYW5ub3RhdGlvblJlZi5udW0sIGFubm90YXRpb25SZWYuZ2VuKSA6IG51bGw7CiAgICAoMCwgX3dyaXRlci53cml0ZU9iamVjdCkoYW5ub3RhdGlvblJlZiwgYW5ub3RhdGlvbkRpY3QsIGJ1ZmZlciwgdHJhbnNmb3JtKTsKICAgIHJldHVybiB7CiAgICAgIHJlZjogYW5ub3RhdGlvblJlZiwKICAgICAgZGF0YTogYnVmZmVyLmpvaW4oIiIpCiAgICB9OwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlTmV3UHJpbnRBbm5vdGF0aW9uKHhyZWYsIGFubm90YXRpb24sIHBhcmFtcykgewogICAgY29uc3QgYXAgPSBhd2FpdCB0aGlzLmNyZWF0ZU5ld0FwcGVhcmFuY2VTdHJlYW0oYW5ub3RhdGlvbiwgeHJlZiwgcGFyYW1zKTsKICAgIGNvbnN0IGFubm90YXRpb25EaWN0ID0gdGhpcy5jcmVhdGVOZXdEaWN0KGFubm90YXRpb24sIHhyZWYsIHsKICAgICAgYXAKICAgIH0pOwogICAgcmV0dXJuIG5ldyB0aGlzLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcih7CiAgICAgIGRpY3Q6IGFubm90YXRpb25EaWN0LAogICAgICB4cmVmLAogICAgICBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZDogcGFyYW1zLmlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkCiAgICB9KTsKICB9Cn0KZXhwb3J0cy5NYXJrdXBBbm5vdGF0aW9uID0gTWFya3VwQW5ub3RhdGlvbjsKY2xhc3MgV2lkZ2V0QW5ub3RhdGlvbiBleHRlbmRzIEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgeHJlZgogICAgfSA9IHBhcmFtczsKICAgIGNvbnN0IGRhdGEgPSB0aGlzLmRhdGE7CiAgICB0aGlzLnJlZiA9IHBhcmFtcy5yZWY7CiAgICB0aGlzLl9uZWVkQXBwZWFyYW5jZXMgPSBwYXJhbXMubmVlZEFwcGVhcmFuY2VzOwogICAgZGF0YS5hbm5vdGF0aW9uVHlwZSA9IF91dGlsLkFubm90YXRpb25UeXBlLldJREdFVDsKICAgIGlmIChkYXRhLmZpZWxkTmFtZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGRhdGEuZmllbGROYW1lID0gdGhpcy5fY29uc3RydWN0RmllbGROYW1lKGRpY3QpOwogICAgfQogICAgaWYgKGRhdGEuYWN0aW9ucyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGRhdGEuYWN0aW9ucyA9ICgwLCBfY29yZV91dGlscy5jb2xsZWN0QWN0aW9ucykoeHJlZiwgZGljdCwgX3V0aWwuQW5ub3RhdGlvbkFjdGlvbkV2ZW50VHlwZSk7CiAgICB9CiAgICBsZXQgZmllbGRWYWx1ZSA9ICgwLCBfY29yZV91dGlscy5nZXRJbmhlcml0YWJsZVByb3BlcnR5KSh7CiAgICAgIGRpY3QsCiAgICAgIGtleTogIlYiLAogICAgICBnZXRBcnJheTogdHJ1ZQogICAgfSk7CiAgICBkYXRhLmZpZWxkVmFsdWUgPSB0aGlzLl9kZWNvZGVGb3JtVmFsdWUoZmllbGRWYWx1ZSk7CiAgICBjb25zdCBkZWZhdWx0RmllbGRWYWx1ZSA9ICgwLCBfY29yZV91dGlscy5nZXRJbmhlcml0YWJsZVByb3BlcnR5KSh7CiAgICAgIGRpY3QsCiAgICAgIGtleTogIkRWIiwKICAgICAgZ2V0QXJyYXk6IHRydWUKICAgIH0pOwogICAgZGF0YS5kZWZhdWx0RmllbGRWYWx1ZSA9IHRoaXMuX2RlY29kZUZvcm1WYWx1ZShkZWZhdWx0RmllbGRWYWx1ZSk7CiAgICBpZiAoZmllbGRWYWx1ZSA9PT0gdW5kZWZpbmVkICYmIHBhcmFtcy54ZmFEYXRhc2V0cykgewogICAgICBjb25zdCBwYXRoID0gdGhpcy5fdGl0bGUuc3RyOwogICAgICBpZiAocGF0aCkgewogICAgICAgIHRoaXMuX2hhc1ZhbHVlRnJvbVhGQSA9IHRydWU7CiAgICAgICAgZGF0YS5maWVsZFZhbHVlID0gZmllbGRWYWx1ZSA9IHBhcmFtcy54ZmFEYXRhc2V0cy5nZXRWYWx1ZShwYXRoKTsKICAgICAgfQogICAgfQogICAgaWYgKGZpZWxkVmFsdWUgPT09IHVuZGVmaW5lZCAmJiBkYXRhLmRlZmF1bHRGaWVsZFZhbHVlICE9PSBudWxsKSB7CiAgICAgIGRhdGEuZmllbGRWYWx1ZSA9IGRhdGEuZGVmYXVsdEZpZWxkVmFsdWU7CiAgICB9CiAgICBkYXRhLmFsdGVybmF0aXZlVGV4dCA9ICgwLCBfdXRpbC5zdHJpbmdUb1BERlN0cmluZykoZGljdC5nZXQoIlRVIikgfHwgIiIpOwogICAgdGhpcy5zZXREZWZhdWx0QXBwZWFyYW5jZShwYXJhbXMpOwogICAgZGF0YS5oYXNBcHBlYXJhbmNlID0gdGhpcy5fbmVlZEFwcGVhcmFuY2VzICYmIGRhdGEuZmllbGRWYWx1ZSAhPT0gdW5kZWZpbmVkICYmIGRhdGEuZmllbGRWYWx1ZSAhPT0gbnVsbCB8fCBkYXRhLmhhc0FwcGVhcmFuY2U7CiAgICBjb25zdCBmaWVsZFR5cGUgPSAoMCwgX2NvcmVfdXRpbHMuZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSkoewogICAgICBkaWN0LAogICAgICBrZXk6ICJGVCIKICAgIH0pOwogICAgZGF0YS5maWVsZFR5cGUgPSBmaWVsZFR5cGUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lID8gZmllbGRUeXBlLm5hbWUgOiBudWxsOwogICAgY29uc3QgbG9jYWxSZXNvdXJjZXMgPSAoMCwgX2NvcmVfdXRpbHMuZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSkoewogICAgICBkaWN0LAogICAgICBrZXk6ICJEUiIKICAgIH0pOwogICAgY29uc3QgYWNyb0Zvcm1SZXNvdXJjZXMgPSBwYXJhbXMuYWNyb0Zvcm0uZ2V0KCJEUiIpOwogICAgY29uc3QgYXBwZWFyYW5jZVJlc291cmNlcyA9IHRoaXMuYXBwZWFyYW5jZSAmJiB0aGlzLmFwcGVhcmFuY2UuZGljdC5nZXQoIlJlc291cmNlcyIpOwogICAgdGhpcy5fZmllbGRSZXNvdXJjZXMgPSB7CiAgICAgIGxvY2FsUmVzb3VyY2VzLAogICAgICBhY3JvRm9ybVJlc291cmNlcywKICAgICAgYXBwZWFyYW5jZVJlc291cmNlcywKICAgICAgbWVyZ2VkUmVzb3VyY2VzOiBfcHJpbWl0aXZlcy5EaWN0Lm1lcmdlKHsKICAgICAgICB4cmVmLAogICAgICAgIGRpY3RBcnJheTogW2xvY2FsUmVzb3VyY2VzLCBhcHBlYXJhbmNlUmVzb3VyY2VzLCBhY3JvRm9ybVJlc291cmNlc10sCiAgICAgICAgbWVyZ2VTdWJEaWN0czogdHJ1ZQogICAgICB9KQogICAgfTsKICAgIGRhdGEuZmllbGRGbGFncyA9ICgwLCBfY29yZV91dGlscy5nZXRJbmhlcml0YWJsZVByb3BlcnR5KSh7CiAgICAgIGRpY3QsCiAgICAgIGtleTogIkZmIgogICAgfSk7CiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoZGF0YS5maWVsZEZsYWdzKSB8fCBkYXRhLmZpZWxkRmxhZ3MgPCAwKSB7CiAgICAgIGRhdGEuZmllbGRGbGFncyA9IDA7CiAgICB9CiAgICBkYXRhLnJlYWRPbmx5ID0gdGhpcy5oYXNGaWVsZEZsYWcoX3V0aWwuQW5ub3RhdGlvbkZpZWxkRmxhZy5SRUFET05MWSk7CiAgICBkYXRhLnJlcXVpcmVkID0gdGhpcy5oYXNGaWVsZEZsYWcoX3V0aWwuQW5ub3RhdGlvbkZpZWxkRmxhZy5SRVFVSVJFRCk7CiAgICBkYXRhLmhpZGRlbiA9IHRoaXMuX2hhc0ZsYWcoZGF0YS5hbm5vdGF0aW9uRmxhZ3MsIF91dGlsLkFubm90YXRpb25GbGFnLkhJRERFTik7CiAgfQogIF9kZWNvZGVGb3JtVmFsdWUoZm9ybVZhbHVlKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheShmb3JtVmFsdWUpKSB7CiAgICAgIHJldHVybiBmb3JtVmFsdWUuZmlsdGVyKGl0ZW0gPT4gdHlwZW9mIGl0ZW0gPT09ICJzdHJpbmciKS5tYXAoaXRlbSA9PiAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGl0ZW0pKTsKICAgIH0gZWxzZSBpZiAoZm9ybVZhbHVlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICByZXR1cm4gKDAsIF91dGlsLnN0cmluZ1RvUERGU3RyaW5nKShmb3JtVmFsdWUubmFtZSk7CiAgICB9IGVsc2UgaWYgKHR5cGVvZiBmb3JtVmFsdWUgPT09ICJzdHJpbmciKSB7CiAgICAgIHJldHVybiAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGZvcm1WYWx1ZSk7CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgaGFzRmllbGRGbGFnKGZsYWcpIHsKICAgIHJldHVybiAhISh0aGlzLmRhdGEuZmllbGRGbGFncyAmIGZsYWcpOwogIH0KICBnZXRSb3RhdGlvbk1hdHJpeChhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgY29uc3Qgc3RvcmFnZUVudHJ5ID0gYW5ub3RhdGlvblN0b3JhZ2UgPyBhbm5vdGF0aW9uU3RvcmFnZS5nZXQodGhpcy5kYXRhLmlkKSA6IHVuZGVmaW5lZDsKICAgIGxldCByb3RhdGlvbiA9IHN0b3JhZ2VFbnRyeSAmJiBzdG9yYWdlRW50cnkucm90YXRpb247CiAgICBpZiAocm90YXRpb24gPT09IHVuZGVmaW5lZCkgewogICAgICByb3RhdGlvbiA9IHRoaXMucm90YXRpb247CiAgICB9CiAgICBpZiAocm90YXRpb24gPT09IDApIHsKICAgICAgcmV0dXJuIF91dGlsLklERU5USVRZX01BVFJJWDsKICAgIH0KICAgIGNvbnN0IHdpZHRoID0gdGhpcy5kYXRhLnJlY3RbMl0gLSB0aGlzLmRhdGEucmVjdFswXTsKICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuZGF0YS5yZWN0WzNdIC0gdGhpcy5kYXRhLnJlY3RbMV07CiAgICByZXR1cm4gKDAsIF9jb3JlX3V0aWxzLmdldFJvdGF0aW9uTWF0cml4KShyb3RhdGlvbiwgd2lkdGgsIGhlaWdodCk7CiAgfQogIGdldEJvcmRlckFuZEJhY2tncm91bmRBcHBlYXJhbmNlcyhhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgY29uc3Qgc3RvcmFnZUVudHJ5ID0gYW5ub3RhdGlvblN0b3JhZ2UgPyBhbm5vdGF0aW9uU3RvcmFnZS5nZXQodGhpcy5kYXRhLmlkKSA6IHVuZGVmaW5lZDsKICAgIGxldCByb3RhdGlvbiA9IHN0b3JhZ2VFbnRyeSAmJiBzdG9yYWdlRW50cnkucm90YXRpb247CiAgICBpZiAocm90YXRpb24gPT09IHVuZGVmaW5lZCkgewogICAgICByb3RhdGlvbiA9IHRoaXMucm90YXRpb247CiAgICB9CiAgICBpZiAoIXRoaXMuYmFja2dyb3VuZENvbG9yICYmICF0aGlzLmJvcmRlckNvbG9yKSB7CiAgICAgIHJldHVybiAiIjsKICAgIH0KICAgIGNvbnN0IHdpZHRoID0gdGhpcy5kYXRhLnJlY3RbMl0gLSB0aGlzLmRhdGEucmVjdFswXTsKICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuZGF0YS5yZWN0WzNdIC0gdGhpcy5kYXRhLnJlY3RbMV07CiAgICBjb25zdCByZWN0ID0gcm90YXRpb24gPT09IDAgfHwgcm90YXRpb24gPT09IDE4MCA/IGAwIDAgJHt3aWR0aH0gJHtoZWlnaHR9IHJlYCA6IGAwIDAgJHtoZWlnaHR9ICR7d2lkdGh9IHJlYDsKICAgIGxldCBzdHIgPSAiIjsKICAgIGlmICh0aGlzLmJhY2tncm91bmRDb2xvcikgewogICAgICBzdHIgPSBgJHsoMCwgX2RlZmF1bHRfYXBwZWFyYW5jZS5nZXRQZGZDb2xvcikodGhpcy5iYWNrZ3JvdW5kQ29sb3IsIHRydWUpfSAke3JlY3R9IGYgYDsKICAgIH0KICAgIGlmICh0aGlzLmJvcmRlckNvbG9yKSB7CiAgICAgIGNvbnN0IGJvcmRlcldpZHRoID0gdGhpcy5ib3JkZXJTdHlsZS53aWR0aCB8fCAxOwogICAgICBzdHIgKz0gYCR7Ym9yZGVyV2lkdGh9IHcgJHsoMCwgX2RlZmF1bHRfYXBwZWFyYW5jZS5nZXRQZGZDb2xvcikodGhpcy5ib3JkZXJDb2xvciwgZmFsc2UpfSAke3JlY3R9IFMgYDsKICAgIH0KICAgIHJldHVybiBzdHI7CiAgfQogIGFzeW5jIGdldE9wZXJhdG9yTGlzdChldmFsdWF0b3IsIHRhc2ssIGludGVudCwgcmVuZGVyRm9ybXMsIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBpZiAocmVuZGVyRm9ybXMgJiYgISh0aGlzIGluc3RhbmNlb2YgU2lnbmF0dXJlV2lkZ2V0QW5ub3RhdGlvbikgJiYgIXRoaXMuZGF0YS5ub0hUTUwpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBvcExpc3Q6IG5ldyBfb3BlcmF0b3JfbGlzdC5PcGVyYXRvckxpc3QoKSwKICAgICAgICBzZXBhcmF0ZUZvcm06IHRydWUsCiAgICAgICAgc2VwYXJhdGVDYW52YXM6IGZhbHNlCiAgICAgIH07CiAgICB9CiAgICBpZiAoIXRoaXMuX2hhc1RleHQpIHsKICAgICAgcmV0dXJuIHN1cGVyLmdldE9wZXJhdG9yTGlzdChldmFsdWF0b3IsIHRhc2ssIGludGVudCwgcmVuZGVyRm9ybXMsIGFubm90YXRpb25TdG9yYWdlKTsKICAgIH0KICAgIGNvbnN0IGNvbnRlbnQgPSBhd2FpdCB0aGlzLl9nZXRBcHBlYXJhbmNlKGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICBpZiAodGhpcy5hcHBlYXJhbmNlICYmIGNvbnRlbnQgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIHN1cGVyLmdldE9wZXJhdG9yTGlzdChldmFsdWF0b3IsIHRhc2ssIGludGVudCwgcmVuZGVyRm9ybXMsIGFubm90YXRpb25TdG9yYWdlKTsKICAgIH0KICAgIGNvbnN0IG9wTGlzdCA9IG5ldyBfb3BlcmF0b3JfbGlzdC5PcGVyYXRvckxpc3QoKTsKICAgIGlmICghdGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UgfHwgY29udGVudCA9PT0gbnVsbCkgewogICAgICByZXR1cm4gewogICAgICAgIG9wTGlzdCwKICAgICAgICBzZXBhcmF0ZUZvcm06IGZhbHNlLAogICAgICAgIHNlcGFyYXRlQ2FudmFzOiBmYWxzZQogICAgICB9OwogICAgfQogICAgY29uc3QgbWF0cml4ID0gWzEsIDAsIDAsIDEsIDAsIDBdOwogICAgY29uc3QgYmJveCA9IFswLCAwLCB0aGlzLmRhdGEucmVjdFsyXSAtIHRoaXMuZGF0YS5yZWN0WzBdLCB0aGlzLmRhdGEucmVjdFszXSAtIHRoaXMuZGF0YS5yZWN0WzFdXTsKICAgIGNvbnN0IHRyYW5zZm9ybSA9IGdldFRyYW5zZm9ybU1hdHJpeCh0aGlzLmRhdGEucmVjdCwgYmJveCwgbWF0cml4KTsKICAgIGxldCBvcHRpb25hbENvbnRlbnQ7CiAgICBpZiAodGhpcy5vYykgewogICAgICBvcHRpb25hbENvbnRlbnQgPSBhd2FpdCBldmFsdWF0b3IucGFyc2VNYXJrZWRDb250ZW50UHJvcHModGhpcy5vYywgbnVsbCk7CiAgICB9CiAgICBpZiAob3B0aW9uYWxDb250ZW50ICE9PSB1bmRlZmluZWQpIHsKICAgICAgb3BMaXN0LmFkZE9wKF91dGlsLk9QUy5iZWdpbk1hcmtlZENvbnRlbnRQcm9wcywgWyJPQyIsIG9wdGlvbmFsQ29udGVudF0pOwogICAgfQogICAgb3BMaXN0LmFkZE9wKF91dGlsLk9QUy5iZWdpbkFubm90YXRpb24sIFt0aGlzLmRhdGEuaWQsIHRoaXMuZGF0YS5yZWN0LCB0cmFuc2Zvcm0sIHRoaXMuZ2V0Um90YXRpb25NYXRyaXgoYW5ub3RhdGlvblN0b3JhZ2UpLCBmYWxzZV0pOwogICAgY29uc3Qgc3RyZWFtID0gbmV3IF9zdHJlYW0uU3RyaW5nU3RyZWFtKGNvbnRlbnQpOwogICAgYXdhaXQgZXZhbHVhdG9yLmdldE9wZXJhdG9yTGlzdCh7CiAgICAgIHN0cmVhbSwKICAgICAgdGFzaywKICAgICAgcmVzb3VyY2VzOiB0aGlzLl9maWVsZFJlc291cmNlcy5tZXJnZWRSZXNvdXJjZXMsCiAgICAgIG9wZXJhdG9yTGlzdDogb3BMaXN0CiAgICB9KTsKICAgIG9wTGlzdC5hZGRPcChfdXRpbC5PUFMuZW5kQW5ub3RhdGlvbiwgW10pOwogICAgaWYgKG9wdGlvbmFsQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIG9wTGlzdC5hZGRPcChfdXRpbC5PUFMuZW5kTWFya2VkQ29udGVudCwgW10pOwogICAgfQogICAgcmV0dXJuIHsKICAgICAgb3BMaXN0LAogICAgICBzZXBhcmF0ZUZvcm06IGZhbHNlLAogICAgICBzZXBhcmF0ZUNhbnZhczogZmFsc2UKICAgIH07CiAgfQogIF9nZXRNS0RpY3Qocm90YXRpb24pIHsKICAgIGNvbnN0IG1rID0gbmV3IF9wcmltaXRpdmVzLkRpY3QobnVsbCk7CiAgICBpZiAocm90YXRpb24pIHsKICAgICAgbWsuc2V0KCJSIiwgcm90YXRpb24pOwogICAgfQogICAgaWYgKHRoaXMuYm9yZGVyQ29sb3IpIHsKICAgICAgbWsuc2V0KCJCQyIsIGdldFBkZkNvbG9yQXJyYXkodGhpcy5ib3JkZXJDb2xvcikpOwogICAgfQogICAgaWYgKHRoaXMuYmFja2dyb3VuZENvbG9yKSB7CiAgICAgIG1rLnNldCgiQkciLCBnZXRQZGZDb2xvckFycmF5KHRoaXMuYmFja2dyb3VuZENvbG9yKSk7CiAgICB9CiAgICByZXR1cm4gbWsuc2l6ZSA+IDAgPyBtayA6IG51bGw7CiAgfQogIGFtZW5kU2F2ZWREaWN0KGFubm90YXRpb25TdG9yYWdlLCBkaWN0KSB7fQogIGFzeW5jIHNhdmUoZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgY29uc3Qgc3RvcmFnZUVudHJ5ID0gYW5ub3RhdGlvblN0b3JhZ2UgPyBhbm5vdGF0aW9uU3RvcmFnZS5nZXQodGhpcy5kYXRhLmlkKSA6IHVuZGVmaW5lZDsKICAgIGxldCB2YWx1ZSA9IHN0b3JhZ2VFbnRyeSAmJiBzdG9yYWdlRW50cnkudmFsdWU7CiAgICBsZXQgcm90YXRpb24gPSBzdG9yYWdlRW50cnkgJiYgc3RvcmFnZUVudHJ5LnJvdGF0aW9uOwogICAgaWYgKHZhbHVlID09PSB0aGlzLmRhdGEuZmllbGRWYWx1ZSB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmICghdGhpcy5faGFzVmFsdWVGcm9tWEZBICYmIHJvdGF0aW9uID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICB2YWx1ZSA9IHZhbHVlIHx8IHRoaXMuZGF0YS5maWVsZFZhbHVlOwogICAgfQogICAgaWYgKHJvdGF0aW9uID09PSB1bmRlZmluZWQgJiYgIXRoaXMuX2hhc1ZhbHVlRnJvbVhGQSAmJiBBcnJheS5pc0FycmF5KHZhbHVlKSAmJiBBcnJheS5pc0FycmF5KHRoaXMuZGF0YS5maWVsZFZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPT09IHRoaXMuZGF0YS5maWVsZFZhbHVlLmxlbmd0aCAmJiB2YWx1ZS5ldmVyeSgoeCwgaSkgPT4geCA9PT0gdGhpcy5kYXRhLmZpZWxkVmFsdWVbaV0pKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKHJvdGF0aW9uID09PSB1bmRlZmluZWQpIHsKICAgICAgcm90YXRpb24gPSB0aGlzLnJvdGF0aW9uOwogICAgfQogICAgbGV0IGFwcGVhcmFuY2UgPSBudWxsOwogICAgaWYgKCF0aGlzLl9uZWVkQXBwZWFyYW5jZXMpIHsKICAgICAgYXBwZWFyYW5jZSA9IGF3YWl0IHRoaXMuX2dldEFwcGVhcmFuY2UoZXZhbHVhdG9yLCB0YXNrLCBfdXRpbC5SZW5kZXJpbmdJbnRlbnRGbGFnLlNBVkUsIGFubm90YXRpb25TdG9yYWdlKTsKICAgICAgaWYgKGFwcGVhcmFuY2UgPT09IG51bGwpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfSBlbHNlIHt9CiAgICBsZXQgbmVlZEFwcGVhcmFuY2VzID0gZmFsc2U7CiAgICBpZiAoYXBwZWFyYW5jZSAmJiBhcHBlYXJhbmNlLm5lZWRBcHBlYXJhbmNlcykgewogICAgICBuZWVkQXBwZWFyYW5jZXMgPSB0cnVlOwogICAgICBhcHBlYXJhbmNlID0gbnVsbDsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgeHJlZgogICAgfSA9IGV2YWx1YXRvcjsKICAgIGNvbnN0IG9yaWdpbmFsRGljdCA9IHhyZWYuZmV0Y2hJZlJlZih0aGlzLnJlZik7CiAgICBpZiAoIShvcmlnaW5hbERpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IGRpY3QgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdCh4cmVmKTsKICAgIGZvciAoY29uc3Qga2V5IG9mIG9yaWdpbmFsRGljdC5nZXRLZXlzKCkpIHsKICAgICAgaWYgKGtleSAhPT0gIkFQIikgewogICAgICAgIGRpY3Quc2V0KGtleSwgb3JpZ2luYWxEaWN0LmdldFJhdyhrZXkpKTsKICAgICAgfQogICAgfQogICAgY29uc3QgeGZhID0gewogICAgICBwYXRoOiB0aGlzLmRhdGEuZmllbGROYW1lLAogICAgICB2YWx1ZQogICAgfTsKICAgIGNvbnN0IGVuY29kZXIgPSB2YWwgPT4gewogICAgICByZXR1cm4gKDAsIF9jb3JlX3V0aWxzLmlzQXNjaWkpKHZhbCkgPyB2YWwgOiAoMCwgX2NvcmVfdXRpbHMuc3RyaW5nVG9VVEYxNlN0cmluZykodmFsLCB0cnVlKTsKICAgIH07CiAgICBkaWN0LnNldCgiViIsIEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUubWFwKGVuY29kZXIpIDogZW5jb2Rlcih2YWx1ZSkpOwogICAgdGhpcy5hbWVuZFNhdmVkRGljdChhbm5vdGF0aW9uU3RvcmFnZSwgZGljdCk7CiAgICBjb25zdCBtYXliZU1LID0gdGhpcy5fZ2V0TUtEaWN0KHJvdGF0aW9uKTsKICAgIGlmIChtYXliZU1LKSB7CiAgICAgIGRpY3Quc2V0KCJNSyIsIG1heWJlTUspOwogICAgfQogICAgY29uc3QgZW5jcnlwdCA9IHhyZWYuZW5jcnlwdDsKICAgIGNvbnN0IG9yaWdpbmFsVHJhbnNmb3JtID0gZW5jcnlwdCA/IGVuY3J5cHQuY3JlYXRlQ2lwaGVyVHJhbnNmb3JtKHRoaXMucmVmLm51bSwgdGhpcy5yZWYuZ2VuKSA6IG51bGw7CiAgICBjb25zdCBidWZmZXIgPSBbXTsKICAgIGNvbnN0IGNoYW5nZXMgPSBbewogICAgICByZWY6IHRoaXMucmVmLAogICAgICBkYXRhOiAiIiwKICAgICAgeGZhLAogICAgICBuZWVkQXBwZWFyYW5jZXMKICAgIH1dOwogICAgaWYgKGFwcGVhcmFuY2UgIT09IG51bGwpIHsKICAgICAgY29uc3QgbmV3UmVmID0geHJlZi5nZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgICAgY29uc3QgQVAgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdCh4cmVmKTsKICAgICAgZGljdC5zZXQoIkFQIiwgQVApOwogICAgICBBUC5zZXQoIk4iLCBuZXdSZWYpOwogICAgICBsZXQgbmV3VHJhbnNmb3JtID0gbnVsbDsKICAgICAgaWYgKGVuY3J5cHQpIHsKICAgICAgICBuZXdUcmFuc2Zvcm0gPSBlbmNyeXB0LmNyZWF0ZUNpcGhlclRyYW5zZm9ybShuZXdSZWYubnVtLCBuZXdSZWYuZ2VuKTsKICAgICAgfQogICAgICBjb25zdCByZXNvdXJjZXMgPSB0aGlzLl9nZXRTYXZlRmllbGRSZXNvdXJjZXMoeHJlZik7CiAgICAgIGNvbnN0IGFwcGVhcmFuY2VTdHJlYW0gPSBuZXcgX3N0cmVhbS5TdHJpbmdTdHJlYW0oYXBwZWFyYW5jZSk7CiAgICAgIGNvbnN0IGFwcGVhcmFuY2VEaWN0ID0gYXBwZWFyYW5jZVN0cmVhbS5kaWN0ID0gbmV3IF9wcmltaXRpdmVzLkRpY3QoeHJlZik7CiAgICAgIGFwcGVhcmFuY2VEaWN0LnNldCgiU3VidHlwZSIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJGb3JtIikpOwogICAgICBhcHBlYXJhbmNlRGljdC5zZXQoIlJlc291cmNlcyIsIHJlc291cmNlcyk7CiAgICAgIGFwcGVhcmFuY2VEaWN0LnNldCgiQkJveCIsIFswLCAwLCB0aGlzLmRhdGEucmVjdFsyXSAtIHRoaXMuZGF0YS5yZWN0WzBdLCB0aGlzLmRhdGEucmVjdFszXSAtIHRoaXMuZGF0YS5yZWN0WzFdXSk7CiAgICAgIGNvbnN0IHJvdGF0aW9uTWF0cml4ID0gdGhpcy5nZXRSb3RhdGlvbk1hdHJpeChhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICAgIGlmIChyb3RhdGlvbk1hdHJpeCAhPT0gX3V0aWwuSURFTlRJVFlfTUFUUklYKSB7CiAgICAgICAgYXBwZWFyYW5jZURpY3Quc2V0KCJNYXRyaXgiLCByb3RhdGlvbk1hdHJpeCk7CiAgICAgIH0KICAgICAgKDAsIF93cml0ZXIud3JpdGVPYmplY3QpKG5ld1JlZiwgYXBwZWFyYW5jZVN0cmVhbSwgYnVmZmVyLCBuZXdUcmFuc2Zvcm0pOwogICAgICBjaGFuZ2VzLnB1c2goewogICAgICAgIHJlZjogbmV3UmVmLAogICAgICAgIGRhdGE6IGJ1ZmZlci5qb2luKCIiKSwKICAgICAgICB4ZmE6IG51bGwsCiAgICAgICAgbmVlZEFwcGVhcmFuY2VzOiBmYWxzZQogICAgICB9KTsKICAgICAgYnVmZmVyLmxlbmd0aCA9IDA7CiAgICB9CiAgICBkaWN0LnNldCgiTSIsIGBEOiR7KDAsIF91dGlsLmdldE1vZGlmaWNhdGlvbkRhdGUpKCl9YCk7CiAgICAoMCwgX3dyaXRlci53cml0ZU9iamVjdCkodGhpcy5yZWYsIGRpY3QsIGJ1ZmZlciwgb3JpZ2luYWxUcmFuc2Zvcm0pOwogICAgY2hhbmdlc1swXS5kYXRhID0gYnVmZmVyLmpvaW4oIiIpOwogICAgcmV0dXJuIGNoYW5nZXM7CiAgfQogIGFzeW5jIF9nZXRBcHBlYXJhbmNlKGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgY29uc3QgaXNQYXNzd29yZCA9IHRoaXMuaGFzRmllbGRGbGFnKF91dGlsLkFubm90YXRpb25GaWVsZEZsYWcuUEFTU1dPUkQpOwogICAgaWYgKGlzUGFzc3dvcmQpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBzdG9yYWdlRW50cnkgPSBhbm5vdGF0aW9uU3RvcmFnZSA/IGFubm90YXRpb25TdG9yYWdlLmdldCh0aGlzLmRhdGEuaWQpIDogdW5kZWZpbmVkOwogICAgbGV0IHZhbHVlLCByb3RhdGlvbjsKICAgIGlmIChzdG9yYWdlRW50cnkpIHsKICAgICAgdmFsdWUgPSBzdG9yYWdlRW50cnkuZm9ybWF0dGVkVmFsdWUgfHwgc3RvcmFnZUVudHJ5LnZhbHVlOwogICAgICByb3RhdGlvbiA9IHN0b3JhZ2VFbnRyeS5yb3RhdGlvbjsKICAgIH0KICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkICYmIHZhbHVlID09PSB1bmRlZmluZWQgJiYgIXRoaXMuX25lZWRBcHBlYXJhbmNlcykgewogICAgICBpZiAoIXRoaXMuX2hhc1ZhbHVlRnJvbVhGQSB8fCB0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQogICAgY29uc3QgY29sb3JzID0gdGhpcy5nZXRCb3JkZXJBbmRCYWNrZ3JvdW5kQXBwZWFyYW5jZXMoYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgdmFsdWUgPSB0aGlzLmRhdGEuZmllbGRWYWx1ZTsKICAgICAgaWYgKCF2YWx1ZSkgewogICAgICAgIHJldHVybiBgL1R4IEJNQyBxICR7Y29sb3JzfVEgRU1DYDsKICAgICAgfQogICAgfQogICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA9PT0gMSkgewogICAgICB2YWx1ZSA9IHZhbHVlWzBdOwogICAgfQogICAgKDAsIF91dGlsLmFzc2VydCkodHlwZW9mIHZhbHVlID09PSAic3RyaW5nIiwgIkV4cGVjdGVkIGB2YWx1ZWAgdG8gYmUgYSBzdHJpbmcuIik7CiAgICB2YWx1ZSA9IHZhbHVlLnRyaW0oKTsKICAgIGlmICh0aGlzLmRhdGEuY29tYm8pIHsKICAgICAgY29uc3Qgb3B0aW9uID0gdGhpcy5kYXRhLm9wdGlvbnMuZmluZChfcmVmMyA9PiB7CiAgICAgICAgbGV0IHsKICAgICAgICAgIGV4cG9ydFZhbHVlCiAgICAgICAgfSA9IF9yZWYzOwogICAgICAgIHJldHVybiB2YWx1ZSA9PT0gZXhwb3J0VmFsdWU7CiAgICAgIH0pOwogICAgICB2YWx1ZSA9IG9wdGlvbiAmJiBvcHRpb24uZGlzcGxheVZhbHVlIHx8IHZhbHVlOwogICAgfQogICAgaWYgKHZhbHVlID09PSAiIikgewogICAgICByZXR1cm4gYC9UeCBCTUMgcSAke2NvbG9yc31RIEVNQ2A7CiAgICB9CiAgICBpZiAocm90YXRpb24gPT09IHVuZGVmaW5lZCkgewogICAgICByb3RhdGlvbiA9IHRoaXMucm90YXRpb247CiAgICB9CiAgICBsZXQgbGluZUNvdW50ID0gLTE7CiAgICBsZXQgbGluZXM7CiAgICBpZiAodGhpcy5kYXRhLm11bHRpTGluZSkgewogICAgICBsaW5lcyA9IHZhbHVlLnNwbGl0KC9cclxuP3xcbi8pLm1hcChsaW5lID0+IGxpbmUubm9ybWFsaXplKCJORkMiKSk7CiAgICAgIGxpbmVDb3VudCA9IGxpbmVzLmxlbmd0aDsKICAgIH0gZWxzZSB7CiAgICAgIGxpbmVzID0gW3ZhbHVlLnJlcGxhY2UoL1xyXG4/fFxuLywgIiIpLm5vcm1hbGl6ZSgiTkZDIildOwogICAgfQogICAgY29uc3QgZGVmYXVsdFBhZGRpbmcgPSAxOwogICAgY29uc3QgZGVmYXVsdEhQYWRkaW5nID0gMjsKICAgIGxldCB0b3RhbEhlaWdodCA9IHRoaXMuZGF0YS5yZWN0WzNdIC0gdGhpcy5kYXRhLnJlY3RbMV07CiAgICBsZXQgdG90YWxXaWR0aCA9IHRoaXMuZGF0YS5yZWN0WzJdIC0gdGhpcy5kYXRhLnJlY3RbMF07CiAgICBpZiAocm90YXRpb24gPT09IDkwIHx8IHJvdGF0aW9uID09PSAyNzApIHsKICAgICAgW3RvdGFsV2lkdGgsIHRvdGFsSGVpZ2h0XSA9IFt0b3RhbEhlaWdodCwgdG90YWxXaWR0aF07CiAgICB9CiAgICBpZiAoIXRoaXMuX2RlZmF1bHRBcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEgPSAoMCwgX2RlZmF1bHRfYXBwZWFyYW5jZS5wYXJzZURlZmF1bHRBcHBlYXJhbmNlKSh0aGlzLl9kZWZhdWx0QXBwZWFyYW5jZSA9ICIvSGVsdmV0aWNhIDAgVGYgMCBnIik7CiAgICB9CiAgICBsZXQgZm9udCA9IGF3YWl0IFdpZGdldEFubm90YXRpb24uX2dldEZvbnREYXRhKGV2YWx1YXRvciwgdGFzaywgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YSwgdGhpcy5fZmllbGRSZXNvdXJjZXMubWVyZ2VkUmVzb3VyY2VzKTsKICAgIGxldCBkZWZhdWx0QXBwZWFyYW5jZSwgZm9udFNpemUsIGxpbmVIZWlnaHQ7CiAgICBjb25zdCBlbmNvZGVkTGluZXMgPSBbXTsKICAgIGxldCBlbmNvZGluZ0Vycm9yID0gZmFsc2U7CiAgICBmb3IgKGNvbnN0IGxpbmUgb2YgbGluZXMpIHsKICAgICAgY29uc3QgZW5jb2RlZFN0cmluZyA9IGZvbnQuZW5jb2RlU3RyaW5nKGxpbmUpOwogICAgICBpZiAoZW5jb2RlZFN0cmluZy5sZW5ndGggPiAxKSB7CiAgICAgICAgZW5jb2RpbmdFcnJvciA9IHRydWU7CiAgICAgIH0KICAgICAgZW5jb2RlZExpbmVzLnB1c2goZW5jb2RlZFN0cmluZy5qb2luKCIiKSk7CiAgICB9CiAgICBpZiAoZW5jb2RpbmdFcnJvciAmJiBpbnRlbnQgJiBfdXRpbC5SZW5kZXJpbmdJbnRlbnRGbGFnLlNBVkUpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBuZWVkQXBwZWFyYW5jZXM6IHRydWUKICAgICAgfTsKICAgIH0KICAgIGlmIChlbmNvZGluZ0Vycm9yICYmIHRoaXMuX2lzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKSB7CiAgICAgIGNvbnN0IGZvbnRGYW1pbHkgPSB0aGlzLmRhdGEuY29tYiA/ICJtb25vc3BhY2UiIDogInNhbnMtc2VyaWYiOwogICAgICBjb25zdCBmYWtlVW5pY29kZUZvbnQgPSBuZXcgX2RlZmF1bHRfYXBwZWFyYW5jZS5GYWtlVW5pY29kZUZvbnQoZXZhbHVhdG9yLnhyZWYsIGZvbnRGYW1pbHkpOwogICAgICBjb25zdCByZXNvdXJjZXMgPSBmYWtlVW5pY29kZUZvbnQuY3JlYXRlRm9udFJlc291cmNlcyhsaW5lcy5qb2luKCIiKSk7CiAgICAgIGNvbnN0IG5ld0ZvbnQgPSByZXNvdXJjZXMuZ2V0UmF3KCJGb250Iik7CiAgICAgIGlmICh0aGlzLl9maWVsZFJlc291cmNlcy5tZXJnZWRSZXNvdXJjZXMuaGFzKCJGb250IikpIHsKICAgICAgICBjb25zdCBvbGRGb250ID0gdGhpcy5fZmllbGRSZXNvdXJjZXMubWVyZ2VkUmVzb3VyY2VzLmdldCgiRm9udCIpOwogICAgICAgIGZvciAoY29uc3Qga2V5IG9mIG5ld0ZvbnQuZ2V0S2V5cygpKSB7CiAgICAgICAgICBvbGRGb250LnNldChrZXksIG5ld0ZvbnQuZ2V0UmF3KGtleSkpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLl9maWVsZFJlc291cmNlcy5tZXJnZWRSZXNvdXJjZXMuc2V0KCJGb250IiwgbmV3Rm9udCk7CiAgICAgIH0KICAgICAgY29uc3QgZm9udE5hbWUgPSBmYWtlVW5pY29kZUZvbnQuZm9udE5hbWUubmFtZTsKICAgICAgZm9udCA9IGF3YWl0IFdpZGdldEFubm90YXRpb24uX2dldEZvbnREYXRhKGV2YWx1YXRvciwgdGFzaywgewogICAgICAgIGZvbnROYW1lLAogICAgICAgIGZvbnRTaXplOiAwCiAgICAgIH0sIHJlc291cmNlcyk7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGVuY29kZWRMaW5lcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgZW5jb2RlZExpbmVzW2ldID0gKDAsIF9jb3JlX3V0aWxzLnN0cmluZ1RvVVRGMTZTdHJpbmcpKGxpbmVzW2ldKTsKICAgICAgfQogICAgICBjb25zdCBzYXZlZERlZmF1bHRBcHBlYXJhbmNlID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG51bGwpLCB0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhKTsKICAgICAgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YS5mb250U2l6ZSA9IDA7CiAgICAgIHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEuZm9udE5hbWUgPSBmb250TmFtZTsKICAgICAgW2RlZmF1bHRBcHBlYXJhbmNlLCBmb250U2l6ZSwgbGluZUhlaWdodF0gPSB0aGlzLl9jb21wdXRlRm9udFNpemUodG90YWxIZWlnaHQgLSAyICogZGVmYXVsdFBhZGRpbmcsIHRvdGFsV2lkdGggLSAyICogZGVmYXVsdEhQYWRkaW5nLCB2YWx1ZSwgZm9udCwgbGluZUNvdW50KTsKICAgICAgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YSA9IHNhdmVkRGVmYXVsdEFwcGVhcmFuY2U7CiAgICB9IGVsc2UgewogICAgICBpZiAoIXRoaXMuX2lzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKCJfZ2V0QXBwZWFyYW5jZTogT2Zmc2NyZWVuQ2FudmFzIGlzIG5vdCBzdXBwb3J0ZWQsIGFubm90YXRpb24gbWF5IG5vdCByZW5kZXIgY29ycmVjdGx5LiIpOwogICAgICB9CiAgICAgIFtkZWZhdWx0QXBwZWFyYW5jZSwgZm9udFNpemUsIGxpbmVIZWlnaHRdID0gdGhpcy5fY29tcHV0ZUZvbnRTaXplKHRvdGFsSGVpZ2h0IC0gMiAqIGRlZmF1bHRQYWRkaW5nLCB0b3RhbFdpZHRoIC0gMiAqIGRlZmF1bHRIUGFkZGluZywgdmFsdWUsIGZvbnQsIGxpbmVDb3VudCk7CiAgICB9CiAgICBsZXQgZGVzY2VudCA9IGZvbnQuZGVzY2VudDsKICAgIGlmIChpc05hTihkZXNjZW50KSkgewogICAgICBkZXNjZW50ID0gX3V0aWwuQkFTRUxJTkVfRkFDVE9SICogbGluZUhlaWdodDsKICAgIH0gZWxzZSB7CiAgICAgIGRlc2NlbnQgPSBNYXRoLm1heChfdXRpbC5CQVNFTElORV9GQUNUT1IgKiBsaW5lSGVpZ2h0LCBNYXRoLmFicyhkZXNjZW50KSAqIGZvbnRTaXplKTsKICAgIH0KICAgIGNvbnN0IGRlZmF1bHRWUGFkZGluZyA9IE1hdGgubWluKE1hdGguZmxvb3IoKHRvdGFsSGVpZ2h0IC0gZm9udFNpemUpIC8gMiksIGRlZmF1bHRQYWRkaW5nKTsKICAgIGNvbnN0IGFsaWdubWVudCA9IHRoaXMuZGF0YS50ZXh0QWxpZ25tZW50OwogICAgaWYgKHRoaXMuZGF0YS5tdWx0aUxpbmUpIHsKICAgICAgcmV0dXJuIHRoaXMuX2dldE11bHRpbGluZUFwcGVhcmFuY2UoZGVmYXVsdEFwcGVhcmFuY2UsIGVuY29kZWRMaW5lcywgZm9udCwgZm9udFNpemUsIHRvdGFsV2lkdGgsIHRvdGFsSGVpZ2h0LCBhbGlnbm1lbnQsIGRlZmF1bHRIUGFkZGluZywgZGVmYXVsdFZQYWRkaW5nLCBkZXNjZW50LCBsaW5lSGVpZ2h0LCBhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICB9CiAgICBpZiAodGhpcy5kYXRhLmNvbWIpIHsKICAgICAgcmV0dXJuIHRoaXMuX2dldENvbWJBcHBlYXJhbmNlKGRlZmF1bHRBcHBlYXJhbmNlLCBmb250LCBlbmNvZGVkTGluZXNbMF0sIGZvbnRTaXplLCB0b3RhbFdpZHRoLCB0b3RhbEhlaWdodCwgZGVmYXVsdEhQYWRkaW5nLCBkZWZhdWx0VlBhZGRpbmcsIGRlc2NlbnQsIGxpbmVIZWlnaHQsIGFubm90YXRpb25TdG9yYWdlKTsKICAgIH0KICAgIGNvbnN0IGJvdHRvbVBhZGRpbmcgPSBkZWZhdWx0VlBhZGRpbmcgKyBkZXNjZW50OwogICAgaWYgKGFsaWdubWVudCA9PT0gMCB8fCBhbGlnbm1lbnQgPiAyKSB7CiAgICAgIHJldHVybiBgL1R4IEJNQyBxICR7Y29sb3JzfUJUIGAgKyBkZWZhdWx0QXBwZWFyYW5jZSArIGAgMSAwIDAgMSAkeygwLCBfY29yZV91dGlscy5udW1iZXJUb1N0cmluZykoZGVmYXVsdEhQYWRkaW5nKX0gJHsoMCwgX2NvcmVfdXRpbHMubnVtYmVyVG9TdHJpbmcpKGJvdHRvbVBhZGRpbmcpfSBUbSAoJHsoMCwgX2NvcmVfdXRpbHMuZXNjYXBlU3RyaW5nKShlbmNvZGVkTGluZXNbMF0pfSkgVGpgICsgIiBFVCBRIEVNQyI7CiAgICB9CiAgICBjb25zdCBwcmV2SW5mbyA9IHsKICAgICAgc2hpZnQ6IDAKICAgIH07CiAgICBjb25zdCByZW5kZXJlZFRleHQgPSB0aGlzLl9yZW5kZXJUZXh0KGVuY29kZWRMaW5lc1swXSwgZm9udCwgZm9udFNpemUsIHRvdGFsV2lkdGgsIGFsaWdubWVudCwgcHJldkluZm8sIGRlZmF1bHRIUGFkZGluZywgYm90dG9tUGFkZGluZyk7CiAgICByZXR1cm4gYC9UeCBCTUMgcSAke2NvbG9yc31CVCBgICsgZGVmYXVsdEFwcGVhcmFuY2UgKyBgIDEgMCAwIDEgMCAwIFRtICR7cmVuZGVyZWRUZXh0fWAgKyAiIEVUIFEgRU1DIjsKICB9CiAgc3RhdGljIGFzeW5jIF9nZXRGb250RGF0YShldmFsdWF0b3IsIHRhc2ssIGFwcGVhcmFuY2VEYXRhLCByZXNvdXJjZXMpIHsKICAgIGNvbnN0IG9wZXJhdG9yTGlzdCA9IG5ldyBfb3BlcmF0b3JfbGlzdC5PcGVyYXRvckxpc3QoKTsKICAgIGNvbnN0IGluaXRpYWxTdGF0ZSA9IHsKICAgICAgZm9udDogbnVsbCwKICAgICAgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgIH07CiAgICBjb25zdCB7CiAgICAgIGZvbnROYW1lLAogICAgICBmb250U2l6ZQogICAgfSA9IGFwcGVhcmFuY2VEYXRhOwogICAgYXdhaXQgZXZhbHVhdG9yLmhhbmRsZVNldEZvbnQocmVzb3VyY2VzLCBbZm9udE5hbWUgJiYgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoZm9udE5hbWUpLCBmb250U2l6ZV0sIG51bGwsIG9wZXJhdG9yTGlzdCwgdGFzaywgaW5pdGlhbFN0YXRlLCBudWxsKTsKICAgIHJldHVybiBpbml0aWFsU3RhdGUuZm9udDsKICB9CiAgX2dldFRleHRXaWR0aCh0ZXh0LCBmb250KSB7CiAgICByZXR1cm4gZm9udC5jaGFyc1RvR2x5cGhzKHRleHQpLnJlZHVjZSgod2lkdGgsIGdseXBoKSA9PiB3aWR0aCArIGdseXBoLndpZHRoLCAwKSAvIDEwMDA7CiAgfQogIF9jb21wdXRlRm9udFNpemUoaGVpZ2h0LCB3aWR0aCwgdGV4dCwgZm9udCwgbGluZUNvdW50KSB7CiAgICBsZXQgewogICAgICBmb250U2l6ZQogICAgfSA9IHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGE7CiAgICBsZXQgbGluZUhlaWdodCA9IChmb250U2l6ZSB8fCAxMikgKiBfdXRpbC5MSU5FX0ZBQ1RPUiwKICAgICAgbnVtYmVyT2ZMaW5lcyA9IE1hdGgucm91bmQoaGVpZ2h0IC8gbGluZUhlaWdodCk7CiAgICBpZiAoIWZvbnRTaXplKSB7CiAgICAgIGNvbnN0IHJvdW5kV2l0aFR3b0RpZ2l0cyA9IHggPT4gTWF0aC5mbG9vcih4ICogMTAwKSAvIDEwMDsKICAgICAgaWYgKGxpbmVDb3VudCA9PT0gLTEpIHsKICAgICAgICBjb25zdCB0ZXh0V2lkdGggPSB0aGlzLl9nZXRUZXh0V2lkdGgodGV4dCwgZm9udCk7CiAgICAgICAgZm9udFNpemUgPSByb3VuZFdpdGhUd29EaWdpdHMoTWF0aC5taW4oaGVpZ2h0IC8gX3V0aWwuTElORV9GQUNUT1IsIHRleHRXaWR0aCA+IHdpZHRoID8gd2lkdGggLyB0ZXh0V2lkdGggOiBJbmZpbml0eSkpOwogICAgICAgIG51bWJlck9mTGluZXMgPSAxOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IGxpbmVzID0gdGV4dC5zcGxpdCgvXHJcbj98XG4vKTsKICAgICAgICBjb25zdCBjYWNoZWRMaW5lcyA9IFtdOwogICAgICAgIGZvciAoY29uc3QgbGluZSBvZiBsaW5lcykgewogICAgICAgICAgY29uc3QgZW5jb2RlZCA9IGZvbnQuZW5jb2RlU3RyaW5nKGxpbmUpLmpvaW4oIiIpOwogICAgICAgICAgY29uc3QgZ2x5cGhzID0gZm9udC5jaGFyc1RvR2x5cGhzKGVuY29kZWQpOwogICAgICAgICAgY29uc3QgcG9zaXRpb25zID0gZm9udC5nZXRDaGFyUG9zaXRpb25zKGVuY29kZWQpOwogICAgICAgICAgY2FjaGVkTGluZXMucHVzaCh7CiAgICAgICAgICAgIGxpbmU6IGVuY29kZWQsCiAgICAgICAgICAgIGdseXBocywKICAgICAgICAgICAgcG9zaXRpb25zCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgaXNUb29CaWcgPSBmc2l6ZSA9PiB7CiAgICAgICAgICBsZXQgdG90YWxIZWlnaHQgPSAwOwogICAgICAgICAgZm9yIChjb25zdCBjYWNoZSBvZiBjYWNoZWRMaW5lcykgewogICAgICAgICAgICBjb25zdCBjaHVua3MgPSB0aGlzLl9zcGxpdExpbmUobnVsbCwgZm9udCwgZnNpemUsIHdpZHRoLCBjYWNoZSk7CiAgICAgICAgICAgIHRvdGFsSGVpZ2h0ICs9IGNodW5rcy5sZW5ndGggKiBmc2l6ZTsKICAgICAgICAgICAgaWYgKHRvdGFsSGVpZ2h0ID4gaGVpZ2h0KSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9OwogICAgICAgIG51bWJlck9mTGluZXMgPSBNYXRoLm1heChudW1iZXJPZkxpbmVzLCBsaW5lQ291bnQpOwogICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICBsaW5lSGVpZ2h0ID0gaGVpZ2h0IC8gbnVtYmVyT2ZMaW5lczsKICAgICAgICAgIGZvbnRTaXplID0gcm91bmRXaXRoVHdvRGlnaXRzKGxpbmVIZWlnaHQgLyBfdXRpbC5MSU5FX0ZBQ1RPUik7CiAgICAgICAgICBpZiAoaXNUb29CaWcoZm9udFNpemUpKSB7CiAgICAgICAgICAgIG51bWJlck9mTGluZXMrKzsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgewogICAgICAgIGZvbnROYW1lLAogICAgICAgIGZvbnRDb2xvcgogICAgICB9ID0gdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YTsKICAgICAgdGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UgPSAoMCwgX2RlZmF1bHRfYXBwZWFyYW5jZS5jcmVhdGVEZWZhdWx0QXBwZWFyYW5jZSkoewogICAgICAgIGZvbnRTaXplLAogICAgICAgIGZvbnROYW1lLAogICAgICAgIGZvbnRDb2xvcgogICAgICB9KTsKICAgIH0KICAgIHJldHVybiBbdGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UsIGZvbnRTaXplLCBoZWlnaHQgLyBudW1iZXJPZkxpbmVzXTsKICB9CiAgX3JlbmRlclRleHQodGV4dCwgZm9udCwgZm9udFNpemUsIHRvdGFsV2lkdGgsIGFsaWdubWVudCwgcHJldkluZm8sIGhQYWRkaW5nLCB2UGFkZGluZykgewogICAgbGV0IHNoaWZ0OwogICAgaWYgKGFsaWdubWVudCA9PT0gMSkgewogICAgICBjb25zdCB3aWR0aCA9IHRoaXMuX2dldFRleHRXaWR0aCh0ZXh0LCBmb250KSAqIGZvbnRTaXplOwogICAgICBzaGlmdCA9ICh0b3RhbFdpZHRoIC0gd2lkdGgpIC8gMjsKICAgIH0gZWxzZSBpZiAoYWxpZ25tZW50ID09PSAyKSB7CiAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5fZ2V0VGV4dFdpZHRoKHRleHQsIGZvbnQpICogZm9udFNpemU7CiAgICAgIHNoaWZ0ID0gdG90YWxXaWR0aCAtIHdpZHRoIC0gaFBhZGRpbmc7CiAgICB9IGVsc2UgewogICAgICBzaGlmdCA9IGhQYWRkaW5nOwogICAgfQogICAgY29uc3Qgc2hpZnRTdHIgPSAoMCwgX2NvcmVfdXRpbHMubnVtYmVyVG9TdHJpbmcpKHNoaWZ0IC0gcHJldkluZm8uc2hpZnQpOwogICAgcHJldkluZm8uc2hpZnQgPSBzaGlmdDsKICAgIHZQYWRkaW5nID0gKDAsIF9jb3JlX3V0aWxzLm51bWJlclRvU3RyaW5nKSh2UGFkZGluZyk7CiAgICByZXR1cm4gYCR7c2hpZnRTdHJ9ICR7dlBhZGRpbmd9IFRkICgkeygwLCBfY29yZV91dGlscy5lc2NhcGVTdHJpbmcpKHRleHQpfSkgVGpgOwogIH0KICBfZ2V0U2F2ZUZpZWxkUmVzb3VyY2VzKHhyZWYpIHsKICAgIGNvbnN0IHsKICAgICAgbG9jYWxSZXNvdXJjZXMsCiAgICAgIGFwcGVhcmFuY2VSZXNvdXJjZXMsCiAgICAgIGFjcm9Gb3JtUmVzb3VyY2VzCiAgICB9ID0gdGhpcy5fZmllbGRSZXNvdXJjZXM7CiAgICBjb25zdCBmb250TmFtZSA9IHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEgJiYgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YS5mb250TmFtZTsKICAgIGlmICghZm9udE5hbWUpIHsKICAgICAgcmV0dXJuIGxvY2FsUmVzb3VyY2VzIHx8IF9wcmltaXRpdmVzLkRpY3QuZW1wdHk7CiAgICB9CiAgICBmb3IgKGNvbnN0IHJlc291cmNlcyBvZiBbbG9jYWxSZXNvdXJjZXMsIGFwcGVhcmFuY2VSZXNvdXJjZXNdKSB7CiAgICAgIGlmIChyZXNvdXJjZXMgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgICAgY29uc3QgbG9jYWxGb250ID0gcmVzb3VyY2VzLmdldCgiRm9udCIpOwogICAgICAgIGlmIChsb2NhbEZvbnQgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0ICYmIGxvY2FsRm9udC5oYXMoZm9udE5hbWUpKSB7CiAgICAgICAgICByZXR1cm4gcmVzb3VyY2VzOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKGFjcm9Gb3JtUmVzb3VyY2VzIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICBjb25zdCBhY3JvRm9ybUZvbnQgPSBhY3JvRm9ybVJlc291cmNlcy5nZXQoIkZvbnQiKTsKICAgICAgaWYgKGFjcm9Gb3JtRm9udCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QgJiYgYWNyb0Zvcm1Gb250Lmhhcyhmb250TmFtZSkpIHsKICAgICAgICBjb25zdCBzdWJGb250RGljdCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHhyZWYpOwogICAgICAgIHN1YkZvbnREaWN0LnNldChmb250TmFtZSwgYWNyb0Zvcm1Gb250LmdldFJhdyhmb250TmFtZSkpOwogICAgICAgIGNvbnN0IHN1YlJlc291cmNlc0RpY3QgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdCh4cmVmKTsKICAgICAgICBzdWJSZXNvdXJjZXNEaWN0LnNldCgiRm9udCIsIHN1YkZvbnREaWN0KTsKICAgICAgICByZXR1cm4gX3ByaW1pdGl2ZXMuRGljdC5tZXJnZSh7CiAgICAgICAgICB4cmVmLAogICAgICAgICAgZGljdEFycmF5OiBbc3ViUmVzb3VyY2VzRGljdCwgbG9jYWxSZXNvdXJjZXNdLAogICAgICAgICAgbWVyZ2VTdWJEaWN0czogdHJ1ZQogICAgICAgIH0pOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbG9jYWxSZXNvdXJjZXMgfHwgX3ByaW1pdGl2ZXMuRGljdC5lbXB0eTsKICB9CiAgZ2V0RmllbGRPYmplY3QoKSB7CiAgICByZXR1cm4gbnVsbDsKICB9Cn0KY2xhc3MgVGV4dFdpZGdldEFubm90YXRpb24gZXh0ZW5kcyBXaWRnZXRBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICB0aGlzLl9oYXNUZXh0ID0gdHJ1ZTsKICAgIGNvbnN0IGRpY3QgPSBwYXJhbXMuZGljdDsKICAgIGlmICh0eXBlb2YgdGhpcy5kYXRhLmZpZWxkVmFsdWUgIT09ICJzdHJpbmciKSB7CiAgICAgIHRoaXMuZGF0YS5maWVsZFZhbHVlID0gIiI7CiAgICB9CiAgICBsZXQgYWxpZ25tZW50ID0gKDAsIF9jb3JlX3V0aWxzLmdldEluaGVyaXRhYmxlUHJvcGVydHkpKHsKICAgICAgZGljdCwKICAgICAga2V5OiAiUSIKICAgIH0pOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGFsaWdubWVudCkgfHwgYWxpZ25tZW50IDwgMCB8fCBhbGlnbm1lbnQgPiAyKSB7CiAgICAgIGFsaWdubWVudCA9IG51bGw7CiAgICB9CiAgICB0aGlzLmRhdGEudGV4dEFsaWdubWVudCA9IGFsaWdubWVudDsKICAgIGxldCBtYXhpbXVtTGVuZ3RoID0gKDAsIF9jb3JlX3V0aWxzLmdldEluaGVyaXRhYmxlUHJvcGVydHkpKHsKICAgICAgZGljdCwKICAgICAga2V5OiAiTWF4TGVuIgogICAgfSk7CiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIobWF4aW11bUxlbmd0aCkgfHwgbWF4aW11bUxlbmd0aCA8IDApIHsKICAgICAgbWF4aW11bUxlbmd0aCA9IDA7CiAgICB9CiAgICB0aGlzLmRhdGEubWF4TGVuID0gbWF4aW11bUxlbmd0aDsKICAgIHRoaXMuZGF0YS5tdWx0aUxpbmUgPSB0aGlzLmhhc0ZpZWxkRmxhZyhfdXRpbC5Bbm5vdGF0aW9uRmllbGRGbGFnLk1VTFRJTElORSk7CiAgICB0aGlzLmRhdGEuY29tYiA9IHRoaXMuaGFzRmllbGRGbGFnKF91dGlsLkFubm90YXRpb25GaWVsZEZsYWcuQ09NQikgJiYgIXRoaXMuaGFzRmllbGRGbGFnKF91dGlsLkFubm90YXRpb25GaWVsZEZsYWcuTVVMVElMSU5FKSAmJiAhdGhpcy5oYXNGaWVsZEZsYWcoX3V0aWwuQW5ub3RhdGlvbkZpZWxkRmxhZy5QQVNTV09SRCkgJiYgIXRoaXMuaGFzRmllbGRGbGFnKF91dGlsLkFubm90YXRpb25GaWVsZEZsYWcuRklMRVNFTEVDVCkgJiYgdGhpcy5kYXRhLm1heExlbiAhPT0gMDsKICAgIHRoaXMuZGF0YS5kb05vdFNjcm9sbCA9IHRoaXMuaGFzRmllbGRGbGFnKF91dGlsLkFubm90YXRpb25GaWVsZEZsYWcuRE9OT1RTQ1JPTEwpOwogIH0KICBfZ2V0Q29tYkFwcGVhcmFuY2UoZGVmYXVsdEFwcGVhcmFuY2UsIGZvbnQsIHRleHQsIGZvbnRTaXplLCB3aWR0aCwgaGVpZ2h0LCBoUGFkZGluZywgdlBhZGRpbmcsIGRlc2NlbnQsIGxpbmVIZWlnaHQsIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBjb25zdCBjb21iV2lkdGggPSB3aWR0aCAvIHRoaXMuZGF0YS5tYXhMZW47CiAgICBjb25zdCBjb2xvcnMgPSB0aGlzLmdldEJvcmRlckFuZEJhY2tncm91bmRBcHBlYXJhbmNlcyhhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICBjb25zdCBidWYgPSBbXTsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IGZvbnQuZ2V0Q2hhclBvc2l0aW9ucyh0ZXh0KTsKICAgIGZvciAoY29uc3QgW3N0YXJ0LCBlbmRdIG9mIHBvc2l0aW9ucykgewogICAgICBidWYucHVzaChgKCR7KDAsIF9jb3JlX3V0aWxzLmVzY2FwZVN0cmluZykodGV4dC5zdWJzdHJpbmcoc3RhcnQsIGVuZCkpfSkgVGpgKTsKICAgIH0KICAgIGNvbnN0IHJlbmRlcmVkQ29tYiA9IGJ1Zi5qb2luKGAgJHsoMCwgX2NvcmVfdXRpbHMubnVtYmVyVG9TdHJpbmcpKGNvbWJXaWR0aCl9IDAgVGQgYCk7CiAgICByZXR1cm4gYC9UeCBCTUMgcSAke2NvbG9yc31CVCBgICsgZGVmYXVsdEFwcGVhcmFuY2UgKyBgIDEgMCAwIDEgJHsoMCwgX2NvcmVfdXRpbHMubnVtYmVyVG9TdHJpbmcpKGhQYWRkaW5nKX0gJHsoMCwgX2NvcmVfdXRpbHMubnVtYmVyVG9TdHJpbmcpKHZQYWRkaW5nICsgZGVzY2VudCl9IFRtICR7cmVuZGVyZWRDb21ifWAgKyAiIEVUIFEgRU1DIjsKICB9CiAgX2dldE11bHRpbGluZUFwcGVhcmFuY2UoZGVmYXVsdEFwcGVhcmFuY2UsIGxpbmVzLCBmb250LCBmb250U2l6ZSwgd2lkdGgsIGhlaWdodCwgYWxpZ25tZW50LCBoUGFkZGluZywgdlBhZGRpbmcsIGRlc2NlbnQsIGxpbmVIZWlnaHQsIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBjb25zdCBidWYgPSBbXTsKICAgIGNvbnN0IHRvdGFsV2lkdGggPSB3aWR0aCAtIDIgKiBoUGFkZGluZzsKICAgIGNvbnN0IHByZXZJbmZvID0gewogICAgICBzaGlmdDogMAogICAgfTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGxpbmVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgbGluZSA9IGxpbmVzW2ldOwogICAgICBjb25zdCBjaHVua3MgPSB0aGlzLl9zcGxpdExpbmUobGluZSwgZm9udCwgZm9udFNpemUsIHRvdGFsV2lkdGgpOwogICAgICBmb3IgKGxldCBqID0gMCwgamogPSBjaHVua3MubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICAgIGNvbnN0IGNodW5rID0gY2h1bmtzW2pdOwogICAgICAgIGNvbnN0IHZTaGlmdCA9IGkgPT09IDAgJiYgaiA9PT0gMCA/IC12UGFkZGluZyAtIChsaW5lSGVpZ2h0IC0gZGVzY2VudCkgOiAtbGluZUhlaWdodDsKICAgICAgICBidWYucHVzaCh0aGlzLl9yZW5kZXJUZXh0KGNodW5rLCBmb250LCBmb250U2l6ZSwgd2lkdGgsIGFsaWdubWVudCwgcHJldkluZm8sIGhQYWRkaW5nLCB2U2hpZnQpKTsKICAgICAgfQogICAgfQogICAgY29uc3QgY29sb3JzID0gdGhpcy5nZXRCb3JkZXJBbmRCYWNrZ3JvdW5kQXBwZWFyYW5jZXMoYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgY29uc3QgcmVuZGVyZWRUZXh0ID0gYnVmLmpvaW4oIlxuIik7CiAgICByZXR1cm4gYC9UeCBCTUMgcSAke2NvbG9yc31CVCBgICsgZGVmYXVsdEFwcGVhcmFuY2UgKyBgIDEgMCAwIDEgMCAkeygwLCBfY29yZV91dGlscy5udW1iZXJUb1N0cmluZykoaGVpZ2h0KX0gVG0gJHtyZW5kZXJlZFRleHR9YCArICIgRVQgUSBFTUMiOwogIH0KICBfc3BsaXRMaW5lKGxpbmUsIGZvbnQsIGZvbnRTaXplLCB3aWR0aCkgewogICAgbGV0IGNhY2hlID0gYXJndW1lbnRzLmxlbmd0aCA+IDQgJiYgYXJndW1lbnRzWzRdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbNF0gOiB7fTsKICAgIGxpbmUgPSBjYWNoZS5saW5lIHx8IGxpbmU7CiAgICBjb25zdCBnbHlwaHMgPSBjYWNoZS5nbHlwaHMgfHwgZm9udC5jaGFyc1RvR2x5cGhzKGxpbmUpOwogICAgaWYgKGdseXBocy5sZW5ndGggPD0gMSkgewogICAgICByZXR1cm4gW2xpbmVdOwogICAgfQogICAgY29uc3QgcG9zaXRpb25zID0gY2FjaGUucG9zaXRpb25zIHx8IGZvbnQuZ2V0Q2hhclBvc2l0aW9ucyhsaW5lKTsKICAgIGNvbnN0IHNjYWxlID0gZm9udFNpemUgLyAxMDAwOwogICAgY29uc3QgY2h1bmtzID0gW107CiAgICBsZXQgbGFzdFNwYWNlUG9zSW5TdHJpbmdTdGFydCA9IC0xLAogICAgICBsYXN0U3BhY2VQb3NJblN0cmluZ0VuZCA9IC0xLAogICAgICBsYXN0U3BhY2VQb3MgPSAtMSwKICAgICAgc3RhcnRDaHVuayA9IDAsCiAgICAgIGN1cnJlbnRXaWR0aCA9IDA7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBnbHlwaHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBbc3RhcnQsIGVuZF0gPSBwb3NpdGlvbnNbaV07CiAgICAgIGNvbnN0IGdseXBoID0gZ2x5cGhzW2ldOwogICAgICBjb25zdCBnbHlwaFdpZHRoID0gZ2x5cGgud2lkdGggKiBzY2FsZTsKICAgICAgaWYgKGdseXBoLnVuaWNvZGUgPT09ICIgIikgewogICAgICAgIGlmIChjdXJyZW50V2lkdGggKyBnbHlwaFdpZHRoID4gd2lkdGgpIHsKICAgICAgICAgIGNodW5rcy5wdXNoKGxpbmUuc3Vic3RyaW5nKHN0YXJ0Q2h1bmssIHN0YXJ0KSk7CiAgICAgICAgICBzdGFydENodW5rID0gc3RhcnQ7CiAgICAgICAgICBjdXJyZW50V2lkdGggPSBnbHlwaFdpZHRoOwogICAgICAgICAgbGFzdFNwYWNlUG9zSW5TdHJpbmdTdGFydCA9IC0xOwogICAgICAgICAgbGFzdFNwYWNlUG9zID0gLTE7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGN1cnJlbnRXaWR0aCArPSBnbHlwaFdpZHRoOwogICAgICAgICAgbGFzdFNwYWNlUG9zSW5TdHJpbmdTdGFydCA9IHN0YXJ0OwogICAgICAgICAgbGFzdFNwYWNlUG9zSW5TdHJpbmdFbmQgPSBlbmQ7CiAgICAgICAgICBsYXN0U3BhY2VQb3MgPSBpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAoY3VycmVudFdpZHRoICsgZ2x5cGhXaWR0aCA+IHdpZHRoKSB7CiAgICAgICAgICBpZiAobGFzdFNwYWNlUG9zSW5TdHJpbmdTdGFydCAhPT0gLTEpIHsKICAgICAgICAgICAgY2h1bmtzLnB1c2gobGluZS5zdWJzdHJpbmcoc3RhcnRDaHVuaywgbGFzdFNwYWNlUG9zSW5TdHJpbmdFbmQpKTsKICAgICAgICAgICAgc3RhcnRDaHVuayA9IGxhc3RTcGFjZVBvc0luU3RyaW5nRW5kOwogICAgICAgICAgICBpID0gbGFzdFNwYWNlUG9zICsgMTsKICAgICAgICAgICAgbGFzdFNwYWNlUG9zSW5TdHJpbmdTdGFydCA9IC0xOwogICAgICAgICAgICBjdXJyZW50V2lkdGggPSAwOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgY2h1bmtzLnB1c2gobGluZS5zdWJzdHJpbmcoc3RhcnRDaHVuaywgc3RhcnQpKTsKICAgICAgICAgICAgc3RhcnRDaHVuayA9IHN0YXJ0OwogICAgICAgICAgICBjdXJyZW50V2lkdGggPSBnbHlwaFdpZHRoOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjdXJyZW50V2lkdGggKz0gZ2x5cGhXaWR0aDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChzdGFydENodW5rIDwgbGluZS5sZW5ndGgpIHsKICAgICAgY2h1bmtzLnB1c2gobGluZS5zdWJzdHJpbmcoc3RhcnRDaHVuaywgbGluZS5sZW5ndGgpKTsKICAgIH0KICAgIHJldHVybiBjaHVua3M7CiAgfQogIGdldEZpZWxkT2JqZWN0KCkgewogICAgcmV0dXJuIHsKICAgICAgaWQ6IHRoaXMuZGF0YS5pZCwKICAgICAgdmFsdWU6IHRoaXMuZGF0YS5maWVsZFZhbHVlLAogICAgICBkZWZhdWx0VmFsdWU6IHRoaXMuZGF0YS5kZWZhdWx0RmllbGRWYWx1ZSB8fCAiIiwKICAgICAgbXVsdGlsaW5lOiB0aGlzLmRhdGEubXVsdGlMaW5lLAogICAgICBwYXNzd29yZDogdGhpcy5oYXNGaWVsZEZsYWcoX3V0aWwuQW5ub3RhdGlvbkZpZWxkRmxhZy5QQVNTV09SRCksCiAgICAgIGNoYXJMaW1pdDogdGhpcy5kYXRhLm1heExlbiwKICAgICAgY29tYjogdGhpcy5kYXRhLmNvbWIsCiAgICAgIGVkaXRhYmxlOiAhdGhpcy5kYXRhLnJlYWRPbmx5LAogICAgICBoaWRkZW46IHRoaXMuZGF0YS5oaWRkZW4sCiAgICAgIG5hbWU6IHRoaXMuZGF0YS5maWVsZE5hbWUsCiAgICAgIHJlY3Q6IHRoaXMuZGF0YS5yZWN0LAogICAgICBhY3Rpb25zOiB0aGlzLmRhdGEuYWN0aW9ucywKICAgICAgcGFnZTogdGhpcy5kYXRhLnBhZ2VJbmRleCwKICAgICAgc3Ryb2tlQ29sb3I6IHRoaXMuZGF0YS5ib3JkZXJDb2xvciwKICAgICAgZmlsbENvbG9yOiB0aGlzLmRhdGEuYmFja2dyb3VuZENvbG9yLAogICAgICByb3RhdGlvbjogdGhpcy5yb3RhdGlvbiwKICAgICAgdHlwZTogInRleHQiCiAgICB9OwogIH0KfQpjbGFzcyBCdXR0b25XaWRnZXRBbm5vdGF0aW9uIGV4dGVuZHMgV2lkZ2V0QW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgdGhpcy5jaGVja2VkQXBwZWFyYW5jZSA9IG51bGw7CiAgICB0aGlzLnVuY2hlY2tlZEFwcGVhcmFuY2UgPSBudWxsOwogICAgdGhpcy5kYXRhLmNoZWNrQm94ID0gIXRoaXMuaGFzRmllbGRGbGFnKF91dGlsLkFubm90YXRpb25GaWVsZEZsYWcuUkFESU8pICYmICF0aGlzLmhhc0ZpZWxkRmxhZyhfdXRpbC5Bbm5vdGF0aW9uRmllbGRGbGFnLlBVU0hCVVRUT04pOwogICAgdGhpcy5kYXRhLnJhZGlvQnV0dG9uID0gdGhpcy5oYXNGaWVsZEZsYWcoX3V0aWwuQW5ub3RhdGlvbkZpZWxkRmxhZy5SQURJTykgJiYgIXRoaXMuaGFzRmllbGRGbGFnKF91dGlsLkFubm90YXRpb25GaWVsZEZsYWcuUFVTSEJVVFRPTik7CiAgICB0aGlzLmRhdGEucHVzaEJ1dHRvbiA9IHRoaXMuaGFzRmllbGRGbGFnKF91dGlsLkFubm90YXRpb25GaWVsZEZsYWcuUFVTSEJVVFRPTik7CiAgICB0aGlzLmRhdGEuaXNUb29sdGlwT25seSA9IGZhbHNlOwogICAgaWYgKHRoaXMuZGF0YS5jaGVja0JveCkgewogICAgICB0aGlzLl9wcm9jZXNzQ2hlY2tCb3gocGFyYW1zKTsKICAgIH0gZWxzZSBpZiAodGhpcy5kYXRhLnJhZGlvQnV0dG9uKSB7CiAgICAgIHRoaXMuX3Byb2Nlc3NSYWRpb0J1dHRvbihwYXJhbXMpOwogICAgfSBlbHNlIGlmICh0aGlzLmRhdGEucHVzaEJ1dHRvbikgewogICAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdHJ1ZTsKICAgICAgdGhpcy5fcHJvY2Vzc1B1c2hCdXR0b24ocGFyYW1zKTsKICAgIH0gZWxzZSB7CiAgICAgICgwLCBfdXRpbC53YXJuKSgiSW52YWxpZCBmaWVsZCBmbGFncyBmb3IgYnV0dG9uIHdpZGdldCBhbm5vdGF0aW9uIik7CiAgICB9CiAgfQogIGFzeW5jIGdldE9wZXJhdG9yTGlzdChldmFsdWF0b3IsIHRhc2ssIGludGVudCwgcmVuZGVyRm9ybXMsIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBpZiAodGhpcy5kYXRhLnB1c2hCdXR0b24pIHsKICAgICAgcmV0dXJuIHN1cGVyLmdldE9wZXJhdG9yTGlzdChldmFsdWF0b3IsIHRhc2ssIGludGVudCwgZmFsc2UsIGFubm90YXRpb25TdG9yYWdlKTsKICAgIH0KICAgIGxldCB2YWx1ZSA9IG51bGw7CiAgICBsZXQgcm90YXRpb24gPSBudWxsOwogICAgaWYgKGFubm90YXRpb25TdG9yYWdlKSB7CiAgICAgIGNvbnN0IHN0b3JhZ2VFbnRyeSA9IGFubm90YXRpb25TdG9yYWdlLmdldCh0aGlzLmRhdGEuaWQpOwogICAgICB2YWx1ZSA9IHN0b3JhZ2VFbnRyeSA/IHN0b3JhZ2VFbnRyeS52YWx1ZSA6IG51bGw7CiAgICAgIHJvdGF0aW9uID0gc3RvcmFnZUVudHJ5ID8gc3RvcmFnZUVudHJ5LnJvdGF0aW9uIDogbnVsbDsKICAgIH0KICAgIGlmICh2YWx1ZSA9PT0gbnVsbCAmJiB0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgcmV0dXJuIHN1cGVyLmdldE9wZXJhdG9yTGlzdChldmFsdWF0b3IsIHRhc2ssIGludGVudCwgcmVuZGVyRm9ybXMsIGFubm90YXRpb25TdG9yYWdlKTsKICAgIH0KICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmICh0aGlzLmRhdGEuY2hlY2tCb3gpIHsKICAgICAgICB2YWx1ZSA9IHRoaXMuZGF0YS5maWVsZFZhbHVlID09PSB0aGlzLmRhdGEuZXhwb3J0VmFsdWU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdmFsdWUgPSB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9PT0gdGhpcy5kYXRhLmJ1dHRvblZhbHVlOwogICAgICB9CiAgICB9CiAgICBjb25zdCBhcHBlYXJhbmNlID0gdmFsdWUgPyB0aGlzLmNoZWNrZWRBcHBlYXJhbmNlIDogdGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlOwogICAgaWYgKGFwcGVhcmFuY2UpIHsKICAgICAgY29uc3Qgc2F2ZWRBcHBlYXJhbmNlID0gdGhpcy5hcHBlYXJhbmNlOwogICAgICBjb25zdCBzYXZlZE1hdHJpeCA9IGFwcGVhcmFuY2UuZGljdC5nZXRBcnJheSgiTWF0cml4IikgfHwgX3V0aWwuSURFTlRJVFlfTUFUUklYOwogICAgICBpZiAocm90YXRpb24pIHsKICAgICAgICBhcHBlYXJhbmNlLmRpY3Quc2V0KCJNYXRyaXgiLCB0aGlzLmdldFJvdGF0aW9uTWF0cml4KGFubm90YXRpb25TdG9yYWdlKSk7CiAgICAgIH0KICAgICAgdGhpcy5hcHBlYXJhbmNlID0gYXBwZWFyYW5jZTsKICAgICAgY29uc3Qgb3BlcmF0b3JMaXN0ID0gc3VwZXIuZ2V0T3BlcmF0b3JMaXN0KGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCByZW5kZXJGb3JtcywgYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgICB0aGlzLmFwcGVhcmFuY2UgPSBzYXZlZEFwcGVhcmFuY2U7CiAgICAgIGFwcGVhcmFuY2UuZGljdC5zZXQoIk1hdHJpeCIsIHNhdmVkTWF0cml4KTsKICAgICAgcmV0dXJuIG9wZXJhdG9yTGlzdDsKICAgIH0KICAgIHJldHVybiB7CiAgICAgIG9wTGlzdDogbmV3IF9vcGVyYXRvcl9saXN0Lk9wZXJhdG9yTGlzdCgpLAogICAgICBzZXBhcmF0ZUZvcm06IGZhbHNlLAogICAgICBzZXBhcmF0ZUNhbnZhczogZmFsc2UKICAgIH07CiAgfQogIGFzeW5jIHNhdmUoZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgaWYgKHRoaXMuZGF0YS5jaGVja0JveCkgewogICAgICByZXR1cm4gdGhpcy5fc2F2ZUNoZWNrYm94KGV2YWx1YXRvciwgdGFzaywgYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgfQogICAgaWYgKHRoaXMuZGF0YS5yYWRpb0J1dHRvbikgewogICAgICByZXR1cm4gdGhpcy5fc2F2ZVJhZGlvQnV0dG9uKGV2YWx1YXRvciwgdGFzaywgYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogIGFzeW5jIF9zYXZlQ2hlY2tib3goZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgaWYgKCFhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHN0b3JhZ2VFbnRyeSA9IGFubm90YXRpb25TdG9yYWdlLmdldCh0aGlzLmRhdGEuaWQpOwogICAgbGV0IHJvdGF0aW9uID0gc3RvcmFnZUVudHJ5ICYmIHN0b3JhZ2VFbnRyeS5yb3RhdGlvbjsKICAgIGxldCB2YWx1ZSA9IHN0b3JhZ2VFbnRyeSAmJiBzdG9yYWdlRW50cnkudmFsdWU7CiAgICBpZiAocm90YXRpb24gPT09IHVuZGVmaW5lZCkgewogICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IHRoaXMuZGF0YS5maWVsZFZhbHVlID09PSB0aGlzLmRhdGEuZXhwb3J0VmFsdWU7CiAgICAgIGlmIChkZWZhdWx0VmFsdWUgPT09IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGRpY3QgPSBldmFsdWF0b3IueHJlZi5mZXRjaElmUmVmKHRoaXMucmVmKTsKICAgIGlmICghKGRpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJvdGF0aW9uID0gdGhpcy5yb3RhdGlvbjsKICAgIH0KICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHZhbHVlID0gdGhpcy5kYXRhLmZpZWxkVmFsdWUgPT09IHRoaXMuZGF0YS5leHBvcnRWYWx1ZTsKICAgIH0KICAgIGNvbnN0IHhmYSA9IHsKICAgICAgcGF0aDogdGhpcy5kYXRhLmZpZWxkTmFtZSwKICAgICAgdmFsdWU6IHZhbHVlID8gdGhpcy5kYXRhLmV4cG9ydFZhbHVlIDogIiIKICAgIH07CiAgICBjb25zdCBuYW1lID0gX3ByaW1pdGl2ZXMuTmFtZS5nZXQodmFsdWUgPyB0aGlzLmRhdGEuZXhwb3J0VmFsdWUgOiAiT2ZmIik7CiAgICBkaWN0LnNldCgiViIsIG5hbWUpOwogICAgZGljdC5zZXQoIkFTIiwgbmFtZSk7CiAgICBkaWN0LnNldCgiTSIsIGBEOiR7KDAsIF91dGlsLmdldE1vZGlmaWNhdGlvbkRhdGUpKCl9YCk7CiAgICBjb25zdCBtYXliZU1LID0gdGhpcy5fZ2V0TUtEaWN0KHJvdGF0aW9uKTsKICAgIGlmIChtYXliZU1LKSB7CiAgICAgIGRpY3Quc2V0KCJNSyIsIG1heWJlTUspOwogICAgfQogICAgY29uc3QgZW5jcnlwdCA9IGV2YWx1YXRvci54cmVmLmVuY3J5cHQ7CiAgICBsZXQgb3JpZ2luYWxUcmFuc2Zvcm0gPSBudWxsOwogICAgaWYgKGVuY3J5cHQpIHsKICAgICAgb3JpZ2luYWxUcmFuc2Zvcm0gPSBlbmNyeXB0LmNyZWF0ZUNpcGhlclRyYW5zZm9ybSh0aGlzLnJlZi5udW0sIHRoaXMucmVmLmdlbik7CiAgICB9CiAgICBjb25zdCBidWZmZXIgPSBbYCR7dGhpcy5yZWYubnVtfSAke3RoaXMucmVmLmdlbn0gb2JqXG5gXTsKICAgICgwLCBfd3JpdGVyLndyaXRlRGljdCkoZGljdCwgYnVmZmVyLCBvcmlnaW5hbFRyYW5zZm9ybSk7CiAgICBidWZmZXIucHVzaCgiXG5lbmRvYmpcbiIpOwogICAgcmV0dXJuIFt7CiAgICAgIHJlZjogdGhpcy5yZWYsCiAgICAgIGRhdGE6IGJ1ZmZlci5qb2luKCIiKSwKICAgICAgeGZhCiAgICB9XTsKICB9CiAgYXN5bmMgX3NhdmVSYWRpb0J1dHRvbihldmFsdWF0b3IsIHRhc2ssIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBpZiAoIWFubm90YXRpb25TdG9yYWdlKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3Qgc3RvcmFnZUVudHJ5ID0gYW5ub3RhdGlvblN0b3JhZ2UuZ2V0KHRoaXMuZGF0YS5pZCk7CiAgICBsZXQgcm90YXRpb24gPSBzdG9yYWdlRW50cnkgJiYgc3RvcmFnZUVudHJ5LnJvdGF0aW9uOwogICAgbGV0IHZhbHVlID0gc3RvcmFnZUVudHJ5ICYmIHN0b3JhZ2VFbnRyeS52YWx1ZTsKICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgY29uc3QgZGVmYXVsdFZhbHVlID0gdGhpcy5kYXRhLmZpZWxkVmFsdWUgPT09IHRoaXMuZGF0YS5idXR0b25WYWx1ZTsKICAgICAgaWYgKGRlZmF1bHRWYWx1ZSA9PT0gdmFsdWUpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQogICAgY29uc3QgZGljdCA9IGV2YWx1YXRvci54cmVmLmZldGNoSWZSZWYodGhpcy5yZWYpOwogICAgaWYgKCEoZGljdCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgdmFsdWUgPSB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9PT0gdGhpcy5kYXRhLmJ1dHRvblZhbHVlOwogICAgfQogICAgaWYgKHJvdGF0aW9uID09PSB1bmRlZmluZWQpIHsKICAgICAgcm90YXRpb24gPSB0aGlzLnJvdGF0aW9uOwogICAgfQogICAgY29uc3QgeGZhID0gewogICAgICBwYXRoOiB0aGlzLmRhdGEuZmllbGROYW1lLAogICAgICB2YWx1ZTogdmFsdWUgPyB0aGlzLmRhdGEuYnV0dG9uVmFsdWUgOiAiIgogICAgfTsKICAgIGNvbnN0IG5hbWUgPSBfcHJpbWl0aXZlcy5OYW1lLmdldCh2YWx1ZSA/IHRoaXMuZGF0YS5idXR0b25WYWx1ZSA6ICJPZmYiKTsKICAgIGxldCBwYXJlbnRCdWZmZXIgPSBudWxsOwogICAgY29uc3QgZW5jcnlwdCA9IGV2YWx1YXRvci54cmVmLmVuY3J5cHQ7CiAgICBpZiAodmFsdWUpIHsKICAgICAgaWYgKHRoaXMucGFyZW50IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgICAgY29uc3QgcGFyZW50ID0gZXZhbHVhdG9yLnhyZWYuZmV0Y2godGhpcy5wYXJlbnQpOwogICAgICAgIGxldCBwYXJlbnRUcmFuc2Zvcm0gPSBudWxsOwogICAgICAgIGlmIChlbmNyeXB0KSB7CiAgICAgICAgICBwYXJlbnRUcmFuc2Zvcm0gPSBlbmNyeXB0LmNyZWF0ZUNpcGhlclRyYW5zZm9ybSh0aGlzLnBhcmVudC5udW0sIHRoaXMucGFyZW50Lmdlbik7CiAgICAgICAgfQogICAgICAgIHBhcmVudC5zZXQoIlYiLCBuYW1lKTsKICAgICAgICBwYXJlbnRCdWZmZXIgPSBbYCR7dGhpcy5wYXJlbnQubnVtfSAke3RoaXMucGFyZW50Lmdlbn0gb2JqXG5gXTsKICAgICAgICAoMCwgX3dyaXRlci53cml0ZURpY3QpKHBhcmVudCwgcGFyZW50QnVmZmVyLCBwYXJlbnRUcmFuc2Zvcm0pOwogICAgICAgIHBhcmVudEJ1ZmZlci5wdXNoKCJcbmVuZG9ialxuIik7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5wYXJlbnQgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgICAgdGhpcy5wYXJlbnQuc2V0KCJWIiwgbmFtZSk7CiAgICAgIH0KICAgIH0KICAgIGRpY3Quc2V0KCJBUyIsIG5hbWUpOwogICAgZGljdC5zZXQoIk0iLCBgRDokeygwLCBfdXRpbC5nZXRNb2RpZmljYXRpb25EYXRlKSgpfWApOwogICAgY29uc3QgbWF5YmVNSyA9IHRoaXMuX2dldE1LRGljdChyb3RhdGlvbik7CiAgICBpZiAobWF5YmVNSykgewogICAgICBkaWN0LnNldCgiTUsiLCBtYXliZU1LKTsKICAgIH0KICAgIGxldCBvcmlnaW5hbFRyYW5zZm9ybSA9IG51bGw7CiAgICBpZiAoZW5jcnlwdCkgewogICAgICBvcmlnaW5hbFRyYW5zZm9ybSA9IGVuY3J5cHQuY3JlYXRlQ2lwaGVyVHJhbnNmb3JtKHRoaXMucmVmLm51bSwgdGhpcy5yZWYuZ2VuKTsKICAgIH0KICAgIGNvbnN0IGJ1ZmZlciA9IFtgJHt0aGlzLnJlZi5udW19ICR7dGhpcy5yZWYuZ2VufSBvYmpcbmBdOwogICAgKDAsIF93cml0ZXIud3JpdGVEaWN0KShkaWN0LCBidWZmZXIsIG9yaWdpbmFsVHJhbnNmb3JtKTsKICAgIGJ1ZmZlci5wdXNoKCJcbmVuZG9ialxuIik7CiAgICBjb25zdCBuZXdSZWZzID0gW3sKICAgICAgcmVmOiB0aGlzLnJlZiwKICAgICAgZGF0YTogYnVmZmVyLmpvaW4oIiIpLAogICAgICB4ZmEKICAgIH1dOwogICAgaWYgKHBhcmVudEJ1ZmZlciAhPT0gbnVsbCkgewogICAgICBuZXdSZWZzLnB1c2goewogICAgICAgIHJlZjogdGhpcy5wYXJlbnQsCiAgICAgICAgZGF0YTogcGFyZW50QnVmZmVyLmpvaW4oIiIpLAogICAgICAgIHhmYTogbnVsbAogICAgICB9KTsKICAgIH0KICAgIHJldHVybiBuZXdSZWZzOwogIH0KICBfZ2V0RGVmYXVsdENoZWNrZWRBcHBlYXJhbmNlKHBhcmFtcywgdHlwZSkgewogICAgY29uc3Qgd2lkdGggPSB0aGlzLmRhdGEucmVjdFsyXSAtIHRoaXMuZGF0YS5yZWN0WzBdOwogICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5kYXRhLnJlY3RbM10gLSB0aGlzLmRhdGEucmVjdFsxXTsKICAgIGNvbnN0IGJib3ggPSBbMCwgMCwgd2lkdGgsIGhlaWdodF07CiAgICBjb25zdCBGT05UX1JBVElPID0gMC44OwogICAgY29uc3QgZm9udFNpemUgPSBNYXRoLm1pbih3aWR0aCwgaGVpZ2h0KSAqIEZPTlRfUkFUSU87CiAgICBsZXQgbWV0cmljcywgY2hhcjsKICAgIGlmICh0eXBlID09PSAiY2hlY2siKSB7CiAgICAgIG1ldHJpY3MgPSB7CiAgICAgICAgd2lkdGg6IDAuNzU1ICogZm9udFNpemUsCiAgICAgICAgaGVpZ2h0OiAwLjcwNSAqIGZvbnRTaXplCiAgICAgIH07CiAgICAgIGNoYXIgPSAiXHgzMyI7CiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICJkaXNjIikgewogICAgICBtZXRyaWNzID0gewogICAgICAgIHdpZHRoOiAwLjc5MSAqIGZvbnRTaXplLAogICAgICAgIGhlaWdodDogMC43MDUgKiBmb250U2l6ZQogICAgICB9OwogICAgICBjaGFyID0gIlx4NkMiOwogICAgfSBlbHNlIHsKICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKShgX2dldERlZmF1bHRDaGVja2VkQXBwZWFyYW5jZSAtIHVuc3VwcG9ydGVkIHR5cGU6ICR7dHlwZX1gKTsKICAgIH0KICAgIGNvbnN0IHhTaGlmdCA9ICgwLCBfY29yZV91dGlscy5udW1iZXJUb1N0cmluZykoKHdpZHRoIC0gbWV0cmljcy53aWR0aCkgLyAyKTsKICAgIGNvbnN0IHlTaGlmdCA9ICgwLCBfY29yZV91dGlscy5udW1iZXJUb1N0cmluZykoKGhlaWdodCAtIG1ldHJpY3MuaGVpZ2h0KSAvIDIpOwogICAgY29uc3QgYXBwZWFyYW5jZSA9IGBxIEJUIC9QZGZKc1phRGIgJHtmb250U2l6ZX0gVGYgMCBnICR7eFNoaWZ0fSAke3lTaGlmdH0gVGQgKCR7Y2hhcn0pIFRqIEVUIFFgOwogICAgY29uc3QgYXBwZWFyYW5jZVN0cmVhbURpY3QgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdChwYXJhbXMueHJlZik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkZvcm1UeXBlIiwgMSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlN1YnR5cGUiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiRm9ybSIpKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiVHlwZSIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJYT2JqZWN0IikpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJCQm94IiwgYmJveCk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIk1hdHJpeCIsIFsxLCAwLCAwLCAxLCAwLCAwXSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkxlbmd0aCIsIGFwcGVhcmFuY2UubGVuZ3RoKTsKICAgIGNvbnN0IHJlc291cmNlcyA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHBhcmFtcy54cmVmKTsKICAgIGNvbnN0IGZvbnQgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdChwYXJhbXMueHJlZik7CiAgICBmb250LnNldCgiUGRmSnNaYURiIiwgdGhpcy5mYWxsYmFja0ZvbnREaWN0KTsKICAgIHJlc291cmNlcy5zZXQoIkZvbnQiLCBmb250KTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiUmVzb3VyY2VzIiwgcmVzb3VyY2VzKTsKICAgIHRoaXMuY2hlY2tlZEFwcGVhcmFuY2UgPSBuZXcgX3N0cmVhbS5TdHJpbmdTdHJlYW0oYXBwZWFyYW5jZSk7CiAgICB0aGlzLmNoZWNrZWRBcHBlYXJhbmNlLmRpY3QgPSBhcHBlYXJhbmNlU3RyZWFtRGljdDsKICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmNoZWNrZWRBcHBlYXJhbmNlKTsKICB9CiAgX3Byb2Nlc3NDaGVja0JveChwYXJhbXMpIHsKICAgIGNvbnN0IGN1c3RvbUFwcGVhcmFuY2UgPSBwYXJhbXMuZGljdC5nZXQoIkFQIik7CiAgICBpZiAoIShjdXN0b21BcHBlYXJhbmNlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgbm9ybWFsQXBwZWFyYW5jZSA9IGN1c3RvbUFwcGVhcmFuY2UuZ2V0KCJOIik7CiAgICBpZiAoIShub3JtYWxBcHBlYXJhbmNlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgYXNWYWx1ZSA9IHRoaXMuX2RlY29kZUZvcm1WYWx1ZShwYXJhbXMuZGljdC5nZXQoIkFTIikpOwogICAgaWYgKHR5cGVvZiBhc1ZhbHVlID09PSAic3RyaW5nIikgewogICAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9IGFzVmFsdWU7CiAgICB9CiAgICBjb25zdCB5ZXMgPSB0aGlzLmRhdGEuZmllbGRWYWx1ZSAhPT0gbnVsbCAmJiB0aGlzLmRhdGEuZmllbGRWYWx1ZSAhPT0gIk9mZiIgPyB0aGlzLmRhdGEuZmllbGRWYWx1ZSA6ICJZZXMiOwogICAgY29uc3QgZXhwb3J0VmFsdWVzID0gbm9ybWFsQXBwZWFyYW5jZS5nZXRLZXlzKCk7CiAgICBpZiAoZXhwb3J0VmFsdWVzLmxlbmd0aCA9PT0gMCkgewogICAgICBleHBvcnRWYWx1ZXMucHVzaCgiT2ZmIiwgeWVzKTsKICAgIH0gZWxzZSBpZiAoZXhwb3J0VmFsdWVzLmxlbmd0aCA9PT0gMSkgewogICAgICBpZiAoZXhwb3J0VmFsdWVzWzBdID09PSAiT2ZmIikgewogICAgICAgIGV4cG9ydFZhbHVlcy5wdXNoKHllcyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZXhwb3J0VmFsdWVzLnVuc2hpZnQoIk9mZiIpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKGV4cG9ydFZhbHVlcy5pbmNsdWRlcyh5ZXMpKSB7CiAgICAgIGV4cG9ydFZhbHVlcy5sZW5ndGggPSAwOwogICAgICBleHBvcnRWYWx1ZXMucHVzaCgiT2ZmIiwgeWVzKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IG90aGVyWWVzID0gZXhwb3J0VmFsdWVzLmZpbmQodiA9PiB2ICE9PSAiT2ZmIik7CiAgICAgIGV4cG9ydFZhbHVlcy5sZW5ndGggPSAwOwogICAgICBleHBvcnRWYWx1ZXMucHVzaCgiT2ZmIiwgb3RoZXJZZXMpOwogICAgfQogICAgaWYgKCFleHBvcnRWYWx1ZXMuaW5jbHVkZXModGhpcy5kYXRhLmZpZWxkVmFsdWUpKSB7CiAgICAgIHRoaXMuZGF0YS5maWVsZFZhbHVlID0gIk9mZiI7CiAgICB9CiAgICB0aGlzLmRhdGEuZXhwb3J0VmFsdWUgPSBleHBvcnRWYWx1ZXNbMV07CiAgICBjb25zdCBjaGVja2VkQXBwZWFyYW5jZSA9IG5vcm1hbEFwcGVhcmFuY2UuZ2V0KHRoaXMuZGF0YS5leHBvcnRWYWx1ZSk7CiAgICB0aGlzLmNoZWNrZWRBcHBlYXJhbmNlID0gY2hlY2tlZEFwcGVhcmFuY2UgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSA/IGNoZWNrZWRBcHBlYXJhbmNlIDogbnVsbDsKICAgIGNvbnN0IHVuY2hlY2tlZEFwcGVhcmFuY2UgPSBub3JtYWxBcHBlYXJhbmNlLmdldCgiT2ZmIik7CiAgICB0aGlzLnVuY2hlY2tlZEFwcGVhcmFuY2UgPSB1bmNoZWNrZWRBcHBlYXJhbmNlIGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0gPyB1bmNoZWNrZWRBcHBlYXJhbmNlIDogbnVsbDsKICAgIGlmICh0aGlzLmNoZWNrZWRBcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmNoZWNrZWRBcHBlYXJhbmNlKTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuX2dldERlZmF1bHRDaGVja2VkQXBwZWFyYW5jZShwYXJhbXMsICJjaGVjayIpOwogICAgfQogICAgaWYgKHRoaXMudW5jaGVja2VkQXBwZWFyYW5jZSkgewogICAgICB0aGlzLl9zdHJlYW1zLnB1c2godGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlKTsKICAgIH0KICAgIHRoaXMuX2ZhbGxiYWNrRm9udERpY3QgPSB0aGlzLmZhbGxiYWNrRm9udERpY3Q7CiAgfQogIF9wcm9jZXNzUmFkaW9CdXR0b24ocGFyYW1zKSB7CiAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9IHRoaXMuZGF0YS5idXR0b25WYWx1ZSA9IG51bGw7CiAgICBjb25zdCBmaWVsZFBhcmVudCA9IHBhcmFtcy5kaWN0LmdldCgiUGFyZW50Iik7CiAgICBpZiAoZmllbGRQYXJlbnQgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgIHRoaXMucGFyZW50ID0gcGFyYW1zLmRpY3QuZ2V0UmF3KCJQYXJlbnQiKTsKICAgICAgY29uc3QgZmllbGRQYXJlbnRWYWx1ZSA9IGZpZWxkUGFyZW50LmdldCgiViIpOwogICAgICBpZiAoZmllbGRQYXJlbnRWYWx1ZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9IHRoaXMuX2RlY29kZUZvcm1WYWx1ZShmaWVsZFBhcmVudFZhbHVlKTsKICAgICAgfQogICAgfQogICAgY29uc3QgYXBwZWFyYW5jZVN0YXRlcyA9IHBhcmFtcy5kaWN0LmdldCgiQVAiKTsKICAgIGlmICghKGFwcGVhcmFuY2VTdGF0ZXMgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBub3JtYWxBcHBlYXJhbmNlID0gYXBwZWFyYW5jZVN0YXRlcy5nZXQoIk4iKTsKICAgIGlmICghKG5vcm1hbEFwcGVhcmFuY2UgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGNvbnN0IGtleSBvZiBub3JtYWxBcHBlYXJhbmNlLmdldEtleXMoKSkgewogICAgICBpZiAoa2V5ICE9PSAiT2ZmIikgewogICAgICAgIHRoaXMuZGF0YS5idXR0b25WYWx1ZSA9IHRoaXMuX2RlY29kZUZvcm1WYWx1ZShrZXkpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBjb25zdCBjaGVja2VkQXBwZWFyYW5jZSA9IG5vcm1hbEFwcGVhcmFuY2UuZ2V0KHRoaXMuZGF0YS5idXR0b25WYWx1ZSk7CiAgICB0aGlzLmNoZWNrZWRBcHBlYXJhbmNlID0gY2hlY2tlZEFwcGVhcmFuY2UgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSA/IGNoZWNrZWRBcHBlYXJhbmNlIDogbnVsbDsKICAgIGNvbnN0IHVuY2hlY2tlZEFwcGVhcmFuY2UgPSBub3JtYWxBcHBlYXJhbmNlLmdldCgiT2ZmIik7CiAgICB0aGlzLnVuY2hlY2tlZEFwcGVhcmFuY2UgPSB1bmNoZWNrZWRBcHBlYXJhbmNlIGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0gPyB1bmNoZWNrZWRBcHBlYXJhbmNlIDogbnVsbDsKICAgIGlmICh0aGlzLmNoZWNrZWRBcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmNoZWNrZWRBcHBlYXJhbmNlKTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuX2dldERlZmF1bHRDaGVja2VkQXBwZWFyYW5jZShwYXJhbXMsICJkaXNjIik7CiAgICB9CiAgICBpZiAodGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLnVuY2hlY2tlZEFwcGVhcmFuY2UpOwogICAgfQogICAgdGhpcy5fZmFsbGJhY2tGb250RGljdCA9IHRoaXMuZmFsbGJhY2tGb250RGljdDsKICB9CiAgX3Byb2Nlc3NQdXNoQnV0dG9uKHBhcmFtcykgewogICAgaWYgKCFwYXJhbXMuZGljdC5oYXMoIkEiKSAmJiAhcGFyYW1zLmRpY3QuaGFzKCJBQSIpICYmICF0aGlzLmRhdGEuYWx0ZXJuYXRpdmVUZXh0KSB7CiAgICAgICgwLCBfdXRpbC53YXJuKSgiUHVzaCBidXR0b25zIHdpdGhvdXQgYWN0aW9uIGRpY3Rpb25hcmllcyBhcmUgbm90IHN1cHBvcnRlZCIpOwogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLmRhdGEuaXNUb29sdGlwT25seSA9ICFwYXJhbXMuZGljdC5oYXMoIkEiKSAmJiAhcGFyYW1zLmRpY3QuaGFzKCJBQSIpOwogICAgX2NhdGFsb2cuQ2F0YWxvZy5wYXJzZURlc3REaWN0aW9uYXJ5KHsKICAgICAgZGVzdERpY3Q6IHBhcmFtcy5kaWN0LAogICAgICByZXN1bHRPYmo6IHRoaXMuZGF0YSwKICAgICAgZG9jQmFzZVVybDogcGFyYW1zLnBkZk1hbmFnZXIuZG9jQmFzZVVybCwKICAgICAgZG9jQXR0YWNobWVudHM6IHBhcmFtcy5hdHRhY2htZW50cwogICAgfSk7CiAgfQogIGdldEZpZWxkT2JqZWN0KCkgewogICAgbGV0IHR5cGUgPSAiYnV0dG9uIjsKICAgIGxldCBleHBvcnRWYWx1ZXM7CiAgICBpZiAodGhpcy5kYXRhLmNoZWNrQm94KSB7CiAgICAgIHR5cGUgPSAiY2hlY2tib3giOwogICAgICBleHBvcnRWYWx1ZXMgPSB0aGlzLmRhdGEuZXhwb3J0VmFsdWU7CiAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YS5yYWRpb0J1dHRvbikgewogICAgICB0eXBlID0gInJhZGlvYnV0dG9uIjsKICAgICAgZXhwb3J0VmFsdWVzID0gdGhpcy5kYXRhLmJ1dHRvblZhbHVlOwogICAgfQogICAgcmV0dXJuIHsKICAgICAgaWQ6IHRoaXMuZGF0YS5pZCwKICAgICAgdmFsdWU6IHRoaXMuZGF0YS5maWVsZFZhbHVlIHx8ICJPZmYiLAogICAgICBkZWZhdWx0VmFsdWU6IHRoaXMuZGF0YS5kZWZhdWx0RmllbGRWYWx1ZSwKICAgICAgZXhwb3J0VmFsdWVzLAogICAgICBlZGl0YWJsZTogIXRoaXMuZGF0YS5yZWFkT25seSwKICAgICAgbmFtZTogdGhpcy5kYXRhLmZpZWxkTmFtZSwKICAgICAgcmVjdDogdGhpcy5kYXRhLnJlY3QsCiAgICAgIGhpZGRlbjogdGhpcy5kYXRhLmhpZGRlbiwKICAgICAgYWN0aW9uczogdGhpcy5kYXRhLmFjdGlvbnMsCiAgICAgIHBhZ2U6IHRoaXMuZGF0YS5wYWdlSW5kZXgsCiAgICAgIHN0cm9rZUNvbG9yOiB0aGlzLmRhdGEuYm9yZGVyQ29sb3IsCiAgICAgIGZpbGxDb2xvcjogdGhpcy5kYXRhLmJhY2tncm91bmRDb2xvciwKICAgICAgcm90YXRpb246IHRoaXMucm90YXRpb24sCiAgICAgIHR5cGUKICAgIH07CiAgfQogIGdldCBmYWxsYmFja0ZvbnREaWN0KCkgewogICAgY29uc3QgZGljdCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KCk7CiAgICBkaWN0LnNldCgiQmFzZUZvbnQiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiWmFwZkRpbmdiYXRzIikpOwogICAgZGljdC5zZXQoIlR5cGUiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiRmFsbGJhY2tUeXBlIikpOwogICAgZGljdC5zZXQoIlN1YnR5cGUiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiRmFsbGJhY2tUeXBlIikpOwogICAgZGljdC5zZXQoIkVuY29kaW5nIiwgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIlphcGZEaW5nYmF0c0VuY29kaW5nIikpOwogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJmYWxsYmFja0ZvbnREaWN0IiwgZGljdCk7CiAgfQp9CmNsYXNzIENob2ljZVdpZGdldEFubm90YXRpb24gZXh0ZW5kcyBXaWRnZXRBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICBjb25zdCB7CiAgICAgIGRpY3QsCiAgICAgIHhyZWYKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLmluZGljZXMgPSBkaWN0LmdldEFycmF5KCJJIik7CiAgICB0aGlzLmhhc0luZGljZXMgPSBBcnJheS5pc0FycmF5KHRoaXMuaW5kaWNlcykgJiYgdGhpcy5pbmRpY2VzLmxlbmd0aCA+IDA7CiAgICB0aGlzLmRhdGEub3B0aW9ucyA9IFtdOwogICAgY29uc3Qgb3B0aW9ucyA9ICgwLCBfY29yZV91dGlscy5nZXRJbmhlcml0YWJsZVByb3BlcnR5KSh7CiAgICAgIGRpY3QsCiAgICAgIGtleTogIk9wdCIKICAgIH0pOwogICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucykpIHsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gb3B0aW9ucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3Qgb3B0aW9uID0geHJlZi5mZXRjaElmUmVmKG9wdGlvbnNbaV0pOwogICAgICAgIGNvbnN0IGlzT3B0aW9uQXJyYXkgPSBBcnJheS5pc0FycmF5KG9wdGlvbik7CiAgICAgICAgdGhpcy5kYXRhLm9wdGlvbnNbaV0gPSB7CiAgICAgICAgICBleHBvcnRWYWx1ZTogdGhpcy5fZGVjb2RlRm9ybVZhbHVlKGlzT3B0aW9uQXJyYXkgPyB4cmVmLmZldGNoSWZSZWYob3B0aW9uWzBdKSA6IG9wdGlvbiksCiAgICAgICAgICBkaXNwbGF5VmFsdWU6IHRoaXMuX2RlY29kZUZvcm1WYWx1ZShpc09wdGlvbkFycmF5ID8geHJlZi5mZXRjaElmUmVmKG9wdGlvblsxXSkgOiBvcHRpb24pCiAgICAgICAgfTsKICAgICAgfQogICAgfQogICAgaWYgKCF0aGlzLmhhc0luZGljZXMpIHsKICAgICAgaWYgKHR5cGVvZiB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9PT0gInN0cmluZyIpIHsKICAgICAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9IFt0aGlzLmRhdGEuZmllbGRWYWx1ZV07CiAgICAgIH0gZWxzZSBpZiAoIXRoaXMuZGF0YS5maWVsZFZhbHVlKSB7CiAgICAgICAgdGhpcy5kYXRhLmZpZWxkVmFsdWUgPSBbXTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdGhpcy5kYXRhLmZpZWxkVmFsdWUgPSBbXTsKICAgICAgY29uc3QgaWkgPSB0aGlzLmRhdGEub3B0aW9ucy5sZW5ndGg7CiAgICAgIGZvciAoY29uc3QgaSBvZiB0aGlzLmluZGljZXMpIHsKICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihpKSAmJiBpID49IDAgJiYgaSA8IGlpKSB7CiAgICAgICAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZS5wdXNoKHRoaXMuZGF0YS5vcHRpb25zW2ldLmV4cG9ydFZhbHVlKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHRoaXMuZGF0YS5jb21ibyA9IHRoaXMuaGFzRmllbGRGbGFnKF91dGlsLkFubm90YXRpb25GaWVsZEZsYWcuQ09NQk8pOwogICAgdGhpcy5kYXRhLm11bHRpU2VsZWN0ID0gdGhpcy5oYXNGaWVsZEZsYWcoX3V0aWwuQW5ub3RhdGlvbkZpZWxkRmxhZy5NVUxUSVNFTEVDVCk7CiAgICB0aGlzLl9oYXNUZXh0ID0gdHJ1ZTsKICB9CiAgZ2V0RmllbGRPYmplY3QoKSB7CiAgICBjb25zdCB0eXBlID0gdGhpcy5kYXRhLmNvbWJvID8gImNvbWJvYm94IiA6ICJsaXN0Ym94IjsKICAgIGNvbnN0IHZhbHVlID0gdGhpcy5kYXRhLmZpZWxkVmFsdWUubGVuZ3RoID4gMCA/IHRoaXMuZGF0YS5maWVsZFZhbHVlWzBdIDogbnVsbDsKICAgIHJldHVybiB7CiAgICAgIGlkOiB0aGlzLmRhdGEuaWQsCiAgICAgIHZhbHVlLAogICAgICBkZWZhdWx0VmFsdWU6IHRoaXMuZGF0YS5kZWZhdWx0RmllbGRWYWx1ZSwKICAgICAgZWRpdGFibGU6ICF0aGlzLmRhdGEucmVhZE9ubHksCiAgICAgIG5hbWU6IHRoaXMuZGF0YS5maWVsZE5hbWUsCiAgICAgIHJlY3Q6IHRoaXMuZGF0YS5yZWN0LAogICAgICBudW1JdGVtczogdGhpcy5kYXRhLmZpZWxkVmFsdWUubGVuZ3RoLAogICAgICBtdWx0aXBsZVNlbGVjdGlvbjogdGhpcy5kYXRhLm11bHRpU2VsZWN0LAogICAgICBoaWRkZW46IHRoaXMuZGF0YS5oaWRkZW4sCiAgICAgIGFjdGlvbnM6IHRoaXMuZGF0YS5hY3Rpb25zLAogICAgICBpdGVtczogdGhpcy5kYXRhLm9wdGlvbnMsCiAgICAgIHBhZ2U6IHRoaXMuZGF0YS5wYWdlSW5kZXgsCiAgICAgIHN0cm9rZUNvbG9yOiB0aGlzLmRhdGEuYm9yZGVyQ29sb3IsCiAgICAgIGZpbGxDb2xvcjogdGhpcy5kYXRhLmJhY2tncm91bmRDb2xvciwKICAgICAgcm90YXRpb246IHRoaXMucm90YXRpb24sCiAgICAgIHR5cGUKICAgIH07CiAgfQogIGFtZW5kU2F2ZWREaWN0KGFubm90YXRpb25TdG9yYWdlLCBkaWN0KSB7CiAgICBpZiAoIXRoaXMuaGFzSW5kaWNlcykgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBzdG9yYWdlRW50cnkgPSBhbm5vdGF0aW9uU3RvcmFnZSA/IGFubm90YXRpb25TdG9yYWdlLmdldCh0aGlzLmRhdGEuaWQpIDogdW5kZWZpbmVkOwogICAgbGV0IHZhbHVlcyA9IHN0b3JhZ2VFbnRyeSAmJiBzdG9yYWdlRW50cnkudmFsdWU7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkodmFsdWVzKSkgewogICAgICB2YWx1ZXMgPSBbdmFsdWVzXTsKICAgIH0KICAgIGNvbnN0IGluZGljZXMgPSBbXTsKICAgIGNvbnN0IHsKICAgICAgb3B0aW9ucwogICAgfSA9IHRoaXMuZGF0YTsKICAgIGZvciAobGV0IGkgPSAwLCBqID0gMCwgaWkgPSBvcHRpb25zLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgaWYgKG9wdGlvbnNbaV0uZXhwb3J0VmFsdWUgPT09IHZhbHVlc1tqXSkgewogICAgICAgIGluZGljZXMucHVzaChpKTsKICAgICAgICBqICs9IDE7CiAgICAgIH0KICAgIH0KICAgIGRpY3Quc2V0KCJJIiwgaW5kaWNlcyk7CiAgfQogIGFzeW5jIF9nZXRBcHBlYXJhbmNlKGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgaWYgKHRoaXMuZGF0YS5jb21ibykgewogICAgICByZXR1cm4gc3VwZXIuX2dldEFwcGVhcmFuY2UoZXZhbHVhdG9yLCB0YXNrLCBpbnRlbnQsIGFubm90YXRpb25TdG9yYWdlKTsKICAgIH0KICAgIGxldCBleHBvcnRlZFZhbHVlLCByb3RhdGlvbjsKICAgIGNvbnN0IHN0b3JhZ2VFbnRyeSA9IGFubm90YXRpb25TdG9yYWdlID8gYW5ub3RhdGlvblN0b3JhZ2UuZ2V0KHRoaXMuZGF0YS5pZCkgOiB1bmRlZmluZWQ7CiAgICBpZiAoc3RvcmFnZUVudHJ5KSB7CiAgICAgIHJvdGF0aW9uID0gc3RvcmFnZUVudHJ5LnJvdGF0aW9uOwogICAgICBleHBvcnRlZFZhbHVlID0gc3RvcmFnZUVudHJ5LnZhbHVlOwogICAgfQogICAgaWYgKHJvdGF0aW9uID09PSB1bmRlZmluZWQgJiYgZXhwb3J0ZWRWYWx1ZSA9PT0gdW5kZWZpbmVkICYmICF0aGlzLl9uZWVkQXBwZWFyYW5jZXMpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBpZiAoZXhwb3J0ZWRWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGV4cG9ydGVkVmFsdWUgPSB0aGlzLmRhdGEuZmllbGRWYWx1ZTsKICAgIH0gZWxzZSBpZiAoIUFycmF5LmlzQXJyYXkoZXhwb3J0ZWRWYWx1ZSkpIHsKICAgICAgZXhwb3J0ZWRWYWx1ZSA9IFtleHBvcnRlZFZhbHVlXTsKICAgIH0KICAgIGNvbnN0IGRlZmF1bHRQYWRkaW5nID0gMTsKICAgIGNvbnN0IGRlZmF1bHRIUGFkZGluZyA9IDI7CiAgICBsZXQgdG90YWxIZWlnaHQgPSB0aGlzLmRhdGEucmVjdFszXSAtIHRoaXMuZGF0YS5yZWN0WzFdOwogICAgbGV0IHRvdGFsV2lkdGggPSB0aGlzLmRhdGEucmVjdFsyXSAtIHRoaXMuZGF0YS5yZWN0WzBdOwogICAgaWYgKHJvdGF0aW9uID09PSA5MCB8fCByb3RhdGlvbiA9PT0gMjcwKSB7CiAgICAgIFt0b3RhbFdpZHRoLCB0b3RhbEhlaWdodF0gPSBbdG90YWxIZWlnaHQsIHRvdGFsV2lkdGhdOwogICAgfQogICAgY29uc3QgbGluZUNvdW50ID0gdGhpcy5kYXRhLm9wdGlvbnMubGVuZ3RoOwogICAgY29uc3QgdmFsdWVJbmRpY2VzID0gW107CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVDb3VudDsgaSsrKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBleHBvcnRWYWx1ZQogICAgICB9ID0gdGhpcy5kYXRhLm9wdGlvbnNbaV07CiAgICAgIGlmIChleHBvcnRlZFZhbHVlLmluY2x1ZGVzKGV4cG9ydFZhbHVlKSkgewogICAgICAgIHZhbHVlSW5kaWNlcy5wdXNoKGkpOwogICAgICB9CiAgICB9CiAgICBpZiAoIXRoaXMuX2RlZmF1bHRBcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEgPSAoMCwgX2RlZmF1bHRfYXBwZWFyYW5jZS5wYXJzZURlZmF1bHRBcHBlYXJhbmNlKSh0aGlzLl9kZWZhdWx0QXBwZWFyYW5jZSA9ICIvSGVsdmV0aWNhIDAgVGYgMCBnIik7CiAgICB9CiAgICBjb25zdCBmb250ID0gYXdhaXQgV2lkZ2V0QW5ub3RhdGlvbi5fZ2V0Rm9udERhdGEoZXZhbHVhdG9yLCB0YXNrLCB0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhLCB0aGlzLl9maWVsZFJlc291cmNlcy5tZXJnZWRSZXNvdXJjZXMpOwogICAgbGV0IGRlZmF1bHRBcHBlYXJhbmNlOwogICAgbGV0IHsKICAgICAgZm9udFNpemUKICAgIH0gPSB0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhOwogICAgaWYgKCFmb250U2l6ZSkgewogICAgICBjb25zdCBsaW5lSGVpZ2h0ID0gKHRvdGFsSGVpZ2h0IC0gZGVmYXVsdFBhZGRpbmcpIC8gbGluZUNvdW50OwogICAgICBsZXQgbGluZVdpZHRoID0gLTE7CiAgICAgIGxldCB2YWx1ZTsKICAgICAgZm9yIChjb25zdCB7CiAgICAgICAgZGlzcGxheVZhbHVlCiAgICAgIH0gb2YgdGhpcy5kYXRhLm9wdGlvbnMpIHsKICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMuX2dldFRleHRXaWR0aChkaXNwbGF5VmFsdWUsIGZvbnQpOwogICAgICAgIGlmICh3aWR0aCA+IGxpbmVXaWR0aCkgewogICAgICAgICAgbGluZVdpZHRoID0gd2lkdGg7CiAgICAgICAgICB2YWx1ZSA9IGRpc3BsYXlWYWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgW2RlZmF1bHRBcHBlYXJhbmNlLCBmb250U2l6ZV0gPSB0aGlzLl9jb21wdXRlRm9udFNpemUobGluZUhlaWdodCwgdG90YWxXaWR0aCAtIDIgKiBkZWZhdWx0SFBhZGRpbmcsIHZhbHVlLCBmb250LCAtMSk7CiAgICB9IGVsc2UgewogICAgICBkZWZhdWx0QXBwZWFyYW5jZSA9IHRoaXMuX2RlZmF1bHRBcHBlYXJhbmNlOwogICAgfQogICAgY29uc3QgbGluZUhlaWdodCA9IGZvbnRTaXplICogX3V0aWwuTElORV9GQUNUT1I7CiAgICBjb25zdCB2UGFkZGluZyA9IChsaW5lSGVpZ2h0IC0gZm9udFNpemUpIC8gMjsKICAgIGNvbnN0IG51bWJlck9mVmlzaWJsZUxpbmVzID0gTWF0aC5mbG9vcih0b3RhbEhlaWdodCAvIGxpbmVIZWlnaHQpOwogICAgbGV0IGZpcnN0SW5kZXg7CiAgICBpZiAodmFsdWVJbmRpY2VzLmxlbmd0aCA9PT0gMSkgewogICAgICBjb25zdCB2YWx1ZVBvc2l0aW9uID0gdmFsdWVJbmRpY2VzWzBdOwogICAgICBjb25zdCBpbmRleEluUGFnZSA9IHZhbHVlUG9zaXRpb24gJSBudW1iZXJPZlZpc2libGVMaW5lczsKICAgICAgZmlyc3RJbmRleCA9IHZhbHVlUG9zaXRpb24gLSBpbmRleEluUGFnZTsKICAgIH0gZWxzZSB7CiAgICAgIGZpcnN0SW5kZXggPSB2YWx1ZUluZGljZXMubGVuZ3RoID8gdmFsdWVJbmRpY2VzWzBdIDogMDsKICAgIH0KICAgIGNvbnN0IGVuZCA9IE1hdGgubWluKGZpcnN0SW5kZXggKyBudW1iZXJPZlZpc2libGVMaW5lcyArIDEsIGxpbmVDb3VudCk7CiAgICBjb25zdCBidWYgPSBbIi9UeCBCTUMgcSIsIGAxIDEgJHt0b3RhbFdpZHRofSAke3RvdGFsSGVpZ2h0fSByZSBXIG5gXTsKICAgIGlmICh2YWx1ZUluZGljZXMubGVuZ3RoKSB7CiAgICAgIGJ1Zi5wdXNoKCIwLjYwMDAwNiAwLjc1Njg2NiAwLjg1NDkwNCByZyIpOwogICAgICBmb3IgKGNvbnN0IGluZGV4IG9mIHZhbHVlSW5kaWNlcykgewogICAgICAgIGlmIChmaXJzdEluZGV4IDw9IGluZGV4ICYmIGluZGV4IDwgZW5kKSB7CiAgICAgICAgICBidWYucHVzaChgMSAke3RvdGFsSGVpZ2h0IC0gKGluZGV4IC0gZmlyc3RJbmRleCArIDEpICogbGluZUhlaWdodH0gJHt0b3RhbFdpZHRofSAke2xpbmVIZWlnaHR9IHJlIGZgKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGJ1Zi5wdXNoKCJCVCIsIGRlZmF1bHRBcHBlYXJhbmNlLCBgMSAwIDAgMSAwICR7dG90YWxIZWlnaHR9IFRtYCk7CiAgICBjb25zdCBwcmV2SW5mbyA9IHsKICAgICAgc2hpZnQ6IDAKICAgIH07CiAgICBmb3IgKGxldCBpID0gZmlyc3RJbmRleDsgaSA8IGVuZDsgaSsrKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBkaXNwbGF5VmFsdWUKICAgICAgfSA9IHRoaXMuZGF0YS5vcHRpb25zW2ldOwogICAgICBjb25zdCB2cGFkZGluZyA9IGkgPT09IGZpcnN0SW5kZXggPyB2UGFkZGluZyA6IDA7CiAgICAgIGJ1Zi5wdXNoKHRoaXMuX3JlbmRlclRleHQoZGlzcGxheVZhbHVlLCBmb250LCBmb250U2l6ZSwgdG90YWxXaWR0aCwgMCwgcHJldkluZm8sIGRlZmF1bHRIUGFkZGluZywgLWxpbmVIZWlnaHQgKyB2cGFkZGluZykpOwogICAgfQogICAgYnVmLnB1c2goIkVUIFEgRU1DIik7CiAgICByZXR1cm4gYnVmLmpvaW4oIlxuIik7CiAgfQp9CmNsYXNzIFNpZ25hdHVyZVdpZGdldEFubm90YXRpb24gZXh0ZW5kcyBXaWRnZXRBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9IG51bGw7CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLm5vUm90YXRlOwogIH0KICBnZXRGaWVsZE9iamVjdCgpIHsKICAgIHJldHVybiB7CiAgICAgIGlkOiB0aGlzLmRhdGEuaWQsCiAgICAgIHZhbHVlOiBudWxsLAogICAgICBwYWdlOiB0aGlzLmRhdGEucGFnZUluZGV4LAogICAgICB0eXBlOiAic2lnbmF0dXJlIgogICAgfTsKICB9Cn0KY2xhc3MgVGV4dEFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIGNvbnN0IERFRkFVTFRfSUNPTl9TSVpFID0gMjI7CiAgICBzdXBlcihwYXJhbXMpOwogICAgdGhpcy5kYXRhLm5vUm90YXRlID0gdHJ1ZTsKICAgIHRoaXMuZGF0YS5oYXNPd25DYW52YXMgPSB0aGlzLmRhdGEubm9Sb3RhdGU7CiAgICBjb25zdCB7CiAgICAgIGRpY3QKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGUgPSBfdXRpbC5Bbm5vdGF0aW9uVHlwZS5URVhUOwogICAgaWYgKHRoaXMuZGF0YS5oYXNBcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuZGF0YS5uYW1lID0gIk5vSWNvbiI7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEucmVjdFsxXSA9IHRoaXMuZGF0YS5yZWN0WzNdIC0gREVGQVVMVF9JQ09OX1NJWkU7CiAgICAgIHRoaXMuZGF0YS5yZWN0WzJdID0gdGhpcy5kYXRhLnJlY3RbMF0gKyBERUZBVUxUX0lDT05fU0laRTsKICAgICAgdGhpcy5kYXRhLm5hbWUgPSBkaWN0LmhhcygiTmFtZSIpID8gZGljdC5nZXQoIk5hbWUiKS5uYW1lIDogIk5vdGUiOwogICAgfQogICAgaWYgKGRpY3QuaGFzKCJTdGF0ZSIpKSB7CiAgICAgIHRoaXMuZGF0YS5zdGF0ZSA9IGRpY3QuZ2V0KCJTdGF0ZSIpIHx8IG51bGw7CiAgICAgIHRoaXMuZGF0YS5zdGF0ZU1vZGVsID0gZGljdC5nZXQoIlN0YXRlTW9kZWwiKSB8fCBudWxsOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5kYXRhLnN0YXRlID0gbnVsbDsKICAgICAgdGhpcy5kYXRhLnN0YXRlTW9kZWwgPSBudWxsOwogICAgfQogIH0KfQpjbGFzcyBMaW5rQW5ub3RhdGlvbiBleHRlbmRzIEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IF91dGlsLkFubm90YXRpb25UeXBlLkxJTks7CiAgICBjb25zdCBxdWFkUG9pbnRzID0gZ2V0UXVhZFBvaW50cyhwYXJhbXMuZGljdCwgdGhpcy5yZWN0YW5nbGUpOwogICAgaWYgKHF1YWRQb2ludHMpIHsKICAgICAgdGhpcy5kYXRhLnF1YWRQb2ludHMgPSBxdWFkUG9pbnRzOwogICAgfQogICAgdGhpcy5kYXRhLmJvcmRlckNvbG9yID0gdGhpcy5kYXRhLmJvcmRlckNvbG9yIHx8IHRoaXMuZGF0YS5jb2xvcjsKICAgIF9jYXRhbG9nLkNhdGFsb2cucGFyc2VEZXN0RGljdGlvbmFyeSh7CiAgICAgIGRlc3REaWN0OiBwYXJhbXMuZGljdCwKICAgICAgcmVzdWx0T2JqOiB0aGlzLmRhdGEsCiAgICAgIGRvY0Jhc2VVcmw6IHBhcmFtcy5wZGZNYW5hZ2VyLmRvY0Jhc2VVcmwsCiAgICAgIGRvY0F0dGFjaG1lbnRzOiBwYXJhbXMuYXR0YWNobWVudHMKICAgIH0pOwogIH0KfQpjbGFzcyBQb3B1cEFubm90YXRpb24gZXh0ZW5kcyBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICBjb25zdCB7CiAgICAgIGRpY3QKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGUgPSBfdXRpbC5Bbm5vdGF0aW9uVHlwZS5QT1BVUDsKICAgIGxldCBwYXJlbnRJdGVtID0gZGljdC5nZXQoIlBhcmVudCIpOwogICAgaWYgKCFwYXJlbnRJdGVtKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKSgiUG9wdXAgYW5ub3RhdGlvbiBoYXMgYSBtaXNzaW5nIG9yIGludmFsaWQgcGFyZW50IGFubm90YXRpb24uIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHBhcmVudFN1YnR5cGUgPSBwYXJlbnRJdGVtLmdldCgiU3VidHlwZSIpOwogICAgdGhpcy5kYXRhLnBhcmVudFR5cGUgPSBwYXJlbnRTdWJ0eXBlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSA/IHBhcmVudFN1YnR5cGUubmFtZSA6IG51bGw7CiAgICBjb25zdCByYXdQYXJlbnQgPSBkaWN0LmdldFJhdygiUGFyZW50Iik7CiAgICB0aGlzLmRhdGEucGFyZW50SWQgPSByYXdQYXJlbnQgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYgPyByYXdQYXJlbnQudG9TdHJpbmcoKSA6IG51bGw7CiAgICBjb25zdCBwYXJlbnRSZWN0ID0gcGFyZW50SXRlbS5nZXRBcnJheSgiUmVjdCIpOwogICAgaWYgKEFycmF5LmlzQXJyYXkocGFyZW50UmVjdCkgJiYgcGFyZW50UmVjdC5sZW5ndGggPT09IDQpIHsKICAgICAgdGhpcy5kYXRhLnBhcmVudFJlY3QgPSBfdXRpbC5VdGlsLm5vcm1hbGl6ZVJlY3QocGFyZW50UmVjdCk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEucGFyZW50UmVjdCA9IFswLCAwLCAwLCAwXTsKICAgIH0KICAgIGNvbnN0IHJ0ID0gcGFyZW50SXRlbS5nZXQoIlJUIik7CiAgICBpZiAoKDAsIF9wcmltaXRpdmVzLmlzTmFtZSkocnQsIF91dGlsLkFubm90YXRpb25SZXBseVR5cGUuR1JPVVApKSB7CiAgICAgIHBhcmVudEl0ZW0gPSBwYXJlbnRJdGVtLmdldCgiSVJUIik7CiAgICB9CiAgICBpZiAoIXBhcmVudEl0ZW0uaGFzKCJNIikpIHsKICAgICAgdGhpcy5kYXRhLm1vZGlmaWNhdGlvbkRhdGUgPSBudWxsOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5zZXRNb2RpZmljYXRpb25EYXRlKHBhcmVudEl0ZW0uZ2V0KCJNIikpOwogICAgICB0aGlzLmRhdGEubW9kaWZpY2F0aW9uRGF0ZSA9IHRoaXMubW9kaWZpY2F0aW9uRGF0ZTsKICAgIH0KICAgIGlmICghcGFyZW50SXRlbS5oYXMoIkMiKSkgewogICAgICB0aGlzLmRhdGEuY29sb3IgPSBudWxsOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5zZXRDb2xvcihwYXJlbnRJdGVtLmdldEFycmF5KCJDIikpOwogICAgICB0aGlzLmRhdGEuY29sb3IgPSB0aGlzLmNvbG9yOwogICAgfQogICAgaWYgKCF0aGlzLnZpZXdhYmxlKSB7CiAgICAgIGNvbnN0IHBhcmVudEZsYWdzID0gcGFyZW50SXRlbS5nZXQoIkYiKTsKICAgICAgaWYgKHRoaXMuX2lzVmlld2FibGUocGFyZW50RmxhZ3MpKSB7CiAgICAgICAgdGhpcy5zZXRGbGFncyhwYXJlbnRGbGFncyk7CiAgICAgIH0KICAgIH0KICAgIHRoaXMuc2V0VGl0bGUocGFyZW50SXRlbS5nZXQoIlQiKSk7CiAgICB0aGlzLmRhdGEudGl0bGVPYmogPSB0aGlzLl90aXRsZTsKICAgIHRoaXMuc2V0Q29udGVudHMocGFyZW50SXRlbS5nZXQoIkNvbnRlbnRzIikpOwogICAgdGhpcy5kYXRhLmNvbnRlbnRzT2JqID0gdGhpcy5fY29udGVudHM7CiAgICBpZiAocGFyZW50SXRlbS5oYXMoIlJDIikpIHsKICAgICAgdGhpcy5kYXRhLnJpY2hUZXh0ID0gX2ZhY3RvcnkuWEZBRmFjdG9yeS5nZXRSaWNoVGV4dEFzSHRtbChwYXJlbnRJdGVtLmdldCgiUkMiKSk7CiAgICB9CiAgfQp9CmV4cG9ydHMuUG9wdXBBbm5vdGF0aW9uID0gUG9wdXBBbm5vdGF0aW9uOwpjbGFzcyBGcmVlVGV4dEFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLm5vUm90YXRlOwogICAgY29uc3QgewogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gX3V0aWwuQW5ub3RhdGlvblR5cGUuRlJFRVRFWFQ7CiAgICB0aGlzLnNldERlZmF1bHRBcHBlYXJhbmNlKHBhcmFtcyk7CiAgICBpZiAoIXRoaXMuYXBwZWFyYW5jZSAmJiB0aGlzLl9pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCkgewogICAgICBjb25zdCBzdHJva2VBbHBoYSA9IHBhcmFtcy5kaWN0LmdldCgiQ0EiKTsKICAgICAgY29uc3QgZmFrZVVuaWNvZGVGb250ID0gbmV3IF9kZWZhdWx0X2FwcGVhcmFuY2UuRmFrZVVuaWNvZGVGb250KHhyZWYsICJzYW5zLXNlcmlmIik7CiAgICAgIGNvbnN0IGZvbnREYXRhID0gdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YTsKICAgICAgdGhpcy5hcHBlYXJhbmNlID0gZmFrZVVuaWNvZGVGb250LmNyZWF0ZUFwcGVhcmFuY2UodGhpcy5fY29udGVudHMuc3RyLCB0aGlzLnJlY3RhbmdsZSwgdGhpcy5yb3RhdGlvbiwgZm9udERhdGEuZm9udFNpemUgfHwgMTAsIGZvbnREYXRhLmZvbnRDb2xvciwgc3Ryb2tlQWxwaGEpOwogICAgICB0aGlzLl9zdHJlYW1zLnB1c2godGhpcy5hcHBlYXJhbmNlLCBfZGVmYXVsdF9hcHBlYXJhbmNlLkZha2VVbmljb2RlRm9udC50b1VuaWNvZGVTdHJlYW0pOwogICAgfSBlbHNlIGlmICghdGhpcy5faXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKCJGcmVlVGV4dEFubm90YXRpb246IE9mZnNjcmVlbkNhbnZhcyBpcyBub3Qgc3VwcG9ydGVkLCBhbm5vdGF0aW9uIG1heSBub3QgcmVuZGVyIGNvcnJlY3RseS4iKTsKICAgIH0KICB9CiAgZ2V0IGhhc1RleHRDb250ZW50KCkgewogICAgcmV0dXJuICEhdGhpcy5hcHBlYXJhbmNlOwogIH0KICBzdGF0aWMgY3JlYXRlTmV3RGljdChhbm5vdGF0aW9uLCB4cmVmLCBfcmVmNCkgewogICAgbGV0IHsKICAgICAgYXBSZWYsCiAgICAgIGFwCiAgICB9ID0gX3JlZjQ7CiAgICBjb25zdCB7CiAgICAgIGNvbG9yLAogICAgICBmb250U2l6ZSwKICAgICAgcmVjdCwKICAgICAgcm90YXRpb24sCiAgICAgIHVzZXIsCiAgICAgIHZhbHVlCiAgICB9ID0gYW5ub3RhdGlvbjsKICAgIGNvbnN0IGZyZWV0ZXh0ID0gbmV3IF9wcmltaXRpdmVzLkRpY3QoeHJlZik7CiAgICBmcmVldGV4dC5zZXQoIlR5cGUiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiQW5ub3QiKSk7CiAgICBmcmVldGV4dC5zZXQoIlN1YnR5cGUiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiRnJlZVRleHQiKSk7CiAgICBmcmVldGV4dC5zZXQoIkNyZWF0aW9uRGF0ZSIsIGBEOiR7KDAsIF91dGlsLmdldE1vZGlmaWNhdGlvbkRhdGUpKCl9YCk7CiAgICBmcmVldGV4dC5zZXQoIlJlY3QiLCByZWN0KTsKICAgIGNvbnN0IGRhID0gYC9IZWx2ICR7Zm9udFNpemV9IFRmICR7KDAsIF9kZWZhdWx0X2FwcGVhcmFuY2UuZ2V0UGRmQ29sb3IpKGNvbG9yLCB0cnVlKX1gOwogICAgZnJlZXRleHQuc2V0KCJEQSIsIGRhKTsKICAgIGZyZWV0ZXh0LnNldCgiQ29udGVudHMiLCAoMCwgX2NvcmVfdXRpbHMuaXNBc2NpaSkodmFsdWUpID8gdmFsdWUgOiAoMCwgX2NvcmVfdXRpbHMuc3RyaW5nVG9VVEYxNlN0cmluZykodmFsdWUsIHRydWUpKTsKICAgIGZyZWV0ZXh0LnNldCgiRiIsIDQpOwogICAgZnJlZXRleHQuc2V0KCJCb3JkZXIiLCBbMCwgMCwgMF0pOwogICAgZnJlZXRleHQuc2V0KCJSb3RhdGUiLCByb3RhdGlvbik7CiAgICBpZiAodXNlcikgewogICAgICBmcmVldGV4dC5zZXQoIlQiLCAoMCwgX2NvcmVfdXRpbHMuaXNBc2NpaSkodXNlcikgPyB1c2VyIDogKDAsIF9jb3JlX3V0aWxzLnN0cmluZ1RvVVRGMTZTdHJpbmcpKHVzZXIsIHRydWUpKTsKICAgIH0KICAgIGlmIChhcFJlZiB8fCBhcCkgewogICAgICBjb25zdCBuID0gbmV3IF9wcmltaXRpdmVzLkRpY3QoeHJlZik7CiAgICAgIGZyZWV0ZXh0LnNldCgiQVAiLCBuKTsKICAgICAgaWYgKGFwUmVmKSB7CiAgICAgICAgbi5zZXQoIk4iLCBhcFJlZik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbi5zZXQoIk4iLCBhcCk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBmcmVldGV4dDsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZU5ld0FwcGVhcmFuY2VTdHJlYW0oYW5ub3RhdGlvbiwgeHJlZiwgcGFyYW1zKSB7CiAgICBjb25zdCB7CiAgICAgIGJhc2VGb250UmVmLAogICAgICBldmFsdWF0b3IsCiAgICAgIHRhc2sKICAgIH0gPSBwYXJhbXM7CiAgICBjb25zdCB7CiAgICAgIGNvbG9yLAogICAgICBmb250U2l6ZSwKICAgICAgcmVjdCwKICAgICAgcm90YXRpb24sCiAgICAgIHZhbHVlCiAgICB9ID0gYW5ub3RhdGlvbjsKICAgIGNvbnN0IHJlc291cmNlcyA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHhyZWYpOwogICAgY29uc3QgZm9udCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHhyZWYpOwogICAgaWYgKGJhc2VGb250UmVmKSB7CiAgICAgIGZvbnQuc2V0KCJIZWx2IiwgYmFzZUZvbnRSZWYpOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgYmFzZUZvbnQgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdCh4cmVmKTsKICAgICAgYmFzZUZvbnQuc2V0KCJCYXNlRm9udCIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJIZWx2ZXRpY2EiKSk7CiAgICAgIGJhc2VGb250LnNldCgiVHlwZSIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJGb250IikpOwogICAgICBiYXNlRm9udC5zZXQoIlN1YnR5cGUiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiVHlwZTEiKSk7CiAgICAgIGJhc2VGb250LnNldCgiRW5jb2RpbmciLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiV2luQW5zaUVuY29kaW5nIikpOwogICAgICBmb250LnNldCgiSGVsdiIsIGJhc2VGb250KTsKICAgIH0KICAgIHJlc291cmNlcy5zZXQoIkZvbnQiLCBmb250KTsKICAgIGNvbnN0IGhlbHYgPSBhd2FpdCBXaWRnZXRBbm5vdGF0aW9uLl9nZXRGb250RGF0YShldmFsdWF0b3IsIHRhc2ssIHsKICAgICAgZm9udE5hbWU6ICJIZWx2ZXRpY2EiLAogICAgICBmb250U2l6ZQogICAgfSwgcmVzb3VyY2VzKTsKICAgIGNvbnN0IFt4MSwgeTEsIHgyLCB5Ml0gPSByZWN0OwogICAgbGV0IHcgPSB4MiAtIHgxOwogICAgbGV0IGggPSB5MiAtIHkxOwogICAgaWYgKHJvdGF0aW9uICUgMTgwICE9PSAwKSB7CiAgICAgIFt3LCBoXSA9IFtoLCB3XTsKICAgIH0KICAgIGNvbnN0IGxpbmVzID0gdmFsdWUuc3BsaXQoIlxuIik7CiAgICBjb25zdCBzY2FsZSA9IGZvbnRTaXplIC8gMTAwMDsKICAgIGxldCB0b3RhbFdpZHRoID0gLUluZmluaXR5OwogICAgY29uc3QgZW5jb2RlZExpbmVzID0gW107CiAgICBmb3IgKGxldCBsaW5lIG9mIGxpbmVzKSB7CiAgICAgIGNvbnN0IGVuY29kZWQgPSBoZWx2LmVuY29kZVN0cmluZyhsaW5lKTsKICAgICAgaWYgKGVuY29kZWQubGVuZ3RoID4gMSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGxpbmUgPSBlbmNvZGVkLmpvaW4oIiIpOwogICAgICBlbmNvZGVkTGluZXMucHVzaChsaW5lKTsKICAgICAgbGV0IGxpbmVXaWR0aCA9IDA7CiAgICAgIGNvbnN0IGdseXBocyA9IGhlbHYuY2hhcnNUb0dseXBocyhsaW5lKTsKICAgICAgZm9yIChjb25zdCBnbHlwaCBvZiBnbHlwaHMpIHsKICAgICAgICBsaW5lV2lkdGggKz0gZ2x5cGgud2lkdGggKiBzY2FsZTsKICAgICAgfQogICAgICB0b3RhbFdpZHRoID0gTWF0aC5tYXgodG90YWxXaWR0aCwgbGluZVdpZHRoKTsKICAgIH0KICAgIGxldCBoc2NhbGUgPSAxOwogICAgaWYgKHRvdGFsV2lkdGggPiB3KSB7CiAgICAgIGhzY2FsZSA9IHcgLyB0b3RhbFdpZHRoOwogICAgfQogICAgbGV0IHZzY2FsZSA9IDE7CiAgICBjb25zdCBsaW5lSGVpZ2h0ID0gX3V0aWwuTElORV9GQUNUT1IgKiBmb250U2l6ZTsKICAgIGNvbnN0IGxpbmVEZXNjZW50ID0gX3V0aWwuTElORV9ERVNDRU5UX0ZBQ1RPUiAqIGZvbnRTaXplOwogICAgY29uc3QgdG90YWxIZWlnaHQgPSBsaW5lSGVpZ2h0ICogbGluZXMubGVuZ3RoOwogICAgaWYgKHRvdGFsSGVpZ2h0ID4gaCkgewogICAgICB2c2NhbGUgPSBoIC8gdG90YWxIZWlnaHQ7CiAgICB9CiAgICBjb25zdCBmc2NhbGUgPSBNYXRoLm1pbihoc2NhbGUsIHZzY2FsZSk7CiAgICBjb25zdCBuZXdGb250U2l6ZSA9IGZvbnRTaXplICogZnNjYWxlOwogICAgY29uc3QgYnVmZmVyID0gWyJxIiwgYDAgMCAkeygwLCBfY29yZV91dGlscy5udW1iZXJUb1N0cmluZykodyl9ICR7KDAsIF9jb3JlX3V0aWxzLm51bWJlclRvU3RyaW5nKShoKX0gcmUgVyBuYCwgYEJUYCwgYDEgMCAwIDEgMCAkeygwLCBfY29yZV91dGlscy5udW1iZXJUb1N0cmluZykoaCArIGxpbmVEZXNjZW50KX0gVG0gMCBUYyAkeygwLCBfZGVmYXVsdF9hcHBlYXJhbmNlLmdldFBkZkNvbG9yKShjb2xvciwgdHJ1ZSl9YCwgYC9IZWx2ICR7KDAsIF9jb3JlX3V0aWxzLm51bWJlclRvU3RyaW5nKShuZXdGb250U2l6ZSl9IFRmYF07CiAgICBjb25zdCB2U2hpZnQgPSAoMCwgX2NvcmVfdXRpbHMubnVtYmVyVG9TdHJpbmcpKGxpbmVIZWlnaHQpOwogICAgZm9yIChjb25zdCBsaW5lIG9mIGVuY29kZWRMaW5lcykgewogICAgICBidWZmZXIucHVzaChgMCAtJHt2U2hpZnR9IFRkICgkeygwLCBfY29yZV91dGlscy5lc2NhcGVTdHJpbmcpKGxpbmUpfSkgVGpgKTsKICAgIH0KICAgIGJ1ZmZlci5wdXNoKCJFVCIsICJRIik7CiAgICBjb25zdCBhcHBlYXJhbmNlID0gYnVmZmVyLmpvaW4oIlxuIik7CiAgICBjb25zdCBhcHBlYXJhbmNlU3RyZWFtRGljdCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHhyZWYpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJGb3JtVHlwZSIsIDEpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJTdWJ0eXBlIiwgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIkZvcm0iKSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlR5cGUiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiWE9iamVjdCIpKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiQkJveCIsIFswLCAwLCB3LCBoXSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlJlc291cmNlcyIsIHJlc291cmNlcyk7CiAgICBpZiAocm90YXRpb24pIHsKICAgICAgY29uc3QgbWF0cml4ID0gKDAsIF9jb3JlX3V0aWxzLmdldFJvdGF0aW9uTWF0cml4KShyb3RhdGlvbiwgdywgaCk7CiAgICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiTWF0cml4IiwgbWF0cml4KTsKICAgIH0KICAgIGNvbnN0IGFwID0gbmV3IF9zdHJlYW0uU3RyaW5nU3RyZWFtKGFwcGVhcmFuY2UpOwogICAgYXAuZGljdCA9IGFwcGVhcmFuY2VTdHJlYW1EaWN0OwogICAgcmV0dXJuIGFwOwogIH0KfQpjbGFzcyBMaW5lQW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgeHJlZgogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IF91dGlsLkFubm90YXRpb25UeXBlLkxJTkU7CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLm5vUm90YXRlOwogICAgY29uc3QgbGluZUNvb3JkaW5hdGVzID0gZGljdC5nZXRBcnJheSgiTCIpOwogICAgdGhpcy5kYXRhLmxpbmVDb29yZGluYXRlcyA9IF91dGlsLlV0aWwubm9ybWFsaXplUmVjdChsaW5lQ29vcmRpbmF0ZXMpOwogICAgdGhpcy5zZXRMaW5lRW5kaW5ncyhkaWN0LmdldEFycmF5KCJMRSIpKTsKICAgIHRoaXMuZGF0YS5saW5lRW5kaW5ncyA9IHRoaXMubGluZUVuZGluZ3M7CiAgICBpZiAoIXRoaXMuYXBwZWFyYW5jZSkgewogICAgICBjb25zdCBzdHJva2VDb2xvciA9IHRoaXMuY29sb3IgPyBnZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IpIDogWzAsIDAsIDBdOwogICAgICBjb25zdCBzdHJva2VBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICBjb25zdCBpbnRlcmlvckNvbG9yID0gZ2V0UmdiQ29sb3IoZGljdC5nZXRBcnJheSgiSUMiKSwgbnVsbCk7CiAgICAgIGNvbnN0IGZpbGxDb2xvciA9IGludGVyaW9yQ29sb3IgPyBnZXRQZGZDb2xvckFycmF5KGludGVyaW9yQ29sb3IpIDogbnVsbDsKICAgICAgY29uc3QgZmlsbEFscGhhID0gZmlsbENvbG9yID8gc3Ryb2tlQWxwaGEgOiBudWxsOwogICAgICBjb25zdCBib3JkZXJXaWR0aCA9IHRoaXMuYm9yZGVyU3R5bGUud2lkdGggfHwgMSwKICAgICAgICBib3JkZXJBZGp1c3QgPSAyICogYm9yZGVyV2lkdGg7CiAgICAgIGNvbnN0IGJib3ggPSBbdGhpcy5kYXRhLmxpbmVDb29yZGluYXRlc1swXSAtIGJvcmRlckFkanVzdCwgdGhpcy5kYXRhLmxpbmVDb29yZGluYXRlc1sxXSAtIGJvcmRlckFkanVzdCwgdGhpcy5kYXRhLmxpbmVDb29yZGluYXRlc1syXSArIGJvcmRlckFkanVzdCwgdGhpcy5kYXRhLmxpbmVDb29yZGluYXRlc1szXSArIGJvcmRlckFkanVzdF07CiAgICAgIGlmICghX3V0aWwuVXRpbC5pbnRlcnNlY3QodGhpcy5yZWN0YW5nbGUsIGJib3gpKSB7CiAgICAgICAgdGhpcy5yZWN0YW5nbGUgPSBiYm94OwogICAgICB9CiAgICAgIHRoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgICAgICB4cmVmLAogICAgICAgIGV4dHJhOiBgJHtib3JkZXJXaWR0aH0gd2AsCiAgICAgICAgc3Ryb2tlQ29sb3IsCiAgICAgICAgZmlsbENvbG9yLAogICAgICAgIHN0cm9rZUFscGhhLAogICAgICAgIGZpbGxBbHBoYSwKICAgICAgICBwb2ludHNDYWxsYmFjazogKGJ1ZmZlciwgcG9pbnRzKSA9PiB7CiAgICAgICAgICBidWZmZXIucHVzaChgJHtsaW5lQ29vcmRpbmF0ZXNbMF19ICR7bGluZUNvb3JkaW5hdGVzWzFdfSBtYCwgYCR7bGluZUNvb3JkaW5hdGVzWzJdfSAke2xpbmVDb29yZGluYXRlc1szXX0gbGAsICJTIik7CiAgICAgICAgICByZXR1cm4gW3BvaW50c1swXS54IC0gYm9yZGVyV2lkdGgsIHBvaW50c1sxXS54ICsgYm9yZGVyV2lkdGgsIHBvaW50c1szXS55IC0gYm9yZGVyV2lkdGgsIHBvaW50c1sxXS55ICsgYm9yZGVyV2lkdGhdOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CiAgfQp9CmNsYXNzIFNxdWFyZUFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICBjb25zdCB7CiAgICAgIGRpY3QsCiAgICAgIHhyZWYKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGUgPSBfdXRpbC5Bbm5vdGF0aW9uVHlwZS5TUVVBUkU7CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLm5vUm90YXRlOwogICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgY29uc3Qgc3Ryb2tlQ29sb3IgPSB0aGlzLmNvbG9yID8gZ2V0UGRmQ29sb3JBcnJheSh0aGlzLmNvbG9yKSA6IFswLCAwLCAwXTsKICAgICAgY29uc3Qgc3Ryb2tlQWxwaGEgPSBkaWN0LmdldCgiQ0EiKTsKICAgICAgY29uc3QgaW50ZXJpb3JDb2xvciA9IGdldFJnYkNvbG9yKGRpY3QuZ2V0QXJyYXkoIklDIiksIG51bGwpOwogICAgICBjb25zdCBmaWxsQ29sb3IgPSBpbnRlcmlvckNvbG9yID8gZ2V0UGRmQ29sb3JBcnJheShpbnRlcmlvckNvbG9yKSA6IG51bGw7CiAgICAgIGNvbnN0IGZpbGxBbHBoYSA9IGZpbGxDb2xvciA/IHN0cm9rZUFscGhhIDogbnVsbDsKICAgICAgaWYgKHRoaXMuYm9yZGVyU3R5bGUud2lkdGggPT09IDAgJiYgIWZpbGxDb2xvcikgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICB0aGlzLl9zZXREZWZhdWx0QXBwZWFyYW5jZSh7CiAgICAgICAgeHJlZiwKICAgICAgICBleHRyYTogYCR7dGhpcy5ib3JkZXJTdHlsZS53aWR0aH0gd2AsCiAgICAgICAgc3Ryb2tlQ29sb3IsCiAgICAgICAgZmlsbENvbG9yLAogICAgICAgIHN0cm9rZUFscGhhLAogICAgICAgIGZpbGxBbHBoYSwKICAgICAgICBwb2ludHNDYWxsYmFjazogKGJ1ZmZlciwgcG9pbnRzKSA9PiB7CiAgICAgICAgICBjb25zdCB4ID0gcG9pbnRzWzJdLnggKyB0aGlzLmJvcmRlclN0eWxlLndpZHRoIC8gMjsKICAgICAgICAgIGNvbnN0IHkgPSBwb2ludHNbMl0ueSArIHRoaXMuYm9yZGVyU3R5bGUud2lkdGggLyAyOwogICAgICAgICAgY29uc3Qgd2lkdGggPSBwb2ludHNbM10ueCAtIHBvaW50c1syXS54IC0gdGhpcy5ib3JkZXJTdHlsZS53aWR0aDsKICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHBvaW50c1sxXS55IC0gcG9pbnRzWzNdLnkgLSB0aGlzLmJvcmRlclN0eWxlLndpZHRoOwogICAgICAgICAgYnVmZmVyLnB1c2goYCR7eH0gJHt5fSAke3dpZHRofSAke2hlaWdodH0gcmVgKTsKICAgICAgICAgIGlmIChmaWxsQ29sb3IpIHsKICAgICAgICAgICAgYnVmZmVyLnB1c2goIkIiKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGJ1ZmZlci5wdXNoKCJTIik7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gW3BvaW50c1swXS54LCBwb2ludHNbMV0ueCwgcG9pbnRzWzNdLnksIHBvaW50c1sxXS55XTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQogIH0KfQpjbGFzcyBDaXJjbGVBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gX3V0aWwuQW5ub3RhdGlvblR5cGUuQ0lSQ0xFOwogICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgY29uc3Qgc3Ryb2tlQ29sb3IgPSB0aGlzLmNvbG9yID8gZ2V0UGRmQ29sb3JBcnJheSh0aGlzLmNvbG9yKSA6IFswLCAwLCAwXTsKICAgICAgY29uc3Qgc3Ryb2tlQWxwaGEgPSBkaWN0LmdldCgiQ0EiKTsKICAgICAgY29uc3QgaW50ZXJpb3JDb2xvciA9IGdldFJnYkNvbG9yKGRpY3QuZ2V0QXJyYXkoIklDIiksIG51bGwpOwogICAgICBjb25zdCBmaWxsQ29sb3IgPSBpbnRlcmlvckNvbG9yID8gZ2V0UGRmQ29sb3JBcnJheShpbnRlcmlvckNvbG9yKSA6IG51bGw7CiAgICAgIGNvbnN0IGZpbGxBbHBoYSA9IGZpbGxDb2xvciA/IHN0cm9rZUFscGhhIDogbnVsbDsKICAgICAgaWYgKHRoaXMuYm9yZGVyU3R5bGUud2lkdGggPT09IDAgJiYgIWZpbGxDb2xvcikgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBjb25zdCBjb250cm9sUG9pbnRzRGlzdGFuY2UgPSA0IC8gMyAqIE1hdGgudGFuKE1hdGguUEkgLyAoMiAqIDQpKTsKICAgICAgdGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2UoewogICAgICAgIHhyZWYsCiAgICAgICAgZXh0cmE6IGAke3RoaXMuYm9yZGVyU3R5bGUud2lkdGh9IHdgLAogICAgICAgIHN0cm9rZUNvbG9yLAogICAgICAgIGZpbGxDb2xvciwKICAgICAgICBzdHJva2VBbHBoYSwKICAgICAgICBmaWxsQWxwaGEsCiAgICAgICAgcG9pbnRzQ2FsbGJhY2s6IChidWZmZXIsIHBvaW50cykgPT4gewogICAgICAgICAgY29uc3QgeDAgPSBwb2ludHNbMF0ueCArIHRoaXMuYm9yZGVyU3R5bGUud2lkdGggLyAyOwogICAgICAgICAgY29uc3QgeTAgPSBwb2ludHNbMF0ueSAtIHRoaXMuYm9yZGVyU3R5bGUud2lkdGggLyAyOwogICAgICAgICAgY29uc3QgeDEgPSBwb2ludHNbM10ueCAtIHRoaXMuYm9yZGVyU3R5bGUud2lkdGggLyAyOwogICAgICAgICAgY29uc3QgeTEgPSBwb2ludHNbM10ueSArIHRoaXMuYm9yZGVyU3R5bGUud2lkdGggLyAyOwogICAgICAgICAgY29uc3QgeE1pZCA9IHgwICsgKHgxIC0geDApIC8gMjsKICAgICAgICAgIGNvbnN0IHlNaWQgPSB5MCArICh5MSAtIHkwKSAvIDI7CiAgICAgICAgICBjb25zdCB4T2Zmc2V0ID0gKHgxIC0geDApIC8gMiAqIGNvbnRyb2xQb2ludHNEaXN0YW5jZTsKICAgICAgICAgIGNvbnN0IHlPZmZzZXQgPSAoeTEgLSB5MCkgLyAyICogY29udHJvbFBvaW50c0Rpc3RhbmNlOwogICAgICAgICAgYnVmZmVyLnB1c2goYCR7eE1pZH0gJHt5MX0gbWAsIGAke3hNaWQgKyB4T2Zmc2V0fSAke3kxfSAke3gxfSAke3lNaWQgKyB5T2Zmc2V0fSAke3gxfSAke3lNaWR9IGNgLCBgJHt4MX0gJHt5TWlkIC0geU9mZnNldH0gJHt4TWlkICsgeE9mZnNldH0gJHt5MH0gJHt4TWlkfSAke3kwfSBjYCwgYCR7eE1pZCAtIHhPZmZzZXR9ICR7eTB9ICR7eDB9ICR7eU1pZCAtIHlPZmZzZXR9ICR7eDB9ICR7eU1pZH0gY2AsIGAke3gwfSAke3lNaWQgKyB5T2Zmc2V0fSAke3hNaWQgLSB4T2Zmc2V0fSAke3kxfSAke3hNaWR9ICR7eTF9IGNgLCAiaCIpOwogICAgICAgICAgaWYgKGZpbGxDb2xvcikgewogICAgICAgICAgICBidWZmZXIucHVzaCgiQiIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYnVmZmVyLnB1c2goIlMiKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBbcG9pbnRzWzBdLngsIHBvaW50c1sxXS54LCBwb2ludHNbM10ueSwgcG9pbnRzWzFdLnldOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CiAgfQp9CmNsYXNzIFBvbHlsaW5lQW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgeHJlZgogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IF91dGlsLkFubm90YXRpb25UeXBlLlBPTFlMSU5FOwogICAgdGhpcy5kYXRhLmhhc093bkNhbnZhcyA9IHRoaXMuZGF0YS5ub1JvdGF0ZTsKICAgIHRoaXMuZGF0YS52ZXJ0aWNlcyA9IFtdOwogICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFBvbHlnb25Bbm5vdGF0aW9uKSkgewogICAgICB0aGlzLnNldExpbmVFbmRpbmdzKGRpY3QuZ2V0QXJyYXkoIkxFIikpOwogICAgICB0aGlzLmRhdGEubGluZUVuZGluZ3MgPSB0aGlzLmxpbmVFbmRpbmdzOwogICAgfQogICAgY29uc3QgcmF3VmVydGljZXMgPSBkaWN0LmdldEFycmF5KCJWZXJ0aWNlcyIpOwogICAgaWYgKCFBcnJheS5pc0FycmF5KHJhd1ZlcnRpY2VzKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSByYXdWZXJ0aWNlcy5sZW5ndGg7IGkgPCBpaTsgaSArPSAyKSB7CiAgICAgIHRoaXMuZGF0YS52ZXJ0aWNlcy5wdXNoKHsKICAgICAgICB4OiByYXdWZXJ0aWNlc1tpXSwKICAgICAgICB5OiByYXdWZXJ0aWNlc1tpICsgMV0KICAgICAgfSk7CiAgICB9CiAgICBpZiAoIXRoaXMuYXBwZWFyYW5jZSkgewogICAgICBjb25zdCBzdHJva2VDb2xvciA9IHRoaXMuY29sb3IgPyBnZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IpIDogWzAsIDAsIDBdOwogICAgICBjb25zdCBzdHJva2VBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICBjb25zdCBib3JkZXJXaWR0aCA9IHRoaXMuYm9yZGVyU3R5bGUud2lkdGggfHwgMSwKICAgICAgICBib3JkZXJBZGp1c3QgPSAyICogYm9yZGVyV2lkdGg7CiAgICAgIGNvbnN0IGJib3ggPSBbSW5maW5pdHksIEluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV07CiAgICAgIGZvciAoY29uc3QgdmVydGV4IG9mIHRoaXMuZGF0YS52ZXJ0aWNlcykgewogICAgICAgIGJib3hbMF0gPSBNYXRoLm1pbihiYm94WzBdLCB2ZXJ0ZXgueCAtIGJvcmRlckFkanVzdCk7CiAgICAgICAgYmJveFsxXSA9IE1hdGgubWluKGJib3hbMV0sIHZlcnRleC55IC0gYm9yZGVyQWRqdXN0KTsKICAgICAgICBiYm94WzJdID0gTWF0aC5tYXgoYmJveFsyXSwgdmVydGV4LnggKyBib3JkZXJBZGp1c3QpOwogICAgICAgIGJib3hbM10gPSBNYXRoLm1heChiYm94WzNdLCB2ZXJ0ZXgueSArIGJvcmRlckFkanVzdCk7CiAgICAgIH0KICAgICAgaWYgKCFfdXRpbC5VdGlsLmludGVyc2VjdCh0aGlzLnJlY3RhbmdsZSwgYmJveCkpIHsKICAgICAgICB0aGlzLnJlY3RhbmdsZSA9IGJib3g7CiAgICAgIH0KICAgICAgdGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2UoewogICAgICAgIHhyZWYsCiAgICAgICAgZXh0cmE6IGAke2JvcmRlcldpZHRofSB3YCwKICAgICAgICBzdHJva2VDb2xvciwKICAgICAgICBzdHJva2VBbHBoYSwKICAgICAgICBwb2ludHNDYWxsYmFjazogKGJ1ZmZlciwgcG9pbnRzKSA9PiB7CiAgICAgICAgICBjb25zdCB2ZXJ0aWNlcyA9IHRoaXMuZGF0YS52ZXJ0aWNlczsKICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHZlcnRpY2VzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgICAgYnVmZmVyLnB1c2goYCR7dmVydGljZXNbaV0ueH0gJHt2ZXJ0aWNlc1tpXS55fSAke2kgPT09IDAgPyAibSIgOiAibCJ9YCk7CiAgICAgICAgICB9CiAgICAgICAgICBidWZmZXIucHVzaCgiUyIpOwogICAgICAgICAgcmV0dXJuIFtwb2ludHNbMF0ueCwgcG9pbnRzWzFdLngsIHBvaW50c1szXS55LCBwb2ludHNbMV0ueV07CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICB9Cn0KY2xhc3MgUG9seWdvbkFubm90YXRpb24gZXh0ZW5kcyBQb2x5bGluZUFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IF91dGlsLkFubm90YXRpb25UeXBlLlBPTFlHT047CiAgfQp9CmNsYXNzIENhcmV0QW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IF91dGlsLkFubm90YXRpb25UeXBlLkNBUkVUOwogIH0KfQpjbGFzcyBJbmtBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgdGhpcy5kYXRhLmhhc093bkNhbnZhcyA9IHRoaXMuZGF0YS5ub1JvdGF0ZTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgeHJlZgogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IF91dGlsLkFubm90YXRpb25UeXBlLklOSzsKICAgIHRoaXMuZGF0YS5pbmtMaXN0cyA9IFtdOwogICAgY29uc3QgcmF3SW5rTGlzdHMgPSBkaWN0LmdldEFycmF5KCJJbmtMaXN0Iik7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkocmF3SW5rTGlzdHMpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHJhd0lua0xpc3RzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgICAgdGhpcy5kYXRhLmlua0xpc3RzLnB1c2goW10pOwogICAgICBmb3IgKGxldCBqID0gMCwgamogPSByYXdJbmtMaXN0c1tpXS5sZW5ndGg7IGogPCBqajsgaiArPSAyKSB7CiAgICAgICAgdGhpcy5kYXRhLmlua0xpc3RzW2ldLnB1c2goewogICAgICAgICAgeDogeHJlZi5mZXRjaElmUmVmKHJhd0lua0xpc3RzW2ldW2pdKSwKICAgICAgICAgIHk6IHhyZWYuZmV0Y2hJZlJlZihyYXdJbmtMaXN0c1tpXVtqICsgMV0pCiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIGlmICghdGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgIGNvbnN0IHN0cm9rZUNvbG9yID0gdGhpcy5jb2xvciA/IGdldFBkZkNvbG9yQXJyYXkodGhpcy5jb2xvcikgOiBbMCwgMCwgMF07CiAgICAgIGNvbnN0IHN0cm9rZUFscGhhID0gZGljdC5nZXQoIkNBIik7CiAgICAgIGNvbnN0IGJvcmRlcldpZHRoID0gdGhpcy5ib3JkZXJTdHlsZS53aWR0aCB8fCAxLAogICAgICAgIGJvcmRlckFkanVzdCA9IDIgKiBib3JkZXJXaWR0aDsKICAgICAgY29uc3QgYmJveCA9IFtJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XTsKICAgICAgZm9yIChjb25zdCBpbmtMaXN0cyBvZiB0aGlzLmRhdGEuaW5rTGlzdHMpIHsKICAgICAgICBmb3IgKGNvbnN0IHZlcnRleCBvZiBpbmtMaXN0cykgewogICAgICAgICAgYmJveFswXSA9IE1hdGgubWluKGJib3hbMF0sIHZlcnRleC54IC0gYm9yZGVyQWRqdXN0KTsKICAgICAgICAgIGJib3hbMV0gPSBNYXRoLm1pbihiYm94WzFdLCB2ZXJ0ZXgueSAtIGJvcmRlckFkanVzdCk7CiAgICAgICAgICBiYm94WzJdID0gTWF0aC5tYXgoYmJveFsyXSwgdmVydGV4LnggKyBib3JkZXJBZGp1c3QpOwogICAgICAgICAgYmJveFszXSA9IE1hdGgubWF4KGJib3hbM10sIHZlcnRleC55ICsgYm9yZGVyQWRqdXN0KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCFfdXRpbC5VdGlsLmludGVyc2VjdCh0aGlzLnJlY3RhbmdsZSwgYmJveCkpIHsKICAgICAgICB0aGlzLnJlY3RhbmdsZSA9IGJib3g7CiAgICAgIH0KICAgICAgdGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2UoewogICAgICAgIHhyZWYsCiAgICAgICAgZXh0cmE6IGAke2JvcmRlcldpZHRofSB3YCwKICAgICAgICBzdHJva2VDb2xvciwKICAgICAgICBzdHJva2VBbHBoYSwKICAgICAgICBwb2ludHNDYWxsYmFjazogKGJ1ZmZlciwgcG9pbnRzKSA9PiB7CiAgICAgICAgICBmb3IgKGNvbnN0IGlua0xpc3Qgb2YgdGhpcy5kYXRhLmlua0xpc3RzKSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGlua0xpc3QubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgICAgIGJ1ZmZlci5wdXNoKGAke2lua0xpc3RbaV0ueH0gJHtpbmtMaXN0W2ldLnl9ICR7aSA9PT0gMCA/ICJtIiA6ICJsIn1gKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBidWZmZXIucHVzaCgiUyIpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIFtwb2ludHNbMF0ueCwgcG9pbnRzWzFdLngsIHBvaW50c1szXS55LCBwb2ludHNbMV0ueV07CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICB9CiAgc3RhdGljIGNyZWF0ZU5ld0RpY3QoYW5ub3RhdGlvbiwgeHJlZiwgX3JlZjUpIHsKICAgIGxldCB7CiAgICAgIGFwUmVmLAogICAgICBhcAogICAgfSA9IF9yZWY1OwogICAgY29uc3QgewogICAgICBwYXRocywKICAgICAgcmVjdCwKICAgICAgcm90YXRpb24KICAgIH0gPSBhbm5vdGF0aW9uOwogICAgY29uc3QgaW5rID0gbmV3IF9wcmltaXRpdmVzLkRpY3QoeHJlZik7CiAgICBpbmsuc2V0KCJUeXBlIiwgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIkFubm90IikpOwogICAgaW5rLnNldCgiU3VidHlwZSIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJJbmsiKSk7CiAgICBpbmsuc2V0KCJDcmVhdGlvbkRhdGUiLCBgRDokeygwLCBfdXRpbC5nZXRNb2RpZmljYXRpb25EYXRlKSgpfWApOwogICAgaW5rLnNldCgiUmVjdCIsIHJlY3QpOwogICAgaW5rLnNldCgiSW5rTGlzdCIsIHBhdGhzLm1hcChwID0+IHAucG9pbnRzKSk7CiAgICBpbmsuc2V0KCJGIiwgNCk7CiAgICBpbmsuc2V0KCJCb3JkZXIiLCBbMCwgMCwgMF0pOwogICAgaW5rLnNldCgiUm90YXRlIiwgcm90YXRpb24pOwogICAgY29uc3QgbiA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHhyZWYpOwogICAgaW5rLnNldCgiQVAiLCBuKTsKICAgIGlmIChhcFJlZikgewogICAgICBuLnNldCgiTiIsIGFwUmVmKTsKICAgIH0gZWxzZSB7CiAgICAgIG4uc2V0KCJOIiwgYXApOwogICAgfQogICAgcmV0dXJuIGluazsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZU5ld0FwcGVhcmFuY2VTdHJlYW0oYW5ub3RhdGlvbiwgeHJlZiwgcGFyYW1zKSB7CiAgICBjb25zdCB7CiAgICAgIGNvbG9yLAogICAgICByZWN0LAogICAgICByb3RhdGlvbiwKICAgICAgcGF0aHMsCiAgICAgIHRoaWNrbmVzcywKICAgICAgb3BhY2l0eQogICAgfSA9IGFubm90YXRpb247CiAgICBjb25zdCBbeDEsIHkxLCB4MiwgeTJdID0gcmVjdDsKICAgIGxldCB3ID0geDIgLSB4MTsKICAgIGxldCBoID0geTIgLSB5MTsKICAgIGlmIChyb3RhdGlvbiAlIDE4MCAhPT0gMCkgewogICAgICBbdywgaF0gPSBbaCwgd107CiAgICB9CiAgICBjb25zdCBhcHBlYXJhbmNlQnVmZmVyID0gW2Ake3RoaWNrbmVzc30gdyAxIEogMSBqYCwgYCR7KDAsIF9kZWZhdWx0X2FwcGVhcmFuY2UuZ2V0UGRmQ29sb3IpKGNvbG9yLCBmYWxzZSl9YF07CiAgICBpZiAob3BhY2l0eSAhPT0gMSkgewogICAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goIi9SMCBncyIpOwogICAgfQogICAgY29uc3QgYnVmZmVyID0gW107CiAgICBmb3IgKGNvbnN0IHsKICAgICAgYmV6aWVyCiAgICB9IG9mIHBhdGhzKSB7CiAgICAgIGJ1ZmZlci5sZW5ndGggPSAwOwogICAgICBidWZmZXIucHVzaChgJHsoMCwgX2NvcmVfdXRpbHMubnVtYmVyVG9TdHJpbmcpKGJlemllclswXSl9ICR7KDAsIF9jb3JlX3V0aWxzLm51bWJlclRvU3RyaW5nKShiZXppZXJbMV0pfSBtYCk7CiAgICAgIGZvciAobGV0IGkgPSAyLCBpaSA9IGJlemllci5sZW5ndGg7IGkgPCBpaTsgaSArPSA2KSB7CiAgICAgICAgY29uc3QgY3VydmUgPSBiZXppZXIuc2xpY2UoaSwgaSArIDYpLm1hcChfY29yZV91dGlscy5udW1iZXJUb1N0cmluZykuam9pbigiICIpOwogICAgICAgIGJ1ZmZlci5wdXNoKGAke2N1cnZlfSBjYCk7CiAgICAgIH0KICAgICAgYnVmZmVyLnB1c2goIlMiKTsKICAgICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKGJ1ZmZlci5qb2luKCJcbiIpKTsKICAgIH0KICAgIGNvbnN0IGFwcGVhcmFuY2UgPSBhcHBlYXJhbmNlQnVmZmVyLmpvaW4oIlxuIik7CiAgICBjb25zdCBhcHBlYXJhbmNlU3RyZWFtRGljdCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHhyZWYpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJGb3JtVHlwZSIsIDEpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJTdWJ0eXBlIiwgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIkZvcm0iKSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlR5cGUiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiWE9iamVjdCIpKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiQkJveCIsIFswLCAwLCB3LCBoXSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkxlbmd0aCIsIGFwcGVhcmFuY2UubGVuZ3RoKTsKICAgIGlmIChyb3RhdGlvbikgewogICAgICBjb25zdCBtYXRyaXggPSAoMCwgX2NvcmVfdXRpbHMuZ2V0Um90YXRpb25NYXRyaXgpKHJvdGF0aW9uLCB3LCBoKTsKICAgICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJNYXRyaXgiLCBtYXRyaXgpOwogICAgfQogICAgaWYgKG9wYWNpdHkgIT09IDEpIHsKICAgICAgY29uc3QgcmVzb3VyY2VzID0gbmV3IF9wcmltaXRpdmVzLkRpY3QoeHJlZik7CiAgICAgIGNvbnN0IGV4dEdTdGF0ZSA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHhyZWYpOwogICAgICBjb25zdCByMCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHhyZWYpOwogICAgICByMC5zZXQoIkNBIiwgb3BhY2l0eSk7CiAgICAgIHIwLnNldCgiVHlwZSIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJFeHRHU3RhdGUiKSk7CiAgICAgIGV4dEdTdGF0ZS5zZXQoIlIwIiwgcjApOwogICAgICByZXNvdXJjZXMuc2V0KCJFeHRHU3RhdGUiLCBleHRHU3RhdGUpOwogICAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlJlc291cmNlcyIsIHJlc291cmNlcyk7CiAgICB9CiAgICBjb25zdCBhcCA9IG5ldyBfc3RyZWFtLlN0cmluZ1N0cmVhbShhcHBlYXJhbmNlKTsKICAgIGFwLmRpY3QgPSBhcHBlYXJhbmNlU3RyZWFtRGljdDsKICAgIHJldHVybiBhcDsKICB9Cn0KY2xhc3MgSGlnaGxpZ2h0QW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgeHJlZgogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IF91dGlsLkFubm90YXRpb25UeXBlLkhJR0hMSUdIVDsKICAgIGNvbnN0IHF1YWRQb2ludHMgPSB0aGlzLmRhdGEucXVhZFBvaW50cyA9IGdldFF1YWRQb2ludHMoZGljdCwgbnVsbCk7CiAgICBpZiAocXVhZFBvaW50cykgewogICAgICBjb25zdCByZXNvdXJjZXMgPSB0aGlzLmFwcGVhcmFuY2UgJiYgdGhpcy5hcHBlYXJhbmNlLmRpY3QuZ2V0KCJSZXNvdXJjZXMiKTsKICAgICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UgfHwgIShyZXNvdXJjZXMgJiYgcmVzb3VyY2VzLmhhcygiRXh0R1N0YXRlIikpKSB7CiAgICAgICAgaWYgKHRoaXMuYXBwZWFyYW5jZSkgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJIaWdobGlnaHRBbm5vdGF0aW9uIC0gaWdub3JpbmcgYnVpbHQtaW4gYXBwZWFyYW5jZSBzdHJlYW0uIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGZpbGxDb2xvciA9IHRoaXMuY29sb3IgPyBnZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IpIDogWzEsIDEsIDBdOwogICAgICAgIGNvbnN0IGZpbGxBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICAgIHRoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgICAgICAgIHhyZWYsCiAgICAgICAgICBmaWxsQ29sb3IsCiAgICAgICAgICBibGVuZE1vZGU6ICJNdWx0aXBseSIsCiAgICAgICAgICBmaWxsQWxwaGEsCiAgICAgICAgICBwb2ludHNDYWxsYmFjazogKGJ1ZmZlciwgcG9pbnRzKSA9PiB7CiAgICAgICAgICAgIGJ1ZmZlci5wdXNoKGAke3BvaW50c1swXS54fSAke3BvaW50c1swXS55fSBtYCwgYCR7cG9pbnRzWzFdLnh9ICR7cG9pbnRzWzFdLnl9IGxgLCBgJHtwb2ludHNbM10ueH0gJHtwb2ludHNbM10ueX0gbGAsIGAke3BvaW50c1syXS54fSAke3BvaW50c1syXS55fSBsYCwgImYiKTsKICAgICAgICAgICAgcmV0dXJuIFtwb2ludHNbMF0ueCwgcG9pbnRzWzFdLngsIHBvaW50c1szXS55LCBwb2ludHNbMV0ueV07CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuZGF0YS5oYXNQb3B1cCA9IGZhbHNlOwogICAgfQogIH0KfQpjbGFzcyBVbmRlcmxpbmVBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gX3V0aWwuQW5ub3RhdGlvblR5cGUuVU5ERVJMSU5FOwogICAgY29uc3QgcXVhZFBvaW50cyA9IHRoaXMuZGF0YS5xdWFkUG9pbnRzID0gZ2V0UXVhZFBvaW50cyhkaWN0LCBudWxsKTsKICAgIGlmIChxdWFkUG9pbnRzKSB7CiAgICAgIGlmICghdGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgICAgY29uc3Qgc3Ryb2tlQ29sb3IgPSB0aGlzLmNvbG9yID8gZ2V0UGRmQ29sb3JBcnJheSh0aGlzLmNvbG9yKSA6IFswLCAwLCAwXTsKICAgICAgICBjb25zdCBzdHJva2VBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICAgIHRoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgICAgICAgIHhyZWYsCiAgICAgICAgICBleHRyYTogIltdIDAgZCAxIHciLAogICAgICAgICAgc3Ryb2tlQ29sb3IsCiAgICAgICAgICBzdHJva2VBbHBoYSwKICAgICAgICAgIHBvaW50c0NhbGxiYWNrOiAoYnVmZmVyLCBwb2ludHMpID0+IHsKICAgICAgICAgICAgYnVmZmVyLnB1c2goYCR7cG9pbnRzWzJdLnh9ICR7cG9pbnRzWzJdLnl9IG1gLCBgJHtwb2ludHNbM10ueH0gJHtwb2ludHNbM10ueX0gbGAsICJTIik7CiAgICAgICAgICAgIHJldHVybiBbcG9pbnRzWzBdLngsIHBvaW50c1sxXS54LCBwb2ludHNbM10ueSwgcG9pbnRzWzFdLnldOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEuaGFzUG9wdXAgPSBmYWxzZTsKICAgIH0KICB9Cn0KY2xhc3MgU3F1aWdnbHlBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gX3V0aWwuQW5ub3RhdGlvblR5cGUuU1FVSUdHTFk7CiAgICBjb25zdCBxdWFkUG9pbnRzID0gdGhpcy5kYXRhLnF1YWRQb2ludHMgPSBnZXRRdWFkUG9pbnRzKGRpY3QsIG51bGwpOwogICAgaWYgKHF1YWRQb2ludHMpIHsKICAgICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgICBjb25zdCBzdHJva2VDb2xvciA9IHRoaXMuY29sb3IgPyBnZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IpIDogWzAsIDAsIDBdOwogICAgICAgIGNvbnN0IHN0cm9rZUFscGhhID0gZGljdC5nZXQoIkNBIik7CiAgICAgICAgdGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2UoewogICAgICAgICAgeHJlZiwKICAgICAgICAgIGV4dHJhOiAiW10gMCBkIDEgdyIsCiAgICAgICAgICBzdHJva2VDb2xvciwKICAgICAgICAgIHN0cm9rZUFscGhhLAogICAgICAgICAgcG9pbnRzQ2FsbGJhY2s6IChidWZmZXIsIHBvaW50cykgPT4gewogICAgICAgICAgICBjb25zdCBkeSA9IChwb2ludHNbMF0ueSAtIHBvaW50c1syXS55KSAvIDY7CiAgICAgICAgICAgIGxldCBzaGlmdCA9IGR5OwogICAgICAgICAgICBsZXQgeCA9IHBvaW50c1syXS54OwogICAgICAgICAgICBjb25zdCB5ID0gcG9pbnRzWzJdLnk7CiAgICAgICAgICAgIGNvbnN0IHhFbmQgPSBwb2ludHNbM10ueDsKICAgICAgICAgICAgYnVmZmVyLnB1c2goYCR7eH0gJHt5ICsgc2hpZnR9IG1gKTsKICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgIHggKz0gMjsKICAgICAgICAgICAgICBzaGlmdCA9IHNoaWZ0ID09PSAwID8gZHkgOiAwOwogICAgICAgICAgICAgIGJ1ZmZlci5wdXNoKGAke3h9ICR7eSArIHNoaWZ0fSBsYCk7CiAgICAgICAgICAgIH0gd2hpbGUgKHggPCB4RW5kKTsKICAgICAgICAgICAgYnVmZmVyLnB1c2goIlMiKTsKICAgICAgICAgICAgcmV0dXJuIFtwb2ludHNbMl0ueCwgeEVuZCwgeSAtIDIgKiBkeSwgeSArIDIgKiBkeV07CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuZGF0YS5oYXNQb3B1cCA9IGZhbHNlOwogICAgfQogIH0KfQpjbGFzcyBTdHJpa2VPdXRBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gX3V0aWwuQW5ub3RhdGlvblR5cGUuU1RSSUtFT1VUOwogICAgY29uc3QgcXVhZFBvaW50cyA9IHRoaXMuZGF0YS5xdWFkUG9pbnRzID0gZ2V0UXVhZFBvaW50cyhkaWN0LCBudWxsKTsKICAgIGlmIChxdWFkUG9pbnRzKSB7CiAgICAgIGlmICghdGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgICAgY29uc3Qgc3Ryb2tlQ29sb3IgPSB0aGlzLmNvbG9yID8gZ2V0UGRmQ29sb3JBcnJheSh0aGlzLmNvbG9yKSA6IFswLCAwLCAwXTsKICAgICAgICBjb25zdCBzdHJva2VBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICAgIHRoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgICAgICAgIHhyZWYsCiAgICAgICAgICBleHRyYTogIltdIDAgZCAxIHciLAogICAgICAgICAgc3Ryb2tlQ29sb3IsCiAgICAgICAgICBzdHJva2VBbHBoYSwKICAgICAgICAgIHBvaW50c0NhbGxiYWNrOiAoYnVmZmVyLCBwb2ludHMpID0+IHsKICAgICAgICAgICAgYnVmZmVyLnB1c2goYCR7KHBvaW50c1swXS54ICsgcG9pbnRzWzJdLngpIC8gMn0gYCArIGAkeyhwb2ludHNbMF0ueSArIHBvaW50c1syXS55KSAvIDJ9IG1gLCBgJHsocG9pbnRzWzFdLnggKyBwb2ludHNbM10ueCkgLyAyfSBgICsgYCR7KHBvaW50c1sxXS55ICsgcG9pbnRzWzNdLnkpIC8gMn0gbGAsICJTIik7CiAgICAgICAgICAgIHJldHVybiBbcG9pbnRzWzBdLngsIHBvaW50c1sxXS54LCBwb2ludHNbM10ueSwgcG9pbnRzWzFdLnldOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEuaGFzUG9wdXAgPSBmYWxzZTsKICAgIH0KICB9Cn0KY2xhc3MgU3RhbXBBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gX3V0aWwuQW5ub3RhdGlvblR5cGUuU1RBTVA7CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLm5vUm90YXRlOwogIH0KfQpjbGFzcyBGaWxlQXR0YWNobWVudEFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICBjb25zdCB7CiAgICAgIGRpY3QsCiAgICAgIHhyZWYKICAgIH0gPSBwYXJhbXM7CiAgICBjb25zdCBmaWxlID0gbmV3IF9maWxlX3NwZWMuRmlsZVNwZWMoZGljdC5nZXQoIkZTIiksIHhyZWYpOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gX3V0aWwuQW5ub3RhdGlvblR5cGUuRklMRUFUVEFDSE1FTlQ7CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLm5vUm90YXRlOwogICAgdGhpcy5kYXRhLmZpbGUgPSBmaWxlLnNlcmlhbGl6YWJsZTsKICAgIGNvbnN0IG5hbWUgPSBkaWN0LmdldCgiTmFtZSIpOwogICAgdGhpcy5kYXRhLm5hbWUgPSBuYW1lIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSA/ICgwLCBfdXRpbC5zdHJpbmdUb1BERlN0cmluZykobmFtZS5uYW1lKSA6ICJQdXNoUGluIjsKICB9Cn0KCi8qKiovIH0pLAovKiAxNDcgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLkZha2VVbmljb2RlRm9udCA9IHZvaWQgMDsKZXhwb3J0cy5jcmVhdGVEZWZhdWx0QXBwZWFyYW5jZSA9IGNyZWF0ZURlZmF1bHRBcHBlYXJhbmNlOwpleHBvcnRzLmdldFBkZkNvbG9yID0gZ2V0UGRmQ29sb3I7CmV4cG9ydHMucGFyc2VEZWZhdWx0QXBwZWFyYW5jZSA9IHBhcnNlRGVmYXVsdEFwcGVhcmFuY2U7CnZhciBfcHJpbWl0aXZlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQwKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwp2YXIgX2NvbG9yc3BhY2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0OCk7CnZhciBfZXZhbHVhdG9yID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDkpOwp2YXIgX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQ0KTsKY2xhc3MgRGVmYXVsdEFwcGVhcmFuY2VFdmFsdWF0b3IgZXh0ZW5kcyBfZXZhbHVhdG9yLkV2YWx1YXRvclByZXByb2Nlc3NvciB7CiAgY29uc3RydWN0b3Ioc3RyKSB7CiAgICBzdXBlcihuZXcgX3N0cmVhbS5TdHJpbmdTdHJlYW0oc3RyKSk7CiAgfQogIHBhcnNlKCkgewogICAgY29uc3Qgb3BlcmF0aW9uID0gewogICAgICBmbjogMCwKICAgICAgYXJnczogW10KICAgIH07CiAgICBjb25zdCByZXN1bHQgPSB7CiAgICAgIGZvbnRTaXplOiAwLAogICAgICBmb250TmFtZTogIiIsCiAgICAgIGZvbnRDb2xvcjogbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDMpCiAgICB9OwogICAgdHJ5IHsKICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICBvcGVyYXRpb24uYXJncy5sZW5ndGggPSAwOwogICAgICAgIGlmICghdGhpcy5yZWFkKG9wZXJhdGlvbikpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAodGhpcy5zYXZlZFN0YXRlc0RlcHRoICE9PSAwKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgewogICAgICAgICAgZm4sCiAgICAgICAgICBhcmdzCiAgICAgICAgfSA9IG9wZXJhdGlvbjsKICAgICAgICBzd2l0Y2ggKGZuIHwgMCkgewogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0Rm9udDoKICAgICAgICAgICAgY29uc3QgW2ZvbnROYW1lLCBmb250U2l6ZV0gPSBhcmdzOwogICAgICAgICAgICBpZiAoZm9udE5hbWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgICAgICAgICAgcmVzdWx0LmZvbnROYW1lID0gZm9udE5hbWUubmFtZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodHlwZW9mIGZvbnRTaXplID09PSAibnVtYmVyIiAmJiBmb250U2l6ZSA+IDApIHsKICAgICAgICAgICAgICByZXN1bHQuZm9udFNpemUgPSBmb250U2l6ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldEZpbGxSR0JDb2xvcjoKICAgICAgICAgICAgX2NvbG9yc3BhY2UuQ29sb3JTcGFjZS5zaW5nbGV0b25zLnJnYi5nZXRSZ2JJdGVtKGFyZ3MsIDAsIHJlc3VsdC5mb250Q29sb3IsIDApOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldEZpbGxHcmF5OgogICAgICAgICAgICBfY29sb3JzcGFjZS5Db2xvclNwYWNlLnNpbmdsZXRvbnMuZ3JheS5nZXRSZ2JJdGVtKGFyZ3MsIDAsIHJlc3VsdC5mb250Q29sb3IsIDApOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldEZpbGxDb2xvclNwYWNlOgogICAgICAgICAgICBfY29sb3JzcGFjZS5Db2xvclNwYWNlLnNpbmdsZXRvbnMuY215ay5nZXRSZ2JJdGVtKGFyZ3MsIDAsIHJlc3VsdC5mb250Q29sb3IsIDApOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICAoMCwgX3V0aWwud2FybikoYHBhcnNlRGVmYXVsdEFwcGVhcmFuY2UgLSBpZ25vcmluZyBlcnJvcnM6ICIke3JlYXNvbn0iLmApOwogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9Cn0KZnVuY3Rpb24gcGFyc2VEZWZhdWx0QXBwZWFyYW5jZShzdHIpIHsKICByZXR1cm4gbmV3IERlZmF1bHRBcHBlYXJhbmNlRXZhbHVhdG9yKHN0cikucGFyc2UoKTsKfQpmdW5jdGlvbiBnZXRQZGZDb2xvcihjb2xvciwgaXNGaWxsKSB7CiAgaWYgKGNvbG9yWzBdID09PSBjb2xvclsxXSAmJiBjb2xvclsxXSA9PT0gY29sb3JbMl0pIHsKICAgIGNvbnN0IGdyYXkgPSBjb2xvclswXSAvIDI1NTsKICAgIHJldHVybiBgJHsoMCwgX2NvcmVfdXRpbHMubnVtYmVyVG9TdHJpbmcpKGdyYXkpfSAke2lzRmlsbCA/ICJnIiA6ICJHIn1gOwogIH0KICByZXR1cm4gQXJyYXkuZnJvbShjb2xvciwgYyA9PiAoMCwgX2NvcmVfdXRpbHMubnVtYmVyVG9TdHJpbmcpKGMgLyAyNTUpKS5qb2luKCIgIikgKyBgICR7aXNGaWxsID8gInJnIiA6ICJSRyJ9YDsKfQpmdW5jdGlvbiBjcmVhdGVEZWZhdWx0QXBwZWFyYW5jZShfcmVmKSB7CiAgbGV0IHsKICAgIGZvbnRTaXplLAogICAgZm9udE5hbWUsCiAgICBmb250Q29sb3IKICB9ID0gX3JlZjsKICByZXR1cm4gYC8keygwLCBfY29yZV91dGlscy5lc2NhcGVQREZOYW1lKShmb250TmFtZSl9ICR7Zm9udFNpemV9IFRmICR7Z2V0UGRmQ29sb3IoZm9udENvbG9yLCB0cnVlKX1gOwp9CmNsYXNzIEZha2VVbmljb2RlRm9udCB7CiAgY29uc3RydWN0b3IoeHJlZiwgZm9udEZhbWlseSkgewogICAgdGhpcy54cmVmID0geHJlZjsKICAgIHRoaXMud2lkdGhzID0gbnVsbDsKICAgIHRoaXMuZmlyc3RDaGFyID0gSW5maW5pdHk7CiAgICB0aGlzLmxhc3RDaGFyID0gLUluZmluaXR5OwogICAgdGhpcy5mb250RmFtaWx5ID0gZm9udEZhbWlseTsKICAgIGNvbnN0IGNhbnZhcyA9IG5ldyBPZmZzY3JlZW5DYW52YXMoMSwgMSk7CiAgICB0aGlzLmN0eE1lYXN1cmUgPSBjYW52YXMuZ2V0Q29udGV4dCgiMmQiKTsKICAgIGlmICghRmFrZVVuaWNvZGVGb250Ll9mb250TmFtZUlkKSB7CiAgICAgIEZha2VVbmljb2RlRm9udC5fZm9udE5hbWVJZCA9IDE7CiAgICB9CiAgICB0aGlzLmZvbnROYW1lID0gX3ByaW1pdGl2ZXMuTmFtZS5nZXQoYEludmFsaWRQREZqc0ZvbnRfJHtmb250RmFtaWx5fV8ke0Zha2VVbmljb2RlRm9udC5fZm9udE5hbWVJZCsrfWApOwogIH0KICBnZXQgdG9Vbmljb2RlUmVmKCkgewogICAgaWYgKCFGYWtlVW5pY29kZUZvbnQuX3RvVW5pY29kZVJlZikgewogICAgICBjb25zdCB0b1VuaWNvZGUgPSBgL0NJREluaXQgL1Byb2NTZXQgZmluZHJlc291cmNlIGJlZ2luCjEyIGRpY3QgYmVnaW4KYmVnaW5jbWFwCi9DSURTeXN0ZW1JbmZvCjw8IC9SZWdpc3RyeSAoQWRvYmUpCi9PcmRlcmluZyAoVUNTKSAvU3VwcGxlbWVudCAwID4+IGRlZgovQ01hcE5hbWUgL0Fkb2JlLUlkZW50aXR5LVVDUyBkZWYKL0NNYXBUeXBlIDIgZGVmCjEgYmVnaW5jb2Rlc3BhY2VyYW5nZQo8MDAwMD4gPEZGRkY+CmVuZGNvZGVzcGFjZXJhbmdlCjEgYmVnaW5iZnJhbmdlCjwwMDAwPiA8RkZGRj4gPDAwMDA+CmVuZGJmcmFuZ2UKZW5kY21hcCBDTWFwTmFtZSBjdXJyZW50ZGljdCAvQ01hcCBkZWZpbmVyZXNvdXJjZSBwb3AgZW5kIGVuZGA7CiAgICAgIGNvbnN0IHRvVW5pY29kZVN0cmVhbSA9IEZha2VVbmljb2RlRm9udC50b1VuaWNvZGVTdHJlYW0gPSBuZXcgX3N0cmVhbS5TdHJpbmdTdHJlYW0odG9Vbmljb2RlKTsKICAgICAgY29uc3QgdG9Vbmljb2RlRGljdCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHRoaXMueHJlZik7CiAgICAgIHRvVW5pY29kZVN0cmVhbS5kaWN0ID0gdG9Vbmljb2RlRGljdDsKICAgICAgdG9Vbmljb2RlRGljdC5zZXQoIkxlbmd0aCIsIHRvVW5pY29kZS5sZW5ndGgpOwogICAgICBGYWtlVW5pY29kZUZvbnQuX3RvVW5pY29kZVJlZiA9IHRoaXMueHJlZi5nZXROZXdQZXJzaXN0ZW50UmVmKHRvVW5pY29kZVN0cmVhbSk7CiAgICB9CiAgICByZXR1cm4gRmFrZVVuaWNvZGVGb250Ll90b1VuaWNvZGVSZWY7CiAgfQogIGdldCBmb250RGVzY3JpcHRvclJlZigpIHsKICAgIGlmICghRmFrZVVuaWNvZGVGb250Ll9mb250RGVzY3JpcHRvclJlZikgewogICAgICBjb25zdCBmb250RGVzY3JpcHRvciA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHRoaXMueHJlZik7CiAgICAgIGZvbnREZXNjcmlwdG9yLnNldCgiVHlwZSIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJGb250RGVzY3JpcHRvciIpKTsKICAgICAgZm9udERlc2NyaXB0b3Iuc2V0KCJGb250TmFtZSIsIHRoaXMuZm9udE5hbWUpOwogICAgICBmb250RGVzY3JpcHRvci5zZXQoIkZvbnRGYW1pbHkiLCAiTXlyaWFkUHJvIFJlZ3VsYXIiKTsKICAgICAgZm9udERlc2NyaXB0b3Iuc2V0KCJGb250QkJveCIsIFswLCAwLCAwLCAwXSk7CiAgICAgIGZvbnREZXNjcmlwdG9yLnNldCgiRm9udFN0cmV0Y2giLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiTm9ybWFsIikpOwogICAgICBmb250RGVzY3JpcHRvci5zZXQoIkZvbnRXZWlnaHQiLCA0MDApOwogICAgICBmb250RGVzY3JpcHRvci5zZXQoIkl0YWxpY0FuZ2xlIiwgMCk7CiAgICAgIEZha2VVbmljb2RlRm9udC5fZm9udERlc2NyaXB0b3JSZWYgPSB0aGlzLnhyZWYuZ2V0TmV3UGVyc2lzdGVudFJlZihmb250RGVzY3JpcHRvcik7CiAgICB9CiAgICByZXR1cm4gRmFrZVVuaWNvZGVGb250Ll9mb250RGVzY3JpcHRvclJlZjsKICB9CiAgZ2V0IGRlc2NlbmRhbnRGb250UmVmKCkgewogICAgY29uc3QgZGVzY2VuZGFudEZvbnQgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdCh0aGlzLnhyZWYpOwogICAgZGVzY2VuZGFudEZvbnQuc2V0KCJCYXNlRm9udCIsIHRoaXMuZm9udE5hbWUpOwogICAgZGVzY2VuZGFudEZvbnQuc2V0KCJUeXBlIiwgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIkZvbnQiKSk7CiAgICBkZXNjZW5kYW50Rm9udC5zZXQoIlN1YnR5cGUiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiQ0lERm9udFR5cGUwIikpOwogICAgZGVzY2VuZGFudEZvbnQuc2V0KCJDSURUb0dJRE1hcCIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJJZGVudGl0eSIpKTsKICAgIGRlc2NlbmRhbnRGb250LnNldCgiRmlyc3RDaGFyIiwgdGhpcy5maXJzdENoYXIpOwogICAgZGVzY2VuZGFudEZvbnQuc2V0KCJMYXN0Q2hhciIsIHRoaXMubGFzdENoYXIpOwogICAgZGVzY2VuZGFudEZvbnQuc2V0KCJGb250RGVzY3JpcHRvciIsIHRoaXMuZm9udERlc2NyaXB0b3JSZWYpOwogICAgZGVzY2VuZGFudEZvbnQuc2V0KCJEVyIsIDEwMDApOwogICAgY29uc3Qgd2lkdGhzID0gW107CiAgICBjb25zdCBjaGFycyA9IFsuLi50aGlzLndpZHRocy5lbnRyaWVzKCldLnNvcnQoKTsKICAgIGxldCBjdXJyZW50Q2hhciA9IG51bGw7CiAgICBsZXQgY3VycmVudFdpZHRocyA9IG51bGw7CiAgICBmb3IgKGNvbnN0IFtjaGFyLCB3aWR0aF0gb2YgY2hhcnMpIHsKICAgICAgaWYgKCFjdXJyZW50Q2hhcikgewogICAgICAgIGN1cnJlbnRDaGFyID0gY2hhcjsKICAgICAgICBjdXJyZW50V2lkdGhzID0gW3dpZHRoXTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoY2hhciA9PT0gY3VycmVudENoYXIgKyBjdXJyZW50V2lkdGhzLmxlbmd0aCkgewogICAgICAgIGN1cnJlbnRXaWR0aHMucHVzaCh3aWR0aCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgd2lkdGhzLnB1c2goY3VycmVudENoYXIsIGN1cnJlbnRXaWR0aHMpOwogICAgICAgIGN1cnJlbnRDaGFyID0gY2hhcjsKICAgICAgICBjdXJyZW50V2lkdGhzID0gW3dpZHRoXTsKICAgICAgfQogICAgfQogICAgaWYgKGN1cnJlbnRDaGFyKSB7CiAgICAgIHdpZHRocy5wdXNoKGN1cnJlbnRDaGFyLCBjdXJyZW50V2lkdGhzKTsKICAgIH0KICAgIGRlc2NlbmRhbnRGb250LnNldCgiVyIsIHdpZHRocyk7CiAgICBjb25zdCBjaWRTeXN0ZW1JbmZvID0gbmV3IF9wcmltaXRpdmVzLkRpY3QodGhpcy54cmVmKTsKICAgIGNpZFN5c3RlbUluZm8uc2V0KCJPcmRlcmluZyIsICJJZGVudGl0eSIpOwogICAgY2lkU3lzdGVtSW5mby5zZXQoIlJlZ2lzdHJ5IiwgIkFkb2JlIik7CiAgICBjaWRTeXN0ZW1JbmZvLnNldCgiU3VwcGxlbWVudCIsIDApOwogICAgZGVzY2VuZGFudEZvbnQuc2V0KCJDSURTeXN0ZW1JbmZvIiwgY2lkU3lzdGVtSW5mbyk7CiAgICByZXR1cm4gdGhpcy54cmVmLmdldE5ld1BlcnNpc3RlbnRSZWYoZGVzY2VuZGFudEZvbnQpOwogIH0KICBnZXQgYmFzZUZvbnRSZWYoKSB7CiAgICBjb25zdCBiYXNlRm9udCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHRoaXMueHJlZik7CiAgICBiYXNlRm9udC5zZXQoIkJhc2VGb250IiwgdGhpcy5mb250TmFtZSk7CiAgICBiYXNlRm9udC5zZXQoIlR5cGUiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiRm9udCIpKTsKICAgIGJhc2VGb250LnNldCgiU3VidHlwZSIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJUeXBlMCIpKTsKICAgIGJhc2VGb250LnNldCgiRW5jb2RpbmciLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiSWRlbnRpdHktSCIpKTsKICAgIGJhc2VGb250LnNldCgiRGVzY2VuZGFudEZvbnRzIiwgW3RoaXMuZGVzY2VuZGFudEZvbnRSZWZdKTsKICAgIGJhc2VGb250LnNldCgiVG9Vbmljb2RlIiwgdGhpcy50b1VuaWNvZGVSZWYpOwogICAgcmV0dXJuIHRoaXMueHJlZi5nZXROZXdQZXJzaXN0ZW50UmVmKGJhc2VGb250KTsKICB9CiAgZ2V0IHJlc291cmNlcygpIHsKICAgIGNvbnN0IHJlc291cmNlcyA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHRoaXMueHJlZik7CiAgICBjb25zdCBmb250ID0gbmV3IF9wcmltaXRpdmVzLkRpY3QodGhpcy54cmVmKTsKICAgIGZvbnQuc2V0KHRoaXMuZm9udE5hbWUubmFtZSwgdGhpcy5iYXNlRm9udFJlZik7CiAgICByZXNvdXJjZXMuc2V0KCJGb250IiwgZm9udCk7CiAgICByZXR1cm4gcmVzb3VyY2VzOwogIH0KICBfY3JlYXRlQ29udGV4dCgpIHsKICAgIHRoaXMud2lkdGhzID0gbmV3IE1hcCgpOwogICAgdGhpcy5jdHhNZWFzdXJlLmZvbnQgPSBgMTAwMHB4ICR7dGhpcy5mb250RmFtaWx5fWA7CiAgICByZXR1cm4gdGhpcy5jdHhNZWFzdXJlOwogIH0KICBjcmVhdGVGb250UmVzb3VyY2VzKHRleHQpIHsKICAgIGNvbnN0IGN0eCA9IHRoaXMuX2NyZWF0ZUNvbnRleHQoKTsKICAgIGZvciAoY29uc3QgbGluZSBvZiB0ZXh0LnNwbGl0KC9cclxuP3xcbi8pKSB7CiAgICAgIGZvciAoY29uc3QgY2hhciBvZiBsaW5lLnNwbGl0KCIiKSkgewogICAgICAgIGNvbnN0IGNvZGUgPSBjaGFyLmNoYXJDb2RlQXQoMCk7CiAgICAgICAgaWYgKHRoaXMud2lkdGhzLmhhcyhjb2RlKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG1ldHJpY3MgPSBjdHgubWVhc3VyZVRleHQoY2hhcik7CiAgICAgICAgY29uc3Qgd2lkdGggPSBNYXRoLmNlaWwobWV0cmljcy53aWR0aCk7CiAgICAgICAgdGhpcy53aWR0aHMuc2V0KGNvZGUsIHdpZHRoKTsKICAgICAgICB0aGlzLmZpcnN0Q2hhciA9IE1hdGgubWluKGNvZGUsIHRoaXMuZmlyc3RDaGFyKTsKICAgICAgICB0aGlzLmxhc3RDaGFyID0gTWF0aC5tYXgoY29kZSwgdGhpcy5sYXN0Q2hhcik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB0aGlzLnJlc291cmNlczsKICB9CiAgY3JlYXRlQXBwZWFyYW5jZSh0ZXh0LCByZWN0LCByb3RhdGlvbiwgZm9udFNpemUsIGJnQ29sb3IsIHN0cm9rZUFscGhhKSB7CiAgICBjb25zdCBjdHggPSB0aGlzLl9jcmVhdGVDb250ZXh0KCk7CiAgICBjb25zdCBsaW5lcyA9IFtdOwogICAgbGV0IG1heFdpZHRoID0gLUluZmluaXR5OwogICAgZm9yIChjb25zdCBsaW5lIG9mIHRleHQuc3BsaXQoL1xyXG4/fFxuLykpIHsKICAgICAgbGluZXMucHVzaChsaW5lKTsKICAgICAgY29uc3QgbGluZVdpZHRoID0gY3R4Lm1lYXN1cmVUZXh0KGxpbmUpLndpZHRoOwogICAgICBtYXhXaWR0aCA9IE1hdGgubWF4KG1heFdpZHRoLCBsaW5lV2lkdGgpOwogICAgICBmb3IgKGNvbnN0IGNoYXIgb2YgbGluZS5zcGxpdCgiIikpIHsKICAgICAgICBjb25zdCBjb2RlID0gY2hhci5jaGFyQ29kZUF0KDApOwogICAgICAgIGxldCB3aWR0aCA9IHRoaXMud2lkdGhzLmdldChjb2RlKTsKICAgICAgICBpZiAod2lkdGggPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgY29uc3QgbWV0cmljcyA9IGN0eC5tZWFzdXJlVGV4dChjaGFyKTsKICAgICAgICAgIHdpZHRoID0gTWF0aC5jZWlsKG1ldHJpY3Mud2lkdGgpOwogICAgICAgICAgdGhpcy53aWR0aHMuc2V0KGNvZGUsIHdpZHRoKTsKICAgICAgICAgIHRoaXMuZmlyc3RDaGFyID0gTWF0aC5taW4oY29kZSwgdGhpcy5maXJzdENoYXIpOwogICAgICAgICAgdGhpcy5sYXN0Q2hhciA9IE1hdGgubWF4KGNvZGUsIHRoaXMubGFzdENoYXIpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgbWF4V2lkdGggKj0gZm9udFNpemUgLyAxMDAwOwogICAgY29uc3QgW3gxLCB5MSwgeDIsIHkyXSA9IHJlY3Q7CiAgICBsZXQgdyA9IHgyIC0geDE7CiAgICBsZXQgaCA9IHkyIC0geTE7CiAgICBpZiAocm90YXRpb24gJSAxODAgIT09IDApIHsKICAgICAgW3csIGhdID0gW2gsIHddOwogICAgfQogICAgbGV0IGhzY2FsZSA9IDE7CiAgICBpZiAobWF4V2lkdGggPiB3KSB7CiAgICAgIGhzY2FsZSA9IHcgLyBtYXhXaWR0aDsKICAgIH0KICAgIGxldCB2c2NhbGUgPSAxOwogICAgY29uc3QgbGluZUhlaWdodCA9IF91dGlsLkxJTkVfRkFDVE9SICogZm9udFNpemU7CiAgICBjb25zdCBsaW5lRGVzY2VudCA9IF91dGlsLkxJTkVfREVTQ0VOVF9GQUNUT1IgKiBmb250U2l6ZTsKICAgIGNvbnN0IG1heEhlaWdodCA9IGxpbmVIZWlnaHQgKiBsaW5lcy5sZW5ndGg7CiAgICBpZiAobWF4SGVpZ2h0ID4gaCkgewogICAgICB2c2NhbGUgPSBoIC8gbWF4SGVpZ2h0OwogICAgfQogICAgY29uc3QgZnNjYWxlID0gTWF0aC5taW4oaHNjYWxlLCB2c2NhbGUpOwogICAgY29uc3QgbmV3Rm9udFNpemUgPSBmb250U2l6ZSAqIGZzY2FsZTsKICAgIGNvbnN0IGJ1ZmZlciA9IFsicSIsIGAwIDAgJHsoMCwgX2NvcmVfdXRpbHMubnVtYmVyVG9TdHJpbmcpKHcpfSAkeygwLCBfY29yZV91dGlscy5udW1iZXJUb1N0cmluZykoaCl9IHJlIFcgbmAsIGBCVGAsIGAxIDAgMCAxIDAgJHsoMCwgX2NvcmVfdXRpbHMubnVtYmVyVG9TdHJpbmcpKGggKyBsaW5lRGVzY2VudCl9IFRtIDAgVGMgJHtnZXRQZGZDb2xvcihiZ0NvbG9yLCB0cnVlKX1gLCBgLyR7dGhpcy5mb250TmFtZS5uYW1lfSAkeygwLCBfY29yZV91dGlscy5udW1iZXJUb1N0cmluZykobmV3Rm9udFNpemUpfSBUZmBdOwogICAgY29uc3QgewogICAgICByZXNvdXJjZXMKICAgIH0gPSB0aGlzOwogICAgc3Ryb2tlQWxwaGEgPSB0eXBlb2Ygc3Ryb2tlQWxwaGEgPT09ICJudW1iZXIiICYmIHN0cm9rZUFscGhhID49IDAgJiYgc3Ryb2tlQWxwaGEgPD0gMSA/IHN0cm9rZUFscGhhIDogMTsKICAgIGlmIChzdHJva2VBbHBoYSAhPT0gMSkgewogICAgICBidWZmZXIucHVzaCgiL1IwIGdzIik7CiAgICAgIGNvbnN0IGV4dEdTdGF0ZSA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHRoaXMueHJlZik7CiAgICAgIGNvbnN0IHIwID0gbmV3IF9wcmltaXRpdmVzLkRpY3QodGhpcy54cmVmKTsKICAgICAgcjAuc2V0KCJjYSIsIHN0cm9rZUFscGhhKTsKICAgICAgcjAuc2V0KCJDQSIsIHN0cm9rZUFscGhhKTsKICAgICAgcjAuc2V0KCJUeXBlIiwgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIkV4dEdTdGF0ZSIpKTsKICAgICAgZXh0R1N0YXRlLnNldCgiUjAiLCByMCk7CiAgICAgIHJlc291cmNlcy5zZXQoIkV4dEdTdGF0ZSIsIGV4dEdTdGF0ZSk7CiAgICB9CiAgICBjb25zdCB2U2hpZnQgPSAoMCwgX2NvcmVfdXRpbHMubnVtYmVyVG9TdHJpbmcpKGxpbmVIZWlnaHQpOwogICAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7CiAgICAgIGJ1ZmZlci5wdXNoKGAwIC0ke3ZTaGlmdH0gVGQgPCR7KDAsIF9jb3JlX3V0aWxzLnN0cmluZ1RvVVRGMTZIZXhTdHJpbmcpKGxpbmUpfT4gVGpgKTsKICAgIH0KICAgIGJ1ZmZlci5wdXNoKCJFVCIsICJRIik7CiAgICBjb25zdCBhcHBlYXJhbmNlID0gYnVmZmVyLmpvaW4oIlxuIik7CiAgICBjb25zdCBhcHBlYXJhbmNlU3RyZWFtRGljdCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHRoaXMueHJlZik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlN1YnR5cGUiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiRm9ybSIpKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiVHlwZSIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJYT2JqZWN0IikpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJCQm94IiwgWzAsIDAsIHcsIGhdKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiTGVuZ3RoIiwgYXBwZWFyYW5jZS5sZW5ndGgpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJSZXNvdXJjZXMiLCByZXNvdXJjZXMpOwogICAgaWYgKHJvdGF0aW9uKSB7CiAgICAgIGNvbnN0IG1hdHJpeCA9ICgwLCBfY29yZV91dGlscy5nZXRSb3RhdGlvbk1hdHJpeCkocm90YXRpb24sIHcsIGgpOwogICAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIk1hdHJpeCIsIG1hdHJpeCk7CiAgICB9CiAgICBjb25zdCBhcCA9IG5ldyBfc3RyZWFtLlN0cmluZ1N0cmVhbShhcHBlYXJhbmNlKTsKICAgIGFwLmRpY3QgPSBhcHBlYXJhbmNlU3RyZWFtRGljdDsKICAgIHJldHVybiBhcDsKICB9Cn0KZXhwb3J0cy5GYWtlVW5pY29kZUZvbnQgPSBGYWtlVW5pY29kZUZvbnQ7CgovKioqLyB9KSwKLyogMTQ4ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5Db2xvclNwYWNlID0gdm9pZCAwOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwp2YXIgX3ByaW1pdGl2ZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MCk7CnZhciBfYmFzZV9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MSk7CnZhciBfY29yZV91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTM5KTsKZnVuY3Rpb24gcmVzaXplUmdiSW1hZ2Uoc3JjLCBkZXN0LCB3MSwgaDEsIHcyLCBoMiwgYWxwaGEwMSkgewogIGNvbnN0IENPTVBPTkVOVFMgPSAzOwogIGFscGhhMDEgPSBhbHBoYTAxICE9PSAxID8gMCA6IGFscGhhMDE7CiAgY29uc3QgeFJhdGlvID0gdzEgLyB3MjsKICBjb25zdCB5UmF0aW8gPSBoMSAvIGgyOwogIGxldCBuZXdJbmRleCA9IDAsCiAgICBvbGRJbmRleDsKICBjb25zdCB4U2NhbGVkID0gbmV3IFVpbnQxNkFycmF5KHcyKTsKICBjb25zdCB3MVNjYW5saW5lID0gdzEgKiBDT01QT05FTlRTOwogIGZvciAobGV0IGkgPSAwOyBpIDwgdzI7IGkrKykgewogICAgeFNjYWxlZFtpXSA9IE1hdGguZmxvb3IoaSAqIHhSYXRpbykgKiBDT01QT05FTlRTOwogIH0KICBmb3IgKGxldCBpID0gMDsgaSA8IGgyOyBpKyspIHsKICAgIGNvbnN0IHB5ID0gTWF0aC5mbG9vcihpICogeVJhdGlvKSAqIHcxU2NhbmxpbmU7CiAgICBmb3IgKGxldCBqID0gMDsgaiA8IHcyOyBqKyspIHsKICAgICAgb2xkSW5kZXggPSBweSArIHhTY2FsZWRbal07CiAgICAgIGRlc3RbbmV3SW5kZXgrK10gPSBzcmNbb2xkSW5kZXgrK107CiAgICAgIGRlc3RbbmV3SW5kZXgrK10gPSBzcmNbb2xkSW5kZXgrK107CiAgICAgIGRlc3RbbmV3SW5kZXgrK10gPSBzcmNbb2xkSW5kZXgrK107CiAgICAgIG5ld0luZGV4ICs9IGFscGhhMDE7CiAgICB9CiAgfQp9CmNsYXNzIENvbG9yU3BhY2UgewogIGNvbnN0cnVjdG9yKG5hbWUsIG51bUNvbXBzKSB7CiAgICBpZiAodGhpcy5jb25zdHJ1Y3RvciA9PT0gQ29sb3JTcGFjZSkgewogICAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJDYW5ub3QgaW5pdGlhbGl6ZSBDb2xvclNwYWNlLiIpOwogICAgfQogICAgdGhpcy5uYW1lID0gbmFtZTsKICAgIHRoaXMubnVtQ29tcHMgPSBudW1Db21wczsKICB9CiAgZ2V0UmdiKHNyYywgc3JjT2Zmc2V0KSB7CiAgICBjb25zdCByZ2IgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoMyk7CiAgICB0aGlzLmdldFJnYkl0ZW0oc3JjLCBzcmNPZmZzZXQsIHJnYiwgMCk7CiAgICByZXR1cm4gcmdiOwogIH0KICBnZXRSZ2JJdGVtKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJTaG91bGQgbm90IGNhbGwgQ29sb3JTcGFjZS5nZXRSZ2JJdGVtIik7CiAgfQogIGdldFJnYkJ1ZmZlcihzcmMsIHNyY09mZnNldCwgY291bnQsIGRlc3QsIGRlc3RPZmZzZXQsIGJpdHMsIGFscGhhMDEpIHsKICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIlNob3VsZCBub3QgY2FsbCBDb2xvclNwYWNlLmdldFJnYkJ1ZmZlciIpOwogIH0KICBnZXRPdXRwdXRMZW5ndGgoaW5wdXRMZW5ndGgsIGFscGhhMDEpIHsKICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIlNob3VsZCBub3QgY2FsbCBDb2xvclNwYWNlLmdldE91dHB1dExlbmd0aCIpOwogIH0KICBpc1Bhc3N0aHJvdWdoKGJpdHMpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgaXNEZWZhdWx0RGVjb2RlKGRlY29kZU1hcCwgYnBjKSB7CiAgICByZXR1cm4gQ29sb3JTcGFjZS5pc0RlZmF1bHREZWNvZGUoZGVjb2RlTWFwLCB0aGlzLm51bUNvbXBzKTsKICB9CiAgZmlsbFJnYihkZXN0LCBvcmlnaW5hbFdpZHRoLCBvcmlnaW5hbEhlaWdodCwgd2lkdGgsIGhlaWdodCwgYWN0dWFsSGVpZ2h0LCBicGMsIGNvbXBzLCBhbHBoYTAxKSB7CiAgICBjb25zdCBjb3VudCA9IG9yaWdpbmFsV2lkdGggKiBvcmlnaW5hbEhlaWdodDsKICAgIGxldCByZ2JCdWYgPSBudWxsOwogICAgY29uc3QgbnVtQ29tcG9uZW50Q29sb3JzID0gMSA8PCBicGM7CiAgICBjb25zdCBuZWVkc1Jlc2l6aW5nID0gb3JpZ2luYWxIZWlnaHQgIT09IGhlaWdodCB8fCBvcmlnaW5hbFdpZHRoICE9PSB3aWR0aDsKICAgIGlmICh0aGlzLmlzUGFzc3Rocm91Z2goYnBjKSkgewogICAgICByZ2JCdWYgPSBjb21wczsKICAgIH0gZWxzZSBpZiAodGhpcy5udW1Db21wcyA9PT0gMSAmJiBjb3VudCA+IG51bUNvbXBvbmVudENvbG9ycyAmJiB0aGlzLm5hbWUgIT09ICJEZXZpY2VHcmF5IiAmJiB0aGlzLm5hbWUgIT09ICJEZXZpY2VSR0IiKSB7CiAgICAgIGNvbnN0IGFsbENvbG9ycyA9IGJwYyA8PSA4ID8gbmV3IFVpbnQ4QXJyYXkobnVtQ29tcG9uZW50Q29sb3JzKSA6IG5ldyBVaW50MTZBcnJheShudW1Db21wb25lbnRDb2xvcnMpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUNvbXBvbmVudENvbG9yczsgaSsrKSB7CiAgICAgICAgYWxsQ29sb3JzW2ldID0gaTsKICAgICAgfQogICAgICBjb25zdCBjb2xvck1hcCA9IG5ldyBVaW50OENsYW1wZWRBcnJheShudW1Db21wb25lbnRDb2xvcnMgKiAzKTsKICAgICAgdGhpcy5nZXRSZ2JCdWZmZXIoYWxsQ29sb3JzLCAwLCBudW1Db21wb25lbnRDb2xvcnMsIGNvbG9yTWFwLCAwLCBicGMsIDApOwogICAgICBpZiAoIW5lZWRzUmVzaXppbmcpIHsKICAgICAgICBsZXQgZGVzdFBvcyA9IDA7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgKytpKSB7CiAgICAgICAgICBjb25zdCBrZXkgPSBjb21wc1tpXSAqIDM7CiAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSBjb2xvck1hcFtrZXldOwogICAgICAgICAgZGVzdFtkZXN0UG9zKytdID0gY29sb3JNYXBba2V5ICsgMV07CiAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSBjb2xvck1hcFtrZXkgKyAyXTsKICAgICAgICAgIGRlc3RQb3MgKz0gYWxwaGEwMTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcmdiQnVmID0gbmV3IFVpbnQ4QXJyYXkoY291bnQgKiAzKTsKICAgICAgICBsZXQgcmdiUG9zID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyArK2kpIHsKICAgICAgICAgIGNvbnN0IGtleSA9IGNvbXBzW2ldICogMzsKICAgICAgICAgIHJnYkJ1ZltyZ2JQb3MrK10gPSBjb2xvck1hcFtrZXldOwogICAgICAgICAgcmdiQnVmW3JnYlBvcysrXSA9IGNvbG9yTWFwW2tleSArIDFdOwogICAgICAgICAgcmdiQnVmW3JnYlBvcysrXSA9IGNvbG9yTWFwW2tleSArIDJdOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgaWYgKCFuZWVkc1Jlc2l6aW5nKSB7CiAgICAgICAgdGhpcy5nZXRSZ2JCdWZmZXIoY29tcHMsIDAsIHdpZHRoICogYWN0dWFsSGVpZ2h0LCBkZXN0LCAwLCBicGMsIGFscGhhMDEpOwogICAgICB9IGVsc2UgewogICAgICAgIHJnYkJ1ZiA9IG5ldyBVaW50OENsYW1wZWRBcnJheShjb3VudCAqIDMpOwogICAgICAgIHRoaXMuZ2V0UmdiQnVmZmVyKGNvbXBzLCAwLCBjb3VudCwgcmdiQnVmLCAwLCBicGMsIDApOwogICAgICB9CiAgICB9CiAgICBpZiAocmdiQnVmKSB7CiAgICAgIGlmIChuZWVkc1Jlc2l6aW5nKSB7CiAgICAgICAgcmVzaXplUmdiSW1hZ2UocmdiQnVmLCBkZXN0LCBvcmlnaW5hbFdpZHRoLCBvcmlnaW5hbEhlaWdodCwgd2lkdGgsIGhlaWdodCwgYWxwaGEwMSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbGV0IGRlc3RQb3MgPSAwLAogICAgICAgICAgcmdiUG9zID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB3aWR0aCAqIGFjdHVhbEhlaWdodDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgIGRlc3RbZGVzdFBvcysrXSA9IHJnYkJ1ZltyZ2JQb3MrK107CiAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSByZ2JCdWZbcmdiUG9zKytdOwogICAgICAgICAgZGVzdFtkZXN0UG9zKytdID0gcmdiQnVmW3JnYlBvcysrXTsKICAgICAgICAgIGRlc3RQb3MgKz0gYWxwaGEwMTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgZ2V0IHVzZXNaZXJvVG9PbmVSYW5nZSgpIHsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAidXNlc1plcm9Ub09uZVJhbmdlIiwgdHJ1ZSk7CiAgfQogIHN0YXRpYyBfY2FjaGUoY2FjaGVLZXksIHhyZWYsIGxvY2FsQ29sb3JTcGFjZUNhY2hlLCBwYXJzZWRDb2xvclNwYWNlKSB7CiAgICBpZiAoIWxvY2FsQ29sb3JTcGFjZUNhY2hlKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignQ29sb3JTcGFjZS5fY2FjaGUgLSBleHBlY3RlZCAibG9jYWxDb2xvclNwYWNlQ2FjaGUiIGFyZ3VtZW50LicpOwogICAgfQogICAgaWYgKCFwYXJzZWRDb2xvclNwYWNlKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignQ29sb3JTcGFjZS5fY2FjaGUgLSBleHBlY3RlZCAicGFyc2VkQ29sb3JTcGFjZSIgYXJndW1lbnQuJyk7CiAgICB9CiAgICBsZXQgY3NOYW1lLCBjc1JlZjsKICAgIGlmIChjYWNoZUtleSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICBjc1JlZiA9IGNhY2hlS2V5OwogICAgICBjYWNoZUtleSA9IHhyZWYuZmV0Y2goY2FjaGVLZXkpOwogICAgfQogICAgaWYgKGNhY2hlS2V5IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICBjc05hbWUgPSBjYWNoZUtleS5uYW1lOwogICAgfQogICAgaWYgKGNzTmFtZSB8fCBjc1JlZikgewogICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZS5zZXQoY3NOYW1lLCBjc1JlZiwgcGFyc2VkQ29sb3JTcGFjZSk7CiAgICB9CiAgfQogIHN0YXRpYyBnZXRDYWNoZWQoY2FjaGVLZXksIHhyZWYsIGxvY2FsQ29sb3JTcGFjZUNhY2hlKSB7CiAgICBpZiAoIWxvY2FsQ29sb3JTcGFjZUNhY2hlKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignQ29sb3JTcGFjZS5nZXRDYWNoZWQgLSBleHBlY3RlZCAibG9jYWxDb2xvclNwYWNlQ2FjaGUiIGFyZ3VtZW50LicpOwogICAgfQogICAgaWYgKGNhY2hlS2V5IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgIGNvbnN0IGxvY2FsQ29sb3JTcGFjZSA9IGxvY2FsQ29sb3JTcGFjZUNhY2hlLmdldEJ5UmVmKGNhY2hlS2V5KTsKICAgICAgaWYgKGxvY2FsQ29sb3JTcGFjZSkgewogICAgICAgIHJldHVybiBsb2NhbENvbG9yU3BhY2U7CiAgICAgIH0KICAgICAgdHJ5IHsKICAgICAgICBjYWNoZUtleSA9IHhyZWYuZmV0Y2goY2FjaGVLZXkpOwogICAgICB9IGNhdGNoIChleCkgewogICAgICAgIGlmIChleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgICB0aHJvdyBleDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChjYWNoZUtleSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgY29uc3QgbG9jYWxDb2xvclNwYWNlID0gbG9jYWxDb2xvclNwYWNlQ2FjaGUuZ2V0QnlOYW1lKGNhY2hlS2V5Lm5hbWUpOwogICAgICBpZiAobG9jYWxDb2xvclNwYWNlKSB7CiAgICAgICAgcmV0dXJuIGxvY2FsQ29sb3JTcGFjZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogIHN0YXRpYyBhc3luYyBwYXJzZUFzeW5jKF9yZWYpIHsKICAgIGxldCB7CiAgICAgIGNzLAogICAgICB4cmVmLAogICAgICByZXNvdXJjZXMgPSBudWxsLAogICAgICBwZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgICB9ID0gX3JlZjsKICAgIGNvbnN0IHBhcnNlZENvbG9yU3BhY2UgPSB0aGlzLl9wYXJzZShjcywgeHJlZiwgcmVzb3VyY2VzLCBwZGZGdW5jdGlvbkZhY3RvcnkpOwogICAgdGhpcy5fY2FjaGUoY3MsIHhyZWYsIGxvY2FsQ29sb3JTcGFjZUNhY2hlLCBwYXJzZWRDb2xvclNwYWNlKTsKICAgIHJldHVybiBwYXJzZWRDb2xvclNwYWNlOwogIH0KICBzdGF0aWMgcGFyc2UoX3JlZjIpIHsKICAgIGxldCB7CiAgICAgIGNzLAogICAgICB4cmVmLAogICAgICByZXNvdXJjZXMgPSBudWxsLAogICAgICBwZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgICB9ID0gX3JlZjI7CiAgICBjb25zdCBjYWNoZWRDb2xvclNwYWNlID0gdGhpcy5nZXRDYWNoZWQoY3MsIHhyZWYsIGxvY2FsQ29sb3JTcGFjZUNhY2hlKTsKICAgIGlmIChjYWNoZWRDb2xvclNwYWNlKSB7CiAgICAgIHJldHVybiBjYWNoZWRDb2xvclNwYWNlOwogICAgfQogICAgY29uc3QgcGFyc2VkQ29sb3JTcGFjZSA9IHRoaXMuX3BhcnNlKGNzLCB4cmVmLCByZXNvdXJjZXMsIHBkZkZ1bmN0aW9uRmFjdG9yeSk7CiAgICB0aGlzLl9jYWNoZShjcywgeHJlZiwgbG9jYWxDb2xvclNwYWNlQ2FjaGUsIHBhcnNlZENvbG9yU3BhY2UpOwogICAgcmV0dXJuIHBhcnNlZENvbG9yU3BhY2U7CiAgfQogIHN0YXRpYyBfcGFyc2UoY3MsIHhyZWYpIHsKICAgIGxldCByZXNvdXJjZXMgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IG51bGw7CiAgICBsZXQgcGRmRnVuY3Rpb25GYWN0b3J5ID0gYXJndW1lbnRzLmxlbmd0aCA+IDMgPyBhcmd1bWVudHNbM10gOiB1bmRlZmluZWQ7CiAgICBjcyA9IHhyZWYuZmV0Y2hJZlJlZihjcyk7CiAgICBpZiAoY3MgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgIHN3aXRjaCAoY3MubmFtZSkgewogICAgICAgIGNhc2UgIkciOgogICAgICAgIGNhc2UgIkRldmljZUdyYXkiOgogICAgICAgICAgcmV0dXJuIHRoaXMuc2luZ2xldG9ucy5ncmF5OwogICAgICAgIGNhc2UgIlJHQiI6CiAgICAgICAgY2FzZSAiRGV2aWNlUkdCIjoKICAgICAgICAgIHJldHVybiB0aGlzLnNpbmdsZXRvbnMucmdiOwogICAgICAgIGNhc2UgIkNNWUsiOgogICAgICAgIGNhc2UgIkRldmljZUNNWUsiOgogICAgICAgICAgcmV0dXJuIHRoaXMuc2luZ2xldG9ucy5jbXlrOwogICAgICAgIGNhc2UgIlBhdHRlcm4iOgogICAgICAgICAgcmV0dXJuIG5ldyBQYXR0ZXJuQ1MobnVsbCk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIGlmIChyZXNvdXJjZXMgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgICAgICAgIGNvbnN0IGNvbG9yU3BhY2VzID0gcmVzb3VyY2VzLmdldCgiQ29sb3JTcGFjZSIpOwogICAgICAgICAgICBpZiAoY29sb3JTcGFjZXMgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgICAgICAgICAgY29uc3QgcmVzb3VyY2VzQ1MgPSBjb2xvclNwYWNlcy5nZXQoY3MubmFtZSk7CiAgICAgICAgICAgICAgaWYgKHJlc291cmNlc0NTKSB7CiAgICAgICAgICAgICAgICBpZiAocmVzb3VyY2VzQ1MgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9wYXJzZShyZXNvdXJjZXNDUywgeHJlZiwgcmVzb3VyY2VzLCBwZGZGdW5jdGlvbkZhY3RvcnkpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY3MgPSByZXNvdXJjZXNDUzsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBVbnJlY29nbml6ZWQgQ29sb3JTcGFjZTogJHtjcy5uYW1lfWApOwogICAgICB9CiAgICB9CiAgICBpZiAoQXJyYXkuaXNBcnJheShjcykpIHsKICAgICAgY29uc3QgbW9kZSA9IHhyZWYuZmV0Y2hJZlJlZihjc1swXSkubmFtZTsKICAgICAgbGV0IHBhcmFtcywgbnVtQ29tcHMsIGJhc2VDUywgd2hpdGVQb2ludCwgYmxhY2tQb2ludCwgZ2FtbWE7CiAgICAgIHN3aXRjaCAobW9kZSkgewogICAgICAgIGNhc2UgIkciOgogICAgICAgIGNhc2UgIkRldmljZUdyYXkiOgogICAgICAgICAgcmV0dXJuIHRoaXMuc2luZ2xldG9ucy5ncmF5OwogICAgICAgIGNhc2UgIlJHQiI6CiAgICAgICAgY2FzZSAiRGV2aWNlUkdCIjoKICAgICAgICAgIHJldHVybiB0aGlzLnNpbmdsZXRvbnMucmdiOwogICAgICAgIGNhc2UgIkNNWUsiOgogICAgICAgIGNhc2UgIkRldmljZUNNWUsiOgogICAgICAgICAgcmV0dXJuIHRoaXMuc2luZ2xldG9ucy5jbXlrOwogICAgICAgIGNhc2UgIkNhbEdyYXkiOgogICAgICAgICAgcGFyYW1zID0geHJlZi5mZXRjaElmUmVmKGNzWzFdKTsKICAgICAgICAgIHdoaXRlUG9pbnQgPSBwYXJhbXMuZ2V0QXJyYXkoIldoaXRlUG9pbnQiKTsKICAgICAgICAgIGJsYWNrUG9pbnQgPSBwYXJhbXMuZ2V0QXJyYXkoIkJsYWNrUG9pbnQiKTsKICAgICAgICAgIGdhbW1hID0gcGFyYW1zLmdldCgiR2FtbWEiKTsKICAgICAgICAgIHJldHVybiBuZXcgQ2FsR3JheUNTKHdoaXRlUG9pbnQsIGJsYWNrUG9pbnQsIGdhbW1hKTsKICAgICAgICBjYXNlICJDYWxSR0IiOgogICAgICAgICAgcGFyYW1zID0geHJlZi5mZXRjaElmUmVmKGNzWzFdKTsKICAgICAgICAgIHdoaXRlUG9pbnQgPSBwYXJhbXMuZ2V0QXJyYXkoIldoaXRlUG9pbnQiKTsKICAgICAgICAgIGJsYWNrUG9pbnQgPSBwYXJhbXMuZ2V0QXJyYXkoIkJsYWNrUG9pbnQiKTsKICAgICAgICAgIGdhbW1hID0gcGFyYW1zLmdldEFycmF5KCJHYW1tYSIpOwogICAgICAgICAgY29uc3QgbWF0cml4ID0gcGFyYW1zLmdldEFycmF5KCJNYXRyaXgiKTsKICAgICAgICAgIHJldHVybiBuZXcgQ2FsUkdCQ1Mod2hpdGVQb2ludCwgYmxhY2tQb2ludCwgZ2FtbWEsIG1hdHJpeCk7CiAgICAgICAgY2FzZSAiSUNDQmFzZWQiOgogICAgICAgICAgY29uc3Qgc3RyZWFtID0geHJlZi5mZXRjaElmUmVmKGNzWzFdKTsKICAgICAgICAgIGNvbnN0IGRpY3QgPSBzdHJlYW0uZGljdDsKICAgICAgICAgIG51bUNvbXBzID0gZGljdC5nZXQoIk4iKTsKICAgICAgICAgIGNvbnN0IGFsdCA9IGRpY3QuZ2V0KCJBbHRlcm5hdGUiKTsKICAgICAgICAgIGlmIChhbHQpIHsKICAgICAgICAgICAgY29uc3QgYWx0Q1MgPSB0aGlzLl9wYXJzZShhbHQsIHhyZWYsIHJlc291cmNlcywgcGRmRnVuY3Rpb25GYWN0b3J5KTsKICAgICAgICAgICAgaWYgKGFsdENTLm51bUNvbXBzID09PSBudW1Db21wcykgewogICAgICAgICAgICAgIHJldHVybiBhbHRDUzsKICAgICAgICAgICAgfQogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoIklDQ0Jhc2VkIGNvbG9yIHNwYWNlOiBJZ25vcmluZyBpbmNvcnJlY3QgL0FsdGVybmF0ZSBlbnRyeS4iKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChudW1Db21wcyA9PT0gMSkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5zaW5nbGV0b25zLmdyYXk7CiAgICAgICAgICB9IGVsc2UgaWYgKG51bUNvbXBzID09PSAzKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnNpbmdsZXRvbnMucmdiOwogICAgICAgICAgfSBlbHNlIGlmIChudW1Db21wcyA9PT0gNCkgewogICAgICAgICAgICByZXR1cm4gdGhpcy5zaW5nbGV0b25zLmNteWs7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJQYXR0ZXJuIjoKICAgICAgICAgIGJhc2VDUyA9IGNzWzFdIHx8IG51bGw7CiAgICAgICAgICBpZiAoYmFzZUNTKSB7CiAgICAgICAgICAgIGJhc2VDUyA9IHRoaXMuX3BhcnNlKGJhc2VDUywgeHJlZiwgcmVzb3VyY2VzLCBwZGZGdW5jdGlvbkZhY3RvcnkpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG5ldyBQYXR0ZXJuQ1MoYmFzZUNTKTsKICAgICAgICBjYXNlICJJIjoKICAgICAgICBjYXNlICJJbmRleGVkIjoKICAgICAgICAgIGJhc2VDUyA9IHRoaXMuX3BhcnNlKGNzWzFdLCB4cmVmLCByZXNvdXJjZXMsIHBkZkZ1bmN0aW9uRmFjdG9yeSk7CiAgICAgICAgICBjb25zdCBoaVZhbCA9IHhyZWYuZmV0Y2hJZlJlZihjc1syXSkgKyAxOwogICAgICAgICAgY29uc3QgbG9va3VwID0geHJlZi5mZXRjaElmUmVmKGNzWzNdKTsKICAgICAgICAgIHJldHVybiBuZXcgSW5kZXhlZENTKGJhc2VDUywgaGlWYWwsIGxvb2t1cCk7CiAgICAgICAgY2FzZSAiU2VwYXJhdGlvbiI6CiAgICAgICAgY2FzZSAiRGV2aWNlTiI6CiAgICAgICAgICBjb25zdCBuYW1lID0geHJlZi5mZXRjaElmUmVmKGNzWzFdKTsKICAgICAgICAgIG51bUNvbXBzID0gQXJyYXkuaXNBcnJheShuYW1lKSA/IG5hbWUubGVuZ3RoIDogMTsKICAgICAgICAgIGJhc2VDUyA9IHRoaXMuX3BhcnNlKGNzWzJdLCB4cmVmLCByZXNvdXJjZXMsIHBkZkZ1bmN0aW9uRmFjdG9yeSk7CiAgICAgICAgICBjb25zdCB0aW50Rm4gPSBwZGZGdW5jdGlvbkZhY3RvcnkuY3JlYXRlKGNzWzNdKTsKICAgICAgICAgIHJldHVybiBuZXcgQWx0ZXJuYXRlQ1MobnVtQ29tcHMsIGJhc2VDUywgdGludEZuKTsKICAgICAgICBjYXNlICJMYWIiOgogICAgICAgICAgcGFyYW1zID0geHJlZi5mZXRjaElmUmVmKGNzWzFdKTsKICAgICAgICAgIHdoaXRlUG9pbnQgPSBwYXJhbXMuZ2V0QXJyYXkoIldoaXRlUG9pbnQiKTsKICAgICAgICAgIGJsYWNrUG9pbnQgPSBwYXJhbXMuZ2V0QXJyYXkoIkJsYWNrUG9pbnQiKTsKICAgICAgICAgIGNvbnN0IHJhbmdlID0gcGFyYW1zLmdldEFycmF5KCJSYW5nZSIpOwogICAgICAgICAgcmV0dXJuIG5ldyBMYWJDUyh3aGl0ZVBvaW50LCBibGFja1BvaW50LCByYW5nZSk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgVW5pbXBsZW1lbnRlZCBDb2xvclNwYWNlIG9iamVjdDogJHttb2RlfWApOwogICAgICB9CiAgICB9CiAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYFVucmVjb2duaXplZCBDb2xvclNwYWNlIG9iamVjdDogJHtjc31gKTsKICB9CiAgc3RhdGljIGlzRGVmYXVsdERlY29kZShkZWNvZGUsIG51bUNvbXBzKSB7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGVjb2RlKSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmIChudW1Db21wcyAqIDIgIT09IGRlY29kZS5sZW5ndGgpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKCJUaGUgZGVjb2RlIG1hcCBpcyBub3QgdGhlIGNvcnJlY3QgbGVuZ3RoIik7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZGVjb2RlLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgaWYgKGRlY29kZVtpXSAhPT0gMCB8fCBkZWNvZGVbaSArIDFdICE9PSAxKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgc3RhdGljIGdldCBzaW5nbGV0b25zKCkgewogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJzaW5nbGV0b25zIiwgewogICAgICBnZXQgZ3JheSgpIHsKICAgICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImdyYXkiLCBuZXcgRGV2aWNlR3JheUNTKCkpOwogICAgICB9LAogICAgICBnZXQgcmdiKCkgewogICAgICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAicmdiIiwgbmV3IERldmljZVJnYkNTKCkpOwogICAgICB9LAogICAgICBnZXQgY215aygpIHsKICAgICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImNteWsiLCBuZXcgRGV2aWNlQ215a0NTKCkpOwogICAgICB9CiAgICB9KTsKICB9Cn0KZXhwb3J0cy5Db2xvclNwYWNlID0gQ29sb3JTcGFjZTsKY2xhc3MgQWx0ZXJuYXRlQ1MgZXh0ZW5kcyBDb2xvclNwYWNlIHsKICBjb25zdHJ1Y3RvcihudW1Db21wcywgYmFzZSwgdGludEZuKSB7CiAgICBzdXBlcigiQWx0ZXJuYXRlIiwgbnVtQ29tcHMpOwogICAgdGhpcy5iYXNlID0gYmFzZTsKICAgIHRoaXMudGludEZuID0gdGludEZuOwogICAgdGhpcy50bXBCdWYgPSBuZXcgRmxvYXQzMkFycmF5KGJhc2UubnVtQ29tcHMpOwogIH0KICBnZXRSZ2JJdGVtKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICBjb25zdCB0bXBCdWYgPSB0aGlzLnRtcEJ1ZjsKICAgIHRoaXMudGludEZuKHNyYywgc3JjT2Zmc2V0LCB0bXBCdWYsIDApOwogICAgdGhpcy5iYXNlLmdldFJnYkl0ZW0odG1wQnVmLCAwLCBkZXN0LCBkZXN0T2Zmc2V0KTsKICB9CiAgZ2V0UmdiQnVmZmVyKHNyYywgc3JjT2Zmc2V0LCBjb3VudCwgZGVzdCwgZGVzdE9mZnNldCwgYml0cywgYWxwaGEwMSkgewogICAgY29uc3QgdGludEZuID0gdGhpcy50aW50Rm47CiAgICBjb25zdCBiYXNlID0gdGhpcy5iYXNlOwogICAgY29uc3Qgc2NhbGUgPSAxIC8gKCgxIDw8IGJpdHMpIC0gMSk7CiAgICBjb25zdCBiYXNlTnVtQ29tcHMgPSBiYXNlLm51bUNvbXBzOwogICAgY29uc3QgdXNlc1plcm9Ub09uZVJhbmdlID0gYmFzZS51c2VzWmVyb1RvT25lUmFuZ2U7CiAgICBjb25zdCBpc1Bhc3N0aHJvdWdoID0gKGJhc2UuaXNQYXNzdGhyb3VnaCg4KSB8fCAhdXNlc1plcm9Ub09uZVJhbmdlKSAmJiBhbHBoYTAxID09PSAwOwogICAgbGV0IHBvcyA9IGlzUGFzc3Rocm91Z2ggPyBkZXN0T2Zmc2V0IDogMDsKICAgIGNvbnN0IGJhc2VCdWYgPSBpc1Bhc3N0aHJvdWdoID8gZGVzdCA6IG5ldyBVaW50OENsYW1wZWRBcnJheShiYXNlTnVtQ29tcHMgKiBjb3VudCk7CiAgICBjb25zdCBudW1Db21wcyA9IHRoaXMubnVtQ29tcHM7CiAgICBjb25zdCBzY2FsZWQgPSBuZXcgRmxvYXQzMkFycmF5KG51bUNvbXBzKTsKICAgIGNvbnN0IHRpbnRlZCA9IG5ldyBGbG9hdDMyQXJyYXkoYmFzZU51bUNvbXBzKTsKICAgIGxldCBpLCBqOwogICAgZm9yIChpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgZm9yIChqID0gMDsgaiA8IG51bUNvbXBzOyBqKyspIHsKICAgICAgICBzY2FsZWRbal0gPSBzcmNbc3JjT2Zmc2V0KytdICogc2NhbGU7CiAgICAgIH0KICAgICAgdGludEZuKHNjYWxlZCwgMCwgdGludGVkLCAwKTsKICAgICAgaWYgKHVzZXNaZXJvVG9PbmVSYW5nZSkgewogICAgICAgIGZvciAoaiA9IDA7IGogPCBiYXNlTnVtQ29tcHM7IGorKykgewogICAgICAgICAgYmFzZUJ1Zltwb3MrK10gPSB0aW50ZWRbal0gKiAyNTU7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGJhc2UuZ2V0UmdiSXRlbSh0aW50ZWQsIDAsIGJhc2VCdWYsIHBvcyk7CiAgICAgICAgcG9zICs9IGJhc2VOdW1Db21wczsKICAgICAgfQogICAgfQogICAgaWYgKCFpc1Bhc3N0aHJvdWdoKSB7CiAgICAgIGJhc2UuZ2V0UmdiQnVmZmVyKGJhc2VCdWYsIDAsIGNvdW50LCBkZXN0LCBkZXN0T2Zmc2V0LCA4LCBhbHBoYTAxKTsKICAgIH0KICB9CiAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICByZXR1cm4gdGhpcy5iYXNlLmdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aCAqIHRoaXMuYmFzZS5udW1Db21wcyAvIHRoaXMubnVtQ29tcHMsIGFscGhhMDEpOwogIH0KfQpjbGFzcyBQYXR0ZXJuQ1MgZXh0ZW5kcyBDb2xvclNwYWNlIHsKICBjb25zdHJ1Y3RvcihiYXNlQ1MpIHsKICAgIHN1cGVyKCJQYXR0ZXJuIiwgbnVsbCk7CiAgICB0aGlzLmJhc2UgPSBiYXNlQ1M7CiAgfQogIGlzRGVmYXVsdERlY29kZShkZWNvZGVNYXAsIGJwYykgewogICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiU2hvdWxkIG5vdCBjYWxsIFBhdHRlcm5DUy5pc0RlZmF1bHREZWNvZGUiKTsKICB9Cn0KY2xhc3MgSW5kZXhlZENTIGV4dGVuZHMgQ29sb3JTcGFjZSB7CiAgY29uc3RydWN0b3IoYmFzZSwgaGlnaFZhbCwgbG9va3VwKSB7CiAgICBzdXBlcigiSW5kZXhlZCIsIDEpOwogICAgdGhpcy5iYXNlID0gYmFzZTsKICAgIHRoaXMuaGlnaFZhbCA9IGhpZ2hWYWw7CiAgICBjb25zdCBsZW5ndGggPSBiYXNlLm51bUNvbXBzICogaGlnaFZhbDsKICAgIHRoaXMubG9va3VwID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoKTsKICAgIGlmIChsb29rdXAgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkgewogICAgICBjb25zdCBieXRlcyA9IGxvb2t1cC5nZXRCeXRlcyhsZW5ndGgpOwogICAgICB0aGlzLmxvb2t1cC5zZXQoYnl0ZXMpOwogICAgfSBlbHNlIGlmICh0eXBlb2YgbG9va3VwID09PSAic3RyaW5nIikgewogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgdGhpcy5sb29rdXBbaV0gPSBsb29rdXAuY2hhckNvZGVBdChpKSAmIDB4ZmY7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgSW5kZXhlZENTIC0gdW5yZWNvZ25pemVkIGxvb2t1cCB0YWJsZTogJHtsb29rdXB9YCk7CiAgICB9CiAgfQogIGdldFJnYkl0ZW0oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgIGNvbnN0IG51bUNvbXBzID0gdGhpcy5iYXNlLm51bUNvbXBzOwogICAgY29uc3Qgc3RhcnQgPSBzcmNbc3JjT2Zmc2V0XSAqIG51bUNvbXBzOwogICAgdGhpcy5iYXNlLmdldFJnYkJ1ZmZlcih0aGlzLmxvb2t1cCwgc3RhcnQsIDEsIGRlc3QsIGRlc3RPZmZzZXQsIDgsIDApOwogIH0KICBnZXRSZ2JCdWZmZXIoc3JjLCBzcmNPZmZzZXQsIGNvdW50LCBkZXN0LCBkZXN0T2Zmc2V0LCBiaXRzLCBhbHBoYTAxKSB7CiAgICBjb25zdCBiYXNlID0gdGhpcy5iYXNlOwogICAgY29uc3QgbnVtQ29tcHMgPSBiYXNlLm51bUNvbXBzOwogICAgY29uc3Qgb3V0cHV0RGVsdGEgPSBiYXNlLmdldE91dHB1dExlbmd0aChudW1Db21wcywgYWxwaGEwMSk7CiAgICBjb25zdCBsb29rdXAgPSB0aGlzLmxvb2t1cDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7ICsraSkgewogICAgICBjb25zdCBsb29rdXBQb3MgPSBzcmNbc3JjT2Zmc2V0KytdICogbnVtQ29tcHM7CiAgICAgIGJhc2UuZ2V0UmdiQnVmZmVyKGxvb2t1cCwgbG9va3VwUG9zLCAxLCBkZXN0LCBkZXN0T2Zmc2V0LCA4LCBhbHBoYTAxKTsKICAgICAgZGVzdE9mZnNldCArPSBvdXRwdXREZWx0YTsKICAgIH0KICB9CiAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICByZXR1cm4gdGhpcy5iYXNlLmdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aCAqIHRoaXMuYmFzZS5udW1Db21wcywgYWxwaGEwMSk7CiAgfQogIGlzRGVmYXVsdERlY29kZShkZWNvZGVNYXAsIGJwYykgewogICAgaWYgKCFBcnJheS5pc0FycmF5KGRlY29kZU1hcCkpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBpZiAoZGVjb2RlTWFwLmxlbmd0aCAhPT0gMikgewogICAgICAoMCwgX3V0aWwud2FybikoIkRlY29kZSBtYXAgbGVuZ3RoIGlzIG5vdCBjb3JyZWN0Iik7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGJwYykgfHwgYnBjIDwgMSkgewogICAgICAoMCwgX3V0aWwud2FybikoIkJpdHMgcGVyIGNvbXBvbmVudCBpcyBub3QgY29ycmVjdCIpOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBkZWNvZGVNYXBbMF0gPT09IDAgJiYgZGVjb2RlTWFwWzFdID09PSAoMSA8PCBicGMpIC0gMTsKICB9Cn0KY2xhc3MgRGV2aWNlR3JheUNTIGV4dGVuZHMgQ29sb3JTcGFjZSB7CiAgY29uc3RydWN0b3IoKSB7CiAgICBzdXBlcigiRGV2aWNlR3JheSIsIDEpOwogIH0KICBnZXRSZ2JJdGVtKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICBjb25zdCBjID0gc3JjW3NyY09mZnNldF0gKiAyNTU7CiAgICBkZXN0W2Rlc3RPZmZzZXRdID0gZGVzdFtkZXN0T2Zmc2V0ICsgMV0gPSBkZXN0W2Rlc3RPZmZzZXQgKyAyXSA9IGM7CiAgfQogIGdldFJnYkJ1ZmZlcihzcmMsIHNyY09mZnNldCwgY291bnQsIGRlc3QsIGRlc3RPZmZzZXQsIGJpdHMsIGFscGhhMDEpIHsKICAgIGNvbnN0IHNjYWxlID0gMjU1IC8gKCgxIDw8IGJpdHMpIC0gMSk7CiAgICBsZXQgaiA9IHNyY09mZnNldCwKICAgICAgcSA9IGRlc3RPZmZzZXQ7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyArK2kpIHsKICAgICAgY29uc3QgYyA9IHNjYWxlICogc3JjW2orK107CiAgICAgIGRlc3RbcSsrXSA9IGM7CiAgICAgIGRlc3RbcSsrXSA9IGM7CiAgICAgIGRlc3RbcSsrXSA9IGM7CiAgICAgIHEgKz0gYWxwaGEwMTsKICAgIH0KICB9CiAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICByZXR1cm4gaW5wdXRMZW5ndGggKiAoMyArIGFscGhhMDEpOwogIH0KfQpjbGFzcyBEZXZpY2VSZ2JDUyBleHRlbmRzIENvbG9yU3BhY2UgewogIGNvbnN0cnVjdG9yKCkgewogICAgc3VwZXIoIkRldmljZVJHQiIsIDMpOwogIH0KICBnZXRSZ2JJdGVtKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICBkZXN0W2Rlc3RPZmZzZXRdID0gc3JjW3NyY09mZnNldF0gKiAyNTU7CiAgICBkZXN0W2Rlc3RPZmZzZXQgKyAxXSA9IHNyY1tzcmNPZmZzZXQgKyAxXSAqIDI1NTsKICAgIGRlc3RbZGVzdE9mZnNldCArIDJdID0gc3JjW3NyY09mZnNldCArIDJdICogMjU1OwogIH0KICBnZXRSZ2JCdWZmZXIoc3JjLCBzcmNPZmZzZXQsIGNvdW50LCBkZXN0LCBkZXN0T2Zmc2V0LCBiaXRzLCBhbHBoYTAxKSB7CiAgICBpZiAoYml0cyA9PT0gOCAmJiBhbHBoYTAxID09PSAwKSB7CiAgICAgIGRlc3Quc2V0KHNyYy5zdWJhcnJheShzcmNPZmZzZXQsIHNyY09mZnNldCArIGNvdW50ICogMyksIGRlc3RPZmZzZXQpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBzY2FsZSA9IDI1NSAvICgoMSA8PCBiaXRzKSAtIDEpOwogICAgbGV0IGogPSBzcmNPZmZzZXQsCiAgICAgIHEgPSBkZXN0T2Zmc2V0OwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgKytpKSB7CiAgICAgIGRlc3RbcSsrXSA9IHNjYWxlICogc3JjW2orK107CiAgICAgIGRlc3RbcSsrXSA9IHNjYWxlICogc3JjW2orK107CiAgICAgIGRlc3RbcSsrXSA9IHNjYWxlICogc3JjW2orK107CiAgICAgIHEgKz0gYWxwaGEwMTsKICAgIH0KICB9CiAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICByZXR1cm4gaW5wdXRMZW5ndGggKiAoMyArIGFscGhhMDEpIC8gMyB8IDA7CiAgfQogIGlzUGFzc3Rocm91Z2goYml0cykgewogICAgcmV0dXJuIGJpdHMgPT09IDg7CiAgfQp9CmNvbnN0IERldmljZUNteWtDUyA9IGZ1bmN0aW9uIERldmljZUNteWtDU0Nsb3N1cmUoKSB7CiAgZnVuY3Rpb24gY29udmVydFRvUmdiKHNyYywgc3JjT2Zmc2V0LCBzcmNTY2FsZSwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgY29uc3QgYyA9IHNyY1tzcmNPZmZzZXRdICogc3JjU2NhbGU7CiAgICBjb25zdCBtID0gc3JjW3NyY09mZnNldCArIDFdICogc3JjU2NhbGU7CiAgICBjb25zdCB5ID0gc3JjW3NyY09mZnNldCArIDJdICogc3JjU2NhbGU7CiAgICBjb25zdCBrID0gc3JjW3NyY09mZnNldCArIDNdICogc3JjU2NhbGU7CiAgICBkZXN0W2Rlc3RPZmZzZXRdID0gMjU1ICsgYyAqICgtNC4zODczMzIzODQ2MDk5ODggKiBjICsgNTQuNDg2MTUxOTQxODkxNzYgKiBtICsgMTguODIyOTA1MDIxNjUzMDIgKiB5ICsgMjEyLjI1NjYyNDUxNjM5NTg1ICogayArIC0yODUuMjMzMTAyNjEzNzAwNCkgKyBtICogKDEuNzE0OTc2MzQ3NzM2MjEzNCAqIG0gLSA1LjYwOTY3MzY5MDQwNDczMTUgKiB5ICsgLTE3Ljg3Mzg3MDg2MTQxNTQ0NCAqIGsgLSA1LjQ5NzAwNjQyNzE5NjM2NikgKyB5ICogKC0yLjUyMTczNDAxMzE2ODMwMzMgKiB5IC0gMjEuMjQ4OTIzMzM3MzUzMDczICogayArIDE3LjUxMTkyNzA4NDE4MTMpICsgayAqICgtMjEuODYxMjIxNDc0NjM2MDUgKiBrIC0gMTg5LjQ4MTgwODM1OTIyNzQ3KTsKICAgIGRlc3RbZGVzdE9mZnNldCArIDFdID0gMjU1ICsgYyAqICg4Ljg0MTA0MTQyMjAzNjE0OSAqIGMgKyA2MC4xMTgwMjcwNDU1OTczNjYgKiBtICsgNi44NzE0MjU1OTIwNDkwMDcgKiB5ICsgMzEuMTU5MTAwMTMwMDU1OTIyICogayArIC03OS4yOTcwODQ0ODE2NTQ4KSArIG0gKiAoLTE1LjMxMDM2MTMwNjk2NzgxNyAqIG0gKyAxNy41NzUyNTEyNjExMDk0ODIgKiB5ICsgMTMxLjM1MjUwOTEyNDkzOTc2ICogayAtIDE5MC45NDUzMzAyNTg4OTUxKSArIHkgKiAoNC40NDQzMzkxMDI4NTI3MzkgKiB5ICsgOS44NjMyODYxNDkzNDA1ICogayAtIDI0Ljg2NzQxNTgyNTU1ODc4KSArIGsgKiAoLTIwLjczNzMyNTQ3MTE4MTAzNCAqIGsgLSAxODcuODA0NTM3MDk3MTk1NzgpOwogICAgZGVzdFtkZXN0T2Zmc2V0ICsgMl0gPSAyNTUgKyBjICogKDAuODg0MjUyMjQzMDAwMzI5NiAqIGMgKyA4LjA3ODY3NzUwMzExMjkyOCAqIG0gKyAzMC44OTk3ODMwOTcwMzcyOSAqIHkgLSAwLjIzODgzMjM4Njg5MTc4OTM0ICogayArIC0xNC4xODM1NzY3OTk2NzMyODYpICsgbSAqICgxMC40OTU5MzI3MzQzMjA3MiAqIG0gKyA2My4wMjM3ODQ5NDc1NDA1MiAqIHkgKyA1MC42MDY5NTc2NTYzNjA3MzQgKiBrIC0gMTEyLjIzODg0MjUzNzE5MjQ4KSArIHkgKiAoMC4wMzI5NjA0MTExNDg3MzIxNyAqIHkgKyAxMTUuNjAzODQ0NDk2NDY2NDEgKiBrICsgLTE5My41ODIwOTM1Njg2MTUwNSkgKyBrICogKC0yMi4zMzgxNjgwNzMwOTg4NiAqIGsgLSAxODAuMTI2MTM5NzQ3MDgzNjcpOwogIH0KICBjbGFzcyBEZXZpY2VDbXlrQ1MgZXh0ZW5kcyBDb2xvclNwYWNlIHsKICAgIGNvbnN0cnVjdG9yKCkgewogICAgICBzdXBlcigiRGV2aWNlQ01ZSyIsIDQpOwogICAgfQogICAgZ2V0UmdiSXRlbShzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgICBjb252ZXJ0VG9SZ2Ioc3JjLCBzcmNPZmZzZXQsIDEsIGRlc3QsIGRlc3RPZmZzZXQpOwogICAgfQogICAgZ2V0UmdiQnVmZmVyKHNyYywgc3JjT2Zmc2V0LCBjb3VudCwgZGVzdCwgZGVzdE9mZnNldCwgYml0cywgYWxwaGEwMSkgewogICAgICBjb25zdCBzY2FsZSA9IDEgLyAoKDEgPDwgYml0cykgLSAxKTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgICAgY29udmVydFRvUmdiKHNyYywgc3JjT2Zmc2V0LCBzY2FsZSwgZGVzdCwgZGVzdE9mZnNldCk7CiAgICAgICAgc3JjT2Zmc2V0ICs9IDQ7CiAgICAgICAgZGVzdE9mZnNldCArPSAzICsgYWxwaGEwMTsKICAgICAgfQogICAgfQogICAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICAgIHJldHVybiBpbnB1dExlbmd0aCAvIDQgKiAoMyArIGFscGhhMDEpIHwgMDsKICAgIH0KICB9CiAgcmV0dXJuIERldmljZUNteWtDUzsKfSgpOwpjb25zdCBDYWxHcmF5Q1MgPSBmdW5jdGlvbiBDYWxHcmF5Q1NDbG9zdXJlKCkgewogIGZ1bmN0aW9uIGNvbnZlcnRUb1JnYihjcywgc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQsIHNjYWxlKSB7CiAgICBjb25zdCBBID0gc3JjW3NyY09mZnNldF0gKiBzY2FsZTsKICAgIGNvbnN0IEFHID0gQSAqKiBjcy5HOwogICAgY29uc3QgTCA9IGNzLllXICogQUc7CiAgICBjb25zdCB2YWwgPSBNYXRoLm1heCgyOTUuOCAqIEwgKiogMC4zMzMzMzMzMzMzMzMzMzMzIC0gNDAuOCwgMCk7CiAgICBkZXN0W2Rlc3RPZmZzZXRdID0gdmFsOwogICAgZGVzdFtkZXN0T2Zmc2V0ICsgMV0gPSB2YWw7CiAgICBkZXN0W2Rlc3RPZmZzZXQgKyAyXSA9IHZhbDsKICB9CiAgY2xhc3MgQ2FsR3JheUNTIGV4dGVuZHMgQ29sb3JTcGFjZSB7CiAgICBjb25zdHJ1Y3Rvcih3aGl0ZVBvaW50LCBibGFja1BvaW50LCBnYW1tYSkgewogICAgICBzdXBlcigiQ2FsR3JheSIsIDEpOwogICAgICBpZiAoIXdoaXRlUG9pbnQpIHsKICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIldoaXRlUG9pbnQgbWlzc2luZyAtIHJlcXVpcmVkIGZvciBjb2xvciBzcGFjZSBDYWxHcmF5Iik7CiAgICAgIH0KICAgICAgYmxhY2tQb2ludCA9IGJsYWNrUG9pbnQgfHwgWzAsIDAsIDBdOwogICAgICBnYW1tYSA9IGdhbW1hIHx8IDE7CiAgICAgIHRoaXMuWFcgPSB3aGl0ZVBvaW50WzBdOwogICAgICB0aGlzLllXID0gd2hpdGVQb2ludFsxXTsKICAgICAgdGhpcy5aVyA9IHdoaXRlUG9pbnRbMl07CiAgICAgIHRoaXMuWEIgPSBibGFja1BvaW50WzBdOwogICAgICB0aGlzLllCID0gYmxhY2tQb2ludFsxXTsKICAgICAgdGhpcy5aQiA9IGJsYWNrUG9pbnRbMl07CiAgICAgIHRoaXMuRyA9IGdhbW1hOwogICAgICBpZiAodGhpcy5YVyA8IDAgfHwgdGhpcy5aVyA8IDAgfHwgdGhpcy5ZVyAhPT0gMSkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgSW52YWxpZCBXaGl0ZVBvaW50IGNvbXBvbmVudHMgZm9yICR7dGhpcy5uYW1lfWAgKyAiLCBubyBmYWxsYmFjayBhdmFpbGFibGUiKTsKICAgICAgfQogICAgICBpZiAodGhpcy5YQiA8IDAgfHwgdGhpcy5ZQiA8IDAgfHwgdGhpcy5aQiA8IDApIHsKICAgICAgICAoMCwgX3V0aWwuaW5mbykoYEludmFsaWQgQmxhY2tQb2ludCBmb3IgJHt0aGlzLm5hbWV9LCBmYWxsaW5nIGJhY2sgdG8gZGVmYXVsdC5gKTsKICAgICAgICB0aGlzLlhCID0gdGhpcy5ZQiA9IHRoaXMuWkIgPSAwOwogICAgICB9CiAgICAgIGlmICh0aGlzLlhCICE9PSAwIHx8IHRoaXMuWUIgIT09IDAgfHwgdGhpcy5aQiAhPT0gMCkgewogICAgICAgICgwLCBfdXRpbC53YXJuKShgJHt0aGlzLm5hbWV9LCBCbGFja1BvaW50OiBYQjogJHt0aGlzLlhCfSwgWUI6ICR7dGhpcy5ZQn0sIGAgKyBgWkI6ICR7dGhpcy5aQn0sIG9ubHkgZGVmYXVsdCB2YWx1ZXMgYXJlIHN1cHBvcnRlZC5gKTsKICAgICAgfQogICAgICBpZiAodGhpcy5HIDwgMSkgewogICAgICAgICgwLCBfdXRpbC5pbmZvKShgSW52YWxpZCBHYW1tYTogJHt0aGlzLkd9IGZvciAke3RoaXMubmFtZX0sIGAgKyAiZmFsbGluZyBiYWNrIHRvIGRlZmF1bHQuIik7CiAgICAgICAgdGhpcy5HID0gMTsKICAgICAgfQogICAgfQogICAgZ2V0UmdiSXRlbShzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgICBjb252ZXJ0VG9SZ2IodGhpcywgc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQsIDEpOwogICAgfQogICAgZ2V0UmdiQnVmZmVyKHNyYywgc3JjT2Zmc2V0LCBjb3VudCwgZGVzdCwgZGVzdE9mZnNldCwgYml0cywgYWxwaGEwMSkgewogICAgICBjb25zdCBzY2FsZSA9IDEgLyAoKDEgPDwgYml0cykgLSAxKTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgKytpKSB7CiAgICAgICAgY29udmVydFRvUmdiKHRoaXMsIHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0LCBzY2FsZSk7CiAgICAgICAgc3JjT2Zmc2V0ICs9IDE7CiAgICAgICAgZGVzdE9mZnNldCArPSAzICsgYWxwaGEwMTsKICAgICAgfQogICAgfQogICAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICAgIHJldHVybiBpbnB1dExlbmd0aCAqICgzICsgYWxwaGEwMSk7CiAgICB9CiAgfQogIHJldHVybiBDYWxHcmF5Q1M7Cn0oKTsKY29uc3QgQ2FsUkdCQ1MgPSBmdW5jdGlvbiBDYWxSR0JDU0Nsb3N1cmUoKSB7CiAgY29uc3QgQlJBREZPUkRfU0NBTEVfTUFUUklYID0gbmV3IEZsb2F0MzJBcnJheShbMC44OTUxLCAwLjI2NjQsIC0wLjE2MTQsIC0wLjc1MDIsIDEuNzEzNSwgMC4wMzY3LCAwLjAzODksIC0wLjA2ODUsIDEuMDI5Nl0pOwogIGNvbnN0IEJSQURGT1JEX1NDQUxFX0lOVkVSU0VfTUFUUklYID0gbmV3IEZsb2F0MzJBcnJheShbMC45ODY5OTI5LCAtMC4xNDcwNTQzLCAwLjE1OTk2MjcsIDAuNDMyMzA1MywgMC41MTgzNjAzLCAwLjA0OTI5MTIsIC0wLjAwODUyODcsIDAuMDQwMDQyOCwgMC45Njg0ODY3XSk7CiAgY29uc3QgU1JHQl9ENjVfWFlaX1RPX1JHQl9NQVRSSVggPSBuZXcgRmxvYXQzMkFycmF5KFszLjI0MDQ1NDIsIC0xLjUzNzEzODUsIC0wLjQ5ODUzMTQsIC0wLjk2OTI2NjAsIDEuODc2MDEwOCwgMC4wNDE1NTYwLCAwLjA1NTY0MzQsIC0wLjIwNDAyNTksIDEuMDU3MjI1Ml0pOwogIGNvbnN0IEZMQVRfV0hJVEVQT0lOVF9NQVRSSVggPSBuZXcgRmxvYXQzMkFycmF5KFsxLCAxLCAxXSk7CiAgY29uc3QgdGVtcE5vcm1hbGl6ZU1hdHJpeCA9IG5ldyBGbG9hdDMyQXJyYXkoMyk7CiAgY29uc3QgdGVtcENvbnZlcnRNYXRyaXgxID0gbmV3IEZsb2F0MzJBcnJheSgzKTsKICBjb25zdCB0ZW1wQ29udmVydE1hdHJpeDIgPSBuZXcgRmxvYXQzMkFycmF5KDMpOwogIGNvbnN0IERFQ09ERV9MX0NPTlNUQU5UID0gKCg4ICsgMTYpIC8gMTE2KSAqKiAzIC8gOC4wOwogIGZ1bmN0aW9uIG1hdHJpeFByb2R1Y3QoYSwgYiwgcmVzdWx0KSB7CiAgICByZXN1bHRbMF0gPSBhWzBdICogYlswXSArIGFbMV0gKiBiWzFdICsgYVsyXSAqIGJbMl07CiAgICByZXN1bHRbMV0gPSBhWzNdICogYlswXSArIGFbNF0gKiBiWzFdICsgYVs1XSAqIGJbMl07CiAgICByZXN1bHRbMl0gPSBhWzZdICogYlswXSArIGFbN10gKiBiWzFdICsgYVs4XSAqIGJbMl07CiAgfQogIGZ1bmN0aW9uIGNvbnZlcnRUb0ZsYXQoc291cmNlV2hpdGVQb2ludCwgTE1TLCByZXN1bHQpIHsKICAgIHJlc3VsdFswXSA9IExNU1swXSAqIDEgLyBzb3VyY2VXaGl0ZVBvaW50WzBdOwogICAgcmVzdWx0WzFdID0gTE1TWzFdICogMSAvIHNvdXJjZVdoaXRlUG9pbnRbMV07CiAgICByZXN1bHRbMl0gPSBMTVNbMl0gKiAxIC8gc291cmNlV2hpdGVQb2ludFsyXTsKICB9CiAgZnVuY3Rpb24gY29udmVydFRvRDY1KHNvdXJjZVdoaXRlUG9pbnQsIExNUywgcmVzdWx0KSB7CiAgICBjb25zdCBENjVYID0gMC45NTA0NzsKICAgIGNvbnN0IEQ2NVkgPSAxOwogICAgY29uc3QgRDY1WiA9IDEuMDg4ODM7CiAgICByZXN1bHRbMF0gPSBMTVNbMF0gKiBENjVYIC8gc291cmNlV2hpdGVQb2ludFswXTsKICAgIHJlc3VsdFsxXSA9IExNU1sxXSAqIEQ2NVkgLyBzb3VyY2VXaGl0ZVBvaW50WzFdOwogICAgcmVzdWx0WzJdID0gTE1TWzJdICogRDY1WiAvIHNvdXJjZVdoaXRlUG9pbnRbMl07CiAgfQogIGZ1bmN0aW9uIHNSR0JUcmFuc2ZlckZ1bmN0aW9uKGNvbG9yKSB7CiAgICBpZiAoY29sb3IgPD0gMC4wMDMxMzA4KSB7CiAgICAgIHJldHVybiBhZGp1c3RUb1JhbmdlKDAsIDEsIDEyLjkyICogY29sb3IpOwogICAgfQogICAgaWYgKGNvbG9yID49IDAuOTk1NTQ1MjUpIHsKICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICByZXR1cm4gYWRqdXN0VG9SYW5nZSgwLCAxLCAoMSArIDAuMDU1KSAqIGNvbG9yICoqICgxIC8gMi40KSAtIDAuMDU1KTsKICB9CiAgZnVuY3Rpb24gYWRqdXN0VG9SYW5nZShtaW4sIG1heCwgdmFsdWUpIHsKICAgIHJldHVybiBNYXRoLm1heChtaW4sIE1hdGgubWluKG1heCwgdmFsdWUpKTsKICB9CiAgZnVuY3Rpb24gZGVjb2RlTChMKSB7CiAgICBpZiAoTCA8IDApIHsKICAgICAgcmV0dXJuIC1kZWNvZGVMKC1MKTsKICAgIH0KICAgIGlmIChMID4gOC4wKSB7CiAgICAgIHJldHVybiAoKEwgKyAxNikgLyAxMTYpICoqIDM7CiAgICB9CiAgICByZXR1cm4gTCAqIERFQ09ERV9MX0NPTlNUQU5UOwogIH0KICBmdW5jdGlvbiBjb21wZW5zYXRlQmxhY2tQb2ludChzb3VyY2VCbGFja1BvaW50LCBYWVpfRmxhdCwgcmVzdWx0KSB7CiAgICBpZiAoc291cmNlQmxhY2tQb2ludFswXSA9PT0gMCAmJiBzb3VyY2VCbGFja1BvaW50WzFdID09PSAwICYmIHNvdXJjZUJsYWNrUG9pbnRbMl0gPT09IDApIHsKICAgICAgcmVzdWx0WzBdID0gWFlaX0ZsYXRbMF07CiAgICAgIHJlc3VsdFsxXSA9IFhZWl9GbGF0WzFdOwogICAgICByZXN1bHRbMl0gPSBYWVpfRmxhdFsyXTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgemVyb0RlY29kZUwgPSBkZWNvZGVMKDApOwogICAgY29uc3QgWF9EU1QgPSB6ZXJvRGVjb2RlTDsKICAgIGNvbnN0IFhfU1JDID0gZGVjb2RlTChzb3VyY2VCbGFja1BvaW50WzBdKTsKICAgIGNvbnN0IFlfRFNUID0gemVyb0RlY29kZUw7CiAgICBjb25zdCBZX1NSQyA9IGRlY29kZUwoc291cmNlQmxhY2tQb2ludFsxXSk7CiAgICBjb25zdCBaX0RTVCA9IHplcm9EZWNvZGVMOwogICAgY29uc3QgWl9TUkMgPSBkZWNvZGVMKHNvdXJjZUJsYWNrUG9pbnRbMl0pOwogICAgY29uc3QgWF9TY2FsZSA9ICgxIC0gWF9EU1QpIC8gKDEgLSBYX1NSQyk7CiAgICBjb25zdCBYX09mZnNldCA9IDEgLSBYX1NjYWxlOwogICAgY29uc3QgWV9TY2FsZSA9ICgxIC0gWV9EU1QpIC8gKDEgLSBZX1NSQyk7CiAgICBjb25zdCBZX09mZnNldCA9IDEgLSBZX1NjYWxlOwogICAgY29uc3QgWl9TY2FsZSA9ICgxIC0gWl9EU1QpIC8gKDEgLSBaX1NSQyk7CiAgICBjb25zdCBaX09mZnNldCA9IDEgLSBaX1NjYWxlOwogICAgcmVzdWx0WzBdID0gWFlaX0ZsYXRbMF0gKiBYX1NjYWxlICsgWF9PZmZzZXQ7CiAgICByZXN1bHRbMV0gPSBYWVpfRmxhdFsxXSAqIFlfU2NhbGUgKyBZX09mZnNldDsKICAgIHJlc3VsdFsyXSA9IFhZWl9GbGF0WzJdICogWl9TY2FsZSArIFpfT2Zmc2V0OwogIH0KICBmdW5jdGlvbiBub3JtYWxpemVXaGl0ZVBvaW50VG9GbGF0KHNvdXJjZVdoaXRlUG9pbnQsIFhZWl9JbiwgcmVzdWx0KSB7CiAgICBpZiAoc291cmNlV2hpdGVQb2ludFswXSA9PT0gMSAmJiBzb3VyY2VXaGl0ZVBvaW50WzJdID09PSAxKSB7CiAgICAgIHJlc3VsdFswXSA9IFhZWl9JblswXTsKICAgICAgcmVzdWx0WzFdID0gWFlaX0luWzFdOwogICAgICByZXN1bHRbMl0gPSBYWVpfSW5bMl07CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IExNUyA9IHJlc3VsdDsKICAgIG1hdHJpeFByb2R1Y3QoQlJBREZPUkRfU0NBTEVfTUFUUklYLCBYWVpfSW4sIExNUyk7CiAgICBjb25zdCBMTVNfRmxhdCA9IHRlbXBOb3JtYWxpemVNYXRyaXg7CiAgICBjb252ZXJ0VG9GbGF0KHNvdXJjZVdoaXRlUG9pbnQsIExNUywgTE1TX0ZsYXQpOwogICAgbWF0cml4UHJvZHVjdChCUkFERk9SRF9TQ0FMRV9JTlZFUlNFX01BVFJJWCwgTE1TX0ZsYXQsIHJlc3VsdCk7CiAgfQogIGZ1bmN0aW9uIG5vcm1hbGl6ZVdoaXRlUG9pbnRUb0Q2NShzb3VyY2VXaGl0ZVBvaW50LCBYWVpfSW4sIHJlc3VsdCkgewogICAgY29uc3QgTE1TID0gcmVzdWx0OwogICAgbWF0cml4UHJvZHVjdChCUkFERk9SRF9TQ0FMRV9NQVRSSVgsIFhZWl9JbiwgTE1TKTsKICAgIGNvbnN0IExNU19ENjUgPSB0ZW1wTm9ybWFsaXplTWF0cml4OwogICAgY29udmVydFRvRDY1KHNvdXJjZVdoaXRlUG9pbnQsIExNUywgTE1TX0Q2NSk7CiAgICBtYXRyaXhQcm9kdWN0KEJSQURGT1JEX1NDQUxFX0lOVkVSU0VfTUFUUklYLCBMTVNfRDY1LCByZXN1bHQpOwogIH0KICBmdW5jdGlvbiBjb252ZXJ0VG9SZ2IoY3MsIHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0LCBzY2FsZSkgewogICAgY29uc3QgQSA9IGFkanVzdFRvUmFuZ2UoMCwgMSwgc3JjW3NyY09mZnNldF0gKiBzY2FsZSk7CiAgICBjb25zdCBCID0gYWRqdXN0VG9SYW5nZSgwLCAxLCBzcmNbc3JjT2Zmc2V0ICsgMV0gKiBzY2FsZSk7CiAgICBjb25zdCBDID0gYWRqdXN0VG9SYW5nZSgwLCAxLCBzcmNbc3JjT2Zmc2V0ICsgMl0gKiBzY2FsZSk7CiAgICBjb25zdCBBR1IgPSBBID09PSAxID8gMSA6IEEgKiogY3MuR1I7CiAgICBjb25zdCBCR0cgPSBCID09PSAxID8gMSA6IEIgKiogY3MuR0c7CiAgICBjb25zdCBDR0IgPSBDID09PSAxID8gMSA6IEMgKiogY3MuR0I7CiAgICBjb25zdCBYID0gY3MuTVhBICogQUdSICsgY3MuTVhCICogQkdHICsgY3MuTVhDICogQ0dCOwogICAgY29uc3QgWSA9IGNzLk1ZQSAqIEFHUiArIGNzLk1ZQiAqIEJHRyArIGNzLk1ZQyAqIENHQjsKICAgIGNvbnN0IFogPSBjcy5NWkEgKiBBR1IgKyBjcy5NWkIgKiBCR0cgKyBjcy5NWkMgKiBDR0I7CiAgICBjb25zdCBYWVogPSB0ZW1wQ29udmVydE1hdHJpeDE7CiAgICBYWVpbMF0gPSBYOwogICAgWFlaWzFdID0gWTsKICAgIFhZWlsyXSA9IFo7CiAgICBjb25zdCBYWVpfRmxhdCA9IHRlbXBDb252ZXJ0TWF0cml4MjsKICAgIG5vcm1hbGl6ZVdoaXRlUG9pbnRUb0ZsYXQoY3Mud2hpdGVQb2ludCwgWFlaLCBYWVpfRmxhdCk7CiAgICBjb25zdCBYWVpfQmxhY2sgPSB0ZW1wQ29udmVydE1hdHJpeDE7CiAgICBjb21wZW5zYXRlQmxhY2tQb2ludChjcy5ibGFja1BvaW50LCBYWVpfRmxhdCwgWFlaX0JsYWNrKTsKICAgIGNvbnN0IFhZWl9ENjUgPSB0ZW1wQ29udmVydE1hdHJpeDI7CiAgICBub3JtYWxpemVXaGl0ZVBvaW50VG9ENjUoRkxBVF9XSElURVBPSU5UX01BVFJJWCwgWFlaX0JsYWNrLCBYWVpfRDY1KTsKICAgIGNvbnN0IFNSR0IgPSB0ZW1wQ29udmVydE1hdHJpeDE7CiAgICBtYXRyaXhQcm9kdWN0KFNSR0JfRDY1X1hZWl9UT19SR0JfTUFUUklYLCBYWVpfRDY1LCBTUkdCKTsKICAgIGRlc3RbZGVzdE9mZnNldF0gPSBzUkdCVHJhbnNmZXJGdW5jdGlvbihTUkdCWzBdKSAqIDI1NTsKICAgIGRlc3RbZGVzdE9mZnNldCArIDFdID0gc1JHQlRyYW5zZmVyRnVuY3Rpb24oU1JHQlsxXSkgKiAyNTU7CiAgICBkZXN0W2Rlc3RPZmZzZXQgKyAyXSA9IHNSR0JUcmFuc2ZlckZ1bmN0aW9uKFNSR0JbMl0pICogMjU1OwogIH0KICBjbGFzcyBDYWxSR0JDUyBleHRlbmRzIENvbG9yU3BhY2UgewogICAgY29uc3RydWN0b3Iod2hpdGVQb2ludCwgYmxhY2tQb2ludCwgZ2FtbWEsIG1hdHJpeCkgewogICAgICBzdXBlcigiQ2FsUkdCIiwgMyk7CiAgICAgIGlmICghd2hpdGVQb2ludCkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiV2hpdGVQb2ludCBtaXNzaW5nIC0gcmVxdWlyZWQgZm9yIGNvbG9yIHNwYWNlIENhbFJHQiIpOwogICAgICB9CiAgICAgIGJsYWNrUG9pbnQgPSBibGFja1BvaW50IHx8IG5ldyBGbG9hdDMyQXJyYXkoMyk7CiAgICAgIGdhbW1hID0gZ2FtbWEgfHwgbmV3IEZsb2F0MzJBcnJheShbMSwgMSwgMV0pOwogICAgICBtYXRyaXggPSBtYXRyaXggfHwgbmV3IEZsb2F0MzJBcnJheShbMSwgMCwgMCwgMCwgMSwgMCwgMCwgMCwgMV0pOwogICAgICBjb25zdCBYVyA9IHdoaXRlUG9pbnRbMF07CiAgICAgIGNvbnN0IFlXID0gd2hpdGVQb2ludFsxXTsKICAgICAgY29uc3QgWlcgPSB3aGl0ZVBvaW50WzJdOwogICAgICB0aGlzLndoaXRlUG9pbnQgPSB3aGl0ZVBvaW50OwogICAgICBjb25zdCBYQiA9IGJsYWNrUG9pbnRbMF07CiAgICAgIGNvbnN0IFlCID0gYmxhY2tQb2ludFsxXTsKICAgICAgY29uc3QgWkIgPSBibGFja1BvaW50WzJdOwogICAgICB0aGlzLmJsYWNrUG9pbnQgPSBibGFja1BvaW50OwogICAgICB0aGlzLkdSID0gZ2FtbWFbMF07CiAgICAgIHRoaXMuR0cgPSBnYW1tYVsxXTsKICAgICAgdGhpcy5HQiA9IGdhbW1hWzJdOwogICAgICB0aGlzLk1YQSA9IG1hdHJpeFswXTsKICAgICAgdGhpcy5NWUEgPSBtYXRyaXhbMV07CiAgICAgIHRoaXMuTVpBID0gbWF0cml4WzJdOwogICAgICB0aGlzLk1YQiA9IG1hdHJpeFszXTsKICAgICAgdGhpcy5NWUIgPSBtYXRyaXhbNF07CiAgICAgIHRoaXMuTVpCID0gbWF0cml4WzVdOwogICAgICB0aGlzLk1YQyA9IG1hdHJpeFs2XTsKICAgICAgdGhpcy5NWUMgPSBtYXRyaXhbN107CiAgICAgIHRoaXMuTVpDID0gbWF0cml4WzhdOwogICAgICBpZiAoWFcgPCAwIHx8IFpXIDwgMCB8fCBZVyAhPT0gMSkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgSW52YWxpZCBXaGl0ZVBvaW50IGNvbXBvbmVudHMgZm9yICR7dGhpcy5uYW1lfWAgKyAiLCBubyBmYWxsYmFjayBhdmFpbGFibGUiKTsKICAgICAgfQogICAgICBpZiAoWEIgPCAwIHx8IFlCIDwgMCB8fCBaQiA8IDApIHsKICAgICAgICAoMCwgX3V0aWwuaW5mbykoYEludmFsaWQgQmxhY2tQb2ludCBmb3IgJHt0aGlzLm5hbWV9IFske1hCfSwgJHtZQn0sICR7WkJ9XSwgYCArICJmYWxsaW5nIGJhY2sgdG8gZGVmYXVsdC4iKTsKICAgICAgICB0aGlzLmJsYWNrUG9pbnQgPSBuZXcgRmxvYXQzMkFycmF5KDMpOwogICAgICB9CiAgICAgIGlmICh0aGlzLkdSIDwgMCB8fCB0aGlzLkdHIDwgMCB8fCB0aGlzLkdCIDwgMCkgewogICAgICAgICgwLCBfdXRpbC5pbmZvKShgSW52YWxpZCBHYW1tYSBbJHt0aGlzLkdSfSwgJHt0aGlzLkdHfSwgJHt0aGlzLkdCfV0gZm9yIGAgKyBgJHt0aGlzLm5hbWV9LCBmYWxsaW5nIGJhY2sgdG8gZGVmYXVsdC5gKTsKICAgICAgICB0aGlzLkdSID0gdGhpcy5HRyA9IHRoaXMuR0IgPSAxOwogICAgICB9CiAgICB9CiAgICBnZXRSZ2JJdGVtKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICAgIGNvbnZlcnRUb1JnYih0aGlzLCBzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCwgMSk7CiAgICB9CiAgICBnZXRSZ2JCdWZmZXIoc3JjLCBzcmNPZmZzZXQsIGNvdW50LCBkZXN0LCBkZXN0T2Zmc2V0LCBiaXRzLCBhbHBoYTAxKSB7CiAgICAgIGNvbnN0IHNjYWxlID0gMSAvICgoMSA8PCBiaXRzKSAtIDEpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyArK2kpIHsKICAgICAgICBjb252ZXJ0VG9SZ2IodGhpcywgc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQsIHNjYWxlKTsKICAgICAgICBzcmNPZmZzZXQgKz0gMzsKICAgICAgICBkZXN0T2Zmc2V0ICs9IDMgKyBhbHBoYTAxOwogICAgICB9CiAgICB9CiAgICBnZXRPdXRwdXRMZW5ndGgoaW5wdXRMZW5ndGgsIGFscGhhMDEpIHsKICAgICAgcmV0dXJuIGlucHV0TGVuZ3RoICogKDMgKyBhbHBoYTAxKSAvIDMgfCAwOwogICAgfQogIH0KICByZXR1cm4gQ2FsUkdCQ1M7Cn0oKTsKY29uc3QgTGFiQ1MgPSBmdW5jdGlvbiBMYWJDU0Nsb3N1cmUoKSB7CiAgZnVuY3Rpb24gZm5fZyh4KSB7CiAgICBsZXQgcmVzdWx0OwogICAgaWYgKHggPj0gNiAvIDI5KSB7CiAgICAgIHJlc3VsdCA9IHggKiogMzsKICAgIH0gZWxzZSB7CiAgICAgIHJlc3VsdCA9IDEwOCAvIDg0MSAqICh4IC0gNCAvIDI5KTsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQogIGZ1bmN0aW9uIGRlY29kZSh2YWx1ZSwgaGlnaDEsIGxvdzIsIGhpZ2gyKSB7CiAgICByZXR1cm4gbG93MiArIHZhbHVlICogKGhpZ2gyIC0gbG93MikgLyBoaWdoMTsKICB9CiAgZnVuY3Rpb24gY29udmVydFRvUmdiKGNzLCBzcmMsIHNyY09mZnNldCwgbWF4VmFsLCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICBsZXQgTHMgPSBzcmNbc3JjT2Zmc2V0XTsKICAgIGxldCBhcyA9IHNyY1tzcmNPZmZzZXQgKyAxXTsKICAgIGxldCBicyA9IHNyY1tzcmNPZmZzZXQgKyAyXTsKICAgIGlmIChtYXhWYWwgIT09IGZhbHNlKSB7CiAgICAgIExzID0gZGVjb2RlKExzLCBtYXhWYWwsIDAsIDEwMCk7CiAgICAgIGFzID0gZGVjb2RlKGFzLCBtYXhWYWwsIGNzLmFtaW4sIGNzLmFtYXgpOwogICAgICBicyA9IGRlY29kZShicywgbWF4VmFsLCBjcy5ibWluLCBjcy5ibWF4KTsKICAgIH0KICAgIGlmIChhcyA+IGNzLmFtYXgpIHsKICAgICAgYXMgPSBjcy5hbWF4OwogICAgfSBlbHNlIGlmIChhcyA8IGNzLmFtaW4pIHsKICAgICAgYXMgPSBjcy5hbWluOwogICAgfQogICAgaWYgKGJzID4gY3MuYm1heCkgewogICAgICBicyA9IGNzLmJtYXg7CiAgICB9IGVsc2UgaWYgKGJzIDwgY3MuYm1pbikgewogICAgICBicyA9IGNzLmJtaW47CiAgICB9CiAgICBjb25zdCBNID0gKExzICsgMTYpIC8gMTE2OwogICAgY29uc3QgTCA9IE0gKyBhcyAvIDUwMDsKICAgIGNvbnN0IE4gPSBNIC0gYnMgLyAyMDA7CiAgICBjb25zdCBYID0gY3MuWFcgKiBmbl9nKEwpOwogICAgY29uc3QgWSA9IGNzLllXICogZm5fZyhNKTsKICAgIGNvbnN0IFogPSBjcy5aVyAqIGZuX2coTik7CiAgICBsZXQgciwgZywgYjsKICAgIGlmIChjcy5aVyA8IDEpIHsKICAgICAgciA9IFggKiAzLjEzMzkgKyBZICogLTEuNjE3ICsgWiAqIC0wLjQ5MDY7CiAgICAgIGcgPSBYICogLTAuOTc4NSArIFkgKiAxLjkxNiArIFogKiAwLjAzMzM7CiAgICAgIGIgPSBYICogMC4wNzIgKyBZICogLTAuMjI5ICsgWiAqIDEuNDA1NzsKICAgIH0gZWxzZSB7CiAgICAgIHIgPSBYICogMy4yNDA2ICsgWSAqIC0xLjUzNzIgKyBaICogLTAuNDk4NjsKICAgICAgZyA9IFggKiAtMC45Njg5ICsgWSAqIDEuODc1OCArIFogKiAwLjA0MTU7CiAgICAgIGIgPSBYICogMC4wNTU3ICsgWSAqIC0wLjIwNCArIFogKiAxLjA1NzsKICAgIH0KICAgIGRlc3RbZGVzdE9mZnNldF0gPSBNYXRoLnNxcnQocikgKiAyNTU7CiAgICBkZXN0W2Rlc3RPZmZzZXQgKyAxXSA9IE1hdGguc3FydChnKSAqIDI1NTsKICAgIGRlc3RbZGVzdE9mZnNldCArIDJdID0gTWF0aC5zcXJ0KGIpICogMjU1OwogIH0KICBjbGFzcyBMYWJDUyBleHRlbmRzIENvbG9yU3BhY2UgewogICAgY29uc3RydWN0b3Iod2hpdGVQb2ludCwgYmxhY2tQb2ludCwgcmFuZ2UpIHsKICAgICAgc3VwZXIoIkxhYiIsIDMpOwogICAgICBpZiAoIXdoaXRlUG9pbnQpIHsKICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIldoaXRlUG9pbnQgbWlzc2luZyAtIHJlcXVpcmVkIGZvciBjb2xvciBzcGFjZSBMYWIiKTsKICAgICAgfQogICAgICBibGFja1BvaW50ID0gYmxhY2tQb2ludCB8fCBbMCwgMCwgMF07CiAgICAgIHJhbmdlID0gcmFuZ2UgfHwgWy0xMDAsIDEwMCwgLTEwMCwgMTAwXTsKICAgICAgdGhpcy5YVyA9IHdoaXRlUG9pbnRbMF07CiAgICAgIHRoaXMuWVcgPSB3aGl0ZVBvaW50WzFdOwogICAgICB0aGlzLlpXID0gd2hpdGVQb2ludFsyXTsKICAgICAgdGhpcy5hbWluID0gcmFuZ2VbMF07CiAgICAgIHRoaXMuYW1heCA9IHJhbmdlWzFdOwogICAgICB0aGlzLmJtaW4gPSByYW5nZVsyXTsKICAgICAgdGhpcy5ibWF4ID0gcmFuZ2VbM107CiAgICAgIHRoaXMuWEIgPSBibGFja1BvaW50WzBdOwogICAgICB0aGlzLllCID0gYmxhY2tQb2ludFsxXTsKICAgICAgdGhpcy5aQiA9IGJsYWNrUG9pbnRbMl07CiAgICAgIGlmICh0aGlzLlhXIDwgMCB8fCB0aGlzLlpXIDwgMCB8fCB0aGlzLllXICE9PSAxKSB7CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJJbnZhbGlkIFdoaXRlUG9pbnQgY29tcG9uZW50cywgbm8gZmFsbGJhY2sgYXZhaWxhYmxlIik7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuWEIgPCAwIHx8IHRoaXMuWUIgPCAwIHx8IHRoaXMuWkIgPCAwKSB7CiAgICAgICAgKDAsIF91dGlsLmluZm8pKCJJbnZhbGlkIEJsYWNrUG9pbnQsIGZhbGxpbmcgYmFjayB0byBkZWZhdWx0Iik7CiAgICAgICAgdGhpcy5YQiA9IHRoaXMuWUIgPSB0aGlzLlpCID0gMDsKICAgICAgfQogICAgICBpZiAodGhpcy5hbWluID4gdGhpcy5hbWF4IHx8IHRoaXMuYm1pbiA+IHRoaXMuYm1heCkgewogICAgICAgICgwLCBfdXRpbC5pbmZvKSgiSW52YWxpZCBSYW5nZSwgZmFsbGluZyBiYWNrIHRvIGRlZmF1bHRzIik7CiAgICAgICAgdGhpcy5hbWluID0gLTEwMDsKICAgICAgICB0aGlzLmFtYXggPSAxMDA7CiAgICAgICAgdGhpcy5ibWluID0gLTEwMDsKICAgICAgICB0aGlzLmJtYXggPSAxMDA7CiAgICAgIH0KICAgIH0KICAgIGdldFJnYkl0ZW0oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgICAgY29udmVydFRvUmdiKHRoaXMsIHNyYywgc3JjT2Zmc2V0LCBmYWxzZSwgZGVzdCwgZGVzdE9mZnNldCk7CiAgICB9CiAgICBnZXRSZ2JCdWZmZXIoc3JjLCBzcmNPZmZzZXQsIGNvdW50LCBkZXN0LCBkZXN0T2Zmc2V0LCBiaXRzLCBhbHBoYTAxKSB7CiAgICAgIGNvbnN0IG1heFZhbCA9ICgxIDw8IGJpdHMpIC0gMTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgICAgY29udmVydFRvUmdiKHRoaXMsIHNyYywgc3JjT2Zmc2V0LCBtYXhWYWwsIGRlc3QsIGRlc3RPZmZzZXQpOwogICAgICAgIHNyY09mZnNldCArPSAzOwogICAgICAgIGRlc3RPZmZzZXQgKz0gMyArIGFscGhhMDE7CiAgICAgIH0KICAgIH0KICAgIGdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aCwgYWxwaGEwMSkgewogICAgICByZXR1cm4gaW5wdXRMZW5ndGggKiAoMyArIGFscGhhMDEpIC8gMyB8IDA7CiAgICB9CiAgICBpc0RlZmF1bHREZWNvZGUoZGVjb2RlTWFwLCBicGMpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBnZXQgdXNlc1plcm9Ub09uZVJhbmdlKCkgewogICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInVzZXNaZXJvVG9PbmVSYW5nZSIsIGZhbHNlKTsKICAgIH0KICB9CiAgcmV0dXJuIExhYkNTOwp9KCk7CgovKioqLyB9KSwKLyogMTQ5ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5QYXJ0aWFsRXZhbHVhdG9yID0gZXhwb3J0cy5FdmFsdWF0b3JQcmVwcm9jZXNzb3IgPSB2b2lkIDA7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CnZhciBfY21hcCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTUwKTsKdmFyIF9wcmltaXRpdmVzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDApOwp2YXIgX2ZvbnRzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNjkpOwp2YXIgX2VuY29kaW5ncyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTcyKTsKdmFyIF9zdGFuZGFyZF9mb250cyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTc2KTsKdmFyIF9wYXR0ZXJuID0gX193X3BkZmpzX3JlcXVpcmVfXygxODUpOwp2YXIgX3hmYV9mb250cyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTg2KTsKdmFyIF90b191bmljb2RlX21hcCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTc3KTsKdmFyIF9mdW5jdGlvbiA9IF9fd19wZGZqc19yZXF1aXJlX18oMTkyKTsKdmFyIF9wYXJzZXIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1MSk7CnZhciBfaW1hZ2VfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE5NCk7CnZhciBfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDQpOwp2YXIgX2Jhc2Vfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDEpOwp2YXIgX2JpZGkgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE5NSk7CnZhciBfY29sb3JzcGFjZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQ4KTsKdmFyIF9kZWNvZGVfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTMpOwp2YXIgX2ZvbnRzX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNzMpOwp2YXIgX2dseXBobGlzdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTc0KTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX21ldHJpY3MgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE4MCk7CnZhciBfdW5pY29kZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTc1KTsKdmFyIF9pbWFnZV9yZXNpemVyID0gX193X3BkZmpzX3JlcXVpcmVfXygxOTYpOwp2YXIgX211cm11cmhhc2ggPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE5Nyk7CnZhciBfb3BlcmF0b3JfbGlzdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTk4KTsKdmFyIF9pbWFnZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTk5KTsKY29uc3QgRGVmYXVsdFBhcnRpYWxFdmFsdWF0b3JPcHRpb25zID0gT2JqZWN0LmZyZWV6ZSh7CiAgbWF4SW1hZ2VTaXplOiAtMSwKICBkaXNhYmxlRm9udEZhY2U6IGZhbHNlLAogIGlnbm9yZUVycm9yczogZmFsc2UsCiAgaXNFdmFsU3VwcG9ydGVkOiB0cnVlLAogIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkOiBmYWxzZSwKICBjYW52YXNNYXhBcmVhSW5CeXRlczogLTEsCiAgZm9udEV4dHJhUHJvcGVydGllczogZmFsc2UsCiAgdXNlU3lzdGVtRm9udHM6IHRydWUsCiAgY01hcFVybDogbnVsbCwKICBzdGFuZGFyZEZvbnREYXRhVXJsOiBudWxsCn0pOwpjb25zdCBQYXR0ZXJuVHlwZSA9IHsKICBUSUxJTkc6IDEsCiAgU0hBRElORzogMgp9Owpjb25zdCBURVhUX0NIVU5LX0JBVENIX1NJWkUgPSAxMDsKY29uc3QgZGVmZXJyZWQgPSBQcm9taXNlLnJlc29sdmUoKTsKZnVuY3Rpb24gbm9ybWFsaXplQmxlbmRNb2RlKHZhbHVlKSB7CiAgbGV0IHBhcnNpbmdBcnJheSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogZmFsc2U7CiAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7CiAgICBmb3IgKGNvbnN0IHZhbCBvZiB2YWx1ZSkgewogICAgICBjb25zdCBtYXliZUJNID0gbm9ybWFsaXplQmxlbmRNb2RlKHZhbCwgdHJ1ZSk7CiAgICAgIGlmIChtYXliZUJNKSB7CiAgICAgICAgcmV0dXJuIG1heWJlQk07CiAgICAgIH0KICAgIH0KICAgICgwLCBfdXRpbC53YXJuKShgVW5zdXBwb3J0ZWQgYmxlbmQgbW9kZSBBcnJheTogJHt2YWx1ZX1gKTsKICAgIHJldHVybiAic291cmNlLW92ZXIiOwogIH0KICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpKSB7CiAgICBpZiAocGFyc2luZ0FycmF5KSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgcmV0dXJuICJzb3VyY2Utb3ZlciI7CiAgfQogIHN3aXRjaCAodmFsdWUubmFtZSkgewogICAgY2FzZSAiTm9ybWFsIjoKICAgIGNhc2UgIkNvbXBhdGlibGUiOgogICAgICByZXR1cm4gInNvdXJjZS1vdmVyIjsKICAgIGNhc2UgIk11bHRpcGx5IjoKICAgICAgcmV0dXJuICJtdWx0aXBseSI7CiAgICBjYXNlICJTY3JlZW4iOgogICAgICByZXR1cm4gInNjcmVlbiI7CiAgICBjYXNlICJPdmVybGF5IjoKICAgICAgcmV0dXJuICJvdmVybGF5IjsKICAgIGNhc2UgIkRhcmtlbiI6CiAgICAgIHJldHVybiAiZGFya2VuIjsKICAgIGNhc2UgIkxpZ2h0ZW4iOgogICAgICByZXR1cm4gImxpZ2h0ZW4iOwogICAgY2FzZSAiQ29sb3JEb2RnZSI6CiAgICAgIHJldHVybiAiY29sb3ItZG9kZ2UiOwogICAgY2FzZSAiQ29sb3JCdXJuIjoKICAgICAgcmV0dXJuICJjb2xvci1idXJuIjsKICAgIGNhc2UgIkhhcmRMaWdodCI6CiAgICAgIHJldHVybiAiaGFyZC1saWdodCI7CiAgICBjYXNlICJTb2Z0TGlnaHQiOgogICAgICByZXR1cm4gInNvZnQtbGlnaHQiOwogICAgY2FzZSAiRGlmZmVyZW5jZSI6CiAgICAgIHJldHVybiAiZGlmZmVyZW5jZSI7CiAgICBjYXNlICJFeGNsdXNpb24iOgogICAgICByZXR1cm4gImV4Y2x1c2lvbiI7CiAgICBjYXNlICJIdWUiOgogICAgICByZXR1cm4gImh1ZSI7CiAgICBjYXNlICJTYXR1cmF0aW9uIjoKICAgICAgcmV0dXJuICJzYXR1cmF0aW9uIjsKICAgIGNhc2UgIkNvbG9yIjoKICAgICAgcmV0dXJuICJjb2xvciI7CiAgICBjYXNlICJMdW1pbm9zaXR5IjoKICAgICAgcmV0dXJuICJsdW1pbm9zaXR5IjsKICB9CiAgaWYgKHBhcnNpbmdBcnJheSkgewogICAgcmV0dXJuIG51bGw7CiAgfQogICgwLCBfdXRpbC53YXJuKShgVW5zdXBwb3J0ZWQgYmxlbmQgbW9kZTogJHt2YWx1ZS5uYW1lfWApOwogIHJldHVybiAic291cmNlLW92ZXIiOwp9CmZ1bmN0aW9uIGluY3JlbWVudENhY2hlZEltYWdlTWFza0NvdW50KGRhdGEpIHsKICBpZiAoZGF0YS5mbiA9PT0gX3V0aWwuT1BTLnBhaW50SW1hZ2VNYXNrWE9iamVjdCAmJiBkYXRhLmFyZ3NbMF0gJiYgZGF0YS5hcmdzWzBdLmNvdW50ID4gMCkgewogICAgZGF0YS5hcmdzWzBdLmNvdW50Kys7CiAgfQp9CmNsYXNzIFRpbWVTbG90TWFuYWdlciB7CiAgc3RhdGljIGdldCBUSU1FX1NMT1RfRFVSQVRJT05fTVMoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIlRJTUVfU0xPVF9EVVJBVElPTl9NUyIsIDIwKTsKICB9CiAgc3RhdGljIGdldCBDSEVDS19USU1FX0VWRVJZKCkgewogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJDSEVDS19USU1FX0VWRVJZIiwgMTAwKTsKICB9CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLnJlc2V0KCk7CiAgfQogIGNoZWNrKCkgewogICAgaWYgKCsrdGhpcy5jaGVja2VkIDwgVGltZVNsb3RNYW5hZ2VyLkNIRUNLX1RJTUVfRVZFUlkpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgdGhpcy5jaGVja2VkID0gMDsKICAgIHJldHVybiB0aGlzLmVuZFRpbWUgPD0gRGF0ZS5ub3coKTsKICB9CiAgcmVzZXQoKSB7CiAgICB0aGlzLmVuZFRpbWUgPSBEYXRlLm5vdygpICsgVGltZVNsb3RNYW5hZ2VyLlRJTUVfU0xPVF9EVVJBVElPTl9NUzsKICAgIHRoaXMuY2hlY2tlZCA9IDA7CiAgfQp9CmNsYXNzIFBhcnRpYWxFdmFsdWF0b3IgewogIGNvbnN0cnVjdG9yKF9yZWYpIHsKICAgIGxldCB7CiAgICAgIHhyZWYsCiAgICAgIGhhbmRsZXIsCiAgICAgIHBhZ2VJbmRleCwKICAgICAgaWRGYWN0b3J5LAogICAgICBmb250Q2FjaGUsCiAgICAgIGJ1aWx0SW5DTWFwQ2FjaGUsCiAgICAgIHN0YW5kYXJkRm9udERhdGFDYWNoZSwKICAgICAgZ2xvYmFsSW1hZ2VDYWNoZSwKICAgICAgb3B0aW9ucyA9IG51bGwKICAgIH0gPSBfcmVmOwogICAgdGhpcy54cmVmID0geHJlZjsKICAgIHRoaXMuaGFuZGxlciA9IGhhbmRsZXI7CiAgICB0aGlzLnBhZ2VJbmRleCA9IHBhZ2VJbmRleDsKICAgIHRoaXMuaWRGYWN0b3J5ID0gaWRGYWN0b3J5OwogICAgdGhpcy5mb250Q2FjaGUgPSBmb250Q2FjaGU7CiAgICB0aGlzLmJ1aWx0SW5DTWFwQ2FjaGUgPSBidWlsdEluQ01hcENhY2hlOwogICAgdGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUgPSBzdGFuZGFyZEZvbnREYXRhQ2FjaGU7CiAgICB0aGlzLmdsb2JhbEltYWdlQ2FjaGUgPSBnbG9iYWxJbWFnZUNhY2hlOwogICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucyB8fCBEZWZhdWx0UGFydGlhbEV2YWx1YXRvck9wdGlvbnM7CiAgICB0aGlzLnBhcnNpbmdUeXBlM0ZvbnQgPSBmYWxzZTsKICAgIHRoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZCA9IHRoaXMuZmV0Y2hCdWlsdEluQ01hcC5iaW5kKHRoaXMpOwogICAgX2ltYWdlX3Jlc2l6ZXIuSW1hZ2VSZXNpemVyLnNldE1heEFyZWEodGhpcy5vcHRpb25zLmNhbnZhc01heEFyZWFJbkJ5dGVzKTsKICB9CiAgZ2V0IF9wZGZGdW5jdGlvbkZhY3RvcnkoKSB7CiAgICBjb25zdCBwZGZGdW5jdGlvbkZhY3RvcnkgPSBuZXcgX2Z1bmN0aW9uLlBERkZ1bmN0aW9uRmFjdG9yeSh7CiAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgaXNFdmFsU3VwcG9ydGVkOiB0aGlzLm9wdGlvbnMuaXNFdmFsU3VwcG9ydGVkCiAgICB9KTsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiX3BkZkZ1bmN0aW9uRmFjdG9yeSIsIHBkZkZ1bmN0aW9uRmFjdG9yeSk7CiAgfQogIGNsb25lKCkgewogICAgbGV0IG5ld09wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IG51bGw7CiAgICBjb25zdCBuZXdFdmFsdWF0b3IgPSBPYmplY3QuY3JlYXRlKHRoaXMpOwogICAgbmV3RXZhbHVhdG9yLm9wdGlvbnMgPSBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobnVsbCksIHRoaXMub3B0aW9ucywgbmV3T3B0aW9ucyk7CiAgICByZXR1cm4gbmV3RXZhbHVhdG9yOwogIH0KICBoYXNCbGVuZE1vZGVzKHJlc291cmNlcywgbm9uQmxlbmRNb2Rlc1NldCkgewogICAgaWYgKCEocmVzb3VyY2VzIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKHJlc291cmNlcy5vYmpJZCAmJiBub25CbGVuZE1vZGVzU2V0LmhhcyhyZXNvdXJjZXMub2JqSWQpKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGNvbnN0IHByb2Nlc3NlZCA9IG5ldyBfcHJpbWl0aXZlcy5SZWZTZXQobm9uQmxlbmRNb2Rlc1NldCk7CiAgICBpZiAocmVzb3VyY2VzLm9iaklkKSB7CiAgICAgIHByb2Nlc3NlZC5wdXQocmVzb3VyY2VzLm9iaklkKTsKICAgIH0KICAgIGNvbnN0IG5vZGVzID0gW3Jlc291cmNlc10sCiAgICAgIHhyZWYgPSB0aGlzLnhyZWY7CiAgICB3aGlsZSAobm9kZXMubGVuZ3RoKSB7CiAgICAgIGNvbnN0IG5vZGUgPSBub2Rlcy5zaGlmdCgpOwogICAgICBjb25zdCBncmFwaGljU3RhdGVzID0gbm9kZS5nZXQoIkV4dEdTdGF0ZSIpOwogICAgICBpZiAoZ3JhcGhpY1N0YXRlcyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpIHsKICAgICAgICBmb3IgKGxldCBncmFwaGljU3RhdGUgb2YgZ3JhcGhpY1N0YXRlcy5nZXRSYXdWYWx1ZXMoKSkgewogICAgICAgICAgaWYgKGdyYXBoaWNTdGF0ZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgICAgICBpZiAocHJvY2Vzc2VkLmhhcyhncmFwaGljU3RhdGUpKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICBncmFwaGljU3RhdGUgPSB4cmVmLmZldGNoKGdyYXBoaWNTdGF0ZSk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICAgICAgcHJvY2Vzc2VkLnB1dChncmFwaGljU3RhdGUpOwogICAgICAgICAgICAgICgwLCBfdXRpbC5pbmZvKShgaGFzQmxlbmRNb2RlcyAtIGlnbm9yaW5nIEV4dEdTdGF0ZTogIiR7ZXh9Ii5gKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKCEoZ3JhcGhpY1N0YXRlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZ3JhcGhpY1N0YXRlLm9iaklkKSB7CiAgICAgICAgICAgIHByb2Nlc3NlZC5wdXQoZ3JhcGhpY1N0YXRlLm9iaklkKTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGJtID0gZ3JhcGhpY1N0YXRlLmdldCgiQk0iKTsKICAgICAgICAgIGlmIChibSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgICAgICAgaWYgKGJtLm5hbWUgIT09ICJOb3JtYWwiKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoYm0gIT09IHVuZGVmaW5lZCAmJiBBcnJheS5pc0FycmF5KGJtKSkgewogICAgICAgICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgYm0pIHsKICAgICAgICAgICAgICBpZiAoZWxlbWVudCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUgJiYgZWxlbWVudC5uYW1lICE9PSAiTm9ybWFsIikgewogICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGNvbnN0IHhPYmplY3RzID0gbm9kZS5nZXQoIlhPYmplY3QiKTsKICAgICAgaWYgKCEoeE9iamVjdHMgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGZvciAobGV0IHhPYmplY3Qgb2YgeE9iamVjdHMuZ2V0UmF3VmFsdWVzKCkpIHsKICAgICAgICBpZiAoeE9iamVjdCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgICAgaWYgKHByb2Nlc3NlZC5oYXMoeE9iamVjdCkpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICB0cnkgewogICAgICAgICAgICB4T2JqZWN0ID0geHJlZi5mZXRjaCh4T2JqZWN0KTsKICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICAgIHByb2Nlc3NlZC5wdXQoeE9iamVjdCk7CiAgICAgICAgICAgICgwLCBfdXRpbC5pbmZvKShgaGFzQmxlbmRNb2RlcyAtIGlnbm9yaW5nIFhPYmplY3Q6ICIke2V4fSIuYCk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoISh4T2JqZWN0IGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0pKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaWYgKHhPYmplY3QuZGljdC5vYmpJZCkgewogICAgICAgICAgcHJvY2Vzc2VkLnB1dCh4T2JqZWN0LmRpY3Qub2JqSWQpOwogICAgICAgIH0KICAgICAgICBjb25zdCB4UmVzb3VyY2VzID0geE9iamVjdC5kaWN0LmdldCgiUmVzb3VyY2VzIik7CiAgICAgICAgaWYgKCEoeFJlc291cmNlcyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaWYgKHhSZXNvdXJjZXMub2JqSWQgJiYgcHJvY2Vzc2VkLmhhcyh4UmVzb3VyY2VzLm9iaklkKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIG5vZGVzLnB1c2goeFJlc291cmNlcyk7CiAgICAgICAgaWYgKHhSZXNvdXJjZXMub2JqSWQpIHsKICAgICAgICAgIHByb2Nlc3NlZC5wdXQoeFJlc291cmNlcy5vYmpJZCk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IHJlZiBvZiBwcm9jZXNzZWQpIHsKICAgICAgbm9uQmxlbmRNb2Rlc1NldC5wdXQocmVmKTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9CiAgYXN5bmMgZmV0Y2hCdWlsdEluQ01hcChuYW1lKSB7CiAgICBjb25zdCBjYWNoZWREYXRhID0gdGhpcy5idWlsdEluQ01hcENhY2hlLmdldChuYW1lKTsKICAgIGlmIChjYWNoZWREYXRhKSB7CiAgICAgIHJldHVybiBjYWNoZWREYXRhOwogICAgfQogICAgbGV0IGRhdGE7CiAgICBpZiAodGhpcy5vcHRpb25zLmNNYXBVcmwgIT09IG51bGwpIHsKICAgICAgY29uc3QgdXJsID0gYCR7dGhpcy5vcHRpb25zLmNNYXBVcmx9JHtuYW1lfS5iY21hcGA7CiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsKTsKICAgICAgaWYgKCFyZXNwb25zZS5vaykgewogICAgICAgIHRocm93IG5ldyBFcnJvcihgZmV0Y2hCdWlsdEluQ01hcDogZmFpbGVkIHRvIGZldGNoIGZpbGUgIiR7dXJsfSIgd2l0aCAiJHtyZXNwb25zZS5zdGF0dXNUZXh0fSIuYCk7CiAgICAgIH0KICAgICAgZGF0YSA9IHsKICAgICAgICBjTWFwRGF0YTogbmV3IFVpbnQ4QXJyYXkoYXdhaXQgcmVzcG9uc2UuYXJyYXlCdWZmZXIoKSksCiAgICAgICAgY29tcHJlc3Npb25UeXBlOiBfdXRpbC5DTWFwQ29tcHJlc3Npb25UeXBlLkJJTkFSWQogICAgICB9OwogICAgfSBlbHNlIHsKICAgICAgZGF0YSA9IGF3YWl0IHRoaXMuaGFuZGxlci5zZW5kV2l0aFByb21pc2UoIkZldGNoQnVpbHRJbkNNYXAiLCB7CiAgICAgICAgbmFtZQogICAgICB9KTsKICAgIH0KICAgIGlmIChkYXRhLmNvbXByZXNzaW9uVHlwZSAhPT0gX3V0aWwuQ01hcENvbXByZXNzaW9uVHlwZS5OT05FKSB7CiAgICAgIHRoaXMuYnVpbHRJbkNNYXBDYWNoZS5zZXQobmFtZSwgZGF0YSk7CiAgICB9CiAgICByZXR1cm4gZGF0YTsKICB9CiAgYXN5bmMgZmV0Y2hTdGFuZGFyZEZvbnREYXRhKG5hbWUpIHsKICAgIGNvbnN0IGNhY2hlZERhdGEgPSB0aGlzLnN0YW5kYXJkRm9udERhdGFDYWNoZS5nZXQobmFtZSk7CiAgICBpZiAoY2FjaGVkRGF0YSkgewogICAgICByZXR1cm4gbmV3IF9zdHJlYW0uU3RyZWFtKGNhY2hlZERhdGEpOwogICAgfQogICAgaWYgKHRoaXMub3B0aW9ucy51c2VTeXN0ZW1Gb250cyAmJiBuYW1lICE9PSAiU3ltYm9sIiAmJiBuYW1lICE9PSAiWmFwZkRpbmdiYXRzIikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHN0YW5kYXJkRm9udE5hbWVUb0ZpbGVOYW1lID0gKDAsIF9zdGFuZGFyZF9mb250cy5nZXRGb250TmFtZVRvRmlsZU1hcCkoKSwKICAgICAgZmlsZW5hbWUgPSBzdGFuZGFyZEZvbnROYW1lVG9GaWxlTmFtZVtuYW1lXTsKICAgIGxldCBkYXRhOwogICAgaWYgKHRoaXMub3B0aW9ucy5zdGFuZGFyZEZvbnREYXRhVXJsICE9PSBudWxsKSB7CiAgICAgIGNvbnN0IHVybCA9IGAke3RoaXMub3B0aW9ucy5zdGFuZGFyZEZvbnREYXRhVXJsfSR7ZmlsZW5hbWV9YDsKICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh1cmwpOwogICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKGBmZXRjaFN0YW5kYXJkRm9udERhdGE6IGZhaWxlZCB0byBmZXRjaCBmaWxlICIke3VybH0iIHdpdGggIiR7cmVzcG9uc2Uuc3RhdHVzVGV4dH0iLmApOwogICAgICB9IGVsc2UgewogICAgICAgIGRhdGEgPSBhd2FpdCByZXNwb25zZS5hcnJheUJ1ZmZlcigpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0cnkgewogICAgICAgIGRhdGEgPSBhd2FpdCB0aGlzLmhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJGZXRjaFN0YW5kYXJkRm9udERhdGEiLCB7CiAgICAgICAgICBmaWxlbmFtZQogICAgICAgIH0pOwogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKGBmZXRjaFN0YW5kYXJkRm9udERhdGE6IGZhaWxlZCB0byBmZXRjaCBmaWxlICIke2ZpbGVuYW1lfSIgd2l0aCAiJHtlfSIuYCk7CiAgICAgIH0KICAgIH0KICAgIGlmICghZGF0YSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIHRoaXMuc3RhbmRhcmRGb250RGF0YUNhY2hlLnNldChuYW1lLCBkYXRhKTsKICAgIHJldHVybiBuZXcgX3N0cmVhbS5TdHJlYW0oZGF0YSk7CiAgfQogIGFzeW5jIGJ1aWxkRm9ybVhPYmplY3QocmVzb3VyY2VzLCB4b2JqLCBzbWFzaywgb3BlcmF0b3JMaXN0LCB0YXNrLCBpbml0aWFsU3RhdGUsIGxvY2FsQ29sb3JTcGFjZUNhY2hlKSB7CiAgICBjb25zdCBkaWN0ID0geG9iai5kaWN0OwogICAgY29uc3QgbWF0cml4ID0gZGljdC5nZXRBcnJheSgiTWF0cml4Iik7CiAgICBsZXQgYmJveCA9IGRpY3QuZ2V0QXJyYXkoIkJCb3giKTsKICAgIGlmIChBcnJheS5pc0FycmF5KGJib3gpICYmIGJib3gubGVuZ3RoID09PSA0KSB7CiAgICAgIGJib3ggPSBfdXRpbC5VdGlsLm5vcm1hbGl6ZVJlY3QoYmJveCk7CiAgICB9IGVsc2UgewogICAgICBiYm94ID0gbnVsbDsKICAgIH0KICAgIGxldCBvcHRpb25hbENvbnRlbnQsIGdyb3VwT3B0aW9uczsKICAgIGlmIChkaWN0LmhhcygiT0MiKSkgewogICAgICBvcHRpb25hbENvbnRlbnQgPSBhd2FpdCB0aGlzLnBhcnNlTWFya2VkQ29udGVudFByb3BzKGRpY3QuZ2V0KCJPQyIpLCByZXNvdXJjZXMpOwogICAgfQogICAgaWYgKG9wdGlvbmFsQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChfdXRpbC5PUFMuYmVnaW5NYXJrZWRDb250ZW50UHJvcHMsIFsiT0MiLCBvcHRpb25hbENvbnRlbnRdKTsKICAgIH0KICAgIGNvbnN0IGdyb3VwID0gZGljdC5nZXQoIkdyb3VwIik7CiAgICBpZiAoZ3JvdXApIHsKICAgICAgZ3JvdXBPcHRpb25zID0gewogICAgICAgIG1hdHJpeCwKICAgICAgICBiYm94LAogICAgICAgIHNtYXNrLAogICAgICAgIGlzb2xhdGVkOiBmYWxzZSwKICAgICAgICBrbm9ja291dDogZmFsc2UKICAgICAgfTsKICAgICAgY29uc3QgZ3JvdXBTdWJ0eXBlID0gZ3JvdXAuZ2V0KCJTIik7CiAgICAgIGxldCBjb2xvclNwYWNlID0gbnVsbDsKICAgICAgaWYgKCgwLCBfcHJpbWl0aXZlcy5pc05hbWUpKGdyb3VwU3VidHlwZSwgIlRyYW5zcGFyZW5jeSIpKSB7CiAgICAgICAgZ3JvdXBPcHRpb25zLmlzb2xhdGVkID0gZ3JvdXAuZ2V0KCJJIikgfHwgZmFsc2U7CiAgICAgICAgZ3JvdXBPcHRpb25zLmtub2Nrb3V0ID0gZ3JvdXAuZ2V0KCJLIikgfHwgZmFsc2U7CiAgICAgICAgaWYgKGdyb3VwLmhhcygiQ1MiKSkgewogICAgICAgICAgY29uc3QgY3MgPSBncm91cC5nZXRSYXcoIkNTIik7CiAgICAgICAgICBjb25zdCBjYWNoZWRDb2xvclNwYWNlID0gX2NvbG9yc3BhY2UuQ29sb3JTcGFjZS5nZXRDYWNoZWQoY3MsIHRoaXMueHJlZiwgbG9jYWxDb2xvclNwYWNlQ2FjaGUpOwogICAgICAgICAgaWYgKGNhY2hlZENvbG9yU3BhY2UpIHsKICAgICAgICAgICAgY29sb3JTcGFjZSA9IGNhY2hlZENvbG9yU3BhY2U7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBjb2xvclNwYWNlID0gYXdhaXQgdGhpcy5wYXJzZUNvbG9yU3BhY2UoewogICAgICAgICAgICAgIGNzLAogICAgICAgICAgICAgIHJlc291cmNlcywKICAgICAgICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKHNtYXNrICYmIHNtYXNrLmJhY2tkcm9wKSB7CiAgICAgICAgY29sb3JTcGFjZSA9IGNvbG9yU3BhY2UgfHwgX2NvbG9yc3BhY2UuQ29sb3JTcGFjZS5zaW5nbGV0b25zLnJnYjsKICAgICAgICBzbWFzay5iYWNrZHJvcCA9IGNvbG9yU3BhY2UuZ2V0UmdiKHNtYXNrLmJhY2tkcm9wLCAwKTsKICAgICAgfQogICAgICBvcGVyYXRvckxpc3QuYWRkT3AoX3V0aWwuT1BTLmJlZ2luR3JvdXAsIFtncm91cE9wdGlvbnNdKTsKICAgIH0KICAgIGNvbnN0IGFyZ3MgPSBncm91cCA/IFttYXRyaXgsIG51bGxdIDogW21hdHJpeCwgYmJveF07CiAgICBvcGVyYXRvckxpc3QuYWRkT3AoX3V0aWwuT1BTLnBhaW50Rm9ybVhPYmplY3RCZWdpbiwgYXJncyk7CiAgICByZXR1cm4gdGhpcy5nZXRPcGVyYXRvckxpc3QoewogICAgICBzdHJlYW06IHhvYmosCiAgICAgIHRhc2ssCiAgICAgIHJlc291cmNlczogZGljdC5nZXQoIlJlc291cmNlcyIpIHx8IHJlc291cmNlcywKICAgICAgb3BlcmF0b3JMaXN0LAogICAgICBpbml0aWFsU3RhdGUKICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICBvcGVyYXRvckxpc3QuYWRkT3AoX3V0aWwuT1BTLnBhaW50Rm9ybVhPYmplY3RFbmQsIFtdKTsKICAgICAgaWYgKGdyb3VwKSB7CiAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKF91dGlsLk9QUy5lbmRHcm91cCwgW2dyb3VwT3B0aW9uc10pOwogICAgICB9CiAgICAgIGlmIChvcHRpb25hbENvbnRlbnQgIT09IHVuZGVmaW5lZCkgewogICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChfdXRpbC5PUFMuZW5kTWFya2VkQ29udGVudCwgW10pOwogICAgICB9CiAgICB9KTsKICB9CiAgX3NlbmRJbWdEYXRhKG9iaklkLCBpbWdEYXRhKSB7CiAgICBsZXQgY2FjaGVHbG9iYWxseSA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogZmFsc2U7CiAgICBjb25zdCB0cmFuc2ZlcnMgPSBpbWdEYXRhID8gW2ltZ0RhdGEuYml0bWFwIHx8IGltZ0RhdGEuZGF0YS5idWZmZXJdIDogbnVsbDsKICAgIGlmICh0aGlzLnBhcnNpbmdUeXBlM0ZvbnQgfHwgY2FjaGVHbG9iYWxseSkgewogICAgICByZXR1cm4gdGhpcy5oYW5kbGVyLnNlbmQoImNvbW1vbm9iaiIsIFtvYmpJZCwgIkltYWdlIiwgaW1nRGF0YV0sIHRyYW5zZmVycyk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5oYW5kbGVyLnNlbmQoIm9iaiIsIFtvYmpJZCwgdGhpcy5wYWdlSW5kZXgsICJJbWFnZSIsIGltZ0RhdGFdLCB0cmFuc2ZlcnMpOwogIH0KICBhc3luYyBidWlsZFBhaW50SW1hZ2VYT2JqZWN0KF9yZWYyKSB7CiAgICBsZXQgewogICAgICByZXNvdXJjZXMsCiAgICAgIGltYWdlLAogICAgICBpc0lubGluZSA9IGZhbHNlLAogICAgICBvcGVyYXRvckxpc3QsCiAgICAgIGNhY2hlS2V5LAogICAgICBsb2NhbEltYWdlQ2FjaGUsCiAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgICB9ID0gX3JlZjI7CiAgICBjb25zdCBkaWN0ID0gaW1hZ2UuZGljdDsKICAgIGNvbnN0IGltYWdlUmVmID0gZGljdC5vYmpJZDsKICAgIGNvbnN0IHcgPSBkaWN0LmdldCgiVyIsICJXaWR0aCIpOwogICAgY29uc3QgaCA9IGRpY3QuZ2V0KCJIIiwgIkhlaWdodCIpOwogICAgaWYgKCEodyAmJiB0eXBlb2YgdyA9PT0gIm51bWJlciIpIHx8ICEoaCAmJiB0eXBlb2YgaCA9PT0gIm51bWJlciIpKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKSgiSW1hZ2UgZGltZW5zaW9ucyBhcmUgbWlzc2luZywgb3Igbm90IG51bWJlcnMuIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG1heEltYWdlU2l6ZSA9IHRoaXMub3B0aW9ucy5tYXhJbWFnZVNpemU7CiAgICBpZiAobWF4SW1hZ2VTaXplICE9PSAtMSAmJiB3ICogaCA+IG1heEltYWdlU2l6ZSkgewogICAgICBjb25zdCBtc2cgPSAiSW1hZ2UgZXhjZWVkZWQgbWF4aW11bSBhbGxvd2VkIHNpemUgYW5kIHdhcyByZW1vdmVkLiI7CiAgICAgIGlmICh0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKG1zZyk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpOwogICAgfQogICAgbGV0IG9wdGlvbmFsQ29udGVudDsKICAgIGlmIChkaWN0LmhhcygiT0MiKSkgewogICAgICBvcHRpb25hbENvbnRlbnQgPSBhd2FpdCB0aGlzLnBhcnNlTWFya2VkQ29udGVudFByb3BzKGRpY3QuZ2V0KCJPQyIpLCByZXNvdXJjZXMpOwogICAgfQogICAgY29uc3QgaW1hZ2VNYXNrID0gZGljdC5nZXQoIklNIiwgIkltYWdlTWFzayIpIHx8IGZhbHNlOwogICAgbGV0IGltZ0RhdGEsIGFyZ3M7CiAgICBpZiAoaW1hZ2VNYXNrKSB7CiAgICAgIGNvbnN0IGludGVycG9sYXRlID0gZGljdC5nZXQoIkkiLCAiSW50ZXJwb2xhdGUiKTsKICAgICAgY29uc3QgYml0U3RyaWRlTGVuZ3RoID0gdyArIDcgPj4gMzsKICAgICAgY29uc3QgaW1nQXJyYXkgPSBpbWFnZS5nZXRCeXRlcyhiaXRTdHJpZGVMZW5ndGggKiBoKTsKICAgICAgY29uc3QgZGVjb2RlID0gZGljdC5nZXRBcnJheSgiRCIsICJEZWNvZGUiKTsKICAgICAgaWYgKHRoaXMucGFyc2luZ1R5cGUzRm9udCkgewogICAgICAgIGltZ0RhdGEgPSBfaW1hZ2UuUERGSW1hZ2UuY3JlYXRlUmF3TWFzayh7CiAgICAgICAgICBpbWdBcnJheSwKICAgICAgICAgIHdpZHRoOiB3LAogICAgICAgICAgaGVpZ2h0OiBoLAogICAgICAgICAgaW1hZ2VJc0Zyb21EZWNvZGVTdHJlYW06IGltYWdlIGluc3RhbmNlb2YgX2RlY29kZV9zdHJlYW0uRGVjb2RlU3RyZWFtLAogICAgICAgICAgaW52ZXJzZURlY29kZTogISFkZWNvZGUgJiYgZGVjb2RlWzBdID4gMCwKICAgICAgICAgIGludGVycG9sYXRlCiAgICAgICAgfSk7CiAgICAgICAgaW1nRGF0YS5jYWNoZWQgPSAhIWNhY2hlS2V5OwogICAgICAgIGFyZ3MgPSBbaW1nRGF0YV07CiAgICAgICAgb3BlcmF0b3JMaXN0LmFkZEltYWdlT3BzKF91dGlsLk9QUy5wYWludEltYWdlTWFza1hPYmplY3QsIGFyZ3MsIG9wdGlvbmFsQ29udGVudCk7CiAgICAgICAgaWYgKGNhY2hlS2V5KSB7CiAgICAgICAgICBsb2NhbEltYWdlQ2FjaGUuc2V0KGNhY2hlS2V5LCBpbWFnZVJlZiwgewogICAgICAgICAgICBmbjogX3V0aWwuT1BTLnBhaW50SW1hZ2VNYXNrWE9iamVjdCwKICAgICAgICAgICAgYXJncywKICAgICAgICAgICAgb3B0aW9uYWxDb250ZW50CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGltZ0RhdGEgPSBhd2FpdCBfaW1hZ2UuUERGSW1hZ2UuY3JlYXRlTWFzayh7CiAgICAgICAgaW1nQXJyYXksCiAgICAgICAgd2lkdGg6IHcsCiAgICAgICAgaGVpZ2h0OiBoLAogICAgICAgIGltYWdlSXNGcm9tRGVjb2RlU3RyZWFtOiBpbWFnZSBpbnN0YW5jZW9mIF9kZWNvZGVfc3RyZWFtLkRlY29kZVN0cmVhbSwKICAgICAgICBpbnZlcnNlRGVjb2RlOiAhIWRlY29kZSAmJiBkZWNvZGVbMF0gPiAwLAogICAgICAgIGludGVycG9sYXRlLAogICAgICAgIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkOiB0aGlzLm9wdGlvbnMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQKICAgICAgfSk7CiAgICAgIGlmIChpbWdEYXRhLmlzU2luZ2xlT3BhcXVlUGl4ZWwpIHsKICAgICAgICBvcGVyYXRvckxpc3QuYWRkSW1hZ2VPcHMoX3V0aWwuT1BTLnBhaW50U29saWRDb2xvckltYWdlTWFzaywgW10sIG9wdGlvbmFsQ29udGVudCk7CiAgICAgICAgaWYgKGNhY2hlS2V5KSB7CiAgICAgICAgICBsb2NhbEltYWdlQ2FjaGUuc2V0KGNhY2hlS2V5LCBpbWFnZVJlZiwgewogICAgICAgICAgICBmbjogX3V0aWwuT1BTLnBhaW50U29saWRDb2xvckltYWdlTWFzaywKICAgICAgICAgICAgYXJnczogW10sCiAgICAgICAgICAgIG9wdGlvbmFsQ29udGVudAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBjb25zdCBvYmpJZCA9IGBtYXNrXyR7dGhpcy5pZEZhY3RvcnkuY3JlYXRlT2JqSWQoKX1gOwogICAgICBvcGVyYXRvckxpc3QuYWRkRGVwZW5kZW5jeShvYmpJZCk7CiAgICAgIHRoaXMuX3NlbmRJbWdEYXRhKG9iaklkLCBpbWdEYXRhKTsKICAgICAgYXJncyA9IFt7CiAgICAgICAgZGF0YTogb2JqSWQsCiAgICAgICAgd2lkdGg6IGltZ0RhdGEud2lkdGgsCiAgICAgICAgaGVpZ2h0OiBpbWdEYXRhLmhlaWdodCwKICAgICAgICBpbnRlcnBvbGF0ZTogaW1nRGF0YS5pbnRlcnBvbGF0ZSwKICAgICAgICBjb3VudDogMQogICAgICB9XTsKICAgICAgb3BlcmF0b3JMaXN0LmFkZEltYWdlT3BzKF91dGlsLk9QUy5wYWludEltYWdlTWFza1hPYmplY3QsIGFyZ3MsIG9wdGlvbmFsQ29udGVudCk7CiAgICAgIGlmIChjYWNoZUtleSkgewogICAgICAgIGxvY2FsSW1hZ2VDYWNoZS5zZXQoY2FjaGVLZXksIGltYWdlUmVmLCB7CiAgICAgICAgICBmbjogX3V0aWwuT1BTLnBhaW50SW1hZ2VNYXNrWE9iamVjdCwKICAgICAgICAgIGFyZ3MsCiAgICAgICAgICBvcHRpb25hbENvbnRlbnQKICAgICAgICB9KTsKICAgICAgfQogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBzb2Z0TWFzayA9IGRpY3QuZ2V0KCJTTSIsICJTTWFzayIpIHx8IGZhbHNlOwogICAgY29uc3QgbWFzayA9IGRpY3QuZ2V0KCJNYXNrIikgfHwgZmFsc2U7CiAgICBjb25zdCBTTUFMTF9JTUFHRV9ESU1FTlNJT05TID0gMjAwOwogICAgaWYgKGlzSW5saW5lICYmICFzb2Z0TWFzayAmJiAhbWFzayAmJiB3ICsgaCA8IFNNQUxMX0lNQUdFX0RJTUVOU0lPTlMpIHsKICAgICAgY29uc3QgaW1hZ2VPYmogPSBuZXcgX2ltYWdlLlBERkltYWdlKHsKICAgICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgICAgcmVzOiByZXNvdXJjZXMsCiAgICAgICAgaW1hZ2UsCiAgICAgICAgaXNJbmxpbmUsCiAgICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5OiB0aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgICAgfSk7CiAgICAgIGltZ0RhdGEgPSBhd2FpdCBpbWFnZU9iai5jcmVhdGVJbWFnZURhdGEodHJ1ZSwgZmFsc2UpOwogICAgICBvcGVyYXRvckxpc3QuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgPSB0aGlzLm9wdGlvbnMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQ7CiAgICAgIG9wZXJhdG9yTGlzdC5hZGRJbWFnZU9wcyhfdXRpbC5PUFMucGFpbnRJbmxpbmVJbWFnZVhPYmplY3QsIFtpbWdEYXRhXSwgb3B0aW9uYWxDb250ZW50KTsKICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IG9iaklkID0gYGltZ18ke3RoaXMuaWRGYWN0b3J5LmNyZWF0ZU9iaklkKCl9YCwKICAgICAgY2FjaGVHbG9iYWxseSA9IGZhbHNlOwogICAgaWYgKHRoaXMucGFyc2luZ1R5cGUzRm9udCkgewogICAgICBvYmpJZCA9IGAke3RoaXMuaWRGYWN0b3J5LmdldERvY0lkKCl9X3R5cGUzXyR7b2JqSWR9YDsKICAgIH0gZWxzZSBpZiAoaW1hZ2VSZWYpIHsKICAgICAgY2FjaGVHbG9iYWxseSA9IHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZS5zaG91bGRDYWNoZShpbWFnZVJlZiwgdGhpcy5wYWdlSW5kZXgpOwogICAgICBpZiAoY2FjaGVHbG9iYWxseSkgewogICAgICAgIG9iaklkID0gYCR7dGhpcy5pZEZhY3RvcnkuZ2V0RG9jSWQoKX1fJHtvYmpJZH1gOwogICAgICB9CiAgICB9CiAgICBvcGVyYXRvckxpc3QuYWRkRGVwZW5kZW5jeShvYmpJZCk7CiAgICBhcmdzID0gW29iaklkLCB3LCBoXTsKICAgIF9pbWFnZS5QREZJbWFnZS5idWlsZEltYWdlKHsKICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICByZXM6IHJlc291cmNlcywKICAgICAgaW1hZ2UsCiAgICAgIGlzSW5saW5lLAogICAgICBwZGZGdW5jdGlvbkZhY3Rvcnk6IHRoaXMuX3BkZkZ1bmN0aW9uRmFjdG9yeSwKICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgIH0pLnRoZW4oYXN5bmMgaW1hZ2VPYmogPT4gewogICAgICBpbWdEYXRhID0gYXdhaXQgaW1hZ2VPYmouY3JlYXRlSW1hZ2VEYXRhKGZhbHNlLCB0aGlzLm9wdGlvbnMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpOwogICAgICBpZiAoY2FjaGVLZXkgJiYgaW1hZ2VSZWYgJiYgY2FjaGVHbG9iYWxseSkgewogICAgICAgIGxldCBsZW5ndGggPSAwOwogICAgICAgIGlmIChpbWdEYXRhLmJpdG1hcCkgewogICAgICAgICAgbGVuZ3RoID0gaW1nRGF0YS53aWR0aCAqIGltZ0RhdGEuaGVpZ2h0ICogNDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbGVuZ3RoID0gaW1nRGF0YS5kYXRhLmxlbmd0aDsKICAgICAgICB9CiAgICAgICAgdGhpcy5nbG9iYWxJbWFnZUNhY2hlLmFkZEJ5dGVTaXplKGltYWdlUmVmLCBsZW5ndGgpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLl9zZW5kSW1nRGF0YShvYmpJZCwgaW1nRGF0YSwgY2FjaGVHbG9iYWxseSk7CiAgICB9KS5jYXRjaChyZWFzb24gPT4gewogICAgICAoMCwgX3V0aWwud2FybikoYFVuYWJsZSB0byBkZWNvZGUgaW1hZ2UgIiR7b2JqSWR9IjogIiR7cmVhc29ufSIuYCk7CiAgICAgIHJldHVybiB0aGlzLl9zZW5kSW1nRGF0YShvYmpJZCwgbnVsbCwgY2FjaGVHbG9iYWxseSk7CiAgICB9KTsKICAgIG9wZXJhdG9yTGlzdC5hZGRJbWFnZU9wcyhfdXRpbC5PUFMucGFpbnRJbWFnZVhPYmplY3QsIGFyZ3MsIG9wdGlvbmFsQ29udGVudCk7CiAgICBpZiAoY2FjaGVLZXkpIHsKICAgICAgbG9jYWxJbWFnZUNhY2hlLnNldChjYWNoZUtleSwgaW1hZ2VSZWYsIHsKICAgICAgICBmbjogX3V0aWwuT1BTLnBhaW50SW1hZ2VYT2JqZWN0LAogICAgICAgIGFyZ3MsCiAgICAgICAgb3B0aW9uYWxDb250ZW50CiAgICAgIH0pOwogICAgICBpZiAoaW1hZ2VSZWYpIHsKICAgICAgICAoMCwgX3V0aWwuYXNzZXJ0KSghaXNJbmxpbmUsICJDYW5ub3QgY2FjaGUgYW4gaW5saW5lIGltYWdlIGdsb2JhbGx5LiIpOwogICAgICAgIHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZS5hZGRQYWdlSW5kZXgoaW1hZ2VSZWYsIHRoaXMucGFnZUluZGV4KTsKICAgICAgICBpZiAoY2FjaGVHbG9iYWxseSkgewogICAgICAgICAgdGhpcy5nbG9iYWxJbWFnZUNhY2hlLnNldERhdGEoaW1hZ2VSZWYsIHsKICAgICAgICAgICAgb2JqSWQsCiAgICAgICAgICAgIGZuOiBfdXRpbC5PUFMucGFpbnRJbWFnZVhPYmplY3QsCiAgICAgICAgICAgIGFyZ3MsCiAgICAgICAgICAgIG9wdGlvbmFsQ29udGVudCwKICAgICAgICAgICAgYnl0ZVNpemU6IDAKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICBoYW5kbGVTTWFzayhzbWFzaywgcmVzb3VyY2VzLCBvcGVyYXRvckxpc3QsIHRhc2ssIHN0YXRlTWFuYWdlciwgbG9jYWxDb2xvclNwYWNlQ2FjaGUpIHsKICAgIGNvbnN0IHNtYXNrQ29udGVudCA9IHNtYXNrLmdldCgiRyIpOwogICAgY29uc3Qgc21hc2tPcHRpb25zID0gewogICAgICBzdWJ0eXBlOiBzbWFzay5nZXQoIlMiKS5uYW1lLAogICAgICBiYWNrZHJvcDogc21hc2suZ2V0KCJCQyIpCiAgICB9OwogICAgY29uc3QgdHJhbnNmZXJPYmogPSBzbWFzay5nZXQoIlRSIik7CiAgICBpZiAoKDAsIF9mdW5jdGlvbi5pc1BERkZ1bmN0aW9uKSh0cmFuc2Zlck9iaikpIHsKICAgICAgY29uc3QgdHJhbnNmZXJGbiA9IHRoaXMuX3BkZkZ1bmN0aW9uRmFjdG9yeS5jcmVhdGUodHJhbnNmZXJPYmopOwogICAgICBjb25zdCB0cmFuc2Zlck1hcCA9IG5ldyBVaW50OEFycmF5KDI1Nik7CiAgICAgIGNvbnN0IHRtcCA9IG5ldyBGbG9hdDMyQXJyYXkoMSk7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMjU2OyBpKyspIHsKICAgICAgICB0bXBbMF0gPSBpIC8gMjU1OwogICAgICAgIHRyYW5zZmVyRm4odG1wLCAwLCB0bXAsIDApOwogICAgICAgIHRyYW5zZmVyTWFwW2ldID0gdG1wWzBdICogMjU1IHwgMDsKICAgICAgfQogICAgICBzbWFza09wdGlvbnMudHJhbnNmZXJNYXAgPSB0cmFuc2Zlck1hcDsKICAgIH0KICAgIHJldHVybiB0aGlzLmJ1aWxkRm9ybVhPYmplY3QocmVzb3VyY2VzLCBzbWFza0NvbnRlbnQsIHNtYXNrT3B0aW9ucywgb3BlcmF0b3JMaXN0LCB0YXNrLCBzdGF0ZU1hbmFnZXIuc3RhdGUuY2xvbmUoKSwgbG9jYWxDb2xvclNwYWNlQ2FjaGUpOwogIH0KICBoYW5kbGVUcmFuc2ZlckZ1bmN0aW9uKHRyKSB7CiAgICBsZXQgdHJhbnNmZXJBcnJheTsKICAgIGlmIChBcnJheS5pc0FycmF5KHRyKSkgewogICAgICB0cmFuc2ZlckFycmF5ID0gdHI7CiAgICB9IGVsc2UgaWYgKCgwLCBfZnVuY3Rpb24uaXNQREZGdW5jdGlvbikodHIpKSB7CiAgICAgIHRyYW5zZmVyQXJyYXkgPSBbdHJdOwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCB0cmFuc2Zlck1hcHMgPSBbXTsKICAgIGxldCBudW1GbnMgPSAwLAogICAgICBudW1FZmZlY3RmdWxGbnMgPSAwOwogICAgZm9yIChjb25zdCBlbnRyeSBvZiB0cmFuc2ZlckFycmF5KSB7CiAgICAgIGNvbnN0IHRyYW5zZmVyT2JqID0gdGhpcy54cmVmLmZldGNoSWZSZWYoZW50cnkpOwogICAgICBudW1GbnMrKzsKICAgICAgaWYgKCgwLCBfcHJpbWl0aXZlcy5pc05hbWUpKHRyYW5zZmVyT2JqLCAiSWRlbnRpdHkiKSkgewogICAgICAgIHRyYW5zZmVyTWFwcy5wdXNoKG51bGwpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9IGVsc2UgaWYgKCEoMCwgX2Z1bmN0aW9uLmlzUERGRnVuY3Rpb24pKHRyYW5zZmVyT2JqKSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IHRyYW5zZmVyRm4gPSB0aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnkuY3JlYXRlKHRyYW5zZmVyT2JqKTsKICAgICAgY29uc3QgdHJhbnNmZXJNYXAgPSBuZXcgVWludDhBcnJheSgyNTYpLAogICAgICAgIHRtcCA9IG5ldyBGbG9hdDMyQXJyYXkoMSk7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMjU2OyBqKyspIHsKICAgICAgICB0bXBbMF0gPSBqIC8gMjU1OwogICAgICAgIHRyYW5zZmVyRm4odG1wLCAwLCB0bXAsIDApOwogICAgICAgIHRyYW5zZmVyTWFwW2pdID0gdG1wWzBdICogMjU1IHwgMDsKICAgICAgfQogICAgICB0cmFuc2Zlck1hcHMucHVzaCh0cmFuc2Zlck1hcCk7CiAgICAgIG51bUVmZmVjdGZ1bEZucysrOwogICAgfQogICAgaWYgKCEobnVtRm5zID09PSAxIHx8IG51bUZucyA9PT0gNCkpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBpZiAobnVtRWZmZWN0ZnVsRm5zID09PSAwKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgcmV0dXJuIHRyYW5zZmVyTWFwczsKICB9CiAgaGFuZGxlVGlsaW5nVHlwZShmbiwgY29sb3IsIHJlc291cmNlcywgcGF0dGVybiwgcGF0dGVybkRpY3QsIG9wZXJhdG9yTGlzdCwgdGFzaywgbG9jYWxUaWxpbmdQYXR0ZXJuQ2FjaGUpIHsKICAgIGNvbnN0IHRpbGluZ09wTGlzdCA9IG5ldyBfb3BlcmF0b3JfbGlzdC5PcGVyYXRvckxpc3QoKTsKICAgIGNvbnN0IHBhdHRlcm5SZXNvdXJjZXMgPSBfcHJpbWl0aXZlcy5EaWN0Lm1lcmdlKHsKICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICBkaWN0QXJyYXk6IFtwYXR0ZXJuRGljdC5nZXQoIlJlc291cmNlcyIpLCByZXNvdXJjZXNdCiAgICB9KTsKICAgIHJldHVybiB0aGlzLmdldE9wZXJhdG9yTGlzdCh7CiAgICAgIHN0cmVhbTogcGF0dGVybiwKICAgICAgdGFzaywKICAgICAgcmVzb3VyY2VzOiBwYXR0ZXJuUmVzb3VyY2VzLAogICAgICBvcGVyYXRvckxpc3Q6IHRpbGluZ09wTGlzdAogICAgfSkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgIGNvbnN0IG9wZXJhdG9yTGlzdElSID0gdGlsaW5nT3BMaXN0LmdldElSKCk7CiAgICAgIGNvbnN0IHRpbGluZ1BhdHRlcm5JUiA9ICgwLCBfcGF0dGVybi5nZXRUaWxpbmdQYXR0ZXJuSVIpKG9wZXJhdG9yTGlzdElSLCBwYXR0ZXJuRGljdCwgY29sb3IpOwogICAgICBvcGVyYXRvckxpc3QuYWRkRGVwZW5kZW5jaWVzKHRpbGluZ09wTGlzdC5kZXBlbmRlbmNpZXMpOwogICAgICBvcGVyYXRvckxpc3QuYWRkT3AoZm4sIHRpbGluZ1BhdHRlcm5JUik7CiAgICAgIGlmIChwYXR0ZXJuRGljdC5vYmpJZCkgewogICAgICAgIGxvY2FsVGlsaW5nUGF0dGVybkNhY2hlLnNldChudWxsLCBwYXR0ZXJuRGljdC5vYmpJZCwgewogICAgICAgICAgb3BlcmF0b3JMaXN0SVIsCiAgICAgICAgICBkaWN0OiBwYXR0ZXJuRGljdAogICAgICAgIH0pOwogICAgICB9CiAgICB9KS5jYXRjaChyZWFzb24gPT4gewogICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgX3V0aWwuQWJvcnRFeGNlcHRpb24pIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKHRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYGhhbmRsZVRpbGluZ1R5cGUgLSBpZ25vcmluZyBwYXR0ZXJuOiAiJHtyZWFzb259Ii5gKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhyb3cgcmVhc29uOwogICAgfSk7CiAgfQogIGhhbmRsZVNldEZvbnQocmVzb3VyY2VzLCBmb250QXJncywgZm9udFJlZiwgb3BlcmF0b3JMaXN0LCB0YXNrLCBzdGF0ZSkgewogICAgbGV0IGZhbGxiYWNrRm9udERpY3QgPSBhcmd1bWVudHMubGVuZ3RoID4gNiAmJiBhcmd1bWVudHNbNl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1s2XSA6IG51bGw7CiAgICBsZXQgY3NzRm9udEluZm8gPSBhcmd1bWVudHMubGVuZ3RoID4gNyAmJiBhcmd1bWVudHNbN10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1s3XSA6IG51bGw7CiAgICBjb25zdCBmb250TmFtZSA9IGZvbnRBcmdzICYmIGZvbnRBcmdzWzBdIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSA/IGZvbnRBcmdzWzBdLm5hbWUgOiBudWxsOwogICAgcmV0dXJuIHRoaXMubG9hZEZvbnQoZm9udE5hbWUsIGZvbnRSZWYsIHJlc291cmNlcywgZmFsbGJhY2tGb250RGljdCwgY3NzRm9udEluZm8pLnRoZW4odHJhbnNsYXRlZCA9PiB7CiAgICAgIGlmICghdHJhbnNsYXRlZC5mb250LmlzVHlwZTNGb250KSB7CiAgICAgICAgcmV0dXJuIHRyYW5zbGF0ZWQ7CiAgICAgIH0KICAgICAgcmV0dXJuIHRyYW5zbGF0ZWQubG9hZFR5cGUzRGF0YSh0aGlzLCByZXNvdXJjZXMsIHRhc2spLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgIG9wZXJhdG9yTGlzdC5hZGREZXBlbmRlbmNpZXModHJhbnNsYXRlZC50eXBlM0RlcGVuZGVuY2llcyk7CiAgICAgICAgcmV0dXJuIHRyYW5zbGF0ZWQ7CiAgICAgIH0pLmNhdGNoKHJlYXNvbiA9PiB7CiAgICAgICAgcmV0dXJuIG5ldyBUcmFuc2xhdGVkRm9udCh7CiAgICAgICAgICBsb2FkZWROYW1lOiAiZ19mb250X2Vycm9yIiwKICAgICAgICAgIGZvbnQ6IG5ldyBfZm9udHMuRXJyb3JGb250KGBUeXBlMyBmb250IGxvYWQgZXJyb3I6ICR7cmVhc29ufWApLAogICAgICAgICAgZGljdDogdHJhbnNsYXRlZC5mb250LAogICAgICAgICAgZXZhbHVhdG9yT3B0aW9uczogdGhpcy5vcHRpb25zCiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgfSkudGhlbih0cmFuc2xhdGVkID0+IHsKICAgICAgc3RhdGUuZm9udCA9IHRyYW5zbGF0ZWQuZm9udDsKICAgICAgdHJhbnNsYXRlZC5zZW5kKHRoaXMuaGFuZGxlcik7CiAgICAgIHJldHVybiB0cmFuc2xhdGVkLmxvYWRlZE5hbWU7CiAgICB9KTsKICB9CiAgaGFuZGxlVGV4dChjaGFycywgc3RhdGUpIHsKICAgIGNvbnN0IGZvbnQgPSBzdGF0ZS5mb250OwogICAgY29uc3QgZ2x5cGhzID0gZm9udC5jaGFyc1RvR2x5cGhzKGNoYXJzKTsKICAgIGlmIChmb250LmRhdGEpIHsKICAgICAgY29uc3QgaXNBZGRUb1BhdGhTZXQgPSAhIShzdGF0ZS50ZXh0UmVuZGVyaW5nTW9kZSAmIF91dGlsLlRleHRSZW5kZXJpbmdNb2RlLkFERF9UT19QQVRIX0ZMQUcpOwogICAgICBpZiAoaXNBZGRUb1BhdGhTZXQgfHwgc3RhdGUuZmlsbENvbG9yU3BhY2UubmFtZSA9PT0gIlBhdHRlcm4iIHx8IGZvbnQuZGlzYWJsZUZvbnRGYWNlIHx8IHRoaXMub3B0aW9ucy5kaXNhYmxlRm9udEZhY2UpIHsKICAgICAgICBQYXJ0aWFsRXZhbHVhdG9yLmJ1aWxkRm9udFBhdGhzKGZvbnQsIGdseXBocywgdGhpcy5oYW5kbGVyLCB0aGlzLm9wdGlvbnMpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZ2x5cGhzOwogIH0KICBlbnN1cmVTdGF0ZUZvbnQoc3RhdGUpIHsKICAgIGlmIChzdGF0ZS5mb250KSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHJlYXNvbiA9IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiTWlzc2luZyBzZXRGb250IChUZikgb3BlcmF0b3IgYmVmb3JlIHRleHQgcmVuZGVyaW5nIG9wZXJhdG9yLiIpOwogICAgaWYgKHRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKGBlbnN1cmVTdGF0ZUZvbnQ6ICIke3JlYXNvbn0iLmApOwogICAgICByZXR1cm47CiAgICB9CiAgICB0aHJvdyByZWFzb247CiAgfQogIGFzeW5jIHNldEdTdGF0ZShfcmVmMykgewogICAgbGV0IHsKICAgICAgcmVzb3VyY2VzLAogICAgICBnU3RhdGUsCiAgICAgIG9wZXJhdG9yTGlzdCwKICAgICAgY2FjaGVLZXksCiAgICAgIHRhc2ssCiAgICAgIHN0YXRlTWFuYWdlciwKICAgICAgbG9jYWxHU3RhdGVDYWNoZSwKICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgIH0gPSBfcmVmMzsKICAgIGNvbnN0IGdTdGF0ZVJlZiA9IGdTdGF0ZS5vYmpJZDsKICAgIGxldCBpc1NpbXBsZUdTdGF0ZSA9IHRydWU7CiAgICBjb25zdCBnU3RhdGVPYmogPSBbXTsKICAgIGxldCBwcm9taXNlID0gUHJvbWlzZS5yZXNvbHZlKCk7CiAgICBmb3IgKGNvbnN0IGtleSBvZiBnU3RhdGUuZ2V0S2V5cygpKSB7CiAgICAgIGNvbnN0IHZhbHVlID0gZ1N0YXRlLmdldChrZXkpOwogICAgICBzd2l0Y2ggKGtleSkgewogICAgICAgIGNhc2UgIlR5cGUiOgogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiTFciOgogICAgICAgIGNhc2UgIkxDIjoKICAgICAgICBjYXNlICJMSiI6CiAgICAgICAgY2FzZSAiTUwiOgogICAgICAgIGNhc2UgIkQiOgogICAgICAgIGNhc2UgIlJJIjoKICAgICAgICBjYXNlICJGTCI6CiAgICAgICAgY2FzZSAiQ0EiOgogICAgICAgIGNhc2UgImNhIjoKICAgICAgICAgIGdTdGF0ZU9iai5wdXNoKFtrZXksIHZhbHVlXSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJGb250IjoKICAgICAgICAgIGlzU2ltcGxlR1N0YXRlID0gZmFsc2U7CiAgICAgICAgICBwcm9taXNlID0gcHJvbWlzZS50aGVuKCgpID0+IHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlU2V0Rm9udChyZXNvdXJjZXMsIG51bGwsIHZhbHVlWzBdLCBvcGVyYXRvckxpc3QsIHRhc2ssIHN0YXRlTWFuYWdlci5zdGF0ZSkudGhlbihmdW5jdGlvbiAobG9hZGVkTmFtZSkgewogICAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGREZXBlbmRlbmN5KGxvYWRlZE5hbWUpOwogICAgICAgICAgICAgIGdTdGF0ZU9iai5wdXNoKFtrZXksIFtsb2FkZWROYW1lLCB2YWx1ZVsxXV1dKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkJNIjoKICAgICAgICAgIGdTdGF0ZU9iai5wdXNoKFtrZXksIG5vcm1hbGl6ZUJsZW5kTW9kZSh2YWx1ZSldKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlNNYXNrIjoKICAgICAgICAgIGlmICgoMCwgX3ByaW1pdGl2ZXMuaXNOYW1lKSh2YWx1ZSwgIk5vbmUiKSkgewogICAgICAgICAgICBnU3RhdGVPYmoucHVzaChba2V5LCBmYWxzZV0pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpIHsKICAgICAgICAgICAgaXNTaW1wbGVHU3RhdGUgPSBmYWxzZTsKICAgICAgICAgICAgcHJvbWlzZSA9IHByb21pc2UudGhlbigoKSA9PiB7CiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlU01hc2sodmFsdWUsIHJlc291cmNlcywgb3BlcmF0b3JMaXN0LCB0YXNrLCBzdGF0ZU1hbmFnZXIsIGxvY2FsQ29sb3JTcGFjZUNhY2hlKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGdTdGF0ZU9iai5wdXNoKFtrZXksIHRydWVdKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiVW5zdXBwb3J0ZWQgU01hc2sgdHlwZSIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiVFIiOgogICAgICAgICAgY29uc3QgdHJhbnNmZXJNYXBzID0gdGhpcy5oYW5kbGVUcmFuc2ZlckZ1bmN0aW9uKHZhbHVlKTsKICAgICAgICAgIGdTdGF0ZU9iai5wdXNoKFtrZXksIHRyYW5zZmVyTWFwc10pOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiT1AiOgogICAgICAgIGNhc2UgIm9wIjoKICAgICAgICBjYXNlICJPUE0iOgogICAgICAgIGNhc2UgIkJHIjoKICAgICAgICBjYXNlICJCRzIiOgogICAgICAgIGNhc2UgIlVDUiI6CiAgICAgICAgY2FzZSAiVUNSMiI6CiAgICAgICAgY2FzZSAiVFIyIjoKICAgICAgICBjYXNlICJIVCI6CiAgICAgICAgY2FzZSAiU00iOgogICAgICAgIGNhc2UgIlNBIjoKICAgICAgICBjYXNlICJBSVMiOgogICAgICAgIGNhc2UgIlRLIjoKICAgICAgICAgICgwLCBfdXRpbC5pbmZvKSgiZ3JhcGhpYyBzdGF0ZSBvcGVyYXRvciAiICsga2V5KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAoMCwgX3V0aWwuaW5mbykoIlVua25vd24gZ3JhcGhpYyBzdGF0ZSBvcGVyYXRvciAiICsga2V5KTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcHJvbWlzZS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgaWYgKGdTdGF0ZU9iai5sZW5ndGggPiAwKSB7CiAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKF91dGlsLk9QUy5zZXRHU3RhdGUsIFtnU3RhdGVPYmpdKTsKICAgICAgfQogICAgICBpZiAoaXNTaW1wbGVHU3RhdGUpIHsKICAgICAgICBsb2NhbEdTdGF0ZUNhY2hlLnNldChjYWNoZUtleSwgZ1N0YXRlUmVmLCBnU3RhdGVPYmopOwogICAgICB9CiAgICB9KTsKICB9CiAgbG9hZEZvbnQoZm9udE5hbWUsIGZvbnQsIHJlc291cmNlcykgewogICAgbGV0IGZhbGxiYWNrRm9udERpY3QgPSBhcmd1bWVudHMubGVuZ3RoID4gMyAmJiBhcmd1bWVudHNbM10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1szXSA6IG51bGw7CiAgICBsZXQgY3NzRm9udEluZm8gPSBhcmd1bWVudHMubGVuZ3RoID4gNCAmJiBhcmd1bWVudHNbNF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1s0XSA6IG51bGw7CiAgICBjb25zdCBlcnJvckZvbnQgPSBhc3luYyAoKSA9PiB7CiAgICAgIHJldHVybiBuZXcgVHJhbnNsYXRlZEZvbnQoewogICAgICAgIGxvYWRlZE5hbWU6ICJnX2ZvbnRfZXJyb3IiLAogICAgICAgIGZvbnQ6IG5ldyBfZm9udHMuRXJyb3JGb250KGBGb250ICIke2ZvbnROYW1lfSIgaXMgbm90IGF2YWlsYWJsZS5gKSwKICAgICAgICBkaWN0OiBmb250LAogICAgICAgIGV2YWx1YXRvck9wdGlvbnM6IHRoaXMub3B0aW9ucwogICAgICB9KTsKICAgIH07CiAgICBjb25zdCB4cmVmID0gdGhpcy54cmVmOwogICAgbGV0IGZvbnRSZWY7CiAgICBpZiAoZm9udCkgewogICAgICBpZiAoZm9udCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgIGZvbnRSZWYgPSBmb250OwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBmb250UmVzID0gcmVzb3VyY2VzLmdldCgiRm9udCIpOwogICAgICBpZiAoZm9udFJlcykgewogICAgICAgIGZvbnRSZWYgPSBmb250UmVzLmdldFJhdyhmb250TmFtZSk7CiAgICAgIH0KICAgIH0KICAgIGlmICghZm9udFJlZikgewogICAgICBjb25zdCBwYXJ0aWFsTXNnID0gYEZvbnQgIiR7Zm9udE5hbWUgfHwgZm9udCAmJiBmb250LnRvU3RyaW5nKCl9IiBpcyBub3QgYXZhaWxhYmxlYDsKICAgICAgaWYgKCF0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzICYmICF0aGlzLnBhcnNpbmdUeXBlM0ZvbnQpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYCR7cGFydGlhbE1zZ30uYCk7CiAgICAgICAgcmV0dXJuIGVycm9yRm9udCgpOwogICAgICB9CiAgICAgICgwLCBfdXRpbC53YXJuKShgJHtwYXJ0aWFsTXNnfSAtLSBhdHRlbXB0aW5nIHRvIGZhbGxiYWNrIHRvIGEgZGVmYXVsdCBmb250LmApOwogICAgICBpZiAoZmFsbGJhY2tGb250RGljdCkgewogICAgICAgIGZvbnRSZWYgPSBmYWxsYmFja0ZvbnREaWN0OwogICAgICB9IGVsc2UgewogICAgICAgIGZvbnRSZWYgPSBQYXJ0aWFsRXZhbHVhdG9yLmZhbGxiYWNrRm9udERpY3Q7CiAgICAgIH0KICAgIH0KICAgIGlmICh0aGlzLnBhcnNpbmdUeXBlM0ZvbnQgJiYgdGhpcy50eXBlM0ZvbnRSZWZzLmhhcyhmb250UmVmKSkgewogICAgICByZXR1cm4gZXJyb3JGb250KCk7CiAgICB9CiAgICBpZiAodGhpcy5mb250Q2FjaGUuaGFzKGZvbnRSZWYpKSB7CiAgICAgIHJldHVybiB0aGlzLmZvbnRDYWNoZS5nZXQoZm9udFJlZik7CiAgICB9CiAgICBmb250ID0geHJlZi5mZXRjaElmUmVmKGZvbnRSZWYpOwogICAgaWYgKCEoZm9udCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybiBlcnJvckZvbnQoKTsKICAgIH0KICAgIGlmIChmb250LmNhY2hlS2V5ICYmIHRoaXMuZm9udENhY2hlLmhhcyhmb250LmNhY2hlS2V5KSkgewogICAgICByZXR1cm4gdGhpcy5mb250Q2FjaGUuZ2V0KGZvbnQuY2FjaGVLZXkpOwogICAgfQogICAgY29uc3QgZm9udENhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICBsZXQgcHJlRXZhbHVhdGVkRm9udDsKICAgIHRyeSB7CiAgICAgIHByZUV2YWx1YXRlZEZvbnQgPSB0aGlzLnByZUV2YWx1YXRlRm9udChmb250KTsKICAgICAgcHJlRXZhbHVhdGVkRm9udC5jc3NGb250SW5mbyA9IGNzc0ZvbnRJbmZvOwogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKShgbG9hZEZvbnQgLSBwcmVFdmFsdWF0ZUZvbnQgZmFpbGVkOiAiJHtyZWFzb259Ii5gKTsKICAgICAgcmV0dXJuIGVycm9yRm9udCgpOwogICAgfQogICAgY29uc3QgewogICAgICBkZXNjcmlwdG9yLAogICAgICBoYXNoCiAgICB9ID0gcHJlRXZhbHVhdGVkRm9udDsKICAgIGNvbnN0IGZvbnRSZWZJc1JlZiA9IGZvbnRSZWYgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWY7CiAgICBsZXQgZm9udElEOwogICAgaWYgKGZvbnRSZWZJc1JlZikgewogICAgICBmb250SUQgPSBgZiR7Zm9udFJlZi50b1N0cmluZygpfWA7CiAgICB9CiAgICBpZiAoaGFzaCAmJiBkZXNjcmlwdG9yIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICBpZiAoIWRlc2NyaXB0b3IuZm9udEFsaWFzZXMpIHsKICAgICAgICBkZXNjcmlwdG9yLmZvbnRBbGlhc2VzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgfQogICAgICBjb25zdCBmb250QWxpYXNlcyA9IGRlc2NyaXB0b3IuZm9udEFsaWFzZXM7CiAgICAgIGlmIChmb250QWxpYXNlc1toYXNoXSkgewogICAgICAgIGNvbnN0IGFsaWFzRm9udFJlZiA9IGZvbnRBbGlhc2VzW2hhc2hdLmFsaWFzUmVmOwogICAgICAgIGlmIChmb250UmVmSXNSZWYgJiYgYWxpYXNGb250UmVmICYmIHRoaXMuZm9udENhY2hlLmhhcyhhbGlhc0ZvbnRSZWYpKSB7CiAgICAgICAgICB0aGlzLmZvbnRDYWNoZS5wdXRBbGlhcyhmb250UmVmLCBhbGlhc0ZvbnRSZWYpOwogICAgICAgICAgcmV0dXJuIHRoaXMuZm9udENhY2hlLmdldChmb250UmVmKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9udEFsaWFzZXNbaGFzaF0gPSB7CiAgICAgICAgICBmb250SUQ6IHRoaXMuaWRGYWN0b3J5LmNyZWF0ZUZvbnRJZCgpCiAgICAgICAgfTsKICAgICAgfQogICAgICBpZiAoZm9udFJlZklzUmVmKSB7CiAgICAgICAgZm9udEFsaWFzZXNbaGFzaF0uYWxpYXNSZWYgPSBmb250UmVmOwogICAgICB9CiAgICAgIGZvbnRJRCA9IGZvbnRBbGlhc2VzW2hhc2hdLmZvbnRJRDsKICAgIH0KICAgIGlmIChmb250UmVmSXNSZWYpIHsKICAgICAgdGhpcy5mb250Q2FjaGUucHV0KGZvbnRSZWYsIGZvbnRDYXBhYmlsaXR5LnByb21pc2UpOwogICAgfSBlbHNlIHsKICAgICAgaWYgKCFmb250SUQpIHsKICAgICAgICBmb250SUQgPSB0aGlzLmlkRmFjdG9yeS5jcmVhdGVGb250SWQoKTsKICAgICAgfQogICAgICBmb250LmNhY2hlS2V5ID0gYGNhY2hlS2V5XyR7Zm9udElEfWA7CiAgICAgIHRoaXMuZm9udENhY2hlLnB1dChmb250LmNhY2hlS2V5LCBmb250Q2FwYWJpbGl0eS5wcm9taXNlKTsKICAgIH0KICAgICgwLCBfdXRpbC5hc3NlcnQpKGZvbnRJRCAmJiBmb250SUQuc3RhcnRzV2l0aCgiZiIpLCAnVGhlICJmb250SUQiIG11c3QgYmUgKGNvcnJlY3RseSkgZGVmaW5lZC4nKTsKICAgIGZvbnQubG9hZGVkTmFtZSA9IGAke3RoaXMuaWRGYWN0b3J5LmdldERvY0lkKCl9XyR7Zm9udElEfWA7CiAgICB0aGlzLnRyYW5zbGF0ZUZvbnQocHJlRXZhbHVhdGVkRm9udCkudGhlbih0cmFuc2xhdGVkRm9udCA9PiB7CiAgICAgIGZvbnRDYXBhYmlsaXR5LnJlc29sdmUobmV3IFRyYW5zbGF0ZWRGb250KHsKICAgICAgICBsb2FkZWROYW1lOiBmb250LmxvYWRlZE5hbWUsCiAgICAgICAgZm9udDogdHJhbnNsYXRlZEZvbnQsCiAgICAgICAgZGljdDogZm9udCwKICAgICAgICBldmFsdWF0b3JPcHRpb25zOiB0aGlzLm9wdGlvbnMKICAgICAgfSkpOwogICAgfSkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgKDAsIF91dGlsLndhcm4pKGBsb2FkRm9udCAtIHRyYW5zbGF0ZUZvbnQgZmFpbGVkOiAiJHtyZWFzb259Ii5gKTsKICAgICAgZm9udENhcGFiaWxpdHkucmVzb2x2ZShuZXcgVHJhbnNsYXRlZEZvbnQoewogICAgICAgIGxvYWRlZE5hbWU6IGZvbnQubG9hZGVkTmFtZSwKICAgICAgICBmb250OiBuZXcgX2ZvbnRzLkVycm9yRm9udChyZWFzb24gaW5zdGFuY2VvZiBFcnJvciA/IHJlYXNvbi5tZXNzYWdlIDogcmVhc29uKSwKICAgICAgICBkaWN0OiBmb250LAogICAgICAgIGV2YWx1YXRvck9wdGlvbnM6IHRoaXMub3B0aW9ucwogICAgICB9KSk7CiAgICB9KTsKICAgIHJldHVybiBmb250Q2FwYWJpbGl0eS5wcm9taXNlOwogIH0KICBidWlsZFBhdGgob3BlcmF0b3JMaXN0LCBmbiwgYXJncykgewogICAgbGV0IHBhcnNpbmdUZXh0ID0gYXJndW1lbnRzLmxlbmd0aCA+IDMgJiYgYXJndW1lbnRzWzNdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbM10gOiBmYWxzZTsKICAgIGNvbnN0IGxhc3RJbmRleCA9IG9wZXJhdG9yTGlzdC5sZW5ndGggLSAxOwogICAgaWYgKCFhcmdzKSB7CiAgICAgIGFyZ3MgPSBbXTsKICAgIH0KICAgIGlmIChsYXN0SW5kZXggPCAwIHx8IG9wZXJhdG9yTGlzdC5mbkFycmF5W2xhc3RJbmRleF0gIT09IF91dGlsLk9QUy5jb25zdHJ1Y3RQYXRoKSB7CiAgICAgIGlmIChwYXJzaW5nVGV4dCkgewogICAgICAgICgwLCBfdXRpbC53YXJuKShgRW5jb3VudGVyZWQgcGF0aCBvcGVyYXRvciAiJHtmbn0iIGluc2lkZSBvZiBhIHRleHQgb2JqZWN0LmApOwogICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChfdXRpbC5PUFMuc2F2ZSwgbnVsbCk7CiAgICAgIH0KICAgICAgbGV0IG1pbk1heDsKICAgICAgc3dpdGNoIChmbikgewogICAgICAgIGNhc2UgX3V0aWwuT1BTLnJlY3RhbmdsZToKICAgICAgICAgIGNvbnN0IHggPSBhcmdzWzBdICsgYXJnc1syXTsKICAgICAgICAgIGNvbnN0IHkgPSBhcmdzWzFdICsgYXJnc1szXTsKICAgICAgICAgIG1pbk1heCA9IFtNYXRoLm1pbihhcmdzWzBdLCB4KSwgTWF0aC5tYXgoYXJnc1swXSwgeCksIE1hdGgubWluKGFyZ3NbMV0sIHkpLCBNYXRoLm1heChhcmdzWzFdLCB5KV07CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIF91dGlsLk9QUy5tb3ZlVG86CiAgICAgICAgY2FzZSBfdXRpbC5PUFMubGluZVRvOgogICAgICAgICAgbWluTWF4ID0gW2FyZ3NbMF0sIGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMV1dOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIG1pbk1heCA9IFtJbmZpbml0eSwgLUluZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5XTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChfdXRpbC5PUFMuY29uc3RydWN0UGF0aCwgW1tmbl0sIGFyZ3MsIG1pbk1heF0pOwogICAgICBpZiAocGFyc2luZ1RleHQpIHsKICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoX3V0aWwuT1BTLnJlc3RvcmUsIG51bGwpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBvcEFyZ3MgPSBvcGVyYXRvckxpc3QuYXJnc0FycmF5W2xhc3RJbmRleF07CiAgICAgIG9wQXJnc1swXS5wdXNoKGZuKTsKICAgICAgb3BBcmdzWzFdLnB1c2goLi4uYXJncyk7CiAgICAgIGNvbnN0IG1pbk1heCA9IG9wQXJnc1syXTsKICAgICAgc3dpdGNoIChmbikgewogICAgICAgIGNhc2UgX3V0aWwuT1BTLnJlY3RhbmdsZToKICAgICAgICAgIGNvbnN0IHggPSBhcmdzWzBdICsgYXJnc1syXTsKICAgICAgICAgIGNvbnN0IHkgPSBhcmdzWzFdICsgYXJnc1szXTsKICAgICAgICAgIG1pbk1heFswXSA9IE1hdGgubWluKG1pbk1heFswXSwgYXJnc1swXSwgeCk7CiAgICAgICAgICBtaW5NYXhbMV0gPSBNYXRoLm1heChtaW5NYXhbMV0sIGFyZ3NbMF0sIHgpOwogICAgICAgICAgbWluTWF4WzJdID0gTWF0aC5taW4obWluTWF4WzJdLCBhcmdzWzFdLCB5KTsKICAgICAgICAgIG1pbk1heFszXSA9IE1hdGgubWF4KG1pbk1heFszXSwgYXJnc1sxXSwgeSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIF91dGlsLk9QUy5tb3ZlVG86CiAgICAgICAgY2FzZSBfdXRpbC5PUFMubGluZVRvOgogICAgICAgICAgbWluTWF4WzBdID0gTWF0aC5taW4obWluTWF4WzBdLCBhcmdzWzBdKTsKICAgICAgICAgIG1pbk1heFsxXSA9IE1hdGgubWF4KG1pbk1heFsxXSwgYXJnc1swXSk7CiAgICAgICAgICBtaW5NYXhbMl0gPSBNYXRoLm1pbihtaW5NYXhbMl0sIGFyZ3NbMV0pOwogICAgICAgICAgbWluTWF4WzNdID0gTWF0aC5tYXgobWluTWF4WzNdLCBhcmdzWzFdKTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQogIHBhcnNlQ29sb3JTcGFjZShfcmVmNCkgewogICAgbGV0IHsKICAgICAgY3MsCiAgICAgIHJlc291cmNlcywKICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgIH0gPSBfcmVmNDsKICAgIHJldHVybiBfY29sb3JzcGFjZS5Db2xvclNwYWNlLnBhcnNlQXN5bmMoewogICAgICBjcywKICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICByZXNvdXJjZXMsCiAgICAgIHBkZkZ1bmN0aW9uRmFjdG9yeTogdGhpcy5fcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgfSkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIF91dGlsLkFib3J0RXhjZXB0aW9uKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgaWYgKHRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYHBhcnNlQ29sb3JTcGFjZSAtIGlnbm9yaW5nIENvbG9yU3BhY2U6ICIke3JlYXNvbn0iLmApOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHRocm93IHJlYXNvbjsKICAgIH0pOwogIH0KICBwYXJzZVNoYWRpbmcoX3JlZjUpIHsKICAgIGxldCB7CiAgICAgIHNoYWRpbmcsCiAgICAgIHJlc291cmNlcywKICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUsCiAgICAgIGxvY2FsU2hhZGluZ1BhdHRlcm5DYWNoZQogICAgfSA9IF9yZWY1OwogICAgbGV0IGlkID0gbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlLmdldChzaGFkaW5nKTsKICAgIGlmICghaWQpIHsKICAgICAgdmFyIHNoYWRpbmdGaWxsID0gX3BhdHRlcm4uUGF0dGVybi5wYXJzZVNoYWRpbmcoc2hhZGluZywgdGhpcy54cmVmLCByZXNvdXJjZXMsIHRoaXMuX3BkZkZ1bmN0aW9uRmFjdG9yeSwgbG9jYWxDb2xvclNwYWNlQ2FjaGUpOwogICAgICBjb25zdCBwYXR0ZXJuSVIgPSBzaGFkaW5nRmlsbC5nZXRJUigpOwogICAgICBpZCA9IGBwYXR0ZXJuXyR7dGhpcy5pZEZhY3RvcnkuY3JlYXRlT2JqSWQoKX1gOwogICAgICBpZiAodGhpcy5wYXJzaW5nVHlwZTNGb250KSB7CiAgICAgICAgaWQgPSBgJHt0aGlzLmlkRmFjdG9yeS5nZXREb2NJZCgpfV90eXBlM18ke2lkfWA7CiAgICAgIH0KICAgICAgbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlLnNldChzaGFkaW5nLCBpZCk7CiAgICAgIGlmICh0aGlzLnBhcnNpbmdUeXBlM0ZvbnQpIHsKICAgICAgICB0aGlzLmhhbmRsZXIuc2VuZCgiY29tbW9ub2JqIiwgW2lkLCAiUGF0dGVybiIsIHBhdHRlcm5JUl0pOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuaGFuZGxlci5zZW5kKCJvYmoiLCBbaWQsIHRoaXMucGFnZUluZGV4LCAiUGF0dGVybiIsIHBhdHRlcm5JUl0pOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gaWQ7CiAgfQogIGhhbmRsZUNvbG9yTihvcGVyYXRvckxpc3QsIGZuLCBhcmdzLCBjcywgcGF0dGVybnMsIHJlc291cmNlcywgdGFzaywgbG9jYWxDb2xvclNwYWNlQ2FjaGUsIGxvY2FsVGlsaW5nUGF0dGVybkNhY2hlLCBsb2NhbFNoYWRpbmdQYXR0ZXJuQ2FjaGUpIHsKICAgIGNvbnN0IHBhdHRlcm5OYW1lID0gYXJncy5wb3AoKTsKICAgIGlmIChwYXR0ZXJuTmFtZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgY29uc3QgcmF3UGF0dGVybiA9IHBhdHRlcm5zLmdldFJhdyhwYXR0ZXJuTmFtZS5uYW1lKTsKICAgICAgY29uc3QgbG9jYWxUaWxpbmdQYXR0ZXJuID0gcmF3UGF0dGVybiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZiAmJiBsb2NhbFRpbGluZ1BhdHRlcm5DYWNoZS5nZXRCeVJlZihyYXdQYXR0ZXJuKTsKICAgICAgaWYgKGxvY2FsVGlsaW5nUGF0dGVybikgewogICAgICAgIHRyeSB7CiAgICAgICAgICBjb25zdCBjb2xvciA9IGNzLmJhc2UgPyBjcy5iYXNlLmdldFJnYihhcmdzLCAwKSA6IG51bGw7CiAgICAgICAgICBjb25zdCB0aWxpbmdQYXR0ZXJuSVIgPSAoMCwgX3BhdHRlcm4uZ2V0VGlsaW5nUGF0dGVybklSKShsb2NhbFRpbGluZ1BhdHRlcm4ub3BlcmF0b3JMaXN0SVIsIGxvY2FsVGlsaW5nUGF0dGVybi5kaWN0LCBjb2xvcik7CiAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoZm4sIHRpbGluZ1BhdHRlcm5JUik7CiAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgICAgIH0gY2F0Y2ggKGV4KSB7fQogICAgICB9CiAgICAgIGNvbnN0IHBhdHRlcm4gPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihyYXdQYXR0ZXJuKTsKICAgICAgaWYgKHBhdHRlcm4pIHsKICAgICAgICBjb25zdCBkaWN0ID0gcGF0dGVybiBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtID8gcGF0dGVybi5kaWN0IDogcGF0dGVybjsKICAgICAgICBjb25zdCB0eXBlTnVtID0gZGljdC5nZXQoIlBhdHRlcm5UeXBlIik7CiAgICAgICAgaWYgKHR5cGVOdW0gPT09IFBhdHRlcm5UeXBlLlRJTElORykgewogICAgICAgICAgY29uc3QgY29sb3IgPSBjcy5iYXNlID8gY3MuYmFzZS5nZXRSZ2IoYXJncywgMCkgOiBudWxsOwogICAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlVGlsaW5nVHlwZShmbiwgY29sb3IsIHJlc291cmNlcywgcGF0dGVybiwgZGljdCwgb3BlcmF0b3JMaXN0LCB0YXNrLCBsb2NhbFRpbGluZ1BhdHRlcm5DYWNoZSk7CiAgICAgICAgfSBlbHNlIGlmICh0eXBlTnVtID09PSBQYXR0ZXJuVHlwZS5TSEFESU5HKSB7CiAgICAgICAgICBjb25zdCBzaGFkaW5nID0gZGljdC5nZXQoIlNoYWRpbmciKTsKICAgICAgICAgIGNvbnN0IG1hdHJpeCA9IGRpY3QuZ2V0QXJyYXkoIk1hdHJpeCIpOwogICAgICAgICAgY29uc3Qgb2JqSWQgPSB0aGlzLnBhcnNlU2hhZGluZyh7CiAgICAgICAgICAgIHNoYWRpbmcsCiAgICAgICAgICAgIHJlc291cmNlcywKICAgICAgICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUsCiAgICAgICAgICAgIGxvY2FsU2hhZGluZ1BhdHRlcm5DYWNoZQogICAgICAgICAgfSk7CiAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoZm4sIFsiU2hhZGluZyIsIG9iaklkLCBtYXRyaXhdKTsKICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICAgICAgfQogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgVW5rbm93biBQYXR0ZXJuVHlwZTogJHt0eXBlTnVtfWApOwogICAgICB9CiAgICB9CiAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYFVua25vd24gUGF0dGVybk5hbWU6ICR7cGF0dGVybk5hbWV9YCk7CiAgfQogIF9wYXJzZVZpc2liaWxpdHlFeHByZXNzaW9uKGFycmF5LCBuZXN0aW5nQ291bnRlciwgY3VycmVudFJlc3VsdCkgewogICAgY29uc3QgTUFYX05FU1RJTkcgPSAxMDsKICAgIGlmICgrK25lc3RpbmdDb3VudGVyID4gTUFYX05FU1RJTkcpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKCJWaXNpYmlsaXR5IGV4cHJlc3Npb24gaXMgdG9vIGRlZXBseSBuZXN0ZWQiKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgbGVuZ3RoID0gYXJyYXkubGVuZ3RoOwogICAgY29uc3Qgb3BlcmF0b3IgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihhcnJheVswXSk7CiAgICBpZiAobGVuZ3RoIDwgMiB8fCAhKG9wZXJhdG9yIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKCJJbnZhbGlkIHZpc2liaWxpdHkgZXhwcmVzc2lvbiIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBzd2l0Y2ggKG9wZXJhdG9yLm5hbWUpIHsKICAgICAgY2FzZSAiQW5kIjoKICAgICAgY2FzZSAiT3IiOgogICAgICBjYXNlICJOb3QiOgogICAgICAgIGN1cnJlbnRSZXN1bHQucHVzaChvcGVyYXRvci5uYW1lKTsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICAoMCwgX3V0aWwud2FybikoYEludmFsaWQgb3BlcmF0b3IgJHtvcGVyYXRvci5uYW1lfSBpbiB2aXNpYmlsaXR5IGV4cHJlc3Npb25gKTsKICAgICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGxldCBpID0gMTsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIGNvbnN0IHJhdyA9IGFycmF5W2ldOwogICAgICBjb25zdCBvYmplY3QgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihyYXcpOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShvYmplY3QpKSB7CiAgICAgICAgY29uc3QgbmVzdGVkUmVzdWx0ID0gW107CiAgICAgICAgY3VycmVudFJlc3VsdC5wdXNoKG5lc3RlZFJlc3VsdCk7CiAgICAgICAgdGhpcy5fcGFyc2VWaXNpYmlsaXR5RXhwcmVzc2lvbihvYmplY3QsIG5lc3RpbmdDb3VudGVyLCBuZXN0ZWRSZXN1bHQpOwogICAgICB9IGVsc2UgaWYgKHJhdyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgIGN1cnJlbnRSZXN1bHQucHVzaChyYXcudG9TdHJpbmcoKSk7CiAgICAgIH0KICAgIH0KICB9CiAgYXN5bmMgcGFyc2VNYXJrZWRDb250ZW50UHJvcHMoY29udGVudFByb3BlcnRpZXMsIHJlc291cmNlcykgewogICAgbGV0IG9wdGlvbmFsQ29udGVudDsKICAgIGlmIChjb250ZW50UHJvcGVydGllcyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgY29uc3QgcHJvcGVydGllcyA9IHJlc291cmNlcy5nZXQoIlByb3BlcnRpZXMiKTsKICAgICAgb3B0aW9uYWxDb250ZW50ID0gcHJvcGVydGllcy5nZXQoY29udGVudFByb3BlcnRpZXMubmFtZSk7CiAgICB9IGVsc2UgaWYgKGNvbnRlbnRQcm9wZXJ0aWVzIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICBvcHRpb25hbENvbnRlbnQgPSBjb250ZW50UHJvcGVydGllczsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiT3B0aW9uYWwgY29udGVudCBwcm9wZXJ0aWVzIG1hbGZvcm1lZC4iKTsKICAgIH0KICAgIGNvbnN0IG9wdGlvbmFsQ29udGVudFR5cGUgPSBvcHRpb25hbENvbnRlbnQuZ2V0KCJUeXBlIikubmFtZTsKICAgIGlmIChvcHRpb25hbENvbnRlbnRUeXBlID09PSAiT0NHIikgewogICAgICByZXR1cm4gewogICAgICAgIHR5cGU6IG9wdGlvbmFsQ29udGVudFR5cGUsCiAgICAgICAgaWQ6IG9wdGlvbmFsQ29udGVudC5vYmpJZAogICAgICB9OwogICAgfSBlbHNlIGlmIChvcHRpb25hbENvbnRlbnRUeXBlID09PSAiT0NNRCIpIHsKICAgICAgY29uc3QgZXhwcmVzc2lvbiA9IG9wdGlvbmFsQ29udGVudC5nZXQoIlZFIik7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KGV4cHJlc3Npb24pKSB7CiAgICAgICAgY29uc3QgcmVzdWx0ID0gW107CiAgICAgICAgdGhpcy5fcGFyc2VWaXNpYmlsaXR5RXhwcmVzc2lvbihleHByZXNzaW9uLCAwLCByZXN1bHQpOwogICAgICAgIGlmIChyZXN1bHQubGVuZ3RoID4gMCkgewogICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgdHlwZTogIk9DTUQiLAogICAgICAgICAgICBleHByZXNzaW9uOiByZXN1bHQKICAgICAgICAgIH07CiAgICAgICAgfQogICAgICB9CiAgICAgIGNvbnN0IG9wdGlvbmFsQ29udGVudEdyb3VwcyA9IG9wdGlvbmFsQ29udGVudC5nZXQoIk9DR3MiKTsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9uYWxDb250ZW50R3JvdXBzKSB8fCBvcHRpb25hbENvbnRlbnRHcm91cHMgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgICAgY29uc3QgZ3JvdXBJZHMgPSBbXTsKICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShvcHRpb25hbENvbnRlbnRHcm91cHMpKSB7CiAgICAgICAgICBmb3IgKGNvbnN0IG9jZyBvZiBvcHRpb25hbENvbnRlbnRHcm91cHMpIHsKICAgICAgICAgICAgZ3JvdXBJZHMucHVzaChvY2cudG9TdHJpbmcoKSk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGdyb3VwSWRzLnB1c2gob3B0aW9uYWxDb250ZW50R3JvdXBzLm9iaklkKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHR5cGU6IG9wdGlvbmFsQ29udGVudFR5cGUsCiAgICAgICAgICBpZHM6IGdyb3VwSWRzLAogICAgICAgICAgcG9saWN5OiBvcHRpb25hbENvbnRlbnQuZ2V0KCJQIikgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lID8gb3B0aW9uYWxDb250ZW50LmdldCgiUCIpLm5hbWUgOiBudWxsLAogICAgICAgICAgZXhwcmVzc2lvbjogbnVsbAogICAgICAgIH07CiAgICAgIH0gZWxzZSBpZiAob3B0aW9uYWxDb250ZW50R3JvdXBzIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHR5cGU6IG9wdGlvbmFsQ29udGVudFR5cGUsCiAgICAgICAgICBpZDogb3B0aW9uYWxDb250ZW50R3JvdXBzLnRvU3RyaW5nKCkKICAgICAgICB9OwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgZ2V0T3BlcmF0b3JMaXN0KF9yZWY2KSB7CiAgICBsZXQgewogICAgICBzdHJlYW0sCiAgICAgIHRhc2ssCiAgICAgIHJlc291cmNlcywKICAgICAgb3BlcmF0b3JMaXN0LAogICAgICBpbml0aWFsU3RhdGUgPSBudWxsLAogICAgICBmYWxsYmFja0ZvbnREaWN0ID0gbnVsbAogICAgfSA9IF9yZWY2OwogICAgcmVzb3VyY2VzID0gcmVzb3VyY2VzIHx8IF9wcmltaXRpdmVzLkRpY3QuZW1wdHk7CiAgICBpbml0aWFsU3RhdGUgPSBpbml0aWFsU3RhdGUgfHwgbmV3IEV2YWxTdGF0ZSgpOwogICAgaWYgKCFvcGVyYXRvckxpc3QpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdnZXRPcGVyYXRvckxpc3Q6IG1pc3NpbmcgIm9wZXJhdG9yTGlzdCIgcGFyYW1ldGVyJyk7CiAgICB9CiAgICBjb25zdCBzZWxmID0gdGhpczsKICAgIGNvbnN0IHhyZWYgPSB0aGlzLnhyZWY7CiAgICBsZXQgcGFyc2luZ1RleHQgPSBmYWxzZTsKICAgIGNvbnN0IGxvY2FsSW1hZ2VDYWNoZSA9IG5ldyBfaW1hZ2VfdXRpbHMuTG9jYWxJbWFnZUNhY2hlKCk7CiAgICBjb25zdCBsb2NhbENvbG9yU3BhY2VDYWNoZSA9IG5ldyBfaW1hZ2VfdXRpbHMuTG9jYWxDb2xvclNwYWNlQ2FjaGUoKTsKICAgIGNvbnN0IGxvY2FsR1N0YXRlQ2FjaGUgPSBuZXcgX2ltYWdlX3V0aWxzLkxvY2FsR1N0YXRlQ2FjaGUoKTsKICAgIGNvbnN0IGxvY2FsVGlsaW5nUGF0dGVybkNhY2hlID0gbmV3IF9pbWFnZV91dGlscy5Mb2NhbFRpbGluZ1BhdHRlcm5DYWNoZSgpOwogICAgY29uc3QgbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlID0gbmV3IE1hcCgpOwogICAgY29uc3QgeG9ianMgPSByZXNvdXJjZXMuZ2V0KCJYT2JqZWN0IikgfHwgX3ByaW1pdGl2ZXMuRGljdC5lbXB0eTsKICAgIGNvbnN0IHBhdHRlcm5zID0gcmVzb3VyY2VzLmdldCgiUGF0dGVybiIpIHx8IF9wcmltaXRpdmVzLkRpY3QuZW1wdHk7CiAgICBjb25zdCBzdGF0ZU1hbmFnZXIgPSBuZXcgU3RhdGVNYW5hZ2VyKGluaXRpYWxTdGF0ZSk7CiAgICBjb25zdCBwcmVwcm9jZXNzb3IgPSBuZXcgRXZhbHVhdG9yUHJlcHJvY2Vzc29yKHN0cmVhbSwgeHJlZiwgc3RhdGVNYW5hZ2VyKTsKICAgIGNvbnN0IHRpbWVTbG90TWFuYWdlciA9IG5ldyBUaW1lU2xvdE1hbmFnZXIoKTsKICAgIGZ1bmN0aW9uIGNsb3NlUGVuZGluZ1Jlc3RvcmVPUFMoYXJndW1lbnQpIHsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gcHJlcHJvY2Vzc29yLnNhdmVkU3RhdGVzRGVwdGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKF91dGlsLk9QUy5yZXN0b3JlLCBbXSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiBwcm9taXNlQm9keShyZXNvbHZlLCByZWplY3QpIHsKICAgICAgY29uc3QgbmV4dCA9IGZ1bmN0aW9uIChwcm9taXNlKSB7CiAgICAgICAgUHJvbWlzZS5hbGwoW3Byb21pc2UsIG9wZXJhdG9yTGlzdC5yZWFkeV0pLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcHJvbWlzZUJvZHkocmVzb2x2ZSwgcmVqZWN0KTsKICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICAgIHJlamVjdChleCk7CiAgICAgICAgICB9CiAgICAgICAgfSwgcmVqZWN0KTsKICAgICAgfTsKICAgICAgdGFzay5lbnN1cmVOb3RUZXJtaW5hdGVkKCk7CiAgICAgIHRpbWVTbG90TWFuYWdlci5yZXNldCgpOwogICAgICBjb25zdCBvcGVyYXRpb24gPSB7fTsKICAgICAgbGV0IHN0b3AsIGksIGlpLCBjcywgbmFtZSwgaXNWYWxpZE5hbWU7CiAgICAgIHdoaWxlICghKHN0b3AgPSB0aW1lU2xvdE1hbmFnZXIuY2hlY2soKSkpIHsKICAgICAgICBvcGVyYXRpb24uYXJncyA9IG51bGw7CiAgICAgICAgaWYgKCFwcmVwcm9jZXNzb3IucmVhZChvcGVyYXRpb24pKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgbGV0IGFyZ3MgPSBvcGVyYXRpb24uYXJnczsKICAgICAgICBsZXQgZm4gPSBvcGVyYXRpb24uZm47CiAgICAgICAgc3dpdGNoIChmbiB8IDApIHsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnBhaW50WE9iamVjdDoKICAgICAgICAgICAgaXNWYWxpZE5hbWUgPSBhcmdzWzBdIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZTsKICAgICAgICAgICAgbmFtZSA9IGFyZ3NbMF0ubmFtZTsKICAgICAgICAgICAgaWYgKGlzVmFsaWROYW1lKSB7CiAgICAgICAgICAgICAgY29uc3QgbG9jYWxJbWFnZSA9IGxvY2FsSW1hZ2VDYWNoZS5nZXRCeU5hbWUobmFtZSk7CiAgICAgICAgICAgICAgaWYgKGxvY2FsSW1hZ2UpIHsKICAgICAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRJbWFnZU9wcyhsb2NhbEltYWdlLmZuLCBsb2NhbEltYWdlLmFyZ3MsIGxvY2FsSW1hZ2Uub3B0aW9uYWxDb250ZW50KTsKICAgICAgICAgICAgICAgIGluY3JlbWVudENhY2hlZEltYWdlTWFza0NvdW50KGxvY2FsSW1hZ2UpOwogICAgICAgICAgICAgICAgYXJncyA9IG51bGw7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbmV4dChuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZVhPYmplY3QsIHJlamVjdFhPYmplY3QpIHsKICAgICAgICAgICAgICBpZiAoIWlzVmFsaWROYW1lKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIlhPYmplY3QgbXVzdCBiZSByZWZlcnJlZCB0byBieSBuYW1lLiIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBsZXQgeG9iaiA9IHhvYmpzLmdldFJhdyhuYW1lKTsKICAgICAgICAgICAgICBpZiAoeG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgICAgICAgICAgY29uc3QgbG9jYWxJbWFnZSA9IGxvY2FsSW1hZ2VDYWNoZS5nZXRCeVJlZih4b2JqKTsKICAgICAgICAgICAgICAgIGlmIChsb2NhbEltYWdlKSB7CiAgICAgICAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRJbWFnZU9wcyhsb2NhbEltYWdlLmZuLCBsb2NhbEltYWdlLmFyZ3MsIGxvY2FsSW1hZ2Uub3B0aW9uYWxDb250ZW50KTsKICAgICAgICAgICAgICAgICAgaW5jcmVtZW50Q2FjaGVkSW1hZ2VNYXNrQ291bnQobG9jYWxJbWFnZSk7CiAgICAgICAgICAgICAgICAgIHJlc29sdmVYT2JqZWN0KCk7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNvbnN0IGdsb2JhbEltYWdlID0gc2VsZi5nbG9iYWxJbWFnZUNhY2hlLmdldERhdGEoeG9iaiwgc2VsZi5wYWdlSW5kZXgpOwogICAgICAgICAgICAgICAgaWYgKGdsb2JhbEltYWdlKSB7CiAgICAgICAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGREZXBlbmRlbmN5KGdsb2JhbEltYWdlLm9iaklkKTsKICAgICAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZEltYWdlT3BzKGdsb2JhbEltYWdlLmZuLCBnbG9iYWxJbWFnZS5hcmdzLCBnbG9iYWxJbWFnZS5vcHRpb25hbENvbnRlbnQpOwogICAgICAgICAgICAgICAgICByZXNvbHZlWE9iamVjdCgpOwogICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB4b2JqID0geHJlZi5mZXRjaCh4b2JqKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKCEoeG9iaiBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJYT2JqZWN0IHNob3VsZCBiZSBhIHN0cmVhbSIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCB0eXBlID0geG9iai5kaWN0LmdldCgiU3VidHlwZSIpOwogICAgICAgICAgICAgIGlmICghKHR5cGUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJYT2JqZWN0IHNob3VsZCBoYXZlIGEgTmFtZSBzdWJ0eXBlIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmICh0eXBlLm5hbWUgPT09ICJGb3JtIikgewogICAgICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnNhdmUoKTsKICAgICAgICAgICAgICAgIHNlbGYuYnVpbGRGb3JtWE9iamVjdChyZXNvdXJjZXMsIHhvYmosIG51bGwsIG9wZXJhdG9yTGlzdCwgdGFzaywgc3RhdGVNYW5hZ2VyLnN0YXRlLmNsb25lKCksIGxvY2FsQ29sb3JTcGFjZUNhY2hlKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnJlc3RvcmUoKTsKICAgICAgICAgICAgICAgICAgcmVzb2x2ZVhPYmplY3QoKTsKICAgICAgICAgICAgICAgIH0sIHJlamVjdFhPYmplY3QpOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZS5uYW1lID09PSAiSW1hZ2UiKSB7CiAgICAgICAgICAgICAgICBzZWxmLmJ1aWxkUGFpbnRJbWFnZVhPYmplY3QoewogICAgICAgICAgICAgICAgICByZXNvdXJjZXMsCiAgICAgICAgICAgICAgICAgIGltYWdlOiB4b2JqLAogICAgICAgICAgICAgICAgICBvcGVyYXRvckxpc3QsCiAgICAgICAgICAgICAgICAgIGNhY2hlS2V5OiBuYW1lLAogICAgICAgICAgICAgICAgICBsb2NhbEltYWdlQ2FjaGUsCiAgICAgICAgICAgICAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgICAgICAgICAgICAgICB9KS50aGVuKHJlc29sdmVYT2JqZWN0LCByZWplY3RYT2JqZWN0KTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUubmFtZSA9PT0gIlBTIikgewogICAgICAgICAgICAgICAgKDAsIF91dGlsLmluZm8pKCJJZ25vcmVkIFhPYmplY3Qgc3VidHlwZSBQUyIpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYFVuaGFuZGxlZCBYT2JqZWN0IHN1YnR5cGUgJHt0eXBlLm5hbWV9YCk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHJlc29sdmVYT2JqZWN0KCk7CiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgX3V0aWwuQWJvcnRFeGNlcHRpb24pIHsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKHNlbGYub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgWE9iamVjdDogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRocm93IHJlYXNvbjsKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRGb250OgogICAgICAgICAgICB2YXIgZm9udFNpemUgPSBhcmdzWzFdOwogICAgICAgICAgICBuZXh0KHNlbGYuaGFuZGxlU2V0Rm9udChyZXNvdXJjZXMsIGFyZ3MsIG51bGwsIG9wZXJhdG9yTGlzdCwgdGFzaywgc3RhdGVNYW5hZ2VyLnN0YXRlLCBmYWxsYmFja0ZvbnREaWN0KS50aGVuKGZ1bmN0aW9uIChsb2FkZWROYW1lKSB7CiAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZERlcGVuZGVuY3kobG9hZGVkTmFtZSk7CiAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKF91dGlsLk9QUy5zZXRGb250LCBbbG9hZGVkTmFtZSwgZm9udFNpemVdKTsKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5iZWdpblRleHQ6CiAgICAgICAgICAgIHBhcnNpbmdUZXh0ID0gdHJ1ZTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5lbmRUZXh0OgogICAgICAgICAgICBwYXJzaW5nVGV4dCA9IGZhbHNlOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmVuZElubGluZUltYWdlOgogICAgICAgICAgICB2YXIgY2FjaGVLZXkgPSBhcmdzWzBdLmNhY2hlS2V5OwogICAgICAgICAgICBpZiAoY2FjaGVLZXkpIHsKICAgICAgICAgICAgICBjb25zdCBsb2NhbEltYWdlID0gbG9jYWxJbWFnZUNhY2hlLmdldEJ5TmFtZShjYWNoZUtleSk7CiAgICAgICAgICAgICAgaWYgKGxvY2FsSW1hZ2UpIHsKICAgICAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRJbWFnZU9wcyhsb2NhbEltYWdlLmZuLCBsb2NhbEltYWdlLmFyZ3MsIGxvY2FsSW1hZ2Uub3B0aW9uYWxDb250ZW50KTsKICAgICAgICAgICAgICAgIGluY3JlbWVudENhY2hlZEltYWdlTWFza0NvdW50KGxvY2FsSW1hZ2UpOwogICAgICAgICAgICAgICAgYXJncyA9IG51bGw7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbmV4dChzZWxmLmJ1aWxkUGFpbnRJbWFnZVhPYmplY3QoewogICAgICAgICAgICAgIHJlc291cmNlcywKICAgICAgICAgICAgICBpbWFnZTogYXJnc1swXSwKICAgICAgICAgICAgICBpc0lubGluZTogdHJ1ZSwKICAgICAgICAgICAgICBvcGVyYXRvckxpc3QsCiAgICAgICAgICAgICAgY2FjaGVLZXksCiAgICAgICAgICAgICAgbG9jYWxJbWFnZUNhY2hlLAogICAgICAgICAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2hvd1RleHQ6CiAgICAgICAgICAgIGlmICghc3RhdGVNYW5hZ2VyLnN0YXRlLmZvbnQpIHsKICAgICAgICAgICAgICBzZWxmLmVuc3VyZVN0YXRlRm9udChzdGF0ZU1hbmFnZXIuc3RhdGUpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGFyZ3NbMF0gPSBzZWxmLmhhbmRsZVRleHQoYXJnc1swXSwgc3RhdGVNYW5hZ2VyLnN0YXRlKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zaG93U3BhY2VkVGV4dDoKICAgICAgICAgICAgaWYgKCFzdGF0ZU1hbmFnZXIuc3RhdGUuZm9udCkgewogICAgICAgICAgICAgIHNlbGYuZW5zdXJlU3RhdGVGb250KHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdmFyIGNvbWJpbmVkR2x5cGhzID0gW107CiAgICAgICAgICAgIHZhciBzdGF0ZSA9IHN0YXRlTWFuYWdlci5zdGF0ZTsKICAgICAgICAgICAgZm9yIChjb25zdCBhcnJJdGVtIG9mIGFyZ3NbMF0pIHsKICAgICAgICAgICAgICBpZiAodHlwZW9mIGFyckl0ZW0gPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgICAgICBjb21iaW5lZEdseXBocy5wdXNoKC4uLnNlbGYuaGFuZGxlVGV4dChhcnJJdGVtLCBzdGF0ZSkpOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGFyckl0ZW0gPT09ICJudW1iZXIiKSB7CiAgICAgICAgICAgICAgICBjb21iaW5lZEdseXBocy5wdXNoKGFyckl0ZW0pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBhcmdzWzBdID0gY29tYmluZWRHbHlwaHM7CiAgICAgICAgICAgIGZuID0gX3V0aWwuT1BTLnNob3dUZXh0OwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLm5leHRMaW5lU2hvd1RleHQ6CiAgICAgICAgICAgIGlmICghc3RhdGVNYW5hZ2VyLnN0YXRlLmZvbnQpIHsKICAgICAgICAgICAgICBzZWxmLmVuc3VyZVN0YXRlRm9udChzdGF0ZU1hbmFnZXIuc3RhdGUpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChfdXRpbC5PUFMubmV4dExpbmUpOwogICAgICAgICAgICBhcmdzWzBdID0gc2VsZi5oYW5kbGVUZXh0KGFyZ3NbMF0sIHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgIGZuID0gX3V0aWwuT1BTLnNob3dUZXh0OwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLm5leHRMaW5lU2V0U3BhY2luZ1Nob3dUZXh0OgogICAgICAgICAgICBpZiAoIXN0YXRlTWFuYWdlci5zdGF0ZS5mb250KSB7CiAgICAgICAgICAgICAgc2VsZi5lbnN1cmVTdGF0ZUZvbnQoc3RhdGVNYW5hZ2VyLnN0YXRlKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoX3V0aWwuT1BTLm5leHRMaW5lKTsKICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKF91dGlsLk9QUy5zZXRXb3JkU3BhY2luZywgW2FyZ3Muc2hpZnQoKV0pOwogICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoX3V0aWwuT1BTLnNldENoYXJTcGFjaW5nLCBbYXJncy5zaGlmdCgpXSk7CiAgICAgICAgICAgIGFyZ3NbMF0gPSBzZWxmLmhhbmRsZVRleHQoYXJnc1swXSwgc3RhdGVNYW5hZ2VyLnN0YXRlKTsKICAgICAgICAgICAgZm4gPSBfdXRpbC5PUFMuc2hvd1RleHQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0VGV4dFJlbmRlcmluZ01vZGU6CiAgICAgICAgICAgIHN0YXRlTWFuYWdlci5zdGF0ZS50ZXh0UmVuZGVyaW5nTW9kZSA9IGFyZ3NbMF07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0RmlsbENvbG9yU3BhY2U6CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICBjb25zdCBjYWNoZWRDb2xvclNwYWNlID0gX2NvbG9yc3BhY2UuQ29sb3JTcGFjZS5nZXRDYWNoZWQoYXJnc1swXSwgeHJlZiwgbG9jYWxDb2xvclNwYWNlQ2FjaGUpOwogICAgICAgICAgICAgIGlmIChjYWNoZWRDb2xvclNwYWNlKSB7CiAgICAgICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUuZmlsbENvbG9yU3BhY2UgPSBjYWNoZWRDb2xvclNwYWNlOwogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIG5leHQoc2VsZi5wYXJzZUNvbG9yU3BhY2UoewogICAgICAgICAgICAgICAgY3M6IGFyZ3NbMF0sCiAgICAgICAgICAgICAgICByZXNvdXJjZXMsCiAgICAgICAgICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgICAgICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKGNvbG9yU3BhY2UpIHsKICAgICAgICAgICAgICAgIGlmIChjb2xvclNwYWNlKSB7CiAgICAgICAgICAgICAgICAgIHN0YXRlTWFuYWdlci5zdGF0ZS5maWxsQ29sb3JTcGFjZSA9IGNvbG9yU3BhY2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0U3Ryb2tlQ29sb3JTcGFjZToKICAgICAgICAgICAgewogICAgICAgICAgICAgIGNvbnN0IGNhY2hlZENvbG9yU3BhY2UgPSBfY29sb3JzcGFjZS5Db2xvclNwYWNlLmdldENhY2hlZChhcmdzWzBdLCB4cmVmLCBsb2NhbENvbG9yU3BhY2VDYWNoZSk7CiAgICAgICAgICAgICAgaWYgKGNhY2hlZENvbG9yU3BhY2UpIHsKICAgICAgICAgICAgICAgIHN0YXRlTWFuYWdlci5zdGF0ZS5zdHJva2VDb2xvclNwYWNlID0gY2FjaGVkQ29sb3JTcGFjZTsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBuZXh0KHNlbGYucGFyc2VDb2xvclNwYWNlKHsKICAgICAgICAgICAgICAgIGNzOiBhcmdzWzBdLAogICAgICAgICAgICAgICAgcmVzb3VyY2VzLAogICAgICAgICAgICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uIChjb2xvclNwYWNlKSB7CiAgICAgICAgICAgICAgICBpZiAoY29sb3JTcGFjZSkgewogICAgICAgICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUuc3Ryb2tlQ29sb3JTcGFjZSA9IGNvbG9yU3BhY2U7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0RmlsbENvbG9yOgogICAgICAgICAgICBjcyA9IHN0YXRlTWFuYWdlci5zdGF0ZS5maWxsQ29sb3JTcGFjZTsKICAgICAgICAgICAgYXJncyA9IGNzLmdldFJnYihhcmdzLCAwKTsKICAgICAgICAgICAgZm4gPSBfdXRpbC5PUFMuc2V0RmlsbFJHQkNvbG9yOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldFN0cm9rZUNvbG9yOgogICAgICAgICAgICBjcyA9IHN0YXRlTWFuYWdlci5zdGF0ZS5zdHJva2VDb2xvclNwYWNlOwogICAgICAgICAgICBhcmdzID0gY3MuZ2V0UmdiKGFyZ3MsIDApOwogICAgICAgICAgICBmbiA9IF91dGlsLk9QUy5zZXRTdHJva2VSR0JDb2xvcjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRGaWxsR3JheToKICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnN0YXRlLmZpbGxDb2xvclNwYWNlID0gX2NvbG9yc3BhY2UuQ29sb3JTcGFjZS5zaW5nbGV0b25zLmdyYXk7CiAgICAgICAgICAgIGFyZ3MgPSBfY29sb3JzcGFjZS5Db2xvclNwYWNlLnNpbmdsZXRvbnMuZ3JheS5nZXRSZ2IoYXJncywgMCk7CiAgICAgICAgICAgIGZuID0gX3V0aWwuT1BTLnNldEZpbGxSR0JDb2xvcjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRTdHJva2VHcmF5OgogICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUuc3Ryb2tlQ29sb3JTcGFjZSA9IF9jb2xvcnNwYWNlLkNvbG9yU3BhY2Uuc2luZ2xldG9ucy5ncmF5OwogICAgICAgICAgICBhcmdzID0gX2NvbG9yc3BhY2UuQ29sb3JTcGFjZS5zaW5nbGV0b25zLmdyYXkuZ2V0UmdiKGFyZ3MsIDApOwogICAgICAgICAgICBmbiA9IF91dGlsLk9QUy5zZXRTdHJva2VSR0JDb2xvcjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRGaWxsQ01ZS0NvbG9yOgogICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUuZmlsbENvbG9yU3BhY2UgPSBfY29sb3JzcGFjZS5Db2xvclNwYWNlLnNpbmdsZXRvbnMuY215azsKICAgICAgICAgICAgYXJncyA9IF9jb2xvcnNwYWNlLkNvbG9yU3BhY2Uuc2luZ2xldG9ucy5jbXlrLmdldFJnYihhcmdzLCAwKTsKICAgICAgICAgICAgZm4gPSBfdXRpbC5PUFMuc2V0RmlsbFJHQkNvbG9yOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldFN0cm9rZUNNWUtDb2xvcjoKICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnN0YXRlLnN0cm9rZUNvbG9yU3BhY2UgPSBfY29sb3JzcGFjZS5Db2xvclNwYWNlLnNpbmdsZXRvbnMuY215azsKICAgICAgICAgICAgYXJncyA9IF9jb2xvcnNwYWNlLkNvbG9yU3BhY2Uuc2luZ2xldG9ucy5jbXlrLmdldFJnYihhcmdzLCAwKTsKICAgICAgICAgICAgZm4gPSBfdXRpbC5PUFMuc2V0U3Ryb2tlUkdCQ29sb3I7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0RmlsbFJHQkNvbG9yOgogICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUuZmlsbENvbG9yU3BhY2UgPSBfY29sb3JzcGFjZS5Db2xvclNwYWNlLnNpbmdsZXRvbnMucmdiOwogICAgICAgICAgICBhcmdzID0gX2NvbG9yc3BhY2UuQ29sb3JTcGFjZS5zaW5nbGV0b25zLnJnYi5nZXRSZ2IoYXJncywgMCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0U3Ryb2tlUkdCQ29sb3I6CiAgICAgICAgICAgIHN0YXRlTWFuYWdlci5zdGF0ZS5zdHJva2VDb2xvclNwYWNlID0gX2NvbG9yc3BhY2UuQ29sb3JTcGFjZS5zaW5nbGV0b25zLnJnYjsKICAgICAgICAgICAgYXJncyA9IF9jb2xvcnNwYWNlLkNvbG9yU3BhY2Uuc2luZ2xldG9ucy5yZ2IuZ2V0UmdiKGFyZ3MsIDApOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldEZpbGxDb2xvck46CiAgICAgICAgICAgIGNzID0gc3RhdGVNYW5hZ2VyLnN0YXRlLmZpbGxDb2xvclNwYWNlOwogICAgICAgICAgICBpZiAoY3MubmFtZSA9PT0gIlBhdHRlcm4iKSB7CiAgICAgICAgICAgICAgbmV4dChzZWxmLmhhbmRsZUNvbG9yTihvcGVyYXRvckxpc3QsIF91dGlsLk9QUy5zZXRGaWxsQ29sb3JOLCBhcmdzLCBjcywgcGF0dGVybnMsIHJlc291cmNlcywgdGFzaywgbG9jYWxDb2xvclNwYWNlQ2FjaGUsIGxvY2FsVGlsaW5nUGF0dGVybkNhY2hlLCBsb2NhbFNoYWRpbmdQYXR0ZXJuQ2FjaGUpKTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYXJncyA9IGNzLmdldFJnYihhcmdzLCAwKTsKICAgICAgICAgICAgZm4gPSBfdXRpbC5PUFMuc2V0RmlsbFJHQkNvbG9yOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldFN0cm9rZUNvbG9yTjoKICAgICAgICAgICAgY3MgPSBzdGF0ZU1hbmFnZXIuc3RhdGUuc3Ryb2tlQ29sb3JTcGFjZTsKICAgICAgICAgICAgaWYgKGNzLm5hbWUgPT09ICJQYXR0ZXJuIikgewogICAgICAgICAgICAgIG5leHQoc2VsZi5oYW5kbGVDb2xvck4ob3BlcmF0b3JMaXN0LCBfdXRpbC5PUFMuc2V0U3Ryb2tlQ29sb3JOLCBhcmdzLCBjcywgcGF0dGVybnMsIHJlc291cmNlcywgdGFzaywgbG9jYWxDb2xvclNwYWNlQ2FjaGUsIGxvY2FsVGlsaW5nUGF0dGVybkNhY2hlLCBsb2NhbFNoYWRpbmdQYXR0ZXJuQ2FjaGUpKTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYXJncyA9IGNzLmdldFJnYihhcmdzLCAwKTsKICAgICAgICAgICAgZm4gPSBfdXRpbC5PUFMuc2V0U3Ryb2tlUkdCQ29sb3I7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2hhZGluZ0ZpbGw6CiAgICAgICAgICAgIHZhciBzaGFkaW5nUmVzID0gcmVzb3VyY2VzLmdldCgiU2hhZGluZyIpOwogICAgICAgICAgICBpZiAoIXNoYWRpbmdSZXMpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIk5vIHNoYWRpbmcgcmVzb3VyY2UgZm91bmQiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgc2hhZGluZyA9IHNoYWRpbmdSZXMuZ2V0KGFyZ3NbMF0ubmFtZSk7CiAgICAgICAgICAgIGlmICghc2hhZGluZykgewogICAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiTm8gc2hhZGluZyBvYmplY3QgZm91bmQiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBwYXR0ZXJuSWQgPSBzZWxmLnBhcnNlU2hhZGluZyh7CiAgICAgICAgICAgICAgc2hhZGluZywKICAgICAgICAgICAgICByZXNvdXJjZXMsCiAgICAgICAgICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUsCiAgICAgICAgICAgICAgbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBhcmdzID0gW3BhdHRlcm5JZF07CiAgICAgICAgICAgIGZuID0gX3V0aWwuT1BTLnNoYWRpbmdGaWxsOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldEdTdGF0ZToKICAgICAgICAgICAgaXNWYWxpZE5hbWUgPSBhcmdzWzBdIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZTsKICAgICAgICAgICAgbmFtZSA9IGFyZ3NbMF0ubmFtZTsKICAgICAgICAgICAgaWYgKGlzVmFsaWROYW1lKSB7CiAgICAgICAgICAgICAgY29uc3QgbG9jYWxHU3RhdGVPYmogPSBsb2NhbEdTdGF0ZUNhY2hlLmdldEJ5TmFtZShuYW1lKTsKICAgICAgICAgICAgICBpZiAobG9jYWxHU3RhdGVPYmopIHsKICAgICAgICAgICAgICAgIGlmIChsb2NhbEdTdGF0ZU9iai5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChfdXRpbC5PUFMuc2V0R1N0YXRlLCBbbG9jYWxHU3RhdGVPYmpdKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGFyZ3MgPSBudWxsOwogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIG5leHQobmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmVHU3RhdGUsIHJlamVjdEdTdGF0ZSkgewogICAgICAgICAgICAgIGlmICghaXNWYWxpZE5hbWUpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiR1N0YXRlIG11c3QgYmUgcmVmZXJyZWQgdG8gYnkgbmFtZS4iKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgZXh0R1N0YXRlID0gcmVzb3VyY2VzLmdldCgiRXh0R1N0YXRlIik7CiAgICAgICAgICAgICAgaWYgKCEoZXh0R1N0YXRlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiRXh0R1N0YXRlIHNob3VsZCBiZSBhIGRpY3Rpb25hcnkuIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNvbnN0IGdTdGF0ZSA9IGV4dEdTdGF0ZS5nZXQobmFtZSk7CiAgICAgICAgICAgICAgaWYgKCEoZ1N0YXRlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiR1N0YXRlIHNob3VsZCBiZSBhIGRpY3Rpb25hcnkuIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHNlbGYuc2V0R1N0YXRlKHsKICAgICAgICAgICAgICAgIHJlc291cmNlcywKICAgICAgICAgICAgICAgIGdTdGF0ZSwKICAgICAgICAgICAgICAgIG9wZXJhdG9yTGlzdCwKICAgICAgICAgICAgICAgIGNhY2hlS2V5OiBuYW1lLAogICAgICAgICAgICAgICAgdGFzaywKICAgICAgICAgICAgICAgIHN0YXRlTWFuYWdlciwKICAgICAgICAgICAgICAgIGxvY2FsR1N0YXRlQ2FjaGUsCiAgICAgICAgICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgICAgICAgICAgIH0pLnRoZW4ocmVzb2x2ZUdTdGF0ZSwgcmVqZWN0R1N0YXRlKTsKICAgICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBfdXRpbC5BYm9ydEV4Y2VwdGlvbikgewogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoc2VsZi5vcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBnZXRPcGVyYXRvckxpc3QgLSBpZ25vcmluZyBFeHRHU3RhdGU6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0aHJvdyByZWFzb247CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMubW92ZVRvOgogICAgICAgICAgY2FzZSBfdXRpbC5PUFMubGluZVRvOgogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuY3VydmVUbzoKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmN1cnZlVG8yOgogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuY3VydmVUbzM6CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5jbG9zZVBhdGg6CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5yZWN0YW5nbGU6CiAgICAgICAgICAgIHNlbGYuYnVpbGRQYXRoKG9wZXJhdG9yTGlzdCwgZm4sIGFyZ3MsIHBhcnNpbmdUZXh0KTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5tYXJrUG9pbnQ6CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5tYXJrUG9pbnRQcm9wczoKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmJlZ2luQ29tcGF0OgogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuZW5kQ29tcGF0OgogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLmJlZ2luTWFya2VkQ29udGVudFByb3BzOgogICAgICAgICAgICBpZiAoIShhcmdzWzBdIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkpIHsKICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYEV4cGVjdGVkIG5hbWUgZm9yIGJlZ2luTWFya2VkQ29udGVudFByb3BzIGFyZzA9JHthcmdzWzBdfWApOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChhcmdzWzBdLm5hbWUgPT09ICJPQyIpIHsKICAgICAgICAgICAgICBuZXh0KHNlbGYucGFyc2VNYXJrZWRDb250ZW50UHJvcHMoYXJnc1sxXSwgcmVzb3VyY2VzKS50aGVuKGRhdGEgPT4gewogICAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKF91dGlsLk9QUy5iZWdpbk1hcmtlZENvbnRlbnRQcm9wcywgWyJPQyIsIGRhdGFdKTsKICAgICAgICAgICAgICB9KS5jYXRjaChyZWFzb24gPT4gewogICAgICAgICAgICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIF91dGlsLkFib3J0RXhjZXB0aW9uKSB7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIChzZWxmLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgYmVnaW5NYXJrZWRDb250ZW50UHJvcHM6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB0aHJvdyByZWFzb247CiAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBhcmdzID0gW2FyZ3NbMF0ubmFtZSwgYXJnc1sxXSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QgPyBhcmdzWzFdLmdldCgiTUNJRCIpIDogbnVsbF07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuYmVnaW5NYXJrZWRDb250ZW50OgogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuZW5kTWFya2VkQ29udGVudDoKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIGlmIChhcmdzICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgZm9yIChpID0gMCwgaWkgPSBhcmdzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgICAgICAgIGlmIChhcmdzW2ldIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKGkgPCBpaSkgewogICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJnZXRPcGVyYXRvckxpc3QgLSBpZ25vcmluZyBvcGVyYXRvcjogIiArIGZuKTsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoZm4sIGFyZ3MpOwogICAgICB9CiAgICAgIGlmIChzdG9wKSB7CiAgICAgICAgbmV4dChkZWZlcnJlZCk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNsb3NlUGVuZGluZ1Jlc3RvcmVPUFMoKTsKICAgICAgcmVzb2x2ZSgpOwogICAgfSkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIF91dGlsLkFib3J0RXhjZXB0aW9uKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICh0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKGBnZXRPcGVyYXRvckxpc3QgLSBpZ25vcmluZyBlcnJvcnMgZHVyaW5nICIke3Rhc2submFtZX0iIGAgKyBgdGFzazogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgY2xvc2VQZW5kaW5nUmVzdG9yZU9QUygpOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICB0aHJvdyByZWFzb247CiAgICB9KTsKICB9CiAgZ2V0VGV4dENvbnRlbnQoX3JlZjcpIHsKICAgIGxldCB7CiAgICAgIHN0cmVhbSwKICAgICAgdGFzaywKICAgICAgcmVzb3VyY2VzLAogICAgICBzdGF0ZU1hbmFnZXIgPSBudWxsLAogICAgICBjb21iaW5lVGV4dEl0ZW1zID0gZmFsc2UsCiAgICAgIGluY2x1ZGVNYXJrZWRDb250ZW50ID0gZmFsc2UsCiAgICAgIHNpbmssCiAgICAgIHNlZW5TdHlsZXMgPSBuZXcgU2V0KCksCiAgICAgIHZpZXdCb3gsCiAgICAgIG1hcmtlZENvbnRlbnREYXRhID0gbnVsbAogICAgfSA9IF9yZWY3OwogICAgcmVzb3VyY2VzID0gcmVzb3VyY2VzIHx8IF9wcmltaXRpdmVzLkRpY3QuZW1wdHk7CiAgICBzdGF0ZU1hbmFnZXIgPSBzdGF0ZU1hbmFnZXIgfHwgbmV3IFN0YXRlTWFuYWdlcihuZXcgVGV4dFN0YXRlKCkpOwogICAgaWYgKGluY2x1ZGVNYXJrZWRDb250ZW50KSB7CiAgICAgIG1hcmtlZENvbnRlbnREYXRhID0gbWFya2VkQ29udGVudERhdGEgfHwgewogICAgICAgIGxldmVsOiAwCiAgICAgIH07CiAgICB9CiAgICBjb25zdCB0ZXh0Q29udGVudCA9IHsKICAgICAgaXRlbXM6IFtdLAogICAgICBzdHlsZXM6IE9iamVjdC5jcmVhdGUobnVsbCkKICAgIH07CiAgICBjb25zdCB0ZXh0Q29udGVudEl0ZW0gPSB7CiAgICAgIGluaXRpYWxpemVkOiBmYWxzZSwKICAgICAgc3RyOiBbXSwKICAgICAgdG90YWxXaWR0aDogMCwKICAgICAgdG90YWxIZWlnaHQ6IDAsCiAgICAgIHdpZHRoOiAwLAogICAgICBoZWlnaHQ6IDAsCiAgICAgIHZlcnRpY2FsOiBmYWxzZSwKICAgICAgcHJldlRyYW5zZm9ybTogbnVsbCwKICAgICAgdGV4dEFkdmFuY2VTY2FsZTogMCwKICAgICAgc3BhY2VJbkZsb3dNaW46IDAsCiAgICAgIHNwYWNlSW5GbG93TWF4OiAwLAogICAgICB0cmFja2luZ1NwYWNlTWluOiBJbmZpbml0eSwKICAgICAgbmVnYXRpdmVTcGFjZU1heDogLUluZmluaXR5LAogICAgICBub3RBU3BhY2U6IC1JbmZpbml0eSwKICAgICAgdHJhbnNmb3JtOiBudWxsLAogICAgICBmb250TmFtZTogbnVsbCwKICAgICAgaGFzRU9MOiBmYWxzZQogICAgfTsKICAgIGNvbnN0IHR3b0xhc3RDaGFycyA9IFsiICIsICIgIl07CiAgICBsZXQgdHdvTGFzdENoYXJzUG9zID0gMDsKICAgIGZ1bmN0aW9uIHNhdmVMYXN0Q2hhcihjaGFyKSB7CiAgICAgIGNvbnN0IG5leHRQb3MgPSAodHdvTGFzdENoYXJzUG9zICsgMSkgJSAyOwogICAgICBjb25zdCByZXQgPSB0d29MYXN0Q2hhcnNbdHdvTGFzdENoYXJzUG9zXSAhPT0gIiAiICYmIHR3b0xhc3RDaGFyc1tuZXh0UG9zXSA9PT0gIiAiOwogICAgICB0d29MYXN0Q2hhcnNbdHdvTGFzdENoYXJzUG9zXSA9IGNoYXI7CiAgICAgIHR3b0xhc3RDaGFyc1BvcyA9IG5leHRQb3M7CiAgICAgIHJldHVybiByZXQ7CiAgICB9CiAgICBmdW5jdGlvbiByZXNldExhc3RDaGFycygpIHsKICAgICAgdHdvTGFzdENoYXJzWzBdID0gdHdvTGFzdENoYXJzWzFdID0gIiAiOwogICAgICB0d29MYXN0Q2hhcnNQb3MgPSAwOwogICAgfQogICAgY29uc3QgVFJBQ0tJTkdfU1BBQ0VfRkFDVE9SID0gMC4xMDI7CiAgICBjb25zdCBOT1RfQV9TUEFDRV9GQUNUT1IgPSAwLjAzOwogICAgY29uc3QgTkVHQVRJVkVfU1BBQ0VfRkFDVE9SID0gLTAuMjsKICAgIGNvbnN0IFNQQUNFX0lOX0ZMT1dfTUlOX0ZBQ1RPUiA9IDAuMTAyOwogICAgY29uc3QgU1BBQ0VfSU5fRkxPV19NQVhfRkFDVE9SID0gMC42OwogICAgY29uc3QgVkVSVElDQUxfU0hJRlRfUkFUSU8gPSAwLjI1OwogICAgY29uc3Qgc2VsZiA9IHRoaXM7CiAgICBjb25zdCB4cmVmID0gdGhpcy54cmVmOwogICAgY29uc3Qgc2hvd1NwYWNlZFRleHRCdWZmZXIgPSBbXTsKICAgIGxldCB4b2JqcyA9IG51bGw7CiAgICBjb25zdCBlbXB0eVhPYmplY3RDYWNoZSA9IG5ldyBfaW1hZ2VfdXRpbHMuTG9jYWxJbWFnZUNhY2hlKCk7CiAgICBjb25zdCBlbXB0eUdTdGF0ZUNhY2hlID0gbmV3IF9pbWFnZV91dGlscy5Mb2NhbEdTdGF0ZUNhY2hlKCk7CiAgICBjb25zdCBwcmVwcm9jZXNzb3IgPSBuZXcgRXZhbHVhdG9yUHJlcHJvY2Vzc29yKHN0cmVhbSwgeHJlZiwgc3RhdGVNYW5hZ2VyKTsKICAgIGxldCB0ZXh0U3RhdGU7CiAgICBmdW5jdGlvbiBnZXRDdXJyZW50VGV4dFRyYW5zZm9ybSgpIHsKICAgICAgY29uc3QgZm9udCA9IHRleHRTdGF0ZS5mb250OwogICAgICBjb25zdCB0c20gPSBbdGV4dFN0YXRlLmZvbnRTaXplICogdGV4dFN0YXRlLnRleHRIU2NhbGUsIDAsIDAsIHRleHRTdGF0ZS5mb250U2l6ZSwgMCwgdGV4dFN0YXRlLnRleHRSaXNlXTsKICAgICAgaWYgKGZvbnQuaXNUeXBlM0ZvbnQgJiYgKHRleHRTdGF0ZS5mb250U2l6ZSA8PSAxIHx8IGZvbnQuaXNDaGFyQkJveCkgJiYgISgwLCBfdXRpbC5pc0FycmF5RXF1YWwpKHRleHRTdGF0ZS5mb250TWF0cml4LCBfdXRpbC5GT05UX0lERU5USVRZX01BVFJJWCkpIHsKICAgICAgICBjb25zdCBnbHlwaEhlaWdodCA9IGZvbnQuYmJveFszXSAtIGZvbnQuYmJveFsxXTsKICAgICAgICBpZiAoZ2x5cGhIZWlnaHQgPiAwKSB7CiAgICAgICAgICB0c21bM10gKj0gZ2x5cGhIZWlnaHQgKiB0ZXh0U3RhdGUuZm9udE1hdHJpeFszXTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIF91dGlsLlV0aWwudHJhbnNmb3JtKHRleHRTdGF0ZS5jdG0sIF91dGlsLlV0aWwudHJhbnNmb3JtKHRleHRTdGF0ZS50ZXh0TWF0cml4LCB0c20pKTsKICAgIH0KICAgIGZ1bmN0aW9uIGVuc3VyZVRleHRDb250ZW50SXRlbSgpIHsKICAgICAgaWYgKHRleHRDb250ZW50SXRlbS5pbml0aWFsaXplZCkgewogICAgICAgIHJldHVybiB0ZXh0Q29udGVudEl0ZW07CiAgICAgIH0KICAgICAgY29uc3QgewogICAgICAgIGZvbnQsCiAgICAgICAgbG9hZGVkTmFtZQogICAgICB9ID0gdGV4dFN0YXRlOwogICAgICBpZiAoIXNlZW5TdHlsZXMuaGFzKGxvYWRlZE5hbWUpKSB7CiAgICAgICAgc2VlblN0eWxlcy5hZGQobG9hZGVkTmFtZSk7CiAgICAgICAgdGV4dENvbnRlbnQuc3R5bGVzW2xvYWRlZE5hbWVdID0gewogICAgICAgICAgZm9udEZhbWlseTogZm9udC5mYWxsYmFja05hbWUsCiAgICAgICAgICBhc2NlbnQ6IGZvbnQuYXNjZW50LAogICAgICAgICAgZGVzY2VudDogZm9udC5kZXNjZW50LAogICAgICAgICAgdmVydGljYWw6IGZvbnQudmVydGljYWwKICAgICAgICB9OwogICAgICB9CiAgICAgIHRleHRDb250ZW50SXRlbS5mb250TmFtZSA9IGxvYWRlZE5hbWU7CiAgICAgIGNvbnN0IHRybSA9IHRleHRDb250ZW50SXRlbS50cmFuc2Zvcm0gPSBnZXRDdXJyZW50VGV4dFRyYW5zZm9ybSgpOwogICAgICBpZiAoIWZvbnQudmVydGljYWwpIHsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0ud2lkdGggPSB0ZXh0Q29udGVudEl0ZW0udG90YWxXaWR0aCA9IDA7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLmhlaWdodCA9IHRleHRDb250ZW50SXRlbS50b3RhbEhlaWdodCA9IE1hdGguaHlwb3QodHJtWzJdLCB0cm1bM10pOwogICAgICAgIHRleHRDb250ZW50SXRlbS52ZXJ0aWNhbCA9IGZhbHNlOwogICAgICB9IGVsc2UgewogICAgICAgIHRleHRDb250ZW50SXRlbS53aWR0aCA9IHRleHRDb250ZW50SXRlbS50b3RhbFdpZHRoID0gTWF0aC5oeXBvdCh0cm1bMF0sIHRybVsxXSk7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLmhlaWdodCA9IHRleHRDb250ZW50SXRlbS50b3RhbEhlaWdodCA9IDA7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLnZlcnRpY2FsID0gdHJ1ZTsKICAgICAgfQogICAgICBjb25zdCBzY2FsZUxpbmVYID0gTWF0aC5oeXBvdCh0ZXh0U3RhdGUudGV4dExpbmVNYXRyaXhbMF0sIHRleHRTdGF0ZS50ZXh0TGluZU1hdHJpeFsxXSk7CiAgICAgIGNvbnN0IHNjYWxlQ3RtWCA9IE1hdGguaHlwb3QodGV4dFN0YXRlLmN0bVswXSwgdGV4dFN0YXRlLmN0bVsxXSk7CiAgICAgIHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlID0gc2NhbGVDdG1YICogc2NhbGVMaW5lWDsKICAgICAgY29uc3QgewogICAgICAgIGZvbnRTaXplCiAgICAgIH0gPSB0ZXh0U3RhdGU7CiAgICAgIHRleHRDb250ZW50SXRlbS50cmFja2luZ1NwYWNlTWluID0gZm9udFNpemUgKiBUUkFDS0lOR19TUEFDRV9GQUNUT1I7CiAgICAgIHRleHRDb250ZW50SXRlbS5ub3RBU3BhY2UgPSBmb250U2l6ZSAqIE5PVF9BX1NQQUNFX0ZBQ1RPUjsKICAgICAgdGV4dENvbnRlbnRJdGVtLm5lZ2F0aXZlU3BhY2VNYXggPSBmb250U2l6ZSAqIE5FR0FUSVZFX1NQQUNFX0ZBQ1RPUjsKICAgICAgdGV4dENvbnRlbnRJdGVtLnNwYWNlSW5GbG93TWluID0gZm9udFNpemUgKiBTUEFDRV9JTl9GTE9XX01JTl9GQUNUT1I7CiAgICAgIHRleHRDb250ZW50SXRlbS5zcGFjZUluRmxvd01heCA9IGZvbnRTaXplICogU1BBQ0VfSU5fRkxPV19NQVhfRkFDVE9SOwogICAgICB0ZXh0Q29udGVudEl0ZW0uaGFzRU9MID0gZmFsc2U7CiAgICAgIHRleHRDb250ZW50SXRlbS5pbml0aWFsaXplZCA9IHRydWU7CiAgICAgIHJldHVybiB0ZXh0Q29udGVudEl0ZW07CiAgICB9CiAgICBmdW5jdGlvbiB1cGRhdGVBZHZhbmNlU2NhbGUoKSB7CiAgICAgIGlmICghdGV4dENvbnRlbnRJdGVtLmluaXRpYWxpemVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNvbnN0IHNjYWxlTGluZVggPSBNYXRoLmh5cG90KHRleHRTdGF0ZS50ZXh0TGluZU1hdHJpeFswXSwgdGV4dFN0YXRlLnRleHRMaW5lTWF0cml4WzFdKTsKICAgICAgY29uc3Qgc2NhbGVDdG1YID0gTWF0aC5oeXBvdCh0ZXh0U3RhdGUuY3RtWzBdLCB0ZXh0U3RhdGUuY3RtWzFdKTsKICAgICAgY29uc3Qgc2NhbGVGYWN0b3IgPSBzY2FsZUN0bVggKiBzY2FsZUxpbmVYOwogICAgICBpZiAoc2NhbGVGYWN0b3IgPT09IHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICghdGV4dENvbnRlbnRJdGVtLnZlcnRpY2FsKSB7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLnRvdGFsV2lkdGggKz0gdGV4dENvbnRlbnRJdGVtLndpZHRoICogdGV4dENvbnRlbnRJdGVtLnRleHRBZHZhbmNlU2NhbGU7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLndpZHRoID0gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0udG90YWxIZWlnaHQgKz0gdGV4dENvbnRlbnRJdGVtLmhlaWdodCAqIHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlOwogICAgICAgIHRleHRDb250ZW50SXRlbS5oZWlnaHQgPSAwOwogICAgICB9CiAgICAgIHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlID0gc2NhbGVGYWN0b3I7CiAgICB9CiAgICBmdW5jdGlvbiBydW5CaWRpVHJhbnNmb3JtKHRleHRDaHVuaykgewogICAgICBjb25zdCB0ZXh0ID0gdGV4dENodW5rLnN0ci5qb2luKCIiKTsKICAgICAgY29uc3QgYmlkaVJlc3VsdCA9ICgwLCBfYmlkaS5iaWRpKSh0ZXh0LCAtMSwgdGV4dENodW5rLnZlcnRpY2FsKTsKICAgICAgcmV0dXJuIHsKICAgICAgICBzdHI6IGJpZGlSZXN1bHQuc3RyLAogICAgICAgIGRpcjogYmlkaVJlc3VsdC5kaXIsCiAgICAgICAgd2lkdGg6IE1hdGguYWJzKHRleHRDaHVuay50b3RhbFdpZHRoKSwKICAgICAgICBoZWlnaHQ6IE1hdGguYWJzKHRleHRDaHVuay50b3RhbEhlaWdodCksCiAgICAgICAgdHJhbnNmb3JtOiB0ZXh0Q2h1bmsudHJhbnNmb3JtLAogICAgICAgIGZvbnROYW1lOiB0ZXh0Q2h1bmsuZm9udE5hbWUsCiAgICAgICAgaGFzRU9MOiB0ZXh0Q2h1bmsuaGFzRU9MCiAgICAgIH07CiAgICB9CiAgICBmdW5jdGlvbiBoYW5kbGVTZXRGb250KGZvbnROYW1lLCBmb250UmVmKSB7CiAgICAgIHJldHVybiBzZWxmLmxvYWRGb250KGZvbnROYW1lLCBmb250UmVmLCByZXNvdXJjZXMpLnRoZW4oZnVuY3Rpb24gKHRyYW5zbGF0ZWQpIHsKICAgICAgICBpZiAoIXRyYW5zbGF0ZWQuZm9udC5pc1R5cGUzRm9udCkgewogICAgICAgICAgcmV0dXJuIHRyYW5zbGF0ZWQ7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0cmFuc2xhdGVkLmxvYWRUeXBlM0RhdGEoc2VsZiwgcmVzb3VyY2VzLCB0YXNrKS5jYXRjaChmdW5jdGlvbiAoKSB7fSkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gdHJhbnNsYXRlZDsKICAgICAgICB9KTsKICAgICAgfSkudGhlbihmdW5jdGlvbiAodHJhbnNsYXRlZCkgewogICAgICAgIHRleHRTdGF0ZS5sb2FkZWROYW1lID0gdHJhbnNsYXRlZC5sb2FkZWROYW1lOwogICAgICAgIHRleHRTdGF0ZS5mb250ID0gdHJhbnNsYXRlZC5mb250OwogICAgICAgIHRleHRTdGF0ZS5mb250TWF0cml4ID0gdHJhbnNsYXRlZC5mb250LmZvbnRNYXRyaXggfHwgX3V0aWwuRk9OVF9JREVOVElUWV9NQVRSSVg7CiAgICAgIH0pOwogICAgfQogICAgZnVuY3Rpb24gYXBwbHlJbnZlcnNlUm90YXRpb24oeCwgeSwgbWF0cml4KSB7CiAgICAgIGNvbnN0IHNjYWxlID0gTWF0aC5oeXBvdChtYXRyaXhbMF0sIG1hdHJpeFsxXSk7CiAgICAgIHJldHVybiBbKG1hdHJpeFswXSAqIHggKyBtYXRyaXhbMV0gKiB5KSAvIHNjYWxlLCAobWF0cml4WzJdICogeCArIG1hdHJpeFszXSAqIHkpIC8gc2NhbGVdOwogICAgfQogICAgZnVuY3Rpb24gY29tcGFyZVdpdGhMYXN0UG9zaXRpb24oKSB7CiAgICAgIGNvbnN0IGN1cnJlbnRUcmFuc2Zvcm0gPSBnZXRDdXJyZW50VGV4dFRyYW5zZm9ybSgpOwogICAgICBsZXQgcG9zWCA9IGN1cnJlbnRUcmFuc2Zvcm1bNF07CiAgICAgIGxldCBwb3NZID0gY3VycmVudFRyYW5zZm9ybVs1XTsKICAgICAgY29uc3Qgc2hpZnRlZFggPSBwb3NYIC0gdmlld0JveFswXTsKICAgICAgY29uc3Qgc2hpZnRlZFkgPSBwb3NZIC0gdmlld0JveFsxXTsKICAgICAgaWYgKHNoaWZ0ZWRYIDwgMCB8fCBzaGlmdGVkWCA+IHZpZXdCb3hbMl0gfHwgc2hpZnRlZFkgPCAwIHx8IHNoaWZ0ZWRZID4gdmlld0JveFszXSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAoIWNvbWJpbmVUZXh0SXRlbXMgfHwgIXRleHRTdGF0ZS5mb250IHx8ICF0ZXh0Q29udGVudEl0ZW0ucHJldlRyYW5zZm9ybSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGxldCBsYXN0UG9zWCA9IHRleHRDb250ZW50SXRlbS5wcmV2VHJhbnNmb3JtWzRdOwogICAgICBsZXQgbGFzdFBvc1kgPSB0ZXh0Q29udGVudEl0ZW0ucHJldlRyYW5zZm9ybVs1XTsKICAgICAgaWYgKGxhc3RQb3NYID09PSBwb3NYICYmIGxhc3RQb3NZID09PSBwb3NZKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgbGV0IHJvdGF0ZSA9IC0xOwogICAgICBpZiAoY3VycmVudFRyYW5zZm9ybVswXSAmJiBjdXJyZW50VHJhbnNmb3JtWzFdID09PSAwICYmIGN1cnJlbnRUcmFuc2Zvcm1bMl0gPT09IDApIHsKICAgICAgICByb3RhdGUgPSBjdXJyZW50VHJhbnNmb3JtWzBdID4gMCA/IDAgOiAxODA7CiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFRyYW5zZm9ybVsxXSAmJiBjdXJyZW50VHJhbnNmb3JtWzBdID09PSAwICYmIGN1cnJlbnRUcmFuc2Zvcm1bM10gPT09IDApIHsKICAgICAgICByb3RhdGUgPSBjdXJyZW50VHJhbnNmb3JtWzFdID4gMCA/IDkwIDogMjcwOwogICAgICB9CiAgICAgIHN3aXRjaCAocm90YXRlKSB7CiAgICAgICAgY2FzZSAwOgogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA5MDoKICAgICAgICAgIFtwb3NYLCBwb3NZXSA9IFtwb3NZLCBwb3NYXTsKICAgICAgICAgIFtsYXN0UG9zWCwgbGFzdFBvc1ldID0gW2xhc3RQb3NZLCBsYXN0UG9zWF07CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDE4MDoKICAgICAgICAgIFtwb3NYLCBwb3NZLCBsYXN0UG9zWCwgbGFzdFBvc1ldID0gWy1wb3NYLCAtcG9zWSwgLWxhc3RQb3NYLCAtbGFzdFBvc1ldOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyNzA6CiAgICAgICAgICBbcG9zWCwgcG9zWV0gPSBbLXBvc1ksIC1wb3NYXTsKICAgICAgICAgIFtsYXN0UG9zWCwgbGFzdFBvc1ldID0gWy1sYXN0UG9zWSwgLWxhc3RQb3NYXTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBbcG9zWCwgcG9zWV0gPSBhcHBseUludmVyc2VSb3RhdGlvbihwb3NYLCBwb3NZLCBjdXJyZW50VHJhbnNmb3JtKTsKICAgICAgICAgIFtsYXN0UG9zWCwgbGFzdFBvc1ldID0gYXBwbHlJbnZlcnNlUm90YXRpb24obGFzdFBvc1gsIGxhc3RQb3NZLCB0ZXh0Q29udGVudEl0ZW0ucHJldlRyYW5zZm9ybSk7CiAgICAgIH0KICAgICAgaWYgKHRleHRTdGF0ZS5mb250LnZlcnRpY2FsKSB7CiAgICAgICAgY29uc3QgYWR2YW5jZVkgPSAobGFzdFBvc1kgLSBwb3NZKSAvIHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlOwogICAgICAgIGNvbnN0IGFkdmFuY2VYID0gcG9zWCAtIGxhc3RQb3NYOwogICAgICAgIGNvbnN0IHRleHRPcmllbnRhdGlvbiA9IE1hdGguc2lnbih0ZXh0Q29udGVudEl0ZW0uaGVpZ2h0KTsKICAgICAgICBpZiAoYWR2YW5jZVkgPCB0ZXh0T3JpZW50YXRpb24gKiB0ZXh0Q29udGVudEl0ZW0ubmVnYXRpdmVTcGFjZU1heCkgewogICAgICAgICAgaWYgKE1hdGguYWJzKGFkdmFuY2VYKSA+IDAuNSAqIHRleHRDb250ZW50SXRlbS53aWR0aCkgewogICAgICAgICAgICBhcHBlbmRFT0woKTsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICB9CiAgICAgICAgICByZXNldExhc3RDaGFycygpOwogICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICBpZiAoTWF0aC5hYnMoYWR2YW5jZVgpID4gdGV4dENvbnRlbnRJdGVtLndpZHRoKSB7CiAgICAgICAgICBhcHBlbmRFT0woKTsKICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICBpZiAoYWR2YW5jZVkgPD0gdGV4dE9yaWVudGF0aW9uICogdGV4dENvbnRlbnRJdGVtLm5vdEFTcGFjZSkgewogICAgICAgICAgcmVzZXRMYXN0Q2hhcnMoKTsKICAgICAgICB9CiAgICAgICAgaWYgKGFkdmFuY2VZIDw9IHRleHRPcmllbnRhdGlvbiAqIHRleHRDb250ZW50SXRlbS50cmFja2luZ1NwYWNlTWluKSB7CiAgICAgICAgICB0ZXh0Q29udGVudEl0ZW0uaGVpZ2h0ICs9IGFkdmFuY2VZOwogICAgICAgIH0gZWxzZSBpZiAoIWFkZEZha2VTcGFjZXMoYWR2YW5jZVksIHRleHRDb250ZW50SXRlbS5wcmV2VHJhbnNmb3JtLCB0ZXh0T3JpZW50YXRpb24pKSB7CiAgICAgICAgICBpZiAodGV4dENvbnRlbnRJdGVtLnN0ci5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgcmVzZXRMYXN0Q2hhcnMoKTsKICAgICAgICAgICAgdGV4dENvbnRlbnQuaXRlbXMucHVzaCh7CiAgICAgICAgICAgICAgc3RyOiAiICIsCiAgICAgICAgICAgICAgZGlyOiAibHRyIiwKICAgICAgICAgICAgICB3aWR0aDogMCwKICAgICAgICAgICAgICBoZWlnaHQ6IE1hdGguYWJzKGFkdmFuY2VZKSwKICAgICAgICAgICAgICB0cmFuc2Zvcm06IHRleHRDb250ZW50SXRlbS5wcmV2VHJhbnNmb3JtLAogICAgICAgICAgICAgIGZvbnROYW1lOiB0ZXh0Q29udGVudEl0ZW0uZm9udE5hbWUsCiAgICAgICAgICAgICAgaGFzRU9MOiBmYWxzZQogICAgICAgICAgICB9KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRleHRDb250ZW50SXRlbS5oZWlnaHQgKz0gYWR2YW5jZVk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChNYXRoLmFicyhhZHZhbmNlWCkgPiB0ZXh0Q29udGVudEl0ZW0ud2lkdGggKiBWRVJUSUNBTF9TSElGVF9SQVRJTykgewogICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgY29uc3QgYWR2YW5jZVggPSAocG9zWCAtIGxhc3RQb3NYKSAvIHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlOwogICAgICBjb25zdCBhZHZhbmNlWSA9IHBvc1kgLSBsYXN0UG9zWTsKICAgICAgY29uc3QgdGV4dE9yaWVudGF0aW9uID0gTWF0aC5zaWduKHRleHRDb250ZW50SXRlbS53aWR0aCk7CiAgICAgIGlmIChhZHZhbmNlWCA8IHRleHRPcmllbnRhdGlvbiAqIHRleHRDb250ZW50SXRlbS5uZWdhdGl2ZVNwYWNlTWF4KSB7CiAgICAgICAgaWYgKE1hdGguYWJzKGFkdmFuY2VZKSA+IDAuNSAqIHRleHRDb250ZW50SXRlbS5oZWlnaHQpIHsKICAgICAgICAgIGFwcGVuZEVPTCgpOwogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIHJlc2V0TGFzdENoYXJzKCk7CiAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoTWF0aC5hYnMoYWR2YW5jZVkpID4gdGV4dENvbnRlbnRJdGVtLmhlaWdodCkgewogICAgICAgIGFwcGVuZEVPTCgpOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmIChhZHZhbmNlWCA8PSB0ZXh0T3JpZW50YXRpb24gKiB0ZXh0Q29udGVudEl0ZW0ubm90QVNwYWNlKSB7CiAgICAgICAgcmVzZXRMYXN0Q2hhcnMoKTsKICAgICAgfQogICAgICBpZiAoYWR2YW5jZVggPD0gdGV4dE9yaWVudGF0aW9uICogdGV4dENvbnRlbnRJdGVtLnRyYWNraW5nU3BhY2VNaW4pIHsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0ud2lkdGggKz0gYWR2YW5jZVg7CiAgICAgIH0gZWxzZSBpZiAoIWFkZEZha2VTcGFjZXMoYWR2YW5jZVgsIHRleHRDb250ZW50SXRlbS5wcmV2VHJhbnNmb3JtLCB0ZXh0T3JpZW50YXRpb24pKSB7CiAgICAgICAgaWYgKHRleHRDb250ZW50SXRlbS5zdHIubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXNldExhc3RDaGFycygpOwogICAgICAgICAgdGV4dENvbnRlbnQuaXRlbXMucHVzaCh7CiAgICAgICAgICAgIHN0cjogIiAiLAogICAgICAgICAgICBkaXI6ICJsdHIiLAogICAgICAgICAgICB3aWR0aDogTWF0aC5hYnMoYWR2YW5jZVgpLAogICAgICAgICAgICBoZWlnaHQ6IDAsCiAgICAgICAgICAgIHRyYW5zZm9ybTogdGV4dENvbnRlbnRJdGVtLnByZXZUcmFuc2Zvcm0sCiAgICAgICAgICAgIGZvbnROYW1lOiB0ZXh0Q29udGVudEl0ZW0uZm9udE5hbWUsCiAgICAgICAgICAgIGhhc0VPTDogZmFsc2UKICAgICAgICAgIH0pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0ZXh0Q29udGVudEl0ZW0ud2lkdGggKz0gYWR2YW5jZVg7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChNYXRoLmFicyhhZHZhbmNlWSkgPiB0ZXh0Q29udGVudEl0ZW0uaGVpZ2h0ICogVkVSVElDQUxfU0hJRlRfUkFUSU8pIHsKICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICB9CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgZnVuY3Rpb24gYnVpbGRUZXh0Q29udGVudEl0ZW0oX3JlZjgpIHsKICAgICAgbGV0IHsKICAgICAgICBjaGFycywKICAgICAgICBleHRyYVNwYWNpbmcKICAgICAgfSA9IF9yZWY4OwogICAgICBjb25zdCBmb250ID0gdGV4dFN0YXRlLmZvbnQ7CiAgICAgIGlmICghY2hhcnMpIHsKICAgICAgICBjb25zdCBjaGFyU3BhY2luZyA9IHRleHRTdGF0ZS5jaGFyU3BhY2luZyArIGV4dHJhU3BhY2luZzsKICAgICAgICBpZiAoY2hhclNwYWNpbmcpIHsKICAgICAgICAgIGlmICghZm9udC52ZXJ0aWNhbCkgewogICAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dE1hdHJpeChjaGFyU3BhY2luZyAqIHRleHRTdGF0ZS50ZXh0SFNjYWxlLCAwKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRleHRTdGF0ZS50cmFuc2xhdGVUZXh0TWF0cml4KDAsIC1jaGFyU3BhY2luZyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBjb25zdCBnbHlwaHMgPSBmb250LmNoYXJzVG9HbHlwaHMoY2hhcnMpOwogICAgICBjb25zdCBzY2FsZSA9IHRleHRTdGF0ZS5mb250TWF0cml4WzBdICogdGV4dFN0YXRlLmZvbnRTaXplOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBnbHlwaHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnN0IGdseXBoID0gZ2x5cGhzW2ldOwogICAgICAgIGNvbnN0IHsKICAgICAgICAgIGNhdGVnb3J5CiAgICAgICAgfSA9IGdseXBoOwogICAgICAgIGlmIChjYXRlZ29yeS5pc0ludmlzaWJsZUZvcm1hdE1hcmspIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBsZXQgY2hhclNwYWNpbmcgPSB0ZXh0U3RhdGUuY2hhclNwYWNpbmcgKyAoaSArIDEgPT09IGlpID8gZXh0cmFTcGFjaW5nIDogMCk7CiAgICAgICAgbGV0IGdseXBoV2lkdGggPSBnbHlwaC53aWR0aDsKICAgICAgICBpZiAoZm9udC52ZXJ0aWNhbCkgewogICAgICAgICAgZ2x5cGhXaWR0aCA9IGdseXBoLnZtZXRyaWMgPyBnbHlwaC52bWV0cmljWzBdIDogLWdseXBoV2lkdGg7CiAgICAgICAgfQogICAgICAgIGxldCBzY2FsZWREaW0gPSBnbHlwaFdpZHRoICogc2NhbGU7CiAgICAgICAgaWYgKGNhdGVnb3J5LmlzV2hpdGVzcGFjZSkgewogICAgICAgICAgaWYgKCFmb250LnZlcnRpY2FsKSB7CiAgICAgICAgICAgIGNoYXJTcGFjaW5nICs9IHNjYWxlZERpbSArIHRleHRTdGF0ZS53b3JkU3BhY2luZzsKICAgICAgICAgICAgdGV4dFN0YXRlLnRyYW5zbGF0ZVRleHRNYXRyaXgoY2hhclNwYWNpbmcgKiB0ZXh0U3RhdGUudGV4dEhTY2FsZSwgMCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBjaGFyU3BhY2luZyArPSAtc2NhbGVkRGltICsgdGV4dFN0YXRlLndvcmRTcGFjaW5nOwogICAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dE1hdHJpeCgwLCAtY2hhclNwYWNpbmcpOwogICAgICAgICAgfQogICAgICAgICAgc2F2ZUxhc3RDaGFyKCIgIik7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaWYgKCFjYXRlZ29yeS5pc1plcm9XaWR0aERpYWNyaXRpYyAmJiAhY29tcGFyZVdpdGhMYXN0UG9zaXRpb24oKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHRleHRDaHVuayA9IGVuc3VyZVRleHRDb250ZW50SXRlbSgpOwogICAgICAgIGlmIChjYXRlZ29yeS5pc1plcm9XaWR0aERpYWNyaXRpYykgewogICAgICAgICAgc2NhbGVkRGltID0gMDsKICAgICAgICB9CiAgICAgICAgaWYgKCFmb250LnZlcnRpY2FsKSB7CiAgICAgICAgICBzY2FsZWREaW0gKj0gdGV4dFN0YXRlLnRleHRIU2NhbGU7CiAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dE1hdHJpeChzY2FsZWREaW0sIDApOwogICAgICAgICAgdGV4dENodW5rLndpZHRoICs9IHNjYWxlZERpbTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGV4dFN0YXRlLnRyYW5zbGF0ZVRleHRNYXRyaXgoMCwgc2NhbGVkRGltKTsKICAgICAgICAgIHNjYWxlZERpbSA9IE1hdGguYWJzKHNjYWxlZERpbSk7CiAgICAgICAgICB0ZXh0Q2h1bmsuaGVpZ2h0ICs9IHNjYWxlZERpbTsKICAgICAgICB9CiAgICAgICAgaWYgKHNjYWxlZERpbSkgewogICAgICAgICAgdGV4dENodW5rLnByZXZUcmFuc2Zvcm0gPSBnZXRDdXJyZW50VGV4dFRyYW5zZm9ybSgpOwogICAgICAgIH0KICAgICAgICBjb25zdCBnbHlwaFVuaWNvZGUgPSBnbHlwaC5ub3JtYWxpemVkVW5pY29kZTsKICAgICAgICBpZiAoc2F2ZUxhc3RDaGFyKGdseXBoVW5pY29kZSkpIHsKICAgICAgICAgIHRleHRDaHVuay5zdHIucHVzaCgiICIpOwogICAgICAgIH0KICAgICAgICB0ZXh0Q2h1bmsuc3RyLnB1c2goZ2x5cGhVbmljb2RlKTsKICAgICAgICBpZiAoY2hhclNwYWNpbmcpIHsKICAgICAgICAgIGlmICghZm9udC52ZXJ0aWNhbCkgewogICAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dE1hdHJpeChjaGFyU3BhY2luZyAqIHRleHRTdGF0ZS50ZXh0SFNjYWxlLCAwKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRleHRTdGF0ZS50cmFuc2xhdGVUZXh0TWF0cml4KDAsIC1jaGFyU3BhY2luZyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBhcHBlbmRFT0woKSB7CiAgICAgIHJlc2V0TGFzdENoYXJzKCk7CiAgICAgIGlmICh0ZXh0Q29udGVudEl0ZW0uaW5pdGlhbGl6ZWQpIHsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0uaGFzRU9MID0gdHJ1ZTsKICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICB9IGVsc2UgewogICAgICAgIHRleHRDb250ZW50Lml0ZW1zLnB1c2goewogICAgICAgICAgc3RyOiAiIiwKICAgICAgICAgIGRpcjogImx0ciIsCiAgICAgICAgICB3aWR0aDogMCwKICAgICAgICAgIGhlaWdodDogMCwKICAgICAgICAgIHRyYW5zZm9ybTogZ2V0Q3VycmVudFRleHRUcmFuc2Zvcm0oKSwKICAgICAgICAgIGZvbnROYW1lOiB0ZXh0U3RhdGUubG9hZGVkTmFtZSwKICAgICAgICAgIGhhc0VPTDogdHJ1ZQogICAgICAgIH0pOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBhZGRGYWtlU3BhY2VzKHdpZHRoLCB0cmFuc2YsIHRleHRPcmllbnRhdGlvbikgewogICAgICBpZiAodGV4dE9yaWVudGF0aW9uICogdGV4dENvbnRlbnRJdGVtLnNwYWNlSW5GbG93TWluIDw9IHdpZHRoICYmIHdpZHRoIDw9IHRleHRPcmllbnRhdGlvbiAqIHRleHRDb250ZW50SXRlbS5zcGFjZUluRmxvd01heCkgewogICAgICAgIGlmICh0ZXh0Q29udGVudEl0ZW0uaW5pdGlhbGl6ZWQpIHsKICAgICAgICAgIHJlc2V0TGFzdENoYXJzKCk7CiAgICAgICAgICB0ZXh0Q29udGVudEl0ZW0uc3RyLnB1c2goIiAiKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGNvbnN0IGZvbnROYW1lID0gdGV4dENvbnRlbnRJdGVtLmZvbnROYW1lOwogICAgICBsZXQgaGVpZ2h0ID0gMDsKICAgICAgaWYgKHRleHRDb250ZW50SXRlbS52ZXJ0aWNhbCkgewogICAgICAgIGhlaWdodCA9IHdpZHRoOwogICAgICAgIHdpZHRoID0gMDsKICAgICAgfQogICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICByZXNldExhc3RDaGFycygpOwogICAgICB0ZXh0Q29udGVudC5pdGVtcy5wdXNoKHsKICAgICAgICBzdHI6ICIgIiwKICAgICAgICBkaXI6ICJsdHIiLAogICAgICAgIHdpZHRoOiBNYXRoLmFicyh3aWR0aCksCiAgICAgICAgaGVpZ2h0OiBNYXRoLmFicyhoZWlnaHQpLAogICAgICAgIHRyYW5zZm9ybTogdHJhbnNmIHx8IGdldEN1cnJlbnRUZXh0VHJhbnNmb3JtKCksCiAgICAgICAgZm9udE5hbWUsCiAgICAgICAgaGFzRU9MOiBmYWxzZQogICAgICB9KTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBmdW5jdGlvbiBmbHVzaFRleHRDb250ZW50SXRlbSgpIHsKICAgICAgaWYgKCF0ZXh0Q29udGVudEl0ZW0uaW5pdGlhbGl6ZWQgfHwgIXRleHRDb250ZW50SXRlbS5zdHIpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKCF0ZXh0Q29udGVudEl0ZW0udmVydGljYWwpIHsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0udG90YWxXaWR0aCArPSB0ZXh0Q29udGVudEl0ZW0ud2lkdGggKiB0ZXh0Q29udGVudEl0ZW0udGV4dEFkdmFuY2VTY2FsZTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0udG90YWxIZWlnaHQgKz0gdGV4dENvbnRlbnRJdGVtLmhlaWdodCAqIHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlOwogICAgICB9CiAgICAgIHRleHRDb250ZW50Lml0ZW1zLnB1c2gocnVuQmlkaVRyYW5zZm9ybSh0ZXh0Q29udGVudEl0ZW0pKTsKICAgICAgdGV4dENvbnRlbnRJdGVtLmluaXRpYWxpemVkID0gZmFsc2U7CiAgICAgIHRleHRDb250ZW50SXRlbS5zdHIubGVuZ3RoID0gMDsKICAgIH0KICAgIGZ1bmN0aW9uIGVucXVldWVDaHVuaygpIHsKICAgICAgbGV0IGJhdGNoID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBmYWxzZTsKICAgICAgY29uc3QgbGVuZ3RoID0gdGV4dENvbnRlbnQuaXRlbXMubGVuZ3RoOwogICAgICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmIChiYXRjaCAmJiBsZW5ndGggPCBURVhUX0NIVU5LX0JBVENIX1NJWkUpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgc2luay5lbnF1ZXVlKHRleHRDb250ZW50LCBsZW5ndGgpOwogICAgICB0ZXh0Q29udGVudC5pdGVtcyA9IFtdOwogICAgICB0ZXh0Q29udGVudC5zdHlsZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgfQogICAgY29uc3QgdGltZVNsb3RNYW5hZ2VyID0gbmV3IFRpbWVTbG90TWFuYWdlcigpOwogICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIHByb21pc2VCb2R5KHJlc29sdmUsIHJlamVjdCkgewogICAgICBjb25zdCBuZXh0ID0gZnVuY3Rpb24gKHByb21pc2UpIHsKICAgICAgICBlbnF1ZXVlQ2h1bmsodHJ1ZSk7CiAgICAgICAgUHJvbWlzZS5hbGwoW3Byb21pc2UsIHNpbmsucmVhZHldKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHByb21pc2VCb2R5KHJlc29sdmUsIHJlamVjdCk7CiAgICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgICByZWplY3QoZXgpOwogICAgICAgICAgfQogICAgICAgIH0sIHJlamVjdCk7CiAgICAgIH07CiAgICAgIHRhc2suZW5zdXJlTm90VGVybWluYXRlZCgpOwogICAgICB0aW1lU2xvdE1hbmFnZXIucmVzZXQoKTsKICAgICAgY29uc3Qgb3BlcmF0aW9uID0ge307CiAgICAgIGxldCBzdG9wLAogICAgICAgIGFyZ3MgPSBbXTsKICAgICAgd2hpbGUgKCEoc3RvcCA9IHRpbWVTbG90TWFuYWdlci5jaGVjaygpKSkgewogICAgICAgIGFyZ3MubGVuZ3RoID0gMDsKICAgICAgICBvcGVyYXRpb24uYXJncyA9IGFyZ3M7CiAgICAgICAgaWYgKCFwcmVwcm9jZXNzb3IucmVhZChvcGVyYXRpb24pKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdGV4dFN0YXRlID0gc3RhdGVNYW5hZ2VyLnN0YXRlOwogICAgICAgIGNvbnN0IGZuID0gb3BlcmF0aW9uLmZuOwogICAgICAgIGFyZ3MgPSBvcGVyYXRpb24uYXJnczsKICAgICAgICBzd2l0Y2ggKGZuIHwgMCkgewogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0Rm9udDoKICAgICAgICAgICAgdmFyIGZvbnROYW1lQXJnID0gYXJnc1swXS5uYW1lLAogICAgICAgICAgICAgIGZvbnRTaXplQXJnID0gYXJnc1sxXTsKICAgICAgICAgICAgaWYgKHRleHRTdGF0ZS5mb250ICYmIGZvbnROYW1lQXJnID09PSB0ZXh0U3RhdGUuZm9udE5hbWUgJiYgZm9udFNpemVBcmcgPT09IHRleHRTdGF0ZS5mb250U2l6ZSkgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZsdXNoVGV4dENvbnRlbnRJdGVtKCk7CiAgICAgICAgICAgIHRleHRTdGF0ZS5mb250TmFtZSA9IGZvbnROYW1lQXJnOwogICAgICAgICAgICB0ZXh0U3RhdGUuZm9udFNpemUgPSBmb250U2l6ZUFyZzsKICAgICAgICAgICAgbmV4dChoYW5kbGVTZXRGb250KGZvbnROYW1lQXJnLCBudWxsKSk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldFRleHRSaXNlOgogICAgICAgICAgICB0ZXh0U3RhdGUudGV4dFJpc2UgPSBhcmdzWzBdOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldEhTY2FsZToKICAgICAgICAgICAgdGV4dFN0YXRlLnRleHRIU2NhbGUgPSBhcmdzWzBdIC8gMTAwOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldExlYWRpbmc6CiAgICAgICAgICAgIHRleHRTdGF0ZS5sZWFkaW5nID0gYXJnc1swXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5tb3ZlVGV4dDoKICAgICAgICAgICAgdGV4dFN0YXRlLnRyYW5zbGF0ZVRleHRMaW5lTWF0cml4KGFyZ3NbMF0sIGFyZ3NbMV0pOwogICAgICAgICAgICB0ZXh0U3RhdGUudGV4dE1hdHJpeCA9IHRleHRTdGF0ZS50ZXh0TGluZU1hdHJpeC5zbGljZSgpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldExlYWRpbmdNb3ZlVGV4dDoKICAgICAgICAgICAgdGV4dFN0YXRlLmxlYWRpbmcgPSAtYXJnc1sxXTsKICAgICAgICAgICAgdGV4dFN0YXRlLnRyYW5zbGF0ZVRleHRMaW5lTWF0cml4KGFyZ3NbMF0sIGFyZ3NbMV0pOwogICAgICAgICAgICB0ZXh0U3RhdGUudGV4dE1hdHJpeCA9IHRleHRTdGF0ZS50ZXh0TGluZU1hdHJpeC5zbGljZSgpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLm5leHRMaW5lOgogICAgICAgICAgICB0ZXh0U3RhdGUuY2FycmlhZ2VSZXR1cm4oKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRUZXh0TWF0cml4OgogICAgICAgICAgICB0ZXh0U3RhdGUuc2V0VGV4dE1hdHJpeChhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdLCBhcmdzWzNdLCBhcmdzWzRdLCBhcmdzWzVdKTsKICAgICAgICAgICAgdGV4dFN0YXRlLnNldFRleHRMaW5lTWF0cml4KGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10sIGFyZ3NbNF0sIGFyZ3NbNV0pOwogICAgICAgICAgICB1cGRhdGVBZHZhbmNlU2NhbGUoKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRDaGFyU3BhY2luZzoKICAgICAgICAgICAgdGV4dFN0YXRlLmNoYXJTcGFjaW5nID0gYXJnc1swXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRXb3JkU3BhY2luZzoKICAgICAgICAgICAgdGV4dFN0YXRlLndvcmRTcGFjaW5nID0gYXJnc1swXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5iZWdpblRleHQ6CiAgICAgICAgICAgIHRleHRTdGF0ZS50ZXh0TWF0cml4ID0gX3V0aWwuSURFTlRJVFlfTUFUUklYLnNsaWNlKCk7CiAgICAgICAgICAgIHRleHRTdGF0ZS50ZXh0TGluZU1hdHJpeCA9IF91dGlsLklERU5USVRZX01BVFJJWC5zbGljZSgpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgX3V0aWwuT1BTLnNob3dTcGFjZWRUZXh0OgogICAgICAgICAgICBpZiAoIXN0YXRlTWFuYWdlci5zdGF0ZS5mb250KSB7CiAgICAgICAgICAgICAgc2VsZi5lbnN1cmVTdGF0ZUZvbnQoc3RhdGVNYW5hZ2VyLnN0YXRlKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBzcGFjZUZhY3RvciA9ICh0ZXh0U3RhdGUuZm9udC52ZXJ0aWNhbCA/IDEgOiAtMSkgKiB0ZXh0U3RhdGUuZm9udFNpemUgLyAxMDAwOwogICAgICAgICAgICBjb25zdCBlbGVtZW50cyA9IGFyZ3NbMF07CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGVsZW1lbnRzLmxlbmd0aDsgaSA8IGlpIC0gMTsgaSsrKSB7CiAgICAgICAgICAgICAgY29uc3QgaXRlbSA9IGVsZW1lbnRzW2ldOwogICAgICAgICAgICAgIGlmICh0eXBlb2YgaXRlbSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICAgIHNob3dTcGFjZWRUZXh0QnVmZmVyLnB1c2goaXRlbSk7CiAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgaXRlbSA9PT0gIm51bWJlciIgJiYgaXRlbSAhPT0gMCkgewogICAgICAgICAgICAgICAgY29uc3Qgc3RyID0gc2hvd1NwYWNlZFRleHRCdWZmZXIuam9pbigiIik7CiAgICAgICAgICAgICAgICBzaG93U3BhY2VkVGV4dEJ1ZmZlci5sZW5ndGggPSAwOwogICAgICAgICAgICAgICAgYnVpbGRUZXh0Q29udGVudEl0ZW0oewogICAgICAgICAgICAgICAgICBjaGFyczogc3RyLAogICAgICAgICAgICAgICAgICBleHRyYVNwYWNpbmc6IGl0ZW0gKiBzcGFjZUZhY3RvcgogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGl0ZW0gPSBlbGVtZW50cy5hdCgtMSk7CiAgICAgICAgICAgIGlmICh0eXBlb2YgaXRlbSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICBzaG93U3BhY2VkVGV4dEJ1ZmZlci5wdXNoKGl0ZW0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChzaG93U3BhY2VkVGV4dEJ1ZmZlci5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgY29uc3Qgc3RyID0gc2hvd1NwYWNlZFRleHRCdWZmZXIuam9pbigiIik7CiAgICAgICAgICAgICAgc2hvd1NwYWNlZFRleHRCdWZmZXIubGVuZ3RoID0gMDsKICAgICAgICAgICAgICBidWlsZFRleHRDb250ZW50SXRlbSh7CiAgICAgICAgICAgICAgICBjaGFyczogc3RyLAogICAgICAgICAgICAgICAgZXh0cmFTcGFjaW5nOiAwCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5zaG93VGV4dDoKICAgICAgICAgICAgaWYgKCFzdGF0ZU1hbmFnZXIuc3RhdGUuZm9udCkgewogICAgICAgICAgICAgIHNlbGYuZW5zdXJlU3RhdGVGb250KHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnVpbGRUZXh0Q29udGVudEl0ZW0oewogICAgICAgICAgICAgIGNoYXJzOiBhcmdzWzBdLAogICAgICAgICAgICAgIGV4dHJhU3BhY2luZzogMAogICAgICAgICAgICB9KTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5uZXh0TGluZVNob3dUZXh0OgogICAgICAgICAgICBpZiAoIXN0YXRlTWFuYWdlci5zdGF0ZS5mb250KSB7CiAgICAgICAgICAgICAgc2VsZi5lbnN1cmVTdGF0ZUZvbnQoc3RhdGVNYW5hZ2VyLnN0YXRlKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0ZXh0U3RhdGUuY2FycmlhZ2VSZXR1cm4oKTsKICAgICAgICAgICAgYnVpbGRUZXh0Q29udGVudEl0ZW0oewogICAgICAgICAgICAgIGNoYXJzOiBhcmdzWzBdLAogICAgICAgICAgICAgIGV4dHJhU3BhY2luZzogMAogICAgICAgICAgICB9KTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIF91dGlsLk9QUy5uZXh0TGluZVNldFNwYWNpbmdTaG93VGV4dDoKICAgICAgICAgICAgaWYgKCFzdGF0ZU1hbmFnZXIuc3RhdGUuZm9udCkgewogICAgICAgICAgICAgIHNlbGYuZW5zdXJlU3RhdGVGb250KHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGV4dFN0YXRlLndvcmRTcGFjaW5nID0gYXJnc1swXTsKICAgICAgICAgICAgdGV4dFN0YXRlLmNoYXJTcGFjaW5nID0gYXJnc1sxXTsKICAgICAgICAgICAgdGV4dFN0YXRlLmNhcnJpYWdlUmV0dXJuKCk7CiAgICAgICAgICAgIGJ1aWxkVGV4dENvbnRlbnRJdGVtKHsKICAgICAgICAgICAgICBjaGFyczogYXJnc1syXSwKICAgICAgICAgICAgICBleHRyYVNwYWNpbmc6IDAKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMucGFpbnRYT2JqZWN0OgogICAgICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICAgICAgICBpZiAoIXhvYmpzKSB7CiAgICAgICAgICAgICAgeG9ianMgPSByZXNvdXJjZXMuZ2V0KCJYT2JqZWN0IikgfHwgX3ByaW1pdGl2ZXMuRGljdC5lbXB0eTsKICAgICAgICAgICAgfQogICAgICAgICAgICB2YXIgaXNWYWxpZE5hbWUgPSBhcmdzWzBdIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZTsKICAgICAgICAgICAgdmFyIG5hbWUgPSBhcmdzWzBdLm5hbWU7CiAgICAgICAgICAgIGlmIChpc1ZhbGlkTmFtZSAmJiBlbXB0eVhPYmplY3RDYWNoZS5nZXRCeU5hbWUobmFtZSkpIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBuZXh0KG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlWE9iamVjdCwgcmVqZWN0WE9iamVjdCkgewogICAgICAgICAgICAgIGlmICghaXNWYWxpZE5hbWUpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiWE9iamVjdCBtdXN0IGJlIHJlZmVycmVkIHRvIGJ5IG5hbWUuIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGxldCB4b2JqID0geG9ianMuZ2V0UmF3KG5hbWUpOwogICAgICAgICAgICAgIGlmICh4b2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgICAgICAgICAgICBpZiAoZW1wdHlYT2JqZWN0Q2FjaGUuZ2V0QnlSZWYoeG9iaikpIHsKICAgICAgICAgICAgICAgICAgcmVzb2x2ZVhPYmplY3QoKTsKICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgY29uc3QgZ2xvYmFsSW1hZ2UgPSBzZWxmLmdsb2JhbEltYWdlQ2FjaGUuZ2V0RGF0YSh4b2JqLCBzZWxmLnBhZ2VJbmRleCk7CiAgICAgICAgICAgICAgICBpZiAoZ2xvYmFsSW1hZ2UpIHsKICAgICAgICAgICAgICAgICAgcmVzb2x2ZVhPYmplY3QoKTsKICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgeG9iaiA9IHhyZWYuZmV0Y2goeG9iaik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmICghKHhvYmogaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiWE9iamVjdCBzaG91bGQgYmUgYSBzdHJlYW0iKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgdHlwZSA9IHhvYmouZGljdC5nZXQoIlN1YnR5cGUiKTsKICAgICAgICAgICAgICBpZiAoISh0eXBlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiWE9iamVjdCBzaG91bGQgaGF2ZSBhIE5hbWUgc3VidHlwZSIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAodHlwZS5uYW1lICE9PSAiRm9ybSIpIHsKICAgICAgICAgICAgICAgIGVtcHR5WE9iamVjdENhY2hlLnNldChuYW1lLCB4b2JqLmRpY3Qub2JqSWQsIHRydWUpOwogICAgICAgICAgICAgICAgcmVzb2x2ZVhPYmplY3QoKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgY3VycmVudFN0YXRlID0gc3RhdGVNYW5hZ2VyLnN0YXRlLmNsb25lKCk7CiAgICAgICAgICAgICAgY29uc3QgeE9ialN0YXRlTWFuYWdlciA9IG5ldyBTdGF0ZU1hbmFnZXIoY3VycmVudFN0YXRlKTsKICAgICAgICAgICAgICBjb25zdCBtYXRyaXggPSB4b2JqLmRpY3QuZ2V0QXJyYXkoIk1hdHJpeCIpOwogICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KG1hdHJpeCkgJiYgbWF0cml4Lmxlbmd0aCA9PT0gNikgewogICAgICAgICAgICAgICAgeE9ialN0YXRlTWFuYWdlci50cmFuc2Zvcm0obWF0cml4KTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgZW5xdWV1ZUNodW5rKCk7CiAgICAgICAgICAgICAgY29uc3Qgc2lua1dyYXBwZXIgPSB7CiAgICAgICAgICAgICAgICBlbnF1ZXVlSW52b2tlZDogZmFsc2UsCiAgICAgICAgICAgICAgICBlbnF1ZXVlKGNodW5rLCBzaXplKSB7CiAgICAgICAgICAgICAgICAgIHRoaXMuZW5xdWV1ZUludm9rZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgICBzaW5rLmVucXVldWUoY2h1bmssIHNpemUpOwogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIGdldCBkZXNpcmVkU2l6ZSgpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuIHNpbmsuZGVzaXJlZFNpemU7CiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgZ2V0IHJlYWR5KCkgewogICAgICAgICAgICAgICAgICByZXR1cm4gc2luay5yZWFkeTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgIHNlbGYuZ2V0VGV4dENvbnRlbnQoewogICAgICAgICAgICAgICAgc3RyZWFtOiB4b2JqLAogICAgICAgICAgICAgICAgdGFzaywKICAgICAgICAgICAgICAgIHJlc291cmNlczogeG9iai5kaWN0LmdldCgiUmVzb3VyY2VzIikgfHwgcmVzb3VyY2VzLAogICAgICAgICAgICAgICAgc3RhdGVNYW5hZ2VyOiB4T2JqU3RhdGVNYW5hZ2VyLAogICAgICAgICAgICAgICAgY29tYmluZVRleHRJdGVtcywKICAgICAgICAgICAgICAgIGluY2x1ZGVNYXJrZWRDb250ZW50LAogICAgICAgICAgICAgICAgc2luazogc2lua1dyYXBwZXIsCiAgICAgICAgICAgICAgICBzZWVuU3R5bGVzLAogICAgICAgICAgICAgICAgdmlld0JveCwKICAgICAgICAgICAgICAgIG1hcmtlZENvbnRlbnREYXRhCiAgICAgICAgICAgICAgfSkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICBpZiAoIXNpbmtXcmFwcGVyLmVucXVldWVJbnZva2VkKSB7CiAgICAgICAgICAgICAgICAgIGVtcHR5WE9iamVjdENhY2hlLnNldChuYW1lLCB4b2JqLmRpY3Qub2JqSWQsIHRydWUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmVzb2x2ZVhPYmplY3QoKTsKICAgICAgICAgICAgICB9LCByZWplY3RYT2JqZWN0KTsKICAgICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBfdXRpbC5BYm9ydEV4Y2VwdGlvbikgewogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoc2VsZi5vcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBnZXRUZXh0Q29udGVudCAtIGlnbm9yaW5nIFhPYmplY3Q6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0aHJvdyByZWFzb247CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0R1N0YXRlOgogICAgICAgICAgICBpc1ZhbGlkTmFtZSA9IGFyZ3NbMF0gaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lOwogICAgICAgICAgICBuYW1lID0gYXJnc1swXS5uYW1lOwogICAgICAgICAgICBpZiAoaXNWYWxpZE5hbWUgJiYgZW1wdHlHU3RhdGVDYWNoZS5nZXRCeU5hbWUobmFtZSkpIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBuZXh0KG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlR1N0YXRlLCByZWplY3RHU3RhdGUpIHsKICAgICAgICAgICAgICBpZiAoIWlzVmFsaWROYW1lKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkdTdGF0ZSBtdXN0IGJlIHJlZmVycmVkIHRvIGJ5IG5hbWUuIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNvbnN0IGV4dEdTdGF0ZSA9IHJlc291cmNlcy5nZXQoIkV4dEdTdGF0ZSIpOwogICAgICAgICAgICAgIGlmICghKGV4dEdTdGF0ZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkV4dEdTdGF0ZSBzaG91bGQgYmUgYSBkaWN0aW9uYXJ5LiIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCBnU3RhdGUgPSBleHRHU3RhdGUuZ2V0KG5hbWUpOwogICAgICAgICAgICAgIGlmICghKGdTdGF0ZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkdTdGF0ZSBzaG91bGQgYmUgYSBkaWN0aW9uYXJ5LiIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCBnU3RhdGVGb250ID0gZ1N0YXRlLmdldCgiRm9udCIpOwogICAgICAgICAgICAgIGlmICghZ1N0YXRlRm9udCkgewogICAgICAgICAgICAgICAgZW1wdHlHU3RhdGVDYWNoZS5zZXQobmFtZSwgZ1N0YXRlLm9iaklkLCB0cnVlKTsKICAgICAgICAgICAgICAgIHJlc29sdmVHU3RhdGUoKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICAgICAgICB0ZXh0U3RhdGUuZm9udE5hbWUgPSBudWxsOwogICAgICAgICAgICAgIHRleHRTdGF0ZS5mb250U2l6ZSA9IGdTdGF0ZUZvbnRbMV07CiAgICAgICAgICAgICAgaGFuZGxlU2V0Rm9udChudWxsLCBnU3RhdGVGb250WzBdKS50aGVuKHJlc29sdmVHU3RhdGUsIHJlamVjdEdTdGF0ZSk7CiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgX3V0aWwuQWJvcnRFeGNlcHRpb24pIHsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKHNlbGYub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgZ2V0VGV4dENvbnRlbnQgLSBpZ25vcmluZyBFeHRHU3RhdGU6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0aHJvdyByZWFzb247CiAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuYmVnaW5NYXJrZWRDb250ZW50OgogICAgICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICAgICAgICBpZiAoaW5jbHVkZU1hcmtlZENvbnRlbnQpIHsKICAgICAgICAgICAgICBtYXJrZWRDb250ZW50RGF0YS5sZXZlbCsrOwogICAgICAgICAgICAgIHRleHRDb250ZW50Lml0ZW1zLnB1c2goewogICAgICAgICAgICAgICAgdHlwZTogImJlZ2luTWFya2VkQ29udGVudCIsCiAgICAgICAgICAgICAgICB0YWc6IGFyZ3NbMF0gaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lID8gYXJnc1swXS5uYW1lIDogbnVsbAogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuYmVnaW5NYXJrZWRDb250ZW50UHJvcHM6CiAgICAgICAgICAgIGZsdXNoVGV4dENvbnRlbnRJdGVtKCk7CiAgICAgICAgICAgIGlmIChpbmNsdWRlTWFya2VkQ29udGVudCkgewogICAgICAgICAgICAgIG1hcmtlZENvbnRlbnREYXRhLmxldmVsKys7CiAgICAgICAgICAgICAgbGV0IG1jaWQgPSBudWxsOwogICAgICAgICAgICAgIGlmIChhcmdzWzFdIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICAgICAgICAgICAgbWNpZCA9IGFyZ3NbMV0uZ2V0KCJNQ0lEIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRleHRDb250ZW50Lml0ZW1zLnB1c2goewogICAgICAgICAgICAgICAgdHlwZTogImJlZ2luTWFya2VkQ29udGVudFByb3BzIiwKICAgICAgICAgICAgICAgIGlkOiBOdW1iZXIuaXNJbnRlZ2VyKG1jaWQpID8gYCR7c2VsZi5pZEZhY3RvcnkuZ2V0UGFnZU9iaklkKCl9X21jaWQke21jaWR9YCA6IG51bGwsCiAgICAgICAgICAgICAgICB0YWc6IGFyZ3NbMF0gaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lID8gYXJnc1swXS5uYW1lIDogbnVsbAogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBfdXRpbC5PUFMuZW5kTWFya2VkQ29udGVudDoKICAgICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICAgICAgaWYgKGluY2x1ZGVNYXJrZWRDb250ZW50KSB7CiAgICAgICAgICAgICAgaWYgKG1hcmtlZENvbnRlbnREYXRhLmxldmVsID09PSAwKSB7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgbWFya2VkQ29udGVudERhdGEubGV2ZWwtLTsKICAgICAgICAgICAgICB0ZXh0Q29udGVudC5pdGVtcy5wdXNoKHsKICAgICAgICAgICAgICAgIHR5cGU6ICJlbmRNYXJrZWRDb250ZW50IgogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAodGV4dENvbnRlbnQuaXRlbXMubGVuZ3RoID49IHNpbmsuZGVzaXJlZFNpemUpIHsKICAgICAgICAgIHN0b3AgPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChzdG9wKSB7CiAgICAgICAgbmV4dChkZWZlcnJlZCk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGZsdXNoVGV4dENvbnRlbnRJdGVtKCk7CiAgICAgIGVucXVldWVDaHVuaygpOwogICAgICByZXNvbHZlKCk7CiAgICB9KS5jYXRjaChyZWFzb24gPT4gewogICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgX3V0aWwuQWJvcnRFeGNlcHRpb24pIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKHRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYGdldFRleHRDb250ZW50IC0gaWdub3JpbmcgZXJyb3JzIGR1cmluZyAiJHt0YXNrLm5hbWV9IiBgICsgYHRhc2s6ICIke3JlYXNvbn0iLmApOwogICAgICAgIGZsdXNoVGV4dENvbnRlbnRJdGVtKCk7CiAgICAgICAgZW5xdWV1ZUNodW5rKCk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHRocm93IHJlYXNvbjsKICAgIH0pOwogIH0KICBleHRyYWN0RGF0YVN0cnVjdHVyZXMoZGljdCwgYmFzZURpY3QsIHByb3BlcnRpZXMpIHsKICAgIGNvbnN0IHhyZWYgPSB0aGlzLnhyZWY7CiAgICBsZXQgY2lkVG9HaWRCeXRlczsKICAgIGNvbnN0IHRvVW5pY29kZVByb21pc2UgPSB0aGlzLnJlYWRUb1VuaWNvZGUocHJvcGVydGllcy50b1VuaWNvZGUgfHwgZGljdC5nZXQoIlRvVW5pY29kZSIpIHx8IGJhc2VEaWN0LmdldCgiVG9Vbmljb2RlIikpOwogICAgaWYgKHByb3BlcnRpZXMuY29tcG9zaXRlKSB7CiAgICAgIGNvbnN0IGNpZFN5c3RlbUluZm8gPSBkaWN0LmdldCgiQ0lEU3lzdGVtSW5mbyIpOwogICAgICBpZiAoY2lkU3lzdGVtSW5mbyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpIHsKICAgICAgICBwcm9wZXJ0aWVzLmNpZFN5c3RlbUluZm8gPSB7CiAgICAgICAgICByZWdpc3RyeTogKDAsIF91dGlsLnN0cmluZ1RvUERGU3RyaW5nKShjaWRTeXN0ZW1JbmZvLmdldCgiUmVnaXN0cnkiKSksCiAgICAgICAgICBvcmRlcmluZzogKDAsIF91dGlsLnN0cmluZ1RvUERGU3RyaW5nKShjaWRTeXN0ZW1JbmZvLmdldCgiT3JkZXJpbmciKSksCiAgICAgICAgICBzdXBwbGVtZW50OiBjaWRTeXN0ZW1JbmZvLmdldCgiU3VwcGxlbWVudCIpCiAgICAgICAgfTsKICAgICAgfQogICAgICB0cnkgewogICAgICAgIGNvbnN0IGNpZFRvR2lkTWFwID0gZGljdC5nZXQoIkNJRFRvR0lETWFwIik7CiAgICAgICAgaWYgKGNpZFRvR2lkTWFwIGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0pIHsKICAgICAgICAgIGNpZFRvR2lkQnl0ZXMgPSBjaWRUb0dpZE1hcC5nZXRCeXRlcygpOwogICAgICAgIH0KICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAgIHRocm93IGV4OwogICAgICAgIH0KICAgICAgICAoMCwgX3V0aWwud2FybikoYGV4dHJhY3REYXRhU3RydWN0dXJlcyAtIGlnbm9yaW5nIENJRFRvR0lETWFwIGRhdGE6ICIke2V4fSIuYCk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGRpZmZlcmVuY2VzID0gW107CiAgICBsZXQgYmFzZUVuY29kaW5nTmFtZSA9IG51bGw7CiAgICBsZXQgZW5jb2Rpbmc7CiAgICBpZiAoZGljdC5oYXMoIkVuY29kaW5nIikpIHsKICAgICAgZW5jb2RpbmcgPSBkaWN0LmdldCgiRW5jb2RpbmciKTsKICAgICAgaWYgKGVuY29kaW5nIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICAgIGJhc2VFbmNvZGluZ05hbWUgPSBlbmNvZGluZy5nZXQoIkJhc2VFbmNvZGluZyIpOwogICAgICAgIGJhc2VFbmNvZGluZ05hbWUgPSBiYXNlRW5jb2RpbmdOYW1lIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSA/IGJhc2VFbmNvZGluZ05hbWUubmFtZSA6IG51bGw7CiAgICAgICAgaWYgKGVuY29kaW5nLmhhcygiRGlmZmVyZW5jZXMiKSkgewogICAgICAgICAgY29uc3QgZGlmZkVuY29kaW5nID0gZW5jb2RpbmcuZ2V0KCJEaWZmZXJlbmNlcyIpOwogICAgICAgICAgbGV0IGluZGV4ID0gMDsKICAgICAgICAgIGZvciAoY29uc3QgZW50cnkgb2YgZGlmZkVuY29kaW5nKSB7CiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSB4cmVmLmZldGNoSWZSZWYoZW50cnkpOwogICAgICAgICAgICBpZiAodHlwZW9mIGRhdGEgPT09ICJudW1iZXIiKSB7CiAgICAgICAgICAgICAgaW5kZXggPSBkYXRhOwogICAgICAgICAgICB9IGVsc2UgaWYgKGRhdGEgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgICAgICAgICAgZGlmZmVyZW5jZXNbaW5kZXgrK10gPSBkYXRhLm5hbWU7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBJbnZhbGlkIGVudHJ5IGluICdEaWZmZXJlbmNlcycgYXJyYXk6ICR7ZGF0YX1gKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChlbmNvZGluZyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgICBiYXNlRW5jb2RpbmdOYW1lID0gZW5jb2RpbmcubmFtZTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBtc2cgPSAiRW5jb2RpbmcgaXMgbm90IGEgTmFtZSBub3IgYSBEaWN0IjsKICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihtc2cpOwogICAgICAgIH0KICAgICAgICAoMCwgX3V0aWwud2FybikobXNnKTsKICAgICAgfQogICAgICBpZiAoYmFzZUVuY29kaW5nTmFtZSAhPT0gIk1hY1JvbWFuRW5jb2RpbmciICYmIGJhc2VFbmNvZGluZ05hbWUgIT09ICJNYWNFeHBlcnRFbmNvZGluZyIgJiYgYmFzZUVuY29kaW5nTmFtZSAhPT0gIldpbkFuc2lFbmNvZGluZyIpIHsKICAgICAgICBiYXNlRW5jb2RpbmdOYW1lID0gbnVsbDsKICAgICAgfQogICAgfQogICAgaWYgKGJhc2VFbmNvZGluZ05hbWUpIHsKICAgICAgcHJvcGVydGllcy5kZWZhdWx0RW5jb2RpbmcgPSAoMCwgX2VuY29kaW5ncy5nZXRFbmNvZGluZykoYmFzZUVuY29kaW5nTmFtZSk7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBpc1N5bWJvbGljRm9udCA9ICEhKHByb3BlcnRpZXMuZmxhZ3MgJiBfZm9udHNfdXRpbHMuRm9udEZsYWdzLlN5bWJvbGljKTsKICAgICAgY29uc3QgaXNOb25zeW1ib2xpY0ZvbnQgPSAhIShwcm9wZXJ0aWVzLmZsYWdzICYgX2ZvbnRzX3V0aWxzLkZvbnRGbGFncy5Ob25zeW1ib2xpYyk7CiAgICAgIGVuY29kaW5nID0gX2VuY29kaW5ncy5TdGFuZGFyZEVuY29kaW5nOwogICAgICBpZiAocHJvcGVydGllcy50eXBlID09PSAiVHJ1ZVR5cGUiICYmICFpc05vbnN5bWJvbGljRm9udCkgewogICAgICAgIGVuY29kaW5nID0gX2VuY29kaW5ncy5XaW5BbnNpRW5jb2Rpbmc7CiAgICAgIH0KICAgICAgaWYgKGlzU3ltYm9saWNGb250KSB7CiAgICAgICAgZW5jb2RpbmcgPSBfZW5jb2RpbmdzLk1hY1JvbWFuRW5jb2Rpbmc7CiAgICAgICAgaWYgKCFwcm9wZXJ0aWVzLmZpbGUgfHwgcHJvcGVydGllcy5pc0ludGVybmFsRm9udCkgewogICAgICAgICAgaWYgKC9TeW1ib2wvaS50ZXN0KHByb3BlcnRpZXMubmFtZSkpIHsKICAgICAgICAgICAgZW5jb2RpbmcgPSBfZW5jb2RpbmdzLlN5bWJvbFNldEVuY29kaW5nOwogICAgICAgICAgfSBlbHNlIGlmICgvRGluZ2JhdHN8V2luZ2RpbmdzL2kudGVzdChwcm9wZXJ0aWVzLm5hbWUpKSB7CiAgICAgICAgICAgIGVuY29kaW5nID0gX2VuY29kaW5ncy5aYXBmRGluZ2JhdHNFbmNvZGluZzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgcHJvcGVydGllcy5kZWZhdWx0RW5jb2RpbmcgPSBlbmNvZGluZzsKICAgIH0KICAgIHByb3BlcnRpZXMuZGlmZmVyZW5jZXMgPSBkaWZmZXJlbmNlczsKICAgIHByb3BlcnRpZXMuYmFzZUVuY29kaW5nTmFtZSA9IGJhc2VFbmNvZGluZ05hbWU7CiAgICBwcm9wZXJ0aWVzLmhhc0VuY29kaW5nID0gISFiYXNlRW5jb2RpbmdOYW1lIHx8IGRpZmZlcmVuY2VzLmxlbmd0aCA+IDA7CiAgICBwcm9wZXJ0aWVzLmRpY3QgPSBkaWN0OwogICAgcmV0dXJuIHRvVW5pY29kZVByb21pc2UudGhlbihyZWFkVG9Vbmljb2RlID0+IHsKICAgICAgcHJvcGVydGllcy50b1VuaWNvZGUgPSByZWFkVG9Vbmljb2RlOwogICAgICByZXR1cm4gdGhpcy5idWlsZFRvVW5pY29kZShwcm9wZXJ0aWVzKTsKICAgIH0pLnRoZW4oYnVpbHRUb1VuaWNvZGUgPT4gewogICAgICBwcm9wZXJ0aWVzLnRvVW5pY29kZSA9IGJ1aWx0VG9Vbmljb2RlOwogICAgICBpZiAoY2lkVG9HaWRCeXRlcykgewogICAgICAgIHByb3BlcnRpZXMuY2lkVG9HaWRNYXAgPSB0aGlzLnJlYWRDaWRUb0dpZE1hcChjaWRUb0dpZEJ5dGVzLCBidWlsdFRvVW5pY29kZSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHByb3BlcnRpZXM7CiAgICB9KTsKICB9CiAgX3NpbXBsZUZvbnRUb1VuaWNvZGUocHJvcGVydGllcykgewogICAgbGV0IGZvcmNlR2x5cGhzID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBmYWxzZTsKICAgICgwLCBfdXRpbC5hc3NlcnQpKCFwcm9wZXJ0aWVzLmNvbXBvc2l0ZSwgIk11c3QgYmUgYSBzaW1wbGUgZm9udC4iKTsKICAgIGNvbnN0IHRvVW5pY29kZSA9IFtdOwogICAgY29uc3QgZW5jb2RpbmcgPSBwcm9wZXJ0aWVzLmRlZmF1bHRFbmNvZGluZy5zbGljZSgpOwogICAgY29uc3QgYmFzZUVuY29kaW5nTmFtZSA9IHByb3BlcnRpZXMuYmFzZUVuY29kaW5nTmFtZTsKICAgIGNvbnN0IGRpZmZlcmVuY2VzID0gcHJvcGVydGllcy5kaWZmZXJlbmNlczsKICAgIGZvciAoY29uc3QgY2hhcmNvZGUgaW4gZGlmZmVyZW5jZXMpIHsKICAgICAgY29uc3QgZ2x5cGhOYW1lID0gZGlmZmVyZW5jZXNbY2hhcmNvZGVdOwogICAgICBpZiAoZ2x5cGhOYW1lID09PSAiLm5vdGRlZiIpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBlbmNvZGluZ1tjaGFyY29kZV0gPSBnbHlwaE5hbWU7CiAgICB9CiAgICBjb25zdCBnbHlwaHNVbmljb2RlTWFwID0gKDAsIF9nbHlwaGxpc3QuZ2V0R2x5cGhzVW5pY29kZSkoKTsKICAgIGZvciAoY29uc3QgY2hhcmNvZGUgaW4gZW5jb2RpbmcpIHsKICAgICAgbGV0IGdseXBoTmFtZSA9IGVuY29kaW5nW2NoYXJjb2RlXTsKICAgICAgaWYgKGdseXBoTmFtZSA9PT0gIiIpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBsZXQgdW5pY29kZSA9IGdseXBoc1VuaWNvZGVNYXBbZ2x5cGhOYW1lXTsKICAgICAgaWYgKHVuaWNvZGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHRvVW5pY29kZVtjaGFyY29kZV0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHVuaWNvZGUpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGxldCBjb2RlID0gMDsKICAgICAgc3dpdGNoIChnbHlwaE5hbWVbMF0pIHsKICAgICAgICBjYXNlICJHIjoKICAgICAgICAgIGlmIChnbHlwaE5hbWUubGVuZ3RoID09PSAzKSB7CiAgICAgICAgICAgIGNvZGUgPSBwYXJzZUludChnbHlwaE5hbWUuc3Vic3RyaW5nKDEpLCAxNik7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJnIjoKICAgICAgICAgIGlmIChnbHlwaE5hbWUubGVuZ3RoID09PSA1KSB7CiAgICAgICAgICAgIGNvZGUgPSBwYXJzZUludChnbHlwaE5hbWUuc3Vic3RyaW5nKDEpLCAxNik7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJDIjoKICAgICAgICBjYXNlICJjIjoKICAgICAgICAgIGlmIChnbHlwaE5hbWUubGVuZ3RoID49IDMgJiYgZ2x5cGhOYW1lLmxlbmd0aCA8PSA0KSB7CiAgICAgICAgICAgIGNvbnN0IGNvZGVTdHIgPSBnbHlwaE5hbWUuc3Vic3RyaW5nKDEpOwogICAgICAgICAgICBpZiAoZm9yY2VHbHlwaHMpIHsKICAgICAgICAgICAgICBjb2RlID0gcGFyc2VJbnQoY29kZVN0ciwgMTYpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvZGUgPSArY29kZVN0cjsKICAgICAgICAgICAgaWYgKE51bWJlci5pc05hTihjb2RlKSAmJiBOdW1iZXIuaXNJbnRlZ2VyKHBhcnNlSW50KGNvZGVTdHIsIDE2KSkpIHsKICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fc2ltcGxlRm9udFRvVW5pY29kZShwcm9wZXJ0aWVzLCB0cnVlKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAidSI6CiAgICAgICAgICB1bmljb2RlID0gKDAsIF91bmljb2RlLmdldFVuaWNvZGVGb3JHbHlwaCkoZ2x5cGhOYW1lLCBnbHlwaHNVbmljb2RlTWFwKTsKICAgICAgICAgIGlmICh1bmljb2RlICE9PSAtMSkgewogICAgICAgICAgICBjb2RlID0gdW5pY29kZTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBzd2l0Y2ggKGdseXBoTmFtZSkgewogICAgICAgICAgICBjYXNlICJmX2giOgogICAgICAgICAgICBjYXNlICJmX3QiOgogICAgICAgICAgICBjYXNlICJUX2giOgogICAgICAgICAgICAgIHRvVW5pY29kZVtjaGFyY29kZV0gPSBnbHlwaE5hbWUucmVwbGFjZUFsbCgiXyIsICIiKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmIChjb2RlID4gMCAmJiBjb2RlIDw9IDB4MTBmZmZmICYmIE51bWJlci5pc0ludGVnZXIoY29kZSkpIHsKICAgICAgICBpZiAoYmFzZUVuY29kaW5nTmFtZSAmJiBjb2RlID09PSArY2hhcmNvZGUpIHsKICAgICAgICAgIGNvbnN0IGJhc2VFbmNvZGluZyA9ICgwLCBfZW5jb2RpbmdzLmdldEVuY29kaW5nKShiYXNlRW5jb2RpbmdOYW1lKTsKICAgICAgICAgIGlmIChiYXNlRW5jb2RpbmcgJiYgKGdseXBoTmFtZSA9IGJhc2VFbmNvZGluZ1tjaGFyY29kZV0pKSB7CiAgICAgICAgICAgIHRvVW5pY29kZVtjaGFyY29kZV0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGdseXBoc1VuaWNvZGVNYXBbZ2x5cGhOYW1lXSk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB0b1VuaWNvZGVbY2hhcmNvZGVdID0gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB0b1VuaWNvZGU7CiAgfQogIGFzeW5jIGJ1aWxkVG9Vbmljb2RlKHByb3BlcnRpZXMpIHsKICAgIHByb3BlcnRpZXMuaGFzSW5jbHVkZWRUb1VuaWNvZGVNYXAgPSAhIXByb3BlcnRpZXMudG9Vbmljb2RlICYmIHByb3BlcnRpZXMudG9Vbmljb2RlLmxlbmd0aCA+IDA7CiAgICBpZiAocHJvcGVydGllcy5oYXNJbmNsdWRlZFRvVW5pY29kZU1hcCkgewogICAgICBpZiAoIXByb3BlcnRpZXMuY29tcG9zaXRlICYmIHByb3BlcnRpZXMuaGFzRW5jb2RpbmcpIHsKICAgICAgICBwcm9wZXJ0aWVzLmZhbGxiYWNrVG9Vbmljb2RlID0gdGhpcy5fc2ltcGxlRm9udFRvVW5pY29kZShwcm9wZXJ0aWVzKTsKICAgICAgfQogICAgICByZXR1cm4gcHJvcGVydGllcy50b1VuaWNvZGU7CiAgICB9CiAgICBpZiAoIXByb3BlcnRpZXMuY29tcG9zaXRlKSB7CiAgICAgIHJldHVybiBuZXcgX3RvX3VuaWNvZGVfbWFwLlRvVW5pY29kZU1hcCh0aGlzLl9zaW1wbGVGb250VG9Vbmljb2RlKHByb3BlcnRpZXMpKTsKICAgIH0KICAgIGlmIChwcm9wZXJ0aWVzLmNvbXBvc2l0ZSAmJiAocHJvcGVydGllcy5jTWFwLmJ1aWx0SW5DTWFwICYmICEocHJvcGVydGllcy5jTWFwIGluc3RhbmNlb2YgX2NtYXAuSWRlbnRpdHlDTWFwKSB8fCBwcm9wZXJ0aWVzLmNpZFN5c3RlbUluZm8ucmVnaXN0cnkgPT09ICJBZG9iZSIgJiYgKHByb3BlcnRpZXMuY2lkU3lzdGVtSW5mby5vcmRlcmluZyA9PT0gIkdCMSIgfHwgcHJvcGVydGllcy5jaWRTeXN0ZW1JbmZvLm9yZGVyaW5nID09PSAiQ05TMSIgfHwgcHJvcGVydGllcy5jaWRTeXN0ZW1JbmZvLm9yZGVyaW5nID09PSAiSmFwYW4xIiB8fCBwcm9wZXJ0aWVzLmNpZFN5c3RlbUluZm8ub3JkZXJpbmcgPT09ICJLb3JlYTEiKSkpIHsKICAgICAgY29uc3QgewogICAgICAgIHJlZ2lzdHJ5LAogICAgICAgIG9yZGVyaW5nCiAgICAgIH0gPSBwcm9wZXJ0aWVzLmNpZFN5c3RlbUluZm87CiAgICAgIGNvbnN0IHVjczJDTWFwTmFtZSA9IF9wcmltaXRpdmVzLk5hbWUuZ2V0KGAke3JlZ2lzdHJ5fS0ke29yZGVyaW5nfS1VQ1MyYCk7CiAgICAgIGNvbnN0IHVjczJDTWFwID0gYXdhaXQgX2NtYXAuQ01hcEZhY3RvcnkuY3JlYXRlKHsKICAgICAgICBlbmNvZGluZzogdWNzMkNNYXBOYW1lLAogICAgICAgIGZldGNoQnVpbHRJbkNNYXA6IHRoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZCwKICAgICAgICB1c2VDTWFwOiBudWxsCiAgICAgIH0pOwogICAgICBjb25zdCB0b1VuaWNvZGUgPSBbXSwKICAgICAgICBidWYgPSBbXTsKICAgICAgcHJvcGVydGllcy5jTWFwLmZvckVhY2goZnVuY3Rpb24gKGNoYXJjb2RlLCBjaWQpIHsKICAgICAgICBpZiAoY2lkID4gMHhmZmZmKSB7CiAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIk1heCBzaXplIG9mIENJRCBpcyA2NSw1MzUiKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgdWNzMiA9IHVjczJDTWFwLmxvb2t1cChjaWQpOwogICAgICAgIGlmICh1Y3MyKSB7CiAgICAgICAgICBidWYubGVuZ3RoID0gMDsKICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHVjczIubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICAgICAgICBidWYucHVzaCgodWNzMi5jaGFyQ29kZUF0KGkpIDw8IDgpICsgdWNzMi5jaGFyQ29kZUF0KGkgKyAxKSk7CiAgICAgICAgICB9CiAgICAgICAgICB0b1VuaWNvZGVbY2hhcmNvZGVdID0gU3RyaW5nLmZyb21DaGFyQ29kZSguLi5idWYpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiBuZXcgX3RvX3VuaWNvZGVfbWFwLlRvVW5pY29kZU1hcCh0b1VuaWNvZGUpOwogICAgfQogICAgcmV0dXJuIG5ldyBfdG9fdW5pY29kZV9tYXAuSWRlbnRpdHlUb1VuaWNvZGVNYXAocHJvcGVydGllcy5maXJzdENoYXIsIHByb3BlcnRpZXMubGFzdENoYXIpOwogIH0KICByZWFkVG9Vbmljb2RlKGNtYXBPYmopIHsKICAgIGlmICghY21hcE9iaikgewogICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG51bGwpOwogICAgfQogICAgaWYgKGNtYXBPYmogaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgIHJldHVybiBfY21hcC5DTWFwRmFjdG9yeS5jcmVhdGUoewogICAgICAgIGVuY29kaW5nOiBjbWFwT2JqLAogICAgICAgIGZldGNoQnVpbHRJbkNNYXA6IHRoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZCwKICAgICAgICB1c2VDTWFwOiBudWxsCiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKGNtYXApIHsKICAgICAgICBpZiAoY21hcCBpbnN0YW5jZW9mIF9jbWFwLklkZW50aXR5Q01hcCkgewogICAgICAgICAgcmV0dXJuIG5ldyBfdG9fdW5pY29kZV9tYXAuSWRlbnRpdHlUb1VuaWNvZGVNYXAoMCwgMHhmZmZmKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBfdG9fdW5pY29kZV9tYXAuVG9Vbmljb2RlTWFwKGNtYXAuZ2V0TWFwKCkpOwogICAgICB9KTsKICAgIH0gZWxzZSBpZiAoY21hcE9iaiBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSB7CiAgICAgIHJldHVybiBfY21hcC5DTWFwRmFjdG9yeS5jcmVhdGUoewogICAgICAgIGVuY29kaW5nOiBjbWFwT2JqLAogICAgICAgIGZldGNoQnVpbHRJbkNNYXA6IHRoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZCwKICAgICAgICB1c2VDTWFwOiBudWxsCiAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKGNtYXApIHsKICAgICAgICBpZiAoY21hcCBpbnN0YW5jZW9mIF9jbWFwLklkZW50aXR5Q01hcCkgewogICAgICAgICAgcmV0dXJuIG5ldyBfdG9fdW5pY29kZV9tYXAuSWRlbnRpdHlUb1VuaWNvZGVNYXAoMCwgMHhmZmZmKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbWFwID0gbmV3IEFycmF5KGNtYXAubGVuZ3RoKTsKICAgICAgICBjbWFwLmZvckVhY2goZnVuY3Rpb24gKGNoYXJDb2RlLCB0b2tlbikgewogICAgICAgICAgaWYgKHR5cGVvZiB0b2tlbiA9PT0gIm51bWJlciIpIHsKICAgICAgICAgICAgbWFwW2NoYXJDb2RlXSA9IFN0cmluZy5mcm9tQ29kZVBvaW50KHRva2VuKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgfQogICAgICAgICAgY29uc3Qgc3RyID0gW107CiAgICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IHRva2VuLmxlbmd0aDsgayArPSAyKSB7CiAgICAgICAgICAgIGNvbnN0IHcxID0gdG9rZW4uY2hhckNvZGVBdChrKSA8PCA4IHwgdG9rZW4uY2hhckNvZGVBdChrICsgMSk7CiAgICAgICAgICAgIGlmICgodzEgJiAweGY4MDApICE9PSAweGQ4MDApIHsKICAgICAgICAgICAgICBzdHIucHVzaCh3MSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgayArPSAyOwogICAgICAgICAgICBjb25zdCB3MiA9IHRva2VuLmNoYXJDb2RlQXQoaykgPDwgOCB8IHRva2VuLmNoYXJDb2RlQXQoayArIDEpOwogICAgICAgICAgICBzdHIucHVzaCgoKHcxICYgMHgzZmYpIDw8IDEwKSArICh3MiAmIDB4M2ZmKSArIDB4MTAwMDApOwogICAgICAgICAgfQogICAgICAgICAgbWFwW2NoYXJDb2RlXSA9IFN0cmluZy5mcm9tQ29kZVBvaW50KC4uLnN0cik7CiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIG5ldyBfdG9fdW5pY29kZV9tYXAuVG9Vbmljb2RlTWFwKG1hcCk7CiAgICAgIH0sIHJlYXNvbiA9PiB7CiAgICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIF91dGlsLkFib3J0RXhjZXB0aW9uKSB7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgcmVhZFRvVW5pY29kZSAtIGlnbm9yaW5nIFRvVW5pY29kZSBkYXRhOiAiJHtyZWFzb259Ii5gKTsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgICB0aHJvdyByZWFzb247CiAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShudWxsKTsKICB9CiAgcmVhZENpZFRvR2lkTWFwKGdseXBoc0RhdGEsIHRvVW5pY29kZSkgewogICAgY29uc3QgcmVzdWx0ID0gW107CiAgICBmb3IgKGxldCBqID0gMCwgamogPSBnbHlwaHNEYXRhLmxlbmd0aDsgaiA8IGpqOyBqKyspIHsKICAgICAgY29uc3QgZ2x5cGhJRCA9IGdseXBoc0RhdGFbaisrXSA8PCA4IHwgZ2x5cGhzRGF0YVtqXTsKICAgICAgY29uc3QgY29kZSA9IGogPj4gMTsKICAgICAgaWYgKGdseXBoSUQgPT09IDAgJiYgIXRvVW5pY29kZS5oYXMoY29kZSkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICByZXN1bHRbY29kZV0gPSBnbHlwaElEOwogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9CiAgZXh0cmFjdFdpZHRocyhkaWN0LCBkZXNjcmlwdG9yLCBwcm9wZXJ0aWVzKSB7CiAgICBjb25zdCB4cmVmID0gdGhpcy54cmVmOwogICAgbGV0IGdseXBoc1dpZHRocyA9IFtdOwogICAgbGV0IGRlZmF1bHRXaWR0aCA9IDA7CiAgICBjb25zdCBnbHlwaHNWTWV0cmljcyA9IFtdOwogICAgbGV0IGRlZmF1bHRWTWV0cmljczsKICAgIGxldCBpLCBpaSwgaiwgamosIHN0YXJ0LCBjb2RlLCB3aWR0aHM7CiAgICBpZiAocHJvcGVydGllcy5jb21wb3NpdGUpIHsKICAgICAgZGVmYXVsdFdpZHRoID0gZGljdC5oYXMoIkRXIikgPyBkaWN0LmdldCgiRFciKSA6IDEwMDA7CiAgICAgIHdpZHRocyA9IGRpY3QuZ2V0KCJXIik7CiAgICAgIGlmICh3aWR0aHMpIHsKICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IHdpZHRocy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICBzdGFydCA9IHhyZWYuZmV0Y2hJZlJlZih3aWR0aHNbaSsrXSk7CiAgICAgICAgICBjb2RlID0geHJlZi5mZXRjaElmUmVmKHdpZHRoc1tpXSk7CiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjb2RlKSkgewogICAgICAgICAgICBmb3IgKGogPSAwLCBqaiA9IGNvZGUubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICAgICAgICAgIGdseXBoc1dpZHRoc1tzdGFydCsrXSA9IHhyZWYuZmV0Y2hJZlJlZihjb2RlW2pdKTsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgY29uc3Qgd2lkdGggPSB4cmVmLmZldGNoSWZSZWYod2lkdGhzWysraV0pOwogICAgICAgICAgICBmb3IgKGogPSBzdGFydDsgaiA8PSBjb2RlOyBqKyspIHsKICAgICAgICAgICAgICBnbHlwaHNXaWR0aHNbal0gPSB3aWR0aDsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBpZiAocHJvcGVydGllcy52ZXJ0aWNhbCkgewogICAgICAgIGxldCB2bWV0cmljcyA9IGRpY3QuZ2V0QXJyYXkoIkRXMiIpIHx8IFs4ODAsIC0xMDAwXTsKICAgICAgICBkZWZhdWx0Vk1ldHJpY3MgPSBbdm1ldHJpY3NbMV0sIGRlZmF1bHRXaWR0aCAqIDAuNSwgdm1ldHJpY3NbMF1dOwogICAgICAgIHZtZXRyaWNzID0gZGljdC5nZXQoIlcyIik7CiAgICAgICAgaWYgKHZtZXRyaWNzKSB7CiAgICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IHZtZXRyaWNzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgICAgc3RhcnQgPSB4cmVmLmZldGNoSWZSZWYodm1ldHJpY3NbaSsrXSk7CiAgICAgICAgICAgIGNvZGUgPSB4cmVmLmZldGNoSWZSZWYodm1ldHJpY3NbaV0pOwogICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjb2RlKSkgewogICAgICAgICAgICAgIGZvciAoaiA9IDAsIGpqID0gY29kZS5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgICAgICAgICAgICBnbHlwaHNWTWV0cmljc1tzdGFydCsrXSA9IFt4cmVmLmZldGNoSWZSZWYoY29kZVtqKytdKSwgeHJlZi5mZXRjaElmUmVmKGNvZGVbaisrXSksIHhyZWYuZmV0Y2hJZlJlZihjb2RlW2pdKV07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGNvbnN0IHZtZXRyaWMgPSBbeHJlZi5mZXRjaElmUmVmKHZtZXRyaWNzWysraV0pLCB4cmVmLmZldGNoSWZSZWYodm1ldHJpY3NbKytpXSksIHhyZWYuZmV0Y2hJZlJlZih2bWV0cmljc1srK2ldKV07CiAgICAgICAgICAgICAgZm9yIChqID0gc3RhcnQ7IGogPD0gY29kZTsgaisrKSB7CiAgICAgICAgICAgICAgICBnbHlwaHNWTWV0cmljc1tqXSA9IHZtZXRyaWM7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBmaXJzdENoYXIgPSBwcm9wZXJ0aWVzLmZpcnN0Q2hhcjsKICAgICAgd2lkdGhzID0gZGljdC5nZXQoIldpZHRocyIpOwogICAgICBpZiAod2lkdGhzKSB7CiAgICAgICAgaiA9IGZpcnN0Q2hhcjsKICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IHdpZHRocy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICBnbHlwaHNXaWR0aHNbaisrXSA9IHhyZWYuZmV0Y2hJZlJlZih3aWR0aHNbaV0pOwogICAgICAgIH0KICAgICAgICBkZWZhdWx0V2lkdGggPSBwYXJzZUZsb2F0KGRlc2NyaXB0b3IuZ2V0KCJNaXNzaW5nV2lkdGgiKSkgfHwgMDsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBiYXNlRm9udE5hbWUgPSBkaWN0LmdldCgiQmFzZUZvbnQiKTsKICAgICAgICBpZiAoYmFzZUZvbnROYW1lIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICAgICAgY29uc3QgbWV0cmljcyA9IHRoaXMuZ2V0QmFzZUZvbnRNZXRyaWNzKGJhc2VGb250TmFtZS5uYW1lKTsKICAgICAgICAgIGdseXBoc1dpZHRocyA9IHRoaXMuYnVpbGRDaGFyQ29kZVRvV2lkdGgobWV0cmljcy53aWR0aHMsIHByb3BlcnRpZXMpOwogICAgICAgICAgZGVmYXVsdFdpZHRoID0gbWV0cmljcy5kZWZhdWx0V2lkdGg7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBsZXQgaXNNb25vc3BhY2UgPSB0cnVlOwogICAgbGV0IGZpcnN0V2lkdGggPSBkZWZhdWx0V2lkdGg7CiAgICBmb3IgKGNvbnN0IGdseXBoIGluIGdseXBoc1dpZHRocykgewogICAgICBjb25zdCBnbHlwaFdpZHRoID0gZ2x5cGhzV2lkdGhzW2dseXBoXTsKICAgICAgaWYgKCFnbHlwaFdpZHRoKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKCFmaXJzdFdpZHRoKSB7CiAgICAgICAgZmlyc3RXaWR0aCA9IGdseXBoV2lkdGg7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGZpcnN0V2lkdGggIT09IGdseXBoV2lkdGgpIHsKICAgICAgICBpc01vbm9zcGFjZSA9IGZhbHNlOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBpZiAoaXNNb25vc3BhY2UpIHsKICAgICAgcHJvcGVydGllcy5mbGFncyB8PSBfZm9udHNfdXRpbHMuRm9udEZsYWdzLkZpeGVkUGl0Y2g7CiAgICB9CiAgICBwcm9wZXJ0aWVzLmRlZmF1bHRXaWR0aCA9IGRlZmF1bHRXaWR0aDsKICAgIHByb3BlcnRpZXMud2lkdGhzID0gZ2x5cGhzV2lkdGhzOwogICAgcHJvcGVydGllcy5kZWZhdWx0Vk1ldHJpY3MgPSBkZWZhdWx0Vk1ldHJpY3M7CiAgICBwcm9wZXJ0aWVzLnZtZXRyaWNzID0gZ2x5cGhzVk1ldHJpY3M7CiAgfQogIGlzU2VyaWZGb250KGJhc2VGb250TmFtZSkgewogICAgY29uc3QgZm9udE5hbWVXb1N0eWxlID0gYmFzZUZvbnROYW1lLnNwbGl0KCItIilbMF07CiAgICByZXR1cm4gZm9udE5hbWVXb1N0eWxlIGluICgwLCBfc3RhbmRhcmRfZm9udHMuZ2V0U2VyaWZGb250cykoKSB8fCAvc2VyaWYvZ2kudGVzdChmb250TmFtZVdvU3R5bGUpOwogIH0KICBnZXRCYXNlRm9udE1ldHJpY3MobmFtZSkgewogICAgbGV0IGRlZmF1bHRXaWR0aCA9IDA7CiAgICBsZXQgd2lkdGhzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGxldCBtb25vc3BhY2UgPSBmYWxzZTsKICAgIGNvbnN0IHN0ZEZvbnRNYXAgPSAoMCwgX3N0YW5kYXJkX2ZvbnRzLmdldFN0ZEZvbnRNYXApKCk7CiAgICBsZXQgbG9va3VwTmFtZSA9IHN0ZEZvbnRNYXBbbmFtZV0gfHwgbmFtZTsKICAgIGNvbnN0IE1ldHJpY3MgPSAoMCwgX21ldHJpY3MuZ2V0TWV0cmljcykoKTsKICAgIGlmICghKGxvb2t1cE5hbWUgaW4gTWV0cmljcykpIHsKICAgICAgaWYgKHRoaXMuaXNTZXJpZkZvbnQobmFtZSkpIHsKICAgICAgICBsb29rdXBOYW1lID0gIlRpbWVzLVJvbWFuIjsKICAgICAgfSBlbHNlIHsKICAgICAgICBsb29rdXBOYW1lID0gIkhlbHZldGljYSI7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGdseXBoV2lkdGhzID0gTWV0cmljc1tsb29rdXBOYW1lXTsKICAgIGlmICh0eXBlb2YgZ2x5cGhXaWR0aHMgPT09ICJudW1iZXIiKSB7CiAgICAgIGRlZmF1bHRXaWR0aCA9IGdseXBoV2lkdGhzOwogICAgICBtb25vc3BhY2UgPSB0cnVlOwogICAgfSBlbHNlIHsKICAgICAgd2lkdGhzID0gZ2x5cGhXaWR0aHMoKTsKICAgIH0KICAgIHJldHVybiB7CiAgICAgIGRlZmF1bHRXaWR0aCwKICAgICAgbW9ub3NwYWNlLAogICAgICB3aWR0aHMKICAgIH07CiAgfQogIGJ1aWxkQ2hhckNvZGVUb1dpZHRoKHdpZHRoc0J5R2x5cGhOYW1lLCBwcm9wZXJ0aWVzKSB7CiAgICBjb25zdCB3aWR0aHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgY29uc3QgZGlmZmVyZW5jZXMgPSBwcm9wZXJ0aWVzLmRpZmZlcmVuY2VzOwogICAgY29uc3QgZW5jb2RpbmcgPSBwcm9wZXJ0aWVzLmRlZmF1bHRFbmNvZGluZzsKICAgIGZvciAobGV0IGNoYXJDb2RlID0gMDsgY2hhckNvZGUgPCAyNTY7IGNoYXJDb2RlKyspIHsKICAgICAgaWYgKGNoYXJDb2RlIGluIGRpZmZlcmVuY2VzICYmIHdpZHRoc0J5R2x5cGhOYW1lW2RpZmZlcmVuY2VzW2NoYXJDb2RlXV0pIHsKICAgICAgICB3aWR0aHNbY2hhckNvZGVdID0gd2lkdGhzQnlHbHlwaE5hbWVbZGlmZmVyZW5jZXNbY2hhckNvZGVdXTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoY2hhckNvZGUgaW4gZW5jb2RpbmcgJiYgd2lkdGhzQnlHbHlwaE5hbWVbZW5jb2RpbmdbY2hhckNvZGVdXSkgewogICAgICAgIHdpZHRoc1tjaGFyQ29kZV0gPSB3aWR0aHNCeUdseXBoTmFtZVtlbmNvZGluZ1tjaGFyQ29kZV1dOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gd2lkdGhzOwogIH0KICBwcmVFdmFsdWF0ZUZvbnQoZGljdCkgewogICAgY29uc3QgYmFzZURpY3QgPSBkaWN0OwogICAgbGV0IHR5cGUgPSBkaWN0LmdldCgiU3VidHlwZSIpOwogICAgaWYgKCEodHlwZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiaW52YWxpZCBmb250IFN1YnR5cGUiKTsKICAgIH0KICAgIGxldCBjb21wb3NpdGUgPSBmYWxzZTsKICAgIGxldCBoYXNoLCB0b1VuaWNvZGU7CiAgICBpZiAodHlwZS5uYW1lID09PSAiVHlwZTAiKSB7CiAgICAgIGNvbnN0IGRmID0gZGljdC5nZXQoIkRlc2NlbmRhbnRGb250cyIpOwogICAgICBpZiAoIWRmKSB7CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJEZXNjZW5kYW50IGZvbnRzIGFyZSBub3Qgc3BlY2lmaWVkIik7CiAgICAgIH0KICAgICAgZGljdCA9IEFycmF5LmlzQXJyYXkoZGYpID8gdGhpcy54cmVmLmZldGNoSWZSZWYoZGZbMF0pIDogZGY7CiAgICAgIGlmICghKGRpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiRGVzY2VuZGFudCBmb250IGlzIG5vdCBhIGRpY3Rpb25hcnkuIik7CiAgICAgIH0KICAgICAgdHlwZSA9IGRpY3QuZ2V0KCJTdWJ0eXBlIik7CiAgICAgIGlmICghKHR5cGUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiaW52YWxpZCBmb250IFN1YnR5cGUiKTsKICAgICAgfQogICAgICBjb21wb3NpdGUgPSB0cnVlOwogICAgfQogICAgY29uc3QgZmlyc3RDaGFyID0gZGljdC5nZXQoIkZpcnN0Q2hhciIpIHx8IDAsCiAgICAgIGxhc3RDaGFyID0gZGljdC5nZXQoIkxhc3RDaGFyIikgfHwgKGNvbXBvc2l0ZSA/IDB4ZmZmZiA6IDB4ZmYpOwogICAgY29uc3QgZGVzY3JpcHRvciA9IGRpY3QuZ2V0KCJGb250RGVzY3JpcHRvciIpOwogICAgaWYgKGRlc2NyaXB0b3IpIHsKICAgICAgaGFzaCA9IG5ldyBfbXVybXVyaGFzaC5NdXJtdXJIYXNoM182NCgpOwogICAgICBjb25zdCBlbmNvZGluZyA9IGJhc2VEaWN0LmdldFJhdygiRW5jb2RpbmciKTsKICAgICAgaWYgKGVuY29kaW5nIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICAgIGhhc2gudXBkYXRlKGVuY29kaW5nLm5hbWUpOwogICAgICB9IGVsc2UgaWYgKGVuY29kaW5nIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgICAgaGFzaC51cGRhdGUoZW5jb2RpbmcudG9TdHJpbmcoKSk7CiAgICAgIH0gZWxzZSBpZiAoZW5jb2RpbmcgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiBlbmNvZGluZy5nZXRSYXdWYWx1ZXMoKSkgewogICAgICAgICAgaWYgKGVudHJ5IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICAgICAgICBoYXNoLnVwZGF0ZShlbnRyeS5uYW1lKTsKICAgICAgICAgIH0gZWxzZSBpZiAoZW50cnkgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpIHsKICAgICAgICAgICAgaGFzaC51cGRhdGUoZW50cnkudG9TdHJpbmcoKSk7CiAgICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZW50cnkpKSB7CiAgICAgICAgICAgIGNvbnN0IGRpZmZMZW5ndGggPSBlbnRyeS5sZW5ndGgsCiAgICAgICAgICAgICAgZGlmZkJ1ZiA9IG5ldyBBcnJheShkaWZmTGVuZ3RoKTsKICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBkaWZmTGVuZ3RoOyBqKyspIHsKICAgICAgICAgICAgICBjb25zdCBkaWZmRW50cnkgPSBlbnRyeVtqXTsKICAgICAgICAgICAgICBpZiAoZGlmZkVudHJ5IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICAgICAgICAgICAgZGlmZkJ1ZltqXSA9IGRpZmZFbnRyeS5uYW1lOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGRpZmZFbnRyeSA9PT0gIm51bWJlciIgfHwgZGlmZkVudHJ5IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgICAgICAgICAgICBkaWZmQnVmW2pdID0gZGlmZkVudHJ5LnRvU3RyaW5nKCk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGhhc2gudXBkYXRlKGRpZmZCdWYuam9pbigpKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgaGFzaC51cGRhdGUoYCR7Zmlyc3RDaGFyfS0ke2xhc3RDaGFyfWApOwogICAgICB0b1VuaWNvZGUgPSBkaWN0LmdldCgiVG9Vbmljb2RlIikgfHwgYmFzZURpY3QuZ2V0KCJUb1VuaWNvZGUiKTsKICAgICAgaWYgKHRvVW5pY29kZSBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSB7CiAgICAgICAgY29uc3Qgc3RyZWFtID0gdG9Vbmljb2RlLnN0ciB8fCB0b1VuaWNvZGU7CiAgICAgICAgY29uc3QgdWludDhhcnJheSA9IHN0cmVhbS5idWZmZXIgPyBuZXcgVWludDhBcnJheShzdHJlYW0uYnVmZmVyLmJ1ZmZlciwgMCwgc3RyZWFtLmJ1ZmZlckxlbmd0aCkgOiBuZXcgVWludDhBcnJheShzdHJlYW0uYnl0ZXMuYnVmZmVyLCBzdHJlYW0uc3RhcnQsIHN0cmVhbS5lbmQgLSBzdHJlYW0uc3RhcnQpOwogICAgICAgIGhhc2gudXBkYXRlKHVpbnQ4YXJyYXkpOwogICAgICB9IGVsc2UgaWYgKHRvVW5pY29kZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgICBoYXNoLnVwZGF0ZSh0b1VuaWNvZGUubmFtZSk7CiAgICAgIH0KICAgICAgY29uc3Qgd2lkdGhzID0gZGljdC5nZXQoIldpZHRocyIpIHx8IGJhc2VEaWN0LmdldCgiV2lkdGhzIik7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KHdpZHRocykpIHsKICAgICAgICBjb25zdCB3aWR0aHNCdWYgPSBbXTsKICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIHdpZHRocykgewogICAgICAgICAgaWYgKHR5cGVvZiBlbnRyeSA9PT0gIm51bWJlciIgfHwgZW50cnkgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpIHsKICAgICAgICAgICAgd2lkdGhzQnVmLnB1c2goZW50cnkudG9TdHJpbmcoKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGhhc2gudXBkYXRlKHdpZHRoc0J1Zi5qb2luKCkpOwogICAgICB9CiAgICAgIGlmIChjb21wb3NpdGUpIHsKICAgICAgICBoYXNoLnVwZGF0ZSgiY29tcG9zaXRlRm9udCIpOwogICAgICAgIGNvbnN0IGNvbXBvc2l0ZVdpZHRocyA9IGRpY3QuZ2V0KCJXIikgfHwgYmFzZURpY3QuZ2V0KCJXIik7CiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29tcG9zaXRlV2lkdGhzKSkgewogICAgICAgICAgY29uc3Qgd2lkdGhzQnVmID0gW107CiAgICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGNvbXBvc2l0ZVdpZHRocykgewogICAgICAgICAgICBpZiAodHlwZW9mIGVudHJ5ID09PSAibnVtYmVyIiB8fCBlbnRyeSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgICAgICAgIHdpZHRoc0J1Zi5wdXNoKGVudHJ5LnRvU3RyaW5nKCkpOwogICAgICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZW50cnkpKSB7CiAgICAgICAgICAgICAgY29uc3Qgc3ViV2lkdGhzQnVmID0gW107CiAgICAgICAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGVudHJ5KSB7CiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGVsZW1lbnQgPT09ICJudW1iZXIiIHx8IGVsZW1lbnQgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpIHsKICAgICAgICAgICAgICAgICAgc3ViV2lkdGhzQnVmLnB1c2goZWxlbWVudC50b1N0cmluZygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgd2lkdGhzQnVmLnB1c2goYFske3N1YldpZHRoc0J1Zi5qb2luKCl9XWApOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBoYXNoLnVwZGF0ZSh3aWR0aHNCdWYuam9pbigpKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgY2lkVG9HaWRNYXAgPSBkaWN0LmdldFJhdygiQ0lEVG9HSURNYXAiKSB8fCBiYXNlRGljdC5nZXRSYXcoIkNJRFRvR0lETWFwIik7CiAgICAgICAgaWYgKGNpZFRvR2lkTWFwIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICAgICAgaGFzaC51cGRhdGUoY2lkVG9HaWRNYXAubmFtZSk7CiAgICAgICAgfSBlbHNlIGlmIChjaWRUb0dpZE1hcCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgICAgaGFzaC51cGRhdGUoY2lkVG9HaWRNYXAudG9TdHJpbmcoKSk7CiAgICAgICAgfSBlbHNlIGlmIChjaWRUb0dpZE1hcCBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSB7CiAgICAgICAgICBoYXNoLnVwZGF0ZShjaWRUb0dpZE1hcC5wZWVrQnl0ZXMoKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gewogICAgICBkZXNjcmlwdG9yLAogICAgICBkaWN0LAogICAgICBiYXNlRGljdCwKICAgICAgY29tcG9zaXRlLAogICAgICB0eXBlOiB0eXBlLm5hbWUsCiAgICAgIGZpcnN0Q2hhciwKICAgICAgbGFzdENoYXIsCiAgICAgIHRvVW5pY29kZSwKICAgICAgaGFzaDogaGFzaCA/IGhhc2guaGV4ZGlnZXN0KCkgOiAiIgogICAgfTsKICB9CiAgYXN5bmMgdHJhbnNsYXRlRm9udChfcmVmOSkgewogICAgbGV0IHsKICAgICAgZGVzY3JpcHRvciwKICAgICAgZGljdCwKICAgICAgYmFzZURpY3QsCiAgICAgIGNvbXBvc2l0ZSwKICAgICAgdHlwZSwKICAgICAgZmlyc3RDaGFyLAogICAgICBsYXN0Q2hhciwKICAgICAgdG9Vbmljb2RlLAogICAgICBjc3NGb250SW5mbwogICAgfSA9IF9yZWY5OwogICAgY29uc3QgaXNUeXBlM0ZvbnQgPSB0eXBlID09PSAiVHlwZTMiOwogICAgbGV0IHByb3BlcnRpZXM7CiAgICBpZiAoIWRlc2NyaXB0b3IpIHsKICAgICAgaWYgKGlzVHlwZTNGb250KSB7CiAgICAgICAgZGVzY3JpcHRvciA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KG51bGwpOwogICAgICAgIGRlc2NyaXB0b3Iuc2V0KCJGb250TmFtZSIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KHR5cGUpKTsKICAgICAgICBkZXNjcmlwdG9yLnNldCgiRm9udEJCb3giLCBkaWN0LmdldEFycmF5KCJGb250QkJveCIpIHx8IFswLCAwLCAwLCAwXSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbGV0IGJhc2VGb250TmFtZSA9IGRpY3QuZ2V0KCJCYXNlRm9udCIpOwogICAgICAgIGlmICghKGJhc2VGb250TmFtZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkJhc2UgZm9udCBpcyBub3Qgc3BlY2lmaWVkIik7CiAgICAgICAgfQogICAgICAgIGJhc2VGb250TmFtZSA9IGJhc2VGb250TmFtZS5uYW1lLnJlcGxhY2VBbGwoL1ssX10vZywgIi0iKTsKICAgICAgICBjb25zdCBtZXRyaWNzID0gdGhpcy5nZXRCYXNlRm9udE1ldHJpY3MoYmFzZUZvbnROYW1lKTsKICAgICAgICBjb25zdCBmb250TmFtZVdvU3R5bGUgPSBiYXNlRm9udE5hbWUuc3BsaXQoIi0iKVswXTsKICAgICAgICBjb25zdCBmbGFncyA9ICh0aGlzLmlzU2VyaWZGb250KGZvbnROYW1lV29TdHlsZSkgPyBfZm9udHNfdXRpbHMuRm9udEZsYWdzLlNlcmlmIDogMCkgfCAobWV0cmljcy5tb25vc3BhY2UgPyBfZm9udHNfdXRpbHMuRm9udEZsYWdzLkZpeGVkUGl0Y2ggOiAwKSB8ICgoMCwgX3N0YW5kYXJkX2ZvbnRzLmdldFN5bWJvbHNGb250cykoKVtmb250TmFtZVdvU3R5bGVdID8gX2ZvbnRzX3V0aWxzLkZvbnRGbGFncy5TeW1ib2xpYyA6IF9mb250c191dGlscy5Gb250RmxhZ3MuTm9uc3ltYm9saWMpOwogICAgICAgIHByb3BlcnRpZXMgPSB7CiAgICAgICAgICB0eXBlLAogICAgICAgICAgbmFtZTogYmFzZUZvbnROYW1lLAogICAgICAgICAgbG9hZGVkTmFtZTogYmFzZURpY3QubG9hZGVkTmFtZSwKICAgICAgICAgIHdpZHRoczogbWV0cmljcy53aWR0aHMsCiAgICAgICAgICBkZWZhdWx0V2lkdGg6IG1ldHJpY3MuZGVmYXVsdFdpZHRoLAogICAgICAgICAgaXNTaW11bGF0ZWRGbGFnczogdHJ1ZSwKICAgICAgICAgIGZsYWdzLAogICAgICAgICAgZmlyc3RDaGFyLAogICAgICAgICAgbGFzdENoYXIsCiAgICAgICAgICB0b1VuaWNvZGUsCiAgICAgICAgICB4SGVpZ2h0OiAwLAogICAgICAgICAgY2FwSGVpZ2h0OiAwLAogICAgICAgICAgaXRhbGljQW5nbGU6IDAsCiAgICAgICAgICBpc1R5cGUzRm9udAogICAgICAgIH07CiAgICAgICAgY29uc3Qgd2lkdGhzID0gZGljdC5nZXQoIldpZHRocyIpOwogICAgICAgIGNvbnN0IHN0YW5kYXJkRm9udE5hbWUgPSAoMCwgX3N0YW5kYXJkX2ZvbnRzLmdldFN0YW5kYXJkRm9udE5hbWUpKGJhc2VGb250TmFtZSk7CiAgICAgICAgbGV0IGZpbGUgPSBudWxsOwogICAgICAgIGlmIChzdGFuZGFyZEZvbnROYW1lKSB7CiAgICAgICAgICBwcm9wZXJ0aWVzLmlzU3RhbmRhcmRGb250ID0gdHJ1ZTsKICAgICAgICAgIGZpbGUgPSBhd2FpdCB0aGlzLmZldGNoU3RhbmRhcmRGb250RGF0YShzdGFuZGFyZEZvbnROYW1lKTsKICAgICAgICAgIHByb3BlcnRpZXMuaXNJbnRlcm5hbEZvbnQgPSAhIWZpbGU7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzLmV4dHJhY3REYXRhU3RydWN0dXJlcyhkaWN0LCBkaWN0LCBwcm9wZXJ0aWVzKS50aGVuKG5ld1Byb3BlcnRpZXMgPT4gewogICAgICAgICAgaWYgKHdpZHRocykgewogICAgICAgICAgICBjb25zdCBnbHlwaFdpZHRocyA9IFtdOwogICAgICAgICAgICBsZXQgaiA9IGZpcnN0Q2hhcjsKICAgICAgICAgICAgZm9yIChjb25zdCB3aWR0aCBvZiB3aWR0aHMpIHsKICAgICAgICAgICAgICBnbHlwaFdpZHRoc1tqKytdID0gdGhpcy54cmVmLmZldGNoSWZSZWYod2lkdGgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG5ld1Byb3BlcnRpZXMud2lkdGhzID0gZ2x5cGhXaWR0aHM7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBuZXdQcm9wZXJ0aWVzLndpZHRocyA9IHRoaXMuYnVpbGRDaGFyQ29kZVRvV2lkdGgobWV0cmljcy53aWR0aHMsIG5ld1Byb3BlcnRpZXMpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG5ldyBfZm9udHMuRm9udChiYXNlRm9udE5hbWUsIGZpbGUsIG5ld1Byb3BlcnRpZXMpOwogICAgICAgIH0pOwogICAgICB9CiAgICB9CiAgICBsZXQgZm9udE5hbWUgPSBkZXNjcmlwdG9yLmdldCgiRm9udE5hbWUiKTsKICAgIGxldCBiYXNlRm9udCA9IGRpY3QuZ2V0KCJCYXNlRm9udCIpOwogICAgaWYgKHR5cGVvZiBmb250TmFtZSA9PT0gInN0cmluZyIpIHsKICAgICAgZm9udE5hbWUgPSBfcHJpbWl0aXZlcy5OYW1lLmdldChmb250TmFtZSk7CiAgICB9CiAgICBpZiAodHlwZW9mIGJhc2VGb250ID09PSAic3RyaW5nIikgewogICAgICBiYXNlRm9udCA9IF9wcmltaXRpdmVzLk5hbWUuZ2V0KGJhc2VGb250KTsKICAgIH0KICAgIGlmICghaXNUeXBlM0ZvbnQpIHsKICAgICAgY29uc3QgZm9udE5hbWVTdHIgPSBmb250TmFtZSAmJiBmb250TmFtZS5uYW1lOwogICAgICBjb25zdCBiYXNlRm9udFN0ciA9IGJhc2VGb250ICYmIGJhc2VGb250Lm5hbWU7CiAgICAgIGlmIChmb250TmFtZVN0ciAhPT0gYmFzZUZvbnRTdHIpIHsKICAgICAgICAoMCwgX3V0aWwuaW5mbykoYFRoZSBGb250RGVzY3JpcHRvcidzIEZvbnROYW1lIGlzICIke2ZvbnROYW1lU3RyfSIgYnV0IGAgKyBgc2hvdWxkIGJlIHRoZSBzYW1lIGFzIHRoZSBGb250J3MgQmFzZUZvbnQgIiR7YmFzZUZvbnRTdHJ9Ii5gKTsKICAgICAgICBpZiAoZm9udE5hbWVTdHIgJiYgYmFzZUZvbnRTdHIgJiYgYmFzZUZvbnRTdHIuc3RhcnRzV2l0aChmb250TmFtZVN0cikpIHsKICAgICAgICAgIGZvbnROYW1lID0gYmFzZUZvbnQ7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBmb250TmFtZSA9IGZvbnROYW1lIHx8IGJhc2VGb250OwogICAgaWYgKCEoZm9udE5hbWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSkgewogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoImludmFsaWQgZm9udCBuYW1lIik7CiAgICB9CiAgICBsZXQgZm9udEZpbGUsIHN1YnR5cGUsIGxlbmd0aDEsIGxlbmd0aDIsIGxlbmd0aDM7CiAgICB0cnkgewogICAgICBmb250RmlsZSA9IGRlc2NyaXB0b3IuZ2V0KCJGb250RmlsZSIsICJGb250RmlsZTIiLCAiRm9udEZpbGUzIik7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoIXRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICAoMCwgX3V0aWwud2FybikoYHRyYW5zbGF0ZUZvbnQgLSBmZXRjaGluZyAiJHtmb250TmFtZS5uYW1lfSIgZm9udCBmaWxlOiAiJHtleH0iLmApOwogICAgICBmb250RmlsZSA9IG5ldyBfc3RyZWFtLk51bGxTdHJlYW0oKTsKICAgIH0KICAgIGxldCBpc1N0YW5kYXJkRm9udCA9IGZhbHNlOwogICAgbGV0IGlzSW50ZXJuYWxGb250ID0gZmFsc2U7CiAgICBsZXQgZ2x5cGhTY2FsZUZhY3RvcnMgPSBudWxsOwogICAgaWYgKGZvbnRGaWxlKSB7CiAgICAgIGlmIChmb250RmlsZS5kaWN0KSB7CiAgICAgICAgY29uc3Qgc3VidHlwZUVudHJ5ID0gZm9udEZpbGUuZGljdC5nZXQoIlN1YnR5cGUiKTsKICAgICAgICBpZiAoc3VidHlwZUVudHJ5IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICAgICAgc3VidHlwZSA9IHN1YnR5cGVFbnRyeS5uYW1lOwogICAgICAgIH0KICAgICAgICBsZW5ndGgxID0gZm9udEZpbGUuZGljdC5nZXQoIkxlbmd0aDEiKTsKICAgICAgICBsZW5ndGgyID0gZm9udEZpbGUuZGljdC5nZXQoIkxlbmd0aDIiKTsKICAgICAgICBsZW5ndGgzID0gZm9udEZpbGUuZGljdC5nZXQoIkxlbmd0aDMiKTsKICAgICAgfQogICAgfSBlbHNlIGlmIChjc3NGb250SW5mbykgewogICAgICBjb25zdCBzdGFuZGFyZEZvbnROYW1lID0gKDAsIF94ZmFfZm9udHMuZ2V0WGZhRm9udE5hbWUpKGZvbnROYW1lLm5hbWUpOwogICAgICBpZiAoc3RhbmRhcmRGb250TmFtZSkgewogICAgICAgIGNzc0ZvbnRJbmZvLmZvbnRGYW1pbHkgPSBgJHtjc3NGb250SW5mby5mb250RmFtaWx5fS1QZGZKUy1YRkFgOwogICAgICAgIGNzc0ZvbnRJbmZvLm1ldHJpY3MgPSBzdGFuZGFyZEZvbnROYW1lLm1ldHJpY3MgfHwgbnVsbDsKICAgICAgICBnbHlwaFNjYWxlRmFjdG9ycyA9IHN0YW5kYXJkRm9udE5hbWUuZmFjdG9ycyB8fCBudWxsOwogICAgICAgIGZvbnRGaWxlID0gYXdhaXQgdGhpcy5mZXRjaFN0YW5kYXJkRm9udERhdGEoc3RhbmRhcmRGb250TmFtZS5uYW1lKTsKICAgICAgICBpc0ludGVybmFsRm9udCA9ICEhZm9udEZpbGU7CiAgICAgICAgYmFzZURpY3QgPSBkaWN0ID0gKDAsIF94ZmFfZm9udHMuZ2V0WGZhRm9udERpY3QpKGZvbnROYW1lLm5hbWUpOwogICAgICAgIGNvbXBvc2l0ZSA9IHRydWU7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoIWlzVHlwZTNGb250KSB7CiAgICAgIGNvbnN0IHN0YW5kYXJkRm9udE5hbWUgPSAoMCwgX3N0YW5kYXJkX2ZvbnRzLmdldFN0YW5kYXJkRm9udE5hbWUpKGZvbnROYW1lLm5hbWUpOwogICAgICBpZiAoc3RhbmRhcmRGb250TmFtZSkgewogICAgICAgIGlzU3RhbmRhcmRGb250ID0gdHJ1ZTsKICAgICAgICBmb250RmlsZSA9IGF3YWl0IHRoaXMuZmV0Y2hTdGFuZGFyZEZvbnREYXRhKHN0YW5kYXJkRm9udE5hbWUpOwogICAgICAgIGlzSW50ZXJuYWxGb250ID0gISFmb250RmlsZTsKICAgICAgfQogICAgfQogICAgcHJvcGVydGllcyA9IHsKICAgICAgdHlwZSwKICAgICAgbmFtZTogZm9udE5hbWUubmFtZSwKICAgICAgc3VidHlwZSwKICAgICAgZmlsZTogZm9udEZpbGUsCiAgICAgIGxlbmd0aDEsCiAgICAgIGxlbmd0aDIsCiAgICAgIGxlbmd0aDMsCiAgICAgIGlzU3RhbmRhcmRGb250LAogICAgICBpc0ludGVybmFsRm9udCwKICAgICAgbG9hZGVkTmFtZTogYmFzZURpY3QubG9hZGVkTmFtZSwKICAgICAgY29tcG9zaXRlLAogICAgICBmaXhlZFBpdGNoOiBmYWxzZSwKICAgICAgZm9udE1hdHJpeDogZGljdC5nZXRBcnJheSgiRm9udE1hdHJpeCIpIHx8IF91dGlsLkZPTlRfSURFTlRJVFlfTUFUUklYLAogICAgICBmaXJzdENoYXIsCiAgICAgIGxhc3RDaGFyLAogICAgICB0b1VuaWNvZGUsCiAgICAgIGJib3g6IGRlc2NyaXB0b3IuZ2V0QXJyYXkoIkZvbnRCQm94IikgfHwgZGljdC5nZXRBcnJheSgiRm9udEJCb3giKSwKICAgICAgYXNjZW50OiBkZXNjcmlwdG9yLmdldCgiQXNjZW50IiksCiAgICAgIGRlc2NlbnQ6IGRlc2NyaXB0b3IuZ2V0KCJEZXNjZW50IiksCiAgICAgIHhIZWlnaHQ6IGRlc2NyaXB0b3IuZ2V0KCJYSGVpZ2h0IikgfHwgMCwKICAgICAgY2FwSGVpZ2h0OiBkZXNjcmlwdG9yLmdldCgiQ2FwSGVpZ2h0IikgfHwgMCwKICAgICAgZmxhZ3M6IGRlc2NyaXB0b3IuZ2V0KCJGbGFncyIpLAogICAgICBpdGFsaWNBbmdsZTogZGVzY3JpcHRvci5nZXQoIkl0YWxpY0FuZ2xlIikgfHwgMCwKICAgICAgaXNUeXBlM0ZvbnQsCiAgICAgIGNzc0ZvbnRJbmZvLAogICAgICBzY2FsZUZhY3RvcnM6IGdseXBoU2NhbGVGYWN0b3JzCiAgICB9OwogICAgaWYgKGNvbXBvc2l0ZSkgewogICAgICBjb25zdCBjaWRFbmNvZGluZyA9IGJhc2VEaWN0LmdldCgiRW5jb2RpbmciKTsKICAgICAgaWYgKGNpZEVuY29kaW5nIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICAgIHByb3BlcnRpZXMuY2lkRW5jb2RpbmcgPSBjaWRFbmNvZGluZy5uYW1lOwogICAgICB9CiAgICAgIGNvbnN0IGNNYXAgPSBhd2FpdCBfY21hcC5DTWFwRmFjdG9yeS5jcmVhdGUoewogICAgICAgIGVuY29kaW5nOiBjaWRFbmNvZGluZywKICAgICAgICBmZXRjaEJ1aWx0SW5DTWFwOiB0aGlzLl9mZXRjaEJ1aWx0SW5DTWFwQm91bmQsCiAgICAgICAgdXNlQ01hcDogbnVsbAogICAgICB9KTsKICAgICAgcHJvcGVydGllcy5jTWFwID0gY01hcDsKICAgICAgcHJvcGVydGllcy52ZXJ0aWNhbCA9IHByb3BlcnRpZXMuY01hcC52ZXJ0aWNhbDsKICAgIH0KICAgIHJldHVybiB0aGlzLmV4dHJhY3REYXRhU3RydWN0dXJlcyhkaWN0LCBiYXNlRGljdCwgcHJvcGVydGllcykudGhlbihuZXdQcm9wZXJ0aWVzID0+IHsKICAgICAgdGhpcy5leHRyYWN0V2lkdGhzKGRpY3QsIGRlc2NyaXB0b3IsIG5ld1Byb3BlcnRpZXMpOwogICAgICByZXR1cm4gbmV3IF9mb250cy5Gb250KGZvbnROYW1lLm5hbWUsIGZvbnRGaWxlLCBuZXdQcm9wZXJ0aWVzKTsKICAgIH0pOwogIH0KICBzdGF0aWMgYnVpbGRGb250UGF0aHMoZm9udCwgZ2x5cGhzLCBoYW5kbGVyLCBldmFsdWF0b3JPcHRpb25zKSB7CiAgICBmdW5jdGlvbiBidWlsZFBhdGgoZm9udENoYXIpIHsKICAgICAgY29uc3QgZ2x5cGhOYW1lID0gYCR7Zm9udC5sb2FkZWROYW1lfV9wYXRoXyR7Zm9udENoYXJ9YDsKICAgICAgdHJ5IHsKICAgICAgICBpZiAoZm9udC5yZW5kZXJlci5oYXNCdWlsdFBhdGgoZm9udENoYXIpKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGhhbmRsZXIuc2VuZCgiY29tbW9ub2JqIiwgW2dseXBoTmFtZSwgIkZvbnRQYXRoIiwgZm9udC5yZW5kZXJlci5nZXRQYXRoSnMoZm9udENoYXIpXSk7CiAgICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICAgIGlmIChldmFsdWF0b3JPcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBidWlsZEZvbnRQYXRocyAtIGlnbm9yaW5nICR7Z2x5cGhOYW1lfSBnbHlwaDogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIHRocm93IHJlYXNvbjsKICAgICAgfQogICAgfQogICAgZm9yIChjb25zdCBnbHlwaCBvZiBnbHlwaHMpIHsKICAgICAgYnVpbGRQYXRoKGdseXBoLmZvbnRDaGFyKTsKICAgICAgY29uc3QgYWNjZW50ID0gZ2x5cGguYWNjZW50OwogICAgICBpZiAoYWNjZW50ICYmIGFjY2VudC5mb250Q2hhcikgewogICAgICAgIGJ1aWxkUGF0aChhY2NlbnQuZm9udENoYXIpOwogICAgICB9CiAgICB9CiAgfQogIHN0YXRpYyBnZXQgZmFsbGJhY2tGb250RGljdCgpIHsKICAgIGNvbnN0IGRpY3QgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdCgpOwogICAgZGljdC5zZXQoIkJhc2VGb250IiwgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIlBERkpTLUZhbGxiYWNrRm9udCIpKTsKICAgIGRpY3Quc2V0KCJUeXBlIiwgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIkZhbGxiYWNrVHlwZSIpKTsKICAgIGRpY3Quc2V0KCJTdWJ0eXBlIiwgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIkZhbGxiYWNrVHlwZSIpKTsKICAgIGRpY3Quc2V0KCJFbmNvZGluZyIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJXaW5BbnNpRW5jb2RpbmciKSk7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImZhbGxiYWNrRm9udERpY3QiLCBkaWN0KTsKICB9Cn0KZXhwb3J0cy5QYXJ0aWFsRXZhbHVhdG9yID0gUGFydGlhbEV2YWx1YXRvcjsKY2xhc3MgVHJhbnNsYXRlZEZvbnQgewogIGNvbnN0cnVjdG9yKF9yZWYxMCkgewogICAgbGV0IHsKICAgICAgbG9hZGVkTmFtZSwKICAgICAgZm9udCwKICAgICAgZGljdCwKICAgICAgZXZhbHVhdG9yT3B0aW9ucwogICAgfSA9IF9yZWYxMDsKICAgIHRoaXMubG9hZGVkTmFtZSA9IGxvYWRlZE5hbWU7CiAgICB0aGlzLmZvbnQgPSBmb250OwogICAgdGhpcy5kaWN0ID0gZGljdDsKICAgIHRoaXMuX2V2YWx1YXRvck9wdGlvbnMgPSBldmFsdWF0b3JPcHRpb25zIHx8IERlZmF1bHRQYXJ0aWFsRXZhbHVhdG9yT3B0aW9uczsKICAgIHRoaXMudHlwZTNMb2FkZWQgPSBudWxsOwogICAgdGhpcy50eXBlM0RlcGVuZGVuY2llcyA9IGZvbnQuaXNUeXBlM0ZvbnQgPyBuZXcgU2V0KCkgOiBudWxsOwogICAgdGhpcy5zZW50ID0gZmFsc2U7CiAgfQogIHNlbmQoaGFuZGxlcikgewogICAgaWYgKHRoaXMuc2VudCkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLnNlbnQgPSB0cnVlOwogICAgaGFuZGxlci5zZW5kKCJjb21tb25vYmoiLCBbdGhpcy5sb2FkZWROYW1lLCAiRm9udCIsIHRoaXMuZm9udC5leHBvcnREYXRhKHRoaXMuX2V2YWx1YXRvck9wdGlvbnMuZm9udEV4dHJhUHJvcGVydGllcyldKTsKICB9CiAgZmFsbGJhY2soaGFuZGxlcikgewogICAgaWYgKCF0aGlzLmZvbnQuZGF0YSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLmZvbnQuZGlzYWJsZUZvbnRGYWNlID0gdHJ1ZTsKICAgIFBhcnRpYWxFdmFsdWF0b3IuYnVpbGRGb250UGF0aHModGhpcy5mb250LCB0aGlzLmZvbnQuZ2x5cGhDYWNoZVZhbHVlcywgaGFuZGxlciwgdGhpcy5fZXZhbHVhdG9yT3B0aW9ucyk7CiAgfQogIGxvYWRUeXBlM0RhdGEoZXZhbHVhdG9yLCByZXNvdXJjZXMsIHRhc2spIHsKICAgIGlmICh0aGlzLnR5cGUzTG9hZGVkKSB7CiAgICAgIHJldHVybiB0aGlzLnR5cGUzTG9hZGVkOwogICAgfQogICAgaWYgKCF0aGlzLmZvbnQuaXNUeXBlM0ZvbnQpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJNdXN0IGJlIGEgVHlwZTMgZm9udC4iKTsKICAgIH0KICAgIGNvbnN0IHR5cGUzRXZhbHVhdG9yID0gZXZhbHVhdG9yLmNsb25lKHsKICAgICAgaWdub3JlRXJyb3JzOiBmYWxzZQogICAgfSk7CiAgICB0eXBlM0V2YWx1YXRvci5wYXJzaW5nVHlwZTNGb250ID0gdHJ1ZTsKICAgIGNvbnN0IHR5cGUzRm9udFJlZnMgPSBuZXcgX3ByaW1pdGl2ZXMuUmVmU2V0KGV2YWx1YXRvci50eXBlM0ZvbnRSZWZzKTsKICAgIGlmICh0aGlzLmRpY3Qub2JqSWQgJiYgIXR5cGUzRm9udFJlZnMuaGFzKHRoaXMuZGljdC5vYmpJZCkpIHsKICAgICAgdHlwZTNGb250UmVmcy5wdXQodGhpcy5kaWN0Lm9iaklkKTsKICAgIH0KICAgIHR5cGUzRXZhbHVhdG9yLnR5cGUzRm9udFJlZnMgPSB0eXBlM0ZvbnRSZWZzOwogICAgY29uc3QgdHJhbnNsYXRlZEZvbnQgPSB0aGlzLmZvbnQsCiAgICAgIHR5cGUzRGVwZW5kZW5jaWVzID0gdGhpcy50eXBlM0RlcGVuZGVuY2llczsKICAgIGxldCBsb2FkQ2hhclByb2NzUHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpOwogICAgY29uc3QgY2hhclByb2NzID0gdGhpcy5kaWN0LmdldCgiQ2hhclByb2NzIik7CiAgICBjb25zdCBmb250UmVzb3VyY2VzID0gdGhpcy5kaWN0LmdldCgiUmVzb3VyY2VzIikgfHwgcmVzb3VyY2VzOwogICAgY29uc3QgY2hhclByb2NPcGVyYXRvckxpc3QgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgY29uc3QgZm9udEJCb3ggPSBfdXRpbC5VdGlsLm5vcm1hbGl6ZVJlY3QodHJhbnNsYXRlZEZvbnQuYmJveCB8fCBbMCwgMCwgMCwgMF0pLAogICAgICB3aWR0aCA9IGZvbnRCQm94WzJdIC0gZm9udEJCb3hbMF0sCiAgICAgIGhlaWdodCA9IGZvbnRCQm94WzNdIC0gZm9udEJCb3hbMV07CiAgICBjb25zdCBmb250QkJveFNpemUgPSBNYXRoLmh5cG90KHdpZHRoLCBoZWlnaHQpOwogICAgZm9yIChjb25zdCBrZXkgb2YgY2hhclByb2NzLmdldEtleXMoKSkgewogICAgICBsb2FkQ2hhclByb2NzUHJvbWlzZSA9IGxvYWRDaGFyUHJvY3NQcm9taXNlLnRoZW4oKCkgPT4gewogICAgICAgIGNvbnN0IGdseXBoU3RyZWFtID0gY2hhclByb2NzLmdldChrZXkpOwogICAgICAgIGNvbnN0IG9wZXJhdG9yTGlzdCA9IG5ldyBfb3BlcmF0b3JfbGlzdC5PcGVyYXRvckxpc3QoKTsKICAgICAgICByZXR1cm4gdHlwZTNFdmFsdWF0b3IuZ2V0T3BlcmF0b3JMaXN0KHsKICAgICAgICAgIHN0cmVhbTogZ2x5cGhTdHJlYW0sCiAgICAgICAgICB0YXNrLAogICAgICAgICAgcmVzb3VyY2VzOiBmb250UmVzb3VyY2VzLAogICAgICAgICAgb3BlcmF0b3JMaXN0CiAgICAgICAgfSkudGhlbigoKSA9PiB7CiAgICAgICAgICBpZiAob3BlcmF0b3JMaXN0LmZuQXJyYXlbMF0gPT09IF91dGlsLk9QUy5zZXRDaGFyV2lkdGhBbmRCb3VuZHMpIHsKICAgICAgICAgICAgdGhpcy5fcmVtb3ZlVHlwZTNDb2xvck9wZXJhdG9ycyhvcGVyYXRvckxpc3QsIGZvbnRCQm94U2l6ZSk7CiAgICAgICAgICB9CiAgICAgICAgICBjaGFyUHJvY09wZXJhdG9yTGlzdFtrZXldID0gb3BlcmF0b3JMaXN0LmdldElSKCk7CiAgICAgICAgICBmb3IgKGNvbnN0IGRlcGVuZGVuY3kgb2Ygb3BlcmF0b3JMaXN0LmRlcGVuZGVuY2llcykgewogICAgICAgICAgICB0eXBlM0RlcGVuZGVuY2llcy5hZGQoZGVwZW5kZW5jeSk7CiAgICAgICAgICB9CiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBUeXBlMyBmb250IHJlc291cmNlICIke2tleX0iIGlzIG5vdCBhdmFpbGFibGUuYCk7CiAgICAgICAgICBjb25zdCBkdW1teU9wZXJhdG9yTGlzdCA9IG5ldyBfb3BlcmF0b3JfbGlzdC5PcGVyYXRvckxpc3QoKTsKICAgICAgICAgIGNoYXJQcm9jT3BlcmF0b3JMaXN0W2tleV0gPSBkdW1teU9wZXJhdG9yTGlzdC5nZXRJUigpOwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0KICAgIHRoaXMudHlwZTNMb2FkZWQgPSBsb2FkQ2hhclByb2NzUHJvbWlzZS50aGVuKCgpID0+IHsKICAgICAgdHJhbnNsYXRlZEZvbnQuY2hhclByb2NPcGVyYXRvckxpc3QgPSBjaGFyUHJvY09wZXJhdG9yTGlzdDsKICAgICAgaWYgKHRoaXMuX2Jib3gpIHsKICAgICAgICB0cmFuc2xhdGVkRm9udC5pc0NoYXJCQm94ID0gdHJ1ZTsKICAgICAgICB0cmFuc2xhdGVkRm9udC5iYm94ID0gdGhpcy5fYmJveDsKICAgICAgfQogICAgfSk7CiAgICByZXR1cm4gdGhpcy50eXBlM0xvYWRlZDsKICB9CiAgX3JlbW92ZVR5cGUzQ29sb3JPcGVyYXRvcnMob3BlcmF0b3JMaXN0KSB7CiAgICBsZXQgZm9udEJCb3hTaXplID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBOYU47CiAgICBjb25zdCBjaGFyQkJveCA9IF91dGlsLlV0aWwubm9ybWFsaXplUmVjdChvcGVyYXRvckxpc3QuYXJnc0FycmF5WzBdLnNsaWNlKDIpKSwKICAgICAgd2lkdGggPSBjaGFyQkJveFsyXSAtIGNoYXJCQm94WzBdLAogICAgICBoZWlnaHQgPSBjaGFyQkJveFszXSAtIGNoYXJCQm94WzFdOwogICAgY29uc3QgY2hhckJCb3hTaXplID0gTWF0aC5oeXBvdCh3aWR0aCwgaGVpZ2h0KTsKICAgIGlmICh3aWR0aCA9PT0gMCB8fCBoZWlnaHQgPT09IDApIHsKICAgICAgb3BlcmF0b3JMaXN0LmZuQXJyYXkuc3BsaWNlKDAsIDEpOwogICAgICBvcGVyYXRvckxpc3QuYXJnc0FycmF5LnNwbGljZSgwLCAxKTsKICAgIH0gZWxzZSBpZiAoZm9udEJCb3hTaXplID09PSAwIHx8IE1hdGgucm91bmQoY2hhckJCb3hTaXplIC8gZm9udEJCb3hTaXplKSA+PSAxMCkgewogICAgICBpZiAoIXRoaXMuX2Jib3gpIHsKICAgICAgICB0aGlzLl9iYm94ID0gW0luZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldOwogICAgICB9CiAgICAgIHRoaXMuX2Jib3hbMF0gPSBNYXRoLm1pbih0aGlzLl9iYm94WzBdLCBjaGFyQkJveFswXSk7CiAgICAgIHRoaXMuX2Jib3hbMV0gPSBNYXRoLm1pbih0aGlzLl9iYm94WzFdLCBjaGFyQkJveFsxXSk7CiAgICAgIHRoaXMuX2Jib3hbMl0gPSBNYXRoLm1heCh0aGlzLl9iYm94WzJdLCBjaGFyQkJveFsyXSk7CiAgICAgIHRoaXMuX2Jib3hbM10gPSBNYXRoLm1heCh0aGlzLl9iYm94WzNdLCBjaGFyQkJveFszXSk7CiAgICB9CiAgICBsZXQgaSA9IDAsCiAgICAgIGlpID0gb3BlcmF0b3JMaXN0Lmxlbmd0aDsKICAgIHdoaWxlIChpIDwgaWkpIHsKICAgICAgc3dpdGNoIChvcGVyYXRvckxpc3QuZm5BcnJheVtpXSkgewogICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldENoYXJXaWR0aEFuZEJvdW5kczoKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldFN0cm9rZUNvbG9yU3BhY2U6CiAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0RmlsbENvbG9yU3BhY2U6CiAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0U3Ryb2tlQ29sb3I6CiAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0U3Ryb2tlQ29sb3JOOgogICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldEZpbGxDb2xvcjoKICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRGaWxsQ29sb3JOOgogICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldFN0cm9rZUdyYXk6CiAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0RmlsbEdyYXk6CiAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0U3Ryb2tlUkdCQ29sb3I6CiAgICAgICAgY2FzZSBfdXRpbC5PUFMuc2V0RmlsbFJHQkNvbG9yOgogICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldFN0cm9rZUNNWUtDb2xvcjoKICAgICAgICBjYXNlIF91dGlsLk9QUy5zZXRGaWxsQ01ZS0NvbG9yOgogICAgICAgIGNhc2UgX3V0aWwuT1BTLnNoYWRpbmdGaWxsOgogICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldFJlbmRlcmluZ0ludGVudDoKICAgICAgICAgIG9wZXJhdG9yTGlzdC5mbkFycmF5LnNwbGljZShpLCAxKTsKICAgICAgICAgIG9wZXJhdG9yTGlzdC5hcmdzQXJyYXkuc3BsaWNlKGksIDEpOwogICAgICAgICAgaWktLTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIGNhc2UgX3V0aWwuT1BTLnNldEdTdGF0ZToKICAgICAgICAgIGNvbnN0IFtnU3RhdGVPYmpdID0gb3BlcmF0b3JMaXN0LmFyZ3NBcnJheVtpXTsKICAgICAgICAgIGxldCBqID0gMCwKICAgICAgICAgICAgamogPSBnU3RhdGVPYmoubGVuZ3RoOwogICAgICAgICAgd2hpbGUgKGogPCBqaikgewogICAgICAgICAgICBjb25zdCBbZ1N0YXRlS2V5XSA9IGdTdGF0ZU9ialtqXTsKICAgICAgICAgICAgc3dpdGNoIChnU3RhdGVLZXkpIHsKICAgICAgICAgICAgICBjYXNlICJUUiI6CiAgICAgICAgICAgICAgY2FzZSAiVFIyIjoKICAgICAgICAgICAgICBjYXNlICJIVCI6CiAgICAgICAgICAgICAgY2FzZSAiQkciOgogICAgICAgICAgICAgIGNhc2UgIkJHMiI6CiAgICAgICAgICAgICAgY2FzZSAiVUNSIjoKICAgICAgICAgICAgICBjYXNlICJVQ1IyIjoKICAgICAgICAgICAgICAgIGdTdGF0ZU9iai5zcGxpY2UoaiwgMSk7CiAgICAgICAgICAgICAgICBqai0tOwogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaisrOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaSsrOwogICAgfQogIH0KfQpjbGFzcyBTdGF0ZU1hbmFnZXIgewogIGNvbnN0cnVjdG9yKCkgewogICAgbGV0IGluaXRpYWxTdGF0ZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbmV3IEV2YWxTdGF0ZSgpOwogICAgdGhpcy5zdGF0ZSA9IGluaXRpYWxTdGF0ZTsKICAgIHRoaXMuc3RhdGVTdGFjayA9IFtdOwogIH0KICBzYXZlKCkgewogICAgY29uc3Qgb2xkID0gdGhpcy5zdGF0ZTsKICAgIHRoaXMuc3RhdGVTdGFjay5wdXNoKHRoaXMuc3RhdGUpOwogICAgdGhpcy5zdGF0ZSA9IG9sZC5jbG9uZSgpOwogIH0KICByZXN0b3JlKCkgewogICAgY29uc3QgcHJldiA9IHRoaXMuc3RhdGVTdGFjay5wb3AoKTsKICAgIGlmIChwcmV2KSB7CiAgICAgIHRoaXMuc3RhdGUgPSBwcmV2OwogICAgfQogIH0KICB0cmFuc2Zvcm0oYXJncykgewogICAgdGhpcy5zdGF0ZS5jdG0gPSBfdXRpbC5VdGlsLnRyYW5zZm9ybSh0aGlzLnN0YXRlLmN0bSwgYXJncyk7CiAgfQp9CmNsYXNzIFRleHRTdGF0ZSB7CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLmN0bSA9IG5ldyBGbG9hdDMyQXJyYXkoX3V0aWwuSURFTlRJVFlfTUFUUklYKTsKICAgIHRoaXMuZm9udE5hbWUgPSBudWxsOwogICAgdGhpcy5mb250U2l6ZSA9IDA7CiAgICB0aGlzLmxvYWRlZE5hbWUgPSBudWxsOwogICAgdGhpcy5mb250ID0gbnVsbDsKICAgIHRoaXMuZm9udE1hdHJpeCA9IF91dGlsLkZPTlRfSURFTlRJVFlfTUFUUklYOwogICAgdGhpcy50ZXh0TWF0cml4ID0gX3V0aWwuSURFTlRJVFlfTUFUUklYLnNsaWNlKCk7CiAgICB0aGlzLnRleHRMaW5lTWF0cml4ID0gX3V0aWwuSURFTlRJVFlfTUFUUklYLnNsaWNlKCk7CiAgICB0aGlzLmNoYXJTcGFjaW5nID0gMDsKICAgIHRoaXMud29yZFNwYWNpbmcgPSAwOwogICAgdGhpcy5sZWFkaW5nID0gMDsKICAgIHRoaXMudGV4dEhTY2FsZSA9IDE7CiAgICB0aGlzLnRleHRSaXNlID0gMDsKICB9CiAgc2V0VGV4dE1hdHJpeChhLCBiLCBjLCBkLCBlLCBmKSB7CiAgICBjb25zdCBtID0gdGhpcy50ZXh0TWF0cml4OwogICAgbVswXSA9IGE7CiAgICBtWzFdID0gYjsKICAgIG1bMl0gPSBjOwogICAgbVszXSA9IGQ7CiAgICBtWzRdID0gZTsKICAgIG1bNV0gPSBmOwogIH0KICBzZXRUZXh0TGluZU1hdHJpeChhLCBiLCBjLCBkLCBlLCBmKSB7CiAgICBjb25zdCBtID0gdGhpcy50ZXh0TGluZU1hdHJpeDsKICAgIG1bMF0gPSBhOwogICAgbVsxXSA9IGI7CiAgICBtWzJdID0gYzsKICAgIG1bM10gPSBkOwogICAgbVs0XSA9IGU7CiAgICBtWzVdID0gZjsKICB9CiAgdHJhbnNsYXRlVGV4dE1hdHJpeCh4LCB5KSB7CiAgICBjb25zdCBtID0gdGhpcy50ZXh0TWF0cml4OwogICAgbVs0XSA9IG1bMF0gKiB4ICsgbVsyXSAqIHkgKyBtWzRdOwogICAgbVs1XSA9IG1bMV0gKiB4ICsgbVszXSAqIHkgKyBtWzVdOwogIH0KICB0cmFuc2xhdGVUZXh0TGluZU1hdHJpeCh4LCB5KSB7CiAgICBjb25zdCBtID0gdGhpcy50ZXh0TGluZU1hdHJpeDsKICAgIG1bNF0gPSBtWzBdICogeCArIG1bMl0gKiB5ICsgbVs0XTsKICAgIG1bNV0gPSBtWzFdICogeCArIG1bM10gKiB5ICsgbVs1XTsKICB9CiAgY2FycmlhZ2VSZXR1cm4oKSB7CiAgICB0aGlzLnRyYW5zbGF0ZVRleHRMaW5lTWF0cml4KDAsIC10aGlzLmxlYWRpbmcpOwogICAgdGhpcy50ZXh0TWF0cml4ID0gdGhpcy50ZXh0TGluZU1hdHJpeC5zbGljZSgpOwogIH0KICBjbG9uZSgpIHsKICAgIGNvbnN0IGNsb25lID0gT2JqZWN0LmNyZWF0ZSh0aGlzKTsKICAgIGNsb25lLnRleHRNYXRyaXggPSB0aGlzLnRleHRNYXRyaXguc2xpY2UoKTsKICAgIGNsb25lLnRleHRMaW5lTWF0cml4ID0gdGhpcy50ZXh0TGluZU1hdHJpeC5zbGljZSgpOwogICAgY2xvbmUuZm9udE1hdHJpeCA9IHRoaXMuZm9udE1hdHJpeC5zbGljZSgpOwogICAgcmV0dXJuIGNsb25lOwogIH0KfQpjbGFzcyBFdmFsU3RhdGUgewogIGNvbnN0cnVjdG9yKCkgewogICAgdGhpcy5jdG0gPSBuZXcgRmxvYXQzMkFycmF5KF91dGlsLklERU5USVRZX01BVFJJWCk7CiAgICB0aGlzLmZvbnQgPSBudWxsOwogICAgdGhpcy50ZXh0UmVuZGVyaW5nTW9kZSA9IF91dGlsLlRleHRSZW5kZXJpbmdNb2RlLkZJTEw7CiAgICB0aGlzLmZpbGxDb2xvclNwYWNlID0gX2NvbG9yc3BhY2UuQ29sb3JTcGFjZS5zaW5nbGV0b25zLmdyYXk7CiAgICB0aGlzLnN0cm9rZUNvbG9yU3BhY2UgPSBfY29sb3JzcGFjZS5Db2xvclNwYWNlLnNpbmdsZXRvbnMuZ3JheTsKICB9CiAgY2xvbmUoKSB7CiAgICByZXR1cm4gT2JqZWN0LmNyZWF0ZSh0aGlzKTsKICB9Cn0KY2xhc3MgRXZhbHVhdG9yUHJlcHJvY2Vzc29yIHsKICBzdGF0aWMgZ2V0IG9wTWFwKCkgewogICAgY29uc3QgZ2V0T1BNYXAgPSAoMCwgX2NvcmVfdXRpbHMuZ2V0TG9va3VwVGFibGVGYWN0b3J5KShmdW5jdGlvbiAodCkgewogICAgICB0LncgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zZXRMaW5lV2lkdGgsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuSiA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnNldExpbmVDYXAsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuaiA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnNldExpbmVKb2luLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0Lk0gPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zZXRNaXRlckxpbWl0LAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LmQgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zZXREYXNoLAogICAgICAgIG51bUFyZ3M6IDIsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LnJpID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuc2V0UmVuZGVyaW5nSW50ZW50LAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LmkgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zZXRGbGF0bmVzcywKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5ncyA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnNldEdTdGF0ZSwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5xID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuc2F2ZSwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5RID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMucmVzdG9yZSwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5jbSA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnRyYW5zZm9ybSwKICAgICAgICBudW1BcmdzOiA2LAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5tID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMubW92ZVRvLAogICAgICAgIG51bUFyZ3M6IDIsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LmwgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5saW5lVG8sCiAgICAgICAgbnVtQXJnczogMiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuYyA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLmN1cnZlVG8sCiAgICAgICAgbnVtQXJnczogNiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQudiA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLmN1cnZlVG8yLAogICAgICAgIG51bUFyZ3M6IDQsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LnkgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5jdXJ2ZVRvMywKICAgICAgICBudW1BcmdzOiA0LAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5oID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuY2xvc2VQYXRoLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LnJlID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMucmVjdGFuZ2xlLAogICAgICAgIG51bUFyZ3M6IDQsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LlMgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zdHJva2UsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQucyA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLmNsb3NlU3Ryb2tlLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LmYgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5maWxsLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LkYgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5maWxsLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0WyJmKiJdID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuZW9GaWxsLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LkIgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5maWxsU3Ryb2tlLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0WyJCKiJdID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuZW9GaWxsU3Ryb2tlLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LmIgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5jbG9zZUZpbGxTdHJva2UsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHRbImIqIl0gPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5jbG9zZUVPRmlsbFN0cm9rZSwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5uID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuZW5kUGF0aCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5XID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuY2xpcCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdFsiVyoiXSA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLmVvQ2xpcCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5CVCA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLmJlZ2luVGV4dCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5FVCA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLmVuZFRleHQsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuVGMgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zZXRDaGFyU3BhY2luZywKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5UdyA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnNldFdvcmRTcGFjaW5nLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LlR6ID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuc2V0SFNjYWxlLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LlRMID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuc2V0TGVhZGluZywKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5UZiA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnNldEZvbnQsCiAgICAgICAgbnVtQXJnczogMiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuVHIgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zZXRUZXh0UmVuZGVyaW5nTW9kZSwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5UcyA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnNldFRleHRSaXNlLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LlRkID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMubW92ZVRleHQsCiAgICAgICAgbnVtQXJnczogMiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuVEQgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zZXRMZWFkaW5nTW92ZVRleHQsCiAgICAgICAgbnVtQXJnczogMiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuVG0gPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zZXRUZXh0TWF0cml4LAogICAgICAgIG51bUFyZ3M6IDYsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0WyJUKiJdID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMubmV4dExpbmUsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuVGogPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zaG93VGV4dCwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5USiA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnNob3dTcGFjZWRUZXh0LAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0WyInIl0gPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5uZXh0TGluZVNob3dUZXh0LAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0WyciJ10gPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5uZXh0TGluZVNldFNwYWNpbmdTaG93VGV4dCwKICAgICAgICBudW1BcmdzOiAzLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5kMCA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnNldENoYXJXaWR0aCwKICAgICAgICBudW1BcmdzOiAyLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5kMSA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnNldENoYXJXaWR0aEFuZEJvdW5kcywKICAgICAgICBudW1BcmdzOiA2LAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5DUyA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnNldFN0cm9rZUNvbG9yU3BhY2UsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuY3MgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zZXRGaWxsQ29sb3JTcGFjZSwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5TQyA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnNldFN0cm9rZUNvbG9yLAogICAgICAgIG51bUFyZ3M6IDQsCiAgICAgICAgdmFyaWFibGVBcmdzOiB0cnVlCiAgICAgIH07CiAgICAgIHQuU0NOID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuc2V0U3Ryb2tlQ29sb3JOLAogICAgICAgIG51bUFyZ3M6IDMzLAogICAgICAgIHZhcmlhYmxlQXJnczogdHJ1ZQogICAgICB9OwogICAgICB0LnNjID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuc2V0RmlsbENvbG9yLAogICAgICAgIG51bUFyZ3M6IDQsCiAgICAgICAgdmFyaWFibGVBcmdzOiB0cnVlCiAgICAgIH07CiAgICAgIHQuc2NuID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuc2V0RmlsbENvbG9yTiwKICAgICAgICBudW1BcmdzOiAzMywKICAgICAgICB2YXJpYWJsZUFyZ3M6IHRydWUKICAgICAgfTsKICAgICAgdC5HID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuc2V0U3Ryb2tlR3JheSwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5nID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuc2V0RmlsbEdyYXksCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuUkcgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zZXRTdHJva2VSR0JDb2xvciwKICAgICAgICBudW1BcmdzOiAzLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5yZyA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnNldEZpbGxSR0JDb2xvciwKICAgICAgICBudW1BcmdzOiAzLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5LID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuc2V0U3Ryb2tlQ01ZS0NvbG9yLAogICAgICAgIG51bUFyZ3M6IDQsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LmsgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5zZXRGaWxsQ01ZS0NvbG9yLAogICAgICAgIG51bUFyZ3M6IDQsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LnNoID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuc2hhZGluZ0ZpbGwsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuQkkgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5iZWdpbklubGluZUltYWdlLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LklEID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuYmVnaW5JbWFnZURhdGEsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuRUkgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5lbmRJbmxpbmVJbWFnZSwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5EbyA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLnBhaW50WE9iamVjdCwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5NUCA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLm1hcmtQb2ludCwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5EUCA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLm1hcmtQb2ludFByb3BzLAogICAgICAgIG51bUFyZ3M6IDIsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LkJNQyA9IHsKICAgICAgICBpZDogX3V0aWwuT1BTLmJlZ2luTWFya2VkQ29udGVudCwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5CREMgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5iZWdpbk1hcmtlZENvbnRlbnRQcm9wcywKICAgICAgICBudW1BcmdzOiAyLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfTsKICAgICAgdC5FTUMgPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5lbmRNYXJrZWRDb250ZW50LAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9OwogICAgICB0LkJYID0gewogICAgICAgIGlkOiBfdXRpbC5PUFMuYmVnaW5Db21wYXQsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuRVggPSB7CiAgICAgICAgaWQ6IF91dGlsLk9QUy5lbmRDb21wYXQsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH07CiAgICAgIHQuQk0gPSBudWxsOwogICAgICB0LkJEID0gbnVsbDsKICAgICAgdC50cnVlID0gbnVsbDsKICAgICAgdC5mYSA9IG51bGw7CiAgICAgIHQuZmFsID0gbnVsbDsKICAgICAgdC5mYWxzID0gbnVsbDsKICAgICAgdC5mYWxzZSA9IG51bGw7CiAgICAgIHQubnUgPSBudWxsOwogICAgICB0Lm51bCA9IG51bGw7CiAgICAgIHQubnVsbCA9IG51bGw7CiAgICB9KTsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAib3BNYXAiLCBnZXRPUE1hcCgpKTsKICB9CiAgc3RhdGljIGdldCBNQVhfSU5WQUxJRF9QQVRIX09QUygpIHsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiTUFYX0lOVkFMSURfUEFUSF9PUFMiLCAxMCk7CiAgfQogIGNvbnN0cnVjdG9yKHN0cmVhbSwgeHJlZikgewogICAgbGV0IHN0YXRlTWFuYWdlciA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogbmV3IFN0YXRlTWFuYWdlcigpOwogICAgdGhpcy5wYXJzZXIgPSBuZXcgX3BhcnNlci5QYXJzZXIoewogICAgICBsZXhlcjogbmV3IF9wYXJzZXIuTGV4ZXIoc3RyZWFtLCBFdmFsdWF0b3JQcmVwcm9jZXNzb3Iub3BNYXApLAogICAgICB4cmVmCiAgICB9KTsKICAgIHRoaXMuc3RhdGVNYW5hZ2VyID0gc3RhdGVNYW5hZ2VyOwogICAgdGhpcy5ub25Qcm9jZXNzZWRBcmdzID0gW107CiAgICB0aGlzLl9pc1BhdGhPcCA9IGZhbHNlOwogICAgdGhpcy5fbnVtSW52YWxpZFBhdGhPUFMgPSAwOwogIH0KICBnZXQgc2F2ZWRTdGF0ZXNEZXB0aCgpIHsKICAgIHJldHVybiB0aGlzLnN0YXRlTWFuYWdlci5zdGF0ZVN0YWNrLmxlbmd0aDsKICB9CiAgcmVhZChvcGVyYXRpb24pIHsKICAgIGxldCBhcmdzID0gb3BlcmF0aW9uLmFyZ3M7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBjb25zdCBvYmogPSB0aGlzLnBhcnNlci5nZXRPYmooKTsKICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkNtZCkgewogICAgICAgIGNvbnN0IGNtZCA9IG9iai5jbWQ7CiAgICAgICAgY29uc3Qgb3BTcGVjID0gRXZhbHVhdG9yUHJlcHJvY2Vzc29yLm9wTWFwW2NtZF07CiAgICAgICAgaWYgKCFvcFNwZWMpIHsKICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgVW5rbm93biBjb21tYW5kICIke2NtZH0iLmApOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGZuID0gb3BTcGVjLmlkOwogICAgICAgIGNvbnN0IG51bUFyZ3MgPSBvcFNwZWMubnVtQXJnczsKICAgICAgICBsZXQgYXJnc0xlbmd0aCA9IGFyZ3MgIT09IG51bGwgPyBhcmdzLmxlbmd0aCA6IDA7CiAgICAgICAgaWYgKCF0aGlzLl9pc1BhdGhPcCkgewogICAgICAgICAgdGhpcy5fbnVtSW52YWxpZFBhdGhPUFMgPSAwOwogICAgICAgIH0KICAgICAgICB0aGlzLl9pc1BhdGhPcCA9IGZuID49IF91dGlsLk9QUy5tb3ZlVG8gJiYgZm4gPD0gX3V0aWwuT1BTLmVuZFBhdGg7CiAgICAgICAgaWYgKCFvcFNwZWMudmFyaWFibGVBcmdzKSB7CiAgICAgICAgICBpZiAoYXJnc0xlbmd0aCAhPT0gbnVtQXJncykgewogICAgICAgICAgICBjb25zdCBub25Qcm9jZXNzZWRBcmdzID0gdGhpcy5ub25Qcm9jZXNzZWRBcmdzOwogICAgICAgICAgICB3aGlsZSAoYXJnc0xlbmd0aCA+IG51bUFyZ3MpIHsKICAgICAgICAgICAgICBub25Qcm9jZXNzZWRBcmdzLnB1c2goYXJncy5zaGlmdCgpKTsKICAgICAgICAgICAgICBhcmdzTGVuZ3RoLS07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgd2hpbGUgKGFyZ3NMZW5ndGggPCBudW1BcmdzICYmIG5vblByb2Nlc3NlZEFyZ3MubGVuZ3RoICE9PSAwKSB7CiAgICAgICAgICAgICAgaWYgKGFyZ3MgPT09IG51bGwpIHsKICAgICAgICAgICAgICAgIGFyZ3MgPSBbXTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYXJncy51bnNoaWZ0KG5vblByb2Nlc3NlZEFyZ3MucG9wKCkpOwogICAgICAgICAgICAgIGFyZ3NMZW5ndGgrKzsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGFyZ3NMZW5ndGggPCBudW1BcmdzKSB7CiAgICAgICAgICAgIGNvbnN0IHBhcnRpYWxNc2cgPSBgY29tbWFuZCAke2NtZH06IGV4cGVjdGVkICR7bnVtQXJnc30gYXJncywgYCArIGBidXQgcmVjZWl2ZWQgJHthcmdzTGVuZ3RofSBhcmdzLmA7CiAgICAgICAgICAgIGlmICh0aGlzLl9pc1BhdGhPcCAmJiArK3RoaXMuX251bUludmFsaWRQYXRoT1BTID4gRXZhbHVhdG9yUHJlcHJvY2Vzc29yLk1BWF9JTlZBTElEX1BBVEhfT1BTKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBJbnZhbGlkICR7cGFydGlhbE1zZ31gKTsKICAgICAgICAgICAgfQogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYFNraXBwaW5nICR7cGFydGlhbE1zZ31gKTsKICAgICAgICAgICAgaWYgKGFyZ3MgIT09IG51bGwpIHsKICAgICAgICAgICAgICBhcmdzLmxlbmd0aCA9IDA7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChhcmdzTGVuZ3RoID4gbnVtQXJncykgewogICAgICAgICAgKDAsIF91dGlsLmluZm8pKGBDb21tYW5kICR7Y21kfTogZXhwZWN0ZWQgWzAsICR7bnVtQXJnc31dIGFyZ3MsIGAgKyBgYnV0IHJlY2VpdmVkICR7YXJnc0xlbmd0aH0gYXJncy5gKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5wcmVwcm9jZXNzQ29tbWFuZChmbiwgYXJncyk7CiAgICAgICAgb3BlcmF0aW9uLmZuID0gZm47CiAgICAgICAgb3BlcmF0aW9uLmFyZ3MgPSBhcmdzOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmIChvYmogPT09IF9wcmltaXRpdmVzLkVPRikgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAob2JqICE9PSBudWxsKSB7CiAgICAgICAgaWYgKGFyZ3MgPT09IG51bGwpIHsKICAgICAgICAgIGFyZ3MgPSBbXTsKICAgICAgICB9CiAgICAgICAgYXJncy5wdXNoKG9iaik7CiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID4gMzMpIHsKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiVG9vIG1hbnkgYXJndW1lbnRzIik7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQogIHByZXByb2Nlc3NDb21tYW5kKGZuLCBhcmdzKSB7CiAgICBzd2l0Y2ggKGZuIHwgMCkgewogICAgICBjYXNlIF91dGlsLk9QUy5zYXZlOgogICAgICAgIHRoaXMuc3RhdGVNYW5hZ2VyLnNhdmUoKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBfdXRpbC5PUFMucmVzdG9yZToKICAgICAgICB0aGlzLnN0YXRlTWFuYWdlci5yZXN0b3JlKCk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgX3V0aWwuT1BTLnRyYW5zZm9ybToKICAgICAgICB0aGlzLnN0YXRlTWFuYWdlci50cmFuc2Zvcm0oYXJncyk7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgfQp9CmV4cG9ydHMuRXZhbHVhdG9yUHJlcHJvY2Vzc29yID0gRXZhbHVhdG9yUHJlcHJvY2Vzc29yOwoKLyoqKi8gfSksCi8qIDE1MCAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuSWRlbnRpdHlDTWFwID0gZXhwb3J0cy5DTWFwRmFjdG9yeSA9IGV4cG9ydHMuQ01hcCA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9wcmltaXRpdmVzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDApOwp2YXIgX2Jhc2Vfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDEpOwp2YXIgX3BhcnNlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTUxKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQ0KTsKY29uc3QgQlVJTFRfSU5fQ01BUFMgPSBbIkFkb2JlLUdCMS1VQ1MyIiwgIkFkb2JlLUNOUzEtVUNTMiIsICJBZG9iZS1KYXBhbjEtVUNTMiIsICJBZG9iZS1Lb3JlYTEtVUNTMiIsICI3OC1FVUMtSCIsICI3OC1FVUMtViIsICI3OC1IIiwgIjc4LVJLU0otSCIsICI3OC1SS1NKLVYiLCAiNzgtViIsICI3OG1zLVJLU0otSCIsICI3OG1zLVJLU0otViIsICI4M3B2LVJLU0otSCIsICI5MG1zLVJLU0otSCIsICI5MG1zLVJLU0otViIsICI5MG1zcC1SS1NKLUgiLCAiOTBtc3AtUktTSi1WIiwgIjkwcHYtUktTSi1IIiwgIjkwcHYtUktTSi1WIiwgIkFkZC1IIiwgIkFkZC1SS1NKLUgiLCAiQWRkLVJLU0otViIsICJBZGQtViIsICJBZG9iZS1DTlMxLTAiLCAiQWRvYmUtQ05TMS0xIiwgIkFkb2JlLUNOUzEtMiIsICJBZG9iZS1DTlMxLTMiLCAiQWRvYmUtQ05TMS00IiwgIkFkb2JlLUNOUzEtNSIsICJBZG9iZS1DTlMxLTYiLCAiQWRvYmUtR0IxLTAiLCAiQWRvYmUtR0IxLTEiLCAiQWRvYmUtR0IxLTIiLCAiQWRvYmUtR0IxLTMiLCAiQWRvYmUtR0IxLTQiLCAiQWRvYmUtR0IxLTUiLCAiQWRvYmUtSmFwYW4xLTAiLCAiQWRvYmUtSmFwYW4xLTEiLCAiQWRvYmUtSmFwYW4xLTIiLCAiQWRvYmUtSmFwYW4xLTMiLCAiQWRvYmUtSmFwYW4xLTQiLCAiQWRvYmUtSmFwYW4xLTUiLCAiQWRvYmUtSmFwYW4xLTYiLCAiQWRvYmUtS29yZWExLTAiLCAiQWRvYmUtS29yZWExLTEiLCAiQWRvYmUtS29yZWExLTIiLCAiQjUtSCIsICJCNS1WIiwgIkI1cGMtSCIsICJCNXBjLVYiLCAiQ05TLUVVQy1IIiwgIkNOUy1FVUMtViIsICJDTlMxLUgiLCAiQ05TMS1WIiwgIkNOUzItSCIsICJDTlMyLVYiLCAiRVRISy1CNS1IIiwgIkVUSEstQjUtViIsICJFVGVuLUI1LUgiLCAiRVRlbi1CNS1WIiwgIkVUZW5tcy1CNS1IIiwgIkVUZW5tcy1CNS1WIiwgIkVVQy1IIiwgIkVVQy1WIiwgIkV4dC1IIiwgIkV4dC1SS1NKLUgiLCAiRXh0LVJLU0otViIsICJFeHQtViIsICJHQi1FVUMtSCIsICJHQi1FVUMtViIsICJHQi1IIiwgIkdCLVYiLCAiR0JLLUVVQy1IIiwgIkdCSy1FVUMtViIsICJHQksySy1IIiwgIkdCSzJLLVYiLCAiR0JLcC1FVUMtSCIsICJHQktwLUVVQy1WIiwgIkdCVC1FVUMtSCIsICJHQlQtRVVDLVYiLCAiR0JULUgiLCAiR0JULVYiLCAiR0JUcGMtRVVDLUgiLCAiR0JUcGMtRVVDLVYiLCAiR0JwYy1FVUMtSCIsICJHQnBjLUVVQy1WIiwgIkgiLCAiSEtkbGEtQjUtSCIsICJIS2RsYS1CNS1WIiwgIkhLZGxiLUI1LUgiLCAiSEtkbGItQjUtViIsICJIS2djY3MtQjUtSCIsICJIS2djY3MtQjUtViIsICJIS20zMTQtQjUtSCIsICJIS20zMTQtQjUtViIsICJIS200NzEtQjUtSCIsICJIS200NzEtQjUtViIsICJIS3Njcy1CNS1IIiwgIkhLc2NzLUI1LVYiLCAiSGFua2FrdSIsICJIaXJhZ2FuYSIsICJLU0MtRVVDLUgiLCAiS1NDLUVVQy1WIiwgIktTQy1IIiwgIktTQy1Kb2hhYi1IIiwgIktTQy1Kb2hhYi1WIiwgIktTQy1WIiwgIktTQ21zLVVIQy1IIiwgIktTQ21zLVVIQy1IVy1IIiwgIktTQ21zLVVIQy1IVy1WIiwgIktTQ21zLVVIQy1WIiwgIktTQ3BjLUVVQy1IIiwgIktTQ3BjLUVVQy1WIiwgIkthdGFrYW5hIiwgIk5XUC1IIiwgIk5XUC1WIiwgIlJLU0otSCIsICJSS1NKLVYiLCAiUm9tYW4iLCAiVW5pQ05TLVVDUzItSCIsICJVbmlDTlMtVUNTMi1WIiwgIlVuaUNOUy1VVEYxNi1IIiwgIlVuaUNOUy1VVEYxNi1WIiwgIlVuaUNOUy1VVEYzMi1IIiwgIlVuaUNOUy1VVEYzMi1WIiwgIlVuaUNOUy1VVEY4LUgiLCAiVW5pQ05TLVVURjgtViIsICJVbmlHQi1VQ1MyLUgiLCAiVW5pR0ItVUNTMi1WIiwgIlVuaUdCLVVURjE2LUgiLCAiVW5pR0ItVVRGMTYtViIsICJVbmlHQi1VVEYzMi1IIiwgIlVuaUdCLVVURjMyLVYiLCAiVW5pR0ItVVRGOC1IIiwgIlVuaUdCLVVURjgtViIsICJVbmlKSVMtVUNTMi1IIiwgIlVuaUpJUy1VQ1MyLUhXLUgiLCAiVW5pSklTLVVDUzItSFctViIsICJVbmlKSVMtVUNTMi1WIiwgIlVuaUpJUy1VVEYxNi1IIiwgIlVuaUpJUy1VVEYxNi1WIiwgIlVuaUpJUy1VVEYzMi1IIiwgIlVuaUpJUy1VVEYzMi1WIiwgIlVuaUpJUy1VVEY4LUgiLCAiVW5pSklTLVVURjgtViIsICJVbmlKSVMyMDA0LVVURjE2LUgiLCAiVW5pSklTMjAwNC1VVEYxNi1WIiwgIlVuaUpJUzIwMDQtVVRGMzItSCIsICJVbmlKSVMyMDA0LVVURjMyLVYiLCAiVW5pSklTMjAwNC1VVEY4LUgiLCAiVW5pSklTMjAwNC1VVEY4LVYiLCAiVW5pSklTUHJvLVVDUzItSFctViIsICJVbmlKSVNQcm8tVUNTMi1WIiwgIlVuaUpJU1Byby1VVEY4LVYiLCAiVW5pSklTWDAyMTMtVVRGMzItSCIsICJVbmlKSVNYMDIxMy1VVEYzMi1WIiwgIlVuaUpJU1gwMjEzMjAwNC1VVEYzMi1IIiwgIlVuaUpJU1gwMjEzMjAwNC1VVEYzMi1WIiwgIlVuaUtTLVVDUzItSCIsICJVbmlLUy1VQ1MyLVYiLCAiVW5pS1MtVVRGMTYtSCIsICJVbmlLUy1VVEYxNi1WIiwgIlVuaUtTLVVURjMyLUgiLCAiVW5pS1MtVVRGMzItViIsICJVbmlLUy1VVEY4LUgiLCAiVW5pS1MtVVRGOC1WIiwgIlYiLCAiV1AtU3ltYm9sIl07CmNvbnN0IE1BWF9NQVBfUkFOR0UgPSAyICoqIDI0IC0gMTsKY2xhc3MgQ01hcCB7CiAgY29uc3RydWN0b3IoKSB7CiAgICBsZXQgYnVpbHRJbkNNYXAgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgdGhpcy5jb2Rlc3BhY2VSYW5nZXMgPSBbW10sIFtdLCBbXSwgW11dOwogICAgdGhpcy5udW1Db2Rlc3BhY2VSYW5nZXMgPSAwOwogICAgdGhpcy5fbWFwID0gW107CiAgICB0aGlzLm5hbWUgPSAiIjsKICAgIHRoaXMudmVydGljYWwgPSBmYWxzZTsKICAgIHRoaXMudXNlQ01hcCA9IG51bGw7CiAgICB0aGlzLmJ1aWx0SW5DTWFwID0gYnVpbHRJbkNNYXA7CiAgfQogIGFkZENvZGVzcGFjZVJhbmdlKG4sIGxvdywgaGlnaCkgewogICAgdGhpcy5jb2Rlc3BhY2VSYW5nZXNbbiAtIDFdLnB1c2gobG93LCBoaWdoKTsKICAgIHRoaXMubnVtQ29kZXNwYWNlUmFuZ2VzKys7CiAgfQogIG1hcENpZFJhbmdlKGxvdywgaGlnaCwgZHN0TG93KSB7CiAgICBpZiAoaGlnaCAtIGxvdyA+IE1BWF9NQVBfUkFOR0UpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJtYXBDaWRSYW5nZSAtIGlnbm9yaW5nIGRhdGEgYWJvdmUgTUFYX01BUF9SQU5HRS4iKTsKICAgIH0KICAgIHdoaWxlIChsb3cgPD0gaGlnaCkgewogICAgICB0aGlzLl9tYXBbbG93KytdID0gZHN0TG93Kys7CiAgICB9CiAgfQogIG1hcEJmUmFuZ2UobG93LCBoaWdoLCBkc3RMb3cpIHsKICAgIGlmIChoaWdoIC0gbG93ID4gTUFYX01BUF9SQU5HRSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIm1hcEJmUmFuZ2UgLSBpZ25vcmluZyBkYXRhIGFib3ZlIE1BWF9NQVBfUkFOR0UuIik7CiAgICB9CiAgICBjb25zdCBsYXN0Qnl0ZSA9IGRzdExvdy5sZW5ndGggLSAxOwogICAgd2hpbGUgKGxvdyA8PSBoaWdoKSB7CiAgICAgIHRoaXMuX21hcFtsb3crK10gPSBkc3RMb3c7CiAgICAgIGNvbnN0IG5leHRDaGFyQ29kZSA9IGRzdExvdy5jaGFyQ29kZUF0KGxhc3RCeXRlKSArIDE7CiAgICAgIGlmIChuZXh0Q2hhckNvZGUgPiAweGZmKSB7CiAgICAgICAgZHN0TG93ID0gZHN0TG93LnN1YnN0cmluZygwLCBsYXN0Qnl0ZSAtIDEpICsgU3RyaW5nLmZyb21DaGFyQ29kZShkc3RMb3cuY2hhckNvZGVBdChsYXN0Qnl0ZSAtIDEpICsgMSkgKyAiXHgwMCI7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZHN0TG93ID0gZHN0TG93LnN1YnN0cmluZygwLCBsYXN0Qnl0ZSkgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKG5leHRDaGFyQ29kZSk7CiAgICB9CiAgfQogIG1hcEJmUmFuZ2VUb0FycmF5KGxvdywgaGlnaCwgYXJyYXkpIHsKICAgIGlmIChoaWdoIC0gbG93ID4gTUFYX01BUF9SQU5HRSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIm1hcEJmUmFuZ2VUb0FycmF5IC0gaWdub3JpbmcgZGF0YSBhYm92ZSBNQVhfTUFQX1JBTkdFLiIpOwogICAgfQogICAgY29uc3QgaWkgPSBhcnJheS5sZW5ndGg7CiAgICBsZXQgaSA9IDA7CiAgICB3aGlsZSAobG93IDw9IGhpZ2ggJiYgaSA8IGlpKSB7CiAgICAgIHRoaXMuX21hcFtsb3ddID0gYXJyYXlbaSsrXTsKICAgICAgKytsb3c7CiAgICB9CiAgfQogIG1hcE9uZShzcmMsIGRzdCkgewogICAgdGhpcy5fbWFwW3NyY10gPSBkc3Q7CiAgfQogIGxvb2t1cChjb2RlKSB7CiAgICByZXR1cm4gdGhpcy5fbWFwW2NvZGVdOwogIH0KICBjb250YWlucyhjb2RlKSB7CiAgICByZXR1cm4gdGhpcy5fbWFwW2NvZGVdICE9PSB1bmRlZmluZWQ7CiAgfQogIGZvckVhY2goY2FsbGJhY2spIHsKICAgIGNvbnN0IG1hcCA9IHRoaXMuX21hcDsKICAgIGNvbnN0IGxlbmd0aCA9IG1hcC5sZW5ndGg7CiAgICBpZiAobGVuZ3RoIDw9IDB4MTAwMDApIHsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgIGlmIChtYXBbaV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgY2FsbGJhY2soaSwgbWFwW2ldKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGZvciAoY29uc3QgaSBpbiBtYXApIHsKICAgICAgICBjYWxsYmFjayhpLCBtYXBbaV0pOwogICAgICB9CiAgICB9CiAgfQogIGNoYXJDb2RlT2YodmFsdWUpIHsKICAgIGNvbnN0IG1hcCA9IHRoaXMuX21hcDsKICAgIGlmIChtYXAubGVuZ3RoIDw9IDB4MTAwMDApIHsKICAgICAgcmV0dXJuIG1hcC5pbmRleE9mKHZhbHVlKTsKICAgIH0KICAgIGZvciAoY29uc3QgY2hhckNvZGUgaW4gbWFwKSB7CiAgICAgIGlmIChtYXBbY2hhckNvZGVdID09PSB2YWx1ZSkgewogICAgICAgIHJldHVybiBjaGFyQ29kZSB8IDA7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiAtMTsKICB9CiAgZ2V0TWFwKCkgewogICAgcmV0dXJuIHRoaXMuX21hcDsKICB9CiAgcmVhZENoYXJDb2RlKHN0ciwgb2Zmc2V0LCBvdXQpIHsKICAgIGxldCBjID0gMDsKICAgIGNvbnN0IGNvZGVzcGFjZVJhbmdlcyA9IHRoaXMuY29kZXNwYWNlUmFuZ2VzOwogICAgZm9yIChsZXQgbiA9IDAsIG5uID0gY29kZXNwYWNlUmFuZ2VzLmxlbmd0aDsgbiA8IG5uOyBuKyspIHsKICAgICAgYyA9IChjIDw8IDggfCBzdHIuY2hhckNvZGVBdChvZmZzZXQgKyBuKSkgPj4+IDA7CiAgICAgIGNvbnN0IGNvZGVzcGFjZVJhbmdlID0gY29kZXNwYWNlUmFuZ2VzW25dOwogICAgICBmb3IgKGxldCBrID0gMCwga2sgPSBjb2Rlc3BhY2VSYW5nZS5sZW5ndGg7IGsgPCBrazspIHsKICAgICAgICBjb25zdCBsb3cgPSBjb2Rlc3BhY2VSYW5nZVtrKytdOwogICAgICAgIGNvbnN0IGhpZ2ggPSBjb2Rlc3BhY2VSYW5nZVtrKytdOwogICAgICAgIGlmIChjID49IGxvdyAmJiBjIDw9IGhpZ2gpIHsKICAgICAgICAgIG91dC5jaGFyY29kZSA9IGM7CiAgICAgICAgICBvdXQubGVuZ3RoID0gbiArIDE7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBvdXQuY2hhcmNvZGUgPSAwOwogICAgb3V0Lmxlbmd0aCA9IDE7CiAgfQogIGdldENoYXJDb2RlTGVuZ3RoKGNoYXJDb2RlKSB7CiAgICBjb25zdCBjb2Rlc3BhY2VSYW5nZXMgPSB0aGlzLmNvZGVzcGFjZVJhbmdlczsKICAgIGZvciAobGV0IG4gPSAwLCBubiA9IGNvZGVzcGFjZVJhbmdlcy5sZW5ndGg7IG4gPCBubjsgbisrKSB7CiAgICAgIGNvbnN0IGNvZGVzcGFjZVJhbmdlID0gY29kZXNwYWNlUmFuZ2VzW25dOwogICAgICBmb3IgKGxldCBrID0gMCwga2sgPSBjb2Rlc3BhY2VSYW5nZS5sZW5ndGg7IGsgPCBrazspIHsKICAgICAgICBjb25zdCBsb3cgPSBjb2Rlc3BhY2VSYW5nZVtrKytdOwogICAgICAgIGNvbnN0IGhpZ2ggPSBjb2Rlc3BhY2VSYW5nZVtrKytdOwogICAgICAgIGlmIChjaGFyQ29kZSA+PSBsb3cgJiYgY2hhckNvZGUgPD0gaGlnaCkgewogICAgICAgICAgcmV0dXJuIG4gKyAxOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIDE7CiAgfQogIGdldCBsZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5fbWFwLmxlbmd0aDsKICB9CiAgZ2V0IGlzSWRlbnRpdHlDTWFwKCkgewogICAgaWYgKCEodGhpcy5uYW1lID09PSAiSWRlbnRpdHktSCIgfHwgdGhpcy5uYW1lID09PSAiSWRlbnRpdHktViIpKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmICh0aGlzLl9tYXAubGVuZ3RoICE9PSAweDEwMDAwKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMHgxMDAwMDsgaSsrKSB7CiAgICAgIGlmICh0aGlzLl9tYXBbaV0gIT09IGkpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB0cnVlOwogIH0KfQpleHBvcnRzLkNNYXAgPSBDTWFwOwpjbGFzcyBJZGVudGl0eUNNYXAgZXh0ZW5kcyBDTWFwIHsKICBjb25zdHJ1Y3Rvcih2ZXJ0aWNhbCwgbikgewogICAgc3VwZXIoKTsKICAgIHRoaXMudmVydGljYWwgPSB2ZXJ0aWNhbDsKICAgIHRoaXMuYWRkQ29kZXNwYWNlUmFuZ2UobiwgMCwgMHhmZmZmKTsKICB9CiAgbWFwQ2lkUmFuZ2UobG93LCBoaWdoLCBkc3RMb3cpIHsKICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoInNob3VsZCBub3QgY2FsbCBtYXBDaWRSYW5nZSIpOwogIH0KICBtYXBCZlJhbmdlKGxvdywgaGlnaCwgZHN0TG93KSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJzaG91bGQgbm90IGNhbGwgbWFwQmZSYW5nZSIpOwogIH0KICBtYXBCZlJhbmdlVG9BcnJheShsb3csIGhpZ2gsIGFycmF5KSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJzaG91bGQgbm90IGNhbGwgbWFwQmZSYW5nZVRvQXJyYXkiKTsKICB9CiAgbWFwT25lKHNyYywgZHN0KSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJzaG91bGQgbm90IGNhbGwgbWFwQ2lkT25lIik7CiAgfQogIGxvb2t1cChjb2RlKSB7CiAgICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcihjb2RlKSAmJiBjb2RlIDw9IDB4ZmZmZiA/IGNvZGUgOiB1bmRlZmluZWQ7CiAgfQogIGNvbnRhaW5zKGNvZGUpIHsKICAgIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKGNvZGUpICYmIGNvZGUgPD0gMHhmZmZmOwogIH0KICBmb3JFYWNoKGNhbGxiYWNrKSB7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8PSAweGZmZmY7IGkrKykgewogICAgICBjYWxsYmFjayhpLCBpKTsKICAgIH0KICB9CiAgY2hhckNvZGVPZih2YWx1ZSkgewogICAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIodmFsdWUpICYmIHZhbHVlIDw9IDB4ZmZmZiA/IHZhbHVlIDogLTE7CiAgfQogIGdldE1hcCgpIHsKICAgIGNvbnN0IG1hcCA9IG5ldyBBcnJheSgweDEwMDAwKTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IDB4ZmZmZjsgaSsrKSB7CiAgICAgIG1hcFtpXSA9IGk7CiAgICB9CiAgICByZXR1cm4gbWFwOwogIH0KICBnZXQgbGVuZ3RoKCkgewogICAgcmV0dXJuIDB4MTAwMDA7CiAgfQogIGdldCBpc0lkZW50aXR5Q01hcCgpIHsKICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoInNob3VsZCBub3QgYWNjZXNzIC5pc0lkZW50aXR5Q01hcCIpOwogIH0KfQpleHBvcnRzLklkZW50aXR5Q01hcCA9IElkZW50aXR5Q01hcDsKY29uc3QgQmluYXJ5Q01hcFJlYWRlciA9IGZ1bmN0aW9uIEJpbmFyeUNNYXBSZWFkZXJDbG9zdXJlKCkgewogIGZ1bmN0aW9uIGhleFRvSW50KGEsIHNpemUpIHsKICAgIGxldCBuID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IHNpemU7IGkrKykgewogICAgICBuID0gbiA8PCA4IHwgYVtpXTsKICAgIH0KICAgIHJldHVybiBuID4+PiAwOwogIH0KICBmdW5jdGlvbiBoZXhUb1N0cihhLCBzaXplKSB7CiAgICBpZiAoc2l6ZSA9PT0gMSkgewogICAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShhWzBdLCBhWzFdKTsKICAgIH0KICAgIGlmIChzaXplID09PSAzKSB7CiAgICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKGFbMF0sIGFbMV0sIGFbMl0sIGFbM10pOwogICAgfQogICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgYS5zdWJhcnJheSgwLCBzaXplICsgMSkpOwogIH0KICBmdW5jdGlvbiBhZGRIZXgoYSwgYiwgc2l6ZSkgewogICAgbGV0IGMgPSAwOwogICAgZm9yIChsZXQgaSA9IHNpemU7IGkgPj0gMDsgaS0tKSB7CiAgICAgIGMgKz0gYVtpXSArIGJbaV07CiAgICAgIGFbaV0gPSBjICYgMjU1OwogICAgICBjID4+PSA4OwogICAgfQogIH0KICBmdW5jdGlvbiBpbmNIZXgoYSwgc2l6ZSkgewogICAgbGV0IGMgPSAxOwogICAgZm9yIChsZXQgaSA9IHNpemU7IGkgPj0gMCAmJiBjID4gMDsgaS0tKSB7CiAgICAgIGMgKz0gYVtpXTsKICAgICAgYVtpXSA9IGMgJiAyNTU7CiAgICAgIGMgPj49IDg7CiAgICB9CiAgfQogIGNvbnN0IE1BWF9OVU1fU0laRSA9IDE2OwogIGNvbnN0IE1BWF9FTkNPREVEX05VTV9TSVpFID0gMTk7CiAgY2xhc3MgQmluYXJ5Q01hcFN0cmVhbSB7CiAgICBjb25zdHJ1Y3RvcihkYXRhKSB7CiAgICAgIHRoaXMuYnVmZmVyID0gZGF0YTsKICAgICAgdGhpcy5wb3MgPSAwOwogICAgICB0aGlzLmVuZCA9IGRhdGEubGVuZ3RoOwogICAgICB0aGlzLnRtcEJ1ZiA9IG5ldyBVaW50OEFycmF5KE1BWF9FTkNPREVEX05VTV9TSVpFKTsKICAgIH0KICAgIHJlYWRCeXRlKCkgewogICAgICBpZiAodGhpcy5wb3MgPj0gdGhpcy5lbmQpIHsKICAgICAgICByZXR1cm4gLTE7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuYnVmZmVyW3RoaXMucG9zKytdOwogICAgfQogICAgcmVhZE51bWJlcigpIHsKICAgICAgbGV0IG4gPSAwOwogICAgICBsZXQgbGFzdDsKICAgICAgZG8gewogICAgICAgIGNvbnN0IGIgPSB0aGlzLnJlYWRCeXRlKCk7CiAgICAgICAgaWYgKGIgPCAwKSB7CiAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoInVuZXhwZWN0ZWQgRU9GIGluIGJjbWFwIik7CiAgICAgICAgfQogICAgICAgIGxhc3QgPSAhKGIgJiAweDgwKTsKICAgICAgICBuID0gbiA8PCA3IHwgYiAmIDB4N2Y7CiAgICAgIH0gd2hpbGUgKCFsYXN0KTsKICAgICAgcmV0dXJuIG47CiAgICB9CiAgICByZWFkU2lnbmVkKCkgewogICAgICBjb25zdCBuID0gdGhpcy5yZWFkTnVtYmVyKCk7CiAgICAgIHJldHVybiBuICYgMSA/IH4obiA+Pj4gMSkgOiBuID4+PiAxOwogICAgfQogICAgcmVhZEhleChudW0sIHNpemUpIHsKICAgICAgbnVtLnNldCh0aGlzLmJ1ZmZlci5zdWJhcnJheSh0aGlzLnBvcywgdGhpcy5wb3MgKyBzaXplICsgMSkpOwogICAgICB0aGlzLnBvcyArPSBzaXplICsgMTsKICAgIH0KICAgIHJlYWRIZXhOdW1iZXIobnVtLCBzaXplKSB7CiAgICAgIGxldCBsYXN0OwogICAgICBjb25zdCBzdGFjayA9IHRoaXMudG1wQnVmOwogICAgICBsZXQgc3AgPSAwOwogICAgICBkbyB7CiAgICAgICAgY29uc3QgYiA9IHRoaXMucmVhZEJ5dGUoKTsKICAgICAgICBpZiAoYiA8IDApIHsKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigidW5leHBlY3RlZCBFT0YgaW4gYmNtYXAiKTsKICAgICAgICB9CiAgICAgICAgbGFzdCA9ICEoYiAmIDB4ODApOwogICAgICAgIHN0YWNrW3NwKytdID0gYiAmIDB4N2Y7CiAgICAgIH0gd2hpbGUgKCFsYXN0KTsKICAgICAgbGV0IGkgPSBzaXplLAogICAgICAgIGJ1ZmZlciA9IDAsCiAgICAgICAgYnVmZmVyU2l6ZSA9IDA7CiAgICAgIHdoaWxlIChpID49IDApIHsKICAgICAgICB3aGlsZSAoYnVmZmVyU2l6ZSA8IDggJiYgc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgICAgYnVmZmVyIHw9IHN0YWNrWy0tc3BdIDw8IGJ1ZmZlclNpemU7CiAgICAgICAgICBidWZmZXJTaXplICs9IDc7CiAgICAgICAgfQogICAgICAgIG51bVtpXSA9IGJ1ZmZlciAmIDI1NTsKICAgICAgICBpLS07CiAgICAgICAgYnVmZmVyID4+PSA4OwogICAgICAgIGJ1ZmZlclNpemUgLT0gODsKICAgICAgfQogICAgfQogICAgcmVhZEhleFNpZ25lZChudW0sIHNpemUpIHsKICAgICAgdGhpcy5yZWFkSGV4TnVtYmVyKG51bSwgc2l6ZSk7CiAgICAgIGNvbnN0IHNpZ24gPSBudW1bc2l6ZV0gJiAxID8gMjU1IDogMDsKICAgICAgbGV0IGMgPSAwOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8PSBzaXplOyBpKyspIHsKICAgICAgICBjID0gKGMgJiAxKSA8PCA4IHwgbnVtW2ldOwogICAgICAgIG51bVtpXSA9IGMgPj4gMSBeIHNpZ247CiAgICAgIH0KICAgIH0KICAgIHJlYWRTdHJpbmcoKSB7CiAgICAgIGNvbnN0IGxlbiA9IHRoaXMucmVhZE51bWJlcigpOwogICAgICBsZXQgcyA9ICIiOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7CiAgICAgICAgcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHRoaXMucmVhZE51bWJlcigpKTsKICAgICAgfQogICAgICByZXR1cm4gczsKICAgIH0KICB9CiAgY2xhc3MgQmluYXJ5Q01hcFJlYWRlciB7CiAgICBhc3luYyBwcm9jZXNzKGRhdGEsIGNNYXAsIGV4dGVuZCkgewogICAgICBjb25zdCBzdHJlYW0gPSBuZXcgQmluYXJ5Q01hcFN0cmVhbShkYXRhKTsKICAgICAgY29uc3QgaGVhZGVyID0gc3RyZWFtLnJlYWRCeXRlKCk7CiAgICAgIGNNYXAudmVydGljYWwgPSAhIShoZWFkZXIgJiAxKTsKICAgICAgbGV0IHVzZUNNYXAgPSBudWxsOwogICAgICBjb25zdCBzdGFydCA9IG5ldyBVaW50OEFycmF5KE1BWF9OVU1fU0laRSk7CiAgICAgIGNvbnN0IGVuZCA9IG5ldyBVaW50OEFycmF5KE1BWF9OVU1fU0laRSk7CiAgICAgIGNvbnN0IGNoYXIgPSBuZXcgVWludDhBcnJheShNQVhfTlVNX1NJWkUpOwogICAgICBjb25zdCBjaGFyQ29kZSA9IG5ldyBVaW50OEFycmF5KE1BWF9OVU1fU0laRSk7CiAgICAgIGNvbnN0IHRtcCA9IG5ldyBVaW50OEFycmF5KE1BWF9OVU1fU0laRSk7CiAgICAgIGxldCBjb2RlOwogICAgICBsZXQgYjsKICAgICAgd2hpbGUgKChiID0gc3RyZWFtLnJlYWRCeXRlKCkpID49IDApIHsKICAgICAgICBjb25zdCB0eXBlID0gYiA+PiA1OwogICAgICAgIGlmICh0eXBlID09PSA3KSB7CiAgICAgICAgICBzd2l0Y2ggKGIgJiAweDFmKSB7CiAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICBzdHJlYW0ucmVhZFN0cmluZygpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgdXNlQ01hcCA9IHN0cmVhbS5yZWFkU3RyaW5nKCk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc2VxdWVuY2UgPSAhIShiICYgMHgxMCk7CiAgICAgICAgY29uc3QgZGF0YVNpemUgPSBiICYgMTU7CiAgICAgICAgaWYgKGRhdGFTaXplICsgMSA+IE1BWF9OVU1fU0laRSkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJCaW5hcnlDTWFwUmVhZGVyLnByb2Nlc3M6IEludmFsaWQgZGF0YVNpemUuIik7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHVjczJEYXRhU2l6ZSA9IDE7CiAgICAgICAgY29uc3Qgc3ViaXRlbXNDb3VudCA9IHN0cmVhbS5yZWFkTnVtYmVyKCk7CiAgICAgICAgc3dpdGNoICh0eXBlKSB7CiAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgIHN0cmVhbS5yZWFkSGV4KHN0YXJ0LCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIHN0cmVhbS5yZWFkSGV4TnVtYmVyKGVuZCwgZGF0YVNpemUpOwogICAgICAgICAgICBhZGRIZXgoZW5kLCBzdGFydCwgZGF0YVNpemUpOwogICAgICAgICAgICBjTWFwLmFkZENvZGVzcGFjZVJhbmdlKGRhdGFTaXplICsgMSwgaGV4VG9JbnQoc3RhcnQsIGRhdGFTaXplKSwgaGV4VG9JbnQoZW5kLCBkYXRhU2l6ZSkpOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHN1Yml0ZW1zQ291bnQ7IGkrKykgewogICAgICAgICAgICAgIGluY0hleChlbmQsIGRhdGFTaXplKTsKICAgICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihzdGFydCwgZGF0YVNpemUpOwogICAgICAgICAgICAgIGFkZEhleChzdGFydCwgZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgICAgYWRkSGV4KGVuZCwgc3RhcnQsIGRhdGFTaXplKTsKICAgICAgICAgICAgICBjTWFwLmFkZENvZGVzcGFjZVJhbmdlKGRhdGFTaXplICsgMSwgaGV4VG9JbnQoc3RhcnQsIGRhdGFTaXplKSwgaGV4VG9JbnQoZW5kLCBkYXRhU2l6ZSkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICBzdHJlYW0ucmVhZEhleChzdGFydCwgZGF0YVNpemUpOwogICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihlbmQsIGRhdGFTaXplKTsKICAgICAgICAgICAgYWRkSGV4KGVuZCwgc3RhcnQsIGRhdGFTaXplKTsKICAgICAgICAgICAgc3RyZWFtLnJlYWROdW1iZXIoKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBzdWJpdGVtc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgICBpbmNIZXgoZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoc3RhcnQsIGRhdGFTaXplKTsKICAgICAgICAgICAgICBhZGRIZXgoc3RhcnQsIGVuZCwgZGF0YVNpemUpOwogICAgICAgICAgICAgIHN0cmVhbS5yZWFkSGV4TnVtYmVyKGVuZCwgZGF0YVNpemUpOwogICAgICAgICAgICAgIGFkZEhleChlbmQsIHN0YXJ0LCBkYXRhU2l6ZSk7CiAgICAgICAgICAgICAgc3RyZWFtLnJlYWROdW1iZXIoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXgoY2hhciwgZGF0YVNpemUpOwogICAgICAgICAgICBjb2RlID0gc3RyZWFtLnJlYWROdW1iZXIoKTsKICAgICAgICAgICAgY01hcC5tYXBPbmUoaGV4VG9JbnQoY2hhciwgZGF0YVNpemUpLCBjb2RlKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBzdWJpdGVtc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgICBpbmNIZXgoY2hhciwgZGF0YVNpemUpOwogICAgICAgICAgICAgIGlmICghc2VxdWVuY2UpIHsKICAgICAgICAgICAgICAgIHN0cmVhbS5yZWFkSGV4TnVtYmVyKHRtcCwgZGF0YVNpemUpOwogICAgICAgICAgICAgICAgYWRkSGV4KGNoYXIsIHRtcCwgZGF0YVNpemUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb2RlID0gc3RyZWFtLnJlYWRTaWduZWQoKSArIChjb2RlICsgMSk7CiAgICAgICAgICAgICAgY01hcC5tYXBPbmUoaGV4VG9JbnQoY2hhciwgZGF0YVNpemUpLCBjb2RlKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXgoc3RhcnQsIGRhdGFTaXplKTsKICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIGFkZEhleChlbmQsIHN0YXJ0LCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIGNvZGUgPSBzdHJlYW0ucmVhZE51bWJlcigpOwogICAgICAgICAgICBjTWFwLm1hcENpZFJhbmdlKGhleFRvSW50KHN0YXJ0LCBkYXRhU2l6ZSksIGhleFRvSW50KGVuZCwgZGF0YVNpemUpLCBjb2RlKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBzdWJpdGVtc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgICBpbmNIZXgoZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgICAgaWYgKCFzZXF1ZW5jZSkgewogICAgICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoc3RhcnQsIGRhdGFTaXplKTsKICAgICAgICAgICAgICAgIGFkZEhleChzdGFydCwgZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHN0YXJ0LnNldChlbmQpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihlbmQsIGRhdGFTaXplKTsKICAgICAgICAgICAgICBhZGRIZXgoZW5kLCBzdGFydCwgZGF0YVNpemUpOwogICAgICAgICAgICAgIGNvZGUgPSBzdHJlYW0ucmVhZE51bWJlcigpOwogICAgICAgICAgICAgIGNNYXAubWFwQ2lkUmFuZ2UoaGV4VG9JbnQoc3RhcnQsIGRhdGFTaXplKSwgaGV4VG9JbnQoZW5kLCBkYXRhU2l6ZSksIGNvZGUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICBzdHJlYW0ucmVhZEhleChjaGFyLCB1Y3MyRGF0YVNpemUpOwogICAgICAgICAgICBzdHJlYW0ucmVhZEhleChjaGFyQ29kZSwgZGF0YVNpemUpOwogICAgICAgICAgICBjTWFwLm1hcE9uZShoZXhUb0ludChjaGFyLCB1Y3MyRGF0YVNpemUpLCBoZXhUb1N0cihjaGFyQ29kZSwgZGF0YVNpemUpKTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBzdWJpdGVtc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgICBpbmNIZXgoY2hhciwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgICAgICBpZiAoIXNlcXVlbmNlKSB7CiAgICAgICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcih0bXAsIHVjczJEYXRhU2l6ZSk7CiAgICAgICAgICAgICAgICBhZGRIZXgoY2hhciwgdG1wLCB1Y3MyRGF0YVNpemUpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpbmNIZXgoY2hhckNvZGUsIGRhdGFTaXplKTsKICAgICAgICAgICAgICBzdHJlYW0ucmVhZEhleFNpZ25lZCh0bXAsIGRhdGFTaXplKTsKICAgICAgICAgICAgICBhZGRIZXgoY2hhckNvZGUsIHRtcCwgZGF0YVNpemUpOwogICAgICAgICAgICAgIGNNYXAubWFwT25lKGhleFRvSW50KGNoYXIsIHVjczJEYXRhU2l6ZSksIGhleFRvU3RyKGNoYXJDb2RlLCBkYXRhU2l6ZSkpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSA1OgogICAgICAgICAgICBzdHJlYW0ucmVhZEhleChzdGFydCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoZW5kLCB1Y3MyRGF0YVNpemUpOwogICAgICAgICAgICBhZGRIZXgoZW5kLCBzdGFydCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXgoY2hhckNvZGUsIGRhdGFTaXplKTsKICAgICAgICAgICAgY01hcC5tYXBCZlJhbmdlKGhleFRvSW50KHN0YXJ0LCB1Y3MyRGF0YVNpemUpLCBoZXhUb0ludChlbmQsIHVjczJEYXRhU2l6ZSksIGhleFRvU3RyKGNoYXJDb2RlLCBkYXRhU2l6ZSkpOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHN1Yml0ZW1zQ291bnQ7IGkrKykgewogICAgICAgICAgICAgIGluY0hleChlbmQsIHVjczJEYXRhU2l6ZSk7CiAgICAgICAgICAgICAgaWYgKCFzZXF1ZW5jZSkgewogICAgICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoc3RhcnQsIHVjczJEYXRhU2l6ZSk7CiAgICAgICAgICAgICAgICBhZGRIZXgoc3RhcnQsIGVuZCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgc3RhcnQuc2V0KGVuZCk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHN0cmVhbS5yZWFkSGV4TnVtYmVyKGVuZCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgICAgICBhZGRIZXgoZW5kLCBzdGFydCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgICAgICBzdHJlYW0ucmVhZEhleChjaGFyQ29kZSwgZGF0YVNpemUpOwogICAgICAgICAgICAgIGNNYXAubWFwQmZSYW5nZShoZXhUb0ludChzdGFydCwgdWNzMkRhdGFTaXplKSwgaGV4VG9JbnQoZW5kLCB1Y3MyRGF0YVNpemUpLCBoZXhUb1N0cihjaGFyQ29kZSwgZGF0YVNpemUpKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQmluYXJ5Q01hcFJlYWRlci5wcm9jZXNzIC0gdW5rbm93biB0eXBlOiAke3R5cGV9YCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICh1c2VDTWFwKSB7CiAgICAgICAgcmV0dXJuIGV4dGVuZCh1c2VDTWFwKTsKICAgICAgfQogICAgICByZXR1cm4gY01hcDsKICAgIH0KICB9CiAgcmV0dXJuIEJpbmFyeUNNYXBSZWFkZXI7Cn0oKTsKY29uc3QgQ01hcEZhY3RvcnkgPSBmdW5jdGlvbiBDTWFwRmFjdG9yeUNsb3N1cmUoKSB7CiAgZnVuY3Rpb24gc3RyVG9JbnQoc3RyKSB7CiAgICBsZXQgYSA9IDA7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykgewogICAgICBhID0gYSA8PCA4IHwgc3RyLmNoYXJDb2RlQXQoaSk7CiAgICB9CiAgICByZXR1cm4gYSA+Pj4gMDsKICB9CiAgZnVuY3Rpb24gZXhwZWN0U3RyaW5nKG9iaikgewogICAgaWYgKHR5cGVvZiBvYmogIT09ICJzdHJpbmciKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiTWFsZm9ybWVkIENNYXA6IGV4cGVjdGVkIHN0cmluZy4iKTsKICAgIH0KICB9CiAgZnVuY3Rpb24gZXhwZWN0SW50KG9iaikgewogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKG9iaikpIHsKICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJNYWxmb3JtZWQgQ01hcDogZXhwZWN0ZWQgaW50LiIpOwogICAgfQogIH0KICBmdW5jdGlvbiBwYXJzZUJmQ2hhcihjTWFwLCBsZXhlcikgewogICAgd2hpbGUgKHRydWUpIHsKICAgICAgbGV0IG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgICBpZiAob2JqID09PSBfcHJpbWl0aXZlcy5FT0YpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAoKDAsIF9wcmltaXRpdmVzLmlzQ21kKShvYmosICJlbmRiZmNoYXIiKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBleHBlY3RTdHJpbmcob2JqKTsKICAgICAgY29uc3Qgc3JjID0gc3RyVG9JbnQob2JqKTsKICAgICAgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICAgIGV4cGVjdFN0cmluZyhvYmopOwogICAgICBjb25zdCBkc3QgPSBvYmo7CiAgICAgIGNNYXAubWFwT25lKHNyYywgZHN0KTsKICAgIH0KICB9CiAgZnVuY3Rpb24gcGFyc2VCZlJhbmdlKGNNYXAsIGxleGVyKSB7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBsZXQgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICAgIGlmIChvYmogPT09IF9wcmltaXRpdmVzLkVPRikgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmICgoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKG9iaiwgImVuZGJmcmFuZ2UiKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBleHBlY3RTdHJpbmcob2JqKTsKICAgICAgY29uc3QgbG93ID0gc3RyVG9JbnQob2JqKTsKICAgICAgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICAgIGV4cGVjdFN0cmluZyhvYmopOwogICAgICBjb25zdCBoaWdoID0gc3RyVG9JbnQob2JqKTsKICAgICAgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKG9iaikgfHwgdHlwZW9mIG9iaiA9PT0gInN0cmluZyIpIHsKICAgICAgICBjb25zdCBkc3RMb3cgPSBOdW1iZXIuaXNJbnRlZ2VyKG9iaikgPyBTdHJpbmcuZnJvbUNoYXJDb2RlKG9iaikgOiBvYmo7CiAgICAgICAgY01hcC5tYXBCZlJhbmdlKGxvdywgaGlnaCwgZHN0TG93KTsKICAgICAgfSBlbHNlIGlmICgoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKG9iaiwgIlsiKSkgewogICAgICAgIG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgICAgIGNvbnN0IGFycmF5ID0gW107CiAgICAgICAgd2hpbGUgKCEoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKG9iaiwgIl0iKSAmJiBvYmogIT09IF9wcmltaXRpdmVzLkVPRikgewogICAgICAgICAgYXJyYXkucHVzaChvYmopOwogICAgICAgICAgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICAgICAgfQogICAgICAgIGNNYXAubWFwQmZSYW5nZVRvQXJyYXkobG93LCBoaWdoLCBhcnJheSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCBiZiByYW5nZS4iKTsKICB9CiAgZnVuY3Rpb24gcGFyc2VDaWRDaGFyKGNNYXAsIGxleGVyKSB7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBsZXQgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICAgIGlmIChvYmogPT09IF9wcmltaXRpdmVzLkVPRikgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmICgoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKG9iaiwgImVuZGNpZGNoYXIiKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBleHBlY3RTdHJpbmcob2JqKTsKICAgICAgY29uc3Qgc3JjID0gc3RyVG9JbnQob2JqKTsKICAgICAgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICAgIGV4cGVjdEludChvYmopOwogICAgICBjb25zdCBkc3QgPSBvYmo7CiAgICAgIGNNYXAubWFwT25lKHNyYywgZHN0KTsKICAgIH0KICB9CiAgZnVuY3Rpb24gcGFyc2VDaWRSYW5nZShjTWFwLCBsZXhlcikgewogICAgd2hpbGUgKHRydWUpIHsKICAgICAgbGV0IG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgICBpZiAob2JqID09PSBfcHJpbWl0aXZlcy5FT0YpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAoKDAsIF9wcmltaXRpdmVzLmlzQ21kKShvYmosICJlbmRjaWRyYW5nZSIpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGV4cGVjdFN0cmluZyhvYmopOwogICAgICBjb25zdCBsb3cgPSBzdHJUb0ludChvYmopOwogICAgICBvYmogPSBsZXhlci5nZXRPYmooKTsKICAgICAgZXhwZWN0U3RyaW5nKG9iaik7CiAgICAgIGNvbnN0IGhpZ2ggPSBzdHJUb0ludChvYmopOwogICAgICBvYmogPSBsZXhlci5nZXRPYmooKTsKICAgICAgZXhwZWN0SW50KG9iaik7CiAgICAgIGNvbnN0IGRzdExvdyA9IG9iajsKICAgICAgY01hcC5tYXBDaWRSYW5nZShsb3csIGhpZ2gsIGRzdExvdyk7CiAgICB9CiAgfQogIGZ1bmN0aW9uIHBhcnNlQ29kZXNwYWNlUmFuZ2UoY01hcCwgbGV4ZXIpIHsKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIGxldCBvYmogPSBsZXhlci5nZXRPYmooKTsKICAgICAgaWYgKG9iaiA9PT0gX3ByaW1pdGl2ZXMuRU9GKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKCgwLCBfcHJpbWl0aXZlcy5pc0NtZCkob2JqLCAiZW5kY29kZXNwYWNlcmFuZ2UiKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBpZiAodHlwZW9mIG9iaiAhPT0gInN0cmluZyIpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBjb25zdCBsb3cgPSBzdHJUb0ludChvYmopOwogICAgICBvYmogPSBsZXhlci5nZXRPYmooKTsKICAgICAgaWYgKHR5cGVvZiBvYmogIT09ICJzdHJpbmciKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY29uc3QgaGlnaCA9IHN0clRvSW50KG9iaik7CiAgICAgIGNNYXAuYWRkQ29kZXNwYWNlUmFuZ2Uob2JqLmxlbmd0aCwgbG93LCBoaWdoKTsKICAgIH0KICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCBjb2Rlc3BhY2UgcmFuZ2UuIik7CiAgfQogIGZ1bmN0aW9uIHBhcnNlV01vZGUoY01hcCwgbGV4ZXIpIHsKICAgIGNvbnN0IG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgaWYgKE51bWJlci5pc0ludGVnZXIob2JqKSkgewogICAgICBjTWFwLnZlcnRpY2FsID0gISFvYmo7CiAgICB9CiAgfQogIGZ1bmN0aW9uIHBhcnNlQ01hcE5hbWUoY01hcCwgbGV4ZXIpIHsKICAgIGNvbnN0IG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgaWYgKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgY01hcC5uYW1lID0gb2JqLm5hbWU7CiAgICB9CiAgfQogIGFzeW5jIGZ1bmN0aW9uIHBhcnNlQ01hcChjTWFwLCBsZXhlciwgZmV0Y2hCdWlsdEluQ01hcCwgdXNlQ01hcCkgewogICAgbGV0IHByZXZpb3VzLCBlbWJlZGRlZFVzZUNNYXA7CiAgICBvYmpMb29wOiB3aGlsZSAodHJ1ZSkgewogICAgICB0cnkgewogICAgICAgIGNvbnN0IG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgICAgIGlmIChvYmogPT09IF9wcmltaXRpdmVzLkVPRikgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgICAgICBpZiAob2JqLm5hbWUgPT09ICJXTW9kZSIpIHsKICAgICAgICAgICAgcGFyc2VXTW9kZShjTWFwLCBsZXhlcik7CiAgICAgICAgICB9IGVsc2UgaWYgKG9iai5uYW1lID09PSAiQ01hcE5hbWUiKSB7CiAgICAgICAgICAgIHBhcnNlQ01hcE5hbWUoY01hcCwgbGV4ZXIpOwogICAgICAgICAgfQogICAgICAgICAgcHJldmlvdXMgPSBvYmo7CiAgICAgICAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5DbWQpIHsKICAgICAgICAgIHN3aXRjaCAob2JqLmNtZCkgewogICAgICAgICAgICBjYXNlICJlbmRjbWFwIjoKICAgICAgICAgICAgICBicmVhayBvYmpMb29wOwogICAgICAgICAgICBjYXNlICJ1c2VjbWFwIjoKICAgICAgICAgICAgICBpZiAocHJldmlvdXMgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgICAgICAgICAgICBlbWJlZGRlZFVzZUNNYXAgPSBwcmV2aW91cy5uYW1lOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYmVnaW5jb2Rlc3BhY2VyYW5nZSI6CiAgICAgICAgICAgICAgcGFyc2VDb2Rlc3BhY2VSYW5nZShjTWFwLCBsZXhlcik7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImJlZ2luYmZjaGFyIjoKICAgICAgICAgICAgICBwYXJzZUJmQ2hhcihjTWFwLCBsZXhlcik7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgImJlZ2luY2lkY2hhciI6CiAgICAgICAgICAgICAgcGFyc2VDaWRDaGFyKGNNYXAsIGxleGVyKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiYmVnaW5iZnJhbmdlIjoKICAgICAgICAgICAgICBwYXJzZUJmUmFuZ2UoY01hcCwgbGV4ZXIpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJiZWdpbmNpZHJhbmdlIjoKICAgICAgICAgICAgICBwYXJzZUNpZFJhbmdlKGNNYXAsIGxleGVyKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgX2NvcmVfdXRpbHMuTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICAgIHRocm93IGV4OwogICAgICAgIH0KICAgICAgICAoMCwgX3V0aWwud2FybikoIkludmFsaWQgY01hcCBkYXRhOiAiICsgZXgpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICB9CiAgICBpZiAoIXVzZUNNYXAgJiYgZW1iZWRkZWRVc2VDTWFwKSB7CiAgICAgIHVzZUNNYXAgPSBlbWJlZGRlZFVzZUNNYXA7CiAgICB9CiAgICBpZiAodXNlQ01hcCkgewogICAgICByZXR1cm4gZXh0ZW5kQ01hcChjTWFwLCBmZXRjaEJ1aWx0SW5DTWFwLCB1c2VDTWFwKTsKICAgIH0KICAgIHJldHVybiBjTWFwOwogIH0KICBhc3luYyBmdW5jdGlvbiBleHRlbmRDTWFwKGNNYXAsIGZldGNoQnVpbHRJbkNNYXAsIHVzZUNNYXApIHsKICAgIGNNYXAudXNlQ01hcCA9IGF3YWl0IGNyZWF0ZUJ1aWx0SW5DTWFwKHVzZUNNYXAsIGZldGNoQnVpbHRJbkNNYXApOwogICAgaWYgKGNNYXAubnVtQ29kZXNwYWNlUmFuZ2VzID09PSAwKSB7CiAgICAgIGNvbnN0IHVzZUNvZGVzcGFjZVJhbmdlcyA9IGNNYXAudXNlQ01hcC5jb2Rlc3BhY2VSYW5nZXM7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdXNlQ29kZXNwYWNlUmFuZ2VzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgY01hcC5jb2Rlc3BhY2VSYW5nZXNbaV0gPSB1c2VDb2Rlc3BhY2VSYW5nZXNbaV0uc2xpY2UoKTsKICAgICAgfQogICAgICBjTWFwLm51bUNvZGVzcGFjZVJhbmdlcyA9IGNNYXAudXNlQ01hcC5udW1Db2Rlc3BhY2VSYW5nZXM7CiAgICB9CiAgICBjTWFwLnVzZUNNYXAuZm9yRWFjaChmdW5jdGlvbiAoa2V5LCB2YWx1ZSkgewogICAgICBpZiAoIWNNYXAuY29udGFpbnMoa2V5KSkgewogICAgICAgIGNNYXAubWFwT25lKGtleSwgY01hcC51c2VDTWFwLmxvb2t1cChrZXkpKTsKICAgICAgfQogICAgfSk7CiAgICByZXR1cm4gY01hcDsKICB9CiAgYXN5bmMgZnVuY3Rpb24gY3JlYXRlQnVpbHRJbkNNYXAobmFtZSwgZmV0Y2hCdWlsdEluQ01hcCkgewogICAgaWYgKG5hbWUgPT09ICJJZGVudGl0eS1IIikgewogICAgICByZXR1cm4gbmV3IElkZW50aXR5Q01hcChmYWxzZSwgMik7CiAgICB9IGVsc2UgaWYgKG5hbWUgPT09ICJJZGVudGl0eS1WIikgewogICAgICByZXR1cm4gbmV3IElkZW50aXR5Q01hcCh0cnVlLCAyKTsKICAgIH0KICAgIGlmICghQlVJTFRfSU5fQ01BUFMuaW5jbHVkZXMobmFtZSkpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJVbmtub3duIENNYXAgbmFtZTogIiArIG5hbWUpOwogICAgfQogICAgaWYgKCFmZXRjaEJ1aWx0SW5DTWFwKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiQnVpbHQtaW4gQ01hcCBwYXJhbWV0ZXJzIGFyZSBub3QgcHJvdmlkZWQuIik7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIGNNYXBEYXRhLAogICAgICBjb21wcmVzc2lvblR5cGUKICAgIH0gPSBhd2FpdCBmZXRjaEJ1aWx0SW5DTWFwKG5hbWUpOwogICAgY29uc3QgY01hcCA9IG5ldyBDTWFwKHRydWUpOwogICAgaWYgKGNvbXByZXNzaW9uVHlwZSA9PT0gX3V0aWwuQ01hcENvbXByZXNzaW9uVHlwZS5CSU5BUlkpIHsKICAgICAgcmV0dXJuIG5ldyBCaW5hcnlDTWFwUmVhZGVyKCkucHJvY2VzcyhjTWFwRGF0YSwgY01hcCwgdXNlQ01hcCA9PiB7CiAgICAgICAgcmV0dXJuIGV4dGVuZENNYXAoY01hcCwgZmV0Y2hCdWlsdEluQ01hcCwgdXNlQ01hcCk7CiAgICAgIH0pOwogICAgfQogICAgaWYgKGNvbXByZXNzaW9uVHlwZSA9PT0gX3V0aWwuQ01hcENvbXByZXNzaW9uVHlwZS5OT05FKSB7CiAgICAgIGNvbnN0IGxleGVyID0gbmV3IF9wYXJzZXIuTGV4ZXIobmV3IF9zdHJlYW0uU3RyZWFtKGNNYXBEYXRhKSk7CiAgICAgIHJldHVybiBwYXJzZUNNYXAoY01hcCwgbGV4ZXIsIGZldGNoQnVpbHRJbkNNYXAsIG51bGwpOwogICAgfQogICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIENNYXAgImNvbXByZXNzaW9uVHlwZSIgdmFsdWU6ICR7Y29tcHJlc3Npb25UeXBlfWApOwogIH0KICByZXR1cm4gewogICAgYXN5bmMgY3JlYXRlKHBhcmFtcykgewogICAgICBjb25zdCBlbmNvZGluZyA9IHBhcmFtcy5lbmNvZGluZzsKICAgICAgY29uc3QgZmV0Y2hCdWlsdEluQ01hcCA9IHBhcmFtcy5mZXRjaEJ1aWx0SW5DTWFwOwogICAgICBjb25zdCB1c2VDTWFwID0gcGFyYW1zLnVzZUNNYXA7CiAgICAgIGlmIChlbmNvZGluZyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgICByZXR1cm4gY3JlYXRlQnVpbHRJbkNNYXAoZW5jb2RpbmcubmFtZSwgZmV0Y2hCdWlsdEluQ01hcCk7CiAgICAgIH0gZWxzZSBpZiAoZW5jb2RpbmcgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkgewogICAgICAgIGNvbnN0IHBhcnNlZENNYXAgPSBhd2FpdCBwYXJzZUNNYXAobmV3IENNYXAoKSwgbmV3IF9wYXJzZXIuTGV4ZXIoZW5jb2RpbmcpLCBmZXRjaEJ1aWx0SW5DTWFwLCB1c2VDTWFwKTsKICAgICAgICBpZiAocGFyc2VkQ01hcC5pc0lkZW50aXR5Q01hcCkgewogICAgICAgICAgcmV0dXJuIGNyZWF0ZUJ1aWx0SW5DTWFwKHBhcnNlZENNYXAubmFtZSwgZmV0Y2hCdWlsdEluQ01hcCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBwYXJzZWRDTWFwOwogICAgICB9CiAgICAgIHRocm93IG5ldyBFcnJvcigiRW5jb2RpbmcgcmVxdWlyZWQuIik7CiAgICB9CiAgfTsKfSgpOwpleHBvcnRzLkNNYXBGYWN0b3J5ID0gQ01hcEZhY3Rvcnk7CgovKioqLyB9KSwKLyogMTUxICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5QYXJzZXIgPSBleHBvcnRzLkxpbmVhcml6YXRpb24gPSBleHBvcnRzLkxleGVyID0gdm9pZCAwOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwp2YXIgX3ByaW1pdGl2ZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MCk7CnZhciBfY29yZV91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTM5KTsKdmFyIF9hc2NpaV84NV9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1Mik7CnZhciBfYXNjaWlfaGV4X3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTU0KTsKdmFyIF9jY2l0dF9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1NSk7CnZhciBfZmxhdGVfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTcpOwp2YXIgX2piaWcyX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTU4KTsKdmFyIF9qcGVnX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTYxKTsKdmFyIF9qcHhfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNjQpOwp2YXIgX2x6d19zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE2Nik7CnZhciBfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDQpOwp2YXIgX3ByZWRpY3Rvcl9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE2Nyk7CnZhciBfcnVuX2xlbmd0aF9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE2OCk7CmNvbnN0IE1BWF9MRU5HVEhfVE9fQ0FDSEUgPSAxMDAwOwpmdW5jdGlvbiBnZXRJbmxpbmVJbWFnZUNhY2hlS2V5KGJ5dGVzKSB7CiAgY29uc3Qgc3RyQnVmID0gW10sCiAgICBpaSA9IGJ5dGVzLmxlbmd0aDsKICBsZXQgaSA9IDA7CiAgd2hpbGUgKGkgPCBpaSAtIDEpIHsKICAgIHN0ckJ1Zi5wdXNoKGJ5dGVzW2krK10gPDwgOCB8IGJ5dGVzW2krK10pOwogIH0KICBpZiAoaSA8IGlpKSB7CiAgICBzdHJCdWYucHVzaChieXRlc1tpXSk7CiAgfQogIHJldHVybiBpaSArICJfIiArIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgc3RyQnVmKTsKfQpjbGFzcyBQYXJzZXIgewogIGNvbnN0cnVjdG9yKF9yZWYpIHsKICAgIGxldCB7CiAgICAgIGxleGVyLAogICAgICB4cmVmLAogICAgICBhbGxvd1N0cmVhbXMgPSBmYWxzZSwKICAgICAgcmVjb3ZlcnlNb2RlID0gZmFsc2UKICAgIH0gPSBfcmVmOwogICAgdGhpcy5sZXhlciA9IGxleGVyOwogICAgdGhpcy54cmVmID0geHJlZjsKICAgIHRoaXMuYWxsb3dTdHJlYW1zID0gYWxsb3dTdHJlYW1zOwogICAgdGhpcy5yZWNvdmVyeU1vZGUgPSByZWNvdmVyeU1vZGU7CiAgICB0aGlzLmltYWdlQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgdGhpcy5faW1hZ2VJZCA9IDA7CiAgICB0aGlzLnJlZmlsbCgpOwogIH0KICByZWZpbGwoKSB7CiAgICB0aGlzLmJ1ZjEgPSB0aGlzLmxleGVyLmdldE9iaigpOwogICAgdGhpcy5idWYyID0gdGhpcy5sZXhlci5nZXRPYmooKTsKICB9CiAgc2hpZnQoKSB7CiAgICBpZiAodGhpcy5idWYyIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuQ21kICYmIHRoaXMuYnVmMi5jbWQgPT09ICJJRCIpIHsKICAgICAgdGhpcy5idWYxID0gdGhpcy5idWYyOwogICAgICB0aGlzLmJ1ZjIgPSBudWxsOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5idWYxID0gdGhpcy5idWYyOwogICAgICB0aGlzLmJ1ZjIgPSB0aGlzLmxleGVyLmdldE9iaigpOwogICAgfQogIH0KICB0cnlTaGlmdCgpIHsKICAgIHRyeSB7CiAgICAgIHRoaXMuc2hpZnQoKTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIGlmIChlIGluc3RhbmNlb2YgX2NvcmVfdXRpbHMuTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBlOwogICAgICB9CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9CiAgZ2V0T2JqKCkgewogICAgbGV0IGNpcGhlclRyYW5zZm9ybSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbnVsbDsKICAgIGNvbnN0IGJ1ZjEgPSB0aGlzLmJ1ZjE7CiAgICB0aGlzLnNoaWZ0KCk7CiAgICBpZiAoYnVmMSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkNtZCkgewogICAgICBzd2l0Y2ggKGJ1ZjEuY21kKSB7CiAgICAgICAgY2FzZSAiQkkiOgogICAgICAgICAgcmV0dXJuIHRoaXMubWFrZUlubGluZUltYWdlKGNpcGhlclRyYW5zZm9ybSk7CiAgICAgICAgY2FzZSAiWyI6CiAgICAgICAgICBjb25zdCBhcnJheSA9IFtdOwogICAgICAgICAgd2hpbGUgKCEoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKHRoaXMuYnVmMSwgIl0iKSAmJiB0aGlzLmJ1ZjEgIT09IF9wcmltaXRpdmVzLkVPRikgewogICAgICAgICAgICBhcnJheS5wdXNoKHRoaXMuZ2V0T2JqKGNpcGhlclRyYW5zZm9ybSkpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHRoaXMuYnVmMSA9PT0gX3ByaW1pdGl2ZXMuRU9GKSB7CiAgICAgICAgICAgIGlmICh0aGlzLnJlY292ZXJ5TW9kZSkgewogICAgICAgICAgICAgIHJldHVybiBhcnJheTsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aHJvdyBuZXcgX2NvcmVfdXRpbHMuUGFyc2VyRU9GRXhjZXB0aW9uKCJFbmQgb2YgZmlsZSBpbnNpZGUgYXJyYXkuIik7CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgICAgICByZXR1cm4gYXJyYXk7CiAgICAgICAgY2FzZSAiPDwiOgogICAgICAgICAgY29uc3QgZGljdCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KHRoaXMueHJlZik7CiAgICAgICAgICB3aGlsZSAoISgwLCBfcHJpbWl0aXZlcy5pc0NtZCkodGhpcy5idWYxLCAiPj4iKSAmJiB0aGlzLmJ1ZjEgIT09IF9wcmltaXRpdmVzLkVPRikgewogICAgICAgICAgICBpZiAoISh0aGlzLmJ1ZjEgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSkgewogICAgICAgICAgICAgICgwLCBfdXRpbC5pbmZvKSgiTWFsZm9ybWVkIGRpY3Rpb25hcnk6IGtleSBtdXN0IGJlIGEgbmFtZSBvYmplY3QiKTsKICAgICAgICAgICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3Qga2V5ID0gdGhpcy5idWYxLm5hbWU7CiAgICAgICAgICAgIHRoaXMuc2hpZnQoKTsKICAgICAgICAgICAgaWYgKHRoaXMuYnVmMSA9PT0gX3ByaW1pdGl2ZXMuRU9GKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZGljdC5zZXQoa2V5LCB0aGlzLmdldE9iaihjaXBoZXJUcmFuc2Zvcm0pKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh0aGlzLmJ1ZjEgPT09IF9wcmltaXRpdmVzLkVPRikgewogICAgICAgICAgICBpZiAodGhpcy5yZWNvdmVyeU1vZGUpIHsKICAgICAgICAgICAgICByZXR1cm4gZGljdDsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aHJvdyBuZXcgX2NvcmVfdXRpbHMuUGFyc2VyRU9GRXhjZXB0aW9uKCJFbmQgb2YgZmlsZSBpbnNpZGUgZGljdGlvbmFyeS4iKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICgoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKHRoaXMuYnVmMiwgInN0cmVhbSIpKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmFsbG93U3RyZWFtcyA/IHRoaXMubWFrZVN0cmVhbShkaWN0LCBjaXBoZXJUcmFuc2Zvcm0pIDogZGljdDsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuc2hpZnQoKTsKICAgICAgICAgIHJldHVybiBkaWN0OwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gYnVmMTsKICAgICAgfQogICAgfQogICAgaWYgKE51bWJlci5pc0ludGVnZXIoYnVmMSkpIHsKICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpcy5idWYxKSAmJiAoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKHRoaXMuYnVmMiwgIlIiKSkgewogICAgICAgIGNvbnN0IHJlZiA9IF9wcmltaXRpdmVzLlJlZi5nZXQoYnVmMSwgdGhpcy5idWYxKTsKICAgICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgICAgdGhpcy5zaGlmdCgpOwogICAgICAgIHJldHVybiByZWY7CiAgICAgIH0KICAgICAgcmV0dXJuIGJ1ZjE7CiAgICB9CiAgICBpZiAodHlwZW9mIGJ1ZjEgPT09ICJzdHJpbmciKSB7CiAgICAgIGlmIChjaXBoZXJUcmFuc2Zvcm0pIHsKICAgICAgICByZXR1cm4gY2lwaGVyVHJhbnNmb3JtLmRlY3J5cHRTdHJpbmcoYnVmMSk7CiAgICAgIH0KICAgICAgcmV0dXJuIGJ1ZjE7CiAgICB9CiAgICByZXR1cm4gYnVmMTsKICB9CiAgZmluZERlZmF1bHRJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKSB7CiAgICBjb25zdCBFID0gMHg0NSwKICAgICAgSSA9IDB4NDksCiAgICAgIFNQQUNFID0gMHgyMCwKICAgICAgTEYgPSAweGEsCiAgICAgIENSID0gMHhkLAogICAgICBOVUwgPSAweDA7CiAgICBjb25zdCBsZXhlciA9IHRoaXMubGV4ZXIsCiAgICAgIHN0YXJ0UG9zID0gc3RyZWFtLnBvcywKICAgICAgbiA9IDEwOwogICAgbGV0IHN0YXRlID0gMCwKICAgICAgY2gsCiAgICAgIG1heWJlRUlQb3M7CiAgICB3aGlsZSAoKGNoID0gc3RyZWFtLmdldEJ5dGUoKSkgIT09IC0xKSB7CiAgICAgIGlmIChzdGF0ZSA9PT0gMCkgewogICAgICAgIHN0YXRlID0gY2ggPT09IEUgPyAxIDogMDsKICAgICAgfSBlbHNlIGlmIChzdGF0ZSA9PT0gMSkgewogICAgICAgIHN0YXRlID0gY2ggPT09IEkgPyAyIDogMDsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAoY2ggPT09IFNQQUNFIHx8IGNoID09PSBMRiB8fCBjaCA9PT0gQ1IpIHsKICAgICAgICAgIG1heWJlRUlQb3MgPSBzdHJlYW0ucG9zOwogICAgICAgICAgY29uc3QgZm9sbG93aW5nQnl0ZXMgPSBzdHJlYW0ucGVla0J5dGVzKG4pOwogICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZm9sbG93aW5nQnl0ZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgICBjaCA9IGZvbGxvd2luZ0J5dGVzW2ldOwogICAgICAgICAgICBpZiAoY2ggPT09IE5VTCAmJiBmb2xsb3dpbmdCeXRlc1tpICsgMV0gIT09IE5VTCkgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChjaCAhPT0gTEYgJiYgY2ggIT09IENSICYmIChjaCA8IFNQQUNFIHx8IGNoID4gMHg3ZikpIHsKICAgICAgICAgICAgICBzdGF0ZSA9IDA7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChzdGF0ZSAhPT0gMikgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChsZXhlci5rbm93bkNvbW1hbmRzKSB7CiAgICAgICAgICAgIGNvbnN0IG5leHRPYmogPSBsZXhlci5wZWVrT2JqKCk7CiAgICAgICAgICAgIGlmIChuZXh0T2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuQ21kICYmICFsZXhlci5rbm93bkNvbW1hbmRzW25leHRPYmouY21kXSkgewogICAgICAgICAgICAgIHN0YXRlID0gMDsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJmaW5kRGVmYXVsdElubGluZVN0cmVhbUVuZCAtIGBsZXhlci5rbm93bkNvbW1hbmRzYCBpcyB1bmRlZmluZWQuIik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoc3RhdGUgPT09IDIpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN0YXRlID0gMDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChjaCA9PT0gLTEpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKCJmaW5kRGVmYXVsdElubGluZVN0cmVhbUVuZDogIiArICJSZWFjaGVkIHRoZSBlbmQgb2YgdGhlIHN0cmVhbSB3aXRob3V0IGZpbmRpbmcgYSB2YWxpZCBFSSBtYXJrZXIiKTsKICAgICAgaWYgKG1heWJlRUlQb3MpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoJy4uLiB0cnlpbmcgdG8gcmVjb3ZlciBieSB1c2luZyB0aGUgbGFzdCAiRUkiIG9jY3VycmVuY2UuJyk7CiAgICAgICAgc3RyZWFtLnNraXAoLShzdHJlYW0ucG9zIC0gbWF5YmVFSVBvcykpOwogICAgICB9CiAgICB9CiAgICBsZXQgZW5kT2Zmc2V0ID0gNDsKICAgIHN0cmVhbS5za2lwKC1lbmRPZmZzZXQpOwogICAgY2ggPSBzdHJlYW0ucGVla0J5dGUoKTsKICAgIHN0cmVhbS5za2lwKGVuZE9mZnNldCk7CiAgICBpZiAoISgwLCBfY29yZV91dGlscy5pc1doaXRlU3BhY2UpKGNoKSkgewogICAgICBlbmRPZmZzZXQtLTsKICAgIH0KICAgIHJldHVybiBzdHJlYW0ucG9zIC0gZW5kT2Zmc2V0IC0gc3RhcnRQb3M7CiAgfQogIGZpbmREQ1REZWNvZGVJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKSB7CiAgICBjb25zdCBzdGFydFBvcyA9IHN0cmVhbS5wb3M7CiAgICBsZXQgZm91bmRFT0kgPSBmYWxzZSwKICAgICAgYiwKICAgICAgbWFya2VyTGVuZ3RoOwogICAgd2hpbGUgKChiID0gc3RyZWFtLmdldEJ5dGUoKSkgIT09IC0xKSB7CiAgICAgIGlmIChiICE9PSAweGZmKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgc3dpdGNoIChzdHJlYW0uZ2V0Qnl0ZSgpKSB7CiAgICAgICAgY2FzZSAweDAwOgogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGZmOgogICAgICAgICAgc3RyZWFtLnNraXAoLTEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGQ5OgogICAgICAgICAgZm91bmRFT0kgPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGMwOgogICAgICAgIGNhc2UgMHhjMToKICAgICAgICBjYXNlIDB4YzI6CiAgICAgICAgY2FzZSAweGMzOgogICAgICAgIGNhc2UgMHhjNToKICAgICAgICBjYXNlIDB4YzY6CiAgICAgICAgY2FzZSAweGM3OgogICAgICAgIGNhc2UgMHhjOToKICAgICAgICBjYXNlIDB4Y2E6CiAgICAgICAgY2FzZSAweGNiOgogICAgICAgIGNhc2UgMHhjZDoKICAgICAgICBjYXNlIDB4Y2U6CiAgICAgICAgY2FzZSAweGNmOgogICAgICAgIGNhc2UgMHhjNDoKICAgICAgICBjYXNlIDB4Y2M6CiAgICAgICAgY2FzZSAweGRhOgogICAgICAgIGNhc2UgMHhkYjoKICAgICAgICBjYXNlIDB4ZGM6CiAgICAgICAgY2FzZSAweGRkOgogICAgICAgIGNhc2UgMHhkZToKICAgICAgICBjYXNlIDB4ZGY6CiAgICAgICAgY2FzZSAweGUwOgogICAgICAgIGNhc2UgMHhlMToKICAgICAgICBjYXNlIDB4ZTI6CiAgICAgICAgY2FzZSAweGUzOgogICAgICAgIGNhc2UgMHhlNDoKICAgICAgICBjYXNlIDB4ZTU6CiAgICAgICAgY2FzZSAweGU2OgogICAgICAgIGNhc2UgMHhlNzoKICAgICAgICBjYXNlIDB4ZTg6CiAgICAgICAgY2FzZSAweGU5OgogICAgICAgIGNhc2UgMHhlYToKICAgICAgICBjYXNlIDB4ZWI6CiAgICAgICAgY2FzZSAweGVjOgogICAgICAgIGNhc2UgMHhlZDoKICAgICAgICBjYXNlIDB4ZWU6CiAgICAgICAgY2FzZSAweGVmOgogICAgICAgIGNhc2UgMHhmZToKICAgICAgICAgIG1hcmtlckxlbmd0aCA9IHN0cmVhbS5nZXRVaW50MTYoKTsKICAgICAgICAgIGlmIChtYXJrZXJMZW5ndGggPiAyKSB7CiAgICAgICAgICAgIHN0cmVhbS5za2lwKG1hcmtlckxlbmd0aCAtIDIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RyZWFtLnNraXAoLTIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKGZvdW5kRU9JKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IHN0cmVhbS5wb3MgLSBzdGFydFBvczsKICAgIGlmIChiID09PSAtMSkgewogICAgICAoMCwgX3V0aWwud2FybikoIklubGluZSBEQ1REZWNvZGUgaW1hZ2Ugc3RyZWFtOiAiICsgIkVPSSBtYXJrZXIgbm90IGZvdW5kLCBzZWFyY2hpbmcgZm9yIC9FSS8gaW5zdGVhZC4iKTsKICAgICAgc3RyZWFtLnNraXAoLWxlbmd0aCk7CiAgICAgIHJldHVybiB0aGlzLmZpbmREZWZhdWx0SW5saW5lU3RyZWFtRW5kKHN0cmVhbSk7CiAgICB9CiAgICB0aGlzLmlubGluZVN0cmVhbVNraXBFSShzdHJlYW0pOwogICAgcmV0dXJuIGxlbmd0aDsKICB9CiAgZmluZEFTQ0lJODVEZWNvZGVJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKSB7CiAgICBjb25zdCBUSUxERSA9IDB4N2UsCiAgICAgIEdUID0gMHgzZTsKICAgIGNvbnN0IHN0YXJ0UG9zID0gc3RyZWFtLnBvczsKICAgIGxldCBjaDsKICAgIHdoaWxlICgoY2ggPSBzdHJlYW0uZ2V0Qnl0ZSgpKSAhPT0gLTEpIHsKICAgICAgaWYgKGNoID09PSBUSUxERSkgewogICAgICAgIGNvbnN0IHRpbGRlUG9zID0gc3RyZWFtLnBvczsKICAgICAgICBjaCA9IHN0cmVhbS5wZWVrQnl0ZSgpOwogICAgICAgIHdoaWxlICgoMCwgX2NvcmVfdXRpbHMuaXNXaGl0ZVNwYWNlKShjaCkpIHsKICAgICAgICAgIHN0cmVhbS5za2lwKCk7CiAgICAgICAgICBjaCA9IHN0cmVhbS5wZWVrQnl0ZSgpOwogICAgICAgIH0KICAgICAgICBpZiAoY2ggPT09IEdUKSB7CiAgICAgICAgICBzdHJlYW0uc2tpcCgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmIChzdHJlYW0ucG9zID4gdGlsZGVQb3MpIHsKICAgICAgICAgIGNvbnN0IG1heWJlRUkgPSBzdHJlYW0ucGVla0J5dGVzKDIpOwogICAgICAgICAgaWYgKG1heWJlRUlbMF0gPT09IDB4NDUgJiYgbWF5YmVFSVsxXSA9PT0gMHg0OSkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IHN0cmVhbS5wb3MgLSBzdGFydFBvczsKICAgIGlmIChjaCA9PT0gLTEpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKCJJbmxpbmUgQVNDSUk4NURlY29kZSBpbWFnZSBzdHJlYW06ICIgKyAiRU9EIG1hcmtlciBub3QgZm91bmQsIHNlYXJjaGluZyBmb3IgL0VJLyBpbnN0ZWFkLiIpOwogICAgICBzdHJlYW0uc2tpcCgtbGVuZ3RoKTsKICAgICAgcmV0dXJuIHRoaXMuZmluZERlZmF1bHRJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKTsKICAgIH0KICAgIHRoaXMuaW5saW5lU3RyZWFtU2tpcEVJKHN0cmVhbSk7CiAgICByZXR1cm4gbGVuZ3RoOwogIH0KICBmaW5kQVNDSUlIZXhEZWNvZGVJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKSB7CiAgICBjb25zdCBHVCA9IDB4M2U7CiAgICBjb25zdCBzdGFydFBvcyA9IHN0cmVhbS5wb3M7CiAgICBsZXQgY2g7CiAgICB3aGlsZSAoKGNoID0gc3RyZWFtLmdldEJ5dGUoKSkgIT09IC0xKSB7CiAgICAgIGlmIChjaCA9PT0gR1QpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgY29uc3QgbGVuZ3RoID0gc3RyZWFtLnBvcyAtIHN0YXJ0UG9zOwogICAgaWYgKGNoID09PSAtMSkgewogICAgICAoMCwgX3V0aWwud2FybikoIklubGluZSBBU0NJSUhleERlY29kZSBpbWFnZSBzdHJlYW06ICIgKyAiRU9EIG1hcmtlciBub3QgZm91bmQsIHNlYXJjaGluZyBmb3IgL0VJLyBpbnN0ZWFkLiIpOwogICAgICBzdHJlYW0uc2tpcCgtbGVuZ3RoKTsKICAgICAgcmV0dXJuIHRoaXMuZmluZERlZmF1bHRJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKTsKICAgIH0KICAgIHRoaXMuaW5saW5lU3RyZWFtU2tpcEVJKHN0cmVhbSk7CiAgICByZXR1cm4gbGVuZ3RoOwogIH0KICBpbmxpbmVTdHJlYW1Ta2lwRUkoc3RyZWFtKSB7CiAgICBjb25zdCBFID0gMHg0NSwKICAgICAgSSA9IDB4NDk7CiAgICBsZXQgc3RhdGUgPSAwLAogICAgICBjaDsKICAgIHdoaWxlICgoY2ggPSBzdHJlYW0uZ2V0Qnl0ZSgpKSAhPT0gLTEpIHsKICAgICAgaWYgKHN0YXRlID09PSAwKSB7CiAgICAgICAgc3RhdGUgPSBjaCA9PT0gRSA/IDEgOiAwOwogICAgICB9IGVsc2UgaWYgKHN0YXRlID09PSAxKSB7CiAgICAgICAgc3RhdGUgPSBjaCA9PT0gSSA/IDIgOiAwOwogICAgICB9IGVsc2UgaWYgKHN0YXRlID09PSAyKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICB9CiAgbWFrZUlubGluZUltYWdlKGNpcGhlclRyYW5zZm9ybSkgewogICAgY29uc3QgbGV4ZXIgPSB0aGlzLmxleGVyOwogICAgY29uc3Qgc3RyZWFtID0gbGV4ZXIuc3RyZWFtOwogICAgY29uc3QgZGljdE1hcCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBsZXQgZGljdExlbmd0aDsKICAgIHdoaWxlICghKDAsIF9wcmltaXRpdmVzLmlzQ21kKSh0aGlzLmJ1ZjEsICJJRCIpICYmIHRoaXMuYnVmMSAhPT0gX3ByaW1pdGl2ZXMuRU9GKSB7CiAgICAgIGlmICghKHRoaXMuYnVmMSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpKSB7CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJEaWN0aW9uYXJ5IGtleSBtdXN0IGJlIGEgbmFtZSBvYmplY3QiKTsKICAgICAgfQogICAgICBjb25zdCBrZXkgPSB0aGlzLmJ1ZjEubmFtZTsKICAgICAgdGhpcy5zaGlmdCgpOwogICAgICBpZiAodGhpcy5idWYxID09PSBfcHJpbWl0aXZlcy5FT0YpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBkaWN0TWFwW2tleV0gPSB0aGlzLmdldE9iaihjaXBoZXJUcmFuc2Zvcm0pOwogICAgfQogICAgaWYgKGxleGVyLmJlZ2luSW5saW5lSW1hZ2VQb3MgIT09IC0xKSB7CiAgICAgIGRpY3RMZW5ndGggPSBzdHJlYW0ucG9zIC0gbGV4ZXIuYmVnaW5JbmxpbmVJbWFnZVBvczsKICAgIH0KICAgIGNvbnN0IGZpbHRlciA9IHRoaXMueHJlZi5mZXRjaElmUmVmKGRpY3RNYXAuRiB8fCBkaWN0TWFwLkZpbHRlcik7CiAgICBsZXQgZmlsdGVyTmFtZTsKICAgIGlmIChmaWx0ZXIgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgIGZpbHRlck5hbWUgPSBmaWx0ZXIubmFtZTsKICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShmaWx0ZXIpKSB7CiAgICAgIGNvbnN0IGZpbHRlclplcm8gPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihmaWx0ZXJbMF0pOwogICAgICBpZiAoZmlsdGVyWmVybyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgICBmaWx0ZXJOYW1lID0gZmlsdGVyWmVyby5uYW1lOwogICAgICB9CiAgICB9CiAgICBjb25zdCBzdGFydFBvcyA9IHN0cmVhbS5wb3M7CiAgICBsZXQgbGVuZ3RoOwogICAgc3dpdGNoIChmaWx0ZXJOYW1lKSB7CiAgICAgIGNhc2UgIkRDVCI6CiAgICAgIGNhc2UgIkRDVERlY29kZSI6CiAgICAgICAgbGVuZ3RoID0gdGhpcy5maW5kRENURGVjb2RlSW5saW5lU3RyZWFtRW5kKHN0cmVhbSk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIkE4NSI6CiAgICAgIGNhc2UgIkFTQ0lJODVEZWNvZGUiOgogICAgICAgIGxlbmd0aCA9IHRoaXMuZmluZEFTQ0lJODVEZWNvZGVJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiQUh4IjoKICAgICAgY2FzZSAiQVNDSUlIZXhEZWNvZGUiOgogICAgICAgIGxlbmd0aCA9IHRoaXMuZmluZEFTQ0lJSGV4RGVjb2RlSW5saW5lU3RyZWFtRW5kKHN0cmVhbSk7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgbGVuZ3RoID0gdGhpcy5maW5kRGVmYXVsdElubGluZVN0cmVhbUVuZChzdHJlYW0pOwogICAgfQogICAgbGV0IGNhY2hlS2V5OwogICAgaWYgKGxlbmd0aCA8IE1BWF9MRU5HVEhfVE9fQ0FDSEUgJiYgZGljdExlbmd0aCA+IDApIHsKICAgICAgY29uc3QgaW5pdGlhbFN0cmVhbVBvcyA9IHN0cmVhbS5wb3M7CiAgICAgIHN0cmVhbS5wb3MgPSBsZXhlci5iZWdpbklubGluZUltYWdlUG9zOwogICAgICBjYWNoZUtleSA9IGdldElubGluZUltYWdlQ2FjaGVLZXkoc3RyZWFtLmdldEJ5dGVzKGRpY3RMZW5ndGggKyBsZW5ndGgpKTsKICAgICAgc3RyZWFtLnBvcyA9IGluaXRpYWxTdHJlYW1Qb3M7CiAgICAgIGNvbnN0IGNhY2hlRW50cnkgPSB0aGlzLmltYWdlQ2FjaGVbY2FjaGVLZXldOwogICAgICBpZiAoY2FjaGVFbnRyeSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgdGhpcy5idWYyID0gX3ByaW1pdGl2ZXMuQ21kLmdldCgiRUkiKTsKICAgICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgICAgY2FjaGVFbnRyeS5yZXNldCgpOwogICAgICAgIHJldHVybiBjYWNoZUVudHJ5OwogICAgICB9CiAgICB9CiAgICBjb25zdCBkaWN0ID0gbmV3IF9wcmltaXRpdmVzLkRpY3QodGhpcy54cmVmKTsKICAgIGZvciAoY29uc3Qga2V5IGluIGRpY3RNYXApIHsKICAgICAgZGljdC5zZXQoa2V5LCBkaWN0TWFwW2tleV0pOwogICAgfQogICAgbGV0IGltYWdlU3RyZWFtID0gc3RyZWFtLm1ha2VTdWJTdHJlYW0oc3RhcnRQb3MsIGxlbmd0aCwgZGljdCk7CiAgICBpZiAoY2lwaGVyVHJhbnNmb3JtKSB7CiAgICAgIGltYWdlU3RyZWFtID0gY2lwaGVyVHJhbnNmb3JtLmNyZWF0ZVN0cmVhbShpbWFnZVN0cmVhbSwgbGVuZ3RoKTsKICAgIH0KICAgIGltYWdlU3RyZWFtID0gdGhpcy5maWx0ZXIoaW1hZ2VTdHJlYW0sIGRpY3QsIGxlbmd0aCk7CiAgICBpbWFnZVN0cmVhbS5kaWN0ID0gZGljdDsKICAgIGlmIChjYWNoZUtleSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGltYWdlU3RyZWFtLmNhY2hlS2V5ID0gYGlubGluZV9pbWdfJHsrK3RoaXMuX2ltYWdlSWR9YDsKICAgICAgdGhpcy5pbWFnZUNhY2hlW2NhY2hlS2V5XSA9IGltYWdlU3RyZWFtOwogICAgfQogICAgdGhpcy5idWYyID0gX3ByaW1pdGl2ZXMuQ21kLmdldCgiRUkiKTsKICAgIHRoaXMuc2hpZnQoKTsKICAgIHJldHVybiBpbWFnZVN0cmVhbTsKICB9CiAgX2ZpbmRTdHJlYW1MZW5ndGgoc3RhcnRQb3MsIHNpZ25hdHVyZSkgewogICAgY29uc3QgewogICAgICBzdHJlYW0KICAgIH0gPSB0aGlzLmxleGVyOwogICAgc3RyZWFtLnBvcyA9IHN0YXJ0UG9zOwogICAgY29uc3QgU0NBTl9CTE9DS19MRU5HVEggPSAyMDQ4OwogICAgY29uc3Qgc2lnbmF0dXJlTGVuZ3RoID0gc2lnbmF0dXJlLmxlbmd0aDsKICAgIHdoaWxlIChzdHJlYW0ucG9zIDwgc3RyZWFtLmVuZCkgewogICAgICBjb25zdCBzY2FuQnl0ZXMgPSBzdHJlYW0ucGVla0J5dGVzKFNDQU5fQkxPQ0tfTEVOR1RIKTsKICAgICAgY29uc3Qgc2Nhbkxlbmd0aCA9IHNjYW5CeXRlcy5sZW5ndGggLSBzaWduYXR1cmVMZW5ndGg7CiAgICAgIGlmIChzY2FuTGVuZ3RoIDw9IDApIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBsZXQgcG9zID0gMDsKICAgICAgd2hpbGUgKHBvcyA8IHNjYW5MZW5ndGgpIHsKICAgICAgICBsZXQgaiA9IDA7CiAgICAgICAgd2hpbGUgKGogPCBzaWduYXR1cmVMZW5ndGggJiYgc2NhbkJ5dGVzW3BvcyArIGpdID09PSBzaWduYXR1cmVbal0pIHsKICAgICAgICAgIGorKzsKICAgICAgICB9CiAgICAgICAgaWYgKGogPj0gc2lnbmF0dXJlTGVuZ3RoKSB7CiAgICAgICAgICBzdHJlYW0ucG9zICs9IHBvczsKICAgICAgICAgIHJldHVybiBzdHJlYW0ucG9zIC0gc3RhcnRQb3M7CiAgICAgICAgfQogICAgICAgIHBvcysrOwogICAgICB9CiAgICAgIHN0cmVhbS5wb3MgKz0gc2Nhbkxlbmd0aDsKICAgIH0KICAgIHJldHVybiAtMTsKICB9CiAgbWFrZVN0cmVhbShkaWN0LCBjaXBoZXJUcmFuc2Zvcm0pIHsKICAgIGNvbnN0IGxleGVyID0gdGhpcy5sZXhlcjsKICAgIGxldCBzdHJlYW0gPSBsZXhlci5zdHJlYW07CiAgICBsZXhlci5za2lwVG9OZXh0TGluZSgpOwogICAgY29uc3Qgc3RhcnRQb3MgPSBzdHJlYW0ucG9zIC0gMTsKICAgIGxldCBsZW5ndGggPSBkaWN0LmdldCgiTGVuZ3RoIik7CiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIobGVuZ3RoKSkgewogICAgICAoMCwgX3V0aWwuaW5mbykoYEJhZCBsZW5ndGggIiR7bGVuZ3RoICYmIGxlbmd0aC50b1N0cmluZygpfSIgaW4gc3RyZWFtLmApOwogICAgICBsZW5ndGggPSAwOwogICAgfQogICAgc3RyZWFtLnBvcyA9IHN0YXJ0UG9zICsgbGVuZ3RoOwogICAgbGV4ZXIubmV4dENoYXIoKTsKICAgIGlmICh0aGlzLnRyeVNoaWZ0KCkgJiYgKDAsIF9wcmltaXRpdmVzLmlzQ21kKSh0aGlzLmJ1ZjIsICJlbmRzdHJlYW0iKSkgewogICAgICB0aGlzLnNoaWZ0KCk7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBFTkRTVFJFQU1fU0lHTkFUVVJFID0gbmV3IFVpbnQ4QXJyYXkoWzB4NjUsIDB4NmUsIDB4NjQsIDB4NzMsIDB4NzQsIDB4NzIsIDB4NjUsIDB4NjEsIDB4NmRdKTsKICAgICAgbGV0IGFjdHVhbExlbmd0aCA9IHRoaXMuX2ZpbmRTdHJlYW1MZW5ndGgoc3RhcnRQb3MsIEVORFNUUkVBTV9TSUdOQVRVUkUpOwogICAgICBpZiAoYWN0dWFsTGVuZ3RoIDwgMCkgewogICAgICAgIGNvbnN0IE1BWF9UUlVOQ0FUSU9OID0gMTsKICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8PSBNQVhfVFJVTkNBVElPTjsgaSsrKSB7CiAgICAgICAgICBjb25zdCBlbmQgPSBFTkRTVFJFQU1fU0lHTkFUVVJFLmxlbmd0aCAtIGk7CiAgICAgICAgICBjb25zdCBUUlVOQ0FURURfU0lHTkFUVVJFID0gRU5EU1RSRUFNX1NJR05BVFVSRS5zbGljZSgwLCBlbmQpOwogICAgICAgICAgY29uc3QgbWF5YmVMZW5ndGggPSB0aGlzLl9maW5kU3RyZWFtTGVuZ3RoKHN0YXJ0UG9zLCBUUlVOQ0FURURfU0lHTkFUVVJFKTsKICAgICAgICAgIGlmIChtYXliZUxlbmd0aCA+PSAwKSB7CiAgICAgICAgICAgIGNvbnN0IGxhc3RCeXRlID0gc3RyZWFtLnBlZWtCeXRlcyhlbmQgKyAxKVtlbmRdOwogICAgICAgICAgICBpZiAoISgwLCBfY29yZV91dGlscy5pc1doaXRlU3BhY2UpKGxhc3RCeXRlKSkgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgICgwLCBfdXRpbC5pbmZvKShgRm91bmQgIiR7KDAsIF91dGlsLmJ5dGVzVG9TdHJpbmcpKFRSVU5DQVRFRF9TSUdOQVRVUkUpfSIgd2hlbiBgICsgInNlYXJjaGluZyBmb3IgZW5kc3RyZWFtIGNvbW1hbmQuIik7CiAgICAgICAgICAgIGFjdHVhbExlbmd0aCA9IG1heWJlTGVuZ3RoOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKGFjdHVhbExlbmd0aCA8IDApIHsKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiTWlzc2luZyBlbmRzdHJlYW0gY29tbWFuZC4iKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgbGVuZ3RoID0gYWN0dWFsTGVuZ3RoOwogICAgICBsZXhlci5uZXh0Q2hhcigpOwogICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgIHRoaXMuc2hpZnQoKTsKICAgIH0KICAgIHRoaXMuc2hpZnQoKTsKICAgIHN0cmVhbSA9IHN0cmVhbS5tYWtlU3ViU3RyZWFtKHN0YXJ0UG9zLCBsZW5ndGgsIGRpY3QpOwogICAgaWYgKGNpcGhlclRyYW5zZm9ybSkgewogICAgICBzdHJlYW0gPSBjaXBoZXJUcmFuc2Zvcm0uY3JlYXRlU3RyZWFtKHN0cmVhbSwgbGVuZ3RoKTsKICAgIH0KICAgIHN0cmVhbSA9IHRoaXMuZmlsdGVyKHN0cmVhbSwgZGljdCwgbGVuZ3RoKTsKICAgIHN0cmVhbS5kaWN0ID0gZGljdDsKICAgIHJldHVybiBzdHJlYW07CiAgfQogIGZpbHRlcihzdHJlYW0sIGRpY3QsIGxlbmd0aCkgewogICAgbGV0IGZpbHRlciA9IGRpY3QuZ2V0KCJGIiwgIkZpbHRlciIpOwogICAgbGV0IHBhcmFtcyA9IGRpY3QuZ2V0KCJEUCIsICJEZWNvZGVQYXJtcyIpOwogICAgaWYgKGZpbHRlciBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkocGFyYW1zKSkgewogICAgICAgICgwLCBfdXRpbC53YXJuKSgiL0RlY29kZVBhcm1zIHNob3VsZCBub3QgYmUgYW4gQXJyYXksIHdoZW4gL0ZpbHRlciBpcyBhIE5hbWUuIik7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMubWFrZUZpbHRlcihzdHJlYW0sIGZpbHRlci5uYW1lLCBsZW5ndGgsIHBhcmFtcyk7CiAgICB9CiAgICBsZXQgbWF5YmVMZW5ndGggPSBsZW5ndGg7CiAgICBpZiAoQXJyYXkuaXNBcnJheShmaWx0ZXIpKSB7CiAgICAgIGNvbnN0IGZpbHRlckFycmF5ID0gZmlsdGVyOwogICAgICBjb25zdCBwYXJhbXNBcnJheSA9IHBhcmFtczsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZmlsdGVyQXJyYXkubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICAgIGZpbHRlciA9IHRoaXMueHJlZi5mZXRjaElmUmVmKGZpbHRlckFycmF5W2ldKTsKICAgICAgICBpZiAoIShmaWx0ZXIgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSkgewogICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBCYWQgZmlsdGVyIG5hbWUgIiR7ZmlsdGVyfSJgKTsKICAgICAgICB9CiAgICAgICAgcGFyYW1zID0gbnVsbDsKICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShwYXJhbXNBcnJheSkgJiYgaSBpbiBwYXJhbXNBcnJheSkgewogICAgICAgICAgcGFyYW1zID0gdGhpcy54cmVmLmZldGNoSWZSZWYocGFyYW1zQXJyYXlbaV0pOwogICAgICAgIH0KICAgICAgICBzdHJlYW0gPSB0aGlzLm1ha2VGaWx0ZXIoc3RyZWFtLCBmaWx0ZXIubmFtZSwgbWF5YmVMZW5ndGgsIHBhcmFtcyk7CiAgICAgICAgbWF5YmVMZW5ndGggPSBudWxsOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc3RyZWFtOwogIH0KICBtYWtlRmlsdGVyKHN0cmVhbSwgbmFtZSwgbWF5YmVMZW5ndGgsIHBhcmFtcykgewogICAgaWYgKG1heWJlTGVuZ3RoID09PSAwKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKShgRW1wdHkgIiR7bmFtZX0iIHN0cmVhbS5gKTsKICAgICAgcmV0dXJuIG5ldyBfc3RyZWFtLk51bGxTdHJlYW0oKTsKICAgIH0KICAgIHRyeSB7CiAgICAgIHN3aXRjaCAobmFtZSkgewogICAgICAgIGNhc2UgIkZsIjoKICAgICAgICBjYXNlICJGbGF0ZURlY29kZSI6CiAgICAgICAgICBpZiAocGFyYW1zKSB7CiAgICAgICAgICAgIHJldHVybiBuZXcgX3ByZWRpY3Rvcl9zdHJlYW0uUHJlZGljdG9yU3RyZWFtKG5ldyBfZmxhdGVfc3RyZWFtLkZsYXRlU3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgpLCBtYXliZUxlbmd0aCwgcGFyYW1zKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBuZXcgX2ZsYXRlX3N0cmVhbS5GbGF0ZVN0cmVhbShzdHJlYW0sIG1heWJlTGVuZ3RoKTsKICAgICAgICBjYXNlICJMWlciOgogICAgICAgIGNhc2UgIkxaV0RlY29kZSI6CiAgICAgICAgICBsZXQgZWFybHlDaGFuZ2UgPSAxOwogICAgICAgICAgaWYgKHBhcmFtcykgewogICAgICAgICAgICBpZiAocGFyYW1zLmhhcygiRWFybHlDaGFuZ2UiKSkgewogICAgICAgICAgICAgIGVhcmx5Q2hhbmdlID0gcGFyYW1zLmdldCgiRWFybHlDaGFuZ2UiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbmV3IF9wcmVkaWN0b3Jfc3RyZWFtLlByZWRpY3RvclN0cmVhbShuZXcgX2x6d19zdHJlYW0uTFpXU3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgsIGVhcmx5Q2hhbmdlKSwgbWF5YmVMZW5ndGgsIHBhcmFtcyk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gbmV3IF9sendfc3RyZWFtLkxaV1N0cmVhbShzdHJlYW0sIG1heWJlTGVuZ3RoLCBlYXJseUNoYW5nZSk7CiAgICAgICAgY2FzZSAiRENUIjoKICAgICAgICBjYXNlICJEQ1REZWNvZGUiOgogICAgICAgICAgcmV0dXJuIG5ldyBfanBlZ19zdHJlYW0uSnBlZ1N0cmVhbShzdHJlYW0sIG1heWJlTGVuZ3RoLCBwYXJhbXMpOwogICAgICAgIGNhc2UgIkpQWCI6CiAgICAgICAgY2FzZSAiSlBYRGVjb2RlIjoKICAgICAgICAgIHJldHVybiBuZXcgX2pweF9zdHJlYW0uSnB4U3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgsIHBhcmFtcyk7CiAgICAgICAgY2FzZSAiQTg1IjoKICAgICAgICBjYXNlICJBU0NJSTg1RGVjb2RlIjoKICAgICAgICAgIHJldHVybiBuZXcgX2FzY2lpXzg1X3N0cmVhbS5Bc2NpaTg1U3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgpOwogICAgICAgIGNhc2UgIkFIeCI6CiAgICAgICAgY2FzZSAiQVNDSUlIZXhEZWNvZGUiOgogICAgICAgICAgcmV0dXJuIG5ldyBfYXNjaWlfaGV4X3N0cmVhbS5Bc2NpaUhleFN0cmVhbShzdHJlYW0sIG1heWJlTGVuZ3RoKTsKICAgICAgICBjYXNlICJDQ0YiOgogICAgICAgIGNhc2UgIkNDSVRURmF4RGVjb2RlIjoKICAgICAgICAgIHJldHVybiBuZXcgX2NjaXR0X3N0cmVhbS5DQ0lUVEZheFN0cmVhbShzdHJlYW0sIG1heWJlTGVuZ3RoLCBwYXJhbXMpOwogICAgICAgIGNhc2UgIlJMIjoKICAgICAgICBjYXNlICJSdW5MZW5ndGhEZWNvZGUiOgogICAgICAgICAgcmV0dXJuIG5ldyBfcnVuX2xlbmd0aF9zdHJlYW0uUnVuTGVuZ3RoU3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgpOwogICAgICAgIGNhc2UgIkpCSUcyRGVjb2RlIjoKICAgICAgICAgIHJldHVybiBuZXcgX2piaWcyX3N0cmVhbS5KYmlnMlN0cmVhbShzdHJlYW0sIG1heWJlTGVuZ3RoLCBwYXJhbXMpOwogICAgICB9CiAgICAgICgwLCBfdXRpbC53YXJuKShgRmlsdGVyICIke25hbWV9IiBpcyBub3Qgc3VwcG9ydGVkLmApOwogICAgICByZXR1cm4gc3RyZWFtOwogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgX2NvcmVfdXRpbHMuTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICAoMCwgX3V0aWwud2FybikoYEludmFsaWQgc3RyZWFtOiAiJHtleH0iYCk7CiAgICAgIHJldHVybiBuZXcgX3N0cmVhbS5OdWxsU3RyZWFtKCk7CiAgICB9CiAgfQp9CmV4cG9ydHMuUGFyc2VyID0gUGFyc2VyOwpjb25zdCBzcGVjaWFsQ2hhcnMgPSBbMSwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMSwgMSwgMCwgMSwgMSwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMSwgMCwgMCwgMCwgMCwgMiwgMCwgMCwgMiwgMiwgMCwgMCwgMCwgMCwgMCwgMiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMiwgMCwgMiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMiwgMCwgMiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMiwgMCwgMiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMF07CmZ1bmN0aW9uIHRvSGV4RGlnaXQoY2gpIHsKICBpZiAoY2ggPj0gMHgzMCAmJiBjaCA8PSAweDM5KSB7CiAgICByZXR1cm4gY2ggJiAweDBmOwogIH0KICBpZiAoY2ggPj0gMHg0MSAmJiBjaCA8PSAweDQ2IHx8IGNoID49IDB4NjEgJiYgY2ggPD0gMHg2NikgewogICAgcmV0dXJuIChjaCAmIDB4MGYpICsgOTsKICB9CiAgcmV0dXJuIC0xOwp9CmNsYXNzIExleGVyIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0pIHsKICAgIGxldCBrbm93bkNvbW1hbmRzID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBudWxsOwogICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07CiAgICB0aGlzLm5leHRDaGFyKCk7CiAgICB0aGlzLnN0ckJ1ZiA9IFtdOwogICAgdGhpcy5rbm93bkNvbW1hbmRzID0ga25vd25Db21tYW5kczsKICAgIHRoaXMuX2hleFN0cmluZ051bVdhcm4gPSAwOwogICAgdGhpcy5iZWdpbklubGluZUltYWdlUG9zID0gLTE7CiAgfQogIG5leHRDaGFyKCkgewogICAgcmV0dXJuIHRoaXMuY3VycmVudENoYXIgPSB0aGlzLnN0cmVhbS5nZXRCeXRlKCk7CiAgfQogIHBlZWtDaGFyKCkgewogICAgcmV0dXJuIHRoaXMuc3RyZWFtLnBlZWtCeXRlKCk7CiAgfQogIGdldE51bWJlcigpIHsKICAgIGxldCBjaCA9IHRoaXMuY3VycmVudENoYXI7CiAgICBsZXQgZU5vdGF0aW9uID0gZmFsc2U7CiAgICBsZXQgZGl2aWRlQnkgPSAwOwogICAgbGV0IHNpZ24gPSAwOwogICAgaWYgKGNoID09PSAweDJkKSB7CiAgICAgIHNpZ24gPSAtMTsKICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICAgIGlmIChjaCA9PT0gMHgyZCkgewogICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKGNoID09PSAweDJiKSB7CiAgICAgIHNpZ24gPSAxOwogICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgIH0KICAgIGlmIChjaCA9PT0gMHgwYSB8fCBjaCA9PT0gMHgwZCkgewogICAgICBkbyB7CiAgICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICAgIH0gd2hpbGUgKGNoID09PSAweDBhIHx8IGNoID09PSAweDBkKTsKICAgIH0KICAgIGlmIChjaCA9PT0gMHgyZSkgewogICAgICBkaXZpZGVCeSA9IDEwOwogICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgIH0KICAgIGlmIChjaCA8IDB4MzAgfHwgY2ggPiAweDM5KSB7CiAgICAgIGNvbnN0IG1zZyA9IGBJbnZhbGlkIG51bWJlcjogJHtTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKX0gKGNoYXJDb2RlICR7Y2h9KWA7CiAgICAgIGlmICgoMCwgX2NvcmVfdXRpbHMuaXNXaGl0ZVNwYWNlKShjaCkgfHwgY2ggPT09IC0xKSB7CiAgICAgICAgKDAsIF91dGlsLmluZm8pKGBMZXhlci5nZXROdW1iZXIgLSAiJHttc2d9Ii5gKTsKICAgICAgICByZXR1cm4gMDsKICAgICAgfQogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IobXNnKTsKICAgIH0KICAgIHNpZ24gPSBzaWduIHx8IDE7CiAgICBsZXQgYmFzZVZhbHVlID0gY2ggLSAweDMwOwogICAgbGV0IHBvd2VyVmFsdWUgPSAwOwogICAgbGV0IHBvd2VyVmFsdWVTaWduID0gMTsKICAgIHdoaWxlICgoY2ggPSB0aGlzLm5leHRDaGFyKCkpID49IDApIHsKICAgICAgaWYgKGNoID49IDB4MzAgJiYgY2ggPD0gMHgzOSkgewogICAgICAgIGNvbnN0IGN1cnJlbnREaWdpdCA9IGNoIC0gMHgzMDsKICAgICAgICBpZiAoZU5vdGF0aW9uKSB7CiAgICAgICAgICBwb3dlclZhbHVlID0gcG93ZXJWYWx1ZSAqIDEwICsgY3VycmVudERpZ2l0OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBpZiAoZGl2aWRlQnkgIT09IDApIHsKICAgICAgICAgICAgZGl2aWRlQnkgKj0gMTA7CiAgICAgICAgICB9CiAgICAgICAgICBiYXNlVmFsdWUgPSBiYXNlVmFsdWUgKiAxMCArIGN1cnJlbnREaWdpdDsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MmUpIHsKICAgICAgICBpZiAoZGl2aWRlQnkgPT09IDApIHsKICAgICAgICAgIGRpdmlkZUJ5ID0gMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGNoID09PSAweDJkKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKCJCYWRseSBmb3JtYXR0ZWQgbnVtYmVyOiBtaW51cyBzaWduIGluIHRoZSBtaWRkbGUiKTsKICAgICAgfSBlbHNlIGlmIChjaCA9PT0gMHg0NSB8fCBjaCA9PT0gMHg2NSkgewogICAgICAgIGNoID0gdGhpcy5wZWVrQ2hhcigpOwogICAgICAgIGlmIChjaCA9PT0gMHgyYiB8fCBjaCA9PT0gMHgyZCkgewogICAgICAgICAgcG93ZXJWYWx1ZVNpZ24gPSBjaCA9PT0gMHgyZCA/IC0xIDogMTsKICAgICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICB9IGVsc2UgaWYgKGNoIDwgMHgzMCB8fCBjaCA+IDB4MzkpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBlTm90YXRpb24gPSB0cnVlOwogICAgICB9IGVsc2UgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBpZiAoZGl2aWRlQnkgIT09IDApIHsKICAgICAgYmFzZVZhbHVlIC89IGRpdmlkZUJ5OwogICAgfQogICAgaWYgKGVOb3RhdGlvbikgewogICAgICBiYXNlVmFsdWUgKj0gMTAgKiogKHBvd2VyVmFsdWVTaWduICogcG93ZXJWYWx1ZSk7CiAgICB9CiAgICByZXR1cm4gc2lnbiAqIGJhc2VWYWx1ZTsKICB9CiAgZ2V0U3RyaW5nKCkgewogICAgbGV0IG51bVBhcmVuID0gMTsKICAgIGxldCBkb25lID0gZmFsc2U7CiAgICBjb25zdCBzdHJCdWYgPSB0aGlzLnN0ckJ1ZjsKICAgIHN0ckJ1Zi5sZW5ndGggPSAwOwogICAgbGV0IGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgbGV0IGNoYXJCdWZmZXJlZCA9IGZhbHNlOwogICAgICBzd2l0Y2ggKGNoIHwgMCkgewogICAgICAgIGNhc2UgLTE6CiAgICAgICAgICAoMCwgX3V0aWwud2FybikoIlVudGVybWluYXRlZCBzdHJpbmciKTsKICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDI4OgogICAgICAgICAgKytudW1QYXJlbjsKICAgICAgICAgIHN0ckJ1Zi5wdXNoKCIoIik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4Mjk6CiAgICAgICAgICBpZiAoLS1udW1QYXJlbiA9PT0gMCkgewogICAgICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RyQnVmLnB1c2goIikiKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMHg1YzoKICAgICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgc3dpdGNoIChjaCkgewogICAgICAgICAgICBjYXNlIC0xOgogICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiVW50ZXJtaW5hdGVkIHN0cmluZyIpOwogICAgICAgICAgICAgIGRvbmUgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDB4NmU6CiAgICAgICAgICAgICAgc3RyQnVmLnB1c2goIlxuIik7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMHg3MjoKICAgICAgICAgICAgICBzdHJCdWYucHVzaCgiXHIiKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDc0OgogICAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKCJcdCIpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDB4NjI6CiAgICAgICAgICAgICAgc3RyQnVmLnB1c2goIlxiIik7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMHg2NjoKICAgICAgICAgICAgICBzdHJCdWYucHVzaCgiXGYiKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDVjOgogICAgICAgICAgICBjYXNlIDB4Mjg6CiAgICAgICAgICAgIGNhc2UgMHgyOToKICAgICAgICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMHgzMDoKICAgICAgICAgICAgY2FzZSAweDMxOgogICAgICAgICAgICBjYXNlIDB4MzI6CiAgICAgICAgICAgIGNhc2UgMHgzMzoKICAgICAgICAgICAgY2FzZSAweDM0OgogICAgICAgICAgICBjYXNlIDB4MzU6CiAgICAgICAgICAgIGNhc2UgMHgzNjoKICAgICAgICAgICAgY2FzZSAweDM3OgogICAgICAgICAgICAgIGxldCB4ID0gY2ggJiAweDBmOwogICAgICAgICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICAgIGNoYXJCdWZmZXJlZCA9IHRydWU7CiAgICAgICAgICAgICAgaWYgKGNoID49IDB4MzAgJiYgY2ggPD0gMHgzNykgewogICAgICAgICAgICAgICAgeCA9ICh4IDw8IDMpICsgKGNoICYgMHgwZik7CiAgICAgICAgICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICAgICAgICAgIGlmIChjaCA+PSAweDMwICYmIGNoIDw9IDB4MzcpIHsKICAgICAgICAgICAgICAgICAgY2hhckJ1ZmZlcmVkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgIHggPSAoeCA8PCAzKSArIChjaCAmIDB4MGYpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKHgpKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDBkOgogICAgICAgICAgICAgIGlmICh0aGlzLnBlZWtDaGFyKCkgPT09IDB4MGEpIHsKICAgICAgICAgICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMHgwYToKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjaCkpOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKGRvbmUpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAoIWNoYXJCdWZmZXJlZCkgewogICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc3RyQnVmLmpvaW4oIiIpOwogIH0KICBnZXROYW1lKCkgewogICAgbGV0IGNoLCBwcmV2aW91c0NoOwogICAgY29uc3Qgc3RyQnVmID0gdGhpcy5zdHJCdWY7CiAgICBzdHJCdWYubGVuZ3RoID0gMDsKICAgIHdoaWxlICgoY2ggPSB0aGlzLm5leHRDaGFyKCkpID49IDAgJiYgIXNwZWNpYWxDaGFyc1tjaF0pIHsKICAgICAgaWYgKGNoID09PSAweDIzKSB7CiAgICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgaWYgKHNwZWNpYWxDaGFyc1tjaF0pIHsKICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiTGV4ZXJfZ2V0TmFtZTogIiArICJOVU1CRVIgU0lHTiAoIykgc2hvdWxkIGJlIGZvbGxvd2VkIGJ5IGEgaGV4YWRlY2ltYWwgbnVtYmVyLiIpOwogICAgICAgICAgc3RyQnVmLnB1c2goIiMiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjb25zdCB4ID0gdG9IZXhEaWdpdChjaCk7CiAgICAgICAgaWYgKHggIT09IC0xKSB7CiAgICAgICAgICBwcmV2aW91c0NoID0gY2g7CiAgICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICAgIGNvbnN0IHgyID0gdG9IZXhEaWdpdChjaCk7CiAgICAgICAgICBpZiAoeDIgPT09IC0xKSB7CiAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgTGV4ZXJfZ2V0TmFtZTogSWxsZWdhbCBkaWdpdCAoJHtTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKX0pIGAgKyAiaW4gaGV4YWRlY2ltYWwgbnVtYmVyLiIpOwogICAgICAgICAgICBzdHJCdWYucHVzaCgiIyIsIFN0cmluZy5mcm9tQ2hhckNvZGUocHJldmlvdXNDaCkpOwogICAgICAgICAgICBpZiAoc3BlY2lhbENoYXJzW2NoXSkgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKHggPDwgNCB8IHgyKSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN0ckJ1Zi5wdXNoKCIjIiwgU3RyaW5nLmZyb21DaGFyQ29kZShjaCkpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKSk7CiAgICAgIH0KICAgIH0KICAgIGlmIChzdHJCdWYubGVuZ3RoID4gMTI3KSB7CiAgICAgICgwLCBfdXRpbC53YXJuKShgTmFtZSB0b2tlbiBpcyBsb25nZXIgdGhhbiBhbGxvd2VkIGJ5IHRoZSBzcGVjOiAke3N0ckJ1Zi5sZW5ndGh9YCk7CiAgICB9CiAgICByZXR1cm4gX3ByaW1pdGl2ZXMuTmFtZS5nZXQoc3RyQnVmLmpvaW4oIiIpKTsKICB9CiAgX2hleFN0cmluZ1dhcm4oY2gpIHsKICAgIGNvbnN0IE1BWF9IRVhfU1RSSU5HX05VTV9XQVJOID0gNTsKICAgIGlmICh0aGlzLl9oZXhTdHJpbmdOdW1XYXJuKysgPT09IE1BWF9IRVhfU1RSSU5HX05VTV9XQVJOKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKSgiZ2V0SGV4U3RyaW5nIC0gaWdub3JpbmcgYWRkaXRpb25hbCBpbnZhbGlkIGNoYXJhY3RlcnMuIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0aGlzLl9oZXhTdHJpbmdOdW1XYXJuID4gTUFYX0hFWF9TVFJJTkdfTlVNX1dBUk4pIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgKDAsIF91dGlsLndhcm4pKGBnZXRIZXhTdHJpbmcgLSBpZ25vcmluZyBpbnZhbGlkIGNoYXJhY3RlcjogJHtjaH1gKTsKICB9CiAgZ2V0SGV4U3RyaW5nKCkgewogICAgY29uc3Qgc3RyQnVmID0gdGhpcy5zdHJCdWY7CiAgICBzdHJCdWYubGVuZ3RoID0gMDsKICAgIGxldCBjaCA9IHRoaXMuY3VycmVudENoYXI7CiAgICBsZXQgaXNGaXJzdEhleCA9IHRydWU7CiAgICBsZXQgZmlyc3REaWdpdCwgc2Vjb25kRGlnaXQ7CiAgICB0aGlzLl9oZXhTdHJpbmdOdW1XYXJuID0gMDsKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIGlmIChjaCA8IDApIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoIlVudGVybWluYXRlZCBoZXggc3RyaW5nIik7CiAgICAgICAgYnJlYWs7CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4M2UpIHsKICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0gZWxzZSBpZiAoc3BlY2lhbENoYXJzW2NoXSA9PT0gMSkgewogICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9IGVsc2UgewogICAgICAgIGlmIChpc0ZpcnN0SGV4KSB7CiAgICAgICAgICBmaXJzdERpZ2l0ID0gdG9IZXhEaWdpdChjaCk7CiAgICAgICAgICBpZiAoZmlyc3REaWdpdCA9PT0gLTEpIHsKICAgICAgICAgICAgdGhpcy5faGV4U3RyaW5nV2FybihjaCk7CiAgICAgICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgc2Vjb25kRGlnaXQgPSB0b0hleERpZ2l0KGNoKTsKICAgICAgICAgIGlmIChzZWNvbmREaWdpdCA9PT0gLTEpIHsKICAgICAgICAgICAgdGhpcy5faGV4U3RyaW5nV2FybihjaCk7CiAgICAgICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIHN0ckJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoZmlyc3REaWdpdCA8PCA0IHwgc2Vjb25kRGlnaXQpKTsKICAgICAgICB9CiAgICAgICAgaXNGaXJzdEhleCA9ICFpc0ZpcnN0SGV4OwogICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc3RyQnVmLmpvaW4oIiIpOwogIH0KICBnZXRPYmooKSB7CiAgICBsZXQgY29tbWVudCA9IGZhbHNlOwogICAgbGV0IGNoID0gdGhpcy5jdXJyZW50Q2hhcjsKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIGlmIChjaCA8IDApIHsKICAgICAgICByZXR1cm4gX3ByaW1pdGl2ZXMuRU9GOwogICAgICB9CiAgICAgIGlmIChjb21tZW50KSB7CiAgICAgICAgaWYgKGNoID09PSAweDBhIHx8IGNoID09PSAweDBkKSB7CiAgICAgICAgICBjb21tZW50ID0gZmFsc2U7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGNoID09PSAweDI1KSB7CiAgICAgICAgY29tbWVudCA9IHRydWU7CiAgICAgIH0gZWxzZSBpZiAoc3BlY2lhbENoYXJzW2NoXSAhPT0gMSkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgfQogICAgc3dpdGNoIChjaCB8IDApIHsKICAgICAgY2FzZSAweDMwOgogICAgICBjYXNlIDB4MzE6CiAgICAgIGNhc2UgMHgzMjoKICAgICAgY2FzZSAweDMzOgogICAgICBjYXNlIDB4MzQ6CiAgICAgIGNhc2UgMHgzNToKICAgICAgY2FzZSAweDM2OgogICAgICBjYXNlIDB4Mzc6CiAgICAgIGNhc2UgMHgzODoKICAgICAgY2FzZSAweDM5OgogICAgICBjYXNlIDB4MmI6CiAgICAgIGNhc2UgMHgyZDoKICAgICAgY2FzZSAweDJlOgogICAgICAgIHJldHVybiB0aGlzLmdldE51bWJlcigpOwogICAgICBjYXNlIDB4Mjg6CiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0U3RyaW5nKCk7CiAgICAgIGNhc2UgMHgyZjoKICAgICAgICByZXR1cm4gdGhpcy5nZXROYW1lKCk7CiAgICAgIGNhc2UgMHg1YjoKICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgcmV0dXJuIF9wcmltaXRpdmVzLkNtZC5nZXQoIlsiKTsKICAgICAgY2FzZSAweDVkOgogICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICByZXR1cm4gX3ByaW1pdGl2ZXMuQ21kLmdldCgiXSIpOwogICAgICBjYXNlIDB4M2M6CiAgICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgaWYgKGNoID09PSAweDNjKSB7CiAgICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgICByZXR1cm4gX3ByaW1pdGl2ZXMuQ21kLmdldCgiPDwiKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SGV4U3RyaW5nKCk7CiAgICAgIGNhc2UgMHgzZToKICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICBpZiAoY2ggPT09IDB4M2UpIHsKICAgICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICAgIHJldHVybiBfcHJpbWl0aXZlcy5DbWQuZ2V0KCI+PiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gX3ByaW1pdGl2ZXMuQ21kLmdldCgiPiIpOwogICAgICBjYXNlIDB4N2I6CiAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgIHJldHVybiBfcHJpbWl0aXZlcy5DbWQuZ2V0KCJ7Iik7CiAgICAgIGNhc2UgMHg3ZDoKICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgcmV0dXJuIF9wcmltaXRpdmVzLkNtZC5nZXQoIn0iKTsKICAgICAgY2FzZSAweDI5OgogICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYElsbGVnYWwgY2hhcmFjdGVyOiAke2NofWApOwogICAgfQogICAgbGV0IHN0ciA9IFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpOwogICAgaWYgKGNoIDwgMHgyMCB8fCBjaCA+IDB4N2YpIHsKICAgICAgY29uc3QgbmV4dENoID0gdGhpcy5wZWVrQ2hhcigpOwogICAgICBpZiAobmV4dENoID49IDB4MjAgJiYgbmV4dENoIDw9IDB4N2YpIHsKICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgcmV0dXJuIF9wcmltaXRpdmVzLkNtZC5nZXQoc3RyKTsKICAgICAgfQogICAgfQogICAgY29uc3Qga25vd25Db21tYW5kcyA9IHRoaXMua25vd25Db21tYW5kczsKICAgIGxldCBrbm93bkNvbW1hbmRGb3VuZCA9IGtub3duQ29tbWFuZHMgJiYga25vd25Db21tYW5kc1tzdHJdICE9PSB1bmRlZmluZWQ7CiAgICB3aGlsZSAoKGNoID0gdGhpcy5uZXh0Q2hhcigpKSA+PSAwICYmICFzcGVjaWFsQ2hhcnNbY2hdKSB7CiAgICAgIGNvbnN0IHBvc3NpYmxlQ29tbWFuZCA9IHN0ciArIFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpOwogICAgICBpZiAoa25vd25Db21tYW5kRm91bmQgJiYga25vd25Db21tYW5kc1twb3NzaWJsZUNvbW1hbmRdID09PSB1bmRlZmluZWQpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAoc3RyLmxlbmd0aCA9PT0gMTI4KSB7CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBDb21tYW5kIHRva2VuIHRvbyBsb25nOiAke3N0ci5sZW5ndGh9YCk7CiAgICAgIH0KICAgICAgc3RyID0gcG9zc2libGVDb21tYW5kOwogICAgICBrbm93bkNvbW1hbmRGb3VuZCA9IGtub3duQ29tbWFuZHMgJiYga25vd25Db21tYW5kc1tzdHJdICE9PSB1bmRlZmluZWQ7CiAgICB9CiAgICBpZiAoc3RyID09PSAidHJ1ZSIpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBpZiAoc3RyID09PSAiZmFsc2UiKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmIChzdHIgPT09ICJudWxsIikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGlmIChzdHIgPT09ICJCSSIpIHsKICAgICAgdGhpcy5iZWdpbklubGluZUltYWdlUG9zID0gdGhpcy5zdHJlYW0ucG9zOwogICAgfQogICAgcmV0dXJuIF9wcmltaXRpdmVzLkNtZC5nZXQoc3RyKTsKICB9CiAgcGVla09iaigpIHsKICAgIGNvbnN0IHN0cmVhbVBvcyA9IHRoaXMuc3RyZWFtLnBvcywKICAgICAgY3VycmVudENoYXIgPSB0aGlzLmN1cnJlbnRDaGFyLAogICAgICBiZWdpbklubGluZUltYWdlUG9zID0gdGhpcy5iZWdpbklubGluZUltYWdlUG9zOwogICAgbGV0IG5leHRPYmo7CiAgICB0cnkgewogICAgICBuZXh0T2JqID0gdGhpcy5nZXRPYmooKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgKDAsIF91dGlsLndhcm4pKGBwZWVrT2JqOiAke2V4fWApOwogICAgfQogICAgdGhpcy5zdHJlYW0ucG9zID0gc3RyZWFtUG9zOwogICAgdGhpcy5jdXJyZW50Q2hhciA9IGN1cnJlbnRDaGFyOwogICAgdGhpcy5iZWdpbklubGluZUltYWdlUG9zID0gYmVnaW5JbmxpbmVJbWFnZVBvczsKICAgIHJldHVybiBuZXh0T2JqOwogIH0KICBza2lwVG9OZXh0TGluZSgpIHsKICAgIGxldCBjaCA9IHRoaXMuY3VycmVudENoYXI7CiAgICB3aGlsZSAoY2ggPj0gMCkgewogICAgICBpZiAoY2ggPT09IDB4MGQpIHsKICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICBpZiAoY2ggPT09IDB4MGEpIHsKICAgICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MGEpIHsKICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICB9CiAgfQp9CmV4cG9ydHMuTGV4ZXIgPSBMZXhlcjsKY2xhc3MgTGluZWFyaXphdGlvbiB7CiAgc3RhdGljIGNyZWF0ZShzdHJlYW0pIHsKICAgIGZ1bmN0aW9uIGdldEludChsaW5EaWN0LCBuYW1lKSB7CiAgICAgIGxldCBhbGxvd1plcm9WYWx1ZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogZmFsc2U7CiAgICAgIGNvbnN0IG9iaiA9IGxpbkRpY3QuZ2V0KG5hbWUpOwogICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihvYmopICYmIChhbGxvd1plcm9WYWx1ZSA/IG9iaiA+PSAwIDogb2JqID4gMCkpIHsKICAgICAgICByZXR1cm4gb2JqOwogICAgICB9CiAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlICIke25hbWV9IiBwYXJhbWV0ZXIgaW4gdGhlIGxpbmVhcml6YXRpb24gYCArICJkaWN0aW9uYXJ5IGlzIGludmFsaWQuIik7CiAgICB9CiAgICBmdW5jdGlvbiBnZXRIaW50cyhsaW5EaWN0KSB7CiAgICAgIGNvbnN0IGhpbnRzID0gbGluRGljdC5nZXQoIkgiKTsKICAgICAgbGV0IGhpbnRzTGVuZ3RoOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShoaW50cykgJiYgKChoaW50c0xlbmd0aCA9IGhpbnRzLmxlbmd0aCkgPT09IDIgfHwgaGludHNMZW5ndGggPT09IDQpKSB7CiAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGhpbnRzTGVuZ3RoOyBpbmRleCsrKSB7CiAgICAgICAgICBjb25zdCBoaW50ID0gaGludHNbaW5kZXhdOwogICAgICAgICAgaWYgKCEoTnVtYmVyLmlzSW50ZWdlcihoaW50KSAmJiBoaW50ID4gMCkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBIaW50ICgke2luZGV4fSkgaW4gdGhlIGxpbmVhcml6YXRpb24gZGljdGlvbmFyeSBpcyBpbnZhbGlkLmApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gaGludHM7CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IEVycm9yKCJIaW50IGFycmF5IGluIHRoZSBsaW5lYXJpemF0aW9uIGRpY3Rpb25hcnkgaXMgaW52YWxpZC4iKTsKICAgIH0KICAgIGNvbnN0IHBhcnNlciA9IG5ldyBQYXJzZXIoewogICAgICBsZXhlcjogbmV3IExleGVyKHN0cmVhbSksCiAgICAgIHhyZWY6IG51bGwKICAgIH0pOwogICAgY29uc3Qgb2JqMSA9IHBhcnNlci5nZXRPYmooKTsKICAgIGNvbnN0IG9iajIgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICBjb25zdCBvYmozID0gcGFyc2VyLmdldE9iaigpOwogICAgY29uc3QgbGluRGljdCA9IHBhcnNlci5nZXRPYmooKTsKICAgIGxldCBvYmosIGxlbmd0aDsKICAgIGlmICghKE51bWJlci5pc0ludGVnZXIob2JqMSkgJiYgTnVtYmVyLmlzSW50ZWdlcihvYmoyKSAmJiAoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKG9iajMsICJvYmoiKSAmJiBsaW5EaWN0IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCAmJiB0eXBlb2YgKG9iaiA9IGxpbkRpY3QuZ2V0KCJMaW5lYXJpemVkIikpID09PSAibnVtYmVyIiAmJiBvYmogPiAwKSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0gZWxzZSBpZiAoKGxlbmd0aCA9IGdldEludChsaW5EaWN0LCAiTCIpKSAhPT0gc3RyZWFtLmxlbmd0aCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSAiTCIgcGFyYW1ldGVyIGluIHRoZSBsaW5lYXJpemF0aW9uIGRpY3Rpb25hcnkgJyArICJkb2VzIG5vdCBlcXVhbCB0aGUgc3RyZWFtIGxlbmd0aC4iKTsKICAgIH0KICAgIHJldHVybiB7CiAgICAgIGxlbmd0aCwKICAgICAgaGludHM6IGdldEhpbnRzKGxpbkRpY3QpLAogICAgICBvYmplY3ROdW1iZXJGaXJzdDogZ2V0SW50KGxpbkRpY3QsICJPIiksCiAgICAgIGVuZEZpcnN0OiBnZXRJbnQobGluRGljdCwgIkUiKSwKICAgICAgbnVtUGFnZXM6IGdldEludChsaW5EaWN0LCAiTiIpLAogICAgICBtYWluWFJlZkVudHJpZXNPZmZzZXQ6IGdldEludChsaW5EaWN0LCAiVCIpLAogICAgICBwYWdlRmlyc3Q6IGxpbkRpY3QuaGFzKCJQIikgPyBnZXRJbnQobGluRGljdCwgIlAiLCB0cnVlKSA6IDAKICAgIH07CiAgfQp9CmV4cG9ydHMuTGluZWFyaXphdGlvbiA9IExpbmVhcml6YXRpb247CgovKioqLyB9KSwKLyogMTUyICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5Bc2NpaTg1U3RyZWFtID0gdm9pZCAwOwp2YXIgX2RlY29kZV9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1Myk7CnZhciBfY29yZV91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTM5KTsKY2xhc3MgQXNjaWk4NVN0cmVhbSBleHRlbmRzIF9kZWNvZGVfc3RyZWFtLkRlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyLCBtYXliZUxlbmd0aCkgewogICAgaWYgKG1heWJlTGVuZ3RoKSB7CiAgICAgIG1heWJlTGVuZ3RoICo9IDAuODsKICAgIH0KICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyID0gc3RyOwogICAgdGhpcy5kaWN0ID0gc3RyLmRpY3Q7CiAgICB0aGlzLmlucHV0ID0gbmV3IFVpbnQ4QXJyYXkoNSk7CiAgfQogIHJlYWRCbG9jaygpIHsKICAgIGNvbnN0IFRJTERBX0NIQVIgPSAweDdlOwogICAgY29uc3QgWl9MT1dFUl9DSEFSID0gMHg3YTsKICAgIGNvbnN0IEVPRiA9IC0xOwogICAgY29uc3Qgc3RyID0gdGhpcy5zdHI7CiAgICBsZXQgYyA9IHN0ci5nZXRCeXRlKCk7CiAgICB3aGlsZSAoKDAsIF9jb3JlX3V0aWxzLmlzV2hpdGVTcGFjZSkoYykpIHsKICAgICAgYyA9IHN0ci5nZXRCeXRlKCk7CiAgICB9CiAgICBpZiAoYyA9PT0gRU9GIHx8IGMgPT09IFRJTERBX0NIQVIpIHsKICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlckxlbmd0aDsKICAgIGxldCBidWZmZXIsIGk7CiAgICBpZiAoYyA9PT0gWl9MT1dFUl9DSEFSKSB7CiAgICAgIGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKGJ1ZmZlckxlbmd0aCArIDQpOwogICAgICBmb3IgKGkgPSAwOyBpIDwgNDsgKytpKSB7CiAgICAgICAgYnVmZmVyW2J1ZmZlckxlbmd0aCArIGldID0gMDsKICAgICAgfQogICAgICB0aGlzLmJ1ZmZlckxlbmd0aCArPSA0OwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgaW5wdXQgPSB0aGlzLmlucHV0OwogICAgICBpbnB1dFswXSA9IGM7CiAgICAgIGZvciAoaSA9IDE7IGkgPCA1OyArK2kpIHsKICAgICAgICBjID0gc3RyLmdldEJ5dGUoKTsKICAgICAgICB3aGlsZSAoKDAsIF9jb3JlX3V0aWxzLmlzV2hpdGVTcGFjZSkoYykpIHsKICAgICAgICAgIGMgPSBzdHIuZ2V0Qnl0ZSgpOwogICAgICAgIH0KICAgICAgICBpbnB1dFtpXSA9IGM7CiAgICAgICAgaWYgKGMgPT09IEVPRiB8fCBjID09PSBUSUxEQV9DSEFSKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgYnVmZmVyID0gdGhpcy5lbnN1cmVCdWZmZXIoYnVmZmVyTGVuZ3RoICsgaSAtIDEpOwogICAgICB0aGlzLmJ1ZmZlckxlbmd0aCArPSBpIC0gMTsKICAgICAgaWYgKGkgPCA1KSB7CiAgICAgICAgZm9yICg7IGkgPCA1OyArK2kpIHsKICAgICAgICAgIGlucHV0W2ldID0gMHgyMSArIDg0OwogICAgICAgIH0KICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgIH0KICAgICAgbGV0IHQgPSAwOwogICAgICBmb3IgKGkgPSAwOyBpIDwgNTsgKytpKSB7CiAgICAgICAgdCA9IHQgKiA4NSArIChpbnB1dFtpXSAtIDB4MjEpOwogICAgICB9CiAgICAgIGZvciAoaSA9IDM7IGkgPj0gMDsgLS1pKSB7CiAgICAgICAgYnVmZmVyW2J1ZmZlckxlbmd0aCArIGldID0gdCAmIDB4ZmY7CiAgICAgICAgdCA+Pj0gODsKICAgICAgfQogICAgfQogIH0KfQpleHBvcnRzLkFzY2lpODVTdHJlYW0gPSBBc2NpaTg1U3RyZWFtOwoKLyoqKi8gfSksCi8qIDE1MyAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuU3RyZWFtc1NlcXVlbmNlU3RyZWFtID0gZXhwb3J0cy5EZWNvZGVTdHJlYW0gPSB2b2lkIDA7CnZhciBfYmFzZV9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MSk7CnZhciBfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDQpOwpjb25zdCBlbXB0eUJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KDApOwpjbGFzcyBEZWNvZGVTdHJlYW0gZXh0ZW5kcyBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSB7CiAgY29uc3RydWN0b3IobWF5YmVNaW5CdWZmZXJMZW5ndGgpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLl9yYXdNaW5CdWZmZXJMZW5ndGggPSBtYXliZU1pbkJ1ZmZlckxlbmd0aCB8fCAwOwogICAgdGhpcy5wb3MgPSAwOwogICAgdGhpcy5idWZmZXJMZW5ndGggPSAwOwogICAgdGhpcy5lb2YgPSBmYWxzZTsKICAgIHRoaXMuYnVmZmVyID0gZW1wdHlCdWZmZXI7CiAgICB0aGlzLm1pbkJ1ZmZlckxlbmd0aCA9IDUxMjsKICAgIGlmIChtYXliZU1pbkJ1ZmZlckxlbmd0aCkgewogICAgICB3aGlsZSAodGhpcy5taW5CdWZmZXJMZW5ndGggPCBtYXliZU1pbkJ1ZmZlckxlbmd0aCkgewogICAgICAgIHRoaXMubWluQnVmZmVyTGVuZ3RoICo9IDI7CiAgICAgIH0KICAgIH0KICB9CiAgZ2V0IGlzRW1wdHkoKSB7CiAgICB3aGlsZSAoIXRoaXMuZW9mICYmIHRoaXMuYnVmZmVyTGVuZ3RoID09PSAwKSB7CiAgICAgIHRoaXMucmVhZEJsb2NrKCk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5idWZmZXJMZW5ndGggPT09IDA7CiAgfQogIGVuc3VyZUJ1ZmZlcihyZXF1ZXN0ZWQpIHsKICAgIGNvbnN0IGJ1ZmZlciA9IHRoaXMuYnVmZmVyOwogICAgaWYgKHJlcXVlc3RlZCA8PSBidWZmZXIuYnl0ZUxlbmd0aCkgewogICAgICByZXR1cm4gYnVmZmVyOwogICAgfQogICAgbGV0IHNpemUgPSB0aGlzLm1pbkJ1ZmZlckxlbmd0aDsKICAgIHdoaWxlIChzaXplIDwgcmVxdWVzdGVkKSB7CiAgICAgIHNpemUgKj0gMjsKICAgIH0KICAgIGNvbnN0IGJ1ZmZlcjIgPSBuZXcgVWludDhBcnJheShzaXplKTsKICAgIGJ1ZmZlcjIuc2V0KGJ1ZmZlcik7CiAgICByZXR1cm4gdGhpcy5idWZmZXIgPSBidWZmZXIyOwogIH0KICBnZXRCeXRlKCkgewogICAgY29uc3QgcG9zID0gdGhpcy5wb3M7CiAgICB3aGlsZSAodGhpcy5idWZmZXJMZW5ndGggPD0gcG9zKSB7CiAgICAgIGlmICh0aGlzLmVvZikgewogICAgICAgIHJldHVybiAtMTsKICAgICAgfQogICAgICB0aGlzLnJlYWRCbG9jaygpOwogICAgfQogICAgcmV0dXJuIHRoaXMuYnVmZmVyW3RoaXMucG9zKytdOwogIH0KICBnZXRCeXRlcyhsZW5ndGgpIHsKICAgIGNvbnN0IHBvcyA9IHRoaXMucG9zOwogICAgbGV0IGVuZDsKICAgIGlmIChsZW5ndGgpIHsKICAgICAgdGhpcy5lbnN1cmVCdWZmZXIocG9zICsgbGVuZ3RoKTsKICAgICAgZW5kID0gcG9zICsgbGVuZ3RoOwogICAgICB3aGlsZSAoIXRoaXMuZW9mICYmIHRoaXMuYnVmZmVyTGVuZ3RoIDwgZW5kKSB7CiAgICAgICAgdGhpcy5yZWFkQmxvY2soKTsKICAgICAgfQogICAgICBjb25zdCBidWZFbmQgPSB0aGlzLmJ1ZmZlckxlbmd0aDsKICAgICAgaWYgKGVuZCA+IGJ1ZkVuZCkgewogICAgICAgIGVuZCA9IGJ1ZkVuZDsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgd2hpbGUgKCF0aGlzLmVvZikgewogICAgICAgIHRoaXMucmVhZEJsb2NrKCk7CiAgICAgIH0KICAgICAgZW5kID0gdGhpcy5idWZmZXJMZW5ndGg7CiAgICB9CiAgICB0aGlzLnBvcyA9IGVuZDsKICAgIHJldHVybiB0aGlzLmJ1ZmZlci5zdWJhcnJheShwb3MsIGVuZCk7CiAgfQogIHJlc2V0KCkgewogICAgdGhpcy5wb3MgPSAwOwogIH0KICBtYWtlU3ViU3RyZWFtKHN0YXJ0LCBsZW5ndGgpIHsKICAgIGxldCBkaWN0ID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBudWxsOwogICAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHdoaWxlICghdGhpcy5lb2YpIHsKICAgICAgICB0aGlzLnJlYWRCbG9jaygpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBlbmQgPSBzdGFydCArIGxlbmd0aDsKICAgICAgd2hpbGUgKHRoaXMuYnVmZmVyTGVuZ3RoIDw9IGVuZCAmJiAhdGhpcy5lb2YpIHsKICAgICAgICB0aGlzLnJlYWRCbG9jaygpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbmV3IF9zdHJlYW0uU3RyZWFtKHRoaXMuYnVmZmVyLCBzdGFydCwgbGVuZ3RoLCBkaWN0KTsKICB9CiAgZ2V0QmFzZVN0cmVhbXMoKSB7CiAgICByZXR1cm4gdGhpcy5zdHIgPyB0aGlzLnN0ci5nZXRCYXNlU3RyZWFtcygpIDogbnVsbDsKICB9Cn0KZXhwb3J0cy5EZWNvZGVTdHJlYW0gPSBEZWNvZGVTdHJlYW07CmNsYXNzIFN0cmVhbXNTZXF1ZW5jZVN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyZWFtcykgewogICAgbGV0IG9uRXJyb3IgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IG51bGw7CiAgICBsZXQgbWF5YmVMZW5ndGggPSAwOwogICAgZm9yIChjb25zdCBzdHJlYW0gb2Ygc3RyZWFtcykgewogICAgICBtYXliZUxlbmd0aCArPSBzdHJlYW0gaW5zdGFuY2VvZiBEZWNvZGVTdHJlYW0gPyBzdHJlYW0uX3Jhd01pbkJ1ZmZlckxlbmd0aCA6IHN0cmVhbS5sZW5ndGg7CiAgICB9CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICB0aGlzLnN0cmVhbXMgPSBzdHJlYW1zOwogICAgdGhpcy5fb25FcnJvciA9IG9uRXJyb3I7CiAgfQogIHJlYWRCbG9jaygpIHsKICAgIGNvbnN0IHN0cmVhbXMgPSB0aGlzLnN0cmVhbXM7CiAgICBpZiAoc3RyZWFtcy5sZW5ndGggPT09IDApIHsKICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBzdHJlYW0gPSBzdHJlYW1zLnNoaWZ0KCk7CiAgICBsZXQgY2h1bms7CiAgICB0cnkgewogICAgICBjaHVuayA9IHN0cmVhbS5nZXRCeXRlcygpOwogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIGlmICh0aGlzLl9vbkVycm9yKSB7CiAgICAgICAgdGhpcy5fb25FcnJvcihyZWFzb24sIHN0cmVhbS5kaWN0ICYmIHN0cmVhbS5kaWN0Lm9iaklkKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhyb3cgcmVhc29uOwogICAgfQogICAgY29uc3QgYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJMZW5ndGg7CiAgICBjb25zdCBuZXdMZW5ndGggPSBidWZmZXJMZW5ndGggKyBjaHVuay5sZW5ndGg7CiAgICBjb25zdCBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihuZXdMZW5ndGgpOwogICAgYnVmZmVyLnNldChjaHVuaywgYnVmZmVyTGVuZ3RoKTsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gbmV3TGVuZ3RoOwogIH0KICBnZXRCYXNlU3RyZWFtcygpIHsKICAgIGNvbnN0IGJhc2VTdHJlYW1zQnVmID0gW107CiAgICBmb3IgKGNvbnN0IHN0cmVhbSBvZiB0aGlzLnN0cmVhbXMpIHsKICAgICAgY29uc3QgYmFzZVN0cmVhbXMgPSBzdHJlYW0uZ2V0QmFzZVN0cmVhbXMoKTsKICAgICAgaWYgKGJhc2VTdHJlYW1zKSB7CiAgICAgICAgYmFzZVN0cmVhbXNCdWYucHVzaCguLi5iYXNlU3RyZWFtcyk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBiYXNlU3RyZWFtc0J1Zi5sZW5ndGggPiAwID8gYmFzZVN0cmVhbXNCdWYgOiBudWxsOwogIH0KfQpleHBvcnRzLlN0cmVhbXNTZXF1ZW5jZVN0cmVhbSA9IFN0cmVhbXNTZXF1ZW5jZVN0cmVhbTsKCi8qKiovIH0pLAovKiAxNTQgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLkFzY2lpSGV4U3RyZWFtID0gdm9pZCAwOwp2YXIgX2RlY29kZV9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1Myk7CmNsYXNzIEFzY2lpSGV4U3RyZWFtIGV4dGVuZHMgX2RlY29kZV9zdHJlYW0uRGVjb2RlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHIsIG1heWJlTGVuZ3RoKSB7CiAgICBpZiAobWF5YmVMZW5ndGgpIHsKICAgICAgbWF5YmVMZW5ndGggKj0gMC41OwogICAgfQogICAgc3VwZXIobWF5YmVMZW5ndGgpOwogICAgdGhpcy5zdHIgPSBzdHI7CiAgICB0aGlzLmRpY3QgPSBzdHIuZGljdDsKICAgIHRoaXMuZmlyc3REaWdpdCA9IC0xOwogIH0KICByZWFkQmxvY2soKSB7CiAgICBjb25zdCBVUFNUUkVBTV9CTE9DS19TSVpFID0gODAwMDsKICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5zdHIuZ2V0Qnl0ZXMoVVBTVFJFQU1fQkxPQ0tfU0laRSk7CiAgICBpZiAoIWJ5dGVzLmxlbmd0aCkgewogICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG1heERlY29kZUxlbmd0aCA9IGJ5dGVzLmxlbmd0aCArIDEgPj4gMTsKICAgIGNvbnN0IGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKHRoaXMuYnVmZmVyTGVuZ3RoICsgbWF4RGVjb2RlTGVuZ3RoKTsKICAgIGxldCBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlckxlbmd0aDsKICAgIGxldCBmaXJzdERpZ2l0ID0gdGhpcy5maXJzdERpZ2l0OwogICAgZm9yIChjb25zdCBjaCBvZiBieXRlcykgewogICAgICBsZXQgZGlnaXQ7CiAgICAgIGlmIChjaCA+PSAweDMwICYmIGNoIDw9IDB4MzkpIHsKICAgICAgICBkaWdpdCA9IGNoICYgMHgwZjsKICAgICAgfSBlbHNlIGlmIChjaCA+PSAweDQxICYmIGNoIDw9IDB4NDYgfHwgY2ggPj0gMHg2MSAmJiBjaCA8PSAweDY2KSB7CiAgICAgICAgZGlnaXQgPSAoY2ggJiAweDBmKSArIDk7CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4M2UpIHsKICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgICAgYnJlYWs7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGZpcnN0RGlnaXQgPCAwKSB7CiAgICAgICAgZmlyc3REaWdpdCA9IGRpZ2l0OwogICAgICB9IGVsc2UgewogICAgICAgIGJ1ZmZlcltidWZmZXJMZW5ndGgrK10gPSBmaXJzdERpZ2l0IDw8IDQgfCBkaWdpdDsKICAgICAgICBmaXJzdERpZ2l0ID0gLTE7CiAgICAgIH0KICAgIH0KICAgIGlmIChmaXJzdERpZ2l0ID49IDAgJiYgdGhpcy5lb2YpIHsKICAgICAgYnVmZmVyW2J1ZmZlckxlbmd0aCsrXSA9IGZpcnN0RGlnaXQgPDwgNDsKICAgICAgZmlyc3REaWdpdCA9IC0xOwogICAgfQogICAgdGhpcy5maXJzdERpZ2l0ID0gZmlyc3REaWdpdDsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gYnVmZmVyTGVuZ3RoOwogIH0KfQpleHBvcnRzLkFzY2lpSGV4U3RyZWFtID0gQXNjaWlIZXhTdHJlYW07CgovKioqLyB9KSwKLyogMTU1ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5DQ0lUVEZheFN0cmVhbSA9IHZvaWQgMDsKdmFyIF9jY2l0dCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTU2KTsKdmFyIF9kZWNvZGVfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTMpOwp2YXIgX3ByaW1pdGl2ZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MCk7CmNsYXNzIENDSVRURmF4U3RyZWFtIGV4dGVuZHMgX2RlY29kZV9zdHJlYW0uRGVjb2RlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHIsIG1heWJlTGVuZ3RoLCBwYXJhbXMpIHsKICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyID0gc3RyOwogICAgdGhpcy5kaWN0ID0gc3RyLmRpY3Q7CiAgICBpZiAoIShwYXJhbXMgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICBwYXJhbXMgPSBfcHJpbWl0aXZlcy5EaWN0LmVtcHR5OwogICAgfQogICAgY29uc3Qgc291cmNlID0gewogICAgICBuZXh0KCkgewogICAgICAgIHJldHVybiBzdHIuZ2V0Qnl0ZSgpOwogICAgICB9CiAgICB9OwogICAgdGhpcy5jY2l0dEZheERlY29kZXIgPSBuZXcgX2NjaXR0LkNDSVRURmF4RGVjb2Rlcihzb3VyY2UsIHsKICAgICAgSzogcGFyYW1zLmdldCgiSyIpLAogICAgICBFbmRPZkxpbmU6IHBhcmFtcy5nZXQoIkVuZE9mTGluZSIpLAogICAgICBFbmNvZGVkQnl0ZUFsaWduOiBwYXJhbXMuZ2V0KCJFbmNvZGVkQnl0ZUFsaWduIiksCiAgICAgIENvbHVtbnM6IHBhcmFtcy5nZXQoIkNvbHVtbnMiKSwKICAgICAgUm93czogcGFyYW1zLmdldCgiUm93cyIpLAogICAgICBFbmRPZkJsb2NrOiBwYXJhbXMuZ2V0KCJFbmRPZkJsb2NrIiksCiAgICAgIEJsYWNrSXMxOiBwYXJhbXMuZ2V0KCJCbGFja0lzMSIpCiAgICB9KTsKICB9CiAgcmVhZEJsb2NrKCkgewogICAgd2hpbGUgKCF0aGlzLmVvZikgewogICAgICBjb25zdCBjID0gdGhpcy5jY2l0dEZheERlY29kZXIucmVhZE5leHRDaGFyKCk7CiAgICAgIGlmIChjID09PSAtMSkgewogICAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhpcy5lbnN1cmVCdWZmZXIodGhpcy5idWZmZXJMZW5ndGggKyAxKTsKICAgICAgdGhpcy5idWZmZXJbdGhpcy5idWZmZXJMZW5ndGgrK10gPSBjOwogICAgfQogIH0KfQpleHBvcnRzLkNDSVRURmF4U3RyZWFtID0gQ0NJVFRGYXhTdHJlYW07CgovKioqLyB9KSwKLyogMTU2ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5DQ0lUVEZheERlY29kZXIgPSB2b2lkIDA7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CmNvbnN0IGNjaXR0RU9MID0gLTI7CmNvbnN0IGNjaXR0RU9GID0gLTE7CmNvbnN0IHR3b0RpbVBhc3MgPSAwOwpjb25zdCB0d29EaW1Ib3JpeiA9IDE7CmNvbnN0IHR3b0RpbVZlcnQwID0gMjsKY29uc3QgdHdvRGltVmVydFIxID0gMzsKY29uc3QgdHdvRGltVmVydEwxID0gNDsKY29uc3QgdHdvRGltVmVydFIyID0gNTsKY29uc3QgdHdvRGltVmVydEwyID0gNjsKY29uc3QgdHdvRGltVmVydFIzID0gNzsKY29uc3QgdHdvRGltVmVydEwzID0gODsKY29uc3QgdHdvRGltVGFibGUgPSBbWy0xLCAtMV0sIFstMSwgLTFdLCBbNywgdHdvRGltVmVydEwzXSwgWzcsIHR3b0RpbVZlcnRSM10sIFs2LCB0d29EaW1WZXJ0TDJdLCBbNiwgdHdvRGltVmVydEwyXSwgWzYsIHR3b0RpbVZlcnRSMl0sIFs2LCB0d29EaW1WZXJ0UjJdLCBbNCwgdHdvRGltUGFzc10sIFs0LCB0d29EaW1QYXNzXSwgWzQsIHR3b0RpbVBhc3NdLCBbNCwgdHdvRGltUGFzc10sIFs0LCB0d29EaW1QYXNzXSwgWzQsIHR3b0RpbVBhc3NdLCBbNCwgdHdvRGltUGFzc10sIFs0LCB0d29EaW1QYXNzXSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbUhvcml6XSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdLCBbMSwgdHdvRGltVmVydDBdXTsKY29uc3Qgd2hpdGVUYWJsZTEgPSBbWy0xLCAtMV0sIFsxMiwgY2NpdHRFT0xdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFsxMSwgMTc5Ml0sIFsxMSwgMTc5Ml0sIFsxMiwgMTk4NF0sIFsxMiwgMjA0OF0sIFsxMiwgMjExMl0sIFsxMiwgMjE3Nl0sIFsxMiwgMjI0MF0sIFsxMiwgMjMwNF0sIFsxMSwgMTg1Nl0sIFsxMSwgMTg1Nl0sIFsxMSwgMTkyMF0sIFsxMSwgMTkyMF0sIFsxMiwgMjM2OF0sIFsxMiwgMjQzMl0sIFsxMiwgMjQ5Nl0sIFsxMiwgMjU2MF1dOwpjb25zdCB3aGl0ZVRhYmxlMiA9IFtbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWzgsIDI5XSwgWzgsIDI5XSwgWzgsIDMwXSwgWzgsIDMwXSwgWzgsIDQ1XSwgWzgsIDQ1XSwgWzgsIDQ2XSwgWzgsIDQ2XSwgWzcsIDIyXSwgWzcsIDIyXSwgWzcsIDIyXSwgWzcsIDIyXSwgWzcsIDIzXSwgWzcsIDIzXSwgWzcsIDIzXSwgWzcsIDIzXSwgWzgsIDQ3XSwgWzgsIDQ3XSwgWzgsIDQ4XSwgWzgsIDQ4XSwgWzYsIDEzXSwgWzYsIDEzXSwgWzYsIDEzXSwgWzYsIDEzXSwgWzYsIDEzXSwgWzYsIDEzXSwgWzYsIDEzXSwgWzYsIDEzXSwgWzcsIDIwXSwgWzcsIDIwXSwgWzcsIDIwXSwgWzcsIDIwXSwgWzgsIDMzXSwgWzgsIDMzXSwgWzgsIDM0XSwgWzgsIDM0XSwgWzgsIDM1XSwgWzgsIDM1XSwgWzgsIDM2XSwgWzgsIDM2XSwgWzgsIDM3XSwgWzgsIDM3XSwgWzgsIDM4XSwgWzgsIDM4XSwgWzcsIDE5XSwgWzcsIDE5XSwgWzcsIDE5XSwgWzcsIDE5XSwgWzgsIDMxXSwgWzgsIDMxXSwgWzgsIDMyXSwgWzgsIDMyXSwgWzYsIDFdLCBbNiwgMV0sIFs2LCAxXSwgWzYsIDFdLCBbNiwgMV0sIFs2LCAxXSwgWzYsIDFdLCBbNiwgMV0sIFs2LCAxMl0sIFs2LCAxMl0sIFs2LCAxMl0sIFs2LCAxMl0sIFs2LCAxMl0sIFs2LCAxMl0sIFs2LCAxMl0sIFs2LCAxMl0sIFs4LCA1M10sIFs4LCA1M10sIFs4LCA1NF0sIFs4LCA1NF0sIFs3LCAyNl0sIFs3LCAyNl0sIFs3LCAyNl0sIFs3LCAyNl0sIFs4LCAzOV0sIFs4LCAzOV0sIFs4LCA0MF0sIFs4LCA0MF0sIFs4LCA0MV0sIFs4LCA0MV0sIFs4LCA0Ml0sIFs4LCA0Ml0sIFs4LCA0M10sIFs4LCA0M10sIFs4LCA0NF0sIFs4LCA0NF0sIFs3LCAyMV0sIFs3LCAyMV0sIFs3LCAyMV0sIFs3LCAyMV0sIFs3LCAyOF0sIFs3LCAyOF0sIFs3LCAyOF0sIFs3LCAyOF0sIFs4LCA2MV0sIFs4LCA2MV0sIFs4LCA2Ml0sIFs4LCA2Ml0sIFs4LCA2M10sIFs4LCA2M10sIFs4LCAwXSwgWzgsIDBdLCBbOCwgMzIwXSwgWzgsIDMyMF0sIFs4LCAzODRdLCBbOCwgMzg0XSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDEwXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzUsIDExXSwgWzcsIDI3XSwgWzcsIDI3XSwgWzcsIDI3XSwgWzcsIDI3XSwgWzgsIDU5XSwgWzgsIDU5XSwgWzgsIDYwXSwgWzgsIDYwXSwgWzksIDE0NzJdLCBbOSwgMTUzNl0sIFs5LCAxNjAwXSwgWzksIDE3MjhdLCBbNywgMThdLCBbNywgMThdLCBbNywgMThdLCBbNywgMThdLCBbNywgMjRdLCBbNywgMjRdLCBbNywgMjRdLCBbNywgMjRdLCBbOCwgNDldLCBbOCwgNDldLCBbOCwgNTBdLCBbOCwgNTBdLCBbOCwgNTFdLCBbOCwgNTFdLCBbOCwgNTJdLCBbOCwgNTJdLCBbNywgMjVdLCBbNywgMjVdLCBbNywgMjVdLCBbNywgMjVdLCBbOCwgNTVdLCBbOCwgNTVdLCBbOCwgNTZdLCBbOCwgNTZdLCBbOCwgNTddLCBbOCwgNTddLCBbOCwgNThdLCBbOCwgNThdLCBbNiwgMTkyXSwgWzYsIDE5Ml0sIFs2LCAxOTJdLCBbNiwgMTkyXSwgWzYsIDE5Ml0sIFs2LCAxOTJdLCBbNiwgMTkyXSwgWzYsIDE5Ml0sIFs2LCAxNjY0XSwgWzYsIDE2NjRdLCBbNiwgMTY2NF0sIFs2LCAxNjY0XSwgWzYsIDE2NjRdLCBbNiwgMTY2NF0sIFs2LCAxNjY0XSwgWzYsIDE2NjRdLCBbOCwgNDQ4XSwgWzgsIDQ0OF0sIFs4LCA1MTJdLCBbOCwgNTEyXSwgWzksIDcwNF0sIFs5LCA3NjhdLCBbOCwgNjQwXSwgWzgsIDY0MF0sIFs4LCA1NzZdLCBbOCwgNTc2XSwgWzksIDgzMl0sIFs5LCA4OTZdLCBbOSwgOTYwXSwgWzksIDEwMjRdLCBbOSwgMTA4OF0sIFs5LCAxMTUyXSwgWzksIDEyMTZdLCBbOSwgMTI4MF0sIFs5LCAxMzQ0XSwgWzksIDE0MDhdLCBbNywgMjU2XSwgWzcsIDI1Nl0sIFs3LCAyNTZdLCBbNywgMjU2XSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs2LCAxNl0sIFs2LCAxNl0sIFs2LCAxNl0sIFs2LCAxNl0sIFs2LCAxNl0sIFs2LCAxNl0sIFs2LCAxNl0sIFs2LCAxNl0sIFs2LCAxN10sIFs2LCAxN10sIFs2LCAxN10sIFs2LCAxN10sIFs2LCAxN10sIFs2LCAxN10sIFs2LCAxN10sIFs2LCAxN10sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzYsIDE0XSwgWzYsIDE0XSwgWzYsIDE0XSwgWzYsIDE0XSwgWzYsIDE0XSwgWzYsIDE0XSwgWzYsIDE0XSwgWzYsIDE0XSwgWzYsIDE1XSwgWzYsIDE1XSwgWzYsIDE1XSwgWzYsIDE1XSwgWzYsIDE1XSwgWzYsIDE1XSwgWzYsIDE1XSwgWzYsIDE1XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzUsIDY0XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddXTsKY29uc3QgYmxhY2tUYWJsZTEgPSBbWy0xLCAtMV0sIFstMSwgLTFdLCBbMTIsIGNjaXR0RU9MXSwgWzEyLCBjY2l0dEVPTF0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbMTEsIDE3OTJdLCBbMTEsIDE3OTJdLCBbMTEsIDE3OTJdLCBbMTEsIDE3OTJdLCBbMTIsIDE5ODRdLCBbMTIsIDE5ODRdLCBbMTIsIDIwNDhdLCBbMTIsIDIwNDhdLCBbMTIsIDIxMTJdLCBbMTIsIDIxMTJdLCBbMTIsIDIxNzZdLCBbMTIsIDIxNzZdLCBbMTIsIDIyNDBdLCBbMTIsIDIyNDBdLCBbMTIsIDIzMDRdLCBbMTIsIDIzMDRdLCBbMTEsIDE4NTZdLCBbMTEsIDE4NTZdLCBbMTEsIDE4NTZdLCBbMTEsIDE4NTZdLCBbMTEsIDE5MjBdLCBbMTEsIDE5MjBdLCBbMTEsIDE5MjBdLCBbMTEsIDE5MjBdLCBbMTIsIDIzNjhdLCBbMTIsIDIzNjhdLCBbMTIsIDI0MzJdLCBbMTIsIDI0MzJdLCBbMTIsIDI0OTZdLCBbMTIsIDI0OTZdLCBbMTIsIDI1NjBdLCBbMTIsIDI1NjBdLCBbMTAsIDE4XSwgWzEwLCAxOF0sIFsxMCwgMThdLCBbMTAsIDE4XSwgWzEwLCAxOF0sIFsxMCwgMThdLCBbMTAsIDE4XSwgWzEwLCAxOF0sIFsxMiwgNTJdLCBbMTIsIDUyXSwgWzEzLCA2NDBdLCBbMTMsIDcwNF0sIFsxMywgNzY4XSwgWzEzLCA4MzJdLCBbMTIsIDU1XSwgWzEyLCA1NV0sIFsxMiwgNTZdLCBbMTIsIDU2XSwgWzEzLCAxMjgwXSwgWzEzLCAxMzQ0XSwgWzEzLCAxNDA4XSwgWzEzLCAxNDcyXSwgWzEyLCA1OV0sIFsxMiwgNTldLCBbMTIsIDYwXSwgWzEyLCA2MF0sIFsxMywgMTUzNl0sIFsxMywgMTYwMF0sIFsxMSwgMjRdLCBbMTEsIDI0XSwgWzExLCAyNF0sIFsxMSwgMjRdLCBbMTEsIDI1XSwgWzExLCAyNV0sIFsxMSwgMjVdLCBbMTEsIDI1XSwgWzEzLCAxNjY0XSwgWzEzLCAxNzI4XSwgWzEyLCAzMjBdLCBbMTIsIDMyMF0sIFsxMiwgMzg0XSwgWzEyLCAzODRdLCBbMTIsIDQ0OF0sIFsxMiwgNDQ4XSwgWzEzLCA1MTJdLCBbMTMsIDU3Nl0sIFsxMiwgNTNdLCBbMTIsIDUzXSwgWzEyLCA1NF0sIFsxMiwgNTRdLCBbMTMsIDg5Nl0sIFsxMywgOTYwXSwgWzEzLCAxMDI0XSwgWzEzLCAxMDg4XSwgWzEzLCAxMTUyXSwgWzEzLCAxMjE2XSwgWzEwLCA2NF0sIFsxMCwgNjRdLCBbMTAsIDY0XSwgWzEwLCA2NF0sIFsxMCwgNjRdLCBbMTAsIDY0XSwgWzEwLCA2NF0sIFsxMCwgNjRdXTsKY29uc3QgYmxhY2tUYWJsZTIgPSBbWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzgsIDEzXSwgWzExLCAyM10sIFsxMSwgMjNdLCBbMTIsIDUwXSwgWzEyLCA1MV0sIFsxMiwgNDRdLCBbMTIsIDQ1XSwgWzEyLCA0Nl0sIFsxMiwgNDddLCBbMTIsIDU3XSwgWzEyLCA1OF0sIFsxMiwgNjFdLCBbMTIsIDI1Nl0sIFsxMCwgMTZdLCBbMTAsIDE2XSwgWzEwLCAxNl0sIFsxMCwgMTZdLCBbMTAsIDE3XSwgWzEwLCAxN10sIFsxMCwgMTddLCBbMTAsIDE3XSwgWzEyLCA0OF0sIFsxMiwgNDldLCBbMTIsIDYyXSwgWzEyLCA2M10sIFsxMiwgMzBdLCBbMTIsIDMxXSwgWzEyLCAzMl0sIFsxMiwgMzNdLCBbMTIsIDQwXSwgWzEyLCA0MV0sIFsxMSwgMjJdLCBbMTEsIDIyXSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzgsIDE0XSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDEwXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzcsIDExXSwgWzksIDE1XSwgWzksIDE1XSwgWzksIDE1XSwgWzksIDE1XSwgWzksIDE1XSwgWzksIDE1XSwgWzksIDE1XSwgWzksIDE1XSwgWzEyLCAxMjhdLCBbMTIsIDE5Ml0sIFsxMiwgMjZdLCBbMTIsIDI3XSwgWzEyLCAyOF0sIFsxMiwgMjldLCBbMTEsIDE5XSwgWzExLCAxOV0sIFsxMSwgMjBdLCBbMTEsIDIwXSwgWzEyLCAzNF0sIFsxMiwgMzVdLCBbMTIsIDM2XSwgWzEyLCAzN10sIFsxMiwgMzhdLCBbMTIsIDM5XSwgWzExLCAyMV0sIFsxMSwgMjFdLCBbMTIsIDQyXSwgWzEyLCA0M10sIFsxMCwgMF0sIFsxMCwgMF0sIFsxMCwgMF0sIFsxMCwgMF0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl0sIFs3LCAxMl1dOwpjb25zdCBibGFja1RhYmxlMyA9IFtbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWzYsIDldLCBbNiwgOF0sIFs1LCA3XSwgWzUsIDddLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzMsIDFdLCBbMywgMV0sIFszLCAxXSwgWzMsIDFdLCBbMywgMV0sIFszLCAxXSwgWzMsIDFdLCBbMywgMV0sIFszLCA0XSwgWzMsIDRdLCBbMywgNF0sIFszLCA0XSwgWzMsIDRdLCBbMywgNF0sIFszLCA0XSwgWzMsIDRdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXV07CmNsYXNzIENDSVRURmF4RGVjb2RlciB7CiAgY29uc3RydWN0b3Ioc291cmNlKSB7CiAgICBsZXQgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307CiAgICBpZiAoIXNvdXJjZSB8fCB0eXBlb2Ygc291cmNlLm5leHQgIT09ICJmdW5jdGlvbiIpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdDQ0lUVEZheERlY29kZXIgLSBpbnZhbGlkICJzb3VyY2UiIHBhcmFtZXRlci4nKTsKICAgIH0KICAgIHRoaXMuc291cmNlID0gc291cmNlOwogICAgdGhpcy5lb2YgPSBmYWxzZTsKICAgIHRoaXMuZW5jb2RpbmcgPSBvcHRpb25zLksgfHwgMDsKICAgIHRoaXMuZW9saW5lID0gb3B0aW9ucy5FbmRPZkxpbmUgfHwgZmFsc2U7CiAgICB0aGlzLmJ5dGVBbGlnbiA9IG9wdGlvbnMuRW5jb2RlZEJ5dGVBbGlnbiB8fCBmYWxzZTsKICAgIHRoaXMuY29sdW1ucyA9IG9wdGlvbnMuQ29sdW1ucyB8fCAxNzI4OwogICAgdGhpcy5yb3dzID0gb3B0aW9ucy5Sb3dzIHx8IDA7CiAgICBsZXQgZW9ibG9jayA9IG9wdGlvbnMuRW5kT2ZCbG9jazsKICAgIGlmIChlb2Jsb2NrID09PSBudWxsIHx8IGVvYmxvY2sgPT09IHVuZGVmaW5lZCkgewogICAgICBlb2Jsb2NrID0gdHJ1ZTsKICAgIH0KICAgIHRoaXMuZW9ibG9jayA9IGVvYmxvY2s7CiAgICB0aGlzLmJsYWNrID0gb3B0aW9ucy5CbGFja0lzMSB8fCBmYWxzZTsKICAgIHRoaXMuY29kaW5nTGluZSA9IG5ldyBVaW50MzJBcnJheSh0aGlzLmNvbHVtbnMgKyAxKTsKICAgIHRoaXMucmVmTGluZSA9IG5ldyBVaW50MzJBcnJheSh0aGlzLmNvbHVtbnMgKyAyKTsKICAgIHRoaXMuY29kaW5nTGluZVswXSA9IHRoaXMuY29sdW1uczsKICAgIHRoaXMuY29kaW5nUG9zID0gMDsKICAgIHRoaXMucm93ID0gMDsKICAgIHRoaXMubmV4dExpbmUyRCA9IHRoaXMuZW5jb2RpbmcgPCAwOwogICAgdGhpcy5pbnB1dEJpdHMgPSAwOwogICAgdGhpcy5pbnB1dEJ1ZiA9IDA7CiAgICB0aGlzLm91dHB1dEJpdHMgPSAwOwogICAgdGhpcy5yb3dzRG9uZSA9IGZhbHNlOwogICAgbGV0IGNvZGUxOwogICAgd2hpbGUgKChjb2RlMSA9IHRoaXMuX2xvb2tCaXRzKDEyKSkgPT09IDApIHsKICAgICAgdGhpcy5fZWF0Qml0cygxKTsKICAgIH0KICAgIGlmIChjb2RlMSA9PT0gMSkgewogICAgICB0aGlzLl9lYXRCaXRzKDEyKTsKICAgIH0KICAgIGlmICh0aGlzLmVuY29kaW5nID4gMCkgewogICAgICB0aGlzLm5leHRMaW5lMkQgPSAhdGhpcy5fbG9va0JpdHMoMSk7CiAgICAgIHRoaXMuX2VhdEJpdHMoMSk7CiAgICB9CiAgfQogIHJlYWROZXh0Q2hhcigpIHsKICAgIGlmICh0aGlzLmVvZikgewogICAgICByZXR1cm4gLTE7CiAgICB9CiAgICBjb25zdCByZWZMaW5lID0gdGhpcy5yZWZMaW5lOwogICAgY29uc3QgY29kaW5nTGluZSA9IHRoaXMuY29kaW5nTGluZTsKICAgIGNvbnN0IGNvbHVtbnMgPSB0aGlzLmNvbHVtbnM7CiAgICBsZXQgcmVmUG9zLCBibGFja1BpeGVscywgYml0cywgaTsKICAgIGlmICh0aGlzLm91dHB1dEJpdHMgPT09IDApIHsKICAgICAgaWYgKHRoaXMucm93c0RvbmUpIHsKICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuZW9mKSB7CiAgICAgICAgcmV0dXJuIC0xOwogICAgICB9CiAgICAgIHRoaXMuZXJyID0gZmFsc2U7CiAgICAgIGxldCBjb2RlMSwgY29kZTIsIGNvZGUzOwogICAgICBpZiAodGhpcy5uZXh0TGluZTJEKSB7CiAgICAgICAgZm9yIChpID0gMDsgY29kaW5nTGluZVtpXSA8IGNvbHVtbnM7ICsraSkgewogICAgICAgICAgcmVmTGluZVtpXSA9IGNvZGluZ0xpbmVbaV07CiAgICAgICAgfQogICAgICAgIHJlZkxpbmVbaSsrXSA9IGNvbHVtbnM7CiAgICAgICAgcmVmTGluZVtpXSA9IGNvbHVtbnM7CiAgICAgICAgY29kaW5nTGluZVswXSA9IDA7CiAgICAgICAgdGhpcy5jb2RpbmdQb3MgPSAwOwogICAgICAgIHJlZlBvcyA9IDA7CiAgICAgICAgYmxhY2tQaXhlbHMgPSAwOwogICAgICAgIHdoaWxlIChjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgIGNvZGUxID0gdGhpcy5fZ2V0VHdvRGltQ29kZSgpOwogICAgICAgICAgc3dpdGNoIChjb2RlMSkgewogICAgICAgICAgICBjYXNlIHR3b0RpbVBhc3M6CiAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzKHJlZkxpbmVbcmVmUG9zICsgMV0sIGJsYWNrUGl4ZWxzKTsKICAgICAgICAgICAgICBpZiAocmVmTGluZVtyZWZQb3MgKyAxXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgIHJlZlBvcyArPSAyOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSB0d29EaW1Ib3JpejoKICAgICAgICAgICAgICBjb2RlMSA9IGNvZGUyID0gMDsKICAgICAgICAgICAgICBpZiAoYmxhY2tQaXhlbHMpIHsKICAgICAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICAgICAgY29kZTEgKz0gY29kZTMgPSB0aGlzLl9nZXRCbGFja0NvZGUoKTsKICAgICAgICAgICAgICAgIH0gd2hpbGUgKGNvZGUzID49IDY0KTsKICAgICAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICAgICAgY29kZTIgKz0gY29kZTMgPSB0aGlzLl9nZXRXaGl0ZUNvZGUoKTsKICAgICAgICAgICAgICAgIH0gd2hpbGUgKGNvZGUzID49IDY0KTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgICAgICBjb2RlMSArPSBjb2RlMyA9IHRoaXMuX2dldFdoaXRlQ29kZSgpOwogICAgICAgICAgICAgICAgfSB3aGlsZSAoY29kZTMgPj0gNjQpOwogICAgICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgICAgICBjb2RlMiArPSBjb2RlMyA9IHRoaXMuX2dldEJsYWNrQ29kZSgpOwogICAgICAgICAgICAgICAgfSB3aGlsZSAoY29kZTMgPj0gNjQpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB0aGlzLl9hZGRQaXhlbHMoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gKyBjb2RlMSwgYmxhY2tQaXhlbHMpOwogICAgICAgICAgICAgIGlmIChjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgIHRoaXMuX2FkZFBpeGVscyhjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSArIGNvZGUyLCBibGFja1BpeGVscyBeIDEpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB3aGlsZSAocmVmTGluZVtyZWZQb3NdIDw9IGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdICYmIHJlZkxpbmVbcmVmUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgIHJlZlBvcyArPSAyOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSB0d29EaW1WZXJ0UjM6CiAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzKHJlZkxpbmVbcmVmUG9zXSArIDMsIGJsYWNrUGl4ZWxzKTsKICAgICAgICAgICAgICBibGFja1BpeGVscyBePSAxOwogICAgICAgICAgICAgIGlmIChjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgICsrcmVmUG9zOwogICAgICAgICAgICAgICAgd2hpbGUgKHJlZkxpbmVbcmVmUG9zXSA8PSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSAmJiByZWZMaW5lW3JlZlBvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICAgIHJlZlBvcyArPSAyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSB0d29EaW1WZXJ0UjI6CiAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzKHJlZkxpbmVbcmVmUG9zXSArIDIsIGJsYWNrUGl4ZWxzKTsKICAgICAgICAgICAgICBibGFja1BpeGVscyBePSAxOwogICAgICAgICAgICAgIGlmIChjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgICsrcmVmUG9zOwogICAgICAgICAgICAgICAgd2hpbGUgKHJlZkxpbmVbcmVmUG9zXSA8PSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSAmJiByZWZMaW5lW3JlZlBvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICAgIHJlZlBvcyArPSAyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSB0d29EaW1WZXJ0UjE6CiAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzKHJlZkxpbmVbcmVmUG9zXSArIDEsIGJsYWNrUGl4ZWxzKTsKICAgICAgICAgICAgICBibGFja1BpeGVscyBePSAxOwogICAgICAgICAgICAgIGlmIChjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgICsrcmVmUG9zOwogICAgICAgICAgICAgICAgd2hpbGUgKHJlZkxpbmVbcmVmUG9zXSA8PSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSAmJiByZWZMaW5lW3JlZlBvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICAgIHJlZlBvcyArPSAyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSB0d29EaW1WZXJ0MDoKICAgICAgICAgICAgICB0aGlzLl9hZGRQaXhlbHMocmVmTGluZVtyZWZQb3NdLCBibGFja1BpeGVscyk7CiAgICAgICAgICAgICAgYmxhY2tQaXhlbHMgXj0gMTsKICAgICAgICAgICAgICBpZiAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICArK3JlZlBvczsKICAgICAgICAgICAgICAgIHdoaWxlIChyZWZMaW5lW3JlZlBvc10gPD0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gJiYgcmVmTGluZVtyZWZQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgICByZWZQb3MgKz0gMjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgdHdvRGltVmVydEwzOgogICAgICAgICAgICAgIHRoaXMuX2FkZFBpeGVsc05lZyhyZWZMaW5lW3JlZlBvc10gLSAzLCBibGFja1BpeGVscyk7CiAgICAgICAgICAgICAgYmxhY2tQaXhlbHMgXj0gMTsKICAgICAgICAgICAgICBpZiAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICBpZiAocmVmUG9zID4gMCkgewogICAgICAgICAgICAgICAgICAtLXJlZlBvczsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICsrcmVmUG9zOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgd2hpbGUgKHJlZkxpbmVbcmVmUG9zXSA8PSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSAmJiByZWZMaW5lW3JlZlBvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICAgIHJlZlBvcyArPSAyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSB0d29EaW1WZXJ0TDI6CiAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzTmVnKHJlZkxpbmVbcmVmUG9zXSAtIDIsIGJsYWNrUGl4ZWxzKTsKICAgICAgICAgICAgICBibGFja1BpeGVscyBePSAxOwogICAgICAgICAgICAgIGlmIChjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgIGlmIChyZWZQb3MgPiAwKSB7CiAgICAgICAgICAgICAgICAgIC0tcmVmUG9zOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgKytyZWZQb3M7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB3aGlsZSAocmVmTGluZVtyZWZQb3NdIDw9IGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdICYmIHJlZkxpbmVbcmVmUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgICAgcmVmUG9zICs9IDI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIHR3b0RpbVZlcnRMMToKICAgICAgICAgICAgICB0aGlzLl9hZGRQaXhlbHNOZWcocmVmTGluZVtyZWZQb3NdIC0gMSwgYmxhY2tQaXhlbHMpOwogICAgICAgICAgICAgIGJsYWNrUGl4ZWxzIF49IDE7CiAgICAgICAgICAgICAgaWYgKGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgaWYgKHJlZlBvcyA+IDApIHsKICAgICAgICAgICAgICAgICAgLS1yZWZQb3M7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICArK3JlZlBvczsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHdoaWxlIChyZWZMaW5lW3JlZlBvc10gPD0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gJiYgcmVmTGluZVtyZWZQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgICByZWZQb3MgKz0gMjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgY2NpdHRFT0Y6CiAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzKGNvbHVtbnMsIDApOwogICAgICAgICAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAoMCwgX3V0aWwuaW5mbykoImJhZCAyZCBjb2RlIik7CiAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzKGNvbHVtbnMsIDApOwogICAgICAgICAgICAgIHRoaXMuZXJyID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29kaW5nTGluZVswXSA9IDA7CiAgICAgICAgdGhpcy5jb2RpbmdQb3MgPSAwOwogICAgICAgIGJsYWNrUGl4ZWxzID0gMDsKICAgICAgICB3aGlsZSAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICBjb2RlMSA9IDA7CiAgICAgICAgICBpZiAoYmxhY2tQaXhlbHMpIHsKICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgIGNvZGUxICs9IGNvZGUzID0gdGhpcy5fZ2V0QmxhY2tDb2RlKCk7CiAgICAgICAgICAgIH0gd2hpbGUgKGNvZGUzID49IDY0KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICBjb2RlMSArPSBjb2RlMyA9IHRoaXMuX2dldFdoaXRlQ29kZSgpOwogICAgICAgICAgICB9IHdoaWxlIChjb2RlMyA+PSA2NCk7CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLl9hZGRQaXhlbHMoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gKyBjb2RlMSwgYmxhY2tQaXhlbHMpOwogICAgICAgICAgYmxhY2tQaXhlbHMgXj0gMTsKICAgICAgICB9CiAgICAgIH0KICAgICAgbGV0IGdvdEVPTCA9IGZhbHNlOwogICAgICBpZiAodGhpcy5ieXRlQWxpZ24pIHsKICAgICAgICB0aGlzLmlucHV0Qml0cyAmPSB+NzsKICAgICAgfQogICAgICBpZiAoIXRoaXMuZW9ibG9jayAmJiB0aGlzLnJvdyA9PT0gdGhpcy5yb3dzIC0gMSkgewogICAgICAgIHRoaXMucm93c0RvbmUgPSB0cnVlOwogICAgICB9IGVsc2UgewogICAgICAgIGNvZGUxID0gdGhpcy5fbG9va0JpdHMoMTIpOwogICAgICAgIGlmICh0aGlzLmVvbGluZSkgewogICAgICAgICAgd2hpbGUgKGNvZGUxICE9PSBjY2l0dEVPRiAmJiBjb2RlMSAhPT0gMSkgewogICAgICAgICAgICB0aGlzLl9lYXRCaXRzKDEpOwogICAgICAgICAgICBjb2RlMSA9IHRoaXMuX2xvb2tCaXRzKDEyKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgd2hpbGUgKGNvZGUxID09PSAwKSB7CiAgICAgICAgICAgIHRoaXMuX2VhdEJpdHMoMSk7CiAgICAgICAgICAgIGNvZGUxID0gdGhpcy5fbG9va0JpdHMoMTIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoY29kZTEgPT09IDEpIHsKICAgICAgICAgIHRoaXMuX2VhdEJpdHMoMTIpOwogICAgICAgICAgZ290RU9MID0gdHJ1ZTsKICAgICAgICB9IGVsc2UgaWYgKGNvZGUxID09PSBjY2l0dEVPRikgewogICAgICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoIXRoaXMuZW9mICYmIHRoaXMuZW5jb2RpbmcgPiAwICYmICF0aGlzLnJvd3NEb25lKSB7CiAgICAgICAgdGhpcy5uZXh0TGluZTJEID0gIXRoaXMuX2xvb2tCaXRzKDEpOwogICAgICAgIHRoaXMuX2VhdEJpdHMoMSk7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuZW9ibG9jayAmJiBnb3RFT0wgJiYgdGhpcy5ieXRlQWxpZ24pIHsKICAgICAgICBjb2RlMSA9IHRoaXMuX2xvb2tCaXRzKDEyKTsKICAgICAgICBpZiAoY29kZTEgPT09IDEpIHsKICAgICAgICAgIHRoaXMuX2VhdEJpdHMoMTIpOwogICAgICAgICAgaWYgKHRoaXMuZW5jb2RpbmcgPiAwKSB7CiAgICAgICAgICAgIHRoaXMuX2xvb2tCaXRzKDEpOwogICAgICAgICAgICB0aGlzLl9lYXRCaXRzKDEpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHRoaXMuZW5jb2RpbmcgPj0gMCkgewogICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNDsgKytpKSB7CiAgICAgICAgICAgICAgY29kZTEgPSB0aGlzLl9sb29rQml0cygxMik7CiAgICAgICAgICAgICAgaWYgKGNvZGUxICE9PSAxKSB7CiAgICAgICAgICAgICAgICAoMCwgX3V0aWwuaW5mbykoImJhZCBydGMgY29kZTogIiArIGNvZGUxKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdGhpcy5fZWF0Qml0cygxMik7CiAgICAgICAgICAgICAgaWYgKHRoaXMuZW5jb2RpbmcgPiAwKSB7CiAgICAgICAgICAgICAgICB0aGlzLl9sb29rQml0cygxKTsKICAgICAgICAgICAgICAgIHRoaXMuX2VhdEJpdHMoMSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKHRoaXMuZXJyICYmIHRoaXMuZW9saW5lKSB7CiAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgIGNvZGUxID0gdGhpcy5fbG9va0JpdHMoMTMpOwogICAgICAgICAgaWYgKGNvZGUxID09PSBjY2l0dEVPRikgewogICAgICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgICAgICAgIHJldHVybiAtMTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChjb2RlMSA+PiAxID09PSAxKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5fZWF0Qml0cygxKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5fZWF0Qml0cygxMik7CiAgICAgICAgaWYgKHRoaXMuZW5jb2RpbmcgPiAwKSB7CiAgICAgICAgICB0aGlzLl9lYXRCaXRzKDEpOwogICAgICAgICAgdGhpcy5uZXh0TGluZTJEID0gIShjb2RlMSAmIDEpOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoY29kaW5nTGluZVswXSA+IDApIHsKICAgICAgICB0aGlzLm91dHB1dEJpdHMgPSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zID0gMF07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5vdXRwdXRCaXRzID0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1BvcyA9IDFdOwogICAgICB9CiAgICAgIHRoaXMucm93Kys7CiAgICB9CiAgICBsZXQgYzsKICAgIGlmICh0aGlzLm91dHB1dEJpdHMgPj0gOCkgewogICAgICBjID0gdGhpcy5jb2RpbmdQb3MgJiAxID8gMCA6IDB4ZmY7CiAgICAgIHRoaXMub3V0cHV0Qml0cyAtPSA4OwogICAgICBpZiAodGhpcy5vdXRwdXRCaXRzID09PSAwICYmIGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIDwgY29sdW1ucykgewogICAgICAgIHRoaXMuY29kaW5nUG9zKys7CiAgICAgICAgdGhpcy5vdXRwdXRCaXRzID0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gLSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zIC0gMV07CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGJpdHMgPSA4OwogICAgICBjID0gMDsKICAgICAgZG8gewogICAgICAgIGlmICh0eXBlb2YgdGhpcy5vdXRwdXRCaXRzICE9PSAibnVtYmVyIikgewogICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCdJbnZhbGlkIC9DQ0lUVEZheERlY29kZSBkYXRhLCAib3V0cHV0Qml0cyIgbXVzdCBiZSBhIG51bWJlci4nKTsKICAgICAgICB9CiAgICAgICAgaWYgKHRoaXMub3V0cHV0Qml0cyA+IGJpdHMpIHsKICAgICAgICAgIGMgPDw9IGJpdHM7CiAgICAgICAgICBpZiAoISh0aGlzLmNvZGluZ1BvcyAmIDEpKSB7CiAgICAgICAgICAgIGMgfD0gMHhmZiA+PiA4IC0gYml0czsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMub3V0cHV0Qml0cyAtPSBiaXRzOwogICAgICAgICAgYml0cyA9IDA7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGMgPDw9IHRoaXMub3V0cHV0Qml0czsKICAgICAgICAgIGlmICghKHRoaXMuY29kaW5nUG9zICYgMSkpIHsKICAgICAgICAgICAgYyB8PSAweGZmID4+IDggLSB0aGlzLm91dHB1dEJpdHM7CiAgICAgICAgICB9CiAgICAgICAgICBiaXRzIC09IHRoaXMub3V0cHV0Qml0czsKICAgICAgICAgIHRoaXMub3V0cHV0Qml0cyA9IDA7CiAgICAgICAgICBpZiAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgIHRoaXMuY29kaW5nUG9zKys7CiAgICAgICAgICAgIHRoaXMub3V0cHV0Qml0cyA9IGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIC0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1BvcyAtIDFdOwogICAgICAgICAgfSBlbHNlIGlmIChiaXRzID4gMCkgewogICAgICAgICAgICBjIDw8PSBiaXRzOwogICAgICAgICAgICBiaXRzID0gMDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gd2hpbGUgKGJpdHMpOwogICAgfQogICAgaWYgKHRoaXMuYmxhY2spIHsKICAgICAgYyBePSAweGZmOwogICAgfQogICAgcmV0dXJuIGM7CiAgfQogIF9hZGRQaXhlbHMoYTEsIGJsYWNrUGl4ZWxzKSB7CiAgICBjb25zdCBjb2RpbmdMaW5lID0gdGhpcy5jb2RpbmdMaW5lOwogICAgbGV0IGNvZGluZ1BvcyA9IHRoaXMuY29kaW5nUG9zOwogICAgaWYgKGExID4gY29kaW5nTGluZVtjb2RpbmdQb3NdKSB7CiAgICAgIGlmIChhMSA+IHRoaXMuY29sdW1ucykgewogICAgICAgICgwLCBfdXRpbC5pbmZvKSgicm93IGlzIHdyb25nIGxlbmd0aCIpOwogICAgICAgIHRoaXMuZXJyID0gdHJ1ZTsKICAgICAgICBhMSA9IHRoaXMuY29sdW1uczsKICAgICAgfQogICAgICBpZiAoY29kaW5nUG9zICYgMSBeIGJsYWNrUGl4ZWxzKSB7CiAgICAgICAgKytjb2RpbmdQb3M7CiAgICAgIH0KICAgICAgY29kaW5nTGluZVtjb2RpbmdQb3NdID0gYTE7CiAgICB9CiAgICB0aGlzLmNvZGluZ1BvcyA9IGNvZGluZ1BvczsKICB9CiAgX2FkZFBpeGVsc05lZyhhMSwgYmxhY2tQaXhlbHMpIHsKICAgIGNvbnN0IGNvZGluZ0xpbmUgPSB0aGlzLmNvZGluZ0xpbmU7CiAgICBsZXQgY29kaW5nUG9zID0gdGhpcy5jb2RpbmdQb3M7CiAgICBpZiAoYTEgPiBjb2RpbmdMaW5lW2NvZGluZ1Bvc10pIHsKICAgICAgaWYgKGExID4gdGhpcy5jb2x1bW5zKSB7CiAgICAgICAgKDAsIF91dGlsLmluZm8pKCJyb3cgaXMgd3JvbmcgbGVuZ3RoIik7CiAgICAgICAgdGhpcy5lcnIgPSB0cnVlOwogICAgICAgIGExID0gdGhpcy5jb2x1bW5zOwogICAgICB9CiAgICAgIGlmIChjb2RpbmdQb3MgJiAxIF4gYmxhY2tQaXhlbHMpIHsKICAgICAgICArK2NvZGluZ1BvczsKICAgICAgfQogICAgICBjb2RpbmdMaW5lW2NvZGluZ1Bvc10gPSBhMTsKICAgIH0gZWxzZSBpZiAoYTEgPCBjb2RpbmdMaW5lW2NvZGluZ1Bvc10pIHsKICAgICAgaWYgKGExIDwgMCkgewogICAgICAgICgwLCBfdXRpbC5pbmZvKSgiaW52YWxpZCBjb2RlIik7CiAgICAgICAgdGhpcy5lcnIgPSB0cnVlOwogICAgICAgIGExID0gMDsKICAgICAgfQogICAgICB3aGlsZSAoY29kaW5nUG9zID4gMCAmJiBhMSA8IGNvZGluZ0xpbmVbY29kaW5nUG9zIC0gMV0pIHsKICAgICAgICAtLWNvZGluZ1BvczsKICAgICAgfQogICAgICBjb2RpbmdMaW5lW2NvZGluZ1Bvc10gPSBhMTsKICAgIH0KICAgIHRoaXMuY29kaW5nUG9zID0gY29kaW5nUG9zOwogIH0KICBfZmluZFRhYmxlQ29kZShzdGFydCwgZW5kLCB0YWJsZSwgbGltaXQpIHsKICAgIGNvbnN0IGxpbWl0VmFsdWUgPSBsaW1pdCB8fCAwOwogICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDw9IGVuZDsgKytpKSB7CiAgICAgIGxldCBjb2RlID0gdGhpcy5fbG9va0JpdHMoaSk7CiAgICAgIGlmIChjb2RlID09PSBjY2l0dEVPRikgewogICAgICAgIHJldHVybiBbdHJ1ZSwgMSwgZmFsc2VdOwogICAgICB9CiAgICAgIGlmIChpIDwgZW5kKSB7CiAgICAgICAgY29kZSA8PD0gZW5kIC0gaTsKICAgICAgfQogICAgICBpZiAoIWxpbWl0VmFsdWUgfHwgY29kZSA+PSBsaW1pdFZhbHVlKSB7CiAgICAgICAgY29uc3QgcCA9IHRhYmxlW2NvZGUgLSBsaW1pdFZhbHVlXTsKICAgICAgICBpZiAocFswXSA9PT0gaSkgewogICAgICAgICAgdGhpcy5fZWF0Qml0cyhpKTsKICAgICAgICAgIHJldHVybiBbdHJ1ZSwgcFsxXSwgdHJ1ZV07CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gW2ZhbHNlLCAwLCBmYWxzZV07CiAgfQogIF9nZXRUd29EaW1Db2RlKCkgewogICAgbGV0IGNvZGUgPSAwOwogICAgbGV0IHA7CiAgICBpZiAodGhpcy5lb2Jsb2NrKSB7CiAgICAgIGNvZGUgPSB0aGlzLl9sb29rQml0cyg3KTsKICAgICAgcCA9IHR3b0RpbVRhYmxlW2NvZGVdOwogICAgICBpZiAocCAmJiBwWzBdID4gMCkgewogICAgICAgIHRoaXMuX2VhdEJpdHMocFswXSk7CiAgICAgICAgcmV0dXJuIHBbMV07CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX2ZpbmRUYWJsZUNvZGUoMSwgNywgdHdvRGltVGFibGUpOwogICAgICBpZiAocmVzdWx0WzBdICYmIHJlc3VsdFsyXSkgewogICAgICAgIHJldHVybiByZXN1bHRbMV07CiAgICAgIH0KICAgIH0KICAgICgwLCBfdXRpbC5pbmZvKSgiQmFkIHR3byBkaW0gY29kZSIpOwogICAgcmV0dXJuIGNjaXR0RU9GOwogIH0KICBfZ2V0V2hpdGVDb2RlKCkgewogICAgbGV0IGNvZGUgPSAwOwogICAgbGV0IHA7CiAgICBpZiAodGhpcy5lb2Jsb2NrKSB7CiAgICAgIGNvZGUgPSB0aGlzLl9sb29rQml0cygxMik7CiAgICAgIGlmIChjb2RlID09PSBjY2l0dEVPRikgewogICAgICAgIHJldHVybiAxOwogICAgICB9CiAgICAgIGlmIChjb2RlID4+IDUgPT09IDApIHsKICAgICAgICBwID0gd2hpdGVUYWJsZTFbY29kZV07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcCA9IHdoaXRlVGFibGUyW2NvZGUgPj4gM107CiAgICAgIH0KICAgICAgaWYgKHBbMF0gPiAwKSB7CiAgICAgICAgdGhpcy5fZWF0Qml0cyhwWzBdKTsKICAgICAgICByZXR1cm4gcFsxXTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgbGV0IHJlc3VsdCA9IHRoaXMuX2ZpbmRUYWJsZUNvZGUoMSwgOSwgd2hpdGVUYWJsZTIpOwogICAgICBpZiAocmVzdWx0WzBdKSB7CiAgICAgICAgcmV0dXJuIHJlc3VsdFsxXTsKICAgICAgfQogICAgICByZXN1bHQgPSB0aGlzLl9maW5kVGFibGVDb2RlKDExLCAxMiwgd2hpdGVUYWJsZTEpOwogICAgICBpZiAocmVzdWx0WzBdKSB7CiAgICAgICAgcmV0dXJuIHJlc3VsdFsxXTsKICAgICAgfQogICAgfQogICAgKDAsIF91dGlsLmluZm8pKCJiYWQgd2hpdGUgY29kZSIpOwogICAgdGhpcy5fZWF0Qml0cygxKTsKICAgIHJldHVybiAxOwogIH0KICBfZ2V0QmxhY2tDb2RlKCkgewogICAgbGV0IGNvZGUsIHA7CiAgICBpZiAodGhpcy5lb2Jsb2NrKSB7CiAgICAgIGNvZGUgPSB0aGlzLl9sb29rQml0cygxMyk7CiAgICAgIGlmIChjb2RlID09PSBjY2l0dEVPRikgewogICAgICAgIHJldHVybiAxOwogICAgICB9CiAgICAgIGlmIChjb2RlID4+IDcgPT09IDApIHsKICAgICAgICBwID0gYmxhY2tUYWJsZTFbY29kZV07CiAgICAgIH0gZWxzZSBpZiAoY29kZSA+PiA5ID09PSAwICYmIGNvZGUgPj4gNyAhPT0gMCkgewogICAgICAgIHAgPSBibGFja1RhYmxlMlsoY29kZSA+PiAxKSAtIDY0XTsKICAgICAgfSBlbHNlIHsKICAgICAgICBwID0gYmxhY2tUYWJsZTNbY29kZSA+PiA3XTsKICAgICAgfQogICAgICBpZiAocFswXSA+IDApIHsKICAgICAgICB0aGlzLl9lYXRCaXRzKHBbMF0pOwogICAgICAgIHJldHVybiBwWzFdOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBsZXQgcmVzdWx0ID0gdGhpcy5fZmluZFRhYmxlQ29kZSgyLCA2LCBibGFja1RhYmxlMyk7CiAgICAgIGlmIChyZXN1bHRbMF0pIHsKICAgICAgICByZXR1cm4gcmVzdWx0WzFdOwogICAgICB9CiAgICAgIHJlc3VsdCA9IHRoaXMuX2ZpbmRUYWJsZUNvZGUoNywgMTIsIGJsYWNrVGFibGUyLCA2NCk7CiAgICAgIGlmIChyZXN1bHRbMF0pIHsKICAgICAgICByZXR1cm4gcmVzdWx0WzFdOwogICAgICB9CiAgICAgIHJlc3VsdCA9IHRoaXMuX2ZpbmRUYWJsZUNvZGUoMTAsIDEzLCBibGFja1RhYmxlMSk7CiAgICAgIGlmIChyZXN1bHRbMF0pIHsKICAgICAgICByZXR1cm4gcmVzdWx0WzFdOwogICAgICB9CiAgICB9CiAgICAoMCwgX3V0aWwuaW5mbykoImJhZCBibGFjayBjb2RlIik7CiAgICB0aGlzLl9lYXRCaXRzKDEpOwogICAgcmV0dXJuIDE7CiAgfQogIF9sb29rQml0cyhuKSB7CiAgICBsZXQgYzsKICAgIHdoaWxlICh0aGlzLmlucHV0Qml0cyA8IG4pIHsKICAgICAgaWYgKChjID0gdGhpcy5zb3VyY2UubmV4dCgpKSA9PT0gLTEpIHsKICAgICAgICBpZiAodGhpcy5pbnB1dEJpdHMgPT09IDApIHsKICAgICAgICAgIHJldHVybiBjY2l0dEVPRjsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXMuaW5wdXRCdWYgPDwgbiAtIHRoaXMuaW5wdXRCaXRzICYgMHhmZmZmID4+IDE2IC0gbjsKICAgICAgfQogICAgICB0aGlzLmlucHV0QnVmID0gdGhpcy5pbnB1dEJ1ZiA8PCA4IHwgYzsKICAgICAgdGhpcy5pbnB1dEJpdHMgKz0gODsKICAgIH0KICAgIHJldHVybiB0aGlzLmlucHV0QnVmID4+IHRoaXMuaW5wdXRCaXRzIC0gbiAmIDB4ZmZmZiA+PiAxNiAtIG47CiAgfQogIF9lYXRCaXRzKG4pIHsKICAgIGlmICgodGhpcy5pbnB1dEJpdHMgLT0gbikgPCAwKSB7CiAgICAgIHRoaXMuaW5wdXRCaXRzID0gMDsKICAgIH0KICB9Cn0KZXhwb3J0cy5DQ0lUVEZheERlY29kZXIgPSBDQ0lUVEZheERlY29kZXI7CgovKioqLyB9KSwKLyogMTU3ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5GbGF0ZVN0cmVhbSA9IHZvaWQgMDsKdmFyIF9kZWNvZGVfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTMpOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpjb25zdCBjb2RlTGVuQ29kZU1hcCA9IG5ldyBJbnQzMkFycmF5KFsxNiwgMTcsIDE4LCAwLCA4LCA3LCA5LCA2LCAxMCwgNSwgMTEsIDQsIDEyLCAzLCAxMywgMiwgMTQsIDEsIDE1XSk7CmNvbnN0IGxlbmd0aERlY29kZSA9IG5ldyBJbnQzMkFycmF5KFsweDAwMDAzLCAweDAwMDA0LCAweDAwMDA1LCAweDAwMDA2LCAweDAwMDA3LCAweDAwMDA4LCAweDAwMDA5LCAweDAwMDBhLCAweDEwMDBiLCAweDEwMDBkLCAweDEwMDBmLCAweDEwMDExLCAweDIwMDEzLCAweDIwMDE3LCAweDIwMDFiLCAweDIwMDFmLCAweDMwMDIzLCAweDMwMDJiLCAweDMwMDMzLCAweDMwMDNiLCAweDQwMDQzLCAweDQwMDUzLCAweDQwMDYzLCAweDQwMDczLCAweDUwMDgzLCAweDUwMGEzLCAweDUwMGMzLCAweDUwMGUzLCAweDAwMTAyLCAweDAwMTAyLCAweDAwMTAyXSk7CmNvbnN0IGRpc3REZWNvZGUgPSBuZXcgSW50MzJBcnJheShbMHgwMDAwMSwgMHgwMDAwMiwgMHgwMDAwMywgMHgwMDAwNCwgMHgxMDAwNSwgMHgxMDAwNywgMHgyMDAwOSwgMHgyMDAwZCwgMHgzMDAxMSwgMHgzMDAxOSwgMHg0MDAyMSwgMHg0MDAzMSwgMHg1MDA0MSwgMHg1MDA2MSwgMHg2MDA4MSwgMHg2MDBjMSwgMHg3MDEwMSwgMHg3MDE4MSwgMHg4MDIwMSwgMHg4MDMwMSwgMHg5MDQwMSwgMHg5MDYwMSwgMHhhMDgwMSwgMHhhMGMwMSwgMHhiMTAwMSwgMHhiMTgwMSwgMHhjMjAwMSwgMHhjMzAwMSwgMHhkNDAwMSwgMHhkNjAwMV0pOwpjb25zdCBmaXhlZExpdENvZGVUYWIgPSBbbmV3IEludDMyQXJyYXkoWzB4NzAxMDAsIDB4ODAwNTAsIDB4ODAwMTAsIDB4ODAxMTgsIDB4NzAxMTAsIDB4ODAwNzAsIDB4ODAwMzAsIDB4OTAwYzAsIDB4NzAxMDgsIDB4ODAwNjAsIDB4ODAwMjAsIDB4OTAwYTAsIDB4ODAwMDAsIDB4ODAwODAsIDB4ODAwNDAsIDB4OTAwZTAsIDB4NzAxMDQsIDB4ODAwNTgsIDB4ODAwMTgsIDB4OTAwOTAsIDB4NzAxMTQsIDB4ODAwNzgsIDB4ODAwMzgsIDB4OTAwZDAsIDB4NzAxMGMsIDB4ODAwNjgsIDB4ODAwMjgsIDB4OTAwYjAsIDB4ODAwMDgsIDB4ODAwODgsIDB4ODAwNDgsIDB4OTAwZjAsIDB4NzAxMDIsIDB4ODAwNTQsIDB4ODAwMTQsIDB4ODAxMWMsIDB4NzAxMTIsIDB4ODAwNzQsIDB4ODAwMzQsIDB4OTAwYzgsIDB4NzAxMGEsIDB4ODAwNjQsIDB4ODAwMjQsIDB4OTAwYTgsIDB4ODAwMDQsIDB4ODAwODQsIDB4ODAwNDQsIDB4OTAwZTgsIDB4NzAxMDYsIDB4ODAwNWMsIDB4ODAwMWMsIDB4OTAwOTgsIDB4NzAxMTYsIDB4ODAwN2MsIDB4ODAwM2MsIDB4OTAwZDgsIDB4NzAxMGUsIDB4ODAwNmMsIDB4ODAwMmMsIDB4OTAwYjgsIDB4ODAwMGMsIDB4ODAwOGMsIDB4ODAwNGMsIDB4OTAwZjgsIDB4NzAxMDEsIDB4ODAwNTIsIDB4ODAwMTIsIDB4ODAxMWEsIDB4NzAxMTEsIDB4ODAwNzIsIDB4ODAwMzIsIDB4OTAwYzQsIDB4NzAxMDksIDB4ODAwNjIsIDB4ODAwMjIsIDB4OTAwYTQsIDB4ODAwMDIsIDB4ODAwODIsIDB4ODAwNDIsIDB4OTAwZTQsIDB4NzAxMDUsIDB4ODAwNWEsIDB4ODAwMWEsIDB4OTAwOTQsIDB4NzAxMTUsIDB4ODAwN2EsIDB4ODAwM2EsIDB4OTAwZDQsIDB4NzAxMGQsIDB4ODAwNmEsIDB4ODAwMmEsIDB4OTAwYjQsIDB4ODAwMGEsIDB4ODAwOGEsIDB4ODAwNGEsIDB4OTAwZjQsIDB4NzAxMDMsIDB4ODAwNTYsIDB4ODAwMTYsIDB4ODAxMWUsIDB4NzAxMTMsIDB4ODAwNzYsIDB4ODAwMzYsIDB4OTAwY2MsIDB4NzAxMGIsIDB4ODAwNjYsIDB4ODAwMjYsIDB4OTAwYWMsIDB4ODAwMDYsIDB4ODAwODYsIDB4ODAwNDYsIDB4OTAwZWMsIDB4NzAxMDcsIDB4ODAwNWUsIDB4ODAwMWUsIDB4OTAwOWMsIDB4NzAxMTcsIDB4ODAwN2UsIDB4ODAwM2UsIDB4OTAwZGMsIDB4NzAxMGYsIDB4ODAwNmUsIDB4ODAwMmUsIDB4OTAwYmMsIDB4ODAwMGUsIDB4ODAwOGUsIDB4ODAwNGUsIDB4OTAwZmMsIDB4NzAxMDAsIDB4ODAwNTEsIDB4ODAwMTEsIDB4ODAxMTksIDB4NzAxMTAsIDB4ODAwNzEsIDB4ODAwMzEsIDB4OTAwYzIsIDB4NzAxMDgsIDB4ODAwNjEsIDB4ODAwMjEsIDB4OTAwYTIsIDB4ODAwMDEsIDB4ODAwODEsIDB4ODAwNDEsIDB4OTAwZTIsIDB4NzAxMDQsIDB4ODAwNTksIDB4ODAwMTksIDB4OTAwOTIsIDB4NzAxMTQsIDB4ODAwNzksIDB4ODAwMzksIDB4OTAwZDIsIDB4NzAxMGMsIDB4ODAwNjksIDB4ODAwMjksIDB4OTAwYjIsIDB4ODAwMDksIDB4ODAwODksIDB4ODAwNDksIDB4OTAwZjIsIDB4NzAxMDIsIDB4ODAwNTUsIDB4ODAwMTUsIDB4ODAxMWQsIDB4NzAxMTIsIDB4ODAwNzUsIDB4ODAwMzUsIDB4OTAwY2EsIDB4NzAxMGEsIDB4ODAwNjUsIDB4ODAwMjUsIDB4OTAwYWEsIDB4ODAwMDUsIDB4ODAwODUsIDB4ODAwNDUsIDB4OTAwZWEsIDB4NzAxMDYsIDB4ODAwNWQsIDB4ODAwMWQsIDB4OTAwOWEsIDB4NzAxMTYsIDB4ODAwN2QsIDB4ODAwM2QsIDB4OTAwZGEsIDB4NzAxMGUsIDB4ODAwNmQsIDB4ODAwMmQsIDB4OTAwYmEsIDB4ODAwMGQsIDB4ODAwOGQsIDB4ODAwNGQsIDB4OTAwZmEsIDB4NzAxMDEsIDB4ODAwNTMsIDB4ODAwMTMsIDB4ODAxMWIsIDB4NzAxMTEsIDB4ODAwNzMsIDB4ODAwMzMsIDB4OTAwYzYsIDB4NzAxMDksIDB4ODAwNjMsIDB4ODAwMjMsIDB4OTAwYTYsIDB4ODAwMDMsIDB4ODAwODMsIDB4ODAwNDMsIDB4OTAwZTYsIDB4NzAxMDUsIDB4ODAwNWIsIDB4ODAwMWIsIDB4OTAwOTYsIDB4NzAxMTUsIDB4ODAwN2IsIDB4ODAwM2IsIDB4OTAwZDYsIDB4NzAxMGQsIDB4ODAwNmIsIDB4ODAwMmIsIDB4OTAwYjYsIDB4ODAwMGIsIDB4ODAwOGIsIDB4ODAwNGIsIDB4OTAwZjYsIDB4NzAxMDMsIDB4ODAwNTcsIDB4ODAwMTcsIDB4ODAxMWYsIDB4NzAxMTMsIDB4ODAwNzcsIDB4ODAwMzcsIDB4OTAwY2UsIDB4NzAxMGIsIDB4ODAwNjcsIDB4ODAwMjcsIDB4OTAwYWUsIDB4ODAwMDcsIDB4ODAwODcsIDB4ODAwNDcsIDB4OTAwZWUsIDB4NzAxMDcsIDB4ODAwNWYsIDB4ODAwMWYsIDB4OTAwOWUsIDB4NzAxMTcsIDB4ODAwN2YsIDB4ODAwM2YsIDB4OTAwZGUsIDB4NzAxMGYsIDB4ODAwNmYsIDB4ODAwMmYsIDB4OTAwYmUsIDB4ODAwMGYsIDB4ODAwOGYsIDB4ODAwNGYsIDB4OTAwZmUsIDB4NzAxMDAsIDB4ODAwNTAsIDB4ODAwMTAsIDB4ODAxMTgsIDB4NzAxMTAsIDB4ODAwNzAsIDB4ODAwMzAsIDB4OTAwYzEsIDB4NzAxMDgsIDB4ODAwNjAsIDB4ODAwMjAsIDB4OTAwYTEsIDB4ODAwMDAsIDB4ODAwODAsIDB4ODAwNDAsIDB4OTAwZTEsIDB4NzAxMDQsIDB4ODAwNTgsIDB4ODAwMTgsIDB4OTAwOTEsIDB4NzAxMTQsIDB4ODAwNzgsIDB4ODAwMzgsIDB4OTAwZDEsIDB4NzAxMGMsIDB4ODAwNjgsIDB4ODAwMjgsIDB4OTAwYjEsIDB4ODAwMDgsIDB4ODAwODgsIDB4ODAwNDgsIDB4OTAwZjEsIDB4NzAxMDIsIDB4ODAwNTQsIDB4ODAwMTQsIDB4ODAxMWMsIDB4NzAxMTIsIDB4ODAwNzQsIDB4ODAwMzQsIDB4OTAwYzksIDB4NzAxMGEsIDB4ODAwNjQsIDB4ODAwMjQsIDB4OTAwYTksIDB4ODAwMDQsIDB4ODAwODQsIDB4ODAwNDQsIDB4OTAwZTksIDB4NzAxMDYsIDB4ODAwNWMsIDB4ODAwMWMsIDB4OTAwOTksIDB4NzAxMTYsIDB4ODAwN2MsIDB4ODAwM2MsIDB4OTAwZDksIDB4NzAxMGUsIDB4ODAwNmMsIDB4ODAwMmMsIDB4OTAwYjksIDB4ODAwMGMsIDB4ODAwOGMsIDB4ODAwNGMsIDB4OTAwZjksIDB4NzAxMDEsIDB4ODAwNTIsIDB4ODAwMTIsIDB4ODAxMWEsIDB4NzAxMTEsIDB4ODAwNzIsIDB4ODAwMzIsIDB4OTAwYzUsIDB4NzAxMDksIDB4ODAwNjIsIDB4ODAwMjIsIDB4OTAwYTUsIDB4ODAwMDIsIDB4ODAwODIsIDB4ODAwNDIsIDB4OTAwZTUsIDB4NzAxMDUsIDB4ODAwNWEsIDB4ODAwMWEsIDB4OTAwOTUsIDB4NzAxMTUsIDB4ODAwN2EsIDB4ODAwM2EsIDB4OTAwZDUsIDB4NzAxMGQsIDB4ODAwNmEsIDB4ODAwMmEsIDB4OTAwYjUsIDB4ODAwMGEsIDB4ODAwOGEsIDB4ODAwNGEsIDB4OTAwZjUsIDB4NzAxMDMsIDB4ODAwNTYsIDB4ODAwMTYsIDB4ODAxMWUsIDB4NzAxMTMsIDB4ODAwNzYsIDB4ODAwMzYsIDB4OTAwY2QsIDB4NzAxMGIsIDB4ODAwNjYsIDB4ODAwMjYsIDB4OTAwYWQsIDB4ODAwMDYsIDB4ODAwODYsIDB4ODAwNDYsIDB4OTAwZWQsIDB4NzAxMDcsIDB4ODAwNWUsIDB4ODAwMWUsIDB4OTAwOWQsIDB4NzAxMTcsIDB4ODAwN2UsIDB4ODAwM2UsIDB4OTAwZGQsIDB4NzAxMGYsIDB4ODAwNmUsIDB4ODAwMmUsIDB4OTAwYmQsIDB4ODAwMGUsIDB4ODAwOGUsIDB4ODAwNGUsIDB4OTAwZmQsIDB4NzAxMDAsIDB4ODAwNTEsIDB4ODAwMTEsIDB4ODAxMTksIDB4NzAxMTAsIDB4ODAwNzEsIDB4ODAwMzEsIDB4OTAwYzMsIDB4NzAxMDgsIDB4ODAwNjEsIDB4ODAwMjEsIDB4OTAwYTMsIDB4ODAwMDEsIDB4ODAwODEsIDB4ODAwNDEsIDB4OTAwZTMsIDB4NzAxMDQsIDB4ODAwNTksIDB4ODAwMTksIDB4OTAwOTMsIDB4NzAxMTQsIDB4ODAwNzksIDB4ODAwMzksIDB4OTAwZDMsIDB4NzAxMGMsIDB4ODAwNjksIDB4ODAwMjksIDB4OTAwYjMsIDB4ODAwMDksIDB4ODAwODksIDB4ODAwNDksIDB4OTAwZjMsIDB4NzAxMDIsIDB4ODAwNTUsIDB4ODAwMTUsIDB4ODAxMWQsIDB4NzAxMTIsIDB4ODAwNzUsIDB4ODAwMzUsIDB4OTAwY2IsIDB4NzAxMGEsIDB4ODAwNjUsIDB4ODAwMjUsIDB4OTAwYWIsIDB4ODAwMDUsIDB4ODAwODUsIDB4ODAwNDUsIDB4OTAwZWIsIDB4NzAxMDYsIDB4ODAwNWQsIDB4ODAwMWQsIDB4OTAwOWIsIDB4NzAxMTYsIDB4ODAwN2QsIDB4ODAwM2QsIDB4OTAwZGIsIDB4NzAxMGUsIDB4ODAwNmQsIDB4ODAwMmQsIDB4OTAwYmIsIDB4ODAwMGQsIDB4ODAwOGQsIDB4ODAwNGQsIDB4OTAwZmIsIDB4NzAxMDEsIDB4ODAwNTMsIDB4ODAwMTMsIDB4ODAxMWIsIDB4NzAxMTEsIDB4ODAwNzMsIDB4ODAwMzMsIDB4OTAwYzcsIDB4NzAxMDksIDB4ODAwNjMsIDB4ODAwMjMsIDB4OTAwYTcsIDB4ODAwMDMsIDB4ODAwODMsIDB4ODAwNDMsIDB4OTAwZTcsIDB4NzAxMDUsIDB4ODAwNWIsIDB4ODAwMWIsIDB4OTAwOTcsIDB4NzAxMTUsIDB4ODAwN2IsIDB4ODAwM2IsIDB4OTAwZDcsIDB4NzAxMGQsIDB4ODAwNmIsIDB4ODAwMmIsIDB4OTAwYjcsIDB4ODAwMGIsIDB4ODAwOGIsIDB4ODAwNGIsIDB4OTAwZjcsIDB4NzAxMDMsIDB4ODAwNTcsIDB4ODAwMTcsIDB4ODAxMWYsIDB4NzAxMTMsIDB4ODAwNzcsIDB4ODAwMzcsIDB4OTAwY2YsIDB4NzAxMGIsIDB4ODAwNjcsIDB4ODAwMjcsIDB4OTAwYWYsIDB4ODAwMDcsIDB4ODAwODcsIDB4ODAwNDcsIDB4OTAwZWYsIDB4NzAxMDcsIDB4ODAwNWYsIDB4ODAwMWYsIDB4OTAwOWYsIDB4NzAxMTcsIDB4ODAwN2YsIDB4ODAwM2YsIDB4OTAwZGYsIDB4NzAxMGYsIDB4ODAwNmYsIDB4ODAwMmYsIDB4OTAwYmYsIDB4ODAwMGYsIDB4ODAwOGYsIDB4ODAwNGYsIDB4OTAwZmZdKSwgOV07CmNvbnN0IGZpeGVkRGlzdENvZGVUYWIgPSBbbmV3IEludDMyQXJyYXkoWzB4NTAwMDAsIDB4NTAwMTAsIDB4NTAwMDgsIDB4NTAwMTgsIDB4NTAwMDQsIDB4NTAwMTQsIDB4NTAwMGMsIDB4NTAwMWMsIDB4NTAwMDIsIDB4NTAwMTIsIDB4NTAwMGEsIDB4NTAwMWEsIDB4NTAwMDYsIDB4NTAwMTYsIDB4NTAwMGUsIDB4MDAwMDAsIDB4NTAwMDEsIDB4NTAwMTEsIDB4NTAwMDksIDB4NTAwMTksIDB4NTAwMDUsIDB4NTAwMTUsIDB4NTAwMGQsIDB4NTAwMWQsIDB4NTAwMDMsIDB4NTAwMTMsIDB4NTAwMGIsIDB4NTAwMWIsIDB4NTAwMDcsIDB4NTAwMTcsIDB4NTAwMGYsIDB4MDAwMDBdKSwgNV07CmNsYXNzIEZsYXRlU3RyZWFtIGV4dGVuZHMgX2RlY29kZV9zdHJlYW0uRGVjb2RlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHIsIG1heWJlTGVuZ3RoKSB7CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICB0aGlzLnN0ciA9IHN0cjsKICAgIHRoaXMuZGljdCA9IHN0ci5kaWN0OwogICAgY29uc3QgY21mID0gc3RyLmdldEJ5dGUoKTsKICAgIGNvbnN0IGZsZyA9IHN0ci5nZXRCeXRlKCk7CiAgICBpZiAoY21mID09PSAtMSB8fCBmbGcgPT09IC0xKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgSW52YWxpZCBoZWFkZXIgaW4gZmxhdGUgc3RyZWFtOiAke2NtZn0sICR7ZmxnfWApOwogICAgfQogICAgaWYgKChjbWYgJiAweDBmKSAhPT0gMHgwOCkgewogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYFVua25vd24gY29tcHJlc3Npb24gbWV0aG9kIGluIGZsYXRlIHN0cmVhbTogJHtjbWZ9LCAke2ZsZ31gKTsKICAgIH0KICAgIGlmICgoKGNtZiA8PCA4KSArIGZsZykgJSAzMSAhPT0gMCkgewogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYEJhZCBGQ0hFQ0sgaW4gZmxhdGUgc3RyZWFtOiAke2NtZn0sICR7ZmxnfWApOwogICAgfQogICAgaWYgKGZsZyAmIDB4MjApIHsKICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBGRElDVCBiaXQgc2V0IGluIGZsYXRlIHN0cmVhbTogJHtjbWZ9LCAke2ZsZ31gKTsKICAgIH0KICAgIHRoaXMuY29kZVNpemUgPSAwOwogICAgdGhpcy5jb2RlQnVmID0gMDsKICB9CiAgZ2V0Qml0cyhiaXRzKSB7CiAgICBjb25zdCBzdHIgPSB0aGlzLnN0cjsKICAgIGxldCBjb2RlU2l6ZSA9IHRoaXMuY29kZVNpemU7CiAgICBsZXQgY29kZUJ1ZiA9IHRoaXMuY29kZUJ1ZjsKICAgIGxldCBiOwogICAgd2hpbGUgKGNvZGVTaXplIDwgYml0cykgewogICAgICBpZiAoKGIgPSBzdHIuZ2V0Qnl0ZSgpKSA9PT0gLTEpIHsKICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkJhZCBlbmNvZGluZyBpbiBmbGF0ZSBzdHJlYW0iKTsKICAgICAgfQogICAgICBjb2RlQnVmIHw9IGIgPDwgY29kZVNpemU7CiAgICAgIGNvZGVTaXplICs9IDg7CiAgICB9CiAgICBiID0gY29kZUJ1ZiAmICgxIDw8IGJpdHMpIC0gMTsKICAgIHRoaXMuY29kZUJ1ZiA9IGNvZGVCdWYgPj4gYml0czsKICAgIHRoaXMuY29kZVNpemUgPSBjb2RlU2l6ZSAtPSBiaXRzOwogICAgcmV0dXJuIGI7CiAgfQogIGdldENvZGUodGFibGUpIHsKICAgIGNvbnN0IHN0ciA9IHRoaXMuc3RyOwogICAgY29uc3QgY29kZXMgPSB0YWJsZVswXTsKICAgIGNvbnN0IG1heExlbiA9IHRhYmxlWzFdOwogICAgbGV0IGNvZGVTaXplID0gdGhpcy5jb2RlU2l6ZTsKICAgIGxldCBjb2RlQnVmID0gdGhpcy5jb2RlQnVmOwogICAgbGV0IGI7CiAgICB3aGlsZSAoY29kZVNpemUgPCBtYXhMZW4pIHsKICAgICAgaWYgKChiID0gc3RyLmdldEJ5dGUoKSkgPT09IC0xKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY29kZUJ1ZiB8PSBiIDw8IGNvZGVTaXplOwogICAgICBjb2RlU2l6ZSArPSA4OwogICAgfQogICAgY29uc3QgY29kZSA9IGNvZGVzW2NvZGVCdWYgJiAoMSA8PCBtYXhMZW4pIC0gMV07CiAgICBjb25zdCBjb2RlTGVuID0gY29kZSA+PiAxNjsKICAgIGNvbnN0IGNvZGVWYWwgPSBjb2RlICYgMHhmZmZmOwogICAgaWYgKGNvZGVMZW4gPCAxIHx8IGNvZGVTaXplIDwgY29kZUxlbikgewogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkJhZCBlbmNvZGluZyBpbiBmbGF0ZSBzdHJlYW0iKTsKICAgIH0KICAgIHRoaXMuY29kZUJ1ZiA9IGNvZGVCdWYgPj4gY29kZUxlbjsKICAgIHRoaXMuY29kZVNpemUgPSBjb2RlU2l6ZSAtIGNvZGVMZW47CiAgICByZXR1cm4gY29kZVZhbDsKICB9CiAgZ2VuZXJhdGVIdWZmbWFuVGFibGUobGVuZ3RocykgewogICAgY29uc3QgbiA9IGxlbmd0aHMubGVuZ3RoOwogICAgbGV0IG1heExlbiA9IDA7CiAgICBsZXQgaTsKICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHsKICAgICAgaWYgKGxlbmd0aHNbaV0gPiBtYXhMZW4pIHsKICAgICAgICBtYXhMZW4gPSBsZW5ndGhzW2ldOwogICAgICB9CiAgICB9CiAgICBjb25zdCBzaXplID0gMSA8PCBtYXhMZW47CiAgICBjb25zdCBjb2RlcyA9IG5ldyBJbnQzMkFycmF5KHNpemUpOwogICAgZm9yIChsZXQgbGVuID0gMSwgY29kZSA9IDAsIHNraXAgPSAyOyBsZW4gPD0gbWF4TGVuOyArK2xlbiwgY29kZSA8PD0gMSwgc2tpcCA8PD0gMSkgewogICAgICBmb3IgKGxldCB2YWwgPSAwOyB2YWwgPCBuOyArK3ZhbCkgewogICAgICAgIGlmIChsZW5ndGhzW3ZhbF0gPT09IGxlbikgewogICAgICAgICAgbGV0IGNvZGUyID0gMDsKICAgICAgICAgIGxldCB0ID0gY29kZTsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47ICsraSkgewogICAgICAgICAgICBjb2RlMiA9IGNvZGUyIDw8IDEgfCB0ICYgMTsKICAgICAgICAgICAgdCA+Pj0gMTsKICAgICAgICAgIH0KICAgICAgICAgIGZvciAoaSA9IGNvZGUyOyBpIDwgc2l6ZTsgaSArPSBza2lwKSB7CiAgICAgICAgICAgIGNvZGVzW2ldID0gbGVuIDw8IDE2IHwgdmFsOwogICAgICAgICAgfQogICAgICAgICAgKytjb2RlOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIFtjb2RlcywgbWF4TGVuXTsKICB9CiAgcmVhZEJsb2NrKCkgewogICAgbGV0IGJ1ZmZlciwgbGVuOwogICAgY29uc3Qgc3RyID0gdGhpcy5zdHI7CiAgICBsZXQgaGRyID0gdGhpcy5nZXRCaXRzKDMpOwogICAgaWYgKGhkciAmIDEpIHsKICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgfQogICAgaGRyID4+PSAxOwogICAgaWYgKGhkciA9PT0gMCkgewogICAgICBsZXQgYjsKICAgICAgaWYgKChiID0gc3RyLmdldEJ5dGUoKSkgPT09IC0xKSB7CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJCYWQgYmxvY2sgaGVhZGVyIGluIGZsYXRlIHN0cmVhbSIpOwogICAgICB9CiAgICAgIGxldCBibG9ja0xlbiA9IGI7CiAgICAgIGlmICgoYiA9IHN0ci5nZXRCeXRlKCkpID09PSAtMSkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiQmFkIGJsb2NrIGhlYWRlciBpbiBmbGF0ZSBzdHJlYW0iKTsKICAgICAgfQogICAgICBibG9ja0xlbiB8PSBiIDw8IDg7CiAgICAgIGlmICgoYiA9IHN0ci5nZXRCeXRlKCkpID09PSAtMSkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiQmFkIGJsb2NrIGhlYWRlciBpbiBmbGF0ZSBzdHJlYW0iKTsKICAgICAgfQogICAgICBsZXQgY2hlY2sgPSBiOwogICAgICBpZiAoKGIgPSBzdHIuZ2V0Qnl0ZSgpKSA9PT0gLTEpIHsKICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkJhZCBibG9jayBoZWFkZXIgaW4gZmxhdGUgc3RyZWFtIik7CiAgICAgIH0KICAgICAgY2hlY2sgfD0gYiA8PCA4OwogICAgICBpZiAoY2hlY2sgIT09ICh+YmxvY2tMZW4gJiAweGZmZmYpICYmIChibG9ja0xlbiAhPT0gMCB8fCBjaGVjayAhPT0gMCkpIHsKICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkJhZCB1bmNvbXByZXNzZWQgYmxvY2sgbGVuZ3RoIGluIGZsYXRlIHN0cmVhbSIpOwogICAgICB9CiAgICAgIHRoaXMuY29kZUJ1ZiA9IDA7CiAgICAgIHRoaXMuY29kZVNpemUgPSAwOwogICAgICBjb25zdCBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlckxlbmd0aCwKICAgICAgICBlbmQgPSBidWZmZXJMZW5ndGggKyBibG9ja0xlbjsKICAgICAgYnVmZmVyID0gdGhpcy5lbnN1cmVCdWZmZXIoZW5kKTsKICAgICAgdGhpcy5idWZmZXJMZW5ndGggPSBlbmQ7CiAgICAgIGlmIChibG9ja0xlbiA9PT0gMCkgewogICAgICAgIGlmIChzdHIucGVla0J5dGUoKSA9PT0gLTEpIHsKICAgICAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgYmxvY2sgPSBzdHIuZ2V0Qnl0ZXMoYmxvY2tMZW4pOwogICAgICAgIGJ1ZmZlci5zZXQoYmxvY2ssIGJ1ZmZlckxlbmd0aCk7CiAgICAgICAgaWYgKGJsb2NrLmxlbmd0aCA8IGJsb2NrTGVuKSB7CiAgICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KICAgIGxldCBsaXRDb2RlVGFibGU7CiAgICBsZXQgZGlzdENvZGVUYWJsZTsKICAgIGlmIChoZHIgPT09IDEpIHsKICAgICAgbGl0Q29kZVRhYmxlID0gZml4ZWRMaXRDb2RlVGFiOwogICAgICBkaXN0Q29kZVRhYmxlID0gZml4ZWREaXN0Q29kZVRhYjsKICAgIH0gZWxzZSBpZiAoaGRyID09PSAyKSB7CiAgICAgIGNvbnN0IG51bUxpdENvZGVzID0gdGhpcy5nZXRCaXRzKDUpICsgMjU3OwogICAgICBjb25zdCBudW1EaXN0Q29kZXMgPSB0aGlzLmdldEJpdHMoNSkgKyAxOwogICAgICBjb25zdCBudW1Db2RlTGVuQ29kZXMgPSB0aGlzLmdldEJpdHMoNCkgKyA0OwogICAgICBjb25zdCBjb2RlTGVuQ29kZUxlbmd0aHMgPSBuZXcgVWludDhBcnJheShjb2RlTGVuQ29kZU1hcC5sZW5ndGgpOwogICAgICBsZXQgaTsKICAgICAgZm9yIChpID0gMDsgaSA8IG51bUNvZGVMZW5Db2RlczsgKytpKSB7CiAgICAgICAgY29kZUxlbkNvZGVMZW5ndGhzW2NvZGVMZW5Db2RlTWFwW2ldXSA9IHRoaXMuZ2V0Qml0cygzKTsKICAgICAgfQogICAgICBjb25zdCBjb2RlTGVuQ29kZVRhYiA9IHRoaXMuZ2VuZXJhdGVIdWZmbWFuVGFibGUoY29kZUxlbkNvZGVMZW5ndGhzKTsKICAgICAgbGVuID0gMDsKICAgICAgaSA9IDA7CiAgICAgIGNvbnN0IGNvZGVzID0gbnVtTGl0Q29kZXMgKyBudW1EaXN0Q29kZXM7CiAgICAgIGNvbnN0IGNvZGVMZW5ndGhzID0gbmV3IFVpbnQ4QXJyYXkoY29kZXMpOwogICAgICBsZXQgYml0c0xlbmd0aCwgYml0c09mZnNldCwgd2hhdDsKICAgICAgd2hpbGUgKGkgPCBjb2RlcykgewogICAgICAgIGNvbnN0IGNvZGUgPSB0aGlzLmdldENvZGUoY29kZUxlbkNvZGVUYWIpOwogICAgICAgIGlmIChjb2RlID09PSAxNikgewogICAgICAgICAgYml0c0xlbmd0aCA9IDI7CiAgICAgICAgICBiaXRzT2Zmc2V0ID0gMzsKICAgICAgICAgIHdoYXQgPSBsZW47CiAgICAgICAgfSBlbHNlIGlmIChjb2RlID09PSAxNykgewogICAgICAgICAgYml0c0xlbmd0aCA9IDM7CiAgICAgICAgICBiaXRzT2Zmc2V0ID0gMzsKICAgICAgICAgIHdoYXQgPSBsZW4gPSAwOwogICAgICAgIH0gZWxzZSBpZiAoY29kZSA9PT0gMTgpIHsKICAgICAgICAgIGJpdHNMZW5ndGggPSA3OwogICAgICAgICAgYml0c09mZnNldCA9IDExOwogICAgICAgICAgd2hhdCA9IGxlbiA9IDA7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNvZGVMZW5ndGhzW2krK10gPSBsZW4gPSBjb2RlOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGxldCByZXBlYXRMZW5ndGggPSB0aGlzLmdldEJpdHMoYml0c0xlbmd0aCkgKyBiaXRzT2Zmc2V0OwogICAgICAgIHdoaWxlIChyZXBlYXRMZW5ndGgtLSA+IDApIHsKICAgICAgICAgIGNvZGVMZW5ndGhzW2krK10gPSB3aGF0OwogICAgICAgIH0KICAgICAgfQogICAgICBsaXRDb2RlVGFibGUgPSB0aGlzLmdlbmVyYXRlSHVmZm1hblRhYmxlKGNvZGVMZW5ndGhzLnN1YmFycmF5KDAsIG51bUxpdENvZGVzKSk7CiAgICAgIGRpc3RDb2RlVGFibGUgPSB0aGlzLmdlbmVyYXRlSHVmZm1hblRhYmxlKGNvZGVMZW5ndGhzLnN1YmFycmF5KG51bUxpdENvZGVzLCBjb2RlcykpOwogICAgfSBlbHNlIHsKICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJVbmtub3duIGJsb2NrIHR5cGUgaW4gZmxhdGUgc3RyZWFtIik7CiAgICB9CiAgICBidWZmZXIgPSB0aGlzLmJ1ZmZlcjsKICAgIGxldCBsaW1pdCA9IGJ1ZmZlciA/IGJ1ZmZlci5sZW5ndGggOiAwOwogICAgbGV0IHBvcyA9IHRoaXMuYnVmZmVyTGVuZ3RoOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgbGV0IGNvZGUxID0gdGhpcy5nZXRDb2RlKGxpdENvZGVUYWJsZSk7CiAgICAgIGlmIChjb2RlMSA8IDI1NikgewogICAgICAgIGlmIChwb3MgKyAxID49IGxpbWl0KSB7CiAgICAgICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihwb3MgKyAxKTsKICAgICAgICAgIGxpbWl0ID0gYnVmZmVyLmxlbmd0aDsKICAgICAgICB9CiAgICAgICAgYnVmZmVyW3BvcysrXSA9IGNvZGUxOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChjb2RlMSA9PT0gMjU2KSB7CiAgICAgICAgdGhpcy5idWZmZXJMZW5ndGggPSBwb3M7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNvZGUxIC09IDI1NzsKICAgICAgY29kZTEgPSBsZW5ndGhEZWNvZGVbY29kZTFdOwogICAgICBsZXQgY29kZTIgPSBjb2RlMSA+PiAxNjsKICAgICAgaWYgKGNvZGUyID4gMCkgewogICAgICAgIGNvZGUyID0gdGhpcy5nZXRCaXRzKGNvZGUyKTsKICAgICAgfQogICAgICBsZW4gPSAoY29kZTEgJiAweGZmZmYpICsgY29kZTI7CiAgICAgIGNvZGUxID0gdGhpcy5nZXRDb2RlKGRpc3RDb2RlVGFibGUpOwogICAgICBjb2RlMSA9IGRpc3REZWNvZGVbY29kZTFdOwogICAgICBjb2RlMiA9IGNvZGUxID4+IDE2OwogICAgICBpZiAoY29kZTIgPiAwKSB7CiAgICAgICAgY29kZTIgPSB0aGlzLmdldEJpdHMoY29kZTIpOwogICAgICB9CiAgICAgIGNvbnN0IGRpc3QgPSAoY29kZTEgJiAweGZmZmYpICsgY29kZTI7CiAgICAgIGlmIChwb3MgKyBsZW4gPj0gbGltaXQpIHsKICAgICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihwb3MgKyBsZW4pOwogICAgICAgIGxpbWl0ID0gYnVmZmVyLmxlbmd0aDsKICAgICAgfQogICAgICBmb3IgKGxldCBrID0gMDsgayA8IGxlbjsgKytrLCArK3BvcykgewogICAgICAgIGJ1ZmZlcltwb3NdID0gYnVmZmVyW3BvcyAtIGRpc3RdOwogICAgICB9CiAgICB9CiAgfQp9CmV4cG9ydHMuRmxhdGVTdHJlYW0gPSBGbGF0ZVN0cmVhbTsKCi8qKiovIH0pLAovKiAxNTggKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLkpiaWcyU3RyZWFtID0gdm9pZCAwOwp2YXIgX2Jhc2Vfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDEpOwp2YXIgX2RlY29kZV9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1Myk7CnZhciBfcHJpbWl0aXZlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQwKTsKdmFyIF9qYmlnID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTkpOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpjbGFzcyBKYmlnMlN0cmVhbSBleHRlbmRzIF9kZWNvZGVfc3RyZWFtLkRlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyZWFtLCBtYXliZUxlbmd0aCwgcGFyYW1zKSB7CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTsKICAgIHRoaXMuZGljdCA9IHN0cmVhbS5kaWN0OwogICAgdGhpcy5tYXliZUxlbmd0aCA9IG1heWJlTGVuZ3RoOwogICAgdGhpcy5wYXJhbXMgPSBwYXJhbXM7CiAgfQogIGdldCBieXRlcygpIHsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiYnl0ZXMiLCB0aGlzLnN0cmVhbS5nZXRCeXRlcyh0aGlzLm1heWJlTGVuZ3RoKSk7CiAgfQogIGVuc3VyZUJ1ZmZlcihyZXF1ZXN0ZWQpIHt9CiAgcmVhZEJsb2NrKCkgewogICAgaWYgKHRoaXMuZW9mKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGpiaWcySW1hZ2UgPSBuZXcgX2piaWcuSmJpZzJJbWFnZSgpOwogICAgY29uc3QgY2h1bmtzID0gW107CiAgICBpZiAodGhpcy5wYXJhbXMgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgIGNvbnN0IGdsb2JhbHNTdHJlYW0gPSB0aGlzLnBhcmFtcy5nZXQoIkpCSUcyR2xvYmFscyIpOwogICAgICBpZiAoZ2xvYmFsc1N0cmVhbSBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSB7CiAgICAgICAgY29uc3QgZ2xvYmFscyA9IGdsb2JhbHNTdHJlYW0uZ2V0Qnl0ZXMoKTsKICAgICAgICBjaHVua3MucHVzaCh7CiAgICAgICAgICBkYXRhOiBnbG9iYWxzLAogICAgICAgICAgc3RhcnQ6IDAsCiAgICAgICAgICBlbmQ6IGdsb2JhbHMubGVuZ3RoCiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIGNodW5rcy5wdXNoKHsKICAgICAgZGF0YTogdGhpcy5ieXRlcywKICAgICAgc3RhcnQ6IDAsCiAgICAgIGVuZDogdGhpcy5ieXRlcy5sZW5ndGgKICAgIH0pOwogICAgY29uc3QgZGF0YSA9IGpiaWcySW1hZ2UucGFyc2VDaHVua3MoY2h1bmtzKTsKICAgIGNvbnN0IGRhdGFMZW5ndGggPSBkYXRhLmxlbmd0aDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YUxlbmd0aDsgaSsrKSB7CiAgICAgIGRhdGFbaV0gXj0gMHhmZjsKICAgIH0KICAgIHRoaXMuYnVmZmVyID0gZGF0YTsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gZGF0YUxlbmd0aDsKICAgIHRoaXMuZW9mID0gdHJ1ZTsKICB9Cn0KZXhwb3J0cy5KYmlnMlN0cmVhbSA9IEpiaWcyU3RyZWFtOwoKLyoqKi8gfSksCi8qIDE1OSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuSmJpZzJJbWFnZSA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX2FyaXRobWV0aWNfZGVjb2RlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTYwKTsKdmFyIF9jY2l0dCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTU2KTsKY2xhc3MgSmJpZzJFcnJvciBleHRlbmRzIF91dGlsLkJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZykgewogICAgc3VwZXIoYEpCSUcyIGVycm9yOiAke21zZ31gLCAiSmJpZzJFcnJvciIpOwogIH0KfQpjbGFzcyBDb250ZXh0Q2FjaGUgewogIGdldENvbnRleHRzKGlkKSB7CiAgICBpZiAoaWQgaW4gdGhpcykgewogICAgICByZXR1cm4gdGhpc1tpZF07CiAgICB9CiAgICByZXR1cm4gdGhpc1tpZF0gPSBuZXcgSW50OEFycmF5KDEgPDwgMTYpOwogIH0KfQpjbGFzcyBEZWNvZGluZ0NvbnRleHQgewogIGNvbnN0cnVjdG9yKGRhdGEsIHN0YXJ0LCBlbmQpIHsKICAgIHRoaXMuZGF0YSA9IGRhdGE7CiAgICB0aGlzLnN0YXJ0ID0gc3RhcnQ7CiAgICB0aGlzLmVuZCA9IGVuZDsKICB9CiAgZ2V0IGRlY29kZXIoKSB7CiAgICBjb25zdCBkZWNvZGVyID0gbmV3IF9hcml0aG1ldGljX2RlY29kZXIuQXJpdGhtZXRpY0RlY29kZXIodGhpcy5kYXRhLCB0aGlzLnN0YXJ0LCB0aGlzLmVuZCk7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImRlY29kZXIiLCBkZWNvZGVyKTsKICB9CiAgZ2V0IGNvbnRleHRDYWNoZSgpIHsKICAgIGNvbnN0IGNhY2hlID0gbmV3IENvbnRleHRDYWNoZSgpOwogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJjb250ZXh0Q2FjaGUiLCBjYWNoZSk7CiAgfQp9CmNvbnN0IE1BWF9JTlRfMzIgPSAyICoqIDMxIC0gMTsKY29uc3QgTUlOX0lOVF8zMiA9IC0oMiAqKiAzMSk7CmZ1bmN0aW9uIGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCBwcm9jZWR1cmUsIGRlY29kZXIpIHsKICBjb25zdCBjb250ZXh0cyA9IGNvbnRleHRDYWNoZS5nZXRDb250ZXh0cyhwcm9jZWR1cmUpOwogIGxldCBwcmV2ID0gMTsKICBmdW5jdGlvbiByZWFkQml0cyhsZW5ndGgpIHsKICAgIGxldCB2ID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgY29uc3QgYml0ID0gZGVjb2Rlci5yZWFkQml0KGNvbnRleHRzLCBwcmV2KTsKICAgICAgcHJldiA9IHByZXYgPCAyNTYgPyBwcmV2IDw8IDEgfCBiaXQgOiAocHJldiA8PCAxIHwgYml0KSAmIDUxMSB8IDI1NjsKICAgICAgdiA9IHYgPDwgMSB8IGJpdDsKICAgIH0KICAgIHJldHVybiB2ID4+PiAwOwogIH0KICBjb25zdCBzaWduID0gcmVhZEJpdHMoMSk7CiAgY29uc3QgdmFsdWUgPSByZWFkQml0cygxKSA/IHJlYWRCaXRzKDEpID8gcmVhZEJpdHMoMSkgPyByZWFkQml0cygxKSA/IHJlYWRCaXRzKDEpID8gcmVhZEJpdHMoMzIpICsgNDQzNiA6IHJlYWRCaXRzKDEyKSArIDM0MCA6IHJlYWRCaXRzKDgpICsgODQgOiByZWFkQml0cyg2KSArIDIwIDogcmVhZEJpdHMoNCkgKyA0IDogcmVhZEJpdHMoMik7CiAgbGV0IHNpZ25lZFZhbHVlOwogIGlmIChzaWduID09PSAwKSB7CiAgICBzaWduZWRWYWx1ZSA9IHZhbHVlOwogIH0gZWxzZSBpZiAodmFsdWUgPiAwKSB7CiAgICBzaWduZWRWYWx1ZSA9IC12YWx1ZTsKICB9CiAgaWYgKHNpZ25lZFZhbHVlID49IE1JTl9JTlRfMzIgJiYgc2lnbmVkVmFsdWUgPD0gTUFYX0lOVF8zMikgewogICAgcmV0dXJuIHNpZ25lZFZhbHVlOwogIH0KICByZXR1cm4gbnVsbDsKfQpmdW5jdGlvbiBkZWNvZGVJQUlEKGNvbnRleHRDYWNoZSwgZGVjb2RlciwgY29kZUxlbmd0aCkgewogIGNvbnN0IGNvbnRleHRzID0gY29udGV4dENhY2hlLmdldENvbnRleHRzKCJJQUlEIik7CiAgbGV0IHByZXYgPSAxOwogIGZvciAobGV0IGkgPSAwOyBpIDwgY29kZUxlbmd0aDsgaSsrKSB7CiAgICBjb25zdCBiaXQgPSBkZWNvZGVyLnJlYWRCaXQoY29udGV4dHMsIHByZXYpOwogICAgcHJldiA9IHByZXYgPDwgMSB8IGJpdDsKICB9CiAgaWYgKGNvZGVMZW5ndGggPCAzMSkgewogICAgcmV0dXJuIHByZXYgJiAoMSA8PCBjb2RlTGVuZ3RoKSAtIDE7CiAgfQogIHJldHVybiBwcmV2ICYgMHg3ZmZmZmZmZjsKfQpjb25zdCBTZWdtZW50VHlwZXMgPSBbIlN5bWJvbERpY3Rpb25hcnkiLCBudWxsLCBudWxsLCBudWxsLCAiSW50ZXJtZWRpYXRlVGV4dFJlZ2lvbiIsIG51bGwsICJJbW1lZGlhdGVUZXh0UmVnaW9uIiwgIkltbWVkaWF0ZUxvc3NsZXNzVGV4dFJlZ2lvbiIsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsICJQYXR0ZXJuRGljdGlvbmFyeSIsIG51bGwsIG51bGwsIG51bGwsICJJbnRlcm1lZGlhdGVIYWxmdG9uZVJlZ2lvbiIsIG51bGwsICJJbW1lZGlhdGVIYWxmdG9uZVJlZ2lvbiIsICJJbW1lZGlhdGVMb3NzbGVzc0hhbGZ0b25lUmVnaW9uIiwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgIkludGVybWVkaWF0ZUdlbmVyaWNSZWdpb24iLCBudWxsLCAiSW1tZWRpYXRlR2VuZXJpY1JlZ2lvbiIsICJJbW1lZGlhdGVMb3NzbGVzc0dlbmVyaWNSZWdpb24iLCAiSW50ZXJtZWRpYXRlR2VuZXJpY1JlZmluZW1lbnRSZWdpb24iLCBudWxsLCAiSW1tZWRpYXRlR2VuZXJpY1JlZmluZW1lbnRSZWdpb24iLCAiSW1tZWRpYXRlTG9zc2xlc3NHZW5lcmljUmVmaW5lbWVudFJlZ2lvbiIsIG51bGwsIG51bGwsIG51bGwsIG51bGwsICJQYWdlSW5mb3JtYXRpb24iLCAiRW5kT2ZQYWdlIiwgIkVuZE9mU3RyaXBlIiwgIkVuZE9mRmlsZSIsICJQcm9maWxlcyIsICJUYWJsZXMiLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCAiRXh0ZW5zaW9uIl07CmNvbnN0IENvZGluZ1RlbXBsYXRlcyA9IFtbewogIHg6IC0xLAogIHk6IC0yCn0sIHsKICB4OiAwLAogIHk6IC0yCn0sIHsKICB4OiAxLAogIHk6IC0yCn0sIHsKICB4OiAtMiwKICB5OiAtMQp9LCB7CiAgeDogLTEsCiAgeTogLTEKfSwgewogIHg6IDAsCiAgeTogLTEKfSwgewogIHg6IDEsCiAgeTogLTEKfSwgewogIHg6IDIsCiAgeTogLTEKfSwgewogIHg6IC00LAogIHk6IDAKfSwgewogIHg6IC0zLAogIHk6IDAKfSwgewogIHg6IC0yLAogIHk6IDAKfSwgewogIHg6IC0xLAogIHk6IDAKfV0sIFt7CiAgeDogLTEsCiAgeTogLTIKfSwgewogIHg6IDAsCiAgeTogLTIKfSwgewogIHg6IDEsCiAgeTogLTIKfSwgewogIHg6IDIsCiAgeTogLTIKfSwgewogIHg6IC0yLAogIHk6IC0xCn0sIHsKICB4OiAtMSwKICB5OiAtMQp9LCB7CiAgeDogMCwKICB5OiAtMQp9LCB7CiAgeDogMSwKICB5OiAtMQp9LCB7CiAgeDogMiwKICB5OiAtMQp9LCB7CiAgeDogLTMsCiAgeTogMAp9LCB7CiAgeDogLTIsCiAgeTogMAp9LCB7CiAgeDogLTEsCiAgeTogMAp9XSwgW3sKICB4OiAtMSwKICB5OiAtMgp9LCB7CiAgeDogMCwKICB5OiAtMgp9LCB7CiAgeDogMSwKICB5OiAtMgp9LCB7CiAgeDogLTIsCiAgeTogLTEKfSwgewogIHg6IC0xLAogIHk6IC0xCn0sIHsKICB4OiAwLAogIHk6IC0xCn0sIHsKICB4OiAxLAogIHk6IC0xCn0sIHsKICB4OiAtMiwKICB5OiAwCn0sIHsKICB4OiAtMSwKICB5OiAwCn1dLCBbewogIHg6IC0zLAogIHk6IC0xCn0sIHsKICB4OiAtMiwKICB5OiAtMQp9LCB7CiAgeDogLTEsCiAgeTogLTEKfSwgewogIHg6IDAsCiAgeTogLTEKfSwgewogIHg6IDEsCiAgeTogLTEKfSwgewogIHg6IC00LAogIHk6IDAKfSwgewogIHg6IC0zLAogIHk6IDAKfSwgewogIHg6IC0yLAogIHk6IDAKfSwgewogIHg6IC0xLAogIHk6IDAKfV1dOwpjb25zdCBSZWZpbmVtZW50VGVtcGxhdGVzID0gW3sKICBjb2Rpbmc6IFt7CiAgICB4OiAwLAogICAgeTogLTEKICB9LCB7CiAgICB4OiAxLAogICAgeTogLTEKICB9LCB7CiAgICB4OiAtMSwKICAgIHk6IDAKICB9XSwKICByZWZlcmVuY2U6IFt7CiAgICB4OiAwLAogICAgeTogLTEKICB9LCB7CiAgICB4OiAxLAogICAgeTogLTEKICB9LCB7CiAgICB4OiAtMSwKICAgIHk6IDAKICB9LCB7CiAgICB4OiAwLAogICAgeTogMAogIH0sIHsKICAgIHg6IDEsCiAgICB5OiAwCiAgfSwgewogICAgeDogLTEsCiAgICB5OiAxCiAgfSwgewogICAgeDogMCwKICAgIHk6IDEKICB9LCB7CiAgICB4OiAxLAogICAgeTogMQogIH1dCn0sIHsKICBjb2Rpbmc6IFt7CiAgICB4OiAtMSwKICAgIHk6IC0xCiAgfSwgewogICAgeDogMCwKICAgIHk6IC0xCiAgfSwgewogICAgeDogMSwKICAgIHk6IC0xCiAgfSwgewogICAgeDogLTEsCiAgICB5OiAwCiAgfV0sCiAgcmVmZXJlbmNlOiBbewogICAgeDogMCwKICAgIHk6IC0xCiAgfSwgewogICAgeDogLTEsCiAgICB5OiAwCiAgfSwgewogICAgeDogMCwKICAgIHk6IDAKICB9LCB7CiAgICB4OiAxLAogICAgeTogMAogIH0sIHsKICAgIHg6IDAsCiAgICB5OiAxCiAgfSwgewogICAgeDogMSwKICAgIHk6IDEKICB9XQp9XTsKY29uc3QgUmV1c2VkQ29udGV4dHMgPSBbMHg5YjI1LCAweDA3OTUsIDB4MDBlNSwgMHgwMTk1XTsKY29uc3QgUmVmaW5lbWVudFJldXNlZENvbnRleHRzID0gWzB4MDAyMCwgMHgwMDA4XTsKZnVuY3Rpb24gZGVjb2RlQml0bWFwVGVtcGxhdGUwKHdpZHRoLCBoZWlnaHQsIGRlY29kaW5nQ29udGV4dCkgewogIGNvbnN0IGRlY29kZXIgPSBkZWNvZGluZ0NvbnRleHQuZGVjb2RlcjsKICBjb25zdCBjb250ZXh0cyA9IGRlY29kaW5nQ29udGV4dC5jb250ZXh0Q2FjaGUuZ2V0Q29udGV4dHMoIkdCIik7CiAgY29uc3QgYml0bWFwID0gW107CiAgbGV0IGNvbnRleHRMYWJlbCwgaSwgaiwgcGl4ZWwsIHJvdywgcm93MSwgcm93MjsKICBjb25zdCBPTERfUElYRUxfTUFTSyA9IDB4N2JmNzsKICBmb3IgKGkgPSAwOyBpIDwgaGVpZ2h0OyBpKyspIHsKICAgIHJvdyA9IGJpdG1hcFtpXSA9IG5ldyBVaW50OEFycmF5KHdpZHRoKTsKICAgIHJvdzEgPSBpIDwgMSA/IHJvdyA6IGJpdG1hcFtpIC0gMV07CiAgICByb3cyID0gaSA8IDIgPyByb3cgOiBiaXRtYXBbaSAtIDJdOwogICAgY29udGV4dExhYmVsID0gcm93MlswXSA8PCAxMyB8IHJvdzJbMV0gPDwgMTIgfCByb3cyWzJdIDw8IDExIHwgcm93MVswXSA8PCA3IHwgcm93MVsxXSA8PCA2IHwgcm93MVsyXSA8PCA1IHwgcm93MVszXSA8PCA0OwogICAgZm9yIChqID0gMDsgaiA8IHdpZHRoOyBqKyspIHsKICAgICAgcm93W2pdID0gcGl4ZWwgPSBkZWNvZGVyLnJlYWRCaXQoY29udGV4dHMsIGNvbnRleHRMYWJlbCk7CiAgICAgIGNvbnRleHRMYWJlbCA9IChjb250ZXh0TGFiZWwgJiBPTERfUElYRUxfTUFTSykgPDwgMSB8IChqICsgMyA8IHdpZHRoID8gcm93MltqICsgM10gPDwgMTEgOiAwKSB8IChqICsgNCA8IHdpZHRoID8gcm93MVtqICsgNF0gPDwgNCA6IDApIHwgcGl4ZWw7CiAgICB9CiAgfQogIHJldHVybiBiaXRtYXA7Cn0KZnVuY3Rpb24gZGVjb2RlQml0bWFwKG1tciwgd2lkdGgsIGhlaWdodCwgdGVtcGxhdGVJbmRleCwgcHJlZGljdGlvbiwgc2tpcCwgYXQsIGRlY29kaW5nQ29udGV4dCkgewogIGlmIChtbXIpIHsKICAgIGNvbnN0IGlucHV0ID0gbmV3IFJlYWRlcihkZWNvZGluZ0NvbnRleHQuZGF0YSwgZGVjb2RpbmdDb250ZXh0LnN0YXJ0LCBkZWNvZGluZ0NvbnRleHQuZW5kKTsKICAgIHJldHVybiBkZWNvZGVNTVJCaXRtYXAoaW5wdXQsIHdpZHRoLCBoZWlnaHQsIGZhbHNlKTsKICB9CiAgaWYgKHRlbXBsYXRlSW5kZXggPT09IDAgJiYgIXNraXAgJiYgIXByZWRpY3Rpb24gJiYgYXQubGVuZ3RoID09PSA0ICYmIGF0WzBdLnggPT09IDMgJiYgYXRbMF0ueSA9PT0gLTEgJiYgYXRbMV0ueCA9PT0gLTMgJiYgYXRbMV0ueSA9PT0gLTEgJiYgYXRbMl0ueCA9PT0gMiAmJiBhdFsyXS55ID09PSAtMiAmJiBhdFszXS54ID09PSAtMiAmJiBhdFszXS55ID09PSAtMikgewogICAgcmV0dXJuIGRlY29kZUJpdG1hcFRlbXBsYXRlMCh3aWR0aCwgaGVpZ2h0LCBkZWNvZGluZ0NvbnRleHQpOwogIH0KICBjb25zdCB1c2Vza2lwID0gISFza2lwOwogIGNvbnN0IHRlbXBsYXRlID0gQ29kaW5nVGVtcGxhdGVzW3RlbXBsYXRlSW5kZXhdLmNvbmNhdChhdCk7CiAgdGVtcGxhdGUuc29ydChmdW5jdGlvbiAoYSwgYikgewogICAgcmV0dXJuIGEueSAtIGIueSB8fCBhLnggLSBiLng7CiAgfSk7CiAgY29uc3QgdGVtcGxhdGVMZW5ndGggPSB0ZW1wbGF0ZS5sZW5ndGg7CiAgY29uc3QgdGVtcGxhdGVYID0gbmV3IEludDhBcnJheSh0ZW1wbGF0ZUxlbmd0aCk7CiAgY29uc3QgdGVtcGxhdGVZID0gbmV3IEludDhBcnJheSh0ZW1wbGF0ZUxlbmd0aCk7CiAgY29uc3QgY2hhbmdpbmdUZW1wbGF0ZUVudHJpZXMgPSBbXTsKICBsZXQgcmV1c2VNYXNrID0gMCwKICAgIG1pblggPSAwLAogICAgbWF4WCA9IDAsCiAgICBtaW5ZID0gMDsKICBsZXQgYywgazsKICBmb3IgKGsgPSAwOyBrIDwgdGVtcGxhdGVMZW5ndGg7IGsrKykgewogICAgdGVtcGxhdGVYW2tdID0gdGVtcGxhdGVba10ueDsKICAgIHRlbXBsYXRlWVtrXSA9IHRlbXBsYXRlW2tdLnk7CiAgICBtaW5YID0gTWF0aC5taW4obWluWCwgdGVtcGxhdGVba10ueCk7CiAgICBtYXhYID0gTWF0aC5tYXgobWF4WCwgdGVtcGxhdGVba10ueCk7CiAgICBtaW5ZID0gTWF0aC5taW4obWluWSwgdGVtcGxhdGVba10ueSk7CiAgICBpZiAoayA8IHRlbXBsYXRlTGVuZ3RoIC0gMSAmJiB0ZW1wbGF0ZVtrXS55ID09PSB0ZW1wbGF0ZVtrICsgMV0ueSAmJiB0ZW1wbGF0ZVtrXS54ID09PSB0ZW1wbGF0ZVtrICsgMV0ueCAtIDEpIHsKICAgICAgcmV1c2VNYXNrIHw9IDEgPDwgdGVtcGxhdGVMZW5ndGggLSAxIC0gazsKICAgIH0gZWxzZSB7CiAgICAgIGNoYW5naW5nVGVtcGxhdGVFbnRyaWVzLnB1c2goayk7CiAgICB9CiAgfQogIGNvbnN0IGNoYW5naW5nRW50cmllc0xlbmd0aCA9IGNoYW5naW5nVGVtcGxhdGVFbnRyaWVzLmxlbmd0aDsKICBjb25zdCBjaGFuZ2luZ1RlbXBsYXRlWCA9IG5ldyBJbnQ4QXJyYXkoY2hhbmdpbmdFbnRyaWVzTGVuZ3RoKTsKICBjb25zdCBjaGFuZ2luZ1RlbXBsYXRlWSA9IG5ldyBJbnQ4QXJyYXkoY2hhbmdpbmdFbnRyaWVzTGVuZ3RoKTsKICBjb25zdCBjaGFuZ2luZ1RlbXBsYXRlQml0ID0gbmV3IFVpbnQxNkFycmF5KGNoYW5naW5nRW50cmllc0xlbmd0aCk7CiAgZm9yIChjID0gMDsgYyA8IGNoYW5naW5nRW50cmllc0xlbmd0aDsgYysrKSB7CiAgICBrID0gY2hhbmdpbmdUZW1wbGF0ZUVudHJpZXNbY107CiAgICBjaGFuZ2luZ1RlbXBsYXRlWFtjXSA9IHRlbXBsYXRlW2tdLng7CiAgICBjaGFuZ2luZ1RlbXBsYXRlWVtjXSA9IHRlbXBsYXRlW2tdLnk7CiAgICBjaGFuZ2luZ1RlbXBsYXRlQml0W2NdID0gMSA8PCB0ZW1wbGF0ZUxlbmd0aCAtIDEgLSBrOwogIH0KICBjb25zdCBzYmJfbGVmdCA9IC1taW5YOwogIGNvbnN0IHNiYl90b3AgPSAtbWluWTsKICBjb25zdCBzYmJfcmlnaHQgPSB3aWR0aCAtIG1heFg7CiAgY29uc3QgcHNldWRvUGl4ZWxDb250ZXh0ID0gUmV1c2VkQ29udGV4dHNbdGVtcGxhdGVJbmRleF07CiAgbGV0IHJvdyA9IG5ldyBVaW50OEFycmF5KHdpZHRoKTsKICBjb25zdCBiaXRtYXAgPSBbXTsKICBjb25zdCBkZWNvZGVyID0gZGVjb2RpbmdDb250ZXh0LmRlY29kZXI7CiAgY29uc3QgY29udGV4dHMgPSBkZWNvZGluZ0NvbnRleHQuY29udGV4dENhY2hlLmdldENvbnRleHRzKCJHQiIpOwogIGxldCBsdHAgPSAwLAogICAgaiwKICAgIGkwLAogICAgajAsCiAgICBjb250ZXh0TGFiZWwgPSAwLAogICAgYml0LAogICAgc2hpZnQ7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCBoZWlnaHQ7IGkrKykgewogICAgaWYgKHByZWRpY3Rpb24pIHsKICAgICAgY29uc3Qgc2x0cCA9IGRlY29kZXIucmVhZEJpdChjb250ZXh0cywgcHNldWRvUGl4ZWxDb250ZXh0KTsKICAgICAgbHRwIF49IHNsdHA7CiAgICAgIGlmIChsdHApIHsKICAgICAgICBiaXRtYXAucHVzaChyb3cpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICB9CiAgICByb3cgPSBuZXcgVWludDhBcnJheShyb3cpOwogICAgYml0bWFwLnB1c2gocm93KTsKICAgIGZvciAoaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7CiAgICAgIGlmICh1c2Vza2lwICYmIHNraXBbaV1bal0pIHsKICAgICAgICByb3dbal0gPSAwOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChqID49IHNiYl9sZWZ0ICYmIGogPCBzYmJfcmlnaHQgJiYgaSA+PSBzYmJfdG9wKSB7CiAgICAgICAgY29udGV4dExhYmVsID0gY29udGV4dExhYmVsIDw8IDEgJiByZXVzZU1hc2s7CiAgICAgICAgZm9yIChrID0gMDsgayA8IGNoYW5naW5nRW50cmllc0xlbmd0aDsgaysrKSB7CiAgICAgICAgICBpMCA9IGkgKyBjaGFuZ2luZ1RlbXBsYXRlWVtrXTsKICAgICAgICAgIGowID0gaiArIGNoYW5naW5nVGVtcGxhdGVYW2tdOwogICAgICAgICAgYml0ID0gYml0bWFwW2kwXVtqMF07CiAgICAgICAgICBpZiAoYml0KSB7CiAgICAgICAgICAgIGJpdCA9IGNoYW5naW5nVGVtcGxhdGVCaXRba107CiAgICAgICAgICAgIGNvbnRleHRMYWJlbCB8PSBiaXQ7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGNvbnRleHRMYWJlbCA9IDA7CiAgICAgICAgc2hpZnQgPSB0ZW1wbGF0ZUxlbmd0aCAtIDE7CiAgICAgICAgZm9yIChrID0gMDsgayA8IHRlbXBsYXRlTGVuZ3RoOyBrKyssIHNoaWZ0LS0pIHsKICAgICAgICAgIGowID0gaiArIHRlbXBsYXRlWFtrXTsKICAgICAgICAgIGlmIChqMCA+PSAwICYmIGowIDwgd2lkdGgpIHsKICAgICAgICAgICAgaTAgPSBpICsgdGVtcGxhdGVZW2tdOwogICAgICAgICAgICBpZiAoaTAgPj0gMCkgewogICAgICAgICAgICAgIGJpdCA9IGJpdG1hcFtpMF1bajBdOwogICAgICAgICAgICAgIGlmIChiaXQpIHsKICAgICAgICAgICAgICAgIGNvbnRleHRMYWJlbCB8PSBiaXQgPDwgc2hpZnQ7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGNvbnN0IHBpeGVsID0gZGVjb2Rlci5yZWFkQml0KGNvbnRleHRzLCBjb250ZXh0TGFiZWwpOwogICAgICByb3dbal0gPSBwaXhlbDsKICAgIH0KICB9CiAgcmV0dXJuIGJpdG1hcDsKfQpmdW5jdGlvbiBkZWNvZGVSZWZpbmVtZW50KHdpZHRoLCBoZWlnaHQsIHRlbXBsYXRlSW5kZXgsIHJlZmVyZW5jZUJpdG1hcCwgb2Zmc2V0WCwgb2Zmc2V0WSwgcHJlZGljdGlvbiwgYXQsIGRlY29kaW5nQ29udGV4dCkgewogIGxldCBjb2RpbmdUZW1wbGF0ZSA9IFJlZmluZW1lbnRUZW1wbGF0ZXNbdGVtcGxhdGVJbmRleF0uY29kaW5nOwogIGlmICh0ZW1wbGF0ZUluZGV4ID09PSAwKSB7CiAgICBjb2RpbmdUZW1wbGF0ZSA9IGNvZGluZ1RlbXBsYXRlLmNvbmNhdChbYXRbMF1dKTsKICB9CiAgY29uc3QgY29kaW5nVGVtcGxhdGVMZW5ndGggPSBjb2RpbmdUZW1wbGF0ZS5sZW5ndGg7CiAgY29uc3QgY29kaW5nVGVtcGxhdGVYID0gbmV3IEludDMyQXJyYXkoY29kaW5nVGVtcGxhdGVMZW5ndGgpOwogIGNvbnN0IGNvZGluZ1RlbXBsYXRlWSA9IG5ldyBJbnQzMkFycmF5KGNvZGluZ1RlbXBsYXRlTGVuZ3RoKTsKICBsZXQgazsKICBmb3IgKGsgPSAwOyBrIDwgY29kaW5nVGVtcGxhdGVMZW5ndGg7IGsrKykgewogICAgY29kaW5nVGVtcGxhdGVYW2tdID0gY29kaW5nVGVtcGxhdGVba10ueDsKICAgIGNvZGluZ1RlbXBsYXRlWVtrXSA9IGNvZGluZ1RlbXBsYXRlW2tdLnk7CiAgfQogIGxldCByZWZlcmVuY2VUZW1wbGF0ZSA9IFJlZmluZW1lbnRUZW1wbGF0ZXNbdGVtcGxhdGVJbmRleF0ucmVmZXJlbmNlOwogIGlmICh0ZW1wbGF0ZUluZGV4ID09PSAwKSB7CiAgICByZWZlcmVuY2VUZW1wbGF0ZSA9IHJlZmVyZW5jZVRlbXBsYXRlLmNvbmNhdChbYXRbMV1dKTsKICB9CiAgY29uc3QgcmVmZXJlbmNlVGVtcGxhdGVMZW5ndGggPSByZWZlcmVuY2VUZW1wbGF0ZS5sZW5ndGg7CiAgY29uc3QgcmVmZXJlbmNlVGVtcGxhdGVYID0gbmV3IEludDMyQXJyYXkocmVmZXJlbmNlVGVtcGxhdGVMZW5ndGgpOwogIGNvbnN0IHJlZmVyZW5jZVRlbXBsYXRlWSA9IG5ldyBJbnQzMkFycmF5KHJlZmVyZW5jZVRlbXBsYXRlTGVuZ3RoKTsKICBmb3IgKGsgPSAwOyBrIDwgcmVmZXJlbmNlVGVtcGxhdGVMZW5ndGg7IGsrKykgewogICAgcmVmZXJlbmNlVGVtcGxhdGVYW2tdID0gcmVmZXJlbmNlVGVtcGxhdGVba10ueDsKICAgIHJlZmVyZW5jZVRlbXBsYXRlWVtrXSA9IHJlZmVyZW5jZVRlbXBsYXRlW2tdLnk7CiAgfQogIGNvbnN0IHJlZmVyZW5jZVdpZHRoID0gcmVmZXJlbmNlQml0bWFwWzBdLmxlbmd0aDsKICBjb25zdCByZWZlcmVuY2VIZWlnaHQgPSByZWZlcmVuY2VCaXRtYXAubGVuZ3RoOwogIGNvbnN0IHBzZXVkb1BpeGVsQ29udGV4dCA9IFJlZmluZW1lbnRSZXVzZWRDb250ZXh0c1t0ZW1wbGF0ZUluZGV4XTsKICBjb25zdCBiaXRtYXAgPSBbXTsKICBjb25zdCBkZWNvZGVyID0gZGVjb2RpbmdDb250ZXh0LmRlY29kZXI7CiAgY29uc3QgY29udGV4dHMgPSBkZWNvZGluZ0NvbnRleHQuY29udGV4dENhY2hlLmdldENvbnRleHRzKCJHUiIpOwogIGxldCBsdHAgPSAwOwogIGZvciAobGV0IGkgPSAwOyBpIDwgaGVpZ2h0OyBpKyspIHsKICAgIGlmIChwcmVkaWN0aW9uKSB7CiAgICAgIGNvbnN0IHNsdHAgPSBkZWNvZGVyLnJlYWRCaXQoY29udGV4dHMsIHBzZXVkb1BpeGVsQ29udGV4dCk7CiAgICAgIGx0cCBePSBzbHRwOwogICAgICBpZiAobHRwKSB7CiAgICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoInByZWRpY3Rpb24gaXMgbm90IHN1cHBvcnRlZCIpOwogICAgICB9CiAgICB9CiAgICBjb25zdCByb3cgPSBuZXcgVWludDhBcnJheSh3aWR0aCk7CiAgICBiaXRtYXAucHVzaChyb3cpOwogICAgZm9yIChsZXQgaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7CiAgICAgIGxldCBpMCwgajA7CiAgICAgIGxldCBjb250ZXh0TGFiZWwgPSAwOwogICAgICBmb3IgKGsgPSAwOyBrIDwgY29kaW5nVGVtcGxhdGVMZW5ndGg7IGsrKykgewogICAgICAgIGkwID0gaSArIGNvZGluZ1RlbXBsYXRlWVtrXTsKICAgICAgICBqMCA9IGogKyBjb2RpbmdUZW1wbGF0ZVhba107CiAgICAgICAgaWYgKGkwIDwgMCB8fCBqMCA8IDAgfHwgajAgPj0gd2lkdGgpIHsKICAgICAgICAgIGNvbnRleHRMYWJlbCA8PD0gMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29udGV4dExhYmVsID0gY29udGV4dExhYmVsIDw8IDEgfCBiaXRtYXBbaTBdW2owXTsKICAgICAgICB9CiAgICAgIH0KICAgICAgZm9yIChrID0gMDsgayA8IHJlZmVyZW5jZVRlbXBsYXRlTGVuZ3RoOyBrKyspIHsKICAgICAgICBpMCA9IGkgKyByZWZlcmVuY2VUZW1wbGF0ZVlba10gLSBvZmZzZXRZOwogICAgICAgIGowID0gaiArIHJlZmVyZW5jZVRlbXBsYXRlWFtrXSAtIG9mZnNldFg7CiAgICAgICAgaWYgKGkwIDwgMCB8fCBpMCA+PSByZWZlcmVuY2VIZWlnaHQgfHwgajAgPCAwIHx8IGowID49IHJlZmVyZW5jZVdpZHRoKSB7CiAgICAgICAgICBjb250ZXh0TGFiZWwgPDw9IDE7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNvbnRleHRMYWJlbCA9IGNvbnRleHRMYWJlbCA8PCAxIHwgcmVmZXJlbmNlQml0bWFwW2kwXVtqMF07CiAgICAgICAgfQogICAgICB9CiAgICAgIGNvbnN0IHBpeGVsID0gZGVjb2Rlci5yZWFkQml0KGNvbnRleHRzLCBjb250ZXh0TGFiZWwpOwogICAgICByb3dbal0gPSBwaXhlbDsKICAgIH0KICB9CiAgcmV0dXJuIGJpdG1hcDsKfQpmdW5jdGlvbiBkZWNvZGVTeW1ib2xEaWN0aW9uYXJ5KGh1ZmZtYW4sIHJlZmluZW1lbnQsIHN5bWJvbHMsIG51bWJlck9mTmV3U3ltYm9scywgbnVtYmVyT2ZFeHBvcnRlZFN5bWJvbHMsIGh1ZmZtYW5UYWJsZXMsIHRlbXBsYXRlSW5kZXgsIGF0LCByZWZpbmVtZW50VGVtcGxhdGVJbmRleCwgcmVmaW5lbWVudEF0LCBkZWNvZGluZ0NvbnRleHQsIGh1ZmZtYW5JbnB1dCkgewogIGlmIChodWZmbWFuICYmIHJlZmluZW1lbnQpIHsKICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJzeW1ib2wgcmVmaW5lbWVudCB3aXRoIEh1ZmZtYW4gaXMgbm90IHN1cHBvcnRlZCIpOwogIH0KICBjb25zdCBuZXdTeW1ib2xzID0gW107CiAgbGV0IGN1cnJlbnRIZWlnaHQgPSAwOwogIGxldCBzeW1ib2xDb2RlTGVuZ3RoID0gKDAsIF9jb3JlX3V0aWxzLmxvZzIpKHN5bWJvbHMubGVuZ3RoICsgbnVtYmVyT2ZOZXdTeW1ib2xzKTsKICBjb25zdCBkZWNvZGVyID0gZGVjb2RpbmdDb250ZXh0LmRlY29kZXI7CiAgY29uc3QgY29udGV4dENhY2hlID0gZGVjb2RpbmdDb250ZXh0LmNvbnRleHRDYWNoZTsKICBsZXQgdGFibGVCMSwgc3ltYm9sV2lkdGhzOwogIGlmIChodWZmbWFuKSB7CiAgICB0YWJsZUIxID0gZ2V0U3RhbmRhcmRUYWJsZSgxKTsKICAgIHN5bWJvbFdpZHRocyA9IFtdOwogICAgc3ltYm9sQ29kZUxlbmd0aCA9IE1hdGgubWF4KHN5bWJvbENvZGVMZW5ndGgsIDEpOwogIH0KICB3aGlsZSAobmV3U3ltYm9scy5sZW5ndGggPCBudW1iZXJPZk5ld1N5bWJvbHMpIHsKICAgIGNvbnN0IGRlbHRhSGVpZ2h0ID0gaHVmZm1hbiA/IGh1ZmZtYW5UYWJsZXMudGFibGVEZWx0YUhlaWdodC5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFESCIsIGRlY29kZXIpOwogICAgY3VycmVudEhlaWdodCArPSBkZWx0YUhlaWdodDsKICAgIGxldCBjdXJyZW50V2lkdGggPSAwLAogICAgICB0b3RhbFdpZHRoID0gMDsKICAgIGNvbnN0IGZpcnN0U3ltYm9sID0gaHVmZm1hbiA/IHN5bWJvbFdpZHRocy5sZW5ndGggOiAwOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgY29uc3QgZGVsdGFXaWR0aCA9IGh1ZmZtYW4gPyBodWZmbWFuVGFibGVzLnRhYmxlRGVsdGFXaWR0aC5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFEVyIsIGRlY29kZXIpOwogICAgICBpZiAoZGVsdGFXaWR0aCA9PT0gbnVsbCkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGN1cnJlbnRXaWR0aCArPSBkZWx0YVdpZHRoOwogICAgICB0b3RhbFdpZHRoICs9IGN1cnJlbnRXaWR0aDsKICAgICAgbGV0IGJpdG1hcDsKICAgICAgaWYgKHJlZmluZW1lbnQpIHsKICAgICAgICBjb25zdCBudW1iZXJPZkluc3RhbmNlcyA9IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFBSSIsIGRlY29kZXIpOwogICAgICAgIGlmIChudW1iZXJPZkluc3RhbmNlcyA+IDEpIHsKICAgICAgICAgIGJpdG1hcCA9IGRlY29kZVRleHRSZWdpb24oaHVmZm1hbiwgcmVmaW5lbWVudCwgY3VycmVudFdpZHRoLCBjdXJyZW50SGVpZ2h0LCAwLCBudW1iZXJPZkluc3RhbmNlcywgMSwgc3ltYm9scy5jb25jYXQobmV3U3ltYm9scyksIHN5bWJvbENvZGVMZW5ndGgsIDAsIDAsIDEsIDAsIGh1ZmZtYW5UYWJsZXMsIHJlZmluZW1lbnRUZW1wbGF0ZUluZGV4LCByZWZpbmVtZW50QXQsIGRlY29kaW5nQ29udGV4dCwgMCwgaHVmZm1hbklucHV0KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3Qgc3ltYm9sSWQgPSBkZWNvZGVJQUlEKGNvbnRleHRDYWNoZSwgZGVjb2Rlciwgc3ltYm9sQ29kZUxlbmd0aCk7CiAgICAgICAgICBjb25zdCByZHggPSBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBUkRYIiwgZGVjb2Rlcik7CiAgICAgICAgICBjb25zdCByZHkgPSBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBUkRZIiwgZGVjb2Rlcik7CiAgICAgICAgICBjb25zdCBzeW1ib2wgPSBzeW1ib2xJZCA8IHN5bWJvbHMubGVuZ3RoID8gc3ltYm9sc1tzeW1ib2xJZF0gOiBuZXdTeW1ib2xzW3N5bWJvbElkIC0gc3ltYm9scy5sZW5ndGhdOwogICAgICAgICAgYml0bWFwID0gZGVjb2RlUmVmaW5lbWVudChjdXJyZW50V2lkdGgsIGN1cnJlbnRIZWlnaHQsIHJlZmluZW1lbnRUZW1wbGF0ZUluZGV4LCBzeW1ib2wsIHJkeCwgcmR5LCBmYWxzZSwgcmVmaW5lbWVudEF0LCBkZWNvZGluZ0NvbnRleHQpOwogICAgICAgIH0KICAgICAgICBuZXdTeW1ib2xzLnB1c2goYml0bWFwKTsKICAgICAgfSBlbHNlIGlmIChodWZmbWFuKSB7CiAgICAgICAgc3ltYm9sV2lkdGhzLnB1c2goY3VycmVudFdpZHRoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBiaXRtYXAgPSBkZWNvZGVCaXRtYXAoZmFsc2UsIGN1cnJlbnRXaWR0aCwgY3VycmVudEhlaWdodCwgdGVtcGxhdGVJbmRleCwgZmFsc2UsIG51bGwsIGF0LCBkZWNvZGluZ0NvbnRleHQpOwogICAgICAgIG5ld1N5bWJvbHMucHVzaChiaXRtYXApOwogICAgICB9CiAgICB9CiAgICBpZiAoaHVmZm1hbiAmJiAhcmVmaW5lbWVudCkgewogICAgICBjb25zdCBiaXRtYXBTaXplID0gaHVmZm1hblRhYmxlcy50YWJsZUJpdG1hcFNpemUuZGVjb2RlKGh1ZmZtYW5JbnB1dCk7CiAgICAgIGh1ZmZtYW5JbnB1dC5ieXRlQWxpZ24oKTsKICAgICAgbGV0IGNvbGxlY3RpdmVCaXRtYXA7CiAgICAgIGlmIChiaXRtYXBTaXplID09PSAwKSB7CiAgICAgICAgY29sbGVjdGl2ZUJpdG1hcCA9IHJlYWRVbmNvbXByZXNzZWRCaXRtYXAoaHVmZm1hbklucHV0LCB0b3RhbFdpZHRoLCBjdXJyZW50SGVpZ2h0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBvcmlnaW5hbEVuZCA9IGh1ZmZtYW5JbnB1dC5lbmQ7CiAgICAgICAgY29uc3QgYml0bWFwRW5kID0gaHVmZm1hbklucHV0LnBvc2l0aW9uICsgYml0bWFwU2l6ZTsKICAgICAgICBodWZmbWFuSW5wdXQuZW5kID0gYml0bWFwRW5kOwogICAgICAgIGNvbGxlY3RpdmVCaXRtYXAgPSBkZWNvZGVNTVJCaXRtYXAoaHVmZm1hbklucHV0LCB0b3RhbFdpZHRoLCBjdXJyZW50SGVpZ2h0LCBmYWxzZSk7CiAgICAgICAgaHVmZm1hbklucHV0LmVuZCA9IG9yaWdpbmFsRW5kOwogICAgICAgIGh1ZmZtYW5JbnB1dC5wb3NpdGlvbiA9IGJpdG1hcEVuZDsKICAgICAgfQogICAgICBjb25zdCBudW1iZXJPZlN5bWJvbHNEZWNvZGVkID0gc3ltYm9sV2lkdGhzLmxlbmd0aDsKICAgICAgaWYgKGZpcnN0U3ltYm9sID09PSBudW1iZXJPZlN5bWJvbHNEZWNvZGVkIC0gMSkgewogICAgICAgIG5ld1N5bWJvbHMucHVzaChjb2xsZWN0aXZlQml0bWFwKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBsZXQgaSwKICAgICAgICAgIHksCiAgICAgICAgICB4TWluID0gMCwKICAgICAgICAgIHhNYXgsCiAgICAgICAgICBiaXRtYXBXaWR0aCwKICAgICAgICAgIHN5bWJvbEJpdG1hcDsKICAgICAgICBmb3IgKGkgPSBmaXJzdFN5bWJvbDsgaSA8IG51bWJlck9mU3ltYm9sc0RlY29kZWQ7IGkrKykgewogICAgICAgICAgYml0bWFwV2lkdGggPSBzeW1ib2xXaWR0aHNbaV07CiAgICAgICAgICB4TWF4ID0geE1pbiArIGJpdG1hcFdpZHRoOwogICAgICAgICAgc3ltYm9sQml0bWFwID0gW107CiAgICAgICAgICBmb3IgKHkgPSAwOyB5IDwgY3VycmVudEhlaWdodDsgeSsrKSB7CiAgICAgICAgICAgIHN5bWJvbEJpdG1hcC5wdXNoKGNvbGxlY3RpdmVCaXRtYXBbeV0uc3ViYXJyYXkoeE1pbiwgeE1heCkpOwogICAgICAgICAgfQogICAgICAgICAgbmV3U3ltYm9scy5wdXNoKHN5bWJvbEJpdG1hcCk7CiAgICAgICAgICB4TWluID0geE1heDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgY29uc3QgZXhwb3J0ZWRTeW1ib2xzID0gW10sCiAgICBmbGFncyA9IFtdOwogIGxldCBjdXJyZW50RmxhZyA9IGZhbHNlLAogICAgaSwKICAgIGlpOwogIGNvbnN0IHRvdGFsU3ltYm9sc0xlbmd0aCA9IHN5bWJvbHMubGVuZ3RoICsgbnVtYmVyT2ZOZXdTeW1ib2xzOwogIHdoaWxlIChmbGFncy5sZW5ndGggPCB0b3RhbFN5bWJvbHNMZW5ndGgpIHsKICAgIGxldCBydW5MZW5ndGggPSBodWZmbWFuID8gdGFibGVCMS5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFFWCIsIGRlY29kZXIpOwogICAgd2hpbGUgKHJ1bkxlbmd0aC0tKSB7CiAgICAgIGZsYWdzLnB1c2goY3VycmVudEZsYWcpOwogICAgfQogICAgY3VycmVudEZsYWcgPSAhY3VycmVudEZsYWc7CiAgfQogIGZvciAoaSA9IDAsIGlpID0gc3ltYm9scy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBpZiAoZmxhZ3NbaV0pIHsKICAgICAgZXhwb3J0ZWRTeW1ib2xzLnB1c2goc3ltYm9sc1tpXSk7CiAgICB9CiAgfQogIGZvciAobGV0IGogPSAwOyBqIDwgbnVtYmVyT2ZOZXdTeW1ib2xzOyBpKyssIGorKykgewogICAgaWYgKGZsYWdzW2ldKSB7CiAgICAgIGV4cG9ydGVkU3ltYm9scy5wdXNoKG5ld1N5bWJvbHNbal0pOwogICAgfQogIH0KICByZXR1cm4gZXhwb3J0ZWRTeW1ib2xzOwp9CmZ1bmN0aW9uIGRlY29kZVRleHRSZWdpb24oaHVmZm1hbiwgcmVmaW5lbWVudCwgd2lkdGgsIGhlaWdodCwgZGVmYXVsdFBpeGVsVmFsdWUsIG51bWJlck9mU3ltYm9sSW5zdGFuY2VzLCBzdHJpcFNpemUsIGlucHV0U3ltYm9scywgc3ltYm9sQ29kZUxlbmd0aCwgdHJhbnNwb3NlZCwgZHNPZmZzZXQsIHJlZmVyZW5jZUNvcm5lciwgY29tYmluYXRpb25PcGVyYXRvciwgaHVmZm1hblRhYmxlcywgcmVmaW5lbWVudFRlbXBsYXRlSW5kZXgsIHJlZmluZW1lbnRBdCwgZGVjb2RpbmdDb250ZXh0LCBsb2dTdHJpcFNpemUsIGh1ZmZtYW5JbnB1dCkgewogIGlmIChodWZmbWFuICYmIHJlZmluZW1lbnQpIHsKICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJyZWZpbmVtZW50IHdpdGggSHVmZm1hbiBpcyBub3Qgc3VwcG9ydGVkIik7CiAgfQogIGNvbnN0IGJpdG1hcCA9IFtdOwogIGxldCBpLCByb3c7CiAgZm9yIChpID0gMDsgaSA8IGhlaWdodDsgaSsrKSB7CiAgICByb3cgPSBuZXcgVWludDhBcnJheSh3aWR0aCk7CiAgICBpZiAoZGVmYXVsdFBpeGVsVmFsdWUpIHsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7CiAgICAgICAgcm93W2pdID0gZGVmYXVsdFBpeGVsVmFsdWU7CiAgICAgIH0KICAgIH0KICAgIGJpdG1hcC5wdXNoKHJvdyk7CiAgfQogIGNvbnN0IGRlY29kZXIgPSBkZWNvZGluZ0NvbnRleHQuZGVjb2RlcjsKICBjb25zdCBjb250ZXh0Q2FjaGUgPSBkZWNvZGluZ0NvbnRleHQuY29udGV4dENhY2hlOwogIGxldCBzdHJpcFQgPSBodWZmbWFuID8gLWh1ZmZtYW5UYWJsZXMudGFibGVEZWx0YVQuZGVjb2RlKGh1ZmZtYW5JbnB1dCkgOiAtZGVjb2RlSW50ZWdlcihjb250ZXh0Q2FjaGUsICJJQURUIiwgZGVjb2Rlcik7CiAgbGV0IGZpcnN0UyA9IDA7CiAgaSA9IDA7CiAgd2hpbGUgKGkgPCBudW1iZXJPZlN5bWJvbEluc3RhbmNlcykgewogICAgY29uc3QgZGVsdGFUID0gaHVmZm1hbiA/IGh1ZmZtYW5UYWJsZXMudGFibGVEZWx0YVQuZGVjb2RlKGh1ZmZtYW5JbnB1dCkgOiBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBRFQiLCBkZWNvZGVyKTsKICAgIHN0cmlwVCArPSBkZWx0YVQ7CiAgICBjb25zdCBkZWx0YUZpcnN0UyA9IGh1ZmZtYW4gPyBodWZmbWFuVGFibGVzLnRhYmxlRmlyc3RTLmRlY29kZShodWZmbWFuSW5wdXQpIDogZGVjb2RlSW50ZWdlcihjb250ZXh0Q2FjaGUsICJJQUZTIiwgZGVjb2Rlcik7CiAgICBmaXJzdFMgKz0gZGVsdGFGaXJzdFM7CiAgICBsZXQgY3VycmVudFMgPSBmaXJzdFM7CiAgICBkbyB7CiAgICAgIGxldCBjdXJyZW50VCA9IDA7CiAgICAgIGlmIChzdHJpcFNpemUgPiAxKSB7CiAgICAgICAgY3VycmVudFQgPSBodWZmbWFuID8gaHVmZm1hbklucHV0LnJlYWRCaXRzKGxvZ1N0cmlwU2l6ZSkgOiBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBSVQiLCBkZWNvZGVyKTsKICAgICAgfQogICAgICBjb25zdCB0ID0gc3RyaXBTaXplICogc3RyaXBUICsgY3VycmVudFQ7CiAgICAgIGNvbnN0IHN5bWJvbElkID0gaHVmZm1hbiA/IGh1ZmZtYW5UYWJsZXMuc3ltYm9sSURUYWJsZS5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUlBSUQoY29udGV4dENhY2hlLCBkZWNvZGVyLCBzeW1ib2xDb2RlTGVuZ3RoKTsKICAgICAgY29uc3QgYXBwbHlSZWZpbmVtZW50ID0gcmVmaW5lbWVudCAmJiAoaHVmZm1hbiA/IGh1ZmZtYW5JbnB1dC5yZWFkQml0KCkgOiBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBUkkiLCBkZWNvZGVyKSk7CiAgICAgIGxldCBzeW1ib2xCaXRtYXAgPSBpbnB1dFN5bWJvbHNbc3ltYm9sSWRdOwogICAgICBsZXQgc3ltYm9sV2lkdGggPSBzeW1ib2xCaXRtYXBbMF0ubGVuZ3RoOwogICAgICBsZXQgc3ltYm9sSGVpZ2h0ID0gc3ltYm9sQml0bWFwLmxlbmd0aDsKICAgICAgaWYgKGFwcGx5UmVmaW5lbWVudCkgewogICAgICAgIGNvbnN0IHJkdyA9IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFSRFciLCBkZWNvZGVyKTsKICAgICAgICBjb25zdCByZGggPSBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBUkRIIiwgZGVjb2Rlcik7CiAgICAgICAgY29uc3QgcmR4ID0gZGVjb2RlSW50ZWdlcihjb250ZXh0Q2FjaGUsICJJQVJEWCIsIGRlY29kZXIpOwogICAgICAgIGNvbnN0IHJkeSA9IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFSRFkiLCBkZWNvZGVyKTsKICAgICAgICBzeW1ib2xXaWR0aCArPSByZHc7CiAgICAgICAgc3ltYm9sSGVpZ2h0ICs9IHJkaDsKICAgICAgICBzeW1ib2xCaXRtYXAgPSBkZWNvZGVSZWZpbmVtZW50KHN5bWJvbFdpZHRoLCBzeW1ib2xIZWlnaHQsIHJlZmluZW1lbnRUZW1wbGF0ZUluZGV4LCBzeW1ib2xCaXRtYXAsIChyZHcgPj4gMSkgKyByZHgsIChyZGggPj4gMSkgKyByZHksIGZhbHNlLCByZWZpbmVtZW50QXQsIGRlY29kaW5nQ29udGV4dCk7CiAgICAgIH0KICAgICAgY29uc3Qgb2Zmc2V0VCA9IHQgLSAocmVmZXJlbmNlQ29ybmVyICYgMSA/IDAgOiBzeW1ib2xIZWlnaHQgLSAxKTsKICAgICAgY29uc3Qgb2Zmc2V0UyA9IGN1cnJlbnRTIC0gKHJlZmVyZW5jZUNvcm5lciAmIDIgPyBzeW1ib2xXaWR0aCAtIDEgOiAwKTsKICAgICAgbGV0IHMyLCB0Miwgc3ltYm9sUm93OwogICAgICBpZiAodHJhbnNwb3NlZCkgewogICAgICAgIGZvciAoczIgPSAwOyBzMiA8IHN5bWJvbEhlaWdodDsgczIrKykgewogICAgICAgICAgcm93ID0gYml0bWFwW29mZnNldFMgKyBzMl07CiAgICAgICAgICBpZiAoIXJvdykgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIHN5bWJvbFJvdyA9IHN5bWJvbEJpdG1hcFtzMl07CiAgICAgICAgICBjb25zdCBtYXhXaWR0aCA9IE1hdGgubWluKHdpZHRoIC0gb2Zmc2V0VCwgc3ltYm9sV2lkdGgpOwogICAgICAgICAgc3dpdGNoIChjb21iaW5hdGlvbk9wZXJhdG9yKSB7CiAgICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgICBmb3IgKHQyID0gMDsgdDIgPCBtYXhXaWR0aDsgdDIrKykgewogICAgICAgICAgICAgICAgcm93W29mZnNldFQgKyB0Ml0gfD0gc3ltYm9sUm93W3QyXTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgICBmb3IgKHQyID0gMDsgdDIgPCBtYXhXaWR0aDsgdDIrKykgewogICAgICAgICAgICAgICAgcm93W29mZnNldFQgKyB0Ml0gXj0gc3ltYm9sUm93W3QyXTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoYG9wZXJhdG9yICR7Y29tYmluYXRpb25PcGVyYXRvcn0gaXMgbm90IHN1cHBvcnRlZGApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjdXJyZW50UyArPSBzeW1ib2xIZWlnaHQgLSAxOwogICAgICB9IGVsc2UgewogICAgICAgIGZvciAodDIgPSAwOyB0MiA8IHN5bWJvbEhlaWdodDsgdDIrKykgewogICAgICAgICAgcm93ID0gYml0bWFwW29mZnNldFQgKyB0Ml07CiAgICAgICAgICBpZiAoIXJvdykgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIHN5bWJvbFJvdyA9IHN5bWJvbEJpdG1hcFt0Ml07CiAgICAgICAgICBzd2l0Y2ggKGNvbWJpbmF0aW9uT3BlcmF0b3IpIHsKICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgIGZvciAoczIgPSAwOyBzMiA8IHN5bWJvbFdpZHRoOyBzMisrKSB7CiAgICAgICAgICAgICAgICByb3dbb2Zmc2V0UyArIHMyXSB8PSBzeW1ib2xSb3dbczJdOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgIGZvciAoczIgPSAwOyBzMiA8IHN5bWJvbFdpZHRoOyBzMisrKSB7CiAgICAgICAgICAgICAgICByb3dbb2Zmc2V0UyArIHMyXSBePSBzeW1ib2xSb3dbczJdOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcihgb3BlcmF0b3IgJHtjb21iaW5hdGlvbk9wZXJhdG9yfSBpcyBub3Qgc3VwcG9ydGVkYCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGN1cnJlbnRTICs9IHN5bWJvbFdpZHRoIC0gMTsKICAgICAgfQogICAgICBpKys7CiAgICAgIGNvbnN0IGRlbHRhUyA9IGh1ZmZtYW4gPyBodWZmbWFuVGFibGVzLnRhYmxlRGVsdGFTLmRlY29kZShodWZmbWFuSW5wdXQpIDogZGVjb2RlSW50ZWdlcihjb250ZXh0Q2FjaGUsICJJQURTIiwgZGVjb2Rlcik7CiAgICAgIGlmIChkZWx0YVMgPT09IG51bGwpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBjdXJyZW50UyArPSBkZWx0YVMgKyBkc09mZnNldDsKICAgIH0gd2hpbGUgKHRydWUpOwogIH0KICByZXR1cm4gYml0bWFwOwp9CmZ1bmN0aW9uIGRlY29kZVBhdHRlcm5EaWN0aW9uYXJ5KG1tciwgcGF0dGVybldpZHRoLCBwYXR0ZXJuSGVpZ2h0LCBtYXhQYXR0ZXJuSW5kZXgsIHRlbXBsYXRlLCBkZWNvZGluZ0NvbnRleHQpIHsKICBjb25zdCBhdCA9IFtdOwogIGlmICghbW1yKSB7CiAgICBhdC5wdXNoKHsKICAgICAgeDogLXBhdHRlcm5XaWR0aCwKICAgICAgeTogMAogICAgfSk7CiAgICBpZiAodGVtcGxhdGUgPT09IDApIHsKICAgICAgYXQucHVzaCh7CiAgICAgICAgeDogLTMsCiAgICAgICAgeTogLTEKICAgICAgfSwgewogICAgICAgIHg6IDIsCiAgICAgICAgeTogLTIKICAgICAgfSwgewogICAgICAgIHg6IC0yLAogICAgICAgIHk6IC0yCiAgICAgIH0pOwogICAgfQogIH0KICBjb25zdCBjb2xsZWN0aXZlV2lkdGggPSAobWF4UGF0dGVybkluZGV4ICsgMSkgKiBwYXR0ZXJuV2lkdGg7CiAgY29uc3QgY29sbGVjdGl2ZUJpdG1hcCA9IGRlY29kZUJpdG1hcChtbXIsIGNvbGxlY3RpdmVXaWR0aCwgcGF0dGVybkhlaWdodCwgdGVtcGxhdGUsIGZhbHNlLCBudWxsLCBhdCwgZGVjb2RpbmdDb250ZXh0KTsKICBjb25zdCBwYXR0ZXJucyA9IFtdOwogIGZvciAobGV0IGkgPSAwOyBpIDw9IG1heFBhdHRlcm5JbmRleDsgaSsrKSB7CiAgICBjb25zdCBwYXR0ZXJuQml0bWFwID0gW107CiAgICBjb25zdCB4TWluID0gcGF0dGVybldpZHRoICogaTsKICAgIGNvbnN0IHhNYXggPSB4TWluICsgcGF0dGVybldpZHRoOwogICAgZm9yIChsZXQgeSA9IDA7IHkgPCBwYXR0ZXJuSGVpZ2h0OyB5KyspIHsKICAgICAgcGF0dGVybkJpdG1hcC5wdXNoKGNvbGxlY3RpdmVCaXRtYXBbeV0uc3ViYXJyYXkoeE1pbiwgeE1heCkpOwogICAgfQogICAgcGF0dGVybnMucHVzaChwYXR0ZXJuQml0bWFwKTsKICB9CiAgcmV0dXJuIHBhdHRlcm5zOwp9CmZ1bmN0aW9uIGRlY29kZUhhbGZ0b25lUmVnaW9uKG1tciwgcGF0dGVybnMsIHRlbXBsYXRlLCByZWdpb25XaWR0aCwgcmVnaW9uSGVpZ2h0LCBkZWZhdWx0UGl4ZWxWYWx1ZSwgZW5hYmxlU2tpcCwgY29tYmluYXRpb25PcGVyYXRvciwgZ3JpZFdpZHRoLCBncmlkSGVpZ2h0LCBncmlkT2Zmc2V0WCwgZ3JpZE9mZnNldFksIGdyaWRWZWN0b3JYLCBncmlkVmVjdG9yWSwgZGVjb2RpbmdDb250ZXh0KSB7CiAgY29uc3Qgc2tpcCA9IG51bGw7CiAgaWYgKGVuYWJsZVNraXApIHsKICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJza2lwIGlzIG5vdCBzdXBwb3J0ZWQiKTsKICB9CiAgaWYgKGNvbWJpbmF0aW9uT3BlcmF0b3IgIT09IDApIHsKICAgIHRocm93IG5ldyBKYmlnMkVycm9yKGBvcGVyYXRvciAiJHtjb21iaW5hdGlvbk9wZXJhdG9yfSIgaXMgbm90IHN1cHBvcnRlZCBpbiBoYWxmdG9uZSByZWdpb25gKTsKICB9CiAgY29uc3QgcmVnaW9uQml0bWFwID0gW107CiAgbGV0IGksIGosIHJvdzsKICBmb3IgKGkgPSAwOyBpIDwgcmVnaW9uSGVpZ2h0OyBpKyspIHsKICAgIHJvdyA9IG5ldyBVaW50OEFycmF5KHJlZ2lvbldpZHRoKTsKICAgIGlmIChkZWZhdWx0UGl4ZWxWYWx1ZSkgewogICAgICBmb3IgKGogPSAwOyBqIDwgcmVnaW9uV2lkdGg7IGorKykgewogICAgICAgIHJvd1tqXSA9IGRlZmF1bHRQaXhlbFZhbHVlOwogICAgICB9CiAgICB9CiAgICByZWdpb25CaXRtYXAucHVzaChyb3cpOwogIH0KICBjb25zdCBudW1iZXJPZlBhdHRlcm5zID0gcGF0dGVybnMubGVuZ3RoOwogIGNvbnN0IHBhdHRlcm4wID0gcGF0dGVybnNbMF07CiAgY29uc3QgcGF0dGVybldpZHRoID0gcGF0dGVybjBbMF0ubGVuZ3RoLAogICAgcGF0dGVybkhlaWdodCA9IHBhdHRlcm4wLmxlbmd0aDsKICBjb25zdCBiaXRzUGVyVmFsdWUgPSAoMCwgX2NvcmVfdXRpbHMubG9nMikobnVtYmVyT2ZQYXR0ZXJucyk7CiAgY29uc3QgYXQgPSBbXTsKICBpZiAoIW1tcikgewogICAgYXQucHVzaCh7CiAgICAgIHg6IHRlbXBsYXRlIDw9IDEgPyAzIDogMiwKICAgICAgeTogLTEKICAgIH0pOwogICAgaWYgKHRlbXBsYXRlID09PSAwKSB7CiAgICAgIGF0LnB1c2goewogICAgICAgIHg6IC0zLAogICAgICAgIHk6IC0xCiAgICAgIH0sIHsKICAgICAgICB4OiAyLAogICAgICAgIHk6IC0yCiAgICAgIH0sIHsKICAgICAgICB4OiAtMiwKICAgICAgICB5OiAtMgogICAgICB9KTsKICAgIH0KICB9CiAgY29uc3QgZ3JheVNjYWxlQml0UGxhbmVzID0gW107CiAgbGV0IG1tcklucHV0LCBiaXRtYXA7CiAgaWYgKG1tcikgewogICAgbW1ySW5wdXQgPSBuZXcgUmVhZGVyKGRlY29kaW5nQ29udGV4dC5kYXRhLCBkZWNvZGluZ0NvbnRleHQuc3RhcnQsIGRlY29kaW5nQ29udGV4dC5lbmQpOwogIH0KICBmb3IgKGkgPSBiaXRzUGVyVmFsdWUgLSAxOyBpID49IDA7IGktLSkgewogICAgaWYgKG1tcikgewogICAgICBiaXRtYXAgPSBkZWNvZGVNTVJCaXRtYXAobW1ySW5wdXQsIGdyaWRXaWR0aCwgZ3JpZEhlaWdodCwgdHJ1ZSk7CiAgICB9IGVsc2UgewogICAgICBiaXRtYXAgPSBkZWNvZGVCaXRtYXAoZmFsc2UsIGdyaWRXaWR0aCwgZ3JpZEhlaWdodCwgdGVtcGxhdGUsIGZhbHNlLCBza2lwLCBhdCwgZGVjb2RpbmdDb250ZXh0KTsKICAgIH0KICAgIGdyYXlTY2FsZUJpdFBsYW5lc1tpXSA9IGJpdG1hcDsKICB9CiAgbGV0IG1nLCBuZywgYml0LCBwYXR0ZXJuSW5kZXgsIHBhdHRlcm5CaXRtYXAsIHgsIHksIHBhdHRlcm5Sb3csIHJlZ2lvblJvdzsKICBmb3IgKG1nID0gMDsgbWcgPCBncmlkSGVpZ2h0OyBtZysrKSB7CiAgICBmb3IgKG5nID0gMDsgbmcgPCBncmlkV2lkdGg7IG5nKyspIHsKICAgICAgYml0ID0gMDsKICAgICAgcGF0dGVybkluZGV4ID0gMDsKICAgICAgZm9yIChqID0gYml0c1BlclZhbHVlIC0gMTsgaiA+PSAwOyBqLS0pIHsKICAgICAgICBiaXQgXj0gZ3JheVNjYWxlQml0UGxhbmVzW2pdW21nXVtuZ107CiAgICAgICAgcGF0dGVybkluZGV4IHw9IGJpdCA8PCBqOwogICAgICB9CiAgICAgIHBhdHRlcm5CaXRtYXAgPSBwYXR0ZXJuc1twYXR0ZXJuSW5kZXhdOwogICAgICB4ID0gZ3JpZE9mZnNldFggKyBtZyAqIGdyaWRWZWN0b3JZICsgbmcgKiBncmlkVmVjdG9yWCA+PiA4OwogICAgICB5ID0gZ3JpZE9mZnNldFkgKyBtZyAqIGdyaWRWZWN0b3JYIC0gbmcgKiBncmlkVmVjdG9yWSA+PiA4OwogICAgICBpZiAoeCA+PSAwICYmIHggKyBwYXR0ZXJuV2lkdGggPD0gcmVnaW9uV2lkdGggJiYgeSA+PSAwICYmIHkgKyBwYXR0ZXJuSGVpZ2h0IDw9IHJlZ2lvbkhlaWdodCkgewogICAgICAgIGZvciAoaSA9IDA7IGkgPCBwYXR0ZXJuSGVpZ2h0OyBpKyspIHsKICAgICAgICAgIHJlZ2lvblJvdyA9IHJlZ2lvbkJpdG1hcFt5ICsgaV07CiAgICAgICAgICBwYXR0ZXJuUm93ID0gcGF0dGVybkJpdG1hcFtpXTsKICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBwYXR0ZXJuV2lkdGg7IGorKykgewogICAgICAgICAgICByZWdpb25Sb3dbeCArIGpdIHw9IHBhdHRlcm5Sb3dbal07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGxldCByZWdpb25YLCByZWdpb25ZOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBwYXR0ZXJuSGVpZ2h0OyBpKyspIHsKICAgICAgICAgIHJlZ2lvblkgPSB5ICsgaTsKICAgICAgICAgIGlmIChyZWdpb25ZIDwgMCB8fCByZWdpb25ZID49IHJlZ2lvbkhlaWdodCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIHJlZ2lvblJvdyA9IHJlZ2lvbkJpdG1hcFtyZWdpb25ZXTsKICAgICAgICAgIHBhdHRlcm5Sb3cgPSBwYXR0ZXJuQml0bWFwW2ldOwogICAgICAgICAgZm9yIChqID0gMDsgaiA8IHBhdHRlcm5XaWR0aDsgaisrKSB7CiAgICAgICAgICAgIHJlZ2lvblggPSB4ICsgajsKICAgICAgICAgICAgaWYgKHJlZ2lvblggPj0gMCAmJiByZWdpb25YIDwgcmVnaW9uV2lkdGgpIHsKICAgICAgICAgICAgICByZWdpb25Sb3dbcmVnaW9uWF0gfD0gcGF0dGVyblJvd1tqXTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICByZXR1cm4gcmVnaW9uQml0bWFwOwp9CmZ1bmN0aW9uIHJlYWRTZWdtZW50SGVhZGVyKGRhdGEsIHN0YXJ0KSB7CiAgY29uc3Qgc2VnbWVudEhlYWRlciA9IHt9OwogIHNlZ21lbnRIZWFkZXIubnVtYmVyID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHN0YXJ0KTsKICBjb25zdCBmbGFncyA9IGRhdGFbc3RhcnQgKyA0XTsKICBjb25zdCBzZWdtZW50VHlwZSA9IGZsYWdzICYgMHgzZjsKICBpZiAoIVNlZ21lbnRUeXBlc1tzZWdtZW50VHlwZV0pIHsKICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJpbnZhbGlkIHNlZ21lbnQgdHlwZTogIiArIHNlZ21lbnRUeXBlKTsKICB9CiAgc2VnbWVudEhlYWRlci50eXBlID0gc2VnbWVudFR5cGU7CiAgc2VnbWVudEhlYWRlci50eXBlTmFtZSA9IFNlZ21lbnRUeXBlc1tzZWdtZW50VHlwZV07CiAgc2VnbWVudEhlYWRlci5kZWZlcnJlZE5vblJldGFpbiA9ICEhKGZsYWdzICYgMHg4MCk7CiAgY29uc3QgcGFnZUFzc29jaWF0aW9uRmllbGRTaXplID0gISEoZmxhZ3MgJiAweDQwKTsKICBjb25zdCByZWZlcnJlZEZsYWdzID0gZGF0YVtzdGFydCArIDVdOwogIGxldCByZWZlcnJlZFRvQ291bnQgPSByZWZlcnJlZEZsYWdzID4+IDUgJiA3OwogIGNvbnN0IHJldGFpbkJpdHMgPSBbcmVmZXJyZWRGbGFncyAmIDMxXTsKICBsZXQgcG9zaXRpb24gPSBzdGFydCArIDY7CiAgaWYgKHJlZmVycmVkRmxhZ3MgPT09IDcpIHsKICAgIHJlZmVycmVkVG9Db3VudCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDMyKShkYXRhLCBwb3NpdGlvbiAtIDEpICYgMHgxZmZmZmZmZjsKICAgIHBvc2l0aW9uICs9IDM7CiAgICBsZXQgYnl0ZXMgPSByZWZlcnJlZFRvQ291bnQgKyA3ID4+IDM7CiAgICByZXRhaW5CaXRzWzBdID0gZGF0YVtwb3NpdGlvbisrXTsKICAgIHdoaWxlICgtLWJ5dGVzID4gMCkgewogICAgICByZXRhaW5CaXRzLnB1c2goZGF0YVtwb3NpdGlvbisrXSk7CiAgICB9CiAgfSBlbHNlIGlmIChyZWZlcnJlZEZsYWdzID09PSA1IHx8IHJlZmVycmVkRmxhZ3MgPT09IDYpIHsKICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJpbnZhbGlkIHJlZmVycmVkLXRvIGZsYWdzIik7CiAgfQogIHNlZ21lbnRIZWFkZXIucmV0YWluQml0cyA9IHJldGFpbkJpdHM7CiAgbGV0IHJlZmVycmVkVG9TZWdtZW50TnVtYmVyU2l6ZSA9IDQ7CiAgaWYgKHNlZ21lbnRIZWFkZXIubnVtYmVyIDw9IDI1NikgewogICAgcmVmZXJyZWRUb1NlZ21lbnROdW1iZXJTaXplID0gMTsKICB9IGVsc2UgaWYgKHNlZ21lbnRIZWFkZXIubnVtYmVyIDw9IDY1NTM2KSB7CiAgICByZWZlcnJlZFRvU2VnbWVudE51bWJlclNpemUgPSAyOwogIH0KICBjb25zdCByZWZlcnJlZFRvID0gW107CiAgbGV0IGksIGlpOwogIGZvciAoaSA9IDA7IGkgPCByZWZlcnJlZFRvQ291bnQ7IGkrKykgewogICAgbGV0IG51bWJlcjsKICAgIGlmIChyZWZlcnJlZFRvU2VnbWVudE51bWJlclNpemUgPT09IDEpIHsKICAgICAgbnVtYmVyID0gZGF0YVtwb3NpdGlvbl07CiAgICB9IGVsc2UgaWYgKHJlZmVycmVkVG9TZWdtZW50TnVtYmVyU2l6ZSA9PT0gMikgewogICAgICBudW1iZXIgPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgcG9zaXRpb24pOwogICAgfSBlbHNlIHsKICAgICAgbnVtYmVyID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uKTsKICAgIH0KICAgIHJlZmVycmVkVG8ucHVzaChudW1iZXIpOwogICAgcG9zaXRpb24gKz0gcmVmZXJyZWRUb1NlZ21lbnROdW1iZXJTaXplOwogIH0KICBzZWdtZW50SGVhZGVyLnJlZmVycmVkVG8gPSByZWZlcnJlZFRvOwogIGlmICghcGFnZUFzc29jaWF0aW9uRmllbGRTaXplKSB7CiAgICBzZWdtZW50SGVhZGVyLnBhZ2VBc3NvY2lhdGlvbiA9IGRhdGFbcG9zaXRpb24rK107CiAgfSBlbHNlIHsKICAgIHNlZ21lbnRIZWFkZXIucGFnZUFzc29jaWF0aW9uID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uKTsKICAgIHBvc2l0aW9uICs9IDQ7CiAgfQogIHNlZ21lbnRIZWFkZXIubGVuZ3RoID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uKTsKICBwb3NpdGlvbiArPSA0OwogIGlmIChzZWdtZW50SGVhZGVyLmxlbmd0aCA9PT0gMHhmZmZmZmZmZikgewogICAgaWYgKHNlZ21lbnRUeXBlID09PSAzOCkgewogICAgICBjb25zdCBnZW5lcmljUmVnaW9uSW5mbyA9IHJlYWRSZWdpb25TZWdtZW50SW5mb3JtYXRpb24oZGF0YSwgcG9zaXRpb24pOwogICAgICBjb25zdCBnZW5lcmljUmVnaW9uU2VnbWVudEZsYWdzID0gZGF0YVtwb3NpdGlvbiArIFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbkZpZWxkTGVuZ3RoXTsKICAgICAgY29uc3QgZ2VuZXJpY1JlZ2lvbk1tciA9ICEhKGdlbmVyaWNSZWdpb25TZWdtZW50RmxhZ3MgJiAxKTsKICAgICAgY29uc3Qgc2VhcmNoUGF0dGVybkxlbmd0aCA9IDY7CiAgICAgIGNvbnN0IHNlYXJjaFBhdHRlcm4gPSBuZXcgVWludDhBcnJheShzZWFyY2hQYXR0ZXJuTGVuZ3RoKTsKICAgICAgaWYgKCFnZW5lcmljUmVnaW9uTW1yKSB7CiAgICAgICAgc2VhcmNoUGF0dGVyblswXSA9IDB4ZmY7CiAgICAgICAgc2VhcmNoUGF0dGVyblsxXSA9IDB4YWM7CiAgICAgIH0KICAgICAgc2VhcmNoUGF0dGVyblsyXSA9IGdlbmVyaWNSZWdpb25JbmZvLmhlaWdodCA+Pj4gMjQgJiAweGZmOwogICAgICBzZWFyY2hQYXR0ZXJuWzNdID0gZ2VuZXJpY1JlZ2lvbkluZm8uaGVpZ2h0ID4+IDE2ICYgMHhmZjsKICAgICAgc2VhcmNoUGF0dGVybls0XSA9IGdlbmVyaWNSZWdpb25JbmZvLmhlaWdodCA+PiA4ICYgMHhmZjsKICAgICAgc2VhcmNoUGF0dGVybls1XSA9IGdlbmVyaWNSZWdpb25JbmZvLmhlaWdodCAmIDB4ZmY7CiAgICAgIGZvciAoaSA9IHBvc2l0aW9uLCBpaSA9IGRhdGEubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGxldCBqID0gMDsKICAgICAgICB3aGlsZSAoaiA8IHNlYXJjaFBhdHRlcm5MZW5ndGggJiYgc2VhcmNoUGF0dGVybltqXSA9PT0gZGF0YVtpICsgal0pIHsKICAgICAgICAgIGorKzsKICAgICAgICB9CiAgICAgICAgaWYgKGogPT09IHNlYXJjaFBhdHRlcm5MZW5ndGgpIHsKICAgICAgICAgIHNlZ21lbnRIZWFkZXIubGVuZ3RoID0gaSArIHNlYXJjaFBhdHRlcm5MZW5ndGg7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKHNlZ21lbnRIZWFkZXIubGVuZ3RoID09PSAweGZmZmZmZmZmKSB7CiAgICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoInNlZ21lbnQgZW5kIHdhcyBub3QgZm91bmQiKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgdW5rbm93biBzZWdtZW50IGxlbmd0aCIpOwogICAgfQogIH0KICBzZWdtZW50SGVhZGVyLmhlYWRlckVuZCA9IHBvc2l0aW9uOwogIHJldHVybiBzZWdtZW50SGVhZGVyOwp9CmZ1bmN0aW9uIHJlYWRTZWdtZW50cyhoZWFkZXIsIGRhdGEsIHN0YXJ0LCBlbmQpIHsKICBjb25zdCBzZWdtZW50cyA9IFtdOwogIGxldCBwb3NpdGlvbiA9IHN0YXJ0OwogIHdoaWxlIChwb3NpdGlvbiA8IGVuZCkgewogICAgY29uc3Qgc2VnbWVudEhlYWRlciA9IHJlYWRTZWdtZW50SGVhZGVyKGRhdGEsIHBvc2l0aW9uKTsKICAgIHBvc2l0aW9uID0gc2VnbWVudEhlYWRlci5oZWFkZXJFbmQ7CiAgICBjb25zdCBzZWdtZW50ID0gewogICAgICBoZWFkZXI6IHNlZ21lbnRIZWFkZXIsCiAgICAgIGRhdGEKICAgIH07CiAgICBpZiAoIWhlYWRlci5yYW5kb21BY2Nlc3MpIHsKICAgICAgc2VnbWVudC5zdGFydCA9IHBvc2l0aW9uOwogICAgICBwb3NpdGlvbiArPSBzZWdtZW50SGVhZGVyLmxlbmd0aDsKICAgICAgc2VnbWVudC5lbmQgPSBwb3NpdGlvbjsKICAgIH0KICAgIHNlZ21lbnRzLnB1c2goc2VnbWVudCk7CiAgICBpZiAoc2VnbWVudEhlYWRlci50eXBlID09PSA1MSkgewogICAgICBicmVhazsKICAgIH0KICB9CiAgaWYgKGhlYWRlci5yYW5kb21BY2Nlc3MpIHsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHNlZ21lbnRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgc2VnbWVudHNbaV0uc3RhcnQgPSBwb3NpdGlvbjsKICAgICAgcG9zaXRpb24gKz0gc2VnbWVudHNbaV0uaGVhZGVyLmxlbmd0aDsKICAgICAgc2VnbWVudHNbaV0uZW5kID0gcG9zaXRpb247CiAgICB9CiAgfQogIHJldHVybiBzZWdtZW50czsKfQpmdW5jdGlvbiByZWFkUmVnaW9uU2VnbWVudEluZm9ybWF0aW9uKGRhdGEsIHN0YXJ0KSB7CiAgcmV0dXJuIHsKICAgIHdpZHRoOiAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQzMikoZGF0YSwgc3RhcnQpLAogICAgaGVpZ2h0OiAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQzMikoZGF0YSwgc3RhcnQgKyA0KSwKICAgIHg6ICgwLCBfY29yZV91dGlscy5yZWFkVWludDMyKShkYXRhLCBzdGFydCArIDgpLAogICAgeTogKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHN0YXJ0ICsgMTIpLAogICAgY29tYmluYXRpb25PcGVyYXRvcjogZGF0YVtzdGFydCArIDE2XSAmIDcKICB9Owp9CmNvbnN0IFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbkZpZWxkTGVuZ3RoID0gMTc7CmZ1bmN0aW9uIHByb2Nlc3NTZWdtZW50KHNlZ21lbnQsIHZpc2l0b3IpIHsKICBjb25zdCBoZWFkZXIgPSBzZWdtZW50LmhlYWRlcjsKICBjb25zdCBkYXRhID0gc2VnbWVudC5kYXRhLAogICAgZW5kID0gc2VnbWVudC5lbmQ7CiAgbGV0IHBvc2l0aW9uID0gc2VnbWVudC5zdGFydDsKICBsZXQgYXJncywgYXQsIGksIGF0TGVuZ3RoOwogIHN3aXRjaCAoaGVhZGVyLnR5cGUpIHsKICAgIGNhc2UgMDoKICAgICAgY29uc3QgZGljdGlvbmFyeSA9IHt9OwogICAgICBjb25zdCBkaWN0aW9uYXJ5RmxhZ3MgPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgcG9zaXRpb24pOwogICAgICBkaWN0aW9uYXJ5Lmh1ZmZtYW4gPSAhIShkaWN0aW9uYXJ5RmxhZ3MgJiAxKTsKICAgICAgZGljdGlvbmFyeS5yZWZpbmVtZW50ID0gISEoZGljdGlvbmFyeUZsYWdzICYgMik7CiAgICAgIGRpY3Rpb25hcnkuaHVmZm1hbkRIU2VsZWN0b3IgPSBkaWN0aW9uYXJ5RmxhZ3MgPj4gMiAmIDM7CiAgICAgIGRpY3Rpb25hcnkuaHVmZm1hbkRXU2VsZWN0b3IgPSBkaWN0aW9uYXJ5RmxhZ3MgPj4gNCAmIDM7CiAgICAgIGRpY3Rpb25hcnkuYml0bWFwU2l6ZVNlbGVjdG9yID0gZGljdGlvbmFyeUZsYWdzID4+IDYgJiAxOwogICAgICBkaWN0aW9uYXJ5LmFnZ3JlZ2F0aW9uSW5zdGFuY2VzU2VsZWN0b3IgPSBkaWN0aW9uYXJ5RmxhZ3MgPj4gNyAmIDE7CiAgICAgIGRpY3Rpb25hcnkuYml0bWFwQ29kaW5nQ29udGV4dFVzZWQgPSAhIShkaWN0aW9uYXJ5RmxhZ3MgJiAyNTYpOwogICAgICBkaWN0aW9uYXJ5LmJpdG1hcENvZGluZ0NvbnRleHRSZXRhaW5lZCA9ICEhKGRpY3Rpb25hcnlGbGFncyAmIDUxMik7CiAgICAgIGRpY3Rpb25hcnkudGVtcGxhdGUgPSBkaWN0aW9uYXJ5RmxhZ3MgPj4gMTAgJiAzOwogICAgICBkaWN0aW9uYXJ5LnJlZmluZW1lbnRUZW1wbGF0ZSA9IGRpY3Rpb25hcnlGbGFncyA+PiAxMiAmIDE7CiAgICAgIHBvc2l0aW9uICs9IDI7CiAgICAgIGlmICghZGljdGlvbmFyeS5odWZmbWFuKSB7CiAgICAgICAgYXRMZW5ndGggPSBkaWN0aW9uYXJ5LnRlbXBsYXRlID09PSAwID8gNCA6IDE7CiAgICAgICAgYXQgPSBbXTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgYXRMZW5ndGg7IGkrKykgewogICAgICAgICAgYXQucHVzaCh7CiAgICAgICAgICAgIHg6ICgwLCBfY29yZV91dGlscy5yZWFkSW50OCkoZGF0YSwgcG9zaXRpb24pLAogICAgICAgICAgICB5OiAoMCwgX2NvcmVfdXRpbHMucmVhZEludDgpKGRhdGEsIHBvc2l0aW9uICsgMSkKICAgICAgICAgIH0pOwogICAgICAgICAgcG9zaXRpb24gKz0gMjsKICAgICAgICB9CiAgICAgICAgZGljdGlvbmFyeS5hdCA9IGF0OwogICAgICB9CiAgICAgIGlmIChkaWN0aW9uYXJ5LnJlZmluZW1lbnQgJiYgIWRpY3Rpb25hcnkucmVmaW5lbWVudFRlbXBsYXRlKSB7CiAgICAgICAgYXQgPSBbXTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMjsgaSsrKSB7CiAgICAgICAgICBhdC5wdXNoKHsKICAgICAgICAgICAgeDogKDAsIF9jb3JlX3V0aWxzLnJlYWRJbnQ4KShkYXRhLCBwb3NpdGlvbiksCiAgICAgICAgICAgIHk6ICgwLCBfY29yZV91dGlscy5yZWFkSW50OCkoZGF0YSwgcG9zaXRpb24gKyAxKQogICAgICAgICAgfSk7CiAgICAgICAgICBwb3NpdGlvbiArPSAyOwogICAgICAgIH0KICAgICAgICBkaWN0aW9uYXJ5LnJlZmluZW1lbnRBdCA9IGF0OwogICAgICB9CiAgICAgIGRpY3Rpb25hcnkubnVtYmVyT2ZFeHBvcnRlZFN5bWJvbHMgPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQzMikoZGF0YSwgcG9zaXRpb24pOwogICAgICBwb3NpdGlvbiArPSA0OwogICAgICBkaWN0aW9uYXJ5Lm51bWJlck9mTmV3U3ltYm9scyA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDMyKShkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IDQ7CiAgICAgIGFyZ3MgPSBbZGljdGlvbmFyeSwgaGVhZGVyLm51bWJlciwgaGVhZGVyLnJlZmVycmVkVG8sIGRhdGEsIHBvc2l0aW9uLCBlbmRdOwogICAgICBicmVhazsKICAgIGNhc2UgNjoKICAgIGNhc2UgNzoKICAgICAgY29uc3QgdGV4dFJlZ2lvbiA9IHt9OwogICAgICB0ZXh0UmVnaW9uLmluZm8gPSByZWFkUmVnaW9uU2VnbWVudEluZm9ybWF0aW9uKGRhdGEsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24gKz0gUmVnaW9uU2VnbWVudEluZm9ybWF0aW9uRmllbGRMZW5ndGg7CiAgICAgIGNvbnN0IHRleHRSZWdpb25TZWdtZW50RmxhZ3MgPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgcG9zaXRpb24pOwogICAgICBwb3NpdGlvbiArPSAyOwogICAgICB0ZXh0UmVnaW9uLmh1ZmZtYW4gPSAhISh0ZXh0UmVnaW9uU2VnbWVudEZsYWdzICYgMSk7CiAgICAgIHRleHRSZWdpb24ucmVmaW5lbWVudCA9ICEhKHRleHRSZWdpb25TZWdtZW50RmxhZ3MgJiAyKTsKICAgICAgdGV4dFJlZ2lvbi5sb2dTdHJpcFNpemUgPSB0ZXh0UmVnaW9uU2VnbWVudEZsYWdzID4+IDIgJiAzOwogICAgICB0ZXh0UmVnaW9uLnN0cmlwU2l6ZSA9IDEgPDwgdGV4dFJlZ2lvbi5sb2dTdHJpcFNpemU7CiAgICAgIHRleHRSZWdpb24ucmVmZXJlbmNlQ29ybmVyID0gdGV4dFJlZ2lvblNlZ21lbnRGbGFncyA+PiA0ICYgMzsKICAgICAgdGV4dFJlZ2lvbi50cmFuc3Bvc2VkID0gISEodGV4dFJlZ2lvblNlZ21lbnRGbGFncyAmIDY0KTsKICAgICAgdGV4dFJlZ2lvbi5jb21iaW5hdGlvbk9wZXJhdG9yID0gdGV4dFJlZ2lvblNlZ21lbnRGbGFncyA+PiA3ICYgMzsKICAgICAgdGV4dFJlZ2lvbi5kZWZhdWx0UGl4ZWxWYWx1ZSA9IHRleHRSZWdpb25TZWdtZW50RmxhZ3MgPj4gOSAmIDE7CiAgICAgIHRleHRSZWdpb24uZHNPZmZzZXQgPSB0ZXh0UmVnaW9uU2VnbWVudEZsYWdzIDw8IDE3ID4+IDI3OwogICAgICB0ZXh0UmVnaW9uLnJlZmluZW1lbnRUZW1wbGF0ZSA9IHRleHRSZWdpb25TZWdtZW50RmxhZ3MgPj4gMTUgJiAxOwogICAgICBpZiAodGV4dFJlZ2lvbi5odWZmbWFuKSB7CiAgICAgICAgY29uc3QgdGV4dFJlZ2lvbkh1ZmZtYW5GbGFncyA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBwb3NpdGlvbik7CiAgICAgICAgcG9zaXRpb24gKz0gMjsKICAgICAgICB0ZXh0UmVnaW9uLmh1ZmZtYW5GUyA9IHRleHRSZWdpb25IdWZmbWFuRmxhZ3MgJiAzOwogICAgICAgIHRleHRSZWdpb24uaHVmZm1hbkRTID0gdGV4dFJlZ2lvbkh1ZmZtYW5GbGFncyA+PiAyICYgMzsKICAgICAgICB0ZXh0UmVnaW9uLmh1ZmZtYW5EVCA9IHRleHRSZWdpb25IdWZmbWFuRmxhZ3MgPj4gNCAmIDM7CiAgICAgICAgdGV4dFJlZ2lvbi5odWZmbWFuUmVmaW5lbWVudERXID0gdGV4dFJlZ2lvbkh1ZmZtYW5GbGFncyA+PiA2ICYgMzsKICAgICAgICB0ZXh0UmVnaW9uLmh1ZmZtYW5SZWZpbmVtZW50REggPSB0ZXh0UmVnaW9uSHVmZm1hbkZsYWdzID4+IDggJiAzOwogICAgICAgIHRleHRSZWdpb24uaHVmZm1hblJlZmluZW1lbnREWCA9IHRleHRSZWdpb25IdWZmbWFuRmxhZ3MgPj4gMTAgJiAzOwogICAgICAgIHRleHRSZWdpb24uaHVmZm1hblJlZmluZW1lbnREWSA9IHRleHRSZWdpb25IdWZmbWFuRmxhZ3MgPj4gMTIgJiAzOwogICAgICAgIHRleHRSZWdpb24uaHVmZm1hblJlZmluZW1lbnRTaXplU2VsZWN0b3IgPSAhISh0ZXh0UmVnaW9uSHVmZm1hbkZsYWdzICYgMHg0MDAwKTsKICAgICAgfQogICAgICBpZiAodGV4dFJlZ2lvbi5yZWZpbmVtZW50ICYmICF0ZXh0UmVnaW9uLnJlZmluZW1lbnRUZW1wbGF0ZSkgewogICAgICAgIGF0ID0gW107CiAgICAgICAgZm9yIChpID0gMDsgaSA8IDI7IGkrKykgewogICAgICAgICAgYXQucHVzaCh7CiAgICAgICAgICAgIHg6ICgwLCBfY29yZV91dGlscy5yZWFkSW50OCkoZGF0YSwgcG9zaXRpb24pLAogICAgICAgICAgICB5OiAoMCwgX2NvcmVfdXRpbHMucmVhZEludDgpKGRhdGEsIHBvc2l0aW9uICsgMSkKICAgICAgICAgIH0pOwogICAgICAgICAgcG9zaXRpb24gKz0gMjsKICAgICAgICB9CiAgICAgICAgdGV4dFJlZ2lvbi5yZWZpbmVtZW50QXQgPSBhdDsKICAgICAgfQogICAgICB0ZXh0UmVnaW9uLm51bWJlck9mU3ltYm9sSW5zdGFuY2VzID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24gKz0gNDsKICAgICAgYXJncyA9IFt0ZXh0UmVnaW9uLCBoZWFkZXIucmVmZXJyZWRUbywgZGF0YSwgcG9zaXRpb24sIGVuZF07CiAgICAgIGJyZWFrOwogICAgY2FzZSAxNjoKICAgICAgY29uc3QgcGF0dGVybkRpY3Rpb25hcnkgPSB7fTsKICAgICAgY29uc3QgcGF0dGVybkRpY3Rpb25hcnlGbGFncyA9IGRhdGFbcG9zaXRpb24rK107CiAgICAgIHBhdHRlcm5EaWN0aW9uYXJ5Lm1tciA9ICEhKHBhdHRlcm5EaWN0aW9uYXJ5RmxhZ3MgJiAxKTsKICAgICAgcGF0dGVybkRpY3Rpb25hcnkudGVtcGxhdGUgPSBwYXR0ZXJuRGljdGlvbmFyeUZsYWdzID4+IDEgJiAzOwogICAgICBwYXR0ZXJuRGljdGlvbmFyeS5wYXR0ZXJuV2lkdGggPSBkYXRhW3Bvc2l0aW9uKytdOwogICAgICBwYXR0ZXJuRGljdGlvbmFyeS5wYXR0ZXJuSGVpZ2h0ID0gZGF0YVtwb3NpdGlvbisrXTsKICAgICAgcGF0dGVybkRpY3Rpb25hcnkubWF4UGF0dGVybkluZGV4ID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24gKz0gNDsKICAgICAgYXJncyA9IFtwYXR0ZXJuRGljdGlvbmFyeSwgaGVhZGVyLm51bWJlciwgZGF0YSwgcG9zaXRpb24sIGVuZF07CiAgICAgIGJyZWFrOwogICAgY2FzZSAyMjoKICAgIGNhc2UgMjM6CiAgICAgIGNvbnN0IGhhbGZ0b25lUmVnaW9uID0ge307CiAgICAgIGhhbGZ0b25lUmVnaW9uLmluZm8gPSByZWFkUmVnaW9uU2VnbWVudEluZm9ybWF0aW9uKGRhdGEsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24gKz0gUmVnaW9uU2VnbWVudEluZm9ybWF0aW9uRmllbGRMZW5ndGg7CiAgICAgIGNvbnN0IGhhbGZ0b25lUmVnaW9uRmxhZ3MgPSBkYXRhW3Bvc2l0aW9uKytdOwogICAgICBoYWxmdG9uZVJlZ2lvbi5tbXIgPSAhIShoYWxmdG9uZVJlZ2lvbkZsYWdzICYgMSk7CiAgICAgIGhhbGZ0b25lUmVnaW9uLnRlbXBsYXRlID0gaGFsZnRvbmVSZWdpb25GbGFncyA+PiAxICYgMzsKICAgICAgaGFsZnRvbmVSZWdpb24uZW5hYmxlU2tpcCA9ICEhKGhhbGZ0b25lUmVnaW9uRmxhZ3MgJiA4KTsKICAgICAgaGFsZnRvbmVSZWdpb24uY29tYmluYXRpb25PcGVyYXRvciA9IGhhbGZ0b25lUmVnaW9uRmxhZ3MgPj4gNCAmIDc7CiAgICAgIGhhbGZ0b25lUmVnaW9uLmRlZmF1bHRQaXhlbFZhbHVlID0gaGFsZnRvbmVSZWdpb25GbGFncyA+PiA3ICYgMTsKICAgICAgaGFsZnRvbmVSZWdpb24uZ3JpZFdpZHRoID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24gKz0gNDsKICAgICAgaGFsZnRvbmVSZWdpb24uZ3JpZEhlaWdodCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDMyKShkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IDQ7CiAgICAgIGhhbGZ0b25lUmVnaW9uLmdyaWRPZmZzZXRYID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uKSAmIDB4ZmZmZmZmZmY7CiAgICAgIHBvc2l0aW9uICs9IDQ7CiAgICAgIGhhbGZ0b25lUmVnaW9uLmdyaWRPZmZzZXRZID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uKSAmIDB4ZmZmZmZmZmY7CiAgICAgIHBvc2l0aW9uICs9IDQ7CiAgICAgIGhhbGZ0b25lUmVnaW9uLmdyaWRWZWN0b3JYID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MTYpKGRhdGEsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24gKz0gMjsKICAgICAgaGFsZnRvbmVSZWdpb24uZ3JpZFZlY3RvclkgPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgcG9zaXRpb24pOwogICAgICBwb3NpdGlvbiArPSAyOwogICAgICBhcmdzID0gW2hhbGZ0b25lUmVnaW9uLCBoZWFkZXIucmVmZXJyZWRUbywgZGF0YSwgcG9zaXRpb24sIGVuZF07CiAgICAgIGJyZWFrOwogICAgY2FzZSAzODoKICAgIGNhc2UgMzk6CiAgICAgIGNvbnN0IGdlbmVyaWNSZWdpb24gPSB7fTsKICAgICAgZ2VuZXJpY1JlZ2lvbi5pbmZvID0gcmVhZFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbihkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbkZpZWxkTGVuZ3RoOwogICAgICBjb25zdCBnZW5lcmljUmVnaW9uU2VnbWVudEZsYWdzID0gZGF0YVtwb3NpdGlvbisrXTsKICAgICAgZ2VuZXJpY1JlZ2lvbi5tbXIgPSAhIShnZW5lcmljUmVnaW9uU2VnbWVudEZsYWdzICYgMSk7CiAgICAgIGdlbmVyaWNSZWdpb24udGVtcGxhdGUgPSBnZW5lcmljUmVnaW9uU2VnbWVudEZsYWdzID4+IDEgJiAzOwogICAgICBnZW5lcmljUmVnaW9uLnByZWRpY3Rpb24gPSAhIShnZW5lcmljUmVnaW9uU2VnbWVudEZsYWdzICYgOCk7CiAgICAgIGlmICghZ2VuZXJpY1JlZ2lvbi5tbXIpIHsKICAgICAgICBhdExlbmd0aCA9IGdlbmVyaWNSZWdpb24udGVtcGxhdGUgPT09IDAgPyA0IDogMTsKICAgICAgICBhdCA9IFtdOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBhdExlbmd0aDsgaSsrKSB7CiAgICAgICAgICBhdC5wdXNoKHsKICAgICAgICAgICAgeDogKDAsIF9jb3JlX3V0aWxzLnJlYWRJbnQ4KShkYXRhLCBwb3NpdGlvbiksCiAgICAgICAgICAgIHk6ICgwLCBfY29yZV91dGlscy5yZWFkSW50OCkoZGF0YSwgcG9zaXRpb24gKyAxKQogICAgICAgICAgfSk7CiAgICAgICAgICBwb3NpdGlvbiArPSAyOwogICAgICAgIH0KICAgICAgICBnZW5lcmljUmVnaW9uLmF0ID0gYXQ7CiAgICAgIH0KICAgICAgYXJncyA9IFtnZW5lcmljUmVnaW9uLCBkYXRhLCBwb3NpdGlvbiwgZW5kXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDQ4OgogICAgICBjb25zdCBwYWdlSW5mbyA9IHsKICAgICAgICB3aWR0aDogKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uKSwKICAgICAgICBoZWlnaHQ6ICgwLCBfY29yZV91dGlscy5yZWFkVWludDMyKShkYXRhLCBwb3NpdGlvbiArIDQpLAogICAgICAgIHJlc29sdXRpb25YOiAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQzMikoZGF0YSwgcG9zaXRpb24gKyA4KSwKICAgICAgICByZXNvbHV0aW9uWTogKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uICsgMTIpCiAgICAgIH07CiAgICAgIGlmIChwYWdlSW5mby5oZWlnaHQgPT09IDB4ZmZmZmZmZmYpIHsKICAgICAgICBkZWxldGUgcGFnZUluZm8uaGVpZ2h0OwogICAgICB9CiAgICAgIGNvbnN0IHBhZ2VTZWdtZW50RmxhZ3MgPSBkYXRhW3Bvc2l0aW9uICsgMTZdOwogICAgICAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgcG9zaXRpb24gKyAxNyk7CiAgICAgIHBhZ2VJbmZvLmxvc3NsZXNzID0gISEocGFnZVNlZ21lbnRGbGFncyAmIDEpOwogICAgICBwYWdlSW5mby5yZWZpbmVtZW50ID0gISEocGFnZVNlZ21lbnRGbGFncyAmIDIpOwogICAgICBwYWdlSW5mby5kZWZhdWx0UGl4ZWxWYWx1ZSA9IHBhZ2VTZWdtZW50RmxhZ3MgPj4gMiAmIDE7CiAgICAgIHBhZ2VJbmZvLmNvbWJpbmF0aW9uT3BlcmF0b3IgPSBwYWdlU2VnbWVudEZsYWdzID4+IDMgJiAzOwogICAgICBwYWdlSW5mby5yZXF1aXJlc0J1ZmZlciA9ICEhKHBhZ2VTZWdtZW50RmxhZ3MgJiAzMik7CiAgICAgIHBhZ2VJbmZvLmNvbWJpbmF0aW9uT3BlcmF0b3JPdmVycmlkZSA9ICEhKHBhZ2VTZWdtZW50RmxhZ3MgJiA2NCk7CiAgICAgIGFyZ3MgPSBbcGFnZUluZm9dOwogICAgICBicmVhazsKICAgIGNhc2UgNDk6CiAgICAgIGJyZWFrOwogICAgY2FzZSA1MDoKICAgICAgYnJlYWs7CiAgICBjYXNlIDUxOgogICAgICBicmVhazsKICAgIGNhc2UgNTM6CiAgICAgIGFyZ3MgPSBbaGVhZGVyLm51bWJlciwgZGF0YSwgcG9zaXRpb24sIGVuZF07CiAgICAgIGJyZWFrOwogICAgY2FzZSA2MjoKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcihgc2VnbWVudCB0eXBlICR7aGVhZGVyLnR5cGVOYW1lfSgke2hlYWRlci50eXBlfSkgaXMgbm90IGltcGxlbWVudGVkYCk7CiAgfQogIGNvbnN0IGNhbGxiYWNrTmFtZSA9ICJvbiIgKyBoZWFkZXIudHlwZU5hbWU7CiAgaWYgKGNhbGxiYWNrTmFtZSBpbiB2aXNpdG9yKSB7CiAgICB2aXNpdG9yW2NhbGxiYWNrTmFtZV0uYXBwbHkodmlzaXRvciwgYXJncyk7CiAgfQp9CmZ1bmN0aW9uIHByb2Nlc3NTZWdtZW50cyhzZWdtZW50cywgdmlzaXRvcikgewogIGZvciAobGV0IGkgPSAwLCBpaSA9IHNlZ21lbnRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIHByb2Nlc3NTZWdtZW50KHNlZ21lbnRzW2ldLCB2aXNpdG9yKTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VKYmlnMkNodW5rcyhjaHVua3MpIHsKICBjb25zdCB2aXNpdG9yID0gbmV3IFNpbXBsZVNlZ21lbnRWaXNpdG9yKCk7CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gY2h1bmtzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IGNodW5rID0gY2h1bmtzW2ldOwogICAgY29uc3Qgc2VnbWVudHMgPSByZWFkU2VnbWVudHMoe30sIGNodW5rLmRhdGEsIGNodW5rLnN0YXJ0LCBjaHVuay5lbmQpOwogICAgcHJvY2Vzc1NlZ21lbnRzKHNlZ21lbnRzLCB2aXNpdG9yKTsKICB9CiAgcmV0dXJuIHZpc2l0b3IuYnVmZmVyOwp9CmZ1bmN0aW9uIHBhcnNlSmJpZzIoZGF0YSkgewogIHRocm93IG5ldyBFcnJvcigiTm90IGltcGxlbWVudGVkOiBwYXJzZUpiaWcyIik7Cn0KY2xhc3MgU2ltcGxlU2VnbWVudFZpc2l0b3IgewogIG9uUGFnZUluZm9ybWF0aW9uKGluZm8pIHsKICAgIHRoaXMuY3VycmVudFBhZ2VJbmZvID0gaW5mbzsKICAgIGNvbnN0IHJvd1NpemUgPSBpbmZvLndpZHRoICsgNyA+PiAzOwogICAgY29uc3QgYnVmZmVyID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHJvd1NpemUgKiBpbmZvLmhlaWdodCk7CiAgICBpZiAoaW5mby5kZWZhdWx0UGl4ZWxWYWx1ZSkgewogICAgICBidWZmZXIuZmlsbCgweGZmKTsKICAgIH0KICAgIHRoaXMuYnVmZmVyID0gYnVmZmVyOwogIH0KICBkcmF3Qml0bWFwKHJlZ2lvbkluZm8sIGJpdG1hcCkgewogICAgY29uc3QgcGFnZUluZm8gPSB0aGlzLmN1cnJlbnRQYWdlSW5mbzsKICAgIGNvbnN0IHdpZHRoID0gcmVnaW9uSW5mby53aWR0aCwKICAgICAgaGVpZ2h0ID0gcmVnaW9uSW5mby5oZWlnaHQ7CiAgICBjb25zdCByb3dTaXplID0gcGFnZUluZm8ud2lkdGggKyA3ID4+IDM7CiAgICBjb25zdCBjb21iaW5hdGlvbk9wZXJhdG9yID0gcGFnZUluZm8uY29tYmluYXRpb25PcGVyYXRvck92ZXJyaWRlID8gcmVnaW9uSW5mby5jb21iaW5hdGlvbk9wZXJhdG9yIDogcGFnZUluZm8uY29tYmluYXRpb25PcGVyYXRvcjsKICAgIGNvbnN0IGJ1ZmZlciA9IHRoaXMuYnVmZmVyOwogICAgY29uc3QgbWFzazAgPSAxMjggPj4gKHJlZ2lvbkluZm8ueCAmIDcpOwogICAgbGV0IG9mZnNldDAgPSByZWdpb25JbmZvLnkgKiByb3dTaXplICsgKHJlZ2lvbkluZm8ueCA+PiAzKTsKICAgIGxldCBpLCBqLCBtYXNrLCBvZmZzZXQ7CiAgICBzd2l0Y2ggKGNvbWJpbmF0aW9uT3BlcmF0b3IpIHsKICAgICAgY2FzZSAwOgogICAgICAgIGZvciAoaSA9IDA7IGkgPCBoZWlnaHQ7IGkrKykgewogICAgICAgICAgbWFzayA9IG1hc2swOwogICAgICAgICAgb2Zmc2V0ID0gb2Zmc2V0MDsKICAgICAgICAgIGZvciAoaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7CiAgICAgICAgICAgIGlmIChiaXRtYXBbaV1bal0pIHsKICAgICAgICAgICAgICBidWZmZXJbb2Zmc2V0XSB8PSBtYXNrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG1hc2sgPj49IDE7CiAgICAgICAgICAgIGlmICghbWFzaykgewogICAgICAgICAgICAgIG1hc2sgPSAxMjg7CiAgICAgICAgICAgICAgb2Zmc2V0Kys7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIG9mZnNldDAgKz0gcm93U2l6ZTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMjoKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgaGVpZ2h0OyBpKyspIHsKICAgICAgICAgIG1hc2sgPSBtYXNrMDsKICAgICAgICAgIG9mZnNldCA9IG9mZnNldDA7CiAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgd2lkdGg7IGorKykgewogICAgICAgICAgICBpZiAoYml0bWFwW2ldW2pdKSB7CiAgICAgICAgICAgICAgYnVmZmVyW29mZnNldF0gXj0gbWFzazsKICAgICAgICAgICAgfQogICAgICAgICAgICBtYXNrID4+PSAxOwogICAgICAgICAgICBpZiAoIW1hc2spIHsKICAgICAgICAgICAgICBtYXNrID0gMTI4OwogICAgICAgICAgICAgIG9mZnNldCsrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBvZmZzZXQwICs9IHJvd1NpemU7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKGBvcGVyYXRvciAke2NvbWJpbmF0aW9uT3BlcmF0b3J9IGlzIG5vdCBzdXBwb3J0ZWRgKTsKICAgIH0KICB9CiAgb25JbW1lZGlhdGVHZW5lcmljUmVnaW9uKHJlZ2lvbiwgZGF0YSwgc3RhcnQsIGVuZCkgewogICAgY29uc3QgcmVnaW9uSW5mbyA9IHJlZ2lvbi5pbmZvOwogICAgY29uc3QgZGVjb2RpbmdDb250ZXh0ID0gbmV3IERlY29kaW5nQ29udGV4dChkYXRhLCBzdGFydCwgZW5kKTsKICAgIGNvbnN0IGJpdG1hcCA9IGRlY29kZUJpdG1hcChyZWdpb24ubW1yLCByZWdpb25JbmZvLndpZHRoLCByZWdpb25JbmZvLmhlaWdodCwgcmVnaW9uLnRlbXBsYXRlLCByZWdpb24ucHJlZGljdGlvbiwgbnVsbCwgcmVnaW9uLmF0LCBkZWNvZGluZ0NvbnRleHQpOwogICAgdGhpcy5kcmF3Qml0bWFwKHJlZ2lvbkluZm8sIGJpdG1hcCk7CiAgfQogIG9uSW1tZWRpYXRlTG9zc2xlc3NHZW5lcmljUmVnaW9uKCkgewogICAgdGhpcy5vbkltbWVkaWF0ZUdlbmVyaWNSZWdpb24oLi4uYXJndW1lbnRzKTsKICB9CiAgb25TeW1ib2xEaWN0aW9uYXJ5KGRpY3Rpb25hcnksIGN1cnJlbnRTZWdtZW50LCByZWZlcnJlZFNlZ21lbnRzLCBkYXRhLCBzdGFydCwgZW5kKSB7CiAgICBsZXQgaHVmZm1hblRhYmxlcywgaHVmZm1hbklucHV0OwogICAgaWYgKGRpY3Rpb25hcnkuaHVmZm1hbikgewogICAgICBodWZmbWFuVGFibGVzID0gZ2V0U3ltYm9sRGljdGlvbmFyeUh1ZmZtYW5UYWJsZXMoZGljdGlvbmFyeSwgcmVmZXJyZWRTZWdtZW50cywgdGhpcy5jdXN0b21UYWJsZXMpOwogICAgICBodWZmbWFuSW5wdXQgPSBuZXcgUmVhZGVyKGRhdGEsIHN0YXJ0LCBlbmQpOwogICAgfQogICAgbGV0IHN5bWJvbHMgPSB0aGlzLnN5bWJvbHM7CiAgICBpZiAoIXN5bWJvbHMpIHsKICAgICAgdGhpcy5zeW1ib2xzID0gc3ltYm9scyA9IHt9OwogICAgfQogICAgY29uc3QgaW5wdXRTeW1ib2xzID0gW107CiAgICBmb3IgKGNvbnN0IHJlZmVycmVkU2VnbWVudCBvZiByZWZlcnJlZFNlZ21lbnRzKSB7CiAgICAgIGNvbnN0IHJlZmVycmVkU3ltYm9scyA9IHN5bWJvbHNbcmVmZXJyZWRTZWdtZW50XTsKICAgICAgaWYgKHJlZmVycmVkU3ltYm9scykgewogICAgICAgIGlucHV0U3ltYm9scy5wdXNoKC4uLnJlZmVycmVkU3ltYm9scyk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGRlY29kaW5nQ29udGV4dCA9IG5ldyBEZWNvZGluZ0NvbnRleHQoZGF0YSwgc3RhcnQsIGVuZCk7CiAgICBzeW1ib2xzW2N1cnJlbnRTZWdtZW50XSA9IGRlY29kZVN5bWJvbERpY3Rpb25hcnkoZGljdGlvbmFyeS5odWZmbWFuLCBkaWN0aW9uYXJ5LnJlZmluZW1lbnQsIGlucHV0U3ltYm9scywgZGljdGlvbmFyeS5udW1iZXJPZk5ld1N5bWJvbHMsIGRpY3Rpb25hcnkubnVtYmVyT2ZFeHBvcnRlZFN5bWJvbHMsIGh1ZmZtYW5UYWJsZXMsIGRpY3Rpb25hcnkudGVtcGxhdGUsIGRpY3Rpb25hcnkuYXQsIGRpY3Rpb25hcnkucmVmaW5lbWVudFRlbXBsYXRlLCBkaWN0aW9uYXJ5LnJlZmluZW1lbnRBdCwgZGVjb2RpbmdDb250ZXh0LCBodWZmbWFuSW5wdXQpOwogIH0KICBvbkltbWVkaWF0ZVRleHRSZWdpb24ocmVnaW9uLCByZWZlcnJlZFNlZ21lbnRzLCBkYXRhLCBzdGFydCwgZW5kKSB7CiAgICBjb25zdCByZWdpb25JbmZvID0gcmVnaW9uLmluZm87CiAgICBsZXQgaHVmZm1hblRhYmxlcywgaHVmZm1hbklucHV0OwogICAgY29uc3Qgc3ltYm9scyA9IHRoaXMuc3ltYm9sczsKICAgIGNvbnN0IGlucHV0U3ltYm9scyA9IFtdOwogICAgZm9yIChjb25zdCByZWZlcnJlZFNlZ21lbnQgb2YgcmVmZXJyZWRTZWdtZW50cykgewogICAgICBjb25zdCByZWZlcnJlZFN5bWJvbHMgPSBzeW1ib2xzW3JlZmVycmVkU2VnbWVudF07CiAgICAgIGlmIChyZWZlcnJlZFN5bWJvbHMpIHsKICAgICAgICBpbnB1dFN5bWJvbHMucHVzaCguLi5yZWZlcnJlZFN5bWJvbHMpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBzeW1ib2xDb2RlTGVuZ3RoID0gKDAsIF9jb3JlX3V0aWxzLmxvZzIpKGlucHV0U3ltYm9scy5sZW5ndGgpOwogICAgaWYgKHJlZ2lvbi5odWZmbWFuKSB7CiAgICAgIGh1ZmZtYW5JbnB1dCA9IG5ldyBSZWFkZXIoZGF0YSwgc3RhcnQsIGVuZCk7CiAgICAgIGh1ZmZtYW5UYWJsZXMgPSBnZXRUZXh0UmVnaW9uSHVmZm1hblRhYmxlcyhyZWdpb24sIHJlZmVycmVkU2VnbWVudHMsIHRoaXMuY3VzdG9tVGFibGVzLCBpbnB1dFN5bWJvbHMubGVuZ3RoLCBodWZmbWFuSW5wdXQpOwogICAgfQogICAgY29uc3QgZGVjb2RpbmdDb250ZXh0ID0gbmV3IERlY29kaW5nQ29udGV4dChkYXRhLCBzdGFydCwgZW5kKTsKICAgIGNvbnN0IGJpdG1hcCA9IGRlY29kZVRleHRSZWdpb24ocmVnaW9uLmh1ZmZtYW4sIHJlZ2lvbi5yZWZpbmVtZW50LCByZWdpb25JbmZvLndpZHRoLCByZWdpb25JbmZvLmhlaWdodCwgcmVnaW9uLmRlZmF1bHRQaXhlbFZhbHVlLCByZWdpb24ubnVtYmVyT2ZTeW1ib2xJbnN0YW5jZXMsIHJlZ2lvbi5zdHJpcFNpemUsIGlucHV0U3ltYm9scywgc3ltYm9sQ29kZUxlbmd0aCwgcmVnaW9uLnRyYW5zcG9zZWQsIHJlZ2lvbi5kc09mZnNldCwgcmVnaW9uLnJlZmVyZW5jZUNvcm5lciwgcmVnaW9uLmNvbWJpbmF0aW9uT3BlcmF0b3IsIGh1ZmZtYW5UYWJsZXMsIHJlZ2lvbi5yZWZpbmVtZW50VGVtcGxhdGUsIHJlZ2lvbi5yZWZpbmVtZW50QXQsIGRlY29kaW5nQ29udGV4dCwgcmVnaW9uLmxvZ1N0cmlwU2l6ZSwgaHVmZm1hbklucHV0KTsKICAgIHRoaXMuZHJhd0JpdG1hcChyZWdpb25JbmZvLCBiaXRtYXApOwogIH0KICBvbkltbWVkaWF0ZUxvc3NsZXNzVGV4dFJlZ2lvbigpIHsKICAgIHRoaXMub25JbW1lZGlhdGVUZXh0UmVnaW9uKC4uLmFyZ3VtZW50cyk7CiAgfQogIG9uUGF0dGVybkRpY3Rpb25hcnkoZGljdGlvbmFyeSwgY3VycmVudFNlZ21lbnQsIGRhdGEsIHN0YXJ0LCBlbmQpIHsKICAgIGxldCBwYXR0ZXJucyA9IHRoaXMucGF0dGVybnM7CiAgICBpZiAoIXBhdHRlcm5zKSB7CiAgICAgIHRoaXMucGF0dGVybnMgPSBwYXR0ZXJucyA9IHt9OwogICAgfQogICAgY29uc3QgZGVjb2RpbmdDb250ZXh0ID0gbmV3IERlY29kaW5nQ29udGV4dChkYXRhLCBzdGFydCwgZW5kKTsKICAgIHBhdHRlcm5zW2N1cnJlbnRTZWdtZW50XSA9IGRlY29kZVBhdHRlcm5EaWN0aW9uYXJ5KGRpY3Rpb25hcnkubW1yLCBkaWN0aW9uYXJ5LnBhdHRlcm5XaWR0aCwgZGljdGlvbmFyeS5wYXR0ZXJuSGVpZ2h0LCBkaWN0aW9uYXJ5Lm1heFBhdHRlcm5JbmRleCwgZGljdGlvbmFyeS50ZW1wbGF0ZSwgZGVjb2RpbmdDb250ZXh0KTsKICB9CiAgb25JbW1lZGlhdGVIYWxmdG9uZVJlZ2lvbihyZWdpb24sIHJlZmVycmVkU2VnbWVudHMsIGRhdGEsIHN0YXJ0LCBlbmQpIHsKICAgIGNvbnN0IHBhdHRlcm5zID0gdGhpcy5wYXR0ZXJuc1tyZWZlcnJlZFNlZ21lbnRzWzBdXTsKICAgIGNvbnN0IHJlZ2lvbkluZm8gPSByZWdpb24uaW5mbzsKICAgIGNvbnN0IGRlY29kaW5nQ29udGV4dCA9IG5ldyBEZWNvZGluZ0NvbnRleHQoZGF0YSwgc3RhcnQsIGVuZCk7CiAgICBjb25zdCBiaXRtYXAgPSBkZWNvZGVIYWxmdG9uZVJlZ2lvbihyZWdpb24ubW1yLCBwYXR0ZXJucywgcmVnaW9uLnRlbXBsYXRlLCByZWdpb25JbmZvLndpZHRoLCByZWdpb25JbmZvLmhlaWdodCwgcmVnaW9uLmRlZmF1bHRQaXhlbFZhbHVlLCByZWdpb24uZW5hYmxlU2tpcCwgcmVnaW9uLmNvbWJpbmF0aW9uT3BlcmF0b3IsIHJlZ2lvbi5ncmlkV2lkdGgsIHJlZ2lvbi5ncmlkSGVpZ2h0LCByZWdpb24uZ3JpZE9mZnNldFgsIHJlZ2lvbi5ncmlkT2Zmc2V0WSwgcmVnaW9uLmdyaWRWZWN0b3JYLCByZWdpb24uZ3JpZFZlY3RvclksIGRlY29kaW5nQ29udGV4dCk7CiAgICB0aGlzLmRyYXdCaXRtYXAocmVnaW9uSW5mbywgYml0bWFwKTsKICB9CiAgb25JbW1lZGlhdGVMb3NzbGVzc0hhbGZ0b25lUmVnaW9uKCkgewogICAgdGhpcy5vbkltbWVkaWF0ZUhhbGZ0b25lUmVnaW9uKC4uLmFyZ3VtZW50cyk7CiAgfQogIG9uVGFibGVzKGN1cnJlbnRTZWdtZW50LCBkYXRhLCBzdGFydCwgZW5kKSB7CiAgICBsZXQgY3VzdG9tVGFibGVzID0gdGhpcy5jdXN0b21UYWJsZXM7CiAgICBpZiAoIWN1c3RvbVRhYmxlcykgewogICAgICB0aGlzLmN1c3RvbVRhYmxlcyA9IGN1c3RvbVRhYmxlcyA9IHt9OwogICAgfQogICAgY3VzdG9tVGFibGVzW2N1cnJlbnRTZWdtZW50XSA9IGRlY29kZVRhYmxlc1NlZ21lbnQoZGF0YSwgc3RhcnQsIGVuZCk7CiAgfQp9CmNsYXNzIEh1ZmZtYW5MaW5lIHsKICBjb25zdHJ1Y3RvcihsaW5lRGF0YSkgewogICAgaWYgKGxpbmVEYXRhLmxlbmd0aCA9PT0gMikgewogICAgICB0aGlzLmlzT09CID0gdHJ1ZTsKICAgICAgdGhpcy5yYW5nZUxvdyA9IDA7CiAgICAgIHRoaXMucHJlZml4TGVuZ3RoID0gbGluZURhdGFbMF07CiAgICAgIHRoaXMucmFuZ2VMZW5ndGggPSAwOwogICAgICB0aGlzLnByZWZpeENvZGUgPSBsaW5lRGF0YVsxXTsKICAgICAgdGhpcy5pc0xvd2VyUmFuZ2UgPSBmYWxzZTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuaXNPT0IgPSBmYWxzZTsKICAgICAgdGhpcy5yYW5nZUxvdyA9IGxpbmVEYXRhWzBdOwogICAgICB0aGlzLnByZWZpeExlbmd0aCA9IGxpbmVEYXRhWzFdOwogICAgICB0aGlzLnJhbmdlTGVuZ3RoID0gbGluZURhdGFbMl07CiAgICAgIHRoaXMucHJlZml4Q29kZSA9IGxpbmVEYXRhWzNdOwogICAgICB0aGlzLmlzTG93ZXJSYW5nZSA9IGxpbmVEYXRhWzRdID09PSAibG93ZXIiOwogICAgfQogIH0KfQpjbGFzcyBIdWZmbWFuVHJlZU5vZGUgewogIGNvbnN0cnVjdG9yKGxpbmUpIHsKICAgIHRoaXMuY2hpbGRyZW4gPSBbXTsKICAgIGlmIChsaW5lKSB7CiAgICAgIHRoaXMuaXNMZWFmID0gdHJ1ZTsKICAgICAgdGhpcy5yYW5nZUxlbmd0aCA9IGxpbmUucmFuZ2VMZW5ndGg7CiAgICAgIHRoaXMucmFuZ2VMb3cgPSBsaW5lLnJhbmdlTG93OwogICAgICB0aGlzLmlzTG93ZXJSYW5nZSA9IGxpbmUuaXNMb3dlclJhbmdlOwogICAgICB0aGlzLmlzT09CID0gbGluZS5pc09PQjsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuaXNMZWFmID0gZmFsc2U7CiAgICB9CiAgfQogIGJ1aWxkVHJlZShsaW5lLCBzaGlmdCkgewogICAgY29uc3QgYml0ID0gbGluZS5wcmVmaXhDb2RlID4+IHNoaWZ0ICYgMTsKICAgIGlmIChzaGlmdCA8PSAwKSB7CiAgICAgIHRoaXMuY2hpbGRyZW5bYml0XSA9IG5ldyBIdWZmbWFuVHJlZU5vZGUobGluZSk7CiAgICB9IGVsc2UgewogICAgICBsZXQgbm9kZSA9IHRoaXMuY2hpbGRyZW5bYml0XTsKICAgICAgaWYgKCFub2RlKSB7CiAgICAgICAgdGhpcy5jaGlsZHJlbltiaXRdID0gbm9kZSA9IG5ldyBIdWZmbWFuVHJlZU5vZGUobnVsbCk7CiAgICAgIH0KICAgICAgbm9kZS5idWlsZFRyZWUobGluZSwgc2hpZnQgLSAxKTsKICAgIH0KICB9CiAgZGVjb2RlTm9kZShyZWFkZXIpIHsKICAgIGlmICh0aGlzLmlzTGVhZikgewogICAgICBpZiAodGhpcy5pc09PQikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IGh0T2Zmc2V0ID0gcmVhZGVyLnJlYWRCaXRzKHRoaXMucmFuZ2VMZW5ndGgpOwogICAgICByZXR1cm4gdGhpcy5yYW5nZUxvdyArICh0aGlzLmlzTG93ZXJSYW5nZSA/IC1odE9mZnNldCA6IGh0T2Zmc2V0KTsKICAgIH0KICAgIGNvbnN0IG5vZGUgPSB0aGlzLmNoaWxkcmVuW3JlYWRlci5yZWFkQml0KCldOwogICAgaWYgKCFub2RlKSB7CiAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJpbnZhbGlkIEh1ZmZtYW4gZGF0YSIpOwogICAgfQogICAgcmV0dXJuIG5vZGUuZGVjb2RlTm9kZShyZWFkZXIpOwogIH0KfQpjbGFzcyBIdWZmbWFuVGFibGUgewogIGNvbnN0cnVjdG9yKGxpbmVzLCBwcmVmaXhDb2Rlc0RvbmUpIHsKICAgIGlmICghcHJlZml4Q29kZXNEb25lKSB7CiAgICAgIHRoaXMuYXNzaWduUHJlZml4Q29kZXMobGluZXMpOwogICAgfQogICAgdGhpcy5yb290Tm9kZSA9IG5ldyBIdWZmbWFuVHJlZU5vZGUobnVsbCk7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBsaW5lcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IGxpbmUgPSBsaW5lc1tpXTsKICAgICAgaWYgKGxpbmUucHJlZml4TGVuZ3RoID4gMCkgewogICAgICAgIHRoaXMucm9vdE5vZGUuYnVpbGRUcmVlKGxpbmUsIGxpbmUucHJlZml4TGVuZ3RoIC0gMSk7CiAgICAgIH0KICAgIH0KICB9CiAgZGVjb2RlKHJlYWRlcikgewogICAgcmV0dXJuIHRoaXMucm9vdE5vZGUuZGVjb2RlTm9kZShyZWFkZXIpOwogIH0KICBhc3NpZ25QcmVmaXhDb2RlcyhsaW5lcykgewogICAgY29uc3QgbGluZXNMZW5ndGggPSBsaW5lcy5sZW5ndGg7CiAgICBsZXQgcHJlZml4TGVuZ3RoTWF4ID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGluZXNMZW5ndGg7IGkrKykgewogICAgICBwcmVmaXhMZW5ndGhNYXggPSBNYXRoLm1heChwcmVmaXhMZW5ndGhNYXgsIGxpbmVzW2ldLnByZWZpeExlbmd0aCk7CiAgICB9CiAgICBjb25zdCBoaXN0b2dyYW0gPSBuZXcgVWludDMyQXJyYXkocHJlZml4TGVuZ3RoTWF4ICsgMSk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzTGVuZ3RoOyBpKyspIHsKICAgICAgaGlzdG9ncmFtW2xpbmVzW2ldLnByZWZpeExlbmd0aF0rKzsKICAgIH0KICAgIGxldCBjdXJyZW50TGVuZ3RoID0gMSwKICAgICAgZmlyc3RDb2RlID0gMCwKICAgICAgY3VycmVudENvZGUsCiAgICAgIGN1cnJlbnRUZW1wLAogICAgICBsaW5lOwogICAgaGlzdG9ncmFtWzBdID0gMDsKICAgIHdoaWxlIChjdXJyZW50TGVuZ3RoIDw9IHByZWZpeExlbmd0aE1heCkgewogICAgICBmaXJzdENvZGUgPSBmaXJzdENvZGUgKyBoaXN0b2dyYW1bY3VycmVudExlbmd0aCAtIDFdIDw8IDE7CiAgICAgIGN1cnJlbnRDb2RlID0gZmlyc3RDb2RlOwogICAgICBjdXJyZW50VGVtcCA9IDA7CiAgICAgIHdoaWxlIChjdXJyZW50VGVtcCA8IGxpbmVzTGVuZ3RoKSB7CiAgICAgICAgbGluZSA9IGxpbmVzW2N1cnJlbnRUZW1wXTsKICAgICAgICBpZiAobGluZS5wcmVmaXhMZW5ndGggPT09IGN1cnJlbnRMZW5ndGgpIHsKICAgICAgICAgIGxpbmUucHJlZml4Q29kZSA9IGN1cnJlbnRDb2RlOwogICAgICAgICAgY3VycmVudENvZGUrKzsKICAgICAgICB9CiAgICAgICAgY3VycmVudFRlbXArKzsKICAgICAgfQogICAgICBjdXJyZW50TGVuZ3RoKys7CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGRlY29kZVRhYmxlc1NlZ21lbnQoZGF0YSwgc3RhcnQsIGVuZCkgewogIGNvbnN0IGZsYWdzID0gZGF0YVtzdGFydF07CiAgY29uc3QgbG93ZXN0VmFsdWUgPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQzMikoZGF0YSwgc3RhcnQgKyAxKSAmIDB4ZmZmZmZmZmY7CiAgY29uc3QgaGlnaGVzdFZhbHVlID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHN0YXJ0ICsgNSkgJiAweGZmZmZmZmZmOwogIGNvbnN0IHJlYWRlciA9IG5ldyBSZWFkZXIoZGF0YSwgc3RhcnQgKyA5LCBlbmQpOwogIGNvbnN0IHByZWZpeFNpemVCaXRzID0gKGZsYWdzID4+IDEgJiA3KSArIDE7CiAgY29uc3QgcmFuZ2VTaXplQml0cyA9IChmbGFncyA+PiA0ICYgNykgKyAxOwogIGNvbnN0IGxpbmVzID0gW107CiAgbGV0IHByZWZpeExlbmd0aCwKICAgIHJhbmdlTGVuZ3RoLAogICAgY3VycmVudFJhbmdlTG93ID0gbG93ZXN0VmFsdWU7CiAgZG8gewogICAgcHJlZml4TGVuZ3RoID0gcmVhZGVyLnJlYWRCaXRzKHByZWZpeFNpemVCaXRzKTsKICAgIHJhbmdlTGVuZ3RoID0gcmVhZGVyLnJlYWRCaXRzKHJhbmdlU2l6ZUJpdHMpOwogICAgbGluZXMucHVzaChuZXcgSHVmZm1hbkxpbmUoW2N1cnJlbnRSYW5nZUxvdywgcHJlZml4TGVuZ3RoLCByYW5nZUxlbmd0aCwgMF0pKTsKICAgIGN1cnJlbnRSYW5nZUxvdyArPSAxIDw8IHJhbmdlTGVuZ3RoOwogIH0gd2hpbGUgKGN1cnJlbnRSYW5nZUxvdyA8IGhpZ2hlc3RWYWx1ZSk7CiAgcHJlZml4TGVuZ3RoID0gcmVhZGVyLnJlYWRCaXRzKHByZWZpeFNpemVCaXRzKTsKICBsaW5lcy5wdXNoKG5ldyBIdWZmbWFuTGluZShbbG93ZXN0VmFsdWUgLSAxLCBwcmVmaXhMZW5ndGgsIDMyLCAwLCAibG93ZXIiXSkpOwogIHByZWZpeExlbmd0aCA9IHJlYWRlci5yZWFkQml0cyhwcmVmaXhTaXplQml0cyk7CiAgbGluZXMucHVzaChuZXcgSHVmZm1hbkxpbmUoW2hpZ2hlc3RWYWx1ZSwgcHJlZml4TGVuZ3RoLCAzMiwgMF0pKTsKICBpZiAoZmxhZ3MgJiAxKSB7CiAgICBwcmVmaXhMZW5ndGggPSByZWFkZXIucmVhZEJpdHMocHJlZml4U2l6ZUJpdHMpOwogICAgbGluZXMucHVzaChuZXcgSHVmZm1hbkxpbmUoW3ByZWZpeExlbmd0aCwgMF0pKTsKICB9CiAgcmV0dXJuIG5ldyBIdWZmbWFuVGFibGUobGluZXMsIGZhbHNlKTsKfQpjb25zdCBzdGFuZGFyZFRhYmxlc0NhY2hlID0ge307CmZ1bmN0aW9uIGdldFN0YW5kYXJkVGFibGUobnVtYmVyKSB7CiAgbGV0IHRhYmxlID0gc3RhbmRhcmRUYWJsZXNDYWNoZVtudW1iZXJdOwogIGlmICh0YWJsZSkgewogICAgcmV0dXJuIHRhYmxlOwogIH0KICBsZXQgbGluZXM7CiAgc3dpdGNoIChudW1iZXIpIHsKICAgIGNhc2UgMToKICAgICAgbGluZXMgPSBbWzAsIDEsIDQsIDB4MF0sIFsxNiwgMiwgOCwgMHgyXSwgWzI3MiwgMywgMTYsIDB4Nl0sIFs2NTgwOCwgMywgMzIsIDB4N11dOwogICAgICBicmVhazsKICAgIGNhc2UgMjoKICAgICAgbGluZXMgPSBbWzAsIDEsIDAsIDB4MF0sIFsxLCAyLCAwLCAweDJdLCBbMiwgMywgMCwgMHg2XSwgWzMsIDQsIDMsIDB4ZV0sIFsxMSwgNSwgNiwgMHgxZV0sIFs3NSwgNiwgMzIsIDB4M2VdLCBbNiwgMHgzZl1dOwogICAgICBicmVhazsKICAgIGNhc2UgMzoKICAgICAgbGluZXMgPSBbWy0yNTYsIDgsIDgsIDB4ZmVdLCBbMCwgMSwgMCwgMHgwXSwgWzEsIDIsIDAsIDB4Ml0sIFsyLCAzLCAwLCAweDZdLCBbMywgNCwgMywgMHhlXSwgWzExLCA1LCA2LCAweDFlXSwgWy0yNTcsIDgsIDMyLCAweGZmLCAibG93ZXIiXSwgWzc1LCA3LCAzMiwgMHg3ZV0sIFs2LCAweDNlXV07CiAgICAgIGJyZWFrOwogICAgY2FzZSA0OgogICAgICBsaW5lcyA9IFtbMSwgMSwgMCwgMHgwXSwgWzIsIDIsIDAsIDB4Ml0sIFszLCAzLCAwLCAweDZdLCBbNCwgNCwgMywgMHhlXSwgWzEyLCA1LCA2LCAweDFlXSwgWzc2LCA1LCAzMiwgMHgxZl1dOwogICAgICBicmVhazsKICAgIGNhc2UgNToKICAgICAgbGluZXMgPSBbWy0yNTUsIDcsIDgsIDB4N2VdLCBbMSwgMSwgMCwgMHgwXSwgWzIsIDIsIDAsIDB4Ml0sIFszLCAzLCAwLCAweDZdLCBbNCwgNCwgMywgMHhlXSwgWzEyLCA1LCA2LCAweDFlXSwgWy0yNTYsIDcsIDMyLCAweDdmLCAibG93ZXIiXSwgWzc2LCA2LCAzMiwgMHgzZV1dOwogICAgICBicmVhazsKICAgIGNhc2UgNjoKICAgICAgbGluZXMgPSBbWy0yMDQ4LCA1LCAxMCwgMHgxY10sIFstMTAyNCwgNCwgOSwgMHg4XSwgWy01MTIsIDQsIDgsIDB4OV0sIFstMjU2LCA0LCA3LCAweGFdLCBbLTEyOCwgNSwgNiwgMHgxZF0sIFstNjQsIDUsIDUsIDB4MWVdLCBbLTMyLCA0LCA1LCAweGJdLCBbMCwgMiwgNywgMHgwXSwgWzEyOCwgMywgNywgMHgyXSwgWzI1NiwgMywgOCwgMHgzXSwgWzUxMiwgNCwgOSwgMHhjXSwgWzEwMjQsIDQsIDEwLCAweGRdLCBbLTIwNDksIDYsIDMyLCAweDNlLCAibG93ZXIiXSwgWzIwNDgsIDYsIDMyLCAweDNmXV07CiAgICAgIGJyZWFrOwogICAgY2FzZSA3OgogICAgICBsaW5lcyA9IFtbLTEwMjQsIDQsIDksIDB4OF0sIFstNTEyLCAzLCA4LCAweDBdLCBbLTI1NiwgNCwgNywgMHg5XSwgWy0xMjgsIDUsIDYsIDB4MWFdLCBbLTY0LCA1LCA1LCAweDFiXSwgWy0zMiwgNCwgNSwgMHhhXSwgWzAsIDQsIDUsIDB4Yl0sIFszMiwgNSwgNSwgMHgxY10sIFs2NCwgNSwgNiwgMHgxZF0sIFsxMjgsIDQsIDcsIDB4Y10sIFsyNTYsIDMsIDgsIDB4MV0sIFs1MTIsIDMsIDksIDB4Ml0sIFsxMDI0LCAzLCAxMCwgMHgzXSwgWy0xMDI1LCA1LCAzMiwgMHgxZSwgImxvd2VyIl0sIFsyMDQ4LCA1LCAzMiwgMHgxZl1dOwogICAgICBicmVhazsKICAgIGNhc2UgODoKICAgICAgbGluZXMgPSBbWy0xNSwgOCwgMywgMHhmY10sIFstNywgOSwgMSwgMHgxZmNdLCBbLTUsIDgsIDEsIDB4ZmRdLCBbLTMsIDksIDAsIDB4MWZkXSwgWy0yLCA3LCAwLCAweDdjXSwgWy0xLCA0LCAwLCAweGFdLCBbMCwgMiwgMSwgMHgwXSwgWzIsIDUsIDAsIDB4MWFdLCBbMywgNiwgMCwgMHgzYV0sIFs0LCAzLCA0LCAweDRdLCBbMjAsIDYsIDEsIDB4M2JdLCBbMjIsIDQsIDQsIDB4Yl0sIFszOCwgNCwgNSwgMHhjXSwgWzcwLCA1LCA2LCAweDFiXSwgWzEzNCwgNSwgNywgMHgxY10sIFsyNjIsIDYsIDcsIDB4M2NdLCBbMzkwLCA3LCA4LCAweDdkXSwgWzY0NiwgNiwgMTAsIDB4M2RdLCBbLTE2LCA5LCAzMiwgMHgxZmUsICJsb3dlciJdLCBbMTY3MCwgOSwgMzIsIDB4MWZmXSwgWzIsIDB4MV1dOwogICAgICBicmVhazsKICAgIGNhc2UgOToKICAgICAgbGluZXMgPSBbWy0zMSwgOCwgNCwgMHhmY10sIFstMTUsIDksIDIsIDB4MWZjXSwgWy0xMSwgOCwgMiwgMHhmZF0sIFstNywgOSwgMSwgMHgxZmRdLCBbLTUsIDcsIDEsIDB4N2NdLCBbLTMsIDQsIDEsIDB4YV0sIFstMSwgMywgMSwgMHgyXSwgWzEsIDMsIDEsIDB4M10sIFszLCA1LCAxLCAweDFhXSwgWzUsIDYsIDEsIDB4M2FdLCBbNywgMywgNSwgMHg0XSwgWzM5LCA2LCAyLCAweDNiXSwgWzQzLCA0LCA1LCAweGJdLCBbNzUsIDQsIDYsIDB4Y10sIFsxMzksIDUsIDcsIDB4MWJdLCBbMjY3LCA1LCA4LCAweDFjXSwgWzUyMywgNiwgOCwgMHgzY10sIFs3NzksIDcsIDksIDB4N2RdLCBbMTI5MSwgNiwgMTEsIDB4M2RdLCBbLTMyLCA5LCAzMiwgMHgxZmUsICJsb3dlciJdLCBbMzMzOSwgOSwgMzIsIDB4MWZmXSwgWzIsIDB4MF1dOwogICAgICBicmVhazsKICAgIGNhc2UgMTA6CiAgICAgIGxpbmVzID0gW1stMjEsIDcsIDQsIDB4N2FdLCBbLTUsIDgsIDAsIDB4ZmNdLCBbLTQsIDcsIDAsIDB4N2JdLCBbLTMsIDUsIDAsIDB4MThdLCBbLTIsIDIsIDIsIDB4MF0sIFsyLCA1LCAwLCAweDE5XSwgWzMsIDYsIDAsIDB4MzZdLCBbNCwgNywgMCwgMHg3Y10sIFs1LCA4LCAwLCAweGZkXSwgWzYsIDIsIDYsIDB4MV0sIFs3MCwgNSwgNSwgMHgxYV0sIFsxMDIsIDYsIDUsIDB4MzddLCBbMTM0LCA2LCA2LCAweDM4XSwgWzE5OCwgNiwgNywgMHgzOV0sIFszMjYsIDYsIDgsIDB4M2FdLCBbNTgyLCA2LCA5LCAweDNiXSwgWzEwOTQsIDYsIDEwLCAweDNjXSwgWzIxMTgsIDcsIDExLCAweDdkXSwgWy0yMiwgOCwgMzIsIDB4ZmUsICJsb3dlciJdLCBbNDE2NiwgOCwgMzIsIDB4ZmZdLCBbMiwgMHgyXV07CiAgICAgIGJyZWFrOwogICAgY2FzZSAxMToKICAgICAgbGluZXMgPSBbWzEsIDEsIDAsIDB4MF0sIFsyLCAyLCAxLCAweDJdLCBbNCwgNCwgMCwgMHhjXSwgWzUsIDQsIDEsIDB4ZF0sIFs3LCA1LCAxLCAweDFjXSwgWzksIDUsIDIsIDB4MWRdLCBbMTMsIDYsIDIsIDB4M2NdLCBbMTcsIDcsIDIsIDB4N2FdLCBbMjEsIDcsIDMsIDB4N2JdLCBbMjksIDcsIDQsIDB4N2NdLCBbNDUsIDcsIDUsIDB4N2RdLCBbNzcsIDcsIDYsIDB4N2VdLCBbMTQxLCA3LCAzMiwgMHg3Zl1dOwogICAgICBicmVhazsKICAgIGNhc2UgMTI6CiAgICAgIGxpbmVzID0gW1sxLCAxLCAwLCAweDBdLCBbMiwgMiwgMCwgMHgyXSwgWzMsIDMsIDEsIDB4Nl0sIFs1LCA1LCAwLCAweDFjXSwgWzYsIDUsIDEsIDB4MWRdLCBbOCwgNiwgMSwgMHgzY10sIFsxMCwgNywgMCwgMHg3YV0sIFsxMSwgNywgMSwgMHg3Yl0sIFsxMywgNywgMiwgMHg3Y10sIFsxNywgNywgMywgMHg3ZF0sIFsyNSwgNywgNCwgMHg3ZV0sIFs0MSwgOCwgNSwgMHhmZV0sIFs3MywgOCwgMzIsIDB4ZmZdXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDEzOgogICAgICBsaW5lcyA9IFtbMSwgMSwgMCwgMHgwXSwgWzIsIDMsIDAsIDB4NF0sIFszLCA0LCAwLCAweGNdLCBbNCwgNSwgMCwgMHgxY10sIFs1LCA0LCAxLCAweGRdLCBbNywgMywgMywgMHg1XSwgWzE1LCA2LCAxLCAweDNhXSwgWzE3LCA2LCAyLCAweDNiXSwgWzIxLCA2LCAzLCAweDNjXSwgWzI5LCA2LCA0LCAweDNkXSwgWzQ1LCA2LCA1LCAweDNlXSwgWzc3LCA3LCA2LCAweDdlXSwgWzE0MSwgNywgMzIsIDB4N2ZdXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDE0OgogICAgICBsaW5lcyA9IFtbLTIsIDMsIDAsIDB4NF0sIFstMSwgMywgMCwgMHg1XSwgWzAsIDEsIDAsIDB4MF0sIFsxLCAzLCAwLCAweDZdLCBbMiwgMywgMCwgMHg3XV07CiAgICAgIGJyZWFrOwogICAgY2FzZSAxNToKICAgICAgbGluZXMgPSBbWy0yNCwgNywgNCwgMHg3Y10sIFstOCwgNiwgMiwgMHgzY10sIFstNCwgNSwgMSwgMHgxY10sIFstMiwgNCwgMCwgMHhjXSwgWy0xLCAzLCAwLCAweDRdLCBbMCwgMSwgMCwgMHgwXSwgWzEsIDMsIDAsIDB4NV0sIFsyLCA0LCAwLCAweGRdLCBbMywgNSwgMSwgMHgxZF0sIFs1LCA2LCAyLCAweDNkXSwgWzksIDcsIDQsIDB4N2RdLCBbLTI1LCA3LCAzMiwgMHg3ZSwgImxvd2VyIl0sIFsyNSwgNywgMzIsIDB4N2ZdXTsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcihgc3RhbmRhcmQgdGFibGUgQi4ke251bWJlcn0gZG9lcyBub3QgZXhpc3RgKTsKICB9CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gbGluZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgbGluZXNbaV0gPSBuZXcgSHVmZm1hbkxpbmUobGluZXNbaV0pOwogIH0KICB0YWJsZSA9IG5ldyBIdWZmbWFuVGFibGUobGluZXMsIHRydWUpOwogIHN0YW5kYXJkVGFibGVzQ2FjaGVbbnVtYmVyXSA9IHRhYmxlOwogIHJldHVybiB0YWJsZTsKfQpjbGFzcyBSZWFkZXIgewogIGNvbnN0cnVjdG9yKGRhdGEsIHN0YXJ0LCBlbmQpIHsKICAgIHRoaXMuZGF0YSA9IGRhdGE7CiAgICB0aGlzLnN0YXJ0ID0gc3RhcnQ7CiAgICB0aGlzLmVuZCA9IGVuZDsKICAgIHRoaXMucG9zaXRpb24gPSBzdGFydDsKICAgIHRoaXMuc2hpZnQgPSAtMTsKICAgIHRoaXMuY3VycmVudEJ5dGUgPSAwOwogIH0KICByZWFkQml0KCkgewogICAgaWYgKHRoaXMuc2hpZnQgPCAwKSB7CiAgICAgIGlmICh0aGlzLnBvc2l0aW9uID49IHRoaXMuZW5kKSB7CiAgICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImVuZCBvZiBkYXRhIHdoaWxlIHJlYWRpbmcgYml0Iik7CiAgICAgIH0KICAgICAgdGhpcy5jdXJyZW50Qnl0ZSA9IHRoaXMuZGF0YVt0aGlzLnBvc2l0aW9uKytdOwogICAgICB0aGlzLnNoaWZ0ID0gNzsKICAgIH0KICAgIGNvbnN0IGJpdCA9IHRoaXMuY3VycmVudEJ5dGUgPj4gdGhpcy5zaGlmdCAmIDE7CiAgICB0aGlzLnNoaWZ0LS07CiAgICByZXR1cm4gYml0OwogIH0KICByZWFkQml0cyhudW1CaXRzKSB7CiAgICBsZXQgcmVzdWx0ID0gMCwKICAgICAgaTsKICAgIGZvciAoaSA9IG51bUJpdHMgLSAxOyBpID49IDA7IGktLSkgewogICAgICByZXN1bHQgfD0gdGhpcy5yZWFkQml0KCkgPDwgaTsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQogIGJ5dGVBbGlnbigpIHsKICAgIHRoaXMuc2hpZnQgPSAtMTsKICB9CiAgbmV4dCgpIHsKICAgIGlmICh0aGlzLnBvc2l0aW9uID49IHRoaXMuZW5kKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIHJldHVybiB0aGlzLmRhdGFbdGhpcy5wb3NpdGlvbisrXTsKICB9Cn0KZnVuY3Rpb24gZ2V0Q3VzdG9tSHVmZm1hblRhYmxlKGluZGV4LCByZWZlcnJlZFRvLCBjdXN0b21UYWJsZXMpIHsKICBsZXQgY3VycmVudEluZGV4ID0gMDsKICBmb3IgKGxldCBpID0gMCwgaWkgPSByZWZlcnJlZFRvLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IHRhYmxlID0gY3VzdG9tVGFibGVzW3JlZmVycmVkVG9baV1dOwogICAgaWYgKHRhYmxlKSB7CiAgICAgIGlmIChpbmRleCA9PT0gY3VycmVudEluZGV4KSB7CiAgICAgICAgcmV0dXJuIHRhYmxlOwogICAgICB9CiAgICAgIGN1cnJlbnRJbmRleCsrOwogICAgfQogIH0KICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiY2FuJ3QgZmluZCBjdXN0b20gSHVmZm1hbiB0YWJsZSIpOwp9CmZ1bmN0aW9uIGdldFRleHRSZWdpb25IdWZmbWFuVGFibGVzKHRleHRSZWdpb24sIHJlZmVycmVkVG8sIGN1c3RvbVRhYmxlcywgbnVtYmVyT2ZTeW1ib2xzLCByZWFkZXIpIHsKICBjb25zdCBjb2RlcyA9IFtdOwogIGZvciAobGV0IGkgPSAwOyBpIDw9IDM0OyBpKyspIHsKICAgIGNvbnN0IGNvZGVMZW5ndGggPSByZWFkZXIucmVhZEJpdHMoNCk7CiAgICBjb2Rlcy5wdXNoKG5ldyBIdWZmbWFuTGluZShbaSwgY29kZUxlbmd0aCwgMCwgMF0pKTsKICB9CiAgY29uc3QgcnVuQ29kZXNUYWJsZSA9IG5ldyBIdWZmbWFuVGFibGUoY29kZXMsIGZhbHNlKTsKICBjb2Rlcy5sZW5ndGggPSAwOwogIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZTeW1ib2xzOykgewogICAgY29uc3QgY29kZUxlbmd0aCA9IHJ1bkNvZGVzVGFibGUuZGVjb2RlKHJlYWRlcik7CiAgICBpZiAoY29kZUxlbmd0aCA+PSAzMikgewogICAgICBsZXQgcmVwZWF0ZWRMZW5ndGgsIG51bWJlck9mUmVwZWF0cywgajsKICAgICAgc3dpdGNoIChjb2RlTGVuZ3RoKSB7CiAgICAgICAgY2FzZSAzMjoKICAgICAgICAgIGlmIChpID09PSAwKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJubyBwcmV2aW91cyB2YWx1ZSBpbiBzeW1ib2wgSUQgdGFibGUiKTsKICAgICAgICAgIH0KICAgICAgICAgIG51bWJlck9mUmVwZWF0cyA9IHJlYWRlci5yZWFkQml0cygyKSArIDM7CiAgICAgICAgICByZXBlYXRlZExlbmd0aCA9IGNvZGVzW2kgLSAxXS5wcmVmaXhMZW5ndGg7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDMzOgogICAgICAgICAgbnVtYmVyT2ZSZXBlYXRzID0gcmVhZGVyLnJlYWRCaXRzKDMpICsgMzsKICAgICAgICAgIHJlcGVhdGVkTGVuZ3RoID0gMDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzQ6CiAgICAgICAgICBudW1iZXJPZlJlcGVhdHMgPSByZWFkZXIucmVhZEJpdHMoNykgKyAxMTsKICAgICAgICAgIHJlcGVhdGVkTGVuZ3RoID0gMDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCBjb2RlIGxlbmd0aCBpbiBzeW1ib2wgSUQgdGFibGUiKTsKICAgICAgfQogICAgICBmb3IgKGogPSAwOyBqIDwgbnVtYmVyT2ZSZXBlYXRzOyBqKyspIHsKICAgICAgICBjb2Rlcy5wdXNoKG5ldyBIdWZmbWFuTGluZShbaSwgcmVwZWF0ZWRMZW5ndGgsIDAsIDBdKSk7CiAgICAgICAgaSsrOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb2Rlcy5wdXNoKG5ldyBIdWZmbWFuTGluZShbaSwgY29kZUxlbmd0aCwgMCwgMF0pKTsKICAgICAgaSsrOwogICAgfQogIH0KICByZWFkZXIuYnl0ZUFsaWduKCk7CiAgY29uc3Qgc3ltYm9sSURUYWJsZSA9IG5ldyBIdWZmbWFuVGFibGUoY29kZXMsIGZhbHNlKTsKICBsZXQgY3VzdG9tSW5kZXggPSAwLAogICAgdGFibGVGaXJzdFMsCiAgICB0YWJsZURlbHRhUywKICAgIHRhYmxlRGVsdGFUOwogIHN3aXRjaCAodGV4dFJlZ2lvbi5odWZmbWFuRlMpIHsKICAgIGNhc2UgMDoKICAgIGNhc2UgMToKICAgICAgdGFibGVGaXJzdFMgPSBnZXRTdGFuZGFyZFRhYmxlKHRleHRSZWdpb24uaHVmZm1hbkZTICsgNik7CiAgICAgIGJyZWFrOwogICAgY2FzZSAzOgogICAgICB0YWJsZUZpcnN0UyA9IGdldEN1c3RvbUh1ZmZtYW5UYWJsZShjdXN0b21JbmRleCwgcmVmZXJyZWRUbywgY3VzdG9tVGFibGVzKTsKICAgICAgY3VzdG9tSW5kZXgrKzsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCBIdWZmbWFuIEZTIHNlbGVjdG9yIik7CiAgfQogIHN3aXRjaCAodGV4dFJlZ2lvbi5odWZmbWFuRFMpIHsKICAgIGNhc2UgMDoKICAgIGNhc2UgMToKICAgIGNhc2UgMjoKICAgICAgdGFibGVEZWx0YVMgPSBnZXRTdGFuZGFyZFRhYmxlKHRleHRSZWdpb24uaHVmZm1hbkRTICsgOCk7CiAgICAgIGJyZWFrOwogICAgY2FzZSAzOgogICAgICB0YWJsZURlbHRhUyA9IGdldEN1c3RvbUh1ZmZtYW5UYWJsZShjdXN0b21JbmRleCwgcmVmZXJyZWRUbywgY3VzdG9tVGFibGVzKTsKICAgICAgY3VzdG9tSW5kZXgrKzsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCBIdWZmbWFuIERTIHNlbGVjdG9yIik7CiAgfQogIHN3aXRjaCAodGV4dFJlZ2lvbi5odWZmbWFuRFQpIHsKICAgIGNhc2UgMDoKICAgIGNhc2UgMToKICAgIGNhc2UgMjoKICAgICAgdGFibGVEZWx0YVQgPSBnZXRTdGFuZGFyZFRhYmxlKHRleHRSZWdpb24uaHVmZm1hbkRUICsgMTEpOwogICAgICBicmVhazsKICAgIGNhc2UgMzoKICAgICAgdGFibGVEZWx0YVQgPSBnZXRDdXN0b21IdWZmbWFuVGFibGUoY3VzdG9tSW5kZXgsIHJlZmVycmVkVG8sIGN1c3RvbVRhYmxlcyk7CiAgICAgIGN1c3RvbUluZGV4Kys7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBEVCBzZWxlY3RvciIpOwogIH0KICBpZiAodGV4dFJlZ2lvbi5yZWZpbmVtZW50KSB7CiAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigicmVmaW5lbWVudCB3aXRoIEh1ZmZtYW4gaXMgbm90IHN1cHBvcnRlZCIpOwogIH0KICByZXR1cm4gewogICAgc3ltYm9sSURUYWJsZSwKICAgIHRhYmxlRmlyc3RTLAogICAgdGFibGVEZWx0YVMsCiAgICB0YWJsZURlbHRhVAogIH07Cn0KZnVuY3Rpb24gZ2V0U3ltYm9sRGljdGlvbmFyeUh1ZmZtYW5UYWJsZXMoZGljdGlvbmFyeSwgcmVmZXJyZWRUbywgY3VzdG9tVGFibGVzKSB7CiAgbGV0IGN1c3RvbUluZGV4ID0gMCwKICAgIHRhYmxlRGVsdGFIZWlnaHQsCiAgICB0YWJsZURlbHRhV2lkdGg7CiAgc3dpdGNoIChkaWN0aW9uYXJ5Lmh1ZmZtYW5ESFNlbGVjdG9yKSB7CiAgICBjYXNlIDA6CiAgICBjYXNlIDE6CiAgICAgIHRhYmxlRGVsdGFIZWlnaHQgPSBnZXRTdGFuZGFyZFRhYmxlKGRpY3Rpb25hcnkuaHVmZm1hbkRIU2VsZWN0b3IgKyA0KTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDM6CiAgICAgIHRhYmxlRGVsdGFIZWlnaHQgPSBnZXRDdXN0b21IdWZmbWFuVGFibGUoY3VzdG9tSW5kZXgsIHJlZmVycmVkVG8sIGN1c3RvbVRhYmxlcyk7CiAgICAgIGN1c3RvbUluZGV4Kys7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBESCBzZWxlY3RvciIpOwogIH0KICBzd2l0Y2ggKGRpY3Rpb25hcnkuaHVmZm1hbkRXU2VsZWN0b3IpIHsKICAgIGNhc2UgMDoKICAgIGNhc2UgMToKICAgICAgdGFibGVEZWx0YVdpZHRoID0gZ2V0U3RhbmRhcmRUYWJsZShkaWN0aW9uYXJ5Lmh1ZmZtYW5EV1NlbGVjdG9yICsgMik7CiAgICAgIGJyZWFrOwogICAgY2FzZSAzOgogICAgICB0YWJsZURlbHRhV2lkdGggPSBnZXRDdXN0b21IdWZmbWFuVGFibGUoY3VzdG9tSW5kZXgsIHJlZmVycmVkVG8sIGN1c3RvbVRhYmxlcyk7CiAgICAgIGN1c3RvbUluZGV4Kys7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBEVyBzZWxlY3RvciIpOwogIH0KICBsZXQgdGFibGVCaXRtYXBTaXplLCB0YWJsZUFnZ3JlZ2F0ZUluc3RhbmNlczsKICBpZiAoZGljdGlvbmFyeS5iaXRtYXBTaXplU2VsZWN0b3IpIHsKICAgIHRhYmxlQml0bWFwU2l6ZSA9IGdldEN1c3RvbUh1ZmZtYW5UYWJsZShjdXN0b21JbmRleCwgcmVmZXJyZWRUbywgY3VzdG9tVGFibGVzKTsKICAgIGN1c3RvbUluZGV4Kys7CiAgfSBlbHNlIHsKICAgIHRhYmxlQml0bWFwU2l6ZSA9IGdldFN0YW5kYXJkVGFibGUoMSk7CiAgfQogIGlmIChkaWN0aW9uYXJ5LmFnZ3JlZ2F0aW9uSW5zdGFuY2VzU2VsZWN0b3IpIHsKICAgIHRhYmxlQWdncmVnYXRlSW5zdGFuY2VzID0gZ2V0Q3VzdG9tSHVmZm1hblRhYmxlKGN1c3RvbUluZGV4LCByZWZlcnJlZFRvLCBjdXN0b21UYWJsZXMpOwogIH0gZWxzZSB7CiAgICB0YWJsZUFnZ3JlZ2F0ZUluc3RhbmNlcyA9IGdldFN0YW5kYXJkVGFibGUoMSk7CiAgfQogIHJldHVybiB7CiAgICB0YWJsZURlbHRhSGVpZ2h0LAogICAgdGFibGVEZWx0YVdpZHRoLAogICAgdGFibGVCaXRtYXBTaXplLAogICAgdGFibGVBZ2dyZWdhdGVJbnN0YW5jZXMKICB9Owp9CmZ1bmN0aW9uIHJlYWRVbmNvbXByZXNzZWRCaXRtYXAocmVhZGVyLCB3aWR0aCwgaGVpZ2h0KSB7CiAgY29uc3QgYml0bWFwID0gW107CiAgZm9yIChsZXQgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykgewogICAgY29uc3Qgcm93ID0gbmV3IFVpbnQ4QXJyYXkod2lkdGgpOwogICAgYml0bWFwLnB1c2gocm93KTsKICAgIGZvciAobGV0IHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewogICAgICByb3dbeF0gPSByZWFkZXIucmVhZEJpdCgpOwogICAgfQogICAgcmVhZGVyLmJ5dGVBbGlnbigpOwogIH0KICByZXR1cm4gYml0bWFwOwp9CmZ1bmN0aW9uIGRlY29kZU1NUkJpdG1hcChpbnB1dCwgd2lkdGgsIGhlaWdodCwgZW5kT2ZCbG9jaykgewogIGNvbnN0IHBhcmFtcyA9IHsKICAgIEs6IC0xLAogICAgQ29sdW1uczogd2lkdGgsCiAgICBSb3dzOiBoZWlnaHQsCiAgICBCbGFja0lzMTogdHJ1ZSwKICAgIEVuZE9mQmxvY2s6IGVuZE9mQmxvY2sKICB9OwogIGNvbnN0IGRlY29kZXIgPSBuZXcgX2NjaXR0LkNDSVRURmF4RGVjb2RlcihpbnB1dCwgcGFyYW1zKTsKICBjb25zdCBiaXRtYXAgPSBbXTsKICBsZXQgY3VycmVudEJ5dGUsCiAgICBlb2YgPSBmYWxzZTsKICBmb3IgKGxldCB5ID0gMDsgeSA8IGhlaWdodDsgeSsrKSB7CiAgICBjb25zdCByb3cgPSBuZXcgVWludDhBcnJheSh3aWR0aCk7CiAgICBiaXRtYXAucHVzaChyb3cpOwogICAgbGV0IHNoaWZ0ID0gLTE7CiAgICBmb3IgKGxldCB4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHsKICAgICAgaWYgKHNoaWZ0IDwgMCkgewogICAgICAgIGN1cnJlbnRCeXRlID0gZGVjb2Rlci5yZWFkTmV4dENoYXIoKTsKICAgICAgICBpZiAoY3VycmVudEJ5dGUgPT09IC0xKSB7CiAgICAgICAgICBjdXJyZW50Qnl0ZSA9IDA7CiAgICAgICAgICBlb2YgPSB0cnVlOwogICAgICAgIH0KICAgICAgICBzaGlmdCA9IDc7CiAgICAgIH0KICAgICAgcm93W3hdID0gY3VycmVudEJ5dGUgPj4gc2hpZnQgJiAxOwogICAgICBzaGlmdC0tOwogICAgfQogIH0KICBpZiAoZW5kT2ZCbG9jayAmJiAhZW9mKSB7CiAgICBjb25zdCBsb29rRm9yRU9GTGltaXQgPSA1OwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsb29rRm9yRU9GTGltaXQ7IGkrKykgewogICAgICBpZiAoZGVjb2Rlci5yZWFkTmV4dENoYXIoKSA9PT0gLTEpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogIH0KICByZXR1cm4gYml0bWFwOwp9CmNsYXNzIEpiaWcySW1hZ2UgewogIHBhcnNlQ2h1bmtzKGNodW5rcykgewogICAgcmV0dXJuIHBhcnNlSmJpZzJDaHVua3MoY2h1bmtzKTsKICB9CiAgcGFyc2UoZGF0YSkgewogICAgdGhyb3cgbmV3IEVycm9yKCJOb3QgaW1wbGVtZW50ZWQ6IEpiaWcySW1hZ2UucGFyc2UiKTsKICB9Cn0KZXhwb3J0cy5KYmlnMkltYWdlID0gSmJpZzJJbWFnZTsKCi8qKiovIH0pLAovKiAxNjAgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLkFyaXRobWV0aWNEZWNvZGVyID0gdm9pZCAwOwpjb25zdCBRZVRhYmxlID0gW3sKICBxZTogMHg1NjAxLAogIG5tcHM6IDEsCiAgbmxwczogMSwKICBzd2l0Y2hGbGFnOiAxCn0sIHsKICBxZTogMHgzNDAxLAogIG5tcHM6IDIsCiAgbmxwczogNiwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgxODAxLAogIG5tcHM6IDMsCiAgbmxwczogOSwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwYWMxLAogIG5tcHM6IDQsCiAgbmxwczogMTIsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDUyMSwKICBubXBzOiA1LAogIG5scHM6IDI5LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDAyMjEsCiAgbm1wczogMzgsCiAgbmxwczogMzMsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4NTYwMSwKICBubXBzOiA3LAogIG5scHM6IDYsCiAgc3dpdGNoRmxhZzogMQp9LCB7CiAgcWU6IDB4NTQwMSwKICBubXBzOiA4LAogIG5scHM6IDE0LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDQ4MDEsCiAgbm1wczogOSwKICBubHBzOiAxNCwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgzODAxLAogIG5tcHM6IDEwLAogIG5scHM6IDE0LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDMwMDEsCiAgbm1wczogMTEsCiAgbmxwczogMTcsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MjQwMSwKICBubXBzOiAxMiwKICBubHBzOiAxOCwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgxYzAxLAogIG5tcHM6IDEzLAogIG5scHM6IDIwLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDE2MDEsCiAgbm1wczogMjksCiAgbmxwczogMjEsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4NTYwMSwKICBubXBzOiAxNSwKICBubHBzOiAxNCwKICBzd2l0Y2hGbGFnOiAxCn0sIHsKICBxZTogMHg1NDAxLAogIG5tcHM6IDE2LAogIG5scHM6IDE0LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDUxMDEsCiAgbm1wczogMTcsCiAgbmxwczogMTUsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4NDgwMSwKICBubXBzOiAxOCwKICBubHBzOiAxNiwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgzODAxLAogIG5tcHM6IDE5LAogIG5scHM6IDE3LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDM0MDEsCiAgbm1wczogMjAsCiAgbmxwczogMTgsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MzAwMSwKICBubXBzOiAyMSwKICBubHBzOiAxOSwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgyODAxLAogIG5tcHM6IDIyLAogIG5scHM6IDE5LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDI0MDEsCiAgbm1wczogMjMsCiAgbmxwczogMjAsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MjIwMSwKICBubXBzOiAyNCwKICBubHBzOiAyMSwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgxYzAxLAogIG5tcHM6IDI1LAogIG5scHM6IDIyLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDE4MDEsCiAgbm1wczogMjYsCiAgbmxwczogMjMsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MTYwMSwKICBubXBzOiAyNywKICBubHBzOiAyNCwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgxNDAxLAogIG5tcHM6IDI4LAogIG5scHM6IDI1LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDEyMDEsCiAgbm1wczogMjksCiAgbmxwczogMjYsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MTEwMSwKICBubXBzOiAzMCwKICBubHBzOiAyNywKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwYWMxLAogIG5tcHM6IDMxLAogIG5scHM6IDI4LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDA5YzEsCiAgbm1wczogMzIsCiAgbmxwczogMjksCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDhhMSwKICBubXBzOiAzMywKICBubHBzOiAzMCwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwNTIxLAogIG5tcHM6IDM0LAogIG5scHM6IDMxLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDA0NDEsCiAgbm1wczogMzUsCiAgbmxwczogMzIsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDJhMSwKICBubXBzOiAzNiwKICBubHBzOiAzMywKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwMjIxLAogIG5tcHM6IDM3LAogIG5scHM6IDM0LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDAxNDEsCiAgbm1wczogMzgsCiAgbmxwczogMzUsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDExMSwKICBubXBzOiAzOSwKICBubHBzOiAzNiwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwMDg1LAogIG5tcHM6IDQwLAogIG5scHM6IDM3LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDAwNDksCiAgbm1wczogNDEsCiAgbmxwczogMzgsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDAyNSwKICBubXBzOiA0MiwKICBubHBzOiAzOSwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwMDE1LAogIG5tcHM6IDQzLAogIG5scHM6IDQwLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDAwMDksCiAgbm1wczogNDQsCiAgbmxwczogNDEsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDAwNSwKICBubXBzOiA0NSwKICBubHBzOiA0MiwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwMDAxLAogIG5tcHM6IDQ1LAogIG5scHM6IDQzLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDU2MDEsCiAgbm1wczogNDYsCiAgbmxwczogNDYsCiAgc3dpdGNoRmxhZzogMAp9XTsKY2xhc3MgQXJpdGhtZXRpY0RlY29kZXIgewogIGNvbnN0cnVjdG9yKGRhdGEsIHN0YXJ0LCBlbmQpIHsKICAgIHRoaXMuZGF0YSA9IGRhdGE7CiAgICB0aGlzLmJwID0gc3RhcnQ7CiAgICB0aGlzLmRhdGFFbmQgPSBlbmQ7CiAgICB0aGlzLmNoaWdoID0gZGF0YVtzdGFydF07CiAgICB0aGlzLmNsb3cgPSAwOwogICAgdGhpcy5ieXRlSW4oKTsKICAgIHRoaXMuY2hpZ2ggPSB0aGlzLmNoaWdoIDw8IDcgJiAweGZmZmYgfCB0aGlzLmNsb3cgPj4gOSAmIDB4N2Y7CiAgICB0aGlzLmNsb3cgPSB0aGlzLmNsb3cgPDwgNyAmIDB4ZmZmZjsKICAgIHRoaXMuY3QgLT0gNzsKICAgIHRoaXMuYSA9IDB4ODAwMDsKICB9CiAgYnl0ZUluKCkgewogICAgY29uc3QgZGF0YSA9IHRoaXMuZGF0YTsKICAgIGxldCBicCA9IHRoaXMuYnA7CiAgICBpZiAoZGF0YVticF0gPT09IDB4ZmYpIHsKICAgICAgaWYgKGRhdGFbYnAgKyAxXSA+IDB4OGYpIHsKICAgICAgICB0aGlzLmNsb3cgKz0gMHhmZjAwOwogICAgICAgIHRoaXMuY3QgPSA4OwogICAgICB9IGVsc2UgewogICAgICAgIGJwKys7CiAgICAgICAgdGhpcy5jbG93ICs9IGRhdGFbYnBdIDw8IDk7CiAgICAgICAgdGhpcy5jdCA9IDc7CiAgICAgICAgdGhpcy5icCA9IGJwOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBicCsrOwogICAgICB0aGlzLmNsb3cgKz0gYnAgPCB0aGlzLmRhdGFFbmQgPyBkYXRhW2JwXSA8PCA4IDogMHhmZjAwOwogICAgICB0aGlzLmN0ID0gODsKICAgICAgdGhpcy5icCA9IGJwOwogICAgfQogICAgaWYgKHRoaXMuY2xvdyA+IDB4ZmZmZikgewogICAgICB0aGlzLmNoaWdoICs9IHRoaXMuY2xvdyA+PiAxNjsKICAgICAgdGhpcy5jbG93ICY9IDB4ZmZmZjsKICAgIH0KICB9CiAgcmVhZEJpdChjb250ZXh0cywgcG9zKSB7CiAgICBsZXQgY3hfaW5kZXggPSBjb250ZXh0c1twb3NdID4+IDEsCiAgICAgIGN4X21wcyA9IGNvbnRleHRzW3Bvc10gJiAxOwogICAgY29uc3QgcWVUYWJsZUljeCA9IFFlVGFibGVbY3hfaW5kZXhdOwogICAgY29uc3QgcWVJY3ggPSBxZVRhYmxlSWN4LnFlOwogICAgbGV0IGQ7CiAgICBsZXQgYSA9IHRoaXMuYSAtIHFlSWN4OwogICAgaWYgKHRoaXMuY2hpZ2ggPCBxZUljeCkgewogICAgICBpZiAoYSA8IHFlSWN4KSB7CiAgICAgICAgYSA9IHFlSWN4OwogICAgICAgIGQgPSBjeF9tcHM7CiAgICAgICAgY3hfaW5kZXggPSBxZVRhYmxlSWN4Lm5tcHM7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYSA9IHFlSWN4OwogICAgICAgIGQgPSAxIF4gY3hfbXBzOwogICAgICAgIGlmIChxZVRhYmxlSWN4LnN3aXRjaEZsYWcgPT09IDEpIHsKICAgICAgICAgIGN4X21wcyA9IGQ7CiAgICAgICAgfQogICAgICAgIGN4X2luZGV4ID0gcWVUYWJsZUljeC5ubHBzOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmNoaWdoIC09IHFlSWN4OwogICAgICBpZiAoKGEgJiAweDgwMDApICE9PSAwKSB7CiAgICAgICAgdGhpcy5hID0gYTsKICAgICAgICByZXR1cm4gY3hfbXBzOwogICAgICB9CiAgICAgIGlmIChhIDwgcWVJY3gpIHsKICAgICAgICBkID0gMSBeIGN4X21wczsKICAgICAgICBpZiAocWVUYWJsZUljeC5zd2l0Y2hGbGFnID09PSAxKSB7CiAgICAgICAgICBjeF9tcHMgPSBkOwogICAgICAgIH0KICAgICAgICBjeF9pbmRleCA9IHFlVGFibGVJY3gubmxwczsKICAgICAgfSBlbHNlIHsKICAgICAgICBkID0gY3hfbXBzOwogICAgICAgIGN4X2luZGV4ID0gcWVUYWJsZUljeC5ubXBzOwogICAgICB9CiAgICB9CiAgICBkbyB7CiAgICAgIGlmICh0aGlzLmN0ID09PSAwKSB7CiAgICAgICAgdGhpcy5ieXRlSW4oKTsKICAgICAgfQogICAgICBhIDw8PSAxOwogICAgICB0aGlzLmNoaWdoID0gdGhpcy5jaGlnaCA8PCAxICYgMHhmZmZmIHwgdGhpcy5jbG93ID4+IDE1ICYgMTsKICAgICAgdGhpcy5jbG93ID0gdGhpcy5jbG93IDw8IDEgJiAweGZmZmY7CiAgICAgIHRoaXMuY3QtLTsKICAgIH0gd2hpbGUgKChhICYgMHg4MDAwKSA9PT0gMCk7CiAgICB0aGlzLmEgPSBhOwogICAgY29udGV4dHNbcG9zXSA9IGN4X2luZGV4IDw8IDEgfCBjeF9tcHM7CiAgICByZXR1cm4gZDsKICB9Cn0KZXhwb3J0cy5Bcml0aG1ldGljRGVjb2RlciA9IEFyaXRobWV0aWNEZWNvZGVyOwoKLyoqKi8gfSksCi8qIDE2MSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuSnBlZ1N0cmVhbSA9IHZvaWQgMDsKdmFyIF9kZWNvZGVfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTMpOwp2YXIgX3ByaW1pdGl2ZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MCk7CnZhciBfanBnID0gX193X3BkZmpzX3JlcXVpcmVfXygxNjIpOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpjbGFzcyBKcGVnU3RyZWFtIGV4dGVuZHMgX2RlY29kZV9zdHJlYW0uRGVjb2RlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIG1heWJlTGVuZ3RoLCBwYXJhbXMpIHsKICAgIGxldCBjaDsKICAgIHdoaWxlICgoY2ggPSBzdHJlYW0uZ2V0Qnl0ZSgpKSAhPT0gLTEpIHsKICAgICAgaWYgKGNoID09PSAweGZmKSB7CiAgICAgICAgc3RyZWFtLnNraXAoLTEpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTsKICAgIHRoaXMuZGljdCA9IHN0cmVhbS5kaWN0OwogICAgdGhpcy5tYXliZUxlbmd0aCA9IG1heWJlTGVuZ3RoOwogICAgdGhpcy5wYXJhbXMgPSBwYXJhbXM7CiAgfQogIGdldCBieXRlcygpIHsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiYnl0ZXMiLCB0aGlzLnN0cmVhbS5nZXRCeXRlcyh0aGlzLm1heWJlTGVuZ3RoKSk7CiAgfQogIGVuc3VyZUJ1ZmZlcihyZXF1ZXN0ZWQpIHt9CiAgcmVhZEJsb2NrKCkgewogICAgaWYgKHRoaXMuZW9mKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGpwZWdPcHRpb25zID0gewogICAgICBkZWNvZGVUcmFuc2Zvcm06IHVuZGVmaW5lZCwKICAgICAgY29sb3JUcmFuc2Zvcm06IHVuZGVmaW5lZAogICAgfTsKICAgIGNvbnN0IGRlY29kZUFyciA9IHRoaXMuZGljdC5nZXRBcnJheSgiRCIsICJEZWNvZGUiKTsKICAgIGlmICgodGhpcy5mb3JjZVJHQkEgfHwgdGhpcy5mb3JjZVJHQikgJiYgQXJyYXkuaXNBcnJheShkZWNvZGVBcnIpKSB7CiAgICAgIGNvbnN0IGJpdHNQZXJDb21wb25lbnQgPSB0aGlzLmRpY3QuZ2V0KCJCUEMiLCAiQml0c1BlckNvbXBvbmVudCIpIHx8IDg7CiAgICAgIGNvbnN0IGRlY29kZUFyckxlbmd0aCA9IGRlY29kZUFyci5sZW5ndGg7CiAgICAgIGNvbnN0IHRyYW5zZm9ybSA9IG5ldyBJbnQzMkFycmF5KGRlY29kZUFyckxlbmd0aCk7CiAgICAgIGxldCB0cmFuc2Zvcm1OZWVkZWQgPSBmYWxzZTsKICAgICAgY29uc3QgbWF4VmFsdWUgPSAoMSA8PCBiaXRzUGVyQ29tcG9uZW50KSAtIDE7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGVjb2RlQXJyTGVuZ3RoOyBpICs9IDIpIHsKICAgICAgICB0cmFuc2Zvcm1baV0gPSAoZGVjb2RlQXJyW2kgKyAxXSAtIGRlY29kZUFycltpXSkgKiAyNTYgfCAwOwogICAgICAgIHRyYW5zZm9ybVtpICsgMV0gPSBkZWNvZGVBcnJbaV0gKiBtYXhWYWx1ZSB8IDA7CiAgICAgICAgaWYgKHRyYW5zZm9ybVtpXSAhPT0gMjU2IHx8IHRyYW5zZm9ybVtpICsgMV0gIT09IDApIHsKICAgICAgICAgIHRyYW5zZm9ybU5lZWRlZCA9IHRydWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICh0cmFuc2Zvcm1OZWVkZWQpIHsKICAgICAgICBqcGVnT3B0aW9ucy5kZWNvZGVUcmFuc2Zvcm0gPSB0cmFuc2Zvcm07CiAgICAgIH0KICAgIH0KICAgIGlmICh0aGlzLnBhcmFtcyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpIHsKICAgICAgY29uc3QgY29sb3JUcmFuc2Zvcm0gPSB0aGlzLnBhcmFtcy5nZXQoIkNvbG9yVHJhbnNmb3JtIik7CiAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKGNvbG9yVHJhbnNmb3JtKSkgewogICAgICAgIGpwZWdPcHRpb25zLmNvbG9yVHJhbnNmb3JtID0gY29sb3JUcmFuc2Zvcm07CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGpwZWdJbWFnZSA9IG5ldyBfanBnLkpwZWdJbWFnZShqcGVnT3B0aW9ucyk7CiAgICBqcGVnSW1hZ2UucGFyc2UodGhpcy5ieXRlcyk7CiAgICBjb25zdCBkYXRhID0ganBlZ0ltYWdlLmdldERhdGEoewogICAgICB3aWR0aDogdGhpcy5kcmF3V2lkdGgsCiAgICAgIGhlaWdodDogdGhpcy5kcmF3SGVpZ2h0LAogICAgICBmb3JjZVJHQkE6IHRoaXMuZm9yY2VSR0JBLAogICAgICBmb3JjZVJHQjogdGhpcy5mb3JjZVJHQiwKICAgICAgaXNTb3VyY2VQREY6IHRydWUKICAgIH0pOwogICAgdGhpcy5idWZmZXIgPSBkYXRhOwogICAgdGhpcy5idWZmZXJMZW5ndGggPSBkYXRhLmxlbmd0aDsKICAgIHRoaXMuZW9mID0gdHJ1ZTsKICB9Cn0KZXhwb3J0cy5KcGVnU3RyZWFtID0gSnBlZ1N0cmVhbTsKCi8qKiovIH0pLAovKiAxNjIgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLkpwZWdJbWFnZSA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9pbWFnZV91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTYzKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwpjbGFzcyBKcGVnRXJyb3IgZXh0ZW5kcyBfdXRpbC5CYXNlRXhjZXB0aW9uIHsKICBjb25zdHJ1Y3Rvcihtc2cpIHsKICAgIHN1cGVyKGBKUEVHIGVycm9yOiAke21zZ31gLCAiSnBlZ0Vycm9yIik7CiAgfQp9CmNsYXNzIEROTE1hcmtlckVycm9yIGV4dGVuZHMgX3V0aWwuQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobWVzc2FnZSwgc2NhbkxpbmVzKSB7CiAgICBzdXBlcihtZXNzYWdlLCAiRE5MTWFya2VyRXJyb3IiKTsKICAgIHRoaXMuc2NhbkxpbmVzID0gc2NhbkxpbmVzOwogIH0KfQpjbGFzcyBFT0lNYXJrZXJFcnJvciBleHRlbmRzIF91dGlsLkJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZykgewogICAgc3VwZXIobXNnLCAiRU9JTWFya2VyRXJyb3IiKTsKICB9Cn0KY29uc3QgZGN0WmlnWmFnID0gbmV3IFVpbnQ4QXJyYXkoWzAsIDEsIDgsIDE2LCA5LCAyLCAzLCAxMCwgMTcsIDI0LCAzMiwgMjUsIDE4LCAxMSwgNCwgNSwgMTIsIDE5LCAyNiwgMzMsIDQwLCA0OCwgNDEsIDM0LCAyNywgMjAsIDEzLCA2LCA3LCAxNCwgMjEsIDI4LCAzNSwgNDIsIDQ5LCA1NiwgNTcsIDUwLCA0MywgMzYsIDI5LCAyMiwgMTUsIDIzLCAzMCwgMzcsIDQ0LCA1MSwgNTgsIDU5LCA1MiwgNDUsIDM4LCAzMSwgMzksIDQ2LCA1MywgNjAsIDYxLCA1NCwgNDcsIDU1LCA2MiwgNjNdKTsKY29uc3QgZGN0Q29zMSA9IDQwMTc7CmNvbnN0IGRjdFNpbjEgPSA3OTk7CmNvbnN0IGRjdENvczMgPSAzNDA2Owpjb25zdCBkY3RTaW4zID0gMjI3NjsKY29uc3QgZGN0Q29zNiA9IDE1Njc7CmNvbnN0IGRjdFNpbjYgPSAzNzg0Owpjb25zdCBkY3RTcXJ0MiA9IDU3OTM7CmNvbnN0IGRjdFNxcnQxZDIgPSAyODk2OwpmdW5jdGlvbiBidWlsZEh1ZmZtYW5UYWJsZShjb2RlTGVuZ3RocywgdmFsdWVzKSB7CiAgbGV0IGsgPSAwLAogICAgaSwKICAgIGosCiAgICBsZW5ndGggPSAxNjsKICB3aGlsZSAobGVuZ3RoID4gMCAmJiAhY29kZUxlbmd0aHNbbGVuZ3RoIC0gMV0pIHsKICAgIGxlbmd0aC0tOwogIH0KICBjb25zdCBjb2RlID0gW3sKICAgIGNoaWxkcmVuOiBbXSwKICAgIGluZGV4OiAwCiAgfV07CiAgbGV0IHAgPSBjb2RlWzBdLAogICAgcTsKICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgIGZvciAoaiA9IDA7IGogPCBjb2RlTGVuZ3Roc1tpXTsgaisrKSB7CiAgICAgIHAgPSBjb2RlLnBvcCgpOwogICAgICBwLmNoaWxkcmVuW3AuaW5kZXhdID0gdmFsdWVzW2tdOwogICAgICB3aGlsZSAocC5pbmRleCA+IDApIHsKICAgICAgICBwID0gY29kZS5wb3AoKTsKICAgICAgfQogICAgICBwLmluZGV4Kys7CiAgICAgIGNvZGUucHVzaChwKTsKICAgICAgd2hpbGUgKGNvZGUubGVuZ3RoIDw9IGkpIHsKICAgICAgICBjb2RlLnB1c2gocSA9IHsKICAgICAgICAgIGNoaWxkcmVuOiBbXSwKICAgICAgICAgIGluZGV4OiAwCiAgICAgICAgfSk7CiAgICAgICAgcC5jaGlsZHJlbltwLmluZGV4XSA9IHEuY2hpbGRyZW47CiAgICAgICAgcCA9IHE7CiAgICAgIH0KICAgICAgaysrOwogICAgfQogICAgaWYgKGkgKyAxIDwgbGVuZ3RoKSB7CiAgICAgIGNvZGUucHVzaChxID0gewogICAgICAgIGNoaWxkcmVuOiBbXSwKICAgICAgICBpbmRleDogMAogICAgICB9KTsKICAgICAgcC5jaGlsZHJlbltwLmluZGV4XSA9IHEuY2hpbGRyZW47CiAgICAgIHAgPSBxOwogICAgfQogIH0KICByZXR1cm4gY29kZVswXS5jaGlsZHJlbjsKfQpmdW5jdGlvbiBnZXRCbG9ja0J1ZmZlck9mZnNldChjb21wb25lbnQsIHJvdywgY29sKSB7CiAgcmV0dXJuIDY0ICogKChjb21wb25lbnQuYmxvY2tzUGVyTGluZSArIDEpICogcm93ICsgY29sKTsKfQpmdW5jdGlvbiBkZWNvZGVTY2FuKGRhdGEsIG9mZnNldCwgZnJhbWUsIGNvbXBvbmVudHMsIHJlc2V0SW50ZXJ2YWwsIHNwZWN0cmFsU3RhcnQsIHNwZWN0cmFsRW5kLCBzdWNjZXNzaXZlUHJldiwgc3VjY2Vzc2l2ZSkgewogIGxldCBwYXJzZUROTE1hcmtlciA9IGFyZ3VtZW50cy5sZW5ndGggPiA5ICYmIGFyZ3VtZW50c1s5XSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzldIDogZmFsc2U7CiAgY29uc3QgbWN1c1BlckxpbmUgPSBmcmFtZS5tY3VzUGVyTGluZTsKICBjb25zdCBwcm9ncmVzc2l2ZSA9IGZyYW1lLnByb2dyZXNzaXZlOwogIGNvbnN0IHN0YXJ0T2Zmc2V0ID0gb2Zmc2V0OwogIGxldCBiaXRzRGF0YSA9IDAsCiAgICBiaXRzQ291bnQgPSAwOwogIGZ1bmN0aW9uIHJlYWRCaXQoKSB7CiAgICBpZiAoYml0c0NvdW50ID4gMCkgewogICAgICBiaXRzQ291bnQtLTsKICAgICAgcmV0dXJuIGJpdHNEYXRhID4+IGJpdHNDb3VudCAmIDE7CiAgICB9CiAgICBiaXRzRGF0YSA9IGRhdGFbb2Zmc2V0KytdOwogICAgaWYgKGJpdHNEYXRhID09PSAweGZmKSB7CiAgICAgIGNvbnN0IG5leHRCeXRlID0gZGF0YVtvZmZzZXQrK107CiAgICAgIGlmIChuZXh0Qnl0ZSkgewogICAgICAgIGlmIChuZXh0Qnl0ZSA9PT0gMHhkYyAmJiBwYXJzZUROTE1hcmtlcikgewogICAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgICAgICBjb25zdCBzY2FuTGluZXMgPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgaWYgKHNjYW5MaW5lcyA+IDAgJiYgc2NhbkxpbmVzICE9PSBmcmFtZS5zY2FuTGluZXMpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEROTE1hcmtlckVycm9yKCJGb3VuZCBETkwgbWFya2VyICgweEZGREMpIHdoaWxlIHBhcnNpbmcgc2NhbiBkYXRhIiwgc2NhbkxpbmVzKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKG5leHRCeXRlID09PSAweGQ5KSB7CiAgICAgICAgICBpZiAocGFyc2VETkxNYXJrZXIpIHsKICAgICAgICAgICAgY29uc3QgbWF5YmVTY2FuTGluZXMgPSBibG9ja1JvdyAqIChmcmFtZS5wcmVjaXNpb24gPT09IDggPyA4IDogMCk7CiAgICAgICAgICAgIGlmIChtYXliZVNjYW5MaW5lcyA+IDAgJiYgTWF0aC5yb3VuZChmcmFtZS5zY2FuTGluZXMgLyBtYXliZVNjYW5MaW5lcykgPj0gNSkgewogICAgICAgICAgICAgIHRocm93IG5ldyBETkxNYXJrZXJFcnJvcigiRm91bmQgRU9JIG1hcmtlciAoMHhGRkQ5KSB3aGlsZSBwYXJzaW5nIHNjYW4gZGF0YSwgIiArICJwb3NzaWJseSBjYXVzZWQgYnkgaW5jb3JyZWN0IGBzY2FuTGluZXNgIHBhcmFtZXRlciIsIG1heWJlU2NhbkxpbmVzKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgdGhyb3cgbmV3IEVPSU1hcmtlckVycm9yKCJGb3VuZCBFT0kgbWFya2VyICgweEZGRDkpIHdoaWxlIHBhcnNpbmcgc2NhbiBkYXRhIik7CiAgICAgICAgfQogICAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoYHVuZXhwZWN0ZWQgbWFya2VyICR7KGJpdHNEYXRhIDw8IDggfCBuZXh0Qnl0ZSkudG9TdHJpbmcoMTYpfWApOwogICAgICB9CiAgICB9CiAgICBiaXRzQ291bnQgPSA3OwogICAgcmV0dXJuIGJpdHNEYXRhID4+PiA3OwogIH0KICBmdW5jdGlvbiBkZWNvZGVIdWZmbWFuKHRyZWUpIHsKICAgIGxldCBub2RlID0gdHJlZTsKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIG5vZGUgPSBub2RlW3JlYWRCaXQoKV07CiAgICAgIHN3aXRjaCAodHlwZW9mIG5vZGUpIHsKICAgICAgICBjYXNlICJudW1iZXIiOgogICAgICAgICAgcmV0dXJuIG5vZGU7CiAgICAgICAgY2FzZSAib2JqZWN0IjoKICAgICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoImludmFsaWQgaHVmZm1hbiBzZXF1ZW5jZSIpOwogICAgfQogIH0KICBmdW5jdGlvbiByZWNlaXZlKGxlbmd0aCkgewogICAgbGV0IG4gPSAwOwogICAgd2hpbGUgKGxlbmd0aCA+IDApIHsKICAgICAgbiA9IG4gPDwgMSB8IHJlYWRCaXQoKTsKICAgICAgbGVuZ3RoLS07CiAgICB9CiAgICByZXR1cm4gbjsKICB9CiAgZnVuY3Rpb24gcmVjZWl2ZUFuZEV4dGVuZChsZW5ndGgpIHsKICAgIGlmIChsZW5ndGggPT09IDEpIHsKICAgICAgcmV0dXJuIHJlYWRCaXQoKSA9PT0gMSA/IDEgOiAtMTsKICAgIH0KICAgIGNvbnN0IG4gPSByZWNlaXZlKGxlbmd0aCk7CiAgICBpZiAobiA+PSAxIDw8IGxlbmd0aCAtIDEpIHsKICAgICAgcmV0dXJuIG47CiAgICB9CiAgICByZXR1cm4gbiArICgtMSA8PCBsZW5ndGgpICsgMTsKICB9CiAgZnVuY3Rpb24gZGVjb2RlQmFzZWxpbmUoY29tcG9uZW50LCBibG9ja09mZnNldCkgewogICAgY29uc3QgdCA9IGRlY29kZUh1ZmZtYW4oY29tcG9uZW50Lmh1ZmZtYW5UYWJsZURDKTsKICAgIGNvbnN0IGRpZmYgPSB0ID09PSAwID8gMCA6IHJlY2VpdmVBbmRFeHRlbmQodCk7CiAgICBjb21wb25lbnQuYmxvY2tEYXRhW2Jsb2NrT2Zmc2V0XSA9IGNvbXBvbmVudC5wcmVkICs9IGRpZmY7CiAgICBsZXQgayA9IDE7CiAgICB3aGlsZSAoayA8IDY0KSB7CiAgICAgIGNvbnN0IHJzID0gZGVjb2RlSHVmZm1hbihjb21wb25lbnQuaHVmZm1hblRhYmxlQUMpOwogICAgICBjb25zdCBzID0gcnMgJiAxNSwKICAgICAgICByID0gcnMgPj4gNDsKICAgICAgaWYgKHMgPT09IDApIHsKICAgICAgICBpZiAociA8IDE1KSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgayArPSAxNjsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBrICs9IHI7CiAgICAgIGNvbnN0IHogPSBkY3RaaWdaYWdba107CiAgICAgIGNvbXBvbmVudC5ibG9ja0RhdGFbYmxvY2tPZmZzZXQgKyB6XSA9IHJlY2VpdmVBbmRFeHRlbmQocyk7CiAgICAgIGsrKzsKICAgIH0KICB9CiAgZnVuY3Rpb24gZGVjb2RlRENGaXJzdChjb21wb25lbnQsIGJsb2NrT2Zmc2V0KSB7CiAgICBjb25zdCB0ID0gZGVjb2RlSHVmZm1hbihjb21wb25lbnQuaHVmZm1hblRhYmxlREMpOwogICAgY29uc3QgZGlmZiA9IHQgPT09IDAgPyAwIDogcmVjZWl2ZUFuZEV4dGVuZCh0KSA8PCBzdWNjZXNzaXZlOwogICAgY29tcG9uZW50LmJsb2NrRGF0YVtibG9ja09mZnNldF0gPSBjb21wb25lbnQucHJlZCArPSBkaWZmOwogIH0KICBmdW5jdGlvbiBkZWNvZGVEQ1N1Y2Nlc3NpdmUoY29tcG9uZW50LCBibG9ja09mZnNldCkgewogICAgY29tcG9uZW50LmJsb2NrRGF0YVtibG9ja09mZnNldF0gfD0gcmVhZEJpdCgpIDw8IHN1Y2Nlc3NpdmU7CiAgfQogIGxldCBlb2JydW4gPSAwOwogIGZ1bmN0aW9uIGRlY29kZUFDRmlyc3QoY29tcG9uZW50LCBibG9ja09mZnNldCkgewogICAgaWYgKGVvYnJ1biA+IDApIHsKICAgICAgZW9icnVuLS07CiAgICAgIHJldHVybjsKICAgIH0KICAgIGxldCBrID0gc3BlY3RyYWxTdGFydDsKICAgIGNvbnN0IGUgPSBzcGVjdHJhbEVuZDsKICAgIHdoaWxlIChrIDw9IGUpIHsKICAgICAgY29uc3QgcnMgPSBkZWNvZGVIdWZmbWFuKGNvbXBvbmVudC5odWZmbWFuVGFibGVBQyk7CiAgICAgIGNvbnN0IHMgPSBycyAmIDE1LAogICAgICAgIHIgPSBycyA+PiA0OwogICAgICBpZiAocyA9PT0gMCkgewogICAgICAgIGlmIChyIDwgMTUpIHsKICAgICAgICAgIGVvYnJ1biA9IHJlY2VpdmUocikgKyAoMSA8PCByKSAtIDE7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgayArPSAxNjsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBrICs9IHI7CiAgICAgIGNvbnN0IHogPSBkY3RaaWdaYWdba107CiAgICAgIGNvbXBvbmVudC5ibG9ja0RhdGFbYmxvY2tPZmZzZXQgKyB6XSA9IHJlY2VpdmVBbmRFeHRlbmQocykgKiAoMSA8PCBzdWNjZXNzaXZlKTsKICAgICAgaysrOwogICAgfQogIH0KICBsZXQgc3VjY2Vzc2l2ZUFDU3RhdGUgPSAwLAogICAgc3VjY2Vzc2l2ZUFDTmV4dFZhbHVlOwogIGZ1bmN0aW9uIGRlY29kZUFDU3VjY2Vzc2l2ZShjb21wb25lbnQsIGJsb2NrT2Zmc2V0KSB7CiAgICBsZXQgayA9IHNwZWN0cmFsU3RhcnQ7CiAgICBjb25zdCBlID0gc3BlY3RyYWxFbmQ7CiAgICBsZXQgciA9IDA7CiAgICBsZXQgczsKICAgIGxldCByczsKICAgIHdoaWxlIChrIDw9IGUpIHsKICAgICAgY29uc3Qgb2Zmc2V0WiA9IGJsb2NrT2Zmc2V0ICsgZGN0WmlnWmFnW2tdOwogICAgICBjb25zdCBzaWduID0gY29tcG9uZW50LmJsb2NrRGF0YVtvZmZzZXRaXSA8IDAgPyAtMSA6IDE7CiAgICAgIHN3aXRjaCAoc3VjY2Vzc2l2ZUFDU3RhdGUpIHsKICAgICAgICBjYXNlIDA6CiAgICAgICAgICBycyA9IGRlY29kZUh1ZmZtYW4oY29tcG9uZW50Lmh1ZmZtYW5UYWJsZUFDKTsKICAgICAgICAgIHMgPSBycyAmIDE1OwogICAgICAgICAgciA9IHJzID4+IDQ7CiAgICAgICAgICBpZiAocyA9PT0gMCkgewogICAgICAgICAgICBpZiAociA8IDE1KSB7CiAgICAgICAgICAgICAgZW9icnVuID0gcmVjZWl2ZShyKSArICgxIDw8IHIpOwogICAgICAgICAgICAgIHN1Y2Nlc3NpdmVBQ1N0YXRlID0gNDsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICByID0gMTY7CiAgICAgICAgICAgICAgc3VjY2Vzc2l2ZUFDU3RhdGUgPSAxOwogICAgICAgICAgICB9CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBpZiAocyAhPT0gMSkgewogICAgICAgICAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoImludmFsaWQgQUNuIGVuY29kaW5nIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3VjY2Vzc2l2ZUFDTmV4dFZhbHVlID0gcmVjZWl2ZUFuZEV4dGVuZChzKTsKICAgICAgICAgICAgc3VjY2Vzc2l2ZUFDU3RhdGUgPSByID8gMiA6IDM7CiAgICAgICAgICB9CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICBjYXNlIDE6CiAgICAgICAgY2FzZSAyOgogICAgICAgICAgaWYgKGNvbXBvbmVudC5ibG9ja0RhdGFbb2Zmc2V0Wl0pIHsKICAgICAgICAgICAgY29tcG9uZW50LmJsb2NrRGF0YVtvZmZzZXRaXSArPSBzaWduICogKHJlYWRCaXQoKSA8PCBzdWNjZXNzaXZlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHItLTsKICAgICAgICAgICAgaWYgKHIgPT09IDApIHsKICAgICAgICAgICAgICBzdWNjZXNzaXZlQUNTdGF0ZSA9IHN1Y2Nlc3NpdmVBQ1N0YXRlID09PSAyID8gMyA6IDA7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzoKICAgICAgICAgIGlmIChjb21wb25lbnQuYmxvY2tEYXRhW29mZnNldFpdKSB7CiAgICAgICAgICAgIGNvbXBvbmVudC5ibG9ja0RhdGFbb2Zmc2V0Wl0gKz0gc2lnbiAqIChyZWFkQml0KCkgPDwgc3VjY2Vzc2l2ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBjb21wb25lbnQuYmxvY2tEYXRhW29mZnNldFpdID0gc3VjY2Vzc2l2ZUFDTmV4dFZhbHVlIDw8IHN1Y2Nlc3NpdmU7CiAgICAgICAgICAgIHN1Y2Nlc3NpdmVBQ1N0YXRlID0gMDsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNDoKICAgICAgICAgIGlmIChjb21wb25lbnQuYmxvY2tEYXRhW29mZnNldFpdKSB7CiAgICAgICAgICAgIGNvbXBvbmVudC5ibG9ja0RhdGFbb2Zmc2V0Wl0gKz0gc2lnbiAqIChyZWFkQml0KCkgPDwgc3VjY2Vzc2l2ZSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBrKys7CiAgICB9CiAgICBpZiAoc3VjY2Vzc2l2ZUFDU3RhdGUgPT09IDQpIHsKICAgICAgZW9icnVuLS07CiAgICAgIGlmIChlb2JydW4gPT09IDApIHsKICAgICAgICBzdWNjZXNzaXZlQUNTdGF0ZSA9IDA7CiAgICAgIH0KICAgIH0KICB9CiAgbGV0IGJsb2NrUm93ID0gMDsKICBmdW5jdGlvbiBkZWNvZGVNY3UoY29tcG9uZW50LCBkZWNvZGUsIG1jdSwgcm93LCBjb2wpIHsKICAgIGNvbnN0IG1jdVJvdyA9IG1jdSAvIG1jdXNQZXJMaW5lIHwgMDsKICAgIGNvbnN0IG1jdUNvbCA9IG1jdSAlIG1jdXNQZXJMaW5lOwogICAgYmxvY2tSb3cgPSBtY3VSb3cgKiBjb21wb25lbnQudiArIHJvdzsKICAgIGNvbnN0IGJsb2NrQ29sID0gbWN1Q29sICogY29tcG9uZW50LmggKyBjb2w7CiAgICBjb25zdCBibG9ja09mZnNldCA9IGdldEJsb2NrQnVmZmVyT2Zmc2V0KGNvbXBvbmVudCwgYmxvY2tSb3csIGJsb2NrQ29sKTsKICAgIGRlY29kZShjb21wb25lbnQsIGJsb2NrT2Zmc2V0KTsKICB9CiAgZnVuY3Rpb24gZGVjb2RlQmxvY2soY29tcG9uZW50LCBkZWNvZGUsIG1jdSkgewogICAgYmxvY2tSb3cgPSBtY3UgLyBjb21wb25lbnQuYmxvY2tzUGVyTGluZSB8IDA7CiAgICBjb25zdCBibG9ja0NvbCA9IG1jdSAlIGNvbXBvbmVudC5ibG9ja3NQZXJMaW5lOwogICAgY29uc3QgYmxvY2tPZmZzZXQgPSBnZXRCbG9ja0J1ZmZlck9mZnNldChjb21wb25lbnQsIGJsb2NrUm93LCBibG9ja0NvbCk7CiAgICBkZWNvZGUoY29tcG9uZW50LCBibG9ja09mZnNldCk7CiAgfQogIGNvbnN0IGNvbXBvbmVudHNMZW5ndGggPSBjb21wb25lbnRzLmxlbmd0aDsKICBsZXQgY29tcG9uZW50LCBpLCBqLCBrLCBuOwogIGxldCBkZWNvZGVGbjsKICBpZiAocHJvZ3Jlc3NpdmUpIHsKICAgIGlmIChzcGVjdHJhbFN0YXJ0ID09PSAwKSB7CiAgICAgIGRlY29kZUZuID0gc3VjY2Vzc2l2ZVByZXYgPT09IDAgPyBkZWNvZGVEQ0ZpcnN0IDogZGVjb2RlRENTdWNjZXNzaXZlOwogICAgfSBlbHNlIHsKICAgICAgZGVjb2RlRm4gPSBzdWNjZXNzaXZlUHJldiA9PT0gMCA/IGRlY29kZUFDRmlyc3QgOiBkZWNvZGVBQ1N1Y2Nlc3NpdmU7CiAgICB9CiAgfSBlbHNlIHsKICAgIGRlY29kZUZuID0gZGVjb2RlQmFzZWxpbmU7CiAgfQogIGxldCBtY3UgPSAwLAogICAgZmlsZU1hcmtlcjsKICBsZXQgbWN1RXhwZWN0ZWQ7CiAgaWYgKGNvbXBvbmVudHNMZW5ndGggPT09IDEpIHsKICAgIG1jdUV4cGVjdGVkID0gY29tcG9uZW50c1swXS5ibG9ja3NQZXJMaW5lICogY29tcG9uZW50c1swXS5ibG9ja3NQZXJDb2x1bW47CiAgfSBlbHNlIHsKICAgIG1jdUV4cGVjdGVkID0gbWN1c1BlckxpbmUgKiBmcmFtZS5tY3VzUGVyQ29sdW1uOwogIH0KICBsZXQgaCwgdjsKICB3aGlsZSAobWN1IDw9IG1jdUV4cGVjdGVkKSB7CiAgICBjb25zdCBtY3VUb1JlYWQgPSByZXNldEludGVydmFsID8gTWF0aC5taW4obWN1RXhwZWN0ZWQgLSBtY3UsIHJlc2V0SW50ZXJ2YWwpIDogbWN1RXhwZWN0ZWQ7CiAgICBpZiAobWN1VG9SZWFkID4gMCkgewogICAgICBmb3IgKGkgPSAwOyBpIDwgY29tcG9uZW50c0xlbmd0aDsgaSsrKSB7CiAgICAgICAgY29tcG9uZW50c1tpXS5wcmVkID0gMDsKICAgICAgfQogICAgICBlb2JydW4gPSAwOwogICAgICBpZiAoY29tcG9uZW50c0xlbmd0aCA9PT0gMSkgewogICAgICAgIGNvbXBvbmVudCA9IGNvbXBvbmVudHNbMF07CiAgICAgICAgZm9yIChuID0gMDsgbiA8IG1jdVRvUmVhZDsgbisrKSB7CiAgICAgICAgICBkZWNvZGVCbG9jayhjb21wb25lbnQsIGRlY29kZUZuLCBtY3UpOwogICAgICAgICAgbWN1Kys7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGZvciAobiA9IDA7IG4gPCBtY3VUb1JlYWQ7IG4rKykgewogICAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvbXBvbmVudHNMZW5ndGg7IGkrKykgewogICAgICAgICAgICBjb21wb25lbnQgPSBjb21wb25lbnRzW2ldOwogICAgICAgICAgICBoID0gY29tcG9uZW50Lmg7CiAgICAgICAgICAgIHYgPSBjb21wb25lbnQudjsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHY7IGorKykgewogICAgICAgICAgICAgIGZvciAoayA9IDA7IGsgPCBoOyBrKyspIHsKICAgICAgICAgICAgICAgIGRlY29kZU1jdShjb21wb25lbnQsIGRlY29kZUZuLCBtY3UsIGosIGspOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgbWN1Kys7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBiaXRzQ291bnQgPSAwOwogICAgZmlsZU1hcmtlciA9IGZpbmROZXh0RmlsZU1hcmtlcihkYXRhLCBvZmZzZXQpOwogICAgaWYgKCFmaWxlTWFya2VyKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgaWYgKGZpbGVNYXJrZXIuaW52YWxpZCkgewogICAgICBjb25zdCBwYXJ0aWFsTXNnID0gbWN1VG9SZWFkID4gMCA/ICJ1bmV4cGVjdGVkIiA6ICJleGNlc3NpdmUiOwogICAgICAoMCwgX3V0aWwud2FybikoYGRlY29kZVNjYW4gLSAke3BhcnRpYWxNc2d9IE1DVSBkYXRhLCBjdXJyZW50IG1hcmtlciBpczogJHtmaWxlTWFya2VyLmludmFsaWR9YCk7CiAgICAgIG9mZnNldCA9IGZpbGVNYXJrZXIub2Zmc2V0OwogICAgfQogICAgaWYgKGZpbGVNYXJrZXIubWFya2VyID49IDB4ZmZkMCAmJiBmaWxlTWFya2VyLm1hcmtlciA8PSAweGZmZDcpIHsKICAgICAgb2Zmc2V0ICs9IDI7CiAgICB9IGVsc2UgewogICAgICBicmVhazsKICAgIH0KICB9CiAgcmV0dXJuIG9mZnNldCAtIHN0YXJ0T2Zmc2V0Owp9CmZ1bmN0aW9uIHF1YW50aXplQW5kSW52ZXJzZShjb21wb25lbnQsIGJsb2NrQnVmZmVyT2Zmc2V0LCBwKSB7CiAgY29uc3QgcXQgPSBjb21wb25lbnQucXVhbnRpemF0aW9uVGFibGUsCiAgICBibG9ja0RhdGEgPSBjb21wb25lbnQuYmxvY2tEYXRhOwogIGxldCB2MCwgdjEsIHYyLCB2MywgdjQsIHY1LCB2Niwgdjc7CiAgbGV0IHAwLCBwMSwgcDIsIHAzLCBwNCwgcDUsIHA2LCBwNzsKICBsZXQgdDsKICBpZiAoIXF0KSB7CiAgICB0aHJvdyBuZXcgSnBlZ0Vycm9yKCJtaXNzaW5nIHJlcXVpcmVkIFF1YW50aXphdGlvbiBUYWJsZS4iKTsKICB9CiAgZm9yIChsZXQgcm93ID0gMDsgcm93IDwgNjQ7IHJvdyArPSA4KSB7CiAgICBwMCA9IGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIHJvd107CiAgICBwMSA9IGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIHJvdyArIDFdOwogICAgcDIgPSBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyByb3cgKyAyXTsKICAgIHAzID0gYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgcm93ICsgM107CiAgICBwNCA9IGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIHJvdyArIDRdOwogICAgcDUgPSBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyByb3cgKyA1XTsKICAgIHA2ID0gYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgcm93ICsgNl07CiAgICBwNyA9IGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIHJvdyArIDddOwogICAgcDAgKj0gcXRbcm93XTsKICAgIGlmICgocDEgfCBwMiB8IHAzIHwgcDQgfCBwNSB8IHA2IHwgcDcpID09PSAwKSB7CiAgICAgIHQgPSBkY3RTcXJ0MiAqIHAwICsgNTEyID4+IDEwOwogICAgICBwW3Jvd10gPSB0OwogICAgICBwW3JvdyArIDFdID0gdDsKICAgICAgcFtyb3cgKyAyXSA9IHQ7CiAgICAgIHBbcm93ICsgM10gPSB0OwogICAgICBwW3JvdyArIDRdID0gdDsKICAgICAgcFtyb3cgKyA1XSA9IHQ7CiAgICAgIHBbcm93ICsgNl0gPSB0OwogICAgICBwW3JvdyArIDddID0gdDsKICAgICAgY29udGludWU7CiAgICB9CiAgICBwMSAqPSBxdFtyb3cgKyAxXTsKICAgIHAyICo9IHF0W3JvdyArIDJdOwogICAgcDMgKj0gcXRbcm93ICsgM107CiAgICBwNCAqPSBxdFtyb3cgKyA0XTsKICAgIHA1ICo9IHF0W3JvdyArIDVdOwogICAgcDYgKj0gcXRbcm93ICsgNl07CiAgICBwNyAqPSBxdFtyb3cgKyA3XTsKICAgIHYwID0gZGN0U3FydDIgKiBwMCArIDEyOCA+PiA4OwogICAgdjEgPSBkY3RTcXJ0MiAqIHA0ICsgMTI4ID4+IDg7CiAgICB2MiA9IHAyOwogICAgdjMgPSBwNjsKICAgIHY0ID0gZGN0U3FydDFkMiAqIChwMSAtIHA3KSArIDEyOCA+PiA4OwogICAgdjcgPSBkY3RTcXJ0MWQyICogKHAxICsgcDcpICsgMTI4ID4+IDg7CiAgICB2NSA9IHAzIDw8IDQ7CiAgICB2NiA9IHA1IDw8IDQ7CiAgICB2MCA9IHYwICsgdjEgKyAxID4+IDE7CiAgICB2MSA9IHYwIC0gdjE7CiAgICB0ID0gdjIgKiBkY3RTaW42ICsgdjMgKiBkY3RDb3M2ICsgMTI4ID4+IDg7CiAgICB2MiA9IHYyICogZGN0Q29zNiAtIHYzICogZGN0U2luNiArIDEyOCA+PiA4OwogICAgdjMgPSB0OwogICAgdjQgPSB2NCArIHY2ICsgMSA+PiAxOwogICAgdjYgPSB2NCAtIHY2OwogICAgdjcgPSB2NyArIHY1ICsgMSA+PiAxOwogICAgdjUgPSB2NyAtIHY1OwogICAgdjAgPSB2MCArIHYzICsgMSA+PiAxOwogICAgdjMgPSB2MCAtIHYzOwogICAgdjEgPSB2MSArIHYyICsgMSA+PiAxOwogICAgdjIgPSB2MSAtIHYyOwogICAgdCA9IHY0ICogZGN0U2luMyArIHY3ICogZGN0Q29zMyArIDIwNDggPj4gMTI7CiAgICB2NCA9IHY0ICogZGN0Q29zMyAtIHY3ICogZGN0U2luMyArIDIwNDggPj4gMTI7CiAgICB2NyA9IHQ7CiAgICB0ID0gdjUgKiBkY3RTaW4xICsgdjYgKiBkY3RDb3MxICsgMjA0OCA+PiAxMjsKICAgIHY1ID0gdjUgKiBkY3RDb3MxIC0gdjYgKiBkY3RTaW4xICsgMjA0OCA+PiAxMjsKICAgIHY2ID0gdDsKICAgIHBbcm93XSA9IHYwICsgdjc7CiAgICBwW3JvdyArIDddID0gdjAgLSB2NzsKICAgIHBbcm93ICsgMV0gPSB2MSArIHY2OwogICAgcFtyb3cgKyA2XSA9IHYxIC0gdjY7CiAgICBwW3JvdyArIDJdID0gdjIgKyB2NTsKICAgIHBbcm93ICsgNV0gPSB2MiAtIHY1OwogICAgcFtyb3cgKyAzXSA9IHYzICsgdjQ7CiAgICBwW3JvdyArIDRdID0gdjMgLSB2NDsKICB9CiAgZm9yIChsZXQgY29sID0gMDsgY29sIDwgODsgKytjb2wpIHsKICAgIHAwID0gcFtjb2xdOwogICAgcDEgPSBwW2NvbCArIDhdOwogICAgcDIgPSBwW2NvbCArIDE2XTsKICAgIHAzID0gcFtjb2wgKyAyNF07CiAgICBwNCA9IHBbY29sICsgMzJdOwogICAgcDUgPSBwW2NvbCArIDQwXTsKICAgIHA2ID0gcFtjb2wgKyA0OF07CiAgICBwNyA9IHBbY29sICsgNTZdOwogICAgaWYgKChwMSB8IHAyIHwgcDMgfCBwNCB8IHA1IHwgcDYgfCBwNykgPT09IDApIHsKICAgICAgdCA9IGRjdFNxcnQyICogcDAgKyA4MTkyID4+IDE0OwogICAgICBpZiAodCA8IC0yMDQwKSB7CiAgICAgICAgdCA9IDA7CiAgICAgIH0gZWxzZSBpZiAodCA+PSAyMDI0KSB7CiAgICAgICAgdCA9IDI1NTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0ID0gdCArIDIwNTYgPj4gNDsKICAgICAgfQogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2xdID0gdDsKICAgICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgOF0gPSB0OwogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyAxNl0gPSB0OwogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyAyNF0gPSB0OwogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyAzMl0gPSB0OwogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyA0MF0gPSB0OwogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyA0OF0gPSB0OwogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyA1Nl0gPSB0OwogICAgICBjb250aW51ZTsKICAgIH0KICAgIHYwID0gZGN0U3FydDIgKiBwMCArIDIwNDggPj4gMTI7CiAgICB2MSA9IGRjdFNxcnQyICogcDQgKyAyMDQ4ID4+IDEyOwogICAgdjIgPSBwMjsKICAgIHYzID0gcDY7CiAgICB2NCA9IGRjdFNxcnQxZDIgKiAocDEgLSBwNykgKyAyMDQ4ID4+IDEyOwogICAgdjcgPSBkY3RTcXJ0MWQyICogKHAxICsgcDcpICsgMjA0OCA+PiAxMjsKICAgIHY1ID0gcDM7CiAgICB2NiA9IHA1OwogICAgdjAgPSAodjAgKyB2MSArIDEgPj4gMSkgKyA0MTEyOwogICAgdjEgPSB2MCAtIHYxOwogICAgdCA9IHYyICogZGN0U2luNiArIHYzICogZGN0Q29zNiArIDIwNDggPj4gMTI7CiAgICB2MiA9IHYyICogZGN0Q29zNiAtIHYzICogZGN0U2luNiArIDIwNDggPj4gMTI7CiAgICB2MyA9IHQ7CiAgICB2NCA9IHY0ICsgdjYgKyAxID4+IDE7CiAgICB2NiA9IHY0IC0gdjY7CiAgICB2NyA9IHY3ICsgdjUgKyAxID4+IDE7CiAgICB2NSA9IHY3IC0gdjU7CiAgICB2MCA9IHYwICsgdjMgKyAxID4+IDE7CiAgICB2MyA9IHYwIC0gdjM7CiAgICB2MSA9IHYxICsgdjIgKyAxID4+IDE7CiAgICB2MiA9IHYxIC0gdjI7CiAgICB0ID0gdjQgKiBkY3RTaW4zICsgdjcgKiBkY3RDb3MzICsgMjA0OCA+PiAxMjsKICAgIHY0ID0gdjQgKiBkY3RDb3MzIC0gdjcgKiBkY3RTaW4zICsgMjA0OCA+PiAxMjsKICAgIHY3ID0gdDsKICAgIHQgPSB2NSAqIGRjdFNpbjEgKyB2NiAqIGRjdENvczEgKyAyMDQ4ID4+IDEyOwogICAgdjUgPSB2NSAqIGRjdENvczEgLSB2NiAqIGRjdFNpbjEgKyAyMDQ4ID4+IDEyOwogICAgdjYgPSB0OwogICAgcDAgPSB2MCArIHY3OwogICAgcDcgPSB2MCAtIHY3OwogICAgcDEgPSB2MSArIHY2OwogICAgcDYgPSB2MSAtIHY2OwogICAgcDIgPSB2MiArIHY1OwogICAgcDUgPSB2MiAtIHY1OwogICAgcDMgPSB2MyArIHY0OwogICAgcDQgPSB2MyAtIHY0OwogICAgaWYgKHAwIDwgMTYpIHsKICAgICAgcDAgPSAwOwogICAgfSBlbHNlIGlmIChwMCA+PSA0MDgwKSB7CiAgICAgIHAwID0gMjU1OwogICAgfSBlbHNlIHsKICAgICAgcDAgPj49IDQ7CiAgICB9CiAgICBpZiAocDEgPCAxNikgewogICAgICBwMSA9IDA7CiAgICB9IGVsc2UgaWYgKHAxID49IDQwODApIHsKICAgICAgcDEgPSAyNTU7CiAgICB9IGVsc2UgewogICAgICBwMSA+Pj0gNDsKICAgIH0KICAgIGlmIChwMiA8IDE2KSB7CiAgICAgIHAyID0gMDsKICAgIH0gZWxzZSBpZiAocDIgPj0gNDA4MCkgewogICAgICBwMiA9IDI1NTsKICAgIH0gZWxzZSB7CiAgICAgIHAyID4+PSA0OwogICAgfQogICAgaWYgKHAzIDwgMTYpIHsKICAgICAgcDMgPSAwOwogICAgfSBlbHNlIGlmIChwMyA+PSA0MDgwKSB7CiAgICAgIHAzID0gMjU1OwogICAgfSBlbHNlIHsKICAgICAgcDMgPj49IDQ7CiAgICB9CiAgICBpZiAocDQgPCAxNikgewogICAgICBwNCA9IDA7CiAgICB9IGVsc2UgaWYgKHA0ID49IDQwODApIHsKICAgICAgcDQgPSAyNTU7CiAgICB9IGVsc2UgewogICAgICBwNCA+Pj0gNDsKICAgIH0KICAgIGlmIChwNSA8IDE2KSB7CiAgICAgIHA1ID0gMDsKICAgIH0gZWxzZSBpZiAocDUgPj0gNDA4MCkgewogICAgICBwNSA9IDI1NTsKICAgIH0gZWxzZSB7CiAgICAgIHA1ID4+PSA0OwogICAgfQogICAgaWYgKHA2IDwgMTYpIHsKICAgICAgcDYgPSAwOwogICAgfSBlbHNlIGlmIChwNiA+PSA0MDgwKSB7CiAgICAgIHA2ID0gMjU1OwogICAgfSBlbHNlIHsKICAgICAgcDYgPj49IDQ7CiAgICB9CiAgICBpZiAocDcgPCAxNikgewogICAgICBwNyA9IDA7CiAgICB9IGVsc2UgaWYgKHA3ID49IDQwODApIHsKICAgICAgcDcgPSAyNTU7CiAgICB9IGVsc2UgewogICAgICBwNyA+Pj0gNDsKICAgIH0KICAgIGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIGNvbF0gPSBwMDsKICAgIGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIGNvbCArIDhdID0gcDE7CiAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyAxNl0gPSBwMjsKICAgIGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIGNvbCArIDI0XSA9IHAzOwogICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgMzJdID0gcDQ7CiAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyA0MF0gPSBwNTsKICAgIGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIGNvbCArIDQ4XSA9IHA2OwogICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgNTZdID0gcDc7CiAgfQp9CmZ1bmN0aW9uIGJ1aWxkQ29tcG9uZW50RGF0YShmcmFtZSwgY29tcG9uZW50KSB7CiAgY29uc3QgYmxvY2tzUGVyTGluZSA9IGNvbXBvbmVudC5ibG9ja3NQZXJMaW5lOwogIGNvbnN0IGJsb2Nrc1BlckNvbHVtbiA9IGNvbXBvbmVudC5ibG9ja3NQZXJDb2x1bW47CiAgY29uc3QgY29tcHV0YXRpb25CdWZmZXIgPSBuZXcgSW50MTZBcnJheSg2NCk7CiAgZm9yIChsZXQgYmxvY2tSb3cgPSAwOyBibG9ja1JvdyA8IGJsb2Nrc1BlckNvbHVtbjsgYmxvY2tSb3crKykgewogICAgZm9yIChsZXQgYmxvY2tDb2wgPSAwOyBibG9ja0NvbCA8IGJsb2Nrc1BlckxpbmU7IGJsb2NrQ29sKyspIHsKICAgICAgY29uc3Qgb2Zmc2V0ID0gZ2V0QmxvY2tCdWZmZXJPZmZzZXQoY29tcG9uZW50LCBibG9ja1JvdywgYmxvY2tDb2wpOwogICAgICBxdWFudGl6ZUFuZEludmVyc2UoY29tcG9uZW50LCBvZmZzZXQsIGNvbXB1dGF0aW9uQnVmZmVyKTsKICAgIH0KICB9CiAgcmV0dXJuIGNvbXBvbmVudC5ibG9ja0RhdGE7Cn0KZnVuY3Rpb24gZmluZE5leHRGaWxlTWFya2VyKGRhdGEsIGN1cnJlbnRQb3MpIHsKICBsZXQgc3RhcnRQb3MgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IGN1cnJlbnRQb3M7CiAgY29uc3QgbWF4UG9zID0gZGF0YS5sZW5ndGggLSAxOwogIGxldCBuZXdQb3MgPSBzdGFydFBvcyA8IGN1cnJlbnRQb3MgPyBzdGFydFBvcyA6IGN1cnJlbnRQb3M7CiAgaWYgKGN1cnJlbnRQb3MgPj0gbWF4UG9zKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgY29uc3QgY3VycmVudE1hcmtlciA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBjdXJyZW50UG9zKTsKICBpZiAoY3VycmVudE1hcmtlciA+PSAweGZmYzAgJiYgY3VycmVudE1hcmtlciA8PSAweGZmZmUpIHsKICAgIHJldHVybiB7CiAgICAgIGludmFsaWQ6IG51bGwsCiAgICAgIG1hcmtlcjogY3VycmVudE1hcmtlciwKICAgICAgb2Zmc2V0OiBjdXJyZW50UG9zCiAgICB9OwogIH0KICBsZXQgbmV3TWFya2VyID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MTYpKGRhdGEsIG5ld1Bvcyk7CiAgd2hpbGUgKCEobmV3TWFya2VyID49IDB4ZmZjMCAmJiBuZXdNYXJrZXIgPD0gMHhmZmZlKSkgewogICAgaWYgKCsrbmV3UG9zID49IG1heFBvcykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIG5ld01hcmtlciA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBuZXdQb3MpOwogIH0KICByZXR1cm4gewogICAgaW52YWxpZDogY3VycmVudE1hcmtlci50b1N0cmluZygxNiksCiAgICBtYXJrZXI6IG5ld01hcmtlciwKICAgIG9mZnNldDogbmV3UG9zCiAgfTsKfQpjbGFzcyBKcGVnSW1hZ2UgewogIGNvbnN0cnVjdG9yKCkgewogICAgbGV0IHsKICAgICAgZGVjb2RlVHJhbnNmb3JtID0gbnVsbCwKICAgICAgY29sb3JUcmFuc2Zvcm0gPSAtMQogICAgfSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDoge307CiAgICB0aGlzLl9kZWNvZGVUcmFuc2Zvcm0gPSBkZWNvZGVUcmFuc2Zvcm07CiAgICB0aGlzLl9jb2xvclRyYW5zZm9ybSA9IGNvbG9yVHJhbnNmb3JtOwogIH0KICBwYXJzZShkYXRhKSB7CiAgICBsZXQgewogICAgICBkbmxTY2FuTGluZXMgPSBudWxsCiAgICB9ID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB7fTsKICAgIGZ1bmN0aW9uIHJlYWREYXRhQmxvY2soKSB7CiAgICAgIGNvbnN0IGxlbmd0aCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBvZmZzZXQpOwogICAgICBvZmZzZXQgKz0gMjsKICAgICAgbGV0IGVuZE9mZnNldCA9IG9mZnNldCArIGxlbmd0aCAtIDI7CiAgICAgIGNvbnN0IGZpbGVNYXJrZXIgPSBmaW5kTmV4dEZpbGVNYXJrZXIoZGF0YSwgZW5kT2Zmc2V0LCBvZmZzZXQpOwogICAgICBpZiAoZmlsZU1hcmtlciAmJiBmaWxlTWFya2VyLmludmFsaWQpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoInJlYWREYXRhQmxvY2sgLSBpbmNvcnJlY3QgbGVuZ3RoLCBjdXJyZW50IG1hcmtlciBpczogIiArIGZpbGVNYXJrZXIuaW52YWxpZCk7CiAgICAgICAgZW5kT2Zmc2V0ID0gZmlsZU1hcmtlci5vZmZzZXQ7CiAgICAgIH0KICAgICAgY29uc3QgYXJyYXkgPSBkYXRhLnN1YmFycmF5KG9mZnNldCwgZW5kT2Zmc2V0KTsKICAgICAgb2Zmc2V0ICs9IGFycmF5Lmxlbmd0aDsKICAgICAgcmV0dXJuIGFycmF5OwogICAgfQogICAgZnVuY3Rpb24gcHJlcGFyZUNvbXBvbmVudHMoZnJhbWUpIHsKICAgICAgY29uc3QgbWN1c1BlckxpbmUgPSBNYXRoLmNlaWwoZnJhbWUuc2FtcGxlc1BlckxpbmUgLyA4IC8gZnJhbWUubWF4SCk7CiAgICAgIGNvbnN0IG1jdXNQZXJDb2x1bW4gPSBNYXRoLmNlaWwoZnJhbWUuc2NhbkxpbmVzIC8gOCAvIGZyYW1lLm1heFYpOwogICAgICBmb3IgKGNvbnN0IGNvbXBvbmVudCBvZiBmcmFtZS5jb21wb25lbnRzKSB7CiAgICAgICAgY29uc3QgYmxvY2tzUGVyTGluZSA9IE1hdGguY2VpbChNYXRoLmNlaWwoZnJhbWUuc2FtcGxlc1BlckxpbmUgLyA4KSAqIGNvbXBvbmVudC5oIC8gZnJhbWUubWF4SCk7CiAgICAgICAgY29uc3QgYmxvY2tzUGVyQ29sdW1uID0gTWF0aC5jZWlsKE1hdGguY2VpbChmcmFtZS5zY2FuTGluZXMgLyA4KSAqIGNvbXBvbmVudC52IC8gZnJhbWUubWF4Vik7CiAgICAgICAgY29uc3QgYmxvY2tzUGVyTGluZUZvck1jdSA9IG1jdXNQZXJMaW5lICogY29tcG9uZW50Lmg7CiAgICAgICAgY29uc3QgYmxvY2tzUGVyQ29sdW1uRm9yTWN1ID0gbWN1c1BlckNvbHVtbiAqIGNvbXBvbmVudC52OwogICAgICAgIGNvbnN0IGJsb2Nrc0J1ZmZlclNpemUgPSA2NCAqIGJsb2Nrc1BlckNvbHVtbkZvck1jdSAqIChibG9ja3NQZXJMaW5lRm9yTWN1ICsgMSk7CiAgICAgICAgY29tcG9uZW50LmJsb2NrRGF0YSA9IG5ldyBJbnQxNkFycmF5KGJsb2Nrc0J1ZmZlclNpemUpOwogICAgICAgIGNvbXBvbmVudC5ibG9ja3NQZXJMaW5lID0gYmxvY2tzUGVyTGluZTsKICAgICAgICBjb21wb25lbnQuYmxvY2tzUGVyQ29sdW1uID0gYmxvY2tzUGVyQ29sdW1uOwogICAgICB9CiAgICAgIGZyYW1lLm1jdXNQZXJMaW5lID0gbWN1c1BlckxpbmU7CiAgICAgIGZyYW1lLm1jdXNQZXJDb2x1bW4gPSBtY3VzUGVyQ29sdW1uOwogICAgfQogICAgbGV0IG9mZnNldCA9IDA7CiAgICBsZXQgamZpZiA9IG51bGw7CiAgICBsZXQgYWRvYmUgPSBudWxsOwogICAgbGV0IGZyYW1lLCByZXNldEludGVydmFsOwogICAgbGV0IG51bVNPU01hcmtlcnMgPSAwOwogICAgY29uc3QgcXVhbnRpemF0aW9uVGFibGVzID0gW107CiAgICBjb25zdCBodWZmbWFuVGFibGVzQUMgPSBbXSwKICAgICAgaHVmZm1hblRhYmxlc0RDID0gW107CiAgICBsZXQgZmlsZU1hcmtlciA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDI7CiAgICBpZiAoZmlsZU1hcmtlciAhPT0gMHhmZmQ4KSB7CiAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoIlNPSSBub3QgZm91bmQiKTsKICAgIH0KICAgIGZpbGVNYXJrZXIgPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgb2Zmc2V0KTsKICAgIG9mZnNldCArPSAyOwogICAgbWFya2VyTG9vcDogd2hpbGUgKGZpbGVNYXJrZXIgIT09IDB4ZmZkOSkgewogICAgICBsZXQgaSwgaiwgbDsKICAgICAgc3dpdGNoIChmaWxlTWFya2VyKSB7CiAgICAgICAgY2FzZSAweGZmZTA6CiAgICAgICAgY2FzZSAweGZmZTE6CiAgICAgICAgY2FzZSAweGZmZTI6CiAgICAgICAgY2FzZSAweGZmZTM6CiAgICAgICAgY2FzZSAweGZmZTQ6CiAgICAgICAgY2FzZSAweGZmZTU6CiAgICAgICAgY2FzZSAweGZmZTY6CiAgICAgICAgY2FzZSAweGZmZTc6CiAgICAgICAgY2FzZSAweGZmZTg6CiAgICAgICAgY2FzZSAweGZmZTk6CiAgICAgICAgY2FzZSAweGZmZWE6CiAgICAgICAgY2FzZSAweGZmZWI6CiAgICAgICAgY2FzZSAweGZmZWM6CiAgICAgICAgY2FzZSAweGZmZWQ6CiAgICAgICAgY2FzZSAweGZmZWU6CiAgICAgICAgY2FzZSAweGZmZWY6CiAgICAgICAgY2FzZSAweGZmZmU6CiAgICAgICAgICBjb25zdCBhcHBEYXRhID0gcmVhZERhdGFCbG9jaygpOwogICAgICAgICAgaWYgKGZpbGVNYXJrZXIgPT09IDB4ZmZlMCkgewogICAgICAgICAgICBpZiAoYXBwRGF0YVswXSA9PT0gMHg0YSAmJiBhcHBEYXRhWzFdID09PSAweDQ2ICYmIGFwcERhdGFbMl0gPT09IDB4NDkgJiYgYXBwRGF0YVszXSA9PT0gMHg0NiAmJiBhcHBEYXRhWzRdID09PSAwKSB7CiAgICAgICAgICAgICAgamZpZiA9IHsKICAgICAgICAgICAgICAgIHZlcnNpb246IHsKICAgICAgICAgICAgICAgICAgbWFqb3I6IGFwcERhdGFbNV0sCiAgICAgICAgICAgICAgICAgIG1pbm9yOiBhcHBEYXRhWzZdCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgZGVuc2l0eVVuaXRzOiBhcHBEYXRhWzddLAogICAgICAgICAgICAgICAgeERlbnNpdHk6IGFwcERhdGFbOF0gPDwgOCB8IGFwcERhdGFbOV0sCiAgICAgICAgICAgICAgICB5RGVuc2l0eTogYXBwRGF0YVsxMF0gPDwgOCB8IGFwcERhdGFbMTFdLAogICAgICAgICAgICAgICAgdGh1bWJXaWR0aDogYXBwRGF0YVsxMl0sCiAgICAgICAgICAgICAgICB0aHVtYkhlaWdodDogYXBwRGF0YVsxM10sCiAgICAgICAgICAgICAgICB0aHVtYkRhdGE6IGFwcERhdGEuc3ViYXJyYXkoMTQsIDE0ICsgMyAqIGFwcERhdGFbMTJdICogYXBwRGF0YVsxM10pCiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGZpbGVNYXJrZXIgPT09IDB4ZmZlZSkgewogICAgICAgICAgICBpZiAoYXBwRGF0YVswXSA9PT0gMHg0MSAmJiBhcHBEYXRhWzFdID09PSAweDY0ICYmIGFwcERhdGFbMl0gPT09IDB4NmYgJiYgYXBwRGF0YVszXSA9PT0gMHg2MiAmJiBhcHBEYXRhWzRdID09PSAweDY1KSB7CiAgICAgICAgICAgICAgYWRvYmUgPSB7CiAgICAgICAgICAgICAgICB2ZXJzaW9uOiBhcHBEYXRhWzVdIDw8IDggfCBhcHBEYXRhWzZdLAogICAgICAgICAgICAgICAgZmxhZ3MwOiBhcHBEYXRhWzddIDw8IDggfCBhcHBEYXRhWzhdLAogICAgICAgICAgICAgICAgZmxhZ3MxOiBhcHBEYXRhWzldIDw8IDggfCBhcHBEYXRhWzEwXSwKICAgICAgICAgICAgICAgIHRyYW5zZm9ybUNvZGU6IGFwcERhdGFbMTFdCiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGZmZGI6CiAgICAgICAgICBjb25zdCBxdWFudGl6YXRpb25UYWJsZXNMZW5ndGggPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgY29uc3QgcXVhbnRpemF0aW9uVGFibGVzRW5kID0gcXVhbnRpemF0aW9uVGFibGVzTGVuZ3RoICsgb2Zmc2V0IC0gMjsKICAgICAgICAgIGxldCB6OwogICAgICAgICAgd2hpbGUgKG9mZnNldCA8IHF1YW50aXphdGlvblRhYmxlc0VuZCkgewogICAgICAgICAgICBjb25zdCBxdWFudGl6YXRpb25UYWJsZVNwZWMgPSBkYXRhW29mZnNldCsrXTsKICAgICAgICAgICAgY29uc3QgdGFibGVEYXRhID0gbmV3IFVpbnQxNkFycmF5KDY0KTsKICAgICAgICAgICAgaWYgKHF1YW50aXphdGlvblRhYmxlU3BlYyA+PiA0ID09PSAwKSB7CiAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IDY0OyBqKyspIHsKICAgICAgICAgICAgICAgIHogPSBkY3RaaWdaYWdbal07CiAgICAgICAgICAgICAgICB0YWJsZURhdGFbel0gPSBkYXRhW29mZnNldCsrXTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSBpZiAocXVhbnRpemF0aW9uVGFibGVTcGVjID4+IDQgPT09IDEpIHsKICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgNjQ7IGorKykgewogICAgICAgICAgICAgICAgeiA9IGRjdFppZ1phZ1tqXTsKICAgICAgICAgICAgICAgIHRhYmxlRGF0YVt6XSA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBvZmZzZXQpOwogICAgICAgICAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoIkRRVCAtIGludmFsaWQgdGFibGUgc3BlYyIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHF1YW50aXphdGlvblRhYmxlc1txdWFudGl6YXRpb25UYWJsZVNwZWMgJiAxNV0gPSB0YWJsZURhdGE7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4ZmZjMDoKICAgICAgICBjYXNlIDB4ZmZjMToKICAgICAgICBjYXNlIDB4ZmZjMjoKICAgICAgICAgIGlmIChmcmFtZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgSnBlZ0Vycm9yKCJPbmx5IHNpbmdsZSBmcmFtZSBKUEVHcyBzdXBwb3J0ZWQiKTsKICAgICAgICAgIH0KICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgZnJhbWUgPSB7fTsKICAgICAgICAgIGZyYW1lLmV4dGVuZGVkID0gZmlsZU1hcmtlciA9PT0gMHhmZmMxOwogICAgICAgICAgZnJhbWUucHJvZ3Jlc3NpdmUgPSBmaWxlTWFya2VyID09PSAweGZmYzI7CiAgICAgICAgICBmcmFtZS5wcmVjaXNpb24gPSBkYXRhW29mZnNldCsrXTsKICAgICAgICAgIGNvbnN0IHNvZlNjYW5MaW5lcyA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBvZmZzZXQpOwogICAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgICAgICBmcmFtZS5zY2FuTGluZXMgPSBkbmxTY2FuTGluZXMgfHwgc29mU2NhbkxpbmVzOwogICAgICAgICAgZnJhbWUuc2FtcGxlc1BlckxpbmUgPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgZnJhbWUuY29tcG9uZW50cyA9IFtdOwogICAgICAgICAgZnJhbWUuY29tcG9uZW50SWRzID0ge307CiAgICAgICAgICBjb25zdCBjb21wb25lbnRzQ291bnQgPSBkYXRhW29mZnNldCsrXTsKICAgICAgICAgIGxldCBtYXhIID0gMCwKICAgICAgICAgICAgbWF4ViA9IDA7CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29tcG9uZW50c0NvdW50OyBpKyspIHsKICAgICAgICAgICAgY29uc3QgY29tcG9uZW50SWQgPSBkYXRhW29mZnNldF07CiAgICAgICAgICAgIGNvbnN0IGggPSBkYXRhW29mZnNldCArIDFdID4+IDQ7CiAgICAgICAgICAgIGNvbnN0IHYgPSBkYXRhW29mZnNldCArIDFdICYgMTU7CiAgICAgICAgICAgIGlmIChtYXhIIDwgaCkgewogICAgICAgICAgICAgIG1heEggPSBoOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChtYXhWIDwgdikgewogICAgICAgICAgICAgIG1heFYgPSB2OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IHFJZCA9IGRhdGFbb2Zmc2V0ICsgMl07CiAgICAgICAgICAgIGwgPSBmcmFtZS5jb21wb25lbnRzLnB1c2goewogICAgICAgICAgICAgIGgsCiAgICAgICAgICAgICAgdiwKICAgICAgICAgICAgICBxdWFudGl6YXRpb25JZDogcUlkLAogICAgICAgICAgICAgIHF1YW50aXphdGlvblRhYmxlOiBudWxsCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBmcmFtZS5jb21wb25lbnRJZHNbY29tcG9uZW50SWRdID0gbCAtIDE7CiAgICAgICAgICAgIG9mZnNldCArPSAzOwogICAgICAgICAgfQogICAgICAgICAgZnJhbWUubWF4SCA9IG1heEg7CiAgICAgICAgICBmcmFtZS5tYXhWID0gbWF4VjsKICAgICAgICAgIHByZXBhcmVDb21wb25lbnRzKGZyYW1lKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMHhmZmM0OgogICAgICAgICAgY29uc3QgaHVmZm1hbkxlbmd0aCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBvZmZzZXQpOwogICAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgICAgICBmb3IgKGkgPSAyOyBpIDwgaHVmZm1hbkxlbmd0aDspIHsKICAgICAgICAgICAgY29uc3QgaHVmZm1hblRhYmxlU3BlYyA9IGRhdGFbb2Zmc2V0KytdOwogICAgICAgICAgICBjb25zdCBjb2RlTGVuZ3RocyA9IG5ldyBVaW50OEFycmF5KDE2KTsKICAgICAgICAgICAgbGV0IGNvZGVMZW5ndGhTdW0gPSAwOwogICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgMTY7IGorKywgb2Zmc2V0KyspIHsKICAgICAgICAgICAgICBjb2RlTGVuZ3RoU3VtICs9IGNvZGVMZW5ndGhzW2pdID0gZGF0YVtvZmZzZXRdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGh1ZmZtYW5WYWx1ZXMgPSBuZXcgVWludDhBcnJheShjb2RlTGVuZ3RoU3VtKTsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGNvZGVMZW5ndGhTdW07IGorKywgb2Zmc2V0KyspIHsKICAgICAgICAgICAgICBodWZmbWFuVmFsdWVzW2pdID0gZGF0YVtvZmZzZXRdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGkgKz0gMTcgKyBjb2RlTGVuZ3RoU3VtOwogICAgICAgICAgICAoaHVmZm1hblRhYmxlU3BlYyA+PiA0ID09PSAwID8gaHVmZm1hblRhYmxlc0RDIDogaHVmZm1hblRhYmxlc0FDKVtodWZmbWFuVGFibGVTcGVjICYgMTVdID0gYnVpbGRIdWZmbWFuVGFibGUoY29kZUxlbmd0aHMsIGh1ZmZtYW5WYWx1ZXMpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGZmZGQ6CiAgICAgICAgICBvZmZzZXQgKz0gMjsKICAgICAgICAgIHJlc2V0SW50ZXJ2YWwgPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGZmZGE6CiAgICAgICAgICBjb25zdCBwYXJzZUROTE1hcmtlciA9ICsrbnVtU09TTWFya2VycyA9PT0gMSAmJiAhZG5sU2NhbkxpbmVzOwogICAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgICAgICBjb25zdCBzZWxlY3RvcnNDb3VudCA9IGRhdGFbb2Zmc2V0KytdLAogICAgICAgICAgICBjb21wb25lbnRzID0gW107CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgc2VsZWN0b3JzQ291bnQ7IGkrKykgewogICAgICAgICAgICBjb25zdCBpbmRleCA9IGRhdGFbb2Zmc2V0KytdOwogICAgICAgICAgICBjb25zdCBjb21wb25lbnRJbmRleCA9IGZyYW1lLmNvbXBvbmVudElkc1tpbmRleF07CiAgICAgICAgICAgIGNvbnN0IGNvbXBvbmVudCA9IGZyYW1lLmNvbXBvbmVudHNbY29tcG9uZW50SW5kZXhdOwogICAgICAgICAgICBjb21wb25lbnQuaW5kZXggPSBpbmRleDsKICAgICAgICAgICAgY29uc3QgdGFibGVTcGVjID0gZGF0YVtvZmZzZXQrK107CiAgICAgICAgICAgIGNvbXBvbmVudC5odWZmbWFuVGFibGVEQyA9IGh1ZmZtYW5UYWJsZXNEQ1t0YWJsZVNwZWMgPj4gNF07CiAgICAgICAgICAgIGNvbXBvbmVudC5odWZmbWFuVGFibGVBQyA9IGh1ZmZtYW5UYWJsZXNBQ1t0YWJsZVNwZWMgJiAxNV07CiAgICAgICAgICAgIGNvbXBvbmVudHMucHVzaChjb21wb25lbnQpOwogICAgICAgICAgfQogICAgICAgICAgY29uc3Qgc3BlY3RyYWxTdGFydCA9IGRhdGFbb2Zmc2V0KytdLAogICAgICAgICAgICBzcGVjdHJhbEVuZCA9IGRhdGFbb2Zmc2V0KytdLAogICAgICAgICAgICBzdWNjZXNzaXZlQXBwcm94aW1hdGlvbiA9IGRhdGFbb2Zmc2V0KytdOwogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgY29uc3QgcHJvY2Vzc2VkID0gZGVjb2RlU2NhbihkYXRhLCBvZmZzZXQsIGZyYW1lLCBjb21wb25lbnRzLCByZXNldEludGVydmFsLCBzcGVjdHJhbFN0YXJ0LCBzcGVjdHJhbEVuZCwgc3VjY2Vzc2l2ZUFwcHJveGltYXRpb24gPj4gNCwgc3VjY2Vzc2l2ZUFwcHJveGltYXRpb24gJiAxNSwgcGFyc2VETkxNYXJrZXIpOwogICAgICAgICAgICBvZmZzZXQgKz0gcHJvY2Vzc2VkOwogICAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgRE5MTWFya2VyRXJyb3IpIHsKICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYCR7ZXgubWVzc2FnZX0gLS0gYXR0ZW1wdGluZyB0byByZS1wYXJzZSB0aGUgSlBFRyBpbWFnZS5gKTsKICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wYXJzZShkYXRhLCB7CiAgICAgICAgICAgICAgICBkbmxTY2FuTGluZXM6IGV4LnNjYW5MaW5lcwogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9IGVsc2UgaWYgKGV4IGluc3RhbmNlb2YgRU9JTWFya2VyRXJyb3IpIHsKICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYCR7ZXgubWVzc2FnZX0gLS0gaWdub3JpbmcgdGhlIHJlc3Qgb2YgdGhlIGltYWdlIGRhdGEuYCk7CiAgICAgICAgICAgICAgYnJlYWsgbWFya2VyTG9vcDsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aHJvdyBleDsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMHhmZmRjOgogICAgICAgICAgb2Zmc2V0ICs9IDQ7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4ZmZmZjoKICAgICAgICAgIGlmIChkYXRhW29mZnNldF0gIT09IDB4ZmYpIHsKICAgICAgICAgICAgb2Zmc2V0LS07CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgY29uc3QgbmV4dEZpbGVNYXJrZXIgPSBmaW5kTmV4dEZpbGVNYXJrZXIoZGF0YSwgb2Zmc2V0IC0gMiwgb2Zmc2V0IC0gMyk7CiAgICAgICAgICBpZiAobmV4dEZpbGVNYXJrZXIgJiYgbmV4dEZpbGVNYXJrZXIuaW52YWxpZCkgewogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoIkpwZWdJbWFnZS5wYXJzZSAtIHVuZXhwZWN0ZWQgZGF0YSwgY3VycmVudCBtYXJrZXIgaXM6ICIgKyBuZXh0RmlsZU1hcmtlci5pbnZhbGlkKTsKICAgICAgICAgICAgb2Zmc2V0ID0gbmV4dEZpbGVNYXJrZXIub2Zmc2V0OwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghbmV4dEZpbGVNYXJrZXIgfHwgb2Zmc2V0ID49IGRhdGEubGVuZ3RoIC0gMSkgewogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoIkpwZWdJbWFnZS5wYXJzZSAtIHJlYWNoZWQgdGhlIGVuZCBvZiB0aGUgaW1hZ2UgZGF0YSAiICsgIndpdGhvdXQgZmluZGluZyBhbiBFT0kgbWFya2VyICgweEZGRDkpLiIpOwogICAgICAgICAgICBicmVhayBtYXJrZXJMb29wOwogICAgICAgICAgfQogICAgICAgICAgdGhyb3cgbmV3IEpwZWdFcnJvcigiSnBlZ0ltYWdlLnBhcnNlIC0gdW5rbm93biBtYXJrZXI6ICIgKyBmaWxlTWFya2VyLnRvU3RyaW5nKDE2KSk7CiAgICAgIH0KICAgICAgZmlsZU1hcmtlciA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBvZmZzZXQpOwogICAgICBvZmZzZXQgKz0gMjsKICAgIH0KICAgIHRoaXMud2lkdGggPSBmcmFtZS5zYW1wbGVzUGVyTGluZTsKICAgIHRoaXMuaGVpZ2h0ID0gZnJhbWUuc2NhbkxpbmVzOwogICAgdGhpcy5qZmlmID0gamZpZjsKICAgIHRoaXMuYWRvYmUgPSBhZG9iZTsKICAgIHRoaXMuY29tcG9uZW50cyA9IFtdOwogICAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgZnJhbWUuY29tcG9uZW50cykgewogICAgICBjb25zdCBxdWFudGl6YXRpb25UYWJsZSA9IHF1YW50aXphdGlvblRhYmxlc1tjb21wb25lbnQucXVhbnRpemF0aW9uSWRdOwogICAgICBpZiAocXVhbnRpemF0aW9uVGFibGUpIHsKICAgICAgICBjb21wb25lbnQucXVhbnRpemF0aW9uVGFibGUgPSBxdWFudGl6YXRpb25UYWJsZTsKICAgICAgfQogICAgICB0aGlzLmNvbXBvbmVudHMucHVzaCh7CiAgICAgICAgaW5kZXg6IGNvbXBvbmVudC5pbmRleCwKICAgICAgICBvdXRwdXQ6IGJ1aWxkQ29tcG9uZW50RGF0YShmcmFtZSwgY29tcG9uZW50KSwKICAgICAgICBzY2FsZVg6IGNvbXBvbmVudC5oIC8gZnJhbWUubWF4SCwKICAgICAgICBzY2FsZVk6IGNvbXBvbmVudC52IC8gZnJhbWUubWF4ViwKICAgICAgICBibG9ja3NQZXJMaW5lOiBjb21wb25lbnQuYmxvY2tzUGVyTGluZSwKICAgICAgICBibG9ja3NQZXJDb2x1bW46IGNvbXBvbmVudC5ibG9ja3NQZXJDb2x1bW4KICAgICAgfSk7CiAgICB9CiAgICB0aGlzLm51bUNvbXBvbmVudHMgPSB0aGlzLmNvbXBvbmVudHMubGVuZ3RoOwogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9CiAgX2dldExpbmVhcml6ZWRCbG9ja0RhdGEod2lkdGgsIGhlaWdodCkgewogICAgbGV0IGlzU291cmNlUERGID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBmYWxzZTsKICAgIGNvbnN0IHNjYWxlWCA9IHRoaXMud2lkdGggLyB3aWR0aCwKICAgICAgc2NhbGVZID0gdGhpcy5oZWlnaHQgLyBoZWlnaHQ7CiAgICBsZXQgY29tcG9uZW50LCBjb21wb25lbnRTY2FsZVgsIGNvbXBvbmVudFNjYWxlWSwgYmxvY2tzUGVyU2NhbmxpbmU7CiAgICBsZXQgeCwgeSwgaSwgaiwgazsKICAgIGxldCBpbmRleDsKICAgIGxldCBvZmZzZXQgPSAwOwogICAgbGV0IG91dHB1dDsKICAgIGNvbnN0IG51bUNvbXBvbmVudHMgPSB0aGlzLmNvbXBvbmVudHMubGVuZ3RoOwogICAgY29uc3QgZGF0YUxlbmd0aCA9IHdpZHRoICogaGVpZ2h0ICogbnVtQ29tcG9uZW50czsKICAgIGNvbnN0IGRhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoZGF0YUxlbmd0aCk7CiAgICBjb25zdCB4U2NhbGVCbG9ja09mZnNldCA9IG5ldyBVaW50MzJBcnJheSh3aWR0aCk7CiAgICBjb25zdCBtYXNrM0xTQiA9IDB4ZmZmZmZmZjg7CiAgICBsZXQgbGFzdENvbXBvbmVudFNjYWxlWDsKICAgIGZvciAoaSA9IDA7IGkgPCBudW1Db21wb25lbnRzOyBpKyspIHsKICAgICAgY29tcG9uZW50ID0gdGhpcy5jb21wb25lbnRzW2ldOwogICAgICBjb21wb25lbnRTY2FsZVggPSBjb21wb25lbnQuc2NhbGVYICogc2NhbGVYOwogICAgICBjb21wb25lbnRTY2FsZVkgPSBjb21wb25lbnQuc2NhbGVZICogc2NhbGVZOwogICAgICBvZmZzZXQgPSBpOwogICAgICBvdXRwdXQgPSBjb21wb25lbnQub3V0cHV0OwogICAgICBibG9ja3NQZXJTY2FubGluZSA9IGNvbXBvbmVudC5ibG9ja3NQZXJMaW5lICsgMSA8PCAzOwogICAgICBpZiAoY29tcG9uZW50U2NhbGVYICE9PSBsYXN0Q29tcG9uZW50U2NhbGVYKSB7CiAgICAgICAgZm9yICh4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHsKICAgICAgICAgIGogPSAwIHwgeCAqIGNvbXBvbmVudFNjYWxlWDsKICAgICAgICAgIHhTY2FsZUJsb2NrT2Zmc2V0W3hdID0gKGogJiBtYXNrM0xTQikgPDwgMyB8IGogJiA3OwogICAgICAgIH0KICAgICAgICBsYXN0Q29tcG9uZW50U2NhbGVYID0gY29tcG9uZW50U2NhbGVYOwogICAgICB9CiAgICAgIGZvciAoeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykgewogICAgICAgIGogPSAwIHwgeSAqIGNvbXBvbmVudFNjYWxlWTsKICAgICAgICBpbmRleCA9IGJsb2Nrc1BlclNjYW5saW5lICogKGogJiBtYXNrM0xTQikgfCAoaiAmIDcpIDw8IDM7CiAgICAgICAgZm9yICh4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHsKICAgICAgICAgIGRhdGFbb2Zmc2V0XSA9IG91dHB1dFtpbmRleCArIHhTY2FsZUJsb2NrT2Zmc2V0W3hdXTsKICAgICAgICAgIG9mZnNldCArPSBudW1Db21wb25lbnRzOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgbGV0IHRyYW5zZm9ybSA9IHRoaXMuX2RlY29kZVRyYW5zZm9ybTsKICAgIGlmICghaXNTb3VyY2VQREYgJiYgbnVtQ29tcG9uZW50cyA9PT0gNCAmJiAhdHJhbnNmb3JtKSB7CiAgICAgIHRyYW5zZm9ybSA9IG5ldyBJbnQzMkFycmF5KFstMjU2LCAyNTUsIC0yNTYsIDI1NSwgLTI1NiwgMjU1LCAtMjU2LCAyNTVdKTsKICAgIH0KICAgIGlmICh0cmFuc2Zvcm0pIHsKICAgICAgZm9yIChpID0gMDsgaSA8IGRhdGFMZW5ndGg7KSB7CiAgICAgICAgZm9yIChqID0gMCwgayA9IDA7IGogPCBudW1Db21wb25lbnRzOyBqKyssIGkrKywgayArPSAyKSB7CiAgICAgICAgICBkYXRhW2ldID0gKGRhdGFbaV0gKiB0cmFuc2Zvcm1ba10gPj4gOCkgKyB0cmFuc2Zvcm1bayArIDFdOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIGRhdGE7CiAgfQogIGdldCBfaXNDb2xvckNvbnZlcnNpb25OZWVkZWQoKSB7CiAgICBpZiAodGhpcy5hZG9iZSkgewogICAgICByZXR1cm4gISF0aGlzLmFkb2JlLnRyYW5zZm9ybUNvZGU7CiAgICB9CiAgICBpZiAodGhpcy5udW1Db21wb25lbnRzID09PSAzKSB7CiAgICAgIGlmICh0aGlzLl9jb2xvclRyYW5zZm9ybSA9PT0gMCkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfSBlbHNlIGlmICh0aGlzLmNvbXBvbmVudHNbMF0uaW5kZXggPT09IDB4NTIgJiYgdGhpcy5jb21wb25lbnRzWzFdLmluZGV4ID09PSAweDQ3ICYmIHRoaXMuY29tcG9uZW50c1syXS5pbmRleCA9PT0gMHg0MikgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmICh0aGlzLl9jb2xvclRyYW5zZm9ybSA9PT0gMSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9CiAgX2NvbnZlcnRZY2NUb1JnYihkYXRhKSB7CiAgICBsZXQgWSwgQ2IsIENyOwogICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IGRhdGEubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHsKICAgICAgWSA9IGRhdGFbaV07CiAgICAgIENiID0gZGF0YVtpICsgMV07CiAgICAgIENyID0gZGF0YVtpICsgMl07CiAgICAgIGRhdGFbaV0gPSBZIC0gMTc5LjQ1NiArIDEuNDAyICogQ3I7CiAgICAgIGRhdGFbaSArIDFdID0gWSArIDEzNS40NTkgLSAwLjM0NCAqIENiIC0gMC43MTQgKiBDcjsKICAgICAgZGF0YVtpICsgMl0gPSBZIC0gMjI2LjgxNiArIDEuNzcyICogQ2I7CiAgICB9CiAgICByZXR1cm4gZGF0YTsKICB9CiAgX2NvbnZlcnRZY2NUb1JnYmEoZGF0YSwgb3V0KSB7CiAgICBmb3IgKGxldCBpID0gMCwgaiA9IDAsIGxlbmd0aCA9IGRhdGEubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpICs9IDMsIGogKz0gNCkgewogICAgICBjb25zdCBZID0gZGF0YVtpXTsKICAgICAgY29uc3QgQ2IgPSBkYXRhW2kgKyAxXTsKICAgICAgY29uc3QgQ3IgPSBkYXRhW2kgKyAyXTsKICAgICAgb3V0W2pdID0gWSAtIDE3OS40NTYgKyAxLjQwMiAqIENyOwogICAgICBvdXRbaiArIDFdID0gWSArIDEzNS40NTkgLSAwLjM0NCAqIENiIC0gMC43MTQgKiBDcjsKICAgICAgb3V0W2ogKyAyXSA9IFkgLSAyMjYuODE2ICsgMS43NzIgKiBDYjsKICAgICAgb3V0W2ogKyAzXSA9IDI1NTsKICAgIH0KICAgIHJldHVybiBvdXQ7CiAgfQogIF9jb252ZXJ0WWNja1RvUmdiKGRhdGEpIHsKICAgIGxldCBZLCBDYiwgQ3IsIGs7CiAgICBsZXQgb2Zmc2V0ID0gMDsKICAgIGZvciAobGV0IGkgPSAwLCBsZW5ndGggPSBkYXRhLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSArPSA0KSB7CiAgICAgIFkgPSBkYXRhW2ldOwogICAgICBDYiA9IGRhdGFbaSArIDFdOwogICAgICBDciA9IGRhdGFbaSArIDJdOwogICAgICBrID0gZGF0YVtpICsgM107CiAgICAgIGRhdGFbb2Zmc2V0KytdID0gLTEyMi42NzE5NTQwNjg5NCArIENiICogKC02LjYwNjM1NjY5NDIwMzY0ZS01ICogQ2IgKyAwLjAwMDQzNzEzMDQ3NTkyNjIzMiAqIENyIC0gNS40MDgwNjEwMDY0NTk5ZS01ICogWSArIDAuMDAwNDg0NDk3OTcxMjAyODEgKiBrIC0gMC4xNTQzNjIxNTE4NzExMjYpICsgQ3IgKiAoLTAuMDAwOTU3OTY0Mzc4NDQ1NzczICogQ3IgKyAwLjAwMDgxNzA3NjkxMTM0NjYyNSAqIFkgLSAwLjAwNDc3MjcxNDA1NDA4NzQ3ICogayArIDEuNTMzODAyNTMyMjE3MzQpICsgWSAqICgwLjAwMDk2MTI1MDE4NDEzMDY4OCAqIFkgLSAwLjAwMjY2MjU3MzMyMjgzOTMzICogayArIDAuNDgzNTcwODg0NTEyNjUpICsgayAqICgtMC4wMDAzMzYxOTcxNzc2MTgzOTQgKiBrICsgMC40ODQ3OTE1NjE0OTA3NzYpOwogICAgICBkYXRhW29mZnNldCsrXSA9IDEwNy4yNjgwMzkzOTc3MjQgKyBDYiAqICgyLjE5OTI3MTA0NTI1NzQxZS01ICogQ2IgLSAwLjAwMDY0MDk5MjAxODI5Nzk0NSAqIENyICsgMC4wMDA2NTkzOTcwMDEyNDU1NzcgKiBZICsgMC4wMDA0MjYxMDU2NTI5Mzg4MzcgKiBrIC0gMC4xNzY0OTE3OTI0NjI4NzUpICsgQ3IgKiAoLTAuMDAwNzc4MjY5OTQxNTEzNjgzICogQ3IgKyAwLjAwMTMwODcyMjYxNDA4Mjc1ICogWSArIDAuMDAwNzcwNDgyNjMxODAxMTMyICogayAtIDAuMTUxMDUxNDkyNzc1NTYyKSArIFkgKiAoMC4wMDEyNjkzNTM2ODExNDg0MyAqIFkgLSAwLjAwMjY1MDkwMTg5MDEwODk4ICogayArIDAuMjU4MDI5MTAyMDY4NDUpICsgayAqICgtMC4wMDAzMTg5MTMxMTc1ODgzMjggKiBrIC0gMC4yMTM3NDI0MDAzMjM2NjUpOwogICAgICBkYXRhW29mZnNldCsrXSA9IC0yMC44MTAwMTI1NDY5NDcgKyBDYiAqICgtMC4wMDA1NzAxMTUxOTY5NzM2NzcgKiBDYiAtIDIuNjM0MDkwNTEwMDQ1ODllLTUgKiBDciArIDAuMDAyMDc0MTA4ODExNTAxMiAqIFkgLSAwLjAwMjg4MjYwMjM2ODUzNDQyICogayArIDAuODE0MjcyOTY4MzU5Mjk1KSArIENyICogKC0xLjUzNDk2MDU3NDQwOTc1ZS01ICogQ3IgLSAwLjAwMDEzMjY4OTA0Mzk2MTQ0NiAqIFkgKyAwLjAwMDU2MDgzMzY5MTI0MjgxMiAqIGsgLSAwLjE5NTE1MjAyNzUzNDA0OSkgKyBZICogKDAuMDAxNzQ0MTgxMzI5Mjc1ODIgKiBZIC0gMC4wMDI1NTI0MzMyMTQzOTM0NyAqIGsgKyAwLjExNjkzNTAyMDQ2NTE0NSkgKyBrICogKC0wLjAwMDM0MzUzMTk5NjUxMDU1NSAqIGsgKyAwLjI0MTY1MjYwMjMyNDA3KTsKICAgIH0KICAgIHJldHVybiBkYXRhLnN1YmFycmF5KDAsIG9mZnNldCk7CiAgfQogIF9jb252ZXJ0WWNja1RvUmdiYShkYXRhKSB7CiAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gZGF0YS5sZW5ndGg7IGkgPCBsZW5ndGg7IGkgKz0gNCkgewogICAgICBjb25zdCBZID0gZGF0YVtpXTsKICAgICAgY29uc3QgQ2IgPSBkYXRhW2kgKyAxXTsKICAgICAgY29uc3QgQ3IgPSBkYXRhW2kgKyAyXTsKICAgICAgY29uc3QgayA9IGRhdGFbaSArIDNdOwogICAgICBkYXRhW2ldID0gLTEyMi42NzE5NTQwNjg5NCArIENiICogKC02LjYwNjM1NjY5NDIwMzY0ZS01ICogQ2IgKyAwLjAwMDQzNzEzMDQ3NTkyNjIzMiAqIENyIC0gNS40MDgwNjEwMDY0NTk5ZS01ICogWSArIDAuMDAwNDg0NDk3OTcxMjAyODEgKiBrIC0gMC4xNTQzNjIxNTE4NzExMjYpICsgQ3IgKiAoLTAuMDAwOTU3OTY0Mzc4NDQ1NzczICogQ3IgKyAwLjAwMDgxNzA3NjkxMTM0NjYyNSAqIFkgLSAwLjAwNDc3MjcxNDA1NDA4NzQ3ICogayArIDEuNTMzODAyNTMyMjE3MzQpICsgWSAqICgwLjAwMDk2MTI1MDE4NDEzMDY4OCAqIFkgLSAwLjAwMjY2MjU3MzMyMjgzOTMzICogayArIDAuNDgzNTcwODg0NTEyNjUpICsgayAqICgtMC4wMDAzMzYxOTcxNzc2MTgzOTQgKiBrICsgMC40ODQ3OTE1NjE0OTA3NzYpOwogICAgICBkYXRhW2kgKyAxXSA9IDEwNy4yNjgwMzkzOTc3MjQgKyBDYiAqICgyLjE5OTI3MTA0NTI1NzQxZS01ICogQ2IgLSAwLjAwMDY0MDk5MjAxODI5Nzk0NSAqIENyICsgMC4wMDA2NTkzOTcwMDEyNDU1NzcgKiBZICsgMC4wMDA0MjYxMDU2NTI5Mzg4MzcgKiBrIC0gMC4xNzY0OTE3OTI0NjI4NzUpICsgQ3IgKiAoLTAuMDAwNzc4MjY5OTQxNTEzNjgzICogQ3IgKyAwLjAwMTMwODcyMjYxNDA4Mjc1ICogWSArIDAuMDAwNzcwNDgyNjMxODAxMTMyICogayAtIDAuMTUxMDUxNDkyNzc1NTYyKSArIFkgKiAoMC4wMDEyNjkzNTM2ODExNDg0MyAqIFkgLSAwLjAwMjY1MDkwMTg5MDEwODk4ICogayArIDAuMjU4MDI5MTAyMDY4NDUpICsgayAqICgtMC4wMDAzMTg5MTMxMTc1ODgzMjggKiBrIC0gMC4yMTM3NDI0MDAzMjM2NjUpOwogICAgICBkYXRhW2kgKyAyXSA9IC0yMC44MTAwMTI1NDY5NDcgKyBDYiAqICgtMC4wMDA1NzAxMTUxOTY5NzM2NzcgKiBDYiAtIDIuNjM0MDkwNTEwMDQ1ODllLTUgKiBDciArIDAuMDAyMDc0MTA4ODExNTAxMiAqIFkgLSAwLjAwMjg4MjYwMjM2ODUzNDQyICogayArIDAuODE0MjcyOTY4MzU5Mjk1KSArIENyICogKC0xLjUzNDk2MDU3NDQwOTc1ZS01ICogQ3IgLSAwLjAwMDEzMjY4OTA0Mzk2MTQ0NiAqIFkgKyAwLjAwMDU2MDgzMzY5MTI0MjgxMiAqIGsgLSAwLjE5NTE1MjAyNzUzNDA0OSkgKyBZICogKDAuMDAxNzQ0MTgxMzI5Mjc1ODIgKiBZIC0gMC4wMDI1NTI0MzMyMTQzOTM0NyAqIGsgKyAwLjExNjkzNTAyMDQ2NTE0NSkgKyBrICogKC0wLjAwMDM0MzUzMTk5NjUxMDU1NSAqIGsgKyAwLjI0MTY1MjYwMjMyNDA3KTsKICAgICAgZGF0YVtpICsgM10gPSAyNTU7CiAgICB9CiAgICByZXR1cm4gZGF0YTsKICB9CiAgX2NvbnZlcnRZY2NrVG9DbXlrKGRhdGEpIHsKICAgIGxldCBZLCBDYiwgQ3I7CiAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gZGF0YS5sZW5ndGg7IGkgPCBsZW5ndGg7IGkgKz0gNCkgewogICAgICBZID0gZGF0YVtpXTsKICAgICAgQ2IgPSBkYXRhW2kgKyAxXTsKICAgICAgQ3IgPSBkYXRhW2kgKyAyXTsKICAgICAgZGF0YVtpXSA9IDQzNC40NTYgLSBZIC0gMS40MDIgKiBDcjsKICAgICAgZGF0YVtpICsgMV0gPSAxMTkuNTQxIC0gWSArIDAuMzQ0ICogQ2IgKyAwLjcxNCAqIENyOwogICAgICBkYXRhW2kgKyAyXSA9IDQ4MS44MTYgLSBZIC0gMS43NzIgKiBDYjsKICAgIH0KICAgIHJldHVybiBkYXRhOwogIH0KICBfY29udmVydENteWtUb1JnYihkYXRhKSB7CiAgICBsZXQgYywgbSwgeSwgazsKICAgIGxldCBvZmZzZXQgPSAwOwogICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IGRhdGEubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpICs9IDQpIHsKICAgICAgYyA9IGRhdGFbaV07CiAgICAgIG0gPSBkYXRhW2kgKyAxXTsKICAgICAgeSA9IGRhdGFbaSArIDJdOwogICAgICBrID0gZGF0YVtpICsgM107CiAgICAgIGRhdGFbb2Zmc2V0KytdID0gMjU1ICsgYyAqICgtMC4wMDAwNjc0NzE0NzA3MzYwMjQ0MSAqIGMgKyAwLjAwMDgzNzkyNjIxMjEwMTM3MjcgKiBtICsgMC4wMDAyODk0NzE4MTg4NjQzMjk0ICogeSArIDAuMDAzMjY0MjMxMDU3NTM3ODA2ICogayAtIDEuMTE4NTYxMTg2NzIwMzkzNykgKyBtICogKDAuMDAwMDI2Mzc0MTA3NjE2MDg5NDA1ICogbSAtIDAuMDAwMDg2MjY5NDkxNTg2Mzg1NzIgKiB5IC0gMC4wMDAyNzQ4NzY5MDY3NDk5NDkxICogayAtIDAuMDIxNTU2ODg3OTQ5Nzg5NjcpICsgeSAqICgtMC4wMDAwMzg3ODA5OTIxMjg2OTM2MyAqIHkgLSAwLjAwMDMyNjc4MDgyNzk0ODUyODYgKiBrICsgMC4wNjg2NzQyMjM4NTk1MzQ1KSAtIGsgKiAoMC4wMDAzMzYxOTcxNzc2MTgzOTM3ICogayArIDAuNzQzMDY1OTE1MTM0MjI1NCk7CiAgICAgIGRhdGFbb2Zmc2V0KytdID0gMjU1ICsgYyAqICgwLjAwMDEzNTk2MzcyODEzNTg4ODQ4ICogYyArIDAuMDAwOTI0NTM3MTMyNTczNTg1ICogbSArIDAuMDAwMTA1NjczNTk2MTg2ODM1OTMgKiB5ICsgMC4wMDA0NzkxODY0Njg3NDM2NTEyICogayAtIDAuMzEwOTY4OTU4NzUxNTg3NSkgKyBtICogKC0wLjAwMDIzNTQ1MzQ2MTA4MzcwMzQ0ICogbSArIDAuMDAwMjcwMjg0NTI1MzUzNDcxNCAqIHkgKyAwLjAwMjAyMDAzMDg5NzczMDcxNTYgKiBrIC0gMC43NDg4MDUyMTY3MDE1NDk0KSArIHkgKiAoMC4wMDAwNjgzNDgxNTk5ODIzNTY2MiAqIHkgKyAwLjAwMDE1MTY4NDUyMzYzNDYwOTczICogayAtIDAuMDk3NTE5Mjc3NzQ3Mjg5MzMpIC0gayAqICgwLjAwMDMxODkxMzExNzU4ODMyODEgKiBrICsgMC43MzY0ODgzODA3NzMzMTY4KTsKICAgICAgZGF0YVtvZmZzZXQrK10gPSAyNTUgKyBjICogKDAuMDAwMDEzNTk4NjUwNDExMzg1MzA3ICogYyArIDAuMDAwMTI0MjM5NTYxNzU0OTA4NTEgKiBtICsgMC4wMDA0NzUxOTg1MDk3NTgzNTg5ICogeSAtIDAuMDAwMDAzNjcyOTMxNzQ3NjYzMDQyMiAqIGsgLSAwLjA1NTYyMTg2OTgwMjY0MDM0KSArIG0gKiAoMC4wMDAxNjE0MTM4MDU5ODcyNDY3NiAqIG0gKyAwLjAwMDk2OTIyMzkxMzA3MjUxODYgKiB5ICsgMC4wMDA3NzgyNjkyNDUwMDM2MjUzICogayAtIDAuNDQwMTUyMzIzNjc1MjY0NjMpICsgeSAqICg1LjA2ODg4MjkxNDA2ODc2OWUtNyAqIHkgKyAwLjAwMTc3NzgzNjkwMTEzNzUwNzEgKiBrIC0gMC43NTkxNDU0NjQ5NzQ5NjA5KSAtIGsgKiAoMC4wMDAzNDM1MzE5OTY1MTA1NTUzICogayArIDAuNzA2Mzc3MDE4NjE2MDE0NCk7CiAgICB9CiAgICByZXR1cm4gZGF0YS5zdWJhcnJheSgwLCBvZmZzZXQpOwogIH0KICBfY29udmVydENteWtUb1JnYmEoZGF0YSkgewogICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IGRhdGEubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpICs9IDQpIHsKICAgICAgY29uc3QgYyA9IGRhdGFbaV07CiAgICAgIGNvbnN0IG0gPSBkYXRhW2kgKyAxXTsKICAgICAgY29uc3QgeSA9IGRhdGFbaSArIDJdOwogICAgICBjb25zdCBrID0gZGF0YVtpICsgM107CiAgICAgIGRhdGFbaV0gPSAyNTUgKyBjICogKC0wLjAwMDA2NzQ3MTQ3MDczNjAyNDQxICogYyArIDAuMDAwODM3OTI2MjEyMTAxMzcyNyAqIG0gKyAwLjAwMDI4OTQ3MTgxODg2NDMyOTQgKiB5ICsgMC4wMDMyNjQyMzEwNTc1Mzc4MDYgKiBrIC0gMS4xMTg1NjExODY3MjAzOTM3KSArIG0gKiAoMC4wMDAwMjYzNzQxMDc2MTYwODk0MDUgKiBtIC0gMC4wMDAwODYyNjk0OTE1ODYzODU3MiAqIHkgLSAwLjAwMDI3NDg3NjkwNjc0OTk0OTEgKiBrIC0gMC4wMjE1NTY4ODc5NDk3ODk2NykgKyB5ICogKC0wLjAwMDAzODc4MDk5MjEyODY5MzYzICogeSAtIDAuMDAwMzI2NzgwODI3OTQ4NTI4NiAqIGsgKyAwLjA2ODY3NDIyMzg1OTUzNDUpIC0gayAqICgwLjAwMDMzNjE5NzE3NzYxODM5MzcgKiBrICsgMC43NDMwNjU5MTUxMzQyMjU0KTsKICAgICAgZGF0YVtpICsgMV0gPSAyNTUgKyBjICogKDAuMDAwMTM1OTYzNzI4MTM1ODg4NDggKiBjICsgMC4wMDA5MjQ1MzcxMzI1NzM1ODUgKiBtICsgMC4wMDAxMDU2NzM1OTYxODY4MzU5MyAqIHkgKyAwLjAwMDQ3OTE4NjQ2ODc0MzY1MTIgKiBrIC0gMC4zMTA5Njg5NTg3NTE1ODc1KSArIG0gKiAoLTAuMDAwMjM1NDUzNDYxMDgzNzAzNDQgKiBtICsgMC4wMDAyNzAyODQ1MjUzNTM0NzE0ICogeSArIDAuMDAyMDIwMDMwODk3NzMwNzE1NiAqIGsgLSAwLjc0ODgwNTIxNjcwMTU0OTQpICsgeSAqICgwLjAwMDA2ODM0ODE1OTk4MjM1NjYyICogeSArIDAuMDAwMTUxNjg0NTIzNjM0NjA5NzMgKiBrIC0gMC4wOTc1MTkyNzc3NDcyODkzMykgLSBrICogKDAuMDAwMzE4OTEzMTE3NTg4MzI4MSAqIGsgKyAwLjczNjQ4ODM4MDc3MzMxNjgpOwogICAgICBkYXRhW2kgKyAyXSA9IDI1NSArIGMgKiAoMC4wMDAwMTM1OTg2NTA0MTEzODUzMDcgKiBjICsgMC4wMDAxMjQyMzk1NjE3NTQ5MDg1MSAqIG0gKyAwLjAwMDQ3NTE5ODUwOTc1ODM1ODkgKiB5IC0gMC4wMDAwMDM2NzI5MzE3NDc2NjMwNDIyICogayAtIDAuMDU1NjIxODY5ODAyNjQwMzQpICsgbSAqICgwLjAwMDE2MTQxMzgwNTk4NzI0Njc2ICogbSArIDAuMDAwOTY5MjIzOTEzMDcyNTE4NiAqIHkgKyAwLjAwMDc3ODI2OTI0NTAwMzYyNTMgKiBrIC0gMC40NDAxNTIzMjM2NzUyNjQ2MykgKyB5ICogKDUuMDY4ODgyOTE0MDY4NzY5ZS03ICogeSArIDAuMDAxNzc3ODM2OTAxMTM3NTA3MSAqIGsgLSAwLjc1OTE0NTQ2NDk3NDk2MDkpIC0gayAqICgwLjAwMDM0MzUzMTk5NjUxMDU1NTMgKiBrICsgMC43MDYzNzcwMTg2MTYwMTQ0KTsKICAgICAgZGF0YVtpICsgM10gPSAyNTU7CiAgICB9CiAgICByZXR1cm4gZGF0YTsKICB9CiAgZ2V0RGF0YShfcmVmKSB7CiAgICBsZXQgewogICAgICB3aWR0aCwKICAgICAgaGVpZ2h0LAogICAgICBmb3JjZVJHQkEgPSBmYWxzZSwKICAgICAgZm9yY2VSR0IgPSBmYWxzZSwKICAgICAgaXNTb3VyY2VQREYgPSBmYWxzZQogICAgfSA9IF9yZWY7CiAgICBpZiAodGhpcy5udW1Db21wb25lbnRzID4gNCkgewogICAgICB0aHJvdyBuZXcgSnBlZ0Vycm9yKCJVbnN1cHBvcnRlZCBjb2xvciBtb2RlIik7CiAgICB9CiAgICBjb25zdCBkYXRhID0gdGhpcy5fZ2V0TGluZWFyaXplZEJsb2NrRGF0YSh3aWR0aCwgaGVpZ2h0LCBpc1NvdXJjZVBERik7CiAgICBpZiAodGhpcy5udW1Db21wb25lbnRzID09PSAxICYmIChmb3JjZVJHQkEgfHwgZm9yY2VSR0IpKSB7CiAgICAgIGNvbnN0IGxlbiA9IGRhdGEubGVuZ3RoICogKGZvcmNlUkdCQSA/IDQgOiAzKTsKICAgICAgY29uc3QgcmdiYURhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkobGVuKTsKICAgICAgbGV0IG9mZnNldCA9IDA7CiAgICAgIGlmIChmb3JjZVJHQkEpIHsKICAgICAgICAoMCwgX2ltYWdlX3V0aWxzLmdyYXlUb1JHQkEpKGRhdGEsIG5ldyBVaW50MzJBcnJheShyZ2JhRGF0YS5idWZmZXIpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBmb3IgKGNvbnN0IGdyYXlDb2xvciBvZiBkYXRhKSB7CiAgICAgICAgICByZ2JhRGF0YVtvZmZzZXQrK10gPSBncmF5Q29sb3I7CiAgICAgICAgICByZ2JhRGF0YVtvZmZzZXQrK10gPSBncmF5Q29sb3I7CiAgICAgICAgICByZ2JhRGF0YVtvZmZzZXQrK10gPSBncmF5Q29sb3I7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiByZ2JhRGF0YTsKICAgIH0gZWxzZSBpZiAodGhpcy5udW1Db21wb25lbnRzID09PSAzICYmIHRoaXMuX2lzQ29sb3JDb252ZXJzaW9uTmVlZGVkKSB7CiAgICAgIGlmIChmb3JjZVJHQkEpIHsKICAgICAgICBjb25zdCByZ2JhRGF0YSA9IG5ldyBVaW50OENsYW1wZWRBcnJheShkYXRhLmxlbmd0aCAvIDMgKiA0KTsKICAgICAgICByZXR1cm4gdGhpcy5fY29udmVydFljY1RvUmdiYShkYXRhLCByZ2JhRGF0YSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuX2NvbnZlcnRZY2NUb1JnYihkYXRhKTsKICAgIH0gZWxzZSBpZiAodGhpcy5udW1Db21wb25lbnRzID09PSA0KSB7CiAgICAgIGlmICh0aGlzLl9pc0NvbG9yQ29udmVyc2lvbk5lZWRlZCkgewogICAgICAgIGlmIChmb3JjZVJHQkEpIHsKICAgICAgICAgIHJldHVybiB0aGlzLl9jb252ZXJ0WWNja1RvUmdiYShkYXRhKTsKICAgICAgICB9CiAgICAgICAgaWYgKGZvcmNlUkdCKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fY29udmVydFljY2tUb1JnYihkYXRhKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnZlcnRZY2NrVG9DbXlrKGRhdGEpOwogICAgICB9IGVsc2UgaWYgKGZvcmNlUkdCQSkgewogICAgICAgIHJldHVybiB0aGlzLl9jb252ZXJ0Q215a1RvUmdiYShkYXRhKTsKICAgICAgfSBlbHNlIGlmIChmb3JjZVJHQikgewogICAgICAgIHJldHVybiB0aGlzLl9jb252ZXJ0Q215a1RvUmdiKGRhdGEpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZGF0YTsKICB9Cn0KZXhwb3J0cy5KcGVnSW1hZ2UgPSBKcGVnSW1hZ2U7CgovKioqLyB9KSwKLyogMTYzICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5jb252ZXJ0QmxhY2tBbmRXaGl0ZVRvUkdCQSA9IGNvbnZlcnRCbGFja0FuZFdoaXRlVG9SR0JBOwpleHBvcnRzLmNvbnZlcnRUb1JHQkEgPSBjb252ZXJ0VG9SR0JBOwpleHBvcnRzLmdyYXlUb1JHQkEgPSBncmF5VG9SR0JBOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpmdW5jdGlvbiBjb252ZXJ0VG9SR0JBKHBhcmFtcykgewogIHN3aXRjaCAocGFyYW1zLmtpbmQpIHsKICAgIGNhc2UgX3V0aWwuSW1hZ2VLaW5kLkdSQVlTQ0FMRV8xQlBQOgogICAgICByZXR1cm4gY29udmVydEJsYWNrQW5kV2hpdGVUb1JHQkEocGFyYW1zKTsKICAgIGNhc2UgX3V0aWwuSW1hZ2VLaW5kLlJHQl8yNEJQUDoKICAgICAgcmV0dXJuIGNvbnZlcnRSR0JUb1JHQkEocGFyYW1zKTsKICB9CiAgcmV0dXJuIG51bGw7Cn0KZnVuY3Rpb24gY29udmVydEJsYWNrQW5kV2hpdGVUb1JHQkEoX3JlZikgewogIGxldCB7CiAgICBzcmMsCiAgICBzcmNQb3MgPSAwLAogICAgZGVzdCwKICAgIHdpZHRoLAogICAgaGVpZ2h0LAogICAgbm9uQmxhY2tDb2xvciA9IDB4ZmZmZmZmZmYsCiAgICBpbnZlcnNlRGVjb2RlID0gZmFsc2UKICB9ID0gX3JlZjsKICBjb25zdCBibGFjayA9IF91dGlsLkZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuID8gMHhmZjAwMDAwMCA6IDB4MDAwMDAwZmY7CiAgY29uc3QgW3plcm9NYXBwaW5nLCBvbmVNYXBwaW5nXSA9IGludmVyc2VEZWNvZGUgPyBbbm9uQmxhY2tDb2xvciwgYmxhY2tdIDogW2JsYWNrLCBub25CbGFja0NvbG9yXTsKICBjb25zdCB3aWR0aEluU291cmNlID0gd2lkdGggPj4gMzsKICBjb25zdCB3aWR0aFJlbWFpbmRlciA9IHdpZHRoICYgNzsKICBjb25zdCBzcmNMZW5ndGggPSBzcmMubGVuZ3RoOwogIGRlc3QgPSBuZXcgVWludDMyQXJyYXkoZGVzdC5idWZmZXIpOwogIGxldCBkZXN0UG9zID0gMDsKICBmb3IgKGxldCBpID0gMDsgaSA8IGhlaWdodDsgaSsrKSB7CiAgICBmb3IgKGNvbnN0IG1heCA9IHNyY1BvcyArIHdpZHRoSW5Tb3VyY2U7IHNyY1BvcyA8IG1heDsgc3JjUG9zKyspIHsKICAgICAgY29uc3QgZWxlbSA9IHNyY1BvcyA8IHNyY0xlbmd0aCA/IHNyY1tzcmNQb3NdIDogMjU1OwogICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMDAwMDAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMTAwMDAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMTAwMDAwID8gb25lTWFwcGluZyA6IHplcm9NYXBwaW5nOwogICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMDAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMTAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMTAwID8gb25lTWFwcGluZyA6IHplcm9NYXBwaW5nOwogICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMSA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgIH0KICAgIGlmICh3aWR0aFJlbWFpbmRlciA9PT0gMCkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGNvbnN0IGVsZW0gPSBzcmNQb3MgPCBzcmNMZW5ndGggPyBzcmNbc3JjUG9zKytdIDogMjU1OwogICAgZm9yIChsZXQgaiA9IDA7IGogPCB3aWR0aFJlbWFpbmRlcjsgaisrKSB7CiAgICAgIGRlc3RbZGVzdFBvcysrXSA9IGVsZW0gJiAxIDw8IDcgLSBqID8gb25lTWFwcGluZyA6IHplcm9NYXBwaW5nOwogICAgfQogIH0KICByZXR1cm4gewogICAgc3JjUG9zLAogICAgZGVzdFBvcwogIH07Cn0KZnVuY3Rpb24gY29udmVydFJHQlRvUkdCQShfcmVmMikgewogIGxldCB7CiAgICBzcmMsCiAgICBzcmNQb3MgPSAwLAogICAgZGVzdCwKICAgIGRlc3RQb3MgPSAwLAogICAgd2lkdGgsCiAgICBoZWlnaHQKICB9ID0gX3JlZjI7CiAgbGV0IGkgPSAwOwogIGNvbnN0IGxlbjMyID0gc3JjLmxlbmd0aCA+PiAyOwogIGNvbnN0IHNyYzMyID0gbmV3IFVpbnQzMkFycmF5KHNyYy5idWZmZXIsIHNyY1BvcywgbGVuMzIpOwogIGlmIChfdXRpbC5GZWF0dXJlVGVzdC5pc0xpdHRsZUVuZGlhbikgewogICAgZm9yICg7IGkgPCBsZW4zMiAtIDI7IGkgKz0gMywgZGVzdFBvcyArPSA0KSB7CiAgICAgIGNvbnN0IHMxID0gc3JjMzJbaV07CiAgICAgIGNvbnN0IHMyID0gc3JjMzJbaSArIDFdOwogICAgICBjb25zdCBzMyA9IHNyYzMyW2kgKyAyXTsKICAgICAgZGVzdFtkZXN0UG9zXSA9IHMxIHwgMHhmZjAwMDAwMDsKICAgICAgZGVzdFtkZXN0UG9zICsgMV0gPSBzMSA+Pj4gMjQgfCBzMiA8PCA4IHwgMHhmZjAwMDAwMDsKICAgICAgZGVzdFtkZXN0UG9zICsgMl0gPSBzMiA+Pj4gMTYgfCBzMyA8PCAxNiB8IDB4ZmYwMDAwMDA7CiAgICAgIGRlc3RbZGVzdFBvcyArIDNdID0gczMgPj4+IDggfCAweGZmMDAwMDAwOwogICAgfQogICAgZm9yIChsZXQgaiA9IGkgKiA0LCBqaiA9IHNyYy5sZW5ndGg7IGogPCBqajsgaiArPSAzKSB7CiAgICAgIGRlc3RbZGVzdFBvcysrXSA9IHNyY1tqXSB8IHNyY1tqICsgMV0gPDwgOCB8IHNyY1tqICsgMl0gPDwgMTYgfCAweGZmMDAwMDAwOwogICAgfQogIH0gZWxzZSB7CiAgICBmb3IgKDsgaSA8IGxlbjMyIC0gMjsgaSArPSAzLCBkZXN0UG9zICs9IDQpIHsKICAgICAgY29uc3QgczEgPSBzcmMzMltpXTsKICAgICAgY29uc3QgczIgPSBzcmMzMltpICsgMV07CiAgICAgIGNvbnN0IHMzID0gc3JjMzJbaSArIDJdOwogICAgICBkZXN0W2Rlc3RQb3NdID0gczEgfCAweGZmOwogICAgICBkZXN0W2Rlc3RQb3MgKyAxXSA9IHMxIDw8IDI0IHwgczIgPj4+IDggfCAweGZmOwogICAgICBkZXN0W2Rlc3RQb3MgKyAyXSA9IHMyIDw8IDE2IHwgczMgPj4+IDE2IHwgMHhmZjsKICAgICAgZGVzdFtkZXN0UG9zICsgM10gPSBzMyA8PCA4IHwgMHhmZjsKICAgIH0KICAgIGZvciAobGV0IGogPSBpICogNCwgamogPSBzcmMubGVuZ3RoOyBqIDwgamo7IGogKz0gMykgewogICAgICBkZXN0W2Rlc3RQb3MrK10gPSBzcmNbal0gPDwgMjQgfCBzcmNbaiArIDFdIDw8IDE2IHwgc3JjW2ogKyAyXSA8PCA4IHwgMHhmZjsKICAgIH0KICB9CiAgcmV0dXJuIHsKICAgIHNyY1BvcywKICAgIGRlc3RQb3MKICB9Owp9CmZ1bmN0aW9uIGdyYXlUb1JHQkEoc3JjLCBkZXN0KSB7CiAgaWYgKF91dGlsLkZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuKSB7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBzcmMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBkZXN0W2ldID0gc3JjW2ldICogMHgxMDEwMSB8IDB4ZmYwMDAwMDA7CiAgICB9CiAgfSBlbHNlIHsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHNyYy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGRlc3RbaV0gPSBzcmNbaV0gKiAweDEwMTAxMDAgfCAweDAwMDAwMGZmOwogICAgfQogIH0KfQoKLyoqKi8gfSksCi8qIDE2NCAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuSnB4U3RyZWFtID0gdm9pZCAwOwp2YXIgX2RlY29kZV9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1Myk7CnZhciBfanB4ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNjUpOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpjbGFzcyBKcHhTdHJlYW0gZXh0ZW5kcyBfZGVjb2RlX3N0cmVhbS5EZWNvZGVTdHJlYW0gewogIGNvbnN0cnVjdG9yKHN0cmVhbSwgbWF5YmVMZW5ndGgsIHBhcmFtcykgewogICAgc3VwZXIobWF5YmVMZW5ndGgpOwogICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07CiAgICB0aGlzLmRpY3QgPSBzdHJlYW0uZGljdDsKICAgIHRoaXMubWF5YmVMZW5ndGggPSBtYXliZUxlbmd0aDsKICAgIHRoaXMucGFyYW1zID0gcGFyYW1zOwogIH0KICBnZXQgYnl0ZXMoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImJ5dGVzIiwgdGhpcy5zdHJlYW0uZ2V0Qnl0ZXModGhpcy5tYXliZUxlbmd0aCkpOwogIH0KICBlbnN1cmVCdWZmZXIocmVxdWVzdGVkKSB7fQogIHJlYWRCbG9jaygpIHsKICAgIGlmICh0aGlzLmVvZikgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBqcHhJbWFnZSA9IG5ldyBfanB4LkpweEltYWdlKCk7CiAgICBqcHhJbWFnZS5wYXJzZSh0aGlzLmJ5dGVzKTsKICAgIGNvbnN0IHdpZHRoID0ganB4SW1hZ2Uud2lkdGg7CiAgICBjb25zdCBoZWlnaHQgPSBqcHhJbWFnZS5oZWlnaHQ7CiAgICBjb25zdCBjb21wb25lbnRzQ291bnQgPSBqcHhJbWFnZS5jb21wb25lbnRzQ291bnQ7CiAgICBjb25zdCB0aWxlQ291bnQgPSBqcHhJbWFnZS50aWxlcy5sZW5ndGg7CiAgICBpZiAodGlsZUNvdW50ID09PSAxKSB7CiAgICAgIHRoaXMuYnVmZmVyID0ganB4SW1hZ2UudGlsZXNbMF0uaXRlbXM7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHdpZHRoICogaGVpZ2h0ICogY29tcG9uZW50c0NvdW50KTsKICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCB0aWxlQ291bnQ7IGsrKykgewogICAgICAgIGNvbnN0IHRpbGVDb21wb25lbnRzID0ganB4SW1hZ2UudGlsZXNba107CiAgICAgICAgY29uc3QgdGlsZVdpZHRoID0gdGlsZUNvbXBvbmVudHMud2lkdGg7CiAgICAgICAgY29uc3QgdGlsZUhlaWdodCA9IHRpbGVDb21wb25lbnRzLmhlaWdodDsKICAgICAgICBjb25zdCB0aWxlTGVmdCA9IHRpbGVDb21wb25lbnRzLmxlZnQ7CiAgICAgICAgY29uc3QgdGlsZVRvcCA9IHRpbGVDb21wb25lbnRzLnRvcDsKICAgICAgICBjb25zdCBzcmMgPSB0aWxlQ29tcG9uZW50cy5pdGVtczsKICAgICAgICBsZXQgc3JjUG9zaXRpb24gPSAwOwogICAgICAgIGxldCBkYXRhUG9zaXRpb24gPSAod2lkdGggKiB0aWxlVG9wICsgdGlsZUxlZnQpICogY29tcG9uZW50c0NvdW50OwogICAgICAgIGNvbnN0IGltZ1Jvd1NpemUgPSB3aWR0aCAqIGNvbXBvbmVudHNDb3VudDsKICAgICAgICBjb25zdCB0aWxlUm93U2l6ZSA9IHRpbGVXaWR0aCAqIGNvbXBvbmVudHNDb3VudDsKICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHRpbGVIZWlnaHQ7IGorKykgewogICAgICAgICAgY29uc3Qgcm93Qnl0ZXMgPSBzcmMuc3ViYXJyYXkoc3JjUG9zaXRpb24sIHNyY1Bvc2l0aW9uICsgdGlsZVJvd1NpemUpOwogICAgICAgICAgZGF0YS5zZXQocm93Qnl0ZXMsIGRhdGFQb3NpdGlvbik7CiAgICAgICAgICBzcmNQb3NpdGlvbiArPSB0aWxlUm93U2l6ZTsKICAgICAgICAgIGRhdGFQb3NpdGlvbiArPSBpbWdSb3dTaXplOwogICAgICAgIH0KICAgICAgfQogICAgICB0aGlzLmJ1ZmZlciA9IGRhdGE7CiAgICB9CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IHRoaXMuYnVmZmVyLmxlbmd0aDsKICAgIHRoaXMuZW9mID0gdHJ1ZTsKICB9Cn0KZXhwb3J0cy5KcHhTdHJlYW0gPSBKcHhTdHJlYW07CgovKioqLyB9KSwKLyogMTY1ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5KcHhJbWFnZSA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX2FyaXRobWV0aWNfZGVjb2RlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTYwKTsKY2xhc3MgSnB4RXJyb3IgZXh0ZW5kcyBfdXRpbC5CYXNlRXhjZXB0aW9uIHsKICBjb25zdHJ1Y3Rvcihtc2cpIHsKICAgIHN1cGVyKGBKUFggZXJyb3I6ICR7bXNnfWAsICJKcHhFcnJvciIpOwogIH0KfQpjb25zdCBTdWJiYW5kc0dhaW5Mb2cyID0gewogIExMOiAwLAogIExIOiAxLAogIEhMOiAxLAogIEhIOiAyCn07CmNsYXNzIEpweEltYWdlIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMuZmFpbE9uQ29ycnVwdGVkSW1hZ2UgPSBmYWxzZTsKICB9CiAgcGFyc2UoZGF0YSkgewogICAgY29uc3QgaGVhZCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCAwKTsKICAgIGlmIChoZWFkID09PSAweGZmNGYpIHsKICAgICAgdGhpcy5wYXJzZUNvZGVzdHJlYW0oZGF0YSwgMCwgZGF0YS5sZW5ndGgpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBsZW5ndGggPSBkYXRhLmxlbmd0aDsKICAgIGxldCBwb3NpdGlvbiA9IDA7CiAgICB3aGlsZSAocG9zaXRpb24gPCBsZW5ndGgpIHsKICAgICAgbGV0IGhlYWRlclNpemUgPSA4OwogICAgICBsZXQgbGJveCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDMyKShkYXRhLCBwb3NpdGlvbik7CiAgICAgIGNvbnN0IHRib3ggPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQzMikoZGF0YSwgcG9zaXRpb24gKyA0KTsKICAgICAgcG9zaXRpb24gKz0gaGVhZGVyU2l6ZTsKICAgICAgaWYgKGxib3ggPT09IDEpIHsKICAgICAgICBsYm94ID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uKSAqIDQyOTQ5NjcyOTYgKyAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQzMikoZGF0YSwgcG9zaXRpb24gKyA0KTsKICAgICAgICBwb3NpdGlvbiArPSA4OwogICAgICAgIGhlYWRlclNpemUgKz0gODsKICAgICAgfQogICAgICBpZiAobGJveCA9PT0gMCkgewogICAgICAgIGxib3ggPSBsZW5ndGggLSBwb3NpdGlvbiArIGhlYWRlclNpemU7CiAgICAgIH0KICAgICAgaWYgKGxib3ggPCBoZWFkZXJTaXplKSB7CiAgICAgICAgdGhyb3cgbmV3IEpweEVycm9yKCJJbnZhbGlkIGJveCBmaWVsZCBzaXplIik7CiAgICAgIH0KICAgICAgY29uc3QgZGF0YUxlbmd0aCA9IGxib3ggLSBoZWFkZXJTaXplOwogICAgICBsZXQganVtcERhdGFMZW5ndGggPSB0cnVlOwogICAgICBzd2l0Y2ggKHRib3gpIHsKICAgICAgICBjYXNlIDB4NmE3MDMyNjg6CiAgICAgICAgICBqdW1wRGF0YUxlbmd0aCA9IGZhbHNlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDYzNmY2YzcyOgogICAgICAgICAgY29uc3QgbWV0aG9kID0gZGF0YVtwb3NpdGlvbl07CiAgICAgICAgICBpZiAobWV0aG9kID09PSAxKSB7CiAgICAgICAgICAgIGNvbnN0IGNvbG9yc3BhY2UgPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQzMikoZGF0YSwgcG9zaXRpb24gKyAzKTsKICAgICAgICAgICAgc3dpdGNoIChjb2xvcnNwYWNlKSB7CiAgICAgICAgICAgICAgY2FzZSAxNjoKICAgICAgICAgICAgICBjYXNlIDE3OgogICAgICAgICAgICAgIGNhc2UgMTg6CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJVbmtub3duIGNvbG9yc3BhY2UgIiArIGNvbG9yc3BhY2UpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSBpZiAobWV0aG9kID09PSAyKSB7CiAgICAgICAgICAgICgwLCBfdXRpbC5pbmZvKSgiSUNDIHByb2ZpbGUgbm90IHN1cHBvcnRlZCIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDZhNzAzMjYzOgogICAgICAgICAgdGhpcy5wYXJzZUNvZGVzdHJlYW0oZGF0YSwgcG9zaXRpb24sIHBvc2l0aW9uICsgZGF0YUxlbmd0aCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4NmE1MDIwMjA6CiAgICAgICAgICBpZiAoKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uKSAhPT0gMHgwZDBhODcwYSkgewogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoIkludmFsaWQgSlAyIHNpZ25hdHVyZSIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDZhNTAxYTFhOgogICAgICAgIGNhc2UgMHg2Njc0Nzk3MDoKICAgICAgICBjYXNlIDB4NzI3MjY1NzE6CiAgICAgICAgY2FzZSAweDcyNjU3MzIwOgogICAgICAgIGNhc2UgMHg2OTY4NjQ3MjoKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBjb25zdCBoZWFkZXJUeXBlID0gU3RyaW5nLmZyb21DaGFyQ29kZSh0Ym94ID4+IDI0ICYgMHhmZiwgdGJveCA+PiAxNiAmIDB4ZmYsIHRib3ggPj4gOCAmIDB4ZmYsIHRib3ggJiAweGZmKTsKICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgVW5zdXBwb3J0ZWQgaGVhZGVyIHR5cGUgJHt0Ym94fSAoJHtoZWFkZXJUeXBlfSkuYCk7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAoanVtcERhdGFMZW5ndGgpIHsKICAgICAgICBwb3NpdGlvbiArPSBkYXRhTGVuZ3RoOwogICAgICB9CiAgICB9CiAgfQogIHBhcnNlSW1hZ2VQcm9wZXJ0aWVzKHN0cmVhbSkgewogICAgbGV0IG5ld0J5dGUgPSBzdHJlYW0uZ2V0Qnl0ZSgpOwogICAgd2hpbGUgKG5ld0J5dGUgPj0gMCkgewogICAgICBjb25zdCBvbGRCeXRlID0gbmV3Qnl0ZTsKICAgICAgbmV3Qnl0ZSA9IHN0cmVhbS5nZXRCeXRlKCk7CiAgICAgIGNvbnN0IGNvZGUgPSBvbGRCeXRlIDw8IDggfCBuZXdCeXRlOwogICAgICBpZiAoY29kZSA9PT0gMHhmZjUxKSB7CiAgICAgICAgc3RyZWFtLnNraXAoNCk7CiAgICAgICAgY29uc3QgWHNpeiA9IHN0cmVhbS5nZXRJbnQzMigpID4+PiAwOwogICAgICAgIGNvbnN0IFlzaXogPSBzdHJlYW0uZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICBjb25zdCBYT3NpeiA9IHN0cmVhbS5nZXRJbnQzMigpID4+PiAwOwogICAgICAgIGNvbnN0IFlPc2l6ID0gc3RyZWFtLmdldEludDMyKCkgPj4+IDA7CiAgICAgICAgc3RyZWFtLnNraXAoMTYpOwogICAgICAgIGNvbnN0IENzaXogPSBzdHJlYW0uZ2V0VWludDE2KCk7CiAgICAgICAgdGhpcy53aWR0aCA9IFhzaXogLSBYT3NpejsKICAgICAgICB0aGlzLmhlaWdodCA9IFlzaXogLSBZT3NpejsKICAgICAgICB0aGlzLmNvbXBvbmVudHNDb3VudCA9IENzaXo7CiAgICAgICAgdGhpcy5iaXRzUGVyQ29tcG9uZW50ID0gODsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgIH0KICAgIHRocm93IG5ldyBKcHhFcnJvcigiTm8gc2l6ZSBtYXJrZXIgZm91bmQgaW4gSlBYIHN0cmVhbSIpOwogIH0KICBwYXJzZUNvZGVzdHJlYW0oZGF0YSwgc3RhcnQsIGVuZCkgewogICAgY29uc3QgY29udGV4dCA9IHt9OwogICAgbGV0IGRvTm90UmVjb3ZlciA9IGZhbHNlOwogICAgdHJ5IHsKICAgICAgbGV0IHBvc2l0aW9uID0gc3RhcnQ7CiAgICAgIHdoaWxlIChwb3NpdGlvbiArIDEgPCBlbmQpIHsKICAgICAgICBjb25zdCBjb2RlID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MTYpKGRhdGEsIHBvc2l0aW9uKTsKICAgICAgICBwb3NpdGlvbiArPSAyOwogICAgICAgIGxldCBsZW5ndGggPSAwLAogICAgICAgICAgaiwKICAgICAgICAgIHNxY2QsCiAgICAgICAgICBzcHFjZHMsCiAgICAgICAgICBzcHFjZFNpemUsCiAgICAgICAgICBzY2FsYXJFeHBvdW5kZWQsCiAgICAgICAgICB0aWxlOwogICAgICAgIHN3aXRjaCAoY29kZSkgewogICAgICAgICAgY2FzZSAweGZmNGY6CiAgICAgICAgICAgIGNvbnRleHQubWFpbkhlYWRlciA9IHRydWU7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAweGZmZDk6CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAweGZmNTE6CiAgICAgICAgICAgIGxlbmd0aCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBwb3NpdGlvbik7CiAgICAgICAgICAgIGNvbnN0IHNpeiA9IHt9OwogICAgICAgICAgICBzaXouWHNpeiA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDMyKShkYXRhLCBwb3NpdGlvbiArIDQpOwogICAgICAgICAgICBzaXouWXNpeiA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDMyKShkYXRhLCBwb3NpdGlvbiArIDgpOwogICAgICAgICAgICBzaXouWE9zaXogPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQzMikoZGF0YSwgcG9zaXRpb24gKyAxMik7CiAgICAgICAgICAgIHNpei5ZT3NpeiA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDMyKShkYXRhLCBwb3NpdGlvbiArIDE2KTsKICAgICAgICAgICAgc2l6LlhUc2l6ID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MzIpKGRhdGEsIHBvc2l0aW9uICsgMjApOwogICAgICAgICAgICBzaXouWVRzaXogPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQzMikoZGF0YSwgcG9zaXRpb24gKyAyNCk7CiAgICAgICAgICAgIHNpei5YVE9zaXogPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQzMikoZGF0YSwgcG9zaXRpb24gKyAyOCk7CiAgICAgICAgICAgIHNpei5ZVE9zaXogPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQzMikoZGF0YSwgcG9zaXRpb24gKyAzMik7CiAgICAgICAgICAgIGNvbnN0IGNvbXBvbmVudHNDb3VudCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBwb3NpdGlvbiArIDM2KTsKICAgICAgICAgICAgc2l6LkNzaXogPSBjb21wb25lbnRzQ291bnQ7CiAgICAgICAgICAgIGNvbnN0IGNvbXBvbmVudHMgPSBbXTsKICAgICAgICAgICAgaiA9IHBvc2l0aW9uICsgMzg7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29tcG9uZW50c0NvdW50OyBpKyspIHsKICAgICAgICAgICAgICBjb25zdCBjb21wb25lbnQgPSB7CiAgICAgICAgICAgICAgICBwcmVjaXNpb246IChkYXRhW2pdICYgMHg3ZikgKyAxLAogICAgICAgICAgICAgICAgaXNTaWduZWQ6ICEhKGRhdGFbal0gJiAweDgwKSwKICAgICAgICAgICAgICAgIFhSc2l6OiBkYXRhW2ogKyAxXSwKICAgICAgICAgICAgICAgIFlSc2l6OiBkYXRhW2ogKyAyXQogICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgaiArPSAzOwogICAgICAgICAgICAgIGNhbGN1bGF0ZUNvbXBvbmVudERpbWVuc2lvbnMoY29tcG9uZW50LCBzaXopOwogICAgICAgICAgICAgIGNvbXBvbmVudHMucHVzaChjb21wb25lbnQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnRleHQuU0laID0gc2l6OwogICAgICAgICAgICBjb250ZXh0LmNvbXBvbmVudHMgPSBjb21wb25lbnRzOwogICAgICAgICAgICBjYWxjdWxhdGVUaWxlR3JpZHMoY29udGV4dCwgY29tcG9uZW50cyk7CiAgICAgICAgICAgIGNvbnRleHQuUUNDID0gW107CiAgICAgICAgICAgIGNvbnRleHQuQ09DID0gW107CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAweGZmNWM6CiAgICAgICAgICAgIGxlbmd0aCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBwb3NpdGlvbik7CiAgICAgICAgICAgIGNvbnN0IHFjZCA9IHt9OwogICAgICAgICAgICBqID0gcG9zaXRpb24gKyAyOwogICAgICAgICAgICBzcWNkID0gZGF0YVtqKytdOwogICAgICAgICAgICBzd2l0Y2ggKHNxY2QgJiAweDFmKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgc3BxY2RTaXplID0gODsKICAgICAgICAgICAgICAgIHNjYWxhckV4cG91bmRlZCA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgICBzcHFjZFNpemUgPSAxNjsKICAgICAgICAgICAgICAgIHNjYWxhckV4cG91bmRlZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgc3BxY2RTaXplID0gMTY7CiAgICAgICAgICAgICAgICBzY2FsYXJFeHBvdW5kZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiSW52YWxpZCBTUWNkIHZhbHVlICIgKyBzcWNkKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBxY2Qubm9RdWFudGl6YXRpb24gPSBzcHFjZFNpemUgPT09IDg7CiAgICAgICAgICAgIHFjZC5zY2FsYXJFeHBvdW5kZWQgPSBzY2FsYXJFeHBvdW5kZWQ7CiAgICAgICAgICAgIHFjZC5ndWFyZEJpdHMgPSBzcWNkID4+IDU7CiAgICAgICAgICAgIHNwcWNkcyA9IFtdOwogICAgICAgICAgICB3aGlsZSAoaiA8IGxlbmd0aCArIHBvc2l0aW9uKSB7CiAgICAgICAgICAgICAgY29uc3Qgc3BxY2QgPSB7fTsKICAgICAgICAgICAgICBpZiAoc3BxY2RTaXplID09PSA4KSB7CiAgICAgICAgICAgICAgICBzcHFjZC5lcHNpbG9uID0gZGF0YVtqKytdID4+IDM7CiAgICAgICAgICAgICAgICBzcHFjZC5tdSA9IDA7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHNwcWNkLmVwc2lsb24gPSBkYXRhW2pdID4+IDM7CiAgICAgICAgICAgICAgICBzcHFjZC5tdSA9IChkYXRhW2pdICYgMHg3KSA8PCA4IHwgZGF0YVtqICsgMV07CiAgICAgICAgICAgICAgICBqICs9IDI7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHNwcWNkcy5wdXNoKHNwcWNkKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBxY2QuU1BxY2RzID0gc3BxY2RzOwogICAgICAgICAgICBpZiAoY29udGV4dC5tYWluSGVhZGVyKSB7CiAgICAgICAgICAgICAgY29udGV4dC5RQ0QgPSBxY2Q7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgY29udGV4dC5jdXJyZW50VGlsZS5RQ0QgPSBxY2Q7CiAgICAgICAgICAgICAgY29udGV4dC5jdXJyZW50VGlsZS5RQ0MgPSBbXTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMHhmZjVkOgogICAgICAgICAgICBsZW5ndGggPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgcG9zaXRpb24pOwogICAgICAgICAgICBjb25zdCBxY2MgPSB7fTsKICAgICAgICAgICAgaiA9IHBvc2l0aW9uICsgMjsKICAgICAgICAgICAgbGV0IGNxY2M7CiAgICAgICAgICAgIGlmIChjb250ZXh0LlNJWi5Dc2l6IDwgMjU3KSB7CiAgICAgICAgICAgICAgY3FjYyA9IGRhdGFbaisrXTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBjcWNjID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MTYpKGRhdGEsIGopOwogICAgICAgICAgICAgIGogKz0gMjsKICAgICAgICAgICAgfQogICAgICAgICAgICBzcWNkID0gZGF0YVtqKytdOwogICAgICAgICAgICBzd2l0Y2ggKHNxY2QgJiAweDFmKSB7CiAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgc3BxY2RTaXplID0gODsKICAgICAgICAgICAgICAgIHNjYWxhckV4cG91bmRlZCA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgICBzcHFjZFNpemUgPSAxNjsKICAgICAgICAgICAgICAgIHNjYWxhckV4cG91bmRlZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgICAgc3BxY2RTaXplID0gMTY7CiAgICAgICAgICAgICAgICBzY2FsYXJFeHBvdW5kZWQgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiSW52YWxpZCBTUWNkIHZhbHVlICIgKyBzcWNkKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBxY2Mubm9RdWFudGl6YXRpb24gPSBzcHFjZFNpemUgPT09IDg7CiAgICAgICAgICAgIHFjYy5zY2FsYXJFeHBvdW5kZWQgPSBzY2FsYXJFeHBvdW5kZWQ7CiAgICAgICAgICAgIHFjYy5ndWFyZEJpdHMgPSBzcWNkID4+IDU7CiAgICAgICAgICAgIHNwcWNkcyA9IFtdOwogICAgICAgICAgICB3aGlsZSAoaiA8IGxlbmd0aCArIHBvc2l0aW9uKSB7CiAgICAgICAgICAgICAgY29uc3Qgc3BxY2QgPSB7fTsKICAgICAgICAgICAgICBpZiAoc3BxY2RTaXplID09PSA4KSB7CiAgICAgICAgICAgICAgICBzcHFjZC5lcHNpbG9uID0gZGF0YVtqKytdID4+IDM7CiAgICAgICAgICAgICAgICBzcHFjZC5tdSA9IDA7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHNwcWNkLmVwc2lsb24gPSBkYXRhW2pdID4+IDM7CiAgICAgICAgICAgICAgICBzcHFjZC5tdSA9IChkYXRhW2pdICYgMHg3KSA8PCA4IHwgZGF0YVtqICsgMV07CiAgICAgICAgICAgICAgICBqICs9IDI7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHNwcWNkcy5wdXNoKHNwcWNkKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBxY2MuU1BxY2RzID0gc3BxY2RzOwogICAgICAgICAgICBpZiAoY29udGV4dC5tYWluSGVhZGVyKSB7CiAgICAgICAgICAgICAgY29udGV4dC5RQ0NbY3FjY10gPSBxY2M7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgY29udGV4dC5jdXJyZW50VGlsZS5RQ0NbY3FjY10gPSBxY2M7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDB4ZmY1MjoKICAgICAgICAgICAgbGVuZ3RoID0gKDAsIF9jb3JlX3V0aWxzLnJlYWRVaW50MTYpKGRhdGEsIHBvc2l0aW9uKTsKICAgICAgICAgICAgY29uc3QgY29kID0ge307CiAgICAgICAgICAgIGogPSBwb3NpdGlvbiArIDI7CiAgICAgICAgICAgIGNvbnN0IHNjb2QgPSBkYXRhW2orK107CiAgICAgICAgICAgIGNvZC5lbnRyb3B5Q29kZXJXaXRoQ3VzdG9tUHJlY2luY3RzID0gISEoc2NvZCAmIDEpOwogICAgICAgICAgICBjb2Quc29wTWFya2VyVXNlZCA9ICEhKHNjb2QgJiAyKTsKICAgICAgICAgICAgY29kLmVwaE1hcmtlclVzZWQgPSAhIShzY29kICYgNCk7CiAgICAgICAgICAgIGNvZC5wcm9ncmVzc2lvbk9yZGVyID0gZGF0YVtqKytdOwogICAgICAgICAgICBjb2QubGF5ZXJzQ291bnQgPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgaik7CiAgICAgICAgICAgIGogKz0gMjsKICAgICAgICAgICAgY29kLm11bHRpcGxlQ29tcG9uZW50VHJhbnNmb3JtID0gZGF0YVtqKytdOwogICAgICAgICAgICBjb2QuZGVjb21wb3NpdGlvbkxldmVsc0NvdW50ID0gZGF0YVtqKytdOwogICAgICAgICAgICBjb2QueGNiID0gKGRhdGFbaisrXSAmIDB4ZikgKyAyOwogICAgICAgICAgICBjb2QueWNiID0gKGRhdGFbaisrXSAmIDB4ZikgKyAyOwogICAgICAgICAgICBjb25zdCBibG9ja1N0eWxlID0gZGF0YVtqKytdOwogICAgICAgICAgICBjb2Quc2VsZWN0aXZlQXJpdGhtZXRpY0NvZGluZ0J5cGFzcyA9ICEhKGJsb2NrU3R5bGUgJiAxKTsKICAgICAgICAgICAgY29kLnJlc2V0Q29udGV4dFByb2JhYmlsaXRpZXMgPSAhIShibG9ja1N0eWxlICYgMik7CiAgICAgICAgICAgIGNvZC50ZXJtaW5hdGlvbk9uRWFjaENvZGluZ1Bhc3MgPSAhIShibG9ja1N0eWxlICYgNCk7CiAgICAgICAgICAgIGNvZC52ZXJ0aWNhbGx5U3RyaXBlID0gISEoYmxvY2tTdHlsZSAmIDgpOwogICAgICAgICAgICBjb2QucHJlZGljdGFibGVUZXJtaW5hdGlvbiA9ICEhKGJsb2NrU3R5bGUgJiAxNik7CiAgICAgICAgICAgIGNvZC5zZWdtZW50YXRpb25TeW1ib2xVc2VkID0gISEoYmxvY2tTdHlsZSAmIDMyKTsKICAgICAgICAgICAgY29kLnJldmVyc2libGVUcmFuc2Zvcm1hdGlvbiA9IGRhdGFbaisrXTsKICAgICAgICAgICAgaWYgKGNvZC5lbnRyb3B5Q29kZXJXaXRoQ3VzdG9tUHJlY2luY3RzKSB7CiAgICAgICAgICAgICAgY29uc3QgcHJlY2luY3RzU2l6ZXMgPSBbXTsKICAgICAgICAgICAgICB3aGlsZSAoaiA8IGxlbmd0aCArIHBvc2l0aW9uKSB7CiAgICAgICAgICAgICAgICBjb25zdCBwcmVjaW5jdHNTaXplID0gZGF0YVtqKytdOwogICAgICAgICAgICAgICAgcHJlY2luY3RzU2l6ZXMucHVzaCh7CiAgICAgICAgICAgICAgICAgIFBQeDogcHJlY2luY3RzU2l6ZSAmIDB4ZiwKICAgICAgICAgICAgICAgICAgUFB5OiBwcmVjaW5jdHNTaXplID4+IDQKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb2QucHJlY2luY3RzU2l6ZXMgPSBwcmVjaW5jdHNTaXplczsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCB1bnN1cHBvcnRlZCA9IFtdOwogICAgICAgICAgICBpZiAoY29kLnNlbGVjdGl2ZUFyaXRobWV0aWNDb2RpbmdCeXBhc3MpIHsKICAgICAgICAgICAgICB1bnN1cHBvcnRlZC5wdXNoKCJzZWxlY3RpdmVBcml0aG1ldGljQ29kaW5nQnlwYXNzIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGNvZC50ZXJtaW5hdGlvbk9uRWFjaENvZGluZ1Bhc3MpIHsKICAgICAgICAgICAgICB1bnN1cHBvcnRlZC5wdXNoKCJ0ZXJtaW5hdGlvbk9uRWFjaENvZGluZ1Bhc3MiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoY29kLnZlcnRpY2FsbHlTdHJpcGUpIHsKICAgICAgICAgICAgICB1bnN1cHBvcnRlZC5wdXNoKCJ2ZXJ0aWNhbGx5U3RyaXBlIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGNvZC5wcmVkaWN0YWJsZVRlcm1pbmF0aW9uKSB7CiAgICAgICAgICAgICAgdW5zdXBwb3J0ZWQucHVzaCgicHJlZGljdGFibGVUZXJtaW5hdGlvbiIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh1bnN1cHBvcnRlZC5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgICAgZG9Ob3RSZWNvdmVyID0gdHJ1ZTsKICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYEpQWDogVW5zdXBwb3J0ZWQgQ09EIG9wdGlvbnMgKCR7dW5zdXBwb3J0ZWQuam9pbigiLCAiKX0pLmApOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChjb250ZXh0Lm1haW5IZWFkZXIpIHsKICAgICAgICAgICAgICBjb250ZXh0LkNPRCA9IGNvZDsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBjb250ZXh0LmN1cnJlbnRUaWxlLkNPRCA9IGNvZDsKICAgICAgICAgICAgICBjb250ZXh0LmN1cnJlbnRUaWxlLkNPQyA9IFtdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAweGZmOTA6CiAgICAgICAgICAgIGxlbmd0aCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBwb3NpdGlvbik7CiAgICAgICAgICAgIHRpbGUgPSB7fTsKICAgICAgICAgICAgdGlsZS5pbmRleCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDE2KShkYXRhLCBwb3NpdGlvbiArIDIpOwogICAgICAgICAgICB0aWxlLmxlbmd0aCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDMyKShkYXRhLCBwb3NpdGlvbiArIDQpOwogICAgICAgICAgICB0aWxlLmRhdGFFbmQgPSB0aWxlLmxlbmd0aCArIHBvc2l0aW9uIC0gMjsKICAgICAgICAgICAgdGlsZS5wYXJ0SW5kZXggPSBkYXRhW3Bvc2l0aW9uICsgOF07CiAgICAgICAgICAgIHRpbGUucGFydHNDb3VudCA9IGRhdGFbcG9zaXRpb24gKyA5XTsKICAgICAgICAgICAgY29udGV4dC5tYWluSGVhZGVyID0gZmFsc2U7CiAgICAgICAgICAgIGlmICh0aWxlLnBhcnRJbmRleCA9PT0gMCkgewogICAgICAgICAgICAgIHRpbGUuQ09EID0gY29udGV4dC5DT0Q7CiAgICAgICAgICAgICAgdGlsZS5DT0MgPSBjb250ZXh0LkNPQy5zbGljZSgwKTsKICAgICAgICAgICAgICB0aWxlLlFDRCA9IGNvbnRleHQuUUNEOwogICAgICAgICAgICAgIHRpbGUuUUNDID0gY29udGV4dC5RQ0Muc2xpY2UoMCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29udGV4dC5jdXJyZW50VGlsZSA9IHRpbGU7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAweGZmOTM6CiAgICAgICAgICAgIHRpbGUgPSBjb250ZXh0LmN1cnJlbnRUaWxlOwogICAgICAgICAgICBpZiAodGlsZS5wYXJ0SW5kZXggPT09IDApIHsKICAgICAgICAgICAgICBpbml0aWFsaXplVGlsZShjb250ZXh0LCB0aWxlLmluZGV4KTsKICAgICAgICAgICAgICBidWlsZFBhY2tldHMoY29udGV4dCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGVuZ3RoID0gdGlsZS5kYXRhRW5kIC0gcG9zaXRpb247CiAgICAgICAgICAgIHBhcnNlVGlsZVBhY2tldHMoY29udGV4dCwgZGF0YSwgcG9zaXRpb24sIGxlbmd0aCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAweGZmNTM6CiAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiSlBYOiBDb2Rlc3RyZWFtIGNvZGUgMHhGRjUzIChDT0MpIGlzIG5vdCBpbXBsZW1lbnRlZC4iKTsKICAgICAgICAgIGNhc2UgMHhmZjU1OgogICAgICAgICAgY2FzZSAweGZmNTc6CiAgICAgICAgICBjYXNlIDB4ZmY1ODoKICAgICAgICAgIGNhc2UgMHhmZjY0OgogICAgICAgICAgICBsZW5ndGggPSAoMCwgX2NvcmVfdXRpbHMucmVhZFVpbnQxNikoZGF0YSwgcG9zaXRpb24pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiVW5rbm93biBjb2Rlc3RyZWFtIGNvZGU6ICIgKyBjb2RlLnRvU3RyaW5nKDE2KSk7CiAgICAgICAgfQogICAgICAgIHBvc2l0aW9uICs9IGxlbmd0aDsKICAgICAgfQogICAgfSBjYXRjaCAoZSkgewogICAgICBpZiAoZG9Ob3RSZWNvdmVyIHx8IHRoaXMuZmFpbE9uQ29ycnVwdGVkSW1hZ2UpIHsKICAgICAgICB0aHJvdyBuZXcgSnB4RXJyb3IoZS5tZXNzYWdlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYEpQWDogVHJ5aW5nIHRvIHJlY292ZXIgZnJvbTogIiR7ZS5tZXNzYWdlfSIuYCk7CiAgICAgIH0KICAgIH0KICAgIHRoaXMudGlsZXMgPSB0cmFuc2Zvcm1Db21wb25lbnRzKGNvbnRleHQpOwogICAgdGhpcy53aWR0aCA9IGNvbnRleHQuU0laLlhzaXogLSBjb250ZXh0LlNJWi5YT3NpejsKICAgIHRoaXMuaGVpZ2h0ID0gY29udGV4dC5TSVouWXNpeiAtIGNvbnRleHQuU0laLllPc2l6OwogICAgdGhpcy5jb21wb25lbnRzQ291bnQgPSBjb250ZXh0LlNJWi5Dc2l6OwogIH0KfQpleHBvcnRzLkpweEltYWdlID0gSnB4SW1hZ2U7CmZ1bmN0aW9uIGNhbGN1bGF0ZUNvbXBvbmVudERpbWVuc2lvbnMoY29tcG9uZW50LCBzaXopIHsKICBjb21wb25lbnQueDAgPSBNYXRoLmNlaWwoc2l6LlhPc2l6IC8gY29tcG9uZW50LlhSc2l6KTsKICBjb21wb25lbnQueDEgPSBNYXRoLmNlaWwoc2l6LlhzaXogLyBjb21wb25lbnQuWFJzaXopOwogIGNvbXBvbmVudC55MCA9IE1hdGguY2VpbChzaXouWU9zaXogLyBjb21wb25lbnQuWVJzaXopOwogIGNvbXBvbmVudC55MSA9IE1hdGguY2VpbChzaXouWXNpeiAvIGNvbXBvbmVudC5ZUnNpeik7CiAgY29tcG9uZW50LndpZHRoID0gY29tcG9uZW50LngxIC0gY29tcG9uZW50LngwOwogIGNvbXBvbmVudC5oZWlnaHQgPSBjb21wb25lbnQueTEgLSBjb21wb25lbnQueTA7Cn0KZnVuY3Rpb24gY2FsY3VsYXRlVGlsZUdyaWRzKGNvbnRleHQsIGNvbXBvbmVudHMpIHsKICBjb25zdCBzaXogPSBjb250ZXh0LlNJWjsKICBjb25zdCB0aWxlcyA9IFtdOwogIGxldCB0aWxlOwogIGNvbnN0IG51bVh0aWxlcyA9IE1hdGguY2VpbCgoc2l6LlhzaXogLSBzaXouWFRPc2l6KSAvIHNpei5YVHNpeik7CiAgY29uc3QgbnVtWXRpbGVzID0gTWF0aC5jZWlsKChzaXouWXNpeiAtIHNpei5ZVE9zaXopIC8gc2l6LllUc2l6KTsKICBmb3IgKGxldCBxID0gMDsgcSA8IG51bVl0aWxlczsgcSsrKSB7CiAgICBmb3IgKGxldCBwID0gMDsgcCA8IG51bVh0aWxlczsgcCsrKSB7CiAgICAgIHRpbGUgPSB7fTsKICAgICAgdGlsZS50eDAgPSBNYXRoLm1heChzaXouWFRPc2l6ICsgcCAqIHNpei5YVHNpeiwgc2l6LlhPc2l6KTsKICAgICAgdGlsZS50eTAgPSBNYXRoLm1heChzaXouWVRPc2l6ICsgcSAqIHNpei5ZVHNpeiwgc2l6LllPc2l6KTsKICAgICAgdGlsZS50eDEgPSBNYXRoLm1pbihzaXouWFRPc2l6ICsgKHAgKyAxKSAqIHNpei5YVHNpeiwgc2l6LlhzaXopOwogICAgICB0aWxlLnR5MSA9IE1hdGgubWluKHNpei5ZVE9zaXogKyAocSArIDEpICogc2l6LllUc2l6LCBzaXouWXNpeik7CiAgICAgIHRpbGUud2lkdGggPSB0aWxlLnR4MSAtIHRpbGUudHgwOwogICAgICB0aWxlLmhlaWdodCA9IHRpbGUudHkxIC0gdGlsZS50eTA7CiAgICAgIHRpbGUuY29tcG9uZW50cyA9IFtdOwogICAgICB0aWxlcy5wdXNoKHRpbGUpOwogICAgfQogIH0KICBjb250ZXh0LnRpbGVzID0gdGlsZXM7CiAgY29uc3QgY29tcG9uZW50c0NvdW50ID0gc2l6LkNzaXo7CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gY29tcG9uZW50c0NvdW50OyBpIDwgaWk7IGkrKykgewogICAgY29uc3QgY29tcG9uZW50ID0gY29tcG9uZW50c1tpXTsKICAgIGZvciAobGV0IGogPSAwLCBqaiA9IHRpbGVzLmxlbmd0aDsgaiA8IGpqOyBqKyspIHsKICAgICAgY29uc3QgdGlsZUNvbXBvbmVudCA9IHt9OwogICAgICB0aWxlID0gdGlsZXNbal07CiAgICAgIHRpbGVDb21wb25lbnQudGN4MCA9IE1hdGguY2VpbCh0aWxlLnR4MCAvIGNvbXBvbmVudC5YUnNpeik7CiAgICAgIHRpbGVDb21wb25lbnQudGN5MCA9IE1hdGguY2VpbCh0aWxlLnR5MCAvIGNvbXBvbmVudC5ZUnNpeik7CiAgICAgIHRpbGVDb21wb25lbnQudGN4MSA9IE1hdGguY2VpbCh0aWxlLnR4MSAvIGNvbXBvbmVudC5YUnNpeik7CiAgICAgIHRpbGVDb21wb25lbnQudGN5MSA9IE1hdGguY2VpbCh0aWxlLnR5MSAvIGNvbXBvbmVudC5ZUnNpeik7CiAgICAgIHRpbGVDb21wb25lbnQud2lkdGggPSB0aWxlQ29tcG9uZW50LnRjeDEgLSB0aWxlQ29tcG9uZW50LnRjeDA7CiAgICAgIHRpbGVDb21wb25lbnQuaGVpZ2h0ID0gdGlsZUNvbXBvbmVudC50Y3kxIC0gdGlsZUNvbXBvbmVudC50Y3kwOwogICAgICB0aWxlLmNvbXBvbmVudHNbaV0gPSB0aWxlQ29tcG9uZW50OwogICAgfQogIH0KfQpmdW5jdGlvbiBnZXRCbG9ja3NEaW1lbnNpb25zKGNvbnRleHQsIGNvbXBvbmVudCwgcikgewogIGNvbnN0IGNvZE9yQ29jID0gY29tcG9uZW50LmNvZGluZ1N0eWxlUGFyYW1ldGVyczsKICBjb25zdCByZXN1bHQgPSB7fTsKICBpZiAoIWNvZE9yQ29jLmVudHJvcHlDb2RlcldpdGhDdXN0b21QcmVjaW5jdHMpIHsKICAgIHJlc3VsdC5QUHggPSAxNTsKICAgIHJlc3VsdC5QUHkgPSAxNTsKICB9IGVsc2UgewogICAgcmVzdWx0LlBQeCA9IGNvZE9yQ29jLnByZWNpbmN0c1NpemVzW3JdLlBQeDsKICAgIHJlc3VsdC5QUHkgPSBjb2RPckNvYy5wcmVjaW5jdHNTaXplc1tyXS5QUHk7CiAgfQogIHJlc3VsdC54Y2JfID0gciA+IDAgPyBNYXRoLm1pbihjb2RPckNvYy54Y2IsIHJlc3VsdC5QUHggLSAxKSA6IE1hdGgubWluKGNvZE9yQ29jLnhjYiwgcmVzdWx0LlBQeCk7CiAgcmVzdWx0LnljYl8gPSByID4gMCA/IE1hdGgubWluKGNvZE9yQ29jLnljYiwgcmVzdWx0LlBQeSAtIDEpIDogTWF0aC5taW4oY29kT3JDb2MueWNiLCByZXN1bHQuUFB5KTsKICByZXR1cm4gcmVzdWx0Owp9CmZ1bmN0aW9uIGJ1aWxkUHJlY2luY3RzKGNvbnRleHQsIHJlc29sdXRpb24sIGRpbWVuc2lvbnMpIHsKICBjb25zdCBwcmVjaW5jdFdpZHRoID0gMSA8PCBkaW1lbnNpb25zLlBQeDsKICBjb25zdCBwcmVjaW5jdEhlaWdodCA9IDEgPDwgZGltZW5zaW9ucy5QUHk7CiAgY29uc3QgaXNaZXJvUmVzID0gcmVzb2x1dGlvbi5yZXNMZXZlbCA9PT0gMDsKICBjb25zdCBwcmVjaW5jdFdpZHRoSW5TdWJiYW5kID0gMSA8PCBkaW1lbnNpb25zLlBQeCArIChpc1plcm9SZXMgPyAwIDogLTEpOwogIGNvbnN0IHByZWNpbmN0SGVpZ2h0SW5TdWJiYW5kID0gMSA8PCBkaW1lbnNpb25zLlBQeSArIChpc1plcm9SZXMgPyAwIDogLTEpOwogIGNvbnN0IG51bXByZWNpbmN0c3dpZGUgPSByZXNvbHV0aW9uLnRyeDEgPiByZXNvbHV0aW9uLnRyeDAgPyBNYXRoLmNlaWwocmVzb2x1dGlvbi50cngxIC8gcHJlY2luY3RXaWR0aCkgLSBNYXRoLmZsb29yKHJlc29sdXRpb24udHJ4MCAvIHByZWNpbmN0V2lkdGgpIDogMDsKICBjb25zdCBudW1wcmVjaW5jdHNoaWdoID0gcmVzb2x1dGlvbi50cnkxID4gcmVzb2x1dGlvbi50cnkwID8gTWF0aC5jZWlsKHJlc29sdXRpb24udHJ5MSAvIHByZWNpbmN0SGVpZ2h0KSAtIE1hdGguZmxvb3IocmVzb2x1dGlvbi50cnkwIC8gcHJlY2luY3RIZWlnaHQpIDogMDsKICBjb25zdCBudW1wcmVjaW5jdHMgPSBudW1wcmVjaW5jdHN3aWRlICogbnVtcHJlY2luY3RzaGlnaDsKICByZXNvbHV0aW9uLnByZWNpbmN0UGFyYW1ldGVycyA9IHsKICAgIHByZWNpbmN0V2lkdGgsCiAgICBwcmVjaW5jdEhlaWdodCwKICAgIG51bXByZWNpbmN0c3dpZGUsCiAgICBudW1wcmVjaW5jdHNoaWdoLAogICAgbnVtcHJlY2luY3RzLAogICAgcHJlY2luY3RXaWR0aEluU3ViYmFuZCwKICAgIHByZWNpbmN0SGVpZ2h0SW5TdWJiYW5kCiAgfTsKfQpmdW5jdGlvbiBidWlsZENvZGVibG9ja3MoY29udGV4dCwgc3ViYmFuZCwgZGltZW5zaW9ucykgewogIGNvbnN0IHhjYl8gPSBkaW1lbnNpb25zLnhjYl87CiAgY29uc3QgeWNiXyA9IGRpbWVuc2lvbnMueWNiXzsKICBjb25zdCBjb2RlYmxvY2tXaWR0aCA9IDEgPDwgeGNiXzsKICBjb25zdCBjb2RlYmxvY2tIZWlnaHQgPSAxIDw8IHljYl87CiAgY29uc3QgY2J4MCA9IHN1YmJhbmQudGJ4MCA+PiB4Y2JfOwogIGNvbnN0IGNieTAgPSBzdWJiYW5kLnRieTAgPj4geWNiXzsKICBjb25zdCBjYngxID0gc3ViYmFuZC50YngxICsgY29kZWJsb2NrV2lkdGggLSAxID4+IHhjYl87CiAgY29uc3QgY2J5MSA9IHN1YmJhbmQudGJ5MSArIGNvZGVibG9ja0hlaWdodCAtIDEgPj4geWNiXzsKICBjb25zdCBwcmVjaW5jdFBhcmFtZXRlcnMgPSBzdWJiYW5kLnJlc29sdXRpb24ucHJlY2luY3RQYXJhbWV0ZXJzOwogIGNvbnN0IGNvZGVibG9ja3MgPSBbXTsKICBjb25zdCBwcmVjaW5jdHMgPSBbXTsKICBsZXQgaSwgaiwgY29kZWJsb2NrLCBwcmVjaW5jdE51bWJlcjsKICBmb3IgKGogPSBjYnkwOyBqIDwgY2J5MTsgaisrKSB7CiAgICBmb3IgKGkgPSBjYngwOyBpIDwgY2J4MTsgaSsrKSB7CiAgICAgIGNvZGVibG9jayA9IHsKICAgICAgICBjYng6IGksCiAgICAgICAgY2J5OiBqLAogICAgICAgIHRieDA6IGNvZGVibG9ja1dpZHRoICogaSwKICAgICAgICB0YnkwOiBjb2RlYmxvY2tIZWlnaHQgKiBqLAogICAgICAgIHRieDE6IGNvZGVibG9ja1dpZHRoICogKGkgKyAxKSwKICAgICAgICB0YnkxOiBjb2RlYmxvY2tIZWlnaHQgKiAoaiArIDEpCiAgICAgIH07CiAgICAgIGNvZGVibG9jay50YngwXyA9IE1hdGgubWF4KHN1YmJhbmQudGJ4MCwgY29kZWJsb2NrLnRieDApOwogICAgICBjb2RlYmxvY2sudGJ5MF8gPSBNYXRoLm1heChzdWJiYW5kLnRieTAsIGNvZGVibG9jay50YnkwKTsKICAgICAgY29kZWJsb2NrLnRieDFfID0gTWF0aC5taW4oc3ViYmFuZC50YngxLCBjb2RlYmxvY2sudGJ4MSk7CiAgICAgIGNvZGVibG9jay50YnkxXyA9IE1hdGgubWluKHN1YmJhbmQudGJ5MSwgY29kZWJsb2NrLnRieTEpOwogICAgICBjb25zdCBwaSA9IE1hdGguZmxvb3IoKGNvZGVibG9jay50YngwXyAtIHN1YmJhbmQudGJ4MCkgLyBwcmVjaW5jdFBhcmFtZXRlcnMucHJlY2luY3RXaWR0aEluU3ViYmFuZCk7CiAgICAgIGNvbnN0IHBqID0gTWF0aC5mbG9vcigoY29kZWJsb2NrLnRieTBfIC0gc3ViYmFuZC50YnkwKSAvIHByZWNpbmN0UGFyYW1ldGVycy5wcmVjaW5jdEhlaWdodEluU3ViYmFuZCk7CiAgICAgIHByZWNpbmN0TnVtYmVyID0gcGkgKyBwaiAqIHByZWNpbmN0UGFyYW1ldGVycy5udW1wcmVjaW5jdHN3aWRlOwogICAgICBjb2RlYmxvY2sucHJlY2luY3ROdW1iZXIgPSBwcmVjaW5jdE51bWJlcjsKICAgICAgY29kZWJsb2NrLnN1YmJhbmRUeXBlID0gc3ViYmFuZC50eXBlOwogICAgICBjb2RlYmxvY2suTGJsb2NrID0gMzsKICAgICAgaWYgKGNvZGVibG9jay50YngxXyA8PSBjb2RlYmxvY2sudGJ4MF8gfHwgY29kZWJsb2NrLnRieTFfIDw9IGNvZGVibG9jay50YnkwXykgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvZGVibG9ja3MucHVzaChjb2RlYmxvY2spOwogICAgICBsZXQgcHJlY2luY3QgPSBwcmVjaW5jdHNbcHJlY2luY3ROdW1iZXJdOwogICAgICBpZiAocHJlY2luY3QgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGlmIChpIDwgcHJlY2luY3QuY2J4TWluKSB7CiAgICAgICAgICBwcmVjaW5jdC5jYnhNaW4gPSBpOwogICAgICAgIH0gZWxzZSBpZiAoaSA+IHByZWNpbmN0LmNieE1heCkgewogICAgICAgICAgcHJlY2luY3QuY2J4TWF4ID0gaTsKICAgICAgICB9CiAgICAgICAgaWYgKGogPCBwcmVjaW5jdC5jYnlNaW4pIHsKICAgICAgICAgIHByZWNpbmN0LmNieE1pbiA9IGo7CiAgICAgICAgfSBlbHNlIGlmIChqID4gcHJlY2luY3QuY2J5TWF4KSB7CiAgICAgICAgICBwcmVjaW5jdC5jYnlNYXggPSBqOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBwcmVjaW5jdHNbcHJlY2luY3ROdW1iZXJdID0gcHJlY2luY3QgPSB7CiAgICAgICAgICBjYnhNaW46IGksCiAgICAgICAgICBjYnlNaW46IGosCiAgICAgICAgICBjYnhNYXg6IGksCiAgICAgICAgICBjYnlNYXg6IGoKICAgICAgICB9OwogICAgICB9CiAgICAgIGNvZGVibG9jay5wcmVjaW5jdCA9IHByZWNpbmN0OwogICAgfQogIH0KICBzdWJiYW5kLmNvZGVibG9ja1BhcmFtZXRlcnMgPSB7CiAgICBjb2RlYmxvY2tXaWR0aDogeGNiXywKICAgIGNvZGVibG9ja0hlaWdodDogeWNiXywKICAgIG51bWNvZGVibG9ja3dpZGU6IGNieDEgLSBjYngwICsgMSwKICAgIG51bWNvZGVibG9ja2hpZ2g6IGNieTEgLSBjYnkwICsgMQogIH07CiAgc3ViYmFuZC5jb2RlYmxvY2tzID0gY29kZWJsb2NrczsKICBzdWJiYW5kLnByZWNpbmN0cyA9IHByZWNpbmN0czsKfQpmdW5jdGlvbiBjcmVhdGVQYWNrZXQocmVzb2x1dGlvbiwgcHJlY2luY3ROdW1iZXIsIGxheWVyTnVtYmVyKSB7CiAgY29uc3QgcHJlY2luY3RDb2RlYmxvY2tzID0gW107CiAgY29uc3Qgc3ViYmFuZHMgPSByZXNvbHV0aW9uLnN1YmJhbmRzOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IHN1YmJhbmRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IHN1YmJhbmQgPSBzdWJiYW5kc1tpXTsKICAgIGNvbnN0IGNvZGVibG9ja3MgPSBzdWJiYW5kLmNvZGVibG9ja3M7CiAgICBmb3IgKGxldCBqID0gMCwgamogPSBjb2RlYmxvY2tzLmxlbmd0aDsgaiA8IGpqOyBqKyspIHsKICAgICAgY29uc3QgY29kZWJsb2NrID0gY29kZWJsb2Nrc1tqXTsKICAgICAgaWYgKGNvZGVibG9jay5wcmVjaW5jdE51bWJlciAhPT0gcHJlY2luY3ROdW1iZXIpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBwcmVjaW5jdENvZGVibG9ja3MucHVzaChjb2RlYmxvY2spOwogICAgfQogIH0KICByZXR1cm4gewogICAgbGF5ZXJOdW1iZXIsCiAgICBjb2RlYmxvY2tzOiBwcmVjaW5jdENvZGVibG9ja3MKICB9Owp9CmZ1bmN0aW9uIExheWVyUmVzb2x1dGlvbkNvbXBvbmVudFBvc2l0aW9uSXRlcmF0b3IoY29udGV4dCkgewogIGNvbnN0IHNpeiA9IGNvbnRleHQuU0laOwogIGNvbnN0IHRpbGVJbmRleCA9IGNvbnRleHQuY3VycmVudFRpbGUuaW5kZXg7CiAgY29uc3QgdGlsZSA9IGNvbnRleHQudGlsZXNbdGlsZUluZGV4XTsKICBjb25zdCBsYXllcnNDb3VudCA9IHRpbGUuY29kaW5nU3R5bGVEZWZhdWx0UGFyYW1ldGVycy5sYXllcnNDb3VudDsKICBjb25zdCBjb21wb25lbnRzQ291bnQgPSBzaXouQ3NpejsKICBsZXQgbWF4RGVjb21wb3NpdGlvbkxldmVsc0NvdW50ID0gMDsKICBmb3IgKGxldCBxID0gMDsgcSA8IGNvbXBvbmVudHNDb3VudDsgcSsrKSB7CiAgICBtYXhEZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQgPSBNYXRoLm1heChtYXhEZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQsIHRpbGUuY29tcG9uZW50c1txXS5jb2RpbmdTdHlsZVBhcmFtZXRlcnMuZGVjb21wb3NpdGlvbkxldmVsc0NvdW50KTsKICB9CiAgbGV0IGwgPSAwLAogICAgciA9IDAsCiAgICBpID0gMCwKICAgIGsgPSAwOwogIHRoaXMubmV4dFBhY2tldCA9IGZ1bmN0aW9uIEpweEltYWdlX25leHRQYWNrZXQoKSB7CiAgICBmb3IgKDsgbCA8IGxheWVyc0NvdW50OyBsKyspIHsKICAgICAgZm9yICg7IHIgPD0gbWF4RGVjb21wb3NpdGlvbkxldmVsc0NvdW50OyByKyspIHsKICAgICAgICBmb3IgKDsgaSA8IGNvbXBvbmVudHNDb3VudDsgaSsrKSB7CiAgICAgICAgICBjb25zdCBjb21wb25lbnQgPSB0aWxlLmNvbXBvbmVudHNbaV07CiAgICAgICAgICBpZiAociA+IGNvbXBvbmVudC5jb2RpbmdTdHlsZVBhcmFtZXRlcnMuZGVjb21wb3NpdGlvbkxldmVsc0NvdW50KSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgcmVzb2x1dGlvbiA9IGNvbXBvbmVudC5yZXNvbHV0aW9uc1tyXTsKICAgICAgICAgIGNvbnN0IG51bXByZWNpbmN0cyA9IHJlc29sdXRpb24ucHJlY2luY3RQYXJhbWV0ZXJzLm51bXByZWNpbmN0czsKICAgICAgICAgIGZvciAoOyBrIDwgbnVtcHJlY2luY3RzOykgewogICAgICAgICAgICBjb25zdCBwYWNrZXQgPSBjcmVhdGVQYWNrZXQocmVzb2x1dGlvbiwgaywgbCk7CiAgICAgICAgICAgIGsrKzsKICAgICAgICAgICAgcmV0dXJuIHBhY2tldDsKICAgICAgICAgIH0KICAgICAgICAgIGsgPSAwOwogICAgICAgIH0KICAgICAgICBpID0gMDsKICAgICAgfQogICAgICByID0gMDsKICAgIH0KICAgIHRocm93IG5ldyBKcHhFcnJvcigiT3V0IG9mIHBhY2tldHMiKTsKICB9Owp9CmZ1bmN0aW9uIFJlc29sdXRpb25MYXllckNvbXBvbmVudFBvc2l0aW9uSXRlcmF0b3IoY29udGV4dCkgewogIGNvbnN0IHNpeiA9IGNvbnRleHQuU0laOwogIGNvbnN0IHRpbGVJbmRleCA9IGNvbnRleHQuY3VycmVudFRpbGUuaW5kZXg7CiAgY29uc3QgdGlsZSA9IGNvbnRleHQudGlsZXNbdGlsZUluZGV4XTsKICBjb25zdCBsYXllcnNDb3VudCA9IHRpbGUuY29kaW5nU3R5bGVEZWZhdWx0UGFyYW1ldGVycy5sYXllcnNDb3VudDsKICBjb25zdCBjb21wb25lbnRzQ291bnQgPSBzaXouQ3NpejsKICBsZXQgbWF4RGVjb21wb3NpdGlvbkxldmVsc0NvdW50ID0gMDsKICBmb3IgKGxldCBxID0gMDsgcSA8IGNvbXBvbmVudHNDb3VudDsgcSsrKSB7CiAgICBtYXhEZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQgPSBNYXRoLm1heChtYXhEZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQsIHRpbGUuY29tcG9uZW50c1txXS5jb2RpbmdTdHlsZVBhcmFtZXRlcnMuZGVjb21wb3NpdGlvbkxldmVsc0NvdW50KTsKICB9CiAgbGV0IHIgPSAwLAogICAgbCA9IDAsCiAgICBpID0gMCwKICAgIGsgPSAwOwogIHRoaXMubmV4dFBhY2tldCA9IGZ1bmN0aW9uIEpweEltYWdlX25leHRQYWNrZXQoKSB7CiAgICBmb3IgKDsgciA8PSBtYXhEZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQ7IHIrKykgewogICAgICBmb3IgKDsgbCA8IGxheWVyc0NvdW50OyBsKyspIHsKICAgICAgICBmb3IgKDsgaSA8IGNvbXBvbmVudHNDb3VudDsgaSsrKSB7CiAgICAgICAgICBjb25zdCBjb21wb25lbnQgPSB0aWxlLmNvbXBvbmVudHNbaV07CiAgICAgICAgICBpZiAociA+IGNvbXBvbmVudC5jb2RpbmdTdHlsZVBhcmFtZXRlcnMuZGVjb21wb3NpdGlvbkxldmVsc0NvdW50KSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgcmVzb2x1dGlvbiA9IGNvbXBvbmVudC5yZXNvbHV0aW9uc1tyXTsKICAgICAgICAgIGNvbnN0IG51bXByZWNpbmN0cyA9IHJlc29sdXRpb24ucHJlY2luY3RQYXJhbWV0ZXJzLm51bXByZWNpbmN0czsKICAgICAgICAgIGZvciAoOyBrIDwgbnVtcHJlY2luY3RzOykgewogICAgICAgICAgICBjb25zdCBwYWNrZXQgPSBjcmVhdGVQYWNrZXQocmVzb2x1dGlvbiwgaywgbCk7CiAgICAgICAgICAgIGsrKzsKICAgICAgICAgICAgcmV0dXJuIHBhY2tldDsKICAgICAgICAgIH0KICAgICAgICAgIGsgPSAwOwogICAgICAgIH0KICAgICAgICBpID0gMDsKICAgICAgfQogICAgICBsID0gMDsKICAgIH0KICAgIHRocm93IG5ldyBKcHhFcnJvcigiT3V0IG9mIHBhY2tldHMiKTsKICB9Owp9CmZ1bmN0aW9uIFJlc29sdXRpb25Qb3NpdGlvbkNvbXBvbmVudExheWVySXRlcmF0b3IoY29udGV4dCkgewogIGNvbnN0IHNpeiA9IGNvbnRleHQuU0laOwogIGNvbnN0IHRpbGVJbmRleCA9IGNvbnRleHQuY3VycmVudFRpbGUuaW5kZXg7CiAgY29uc3QgdGlsZSA9IGNvbnRleHQudGlsZXNbdGlsZUluZGV4XTsKICBjb25zdCBsYXllcnNDb3VudCA9IHRpbGUuY29kaW5nU3R5bGVEZWZhdWx0UGFyYW1ldGVycy5sYXllcnNDb3VudDsKICBjb25zdCBjb21wb25lbnRzQ291bnQgPSBzaXouQ3NpejsKICBsZXQgbCwgciwgYywgcDsKICBsZXQgbWF4RGVjb21wb3NpdGlvbkxldmVsc0NvdW50ID0gMDsKICBmb3IgKGMgPSAwOyBjIDwgY29tcG9uZW50c0NvdW50OyBjKyspIHsKICAgIGNvbnN0IGNvbXBvbmVudCA9IHRpbGUuY29tcG9uZW50c1tjXTsKICAgIG1heERlY29tcG9zaXRpb25MZXZlbHNDb3VudCA9IE1hdGgubWF4KG1heERlY29tcG9zaXRpb25MZXZlbHNDb3VudCwgY29tcG9uZW50LmNvZGluZ1N0eWxlUGFyYW1ldGVycy5kZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQpOwogIH0KICBjb25zdCBtYXhOdW1QcmVjaW5jdHNJbkxldmVsID0gbmV3IEludDMyQXJyYXkobWF4RGVjb21wb3NpdGlvbkxldmVsc0NvdW50ICsgMSk7CiAgZm9yIChyID0gMDsgciA8PSBtYXhEZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQ7ICsrcikgewogICAgbGV0IG1heE51bVByZWNpbmN0cyA9IDA7CiAgICBmb3IgKGMgPSAwOyBjIDwgY29tcG9uZW50c0NvdW50OyArK2MpIHsKICAgICAgY29uc3QgcmVzb2x1dGlvbnMgPSB0aWxlLmNvbXBvbmVudHNbY10ucmVzb2x1dGlvbnM7CiAgICAgIGlmIChyIDwgcmVzb2x1dGlvbnMubGVuZ3RoKSB7CiAgICAgICAgbWF4TnVtUHJlY2luY3RzID0gTWF0aC5tYXgobWF4TnVtUHJlY2luY3RzLCByZXNvbHV0aW9uc1tyXS5wcmVjaW5jdFBhcmFtZXRlcnMubnVtcHJlY2luY3RzKTsKICAgICAgfQogICAgfQogICAgbWF4TnVtUHJlY2luY3RzSW5MZXZlbFtyXSA9IG1heE51bVByZWNpbmN0czsKICB9CiAgbCA9IDA7CiAgciA9IDA7CiAgYyA9IDA7CiAgcCA9IDA7CiAgdGhpcy5uZXh0UGFja2V0ID0gZnVuY3Rpb24gSnB4SW1hZ2VfbmV4dFBhY2tldCgpIHsKICAgIGZvciAoOyByIDw9IG1heERlY29tcG9zaXRpb25MZXZlbHNDb3VudDsgcisrKSB7CiAgICAgIGZvciAoOyBwIDwgbWF4TnVtUHJlY2luY3RzSW5MZXZlbFtyXTsgcCsrKSB7CiAgICAgICAgZm9yICg7IGMgPCBjb21wb25lbnRzQ291bnQ7IGMrKykgewogICAgICAgICAgY29uc3QgY29tcG9uZW50ID0gdGlsZS5jb21wb25lbnRzW2NdOwogICAgICAgICAgaWYgKHIgPiBjb21wb25lbnQuY29kaW5nU3R5bGVQYXJhbWV0ZXJzLmRlY29tcG9zaXRpb25MZXZlbHNDb3VudCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IHJlc29sdXRpb24gPSBjb21wb25lbnQucmVzb2x1dGlvbnNbcl07CiAgICAgICAgICBjb25zdCBudW1wcmVjaW5jdHMgPSByZXNvbHV0aW9uLnByZWNpbmN0UGFyYW1ldGVycy5udW1wcmVjaW5jdHM7CiAgICAgICAgICBpZiAocCA+PSBudW1wcmVjaW5jdHMpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBmb3IgKDsgbCA8IGxheWVyc0NvdW50OykgewogICAgICAgICAgICBjb25zdCBwYWNrZXQgPSBjcmVhdGVQYWNrZXQocmVzb2x1dGlvbiwgcCwgbCk7CiAgICAgICAgICAgIGwrKzsKICAgICAgICAgICAgcmV0dXJuIHBhY2tldDsKICAgICAgICAgIH0KICAgICAgICAgIGwgPSAwOwogICAgICAgIH0KICAgICAgICBjID0gMDsKICAgICAgfQogICAgICBwID0gMDsKICAgIH0KICAgIHRocm93IG5ldyBKcHhFcnJvcigiT3V0IG9mIHBhY2tldHMiKTsKICB9Owp9CmZ1bmN0aW9uIFBvc2l0aW9uQ29tcG9uZW50UmVzb2x1dGlvbkxheWVySXRlcmF0b3IoY29udGV4dCkgewogIGNvbnN0IHNpeiA9IGNvbnRleHQuU0laOwogIGNvbnN0IHRpbGVJbmRleCA9IGNvbnRleHQuY3VycmVudFRpbGUuaW5kZXg7CiAgY29uc3QgdGlsZSA9IGNvbnRleHQudGlsZXNbdGlsZUluZGV4XTsKICBjb25zdCBsYXllcnNDb3VudCA9IHRpbGUuY29kaW5nU3R5bGVEZWZhdWx0UGFyYW1ldGVycy5sYXllcnNDb3VudDsKICBjb25zdCBjb21wb25lbnRzQ291bnQgPSBzaXouQ3NpejsKICBjb25zdCBwcmVjaW5jdHNTaXplcyA9IGdldFByZWNpbmN0U2l6ZXNJbkltYWdlU2NhbGUodGlsZSk7CiAgY29uc3QgcHJlY2luY3RzSXRlcmF0aW9uU2l6ZXMgPSBwcmVjaW5jdHNTaXplczsKICBsZXQgbCA9IDAsCiAgICByID0gMCwKICAgIGMgPSAwLAogICAgcHggPSAwLAogICAgcHkgPSAwOwogIHRoaXMubmV4dFBhY2tldCA9IGZ1bmN0aW9uIEpweEltYWdlX25leHRQYWNrZXQoKSB7CiAgICBmb3IgKDsgcHkgPCBwcmVjaW5jdHNJdGVyYXRpb25TaXplcy5tYXhOdW1IaWdoOyBweSsrKSB7CiAgICAgIGZvciAoOyBweCA8IHByZWNpbmN0c0l0ZXJhdGlvblNpemVzLm1heE51bVdpZGU7IHB4KyspIHsKICAgICAgICBmb3IgKDsgYyA8IGNvbXBvbmVudHNDb3VudDsgYysrKSB7CiAgICAgICAgICBjb25zdCBjb21wb25lbnQgPSB0aWxlLmNvbXBvbmVudHNbY107CiAgICAgICAgICBjb25zdCBkZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQgPSBjb21wb25lbnQuY29kaW5nU3R5bGVQYXJhbWV0ZXJzLmRlY29tcG9zaXRpb25MZXZlbHNDb3VudDsKICAgICAgICAgIGZvciAoOyByIDw9IGRlY29tcG9zaXRpb25MZXZlbHNDb3VudDsgcisrKSB7CiAgICAgICAgICAgIGNvbnN0IHJlc29sdXRpb24gPSBjb21wb25lbnQucmVzb2x1dGlvbnNbcl07CiAgICAgICAgICAgIGNvbnN0IHNpemVJbkltYWdlU2NhbGUgPSBwcmVjaW5jdHNTaXplcy5jb21wb25lbnRzW2NdLnJlc29sdXRpb25zW3JdOwogICAgICAgICAgICBjb25zdCBrID0gZ2V0UHJlY2luY3RJbmRleElmRXhpc3QocHgsIHB5LCBzaXplSW5JbWFnZVNjYWxlLCBwcmVjaW5jdHNJdGVyYXRpb25TaXplcywgcmVzb2x1dGlvbik7CiAgICAgICAgICAgIGlmIChrID09PSBudWxsKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yICg7IGwgPCBsYXllcnNDb3VudDspIHsKICAgICAgICAgICAgICBjb25zdCBwYWNrZXQgPSBjcmVhdGVQYWNrZXQocmVzb2x1dGlvbiwgaywgbCk7CiAgICAgICAgICAgICAgbCsrOwogICAgICAgICAgICAgIHJldHVybiBwYWNrZXQ7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbCA9IDA7CiAgICAgICAgICB9CiAgICAgICAgICByID0gMDsKICAgICAgICB9CiAgICAgICAgYyA9IDA7CiAgICAgIH0KICAgICAgcHggPSAwOwogICAgfQogICAgdGhyb3cgbmV3IEpweEVycm9yKCJPdXQgb2YgcGFja2V0cyIpOwogIH07Cn0KZnVuY3Rpb24gQ29tcG9uZW50UG9zaXRpb25SZXNvbHV0aW9uTGF5ZXJJdGVyYXRvcihjb250ZXh0KSB7CiAgY29uc3Qgc2l6ID0gY29udGV4dC5TSVo7CiAgY29uc3QgdGlsZUluZGV4ID0gY29udGV4dC5jdXJyZW50VGlsZS5pbmRleDsKICBjb25zdCB0aWxlID0gY29udGV4dC50aWxlc1t0aWxlSW5kZXhdOwogIGNvbnN0IGxheWVyc0NvdW50ID0gdGlsZS5jb2RpbmdTdHlsZURlZmF1bHRQYXJhbWV0ZXJzLmxheWVyc0NvdW50OwogIGNvbnN0IGNvbXBvbmVudHNDb3VudCA9IHNpei5Dc2l6OwogIGNvbnN0IHByZWNpbmN0c1NpemVzID0gZ2V0UHJlY2luY3RTaXplc0luSW1hZ2VTY2FsZSh0aWxlKTsKICBsZXQgbCA9IDAsCiAgICByID0gMCwKICAgIGMgPSAwLAogICAgcHggPSAwLAogICAgcHkgPSAwOwogIHRoaXMubmV4dFBhY2tldCA9IGZ1bmN0aW9uIEpweEltYWdlX25leHRQYWNrZXQoKSB7CiAgICBmb3IgKDsgYyA8IGNvbXBvbmVudHNDb3VudDsgKytjKSB7CiAgICAgIGNvbnN0IGNvbXBvbmVudCA9IHRpbGUuY29tcG9uZW50c1tjXTsKICAgICAgY29uc3QgcHJlY2luY3RzSXRlcmF0aW9uU2l6ZXMgPSBwcmVjaW5jdHNTaXplcy5jb21wb25lbnRzW2NdOwogICAgICBjb25zdCBkZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQgPSBjb21wb25lbnQuY29kaW5nU3R5bGVQYXJhbWV0ZXJzLmRlY29tcG9zaXRpb25MZXZlbHNDb3VudDsKICAgICAgZm9yICg7IHB5IDwgcHJlY2luY3RzSXRlcmF0aW9uU2l6ZXMubWF4TnVtSGlnaDsgcHkrKykgewogICAgICAgIGZvciAoOyBweCA8IHByZWNpbmN0c0l0ZXJhdGlvblNpemVzLm1heE51bVdpZGU7IHB4KyspIHsKICAgICAgICAgIGZvciAoOyByIDw9IGRlY29tcG9zaXRpb25MZXZlbHNDb3VudDsgcisrKSB7CiAgICAgICAgICAgIGNvbnN0IHJlc29sdXRpb24gPSBjb21wb25lbnQucmVzb2x1dGlvbnNbcl07CiAgICAgICAgICAgIGNvbnN0IHNpemVJbkltYWdlU2NhbGUgPSBwcmVjaW5jdHNJdGVyYXRpb25TaXplcy5yZXNvbHV0aW9uc1tyXTsKICAgICAgICAgICAgY29uc3QgayA9IGdldFByZWNpbmN0SW5kZXhJZkV4aXN0KHB4LCBweSwgc2l6ZUluSW1hZ2VTY2FsZSwgcHJlY2luY3RzSXRlcmF0aW9uU2l6ZXMsIHJlc29sdXRpb24pOwogICAgICAgICAgICBpZiAoayA9PT0gbnVsbCkgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvciAoOyBsIDwgbGF5ZXJzQ291bnQ7KSB7CiAgICAgICAgICAgICAgY29uc3QgcGFja2V0ID0gY3JlYXRlUGFja2V0KHJlc29sdXRpb24sIGssIGwpOwogICAgICAgICAgICAgIGwrKzsKICAgICAgICAgICAgICByZXR1cm4gcGFja2V0OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGwgPSAwOwogICAgICAgICAgfQogICAgICAgICAgciA9IDA7CiAgICAgICAgfQogICAgICAgIHB4ID0gMDsKICAgICAgfQogICAgICBweSA9IDA7CiAgICB9CiAgICB0aHJvdyBuZXcgSnB4RXJyb3IoIk91dCBvZiBwYWNrZXRzIik7CiAgfTsKfQpmdW5jdGlvbiBnZXRQcmVjaW5jdEluZGV4SWZFeGlzdChweEluZGV4LCBweUluZGV4LCBzaXplSW5JbWFnZVNjYWxlLCBwcmVjaW5jdEl0ZXJhdGlvblNpemVzLCByZXNvbHV0aW9uKSB7CiAgY29uc3QgcG9zWCA9IHB4SW5kZXggKiBwcmVjaW5jdEl0ZXJhdGlvblNpemVzLm1pbldpZHRoOwogIGNvbnN0IHBvc1kgPSBweUluZGV4ICogcHJlY2luY3RJdGVyYXRpb25TaXplcy5taW5IZWlnaHQ7CiAgaWYgKHBvc1ggJSBzaXplSW5JbWFnZVNjYWxlLndpZHRoICE9PSAwIHx8IHBvc1kgJSBzaXplSW5JbWFnZVNjYWxlLmhlaWdodCAhPT0gMCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGNvbnN0IHN0YXJ0UHJlY2luY3RSb3dJbmRleCA9IHBvc1kgLyBzaXplSW5JbWFnZVNjYWxlLndpZHRoICogcmVzb2x1dGlvbi5wcmVjaW5jdFBhcmFtZXRlcnMubnVtcHJlY2luY3Rzd2lkZTsKICByZXR1cm4gcG9zWCAvIHNpemVJbkltYWdlU2NhbGUuaGVpZ2h0ICsgc3RhcnRQcmVjaW5jdFJvd0luZGV4Owp9CmZ1bmN0aW9uIGdldFByZWNpbmN0U2l6ZXNJbkltYWdlU2NhbGUodGlsZSkgewogIGNvbnN0IGNvbXBvbmVudHNDb3VudCA9IHRpbGUuY29tcG9uZW50cy5sZW5ndGg7CiAgbGV0IG1pbldpZHRoID0gTnVtYmVyLk1BWF9WQUxVRTsKICBsZXQgbWluSGVpZ2h0ID0gTnVtYmVyLk1BWF9WQUxVRTsKICBsZXQgbWF4TnVtV2lkZSA9IDA7CiAgbGV0IG1heE51bUhpZ2ggPSAwOwogIGNvbnN0IHNpemVQZXJDb21wb25lbnQgPSBuZXcgQXJyYXkoY29tcG9uZW50c0NvdW50KTsKICBmb3IgKGxldCBjID0gMDsgYyA8IGNvbXBvbmVudHNDb3VudDsgYysrKSB7CiAgICBjb25zdCBjb21wb25lbnQgPSB0aWxlLmNvbXBvbmVudHNbY107CiAgICBjb25zdCBkZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQgPSBjb21wb25lbnQuY29kaW5nU3R5bGVQYXJhbWV0ZXJzLmRlY29tcG9zaXRpb25MZXZlbHNDb3VudDsKICAgIGNvbnN0IHNpemVQZXJSZXNvbHV0aW9uID0gbmV3IEFycmF5KGRlY29tcG9zaXRpb25MZXZlbHNDb3VudCArIDEpOwogICAgbGV0IG1pbldpZHRoQ3VycmVudENvbXBvbmVudCA9IE51bWJlci5NQVhfVkFMVUU7CiAgICBsZXQgbWluSGVpZ2h0Q3VycmVudENvbXBvbmVudCA9IE51bWJlci5NQVhfVkFMVUU7CiAgICBsZXQgbWF4TnVtV2lkZUN1cnJlbnRDb21wb25lbnQgPSAwOwogICAgbGV0IG1heE51bUhpZ2hDdXJyZW50Q29tcG9uZW50ID0gMDsKICAgIGxldCBzY2FsZSA9IDE7CiAgICBmb3IgKGxldCByID0gZGVjb21wb3NpdGlvbkxldmVsc0NvdW50OyByID49IDA7IC0tcikgewogICAgICBjb25zdCByZXNvbHV0aW9uID0gY29tcG9uZW50LnJlc29sdXRpb25zW3JdOwogICAgICBjb25zdCB3aWR0aEN1cnJlbnRSZXNvbHV0aW9uID0gc2NhbGUgKiByZXNvbHV0aW9uLnByZWNpbmN0UGFyYW1ldGVycy5wcmVjaW5jdFdpZHRoOwogICAgICBjb25zdCBoZWlnaHRDdXJyZW50UmVzb2x1dGlvbiA9IHNjYWxlICogcmVzb2x1dGlvbi5wcmVjaW5jdFBhcmFtZXRlcnMucHJlY2luY3RIZWlnaHQ7CiAgICAgIG1pbldpZHRoQ3VycmVudENvbXBvbmVudCA9IE1hdGgubWluKG1pbldpZHRoQ3VycmVudENvbXBvbmVudCwgd2lkdGhDdXJyZW50UmVzb2x1dGlvbik7CiAgICAgIG1pbkhlaWdodEN1cnJlbnRDb21wb25lbnQgPSBNYXRoLm1pbihtaW5IZWlnaHRDdXJyZW50Q29tcG9uZW50LCBoZWlnaHRDdXJyZW50UmVzb2x1dGlvbik7CiAgICAgIG1heE51bVdpZGVDdXJyZW50Q29tcG9uZW50ID0gTWF0aC5tYXgobWF4TnVtV2lkZUN1cnJlbnRDb21wb25lbnQsIHJlc29sdXRpb24ucHJlY2luY3RQYXJhbWV0ZXJzLm51bXByZWNpbmN0c3dpZGUpOwogICAgICBtYXhOdW1IaWdoQ3VycmVudENvbXBvbmVudCA9IE1hdGgubWF4KG1heE51bUhpZ2hDdXJyZW50Q29tcG9uZW50LCByZXNvbHV0aW9uLnByZWNpbmN0UGFyYW1ldGVycy5udW1wcmVjaW5jdHNoaWdoKTsKICAgICAgc2l6ZVBlclJlc29sdXRpb25bcl0gPSB7CiAgICAgICAgd2lkdGg6IHdpZHRoQ3VycmVudFJlc29sdXRpb24sCiAgICAgICAgaGVpZ2h0OiBoZWlnaHRDdXJyZW50UmVzb2x1dGlvbgogICAgICB9OwogICAgICBzY2FsZSA8PD0gMTsKICAgIH0KICAgIG1pbldpZHRoID0gTWF0aC5taW4obWluV2lkdGgsIG1pbldpZHRoQ3VycmVudENvbXBvbmVudCk7CiAgICBtaW5IZWlnaHQgPSBNYXRoLm1pbihtaW5IZWlnaHQsIG1pbkhlaWdodEN1cnJlbnRDb21wb25lbnQpOwogICAgbWF4TnVtV2lkZSA9IE1hdGgubWF4KG1heE51bVdpZGUsIG1heE51bVdpZGVDdXJyZW50Q29tcG9uZW50KTsKICAgIG1heE51bUhpZ2ggPSBNYXRoLm1heChtYXhOdW1IaWdoLCBtYXhOdW1IaWdoQ3VycmVudENvbXBvbmVudCk7CiAgICBzaXplUGVyQ29tcG9uZW50W2NdID0gewogICAgICByZXNvbHV0aW9uczogc2l6ZVBlclJlc29sdXRpb24sCiAgICAgIG1pbldpZHRoOiBtaW5XaWR0aEN1cnJlbnRDb21wb25lbnQsCiAgICAgIG1pbkhlaWdodDogbWluSGVpZ2h0Q3VycmVudENvbXBvbmVudCwKICAgICAgbWF4TnVtV2lkZTogbWF4TnVtV2lkZUN1cnJlbnRDb21wb25lbnQsCiAgICAgIG1heE51bUhpZ2g6IG1heE51bUhpZ2hDdXJyZW50Q29tcG9uZW50CiAgICB9OwogIH0KICByZXR1cm4gewogICAgY29tcG9uZW50czogc2l6ZVBlckNvbXBvbmVudCwKICAgIG1pbldpZHRoLAogICAgbWluSGVpZ2h0LAogICAgbWF4TnVtV2lkZSwKICAgIG1heE51bUhpZ2gKICB9Owp9CmZ1bmN0aW9uIGJ1aWxkUGFja2V0cyhjb250ZXh0KSB7CiAgY29uc3Qgc2l6ID0gY29udGV4dC5TSVo7CiAgY29uc3QgdGlsZUluZGV4ID0gY29udGV4dC5jdXJyZW50VGlsZS5pbmRleDsKICBjb25zdCB0aWxlID0gY29udGV4dC50aWxlc1t0aWxlSW5kZXhdOwogIGNvbnN0IGNvbXBvbmVudHNDb3VudCA9IHNpei5Dc2l6OwogIGZvciAobGV0IGMgPSAwOyBjIDwgY29tcG9uZW50c0NvdW50OyBjKyspIHsKICAgIGNvbnN0IGNvbXBvbmVudCA9IHRpbGUuY29tcG9uZW50c1tjXTsKICAgIGNvbnN0IGRlY29tcG9zaXRpb25MZXZlbHNDb3VudCA9IGNvbXBvbmVudC5jb2RpbmdTdHlsZVBhcmFtZXRlcnMuZGVjb21wb3NpdGlvbkxldmVsc0NvdW50OwogICAgY29uc3QgcmVzb2x1dGlvbnMgPSBbXTsKICAgIGNvbnN0IHN1YmJhbmRzID0gW107CiAgICBmb3IgKGxldCByID0gMDsgciA8PSBkZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQ7IHIrKykgewogICAgICBjb25zdCBibG9ja3NEaW1lbnNpb25zID0gZ2V0QmxvY2tzRGltZW5zaW9ucyhjb250ZXh0LCBjb21wb25lbnQsIHIpOwogICAgICBjb25zdCByZXNvbHV0aW9uID0ge307CiAgICAgIGNvbnN0IHNjYWxlID0gMSA8PCBkZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQgLSByOwogICAgICByZXNvbHV0aW9uLnRyeDAgPSBNYXRoLmNlaWwoY29tcG9uZW50LnRjeDAgLyBzY2FsZSk7CiAgICAgIHJlc29sdXRpb24udHJ5MCA9IE1hdGguY2VpbChjb21wb25lbnQudGN5MCAvIHNjYWxlKTsKICAgICAgcmVzb2x1dGlvbi50cngxID0gTWF0aC5jZWlsKGNvbXBvbmVudC50Y3gxIC8gc2NhbGUpOwogICAgICByZXNvbHV0aW9uLnRyeTEgPSBNYXRoLmNlaWwoY29tcG9uZW50LnRjeTEgLyBzY2FsZSk7CiAgICAgIHJlc29sdXRpb24ucmVzTGV2ZWwgPSByOwogICAgICBidWlsZFByZWNpbmN0cyhjb250ZXh0LCByZXNvbHV0aW9uLCBibG9ja3NEaW1lbnNpb25zKTsKICAgICAgcmVzb2x1dGlvbnMucHVzaChyZXNvbHV0aW9uKTsKICAgICAgbGV0IHN1YmJhbmQ7CiAgICAgIGlmIChyID09PSAwKSB7CiAgICAgICAgc3ViYmFuZCA9IHt9OwogICAgICAgIHN1YmJhbmQudHlwZSA9ICJMTCI7CiAgICAgICAgc3ViYmFuZC50YngwID0gTWF0aC5jZWlsKGNvbXBvbmVudC50Y3gwIC8gc2NhbGUpOwogICAgICAgIHN1YmJhbmQudGJ5MCA9IE1hdGguY2VpbChjb21wb25lbnQudGN5MCAvIHNjYWxlKTsKICAgICAgICBzdWJiYW5kLnRieDEgPSBNYXRoLmNlaWwoY29tcG9uZW50LnRjeDEgLyBzY2FsZSk7CiAgICAgICAgc3ViYmFuZC50YnkxID0gTWF0aC5jZWlsKGNvbXBvbmVudC50Y3kxIC8gc2NhbGUpOwogICAgICAgIHN1YmJhbmQucmVzb2x1dGlvbiA9IHJlc29sdXRpb247CiAgICAgICAgYnVpbGRDb2RlYmxvY2tzKGNvbnRleHQsIHN1YmJhbmQsIGJsb2Nrc0RpbWVuc2lvbnMpOwogICAgICAgIHN1YmJhbmRzLnB1c2goc3ViYmFuZCk7CiAgICAgICAgcmVzb2x1dGlvbi5zdWJiYW5kcyA9IFtzdWJiYW5kXTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBic2NhbGUgPSAxIDw8IGRlY29tcG9zaXRpb25MZXZlbHNDb3VudCAtIHIgKyAxOwogICAgICAgIGNvbnN0IHJlc29sdXRpb25TdWJiYW5kcyA9IFtdOwogICAgICAgIHN1YmJhbmQgPSB7fTsKICAgICAgICBzdWJiYW5kLnR5cGUgPSAiSEwiOwogICAgICAgIHN1YmJhbmQudGJ4MCA9IE1hdGguY2VpbChjb21wb25lbnQudGN4MCAvIGJzY2FsZSAtIDAuNSk7CiAgICAgICAgc3ViYmFuZC50YnkwID0gTWF0aC5jZWlsKGNvbXBvbmVudC50Y3kwIC8gYnNjYWxlKTsKICAgICAgICBzdWJiYW5kLnRieDEgPSBNYXRoLmNlaWwoY29tcG9uZW50LnRjeDEgLyBic2NhbGUgLSAwLjUpOwogICAgICAgIHN1YmJhbmQudGJ5MSA9IE1hdGguY2VpbChjb21wb25lbnQudGN5MSAvIGJzY2FsZSk7CiAgICAgICAgc3ViYmFuZC5yZXNvbHV0aW9uID0gcmVzb2x1dGlvbjsKICAgICAgICBidWlsZENvZGVibG9ja3MoY29udGV4dCwgc3ViYmFuZCwgYmxvY2tzRGltZW5zaW9ucyk7CiAgICAgICAgc3ViYmFuZHMucHVzaChzdWJiYW5kKTsKICAgICAgICByZXNvbHV0aW9uU3ViYmFuZHMucHVzaChzdWJiYW5kKTsKICAgICAgICBzdWJiYW5kID0ge307CiAgICAgICAgc3ViYmFuZC50eXBlID0gIkxIIjsKICAgICAgICBzdWJiYW5kLnRieDAgPSBNYXRoLmNlaWwoY29tcG9uZW50LnRjeDAgLyBic2NhbGUpOwogICAgICAgIHN1YmJhbmQudGJ5MCA9IE1hdGguY2VpbChjb21wb25lbnQudGN5MCAvIGJzY2FsZSAtIDAuNSk7CiAgICAgICAgc3ViYmFuZC50YngxID0gTWF0aC5jZWlsKGNvbXBvbmVudC50Y3gxIC8gYnNjYWxlKTsKICAgICAgICBzdWJiYW5kLnRieTEgPSBNYXRoLmNlaWwoY29tcG9uZW50LnRjeTEgLyBic2NhbGUgLSAwLjUpOwogICAgICAgIHN1YmJhbmQucmVzb2x1dGlvbiA9IHJlc29sdXRpb247CiAgICAgICAgYnVpbGRDb2RlYmxvY2tzKGNvbnRleHQsIHN1YmJhbmQsIGJsb2Nrc0RpbWVuc2lvbnMpOwogICAgICAgIHN1YmJhbmRzLnB1c2goc3ViYmFuZCk7CiAgICAgICAgcmVzb2x1dGlvblN1YmJhbmRzLnB1c2goc3ViYmFuZCk7CiAgICAgICAgc3ViYmFuZCA9IHt9OwogICAgICAgIHN1YmJhbmQudHlwZSA9ICJISCI7CiAgICAgICAgc3ViYmFuZC50YngwID0gTWF0aC5jZWlsKGNvbXBvbmVudC50Y3gwIC8gYnNjYWxlIC0gMC41KTsKICAgICAgICBzdWJiYW5kLnRieTAgPSBNYXRoLmNlaWwoY29tcG9uZW50LnRjeTAgLyBic2NhbGUgLSAwLjUpOwogICAgICAgIHN1YmJhbmQudGJ4MSA9IE1hdGguY2VpbChjb21wb25lbnQudGN4MSAvIGJzY2FsZSAtIDAuNSk7CiAgICAgICAgc3ViYmFuZC50YnkxID0gTWF0aC5jZWlsKGNvbXBvbmVudC50Y3kxIC8gYnNjYWxlIC0gMC41KTsKICAgICAgICBzdWJiYW5kLnJlc29sdXRpb24gPSByZXNvbHV0aW9uOwogICAgICAgIGJ1aWxkQ29kZWJsb2Nrcyhjb250ZXh0LCBzdWJiYW5kLCBibG9ja3NEaW1lbnNpb25zKTsKICAgICAgICBzdWJiYW5kcy5wdXNoKHN1YmJhbmQpOwogICAgICAgIHJlc29sdXRpb25TdWJiYW5kcy5wdXNoKHN1YmJhbmQpOwogICAgICAgIHJlc29sdXRpb24uc3ViYmFuZHMgPSByZXNvbHV0aW9uU3ViYmFuZHM7CiAgICAgIH0KICAgIH0KICAgIGNvbXBvbmVudC5yZXNvbHV0aW9ucyA9IHJlc29sdXRpb25zOwogICAgY29tcG9uZW50LnN1YmJhbmRzID0gc3ViYmFuZHM7CiAgfQogIGNvbnN0IHByb2dyZXNzaW9uT3JkZXIgPSB0aWxlLmNvZGluZ1N0eWxlRGVmYXVsdFBhcmFtZXRlcnMucHJvZ3Jlc3Npb25PcmRlcjsKICBzd2l0Y2ggKHByb2dyZXNzaW9uT3JkZXIpIHsKICAgIGNhc2UgMDoKICAgICAgdGlsZS5wYWNrZXRzSXRlcmF0b3IgPSBuZXcgTGF5ZXJSZXNvbHV0aW9uQ29tcG9uZW50UG9zaXRpb25JdGVyYXRvcihjb250ZXh0KTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDE6CiAgICAgIHRpbGUucGFja2V0c0l0ZXJhdG9yID0gbmV3IFJlc29sdXRpb25MYXllckNvbXBvbmVudFBvc2l0aW9uSXRlcmF0b3IoY29udGV4dCk7CiAgICAgIGJyZWFrOwogICAgY2FzZSAyOgogICAgICB0aWxlLnBhY2tldHNJdGVyYXRvciA9IG5ldyBSZXNvbHV0aW9uUG9zaXRpb25Db21wb25lbnRMYXllckl0ZXJhdG9yKGNvbnRleHQpOwogICAgICBicmVhazsKICAgIGNhc2UgMzoKICAgICAgdGlsZS5wYWNrZXRzSXRlcmF0b3IgPSBuZXcgUG9zaXRpb25Db21wb25lbnRSZXNvbHV0aW9uTGF5ZXJJdGVyYXRvcihjb250ZXh0KTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDQ6CiAgICAgIHRpbGUucGFja2V0c0l0ZXJhdG9yID0gbmV3IENvbXBvbmVudFBvc2l0aW9uUmVzb2x1dGlvbkxheWVySXRlcmF0b3IoY29udGV4dCk7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEpweEVycm9yKGBVbnN1cHBvcnRlZCBwcm9ncmVzc2lvbiBvcmRlciAke3Byb2dyZXNzaW9uT3JkZXJ9YCk7CiAgfQp9CmZ1bmN0aW9uIHBhcnNlVGlsZVBhY2tldHMoY29udGV4dCwgZGF0YSwgb2Zmc2V0LCBkYXRhTGVuZ3RoKSB7CiAgbGV0IHBvc2l0aW9uID0gMDsKICBsZXQgYnVmZmVyLAogICAgYnVmZmVyU2l6ZSA9IDAsCiAgICBza2lwTmV4dEJpdCA9IGZhbHNlOwogIGZ1bmN0aW9uIHJlYWRCaXRzKGNvdW50KSB7CiAgICB3aGlsZSAoYnVmZmVyU2l6ZSA8IGNvdW50KSB7CiAgICAgIGNvbnN0IGIgPSBkYXRhW29mZnNldCArIHBvc2l0aW9uXTsKICAgICAgcG9zaXRpb24rKzsKICAgICAgaWYgKHNraXBOZXh0Qml0KSB7CiAgICAgICAgYnVmZmVyID0gYnVmZmVyIDw8IDcgfCBiOwogICAgICAgIGJ1ZmZlclNpemUgKz0gNzsKICAgICAgICBza2lwTmV4dEJpdCA9IGZhbHNlOwogICAgICB9IGVsc2UgewogICAgICAgIGJ1ZmZlciA9IGJ1ZmZlciA8PCA4IHwgYjsKICAgICAgICBidWZmZXJTaXplICs9IDg7CiAgICAgIH0KICAgICAgaWYgKGIgPT09IDB4ZmYpIHsKICAgICAgICBza2lwTmV4dEJpdCA9IHRydWU7CiAgICAgIH0KICAgIH0KICAgIGJ1ZmZlclNpemUgLT0gY291bnQ7CiAgICByZXR1cm4gYnVmZmVyID4+PiBidWZmZXJTaXplICYgKDEgPDwgY291bnQpIC0gMTsKICB9CiAgZnVuY3Rpb24gc2tpcE1hcmtlcklmRXF1YWwodmFsdWUpIHsKICAgIGlmIChkYXRhW29mZnNldCArIHBvc2l0aW9uIC0gMV0gPT09IDB4ZmYgJiYgZGF0YVtvZmZzZXQgKyBwb3NpdGlvbl0gPT09IHZhbHVlKSB7CiAgICAgIHNraXBCeXRlcygxKTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9IGVsc2UgaWYgKGRhdGFbb2Zmc2V0ICsgcG9zaXRpb25dID09PSAweGZmICYmIGRhdGFbb2Zmc2V0ICsgcG9zaXRpb24gKyAxXSA9PT0gdmFsdWUpIHsKICAgICAgc2tpcEJ5dGVzKDIpOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9CiAgZnVuY3Rpb24gc2tpcEJ5dGVzKGNvdW50KSB7CiAgICBwb3NpdGlvbiArPSBjb3VudDsKICB9CiAgZnVuY3Rpb24gYWxpZ25Ub0J5dGUoKSB7CiAgICBidWZmZXJTaXplID0gMDsKICAgIGlmIChza2lwTmV4dEJpdCkgewogICAgICBwb3NpdGlvbisrOwogICAgICBza2lwTmV4dEJpdCA9IGZhbHNlOwogICAgfQogIH0KICBmdW5jdGlvbiByZWFkQ29kaW5ncGFzc2VzKCkgewogICAgaWYgKHJlYWRCaXRzKDEpID09PSAwKSB7CiAgICAgIHJldHVybiAxOwogICAgfQogICAgaWYgKHJlYWRCaXRzKDEpID09PSAwKSB7CiAgICAgIHJldHVybiAyOwogICAgfQogICAgbGV0IHZhbHVlID0gcmVhZEJpdHMoMik7CiAgICBpZiAodmFsdWUgPCAzKSB7CiAgICAgIHJldHVybiB2YWx1ZSArIDM7CiAgICB9CiAgICB2YWx1ZSA9IHJlYWRCaXRzKDUpOwogICAgaWYgKHZhbHVlIDwgMzEpIHsKICAgICAgcmV0dXJuIHZhbHVlICsgNjsKICAgIH0KICAgIHZhbHVlID0gcmVhZEJpdHMoNyk7CiAgICByZXR1cm4gdmFsdWUgKyAzNzsKICB9CiAgY29uc3QgdGlsZUluZGV4ID0gY29udGV4dC5jdXJyZW50VGlsZS5pbmRleDsKICBjb25zdCB0aWxlID0gY29udGV4dC50aWxlc1t0aWxlSW5kZXhdOwogIGNvbnN0IHNvcE1hcmtlclVzZWQgPSBjb250ZXh0LkNPRC5zb3BNYXJrZXJVc2VkOwogIGNvbnN0IGVwaE1hcmtlclVzZWQgPSBjb250ZXh0LkNPRC5lcGhNYXJrZXJVc2VkOwogIGNvbnN0IHBhY2tldHNJdGVyYXRvciA9IHRpbGUucGFja2V0c0l0ZXJhdG9yOwogIHdoaWxlIChwb3NpdGlvbiA8IGRhdGFMZW5ndGgpIHsKICAgIGFsaWduVG9CeXRlKCk7CiAgICBpZiAoc29wTWFya2VyVXNlZCAmJiBza2lwTWFya2VySWZFcXVhbCgweDkxKSkgewogICAgICBza2lwQnl0ZXMoNCk7CiAgICB9CiAgICBjb25zdCBwYWNrZXQgPSBwYWNrZXRzSXRlcmF0b3IubmV4dFBhY2tldCgpOwogICAgaWYgKCFyZWFkQml0cygxKSkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGNvbnN0IGxheWVyTnVtYmVyID0gcGFja2V0LmxheWVyTnVtYmVyLAogICAgICBxdWV1ZSA9IFtdOwogICAgbGV0IGNvZGVibG9jazsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHBhY2tldC5jb2RlYmxvY2tzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29kZWJsb2NrID0gcGFja2V0LmNvZGVibG9ja3NbaV07CiAgICAgIGxldCBwcmVjaW5jdCA9IGNvZGVibG9jay5wcmVjaW5jdDsKICAgICAgY29uc3QgY29kZWJsb2NrQ29sdW1uID0gY29kZWJsb2NrLmNieCAtIHByZWNpbmN0LmNieE1pbjsKICAgICAgY29uc3QgY29kZWJsb2NrUm93ID0gY29kZWJsb2NrLmNieSAtIHByZWNpbmN0LmNieU1pbjsKICAgICAgbGV0IGNvZGVibG9ja0luY2x1ZGVkID0gZmFsc2U7CiAgICAgIGxldCBmaXJzdFRpbWVJbmNsdXNpb24gPSBmYWxzZTsKICAgICAgbGV0IHZhbHVlUmVhZHksIHplcm9CaXRQbGFuZXNUcmVlOwogICAgICBpZiAoY29kZWJsb2NrLmluY2x1ZGVkICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBjb2RlYmxvY2tJbmNsdWRlZCA9ICEhcmVhZEJpdHMoMSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcHJlY2luY3QgPSBjb2RlYmxvY2sucHJlY2luY3Q7CiAgICAgICAgbGV0IGluY2x1c2lvblRyZWU7CiAgICAgICAgaWYgKHByZWNpbmN0LmluY2x1c2lvblRyZWUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgaW5jbHVzaW9uVHJlZSA9IHByZWNpbmN0LmluY2x1c2lvblRyZWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNvbnN0IHdpZHRoID0gcHJlY2luY3QuY2J4TWF4IC0gcHJlY2luY3QuY2J4TWluICsgMTsKICAgICAgICAgIGNvbnN0IGhlaWdodCA9IHByZWNpbmN0LmNieU1heCAtIHByZWNpbmN0LmNieU1pbiArIDE7CiAgICAgICAgICBpbmNsdXNpb25UcmVlID0gbmV3IEluY2x1c2lvblRyZWUod2lkdGgsIGhlaWdodCwgbGF5ZXJOdW1iZXIpOwogICAgICAgICAgemVyb0JpdFBsYW5lc1RyZWUgPSBuZXcgVGFnVHJlZSh3aWR0aCwgaGVpZ2h0KTsKICAgICAgICAgIHByZWNpbmN0LmluY2x1c2lvblRyZWUgPSBpbmNsdXNpb25UcmVlOwogICAgICAgICAgcHJlY2luY3QuemVyb0JpdFBsYW5lc1RyZWUgPSB6ZXJvQml0UGxhbmVzVHJlZTsKICAgICAgICAgIGZvciAobGV0IGwgPSAwOyBsIDwgbGF5ZXJOdW1iZXI7IGwrKykgewogICAgICAgICAgICBpZiAocmVhZEJpdHMoMSkgIT09IDApIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgSnB4RXJyb3IoIkludmFsaWQgdGFnIHRyZWUiKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoaW5jbHVzaW9uVHJlZS5yZXNldChjb2RlYmxvY2tDb2x1bW4sIGNvZGVibG9ja1JvdywgbGF5ZXJOdW1iZXIpKSB7CiAgICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgICBpZiAocmVhZEJpdHMoMSkpIHsKICAgICAgICAgICAgICB2YWx1ZVJlYWR5ID0gIWluY2x1c2lvblRyZWUubmV4dExldmVsKCk7CiAgICAgICAgICAgICAgaWYgKHZhbHVlUmVhZHkpIHsKICAgICAgICAgICAgICAgIGNvZGVibG9jay5pbmNsdWRlZCA9IHRydWU7CiAgICAgICAgICAgICAgICBjb2RlYmxvY2tJbmNsdWRlZCA9IGZpcnN0VGltZUluY2x1c2lvbiA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgaW5jbHVzaW9uVHJlZS5pbmNyZW1lbnRWYWx1ZShsYXllck51bWJlcik7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCFjb2RlYmxvY2tJbmNsdWRlZCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChmaXJzdFRpbWVJbmNsdXNpb24pIHsKICAgICAgICB6ZXJvQml0UGxhbmVzVHJlZSA9IHByZWNpbmN0Lnplcm9CaXRQbGFuZXNUcmVlOwogICAgICAgIHplcm9CaXRQbGFuZXNUcmVlLnJlc2V0KGNvZGVibG9ja0NvbHVtbiwgY29kZWJsb2NrUm93KTsKICAgICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgICAgaWYgKHJlYWRCaXRzKDEpKSB7CiAgICAgICAgICAgIHZhbHVlUmVhZHkgPSAhemVyb0JpdFBsYW5lc1RyZWUubmV4dExldmVsKCk7CiAgICAgICAgICAgIGlmICh2YWx1ZVJlYWR5KSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHplcm9CaXRQbGFuZXNUcmVlLmluY3JlbWVudFZhbHVlKCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvZGVibG9jay56ZXJvQml0UGxhbmVzID0gemVyb0JpdFBsYW5lc1RyZWUudmFsdWU7CiAgICAgIH0KICAgICAgY29uc3QgY29kaW5ncGFzc2VzID0gcmVhZENvZGluZ3Bhc3NlcygpOwogICAgICB3aGlsZSAocmVhZEJpdHMoMSkpIHsKICAgICAgICBjb2RlYmxvY2suTGJsb2NrKys7CiAgICAgIH0KICAgICAgY29uc3QgY29kaW5ncGFzc2VzTG9nMiA9ICgwLCBfY29yZV91dGlscy5sb2cyKShjb2RpbmdwYXNzZXMpOwogICAgICBjb25zdCBiaXRzID0gKGNvZGluZ3Bhc3NlcyA8IDEgPDwgY29kaW5ncGFzc2VzTG9nMiA/IGNvZGluZ3Bhc3Nlc0xvZzIgLSAxIDogY29kaW5ncGFzc2VzTG9nMikgKyBjb2RlYmxvY2suTGJsb2NrOwogICAgICBjb25zdCBjb2RlZERhdGFMZW5ndGggPSByZWFkQml0cyhiaXRzKTsKICAgICAgcXVldWUucHVzaCh7CiAgICAgICAgY29kZWJsb2NrLAogICAgICAgIGNvZGluZ3Bhc3NlcywKICAgICAgICBkYXRhTGVuZ3RoOiBjb2RlZERhdGFMZW5ndGgKICAgICAgfSk7CiAgICB9CiAgICBhbGlnblRvQnl0ZSgpOwogICAgaWYgKGVwaE1hcmtlclVzZWQpIHsKICAgICAgc2tpcE1hcmtlcklmRXF1YWwoMHg5Mik7CiAgICB9CiAgICB3aGlsZSAocXVldWUubGVuZ3RoID4gMCkgewogICAgICBjb25zdCBwYWNrZXRJdGVtID0gcXVldWUuc2hpZnQoKTsKICAgICAgY29kZWJsb2NrID0gcGFja2V0SXRlbS5jb2RlYmxvY2s7CiAgICAgIGlmIChjb2RlYmxvY2suZGF0YSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgY29kZWJsb2NrLmRhdGEgPSBbXTsKICAgICAgfQogICAgICBjb2RlYmxvY2suZGF0YS5wdXNoKHsKICAgICAgICBkYXRhLAogICAgICAgIHN0YXJ0OiBvZmZzZXQgKyBwb3NpdGlvbiwKICAgICAgICBlbmQ6IG9mZnNldCArIHBvc2l0aW9uICsgcGFja2V0SXRlbS5kYXRhTGVuZ3RoLAogICAgICAgIGNvZGluZ3Bhc3NlczogcGFja2V0SXRlbS5jb2RpbmdwYXNzZXMKICAgICAgfSk7CiAgICAgIHBvc2l0aW9uICs9IHBhY2tldEl0ZW0uZGF0YUxlbmd0aDsKICAgIH0KICB9CiAgcmV0dXJuIHBvc2l0aW9uOwp9CmZ1bmN0aW9uIGNvcHlDb2VmZmljaWVudHMoY29lZmZpY2llbnRzLCBsZXZlbFdpZHRoLCBsZXZlbEhlaWdodCwgc3ViYmFuZCwgZGVsdGEsIG1iLCByZXZlcnNpYmxlLCBzZWdtZW50YXRpb25TeW1ib2xVc2VkLCByZXNldENvbnRleHRQcm9iYWJpbGl0aWVzKSB7CiAgY29uc3QgeDAgPSBzdWJiYW5kLnRieDA7CiAgY29uc3QgeTAgPSBzdWJiYW5kLnRieTA7CiAgY29uc3Qgd2lkdGggPSBzdWJiYW5kLnRieDEgLSBzdWJiYW5kLnRieDA7CiAgY29uc3QgY29kZWJsb2NrcyA9IHN1YmJhbmQuY29kZWJsb2NrczsKICBjb25zdCByaWdodCA9IHN1YmJhbmQudHlwZS5jaGFyQXQoMCkgPT09ICJIIiA/IDEgOiAwOwogIGNvbnN0IGJvdHRvbSA9IHN1YmJhbmQudHlwZS5jaGFyQXQoMSkgPT09ICJIIiA/IGxldmVsV2lkdGggOiAwOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IGNvZGVibG9ja3MubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgY29uc3QgY29kZWJsb2NrID0gY29kZWJsb2Nrc1tpXTsKICAgIGNvbnN0IGJsb2NrV2lkdGggPSBjb2RlYmxvY2sudGJ4MV8gLSBjb2RlYmxvY2sudGJ4MF87CiAgICBjb25zdCBibG9ja0hlaWdodCA9IGNvZGVibG9jay50YnkxXyAtIGNvZGVibG9jay50YnkwXzsKICAgIGlmIChibG9ja1dpZHRoID09PSAwIHx8IGJsb2NrSGVpZ2h0ID09PSAwKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgaWYgKGNvZGVibG9jay5kYXRhID09PSB1bmRlZmluZWQpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBjb25zdCBiaXRNb2RlbCA9IG5ldyBCaXRNb2RlbChibG9ja1dpZHRoLCBibG9ja0hlaWdodCwgY29kZWJsb2NrLnN1YmJhbmRUeXBlLCBjb2RlYmxvY2suemVyb0JpdFBsYW5lcywgbWIpOwogICAgbGV0IGN1cnJlbnRDb2RpbmdwYXNzVHlwZSA9IDI7CiAgICBjb25zdCBkYXRhID0gY29kZWJsb2NrLmRhdGE7CiAgICBsZXQgdG90YWxMZW5ndGggPSAwLAogICAgICBjb2RpbmdwYXNzZXMgPSAwOwogICAgbGV0IGosIGpqLCBkYXRhSXRlbTsKICAgIGZvciAoaiA9IDAsIGpqID0gZGF0YS5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgIGRhdGFJdGVtID0gZGF0YVtqXTsKICAgICAgdG90YWxMZW5ndGggKz0gZGF0YUl0ZW0uZW5kIC0gZGF0YUl0ZW0uc3RhcnQ7CiAgICAgIGNvZGluZ3Bhc3NlcyArPSBkYXRhSXRlbS5jb2RpbmdwYXNzZXM7CiAgICB9CiAgICBjb25zdCBlbmNvZGVkRGF0YSA9IG5ldyBVaW50OEFycmF5KHRvdGFsTGVuZ3RoKTsKICAgIGxldCBwb3NpdGlvbiA9IDA7CiAgICBmb3IgKGogPSAwLCBqaiA9IGRhdGEubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICBkYXRhSXRlbSA9IGRhdGFbal07CiAgICAgIGNvbnN0IGNodW5rID0gZGF0YUl0ZW0uZGF0YS5zdWJhcnJheShkYXRhSXRlbS5zdGFydCwgZGF0YUl0ZW0uZW5kKTsKICAgICAgZW5jb2RlZERhdGEuc2V0KGNodW5rLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IGNodW5rLmxlbmd0aDsKICAgIH0KICAgIGNvbnN0IGRlY29kZXIgPSBuZXcgX2FyaXRobWV0aWNfZGVjb2Rlci5Bcml0aG1ldGljRGVjb2RlcihlbmNvZGVkRGF0YSwgMCwgdG90YWxMZW5ndGgpOwogICAgYml0TW9kZWwuc2V0RGVjb2RlcihkZWNvZGVyKTsKICAgIGZvciAoaiA9IDA7IGogPCBjb2RpbmdwYXNzZXM7IGorKykgewogICAgICBzd2l0Y2ggKGN1cnJlbnRDb2RpbmdwYXNzVHlwZSkgewogICAgICAgIGNhc2UgMDoKICAgICAgICAgIGJpdE1vZGVsLnJ1blNpZ25pZmljYW5jZVByb3BhZ2F0aW9uUGFzcygpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxOgogICAgICAgICAgYml0TW9kZWwucnVuTWFnbml0dWRlUmVmaW5lbWVudFBhc3MoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjoKICAgICAgICAgIGJpdE1vZGVsLnJ1bkNsZWFudXBQYXNzKCk7CiAgICAgICAgICBpZiAoc2VnbWVudGF0aW9uU3ltYm9sVXNlZCkgewogICAgICAgICAgICBiaXRNb2RlbC5jaGVja1NlZ21lbnRhdGlvblN5bWJvbCgpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKHJlc2V0Q29udGV4dFByb2JhYmlsaXRpZXMpIHsKICAgICAgICBiaXRNb2RlbC5yZXNldCgpOwogICAgICB9CiAgICAgIGN1cnJlbnRDb2RpbmdwYXNzVHlwZSA9IChjdXJyZW50Q29kaW5ncGFzc1R5cGUgKyAxKSAlIDM7CiAgICB9CiAgICBsZXQgb2Zmc2V0ID0gY29kZWJsb2NrLnRieDBfIC0geDAgKyAoY29kZWJsb2NrLnRieTBfIC0geTApICogd2lkdGg7CiAgICBjb25zdCBzaWduID0gYml0TW9kZWwuY29lZmZpY2VudHNTaWduOwogICAgY29uc3QgbWFnbml0dWRlID0gYml0TW9kZWwuY29lZmZpY2VudHNNYWduaXR1ZGU7CiAgICBjb25zdCBiaXRzRGVjb2RlZCA9IGJpdE1vZGVsLmJpdHNEZWNvZGVkOwogICAgY29uc3QgbWFnbml0dWRlQ29ycmVjdGlvbiA9IHJldmVyc2libGUgPyAwIDogMC41OwogICAgbGV0IGssIG4sIG5iOwogICAgcG9zaXRpb24gPSAwOwogICAgY29uc3QgaW50ZXJsZWF2ZSA9IHN1YmJhbmQudHlwZSAhPT0gIkxMIjsKICAgIGZvciAoaiA9IDA7IGogPCBibG9ja0hlaWdodDsgaisrKSB7CiAgICAgIGNvbnN0IHJvdyA9IG9mZnNldCAvIHdpZHRoIHwgMDsKICAgICAgY29uc3QgbGV2ZWxPZmZzZXQgPSAyICogcm93ICogKGxldmVsV2lkdGggLSB3aWR0aCkgKyByaWdodCArIGJvdHRvbTsKICAgICAgZm9yIChrID0gMDsgayA8IGJsb2NrV2lkdGg7IGsrKykgewogICAgICAgIG4gPSBtYWduaXR1ZGVbcG9zaXRpb25dOwogICAgICAgIGlmIChuICE9PSAwKSB7CiAgICAgICAgICBuID0gKG4gKyBtYWduaXR1ZGVDb3JyZWN0aW9uKSAqIGRlbHRhOwogICAgICAgICAgaWYgKHNpZ25bcG9zaXRpb25dICE9PSAwKSB7CiAgICAgICAgICAgIG4gPSAtbjsKICAgICAgICAgIH0KICAgICAgICAgIG5iID0gYml0c0RlY29kZWRbcG9zaXRpb25dOwogICAgICAgICAgY29uc3QgcG9zID0gaW50ZXJsZWF2ZSA/IGxldmVsT2Zmc2V0ICsgKG9mZnNldCA8PCAxKSA6IG9mZnNldDsKICAgICAgICAgIGlmIChyZXZlcnNpYmxlICYmIG5iID49IG1iKSB7CiAgICAgICAgICAgIGNvZWZmaWNpZW50c1twb3NdID0gbjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGNvZWZmaWNpZW50c1twb3NdID0gbiAqICgxIDw8IG1iIC0gbmIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBvZmZzZXQrKzsKICAgICAgICBwb3NpdGlvbisrOwogICAgICB9CiAgICAgIG9mZnNldCArPSB3aWR0aCAtIGJsb2NrV2lkdGg7CiAgICB9CiAgfQp9CmZ1bmN0aW9uIHRyYW5zZm9ybVRpbGUoY29udGV4dCwgdGlsZSwgYykgewogIGNvbnN0IGNvbXBvbmVudCA9IHRpbGUuY29tcG9uZW50c1tjXTsKICBjb25zdCBjb2RpbmdTdHlsZVBhcmFtZXRlcnMgPSBjb21wb25lbnQuY29kaW5nU3R5bGVQYXJhbWV0ZXJzOwogIGNvbnN0IHF1YW50aXphdGlvblBhcmFtZXRlcnMgPSBjb21wb25lbnQucXVhbnRpemF0aW9uUGFyYW1ldGVyczsKICBjb25zdCBkZWNvbXBvc2l0aW9uTGV2ZWxzQ291bnQgPSBjb2RpbmdTdHlsZVBhcmFtZXRlcnMuZGVjb21wb3NpdGlvbkxldmVsc0NvdW50OwogIGNvbnN0IHNwcWNkcyA9IHF1YW50aXphdGlvblBhcmFtZXRlcnMuU1BxY2RzOwogIGNvbnN0IHNjYWxhckV4cG91bmRlZCA9IHF1YW50aXphdGlvblBhcmFtZXRlcnMuc2NhbGFyRXhwb3VuZGVkOwogIGNvbnN0IGd1YXJkQml0cyA9IHF1YW50aXphdGlvblBhcmFtZXRlcnMuZ3VhcmRCaXRzOwogIGNvbnN0IHNlZ21lbnRhdGlvblN5bWJvbFVzZWQgPSBjb2RpbmdTdHlsZVBhcmFtZXRlcnMuc2VnbWVudGF0aW9uU3ltYm9sVXNlZDsKICBjb25zdCByZXNldENvbnRleHRQcm9iYWJpbGl0aWVzID0gY29kaW5nU3R5bGVQYXJhbWV0ZXJzLnJlc2V0Q29udGV4dFByb2JhYmlsaXRpZXM7CiAgY29uc3QgcHJlY2lzaW9uID0gY29udGV4dC5jb21wb25lbnRzW2NdLnByZWNpc2lvbjsKICBjb25zdCByZXZlcnNpYmxlID0gY29kaW5nU3R5bGVQYXJhbWV0ZXJzLnJldmVyc2libGVUcmFuc2Zvcm1hdGlvbjsKICBjb25zdCB0cmFuc2Zvcm0gPSByZXZlcnNpYmxlID8gbmV3IFJldmVyc2libGVUcmFuc2Zvcm0oKSA6IG5ldyBJcnJldmVyc2libGVUcmFuc2Zvcm0oKTsKICBjb25zdCBzdWJiYW5kQ29lZmZpY2llbnRzID0gW107CiAgbGV0IGIgPSAwOwogIGZvciAobGV0IGkgPSAwOyBpIDw9IGRlY29tcG9zaXRpb25MZXZlbHNDb3VudDsgaSsrKSB7CiAgICBjb25zdCByZXNvbHV0aW9uID0gY29tcG9uZW50LnJlc29sdXRpb25zW2ldOwogICAgY29uc3Qgd2lkdGggPSByZXNvbHV0aW9uLnRyeDEgLSByZXNvbHV0aW9uLnRyeDA7CiAgICBjb25zdCBoZWlnaHQgPSByZXNvbHV0aW9uLnRyeTEgLSByZXNvbHV0aW9uLnRyeTA7CiAgICBjb25zdCBjb2VmZmljaWVudHMgPSBuZXcgRmxvYXQzMkFycmF5KHdpZHRoICogaGVpZ2h0KTsKICAgIGZvciAobGV0IGogPSAwLCBqaiA9IHJlc29sdXRpb24uc3ViYmFuZHMubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICBsZXQgbXUsIGVwc2lsb247CiAgICAgIGlmICghc2NhbGFyRXhwb3VuZGVkKSB7CiAgICAgICAgbXUgPSBzcHFjZHNbMF0ubXU7CiAgICAgICAgZXBzaWxvbiA9IHNwcWNkc1swXS5lcHNpbG9uICsgKGkgPiAwID8gMSAtIGkgOiAwKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBtdSA9IHNwcWNkc1tiXS5tdTsKICAgICAgICBlcHNpbG9uID0gc3BxY2RzW2JdLmVwc2lsb247CiAgICAgICAgYisrOwogICAgICB9CiAgICAgIGNvbnN0IHN1YmJhbmQgPSByZXNvbHV0aW9uLnN1YmJhbmRzW2pdOwogICAgICBjb25zdCBnYWluTG9nMiA9IFN1YmJhbmRzR2FpbkxvZzJbc3ViYmFuZC50eXBlXTsKICAgICAgY29uc3QgZGVsdGEgPSByZXZlcnNpYmxlID8gMSA6IDIgKiogKHByZWNpc2lvbiArIGdhaW5Mb2cyIC0gZXBzaWxvbikgKiAoMSArIG11IC8gMjA0OCk7CiAgICAgIGNvbnN0IG1iID0gZ3VhcmRCaXRzICsgZXBzaWxvbiAtIDE7CiAgICAgIGNvcHlDb2VmZmljaWVudHMoY29lZmZpY2llbnRzLCB3aWR0aCwgaGVpZ2h0LCBzdWJiYW5kLCBkZWx0YSwgbWIsIHJldmVyc2libGUsIHNlZ21lbnRhdGlvblN5bWJvbFVzZWQsIHJlc2V0Q29udGV4dFByb2JhYmlsaXRpZXMpOwogICAgfQogICAgc3ViYmFuZENvZWZmaWNpZW50cy5wdXNoKHsKICAgICAgd2lkdGgsCiAgICAgIGhlaWdodCwKICAgICAgaXRlbXM6IGNvZWZmaWNpZW50cwogICAgfSk7CiAgfQogIGNvbnN0IHJlc3VsdCA9IHRyYW5zZm9ybS5jYWxjdWxhdGUoc3ViYmFuZENvZWZmaWNpZW50cywgY29tcG9uZW50LnRjeDAsIGNvbXBvbmVudC50Y3kwKTsKICByZXR1cm4gewogICAgbGVmdDogY29tcG9uZW50LnRjeDAsCiAgICB0b3A6IGNvbXBvbmVudC50Y3kwLAogICAgd2lkdGg6IHJlc3VsdC53aWR0aCwKICAgIGhlaWdodDogcmVzdWx0LmhlaWdodCwKICAgIGl0ZW1zOiByZXN1bHQuaXRlbXMKICB9Owp9CmZ1bmN0aW9uIHRyYW5zZm9ybUNvbXBvbmVudHMoY29udGV4dCkgewogIGNvbnN0IHNpeiA9IGNvbnRleHQuU0laOwogIGNvbnN0IGNvbXBvbmVudHMgPSBjb250ZXh0LmNvbXBvbmVudHM7CiAgY29uc3QgY29tcG9uZW50c0NvdW50ID0gc2l6LkNzaXo7CiAgY29uc3QgcmVzdWx0SW1hZ2VzID0gW107CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gY29udGV4dC50aWxlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCB0aWxlID0gY29udGV4dC50aWxlc1tpXTsKICAgIGNvbnN0IHRyYW5zZm9ybWVkVGlsZXMgPSBbXTsKICAgIGZvciAobGV0IGMgPSAwOyBjIDwgY29tcG9uZW50c0NvdW50OyBjKyspIHsKICAgICAgdHJhbnNmb3JtZWRUaWxlc1tjXSA9IHRyYW5zZm9ybVRpbGUoY29udGV4dCwgdGlsZSwgYyk7CiAgICB9CiAgICBjb25zdCB0aWxlMCA9IHRyYW5zZm9ybWVkVGlsZXNbMF07CiAgICBjb25zdCBvdXQgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkodGlsZTAuaXRlbXMubGVuZ3RoICogY29tcG9uZW50c0NvdW50KTsKICAgIGNvbnN0IHJlc3VsdCA9IHsKICAgICAgbGVmdDogdGlsZTAubGVmdCwKICAgICAgdG9wOiB0aWxlMC50b3AsCiAgICAgIHdpZHRoOiB0aWxlMC53aWR0aCwKICAgICAgaGVpZ2h0OiB0aWxlMC5oZWlnaHQsCiAgICAgIGl0ZW1zOiBvdXQKICAgIH07CiAgICBsZXQgc2hpZnQsIG9mZnNldDsKICAgIGxldCBwb3MgPSAwLAogICAgICBqLAogICAgICBqaiwKICAgICAgeTAsCiAgICAgIHkxLAogICAgICB5MjsKICAgIGlmICh0aWxlLmNvZGluZ1N0eWxlRGVmYXVsdFBhcmFtZXRlcnMubXVsdGlwbGVDb21wb25lbnRUcmFuc2Zvcm0pIHsKICAgICAgY29uc3QgZm91ckNvbXBvbmVudHMgPSBjb21wb25lbnRzQ291bnQgPT09IDQ7CiAgICAgIGNvbnN0IHkwaXRlbXMgPSB0cmFuc2Zvcm1lZFRpbGVzWzBdLml0ZW1zOwogICAgICBjb25zdCB5MWl0ZW1zID0gdHJhbnNmb3JtZWRUaWxlc1sxXS5pdGVtczsKICAgICAgY29uc3QgeTJpdGVtcyA9IHRyYW5zZm9ybWVkVGlsZXNbMl0uaXRlbXM7CiAgICAgIGNvbnN0IHkzaXRlbXMgPSBmb3VyQ29tcG9uZW50cyA/IHRyYW5zZm9ybWVkVGlsZXNbM10uaXRlbXMgOiBudWxsOwogICAgICBzaGlmdCA9IGNvbXBvbmVudHNbMF0ucHJlY2lzaW9uIC0gODsKICAgICAgb2Zmc2V0ID0gKDEyOCA8PCBzaGlmdCkgKyAwLjU7CiAgICAgIGNvbnN0IGNvbXBvbmVudDAgPSB0aWxlLmNvbXBvbmVudHNbMF07CiAgICAgIGNvbnN0IGFscGhhMDEgPSBjb21wb25lbnRzQ291bnQgLSAzOwogICAgICBqaiA9IHkwaXRlbXMubGVuZ3RoOwogICAgICBpZiAoIWNvbXBvbmVudDAuY29kaW5nU3R5bGVQYXJhbWV0ZXJzLnJldmVyc2libGVUcmFuc2Zvcm1hdGlvbikgewogICAgICAgIGZvciAoaiA9IDA7IGogPCBqajsgaisrLCBwb3MgKz0gYWxwaGEwMSkgewogICAgICAgICAgeTAgPSB5MGl0ZW1zW2pdICsgb2Zmc2V0OwogICAgICAgICAgeTEgPSB5MWl0ZW1zW2pdOwogICAgICAgICAgeTIgPSB5Mml0ZW1zW2pdOwogICAgICAgICAgb3V0W3BvcysrXSA9IHkwICsgMS40MDIgKiB5MiA+PiBzaGlmdDsKICAgICAgICAgIG91dFtwb3MrK10gPSB5MCAtIDAuMzQ0MTMgKiB5MSAtIDAuNzE0MTQgKiB5MiA+PiBzaGlmdDsKICAgICAgICAgIG91dFtwb3MrK10gPSB5MCArIDEuNzcyICogeTEgPj4gc2hpZnQ7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGZvciAoaiA9IDA7IGogPCBqajsgaisrLCBwb3MgKz0gYWxwaGEwMSkgewogICAgICAgICAgeTAgPSB5MGl0ZW1zW2pdICsgb2Zmc2V0OwogICAgICAgICAgeTEgPSB5MWl0ZW1zW2pdOwogICAgICAgICAgeTIgPSB5Mml0ZW1zW2pdOwogICAgICAgICAgY29uc3QgZyA9IHkwIC0gKHkyICsgeTEgPj4gMik7CiAgICAgICAgICBvdXRbcG9zKytdID0gZyArIHkyID4+IHNoaWZ0OwogICAgICAgICAgb3V0W3BvcysrXSA9IGcgPj4gc2hpZnQ7CiAgICAgICAgICBvdXRbcG9zKytdID0gZyArIHkxID4+IHNoaWZ0OwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoZm91ckNvbXBvbmVudHMpIHsKICAgICAgICBmb3IgKGogPSAwLCBwb3MgPSAzOyBqIDwgamo7IGorKywgcG9zICs9IDQpIHsKICAgICAgICAgIG91dFtwb3NdID0geTNpdGVtc1tqXSArIG9mZnNldCA+PiBzaGlmdDsKICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGZvciAobGV0IGMgPSAwOyBjIDwgY29tcG9uZW50c0NvdW50OyBjKyspIHsKICAgICAgICBjb25zdCBpdGVtcyA9IHRyYW5zZm9ybWVkVGlsZXNbY10uaXRlbXM7CiAgICAgICAgc2hpZnQgPSBjb21wb25lbnRzW2NdLnByZWNpc2lvbiAtIDg7CiAgICAgICAgb2Zmc2V0ID0gKDEyOCA8PCBzaGlmdCkgKyAwLjU7CiAgICAgICAgZm9yIChwb3MgPSBjLCBqID0gMCwgamogPSBpdGVtcy5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgICAgICBvdXRbcG9zXSA9IGl0ZW1zW2pdICsgb2Zmc2V0ID4+IHNoaWZ0OwogICAgICAgICAgcG9zICs9IGNvbXBvbmVudHNDb3VudDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJlc3VsdEltYWdlcy5wdXNoKHJlc3VsdCk7CiAgfQogIHJldHVybiByZXN1bHRJbWFnZXM7Cn0KZnVuY3Rpb24gaW5pdGlhbGl6ZVRpbGUoY29udGV4dCwgdGlsZUluZGV4KSB7CiAgY29uc3Qgc2l6ID0gY29udGV4dC5TSVo7CiAgY29uc3QgY29tcG9uZW50c0NvdW50ID0gc2l6LkNzaXo7CiAgY29uc3QgdGlsZSA9IGNvbnRleHQudGlsZXNbdGlsZUluZGV4XTsKICBmb3IgKGxldCBjID0gMDsgYyA8IGNvbXBvbmVudHNDb3VudDsgYysrKSB7CiAgICBjb25zdCBjb21wb25lbnQgPSB0aWxlLmNvbXBvbmVudHNbY107CiAgICBjb25zdCBxY2RPclFjYyA9IGNvbnRleHQuY3VycmVudFRpbGUuUUNDW2NdICE9PSB1bmRlZmluZWQgPyBjb250ZXh0LmN1cnJlbnRUaWxlLlFDQ1tjXSA6IGNvbnRleHQuY3VycmVudFRpbGUuUUNEOwogICAgY29tcG9uZW50LnF1YW50aXphdGlvblBhcmFtZXRlcnMgPSBxY2RPclFjYzsKICAgIGNvbnN0IGNvZE9yQ29jID0gY29udGV4dC5jdXJyZW50VGlsZS5DT0NbY10gIT09IHVuZGVmaW5lZCA/IGNvbnRleHQuY3VycmVudFRpbGUuQ09DW2NdIDogY29udGV4dC5jdXJyZW50VGlsZS5DT0Q7CiAgICBjb21wb25lbnQuY29kaW5nU3R5bGVQYXJhbWV0ZXJzID0gY29kT3JDb2M7CiAgfQogIHRpbGUuY29kaW5nU3R5bGVEZWZhdWx0UGFyYW1ldGVycyA9IGNvbnRleHQuY3VycmVudFRpbGUuQ09EOwp9CmNsYXNzIFRhZ1RyZWUgewogIGNvbnN0cnVjdG9yKHdpZHRoLCBoZWlnaHQpIHsKICAgIGNvbnN0IGxldmVsc0xlbmd0aCA9ICgwLCBfY29yZV91dGlscy5sb2cyKShNYXRoLm1heCh3aWR0aCwgaGVpZ2h0KSkgKyAxOwogICAgdGhpcy5sZXZlbHMgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGV2ZWxzTGVuZ3RoOyBpKyspIHsKICAgICAgY29uc3QgbGV2ZWwgPSB7CiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0LAogICAgICAgIGl0ZW1zOiBbXQogICAgICB9OwogICAgICB0aGlzLmxldmVscy5wdXNoKGxldmVsKTsKICAgICAgd2lkdGggPSBNYXRoLmNlaWwod2lkdGggLyAyKTsKICAgICAgaGVpZ2h0ID0gTWF0aC5jZWlsKGhlaWdodCAvIDIpOwogICAgfQogIH0KICByZXNldChpLCBqKSB7CiAgICBsZXQgY3VycmVudExldmVsID0gMCwKICAgICAgdmFsdWUgPSAwLAogICAgICBsZXZlbDsKICAgIHdoaWxlIChjdXJyZW50TGV2ZWwgPCB0aGlzLmxldmVscy5sZW5ndGgpIHsKICAgICAgbGV2ZWwgPSB0aGlzLmxldmVsc1tjdXJyZW50TGV2ZWxdOwogICAgICBjb25zdCBpbmRleCA9IGkgKyBqICogbGV2ZWwud2lkdGg7CiAgICAgIGlmIChsZXZlbC5pdGVtc1tpbmRleF0gIT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhbHVlID0gbGV2ZWwuaXRlbXNbaW5kZXhdOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGxldmVsLmluZGV4ID0gaW5kZXg7CiAgICAgIGkgPj49IDE7CiAgICAgIGogPj49IDE7CiAgICAgIGN1cnJlbnRMZXZlbCsrOwogICAgfQogICAgY3VycmVudExldmVsLS07CiAgICBsZXZlbCA9IHRoaXMubGV2ZWxzW2N1cnJlbnRMZXZlbF07CiAgICBsZXZlbC5pdGVtc1tsZXZlbC5pbmRleF0gPSB2YWx1ZTsKICAgIHRoaXMuY3VycmVudExldmVsID0gY3VycmVudExldmVsOwogICAgZGVsZXRlIHRoaXMudmFsdWU7CiAgfQogIGluY3JlbWVudFZhbHVlKCkgewogICAgY29uc3QgbGV2ZWwgPSB0aGlzLmxldmVsc1t0aGlzLmN1cnJlbnRMZXZlbF07CiAgICBsZXZlbC5pdGVtc1tsZXZlbC5pbmRleF0rKzsKICB9CiAgbmV4dExldmVsKCkgewogICAgbGV0IGN1cnJlbnRMZXZlbCA9IHRoaXMuY3VycmVudExldmVsOwogICAgbGV0IGxldmVsID0gdGhpcy5sZXZlbHNbY3VycmVudExldmVsXTsKICAgIGNvbnN0IHZhbHVlID0gbGV2ZWwuaXRlbXNbbGV2ZWwuaW5kZXhdOwogICAgY3VycmVudExldmVsLS07CiAgICBpZiAoY3VycmVudExldmVsIDwgMCkgewogICAgICB0aGlzLnZhbHVlID0gdmFsdWU7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHRoaXMuY3VycmVudExldmVsID0gY3VycmVudExldmVsOwogICAgbGV2ZWwgPSB0aGlzLmxldmVsc1tjdXJyZW50TGV2ZWxdOwogICAgbGV2ZWwuaXRlbXNbbGV2ZWwuaW5kZXhdID0gdmFsdWU7CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KY2xhc3MgSW5jbHVzaW9uVHJlZSB7CiAgY29uc3RydWN0b3Iod2lkdGgsIGhlaWdodCwgZGVmYXVsdFZhbHVlKSB7CiAgICBjb25zdCBsZXZlbHNMZW5ndGggPSAoMCwgX2NvcmVfdXRpbHMubG9nMikoTWF0aC5tYXgod2lkdGgsIGhlaWdodCkpICsgMTsKICAgIHRoaXMubGV2ZWxzID0gW107CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxldmVsc0xlbmd0aDsgaSsrKSB7CiAgICAgIGNvbnN0IGl0ZW1zID0gbmV3IFVpbnQ4QXJyYXkod2lkdGggKiBoZWlnaHQpOwogICAgICBmb3IgKGxldCBqID0gMCwgamogPSBpdGVtcy5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgICAgaXRlbXNbal0gPSBkZWZhdWx0VmFsdWU7CiAgICAgIH0KICAgICAgY29uc3QgbGV2ZWwgPSB7CiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0LAogICAgICAgIGl0ZW1zCiAgICAgIH07CiAgICAgIHRoaXMubGV2ZWxzLnB1c2gobGV2ZWwpOwogICAgICB3aWR0aCA9IE1hdGguY2VpbCh3aWR0aCAvIDIpOwogICAgICBoZWlnaHQgPSBNYXRoLmNlaWwoaGVpZ2h0IC8gMik7CiAgICB9CiAgfQogIHJlc2V0KGksIGosIHN0b3BWYWx1ZSkgewogICAgbGV0IGN1cnJlbnRMZXZlbCA9IDA7CiAgICB3aGlsZSAoY3VycmVudExldmVsIDwgdGhpcy5sZXZlbHMubGVuZ3RoKSB7CiAgICAgIGNvbnN0IGxldmVsID0gdGhpcy5sZXZlbHNbY3VycmVudExldmVsXTsKICAgICAgY29uc3QgaW5kZXggPSBpICsgaiAqIGxldmVsLndpZHRoOwogICAgICBsZXZlbC5pbmRleCA9IGluZGV4OwogICAgICBjb25zdCB2YWx1ZSA9IGxldmVsLml0ZW1zW2luZGV4XTsKICAgICAgaWYgKHZhbHVlID09PSAweGZmKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKHZhbHVlID4gc3RvcFZhbHVlKSB7CiAgICAgICAgdGhpcy5jdXJyZW50TGV2ZWwgPSBjdXJyZW50TGV2ZWw7CiAgICAgICAgdGhpcy5wcm9wYWdhdGVWYWx1ZXMoKTsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgaSA+Pj0gMTsKICAgICAgaiA+Pj0gMTsKICAgICAgY3VycmVudExldmVsKys7CiAgICB9CiAgICB0aGlzLmN1cnJlbnRMZXZlbCA9IGN1cnJlbnRMZXZlbCAtIDE7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgaW5jcmVtZW50VmFsdWUoc3RvcFZhbHVlKSB7CiAgICBjb25zdCBsZXZlbCA9IHRoaXMubGV2ZWxzW3RoaXMuY3VycmVudExldmVsXTsKICAgIGxldmVsLml0ZW1zW2xldmVsLmluZGV4XSA9IHN0b3BWYWx1ZSArIDE7CiAgICB0aGlzLnByb3BhZ2F0ZVZhbHVlcygpOwogIH0KICBwcm9wYWdhdGVWYWx1ZXMoKSB7CiAgICBsZXQgbGV2ZWxJbmRleCA9IHRoaXMuY3VycmVudExldmVsOwogICAgbGV0IGxldmVsID0gdGhpcy5sZXZlbHNbbGV2ZWxJbmRleF07CiAgICBjb25zdCBjdXJyZW50VmFsdWUgPSBsZXZlbC5pdGVtc1tsZXZlbC5pbmRleF07CiAgICB3aGlsZSAoLS1sZXZlbEluZGV4ID49IDApIHsKICAgICAgbGV2ZWwgPSB0aGlzLmxldmVsc1tsZXZlbEluZGV4XTsKICAgICAgbGV2ZWwuaXRlbXNbbGV2ZWwuaW5kZXhdID0gY3VycmVudFZhbHVlOwogICAgfQogIH0KICBuZXh0TGV2ZWwoKSB7CiAgICBsZXQgY3VycmVudExldmVsID0gdGhpcy5jdXJyZW50TGV2ZWw7CiAgICBsZXQgbGV2ZWwgPSB0aGlzLmxldmVsc1tjdXJyZW50TGV2ZWxdOwogICAgY29uc3QgdmFsdWUgPSBsZXZlbC5pdGVtc1tsZXZlbC5pbmRleF07CiAgICBsZXZlbC5pdGVtc1tsZXZlbC5pbmRleF0gPSAweGZmOwogICAgY3VycmVudExldmVsLS07CiAgICBpZiAoY3VycmVudExldmVsIDwgMCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICB0aGlzLmN1cnJlbnRMZXZlbCA9IGN1cnJlbnRMZXZlbDsKICAgIGxldmVsID0gdGhpcy5sZXZlbHNbY3VycmVudExldmVsXTsKICAgIGxldmVsLml0ZW1zW2xldmVsLmluZGV4XSA9IHZhbHVlOwogICAgcmV0dXJuIHRydWU7CiAgfQp9CmNvbnN0IEJpdE1vZGVsID0gZnVuY3Rpb24gQml0TW9kZWxDbG9zdXJlKCkgewogIGNvbnN0IFVOSUZPUk1fQ09OVEVYVCA9IDE3OwogIGNvbnN0IFJVTkxFTkdUSF9DT05URVhUID0gMTg7CiAgY29uc3QgTExBbmRMSENvbnRleHRzTGFiZWwgPSBuZXcgVWludDhBcnJheShbMCwgNSwgOCwgMCwgMywgNywgOCwgMCwgNCwgNywgOCwgMCwgMCwgMCwgMCwgMCwgMSwgNiwgOCwgMCwgMywgNywgOCwgMCwgNCwgNywgOCwgMCwgMCwgMCwgMCwgMCwgMiwgNiwgOCwgMCwgMywgNywgOCwgMCwgNCwgNywgOCwgMCwgMCwgMCwgMCwgMCwgMiwgNiwgOCwgMCwgMywgNywgOCwgMCwgNCwgNywgOCwgMCwgMCwgMCwgMCwgMCwgMiwgNiwgOCwgMCwgMywgNywgOCwgMCwgNCwgNywgOF0pOwogIGNvbnN0IEhMQ29udGV4dExhYmVsID0gbmV3IFVpbnQ4QXJyYXkoWzAsIDMsIDQsIDAsIDUsIDcsIDcsIDAsIDgsIDgsIDgsIDAsIDAsIDAsIDAsIDAsIDEsIDMsIDQsIDAsIDYsIDcsIDcsIDAsIDgsIDgsIDgsIDAsIDAsIDAsIDAsIDAsIDIsIDMsIDQsIDAsIDYsIDcsIDcsIDAsIDgsIDgsIDgsIDAsIDAsIDAsIDAsIDAsIDIsIDMsIDQsIDAsIDYsIDcsIDcsIDAsIDgsIDgsIDgsIDAsIDAsIDAsIDAsIDAsIDIsIDMsIDQsIDAsIDYsIDcsIDcsIDAsIDgsIDgsIDhdKTsKICBjb25zdCBISENvbnRleHRMYWJlbCA9IG5ldyBVaW50OEFycmF5KFswLCAxLCAyLCAwLCAxLCAyLCAyLCAwLCAyLCAyLCAyLCAwLCAwLCAwLCAwLCAwLCAzLCA0LCA1LCAwLCA0LCA1LCA1LCAwLCA1LCA1LCA1LCAwLCAwLCAwLCAwLCAwLCA2LCA3LCA3LCAwLCA3LCA3LCA3LCAwLCA3LCA3LCA3LCAwLCAwLCAwLCAwLCAwLCA4LCA4LCA4LCAwLCA4LCA4LCA4LCAwLCA4LCA4LCA4LCAwLCAwLCAwLCAwLCAwLCA4LCA4LCA4LCAwLCA4LCA4LCA4LCAwLCA4LCA4LCA4XSk7CiAgY2xhc3MgQml0TW9kZWwgewogICAgY29uc3RydWN0b3Iod2lkdGgsIGhlaWdodCwgc3ViYmFuZCwgemVyb0JpdFBsYW5lcywgbWIpIHsKICAgICAgdGhpcy53aWR0aCA9IHdpZHRoOwogICAgICB0aGlzLmhlaWdodCA9IGhlaWdodDsKICAgICAgbGV0IGNvbnRleHRMYWJlbFRhYmxlOwogICAgICBpZiAoc3ViYmFuZCA9PT0gIkhIIikgewogICAgICAgIGNvbnRleHRMYWJlbFRhYmxlID0gSEhDb250ZXh0TGFiZWw7CiAgICAgIH0gZWxzZSBpZiAoc3ViYmFuZCA9PT0gIkhMIikgewogICAgICAgIGNvbnRleHRMYWJlbFRhYmxlID0gSExDb250ZXh0TGFiZWw7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29udGV4dExhYmVsVGFibGUgPSBMTEFuZExIQ29udGV4dHNMYWJlbDsKICAgICAgfQogICAgICB0aGlzLmNvbnRleHRMYWJlbFRhYmxlID0gY29udGV4dExhYmVsVGFibGU7CiAgICAgIGNvbnN0IGNvZWZmaWNpZW50Q291bnQgPSB3aWR0aCAqIGhlaWdodDsKICAgICAgdGhpcy5uZWlnaGJvcnNTaWduaWZpY2FuY2UgPSBuZXcgVWludDhBcnJheShjb2VmZmljaWVudENvdW50KTsKICAgICAgdGhpcy5jb2VmZmljZW50c1NpZ24gPSBuZXcgVWludDhBcnJheShjb2VmZmljaWVudENvdW50KTsKICAgICAgbGV0IGNvZWZmaWNlbnRzTWFnbml0dWRlOwogICAgICBpZiAobWIgPiAxNCkgewogICAgICAgIGNvZWZmaWNlbnRzTWFnbml0dWRlID0gbmV3IFVpbnQzMkFycmF5KGNvZWZmaWNpZW50Q291bnQpOwogICAgICB9IGVsc2UgaWYgKG1iID4gNikgewogICAgICAgIGNvZWZmaWNlbnRzTWFnbml0dWRlID0gbmV3IFVpbnQxNkFycmF5KGNvZWZmaWNpZW50Q291bnQpOwogICAgICB9IGVsc2UgewogICAgICAgIGNvZWZmaWNlbnRzTWFnbml0dWRlID0gbmV3IFVpbnQ4QXJyYXkoY29lZmZpY2llbnRDb3VudCk7CiAgICAgIH0KICAgICAgdGhpcy5jb2VmZmljZW50c01hZ25pdHVkZSA9IGNvZWZmaWNlbnRzTWFnbml0dWRlOwogICAgICB0aGlzLnByb2Nlc3NpbmdGbGFncyA9IG5ldyBVaW50OEFycmF5KGNvZWZmaWNpZW50Q291bnQpOwogICAgICBjb25zdCBiaXRzRGVjb2RlZCA9IG5ldyBVaW50OEFycmF5KGNvZWZmaWNpZW50Q291bnQpOwogICAgICBpZiAoemVyb0JpdFBsYW5lcyAhPT0gMCkgewogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29lZmZpY2llbnRDb3VudDsgaSsrKSB7CiAgICAgICAgICBiaXRzRGVjb2RlZFtpXSA9IHplcm9CaXRQbGFuZXM7CiAgICAgICAgfQogICAgICB9CiAgICAgIHRoaXMuYml0c0RlY29kZWQgPSBiaXRzRGVjb2RlZDsKICAgICAgdGhpcy5yZXNldCgpOwogICAgfQogICAgc2V0RGVjb2RlcihkZWNvZGVyKSB7CiAgICAgIHRoaXMuZGVjb2RlciA9IGRlY29kZXI7CiAgICB9CiAgICByZXNldCgpIHsKICAgICAgdGhpcy5jb250ZXh0cyA9IG5ldyBJbnQ4QXJyYXkoMTkpOwogICAgICB0aGlzLmNvbnRleHRzWzBdID0gNCA8PCAxIHwgMDsKICAgICAgdGhpcy5jb250ZXh0c1tVTklGT1JNX0NPTlRFWFRdID0gNDYgPDwgMSB8IDA7CiAgICAgIHRoaXMuY29udGV4dHNbUlVOTEVOR1RIX0NPTlRFWFRdID0gMyA8PCAxIHwgMDsKICAgIH0KICAgIHNldE5laWdoYm9yc1NpZ25pZmljYW5jZShyb3csIGNvbHVtbiwgaW5kZXgpIHsKICAgICAgY29uc3QgbmVpZ2hib3JzU2lnbmlmaWNhbmNlID0gdGhpcy5uZWlnaGJvcnNTaWduaWZpY2FuY2U7CiAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy53aWR0aCwKICAgICAgICBoZWlnaHQgPSB0aGlzLmhlaWdodDsKICAgICAgY29uc3QgbGVmdCA9IGNvbHVtbiA+IDA7CiAgICAgIGNvbnN0IHJpZ2h0ID0gY29sdW1uICsgMSA8IHdpZHRoOwogICAgICBsZXQgaTsKICAgICAgaWYgKHJvdyA+IDApIHsKICAgICAgICBpID0gaW5kZXggLSB3aWR0aDsKICAgICAgICBpZiAobGVmdCkgewogICAgICAgICAgbmVpZ2hib3JzU2lnbmlmaWNhbmNlW2kgLSAxXSArPSAweDEwOwogICAgICAgIH0KICAgICAgICBpZiAocmlnaHQpIHsKICAgICAgICAgIG5laWdoYm9yc1NpZ25pZmljYW5jZVtpICsgMV0gKz0gMHgxMDsKICAgICAgICB9CiAgICAgICAgbmVpZ2hib3JzU2lnbmlmaWNhbmNlW2ldICs9IDB4MDQ7CiAgICAgIH0KICAgICAgaWYgKHJvdyArIDEgPCBoZWlnaHQpIHsKICAgICAgICBpID0gaW5kZXggKyB3aWR0aDsKICAgICAgICBpZiAobGVmdCkgewogICAgICAgICAgbmVpZ2hib3JzU2lnbmlmaWNhbmNlW2kgLSAxXSArPSAweDEwOwogICAgICAgIH0KICAgICAgICBpZiAocmlnaHQpIHsKICAgICAgICAgIG5laWdoYm9yc1NpZ25pZmljYW5jZVtpICsgMV0gKz0gMHgxMDsKICAgICAgICB9CiAgICAgICAgbmVpZ2hib3JzU2lnbmlmaWNhbmNlW2ldICs9IDB4MDQ7CiAgICAgIH0KICAgICAgaWYgKGxlZnQpIHsKICAgICAgICBuZWlnaGJvcnNTaWduaWZpY2FuY2VbaW5kZXggLSAxXSArPSAweDAxOwogICAgICB9CiAgICAgIGlmIChyaWdodCkgewogICAgICAgIG5laWdoYm9yc1NpZ25pZmljYW5jZVtpbmRleCArIDFdICs9IDB4MDE7CiAgICAgIH0KICAgICAgbmVpZ2hib3JzU2lnbmlmaWNhbmNlW2luZGV4XSB8PSAweDgwOwogICAgfQogICAgcnVuU2lnbmlmaWNhbmNlUHJvcGFnYXRpb25QYXNzKCkgewogICAgICBjb25zdCBkZWNvZGVyID0gdGhpcy5kZWNvZGVyOwogICAgICBjb25zdCB3aWR0aCA9IHRoaXMud2lkdGgsCiAgICAgICAgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7CiAgICAgIGNvbnN0IGNvZWZmaWNlbnRzTWFnbml0dWRlID0gdGhpcy5jb2VmZmljZW50c01hZ25pdHVkZTsKICAgICAgY29uc3QgY29lZmZpY2VudHNTaWduID0gdGhpcy5jb2VmZmljZW50c1NpZ247CiAgICAgIGNvbnN0IG5laWdoYm9yc1NpZ25pZmljYW5jZSA9IHRoaXMubmVpZ2hib3JzU2lnbmlmaWNhbmNlOwogICAgICBjb25zdCBwcm9jZXNzaW5nRmxhZ3MgPSB0aGlzLnByb2Nlc3NpbmdGbGFnczsKICAgICAgY29uc3QgY29udGV4dHMgPSB0aGlzLmNvbnRleHRzOwogICAgICBjb25zdCBsYWJlbHMgPSB0aGlzLmNvbnRleHRMYWJlbFRhYmxlOwogICAgICBjb25zdCBiaXRzRGVjb2RlZCA9IHRoaXMuYml0c0RlY29kZWQ7CiAgICAgIGNvbnN0IHByb2Nlc3NlZEludmVyc2VNYXNrID0gfjE7CiAgICAgIGNvbnN0IHByb2Nlc3NlZE1hc2sgPSAxOwogICAgICBjb25zdCBmaXJzdE1hZ25pdHVkZUJpdE1hc2sgPSAyOwogICAgICBmb3IgKGxldCBpMCA9IDA7IGkwIDwgaGVpZ2h0OyBpMCArPSA0KSB7CiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7CiAgICAgICAgICBsZXQgaW5kZXggPSBpMCAqIHdpZHRoICsgajsKICAgICAgICAgIGZvciAobGV0IGkxID0gMDsgaTEgPCA0OyBpMSsrLCBpbmRleCArPSB3aWR0aCkgewogICAgICAgICAgICBjb25zdCBpID0gaTAgKyBpMTsKICAgICAgICAgICAgaWYgKGkgPj0gaGVpZ2h0KSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcHJvY2Vzc2luZ0ZsYWdzW2luZGV4XSAmPSBwcm9jZXNzZWRJbnZlcnNlTWFzazsKICAgICAgICAgICAgaWYgKGNvZWZmaWNlbnRzTWFnbml0dWRlW2luZGV4XSB8fCAhbmVpZ2hib3JzU2lnbmlmaWNhbmNlW2luZGV4XSkgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGNvbnRleHRMYWJlbCA9IGxhYmVsc1tuZWlnaGJvcnNTaWduaWZpY2FuY2VbaW5kZXhdXTsKICAgICAgICAgICAgY29uc3QgZGVjaXNpb24gPSBkZWNvZGVyLnJlYWRCaXQoY29udGV4dHMsIGNvbnRleHRMYWJlbCk7CiAgICAgICAgICAgIGlmIChkZWNpc2lvbikgewogICAgICAgICAgICAgIGNvbnN0IHNpZ24gPSB0aGlzLmRlY29kZVNpZ25CaXQoaSwgaiwgaW5kZXgpOwogICAgICAgICAgICAgIGNvZWZmaWNlbnRzU2lnbltpbmRleF0gPSBzaWduOwogICAgICAgICAgICAgIGNvZWZmaWNlbnRzTWFnbml0dWRlW2luZGV4XSA9IDE7CiAgICAgICAgICAgICAgdGhpcy5zZXROZWlnaGJvcnNTaWduaWZpY2FuY2UoaSwgaiwgaW5kZXgpOwogICAgICAgICAgICAgIHByb2Nlc3NpbmdGbGFnc1tpbmRleF0gfD0gZmlyc3RNYWduaXR1ZGVCaXRNYXNrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJpdHNEZWNvZGVkW2luZGV4XSsrOwogICAgICAgICAgICBwcm9jZXNzaW5nRmxhZ3NbaW5kZXhdIHw9IHByb2Nlc3NlZE1hc2s7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBkZWNvZGVTaWduQml0KHJvdywgY29sdW1uLCBpbmRleCkgewogICAgICBjb25zdCB3aWR0aCA9IHRoaXMud2lkdGgsCiAgICAgICAgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7CiAgICAgIGNvbnN0IGNvZWZmaWNlbnRzTWFnbml0dWRlID0gdGhpcy5jb2VmZmljZW50c01hZ25pdHVkZTsKICAgICAgY29uc3QgY29lZmZpY2VudHNTaWduID0gdGhpcy5jb2VmZmljZW50c1NpZ247CiAgICAgIGxldCBjb250cmlidXRpb24sIHNpZ24wLCBzaWduMSwgc2lnbmlmaWNhbmNlMTsKICAgICAgbGV0IGNvbnRleHRMYWJlbCwgZGVjb2RlZDsKICAgICAgc2lnbmlmaWNhbmNlMSA9IGNvbHVtbiA+IDAgJiYgY29lZmZpY2VudHNNYWduaXR1ZGVbaW5kZXggLSAxXSAhPT0gMDsKICAgICAgaWYgKGNvbHVtbiArIDEgPCB3aWR0aCAmJiBjb2VmZmljZW50c01hZ25pdHVkZVtpbmRleCArIDFdICE9PSAwKSB7CiAgICAgICAgc2lnbjEgPSBjb2VmZmljZW50c1NpZ25baW5kZXggKyAxXTsKICAgICAgICBpZiAoc2lnbmlmaWNhbmNlMSkgewogICAgICAgICAgc2lnbjAgPSBjb2VmZmljZW50c1NpZ25baW5kZXggLSAxXTsKICAgICAgICAgIGNvbnRyaWJ1dGlvbiA9IDEgLSBzaWduMSAtIHNpZ24wOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb250cmlidXRpb24gPSAxIC0gc2lnbjEgLSBzaWduMTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoc2lnbmlmaWNhbmNlMSkgewogICAgICAgIHNpZ24wID0gY29lZmZpY2VudHNTaWduW2luZGV4IC0gMV07CiAgICAgICAgY29udHJpYnV0aW9uID0gMSAtIHNpZ24wIC0gc2lnbjA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29udHJpYnV0aW9uID0gMDsKICAgICAgfQogICAgICBjb25zdCBob3Jpem9udGFsQ29udHJpYnV0aW9uID0gMyAqIGNvbnRyaWJ1dGlvbjsKICAgICAgc2lnbmlmaWNhbmNlMSA9IHJvdyA+IDAgJiYgY29lZmZpY2VudHNNYWduaXR1ZGVbaW5kZXggLSB3aWR0aF0gIT09IDA7CiAgICAgIGlmIChyb3cgKyAxIDwgaGVpZ2h0ICYmIGNvZWZmaWNlbnRzTWFnbml0dWRlW2luZGV4ICsgd2lkdGhdICE9PSAwKSB7CiAgICAgICAgc2lnbjEgPSBjb2VmZmljZW50c1NpZ25baW5kZXggKyB3aWR0aF07CiAgICAgICAgaWYgKHNpZ25pZmljYW5jZTEpIHsKICAgICAgICAgIHNpZ24wID0gY29lZmZpY2VudHNTaWduW2luZGV4IC0gd2lkdGhdOwogICAgICAgICAgY29udHJpYnV0aW9uID0gMSAtIHNpZ24xIC0gc2lnbjAgKyBob3Jpem9udGFsQ29udHJpYnV0aW9uOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb250cmlidXRpb24gPSAxIC0gc2lnbjEgLSBzaWduMSArIGhvcml6b250YWxDb250cmlidXRpb247CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKHNpZ25pZmljYW5jZTEpIHsKICAgICAgICBzaWduMCA9IGNvZWZmaWNlbnRzU2lnbltpbmRleCAtIHdpZHRoXTsKICAgICAgICBjb250cmlidXRpb24gPSAxIC0gc2lnbjAgLSBzaWduMCArIGhvcml6b250YWxDb250cmlidXRpb247CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29udHJpYnV0aW9uID0gaG9yaXpvbnRhbENvbnRyaWJ1dGlvbjsKICAgICAgfQogICAgICBpZiAoY29udHJpYnV0aW9uID49IDApIHsKICAgICAgICBjb250ZXh0TGFiZWwgPSA5ICsgY29udHJpYnV0aW9uOwogICAgICAgIGRlY29kZWQgPSB0aGlzLmRlY29kZXIucmVhZEJpdCh0aGlzLmNvbnRleHRzLCBjb250ZXh0TGFiZWwpOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnRleHRMYWJlbCA9IDkgLSBjb250cmlidXRpb247CiAgICAgICAgZGVjb2RlZCA9IHRoaXMuZGVjb2Rlci5yZWFkQml0KHRoaXMuY29udGV4dHMsIGNvbnRleHRMYWJlbCkgXiAxOwogICAgICB9CiAgICAgIHJldHVybiBkZWNvZGVkOwogICAgfQogICAgcnVuTWFnbml0dWRlUmVmaW5lbWVudFBhc3MoKSB7CiAgICAgIGNvbnN0IGRlY29kZXIgPSB0aGlzLmRlY29kZXI7CiAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy53aWR0aCwKICAgICAgICBoZWlnaHQgPSB0aGlzLmhlaWdodDsKICAgICAgY29uc3QgY29lZmZpY2VudHNNYWduaXR1ZGUgPSB0aGlzLmNvZWZmaWNlbnRzTWFnbml0dWRlOwogICAgICBjb25zdCBuZWlnaGJvcnNTaWduaWZpY2FuY2UgPSB0aGlzLm5laWdoYm9yc1NpZ25pZmljYW5jZTsKICAgICAgY29uc3QgY29udGV4dHMgPSB0aGlzLmNvbnRleHRzOwogICAgICBjb25zdCBiaXRzRGVjb2RlZCA9IHRoaXMuYml0c0RlY29kZWQ7CiAgICAgIGNvbnN0IHByb2Nlc3NpbmdGbGFncyA9IHRoaXMucHJvY2Vzc2luZ0ZsYWdzOwogICAgICBjb25zdCBwcm9jZXNzZWRNYXNrID0gMTsKICAgICAgY29uc3QgZmlyc3RNYWduaXR1ZGVCaXRNYXNrID0gMjsKICAgICAgY29uc3QgbGVuZ3RoID0gd2lkdGggKiBoZWlnaHQ7CiAgICAgIGNvbnN0IHdpZHRoNCA9IHdpZHRoICogNDsKICAgICAgZm9yIChsZXQgaW5kZXgwID0gMCwgaW5kZXhOZXh0OyBpbmRleDAgPCBsZW5ndGg7IGluZGV4MCA9IGluZGV4TmV4dCkgewogICAgICAgIGluZGV4TmV4dCA9IE1hdGgubWluKGxlbmd0aCwgaW5kZXgwICsgd2lkdGg0KTsKICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHdpZHRoOyBqKyspIHsKICAgICAgICAgIGZvciAobGV0IGluZGV4ID0gaW5kZXgwICsgajsgaW5kZXggPCBpbmRleE5leHQ7IGluZGV4ICs9IHdpZHRoKSB7CiAgICAgICAgICAgIGlmICghY29lZmZpY2VudHNNYWduaXR1ZGVbaW5kZXhdIHx8IChwcm9jZXNzaW5nRmxhZ3NbaW5kZXhdICYgcHJvY2Vzc2VkTWFzaykgIT09IDApIHsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZXQgY29udGV4dExhYmVsID0gMTY7CiAgICAgICAgICAgIGlmICgocHJvY2Vzc2luZ0ZsYWdzW2luZGV4XSAmIGZpcnN0TWFnbml0dWRlQml0TWFzaykgIT09IDApIHsKICAgICAgICAgICAgICBwcm9jZXNzaW5nRmxhZ3NbaW5kZXhdIF49IGZpcnN0TWFnbml0dWRlQml0TWFzazsKICAgICAgICAgICAgICBjb25zdCBzaWduaWZpY2FuY2UgPSBuZWlnaGJvcnNTaWduaWZpY2FuY2VbaW5kZXhdICYgMTI3OwogICAgICAgICAgICAgIGNvbnRleHRMYWJlbCA9IHNpZ25pZmljYW5jZSA9PT0gMCA/IDE1IDogMTQ7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgYml0ID0gZGVjb2Rlci5yZWFkQml0KGNvbnRleHRzLCBjb250ZXh0TGFiZWwpOwogICAgICAgICAgICBjb2VmZmljZW50c01hZ25pdHVkZVtpbmRleF0gPSBjb2VmZmljZW50c01hZ25pdHVkZVtpbmRleF0gPDwgMSB8IGJpdDsKICAgICAgICAgICAgYml0c0RlY29kZWRbaW5kZXhdKys7CiAgICAgICAgICAgIHByb2Nlc3NpbmdGbGFnc1tpbmRleF0gfD0gcHJvY2Vzc2VkTWFzazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJ1bkNsZWFudXBQYXNzKCkgewogICAgICBjb25zdCBkZWNvZGVyID0gdGhpcy5kZWNvZGVyOwogICAgICBjb25zdCB3aWR0aCA9IHRoaXMud2lkdGgsCiAgICAgICAgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7CiAgICAgIGNvbnN0IG5laWdoYm9yc1NpZ25pZmljYW5jZSA9IHRoaXMubmVpZ2hib3JzU2lnbmlmaWNhbmNlOwogICAgICBjb25zdCBjb2VmZmljZW50c01hZ25pdHVkZSA9IHRoaXMuY29lZmZpY2VudHNNYWduaXR1ZGU7CiAgICAgIGNvbnN0IGNvZWZmaWNlbnRzU2lnbiA9IHRoaXMuY29lZmZpY2VudHNTaWduOwogICAgICBjb25zdCBjb250ZXh0cyA9IHRoaXMuY29udGV4dHM7CiAgICAgIGNvbnN0IGxhYmVscyA9IHRoaXMuY29udGV4dExhYmVsVGFibGU7CiAgICAgIGNvbnN0IGJpdHNEZWNvZGVkID0gdGhpcy5iaXRzRGVjb2RlZDsKICAgICAgY29uc3QgcHJvY2Vzc2luZ0ZsYWdzID0gdGhpcy5wcm9jZXNzaW5nRmxhZ3M7CiAgICAgIGNvbnN0IHByb2Nlc3NlZE1hc2sgPSAxOwogICAgICBjb25zdCBmaXJzdE1hZ25pdHVkZUJpdE1hc2sgPSAyOwogICAgICBjb25zdCBvbmVSb3dEb3duID0gd2lkdGg7CiAgICAgIGNvbnN0IHR3b1Jvd3NEb3duID0gd2lkdGggKiAyOwogICAgICBjb25zdCB0aHJlZVJvd3NEb3duID0gd2lkdGggKiAzOwogICAgICBsZXQgaU5leHQ7CiAgICAgIGZvciAobGV0IGkwID0gMDsgaTAgPCBoZWlnaHQ7IGkwID0gaU5leHQpIHsKICAgICAgICBpTmV4dCA9IE1hdGgubWluKGkwICsgNCwgaGVpZ2h0KTsKICAgICAgICBjb25zdCBpbmRleEJhc2UgPSBpMCAqIHdpZHRoOwogICAgICAgIGNvbnN0IGNoZWNrQWxsRW1wdHkgPSBpMCArIDMgPCBoZWlnaHQ7CiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7CiAgICAgICAgICBjb25zdCBpbmRleDAgPSBpbmRleEJhc2UgKyBqOwogICAgICAgICAgY29uc3QgYWxsRW1wdHkgPSBjaGVja0FsbEVtcHR5ICYmIHByb2Nlc3NpbmdGbGFnc1tpbmRleDBdID09PSAwICYmIHByb2Nlc3NpbmdGbGFnc1tpbmRleDAgKyBvbmVSb3dEb3duXSA9PT0gMCAmJiBwcm9jZXNzaW5nRmxhZ3NbaW5kZXgwICsgdHdvUm93c0Rvd25dID09PSAwICYmIHByb2Nlc3NpbmdGbGFnc1tpbmRleDAgKyB0aHJlZVJvd3NEb3duXSA9PT0gMCAmJiBuZWlnaGJvcnNTaWduaWZpY2FuY2VbaW5kZXgwXSA9PT0gMCAmJiBuZWlnaGJvcnNTaWduaWZpY2FuY2VbaW5kZXgwICsgb25lUm93RG93bl0gPT09IDAgJiYgbmVpZ2hib3JzU2lnbmlmaWNhbmNlW2luZGV4MCArIHR3b1Jvd3NEb3duXSA9PT0gMCAmJiBuZWlnaGJvcnNTaWduaWZpY2FuY2VbaW5kZXgwICsgdGhyZWVSb3dzRG93bl0gPT09IDA7CiAgICAgICAgICBsZXQgaTEgPSAwLAogICAgICAgICAgICBpbmRleCA9IGluZGV4MDsKICAgICAgICAgIGxldCBpID0gaTAsCiAgICAgICAgICAgIHNpZ247CiAgICAgICAgICBpZiAoYWxsRW1wdHkpIHsKICAgICAgICAgICAgY29uc3QgaGFzU2lnbmlmaWNhbnRDb2VmZmljZW50ID0gZGVjb2Rlci5yZWFkQml0KGNvbnRleHRzLCBSVU5MRU5HVEhfQ09OVEVYVCk7CiAgICAgICAgICAgIGlmICghaGFzU2lnbmlmaWNhbnRDb2VmZmljZW50KSB7CiAgICAgICAgICAgICAgYml0c0RlY29kZWRbaW5kZXgwXSsrOwogICAgICAgICAgICAgIGJpdHNEZWNvZGVkW2luZGV4MCArIG9uZVJvd0Rvd25dKys7CiAgICAgICAgICAgICAgYml0c0RlY29kZWRbaW5kZXgwICsgdHdvUm93c0Rvd25dKys7CiAgICAgICAgICAgICAgYml0c0RlY29kZWRbaW5kZXgwICsgdGhyZWVSb3dzRG93bl0rKzsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpMSA9IGRlY29kZXIucmVhZEJpdChjb250ZXh0cywgVU5JRk9STV9DT05URVhUKSA8PCAxIHwgZGVjb2Rlci5yZWFkQml0KGNvbnRleHRzLCBVTklGT1JNX0NPTlRFWFQpOwogICAgICAgICAgICBpZiAoaTEgIT09IDApIHsKICAgICAgICAgICAgICBpID0gaTAgKyBpMTsKICAgICAgICAgICAgICBpbmRleCArPSBpMSAqIHdpZHRoOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHNpZ24gPSB0aGlzLmRlY29kZVNpZ25CaXQoaSwgaiwgaW5kZXgpOwogICAgICAgICAgICBjb2VmZmljZW50c1NpZ25baW5kZXhdID0gc2lnbjsKICAgICAgICAgICAgY29lZmZpY2VudHNNYWduaXR1ZGVbaW5kZXhdID0gMTsKICAgICAgICAgICAgdGhpcy5zZXROZWlnaGJvcnNTaWduaWZpY2FuY2UoaSwgaiwgaW5kZXgpOwogICAgICAgICAgICBwcm9jZXNzaW5nRmxhZ3NbaW5kZXhdIHw9IGZpcnN0TWFnbml0dWRlQml0TWFzazsKICAgICAgICAgICAgaW5kZXggPSBpbmRleDA7CiAgICAgICAgICAgIGZvciAobGV0IGkyID0gaTA7IGkyIDw9IGk7IGkyKyssIGluZGV4ICs9IHdpZHRoKSB7CiAgICAgICAgICAgICAgYml0c0RlY29kZWRbaW5kZXhdKys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaTErKzsKICAgICAgICAgIH0KICAgICAgICAgIGZvciAoaSA9IGkwICsgaTE7IGkgPCBpTmV4dDsgaSsrLCBpbmRleCArPSB3aWR0aCkgewogICAgICAgICAgICBpZiAoY29lZmZpY2VudHNNYWduaXR1ZGVbaW5kZXhdIHx8IChwcm9jZXNzaW5nRmxhZ3NbaW5kZXhdICYgcHJvY2Vzc2VkTWFzaykgIT09IDApIHsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBjb250ZXh0TGFiZWwgPSBsYWJlbHNbbmVpZ2hib3JzU2lnbmlmaWNhbmNlW2luZGV4XV07CiAgICAgICAgICAgIGNvbnN0IGRlY2lzaW9uID0gZGVjb2Rlci5yZWFkQml0KGNvbnRleHRzLCBjb250ZXh0TGFiZWwpOwogICAgICAgICAgICBpZiAoZGVjaXNpb24gPT09IDEpIHsKICAgICAgICAgICAgICBzaWduID0gdGhpcy5kZWNvZGVTaWduQml0KGksIGosIGluZGV4KTsKICAgICAgICAgICAgICBjb2VmZmljZW50c1NpZ25baW5kZXhdID0gc2lnbjsKICAgICAgICAgICAgICBjb2VmZmljZW50c01hZ25pdHVkZVtpbmRleF0gPSAxOwogICAgICAgICAgICAgIHRoaXMuc2V0TmVpZ2hib3JzU2lnbmlmaWNhbmNlKGksIGosIGluZGV4KTsKICAgICAgICAgICAgICBwcm9jZXNzaW5nRmxhZ3NbaW5kZXhdIHw9IGZpcnN0TWFnbml0dWRlQml0TWFzazsKICAgICAgICAgICAgfQogICAgICAgICAgICBiaXRzRGVjb2RlZFtpbmRleF0rKzsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGNoZWNrU2VnbWVudGF0aW9uU3ltYm9sKCkgewogICAgICBjb25zdCBkZWNvZGVyID0gdGhpcy5kZWNvZGVyOwogICAgICBjb25zdCBjb250ZXh0cyA9IHRoaXMuY29udGV4dHM7CiAgICAgIGNvbnN0IHN5bWJvbCA9IGRlY29kZXIucmVhZEJpdChjb250ZXh0cywgVU5JRk9STV9DT05URVhUKSA8PCAzIHwgZGVjb2Rlci5yZWFkQml0KGNvbnRleHRzLCBVTklGT1JNX0NPTlRFWFQpIDw8IDIgfCBkZWNvZGVyLnJlYWRCaXQoY29udGV4dHMsIFVOSUZPUk1fQ09OVEVYVCkgPDwgMSB8IGRlY29kZXIucmVhZEJpdChjb250ZXh0cywgVU5JRk9STV9DT05URVhUKTsKICAgICAgaWYgKHN5bWJvbCAhPT0gMHhhKSB7CiAgICAgICAgdGhyb3cgbmV3IEpweEVycm9yKCJJbnZhbGlkIHNlZ21lbnRhdGlvbiBzeW1ib2wiKTsKICAgICAgfQogICAgfQogIH0KICByZXR1cm4gQml0TW9kZWw7Cn0oKTsKY2xhc3MgVHJhbnNmb3JtIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yID09PSBUcmFuc2Zvcm0pIHsKICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQ2Fubm90IGluaXRpYWxpemUgVHJhbnNmb3JtLiIpOwogICAgfQogIH0KICBjYWxjdWxhdGUoc3ViYmFuZHMsIHUwLCB2MCkgewogICAgbGV0IGxsID0gc3ViYmFuZHNbMF07CiAgICBmb3IgKGxldCBpID0gMSwgaWkgPSBzdWJiYW5kcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGxsID0gdGhpcy5pdGVyYXRlKGxsLCBzdWJiYW5kc1tpXSwgdTAsIHYwKTsKICAgIH0KICAgIHJldHVybiBsbDsKICB9CiAgZXh0ZW5kKGJ1ZmZlciwgb2Zmc2V0LCBzaXplKSB7CiAgICBsZXQgaTEgPSBvZmZzZXQgLSAxLAogICAgICBqMSA9IG9mZnNldCArIDE7CiAgICBsZXQgaTIgPSBvZmZzZXQgKyBzaXplIC0gMiwKICAgICAgajIgPSBvZmZzZXQgKyBzaXplOwogICAgYnVmZmVyW2kxLS1dID0gYnVmZmVyW2oxKytdOwogICAgYnVmZmVyW2oyKytdID0gYnVmZmVyW2kyLS1dOwogICAgYnVmZmVyW2kxLS1dID0gYnVmZmVyW2oxKytdOwogICAgYnVmZmVyW2oyKytdID0gYnVmZmVyW2kyLS1dOwogICAgYnVmZmVyW2kxLS1dID0gYnVmZmVyW2oxKytdOwogICAgYnVmZmVyW2oyKytdID0gYnVmZmVyW2kyLS1dOwogICAgYnVmZmVyW2kxXSA9IGJ1ZmZlcltqMV07CiAgICBidWZmZXJbajJdID0gYnVmZmVyW2kyXTsKICB9CiAgZmlsdGVyKHgsIG9mZnNldCwgbGVuZ3RoKSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBtZXRob2QgYGZpbHRlcmAgY2FsbGVkIik7CiAgfQogIGl0ZXJhdGUobGwsIGhsX2xoX2hoLCB1MCwgdjApIHsKICAgIGNvbnN0IGxsV2lkdGggPSBsbC53aWR0aCwKICAgICAgbGxIZWlnaHQgPSBsbC5oZWlnaHQ7CiAgICBsZXQgbGxJdGVtcyA9IGxsLml0ZW1zOwogICAgY29uc3Qgd2lkdGggPSBobF9saF9oaC53aWR0aDsKICAgIGNvbnN0IGhlaWdodCA9IGhsX2xoX2hoLmhlaWdodDsKICAgIGNvbnN0IGl0ZW1zID0gaGxfbGhfaGguaXRlbXM7CiAgICBsZXQgaSwgaiwgaywgbCwgdSwgdjsKICAgIGZvciAoayA9IDAsIGkgPSAwOyBpIDwgbGxIZWlnaHQ7IGkrKykgewogICAgICBsID0gaSAqIDIgKiB3aWR0aDsKICAgICAgZm9yIChqID0gMDsgaiA8IGxsV2lkdGg7IGorKywgaysrLCBsICs9IDIpIHsKICAgICAgICBpdGVtc1tsXSA9IGxsSXRlbXNba107CiAgICAgIH0KICAgIH0KICAgIGxsSXRlbXMgPSBsbC5pdGVtcyA9IG51bGw7CiAgICBjb25zdCBidWZmZXJQYWRkaW5nID0gNDsKICAgIGNvbnN0IHJvd0J1ZmZlciA9IG5ldyBGbG9hdDMyQXJyYXkod2lkdGggKyAyICogYnVmZmVyUGFkZGluZyk7CiAgICBpZiAod2lkdGggPT09IDEpIHsKICAgICAgaWYgKCh1MCAmIDEpICE9PSAwKSB7CiAgICAgICAgZm9yICh2ID0gMCwgayA9IDA7IHYgPCBoZWlnaHQ7IHYrKywgayArPSB3aWR0aCkgewogICAgICAgICAgaXRlbXNba10gKj0gMC41OwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgZm9yICh2ID0gMCwgayA9IDA7IHYgPCBoZWlnaHQ7IHYrKywgayArPSB3aWR0aCkgewogICAgICAgIHJvd0J1ZmZlci5zZXQoaXRlbXMuc3ViYXJyYXkoaywgayArIHdpZHRoKSwgYnVmZmVyUGFkZGluZyk7CiAgICAgICAgdGhpcy5leHRlbmQocm93QnVmZmVyLCBidWZmZXJQYWRkaW5nLCB3aWR0aCk7CiAgICAgICAgdGhpcy5maWx0ZXIocm93QnVmZmVyLCBidWZmZXJQYWRkaW5nLCB3aWR0aCk7CiAgICAgICAgaXRlbXMuc2V0KHJvd0J1ZmZlci5zdWJhcnJheShidWZmZXJQYWRkaW5nLCBidWZmZXJQYWRkaW5nICsgd2lkdGgpLCBrKTsKICAgICAgfQogICAgfQogICAgbGV0IG51bUJ1ZmZlcnMgPSAxNjsKICAgIGNvbnN0IGNvbEJ1ZmZlcnMgPSBbXTsKICAgIGZvciAoaSA9IDA7IGkgPCBudW1CdWZmZXJzOyBpKyspIHsKICAgICAgY29sQnVmZmVycy5wdXNoKG5ldyBGbG9hdDMyQXJyYXkoaGVpZ2h0ICsgMiAqIGJ1ZmZlclBhZGRpbmcpKTsKICAgIH0KICAgIGxldCBiLAogICAgICBjdXJyZW50QnVmZmVyID0gMDsKICAgIGxsID0gYnVmZmVyUGFkZGluZyArIGhlaWdodDsKICAgIGlmIChoZWlnaHQgPT09IDEpIHsKICAgICAgaWYgKCh2MCAmIDEpICE9PSAwKSB7CiAgICAgICAgZm9yICh1ID0gMDsgdSA8IHdpZHRoOyB1KyspIHsKICAgICAgICAgIGl0ZW1zW3VdICo9IDAuNTsKICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGZvciAodSA9IDA7IHUgPCB3aWR0aDsgdSsrKSB7CiAgICAgICAgaWYgKGN1cnJlbnRCdWZmZXIgPT09IDApIHsKICAgICAgICAgIG51bUJ1ZmZlcnMgPSBNYXRoLm1pbih3aWR0aCAtIHUsIG51bUJ1ZmZlcnMpOwogICAgICAgICAgZm9yIChrID0gdSwgbCA9IGJ1ZmZlclBhZGRpbmc7IGwgPCBsbDsgayArPSB3aWR0aCwgbCsrKSB7CiAgICAgICAgICAgIGZvciAoYiA9IDA7IGIgPCBudW1CdWZmZXJzOyBiKyspIHsKICAgICAgICAgICAgICBjb2xCdWZmZXJzW2JdW2xdID0gaXRlbXNbayArIGJdOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBjdXJyZW50QnVmZmVyID0gbnVtQnVmZmVyczsKICAgICAgICB9CiAgICAgICAgY3VycmVudEJ1ZmZlci0tOwogICAgICAgIGNvbnN0IGJ1ZmZlciA9IGNvbEJ1ZmZlcnNbY3VycmVudEJ1ZmZlcl07CiAgICAgICAgdGhpcy5leHRlbmQoYnVmZmVyLCBidWZmZXJQYWRkaW5nLCBoZWlnaHQpOwogICAgICAgIHRoaXMuZmlsdGVyKGJ1ZmZlciwgYnVmZmVyUGFkZGluZywgaGVpZ2h0KTsKICAgICAgICBpZiAoY3VycmVudEJ1ZmZlciA9PT0gMCkgewogICAgICAgICAgayA9IHUgLSBudW1CdWZmZXJzICsgMTsKICAgICAgICAgIGZvciAobCA9IGJ1ZmZlclBhZGRpbmc7IGwgPCBsbDsgayArPSB3aWR0aCwgbCsrKSB7CiAgICAgICAgICAgIGZvciAoYiA9IDA7IGIgPCBudW1CdWZmZXJzOyBiKyspIHsKICAgICAgICAgICAgICBpdGVtc1trICsgYl0gPSBjb2xCdWZmZXJzW2JdW2xdOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gewogICAgICB3aWR0aCwKICAgICAgaGVpZ2h0LAogICAgICBpdGVtcwogICAgfTsKICB9Cn0KY2xhc3MgSXJyZXZlcnNpYmxlVHJhbnNmb3JtIGV4dGVuZHMgVHJhbnNmb3JtIHsKICBmaWx0ZXIoeCwgb2Zmc2V0LCBsZW5ndGgpIHsKICAgIGNvbnN0IGxlbiA9IGxlbmd0aCA+PiAxOwogICAgb2Zmc2V0IHw9IDA7CiAgICBsZXQgaiwgbiwgY3VycmVudCwgbmV4dDsKICAgIGNvbnN0IGFscGhhID0gLTEuNTg2MTM0MzQyMDU5OTI0OwogICAgY29uc3QgYmV0YSA9IC0wLjA1Mjk4MDExODU3Mjk2MTsKICAgIGNvbnN0IGdhbW1hID0gMC44ODI5MTEwNzU1MzA5MzQ7CiAgICBjb25zdCBkZWx0YSA9IDAuNDQzNTA2ODUyMDQzOTcxOwogICAgY29uc3QgSyA9IDEuMjMwMTc0MTA0OTE0MDAxOwogICAgY29uc3QgS18gPSAxIC8gSzsKICAgIGogPSBvZmZzZXQgLSAzOwogICAgZm9yIChuID0gbGVuICsgNDsgbi0tOyBqICs9IDIpIHsKICAgICAgeFtqXSAqPSBLXzsKICAgIH0KICAgIGogPSBvZmZzZXQgLSAyOwogICAgY3VycmVudCA9IGRlbHRhICogeFtqIC0gMV07CiAgICBmb3IgKG4gPSBsZW4gKyAzOyBuLS07IGogKz0gMikgewogICAgICBuZXh0ID0gZGVsdGEgKiB4W2ogKyAxXTsKICAgICAgeFtqXSA9IEsgKiB4W2pdIC0gY3VycmVudCAtIG5leHQ7CiAgICAgIGlmIChuLS0pIHsKICAgICAgICBqICs9IDI7CiAgICAgICAgY3VycmVudCA9IGRlbHRhICogeFtqICsgMV07CiAgICAgICAgeFtqXSA9IEsgKiB4W2pdIC0gY3VycmVudCAtIG5leHQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGogPSBvZmZzZXQgLSAxOwogICAgY3VycmVudCA9IGdhbW1hICogeFtqIC0gMV07CiAgICBmb3IgKG4gPSBsZW4gKyAyOyBuLS07IGogKz0gMikgewogICAgICBuZXh0ID0gZ2FtbWEgKiB4W2ogKyAxXTsKICAgICAgeFtqXSAtPSBjdXJyZW50ICsgbmV4dDsKICAgICAgaWYgKG4tLSkgewogICAgICAgIGogKz0gMjsKICAgICAgICBjdXJyZW50ID0gZ2FtbWEgKiB4W2ogKyAxXTsKICAgICAgICB4W2pdIC09IGN1cnJlbnQgKyBuZXh0OwogICAgICB9IGVsc2UgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBqID0gb2Zmc2V0OwogICAgY3VycmVudCA9IGJldGEgKiB4W2ogLSAxXTsKICAgIGZvciAobiA9IGxlbiArIDE7IG4tLTsgaiArPSAyKSB7CiAgICAgIG5leHQgPSBiZXRhICogeFtqICsgMV07CiAgICAgIHhbal0gLT0gY3VycmVudCArIG5leHQ7CiAgICAgIGlmIChuLS0pIHsKICAgICAgICBqICs9IDI7CiAgICAgICAgY3VycmVudCA9IGJldGEgKiB4W2ogKyAxXTsKICAgICAgICB4W2pdIC09IGN1cnJlbnQgKyBuZXh0OwogICAgICB9IGVsc2UgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBpZiAobGVuICE9PSAwKSB7CiAgICAgIGogPSBvZmZzZXQgKyAxOwogICAgICBjdXJyZW50ID0gYWxwaGEgKiB4W2ogLSAxXTsKICAgICAgZm9yIChuID0gbGVuOyBuLS07IGogKz0gMikgewogICAgICAgIG5leHQgPSBhbHBoYSAqIHhbaiArIDFdOwogICAgICAgIHhbal0gLT0gY3VycmVudCArIG5leHQ7CiAgICAgICAgaWYgKG4tLSkgewogICAgICAgICAgaiArPSAyOwogICAgICAgICAgY3VycmVudCA9IGFscGhhICogeFtqICsgMV07CiAgICAgICAgICB4W2pdIC09IGN1cnJlbnQgKyBuZXh0OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9Cn0KY2xhc3MgUmV2ZXJzaWJsZVRyYW5zZm9ybSBleHRlbmRzIFRyYW5zZm9ybSB7CiAgZmlsdGVyKHgsIG9mZnNldCwgbGVuZ3RoKSB7CiAgICBjb25zdCBsZW4gPSBsZW5ndGggPj4gMTsKICAgIG9mZnNldCB8PSAwOwogICAgbGV0IGosIG47CiAgICBmb3IgKGogPSBvZmZzZXQsIG4gPSBsZW4gKyAxOyBuLS07IGogKz0gMikgewogICAgICB4W2pdIC09IHhbaiAtIDFdICsgeFtqICsgMV0gKyAyID4+IDI7CiAgICB9CiAgICBmb3IgKGogPSBvZmZzZXQgKyAxLCBuID0gbGVuOyBuLS07IGogKz0gMikgewogICAgICB4W2pdICs9IHhbaiAtIDFdICsgeFtqICsgMV0gPj4gMTsKICAgIH0KICB9Cn0KCi8qKiovIH0pLAovKiAxNjYgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLkxaV1N0cmVhbSA9IHZvaWQgMDsKdmFyIF9kZWNvZGVfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTMpOwpjbGFzcyBMWldTdHJlYW0gZXh0ZW5kcyBfZGVjb2RlX3N0cmVhbS5EZWNvZGVTdHJlYW0gewogIGNvbnN0cnVjdG9yKHN0ciwgbWF5YmVMZW5ndGgsIGVhcmx5Q2hhbmdlKSB7CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICB0aGlzLnN0ciA9IHN0cjsKICAgIHRoaXMuZGljdCA9IHN0ci5kaWN0OwogICAgdGhpcy5jYWNoZWREYXRhID0gMDsKICAgIHRoaXMuYml0c0NhY2hlZCA9IDA7CiAgICBjb25zdCBtYXhMendEaWN0aW9uYXJ5U2l6ZSA9IDQwOTY7CiAgICBjb25zdCBsendTdGF0ZSA9IHsKICAgICAgZWFybHlDaGFuZ2UsCiAgICAgIGNvZGVMZW5ndGg6IDksCiAgICAgIG5leHRDb2RlOiAyNTgsCiAgICAgIGRpY3Rpb25hcnlWYWx1ZXM6IG5ldyBVaW50OEFycmF5KG1heEx6d0RpY3Rpb25hcnlTaXplKSwKICAgICAgZGljdGlvbmFyeUxlbmd0aHM6IG5ldyBVaW50MTZBcnJheShtYXhMendEaWN0aW9uYXJ5U2l6ZSksCiAgICAgIGRpY3Rpb25hcnlQcmV2Q29kZXM6IG5ldyBVaW50MTZBcnJheShtYXhMendEaWN0aW9uYXJ5U2l6ZSksCiAgICAgIGN1cnJlbnRTZXF1ZW5jZTogbmV3IFVpbnQ4QXJyYXkobWF4THp3RGljdGlvbmFyeVNpemUpLAogICAgICBjdXJyZW50U2VxdWVuY2VMZW5ndGg6IDAKICAgIH07CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgKytpKSB7CiAgICAgIGx6d1N0YXRlLmRpY3Rpb25hcnlWYWx1ZXNbaV0gPSBpOwogICAgICBsendTdGF0ZS5kaWN0aW9uYXJ5TGVuZ3Roc1tpXSA9IDE7CiAgICB9CiAgICB0aGlzLmx6d1N0YXRlID0gbHp3U3RhdGU7CiAgfQogIHJlYWRCaXRzKG4pIHsKICAgIGxldCBiaXRzQ2FjaGVkID0gdGhpcy5iaXRzQ2FjaGVkOwogICAgbGV0IGNhY2hlZERhdGEgPSB0aGlzLmNhY2hlZERhdGE7CiAgICB3aGlsZSAoYml0c0NhY2hlZCA8IG4pIHsKICAgICAgY29uc3QgYyA9IHRoaXMuc3RyLmdldEJ5dGUoKTsKICAgICAgaWYgKGMgPT09IC0xKSB7CiAgICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNhY2hlZERhdGEgPSBjYWNoZWREYXRhIDw8IDggfCBjOwogICAgICBiaXRzQ2FjaGVkICs9IDg7CiAgICB9CiAgICB0aGlzLmJpdHNDYWNoZWQgPSBiaXRzQ2FjaGVkIC09IG47CiAgICB0aGlzLmNhY2hlZERhdGEgPSBjYWNoZWREYXRhOwogICAgdGhpcy5sYXN0Q29kZSA9IG51bGw7CiAgICByZXR1cm4gY2FjaGVkRGF0YSA+Pj4gYml0c0NhY2hlZCAmICgxIDw8IG4pIC0gMTsKICB9CiAgcmVhZEJsb2NrKCkgewogICAgY29uc3QgYmxvY2tTaXplID0gNTEyLAogICAgICBkZWNvZGVkU2l6ZURlbHRhID0gYmxvY2tTaXplOwogICAgbGV0IGVzdGltYXRlZERlY29kZWRTaXplID0gYmxvY2tTaXplICogMjsKICAgIGxldCBpLCBqLCBxOwogICAgY29uc3QgbHp3U3RhdGUgPSB0aGlzLmx6d1N0YXRlOwogICAgaWYgKCFsendTdGF0ZSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBlYXJseUNoYW5nZSA9IGx6d1N0YXRlLmVhcmx5Q2hhbmdlOwogICAgbGV0IG5leHRDb2RlID0gbHp3U3RhdGUubmV4dENvZGU7CiAgICBjb25zdCBkaWN0aW9uYXJ5VmFsdWVzID0gbHp3U3RhdGUuZGljdGlvbmFyeVZhbHVlczsKICAgIGNvbnN0IGRpY3Rpb25hcnlMZW5ndGhzID0gbHp3U3RhdGUuZGljdGlvbmFyeUxlbmd0aHM7CiAgICBjb25zdCBkaWN0aW9uYXJ5UHJldkNvZGVzID0gbHp3U3RhdGUuZGljdGlvbmFyeVByZXZDb2RlczsKICAgIGxldCBjb2RlTGVuZ3RoID0gbHp3U3RhdGUuY29kZUxlbmd0aDsKICAgIGxldCBwcmV2Q29kZSA9IGx6d1N0YXRlLnByZXZDb2RlOwogICAgY29uc3QgY3VycmVudFNlcXVlbmNlID0gbHp3U3RhdGUuY3VycmVudFNlcXVlbmNlOwogICAgbGV0IGN1cnJlbnRTZXF1ZW5jZUxlbmd0aCA9IGx6d1N0YXRlLmN1cnJlbnRTZXF1ZW5jZUxlbmd0aDsKICAgIGxldCBkZWNvZGVkTGVuZ3RoID0gMDsKICAgIGxldCBjdXJyZW50QnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJMZW5ndGg7CiAgICBsZXQgYnVmZmVyID0gdGhpcy5lbnN1cmVCdWZmZXIodGhpcy5idWZmZXJMZW5ndGggKyBlc3RpbWF0ZWREZWNvZGVkU2l6ZSk7CiAgICBmb3IgKGkgPSAwOyBpIDwgYmxvY2tTaXplOyBpKyspIHsKICAgICAgY29uc3QgY29kZSA9IHRoaXMucmVhZEJpdHMoY29kZUxlbmd0aCk7CiAgICAgIGNvbnN0IGhhc1ByZXYgPSBjdXJyZW50U2VxdWVuY2VMZW5ndGggPiAwOwogICAgICBpZiAoY29kZSA8IDI1NikgewogICAgICAgIGN1cnJlbnRTZXF1ZW5jZVswXSA9IGNvZGU7CiAgICAgICAgY3VycmVudFNlcXVlbmNlTGVuZ3RoID0gMTsKICAgICAgfSBlbHNlIGlmIChjb2RlID49IDI1OCkgewogICAgICAgIGlmIChjb2RlIDwgbmV4dENvZGUpIHsKICAgICAgICAgIGN1cnJlbnRTZXF1ZW5jZUxlbmd0aCA9IGRpY3Rpb25hcnlMZW5ndGhzW2NvZGVdOwogICAgICAgICAgZm9yIChqID0gY3VycmVudFNlcXVlbmNlTGVuZ3RoIC0gMSwgcSA9IGNvZGU7IGogPj0gMDsgai0tKSB7CiAgICAgICAgICAgIGN1cnJlbnRTZXF1ZW5jZVtqXSA9IGRpY3Rpb25hcnlWYWx1ZXNbcV07CiAgICAgICAgICAgIHEgPSBkaWN0aW9uYXJ5UHJldkNvZGVzW3FdOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjdXJyZW50U2VxdWVuY2VbY3VycmVudFNlcXVlbmNlTGVuZ3RoKytdID0gY3VycmVudFNlcXVlbmNlWzBdOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChjb2RlID09PSAyNTYpIHsKICAgICAgICBjb2RlTGVuZ3RoID0gOTsKICAgICAgICBuZXh0Q29kZSA9IDI1ODsKICAgICAgICBjdXJyZW50U2VxdWVuY2VMZW5ndGggPSAwOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgICBkZWxldGUgdGhpcy5sendTdGF0ZTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAoaGFzUHJldikgewogICAgICAgIGRpY3Rpb25hcnlQcmV2Q29kZXNbbmV4dENvZGVdID0gcHJldkNvZGU7CiAgICAgICAgZGljdGlvbmFyeUxlbmd0aHNbbmV4dENvZGVdID0gZGljdGlvbmFyeUxlbmd0aHNbcHJldkNvZGVdICsgMTsKICAgICAgICBkaWN0aW9uYXJ5VmFsdWVzW25leHRDb2RlXSA9IGN1cnJlbnRTZXF1ZW5jZVswXTsKICAgICAgICBuZXh0Q29kZSsrOwogICAgICAgIGNvZGVMZW5ndGggPSBuZXh0Q29kZSArIGVhcmx5Q2hhbmdlICYgbmV4dENvZGUgKyBlYXJseUNoYW5nZSAtIDEgPyBjb2RlTGVuZ3RoIDogTWF0aC5taW4oTWF0aC5sb2cobmV4dENvZGUgKyBlYXJseUNoYW5nZSkgLyAwLjY5MzE0NzE4MDU1OTk0NTMgKyAxLCAxMikgfCAwOwogICAgICB9CiAgICAgIHByZXZDb2RlID0gY29kZTsKICAgICAgZGVjb2RlZExlbmd0aCArPSBjdXJyZW50U2VxdWVuY2VMZW5ndGg7CiAgICAgIGlmIChlc3RpbWF0ZWREZWNvZGVkU2l6ZSA8IGRlY29kZWRMZW5ndGgpIHsKICAgICAgICBkbyB7CiAgICAgICAgICBlc3RpbWF0ZWREZWNvZGVkU2l6ZSArPSBkZWNvZGVkU2l6ZURlbHRhOwogICAgICAgIH0gd2hpbGUgKGVzdGltYXRlZERlY29kZWRTaXplIDwgZGVjb2RlZExlbmd0aCk7CiAgICAgICAgYnVmZmVyID0gdGhpcy5lbnN1cmVCdWZmZXIodGhpcy5idWZmZXJMZW5ndGggKyBlc3RpbWF0ZWREZWNvZGVkU2l6ZSk7CiAgICAgIH0KICAgICAgZm9yIChqID0gMDsgaiA8IGN1cnJlbnRTZXF1ZW5jZUxlbmd0aDsgaisrKSB7CiAgICAgICAgYnVmZmVyW2N1cnJlbnRCdWZmZXJMZW5ndGgrK10gPSBjdXJyZW50U2VxdWVuY2Vbal07CiAgICAgIH0KICAgIH0KICAgIGx6d1N0YXRlLm5leHRDb2RlID0gbmV4dENvZGU7CiAgICBsendTdGF0ZS5jb2RlTGVuZ3RoID0gY29kZUxlbmd0aDsKICAgIGx6d1N0YXRlLnByZXZDb2RlID0gcHJldkNvZGU7CiAgICBsendTdGF0ZS5jdXJyZW50U2VxdWVuY2VMZW5ndGggPSBjdXJyZW50U2VxdWVuY2VMZW5ndGg7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGN1cnJlbnRCdWZmZXJMZW5ndGg7CiAgfQp9CmV4cG9ydHMuTFpXU3RyZWFtID0gTFpXU3RyZWFtOwoKLyoqKi8gfSksCi8qIDE2NyAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuUHJlZGljdG9yU3RyZWFtID0gdm9pZCAwOwp2YXIgX2RlY29kZV9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1Myk7CnZhciBfcHJpbWl0aXZlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQwKTsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKY2xhc3MgUHJlZGljdG9yU3RyZWFtIGV4dGVuZHMgX2RlY29kZV9zdHJlYW0uRGVjb2RlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHIsIG1heWJlTGVuZ3RoLCBwYXJhbXMpIHsKICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIGlmICghKHBhcmFtcyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybiBzdHI7CiAgICB9CiAgICBjb25zdCBwcmVkaWN0b3IgPSB0aGlzLnByZWRpY3RvciA9IHBhcmFtcy5nZXQoIlByZWRpY3RvciIpIHx8IDE7CiAgICBpZiAocHJlZGljdG9yIDw9IDEpIHsKICAgICAgcmV0dXJuIHN0cjsKICAgIH0KICAgIGlmIChwcmVkaWN0b3IgIT09IDIgJiYgKHByZWRpY3RvciA8IDEwIHx8IHByZWRpY3RvciA+IDE1KSkgewogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYFVuc3VwcG9ydGVkIHByZWRpY3RvcjogJHtwcmVkaWN0b3J9YCk7CiAgICB9CiAgICBpZiAocHJlZGljdG9yID09PSAyKSB7CiAgICAgIHRoaXMucmVhZEJsb2NrID0gdGhpcy5yZWFkQmxvY2tUaWZmOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5yZWFkQmxvY2sgPSB0aGlzLnJlYWRCbG9ja1BuZzsKICAgIH0KICAgIHRoaXMuc3RyID0gc3RyOwogICAgdGhpcy5kaWN0ID0gc3RyLmRpY3Q7CiAgICBjb25zdCBjb2xvcnMgPSB0aGlzLmNvbG9ycyA9IHBhcmFtcy5nZXQoIkNvbG9ycyIpIHx8IDE7CiAgICBjb25zdCBiaXRzID0gdGhpcy5iaXRzID0gcGFyYW1zLmdldCgiQlBDIiwgIkJpdHNQZXJDb21wb25lbnQiKSB8fCA4OwogICAgY29uc3QgY29sdW1ucyA9IHRoaXMuY29sdW1ucyA9IHBhcmFtcy5nZXQoIkNvbHVtbnMiKSB8fCAxOwogICAgdGhpcy5waXhCeXRlcyA9IGNvbG9ycyAqIGJpdHMgKyA3ID4+IDM7CiAgICB0aGlzLnJvd0J5dGVzID0gY29sdW1ucyAqIGNvbG9ycyAqIGJpdHMgKyA3ID4+IDM7CiAgICByZXR1cm4gdGhpczsKICB9CiAgcmVhZEJsb2NrVGlmZigpIHsKICAgIGNvbnN0IHJvd0J5dGVzID0gdGhpcy5yb3dCeXRlczsKICAgIGNvbnN0IGJ1ZmZlckxlbmd0aCA9IHRoaXMuYnVmZmVyTGVuZ3RoOwogICAgY29uc3QgYnVmZmVyID0gdGhpcy5lbnN1cmVCdWZmZXIoYnVmZmVyTGVuZ3RoICsgcm93Qnl0ZXMpOwogICAgY29uc3QgYml0cyA9IHRoaXMuYml0czsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuY29sb3JzOwogICAgY29uc3QgcmF3Qnl0ZXMgPSB0aGlzLnN0ci5nZXRCeXRlcyhyb3dCeXRlcyk7CiAgICB0aGlzLmVvZiA9ICFyYXdCeXRlcy5sZW5ndGg7CiAgICBpZiAodGhpcy5lb2YpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IGluYnVmID0gMCwKICAgICAgb3V0YnVmID0gMDsKICAgIGxldCBpbmJpdHMgPSAwLAogICAgICBvdXRiaXRzID0gMDsKICAgIGxldCBwb3MgPSBidWZmZXJMZW5ndGg7CiAgICBsZXQgaTsKICAgIGlmIChiaXRzID09PSAxICYmIGNvbG9ycyA9PT0gMSkgewogICAgICBmb3IgKGkgPSAwOyBpIDwgcm93Qnl0ZXM7ICsraSkgewogICAgICAgIGxldCBjID0gcmF3Qnl0ZXNbaV0gXiBpbmJ1ZjsKICAgICAgICBjIF49IGMgPj4gMTsKICAgICAgICBjIF49IGMgPj4gMjsKICAgICAgICBjIF49IGMgPj4gNDsKICAgICAgICBpbmJ1ZiA9IChjICYgMSkgPDwgNzsKICAgICAgICBidWZmZXJbcG9zKytdID0gYzsKICAgICAgfQogICAgfSBlbHNlIGlmIChiaXRzID09PSA4KSB7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBjb2xvcnM7ICsraSkgewogICAgICAgIGJ1ZmZlcltwb3MrK10gPSByYXdCeXRlc1tpXTsKICAgICAgfQogICAgICBmb3IgKDsgaSA8IHJvd0J5dGVzOyArK2kpIHsKICAgICAgICBidWZmZXJbcG9zXSA9IGJ1ZmZlcltwb3MgLSBjb2xvcnNdICsgcmF3Qnl0ZXNbaV07CiAgICAgICAgcG9zKys7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoYml0cyA9PT0gMTYpIHsKICAgICAgY29uc3QgYnl0ZXNQZXJQaXhlbCA9IGNvbG9ycyAqIDI7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBieXRlc1BlclBpeGVsOyArK2kpIHsKICAgICAgICBidWZmZXJbcG9zKytdID0gcmF3Qnl0ZXNbaV07CiAgICAgIH0KICAgICAgZm9yICg7IGkgPCByb3dCeXRlczsgaSArPSAyKSB7CiAgICAgICAgY29uc3Qgc3VtID0gKChyYXdCeXRlc1tpXSAmIDB4ZmYpIDw8IDgpICsgKHJhd0J5dGVzW2kgKyAxXSAmIDB4ZmYpICsgKChidWZmZXJbcG9zIC0gYnl0ZXNQZXJQaXhlbF0gJiAweGZmKSA8PCA4KSArIChidWZmZXJbcG9zIC0gYnl0ZXNQZXJQaXhlbCArIDFdICYgMHhmZik7CiAgICAgICAgYnVmZmVyW3BvcysrXSA9IHN1bSA+PiA4ICYgMHhmZjsKICAgICAgICBidWZmZXJbcG9zKytdID0gc3VtICYgMHhmZjsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgY29uc3QgY29tcEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoY29sb3JzICsgMSk7CiAgICAgIGNvbnN0IGJpdE1hc2sgPSAoMSA8PCBiaXRzKSAtIDE7CiAgICAgIGxldCBqID0gMCwKICAgICAgICBrID0gYnVmZmVyTGVuZ3RoOwogICAgICBjb25zdCBjb2x1bW5zID0gdGhpcy5jb2x1bW5zOwogICAgICBmb3IgKGkgPSAwOyBpIDwgY29sdW1uczsgKytpKSB7CiAgICAgICAgZm9yIChsZXQga2sgPSAwOyBrayA8IGNvbG9yczsgKytraykgewogICAgICAgICAgaWYgKGluYml0cyA8IGJpdHMpIHsKICAgICAgICAgICAgaW5idWYgPSBpbmJ1ZiA8PCA4IHwgcmF3Qnl0ZXNbaisrXSAmIDB4ZmY7CiAgICAgICAgICAgIGluYml0cyArPSA4OwogICAgICAgICAgfQogICAgICAgICAgY29tcEFycmF5W2trXSA9IGNvbXBBcnJheVtra10gKyAoaW5idWYgPj4gaW5iaXRzIC0gYml0cykgJiBiaXRNYXNrOwogICAgICAgICAgaW5iaXRzIC09IGJpdHM7CiAgICAgICAgICBvdXRidWYgPSBvdXRidWYgPDwgYml0cyB8IGNvbXBBcnJheVtra107CiAgICAgICAgICBvdXRiaXRzICs9IGJpdHM7CiAgICAgICAgICBpZiAob3V0Yml0cyA+PSA4KSB7CiAgICAgICAgICAgIGJ1ZmZlcltrKytdID0gb3V0YnVmID4+IG91dGJpdHMgLSA4ICYgMHhmZjsKICAgICAgICAgICAgb3V0Yml0cyAtPSA4OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBpZiAob3V0Yml0cyA+IDApIHsKICAgICAgICBidWZmZXJbaysrXSA9IChvdXRidWYgPDwgOCAtIG91dGJpdHMpICsgKGluYnVmICYgKDEgPDwgOCAtIG91dGJpdHMpIC0gMSk7CiAgICAgIH0KICAgIH0KICAgIHRoaXMuYnVmZmVyTGVuZ3RoICs9IHJvd0J5dGVzOwogIH0KICByZWFkQmxvY2tQbmcoKSB7CiAgICBjb25zdCByb3dCeXRlcyA9IHRoaXMucm93Qnl0ZXM7CiAgICBjb25zdCBwaXhCeXRlcyA9IHRoaXMucGl4Qnl0ZXM7CiAgICBjb25zdCBwcmVkaWN0b3IgPSB0aGlzLnN0ci5nZXRCeXRlKCk7CiAgICBjb25zdCByYXdCeXRlcyA9IHRoaXMuc3RyLmdldEJ5dGVzKHJvd0J5dGVzKTsKICAgIHRoaXMuZW9mID0gIXJhd0J5dGVzLmxlbmd0aDsKICAgIGlmICh0aGlzLmVvZikgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlckxlbmd0aDsKICAgIGNvbnN0IGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKGJ1ZmZlckxlbmd0aCArIHJvd0J5dGVzKTsKICAgIGxldCBwcmV2Um93ID0gYnVmZmVyLnN1YmFycmF5KGJ1ZmZlckxlbmd0aCAtIHJvd0J5dGVzLCBidWZmZXJMZW5ndGgpOwogICAgaWYgKHByZXZSb3cubGVuZ3RoID09PSAwKSB7CiAgICAgIHByZXZSb3cgPSBuZXcgVWludDhBcnJheShyb3dCeXRlcyk7CiAgICB9CiAgICBsZXQgaSwKICAgICAgaiA9IGJ1ZmZlckxlbmd0aCwKICAgICAgdXAsCiAgICAgIGM7CiAgICBzd2l0Y2ggKHByZWRpY3RvcikgewogICAgICBjYXNlIDA6CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHJvd0J5dGVzOyArK2kpIHsKICAgICAgICAgIGJ1ZmZlcltqKytdID0gcmF3Qnl0ZXNbaV07CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDE6CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHBpeEJ5dGVzOyArK2kpIHsKICAgICAgICAgIGJ1ZmZlcltqKytdID0gcmF3Qnl0ZXNbaV07CiAgICAgICAgfQogICAgICAgIGZvciAoOyBpIDwgcm93Qnl0ZXM7ICsraSkgewogICAgICAgICAgYnVmZmVyW2pdID0gYnVmZmVyW2ogLSBwaXhCeXRlc10gKyByYXdCeXRlc1tpXSAmIDB4ZmY7CiAgICAgICAgICBqKys7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDI6CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHJvd0J5dGVzOyArK2kpIHsKICAgICAgICAgIGJ1ZmZlcltqKytdID0gcHJldlJvd1tpXSArIHJhd0J5dGVzW2ldICYgMHhmZjsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMzoKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcGl4Qnl0ZXM7ICsraSkgewogICAgICAgICAgYnVmZmVyW2orK10gPSAocHJldlJvd1tpXSA+PiAxKSArIHJhd0J5dGVzW2ldOwogICAgICAgIH0KICAgICAgICBmb3IgKDsgaSA8IHJvd0J5dGVzOyArK2kpIHsKICAgICAgICAgIGJ1ZmZlcltqXSA9IChwcmV2Um93W2ldICsgYnVmZmVyW2ogLSBwaXhCeXRlc10gPj4gMSkgKyByYXdCeXRlc1tpXSAmIDB4ZmY7CiAgICAgICAgICBqKys7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDQ6CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHBpeEJ5dGVzOyArK2kpIHsKICAgICAgICAgIHVwID0gcHJldlJvd1tpXTsKICAgICAgICAgIGMgPSByYXdCeXRlc1tpXTsKICAgICAgICAgIGJ1ZmZlcltqKytdID0gdXAgKyBjOwogICAgICAgIH0KICAgICAgICBmb3IgKDsgaSA8IHJvd0J5dGVzOyArK2kpIHsKICAgICAgICAgIHVwID0gcHJldlJvd1tpXTsKICAgICAgICAgIGNvbnN0IHVwTGVmdCA9IHByZXZSb3dbaSAtIHBpeEJ5dGVzXTsKICAgICAgICAgIGNvbnN0IGxlZnQgPSBidWZmZXJbaiAtIHBpeEJ5dGVzXTsKICAgICAgICAgIGNvbnN0IHAgPSBsZWZ0ICsgdXAgLSB1cExlZnQ7CiAgICAgICAgICBsZXQgcGEgPSBwIC0gbGVmdDsKICAgICAgICAgIGlmIChwYSA8IDApIHsKICAgICAgICAgICAgcGEgPSAtcGE7CiAgICAgICAgICB9CiAgICAgICAgICBsZXQgcGIgPSBwIC0gdXA7CiAgICAgICAgICBpZiAocGIgPCAwKSB7CiAgICAgICAgICAgIHBiID0gLXBiOwogICAgICAgICAgfQogICAgICAgICAgbGV0IHBjID0gcCAtIHVwTGVmdDsKICAgICAgICAgIGlmIChwYyA8IDApIHsKICAgICAgICAgICAgcGMgPSAtcGM7CiAgICAgICAgICB9CiAgICAgICAgICBjID0gcmF3Qnl0ZXNbaV07CiAgICAgICAgICBpZiAocGEgPD0gcGIgJiYgcGEgPD0gcGMpIHsKICAgICAgICAgICAgYnVmZmVyW2orK10gPSBsZWZ0ICsgYzsKICAgICAgICAgIH0gZWxzZSBpZiAocGIgPD0gcGMpIHsKICAgICAgICAgICAgYnVmZmVyW2orK10gPSB1cCArIGM7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBidWZmZXJbaisrXSA9IHVwTGVmdCArIGM7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgVW5zdXBwb3J0ZWQgcHJlZGljdG9yOiAke3ByZWRpY3Rvcn1gKTsKICAgIH0KICAgIHRoaXMuYnVmZmVyTGVuZ3RoICs9IHJvd0J5dGVzOwogIH0KfQpleHBvcnRzLlByZWRpY3RvclN0cmVhbSA9IFByZWRpY3RvclN0cmVhbTsKCi8qKiovIH0pLAovKiAxNjggKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlJ1bkxlbmd0aFN0cmVhbSA9IHZvaWQgMDsKdmFyIF9kZWNvZGVfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTMpOwpjbGFzcyBSdW5MZW5ndGhTdHJlYW0gZXh0ZW5kcyBfZGVjb2RlX3N0cmVhbS5EZWNvZGVTdHJlYW0gewogIGNvbnN0cnVjdG9yKHN0ciwgbWF5YmVMZW5ndGgpIHsKICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyID0gc3RyOwogICAgdGhpcy5kaWN0ID0gc3RyLmRpY3Q7CiAgfQogIHJlYWRCbG9jaygpIHsKICAgIGNvbnN0IHJlcGVhdEhlYWRlciA9IHRoaXMuc3RyLmdldEJ5dGVzKDIpOwogICAgaWYgKCFyZXBlYXRIZWFkZXIgfHwgcmVwZWF0SGVhZGVyLmxlbmd0aCA8IDIgfHwgcmVwZWF0SGVhZGVyWzBdID09PSAxMjgpIHsKICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgYnVmZmVyOwogICAgbGV0IGJ1ZmZlckxlbmd0aCA9IHRoaXMuYnVmZmVyTGVuZ3RoOwogICAgbGV0IG4gPSByZXBlYXRIZWFkZXJbMF07CiAgICBpZiAobiA8IDEyOCkgewogICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihidWZmZXJMZW5ndGggKyBuICsgMSk7CiAgICAgIGJ1ZmZlcltidWZmZXJMZW5ndGgrK10gPSByZXBlYXRIZWFkZXJbMV07CiAgICAgIGlmIChuID4gMCkgewogICAgICAgIGNvbnN0IHNvdXJjZSA9IHRoaXMuc3RyLmdldEJ5dGVzKG4pOwogICAgICAgIGJ1ZmZlci5zZXQoc291cmNlLCBidWZmZXJMZW5ndGgpOwogICAgICAgIGJ1ZmZlckxlbmd0aCArPSBuOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBuID0gMjU3IC0gbjsKICAgICAgY29uc3QgYiA9IHJlcGVhdEhlYWRlclsxXTsKICAgICAgYnVmZmVyID0gdGhpcy5lbnN1cmVCdWZmZXIoYnVmZmVyTGVuZ3RoICsgbiArIDEpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgIGJ1ZmZlcltidWZmZXJMZW5ndGgrK10gPSBiOwogICAgICB9CiAgICB9CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGJ1ZmZlckxlbmd0aDsKICB9Cn0KZXhwb3J0cy5SdW5MZW5ndGhTdHJlYW0gPSBSdW5MZW5ndGhTdHJlYW07CgovKioqLyB9KSwKLyogMTY5ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5Gb250ID0gZXhwb3J0cy5FcnJvckZvbnQgPSB2b2lkIDA7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CnZhciBfY2ZmX3BhcnNlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTcwKTsKdmFyIF9mb250c191dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTczKTsKdmFyIF91bmljb2RlID0gX193X3BkZmpzX3JlcXVpcmVfXygxNzUpOwp2YXIgX2dseXBobGlzdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTc0KTsKdmFyIF9lbmNvZGluZ3MgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE3Mik7CnZhciBfc3RhbmRhcmRfZm9udHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE3Nik7CnZhciBfdG9fdW5pY29kZV9tYXAgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE3Nyk7CnZhciBfY2ZmX2ZvbnQgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE3OCk7CnZhciBfZm9udF9yZW5kZXJlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTc5KTsKdmFyIF9tZXRyaWNzID0gX193X3BkZmpzX3JlcXVpcmVfXygxODApOwp2YXIgX2dseWYgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE4MSk7CnZhciBfY21hcCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTUwKTsKdmFyIF9vcGVudHlwZV9maWxlX2J1aWxkZXIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE4Mik7CnZhciBfY29yZV91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTM5KTsKdmFyIF9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0NCk7CnZhciBfdHlwZTFfZm9udCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTgzKTsKY29uc3QgUFJJVkFURV9VU0VfQVJFQVMgPSBbWzB4ZTAwMCwgMHhmOGZmXSwgWzB4MTAwMDAwLCAweDEwZmZmZF1dOwpjb25zdCBQREZfR0xZUEhfU1BBQ0VfVU5JVFMgPSAxMDAwOwpjb25zdCBFWFBPUlRfREFUQV9QUk9QRVJUSUVTID0gWyJhc2NlbnQiLCAiYmJveCIsICJibGFjayIsICJib2xkIiwgImNoYXJQcm9jT3BlcmF0b3JMaXN0IiwgImNvbXBvc2l0ZSIsICJjc3NGb250SW5mbyIsICJkYXRhIiwgImRlZmF1bHRWTWV0cmljcyIsICJkZWZhdWx0V2lkdGgiLCAiZGVzY2VudCIsICJmYWxsYmFja05hbWUiLCAiZm9udE1hdHJpeCIsICJpc0ludmFsaWRQREZqc0ZvbnQiLCAiaXNUeXBlM0ZvbnQiLCAiaXRhbGljIiwgImxvYWRlZE5hbWUiLCAibWltZXR5cGUiLCAibWlzc2luZ0ZpbGUiLCAibmFtZSIsICJyZW1lYXN1cmUiLCAic3VidHlwZSIsICJ0eXBlIiwgInZlcnRpY2FsIl07CmNvbnN0IEVYUE9SVF9EQVRBX0VYVFJBX1BST1BFUlRJRVMgPSBbImNNYXAiLCAiZGVmYXVsdEVuY29kaW5nIiwgImRpZmZlcmVuY2VzIiwgImlzTW9ub3NwYWNlIiwgImlzU2VyaWZGb250IiwgImlzU3ltYm9saWNGb250IiwgInNlYWNNYXAiLCAidG9Gb250Q2hhciIsICJ0b1VuaWNvZGUiLCAidm1ldHJpY3MiLCAid2lkdGhzIl07CmZ1bmN0aW9uIGFkanVzdFdpZHRocyhwcm9wZXJ0aWVzKSB7CiAgaWYgKCFwcm9wZXJ0aWVzLmZvbnRNYXRyaXgpIHsKICAgIHJldHVybjsKICB9CiAgaWYgKHByb3BlcnRpZXMuZm9udE1hdHJpeFswXSA9PT0gX3V0aWwuRk9OVF9JREVOVElUWV9NQVRSSVhbMF0pIHsKICAgIHJldHVybjsKICB9CiAgY29uc3Qgc2NhbGUgPSAwLjAwMSAvIHByb3BlcnRpZXMuZm9udE1hdHJpeFswXTsKICBjb25zdCBnbHlwaHNXaWR0aHMgPSBwcm9wZXJ0aWVzLndpZHRoczsKICBmb3IgKGNvbnN0IGdseXBoIGluIGdseXBoc1dpZHRocykgewogICAgZ2x5cGhzV2lkdGhzW2dseXBoXSAqPSBzY2FsZTsKICB9CiAgcHJvcGVydGllcy5kZWZhdWx0V2lkdGggKj0gc2NhbGU7Cn0KZnVuY3Rpb24gYWRqdXN0VHJ1ZVR5cGVUb1VuaWNvZGUocHJvcGVydGllcywgaXNTeW1ib2xpY0ZvbnQsIG5hbWVSZWNvcmRzKSB7CiAgaWYgKHByb3BlcnRpZXMuaXNJbnRlcm5hbEZvbnQpIHsKICAgIHJldHVybjsKICB9CiAgaWYgKHByb3BlcnRpZXMuaGFzSW5jbHVkZWRUb1VuaWNvZGVNYXApIHsKICAgIHJldHVybjsKICB9CiAgaWYgKHByb3BlcnRpZXMuaGFzRW5jb2RpbmcpIHsKICAgIHJldHVybjsKICB9CiAgaWYgKHByb3BlcnRpZXMudG9Vbmljb2RlIGluc3RhbmNlb2YgX3RvX3VuaWNvZGVfbWFwLklkZW50aXR5VG9Vbmljb2RlTWFwKSB7CiAgICByZXR1cm47CiAgfQogIGlmICghaXNTeW1ib2xpY0ZvbnQpIHsKICAgIHJldHVybjsKICB9CiAgaWYgKG5hbWVSZWNvcmRzLmxlbmd0aCA9PT0gMCkgewogICAgcmV0dXJuOwogIH0KICBpZiAocHJvcGVydGllcy5kZWZhdWx0RW5jb2RpbmcgPT09IF9lbmNvZGluZ3MuV2luQW5zaUVuY29kaW5nKSB7CiAgICByZXR1cm47CiAgfQogIGZvciAoY29uc3QgciBvZiBuYW1lUmVjb3JkcykgewogICAgaWYgKCFpc1dpbk5hbWVSZWNvcmQocikpIHsKICAgICAgcmV0dXJuOwogICAgfQogIH0KICBjb25zdCBlbmNvZGluZyA9IF9lbmNvZGluZ3MuV2luQW5zaUVuY29kaW5nOwogIGNvbnN0IHRvVW5pY29kZSA9IFtdLAogICAgZ2x5cGhzVW5pY29kZU1hcCA9ICgwLCBfZ2x5cGhsaXN0LmdldEdseXBoc1VuaWNvZGUpKCk7CiAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBlbmNvZGluZykgewogICAgY29uc3QgZ2x5cGhOYW1lID0gZW5jb2RpbmdbY2hhckNvZGVdOwogICAgaWYgKGdseXBoTmFtZSA9PT0gIiIpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBjb25zdCB1bmljb2RlID0gZ2x5cGhzVW5pY29kZU1hcFtnbHlwaE5hbWVdOwogICAgaWYgKHVuaWNvZGUgPT09IHVuZGVmaW5lZCkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIHRvVW5pY29kZVtjaGFyQ29kZV0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHVuaWNvZGUpOwogIH0KICBpZiAodG9Vbmljb2RlLmxlbmd0aCA+IDApIHsKICAgIHByb3BlcnRpZXMudG9Vbmljb2RlLmFtZW5kKHRvVW5pY29kZSk7CiAgfQp9CmZ1bmN0aW9uIGFkanVzdFR5cGUxVG9Vbmljb2RlKHByb3BlcnRpZXMsIGJ1aWx0SW5FbmNvZGluZykgewogIGlmIChwcm9wZXJ0aWVzLmlzSW50ZXJuYWxGb250KSB7CiAgICByZXR1cm47CiAgfQogIGlmIChwcm9wZXJ0aWVzLmhhc0luY2x1ZGVkVG9Vbmljb2RlTWFwKSB7CiAgICByZXR1cm47CiAgfQogIGlmIChidWlsdEluRW5jb2RpbmcgPT09IHByb3BlcnRpZXMuZGVmYXVsdEVuY29kaW5nKSB7CiAgICByZXR1cm47CiAgfQogIGlmIChwcm9wZXJ0aWVzLnRvVW5pY29kZSBpbnN0YW5jZW9mIF90b191bmljb2RlX21hcC5JZGVudGl0eVRvVW5pY29kZU1hcCkgewogICAgcmV0dXJuOwogIH0KICBjb25zdCB0b1VuaWNvZGUgPSBbXSwKICAgIGdseXBoc1VuaWNvZGVNYXAgPSAoMCwgX2dseXBobGlzdC5nZXRHbHlwaHNVbmljb2RlKSgpOwogIGZvciAoY29uc3QgY2hhckNvZGUgaW4gYnVpbHRJbkVuY29kaW5nKSB7CiAgICBpZiAocHJvcGVydGllcy5oYXNFbmNvZGluZykgewogICAgICBpZiAocHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lIHx8IHByb3BlcnRpZXMuZGlmZmVyZW5jZXNbY2hhckNvZGVdICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgfQogICAgY29uc3QgZ2x5cGhOYW1lID0gYnVpbHRJbkVuY29kaW5nW2NoYXJDb2RlXTsKICAgIGNvbnN0IHVuaWNvZGUgPSAoMCwgX3VuaWNvZGUuZ2V0VW5pY29kZUZvckdseXBoKShnbHlwaE5hbWUsIGdseXBoc1VuaWNvZGVNYXApOwogICAgaWYgKHVuaWNvZGUgIT09IC0xKSB7CiAgICAgIHRvVW5pY29kZVtjaGFyQ29kZV0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHVuaWNvZGUpOwogICAgfQogIH0KICBpZiAodG9Vbmljb2RlLmxlbmd0aCA+IDApIHsKICAgIHByb3BlcnRpZXMudG9Vbmljb2RlLmFtZW5kKHRvVW5pY29kZSk7CiAgfQp9CmZ1bmN0aW9uIGFtZW5kRmFsbGJhY2tUb1VuaWNvZGUocHJvcGVydGllcykgewogIGlmICghcHJvcGVydGllcy5mYWxsYmFja1RvVW5pY29kZSkgewogICAgcmV0dXJuOwogIH0KICBpZiAocHJvcGVydGllcy50b1VuaWNvZGUgaW5zdGFuY2VvZiBfdG9fdW5pY29kZV9tYXAuSWRlbnRpdHlUb1VuaWNvZGVNYXApIHsKICAgIHJldHVybjsKICB9CiAgY29uc3QgdG9Vbmljb2RlID0gW107CiAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBwcm9wZXJ0aWVzLmZhbGxiYWNrVG9Vbmljb2RlKSB7CiAgICBpZiAocHJvcGVydGllcy50b1VuaWNvZGUuaGFzKGNoYXJDb2RlKSkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIHRvVW5pY29kZVtjaGFyQ29kZV0gPSBwcm9wZXJ0aWVzLmZhbGxiYWNrVG9Vbmljb2RlW2NoYXJDb2RlXTsKICB9CiAgaWYgKHRvVW5pY29kZS5sZW5ndGggPiAwKSB7CiAgICBwcm9wZXJ0aWVzLnRvVW5pY29kZS5hbWVuZCh0b1VuaWNvZGUpOwogIH0KfQpjbGFzcyBHbHlwaCB7CiAgY29uc3RydWN0b3Iob3JpZ2luYWxDaGFyQ29kZSwgZm9udENoYXIsIHVuaWNvZGUsIGFjY2VudCwgd2lkdGgsIHZtZXRyaWMsIG9wZXJhdG9yTGlzdElkLCBpc1NwYWNlLCBpc0luRm9udCkgewogICAgdGhpcy5vcmlnaW5hbENoYXJDb2RlID0gb3JpZ2luYWxDaGFyQ29kZTsKICAgIHRoaXMuZm9udENoYXIgPSBmb250Q2hhcjsKICAgIHRoaXMudW5pY29kZSA9IHVuaWNvZGU7CiAgICB0aGlzLmFjY2VudCA9IGFjY2VudDsKICAgIHRoaXMud2lkdGggPSB3aWR0aDsKICAgIHRoaXMudm1ldHJpYyA9IHZtZXRyaWM7CiAgICB0aGlzLm9wZXJhdG9yTGlzdElkID0gb3BlcmF0b3JMaXN0SWQ7CiAgICB0aGlzLmlzU3BhY2UgPSBpc1NwYWNlOwogICAgdGhpcy5pc0luRm9udCA9IGlzSW5Gb250OwogIH0KICBnZXQgY2F0ZWdvcnkoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImNhdGVnb3J5IiwgKDAsIF91bmljb2RlLmdldENoYXJVbmljb2RlQ2F0ZWdvcnkpKHRoaXMudW5pY29kZSksIHRydWUpOwogIH0KICBnZXQgbm9ybWFsaXplZFVuaWNvZGUoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIm5vcm1hbGl6ZWRVbmljb2RlIiwgKDAsIF91bmljb2RlLnJldmVyc2VJZlJ0bCkoR2x5cGguX05vcm1hbGl6ZWRVbmljb2Rlc1t0aGlzLnVuaWNvZGVdIHx8IHRoaXMudW5pY29kZSksIHRydWUpOwogIH0KICBzdGF0aWMgZ2V0IF9Ob3JtYWxpemVkVW5pY29kZXMoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIl9Ob3JtYWxpemVkVW5pY29kZXMiLCAoMCwgX3VuaWNvZGUuZ2V0Tm9ybWFsaXplZFVuaWNvZGVzKSgpKTsKICB9Cn0KZnVuY3Rpb24gaW50MTYoYjAsIGIxKSB7CiAgcmV0dXJuIChiMCA8PCA4KSArIGIxOwp9CmZ1bmN0aW9uIHdyaXRlU2lnbmVkSW50MTYoYnl0ZXMsIGluZGV4LCB2YWx1ZSkgewogIGJ5dGVzW2luZGV4ICsgMV0gPSB2YWx1ZTsKICBieXRlc1tpbmRleF0gPSB2YWx1ZSA+Pj4gODsKfQpmdW5jdGlvbiBzaWduZWRJbnQxNihiMCwgYjEpIHsKICBjb25zdCB2YWx1ZSA9IChiMCA8PCA4KSArIGIxOwogIHJldHVybiB2YWx1ZSAmIDEgPDwgMTUgPyB2YWx1ZSAtIDB4MTAwMDAgOiB2YWx1ZTsKfQpmdW5jdGlvbiBpbnQzMihiMCwgYjEsIGIyLCBiMykgewogIHJldHVybiAoYjAgPDwgMjQpICsgKGIxIDw8IDE2KSArIChiMiA8PCA4KSArIGIzOwp9CmZ1bmN0aW9uIHN0cmluZzE2KHZhbHVlKSB7CiAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUodmFsdWUgPj4gOCAmIDB4ZmYsIHZhbHVlICYgMHhmZik7Cn0KZnVuY3Rpb24gc2FmZVN0cmluZzE2KHZhbHVlKSB7CiAgaWYgKHZhbHVlID4gMHg3ZmZmKSB7CiAgICB2YWx1ZSA9IDB4N2ZmZjsKICB9IGVsc2UgaWYgKHZhbHVlIDwgLTB4ODAwMCkgewogICAgdmFsdWUgPSAtMHg4MDAwOwogIH0KICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSh2YWx1ZSA+PiA4ICYgMHhmZiwgdmFsdWUgJiAweGZmKTsKfQpmdW5jdGlvbiBpc1RydWVUeXBlRmlsZShmaWxlKSB7CiAgY29uc3QgaGVhZGVyID0gZmlsZS5wZWVrQnl0ZXMoNCk7CiAgcmV0dXJuICgwLCBfY29yZV91dGlscy5yZWFkVWludDMyKShoZWFkZXIsIDApID09PSAweDAwMDEwMDAwIHx8ICgwLCBfdXRpbC5ieXRlc1RvU3RyaW5nKShoZWFkZXIpID09PSAidHJ1ZSI7Cn0KZnVuY3Rpb24gaXNUcnVlVHlwZUNvbGxlY3Rpb25GaWxlKGZpbGUpIHsKICBjb25zdCBoZWFkZXIgPSBmaWxlLnBlZWtCeXRlcyg0KTsKICByZXR1cm4gKDAsIF91dGlsLmJ5dGVzVG9TdHJpbmcpKGhlYWRlcikgPT09ICJ0dGNmIjsKfQpmdW5jdGlvbiBpc09wZW5UeXBlRmlsZShmaWxlKSB7CiAgY29uc3QgaGVhZGVyID0gZmlsZS5wZWVrQnl0ZXMoNCk7CiAgcmV0dXJuICgwLCBfdXRpbC5ieXRlc1RvU3RyaW5nKShoZWFkZXIpID09PSAiT1RUTyI7Cn0KZnVuY3Rpb24gaXNUeXBlMUZpbGUoZmlsZSkgewogIGNvbnN0IGhlYWRlciA9IGZpbGUucGVla0J5dGVzKDIpOwogIGlmIChoZWFkZXJbMF0gPT09IDB4MjUgJiYgaGVhZGVyWzFdID09PSAweDIxKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgaWYgKGhlYWRlclswXSA9PT0gMHg4MCAmJiBoZWFkZXJbMV0gPT09IDB4MDEpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICByZXR1cm4gZmFsc2U7Cn0KZnVuY3Rpb24gaXNDRkZGaWxlKGZpbGUpIHsKICBjb25zdCBoZWFkZXIgPSBmaWxlLnBlZWtCeXRlcyg0KTsKICBpZiAoaGVhZGVyWzBdID49IDEgJiYgaGVhZGVyWzNdID49IDEgJiYgaGVhZGVyWzNdIDw9IDQpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICByZXR1cm4gZmFsc2U7Cn0KZnVuY3Rpb24gZ2V0Rm9udEZpbGVUeXBlKGZpbGUsIF9yZWYpIHsKICBsZXQgewogICAgdHlwZSwKICAgIHN1YnR5cGUsCiAgICBjb21wb3NpdGUKICB9ID0gX3JlZjsKICBsZXQgZmlsZVR5cGUsIGZpbGVTdWJ0eXBlOwogIGlmIChpc1RydWVUeXBlRmlsZShmaWxlKSB8fCBpc1RydWVUeXBlQ29sbGVjdGlvbkZpbGUoZmlsZSkpIHsKICAgIGlmIChjb21wb3NpdGUpIHsKICAgICAgZmlsZVR5cGUgPSAiQ0lERm9udFR5cGUyIjsKICAgIH0gZWxzZSB7CiAgICAgIGZpbGVUeXBlID0gIlRydWVUeXBlIjsKICAgIH0KICB9IGVsc2UgaWYgKGlzT3BlblR5cGVGaWxlKGZpbGUpKSB7CiAgICBpZiAoY29tcG9zaXRlKSB7CiAgICAgIGZpbGVUeXBlID0gIkNJREZvbnRUeXBlMiI7CiAgICB9IGVsc2UgewogICAgICBmaWxlVHlwZSA9ICJPcGVuVHlwZSI7CiAgICB9CiAgfSBlbHNlIGlmIChpc1R5cGUxRmlsZShmaWxlKSkgewogICAgaWYgKGNvbXBvc2l0ZSkgewogICAgICBmaWxlVHlwZSA9ICJDSURGb250VHlwZTAiOwogICAgfSBlbHNlIHsKICAgICAgZmlsZVR5cGUgPSB0eXBlID09PSAiTU1UeXBlMSIgPyAiTU1UeXBlMSIgOiAiVHlwZTEiOwogICAgfQogIH0gZWxzZSBpZiAoaXNDRkZGaWxlKGZpbGUpKSB7CiAgICBpZiAoY29tcG9zaXRlKSB7CiAgICAgIGZpbGVUeXBlID0gIkNJREZvbnRUeXBlMCI7CiAgICAgIGZpbGVTdWJ0eXBlID0gIkNJREZvbnRUeXBlMEMiOwogICAgfSBlbHNlIHsKICAgICAgZmlsZVR5cGUgPSB0eXBlID09PSAiTU1UeXBlMSIgPyAiTU1UeXBlMSIgOiAiVHlwZTEiOwogICAgICBmaWxlU3VidHlwZSA9ICJUeXBlMUMiOwogICAgfQogIH0gZWxzZSB7CiAgICAoMCwgX3V0aWwud2FybikoImdldEZvbnRGaWxlVHlwZTogVW5hYmxlIHRvIGRldGVjdCBjb3JyZWN0IGZvbnQgZmlsZSBUeXBlL1N1YnR5cGUuIik7CiAgICBmaWxlVHlwZSA9IHR5cGU7CiAgICBmaWxlU3VidHlwZSA9IHN1YnR5cGU7CiAgfQogIHJldHVybiBbZmlsZVR5cGUsIGZpbGVTdWJ0eXBlXTsKfQpmdW5jdGlvbiBhcHBseVN0YW5kYXJkRm9udEdseXBoTWFwKG1hcCwgZ2x5cGhNYXApIHsKICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIGdseXBoTWFwKSB7CiAgICBtYXBbK2NoYXJDb2RlXSA9IGdseXBoTWFwW2NoYXJDb2RlXTsKICB9Cn0KZnVuY3Rpb24gYnVpbGRUb0ZvbnRDaGFyKGVuY29kaW5nLCBnbHlwaHNVbmljb2RlTWFwLCBkaWZmZXJlbmNlcykgewogIGNvbnN0IHRvRm9udENoYXIgPSBbXTsKICBsZXQgdW5pY29kZTsKICBmb3IgKGxldCBpID0gMCwgaWkgPSBlbmNvZGluZy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICB1bmljb2RlID0gKDAsIF91bmljb2RlLmdldFVuaWNvZGVGb3JHbHlwaCkoZW5jb2RpbmdbaV0sIGdseXBoc1VuaWNvZGVNYXApOwogICAgaWYgKHVuaWNvZGUgIT09IC0xKSB7CiAgICAgIHRvRm9udENoYXJbaV0gPSB1bmljb2RlOwogICAgfQogIH0KICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIGRpZmZlcmVuY2VzKSB7CiAgICB1bmljb2RlID0gKDAsIF91bmljb2RlLmdldFVuaWNvZGVGb3JHbHlwaCkoZGlmZmVyZW5jZXNbY2hhckNvZGVdLCBnbHlwaHNVbmljb2RlTWFwKTsKICAgIGlmICh1bmljb2RlICE9PSAtMSkgewogICAgICB0b0ZvbnRDaGFyWytjaGFyQ29kZV0gPSB1bmljb2RlOwogICAgfQogIH0KICByZXR1cm4gdG9Gb250Q2hhcjsKfQpmdW5jdGlvbiBpc01hY05hbWVSZWNvcmQocikgewogIHJldHVybiByLnBsYXRmb3JtID09PSAxICYmIHIuZW5jb2RpbmcgPT09IDAgJiYgci5sYW5ndWFnZSA9PT0gMDsKfQpmdW5jdGlvbiBpc1dpbk5hbWVSZWNvcmQocikgewogIHJldHVybiByLnBsYXRmb3JtID09PSAzICYmIHIuZW5jb2RpbmcgPT09IDEgJiYgci5sYW5ndWFnZSA9PT0gMHg0MDk7Cn0KZnVuY3Rpb24gY29udmVydENpZFN0cmluZyhjaGFyQ29kZSwgY2lkKSB7CiAgbGV0IHNob3VsZFRocm93ID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBmYWxzZTsKICBzd2l0Y2ggKGNpZC5sZW5ndGgpIHsKICAgIGNhc2UgMToKICAgICAgcmV0dXJuIGNpZC5jaGFyQ29kZUF0KDApOwogICAgY2FzZSAyOgogICAgICByZXR1cm4gY2lkLmNoYXJDb2RlQXQoMCkgPDwgOCB8IGNpZC5jaGFyQ29kZUF0KDEpOwogIH0KICBjb25zdCBtc2cgPSBgVW5zdXBwb3J0ZWQgQ0lEIHN0cmluZyAoY2hhckNvZGUgJHtjaGFyQ29kZX0pOiAiJHtjaWR9Ii5gOwogIGlmIChzaG91bGRUaHJvdykgewogICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKG1zZyk7CiAgfQogICgwLCBfdXRpbC53YXJuKShtc2cpOwogIHJldHVybiBjaWQ7Cn0KZnVuY3Rpb24gYWRqdXN0TWFwcGluZyhjaGFyQ29kZVRvR2x5cGhJZCwgaGFzR2x5cGgsIG5ld0dseXBoWmVyb0lkLCB0b1VuaWNvZGUpIHsKICBjb25zdCBuZXdNYXAgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIGNvbnN0IHRvVW5pY29kZUV4dHJhTWFwID0gbmV3IE1hcCgpOwogIGNvbnN0IHRvRm9udENoYXIgPSBbXTsKICBjb25zdCB1c2VkR2x5cGhJZHMgPSBuZXcgU2V0KCk7CiAgbGV0IHByaXZhdGVVc2VBcmVhSW5kZXggPSAwOwogIGNvbnN0IHByaXZhdGVVc2VPZmZldFN0YXJ0ID0gUFJJVkFURV9VU0VfQVJFQVNbcHJpdmF0ZVVzZUFyZWFJbmRleF1bMF07CiAgbGV0IG5leHRBdmFpbGFibGVGb250Q2hhckNvZGUgPSBwcml2YXRlVXNlT2ZmZXRTdGFydDsKICBsZXQgcHJpdmF0ZVVzZU9mZmV0RW5kID0gUFJJVkFURV9VU0VfQVJFQVNbcHJpdmF0ZVVzZUFyZWFJbmRleF1bMV07CiAgZm9yIChsZXQgb3JpZ2luYWxDaGFyQ29kZSBpbiBjaGFyQ29kZVRvR2x5cGhJZCkgewogICAgb3JpZ2luYWxDaGFyQ29kZSB8PSAwOwogICAgbGV0IGdseXBoSWQgPSBjaGFyQ29kZVRvR2x5cGhJZFtvcmlnaW5hbENoYXJDb2RlXTsKICAgIGlmICghaGFzR2x5cGgoZ2x5cGhJZCkpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBpZiAobmV4dEF2YWlsYWJsZUZvbnRDaGFyQ29kZSA+IHByaXZhdGVVc2VPZmZldEVuZCkgewogICAgICBwcml2YXRlVXNlQXJlYUluZGV4Kys7CiAgICAgIGlmIChwcml2YXRlVXNlQXJlYUluZGV4ID49IFBSSVZBVEVfVVNFX0FSRUFTLmxlbmd0aCkgewogICAgICAgICgwLCBfdXRpbC53YXJuKSgiUmFuIG91dCBvZiBzcGFjZSBpbiBmb250IHByaXZhdGUgdXNlIGFyZWEuIik7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgbmV4dEF2YWlsYWJsZUZvbnRDaGFyQ29kZSA9IFBSSVZBVEVfVVNFX0FSRUFTW3ByaXZhdGVVc2VBcmVhSW5kZXhdWzBdOwogICAgICBwcml2YXRlVXNlT2ZmZXRFbmQgPSBQUklWQVRFX1VTRV9BUkVBU1twcml2YXRlVXNlQXJlYUluZGV4XVsxXTsKICAgIH0KICAgIGNvbnN0IGZvbnRDaGFyQ29kZSA9IG5leHRBdmFpbGFibGVGb250Q2hhckNvZGUrKzsKICAgIGlmIChnbHlwaElkID09PSAwKSB7CiAgICAgIGdseXBoSWQgPSBuZXdHbHlwaFplcm9JZDsKICAgIH0KICAgIGxldCB1bmljb2RlID0gdG9Vbmljb2RlLmdldChvcmlnaW5hbENoYXJDb2RlKTsKICAgIGlmICh0eXBlb2YgdW5pY29kZSA9PT0gInN0cmluZyIpIHsKICAgICAgdW5pY29kZSA9IHVuaWNvZGUuY29kZVBvaW50QXQoMCk7CiAgICB9CiAgICBpZiAodW5pY29kZSAmJiB1bmljb2RlIDwgcHJpdmF0ZVVzZU9mZmV0U3RhcnQgJiYgIXVzZWRHbHlwaElkcy5oYXMoZ2x5cGhJZCkpIHsKICAgICAgdG9Vbmljb2RlRXh0cmFNYXAuc2V0KHVuaWNvZGUsIGdseXBoSWQpOwogICAgICB1c2VkR2x5cGhJZHMuYWRkKGdseXBoSWQpOwogICAgfQogICAgbmV3TWFwW2ZvbnRDaGFyQ29kZV0gPSBnbHlwaElkOwogICAgdG9Gb250Q2hhcltvcmlnaW5hbENoYXJDb2RlXSA9IGZvbnRDaGFyQ29kZTsKICB9CiAgcmV0dXJuIHsKICAgIHRvRm9udENoYXIsCiAgICBjaGFyQ29kZVRvR2x5cGhJZDogbmV3TWFwLAogICAgdG9Vbmljb2RlRXh0cmFNYXAsCiAgICBuZXh0QXZhaWxhYmxlRm9udENoYXJDb2RlCiAgfTsKfQpmdW5jdGlvbiBnZXRSYW5nZXMoZ2x5cGhzLCB0b1VuaWNvZGVFeHRyYU1hcCwgbnVtR2x5cGhzKSB7CiAgY29uc3QgY29kZXMgPSBbXTsKICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIGdseXBocykgewogICAgaWYgKGdseXBoc1tjaGFyQ29kZV0gPj0gbnVtR2x5cGhzKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgY29kZXMucHVzaCh7CiAgICAgIGZvbnRDaGFyQ29kZTogY2hhckNvZGUgfCAwLAogICAgICBnbHlwaElkOiBnbHlwaHNbY2hhckNvZGVdCiAgICB9KTsKICB9CiAgaWYgKHRvVW5pY29kZUV4dHJhTWFwKSB7CiAgICBmb3IgKGNvbnN0IFt1bmljb2RlLCBnbHlwaElkXSBvZiB0b1VuaWNvZGVFeHRyYU1hcCkgewogICAgICBpZiAoZ2x5cGhJZCA+PSBudW1HbHlwaHMpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb2Rlcy5wdXNoKHsKICAgICAgICBmb250Q2hhckNvZGU6IHVuaWNvZGUsCiAgICAgICAgZ2x5cGhJZAogICAgICB9KTsKICAgIH0KICB9CiAgaWYgKGNvZGVzLmxlbmd0aCA9PT0gMCkgewogICAgY29kZXMucHVzaCh7CiAgICAgIGZvbnRDaGFyQ29kZTogMCwKICAgICAgZ2x5cGhJZDogMAogICAgfSk7CiAgfQogIGNvZGVzLnNvcnQoZnVuY3Rpb24gZm9udEdldFJhbmdlc1NvcnQoYSwgYikgewogICAgcmV0dXJuIGEuZm9udENoYXJDb2RlIC0gYi5mb250Q2hhckNvZGU7CiAgfSk7CiAgY29uc3QgcmFuZ2VzID0gW107CiAgY29uc3QgbGVuZ3RoID0gY29kZXMubGVuZ3RoOwogIGZvciAobGV0IG4gPSAwOyBuIDwgbGVuZ3RoOykgewogICAgY29uc3Qgc3RhcnQgPSBjb2Rlc1tuXS5mb250Q2hhckNvZGU7CiAgICBjb25zdCBjb2RlSW5kaWNlcyA9IFtjb2Rlc1tuXS5nbHlwaElkXTsKICAgICsrbjsKICAgIGxldCBlbmQgPSBzdGFydDsKICAgIHdoaWxlIChuIDwgbGVuZ3RoICYmIGVuZCArIDEgPT09IGNvZGVzW25dLmZvbnRDaGFyQ29kZSkgewogICAgICBjb2RlSW5kaWNlcy5wdXNoKGNvZGVzW25dLmdseXBoSWQpOwogICAgICArK2VuZDsKICAgICAgKytuOwogICAgICBpZiAoZW5kID09PSAweGZmZmYpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgcmFuZ2VzLnB1c2goW3N0YXJ0LCBlbmQsIGNvZGVJbmRpY2VzXSk7CiAgfQogIHJldHVybiByYW5nZXM7Cn0KZnVuY3Rpb24gY3JlYXRlQ21hcFRhYmxlKGdseXBocywgdG9Vbmljb2RlRXh0cmFNYXAsIG51bUdseXBocykgewogIGNvbnN0IHJhbmdlcyA9IGdldFJhbmdlcyhnbHlwaHMsIHRvVW5pY29kZUV4dHJhTWFwLCBudW1HbHlwaHMpOwogIGNvbnN0IG51bVRhYmxlcyA9IHJhbmdlcy5hdCgtMSlbMV0gPiAweGZmZmYgPyAyIDogMTsKICBsZXQgY21hcCA9ICJceDAwXHgwMCIgKyBzdHJpbmcxNihudW1UYWJsZXMpICsgIlx4MDBceDAzIiArICJceDAwXHgwMSIgKyAoMCwgX3V0aWwuc3RyaW5nMzIpKDQgKyBudW1UYWJsZXMgKiA4KTsKICBsZXQgaSwgaWksIGosIGpqOwogIGZvciAoaSA9IHJhbmdlcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgewogICAgaWYgKHJhbmdlc1tpXVswXSA8PSAweGZmZmYpIHsKICAgICAgYnJlYWs7CiAgICB9CiAgfQogIGNvbnN0IGJtcExlbmd0aCA9IGkgKyAxOwogIGlmIChyYW5nZXNbaV1bMF0gPCAweGZmZmYgJiYgcmFuZ2VzW2ldWzFdID09PSAweGZmZmYpIHsKICAgIHJhbmdlc1tpXVsxXSA9IDB4ZmZmZTsKICB9CiAgY29uc3QgdHJhaWxpbmdSYW5nZXNDb3VudCA9IHJhbmdlc1tpXVsxXSA8IDB4ZmZmZiA/IDEgOiAwOwogIGNvbnN0IHNlZ0NvdW50ID0gYm1wTGVuZ3RoICsgdHJhaWxpbmdSYW5nZXNDb3VudDsKICBjb25zdCBzZWFyY2hQYXJhbXMgPSBfb3BlbnR5cGVfZmlsZV9idWlsZGVyLk9wZW5UeXBlRmlsZUJ1aWxkZXIuZ2V0U2VhcmNoUGFyYW1zKHNlZ0NvdW50LCAyKTsKICBsZXQgc3RhcnRDb3VudCA9ICIiOwogIGxldCBlbmRDb3VudCA9ICIiOwogIGxldCBpZERlbHRhcyA9ICIiOwogIGxldCBpZFJhbmdlT2Zmc2V0cyA9ICIiOwogIGxldCBnbHlwaHNJZHMgPSAiIjsKICBsZXQgYmlhcyA9IDA7CiAgbGV0IHJhbmdlLCBzdGFydCwgZW5kLCBjb2RlczsKICBmb3IgKGkgPSAwLCBpaSA9IGJtcExlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIHJhbmdlID0gcmFuZ2VzW2ldOwogICAgc3RhcnQgPSByYW5nZVswXTsKICAgIGVuZCA9IHJhbmdlWzFdOwogICAgc3RhcnRDb3VudCArPSBzdHJpbmcxNihzdGFydCk7CiAgICBlbmRDb3VudCArPSBzdHJpbmcxNihlbmQpOwogICAgY29kZXMgPSByYW5nZVsyXTsKICAgIGxldCBjb250aWd1b3VzID0gdHJ1ZTsKICAgIGZvciAoaiA9IDEsIGpqID0gY29kZXMubGVuZ3RoOyBqIDwgamo7ICsraikgewogICAgICBpZiAoY29kZXNbal0gIT09IGNvZGVzW2ogLSAxXSArIDEpIHsKICAgICAgICBjb250aWd1b3VzID0gZmFsc2U7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGlmICghY29udGlndW91cykgewogICAgICBjb25zdCBvZmZzZXQgPSAoc2VnQ291bnQgLSBpKSAqIDIgKyBiaWFzICogMjsKICAgICAgYmlhcyArPSBlbmQgLSBzdGFydCArIDE7CiAgICAgIGlkRGVsdGFzICs9IHN0cmluZzE2KDApOwogICAgICBpZFJhbmdlT2Zmc2V0cyArPSBzdHJpbmcxNihvZmZzZXQpOwogICAgICBmb3IgKGogPSAwLCBqaiA9IGNvZGVzLmxlbmd0aDsgaiA8IGpqOyArK2opIHsKICAgICAgICBnbHlwaHNJZHMgKz0gc3RyaW5nMTYoY29kZXNbal0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBzdGFydENvZGUgPSBjb2Rlc1swXTsKICAgICAgaWREZWx0YXMgKz0gc3RyaW5nMTYoc3RhcnRDb2RlIC0gc3RhcnQgJiAweGZmZmYpOwogICAgICBpZFJhbmdlT2Zmc2V0cyArPSBzdHJpbmcxNigwKTsKICAgIH0KICB9CiAgaWYgKHRyYWlsaW5nUmFuZ2VzQ291bnQgPiAwKSB7CiAgICBlbmRDb3VudCArPSAiXHhGRlx4RkYiOwogICAgc3RhcnRDb3VudCArPSAiXHhGRlx4RkYiOwogICAgaWREZWx0YXMgKz0gIlx4MDBceDAxIjsKICAgIGlkUmFuZ2VPZmZzZXRzICs9ICJceDAwXHgwMCI7CiAgfQogIGNvbnN0IGZvcm1hdDMxNCA9ICJceDAwXHgwMCIgKyBzdHJpbmcxNigyICogc2VnQ291bnQpICsgc3RyaW5nMTYoc2VhcmNoUGFyYW1zLnJhbmdlKSArIHN0cmluZzE2KHNlYXJjaFBhcmFtcy5lbnRyeSkgKyBzdHJpbmcxNihzZWFyY2hQYXJhbXMucmFuZ2VTaGlmdCkgKyBlbmRDb3VudCArICJceDAwXHgwMCIgKyBzdGFydENvdW50ICsgaWREZWx0YXMgKyBpZFJhbmdlT2Zmc2V0cyArIGdseXBoc0lkczsKICBsZXQgZm9ybWF0MzEwMTIgPSAiIjsKICBsZXQgaGVhZGVyMzEwMTIgPSAiIjsKICBpZiAobnVtVGFibGVzID4gMSkgewogICAgY21hcCArPSAiXHgwMFx4MDMiICsgIlx4MDBceDBBIiArICgwLCBfdXRpbC5zdHJpbmczMikoNCArIG51bVRhYmxlcyAqIDggKyA0ICsgZm9ybWF0MzE0Lmxlbmd0aCk7CiAgICBmb3JtYXQzMTAxMiA9ICIiOwogICAgZm9yIChpID0gMCwgaWkgPSByYW5nZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICByYW5nZSA9IHJhbmdlc1tpXTsKICAgICAgc3RhcnQgPSByYW5nZVswXTsKICAgICAgY29kZXMgPSByYW5nZVsyXTsKICAgICAgbGV0IGNvZGUgPSBjb2Rlc1swXTsKICAgICAgZm9yIChqID0gMSwgamogPSBjb2Rlcy5sZW5ndGg7IGogPCBqajsgKytqKSB7CiAgICAgICAgaWYgKGNvZGVzW2pdICE9PSBjb2Rlc1tqIC0gMV0gKyAxKSB7CiAgICAgICAgICBlbmQgPSByYW5nZVswXSArIGogLSAxOwogICAgICAgICAgZm9ybWF0MzEwMTIgKz0gKDAsIF91dGlsLnN0cmluZzMyKShzdGFydCkgKyAoMCwgX3V0aWwuc3RyaW5nMzIpKGVuZCkgKyAoMCwgX3V0aWwuc3RyaW5nMzIpKGNvZGUpOwogICAgICAgICAgc3RhcnQgPSBlbmQgKyAxOwogICAgICAgICAgY29kZSA9IGNvZGVzW2pdOwogICAgICAgIH0KICAgICAgfQogICAgICBmb3JtYXQzMTAxMiArPSAoMCwgX3V0aWwuc3RyaW5nMzIpKHN0YXJ0KSArICgwLCBfdXRpbC5zdHJpbmczMikocmFuZ2VbMV0pICsgKDAsIF91dGlsLnN0cmluZzMyKShjb2RlKTsKICAgIH0KICAgIGhlYWRlcjMxMDEyID0gIlx4MDBceDBDIiArICJceDAwXHgwMCIgKyAoMCwgX3V0aWwuc3RyaW5nMzIpKGZvcm1hdDMxMDEyLmxlbmd0aCArIDE2KSArICJceDAwXHgwMFx4MDBceDAwIiArICgwLCBfdXRpbC5zdHJpbmczMikoZm9ybWF0MzEwMTIubGVuZ3RoIC8gMTIpOwogIH0KICByZXR1cm4gY21hcCArICJceDAwXHgwNCIgKyBzdHJpbmcxNihmb3JtYXQzMTQubGVuZ3RoICsgNCkgKyBmb3JtYXQzMTQgKyBoZWFkZXIzMTAxMiArIGZvcm1hdDMxMDEyOwp9CmZ1bmN0aW9uIHZhbGlkYXRlT1MyVGFibGUob3MyLCBmaWxlKSB7CiAgZmlsZS5wb3MgPSAoZmlsZS5zdGFydCB8fCAwKSArIG9zMi5vZmZzZXQ7CiAgY29uc3QgdmVyc2lvbiA9IGZpbGUuZ2V0VWludDE2KCk7CiAgZmlsZS5za2lwKDYwKTsKICBjb25zdCBzZWxlY3Rpb24gPSBmaWxlLmdldFVpbnQxNigpOwogIGlmICh2ZXJzaW9uIDwgNCAmJiBzZWxlY3Rpb24gJiAweDAzMDApIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgY29uc3QgZmlyc3RDaGFyID0gZmlsZS5nZXRVaW50MTYoKTsKICBjb25zdCBsYXN0Q2hhciA9IGZpbGUuZ2V0VWludDE2KCk7CiAgaWYgKGZpcnN0Q2hhciA+IGxhc3RDaGFyKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGZpbGUuc2tpcCg2KTsKICBjb25zdCB1c1dpbkFzY2VudCA9IGZpbGUuZ2V0VWludDE2KCk7CiAgaWYgKHVzV2luQXNjZW50ID09PSAwKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIG9zMi5kYXRhWzhdID0gb3MyLmRhdGFbOV0gPSAwOwogIHJldHVybiB0cnVlOwp9CmZ1bmN0aW9uIGNyZWF0ZU9TMlRhYmxlKHByb3BlcnRpZXMsIGNoYXJzdHJpbmdzLCBvdmVycmlkZSkgewogIG92ZXJyaWRlID0gb3ZlcnJpZGUgfHwgewogICAgdW5pdHNQZXJFbTogMCwKICAgIHlNYXg6IDAsCiAgICB5TWluOiAwLAogICAgYXNjZW50OiAwLAogICAgZGVzY2VudDogMAogIH07CiAgbGV0IHVsVW5pY29kZVJhbmdlMSA9IDA7CiAgbGV0IHVsVW5pY29kZVJhbmdlMiA9IDA7CiAgbGV0IHVsVW5pY29kZVJhbmdlMyA9IDA7CiAgbGV0IHVsVW5pY29kZVJhbmdlNCA9IDA7CiAgbGV0IGZpcnN0Q2hhckluZGV4ID0gbnVsbDsKICBsZXQgbGFzdENoYXJJbmRleCA9IDA7CiAgaWYgKGNoYXJzdHJpbmdzKSB7CiAgICBmb3IgKGxldCBjb2RlIGluIGNoYXJzdHJpbmdzKSB7CiAgICAgIGNvZGUgfD0gMDsKICAgICAgaWYgKGZpcnN0Q2hhckluZGV4ID4gY29kZSB8fCAhZmlyc3RDaGFySW5kZXgpIHsKICAgICAgICBmaXJzdENoYXJJbmRleCA9IGNvZGU7CiAgICAgIH0KICAgICAgaWYgKGxhc3RDaGFySW5kZXggPCBjb2RlKSB7CiAgICAgICAgbGFzdENoYXJJbmRleCA9IGNvZGU7CiAgICAgIH0KICAgICAgY29uc3QgcG9zaXRpb24gPSAoMCwgX3VuaWNvZGUuZ2V0VW5pY29kZVJhbmdlRm9yKShjb2RlKTsKICAgICAgaWYgKHBvc2l0aW9uIDwgMzIpIHsKICAgICAgICB1bFVuaWNvZGVSYW5nZTEgfD0gMSA8PCBwb3NpdGlvbjsKICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA8IDY0KSB7CiAgICAgICAgdWxVbmljb2RlUmFuZ2UyIHw9IDEgPDwgcG9zaXRpb24gLSAzMjsKICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA8IDk2KSB7CiAgICAgICAgdWxVbmljb2RlUmFuZ2UzIHw9IDEgPDwgcG9zaXRpb24gLSA2NDsKICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA8IDEyMykgewogICAgICAgIHVsVW5pY29kZVJhbmdlNCB8PSAxIDw8IHBvc2l0aW9uIC0gOTY7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJVbmljb2RlIHJhbmdlcyBCaXRzID4gMTIzIGFyZSByZXNlcnZlZCBmb3IgaW50ZXJuYWwgdXNhZ2UiKTsKICAgICAgfQogICAgfQogICAgaWYgKGxhc3RDaGFySW5kZXggPiAweGZmZmYpIHsKICAgICAgbGFzdENoYXJJbmRleCA9IDB4ZmZmZjsKICAgIH0KICB9IGVsc2UgewogICAgZmlyc3RDaGFySW5kZXggPSAwOwogICAgbGFzdENoYXJJbmRleCA9IDI1NTsKICB9CiAgY29uc3QgYmJveCA9IHByb3BlcnRpZXMuYmJveCB8fCBbMCwgMCwgMCwgMF07CiAgY29uc3QgdW5pdHNQZXJFbSA9IG92ZXJyaWRlLnVuaXRzUGVyRW0gfHwgMSAvIChwcm9wZXJ0aWVzLmZvbnRNYXRyaXggfHwgX3V0aWwuRk9OVF9JREVOVElUWV9NQVRSSVgpWzBdOwogIGNvbnN0IHNjYWxlID0gcHJvcGVydGllcy5hc2NlbnRTY2FsZWQgPyAxLjAgOiB1bml0c1BlckVtIC8gUERGX0dMWVBIX1NQQUNFX1VOSVRTOwogIGNvbnN0IHR5cG9Bc2NlbnQgPSBvdmVycmlkZS5hc2NlbnQgfHwgTWF0aC5yb3VuZChzY2FsZSAqIChwcm9wZXJ0aWVzLmFzY2VudCB8fCBiYm94WzNdKSk7CiAgbGV0IHR5cG9EZXNjZW50ID0gb3ZlcnJpZGUuZGVzY2VudCB8fCBNYXRoLnJvdW5kKHNjYWxlICogKHByb3BlcnRpZXMuZGVzY2VudCB8fCBiYm94WzFdKSk7CiAgaWYgKHR5cG9EZXNjZW50ID4gMCAmJiBwcm9wZXJ0aWVzLmRlc2NlbnQgPiAwICYmIGJib3hbMV0gPCAwKSB7CiAgICB0eXBvRGVzY2VudCA9IC10eXBvRGVzY2VudDsKICB9CiAgY29uc3Qgd2luQXNjZW50ID0gb3ZlcnJpZGUueU1heCB8fCB0eXBvQXNjZW50OwogIGNvbnN0IHdpbkRlc2NlbnQgPSAtb3ZlcnJpZGUueU1pbiB8fCAtdHlwb0Rlc2NlbnQ7CiAgcmV0dXJuICJceDAwXHgwMyIgKyAiXHgwMlx4MjQiICsgIlx4MDFceEY0IiArICJceDAwXHgwNSIgKyAiXHgwMFx4MDAiICsgIlx4MDJceDhBIiArICJceDAyXHhCQiIgKyAiXHgwMFx4MDAiICsgIlx4MDBceDhDIiArICJceDAyXHg4QSIgKyAiXHgwMlx4QkIiICsgIlx4MDBceDAwIiArICJceDAxXHhERiIgKyAiXHgwMFx4MzEiICsgIlx4MDFceDAyIiArICJceDAwXHgwMCIgKyAiXHgwMFx4MDBceDA2IiArIFN0cmluZy5mcm9tQ2hhckNvZGUocHJvcGVydGllcy5maXhlZFBpdGNoID8gMHgwOSA6IDB4MDApICsgIlx4MDBceDAwXHgwMFx4MDBceDAwXHgwMCIgKyAoMCwgX3V0aWwuc3RyaW5nMzIpKHVsVW5pY29kZVJhbmdlMSkgKyAoMCwgX3V0aWwuc3RyaW5nMzIpKHVsVW5pY29kZVJhbmdlMikgKyAoMCwgX3V0aWwuc3RyaW5nMzIpKHVsVW5pY29kZVJhbmdlMykgKyAoMCwgX3V0aWwuc3RyaW5nMzIpKHVsVW5pY29kZVJhbmdlNCkgKyAiXHgyQVx4MzJceDMxXHgyQSIgKyBzdHJpbmcxNihwcm9wZXJ0aWVzLml0YWxpY0FuZ2xlID8gMSA6IDApICsgc3RyaW5nMTYoZmlyc3RDaGFySW5kZXggfHwgcHJvcGVydGllcy5maXJzdENoYXIpICsgc3RyaW5nMTYobGFzdENoYXJJbmRleCB8fCBwcm9wZXJ0aWVzLmxhc3RDaGFyKSArIHN0cmluZzE2KHR5cG9Bc2NlbnQpICsgc3RyaW5nMTYodHlwb0Rlc2NlbnQpICsgIlx4MDBceDY0IiArIHN0cmluZzE2KHdpbkFzY2VudCkgKyBzdHJpbmcxNih3aW5EZXNjZW50KSArICJceDAwXHgwMFx4MDBceDAwIiArICJceDAwXHgwMFx4MDBceDAwIiArIHN0cmluZzE2KHByb3BlcnRpZXMueEhlaWdodCkgKyBzdHJpbmcxNihwcm9wZXJ0aWVzLmNhcEhlaWdodCkgKyBzdHJpbmcxNigwKSArIHN0cmluZzE2KGZpcnN0Q2hhckluZGV4IHx8IHByb3BlcnRpZXMuZmlyc3RDaGFyKSArICJceDAwXHgwMyI7Cn0KZnVuY3Rpb24gY3JlYXRlUG9zdFRhYmxlKHByb3BlcnRpZXMpIHsKICBjb25zdCBhbmdsZSA9IE1hdGguZmxvb3IocHJvcGVydGllcy5pdGFsaWNBbmdsZSAqIDIgKiogMTYpOwogIHJldHVybiAiXHgwMFx4MDNceDAwXHgwMCIgKyAoMCwgX3V0aWwuc3RyaW5nMzIpKGFuZ2xlKSArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiICsgKDAsIF91dGlsLnN0cmluZzMyKShwcm9wZXJ0aWVzLmZpeGVkUGl0Y2ggPyAxIDogMCkgKyAiXHgwMFx4MDBceDAwXHgwMCIgKyAiXHgwMFx4MDBceDAwXHgwMCIgKyAiXHgwMFx4MDBceDAwXHgwMCIgKyAiXHgwMFx4MDBceDAwXHgwMCI7Cn0KZnVuY3Rpb24gY3JlYXRlUG9zdHNjcmlwdE5hbWUobmFtZSkgewogIHJldHVybiBuYW1lLnJlcGxhY2VBbGwoL1teXHgyMS1ceDdFXXxbW1xdKCl7fTw+LyVdL2csICIiKS5zbGljZSgwLCA2Myk7Cn0KZnVuY3Rpb24gY3JlYXRlTmFtZVRhYmxlKG5hbWUsIHByb3RvKSB7CiAgaWYgKCFwcm90bykgewogICAgcHJvdG8gPSBbW10sIFtdXTsKICB9CiAgY29uc3Qgc3RyaW5ncyA9IFtwcm90b1swXVswXSB8fCAiT3JpZ2luYWwgbGljZW5jZSIsIHByb3RvWzBdWzFdIHx8IG5hbWUsIHByb3RvWzBdWzJdIHx8ICJVbmtub3duIiwgcHJvdG9bMF1bM10gfHwgInVuaXF1ZUlEIiwgcHJvdG9bMF1bNF0gfHwgbmFtZSwgcHJvdG9bMF1bNV0gfHwgIlZlcnNpb24gMC4xMSIsIHByb3RvWzBdWzZdIHx8IGNyZWF0ZVBvc3RzY3JpcHROYW1lKG5hbWUpLCBwcm90b1swXVs3XSB8fCAiVW5rbm93biIsIHByb3RvWzBdWzhdIHx8ICJVbmtub3duIiwgcHJvdG9bMF1bOV0gfHwgIlVua25vd24iXTsKICBjb25zdCBzdHJpbmdzVW5pY29kZSA9IFtdOwogIGxldCBpLCBpaSwgaiwgamosIHN0cjsKICBmb3IgKGkgPSAwLCBpaSA9IHN0cmluZ3MubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgc3RyID0gcHJvdG9bMV1baV0gfHwgc3RyaW5nc1tpXTsKICAgIGNvbnN0IHN0ckJ1ZlVuaWNvZGUgPSBbXTsKICAgIGZvciAoaiA9IDAsIGpqID0gc3RyLmxlbmd0aDsgaiA8IGpqOyBqKyspIHsKICAgICAgc3RyQnVmVW5pY29kZS5wdXNoKHN0cmluZzE2KHN0ci5jaGFyQ29kZUF0KGopKSk7CiAgICB9CiAgICBzdHJpbmdzVW5pY29kZS5wdXNoKHN0ckJ1ZlVuaWNvZGUuam9pbigiIikpOwogIH0KICBjb25zdCBuYW1lcyA9IFtzdHJpbmdzLCBzdHJpbmdzVW5pY29kZV07CiAgY29uc3QgcGxhdGZvcm1zID0gWyJceDAwXHgwMSIsICJceDAwXHgwMyJdOwogIGNvbnN0IGVuY29kaW5ncyA9IFsiXHgwMFx4MDAiLCAiXHgwMFx4MDEiXTsKICBjb25zdCBsYW5ndWFnZXMgPSBbIlx4MDBceDAwIiwgIlx4MDRceDA5Il07CiAgY29uc3QgbmFtZXNSZWNvcmRDb3VudCA9IHN0cmluZ3MubGVuZ3RoICogcGxhdGZvcm1zLmxlbmd0aDsKICBsZXQgbmFtZVRhYmxlID0gIlx4MDBceDAwIiArIHN0cmluZzE2KG5hbWVzUmVjb3JkQ291bnQpICsgc3RyaW5nMTYobmFtZXNSZWNvcmRDb3VudCAqIDEyICsgNik7CiAgbGV0IHN0ck9mZnNldCA9IDA7CiAgZm9yIChpID0gMCwgaWkgPSBwbGF0Zm9ybXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgY29uc3Qgc3RycyA9IG5hbWVzW2ldOwogICAgZm9yIChqID0gMCwgamogPSBzdHJzLmxlbmd0aDsgaiA8IGpqOyBqKyspIHsKICAgICAgc3RyID0gc3Ryc1tqXTsKICAgICAgY29uc3QgbmFtZVJlY29yZCA9IHBsYXRmb3Jtc1tpXSArIGVuY29kaW5nc1tpXSArIGxhbmd1YWdlc1tpXSArIHN0cmluZzE2KGopICsgc3RyaW5nMTYoc3RyLmxlbmd0aCkgKyBzdHJpbmcxNihzdHJPZmZzZXQpOwogICAgICBuYW1lVGFibGUgKz0gbmFtZVJlY29yZDsKICAgICAgc3RyT2Zmc2V0ICs9IHN0ci5sZW5ndGg7CiAgICB9CiAgfQogIG5hbWVUYWJsZSArPSBzdHJpbmdzLmpvaW4oIiIpICsgc3RyaW5nc1VuaWNvZGUuam9pbigiIik7CiAgcmV0dXJuIG5hbWVUYWJsZTsKfQpjbGFzcyBGb250IHsKICBjb25zdHJ1Y3RvcihuYW1lLCBmaWxlLCBwcm9wZXJ0aWVzKSB7CiAgICB0aGlzLm5hbWUgPSBuYW1lOwogICAgdGhpcy5wc05hbWUgPSBudWxsOwogICAgdGhpcy5taW1ldHlwZSA9IG51bGw7CiAgICB0aGlzLmRpc2FibGVGb250RmFjZSA9IGZhbHNlOwogICAgdGhpcy5sb2FkZWROYW1lID0gcHJvcGVydGllcy5sb2FkZWROYW1lOwogICAgdGhpcy5pc1R5cGUzRm9udCA9IHByb3BlcnRpZXMuaXNUeXBlM0ZvbnQ7CiAgICB0aGlzLm1pc3NpbmdGaWxlID0gZmFsc2U7CiAgICB0aGlzLmNzc0ZvbnRJbmZvID0gcHJvcGVydGllcy5jc3NGb250SW5mbzsKICAgIHRoaXMuX2NoYXJzQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgdGhpcy5fZ2x5cGhDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBsZXQgaXNTZXJpZkZvbnQgPSAhIShwcm9wZXJ0aWVzLmZsYWdzICYgX2ZvbnRzX3V0aWxzLkZvbnRGbGFncy5TZXJpZik7CiAgICBpZiAoIWlzU2VyaWZGb250ICYmICFwcm9wZXJ0aWVzLmlzU2ltdWxhdGVkRmxhZ3MpIHsKICAgICAgY29uc3QgYmFzZU5hbWUgPSBuYW1lLnJlcGxhY2VBbGwoL1ssX10vZywgIi0iKS5zcGxpdCgiLSIpWzBdLAogICAgICAgIHNlcmlmRm9udHMgPSAoMCwgX3N0YW5kYXJkX2ZvbnRzLmdldFNlcmlmRm9udHMpKCk7CiAgICAgIGZvciAoY29uc3QgbmFtZVBhcnQgb2YgYmFzZU5hbWUuc3BsaXQoIisiKSkgewogICAgICAgIGlmIChzZXJpZkZvbnRzW25hbWVQYXJ0XSkgewogICAgICAgICAgaXNTZXJpZkZvbnQgPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICB0aGlzLmlzU2VyaWZGb250ID0gaXNTZXJpZkZvbnQ7CiAgICB0aGlzLmlzU3ltYm9saWNGb250ID0gISEocHJvcGVydGllcy5mbGFncyAmIF9mb250c191dGlscy5Gb250RmxhZ3MuU3ltYm9saWMpOwogICAgdGhpcy5pc01vbm9zcGFjZSA9ICEhKHByb3BlcnRpZXMuZmxhZ3MgJiBfZm9udHNfdXRpbHMuRm9udEZsYWdzLkZpeGVkUGl0Y2gpOwogICAgbGV0IHsKICAgICAgdHlwZSwKICAgICAgc3VidHlwZQogICAgfSA9IHByb3BlcnRpZXM7CiAgICB0aGlzLnR5cGUgPSB0eXBlOwogICAgdGhpcy5zdWJ0eXBlID0gc3VidHlwZTsKICAgIGNvbnN0IG1hdGNoZXMgPSBuYW1lLm1hdGNoKC9eSW52YWxpZFBERmpzRm9udF8oLiopX1xkKyQvKTsKICAgIHRoaXMuaXNJbnZhbGlkUERGanNGb250ID0gISFtYXRjaGVzOwogICAgaWYgKHRoaXMuaXNJbnZhbGlkUERGanNGb250KSB7CiAgICAgIHRoaXMuZmFsbGJhY2tOYW1lID0gbWF0Y2hlc1sxXTsKICAgIH0gZWxzZSBpZiAodGhpcy5pc01vbm9zcGFjZSkgewogICAgICB0aGlzLmZhbGxiYWNrTmFtZSA9ICJtb25vc3BhY2UiOwogICAgfSBlbHNlIGlmICh0aGlzLmlzU2VyaWZGb250KSB7CiAgICAgIHRoaXMuZmFsbGJhY2tOYW1lID0gInNlcmlmIjsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuZmFsbGJhY2tOYW1lID0gInNhbnMtc2VyaWYiOwogICAgfQogICAgdGhpcy5kaWZmZXJlbmNlcyA9IHByb3BlcnRpZXMuZGlmZmVyZW5jZXM7CiAgICB0aGlzLndpZHRocyA9IHByb3BlcnRpZXMud2lkdGhzOwogICAgdGhpcy5kZWZhdWx0V2lkdGggPSBwcm9wZXJ0aWVzLmRlZmF1bHRXaWR0aDsKICAgIHRoaXMuY29tcG9zaXRlID0gcHJvcGVydGllcy5jb21wb3NpdGU7CiAgICB0aGlzLmNNYXAgPSBwcm9wZXJ0aWVzLmNNYXA7CiAgICB0aGlzLmNhcEhlaWdodCA9IHByb3BlcnRpZXMuY2FwSGVpZ2h0IC8gUERGX0dMWVBIX1NQQUNFX1VOSVRTOwogICAgdGhpcy5hc2NlbnQgPSBwcm9wZXJ0aWVzLmFzY2VudCAvIFBERl9HTFlQSF9TUEFDRV9VTklUUzsKICAgIHRoaXMuZGVzY2VudCA9IHByb3BlcnRpZXMuZGVzY2VudCAvIFBERl9HTFlQSF9TUEFDRV9VTklUUzsKICAgIHRoaXMubGluZUhlaWdodCA9IHRoaXMuYXNjZW50IC0gdGhpcy5kZXNjZW50OwogICAgdGhpcy5mb250TWF0cml4ID0gcHJvcGVydGllcy5mb250TWF0cml4OwogICAgdGhpcy5iYm94ID0gcHJvcGVydGllcy5iYm94OwogICAgdGhpcy5kZWZhdWx0RW5jb2RpbmcgPSBwcm9wZXJ0aWVzLmRlZmF1bHRFbmNvZGluZzsKICAgIHRoaXMudG9Vbmljb2RlID0gcHJvcGVydGllcy50b1VuaWNvZGU7CiAgICB0aGlzLnRvRm9udENoYXIgPSBbXTsKICAgIGlmIChwcm9wZXJ0aWVzLnR5cGUgPT09ICJUeXBlMyIpIHsKICAgICAgZm9yIChsZXQgY2hhckNvZGUgPSAwOyBjaGFyQ29kZSA8IDI1NjsgY2hhckNvZGUrKykgewogICAgICAgIHRoaXMudG9Gb250Q2hhcltjaGFyQ29kZV0gPSB0aGlzLmRpZmZlcmVuY2VzW2NoYXJDb2RlXSB8fCBwcm9wZXJ0aWVzLmRlZmF1bHRFbmNvZGluZ1tjaGFyQ29kZV07CiAgICAgIH0KICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5jaWRFbmNvZGluZyA9IHByb3BlcnRpZXMuY2lkRW5jb2RpbmcgfHwgIiI7CiAgICB0aGlzLnZlcnRpY2FsID0gISFwcm9wZXJ0aWVzLnZlcnRpY2FsOwogICAgaWYgKHRoaXMudmVydGljYWwpIHsKICAgICAgdGhpcy52bWV0cmljcyA9IHByb3BlcnRpZXMudm1ldHJpY3M7CiAgICAgIHRoaXMuZGVmYXVsdFZNZXRyaWNzID0gcHJvcGVydGllcy5kZWZhdWx0Vk1ldHJpY3M7CiAgICB9CiAgICBpZiAoIWZpbGUgfHwgZmlsZS5pc0VtcHR5KSB7CiAgICAgIGlmIChmaWxlKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKCdGb250IGZpbGUgaXMgZW1wdHkgaW4gIicgKyBuYW1lICsgJyIgKCcgKyB0aGlzLmxvYWRlZE5hbWUgKyAiKSIpOwogICAgICB9CiAgICAgIHRoaXMuZmFsbGJhY2tUb1N5c3RlbUZvbnQocHJvcGVydGllcyk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIFt0eXBlLCBzdWJ0eXBlXSA9IGdldEZvbnRGaWxlVHlwZShmaWxlLCBwcm9wZXJ0aWVzKTsKICAgIGlmICh0eXBlICE9PSB0aGlzLnR5cGUgfHwgc3VidHlwZSAhPT0gdGhpcy5zdWJ0eXBlKSB7CiAgICAgICgwLCBfdXRpbC5pbmZvKSgiSW5jb25zaXN0ZW50IGZvbnQgZmlsZSBUeXBlL1N1YlR5cGUsIGV4cGVjdGVkOiAiICsgYCR7dGhpcy50eXBlfS8ke3RoaXMuc3VidHlwZX0gYnV0IGZvdW5kOiAke3R5cGV9LyR7c3VidHlwZX0uYCk7CiAgICB9CiAgICBsZXQgZGF0YTsKICAgIHRyeSB7CiAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgIGNhc2UgIk1NVHlwZTEiOgogICAgICAgICAgKDAsIF91dGlsLmluZm8pKCJNTVR5cGUxIGZvbnQgKCIgKyBuYW1lICsgIiksIGZhbGxpbmcgYmFjayB0byBUeXBlMS4iKTsKICAgICAgICBjYXNlICJUeXBlMSI6CiAgICAgICAgY2FzZSAiQ0lERm9udFR5cGUwIjoKICAgICAgICAgIHRoaXMubWltZXR5cGUgPSAiZm9udC9vcGVudHlwZSI7CiAgICAgICAgICBjb25zdCBjZmYgPSBzdWJ0eXBlID09PSAiVHlwZTFDIiB8fCBzdWJ0eXBlID09PSAiQ0lERm9udFR5cGUwQyIgPyBuZXcgX2NmZl9mb250LkNGRkZvbnQoZmlsZSwgcHJvcGVydGllcykgOiBuZXcgX3R5cGUxX2ZvbnQuVHlwZTFGb250KG5hbWUsIGZpbGUsIHByb3BlcnRpZXMpOwogICAgICAgICAgYWRqdXN0V2lkdGhzKHByb3BlcnRpZXMpOwogICAgICAgICAgZGF0YSA9IHRoaXMuY29udmVydChuYW1lLCBjZmYsIHByb3BlcnRpZXMpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiT3BlblR5cGUiOgogICAgICAgIGNhc2UgIlRydWVUeXBlIjoKICAgICAgICBjYXNlICJDSURGb250VHlwZTIiOgogICAgICAgICAgdGhpcy5taW1ldHlwZSA9ICJmb250L29wZW50eXBlIjsKICAgICAgICAgIGRhdGEgPSB0aGlzLmNoZWNrQW5kUmVwYWlyKG5hbWUsIGZpbGUsIHByb3BlcnRpZXMpOwogICAgICAgICAgaWYgKHRoaXMuaXNPcGVuVHlwZSkgewogICAgICAgICAgICBhZGp1c3RXaWR0aHMocHJvcGVydGllcyk7CiAgICAgICAgICAgIHR5cGUgPSAiT3BlblR5cGUiOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgRm9udCAke3R5cGV9IGlzIG5vdCBzdXBwb3J0ZWRgKTsKICAgICAgfQogICAgfSBjYXRjaCAoZSkgewogICAgICAoMCwgX3V0aWwud2FybikoZSk7CiAgICAgIHRoaXMuZmFsbGJhY2tUb1N5c3RlbUZvbnQocHJvcGVydGllcyk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGFtZW5kRmFsbGJhY2tUb1VuaWNvZGUocHJvcGVydGllcyk7CiAgICB0aGlzLmRhdGEgPSBkYXRhOwogICAgdGhpcy50eXBlID0gdHlwZTsKICAgIHRoaXMuc3VidHlwZSA9IHN1YnR5cGU7CiAgICB0aGlzLmZvbnRNYXRyaXggPSBwcm9wZXJ0aWVzLmZvbnRNYXRyaXg7CiAgICB0aGlzLndpZHRocyA9IHByb3BlcnRpZXMud2lkdGhzOwogICAgdGhpcy5kZWZhdWx0V2lkdGggPSBwcm9wZXJ0aWVzLmRlZmF1bHRXaWR0aDsKICAgIHRoaXMudG9Vbmljb2RlID0gcHJvcGVydGllcy50b1VuaWNvZGU7CiAgICB0aGlzLnNlYWNNYXAgPSBwcm9wZXJ0aWVzLnNlYWNNYXA7CiAgfQogIGdldCByZW5kZXJlcigpIHsKICAgIGNvbnN0IHJlbmRlcmVyID0gX2ZvbnRfcmVuZGVyZXIuRm9udFJlbmRlcmVyRmFjdG9yeS5jcmVhdGUodGhpcywgX2ZvbnRzX3V0aWxzLlNFQUNfQU5BTFlTSVNfRU5BQkxFRCk7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInJlbmRlcmVyIiwgcmVuZGVyZXIpOwogIH0KICBleHBvcnREYXRhKCkgewogICAgbGV0IGV4dHJhUHJvcGVydGllcyA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogZmFsc2U7CiAgICBjb25zdCBleHBvcnREYXRhUHJvcGVydGllcyA9IGV4dHJhUHJvcGVydGllcyA/IFsuLi5FWFBPUlRfREFUQV9QUk9QRVJUSUVTLCAuLi5FWFBPUlRfREFUQV9FWFRSQV9QUk9QRVJUSUVTXSA6IEVYUE9SVF9EQVRBX1BST1BFUlRJRVM7CiAgICBjb25zdCBkYXRhID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGxldCBwcm9wZXJ0eSwgdmFsdWU7CiAgICBmb3IgKHByb3BlcnR5IG9mIGV4cG9ydERhdGFQcm9wZXJ0aWVzKSB7CiAgICAgIHZhbHVlID0gdGhpc1twcm9wZXJ0eV07CiAgICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZGF0YVtwcm9wZXJ0eV0gPSB2YWx1ZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGRhdGE7CiAgfQogIGZhbGxiYWNrVG9TeXN0ZW1Gb250KHByb3BlcnRpZXMpIHsKICAgIHRoaXMubWlzc2luZ0ZpbGUgPSB0cnVlOwogICAgY29uc3QgewogICAgICBuYW1lLAogICAgICB0eXBlCiAgICB9ID0gdGhpczsKICAgIGxldCBmb250TmFtZSA9ICgwLCBfZm9udHNfdXRpbHMubm9ybWFsaXplRm9udE5hbWUpKG5hbWUpOwogICAgY29uc3Qgc3RkRm9udE1hcCA9ICgwLCBfc3RhbmRhcmRfZm9udHMuZ2V0U3RkRm9udE1hcCkoKSwKICAgICAgbm9uU3RkRm9udE1hcCA9ICgwLCBfc3RhbmRhcmRfZm9udHMuZ2V0Tm9uU3RkRm9udE1hcCkoKTsKICAgIGNvbnN0IGlzU3RhbmRhcmRGb250ID0gISFzdGRGb250TWFwW2ZvbnROYW1lXTsKICAgIGNvbnN0IGlzTWFwcGVkVG9TdGFuZGFyZEZvbnQgPSAhIShub25TdGRGb250TWFwW2ZvbnROYW1lXSAmJiBzdGRGb250TWFwW25vblN0ZEZvbnRNYXBbZm9udE5hbWVdXSk7CiAgICBmb250TmFtZSA9IHN0ZEZvbnRNYXBbZm9udE5hbWVdIHx8IG5vblN0ZEZvbnRNYXBbZm9udE5hbWVdIHx8IGZvbnROYW1lOwogICAgY29uc3QgZm9udEJhc2ljTWV0cmljc01hcCA9ICgwLCBfbWV0cmljcy5nZXRGb250QmFzaWNNZXRyaWNzKSgpOwogICAgY29uc3QgbWV0cmljcyA9IGZvbnRCYXNpY01ldHJpY3NNYXBbZm9udE5hbWVdOwogICAgaWYgKG1ldHJpY3MpIHsKICAgICAgaWYgKGlzTmFOKHRoaXMuYXNjZW50KSkgewogICAgICAgIHRoaXMuYXNjZW50ID0gbWV0cmljcy5hc2NlbnQgLyBQREZfR0xZUEhfU1BBQ0VfVU5JVFM7CiAgICAgIH0KICAgICAgaWYgKGlzTmFOKHRoaXMuZGVzY2VudCkpIHsKICAgICAgICB0aGlzLmRlc2NlbnQgPSBtZXRyaWNzLmRlc2NlbnQgLyBQREZfR0xZUEhfU1BBQ0VfVU5JVFM7CiAgICAgIH0KICAgICAgaWYgKGlzTmFOKHRoaXMuY2FwSGVpZ2h0KSkgewogICAgICAgIHRoaXMuY2FwSGVpZ2h0ID0gbWV0cmljcy5jYXBIZWlnaHQgLyBQREZfR0xZUEhfU1BBQ0VfVU5JVFM7CiAgICAgIH0KICAgIH0KICAgIHRoaXMuYm9sZCA9IC9ib2xkL2dpLnRlc3QoZm9udE5hbWUpOwogICAgdGhpcy5pdGFsaWMgPSAvb2JsaXF1ZXxpdGFsaWMvZ2kudGVzdChmb250TmFtZSk7CiAgICB0aGlzLmJsYWNrID0gL0JsYWNrL2cudGVzdChuYW1lKTsKICAgIGNvbnN0IGlzTmFycm93ID0gL05hcnJvdy9nLnRlc3QobmFtZSk7CiAgICB0aGlzLnJlbWVhc3VyZSA9ICghaXNTdGFuZGFyZEZvbnQgfHwgaXNOYXJyb3cpICYmIE9iamVjdC5rZXlzKHRoaXMud2lkdGhzKS5sZW5ndGggPiAwOwogICAgaWYgKChpc1N0YW5kYXJkRm9udCB8fCBpc01hcHBlZFRvU3RhbmRhcmRGb250KSAmJiB0eXBlID09PSAiQ0lERm9udFR5cGUyIiAmJiB0aGlzLmNpZEVuY29kaW5nLnN0YXJ0c1dpdGgoIklkZW50aXR5LSIpKSB7CiAgICAgIGNvbnN0IGNpZFRvR2lkTWFwID0gcHJvcGVydGllcy5jaWRUb0dpZE1hcDsKICAgICAgY29uc3QgbWFwID0gW107CiAgICAgIGFwcGx5U3RhbmRhcmRGb250R2x5cGhNYXAobWFwLCAoMCwgX3N0YW5kYXJkX2ZvbnRzLmdldEdseXBoTWFwRm9yU3RhbmRhcmRGb250cykoKSk7CiAgICAgIGlmICgvQXJpYWwtP0JsYWNrL2kudGVzdChuYW1lKSkgewogICAgICAgIGFwcGx5U3RhbmRhcmRGb250R2x5cGhNYXAobWFwLCAoMCwgX3N0YW5kYXJkX2ZvbnRzLmdldFN1cHBsZW1lbnRhbEdseXBoTWFwRm9yQXJpYWxCbGFjaykoKSk7CiAgICAgIH0gZWxzZSBpZiAoL0NhbGlicmkvaS50ZXN0KG5hbWUpKSB7CiAgICAgICAgYXBwbHlTdGFuZGFyZEZvbnRHbHlwaE1hcChtYXAsICgwLCBfc3RhbmRhcmRfZm9udHMuZ2V0U3VwcGxlbWVudGFsR2x5cGhNYXBGb3JDYWxpYnJpKSgpKTsKICAgICAgfQogICAgICBpZiAoY2lkVG9HaWRNYXApIHsKICAgICAgICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIG1hcCkgewogICAgICAgICAgY29uc3QgY2lkID0gbWFwW2NoYXJDb2RlXTsKICAgICAgICAgIGlmIChjaWRUb0dpZE1hcFtjaWRdICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgbWFwWytjaGFyQ29kZV0gPSBjaWRUb0dpZE1hcFtjaWRdOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoY2lkVG9HaWRNYXAubGVuZ3RoICE9PSB0aGlzLnRvVW5pY29kZS5sZW5ndGggJiYgcHJvcGVydGllcy5oYXNJbmNsdWRlZFRvVW5pY29kZU1hcCAmJiB0aGlzLnRvVW5pY29kZSBpbnN0YW5jZW9mIF90b191bmljb2RlX21hcC5JZGVudGl0eVRvVW5pY29kZU1hcCkgewogICAgICAgICAgdGhpcy50b1VuaWNvZGUuZm9yRWFjaChmdW5jdGlvbiAoY2hhckNvZGUsIHVuaWNvZGVDaGFyQ29kZSkgewogICAgICAgICAgICBjb25zdCBjaWQgPSBtYXBbY2hhckNvZGVdOwogICAgICAgICAgICBpZiAoY2lkVG9HaWRNYXBbY2lkXSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgbWFwWytjaGFyQ29kZV0gPSB1bmljb2RlQ2hhckNvZGU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoISh0aGlzLnRvVW5pY29kZSBpbnN0YW5jZW9mIF90b191bmljb2RlX21hcC5JZGVudGl0eVRvVW5pY29kZU1hcCkpIHsKICAgICAgICB0aGlzLnRvVW5pY29kZS5mb3JFYWNoKGZ1bmN0aW9uIChjaGFyQ29kZSwgdW5pY29kZUNoYXJDb2RlKSB7CiAgICAgICAgICBtYXBbK2NoYXJDb2RlXSA9IHVuaWNvZGVDaGFyQ29kZTsKICAgICAgICB9KTsKICAgICAgfQogICAgICB0aGlzLnRvRm9udENoYXIgPSBtYXA7CiAgICAgIHRoaXMudG9Vbmljb2RlID0gbmV3IF90b191bmljb2RlX21hcC5Ub1VuaWNvZGVNYXAobWFwKTsKICAgIH0gZWxzZSBpZiAoL1N5bWJvbC9pLnRlc3QoZm9udE5hbWUpKSB7CiAgICAgIHRoaXMudG9Gb250Q2hhciA9IGJ1aWxkVG9Gb250Q2hhcihfZW5jb2RpbmdzLlN5bWJvbFNldEVuY29kaW5nLCAoMCwgX2dseXBobGlzdC5nZXRHbHlwaHNVbmljb2RlKSgpLCB0aGlzLmRpZmZlcmVuY2VzKTsKICAgIH0gZWxzZSBpZiAoL0RpbmdiYXRzL2kudGVzdChmb250TmFtZSkpIHsKICAgICAgaWYgKC9XaW5nZGluZ3MvaS50ZXN0KG5hbWUpKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKCJOb24tZW1iZWRkZWQgV2luZ2RpbmdzIGZvbnQsIGZhbGxpbmcgYmFjayB0byBaYXBmRGluZ2JhdHMuIik7CiAgICAgIH0KICAgICAgdGhpcy50b0ZvbnRDaGFyID0gYnVpbGRUb0ZvbnRDaGFyKF9lbmNvZGluZ3MuWmFwZkRpbmdiYXRzRW5jb2RpbmcsICgwLCBfZ2x5cGhsaXN0LmdldERpbmdiYXRzR2x5cGhzVW5pY29kZSkoKSwgdGhpcy5kaWZmZXJlbmNlcyk7CiAgICB9IGVsc2UgaWYgKGlzU3RhbmRhcmRGb250KSB7CiAgICAgIGNvbnN0IG1hcCA9IGJ1aWxkVG9Gb250Q2hhcih0aGlzLmRlZmF1bHRFbmNvZGluZywgKDAsIF9nbHlwaGxpc3QuZ2V0R2x5cGhzVW5pY29kZSkoKSwgdGhpcy5kaWZmZXJlbmNlcyk7CiAgICAgIGlmICh0eXBlID09PSAiQ0lERm9udFR5cGUyIiAmJiAhdGhpcy5jaWRFbmNvZGluZy5zdGFydHNXaXRoKCJJZGVudGl0eS0iKSAmJiAhKHRoaXMudG9Vbmljb2RlIGluc3RhbmNlb2YgX3RvX3VuaWNvZGVfbWFwLklkZW50aXR5VG9Vbmljb2RlTWFwKSkgewogICAgICAgIHRoaXMudG9Vbmljb2RlLmZvckVhY2goZnVuY3Rpb24gKGNoYXJDb2RlLCB1bmljb2RlQ2hhckNvZGUpIHsKICAgICAgICAgIG1hcFsrY2hhckNvZGVdID0gdW5pY29kZUNoYXJDb2RlOwogICAgICAgIH0pOwogICAgICB9CiAgICAgIHRoaXMudG9Gb250Q2hhciA9IG1hcDsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IGdseXBoc1VuaWNvZGVNYXAgPSAoMCwgX2dseXBobGlzdC5nZXRHbHlwaHNVbmljb2RlKSgpOwogICAgICBjb25zdCBtYXAgPSBbXTsKICAgICAgdGhpcy50b1VuaWNvZGUuZm9yRWFjaCgoY2hhckNvZGUsIHVuaWNvZGVDaGFyQ29kZSkgPT4gewogICAgICAgIGlmICghdGhpcy5jb21wb3NpdGUpIHsKICAgICAgICAgIGNvbnN0IGdseXBoTmFtZSA9IHRoaXMuZGlmZmVyZW5jZXNbY2hhckNvZGVdIHx8IHRoaXMuZGVmYXVsdEVuY29kaW5nW2NoYXJDb2RlXTsKICAgICAgICAgIGNvbnN0IHVuaWNvZGUgPSAoMCwgX3VuaWNvZGUuZ2V0VW5pY29kZUZvckdseXBoKShnbHlwaE5hbWUsIGdseXBoc1VuaWNvZGVNYXApOwogICAgICAgICAgaWYgKHVuaWNvZGUgIT09IC0xKSB7CiAgICAgICAgICAgIHVuaWNvZGVDaGFyQ29kZSA9IHVuaWNvZGU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG1hcFsrY2hhckNvZGVdID0gdW5pY29kZUNoYXJDb2RlOwogICAgICB9KTsKICAgICAgaWYgKHRoaXMuY29tcG9zaXRlICYmIHRoaXMudG9Vbmljb2RlIGluc3RhbmNlb2YgX3RvX3VuaWNvZGVfbWFwLklkZW50aXR5VG9Vbmljb2RlTWFwKSB7CiAgICAgICAgaWYgKC9UYWhvbWF8VmVyZGFuYS9pLnRlc3QobmFtZSkpIHsKICAgICAgICAgIGFwcGx5U3RhbmRhcmRGb250R2x5cGhNYXAobWFwLCAoMCwgX3N0YW5kYXJkX2ZvbnRzLmdldEdseXBoTWFwRm9yU3RhbmRhcmRGb250cykoKSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHRoaXMudG9Gb250Q2hhciA9IG1hcDsKICAgIH0KICAgIGFtZW5kRmFsbGJhY2tUb1VuaWNvZGUocHJvcGVydGllcyk7CiAgICB0aGlzLmxvYWRlZE5hbWUgPSBmb250TmFtZS5zcGxpdCgiLSIpWzBdOwogIH0KICBjaGVja0FuZFJlcGFpcihuYW1lLCBmb250LCBwcm9wZXJ0aWVzKSB7CiAgICBjb25zdCBWQUxJRF9UQUJMRVMgPSBbIk9TLzIiLCAiY21hcCIsICJoZWFkIiwgImhoZWEiLCAiaG10eCIsICJtYXhwIiwgIm5hbWUiLCAicG9zdCIsICJsb2NhIiwgImdseWYiLCAiZnBnbSIsICJwcmVwIiwgImN2dCAiLCAiQ0ZGICJdOwogICAgZnVuY3Rpb24gcmVhZFRhYmxlcyhmaWxlLCBudW1UYWJsZXMpIHsKICAgICAgY29uc3QgdGFibGVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdGFibGVzWyJPUy8yIl0gPSBudWxsOwogICAgICB0YWJsZXMuY21hcCA9IG51bGw7CiAgICAgIHRhYmxlcy5oZWFkID0gbnVsbDsKICAgICAgdGFibGVzLmhoZWEgPSBudWxsOwogICAgICB0YWJsZXMuaG10eCA9IG51bGw7CiAgICAgIHRhYmxlcy5tYXhwID0gbnVsbDsKICAgICAgdGFibGVzLm5hbWUgPSBudWxsOwogICAgICB0YWJsZXMucG9zdCA9IG51bGw7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtVGFibGVzOyBpKyspIHsKICAgICAgICBjb25zdCB0YWJsZSA9IHJlYWRUYWJsZUVudHJ5KGZpbGUpOwogICAgICAgIGlmICghVkFMSURfVEFCTEVTLmluY2x1ZGVzKHRhYmxlLnRhZykpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBpZiAodGFibGUubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgdGFibGVzW3RhYmxlLnRhZ10gPSB0YWJsZTsKICAgICAgfQogICAgICByZXR1cm4gdGFibGVzOwogICAgfQogICAgZnVuY3Rpb24gcmVhZFRhYmxlRW50cnkoZmlsZSkgewogICAgICBjb25zdCB0YWcgPSBmaWxlLmdldFN0cmluZyg0KTsKICAgICAgY29uc3QgY2hlY2tzdW0gPSBmaWxlLmdldEludDMyKCkgPj4+IDA7CiAgICAgIGNvbnN0IG9mZnNldCA9IGZpbGUuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgY29uc3QgbGVuZ3RoID0gZmlsZS5nZXRJbnQzMigpID4+PiAwOwogICAgICBjb25zdCBwcmV2aW91c1Bvc2l0aW9uID0gZmlsZS5wb3M7CiAgICAgIGZpbGUucG9zID0gZmlsZS5zdGFydCB8fCAwOwogICAgICBmaWxlLnNraXAob2Zmc2V0KTsKICAgICAgY29uc3QgZGF0YSA9IGZpbGUuZ2V0Qnl0ZXMobGVuZ3RoKTsKICAgICAgZmlsZS5wb3MgPSBwcmV2aW91c1Bvc2l0aW9uOwogICAgICBpZiAodGFnID09PSAiaGVhZCIpIHsKICAgICAgICBkYXRhWzhdID0gZGF0YVs5XSA9IGRhdGFbMTBdID0gZGF0YVsxMV0gPSAwOwogICAgICAgIGRhdGFbMTddIHw9IDB4MjA7CiAgICAgIH0KICAgICAgcmV0dXJuIHsKICAgICAgICB0YWcsCiAgICAgICAgY2hlY2tzdW0sCiAgICAgICAgbGVuZ3RoLAogICAgICAgIG9mZnNldCwKICAgICAgICBkYXRhCiAgICAgIH07CiAgICB9CiAgICBmdW5jdGlvbiByZWFkT3BlblR5cGVIZWFkZXIodHRmKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgdmVyc2lvbjogdHRmLmdldFN0cmluZyg0KSwKICAgICAgICBudW1UYWJsZXM6IHR0Zi5nZXRVaW50MTYoKSwKICAgICAgICBzZWFyY2hSYW5nZTogdHRmLmdldFVpbnQxNigpLAogICAgICAgIGVudHJ5U2VsZWN0b3I6IHR0Zi5nZXRVaW50MTYoKSwKICAgICAgICByYW5nZVNoaWZ0OiB0dGYuZ2V0VWludDE2KCkKICAgICAgfTsKICAgIH0KICAgIGZ1bmN0aW9uIHJlYWRUcnVlVHlwZUNvbGxlY3Rpb25IZWFkZXIodHRjKSB7CiAgICAgIGNvbnN0IHR0Y1RhZyA9IHR0Yy5nZXRTdHJpbmcoNCk7CiAgICAgICgwLCBfdXRpbC5hc3NlcnQpKHR0Y1RhZyA9PT0gInR0Y2YiLCAiTXVzdCBiZSBhIFRydWVUeXBlIENvbGxlY3Rpb24gZm9udC4iKTsKICAgICAgY29uc3QgbWFqb3JWZXJzaW9uID0gdHRjLmdldFVpbnQxNigpOwogICAgICBjb25zdCBtaW5vclZlcnNpb24gPSB0dGMuZ2V0VWludDE2KCk7CiAgICAgIGNvbnN0IG51bUZvbnRzID0gdHRjLmdldEludDMyKCkgPj4+IDA7CiAgICAgIGNvbnN0IG9mZnNldFRhYmxlID0gW107CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtRm9udHM7IGkrKykgewogICAgICAgIG9mZnNldFRhYmxlLnB1c2godHRjLmdldEludDMyKCkgPj4+IDApOwogICAgICB9CiAgICAgIGNvbnN0IGhlYWRlciA9IHsKICAgICAgICB0dGNUYWcsCiAgICAgICAgbWFqb3JWZXJzaW9uLAogICAgICAgIG1pbm9yVmVyc2lvbiwKICAgICAgICBudW1Gb250cywKICAgICAgICBvZmZzZXRUYWJsZQogICAgICB9OwogICAgICBzd2l0Y2ggKG1ham9yVmVyc2lvbikgewogICAgICAgIGNhc2UgMToKICAgICAgICAgIHJldHVybiBoZWFkZXI7CiAgICAgICAgY2FzZSAyOgogICAgICAgICAgaGVhZGVyLmRzaWdUYWcgPSB0dGMuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICAgIGhlYWRlci5kc2lnTGVuZ3RoID0gdHRjLmdldEludDMyKCkgPj4+IDA7CiAgICAgICAgICBoZWFkZXIuZHNpZ09mZnNldCA9IHR0Yy5nZXRJbnQzMigpID4+PiAwOwogICAgICAgICAgcmV0dXJuIGhlYWRlcjsKICAgICAgfQogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYEludmFsaWQgVHJ1ZVR5cGUgQ29sbGVjdGlvbiBtYWpvclZlcnNpb246ICR7bWFqb3JWZXJzaW9ufS5gKTsKICAgIH0KICAgIGZ1bmN0aW9uIHJlYWRUcnVlVHlwZUNvbGxlY3Rpb25EYXRhKHR0YywgZm9udE5hbWUpIHsKICAgICAgY29uc3QgewogICAgICAgIG51bUZvbnRzLAogICAgICAgIG9mZnNldFRhYmxlCiAgICAgIH0gPSByZWFkVHJ1ZVR5cGVDb2xsZWN0aW9uSGVhZGVyKHR0Yyk7CiAgICAgIGNvbnN0IGZvbnROYW1lUGFydHMgPSBmb250TmFtZS5zcGxpdCgiKyIpOwogICAgICBsZXQgZmFsbGJhY2tEYXRhOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUZvbnRzOyBpKyspIHsKICAgICAgICB0dGMucG9zID0gKHR0Yy5zdGFydCB8fCAwKSArIG9mZnNldFRhYmxlW2ldOwogICAgICAgIGNvbnN0IHBvdGVudGlhbEhlYWRlciA9IHJlYWRPcGVuVHlwZUhlYWRlcih0dGMpOwogICAgICAgIGNvbnN0IHBvdGVudGlhbFRhYmxlcyA9IHJlYWRUYWJsZXModHRjLCBwb3RlbnRpYWxIZWFkZXIubnVtVGFibGVzKTsKICAgICAgICBpZiAoIXBvdGVudGlhbFRhYmxlcy5uYW1lKSB7CiAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoJ1RydWVUeXBlIENvbGxlY3Rpb24gZm9udCBtdXN0IGNvbnRhaW4gYSAibmFtZSIgdGFibGUuJyk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IFtuYW1lVGFibGVdID0gcmVhZE5hbWVUYWJsZShwb3RlbnRpYWxUYWJsZXMubmFtZSk7CiAgICAgICAgZm9yIChsZXQgaiA9IDAsIGpqID0gbmFtZVRhYmxlLmxlbmd0aDsgaiA8IGpqOyBqKyspIHsKICAgICAgICAgIGZvciAobGV0IGsgPSAwLCBrayA9IG5hbWVUYWJsZVtqXS5sZW5ndGg7IGsgPCBrazsgaysrKSB7CiAgICAgICAgICAgIGNvbnN0IG5hbWVFbnRyeSA9IG5hbWVUYWJsZVtqXVtrXSAmJiBuYW1lVGFibGVbal1ba10ucmVwbGFjZUFsbCgvXHMvZywgIiIpOwogICAgICAgICAgICBpZiAoIW5hbWVFbnRyeSkgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChuYW1lRW50cnkgPT09IGZvbnROYW1lKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgICAgIGhlYWRlcjogcG90ZW50aWFsSGVhZGVyLAogICAgICAgICAgICAgICAgdGFibGVzOiBwb3RlbnRpYWxUYWJsZXMKICAgICAgICAgICAgICB9OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChmb250TmFtZVBhcnRzLmxlbmd0aCA8IDIpIHsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBmb3IgKGNvbnN0IHBhcnQgb2YgZm9udE5hbWVQYXJ0cykgewogICAgICAgICAgICAgIGlmIChuYW1lRW50cnkgPT09IHBhcnQpIHsKICAgICAgICAgICAgICAgIGZhbGxiYWNrRGF0YSA9IHsKICAgICAgICAgICAgICAgICAgbmFtZTogcGFydCwKICAgICAgICAgICAgICAgICAgaGVhZGVyOiBwb3RlbnRpYWxIZWFkZXIsCiAgICAgICAgICAgICAgICAgIHRhYmxlczogcG90ZW50aWFsVGFibGVzCiAgICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoZmFsbGJhY2tEYXRhKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKGBUcnVlVHlwZSBDb2xsZWN0aW9uIGRvZXMgbm90IGNvbnRhaW4gIiR7Zm9udE5hbWV9IiBmb250LCBgICsgYGZhbGxpbmcgYmFjayB0byAiJHtmYWxsYmFja0RhdGEubmFtZX0iIGZvbnQgaW5zdGVhZC5gKTsKICAgICAgICByZXR1cm4gewogICAgICAgICAgaGVhZGVyOiBmYWxsYmFja0RhdGEuaGVhZGVyLAogICAgICAgICAgdGFibGVzOiBmYWxsYmFja0RhdGEudGFibGVzCiAgICAgICAgfTsKICAgICAgfQogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYFRydWVUeXBlIENvbGxlY3Rpb24gZG9lcyBub3QgY29udGFpbiAiJHtmb250TmFtZX0iIGZvbnQuYCk7CiAgICB9CiAgICBmdW5jdGlvbiByZWFkQ21hcFRhYmxlKGNtYXAsIGZpbGUsIGlzU3ltYm9saWNGb250LCBoYXNFbmNvZGluZykgewogICAgICBpZiAoIWNtYXApIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoIk5vIGNtYXAgdGFibGUgYXZhaWxhYmxlLiIpOwogICAgICAgIHJldHVybiB7CiAgICAgICAgICBwbGF0Zm9ybUlkOiAtMSwKICAgICAgICAgIGVuY29kaW5nSWQ6IC0xLAogICAgICAgICAgbWFwcGluZ3M6IFtdLAogICAgICAgICAgaGFzU2hvcnRDbWFwOiBmYWxzZQogICAgICAgIH07CiAgICAgIH0KICAgICAgbGV0IHNlZ21lbnQ7CiAgICAgIGxldCBzdGFydCA9IChmaWxlLnN0YXJ0IHx8IDApICsgY21hcC5vZmZzZXQ7CiAgICAgIGZpbGUucG9zID0gc3RhcnQ7CiAgICAgIGZpbGUuc2tpcCgyKTsKICAgICAgY29uc3QgbnVtVGFibGVzID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgbGV0IHBvdGVudGlhbFRhYmxlOwogICAgICBsZXQgY2FuQnJlYWsgPSBmYWxzZTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1UYWJsZXM7IGkrKykgewogICAgICAgIGNvbnN0IHBsYXRmb3JtSWQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgIGNvbnN0IGVuY29kaW5nSWQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgIGNvbnN0IG9mZnNldCA9IGZpbGUuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICBsZXQgdXNlVGFibGUgPSBmYWxzZTsKICAgICAgICBpZiAocG90ZW50aWFsVGFibGUgJiYgcG90ZW50aWFsVGFibGUucGxhdGZvcm1JZCA9PT0gcGxhdGZvcm1JZCAmJiBwb3RlbnRpYWxUYWJsZS5lbmNvZGluZ0lkID09PSBlbmNvZGluZ0lkKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaWYgKHBsYXRmb3JtSWQgPT09IDAgJiYgKGVuY29kaW5nSWQgPT09IDAgfHwgZW5jb2RpbmdJZCA9PT0gMSB8fCBlbmNvZGluZ0lkID09PSAzKSkgewogICAgICAgICAgdXNlVGFibGUgPSB0cnVlOwogICAgICAgIH0gZWxzZSBpZiAocGxhdGZvcm1JZCA9PT0gMSAmJiBlbmNvZGluZ0lkID09PSAwKSB7CiAgICAgICAgICB1c2VUYWJsZSA9IHRydWU7CiAgICAgICAgfSBlbHNlIGlmIChwbGF0Zm9ybUlkID09PSAzICYmIGVuY29kaW5nSWQgPT09IDEgJiYgKGhhc0VuY29kaW5nIHx8ICFwb3RlbnRpYWxUYWJsZSkpIHsKICAgICAgICAgIHVzZVRhYmxlID0gdHJ1ZTsKICAgICAgICAgIGlmICghaXNTeW1ib2xpY0ZvbnQpIHsKICAgICAgICAgICAgY2FuQnJlYWsgPSB0cnVlOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoaXNTeW1ib2xpY0ZvbnQgJiYgcGxhdGZvcm1JZCA9PT0gMyAmJiBlbmNvZGluZ0lkID09PSAwKSB7CiAgICAgICAgICB1c2VUYWJsZSA9IHRydWU7CiAgICAgICAgICBsZXQgY29ycmVjdGx5U29ydGVkID0gdHJ1ZTsKICAgICAgICAgIGlmIChpIDwgbnVtVGFibGVzIC0gMSkgewogICAgICAgICAgICBjb25zdCBuZXh0Qnl0ZXMgPSBmaWxlLnBlZWtCeXRlcygyKSwKICAgICAgICAgICAgICBuZXh0UGxhdGZvcm1JZCA9IGludDE2KG5leHRCeXRlc1swXSwgbmV4dEJ5dGVzWzFdKTsKICAgICAgICAgICAgaWYgKG5leHRQbGF0Zm9ybUlkIDwgcGxhdGZvcm1JZCkgewogICAgICAgICAgICAgIGNvcnJlY3RseVNvcnRlZCA9IGZhbHNlOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoY29ycmVjdGx5U29ydGVkKSB7CiAgICAgICAgICAgIGNhbkJyZWFrID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHVzZVRhYmxlKSB7CiAgICAgICAgICBwb3RlbnRpYWxUYWJsZSA9IHsKICAgICAgICAgICAgcGxhdGZvcm1JZCwKICAgICAgICAgICAgZW5jb2RpbmdJZCwKICAgICAgICAgICAgb2Zmc2V0CiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICBpZiAoY2FuQnJlYWspIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAocG90ZW50aWFsVGFibGUpIHsKICAgICAgICBmaWxlLnBvcyA9IHN0YXJ0ICsgcG90ZW50aWFsVGFibGUub2Zmc2V0OwogICAgICB9CiAgICAgIGlmICghcG90ZW50aWFsVGFibGUgfHwgZmlsZS5wZWVrQnl0ZSgpID09PSAtMSkgewogICAgICAgICgwLCBfdXRpbC53YXJuKSgiQ291bGQgbm90IGZpbmQgYSBwcmVmZXJyZWQgY21hcCB0YWJsZS4iKTsKICAgICAgICByZXR1cm4gewogICAgICAgICAgcGxhdGZvcm1JZDogLTEsCiAgICAgICAgICBlbmNvZGluZ0lkOiAtMSwKICAgICAgICAgIG1hcHBpbmdzOiBbXSwKICAgICAgICAgIGhhc1Nob3J0Q21hcDogZmFsc2UKICAgICAgICB9OwogICAgICB9CiAgICAgIGNvbnN0IGZvcm1hdCA9IGZpbGUuZ2V0VWludDE2KCk7CiAgICAgIGxldCBoYXNTaG9ydENtYXAgPSBmYWxzZTsKICAgICAgY29uc3QgbWFwcGluZ3MgPSBbXTsKICAgICAgbGV0IGosIGdseXBoSWQ7CiAgICAgIGlmIChmb3JtYXQgPT09IDApIHsKICAgICAgICBmaWxlLnNraXAoMiArIDIpOwogICAgICAgIGZvciAoaiA9IDA7IGogPCAyNTY7IGorKykgewogICAgICAgICAgY29uc3QgaW5kZXggPSBmaWxlLmdldEJ5dGUoKTsKICAgICAgICAgIGlmICghaW5kZXgpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBtYXBwaW5ncy5wdXNoKHsKICAgICAgICAgICAgY2hhckNvZGU6IGosCiAgICAgICAgICAgIGdseXBoSWQ6IGluZGV4CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaGFzU2hvcnRDbWFwID0gdHJ1ZTsKICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09IDIpIHsKICAgICAgICBmaWxlLnNraXAoMiArIDIpOwogICAgICAgIGNvbnN0IHN1YkhlYWRlcktleXMgPSBbXTsKICAgICAgICBsZXQgbWF4U3ViSGVhZGVyS2V5ID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgaSsrKSB7CiAgICAgICAgICBjb25zdCBzdWJIZWFkZXJLZXkgPSBmaWxlLmdldFVpbnQxNigpID4+IDM7CiAgICAgICAgICBzdWJIZWFkZXJLZXlzLnB1c2goc3ViSGVhZGVyS2V5KTsKICAgICAgICAgIG1heFN1YkhlYWRlcktleSA9IE1hdGgubWF4KHN1YkhlYWRlcktleSwgbWF4U3ViSGVhZGVyS2V5KTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc3ViSGVhZGVycyA9IFtdOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IG1heFN1YkhlYWRlcktleTsgaSsrKSB7CiAgICAgICAgICBzdWJIZWFkZXJzLnB1c2goewogICAgICAgICAgICBmaXJzdENvZGU6IGZpbGUuZ2V0VWludDE2KCksCiAgICAgICAgICAgIGVudHJ5Q291bnQ6IGZpbGUuZ2V0VWludDE2KCksCiAgICAgICAgICAgIGlkRGVsdGE6IHNpZ25lZEludDE2KGZpbGUuZ2V0Qnl0ZSgpLCBmaWxlLmdldEJ5dGUoKSksCiAgICAgICAgICAgIGlkUmFuZ2VQb3M6IGZpbGUucG9zICsgZmlsZS5nZXRVaW50MTYoKQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMjU2OyBpKyspIHsKICAgICAgICAgIGlmIChzdWJIZWFkZXJLZXlzW2ldID09PSAwKSB7CiAgICAgICAgICAgIGZpbGUucG9zID0gc3ViSGVhZGVyc1swXS5pZFJhbmdlUG9zICsgMiAqIGk7CiAgICAgICAgICAgIGdseXBoSWQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgICAgICBtYXBwaW5ncy5wdXNoKHsKICAgICAgICAgICAgICBjaGFyQ29kZTogaSwKICAgICAgICAgICAgICBnbHlwaElkCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgY29uc3QgcyA9IHN1YkhlYWRlcnNbc3ViSGVhZGVyS2V5c1tpXV07CiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBzLmVudHJ5Q291bnQ7IGorKykgewogICAgICAgICAgICAgIGNvbnN0IGNoYXJDb2RlID0gKGkgPDwgOCkgKyBqICsgcy5maXJzdENvZGU7CiAgICAgICAgICAgICAgZmlsZS5wb3MgPSBzLmlkUmFuZ2VQb3MgKyAyICogajsKICAgICAgICAgICAgICBnbHlwaElkID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICAgICAgICBpZiAoZ2x5cGhJZCAhPT0gMCkgewogICAgICAgICAgICAgICAgZ2x5cGhJZCA9IChnbHlwaElkICsgcy5pZERlbHRhKSAlIDY1NTM2OwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBtYXBwaW5ncy5wdXNoKHsKICAgICAgICAgICAgICAgIGNoYXJDb2RlLAogICAgICAgICAgICAgICAgZ2x5cGhJZAogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGZvcm1hdCA9PT0gNCkgewogICAgICAgIGZpbGUuc2tpcCgyICsgMik7CiAgICAgICAgY29uc3Qgc2VnQ291bnQgPSBmaWxlLmdldFVpbnQxNigpID4+IDE7CiAgICAgICAgZmlsZS5za2lwKDYpOwogICAgICAgIGNvbnN0IHNlZ21lbnRzID0gW107CiAgICAgICAgbGV0IHNlZ0luZGV4OwogICAgICAgIGZvciAoc2VnSW5kZXggPSAwOyBzZWdJbmRleCA8IHNlZ0NvdW50OyBzZWdJbmRleCsrKSB7CiAgICAgICAgICBzZWdtZW50cy5wdXNoKHsKICAgICAgICAgICAgZW5kOiBmaWxlLmdldFVpbnQxNigpCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgZmlsZS5za2lwKDIpOwogICAgICAgIGZvciAoc2VnSW5kZXggPSAwOyBzZWdJbmRleCA8IHNlZ0NvdW50OyBzZWdJbmRleCsrKSB7CiAgICAgICAgICBzZWdtZW50c1tzZWdJbmRleF0uc3RhcnQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgIH0KICAgICAgICBmb3IgKHNlZ0luZGV4ID0gMDsgc2VnSW5kZXggPCBzZWdDb3VudDsgc2VnSW5kZXgrKykgewogICAgICAgICAgc2VnbWVudHNbc2VnSW5kZXhdLmRlbHRhID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICB9CiAgICAgICAgbGV0IG9mZnNldHNDb3VudCA9IDAsCiAgICAgICAgICBvZmZzZXRJbmRleDsKICAgICAgICBmb3IgKHNlZ0luZGV4ID0gMDsgc2VnSW5kZXggPCBzZWdDb3VudDsgc2VnSW5kZXgrKykgewogICAgICAgICAgc2VnbWVudCA9IHNlZ21lbnRzW3NlZ0luZGV4XTsKICAgICAgICAgIGNvbnN0IHJhbmdlT2Zmc2V0ID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICAgIGlmICghcmFuZ2VPZmZzZXQpIHsKICAgICAgICAgICAgc2VnbWVudC5vZmZzZXRJbmRleCA9IC0xOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIG9mZnNldEluZGV4ID0gKHJhbmdlT2Zmc2V0ID4+IDEpIC0gKHNlZ0NvdW50IC0gc2VnSW5kZXgpOwogICAgICAgICAgc2VnbWVudC5vZmZzZXRJbmRleCA9IG9mZnNldEluZGV4OwogICAgICAgICAgb2Zmc2V0c0NvdW50ID0gTWF0aC5tYXgob2Zmc2V0c0NvdW50LCBvZmZzZXRJbmRleCArIHNlZ21lbnQuZW5kIC0gc2VnbWVudC5zdGFydCArIDEpOwogICAgICAgIH0KICAgICAgICBjb25zdCBvZmZzZXRzID0gW107CiAgICAgICAgZm9yIChqID0gMDsgaiA8IG9mZnNldHNDb3VudDsgaisrKSB7CiAgICAgICAgICBvZmZzZXRzLnB1c2goZmlsZS5nZXRVaW50MTYoKSk7CiAgICAgICAgfQogICAgICAgIGZvciAoc2VnSW5kZXggPSAwOyBzZWdJbmRleCA8IHNlZ0NvdW50OyBzZWdJbmRleCsrKSB7CiAgICAgICAgICBzZWdtZW50ID0gc2VnbWVudHNbc2VnSW5kZXhdOwogICAgICAgICAgc3RhcnQgPSBzZWdtZW50LnN0YXJ0OwogICAgICAgICAgY29uc3QgZW5kID0gc2VnbWVudC5lbmQ7CiAgICAgICAgICBjb25zdCBkZWx0YSA9IHNlZ21lbnQuZGVsdGE7CiAgICAgICAgICBvZmZzZXRJbmRleCA9IHNlZ21lbnQub2Zmc2V0SW5kZXg7CiAgICAgICAgICBmb3IgKGogPSBzdGFydDsgaiA8PSBlbmQ7IGorKykgewogICAgICAgICAgICBpZiAoaiA9PT0gMHhmZmZmKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZ2x5cGhJZCA9IG9mZnNldEluZGV4IDwgMCA/IGogOiBvZmZzZXRzW29mZnNldEluZGV4ICsgaiAtIHN0YXJ0XTsKICAgICAgICAgICAgZ2x5cGhJZCA9IGdseXBoSWQgKyBkZWx0YSAmIDB4ZmZmZjsKICAgICAgICAgICAgbWFwcGluZ3MucHVzaCh7CiAgICAgICAgICAgICAgY2hhckNvZGU6IGosCiAgICAgICAgICAgICAgZ2x5cGhJZAogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoZm9ybWF0ID09PSA2KSB7CiAgICAgICAgZmlsZS5za2lwKDIgKyAyKTsKICAgICAgICBjb25zdCBmaXJzdENvZGUgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgIGNvbnN0IGVudHJ5Q291bnQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgIGZvciAoaiA9IDA7IGogPCBlbnRyeUNvdW50OyBqKyspIHsKICAgICAgICAgIGdseXBoSWQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgICAgY29uc3QgY2hhckNvZGUgPSBmaXJzdENvZGUgKyBqOwogICAgICAgICAgbWFwcGluZ3MucHVzaCh7CiAgICAgICAgICAgIGNoYXJDb2RlLAogICAgICAgICAgICBnbHlwaElkCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoZm9ybWF0ID09PSAxMikgewogICAgICAgIGZpbGUuc2tpcCgyICsgNCArIDQpOwogICAgICAgIGNvbnN0IG5Hcm91cHMgPSBmaWxlLmdldEludDMyKCkgPj4+IDA7CiAgICAgICAgZm9yIChqID0gMDsgaiA8IG5Hcm91cHM7IGorKykgewogICAgICAgICAgY29uc3Qgc3RhcnRDaGFyQ29kZSA9IGZpbGUuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICAgIGNvbnN0IGVuZENoYXJDb2RlID0gZmlsZS5nZXRJbnQzMigpID4+PiAwOwogICAgICAgICAgbGV0IGdseXBoQ29kZSA9IGZpbGUuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICAgIGZvciAobGV0IGNoYXJDb2RlID0gc3RhcnRDaGFyQ29kZTsgY2hhckNvZGUgPD0gZW5kQ2hhckNvZGU7IGNoYXJDb2RlKyspIHsKICAgICAgICAgICAgbWFwcGluZ3MucHVzaCh7CiAgICAgICAgICAgICAgY2hhckNvZGUsCiAgICAgICAgICAgICAgZ2x5cGhJZDogZ2x5cGhDb2RlKysKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgICgwLCBfdXRpbC53YXJuKSgiY21hcCB0YWJsZSBoYXMgdW5zdXBwb3J0ZWQgZm9ybWF0OiAiICsgZm9ybWF0KTsKICAgICAgICByZXR1cm4gewogICAgICAgICAgcGxhdGZvcm1JZDogLTEsCiAgICAgICAgICBlbmNvZGluZ0lkOiAtMSwKICAgICAgICAgIG1hcHBpbmdzOiBbXSwKICAgICAgICAgIGhhc1Nob3J0Q21hcDogZmFsc2UKICAgICAgICB9OwogICAgICB9CiAgICAgIG1hcHBpbmdzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHsKICAgICAgICByZXR1cm4gYS5jaGFyQ29kZSAtIGIuY2hhckNvZGU7CiAgICAgIH0pOwogICAgICBmb3IgKGxldCBpID0gMTsgaSA8IG1hcHBpbmdzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgaWYgKG1hcHBpbmdzW2kgLSAxXS5jaGFyQ29kZSA9PT0gbWFwcGluZ3NbaV0uY2hhckNvZGUpIHsKICAgICAgICAgIG1hcHBpbmdzLnNwbGljZShpLCAxKTsKICAgICAgICAgIGktLTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIHsKICAgICAgICBwbGF0Zm9ybUlkOiBwb3RlbnRpYWxUYWJsZS5wbGF0Zm9ybUlkLAogICAgICAgIGVuY29kaW5nSWQ6IHBvdGVudGlhbFRhYmxlLmVuY29kaW5nSWQsCiAgICAgICAgbWFwcGluZ3MsCiAgICAgICAgaGFzU2hvcnRDbWFwCiAgICAgIH07CiAgICB9CiAgICBmdW5jdGlvbiBzYW5pdGl6ZU1ldHJpY3MoZmlsZSwgaGVhZGVyLCBtZXRyaWNzLCBoZWFkVGFibGUsIG51bUdseXBocywgZHVwRmlyc3RFbnRyeSkgewogICAgICBpZiAoIWhlYWRlcikgewogICAgICAgIGlmIChtZXRyaWNzKSB7CiAgICAgICAgICBtZXRyaWNzLmRhdGEgPSBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgZmlsZS5wb3MgPSAoZmlsZS5zdGFydCB8fCAwKSArIGhlYWRlci5vZmZzZXQ7CiAgICAgIGZpbGUucG9zICs9IDQ7CiAgICAgIGZpbGUucG9zICs9IDI7CiAgICAgIGZpbGUucG9zICs9IDI7CiAgICAgIGZpbGUucG9zICs9IDI7CiAgICAgIGZpbGUucG9zICs9IDI7CiAgICAgIGZpbGUucG9zICs9IDI7CiAgICAgIGZpbGUucG9zICs9IDI7CiAgICAgIGZpbGUucG9zICs9IDI7CiAgICAgIGZpbGUucG9zICs9IDI7CiAgICAgIGZpbGUucG9zICs9IDI7CiAgICAgIGNvbnN0IGNhcmV0T2Zmc2V0ID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgZmlsZS5wb3MgKz0gODsKICAgICAgZmlsZS5wb3MgKz0gMjsKICAgICAgbGV0IG51bU9mTWV0cmljcyA9IGZpbGUuZ2V0VWludDE2KCk7CiAgICAgIGlmIChjYXJldE9mZnNldCAhPT0gMCkgewogICAgICAgIGNvbnN0IG1hY1N0eWxlID0gaW50MTYoaGVhZFRhYmxlLmRhdGFbNDRdLCBoZWFkVGFibGUuZGF0YVs0NV0pOwogICAgICAgIGlmICghKG1hY1N0eWxlICYgMikpIHsKICAgICAgICAgIGhlYWRlci5kYXRhWzIyXSA9IDA7CiAgICAgICAgICBoZWFkZXIuZGF0YVsyM10gPSAwOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAobnVtT2ZNZXRyaWNzID4gbnVtR2x5cGhzKSB7CiAgICAgICAgKDAsIF91dGlsLmluZm8pKGBUaGUgbnVtT2ZNZXRyaWNzICgke251bU9mTWV0cmljc30pIHNob3VsZCBub3QgYmUgYCArIGBncmVhdGVyIHRoYW4gdGhlIG51bUdseXBocyAoJHtudW1HbHlwaHN9KS5gKTsKICAgICAgICBudW1PZk1ldHJpY3MgPSBudW1HbHlwaHM7CiAgICAgICAgaGVhZGVyLmRhdGFbMzRdID0gKG51bU9mTWV0cmljcyAmIDB4ZmYwMCkgPj4gODsKICAgICAgICBoZWFkZXIuZGF0YVszNV0gPSBudW1PZk1ldHJpY3MgJiAweDAwZmY7CiAgICAgIH0KICAgICAgY29uc3QgbnVtT2ZTaWRlYmVhcmluZ3MgPSBudW1HbHlwaHMgLSBudW1PZk1ldHJpY3M7CiAgICAgIGNvbnN0IG51bU1pc3NpbmcgPSBudW1PZlNpZGViZWFyaW5ncyAtIChtZXRyaWNzLmxlbmd0aCAtIG51bU9mTWV0cmljcyAqIDQgPj4gMSk7CiAgICAgIGlmIChudW1NaXNzaW5nID4gMCkgewogICAgICAgIGNvbnN0IGVudHJpZXMgPSBuZXcgVWludDhBcnJheShtZXRyaWNzLmxlbmd0aCArIG51bU1pc3NpbmcgKiAyKTsKICAgICAgICBlbnRyaWVzLnNldChtZXRyaWNzLmRhdGEpOwogICAgICAgIGlmIChkdXBGaXJzdEVudHJ5KSB7CiAgICAgICAgICBlbnRyaWVzW21ldHJpY3MubGVuZ3RoXSA9IG1ldHJpY3MuZGF0YVsyXTsKICAgICAgICAgIGVudHJpZXNbbWV0cmljcy5sZW5ndGggKyAxXSA9IG1ldHJpY3MuZGF0YVszXTsKICAgICAgICB9CiAgICAgICAgbWV0cmljcy5kYXRhID0gZW50cmllczsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gc2FuaXRpemVHbHlwaChzb3VyY2UsIHNvdXJjZVN0YXJ0LCBzb3VyY2VFbmQsIGRlc3QsIGRlc3RTdGFydCwgaGludHNWYWxpZCkgewogICAgICBjb25zdCBnbHlwaFByb2ZpbGUgPSB7CiAgICAgICAgbGVuZ3RoOiAwLAogICAgICAgIHNpemVPZkluc3RydWN0aW9uczogMAogICAgICB9OwogICAgICBpZiAoc291cmNlRW5kIC0gc291cmNlU3RhcnQgPD0gMTIpIHsKICAgICAgICByZXR1cm4gZ2x5cGhQcm9maWxlOwogICAgICB9CiAgICAgIGNvbnN0IGdseWYgPSBzb3VyY2Uuc3ViYXJyYXkoc291cmNlU3RhcnQsIHNvdXJjZUVuZCk7CiAgICAgIGxldCBjb250b3Vyc0NvdW50ID0gc2lnbmVkSW50MTYoZ2x5ZlswXSwgZ2x5ZlsxXSk7CiAgICAgIGlmIChjb250b3Vyc0NvdW50IDwgMCkgewogICAgICAgIGNvbnRvdXJzQ291bnQgPSAtMTsKICAgICAgICB3cml0ZVNpZ25lZEludDE2KGdseWYsIDAsIGNvbnRvdXJzQ291bnQpOwogICAgICAgIGRlc3Quc2V0KGdseWYsIGRlc3RTdGFydCk7CiAgICAgICAgZ2x5cGhQcm9maWxlLmxlbmd0aCA9IGdseWYubGVuZ3RoOwogICAgICAgIHJldHVybiBnbHlwaFByb2ZpbGU7CiAgICAgIH0KICAgICAgbGV0IGksCiAgICAgICAgaiA9IDEwLAogICAgICAgIGZsYWdzQ291bnQgPSAwOwogICAgICBmb3IgKGkgPSAwOyBpIDwgY29udG91cnNDb3VudDsgaSsrKSB7CiAgICAgICAgY29uc3QgZW5kUG9pbnQgPSBnbHlmW2pdIDw8IDggfCBnbHlmW2ogKyAxXTsKICAgICAgICBmbGFnc0NvdW50ID0gZW5kUG9pbnQgKyAxOwogICAgICAgIGogKz0gMjsKICAgICAgfQogICAgICBjb25zdCBpbnN0cnVjdGlvbnNTdGFydCA9IGo7CiAgICAgIGNvbnN0IGluc3RydWN0aW9uc0xlbmd0aCA9IGdseWZbal0gPDwgOCB8IGdseWZbaiArIDFdOwogICAgICBnbHlwaFByb2ZpbGUuc2l6ZU9mSW5zdHJ1Y3Rpb25zID0gaW5zdHJ1Y3Rpb25zTGVuZ3RoOwogICAgICBqICs9IDIgKyBpbnN0cnVjdGlvbnNMZW5ndGg7CiAgICAgIGNvbnN0IGluc3RydWN0aW9uc0VuZCA9IGo7CiAgICAgIGxldCBjb29yZGluYXRlc0xlbmd0aCA9IDA7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBmbGFnc0NvdW50OyBpKyspIHsKICAgICAgICBjb25zdCBmbGFnID0gZ2x5ZltqKytdOwogICAgICAgIGlmIChmbGFnICYgMHhjMCkgewogICAgICAgICAgZ2x5ZltqIC0gMV0gPSBmbGFnICYgMHgzZjsKICAgICAgICB9CiAgICAgICAgbGV0IHhMZW5ndGggPSAyOwogICAgICAgIGlmIChmbGFnICYgMikgewogICAgICAgICAgeExlbmd0aCA9IDE7CiAgICAgICAgfSBlbHNlIGlmIChmbGFnICYgMTYpIHsKICAgICAgICAgIHhMZW5ndGggPSAwOwogICAgICAgIH0KICAgICAgICBsZXQgeUxlbmd0aCA9IDI7CiAgICAgICAgaWYgKGZsYWcgJiA0KSB7CiAgICAgICAgICB5TGVuZ3RoID0gMTsKICAgICAgICB9IGVsc2UgaWYgKGZsYWcgJiAzMikgewogICAgICAgICAgeUxlbmd0aCA9IDA7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHh5TGVuZ3RoID0geExlbmd0aCArIHlMZW5ndGg7CiAgICAgICAgY29vcmRpbmF0ZXNMZW5ndGggKz0geHlMZW5ndGg7CiAgICAgICAgaWYgKGZsYWcgJiA4KSB7CiAgICAgICAgICBjb25zdCByZXBlYXQgPSBnbHlmW2orK107CiAgICAgICAgICBpICs9IHJlcGVhdDsKICAgICAgICAgIGNvb3JkaW5hdGVzTGVuZ3RoICs9IHJlcGVhdCAqIHh5TGVuZ3RoOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoY29vcmRpbmF0ZXNMZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gZ2x5cGhQcm9maWxlOwogICAgICB9CiAgICAgIGxldCBnbHlwaERhdGFMZW5ndGggPSBqICsgY29vcmRpbmF0ZXNMZW5ndGg7CiAgICAgIGlmIChnbHlwaERhdGFMZW5ndGggPiBnbHlmLmxlbmd0aCkgewogICAgICAgIHJldHVybiBnbHlwaFByb2ZpbGU7CiAgICAgIH0KICAgICAgaWYgKCFoaW50c1ZhbGlkICYmIGluc3RydWN0aW9uc0xlbmd0aCA+IDApIHsKICAgICAgICBkZXN0LnNldChnbHlmLnN1YmFycmF5KDAsIGluc3RydWN0aW9uc1N0YXJ0KSwgZGVzdFN0YXJ0KTsKICAgICAgICBkZXN0LnNldChbMCwgMF0sIGRlc3RTdGFydCArIGluc3RydWN0aW9uc1N0YXJ0KTsKICAgICAgICBkZXN0LnNldChnbHlmLnN1YmFycmF5KGluc3RydWN0aW9uc0VuZCwgZ2x5cGhEYXRhTGVuZ3RoKSwgZGVzdFN0YXJ0ICsgaW5zdHJ1Y3Rpb25zU3RhcnQgKyAyKTsKICAgICAgICBnbHlwaERhdGFMZW5ndGggLT0gaW5zdHJ1Y3Rpb25zTGVuZ3RoOwogICAgICAgIGlmIChnbHlmLmxlbmd0aCAtIGdseXBoRGF0YUxlbmd0aCA+IDMpIHsKICAgICAgICAgIGdseXBoRGF0YUxlbmd0aCA9IGdseXBoRGF0YUxlbmd0aCArIDMgJiB+MzsKICAgICAgICB9CiAgICAgICAgZ2x5cGhQcm9maWxlLmxlbmd0aCA9IGdseXBoRGF0YUxlbmd0aDsKICAgICAgICByZXR1cm4gZ2x5cGhQcm9maWxlOwogICAgICB9CiAgICAgIGlmIChnbHlmLmxlbmd0aCAtIGdseXBoRGF0YUxlbmd0aCA+IDMpIHsKICAgICAgICBnbHlwaERhdGFMZW5ndGggPSBnbHlwaERhdGFMZW5ndGggKyAzICYgfjM7CiAgICAgICAgZGVzdC5zZXQoZ2x5Zi5zdWJhcnJheSgwLCBnbHlwaERhdGFMZW5ndGgpLCBkZXN0U3RhcnQpOwogICAgICAgIGdseXBoUHJvZmlsZS5sZW5ndGggPSBnbHlwaERhdGFMZW5ndGg7CiAgICAgICAgcmV0dXJuIGdseXBoUHJvZmlsZTsKICAgICAgfQogICAgICBkZXN0LnNldChnbHlmLCBkZXN0U3RhcnQpOwogICAgICBnbHlwaFByb2ZpbGUubGVuZ3RoID0gZ2x5Zi5sZW5ndGg7CiAgICAgIHJldHVybiBnbHlwaFByb2ZpbGU7CiAgICB9CiAgICBmdW5jdGlvbiBzYW5pdGl6ZUhlYWQoaGVhZCwgbnVtR2x5cGhzLCBsb2NhTGVuZ3RoKSB7CiAgICAgIGNvbnN0IGRhdGEgPSBoZWFkLmRhdGE7CiAgICAgIGNvbnN0IHZlcnNpb24gPSBpbnQzMihkYXRhWzBdLCBkYXRhWzFdLCBkYXRhWzJdLCBkYXRhWzNdKTsKICAgICAgaWYgKHZlcnNpb24gPj4gMTYgIT09IDEpIHsKICAgICAgICAoMCwgX3V0aWwuaW5mbykoIkF0dGVtcHRpbmcgdG8gZml4IGludmFsaWQgdmVyc2lvbiBpbiBoZWFkIHRhYmxlOiAiICsgdmVyc2lvbik7CiAgICAgICAgZGF0YVswXSA9IDA7CiAgICAgICAgZGF0YVsxXSA9IDE7CiAgICAgICAgZGF0YVsyXSA9IDA7CiAgICAgICAgZGF0YVszXSA9IDA7CiAgICAgIH0KICAgICAgY29uc3QgaW5kZXhUb0xvY0Zvcm1hdCA9IGludDE2KGRhdGFbNTBdLCBkYXRhWzUxXSk7CiAgICAgIGlmIChpbmRleFRvTG9jRm9ybWF0IDwgMCB8fCBpbmRleFRvTG9jRm9ybWF0ID4gMSkgewogICAgICAgICgwLCBfdXRpbC5pbmZvKSgiQXR0ZW1wdGluZyB0byBmaXggaW52YWxpZCBpbmRleFRvTG9jRm9ybWF0IGluIGhlYWQgdGFibGU6ICIgKyBpbmRleFRvTG9jRm9ybWF0KTsKICAgICAgICBjb25zdCBudW1HbHlwaHNQbHVzT25lID0gbnVtR2x5cGhzICsgMTsKICAgICAgICBpZiAobG9jYUxlbmd0aCA9PT0gbnVtR2x5cGhzUGx1c09uZSA8PCAxKSB7CiAgICAgICAgICBkYXRhWzUwXSA9IDA7CiAgICAgICAgICBkYXRhWzUxXSA9IDA7CiAgICAgICAgfSBlbHNlIGlmIChsb2NhTGVuZ3RoID09PSBudW1HbHlwaHNQbHVzT25lIDw8IDIpIHsKICAgICAgICAgIGRhdGFbNTBdID0gMDsKICAgICAgICAgIGRhdGFbNTFdID0gMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJDb3VsZCBub3QgZml4IGluZGV4VG9Mb2NGb3JtYXQ6ICIgKyBpbmRleFRvTG9jRm9ybWF0KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIHNhbml0aXplR2x5cGhMb2NhdGlvbnMobG9jYSwgZ2x5ZiwgbnVtR2x5cGhzLCBpc0dseXBoTG9jYXRpb25zTG9uZywgaGludHNWYWxpZCwgZHVwRmlyc3RFbnRyeSwgbWF4U2l6ZU9mSW5zdHJ1Y3Rpb25zKSB7CiAgICAgIGxldCBpdGVtU2l6ZSwgaXRlbURlY29kZSwgaXRlbUVuY29kZTsKICAgICAgaWYgKGlzR2x5cGhMb2NhdGlvbnNMb25nKSB7CiAgICAgICAgaXRlbVNpemUgPSA0OwogICAgICAgIGl0ZW1EZWNvZGUgPSBmdW5jdGlvbiBmb250SXRlbURlY29kZUxvbmcoZGF0YSwgb2Zmc2V0KSB7CiAgICAgICAgICByZXR1cm4gZGF0YVtvZmZzZXRdIDw8IDI0IHwgZGF0YVtvZmZzZXQgKyAxXSA8PCAxNiB8IGRhdGFbb2Zmc2V0ICsgMl0gPDwgOCB8IGRhdGFbb2Zmc2V0ICsgM107CiAgICAgICAgfTsKICAgICAgICBpdGVtRW5jb2RlID0gZnVuY3Rpb24gZm9udEl0ZW1FbmNvZGVMb25nKGRhdGEsIG9mZnNldCwgdmFsdWUpIHsKICAgICAgICAgIGRhdGFbb2Zmc2V0XSA9IHZhbHVlID4+PiAyNCAmIDB4ZmY7CiAgICAgICAgICBkYXRhW29mZnNldCArIDFdID0gdmFsdWUgPj4gMTYgJiAweGZmOwogICAgICAgICAgZGF0YVtvZmZzZXQgKyAyXSA9IHZhbHVlID4+IDggJiAweGZmOwogICAgICAgICAgZGF0YVtvZmZzZXQgKyAzXSA9IHZhbHVlICYgMHhmZjsKICAgICAgICB9OwogICAgICB9IGVsc2UgewogICAgICAgIGl0ZW1TaXplID0gMjsKICAgICAgICBpdGVtRGVjb2RlID0gZnVuY3Rpb24gZm9udEl0ZW1EZWNvZGUoZGF0YSwgb2Zmc2V0KSB7CiAgICAgICAgICByZXR1cm4gZGF0YVtvZmZzZXRdIDw8IDkgfCBkYXRhW29mZnNldCArIDFdIDw8IDE7CiAgICAgICAgfTsKICAgICAgICBpdGVtRW5jb2RlID0gZnVuY3Rpb24gZm9udEl0ZW1FbmNvZGUoZGF0YSwgb2Zmc2V0LCB2YWx1ZSkgewogICAgICAgICAgZGF0YVtvZmZzZXRdID0gdmFsdWUgPj4gOSAmIDB4ZmY7CiAgICAgICAgICBkYXRhW29mZnNldCArIDFdID0gdmFsdWUgPj4gMSAmIDB4ZmY7CiAgICAgICAgfTsKICAgICAgfQogICAgICBjb25zdCBudW1HbHlwaHNPdXQgPSBkdXBGaXJzdEVudHJ5ID8gbnVtR2x5cGhzICsgMSA6IG51bUdseXBoczsKICAgICAgY29uc3QgbG9jYURhdGFTaXplID0gaXRlbVNpemUgKiAoMSArIG51bUdseXBoc091dCk7CiAgICAgIGNvbnN0IGxvY2FEYXRhID0gbmV3IFVpbnQ4QXJyYXkobG9jYURhdGFTaXplKTsKICAgICAgbG9jYURhdGEuc2V0KGxvY2EuZGF0YS5zdWJhcnJheSgwLCBsb2NhRGF0YVNpemUpKTsKICAgICAgbG9jYS5kYXRhID0gbG9jYURhdGE7CiAgICAgIGNvbnN0IG9sZEdseWZEYXRhID0gZ2x5Zi5kYXRhOwogICAgICBjb25zdCBvbGRHbHlmRGF0YUxlbmd0aCA9IG9sZEdseWZEYXRhLmxlbmd0aDsKICAgICAgY29uc3QgbmV3R2x5ZkRhdGEgPSBuZXcgVWludDhBcnJheShvbGRHbHlmRGF0YUxlbmd0aCk7CiAgICAgIGxldCBpLCBqOwogICAgICBjb25zdCBsb2NhRW50cmllcyA9IFtdOwogICAgICBmb3IgKGkgPSAwLCBqID0gMDsgaSA8IG51bUdseXBocyArIDE7IGkrKywgaiArPSBpdGVtU2l6ZSkgewogICAgICAgIGxldCBvZmZzZXQgPSBpdGVtRGVjb2RlKGxvY2FEYXRhLCBqKTsKICAgICAgICBpZiAob2Zmc2V0ID4gb2xkR2x5ZkRhdGFMZW5ndGgpIHsKICAgICAgICAgIG9mZnNldCA9IG9sZEdseWZEYXRhTGVuZ3RoOwogICAgICAgIH0KICAgICAgICBsb2NhRW50cmllcy5wdXNoKHsKICAgICAgICAgIGluZGV4OiBpLAogICAgICAgICAgb2Zmc2V0LAogICAgICAgICAgZW5kT2Zmc2V0OiAwCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgbG9jYUVudHJpZXMuc29ydCgoYSwgYikgPT4gewogICAgICAgIHJldHVybiBhLm9mZnNldCAtIGIub2Zmc2V0OwogICAgICB9KTsKICAgICAgZm9yIChpID0gMDsgaSA8IG51bUdseXBoczsgaSsrKSB7CiAgICAgICAgbG9jYUVudHJpZXNbaV0uZW5kT2Zmc2V0ID0gbG9jYUVudHJpZXNbaSArIDFdLm9mZnNldDsKICAgICAgfQogICAgICBsb2NhRW50cmllcy5zb3J0KChhLCBiKSA9PiB7CiAgICAgICAgcmV0dXJuIGEuaW5kZXggLSBiLmluZGV4OwogICAgICB9KTsKICAgICAgZm9yIChpID0gMDsgaSA8IG51bUdseXBoczsgaSsrKSB7CiAgICAgICAgY29uc3QgewogICAgICAgICAgb2Zmc2V0LAogICAgICAgICAgZW5kT2Zmc2V0CiAgICAgICAgfSA9IGxvY2FFbnRyaWVzW2ldOwogICAgICAgIGlmIChvZmZzZXQgIT09IDAgfHwgZW5kT2Zmc2V0ICE9PSAwKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgY29uc3QgbmV4dE9mZnNldCA9IGxvY2FFbnRyaWVzW2kgKyAxXS5vZmZzZXQ7CiAgICAgICAgaWYgKG5leHRPZmZzZXQgPT09IDApIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBsb2NhRW50cmllc1tpXS5lbmRPZmZzZXQgPSBuZXh0T2Zmc2V0OwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNvbnN0IG1pc3NpbmdHbHlwaHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBsZXQgd3JpdGVPZmZzZXQgPSAwOwogICAgICBpdGVtRW5jb2RlKGxvY2FEYXRhLCAwLCB3cml0ZU9mZnNldCk7CiAgICAgIGZvciAoaSA9IDAsIGogPSBpdGVtU2l6ZTsgaSA8IG51bUdseXBoczsgaSsrLCBqICs9IGl0ZW1TaXplKSB7CiAgICAgICAgY29uc3QgZ2x5cGhQcm9maWxlID0gc2FuaXRpemVHbHlwaChvbGRHbHlmRGF0YSwgbG9jYUVudHJpZXNbaV0ub2Zmc2V0LCBsb2NhRW50cmllc1tpXS5lbmRPZmZzZXQsIG5ld0dseWZEYXRhLCB3cml0ZU9mZnNldCwgaGludHNWYWxpZCk7CiAgICAgICAgY29uc3QgbmV3TGVuZ3RoID0gZ2x5cGhQcm9maWxlLmxlbmd0aDsKICAgICAgICBpZiAobmV3TGVuZ3RoID09PSAwKSB7CiAgICAgICAgICBtaXNzaW5nR2x5cGhzW2ldID0gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgaWYgKGdseXBoUHJvZmlsZS5zaXplT2ZJbnN0cnVjdGlvbnMgPiBtYXhTaXplT2ZJbnN0cnVjdGlvbnMpIHsKICAgICAgICAgIG1heFNpemVPZkluc3RydWN0aW9ucyA9IGdseXBoUHJvZmlsZS5zaXplT2ZJbnN0cnVjdGlvbnM7CiAgICAgICAgfQogICAgICAgIHdyaXRlT2Zmc2V0ICs9IG5ld0xlbmd0aDsKICAgICAgICBpdGVtRW5jb2RlKGxvY2FEYXRhLCBqLCB3cml0ZU9mZnNldCk7CiAgICAgIH0KICAgICAgaWYgKHdyaXRlT2Zmc2V0ID09PSAwKSB7CiAgICAgICAgY29uc3Qgc2ltcGxlR2x5cGggPSBuZXcgVWludDhBcnJheShbMCwgMSwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgNDksIDBdKTsKICAgICAgICBmb3IgKGkgPSAwLCBqID0gaXRlbVNpemU7IGkgPCBudW1HbHlwaHNPdXQ7IGkrKywgaiArPSBpdGVtU2l6ZSkgewogICAgICAgICAgaXRlbUVuY29kZShsb2NhRGF0YSwgaiwgc2ltcGxlR2x5cGgubGVuZ3RoKTsKICAgICAgICB9CiAgICAgICAgZ2x5Zi5kYXRhID0gc2ltcGxlR2x5cGg7CiAgICAgIH0gZWxzZSBpZiAoZHVwRmlyc3RFbnRyeSkgewogICAgICAgIGNvbnN0IGZpcnN0RW50cnlMZW5ndGggPSBpdGVtRGVjb2RlKGxvY2FEYXRhLCBpdGVtU2l6ZSk7CiAgICAgICAgaWYgKG5ld0dseWZEYXRhLmxlbmd0aCA+IGZpcnN0RW50cnlMZW5ndGggKyB3cml0ZU9mZnNldCkgewogICAgICAgICAgZ2x5Zi5kYXRhID0gbmV3R2x5ZkRhdGEuc3ViYXJyYXkoMCwgZmlyc3RFbnRyeUxlbmd0aCArIHdyaXRlT2Zmc2V0KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgZ2x5Zi5kYXRhID0gbmV3IFVpbnQ4QXJyYXkoZmlyc3RFbnRyeUxlbmd0aCArIHdyaXRlT2Zmc2V0KTsKICAgICAgICAgIGdseWYuZGF0YS5zZXQobmV3R2x5ZkRhdGEuc3ViYXJyYXkoMCwgd3JpdGVPZmZzZXQpKTsKICAgICAgICB9CiAgICAgICAgZ2x5Zi5kYXRhLnNldChuZXdHbHlmRGF0YS5zdWJhcnJheSgwLCBmaXJzdEVudHJ5TGVuZ3RoKSwgd3JpdGVPZmZzZXQpOwogICAgICAgIGl0ZW1FbmNvZGUobG9jYS5kYXRhLCBsb2NhRGF0YS5sZW5ndGggLSBpdGVtU2l6ZSwgd3JpdGVPZmZzZXQgKyBmaXJzdEVudHJ5TGVuZ3RoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBnbHlmLmRhdGEgPSBuZXdHbHlmRGF0YS5zdWJhcnJheSgwLCB3cml0ZU9mZnNldCk7CiAgICAgIH0KICAgICAgcmV0dXJuIHsKICAgICAgICBtaXNzaW5nR2x5cGhzLAogICAgICAgIG1heFNpemVPZkluc3RydWN0aW9ucwogICAgICB9OwogICAgfQogICAgZnVuY3Rpb24gcmVhZFBvc3RTY3JpcHRUYWJsZShwb3N0LCBwcm9wZXJ0aWVzT2JqLCBtYXhwTnVtR2x5cGhzKSB7CiAgICAgIGNvbnN0IHN0YXJ0ID0gKGZvbnQuc3RhcnQgfHwgMCkgKyBwb3N0Lm9mZnNldDsKICAgICAgZm9udC5wb3MgPSBzdGFydDsKICAgICAgY29uc3QgbGVuZ3RoID0gcG9zdC5sZW5ndGgsCiAgICAgICAgZW5kID0gc3RhcnQgKyBsZW5ndGg7CiAgICAgIGNvbnN0IHZlcnNpb24gPSBmb250LmdldEludDMyKCk7CiAgICAgIGZvbnQuc2tpcCgyOCk7CiAgICAgIGxldCBnbHlwaE5hbWVzOwogICAgICBsZXQgdmFsaWQgPSB0cnVlOwogICAgICBsZXQgaTsKICAgICAgc3dpdGNoICh2ZXJzaW9uKSB7CiAgICAgICAgY2FzZSAweDAwMDEwMDAwOgogICAgICAgICAgZ2x5cGhOYW1lcyA9IF9mb250c191dGlscy5NYWNTdGFuZGFyZEdseXBoT3JkZXJpbmc7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4MDAwMjAwMDA6CiAgICAgICAgICBjb25zdCBudW1HbHlwaHMgPSBmb250LmdldFVpbnQxNigpOwogICAgICAgICAgaWYgKG51bUdseXBocyAhPT0gbWF4cE51bUdseXBocykgewogICAgICAgICAgICB2YWxpZCA9IGZhbHNlOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGdseXBoTmFtZUluZGV4ZXMgPSBbXTsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1HbHlwaHM7ICsraSkgewogICAgICAgICAgICBjb25zdCBpbmRleCA9IGZvbnQuZ2V0VWludDE2KCk7CiAgICAgICAgICAgIGlmIChpbmRleCA+PSAzMjc2OCkgewogICAgICAgICAgICAgIHZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZ2x5cGhOYW1lSW5kZXhlcy5wdXNoKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghdmFsaWQpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBjdXN0b21OYW1lcyA9IFtdLAogICAgICAgICAgICBzdHJCdWYgPSBbXTsKICAgICAgICAgIHdoaWxlIChmb250LnBvcyA8IGVuZCkgewogICAgICAgICAgICBjb25zdCBzdHJpbmdMZW5ndGggPSBmb250LmdldEJ5dGUoKTsKICAgICAgICAgICAgc3RyQnVmLmxlbmd0aCA9IHN0cmluZ0xlbmd0aDsKICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHN0cmluZ0xlbmd0aDsgKytpKSB7CiAgICAgICAgICAgICAgc3RyQnVmW2ldID0gU3RyaW5nLmZyb21DaGFyQ29kZShmb250LmdldEJ5dGUoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY3VzdG9tTmFtZXMucHVzaChzdHJCdWYuam9pbigiIikpOwogICAgICAgICAgfQogICAgICAgICAgZ2x5cGhOYW1lcyA9IFtdOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8IG51bUdseXBoczsgKytpKSB7CiAgICAgICAgICAgIGNvbnN0IGogPSBnbHlwaE5hbWVJbmRleGVzW2ldOwogICAgICAgICAgICBpZiAoaiA8IDI1OCkgewogICAgICAgICAgICAgIGdseXBoTmFtZXMucHVzaChfZm9udHNfdXRpbHMuTWFjU3RhbmRhcmRHbHlwaE9yZGVyaW5nW2pdKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBnbHlwaE5hbWVzLnB1c2goY3VzdG9tTmFtZXNbaiAtIDI1OF0pOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDAwMDMwMDAwOgogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiVW5rbm93bi91bnN1cHBvcnRlZCBwb3N0IHRhYmxlIHZlcnNpb24gIiArIHZlcnNpb24pOwogICAgICAgICAgdmFsaWQgPSBmYWxzZTsKICAgICAgICAgIGlmIChwcm9wZXJ0aWVzT2JqLmRlZmF1bHRFbmNvZGluZykgewogICAgICAgICAgICBnbHlwaE5hbWVzID0gcHJvcGVydGllc09iai5kZWZhdWx0RW5jb2Rpbmc7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBwcm9wZXJ0aWVzT2JqLmdseXBoTmFtZXMgPSBnbHlwaE5hbWVzOwogICAgICByZXR1cm4gdmFsaWQ7CiAgICB9CiAgICBmdW5jdGlvbiByZWFkTmFtZVRhYmxlKG5hbWVUYWJsZSkgewogICAgICBjb25zdCBzdGFydCA9IChmb250LnN0YXJ0IHx8IDApICsgbmFtZVRhYmxlLm9mZnNldDsKICAgICAgZm9udC5wb3MgPSBzdGFydDsKICAgICAgY29uc3QgbmFtZXMgPSBbW10sIFtdXSwKICAgICAgICByZWNvcmRzID0gW107CiAgICAgIGNvbnN0IGxlbmd0aCA9IG5hbWVUYWJsZS5sZW5ndGgsCiAgICAgICAgZW5kID0gc3RhcnQgKyBsZW5ndGg7CiAgICAgIGNvbnN0IGZvcm1hdCA9IGZvbnQuZ2V0VWludDE2KCk7CiAgICAgIGNvbnN0IEZPUk1BVF8wX0hFQURFUl9MRU5HVEggPSA2OwogICAgICBpZiAoZm9ybWF0ICE9PSAwIHx8IGxlbmd0aCA8IEZPUk1BVF8wX0hFQURFUl9MRU5HVEgpIHsKICAgICAgICByZXR1cm4gW25hbWVzLCByZWNvcmRzXTsKICAgICAgfQogICAgICBjb25zdCBudW1SZWNvcmRzID0gZm9udC5nZXRVaW50MTYoKTsKICAgICAgY29uc3Qgc3RyaW5nc1N0YXJ0ID0gZm9udC5nZXRVaW50MTYoKTsKICAgICAgY29uc3QgTkFNRV9SRUNPUkRfTEVOR1RIID0gMTI7CiAgICAgIGxldCBpLCBpaTsKICAgICAgZm9yIChpID0gMDsgaSA8IG51bVJlY29yZHMgJiYgZm9udC5wb3MgKyBOQU1FX1JFQ09SRF9MRU5HVEggPD0gZW5kOyBpKyspIHsKICAgICAgICBjb25zdCByID0gewogICAgICAgICAgcGxhdGZvcm06IGZvbnQuZ2V0VWludDE2KCksCiAgICAgICAgICBlbmNvZGluZzogZm9udC5nZXRVaW50MTYoKSwKICAgICAgICAgIGxhbmd1YWdlOiBmb250LmdldFVpbnQxNigpLAogICAgICAgICAgbmFtZTogZm9udC5nZXRVaW50MTYoKSwKICAgICAgICAgIGxlbmd0aDogZm9udC5nZXRVaW50MTYoKSwKICAgICAgICAgIG9mZnNldDogZm9udC5nZXRVaW50MTYoKQogICAgICAgIH07CiAgICAgICAgaWYgKGlzTWFjTmFtZVJlY29yZChyKSB8fCBpc1dpbk5hbWVSZWNvcmQocikpIHsKICAgICAgICAgIHJlY29yZHMucHVzaChyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgZm9yIChpID0gMCwgaWkgPSByZWNvcmRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb25zdCByZWNvcmQgPSByZWNvcmRzW2ldOwogICAgICAgIGlmIChyZWNvcmQubGVuZ3RoIDw9IDApIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBwb3MgPSBzdGFydCArIHN0cmluZ3NTdGFydCArIHJlY29yZC5vZmZzZXQ7CiAgICAgICAgaWYgKHBvcyArIHJlY29yZC5sZW5ndGggPiBlbmQpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBmb250LnBvcyA9IHBvczsKICAgICAgICBjb25zdCBuYW1lSW5kZXggPSByZWNvcmQubmFtZTsKICAgICAgICBpZiAocmVjb3JkLmVuY29kaW5nKSB7CiAgICAgICAgICBsZXQgc3RyID0gIiI7CiAgICAgICAgICBmb3IgKGxldCBqID0gMCwgamogPSByZWNvcmQubGVuZ3RoOyBqIDwgamo7IGogKz0gMikgewogICAgICAgICAgICBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShmb250LmdldFVpbnQxNigpKTsKICAgICAgICAgIH0KICAgICAgICAgIG5hbWVzWzFdW25hbWVJbmRleF0gPSBzdHI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG5hbWVzWzBdW25hbWVJbmRleF0gPSBmb250LmdldFN0cmluZyhyZWNvcmQubGVuZ3RoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIFtuYW1lcywgcmVjb3Jkc107CiAgICB9CiAgICBjb25zdCBUVE9wc1N0YWNrRGVsdGFzID0gWzAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIC0yLCAtMiwgLTIsIC0yLCAwLCAwLCAtMiwgLTUsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgMCwgMCwgLTEsIDAsIC0xLCAtMSwgLTEsIC0xLCAxLCAtMSwgLTk5OSwgMCwgMSwgMCwgLTEsIC0yLCAwLCAtMSwgLTIsIC0xLCAtMSwgMCwgLTEsIC0xLCAwLCAwLCAtOTk5LCAtOTk5LCAtMSwgLTEsIC0xLCAtMSwgLTIsIC05OTksIC0yLCAtMiwgLTk5OSwgMCwgLTIsIC0yLCAwLCAwLCAtMiwgMCwgLTIsIDAsIDAsIDAsIC0yLCAtMSwgLTEsIDEsIDEsIDAsIDAsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAwLCAwLCAtMSwgMCwgLTEsIC0xLCAwLCAtOTk5LCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAtMiwgLTk5OSwgLTk5OSwgLTk5OSwgLTk5OSwgLTk5OSwgLTEsIC0xLCAtMiwgLTIsIDAsIDAsIDAsIDAsIC0xLCAtMSwgLTk5OSwgLTIsIC0yLCAwLCAwLCAtMSwgLTIsIC0yLCAwLCAwLCAwLCAtMSwgLTEsIC0xLCAtMl07CiAgICBmdW5jdGlvbiBzYW5pdGl6ZVRUUHJvZ3JhbSh0YWJsZSwgdHRDb250ZXh0KSB7CiAgICAgIGxldCBkYXRhID0gdGFibGUuZGF0YTsKICAgICAgbGV0IGkgPSAwLAogICAgICAgIGosCiAgICAgICAgbiwKICAgICAgICBiLAogICAgICAgIGZ1bmNJZCwKICAgICAgICBwYywKICAgICAgICBsYXN0RW5kZiA9IDAsCiAgICAgICAgbGFzdERlZmYgPSAwOwogICAgICBjb25zdCBzdGFjayA9IFtdOwogICAgICBjb25zdCBjYWxsc3RhY2sgPSBbXTsKICAgICAgY29uc3QgZnVuY3Rpb25zQ2FsbGVkID0gW107CiAgICAgIGxldCB0b29Db21wbGV4VG9Gb2xsb3dGdW5jdGlvbnMgPSB0dENvbnRleHQudG9vQ29tcGxleFRvRm9sbG93RnVuY3Rpb25zOwogICAgICBsZXQgaW5GREVGID0gZmFsc2UsCiAgICAgICAgaWZMZXZlbCA9IDAsCiAgICAgICAgaW5FTFNFID0gMDsKICAgICAgZm9yIChsZXQgaWkgPSBkYXRhLmxlbmd0aDsgaSA8IGlpOykgewogICAgICAgIGNvbnN0IG9wID0gZGF0YVtpKytdOwogICAgICAgIGlmIChvcCA9PT0gMHg0MCkgewogICAgICAgICAgbiA9IGRhdGFbaSsrXTsKICAgICAgICAgIGlmIChpbkZERUYgfHwgaW5FTFNFKSB7CiAgICAgICAgICAgIGkgKz0gbjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBuOyBqKyspIHsKICAgICAgICAgICAgICBzdGFjay5wdXNoKGRhdGFbaSsrXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKG9wID09PSAweDQxKSB7CiAgICAgICAgICBuID0gZGF0YVtpKytdOwogICAgICAgICAgaWYgKGluRkRFRiB8fCBpbkVMU0UpIHsKICAgICAgICAgICAgaSArPSBuICogMjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBuOyBqKyspIHsKICAgICAgICAgICAgICBiID0gZGF0YVtpKytdOwogICAgICAgICAgICAgIHN0YWNrLnB1c2goYiA8PCA4IHwgZGF0YVtpKytdKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoKG9wICYgMHhmOCkgPT09IDB4YjApIHsKICAgICAgICAgIG4gPSBvcCAtIDB4YjAgKyAxOwogICAgICAgICAgaWYgKGluRkRFRiB8fCBpbkVMU0UpIHsKICAgICAgICAgICAgaSArPSBuOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IG47IGorKykgewogICAgICAgICAgICAgIHN0YWNrLnB1c2goZGF0YVtpKytdKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoKG9wICYgMHhmOCkgPT09IDB4YjgpIHsKICAgICAgICAgIG4gPSBvcCAtIDB4YjggKyAxOwogICAgICAgICAgaWYgKGluRkRFRiB8fCBpbkVMU0UpIHsKICAgICAgICAgICAgaSArPSBuICogMjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBuOyBqKyspIHsKICAgICAgICAgICAgICBiID0gZGF0YVtpKytdOwogICAgICAgICAgICAgIHN0YWNrLnB1c2goYiA8PCA4IHwgZGF0YVtpKytdKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAob3AgPT09IDB4MmIgJiYgIXRvb0NvbXBsZXhUb0ZvbGxvd0Z1bmN0aW9ucykgewogICAgICAgICAgaWYgKCFpbkZERUYgJiYgIWluRUxTRSkgewogICAgICAgICAgICBmdW5jSWQgPSBzdGFjay5hdCgtMSk7CiAgICAgICAgICAgIGlmIChpc05hTihmdW5jSWQpKSB7CiAgICAgICAgICAgICAgKDAsIF91dGlsLmluZm8pKCJUVDogQ0FMTCBlbXB0eSBzdGFjayAob3IgaW52YWxpZCBlbnRyeSkuIik7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdHRDb250ZXh0LmZ1bmN0aW9uc1VzZWRbZnVuY0lkXSA9IHRydWU7CiAgICAgICAgICAgICAgaWYgKGZ1bmNJZCBpbiB0dENvbnRleHQuZnVuY3Rpb25zU3RhY2tEZWx0YXMpIHsKICAgICAgICAgICAgICAgIGNvbnN0IG5ld1N0YWNrTGVuZ3RoID0gc3RhY2subGVuZ3RoICsgdHRDb250ZXh0LmZ1bmN0aW9uc1N0YWNrRGVsdGFzW2Z1bmNJZF07CiAgICAgICAgICAgICAgICBpZiAobmV3U3RhY2tMZW5ndGggPCAwKSB7CiAgICAgICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiVFQ6IENBTEwgaW52YWxpZCBmdW5jdGlvbnMgc3RhY2sgZGVsdGEuIik7CiAgICAgICAgICAgICAgICAgIHR0Q29udGV4dC5oaW50c1ZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHN0YWNrLmxlbmd0aCA9IG5ld1N0YWNrTGVuZ3RoOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAoZnVuY0lkIGluIHR0Q29udGV4dC5mdW5jdGlvbnNEZWZpbmVkICYmICFmdW5jdGlvbnNDYWxsZWQuaW5jbHVkZXMoZnVuY0lkKSkgewogICAgICAgICAgICAgICAgY2FsbHN0YWNrLnB1c2goewogICAgICAgICAgICAgICAgICBkYXRhLAogICAgICAgICAgICAgICAgICBpLAogICAgICAgICAgICAgICAgICBzdGFja1RvcDogc3RhY2subGVuZ3RoIC0gMQogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICBmdW5jdGlvbnNDYWxsZWQucHVzaChmdW5jSWQpOwogICAgICAgICAgICAgICAgcGMgPSB0dENvbnRleHQuZnVuY3Rpb25zRGVmaW5lZFtmdW5jSWRdOwogICAgICAgICAgICAgICAgaWYgKCFwYykgewogICAgICAgICAgICAgICAgICAoMCwgX3V0aWwud2FybikoIlRUOiBDQUxMIG5vbi1leGlzdGVudCBmdW5jdGlvbiIpOwogICAgICAgICAgICAgICAgICB0dENvbnRleHQuaGludHNWYWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBkYXRhID0gcGMuZGF0YTsKICAgICAgICAgICAgICAgIGkgPSBwYy5pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAob3AgPT09IDB4MmMgJiYgIXRvb0NvbXBsZXhUb0ZvbGxvd0Z1bmN0aW9ucykgewogICAgICAgICAgaWYgKGluRkRFRiB8fCBpbkVMU0UpIHsKICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJUVDogbmVzdGVkIEZERUZzIG5vdCBhbGxvd2VkIik7CiAgICAgICAgICAgIHRvb0NvbXBsZXhUb0ZvbGxvd0Z1bmN0aW9ucyA9IHRydWU7CiAgICAgICAgICB9CiAgICAgICAgICBpbkZERUYgPSB0cnVlOwogICAgICAgICAgbGFzdERlZmYgPSBpOwogICAgICAgICAgZnVuY0lkID0gc3RhY2sucG9wKCk7CiAgICAgICAgICB0dENvbnRleHQuZnVuY3Rpb25zRGVmaW5lZFtmdW5jSWRdID0gewogICAgICAgICAgICBkYXRhLAogICAgICAgICAgICBpCiAgICAgICAgICB9OwogICAgICAgIH0gZWxzZSBpZiAob3AgPT09IDB4MmQpIHsKICAgICAgICAgIGlmIChpbkZERUYpIHsKICAgICAgICAgICAgaW5GREVGID0gZmFsc2U7CiAgICAgICAgICAgIGxhc3RFbmRmID0gaTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHBjID0gY2FsbHN0YWNrLnBvcCgpOwogICAgICAgICAgICBpZiAoIXBjKSB7CiAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJUVDogRU5ERiBiYWQgc3RhY2siKTsKICAgICAgICAgICAgICB0dENvbnRleHQuaGludHNWYWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBmdW5jSWQgPSBmdW5jdGlvbnNDYWxsZWQucG9wKCk7CiAgICAgICAgICAgIGRhdGEgPSBwYy5kYXRhOwogICAgICAgICAgICBpID0gcGMuaTsKICAgICAgICAgICAgdHRDb250ZXh0LmZ1bmN0aW9uc1N0YWNrRGVsdGFzW2Z1bmNJZF0gPSBzdGFjay5sZW5ndGggLSBwYy5zdGFja1RvcDsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKG9wID09PSAweDg5KSB7CiAgICAgICAgICBpZiAoaW5GREVGIHx8IGluRUxTRSkgewogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoIlRUOiBuZXN0ZWQgSURFRnMgbm90IGFsbG93ZWQiKTsKICAgICAgICAgICAgdG9vQ29tcGxleFRvRm9sbG93RnVuY3Rpb25zID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICAgIGluRkRFRiA9IHRydWU7CiAgICAgICAgICBsYXN0RGVmZiA9IGk7CiAgICAgICAgfSBlbHNlIGlmIChvcCA9PT0gMHg1OCkgewogICAgICAgICAgKytpZkxldmVsOwogICAgICAgIH0gZWxzZSBpZiAob3AgPT09IDB4MWIpIHsKICAgICAgICAgIGluRUxTRSA9IGlmTGV2ZWw7CiAgICAgICAgfSBlbHNlIGlmIChvcCA9PT0gMHg1OSkgewogICAgICAgICAgaWYgKGluRUxTRSA9PT0gaWZMZXZlbCkgewogICAgICAgICAgICBpbkVMU0UgPSAwOwogICAgICAgICAgfQogICAgICAgICAgLS1pZkxldmVsOwogICAgICAgIH0gZWxzZSBpZiAob3AgPT09IDB4MWMpIHsKICAgICAgICAgIGlmICghaW5GREVGICYmICFpbkVMU0UpIHsKICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gc3RhY2suYXQoLTEpOwogICAgICAgICAgICBpZiAob2Zmc2V0ID4gMCkgewogICAgICAgICAgICAgIGkgKz0gb2Zmc2V0IC0gMTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoIWluRkRFRiAmJiAhaW5FTFNFKSB7CiAgICAgICAgICBsZXQgc3RhY2tEZWx0YSA9IDA7CiAgICAgICAgICBpZiAob3AgPD0gMHg4ZSkgewogICAgICAgICAgICBzdGFja0RlbHRhID0gVFRPcHNTdGFja0RlbHRhc1tvcF07CiAgICAgICAgICB9IGVsc2UgaWYgKG9wID49IDB4YzAgJiYgb3AgPD0gMHhkZikgewogICAgICAgICAgICBzdGFja0RlbHRhID0gLTE7CiAgICAgICAgICB9IGVsc2UgaWYgKG9wID49IDB4ZTApIHsKICAgICAgICAgICAgc3RhY2tEZWx0YSA9IC0yOwogICAgICAgICAgfQogICAgICAgICAgaWYgKG9wID49IDB4NzEgJiYgb3AgPD0gMHg3NSkgewogICAgICAgICAgICBuID0gc3RhY2sucG9wKCk7CiAgICAgICAgICAgIGlmICghaXNOYU4obikpIHsKICAgICAgICAgICAgICBzdGFja0RlbHRhID0gLW4gKiAyOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB3aGlsZSAoc3RhY2tEZWx0YSA8IDAgJiYgc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgICAgICBzdGFjay5wb3AoKTsKICAgICAgICAgICAgc3RhY2tEZWx0YSsrOwogICAgICAgICAgfQogICAgICAgICAgd2hpbGUgKHN0YWNrRGVsdGEgPiAwKSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goTmFOKTsKICAgICAgICAgICAgc3RhY2tEZWx0YS0tOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICB0dENvbnRleHQudG9vQ29tcGxleFRvRm9sbG93RnVuY3Rpb25zID0gdG9vQ29tcGxleFRvRm9sbG93RnVuY3Rpb25zOwogICAgICBjb25zdCBjb250ZW50ID0gW2RhdGFdOwogICAgICBpZiAoaSA+IGRhdGEubGVuZ3RoKSB7CiAgICAgICAgY29udGVudC5wdXNoKG5ldyBVaW50OEFycmF5KGkgLSBkYXRhLmxlbmd0aCkpOwogICAgICB9CiAgICAgIGlmIChsYXN0RGVmZiA+IGxhc3RFbmRmKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKCJUVDogY29tcGxlbWVudGluZyBhIG1pc3NpbmcgZnVuY3Rpb24gdGFpbCIpOwogICAgICAgIGNvbnRlbnQucHVzaChuZXcgVWludDhBcnJheShbMHgyMiwgMHgyZF0pKTsKICAgICAgfQogICAgICBmb2xkVFRUYWJsZSh0YWJsZSwgY29udGVudCk7CiAgICB9CiAgICBmdW5jdGlvbiBjaGVja0ludmFsaWRGdW5jdGlvbnModHRDb250ZXh0LCBtYXhGdW5jdGlvbkRlZnMpIHsKICAgICAgaWYgKHR0Q29udGV4dC50b29Db21wbGV4VG9Gb2xsb3dGdW5jdGlvbnMpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKHR0Q29udGV4dC5mdW5jdGlvbnNEZWZpbmVkLmxlbmd0aCA+IG1heEZ1bmN0aW9uRGVmcykgewogICAgICAgICgwLCBfdXRpbC53YXJuKSgiVFQ6IG1vcmUgZnVuY3Rpb25zIGRlZmluZWQgdGhhbiBleHBlY3RlZCIpOwogICAgICAgIHR0Q29udGV4dC5oaW50c1ZhbGlkID0gZmFsc2U7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGZvciAobGV0IGogPSAwLCBqaiA9IHR0Q29udGV4dC5mdW5jdGlvbnNVc2VkLmxlbmd0aDsgaiA8IGpqOyBqKyspIHsKICAgICAgICBpZiAoaiA+IG1heEZ1bmN0aW9uRGVmcykgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJUVDogaW52YWxpZCBmdW5jdGlvbiBpZDogIiArIGopOwogICAgICAgICAgdHRDb250ZXh0LmhpbnRzVmFsaWQgPSBmYWxzZTsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgaWYgKHR0Q29udGV4dC5mdW5jdGlvbnNVc2VkW2pdICYmICF0dENvbnRleHQuZnVuY3Rpb25zRGVmaW5lZFtqXSkgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJUVDogdW5kZWZpbmVkIGZ1bmN0aW9uOiAiICsgaik7CiAgICAgICAgICB0dENvbnRleHQuaGludHNWYWxpZCA9IGZhbHNlOwogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gZm9sZFRUVGFibGUodGFibGUsIGNvbnRlbnQpIHsKICAgICAgaWYgKGNvbnRlbnQubGVuZ3RoID4gMSkgewogICAgICAgIGxldCBuZXdMZW5ndGggPSAwOwogICAgICAgIGxldCBqLCBqajsKICAgICAgICBmb3IgKGogPSAwLCBqaiA9IGNvbnRlbnQubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICAgICAgbmV3TGVuZ3RoICs9IGNvbnRlbnRbal0ubGVuZ3RoOwogICAgICAgIH0KICAgICAgICBuZXdMZW5ndGggPSBuZXdMZW5ndGggKyAzICYgfjM7CiAgICAgICAgY29uc3QgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkobmV3TGVuZ3RoKTsKICAgICAgICBsZXQgcG9zID0gMDsKICAgICAgICBmb3IgKGogPSAwLCBqaiA9IGNvbnRlbnQubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICAgICAgcmVzdWx0LnNldChjb250ZW50W2pdLCBwb3MpOwogICAgICAgICAgcG9zICs9IGNvbnRlbnRbal0ubGVuZ3RoOwogICAgICAgIH0KICAgICAgICB0YWJsZS5kYXRhID0gcmVzdWx0OwogICAgICAgIHRhYmxlLmxlbmd0aCA9IG5ld0xlbmd0aDsKICAgICAgfQogICAgfQogICAgZnVuY3Rpb24gc2FuaXRpemVUVFByb2dyYW1zKGZwZ20sIHByZXAsIGN2dCwgbWF4RnVuY3Rpb25EZWZzKSB7CiAgICAgIGNvbnN0IHR0Q29udGV4dCA9IHsKICAgICAgICBmdW5jdGlvbnNEZWZpbmVkOiBbXSwKICAgICAgICBmdW5jdGlvbnNVc2VkOiBbXSwKICAgICAgICBmdW5jdGlvbnNTdGFja0RlbHRhczogW10sCiAgICAgICAgdG9vQ29tcGxleFRvRm9sbG93RnVuY3Rpb25zOiBmYWxzZSwKICAgICAgICBoaW50c1ZhbGlkOiB0cnVlCiAgICAgIH07CiAgICAgIGlmIChmcGdtKSB7CiAgICAgICAgc2FuaXRpemVUVFByb2dyYW0oZnBnbSwgdHRDb250ZXh0KTsKICAgICAgfQogICAgICBpZiAocHJlcCkgewogICAgICAgIHNhbml0aXplVFRQcm9ncmFtKHByZXAsIHR0Q29udGV4dCk7CiAgICAgIH0KICAgICAgaWYgKGZwZ20pIHsKICAgICAgICBjaGVja0ludmFsaWRGdW5jdGlvbnModHRDb250ZXh0LCBtYXhGdW5jdGlvbkRlZnMpOwogICAgICB9CiAgICAgIGlmIChjdnQgJiYgY3Z0Lmxlbmd0aCAmIDEpIHsKICAgICAgICBjb25zdCBjdnREYXRhID0gbmV3IFVpbnQ4QXJyYXkoY3Z0Lmxlbmd0aCArIDEpOwogICAgICAgIGN2dERhdGEuc2V0KGN2dC5kYXRhKTsKICAgICAgICBjdnQuZGF0YSA9IGN2dERhdGE7CiAgICAgIH0KICAgICAgcmV0dXJuIHR0Q29udGV4dC5oaW50c1ZhbGlkOwogICAgfQogICAgZm9udCA9IG5ldyBfc3RyZWFtLlN0cmVhbShuZXcgVWludDhBcnJheShmb250LmdldEJ5dGVzKCkpKTsKICAgIGxldCBoZWFkZXIsIHRhYmxlczsKICAgIGlmIChpc1RydWVUeXBlQ29sbGVjdGlvbkZpbGUoZm9udCkpIHsKICAgICAgY29uc3QgdHRjRGF0YSA9IHJlYWRUcnVlVHlwZUNvbGxlY3Rpb25EYXRhKGZvbnQsIHRoaXMubmFtZSk7CiAgICAgIGhlYWRlciA9IHR0Y0RhdGEuaGVhZGVyOwogICAgICB0YWJsZXMgPSB0dGNEYXRhLnRhYmxlczsKICAgIH0gZWxzZSB7CiAgICAgIGhlYWRlciA9IHJlYWRPcGVuVHlwZUhlYWRlcihmb250KTsKICAgICAgdGFibGVzID0gcmVhZFRhYmxlcyhmb250LCBoZWFkZXIubnVtVGFibGVzKTsKICAgIH0KICAgIGxldCBjZmYsIGNmZkZpbGU7CiAgICBjb25zdCBpc1RydWVUeXBlID0gIXRhYmxlc1siQ0ZGICJdOwogICAgaWYgKCFpc1RydWVUeXBlKSB7CiAgICAgIGNvbnN0IGlzQ29tcG9zaXRlID0gcHJvcGVydGllcy5jb21wb3NpdGUgJiYgKChwcm9wZXJ0aWVzLmNpZFRvR2lkTWFwIHx8IFtdKS5sZW5ndGggPiAwIHx8ICEocHJvcGVydGllcy5jTWFwIGluc3RhbmNlb2YgX2NtYXAuSWRlbnRpdHlDTWFwKSk7CiAgICAgIGlmIChoZWFkZXIudmVyc2lvbiA9PT0gIk9UVE8iICYmICFpc0NvbXBvc2l0ZSB8fCAhdGFibGVzLmhlYWQgfHwgIXRhYmxlcy5oaGVhIHx8ICF0YWJsZXMubWF4cCB8fCAhdGFibGVzLnBvc3QpIHsKICAgICAgICBjZmZGaWxlID0gbmV3IF9zdHJlYW0uU3RyZWFtKHRhYmxlc1siQ0ZGICJdLmRhdGEpOwogICAgICAgIGNmZiA9IG5ldyBfY2ZmX2ZvbnQuQ0ZGRm9udChjZmZGaWxlLCBwcm9wZXJ0aWVzKTsKICAgICAgICBhZGp1c3RXaWR0aHMocHJvcGVydGllcyk7CiAgICAgICAgcmV0dXJuIHRoaXMuY29udmVydChuYW1lLCBjZmYsIHByb3BlcnRpZXMpOwogICAgICB9CiAgICAgIGRlbGV0ZSB0YWJsZXMuZ2x5ZjsKICAgICAgZGVsZXRlIHRhYmxlcy5sb2NhOwogICAgICBkZWxldGUgdGFibGVzLmZwZ207CiAgICAgIGRlbGV0ZSB0YWJsZXMucHJlcDsKICAgICAgZGVsZXRlIHRhYmxlc1siY3Z0ICJdOwogICAgICB0aGlzLmlzT3BlblR5cGUgPSB0cnVlOwogICAgfSBlbHNlIHsKICAgICAgaWYgKCF0YWJsZXMubG9jYSkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcignUmVxdWlyZWQgImxvY2EiIHRhYmxlIGlzIG5vdCBmb3VuZCcpOwogICAgICB9CiAgICAgIGlmICghdGFibGVzLmdseWYpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoJ1JlcXVpcmVkICJnbHlmIiB0YWJsZSBpcyBub3QgZm91bmQgLS0gdHJ5aW5nIHRvIHJlY292ZXIuJyk7CiAgICAgICAgdGFibGVzLmdseWYgPSB7CiAgICAgICAgICB0YWc6ICJnbHlmIiwKICAgICAgICAgIGRhdGE6IG5ldyBVaW50OEFycmF5KDApCiAgICAgICAgfTsKICAgICAgfQogICAgICB0aGlzLmlzT3BlblR5cGUgPSBmYWxzZTsKICAgIH0KICAgIGlmICghdGFibGVzLm1heHApIHsKICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCdSZXF1aXJlZCAibWF4cCIgdGFibGUgaXMgbm90IGZvdW5kJyk7CiAgICB9CiAgICBmb250LnBvcyA9IChmb250LnN0YXJ0IHx8IDApICsgdGFibGVzLm1heHAub2Zmc2V0OwogICAgY29uc3QgdmVyc2lvbiA9IGZvbnQuZ2V0SW50MzIoKTsKICAgIGNvbnN0IG51bUdseXBocyA9IGZvbnQuZ2V0VWludDE2KCk7CiAgICBpZiAocHJvcGVydGllcy5zY2FsZUZhY3RvcnMgJiYgcHJvcGVydGllcy5zY2FsZUZhY3RvcnMubGVuZ3RoID09PSBudW1HbHlwaHMgJiYgaXNUcnVlVHlwZSkgewogICAgICBjb25zdCB7CiAgICAgICAgc2NhbGVGYWN0b3JzCiAgICAgIH0gPSBwcm9wZXJ0aWVzOwogICAgICBjb25zdCBpc0dseXBoTG9jYXRpb25zTG9uZyA9IGludDE2KHRhYmxlcy5oZWFkLmRhdGFbNTBdLCB0YWJsZXMuaGVhZC5kYXRhWzUxXSk7CiAgICAgIGNvbnN0IGdseXBocyA9IG5ldyBfZ2x5Zi5HbHlmVGFibGUoewogICAgICAgIGdseWZUYWJsZTogdGFibGVzLmdseWYuZGF0YSwKICAgICAgICBpc0dseXBoTG9jYXRpb25zTG9uZywKICAgICAgICBsb2NhVGFibGU6IHRhYmxlcy5sb2NhLmRhdGEsCiAgICAgICAgbnVtR2x5cGhzCiAgICAgIH0pOwogICAgICBnbHlwaHMuc2NhbGUoc2NhbGVGYWN0b3JzKTsKICAgICAgY29uc3QgewogICAgICAgIGdseWYsCiAgICAgICAgbG9jYSwKICAgICAgICBpc0xvY2F0aW9uTG9uZwogICAgICB9ID0gZ2x5cGhzLndyaXRlKCk7CiAgICAgIHRhYmxlcy5nbHlmLmRhdGEgPSBnbHlmOwogICAgICB0YWJsZXMubG9jYS5kYXRhID0gbG9jYTsKICAgICAgaWYgKGlzTG9jYXRpb25Mb25nICE9PSAhIWlzR2x5cGhMb2NhdGlvbnNMb25nKSB7CiAgICAgICAgdGFibGVzLmhlYWQuZGF0YVs1MF0gPSAwOwogICAgICAgIHRhYmxlcy5oZWFkLmRhdGFbNTFdID0gaXNMb2NhdGlvbkxvbmcgPyAxIDogMDsKICAgICAgfQogICAgICBjb25zdCBtZXRyaWNzID0gdGFibGVzLmhtdHguZGF0YTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1HbHlwaHM7IGkrKykgewogICAgICAgIGNvbnN0IGogPSA0ICogaTsKICAgICAgICBjb25zdCBhZHZhbmNlV2lkdGggPSBNYXRoLnJvdW5kKHNjYWxlRmFjdG9yc1tpXSAqIGludDE2KG1ldHJpY3Nbal0sIG1ldHJpY3NbaiArIDFdKSk7CiAgICAgICAgbWV0cmljc1tqXSA9IGFkdmFuY2VXaWR0aCA+PiA4ICYgMHhmZjsKICAgICAgICBtZXRyaWNzW2ogKyAxXSA9IGFkdmFuY2VXaWR0aCAmIDB4ZmY7CiAgICAgICAgY29uc3QgbHNiID0gTWF0aC5yb3VuZChzY2FsZUZhY3RvcnNbaV0gKiBzaWduZWRJbnQxNihtZXRyaWNzW2ogKyAyXSwgbWV0cmljc1tqICsgM10pKTsKICAgICAgICB3cml0ZVNpZ25lZEludDE2KG1ldHJpY3MsIGogKyAyLCBsc2IpOwogICAgICB9CiAgICB9CiAgICBsZXQgbnVtR2x5cGhzT3V0ID0gbnVtR2x5cGhzICsgMTsKICAgIGxldCBkdXBGaXJzdEVudHJ5ID0gdHJ1ZTsKICAgIGlmIChudW1HbHlwaHNPdXQgPiAweGZmZmYpIHsKICAgICAgZHVwRmlyc3RFbnRyeSA9IGZhbHNlOwogICAgICBudW1HbHlwaHNPdXQgPSBudW1HbHlwaHM7CiAgICAgICgwLCBfdXRpbC53YXJuKSgiTm90IGVub3VnaCBzcGFjZSBpbiBnbHlmcyB0byBkdXBsaWNhdGUgZmlyc3QgZ2x5cGguIik7CiAgICB9CiAgICBsZXQgbWF4RnVuY3Rpb25EZWZzID0gMDsKICAgIGxldCBtYXhTaXplT2ZJbnN0cnVjdGlvbnMgPSAwOwogICAgaWYgKHZlcnNpb24gPj0gMHgwMDAxMDAwMCAmJiB0YWJsZXMubWF4cC5sZW5ndGggPj0gMjIpIHsKICAgICAgZm9udC5wb3MgKz0gODsKICAgICAgY29uc3QgbWF4Wm9uZXMgPSBmb250LmdldFVpbnQxNigpOwogICAgICBpZiAobWF4Wm9uZXMgPiAyKSB7CiAgICAgICAgdGFibGVzLm1heHAuZGF0YVsxNF0gPSAwOwogICAgICAgIHRhYmxlcy5tYXhwLmRhdGFbMTVdID0gMjsKICAgICAgfQogICAgICBmb250LnBvcyArPSA0OwogICAgICBtYXhGdW5jdGlvbkRlZnMgPSBmb250LmdldFVpbnQxNigpOwogICAgICBmb250LnBvcyArPSA0OwogICAgICBtYXhTaXplT2ZJbnN0cnVjdGlvbnMgPSBmb250LmdldFVpbnQxNigpOwogICAgfQogICAgdGFibGVzLm1heHAuZGF0YVs0XSA9IG51bUdseXBoc091dCA+PiA4OwogICAgdGFibGVzLm1heHAuZGF0YVs1XSA9IG51bUdseXBoc091dCAmIDI1NTsKICAgIGNvbnN0IGhpbnRzVmFsaWQgPSBzYW5pdGl6ZVRUUHJvZ3JhbXModGFibGVzLmZwZ20sIHRhYmxlcy5wcmVwLCB0YWJsZXNbImN2dCAiXSwgbWF4RnVuY3Rpb25EZWZzKTsKICAgIGlmICghaGludHNWYWxpZCkgewogICAgICBkZWxldGUgdGFibGVzLmZwZ207CiAgICAgIGRlbGV0ZSB0YWJsZXMucHJlcDsKICAgICAgZGVsZXRlIHRhYmxlc1siY3Z0ICJdOwogICAgfQogICAgc2FuaXRpemVNZXRyaWNzKGZvbnQsIHRhYmxlcy5oaGVhLCB0YWJsZXMuaG10eCwgdGFibGVzLmhlYWQsIG51bUdseXBoc091dCwgZHVwRmlyc3RFbnRyeSk7CiAgICBpZiAoIXRhYmxlcy5oZWFkKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcignUmVxdWlyZWQgImhlYWQiIHRhYmxlIGlzIG5vdCBmb3VuZCcpOwogICAgfQogICAgc2FuaXRpemVIZWFkKHRhYmxlcy5oZWFkLCBudW1HbHlwaHMsIGlzVHJ1ZVR5cGUgPyB0YWJsZXMubG9jYS5sZW5ndGggOiAwKTsKICAgIGxldCBtaXNzaW5nR2x5cGhzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGlmIChpc1RydWVUeXBlKSB7CiAgICAgIGNvbnN0IGlzR2x5cGhMb2NhdGlvbnNMb25nID0gaW50MTYodGFibGVzLmhlYWQuZGF0YVs1MF0sIHRhYmxlcy5oZWFkLmRhdGFbNTFdKTsKICAgICAgY29uc3QgZ2x5cGhzSW5mbyA9IHNhbml0aXplR2x5cGhMb2NhdGlvbnModGFibGVzLmxvY2EsIHRhYmxlcy5nbHlmLCBudW1HbHlwaHMsIGlzR2x5cGhMb2NhdGlvbnNMb25nLCBoaW50c1ZhbGlkLCBkdXBGaXJzdEVudHJ5LCBtYXhTaXplT2ZJbnN0cnVjdGlvbnMpOwogICAgICBtaXNzaW5nR2x5cGhzID0gZ2x5cGhzSW5mby5taXNzaW5nR2x5cGhzOwogICAgICBpZiAodmVyc2lvbiA+PSAweDAwMDEwMDAwICYmIHRhYmxlcy5tYXhwLmxlbmd0aCA+PSAyMikgewogICAgICAgIHRhYmxlcy5tYXhwLmRhdGFbMjZdID0gZ2x5cGhzSW5mby5tYXhTaXplT2ZJbnN0cnVjdGlvbnMgPj4gODsKICAgICAgICB0YWJsZXMubWF4cC5kYXRhWzI3XSA9IGdseXBoc0luZm8ubWF4U2l6ZU9mSW5zdHJ1Y3Rpb25zICYgMjU1OwogICAgICB9CiAgICB9CiAgICBpZiAoIXRhYmxlcy5oaGVhKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcignUmVxdWlyZWQgImhoZWEiIHRhYmxlIGlzIG5vdCBmb3VuZCcpOwogICAgfQogICAgaWYgKHRhYmxlcy5oaGVhLmRhdGFbMTBdID09PSAwICYmIHRhYmxlcy5oaGVhLmRhdGFbMTFdID09PSAwKSB7CiAgICAgIHRhYmxlcy5oaGVhLmRhdGFbMTBdID0gMHhmZjsKICAgICAgdGFibGVzLmhoZWEuZGF0YVsxMV0gPSAweGZmOwogICAgfQogICAgY29uc3QgbWV0cmljc092ZXJyaWRlID0gewogICAgICB1bml0c1BlckVtOiBpbnQxNih0YWJsZXMuaGVhZC5kYXRhWzE4XSwgdGFibGVzLmhlYWQuZGF0YVsxOV0pLAogICAgICB5TWF4OiBpbnQxNih0YWJsZXMuaGVhZC5kYXRhWzQyXSwgdGFibGVzLmhlYWQuZGF0YVs0M10pLAogICAgICB5TWluOiBzaWduZWRJbnQxNih0YWJsZXMuaGVhZC5kYXRhWzM4XSwgdGFibGVzLmhlYWQuZGF0YVszOV0pLAogICAgICBhc2NlbnQ6IHNpZ25lZEludDE2KHRhYmxlcy5oaGVhLmRhdGFbNF0sIHRhYmxlcy5oaGVhLmRhdGFbNV0pLAogICAgICBkZXNjZW50OiBzaWduZWRJbnQxNih0YWJsZXMuaGhlYS5kYXRhWzZdLCB0YWJsZXMuaGhlYS5kYXRhWzddKSwKICAgICAgbGluZUdhcDogc2lnbmVkSW50MTYodGFibGVzLmhoZWEuZGF0YVs4XSwgdGFibGVzLmhoZWEuZGF0YVs5XSkKICAgIH07CiAgICB0aGlzLmFzY2VudCA9IG1ldHJpY3NPdmVycmlkZS5hc2NlbnQgLyBtZXRyaWNzT3ZlcnJpZGUudW5pdHNQZXJFbTsKICAgIHRoaXMuZGVzY2VudCA9IG1ldHJpY3NPdmVycmlkZS5kZXNjZW50IC8gbWV0cmljc092ZXJyaWRlLnVuaXRzUGVyRW07CiAgICB0aGlzLmxpbmVHYXAgPSBtZXRyaWNzT3ZlcnJpZGUubGluZUdhcCAvIG1ldHJpY3NPdmVycmlkZS51bml0c1BlckVtOwogICAgaWYgKHRoaXMuY3NzRm9udEluZm8gJiYgdGhpcy5jc3NGb250SW5mby5saW5lSGVpZ2h0KSB7CiAgICAgIHRoaXMubGluZUhlaWdodCA9IHRoaXMuY3NzRm9udEluZm8ubWV0cmljcy5saW5lSGVpZ2h0OwogICAgICB0aGlzLmxpbmVHYXAgPSB0aGlzLmNzc0ZvbnRJbmZvLm1ldHJpY3MubGluZUdhcDsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMubGluZUhlaWdodCA9IHRoaXMuYXNjZW50IC0gdGhpcy5kZXNjZW50ICsgdGhpcy5saW5lR2FwOwogICAgfQogICAgaWYgKHRhYmxlcy5wb3N0KSB7CiAgICAgIHJlYWRQb3N0U2NyaXB0VGFibGUodGFibGVzLnBvc3QsIHByb3BlcnRpZXMsIG51bUdseXBocyk7CiAgICB9CiAgICB0YWJsZXMucG9zdCA9IHsKICAgICAgdGFnOiAicG9zdCIsCiAgICAgIGRhdGE6IGNyZWF0ZVBvc3RUYWJsZShwcm9wZXJ0aWVzKQogICAgfTsKICAgIGNvbnN0IGNoYXJDb2RlVG9HbHlwaElkID0gW107CiAgICBmdW5jdGlvbiBoYXNHbHlwaChnbHlwaElkKSB7CiAgICAgIHJldHVybiAhbWlzc2luZ0dseXBoc1tnbHlwaElkXTsKICAgIH0KICAgIGlmIChwcm9wZXJ0aWVzLmNvbXBvc2l0ZSkgewogICAgICBjb25zdCBjaWRUb0dpZE1hcCA9IHByb3BlcnRpZXMuY2lkVG9HaWRNYXAgfHwgW107CiAgICAgIGNvbnN0IGlzQ2lkVG9HaWRNYXBFbXB0eSA9IGNpZFRvR2lkTWFwLmxlbmd0aCA9PT0gMDsKICAgICAgcHJvcGVydGllcy5jTWFwLmZvckVhY2goZnVuY3Rpb24gKGNoYXJDb2RlLCBjaWQpIHsKICAgICAgICBpZiAodHlwZW9mIGNpZCA9PT0gInN0cmluZyIpIHsKICAgICAgICAgIGNpZCA9IGNvbnZlcnRDaWRTdHJpbmcoY2hhckNvZGUsIGNpZCwgdHJ1ZSk7CiAgICAgICAgfQogICAgICAgIGlmIChjaWQgPiAweGZmZmYpIHsKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiTWF4IHNpemUgb2YgQ0lEIGlzIDY1LDUzNSIpOwogICAgICAgIH0KICAgICAgICBsZXQgZ2x5cGhJZCA9IC0xOwogICAgICAgIGlmIChpc0NpZFRvR2lkTWFwRW1wdHkpIHsKICAgICAgICAgIGdseXBoSWQgPSBjaWQ7CiAgICAgICAgfSBlbHNlIGlmIChjaWRUb0dpZE1hcFtjaWRdICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGdseXBoSWQgPSBjaWRUb0dpZE1hcFtjaWRdOwogICAgICAgIH0KICAgICAgICBpZiAoZ2x5cGhJZCA+PSAwICYmIGdseXBoSWQgPCBudW1HbHlwaHMgJiYgaGFzR2x5cGgoZ2x5cGhJZCkpIHsKICAgICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IGdseXBoSWQ7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IGNtYXBUYWJsZSA9IHJlYWRDbWFwVGFibGUodGFibGVzLmNtYXAsIGZvbnQsIHRoaXMuaXNTeW1ib2xpY0ZvbnQsIHByb3BlcnRpZXMuaGFzRW5jb2RpbmcpOwogICAgICBjb25zdCBjbWFwUGxhdGZvcm1JZCA9IGNtYXBUYWJsZS5wbGF0Zm9ybUlkOwogICAgICBjb25zdCBjbWFwRW5jb2RpbmdJZCA9IGNtYXBUYWJsZS5lbmNvZGluZ0lkOwogICAgICBjb25zdCBjbWFwTWFwcGluZ3MgPSBjbWFwVGFibGUubWFwcGluZ3M7CiAgICAgIGxldCBiYXNlRW5jb2RpbmcgPSBbXSwKICAgICAgICBmb3JjZVBvc3RUYWJsZSA9IGZhbHNlOwogICAgICBpZiAocHJvcGVydGllcy5oYXNFbmNvZGluZyAmJiAocHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lID09PSAiTWFjUm9tYW5FbmNvZGluZyIgfHwgcHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lID09PSAiV2luQW5zaUVuY29kaW5nIikpIHsKICAgICAgICBiYXNlRW5jb2RpbmcgPSAoMCwgX2VuY29kaW5ncy5nZXRFbmNvZGluZykocHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lKTsKICAgICAgfQogICAgICBpZiAocHJvcGVydGllcy5oYXNFbmNvZGluZyAmJiAhdGhpcy5pc1N5bWJvbGljRm9udCAmJiAoY21hcFBsYXRmb3JtSWQgPT09IDMgJiYgY21hcEVuY29kaW5nSWQgPT09IDEgfHwgY21hcFBsYXRmb3JtSWQgPT09IDEgJiYgY21hcEVuY29kaW5nSWQgPT09IDApKSB7CiAgICAgICAgY29uc3QgZ2x5cGhzVW5pY29kZU1hcCA9ICgwLCBfZ2x5cGhsaXN0LmdldEdseXBoc1VuaWNvZGUpKCk7CiAgICAgICAgZm9yIChsZXQgY2hhckNvZGUgPSAwOyBjaGFyQ29kZSA8IDI1NjsgY2hhckNvZGUrKykgewogICAgICAgICAgbGV0IGdseXBoTmFtZTsKICAgICAgICAgIGlmICh0aGlzLmRpZmZlcmVuY2VzW2NoYXJDb2RlXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGdseXBoTmFtZSA9IHRoaXMuZGlmZmVyZW5jZXNbY2hhckNvZGVdOwogICAgICAgICAgfSBlbHNlIGlmIChiYXNlRW5jb2RpbmcubGVuZ3RoICYmIGJhc2VFbmNvZGluZ1tjaGFyQ29kZV0gIT09ICIiKSB7CiAgICAgICAgICAgIGdseXBoTmFtZSA9IGJhc2VFbmNvZGluZ1tjaGFyQ29kZV07CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBnbHlwaE5hbWUgPSBfZW5jb2RpbmdzLlN0YW5kYXJkRW5jb2RpbmdbY2hhckNvZGVdOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCFnbHlwaE5hbWUpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBzdGFuZGFyZEdseXBoTmFtZSA9ICgwLCBfZm9udHNfdXRpbHMucmVjb3ZlckdseXBoTmFtZSkoZ2x5cGhOYW1lLCBnbHlwaHNVbmljb2RlTWFwKTsKICAgICAgICAgIGxldCB1bmljb2RlT3JDaGFyQ29kZTsKICAgICAgICAgIGlmIChjbWFwUGxhdGZvcm1JZCA9PT0gMyAmJiBjbWFwRW5jb2RpbmdJZCA9PT0gMSkgewogICAgICAgICAgICB1bmljb2RlT3JDaGFyQ29kZSA9IGdseXBoc1VuaWNvZGVNYXBbc3RhbmRhcmRHbHlwaE5hbWVdOwogICAgICAgICAgfSBlbHNlIGlmIChjbWFwUGxhdGZvcm1JZCA9PT0gMSAmJiBjbWFwRW5jb2RpbmdJZCA9PT0gMCkgewogICAgICAgICAgICB1bmljb2RlT3JDaGFyQ29kZSA9IF9lbmNvZGluZ3MuTWFjUm9tYW5FbmNvZGluZy5pbmRleE9mKHN0YW5kYXJkR2x5cGhOYW1lKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh1bmljb2RlT3JDaGFyQ29kZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGlmICghcHJvcGVydGllcy5nbHlwaE5hbWVzICYmIHByb3BlcnRpZXMuaGFzSW5jbHVkZWRUb1VuaWNvZGVNYXAgJiYgISh0aGlzLnRvVW5pY29kZSBpbnN0YW5jZW9mIF90b191bmljb2RlX21hcC5JZGVudGl0eVRvVW5pY29kZU1hcCkpIHsKICAgICAgICAgICAgICBjb25zdCB1bmljb2RlID0gdGhpcy50b1VuaWNvZGUuZ2V0KGNoYXJDb2RlKTsKICAgICAgICAgICAgICBpZiAodW5pY29kZSkgewogICAgICAgICAgICAgICAgdW5pY29kZU9yQ2hhckNvZGUgPSB1bmljb2RlLmNvZGVQb2ludEF0KDApOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodW5pY29kZU9yQ2hhckNvZGUgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBmb3IgKGNvbnN0IG1hcHBpbmcgb2YgY21hcE1hcHBpbmdzKSB7CiAgICAgICAgICAgIGlmIChtYXBwaW5nLmNoYXJDb2RlICE9PSB1bmljb2RlT3JDaGFyQ29kZSkgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IG1hcHBpbmcuZ2x5cGhJZDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGNtYXBQbGF0Zm9ybUlkID09PSAwKSB7CiAgICAgICAgZm9yIChjb25zdCBtYXBwaW5nIG9mIGNtYXBNYXBwaW5ncykgewogICAgICAgICAgY2hhckNvZGVUb0dseXBoSWRbbWFwcGluZy5jaGFyQ29kZV0gPSBtYXBwaW5nLmdseXBoSWQ7CiAgICAgICAgfQogICAgICAgIGZvcmNlUG9zdFRhYmxlID0gdHJ1ZTsKICAgICAgfSBlbHNlIHsKICAgICAgICBmb3IgKGNvbnN0IG1hcHBpbmcgb2YgY21hcE1hcHBpbmdzKSB7CiAgICAgICAgICBsZXQgY2hhckNvZGUgPSBtYXBwaW5nLmNoYXJDb2RlOwogICAgICAgICAgaWYgKGNtYXBQbGF0Zm9ybUlkID09PSAzICYmIGNoYXJDb2RlID49IDB4ZjAwMCAmJiBjaGFyQ29kZSA8PSAweGYwZmYpIHsKICAgICAgICAgICAgY2hhckNvZGUgJj0gMHhmZjsKICAgICAgICAgIH0KICAgICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IG1hcHBpbmcuZ2x5cGhJZDsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKHByb3BlcnRpZXMuZ2x5cGhOYW1lcyAmJiAoYmFzZUVuY29kaW5nLmxlbmd0aCB8fCB0aGlzLmRpZmZlcmVuY2VzLmxlbmd0aCkpIHsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgKytpKSB7CiAgICAgICAgICBpZiAoIWZvcmNlUG9zdFRhYmxlICYmIGNoYXJDb2RlVG9HbHlwaElkW2ldICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBnbHlwaE5hbWUgPSB0aGlzLmRpZmZlcmVuY2VzW2ldIHx8IGJhc2VFbmNvZGluZ1tpXTsKICAgICAgICAgIGlmICghZ2x5cGhOYW1lKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgZ2x5cGhJZCA9IHByb3BlcnRpZXMuZ2x5cGhOYW1lcy5pbmRleE9mKGdseXBoTmFtZSk7CiAgICAgICAgICBpZiAoZ2x5cGhJZCA+IDAgJiYgaGFzR2x5cGgoZ2x5cGhJZCkpIHsKICAgICAgICAgICAgY2hhckNvZGVUb0dseXBoSWRbaV0gPSBnbHlwaElkOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKGNoYXJDb2RlVG9HbHlwaElkLmxlbmd0aCA9PT0gMCkgewogICAgICBjaGFyQ29kZVRvR2x5cGhJZFswXSA9IDA7CiAgICB9CiAgICBsZXQgZ2x5cGhaZXJvSWQgPSBudW1HbHlwaHNPdXQgLSAxOwogICAgaWYgKCFkdXBGaXJzdEVudHJ5KSB7CiAgICAgIGdseXBoWmVyb0lkID0gMDsKICAgIH0KICAgIGlmICghcHJvcGVydGllcy5jc3NGb250SW5mbykgewogICAgICBjb25zdCBuZXdNYXBwaW5nID0gYWRqdXN0TWFwcGluZyhjaGFyQ29kZVRvR2x5cGhJZCwgaGFzR2x5cGgsIGdseXBoWmVyb0lkLCB0aGlzLnRvVW5pY29kZSk7CiAgICAgIHRoaXMudG9Gb250Q2hhciA9IG5ld01hcHBpbmcudG9Gb250Q2hhcjsKICAgICAgdGFibGVzLmNtYXAgPSB7CiAgICAgICAgdGFnOiAiY21hcCIsCiAgICAgICAgZGF0YTogY3JlYXRlQ21hcFRhYmxlKG5ld01hcHBpbmcuY2hhckNvZGVUb0dseXBoSWQsIG5ld01hcHBpbmcudG9Vbmljb2RlRXh0cmFNYXAsIG51bUdseXBoc091dCkKICAgICAgfTsKICAgICAgaWYgKCF0YWJsZXNbIk9TLzIiXSB8fCAhdmFsaWRhdGVPUzJUYWJsZSh0YWJsZXNbIk9TLzIiXSwgZm9udCkpIHsKICAgICAgICB0YWJsZXNbIk9TLzIiXSA9IHsKICAgICAgICAgIHRhZzogIk9TLzIiLAogICAgICAgICAgZGF0YTogY3JlYXRlT1MyVGFibGUocHJvcGVydGllcywgbmV3TWFwcGluZy5jaGFyQ29kZVRvR2x5cGhJZCwgbWV0cmljc092ZXJyaWRlKQogICAgICAgIH07CiAgICAgIH0KICAgIH0KICAgIGlmICghaXNUcnVlVHlwZSkgewogICAgICB0cnkgewogICAgICAgIGNmZkZpbGUgPSBuZXcgX3N0cmVhbS5TdHJlYW0odGFibGVzWyJDRkYgIl0uZGF0YSk7CiAgICAgICAgY29uc3QgcGFyc2VyID0gbmV3IF9jZmZfcGFyc2VyLkNGRlBhcnNlcihjZmZGaWxlLCBwcm9wZXJ0aWVzLCBfZm9udHNfdXRpbHMuU0VBQ19BTkFMWVNJU19FTkFCTEVEKTsKICAgICAgICBjZmYgPSBwYXJzZXIucGFyc2UoKTsKICAgICAgICBjZmYuZHVwbGljYXRlRmlyc3RHbHlwaCgpOwogICAgICAgIGNvbnN0IGNvbXBpbGVyID0gbmV3IF9jZmZfcGFyc2VyLkNGRkNvbXBpbGVyKGNmZik7CiAgICAgICAgdGFibGVzWyJDRkYgIl0uZGF0YSA9IGNvbXBpbGVyLmNvbXBpbGUoKTsKICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICgwLCBfdXRpbC53YXJuKSgiRmFpbGVkIHRvIGNvbXBpbGUgZm9udCAiICsgcHJvcGVydGllcy5sb2FkZWROYW1lKTsKICAgICAgfQogICAgfQogICAgaWYgKCF0YWJsZXMubmFtZSkgewogICAgICB0YWJsZXMubmFtZSA9IHsKICAgICAgICB0YWc6ICJuYW1lIiwKICAgICAgICBkYXRhOiBjcmVhdGVOYW1lVGFibGUodGhpcy5uYW1lKQogICAgICB9OwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgW25hbWVQcm90b3R5cGUsIG5hbWVSZWNvcmRzXSA9IHJlYWROYW1lVGFibGUodGFibGVzLm5hbWUpOwogICAgICB0YWJsZXMubmFtZS5kYXRhID0gY3JlYXRlTmFtZVRhYmxlKG5hbWUsIG5hbWVQcm90b3R5cGUpOwogICAgICB0aGlzLnBzTmFtZSA9IG5hbWVQcm90b3R5cGVbMF1bNl0gfHwgbnVsbDsKICAgICAgaWYgKCFwcm9wZXJ0aWVzLmNvbXBvc2l0ZSkgewogICAgICAgIGFkanVzdFRydWVUeXBlVG9Vbmljb2RlKHByb3BlcnRpZXMsIHRoaXMuaXNTeW1ib2xpY0ZvbnQsIG5hbWVSZWNvcmRzKTsKICAgICAgfQogICAgfQogICAgY29uc3QgYnVpbGRlciA9IG5ldyBfb3BlbnR5cGVfZmlsZV9idWlsZGVyLk9wZW5UeXBlRmlsZUJ1aWxkZXIoaGVhZGVyLnZlcnNpb24pOwogICAgZm9yIChjb25zdCB0YWJsZVRhZyBpbiB0YWJsZXMpIHsKICAgICAgYnVpbGRlci5hZGRUYWJsZSh0YWJsZVRhZywgdGFibGVzW3RhYmxlVGFnXS5kYXRhKTsKICAgIH0KICAgIHJldHVybiBidWlsZGVyLnRvQXJyYXkoKTsKICB9CiAgY29udmVydChmb250TmFtZSwgZm9udCwgcHJvcGVydGllcykgewogICAgcHJvcGVydGllcy5maXhlZFBpdGNoID0gZmFsc2U7CiAgICBpZiAocHJvcGVydGllcy5idWlsdEluRW5jb2RpbmcpIHsKICAgICAgYWRqdXN0VHlwZTFUb1VuaWNvZGUocHJvcGVydGllcywgcHJvcGVydGllcy5idWlsdEluRW5jb2RpbmcpOwogICAgfQogICAgbGV0IGdseXBoWmVyb0lkID0gMTsKICAgIGlmIChmb250IGluc3RhbmNlb2YgX2NmZl9mb250LkNGRkZvbnQpIHsKICAgICAgZ2x5cGhaZXJvSWQgPSBmb250Lm51bUdseXBocyAtIDE7CiAgICB9CiAgICBjb25zdCBtYXBwaW5nID0gZm9udC5nZXRHbHlwaE1hcHBpbmcocHJvcGVydGllcyk7CiAgICBsZXQgbmV3TWFwcGluZyA9IG51bGw7CiAgICBsZXQgbmV3Q2hhckNvZGVUb0dseXBoSWQgPSBtYXBwaW5nOwogICAgbGV0IHRvVW5pY29kZUV4dHJhTWFwID0gbnVsbDsKICAgIGlmICghcHJvcGVydGllcy5jc3NGb250SW5mbykgewogICAgICBuZXdNYXBwaW5nID0gYWRqdXN0TWFwcGluZyhtYXBwaW5nLCBmb250Lmhhc0dseXBoSWQuYmluZChmb250KSwgZ2x5cGhaZXJvSWQsIHRoaXMudG9Vbmljb2RlKTsKICAgICAgdGhpcy50b0ZvbnRDaGFyID0gbmV3TWFwcGluZy50b0ZvbnRDaGFyOwogICAgICBuZXdDaGFyQ29kZVRvR2x5cGhJZCA9IG5ld01hcHBpbmcuY2hhckNvZGVUb0dseXBoSWQ7CiAgICAgIHRvVW5pY29kZUV4dHJhTWFwID0gbmV3TWFwcGluZy50b1VuaWNvZGVFeHRyYU1hcDsKICAgIH0KICAgIGNvbnN0IG51bUdseXBocyA9IGZvbnQubnVtR2x5cGhzOwogICAgZnVuY3Rpb24gZ2V0Q2hhckNvZGVzKGNoYXJDb2RlVG9HbHlwaElkLCBnbHlwaElkKSB7CiAgICAgIGxldCBjaGFyQ29kZXMgPSBudWxsOwogICAgICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIGNoYXJDb2RlVG9HbHlwaElkKSB7CiAgICAgICAgaWYgKGdseXBoSWQgPT09IGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSkgewogICAgICAgICAgaWYgKCFjaGFyQ29kZXMpIHsKICAgICAgICAgICAgY2hhckNvZGVzID0gW107CiAgICAgICAgICB9CiAgICAgICAgICBjaGFyQ29kZXMucHVzaChjaGFyQ29kZSB8IDApOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gY2hhckNvZGVzOwogICAgfQogICAgZnVuY3Rpb24gY3JlYXRlQ2hhckNvZGUoY2hhckNvZGVUb0dseXBoSWQsIGdseXBoSWQpIHsKICAgICAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBjaGFyQ29kZVRvR2x5cGhJZCkgewogICAgICAgIGlmIChnbHlwaElkID09PSBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0pIHsKICAgICAgICAgIHJldHVybiBjaGFyQ29kZSB8IDA7CiAgICAgICAgfQogICAgICB9CiAgICAgIG5ld01hcHBpbmcuY2hhckNvZGVUb0dseXBoSWRbbmV3TWFwcGluZy5uZXh0QXZhaWxhYmxlRm9udENoYXJDb2RlXSA9IGdseXBoSWQ7CiAgICAgIHJldHVybiBuZXdNYXBwaW5nLm5leHRBdmFpbGFibGVGb250Q2hhckNvZGUrKzsKICAgIH0KICAgIGNvbnN0IHNlYWNzID0gZm9udC5zZWFjczsKICAgIGlmIChuZXdNYXBwaW5nICYmIF9mb250c191dGlscy5TRUFDX0FOQUxZU0lTX0VOQUJMRUQgJiYgc2VhY3MgJiYgc2VhY3MubGVuZ3RoKSB7CiAgICAgIGNvbnN0IG1hdHJpeCA9IHByb3BlcnRpZXMuZm9udE1hdHJpeCB8fCBfdXRpbC5GT05UX0lERU5USVRZX01BVFJJWDsKICAgICAgY29uc3QgY2hhcnNldCA9IGZvbnQuZ2V0Q2hhcnNldCgpOwogICAgICBjb25zdCBzZWFjTWFwID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgZm9yIChsZXQgZ2x5cGhJZCBpbiBzZWFjcykgewogICAgICAgIGdseXBoSWQgfD0gMDsKICAgICAgICBjb25zdCBzZWFjID0gc2VhY3NbZ2x5cGhJZF07CiAgICAgICAgY29uc3QgYmFzZUdseXBoTmFtZSA9IF9lbmNvZGluZ3MuU3RhbmRhcmRFbmNvZGluZ1tzZWFjWzJdXTsKICAgICAgICBjb25zdCBhY2NlbnRHbHlwaE5hbWUgPSBfZW5jb2RpbmdzLlN0YW5kYXJkRW5jb2Rpbmdbc2VhY1szXV07CiAgICAgICAgY29uc3QgYmFzZUdseXBoSWQgPSBjaGFyc2V0LmluZGV4T2YoYmFzZUdseXBoTmFtZSk7CiAgICAgICAgY29uc3QgYWNjZW50R2x5cGhJZCA9IGNoYXJzZXQuaW5kZXhPZihhY2NlbnRHbHlwaE5hbWUpOwogICAgICAgIGlmIChiYXNlR2x5cGhJZCA8IDAgfHwgYWNjZW50R2x5cGhJZCA8IDApIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBhY2NlbnRPZmZzZXQgPSB7CiAgICAgICAgICB4OiBzZWFjWzBdICogbWF0cml4WzBdICsgc2VhY1sxXSAqIG1hdHJpeFsyXSArIG1hdHJpeFs0XSwKICAgICAgICAgIHk6IHNlYWNbMF0gKiBtYXRyaXhbMV0gKyBzZWFjWzFdICogbWF0cml4WzNdICsgbWF0cml4WzVdCiAgICAgICAgfTsKICAgICAgICBjb25zdCBjaGFyQ29kZXMgPSBnZXRDaGFyQ29kZXMobWFwcGluZywgZ2x5cGhJZCk7CiAgICAgICAgaWYgKCFjaGFyQ29kZXMpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBmb3IgKGNvbnN0IGNoYXJDb2RlIG9mIGNoYXJDb2RlcykgewogICAgICAgICAgY29uc3QgY2hhckNvZGVUb0dseXBoSWQgPSBuZXdNYXBwaW5nLmNoYXJDb2RlVG9HbHlwaElkOwogICAgICAgICAgY29uc3QgYmFzZUZvbnRDaGFyQ29kZSA9IGNyZWF0ZUNoYXJDb2RlKGNoYXJDb2RlVG9HbHlwaElkLCBiYXNlR2x5cGhJZCk7CiAgICAgICAgICBjb25zdCBhY2NlbnRGb250Q2hhckNvZGUgPSBjcmVhdGVDaGFyQ29kZShjaGFyQ29kZVRvR2x5cGhJZCwgYWNjZW50R2x5cGhJZCk7CiAgICAgICAgICBzZWFjTWFwW2NoYXJDb2RlXSA9IHsKICAgICAgICAgICAgYmFzZUZvbnRDaGFyQ29kZSwKICAgICAgICAgICAgYWNjZW50Rm9udENoYXJDb2RlLAogICAgICAgICAgICBhY2NlbnRPZmZzZXQKICAgICAgICAgIH07CiAgICAgICAgfQogICAgICB9CiAgICAgIHByb3BlcnRpZXMuc2VhY01hcCA9IHNlYWNNYXA7CiAgICB9CiAgICBjb25zdCB1bml0c1BlckVtID0gMSAvIChwcm9wZXJ0aWVzLmZvbnRNYXRyaXggfHwgX3V0aWwuRk9OVF9JREVOVElUWV9NQVRSSVgpWzBdOwogICAgY29uc3QgYnVpbGRlciA9IG5ldyBfb3BlbnR5cGVfZmlsZV9idWlsZGVyLk9wZW5UeXBlRmlsZUJ1aWxkZXIoIlx4NEZceDU0XHg1NFx4NEYiKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoIkNGRiAiLCBmb250LmRhdGEpOwogICAgYnVpbGRlci5hZGRUYWJsZSgiT1MvMiIsIGNyZWF0ZU9TMlRhYmxlKHByb3BlcnRpZXMsIG5ld0NoYXJDb2RlVG9HbHlwaElkKSk7CiAgICBidWlsZGVyLmFkZFRhYmxlKCJjbWFwIiwgY3JlYXRlQ21hcFRhYmxlKG5ld0NoYXJDb2RlVG9HbHlwaElkLCB0b1VuaWNvZGVFeHRyYU1hcCwgbnVtR2x5cGhzKSk7CiAgICBidWlsZGVyLmFkZFRhYmxlKCJoZWFkIiwgIlx4MDBceDAxXHgwMFx4MDAiICsgIlx4MDBceDAwXHgxMFx4MDAiICsgIlx4MDBceDAwXHgwMFx4MDAiICsgIlx4NUZceDBGXHgzQ1x4RjUiICsgIlx4MDBceDAwIiArIHNhZmVTdHJpbmcxNih1bml0c1BlckVtKSArICJceDAwXHgwMFx4MDBceDAwXHg5ZVx4MGJceDdlXHgyNyIgKyAiXHgwMFx4MDBceDAwXHgwMFx4OWVceDBiXHg3ZVx4MjciICsgIlx4MDBceDAwIiArIHNhZmVTdHJpbmcxNihwcm9wZXJ0aWVzLmRlc2NlbnQpICsgIlx4MEZceEZGIiArIHNhZmVTdHJpbmcxNihwcm9wZXJ0aWVzLmFzY2VudCkgKyBzdHJpbmcxNihwcm9wZXJ0aWVzLml0YWxpY0FuZ2xlID8gMiA6IDApICsgIlx4MDBceDExIiArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiICsgIlx4MDBceDAwIik7CiAgICBidWlsZGVyLmFkZFRhYmxlKCJoaGVhIiwgIlx4MDBceDAxXHgwMFx4MDAiICsgc2FmZVN0cmluZzE2KHByb3BlcnRpZXMuYXNjZW50KSArIHNhZmVTdHJpbmcxNihwcm9wZXJ0aWVzLmRlc2NlbnQpICsgIlx4MDBceDAwIiArICJceEZGXHhGRiIgKyAiXHgwMFx4MDAiICsgIlx4MDBceDAwIiArICJceDAwXHgwMCIgKyBzYWZlU3RyaW5nMTYocHJvcGVydGllcy5jYXBIZWlnaHQpICsgc2FmZVN0cmluZzE2KE1hdGgudGFuKHByb3BlcnRpZXMuaXRhbGljQW5nbGUpICogcHJvcGVydGllcy54SGVpZ2h0KSArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiICsgIlx4MDBceDAwIiArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiICsgIlx4MDBceDAwIiArIHN0cmluZzE2KG51bUdseXBocykpOwogICAgYnVpbGRlci5hZGRUYWJsZSgiaG10eCIsIGZ1bmN0aW9uIGZvbnRGaWVsZHNIbXR4KCkgewogICAgICBjb25zdCBjaGFyc3RyaW5ncyA9IGZvbnQuY2hhcnN0cmluZ3M7CiAgICAgIGNvbnN0IGNmZldpZHRocyA9IGZvbnQuY2ZmID8gZm9udC5jZmYud2lkdGhzIDogbnVsbDsKICAgICAgbGV0IGhtdHggPSAiXHgwMFx4MDBceDAwXHgwMCI7CiAgICAgIGZvciAobGV0IGkgPSAxLCBpaSA9IG51bUdseXBoczsgaSA8IGlpOyBpKyspIHsKICAgICAgICBsZXQgd2lkdGggPSAwOwogICAgICAgIGlmIChjaGFyc3RyaW5ncykgewogICAgICAgICAgY29uc3QgY2hhcnN0cmluZyA9IGNoYXJzdHJpbmdzW2kgLSAxXTsKICAgICAgICAgIHdpZHRoID0gIndpZHRoIiBpbiBjaGFyc3RyaW5nID8gY2hhcnN0cmluZy53aWR0aCA6IDA7CiAgICAgICAgfSBlbHNlIGlmIChjZmZXaWR0aHMpIHsKICAgICAgICAgIHdpZHRoID0gTWF0aC5jZWlsKGNmZldpZHRoc1tpXSB8fCAwKTsKICAgICAgICB9CiAgICAgICAgaG10eCArPSBzdHJpbmcxNih3aWR0aCkgKyBzdHJpbmcxNigwKTsKICAgICAgfQogICAgICByZXR1cm4gaG10eDsKICAgIH0oKSk7CiAgICBidWlsZGVyLmFkZFRhYmxlKCJtYXhwIiwgIlx4MDBceDAwXHg1MFx4MDAiICsgc3RyaW5nMTYobnVtR2x5cGhzKSk7CiAgICBidWlsZGVyLmFkZFRhYmxlKCJuYW1lIiwgY3JlYXRlTmFtZVRhYmxlKGZvbnROYW1lKSk7CiAgICBidWlsZGVyLmFkZFRhYmxlKCJwb3N0IiwgY3JlYXRlUG9zdFRhYmxlKHByb3BlcnRpZXMpKTsKICAgIHJldHVybiBidWlsZGVyLnRvQXJyYXkoKTsKICB9CiAgZ2V0IHNwYWNlV2lkdGgoKSB7CiAgICBjb25zdCBwb3NzaWJsZVNwYWNlUmVwbGFjZW1lbnRzID0gWyJzcGFjZSIsICJtaW51cyIsICJvbmUiLCAiaSIsICJJIl07CiAgICBsZXQgd2lkdGg7CiAgICBmb3IgKGNvbnN0IGdseXBoTmFtZSBvZiBwb3NzaWJsZVNwYWNlUmVwbGFjZW1lbnRzKSB7CiAgICAgIGlmIChnbHlwaE5hbWUgaW4gdGhpcy53aWR0aHMpIHsKICAgICAgICB3aWR0aCA9IHRoaXMud2lkdGhzW2dseXBoTmFtZV07CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY29uc3QgZ2x5cGhzVW5pY29kZU1hcCA9ICgwLCBfZ2x5cGhsaXN0LmdldEdseXBoc1VuaWNvZGUpKCk7CiAgICAgIGNvbnN0IGdseXBoVW5pY29kZSA9IGdseXBoc1VuaWNvZGVNYXBbZ2x5cGhOYW1lXTsKICAgICAgbGV0IGNoYXJjb2RlID0gMDsKICAgICAgaWYgKHRoaXMuY29tcG9zaXRlICYmIHRoaXMuY01hcC5jb250YWlucyhnbHlwaFVuaWNvZGUpKSB7CiAgICAgICAgY2hhcmNvZGUgPSB0aGlzLmNNYXAubG9va3VwKGdseXBoVW5pY29kZSk7CiAgICAgICAgaWYgKHR5cGVvZiBjaGFyY29kZSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgIGNoYXJjb2RlID0gY29udmVydENpZFN0cmluZyhnbHlwaFVuaWNvZGUsIGNoYXJjb2RlKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCFjaGFyY29kZSAmJiB0aGlzLnRvVW5pY29kZSkgewogICAgICAgIGNoYXJjb2RlID0gdGhpcy50b1VuaWNvZGUuY2hhckNvZGVPZihnbHlwaFVuaWNvZGUpOwogICAgICB9CiAgICAgIGlmIChjaGFyY29kZSA8PSAwKSB7CiAgICAgICAgY2hhcmNvZGUgPSBnbHlwaFVuaWNvZGU7CiAgICAgIH0KICAgICAgd2lkdGggPSB0aGlzLndpZHRoc1tjaGFyY29kZV07CiAgICAgIGlmICh3aWR0aCkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICB3aWR0aCA9IHdpZHRoIHx8IHRoaXMuZGVmYXVsdFdpZHRoOwogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJzcGFjZVdpZHRoIiwgd2lkdGgpOwogIH0KICBfY2hhclRvR2x5cGgoY2hhcmNvZGUpIHsKICAgIGxldCBpc1NwYWNlID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBmYWxzZTsKICAgIGxldCBnbHlwaCA9IHRoaXMuX2dseXBoQ2FjaGVbY2hhcmNvZGVdOwogICAgaWYgKGdseXBoICYmIGdseXBoLmlzU3BhY2UgPT09IGlzU3BhY2UpIHsKICAgICAgcmV0dXJuIGdseXBoOwogICAgfQogICAgbGV0IGZvbnRDaGFyQ29kZSwgd2lkdGgsIG9wZXJhdG9yTGlzdElkOwogICAgbGV0IHdpZHRoQ29kZSA9IGNoYXJjb2RlOwogICAgaWYgKHRoaXMuY01hcCAmJiB0aGlzLmNNYXAuY29udGFpbnMoY2hhcmNvZGUpKSB7CiAgICAgIHdpZHRoQ29kZSA9IHRoaXMuY01hcC5sb29rdXAoY2hhcmNvZGUpOwogICAgICBpZiAodHlwZW9mIHdpZHRoQ29kZSA9PT0gInN0cmluZyIpIHsKICAgICAgICB3aWR0aENvZGUgPSBjb252ZXJ0Q2lkU3RyaW5nKGNoYXJjb2RlLCB3aWR0aENvZGUpOwogICAgICB9CiAgICB9CiAgICB3aWR0aCA9IHRoaXMud2lkdGhzW3dpZHRoQ29kZV07CiAgICBpZiAodHlwZW9mIHdpZHRoICE9PSAibnVtYmVyIikgewogICAgICB3aWR0aCA9IHRoaXMuZGVmYXVsdFdpZHRoOwogICAgfQogICAgY29uc3Qgdm1ldHJpYyA9IHRoaXMudm1ldHJpY3MgJiYgdGhpcy52bWV0cmljc1t3aWR0aENvZGVdOwogICAgbGV0IHVuaWNvZGUgPSB0aGlzLnRvVW5pY29kZS5nZXQoY2hhcmNvZGUpIHx8IGNoYXJjb2RlOwogICAgaWYgKHR5cGVvZiB1bmljb2RlID09PSAibnVtYmVyIikgewogICAgICB1bmljb2RlID0gU3RyaW5nLmZyb21DaGFyQ29kZSh1bmljb2RlKTsKICAgIH0KICAgIGxldCBpc0luRm9udCA9IHRoaXMudG9Gb250Q2hhcltjaGFyY29kZV0gIT09IHVuZGVmaW5lZDsKICAgIGZvbnRDaGFyQ29kZSA9IHRoaXMudG9Gb250Q2hhcltjaGFyY29kZV0gfHwgY2hhcmNvZGU7CiAgICBpZiAodGhpcy5taXNzaW5nRmlsZSkgewogICAgICBjb25zdCBnbHlwaE5hbWUgPSB0aGlzLmRpZmZlcmVuY2VzW2NoYXJjb2RlXSB8fCB0aGlzLmRlZmF1bHRFbmNvZGluZ1tjaGFyY29kZV07CiAgICAgIGlmICgoZ2x5cGhOYW1lID09PSAiLm5vdGRlZiIgfHwgZ2x5cGhOYW1lID09PSAiIikgJiYgdGhpcy50eXBlID09PSAiVHlwZTEiKSB7CiAgICAgICAgZm9udENoYXJDb2RlID0gMHgyMDsKICAgICAgfQogICAgICBmb250Q2hhckNvZGUgPSAoMCwgX3VuaWNvZGUubWFwU3BlY2lhbFVuaWNvZGVWYWx1ZXMpKGZvbnRDaGFyQ29kZSk7CiAgICB9CiAgICBpZiAodGhpcy5pc1R5cGUzRm9udCkgewogICAgICBvcGVyYXRvckxpc3RJZCA9IGZvbnRDaGFyQ29kZTsKICAgIH0KICAgIGxldCBhY2NlbnQgPSBudWxsOwogICAgaWYgKHRoaXMuc2VhY01hcCAmJiB0aGlzLnNlYWNNYXBbY2hhcmNvZGVdKSB7CiAgICAgIGlzSW5Gb250ID0gdHJ1ZTsKICAgICAgY29uc3Qgc2VhYyA9IHRoaXMuc2VhY01hcFtjaGFyY29kZV07CiAgICAgIGZvbnRDaGFyQ29kZSA9IHNlYWMuYmFzZUZvbnRDaGFyQ29kZTsKICAgICAgYWNjZW50ID0gewogICAgICAgIGZvbnRDaGFyOiBTdHJpbmcuZnJvbUNvZGVQb2ludChzZWFjLmFjY2VudEZvbnRDaGFyQ29kZSksCiAgICAgICAgb2Zmc2V0OiBzZWFjLmFjY2VudE9mZnNldAogICAgICB9OwogICAgfQogICAgbGV0IGZvbnRDaGFyID0gIiI7CiAgICBpZiAodHlwZW9mIGZvbnRDaGFyQ29kZSA9PT0gIm51bWJlciIpIHsKICAgICAgaWYgKGZvbnRDaGFyQ29kZSA8PSAweDEwZmZmZikgewogICAgICAgIGZvbnRDaGFyID0gU3RyaW5nLmZyb21Db2RlUG9pbnQoZm9udENoYXJDb2RlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYGNoYXJUb0dseXBoIC0gaW52YWxpZCBmb250Q2hhckNvZGU6ICR7Zm9udENoYXJDb2RlfWApOwogICAgICB9CiAgICB9CiAgICBnbHlwaCA9IG5ldyBHbHlwaChjaGFyY29kZSwgZm9udENoYXIsIHVuaWNvZGUsIGFjY2VudCwgd2lkdGgsIHZtZXRyaWMsIG9wZXJhdG9yTGlzdElkLCBpc1NwYWNlLCBpc0luRm9udCk7CiAgICByZXR1cm4gdGhpcy5fZ2x5cGhDYWNoZVtjaGFyY29kZV0gPSBnbHlwaDsKICB9CiAgY2hhcnNUb0dseXBocyhjaGFycykgewogICAgbGV0IGdseXBocyA9IHRoaXMuX2NoYXJzQ2FjaGVbY2hhcnNdOwogICAgaWYgKGdseXBocykgewogICAgICByZXR1cm4gZ2x5cGhzOwogICAgfQogICAgZ2x5cGhzID0gW107CiAgICBpZiAodGhpcy5jTWFwKSB7CiAgICAgIGNvbnN0IGMgPSBPYmplY3QuY3JlYXRlKG51bGwpLAogICAgICAgIGlpID0gY2hhcnMubGVuZ3RoOwogICAgICBsZXQgaSA9IDA7CiAgICAgIHdoaWxlIChpIDwgaWkpIHsKICAgICAgICB0aGlzLmNNYXAucmVhZENoYXJDb2RlKGNoYXJzLCBpLCBjKTsKICAgICAgICBjb25zdCB7CiAgICAgICAgICBjaGFyY29kZSwKICAgICAgICAgIGxlbmd0aAogICAgICAgIH0gPSBjOwogICAgICAgIGkgKz0gbGVuZ3RoOwogICAgICAgIGNvbnN0IGdseXBoID0gdGhpcy5fY2hhclRvR2x5cGgoY2hhcmNvZGUsIGxlbmd0aCA9PT0gMSAmJiBjaGFycy5jaGFyQ29kZUF0KGkgLSAxKSA9PT0gMHgyMCk7CiAgICAgICAgZ2x5cGhzLnB1c2goZ2x5cGgpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBjaGFycy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7CiAgICAgICAgY29uc3QgY2hhcmNvZGUgPSBjaGFycy5jaGFyQ29kZUF0KGkpOwogICAgICAgIGNvbnN0IGdseXBoID0gdGhpcy5fY2hhclRvR2x5cGgoY2hhcmNvZGUsIGNoYXJjb2RlID09PSAweDIwKTsKICAgICAgICBnbHlwaHMucHVzaChnbHlwaCk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB0aGlzLl9jaGFyc0NhY2hlW2NoYXJzXSA9IGdseXBoczsKICB9CiAgZ2V0Q2hhclBvc2l0aW9ucyhjaGFycykgewogICAgY29uc3QgcG9zaXRpb25zID0gW107CiAgICBpZiAodGhpcy5jTWFwKSB7CiAgICAgIGNvbnN0IGMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBsZXQgaSA9IDA7CiAgICAgIHdoaWxlIChpIDwgY2hhcnMubGVuZ3RoKSB7CiAgICAgICAgdGhpcy5jTWFwLnJlYWRDaGFyQ29kZShjaGFycywgaSwgYyk7CiAgICAgICAgY29uc3QgbGVuZ3RoID0gYy5sZW5ndGg7CiAgICAgICAgcG9zaXRpb25zLnB1c2goW2ksIGkgKyBsZW5ndGhdKTsKICAgICAgICBpICs9IGxlbmd0aDsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gY2hhcnMubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICAgIHBvc2l0aW9ucy5wdXNoKFtpLCBpICsgMV0pOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcG9zaXRpb25zOwogIH0KICBnZXQgZ2x5cGhDYWNoZVZhbHVlcygpIHsKICAgIHJldHVybiBPYmplY3QudmFsdWVzKHRoaXMuX2dseXBoQ2FjaGUpOwogIH0KICBlbmNvZGVTdHJpbmcoc3RyKSB7CiAgICBjb25zdCBidWZmZXJzID0gW107CiAgICBjb25zdCBjdXJyZW50QnVmID0gW107CiAgICBjb25zdCBoYXNDdXJyZW50QnVmRXJyb3JzID0gKCkgPT4gYnVmZmVycy5sZW5ndGggJSAyID09PSAxOwogICAgY29uc3QgZ2V0Q2hhckNvZGUgPSB0aGlzLnRvVW5pY29kZSBpbnN0YW5jZW9mIF90b191bmljb2RlX21hcC5JZGVudGl0eVRvVW5pY29kZU1hcCA/IHVuaWNvZGUgPT4gdGhpcy50b1VuaWNvZGUuY2hhckNvZGVPZih1bmljb2RlKSA6IHVuaWNvZGUgPT4gdGhpcy50b1VuaWNvZGUuY2hhckNvZGVPZihTdHJpbmcuZnJvbUNvZGVQb2ludCh1bmljb2RlKSk7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBzdHIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCB1bmljb2RlID0gc3RyLmNvZGVQb2ludEF0KGkpOwogICAgICBpZiAodW5pY29kZSA+IDB4ZDdmZiAmJiAodW5pY29kZSA8IDB4ZTAwMCB8fCB1bmljb2RlID4gMHhmZmZkKSkgewogICAgICAgIGkrKzsKICAgICAgfQogICAgICBpZiAodGhpcy50b1VuaWNvZGUpIHsKICAgICAgICBjb25zdCBjaGFyQ29kZSA9IGdldENoYXJDb2RlKHVuaWNvZGUpOwogICAgICAgIGlmIChjaGFyQ29kZSAhPT0gLTEpIHsKICAgICAgICAgIGlmIChoYXNDdXJyZW50QnVmRXJyb3JzKCkpIHsKICAgICAgICAgICAgYnVmZmVycy5wdXNoKGN1cnJlbnRCdWYuam9pbigiIikpOwogICAgICAgICAgICBjdXJyZW50QnVmLmxlbmd0aCA9IDA7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBjaGFyQ29kZUxlbmd0aCA9IHRoaXMuY01hcCA/IHRoaXMuY01hcC5nZXRDaGFyQ29kZUxlbmd0aChjaGFyQ29kZSkgOiAxOwogICAgICAgICAgZm9yIChsZXQgaiA9IGNoYXJDb2RlTGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHsKICAgICAgICAgICAgY3VycmVudEJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoY2hhckNvZGUgPj4gOCAqIGogJiAweGZmKSk7CiAgICAgICAgICB9CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCFoYXNDdXJyZW50QnVmRXJyb3JzKCkpIHsKICAgICAgICBidWZmZXJzLnB1c2goY3VycmVudEJ1Zi5qb2luKCIiKSk7CiAgICAgICAgY3VycmVudEJ1Zi5sZW5ndGggPSAwOwogICAgICB9CiAgICAgIGN1cnJlbnRCdWYucHVzaChTdHJpbmcuZnJvbUNvZGVQb2ludCh1bmljb2RlKSk7CiAgICB9CiAgICBidWZmZXJzLnB1c2goY3VycmVudEJ1Zi5qb2luKCIiKSk7CiAgICByZXR1cm4gYnVmZmVyczsKICB9Cn0KZXhwb3J0cy5Gb250ID0gRm9udDsKY2xhc3MgRXJyb3JGb250IHsKICBjb25zdHJ1Y3RvcihlcnJvcikgewogICAgdGhpcy5lcnJvciA9IGVycm9yOwogICAgdGhpcy5sb2FkZWROYW1lID0gImdfZm9udF9lcnJvciI7CiAgICB0aGlzLm1pc3NpbmdGaWxlID0gdHJ1ZTsKICB9CiAgY2hhcnNUb0dseXBocygpIHsKICAgIHJldHVybiBbXTsKICB9CiAgZW5jb2RlU3RyaW5nKGNoYXJzKSB7CiAgICByZXR1cm4gW2NoYXJzXTsKICB9CiAgZXhwb3J0RGF0YSgpIHsKICAgIGxldCBleHRyYVByb3BlcnRpZXMgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgcmV0dXJuIHsKICAgICAgZXJyb3I6IHRoaXMuZXJyb3IKICAgIH07CiAgfQp9CmV4cG9ydHMuRXJyb3JGb250ID0gRXJyb3JGb250OwoKLyoqKi8gfSksCi8qIDE3MCAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuQ0ZGVG9wRGljdCA9IGV4cG9ydHMuQ0ZGU3RyaW5ncyA9IGV4cG9ydHMuQ0ZGU3RhbmRhcmRTdHJpbmdzID0gZXhwb3J0cy5DRkZQcml2YXRlRGljdCA9IGV4cG9ydHMuQ0ZGUGFyc2VyID0gZXhwb3J0cy5DRkZJbmRleCA9IGV4cG9ydHMuQ0ZGSGVhZGVyID0gZXhwb3J0cy5DRkZGRFNlbGVjdCA9IGV4cG9ydHMuQ0ZGQ29tcGlsZXIgPSBleHBvcnRzLkNGRkNoYXJzZXQgPSBleHBvcnRzLkNGRiA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9jaGFyc2V0cyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTcxKTsKdmFyIF9lbmNvZGluZ3MgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE3Mik7CmNvbnN0IE1BWF9TVUJSX05FU1RJTkcgPSAxMDsKY29uc3QgQ0ZGU3RhbmRhcmRTdHJpbmdzID0gWyIubm90ZGVmIiwgInNwYWNlIiwgImV4Y2xhbSIsICJxdW90ZWRibCIsICJudW1iZXJzaWduIiwgImRvbGxhciIsICJwZXJjZW50IiwgImFtcGVyc2FuZCIsICJxdW90ZXJpZ2h0IiwgInBhcmVubGVmdCIsICJwYXJlbnJpZ2h0IiwgImFzdGVyaXNrIiwgInBsdXMiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJzbGFzaCIsICJ6ZXJvIiwgIm9uZSIsICJ0d28iLCAidGhyZWUiLCAiZm91ciIsICJmaXZlIiwgInNpeCIsICJzZXZlbiIsICJlaWdodCIsICJuaW5lIiwgImNvbG9uIiwgInNlbWljb2xvbiIsICJsZXNzIiwgImVxdWFsIiwgImdyZWF0ZXIiLCAicXVlc3Rpb24iLCAiYXQiLCAiQSIsICJCIiwgIkMiLCAiRCIsICJFIiwgIkYiLCAiRyIsICJIIiwgIkkiLCAiSiIsICJLIiwgIkwiLCAiTSIsICJOIiwgIk8iLCAiUCIsICJRIiwgIlIiLCAiUyIsICJUIiwgIlUiLCAiViIsICJXIiwgIlgiLCAiWSIsICJaIiwgImJyYWNrZXRsZWZ0IiwgImJhY2tzbGFzaCIsICJicmFja2V0cmlnaHQiLCAiYXNjaWljaXJjdW0iLCAidW5kZXJzY29yZSIsICJxdW90ZWxlZnQiLCAiYSIsICJiIiwgImMiLCAiZCIsICJlIiwgImYiLCAiZyIsICJoIiwgImkiLCAiaiIsICJrIiwgImwiLCAibSIsICJuIiwgIm8iLCAicCIsICJxIiwgInIiLCAicyIsICJ0IiwgInUiLCAidiIsICJ3IiwgIngiLCAieSIsICJ6IiwgImJyYWNlbGVmdCIsICJiYXIiLCAiYnJhY2VyaWdodCIsICJhc2NpaXRpbGRlIiwgImV4Y2xhbWRvd24iLCAiY2VudCIsICJzdGVybGluZyIsICJmcmFjdGlvbiIsICJ5ZW4iLCAiZmxvcmluIiwgInNlY3Rpb24iLCAiY3VycmVuY3kiLCAicXVvdGVzaW5nbGUiLCAicXVvdGVkYmxsZWZ0IiwgImd1aWxsZW1vdGxlZnQiLCAiZ3VpbHNpbmdsbGVmdCIsICJndWlsc2luZ2xyaWdodCIsICJmaSIsICJmbCIsICJlbmRhc2giLCAiZGFnZ2VyIiwgImRhZ2dlcmRibCIsICJwZXJpb2RjZW50ZXJlZCIsICJwYXJhZ3JhcGgiLCAiYnVsbGV0IiwgInF1b3Rlc2luZ2xiYXNlIiwgInF1b3RlZGJsYmFzZSIsICJxdW90ZWRibHJpZ2h0IiwgImd1aWxsZW1vdHJpZ2h0IiwgImVsbGlwc2lzIiwgInBlcnRob3VzYW5kIiwgInF1ZXN0aW9uZG93biIsICJncmF2ZSIsICJhY3V0ZSIsICJjaXJjdW1mbGV4IiwgInRpbGRlIiwgIm1hY3JvbiIsICJicmV2ZSIsICJkb3RhY2NlbnQiLCAiZGllcmVzaXMiLCAicmluZyIsICJjZWRpbGxhIiwgImh1bmdhcnVtbGF1dCIsICJvZ29uZWsiLCAiY2Fyb24iLCAiZW1kYXNoIiwgIkFFIiwgIm9yZGZlbWluaW5lIiwgIkxzbGFzaCIsICJPc2xhc2giLCAiT0UiLCAib3JkbWFzY3VsaW5lIiwgImFlIiwgImRvdGxlc3NpIiwgImxzbGFzaCIsICJvc2xhc2giLCAib2UiLCAiZ2VybWFuZGJscyIsICJvbmVzdXBlcmlvciIsICJsb2dpY2Fsbm90IiwgIm11IiwgInRyYWRlbWFyayIsICJFdGgiLCAib25laGFsZiIsICJwbHVzbWludXMiLCAiVGhvcm4iLCAib25lcXVhcnRlciIsICJkaXZpZGUiLCAiYnJva2VuYmFyIiwgImRlZ3JlZSIsICJ0aG9ybiIsICJ0aHJlZXF1YXJ0ZXJzIiwgInR3b3N1cGVyaW9yIiwgInJlZ2lzdGVyZWQiLCAibWludXMiLCAiZXRoIiwgIm11bHRpcGx5IiwgInRocmVlc3VwZXJpb3IiLCAiY29weXJpZ2h0IiwgIkFhY3V0ZSIsICJBY2lyY3VtZmxleCIsICJBZGllcmVzaXMiLCAiQWdyYXZlIiwgIkFyaW5nIiwgIkF0aWxkZSIsICJDY2VkaWxsYSIsICJFYWN1dGUiLCAiRWNpcmN1bWZsZXgiLCAiRWRpZXJlc2lzIiwgIkVncmF2ZSIsICJJYWN1dGUiLCAiSWNpcmN1bWZsZXgiLCAiSWRpZXJlc2lzIiwgIklncmF2ZSIsICJOdGlsZGUiLCAiT2FjdXRlIiwgIk9jaXJjdW1mbGV4IiwgIk9kaWVyZXNpcyIsICJPZ3JhdmUiLCAiT3RpbGRlIiwgIlNjYXJvbiIsICJVYWN1dGUiLCAiVWNpcmN1bWZsZXgiLCAiVWRpZXJlc2lzIiwgIlVncmF2ZSIsICJZYWN1dGUiLCAiWWRpZXJlc2lzIiwgIlpjYXJvbiIsICJhYWN1dGUiLCAiYWNpcmN1bWZsZXgiLCAiYWRpZXJlc2lzIiwgImFncmF2ZSIsICJhcmluZyIsICJhdGlsZGUiLCAiY2NlZGlsbGEiLCAiZWFjdXRlIiwgImVjaXJjdW1mbGV4IiwgImVkaWVyZXNpcyIsICJlZ3JhdmUiLCAiaWFjdXRlIiwgImljaXJjdW1mbGV4IiwgImlkaWVyZXNpcyIsICJpZ3JhdmUiLCAibnRpbGRlIiwgIm9hY3V0ZSIsICJvY2lyY3VtZmxleCIsICJvZGllcmVzaXMiLCAib2dyYXZlIiwgIm90aWxkZSIsICJzY2Fyb24iLCAidWFjdXRlIiwgInVjaXJjdW1mbGV4IiwgInVkaWVyZXNpcyIsICJ1Z3JhdmUiLCAieWFjdXRlIiwgInlkaWVyZXNpcyIsICJ6Y2Fyb24iLCAiZXhjbGFtc21hbGwiLCAiSHVuZ2FydW1sYXV0c21hbGwiLCAiZG9sbGFyb2xkc3R5bGUiLCAiZG9sbGFyc3VwZXJpb3IiLCAiYW1wZXJzYW5kc21hbGwiLCAiQWN1dGVzbWFsbCIsICJwYXJlbmxlZnRzdXBlcmlvciIsICJwYXJlbnJpZ2h0c3VwZXJpb3IiLCAidHdvZG90ZW5sZWFkZXIiLCAib25lZG90ZW5sZWFkZXIiLCAiemVyb29sZHN0eWxlIiwgIm9uZW9sZHN0eWxlIiwgInR3b29sZHN0eWxlIiwgInRocmVlb2xkc3R5bGUiLCAiZm91cm9sZHN0eWxlIiwgImZpdmVvbGRzdHlsZSIsICJzaXhvbGRzdHlsZSIsICJzZXZlbm9sZHN0eWxlIiwgImVpZ2h0b2xkc3R5bGUiLCAibmluZW9sZHN0eWxlIiwgImNvbW1hc3VwZXJpb3IiLCAidGhyZWVxdWFydGVyc2VtZGFzaCIsICJwZXJpb2RzdXBlcmlvciIsICJxdWVzdGlvbnNtYWxsIiwgImFzdXBlcmlvciIsICJic3VwZXJpb3IiLCAiY2VudHN1cGVyaW9yIiwgImRzdXBlcmlvciIsICJlc3VwZXJpb3IiLCAiaXN1cGVyaW9yIiwgImxzdXBlcmlvciIsICJtc3VwZXJpb3IiLCAibnN1cGVyaW9yIiwgIm9zdXBlcmlvciIsICJyc3VwZXJpb3IiLCAic3N1cGVyaW9yIiwgInRzdXBlcmlvciIsICJmZiIsICJmZmkiLCAiZmZsIiwgInBhcmVubGVmdGluZmVyaW9yIiwgInBhcmVucmlnaHRpbmZlcmlvciIsICJDaXJjdW1mbGV4c21hbGwiLCAiaHlwaGVuc3VwZXJpb3IiLCAiR3JhdmVzbWFsbCIsICJBc21hbGwiLCAiQnNtYWxsIiwgIkNzbWFsbCIsICJEc21hbGwiLCAiRXNtYWxsIiwgIkZzbWFsbCIsICJHc21hbGwiLCAiSHNtYWxsIiwgIklzbWFsbCIsICJKc21hbGwiLCAiS3NtYWxsIiwgIkxzbWFsbCIsICJNc21hbGwiLCAiTnNtYWxsIiwgIk9zbWFsbCIsICJQc21hbGwiLCAiUXNtYWxsIiwgIlJzbWFsbCIsICJTc21hbGwiLCAiVHNtYWxsIiwgIlVzbWFsbCIsICJWc21hbGwiLCAiV3NtYWxsIiwgIlhzbWFsbCIsICJZc21hbGwiLCAiWnNtYWxsIiwgImNvbG9ubW9uZXRhcnkiLCAib25lZml0dGVkIiwgInJ1cGlhaCIsICJUaWxkZXNtYWxsIiwgImV4Y2xhbWRvd25zbWFsbCIsICJjZW50b2xkc3R5bGUiLCAiTHNsYXNoc21hbGwiLCAiU2Nhcm9uc21hbGwiLCAiWmNhcm9uc21hbGwiLCAiRGllcmVzaXNzbWFsbCIsICJCcmV2ZXNtYWxsIiwgIkNhcm9uc21hbGwiLCAiRG90YWNjZW50c21hbGwiLCAiTWFjcm9uc21hbGwiLCAiZmlndXJlZGFzaCIsICJoeXBoZW5pbmZlcmlvciIsICJPZ29uZWtzbWFsbCIsICJSaW5nc21hbGwiLCAiQ2VkaWxsYXNtYWxsIiwgInF1ZXN0aW9uZG93bnNtYWxsIiwgIm9uZWVpZ2h0aCIsICJ0aHJlZWVpZ2h0aHMiLCAiZml2ZWVpZ2h0aHMiLCAic2V2ZW5laWdodGhzIiwgIm9uZXRoaXJkIiwgInR3b3RoaXJkcyIsICJ6ZXJvc3VwZXJpb3IiLCAiZm91cnN1cGVyaW9yIiwgImZpdmVzdXBlcmlvciIsICJzaXhzdXBlcmlvciIsICJzZXZlbnN1cGVyaW9yIiwgImVpZ2h0c3VwZXJpb3IiLCAibmluZXN1cGVyaW9yIiwgInplcm9pbmZlcmlvciIsICJvbmVpbmZlcmlvciIsICJ0d29pbmZlcmlvciIsICJ0aHJlZWluZmVyaW9yIiwgImZvdXJpbmZlcmlvciIsICJmaXZlaW5mZXJpb3IiLCAic2l4aW5mZXJpb3IiLCAic2V2ZW5pbmZlcmlvciIsICJlaWdodGluZmVyaW9yIiwgIm5pbmVpbmZlcmlvciIsICJjZW50aW5mZXJpb3IiLCAiZG9sbGFyaW5mZXJpb3IiLCAicGVyaW9kaW5mZXJpb3IiLCAiY29tbWFpbmZlcmlvciIsICJBZ3JhdmVzbWFsbCIsICJBYWN1dGVzbWFsbCIsICJBY2lyY3VtZmxleHNtYWxsIiwgIkF0aWxkZXNtYWxsIiwgIkFkaWVyZXNpc3NtYWxsIiwgIkFyaW5nc21hbGwiLCAiQUVzbWFsbCIsICJDY2VkaWxsYXNtYWxsIiwgIkVncmF2ZXNtYWxsIiwgIkVhY3V0ZXNtYWxsIiwgIkVjaXJjdW1mbGV4c21hbGwiLCAiRWRpZXJlc2lzc21hbGwiLCAiSWdyYXZlc21hbGwiLCAiSWFjdXRlc21hbGwiLCAiSWNpcmN1bWZsZXhzbWFsbCIsICJJZGllcmVzaXNzbWFsbCIsICJFdGhzbWFsbCIsICJOdGlsZGVzbWFsbCIsICJPZ3JhdmVzbWFsbCIsICJPYWN1dGVzbWFsbCIsICJPY2lyY3VtZmxleHNtYWxsIiwgIk90aWxkZXNtYWxsIiwgIk9kaWVyZXNpc3NtYWxsIiwgIk9Fc21hbGwiLCAiT3NsYXNoc21hbGwiLCAiVWdyYXZlc21hbGwiLCAiVWFjdXRlc21hbGwiLCAiVWNpcmN1bWZsZXhzbWFsbCIsICJVZGllcmVzaXNzbWFsbCIsICJZYWN1dGVzbWFsbCIsICJUaG9ybnNtYWxsIiwgIllkaWVyZXNpc3NtYWxsIiwgIjAwMS4wMDAiLCAiMDAxLjAwMSIsICIwMDEuMDAyIiwgIjAwMS4wMDMiLCAiQmxhY2siLCAiQm9sZCIsICJCb29rIiwgIkxpZ2h0IiwgIk1lZGl1bSIsICJSZWd1bGFyIiwgIlJvbWFuIiwgIlNlbWlib2xkIl07CmV4cG9ydHMuQ0ZGU3RhbmRhcmRTdHJpbmdzID0gQ0ZGU3RhbmRhcmRTdHJpbmdzOwpjb25zdCBOVU1fU1RBTkRBUkRfQ0ZGX1NUUklOR1MgPSAzOTE7CmNvbnN0IENoYXJzdHJpbmdWYWxpZGF0aW9uRGF0YSA9IFtudWxsLCB7CiAgaWQ6ICJoc3RlbSIsCiAgbWluOiAyLAogIHN0YWNrQ2xlYXJpbmc6IHRydWUsCiAgc3RlbTogdHJ1ZQp9LCBudWxsLCB7CiAgaWQ6ICJ2c3RlbSIsCiAgbWluOiAyLAogIHN0YWNrQ2xlYXJpbmc6IHRydWUsCiAgc3RlbTogdHJ1ZQp9LCB7CiAgaWQ6ICJ2bW92ZXRvIiwKICBtaW46IDEsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZQp9LCB7CiAgaWQ6ICJybGluZXRvIiwKICBtaW46IDIsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJobGluZXRvIiwKICBtaW46IDEsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJ2bGluZXRvIiwKICBtaW46IDEsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJycmN1cnZldG8iLAogIG1pbjogNiwKICByZXNldFN0YWNrOiB0cnVlCn0sIG51bGwsIHsKICBpZDogImNhbGxzdWJyIiwKICBtaW46IDEsCiAgdW5kZWZTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJyZXR1cm4iLAogIG1pbjogMCwKICB1bmRlZlN0YWNrOiB0cnVlCn0sIG51bGwsIG51bGwsIHsKICBpZDogImVuZGNoYXIiLAogIG1pbjogMCwKICBzdGFja0NsZWFyaW5nOiB0cnVlCn0sIG51bGwsIG51bGwsIG51bGwsIHsKICBpZDogImhzdGVtaG0iLAogIG1pbjogMiwKICBzdGFja0NsZWFyaW5nOiB0cnVlLAogIHN0ZW06IHRydWUKfSwgewogIGlkOiAiaGludG1hc2siLAogIG1pbjogMCwKICBzdGFja0NsZWFyaW5nOiB0cnVlCn0sIHsKICBpZDogImNudHJtYXNrIiwKICBtaW46IDAsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZQp9LCB7CiAgaWQ6ICJybW92ZXRvIiwKICBtaW46IDIsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZQp9LCB7CiAgaWQ6ICJobW92ZXRvIiwKICBtaW46IDEsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZQp9LCB7CiAgaWQ6ICJ2c3RlbWhtIiwKICBtaW46IDIsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZSwKICBzdGVtOiB0cnVlCn0sIHsKICBpZDogInJjdXJ2ZWxpbmUiLAogIG1pbjogOCwKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogInJsaW5lY3VydmUiLAogIG1pbjogOCwKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogInZ2Y3VydmV0byIsCiAgbWluOiA0LAogIHJlc2V0U3RhY2s6IHRydWUKfSwgewogIGlkOiAiaGhjdXJ2ZXRvIiwKICBtaW46IDQsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCBudWxsLCB7CiAgaWQ6ICJjYWxsZ3N1YnIiLAogIG1pbjogMSwKICB1bmRlZlN0YWNrOiB0cnVlCn0sIHsKICBpZDogInZoY3VydmV0byIsCiAgbWluOiA0LAogIHJlc2V0U3RhY2s6IHRydWUKfSwgewogIGlkOiAiaHZjdXJ2ZXRvIiwKICBtaW46IDQsCiAgcmVzZXRTdGFjazogdHJ1ZQp9XTsKY29uc3QgQ2hhcnN0cmluZ1ZhbGlkYXRpb25EYXRhMTIgPSBbbnVsbCwgbnVsbCwgbnVsbCwgewogIGlkOiAiYW5kIiwKICBtaW46IDIsCiAgc3RhY2tEZWx0YTogLTEKfSwgewogIGlkOiAib3IiLAogIG1pbjogMiwKICBzdGFja0RlbHRhOiAtMQp9LCB7CiAgaWQ6ICJub3QiLAogIG1pbjogMSwKICBzdGFja0RlbHRhOiAwCn0sIG51bGwsIG51bGwsIG51bGwsIHsKICBpZDogImFicyIsCiAgbWluOiAxLAogIHN0YWNrRGVsdGE6IDAKfSwgewogIGlkOiAiYWRkIiwKICBtaW46IDIsCiAgc3RhY2tEZWx0YTogLTEsCiAgc3RhY2tGbihzdGFjaywgaW5kZXgpIHsKICAgIHN0YWNrW2luZGV4IC0gMl0gPSBzdGFja1tpbmRleCAtIDJdICsgc3RhY2tbaW5kZXggLSAxXTsKICB9Cn0sIHsKICBpZDogInN1YiIsCiAgbWluOiAyLAogIHN0YWNrRGVsdGE6IC0xLAogIHN0YWNrRm4oc3RhY2ssIGluZGV4KSB7CiAgICBzdGFja1tpbmRleCAtIDJdID0gc3RhY2tbaW5kZXggLSAyXSAtIHN0YWNrW2luZGV4IC0gMV07CiAgfQp9LCB7CiAgaWQ6ICJkaXYiLAogIG1pbjogMiwKICBzdGFja0RlbHRhOiAtMSwKICBzdGFja0ZuKHN0YWNrLCBpbmRleCkgewogICAgc3RhY2tbaW5kZXggLSAyXSA9IHN0YWNrW2luZGV4IC0gMl0gLyBzdGFja1tpbmRleCAtIDFdOwogIH0KfSwgbnVsbCwgewogIGlkOiAibmVnIiwKICBtaW46IDEsCiAgc3RhY2tEZWx0YTogMCwKICBzdGFja0ZuKHN0YWNrLCBpbmRleCkgewogICAgc3RhY2tbaW5kZXggLSAxXSA9IC1zdGFja1tpbmRleCAtIDFdOwogIH0KfSwgewogIGlkOiAiZXEiLAogIG1pbjogMiwKICBzdGFja0RlbHRhOiAtMQp9LCBudWxsLCBudWxsLCB7CiAgaWQ6ICJkcm9wIiwKICBtaW46IDEsCiAgc3RhY2tEZWx0YTogLTEKfSwgbnVsbCwgewogIGlkOiAicHV0IiwKICBtaW46IDIsCiAgc3RhY2tEZWx0YTogLTIKfSwgewogIGlkOiAiZ2V0IiwKICBtaW46IDEsCiAgc3RhY2tEZWx0YTogMAp9LCB7CiAgaWQ6ICJpZmVsc2UiLAogIG1pbjogNCwKICBzdGFja0RlbHRhOiAtMwp9LCB7CiAgaWQ6ICJyYW5kb20iLAogIG1pbjogMCwKICBzdGFja0RlbHRhOiAxCn0sIHsKICBpZDogIm11bCIsCiAgbWluOiAyLAogIHN0YWNrRGVsdGE6IC0xLAogIHN0YWNrRm4oc3RhY2ssIGluZGV4KSB7CiAgICBzdGFja1tpbmRleCAtIDJdID0gc3RhY2tbaW5kZXggLSAyXSAqIHN0YWNrW2luZGV4IC0gMV07CiAgfQp9LCBudWxsLCB7CiAgaWQ6ICJzcXJ0IiwKICBtaW46IDEsCiAgc3RhY2tEZWx0YTogMAp9LCB7CiAgaWQ6ICJkdXAiLAogIG1pbjogMSwKICBzdGFja0RlbHRhOiAxCn0sIHsKICBpZDogImV4Y2giLAogIG1pbjogMiwKICBzdGFja0RlbHRhOiAwCn0sIHsKICBpZDogImluZGV4IiwKICBtaW46IDIsCiAgc3RhY2tEZWx0YTogMAp9LCB7CiAgaWQ6ICJyb2xsIiwKICBtaW46IDMsCiAgc3RhY2tEZWx0YTogLTIKfSwgbnVsbCwgbnVsbCwgbnVsbCwgewogIGlkOiAiaGZsZXgiLAogIG1pbjogNywKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogImZsZXgiLAogIG1pbjogMTMsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJoZmxleDEiLAogIG1pbjogOSwKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogImZsZXgxIiwKICBtaW46IDExLAogIHJlc2V0U3RhY2s6IHRydWUKfV07CmNsYXNzIENGRlBhcnNlciB7CiAgY29uc3RydWN0b3IoZmlsZSwgcHJvcGVydGllcywgc2VhY0FuYWx5c2lzRW5hYmxlZCkgewogICAgdGhpcy5ieXRlcyA9IGZpbGUuZ2V0Qnl0ZXMoKTsKICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7CiAgICB0aGlzLnNlYWNBbmFseXNpc0VuYWJsZWQgPSAhIXNlYWNBbmFseXNpc0VuYWJsZWQ7CiAgfQogIHBhcnNlKCkgewogICAgY29uc3QgcHJvcGVydGllcyA9IHRoaXMucHJvcGVydGllczsKICAgIGNvbnN0IGNmZiA9IG5ldyBDRkYoKTsKICAgIHRoaXMuY2ZmID0gY2ZmOwogICAgY29uc3QgaGVhZGVyID0gdGhpcy5wYXJzZUhlYWRlcigpOwogICAgY29uc3QgbmFtZUluZGV4ID0gdGhpcy5wYXJzZUluZGV4KGhlYWRlci5lbmRQb3MpOwogICAgY29uc3QgdG9wRGljdEluZGV4ID0gdGhpcy5wYXJzZUluZGV4KG5hbWVJbmRleC5lbmRQb3MpOwogICAgY29uc3Qgc3RyaW5nSW5kZXggPSB0aGlzLnBhcnNlSW5kZXgodG9wRGljdEluZGV4LmVuZFBvcyk7CiAgICBjb25zdCBnbG9iYWxTdWJySW5kZXggPSB0aGlzLnBhcnNlSW5kZXgoc3RyaW5nSW5kZXguZW5kUG9zKTsKICAgIGNvbnN0IHRvcERpY3RQYXJzZWQgPSB0aGlzLnBhcnNlRGljdCh0b3BEaWN0SW5kZXgub2JqLmdldCgwKSk7CiAgICBjb25zdCB0b3BEaWN0ID0gdGhpcy5jcmVhdGVEaWN0KENGRlRvcERpY3QsIHRvcERpY3RQYXJzZWQsIGNmZi5zdHJpbmdzKTsKICAgIGNmZi5oZWFkZXIgPSBoZWFkZXIub2JqOwogICAgY2ZmLm5hbWVzID0gdGhpcy5wYXJzZU5hbWVJbmRleChuYW1lSW5kZXgub2JqKTsKICAgIGNmZi5zdHJpbmdzID0gdGhpcy5wYXJzZVN0cmluZ0luZGV4KHN0cmluZ0luZGV4Lm9iaik7CiAgICBjZmYudG9wRGljdCA9IHRvcERpY3Q7CiAgICBjZmYuZ2xvYmFsU3VickluZGV4ID0gZ2xvYmFsU3VickluZGV4Lm9iajsKICAgIHRoaXMucGFyc2VQcml2YXRlRGljdChjZmYudG9wRGljdCk7CiAgICBjZmYuaXNDSURGb250ID0gdG9wRGljdC5oYXNOYW1lKCJST1MiKTsKICAgIGNvbnN0IGNoYXJTdHJpbmdPZmZzZXQgPSB0b3BEaWN0LmdldEJ5TmFtZSgiQ2hhclN0cmluZ3MiKTsKICAgIGNvbnN0IGNoYXJTdHJpbmdJbmRleCA9IHRoaXMucGFyc2VJbmRleChjaGFyU3RyaW5nT2Zmc2V0KS5vYmo7CiAgICBjb25zdCBmb250TWF0cml4ID0gdG9wRGljdC5nZXRCeU5hbWUoIkZvbnRNYXRyaXgiKTsKICAgIGlmIChmb250TWF0cml4KSB7CiAgICAgIHByb3BlcnRpZXMuZm9udE1hdHJpeCA9IGZvbnRNYXRyaXg7CiAgICB9CiAgICBjb25zdCBmb250QkJveCA9IHRvcERpY3QuZ2V0QnlOYW1lKCJGb250QkJveCIpOwogICAgaWYgKGZvbnRCQm94KSB7CiAgICAgIHByb3BlcnRpZXMuYXNjZW50ID0gTWF0aC5tYXgoZm9udEJCb3hbM10sIGZvbnRCQm94WzFdKTsKICAgICAgcHJvcGVydGllcy5kZXNjZW50ID0gTWF0aC5taW4oZm9udEJCb3hbMV0sIGZvbnRCQm94WzNdKTsKICAgICAgcHJvcGVydGllcy5hc2NlbnRTY2FsZWQgPSB0cnVlOwogICAgfQogICAgbGV0IGNoYXJzZXQsIGVuY29kaW5nOwogICAgaWYgKGNmZi5pc0NJREZvbnQpIHsKICAgICAgY29uc3QgZmRBcnJheUluZGV4ID0gdGhpcy5wYXJzZUluZGV4KHRvcERpY3QuZ2V0QnlOYW1lKCJGREFycmF5IikpLm9iajsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZmRBcnJheUluZGV4LmNvdW50OyBpIDwgaWk7ICsraSkgewogICAgICAgIGNvbnN0IGRpY3RSYXcgPSBmZEFycmF5SW5kZXguZ2V0KGkpOwogICAgICAgIGNvbnN0IGZvbnREaWN0ID0gdGhpcy5jcmVhdGVEaWN0KENGRlRvcERpY3QsIHRoaXMucGFyc2VEaWN0KGRpY3RSYXcpLCBjZmYuc3RyaW5ncyk7CiAgICAgICAgdGhpcy5wYXJzZVByaXZhdGVEaWN0KGZvbnREaWN0KTsKICAgICAgICBjZmYuZmRBcnJheS5wdXNoKGZvbnREaWN0KTsKICAgICAgfQogICAgICBlbmNvZGluZyA9IG51bGw7CiAgICAgIGNoYXJzZXQgPSB0aGlzLnBhcnNlQ2hhcnNldHModG9wRGljdC5nZXRCeU5hbWUoImNoYXJzZXQiKSwgY2hhclN0cmluZ0luZGV4LmNvdW50LCBjZmYuc3RyaW5ncywgdHJ1ZSk7CiAgICAgIGNmZi5mZFNlbGVjdCA9IHRoaXMucGFyc2VGRFNlbGVjdCh0b3BEaWN0LmdldEJ5TmFtZSgiRkRTZWxlY3QiKSwgY2hhclN0cmluZ0luZGV4LmNvdW50KTsKICAgIH0gZWxzZSB7CiAgICAgIGNoYXJzZXQgPSB0aGlzLnBhcnNlQ2hhcnNldHModG9wRGljdC5nZXRCeU5hbWUoImNoYXJzZXQiKSwgY2hhclN0cmluZ0luZGV4LmNvdW50LCBjZmYuc3RyaW5ncywgZmFsc2UpOwogICAgICBlbmNvZGluZyA9IHRoaXMucGFyc2VFbmNvZGluZyh0b3BEaWN0LmdldEJ5TmFtZSgiRW5jb2RpbmciKSwgcHJvcGVydGllcywgY2ZmLnN0cmluZ3MsIGNoYXJzZXQuY2hhcnNldCk7CiAgICB9CiAgICBjZmYuY2hhcnNldCA9IGNoYXJzZXQ7CiAgICBjZmYuZW5jb2RpbmcgPSBlbmNvZGluZzsKICAgIGNvbnN0IGNoYXJTdHJpbmdzQW5kU2VhY3MgPSB0aGlzLnBhcnNlQ2hhclN0cmluZ3MoewogICAgICBjaGFyU3RyaW5nczogY2hhclN0cmluZ0luZGV4LAogICAgICBsb2NhbFN1YnJJbmRleDogdG9wRGljdC5wcml2YXRlRGljdC5zdWJyc0luZGV4LAogICAgICBnbG9iYWxTdWJySW5kZXg6IGdsb2JhbFN1YnJJbmRleC5vYmosCiAgICAgIGZkU2VsZWN0OiBjZmYuZmRTZWxlY3QsCiAgICAgIGZkQXJyYXk6IGNmZi5mZEFycmF5LAogICAgICBwcml2YXRlRGljdDogdG9wRGljdC5wcml2YXRlRGljdAogICAgfSk7CiAgICBjZmYuY2hhclN0cmluZ3MgPSBjaGFyU3RyaW5nc0FuZFNlYWNzLmNoYXJTdHJpbmdzOwogICAgY2ZmLnNlYWNzID0gY2hhclN0cmluZ3NBbmRTZWFjcy5zZWFjczsKICAgIGNmZi53aWR0aHMgPSBjaGFyU3RyaW5nc0FuZFNlYWNzLndpZHRoczsKICAgIHJldHVybiBjZmY7CiAgfQogIHBhcnNlSGVhZGVyKCkgewogICAgbGV0IGJ5dGVzID0gdGhpcy5ieXRlczsKICAgIGNvbnN0IGJ5dGVzTGVuZ3RoID0gYnl0ZXMubGVuZ3RoOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICB3aGlsZSAob2Zmc2V0IDwgYnl0ZXNMZW5ndGggJiYgYnl0ZXNbb2Zmc2V0XSAhPT0gMSkgewogICAgICArK29mZnNldDsKICAgIH0KICAgIGlmIChvZmZzZXQgPj0gYnl0ZXNMZW5ndGgpIHsKICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJJbnZhbGlkIENGRiBoZWFkZXIiKTsKICAgIH0KICAgIGlmIChvZmZzZXQgIT09IDApIHsKICAgICAgKDAsIF91dGlsLmluZm8pKCJjZmYgZGF0YSBpcyBzaGlmdGVkIik7CiAgICAgIGJ5dGVzID0gYnl0ZXMuc3ViYXJyYXkob2Zmc2V0KTsKICAgICAgdGhpcy5ieXRlcyA9IGJ5dGVzOwogICAgfQogICAgY29uc3QgbWFqb3IgPSBieXRlc1swXTsKICAgIGNvbnN0IG1pbm9yID0gYnl0ZXNbMV07CiAgICBjb25zdCBoZHJTaXplID0gYnl0ZXNbMl07CiAgICBjb25zdCBvZmZTaXplID0gYnl0ZXNbM107CiAgICBjb25zdCBoZWFkZXIgPSBuZXcgQ0ZGSGVhZGVyKG1ham9yLCBtaW5vciwgaGRyU2l6ZSwgb2ZmU2l6ZSk7CiAgICByZXR1cm4gewogICAgICBvYmo6IGhlYWRlciwKICAgICAgZW5kUG9zOiBoZHJTaXplCiAgICB9OwogIH0KICBwYXJzZURpY3QoZGljdCkgewogICAgbGV0IHBvcyA9IDA7CiAgICBmdW5jdGlvbiBwYXJzZU9wZXJhbmQoKSB7CiAgICAgIGxldCB2YWx1ZSA9IGRpY3RbcG9zKytdOwogICAgICBpZiAodmFsdWUgPT09IDMwKSB7CiAgICAgICAgcmV0dXJuIHBhcnNlRmxvYXRPcGVyYW5kKCk7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IDI4KSB7CiAgICAgICAgdmFsdWUgPSBkaWN0W3BvcysrXTsKICAgICAgICB2YWx1ZSA9ICh2YWx1ZSA8PCAyNCB8IGRpY3RbcG9zKytdIDw8IDE2KSA+PiAxNjsKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IDI5KSB7CiAgICAgICAgdmFsdWUgPSBkaWN0W3BvcysrXTsKICAgICAgICB2YWx1ZSA9IHZhbHVlIDw8IDggfCBkaWN0W3BvcysrXTsKICAgICAgICB2YWx1ZSA9IHZhbHVlIDw8IDggfCBkaWN0W3BvcysrXTsKICAgICAgICB2YWx1ZSA9IHZhbHVlIDw8IDggfCBkaWN0W3BvcysrXTsKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPj0gMzIgJiYgdmFsdWUgPD0gMjQ2KSB7CiAgICAgICAgcmV0dXJuIHZhbHVlIC0gMTM5OwogICAgICB9IGVsc2UgaWYgKHZhbHVlID49IDI0NyAmJiB2YWx1ZSA8PSAyNTApIHsKICAgICAgICByZXR1cm4gKHZhbHVlIC0gMjQ3KSAqIDI1NiArIGRpY3RbcG9zKytdICsgMTA4OwogICAgICB9IGVsc2UgaWYgKHZhbHVlID49IDI1MSAmJiB2YWx1ZSA8PSAyNTQpIHsKICAgICAgICByZXR1cm4gLSgodmFsdWUgLSAyNTEpICogMjU2KSAtIGRpY3RbcG9zKytdIC0gMTA4OwogICAgICB9CiAgICAgICgwLCBfdXRpbC53YXJuKSgnQ0ZGUGFyc2VyX3BhcnNlRGljdDogIicgKyB2YWx1ZSArICciIGlzIGEgcmVzZXJ2ZWQgY29tbWFuZC4nKTsKICAgICAgcmV0dXJuIE5hTjsKICAgIH0KICAgIGZ1bmN0aW9uIHBhcnNlRmxvYXRPcGVyYW5kKCkgewogICAgICBsZXQgc3RyID0gIiI7CiAgICAgIGNvbnN0IGVvZiA9IDE1OwogICAgICBjb25zdCBsb29rdXAgPSBbIjAiLCAiMSIsICIyIiwgIjMiLCAiNCIsICI1IiwgIjYiLCAiNyIsICI4IiwgIjkiLCAiLiIsICJFIiwgIkUtIiwgbnVsbCwgIi0iXTsKICAgICAgY29uc3QgbGVuZ3RoID0gZGljdC5sZW5ndGg7CiAgICAgIHdoaWxlIChwb3MgPCBsZW5ndGgpIHsKICAgICAgICBjb25zdCBiID0gZGljdFtwb3MrK107CiAgICAgICAgY29uc3QgYjEgPSBiID4+IDQ7CiAgICAgICAgY29uc3QgYjIgPSBiICYgMTU7CiAgICAgICAgaWYgKGIxID09PSBlb2YpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBzdHIgKz0gbG9va3VwW2IxXTsKICAgICAgICBpZiAoYjIgPT09IGVvZikgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHN0ciArPSBsb29rdXBbYjJdOwogICAgICB9CiAgICAgIHJldHVybiBwYXJzZUZsb2F0KHN0cik7CiAgICB9CiAgICBsZXQgb3BlcmFuZHMgPSBbXTsKICAgIGNvbnN0IGVudHJpZXMgPSBbXTsKICAgIHBvcyA9IDA7CiAgICBjb25zdCBlbmQgPSBkaWN0Lmxlbmd0aDsKICAgIHdoaWxlIChwb3MgPCBlbmQpIHsKICAgICAgbGV0IGIgPSBkaWN0W3Bvc107CiAgICAgIGlmIChiIDw9IDIxKSB7CiAgICAgICAgaWYgKGIgPT09IDEyKSB7CiAgICAgICAgICBiID0gYiA8PCA4IHwgZGljdFsrK3Bvc107CiAgICAgICAgfQogICAgICAgIGVudHJpZXMucHVzaChbYiwgb3BlcmFuZHNdKTsKICAgICAgICBvcGVyYW5kcyA9IFtdOwogICAgICAgICsrcG9zOwogICAgICB9IGVsc2UgewogICAgICAgIG9wZXJhbmRzLnB1c2gocGFyc2VPcGVyYW5kKCkpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZW50cmllczsKICB9CiAgcGFyc2VJbmRleChwb3MpIHsKICAgIGNvbnN0IGNmZkluZGV4ID0gbmV3IENGRkluZGV4KCk7CiAgICBjb25zdCBieXRlcyA9IHRoaXMuYnl0ZXM7CiAgICBjb25zdCBjb3VudCA9IGJ5dGVzW3BvcysrXSA8PCA4IHwgYnl0ZXNbcG9zKytdOwogICAgY29uc3Qgb2Zmc2V0cyA9IFtdOwogICAgbGV0IGVuZCA9IHBvczsKICAgIGxldCBpLCBpaTsKICAgIGlmIChjb3VudCAhPT0gMCkgewogICAgICBjb25zdCBvZmZzZXRTaXplID0gYnl0ZXNbcG9zKytdOwogICAgICBjb25zdCBzdGFydFBvcyA9IHBvcyArIChjb3VudCArIDEpICogb2Zmc2V0U2l6ZSAtIDE7CiAgICAgIGZvciAoaSA9IDAsIGlpID0gY291bnQgKyAxOyBpIDwgaWk7ICsraSkgewogICAgICAgIGxldCBvZmZzZXQgPSAwOwogICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgb2Zmc2V0U2l6ZTsgKytqKSB7CiAgICAgICAgICBvZmZzZXQgPDw9IDg7CiAgICAgICAgICBvZmZzZXQgKz0gYnl0ZXNbcG9zKytdOwogICAgICAgIH0KICAgICAgICBvZmZzZXRzLnB1c2goc3RhcnRQb3MgKyBvZmZzZXQpOwogICAgICB9CiAgICAgIGVuZCA9IG9mZnNldHNbY291bnRdOwogICAgfQogICAgZm9yIChpID0gMCwgaWkgPSBvZmZzZXRzLmxlbmd0aCAtIDE7IGkgPCBpaTsgKytpKSB7CiAgICAgIGNvbnN0IG9mZnNldFN0YXJ0ID0gb2Zmc2V0c1tpXTsKICAgICAgY29uc3Qgb2Zmc2V0RW5kID0gb2Zmc2V0c1tpICsgMV07CiAgICAgIGNmZkluZGV4LmFkZChieXRlcy5zdWJhcnJheShvZmZzZXRTdGFydCwgb2Zmc2V0RW5kKSk7CiAgICB9CiAgICByZXR1cm4gewogICAgICBvYmo6IGNmZkluZGV4LAogICAgICBlbmRQb3M6IGVuZAogICAgfTsKICB9CiAgcGFyc2VOYW1lSW5kZXgoaW5kZXgpIHsKICAgIGNvbnN0IG5hbWVzID0gW107CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBpbmRleC5jb3VudDsgaSA8IGlpOyArK2kpIHsKICAgICAgY29uc3QgbmFtZSA9IGluZGV4LmdldChpKTsKICAgICAgbmFtZXMucHVzaCgoMCwgX3V0aWwuYnl0ZXNUb1N0cmluZykobmFtZSkpOwogICAgfQogICAgcmV0dXJuIG5hbWVzOwogIH0KICBwYXJzZVN0cmluZ0luZGV4KGluZGV4KSB7CiAgICBjb25zdCBzdHJpbmdzID0gbmV3IENGRlN0cmluZ3MoKTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGluZGV4LmNvdW50OyBpIDwgaWk7ICsraSkgewogICAgICBjb25zdCBkYXRhID0gaW5kZXguZ2V0KGkpOwogICAgICBzdHJpbmdzLmFkZCgoMCwgX3V0aWwuYnl0ZXNUb1N0cmluZykoZGF0YSkpOwogICAgfQogICAgcmV0dXJuIHN0cmluZ3M7CiAgfQogIGNyZWF0ZURpY3QoVHlwZSwgZGljdCwgc3RyaW5ncykgewogICAgY29uc3QgY2ZmRGljdCA9IG5ldyBUeXBlKHN0cmluZ3MpOwogICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgZGljdCkgewogICAgICBjZmZEaWN0LnNldEJ5S2V5KGtleSwgdmFsdWUpOwogICAgfQogICAgcmV0dXJuIGNmZkRpY3Q7CiAgfQogIHBhcnNlQ2hhclN0cmluZyhzdGF0ZSwgZGF0YSwgbG9jYWxTdWJySW5kZXgsIGdsb2JhbFN1YnJJbmRleCkgewogICAgaWYgKCFkYXRhIHx8IHN0YXRlLmNhbGxEZXB0aCA+IE1BWF9TVUJSX05FU1RJTkcpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgbGV0IHN0YWNrU2l6ZSA9IHN0YXRlLnN0YWNrU2l6ZTsKICAgIGNvbnN0IHN0YWNrID0gc3RhdGUuc3RhY2s7CiAgICBsZXQgbGVuZ3RoID0gZGF0YS5sZW5ndGg7CiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxlbmd0aDspIHsKICAgICAgY29uc3QgdmFsdWUgPSBkYXRhW2orK107CiAgICAgIGxldCB2YWxpZGF0aW9uQ29tbWFuZCA9IG51bGw7CiAgICAgIGlmICh2YWx1ZSA9PT0gMTIpIHsKICAgICAgICBjb25zdCBxID0gZGF0YVtqKytdOwogICAgICAgIGlmIChxID09PSAwKSB7CiAgICAgICAgICBkYXRhW2ogLSAyXSA9IDEzOTsKICAgICAgICAgIGRhdGFbaiAtIDFdID0gMjI7CiAgICAgICAgICBzdGFja1NpemUgPSAwOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB2YWxpZGF0aW9uQ29tbWFuZCA9IENoYXJzdHJpbmdWYWxpZGF0aW9uRGF0YTEyW3FdOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gMjgpIHsKICAgICAgICBzdGFja1tzdGFja1NpemVdID0gKGRhdGFbal0gPDwgMjQgfCBkYXRhW2ogKyAxXSA8PCAxNikgPj4gMTY7CiAgICAgICAgaiArPSAyOwogICAgICAgIHN0YWNrU2l6ZSsrOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAxNCkgewogICAgICAgIGlmIChzdGFja1NpemUgPj0gNCkgewogICAgICAgICAgc3RhY2tTaXplIC09IDQ7CiAgICAgICAgICBpZiAodGhpcy5zZWFjQW5hbHlzaXNFbmFibGVkKSB7CiAgICAgICAgICAgIHN0YXRlLnNlYWMgPSBzdGFjay5zbGljZShzdGFja1NpemUsIHN0YWNrU2l6ZSArIDQpOwogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHZhbGlkYXRpb25Db21tYW5kID0gQ2hhcnN0cmluZ1ZhbGlkYXRpb25EYXRhW3ZhbHVlXTsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA+PSAzMiAmJiB2YWx1ZSA8PSAyNDYpIHsKICAgICAgICBzdGFja1tzdGFja1NpemVdID0gdmFsdWUgLSAxMzk7CiAgICAgICAgc3RhY2tTaXplKys7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPj0gMjQ3ICYmIHZhbHVlIDw9IDI1NCkgewogICAgICAgIHN0YWNrW3N0YWNrU2l6ZV0gPSB2YWx1ZSA8IDI1MSA/ICh2YWx1ZSAtIDI0NyA8PCA4KSArIGRhdGFbal0gKyAxMDggOiAtKHZhbHVlIC0gMjUxIDw8IDgpIC0gZGF0YVtqXSAtIDEwODsKICAgICAgICBqKys7CiAgICAgICAgc3RhY2tTaXplKys7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IDI1NSkgewogICAgICAgIHN0YWNrW3N0YWNrU2l6ZV0gPSAoZGF0YVtqXSA8PCAyNCB8IGRhdGFbaiArIDFdIDw8IDE2IHwgZGF0YVtqICsgMl0gPDwgOCB8IGRhdGFbaiArIDNdKSAvIDY1NTM2OwogICAgICAgIGogKz0gNDsKICAgICAgICBzdGFja1NpemUrKzsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gMTkgfHwgdmFsdWUgPT09IDIwKSB7CiAgICAgICAgc3RhdGUuaGludHMgKz0gc3RhY2tTaXplID4+IDE7CiAgICAgICAgaiArPSBzdGF0ZS5oaW50cyArIDcgPj4gMzsKICAgICAgICBzdGFja1NpemUgJT0gMjsKICAgICAgICB2YWxpZGF0aW9uQ29tbWFuZCA9IENoYXJzdHJpbmdWYWxpZGF0aW9uRGF0YVt2YWx1ZV07CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IDEwIHx8IHZhbHVlID09PSAyOSkgewogICAgICAgIGxldCBzdWJyc0luZGV4OwogICAgICAgIGlmICh2YWx1ZSA9PT0gMTApIHsKICAgICAgICAgIHN1YnJzSW5kZXggPSBsb2NhbFN1YnJJbmRleDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3VicnNJbmRleCA9IGdsb2JhbFN1YnJJbmRleDsKICAgICAgICB9CiAgICAgICAgaWYgKCFzdWJyc0luZGV4KSB7CiAgICAgICAgICB2YWxpZGF0aW9uQ29tbWFuZCA9IENoYXJzdHJpbmdWYWxpZGF0aW9uRGF0YVt2YWx1ZV07CiAgICAgICAgICAoMCwgX3V0aWwud2FybikoIk1pc3Npbmcgc3VicnNJbmRleCBmb3IgIiArIHZhbGlkYXRpb25Db21tYW5kLmlkKTsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgbGV0IGJpYXMgPSAzMjc2ODsKICAgICAgICBpZiAoc3VicnNJbmRleC5jb3VudCA8IDEyNDApIHsKICAgICAgICAgIGJpYXMgPSAxMDc7CiAgICAgICAgfSBlbHNlIGlmIChzdWJyc0luZGV4LmNvdW50IDwgMzM5MDApIHsKICAgICAgICAgIGJpYXMgPSAxMTMxOwogICAgICAgIH0KICAgICAgICBjb25zdCBzdWJyTnVtYmVyID0gc3RhY2tbLS1zdGFja1NpemVdICsgYmlhczsKICAgICAgICBpZiAoc3Vick51bWJlciA8IDAgfHwgc3Vick51bWJlciA+PSBzdWJyc0luZGV4LmNvdW50IHx8IGlzTmFOKHN1YnJOdW1iZXIpKSB7CiAgICAgICAgICB2YWxpZGF0aW9uQ29tbWFuZCA9IENoYXJzdHJpbmdWYWxpZGF0aW9uRGF0YVt2YWx1ZV07CiAgICAgICAgICAoMCwgX3V0aWwud2FybikoIk91dCBvZiBib3VuZHMgc3VickluZGV4IGZvciAiICsgdmFsaWRhdGlvbkNvbW1hbmQuaWQpOwogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICBzdGF0ZS5zdGFja1NpemUgPSBzdGFja1NpemU7CiAgICAgICAgc3RhdGUuY2FsbERlcHRoKys7CiAgICAgICAgY29uc3QgdmFsaWQgPSB0aGlzLnBhcnNlQ2hhclN0cmluZyhzdGF0ZSwgc3VicnNJbmRleC5nZXQoc3Vick51bWJlciksIGxvY2FsU3VickluZGV4LCBnbG9iYWxTdWJySW5kZXgpOwogICAgICAgIGlmICghdmFsaWQpIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgc3RhdGUuY2FsbERlcHRoLS07CiAgICAgICAgc3RhY2tTaXplID0gc3RhdGUuc3RhY2tTaXplOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAxMSkgewogICAgICAgIHN0YXRlLnN0YWNrU2l6ZSA9IHN0YWNrU2l6ZTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gMCAmJiBqID09PSBkYXRhLmxlbmd0aCkgewogICAgICAgIGRhdGFbaiAtIDFdID0gMTQ7CiAgICAgICAgdmFsaWRhdGlvbkNvbW1hbmQgPSBDaGFyc3RyaW5nVmFsaWRhdGlvbkRhdGFbMTRdOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSA5KSB7CiAgICAgICAgZGF0YS5jb3B5V2l0aGluKGogLSAxLCBqLCAtMSk7CiAgICAgICAgaiAtPSAxOwogICAgICAgIGxlbmd0aCAtPSAxOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9IGVsc2UgewogICAgICAgIHZhbGlkYXRpb25Db21tYW5kID0gQ2hhcnN0cmluZ1ZhbGlkYXRpb25EYXRhW3ZhbHVlXTsKICAgICAgfQogICAgICBpZiAodmFsaWRhdGlvbkNvbW1hbmQpIHsKICAgICAgICBpZiAodmFsaWRhdGlvbkNvbW1hbmQuc3RlbSkgewogICAgICAgICAgc3RhdGUuaGludHMgKz0gc3RhY2tTaXplID4+IDE7CiAgICAgICAgICBpZiAodmFsdWUgPT09IDMgfHwgdmFsdWUgPT09IDIzKSB7CiAgICAgICAgICAgIHN0YXRlLmhhc1ZTdGVtcyA9IHRydWU7CiAgICAgICAgICB9IGVsc2UgaWYgKHN0YXRlLmhhc1ZTdGVtcyAmJiAodmFsdWUgPT09IDEgfHwgdmFsdWUgPT09IDE4KSkgewogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoIkNGRiBzdGVtIGhpbnRzIGFyZSBpbiB3cm9uZyBvcmRlciIpOwogICAgICAgICAgICBkYXRhW2ogLSAxXSA9IHZhbHVlID09PSAxID8gMyA6IDIzOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoIm1pbiIgaW4gdmFsaWRhdGlvbkNvbW1hbmQpIHsKICAgICAgICAgIGlmICghc3RhdGUudW5kZWZTdGFjayAmJiBzdGFja1NpemUgPCB2YWxpZGF0aW9uQ29tbWFuZC5taW4pIHsKICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJOb3QgZW5vdWdoIHBhcmFtZXRlcnMgZm9yICIgKyB2YWxpZGF0aW9uQ29tbWFuZC5pZCArICI7IGFjdHVhbDogIiArIHN0YWNrU2l6ZSArICIsIGV4cGVjdGVkOiAiICsgdmFsaWRhdGlvbkNvbW1hbmQubWluKTsKICAgICAgICAgICAgaWYgKHN0YWNrU2l6ZSA9PT0gMCkgewogICAgICAgICAgICAgIGRhdGFbaiAtIDFdID0gMTQ7CiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoc3RhdGUuZmlyc3RTdGFja0NsZWFyaW5nICYmIHZhbGlkYXRpb25Db21tYW5kLnN0YWNrQ2xlYXJpbmcpIHsKICAgICAgICAgIHN0YXRlLmZpcnN0U3RhY2tDbGVhcmluZyA9IGZhbHNlOwogICAgICAgICAgc3RhY2tTaXplIC09IHZhbGlkYXRpb25Db21tYW5kLm1pbjsKICAgICAgICAgIGlmIChzdGFja1NpemUgPj0gMiAmJiB2YWxpZGF0aW9uQ29tbWFuZC5zdGVtKSB7CiAgICAgICAgICAgIHN0YWNrU2l6ZSAlPSAyOwogICAgICAgICAgfSBlbHNlIGlmIChzdGFja1NpemUgPiAxKSB7CiAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiRm91bmQgdG9vIG1hbnkgcGFyYW1ldGVycyBmb3Igc3RhY2stY2xlYXJpbmcgY29tbWFuZCIpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHN0YWNrU2l6ZSA+IDApIHsKICAgICAgICAgICAgc3RhdGUud2lkdGggPSBzdGFja1tzdGFja1NpemUgLSAxXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKCJzdGFja0RlbHRhIiBpbiB2YWxpZGF0aW9uQ29tbWFuZCkgewogICAgICAgICAgaWYgKCJzdGFja0ZuIiBpbiB2YWxpZGF0aW9uQ29tbWFuZCkgewogICAgICAgICAgICB2YWxpZGF0aW9uQ29tbWFuZC5zdGFja0ZuKHN0YWNrLCBzdGFja1NpemUpOwogICAgICAgICAgfQogICAgICAgICAgc3RhY2tTaXplICs9IHZhbGlkYXRpb25Db21tYW5kLnN0YWNrRGVsdGE7CiAgICAgICAgfSBlbHNlIGlmICh2YWxpZGF0aW9uQ29tbWFuZC5zdGFja0NsZWFyaW5nKSB7CiAgICAgICAgICBzdGFja1NpemUgPSAwOwogICAgICAgIH0gZWxzZSBpZiAodmFsaWRhdGlvbkNvbW1hbmQucmVzZXRTdGFjaykgewogICAgICAgICAgc3RhY2tTaXplID0gMDsKICAgICAgICAgIHN0YXRlLnVuZGVmU3RhY2sgPSBmYWxzZTsKICAgICAgICB9IGVsc2UgaWYgKHZhbGlkYXRpb25Db21tYW5kLnVuZGVmU3RhY2spIHsKICAgICAgICAgIHN0YWNrU2l6ZSA9IDA7CiAgICAgICAgICBzdGF0ZS51bmRlZlN0YWNrID0gdHJ1ZTsKICAgICAgICAgIHN0YXRlLmZpcnN0U3RhY2tDbGVhcmluZyA9IGZhbHNlOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKGxlbmd0aCA8IGRhdGEubGVuZ3RoKSB7CiAgICAgIGRhdGEuZmlsbCgxNCwgbGVuZ3RoKTsKICAgIH0KICAgIHN0YXRlLnN0YWNrU2l6ZSA9IHN0YWNrU2l6ZTsKICAgIHJldHVybiB0cnVlOwogIH0KICBwYXJzZUNoYXJTdHJpbmdzKF9yZWYpIHsKICAgIGxldCB7CiAgICAgIGNoYXJTdHJpbmdzLAogICAgICBsb2NhbFN1YnJJbmRleCwKICAgICAgZ2xvYmFsU3VickluZGV4LAogICAgICBmZFNlbGVjdCwKICAgICAgZmRBcnJheSwKICAgICAgcHJpdmF0ZURpY3QKICAgIH0gPSBfcmVmOwogICAgY29uc3Qgc2VhY3MgPSBbXTsKICAgIGNvbnN0IHdpZHRocyA9IFtdOwogICAgY29uc3QgY291bnQgPSBjaGFyU3RyaW5ncy5jb3VudDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7IGkrKykgewogICAgICBjb25zdCBjaGFyc3RyaW5nID0gY2hhclN0cmluZ3MuZ2V0KGkpOwogICAgICBjb25zdCBzdGF0ZSA9IHsKICAgICAgICBjYWxsRGVwdGg6IDAsCiAgICAgICAgc3RhY2tTaXplOiAwLAogICAgICAgIHN0YWNrOiBbXSwKICAgICAgICB1bmRlZlN0YWNrOiB0cnVlLAogICAgICAgIGhpbnRzOiAwLAogICAgICAgIGZpcnN0U3RhY2tDbGVhcmluZzogdHJ1ZSwKICAgICAgICBzZWFjOiBudWxsLAogICAgICAgIHdpZHRoOiBudWxsLAogICAgICAgIGhhc1ZTdGVtczogZmFsc2UKICAgICAgfTsKICAgICAgbGV0IHZhbGlkID0gdHJ1ZTsKICAgICAgbGV0IGxvY2FsU3ViclRvVXNlID0gbnVsbDsKICAgICAgbGV0IHByaXZhdGVEaWN0VG9Vc2UgPSBwcml2YXRlRGljdDsKICAgICAgaWYgKGZkU2VsZWN0ICYmIGZkQXJyYXkubGVuZ3RoKSB7CiAgICAgICAgY29uc3QgZmRJbmRleCA9IGZkU2VsZWN0LmdldEZESW5kZXgoaSk7CiAgICAgICAgaWYgKGZkSW5kZXggPT09IC0xKSB7CiAgICAgICAgICAoMCwgX3V0aWwud2FybikoIkdseXBoIGluZGV4IGlzIG5vdCBpbiBmZCBzZWxlY3QuIik7CiAgICAgICAgICB2YWxpZCA9IGZhbHNlOwogICAgICAgIH0KICAgICAgICBpZiAoZmRJbmRleCA+PSBmZEFycmF5Lmxlbmd0aCkgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJJbnZhbGlkIGZkIGluZGV4IGZvciBnbHlwaCBpbmRleC4iKTsKICAgICAgICAgIHZhbGlkID0gZmFsc2U7CiAgICAgICAgfQogICAgICAgIGlmICh2YWxpZCkgewogICAgICAgICAgcHJpdmF0ZURpY3RUb1VzZSA9IGZkQXJyYXlbZmRJbmRleF0ucHJpdmF0ZURpY3Q7CiAgICAgICAgICBsb2NhbFN1YnJUb1VzZSA9IHByaXZhdGVEaWN0VG9Vc2Uuc3VicnNJbmRleDsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAobG9jYWxTdWJySW5kZXgpIHsKICAgICAgICBsb2NhbFN1YnJUb1VzZSA9IGxvY2FsU3VickluZGV4OwogICAgICB9CiAgICAgIGlmICh2YWxpZCkgewogICAgICAgIHZhbGlkID0gdGhpcy5wYXJzZUNoYXJTdHJpbmcoc3RhdGUsIGNoYXJzdHJpbmcsIGxvY2FsU3ViclRvVXNlLCBnbG9iYWxTdWJySW5kZXgpOwogICAgICB9CiAgICAgIGlmIChzdGF0ZS53aWR0aCAhPT0gbnVsbCkgewogICAgICAgIGNvbnN0IG5vbWluYWxXaWR0aCA9IHByaXZhdGVEaWN0VG9Vc2UuZ2V0QnlOYW1lKCJub21pbmFsV2lkdGhYIik7CiAgICAgICAgd2lkdGhzW2ldID0gbm9taW5hbFdpZHRoICsgc3RhdGUud2lkdGg7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgZGVmYXVsdFdpZHRoID0gcHJpdmF0ZURpY3RUb1VzZS5nZXRCeU5hbWUoImRlZmF1bHRXaWR0aFgiKTsKICAgICAgICB3aWR0aHNbaV0gPSBkZWZhdWx0V2lkdGg7CiAgICAgIH0KICAgICAgaWYgKHN0YXRlLnNlYWMgIT09IG51bGwpIHsKICAgICAgICBzZWFjc1tpXSA9IHN0YXRlLnNlYWM7CiAgICAgIH0KICAgICAgaWYgKCF2YWxpZCkgewogICAgICAgIGNoYXJTdHJpbmdzLnNldChpLCBuZXcgVWludDhBcnJheShbMTRdKSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7CiAgICAgIGNoYXJTdHJpbmdzLAogICAgICBzZWFjcywKICAgICAgd2lkdGhzCiAgICB9OwogIH0KICBlbXB0eVByaXZhdGVEaWN0aW9uYXJ5KHBhcmVudERpY3QpIHsKICAgIGNvbnN0IHByaXZhdGVEaWN0ID0gdGhpcy5jcmVhdGVEaWN0KENGRlByaXZhdGVEaWN0LCBbXSwgcGFyZW50RGljdC5zdHJpbmdzKTsKICAgIHBhcmVudERpY3Quc2V0QnlLZXkoMTgsIFswLCAwXSk7CiAgICBwYXJlbnREaWN0LnByaXZhdGVEaWN0ID0gcHJpdmF0ZURpY3Q7CiAgfQogIHBhcnNlUHJpdmF0ZURpY3QocGFyZW50RGljdCkgewogICAgaWYgKCFwYXJlbnREaWN0Lmhhc05hbWUoIlByaXZhdGUiKSkgewogICAgICB0aGlzLmVtcHR5UHJpdmF0ZURpY3Rpb25hcnkocGFyZW50RGljdCk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHByaXZhdGVPZmZzZXQgPSBwYXJlbnREaWN0LmdldEJ5TmFtZSgiUHJpdmF0ZSIpOwogICAgaWYgKCFBcnJheS5pc0FycmF5KHByaXZhdGVPZmZzZXQpIHx8IHByaXZhdGVPZmZzZXQubGVuZ3RoICE9PSAyKSB7CiAgICAgIHBhcmVudERpY3QucmVtb3ZlQnlOYW1lKCJQcml2YXRlIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHNpemUgPSBwcml2YXRlT2Zmc2V0WzBdOwogICAgY29uc3Qgb2Zmc2V0ID0gcHJpdmF0ZU9mZnNldFsxXTsKICAgIGlmIChzaXplID09PSAwIHx8IG9mZnNldCA+PSB0aGlzLmJ5dGVzLmxlbmd0aCkgewogICAgICB0aGlzLmVtcHR5UHJpdmF0ZURpY3Rpb25hcnkocGFyZW50RGljdCk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHByaXZhdGVEaWN0RW5kID0gb2Zmc2V0ICsgc2l6ZTsKICAgIGNvbnN0IGRpY3REYXRhID0gdGhpcy5ieXRlcy5zdWJhcnJheShvZmZzZXQsIHByaXZhdGVEaWN0RW5kKTsKICAgIGNvbnN0IGRpY3QgPSB0aGlzLnBhcnNlRGljdChkaWN0RGF0YSk7CiAgICBjb25zdCBwcml2YXRlRGljdCA9IHRoaXMuY3JlYXRlRGljdChDRkZQcml2YXRlRGljdCwgZGljdCwgcGFyZW50RGljdC5zdHJpbmdzKTsKICAgIHBhcmVudERpY3QucHJpdmF0ZURpY3QgPSBwcml2YXRlRGljdDsKICAgIGlmIChwcml2YXRlRGljdC5nZXRCeU5hbWUoIkV4cGFuc2lvbkZhY3RvciIpID09PSAwKSB7CiAgICAgIHByaXZhdGVEaWN0LnNldEJ5TmFtZSgiRXhwYW5zaW9uRmFjdG9yIiwgMC4wNik7CiAgICB9CiAgICBpZiAoIXByaXZhdGVEaWN0LmdldEJ5TmFtZSgiU3VicnMiKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBzdWJyc09mZnNldCA9IHByaXZhdGVEaWN0LmdldEJ5TmFtZSgiU3VicnMiKTsKICAgIGNvbnN0IHJlbGF0aXZlT2Zmc2V0ID0gb2Zmc2V0ICsgc3VicnNPZmZzZXQ7CiAgICBpZiAoc3VicnNPZmZzZXQgPT09IDAgfHwgcmVsYXRpdmVPZmZzZXQgPj0gdGhpcy5ieXRlcy5sZW5ndGgpIHsKICAgICAgdGhpcy5lbXB0eVByaXZhdGVEaWN0aW9uYXJ5KHBhcmVudERpY3QpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBzdWJyc0luZGV4ID0gdGhpcy5wYXJzZUluZGV4KHJlbGF0aXZlT2Zmc2V0KTsKICAgIHByaXZhdGVEaWN0LnN1YnJzSW5kZXggPSBzdWJyc0luZGV4Lm9iajsKICB9CiAgcGFyc2VDaGFyc2V0cyhwb3MsIGxlbmd0aCwgc3RyaW5ncywgY2lkKSB7CiAgICBpZiAocG9zID09PSAwKSB7CiAgICAgIHJldHVybiBuZXcgQ0ZGQ2hhcnNldCh0cnVlLCBDRkZDaGFyc2V0UHJlZGVmaW5lZFR5cGVzLklTT19BRE9CRSwgX2NoYXJzZXRzLklTT0Fkb2JlQ2hhcnNldCk7CiAgICB9IGVsc2UgaWYgKHBvcyA9PT0gMSkgewogICAgICByZXR1cm4gbmV3IENGRkNoYXJzZXQodHJ1ZSwgQ0ZGQ2hhcnNldFByZWRlZmluZWRUeXBlcy5FWFBFUlQsIF9jaGFyc2V0cy5FeHBlcnRDaGFyc2V0KTsKICAgIH0gZWxzZSBpZiAocG9zID09PSAyKSB7CiAgICAgIHJldHVybiBuZXcgQ0ZGQ2hhcnNldCh0cnVlLCBDRkZDaGFyc2V0UHJlZGVmaW5lZFR5cGVzLkVYUEVSVF9TVUJTRVQsIF9jaGFyc2V0cy5FeHBlcnRTdWJzZXRDaGFyc2V0KTsKICAgIH0KICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5ieXRlczsKICAgIGNvbnN0IHN0YXJ0ID0gcG9zOwogICAgY29uc3QgZm9ybWF0ID0gYnl0ZXNbcG9zKytdOwogICAgY29uc3QgY2hhcnNldCA9IFtjaWQgPyAwIDogIi5ub3RkZWYiXTsKICAgIGxldCBpZCwgY291bnQsIGk7CiAgICBsZW5ndGggLT0gMTsKICAgIHN3aXRjaCAoZm9ybWF0KSB7CiAgICAgIGNhc2UgMDoKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGlkID0gYnl0ZXNbcG9zKytdIDw8IDggfCBieXRlc1twb3MrK107CiAgICAgICAgICBjaGFyc2V0LnB1c2goY2lkID8gaWQgOiBzdHJpbmdzLmdldChpZCkpOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSAxOgogICAgICAgIHdoaWxlIChjaGFyc2V0Lmxlbmd0aCA8PSBsZW5ndGgpIHsKICAgICAgICAgIGlkID0gYnl0ZXNbcG9zKytdIDw8IDggfCBieXRlc1twb3MrK107CiAgICAgICAgICBjb3VudCA9IGJ5dGVzW3BvcysrXTsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPD0gY291bnQ7IGkrKykgewogICAgICAgICAgICBjaGFyc2V0LnB1c2goY2lkID8gaWQrKyA6IHN0cmluZ3MuZ2V0KGlkKyspKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMjoKICAgICAgICB3aGlsZSAoY2hhcnNldC5sZW5ndGggPD0gbGVuZ3RoKSB7CiAgICAgICAgICBpZCA9IGJ5dGVzW3BvcysrXSA8PCA4IHwgYnl0ZXNbcG9zKytdOwogICAgICAgICAgY291bnQgPSBieXRlc1twb3MrK10gPDwgOCB8IGJ5dGVzW3BvcysrXTsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPD0gY291bnQ7IGkrKykgewogICAgICAgICAgICBjaGFyc2V0LnB1c2goY2lkID8gaWQrKyA6IHN0cmluZ3MuZ2V0KGlkKyspKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJVbmtub3duIGNoYXJzZXQgZm9ybWF0Iik7CiAgICB9CiAgICBjb25zdCBlbmQgPSBwb3M7CiAgICBjb25zdCByYXcgPSBieXRlcy5zdWJhcnJheShzdGFydCwgZW5kKTsKICAgIHJldHVybiBuZXcgQ0ZGQ2hhcnNldChmYWxzZSwgZm9ybWF0LCBjaGFyc2V0LCByYXcpOwogIH0KICBwYXJzZUVuY29kaW5nKHBvcywgcHJvcGVydGllcywgc3RyaW5ncywgY2hhcnNldCkgewogICAgY29uc3QgZW5jb2RpbmcgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgY29uc3QgYnl0ZXMgPSB0aGlzLmJ5dGVzOwogICAgbGV0IHByZWRlZmluZWQgPSBmYWxzZTsKICAgIGxldCBmb3JtYXQsIGksIGlpOwogICAgbGV0IHJhdyA9IG51bGw7CiAgICBmdW5jdGlvbiByZWFkU3VwcGxlbWVudCgpIHsKICAgICAgY29uc3Qgc3VwcGxlbWVudHNDb3VudCA9IGJ5dGVzW3BvcysrXTsKICAgICAgZm9yIChpID0gMDsgaSA8IHN1cHBsZW1lbnRzQ291bnQ7IGkrKykgewogICAgICAgIGNvbnN0IGNvZGUgPSBieXRlc1twb3MrK107CiAgICAgICAgY29uc3Qgc2lkID0gKGJ5dGVzW3BvcysrXSA8PCA4KSArIChieXRlc1twb3MrK10gJiAweGZmKTsKICAgICAgICBlbmNvZGluZ1tjb2RlXSA9IGNoYXJzZXQuaW5kZXhPZihzdHJpbmdzLmdldChzaWQpKTsKICAgICAgfQogICAgfQogICAgaWYgKHBvcyA9PT0gMCB8fCBwb3MgPT09IDEpIHsKICAgICAgcHJlZGVmaW5lZCA9IHRydWU7CiAgICAgIGZvcm1hdCA9IHBvczsKICAgICAgY29uc3QgYmFzZUVuY29kaW5nID0gcG9zID8gX2VuY29kaW5ncy5FeHBlcnRFbmNvZGluZyA6IF9lbmNvZGluZ3MuU3RhbmRhcmRFbmNvZGluZzsKICAgICAgZm9yIChpID0gMCwgaWkgPSBjaGFyc2V0Lmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb25zdCBpbmRleCA9IGJhc2VFbmNvZGluZy5pbmRleE9mKGNoYXJzZXRbaV0pOwogICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgICAgIGVuY29kaW5nW2luZGV4XSA9IGk7CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBkYXRhU3RhcnQgPSBwb3M7CiAgICAgIGZvcm1hdCA9IGJ5dGVzW3BvcysrXTsKICAgICAgc3dpdGNoIChmb3JtYXQgJiAweDdmKSB7CiAgICAgICAgY2FzZSAwOgogICAgICAgICAgY29uc3QgZ2x5cGhzQ291bnQgPSBieXRlc1twb3MrK107CiAgICAgICAgICBmb3IgKGkgPSAxOyBpIDw9IGdseXBoc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgZW5jb2RpbmdbYnl0ZXNbcG9zKytdXSA9IGk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDE6CiAgICAgICAgICBjb25zdCByYW5nZXNDb3VudCA9IGJ5dGVzW3BvcysrXTsKICAgICAgICAgIGxldCBnaWQgPSAxOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8IHJhbmdlc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgY29uc3Qgc3RhcnQgPSBieXRlc1twb3MrK107CiAgICAgICAgICAgIGNvbnN0IGxlZnQgPSBieXRlc1twb3MrK107CiAgICAgICAgICAgIGZvciAobGV0IGogPSBzdGFydDsgaiA8PSBzdGFydCArIGxlZnQ7IGorKykgewogICAgICAgICAgICAgIGVuY29kaW5nW2pdID0gZ2lkKys7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYFVua25vd24gZW5jb2RpbmcgZm9ybWF0OiAke2Zvcm1hdH0gaW4gQ0ZGYCk7CiAgICAgIH0KICAgICAgY29uc3QgZGF0YUVuZCA9IHBvczsKICAgICAgaWYgKGZvcm1hdCAmIDB4ODApIHsKICAgICAgICBieXRlc1tkYXRhU3RhcnRdICY9IDB4N2Y7CiAgICAgICAgcmVhZFN1cHBsZW1lbnQoKTsKICAgICAgfQogICAgICByYXcgPSBieXRlcy5zdWJhcnJheShkYXRhU3RhcnQsIGRhdGFFbmQpOwogICAgfQogICAgZm9ybWF0ICY9IDB4N2Y7CiAgICByZXR1cm4gbmV3IENGRkVuY29kaW5nKHByZWRlZmluZWQsIGZvcm1hdCwgZW5jb2RpbmcsIHJhdyk7CiAgfQogIHBhcnNlRkRTZWxlY3QocG9zLCBsZW5ndGgpIHsKICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5ieXRlczsKICAgIGNvbnN0IGZvcm1hdCA9IGJ5dGVzW3BvcysrXTsKICAgIGNvbnN0IGZkU2VsZWN0ID0gW107CiAgICBsZXQgaTsKICAgIHN3aXRjaCAoZm9ybWF0KSB7CiAgICAgIGNhc2UgMDoKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgIGNvbnN0IGlkID0gYnl0ZXNbcG9zKytdOwogICAgICAgICAgZmRTZWxlY3QucHVzaChpZCk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDM6CiAgICAgICAgY29uc3QgcmFuZ2VzQ291bnQgPSBieXRlc1twb3MrK10gPDwgOCB8IGJ5dGVzW3BvcysrXTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcmFuZ2VzQ291bnQ7ICsraSkgewogICAgICAgICAgbGV0IGZpcnN0ID0gYnl0ZXNbcG9zKytdIDw8IDggfCBieXRlc1twb3MrK107CiAgICAgICAgICBpZiAoaSA9PT0gMCAmJiBmaXJzdCAhPT0gMCkgewogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoInBhcnNlRkRTZWxlY3Q6IFRoZSBmaXJzdCByYW5nZSBtdXN0IGhhdmUgYSBmaXJzdCBHSUQgb2YgMCIgKyAiIC0tIHRyeWluZyB0byByZWNvdmVyLiIpOwogICAgICAgICAgICBmaXJzdCA9IDA7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBmZEluZGV4ID0gYnl0ZXNbcG9zKytdOwogICAgICAgICAgY29uc3QgbmV4dCA9IGJ5dGVzW3Bvc10gPDwgOCB8IGJ5dGVzW3BvcyArIDFdOwogICAgICAgICAgZm9yIChsZXQgaiA9IGZpcnN0OyBqIDwgbmV4dDsgKytqKSB7CiAgICAgICAgICAgIGZkU2VsZWN0LnB1c2goZmRJbmRleCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHBvcyArPSAyOwogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgcGFyc2VGRFNlbGVjdDogVW5rbm93biBmb3JtYXQgIiR7Zm9ybWF0fSIuYCk7CiAgICB9CiAgICBpZiAoZmRTZWxlY3QubGVuZ3RoICE9PSBsZW5ndGgpIHsKICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJwYXJzZUZEU2VsZWN0OiBJbnZhbGlkIGZvbnQgZGF0YS4iKTsKICAgIH0KICAgIHJldHVybiBuZXcgQ0ZGRkRTZWxlY3QoZm9ybWF0LCBmZFNlbGVjdCk7CiAgfQp9CmV4cG9ydHMuQ0ZGUGFyc2VyID0gQ0ZGUGFyc2VyOwpjbGFzcyBDRkYgewogIGNvbnN0cnVjdG9yKCkgewogICAgdGhpcy5oZWFkZXIgPSBudWxsOwogICAgdGhpcy5uYW1lcyA9IFtdOwogICAgdGhpcy50b3BEaWN0ID0gbnVsbDsKICAgIHRoaXMuc3RyaW5ncyA9IG5ldyBDRkZTdHJpbmdzKCk7CiAgICB0aGlzLmdsb2JhbFN1YnJJbmRleCA9IG51bGw7CiAgICB0aGlzLmVuY29kaW5nID0gbnVsbDsKICAgIHRoaXMuY2hhcnNldCA9IG51bGw7CiAgICB0aGlzLmNoYXJTdHJpbmdzID0gbnVsbDsKICAgIHRoaXMuZmRBcnJheSA9IFtdOwogICAgdGhpcy5mZFNlbGVjdCA9IG51bGw7CiAgICB0aGlzLmlzQ0lERm9udCA9IGZhbHNlOwogIH0KICBkdXBsaWNhdGVGaXJzdEdseXBoKCkgewogICAgaWYgKHRoaXMuY2hhclN0cmluZ3MuY291bnQgPj0gNjU1MzUpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKCJOb3QgZW5vdWdoIHNwYWNlIGluIGNoYXJzdHJpbmdzIHRvIGR1cGxpY2F0ZSBmaXJzdCBnbHlwaC4iKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgZ2x5cGhaZXJvID0gdGhpcy5jaGFyU3RyaW5ncy5nZXQoMCk7CiAgICB0aGlzLmNoYXJTdHJpbmdzLmFkZChnbHlwaFplcm8pOwogICAgaWYgKHRoaXMuaXNDSURGb250KSB7CiAgICAgIHRoaXMuZmRTZWxlY3QuZmRTZWxlY3QucHVzaCh0aGlzLmZkU2VsZWN0LmZkU2VsZWN0WzBdKTsKICAgIH0KICB9CiAgaGFzR2x5cGhJZChpZCkgewogICAgaWYgKGlkIDwgMCB8fCBpZCA+PSB0aGlzLmNoYXJTdHJpbmdzLmNvdW50KSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGNvbnN0IGdseXBoID0gdGhpcy5jaGFyU3RyaW5ncy5nZXQoaWQpOwogICAgcmV0dXJuIGdseXBoLmxlbmd0aCA+IDA7CiAgfQp9CmV4cG9ydHMuQ0ZGID0gQ0ZGOwpjbGFzcyBDRkZIZWFkZXIgewogIGNvbnN0cnVjdG9yKG1ham9yLCBtaW5vciwgaGRyU2l6ZSwgb2ZmU2l6ZSkgewogICAgdGhpcy5tYWpvciA9IG1ham9yOwogICAgdGhpcy5taW5vciA9IG1pbm9yOwogICAgdGhpcy5oZHJTaXplID0gaGRyU2l6ZTsKICAgIHRoaXMub2ZmU2l6ZSA9IG9mZlNpemU7CiAgfQp9CmV4cG9ydHMuQ0ZGSGVhZGVyID0gQ0ZGSGVhZGVyOwpjbGFzcyBDRkZTdHJpbmdzIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMuc3RyaW5ncyA9IFtdOwogIH0KICBnZXQoaW5kZXgpIHsKICAgIGlmIChpbmRleCA+PSAwICYmIGluZGV4IDw9IE5VTV9TVEFOREFSRF9DRkZfU1RSSU5HUyAtIDEpIHsKICAgICAgcmV0dXJuIENGRlN0YW5kYXJkU3RyaW5nc1tpbmRleF07CiAgICB9CiAgICBpZiAoaW5kZXggLSBOVU1fU1RBTkRBUkRfQ0ZGX1NUUklOR1MgPD0gdGhpcy5zdHJpbmdzLmxlbmd0aCkgewogICAgICByZXR1cm4gdGhpcy5zdHJpbmdzW2luZGV4IC0gTlVNX1NUQU5EQVJEX0NGRl9TVFJJTkdTXTsKICAgIH0KICAgIHJldHVybiBDRkZTdGFuZGFyZFN0cmluZ3NbMF07CiAgfQogIGdldFNJRChzdHIpIHsKICAgIGxldCBpbmRleCA9IENGRlN0YW5kYXJkU3RyaW5ncy5pbmRleE9mKHN0cik7CiAgICBpZiAoaW5kZXggIT09IC0xKSB7CiAgICAgIHJldHVybiBpbmRleDsKICAgIH0KICAgIGluZGV4ID0gdGhpcy5zdHJpbmdzLmluZGV4T2Yoc3RyKTsKICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgcmV0dXJuIGluZGV4ICsgTlVNX1NUQU5EQVJEX0NGRl9TVFJJTkdTOwogICAgfQogICAgcmV0dXJuIC0xOwogIH0KICBhZGQodmFsdWUpIHsKICAgIHRoaXMuc3RyaW5ncy5wdXNoKHZhbHVlKTsKICB9CiAgZ2V0IGNvdW50KCkgewogICAgcmV0dXJuIHRoaXMuc3RyaW5ncy5sZW5ndGg7CiAgfQp9CmV4cG9ydHMuQ0ZGU3RyaW5ncyA9IENGRlN0cmluZ3M7CmNsYXNzIENGRkluZGV4IHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMub2JqZWN0cyA9IFtdOwogICAgdGhpcy5sZW5ndGggPSAwOwogIH0KICBhZGQoZGF0YSkgewogICAgdGhpcy5sZW5ndGggKz0gZGF0YS5sZW5ndGg7CiAgICB0aGlzLm9iamVjdHMucHVzaChkYXRhKTsKICB9CiAgc2V0KGluZGV4LCBkYXRhKSB7CiAgICB0aGlzLmxlbmd0aCArPSBkYXRhLmxlbmd0aCAtIHRoaXMub2JqZWN0c1tpbmRleF0ubGVuZ3RoOwogICAgdGhpcy5vYmplY3RzW2luZGV4XSA9IGRhdGE7CiAgfQogIGdldChpbmRleCkgewogICAgcmV0dXJuIHRoaXMub2JqZWN0c1tpbmRleF07CiAgfQogIGdldCBjb3VudCgpIHsKICAgIHJldHVybiB0aGlzLm9iamVjdHMubGVuZ3RoOwogIH0KfQpleHBvcnRzLkNGRkluZGV4ID0gQ0ZGSW5kZXg7CmNsYXNzIENGRkRpY3QgewogIGNvbnN0cnVjdG9yKHRhYmxlcywgc3RyaW5ncykgewogICAgdGhpcy5rZXlUb05hbWVNYXAgPSB0YWJsZXMua2V5VG9OYW1lTWFwOwogICAgdGhpcy5uYW1lVG9LZXlNYXAgPSB0YWJsZXMubmFtZVRvS2V5TWFwOwogICAgdGhpcy5kZWZhdWx0cyA9IHRhYmxlcy5kZWZhdWx0czsKICAgIHRoaXMudHlwZXMgPSB0YWJsZXMudHlwZXM7CiAgICB0aGlzLm9wY29kZXMgPSB0YWJsZXMub3Bjb2RlczsKICAgIHRoaXMub3JkZXIgPSB0YWJsZXMub3JkZXI7CiAgICB0aGlzLnN0cmluZ3MgPSBzdHJpbmdzOwogICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIH0KICBzZXRCeUtleShrZXksIHZhbHVlKSB7CiAgICBpZiAoIShrZXkgaW4gdGhpcy5rZXlUb05hbWVNYXApKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmICh2YWx1ZS5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBmb3IgKGNvbnN0IHZhbCBvZiB2YWx1ZSkgewogICAgICBpZiAoaXNOYU4odmFsKSkgewogICAgICAgICgwLCBfdXRpbC53YXJuKShgSW52YWxpZCBDRkZEaWN0IHZhbHVlOiAiJHt2YWx1ZX0iIGZvciBrZXkgIiR7a2V5fSIuYCk7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHR5cGUgPSB0aGlzLnR5cGVzW2tleV07CiAgICBpZiAodHlwZSA9PT0gIm51bSIgfHwgdHlwZSA9PT0gInNpZCIgfHwgdHlwZSA9PT0gIm9mZnNldCIpIHsKICAgICAgdmFsdWUgPSB2YWx1ZVswXTsKICAgIH0KICAgIHRoaXMudmFsdWVzW2tleV0gPSB2YWx1ZTsKICAgIHJldHVybiB0cnVlOwogIH0KICBzZXRCeU5hbWUobmFtZSwgdmFsdWUpIHsKICAgIGlmICghKG5hbWUgaW4gdGhpcy5uYW1lVG9LZXlNYXApKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgSW52YWxpZCBkaWN0aW9uYXJ5IG5hbWUgIiR7bmFtZX0iYCk7CiAgICB9CiAgICB0aGlzLnZhbHVlc1t0aGlzLm5hbWVUb0tleU1hcFtuYW1lXV0gPSB2YWx1ZTsKICB9CiAgaGFzTmFtZShuYW1lKSB7CiAgICByZXR1cm4gdGhpcy5uYW1lVG9LZXlNYXBbbmFtZV0gaW4gdGhpcy52YWx1ZXM7CiAgfQogIGdldEJ5TmFtZShuYW1lKSB7CiAgICBpZiAoIShuYW1lIGluIHRoaXMubmFtZVRvS2V5TWFwKSkgewogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYEludmFsaWQgZGljdGlvbmFyeSBuYW1lICR7bmFtZX0iYCk7CiAgICB9CiAgICBjb25zdCBrZXkgPSB0aGlzLm5hbWVUb0tleU1hcFtuYW1lXTsKICAgIGlmICghKGtleSBpbiB0aGlzLnZhbHVlcykpIHsKICAgICAgcmV0dXJuIHRoaXMuZGVmYXVsdHNba2V5XTsKICAgIH0KICAgIHJldHVybiB0aGlzLnZhbHVlc1trZXldOwogIH0KICByZW1vdmVCeU5hbWUobmFtZSkgewogICAgZGVsZXRlIHRoaXMudmFsdWVzW3RoaXMubmFtZVRvS2V5TWFwW25hbWVdXTsKICB9CiAgc3RhdGljIGNyZWF0ZVRhYmxlcyhsYXlvdXQpIHsKICAgIGNvbnN0IHRhYmxlcyA9IHsKICAgICAga2V5VG9OYW1lTWFwOiB7fSwKICAgICAgbmFtZVRvS2V5TWFwOiB7fSwKICAgICAgZGVmYXVsdHM6IHt9LAogICAgICB0eXBlczoge30sCiAgICAgIG9wY29kZXM6IHt9LAogICAgICBvcmRlcjogW10KICAgIH07CiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGxheW91dCkgewogICAgICBjb25zdCBrZXkgPSBBcnJheS5pc0FycmF5KGVudHJ5WzBdKSA/IChlbnRyeVswXVswXSA8PCA4KSArIGVudHJ5WzBdWzFdIDogZW50cnlbMF07CiAgICAgIHRhYmxlcy5rZXlUb05hbWVNYXBba2V5XSA9IGVudHJ5WzFdOwogICAgICB0YWJsZXMubmFtZVRvS2V5TWFwW2VudHJ5WzFdXSA9IGtleTsKICAgICAgdGFibGVzLnR5cGVzW2tleV0gPSBlbnRyeVsyXTsKICAgICAgdGFibGVzLmRlZmF1bHRzW2tleV0gPSBlbnRyeVszXTsKICAgICAgdGFibGVzLm9wY29kZXNba2V5XSA9IEFycmF5LmlzQXJyYXkoZW50cnlbMF0pID8gZW50cnlbMF0gOiBbZW50cnlbMF1dOwogICAgICB0YWJsZXMub3JkZXIucHVzaChrZXkpOwogICAgfQogICAgcmV0dXJuIHRhYmxlczsKICB9Cn0KY29uc3QgQ0ZGVG9wRGljdExheW91dCA9IFtbWzEyLCAzMF0sICJST1MiLCBbInNpZCIsICJzaWQiLCAibnVtIl0sIG51bGxdLCBbWzEyLCAyMF0sICJTeW50aGV0aWNCYXNlIiwgIm51bSIsIG51bGxdLCBbMCwgInZlcnNpb24iLCAic2lkIiwgbnVsbF0sIFsxLCAiTm90aWNlIiwgInNpZCIsIG51bGxdLCBbWzEyLCAwXSwgIkNvcHlyaWdodCIsICJzaWQiLCBudWxsXSwgWzIsICJGdWxsTmFtZSIsICJzaWQiLCBudWxsXSwgWzMsICJGYW1pbHlOYW1lIiwgInNpZCIsIG51bGxdLCBbNCwgIldlaWdodCIsICJzaWQiLCBudWxsXSwgW1sxMiwgMV0sICJpc0ZpeGVkUGl0Y2giLCAibnVtIiwgMF0sIFtbMTIsIDJdLCAiSXRhbGljQW5nbGUiLCAibnVtIiwgMF0sIFtbMTIsIDNdLCAiVW5kZXJsaW5lUG9zaXRpb24iLCAibnVtIiwgLTEwMF0sIFtbMTIsIDRdLCAiVW5kZXJsaW5lVGhpY2tuZXNzIiwgIm51bSIsIDUwXSwgW1sxMiwgNV0sICJQYWludFR5cGUiLCAibnVtIiwgMF0sIFtbMTIsIDZdLCAiQ2hhcnN0cmluZ1R5cGUiLCAibnVtIiwgMl0sIFtbMTIsIDddLCAiRm9udE1hdHJpeCIsIFsibnVtIiwgIm51bSIsICJudW0iLCAibnVtIiwgIm51bSIsICJudW0iXSwgWzAuMDAxLCAwLCAwLCAwLjAwMSwgMCwgMF1dLCBbMTMsICJVbmlxdWVJRCIsICJudW0iLCBudWxsXSwgWzUsICJGb250QkJveCIsIFsibnVtIiwgIm51bSIsICJudW0iLCAibnVtIl0sIFswLCAwLCAwLCAwXV0sIFtbMTIsIDhdLCAiU3Ryb2tlV2lkdGgiLCAibnVtIiwgMF0sIFsxNCwgIlhVSUQiLCAiYXJyYXkiLCBudWxsXSwgWzE1LCAiY2hhcnNldCIsICJvZmZzZXQiLCAwXSwgWzE2LCAiRW5jb2RpbmciLCAib2Zmc2V0IiwgMF0sIFsxNywgIkNoYXJTdHJpbmdzIiwgIm9mZnNldCIsIDBdLCBbMTgsICJQcml2YXRlIiwgWyJvZmZzZXQiLCAib2Zmc2V0Il0sIG51bGxdLCBbWzEyLCAyMV0sICJQb3N0U2NyaXB0IiwgInNpZCIsIG51bGxdLCBbWzEyLCAyMl0sICJCYXNlRm9udE5hbWUiLCAic2lkIiwgbnVsbF0sIFtbMTIsIDIzXSwgIkJhc2VGb250QmxlbmQiLCAiZGVsdGEiLCBudWxsXSwgW1sxMiwgMzFdLCAiQ0lERm9udFZlcnNpb24iLCAibnVtIiwgMF0sIFtbMTIsIDMyXSwgIkNJREZvbnRSZXZpc2lvbiIsICJudW0iLCAwXSwgW1sxMiwgMzNdLCAiQ0lERm9udFR5cGUiLCAibnVtIiwgMF0sIFtbMTIsIDM0XSwgIkNJRENvdW50IiwgIm51bSIsIDg3MjBdLCBbWzEyLCAzNV0sICJVSURCYXNlIiwgIm51bSIsIG51bGxdLCBbWzEyLCAzN10sICJGRFNlbGVjdCIsICJvZmZzZXQiLCBudWxsXSwgW1sxMiwgMzZdLCAiRkRBcnJheSIsICJvZmZzZXQiLCBudWxsXSwgW1sxMiwgMzhdLCAiRm9udE5hbWUiLCAic2lkIiwgbnVsbF1dOwpjbGFzcyBDRkZUb3BEaWN0IGV4dGVuZHMgQ0ZGRGljdCB7CiAgc3RhdGljIGdldCB0YWJsZXMoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInRhYmxlcyIsIHRoaXMuY3JlYXRlVGFibGVzKENGRlRvcERpY3RMYXlvdXQpKTsKICB9CiAgY29uc3RydWN0b3Ioc3RyaW5ncykgewogICAgc3VwZXIoQ0ZGVG9wRGljdC50YWJsZXMsIHN0cmluZ3MpOwogICAgdGhpcy5wcml2YXRlRGljdCA9IG51bGw7CiAgfQp9CmV4cG9ydHMuQ0ZGVG9wRGljdCA9IENGRlRvcERpY3Q7CmNvbnN0IENGRlByaXZhdGVEaWN0TGF5b3V0ID0gW1s2LCAiQmx1ZVZhbHVlcyIsICJkZWx0YSIsIG51bGxdLCBbNywgIk90aGVyQmx1ZXMiLCAiZGVsdGEiLCBudWxsXSwgWzgsICJGYW1pbHlCbHVlcyIsICJkZWx0YSIsIG51bGxdLCBbOSwgIkZhbWlseU90aGVyQmx1ZXMiLCAiZGVsdGEiLCBudWxsXSwgW1sxMiwgOV0sICJCbHVlU2NhbGUiLCAibnVtIiwgMC4wMzk2MjVdLCBbWzEyLCAxMF0sICJCbHVlU2hpZnQiLCAibnVtIiwgN10sIFtbMTIsIDExXSwgIkJsdWVGdXp6IiwgIm51bSIsIDFdLCBbMTAsICJTdGRIVyIsICJudW0iLCBudWxsXSwgWzExLCAiU3RkVlciLCAibnVtIiwgbnVsbF0sIFtbMTIsIDEyXSwgIlN0ZW1TbmFwSCIsICJkZWx0YSIsIG51bGxdLCBbWzEyLCAxM10sICJTdGVtU25hcFYiLCAiZGVsdGEiLCBudWxsXSwgW1sxMiwgMTRdLCAiRm9yY2VCb2xkIiwgIm51bSIsIDBdLCBbWzEyLCAxN10sICJMYW5ndWFnZUdyb3VwIiwgIm51bSIsIDBdLCBbWzEyLCAxOF0sICJFeHBhbnNpb25GYWN0b3IiLCAibnVtIiwgMC4wNl0sIFtbMTIsIDE5XSwgImluaXRpYWxSYW5kb21TZWVkIiwgIm51bSIsIDBdLCBbMjAsICJkZWZhdWx0V2lkdGhYIiwgIm51bSIsIDBdLCBbMjEsICJub21pbmFsV2lkdGhYIiwgIm51bSIsIDBdLCBbMTksICJTdWJycyIsICJvZmZzZXQiLCBudWxsXV07CmNsYXNzIENGRlByaXZhdGVEaWN0IGV4dGVuZHMgQ0ZGRGljdCB7CiAgc3RhdGljIGdldCB0YWJsZXMoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInRhYmxlcyIsIHRoaXMuY3JlYXRlVGFibGVzKENGRlByaXZhdGVEaWN0TGF5b3V0KSk7CiAgfQogIGNvbnN0cnVjdG9yKHN0cmluZ3MpIHsKICAgIHN1cGVyKENGRlByaXZhdGVEaWN0LnRhYmxlcywgc3RyaW5ncyk7CiAgICB0aGlzLnN1YnJzSW5kZXggPSBudWxsOwogIH0KfQpleHBvcnRzLkNGRlByaXZhdGVEaWN0ID0gQ0ZGUHJpdmF0ZURpY3Q7CmNvbnN0IENGRkNoYXJzZXRQcmVkZWZpbmVkVHlwZXMgPSB7CiAgSVNPX0FET0JFOiAwLAogIEVYUEVSVDogMSwKICBFWFBFUlRfU1VCU0VUOiAyCn07CmNsYXNzIENGRkNoYXJzZXQgewogIGNvbnN0cnVjdG9yKHByZWRlZmluZWQsIGZvcm1hdCwgY2hhcnNldCwgcmF3KSB7CiAgICB0aGlzLnByZWRlZmluZWQgPSBwcmVkZWZpbmVkOwogICAgdGhpcy5mb3JtYXQgPSBmb3JtYXQ7CiAgICB0aGlzLmNoYXJzZXQgPSBjaGFyc2V0OwogICAgdGhpcy5yYXcgPSByYXc7CiAgfQp9CmV4cG9ydHMuQ0ZGQ2hhcnNldCA9IENGRkNoYXJzZXQ7CmNsYXNzIENGRkVuY29kaW5nIHsKICBjb25zdHJ1Y3RvcihwcmVkZWZpbmVkLCBmb3JtYXQsIGVuY29kaW5nLCByYXcpIHsKICAgIHRoaXMucHJlZGVmaW5lZCA9IHByZWRlZmluZWQ7CiAgICB0aGlzLmZvcm1hdCA9IGZvcm1hdDsKICAgIHRoaXMuZW5jb2RpbmcgPSBlbmNvZGluZzsKICAgIHRoaXMucmF3ID0gcmF3OwogIH0KfQpjbGFzcyBDRkZGRFNlbGVjdCB7CiAgY29uc3RydWN0b3IoZm9ybWF0LCBmZFNlbGVjdCkgewogICAgdGhpcy5mb3JtYXQgPSBmb3JtYXQ7CiAgICB0aGlzLmZkU2VsZWN0ID0gZmRTZWxlY3Q7CiAgfQogIGdldEZESW5kZXgoZ2x5cGhJbmRleCkgewogICAgaWYgKGdseXBoSW5kZXggPCAwIHx8IGdseXBoSW5kZXggPj0gdGhpcy5mZFNlbGVjdC5sZW5ndGgpIHsKICAgICAgcmV0dXJuIC0xOwogICAgfQogICAgcmV0dXJuIHRoaXMuZmRTZWxlY3RbZ2x5cGhJbmRleF07CiAgfQp9CmV4cG9ydHMuQ0ZGRkRTZWxlY3QgPSBDRkZGRFNlbGVjdDsKY2xhc3MgQ0ZGT2Zmc2V0VHJhY2tlciB7CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLm9mZnNldHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIH0KICBpc1RyYWNraW5nKGtleSkgewogICAgcmV0dXJuIGtleSBpbiB0aGlzLm9mZnNldHM7CiAgfQogIHRyYWNrKGtleSwgbG9jYXRpb24pIHsKICAgIGlmIChrZXkgaW4gdGhpcy5vZmZzZXRzKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgQWxyZWFkeSB0cmFja2luZyBsb2NhdGlvbiBvZiAke2tleX1gKTsKICAgIH0KICAgIHRoaXMub2Zmc2V0c1trZXldID0gbG9jYXRpb247CiAgfQogIG9mZnNldCh2YWx1ZSkgewogICAgZm9yIChjb25zdCBrZXkgaW4gdGhpcy5vZmZzZXRzKSB7CiAgICAgIHRoaXMub2Zmc2V0c1trZXldICs9IHZhbHVlOwogICAgfQogIH0KICBzZXRFbnRyeUxvY2F0aW9uKGtleSwgdmFsdWVzLCBvdXRwdXQpIHsKICAgIGlmICghKGtleSBpbiB0aGlzLm9mZnNldHMpKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgTm90IHRyYWNraW5nIGxvY2F0aW9uIG9mICR7a2V5fWApOwogICAgfQogICAgY29uc3QgZGF0YSA9IG91dHB1dC5kYXRhOwogICAgY29uc3QgZGF0YU9mZnNldCA9IHRoaXMub2Zmc2V0c1trZXldOwogICAgY29uc3Qgc2l6ZSA9IDU7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB2YWx1ZXMubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICBjb25zdCBvZmZzZXQwID0gaSAqIHNpemUgKyBkYXRhT2Zmc2V0OwogICAgICBjb25zdCBvZmZzZXQxID0gb2Zmc2V0MCArIDE7CiAgICAgIGNvbnN0IG9mZnNldDIgPSBvZmZzZXQwICsgMjsKICAgICAgY29uc3Qgb2Zmc2V0MyA9IG9mZnNldDAgKyAzOwogICAgICBjb25zdCBvZmZzZXQ0ID0gb2Zmc2V0MCArIDQ7CiAgICAgIGlmIChkYXRhW29mZnNldDBdICE9PSAweDFkIHx8IGRhdGFbb2Zmc2V0MV0gIT09IDAgfHwgZGF0YVtvZmZzZXQyXSAhPT0gMCB8fCBkYXRhW29mZnNldDNdICE9PSAwIHx8IGRhdGFbb2Zmc2V0NF0gIT09IDApIHsKICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIndyaXRpbmcgdG8gYW4gb2Zmc2V0IHRoYXQgaXMgbm90IGVtcHR5Iik7CiAgICAgIH0KICAgICAgY29uc3QgdmFsdWUgPSB2YWx1ZXNbaV07CiAgICAgIGRhdGFbb2Zmc2V0MF0gPSAweDFkOwogICAgICBkYXRhW29mZnNldDFdID0gdmFsdWUgPj4gMjQgJiAweGZmOwogICAgICBkYXRhW29mZnNldDJdID0gdmFsdWUgPj4gMTYgJiAweGZmOwogICAgICBkYXRhW29mZnNldDNdID0gdmFsdWUgPj4gOCAmIDB4ZmY7CiAgICAgIGRhdGFbb2Zmc2V0NF0gPSB2YWx1ZSAmIDB4ZmY7CiAgICB9CiAgfQp9CmNsYXNzIENGRkNvbXBpbGVyIHsKICBjb25zdHJ1Y3RvcihjZmYpIHsKICAgIHRoaXMuY2ZmID0gY2ZmOwogIH0KICBjb21waWxlKCkgewogICAgY29uc3QgY2ZmID0gdGhpcy5jZmY7CiAgICBjb25zdCBvdXRwdXQgPSB7CiAgICAgIGRhdGE6IFtdLAogICAgICBsZW5ndGg6IDAsCiAgICAgIGFkZChkYXRhKSB7CiAgICAgICAgdGhpcy5kYXRhID0gdGhpcy5kYXRhLmNvbmNhdChkYXRhKTsKICAgICAgICB0aGlzLmxlbmd0aCA9IHRoaXMuZGF0YS5sZW5ndGg7CiAgICAgIH0KICAgIH07CiAgICBjb25zdCBoZWFkZXIgPSB0aGlzLmNvbXBpbGVIZWFkZXIoY2ZmLmhlYWRlcik7CiAgICBvdXRwdXQuYWRkKGhlYWRlcik7CiAgICBjb25zdCBuYW1lSW5kZXggPSB0aGlzLmNvbXBpbGVOYW1lSW5kZXgoY2ZmLm5hbWVzKTsKICAgIG91dHB1dC5hZGQobmFtZUluZGV4KTsKICAgIGlmIChjZmYuaXNDSURGb250KSB7CiAgICAgIGlmIChjZmYudG9wRGljdC5oYXNOYW1lKCJGb250TWF0cml4IikpIHsKICAgICAgICBjb25zdCBiYXNlID0gY2ZmLnRvcERpY3QuZ2V0QnlOYW1lKCJGb250TWF0cml4Iik7CiAgICAgICAgY2ZmLnRvcERpY3QucmVtb3ZlQnlOYW1lKCJGb250TWF0cml4Iik7CiAgICAgICAgZm9yIChjb25zdCBzdWJEaWN0IG9mIGNmZi5mZEFycmF5KSB7CiAgICAgICAgICBsZXQgbWF0cml4ID0gYmFzZS5zbGljZSgwKTsKICAgICAgICAgIGlmIChzdWJEaWN0Lmhhc05hbWUoIkZvbnRNYXRyaXgiKSkgewogICAgICAgICAgICBtYXRyaXggPSBfdXRpbC5VdGlsLnRyYW5zZm9ybShtYXRyaXgsIHN1YkRpY3QuZ2V0QnlOYW1lKCJGb250TWF0cml4IikpOwogICAgICAgICAgfQogICAgICAgICAgc3ViRGljdC5zZXRCeU5hbWUoIkZvbnRNYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgY29uc3QgeHVpZCA9IGNmZi50b3BEaWN0LmdldEJ5TmFtZSgiWFVJRCIpOwogICAgaWYgKHh1aWQgJiYgeHVpZC5sZW5ndGggPiAxNikgewogICAgICBjZmYudG9wRGljdC5yZW1vdmVCeU5hbWUoIlhVSUQiKTsKICAgIH0KICAgIGNmZi50b3BEaWN0LnNldEJ5TmFtZSgiY2hhcnNldCIsIDApOwogICAgbGV0IGNvbXBpbGVkID0gdGhpcy5jb21waWxlVG9wRGljdHMoW2NmZi50b3BEaWN0XSwgb3V0cHV0Lmxlbmd0aCwgY2ZmLmlzQ0lERm9udCk7CiAgICBvdXRwdXQuYWRkKGNvbXBpbGVkLm91dHB1dCk7CiAgICBjb25zdCB0b3BEaWN0VHJhY2tlciA9IGNvbXBpbGVkLnRyYWNrZXJzWzBdOwogICAgY29uc3Qgc3RyaW5nSW5kZXggPSB0aGlzLmNvbXBpbGVTdHJpbmdJbmRleChjZmYuc3RyaW5ncy5zdHJpbmdzKTsKICAgIG91dHB1dC5hZGQoc3RyaW5nSW5kZXgpOwogICAgY29uc3QgZ2xvYmFsU3VickluZGV4ID0gdGhpcy5jb21waWxlSW5kZXgoY2ZmLmdsb2JhbFN1YnJJbmRleCk7CiAgICBvdXRwdXQuYWRkKGdsb2JhbFN1YnJJbmRleCk7CiAgICBpZiAoY2ZmLmVuY29kaW5nICYmIGNmZi50b3BEaWN0Lmhhc05hbWUoIkVuY29kaW5nIikpIHsKICAgICAgaWYgKGNmZi5lbmNvZGluZy5wcmVkZWZpbmVkKSB7CiAgICAgICAgdG9wRGljdFRyYWNrZXIuc2V0RW50cnlMb2NhdGlvbigiRW5jb2RpbmciLCBbY2ZmLmVuY29kaW5nLmZvcm1hdF0sIG91dHB1dCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgZW5jb2RpbmcgPSB0aGlzLmNvbXBpbGVFbmNvZGluZyhjZmYuZW5jb2RpbmcpOwogICAgICAgIHRvcERpY3RUcmFja2VyLnNldEVudHJ5TG9jYXRpb24oIkVuY29kaW5nIiwgW291dHB1dC5sZW5ndGhdLCBvdXRwdXQpOwogICAgICAgIG91dHB1dC5hZGQoZW5jb2RpbmcpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBjaGFyc2V0ID0gdGhpcy5jb21waWxlQ2hhcnNldChjZmYuY2hhcnNldCwgY2ZmLmNoYXJTdHJpbmdzLmNvdW50LCBjZmYuc3RyaW5ncywgY2ZmLmlzQ0lERm9udCk7CiAgICB0b3BEaWN0VHJhY2tlci5zZXRFbnRyeUxvY2F0aW9uKCJjaGFyc2V0IiwgW291dHB1dC5sZW5ndGhdLCBvdXRwdXQpOwogICAgb3V0cHV0LmFkZChjaGFyc2V0KTsKICAgIGNvbnN0IGNoYXJTdHJpbmdzID0gdGhpcy5jb21waWxlQ2hhclN0cmluZ3MoY2ZmLmNoYXJTdHJpbmdzKTsKICAgIHRvcERpY3RUcmFja2VyLnNldEVudHJ5TG9jYXRpb24oIkNoYXJTdHJpbmdzIiwgW291dHB1dC5sZW5ndGhdLCBvdXRwdXQpOwogICAgb3V0cHV0LmFkZChjaGFyU3RyaW5ncyk7CiAgICBpZiAoY2ZmLmlzQ0lERm9udCkgewogICAgICB0b3BEaWN0VHJhY2tlci5zZXRFbnRyeUxvY2F0aW9uKCJGRFNlbGVjdCIsIFtvdXRwdXQubGVuZ3RoXSwgb3V0cHV0KTsKICAgICAgY29uc3QgZmRTZWxlY3QgPSB0aGlzLmNvbXBpbGVGRFNlbGVjdChjZmYuZmRTZWxlY3QpOwogICAgICBvdXRwdXQuYWRkKGZkU2VsZWN0KTsKICAgICAgY29tcGlsZWQgPSB0aGlzLmNvbXBpbGVUb3BEaWN0cyhjZmYuZmRBcnJheSwgb3V0cHV0Lmxlbmd0aCwgdHJ1ZSk7CiAgICAgIHRvcERpY3RUcmFja2VyLnNldEVudHJ5TG9jYXRpb24oIkZEQXJyYXkiLCBbb3V0cHV0Lmxlbmd0aF0sIG91dHB1dCk7CiAgICAgIG91dHB1dC5hZGQoY29tcGlsZWQub3V0cHV0KTsKICAgICAgY29uc3QgZm9udERpY3RUcmFja2VycyA9IGNvbXBpbGVkLnRyYWNrZXJzOwogICAgICB0aGlzLmNvbXBpbGVQcml2YXRlRGljdHMoY2ZmLmZkQXJyYXksIGZvbnREaWN0VHJhY2tlcnMsIG91dHB1dCk7CiAgICB9CiAgICB0aGlzLmNvbXBpbGVQcml2YXRlRGljdHMoW2NmZi50b3BEaWN0XSwgW3RvcERpY3RUcmFja2VyXSwgb3V0cHV0KTsKICAgIG91dHB1dC5hZGQoWzBdKTsKICAgIHJldHVybiBvdXRwdXQuZGF0YTsKICB9CiAgZW5jb2RlTnVtYmVyKHZhbHVlKSB7CiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcih2YWx1ZSkpIHsKICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlSW50ZWdlcih2YWx1ZSk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5lbmNvZGVGbG9hdCh2YWx1ZSk7CiAgfQogIHN0YXRpYyBnZXQgRW5jb2RlRmxvYXRSZWdFeHAoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIkVuY29kZUZsb2F0UmVnRXhwIiwgL1wuKFxkKj8pKD86OXs1LDIwfXwwezUsMjB9KVxkezAsMn0oPzplKC4rKXwkKS8pOwogIH0KICBlbmNvZGVGbG9hdChudW0pIHsKICAgIGxldCB2YWx1ZSA9IG51bS50b1N0cmluZygpOwogICAgY29uc3QgbSA9IENGRkNvbXBpbGVyLkVuY29kZUZsb2F0UmVnRXhwLmV4ZWModmFsdWUpOwogICAgaWYgKG0pIHsKICAgICAgY29uc3QgZXBzaWxvbiA9IHBhcnNlRmxvYXQoIjFlIiArICgobVsyXSA/ICttWzJdIDogMCkgKyBtWzFdLmxlbmd0aCkpOwogICAgICB2YWx1ZSA9IChNYXRoLnJvdW5kKG51bSAqIGVwc2lsb24pIC8gZXBzaWxvbikudG9TdHJpbmcoKTsKICAgIH0KICAgIGxldCBuaWJibGVzID0gIiI7CiAgICBsZXQgaSwgaWk7CiAgICBmb3IgKGkgPSAwLCBpaSA9IHZhbHVlLmxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgICAgY29uc3QgYSA9IHZhbHVlW2ldOwogICAgICBpZiAoYSA9PT0gImUiKSB7CiAgICAgICAgbmliYmxlcyArPSB2YWx1ZVsrK2ldID09PSAiLSIgPyAiYyIgOiAiYiI7CiAgICAgIH0gZWxzZSBpZiAoYSA9PT0gIi4iKSB7CiAgICAgICAgbmliYmxlcyArPSAiYSI7CiAgICAgIH0gZWxzZSBpZiAoYSA9PT0gIi0iKSB7CiAgICAgICAgbmliYmxlcyArPSAiZSI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmliYmxlcyArPSBhOwogICAgICB9CiAgICB9CiAgICBuaWJibGVzICs9IG5pYmJsZXMubGVuZ3RoICYgMSA/ICJmIiA6ICJmZiI7CiAgICBjb25zdCBvdXQgPSBbMzBdOwogICAgZm9yIChpID0gMCwgaWkgPSBuaWJibGVzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgb3V0LnB1c2gocGFyc2VJbnQobmliYmxlcy5zdWJzdHJpbmcoaSwgaSArIDIpLCAxNikpOwogICAgfQogICAgcmV0dXJuIG91dDsKICB9CiAgZW5jb2RlSW50ZWdlcih2YWx1ZSkgewogICAgbGV0IGNvZGU7CiAgICBpZiAodmFsdWUgPj0gLTEwNyAmJiB2YWx1ZSA8PSAxMDcpIHsKICAgICAgY29kZSA9IFt2YWx1ZSArIDEzOV07CiAgICB9IGVsc2UgaWYgKHZhbHVlID49IDEwOCAmJiB2YWx1ZSA8PSAxMTMxKSB7CiAgICAgIHZhbHVlIC09IDEwODsKICAgICAgY29kZSA9IFsodmFsdWUgPj4gOCkgKyAyNDcsIHZhbHVlICYgMHhmZl07CiAgICB9IGVsc2UgaWYgKHZhbHVlID49IC0xMTMxICYmIHZhbHVlIDw9IC0xMDgpIHsKICAgICAgdmFsdWUgPSAtdmFsdWUgLSAxMDg7CiAgICAgIGNvZGUgPSBbKHZhbHVlID4+IDgpICsgMjUxLCB2YWx1ZSAmIDB4ZmZdOwogICAgfSBlbHNlIGlmICh2YWx1ZSA+PSAtMzI3NjggJiYgdmFsdWUgPD0gMzI3NjcpIHsKICAgICAgY29kZSA9IFsweDFjLCB2YWx1ZSA+PiA4ICYgMHhmZiwgdmFsdWUgJiAweGZmXTsKICAgIH0gZWxzZSB7CiAgICAgIGNvZGUgPSBbMHgxZCwgdmFsdWUgPj4gMjQgJiAweGZmLCB2YWx1ZSA+PiAxNiAmIDB4ZmYsIHZhbHVlID4+IDggJiAweGZmLCB2YWx1ZSAmIDB4ZmZdOwogICAgfQogICAgcmV0dXJuIGNvZGU7CiAgfQogIGNvbXBpbGVIZWFkZXIoaGVhZGVyKSB7CiAgICByZXR1cm4gW2hlYWRlci5tYWpvciwgaGVhZGVyLm1pbm9yLCA0LCBoZWFkZXIub2ZmU2l6ZV07CiAgfQogIGNvbXBpbGVOYW1lSW5kZXgobmFtZXMpIHsKICAgIGNvbnN0IG5hbWVJbmRleCA9IG5ldyBDRkZJbmRleCgpOwogICAgZm9yIChjb25zdCBuYW1lIG9mIG5hbWVzKSB7CiAgICAgIGNvbnN0IGxlbmd0aCA9IE1hdGgubWluKG5hbWUubGVuZ3RoLCAxMjcpOwogICAgICBsZXQgc2FuaXRpemVkTmFtZSA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxlbmd0aDsgaisrKSB7CiAgICAgICAgbGV0IGNoYXIgPSBuYW1lW2pdOwogICAgICAgIGlmIChjaGFyIDwgIiEiIHx8IGNoYXIgPiAifiIgfHwgY2hhciA9PT0gIlsiIHx8IGNoYXIgPT09ICJdIiB8fCBjaGFyID09PSAiKCIgfHwgY2hhciA9PT0gIikiIHx8IGNoYXIgPT09ICJ7IiB8fCBjaGFyID09PSAifSIgfHwgY2hhciA9PT0gIjwiIHx8IGNoYXIgPT09ICI+IiB8fCBjaGFyID09PSAiLyIgfHwgY2hhciA9PT0gIiUiKSB7CiAgICAgICAgICBjaGFyID0gIl8iOwogICAgICAgIH0KICAgICAgICBzYW5pdGl6ZWROYW1lW2pdID0gY2hhcjsKICAgICAgfQogICAgICBzYW5pdGl6ZWROYW1lID0gc2FuaXRpemVkTmFtZS5qb2luKCIiKTsKICAgICAgaWYgKHNhbml0aXplZE5hbWUgPT09ICIiKSB7CiAgICAgICAgc2FuaXRpemVkTmFtZSA9ICJCYWRfRm9udF9OYW1lIjsKICAgICAgfQogICAgICBuYW1lSW5kZXguYWRkKCgwLCBfdXRpbC5zdHJpbmdUb0J5dGVzKShzYW5pdGl6ZWROYW1lKSk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5jb21waWxlSW5kZXgobmFtZUluZGV4KTsKICB9CiAgY29tcGlsZVRvcERpY3RzKGRpY3RzLCBsZW5ndGgsIHJlbW92ZUNpZEtleXMpIHsKICAgIGNvbnN0IGZvbnREaWN0VHJhY2tlcnMgPSBbXTsKICAgIGxldCBmZEFycmF5SW5kZXggPSBuZXcgQ0ZGSW5kZXgoKTsKICAgIGZvciAoY29uc3QgZm9udERpY3Qgb2YgZGljdHMpIHsKICAgICAgaWYgKHJlbW92ZUNpZEtleXMpIHsKICAgICAgICBmb250RGljdC5yZW1vdmVCeU5hbWUoIkNJREZvbnRWZXJzaW9uIik7CiAgICAgICAgZm9udERpY3QucmVtb3ZlQnlOYW1lKCJDSURGb250UmV2aXNpb24iKTsKICAgICAgICBmb250RGljdC5yZW1vdmVCeU5hbWUoIkNJREZvbnRUeXBlIik7CiAgICAgICAgZm9udERpY3QucmVtb3ZlQnlOYW1lKCJDSURDb3VudCIpOwogICAgICAgIGZvbnREaWN0LnJlbW92ZUJ5TmFtZSgiVUlEQmFzZSIpOwogICAgICB9CiAgICAgIGNvbnN0IGZvbnREaWN0VHJhY2tlciA9IG5ldyBDRkZPZmZzZXRUcmFja2VyKCk7CiAgICAgIGNvbnN0IGZvbnREaWN0RGF0YSA9IHRoaXMuY29tcGlsZURpY3QoZm9udERpY3QsIGZvbnREaWN0VHJhY2tlcik7CiAgICAgIGZvbnREaWN0VHJhY2tlcnMucHVzaChmb250RGljdFRyYWNrZXIpOwogICAgICBmZEFycmF5SW5kZXguYWRkKGZvbnREaWN0RGF0YSk7CiAgICAgIGZvbnREaWN0VHJhY2tlci5vZmZzZXQobGVuZ3RoKTsKICAgIH0KICAgIGZkQXJyYXlJbmRleCA9IHRoaXMuY29tcGlsZUluZGV4KGZkQXJyYXlJbmRleCwgZm9udERpY3RUcmFja2Vycyk7CiAgICByZXR1cm4gewogICAgICB0cmFja2VyczogZm9udERpY3RUcmFja2VycywKICAgICAgb3V0cHV0OiBmZEFycmF5SW5kZXgKICAgIH07CiAgfQogIGNvbXBpbGVQcml2YXRlRGljdHMoZGljdHMsIHRyYWNrZXJzLCBvdXRwdXQpIHsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGRpY3RzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgICAgY29uc3QgZm9udERpY3QgPSBkaWN0c1tpXTsKICAgICAgY29uc3QgcHJpdmF0ZURpY3QgPSBmb250RGljdC5wcml2YXRlRGljdDsKICAgICAgaWYgKCFwcml2YXRlRGljdCB8fCAhZm9udERpY3QuaGFzTmFtZSgiUHJpdmF0ZSIpKSB7CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJUaGVyZSBtdXN0IGJlIGEgcHJpdmF0ZSBkaWN0aW9uYXJ5LiIpOwogICAgICB9CiAgICAgIGNvbnN0IHByaXZhdGVEaWN0VHJhY2tlciA9IG5ldyBDRkZPZmZzZXRUcmFja2VyKCk7CiAgICAgIGNvbnN0IHByaXZhdGVEaWN0RGF0YSA9IHRoaXMuY29tcGlsZURpY3QocHJpdmF0ZURpY3QsIHByaXZhdGVEaWN0VHJhY2tlcik7CiAgICAgIGxldCBvdXRwdXRMZW5ndGggPSBvdXRwdXQubGVuZ3RoOwogICAgICBwcml2YXRlRGljdFRyYWNrZXIub2Zmc2V0KG91dHB1dExlbmd0aCk7CiAgICAgIGlmICghcHJpdmF0ZURpY3REYXRhLmxlbmd0aCkgewogICAgICAgIG91dHB1dExlbmd0aCA9IDA7CiAgICAgIH0KICAgICAgdHJhY2tlcnNbaV0uc2V0RW50cnlMb2NhdGlvbigiUHJpdmF0ZSIsIFtwcml2YXRlRGljdERhdGEubGVuZ3RoLCBvdXRwdXRMZW5ndGhdLCBvdXRwdXQpOwogICAgICBvdXRwdXQuYWRkKHByaXZhdGVEaWN0RGF0YSk7CiAgICAgIGlmIChwcml2YXRlRGljdC5zdWJyc0luZGV4ICYmIHByaXZhdGVEaWN0Lmhhc05hbWUoIlN1YnJzIikpIHsKICAgICAgICBjb25zdCBzdWJycyA9IHRoaXMuY29tcGlsZUluZGV4KHByaXZhdGVEaWN0LnN1YnJzSW5kZXgpOwogICAgICAgIHByaXZhdGVEaWN0VHJhY2tlci5zZXRFbnRyeUxvY2F0aW9uKCJTdWJycyIsIFtwcml2YXRlRGljdERhdGEubGVuZ3RoXSwgb3V0cHV0KTsKICAgICAgICBvdXRwdXQuYWRkKHN1YnJzKTsKICAgICAgfQogICAgfQogIH0KICBjb21waWxlRGljdChkaWN0LCBvZmZzZXRUcmFja2VyKSB7CiAgICBjb25zdCBvdXQgPSBbXTsKICAgIGZvciAoY29uc3Qga2V5IG9mIGRpY3Qub3JkZXIpIHsKICAgICAgaWYgKCEoa2V5IGluIGRpY3QudmFsdWVzKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGxldCB2YWx1ZXMgPSBkaWN0LnZhbHVlc1trZXldOwogICAgICBsZXQgdHlwZXMgPSBkaWN0LnR5cGVzW2tleV07CiAgICAgIGlmICghQXJyYXkuaXNBcnJheSh0eXBlcykpIHsKICAgICAgICB0eXBlcyA9IFt0eXBlc107CiAgICAgIH0KICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlcykpIHsKICAgICAgICB2YWx1ZXMgPSBbdmFsdWVzXTsKICAgICAgfQogICAgICBpZiAodmFsdWVzLmxlbmd0aCA9PT0gMCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGZvciAobGV0IGogPSAwLCBqaiA9IHR5cGVzLmxlbmd0aDsgaiA8IGpqOyArK2opIHsKICAgICAgICBjb25zdCB0eXBlID0gdHlwZXNbal07CiAgICAgICAgY29uc3QgdmFsdWUgPSB2YWx1ZXNbal07CiAgICAgICAgc3dpdGNoICh0eXBlKSB7CiAgICAgICAgICBjYXNlICJudW0iOgogICAgICAgICAgY2FzZSAic2lkIjoKICAgICAgICAgICAgb3V0LnB1c2goLi4udGhpcy5lbmNvZGVOdW1iZXIodmFsdWUpKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICJvZmZzZXQiOgogICAgICAgICAgICBjb25zdCBuYW1lID0gZGljdC5rZXlUb05hbWVNYXBba2V5XTsKICAgICAgICAgICAgaWYgKCFvZmZzZXRUcmFja2VyLmlzVHJhY2tpbmcobmFtZSkpIHsKICAgICAgICAgICAgICBvZmZzZXRUcmFja2VyLnRyYWNrKG5hbWUsIG91dC5sZW5ndGgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG91dC5wdXNoKDB4MWQsIDAsIDAsIDAsIDApOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgImFycmF5IjoKICAgICAgICAgIGNhc2UgImRlbHRhIjoKICAgICAgICAgICAgb3V0LnB1c2goLi4udGhpcy5lbmNvZGVOdW1iZXIodmFsdWUpKTsKICAgICAgICAgICAgZm9yIChsZXQgayA9IDEsIGtrID0gdmFsdWVzLmxlbmd0aDsgayA8IGtrOyArK2spIHsKICAgICAgICAgICAgICBvdXQucHVzaCguLi50aGlzLmVuY29kZU51bWJlcih2YWx1ZXNba10pKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgVW5rbm93biBkYXRhIHR5cGUgb2YgJHt0eXBlfWApOwogICAgICAgIH0KICAgICAgfQogICAgICBvdXQucHVzaCguLi5kaWN0Lm9wY29kZXNba2V5XSk7CiAgICB9CiAgICByZXR1cm4gb3V0OwogIH0KICBjb21waWxlU3RyaW5nSW5kZXgoc3RyaW5ncykgewogICAgY29uc3Qgc3RyaW5nSW5kZXggPSBuZXcgQ0ZGSW5kZXgoKTsKICAgIGZvciAoY29uc3Qgc3RyaW5nIG9mIHN0cmluZ3MpIHsKICAgICAgc3RyaW5nSW5kZXguYWRkKCgwLCBfdXRpbC5zdHJpbmdUb0J5dGVzKShzdHJpbmcpKTsKICAgIH0KICAgIHJldHVybiB0aGlzLmNvbXBpbGVJbmRleChzdHJpbmdJbmRleCk7CiAgfQogIGNvbXBpbGVHbG9iYWxTdWJySW5kZXgoKSB7CiAgICBjb25zdCBnbG9iYWxTdWJySW5kZXggPSB0aGlzLmNmZi5nbG9iYWxTdWJySW5kZXg7CiAgICB0aGlzLm91dC53cml0ZUJ5dGVBcnJheSh0aGlzLmNvbXBpbGVJbmRleChnbG9iYWxTdWJySW5kZXgpKTsKICB9CiAgY29tcGlsZUNoYXJTdHJpbmdzKGNoYXJTdHJpbmdzKSB7CiAgICBjb25zdCBjaGFyU3RyaW5nc0luZGV4ID0gbmV3IENGRkluZGV4KCk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoYXJTdHJpbmdzLmNvdW50OyBpKyspIHsKICAgICAgY29uc3QgZ2x5cGggPSBjaGFyU3RyaW5ncy5nZXQoaSk7CiAgICAgIGlmIChnbHlwaC5sZW5ndGggPT09IDApIHsKICAgICAgICBjaGFyU3RyaW5nc0luZGV4LmFkZChuZXcgVWludDhBcnJheShbMHg4YiwgMHgwZV0pKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjaGFyU3RyaW5nc0luZGV4LmFkZChnbHlwaCk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5jb21waWxlSW5kZXgoY2hhclN0cmluZ3NJbmRleCk7CiAgfQogIGNvbXBpbGVDaGFyc2V0KGNoYXJzZXQsIG51bUdseXBocywgc3RyaW5ncywgaXNDSURGb250KSB7CiAgICBsZXQgb3V0OwogICAgY29uc3QgbnVtR2x5cGhzTGVzc05vdERlZiA9IG51bUdseXBocyAtIDE7CiAgICBpZiAoaXNDSURGb250KSB7CiAgICAgIG91dCA9IG5ldyBVaW50OEFycmF5KFsyLCAwLCAwLCBudW1HbHlwaHNMZXNzTm90RGVmID4+IDggJiAweGZmLCBudW1HbHlwaHNMZXNzTm90RGVmICYgMHhmZl0pOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgbGVuZ3RoID0gMSArIG51bUdseXBoc0xlc3NOb3REZWYgKiAyOwogICAgICBvdXQgPSBuZXcgVWludDhBcnJheShsZW5ndGgpOwogICAgICBvdXRbMF0gPSAwOwogICAgICBsZXQgY2hhcnNldEluZGV4ID0gMDsKICAgICAgY29uc3QgbnVtQ2hhcnNldHMgPSBjaGFyc2V0LmNoYXJzZXQubGVuZ3RoOwogICAgICBsZXQgd2FybmVkID0gZmFsc2U7CiAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgb3V0Lmxlbmd0aDsgaSArPSAyKSB7CiAgICAgICAgbGV0IHNpZCA9IDA7CiAgICAgICAgaWYgKGNoYXJzZXRJbmRleCA8IG51bUNoYXJzZXRzKSB7CiAgICAgICAgICBjb25zdCBuYW1lID0gY2hhcnNldC5jaGFyc2V0W2NoYXJzZXRJbmRleCsrXTsKICAgICAgICAgIHNpZCA9IHN0cmluZ3MuZ2V0U0lEKG5hbWUpOwogICAgICAgICAgaWYgKHNpZCA9PT0gLTEpIHsKICAgICAgICAgICAgc2lkID0gMDsKICAgICAgICAgICAgaWYgKCF3YXJuZWQpIHsKICAgICAgICAgICAgICB3YXJuZWQgPSB0cnVlOwogICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgQ291bGRuJ3QgZmluZCAke25hbWV9IGluIENGRiBzdHJpbmdzYCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgb3V0W2ldID0gc2lkID4+IDggJiAweGZmOwogICAgICAgIG91dFtpICsgMV0gPSBzaWQgJiAweGZmOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdGhpcy5jb21waWxlVHlwZWRBcnJheShvdXQpOwogIH0KICBjb21waWxlRW5jb2RpbmcoZW5jb2RpbmcpIHsKICAgIHJldHVybiB0aGlzLmNvbXBpbGVUeXBlZEFycmF5KGVuY29kaW5nLnJhdyk7CiAgfQogIGNvbXBpbGVGRFNlbGVjdChmZFNlbGVjdCkgewogICAgY29uc3QgZm9ybWF0ID0gZmRTZWxlY3QuZm9ybWF0OwogICAgbGV0IG91dCwgaTsKICAgIHN3aXRjaCAoZm9ybWF0KSB7CiAgICAgIGNhc2UgMDoKICAgICAgICBvdXQgPSBuZXcgVWludDhBcnJheSgxICsgZmRTZWxlY3QuZmRTZWxlY3QubGVuZ3RoKTsKICAgICAgICBvdXRbMF0gPSBmb3JtYXQ7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGZkU2VsZWN0LmZkU2VsZWN0Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBvdXRbaSArIDFdID0gZmRTZWxlY3QuZmRTZWxlY3RbaV07CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDM6CiAgICAgICAgY29uc3Qgc3RhcnQgPSAwOwogICAgICAgIGxldCBsYXN0RkQgPSBmZFNlbGVjdC5mZFNlbGVjdFswXTsKICAgICAgICBjb25zdCByYW5nZXMgPSBbZm9ybWF0LCAwLCAwLCBzdGFydCA+PiA4ICYgMHhmZiwgc3RhcnQgJiAweGZmLCBsYXN0RkRdOwogICAgICAgIGZvciAoaSA9IDE7IGkgPCBmZFNlbGVjdC5mZFNlbGVjdC5sZW5ndGg7IGkrKykgewogICAgICAgICAgY29uc3QgY3VycmVudEZEID0gZmRTZWxlY3QuZmRTZWxlY3RbaV07CiAgICAgICAgICBpZiAoY3VycmVudEZEICE9PSBsYXN0RkQpIHsKICAgICAgICAgICAgcmFuZ2VzLnB1c2goaSA+PiA4ICYgMHhmZiwgaSAmIDB4ZmYsIGN1cnJlbnRGRCk7CiAgICAgICAgICAgIGxhc3RGRCA9IGN1cnJlbnRGRDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgbnVtUmFuZ2VzID0gKHJhbmdlcy5sZW5ndGggLSAzKSAvIDM7CiAgICAgICAgcmFuZ2VzWzFdID0gbnVtUmFuZ2VzID4+IDggJiAweGZmOwogICAgICAgIHJhbmdlc1syXSA9IG51bVJhbmdlcyAmIDB4ZmY7CiAgICAgICAgcmFuZ2VzLnB1c2goaSA+PiA4ICYgMHhmZiwgaSAmIDB4ZmYpOwogICAgICAgIG91dCA9IG5ldyBVaW50OEFycmF5KHJhbmdlcyk7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICByZXR1cm4gdGhpcy5jb21waWxlVHlwZWRBcnJheShvdXQpOwogIH0KICBjb21waWxlVHlwZWRBcnJheShkYXRhKSB7CiAgICBjb25zdCBvdXQgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGRhdGEubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICBvdXRbaV0gPSBkYXRhW2ldOwogICAgfQogICAgcmV0dXJuIG91dDsKICB9CiAgY29tcGlsZUluZGV4KGluZGV4KSB7CiAgICBsZXQgdHJhY2tlcnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IFtdOwogICAgY29uc3Qgb2JqZWN0cyA9IGluZGV4Lm9iamVjdHM7CiAgICBjb25zdCBjb3VudCA9IG9iamVjdHMubGVuZ3RoOwogICAgaWYgKGNvdW50ID09PSAwKSB7CiAgICAgIHJldHVybiBbMCwgMF07CiAgICB9CiAgICBjb25zdCBkYXRhID0gW2NvdW50ID4+IDggJiAweGZmLCBjb3VudCAmIDB4ZmZdOwogICAgbGV0IGxhc3RPZmZzZXQgPSAxLAogICAgICBpOwogICAgZm9yIChpID0gMDsgaSA8IGNvdW50OyArK2kpIHsKICAgICAgbGFzdE9mZnNldCArPSBvYmplY3RzW2ldLmxlbmd0aDsKICAgIH0KICAgIGxldCBvZmZzZXRTaXplOwogICAgaWYgKGxhc3RPZmZzZXQgPCAweDEwMCkgewogICAgICBvZmZzZXRTaXplID0gMTsKICAgIH0gZWxzZSBpZiAobGFzdE9mZnNldCA8IDB4MTAwMDApIHsKICAgICAgb2Zmc2V0U2l6ZSA9IDI7CiAgICB9IGVsc2UgaWYgKGxhc3RPZmZzZXQgPCAweDEwMDAwMDApIHsKICAgICAgb2Zmc2V0U2l6ZSA9IDM7CiAgICB9IGVsc2UgewogICAgICBvZmZzZXRTaXplID0gNDsKICAgIH0KICAgIGRhdGEucHVzaChvZmZzZXRTaXplKTsKICAgIGxldCByZWxhdGl2ZU9mZnNldCA9IDE7CiAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQgKyAxOyBpKyspIHsKICAgICAgaWYgKG9mZnNldFNpemUgPT09IDEpIHsKICAgICAgICBkYXRhLnB1c2gocmVsYXRpdmVPZmZzZXQgJiAweGZmKTsKICAgICAgfSBlbHNlIGlmIChvZmZzZXRTaXplID09PSAyKSB7CiAgICAgICAgZGF0YS5wdXNoKHJlbGF0aXZlT2Zmc2V0ID4+IDggJiAweGZmLCByZWxhdGl2ZU9mZnNldCAmIDB4ZmYpOwogICAgICB9IGVsc2UgaWYgKG9mZnNldFNpemUgPT09IDMpIHsKICAgICAgICBkYXRhLnB1c2gocmVsYXRpdmVPZmZzZXQgPj4gMTYgJiAweGZmLCByZWxhdGl2ZU9mZnNldCA+PiA4ICYgMHhmZiwgcmVsYXRpdmVPZmZzZXQgJiAweGZmKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBkYXRhLnB1c2gocmVsYXRpdmVPZmZzZXQgPj4+IDI0ICYgMHhmZiwgcmVsYXRpdmVPZmZzZXQgPj4gMTYgJiAweGZmLCByZWxhdGl2ZU9mZnNldCA+PiA4ICYgMHhmZiwgcmVsYXRpdmVPZmZzZXQgJiAweGZmKTsKICAgICAgfQogICAgICBpZiAob2JqZWN0c1tpXSkgewogICAgICAgIHJlbGF0aXZlT2Zmc2V0ICs9IG9iamVjdHNbaV0ubGVuZ3RoOwogICAgICB9CiAgICB9CiAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQ7IGkrKykgewogICAgICBpZiAodHJhY2tlcnNbaV0pIHsKICAgICAgICB0cmFja2Vyc1tpXS5vZmZzZXQoZGF0YS5sZW5ndGgpOwogICAgICB9CiAgICAgIGRhdGEucHVzaCguLi5vYmplY3RzW2ldKTsKICAgIH0KICAgIHJldHVybiBkYXRhOwogIH0KfQpleHBvcnRzLkNGRkNvbXBpbGVyID0gQ0ZGQ29tcGlsZXI7CgovKioqLyB9KSwKLyogMTcxICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMpID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5JU09BZG9iZUNoYXJzZXQgPSBleHBvcnRzLkV4cGVydFN1YnNldENoYXJzZXQgPSBleHBvcnRzLkV4cGVydENoYXJzZXQgPSB2b2lkIDA7CmNvbnN0IElTT0Fkb2JlQ2hhcnNldCA9IFsiLm5vdGRlZiIsICJzcGFjZSIsICJleGNsYW0iLCAicXVvdGVkYmwiLCAibnVtYmVyc2lnbiIsICJkb2xsYXIiLCAicGVyY2VudCIsICJhbXBlcnNhbmQiLCAicXVvdGVyaWdodCIsICJwYXJlbmxlZnQiLCAicGFyZW5yaWdodCIsICJhc3RlcmlzayIsICJwbHVzIiwgImNvbW1hIiwgImh5cGhlbiIsICJwZXJpb2QiLCAic2xhc2giLCAiemVybyIsICJvbmUiLCAidHdvIiwgInRocmVlIiwgImZvdXIiLCAiZml2ZSIsICJzaXgiLCAic2V2ZW4iLCAiZWlnaHQiLCAibmluZSIsICJjb2xvbiIsICJzZW1pY29sb24iLCAibGVzcyIsICJlcXVhbCIsICJncmVhdGVyIiwgInF1ZXN0aW9uIiwgImF0IiwgIkEiLCAiQiIsICJDIiwgIkQiLCAiRSIsICJGIiwgIkciLCAiSCIsICJJIiwgIkoiLCAiSyIsICJMIiwgIk0iLCAiTiIsICJPIiwgIlAiLCAiUSIsICJSIiwgIlMiLCAiVCIsICJVIiwgIlYiLCAiVyIsICJYIiwgIlkiLCAiWiIsICJicmFja2V0bGVmdCIsICJiYWNrc2xhc2giLCAiYnJhY2tldHJpZ2h0IiwgImFzY2lpY2lyY3VtIiwgInVuZGVyc2NvcmUiLCAicXVvdGVsZWZ0IiwgImEiLCAiYiIsICJjIiwgImQiLCAiZSIsICJmIiwgImciLCAiaCIsICJpIiwgImoiLCAiayIsICJsIiwgIm0iLCAibiIsICJvIiwgInAiLCAicSIsICJyIiwgInMiLCAidCIsICJ1IiwgInYiLCAidyIsICJ4IiwgInkiLCAieiIsICJicmFjZWxlZnQiLCAiYmFyIiwgImJyYWNlcmlnaHQiLCAiYXNjaWl0aWxkZSIsICJleGNsYW1kb3duIiwgImNlbnQiLCAic3RlcmxpbmciLCAiZnJhY3Rpb24iLCAieWVuIiwgImZsb3JpbiIsICJzZWN0aW9uIiwgImN1cnJlbmN5IiwgInF1b3Rlc2luZ2xlIiwgInF1b3RlZGJsbGVmdCIsICJndWlsbGVtb3RsZWZ0IiwgImd1aWxzaW5nbGxlZnQiLCAiZ3VpbHNpbmdscmlnaHQiLCAiZmkiLCAiZmwiLCAiZW5kYXNoIiwgImRhZ2dlciIsICJkYWdnZXJkYmwiLCAicGVyaW9kY2VudGVyZWQiLCAicGFyYWdyYXBoIiwgImJ1bGxldCIsICJxdW90ZXNpbmdsYmFzZSIsICJxdW90ZWRibGJhc2UiLCAicXVvdGVkYmxyaWdodCIsICJndWlsbGVtb3RyaWdodCIsICJlbGxpcHNpcyIsICJwZXJ0aG91c2FuZCIsICJxdWVzdGlvbmRvd24iLCAiZ3JhdmUiLCAiYWN1dGUiLCAiY2lyY3VtZmxleCIsICJ0aWxkZSIsICJtYWNyb24iLCAiYnJldmUiLCAiZG90YWNjZW50IiwgImRpZXJlc2lzIiwgInJpbmciLCAiY2VkaWxsYSIsICJodW5nYXJ1bWxhdXQiLCAib2dvbmVrIiwgImNhcm9uIiwgImVtZGFzaCIsICJBRSIsICJvcmRmZW1pbmluZSIsICJMc2xhc2giLCAiT3NsYXNoIiwgIk9FIiwgIm9yZG1hc2N1bGluZSIsICJhZSIsICJkb3RsZXNzaSIsICJsc2xhc2giLCAib3NsYXNoIiwgIm9lIiwgImdlcm1hbmRibHMiLCAib25lc3VwZXJpb3IiLCAibG9naWNhbG5vdCIsICJtdSIsICJ0cmFkZW1hcmsiLCAiRXRoIiwgIm9uZWhhbGYiLCAicGx1c21pbnVzIiwgIlRob3JuIiwgIm9uZXF1YXJ0ZXIiLCAiZGl2aWRlIiwgImJyb2tlbmJhciIsICJkZWdyZWUiLCAidGhvcm4iLCAidGhyZWVxdWFydGVycyIsICJ0d29zdXBlcmlvciIsICJyZWdpc3RlcmVkIiwgIm1pbnVzIiwgImV0aCIsICJtdWx0aXBseSIsICJ0aHJlZXN1cGVyaW9yIiwgImNvcHlyaWdodCIsICJBYWN1dGUiLCAiQWNpcmN1bWZsZXgiLCAiQWRpZXJlc2lzIiwgIkFncmF2ZSIsICJBcmluZyIsICJBdGlsZGUiLCAiQ2NlZGlsbGEiLCAiRWFjdXRlIiwgIkVjaXJjdW1mbGV4IiwgIkVkaWVyZXNpcyIsICJFZ3JhdmUiLCAiSWFjdXRlIiwgIkljaXJjdW1mbGV4IiwgIklkaWVyZXNpcyIsICJJZ3JhdmUiLCAiTnRpbGRlIiwgIk9hY3V0ZSIsICJPY2lyY3VtZmxleCIsICJPZGllcmVzaXMiLCAiT2dyYXZlIiwgIk90aWxkZSIsICJTY2Fyb24iLCAiVWFjdXRlIiwgIlVjaXJjdW1mbGV4IiwgIlVkaWVyZXNpcyIsICJVZ3JhdmUiLCAiWWFjdXRlIiwgIllkaWVyZXNpcyIsICJaY2Fyb24iLCAiYWFjdXRlIiwgImFjaXJjdW1mbGV4IiwgImFkaWVyZXNpcyIsICJhZ3JhdmUiLCAiYXJpbmciLCAiYXRpbGRlIiwgImNjZWRpbGxhIiwgImVhY3V0ZSIsICJlY2lyY3VtZmxleCIsICJlZGllcmVzaXMiLCAiZWdyYXZlIiwgImlhY3V0ZSIsICJpY2lyY3VtZmxleCIsICJpZGllcmVzaXMiLCAiaWdyYXZlIiwgIm50aWxkZSIsICJvYWN1dGUiLCAib2NpcmN1bWZsZXgiLCAib2RpZXJlc2lzIiwgIm9ncmF2ZSIsICJvdGlsZGUiLCAic2Nhcm9uIiwgInVhY3V0ZSIsICJ1Y2lyY3VtZmxleCIsICJ1ZGllcmVzaXMiLCAidWdyYXZlIiwgInlhY3V0ZSIsICJ5ZGllcmVzaXMiLCAiemNhcm9uIl07CmV4cG9ydHMuSVNPQWRvYmVDaGFyc2V0ID0gSVNPQWRvYmVDaGFyc2V0Owpjb25zdCBFeHBlcnRDaGFyc2V0ID0gWyIubm90ZGVmIiwgInNwYWNlIiwgImV4Y2xhbXNtYWxsIiwgIkh1bmdhcnVtbGF1dHNtYWxsIiwgImRvbGxhcm9sZHN0eWxlIiwgImRvbGxhcnN1cGVyaW9yIiwgImFtcGVyc2FuZHNtYWxsIiwgIkFjdXRlc21hbGwiLCAicGFyZW5sZWZ0c3VwZXJpb3IiLCAicGFyZW5yaWdodHN1cGVyaW9yIiwgInR3b2RvdGVubGVhZGVyIiwgIm9uZWRvdGVubGVhZGVyIiwgImNvbW1hIiwgImh5cGhlbiIsICJwZXJpb2QiLCAiZnJhY3Rpb24iLCAiemVyb29sZHN0eWxlIiwgIm9uZW9sZHN0eWxlIiwgInR3b29sZHN0eWxlIiwgInRocmVlb2xkc3R5bGUiLCAiZm91cm9sZHN0eWxlIiwgImZpdmVvbGRzdHlsZSIsICJzaXhvbGRzdHlsZSIsICJzZXZlbm9sZHN0eWxlIiwgImVpZ2h0b2xkc3R5bGUiLCAibmluZW9sZHN0eWxlIiwgImNvbG9uIiwgInNlbWljb2xvbiIsICJjb21tYXN1cGVyaW9yIiwgInRocmVlcXVhcnRlcnNlbWRhc2giLCAicGVyaW9kc3VwZXJpb3IiLCAicXVlc3Rpb25zbWFsbCIsICJhc3VwZXJpb3IiLCAiYnN1cGVyaW9yIiwgImNlbnRzdXBlcmlvciIsICJkc3VwZXJpb3IiLCAiZXN1cGVyaW9yIiwgImlzdXBlcmlvciIsICJsc3VwZXJpb3IiLCAibXN1cGVyaW9yIiwgIm5zdXBlcmlvciIsICJvc3VwZXJpb3IiLCAicnN1cGVyaW9yIiwgInNzdXBlcmlvciIsICJ0c3VwZXJpb3IiLCAiZmYiLCAiZmkiLCAiZmwiLCAiZmZpIiwgImZmbCIsICJwYXJlbmxlZnRpbmZlcmlvciIsICJwYXJlbnJpZ2h0aW5mZXJpb3IiLCAiQ2lyY3VtZmxleHNtYWxsIiwgImh5cGhlbnN1cGVyaW9yIiwgIkdyYXZlc21hbGwiLCAiQXNtYWxsIiwgIkJzbWFsbCIsICJDc21hbGwiLCAiRHNtYWxsIiwgIkVzbWFsbCIsICJGc21hbGwiLCAiR3NtYWxsIiwgIkhzbWFsbCIsICJJc21hbGwiLCAiSnNtYWxsIiwgIktzbWFsbCIsICJMc21hbGwiLCAiTXNtYWxsIiwgIk5zbWFsbCIsICJPc21hbGwiLCAiUHNtYWxsIiwgIlFzbWFsbCIsICJSc21hbGwiLCAiU3NtYWxsIiwgIlRzbWFsbCIsICJVc21hbGwiLCAiVnNtYWxsIiwgIldzbWFsbCIsICJYc21hbGwiLCAiWXNtYWxsIiwgIlpzbWFsbCIsICJjb2xvbm1vbmV0YXJ5IiwgIm9uZWZpdHRlZCIsICJydXBpYWgiLCAiVGlsZGVzbWFsbCIsICJleGNsYW1kb3duc21hbGwiLCAiY2VudG9sZHN0eWxlIiwgIkxzbGFzaHNtYWxsIiwgIlNjYXJvbnNtYWxsIiwgIlpjYXJvbnNtYWxsIiwgIkRpZXJlc2lzc21hbGwiLCAiQnJldmVzbWFsbCIsICJDYXJvbnNtYWxsIiwgIkRvdGFjY2VudHNtYWxsIiwgIk1hY3JvbnNtYWxsIiwgImZpZ3VyZWRhc2giLCAiaHlwaGVuaW5mZXJpb3IiLCAiT2dvbmVrc21hbGwiLCAiUmluZ3NtYWxsIiwgIkNlZGlsbGFzbWFsbCIsICJvbmVxdWFydGVyIiwgIm9uZWhhbGYiLCAidGhyZWVxdWFydGVycyIsICJxdWVzdGlvbmRvd25zbWFsbCIsICJvbmVlaWdodGgiLCAidGhyZWVlaWdodGhzIiwgImZpdmVlaWdodGhzIiwgInNldmVuZWlnaHRocyIsICJvbmV0aGlyZCIsICJ0d290aGlyZHMiLCAiemVyb3N1cGVyaW9yIiwgIm9uZXN1cGVyaW9yIiwgInR3b3N1cGVyaW9yIiwgInRocmVlc3VwZXJpb3IiLCAiZm91cnN1cGVyaW9yIiwgImZpdmVzdXBlcmlvciIsICJzaXhzdXBlcmlvciIsICJzZXZlbnN1cGVyaW9yIiwgImVpZ2h0c3VwZXJpb3IiLCAibmluZXN1cGVyaW9yIiwgInplcm9pbmZlcmlvciIsICJvbmVpbmZlcmlvciIsICJ0d29pbmZlcmlvciIsICJ0aHJlZWluZmVyaW9yIiwgImZvdXJpbmZlcmlvciIsICJmaXZlaW5mZXJpb3IiLCAic2l4aW5mZXJpb3IiLCAic2V2ZW5pbmZlcmlvciIsICJlaWdodGluZmVyaW9yIiwgIm5pbmVpbmZlcmlvciIsICJjZW50aW5mZXJpb3IiLCAiZG9sbGFyaW5mZXJpb3IiLCAicGVyaW9kaW5mZXJpb3IiLCAiY29tbWFpbmZlcmlvciIsICJBZ3JhdmVzbWFsbCIsICJBYWN1dGVzbWFsbCIsICJBY2lyY3VtZmxleHNtYWxsIiwgIkF0aWxkZXNtYWxsIiwgIkFkaWVyZXNpc3NtYWxsIiwgIkFyaW5nc21hbGwiLCAiQUVzbWFsbCIsICJDY2VkaWxsYXNtYWxsIiwgIkVncmF2ZXNtYWxsIiwgIkVhY3V0ZXNtYWxsIiwgIkVjaXJjdW1mbGV4c21hbGwiLCAiRWRpZXJlc2lzc21hbGwiLCAiSWdyYXZlc21hbGwiLCAiSWFjdXRlc21hbGwiLCAiSWNpcmN1bWZsZXhzbWFsbCIsICJJZGllcmVzaXNzbWFsbCIsICJFdGhzbWFsbCIsICJOdGlsZGVzbWFsbCIsICJPZ3JhdmVzbWFsbCIsICJPYWN1dGVzbWFsbCIsICJPY2lyY3VtZmxleHNtYWxsIiwgIk90aWxkZXNtYWxsIiwgIk9kaWVyZXNpc3NtYWxsIiwgIk9Fc21hbGwiLCAiT3NsYXNoc21hbGwiLCAiVWdyYXZlc21hbGwiLCAiVWFjdXRlc21hbGwiLCAiVWNpcmN1bWZsZXhzbWFsbCIsICJVZGllcmVzaXNzbWFsbCIsICJZYWN1dGVzbWFsbCIsICJUaG9ybnNtYWxsIiwgIllkaWVyZXNpc3NtYWxsIl07CmV4cG9ydHMuRXhwZXJ0Q2hhcnNldCA9IEV4cGVydENoYXJzZXQ7CmNvbnN0IEV4cGVydFN1YnNldENoYXJzZXQgPSBbIi5ub3RkZWYiLCAic3BhY2UiLCAiZG9sbGFyb2xkc3R5bGUiLCAiZG9sbGFyc3VwZXJpb3IiLCAicGFyZW5sZWZ0c3VwZXJpb3IiLCAicGFyZW5yaWdodHN1cGVyaW9yIiwgInR3b2RvdGVubGVhZGVyIiwgIm9uZWRvdGVubGVhZGVyIiwgImNvbW1hIiwgImh5cGhlbiIsICJwZXJpb2QiLCAiZnJhY3Rpb24iLCAiemVyb29sZHN0eWxlIiwgIm9uZW9sZHN0eWxlIiwgInR3b29sZHN0eWxlIiwgInRocmVlb2xkc3R5bGUiLCAiZm91cm9sZHN0eWxlIiwgImZpdmVvbGRzdHlsZSIsICJzaXhvbGRzdHlsZSIsICJzZXZlbm9sZHN0eWxlIiwgImVpZ2h0b2xkc3R5bGUiLCAibmluZW9sZHN0eWxlIiwgImNvbG9uIiwgInNlbWljb2xvbiIsICJjb21tYXN1cGVyaW9yIiwgInRocmVlcXVhcnRlcnNlbWRhc2giLCAicGVyaW9kc3VwZXJpb3IiLCAiYXN1cGVyaW9yIiwgImJzdXBlcmlvciIsICJjZW50c3VwZXJpb3IiLCAiZHN1cGVyaW9yIiwgImVzdXBlcmlvciIsICJpc3VwZXJpb3IiLCAibHN1cGVyaW9yIiwgIm1zdXBlcmlvciIsICJuc3VwZXJpb3IiLCAib3N1cGVyaW9yIiwgInJzdXBlcmlvciIsICJzc3VwZXJpb3IiLCAidHN1cGVyaW9yIiwgImZmIiwgImZpIiwgImZsIiwgImZmaSIsICJmZmwiLCAicGFyZW5sZWZ0aW5mZXJpb3IiLCAicGFyZW5yaWdodGluZmVyaW9yIiwgImh5cGhlbnN1cGVyaW9yIiwgImNvbG9ubW9uZXRhcnkiLCAib25lZml0dGVkIiwgInJ1cGlhaCIsICJjZW50b2xkc3R5bGUiLCAiZmlndXJlZGFzaCIsICJoeXBoZW5pbmZlcmlvciIsICJvbmVxdWFydGVyIiwgIm9uZWhhbGYiLCAidGhyZWVxdWFydGVycyIsICJvbmVlaWdodGgiLCAidGhyZWVlaWdodGhzIiwgImZpdmVlaWdodGhzIiwgInNldmVuZWlnaHRocyIsICJvbmV0aGlyZCIsICJ0d290aGlyZHMiLCAiemVyb3N1cGVyaW9yIiwgIm9uZXN1cGVyaW9yIiwgInR3b3N1cGVyaW9yIiwgInRocmVlc3VwZXJpb3IiLCAiZm91cnN1cGVyaW9yIiwgImZpdmVzdXBlcmlvciIsICJzaXhzdXBlcmlvciIsICJzZXZlbnN1cGVyaW9yIiwgImVpZ2h0c3VwZXJpb3IiLCAibmluZXN1cGVyaW9yIiwgInplcm9pbmZlcmlvciIsICJvbmVpbmZlcmlvciIsICJ0d29pbmZlcmlvciIsICJ0aHJlZWluZmVyaW9yIiwgImZvdXJpbmZlcmlvciIsICJmaXZlaW5mZXJpb3IiLCAic2l4aW5mZXJpb3IiLCAic2V2ZW5pbmZlcmlvciIsICJlaWdodGluZmVyaW9yIiwgIm5pbmVpbmZlcmlvciIsICJjZW50aW5mZXJpb3IiLCAiZG9sbGFyaW5mZXJpb3IiLCAicGVyaW9kaW5mZXJpb3IiLCAiY29tbWFpbmZlcmlvciJdOwpleHBvcnRzLkV4cGVydFN1YnNldENoYXJzZXQgPSBFeHBlcnRTdWJzZXRDaGFyc2V0OwoKLyoqKi8gfSksCi8qIDE3MiAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuWmFwZkRpbmdiYXRzRW5jb2RpbmcgPSBleHBvcnRzLldpbkFuc2lFbmNvZGluZyA9IGV4cG9ydHMuU3ltYm9sU2V0RW5jb2RpbmcgPSBleHBvcnRzLlN0YW5kYXJkRW5jb2RpbmcgPSBleHBvcnRzLk1hY1JvbWFuRW5jb2RpbmcgPSBleHBvcnRzLkV4cGVydEVuY29kaW5nID0gdm9pZCAwOwpleHBvcnRzLmdldEVuY29kaW5nID0gZ2V0RW5jb2Rpbmc7CmNvbnN0IEV4cGVydEVuY29kaW5nID0gWyIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgInNwYWNlIiwgImV4Y2xhbXNtYWxsIiwgIkh1bmdhcnVtbGF1dHNtYWxsIiwgIiIsICJkb2xsYXJvbGRzdHlsZSIsICJkb2xsYXJzdXBlcmlvciIsICJhbXBlcnNhbmRzbWFsbCIsICJBY3V0ZXNtYWxsIiwgInBhcmVubGVmdHN1cGVyaW9yIiwgInBhcmVucmlnaHRzdXBlcmlvciIsICJ0d29kb3RlbmxlYWRlciIsICJvbmVkb3RlbmxlYWRlciIsICJjb21tYSIsICJoeXBoZW4iLCAicGVyaW9kIiwgImZyYWN0aW9uIiwgInplcm9vbGRzdHlsZSIsICJvbmVvbGRzdHlsZSIsICJ0d29vbGRzdHlsZSIsICJ0aHJlZW9sZHN0eWxlIiwgImZvdXJvbGRzdHlsZSIsICJmaXZlb2xkc3R5bGUiLCAic2l4b2xkc3R5bGUiLCAic2V2ZW5vbGRzdHlsZSIsICJlaWdodG9sZHN0eWxlIiwgIm5pbmVvbGRzdHlsZSIsICJjb2xvbiIsICJzZW1pY29sb24iLCAiY29tbWFzdXBlcmlvciIsICJ0aHJlZXF1YXJ0ZXJzZW1kYXNoIiwgInBlcmlvZHN1cGVyaW9yIiwgInF1ZXN0aW9uc21hbGwiLCAiIiwgImFzdXBlcmlvciIsICJic3VwZXJpb3IiLCAiY2VudHN1cGVyaW9yIiwgImRzdXBlcmlvciIsICJlc3VwZXJpb3IiLCAiIiwgIiIsICIiLCAiaXN1cGVyaW9yIiwgIiIsICIiLCAibHN1cGVyaW9yIiwgIm1zdXBlcmlvciIsICJuc3VwZXJpb3IiLCAib3N1cGVyaW9yIiwgIiIsICIiLCAicnN1cGVyaW9yIiwgInNzdXBlcmlvciIsICJ0c3VwZXJpb3IiLCAiIiwgImZmIiwgImZpIiwgImZsIiwgImZmaSIsICJmZmwiLCAicGFyZW5sZWZ0aW5mZXJpb3IiLCAiIiwgInBhcmVucmlnaHRpbmZlcmlvciIsICJDaXJjdW1mbGV4c21hbGwiLCAiaHlwaGVuc3VwZXJpb3IiLCAiR3JhdmVzbWFsbCIsICJBc21hbGwiLCAiQnNtYWxsIiwgIkNzbWFsbCIsICJEc21hbGwiLCAiRXNtYWxsIiwgIkZzbWFsbCIsICJHc21hbGwiLCAiSHNtYWxsIiwgIklzbWFsbCIsICJKc21hbGwiLCAiS3NtYWxsIiwgIkxzbWFsbCIsICJNc21hbGwiLCAiTnNtYWxsIiwgIk9zbWFsbCIsICJQc21hbGwiLCAiUXNtYWxsIiwgIlJzbWFsbCIsICJTc21hbGwiLCAiVHNtYWxsIiwgIlVzbWFsbCIsICJWc21hbGwiLCAiV3NtYWxsIiwgIlhzbWFsbCIsICJZc21hbGwiLCAiWnNtYWxsIiwgImNvbG9ubW9uZXRhcnkiLCAib25lZml0dGVkIiwgInJ1cGlhaCIsICJUaWxkZXNtYWxsIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJleGNsYW1kb3duc21hbGwiLCAiY2VudG9sZHN0eWxlIiwgIkxzbGFzaHNtYWxsIiwgIiIsICIiLCAiU2Nhcm9uc21hbGwiLCAiWmNhcm9uc21hbGwiLCAiRGllcmVzaXNzbWFsbCIsICJCcmV2ZXNtYWxsIiwgIkNhcm9uc21hbGwiLCAiIiwgIkRvdGFjY2VudHNtYWxsIiwgIiIsICIiLCAiTWFjcm9uc21hbGwiLCAiIiwgIiIsICJmaWd1cmVkYXNoIiwgImh5cGhlbmluZmVyaW9yIiwgIiIsICIiLCAiT2dvbmVrc21hbGwiLCAiUmluZ3NtYWxsIiwgIkNlZGlsbGFzbWFsbCIsICIiLCAiIiwgIiIsICJvbmVxdWFydGVyIiwgIm9uZWhhbGYiLCAidGhyZWVxdWFydGVycyIsICJxdWVzdGlvbmRvd25zbWFsbCIsICJvbmVlaWdodGgiLCAidGhyZWVlaWdodGhzIiwgImZpdmVlaWdodGhzIiwgInNldmVuZWlnaHRocyIsICJvbmV0aGlyZCIsICJ0d290aGlyZHMiLCAiIiwgIiIsICJ6ZXJvc3VwZXJpb3IiLCAib25lc3VwZXJpb3IiLCAidHdvc3VwZXJpb3IiLCAidGhyZWVzdXBlcmlvciIsICJmb3Vyc3VwZXJpb3IiLCAiZml2ZXN1cGVyaW9yIiwgInNpeHN1cGVyaW9yIiwgInNldmVuc3VwZXJpb3IiLCAiZWlnaHRzdXBlcmlvciIsICJuaW5lc3VwZXJpb3IiLCAiemVyb2luZmVyaW9yIiwgIm9uZWluZmVyaW9yIiwgInR3b2luZmVyaW9yIiwgInRocmVlaW5mZXJpb3IiLCAiZm91cmluZmVyaW9yIiwgImZpdmVpbmZlcmlvciIsICJzaXhpbmZlcmlvciIsICJzZXZlbmluZmVyaW9yIiwgImVpZ2h0aW5mZXJpb3IiLCAibmluZWluZmVyaW9yIiwgImNlbnRpbmZlcmlvciIsICJkb2xsYXJpbmZlcmlvciIsICJwZXJpb2RpbmZlcmlvciIsICJjb21tYWluZmVyaW9yIiwgIkFncmF2ZXNtYWxsIiwgIkFhY3V0ZXNtYWxsIiwgIkFjaXJjdW1mbGV4c21hbGwiLCAiQXRpbGRlc21hbGwiLCAiQWRpZXJlc2lzc21hbGwiLCAiQXJpbmdzbWFsbCIsICJBRXNtYWxsIiwgIkNjZWRpbGxhc21hbGwiLCAiRWdyYXZlc21hbGwiLCAiRWFjdXRlc21hbGwiLCAiRWNpcmN1bWZsZXhzbWFsbCIsICJFZGllcmVzaXNzbWFsbCIsICJJZ3JhdmVzbWFsbCIsICJJYWN1dGVzbWFsbCIsICJJY2lyY3VtZmxleHNtYWxsIiwgIklkaWVyZXNpc3NtYWxsIiwgIkV0aHNtYWxsIiwgIk50aWxkZXNtYWxsIiwgIk9ncmF2ZXNtYWxsIiwgIk9hY3V0ZXNtYWxsIiwgIk9jaXJjdW1mbGV4c21hbGwiLCAiT3RpbGRlc21hbGwiLCAiT2RpZXJlc2lzc21hbGwiLCAiT0VzbWFsbCIsICJPc2xhc2hzbWFsbCIsICJVZ3JhdmVzbWFsbCIsICJVYWN1dGVzbWFsbCIsICJVY2lyY3VtZmxleHNtYWxsIiwgIlVkaWVyZXNpc3NtYWxsIiwgIllhY3V0ZXNtYWxsIiwgIlRob3Juc21hbGwiLCAiWWRpZXJlc2lzc21hbGwiXTsKZXhwb3J0cy5FeHBlcnRFbmNvZGluZyA9IEV4cGVydEVuY29kaW5nOwpjb25zdCBNYWNFeHBlcnRFbmNvZGluZyA9IFsiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJzcGFjZSIsICJleGNsYW1zbWFsbCIsICJIdW5nYXJ1bWxhdXRzbWFsbCIsICJjZW50b2xkc3R5bGUiLCAiZG9sbGFyb2xkc3R5bGUiLCAiZG9sbGFyc3VwZXJpb3IiLCAiYW1wZXJzYW5kc21hbGwiLCAiQWN1dGVzbWFsbCIsICJwYXJlbmxlZnRzdXBlcmlvciIsICJwYXJlbnJpZ2h0c3VwZXJpb3IiLCAidHdvZG90ZW5sZWFkZXIiLCAib25lZG90ZW5sZWFkZXIiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJmcmFjdGlvbiIsICJ6ZXJvb2xkc3R5bGUiLCAib25lb2xkc3R5bGUiLCAidHdvb2xkc3R5bGUiLCAidGhyZWVvbGRzdHlsZSIsICJmb3Vyb2xkc3R5bGUiLCAiZml2ZW9sZHN0eWxlIiwgInNpeG9sZHN0eWxlIiwgInNldmVub2xkc3R5bGUiLCAiZWlnaHRvbGRzdHlsZSIsICJuaW5lb2xkc3R5bGUiLCAiY29sb24iLCAic2VtaWNvbG9uIiwgIiIsICJ0aHJlZXF1YXJ0ZXJzZW1kYXNoIiwgIiIsICJxdWVzdGlvbnNtYWxsIiwgIiIsICIiLCAiIiwgIiIsICJFdGhzbWFsbCIsICIiLCAiIiwgIm9uZXF1YXJ0ZXIiLCAib25laGFsZiIsICJ0aHJlZXF1YXJ0ZXJzIiwgIm9uZWVpZ2h0aCIsICJ0aHJlZWVpZ2h0aHMiLCAiZml2ZWVpZ2h0aHMiLCAic2V2ZW5laWdodGhzIiwgIm9uZXRoaXJkIiwgInR3b3RoaXJkcyIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJmZiIsICJmaSIsICJmbCIsICJmZmkiLCAiZmZsIiwgInBhcmVubGVmdGluZmVyaW9yIiwgIiIsICJwYXJlbnJpZ2h0aW5mZXJpb3IiLCAiQ2lyY3VtZmxleHNtYWxsIiwgImh5cGhlbmluZmVyaW9yIiwgIkdyYXZlc21hbGwiLCAiQXNtYWxsIiwgIkJzbWFsbCIsICJDc21hbGwiLCAiRHNtYWxsIiwgIkVzbWFsbCIsICJGc21hbGwiLCAiR3NtYWxsIiwgIkhzbWFsbCIsICJJc21hbGwiLCAiSnNtYWxsIiwgIktzbWFsbCIsICJMc21hbGwiLCAiTXNtYWxsIiwgIk5zbWFsbCIsICJPc21hbGwiLCAiUHNtYWxsIiwgIlFzbWFsbCIsICJSc21hbGwiLCAiU3NtYWxsIiwgIlRzbWFsbCIsICJVc21hbGwiLCAiVnNtYWxsIiwgIldzbWFsbCIsICJYc21hbGwiLCAiWXNtYWxsIiwgIlpzbWFsbCIsICJjb2xvbm1vbmV0YXJ5IiwgIm9uZWZpdHRlZCIsICJydXBpYWgiLCAiVGlsZGVzbWFsbCIsICIiLCAiIiwgImFzdXBlcmlvciIsICJjZW50c3VwZXJpb3IiLCAiIiwgIiIsICIiLCAiIiwgIkFhY3V0ZXNtYWxsIiwgIkFncmF2ZXNtYWxsIiwgIkFjaXJjdW1mbGV4c21hbGwiLCAiQWRpZXJlc2lzc21hbGwiLCAiQXRpbGRlc21hbGwiLCAiQXJpbmdzbWFsbCIsICJDY2VkaWxsYXNtYWxsIiwgIkVhY3V0ZXNtYWxsIiwgIkVncmF2ZXNtYWxsIiwgIkVjaXJjdW1mbGV4c21hbGwiLCAiRWRpZXJlc2lzc21hbGwiLCAiSWFjdXRlc21hbGwiLCAiSWdyYXZlc21hbGwiLCAiSWNpcmN1bWZsZXhzbWFsbCIsICJJZGllcmVzaXNzbWFsbCIsICJOdGlsZGVzbWFsbCIsICJPYWN1dGVzbWFsbCIsICJPZ3JhdmVzbWFsbCIsICJPY2lyY3VtZmxleHNtYWxsIiwgIk9kaWVyZXNpc3NtYWxsIiwgIk90aWxkZXNtYWxsIiwgIlVhY3V0ZXNtYWxsIiwgIlVncmF2ZXNtYWxsIiwgIlVjaXJjdW1mbGV4c21hbGwiLCAiVWRpZXJlc2lzc21hbGwiLCAiIiwgImVpZ2h0c3VwZXJpb3IiLCAiZm91cmluZmVyaW9yIiwgInRocmVlaW5mZXJpb3IiLCAic2l4aW5mZXJpb3IiLCAiZWlnaHRpbmZlcmlvciIsICJzZXZlbmluZmVyaW9yIiwgIlNjYXJvbnNtYWxsIiwgIiIsICJjZW50aW5mZXJpb3IiLCAidHdvaW5mZXJpb3IiLCAiIiwgIkRpZXJlc2lzc21hbGwiLCAiIiwgIkNhcm9uc21hbGwiLCAib3N1cGVyaW9yIiwgImZpdmVpbmZlcmlvciIsICIiLCAiY29tbWFpbmZlcmlvciIsICJwZXJpb2RpbmZlcmlvciIsICJZYWN1dGVzbWFsbCIsICIiLCAiZG9sbGFyaW5mZXJpb3IiLCAiIiwgIiIsICJUaG9ybnNtYWxsIiwgIiIsICJuaW5laW5mZXJpb3IiLCAiemVyb2luZmVyaW9yIiwgIlpjYXJvbnNtYWxsIiwgIkFFc21hbGwiLCAiT3NsYXNoc21hbGwiLCAicXVlc3Rpb25kb3duc21hbGwiLCAib25laW5mZXJpb3IiLCAiTHNsYXNoc21hbGwiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiQ2VkaWxsYXNtYWxsIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiT0VzbWFsbCIsICJmaWd1cmVkYXNoIiwgImh5cGhlbnN1cGVyaW9yIiwgIiIsICIiLCAiIiwgIiIsICJleGNsYW1kb3duc21hbGwiLCAiIiwgIllkaWVyZXNpc3NtYWxsIiwgIiIsICJvbmVzdXBlcmlvciIsICJ0d29zdXBlcmlvciIsICJ0aHJlZXN1cGVyaW9yIiwgImZvdXJzdXBlcmlvciIsICJmaXZlc3VwZXJpb3IiLCAic2l4c3VwZXJpb3IiLCAic2V2ZW5zdXBlcmlvciIsICJuaW5lc3VwZXJpb3IiLCAiemVyb3N1cGVyaW9yIiwgIiIsICJlc3VwZXJpb3IiLCAicnN1cGVyaW9yIiwgInRzdXBlcmlvciIsICIiLCAiIiwgImlzdXBlcmlvciIsICJzc3VwZXJpb3IiLCAiZHN1cGVyaW9yIiwgIiIsICIiLCAiIiwgIiIsICIiLCAibHN1cGVyaW9yIiwgIk9nb25la3NtYWxsIiwgIkJyZXZlc21hbGwiLCAiTWFjcm9uc21hbGwiLCAiYnN1cGVyaW9yIiwgIm5zdXBlcmlvciIsICJtc3VwZXJpb3IiLCAiY29tbWFzdXBlcmlvciIsICJwZXJpb2RzdXBlcmlvciIsICJEb3RhY2NlbnRzbWFsbCIsICJSaW5nc21hbGwiLCAiIiwgIiIsICIiLCAiIl07CmNvbnN0IE1hY1JvbWFuRW5jb2RpbmcgPSBbIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAic3BhY2UiLCAiZXhjbGFtIiwgInF1b3RlZGJsIiwgIm51bWJlcnNpZ24iLCAiZG9sbGFyIiwgInBlcmNlbnQiLCAiYW1wZXJzYW5kIiwgInF1b3Rlc2luZ2xlIiwgInBhcmVubGVmdCIsICJwYXJlbnJpZ2h0IiwgImFzdGVyaXNrIiwgInBsdXMiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJzbGFzaCIsICJ6ZXJvIiwgIm9uZSIsICJ0d28iLCAidGhyZWUiLCAiZm91ciIsICJmaXZlIiwgInNpeCIsICJzZXZlbiIsICJlaWdodCIsICJuaW5lIiwgImNvbG9uIiwgInNlbWljb2xvbiIsICJsZXNzIiwgImVxdWFsIiwgImdyZWF0ZXIiLCAicXVlc3Rpb24iLCAiYXQiLCAiQSIsICJCIiwgIkMiLCAiRCIsICJFIiwgIkYiLCAiRyIsICJIIiwgIkkiLCAiSiIsICJLIiwgIkwiLCAiTSIsICJOIiwgIk8iLCAiUCIsICJRIiwgIlIiLCAiUyIsICJUIiwgIlUiLCAiViIsICJXIiwgIlgiLCAiWSIsICJaIiwgImJyYWNrZXRsZWZ0IiwgImJhY2tzbGFzaCIsICJicmFja2V0cmlnaHQiLCAiYXNjaWljaXJjdW0iLCAidW5kZXJzY29yZSIsICJncmF2ZSIsICJhIiwgImIiLCAiYyIsICJkIiwgImUiLCAiZiIsICJnIiwgImgiLCAiaSIsICJqIiwgImsiLCAibCIsICJtIiwgIm4iLCAibyIsICJwIiwgInEiLCAiciIsICJzIiwgInQiLCAidSIsICJ2IiwgInciLCAieCIsICJ5IiwgInoiLCAiYnJhY2VsZWZ0IiwgImJhciIsICJicmFjZXJpZ2h0IiwgImFzY2lpdGlsZGUiLCAiIiwgIkFkaWVyZXNpcyIsICJBcmluZyIsICJDY2VkaWxsYSIsICJFYWN1dGUiLCAiTnRpbGRlIiwgIk9kaWVyZXNpcyIsICJVZGllcmVzaXMiLCAiYWFjdXRlIiwgImFncmF2ZSIsICJhY2lyY3VtZmxleCIsICJhZGllcmVzaXMiLCAiYXRpbGRlIiwgImFyaW5nIiwgImNjZWRpbGxhIiwgImVhY3V0ZSIsICJlZ3JhdmUiLCAiZWNpcmN1bWZsZXgiLCAiZWRpZXJlc2lzIiwgImlhY3V0ZSIsICJpZ3JhdmUiLCAiaWNpcmN1bWZsZXgiLCAiaWRpZXJlc2lzIiwgIm50aWxkZSIsICJvYWN1dGUiLCAib2dyYXZlIiwgIm9jaXJjdW1mbGV4IiwgIm9kaWVyZXNpcyIsICJvdGlsZGUiLCAidWFjdXRlIiwgInVncmF2ZSIsICJ1Y2lyY3VtZmxleCIsICJ1ZGllcmVzaXMiLCAiZGFnZ2VyIiwgImRlZ3JlZSIsICJjZW50IiwgInN0ZXJsaW5nIiwgInNlY3Rpb24iLCAiYnVsbGV0IiwgInBhcmFncmFwaCIsICJnZXJtYW5kYmxzIiwgInJlZ2lzdGVyZWQiLCAiY29weXJpZ2h0IiwgInRyYWRlbWFyayIsICJhY3V0ZSIsICJkaWVyZXNpcyIsICJub3RlcXVhbCIsICJBRSIsICJPc2xhc2giLCAiaW5maW5pdHkiLCAicGx1c21pbnVzIiwgImxlc3NlcXVhbCIsICJncmVhdGVyZXF1YWwiLCAieWVuIiwgIm11IiwgInBhcnRpYWxkaWZmIiwgInN1bW1hdGlvbiIsICJwcm9kdWN0IiwgInBpIiwgImludGVncmFsIiwgIm9yZGZlbWluaW5lIiwgIm9yZG1hc2N1bGluZSIsICJPbWVnYSIsICJhZSIsICJvc2xhc2giLCAicXVlc3Rpb25kb3duIiwgImV4Y2xhbWRvd24iLCAibG9naWNhbG5vdCIsICJyYWRpY2FsIiwgImZsb3JpbiIsICJhcHByb3hlcXVhbCIsICJEZWx0YSIsICJndWlsbGVtb3RsZWZ0IiwgImd1aWxsZW1vdHJpZ2h0IiwgImVsbGlwc2lzIiwgInNwYWNlIiwgIkFncmF2ZSIsICJBdGlsZGUiLCAiT3RpbGRlIiwgIk9FIiwgIm9lIiwgImVuZGFzaCIsICJlbWRhc2giLCAicXVvdGVkYmxsZWZ0IiwgInF1b3RlZGJscmlnaHQiLCAicXVvdGVsZWZ0IiwgInF1b3RlcmlnaHQiLCAiZGl2aWRlIiwgImxvemVuZ2UiLCAieWRpZXJlc2lzIiwgIllkaWVyZXNpcyIsICJmcmFjdGlvbiIsICJjdXJyZW5jeSIsICJndWlsc2luZ2xsZWZ0IiwgImd1aWxzaW5nbHJpZ2h0IiwgImZpIiwgImZsIiwgImRhZ2dlcmRibCIsICJwZXJpb2RjZW50ZXJlZCIsICJxdW90ZXNpbmdsYmFzZSIsICJxdW90ZWRibGJhc2UiLCAicGVydGhvdXNhbmQiLCAiQWNpcmN1bWZsZXgiLCAiRWNpcmN1bWZsZXgiLCAiQWFjdXRlIiwgIkVkaWVyZXNpcyIsICJFZ3JhdmUiLCAiSWFjdXRlIiwgIkljaXJjdW1mbGV4IiwgIklkaWVyZXNpcyIsICJJZ3JhdmUiLCAiT2FjdXRlIiwgIk9jaXJjdW1mbGV4IiwgImFwcGxlIiwgIk9ncmF2ZSIsICJVYWN1dGUiLCAiVWNpcmN1bWZsZXgiLCAiVWdyYXZlIiwgImRvdGxlc3NpIiwgImNpcmN1bWZsZXgiLCAidGlsZGUiLCAibWFjcm9uIiwgImJyZXZlIiwgImRvdGFjY2VudCIsICJyaW5nIiwgImNlZGlsbGEiLCAiaHVuZ2FydW1sYXV0IiwgIm9nb25layIsICJjYXJvbiJdOwpleHBvcnRzLk1hY1JvbWFuRW5jb2RpbmcgPSBNYWNSb21hbkVuY29kaW5nOwpjb25zdCBTdGFuZGFyZEVuY29kaW5nID0gWyIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgInNwYWNlIiwgImV4Y2xhbSIsICJxdW90ZWRibCIsICJudW1iZXJzaWduIiwgImRvbGxhciIsICJwZXJjZW50IiwgImFtcGVyc2FuZCIsICJxdW90ZXJpZ2h0IiwgInBhcmVubGVmdCIsICJwYXJlbnJpZ2h0IiwgImFzdGVyaXNrIiwgInBsdXMiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJzbGFzaCIsICJ6ZXJvIiwgIm9uZSIsICJ0d28iLCAidGhyZWUiLCAiZm91ciIsICJmaXZlIiwgInNpeCIsICJzZXZlbiIsICJlaWdodCIsICJuaW5lIiwgImNvbG9uIiwgInNlbWljb2xvbiIsICJsZXNzIiwgImVxdWFsIiwgImdyZWF0ZXIiLCAicXVlc3Rpb24iLCAiYXQiLCAiQSIsICJCIiwgIkMiLCAiRCIsICJFIiwgIkYiLCAiRyIsICJIIiwgIkkiLCAiSiIsICJLIiwgIkwiLCAiTSIsICJOIiwgIk8iLCAiUCIsICJRIiwgIlIiLCAiUyIsICJUIiwgIlUiLCAiViIsICJXIiwgIlgiLCAiWSIsICJaIiwgImJyYWNrZXRsZWZ0IiwgImJhY2tzbGFzaCIsICJicmFja2V0cmlnaHQiLCAiYXNjaWljaXJjdW0iLCAidW5kZXJzY29yZSIsICJxdW90ZWxlZnQiLCAiYSIsICJiIiwgImMiLCAiZCIsICJlIiwgImYiLCAiZyIsICJoIiwgImkiLCAiaiIsICJrIiwgImwiLCAibSIsICJuIiwgIm8iLCAicCIsICJxIiwgInIiLCAicyIsICJ0IiwgInUiLCAidiIsICJ3IiwgIngiLCAieSIsICJ6IiwgImJyYWNlbGVmdCIsICJiYXIiLCAiYnJhY2VyaWdodCIsICJhc2NpaXRpbGRlIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJleGNsYW1kb3duIiwgImNlbnQiLCAic3RlcmxpbmciLCAiZnJhY3Rpb24iLCAieWVuIiwgImZsb3JpbiIsICJzZWN0aW9uIiwgImN1cnJlbmN5IiwgInF1b3Rlc2luZ2xlIiwgInF1b3RlZGJsbGVmdCIsICJndWlsbGVtb3RsZWZ0IiwgImd1aWxzaW5nbGxlZnQiLCAiZ3VpbHNpbmdscmlnaHQiLCAiZmkiLCAiZmwiLCAiIiwgImVuZGFzaCIsICJkYWdnZXIiLCAiZGFnZ2VyZGJsIiwgInBlcmlvZGNlbnRlcmVkIiwgIiIsICJwYXJhZ3JhcGgiLCAiYnVsbGV0IiwgInF1b3Rlc2luZ2xiYXNlIiwgInF1b3RlZGJsYmFzZSIsICJxdW90ZWRibHJpZ2h0IiwgImd1aWxsZW1vdHJpZ2h0IiwgImVsbGlwc2lzIiwgInBlcnRob3VzYW5kIiwgIiIsICJxdWVzdGlvbmRvd24iLCAiIiwgImdyYXZlIiwgImFjdXRlIiwgImNpcmN1bWZsZXgiLCAidGlsZGUiLCAibWFjcm9uIiwgImJyZXZlIiwgImRvdGFjY2VudCIsICJkaWVyZXNpcyIsICIiLCAicmluZyIsICJjZWRpbGxhIiwgIiIsICJodW5nYXJ1bWxhdXQiLCAib2dvbmVrIiwgImNhcm9uIiwgImVtZGFzaCIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiQUUiLCAiIiwgIm9yZGZlbWluaW5lIiwgIiIsICIiLCAiIiwgIiIsICJMc2xhc2giLCAiT3NsYXNoIiwgIk9FIiwgIm9yZG1hc2N1bGluZSIsICIiLCAiIiwgIiIsICIiLCAiIiwgImFlIiwgIiIsICIiLCAiIiwgImRvdGxlc3NpIiwgIiIsICIiLCAibHNsYXNoIiwgIm9zbGFzaCIsICJvZSIsICJnZXJtYW5kYmxzIiwgIiIsICIiLCAiIiwgIiJdOwpleHBvcnRzLlN0YW5kYXJkRW5jb2RpbmcgPSBTdGFuZGFyZEVuY29kaW5nOwpjb25zdCBXaW5BbnNpRW5jb2RpbmcgPSBbIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAic3BhY2UiLCAiZXhjbGFtIiwgInF1b3RlZGJsIiwgIm51bWJlcnNpZ24iLCAiZG9sbGFyIiwgInBlcmNlbnQiLCAiYW1wZXJzYW5kIiwgInF1b3Rlc2luZ2xlIiwgInBhcmVubGVmdCIsICJwYXJlbnJpZ2h0IiwgImFzdGVyaXNrIiwgInBsdXMiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJzbGFzaCIsICJ6ZXJvIiwgIm9uZSIsICJ0d28iLCAidGhyZWUiLCAiZm91ciIsICJmaXZlIiwgInNpeCIsICJzZXZlbiIsICJlaWdodCIsICJuaW5lIiwgImNvbG9uIiwgInNlbWljb2xvbiIsICJsZXNzIiwgImVxdWFsIiwgImdyZWF0ZXIiLCAicXVlc3Rpb24iLCAiYXQiLCAiQSIsICJCIiwgIkMiLCAiRCIsICJFIiwgIkYiLCAiRyIsICJIIiwgIkkiLCAiSiIsICJLIiwgIkwiLCAiTSIsICJOIiwgIk8iLCAiUCIsICJRIiwgIlIiLCAiUyIsICJUIiwgIlUiLCAiViIsICJXIiwgIlgiLCAiWSIsICJaIiwgImJyYWNrZXRsZWZ0IiwgImJhY2tzbGFzaCIsICJicmFja2V0cmlnaHQiLCAiYXNjaWljaXJjdW0iLCAidW5kZXJzY29yZSIsICJncmF2ZSIsICJhIiwgImIiLCAiYyIsICJkIiwgImUiLCAiZiIsICJnIiwgImgiLCAiaSIsICJqIiwgImsiLCAibCIsICJtIiwgIm4iLCAibyIsICJwIiwgInEiLCAiciIsICJzIiwgInQiLCAidSIsICJ2IiwgInciLCAieCIsICJ5IiwgInoiLCAiYnJhY2VsZWZ0IiwgImJhciIsICJicmFjZXJpZ2h0IiwgImFzY2lpdGlsZGUiLCAiYnVsbGV0IiwgIkV1cm8iLCAiYnVsbGV0IiwgInF1b3Rlc2luZ2xiYXNlIiwgImZsb3JpbiIsICJxdW90ZWRibGJhc2UiLCAiZWxsaXBzaXMiLCAiZGFnZ2VyIiwgImRhZ2dlcmRibCIsICJjaXJjdW1mbGV4IiwgInBlcnRob3VzYW5kIiwgIlNjYXJvbiIsICJndWlsc2luZ2xsZWZ0IiwgIk9FIiwgImJ1bGxldCIsICJaY2Fyb24iLCAiYnVsbGV0IiwgImJ1bGxldCIsICJxdW90ZWxlZnQiLCAicXVvdGVyaWdodCIsICJxdW90ZWRibGxlZnQiLCAicXVvdGVkYmxyaWdodCIsICJidWxsZXQiLCAiZW5kYXNoIiwgImVtZGFzaCIsICJ0aWxkZSIsICJ0cmFkZW1hcmsiLCAic2Nhcm9uIiwgImd1aWxzaW5nbHJpZ2h0IiwgIm9lIiwgImJ1bGxldCIsICJ6Y2Fyb24iLCAiWWRpZXJlc2lzIiwgInNwYWNlIiwgImV4Y2xhbWRvd24iLCAiY2VudCIsICJzdGVybGluZyIsICJjdXJyZW5jeSIsICJ5ZW4iLCAiYnJva2VuYmFyIiwgInNlY3Rpb24iLCAiZGllcmVzaXMiLCAiY29weXJpZ2h0IiwgIm9yZGZlbWluaW5lIiwgImd1aWxsZW1vdGxlZnQiLCAibG9naWNhbG5vdCIsICJoeXBoZW4iLCAicmVnaXN0ZXJlZCIsICJtYWNyb24iLCAiZGVncmVlIiwgInBsdXNtaW51cyIsICJ0d29zdXBlcmlvciIsICJ0aHJlZXN1cGVyaW9yIiwgImFjdXRlIiwgIm11IiwgInBhcmFncmFwaCIsICJwZXJpb2RjZW50ZXJlZCIsICJjZWRpbGxhIiwgIm9uZXN1cGVyaW9yIiwgIm9yZG1hc2N1bGluZSIsICJndWlsbGVtb3RyaWdodCIsICJvbmVxdWFydGVyIiwgIm9uZWhhbGYiLCAidGhyZWVxdWFydGVycyIsICJxdWVzdGlvbmRvd24iLCAiQWdyYXZlIiwgIkFhY3V0ZSIsICJBY2lyY3VtZmxleCIsICJBdGlsZGUiLCAiQWRpZXJlc2lzIiwgIkFyaW5nIiwgIkFFIiwgIkNjZWRpbGxhIiwgIkVncmF2ZSIsICJFYWN1dGUiLCAiRWNpcmN1bWZsZXgiLCAiRWRpZXJlc2lzIiwgIklncmF2ZSIsICJJYWN1dGUiLCAiSWNpcmN1bWZsZXgiLCAiSWRpZXJlc2lzIiwgIkV0aCIsICJOdGlsZGUiLCAiT2dyYXZlIiwgIk9hY3V0ZSIsICJPY2lyY3VtZmxleCIsICJPdGlsZGUiLCAiT2RpZXJlc2lzIiwgIm11bHRpcGx5IiwgIk9zbGFzaCIsICJVZ3JhdmUiLCAiVWFjdXRlIiwgIlVjaXJjdW1mbGV4IiwgIlVkaWVyZXNpcyIsICJZYWN1dGUiLCAiVGhvcm4iLCAiZ2VybWFuZGJscyIsICJhZ3JhdmUiLCAiYWFjdXRlIiwgImFjaXJjdW1mbGV4IiwgImF0aWxkZSIsICJhZGllcmVzaXMiLCAiYXJpbmciLCAiYWUiLCAiY2NlZGlsbGEiLCAiZWdyYXZlIiwgImVhY3V0ZSIsICJlY2lyY3VtZmxleCIsICJlZGllcmVzaXMiLCAiaWdyYXZlIiwgImlhY3V0ZSIsICJpY2lyY3VtZmxleCIsICJpZGllcmVzaXMiLCAiZXRoIiwgIm50aWxkZSIsICJvZ3JhdmUiLCAib2FjdXRlIiwgIm9jaXJjdW1mbGV4IiwgIm90aWxkZSIsICJvZGllcmVzaXMiLCAiZGl2aWRlIiwgIm9zbGFzaCIsICJ1Z3JhdmUiLCAidWFjdXRlIiwgInVjaXJjdW1mbGV4IiwgInVkaWVyZXNpcyIsICJ5YWN1dGUiLCAidGhvcm4iLCAieWRpZXJlc2lzIl07CmV4cG9ydHMuV2luQW5zaUVuY29kaW5nID0gV2luQW5zaUVuY29kaW5nOwpjb25zdCBTeW1ib2xTZXRFbmNvZGluZyA9IFsiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJzcGFjZSIsICJleGNsYW0iLCAidW5pdmVyc2FsIiwgIm51bWJlcnNpZ24iLCAiZXhpc3RlbnRpYWwiLCAicGVyY2VudCIsICJhbXBlcnNhbmQiLCAic3VjaHRoYXQiLCAicGFyZW5sZWZ0IiwgInBhcmVucmlnaHQiLCAiYXN0ZXJpc2ttYXRoIiwgInBsdXMiLCAiY29tbWEiLCAibWludXMiLCAicGVyaW9kIiwgInNsYXNoIiwgInplcm8iLCAib25lIiwgInR3byIsICJ0aHJlZSIsICJmb3VyIiwgImZpdmUiLCAic2l4IiwgInNldmVuIiwgImVpZ2h0IiwgIm5pbmUiLCAiY29sb24iLCAic2VtaWNvbG9uIiwgImxlc3MiLCAiZXF1YWwiLCAiZ3JlYXRlciIsICJxdWVzdGlvbiIsICJjb25ncnVlbnQiLCAiQWxwaGEiLCAiQmV0YSIsICJDaGkiLCAiRGVsdGEiLCAiRXBzaWxvbiIsICJQaGkiLCAiR2FtbWEiLCAiRXRhIiwgIklvdGEiLCAidGhldGExIiwgIkthcHBhIiwgIkxhbWJkYSIsICJNdSIsICJOdSIsICJPbWljcm9uIiwgIlBpIiwgIlRoZXRhIiwgIlJobyIsICJTaWdtYSIsICJUYXUiLCAiVXBzaWxvbiIsICJzaWdtYTEiLCAiT21lZ2EiLCAiWGkiLCAiUHNpIiwgIlpldGEiLCAiYnJhY2tldGxlZnQiLCAidGhlcmVmb3JlIiwgImJyYWNrZXRyaWdodCIsICJwZXJwZW5kaWN1bGFyIiwgInVuZGVyc2NvcmUiLCAicmFkaWNhbGV4IiwgImFscGhhIiwgImJldGEiLCAiY2hpIiwgImRlbHRhIiwgImVwc2lsb24iLCAicGhpIiwgImdhbW1hIiwgImV0YSIsICJpb3RhIiwgInBoaTEiLCAia2FwcGEiLCAibGFtYmRhIiwgIm11IiwgIm51IiwgIm9taWNyb24iLCAicGkiLCAidGhldGEiLCAicmhvIiwgInNpZ21hIiwgInRhdSIsICJ1cHNpbG9uIiwgIm9tZWdhMSIsICJvbWVnYSIsICJ4aSIsICJwc2kiLCAiemV0YSIsICJicmFjZWxlZnQiLCAiYmFyIiwgImJyYWNlcmlnaHQiLCAic2ltaWxhciIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJFdXJvIiwgIlVwc2lsb24xIiwgIm1pbnV0ZSIsICJsZXNzZXF1YWwiLCAiZnJhY3Rpb24iLCAiaW5maW5pdHkiLCAiZmxvcmluIiwgImNsdWIiLCAiZGlhbW9uZCIsICJoZWFydCIsICJzcGFkZSIsICJhcnJvd2JvdGgiLCAiYXJyb3dsZWZ0IiwgImFycm93dXAiLCAiYXJyb3dyaWdodCIsICJhcnJvd2Rvd24iLCAiZGVncmVlIiwgInBsdXNtaW51cyIsICJzZWNvbmQiLCAiZ3JlYXRlcmVxdWFsIiwgIm11bHRpcGx5IiwgInByb3BvcnRpb25hbCIsICJwYXJ0aWFsZGlmZiIsICJidWxsZXQiLCAiZGl2aWRlIiwgIm5vdGVxdWFsIiwgImVxdWl2YWxlbmNlIiwgImFwcHJveGVxdWFsIiwgImVsbGlwc2lzIiwgImFycm93dmVydGV4IiwgImFycm93aG9yaXpleCIsICJjYXJyaWFnZXJldHVybiIsICJhbGVwaCIsICJJZnJha3R1ciIsICJSZnJha3R1ciIsICJ3ZWllcnN0cmFzcyIsICJjaXJjbGVtdWx0aXBseSIsICJjaXJjbGVwbHVzIiwgImVtcHR5c2V0IiwgImludGVyc2VjdGlvbiIsICJ1bmlvbiIsICJwcm9wZXJzdXBlcnNldCIsICJyZWZsZXhzdXBlcnNldCIsICJub3RzdWJzZXQiLCAicHJvcGVyc3Vic2V0IiwgInJlZmxleHN1YnNldCIsICJlbGVtZW50IiwgIm5vdGVsZW1lbnQiLCAiYW5nbGUiLCAiZ3JhZGllbnQiLCAicmVnaXN0ZXJzZXJpZiIsICJjb3B5cmlnaHRzZXJpZiIsICJ0cmFkZW1hcmtzZXJpZiIsICJwcm9kdWN0IiwgInJhZGljYWwiLCAiZG90bWF0aCIsICJsb2dpY2Fsbm90IiwgImxvZ2ljYWxhbmQiLCAibG9naWNhbG9yIiwgImFycm93ZGJsYm90aCIsICJhcnJvd2RibGxlZnQiLCAiYXJyb3dkYmx1cCIsICJhcnJvd2RibHJpZ2h0IiwgImFycm93ZGJsZG93biIsICJsb3plbmdlIiwgImFuZ2xlbGVmdCIsICJyZWdpc3RlcnNhbnMiLCAiY29weXJpZ2h0c2FucyIsICJ0cmFkZW1hcmtzYW5zIiwgInN1bW1hdGlvbiIsICJwYXJlbmxlZnR0cCIsICJwYXJlbmxlZnRleCIsICJwYXJlbmxlZnRidCIsICJicmFja2V0bGVmdHRwIiwgImJyYWNrZXRsZWZ0ZXgiLCAiYnJhY2tldGxlZnRidCIsICJicmFjZWxlZnR0cCIsICJicmFjZWxlZnRtaWQiLCAiYnJhY2VsZWZ0YnQiLCAiYnJhY2VleCIsICIiLCAiYW5nbGVyaWdodCIsICJpbnRlZ3JhbCIsICJpbnRlZ3JhbHRwIiwgImludGVncmFsZXgiLCAiaW50ZWdyYWxidCIsICJwYXJlbnJpZ2h0dHAiLCAicGFyZW5yaWdodGV4IiwgInBhcmVucmlnaHRidCIsICJicmFja2V0cmlnaHR0cCIsICJicmFja2V0cmlnaHRleCIsICJicmFja2V0cmlnaHRidCIsICJicmFjZXJpZ2h0dHAiLCAiYnJhY2VyaWdodG1pZCIsICJicmFjZXJpZ2h0YnQiLCAiIl07CmV4cG9ydHMuU3ltYm9sU2V0RW5jb2RpbmcgPSBTeW1ib2xTZXRFbmNvZGluZzsKY29uc3QgWmFwZkRpbmdiYXRzRW5jb2RpbmcgPSBbIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAic3BhY2UiLCAiYTEiLCAiYTIiLCAiYTIwMiIsICJhMyIsICJhNCIsICJhNSIsICJhMTE5IiwgImExMTgiLCAiYTExNyIsICJhMTEiLCAiYTEyIiwgImExMyIsICJhMTQiLCAiYTE1IiwgImExNiIsICJhMTA1IiwgImExNyIsICJhMTgiLCAiYTE5IiwgImEyMCIsICJhMjEiLCAiYTIyIiwgImEyMyIsICJhMjQiLCAiYTI1IiwgImEyNiIsICJhMjciLCAiYTI4IiwgImE2IiwgImE3IiwgImE4IiwgImE5IiwgImExMCIsICJhMjkiLCAiYTMwIiwgImEzMSIsICJhMzIiLCAiYTMzIiwgImEzNCIsICJhMzUiLCAiYTM2IiwgImEzNyIsICJhMzgiLCAiYTM5IiwgImE0MCIsICJhNDEiLCAiYTQyIiwgImE0MyIsICJhNDQiLCAiYTQ1IiwgImE0NiIsICJhNDciLCAiYTQ4IiwgImE0OSIsICJhNTAiLCAiYTUxIiwgImE1MiIsICJhNTMiLCAiYTU0IiwgImE1NSIsICJhNTYiLCAiYTU3IiwgImE1OCIsICJhNTkiLCAiYTYwIiwgImE2MSIsICJhNjIiLCAiYTYzIiwgImE2NCIsICJhNjUiLCAiYTY2IiwgImE2NyIsICJhNjgiLCAiYTY5IiwgImE3MCIsICJhNzEiLCAiYTcyIiwgImE3MyIsICJhNzQiLCAiYTIwMyIsICJhNzUiLCAiYTIwNCIsICJhNzYiLCAiYTc3IiwgImE3OCIsICJhNzkiLCAiYTgxIiwgImE4MiIsICJhODMiLCAiYTg0IiwgImE5NyIsICJhOTgiLCAiYTk5IiwgImExMDAiLCAiIiwgImE4OSIsICJhOTAiLCAiYTkzIiwgImE5NCIsICJhOTEiLCAiYTkyIiwgImEyMDUiLCAiYTg1IiwgImEyMDYiLCAiYTg2IiwgImE4NyIsICJhODgiLCAiYTk1IiwgImE5NiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiYTEwMSIsICJhMTAyIiwgImExMDMiLCAiYTEwNCIsICJhMTA2IiwgImExMDciLCAiYTEwOCIsICJhMTEyIiwgImExMTEiLCAiYTExMCIsICJhMTA5IiwgImExMjAiLCAiYTEyMSIsICJhMTIyIiwgImExMjMiLCAiYTEyNCIsICJhMTI1IiwgImExMjYiLCAiYTEyNyIsICJhMTI4IiwgImExMjkiLCAiYTEzMCIsICJhMTMxIiwgImExMzIiLCAiYTEzMyIsICJhMTM0IiwgImExMzUiLCAiYTEzNiIsICJhMTM3IiwgImExMzgiLCAiYTEzOSIsICJhMTQwIiwgImExNDEiLCAiYTE0MiIsICJhMTQzIiwgImExNDQiLCAiYTE0NSIsICJhMTQ2IiwgImExNDciLCAiYTE0OCIsICJhMTQ5IiwgImExNTAiLCAiYTE1MSIsICJhMTUyIiwgImExNTMiLCAiYTE1NCIsICJhMTU1IiwgImExNTYiLCAiYTE1NyIsICJhMTU4IiwgImExNTkiLCAiYTE2MCIsICJhMTYxIiwgImExNjMiLCAiYTE2NCIsICJhMTk2IiwgImExNjUiLCAiYTE5MiIsICJhMTY2IiwgImExNjciLCAiYTE2OCIsICJhMTY5IiwgImExNzAiLCAiYTE3MSIsICJhMTcyIiwgImExNzMiLCAiYTE2MiIsICJhMTc0IiwgImExNzUiLCAiYTE3NiIsICJhMTc3IiwgImExNzgiLCAiYTE3OSIsICJhMTkzIiwgImExODAiLCAiYTE5OSIsICJhMTgxIiwgImEyMDAiLCAiYTE4MiIsICIiLCAiYTIwMSIsICJhMTgzIiwgImExODQiLCAiYTE5NyIsICJhMTg1IiwgImExOTQiLCAiYTE5OCIsICJhMTg2IiwgImExOTUiLCAiYTE4NyIsICJhMTg4IiwgImExODkiLCAiYTE5MCIsICJhMTkxIiwgIiJdOwpleHBvcnRzLlphcGZEaW5nYmF0c0VuY29kaW5nID0gWmFwZkRpbmdiYXRzRW5jb2Rpbmc7CmZ1bmN0aW9uIGdldEVuY29kaW5nKGVuY29kaW5nTmFtZSkgewogIHN3aXRjaCAoZW5jb2RpbmdOYW1lKSB7CiAgICBjYXNlICJXaW5BbnNpRW5jb2RpbmciOgogICAgICByZXR1cm4gV2luQW5zaUVuY29kaW5nOwogICAgY2FzZSAiU3RhbmRhcmRFbmNvZGluZyI6CiAgICAgIHJldHVybiBTdGFuZGFyZEVuY29kaW5nOwogICAgY2FzZSAiTWFjUm9tYW5FbmNvZGluZyI6CiAgICAgIHJldHVybiBNYWNSb21hbkVuY29kaW5nOwogICAgY2FzZSAiU3ltYm9sU2V0RW5jb2RpbmciOgogICAgICByZXR1cm4gU3ltYm9sU2V0RW5jb2Rpbmc7CiAgICBjYXNlICJaYXBmRGluZ2JhdHNFbmNvZGluZyI6CiAgICAgIHJldHVybiBaYXBmRGluZ2JhdHNFbmNvZGluZzsKICAgIGNhc2UgIkV4cGVydEVuY29kaW5nIjoKICAgICAgcmV0dXJuIEV4cGVydEVuY29kaW5nOwogICAgY2FzZSAiTWFjRXhwZXJ0RW5jb2RpbmciOgogICAgICByZXR1cm4gTWFjRXhwZXJ0RW5jb2Rpbmc7CiAgICBkZWZhdWx0OgogICAgICByZXR1cm4gbnVsbDsKICB9Cn0KCi8qKiovIH0pLAovKiAxNzMgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlNFQUNfQU5BTFlTSVNfRU5BQkxFRCA9IGV4cG9ydHMuTWFjU3RhbmRhcmRHbHlwaE9yZGVyaW5nID0gZXhwb3J0cy5Gb250RmxhZ3MgPSB2b2lkIDA7CmV4cG9ydHMubm9ybWFsaXplRm9udE5hbWUgPSBub3JtYWxpemVGb250TmFtZTsKZXhwb3J0cy5yZWNvdmVyR2x5cGhOYW1lID0gcmVjb3ZlckdseXBoTmFtZTsKZXhwb3J0cy50eXBlMUZvbnRHbHlwaE1hcHBpbmcgPSB0eXBlMUZvbnRHbHlwaE1hcHBpbmc7CnZhciBfZW5jb2RpbmdzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNzIpOwp2YXIgX2dseXBobGlzdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMTc0KTsKdmFyIF91bmljb2RlID0gX193X3BkZmpzX3JlcXVpcmVfXygxNzUpOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpjb25zdCBTRUFDX0FOQUxZU0lTX0VOQUJMRUQgPSB0cnVlOwpleHBvcnRzLlNFQUNfQU5BTFlTSVNfRU5BQkxFRCA9IFNFQUNfQU5BTFlTSVNfRU5BQkxFRDsKY29uc3QgRm9udEZsYWdzID0gewogIEZpeGVkUGl0Y2g6IDEsCiAgU2VyaWY6IDIsCiAgU3ltYm9saWM6IDQsCiAgU2NyaXB0OiA4LAogIE5vbnN5bWJvbGljOiAzMiwKICBJdGFsaWM6IDY0LAogIEFsbENhcDogNjU1MzYsCiAgU21hbGxDYXA6IDEzMTA3MiwKICBGb3JjZUJvbGQ6IDI2MjE0NAp9OwpleHBvcnRzLkZvbnRGbGFncyA9IEZvbnRGbGFnczsKY29uc3QgTWFjU3RhbmRhcmRHbHlwaE9yZGVyaW5nID0gWyIubm90ZGVmIiwgIi5udWxsIiwgIm5vbm1hcmtpbmdyZXR1cm4iLCAic3BhY2UiLCAiZXhjbGFtIiwgInF1b3RlZGJsIiwgIm51bWJlcnNpZ24iLCAiZG9sbGFyIiwgInBlcmNlbnQiLCAiYW1wZXJzYW5kIiwgInF1b3Rlc2luZ2xlIiwgInBhcmVubGVmdCIsICJwYXJlbnJpZ2h0IiwgImFzdGVyaXNrIiwgInBsdXMiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJzbGFzaCIsICJ6ZXJvIiwgIm9uZSIsICJ0d28iLCAidGhyZWUiLCAiZm91ciIsICJmaXZlIiwgInNpeCIsICJzZXZlbiIsICJlaWdodCIsICJuaW5lIiwgImNvbG9uIiwgInNlbWljb2xvbiIsICJsZXNzIiwgImVxdWFsIiwgImdyZWF0ZXIiLCAicXVlc3Rpb24iLCAiYXQiLCAiQSIsICJCIiwgIkMiLCAiRCIsICJFIiwgIkYiLCAiRyIsICJIIiwgIkkiLCAiSiIsICJLIiwgIkwiLCAiTSIsICJOIiwgIk8iLCAiUCIsICJRIiwgIlIiLCAiUyIsICJUIiwgIlUiLCAiViIsICJXIiwgIlgiLCAiWSIsICJaIiwgImJyYWNrZXRsZWZ0IiwgImJhY2tzbGFzaCIsICJicmFja2V0cmlnaHQiLCAiYXNjaWljaXJjdW0iLCAidW5kZXJzY29yZSIsICJncmF2ZSIsICJhIiwgImIiLCAiYyIsICJkIiwgImUiLCAiZiIsICJnIiwgImgiLCAiaSIsICJqIiwgImsiLCAibCIsICJtIiwgIm4iLCAibyIsICJwIiwgInEiLCAiciIsICJzIiwgInQiLCAidSIsICJ2IiwgInciLCAieCIsICJ5IiwgInoiLCAiYnJhY2VsZWZ0IiwgImJhciIsICJicmFjZXJpZ2h0IiwgImFzY2lpdGlsZGUiLCAiQWRpZXJlc2lzIiwgIkFyaW5nIiwgIkNjZWRpbGxhIiwgIkVhY3V0ZSIsICJOdGlsZGUiLCAiT2RpZXJlc2lzIiwgIlVkaWVyZXNpcyIsICJhYWN1dGUiLCAiYWdyYXZlIiwgImFjaXJjdW1mbGV4IiwgImFkaWVyZXNpcyIsICJhdGlsZGUiLCAiYXJpbmciLCAiY2NlZGlsbGEiLCAiZWFjdXRlIiwgImVncmF2ZSIsICJlY2lyY3VtZmxleCIsICJlZGllcmVzaXMiLCAiaWFjdXRlIiwgImlncmF2ZSIsICJpY2lyY3VtZmxleCIsICJpZGllcmVzaXMiLCAibnRpbGRlIiwgIm9hY3V0ZSIsICJvZ3JhdmUiLCAib2NpcmN1bWZsZXgiLCAib2RpZXJlc2lzIiwgIm90aWxkZSIsICJ1YWN1dGUiLCAidWdyYXZlIiwgInVjaXJjdW1mbGV4IiwgInVkaWVyZXNpcyIsICJkYWdnZXIiLCAiZGVncmVlIiwgImNlbnQiLCAic3RlcmxpbmciLCAic2VjdGlvbiIsICJidWxsZXQiLCAicGFyYWdyYXBoIiwgImdlcm1hbmRibHMiLCAicmVnaXN0ZXJlZCIsICJjb3B5cmlnaHQiLCAidHJhZGVtYXJrIiwgImFjdXRlIiwgImRpZXJlc2lzIiwgIm5vdGVxdWFsIiwgIkFFIiwgIk9zbGFzaCIsICJpbmZpbml0eSIsICJwbHVzbWludXMiLCAibGVzc2VxdWFsIiwgImdyZWF0ZXJlcXVhbCIsICJ5ZW4iLCAibXUiLCAicGFydGlhbGRpZmYiLCAic3VtbWF0aW9uIiwgInByb2R1Y3QiLCAicGkiLCAiaW50ZWdyYWwiLCAib3JkZmVtaW5pbmUiLCAib3JkbWFzY3VsaW5lIiwgIk9tZWdhIiwgImFlIiwgIm9zbGFzaCIsICJxdWVzdGlvbmRvd24iLCAiZXhjbGFtZG93biIsICJsb2dpY2Fsbm90IiwgInJhZGljYWwiLCAiZmxvcmluIiwgImFwcHJveGVxdWFsIiwgIkRlbHRhIiwgImd1aWxsZW1vdGxlZnQiLCAiZ3VpbGxlbW90cmlnaHQiLCAiZWxsaXBzaXMiLCAibm9uYnJlYWtpbmdzcGFjZSIsICJBZ3JhdmUiLCAiQXRpbGRlIiwgIk90aWxkZSIsICJPRSIsICJvZSIsICJlbmRhc2giLCAiZW1kYXNoIiwgInF1b3RlZGJsbGVmdCIsICJxdW90ZWRibHJpZ2h0IiwgInF1b3RlbGVmdCIsICJxdW90ZXJpZ2h0IiwgImRpdmlkZSIsICJsb3plbmdlIiwgInlkaWVyZXNpcyIsICJZZGllcmVzaXMiLCAiZnJhY3Rpb24iLCAiY3VycmVuY3kiLCAiZ3VpbHNpbmdsbGVmdCIsICJndWlsc2luZ2xyaWdodCIsICJmaSIsICJmbCIsICJkYWdnZXJkYmwiLCAicGVyaW9kY2VudGVyZWQiLCAicXVvdGVzaW5nbGJhc2UiLCAicXVvdGVkYmxiYXNlIiwgInBlcnRob3VzYW5kIiwgIkFjaXJjdW1mbGV4IiwgIkVjaXJjdW1mbGV4IiwgIkFhY3V0ZSIsICJFZGllcmVzaXMiLCAiRWdyYXZlIiwgIklhY3V0ZSIsICJJY2lyY3VtZmxleCIsICJJZGllcmVzaXMiLCAiSWdyYXZlIiwgIk9hY3V0ZSIsICJPY2lyY3VtZmxleCIsICJhcHBsZSIsICJPZ3JhdmUiLCAiVWFjdXRlIiwgIlVjaXJjdW1mbGV4IiwgIlVncmF2ZSIsICJkb3RsZXNzaSIsICJjaXJjdW1mbGV4IiwgInRpbGRlIiwgIm1hY3JvbiIsICJicmV2ZSIsICJkb3RhY2NlbnQiLCAicmluZyIsICJjZWRpbGxhIiwgImh1bmdhcnVtbGF1dCIsICJvZ29uZWsiLCAiY2Fyb24iLCAiTHNsYXNoIiwgImxzbGFzaCIsICJTY2Fyb24iLCAic2Nhcm9uIiwgIlpjYXJvbiIsICJ6Y2Fyb24iLCAiYnJva2VuYmFyIiwgIkV0aCIsICJldGgiLCAiWWFjdXRlIiwgInlhY3V0ZSIsICJUaG9ybiIsICJ0aG9ybiIsICJtaW51cyIsICJtdWx0aXBseSIsICJvbmVzdXBlcmlvciIsICJ0d29zdXBlcmlvciIsICJ0aHJlZXN1cGVyaW9yIiwgIm9uZWhhbGYiLCAib25lcXVhcnRlciIsICJ0aHJlZXF1YXJ0ZXJzIiwgImZyYW5jIiwgIkdicmV2ZSIsICJnYnJldmUiLCAiSWRvdGFjY2VudCIsICJTY2VkaWxsYSIsICJzY2VkaWxsYSIsICJDYWN1dGUiLCAiY2FjdXRlIiwgIkNjYXJvbiIsICJjY2Fyb24iLCAiZGNyb2F0Il07CmV4cG9ydHMuTWFjU3RhbmRhcmRHbHlwaE9yZGVyaW5nID0gTWFjU3RhbmRhcmRHbHlwaE9yZGVyaW5nOwpmdW5jdGlvbiByZWNvdmVyR2x5cGhOYW1lKG5hbWUsIGdseXBoc1VuaWNvZGVNYXApIHsKICBpZiAoZ2x5cGhzVW5pY29kZU1hcFtuYW1lXSAhPT0gdW5kZWZpbmVkKSB7CiAgICByZXR1cm4gbmFtZTsKICB9CiAgY29uc3QgdW5pY29kZSA9ICgwLCBfdW5pY29kZS5nZXRVbmljb2RlRm9yR2x5cGgpKG5hbWUsIGdseXBoc1VuaWNvZGVNYXApOwogIGlmICh1bmljb2RlICE9PSAtMSkgewogICAgZm9yIChjb25zdCBrZXkgaW4gZ2x5cGhzVW5pY29kZU1hcCkgewogICAgICBpZiAoZ2x5cGhzVW5pY29kZU1hcFtrZXldID09PSB1bmljb2RlKSB7CiAgICAgICAgcmV0dXJuIGtleTsKICAgICAgfQogICAgfQogIH0KICAoMCwgX3V0aWwuaW5mbykoIlVuYWJsZSB0byByZWNvdmVyIGEgc3RhbmRhcmQgZ2x5cGggbmFtZSBmb3I6ICIgKyBuYW1lKTsKICByZXR1cm4gbmFtZTsKfQpmdW5jdGlvbiB0eXBlMUZvbnRHbHlwaE1hcHBpbmcocHJvcGVydGllcywgYnVpbHRJbkVuY29kaW5nLCBnbHlwaE5hbWVzKSB7CiAgY29uc3QgY2hhckNvZGVUb0dseXBoSWQgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIGxldCBnbHlwaElkLCBjaGFyQ29kZSwgYmFzZUVuY29kaW5nOwogIGNvbnN0IGlzU3ltYm9saWNGb250ID0gISEocHJvcGVydGllcy5mbGFncyAmIEZvbnRGbGFncy5TeW1ib2xpYyk7CiAgaWYgKHByb3BlcnRpZXMuaXNJbnRlcm5hbEZvbnQpIHsKICAgIGJhc2VFbmNvZGluZyA9IGJ1aWx0SW5FbmNvZGluZzsKICAgIGZvciAoY2hhckNvZGUgPSAwOyBjaGFyQ29kZSA8IGJhc2VFbmNvZGluZy5sZW5ndGg7IGNoYXJDb2RlKyspIHsKICAgICAgZ2x5cGhJZCA9IGdseXBoTmFtZXMuaW5kZXhPZihiYXNlRW5jb2RpbmdbY2hhckNvZGVdKTsKICAgICAgaWYgKGdseXBoSWQgPj0gMCkgewogICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IGdseXBoSWQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID0gMDsKICAgICAgfQogICAgfQogIH0gZWxzZSBpZiAocHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lKSB7CiAgICBiYXNlRW5jb2RpbmcgPSAoMCwgX2VuY29kaW5ncy5nZXRFbmNvZGluZykocHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lKTsKICAgIGZvciAoY2hhckNvZGUgPSAwOyBjaGFyQ29kZSA8IGJhc2VFbmNvZGluZy5sZW5ndGg7IGNoYXJDb2RlKyspIHsKICAgICAgZ2x5cGhJZCA9IGdseXBoTmFtZXMuaW5kZXhPZihiYXNlRW5jb2RpbmdbY2hhckNvZGVdKTsKICAgICAgaWYgKGdseXBoSWQgPj0gMCkgewogICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IGdseXBoSWQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID0gMDsKICAgICAgfQogICAgfQogIH0gZWxzZSBpZiAoaXNTeW1ib2xpY0ZvbnQpIHsKICAgIGZvciAoY2hhckNvZGUgaW4gYnVpbHRJbkVuY29kaW5nKSB7CiAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IGJ1aWx0SW5FbmNvZGluZ1tjaGFyQ29kZV07CiAgICB9CiAgfSBlbHNlIHsKICAgIGJhc2VFbmNvZGluZyA9IF9lbmNvZGluZ3MuU3RhbmRhcmRFbmNvZGluZzsKICAgIGZvciAoY2hhckNvZGUgPSAwOyBjaGFyQ29kZSA8IGJhc2VFbmNvZGluZy5sZW5ndGg7IGNoYXJDb2RlKyspIHsKICAgICAgZ2x5cGhJZCA9IGdseXBoTmFtZXMuaW5kZXhPZihiYXNlRW5jb2RpbmdbY2hhckNvZGVdKTsKICAgICAgaWYgKGdseXBoSWQgPj0gMCkgewogICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IGdseXBoSWQ7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID0gMDsKICAgICAgfQogICAgfQogIH0KICBjb25zdCBkaWZmZXJlbmNlcyA9IHByb3BlcnRpZXMuZGlmZmVyZW5jZXM7CiAgbGV0IGdseXBoc1VuaWNvZGVNYXA7CiAgaWYgKGRpZmZlcmVuY2VzKSB7CiAgICBmb3IgKGNoYXJDb2RlIGluIGRpZmZlcmVuY2VzKSB7CiAgICAgIGNvbnN0IGdseXBoTmFtZSA9IGRpZmZlcmVuY2VzW2NoYXJDb2RlXTsKICAgICAgZ2x5cGhJZCA9IGdseXBoTmFtZXMuaW5kZXhPZihnbHlwaE5hbWUpOwogICAgICBpZiAoZ2x5cGhJZCA9PT0gLTEpIHsKICAgICAgICBpZiAoIWdseXBoc1VuaWNvZGVNYXApIHsKICAgICAgICAgIGdseXBoc1VuaWNvZGVNYXAgPSAoMCwgX2dseXBobGlzdC5nZXRHbHlwaHNVbmljb2RlKSgpOwogICAgICAgIH0KICAgICAgICBjb25zdCBzdGFuZGFyZEdseXBoTmFtZSA9IHJlY292ZXJHbHlwaE5hbWUoZ2x5cGhOYW1lLCBnbHlwaHNVbmljb2RlTWFwKTsKICAgICAgICBpZiAoc3RhbmRhcmRHbHlwaE5hbWUgIT09IGdseXBoTmFtZSkgewogICAgICAgICAgZ2x5cGhJZCA9IGdseXBoTmFtZXMuaW5kZXhPZihzdGFuZGFyZEdseXBoTmFtZSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChnbHlwaElkID49IDApIHsKICAgICAgICBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPSBnbHlwaElkOwogICAgICB9IGVsc2UgewogICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IDA7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIGNoYXJDb2RlVG9HbHlwaElkOwp9CmZ1bmN0aW9uIG5vcm1hbGl6ZUZvbnROYW1lKG5hbWUpIHsKICByZXR1cm4gbmFtZS5yZXBsYWNlQWxsKC9bLF9dL2csICItIikucmVwbGFjZUFsbCgvXHMvZywgIiIpOwp9CgovKioqLyB9KSwKLyogMTc0ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fd2VicGFja19leHBvcnRzX18sIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKX193X3BkZmpzX3JlcXVpcmVfXy5yKF9fd2VicGFja19leHBvcnRzX18pOwovKiBoYXJtb255IGV4cG9ydCAqLyBfX3dfcGRmanNfcmVxdWlyZV9fLmQoX193ZWJwYWNrX2V4cG9ydHNfXywgewovKiBoYXJtb255IGV4cG9ydCAqLyAgICJnZXREaW5nYmF0c0dseXBoc1VuaWNvZGUiOiAoKSA9PiAoLyogYmluZGluZyAqLyBnZXREaW5nYmF0c0dseXBoc1VuaWNvZGUpLAovKiBoYXJtb255IGV4cG9ydCAqLyAgICJnZXRHbHlwaHNVbmljb2RlIjogKCkgPT4gKC8qIGJpbmRpbmcgKi8gZ2V0R2x5cGhzVW5pY29kZSkKLyogaGFybW9ueSBleHBvcnQgKi8gfSk7Ci8qIGhhcm1vbnkgaW1wb3J0ICovIHZhciBfY29yZV91dGlsc19qc19fV0VCUEFDS19JTVBPUlRFRF9NT0RVTEVfMF9fID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwoKY29uc3QgZ2V0R2x5cGhzVW5pY29kZSA9ICgwLF9jb3JlX3V0aWxzX2pzX19XRUJQQUNLX0lNUE9SVEVEX01PRFVMRV8wX18uZ2V0QXJyYXlMb29rdXBUYWJsZUZhY3RvcnkpKGZ1bmN0aW9uICgpIHsKIHJldHVybiBbCiAgIkEiLAogIDB4MDA0MSwKICAiQUUiLAogIDB4MDBjNiwKICAiQUVhY3V0ZSIsCiAgMHgwMWZjLAogICJBRW1hY3JvbiIsCiAgMHgwMWUyLAogICJBRXNtYWxsIiwKICAweGY3ZTYsCiAgIkFhY3V0ZSIsCiAgMHgwMGMxLAogICJBYWN1dGVzbWFsbCIsCiAgMHhmN2UxLAogICJBYnJldmUiLAogIDB4MDEwMiwKICAiQWJyZXZlYWN1dGUiLAogIDB4MWVhZSwKICAiQWJyZXZlY3lyaWxsaWMiLAogIDB4MDRkMCwKICAiQWJyZXZlZG90YmVsb3ciLAogIDB4MWViNiwKICAiQWJyZXZlZ3JhdmUiLAogIDB4MWViMCwKICAiQWJyZXZlaG9va2Fib3ZlIiwKICAweDFlYjIsCiAgIkFicmV2ZXRpbGRlIiwKICAweDFlYjQsCiAgIkFjYXJvbiIsCiAgMHgwMWNkLAogICJBY2lyY2xlIiwKICAweDI0YjYsCiAgIkFjaXJjdW1mbGV4IiwKICAweDAwYzIsCiAgIkFjaXJjdW1mbGV4YWN1dGUiLAogIDB4MWVhNCwKICAiQWNpcmN1bWZsZXhkb3RiZWxvdyIsCiAgMHgxZWFjLAogICJBY2lyY3VtZmxleGdyYXZlIiwKICAweDFlYTYsCiAgIkFjaXJjdW1mbGV4aG9va2Fib3ZlIiwKICAweDFlYTgsCiAgIkFjaXJjdW1mbGV4c21hbGwiLAogIDB4ZjdlMiwKICAiQWNpcmN1bWZsZXh0aWxkZSIsCiAgMHgxZWFhLAogICJBY3V0ZSIsCiAgMHhmNmM5LAogICJBY3V0ZXNtYWxsIiwKICAweGY3YjQsCiAgIkFjeXJpbGxpYyIsCiAgMHgwNDEwLAogICJBZGJsZ3JhdmUiLAogIDB4MDIwMCwKICAiQWRpZXJlc2lzIiwKICAweDAwYzQsCiAgIkFkaWVyZXNpc2N5cmlsbGljIiwKICAweDA0ZDIsCiAgIkFkaWVyZXNpc21hY3JvbiIsCiAgMHgwMWRlLAogICJBZGllcmVzaXNzbWFsbCIsCiAgMHhmN2U0LAogICJBZG90YmVsb3ciLAogIDB4MWVhMCwKICAiQWRvdG1hY3JvbiIsCiAgMHgwMWUwLAogICJBZ3JhdmUiLAogIDB4MDBjMCwKICAiQWdyYXZlc21hbGwiLAogIDB4ZjdlMCwKICAiQWhvb2thYm92ZSIsCiAgMHgxZWEyLAogICJBaWVjeXJpbGxpYyIsCiAgMHgwNGQ0LAogICJBaW52ZXJ0ZWRicmV2ZSIsCiAgMHgwMjAyLAogICJBbHBoYSIsCiAgMHgwMzkxLAogICJBbHBoYXRvbm9zIiwKICAweDAzODYsCiAgIkFtYWNyb24iLAogIDB4MDEwMCwKICAiQW1vbm9zcGFjZSIsCiAgMHhmZjIxLAogICJBb2dvbmVrIiwKICAweDAxMDQsCiAgIkFyaW5nIiwKICAweDAwYzUsCiAgIkFyaW5nYWN1dGUiLAogIDB4MDFmYSwKICAiQXJpbmdiZWxvdyIsCiAgMHgxZTAwLAogICJBcmluZ3NtYWxsIiwKICAweGY3ZTUsCiAgIkFzbWFsbCIsCiAgMHhmNzYxLAogICJBdGlsZGUiLAogIDB4MDBjMywKICAiQXRpbGRlc21hbGwiLAogIDB4ZjdlMywKICAiQXliYXJtZW5pYW4iLAogIDB4MDUzMSwKICAiQiIsCiAgMHgwMDQyLAogICJCY2lyY2xlIiwKICAweDI0YjcsCiAgIkJkb3RhY2NlbnQiLAogIDB4MWUwMiwKICAiQmRvdGJlbG93IiwKICAweDFlMDQsCiAgIkJlY3lyaWxsaWMiLAogIDB4MDQxMSwKICAiQmVuYXJtZW5pYW4iLAogIDB4MDUzMiwKICAiQmV0YSIsCiAgMHgwMzkyLAogICJCaG9vayIsCiAgMHgwMTgxLAogICJCbGluZWJlbG93IiwKICAweDFlMDYsCiAgIkJtb25vc3BhY2UiLAogIDB4ZmYyMiwKICAiQnJldmVzbWFsbCIsCiAgMHhmNmY0LAogICJCc21hbGwiLAogIDB4Zjc2MiwKICAiQnRvcGJhciIsCiAgMHgwMTgyLAogICJDIiwKICAweDAwNDMsCiAgIkNhYXJtZW5pYW4iLAogIDB4MDUzZSwKICAiQ2FjdXRlIiwKICAweDAxMDYsCiAgIkNhcm9uIiwKICAweGY2Y2EsCiAgIkNhcm9uc21hbGwiLAogIDB4ZjZmNSwKICAiQ2Nhcm9uIiwKICAweDAxMGMsCiAgIkNjZWRpbGxhIiwKICAweDAwYzcsCiAgIkNjZWRpbGxhYWN1dGUiLAogIDB4MWUwOCwKICAiQ2NlZGlsbGFzbWFsbCIsCiAgMHhmN2U3LAogICJDY2lyY2xlIiwKICAweDI0YjgsCiAgIkNjaXJjdW1mbGV4IiwKICAweDAxMDgsCiAgIkNkb3QiLAogIDB4MDEwYSwKICAiQ2RvdGFjY2VudCIsCiAgMHgwMTBhLAogICJDZWRpbGxhc21hbGwiLAogIDB4ZjdiOCwKICAiQ2hhYXJtZW5pYW4iLAogIDB4MDU0OSwKICAiQ2hlYWJraGFzaWFuY3lyaWxsaWMiLAogIDB4MDRiYywKICAiQ2hlY3lyaWxsaWMiLAogIDB4MDQyNywKICAiQ2hlZGVzY2VuZGVyYWJraGFzaWFuY3lyaWxsaWMiLAogIDB4MDRiZSwKICAiQ2hlZGVzY2VuZGVyY3lyaWxsaWMiLAogIDB4MDRiNiwKICAiQ2hlZGllcmVzaXNjeXJpbGxpYyIsCiAgMHgwNGY0LAogICJDaGVoYXJtZW5pYW4iLAogIDB4MDU0MywKICAiQ2hla2hha2Fzc2lhbmN5cmlsbGljIiwKICAweDA0Y2IsCiAgIkNoZXZlcnRpY2Fsc3Ryb2tlY3lyaWxsaWMiLAogIDB4MDRiOCwKICAiQ2hpIiwKICAweDAzYTcsCiAgIkNob29rIiwKICAweDAxODcsCiAgIkNpcmN1bWZsZXhzbWFsbCIsCiAgMHhmNmY2LAogICJDbW9ub3NwYWNlIiwKICAweGZmMjMsCiAgIkNvYXJtZW5pYW4iLAogIDB4MDU1MSwKICAiQ3NtYWxsIiwKICAweGY3NjMsCiAgIkQiLAogIDB4MDA0NCwKICAiRFoiLAogIDB4MDFmMSwKICAiRFpjYXJvbiIsCiAgMHgwMWM0LAogICJEYWFybWVuaWFuIiwKICAweDA1MzQsCiAgIkRhZnJpY2FuIiwKICAweDAxODksCiAgIkRjYXJvbiIsCiAgMHgwMTBlLAogICJEY2VkaWxsYSIsCiAgMHgxZTEwLAogICJEY2lyY2xlIiwKICAweDI0YjksCiAgIkRjaXJjdW1mbGV4YmVsb3ciLAogIDB4MWUxMiwKICAiRGNyb2F0IiwKICAweDAxMTAsCiAgIkRkb3RhY2NlbnQiLAogIDB4MWUwYSwKICAiRGRvdGJlbG93IiwKICAweDFlMGMsCiAgIkRlY3lyaWxsaWMiLAogIDB4MDQxNCwKICAiRGVpY29wdGljIiwKICAweDAzZWUsCiAgIkRlbHRhIiwKICAweDIyMDYsCiAgIkRlbHRhZ3JlZWsiLAogIDB4MDM5NCwKICAiRGhvb2siLAogIDB4MDE4YSwKICAiRGllcmVzaXMiLAogIDB4ZjZjYiwKICAiRGllcmVzaXNBY3V0ZSIsCiAgMHhmNmNjLAogICJEaWVyZXNpc0dyYXZlIiwKICAweGY2Y2QsCiAgIkRpZXJlc2lzc21hbGwiLAogIDB4ZjdhOCwKICAiRGlnYW1tYWdyZWVrIiwKICAweDAzZGMsCiAgIkRqZWN5cmlsbGljIiwKICAweDA0MDIsCiAgIkRsaW5lYmVsb3ciLAogIDB4MWUwZSwKICAiRG1vbm9zcGFjZSIsCiAgMHhmZjI0LAogICJEb3RhY2NlbnRzbWFsbCIsCiAgMHhmNmY3LAogICJEc2xhc2giLAogIDB4MDExMCwKICAiRHNtYWxsIiwKICAweGY3NjQsCiAgIkR0b3BiYXIiLAogIDB4MDE4YiwKICAiRHoiLAogIDB4MDFmMiwKICAiRHpjYXJvbiIsCiAgMHgwMWM1LAogICJEemVhYmtoYXNpYW5jeXJpbGxpYyIsCiAgMHgwNGUwLAogICJEemVjeXJpbGxpYyIsCiAgMHgwNDA1LAogICJEemhlY3lyaWxsaWMiLAogIDB4MDQwZiwKICAiRSIsCiAgMHgwMDQ1LAogICJFYWN1dGUiLAogIDB4MDBjOSwKICAiRWFjdXRlc21hbGwiLAogIDB4ZjdlOSwKICAiRWJyZXZlIiwKICAweDAxMTQsCiAgIkVjYXJvbiIsCiAgMHgwMTFhLAogICJFY2VkaWxsYWJyZXZlIiwKICAweDFlMWMsCiAgIkVjaGFybWVuaWFuIiwKICAweDA1MzUsCiAgIkVjaXJjbGUiLAogIDB4MjRiYSwKICAiRWNpcmN1bWZsZXgiLAogIDB4MDBjYSwKICAiRWNpcmN1bWZsZXhhY3V0ZSIsCiAgMHgxZWJlLAogICJFY2lyY3VtZmxleGJlbG93IiwKICAweDFlMTgsCiAgIkVjaXJjdW1mbGV4ZG90YmVsb3ciLAogIDB4MWVjNiwKICAiRWNpcmN1bWZsZXhncmF2ZSIsCiAgMHgxZWMwLAogICJFY2lyY3VtZmxleGhvb2thYm92ZSIsCiAgMHgxZWMyLAogICJFY2lyY3VtZmxleHNtYWxsIiwKICAweGY3ZWEsCiAgIkVjaXJjdW1mbGV4dGlsZGUiLAogIDB4MWVjNCwKICAiRWN5cmlsbGljIiwKICAweDA0MDQsCiAgIkVkYmxncmF2ZSIsCiAgMHgwMjA0LAogICJFZGllcmVzaXMiLAogIDB4MDBjYiwKICAiRWRpZXJlc2lzc21hbGwiLAogIDB4ZjdlYiwKICAiRWRvdCIsCiAgMHgwMTE2LAogICJFZG90YWNjZW50IiwKICAweDAxMTYsCiAgIkVkb3RiZWxvdyIsCiAgMHgxZWI4LAogICJFZmN5cmlsbGljIiwKICAweDA0MjQsCiAgIkVncmF2ZSIsCiAgMHgwMGM4LAogICJFZ3JhdmVzbWFsbCIsCiAgMHhmN2U4LAogICJFaGFybWVuaWFuIiwKICAweDA1MzcsCiAgIkVob29rYWJvdmUiLAogIDB4MWViYSwKICAiRWlnaHRyb21hbiIsCiAgMHgyMTY3LAogICJFaW52ZXJ0ZWRicmV2ZSIsCiAgMHgwMjA2LAogICJFaW90aWZpZWRjeXJpbGxpYyIsCiAgMHgwNDY0LAogICJFbGN5cmlsbGljIiwKICAweDA0MWIsCiAgIkVsZXZlbnJvbWFuIiwKICAweDIxNmEsCiAgIkVtYWNyb24iLAogIDB4MDExMiwKICAiRW1hY3JvbmFjdXRlIiwKICAweDFlMTYsCiAgIkVtYWNyb25ncmF2ZSIsCiAgMHgxZTE0LAogICJFbWN5cmlsbGljIiwKICAweDA0MWMsCiAgIkVtb25vc3BhY2UiLAogIDB4ZmYyNSwKICAiRW5jeXJpbGxpYyIsCiAgMHgwNDFkLAogICJFbmRlc2NlbmRlcmN5cmlsbGljIiwKICAweDA0YTIsCiAgIkVuZyIsCiAgMHgwMTRhLAogICJFbmdoZWN5cmlsbGljIiwKICAweDA0YTQsCiAgIkVuaG9va2N5cmlsbGljIiwKICAweDA0YzcsCiAgIkVvZ29uZWsiLAogIDB4MDExOCwKICAiRW9wZW4iLAogIDB4MDE5MCwKICAiRXBzaWxvbiIsCiAgMHgwMzk1LAogICJFcHNpbG9udG9ub3MiLAogIDB4MDM4OCwKICAiRXJjeXJpbGxpYyIsCiAgMHgwNDIwLAogICJFcmV2ZXJzZWQiLAogIDB4MDE4ZSwKICAiRXJldmVyc2VkY3lyaWxsaWMiLAogIDB4MDQyZCwKICAiRXNjeXJpbGxpYyIsCiAgMHgwNDIxLAogICJFc2Rlc2NlbmRlcmN5cmlsbGljIiwKICAweDA0YWEsCiAgIkVzaCIsCiAgMHgwMWE5LAogICJFc21hbGwiLAogIDB4Zjc2NSwKICAiRXRhIiwKICAweDAzOTcsCiAgIkV0YXJtZW5pYW4iLAogIDB4MDUzOCwKICAiRXRhdG9ub3MiLAogIDB4MDM4OSwKICAiRXRoIiwKICAweDAwZDAsCiAgIkV0aHNtYWxsIiwKICAweGY3ZjAsCiAgIkV0aWxkZSIsCiAgMHgxZWJjLAogICJFdGlsZGViZWxvdyIsCiAgMHgxZTFhLAogICJFdXJvIiwKICAweDIwYWMsCiAgIkV6aCIsCiAgMHgwMWI3LAogICJFemhjYXJvbiIsCiAgMHgwMWVlLAogICJFemhyZXZlcnNlZCIsCiAgMHgwMWI4LAogICJGIiwKICAweDAwNDYsCiAgIkZjaXJjbGUiLAogIDB4MjRiYiwKICAiRmRvdGFjY2VudCIsCiAgMHgxZTFlLAogICJGZWhhcm1lbmlhbiIsCiAgMHgwNTU2LAogICJGZWljb3B0aWMiLAogIDB4MDNlNCwKICAiRmhvb2siLAogIDB4MDE5MSwKICAiRml0YWN5cmlsbGljIiwKICAweDA0NzIsCiAgIkZpdmVyb21hbiIsCiAgMHgyMTY0LAogICJGbW9ub3NwYWNlIiwKICAweGZmMjYsCiAgIkZvdXJyb21hbiIsCiAgMHgyMTYzLAogICJGc21hbGwiLAogIDB4Zjc2NiwKICAiRyIsCiAgMHgwMDQ3LAogICJHQnNxdWFyZSIsCiAgMHgzMzg3LAogICJHYWN1dGUiLAogIDB4MDFmNCwKICAiR2FtbWEiLAogIDB4MDM5MywKICAiR2FtbWFhZnJpY2FuIiwKICAweDAxOTQsCiAgIkdhbmdpYWNvcHRpYyIsCiAgMHgwM2VhLAogICJHYnJldmUiLAogIDB4MDExZSwKICAiR2Nhcm9uIiwKICAweDAxZTYsCiAgIkdjZWRpbGxhIiwKICAweDAxMjIsCiAgIkdjaXJjbGUiLAogIDB4MjRiYywKICAiR2NpcmN1bWZsZXgiLAogIDB4MDExYywKICAiR2NvbW1hYWNjZW50IiwKICAweDAxMjIsCiAgIkdkb3QiLAogIDB4MDEyMCwKICAiR2RvdGFjY2VudCIsCiAgMHgwMTIwLAogICJHZWN5cmlsbGljIiwKICAweDA0MTMsCiAgIkdoYWRhcm1lbmlhbiIsCiAgMHgwNTQyLAogICJHaGVtaWRkbGVob29rY3lyaWxsaWMiLAogIDB4MDQ5NCwKICAiR2hlc3Ryb2tlY3lyaWxsaWMiLAogIDB4MDQ5MiwKICAiR2hldXB0dXJuY3lyaWxsaWMiLAogIDB4MDQ5MCwKICAiR2hvb2siLAogIDB4MDE5MywKICAiR2ltYXJtZW5pYW4iLAogIDB4MDUzMywKICAiR2plY3lyaWxsaWMiLAogIDB4MDQwMywKICAiR21hY3JvbiIsCiAgMHgxZTIwLAogICJHbW9ub3NwYWNlIiwKICAweGZmMjcsCiAgIkdyYXZlIiwKICAweGY2Y2UsCiAgIkdyYXZlc21hbGwiLAogIDB4Zjc2MCwKICAiR3NtYWxsIiwKICAweGY3NjcsCiAgIkdzbWFsbGhvb2siLAogIDB4MDI5YiwKICAiR3N0cm9rZSIsCiAgMHgwMWU0LAogICJIIiwKICAweDAwNDgsCiAgIkgxODUzMyIsCiAgMHgyNWNmLAogICJIMTg1NDMiLAogIDB4MjVhYSwKICAiSDE4NTUxIiwKICAweDI1YWIsCiAgIkgyMjA3MyIsCiAgMHgyNWExLAogICJIUHNxdWFyZSIsCiAgMHgzM2NiLAogICJIYWFia2hhc2lhbmN5cmlsbGljIiwKICAweDA0YTgsCiAgIkhhZGVzY2VuZGVyY3lyaWxsaWMiLAogIDB4MDRiMiwKICAiSGFyZHNpZ25jeXJpbGxpYyIsCiAgMHgwNDJhLAogICJIYmFyIiwKICAweDAxMjYsCiAgIkhicmV2ZWJlbG93IiwKICAweDFlMmEsCiAgIkhjZWRpbGxhIiwKICAweDFlMjgsCiAgIkhjaXJjbGUiLAogIDB4MjRiZCwKICAiSGNpcmN1bWZsZXgiLAogIDB4MDEyNCwKICAiSGRpZXJlc2lzIiwKICAweDFlMjYsCiAgIkhkb3RhY2NlbnQiLAogIDB4MWUyMiwKICAiSGRvdGJlbG93IiwKICAweDFlMjQsCiAgIkhtb25vc3BhY2UiLAogIDB4ZmYyOCwKICAiSG9hcm1lbmlhbiIsCiAgMHgwNTQwLAogICJIb3JpY29wdGljIiwKICAweDAzZTgsCiAgIkhzbWFsbCIsCiAgMHhmNzY4LAogICJIdW5nYXJ1bWxhdXQiLAogIDB4ZjZjZiwKICAiSHVuZ2FydW1sYXV0c21hbGwiLAogIDB4ZjZmOCwKICAiSHpzcXVhcmUiLAogIDB4MzM5MCwKICAiSSIsCiAgMHgwMDQ5LAogICJJQWN5cmlsbGljIiwKICAweDA0MmYsCiAgIklKIiwKICAweDAxMzIsCiAgIklVY3lyaWxsaWMiLAogIDB4MDQyZSwKICAiSWFjdXRlIiwKICAweDAwY2QsCiAgIklhY3V0ZXNtYWxsIiwKICAweGY3ZWQsCiAgIklicmV2ZSIsCiAgMHgwMTJjLAogICJJY2Fyb24iLAogIDB4MDFjZiwKICAiSWNpcmNsZSIsCiAgMHgyNGJlLAogICJJY2lyY3VtZmxleCIsCiAgMHgwMGNlLAogICJJY2lyY3VtZmxleHNtYWxsIiwKICAweGY3ZWUsCiAgIkljeXJpbGxpYyIsCiAgMHgwNDA2LAogICJJZGJsZ3JhdmUiLAogIDB4MDIwOCwKICAiSWRpZXJlc2lzIiwKICAweDAwY2YsCiAgIklkaWVyZXNpc2FjdXRlIiwKICAweDFlMmUsCiAgIklkaWVyZXNpc2N5cmlsbGljIiwKICAweDA0ZTQsCiAgIklkaWVyZXNpc3NtYWxsIiwKICAweGY3ZWYsCiAgIklkb3QiLAogIDB4MDEzMCwKICAiSWRvdGFjY2VudCIsCiAgMHgwMTMwLAogICJJZG90YmVsb3ciLAogIDB4MWVjYSwKICAiSWVicmV2ZWN5cmlsbGljIiwKICAweDA0ZDYsCiAgIkllY3lyaWxsaWMiLAogIDB4MDQxNSwKICAiSWZyYWt0dXIiLAogIDB4MjExMSwKICAiSWdyYXZlIiwKICAweDAwY2MsCiAgIklncmF2ZXNtYWxsIiwKICAweGY3ZWMsCiAgIklob29rYWJvdmUiLAogIDB4MWVjOCwKICAiSWljeXJpbGxpYyIsCiAgMHgwNDE4LAogICJJaW52ZXJ0ZWRicmV2ZSIsCiAgMHgwMjBhLAogICJJaXNob3J0Y3lyaWxsaWMiLAogIDB4MDQxOSwKICAiSW1hY3JvbiIsCiAgMHgwMTJhLAogICJJbWFjcm9uY3lyaWxsaWMiLAogIDB4MDRlMiwKICAiSW1vbm9zcGFjZSIsCiAgMHhmZjI5LAogICJJbmlhcm1lbmlhbiIsCiAgMHgwNTNiLAogICJJb2N5cmlsbGljIiwKICAweDA0MDEsCiAgIklvZ29uZWsiLAogIDB4MDEyZSwKICAiSW90YSIsCiAgMHgwMzk5LAogICJJb3RhYWZyaWNhbiIsCiAgMHgwMTk2LAogICJJb3RhZGllcmVzaXMiLAogIDB4MDNhYSwKICAiSW90YXRvbm9zIiwKICAweDAzOGEsCiAgIklzbWFsbCIsCiAgMHhmNzY5LAogICJJc3Ryb2tlIiwKICAweDAxOTcsCiAgIkl0aWxkZSIsCiAgMHgwMTI4LAogICJJdGlsZGViZWxvdyIsCiAgMHgxZTJjLAogICJJemhpdHNhY3lyaWxsaWMiLAogIDB4MDQ3NCwKICAiSXpoaXRzYWRibGdyYXZlY3lyaWxsaWMiLAogIDB4MDQ3NiwKICAiSiIsCiAgMHgwMDRhLAogICJKYWFybWVuaWFuIiwKICAweDA1NDEsCiAgIkpjaXJjbGUiLAogIDB4MjRiZiwKICAiSmNpcmN1bWZsZXgiLAogIDB4MDEzNCwKICAiSmVjeXJpbGxpYyIsCiAgMHgwNDA4LAogICJKaGVoYXJtZW5pYW4iLAogIDB4MDU0YiwKICAiSm1vbm9zcGFjZSIsCiAgMHhmZjJhLAogICJKc21hbGwiLAogIDB4Zjc2YSwKICAiSyIsCiAgMHgwMDRiLAogICJLQnNxdWFyZSIsCiAgMHgzMzg1LAogICJLS3NxdWFyZSIsCiAgMHgzM2NkLAogICJLYWJhc2hraXJjeXJpbGxpYyIsCiAgMHgwNGEwLAogICJLYWN1dGUiLAogIDB4MWUzMCwKICAiS2FjeXJpbGxpYyIsCiAgMHgwNDFhLAogICJLYWRlc2NlbmRlcmN5cmlsbGljIiwKICAweDA0OWEsCiAgIkthaG9va2N5cmlsbGljIiwKICAweDA0YzMsCiAgIkthcHBhIiwKICAweDAzOWEsCiAgIkthc3Ryb2tlY3lyaWxsaWMiLAogIDB4MDQ5ZSwKICAiS2F2ZXJ0aWNhbHN0cm9rZWN5cmlsbGljIiwKICAweDA0OWMsCiAgIktjYXJvbiIsCiAgMHgwMWU4LAogICJLY2VkaWxsYSIsCiAgMHgwMTM2LAogICJLY2lyY2xlIiwKICAweDI0YzAsCiAgIktjb21tYWFjY2VudCIsCiAgMHgwMTM2LAogICJLZG90YmVsb3ciLAogIDB4MWUzMiwKICAiS2VoYXJtZW5pYW4iLAogIDB4MDU1NCwKICAiS2VuYXJtZW5pYW4iLAogIDB4MDUzZiwKICAiS2hhY3lyaWxsaWMiLAogIDB4MDQyNSwKICAiS2hlaWNvcHRpYyIsCiAgMHgwM2U2LAogICJLaG9vayIsCiAgMHgwMTk4LAogICJLamVjeXJpbGxpYyIsCiAgMHgwNDBjLAogICJLbGluZWJlbG93IiwKICAweDFlMzQsCiAgIkttb25vc3BhY2UiLAogIDB4ZmYyYiwKICAiS29wcGFjeXJpbGxpYyIsCiAgMHgwNDgwLAogICJLb3BwYWdyZWVrIiwKICAweDAzZGUsCiAgIktzaWN5cmlsbGljIiwKICAweDA0NmUsCiAgIktzbWFsbCIsCiAgMHhmNzZiLAogICJMIiwKICAweDAwNGMsCiAgIkxKIiwKICAweDAxYzcsCiAgIkxMIiwKICAweGY2YmYsCiAgIkxhY3V0ZSIsCiAgMHgwMTM5LAogICJMYW1iZGEiLAogIDB4MDM5YiwKICAiTGNhcm9uIiwKICAweDAxM2QsCiAgIkxjZWRpbGxhIiwKICAweDAxM2IsCiAgIkxjaXJjbGUiLAogIDB4MjRjMSwKICAiTGNpcmN1bWZsZXhiZWxvdyIsCiAgMHgxZTNjLAogICJMY29tbWFhY2NlbnQiLAogIDB4MDEzYiwKICAiTGRvdCIsCiAgMHgwMTNmLAogICJMZG90YWNjZW50IiwKICAweDAxM2YsCiAgIkxkb3RiZWxvdyIsCiAgMHgxZTM2LAogICJMZG90YmVsb3dtYWNyb24iLAogIDB4MWUzOCwKICAiTGl3bmFybWVuaWFuIiwKICAweDA1M2MsCiAgIkxqIiwKICAweDAxYzgsCiAgIkxqZWN5cmlsbGljIiwKICAweDA0MDksCiAgIkxsaW5lYmVsb3ciLAogIDB4MWUzYSwKICAiTG1vbm9zcGFjZSIsCiAgMHhmZjJjLAogICJMc2xhc2giLAogIDB4MDE0MSwKICAiTHNsYXNoc21hbGwiLAogIDB4ZjZmOSwKICAiTHNtYWxsIiwKICAweGY3NmMsCiAgIk0iLAogIDB4MDA0ZCwKICAiTUJzcXVhcmUiLAogIDB4MzM4NiwKICAiTWFjcm9uIiwKICAweGY2ZDAsCiAgIk1hY3JvbnNtYWxsIiwKICAweGY3YWYsCiAgIk1hY3V0ZSIsCiAgMHgxZTNlLAogICJNY2lyY2xlIiwKICAweDI0YzIsCiAgIk1kb3RhY2NlbnQiLAogIDB4MWU0MCwKICAiTWRvdGJlbG93IiwKICAweDFlNDIsCiAgIk1lbmFybWVuaWFuIiwKICAweDA1NDQsCiAgIk1tb25vc3BhY2UiLAogIDB4ZmYyZCwKICAiTXNtYWxsIiwKICAweGY3NmQsCiAgIk10dXJuZWQiLAogIDB4MDE5YywKICAiTXUiLAogIDB4MDM5YywKICAiTiIsCiAgMHgwMDRlLAogICJOSiIsCiAgMHgwMWNhLAogICJOYWN1dGUiLAogIDB4MDE0MywKICAiTmNhcm9uIiwKICAweDAxNDcsCiAgIk5jZWRpbGxhIiwKICAweDAxNDUsCiAgIk5jaXJjbGUiLAogIDB4MjRjMywKICAiTmNpcmN1bWZsZXhiZWxvdyIsCiAgMHgxZTRhLAogICJOY29tbWFhY2NlbnQiLAogIDB4MDE0NSwKICAiTmRvdGFjY2VudCIsCiAgMHgxZTQ0LAogICJOZG90YmVsb3ciLAogIDB4MWU0NiwKICAiTmhvb2tsZWZ0IiwKICAweDAxOWQsCiAgIk5pbmVyb21hbiIsCiAgMHgyMTY4LAogICJOaiIsCiAgMHgwMWNiLAogICJOamVjeXJpbGxpYyIsCiAgMHgwNDBhLAogICJObGluZWJlbG93IiwKICAweDFlNDgsCiAgIk5tb25vc3BhY2UiLAogIDB4ZmYyZSwKICAiTm93YXJtZW5pYW4iLAogIDB4MDU0NiwKICAiTnNtYWxsIiwKICAweGY3NmUsCiAgIk50aWxkZSIsCiAgMHgwMGQxLAogICJOdGlsZGVzbWFsbCIsCiAgMHhmN2YxLAogICJOdSIsCiAgMHgwMzlkLAogICJPIiwKICAweDAwNGYsCiAgIk9FIiwKICAweDAxNTIsCiAgIk9Fc21hbGwiLAogIDB4ZjZmYSwKICAiT2FjdXRlIiwKICAweDAwZDMsCiAgIk9hY3V0ZXNtYWxsIiwKICAweGY3ZjMsCiAgIk9iYXJyZWRjeXJpbGxpYyIsCiAgMHgwNGU4LAogICJPYmFycmVkZGllcmVzaXNjeXJpbGxpYyIsCiAgMHgwNGVhLAogICJPYnJldmUiLAogIDB4MDE0ZSwKICAiT2Nhcm9uIiwKICAweDAxZDEsCiAgIk9jZW50ZXJlZHRpbGRlIiwKICAweDAxOWYsCiAgIk9jaXJjbGUiLAogIDB4MjRjNCwKICAiT2NpcmN1bWZsZXgiLAogIDB4MDBkNCwKICAiT2NpcmN1bWZsZXhhY3V0ZSIsCiAgMHgxZWQwLAogICJPY2lyY3VtZmxleGRvdGJlbG93IiwKICAweDFlZDgsCiAgIk9jaXJjdW1mbGV4Z3JhdmUiLAogIDB4MWVkMiwKICAiT2NpcmN1bWZsZXhob29rYWJvdmUiLAogIDB4MWVkNCwKICAiT2NpcmN1bWZsZXhzbWFsbCIsCiAgMHhmN2Y0LAogICJPY2lyY3VtZmxleHRpbGRlIiwKICAweDFlZDYsCiAgIk9jeXJpbGxpYyIsCiAgMHgwNDFlLAogICJPZGJsYWN1dGUiLAogIDB4MDE1MCwKICAiT2RibGdyYXZlIiwKICAweDAyMGMsCiAgIk9kaWVyZXNpcyIsCiAgMHgwMGQ2LAogICJPZGllcmVzaXNjeXJpbGxpYyIsCiAgMHgwNGU2LAogICJPZGllcmVzaXNzbWFsbCIsCiAgMHhmN2Y2LAogICJPZG90YmVsb3ciLAogIDB4MWVjYywKICAiT2dvbmVrc21hbGwiLAogIDB4ZjZmYiwKICAiT2dyYXZlIiwKICAweDAwZDIsCiAgIk9ncmF2ZXNtYWxsIiwKICAweGY3ZjIsCiAgIk9oYXJtZW5pYW4iLAogIDB4MDU1NSwKICAiT2htIiwKICAweDIxMjYsCiAgIk9ob29rYWJvdmUiLAogIDB4MWVjZSwKICAiT2hvcm4iLAogIDB4MDFhMCwKICAiT2hvcm5hY3V0ZSIsCiAgMHgxZWRhLAogICJPaG9ybmRvdGJlbG93IiwKICAweDFlZTIsCiAgIk9ob3JuZ3JhdmUiLAogIDB4MWVkYywKICAiT2hvcm5ob29rYWJvdmUiLAogIDB4MWVkZSwKICAiT2hvcm50aWxkZSIsCiAgMHgxZWUwLAogICJPaHVuZ2FydW1sYXV0IiwKICAweDAxNTAsCiAgIk9pIiwKICAweDAxYTIsCiAgIk9pbnZlcnRlZGJyZXZlIiwKICAweDAyMGUsCiAgIk9tYWNyb24iLAogIDB4MDE0YywKICAiT21hY3JvbmFjdXRlIiwKICAweDFlNTIsCiAgIk9tYWNyb25ncmF2ZSIsCiAgMHgxZTUwLAogICJPbWVnYSIsCiAgMHgyMTI2LAogICJPbWVnYWN5cmlsbGljIiwKICAweDA0NjAsCiAgIk9tZWdhZ3JlZWsiLAogIDB4MDNhOSwKICAiT21lZ2Fyb3VuZGN5cmlsbGljIiwKICAweDA0N2EsCiAgIk9tZWdhdGl0bG9jeXJpbGxpYyIsCiAgMHgwNDdjLAogICJPbWVnYXRvbm9zIiwKICAweDAzOGYsCiAgIk9taWNyb24iLAogIDB4MDM5ZiwKICAiT21pY3JvbnRvbm9zIiwKICAweDAzOGMsCiAgIk9tb25vc3BhY2UiLAogIDB4ZmYyZiwKICAiT25lcm9tYW4iLAogIDB4MjE2MCwKICAiT29nb25layIsCiAgMHgwMWVhLAogICJPb2dvbmVrbWFjcm9uIiwKICAweDAxZWMsCiAgIk9vcGVuIiwKICAweDAxODYsCiAgIk9zbGFzaCIsCiAgMHgwMGQ4LAogICJPc2xhc2hhY3V0ZSIsCiAgMHgwMWZlLAogICJPc2xhc2hzbWFsbCIsCiAgMHhmN2Y4LAogICJPc21hbGwiLAogIDB4Zjc2ZiwKICAiT3N0cm9rZWFjdXRlIiwKICAweDAxZmUsCiAgIk90Y3lyaWxsaWMiLAogIDB4MDQ3ZSwKICAiT3RpbGRlIiwKICAweDAwZDUsCiAgIk90aWxkZWFjdXRlIiwKICAweDFlNGMsCiAgIk90aWxkZWRpZXJlc2lzIiwKICAweDFlNGUsCiAgIk90aWxkZXNtYWxsIiwKICAweGY3ZjUsCiAgIlAiLAogIDB4MDA1MCwKICAiUGFjdXRlIiwKICAweDFlNTQsCiAgIlBjaXJjbGUiLAogIDB4MjRjNSwKICAiUGRvdGFjY2VudCIsCiAgMHgxZTU2LAogICJQZWN5cmlsbGljIiwKICAweDA0MWYsCiAgIlBlaGFybWVuaWFuIiwKICAweDA1NGEsCiAgIlBlbWlkZGxlaG9va2N5cmlsbGljIiwKICAweDA0YTYsCiAgIlBoaSIsCiAgMHgwM2E2LAogICJQaG9vayIsCiAgMHgwMWE0LAogICJQaSIsCiAgMHgwM2EwLAogICJQaXdyYXJtZW5pYW4iLAogIDB4MDU1MywKICAiUG1vbm9zcGFjZSIsCiAgMHhmZjMwLAogICJQc2kiLAogIDB4MDNhOCwKICAiUHNpY3lyaWxsaWMiLAogIDB4MDQ3MCwKICAiUHNtYWxsIiwKICAweGY3NzAsCiAgIlEiLAogIDB4MDA1MSwKICAiUWNpcmNsZSIsCiAgMHgyNGM2LAogICJRbW9ub3NwYWNlIiwKICAweGZmMzEsCiAgIlFzbWFsbCIsCiAgMHhmNzcxLAogICJSIiwKICAweDAwNTIsCiAgIlJhYXJtZW5pYW4iLAogIDB4MDU0YywKICAiUmFjdXRlIiwKICAweDAxNTQsCiAgIlJjYXJvbiIsCiAgMHgwMTU4LAogICJSY2VkaWxsYSIsCiAgMHgwMTU2LAogICJSY2lyY2xlIiwKICAweDI0YzcsCiAgIlJjb21tYWFjY2VudCIsCiAgMHgwMTU2LAogICJSZGJsZ3JhdmUiLAogIDB4MDIxMCwKICAiUmRvdGFjY2VudCIsCiAgMHgxZTU4LAogICJSZG90YmVsb3ciLAogIDB4MWU1YSwKICAiUmRvdGJlbG93bWFjcm9uIiwKICAweDFlNWMsCiAgIlJlaGFybWVuaWFuIiwKICAweDA1NTAsCiAgIlJmcmFrdHVyIiwKICAweDIxMWMsCiAgIlJobyIsCiAgMHgwM2ExLAogICJSaW5nc21hbGwiLAogIDB4ZjZmYywKICAiUmludmVydGVkYnJldmUiLAogIDB4MDIxMiwKICAiUmxpbmViZWxvdyIsCiAgMHgxZTVlLAogICJSbW9ub3NwYWNlIiwKICAweGZmMzIsCiAgIlJzbWFsbCIsCiAgMHhmNzcyLAogICJSc21hbGxpbnZlcnRlZCIsCiAgMHgwMjgxLAogICJSc21hbGxpbnZlcnRlZHN1cGVyaW9yIiwKICAweDAyYjYsCiAgIlMiLAogIDB4MDA1MywKICAiU0YwMTAwMDAiLAogIDB4MjUwYywKICAiU0YwMjAwMDAiLAogIDB4MjUxNCwKICAiU0YwMzAwMDAiLAogIDB4MjUxMCwKICAiU0YwNDAwMDAiLAogIDB4MjUxOCwKICAiU0YwNTAwMDAiLAogIDB4MjUzYywKICAiU0YwNjAwMDAiLAogIDB4MjUyYywKICAiU0YwNzAwMDAiLAogIDB4MjUzNCwKICAiU0YwODAwMDAiLAogIDB4MjUxYywKICAiU0YwOTAwMDAiLAogIDB4MjUyNCwKICAiU0YxMDAwMDAiLAogIDB4MjUwMCwKICAiU0YxMTAwMDAiLAogIDB4MjUwMiwKICAiU0YxOTAwMDAiLAogIDB4MjU2MSwKICAiU0YyMDAwMDAiLAogIDB4MjU2MiwKICAiU0YyMTAwMDAiLAogIDB4MjU1NiwKICAiU0YyMjAwMDAiLAogIDB4MjU1NSwKICAiU0YyMzAwMDAiLAogIDB4MjU2MywKICAiU0YyNDAwMDAiLAogIDB4MjU1MSwKICAiU0YyNTAwMDAiLAogIDB4MjU1NywKICAiU0YyNjAwMDAiLAogIDB4MjU1ZCwKICAiU0YyNzAwMDAiLAogIDB4MjU1YywKICAiU0YyODAwMDAiLAogIDB4MjU1YiwKICAiU0YzNjAwMDAiLAogIDB4MjU1ZSwKICAiU0YzNzAwMDAiLAogIDB4MjU1ZiwKICAiU0YzODAwMDAiLAogIDB4MjU1YSwKICAiU0YzOTAwMDAiLAogIDB4MjU1NCwKICAiU0Y0MDAwMDAiLAogIDB4MjU2OSwKICAiU0Y0MTAwMDAiLAogIDB4MjU2NiwKICAiU0Y0MjAwMDAiLAogIDB4MjU2MCwKICAiU0Y0MzAwMDAiLAogIDB4MjU1MCwKICAiU0Y0NDAwMDAiLAogIDB4MjU2YywKICAiU0Y0NTAwMDAiLAogIDB4MjU2NywKICAiU0Y0NjAwMDAiLAogIDB4MjU2OCwKICAiU0Y0NzAwMDAiLAogIDB4MjU2NCwKICAiU0Y0ODAwMDAiLAogIDB4MjU2NSwKICAiU0Y0OTAwMDAiLAogIDB4MjU1OSwKICAiU0Y1MDAwMDAiLAogIDB4MjU1OCwKICAiU0Y1MTAwMDAiLAogIDB4MjU1MiwKICAiU0Y1MjAwMDAiLAogIDB4MjU1MywKICAiU0Y1MzAwMDAiLAogIDB4MjU2YiwKICAiU0Y1NDAwMDAiLAogIDB4MjU2YSwKICAiU2FjdXRlIiwKICAweDAxNWEsCiAgIlNhY3V0ZWRvdGFjY2VudCIsCiAgMHgxZTY0LAogICJTYW1waWdyZWVrIiwKICAweDAzZTAsCiAgIlNjYXJvbiIsCiAgMHgwMTYwLAogICJTY2Fyb25kb3RhY2NlbnQiLAogIDB4MWU2NiwKICAiU2Nhcm9uc21hbGwiLAogIDB4ZjZmZCwKICAiU2NlZGlsbGEiLAogIDB4MDE1ZSwKICAiU2Nod2EiLAogIDB4MDE4ZiwKICAiU2Nod2FjeXJpbGxpYyIsCiAgMHgwNGQ4LAogICJTY2h3YWRpZXJlc2lzY3lyaWxsaWMiLAogIDB4MDRkYSwKICAiU2NpcmNsZSIsCiAgMHgyNGM4LAogICJTY2lyY3VtZmxleCIsCiAgMHgwMTVjLAogICJTY29tbWFhY2NlbnQiLAogIDB4MDIxOCwKICAiU2RvdGFjY2VudCIsCiAgMHgxZTYwLAogICJTZG90YmVsb3ciLAogIDB4MWU2MiwKICAiU2RvdGJlbG93ZG90YWNjZW50IiwKICAweDFlNjgsCiAgIlNlaGFybWVuaWFuIiwKICAweDA1NGQsCiAgIlNldmVucm9tYW4iLAogIDB4MjE2NiwKICAiU2hhYXJtZW5pYW4iLAogIDB4MDU0NywKICAiU2hhY3lyaWxsaWMiLAogIDB4MDQyOCwKICAiU2hjaGFjeXJpbGxpYyIsCiAgMHgwNDI5LAogICJTaGVpY29wdGljIiwKICAweDAzZTIsCiAgIlNoaGFjeXJpbGxpYyIsCiAgMHgwNGJhLAogICJTaGltYWNvcHRpYyIsCiAgMHgwM2VjLAogICJTaWdtYSIsCiAgMHgwM2EzLAogICJTaXhyb21hbiIsCiAgMHgyMTY1LAogICJTbW9ub3NwYWNlIiwKICAweGZmMzMsCiAgIlNvZnRzaWduY3lyaWxsaWMiLAogIDB4MDQyYywKICAiU3NtYWxsIiwKICAweGY3NzMsCiAgIlN0aWdtYWdyZWVrIiwKICAweDAzZGEsCiAgIlQiLAogIDB4MDA1NCwKICAiVGF1IiwKICAweDAzYTQsCiAgIlRiYXIiLAogIDB4MDE2NiwKICAiVGNhcm9uIiwKICAweDAxNjQsCiAgIlRjZWRpbGxhIiwKICAweDAxNjIsCiAgIlRjaXJjbGUiLAogIDB4MjRjOSwKICAiVGNpcmN1bWZsZXhiZWxvdyIsCiAgMHgxZTcwLAogICJUY29tbWFhY2NlbnQiLAogIDB4MDE2MiwKICAiVGRvdGFjY2VudCIsCiAgMHgxZTZhLAogICJUZG90YmVsb3ciLAogIDB4MWU2YywKICAiVGVjeXJpbGxpYyIsCiAgMHgwNDIyLAogICJUZWRlc2NlbmRlcmN5cmlsbGljIiwKICAweDA0YWMsCiAgIlRlbnJvbWFuIiwKICAweDIxNjksCiAgIlRldHNlY3lyaWxsaWMiLAogIDB4MDRiNCwKICAiVGhldGEiLAogIDB4MDM5OCwKICAiVGhvb2siLAogIDB4MDFhYywKICAiVGhvcm4iLAogIDB4MDBkZSwKICAiVGhvcm5zbWFsbCIsCiAgMHhmN2ZlLAogICJUaHJlZXJvbWFuIiwKICAweDIxNjIsCiAgIlRpbGRlc21hbGwiLAogIDB4ZjZmZSwKICAiVGl3bmFybWVuaWFuIiwKICAweDA1NGYsCiAgIlRsaW5lYmVsb3ciLAogIDB4MWU2ZSwKICAiVG1vbm9zcGFjZSIsCiAgMHhmZjM0LAogICJUb2FybWVuaWFuIiwKICAweDA1MzksCiAgIlRvbmVmaXZlIiwKICAweDAxYmMsCiAgIlRvbmVzaXgiLAogIDB4MDE4NCwKICAiVG9uZXR3byIsCiAgMHgwMWE3LAogICJUcmV0cm9mbGV4aG9vayIsCiAgMHgwMWFlLAogICJUc2VjeXJpbGxpYyIsCiAgMHgwNDI2LAogICJUc2hlY3lyaWxsaWMiLAogIDB4MDQwYiwKICAiVHNtYWxsIiwKICAweGY3NzQsCiAgIlR3ZWx2ZXJvbWFuIiwKICAweDIxNmIsCiAgIlR3b3JvbWFuIiwKICAweDIxNjEsCiAgIlUiLAogIDB4MDA1NSwKICAiVWFjdXRlIiwKICAweDAwZGEsCiAgIlVhY3V0ZXNtYWxsIiwKICAweGY3ZmEsCiAgIlVicmV2ZSIsCiAgMHgwMTZjLAogICJVY2Fyb24iLAogIDB4MDFkMywKICAiVWNpcmNsZSIsCiAgMHgyNGNhLAogICJVY2lyY3VtZmxleCIsCiAgMHgwMGRiLAogICJVY2lyY3VtZmxleGJlbG93IiwKICAweDFlNzYsCiAgIlVjaXJjdW1mbGV4c21hbGwiLAogIDB4ZjdmYiwKICAiVWN5cmlsbGljIiwKICAweDA0MjMsCiAgIlVkYmxhY3V0ZSIsCiAgMHgwMTcwLAogICJVZGJsZ3JhdmUiLAogIDB4MDIxNCwKICAiVWRpZXJlc2lzIiwKICAweDAwZGMsCiAgIlVkaWVyZXNpc2FjdXRlIiwKICAweDAxZDcsCiAgIlVkaWVyZXNpc2JlbG93IiwKICAweDFlNzIsCiAgIlVkaWVyZXNpc2Nhcm9uIiwKICAweDAxZDksCiAgIlVkaWVyZXNpc2N5cmlsbGljIiwKICAweDA0ZjAsCiAgIlVkaWVyZXNpc2dyYXZlIiwKICAweDAxZGIsCiAgIlVkaWVyZXNpc21hY3JvbiIsCiAgMHgwMWQ1LAogICJVZGllcmVzaXNzbWFsbCIsCiAgMHhmN2ZjLAogICJVZG90YmVsb3ciLAogIDB4MWVlNCwKICAiVWdyYXZlIiwKICAweDAwZDksCiAgIlVncmF2ZXNtYWxsIiwKICAweGY3ZjksCiAgIlVob29rYWJvdmUiLAogIDB4MWVlNiwKICAiVWhvcm4iLAogIDB4MDFhZiwKICAiVWhvcm5hY3V0ZSIsCiAgMHgxZWU4LAogICJVaG9ybmRvdGJlbG93IiwKICAweDFlZjAsCiAgIlVob3JuZ3JhdmUiLAogIDB4MWVlYSwKICAiVWhvcm5ob29rYWJvdmUiLAogIDB4MWVlYywKICAiVWhvcm50aWxkZSIsCiAgMHgxZWVlLAogICJVaHVuZ2FydW1sYXV0IiwKICAweDAxNzAsCiAgIlVodW5nYXJ1bWxhdXRjeXJpbGxpYyIsCiAgMHgwNGYyLAogICJVaW52ZXJ0ZWRicmV2ZSIsCiAgMHgwMjE2LAogICJVa2N5cmlsbGljIiwKICAweDA0NzgsCiAgIlVtYWNyb24iLAogIDB4MDE2YSwKICAiVW1hY3JvbmN5cmlsbGljIiwKICAweDA0ZWUsCiAgIlVtYWNyb25kaWVyZXNpcyIsCiAgMHgxZTdhLAogICJVbW9ub3NwYWNlIiwKICAweGZmMzUsCiAgIlVvZ29uZWsiLAogIDB4MDE3MiwKICAiVXBzaWxvbiIsCiAgMHgwM2E1LAogICJVcHNpbG9uMSIsCiAgMHgwM2QyLAogICJVcHNpbG9uYWN1dGVob29rc3ltYm9sZ3JlZWsiLAogIDB4MDNkMywKICAiVXBzaWxvbmFmcmljYW4iLAogIDB4MDFiMSwKICAiVXBzaWxvbmRpZXJlc2lzIiwKICAweDAzYWIsCiAgIlVwc2lsb25kaWVyZXNpc2hvb2tzeW1ib2xncmVlayIsCiAgMHgwM2Q0LAogICJVcHNpbG9uaG9va3N5bWJvbCIsCiAgMHgwM2QyLAogICJVcHNpbG9udG9ub3MiLAogIDB4MDM4ZSwKICAiVXJpbmciLAogIDB4MDE2ZSwKICAiVXNob3J0Y3lyaWxsaWMiLAogIDB4MDQwZSwKICAiVXNtYWxsIiwKICAweGY3NzUsCiAgIlVzdHJhaWdodGN5cmlsbGljIiwKICAweDA0YWUsCiAgIlVzdHJhaWdodHN0cm9rZWN5cmlsbGljIiwKICAweDA0YjAsCiAgIlV0aWxkZSIsCiAgMHgwMTY4LAogICJVdGlsZGVhY3V0ZSIsCiAgMHgxZTc4LAogICJVdGlsZGViZWxvdyIsCiAgMHgxZTc0LAogICJWIiwKICAweDAwNTYsCiAgIlZjaXJjbGUiLAogIDB4MjRjYiwKICAiVmRvdGJlbG93IiwKICAweDFlN2UsCiAgIlZlY3lyaWxsaWMiLAogIDB4MDQxMiwKICAiVmV3YXJtZW5pYW4iLAogIDB4MDU0ZSwKICAiVmhvb2siLAogIDB4MDFiMiwKICAiVm1vbm9zcGFjZSIsCiAgMHhmZjM2LAogICJWb2FybWVuaWFuIiwKICAweDA1NDgsCiAgIlZzbWFsbCIsCiAgMHhmNzc2LAogICJWdGlsZGUiLAogIDB4MWU3YywKICAiVyIsCiAgMHgwMDU3LAogICJXYWN1dGUiLAogIDB4MWU4MiwKICAiV2NpcmNsZSIsCiAgMHgyNGNjLAogICJXY2lyY3VtZmxleCIsCiAgMHgwMTc0LAogICJXZGllcmVzaXMiLAogIDB4MWU4NCwKICAiV2RvdGFjY2VudCIsCiAgMHgxZTg2LAogICJXZG90YmVsb3ciLAogIDB4MWU4OCwKICAiV2dyYXZlIiwKICAweDFlODAsCiAgIldtb25vc3BhY2UiLAogIDB4ZmYzNywKICAiV3NtYWxsIiwKICAweGY3NzcsCiAgIlgiLAogIDB4MDA1OCwKICAiWGNpcmNsZSIsCiAgMHgyNGNkLAogICJYZGllcmVzaXMiLAogIDB4MWU4YywKICAiWGRvdGFjY2VudCIsCiAgMHgxZThhLAogICJYZWhhcm1lbmlhbiIsCiAgMHgwNTNkLAogICJYaSIsCiAgMHgwMzllLAogICJYbW9ub3NwYWNlIiwKICAweGZmMzgsCiAgIlhzbWFsbCIsCiAgMHhmNzc4LAogICJZIiwKICAweDAwNTksCiAgIllhY3V0ZSIsCiAgMHgwMGRkLAogICJZYWN1dGVzbWFsbCIsCiAgMHhmN2ZkLAogICJZYXRjeXJpbGxpYyIsCiAgMHgwNDYyLAogICJZY2lyY2xlIiwKICAweDI0Y2UsCiAgIlljaXJjdW1mbGV4IiwKICAweDAxNzYsCiAgIllkaWVyZXNpcyIsCiAgMHgwMTc4LAogICJZZGllcmVzaXNzbWFsbCIsCiAgMHhmN2ZmLAogICJZZG90YWNjZW50IiwKICAweDFlOGUsCiAgIllkb3RiZWxvdyIsCiAgMHgxZWY0LAogICJZZXJpY3lyaWxsaWMiLAogIDB4MDQyYiwKICAiWWVydWRpZXJlc2lzY3lyaWxsaWMiLAogIDB4MDRmOCwKICAiWWdyYXZlIiwKICAweDFlZjIsCiAgIllob29rIiwKICAweDAxYjMsCiAgIllob29rYWJvdmUiLAogIDB4MWVmNiwKICAiWWlhcm1lbmlhbiIsCiAgMHgwNTQ1LAogICJZaWN5cmlsbGljIiwKICAweDA0MDcsCiAgIllpd25hcm1lbmlhbiIsCiAgMHgwNTUyLAogICJZbW9ub3NwYWNlIiwKICAweGZmMzksCiAgIllzbWFsbCIsCiAgMHhmNzc5LAogICJZdGlsZGUiLAogIDB4MWVmOCwKICAiWXVzYmlnY3lyaWxsaWMiLAogIDB4MDQ2YSwKICAiWXVzYmlnaW90aWZpZWRjeXJpbGxpYyIsCiAgMHgwNDZjLAogICJZdXNsaXR0bGVjeXJpbGxpYyIsCiAgMHgwNDY2LAogICJZdXNsaXR0bGVpb3RpZmllZGN5cmlsbGljIiwKICAweDA0NjgsCiAgIloiLAogIDB4MDA1YSwKICAiWmFhcm1lbmlhbiIsCiAgMHgwNTM2LAogICJaYWN1dGUiLAogIDB4MDE3OSwKICAiWmNhcm9uIiwKICAweDAxN2QsCiAgIlpjYXJvbnNtYWxsIiwKICAweGY2ZmYsCiAgIlpjaXJjbGUiLAogIDB4MjRjZiwKICAiWmNpcmN1bWZsZXgiLAogIDB4MWU5MCwKICAiWmRvdCIsCiAgMHgwMTdiLAogICJaZG90YWNjZW50IiwKICAweDAxN2IsCiAgIlpkb3RiZWxvdyIsCiAgMHgxZTkyLAogICJaZWN5cmlsbGljIiwKICAweDA0MTcsCiAgIlplZGVzY2VuZGVyY3lyaWxsaWMiLAogIDB4MDQ5OCwKICAiWmVkaWVyZXNpc2N5cmlsbGljIiwKICAweDA0ZGUsCiAgIlpldGEiLAogIDB4MDM5NiwKICAiWmhlYXJtZW5pYW4iLAogIDB4MDUzYSwKICAiWmhlYnJldmVjeXJpbGxpYyIsCiAgMHgwNGMxLAogICJaaGVjeXJpbGxpYyIsCiAgMHgwNDE2LAogICJaaGVkZXNjZW5kZXJjeXJpbGxpYyIsCiAgMHgwNDk2LAogICJaaGVkaWVyZXNpc2N5cmlsbGljIiwKICAweDA0ZGMsCiAgIlpsaW5lYmVsb3ciLAogIDB4MWU5NCwKICAiWm1vbm9zcGFjZSIsCiAgMHhmZjNhLAogICJac21hbGwiLAogIDB4Zjc3YSwKICAiWnN0cm9rZSIsCiAgMHgwMWI1LAogICJhIiwKICAweDAwNjEsCiAgImFhYmVuZ2FsaSIsCiAgMHgwOTg2LAogICJhYWN1dGUiLAogIDB4MDBlMSwKICAiYWFkZXZhIiwKICAweDA5MDYsCiAgImFhZ3VqYXJhdGkiLAogIDB4MGE4NiwKICAiYWFndXJtdWtoaSIsCiAgMHgwYTA2LAogICJhYW1hdHJhZ3VybXVraGkiLAogIDB4MGEzZSwKICAiYWFydXNxdWFyZSIsCiAgMHgzMzAzLAogICJhYXZvd2Vsc2lnbmJlbmdhbGkiLAogIDB4MDliZSwKICAiYWF2b3dlbHNpZ25kZXZhIiwKICAweDA5M2UsCiAgImFhdm93ZWxzaWduZ3VqYXJhdGkiLAogIDB4MGFiZSwKICAiYWJicmV2aWF0aW9ubWFya2FybWVuaWFuIiwKICAweDA1NWYsCiAgImFiYnJldmlhdGlvbnNpZ25kZXZhIiwKICAweDA5NzAsCiAgImFiZW5nYWxpIiwKICAweDA5ODUsCiAgImFib3BvbW9mbyIsCiAgMHgzMTFhLAogICJhYnJldmUiLAogIDB4MDEwMywKICAiYWJyZXZlYWN1dGUiLAogIDB4MWVhZiwKICAiYWJyZXZlY3lyaWxsaWMiLAogIDB4MDRkMSwKICAiYWJyZXZlZG90YmVsb3ciLAogIDB4MWViNywKICAiYWJyZXZlZ3JhdmUiLAogIDB4MWViMSwKICAiYWJyZXZlaG9va2Fib3ZlIiwKICAweDFlYjMsCiAgImFicmV2ZXRpbGRlIiwKICAweDFlYjUsCiAgImFjYXJvbiIsCiAgMHgwMWNlLAogICJhY2lyY2xlIiwKICAweDI0ZDAsCiAgImFjaXJjdW1mbGV4IiwKICAweDAwZTIsCiAgImFjaXJjdW1mbGV4YWN1dGUiLAogIDB4MWVhNSwKICAiYWNpcmN1bWZsZXhkb3RiZWxvdyIsCiAgMHgxZWFkLAogICJhY2lyY3VtZmxleGdyYXZlIiwKICAweDFlYTcsCiAgImFjaXJjdW1mbGV4aG9va2Fib3ZlIiwKICAweDFlYTksCiAgImFjaXJjdW1mbGV4dGlsZGUiLAogIDB4MWVhYiwKICAiYWN1dGUiLAogIDB4MDBiNCwKICAiYWN1dGViZWxvd2NtYiIsCiAgMHgwMzE3LAogICJhY3V0ZWNtYiIsCiAgMHgwMzAxLAogICJhY3V0ZWNvbWIiLAogIDB4MDMwMSwKICAiYWN1dGVkZXZhIiwKICAweDA5NTQsCiAgImFjdXRlbG93bW9kIiwKICAweDAyY2YsCiAgImFjdXRldG9uZWNtYiIsCiAgMHgwMzQxLAogICJhY3lyaWxsaWMiLAogIDB4MDQzMCwKICAiYWRibGdyYXZlIiwKICAweDAyMDEsCiAgImFkZGFrZ3VybXVraGkiLAogIDB4MGE3MSwKICAiYWRldmEiLAogIDB4MDkwNSwKICAiYWRpZXJlc2lzIiwKICAweDAwZTQsCiAgImFkaWVyZXNpc2N5cmlsbGljIiwKICAweDA0ZDMsCiAgImFkaWVyZXNpc21hY3JvbiIsCiAgMHgwMWRmLAogICJhZG90YmVsb3ciLAogIDB4MWVhMSwKICAiYWRvdG1hY3JvbiIsCiAgMHgwMWUxLAogICJhZSIsCiAgMHgwMGU2LAogICJhZWFjdXRlIiwKICAweDAxZmQsCiAgImFla29yZWFuIiwKICAweDMxNTAsCiAgImFlbWFjcm9uIiwKICAweDAxZTMsCiAgImFmaWkwMDIwOCIsCiAgMHgyMDE1LAogICJhZmlpMDg5NDEiLAogIDB4MjBhNCwKICAiYWZpaTEwMDE3IiwKICAweDA0MTAsCiAgImFmaWkxMDAxOCIsCiAgMHgwNDExLAogICJhZmlpMTAwMTkiLAogIDB4MDQxMiwKICAiYWZpaTEwMDIwIiwKICAweDA0MTMsCiAgImFmaWkxMDAyMSIsCiAgMHgwNDE0LAogICJhZmlpMTAwMjIiLAogIDB4MDQxNSwKICAiYWZpaTEwMDIzIiwKICAweDA0MDEsCiAgImFmaWkxMDAyNCIsCiAgMHgwNDE2LAogICJhZmlpMTAwMjUiLAogIDB4MDQxNywKICAiYWZpaTEwMDI2IiwKICAweDA0MTgsCiAgImFmaWkxMDAyNyIsCiAgMHgwNDE5LAogICJhZmlpMTAwMjgiLAogIDB4MDQxYSwKICAiYWZpaTEwMDI5IiwKICAweDA0MWIsCiAgImFmaWkxMDAzMCIsCiAgMHgwNDFjLAogICJhZmlpMTAwMzEiLAogIDB4MDQxZCwKICAiYWZpaTEwMDMyIiwKICAweDA0MWUsCiAgImFmaWkxMDAzMyIsCiAgMHgwNDFmLAogICJhZmlpMTAwMzQiLAogIDB4MDQyMCwKICAiYWZpaTEwMDM1IiwKICAweDA0MjEsCiAgImFmaWkxMDAzNiIsCiAgMHgwNDIyLAogICJhZmlpMTAwMzciLAogIDB4MDQyMywKICAiYWZpaTEwMDM4IiwKICAweDA0MjQsCiAgImFmaWkxMDAzOSIsCiAgMHgwNDI1LAogICJhZmlpMTAwNDAiLAogIDB4MDQyNiwKICAiYWZpaTEwMDQxIiwKICAweDA0MjcsCiAgImFmaWkxMDA0MiIsCiAgMHgwNDI4LAogICJhZmlpMTAwNDMiLAogIDB4MDQyOSwKICAiYWZpaTEwMDQ0IiwKICAweDA0MmEsCiAgImFmaWkxMDA0NSIsCiAgMHgwNDJiLAogICJhZmlpMTAwNDYiLAogIDB4MDQyYywKICAiYWZpaTEwMDQ3IiwKICAweDA0MmQsCiAgImFmaWkxMDA0OCIsCiAgMHgwNDJlLAogICJhZmlpMTAwNDkiLAogIDB4MDQyZiwKICAiYWZpaTEwMDUwIiwKICAweDA0OTAsCiAgImFmaWkxMDA1MSIsCiAgMHgwNDAyLAogICJhZmlpMTAwNTIiLAogIDB4MDQwMywKICAiYWZpaTEwMDUzIiwKICAweDA0MDQsCiAgImFmaWkxMDA1NCIsCiAgMHgwNDA1LAogICJhZmlpMTAwNTUiLAogIDB4MDQwNiwKICAiYWZpaTEwMDU2IiwKICAweDA0MDcsCiAgImFmaWkxMDA1NyIsCiAgMHgwNDA4LAogICJhZmlpMTAwNTgiLAogIDB4MDQwOSwKICAiYWZpaTEwMDU5IiwKICAweDA0MGEsCiAgImFmaWkxMDA2MCIsCiAgMHgwNDBiLAogICJhZmlpMTAwNjEiLAogIDB4MDQwYywKICAiYWZpaTEwMDYyIiwKICAweDA0MGUsCiAgImFmaWkxMDA2MyIsCiAgMHhmNmM0LAogICJhZmlpMTAwNjQiLAogIDB4ZjZjNSwKICAiYWZpaTEwMDY1IiwKICAweDA0MzAsCiAgImFmaWkxMDA2NiIsCiAgMHgwNDMxLAogICJhZmlpMTAwNjciLAogIDB4MDQzMiwKICAiYWZpaTEwMDY4IiwKICAweDA0MzMsCiAgImFmaWkxMDA2OSIsCiAgMHgwNDM0LAogICJhZmlpMTAwNzAiLAogIDB4MDQzNSwKICAiYWZpaTEwMDcxIiwKICAweDA0NTEsCiAgImFmaWkxMDA3MiIsCiAgMHgwNDM2LAogICJhZmlpMTAwNzMiLAogIDB4MDQzNywKICAiYWZpaTEwMDc0IiwKICAweDA0MzgsCiAgImFmaWkxMDA3NSIsCiAgMHgwNDM5LAogICJhZmlpMTAwNzYiLAogIDB4MDQzYSwKICAiYWZpaTEwMDc3IiwKICAweDA0M2IsCiAgImFmaWkxMDA3OCIsCiAgMHgwNDNjLAogICJhZmlpMTAwNzkiLAogIDB4MDQzZCwKICAiYWZpaTEwMDgwIiwKICAweDA0M2UsCiAgImFmaWkxMDA4MSIsCiAgMHgwNDNmLAogICJhZmlpMTAwODIiLAogIDB4MDQ0MCwKICAiYWZpaTEwMDgzIiwKICAweDA0NDEsCiAgImFmaWkxMDA4NCIsCiAgMHgwNDQyLAogICJhZmlpMTAwODUiLAogIDB4MDQ0MywKICAiYWZpaTEwMDg2IiwKICAweDA0NDQsCiAgImFmaWkxMDA4NyIsCiAgMHgwNDQ1LAogICJhZmlpMTAwODgiLAogIDB4MDQ0NiwKICAiYWZpaTEwMDg5IiwKICAweDA0NDcsCiAgImFmaWkxMDA5MCIsCiAgMHgwNDQ4LAogICJhZmlpMTAwOTEiLAogIDB4MDQ0OSwKICAiYWZpaTEwMDkyIiwKICAweDA0NGEsCiAgImFmaWkxMDA5MyIsCiAgMHgwNDRiLAogICJhZmlpMTAwOTQiLAogIDB4MDQ0YywKICAiYWZpaTEwMDk1IiwKICAweDA0NGQsCiAgImFmaWkxMDA5NiIsCiAgMHgwNDRlLAogICJhZmlpMTAwOTciLAogIDB4MDQ0ZiwKICAiYWZpaTEwMDk4IiwKICAweDA0OTEsCiAgImFmaWkxMDA5OSIsCiAgMHgwNDUyLAogICJhZmlpMTAxMDAiLAogIDB4MDQ1MywKICAiYWZpaTEwMTAxIiwKICAweDA0NTQsCiAgImFmaWkxMDEwMiIsCiAgMHgwNDU1LAogICJhZmlpMTAxMDMiLAogIDB4MDQ1NiwKICAiYWZpaTEwMTA0IiwKICAweDA0NTcsCiAgImFmaWkxMDEwNSIsCiAgMHgwNDU4LAogICJhZmlpMTAxMDYiLAogIDB4MDQ1OSwKICAiYWZpaTEwMTA3IiwKICAweDA0NWEsCiAgImFmaWkxMDEwOCIsCiAgMHgwNDViLAogICJhZmlpMTAxMDkiLAogIDB4MDQ1YywKICAiYWZpaTEwMTEwIiwKICAweDA0NWUsCiAgImFmaWkxMDE0NSIsCiAgMHgwNDBmLAogICJhZmlpMTAxNDYiLAogIDB4MDQ2MiwKICAiYWZpaTEwMTQ3IiwKICAweDA0NzIsCiAgImFmaWkxMDE0OCIsCiAgMHgwNDc0LAogICJhZmlpMTAxOTIiLAogIDB4ZjZjNiwKICAiYWZpaTEwMTkzIiwKICAweDA0NWYsCiAgImFmaWkxMDE5NCIsCiAgMHgwNDYzLAogICJhZmlpMTAxOTUiLAogIDB4MDQ3MywKICAiYWZpaTEwMTk2IiwKICAweDA0NzUsCiAgImFmaWkxMDgzMSIsCiAgMHhmNmM3LAogICJhZmlpMTA4MzIiLAogIDB4ZjZjOCwKICAiYWZpaTEwODQ2IiwKICAweDA0ZDksCiAgImFmaWkyOTkiLAogIDB4MjAwZSwKICAiYWZpaTMwMCIsCiAgMHgyMDBmLAogICJhZmlpMzAxIiwKICAweDIwMGQsCiAgImFmaWk1NzM4MSIsCiAgMHgwNjZhLAogICJhZmlpNTczODgiLAogIDB4MDYwYywKICAiYWZpaTU3MzkyIiwKICAweDA2NjAsCiAgImFmaWk1NzM5MyIsCiAgMHgwNjYxLAogICJhZmlpNTczOTQiLAogIDB4MDY2MiwKICAiYWZpaTU3Mzk1IiwKICAweDA2NjMsCiAgImFmaWk1NzM5NiIsCiAgMHgwNjY0LAogICJhZmlpNTczOTciLAogIDB4MDY2NSwKICAiYWZpaTU3Mzk4IiwKICAweDA2NjYsCiAgImFmaWk1NzM5OSIsCiAgMHgwNjY3LAogICJhZmlpNTc0MDAiLAogIDB4MDY2OCwKICAiYWZpaTU3NDAxIiwKICAweDA2NjksCiAgImFmaWk1NzQwMyIsCiAgMHgwNjFiLAogICJhZmlpNTc0MDciLAogIDB4MDYxZiwKICAiYWZpaTU3NDA5IiwKICAweDA2MjEsCiAgImFmaWk1NzQxMCIsCiAgMHgwNjIyLAogICJhZmlpNTc0MTEiLAogIDB4MDYyMywKICAiYWZpaTU3NDEyIiwKICAweDA2MjQsCiAgImFmaWk1NzQxMyIsCiAgMHgwNjI1LAogICJhZmlpNTc0MTQiLAogIDB4MDYyNiwKICAiYWZpaTU3NDE1IiwKICAweDA2MjcsCiAgImFmaWk1NzQxNiIsCiAgMHgwNjI4LAogICJhZmlpNTc0MTciLAogIDB4MDYyOSwKICAiYWZpaTU3NDE4IiwKICAweDA2MmEsCiAgImFmaWk1NzQxOSIsCiAgMHgwNjJiLAogICJhZmlpNTc0MjAiLAogIDB4MDYyYywKICAiYWZpaTU3NDIxIiwKICAweDA2MmQsCiAgImFmaWk1NzQyMiIsCiAgMHgwNjJlLAogICJhZmlpNTc0MjMiLAogIDB4MDYyZiwKICAiYWZpaTU3NDI0IiwKICAweDA2MzAsCiAgImFmaWk1NzQyNSIsCiAgMHgwNjMxLAogICJhZmlpNTc0MjYiLAogIDB4MDYzMiwKICAiYWZpaTU3NDI3IiwKICAweDA2MzMsCiAgImFmaWk1NzQyOCIsCiAgMHgwNjM0LAogICJhZmlpNTc0MjkiLAogIDB4MDYzNSwKICAiYWZpaTU3NDMwIiwKICAweDA2MzYsCiAgImFmaWk1NzQzMSIsCiAgMHgwNjM3LAogICJhZmlpNTc0MzIiLAogIDB4MDYzOCwKICAiYWZpaTU3NDMzIiwKICAweDA2MzksCiAgImFmaWk1NzQzNCIsCiAgMHgwNjNhLAogICJhZmlpNTc0NDAiLAogIDB4MDY0MCwKICAiYWZpaTU3NDQxIiwKICAweDA2NDEsCiAgImFmaWk1NzQ0MiIsCiAgMHgwNjQyLAogICJhZmlpNTc0NDMiLAogIDB4MDY0MywKICAiYWZpaTU3NDQ0IiwKICAweDA2NDQsCiAgImFmaWk1NzQ0NSIsCiAgMHgwNjQ1LAogICJhZmlpNTc0NDYiLAogIDB4MDY0NiwKICAiYWZpaTU3NDQ4IiwKICAweDA2NDgsCiAgImFmaWk1NzQ0OSIsCiAgMHgwNjQ5LAogICJhZmlpNTc0NTAiLAogIDB4MDY0YSwKICAiYWZpaTU3NDUxIiwKICAweDA2NGIsCiAgImFmaWk1NzQ1MiIsCiAgMHgwNjRjLAogICJhZmlpNTc0NTMiLAogIDB4MDY0ZCwKICAiYWZpaTU3NDU0IiwKICAweDA2NGUsCiAgImFmaWk1NzQ1NSIsCiAgMHgwNjRmLAogICJhZmlpNTc0NTYiLAogIDB4MDY1MCwKICAiYWZpaTU3NDU3IiwKICAweDA2NTEsCiAgImFmaWk1NzQ1OCIsCiAgMHgwNjUyLAogICJhZmlpNTc0NzAiLAogIDB4MDY0NywKICAiYWZpaTU3NTA1IiwKICAweDA2YTQsCiAgImFmaWk1NzUwNiIsCiAgMHgwNjdlLAogICJhZmlpNTc1MDciLAogIDB4MDY4NiwKICAiYWZpaTU3NTA4IiwKICAweDA2OTgsCiAgImFmaWk1NzUwOSIsCiAgMHgwNmFmLAogICJhZmlpNTc1MTEiLAogIDB4MDY3OSwKICAiYWZpaTU3NTEyIiwKICAweDA2ODgsCiAgImFmaWk1NzUxMyIsCiAgMHgwNjkxLAogICJhZmlpNTc1MTQiLAogIDB4MDZiYSwKICAiYWZpaTU3NTE5IiwKICAweDA2ZDIsCiAgImFmaWk1NzUzNCIsCiAgMHgwNmQ1LAogICJhZmlpNTc2MzYiLAogIDB4MjBhYSwKICAiYWZpaTU3NjQ1IiwKICAweDA1YmUsCiAgImFmaWk1NzY1OCIsCiAgMHgwNWMzLAogICJhZmlpNTc2NjQiLAogIDB4MDVkMCwKICAiYWZpaTU3NjY1IiwKICAweDA1ZDEsCiAgImFmaWk1NzY2NiIsCiAgMHgwNWQyLAogICJhZmlpNTc2NjciLAogIDB4MDVkMywKICAiYWZpaTU3NjY4IiwKICAweDA1ZDQsCiAgImFmaWk1NzY2OSIsCiAgMHgwNWQ1LAogICJhZmlpNTc2NzAiLAogIDB4MDVkNiwKICAiYWZpaTU3NjcxIiwKICAweDA1ZDcsCiAgImFmaWk1NzY3MiIsCiAgMHgwNWQ4LAogICJhZmlpNTc2NzMiLAogIDB4MDVkOSwKICAiYWZpaTU3Njc0IiwKICAweDA1ZGEsCiAgImFmaWk1NzY3NSIsCiAgMHgwNWRiLAogICJhZmlpNTc2NzYiLAogIDB4MDVkYywKICAiYWZpaTU3Njc3IiwKICAweDA1ZGQsCiAgImFmaWk1NzY3OCIsCiAgMHgwNWRlLAogICJhZmlpNTc2NzkiLAogIDB4MDVkZiwKICAiYWZpaTU3NjgwIiwKICAweDA1ZTAsCiAgImFmaWk1NzY4MSIsCiAgMHgwNWUxLAogICJhZmlpNTc2ODIiLAogIDB4MDVlMiwKICAiYWZpaTU3NjgzIiwKICAweDA1ZTMsCiAgImFmaWk1NzY4NCIsCiAgMHgwNWU0LAogICJhZmlpNTc2ODUiLAogIDB4MDVlNSwKICAiYWZpaTU3Njg2IiwKICAweDA1ZTYsCiAgImFmaWk1NzY4NyIsCiAgMHgwNWU3LAogICJhZmlpNTc2ODgiLAogIDB4MDVlOCwKICAiYWZpaTU3Njg5IiwKICAweDA1ZTksCiAgImFmaWk1NzY5MCIsCiAgMHgwNWVhLAogICJhZmlpNTc2OTQiLAogIDB4ZmIyYSwKICAiYWZpaTU3Njk1IiwKICAweGZiMmIsCiAgImFmaWk1NzcwMCIsCiAgMHhmYjRiLAogICJhZmlpNTc3MDUiLAogIDB4ZmIxZiwKICAiYWZpaTU3NzE2IiwKICAweDA1ZjAsCiAgImFmaWk1NzcxNyIsCiAgMHgwNWYxLAogICJhZmlpNTc3MTgiLAogIDB4MDVmMiwKICAiYWZpaTU3NzIzIiwKICAweGZiMzUsCiAgImFmaWk1Nzc5MyIsCiAgMHgwNWI0LAogICJhZmlpNTc3OTQiLAogIDB4MDViNSwKICAiYWZpaTU3Nzk1IiwKICAweDA1YjYsCiAgImFmaWk1Nzc5NiIsCiAgMHgwNWJiLAogICJhZmlpNTc3OTciLAogIDB4MDViOCwKICAiYWZpaTU3Nzk4IiwKICAweDA1YjcsCiAgImFmaWk1Nzc5OSIsCiAgMHgwNWIwLAogICJhZmlpNTc4MDAiLAogIDB4MDViMiwKICAiYWZpaTU3ODAxIiwKICAweDA1YjEsCiAgImFmaWk1NzgwMiIsCiAgMHgwNWIzLAogICJhZmlpNTc4MDMiLAogIDB4MDVjMiwKICAiYWZpaTU3ODA0IiwKICAweDA1YzEsCiAgImFmaWk1NzgwNiIsCiAgMHgwNWI5LAogICJhZmlpNTc4MDciLAogIDB4MDViYywKICAiYWZpaTU3ODM5IiwKICAweDA1YmQsCiAgImFmaWk1Nzg0MSIsCiAgMHgwNWJmLAogICJhZmlpNTc4NDIiLAogIDB4MDVjMCwKICAiYWZpaTU3OTI5IiwKICAweDAyYmMsCiAgImFmaWk2MTI0OCIsCiAgMHgyMTA1LAogICJhZmlpNjEyODkiLAogIDB4MjExMywKICAiYWZpaTYxMzUyIiwKICAweDIxMTYsCiAgImFmaWk2MTU3MyIsCiAgMHgyMDJjLAogICJhZmlpNjE1NzQiLAogIDB4MjAyZCwKICAiYWZpaTYxNTc1IiwKICAweDIwMmUsCiAgImFmaWk2MTY2NCIsCiAgMHgyMDBjLAogICJhZmlpNjMxNjciLAogIDB4MDY2ZCwKICAiYWZpaTY0OTM3IiwKICAweDAyYmQsCiAgImFncmF2ZSIsCiAgMHgwMGUwLAogICJhZ3VqYXJhdGkiLAogIDB4MGE4NSwKICAiYWd1cm11a2hpIiwKICAweDBhMDUsCiAgImFoaXJhZ2FuYSIsCiAgMHgzMDQyLAogICJhaG9va2Fib3ZlIiwKICAweDFlYTMsCiAgImFpYmVuZ2FsaSIsCiAgMHgwOTkwLAogICJhaWJvcG9tb2ZvIiwKICAweDMxMWUsCiAgImFpZGV2YSIsCiAgMHgwOTEwLAogICJhaWVjeXJpbGxpYyIsCiAgMHgwNGQ1LAogICJhaWd1amFyYXRpIiwKICAweDBhOTAsCiAgImFpZ3VybXVraGkiLAogIDB4MGExMCwKICAiYWltYXRyYWd1cm11a2hpIiwKICAweDBhNDgsCiAgImFpbmFyYWJpYyIsCiAgMHgwNjM5LAogICJhaW5maW5hbGFyYWJpYyIsCiAgMHhmZWNhLAogICJhaW5pbml0aWFsYXJhYmljIiwKICAweGZlY2IsCiAgImFpbm1lZGlhbGFyYWJpYyIsCiAgMHhmZWNjLAogICJhaW52ZXJ0ZWRicmV2ZSIsCiAgMHgwMjAzLAogICJhaXZvd2Vsc2lnbmJlbmdhbGkiLAogIDB4MDljOCwKICAiYWl2b3dlbHNpZ25kZXZhIiwKICAweDA5NDgsCiAgImFpdm93ZWxzaWduZ3VqYXJhdGkiLAogIDB4MGFjOCwKICAiYWthdGFrYW5hIiwKICAweDMwYTIsCiAgImFrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjcxLAogICJha29yZWFuIiwKICAweDMxNGYsCiAgImFsZWYiLAogIDB4MDVkMCwKICAiYWxlZmFyYWJpYyIsCiAgMHgwNjI3LAogICJhbGVmZGFnZXNoaGVicmV3IiwKICAweGZiMzAsCiAgImFsZWZmaW5hbGFyYWJpYyIsCiAgMHhmZThlLAogICJhbGVmaGFtemFhYm92ZWFyYWJpYyIsCiAgMHgwNjIzLAogICJhbGVmaGFtemFhYm92ZWZpbmFsYXJhYmljIiwKICAweGZlODQsCiAgImFsZWZoYW16YWJlbG93YXJhYmljIiwKICAweDA2MjUsCiAgImFsZWZoYW16YWJlbG93ZmluYWxhcmFiaWMiLAogIDB4ZmU4OCwKICAiYWxlZmhlYnJldyIsCiAgMHgwNWQwLAogICJhbGVmbGFtZWRoZWJyZXciLAogIDB4ZmI0ZiwKICAiYWxlZm1hZGRhYWJvdmVhcmFiaWMiLAogIDB4MDYyMiwKICAiYWxlZm1hZGRhYWJvdmVmaW5hbGFyYWJpYyIsCiAgMHhmZTgyLAogICJhbGVmbWFrc3VyYWFyYWJpYyIsCiAgMHgwNjQ5LAogICJhbGVmbWFrc3VyYWZpbmFsYXJhYmljIiwKICAweGZlZjAsCiAgImFsZWZtYWtzdXJhaW5pdGlhbGFyYWJpYyIsCiAgMHhmZWYzLAogICJhbGVmbWFrc3VyYW1lZGlhbGFyYWJpYyIsCiAgMHhmZWY0LAogICJhbGVmcGF0YWhoZWJyZXciLAogIDB4ZmIyZSwKICAiYWxlZnFhbWF0c2hlYnJldyIsCiAgMHhmYjJmLAogICJhbGVwaCIsCiAgMHgyMTM1LAogICJhbGxlcXVhbCIsCiAgMHgyMjRjLAogICJhbHBoYSIsCiAgMHgwM2IxLAogICJhbHBoYXRvbm9zIiwKICAweDAzYWMsCiAgImFtYWNyb24iLAogIDB4MDEwMSwKICAiYW1vbm9zcGFjZSIsCiAgMHhmZjQxLAogICJhbXBlcnNhbmQiLAogIDB4MDAyNiwKICAiYW1wZXJzYW5kbW9ub3NwYWNlIiwKICAweGZmMDYsCiAgImFtcGVyc2FuZHNtYWxsIiwKICAweGY3MjYsCiAgImFtc3F1YXJlIiwKICAweDMzYzIsCiAgImFuYm9wb21vZm8iLAogIDB4MzEyMiwKICAiYW5nYm9wb21vZm8iLAogIDB4MzEyNCwKICAiYW5nYnJhY2tldGxlZnQiLAogIDB4MzAwOCwKICAiYW5nYnJhY2tldHJpZ2h0IiwKICAweDMwMDksCiAgImFuZ2toYW5raHV0aGFpIiwKICAweDBlNWEsCiAgImFuZ2xlIiwKICAweDIyMjAsCiAgImFuZ2xlYnJhY2tldGxlZnQiLAogIDB4MzAwOCwKICAiYW5nbGVicmFja2V0bGVmdHZlcnRpY2FsIiwKICAweGZlM2YsCiAgImFuZ2xlYnJhY2tldHJpZ2h0IiwKICAweDMwMDksCiAgImFuZ2xlYnJhY2tldHJpZ2h0dmVydGljYWwiLAogIDB4ZmU0MCwKICAiYW5nbGVsZWZ0IiwKICAweDIzMjksCiAgImFuZ2xlcmlnaHQiLAogIDB4MjMyYSwKICAiYW5nc3Ryb20iLAogIDB4MjEyYiwKICAiYW5vdGVsZWlhIiwKICAweDAzODcsCiAgImFudWRhdHRhZGV2YSIsCiAgMHgwOTUyLAogICJhbnVzdmFyYWJlbmdhbGkiLAogIDB4MDk4MiwKICAiYW51c3ZhcmFkZXZhIiwKICAweDA5MDIsCiAgImFudXN2YXJhZ3VqYXJhdGkiLAogIDB4MGE4MiwKICAiYW9nb25layIsCiAgMHgwMTA1LAogICJhcGFhdG9zcXVhcmUiLAogIDB4MzMwMCwKICAiYXBhcmVuIiwKICAweDI0OWMsCiAgImFwb3N0cm9waGVhcm1lbmlhbiIsCiAgMHgwNTVhLAogICJhcG9zdHJvcGhlbW9kIiwKICAweDAyYmMsCiAgImFwcGxlIiwKICAweGY4ZmYsCiAgImFwcHJvYWNoZXMiLAogIDB4MjI1MCwKICAiYXBwcm94ZXF1YWwiLAogIDB4MjI0OCwKICAiYXBwcm94ZXF1YWxvcmltYWdlIiwKICAweDIyNTIsCiAgImFwcHJveGltYXRlbHllcXVhbCIsCiAgMHgyMjQ1LAogICJhcmFlYWVrb3JlYW4iLAogIDB4MzE4ZSwKICAiYXJhZWFrb3JlYW4iLAogIDB4MzE4ZCwKICAiYXJjIiwKICAweDIzMTIsCiAgImFyaWdodGhhbGZyaW5nIiwKICAweDFlOWEsCiAgImFyaW5nIiwKICAweDAwZTUsCiAgImFyaW5nYWN1dGUiLAogIDB4MDFmYiwKICAiYXJpbmdiZWxvdyIsCiAgMHgxZTAxLAogICJhcnJvd2JvdGgiLAogIDB4MjE5NCwKICAiYXJyb3dkYXNoZG93biIsCiAgMHgyMWUzLAogICJhcnJvd2Rhc2hsZWZ0IiwKICAweDIxZTAsCiAgImFycm93ZGFzaHJpZ2h0IiwKICAweDIxZTIsCiAgImFycm93ZGFzaHVwIiwKICAweDIxZTEsCiAgImFycm93ZGJsYm90aCIsCiAgMHgyMWQ0LAogICJhcnJvd2RibGRvd24iLAogIDB4MjFkMywKICAiYXJyb3dkYmxsZWZ0IiwKICAweDIxZDAsCiAgImFycm93ZGJscmlnaHQiLAogIDB4MjFkMiwKICAiYXJyb3dkYmx1cCIsCiAgMHgyMWQxLAogICJhcnJvd2Rvd24iLAogIDB4MjE5MywKICAiYXJyb3dkb3dubGVmdCIsCiAgMHgyMTk5LAogICJhcnJvd2Rvd25yaWdodCIsCiAgMHgyMTk4LAogICJhcnJvd2Rvd253aGl0ZSIsCiAgMHgyMWU5LAogICJhcnJvd2hlYWRkb3dubW9kIiwKICAweDAyYzUsCiAgImFycm93aGVhZGxlZnRtb2QiLAogIDB4MDJjMiwKICAiYXJyb3doZWFkcmlnaHRtb2QiLAogIDB4MDJjMywKICAiYXJyb3doZWFkdXBtb2QiLAogIDB4MDJjNCwKICAiYXJyb3dob3JpemV4IiwKICAweGY4ZTcsCiAgImFycm93bGVmdCIsCiAgMHgyMTkwLAogICJhcnJvd2xlZnRkYmwiLAogIDB4MjFkMCwKICAiYXJyb3dsZWZ0ZGJsc3Ryb2tlIiwKICAweDIxY2QsCiAgImFycm93bGVmdG92ZXJyaWdodCIsCiAgMHgyMWM2LAogICJhcnJvd2xlZnR3aGl0ZSIsCiAgMHgyMWU2LAogICJhcnJvd3JpZ2h0IiwKICAweDIxOTIsCiAgImFycm93cmlnaHRkYmxzdHJva2UiLAogIDB4MjFjZiwKICAiYXJyb3dyaWdodGhlYXZ5IiwKICAweDI3OWUsCiAgImFycm93cmlnaHRvdmVybGVmdCIsCiAgMHgyMWM0LAogICJhcnJvd3JpZ2h0d2hpdGUiLAogIDB4MjFlOCwKICAiYXJyb3d0YWJsZWZ0IiwKICAweDIxZTQsCiAgImFycm93dGFicmlnaHQiLAogIDB4MjFlNSwKICAiYXJyb3d1cCIsCiAgMHgyMTkxLAogICJhcnJvd3VwZG4iLAogIDB4MjE5NSwKICAiYXJyb3d1cGRuYnNlIiwKICAweDIxYTgsCiAgImFycm93dXBkb3duYmFzZSIsCiAgMHgyMWE4LAogICJhcnJvd3VwbGVmdCIsCiAgMHgyMTk2LAogICJhcnJvd3VwbGVmdG9mZG93biIsCiAgMHgyMWM1LAogICJhcnJvd3VwcmlnaHQiLAogIDB4MjE5NywKICAiYXJyb3d1cHdoaXRlIiwKICAweDIxZTcsCiAgImFycm93dmVydGV4IiwKICAweGY4ZTYsCiAgImFzY2lpY2lyY3VtIiwKICAweDAwNWUsCiAgImFzY2lpY2lyY3VtbW9ub3NwYWNlIiwKICAweGZmM2UsCiAgImFzY2lpdGlsZGUiLAogIDB4MDA3ZSwKICAiYXNjaWl0aWxkZW1vbm9zcGFjZSIsCiAgMHhmZjVlLAogICJhc2NyaXB0IiwKICAweDAyNTEsCiAgImFzY3JpcHR0dXJuZWQiLAogIDB4MDI1MiwKICAiYXNtYWxsaGlyYWdhbmEiLAogIDB4MzA0MSwKICAiYXNtYWxsa2F0YWthbmEiLAogIDB4MzBhMSwKICAiYXNtYWxsa2F0YWthbmFoYWxmd2lkdGgiLAogIDB4ZmY2NywKICAiYXN0ZXJpc2siLAogIDB4MDAyYSwKICAiYXN0ZXJpc2thbHRvbmVhcmFiaWMiLAogIDB4MDY2ZCwKICAiYXN0ZXJpc2thcmFiaWMiLAogIDB4MDY2ZCwKICAiYXN0ZXJpc2ttYXRoIiwKICAweDIyMTcsCiAgImFzdGVyaXNrbW9ub3NwYWNlIiwKICAweGZmMGEsCiAgImFzdGVyaXNrc21hbGwiLAogIDB4ZmU2MSwKICAiYXN0ZXJpc20iLAogIDB4MjA0MiwKICAiYXN1cGVyaW9yIiwKICAweGY2ZTksCiAgImFzeW1wdG90aWNhbGx5ZXF1YWwiLAogIDB4MjI0MywKICAiYXQiLAogIDB4MDA0MCwKICAiYXRpbGRlIiwKICAweDAwZTMsCiAgImF0bW9ub3NwYWNlIiwKICAweGZmMjAsCiAgImF0c21hbGwiLAogIDB4ZmU2YiwKICAiYXR1cm5lZCIsCiAgMHgwMjUwLAogICJhdWJlbmdhbGkiLAogIDB4MDk5NCwKICAiYXVib3BvbW9mbyIsCiAgMHgzMTIwLAogICJhdWRldmEiLAogIDB4MDkxNCwKICAiYXVndWphcmF0aSIsCiAgMHgwYTk0LAogICJhdWd1cm11a2hpIiwKICAweDBhMTQsCiAgImF1bGVuZ3RobWFya2JlbmdhbGkiLAogIDB4MDlkNywKICAiYXVtYXRyYWd1cm11a2hpIiwKICAweDBhNGMsCiAgImF1dm93ZWxzaWduYmVuZ2FsaSIsCiAgMHgwOWNjLAogICJhdXZvd2Vsc2lnbmRldmEiLAogIDB4MDk0YywKICAiYXV2b3dlbHNpZ25ndWphcmF0aSIsCiAgMHgwYWNjLAogICJhdmFncmFoYWRldmEiLAogIDB4MDkzZCwKICAiYXliYXJtZW5pYW4iLAogIDB4MDU2MSwKICAiYXlpbiIsCiAgMHgwNWUyLAogICJheWluYWx0b25laGVicmV3IiwKICAweGZiMjAsCiAgImF5aW5oZWJyZXciLAogIDB4MDVlMiwKICAiYiIsCiAgMHgwMDYyLAogICJiYWJlbmdhbGkiLAogIDB4MDlhYywKICAiYmFja3NsYXNoIiwKICAweDAwNWMsCiAgImJhY2tzbGFzaG1vbm9zcGFjZSIsCiAgMHhmZjNjLAogICJiYWRldmEiLAogIDB4MDkyYywKICAiYmFndWphcmF0aSIsCiAgMHgwYWFjLAogICJiYWd1cm11a2hpIiwKICAweDBhMmMsCiAgImJhaGlyYWdhbmEiLAogIDB4MzA3MCwKICAiYmFodHRoYWkiLAogIDB4MGUzZiwKICAiYmFrYXRha2FuYSIsCiAgMHgzMGQwLAogICJiYXIiLAogIDB4MDA3YywKICAiYmFybW9ub3NwYWNlIiwKICAweGZmNWMsCiAgImJib3BvbW9mbyIsCiAgMHgzMTA1LAogICJiY2lyY2xlIiwKICAweDI0ZDEsCiAgImJkb3RhY2NlbnQiLAogIDB4MWUwMywKICAiYmRvdGJlbG93IiwKICAweDFlMDUsCiAgImJlYW1lZHNpeHRlZW50aG5vdGVzIiwKICAweDI2NmMsCiAgImJlY2F1c2UiLAogIDB4MjIzNSwKICAiYmVjeXJpbGxpYyIsCiAgMHgwNDMxLAogICJiZWhhcmFiaWMiLAogIDB4MDYyOCwKICAiYmVoZmluYWxhcmFiaWMiLAogIDB4ZmU5MCwKICAiYmVoaW5pdGlhbGFyYWJpYyIsCiAgMHhmZTkxLAogICJiZWhpcmFnYW5hIiwKICAweDMwNzksCiAgImJlaG1lZGlhbGFyYWJpYyIsCiAgMHhmZTkyLAogICJiZWhtZWVtaW5pdGlhbGFyYWJpYyIsCiAgMHhmYzlmLAogICJiZWhtZWVtaXNvbGF0ZWRhcmFiaWMiLAogIDB4ZmMwOCwKICAiYmVobm9vbmZpbmFsYXJhYmljIiwKICAweGZjNmQsCiAgImJla2F0YWthbmEiLAogIDB4MzBkOSwKICAiYmVuYXJtZW5pYW4iLAogIDB4MDU2MiwKICAiYmV0IiwKICAweDA1ZDEsCiAgImJldGEiLAogIDB4MDNiMiwKICAiYmV0YXN5bWJvbGdyZWVrIiwKICAweDAzZDAsCiAgImJldGRhZ2VzaCIsCiAgMHhmYjMxLAogICJiZXRkYWdlc2hoZWJyZXciLAogIDB4ZmIzMSwKICAiYmV0aGVicmV3IiwKICAweDA1ZDEsCiAgImJldHJhZmVoZWJyZXciLAogIDB4ZmI0YywKICAiYmhhYmVuZ2FsaSIsCiAgMHgwOWFkLAogICJiaGFkZXZhIiwKICAweDA5MmQsCiAgImJoYWd1amFyYXRpIiwKICAweDBhYWQsCiAgImJoYWd1cm11a2hpIiwKICAweDBhMmQsCiAgImJob29rIiwKICAweDAyNTMsCiAgImJpaGlyYWdhbmEiLAogIDB4MzA3MywKICAiYmlrYXRha2FuYSIsCiAgMHgzMGQzLAogICJiaWxhYmlhbGNsaWNrIiwKICAweDAyOTgsCiAgImJpbmRpZ3VybXVraGkiLAogIDB4MGEwMiwKICAiYmlydXNxdWFyZSIsCiAgMHgzMzMxLAogICJibGFja2NpcmNsZSIsCiAgMHgyNWNmLAogICJibGFja2RpYW1vbmQiLAogIDB4MjVjNiwKICAiYmxhY2tkb3ducG9pbnRpbmd0cmlhbmdsZSIsCiAgMHgyNWJjLAogICJibGFja2xlZnRwb2ludGluZ3BvaW50ZXIiLAogIDB4MjVjNCwKICAiYmxhY2tsZWZ0cG9pbnRpbmd0cmlhbmdsZSIsCiAgMHgyNWMwLAogICJibGFja2xlbnRpY3VsYXJicmFja2V0bGVmdCIsCiAgMHgzMDEwLAogICJibGFja2xlbnRpY3VsYXJicmFja2V0bGVmdHZlcnRpY2FsIiwKICAweGZlM2IsCiAgImJsYWNrbGVudGljdWxhcmJyYWNrZXRyaWdodCIsCiAgMHgzMDExLAogICJibGFja2xlbnRpY3VsYXJicmFja2V0cmlnaHR2ZXJ0aWNhbCIsCiAgMHhmZTNjLAogICJibGFja2xvd2VybGVmdHRyaWFuZ2xlIiwKICAweDI1ZTMsCiAgImJsYWNrbG93ZXJyaWdodHRyaWFuZ2xlIiwKICAweDI1ZTIsCiAgImJsYWNrcmVjdGFuZ2xlIiwKICAweDI1YWMsCiAgImJsYWNrcmlnaHRwb2ludGluZ3BvaW50ZXIiLAogIDB4MjViYSwKICAiYmxhY2tyaWdodHBvaW50aW5ndHJpYW5nbGUiLAogIDB4MjViNiwKICAiYmxhY2tzbWFsbHNxdWFyZSIsCiAgMHgyNWFhLAogICJibGFja3NtaWxpbmdmYWNlIiwKICAweDI2M2IsCiAgImJsYWNrc3F1YXJlIiwKICAweDI1YTAsCiAgImJsYWNrc3RhciIsCiAgMHgyNjA1LAogICJibGFja3VwcGVybGVmdHRyaWFuZ2xlIiwKICAweDI1ZTQsCiAgImJsYWNrdXBwZXJyaWdodHRyaWFuZ2xlIiwKICAweDI1ZTUsCiAgImJsYWNrdXBwb2ludGluZ3NtYWxsdHJpYW5nbGUiLAogIDB4MjViNCwKICAiYmxhY2t1cHBvaW50aW5ndHJpYW5nbGUiLAogIDB4MjViMiwKICAiYmxhbmsiLAogIDB4MjQyMywKICAiYmxpbmViZWxvdyIsCiAgMHgxZTA3LAogICJibG9jayIsCiAgMHgyNTg4LAogICJibW9ub3NwYWNlIiwKICAweGZmNDIsCiAgImJvYmFpbWFpdGhhaSIsCiAgMHgwZTFhLAogICJib2hpcmFnYW5hIiwKICAweDMwN2MsCiAgImJva2F0YWthbmEiLAogIDB4MzBkYywKICAiYnBhcmVuIiwKICAweDI0OWQsCiAgImJxc3F1YXJlIiwKICAweDMzYzMsCiAgImJyYWNlZXgiLAogIDB4ZjhmNCwKICAiYnJhY2VsZWZ0IiwKICAweDAwN2IsCiAgImJyYWNlbGVmdGJ0IiwKICAweGY4ZjMsCiAgImJyYWNlbGVmdG1pZCIsCiAgMHhmOGYyLAogICJicmFjZWxlZnRtb25vc3BhY2UiLAogIDB4ZmY1YiwKICAiYnJhY2VsZWZ0c21hbGwiLAogIDB4ZmU1YiwKICAiYnJhY2VsZWZ0dHAiLAogIDB4ZjhmMSwKICAiYnJhY2VsZWZ0dmVydGljYWwiLAogIDB4ZmUzNywKICAiYnJhY2VyaWdodCIsCiAgMHgwMDdkLAogICJicmFjZXJpZ2h0YnQiLAogIDB4ZjhmZSwKICAiYnJhY2VyaWdodG1pZCIsCiAgMHhmOGZkLAogICJicmFjZXJpZ2h0bW9ub3NwYWNlIiwKICAweGZmNWQsCiAgImJyYWNlcmlnaHRzbWFsbCIsCiAgMHhmZTVjLAogICJicmFjZXJpZ2h0dHAiLAogIDB4ZjhmYywKICAiYnJhY2VyaWdodHZlcnRpY2FsIiwKICAweGZlMzgsCiAgImJyYWNrZXRsZWZ0IiwKICAweDAwNWIsCiAgImJyYWNrZXRsZWZ0YnQiLAogIDB4ZjhmMCwKICAiYnJhY2tldGxlZnRleCIsCiAgMHhmOGVmLAogICJicmFja2V0bGVmdG1vbm9zcGFjZSIsCiAgMHhmZjNiLAogICJicmFja2V0bGVmdHRwIiwKICAweGY4ZWUsCiAgImJyYWNrZXRyaWdodCIsCiAgMHgwMDVkLAogICJicmFja2V0cmlnaHRidCIsCiAgMHhmOGZiLAogICJicmFja2V0cmlnaHRleCIsCiAgMHhmOGZhLAogICJicmFja2V0cmlnaHRtb25vc3BhY2UiLAogIDB4ZmYzZCwKICAiYnJhY2tldHJpZ2h0dHAiLAogIDB4ZjhmOSwKICAiYnJldmUiLAogIDB4MDJkOCwKICAiYnJldmViZWxvd2NtYiIsCiAgMHgwMzJlLAogICJicmV2ZWNtYiIsCiAgMHgwMzA2LAogICJicmV2ZWludmVydGVkYmVsb3djbWIiLAogIDB4MDMyZiwKICAiYnJldmVpbnZlcnRlZGNtYiIsCiAgMHgwMzExLAogICJicmV2ZWludmVydGVkZG91YmxlY21iIiwKICAweDAzNjEsCiAgImJyaWRnZWJlbG93Y21iIiwKICAweDAzMmEsCiAgImJyaWRnZWludmVydGVkYmVsb3djbWIiLAogIDB4MDMzYSwKICAiYnJva2VuYmFyIiwKICAweDAwYTYsCiAgImJzdHJva2UiLAogIDB4MDE4MCwKICAiYnN1cGVyaW9yIiwKICAweGY2ZWEsCiAgImJ0b3BiYXIiLAogIDB4MDE4MywKICAiYnVoaXJhZ2FuYSIsCiAgMHgzMDc2LAogICJidWthdGFrYW5hIiwKICAweDMwZDYsCiAgImJ1bGxldCIsCiAgMHgyMDIyLAogICJidWxsZXRpbnZlcnNlIiwKICAweDI1ZDgsCiAgImJ1bGxldG9wZXJhdG9yIiwKICAweDIyMTksCiAgImJ1bGxzZXllIiwKICAweDI1Y2UsCiAgImMiLAogIDB4MDA2MywKICAiY2Fhcm1lbmlhbiIsCiAgMHgwNTZlLAogICJjYWJlbmdhbGkiLAogIDB4MDk5YSwKICAiY2FjdXRlIiwKICAweDAxMDcsCiAgImNhZGV2YSIsCiAgMHgwOTFhLAogICJjYWd1amFyYXRpIiwKICAweDBhOWEsCiAgImNhZ3VybXVraGkiLAogIDB4MGExYSwKICAiY2Fsc3F1YXJlIiwKICAweDMzODgsCiAgImNhbmRyYWJpbmR1YmVuZ2FsaSIsCiAgMHgwOTgxLAogICJjYW5kcmFiaW5kdWNtYiIsCiAgMHgwMzEwLAogICJjYW5kcmFiaW5kdWRldmEiLAogIDB4MDkwMSwKICAiY2FuZHJhYmluZHVndWphcmF0aSIsCiAgMHgwYTgxLAogICJjYXBzbG9jayIsCiAgMHgyMWVhLAogICJjYXJlb2YiLAogIDB4MjEwNSwKICAiY2Fyb24iLAogIDB4MDJjNywKICAiY2Fyb25iZWxvd2NtYiIsCiAgMHgwMzJjLAogICJjYXJvbmNtYiIsCiAgMHgwMzBjLAogICJjYXJyaWFnZXJldHVybiIsCiAgMHgyMWI1LAogICJjYm9wb21vZm8iLAogIDB4MzExOCwKICAiY2Nhcm9uIiwKICAweDAxMGQsCiAgImNjZWRpbGxhIiwKICAweDAwZTcsCiAgImNjZWRpbGxhYWN1dGUiLAogIDB4MWUwOSwKICAiY2NpcmNsZSIsCiAgMHgyNGQyLAogICJjY2lyY3VtZmxleCIsCiAgMHgwMTA5LAogICJjY3VybCIsCiAgMHgwMjU1LAogICJjZG90IiwKICAweDAxMGIsCiAgImNkb3RhY2NlbnQiLAogIDB4MDEwYiwKICAiY2RzcXVhcmUiLAogIDB4MzNjNSwKICAiY2VkaWxsYSIsCiAgMHgwMGI4LAogICJjZWRpbGxhY21iIiwKICAweDAzMjcsCiAgImNlbnQiLAogIDB4MDBhMiwKICAiY2VudGlncmFkZSIsCiAgMHgyMTAzLAogICJjZW50aW5mZXJpb3IiLAogIDB4ZjZkZiwKICAiY2VudG1vbm9zcGFjZSIsCiAgMHhmZmUwLAogICJjZW50b2xkc3R5bGUiLAogIDB4ZjdhMiwKICAiY2VudHN1cGVyaW9yIiwKICAweGY2ZTAsCiAgImNoYWFybWVuaWFuIiwKICAweDA1NzksCiAgImNoYWJlbmdhbGkiLAogIDB4MDk5YiwKICAiY2hhZGV2YSIsCiAgMHgwOTFiLAogICJjaGFndWphcmF0aSIsCiAgMHgwYTliLAogICJjaGFndXJtdWtoaSIsCiAgMHgwYTFiLAogICJjaGJvcG9tb2ZvIiwKICAweDMxMTQsCiAgImNoZWFia2hhc2lhbmN5cmlsbGljIiwKICAweDA0YmQsCiAgImNoZWNrbWFyayIsCiAgMHgyNzEzLAogICJjaGVjeXJpbGxpYyIsCiAgMHgwNDQ3LAogICJjaGVkZXNjZW5kZXJhYmtoYXNpYW5jeXJpbGxpYyIsCiAgMHgwNGJmLAogICJjaGVkZXNjZW5kZXJjeXJpbGxpYyIsCiAgMHgwNGI3LAogICJjaGVkaWVyZXNpc2N5cmlsbGljIiwKICAweDA0ZjUsCiAgImNoZWhhcm1lbmlhbiIsCiAgMHgwNTczLAogICJjaGVraGFrYXNzaWFuY3lyaWxsaWMiLAogIDB4MDRjYywKICAiY2hldmVydGljYWxzdHJva2VjeXJpbGxpYyIsCiAgMHgwNGI5LAogICJjaGkiLAogIDB4MDNjNywKICAiY2hpZXVjaGFjaXJjbGVrb3JlYW4iLAogIDB4MzI3NywKICAiY2hpZXVjaGFwYXJlbmtvcmVhbiIsCiAgMHgzMjE3LAogICJjaGlldWNoY2lyY2xla29yZWFuIiwKICAweDMyNjksCiAgImNoaWV1Y2hrb3JlYW4iLAogIDB4MzE0YSwKICAiY2hpZXVjaHBhcmVua29yZWFuIiwKICAweDMyMDksCiAgImNob2NoYW5ndGhhaSIsCiAgMHgwZTBhLAogICJjaG9jaGFudGhhaSIsCiAgMHgwZTA4LAogICJjaG9jaGluZ3RoYWkiLAogIDB4MGUwOSwKICAiY2hvY2hvZXRoYWkiLAogIDB4MGUwYywKICAiY2hvb2siLAogIDB4MDE4OCwKICAiY2lldWNhY2lyY2xla29yZWFuIiwKICAweDMyNzYsCiAgImNpZXVjYXBhcmVua29yZWFuIiwKICAweDMyMTYsCiAgImNpZXVjY2lyY2xla29yZWFuIiwKICAweDMyNjgsCiAgImNpZXVja29yZWFuIiwKICAweDMxNDgsCiAgImNpZXVjcGFyZW5rb3JlYW4iLAogIDB4MzIwOCwKICAiY2lldWN1cGFyZW5rb3JlYW4iLAogIDB4MzIxYywKICAiY2lyY2xlIiwKICAweDI1Y2IsCiAgImNpcmNsZWNvcHlydCIsCiAgMHgwMGE5LAogICJjaXJjbGVtdWx0aXBseSIsCiAgMHgyMjk3LAogICJjaXJjbGVvdCIsCiAgMHgyMjk5LAogICJjaXJjbGVwbHVzIiwKICAweDIyOTUsCiAgImNpcmNsZXBvc3RhbG1hcmsiLAogIDB4MzAzNiwKICAiY2lyY2xld2l0aGxlZnRoYWxmYmxhY2siLAogIDB4MjVkMCwKICAiY2lyY2xld2l0aHJpZ2h0aGFsZmJsYWNrIiwKICAweDI1ZDEsCiAgImNpcmN1bWZsZXgiLAogIDB4MDJjNiwKICAiY2lyY3VtZmxleGJlbG93Y21iIiwKICAweDAzMmQsCiAgImNpcmN1bWZsZXhjbWIiLAogIDB4MDMwMiwKICAiY2xlYXIiLAogIDB4MjMyNywKICAiY2xpY2thbHZlb2xhciIsCiAgMHgwMWMyLAogICJjbGlja2RlbnRhbCIsCiAgMHgwMWMwLAogICJjbGlja2xhdGVyYWwiLAogIDB4MDFjMSwKICAiY2xpY2tyZXRyb2ZsZXgiLAogIDB4MDFjMywKICAiY2x1YiIsCiAgMHgyNjYzLAogICJjbHVic3VpdGJsYWNrIiwKICAweDI2NjMsCiAgImNsdWJzdWl0d2hpdGUiLAogIDB4MjY2NywKICAiY21jdWJlZHNxdWFyZSIsCiAgMHgzM2E0LAogICJjbW9ub3NwYWNlIiwKICAweGZmNDMsCiAgImNtc3F1YXJlZHNxdWFyZSIsCiAgMHgzM2EwLAogICJjb2FybWVuaWFuIiwKICAweDA1ODEsCiAgImNvbG9uIiwKICAweDAwM2EsCiAgImNvbG9ubW9uZXRhcnkiLAogIDB4MjBhMSwKICAiY29sb25tb25vc3BhY2UiLAogIDB4ZmYxYSwKICAiY29sb25zaWduIiwKICAweDIwYTEsCiAgImNvbG9uc21hbGwiLAogIDB4ZmU1NSwKICAiY29sb250cmlhbmd1bGFyaGFsZm1vZCIsCiAgMHgwMmQxLAogICJjb2xvbnRyaWFuZ3VsYXJtb2QiLAogIDB4MDJkMCwKICAiY29tbWEiLAogIDB4MDAyYywKICAiY29tbWFhYm92ZWNtYiIsCiAgMHgwMzEzLAogICJjb21tYWFib3ZlcmlnaHRjbWIiLAogIDB4MDMxNSwKICAiY29tbWFhY2NlbnQiLAogIDB4ZjZjMywKICAiY29tbWFhcmFiaWMiLAogIDB4MDYwYywKICAiY29tbWFhcm1lbmlhbiIsCiAgMHgwNTVkLAogICJjb21tYWluZmVyaW9yIiwKICAweGY2ZTEsCiAgImNvbW1hbW9ub3NwYWNlIiwKICAweGZmMGMsCiAgImNvbW1hcmV2ZXJzZWRhYm92ZWNtYiIsCiAgMHgwMzE0LAogICJjb21tYXJldmVyc2VkbW9kIiwKICAweDAyYmQsCiAgImNvbW1hc21hbGwiLAogIDB4ZmU1MCwKICAiY29tbWFzdXBlcmlvciIsCiAgMHhmNmUyLAogICJjb21tYXR1cm5lZGFib3ZlY21iIiwKICAweDAzMTIsCiAgImNvbW1hdHVybmVkbW9kIiwKICAweDAyYmIsCiAgImNvbXBhc3MiLAogIDB4MjYzYywKICAiY29uZ3J1ZW50IiwKICAweDIyNDUsCiAgImNvbnRvdXJpbnRlZ3JhbCIsCiAgMHgyMjJlLAogICJjb250cm9sIiwKICAweDIzMDMsCiAgImNvbnRyb2xBQ0siLAogIDB4MDAwNiwKICAiY29udHJvbEJFTCIsCiAgMHgwMDA3LAogICJjb250cm9sQlMiLAogIDB4MDAwOCwKICAiY29udHJvbENBTiIsCiAgMHgwMDE4LAogICJjb250cm9sQ1IiLAogIDB4MDAwZCwKICAiY29udHJvbERDMSIsCiAgMHgwMDExLAogICJjb250cm9sREMyIiwKICAweDAwMTIsCiAgImNvbnRyb2xEQzMiLAogIDB4MDAxMywKICAiY29udHJvbERDNCIsCiAgMHgwMDE0LAogICJjb250cm9sREVMIiwKICAweDAwN2YsCiAgImNvbnRyb2xETEUiLAogIDB4MDAxMCwKICAiY29udHJvbEVNIiwKICAweDAwMTksCiAgImNvbnRyb2xFTlEiLAogIDB4MDAwNSwKICAiY29udHJvbEVPVCIsCiAgMHgwMDA0LAogICJjb250cm9sRVNDIiwKICAweDAwMWIsCiAgImNvbnRyb2xFVEIiLAogIDB4MDAxNywKICAiY29udHJvbEVUWCIsCiAgMHgwMDAzLAogICJjb250cm9sRkYiLAogIDB4MDAwYywKICAiY29udHJvbEZTIiwKICAweDAwMWMsCiAgImNvbnRyb2xHUyIsCiAgMHgwMDFkLAogICJjb250cm9sSFQiLAogIDB4MDAwOSwKICAiY29udHJvbExGIiwKICAweDAwMGEsCiAgImNvbnRyb2xOQUsiLAogIDB4MDAxNSwKICAiY29udHJvbE5VTEwiLAogIDB4MDAwMCwKICAiY29udHJvbFJTIiwKICAweDAwMWUsCiAgImNvbnRyb2xTSSIsCiAgMHgwMDBmLAogICJjb250cm9sU08iLAogIDB4MDAwZSwKICAiY29udHJvbFNPVCIsCiAgMHgwMDAyLAogICJjb250cm9sU1RYIiwKICAweDAwMDEsCiAgImNvbnRyb2xTVUIiLAogIDB4MDAxYSwKICAiY29udHJvbFNZTiIsCiAgMHgwMDE2LAogICJjb250cm9sVVMiLAogIDB4MDAxZiwKICAiY29udHJvbFZUIiwKICAweDAwMGIsCiAgImNvcHlyaWdodCIsCiAgMHgwMGE5LAogICJjb3B5cmlnaHRzYW5zIiwKICAweGY4ZTksCiAgImNvcHlyaWdodHNlcmlmIiwKICAweGY2ZDksCiAgImNvcm5lcmJyYWNrZXRsZWZ0IiwKICAweDMwMGMsCiAgImNvcm5lcmJyYWNrZXRsZWZ0aGFsZndpZHRoIiwKICAweGZmNjIsCiAgImNvcm5lcmJyYWNrZXRsZWZ0dmVydGljYWwiLAogIDB4ZmU0MSwKICAiY29ybmVyYnJhY2tldHJpZ2h0IiwKICAweDMwMGQsCiAgImNvcm5lcmJyYWNrZXRyaWdodGhhbGZ3aWR0aCIsCiAgMHhmZjYzLAogICJjb3JuZXJicmFja2V0cmlnaHR2ZXJ0aWNhbCIsCiAgMHhmZTQyLAogICJjb3Jwb3JhdGlvbnNxdWFyZSIsCiAgMHgzMzdmLAogICJjb3NxdWFyZSIsCiAgMHgzM2M3LAogICJjb3Zlcmtnc3F1YXJlIiwKICAweDMzYzYsCiAgImNwYXJlbiIsCiAgMHgyNDllLAogICJjcnV6ZWlybyIsCiAgMHgyMGEyLAogICJjc3RyZXRjaGVkIiwKICAweDAyOTcsCiAgImN1cmx5YW5kIiwKICAweDIyY2YsCiAgImN1cmx5b3IiLAogIDB4MjJjZSwKICAiY3VycmVuY3kiLAogIDB4MDBhNCwKICAiY3lyQnJldmUiLAogIDB4ZjZkMSwKICAiY3lyRmxleCIsCiAgMHhmNmQyLAogICJjeXJicmV2ZSIsCiAgMHhmNmQ0LAogICJjeXJmbGV4IiwKICAweGY2ZDUsCiAgImQiLAogIDB4MDA2NCwKICAiZGFhcm1lbmlhbiIsCiAgMHgwNTY0LAogICJkYWJlbmdhbGkiLAogIDB4MDlhNiwKICAiZGFkYXJhYmljIiwKICAweDA2MzYsCiAgImRhZGV2YSIsCiAgMHgwOTI2LAogICJkYWRmaW5hbGFyYWJpYyIsCiAgMHhmZWJlLAogICJkYWRpbml0aWFsYXJhYmljIiwKICAweGZlYmYsCiAgImRhZG1lZGlhbGFyYWJpYyIsCiAgMHhmZWMwLAogICJkYWdlc2giLAogIDB4MDViYywKICAiZGFnZXNoaGVicmV3IiwKICAweDA1YmMsCiAgImRhZ2dlciIsCiAgMHgyMDIwLAogICJkYWdnZXJkYmwiLAogIDB4MjAyMSwKICAiZGFndWphcmF0aSIsCiAgMHgwYWE2LAogICJkYWd1cm11a2hpIiwKICAweDBhMjYsCiAgImRhaGlyYWdhbmEiLAogIDB4MzA2MCwKICAiZGFrYXRha2FuYSIsCiAgMHgzMGMwLAogICJkYWxhcmFiaWMiLAogIDB4MDYyZiwKICAiZGFsZXQiLAogIDB4MDVkMywKICAiZGFsZXRkYWdlc2giLAogIDB4ZmIzMywKICAiZGFsZXRkYWdlc2hoZWJyZXciLAogIDB4ZmIzMywKICAiZGFsZXRoZWJyZXciLAogIDB4MDVkMywKICAiZGFsZmluYWxhcmFiaWMiLAogIDB4ZmVhYSwKICAiZGFtbWFhcmFiaWMiLAogIDB4MDY0ZiwKICAiZGFtbWFsb3dhcmFiaWMiLAogIDB4MDY0ZiwKICAiZGFtbWF0YW5hbHRvbmVhcmFiaWMiLAogIDB4MDY0YywKICAiZGFtbWF0YW5hcmFiaWMiLAogIDB4MDY0YywKICAiZGFuZGEiLAogIDB4MDk2NCwKICAiZGFyZ2FoZWJyZXciLAogIDB4MDVhNywKICAiZGFyZ2FsZWZ0aGVicmV3IiwKICAweDA1YTcsCiAgImRhc2lhcG5ldW1hdGFjeXJpbGxpY2NtYiIsCiAgMHgwNDg1LAogICJkYmxHcmF2ZSIsCiAgMHhmNmQzLAogICJkYmxhbmdsZWJyYWNrZXRsZWZ0IiwKICAweDMwMGEsCiAgImRibGFuZ2xlYnJhY2tldGxlZnR2ZXJ0aWNhbCIsCiAgMHhmZTNkLAogICJkYmxhbmdsZWJyYWNrZXRyaWdodCIsCiAgMHgzMDBiLAogICJkYmxhbmdsZWJyYWNrZXRyaWdodHZlcnRpY2FsIiwKICAweGZlM2UsCiAgImRibGFyY2hpbnZlcnRlZGJlbG93Y21iIiwKICAweDAzMmIsCiAgImRibGFycm93bGVmdCIsCiAgMHgyMWQ0LAogICJkYmxhcnJvd3JpZ2h0IiwKICAweDIxZDIsCiAgImRibGRhbmRhIiwKICAweDA5NjUsCiAgImRibGdyYXZlIiwKICAweGY2ZDYsCiAgImRibGdyYXZlY21iIiwKICAweDAzMGYsCiAgImRibGludGVncmFsIiwKICAweDIyMmMsCiAgImRibGxvd2xpbmUiLAogIDB4MjAxNywKICAiZGJsbG93bGluZWNtYiIsCiAgMHgwMzMzLAogICJkYmxvdmVybGluZWNtYiIsCiAgMHgwMzNmLAogICJkYmxwcmltZW1vZCIsCiAgMHgwMmJhLAogICJkYmx2ZXJ0aWNhbGJhciIsCiAgMHgyMDE2LAogICJkYmx2ZXJ0aWNhbGxpbmVhYm92ZWNtYiIsCiAgMHgwMzBlLAogICJkYm9wb21vZm8iLAogIDB4MzEwOSwKICAiZGJzcXVhcmUiLAogIDB4MzNjOCwKICAiZGNhcm9uIiwKICAweDAxMGYsCiAgImRjZWRpbGxhIiwKICAweDFlMTEsCiAgImRjaXJjbGUiLAogIDB4MjRkMywKICAiZGNpcmN1bWZsZXhiZWxvdyIsCiAgMHgxZTEzLAogICJkY3JvYXQiLAogIDB4MDExMSwKICAiZGRhYmVuZ2FsaSIsCiAgMHgwOWExLAogICJkZGFkZXZhIiwKICAweDA5MjEsCiAgImRkYWd1amFyYXRpIiwKICAweDBhYTEsCiAgImRkYWd1cm11a2hpIiwKICAweDBhMjEsCiAgImRkYWxhcmFiaWMiLAogIDB4MDY4OCwKICAiZGRhbGZpbmFsYXJhYmljIiwKICAweGZiODksCiAgImRkZGhhZGV2YSIsCiAgMHgwOTVjLAogICJkZGhhYmVuZ2FsaSIsCiAgMHgwOWEyLAogICJkZGhhZGV2YSIsCiAgMHgwOTIyLAogICJkZGhhZ3VqYXJhdGkiLAogIDB4MGFhMiwKICAiZGRoYWd1cm11a2hpIiwKICAweDBhMjIsCiAgImRkb3RhY2NlbnQiLAogIDB4MWUwYiwKICAiZGRvdGJlbG93IiwKICAweDFlMGQsCiAgImRlY2ltYWxzZXBhcmF0b3JhcmFiaWMiLAogIDB4MDY2YiwKICAiZGVjaW1hbHNlcGFyYXRvcnBlcnNpYW4iLAogIDB4MDY2YiwKICAiZGVjeXJpbGxpYyIsCiAgMHgwNDM0LAogICJkZWdyZWUiLAogIDB4MDBiMCwKICAiZGVoaWhlYnJldyIsCiAgMHgwNWFkLAogICJkZWhpcmFnYW5hIiwKICAweDMwNjcsCiAgImRlaWNvcHRpYyIsCiAgMHgwM2VmLAogICJkZWthdGFrYW5hIiwKICAweDMwYzcsCiAgImRlbGV0ZWxlZnQiLAogIDB4MjMyYiwKICAiZGVsZXRlcmlnaHQiLAogIDB4MjMyNiwKICAiZGVsdGEiLAogIDB4MDNiNCwKICAiZGVsdGF0dXJuZWQiLAogIDB4MDE4ZCwKICAiZGVub21pbmF0b3JtaW51c29uZW51bWVyYXRvcmJlbmdhbGkiLAogIDB4MDlmOCwKICAiZGV6aCIsCiAgMHgwMmE0LAogICJkaGFiZW5nYWxpIiwKICAweDA5YTcsCiAgImRoYWRldmEiLAogIDB4MDkyNywKICAiZGhhZ3VqYXJhdGkiLAogIDB4MGFhNywKICAiZGhhZ3VybXVraGkiLAogIDB4MGEyNywKICAiZGhvb2siLAogIDB4MDI1NywKICAiZGlhbHl0aWthdG9ub3MiLAogIDB4MDM4NSwKICAiZGlhbHl0aWthdG9ub3NjbWIiLAogIDB4MDM0NCwKICAiZGlhbW9uZCIsCiAgMHgyNjY2LAogICJkaWFtb25kc3VpdHdoaXRlIiwKICAweDI2NjIsCiAgImRpZXJlc2lzIiwKICAweDAwYTgsCiAgImRpZXJlc2lzYWN1dGUiLAogIDB4ZjZkNywKICAiZGllcmVzaXNiZWxvd2NtYiIsCiAgMHgwMzI0LAogICJkaWVyZXNpc2NtYiIsCiAgMHgwMzA4LAogICJkaWVyZXNpc2dyYXZlIiwKICAweGY2ZDgsCiAgImRpZXJlc2lzdG9ub3MiLAogIDB4MDM4NSwKICAiZGloaXJhZ2FuYSIsCiAgMHgzMDYyLAogICJkaWthdGFrYW5hIiwKICAweDMwYzIsCiAgImRpdHRvbWFyayIsCiAgMHgzMDAzLAogICJkaXZpZGUiLAogIDB4MDBmNywKICAiZGl2aWRlcyIsCiAgMHgyMjIzLAogICJkaXZpc2lvbnNsYXNoIiwKICAweDIyMTUsCiAgImRqZWN5cmlsbGljIiwKICAweDA0NTIsCiAgImRrc2hhZGUiLAogIDB4MjU5MywKICAiZGxpbmViZWxvdyIsCiAgMHgxZTBmLAogICJkbHNxdWFyZSIsCiAgMHgzMzk3LAogICJkbWFjcm9uIiwKICAweDAxMTEsCiAgImRtb25vc3BhY2UiLAogIDB4ZmY0NCwKICAiZG5ibG9jayIsCiAgMHgyNTg0LAogICJkb2NoYWRhdGhhaSIsCiAgMHgwZTBlLAogICJkb2Rla3RoYWkiLAogIDB4MGUxNCwKICAiZG9oaXJhZ2FuYSIsCiAgMHgzMDY5LAogICJkb2thdGFrYW5hIiwKICAweDMwYzksCiAgImRvbGxhciIsCiAgMHgwMDI0LAogICJkb2xsYXJpbmZlcmlvciIsCiAgMHhmNmUzLAogICJkb2xsYXJtb25vc3BhY2UiLAogIDB4ZmYwNCwKICAiZG9sbGFyb2xkc3R5bGUiLAogIDB4ZjcyNCwKICAiZG9sbGFyc21hbGwiLAogIDB4ZmU2OSwKICAiZG9sbGFyc3VwZXJpb3IiLAogIDB4ZjZlNCwKICAiZG9uZyIsCiAgMHgyMGFiLAogICJkb3J1c3F1YXJlIiwKICAweDMzMjYsCiAgImRvdGFjY2VudCIsCiAgMHgwMmQ5LAogICJkb3RhY2NlbnRjbWIiLAogIDB4MDMwNywKICAiZG90YmVsb3djbWIiLAogIDB4MDMyMywKICAiZG90YmVsb3djb21iIiwKICAweDAzMjMsCiAgImRvdGthdGFrYW5hIiwKICAweDMwZmIsCiAgImRvdGxlc3NpIiwKICAweDAxMzEsCiAgImRvdGxlc3NqIiwKICAweGY2YmUsCiAgImRvdGxlc3Nqc3Ryb2tlaG9vayIsCiAgMHgwMjg0LAogICJkb3RtYXRoIiwKICAweDIyYzUsCiAgImRvdHRlZGNpcmNsZSIsCiAgMHgyNWNjLAogICJkb3VibGV5b2RwYXRhaCIsCiAgMHhmYjFmLAogICJkb3VibGV5b2RwYXRhaGhlYnJldyIsCiAgMHhmYjFmLAogICJkb3dudGFja2JlbG93Y21iIiwKICAweDAzMWUsCiAgImRvd250YWNrbW9kIiwKICAweDAyZDUsCiAgImRwYXJlbiIsCiAgMHgyNDlmLAogICJkc3VwZXJpb3IiLAogIDB4ZjZlYiwKICAiZHRhaWwiLAogIDB4MDI1NiwKICAiZHRvcGJhciIsCiAgMHgwMThjLAogICJkdWhpcmFnYW5hIiwKICAweDMwNjUsCiAgImR1a2F0YWthbmEiLAogIDB4MzBjNSwKICAiZHoiLAogIDB4MDFmMywKICAiZHphbHRvbmUiLAogIDB4MDJhMywKICAiZHpjYXJvbiIsCiAgMHgwMWM2LAogICJkemN1cmwiLAogIDB4MDJhNSwKICAiZHplYWJraGFzaWFuY3lyaWxsaWMiLAogIDB4MDRlMSwKICAiZHplY3lyaWxsaWMiLAogIDB4MDQ1NSwKICAiZHpoZWN5cmlsbGljIiwKICAweDA0NWYsCiAgImUiLAogIDB4MDA2NSwKICAiZWFjdXRlIiwKICAweDAwZTksCiAgImVhcnRoIiwKICAweDI2NDEsCiAgImViZW5nYWxpIiwKICAweDA5OGYsCiAgImVib3BvbW9mbyIsCiAgMHgzMTFjLAogICJlYnJldmUiLAogIDB4MDExNSwKICAiZWNhbmRyYWRldmEiLAogIDB4MDkwZCwKICAiZWNhbmRyYWd1amFyYXRpIiwKICAweDBhOGQsCiAgImVjYW5kcmF2b3dlbHNpZ25kZXZhIiwKICAweDA5NDUsCiAgImVjYW5kcmF2b3dlbHNpZ25ndWphcmF0aSIsCiAgMHgwYWM1LAogICJlY2Fyb24iLAogIDB4MDExYiwKICAiZWNlZGlsbGFicmV2ZSIsCiAgMHgxZTFkLAogICJlY2hhcm1lbmlhbiIsCiAgMHgwNTY1LAogICJlY2h5aXduYXJtZW5pYW4iLAogIDB4MDU4NywKICAiZWNpcmNsZSIsCiAgMHgyNGQ0LAogICJlY2lyY3VtZmxleCIsCiAgMHgwMGVhLAogICJlY2lyY3VtZmxleGFjdXRlIiwKICAweDFlYmYsCiAgImVjaXJjdW1mbGV4YmVsb3ciLAogIDB4MWUxOSwKICAiZWNpcmN1bWZsZXhkb3RiZWxvdyIsCiAgMHgxZWM3LAogICJlY2lyY3VtZmxleGdyYXZlIiwKICAweDFlYzEsCiAgImVjaXJjdW1mbGV4aG9va2Fib3ZlIiwKICAweDFlYzMsCiAgImVjaXJjdW1mbGV4dGlsZGUiLAogIDB4MWVjNSwKICAiZWN5cmlsbGljIiwKICAweDA0NTQsCiAgImVkYmxncmF2ZSIsCiAgMHgwMjA1LAogICJlZGV2YSIsCiAgMHgwOTBmLAogICJlZGllcmVzaXMiLAogIDB4MDBlYiwKICAiZWRvdCIsCiAgMHgwMTE3LAogICJlZG90YWNjZW50IiwKICAweDAxMTcsCiAgImVkb3RiZWxvdyIsCiAgMHgxZWI5LAogICJlZWd1cm11a2hpIiwKICAweDBhMGYsCiAgImVlbWF0cmFndXJtdWtoaSIsCiAgMHgwYTQ3LAogICJlZmN5cmlsbGljIiwKICAweDA0NDQsCiAgImVncmF2ZSIsCiAgMHgwMGU4LAogICJlZ3VqYXJhdGkiLAogIDB4MGE4ZiwKICAiZWhhcm1lbmlhbiIsCiAgMHgwNTY3LAogICJlaGJvcG9tb2ZvIiwKICAweDMxMWQsCiAgImVoaXJhZ2FuYSIsCiAgMHgzMDQ4LAogICJlaG9va2Fib3ZlIiwKICAweDFlYmIsCiAgImVpYm9wb21vZm8iLAogIDB4MzExZiwKICAiZWlnaHQiLAogIDB4MDAzOCwKICAiZWlnaHRhcmFiaWMiLAogIDB4MDY2OCwKICAiZWlnaHRiZW5nYWxpIiwKICAweDA5ZWUsCiAgImVpZ2h0Y2lyY2xlIiwKICAweDI0NjcsCiAgImVpZ2h0Y2lyY2xlaW52ZXJzZXNhbnNzZXJpZiIsCiAgMHgyNzkxLAogICJlaWdodGRldmEiLAogIDB4MDk2ZSwKICAiZWlnaHRlZW5jaXJjbGUiLAogIDB4MjQ3MSwKICAiZWlnaHRlZW5wYXJlbiIsCiAgMHgyNDg1LAogICJlaWdodGVlbnBlcmlvZCIsCiAgMHgyNDk5LAogICJlaWdodGd1amFyYXRpIiwKICAweDBhZWUsCiAgImVpZ2h0Z3VybXVraGkiLAogIDB4MGE2ZSwKICAiZWlnaHRoYWNrYXJhYmljIiwKICAweDA2NjgsCiAgImVpZ2h0aGFuZ3pob3UiLAogIDB4MzAyOCwKICAiZWlnaHRobm90ZWJlYW1lZCIsCiAgMHgyNjZiLAogICJlaWdodGlkZW9ncmFwaGljcGFyZW4iLAogIDB4MzIyNywKICAiZWlnaHRpbmZlcmlvciIsCiAgMHgyMDg4LAogICJlaWdodG1vbm9zcGFjZSIsCiAgMHhmZjE4LAogICJlaWdodG9sZHN0eWxlIiwKICAweGY3MzgsCiAgImVpZ2h0cGFyZW4iLAogIDB4MjQ3YiwKICAiZWlnaHRwZXJpb2QiLAogIDB4MjQ4ZiwKICAiZWlnaHRwZXJzaWFuIiwKICAweDA2ZjgsCiAgImVpZ2h0cm9tYW4iLAogIDB4MjE3NywKICAiZWlnaHRzdXBlcmlvciIsCiAgMHgyMDc4LAogICJlaWdodHRoYWkiLAogIDB4MGU1OCwKICAiZWludmVydGVkYnJldmUiLAogIDB4MDIwNywKICAiZWlvdGlmaWVkY3lyaWxsaWMiLAogIDB4MDQ2NSwKICAiZWthdGFrYW5hIiwKICAweDMwYTgsCiAgImVrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjc0LAogICJla29ua2FyZ3VybXVraGkiLAogIDB4MGE3NCwKICAiZWtvcmVhbiIsCiAgMHgzMTU0LAogICJlbGN5cmlsbGljIiwKICAweDA0M2IsCiAgImVsZW1lbnQiLAogIDB4MjIwOCwKICAiZWxldmVuY2lyY2xlIiwKICAweDI0NmEsCiAgImVsZXZlbnBhcmVuIiwKICAweDI0N2UsCiAgImVsZXZlbnBlcmlvZCIsCiAgMHgyNDkyLAogICJlbGV2ZW5yb21hbiIsCiAgMHgyMTdhLAogICJlbGxpcHNpcyIsCiAgMHgyMDI2LAogICJlbGxpcHNpc3ZlcnRpY2FsIiwKICAweDIyZWUsCiAgImVtYWNyb24iLAogIDB4MDExMywKICAiZW1hY3JvbmFjdXRlIiwKICAweDFlMTcsCiAgImVtYWNyb25ncmF2ZSIsCiAgMHgxZTE1LAogICJlbWN5cmlsbGljIiwKICAweDA0M2MsCiAgImVtZGFzaCIsCiAgMHgyMDE0LAogICJlbWRhc2h2ZXJ0aWNhbCIsCiAgMHhmZTMxLAogICJlbW9ub3NwYWNlIiwKICAweGZmNDUsCiAgImVtcGhhc2lzbWFya2FybWVuaWFuIiwKICAweDA1NWIsCiAgImVtcHR5c2V0IiwKICAweDIyMDUsCiAgImVuYm9wb21vZm8iLAogIDB4MzEyMywKICAiZW5jeXJpbGxpYyIsCiAgMHgwNDNkLAogICJlbmRhc2giLAogIDB4MjAxMywKICAiZW5kYXNodmVydGljYWwiLAogIDB4ZmUzMiwKICAiZW5kZXNjZW5kZXJjeXJpbGxpYyIsCiAgMHgwNGEzLAogICJlbmciLAogIDB4MDE0YiwKICAiZW5nYm9wb21vZm8iLAogIDB4MzEyNSwKICAiZW5naGVjeXJpbGxpYyIsCiAgMHgwNGE1LAogICJlbmhvb2tjeXJpbGxpYyIsCiAgMHgwNGM4LAogICJlbnNwYWNlIiwKICAweDIwMDIsCiAgImVvZ29uZWsiLAogIDB4MDExOSwKICAiZW9rb3JlYW4iLAogIDB4MzE1MywKICAiZW9wZW4iLAogIDB4MDI1YiwKICAiZW9wZW5jbG9zZWQiLAogIDB4MDI5YSwKICAiZW9wZW5yZXZlcnNlZCIsCiAgMHgwMjVjLAogICJlb3BlbnJldmVyc2VkY2xvc2VkIiwKICAweDAyNWUsCiAgImVvcGVucmV2ZXJzZWRob29rIiwKICAweDAyNWQsCiAgImVwYXJlbiIsCiAgMHgyNGEwLAogICJlcHNpbG9uIiwKICAweDAzYjUsCiAgImVwc2lsb250b25vcyIsCiAgMHgwM2FkLAogICJlcXVhbCIsCiAgMHgwMDNkLAogICJlcXVhbG1vbm9zcGFjZSIsCiAgMHhmZjFkLAogICJlcXVhbHNtYWxsIiwKICAweGZlNjYsCiAgImVxdWFsc3VwZXJpb3IiLAogIDB4MjA3YywKICAiZXF1aXZhbGVuY2UiLAogIDB4MjI2MSwKICAiZXJib3BvbW9mbyIsCiAgMHgzMTI2LAogICJlcmN5cmlsbGljIiwKICAweDA0NDAsCiAgImVyZXZlcnNlZCIsCiAgMHgwMjU4LAogICJlcmV2ZXJzZWRjeXJpbGxpYyIsCiAgMHgwNDRkLAogICJlc2N5cmlsbGljIiwKICAweDA0NDEsCiAgImVzZGVzY2VuZGVyY3lyaWxsaWMiLAogIDB4MDRhYiwKICAiZXNoIiwKICAweDAyODMsCiAgImVzaGN1cmwiLAogIDB4MDI4NiwKICAiZXNob3J0ZGV2YSIsCiAgMHgwOTBlLAogICJlc2hvcnR2b3dlbHNpZ25kZXZhIiwKICAweDA5NDYsCiAgImVzaHJldmVyc2VkbG9vcCIsCiAgMHgwMWFhLAogICJlc2hzcXVhdHJldmVyc2VkIiwKICAweDAyODUsCiAgImVzbWFsbGhpcmFnYW5hIiwKICAweDMwNDcsCiAgImVzbWFsbGthdGFrYW5hIiwKICAweDMwYTcsCiAgImVzbWFsbGthdGFrYW5haGFsZndpZHRoIiwKICAweGZmNmEsCiAgImVzdGltYXRlZCIsCiAgMHgyMTJlLAogICJlc3VwZXJpb3IiLAogIDB4ZjZlYywKICAiZXRhIiwKICAweDAzYjcsCiAgImV0YXJtZW5pYW4iLAogIDB4MDU2OCwKICAiZXRhdG9ub3MiLAogIDB4MDNhZSwKICAiZXRoIiwKICAweDAwZjAsCiAgImV0aWxkZSIsCiAgMHgxZWJkLAogICJldGlsZGViZWxvdyIsCiAgMHgxZTFiLAogICJldG5haHRhZm91a2hoZWJyZXciLAogIDB4MDU5MSwKICAiZXRuYWh0YWZvdWtobGVmdGhlYnJldyIsCiAgMHgwNTkxLAogICJldG5haHRhaGVicmV3IiwKICAweDA1OTEsCiAgImV0bmFodGFsZWZ0aGVicmV3IiwKICAweDA1OTEsCiAgImV0dXJuZWQiLAogIDB4MDFkZCwKICAiZXVrb3JlYW4iLAogIDB4MzE2MSwKICAiZXVybyIsCiAgMHgyMGFjLAogICJldm93ZWxzaWduYmVuZ2FsaSIsCiAgMHgwOWM3LAogICJldm93ZWxzaWduZGV2YSIsCiAgMHgwOTQ3LAogICJldm93ZWxzaWduZ3VqYXJhdGkiLAogIDB4MGFjNywKICAiZXhjbGFtIiwKICAweDAwMjEsCiAgImV4Y2xhbWFybWVuaWFuIiwKICAweDA1NWMsCiAgImV4Y2xhbWRibCIsCiAgMHgyMDNjLAogICJleGNsYW1kb3duIiwKICAweDAwYTEsCiAgImV4Y2xhbWRvd25zbWFsbCIsCiAgMHhmN2ExLAogICJleGNsYW1tb25vc3BhY2UiLAogIDB4ZmYwMSwKICAiZXhjbGFtc21hbGwiLAogIDB4ZjcyMSwKICAiZXhpc3RlbnRpYWwiLAogIDB4MjIwMywKICAiZXpoIiwKICAweDAyOTIsCiAgImV6aGNhcm9uIiwKICAweDAxZWYsCiAgImV6aGN1cmwiLAogIDB4MDI5MywKICAiZXpocmV2ZXJzZWQiLAogIDB4MDFiOSwKICAiZXpodGFpbCIsCiAgMHgwMWJhLAogICJmIiwKICAweDAwNjYsCiAgImZhZGV2YSIsCiAgMHgwOTVlLAogICJmYWd1cm11a2hpIiwKICAweDBhNWUsCiAgImZhaHJlbmhlaXQiLAogIDB4MjEwOSwKICAiZmF0aGFhcmFiaWMiLAogIDB4MDY0ZSwKICAiZmF0aGFsb3dhcmFiaWMiLAogIDB4MDY0ZSwKICAiZmF0aGF0YW5hcmFiaWMiLAogIDB4MDY0YiwKICAiZmJvcG9tb2ZvIiwKICAweDMxMDgsCiAgImZjaXJjbGUiLAogIDB4MjRkNSwKICAiZmRvdGFjY2VudCIsCiAgMHgxZTFmLAogICJmZWhhcmFiaWMiLAogIDB4MDY0MSwKICAiZmVoYXJtZW5pYW4iLAogIDB4MDU4NiwKICAiZmVoZmluYWxhcmFiaWMiLAogIDB4ZmVkMiwKICAiZmVoaW5pdGlhbGFyYWJpYyIsCiAgMHhmZWQzLAogICJmZWhtZWRpYWxhcmFiaWMiLAogIDB4ZmVkNCwKICAiZmVpY29wdGljIiwKICAweDAzZTUsCiAgImZlbWFsZSIsCiAgMHgyNjQwLAogICJmZiIsCiAgMHhmYjAwLAogICJmX2YiLAogIDB4ZmIwMCwKICAiZmZpIiwKICAweGZiMDMsCiAgImZfZl9pIiwKICAweGZiMDMsCiAgImZmbCIsCiAgMHhmYjA0LAogICJmX2ZfbCIsCiAgMHhmYjA0LAogICJmaSIsCiAgMHhmYjAxLAogICJmX2kiLAogIDB4ZmIwMSwKICAiZmlmdGVlbmNpcmNsZSIsCiAgMHgyNDZlLAogICJmaWZ0ZWVucGFyZW4iLAogIDB4MjQ4MiwKICAiZmlmdGVlbnBlcmlvZCIsCiAgMHgyNDk2LAogICJmaWd1cmVkYXNoIiwKICAweDIwMTIsCiAgImZpbGxlZGJveCIsCiAgMHgyNWEwLAogICJmaWxsZWRyZWN0IiwKICAweDI1YWMsCiAgImZpbmFsa2FmIiwKICAweDA1ZGEsCiAgImZpbmFsa2FmZGFnZXNoIiwKICAweGZiM2EsCiAgImZpbmFsa2FmZGFnZXNoaGVicmV3IiwKICAweGZiM2EsCiAgImZpbmFsa2FmaGVicmV3IiwKICAweDA1ZGEsCiAgImZpbmFsbWVtIiwKICAweDA1ZGQsCiAgImZpbmFsbWVtaGVicmV3IiwKICAweDA1ZGQsCiAgImZpbmFsbnVuIiwKICAweDA1ZGYsCiAgImZpbmFsbnVuaGVicmV3IiwKICAweDA1ZGYsCiAgImZpbmFscGUiLAogIDB4MDVlMywKICAiZmluYWxwZWhlYnJldyIsCiAgMHgwNWUzLAogICJmaW5hbHRzYWRpIiwKICAweDA1ZTUsCiAgImZpbmFsdHNhZGloZWJyZXciLAogIDB4MDVlNSwKICAiZmlyc3R0b25lY2hpbmVzZSIsCiAgMHgwMmM5LAogICJmaXNoZXllIiwKICAweDI1YzksCiAgImZpdGFjeXJpbGxpYyIsCiAgMHgwNDczLAogICJmaXZlIiwKICAweDAwMzUsCiAgImZpdmVhcmFiaWMiLAogIDB4MDY2NSwKICAiZml2ZWJlbmdhbGkiLAogIDB4MDllYiwKICAiZml2ZWNpcmNsZSIsCiAgMHgyNDY0LAogICJmaXZlY2lyY2xlaW52ZXJzZXNhbnNzZXJpZiIsCiAgMHgyNzhlLAogICJmaXZlZGV2YSIsCiAgMHgwOTZiLAogICJmaXZlZWlnaHRocyIsCiAgMHgyMTVkLAogICJmaXZlZ3VqYXJhdGkiLAogIDB4MGFlYiwKICAiZml2ZWd1cm11a2hpIiwKICAweDBhNmIsCiAgImZpdmVoYWNrYXJhYmljIiwKICAweDA2NjUsCiAgImZpdmVoYW5nemhvdSIsCiAgMHgzMDI1LAogICJmaXZlaWRlb2dyYXBoaWNwYXJlbiIsCiAgMHgzMjI0LAogICJmaXZlaW5mZXJpb3IiLAogIDB4MjA4NSwKICAiZml2ZW1vbm9zcGFjZSIsCiAgMHhmZjE1LAogICJmaXZlb2xkc3R5bGUiLAogIDB4ZjczNSwKICAiZml2ZXBhcmVuIiwKICAweDI0NzgsCiAgImZpdmVwZXJpb2QiLAogIDB4MjQ4YywKICAiZml2ZXBlcnNpYW4iLAogIDB4MDZmNSwKICAiZml2ZXJvbWFuIiwKICAweDIxNzQsCiAgImZpdmVzdXBlcmlvciIsCiAgMHgyMDc1LAogICJmaXZldGhhaSIsCiAgMHgwZTU1LAogICJmbCIsCiAgMHhmYjAyLAogICJmX2wiLAogIDB4ZmIwMiwKICAiZmxvcmluIiwKICAweDAxOTIsCiAgImZtb25vc3BhY2UiLAogIDB4ZmY0NiwKICAiZm1zcXVhcmUiLAogIDB4MzM5OSwKICAiZm9mYW50aGFpIiwKICAweDBlMWYsCiAgImZvZmF0aGFpIiwKICAweDBlMWQsCiAgImZvbmdtYW50aGFpIiwKICAweDBlNGYsCiAgImZvcmFsbCIsCiAgMHgyMjAwLAogICJmb3VyIiwKICAweDAwMzQsCiAgImZvdXJhcmFiaWMiLAogIDB4MDY2NCwKICAiZm91cmJlbmdhbGkiLAogIDB4MDllYSwKICAiZm91cmNpcmNsZSIsCiAgMHgyNDYzLAogICJmb3VyY2lyY2xlaW52ZXJzZXNhbnNzZXJpZiIsCiAgMHgyNzhkLAogICJmb3VyZGV2YSIsCiAgMHgwOTZhLAogICJmb3VyZ3VqYXJhdGkiLAogIDB4MGFlYSwKICAiZm91cmd1cm11a2hpIiwKICAweDBhNmEsCiAgImZvdXJoYWNrYXJhYmljIiwKICAweDA2NjQsCiAgImZvdXJoYW5nemhvdSIsCiAgMHgzMDI0LAogICJmb3VyaWRlb2dyYXBoaWNwYXJlbiIsCiAgMHgzMjIzLAogICJmb3VyaW5mZXJpb3IiLAogIDB4MjA4NCwKICAiZm91cm1vbm9zcGFjZSIsCiAgMHhmZjE0LAogICJmb3VybnVtZXJhdG9yYmVuZ2FsaSIsCiAgMHgwOWY3LAogICJmb3Vyb2xkc3R5bGUiLAogIDB4ZjczNCwKICAiZm91cnBhcmVuIiwKICAweDI0NzcsCiAgImZvdXJwZXJpb2QiLAogIDB4MjQ4YiwKICAiZm91cnBlcnNpYW4iLAogIDB4MDZmNCwKICAiZm91cnJvbWFuIiwKICAweDIxNzMsCiAgImZvdXJzdXBlcmlvciIsCiAgMHgyMDc0LAogICJmb3VydGVlbmNpcmNsZSIsCiAgMHgyNDZkLAogICJmb3VydGVlbnBhcmVuIiwKICAweDI0ODEsCiAgImZvdXJ0ZWVucGVyaW9kIiwKICAweDI0OTUsCiAgImZvdXJ0aGFpIiwKICAweDBlNTQsCiAgImZvdXJ0aHRvbmVjaGluZXNlIiwKICAweDAyY2IsCiAgImZwYXJlbiIsCiAgMHgyNGExLAogICJmcmFjdGlvbiIsCiAgMHgyMDQ0LAogICJmcmFuYyIsCiAgMHgyMGEzLAogICJnIiwKICAweDAwNjcsCiAgImdhYmVuZ2FsaSIsCiAgMHgwOTk3LAogICJnYWN1dGUiLAogIDB4MDFmNSwKICAiZ2FkZXZhIiwKICAweDA5MTcsCiAgImdhZmFyYWJpYyIsCiAgMHgwNmFmLAogICJnYWZmaW5hbGFyYWJpYyIsCiAgMHhmYjkzLAogICJnYWZpbml0aWFsYXJhYmljIiwKICAweGZiOTQsCiAgImdhZm1lZGlhbGFyYWJpYyIsCiAgMHhmYjk1LAogICJnYWd1amFyYXRpIiwKICAweDBhOTcsCiAgImdhZ3VybXVraGkiLAogIDB4MGExNywKICAiZ2FoaXJhZ2FuYSIsCiAgMHgzMDRjLAogICJnYWthdGFrYW5hIiwKICAweDMwYWMsCiAgImdhbW1hIiwKICAweDAzYjMsCiAgImdhbW1hbGF0aW5zbWFsbCIsCiAgMHgwMjYzLAogICJnYW1tYXN1cGVyaW9yIiwKICAweDAyZTAsCiAgImdhbmdpYWNvcHRpYyIsCiAgMHgwM2ViLAogICJnYm9wb21vZm8iLAogIDB4MzEwZCwKICAiZ2JyZXZlIiwKICAweDAxMWYsCiAgImdjYXJvbiIsCiAgMHgwMWU3LAogICJnY2VkaWxsYSIsCiAgMHgwMTIzLAogICJnY2lyY2xlIiwKICAweDI0ZDYsCiAgImdjaXJjdW1mbGV4IiwKICAweDAxMWQsCiAgImdjb21tYWFjY2VudCIsCiAgMHgwMTIzLAogICJnZG90IiwKICAweDAxMjEsCiAgImdkb3RhY2NlbnQiLAogIDB4MDEyMSwKICAiZ2VjeXJpbGxpYyIsCiAgMHgwNDMzLAogICJnZWhpcmFnYW5hIiwKICAweDMwNTIsCiAgImdla2F0YWthbmEiLAogIDB4MzBiMiwKICAiZ2VvbWV0cmljYWxseWVxdWFsIiwKICAweDIyNTEsCiAgImdlcmVzaGFjY2VudGhlYnJldyIsCiAgMHgwNTljLAogICJnZXJlc2hoZWJyZXciLAogIDB4MDVmMywKICAiZ2VyZXNobXVxZGFtaGVicmV3IiwKICAweDA1OWQsCiAgImdlcm1hbmRibHMiLAogIDB4MDBkZiwKICAiZ2Vyc2hheWltYWNjZW50aGVicmV3IiwKICAweDA1OWUsCiAgImdlcnNoYXlpbWhlYnJldyIsCiAgMHgwNWY0LAogICJnZXRhbWFyayIsCiAgMHgzMDEzLAogICJnaGFiZW5nYWxpIiwKICAweDA5OTgsCiAgImdoYWRhcm1lbmlhbiIsCiAgMHgwNTcyLAogICJnaGFkZXZhIiwKICAweDA5MTgsCiAgImdoYWd1amFyYXRpIiwKICAweDBhOTgsCiAgImdoYWd1cm11a2hpIiwKICAweDBhMTgsCiAgImdoYWluYXJhYmljIiwKICAweDA2M2EsCiAgImdoYWluZmluYWxhcmFiaWMiLAogIDB4ZmVjZSwKICAiZ2hhaW5pbml0aWFsYXJhYmljIiwKICAweGZlY2YsCiAgImdoYWlubWVkaWFsYXJhYmljIiwKICAweGZlZDAsCiAgImdoZW1pZGRsZWhvb2tjeXJpbGxpYyIsCiAgMHgwNDk1LAogICJnaGVzdHJva2VjeXJpbGxpYyIsCiAgMHgwNDkzLAogICJnaGV1cHR1cm5jeXJpbGxpYyIsCiAgMHgwNDkxLAogICJnaGhhZGV2YSIsCiAgMHgwOTVhLAogICJnaGhhZ3VybXVraGkiLAogIDB4MGE1YSwKICAiZ2hvb2siLAogIDB4MDI2MCwKICAiZ2h6c3F1YXJlIiwKICAweDMzOTMsCiAgImdpaGlyYWdhbmEiLAogIDB4MzA0ZSwKICAiZ2lrYXRha2FuYSIsCiAgMHgzMGFlLAogICJnaW1hcm1lbmlhbiIsCiAgMHgwNTYzLAogICJnaW1lbCIsCiAgMHgwNWQyLAogICJnaW1lbGRhZ2VzaCIsCiAgMHhmYjMyLAogICJnaW1lbGRhZ2VzaGhlYnJldyIsCiAgMHhmYjMyLAogICJnaW1lbGhlYnJldyIsCiAgMHgwNWQyLAogICJnamVjeXJpbGxpYyIsCiAgMHgwNDUzLAogICJnbG90dGFsaW52ZXJ0ZWRzdHJva2UiLAogIDB4MDFiZSwKICAiZ2xvdHRhbHN0b3AiLAogIDB4MDI5NCwKICAiZ2xvdHRhbHN0b3BpbnZlcnRlZCIsCiAgMHgwMjk2LAogICJnbG90dGFsc3RvcG1vZCIsCiAgMHgwMmMwLAogICJnbG90dGFsc3RvcHJldmVyc2VkIiwKICAweDAyOTUsCiAgImdsb3R0YWxzdG9wcmV2ZXJzZWRtb2QiLAogIDB4MDJjMSwKICAiZ2xvdHRhbHN0b3ByZXZlcnNlZHN1cGVyaW9yIiwKICAweDAyZTQsCiAgImdsb3R0YWxzdG9wc3Ryb2tlIiwKICAweDAyYTEsCiAgImdsb3R0YWxzdG9wc3Ryb2tlcmV2ZXJzZWQiLAogIDB4MDJhMiwKICAiZ21hY3JvbiIsCiAgMHgxZTIxLAogICJnbW9ub3NwYWNlIiwKICAweGZmNDcsCiAgImdvaGlyYWdhbmEiLAogIDB4MzA1NCwKICAiZ29rYXRha2FuYSIsCiAgMHgzMGI0LAogICJncGFyZW4iLAogIDB4MjRhMiwKICAiZ3Bhc3F1YXJlIiwKICAweDMzYWMsCiAgImdyYWRpZW50IiwKICAweDIyMDcsCiAgImdyYXZlIiwKICAweDAwNjAsCiAgImdyYXZlYmVsb3djbWIiLAogIDB4MDMxNiwKICAiZ3JhdmVjbWIiLAogIDB4MDMwMCwKICAiZ3JhdmVjb21iIiwKICAweDAzMDAsCiAgImdyYXZlZGV2YSIsCiAgMHgwOTUzLAogICJncmF2ZWxvd21vZCIsCiAgMHgwMmNlLAogICJncmF2ZW1vbm9zcGFjZSIsCiAgMHhmZjQwLAogICJncmF2ZXRvbmVjbWIiLAogIDB4MDM0MCwKICAiZ3JlYXRlciIsCiAgMHgwMDNlLAogICJncmVhdGVyZXF1YWwiLAogIDB4MjI2NSwKICAiZ3JlYXRlcmVxdWFsb3JsZXNzIiwKICAweDIyZGIsCiAgImdyZWF0ZXJtb25vc3BhY2UiLAogIDB4ZmYxZSwKICAiZ3JlYXRlcm9yZXF1aXZhbGVudCIsCiAgMHgyMjczLAogICJncmVhdGVyb3JsZXNzIiwKICAweDIyNzcsCiAgImdyZWF0ZXJvdmVyZXF1YWwiLAogIDB4MjI2NywKICAiZ3JlYXRlcnNtYWxsIiwKICAweGZlNjUsCiAgImdzY3JpcHQiLAogIDB4MDI2MSwKICAiZ3N0cm9rZSIsCiAgMHgwMWU1LAogICJndWhpcmFnYW5hIiwKICAweDMwNTAsCiAgImd1aWxsZW1vdGxlZnQiLAogIDB4MDBhYiwKICAiZ3VpbGxlbW90cmlnaHQiLAogIDB4MDBiYiwKICAiZ3VpbHNpbmdsbGVmdCIsCiAgMHgyMDM5LAogICJndWlsc2luZ2xyaWdodCIsCiAgMHgyMDNhLAogICJndWthdGFrYW5hIiwKICAweDMwYjAsCiAgImd1cmFtdXNxdWFyZSIsCiAgMHgzMzE4LAogICJneXNxdWFyZSIsCiAgMHgzM2M5LAogICJoIiwKICAweDAwNjgsCiAgImhhYWJraGFzaWFuY3lyaWxsaWMiLAogIDB4MDRhOSwKICAiaGFhbHRvbmVhcmFiaWMiLAogIDB4MDZjMSwKICAiaGFiZW5nYWxpIiwKICAweDA5YjksCiAgImhhZGVzY2VuZGVyY3lyaWxsaWMiLAogIDB4MDRiMywKICAiaGFkZXZhIiwKICAweDA5MzksCiAgImhhZ3VqYXJhdGkiLAogIDB4MGFiOSwKICAiaGFndXJtdWtoaSIsCiAgMHgwYTM5LAogICJoYWhhcmFiaWMiLAogIDB4MDYyZCwKICAiaGFoZmluYWxhcmFiaWMiLAogIDB4ZmVhMiwKICAiaGFoaW5pdGlhbGFyYWJpYyIsCiAgMHhmZWEzLAogICJoYWhpcmFnYW5hIiwKICAweDMwNmYsCiAgImhhaG1lZGlhbGFyYWJpYyIsCiAgMHhmZWE0LAogICJoYWl0dXNxdWFyZSIsCiAgMHgzMzJhLAogICJoYWthdGFrYW5hIiwKICAweDMwY2YsCiAgImhha2F0YWthbmFoYWxmd2lkdGgiLAogIDB4ZmY4YSwKICAiaGFsYW50Z3VybXVraGkiLAogIDB4MGE0ZCwKICAiaGFtemFhcmFiaWMiLAogIDB4MDYyMSwKICAiaGFtemFsb3dhcmFiaWMiLAogIDB4MDYyMSwKICAiaGFuZ3VsZmlsbGVyIiwKICAweDMxNjQsCiAgImhhcmRzaWduY3lyaWxsaWMiLAogIDB4MDQ0YSwKICAiaGFycG9vbmxlZnRiYXJidXAiLAogIDB4MjFiYywKICAiaGFycG9vbnJpZ2h0YmFyYnVwIiwKICAweDIxYzAsCiAgImhhc3F1YXJlIiwKICAweDMzY2EsCiAgImhhdGFmcGF0YWgiLAogIDB4MDViMiwKICAiaGF0YWZwYXRhaDE2IiwKICAweDA1YjIsCiAgImhhdGFmcGF0YWgyMyIsCiAgMHgwNWIyLAogICJoYXRhZnBhdGFoMmYiLAogIDB4MDViMiwKICAiaGF0YWZwYXRhaGhlYnJldyIsCiAgMHgwNWIyLAogICJoYXRhZnBhdGFobmFycm93aGVicmV3IiwKICAweDA1YjIsCiAgImhhdGFmcGF0YWhxdWFydGVyaGVicmV3IiwKICAweDA1YjIsCiAgImhhdGFmcGF0YWh3aWRlaGVicmV3IiwKICAweDA1YjIsCiAgImhhdGFmcWFtYXRzIiwKICAweDA1YjMsCiAgImhhdGFmcWFtYXRzMWIiLAogIDB4MDViMywKICAiaGF0YWZxYW1hdHMyOCIsCiAgMHgwNWIzLAogICJoYXRhZnFhbWF0czM0IiwKICAweDA1YjMsCiAgImhhdGFmcWFtYXRzaGVicmV3IiwKICAweDA1YjMsCiAgImhhdGFmcWFtYXRzbmFycm93aGVicmV3IiwKICAweDA1YjMsCiAgImhhdGFmcWFtYXRzcXVhcnRlcmhlYnJldyIsCiAgMHgwNWIzLAogICJoYXRhZnFhbWF0c3dpZGVoZWJyZXciLAogIDB4MDViMywKICAiaGF0YWZzZWdvbCIsCiAgMHgwNWIxLAogICJoYXRhZnNlZ29sMTciLAogIDB4MDViMSwKICAiaGF0YWZzZWdvbDI0IiwKICAweDA1YjEsCiAgImhhdGFmc2Vnb2wzMCIsCiAgMHgwNWIxLAogICJoYXRhZnNlZ29saGVicmV3IiwKICAweDA1YjEsCiAgImhhdGFmc2Vnb2xuYXJyb3doZWJyZXciLAogIDB4MDViMSwKICAiaGF0YWZzZWdvbHF1YXJ0ZXJoZWJyZXciLAogIDB4MDViMSwKICAiaGF0YWZzZWdvbHdpZGVoZWJyZXciLAogIDB4MDViMSwKICAiaGJhciIsCiAgMHgwMTI3LAogICJoYm9wb21vZm8iLAogIDB4MzEwZiwKICAiaGJyZXZlYmVsb3ciLAogIDB4MWUyYiwKICAiaGNlZGlsbGEiLAogIDB4MWUyOSwKICAiaGNpcmNsZSIsCiAgMHgyNGQ3LAogICJoY2lyY3VtZmxleCIsCiAgMHgwMTI1LAogICJoZGllcmVzaXMiLAogIDB4MWUyNywKICAiaGRvdGFjY2VudCIsCiAgMHgxZTIzLAogICJoZG90YmVsb3ciLAogIDB4MWUyNSwKICAiaGUiLAogIDB4MDVkNCwKICAiaGVhcnQiLAogIDB4MjY2NSwKICAiaGVhcnRzdWl0YmxhY2siLAogIDB4MjY2NSwKICAiaGVhcnRzdWl0d2hpdGUiLAogIDB4MjY2MSwKICAiaGVkYWdlc2giLAogIDB4ZmIzNCwKICAiaGVkYWdlc2hoZWJyZXciLAogIDB4ZmIzNCwKICAiaGVoYWx0b25lYXJhYmljIiwKICAweDA2YzEsCiAgImhlaGFyYWJpYyIsCiAgMHgwNjQ3LAogICJoZWhlYnJldyIsCiAgMHgwNWQ0LAogICJoZWhmaW5hbGFsdG9uZWFyYWJpYyIsCiAgMHhmYmE3LAogICJoZWhmaW5hbGFsdHR3b2FyYWJpYyIsCiAgMHhmZWVhLAogICJoZWhmaW5hbGFyYWJpYyIsCiAgMHhmZWVhLAogICJoZWhoYW16YWFib3ZlZmluYWxhcmFiaWMiLAogIDB4ZmJhNSwKICAiaGVoaGFtemFhYm92ZWlzb2xhdGVkYXJhYmljIiwKICAweGZiYTQsCiAgImhlaGluaXRpYWxhbHRvbmVhcmFiaWMiLAogIDB4ZmJhOCwKICAiaGVoaW5pdGlhbGFyYWJpYyIsCiAgMHhmZWViLAogICJoZWhpcmFnYW5hIiwKICAweDMwNzgsCiAgImhlaG1lZGlhbGFsdG9uZWFyYWJpYyIsCiAgMHhmYmE5LAogICJoZWhtZWRpYWxhcmFiaWMiLAogIDB4ZmVlYywKICAiaGVpc2VpZXJhc3F1YXJlIiwKICAweDMzN2IsCiAgImhla2F0YWthbmEiLAogIDB4MzBkOCwKICAiaGVrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjhkLAogICJoZWt1dGFhcnVzcXVhcmUiLAogIDB4MzMzNiwKICAiaGVuZ2hvb2siLAogIDB4MDI2NywKICAiaGVydXR1c3F1YXJlIiwKICAweDMzMzksCiAgImhldCIsCiAgMHgwNWQ3LAogICJoZXRoZWJyZXciLAogIDB4MDVkNywKICAiaGhvb2siLAogIDB4MDI2NiwKICAiaGhvb2tzdXBlcmlvciIsCiAgMHgwMmIxLAogICJoaWV1aGFjaXJjbGVrb3JlYW4iLAogIDB4MzI3YiwKICAiaGlldWhhcGFyZW5rb3JlYW4iLAogIDB4MzIxYiwKICAiaGlldWhjaXJjbGVrb3JlYW4iLAogIDB4MzI2ZCwKICAiaGlldWhrb3JlYW4iLAogIDB4MzE0ZSwKICAiaGlldWhwYXJlbmtvcmVhbiIsCiAgMHgzMjBkLAogICJoaWhpcmFnYW5hIiwKICAweDMwNzIsCiAgImhpa2F0YWthbmEiLAogIDB4MzBkMiwKICAiaGlrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjhiLAogICJoaXJpcSIsCiAgMHgwNWI0LAogICJoaXJpcTE0IiwKICAweDA1YjQsCiAgImhpcmlxMjEiLAogIDB4MDViNCwKICAiaGlyaXEyZCIsCiAgMHgwNWI0LAogICJoaXJpcWhlYnJldyIsCiAgMHgwNWI0LAogICJoaXJpcW5hcnJvd2hlYnJldyIsCiAgMHgwNWI0LAogICJoaXJpcXF1YXJ0ZXJoZWJyZXciLAogIDB4MDViNCwKICAiaGlyaXF3aWRlaGVicmV3IiwKICAweDA1YjQsCiAgImhsaW5lYmVsb3ciLAogIDB4MWU5NiwKICAiaG1vbm9zcGFjZSIsCiAgMHhmZjQ4LAogICJob2FybWVuaWFuIiwKICAweDA1NzAsCiAgImhvaGlwdGhhaSIsCiAgMHgwZTJiLAogICJob2hpcmFnYW5hIiwKICAweDMwN2IsCiAgImhva2F0YWthbmEiLAogIDB4MzBkYiwKICAiaG9rYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjhlLAogICJob2xhbSIsCiAgMHgwNWI5LAogICJob2xhbTE5IiwKICAweDA1YjksCiAgImhvbGFtMjYiLAogIDB4MDViOSwKICAiaG9sYW0zMiIsCiAgMHgwNWI5LAogICJob2xhbWhlYnJldyIsCiAgMHgwNWI5LAogICJob2xhbW5hcnJvd2hlYnJldyIsCiAgMHgwNWI5LAogICJob2xhbXF1YXJ0ZXJoZWJyZXciLAogIDB4MDViOSwKICAiaG9sYW13aWRlaGVicmV3IiwKICAweDA1YjksCiAgImhvbm9raHVrdGhhaSIsCiAgMHgwZTJlLAogICJob29rYWJvdmVjb21iIiwKICAweDAzMDksCiAgImhvb2tjbWIiLAogIDB4MDMwOSwKICAiaG9va3BhbGF0YWxpemVkYmVsb3djbWIiLAogIDB4MDMyMSwKICAiaG9va3JldHJvZmxleGJlbG93Y21iIiwKICAweDAzMjIsCiAgImhvb25zcXVhcmUiLAogIDB4MzM0MiwKICAiaG9yaWNvcHRpYyIsCiAgMHgwM2U5LAogICJob3Jpem9udGFsYmFyIiwKICAweDIwMTUsCiAgImhvcm5jbWIiLAogIDB4MDMxYiwKICAiaG90c3ByaW5ncyIsCiAgMHgyNjY4LAogICJob3VzZSIsCiAgMHgyMzAyLAogICJocGFyZW4iLAogIDB4MjRhMywKICAiaHN1cGVyaW9yIiwKICAweDAyYjAsCiAgImh0dXJuZWQiLAogIDB4MDI2NSwKICAiaHVoaXJhZ2FuYSIsCiAgMHgzMDc1LAogICJodWlpdG9zcXVhcmUiLAogIDB4MzMzMywKICAiaHVrYXRha2FuYSIsCiAgMHgzMGQ1LAogICJodWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmOGMsCiAgImh1bmdhcnVtbGF1dCIsCiAgMHgwMmRkLAogICJodW5nYXJ1bWxhdXRjbWIiLAogIDB4MDMwYiwKICAiaHYiLAogIDB4MDE5NSwKICAiaHlwaGVuIiwKICAweDAwMmQsCiAgImh5cGhlbmluZmVyaW9yIiwKICAweGY2ZTUsCiAgImh5cGhlbm1vbm9zcGFjZSIsCiAgMHhmZjBkLAogICJoeXBoZW5zbWFsbCIsCiAgMHhmZTYzLAogICJoeXBoZW5zdXBlcmlvciIsCiAgMHhmNmU2LAogICJoeXBoZW50d28iLAogIDB4MjAxMCwKICAiaSIsCiAgMHgwMDY5LAogICJpYWN1dGUiLAogIDB4MDBlZCwKICAiaWFjeXJpbGxpYyIsCiAgMHgwNDRmLAogICJpYmVuZ2FsaSIsCiAgMHgwOTg3LAogICJpYm9wb21vZm8iLAogIDB4MzEyNywKICAiaWJyZXZlIiwKICAweDAxMmQsCiAgImljYXJvbiIsCiAgMHgwMWQwLAogICJpY2lyY2xlIiwKICAweDI0ZDgsCiAgImljaXJjdW1mbGV4IiwKICAweDAwZWUsCiAgImljeXJpbGxpYyIsCiAgMHgwNDU2LAogICJpZGJsZ3JhdmUiLAogIDB4MDIwOSwKICAiaWRlb2dyYXBoZWFydGhjaXJjbGUiLAogIDB4MzI4ZiwKICAiaWRlb2dyYXBoZmlyZWNpcmNsZSIsCiAgMHgzMjhiLAogICJpZGVvZ3JhcGhpY2FsbGlhbmNlcGFyZW4iLAogIDB4MzIzZiwKICAiaWRlb2dyYXBoaWNjYWxscGFyZW4iLAogIDB4MzIzYSwKICAiaWRlb2dyYXBoaWNjZW50cmVjaXJjbGUiLAogIDB4MzJhNSwKICAiaWRlb2dyYXBoaWNjbG9zZSIsCiAgMHgzMDA2LAogICJpZGVvZ3JhcGhpY2NvbW1hIiwKICAweDMwMDEsCiAgImlkZW9ncmFwaGljY29tbWFsZWZ0IiwKICAweGZmNjQsCiAgImlkZW9ncmFwaGljY29uZ3JhdHVsYXRpb25wYXJlbiIsCiAgMHgzMjM3LAogICJpZGVvZ3JhcGhpY2NvcnJlY3RjaXJjbGUiLAogIDB4MzJhMywKICAiaWRlb2dyYXBoaWNlYXJ0aHBhcmVuIiwKICAweDMyMmYsCiAgImlkZW9ncmFwaGljZW50ZXJwcmlzZXBhcmVuIiwKICAweDMyM2QsCiAgImlkZW9ncmFwaGljZXhjZWxsZW50Y2lyY2xlIiwKICAweDMyOWQsCiAgImlkZW9ncmFwaGljZmVzdGl2YWxwYXJlbiIsCiAgMHgzMjQwLAogICJpZGVvZ3JhcGhpY2ZpbmFuY2lhbGNpcmNsZSIsCiAgMHgzMjk2LAogICJpZGVvZ3JhcGhpY2ZpbmFuY2lhbHBhcmVuIiwKICAweDMyMzYsCiAgImlkZW9ncmFwaGljZmlyZXBhcmVuIiwKICAweDMyMmIsCiAgImlkZW9ncmFwaGljaGF2ZXBhcmVuIiwKICAweDMyMzIsCiAgImlkZW9ncmFwaGljaGlnaGNpcmNsZSIsCiAgMHgzMmE0LAogICJpZGVvZ3JhcGhpY2l0ZXJhdGlvbm1hcmsiLAogIDB4MzAwNSwKICAiaWRlb2dyYXBoaWNsYWJvcmNpcmNsZSIsCiAgMHgzMjk4LAogICJpZGVvZ3JhcGhpY2xhYm9ycGFyZW4iLAogIDB4MzIzOCwKICAiaWRlb2dyYXBoaWNsZWZ0Y2lyY2xlIiwKICAweDMyYTcsCiAgImlkZW9ncmFwaGljbG93Y2lyY2xlIiwKICAweDMyYTYsCiAgImlkZW9ncmFwaGljbWVkaWNpbmVjaXJjbGUiLAogIDB4MzJhOSwKICAiaWRlb2dyYXBoaWNtZXRhbHBhcmVuIiwKICAweDMyMmUsCiAgImlkZW9ncmFwaGljbW9vbnBhcmVuIiwKICAweDMyMmEsCiAgImlkZW9ncmFwaGljbmFtZXBhcmVuIiwKICAweDMyMzQsCiAgImlkZW9ncmFwaGljcGVyaW9kIiwKICAweDMwMDIsCiAgImlkZW9ncmFwaGljcHJpbnRjaXJjbGUiLAogIDB4MzI5ZSwKICAiaWRlb2dyYXBoaWNyZWFjaHBhcmVuIiwKICAweDMyNDMsCiAgImlkZW9ncmFwaGljcmVwcmVzZW50cGFyZW4iLAogIDB4MzIzOSwKICAiaWRlb2dyYXBoaWNyZXNvdXJjZXBhcmVuIiwKICAweDMyM2UsCiAgImlkZW9ncmFwaGljcmlnaHRjaXJjbGUiLAogIDB4MzJhOCwKICAiaWRlb2dyYXBoaWNzZWNyZXRjaXJjbGUiLAogIDB4MzI5OSwKICAiaWRlb2dyYXBoaWNzZWxmcGFyZW4iLAogIDB4MzI0MiwKICAiaWRlb2dyYXBoaWNzb2NpZXR5cGFyZW4iLAogIDB4MzIzMywKICAiaWRlb2dyYXBoaWNzcGFjZSIsCiAgMHgzMDAwLAogICJpZGVvZ3JhcGhpY3NwZWNpYWxwYXJlbiIsCiAgMHgzMjM1LAogICJpZGVvZ3JhcGhpY3N0b2NrcGFyZW4iLAogIDB4MzIzMSwKICAiaWRlb2dyYXBoaWNzdHVkeXBhcmVuIiwKICAweDMyM2IsCiAgImlkZW9ncmFwaGljc3VucGFyZW4iLAogIDB4MzIzMCwKICAiaWRlb2dyYXBoaWNzdXBlcnZpc2VwYXJlbiIsCiAgMHgzMjNjLAogICJpZGVvZ3JhcGhpY3dhdGVycGFyZW4iLAogIDB4MzIyYywKICAiaWRlb2dyYXBoaWN3b29kcGFyZW4iLAogIDB4MzIyZCwKICAiaWRlb2dyYXBoaWN6ZXJvIiwKICAweDMwMDcsCiAgImlkZW9ncmFwaG1ldGFsY2lyY2xlIiwKICAweDMyOGUsCiAgImlkZW9ncmFwaG1vb25jaXJjbGUiLAogIDB4MzI4YSwKICAiaWRlb2dyYXBobmFtZWNpcmNsZSIsCiAgMHgzMjk0LAogICJpZGVvZ3JhcGhzdW5jaXJjbGUiLAogIDB4MzI5MCwKICAiaWRlb2dyYXBod2F0ZXJjaXJjbGUiLAogIDB4MzI4YywKICAiaWRlb2dyYXBod29vZGNpcmNsZSIsCiAgMHgzMjhkLAogICJpZGV2YSIsCiAgMHgwOTA3LAogICJpZGllcmVzaXMiLAogIDB4MDBlZiwKICAiaWRpZXJlc2lzYWN1dGUiLAogIDB4MWUyZiwKICAiaWRpZXJlc2lzY3lyaWxsaWMiLAogIDB4MDRlNSwKICAiaWRvdGJlbG93IiwKICAweDFlY2IsCiAgImllYnJldmVjeXJpbGxpYyIsCiAgMHgwNGQ3LAogICJpZWN5cmlsbGljIiwKICAweDA0MzUsCiAgImlldW5nYWNpcmNsZWtvcmVhbiIsCiAgMHgzMjc1LAogICJpZXVuZ2FwYXJlbmtvcmVhbiIsCiAgMHgzMjE1LAogICJpZXVuZ2NpcmNsZWtvcmVhbiIsCiAgMHgzMjY3LAogICJpZXVuZ2tvcmVhbiIsCiAgMHgzMTQ3LAogICJpZXVuZ3BhcmVua29yZWFuIiwKICAweDMyMDcsCiAgImlncmF2ZSIsCiAgMHgwMGVjLAogICJpZ3VqYXJhdGkiLAogIDB4MGE4NywKICAiaWd1cm11a2hpIiwKICAweDBhMDcsCiAgImloaXJhZ2FuYSIsCiAgMHgzMDQ0LAogICJpaG9va2Fib3ZlIiwKICAweDFlYzksCiAgImlpYmVuZ2FsaSIsCiAgMHgwOTg4LAogICJpaWN5cmlsbGljIiwKICAweDA0MzgsCiAgImlpZGV2YSIsCiAgMHgwOTA4LAogICJpaWd1amFyYXRpIiwKICAweDBhODgsCiAgImlpZ3VybXVraGkiLAogIDB4MGEwOCwKICAiaWltYXRyYWd1cm11a2hpIiwKICAweDBhNDAsCiAgImlpbnZlcnRlZGJyZXZlIiwKICAweDAyMGIsCiAgImlpc2hvcnRjeXJpbGxpYyIsCiAgMHgwNDM5LAogICJpaXZvd2Vsc2lnbmJlbmdhbGkiLAogIDB4MDljMCwKICAiaWl2b3dlbHNpZ25kZXZhIiwKICAweDA5NDAsCiAgImlpdm93ZWxzaWduZ3VqYXJhdGkiLAogIDB4MGFjMCwKICAiaWoiLAogIDB4MDEzMywKICAiaWthdGFrYW5hIiwKICAweDMwYTQsCiAgImlrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjcyLAogICJpa29yZWFuIiwKICAweDMxNjMsCiAgImlsZGUiLAogIDB4MDJkYywKICAiaWx1eWhlYnJldyIsCiAgMHgwNWFjLAogICJpbWFjcm9uIiwKICAweDAxMmIsCiAgImltYWNyb25jeXJpbGxpYyIsCiAgMHgwNGUzLAogICJpbWFnZW9yYXBwcm94aW1hdGVseWVxdWFsIiwKICAweDIyNTMsCiAgImltYXRyYWd1cm11a2hpIiwKICAweDBhM2YsCiAgImltb25vc3BhY2UiLAogIDB4ZmY0OSwKICAiaW5jcmVtZW50IiwKICAweDIyMDYsCiAgImluZmluaXR5IiwKICAweDIyMWUsCiAgImluaWFybWVuaWFuIiwKICAweDA1NmIsCiAgImludGVncmFsIiwKICAweDIyMmIsCiAgImludGVncmFsYm90dG9tIiwKICAweDIzMjEsCiAgImludGVncmFsYnQiLAogIDB4MjMyMSwKICAiaW50ZWdyYWxleCIsCiAgMHhmOGY1LAogICJpbnRlZ3JhbHRvcCIsCiAgMHgyMzIwLAogICJpbnRlZ3JhbHRwIiwKICAweDIzMjAsCiAgImludGVyc2VjdGlvbiIsCiAgMHgyMjI5LAogICJpbnRpc3F1YXJlIiwKICAweDMzMDUsCiAgImludmJ1bGxldCIsCiAgMHgyNWQ4LAogICJpbnZjaXJjbGUiLAogIDB4MjVkOSwKICAiaW52c21pbGVmYWNlIiwKICAweDI2M2IsCiAgImlvY3lyaWxsaWMiLAogIDB4MDQ1MSwKICAiaW9nb25layIsCiAgMHgwMTJmLAogICJpb3RhIiwKICAweDAzYjksCiAgImlvdGFkaWVyZXNpcyIsCiAgMHgwM2NhLAogICJpb3RhZGllcmVzaXN0b25vcyIsCiAgMHgwMzkwLAogICJpb3RhbGF0aW4iLAogIDB4MDI2OSwKICAiaW90YXRvbm9zIiwKICAweDAzYWYsCiAgImlwYXJlbiIsCiAgMHgyNGE0LAogICJpcmlndXJtdWtoaSIsCiAgMHgwYTcyLAogICJpc21hbGxoaXJhZ2FuYSIsCiAgMHgzMDQzLAogICJpc21hbGxrYXRha2FuYSIsCiAgMHgzMGEzLAogICJpc21hbGxrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjY4LAogICJpc3NoYXJiZW5nYWxpIiwKICAweDA5ZmEsCiAgImlzdHJva2UiLAogIDB4MDI2OCwKICAiaXN1cGVyaW9yIiwKICAweGY2ZWQsCiAgIml0ZXJhdGlvbmhpcmFnYW5hIiwKICAweDMwOWQsCiAgIml0ZXJhdGlvbmthdGFrYW5hIiwKICAweDMwZmQsCiAgIml0aWxkZSIsCiAgMHgwMTI5LAogICJpdGlsZGViZWxvdyIsCiAgMHgxZTJkLAogICJpdWJvcG9tb2ZvIiwKICAweDMxMjksCiAgIml1Y3lyaWxsaWMiLAogIDB4MDQ0ZSwKICAiaXZvd2Vsc2lnbmJlbmdhbGkiLAogIDB4MDliZiwKICAiaXZvd2Vsc2lnbmRldmEiLAogIDB4MDkzZiwKICAiaXZvd2Vsc2lnbmd1amFyYXRpIiwKICAweDBhYmYsCiAgIml6aGl0c2FjeXJpbGxpYyIsCiAgMHgwNDc1LAogICJpemhpdHNhZGJsZ3JhdmVjeXJpbGxpYyIsCiAgMHgwNDc3LAogICJqIiwKICAweDAwNmEsCiAgImphYXJtZW5pYW4iLAogIDB4MDU3MSwKICAiamFiZW5nYWxpIiwKICAweDA5OWMsCiAgImphZGV2YSIsCiAgMHgwOTFjLAogICJqYWd1amFyYXRpIiwKICAweDBhOWMsCiAgImphZ3VybXVraGkiLAogIDB4MGExYywKICAiamJvcG9tb2ZvIiwKICAweDMxMTAsCiAgImpjYXJvbiIsCiAgMHgwMWYwLAogICJqY2lyY2xlIiwKICAweDI0ZDksCiAgImpjaXJjdW1mbGV4IiwKICAweDAxMzUsCiAgImpjcm9zc2VkdGFpbCIsCiAgMHgwMjlkLAogICJqZG90bGVzc3N0cm9rZSIsCiAgMHgwMjVmLAogICJqZWN5cmlsbGljIiwKICAweDA0NTgsCiAgImplZW1hcmFiaWMiLAogIDB4MDYyYywKICAiamVlbWZpbmFsYXJhYmljIiwKICAweGZlOWUsCiAgImplZW1pbml0aWFsYXJhYmljIiwKICAweGZlOWYsCiAgImplZW1tZWRpYWxhcmFiaWMiLAogIDB4ZmVhMCwKICAiamVoYXJhYmljIiwKICAweDA2OTgsCiAgImplaGZpbmFsYXJhYmljIiwKICAweGZiOGIsCiAgImpoYWJlbmdhbGkiLAogIDB4MDk5ZCwKICAiamhhZGV2YSIsCiAgMHgwOTFkLAogICJqaGFndWphcmF0aSIsCiAgMHgwYTlkLAogICJqaGFndXJtdWtoaSIsCiAgMHgwYTFkLAogICJqaGVoYXJtZW5pYW4iLAogIDB4MDU3YiwKICAiamlzIiwKICAweDMwMDQsCiAgImptb25vc3BhY2UiLAogIDB4ZmY0YSwKICAianBhcmVuIiwKICAweDI0YTUsCiAgImpzdXBlcmlvciIsCiAgMHgwMmIyLAogICJrIiwKICAweDAwNmIsCiAgImthYmFzaGtpcmN5cmlsbGljIiwKICAweDA0YTEsCiAgImthYmVuZ2FsaSIsCiAgMHgwOTk1LAogICJrYWN1dGUiLAogIDB4MWUzMSwKICAia2FjeXJpbGxpYyIsCiAgMHgwNDNhLAogICJrYWRlc2NlbmRlcmN5cmlsbGljIiwKICAweDA0OWIsCiAgImthZGV2YSIsCiAgMHgwOTE1LAogICJrYWYiLAogIDB4MDVkYiwKICAia2FmYXJhYmljIiwKICAweDA2NDMsCiAgImthZmRhZ2VzaCIsCiAgMHhmYjNiLAogICJrYWZkYWdlc2hoZWJyZXciLAogIDB4ZmIzYiwKICAia2FmZmluYWxhcmFiaWMiLAogIDB4ZmVkYSwKICAia2FmaGVicmV3IiwKICAweDA1ZGIsCiAgImthZmluaXRpYWxhcmFiaWMiLAogIDB4ZmVkYiwKICAia2FmbWVkaWFsYXJhYmljIiwKICAweGZlZGMsCiAgImthZnJhZmVoZWJyZXciLAogIDB4ZmI0ZCwKICAia2FndWphcmF0aSIsCiAgMHgwYTk1LAogICJrYWd1cm11a2hpIiwKICAweDBhMTUsCiAgImthaGlyYWdhbmEiLAogIDB4MzA0YiwKICAia2Fob29rY3lyaWxsaWMiLAogIDB4MDRjNCwKICAia2FrYXRha2FuYSIsCiAgMHgzMGFiLAogICJrYWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmNzYsCiAgImthcHBhIiwKICAweDAzYmEsCiAgImthcHBhc3ltYm9sZ3JlZWsiLAogIDB4MDNmMCwKICAia2FweWVvdW5taWV1bWtvcmVhbiIsCiAgMHgzMTcxLAogICJrYXB5ZW91bnBoaWV1cGhrb3JlYW4iLAogIDB4MzE4NCwKICAia2FweWVvdW5waWV1cGtvcmVhbiIsCiAgMHgzMTc4LAogICJrYXB5ZW91bnNzYW5ncGlldXBrb3JlYW4iLAogIDB4MzE3OSwKICAia2Fyb3JpaXNxdWFyZSIsCiAgMHgzMzBkLAogICJrYXNoaWRhYXV0b2FyYWJpYyIsCiAgMHgwNjQwLAogICJrYXNoaWRhYXV0b25vc2lkZWJlYXJpbmdhcmFiaWMiLAogIDB4MDY0MCwKICAia2FzbWFsbGthdGFrYW5hIiwKICAweDMwZjUsCiAgImthc3F1YXJlIiwKICAweDMzODQsCiAgImthc3JhYXJhYmljIiwKICAweDA2NTAsCiAgImthc3JhdGFuYXJhYmljIiwKICAweDA2NGQsCiAgImthc3Ryb2tlY3lyaWxsaWMiLAogIDB4MDQ5ZiwKICAia2F0YWhpcmFwcm9sb25nbWFya2hhbGZ3aWR0aCIsCiAgMHhmZjcwLAogICJrYXZlcnRpY2Fsc3Ryb2tlY3lyaWxsaWMiLAogIDB4MDQ5ZCwKICAia2JvcG9tb2ZvIiwKICAweDMxMGUsCiAgImtjYWxzcXVhcmUiLAogIDB4MzM4OSwKICAia2Nhcm9uIiwKICAweDAxZTksCiAgImtjZWRpbGxhIiwKICAweDAxMzcsCiAgImtjaXJjbGUiLAogIDB4MjRkYSwKICAia2NvbW1hYWNjZW50IiwKICAweDAxMzcsCiAgImtkb3RiZWxvdyIsCiAgMHgxZTMzLAogICJrZWhhcm1lbmlhbiIsCiAgMHgwNTg0LAogICJrZWhpcmFnYW5hIiwKICAweDMwNTEsCiAgImtla2F0YWthbmEiLAogIDB4MzBiMSwKICAia2VrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjc5LAogICJrZW5hcm1lbmlhbiIsCiAgMHgwNTZmLAogICJrZXNtYWxsa2F0YWthbmEiLAogIDB4MzBmNiwKICAia2dyZWVubGFuZGljIiwKICAweDAxMzgsCiAgImtoYWJlbmdhbGkiLAogIDB4MDk5NiwKICAia2hhY3lyaWxsaWMiLAogIDB4MDQ0NSwKICAia2hhZGV2YSIsCiAgMHgwOTE2LAogICJraGFndWphcmF0aSIsCiAgMHgwYTk2LAogICJraGFndXJtdWtoaSIsCiAgMHgwYTE2LAogICJraGFoYXJhYmljIiwKICAweDA2MmUsCiAgImtoYWhmaW5hbGFyYWJpYyIsCiAgMHhmZWE2LAogICJraGFoaW5pdGlhbGFyYWJpYyIsCiAgMHhmZWE3LAogICJraGFobWVkaWFsYXJhYmljIiwKICAweGZlYTgsCiAgImtoZWljb3B0aWMiLAogIDB4MDNlNywKICAia2hoYWRldmEiLAogIDB4MDk1OSwKICAia2hoYWd1cm11a2hpIiwKICAweDBhNTksCiAgImtoaWV1a2hhY2lyY2xla29yZWFuIiwKICAweDMyNzgsCiAgImtoaWV1a2hhcGFyZW5rb3JlYW4iLAogIDB4MzIxOCwKICAia2hpZXVraGNpcmNsZWtvcmVhbiIsCiAgMHgzMjZhLAogICJraGlldWtoa29yZWFuIiwKICAweDMxNGIsCiAgImtoaWV1a2hwYXJlbmtvcmVhbiIsCiAgMHgzMjBhLAogICJraG9raGFpdGhhaSIsCiAgMHgwZTAyLAogICJraG9raG9udGhhaSIsCiAgMHgwZTA1LAogICJraG9raHVhdHRoYWkiLAogIDB4MGUwMywKICAia2hva2h3YWl0aGFpIiwKICAweDBlMDQsCiAgImtob211dHRoYWkiLAogIDB4MGU1YiwKICAia2hvb2siLAogIDB4MDE5OSwKICAia2hvcmFraGFuZ3RoYWkiLAogIDB4MGUwNiwKICAia2h6c3F1YXJlIiwKICAweDMzOTEsCiAgImtpaGlyYWdhbmEiLAogIDB4MzA0ZCwKICAia2lrYXRha2FuYSIsCiAgMHgzMGFkLAogICJraWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmNzcsCiAgImtpcm9ndXJhbXVzcXVhcmUiLAogIDB4MzMxNSwKICAia2lyb21lZXRvcnVzcXVhcmUiLAogIDB4MzMxNiwKICAia2lyb3NxdWFyZSIsCiAgMHgzMzE0LAogICJraXllb2thY2lyY2xla29yZWFuIiwKICAweDMyNmUsCiAgImtpeWVva2FwYXJlbmtvcmVhbiIsCiAgMHgzMjBlLAogICJraXllb2tjaXJjbGVrb3JlYW4iLAogIDB4MzI2MCwKICAia2l5ZW9ra29yZWFuIiwKICAweDMxMzEsCiAgImtpeWVva3BhcmVua29yZWFuIiwKICAweDMyMDAsCiAgImtpeWVva3Npb3Nrb3JlYW4iLAogIDB4MzEzMywKICAia2plY3lyaWxsaWMiLAogIDB4MDQ1YywKICAia2xpbmViZWxvdyIsCiAgMHgxZTM1LAogICJrbHNxdWFyZSIsCiAgMHgzMzk4LAogICJrbWN1YmVkc3F1YXJlIiwKICAweDMzYTYsCiAgImttb25vc3BhY2UiLAogIDB4ZmY0YiwKICAia21zcXVhcmVkc3F1YXJlIiwKICAweDMzYTIsCiAgImtvaGlyYWdhbmEiLAogIDB4MzA1MywKICAia29obXNxdWFyZSIsCiAgMHgzM2MwLAogICJrb2thaXRoYWkiLAogIDB4MGUwMSwKICAia29rYXRha2FuYSIsCiAgMHgzMGIzLAogICJrb2thdGFrYW5haGFsZndpZHRoIiwKICAweGZmN2EsCiAgImtvb3Bvc3F1YXJlIiwKICAweDMzMWUsCiAgImtvcHBhY3lyaWxsaWMiLAogIDB4MDQ4MSwKICAia29yZWFuc3RhbmRhcmRzeW1ib2wiLAogIDB4MzI3ZiwKICAia29yb25pc2NtYiIsCiAgMHgwMzQzLAogICJrcGFyZW4iLAogIDB4MjRhNiwKICAia3Bhc3F1YXJlIiwKICAweDMzYWEsCiAgImtzaWN5cmlsbGljIiwKICAweDA0NmYsCiAgImt0c3F1YXJlIiwKICAweDMzY2YsCiAgImt0dXJuZWQiLAogIDB4MDI5ZSwKICAia3VoaXJhZ2FuYSIsCiAgMHgzMDRmLAogICJrdWthdGFrYW5hIiwKICAweDMwYWYsCiAgImt1a2F0YWthbmFoYWxmd2lkdGgiLAogIDB4ZmY3OCwKICAia3ZzcXVhcmUiLAogIDB4MzNiOCwKICAia3dzcXVhcmUiLAogIDB4MzNiZSwKICAibCIsCiAgMHgwMDZjLAogICJsYWJlbmdhbGkiLAogIDB4MDliMiwKICAibGFjdXRlIiwKICAweDAxM2EsCiAgImxhZGV2YSIsCiAgMHgwOTMyLAogICJsYWd1amFyYXRpIiwKICAweDBhYjIsCiAgImxhZ3VybXVraGkiLAogIDB4MGEzMiwKICAibGFra2hhbmd5YW90aGFpIiwKICAweDBlNDUsCiAgImxhbWFsZWZmaW5hbGFyYWJpYyIsCiAgMHhmZWZjLAogICJsYW1hbGVmaGFtemFhYm92ZWZpbmFsYXJhYmljIiwKICAweGZlZjgsCiAgImxhbWFsZWZoYW16YWFib3ZlaXNvbGF0ZWRhcmFiaWMiLAogIDB4ZmVmNywKICAibGFtYWxlZmhhbXphYmVsb3dmaW5hbGFyYWJpYyIsCiAgMHhmZWZhLAogICJsYW1hbGVmaGFtemFiZWxvd2lzb2xhdGVkYXJhYmljIiwKICAweGZlZjksCiAgImxhbWFsZWZpc29sYXRlZGFyYWJpYyIsCiAgMHhmZWZiLAogICJsYW1hbGVmbWFkZGFhYm92ZWZpbmFsYXJhYmljIiwKICAweGZlZjYsCiAgImxhbWFsZWZtYWRkYWFib3ZlaXNvbGF0ZWRhcmFiaWMiLAogIDB4ZmVmNSwKICAibGFtYXJhYmljIiwKICAweDA2NDQsCiAgImxhbWJkYSIsCiAgMHgwM2JiLAogICJsYW1iZGFzdHJva2UiLAogIDB4MDE5YiwKICAibGFtZWQiLAogIDB4MDVkYywKICAibGFtZWRkYWdlc2giLAogIDB4ZmIzYywKICAibGFtZWRkYWdlc2hoZWJyZXciLAogIDB4ZmIzYywKICAibGFtZWRoZWJyZXciLAogIDB4MDVkYywKICAibGFtZmluYWxhcmFiaWMiLAogIDB4ZmVkZSwKICAibGFtaGFoaW5pdGlhbGFyYWJpYyIsCiAgMHhmY2NhLAogICJsYW1pbml0aWFsYXJhYmljIiwKICAweGZlZGYsCiAgImxhbWplZW1pbml0aWFsYXJhYmljIiwKICAweGZjYzksCiAgImxhbWtoYWhpbml0aWFsYXJhYmljIiwKICAweGZjY2IsCiAgImxhbWxhbWhlaGlzb2xhdGVkYXJhYmljIiwKICAweGZkZjIsCiAgImxhbW1lZGlhbGFyYWJpYyIsCiAgMHhmZWUwLAogICJsYW1tZWVtaGFoaW5pdGlhbGFyYWJpYyIsCiAgMHhmZDg4LAogICJsYW1tZWVtaW5pdGlhbGFyYWJpYyIsCiAgMHhmY2NjLAogICJsYXJnZWNpcmNsZSIsCiAgMHgyNWVmLAogICJsYmFyIiwKICAweDAxOWEsCiAgImxiZWx0IiwKICAweDAyNmMsCiAgImxib3BvbW9mbyIsCiAgMHgzMTBjLAogICJsY2Fyb24iLAogIDB4MDEzZSwKICAibGNlZGlsbGEiLAogIDB4MDEzYywKICAibGNpcmNsZSIsCiAgMHgyNGRiLAogICJsY2lyY3VtZmxleGJlbG93IiwKICAweDFlM2QsCiAgImxjb21tYWFjY2VudCIsCiAgMHgwMTNjLAogICJsZG90IiwKICAweDAxNDAsCiAgImxkb3RhY2NlbnQiLAogIDB4MDE0MCwKICAibGRvdGJlbG93IiwKICAweDFlMzcsCiAgImxkb3RiZWxvd21hY3JvbiIsCiAgMHgxZTM5LAogICJsZWZ0YW5nbGVhYm92ZWNtYiIsCiAgMHgwMzFhLAogICJsZWZ0dGFja2JlbG93Y21iIiwKICAweDAzMTgsCiAgImxlc3MiLAogIDB4MDAzYywKICAibGVzc2VxdWFsIiwKICAweDIyNjQsCiAgImxlc3NlcXVhbG9yZ3JlYXRlciIsCiAgMHgyMmRhLAogICJsZXNzbW9ub3NwYWNlIiwKICAweGZmMWMsCiAgImxlc3NvcmVxdWl2YWxlbnQiLAogIDB4MjI3MiwKICAibGVzc29yZ3JlYXRlciIsCiAgMHgyMjc2LAogICJsZXNzb3ZlcmVxdWFsIiwKICAweDIyNjYsCiAgImxlc3NzbWFsbCIsCiAgMHhmZTY0LAogICJsZXpoIiwKICAweDAyNmUsCiAgImxmYmxvY2siLAogIDB4MjU4YywKICAibGhvb2tyZXRyb2ZsZXgiLAogIDB4MDI2ZCwKICAibGlyYSIsCiAgMHgyMGE0LAogICJsaXduYXJtZW5pYW4iLAogIDB4MDU2YywKICAibGoiLAogIDB4MDFjOSwKICAibGplY3lyaWxsaWMiLAogIDB4MDQ1OSwKICAibGwiLAogIDB4ZjZjMCwKICAibGxhZGV2YSIsCiAgMHgwOTMzLAogICJsbGFndWphcmF0aSIsCiAgMHgwYWIzLAogICJsbGluZWJlbG93IiwKICAweDFlM2IsCiAgImxsbGFkZXZhIiwKICAweDA5MzQsCiAgImxsdm9jYWxpY2JlbmdhbGkiLAogIDB4MDllMSwKICAibGx2b2NhbGljZGV2YSIsCiAgMHgwOTYxLAogICJsbHZvY2FsaWN2b3dlbHNpZ25iZW5nYWxpIiwKICAweDA5ZTMsCiAgImxsdm9jYWxpY3Zvd2Vsc2lnbmRldmEiLAogIDB4MDk2MywKICAibG1pZGRsZXRpbGRlIiwKICAweDAyNmIsCiAgImxtb25vc3BhY2UiLAogIDB4ZmY0YywKICAibG1zcXVhcmUiLAogIDB4MzNkMCwKICAibG9jaHVsYXRoYWkiLAogIDB4MGUyYywKICAibG9naWNhbGFuZCIsCiAgMHgyMjI3LAogICJsb2dpY2Fsbm90IiwKICAweDAwYWMsCiAgImxvZ2ljYWxub3RyZXZlcnNlZCIsCiAgMHgyMzEwLAogICJsb2dpY2Fsb3IiLAogIDB4MjIyOCwKICAibG9saW5ndGhhaSIsCiAgMHgwZTI1LAogICJsb25ncyIsCiAgMHgwMTdmLAogICJsb3dsaW5lY2VudGVybGluZSIsCiAgMHhmZTRlLAogICJsb3dsaW5lY21iIiwKICAweDAzMzIsCiAgImxvd2xpbmVkYXNoZWQiLAogIDB4ZmU0ZCwKICAibG96ZW5nZSIsCiAgMHgyNWNhLAogICJscGFyZW4iLAogIDB4MjRhNywKICAibHNsYXNoIiwKICAweDAxNDIsCiAgImxzcXVhcmUiLAogIDB4MjExMywKICAibHN1cGVyaW9yIiwKICAweGY2ZWUsCiAgImx0c2hhZGUiLAogIDB4MjU5MSwKICAibHV0aGFpIiwKICAweDBlMjYsCiAgImx2b2NhbGljYmVuZ2FsaSIsCiAgMHgwOThjLAogICJsdm9jYWxpY2RldmEiLAogIDB4MDkwYywKICAibHZvY2FsaWN2b3dlbHNpZ25iZW5nYWxpIiwKICAweDA5ZTIsCiAgImx2b2NhbGljdm93ZWxzaWduZGV2YSIsCiAgMHgwOTYyLAogICJseHNxdWFyZSIsCiAgMHgzM2QzLAogICJtIiwKICAweDAwNmQsCiAgIm1hYmVuZ2FsaSIsCiAgMHgwOWFlLAogICJtYWNyb24iLAogIDB4MDBhZiwKICAibWFjcm9uYmVsb3djbWIiLAogIDB4MDMzMSwKICAibWFjcm9uY21iIiwKICAweDAzMDQsCiAgIm1hY3Jvbmxvd21vZCIsCiAgMHgwMmNkLAogICJtYWNyb25tb25vc3BhY2UiLAogIDB4ZmZlMywKICAibWFjdXRlIiwKICAweDFlM2YsCiAgIm1hZGV2YSIsCiAgMHgwOTJlLAogICJtYWd1amFyYXRpIiwKICAweDBhYWUsCiAgIm1hZ3VybXVraGkiLAogIDB4MGEyZSwKICAibWFoYXBha2hoZWJyZXciLAogIDB4MDVhNCwKICAibWFoYXBha2hsZWZ0aGVicmV3IiwKICAweDA1YTQsCiAgIm1haGlyYWdhbmEiLAogIDB4MzA3ZSwKICAibWFpY2hhdHRhd2Fsb3dsZWZ0dGhhaSIsCiAgMHhmODk1LAogICJtYWljaGF0dGF3YWxvd3JpZ2h0dGhhaSIsCiAgMHhmODk0LAogICJtYWljaGF0dGF3YXRoYWkiLAogIDB4MGU0YiwKICAibWFpY2hhdHRhd2F1cHBlcmxlZnR0aGFpIiwKICAweGY4OTMsCiAgIm1haWVrbG93bGVmdHRoYWkiLAogIDB4Zjg4YywKICAibWFpZWtsb3dyaWdodHRoYWkiLAogIDB4Zjg4YiwKICAibWFpZWt0aGFpIiwKICAweDBlNDgsCiAgIm1haWVrdXBwZXJsZWZ0dGhhaSIsCiAgMHhmODhhLAogICJtYWloYW5ha2F0bGVmdHRoYWkiLAogIDB4Zjg4NCwKICAibWFpaGFuYWthdHRoYWkiLAogIDB4MGUzMSwKICAibWFpdGFpa2h1bGVmdHRoYWkiLAogIDB4Zjg4OSwKICAibWFpdGFpa2h1dGhhaSIsCiAgMHgwZTQ3LAogICJtYWl0aG9sb3dsZWZ0dGhhaSIsCiAgMHhmODhmLAogICJtYWl0aG9sb3dyaWdodHRoYWkiLAogIDB4Zjg4ZSwKICAibWFpdGhvdGhhaSIsCiAgMHgwZTQ5LAogICJtYWl0aG91cHBlcmxlZnR0aGFpIiwKICAweGY4OGQsCiAgIm1haXRyaWxvd2xlZnR0aGFpIiwKICAweGY4OTIsCiAgIm1haXRyaWxvd3JpZ2h0dGhhaSIsCiAgMHhmODkxLAogICJtYWl0cml0aGFpIiwKICAweDBlNGEsCiAgIm1haXRyaXVwcGVybGVmdHRoYWkiLAogIDB4Zjg5MCwKICAibWFpeWFtb2t0aGFpIiwKICAweDBlNDYsCiAgIm1ha2F0YWthbmEiLAogIDB4MzBkZSwKICAibWFrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjhmLAogICJtYWxlIiwKICAweDI2NDIsCiAgIm1hbnN5b25zcXVhcmUiLAogIDB4MzM0NywKICAibWFxYWZoZWJyZXciLAogIDB4MDViZSwKICAibWFycyIsCiAgMHgyNjQyLAogICJtYXNvcmFjaXJjbGVoZWJyZXciLAogIDB4MDVhZiwKICAibWFzcXVhcmUiLAogIDB4MzM4MywKICAibWJvcG9tb2ZvIiwKICAweDMxMDcsCiAgIm1ic3F1YXJlIiwKICAweDMzZDQsCiAgIm1jaXJjbGUiLAogIDB4MjRkYywKICAibWN1YmVkc3F1YXJlIiwKICAweDMzYTUsCiAgIm1kb3RhY2NlbnQiLAogIDB4MWU0MSwKICAibWRvdGJlbG93IiwKICAweDFlNDMsCiAgIm1lZW1hcmFiaWMiLAogIDB4MDY0NSwKICAibWVlbWZpbmFsYXJhYmljIiwKICAweGZlZTIsCiAgIm1lZW1pbml0aWFsYXJhYmljIiwKICAweGZlZTMsCiAgIm1lZW1tZWRpYWxhcmFiaWMiLAogIDB4ZmVlNCwKICAibWVlbW1lZW1pbml0aWFsYXJhYmljIiwKICAweGZjZDEsCiAgIm1lZW1tZWVtaXNvbGF0ZWRhcmFiaWMiLAogIDB4ZmM0OCwKICAibWVldG9ydXNxdWFyZSIsCiAgMHgzMzRkLAogICJtZWhpcmFnYW5hIiwKICAweDMwODEsCiAgIm1laXppZXJhc3F1YXJlIiwKICAweDMzN2UsCiAgIm1la2F0YWthbmEiLAogIDB4MzBlMSwKICAibWVrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjkyLAogICJtZW0iLAogIDB4MDVkZSwKICAibWVtZGFnZXNoIiwKICAweGZiM2UsCiAgIm1lbWRhZ2VzaGhlYnJldyIsCiAgMHhmYjNlLAogICJtZW1oZWJyZXciLAogIDB4MDVkZSwKICAibWVuYXJtZW5pYW4iLAogIDB4MDU3NCwKICAibWVya2hhaGVicmV3IiwKICAweDA1YTUsCiAgIm1lcmtoYWtlZnVsYWhlYnJldyIsCiAgMHgwNWE2LAogICJtZXJraGFrZWZ1bGFsZWZ0aGVicmV3IiwKICAweDA1YTYsCiAgIm1lcmtoYWxlZnRoZWJyZXciLAogIDB4MDVhNSwKICAibWhvb2siLAogIDB4MDI3MSwKICAibWh6c3F1YXJlIiwKICAweDMzOTIsCiAgIm1pZGRsZWRvdGthdGFrYW5haGFsZndpZHRoIiwKICAweGZmNjUsCiAgIm1pZGRvdCIsCiAgMHgwMGI3LAogICJtaWV1bWFjaXJjbGVrb3JlYW4iLAogIDB4MzI3MiwKICAibWlldW1hcGFyZW5rb3JlYW4iLAogIDB4MzIxMiwKICAibWlldW1jaXJjbGVrb3JlYW4iLAogIDB4MzI2NCwKICAibWlldW1rb3JlYW4iLAogIDB4MzE0MSwKICAibWlldW1wYW5zaW9za29yZWFuIiwKICAweDMxNzAsCiAgIm1pZXVtcGFyZW5rb3JlYW4iLAogIDB4MzIwNCwKICAibWlldW1waWV1cGtvcmVhbiIsCiAgMHgzMTZlLAogICJtaWV1bXNpb3Nrb3JlYW4iLAogIDB4MzE2ZiwKICAibWloaXJhZ2FuYSIsCiAgMHgzMDdmLAogICJtaWthdGFrYW5hIiwKICAweDMwZGYsCiAgIm1pa2F0YWthbmFoYWxmd2lkdGgiLAogIDB4ZmY5MCwKICAibWludXMiLAogIDB4MjIxMiwKICAibWludXNiZWxvd2NtYiIsCiAgMHgwMzIwLAogICJtaW51c2NpcmNsZSIsCiAgMHgyMjk2LAogICJtaW51c21vZCIsCiAgMHgwMmQ3LAogICJtaW51c3BsdXMiLAogIDB4MjIxMywKICAibWludXRlIiwKICAweDIwMzIsCiAgIm1pcmliYWFydXNxdWFyZSIsCiAgMHgzMzRhLAogICJtaXJpc3F1YXJlIiwKICAweDMzNDksCiAgIm1sb25nbGVndHVybmVkIiwKICAweDAyNzAsCiAgIm1sc3F1YXJlIiwKICAweDMzOTYsCiAgIm1tY3ViZWRzcXVhcmUiLAogIDB4MzNhMywKICAibW1vbm9zcGFjZSIsCiAgMHhmZjRkLAogICJtbXNxdWFyZWRzcXVhcmUiLAogIDB4MzM5ZiwKICAibW9oaXJhZ2FuYSIsCiAgMHgzMDgyLAogICJtb2htc3F1YXJlIiwKICAweDMzYzEsCiAgIm1va2F0YWthbmEiLAogIDB4MzBlMiwKICAibW9rYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjkzLAogICJtb2xzcXVhcmUiLAogIDB4MzNkNiwKICAibW9tYXRoYWkiLAogIDB4MGUyMSwKICAibW92ZXJzc3F1YXJlIiwKICAweDMzYTcsCiAgIm1vdmVyc3NxdWFyZWRzcXVhcmUiLAogIDB4MzNhOCwKICAibXBhcmVuIiwKICAweDI0YTgsCiAgIm1wYXNxdWFyZSIsCiAgMHgzM2FiLAogICJtc3NxdWFyZSIsCiAgMHgzM2IzLAogICJtc3VwZXJpb3IiLAogIDB4ZjZlZiwKICAibXR1cm5lZCIsCiAgMHgwMjZmLAogICJtdSIsCiAgMHgwMGI1LAogICJtdTEiLAogIDB4MDBiNSwKICAibXVhc3F1YXJlIiwKICAweDMzODIsCiAgIm11Y2hncmVhdGVyIiwKICAweDIyNmIsCiAgIm11Y2hsZXNzIiwKICAweDIyNmEsCiAgIm11ZnNxdWFyZSIsCiAgMHgzMzhjLAogICJtdWdyZWVrIiwKICAweDAzYmMsCiAgIm11Z3NxdWFyZSIsCiAgMHgzMzhkLAogICJtdWhpcmFnYW5hIiwKICAweDMwODAsCiAgIm11a2F0YWthbmEiLAogIDB4MzBlMCwKICAibXVrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjkxLAogICJtdWxzcXVhcmUiLAogIDB4MzM5NSwKICAibXVsdGlwbHkiLAogIDB4MDBkNywKICAibXVtc3F1YXJlIiwKICAweDMzOWIsCiAgIm11bmFoaGVicmV3IiwKICAweDA1YTMsCiAgIm11bmFobGVmdGhlYnJldyIsCiAgMHgwNWEzLAogICJtdXNpY2Fsbm90ZSIsCiAgMHgyNjZhLAogICJtdXNpY2Fsbm90ZWRibCIsCiAgMHgyNjZiLAogICJtdXNpY2ZsYXRzaWduIiwKICAweDI2NmQsCiAgIm11c2ljc2hhcnBzaWduIiwKICAweDI2NmYsCiAgIm11c3NxdWFyZSIsCiAgMHgzM2IyLAogICJtdXZzcXVhcmUiLAogIDB4MzNiNiwKICAibXV3c3F1YXJlIiwKICAweDMzYmMsCiAgIm12bWVnYXNxdWFyZSIsCiAgMHgzM2I5LAogICJtdnNxdWFyZSIsCiAgMHgzM2I3LAogICJtd21lZ2FzcXVhcmUiLAogIDB4MzNiZiwKICAibXdzcXVhcmUiLAogIDB4MzNiZCwKICAibiIsCiAgMHgwMDZlLAogICJuYWJlbmdhbGkiLAogIDB4MDlhOCwKICAibmFibGEiLAogIDB4MjIwNywKICAibmFjdXRlIiwKICAweDAxNDQsCiAgIm5hZGV2YSIsCiAgMHgwOTI4LAogICJuYWd1amFyYXRpIiwKICAweDBhYTgsCiAgIm5hZ3VybXVraGkiLAogIDB4MGEyOCwKICAibmFoaXJhZ2FuYSIsCiAgMHgzMDZhLAogICJuYWthdGFrYW5hIiwKICAweDMwY2EsCiAgIm5ha2F0YWthbmFoYWxmd2lkdGgiLAogIDB4ZmY4NSwKICAibmFwb3N0cm9waGUiLAogIDB4MDE0OSwKICAibmFzcXVhcmUiLAogIDB4MzM4MSwKICAibmJvcG9tb2ZvIiwKICAweDMxMGIsCiAgIm5ic3BhY2UiLAogIDB4MDBhMCwKICAibmNhcm9uIiwKICAweDAxNDgsCiAgIm5jZWRpbGxhIiwKICAweDAxNDYsCiAgIm5jaXJjbGUiLAogIDB4MjRkZCwKICAibmNpcmN1bWZsZXhiZWxvdyIsCiAgMHgxZTRiLAogICJuY29tbWFhY2NlbnQiLAogIDB4MDE0NiwKICAibmRvdGFjY2VudCIsCiAgMHgxZTQ1LAogICJuZG90YmVsb3ciLAogIDB4MWU0NywKICAibmVoaXJhZ2FuYSIsCiAgMHgzMDZkLAogICJuZWthdGFrYW5hIiwKICAweDMwY2QsCiAgIm5la2F0YWthbmFoYWxmd2lkdGgiLAogIDB4ZmY4OCwKICAibmV3c2hlcWVsc2lnbiIsCiAgMHgyMGFhLAogICJuZnNxdWFyZSIsCiAgMHgzMzhiLAogICJuZ2FiZW5nYWxpIiwKICAweDA5OTksCiAgIm5nYWRldmEiLAogIDB4MDkxOSwKICAibmdhZ3VqYXJhdGkiLAogIDB4MGE5OSwKICAibmdhZ3VybXVraGkiLAogIDB4MGExOSwKICAibmdvbmd1dGhhaSIsCiAgMHgwZTA3LAogICJuaGlyYWdhbmEiLAogIDB4MzA5MywKICAibmhvb2tsZWZ0IiwKICAweDAyNzIsCiAgIm5ob29rcmV0cm9mbGV4IiwKICAweDAyNzMsCiAgIm5pZXVuYWNpcmNsZWtvcmVhbiIsCiAgMHgzMjZmLAogICJuaWV1bmFwYXJlbmtvcmVhbiIsCiAgMHgzMjBmLAogICJuaWV1bmNpZXVja29yZWFuIiwKICAweDMxMzUsCiAgIm5pZXVuY2lyY2xla29yZWFuIiwKICAweDMyNjEsCiAgIm5pZXVuaGlldWhrb3JlYW4iLAogIDB4MzEzNiwKICAibmlldW5rb3JlYW4iLAogIDB4MzEzNCwKICAibmlldW5wYW5zaW9za29yZWFuIiwKICAweDMxNjgsCiAgIm5pZXVucGFyZW5rb3JlYW4iLAogIDB4MzIwMSwKICAibmlldW5zaW9za29yZWFuIiwKICAweDMxNjcsCiAgIm5pZXVudGlrZXV0a29yZWFuIiwKICAweDMxNjYsCiAgIm5paGlyYWdhbmEiLAogIDB4MzA2YiwKICAibmlrYXRha2FuYSIsCiAgMHgzMGNiLAogICJuaWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmODYsCiAgIm5pa2hhaGl0bGVmdHRoYWkiLAogIDB4Zjg5OSwKICAibmlraGFoaXR0aGFpIiwKICAweDBlNGQsCiAgIm5pbmUiLAogIDB4MDAzOSwKICAibmluZWFyYWJpYyIsCiAgMHgwNjY5LAogICJuaW5lYmVuZ2FsaSIsCiAgMHgwOWVmLAogICJuaW5lY2lyY2xlIiwKICAweDI0NjgsCiAgIm5pbmVjaXJjbGVpbnZlcnNlc2Fuc3NlcmlmIiwKICAweDI3OTIsCiAgIm5pbmVkZXZhIiwKICAweDA5NmYsCiAgIm5pbmVndWphcmF0aSIsCiAgMHgwYWVmLAogICJuaW5lZ3VybXVraGkiLAogIDB4MGE2ZiwKICAibmluZWhhY2thcmFiaWMiLAogIDB4MDY2OSwKICAibmluZWhhbmd6aG91IiwKICAweDMwMjksCiAgIm5pbmVpZGVvZ3JhcGhpY3BhcmVuIiwKICAweDMyMjgsCiAgIm5pbmVpbmZlcmlvciIsCiAgMHgyMDg5LAogICJuaW5lbW9ub3NwYWNlIiwKICAweGZmMTksCiAgIm5pbmVvbGRzdHlsZSIsCiAgMHhmNzM5LAogICJuaW5lcGFyZW4iLAogIDB4MjQ3YywKICAibmluZXBlcmlvZCIsCiAgMHgyNDkwLAogICJuaW5lcGVyc2lhbiIsCiAgMHgwNmY5LAogICJuaW5lcm9tYW4iLAogIDB4MjE3OCwKICAibmluZXN1cGVyaW9yIiwKICAweDIwNzksCiAgIm5pbmV0ZWVuY2lyY2xlIiwKICAweDI0NzIsCiAgIm5pbmV0ZWVucGFyZW4iLAogIDB4MjQ4NiwKICAibmluZXRlZW5wZXJpb2QiLAogIDB4MjQ5YSwKICAibmluZXRoYWkiLAogIDB4MGU1OSwKICAibmoiLAogIDB4MDFjYywKICAibmplY3lyaWxsaWMiLAogIDB4MDQ1YSwKICAibmthdGFrYW5hIiwKICAweDMwZjMsCiAgIm5rYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjlkLAogICJubGVncmlnaHRsb25nIiwKICAweDAxOWUsCiAgIm5saW5lYmVsb3ciLAogIDB4MWU0OSwKICAibm1vbm9zcGFjZSIsCiAgMHhmZjRlLAogICJubXNxdWFyZSIsCiAgMHgzMzlhLAogICJubmFiZW5nYWxpIiwKICAweDA5YTMsCiAgIm5uYWRldmEiLAogIDB4MDkyMywKICAibm5hZ3VqYXJhdGkiLAogIDB4MGFhMywKICAibm5hZ3VybXVraGkiLAogIDB4MGEyMywKICAibm5uYWRldmEiLAogIDB4MDkyOSwKICAibm9oaXJhZ2FuYSIsCiAgMHgzMDZlLAogICJub2thdGFrYW5hIiwKICAweDMwY2UsCiAgIm5va2F0YWthbmFoYWxmd2lkdGgiLAogIDB4ZmY4OSwKICAibm9uYnJlYWtpbmdzcGFjZSIsCiAgMHgwMGEwLAogICJub25lbnRoYWkiLAogIDB4MGUxMywKICAibm9udXRoYWkiLAogIDB4MGUxOSwKICAibm9vbmFyYWJpYyIsCiAgMHgwNjQ2LAogICJub29uZmluYWxhcmFiaWMiLAogIDB4ZmVlNiwKICAibm9vbmdodW5uYWFyYWJpYyIsCiAgMHgwNmJhLAogICJub29uZ2h1bm5hZmluYWxhcmFiaWMiLAogIDB4ZmI5ZiwKICAibm9vbmluaXRpYWxhcmFiaWMiLAogIDB4ZmVlNywKICAibm9vbmplZW1pbml0aWFsYXJhYmljIiwKICAweGZjZDIsCiAgIm5vb25qZWVtaXNvbGF0ZWRhcmFiaWMiLAogIDB4ZmM0YiwKICAibm9vbm1lZGlhbGFyYWJpYyIsCiAgMHhmZWU4LAogICJub29ubWVlbWluaXRpYWxhcmFiaWMiLAogIDB4ZmNkNSwKICAibm9vbm1lZW1pc29sYXRlZGFyYWJpYyIsCiAgMHhmYzRlLAogICJub29ubm9vbmZpbmFsYXJhYmljIiwKICAweGZjOGQsCiAgIm5vdGNvbnRhaW5zIiwKICAweDIyMGMsCiAgIm5vdGVsZW1lbnQiLAogIDB4MjIwOSwKICAibm90ZWxlbWVudG9mIiwKICAweDIyMDksCiAgIm5vdGVxdWFsIiwKICAweDIyNjAsCiAgIm5vdGdyZWF0ZXIiLAogIDB4MjI2ZiwKICAibm90Z3JlYXRlcm5vcmVxdWFsIiwKICAweDIyNzEsCiAgIm5vdGdyZWF0ZXJub3JsZXNzIiwKICAweDIyNzksCiAgIm5vdGlkZW50aWNhbCIsCiAgMHgyMjYyLAogICJub3RsZXNzIiwKICAweDIyNmUsCiAgIm5vdGxlc3Nub3JlcXVhbCIsCiAgMHgyMjcwLAogICJub3RwYXJhbGxlbCIsCiAgMHgyMjI2LAogICJub3RwcmVjZWRlcyIsCiAgMHgyMjgwLAogICJub3RzdWJzZXQiLAogIDB4MjI4NCwKICAibm90c3VjY2VlZHMiLAogIDB4MjI4MSwKICAibm90c3VwZXJzZXQiLAogIDB4MjI4NSwKICAibm93YXJtZW5pYW4iLAogIDB4MDU3NiwKICAibnBhcmVuIiwKICAweDI0YTksCiAgIm5zc3F1YXJlIiwKICAweDMzYjEsCiAgIm5zdXBlcmlvciIsCiAgMHgyMDdmLAogICJudGlsZGUiLAogIDB4MDBmMSwKICAibnUiLAogIDB4MDNiZCwKICAibnVoaXJhZ2FuYSIsCiAgMHgzMDZjLAogICJudWthdGFrYW5hIiwKICAweDMwY2MsCiAgIm51a2F0YWthbmFoYWxmd2lkdGgiLAogIDB4ZmY4NywKICAibnVrdGFiZW5nYWxpIiwKICAweDA5YmMsCiAgIm51a3RhZGV2YSIsCiAgMHgwOTNjLAogICJudWt0YWd1amFyYXRpIiwKICAweDBhYmMsCiAgIm51a3RhZ3VybXVraGkiLAogIDB4MGEzYywKICAibnVtYmVyc2lnbiIsCiAgMHgwMDIzLAogICJudW1iZXJzaWdubW9ub3NwYWNlIiwKICAweGZmMDMsCiAgIm51bWJlcnNpZ25zbWFsbCIsCiAgMHhmZTVmLAogICJudW1lcmFsc2lnbmdyZWVrIiwKICAweDAzNzQsCiAgIm51bWVyYWxzaWdubG93ZXJncmVlayIsCiAgMHgwMzc1LAogICJudW1lcm8iLAogIDB4MjExNiwKICAibnVuIiwKICAweDA1ZTAsCiAgIm51bmRhZ2VzaCIsCiAgMHhmYjQwLAogICJudW5kYWdlc2hoZWJyZXciLAogIDB4ZmI0MCwKICAibnVuaGVicmV3IiwKICAweDA1ZTAsCiAgIm52c3F1YXJlIiwKICAweDMzYjUsCiAgIm53c3F1YXJlIiwKICAweDMzYmIsCiAgIm55YWJlbmdhbGkiLAogIDB4MDk5ZSwKICAibnlhZGV2YSIsCiAgMHgwOTFlLAogICJueWFndWphcmF0aSIsCiAgMHgwYTllLAogICJueWFndXJtdWtoaSIsCiAgMHgwYTFlLAogICJvIiwKICAweDAwNmYsCiAgIm9hY3V0ZSIsCiAgMHgwMGYzLAogICJvYW5ndGhhaSIsCiAgMHgwZTJkLAogICJvYmFycmVkIiwKICAweDAyNzUsCiAgIm9iYXJyZWRjeXJpbGxpYyIsCiAgMHgwNGU5LAogICJvYmFycmVkZGllcmVzaXNjeXJpbGxpYyIsCiAgMHgwNGViLAogICJvYmVuZ2FsaSIsCiAgMHgwOTkzLAogICJvYm9wb21vZm8iLAogIDB4MzExYiwKICAib2JyZXZlIiwKICAweDAxNGYsCiAgIm9jYW5kcmFkZXZhIiwKICAweDA5MTEsCiAgIm9jYW5kcmFndWphcmF0aSIsCiAgMHgwYTkxLAogICJvY2FuZHJhdm93ZWxzaWduZGV2YSIsCiAgMHgwOTQ5LAogICJvY2FuZHJhdm93ZWxzaWduZ3VqYXJhdGkiLAogIDB4MGFjOSwKICAib2Nhcm9uIiwKICAweDAxZDIsCiAgIm9jaXJjbGUiLAogIDB4MjRkZSwKICAib2NpcmN1bWZsZXgiLAogIDB4MDBmNCwKICAib2NpcmN1bWZsZXhhY3V0ZSIsCiAgMHgxZWQxLAogICJvY2lyY3VtZmxleGRvdGJlbG93IiwKICAweDFlZDksCiAgIm9jaXJjdW1mbGV4Z3JhdmUiLAogIDB4MWVkMywKICAib2NpcmN1bWZsZXhob29rYWJvdmUiLAogIDB4MWVkNSwKICAib2NpcmN1bWZsZXh0aWxkZSIsCiAgMHgxZWQ3LAogICJvY3lyaWxsaWMiLAogIDB4MDQzZSwKICAib2RibGFjdXRlIiwKICAweDAxNTEsCiAgIm9kYmxncmF2ZSIsCiAgMHgwMjBkLAogICJvZGV2YSIsCiAgMHgwOTEzLAogICJvZGllcmVzaXMiLAogIDB4MDBmNiwKICAib2RpZXJlc2lzY3lyaWxsaWMiLAogIDB4MDRlNywKICAib2RvdGJlbG93IiwKICAweDFlY2QsCiAgIm9lIiwKICAweDAxNTMsCiAgIm9la29yZWFuIiwKICAweDMxNWEsCiAgIm9nb25layIsCiAgMHgwMmRiLAogICJvZ29uZWtjbWIiLAogIDB4MDMyOCwKICAib2dyYXZlIiwKICAweDAwZjIsCiAgIm9ndWphcmF0aSIsCiAgMHgwYTkzLAogICJvaGFybWVuaWFuIiwKICAweDA1ODUsCiAgIm9oaXJhZ2FuYSIsCiAgMHgzMDRhLAogICJvaG9va2Fib3ZlIiwKICAweDFlY2YsCiAgIm9ob3JuIiwKICAweDAxYTEsCiAgIm9ob3JuYWN1dGUiLAogIDB4MWVkYiwKICAib2hvcm5kb3RiZWxvdyIsCiAgMHgxZWUzLAogICJvaG9ybmdyYXZlIiwKICAweDFlZGQsCiAgIm9ob3JuaG9va2Fib3ZlIiwKICAweDFlZGYsCiAgIm9ob3JudGlsZGUiLAogIDB4MWVlMSwKICAib2h1bmdhcnVtbGF1dCIsCiAgMHgwMTUxLAogICJvaSIsCiAgMHgwMWEzLAogICJvaW52ZXJ0ZWRicmV2ZSIsCiAgMHgwMjBmLAogICJva2F0YWthbmEiLAogIDB4MzBhYSwKICAib2thdGFrYW5haGFsZndpZHRoIiwKICAweGZmNzUsCiAgIm9rb3JlYW4iLAogIDB4MzE1NywKICAib2xlaGVicmV3IiwKICAweDA1YWIsCiAgIm9tYWNyb24iLAogIDB4MDE0ZCwKICAib21hY3JvbmFjdXRlIiwKICAweDFlNTMsCiAgIm9tYWNyb25ncmF2ZSIsCiAgMHgxZTUxLAogICJvbWRldmEiLAogIDB4MDk1MCwKICAib21lZ2EiLAogIDB4MDNjOSwKICAib21lZ2ExIiwKICAweDAzZDYsCiAgIm9tZWdhY3lyaWxsaWMiLAogIDB4MDQ2MSwKICAib21lZ2FsYXRpbmNsb3NlZCIsCiAgMHgwMjc3LAogICJvbWVnYXJvdW5kY3lyaWxsaWMiLAogIDB4MDQ3YiwKICAib21lZ2F0aXRsb2N5cmlsbGljIiwKICAweDA0N2QsCiAgIm9tZWdhdG9ub3MiLAogIDB4MDNjZSwKICAib21ndWphcmF0aSIsCiAgMHgwYWQwLAogICJvbWljcm9uIiwKICAweDAzYmYsCiAgIm9taWNyb250b25vcyIsCiAgMHgwM2NjLAogICJvbW9ub3NwYWNlIiwKICAweGZmNGYsCiAgIm9uZSIsCiAgMHgwMDMxLAogICJvbmVhcmFiaWMiLAogIDB4MDY2MSwKICAib25lYmVuZ2FsaSIsCiAgMHgwOWU3LAogICJvbmVjaXJjbGUiLAogIDB4MjQ2MCwKICAib25lY2lyY2xlaW52ZXJzZXNhbnNzZXJpZiIsCiAgMHgyNzhhLAogICJvbmVkZXZhIiwKICAweDA5NjcsCiAgIm9uZWRvdGVubGVhZGVyIiwKICAweDIwMjQsCiAgIm9uZWVpZ2h0aCIsCiAgMHgyMTViLAogICJvbmVmaXR0ZWQiLAogIDB4ZjZkYywKICAib25lZ3VqYXJhdGkiLAogIDB4MGFlNywKICAib25lZ3VybXVraGkiLAogIDB4MGE2NywKICAib25laGFja2FyYWJpYyIsCiAgMHgwNjYxLAogICJvbmVoYWxmIiwKICAweDAwYmQsCiAgIm9uZWhhbmd6aG91IiwKICAweDMwMjEsCiAgIm9uZWlkZW9ncmFwaGljcGFyZW4iLAogIDB4MzIyMCwKICAib25laW5mZXJpb3IiLAogIDB4MjA4MSwKICAib25lbW9ub3NwYWNlIiwKICAweGZmMTEsCiAgIm9uZW51bWVyYXRvcmJlbmdhbGkiLAogIDB4MDlmNCwKICAib25lb2xkc3R5bGUiLAogIDB4ZjczMSwKICAib25lcGFyZW4iLAogIDB4MjQ3NCwKICAib25lcGVyaW9kIiwKICAweDI0ODgsCiAgIm9uZXBlcnNpYW4iLAogIDB4MDZmMSwKICAib25lcXVhcnRlciIsCiAgMHgwMGJjLAogICJvbmVyb21hbiIsCiAgMHgyMTcwLAogICJvbmVzdXBlcmlvciIsCiAgMHgwMGI5LAogICJvbmV0aGFpIiwKICAweDBlNTEsCiAgIm9uZXRoaXJkIiwKICAweDIxNTMsCiAgIm9vZ29uZWsiLAogIDB4MDFlYiwKICAib29nb25la21hY3JvbiIsCiAgMHgwMWVkLAogICJvb2d1cm11a2hpIiwKICAweDBhMTMsCiAgIm9vbWF0cmFndXJtdWtoaSIsCiAgMHgwYTRiLAogICJvb3BlbiIsCiAgMHgwMjU0LAogICJvcGFyZW4iLAogIDB4MjRhYSwKICAib3BlbmJ1bGxldCIsCiAgMHgyNWU2LAogICJvcHRpb24iLAogIDB4MjMyNSwKICAib3JkZmVtaW5pbmUiLAogIDB4MDBhYSwKICAib3JkbWFzY3VsaW5lIiwKICAweDAwYmEsCiAgIm9ydGhvZ29uYWwiLAogIDB4MjIxZiwKICAib3Nob3J0ZGV2YSIsCiAgMHgwOTEyLAogICJvc2hvcnR2b3dlbHNpZ25kZXZhIiwKICAweDA5NGEsCiAgIm9zbGFzaCIsCiAgMHgwMGY4LAogICJvc2xhc2hhY3V0ZSIsCiAgMHgwMWZmLAogICJvc21hbGxoaXJhZ2FuYSIsCiAgMHgzMDQ5LAogICJvc21hbGxrYXRha2FuYSIsCiAgMHgzMGE5LAogICJvc21hbGxrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjZiLAogICJvc3Ryb2tlYWN1dGUiLAogIDB4MDFmZiwKICAib3N1cGVyaW9yIiwKICAweGY2ZjAsCiAgIm90Y3lyaWxsaWMiLAogIDB4MDQ3ZiwKICAib3RpbGRlIiwKICAweDAwZjUsCiAgIm90aWxkZWFjdXRlIiwKICAweDFlNGQsCiAgIm90aWxkZWRpZXJlc2lzIiwKICAweDFlNGYsCiAgIm91Ym9wb21vZm8iLAogIDB4MzEyMSwKICAib3ZlcmxpbmUiLAogIDB4MjAzZSwKICAib3ZlcmxpbmVjZW50ZXJsaW5lIiwKICAweGZlNGEsCiAgIm92ZXJsaW5lY21iIiwKICAweDAzMDUsCiAgIm92ZXJsaW5lZGFzaGVkIiwKICAweGZlNDksCiAgIm92ZXJsaW5lZGJsd2F2eSIsCiAgMHhmZTRjLAogICJvdmVybGluZXdhdnkiLAogIDB4ZmU0YiwKICAib3ZlcnNjb3JlIiwKICAweDAwYWYsCiAgIm92b3dlbHNpZ25iZW5nYWxpIiwKICAweDA5Y2IsCiAgIm92b3dlbHNpZ25kZXZhIiwKICAweDA5NGIsCiAgIm92b3dlbHNpZ25ndWphcmF0aSIsCiAgMHgwYWNiLAogICJwIiwKICAweDAwNzAsCiAgInBhYW1wc3NxdWFyZSIsCiAgMHgzMzgwLAogICJwYWFzZW50b3NxdWFyZSIsCiAgMHgzMzJiLAogICJwYWJlbmdhbGkiLAogIDB4MDlhYSwKICAicGFjdXRlIiwKICAweDFlNTUsCiAgInBhZGV2YSIsCiAgMHgwOTJhLAogICJwYWdlZG93biIsCiAgMHgyMWRmLAogICJwYWdldXAiLAogIDB4MjFkZSwKICAicGFndWphcmF0aSIsCiAgMHgwYWFhLAogICJwYWd1cm11a2hpIiwKICAweDBhMmEsCiAgInBhaGlyYWdhbmEiLAogIDB4MzA3MSwKICAicGFpeWFubm9pdGhhaSIsCiAgMHgwZTJmLAogICJwYWthdGFrYW5hIiwKICAweDMwZDEsCiAgInBhbGF0YWxpemF0aW9uY3lyaWxsaWNjbWIiLAogIDB4MDQ4NCwKICAicGFsb2Noa2FjeXJpbGxpYyIsCiAgMHgwNGMwLAogICJwYW5zaW9za29yZWFuIiwKICAweDMxN2YsCiAgInBhcmFncmFwaCIsCiAgMHgwMGI2LAogICJwYXJhbGxlbCIsCiAgMHgyMjI1LAogICJwYXJlbmxlZnQiLAogIDB4MDAyOCwKICAicGFyZW5sZWZ0YWx0b25lYXJhYmljIiwKICAweGZkM2UsCiAgInBhcmVubGVmdGJ0IiwKICAweGY4ZWQsCiAgInBhcmVubGVmdGV4IiwKICAweGY4ZWMsCiAgInBhcmVubGVmdGluZmVyaW9yIiwKICAweDIwOGQsCiAgInBhcmVubGVmdG1vbm9zcGFjZSIsCiAgMHhmZjA4LAogICJwYXJlbmxlZnRzbWFsbCIsCiAgMHhmZTU5LAogICJwYXJlbmxlZnRzdXBlcmlvciIsCiAgMHgyMDdkLAogICJwYXJlbmxlZnR0cCIsCiAgMHhmOGViLAogICJwYXJlbmxlZnR2ZXJ0aWNhbCIsCiAgMHhmZTM1LAogICJwYXJlbnJpZ2h0IiwKICAweDAwMjksCiAgInBhcmVucmlnaHRhbHRvbmVhcmFiaWMiLAogIDB4ZmQzZiwKICAicGFyZW5yaWdodGJ0IiwKICAweGY4ZjgsCiAgInBhcmVucmlnaHRleCIsCiAgMHhmOGY3LAogICJwYXJlbnJpZ2h0aW5mZXJpb3IiLAogIDB4MjA4ZSwKICAicGFyZW5yaWdodG1vbm9zcGFjZSIsCiAgMHhmZjA5LAogICJwYXJlbnJpZ2h0c21hbGwiLAogIDB4ZmU1YSwKICAicGFyZW5yaWdodHN1cGVyaW9yIiwKICAweDIwN2UsCiAgInBhcmVucmlnaHR0cCIsCiAgMHhmOGY2LAogICJwYXJlbnJpZ2h0dmVydGljYWwiLAogIDB4ZmUzNiwKICAicGFydGlhbGRpZmYiLAogIDB4MjIwMiwKICAicGFzZXFoZWJyZXciLAogIDB4MDVjMCwKICAicGFzaHRhaGVicmV3IiwKICAweDA1OTksCiAgInBhc3F1YXJlIiwKICAweDMzYTksCiAgInBhdGFoIiwKICAweDA1YjcsCiAgInBhdGFoMTEiLAogIDB4MDViNywKICAicGF0YWgxZCIsCiAgMHgwNWI3LAogICJwYXRhaDJhIiwKICAweDA1YjcsCiAgInBhdGFoaGVicmV3IiwKICAweDA1YjcsCiAgInBhdGFobmFycm93aGVicmV3IiwKICAweDA1YjcsCiAgInBhdGFocXVhcnRlcmhlYnJldyIsCiAgMHgwNWI3LAogICJwYXRhaHdpZGVoZWJyZXciLAogIDB4MDViNywKICAicGF6ZXJoZWJyZXciLAogIDB4MDVhMSwKICAicGJvcG9tb2ZvIiwKICAweDMxMDYsCiAgInBjaXJjbGUiLAogIDB4MjRkZiwKICAicGRvdGFjY2VudCIsCiAgMHgxZTU3LAogICJwZSIsCiAgMHgwNWU0LAogICJwZWN5cmlsbGljIiwKICAweDA0M2YsCiAgInBlZGFnZXNoIiwKICAweGZiNDQsCiAgInBlZGFnZXNoaGVicmV3IiwKICAweGZiNDQsCiAgInBlZXppc3F1YXJlIiwKICAweDMzM2IsCiAgInBlZmluYWxkYWdlc2hoZWJyZXciLAogIDB4ZmI0MywKICAicGVoYXJhYmljIiwKICAweDA2N2UsCiAgInBlaGFybWVuaWFuIiwKICAweDA1N2EsCiAgInBlaGVicmV3IiwKICAweDA1ZTQsCiAgInBlaGZpbmFsYXJhYmljIiwKICAweGZiNTcsCiAgInBlaGluaXRpYWxhcmFiaWMiLAogIDB4ZmI1OCwKICAicGVoaXJhZ2FuYSIsCiAgMHgzMDdhLAogICJwZWhtZWRpYWxhcmFiaWMiLAogIDB4ZmI1OSwKICAicGVrYXRha2FuYSIsCiAgMHgzMGRhLAogICJwZW1pZGRsZWhvb2tjeXJpbGxpYyIsCiAgMHgwNGE3LAogICJwZXJhZmVoZWJyZXciLAogIDB4ZmI0ZSwKICAicGVyY2VudCIsCiAgMHgwMDI1LAogICJwZXJjZW50YXJhYmljIiwKICAweDA2NmEsCiAgInBlcmNlbnRtb25vc3BhY2UiLAogIDB4ZmYwNSwKICAicGVyY2VudHNtYWxsIiwKICAweGZlNmEsCiAgInBlcmlvZCIsCiAgMHgwMDJlLAogICJwZXJpb2Rhcm1lbmlhbiIsCiAgMHgwNTg5LAogICJwZXJpb2RjZW50ZXJlZCIsCiAgMHgwMGI3LAogICJwZXJpb2RoYWxmd2lkdGgiLAogIDB4ZmY2MSwKICAicGVyaW9kaW5mZXJpb3IiLAogIDB4ZjZlNywKICAicGVyaW9kbW9ub3NwYWNlIiwKICAweGZmMGUsCiAgInBlcmlvZHNtYWxsIiwKICAweGZlNTIsCiAgInBlcmlvZHN1cGVyaW9yIiwKICAweGY2ZTgsCiAgInBlcmlzcG9tZW5pZ3JlZWtjbWIiLAogIDB4MDM0MiwKICAicGVycGVuZGljdWxhciIsCiAgMHgyMmE1LAogICJwZXJ0aG91c2FuZCIsCiAgMHgyMDMwLAogICJwZXNldGEiLAogIDB4MjBhNywKICAicGZzcXVhcmUiLAogIDB4MzM4YSwKICAicGhhYmVuZ2FsaSIsCiAgMHgwOWFiLAogICJwaGFkZXZhIiwKICAweDA5MmIsCiAgInBoYWd1amFyYXRpIiwKICAweDBhYWIsCiAgInBoYWd1cm11a2hpIiwKICAweDBhMmIsCiAgInBoaSIsCiAgMHgwM2M2LAogICJwaGkxIiwKICAweDAzZDUsCiAgInBoaWV1cGhhY2lyY2xla29yZWFuIiwKICAweDMyN2EsCiAgInBoaWV1cGhhcGFyZW5rb3JlYW4iLAogIDB4MzIxYSwKICAicGhpZXVwaGNpcmNsZWtvcmVhbiIsCiAgMHgzMjZjLAogICJwaGlldXBoa29yZWFuIiwKICAweDMxNGQsCiAgInBoaWV1cGhwYXJlbmtvcmVhbiIsCiAgMHgzMjBjLAogICJwaGlsYXRpbiIsCiAgMHgwMjc4LAogICJwaGludGh1dGhhaSIsCiAgMHgwZTNhLAogICJwaGlzeW1ib2xncmVlayIsCiAgMHgwM2Q1LAogICJwaG9vayIsCiAgMHgwMWE1LAogICJwaG9waGFudGhhaSIsCiAgMHgwZTFlLAogICJwaG9waHVuZ3RoYWkiLAogIDB4MGUxYywKICAicGhvc2FtcGhhb3RoYWkiLAogIDB4MGUyMCwKICAicGkiLAogIDB4MDNjMCwKICAicGlldXBhY2lyY2xla29yZWFuIiwKICAweDMyNzMsCiAgInBpZXVwYXBhcmVua29yZWFuIiwKICAweDMyMTMsCiAgInBpZXVwY2lldWNrb3JlYW4iLAogIDB4MzE3NiwKICAicGlldXBjaXJjbGVrb3JlYW4iLAogIDB4MzI2NSwKICAicGlldXBraXllb2trb3JlYW4iLAogIDB4MzE3MiwKICAicGlldXBrb3JlYW4iLAogIDB4MzE0MiwKICAicGlldXBwYXJlbmtvcmVhbiIsCiAgMHgzMjA1LAogICJwaWV1cHNpb3NraXllb2trb3JlYW4iLAogIDB4MzE3NCwKICAicGlldXBzaW9za29yZWFuIiwKICAweDMxNDQsCiAgInBpZXVwc2lvc3Rpa2V1dGtvcmVhbiIsCiAgMHgzMTc1LAogICJwaWV1cHRoaWV1dGhrb3JlYW4iLAogIDB4MzE3NywKICAicGlldXB0aWtldXRrb3JlYW4iLAogIDB4MzE3MywKICAicGloaXJhZ2FuYSIsCiAgMHgzMDc0LAogICJwaWthdGFrYW5hIiwKICAweDMwZDQsCiAgInBpc3ltYm9sZ3JlZWsiLAogIDB4MDNkNiwKICAicGl3cmFybWVuaWFuIiwKICAweDA1ODMsCiAgInBsdXMiLAogIDB4MDAyYiwKICAicGx1c2JlbG93Y21iIiwKICAweDAzMWYsCiAgInBsdXNjaXJjbGUiLAogIDB4MjI5NSwKICAicGx1c21pbnVzIiwKICAweDAwYjEsCiAgInBsdXNtb2QiLAogIDB4MDJkNiwKICAicGx1c21vbm9zcGFjZSIsCiAgMHhmZjBiLAogICJwbHVzc21hbGwiLAogIDB4ZmU2MiwKICAicGx1c3N1cGVyaW9yIiwKICAweDIwN2EsCiAgInBtb25vc3BhY2UiLAogIDB4ZmY1MCwKICAicG1zcXVhcmUiLAogIDB4MzNkOCwKICAicG9oaXJhZ2FuYSIsCiAgMHgzMDdkLAogICJwb2ludGluZ2luZGV4ZG93bndoaXRlIiwKICAweDI2MWYsCiAgInBvaW50aW5naW5kZXhsZWZ0d2hpdGUiLAogIDB4MjYxYywKICAicG9pbnRpbmdpbmRleHJpZ2h0d2hpdGUiLAogIDB4MjYxZSwKICAicG9pbnRpbmdpbmRleHVwd2hpdGUiLAogIDB4MjYxZCwKICAicG9rYXRha2FuYSIsCiAgMHgzMGRkLAogICJwb3BsYXRoYWkiLAogIDB4MGUxYiwKICAicG9zdGFsbWFyayIsCiAgMHgzMDEyLAogICJwb3N0YWxtYXJrZmFjZSIsCiAgMHgzMDIwLAogICJwcGFyZW4iLAogIDB4MjRhYiwKICAicHJlY2VkZXMiLAogIDB4MjI3YSwKICAicHJlc2NyaXB0aW9uIiwKICAweDIxMWUsCiAgInByaW1lbW9kIiwKICAweDAyYjksCiAgInByaW1lcmV2ZXJzZWQiLAogIDB4MjAzNSwKICAicHJvZHVjdCIsCiAgMHgyMjBmLAogICJwcm9qZWN0aXZlIiwKICAweDIzMDUsCiAgInByb2xvbmdlZGthbmEiLAogIDB4MzBmYywKICAicHJvcGVsbG9yIiwKICAweDIzMTgsCiAgInByb3BlcnN1YnNldCIsCiAgMHgyMjgyLAogICJwcm9wZXJzdXBlcnNldCIsCiAgMHgyMjgzLAogICJwcm9wb3J0aW9uIiwKICAweDIyMzcsCiAgInByb3BvcnRpb25hbCIsCiAgMHgyMjFkLAogICJwc2kiLAogIDB4MDNjOCwKICAicHNpY3lyaWxsaWMiLAogIDB4MDQ3MSwKICAicHNpbGlwbmV1bWF0YWN5cmlsbGljY21iIiwKICAweDA0ODYsCiAgInBzc3F1YXJlIiwKICAweDMzYjAsCiAgInB1aGlyYWdhbmEiLAogIDB4MzA3NywKICAicHVrYXRha2FuYSIsCiAgMHgzMGQ3LAogICJwdnNxdWFyZSIsCiAgMHgzM2I0LAogICJwd3NxdWFyZSIsCiAgMHgzM2JhLAogICJxIiwKICAweDAwNzEsCiAgInFhZGV2YSIsCiAgMHgwOTU4LAogICJxYWRtYWhlYnJldyIsCiAgMHgwNWE4LAogICJxYWZhcmFiaWMiLAogIDB4MDY0MiwKICAicWFmZmluYWxhcmFiaWMiLAogIDB4ZmVkNiwKICAicWFmaW5pdGlhbGFyYWJpYyIsCiAgMHhmZWQ3LAogICJxYWZtZWRpYWxhcmFiaWMiLAogIDB4ZmVkOCwKICAicWFtYXRzIiwKICAweDA1YjgsCiAgInFhbWF0czEwIiwKICAweDA1YjgsCiAgInFhbWF0czFhIiwKICAweDA1YjgsCiAgInFhbWF0czFjIiwKICAweDA1YjgsCiAgInFhbWF0czI3IiwKICAweDA1YjgsCiAgInFhbWF0czI5IiwKICAweDA1YjgsCiAgInFhbWF0czMzIiwKICAweDA1YjgsCiAgInFhbWF0c2RlIiwKICAweDA1YjgsCiAgInFhbWF0c2hlYnJldyIsCiAgMHgwNWI4LAogICJxYW1hdHNuYXJyb3doZWJyZXciLAogIDB4MDViOCwKICAicWFtYXRzcWF0YW5oZWJyZXciLAogIDB4MDViOCwKICAicWFtYXRzcWF0YW5uYXJyb3doZWJyZXciLAogIDB4MDViOCwKICAicWFtYXRzcWF0YW5xdWFydGVyaGVicmV3IiwKICAweDA1YjgsCiAgInFhbWF0c3FhdGFud2lkZWhlYnJldyIsCiAgMHgwNWI4LAogICJxYW1hdHNxdWFydGVyaGVicmV3IiwKICAweDA1YjgsCiAgInFhbWF0c3dpZGVoZWJyZXciLAogIDB4MDViOCwKICAicWFybmV5cGFyYWhlYnJldyIsCiAgMHgwNTlmLAogICJxYm9wb21vZm8iLAogIDB4MzExMSwKICAicWNpcmNsZSIsCiAgMHgyNGUwLAogICJxaG9vayIsCiAgMHgwMmEwLAogICJxbW9ub3NwYWNlIiwKICAweGZmNTEsCiAgInFvZiIsCiAgMHgwNWU3LAogICJxb2ZkYWdlc2giLAogIDB4ZmI0NywKICAicW9mZGFnZXNoaGVicmV3IiwKICAweGZiNDcsCiAgInFvZmhlYnJldyIsCiAgMHgwNWU3LAogICJxcGFyZW4iLAogIDB4MjRhYywKICAicXVhcnRlcm5vdGUiLAogIDB4MjY2OSwKICAicXVidXRzIiwKICAweDA1YmIsCiAgInF1YnV0czE4IiwKICAweDA1YmIsCiAgInF1YnV0czI1IiwKICAweDA1YmIsCiAgInF1YnV0czMxIiwKICAweDA1YmIsCiAgInF1YnV0c2hlYnJldyIsCiAgMHgwNWJiLAogICJxdWJ1dHNuYXJyb3doZWJyZXciLAogIDB4MDViYiwKICAicXVidXRzcXVhcnRlcmhlYnJldyIsCiAgMHgwNWJiLAogICJxdWJ1dHN3aWRlaGVicmV3IiwKICAweDA1YmIsCiAgInF1ZXN0aW9uIiwKICAweDAwM2YsCiAgInF1ZXN0aW9uYXJhYmljIiwKICAweDA2MWYsCiAgInF1ZXN0aW9uYXJtZW5pYW4iLAogIDB4MDU1ZSwKICAicXVlc3Rpb25kb3duIiwKICAweDAwYmYsCiAgInF1ZXN0aW9uZG93bnNtYWxsIiwKICAweGY3YmYsCiAgInF1ZXN0aW9uZ3JlZWsiLAogIDB4MDM3ZSwKICAicXVlc3Rpb25tb25vc3BhY2UiLAogIDB4ZmYxZiwKICAicXVlc3Rpb25zbWFsbCIsCiAgMHhmNzNmLAogICJxdW90ZWRibCIsCiAgMHgwMDIyLAogICJxdW90ZWRibGJhc2UiLAogIDB4MjAxZSwKICAicXVvdGVkYmxsZWZ0IiwKICAweDIwMWMsCiAgInF1b3RlZGJsbW9ub3NwYWNlIiwKICAweGZmMDIsCiAgInF1b3RlZGJscHJpbWUiLAogIDB4MzAxZSwKICAicXVvdGVkYmxwcmltZXJldmVyc2VkIiwKICAweDMwMWQsCiAgInF1b3RlZGJscmlnaHQiLAogIDB4MjAxZCwKICAicXVvdGVsZWZ0IiwKICAweDIwMTgsCiAgInF1b3RlbGVmdHJldmVyc2VkIiwKICAweDIwMWIsCiAgInF1b3RlcmV2ZXJzZWQiLAogIDB4MjAxYiwKICAicXVvdGVyaWdodCIsCiAgMHgyMDE5LAogICJxdW90ZXJpZ2h0biIsCiAgMHgwMTQ5LAogICJxdW90ZXNpbmdsYmFzZSIsCiAgMHgyMDFhLAogICJxdW90ZXNpbmdsZSIsCiAgMHgwMDI3LAogICJxdW90ZXNpbmdsZW1vbm9zcGFjZSIsCiAgMHhmZjA3LAogICJyIiwKICAweDAwNzIsCiAgInJhYXJtZW5pYW4iLAogIDB4MDU3YywKICAicmFiZW5nYWxpIiwKICAweDA5YjAsCiAgInJhY3V0ZSIsCiAgMHgwMTU1LAogICJyYWRldmEiLAogIDB4MDkzMCwKICAicmFkaWNhbCIsCiAgMHgyMjFhLAogICJyYWRpY2FsZXgiLAogIDB4ZjhlNSwKICAicmFkb3ZlcnNzcXVhcmUiLAogIDB4MzNhZSwKICAicmFkb3ZlcnNzcXVhcmVkc3F1YXJlIiwKICAweDMzYWYsCiAgInJhZHNxdWFyZSIsCiAgMHgzM2FkLAogICJyYWZlIiwKICAweDA1YmYsCiAgInJhZmVoZWJyZXciLAogIDB4MDViZiwKICAicmFndWphcmF0aSIsCiAgMHgwYWIwLAogICJyYWd1cm11a2hpIiwKICAweDBhMzAsCiAgInJhaGlyYWdhbmEiLAogIDB4MzA4OSwKICAicmFrYXRha2FuYSIsCiAgMHgzMGU5LAogICJyYWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmOTcsCiAgInJhbG93ZXJkaWFnb25hbGJlbmdhbGkiLAogIDB4MDlmMSwKICAicmFtaWRkbGVkaWFnb25hbGJlbmdhbGkiLAogIDB4MDlmMCwKICAicmFtc2hvcm4iLAogIDB4MDI2NCwKICAicmF0aW8iLAogIDB4MjIzNiwKICAicmJvcG9tb2ZvIiwKICAweDMxMTYsCiAgInJjYXJvbiIsCiAgMHgwMTU5LAogICJyY2VkaWxsYSIsCiAgMHgwMTU3LAogICJyY2lyY2xlIiwKICAweDI0ZTEsCiAgInJjb21tYWFjY2VudCIsCiAgMHgwMTU3LAogICJyZGJsZ3JhdmUiLAogIDB4MDIxMSwKICAicmRvdGFjY2VudCIsCiAgMHgxZTU5LAogICJyZG90YmVsb3ciLAogIDB4MWU1YiwKICAicmRvdGJlbG93bWFjcm9uIiwKICAweDFlNWQsCiAgInJlZmVyZW5jZW1hcmsiLAogIDB4MjAzYiwKICAicmVmbGV4c3Vic2V0IiwKICAweDIyODYsCiAgInJlZmxleHN1cGVyc2V0IiwKICAweDIyODcsCiAgInJlZ2lzdGVyZWQiLAogIDB4MDBhZSwKICAicmVnaXN0ZXJzYW5zIiwKICAweGY4ZTgsCiAgInJlZ2lzdGVyc2VyaWYiLAogIDB4ZjZkYSwKICAicmVoYXJhYmljIiwKICAweDA2MzEsCiAgInJlaGFybWVuaWFuIiwKICAweDA1ODAsCiAgInJlaGZpbmFsYXJhYmljIiwKICAweGZlYWUsCiAgInJlaGlyYWdhbmEiLAogIDB4MzA4YywKICAicmVrYXRha2FuYSIsCiAgMHgzMGVjLAogICJyZWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmOWEsCiAgInJlc2giLAogIDB4MDVlOCwKICAicmVzaGRhZ2VzaGhlYnJldyIsCiAgMHhmYjQ4LAogICJyZXNoaGVicmV3IiwKICAweDA1ZTgsCiAgInJldmVyc2VkdGlsZGUiLAogIDB4MjIzZCwKICAicmV2aWFoZWJyZXciLAogIDB4MDU5NywKICAicmV2aWFtdWdyYXNoaGVicmV3IiwKICAweDA1OTcsCiAgInJldmxvZ2ljYWxub3QiLAogIDB4MjMxMCwKICAicmZpc2hob29rIiwKICAweDAyN2UsCiAgInJmaXNoaG9va3JldmVyc2VkIiwKICAweDAyN2YsCiAgInJoYWJlbmdhbGkiLAogIDB4MDlkZCwKICAicmhhZGV2YSIsCiAgMHgwOTVkLAogICJyaG8iLAogIDB4MDNjMSwKICAicmhvb2siLAogIDB4MDI3ZCwKICAicmhvb2t0dXJuZWQiLAogIDB4MDI3YiwKICAicmhvb2t0dXJuZWRzdXBlcmlvciIsCiAgMHgwMmI1LAogICJyaG9zeW1ib2xncmVlayIsCiAgMHgwM2YxLAogICJyaG90aWNob29rbW9kIiwKICAweDAyZGUsCiAgInJpZXVsYWNpcmNsZWtvcmVhbiIsCiAgMHgzMjcxLAogICJyaWV1bGFwYXJlbmtvcmVhbiIsCiAgMHgzMjExLAogICJyaWV1bGNpcmNsZWtvcmVhbiIsCiAgMHgzMjYzLAogICJyaWV1bGhpZXVoa29yZWFuIiwKICAweDMxNDAsCiAgInJpZXVsa2l5ZW9ra29yZWFuIiwKICAweDMxM2EsCiAgInJpZXVsa2l5ZW9rc2lvc2tvcmVhbiIsCiAgMHgzMTY5LAogICJyaWV1bGtvcmVhbiIsCiAgMHgzMTM5LAogICJyaWV1bG1pZXVta29yZWFuIiwKICAweDMxM2IsCiAgInJpZXVscGFuc2lvc2tvcmVhbiIsCiAgMHgzMTZjLAogICJyaWV1bHBhcmVua29yZWFuIiwKICAweDMyMDMsCiAgInJpZXVscGhpZXVwaGtvcmVhbiIsCiAgMHgzMTNmLAogICJyaWV1bHBpZXVwa29yZWFuIiwKICAweDMxM2MsCiAgInJpZXVscGlldXBzaW9za29yZWFuIiwKICAweDMxNmIsCiAgInJpZXVsc2lvc2tvcmVhbiIsCiAgMHgzMTNkLAogICJyaWV1bHRoaWV1dGhrb3JlYW4iLAogIDB4MzEzZSwKICAicmlldWx0aWtldXRrb3JlYW4iLAogIDB4MzE2YSwKICAicmlldWx5ZW9yaW5oaWV1aGtvcmVhbiIsCiAgMHgzMTZkLAogICJyaWdodGFuZ2xlIiwKICAweDIyMWYsCiAgInJpZ2h0dGFja2JlbG93Y21iIiwKICAweDAzMTksCiAgInJpZ2h0dHJpYW5nbGUiLAogIDB4MjJiZiwKICAicmloaXJhZ2FuYSIsCiAgMHgzMDhhLAogICJyaWthdGFrYW5hIiwKICAweDMwZWEsCiAgInJpa2F0YWthbmFoYWxmd2lkdGgiLAogIDB4ZmY5OCwKICAicmluZyIsCiAgMHgwMmRhLAogICJyaW5nYmVsb3djbWIiLAogIDB4MDMyNSwKICAicmluZ2NtYiIsCiAgMHgwMzBhLAogICJyaW5naGFsZmxlZnQiLAogIDB4MDJiZiwKICAicmluZ2hhbGZsZWZ0YXJtZW5pYW4iLAogIDB4MDU1OSwKICAicmluZ2hhbGZsZWZ0YmVsb3djbWIiLAogIDB4MDMxYywKICAicmluZ2hhbGZsZWZ0Y2VudGVyZWQiLAogIDB4MDJkMywKICAicmluZ2hhbGZyaWdodCIsCiAgMHgwMmJlLAogICJyaW5naGFsZnJpZ2h0YmVsb3djbWIiLAogIDB4MDMzOSwKICAicmluZ2hhbGZyaWdodGNlbnRlcmVkIiwKICAweDAyZDIsCiAgInJpbnZlcnRlZGJyZXZlIiwKICAweDAyMTMsCiAgInJpdHRvcnVzcXVhcmUiLAogIDB4MzM1MSwKICAicmxpbmViZWxvdyIsCiAgMHgxZTVmLAogICJybG9uZ2xlZyIsCiAgMHgwMjdjLAogICJybG9uZ2xlZ3R1cm5lZCIsCiAgMHgwMjdhLAogICJybW9ub3NwYWNlIiwKICAweGZmNTIsCiAgInJvaGlyYWdhbmEiLAogIDB4MzA4ZCwKICAicm9rYXRha2FuYSIsCiAgMHgzMGVkLAogICJyb2thdGFrYW5haGFsZndpZHRoIiwKICAweGZmOWIsCiAgInJvcnVhdGhhaSIsCiAgMHgwZTIzLAogICJycGFyZW4iLAogIDB4MjRhZCwKICAicnJhYmVuZ2FsaSIsCiAgMHgwOWRjLAogICJycmFkZXZhIiwKICAweDA5MzEsCiAgInJyYWd1cm11a2hpIiwKICAweDBhNWMsCiAgInJyZWhhcmFiaWMiLAogIDB4MDY5MSwKICAicnJlaGZpbmFsYXJhYmljIiwKICAweGZiOGQsCiAgInJydm9jYWxpY2JlbmdhbGkiLAogIDB4MDllMCwKICAicnJ2b2NhbGljZGV2YSIsCiAgMHgwOTYwLAogICJycnZvY2FsaWNndWphcmF0aSIsCiAgMHgwYWUwLAogICJycnZvY2FsaWN2b3dlbHNpZ25iZW5nYWxpIiwKICAweDA5YzQsCiAgInJydm9jYWxpY3Zvd2Vsc2lnbmRldmEiLAogIDB4MDk0NCwKICAicnJ2b2NhbGljdm93ZWxzaWduZ3VqYXJhdGkiLAogIDB4MGFjNCwKICAicnN1cGVyaW9yIiwKICAweGY2ZjEsCiAgInJ0YmxvY2siLAogIDB4MjU5MCwKICAicnR1cm5lZCIsCiAgMHgwMjc5LAogICJydHVybmVkc3VwZXJpb3IiLAogIDB4MDJiNCwKICAicnVoaXJhZ2FuYSIsCiAgMHgzMDhiLAogICJydWthdGFrYW5hIiwKICAweDMwZWIsCiAgInJ1a2F0YWthbmFoYWxmd2lkdGgiLAogIDB4ZmY5OSwKICAicnVwZWVtYXJrYmVuZ2FsaSIsCiAgMHgwOWYyLAogICJydXBlZXNpZ25iZW5nYWxpIiwKICAweDA5ZjMsCiAgInJ1cGlhaCIsCiAgMHhmNmRkLAogICJydXRoYWkiLAogIDB4MGUyNCwKICAicnZvY2FsaWNiZW5nYWxpIiwKICAweDA5OGIsCiAgInJ2b2NhbGljZGV2YSIsCiAgMHgwOTBiLAogICJydm9jYWxpY2d1amFyYXRpIiwKICAweDBhOGIsCiAgInJ2b2NhbGljdm93ZWxzaWduYmVuZ2FsaSIsCiAgMHgwOWMzLAogICJydm9jYWxpY3Zvd2Vsc2lnbmRldmEiLAogIDB4MDk0MywKICAicnZvY2FsaWN2b3dlbHNpZ25ndWphcmF0aSIsCiAgMHgwYWMzLAogICJzIiwKICAweDAwNzMsCiAgInNhYmVuZ2FsaSIsCiAgMHgwOWI4LAogICJzYWN1dGUiLAogIDB4MDE1YiwKICAic2FjdXRlZG90YWNjZW50IiwKICAweDFlNjUsCiAgInNhZGFyYWJpYyIsCiAgMHgwNjM1LAogICJzYWRldmEiLAogIDB4MDkzOCwKICAic2FkZmluYWxhcmFiaWMiLAogIDB4ZmViYSwKICAic2FkaW5pdGlhbGFyYWJpYyIsCiAgMHhmZWJiLAogICJzYWRtZWRpYWxhcmFiaWMiLAogIDB4ZmViYywKICAic2FndWphcmF0aSIsCiAgMHgwYWI4LAogICJzYWd1cm11a2hpIiwKICAweDBhMzgsCiAgInNhaGlyYWdhbmEiLAogIDB4MzA1NSwKICAic2FrYXRha2FuYSIsCiAgMHgzMGI1LAogICJzYWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmN2IsCiAgInNhbGxhbGxhaG91YWxheWhld2FzYWxsYW1hcmFiaWMiLAogIDB4ZmRmYSwKICAic2FtZWtoIiwKICAweDA1ZTEsCiAgInNhbWVraGRhZ2VzaCIsCiAgMHhmYjQxLAogICJzYW1la2hkYWdlc2hoZWJyZXciLAogIDB4ZmI0MSwKICAic2FtZWtoaGVicmV3IiwKICAweDA1ZTEsCiAgInNhcmFhYXRoYWkiLAogIDB4MGUzMiwKICAic2FyYWFldGhhaSIsCiAgMHgwZTQxLAogICJzYXJhYWltYWltYWxhaXRoYWkiLAogIDB4MGU0NCwKICAic2FyYWFpbWFpbXVhbnRoYWkiLAogIDB4MGU0MywKICAic2FyYWFtdGhhaSIsCiAgMHgwZTMzLAogICJzYXJhYXRoYWkiLAogIDB4MGUzMCwKICAic2FyYWV0aGFpIiwKICAweDBlNDAsCiAgInNhcmFpaWxlZnR0aGFpIiwKICAweGY4ODYsCiAgInNhcmFpaXRoYWkiLAogIDB4MGUzNSwKICAic2FyYWlsZWZ0dGhhaSIsCiAgMHhmODg1LAogICJzYXJhaXRoYWkiLAogIDB4MGUzNCwKICAic2FyYW90aGFpIiwKICAweDBlNDIsCiAgInNhcmF1ZWVsZWZ0dGhhaSIsCiAgMHhmODg4LAogICJzYXJhdWVldGhhaSIsCiAgMHgwZTM3LAogICJzYXJhdWVsZWZ0dGhhaSIsCiAgMHhmODg3LAogICJzYXJhdWV0aGFpIiwKICAweDBlMzYsCiAgInNhcmF1dGhhaSIsCiAgMHgwZTM4LAogICJzYXJhdXV0aGFpIiwKICAweDBlMzksCiAgInNib3BvbW9mbyIsCiAgMHgzMTE5LAogICJzY2Fyb24iLAogIDB4MDE2MSwKICAic2Nhcm9uZG90YWNjZW50IiwKICAweDFlNjcsCiAgInNjZWRpbGxhIiwKICAweDAxNWYsCiAgInNjaHdhIiwKICAweDAyNTksCiAgInNjaHdhY3lyaWxsaWMiLAogIDB4MDRkOSwKICAic2Nod2FkaWVyZXNpc2N5cmlsbGljIiwKICAweDA0ZGIsCiAgInNjaHdhaG9vayIsCiAgMHgwMjVhLAogICJzY2lyY2xlIiwKICAweDI0ZTIsCiAgInNjaXJjdW1mbGV4IiwKICAweDAxNWQsCiAgInNjb21tYWFjY2VudCIsCiAgMHgwMjE5LAogICJzZG90YWNjZW50IiwKICAweDFlNjEsCiAgInNkb3RiZWxvdyIsCiAgMHgxZTYzLAogICJzZG90YmVsb3dkb3RhY2NlbnQiLAogIDB4MWU2OSwKICAic2VhZ3VsbGJlbG93Y21iIiwKICAweDAzM2MsCiAgInNlY29uZCIsCiAgMHgyMDMzLAogICJzZWNvbmR0b25lY2hpbmVzZSIsCiAgMHgwMmNhLAogICJzZWN0aW9uIiwKICAweDAwYTcsCiAgInNlZW5hcmFiaWMiLAogIDB4MDYzMywKICAic2VlbmZpbmFsYXJhYmljIiwKICAweGZlYjIsCiAgInNlZW5pbml0aWFsYXJhYmljIiwKICAweGZlYjMsCiAgInNlZW5tZWRpYWxhcmFiaWMiLAogIDB4ZmViNCwKICAic2Vnb2wiLAogIDB4MDViNiwKICAic2Vnb2wxMyIsCiAgMHgwNWI2LAogICJzZWdvbDFmIiwKICAweDA1YjYsCiAgInNlZ29sMmMiLAogIDB4MDViNiwKICAic2Vnb2xoZWJyZXciLAogIDB4MDViNiwKICAic2Vnb2xuYXJyb3doZWJyZXciLAogIDB4MDViNiwKICAic2Vnb2xxdWFydGVyaGVicmV3IiwKICAweDA1YjYsCiAgInNlZ29sdGFoZWJyZXciLAogIDB4MDU5MiwKICAic2Vnb2x3aWRlaGVicmV3IiwKICAweDA1YjYsCiAgInNlaGFybWVuaWFuIiwKICAweDA1N2QsCiAgInNlaGlyYWdhbmEiLAogIDB4MzA1YiwKICAic2VrYXRha2FuYSIsCiAgMHgzMGJiLAogICJzZWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmN2UsCiAgInNlbWljb2xvbiIsCiAgMHgwMDNiLAogICJzZW1pY29sb25hcmFiaWMiLAogIDB4MDYxYiwKICAic2VtaWNvbG9ubW9ub3NwYWNlIiwKICAweGZmMWIsCiAgInNlbWljb2xvbnNtYWxsIiwKICAweGZlNTQsCiAgInNlbWl2b2ljZWRtYXJra2FuYSIsCiAgMHgzMDljLAogICJzZW1pdm9pY2VkbWFya2thbmFoYWxmd2lkdGgiLAogIDB4ZmY5ZiwKICAic2VudGlzcXVhcmUiLAogIDB4MzMyMiwKICAic2VudG9zcXVhcmUiLAogIDB4MzMyMywKICAic2V2ZW4iLAogIDB4MDAzNywKICAic2V2ZW5hcmFiaWMiLAogIDB4MDY2NywKICAic2V2ZW5iZW5nYWxpIiwKICAweDA5ZWQsCiAgInNldmVuY2lyY2xlIiwKICAweDI0NjYsCiAgInNldmVuY2lyY2xlaW52ZXJzZXNhbnNzZXJpZiIsCiAgMHgyNzkwLAogICJzZXZlbmRldmEiLAogIDB4MDk2ZCwKICAic2V2ZW5laWdodGhzIiwKICAweDIxNWUsCiAgInNldmVuZ3VqYXJhdGkiLAogIDB4MGFlZCwKICAic2V2ZW5ndXJtdWtoaSIsCiAgMHgwYTZkLAogICJzZXZlbmhhY2thcmFiaWMiLAogIDB4MDY2NywKICAic2V2ZW5oYW5nemhvdSIsCiAgMHgzMDI3LAogICJzZXZlbmlkZW9ncmFwaGljcGFyZW4iLAogIDB4MzIyNiwKICAic2V2ZW5pbmZlcmlvciIsCiAgMHgyMDg3LAogICJzZXZlbm1vbm9zcGFjZSIsCiAgMHhmZjE3LAogICJzZXZlbm9sZHN0eWxlIiwKICAweGY3MzcsCiAgInNldmVucGFyZW4iLAogIDB4MjQ3YSwKICAic2V2ZW5wZXJpb2QiLAogIDB4MjQ4ZSwKICAic2V2ZW5wZXJzaWFuIiwKICAweDA2ZjcsCiAgInNldmVucm9tYW4iLAogIDB4MjE3NiwKICAic2V2ZW5zdXBlcmlvciIsCiAgMHgyMDc3LAogICJzZXZlbnRlZW5jaXJjbGUiLAogIDB4MjQ3MCwKICAic2V2ZW50ZWVucGFyZW4iLAogIDB4MjQ4NCwKICAic2V2ZW50ZWVucGVyaW9kIiwKICAweDI0OTgsCiAgInNldmVudGhhaSIsCiAgMHgwZTU3LAogICJzZnRoeXBoZW4iLAogIDB4MDBhZCwKICAic2hhYXJtZW5pYW4iLAogIDB4MDU3NywKICAic2hhYmVuZ2FsaSIsCiAgMHgwOWI2LAogICJzaGFjeXJpbGxpYyIsCiAgMHgwNDQ4LAogICJzaGFkZGFhcmFiaWMiLAogIDB4MDY1MSwKICAic2hhZGRhZGFtbWFhcmFiaWMiLAogIDB4ZmM2MSwKICAic2hhZGRhZGFtbWF0YW5hcmFiaWMiLAogIDB4ZmM1ZSwKICAic2hhZGRhZmF0aGFhcmFiaWMiLAogIDB4ZmM2MCwKICAic2hhZGRha2FzcmFhcmFiaWMiLAogIDB4ZmM2MiwKICAic2hhZGRha2FzcmF0YW5hcmFiaWMiLAogIDB4ZmM1ZiwKICAic2hhZGUiLAogIDB4MjU5MiwKICAic2hhZGVkYXJrIiwKICAweDI1OTMsCiAgInNoYWRlbGlnaHQiLAogIDB4MjU5MSwKICAic2hhZGVtZWRpdW0iLAogIDB4MjU5MiwKICAic2hhZGV2YSIsCiAgMHgwOTM2LAogICJzaGFndWphcmF0aSIsCiAgMHgwYWI2LAogICJzaGFndXJtdWtoaSIsCiAgMHgwYTM2LAogICJzaGFsc2hlbGV0aGVicmV3IiwKICAweDA1OTMsCiAgInNoYm9wb21vZm8iLAogIDB4MzExNSwKICAic2hjaGFjeXJpbGxpYyIsCiAgMHgwNDQ5LAogICJzaGVlbmFyYWJpYyIsCiAgMHgwNjM0LAogICJzaGVlbmZpbmFsYXJhYmljIiwKICAweGZlYjYsCiAgInNoZWVuaW5pdGlhbGFyYWJpYyIsCiAgMHhmZWI3LAogICJzaGVlbm1lZGlhbGFyYWJpYyIsCiAgMHhmZWI4LAogICJzaGVpY29wdGljIiwKICAweDAzZTMsCiAgInNoZXFlbCIsCiAgMHgyMGFhLAogICJzaGVxZWxoZWJyZXciLAogIDB4MjBhYSwKICAic2hldmEiLAogIDB4MDViMCwKICAic2hldmExMTUiLAogIDB4MDViMCwKICAic2hldmExNSIsCiAgMHgwNWIwLAogICJzaGV2YTIyIiwKICAweDA1YjAsCiAgInNoZXZhMmUiLAogIDB4MDViMCwKICAic2hldmFoZWJyZXciLAogIDB4MDViMCwKICAic2hldmFuYXJyb3doZWJyZXciLAogIDB4MDViMCwKICAic2hldmFxdWFydGVyaGVicmV3IiwKICAweDA1YjAsCiAgInNoZXZhd2lkZWhlYnJldyIsCiAgMHgwNWIwLAogICJzaGhhY3lyaWxsaWMiLAogIDB4MDRiYiwKICAic2hpbWFjb3B0aWMiLAogIDB4MDNlZCwKICAic2hpbiIsCiAgMHgwNWU5LAogICJzaGluZGFnZXNoIiwKICAweGZiNDksCiAgInNoaW5kYWdlc2hoZWJyZXciLAogIDB4ZmI0OSwKICAic2hpbmRhZ2VzaHNoaW5kb3QiLAogIDB4ZmIyYywKICAic2hpbmRhZ2VzaHNoaW5kb3RoZWJyZXciLAogIDB4ZmIyYywKICAic2hpbmRhZ2VzaHNpbmRvdCIsCiAgMHhmYjJkLAogICJzaGluZGFnZXNoc2luZG90aGVicmV3IiwKICAweGZiMmQsCiAgInNoaW5kb3RoZWJyZXciLAogIDB4MDVjMSwKICAic2hpbmhlYnJldyIsCiAgMHgwNWU5LAogICJzaGluc2hpbmRvdCIsCiAgMHhmYjJhLAogICJzaGluc2hpbmRvdGhlYnJldyIsCiAgMHhmYjJhLAogICJzaGluc2luZG90IiwKICAweGZiMmIsCiAgInNoaW5zaW5kb3RoZWJyZXciLAogIDB4ZmIyYiwKICAic2hvb2siLAogIDB4MDI4MiwKICAic2lnbWEiLAogIDB4MDNjMywKICAic2lnbWExIiwKICAweDAzYzIsCiAgInNpZ21hZmluYWwiLAogIDB4MDNjMiwKICAic2lnbWFsdW5hdGVzeW1ib2xncmVlayIsCiAgMHgwM2YyLAogICJzaWhpcmFnYW5hIiwKICAweDMwNTcsCiAgInNpa2F0YWthbmEiLAogIDB4MzBiNywKICAic2lrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjdjLAogICJzaWx1cWhlYnJldyIsCiAgMHgwNWJkLAogICJzaWx1cWxlZnRoZWJyZXciLAogIDB4MDViZCwKICAic2ltaWxhciIsCiAgMHgyMjNjLAogICJzaW5kb3RoZWJyZXciLAogIDB4MDVjMiwKICAic2lvc2FjaXJjbGVrb3JlYW4iLAogIDB4MzI3NCwKICAic2lvc2FwYXJlbmtvcmVhbiIsCiAgMHgzMjE0LAogICJzaW9zY2lldWNrb3JlYW4iLAogIDB4MzE3ZSwKICAic2lvc2NpcmNsZWtvcmVhbiIsCiAgMHgzMjY2LAogICJzaW9za2l5ZW9ra29yZWFuIiwKICAweDMxN2EsCiAgInNpb3Nrb3JlYW4iLAogIDB4MzE0NSwKICAic2lvc25pZXVua29yZWFuIiwKICAweDMxN2IsCiAgInNpb3NwYXJlbmtvcmVhbiIsCiAgMHgzMjA2LAogICJzaW9zcGlldXBrb3JlYW4iLAogIDB4MzE3ZCwKICAic2lvc3Rpa2V1dGtvcmVhbiIsCiAgMHgzMTdjLAogICJzaXgiLAogIDB4MDAzNiwKICAic2l4YXJhYmljIiwKICAweDA2NjYsCiAgInNpeGJlbmdhbGkiLAogIDB4MDllYywKICAic2l4Y2lyY2xlIiwKICAweDI0NjUsCiAgInNpeGNpcmNsZWludmVyc2VzYW5zc2VyaWYiLAogIDB4Mjc4ZiwKICAic2l4ZGV2YSIsCiAgMHgwOTZjLAogICJzaXhndWphcmF0aSIsCiAgMHgwYWVjLAogICJzaXhndXJtdWtoaSIsCiAgMHgwYTZjLAogICJzaXhoYWNrYXJhYmljIiwKICAweDA2NjYsCiAgInNpeGhhbmd6aG91IiwKICAweDMwMjYsCiAgInNpeGlkZW9ncmFwaGljcGFyZW4iLAogIDB4MzIyNSwKICAic2l4aW5mZXJpb3IiLAogIDB4MjA4NiwKICAic2l4bW9ub3NwYWNlIiwKICAweGZmMTYsCiAgInNpeG9sZHN0eWxlIiwKICAweGY3MzYsCiAgInNpeHBhcmVuIiwKICAweDI0NzksCiAgInNpeHBlcmlvZCIsCiAgMHgyNDhkLAogICJzaXhwZXJzaWFuIiwKICAweDA2ZjYsCiAgInNpeHJvbWFuIiwKICAweDIxNzUsCiAgInNpeHN1cGVyaW9yIiwKICAweDIwNzYsCiAgInNpeHRlZW5jaXJjbGUiLAogIDB4MjQ2ZiwKICAic2l4dGVlbmN1cnJlbmN5ZGVub21pbmF0b3JiZW5nYWxpIiwKICAweDA5ZjksCiAgInNpeHRlZW5wYXJlbiIsCiAgMHgyNDgzLAogICJzaXh0ZWVucGVyaW9kIiwKICAweDI0OTcsCiAgInNpeHRoYWkiLAogIDB4MGU1NiwKICAic2xhc2giLAogIDB4MDAyZiwKICAic2xhc2htb25vc3BhY2UiLAogIDB4ZmYwZiwKICAic2xvbmciLAogIDB4MDE3ZiwKICAic2xvbmdkb3RhY2NlbnQiLAogIDB4MWU5YiwKICAic21pbGVmYWNlIiwKICAweDI2M2EsCiAgInNtb25vc3BhY2UiLAogIDB4ZmY1MywKICAic29mcGFzdXFoZWJyZXciLAogIDB4MDVjMywKICAic29mdGh5cGhlbiIsCiAgMHgwMGFkLAogICJzb2Z0c2lnbmN5cmlsbGljIiwKICAweDA0NGMsCiAgInNvaGlyYWdhbmEiLAogIDB4MzA1ZCwKICAic29rYXRha2FuYSIsCiAgMHgzMGJkLAogICJzb2thdGFrYW5haGFsZndpZHRoIiwKICAweGZmN2YsCiAgInNvbGlkdXNsb25nb3ZlcmxheWNtYiIsCiAgMHgwMzM4LAogICJzb2xpZHVzc2hvcnRvdmVybGF5Y21iIiwKICAweDAzMzcsCiAgInNvcnVzaXRoYWkiLAogIDB4MGUyOSwKICAic29zYWxhdGhhaSIsCiAgMHgwZTI4LAogICJzb3NvdGhhaSIsCiAgMHgwZTBiLAogICJzb3N1YXRoYWkiLAogIDB4MGUyYSwKICAic3BhY2UiLAogIDB4MDAyMCwKICAic3BhY2VoYWNrYXJhYmljIiwKICAweDAwMjAsCiAgInNwYWRlIiwKICAweDI2NjAsCiAgInNwYWRlc3VpdGJsYWNrIiwKICAweDI2NjAsCiAgInNwYWRlc3VpdHdoaXRlIiwKICAweDI2NjQsCiAgInNwYXJlbiIsCiAgMHgyNGFlLAogICJzcXVhcmViZWxvd2NtYiIsCiAgMHgwMzNiLAogICJzcXVhcmVjYyIsCiAgMHgzM2M0LAogICJzcXVhcmVjbSIsCiAgMHgzMzlkLAogICJzcXVhcmVkaWFnb25hbGNyb3NzaGF0Y2hmaWxsIiwKICAweDI1YTksCiAgInNxdWFyZWhvcml6b250YWxmaWxsIiwKICAweDI1YTQsCiAgInNxdWFyZWtnIiwKICAweDMzOGYsCiAgInNxdWFyZWttIiwKICAweDMzOWUsCiAgInNxdWFyZWttY2FwaXRhbCIsCiAgMHgzM2NlLAogICJzcXVhcmVsbiIsCiAgMHgzM2QxLAogICJzcXVhcmVsb2ciLAogIDB4MzNkMiwKICAic3F1YXJlbWciLAogIDB4MzM4ZSwKICAic3F1YXJlbWlsIiwKICAweDMzZDUsCiAgInNxdWFyZW1tIiwKICAweDMzOWMsCiAgInNxdWFyZW1zcXVhcmVkIiwKICAweDMzYTEsCiAgInNxdWFyZW9ydGhvZ29uYWxjcm9zc2hhdGNoZmlsbCIsCiAgMHgyNWE2LAogICJzcXVhcmV1cHBlcmxlZnR0b2xvd2VycmlnaHRmaWxsIiwKICAweDI1YTcsCiAgInNxdWFyZXVwcGVycmlnaHR0b2xvd2VybGVmdGZpbGwiLAogIDB4MjVhOCwKICAic3F1YXJldmVydGljYWxmaWxsIiwKICAweDI1YTUsCiAgInNxdWFyZXdoaXRld2l0aHNtYWxsYmxhY2siLAogIDB4MjVhMywKICAic3JzcXVhcmUiLAogIDB4MzNkYiwKICAic3NhYmVuZ2FsaSIsCiAgMHgwOWI3LAogICJzc2FkZXZhIiwKICAweDA5MzcsCiAgInNzYWd1amFyYXRpIiwKICAweDBhYjcsCiAgInNzYW5nY2lldWNrb3JlYW4iLAogIDB4MzE0OSwKICAic3NhbmdoaWV1aGtvcmVhbiIsCiAgMHgzMTg1LAogICJzc2FuZ2lldW5na29yZWFuIiwKICAweDMxODAsCiAgInNzYW5na2l5ZW9ra29yZWFuIiwKICAweDMxMzIsCiAgInNzYW5nbmlldW5rb3JlYW4iLAogIDB4MzE2NSwKICAic3NhbmdwaWV1cGtvcmVhbiIsCiAgMHgzMTQzLAogICJzc2FuZ3Npb3Nrb3JlYW4iLAogIDB4MzE0NiwKICAic3Nhbmd0aWtldXRrb3JlYW4iLAogIDB4MzEzOCwKICAic3N1cGVyaW9yIiwKICAweGY2ZjIsCiAgInN0ZXJsaW5nIiwKICAweDAwYTMsCiAgInN0ZXJsaW5nbW9ub3NwYWNlIiwKICAweGZmZTEsCiAgInN0cm9rZWxvbmdvdmVybGF5Y21iIiwKICAweDAzMzYsCiAgInN0cm9rZXNob3J0b3ZlcmxheWNtYiIsCiAgMHgwMzM1LAogICJzdWJzZXQiLAogIDB4MjI4MiwKICAic3Vic2V0bm90ZXF1YWwiLAogIDB4MjI4YSwKICAic3Vic2V0b3JlcXVhbCIsCiAgMHgyMjg2LAogICJzdWNjZWVkcyIsCiAgMHgyMjdiLAogICJzdWNodGhhdCIsCiAgMHgyMjBiLAogICJzdWhpcmFnYW5hIiwKICAweDMwNTksCiAgInN1a2F0YWthbmEiLAogIDB4MzBiOSwKICAic3VrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjdkLAogICJzdWt1bmFyYWJpYyIsCiAgMHgwNjUyLAogICJzdW1tYXRpb24iLAogIDB4MjIxMSwKICAic3VuIiwKICAweDI2M2MsCiAgInN1cGVyc2V0IiwKICAweDIyODMsCiAgInN1cGVyc2V0bm90ZXF1YWwiLAogIDB4MjI4YiwKICAic3VwZXJzZXRvcmVxdWFsIiwKICAweDIyODcsCiAgInN2c3F1YXJlIiwKICAweDMzZGMsCiAgInN5b3V3YWVyYXNxdWFyZSIsCiAgMHgzMzdjLAogICJ0IiwKICAweDAwNzQsCiAgInRhYmVuZ2FsaSIsCiAgMHgwOWE0LAogICJ0YWNrZG93biIsCiAgMHgyMmE0LAogICJ0YWNrbGVmdCIsCiAgMHgyMmEzLAogICJ0YWRldmEiLAogIDB4MDkyNCwKICAidGFndWphcmF0aSIsCiAgMHgwYWE0LAogICJ0YWd1cm11a2hpIiwKICAweDBhMjQsCiAgInRhaGFyYWJpYyIsCiAgMHgwNjM3LAogICJ0YWhmaW5hbGFyYWJpYyIsCiAgMHhmZWMyLAogICJ0YWhpbml0aWFsYXJhYmljIiwKICAweGZlYzMsCiAgInRhaGlyYWdhbmEiLAogIDB4MzA1ZiwKICAidGFobWVkaWFsYXJhYmljIiwKICAweGZlYzQsCiAgInRhaXN5b3VlcmFzcXVhcmUiLAogIDB4MzM3ZCwKICAidGFrYXRha2FuYSIsCiAgMHgzMGJmLAogICJ0YWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmODAsCiAgInRhdHdlZWxhcmFiaWMiLAogIDB4MDY0MCwKICAidGF1IiwKICAweDAzYzQsCiAgInRhdiIsCiAgMHgwNWVhLAogICJ0YXZkYWdlcyIsCiAgMHhmYjRhLAogICJ0YXZkYWdlc2giLAogIDB4ZmI0YSwKICAidGF2ZGFnZXNoaGVicmV3IiwKICAweGZiNGEsCiAgInRhdmhlYnJldyIsCiAgMHgwNWVhLAogICJ0YmFyIiwKICAweDAxNjcsCiAgInRib3BvbW9mbyIsCiAgMHgzMTBhLAogICJ0Y2Fyb24iLAogIDB4MDE2NSwKICAidGNjdXJsIiwKICAweDAyYTgsCiAgInRjZWRpbGxhIiwKICAweDAxNjMsCiAgInRjaGVoYXJhYmljIiwKICAweDA2ODYsCiAgInRjaGVoZmluYWxhcmFiaWMiLAogIDB4ZmI3YiwKICAidGNoZWhpbml0aWFsYXJhYmljIiwKICAweGZiN2MsCiAgInRjaGVobWVkaWFsYXJhYmljIiwKICAweGZiN2QsCiAgInRjaXJjbGUiLAogIDB4MjRlMywKICAidGNpcmN1bWZsZXhiZWxvdyIsCiAgMHgxZTcxLAogICJ0Y29tbWFhY2NlbnQiLAogIDB4MDE2MywKICAidGRpZXJlc2lzIiwKICAweDFlOTcsCiAgInRkb3RhY2NlbnQiLAogIDB4MWU2YiwKICAidGRvdGJlbG93IiwKICAweDFlNmQsCiAgInRlY3lyaWxsaWMiLAogIDB4MDQ0MiwKICAidGVkZXNjZW5kZXJjeXJpbGxpYyIsCiAgMHgwNGFkLAogICJ0ZWhhcmFiaWMiLAogIDB4MDYyYSwKICAidGVoZmluYWxhcmFiaWMiLAogIDB4ZmU5NiwKICAidGVoaGFoaW5pdGlhbGFyYWJpYyIsCiAgMHhmY2EyLAogICJ0ZWhoYWhpc29sYXRlZGFyYWJpYyIsCiAgMHhmYzBjLAogICJ0ZWhpbml0aWFsYXJhYmljIiwKICAweGZlOTcsCiAgInRlaGlyYWdhbmEiLAogIDB4MzA2NiwKICAidGVoamVlbWluaXRpYWxhcmFiaWMiLAogIDB4ZmNhMSwKICAidGVoamVlbWlzb2xhdGVkYXJhYmljIiwKICAweGZjMGIsCiAgInRlaG1hcmJ1dGFhcmFiaWMiLAogIDB4MDYyOSwKICAidGVobWFyYnV0YWZpbmFsYXJhYmljIiwKICAweGZlOTQsCiAgInRlaG1lZGlhbGFyYWJpYyIsCiAgMHhmZTk4LAogICJ0ZWhtZWVtaW5pdGlhbGFyYWJpYyIsCiAgMHhmY2E0LAogICJ0ZWhtZWVtaXNvbGF0ZWRhcmFiaWMiLAogIDB4ZmMwZSwKICAidGVobm9vbmZpbmFsYXJhYmljIiwKICAweGZjNzMsCiAgInRla2F0YWthbmEiLAogIDB4MzBjNiwKICAidGVrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjgzLAogICJ0ZWxlcGhvbmUiLAogIDB4MjEyMSwKICAidGVsZXBob25lYmxhY2siLAogIDB4MjYwZSwKICAidGVsaXNoYWdlZG9sYWhlYnJldyIsCiAgMHgwNWEwLAogICJ0ZWxpc2hhcWV0YW5haGVicmV3IiwKICAweDA1YTksCiAgInRlbmNpcmNsZSIsCiAgMHgyNDY5LAogICJ0ZW5pZGVvZ3JhcGhpY3BhcmVuIiwKICAweDMyMjksCiAgInRlbnBhcmVuIiwKICAweDI0N2QsCiAgInRlbnBlcmlvZCIsCiAgMHgyNDkxLAogICJ0ZW5yb21hbiIsCiAgMHgyMTc5LAogICJ0ZXNoIiwKICAweDAyYTcsCiAgInRldCIsCiAgMHgwNWQ4LAogICJ0ZXRkYWdlc2giLAogIDB4ZmIzOCwKICAidGV0ZGFnZXNoaGVicmV3IiwKICAweGZiMzgsCiAgInRldGhlYnJldyIsCiAgMHgwNWQ4LAogICJ0ZXRzZWN5cmlsbGljIiwKICAweDA0YjUsCiAgInRldmlyaGVicmV3IiwKICAweDA1OWIsCiAgInRldmlybGVmdGhlYnJldyIsCiAgMHgwNTliLAogICJ0aGFiZW5nYWxpIiwKICAweDA5YTUsCiAgInRoYWRldmEiLAogIDB4MDkyNSwKICAidGhhZ3VqYXJhdGkiLAogIDB4MGFhNSwKICAidGhhZ3VybXVraGkiLAogIDB4MGEyNSwKICAidGhhbGFyYWJpYyIsCiAgMHgwNjMwLAogICJ0aGFsZmluYWxhcmFiaWMiLAogIDB4ZmVhYywKICAidGhhbnRoYWtoYXRsb3dsZWZ0dGhhaSIsCiAgMHhmODk4LAogICJ0aGFudGhha2hhdGxvd3JpZ2h0dGhhaSIsCiAgMHhmODk3LAogICJ0aGFudGhha2hhdHRoYWkiLAogIDB4MGU0YywKICAidGhhbnRoYWtoYXR1cHBlcmxlZnR0aGFpIiwKICAweGY4OTYsCiAgInRoZWhhcmFiaWMiLAogIDB4MDYyYiwKICAidGhlaGZpbmFsYXJhYmljIiwKICAweGZlOWEsCiAgInRoZWhpbml0aWFsYXJhYmljIiwKICAweGZlOWIsCiAgInRoZWhtZWRpYWxhcmFiaWMiLAogIDB4ZmU5YywKICAidGhlcmVleGlzdHMiLAogIDB4MjIwMywKICAidGhlcmVmb3JlIiwKICAweDIyMzQsCiAgInRoZXRhIiwKICAweDAzYjgsCiAgInRoZXRhMSIsCiAgMHgwM2QxLAogICJ0aGV0YXN5bWJvbGdyZWVrIiwKICAweDAzZDEsCiAgInRoaWV1dGhhY2lyY2xla29yZWFuIiwKICAweDMyNzksCiAgInRoaWV1dGhhcGFyZW5rb3JlYW4iLAogIDB4MzIxOSwKICAidGhpZXV0aGNpcmNsZWtvcmVhbiIsCiAgMHgzMjZiLAogICJ0aGlldXRoa29yZWFuIiwKICAweDMxNGMsCiAgInRoaWV1dGhwYXJlbmtvcmVhbiIsCiAgMHgzMjBiLAogICJ0aGlydGVlbmNpcmNsZSIsCiAgMHgyNDZjLAogICJ0aGlydGVlbnBhcmVuIiwKICAweDI0ODAsCiAgInRoaXJ0ZWVucGVyaW9kIiwKICAweDI0OTQsCiAgInRob25hbmdtb250aG90aGFpIiwKICAweDBlMTEsCiAgInRob29rIiwKICAweDAxYWQsCiAgInRob3BodXRoYW90aGFpIiwKICAweDBlMTIsCiAgInRob3JuIiwKICAweDAwZmUsCiAgInRob3RoYWhhbnRoYWkiLAogIDB4MGUxNywKICAidGhvdGhhbnRoYWkiLAogIDB4MGUxMCwKICAidGhvdGhvbmd0aGFpIiwKICAweDBlMTgsCiAgInRob3RodW5ndGhhaSIsCiAgMHgwZTE2LAogICJ0aG91c2FuZGN5cmlsbGljIiwKICAweDA0ODIsCiAgInRob3VzYW5kc3NlcGFyYXRvcmFyYWJpYyIsCiAgMHgwNjZjLAogICJ0aG91c2FuZHNzZXBhcmF0b3JwZXJzaWFuIiwKICAweDA2NmMsCiAgInRocmVlIiwKICAweDAwMzMsCiAgInRocmVlYXJhYmljIiwKICAweDA2NjMsCiAgInRocmVlYmVuZ2FsaSIsCiAgMHgwOWU5LAogICJ0aHJlZWNpcmNsZSIsCiAgMHgyNDYyLAogICJ0aHJlZWNpcmNsZWludmVyc2VzYW5zc2VyaWYiLAogIDB4Mjc4YywKICAidGhyZWVkZXZhIiwKICAweDA5NjksCiAgInRocmVlZWlnaHRocyIsCiAgMHgyMTVjLAogICJ0aHJlZWd1amFyYXRpIiwKICAweDBhZTksCiAgInRocmVlZ3VybXVraGkiLAogIDB4MGE2OSwKICAidGhyZWVoYWNrYXJhYmljIiwKICAweDA2NjMsCiAgInRocmVlaGFuZ3pob3UiLAogIDB4MzAyMywKICAidGhyZWVpZGVvZ3JhcGhpY3BhcmVuIiwKICAweDMyMjIsCiAgInRocmVlaW5mZXJpb3IiLAogIDB4MjA4MywKICAidGhyZWVtb25vc3BhY2UiLAogIDB4ZmYxMywKICAidGhyZWVudW1lcmF0b3JiZW5nYWxpIiwKICAweDA5ZjYsCiAgInRocmVlb2xkc3R5bGUiLAogIDB4ZjczMywKICAidGhyZWVwYXJlbiIsCiAgMHgyNDc2LAogICJ0aHJlZXBlcmlvZCIsCiAgMHgyNDhhLAogICJ0aHJlZXBlcnNpYW4iLAogIDB4MDZmMywKICAidGhyZWVxdWFydGVycyIsCiAgMHgwMGJlLAogICJ0aHJlZXF1YXJ0ZXJzZW1kYXNoIiwKICAweGY2ZGUsCiAgInRocmVlcm9tYW4iLAogIDB4MjE3MiwKICAidGhyZWVzdXBlcmlvciIsCiAgMHgwMGIzLAogICJ0aHJlZXRoYWkiLAogIDB4MGU1MywKICAidGh6c3F1YXJlIiwKICAweDMzOTQsCiAgInRpaGlyYWdhbmEiLAogIDB4MzA2MSwKICAidGlrYXRha2FuYSIsCiAgMHgzMGMxLAogICJ0aWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmODEsCiAgInRpa2V1dGFjaXJjbGVrb3JlYW4iLAogIDB4MzI3MCwKICAidGlrZXV0YXBhcmVua29yZWFuIiwKICAweDMyMTAsCiAgInRpa2V1dGNpcmNsZWtvcmVhbiIsCiAgMHgzMjYyLAogICJ0aWtldXRrb3JlYW4iLAogIDB4MzEzNywKICAidGlrZXV0cGFyZW5rb3JlYW4iLAogIDB4MzIwMiwKICAidGlsZGUiLAogIDB4MDJkYywKICAidGlsZGViZWxvd2NtYiIsCiAgMHgwMzMwLAogICJ0aWxkZWNtYiIsCiAgMHgwMzAzLAogICJ0aWxkZWNvbWIiLAogIDB4MDMwMywKICAidGlsZGVkb3VibGVjbWIiLAogIDB4MDM2MCwKICAidGlsZGVvcGVyYXRvciIsCiAgMHgyMjNjLAogICJ0aWxkZW92ZXJsYXljbWIiLAogIDB4MDMzNCwKICAidGlsZGV2ZXJ0aWNhbGNtYiIsCiAgMHgwMzNlLAogICJ0aW1lc2NpcmNsZSIsCiAgMHgyMjk3LAogICJ0aXBlaGFoZWJyZXciLAogIDB4MDU5NiwKICAidGlwZWhhbGVmdGhlYnJldyIsCiAgMHgwNTk2LAogICJ0aXBwaWd1cm11a2hpIiwKICAweDBhNzAsCiAgInRpdGxvY3lyaWxsaWNjbWIiLAogIDB4MDQ4MywKICAidGl3bmFybWVuaWFuIiwKICAweDA1N2YsCiAgInRsaW5lYmVsb3ciLAogIDB4MWU2ZiwKICAidG1vbm9zcGFjZSIsCiAgMHhmZjU0LAogICJ0b2FybWVuaWFuIiwKICAweDA1NjksCiAgInRvaGlyYWdhbmEiLAogIDB4MzA2OCwKICAidG9rYXRha2FuYSIsCiAgMHgzMGM4LAogICJ0b2thdGFrYW5haGFsZndpZHRoIiwKICAweGZmODQsCiAgInRvbmViYXJleHRyYWhpZ2htb2QiLAogIDB4MDJlNSwKICAidG9uZWJhcmV4dHJhbG93bW9kIiwKICAweDAyZTksCiAgInRvbmViYXJoaWdobW9kIiwKICAweDAyZTYsCiAgInRvbmViYXJsb3dtb2QiLAogIDB4MDJlOCwKICAidG9uZWJhcm1pZG1vZCIsCiAgMHgwMmU3LAogICJ0b25lZml2ZSIsCiAgMHgwMWJkLAogICJ0b25lc2l4IiwKICAweDAxODUsCiAgInRvbmV0d28iLAogIDB4MDFhOCwKICAidG9ub3MiLAogIDB4MDM4NCwKICAidG9uc3F1YXJlIiwKICAweDMzMjcsCiAgInRvcGF0YWt0aGFpIiwKICAweDBlMGYsCiAgInRvcnRvaXNlc2hlbGxicmFja2V0bGVmdCIsCiAgMHgzMDE0LAogICJ0b3J0b2lzZXNoZWxsYnJhY2tldGxlZnRzbWFsbCIsCiAgMHhmZTVkLAogICJ0b3J0b2lzZXNoZWxsYnJhY2tldGxlZnR2ZXJ0aWNhbCIsCiAgMHhmZTM5LAogICJ0b3J0b2lzZXNoZWxsYnJhY2tldHJpZ2h0IiwKICAweDMwMTUsCiAgInRvcnRvaXNlc2hlbGxicmFja2V0cmlnaHRzbWFsbCIsCiAgMHhmZTVlLAogICJ0b3J0b2lzZXNoZWxsYnJhY2tldHJpZ2h0dmVydGljYWwiLAogIDB4ZmUzYSwKICAidG90YW90aGFpIiwKICAweDBlMTUsCiAgInRwYWxhdGFsaG9vayIsCiAgMHgwMWFiLAogICJ0cGFyZW4iLAogIDB4MjRhZiwKICAidHJhZGVtYXJrIiwKICAweDIxMjIsCiAgInRyYWRlbWFya3NhbnMiLAogIDB4ZjhlYSwKICAidHJhZGVtYXJrc2VyaWYiLAogIDB4ZjZkYiwKICAidHJldHJvZmxleGhvb2siLAogIDB4MDI4OCwKICAidHJpYWdkbiIsCiAgMHgyNWJjLAogICJ0cmlhZ2xmIiwKICAweDI1YzQsCiAgInRyaWFncnQiLAogIDB4MjViYSwKICAidHJpYWd1cCIsCiAgMHgyNWIyLAogICJ0cyIsCiAgMHgwMmE2LAogICJ0c2FkaSIsCiAgMHgwNWU2LAogICJ0c2FkaWRhZ2VzaCIsCiAgMHhmYjQ2LAogICJ0c2FkaWRhZ2VzaGhlYnJldyIsCiAgMHhmYjQ2LAogICJ0c2FkaWhlYnJldyIsCiAgMHgwNWU2LAogICJ0c2VjeXJpbGxpYyIsCiAgMHgwNDQ2LAogICJ0c2VyZSIsCiAgMHgwNWI1LAogICJ0c2VyZTEyIiwKICAweDA1YjUsCiAgInRzZXJlMWUiLAogIDB4MDViNSwKICAidHNlcmUyYiIsCiAgMHgwNWI1LAogICJ0c2VyZWhlYnJldyIsCiAgMHgwNWI1LAogICJ0c2VyZW5hcnJvd2hlYnJldyIsCiAgMHgwNWI1LAogICJ0c2VyZXF1YXJ0ZXJoZWJyZXciLAogIDB4MDViNSwKICAidHNlcmV3aWRlaGVicmV3IiwKICAweDA1YjUsCiAgInRzaGVjeXJpbGxpYyIsCiAgMHgwNDViLAogICJ0c3VwZXJpb3IiLAogIDB4ZjZmMywKICAidHRhYmVuZ2FsaSIsCiAgMHgwOTlmLAogICJ0dGFkZXZhIiwKICAweDA5MWYsCiAgInR0YWd1amFyYXRpIiwKICAweDBhOWYsCiAgInR0YWd1cm11a2hpIiwKICAweDBhMWYsCiAgInR0ZWhhcmFiaWMiLAogIDB4MDY3OSwKICAidHRlaGZpbmFsYXJhYmljIiwKICAweGZiNjcsCiAgInR0ZWhpbml0aWFsYXJhYmljIiwKICAweGZiNjgsCiAgInR0ZWhtZWRpYWxhcmFiaWMiLAogIDB4ZmI2OSwKICAidHRoYWJlbmdhbGkiLAogIDB4MDlhMCwKICAidHRoYWRldmEiLAogIDB4MDkyMCwKICAidHRoYWd1amFyYXRpIiwKICAweDBhYTAsCiAgInR0aGFndXJtdWtoaSIsCiAgMHgwYTIwLAogICJ0dHVybmVkIiwKICAweDAyODcsCiAgInR1aGlyYWdhbmEiLAogIDB4MzA2NCwKICAidHVrYXRha2FuYSIsCiAgMHgzMGM0LAogICJ0dWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmODIsCiAgInR1c21hbGxoaXJhZ2FuYSIsCiAgMHgzMDYzLAogICJ0dXNtYWxsa2F0YWthbmEiLAogIDB4MzBjMywKICAidHVzbWFsbGthdGFrYW5haGFsZndpZHRoIiwKICAweGZmNmYsCiAgInR3ZWx2ZWNpcmNsZSIsCiAgMHgyNDZiLAogICJ0d2VsdmVwYXJlbiIsCiAgMHgyNDdmLAogICJ0d2VsdmVwZXJpb2QiLAogIDB4MjQ5MywKICAidHdlbHZlcm9tYW4iLAogIDB4MjE3YiwKICAidHdlbnR5Y2lyY2xlIiwKICAweDI0NzMsCiAgInR3ZW50eWhhbmd6aG91IiwKICAweDUzNDQsCiAgInR3ZW50eXBhcmVuIiwKICAweDI0ODcsCiAgInR3ZW50eXBlcmlvZCIsCiAgMHgyNDliLAogICJ0d28iLAogIDB4MDAzMiwKICAidHdvYXJhYmljIiwKICAweDA2NjIsCiAgInR3b2JlbmdhbGkiLAogIDB4MDllOCwKICAidHdvY2lyY2xlIiwKICAweDI0NjEsCiAgInR3b2NpcmNsZWludmVyc2VzYW5zc2VyaWYiLAogIDB4Mjc4YiwKICAidHdvZGV2YSIsCiAgMHgwOTY4LAogICJ0d29kb3RlbmxlYWRlciIsCiAgMHgyMDI1LAogICJ0d29kb3RsZWFkZXIiLAogIDB4MjAyNSwKICAidHdvZG90bGVhZGVydmVydGljYWwiLAogIDB4ZmUzMCwKICAidHdvZ3VqYXJhdGkiLAogIDB4MGFlOCwKICAidHdvZ3VybXVraGkiLAogIDB4MGE2OCwKICAidHdvaGFja2FyYWJpYyIsCiAgMHgwNjYyLAogICJ0d29oYW5nemhvdSIsCiAgMHgzMDIyLAogICJ0d29pZGVvZ3JhcGhpY3BhcmVuIiwKICAweDMyMjEsCiAgInR3b2luZmVyaW9yIiwKICAweDIwODIsCiAgInR3b21vbm9zcGFjZSIsCiAgMHhmZjEyLAogICJ0d29udW1lcmF0b3JiZW5nYWxpIiwKICAweDA5ZjUsCiAgInR3b29sZHN0eWxlIiwKICAweGY3MzIsCiAgInR3b3BhcmVuIiwKICAweDI0NzUsCiAgInR3b3BlcmlvZCIsCiAgMHgyNDg5LAogICJ0d29wZXJzaWFuIiwKICAweDA2ZjIsCiAgInR3b3JvbWFuIiwKICAweDIxNzEsCiAgInR3b3N0cm9rZSIsCiAgMHgwMWJiLAogICJ0d29zdXBlcmlvciIsCiAgMHgwMGIyLAogICJ0d290aGFpIiwKICAweDBlNTIsCiAgInR3b3RoaXJkcyIsCiAgMHgyMTU0LAogICJ1IiwKICAweDAwNzUsCiAgInVhY3V0ZSIsCiAgMHgwMGZhLAogICJ1YmFyIiwKICAweDAyODksCiAgInViZW5nYWxpIiwKICAweDA5ODksCiAgInVib3BvbW9mbyIsCiAgMHgzMTI4LAogICJ1YnJldmUiLAogIDB4MDE2ZCwKICAidWNhcm9uIiwKICAweDAxZDQsCiAgInVjaXJjbGUiLAogIDB4MjRlNCwKICAidWNpcmN1bWZsZXgiLAogIDB4MDBmYiwKICAidWNpcmN1bWZsZXhiZWxvdyIsCiAgMHgxZTc3LAogICJ1Y3lyaWxsaWMiLAogIDB4MDQ0MywKICAidWRhdHRhZGV2YSIsCiAgMHgwOTUxLAogICJ1ZGJsYWN1dGUiLAogIDB4MDE3MSwKICAidWRibGdyYXZlIiwKICAweDAyMTUsCiAgInVkZXZhIiwKICAweDA5MDksCiAgInVkaWVyZXNpcyIsCiAgMHgwMGZjLAogICJ1ZGllcmVzaXNhY3V0ZSIsCiAgMHgwMWQ4LAogICJ1ZGllcmVzaXNiZWxvdyIsCiAgMHgxZTczLAogICJ1ZGllcmVzaXNjYXJvbiIsCiAgMHgwMWRhLAogICJ1ZGllcmVzaXNjeXJpbGxpYyIsCiAgMHgwNGYxLAogICJ1ZGllcmVzaXNncmF2ZSIsCiAgMHgwMWRjLAogICJ1ZGllcmVzaXNtYWNyb24iLAogIDB4MDFkNiwKICAidWRvdGJlbG93IiwKICAweDFlZTUsCiAgInVncmF2ZSIsCiAgMHgwMGY5LAogICJ1Z3VqYXJhdGkiLAogIDB4MGE4OSwKICAidWd1cm11a2hpIiwKICAweDBhMDksCiAgInVoaXJhZ2FuYSIsCiAgMHgzMDQ2LAogICJ1aG9va2Fib3ZlIiwKICAweDFlZTcsCiAgInVob3JuIiwKICAweDAxYjAsCiAgInVob3JuYWN1dGUiLAogIDB4MWVlOSwKICAidWhvcm5kb3RiZWxvdyIsCiAgMHgxZWYxLAogICJ1aG9ybmdyYXZlIiwKICAweDFlZWIsCiAgInVob3JuaG9va2Fib3ZlIiwKICAweDFlZWQsCiAgInVob3JudGlsZGUiLAogIDB4MWVlZiwKICAidWh1bmdhcnVtbGF1dCIsCiAgMHgwMTcxLAogICJ1aHVuZ2FydW1sYXV0Y3lyaWxsaWMiLAogIDB4MDRmMywKICAidWludmVydGVkYnJldmUiLAogIDB4MDIxNywKICAidWthdGFrYW5hIiwKICAweDMwYTYsCiAgInVrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjczLAogICJ1a2N5cmlsbGljIiwKICAweDA0NzksCiAgInVrb3JlYW4iLAogIDB4MzE1YywKICAidW1hY3JvbiIsCiAgMHgwMTZiLAogICJ1bWFjcm9uY3lyaWxsaWMiLAogIDB4MDRlZiwKICAidW1hY3JvbmRpZXJlc2lzIiwKICAweDFlN2IsCiAgInVtYXRyYWd1cm11a2hpIiwKICAweDBhNDEsCiAgInVtb25vc3BhY2UiLAogIDB4ZmY1NSwKICAidW5kZXJzY29yZSIsCiAgMHgwMDVmLAogICJ1bmRlcnNjb3JlZGJsIiwKICAweDIwMTcsCiAgInVuZGVyc2NvcmVtb25vc3BhY2UiLAogIDB4ZmYzZiwKICAidW5kZXJzY29yZXZlcnRpY2FsIiwKICAweGZlMzMsCiAgInVuZGVyc2NvcmV3YXZ5IiwKICAweGZlNGYsCiAgInVuaW9uIiwKICAweDIyMmEsCiAgInVuaXZlcnNhbCIsCiAgMHgyMjAwLAogICJ1b2dvbmVrIiwKICAweDAxNzMsCiAgInVwYXJlbiIsCiAgMHgyNGIwLAogICJ1cGJsb2NrIiwKICAweDI1ODAsCiAgInVwcGVyZG90aGVicmV3IiwKICAweDA1YzQsCiAgInVwc2lsb24iLAogIDB4MDNjNSwKICAidXBzaWxvbmRpZXJlc2lzIiwKICAweDAzY2IsCiAgInVwc2lsb25kaWVyZXNpc3Rvbm9zIiwKICAweDAzYjAsCiAgInVwc2lsb25sYXRpbiIsCiAgMHgwMjhhLAogICJ1cHNpbG9udG9ub3MiLAogIDB4MDNjZCwKICAidXB0YWNrYmVsb3djbWIiLAogIDB4MDMxZCwKICAidXB0YWNrbW9kIiwKICAweDAyZDQsCiAgInVyYWd1cm11a2hpIiwKICAweDBhNzMsCiAgInVyaW5nIiwKICAweDAxNmYsCiAgInVzaG9ydGN5cmlsbGljIiwKICAweDA0NWUsCiAgInVzbWFsbGhpcmFnYW5hIiwKICAweDMwNDUsCiAgInVzbWFsbGthdGFrYW5hIiwKICAweDMwYTUsCiAgInVzbWFsbGthdGFrYW5haGFsZndpZHRoIiwKICAweGZmNjksCiAgInVzdHJhaWdodGN5cmlsbGljIiwKICAweDA0YWYsCiAgInVzdHJhaWdodHN0cm9rZWN5cmlsbGljIiwKICAweDA0YjEsCiAgInV0aWxkZSIsCiAgMHgwMTY5LAogICJ1dGlsZGVhY3V0ZSIsCiAgMHgxZTc5LAogICJ1dGlsZGViZWxvdyIsCiAgMHgxZTc1LAogICJ1dWJlbmdhbGkiLAogIDB4MDk4YSwKICAidXVkZXZhIiwKICAweDA5MGEsCiAgInV1Z3VqYXJhdGkiLAogIDB4MGE4YSwKICAidXVndXJtdWtoaSIsCiAgMHgwYTBhLAogICJ1dW1hdHJhZ3VybXVraGkiLAogIDB4MGE0MiwKICAidXV2b3dlbHNpZ25iZW5nYWxpIiwKICAweDA5YzIsCiAgInV1dm93ZWxzaWduZGV2YSIsCiAgMHgwOTQyLAogICJ1dXZvd2Vsc2lnbmd1amFyYXRpIiwKICAweDBhYzIsCiAgInV2b3dlbHNpZ25iZW5nYWxpIiwKICAweDA5YzEsCiAgInV2b3dlbHNpZ25kZXZhIiwKICAweDA5NDEsCiAgInV2b3dlbHNpZ25ndWphcmF0aSIsCiAgMHgwYWMxLAogICJ2IiwKICAweDAwNzYsCiAgInZhZGV2YSIsCiAgMHgwOTM1LAogICJ2YWd1amFyYXRpIiwKICAweDBhYjUsCiAgInZhZ3VybXVraGkiLAogIDB4MGEzNSwKICAidmFrYXRha2FuYSIsCiAgMHgzMGY3LAogICJ2YXYiLAogIDB4MDVkNSwKICAidmF2ZGFnZXNoIiwKICAweGZiMzUsCiAgInZhdmRhZ2VzaDY1IiwKICAweGZiMzUsCiAgInZhdmRhZ2VzaGhlYnJldyIsCiAgMHhmYjM1LAogICJ2YXZoZWJyZXciLAogIDB4MDVkNSwKICAidmF2aG9sYW0iLAogIDB4ZmI0YiwKICAidmF2aG9sYW1oZWJyZXciLAogIDB4ZmI0YiwKICAidmF2dmF2aGVicmV3IiwKICAweDA1ZjAsCiAgInZhdnlvZGhlYnJldyIsCiAgMHgwNWYxLAogICJ2Y2lyY2xlIiwKICAweDI0ZTUsCiAgInZkb3RiZWxvdyIsCiAgMHgxZTdmLAogICJ2ZWN5cmlsbGljIiwKICAweDA0MzIsCiAgInZlaGFyYWJpYyIsCiAgMHgwNmE0LAogICJ2ZWhmaW5hbGFyYWJpYyIsCiAgMHhmYjZiLAogICJ2ZWhpbml0aWFsYXJhYmljIiwKICAweGZiNmMsCiAgInZlaG1lZGlhbGFyYWJpYyIsCiAgMHhmYjZkLAogICJ2ZWthdGFrYW5hIiwKICAweDMwZjksCiAgInZlbnVzIiwKICAweDI2NDAsCiAgInZlcnRpY2FsYmFyIiwKICAweDAwN2MsCiAgInZlcnRpY2FsbGluZWFib3ZlY21iIiwKICAweDAzMGQsCiAgInZlcnRpY2FsbGluZWJlbG93Y21iIiwKICAweDAzMjksCiAgInZlcnRpY2FsbGluZWxvd21vZCIsCiAgMHgwMmNjLAogICJ2ZXJ0aWNhbGxpbmVtb2QiLAogIDB4MDJjOCwKICAidmV3YXJtZW5pYW4iLAogIDB4MDU3ZSwKICAidmhvb2siLAogIDB4MDI4YiwKICAidmlrYXRha2FuYSIsCiAgMHgzMGY4LAogICJ2aXJhbWFiZW5nYWxpIiwKICAweDA5Y2QsCiAgInZpcmFtYWRldmEiLAogIDB4MDk0ZCwKICAidmlyYW1hZ3VqYXJhdGkiLAogIDB4MGFjZCwKICAidmlzYXJnYWJlbmdhbGkiLAogIDB4MDk4MywKICAidmlzYXJnYWRldmEiLAogIDB4MDkwMywKICAidmlzYXJnYWd1amFyYXRpIiwKICAweDBhODMsCiAgInZtb25vc3BhY2UiLAogIDB4ZmY1NiwKICAidm9hcm1lbmlhbiIsCiAgMHgwNTc4LAogICJ2b2ljZWRpdGVyYXRpb25oaXJhZ2FuYSIsCiAgMHgzMDllLAogICJ2b2ljZWRpdGVyYXRpb25rYXRha2FuYSIsCiAgMHgzMGZlLAogICJ2b2ljZWRtYXJra2FuYSIsCiAgMHgzMDliLAogICJ2b2ljZWRtYXJra2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjllLAogICJ2b2thdGFrYW5hIiwKICAweDMwZmEsCiAgInZwYXJlbiIsCiAgMHgyNGIxLAogICJ2dGlsZGUiLAogIDB4MWU3ZCwKICAidnR1cm5lZCIsCiAgMHgwMjhjLAogICJ2dWhpcmFnYW5hIiwKICAweDMwOTQsCiAgInZ1a2F0YWthbmEiLAogIDB4MzBmNCwKICAidyIsCiAgMHgwMDc3LAogICJ3YWN1dGUiLAogIDB4MWU4MywKICAid2Fla29yZWFuIiwKICAweDMxNTksCiAgIndhaGlyYWdhbmEiLAogIDB4MzA4ZiwKICAid2FrYXRha2FuYSIsCiAgMHgzMGVmLAogICJ3YWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmOWMsCiAgIndha29yZWFuIiwKICAweDMxNTgsCiAgIndhc21hbGxoaXJhZ2FuYSIsCiAgMHgzMDhlLAogICJ3YXNtYWxsa2F0YWthbmEiLAogIDB4MzBlZSwKICAid2F0dG9zcXVhcmUiLAogIDB4MzM1NywKICAid2F2ZWRhc2giLAogIDB4MzAxYywKICAid2F2eXVuZGVyc2NvcmV2ZXJ0aWNhbCIsCiAgMHhmZTM0LAogICJ3YXdhcmFiaWMiLAogIDB4MDY0OCwKICAid2F3ZmluYWxhcmFiaWMiLAogIDB4ZmVlZSwKICAid2F3aGFtemFhYm92ZWFyYWJpYyIsCiAgMHgwNjI0LAogICJ3YXdoYW16YWFib3ZlZmluYWxhcmFiaWMiLAogIDB4ZmU4NiwKICAid2JzcXVhcmUiLAogIDB4MzNkZCwKICAid2NpcmNsZSIsCiAgMHgyNGU2LAogICJ3Y2lyY3VtZmxleCIsCiAgMHgwMTc1LAogICJ3ZGllcmVzaXMiLAogIDB4MWU4NSwKICAid2RvdGFjY2VudCIsCiAgMHgxZTg3LAogICJ3ZG90YmVsb3ciLAogIDB4MWU4OSwKICAid2VoaXJhZ2FuYSIsCiAgMHgzMDkxLAogICJ3ZWllcnN0cmFzcyIsCiAgMHgyMTE4LAogICJ3ZWthdGFrYW5hIiwKICAweDMwZjEsCiAgIndla29yZWFuIiwKICAweDMxNWUsCiAgIndlb2tvcmVhbiIsCiAgMHgzMTVkLAogICJ3Z3JhdmUiLAogIDB4MWU4MSwKICAid2hpdGVidWxsZXQiLAogIDB4MjVlNiwKICAid2hpdGVjaXJjbGUiLAogIDB4MjVjYiwKICAid2hpdGVjaXJjbGVpbnZlcnNlIiwKICAweDI1ZDksCiAgIndoaXRlY29ybmVyYnJhY2tldGxlZnQiLAogIDB4MzAwZSwKICAid2hpdGVjb3JuZXJicmFja2V0bGVmdHZlcnRpY2FsIiwKICAweGZlNDMsCiAgIndoaXRlY29ybmVyYnJhY2tldHJpZ2h0IiwKICAweDMwMGYsCiAgIndoaXRlY29ybmVyYnJhY2tldHJpZ2h0dmVydGljYWwiLAogIDB4ZmU0NCwKICAid2hpdGVkaWFtb25kIiwKICAweDI1YzcsCiAgIndoaXRlZGlhbW9uZGNvbnRhaW5pbmdibGFja3NtYWxsZGlhbW9uZCIsCiAgMHgyNWM4LAogICJ3aGl0ZWRvd25wb2ludGluZ3NtYWxsdHJpYW5nbGUiLAogIDB4MjViZiwKICAid2hpdGVkb3ducG9pbnRpbmd0cmlhbmdsZSIsCiAgMHgyNWJkLAogICJ3aGl0ZWxlZnRwb2ludGluZ3NtYWxsdHJpYW5nbGUiLAogIDB4MjVjMywKICAid2hpdGVsZWZ0cG9pbnRpbmd0cmlhbmdsZSIsCiAgMHgyNWMxLAogICJ3aGl0ZWxlbnRpY3VsYXJicmFja2V0bGVmdCIsCiAgMHgzMDE2LAogICJ3aGl0ZWxlbnRpY3VsYXJicmFja2V0cmlnaHQiLAogIDB4MzAxNywKICAid2hpdGVyaWdodHBvaW50aW5nc21hbGx0cmlhbmdsZSIsCiAgMHgyNWI5LAogICJ3aGl0ZXJpZ2h0cG9pbnRpbmd0cmlhbmdsZSIsCiAgMHgyNWI3LAogICJ3aGl0ZXNtYWxsc3F1YXJlIiwKICAweDI1YWIsCiAgIndoaXRlc21pbGluZ2ZhY2UiLAogIDB4MjYzYSwKICAid2hpdGVzcXVhcmUiLAogIDB4MjVhMSwKICAid2hpdGVzdGFyIiwKICAweDI2MDYsCiAgIndoaXRldGVsZXBob25lIiwKICAweDI2MGYsCiAgIndoaXRldG9ydG9pc2VzaGVsbGJyYWNrZXRsZWZ0IiwKICAweDMwMTgsCiAgIndoaXRldG9ydG9pc2VzaGVsbGJyYWNrZXRyaWdodCIsCiAgMHgzMDE5LAogICJ3aGl0ZXVwcG9pbnRpbmdzbWFsbHRyaWFuZ2xlIiwKICAweDI1YjUsCiAgIndoaXRldXBwb2ludGluZ3RyaWFuZ2xlIiwKICAweDI1YjMsCiAgIndpaGlyYWdhbmEiLAogIDB4MzA5MCwKICAid2lrYXRha2FuYSIsCiAgMHgzMGYwLAogICJ3aWtvcmVhbiIsCiAgMHgzMTVmLAogICJ3bW9ub3NwYWNlIiwKICAweGZmNTcsCiAgIndvaGlyYWdhbmEiLAogIDB4MzA5MiwKICAid29rYXRha2FuYSIsCiAgMHgzMGYyLAogICJ3b2thdGFrYW5haGFsZndpZHRoIiwKICAweGZmNjYsCiAgIndvbiIsCiAgMHgyMGE5LAogICJ3b25tb25vc3BhY2UiLAogIDB4ZmZlNiwKICAid293YWVudGhhaSIsCiAgMHgwZTI3LAogICJ3cGFyZW4iLAogIDB4MjRiMiwKICAid3JpbmciLAogIDB4MWU5OCwKICAid3N1cGVyaW9yIiwKICAweDAyYjcsCiAgInd0dXJuZWQiLAogIDB4MDI4ZCwKICAid3lubiIsCiAgMHgwMWJmLAogICJ4IiwKICAweDAwNzgsCiAgInhhYm92ZWNtYiIsCiAgMHgwMzNkLAogICJ4Ym9wb21vZm8iLAogIDB4MzExMiwKICAieGNpcmNsZSIsCiAgMHgyNGU3LAogICJ4ZGllcmVzaXMiLAogIDB4MWU4ZCwKICAieGRvdGFjY2VudCIsCiAgMHgxZThiLAogICJ4ZWhhcm1lbmlhbiIsCiAgMHgwNTZkLAogICJ4aSIsCiAgMHgwM2JlLAogICJ4bW9ub3NwYWNlIiwKICAweGZmNTgsCiAgInhwYXJlbiIsCiAgMHgyNGIzLAogICJ4c3VwZXJpb3IiLAogIDB4MDJlMywKICAieSIsCiAgMHgwMDc5LAogICJ5YWFkb3NxdWFyZSIsCiAgMHgzMzRlLAogICJ5YWJlbmdhbGkiLAogIDB4MDlhZiwKICAieWFjdXRlIiwKICAweDAwZmQsCiAgInlhZGV2YSIsCiAgMHgwOTJmLAogICJ5YWVrb3JlYW4iLAogIDB4MzE1MiwKICAieWFndWphcmF0aSIsCiAgMHgwYWFmLAogICJ5YWd1cm11a2hpIiwKICAweDBhMmYsCiAgInlhaGlyYWdhbmEiLAogIDB4MzA4NCwKICAieWFrYXRha2FuYSIsCiAgMHgzMGU0LAogICJ5YWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmOTQsCiAgInlha29yZWFuIiwKICAweDMxNTEsCiAgInlhbWFra2FudGhhaSIsCiAgMHgwZTRlLAogICJ5YXNtYWxsaGlyYWdhbmEiLAogIDB4MzA4MywKICAieWFzbWFsbGthdGFrYW5hIiwKICAweDMwZTMsCiAgInlhc21hbGxrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjZjLAogICJ5YXRjeXJpbGxpYyIsCiAgMHgwNDYzLAogICJ5Y2lyY2xlIiwKICAweDI0ZTgsCiAgInljaXJjdW1mbGV4IiwKICAweDAxNzcsCiAgInlkaWVyZXNpcyIsCiAgMHgwMGZmLAogICJ5ZG90YWNjZW50IiwKICAweDFlOGYsCiAgInlkb3RiZWxvdyIsCiAgMHgxZWY1LAogICJ5ZWhhcmFiaWMiLAogIDB4MDY0YSwKICAieWVoYmFycmVlYXJhYmljIiwKICAweDA2ZDIsCiAgInllaGJhcnJlZWZpbmFsYXJhYmljIiwKICAweGZiYWYsCiAgInllaGZpbmFsYXJhYmljIiwKICAweGZlZjIsCiAgInllaGhhbXphYWJvdmVhcmFiaWMiLAogIDB4MDYyNiwKICAieWVoaGFtemFhYm92ZWZpbmFsYXJhYmljIiwKICAweGZlOGEsCiAgInllaGhhbXphYWJvdmVpbml0aWFsYXJhYmljIiwKICAweGZlOGIsCiAgInllaGhhbXphYWJvdmVtZWRpYWxhcmFiaWMiLAogIDB4ZmU4YywKICAieWVoaW5pdGlhbGFyYWJpYyIsCiAgMHhmZWYzLAogICJ5ZWhtZWRpYWxhcmFiaWMiLAogIDB4ZmVmNCwKICAieWVobWVlbWluaXRpYWxhcmFiaWMiLAogIDB4ZmNkZCwKICAieWVobWVlbWlzb2xhdGVkYXJhYmljIiwKICAweGZjNTgsCiAgInllaG5vb25maW5hbGFyYWJpYyIsCiAgMHhmYzk0LAogICJ5ZWh0aHJlZWRvdHNiZWxvd2FyYWJpYyIsCiAgMHgwNmQxLAogICJ5ZWtvcmVhbiIsCiAgMHgzMTU2LAogICJ5ZW4iLAogIDB4MDBhNSwKICAieWVubW9ub3NwYWNlIiwKICAweGZmZTUsCiAgInllb2tvcmVhbiIsCiAgMHgzMTU1LAogICJ5ZW9yaW5oaWV1aGtvcmVhbiIsCiAgMHgzMTg2LAogICJ5ZXJhaGJlbnlvbW9oZWJyZXciLAogIDB4MDVhYSwKICAieWVyYWhiZW55b21vbGVmdGhlYnJldyIsCiAgMHgwNWFhLAogICJ5ZXJpY3lyaWxsaWMiLAogIDB4MDQ0YiwKICAieWVydWRpZXJlc2lzY3lyaWxsaWMiLAogIDB4MDRmOSwKICAieWVzaWV1bmdrb3JlYW4iLAogIDB4MzE4MSwKICAieWVzaWV1bmdwYW5zaW9za29yZWFuIiwKICAweDMxODMsCiAgInllc2lldW5nc2lvc2tvcmVhbiIsCiAgMHgzMTgyLAogICJ5ZXRpdmhlYnJldyIsCiAgMHgwNTlhLAogICJ5Z3JhdmUiLAogIDB4MWVmMywKICAieWhvb2siLAogIDB4MDFiNCwKICAieWhvb2thYm92ZSIsCiAgMHgxZWY3LAogICJ5aWFybWVuaWFuIiwKICAweDA1NzUsCiAgInlpY3lyaWxsaWMiLAogIDB4MDQ1NywKICAieWlrb3JlYW4iLAogIDB4MzE2MiwKICAieWlueWFuZyIsCiAgMHgyNjJmLAogICJ5aXduYXJtZW5pYW4iLAogIDB4MDU4MiwKICAieW1vbm9zcGFjZSIsCiAgMHhmZjU5LAogICJ5b2QiLAogIDB4MDVkOSwKICAieW9kZGFnZXNoIiwKICAweGZiMzksCiAgInlvZGRhZ2VzaGhlYnJldyIsCiAgMHhmYjM5LAogICJ5b2RoZWJyZXciLAogIDB4MDVkOSwKICAieW9keW9kaGVicmV3IiwKICAweDA1ZjIsCiAgInlvZHlvZHBhdGFoaGVicmV3IiwKICAweGZiMWYsCiAgInlvaGlyYWdhbmEiLAogIDB4MzA4OCwKICAieW9pa29yZWFuIiwKICAweDMxODksCiAgInlva2F0YWthbmEiLAogIDB4MzBlOCwKICAieW9rYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjk2LAogICJ5b2tvcmVhbiIsCiAgMHgzMTViLAogICJ5b3NtYWxsaGlyYWdhbmEiLAogIDB4MzA4NywKICAieW9zbWFsbGthdGFrYW5hIiwKICAweDMwZTcsCiAgInlvc21hbGxrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjZlLAogICJ5b3RncmVlayIsCiAgMHgwM2YzLAogICJ5b3lhZWtvcmVhbiIsCiAgMHgzMTg4LAogICJ5b3lha29yZWFuIiwKICAweDMxODcsCiAgInlveWFrdGhhaSIsCiAgMHgwZTIyLAogICJ5b3lpbmd0aGFpIiwKICAweDBlMGQsCiAgInlwYXJlbiIsCiAgMHgyNGI0LAogICJ5cG9nZWdyYW1tZW5pIiwKICAweDAzN2EsCiAgInlwb2dlZ3JhbW1lbmlncmVla2NtYiIsCiAgMHgwMzQ1LAogICJ5ciIsCiAgMHgwMWE2LAogICJ5cmluZyIsCiAgMHgxZTk5LAogICJ5c3VwZXJpb3IiLAogIDB4MDJiOCwKICAieXRpbGRlIiwKICAweDFlZjksCiAgInl0dXJuZWQiLAogIDB4MDI4ZSwKICAieXVoaXJhZ2FuYSIsCiAgMHgzMDg2LAogICJ5dWlrb3JlYW4iLAogIDB4MzE4YywKICAieXVrYXRha2FuYSIsCiAgMHgzMGU2LAogICJ5dWthdGFrYW5haGFsZndpZHRoIiwKICAweGZmOTUsCiAgInl1a29yZWFuIiwKICAweDMxNjAsCiAgInl1c2JpZ2N5cmlsbGljIiwKICAweDA0NmIsCiAgInl1c2JpZ2lvdGlmaWVkY3lyaWxsaWMiLAogIDB4MDQ2ZCwKICAieXVzbGl0dGxlY3lyaWxsaWMiLAogIDB4MDQ2NywKICAieXVzbGl0dGxlaW90aWZpZWRjeXJpbGxpYyIsCiAgMHgwNDY5LAogICJ5dXNtYWxsaGlyYWdhbmEiLAogIDB4MzA4NSwKICAieXVzbWFsbGthdGFrYW5hIiwKICAweDMwZTUsCiAgInl1c21hbGxrYXRha2FuYWhhbGZ3aWR0aCIsCiAgMHhmZjZkLAogICJ5dXlla29yZWFuIiwKICAweDMxOGIsCiAgInl1eWVva29yZWFuIiwKICAweDMxOGEsCiAgInl5YWJlbmdhbGkiLAogIDB4MDlkZiwKICAieXlhZGV2YSIsCiAgMHgwOTVmLAogICJ6IiwKICAweDAwN2EsCiAgInphYXJtZW5pYW4iLAogIDB4MDU2NiwKICAiemFjdXRlIiwKICAweDAxN2EsCiAgInphZGV2YSIsCiAgMHgwOTViLAogICJ6YWd1cm11a2hpIiwKICAweDBhNWIsCiAgInphaGFyYWJpYyIsCiAgMHgwNjM4LAogICJ6YWhmaW5hbGFyYWJpYyIsCiAgMHhmZWM2LAogICJ6YWhpbml0aWFsYXJhYmljIiwKICAweGZlYzcsCiAgInphaGlyYWdhbmEiLAogIDB4MzA1NiwKICAiemFobWVkaWFsYXJhYmljIiwKICAweGZlYzgsCiAgInphaW5hcmFiaWMiLAogIDB4MDYzMiwKICAiemFpbmZpbmFsYXJhYmljIiwKICAweGZlYjAsCiAgInpha2F0YWthbmEiLAogIDB4MzBiNiwKICAiemFxZWZnYWRvbGhlYnJldyIsCiAgMHgwNTk1LAogICJ6YXFlZnFhdGFuaGVicmV3IiwKICAweDA1OTQsCiAgInphcnFhaGVicmV3IiwKICAweDA1OTgsCiAgInpheWluIiwKICAweDA1ZDYsCiAgInpheWluZGFnZXNoIiwKICAweGZiMzYsCiAgInpheWluZGFnZXNoaGVicmV3IiwKICAweGZiMzYsCiAgInpheWluaGVicmV3IiwKICAweDA1ZDYsCiAgInpib3BvbW9mbyIsCiAgMHgzMTE3LAogICJ6Y2Fyb24iLAogIDB4MDE3ZSwKICAiemNpcmNsZSIsCiAgMHgyNGU5LAogICJ6Y2lyY3VtZmxleCIsCiAgMHgxZTkxLAogICJ6Y3VybCIsCiAgMHgwMjkxLAogICJ6ZG90IiwKICAweDAxN2MsCiAgInpkb3RhY2NlbnQiLAogIDB4MDE3YywKICAiemRvdGJlbG93IiwKICAweDFlOTMsCiAgInplY3lyaWxsaWMiLAogIDB4MDQzNywKICAiemVkZXNjZW5kZXJjeXJpbGxpYyIsCiAgMHgwNDk5LAogICJ6ZWRpZXJlc2lzY3lyaWxsaWMiLAogIDB4MDRkZiwKICAiemVoaXJhZ2FuYSIsCiAgMHgzMDVjLAogICJ6ZWthdGFrYW5hIiwKICAweDMwYmMsCiAgInplcm8iLAogIDB4MDAzMCwKICAiemVyb2FyYWJpYyIsCiAgMHgwNjYwLAogICJ6ZXJvYmVuZ2FsaSIsCiAgMHgwOWU2LAogICJ6ZXJvZGV2YSIsCiAgMHgwOTY2LAogICJ6ZXJvZ3VqYXJhdGkiLAogIDB4MGFlNiwKICAiemVyb2d1cm11a2hpIiwKICAweDBhNjYsCiAgInplcm9oYWNrYXJhYmljIiwKICAweDA2NjAsCiAgInplcm9pbmZlcmlvciIsCiAgMHgyMDgwLAogICJ6ZXJvbW9ub3NwYWNlIiwKICAweGZmMTAsCiAgInplcm9vbGRzdHlsZSIsCiAgMHhmNzMwLAogICJ6ZXJvcGVyc2lhbiIsCiAgMHgwNmYwLAogICJ6ZXJvc3VwZXJpb3IiLAogIDB4MjA3MCwKICAiemVyb3RoYWkiLAogIDB4MGU1MCwKICAiemVyb3dpZHRoam9pbmVyIiwKICAweGZlZmYsCiAgInplcm93aWR0aG5vbmpvaW5lciIsCiAgMHgyMDBjLAogICJ6ZXJvd2lkdGhzcGFjZSIsCiAgMHgyMDBiLAogICJ6ZXRhIiwKICAweDAzYjYsCiAgInpoYm9wb21vZm8iLAogIDB4MzExMywKICAiemhlYXJtZW5pYW4iLAogIDB4MDU2YSwKICAiemhlYnJldmVjeXJpbGxpYyIsCiAgMHgwNGMyLAogICJ6aGVjeXJpbGxpYyIsCiAgMHgwNDM2LAogICJ6aGVkZXNjZW5kZXJjeXJpbGxpYyIsCiAgMHgwNDk3LAogICJ6aGVkaWVyZXNpc2N5cmlsbGljIiwKICAweDA0ZGQsCiAgInppaGlyYWdhbmEiLAogIDB4MzA1OCwKICAiemlrYXRha2FuYSIsCiAgMHgzMGI4LAogICJ6aW5vcmhlYnJldyIsCiAgMHgwNWFlLAogICJ6bGluZWJlbG93IiwKICAweDFlOTUsCiAgInptb25vc3BhY2UiLAogIDB4ZmY1YSwKICAiem9oaXJhZ2FuYSIsCiAgMHgzMDVlLAogICJ6b2thdGFrYW5hIiwKICAweDMwYmUsCiAgInpwYXJlbiIsCiAgMHgyNGI1LAogICJ6cmV0cm9mbGV4aG9vayIsCiAgMHgwMjkwLAogICJ6c3Ryb2tlIiwKICAweDAxYjYsCiAgInp1aGlyYWdhbmEiLAogIDB4MzA1YSwKICAienVrYXRha2FuYSIsCiAgMHgzMGJhLAogICIubm90ZGVmIiwKICAweDAwMDAsCiAgImFuZ2JyYWNrZXRsZWZ0YmlnIiwKICAweDIzMjksCiAgImFuZ2JyYWNrZXRsZWZ0QmlnIiwKICAweDIzMjksCiAgImFuZ2JyYWNrZXRsZWZ0YmlnZyIsCiAgMHgyMzI5LAogICJhbmdicmFja2V0bGVmdEJpZ2ciLAogIDB4MjMyOSwKICAiYW5nYnJhY2tldHJpZ2h0QmlnIiwKICAweDIzMmEsCiAgImFuZ2JyYWNrZXRyaWdodGJpZyIsCiAgMHgyMzJhLAogICJhbmdicmFja2V0cmlnaHRCaWdnIiwKICAweDIzMmEsCiAgImFuZ2JyYWNrZXRyaWdodGJpZ2ciLAogIDB4MjMyYSwKICAiYXJyb3dob29rbGVmdCIsCiAgMHgyMWFhLAogICJhcnJvd2hvb2tyaWdodCIsCiAgMHgyMWE5LAogICJhcnJvd2xlZnR0b3BoYWxmIiwKICAweDIxYmMsCiAgImFycm93bGVmdGJvdGhhbGYiLAogIDB4MjFiZCwKICAiYXJyb3dub3J0aGVhc3QiLAogIDB4MjE5NywKICAiYXJyb3dub3J0aHdlc3QiLAogIDB4MjE5NiwKICAiYXJyb3dyaWdodHRvcGhhbGYiLAogIDB4MjFjMCwKICAiYXJyb3dyaWdodGJvdGhhbGYiLAogIDB4MjFjMSwKICAiYXJyb3dzb3V0aGVhc3QiLAogIDB4MjE5OCwKICAiYXJyb3dzb3V0aHdlc3QiLAogIDB4MjE5OSwKICAiYmFja3NsYXNoYmlnIiwKICAweDIyMTYsCiAgImJhY2tzbGFzaEJpZyIsCiAgMHgyMjE2LAogICJiYWNrc2xhc2hCaWdnIiwKICAweDIyMTYsCiAgImJhY2tzbGFzaGJpZ2ciLAogIDB4MjIxNiwKICAiYmFyZGJsIiwKICAweDIwMTYsCiAgImJyYWNlaHRpcGRvd25sZWZ0IiwKICAweGZlMzcsCiAgImJyYWNlaHRpcGRvd25yaWdodCIsCiAgMHhmZTM3LAogICJicmFjZWh0aXB1cGxlZnQiLAogIDB4ZmUzOCwKICAiYnJhY2VodGlwdXByaWdodCIsCiAgMHhmZTM4LAogICJicmFjZWxlZnRCaWciLAogIDB4MDA3YiwKICAiYnJhY2VsZWZ0YmlnIiwKICAweDAwN2IsCiAgImJyYWNlbGVmdGJpZ2ciLAogIDB4MDA3YiwKICAiYnJhY2VsZWZ0QmlnZyIsCiAgMHgwMDdiLAogICJicmFjZXJpZ2h0QmlnIiwKICAweDAwN2QsCiAgImJyYWNlcmlnaHRiaWciLAogIDB4MDA3ZCwKICAiYnJhY2VyaWdodGJpZ2ciLAogIDB4MDA3ZCwKICAiYnJhY2VyaWdodEJpZ2ciLAogIDB4MDA3ZCwKICAiYnJhY2tldGxlZnRiaWciLAogIDB4MDA1YiwKICAiYnJhY2tldGxlZnRCaWciLAogIDB4MDA1YiwKICAiYnJhY2tldGxlZnRiaWdnIiwKICAweDAwNWIsCiAgImJyYWNrZXRsZWZ0QmlnZyIsCiAgMHgwMDViLAogICJicmFja2V0cmlnaHRCaWciLAogIDB4MDA1ZCwKICAiYnJhY2tldHJpZ2h0YmlnIiwKICAweDAwNWQsCiAgImJyYWNrZXRyaWdodGJpZ2ciLAogIDB4MDA1ZCwKICAiYnJhY2tldHJpZ2h0QmlnZyIsCiAgMHgwMDVkLAogICJjZWlsaW5nbGVmdGJpZyIsCiAgMHgyMzA4LAogICJjZWlsaW5nbGVmdEJpZyIsCiAgMHgyMzA4LAogICJjZWlsaW5nbGVmdEJpZ2ciLAogIDB4MjMwOCwKICAiY2VpbGluZ2xlZnRiaWdnIiwKICAweDIzMDgsCiAgImNlaWxpbmdyaWdodGJpZyIsCiAgMHgyMzA5LAogICJjZWlsaW5ncmlnaHRCaWciLAogIDB4MjMwOSwKICAiY2VpbGluZ3JpZ2h0YmlnZyIsCiAgMHgyMzA5LAogICJjZWlsaW5ncmlnaHRCaWdnIiwKICAweDIzMDksCiAgImNpcmNsZWRvdGRpc3BsYXkiLAogIDB4MjI5OSwKICAiY2lyY2xlZG90dGV4dCIsCiAgMHgyMjk5LAogICJjaXJjbGVtdWx0aXBseWRpc3BsYXkiLAogIDB4MjI5NywKICAiY2lyY2xlbXVsdGlwbHl0ZXh0IiwKICAweDIyOTcsCiAgImNpcmNsZXBsdXNkaXNwbGF5IiwKICAweDIyOTUsCiAgImNpcmNsZXBsdXN0ZXh0IiwKICAweDIyOTUsCiAgImNvbnRpbnRlZ3JhbGRpc3BsYXkiLAogIDB4MjIyZSwKICAiY29udGludGVncmFsdGV4dCIsCiAgMHgyMjJlLAogICJjb3Byb2R1Y3RkaXNwbGF5IiwKICAweDIyMTAsCiAgImNvcHJvZHVjdHRleHQiLAogIDB4MjIxMCwKICAiZmxvb3JsZWZ0QmlnIiwKICAweDIzMGEsCiAgImZsb29ybGVmdGJpZyIsCiAgMHgyMzBhLAogICJmbG9vcmxlZnRiaWdnIiwKICAweDIzMGEsCiAgImZsb29ybGVmdEJpZ2ciLAogIDB4MjMwYSwKICAiZmxvb3JyaWdodGJpZyIsCiAgMHgyMzBiLAogICJmbG9vcnJpZ2h0QmlnIiwKICAweDIzMGIsCiAgImZsb29ycmlnaHRCaWdnIiwKICAweDIzMGIsCiAgImZsb29ycmlnaHRiaWdnIiwKICAweDIzMGIsCiAgImhhdHdpZGUiLAogIDB4MDMwMiwKICAiaGF0d2lkZXIiLAogIDB4MDMwMiwKICAiaGF0d2lkZXN0IiwKICAweDAzMDIsCiAgImludGVyY2FsIiwKICAweDFkNDAsCiAgImludGVncmFsZGlzcGxheSIsCiAgMHgyMjJiLAogICJpbnRlZ3JhbHRleHQiLAogIDB4MjIyYiwKICAiaW50ZXJzZWN0aW9uZGlzcGxheSIsCiAgMHgyMmMyLAogICJpbnRlcnNlY3Rpb250ZXh0IiwKICAweDIyYzIsCiAgImxvZ2ljYWxhbmRkaXNwbGF5IiwKICAweDIyMjcsCiAgImxvZ2ljYWxhbmR0ZXh0IiwKICAweDIyMjcsCiAgImxvZ2ljYWxvcmRpc3BsYXkiLAogIDB4MjIyOCwKICAibG9naWNhbG9ydGV4dCIsCiAgMHgyMjI4LAogICJwYXJlbmxlZnRCaWciLAogIDB4MDAyOCwKICAicGFyZW5sZWZ0YmlnIiwKICAweDAwMjgsCiAgInBhcmVubGVmdEJpZ2ciLAogIDB4MDAyOCwKICAicGFyZW5sZWZ0YmlnZyIsCiAgMHgwMDI4LAogICJwYXJlbnJpZ2h0QmlnIiwKICAweDAwMjksCiAgInBhcmVucmlnaHRiaWciLAogIDB4MDAyOSwKICAicGFyZW5yaWdodEJpZ2ciLAogIDB4MDAyOSwKICAicGFyZW5yaWdodGJpZ2ciLAogIDB4MDAyOSwKICAicHJpbWUiLAogIDB4MjAzMiwKICAicHJvZHVjdGRpc3BsYXkiLAogIDB4MjIwZiwKICAicHJvZHVjdHRleHQiLAogIDB4MjIwZiwKICAicmFkaWNhbGJpZyIsCiAgMHgyMjFhLAogICJyYWRpY2FsQmlnIiwKICAweDIyMWEsCiAgInJhZGljYWxCaWdnIiwKICAweDIyMWEsCiAgInJhZGljYWxiaWdnIiwKICAweDIyMWEsCiAgInJhZGljYWxidCIsCiAgMHgyMjFhLAogICJyYWRpY2FsdHAiLAogIDB4MjIxYSwKICAicmFkaWNhbHZlcnRleCIsCiAgMHgyMjFhLAogICJzbGFzaGJpZyIsCiAgMHgwMDJmLAogICJzbGFzaEJpZyIsCiAgMHgwMDJmLAogICJzbGFzaEJpZ2ciLAogIDB4MDAyZiwKICAic2xhc2hiaWdnIiwKICAweDAwMmYsCiAgInN1bW1hdGlvbmRpc3BsYXkiLAogIDB4MjIxMSwKICAic3VtbWF0aW9udGV4dCIsCiAgMHgyMjExLAogICJ0aWxkZXdpZGUiLAogIDB4MDJkYywKICAidGlsZGV3aWRlciIsCiAgMHgwMmRjLAogICJ0aWxkZXdpZGVzdCIsCiAgMHgwMmRjLAogICJ1bmlvbmRpc3BsYXkiLAogIDB4MjJjMywKICAidW5pb25tdWx0aWRpc3BsYXkiLAogIDB4MjI4ZSwKICAidW5pb25tdWx0aXRleHQiLAogIDB4MjI4ZSwKICAidW5pb25zcWRpc3BsYXkiLAogIDB4MjI5NCwKICAidW5pb25zcXRleHQiLAogIDB4MjI5NCwKICAidW5pb250ZXh0IiwKICAweDIyYzMsCiAgInZleHRlbmRkb3VibGUiLAogIDB4MjIyNSwKICAidmV4dGVuZHNpbmdsZSIsCiAgMHgyMjIzCiBdOwp9KTsKY29uc3QgZ2V0RGluZ2JhdHNHbHlwaHNVbmljb2RlID0gKDAsX2NvcmVfdXRpbHNfanNfX1dFQlBBQ0tfSU1QT1JURURfTU9EVUxFXzBfXy5nZXRBcnJheUxvb2t1cFRhYmxlRmFjdG9yeSkoZnVuY3Rpb24gKCkgewogcmV0dXJuIFsKICAic3BhY2UiLAogIDB4MDAyMCwKICAiYTEiLAogIDB4MjcwMSwKICAiYTIiLAogIDB4MjcwMiwKICAiYTIwMiIsCiAgMHgyNzAzLAogICJhMyIsCiAgMHgyNzA0LAogICJhNCIsCiAgMHgyNjBlLAogICJhNSIsCiAgMHgyNzA2LAogICJhMTE5IiwKICAweDI3MDcsCiAgImExMTgiLAogIDB4MjcwOCwKICAiYTExNyIsCiAgMHgyNzA5LAogICJhMTEiLAogIDB4MjYxYiwKICAiYTEyIiwKICAweDI2MWUsCiAgImExMyIsCiAgMHgyNzBjLAogICJhMTQiLAogIDB4MjcwZCwKICAiYTE1IiwKICAweDI3MGUsCiAgImExNiIsCiAgMHgyNzBmLAogICJhMTA1IiwKICAweDI3MTAsCiAgImExNyIsCiAgMHgyNzExLAogICJhMTgiLAogIDB4MjcxMiwKICAiYTE5IiwKICAweDI3MTMsCiAgImEyMCIsCiAgMHgyNzE0LAogICJhMjEiLAogIDB4MjcxNSwKICAiYTIyIiwKICAweDI3MTYsCiAgImEyMyIsCiAgMHgyNzE3LAogICJhMjQiLAogIDB4MjcxOCwKICAiYTI1IiwKICAweDI3MTksCiAgImEyNiIsCiAgMHgyNzFhLAogICJhMjciLAogIDB4MjcxYiwKICAiYTI4IiwKICAweDI3MWMsCiAgImE2IiwKICAweDI3MWQsCiAgImE3IiwKICAweDI3MWUsCiAgImE4IiwKICAweDI3MWYsCiAgImE5IiwKICAweDI3MjAsCiAgImExMCIsCiAgMHgyNzIxLAogICJhMjkiLAogIDB4MjcyMiwKICAiYTMwIiwKICAweDI3MjMsCiAgImEzMSIsCiAgMHgyNzI0LAogICJhMzIiLAogIDB4MjcyNSwKICAiYTMzIiwKICAweDI3MjYsCiAgImEzNCIsCiAgMHgyNzI3LAogICJhMzUiLAogIDB4MjYwNSwKICAiYTM2IiwKICAweDI3MjksCiAgImEzNyIsCiAgMHgyNzJhLAogICJhMzgiLAogIDB4MjcyYiwKICAiYTM5IiwKICAweDI3MmMsCiAgImE0MCIsCiAgMHgyNzJkLAogICJhNDEiLAogIDB4MjcyZSwKICAiYTQyIiwKICAweDI3MmYsCiAgImE0MyIsCiAgMHgyNzMwLAogICJhNDQiLAogIDB4MjczMSwKICAiYTQ1IiwKICAweDI3MzIsCiAgImE0NiIsCiAgMHgyNzMzLAogICJhNDciLAogIDB4MjczNCwKICAiYTQ4IiwKICAweDI3MzUsCiAgImE0OSIsCiAgMHgyNzM2LAogICJhNTAiLAogIDB4MjczNywKICAiYTUxIiwKICAweDI3MzgsCiAgImE1MiIsCiAgMHgyNzM5LAogICJhNTMiLAogIDB4MjczYSwKICAiYTU0IiwKICAweDI3M2IsCiAgImE1NSIsCiAgMHgyNzNjLAogICJhNTYiLAogIDB4MjczZCwKICAiYTU3IiwKICAweDI3M2UsCiAgImE1OCIsCiAgMHgyNzNmLAogICJhNTkiLAogIDB4Mjc0MCwKICAiYTYwIiwKICAweDI3NDEsCiAgImE2MSIsCiAgMHgyNzQyLAogICJhNjIiLAogIDB4Mjc0MywKICAiYTYzIiwKICAweDI3NDQsCiAgImE2NCIsCiAgMHgyNzQ1LAogICJhNjUiLAogIDB4Mjc0NiwKICAiYTY2IiwKICAweDI3NDcsCiAgImE2NyIsCiAgMHgyNzQ4LAogICJhNjgiLAogIDB4Mjc0OSwKICAiYTY5IiwKICAweDI3NGEsCiAgImE3MCIsCiAgMHgyNzRiLAogICJhNzEiLAogIDB4MjVjZiwKICAiYTcyIiwKICAweDI3NGQsCiAgImE3MyIsCiAgMHgyNWEwLAogICJhNzQiLAogIDB4Mjc0ZiwKICAiYTIwMyIsCiAgMHgyNzUwLAogICJhNzUiLAogIDB4Mjc1MSwKICAiYTIwNCIsCiAgMHgyNzUyLAogICJhNzYiLAogIDB4MjViMiwKICAiYTc3IiwKICAweDI1YmMsCiAgImE3OCIsCiAgMHgyNWM2LAogICJhNzkiLAogIDB4Mjc1NiwKICAiYTgxIiwKICAweDI1ZDcsCiAgImE4MiIsCiAgMHgyNzU4LAogICJhODMiLAogIDB4Mjc1OSwKICAiYTg0IiwKICAweDI3NWEsCiAgImE5NyIsCiAgMHgyNzViLAogICJhOTgiLAogIDB4Mjc1YywKICAiYTk5IiwKICAweDI3NWQsCiAgImExMDAiLAogIDB4Mjc1ZSwKICAiYTEwMSIsCiAgMHgyNzYxLAogICJhMTAyIiwKICAweDI3NjIsCiAgImExMDMiLAogIDB4Mjc2MywKICAiYTEwNCIsCiAgMHgyNzY0LAogICJhMTA2IiwKICAweDI3NjUsCiAgImExMDciLAogIDB4Mjc2NiwKICAiYTEwOCIsCiAgMHgyNzY3LAogICJhMTEyIiwKICAweDI2NjMsCiAgImExMTEiLAogIDB4MjY2NiwKICAiYTExMCIsCiAgMHgyNjY1LAogICJhMTA5IiwKICAweDI2NjAsCiAgImExMjAiLAogIDB4MjQ2MCwKICAiYTEyMSIsCiAgMHgyNDYxLAogICJhMTIyIiwKICAweDI0NjIsCiAgImExMjMiLAogIDB4MjQ2MywKICAiYTEyNCIsCiAgMHgyNDY0LAogICJhMTI1IiwKICAweDI0NjUsCiAgImExMjYiLAogIDB4MjQ2NiwKICAiYTEyNyIsCiAgMHgyNDY3LAogICJhMTI4IiwKICAweDI0NjgsCiAgImExMjkiLAogIDB4MjQ2OSwKICAiYTEzMCIsCiAgMHgyNzc2LAogICJhMTMxIiwKICAweDI3NzcsCiAgImExMzIiLAogIDB4Mjc3OCwKICAiYTEzMyIsCiAgMHgyNzc5LAogICJhMTM0IiwKICAweDI3N2EsCiAgImExMzUiLAogIDB4Mjc3YiwKICAiYTEzNiIsCiAgMHgyNzdjLAogICJhMTM3IiwKICAweDI3N2QsCiAgImExMzgiLAogIDB4Mjc3ZSwKICAiYTEzOSIsCiAgMHgyNzdmLAogICJhMTQwIiwKICAweDI3ODAsCiAgImExNDEiLAogIDB4Mjc4MSwKICAiYTE0MiIsCiAgMHgyNzgyLAogICJhMTQzIiwKICAweDI3ODMsCiAgImExNDQiLAogIDB4Mjc4NCwKICAiYTE0NSIsCiAgMHgyNzg1LAogICJhMTQ2IiwKICAweDI3ODYsCiAgImExNDciLAogIDB4Mjc4NywKICAiYTE0OCIsCiAgMHgyNzg4LAogICJhMTQ5IiwKICAweDI3ODksCiAgImExNTAiLAogIDB4Mjc4YSwKICAiYTE1MSIsCiAgMHgyNzhiLAogICJhMTUyIiwKICAweDI3OGMsCiAgImExNTMiLAogIDB4Mjc4ZCwKICAiYTE1NCIsCiAgMHgyNzhlLAogICJhMTU1IiwKICAweDI3OGYsCiAgImExNTYiLAogIDB4Mjc5MCwKICAiYTE1NyIsCiAgMHgyNzkxLAogICJhMTU4IiwKICAweDI3OTIsCiAgImExNTkiLAogIDB4Mjc5MywKICAiYTE2MCIsCiAgMHgyNzk0LAogICJhMTYxIiwKICAweDIxOTIsCiAgImExNjMiLAogIDB4MjE5NCwKICAiYTE2NCIsCiAgMHgyMTk1LAogICJhMTk2IiwKICAweDI3OTgsCiAgImExNjUiLAogIDB4Mjc5OSwKICAiYTE5MiIsCiAgMHgyNzlhLAogICJhMTY2IiwKICAweDI3OWIsCiAgImExNjciLAogIDB4Mjc5YywKICAiYTE2OCIsCiAgMHgyNzlkLAogICJhMTY5IiwKICAweDI3OWUsCiAgImExNzAiLAogIDB4Mjc5ZiwKICAiYTE3MSIsCiAgMHgyN2EwLAogICJhMTcyIiwKICAweDI3YTEsCiAgImExNzMiLAogIDB4MjdhMiwKICAiYTE2MiIsCiAgMHgyN2EzLAogICJhMTc0IiwKICAweDI3YTQsCiAgImExNzUiLAogIDB4MjdhNSwKICAiYTE3NiIsCiAgMHgyN2E2LAogICJhMTc3IiwKICAweDI3YTcsCiAgImExNzgiLAogIDB4MjdhOCwKICAiYTE3OSIsCiAgMHgyN2E5LAogICJhMTkzIiwKICAweDI3YWEsCiAgImExODAiLAogIDB4MjdhYiwKICAiYTE5OSIsCiAgMHgyN2FjLAogICJhMTgxIiwKICAweDI3YWQsCiAgImEyMDAiLAogIDB4MjdhZSwKICAiYTE4MiIsCiAgMHgyN2FmLAogICJhMjAxIiwKICAweDI3YjEsCiAgImExODMiLAogIDB4MjdiMiwKICAiYTE4NCIsCiAgMHgyN2IzLAogICJhMTk3IiwKICAweDI3YjQsCiAgImExODUiLAogIDB4MjdiNSwKICAiYTE5NCIsCiAgMHgyN2I2LAogICJhMTk4IiwKICAweDI3YjcsCiAgImExODYiLAogIDB4MjdiOCwKICAiYTE5NSIsCiAgMHgyN2I5LAogICJhMTg3IiwKICAweDI3YmEsCiAgImExODgiLAogIDB4MjdiYiwKICAiYTE4OSIsCiAgMHgyN2JjLAogICJhMTkwIiwKICAweDI3YmQsCiAgImExOTEiLAogIDB4MjdiZSwKICAiYTg5IiwKICAweDI3NjgsCiAgImE5MCIsCiAgMHgyNzY5LAogICJhOTMiLAogIDB4Mjc2YSwKICAiYTk0IiwKICAweDI3NmIsCiAgImE5MSIsCiAgMHgyNzZjLAogICJhOTIiLAogIDB4Mjc2ZCwKICAiYTIwNSIsCiAgMHgyNzZlLAogICJhODUiLAogIDB4Mjc2ZiwKICAiYTIwNiIsCiAgMHgyNzcwLAogICJhODYiLAogIDB4Mjc3MSwKICAiYTg3IiwKICAweDI3NzIsCiAgImE4OCIsCiAgMHgyNzczLAogICJhOTUiLAogIDB4Mjc3NCwKICAiYTk2IiwKICAweDI3NzUsCiAgIi5ub3RkZWYiLAogIDB4MDAwMAogXTsKfSk7CgoKLyoqKi8gfSksCi8qIDE3NSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3dlYnBhY2tfZXhwb3J0c19fLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7Cl9fd19wZGZqc19yZXF1aXJlX18ucihfX3dlYnBhY2tfZXhwb3J0c19fKTsKLyogaGFybW9ueSBleHBvcnQgKi8gX193X3BkZmpzX3JlcXVpcmVfXy5kKF9fd2VicGFja19leHBvcnRzX18sIHsKLyogaGFybW9ueSBleHBvcnQgKi8gICAiY2xlYXJVbmljb2RlQ2FjaGVzIjogKCkgPT4gKC8qIGJpbmRpbmcgKi8gY2xlYXJVbmljb2RlQ2FjaGVzKSwKLyogaGFybW9ueSBleHBvcnQgKi8gICAiZ2V0Q2hhclVuaWNvZGVDYXRlZ29yeSI6ICgpID0+ICgvKiBiaW5kaW5nICovIGdldENoYXJVbmljb2RlQ2F0ZWdvcnkpLAovKiBoYXJtb255IGV4cG9ydCAqLyAgICJnZXROb3JtYWxpemVkVW5pY29kZXMiOiAoKSA9PiAoLyogYmluZGluZyAqLyBnZXROb3JtYWxpemVkVW5pY29kZXMpLAovKiBoYXJtb255IGV4cG9ydCAqLyAgICJnZXRVbmljb2RlRm9yR2x5cGgiOiAoKSA9PiAoLyogYmluZGluZyAqLyBnZXRVbmljb2RlRm9yR2x5cGgpLAovKiBoYXJtb255IGV4cG9ydCAqLyAgICJnZXRVbmljb2RlUmFuZ2VGb3IiOiAoKSA9PiAoLyogYmluZGluZyAqLyBnZXRVbmljb2RlUmFuZ2VGb3IpLAovKiBoYXJtb255IGV4cG9ydCAqLyAgICJtYXBTcGVjaWFsVW5pY29kZVZhbHVlcyI6ICgpID0+ICgvKiBiaW5kaW5nICovIG1hcFNwZWNpYWxVbmljb2RlVmFsdWVzKSwKLyogaGFybW9ueSBleHBvcnQgKi8gICAicmV2ZXJzZUlmUnRsIjogKCkgPT4gKC8qIGJpbmRpbmcgKi8gcmV2ZXJzZUlmUnRsKQovKiBoYXJtb255IGV4cG9ydCAqLyB9KTsKLyogaGFybW9ueSBpbXBvcnQgKi8gdmFyIF9jb3JlX3V0aWxzX2pzX19XRUJQQUNLX0lNUE9SVEVEX01PRFVMRV8wX18gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzOSk7Cgpjb25zdCBnZXRTcGVjaWFsUFVBU3ltYm9scyA9ICgwLF9jb3JlX3V0aWxzX2pzX19XRUJQQUNLX0lNUE9SVEVEX01PRFVMRV8wX18uZ2V0TG9va3VwVGFibGVGYWN0b3J5KShmdW5jdGlvbiAodCkgewogdFs2MzcyMV0gPSAweDAwYTk7CiB0WzYzMTkzXSA9IDB4MDBhOTsKIHRbNjM3MjBdID0gMHgwMGFlOwogdFs2MzE5NF0gPSAweDAwYWU7CiB0WzYzNzIyXSA9IDB4MjEyMjsKIHRbNjMxOTVdID0gMHgyMTIyOwogdFs2MzcyOV0gPSAweDIzYTc7CiB0WzYzNzMwXSA9IDB4MjNhODsKIHRbNjM3MzFdID0gMHgyM2E5OwogdFs2Mzc0MF0gPSAweDIzYWI7CiB0WzYzNzQxXSA9IDB4MjNhYzsKIHRbNjM3NDJdID0gMHgyM2FkOwogdFs2MzcyNl0gPSAweDIzYTE7CiB0WzYzNzI3XSA9IDB4MjNhMjsKIHRbNjM3MjhdID0gMHgyM2EzOwogdFs2MzczN10gPSAweDIzYTQ7CiB0WzYzNzM4XSA9IDB4MjNhNTsKIHRbNjM3MzldID0gMHgyM2E2OwogdFs2MzcyM10gPSAweDIzOWI7CiB0WzYzNzI0XSA9IDB4MjM5YzsKIHRbNjM3MjVdID0gMHgyMzlkOwogdFs2MzczNF0gPSAweDIzOWU7CiB0WzYzNzM1XSA9IDB4MjM5ZjsKIHRbNjM3MzZdID0gMHgyM2EwOwp9KTsKZnVuY3Rpb24gbWFwU3BlY2lhbFVuaWNvZGVWYWx1ZXMoY29kZSkgewogaWYgKGNvZGUgPj0gMHhmZmYwICYmIGNvZGUgPD0gMHhmZmZmKSB7CiAgcmV0dXJuIDA7CiB9IGVsc2UgaWYgKGNvZGUgPj0gMHhmNjAwICYmIGNvZGUgPD0gMHhmOGZmKSB7CiAgcmV0dXJuIGdldFNwZWNpYWxQVUFTeW1ib2xzKClbY29kZV0gfHwgY29kZTsKIH0gZWxzZSBpZiAoY29kZSA9PT0gMHgwMGFkKSB7CiAgcmV0dXJuIDB4MDAyZDsKIH0KIHJldHVybiBjb2RlOwp9CmZ1bmN0aW9uIGdldFVuaWNvZGVGb3JHbHlwaChuYW1lLCBnbHlwaHNVbmljb2RlTWFwKSB7CiBsZXQgdW5pY29kZSA9IGdseXBoc1VuaWNvZGVNYXBbbmFtZV07CiBpZiAodW5pY29kZSAhPT0gdW5kZWZpbmVkKSB7CiAgcmV0dXJuIHVuaWNvZGU7CiB9CiBpZiAoIW5hbWUpIHsKICByZXR1cm4gLTE7CiB9CiBpZiAobmFtZVswXSA9PT0gInUiKSB7CiAgY29uc3QgbmFtZUxlbiA9IG5hbWUubGVuZ3RoOwogIGxldCBoZXhTdHI7CiAgaWYgKG5hbWVMZW4gPT09IDcgJiYgbmFtZVsxXSA9PT0gIm4iICYmIG5hbWVbMl0gPT09ICJpIikgewogICBoZXhTdHIgPSBuYW1lLnN1YnN0cmluZygzKTsKICB9IGVsc2UgaWYgKG5hbWVMZW4gPj0gNSAmJiBuYW1lTGVuIDw9IDcpIHsKICAgaGV4U3RyID0gbmFtZS5zdWJzdHJpbmcoMSk7CiAgfSBlbHNlIHsKICAgcmV0dXJuIC0xOwogIH0KICBpZiAoaGV4U3RyID09PSBoZXhTdHIudG9VcHBlckNhc2UoKSkgewogICB1bmljb2RlID0gcGFyc2VJbnQoaGV4U3RyLCAxNik7CiAgIGlmICh1bmljb2RlID49IDApIHsKICAgIHJldHVybiB1bmljb2RlOwogICB9CiAgfQogfQogcmV0dXJuIC0xOwp9CmNvbnN0IFVuaWNvZGVSYW5nZXMgPSBbCiB7CiAgYmVnaW46IDB4MDAwMCwKICBlbmQ6IDB4MDA3ZgogfSwKIHsKICBiZWdpbjogMHgwMDgwLAogIGVuZDogMHgwMGZmCiB9LAogewogIGJlZ2luOiAweDAxMDAsCiAgZW5kOiAweDAxN2YKIH0sCiB7CiAgYmVnaW46IDB4MDE4MCwKICBlbmQ6IDB4MDI0ZgogfSwKIHsKICBiZWdpbjogMHgwMjUwLAogIGVuZDogMHgwMmFmCiB9LAogewogIGJlZ2luOiAweDAyYjAsCiAgZW5kOiAweDAyZmYKIH0sCiB7CiAgYmVnaW46IDB4MDMwMCwKICBlbmQ6IDB4MDM2ZgogfSwKIHsKICBiZWdpbjogMHgwMzcwLAogIGVuZDogMHgwM2ZmCiB9LAogewogIGJlZ2luOiAweDJjODAsCiAgZW5kOiAweDJjZmYKIH0sCiB7CiAgYmVnaW46IDB4MDQwMCwKICBlbmQ6IDB4MDRmZgogfSwKIHsKICBiZWdpbjogMHgwNTMwLAogIGVuZDogMHgwNThmCiB9LAogewogIGJlZ2luOiAweDA1OTAsCiAgZW5kOiAweDA1ZmYKIH0sCiB7CiAgYmVnaW46IDB4YTUwMCwKICBlbmQ6IDB4YTYzZgogfSwKIHsKICBiZWdpbjogMHgwNjAwLAogIGVuZDogMHgwNmZmCiB9LAogewogIGJlZ2luOiAweDA3YzAsCiAgZW5kOiAweDA3ZmYKIH0sCiB7CiAgYmVnaW46IDB4MDkwMCwKICBlbmQ6IDB4MDk3ZgogfSwKIHsKICBiZWdpbjogMHgwOTgwLAogIGVuZDogMHgwOWZmCiB9LAogewogIGJlZ2luOiAweDBhMDAsCiAgZW5kOiAweDBhN2YKIH0sCiB7CiAgYmVnaW46IDB4MGE4MCwKICBlbmQ6IDB4MGFmZgogfSwKIHsKICBiZWdpbjogMHgwYjAwLAogIGVuZDogMHgwYjdmCiB9LAogewogIGJlZ2luOiAweDBiODAsCiAgZW5kOiAweDBiZmYKIH0sCiB7CiAgYmVnaW46IDB4MGMwMCwKICBlbmQ6IDB4MGM3ZgogfSwKIHsKICBiZWdpbjogMHgwYzgwLAogIGVuZDogMHgwY2ZmCiB9LAogewogIGJlZ2luOiAweDBkMDAsCiAgZW5kOiAweDBkN2YKIH0sCiB7CiAgYmVnaW46IDB4MGUwMCwKICBlbmQ6IDB4MGU3ZgogfSwKIHsKICBiZWdpbjogMHgwZTgwLAogIGVuZDogMHgwZWZmCiB9LAogewogIGJlZ2luOiAweDEwYTAsCiAgZW5kOiAweDEwZmYKIH0sCiB7CiAgYmVnaW46IDB4MWIwMCwKICBlbmQ6IDB4MWI3ZgogfSwKIHsKICBiZWdpbjogMHgxMTAwLAogIGVuZDogMHgxMWZmCiB9LAogewogIGJlZ2luOiAweDFlMDAsCiAgZW5kOiAweDFlZmYKIH0sCiB7CiAgYmVnaW46IDB4MWYwMCwKICBlbmQ6IDB4MWZmZgogfSwKIHsKICBiZWdpbjogMHgyMDAwLAogIGVuZDogMHgyMDZmCiB9LAogewogIGJlZ2luOiAweDIwNzAsCiAgZW5kOiAweDIwOWYKIH0sCiB7CiAgYmVnaW46IDB4MjBhMCwKICBlbmQ6IDB4MjBjZgogfSwKIHsKICBiZWdpbjogMHgyMGQwLAogIGVuZDogMHgyMGZmCiB9LAogewogIGJlZ2luOiAweDIxMDAsCiAgZW5kOiAweDIxNGYKIH0sCiB7CiAgYmVnaW46IDB4MjE1MCwKICBlbmQ6IDB4MjE4ZgogfSwKIHsKICBiZWdpbjogMHgyMTkwLAogIGVuZDogMHgyMWZmCiB9LAogewogIGJlZ2luOiAweDIyMDAsCiAgZW5kOiAweDIyZmYKIH0sCiB7CiAgYmVnaW46IDB4MjMwMCwKICBlbmQ6IDB4MjNmZgogfSwKIHsKICBiZWdpbjogMHgyNDAwLAogIGVuZDogMHgyNDNmCiB9LAogewogIGJlZ2luOiAweDI0NDAsCiAgZW5kOiAweDI0NWYKIH0sCiB7CiAgYmVnaW46IDB4MjQ2MCwKICBlbmQ6IDB4MjRmZgogfSwKIHsKICBiZWdpbjogMHgyNTAwLAogIGVuZDogMHgyNTdmCiB9LAogewogIGJlZ2luOiAweDI1ODAsCiAgZW5kOiAweDI1OWYKIH0sCiB7CiAgYmVnaW46IDB4MjVhMCwKICBlbmQ6IDB4MjVmZgogfSwKIHsKICBiZWdpbjogMHgyNjAwLAogIGVuZDogMHgyNmZmCiB9LAogewogIGJlZ2luOiAweDI3MDAsCiAgZW5kOiAweDI3YmYKIH0sCiB7CiAgYmVnaW46IDB4MzAwMCwKICBlbmQ6IDB4MzAzZgogfSwKIHsKICBiZWdpbjogMHgzMDQwLAogIGVuZDogMHgzMDlmCiB9LAogewogIGJlZ2luOiAweDMwYTAsCiAgZW5kOiAweDMwZmYKIH0sCiB7CiAgYmVnaW46IDB4MzEwMCwKICBlbmQ6IDB4MzEyZgogfSwKIHsKICBiZWdpbjogMHgzMTMwLAogIGVuZDogMHgzMThmCiB9LAogewogIGJlZ2luOiAweGE4NDAsCiAgZW5kOiAweGE4N2YKIH0sCiB7CiAgYmVnaW46IDB4MzIwMCwKICBlbmQ6IDB4MzJmZgogfSwKIHsKICBiZWdpbjogMHgzMzAwLAogIGVuZDogMHgzM2ZmCiB9LAogewogIGJlZ2luOiAweGFjMDAsCiAgZW5kOiAweGQ3YWYKIH0sCiB7CiAgYmVnaW46IDB4ZDgwMCwKICBlbmQ6IDB4ZGZmZgogfSwKIHsKICBiZWdpbjogMHgxMDkwMCwKICBlbmQ6IDB4MTA5MWYKIH0sCiB7CiAgYmVnaW46IDB4NGUwMCwKICBlbmQ6IDB4OWZmZgogfSwKIHsKICBiZWdpbjogMHhlMDAwLAogIGVuZDogMHhmOGZmCiB9LAogewogIGJlZ2luOiAweDMxYzAsCiAgZW5kOiAweDMxZWYKIH0sCiB7CiAgYmVnaW46IDB4ZmIwMCwKICBlbmQ6IDB4ZmI0ZgogfSwKIHsKICBiZWdpbjogMHhmYjUwLAogIGVuZDogMHhmZGZmCiB9LAogewogIGJlZ2luOiAweGZlMjAsCiAgZW5kOiAweGZlMmYKIH0sCiB7CiAgYmVnaW46IDB4ZmUxMCwKICBlbmQ6IDB4ZmUxZgogfSwKIHsKICBiZWdpbjogMHhmZTUwLAogIGVuZDogMHhmZTZmCiB9LAogewogIGJlZ2luOiAweGZlNzAsCiAgZW5kOiAweGZlZmYKIH0sCiB7CiAgYmVnaW46IDB4ZmYwMCwKICBlbmQ6IDB4ZmZlZgogfSwKIHsKICBiZWdpbjogMHhmZmYwLAogIGVuZDogMHhmZmZmCiB9LAogewogIGJlZ2luOiAweDBmMDAsCiAgZW5kOiAweDBmZmYKIH0sCiB7CiAgYmVnaW46IDB4MDcwMCwKICBlbmQ6IDB4MDc0ZgogfSwKIHsKICBiZWdpbjogMHgwNzgwLAogIGVuZDogMHgwN2JmCiB9LAogewogIGJlZ2luOiAweDBkODAsCiAgZW5kOiAweDBkZmYKIH0sCiB7CiAgYmVnaW46IDB4MTAwMCwKICBlbmQ6IDB4MTA5ZgogfSwKIHsKICBiZWdpbjogMHgxMjAwLAogIGVuZDogMHgxMzdmCiB9LAogewogIGJlZ2luOiAweDEzYTAsCiAgZW5kOiAweDEzZmYKIH0sCiB7CiAgYmVnaW46IDB4MTQwMCwKICBlbmQ6IDB4MTY3ZgogfSwKIHsKICBiZWdpbjogMHgxNjgwLAogIGVuZDogMHgxNjlmCiB9LAogewogIGJlZ2luOiAweDE2YTAsCiAgZW5kOiAweDE2ZmYKIH0sCiB7CiAgYmVnaW46IDB4MTc4MCwKICBlbmQ6IDB4MTdmZgogfSwKIHsKICBiZWdpbjogMHgxODAwLAogIGVuZDogMHgxOGFmCiB9LAogewogIGJlZ2luOiAweDI4MDAsCiAgZW5kOiAweDI4ZmYKIH0sCiB7CiAgYmVnaW46IDB4YTAwMCwKICBlbmQ6IDB4YTQ4ZgogfSwKIHsKICBiZWdpbjogMHgxNzAwLAogIGVuZDogMHgxNzFmCiB9LAogewogIGJlZ2luOiAweDEwMzAwLAogIGVuZDogMHgxMDMyZgogfSwKIHsKICBiZWdpbjogMHgxMDMzMCwKICBlbmQ6IDB4MTAzNGYKIH0sCiB7CiAgYmVnaW46IDB4MTA0MDAsCiAgZW5kOiAweDEwNDRmCiB9LAogewogIGJlZ2luOiAweDFkMDAwLAogIGVuZDogMHgxZDBmZgogfSwKIHsKICBiZWdpbjogMHgxZDQwMCwKICBlbmQ6IDB4MWQ3ZmYKIH0sCiB7CiAgYmVnaW46IDB4ZmYwMDAsCiAgZW5kOiAweGZmZmZkCiB9LAogewogIGJlZ2luOiAweGZlMDAsCiAgZW5kOiAweGZlMGYKIH0sCiB7CiAgYmVnaW46IDB4ZTAwMDAsCiAgZW5kOiAweGUwMDdmCiB9LAogewogIGJlZ2luOiAweDE5MDAsCiAgZW5kOiAweDE5NGYKIH0sCiB7CiAgYmVnaW46IDB4MTk1MCwKICBlbmQ6IDB4MTk3ZgogfSwKIHsKICBiZWdpbjogMHgxOTgwLAogIGVuZDogMHgxOWRmCiB9LAogewogIGJlZ2luOiAweDFhMDAsCiAgZW5kOiAweDFhMWYKIH0sCiB7CiAgYmVnaW46IDB4MmMwMCwKICBlbmQ6IDB4MmM1ZgogfSwKIHsKICBiZWdpbjogMHgyZDMwLAogIGVuZDogMHgyZDdmCiB9LAogewogIGJlZ2luOiAweDRkYzAsCiAgZW5kOiAweDRkZmYKIH0sCiB7CiAgYmVnaW46IDB4YTgwMCwKICBlbmQ6IDB4YTgyZgogfSwKIHsKICBiZWdpbjogMHgxMDAwMCwKICBlbmQ6IDB4MTAwN2YKIH0sCiB7CiAgYmVnaW46IDB4MTAxNDAsCiAgZW5kOiAweDEwMThmCiB9LAogewogIGJlZ2luOiAweDEwMzgwLAogIGVuZDogMHgxMDM5ZgogfSwKIHsKICBiZWdpbjogMHgxMDNhMCwKICBlbmQ6IDB4MTAzZGYKIH0sCiB7CiAgYmVnaW46IDB4MTA0NTAsCiAgZW5kOiAweDEwNDdmCiB9LAogewogIGJlZ2luOiAweDEwNDgwLAogIGVuZDogMHgxMDRhZgogfSwKIHsKICBiZWdpbjogMHgxMDgwMCwKICBlbmQ6IDB4MTA4M2YKIH0sCiB7CiAgYmVnaW46IDB4MTBhMDAsCiAgZW5kOiAweDEwYTVmCiB9LAogewogIGJlZ2luOiAweDFkMzAwLAogIGVuZDogMHgxZDM1ZgogfSwKIHsKICBiZWdpbjogMHgxMjAwMCwKICBlbmQ6IDB4MTIzZmYKIH0sCiB7CiAgYmVnaW46IDB4MWQzNjAsCiAgZW5kOiAweDFkMzdmCiB9LAogewogIGJlZ2luOiAweDFiODAsCiAgZW5kOiAweDFiYmYKIH0sCiB7CiAgYmVnaW46IDB4MWMwMCwKICBlbmQ6IDB4MWM0ZgogfSwKIHsKICBiZWdpbjogMHgxYzUwLAogIGVuZDogMHgxYzdmCiB9LAogewogIGJlZ2luOiAweGE4ODAsCiAgZW5kOiAweGE4ZGYKIH0sCiB7CiAgYmVnaW46IDB4YTkwMCwKICBlbmQ6IDB4YTkyZgogfSwKIHsKICBiZWdpbjogMHhhOTMwLAogIGVuZDogMHhhOTVmCiB9LAogewogIGJlZ2luOiAweGFhMDAsCiAgZW5kOiAweGFhNWYKIH0sCiB7CiAgYmVnaW46IDB4MTAxOTAsCiAgZW5kOiAweDEwMWNmCiB9LAogewogIGJlZ2luOiAweDEwMWQwLAogIGVuZDogMHgxMDFmZgogfSwKIHsKICBiZWdpbjogMHgxMDJhMCwKICBlbmQ6IDB4MTAyZGYKIH0sCiB7CiAgYmVnaW46IDB4MWYwMzAsCiAgZW5kOiAweDFmMDlmCiB9Cl07CmZ1bmN0aW9uIGdldFVuaWNvZGVSYW5nZUZvcih2YWx1ZSkgewogZm9yIChsZXQgaSA9IDAsIGlpID0gVW5pY29kZVJhbmdlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgY29uc3QgcmFuZ2UgPSBVbmljb2RlUmFuZ2VzW2ldOwogIGlmICh2YWx1ZSA+PSByYW5nZS5iZWdpbiAmJiB2YWx1ZSA8IHJhbmdlLmVuZCkgewogICByZXR1cm4gaTsKICB9CiB9CiByZXR1cm4gLTE7Cn0KZnVuY3Rpb24gaXNSVExSYW5nZUZvcih2YWx1ZSkgewogbGV0IHJhbmdlID0gVW5pY29kZVJhbmdlc1sxM107CiBpZiAodmFsdWUgPj0gcmFuZ2UuYmVnaW4gJiYgdmFsdWUgPCByYW5nZS5lbmQpIHsKICByZXR1cm4gdHJ1ZTsKIH0KIHJhbmdlID0gVW5pY29kZVJhbmdlc1sxMV07CiBpZiAodmFsdWUgPj0gcmFuZ2UuYmVnaW4gJiYgdmFsdWUgPCByYW5nZS5lbmQpIHsKICByZXR1cm4gdHJ1ZTsKIH0KIHJldHVybiBmYWxzZTsKfQpjb25zdCBnZXROb3JtYWxpemVkVW5pY29kZXMgPSAoMCxfY29yZV91dGlsc19qc19fV0VCUEFDS19JTVBPUlRFRF9NT0RVTEVfMF9fLmdldEFycmF5TG9va3VwVGFibGVGYWN0b3J5KShmdW5jdGlvbiAoKSB7CiByZXR1cm4gWwogICJcdTAwQTgiLAogICJcdTAwMjBcdTAzMDgiLAogICJcdTAwQUYiLAogICJcdTAwMjBcdTAzMDQiLAogICJcdTAwQjQiLAogICJcdTAwMjBcdTAzMDEiLAogICJcdTAwQjUiLAogICJcdTAzQkMiLAogICJcdTAwQjgiLAogICJcdTAwMjBcdTAzMjciLAogICJcdTAxMzIiLAogICJcdTAwNDlcdTAwNEEiLAogICJcdTAxMzMiLAogICJcdTAwNjlcdTAwNkEiLAogICJcdTAxM0YiLAogICJcdTAwNENcdTAwQjciLAogICJcdTAxNDAiLAogICJcdTAwNkNcdTAwQjciLAogICJcdTAxNDkiLAogICJcdTAyQkNcdTAwNkUiLAogICJcdTAxN0YiLAogICJcdTAwNzMiLAogICJcdTAxQzQiLAogICJcdTAwNDRcdTAxN0QiLAogICJcdTAxQzUiLAogICJcdTAwNDRcdTAxN0UiLAogICJcdTAxQzYiLAogICJcdTAwNjRcdTAxN0UiLAogICJcdTAxQzciLAogICJcdTAwNENcdTAwNEEiLAogICJcdTAxQzgiLAogICJcdTAwNENcdTAwNkEiLAogICJcdTAxQzkiLAogICJcdTAwNkNcdTAwNkEiLAogICJcdTAxQ0EiLAogICJcdTAwNEVcdTAwNEEiLAogICJcdTAxQ0IiLAogICJcdTAwNEVcdTAwNkEiLAogICJcdTAxQ0MiLAogICJcdTAwNkVcdTAwNkEiLAogICJcdTAxRjEiLAogICJcdTAwNDRcdTAwNUEiLAogICJcdTAxRjIiLAogICJcdTAwNDRcdTAwN0EiLAogICJcdTAxRjMiLAogICJcdTAwNjRcdTAwN0EiLAogICJcdTAyRDgiLAogICJcdTAwMjBcdTAzMDYiLAogICJcdTAyRDkiLAogICJcdTAwMjBcdTAzMDciLAogICJcdTAyREEiLAogICJcdTAwMjBcdTAzMEEiLAogICJcdTAyREIiLAogICJcdTAwMjBcdTAzMjgiLAogICJcdTAyREMiLAogICJcdTAwMjBcdTAzMDMiLAogICJcdTAyREQiLAogICJcdTAwMjBcdTAzMEIiLAogICJcdTAzN0EiLAogICJcdTAwMjBcdTAzNDUiLAogICJcdTAzODQiLAogICJcdTAwMjBcdTAzMDEiLAogICJcdTAzRDAiLAogICJcdTAzQjIiLAogICJcdTAzRDEiLAogICJcdTAzQjgiLAogICJcdTAzRDIiLAogICJcdTAzQTUiLAogICJcdTAzRDUiLAogICJcdTAzQzYiLAogICJcdTAzRDYiLAogICJcdTAzQzAiLAogICJcdTAzRjAiLAogICJcdTAzQkEiLAogICJcdTAzRjEiLAogICJcdTAzQzEiLAogICJcdTAzRjIiLAogICJcdTAzQzIiLAogICJcdTAzRjQiLAogICJcdTAzOTgiLAogICJcdTAzRjUiLAogICJcdTAzQjUiLAogICJcdTAzRjkiLAogICJcdTAzQTMiLAogICJcdTA1ODciLAogICJcdTA1NjVcdTA1ODIiLAogICJcdTA2NzUiLAogICJcdTA2MjdcdTA2NzQiLAogICJcdTA2NzYiLAogICJcdTA2NDhcdTA2NzQiLAogICJcdTA2NzciLAogICJcdTA2QzdcdTA2NzQiLAogICJcdTA2NzgiLAogICJcdTA2NEFcdTA2NzQiLAogICJcdTBFMzMiLAogICJcdTBFNERcdTBFMzIiLAogICJcdTBFQjMiLAogICJcdTBFQ0RcdTBFQjIiLAogICJcdTBFREMiLAogICJcdTBFQUJcdTBFOTkiLAogICJcdTBFREQiLAogICJcdTBFQUJcdTBFQTEiLAogICJcdTBGNzciLAogICJcdTBGQjJcdTBGODEiLAogICJcdTBGNzkiLAogICJcdTBGQjNcdTBGODEiLAogICJcdTFFOUEiLAogICJcdTAwNjFcdTAyQkUiLAogICJcdTFGQkQiLAogICJcdTAwMjBcdTAzMTMiLAogICJcdTFGQkYiLAogICJcdTAwMjBcdTAzMTMiLAogICJcdTFGQzAiLAogICJcdTAwMjBcdTAzNDIiLAogICJcdTFGRkUiLAogICJcdTAwMjBcdTAzMTQiLAogICJcdTIwMDIiLAogICJcdTAwMjAiLAogICJcdTIwMDMiLAogICJcdTAwMjAiLAogICJcdTIwMDQiLAogICJcdTAwMjAiLAogICJcdTIwMDUiLAogICJcdTAwMjAiLAogICJcdTIwMDYiLAogICJcdTAwMjAiLAogICJcdTIwMDgiLAogICJcdTAwMjAiLAogICJcdTIwMDkiLAogICJcdTAwMjAiLAogICJcdTIwMEEiLAogICJcdTAwMjAiLAogICJcdTIwMTciLAogICJcdTAwMjBcdTAzMzMiLAogICJcdTIwMjQiLAogICJcdTAwMkUiLAogICJcdTIwMjUiLAogICJcdTAwMkVcdTAwMkUiLAogICJcdTIwMjYiLAogICJcdTAwMkVcdTAwMkVcdTAwMkUiLAogICJcdTIwMzMiLAogICJcdTIwMzJcdTIwMzIiLAogICJcdTIwMzQiLAogICJcdTIwMzJcdTIwMzJcdTIwMzIiLAogICJcdTIwMzYiLAogICJcdTIwMzVcdTIwMzUiLAogICJcdTIwMzciLAogICJcdTIwMzVcdTIwMzVcdTIwMzUiLAogICJcdTIwM0MiLAogICJcdTAwMjFcdTAwMjEiLAogICJcdTIwM0UiLAogICJcdTAwMjBcdTAzMDUiLAogICJcdTIwNDciLAogICJcdTAwM0ZcdTAwM0YiLAogICJcdTIwNDgiLAogICJcdTAwM0ZcdTAwMjEiLAogICJcdTIwNDkiLAogICJcdTAwMjFcdTAwM0YiLAogICJcdTIwNTciLAogICJcdTIwMzJcdTIwMzJcdTIwMzJcdTIwMzIiLAogICJcdTIwNUYiLAogICJcdTAwMjAiLAogICJcdTIwQTgiLAogICJcdTAwNTJcdTAwNzMiLAogICJcdTIxMDAiLAogICJcdTAwNjFcdTAwMkZcdTAwNjMiLAogICJcdTIxMDEiLAogICJcdTAwNjFcdTAwMkZcdTAwNzMiLAogICJcdTIxMDMiLAogICJcdTAwQjBcdTAwNDMiLAogICJcdTIxMDUiLAogICJcdTAwNjNcdTAwMkZcdTAwNkYiLAogICJcdTIxMDYiLAogICJcdTAwNjNcdTAwMkZcdTAwNzUiLAogICJcdTIxMDciLAogICJcdTAxOTAiLAogICJcdTIxMDkiLAogICJcdTAwQjBcdTAwNDYiLAogICJcdTIxMTYiLAogICJcdTAwNEVcdTAwNkYiLAogICJcdTIxMjEiLAogICJcdTAwNTRcdTAwNDVcdTAwNEMiLAogICJcdTIxMzUiLAogICJcdTA1RDAiLAogICJcdTIxMzYiLAogICJcdTA1RDEiLAogICJcdTIxMzciLAogICJcdTA1RDIiLAogICJcdTIxMzgiLAogICJcdTA1RDMiLAogICJcdTIxM0IiLAogICJcdTAwNDZcdTAwNDFcdTAwNTgiLAogICJcdTIxNjAiLAogICJcdTAwNDkiLAogICJcdTIxNjEiLAogICJcdTAwNDlcdTAwNDkiLAogICJcdTIxNjIiLAogICJcdTAwNDlcdTAwNDlcdTAwNDkiLAogICJcdTIxNjMiLAogICJcdTAwNDlcdTAwNTYiLAogICJcdTIxNjQiLAogICJcdTAwNTYiLAogICJcdTIxNjUiLAogICJcdTAwNTZcdTAwNDkiLAogICJcdTIxNjYiLAogICJcdTAwNTZcdTAwNDlcdTAwNDkiLAogICJcdTIxNjciLAogICJcdTAwNTZcdTAwNDlcdTAwNDlcdTAwNDkiLAogICJcdTIxNjgiLAogICJcdTAwNDlcdTAwNTgiLAogICJcdTIxNjkiLAogICJcdTAwNTgiLAogICJcdTIxNkEiLAogICJcdTAwNThcdTAwNDkiLAogICJcdTIxNkIiLAogICJcdTAwNThcdTAwNDlcdTAwNDkiLAogICJcdTIxNkMiLAogICJcdTAwNEMiLAogICJcdTIxNkQiLAogICJcdTAwNDMiLAogICJcdTIxNkUiLAogICJcdTAwNDQiLAogICJcdTIxNkYiLAogICJcdTAwNEQiLAogICJcdTIxNzAiLAogICJcdTAwNjkiLAogICJcdTIxNzEiLAogICJcdTAwNjlcdTAwNjkiLAogICJcdTIxNzIiLAogICJcdTAwNjlcdTAwNjlcdTAwNjkiLAogICJcdTIxNzMiLAogICJcdTAwNjlcdTAwNzYiLAogICJcdTIxNzQiLAogICJcdTAwNzYiLAogICJcdTIxNzUiLAogICJcdTAwNzZcdTAwNjkiLAogICJcdTIxNzYiLAogICJcdTAwNzZcdTAwNjlcdTAwNjkiLAogICJcdTIxNzciLAogICJcdTAwNzZcdTAwNjlcdTAwNjlcdTAwNjkiLAogICJcdTIxNzgiLAogICJcdTAwNjlcdTAwNzgiLAogICJcdTIxNzkiLAogICJcdTAwNzgiLAogICJcdTIxN0EiLAogICJcdTAwNzhcdTAwNjkiLAogICJcdTIxN0IiLAogICJcdTAwNzhcdTAwNjlcdTAwNjkiLAogICJcdTIxN0MiLAogICJcdTAwNkMiLAogICJcdTIxN0QiLAogICJcdTAwNjMiLAogICJcdTIxN0UiLAogICJcdTAwNjQiLAogICJcdTIxN0YiLAogICJcdTAwNkQiLAogICJcdTIyMkMiLAogICJcdTIyMkJcdTIyMkIiLAogICJcdTIyMkQiLAogICJcdTIyMkJcdTIyMkJcdTIyMkIiLAogICJcdTIyMkYiLAogICJcdTIyMkVcdTIyMkUiLAogICJcdTIyMzAiLAogICJcdTIyMkVcdTIyMkVcdTIyMkUiLAogICJcdTI0NzQiLAogICJcdTAwMjhcdTAwMzFcdTAwMjkiLAogICJcdTI0NzUiLAogICJcdTAwMjhcdTAwMzJcdTAwMjkiLAogICJcdTI0NzYiLAogICJcdTAwMjhcdTAwMzNcdTAwMjkiLAogICJcdTI0NzciLAogICJcdTAwMjhcdTAwMzRcdTAwMjkiLAogICJcdTI0NzgiLAogICJcdTAwMjhcdTAwMzVcdTAwMjkiLAogICJcdTI0NzkiLAogICJcdTAwMjhcdTAwMzZcdTAwMjkiLAogICJcdTI0N0EiLAogICJcdTAwMjhcdTAwMzdcdTAwMjkiLAogICJcdTI0N0IiLAogICJcdTAwMjhcdTAwMzhcdTAwMjkiLAogICJcdTI0N0MiLAogICJcdTAwMjhcdTAwMzlcdTAwMjkiLAogICJcdTI0N0QiLAogICJcdTAwMjhcdTAwMzFcdTAwMzBcdTAwMjkiLAogICJcdTI0N0UiLAogICJcdTAwMjhcdTAwMzFcdTAwMzFcdTAwMjkiLAogICJcdTI0N0YiLAogICJcdTAwMjhcdTAwMzFcdTAwMzJcdTAwMjkiLAogICJcdTI0ODAiLAogICJcdTAwMjhcdTAwMzFcdTAwMzNcdTAwMjkiLAogICJcdTI0ODEiLAogICJcdTAwMjhcdTAwMzFcdTAwMzRcdTAwMjkiLAogICJcdTI0ODIiLAogICJcdTAwMjhcdTAwMzFcdTAwMzVcdTAwMjkiLAogICJcdTI0ODMiLAogICJcdTAwMjhcdTAwMzFcdTAwMzZcdTAwMjkiLAogICJcdTI0ODQiLAogICJcdTAwMjhcdTAwMzFcdTAwMzdcdTAwMjkiLAogICJcdTI0ODUiLAogICJcdTAwMjhcdTAwMzFcdTAwMzhcdTAwMjkiLAogICJcdTI0ODYiLAogICJcdTAwMjhcdTAwMzFcdTAwMzlcdTAwMjkiLAogICJcdTI0ODciLAogICJcdTAwMjhcdTAwMzJcdTAwMzBcdTAwMjkiLAogICJcdTI0ODgiLAogICJcdTAwMzFcdTAwMkUiLAogICJcdTI0ODkiLAogICJcdTAwMzJcdTAwMkUiLAogICJcdTI0OEEiLAogICJcdTAwMzNcdTAwMkUiLAogICJcdTI0OEIiLAogICJcdTAwMzRcdTAwMkUiLAogICJcdTI0OEMiLAogICJcdTAwMzVcdTAwMkUiLAogICJcdTI0OEQiLAogICJcdTAwMzZcdTAwMkUiLAogICJcdTI0OEUiLAogICJcdTAwMzdcdTAwMkUiLAogICJcdTI0OEYiLAogICJcdTAwMzhcdTAwMkUiLAogICJcdTI0OTAiLAogICJcdTAwMzlcdTAwMkUiLAogICJcdTI0OTEiLAogICJcdTAwMzFcdTAwMzBcdTAwMkUiLAogICJcdTI0OTIiLAogICJcdTAwMzFcdTAwMzFcdTAwMkUiLAogICJcdTI0OTMiLAogICJcdTAwMzFcdTAwMzJcdTAwMkUiLAogICJcdTI0OTQiLAogICJcdTAwMzFcdTAwMzNcdTAwMkUiLAogICJcdTI0OTUiLAogICJcdTAwMzFcdTAwMzRcdTAwMkUiLAogICJcdTI0OTYiLAogICJcdTAwMzFcdTAwMzVcdTAwMkUiLAogICJcdTI0OTciLAogICJcdTAwMzFcdTAwMzZcdTAwMkUiLAogICJcdTI0OTgiLAogICJcdTAwMzFcdTAwMzdcdTAwMkUiLAogICJcdTI0OTkiLAogICJcdTAwMzFcdTAwMzhcdTAwMkUiLAogICJcdTI0OUEiLAogICJcdTAwMzFcdTAwMzlcdTAwMkUiLAogICJcdTI0OUIiLAogICJcdTAwMzJcdTAwMzBcdTAwMkUiLAogICJcdTI0OUMiLAogICJcdTAwMjhcdTAwNjFcdTAwMjkiLAogICJcdTI0OUQiLAogICJcdTAwMjhcdTAwNjJcdTAwMjkiLAogICJcdTI0OUUiLAogICJcdTAwMjhcdTAwNjNcdTAwMjkiLAogICJcdTI0OUYiLAogICJcdTAwMjhcdTAwNjRcdTAwMjkiLAogICJcdTI0QTAiLAogICJcdTAwMjhcdTAwNjVcdTAwMjkiLAogICJcdTI0QTEiLAogICJcdTAwMjhcdTAwNjZcdTAwMjkiLAogICJcdTI0QTIiLAogICJcdTAwMjhcdTAwNjdcdTAwMjkiLAogICJcdTI0QTMiLAogICJcdTAwMjhcdTAwNjhcdTAwMjkiLAogICJcdTI0QTQiLAogICJcdTAwMjhcdTAwNjlcdTAwMjkiLAogICJcdTI0QTUiLAogICJcdTAwMjhcdTAwNkFcdTAwMjkiLAogICJcdTI0QTYiLAogICJcdTAwMjhcdTAwNkJcdTAwMjkiLAogICJcdTI0QTciLAogICJcdTAwMjhcdTAwNkNcdTAwMjkiLAogICJcdTI0QTgiLAogICJcdTAwMjhcdTAwNkRcdTAwMjkiLAogICJcdTI0QTkiLAogICJcdTAwMjhcdTAwNkVcdTAwMjkiLAogICJcdTI0QUEiLAogICJcdTAwMjhcdTAwNkZcdTAwMjkiLAogICJcdTI0QUIiLAogICJcdTAwMjhcdTAwNzBcdTAwMjkiLAogICJcdTI0QUMiLAogICJcdTAwMjhcdTAwNzFcdTAwMjkiLAogICJcdTI0QUQiLAogICJcdTAwMjhcdTAwNzJcdTAwMjkiLAogICJcdTI0QUUiLAogICJcdTAwMjhcdTAwNzNcdTAwMjkiLAogICJcdTI0QUYiLAogICJcdTAwMjhcdTAwNzRcdTAwMjkiLAogICJcdTI0QjAiLAogICJcdTAwMjhcdTAwNzVcdTAwMjkiLAogICJcdTI0QjEiLAogICJcdTAwMjhcdTAwNzZcdTAwMjkiLAogICJcdTI0QjIiLAogICJcdTAwMjhcdTAwNzdcdTAwMjkiLAogICJcdTI0QjMiLAogICJcdTAwMjhcdTAwNzhcdTAwMjkiLAogICJcdTI0QjQiLAogICJcdTAwMjhcdTAwNzlcdTAwMjkiLAogICJcdTI0QjUiLAogICJcdTAwMjhcdTAwN0FcdTAwMjkiLAogICJcdTJBMEMiLAogICJcdTIyMkJcdTIyMkJcdTIyMkJcdTIyMkIiLAogICJcdTJBNzQiLAogICJcdTAwM0FcdTAwM0FcdTAwM0QiLAogICJcdTJBNzUiLAogICJcdTAwM0RcdTAwM0QiLAogICJcdTJBNzYiLAogICJcdTAwM0RcdTAwM0RcdTAwM0QiLAogICJcdTJFOUYiLAogICJcdTZCQ0QiLAogICJcdTJFRjMiLAogICJcdTlGOUYiLAogICJcdTJGMDAiLAogICJcdTRFMDAiLAogICJcdTJGMDEiLAogICJcdTRFMjgiLAogICJcdTJGMDIiLAogICJcdTRFMzYiLAogICJcdTJGMDMiLAogICJcdTRFM0YiLAogICJcdTJGMDQiLAogICJcdTRFNTkiLAogICJcdTJGMDUiLAogICJcdTRFODUiLAogICJcdTJGMDYiLAogICJcdTRFOEMiLAogICJcdTJGMDciLAogICJcdTRFQTAiLAogICJcdTJGMDgiLAogICJcdTRFQkEiLAogICJcdTJGMDkiLAogICJcdTUxM0YiLAogICJcdTJGMEEiLAogICJcdTUxNjUiLAogICJcdTJGMEIiLAogICJcdTUxNkIiLAogICJcdTJGMEMiLAogICJcdTUxODIiLAogICJcdTJGMEQiLAogICJcdTUxOTYiLAogICJcdTJGMEUiLAogICJcdTUxQUIiLAogICJcdTJGMEYiLAogICJcdTUxRTAiLAogICJcdTJGMTAiLAogICJcdTUxRjUiLAogICJcdTJGMTEiLAogICJcdTUyMDAiLAogICJcdTJGMTIiLAogICJcdTUyOUIiLAogICJcdTJGMTMiLAogICJcdTUyRjkiLAogICJcdTJGMTQiLAogICJcdTUzMTUiLAogICJcdTJGMTUiLAogICJcdTUzMUEiLAogICJcdTJGMTYiLAogICJcdTUzMzgiLAogICJcdTJGMTciLAogICJcdTUzNDEiLAogICJcdTJGMTgiLAogICJcdTUzNUMiLAogICJcdTJGMTkiLAogICJcdTUzNjkiLAogICJcdTJGMUEiLAogICJcdTUzODIiLAogICJcdTJGMUIiLAogICJcdTUzQjYiLAogICJcdTJGMUMiLAogICJcdTUzQzgiLAogICJcdTJGMUQiLAogICJcdTUzRTMiLAogICJcdTJGMUUiLAogICJcdTU2RDciLAogICJcdTJGMUYiLAogICJcdTU3MUYiLAogICJcdTJGMjAiLAogICJcdTU4RUIiLAogICJcdTJGMjEiLAogICJcdTU5MDIiLAogICJcdTJGMjIiLAogICJcdTU5MEEiLAogICJcdTJGMjMiLAogICJcdTU5MTUiLAogICJcdTJGMjQiLAogICJcdTU5MjciLAogICJcdTJGMjUiLAogICJcdTU5NzMiLAogICJcdTJGMjYiLAogICJcdTVCNTAiLAogICJcdTJGMjciLAogICJcdTVCODAiLAogICJcdTJGMjgiLAogICJcdTVCRjgiLAogICJcdTJGMjkiLAogICJcdTVDMEYiLAogICJcdTJGMkEiLAogICJcdTVDMjIiLAogICJcdTJGMkIiLAogICJcdTVDMzgiLAogICJcdTJGMkMiLAogICJcdTVDNkUiLAogICJcdTJGMkQiLAogICJcdTVDNzEiLAogICJcdTJGMkUiLAogICJcdTVEREIiLAogICJcdTJGMkYiLAogICJcdTVERTUiLAogICJcdTJGMzAiLAogICJcdTVERjEiLAogICJcdTJGMzEiLAogICJcdTVERkUiLAogICJcdTJGMzIiLAogICJcdTVFNzIiLAogICJcdTJGMzMiLAogICJcdTVFN0EiLAogICJcdTJGMzQiLAogICJcdTVFN0YiLAogICJcdTJGMzUiLAogICJcdTVFRjQiLAogICJcdTJGMzYiLAogICJcdTVFRkUiLAogICJcdTJGMzciLAogICJcdTVGMEIiLAogICJcdTJGMzgiLAogICJcdTVGMTMiLAogICJcdTJGMzkiLAogICJcdTVGNTAiLAogICJcdTJGM0EiLAogICJcdTVGNjEiLAogICJcdTJGM0IiLAogICJcdTVGNzMiLAogICJcdTJGM0MiLAogICJcdTVGQzMiLAogICJcdTJGM0QiLAogICJcdTYyMDgiLAogICJcdTJGM0UiLAogICJcdTYyMzYiLAogICJcdTJGM0YiLAogICJcdTYyNEIiLAogICJcdTJGNDAiLAogICJcdTY1MkYiLAogICJcdTJGNDEiLAogICJcdTY1MzQiLAogICJcdTJGNDIiLAogICJcdTY1ODciLAogICJcdTJGNDMiLAogICJcdTY1OTciLAogICJcdTJGNDQiLAogICJcdTY1QTQiLAogICJcdTJGNDUiLAogICJcdTY1QjkiLAogICJcdTJGNDYiLAogICJcdTY1RTAiLAogICJcdTJGNDciLAogICJcdTY1RTUiLAogICJcdTJGNDgiLAogICJcdTY2RjAiLAogICJcdTJGNDkiLAogICJcdTY3MDgiLAogICJcdTJGNEEiLAogICJcdTY3MjgiLAogICJcdTJGNEIiLAogICJcdTZCMjAiLAogICJcdTJGNEMiLAogICJcdTZCNjIiLAogICJcdTJGNEQiLAogICJcdTZCNzkiLAogICJcdTJGNEUiLAogICJcdTZCQjMiLAogICJcdTJGNEYiLAogICJcdTZCQ0IiLAogICJcdTJGNTAiLAogICJcdTZCRDQiLAogICJcdTJGNTEiLAogICJcdTZCREIiLAogICJcdTJGNTIiLAogICJcdTZDMEYiLAogICJcdTJGNTMiLAogICJcdTZDMTQiLAogICJcdTJGNTQiLAogICJcdTZDMzQiLAogICJcdTJGNTUiLAogICJcdTcwNkIiLAogICJcdTJGNTYiLAogICJcdTcyMkEiLAogICJcdTJGNTciLAogICJcdTcyMzYiLAogICJcdTJGNTgiLAogICJcdTcyM0IiLAogICJcdTJGNTkiLAogICJcdTcyM0YiLAogICJcdTJGNUEiLAogICJcdTcyNDciLAogICJcdTJGNUIiLAogICJcdTcyNTkiLAogICJcdTJGNUMiLAogICJcdTcyNUIiLAogICJcdTJGNUQiLAogICJcdTcyQUMiLAogICJcdTJGNUUiLAogICJcdTczODQiLAogICJcdTJGNUYiLAogICJcdTczODkiLAogICJcdTJGNjAiLAogICJcdTc0REMiLAogICJcdTJGNjEiLAogICJcdTc0RTYiLAogICJcdTJGNjIiLAogICJcdTc1MTgiLAogICJcdTJGNjMiLAogICJcdTc1MUYiLAogICJcdTJGNjQiLAogICJcdTc1MjgiLAogICJcdTJGNjUiLAogICJcdTc1MzAiLAogICJcdTJGNjYiLAogICJcdTc1OEIiLAogICJcdTJGNjciLAogICJcdTc1OTIiLAogICJcdTJGNjgiLAogICJcdTc2NzYiLAogICJcdTJGNjkiLAogICJcdTc2N0QiLAogICJcdTJGNkEiLAogICJcdTc2QUUiLAogICJcdTJGNkIiLAogICJcdTc2QkYiLAogICJcdTJGNkMiLAogICJcdTc2RUUiLAogICJcdTJGNkQiLAogICJcdTc3REIiLAogICJcdTJGNkUiLAogICJcdTc3RTIiLAogICJcdTJGNkYiLAogICJcdTc3RjMiLAogICJcdTJGNzAiLAogICJcdTc5M0EiLAogICJcdTJGNzEiLAogICJcdTc5QjgiLAogICJcdTJGNzIiLAogICJcdTc5QkUiLAogICJcdTJGNzMiLAogICJcdTdBNzQiLAogICJcdTJGNzQiLAogICJcdTdBQ0IiLAogICJcdTJGNzUiLAogICJcdTdBRjkiLAogICJcdTJGNzYiLAogICJcdTdDNzMiLAogICJcdTJGNzciLAogICJcdTdDRjgiLAogICJcdTJGNzgiLAogICJcdTdGMzYiLAogICJcdTJGNzkiLAogICJcdTdGNTEiLAogICJcdTJGN0EiLAogICJcdTdGOEEiLAogICJcdTJGN0IiLAogICJcdTdGQkQiLAogICJcdTJGN0MiLAogICJcdTgwMDEiLAogICJcdTJGN0QiLAogICJcdTgwMEMiLAogICJcdTJGN0UiLAogICJcdTgwMTIiLAogICJcdTJGN0YiLAogICJcdTgwMzMiLAogICJcdTJGODAiLAogICJcdTgwN0YiLAogICJcdTJGODEiLAogICJcdTgwODkiLAogICJcdTJGODIiLAogICJcdTgxRTMiLAogICJcdTJGODMiLAogICJcdTgxRUEiLAogICJcdTJGODQiLAogICJcdTgxRjMiLAogICJcdTJGODUiLAogICJcdTgxRkMiLAogICJcdTJGODYiLAogICJcdTgyMEMiLAogICJcdTJGODciLAogICJcdTgyMUIiLAogICJcdTJGODgiLAogICJcdTgyMUYiLAogICJcdTJGODkiLAogICJcdTgyNkUiLAogICJcdTJGOEEiLAogICJcdTgyNzIiLAogICJcdTJGOEIiLAogICJcdTgyNzgiLAogICJcdTJGOEMiLAogICJcdTg2NEQiLAogICJcdTJGOEQiLAogICJcdTg2NkIiLAogICJcdTJGOEUiLAogICJcdTg4NDAiLAogICJcdTJGOEYiLAogICJcdTg4NEMiLAogICJcdTJGOTAiLAogICJcdTg4NjMiLAogICJcdTJGOTEiLAogICJcdTg5N0UiLAogICJcdTJGOTIiLAogICJcdTg5OEIiLAogICJcdTJGOTMiLAogICJcdTg5RDIiLAogICJcdTJGOTQiLAogICJcdThBMDAiLAogICJcdTJGOTUiLAogICJcdThDMzciLAogICJcdTJGOTYiLAogICJcdThDNDYiLAogICJcdTJGOTciLAogICJcdThDNTUiLAogICJcdTJGOTgiLAogICJcdThDNzgiLAogICJcdTJGOTkiLAogICJcdThDOUQiLAogICJcdTJGOUEiLAogICJcdThENjQiLAogICJcdTJGOUIiLAogICJcdThENzAiLAogICJcdTJGOUMiLAogICJcdThEQjMiLAogICJcdTJGOUQiLAogICJcdThFQUIiLAogICJcdTJGOUUiLAogICJcdThFQ0EiLAogICJcdTJGOUYiLAogICJcdThGOUIiLAogICJcdTJGQTAiLAogICJcdThGQjAiLAogICJcdTJGQTEiLAogICJcdThGQjUiLAogICJcdTJGQTIiLAogICJcdTkwOTEiLAogICJcdTJGQTMiLAogICJcdTkxNDkiLAogICJcdTJGQTQiLAogICJcdTkxQzYiLAogICJcdTJGQTUiLAogICJcdTkxQ0MiLAogICJcdTJGQTYiLAogICJcdTkxRDEiLAogICJcdTJGQTciLAogICJcdTk1NzciLAogICJcdTJGQTgiLAogICJcdTk1ODAiLAogICJcdTJGQTkiLAogICJcdTk2MUMiLAogICJcdTJGQUEiLAogICJcdTk2QjYiLAogICJcdTJGQUIiLAogICJcdTk2QjkiLAogICJcdTJGQUMiLAogICJcdTk2RTgiLAogICJcdTJGQUQiLAogICJcdTk3NTEiLAogICJcdTJGQUUiLAogICJcdTk3NUUiLAogICJcdTJGQUYiLAogICJcdTk3NjIiLAogICJcdTJGQjAiLAogICJcdTk3NjkiLAogICJcdTJGQjEiLAogICJcdTk3Q0IiLAogICJcdTJGQjIiLAogICJcdTk3RUQiLAogICJcdTJGQjMiLAogICJcdTk3RjMiLAogICJcdTJGQjQiLAogICJcdTk4MDEiLAogICJcdTJGQjUiLAogICJcdTk4QTgiLAogICJcdTJGQjYiLAogICJcdTk4REIiLAogICJcdTJGQjciLAogICJcdTk4REYiLAogICJcdTJGQjgiLAogICJcdTk5OTYiLAogICJcdTJGQjkiLAogICJcdTk5OTkiLAogICJcdTJGQkEiLAogICJcdTk5QUMiLAogICJcdTJGQkIiLAogICJcdTlBQTgiLAogICJcdTJGQkMiLAogICJcdTlBRDgiLAogICJcdTJGQkQiLAogICJcdTlBREYiLAogICJcdTJGQkUiLAogICJcdTlCMjUiLAogICJcdTJGQkYiLAogICJcdTlCMkYiLAogICJcdTJGQzAiLAogICJcdTlCMzIiLAogICJcdTJGQzEiLAogICJcdTlCM0MiLAogICJcdTJGQzIiLAogICJcdTlCNUEiLAogICJcdTJGQzMiLAogICJcdTlDRTUiLAogICJcdTJGQzQiLAogICJcdTlFNzUiLAogICJcdTJGQzUiLAogICJcdTlFN0YiLAogICJcdTJGQzYiLAogICJcdTlFQTUiLAogICJcdTJGQzciLAogICJcdTlFQkIiLAogICJcdTJGQzgiLAogICJcdTlFQzMiLAogICJcdTJGQzkiLAogICJcdTlFQ0QiLAogICJcdTJGQ0EiLAogICJcdTlFRDEiLAogICJcdTJGQ0IiLAogICJcdTlFRjkiLAogICJcdTJGQ0MiLAogICJcdTlFRkQiLAogICJcdTJGQ0QiLAogICJcdTlGMEUiLAogICJcdTJGQ0UiLAogICJcdTlGMTMiLAogICJcdTJGQ0YiLAogICJcdTlGMjAiLAogICJcdTJGRDAiLAogICJcdTlGM0IiLAogICJcdTJGRDEiLAogICJcdTlGNEEiLAogICJcdTJGRDIiLAogICJcdTlGNTIiLAogICJcdTJGRDMiLAogICJcdTlGOEQiLAogICJcdTJGRDQiLAogICJcdTlGOUMiLAogICJcdTJGRDUiLAogICJcdTlGQTAiLAogICJcdTMwMzYiLAogICJcdTMwMTIiLAogICJcdTMwMzgiLAogICJcdTUzNDEiLAogICJcdTMwMzkiLAogICJcdTUzNDQiLAogICJcdTMwM0EiLAogICJcdTUzNDUiLAogICJcdTMwOUIiLAogICJcdTAwMjBcdTMwOTkiLAogICJcdTMwOUMiLAogICJcdTAwMjBcdTMwOUEiLAogICJcdTMxMzEiLAogICJcdTExMDAiLAogICJcdTMxMzIiLAogICJcdTExMDEiLAogICJcdTMxMzMiLAogICJcdTExQUEiLAogICJcdTMxMzQiLAogICJcdTExMDIiLAogICJcdTMxMzUiLAogICJcdTExQUMiLAogICJcdTMxMzYiLAogICJcdTExQUQiLAogICJcdTMxMzciLAogICJcdTExMDMiLAogICJcdTMxMzgiLAogICJcdTExMDQiLAogICJcdTMxMzkiLAogICJcdTExMDUiLAogICJcdTMxM0EiLAogICJcdTExQjAiLAogICJcdTMxM0IiLAogICJcdTExQjEiLAogICJcdTMxM0MiLAogICJcdTExQjIiLAogICJcdTMxM0QiLAogICJcdTExQjMiLAogICJcdTMxM0UiLAogICJcdTExQjQiLAogICJcdTMxM0YiLAogICJcdTExQjUiLAogICJcdTMxNDAiLAogICJcdTExMUEiLAogICJcdTMxNDEiLAogICJcdTExMDYiLAogICJcdTMxNDIiLAogICJcdTExMDciLAogICJcdTMxNDMiLAogICJcdTExMDgiLAogICJcdTMxNDQiLAogICJcdTExMjEiLAogICJcdTMxNDUiLAogICJcdTExMDkiLAogICJcdTMxNDYiLAogICJcdTExMEEiLAogICJcdTMxNDciLAogICJcdTExMEIiLAogICJcdTMxNDgiLAogICJcdTExMEMiLAogICJcdTMxNDkiLAogICJcdTExMEQiLAogICJcdTMxNEEiLAogICJcdTExMEUiLAogICJcdTMxNEIiLAogICJcdTExMEYiLAogICJcdTMxNEMiLAogICJcdTExMTAiLAogICJcdTMxNEQiLAogICJcdTExMTEiLAogICJcdTMxNEUiLAogICJcdTExMTIiLAogICJcdTMxNEYiLAogICJcdTExNjEiLAogICJcdTMxNTAiLAogICJcdTExNjIiLAogICJcdTMxNTEiLAogICJcdTExNjMiLAogICJcdTMxNTIiLAogICJcdTExNjQiLAogICJcdTMxNTMiLAogICJcdTExNjUiLAogICJcdTMxNTQiLAogICJcdTExNjYiLAogICJcdTMxNTUiLAogICJcdTExNjciLAogICJcdTMxNTYiLAogICJcdTExNjgiLAogICJcdTMxNTciLAogICJcdTExNjkiLAogICJcdTMxNTgiLAogICJcdTExNkEiLAogICJcdTMxNTkiLAogICJcdTExNkIiLAogICJcdTMxNUEiLAogICJcdTExNkMiLAogICJcdTMxNUIiLAogICJcdTExNkQiLAogICJcdTMxNUMiLAogICJcdTExNkUiLAogICJcdTMxNUQiLAogICJcdTExNkYiLAogICJcdTMxNUUiLAogICJcdTExNzAiLAogICJcdTMxNUYiLAogICJcdTExNzEiLAogICJcdTMxNjAiLAogICJcdTExNzIiLAogICJcdTMxNjEiLAogICJcdTExNzMiLAogICJcdTMxNjIiLAogICJcdTExNzQiLAogICJcdTMxNjMiLAogICJcdTExNzUiLAogICJcdTMxNjQiLAogICJcdTExNjAiLAogICJcdTMxNjUiLAogICJcdTExMTQiLAogICJcdTMxNjYiLAogICJcdTExMTUiLAogICJcdTMxNjciLAogICJcdTExQzciLAogICJcdTMxNjgiLAogICJcdTExQzgiLAogICJcdTMxNjkiLAogICJcdTExQ0MiLAogICJcdTMxNkEiLAogICJcdTExQ0UiLAogICJcdTMxNkIiLAogICJcdTExRDMiLAogICJcdTMxNkMiLAogICJcdTExRDciLAogICJcdTMxNkQiLAogICJcdTExRDkiLAogICJcdTMxNkUiLAogICJcdTExMUMiLAogICJcdTMxNkYiLAogICJcdTExREQiLAogICJcdTMxNzAiLAogICJcdTExREYiLAogICJcdTMxNzEiLAogICJcdTExMUQiLAogICJcdTMxNzIiLAogICJcdTExMUUiLAogICJcdTMxNzMiLAogICJcdTExMjAiLAogICJcdTMxNzQiLAogICJcdTExMjIiLAogICJcdTMxNzUiLAogICJcdTExMjMiLAogICJcdTMxNzYiLAogICJcdTExMjciLAogICJcdTMxNzciLAogICJcdTExMjkiLAogICJcdTMxNzgiLAogICJcdTExMkIiLAogICJcdTMxNzkiLAogICJcdTExMkMiLAogICJcdTMxN0EiLAogICJcdTExMkQiLAogICJcdTMxN0IiLAogICJcdTExMkUiLAogICJcdTMxN0MiLAogICJcdTExMkYiLAogICJcdTMxN0QiLAogICJcdTExMzIiLAogICJcdTMxN0UiLAogICJcdTExMzYiLAogICJcdTMxN0YiLAogICJcdTExNDAiLAogICJcdTMxODAiLAogICJcdTExNDciLAogICJcdTMxODEiLAogICJcdTExNEMiLAogICJcdTMxODIiLAogICJcdTExRjEiLAogICJcdTMxODMiLAogICJcdTExRjIiLAogICJcdTMxODQiLAogICJcdTExNTciLAogICJcdTMxODUiLAogICJcdTExNTgiLAogICJcdTMxODYiLAogICJcdTExNTkiLAogICJcdTMxODciLAogICJcdTExODQiLAogICJcdTMxODgiLAogICJcdTExODUiLAogICJcdTMxODkiLAogICJcdTExODgiLAogICJcdTMxOEEiLAogICJcdTExOTEiLAogICJcdTMxOEIiLAogICJcdTExOTIiLAogICJcdTMxOEMiLAogICJcdTExOTQiLAogICJcdTMxOEQiLAogICJcdTExOUUiLAogICJcdTMxOEUiLAogICJcdTExQTEiLAogICJcdTMyMDAiLAogICJcdTAwMjhcdTExMDBcdTAwMjkiLAogICJcdTMyMDEiLAogICJcdTAwMjhcdTExMDJcdTAwMjkiLAogICJcdTMyMDIiLAogICJcdTAwMjhcdTExMDNcdTAwMjkiLAogICJcdTMyMDMiLAogICJcdTAwMjhcdTExMDVcdTAwMjkiLAogICJcdTMyMDQiLAogICJcdTAwMjhcdTExMDZcdTAwMjkiLAogICJcdTMyMDUiLAogICJcdTAwMjhcdTExMDdcdTAwMjkiLAogICJcdTMyMDYiLAogICJcdTAwMjhcdTExMDlcdTAwMjkiLAogICJcdTMyMDciLAogICJcdTAwMjhcdTExMEJcdTAwMjkiLAogICJcdTMyMDgiLAogICJcdTAwMjhcdTExMENcdTAwMjkiLAogICJcdTMyMDkiLAogICJcdTAwMjhcdTExMEVcdTAwMjkiLAogICJcdTMyMEEiLAogICJcdTAwMjhcdTExMEZcdTAwMjkiLAogICJcdTMyMEIiLAogICJcdTAwMjhcdTExMTBcdTAwMjkiLAogICJcdTMyMEMiLAogICJcdTAwMjhcdTExMTFcdTAwMjkiLAogICJcdTMyMEQiLAogICJcdTAwMjhcdTExMTJcdTAwMjkiLAogICJcdTMyMEUiLAogICJcdTAwMjhcdTExMDBcdTExNjFcdTAwMjkiLAogICJcdTMyMEYiLAogICJcdTAwMjhcdTExMDJcdTExNjFcdTAwMjkiLAogICJcdTMyMTAiLAogICJcdTAwMjhcdTExMDNcdTExNjFcdTAwMjkiLAogICJcdTMyMTEiLAogICJcdTAwMjhcdTExMDVcdTExNjFcdTAwMjkiLAogICJcdTMyMTIiLAogICJcdTAwMjhcdTExMDZcdTExNjFcdTAwMjkiLAogICJcdTMyMTMiLAogICJcdTAwMjhcdTExMDdcdTExNjFcdTAwMjkiLAogICJcdTMyMTQiLAogICJcdTAwMjhcdTExMDlcdTExNjFcdTAwMjkiLAogICJcdTMyMTUiLAogICJcdTAwMjhcdTExMEJcdTExNjFcdTAwMjkiLAogICJcdTMyMTYiLAogICJcdTAwMjhcdTExMENcdTExNjFcdTAwMjkiLAogICJcdTMyMTciLAogICJcdTAwMjhcdTExMEVcdTExNjFcdTAwMjkiLAogICJcdTMyMTgiLAogICJcdTAwMjhcdTExMEZcdTExNjFcdTAwMjkiLAogICJcdTMyMTkiLAogICJcdTAwMjhcdTExMTBcdTExNjFcdTAwMjkiLAogICJcdTMyMUEiLAogICJcdTAwMjhcdTExMTFcdTExNjFcdTAwMjkiLAogICJcdTMyMUIiLAogICJcdTAwMjhcdTExMTJcdTExNjFcdTAwMjkiLAogICJcdTMyMUMiLAogICJcdTAwMjhcdTExMENcdTExNkVcdTAwMjkiLAogICJcdTMyMUQiLAogICJcdTAwMjhcdTExMEJcdTExNjlcdTExMENcdTExNjVcdTExQUJcdTAwMjkiLAogICJcdTMyMUUiLAogICJcdTAwMjhcdTExMEJcdTExNjlcdTExMTJcdTExNkVcdTAwMjkiLAogICJcdTMyMjAiLAogICJcdTAwMjhcdTRFMDBcdTAwMjkiLAogICJcdTMyMjEiLAogICJcdTAwMjhcdTRFOENcdTAwMjkiLAogICJcdTMyMjIiLAogICJcdTAwMjhcdTRFMDlcdTAwMjkiLAogICJcdTMyMjMiLAogICJcdTAwMjhcdTU2REJcdTAwMjkiLAogICJcdTMyMjQiLAogICJcdTAwMjhcdTRFOTRcdTAwMjkiLAogICJcdTMyMjUiLAogICJcdTAwMjhcdTUxNkRcdTAwMjkiLAogICJcdTMyMjYiLAogICJcdTAwMjhcdTRFMDNcdTAwMjkiLAogICJcdTMyMjciLAogICJcdTAwMjhcdTUxNkJcdTAwMjkiLAogICJcdTMyMjgiLAogICJcdTAwMjhcdTRFNURcdTAwMjkiLAogICJcdTMyMjkiLAogICJcdTAwMjhcdTUzNDFcdTAwMjkiLAogICJcdTMyMkEiLAogICJcdTAwMjhcdTY3MDhcdTAwMjkiLAogICJcdTMyMkIiLAogICJcdTAwMjhcdTcwNkJcdTAwMjkiLAogICJcdTMyMkMiLAogICJcdTAwMjhcdTZDMzRcdTAwMjkiLAogICJcdTMyMkQiLAogICJcdTAwMjhcdTY3MjhcdTAwMjkiLAogICJcdTMyMkUiLAogICJcdTAwMjhcdTkxRDFcdTAwMjkiLAogICJcdTMyMkYiLAogICJcdTAwMjhcdTU3MUZcdTAwMjkiLAogICJcdTMyMzAiLAogICJcdTAwMjhcdTY1RTVcdTAwMjkiLAogICJcdTMyMzEiLAogICJcdTAwMjhcdTY4MkFcdTAwMjkiLAogICJcdTMyMzIiLAogICJcdTAwMjhcdTY3MDlcdTAwMjkiLAogICJcdTMyMzMiLAogICJcdTAwMjhcdTc5M0VcdTAwMjkiLAogICJcdTMyMzQiLAogICJcdTAwMjhcdTU0MERcdTAwMjkiLAogICJcdTMyMzUiLAogICJcdTAwMjhcdTcyNzlcdTAwMjkiLAogICJcdTMyMzYiLAogICJcdTAwMjhcdThDQTFcdTAwMjkiLAogICJcdTMyMzciLAogICJcdTAwMjhcdTc5NURcdTAwMjkiLAogICJcdTMyMzgiLAogICJcdTAwMjhcdTUyQjRcdTAwMjkiLAogICJcdTMyMzkiLAogICJcdTAwMjhcdTRFRTNcdTAwMjkiLAogICJcdTMyM0EiLAogICJcdTAwMjhcdTU0N0NcdTAwMjkiLAogICJcdTMyM0IiLAogICJcdTAwMjhcdTVCNjZcdTAwMjkiLAogICJcdTMyM0MiLAogICJcdTAwMjhcdTc2RTNcdTAwMjkiLAogICJcdTMyM0QiLAogICJcdTAwMjhcdTRGMDFcdTAwMjkiLAogICJcdTMyM0UiLAogICJcdTAwMjhcdThDQzdcdTAwMjkiLAogICJcdTMyM0YiLAogICJcdTAwMjhcdTUzNTRcdTAwMjkiLAogICJcdTMyNDAiLAogICJcdTAwMjhcdTc5NkRcdTAwMjkiLAogICJcdTMyNDEiLAogICJcdTAwMjhcdTRGMTFcdTAwMjkiLAogICJcdTMyNDIiLAogICJcdTAwMjhcdTgxRUFcdTAwMjkiLAogICJcdTMyNDMiLAogICJcdTAwMjhcdTgxRjNcdTAwMjkiLAogICJcdTMyQzAiLAogICJcdTAwMzFcdTY3MDgiLAogICJcdTMyQzEiLAogICJcdTAwMzJcdTY3MDgiLAogICJcdTMyQzIiLAogICJcdTAwMzNcdTY3MDgiLAogICJcdTMyQzMiLAogICJcdTAwMzRcdTY3MDgiLAogICJcdTMyQzQiLAogICJcdTAwMzVcdTY3MDgiLAogICJcdTMyQzUiLAogICJcdTAwMzZcdTY3MDgiLAogICJcdTMyQzYiLAogICJcdTAwMzdcdTY3MDgiLAogICJcdTMyQzciLAogICJcdTAwMzhcdTY3MDgiLAogICJcdTMyQzgiLAogICJcdTAwMzlcdTY3MDgiLAogICJcdTMyQzkiLAogICJcdTAwMzFcdTAwMzBcdTY3MDgiLAogICJcdTMyQ0EiLAogICJcdTAwMzFcdTAwMzFcdTY3MDgiLAogICJcdTMyQ0IiLAogICJcdTAwMzFcdTAwMzJcdTY3MDgiLAogICJcdTMzNTgiLAogICJcdTAwMzBcdTcwQjkiLAogICJcdTMzNTkiLAogICJcdTAwMzFcdTcwQjkiLAogICJcdTMzNUEiLAogICJcdTAwMzJcdTcwQjkiLAogICJcdTMzNUIiLAogICJcdTAwMzNcdTcwQjkiLAogICJcdTMzNUMiLAogICJcdTAwMzRcdTcwQjkiLAogICJcdTMzNUQiLAogICJcdTAwMzVcdTcwQjkiLAogICJcdTMzNUUiLAogICJcdTAwMzZcdTcwQjkiLAogICJcdTMzNUYiLAogICJcdTAwMzdcdTcwQjkiLAogICJcdTMzNjAiLAogICJcdTAwMzhcdTcwQjkiLAogICJcdTMzNjEiLAogICJcdTAwMzlcdTcwQjkiLAogICJcdTMzNjIiLAogICJcdTAwMzFcdTAwMzBcdTcwQjkiLAogICJcdTMzNjMiLAogICJcdTAwMzFcdTAwMzFcdTcwQjkiLAogICJcdTMzNjQiLAogICJcdTAwMzFcdTAwMzJcdTcwQjkiLAogICJcdTMzNjUiLAogICJcdTAwMzFcdTAwMzNcdTcwQjkiLAogICJcdTMzNjYiLAogICJcdTAwMzFcdTAwMzRcdTcwQjkiLAogICJcdTMzNjciLAogICJcdTAwMzFcdTAwMzVcdTcwQjkiLAogICJcdTMzNjgiLAogICJcdTAwMzFcdTAwMzZcdTcwQjkiLAogICJcdTMzNjkiLAogICJcdTAwMzFcdTAwMzdcdTcwQjkiLAogICJcdTMzNkEiLAogICJcdTAwMzFcdTAwMzhcdTcwQjkiLAogICJcdTMzNkIiLAogICJcdTAwMzFcdTAwMzlcdTcwQjkiLAogICJcdTMzNkMiLAogICJcdTAwMzJcdTAwMzBcdTcwQjkiLAogICJcdTMzNkQiLAogICJcdTAwMzJcdTAwMzFcdTcwQjkiLAogICJcdTMzNkUiLAogICJcdTAwMzJcdTAwMzJcdTcwQjkiLAogICJcdTMzNkYiLAogICJcdTAwMzJcdTAwMzNcdTcwQjkiLAogICJcdTMzNzAiLAogICJcdTAwMzJcdTAwMzRcdTcwQjkiLAogICJcdTMzRTAiLAogICJcdTAwMzFcdTY1RTUiLAogICJcdTMzRTEiLAogICJcdTAwMzJcdTY1RTUiLAogICJcdTMzRTIiLAogICJcdTAwMzNcdTY1RTUiLAogICJcdTMzRTMiLAogICJcdTAwMzRcdTY1RTUiLAogICJcdTMzRTQiLAogICJcdTAwMzVcdTY1RTUiLAogICJcdTMzRTUiLAogICJcdTAwMzZcdTY1RTUiLAogICJcdTMzRTYiLAogICJcdTAwMzdcdTY1RTUiLAogICJcdTMzRTciLAogICJcdTAwMzhcdTY1RTUiLAogICJcdTMzRTgiLAogICJcdTAwMzlcdTY1RTUiLAogICJcdTMzRTkiLAogICJcdTAwMzFcdTAwMzBcdTY1RTUiLAogICJcdTMzRUEiLAogICJcdTAwMzFcdTAwMzFcdTY1RTUiLAogICJcdTMzRUIiLAogICJcdTAwMzFcdTAwMzJcdTY1RTUiLAogICJcdTMzRUMiLAogICJcdTAwMzFcdTAwMzNcdTY1RTUiLAogICJcdTMzRUQiLAogICJcdTAwMzFcdTAwMzRcdTY1RTUiLAogICJcdTMzRUUiLAogICJcdTAwMzFcdTAwMzVcdTY1RTUiLAogICJcdTMzRUYiLAogICJcdTAwMzFcdTAwMzZcdTY1RTUiLAogICJcdTMzRjAiLAogICJcdTAwMzFcdTAwMzdcdTY1RTUiLAogICJcdTMzRjEiLAogICJcdTAwMzFcdTAwMzhcdTY1RTUiLAogICJcdTMzRjIiLAogICJcdTAwMzFcdTAwMzlcdTY1RTUiLAogICJcdTMzRjMiLAogICJcdTAwMzJcdTAwMzBcdTY1RTUiLAogICJcdTMzRjQiLAogICJcdTAwMzJcdTAwMzFcdTY1RTUiLAogICJcdTMzRjUiLAogICJcdTAwMzJcdTAwMzJcdTY1RTUiLAogICJcdTMzRjYiLAogICJcdTAwMzJcdTAwMzNcdTY1RTUiLAogICJcdTMzRjciLAogICJcdTAwMzJcdTAwMzRcdTY1RTUiLAogICJcdTMzRjgiLAogICJcdTAwMzJcdTAwMzVcdTY1RTUiLAogICJcdTMzRjkiLAogICJcdTAwMzJcdTAwMzZcdTY1RTUiLAogICJcdTMzRkEiLAogICJcdTAwMzJcdTAwMzdcdTY1RTUiLAogICJcdTMzRkIiLAogICJcdTAwMzJcdTAwMzhcdTY1RTUiLAogICJcdTMzRkMiLAogICJcdTAwMzJcdTAwMzlcdTY1RTUiLAogICJcdTMzRkQiLAogICJcdTAwMzNcdTAwMzBcdTY1RTUiLAogICJcdTMzRkUiLAogICJcdTAwMzNcdTAwMzFcdTY1RTUiLAogICJcdUZCMDAiLAogICJcdTAwNjZcdTAwNjYiLAogICJcdUZCMDEiLAogICJcdTAwNjZcdTAwNjkiLAogICJcdUZCMDIiLAogICJcdTAwNjZcdTAwNkMiLAogICJcdUZCMDMiLAogICJcdTAwNjZcdTAwNjZcdTAwNjkiLAogICJcdUZCMDQiLAogICJcdTAwNjZcdTAwNjZcdTAwNkMiLAogICJcdUZCMDUiLAogICJcdTAxN0ZcdTAwNzQiLAogICJcdUZCMDYiLAogICJcdTAwNzNcdTAwNzQiLAogICJcdUZCMTMiLAogICJcdTA1NzRcdTA1NzYiLAogICJcdUZCMTQiLAogICJcdTA1NzRcdTA1NjUiLAogICJcdUZCMTUiLAogICJcdTA1NzRcdTA1NkIiLAogICJcdUZCMTYiLAogICJcdTA1N0VcdTA1NzYiLAogICJcdUZCMTciLAogICJcdTA1NzRcdTA1NkQiLAogICJcdUZCNEYiLAogICJcdTA1RDBcdTA1REMiLAogICJcdUZCNTAiLAogICJcdTA2NzEiLAogICJcdUZCNTEiLAogICJcdTA2NzEiLAogICJcdUZCNTIiLAogICJcdTA2N0IiLAogICJcdUZCNTMiLAogICJcdTA2N0IiLAogICJcdUZCNTQiLAogICJcdTA2N0IiLAogICJcdUZCNTUiLAogICJcdTA2N0IiLAogICJcdUZCNTYiLAogICJcdTA2N0UiLAogICJcdUZCNTciLAogICJcdTA2N0UiLAogICJcdUZCNTgiLAogICJcdTA2N0UiLAogICJcdUZCNTkiLAogICJcdTA2N0UiLAogICJcdUZCNUEiLAogICJcdTA2ODAiLAogICJcdUZCNUIiLAogICJcdTA2ODAiLAogICJcdUZCNUMiLAogICJcdTA2ODAiLAogICJcdUZCNUQiLAogICJcdTA2ODAiLAogICJcdUZCNUUiLAogICJcdTA2N0EiLAogICJcdUZCNUYiLAogICJcdTA2N0EiLAogICJcdUZCNjAiLAogICJcdTA2N0EiLAogICJcdUZCNjEiLAogICJcdTA2N0EiLAogICJcdUZCNjIiLAogICJcdTA2N0YiLAogICJcdUZCNjMiLAogICJcdTA2N0YiLAogICJcdUZCNjQiLAogICJcdTA2N0YiLAogICJcdUZCNjUiLAogICJcdTA2N0YiLAogICJcdUZCNjYiLAogICJcdTA2NzkiLAogICJcdUZCNjciLAogICJcdTA2NzkiLAogICJcdUZCNjgiLAogICJcdTA2NzkiLAogICJcdUZCNjkiLAogICJcdTA2NzkiLAogICJcdUZCNkEiLAogICJcdTA2QTQiLAogICJcdUZCNkIiLAogICJcdTA2QTQiLAogICJcdUZCNkMiLAogICJcdTA2QTQiLAogICJcdUZCNkQiLAogICJcdTA2QTQiLAogICJcdUZCNkUiLAogICJcdTA2QTYiLAogICJcdUZCNkYiLAogICJcdTA2QTYiLAogICJcdUZCNzAiLAogICJcdTA2QTYiLAogICJcdUZCNzEiLAogICJcdTA2QTYiLAogICJcdUZCNzIiLAogICJcdTA2ODQiLAogICJcdUZCNzMiLAogICJcdTA2ODQiLAogICJcdUZCNzQiLAogICJcdTA2ODQiLAogICJcdUZCNzUiLAogICJcdTA2ODQiLAogICJcdUZCNzYiLAogICJcdTA2ODMiLAogICJcdUZCNzciLAogICJcdTA2ODMiLAogICJcdUZCNzgiLAogICJcdTA2ODMiLAogICJcdUZCNzkiLAogICJcdTA2ODMiLAogICJcdUZCN0EiLAogICJcdTA2ODYiLAogICJcdUZCN0IiLAogICJcdTA2ODYiLAogICJcdUZCN0MiLAogICJcdTA2ODYiLAogICJcdUZCN0QiLAogICJcdTA2ODYiLAogICJcdUZCN0UiLAogICJcdTA2ODciLAogICJcdUZCN0YiLAogICJcdTA2ODciLAogICJcdUZCODAiLAogICJcdTA2ODciLAogICJcdUZCODEiLAogICJcdTA2ODciLAogICJcdUZCODIiLAogICJcdTA2OEQiLAogICJcdUZCODMiLAogICJcdTA2OEQiLAogICJcdUZCODQiLAogICJcdTA2OEMiLAogICJcdUZCODUiLAogICJcdTA2OEMiLAogICJcdUZCODYiLAogICJcdTA2OEUiLAogICJcdUZCODciLAogICJcdTA2OEUiLAogICJcdUZCODgiLAogICJcdTA2ODgiLAogICJcdUZCODkiLAogICJcdTA2ODgiLAogICJcdUZCOEEiLAogICJcdTA2OTgiLAogICJcdUZCOEIiLAogICJcdTA2OTgiLAogICJcdUZCOEMiLAogICJcdTA2OTEiLAogICJcdUZCOEQiLAogICJcdTA2OTEiLAogICJcdUZCOEUiLAogICJcdTA2QTkiLAogICJcdUZCOEYiLAogICJcdTA2QTkiLAogICJcdUZCOTAiLAogICJcdTA2QTkiLAogICJcdUZCOTEiLAogICJcdTA2QTkiLAogICJcdUZCOTIiLAogICJcdTA2QUYiLAogICJcdUZCOTMiLAogICJcdTA2QUYiLAogICJcdUZCOTQiLAogICJcdTA2QUYiLAogICJcdUZCOTUiLAogICJcdTA2QUYiLAogICJcdUZCOTYiLAogICJcdTA2QjMiLAogICJcdUZCOTciLAogICJcdTA2QjMiLAogICJcdUZCOTgiLAogICJcdTA2QjMiLAogICJcdUZCOTkiLAogICJcdTA2QjMiLAogICJcdUZCOUEiLAogICJcdTA2QjEiLAogICJcdUZCOUIiLAogICJcdTA2QjEiLAogICJcdUZCOUMiLAogICJcdTA2QjEiLAogICJcdUZCOUQiLAogICJcdTA2QjEiLAogICJcdUZCOUUiLAogICJcdTA2QkEiLAogICJcdUZCOUYiLAogICJcdTA2QkEiLAogICJcdUZCQTAiLAogICJcdTA2QkIiLAogICJcdUZCQTEiLAogICJcdTA2QkIiLAogICJcdUZCQTIiLAogICJcdTA2QkIiLAogICJcdUZCQTMiLAogICJcdTA2QkIiLAogICJcdUZCQTQiLAogICJcdTA2QzAiLAogICJcdUZCQTUiLAogICJcdTA2QzAiLAogICJcdUZCQTYiLAogICJcdTA2QzEiLAogICJcdUZCQTciLAogICJcdTA2QzEiLAogICJcdUZCQTgiLAogICJcdTA2QzEiLAogICJcdUZCQTkiLAogICJcdTA2QzEiLAogICJcdUZCQUEiLAogICJcdTA2QkUiLAogICJcdUZCQUIiLAogICJcdTA2QkUiLAogICJcdUZCQUMiLAogICJcdTA2QkUiLAogICJcdUZCQUQiLAogICJcdTA2QkUiLAogICJcdUZCQUUiLAogICJcdTA2RDIiLAogICJcdUZCQUYiLAogICJcdTA2RDIiLAogICJcdUZCQjAiLAogICJcdTA2RDMiLAogICJcdUZCQjEiLAogICJcdTA2RDMiLAogICJcdUZCRDMiLAogICJcdTA2QUQiLAogICJcdUZCRDQiLAogICJcdTA2QUQiLAogICJcdUZCRDUiLAogICJcdTA2QUQiLAogICJcdUZCRDYiLAogICJcdTA2QUQiLAogICJcdUZCRDciLAogICJcdTA2QzciLAogICJcdUZCRDgiLAogICJcdTA2QzciLAogICJcdUZCRDkiLAogICJcdTA2QzYiLAogICJcdUZCREEiLAogICJcdTA2QzYiLAogICJcdUZCREIiLAogICJcdTA2QzgiLAogICJcdUZCREMiLAogICJcdTA2QzgiLAogICJcdUZCREQiLAogICJcdTA2NzciLAogICJcdUZCREUiLAogICJcdTA2Q0IiLAogICJcdUZCREYiLAogICJcdTA2Q0IiLAogICJcdUZCRTAiLAogICJcdTA2QzUiLAogICJcdUZCRTEiLAogICJcdTA2QzUiLAogICJcdUZCRTIiLAogICJcdTA2QzkiLAogICJcdUZCRTMiLAogICJcdTA2QzkiLAogICJcdUZCRTQiLAogICJcdTA2RDAiLAogICJcdUZCRTUiLAogICJcdTA2RDAiLAogICJcdUZCRTYiLAogICJcdTA2RDAiLAogICJcdUZCRTciLAogICJcdTA2RDAiLAogICJcdUZCRTgiLAogICJcdTA2NDkiLAogICJcdUZCRTkiLAogICJcdTA2NDkiLAogICJcdUZCRUEiLAogICJcdTA2MjZcdTA2MjciLAogICJcdUZCRUIiLAogICJcdTA2MjZcdTA2MjciLAogICJcdUZCRUMiLAogICJcdTA2MjZcdTA2RDUiLAogICJcdUZCRUQiLAogICJcdTA2MjZcdTA2RDUiLAogICJcdUZCRUUiLAogICJcdTA2MjZcdTA2NDgiLAogICJcdUZCRUYiLAogICJcdTA2MjZcdTA2NDgiLAogICJcdUZCRjAiLAogICJcdTA2MjZcdTA2QzciLAogICJcdUZCRjEiLAogICJcdTA2MjZcdTA2QzciLAogICJcdUZCRjIiLAogICJcdTA2MjZcdTA2QzYiLAogICJcdUZCRjMiLAogICJcdTA2MjZcdTA2QzYiLAogICJcdUZCRjQiLAogICJcdTA2MjZcdTA2QzgiLAogICJcdUZCRjUiLAogICJcdTA2MjZcdTA2QzgiLAogICJcdUZCRjYiLAogICJcdTA2MjZcdTA2RDAiLAogICJcdUZCRjciLAogICJcdTA2MjZcdTA2RDAiLAogICJcdUZCRjgiLAogICJcdTA2MjZcdTA2RDAiLAogICJcdUZCRjkiLAogICJcdTA2MjZcdTA2NDkiLAogICJcdUZCRkEiLAogICJcdTA2MjZcdTA2NDkiLAogICJcdUZCRkIiLAogICJcdTA2MjZcdTA2NDkiLAogICJcdUZCRkMiLAogICJcdTA2Q0MiLAogICJcdUZCRkQiLAogICJcdTA2Q0MiLAogICJcdUZCRkUiLAogICJcdTA2Q0MiLAogICJcdUZCRkYiLAogICJcdTA2Q0MiLAogICJcdUZDMDAiLAogICJcdTA2MjZcdTA2MkMiLAogICJcdUZDMDEiLAogICJcdTA2MjZcdTA2MkQiLAogICJcdUZDMDIiLAogICJcdTA2MjZcdTA2NDUiLAogICJcdUZDMDMiLAogICJcdTA2MjZcdTA2NDkiLAogICJcdUZDMDQiLAogICJcdTA2MjZcdTA2NEEiLAogICJcdUZDMDUiLAogICJcdTA2MjhcdTA2MkMiLAogICJcdUZDMDYiLAogICJcdTA2MjhcdTA2MkQiLAogICJcdUZDMDciLAogICJcdTA2MjhcdTA2MkUiLAogICJcdUZDMDgiLAogICJcdTA2MjhcdTA2NDUiLAogICJcdUZDMDkiLAogICJcdTA2MjhcdTA2NDkiLAogICJcdUZDMEEiLAogICJcdTA2MjhcdTA2NEEiLAogICJcdUZDMEIiLAogICJcdTA2MkFcdTA2MkMiLAogICJcdUZDMEMiLAogICJcdTA2MkFcdTA2MkQiLAogICJcdUZDMEQiLAogICJcdTA2MkFcdTA2MkUiLAogICJcdUZDMEUiLAogICJcdTA2MkFcdTA2NDUiLAogICJcdUZDMEYiLAogICJcdTA2MkFcdTA2NDkiLAogICJcdUZDMTAiLAogICJcdTA2MkFcdTA2NEEiLAogICJcdUZDMTEiLAogICJcdTA2MkJcdTA2MkMiLAogICJcdUZDMTIiLAogICJcdTA2MkJcdTA2NDUiLAogICJcdUZDMTMiLAogICJcdTA2MkJcdTA2NDkiLAogICJcdUZDMTQiLAogICJcdTA2MkJcdTA2NEEiLAogICJcdUZDMTUiLAogICJcdTA2MkNcdTA2MkQiLAogICJcdUZDMTYiLAogICJcdTA2MkNcdTA2NDUiLAogICJcdUZDMTciLAogICJcdTA2MkRcdTA2MkMiLAogICJcdUZDMTgiLAogICJcdTA2MkRcdTA2NDUiLAogICJcdUZDMTkiLAogICJcdTA2MkVcdTA2MkMiLAogICJcdUZDMUEiLAogICJcdTA2MkVcdTA2MkQiLAogICJcdUZDMUIiLAogICJcdTA2MkVcdTA2NDUiLAogICJcdUZDMUMiLAogICJcdTA2MzNcdTA2MkMiLAogICJcdUZDMUQiLAogICJcdTA2MzNcdTA2MkQiLAogICJcdUZDMUUiLAogICJcdTA2MzNcdTA2MkUiLAogICJcdUZDMUYiLAogICJcdTA2MzNcdTA2NDUiLAogICJcdUZDMjAiLAogICJcdTA2MzVcdTA2MkQiLAogICJcdUZDMjEiLAogICJcdTA2MzVcdTA2NDUiLAogICJcdUZDMjIiLAogICJcdTA2MzZcdTA2MkMiLAogICJcdUZDMjMiLAogICJcdTA2MzZcdTA2MkQiLAogICJcdUZDMjQiLAogICJcdTA2MzZcdTA2MkUiLAogICJcdUZDMjUiLAogICJcdTA2MzZcdTA2NDUiLAogICJcdUZDMjYiLAogICJcdTA2MzdcdTA2MkQiLAogICJcdUZDMjciLAogICJcdTA2MzdcdTA2NDUiLAogICJcdUZDMjgiLAogICJcdTA2MzhcdTA2NDUiLAogICJcdUZDMjkiLAogICJcdTA2MzlcdTA2MkMiLAogICJcdUZDMkEiLAogICJcdTA2MzlcdTA2NDUiLAogICJcdUZDMkIiLAogICJcdTA2M0FcdTA2MkMiLAogICJcdUZDMkMiLAogICJcdTA2M0FcdTA2NDUiLAogICJcdUZDMkQiLAogICJcdTA2NDFcdTA2MkMiLAogICJcdUZDMkUiLAogICJcdTA2NDFcdTA2MkQiLAogICJcdUZDMkYiLAogICJcdTA2NDFcdTA2MkUiLAogICJcdUZDMzAiLAogICJcdTA2NDFcdTA2NDUiLAogICJcdUZDMzEiLAogICJcdTA2NDFcdTA2NDkiLAogICJcdUZDMzIiLAogICJcdTA2NDFcdTA2NEEiLAogICJcdUZDMzMiLAogICJcdTA2NDJcdTA2MkQiLAogICJcdUZDMzQiLAogICJcdTA2NDJcdTA2NDUiLAogICJcdUZDMzUiLAogICJcdTA2NDJcdTA2NDkiLAogICJcdUZDMzYiLAogICJcdTA2NDJcdTA2NEEiLAogICJcdUZDMzciLAogICJcdTA2NDNcdTA2MjciLAogICJcdUZDMzgiLAogICJcdTA2NDNcdTA2MkMiLAogICJcdUZDMzkiLAogICJcdTA2NDNcdTA2MkQiLAogICJcdUZDM0EiLAogICJcdTA2NDNcdTA2MkUiLAogICJcdUZDM0IiLAogICJcdTA2NDNcdTA2NDQiLAogICJcdUZDM0MiLAogICJcdTA2NDNcdTA2NDUiLAogICJcdUZDM0QiLAogICJcdTA2NDNcdTA2NDkiLAogICJcdUZDM0UiLAogICJcdTA2NDNcdTA2NEEiLAogICJcdUZDM0YiLAogICJcdTA2NDRcdTA2MkMiLAogICJcdUZDNDAiLAogICJcdTA2NDRcdTA2MkQiLAogICJcdUZDNDEiLAogICJcdTA2NDRcdTA2MkUiLAogICJcdUZDNDIiLAogICJcdTA2NDRcdTA2NDUiLAogICJcdUZDNDMiLAogICJcdTA2NDRcdTA2NDkiLAogICJcdUZDNDQiLAogICJcdTA2NDRcdTA2NEEiLAogICJcdUZDNDUiLAogICJcdTA2NDVcdTA2MkMiLAogICJcdUZDNDYiLAogICJcdTA2NDVcdTA2MkQiLAogICJcdUZDNDciLAogICJcdTA2NDVcdTA2MkUiLAogICJcdUZDNDgiLAogICJcdTA2NDVcdTA2NDUiLAogICJcdUZDNDkiLAogICJcdTA2NDVcdTA2NDkiLAogICJcdUZDNEEiLAogICJcdTA2NDVcdTA2NEEiLAogICJcdUZDNEIiLAogICJcdTA2NDZcdTA2MkMiLAogICJcdUZDNEMiLAogICJcdTA2NDZcdTA2MkQiLAogICJcdUZDNEQiLAogICJcdTA2NDZcdTA2MkUiLAogICJcdUZDNEUiLAogICJcdTA2NDZcdTA2NDUiLAogICJcdUZDNEYiLAogICJcdTA2NDZcdTA2NDkiLAogICJcdUZDNTAiLAogICJcdTA2NDZcdTA2NEEiLAogICJcdUZDNTEiLAogICJcdTA2NDdcdTA2MkMiLAogICJcdUZDNTIiLAogICJcdTA2NDdcdTA2NDUiLAogICJcdUZDNTMiLAogICJcdTA2NDdcdTA2NDkiLAogICJcdUZDNTQiLAogICJcdTA2NDdcdTA2NEEiLAogICJcdUZDNTUiLAogICJcdTA2NEFcdTA2MkMiLAogICJcdUZDNTYiLAogICJcdTA2NEFcdTA2MkQiLAogICJcdUZDNTciLAogICJcdTA2NEFcdTA2MkUiLAogICJcdUZDNTgiLAogICJcdTA2NEFcdTA2NDUiLAogICJcdUZDNTkiLAogICJcdTA2NEFcdTA2NDkiLAogICJcdUZDNUEiLAogICJcdTA2NEFcdTA2NEEiLAogICJcdUZDNUIiLAogICJcdTA2MzBcdTA2NzAiLAogICJcdUZDNUMiLAogICJcdTA2MzFcdTA2NzAiLAogICJcdUZDNUQiLAogICJcdTA2NDlcdTA2NzAiLAogICJcdUZDNUUiLAogICJcdTAwMjBcdTA2NENcdTA2NTEiLAogICJcdUZDNUYiLAogICJcdTAwMjBcdTA2NERcdTA2NTEiLAogICJcdUZDNjAiLAogICJcdTAwMjBcdTA2NEVcdTA2NTEiLAogICJcdUZDNjEiLAogICJcdTAwMjBcdTA2NEZcdTA2NTEiLAogICJcdUZDNjIiLAogICJcdTAwMjBcdTA2NTBcdTA2NTEiLAogICJcdUZDNjMiLAogICJcdTAwMjBcdTA2NTFcdTA2NzAiLAogICJcdUZDNjQiLAogICJcdTA2MjZcdTA2MzEiLAogICJcdUZDNjUiLAogICJcdTA2MjZcdTA2MzIiLAogICJcdUZDNjYiLAogICJcdTA2MjZcdTA2NDUiLAogICJcdUZDNjciLAogICJcdTA2MjZcdTA2NDYiLAogICJcdUZDNjgiLAogICJcdTA2MjZcdTA2NDkiLAogICJcdUZDNjkiLAogICJcdTA2MjZcdTA2NEEiLAogICJcdUZDNkEiLAogICJcdTA2MjhcdTA2MzEiLAogICJcdUZDNkIiLAogICJcdTA2MjhcdTA2MzIiLAogICJcdUZDNkMiLAogICJcdTA2MjhcdTA2NDUiLAogICJcdUZDNkQiLAogICJcdTA2MjhcdTA2NDYiLAogICJcdUZDNkUiLAogICJcdTA2MjhcdTA2NDkiLAogICJcdUZDNkYiLAogICJcdTA2MjhcdTA2NEEiLAogICJcdUZDNzAiLAogICJcdTA2MkFcdTA2MzEiLAogICJcdUZDNzEiLAogICJcdTA2MkFcdTA2MzIiLAogICJcdUZDNzIiLAogICJcdTA2MkFcdTA2NDUiLAogICJcdUZDNzMiLAogICJcdTA2MkFcdTA2NDYiLAogICJcdUZDNzQiLAogICJcdTA2MkFcdTA2NDkiLAogICJcdUZDNzUiLAogICJcdTA2MkFcdTA2NEEiLAogICJcdUZDNzYiLAogICJcdTA2MkJcdTA2MzEiLAogICJcdUZDNzciLAogICJcdTA2MkJcdTA2MzIiLAogICJcdUZDNzgiLAogICJcdTA2MkJcdTA2NDUiLAogICJcdUZDNzkiLAogICJcdTA2MkJcdTA2NDYiLAogICJcdUZDN0EiLAogICJcdTA2MkJcdTA2NDkiLAogICJcdUZDN0IiLAogICJcdTA2MkJcdTA2NEEiLAogICJcdUZDN0MiLAogICJcdTA2NDFcdTA2NDkiLAogICJcdUZDN0QiLAogICJcdTA2NDFcdTA2NEEiLAogICJcdUZDN0UiLAogICJcdTA2NDJcdTA2NDkiLAogICJcdUZDN0YiLAogICJcdTA2NDJcdTA2NEEiLAogICJcdUZDODAiLAogICJcdTA2NDNcdTA2MjciLAogICJcdUZDODEiLAogICJcdTA2NDNcdTA2NDQiLAogICJcdUZDODIiLAogICJcdTA2NDNcdTA2NDUiLAogICJcdUZDODMiLAogICJcdTA2NDNcdTA2NDkiLAogICJcdUZDODQiLAogICJcdTA2NDNcdTA2NEEiLAogICJcdUZDODUiLAogICJcdTA2NDRcdTA2NDUiLAogICJcdUZDODYiLAogICJcdTA2NDRcdTA2NDkiLAogICJcdUZDODciLAogICJcdTA2NDRcdTA2NEEiLAogICJcdUZDODgiLAogICJcdTA2NDVcdTA2MjciLAogICJcdUZDODkiLAogICJcdTA2NDVcdTA2NDUiLAogICJcdUZDOEEiLAogICJcdTA2NDZcdTA2MzEiLAogICJcdUZDOEIiLAogICJcdTA2NDZcdTA2MzIiLAogICJcdUZDOEMiLAogICJcdTA2NDZcdTA2NDUiLAogICJcdUZDOEQiLAogICJcdTA2NDZcdTA2NDYiLAogICJcdUZDOEUiLAogICJcdTA2NDZcdTA2NDkiLAogICJcdUZDOEYiLAogICJcdTA2NDZcdTA2NEEiLAogICJcdUZDOTAiLAogICJcdTA2NDlcdTA2NzAiLAogICJcdUZDOTEiLAogICJcdTA2NEFcdTA2MzEiLAogICJcdUZDOTIiLAogICJcdTA2NEFcdTA2MzIiLAogICJcdUZDOTMiLAogICJcdTA2NEFcdTA2NDUiLAogICJcdUZDOTQiLAogICJcdTA2NEFcdTA2NDYiLAogICJcdUZDOTUiLAogICJcdTA2NEFcdTA2NDkiLAogICJcdUZDOTYiLAogICJcdTA2NEFcdTA2NEEiLAogICJcdUZDOTciLAogICJcdTA2MjZcdTA2MkMiLAogICJcdUZDOTgiLAogICJcdTA2MjZcdTA2MkQiLAogICJcdUZDOTkiLAogICJcdTA2MjZcdTA2MkUiLAogICJcdUZDOUEiLAogICJcdTA2MjZcdTA2NDUiLAogICJcdUZDOUIiLAogICJcdTA2MjZcdTA2NDciLAogICJcdUZDOUMiLAogICJcdTA2MjhcdTA2MkMiLAogICJcdUZDOUQiLAogICJcdTA2MjhcdTA2MkQiLAogICJcdUZDOUUiLAogICJcdTA2MjhcdTA2MkUiLAogICJcdUZDOUYiLAogICJcdTA2MjhcdTA2NDUiLAogICJcdUZDQTAiLAogICJcdTA2MjhcdTA2NDciLAogICJcdUZDQTEiLAogICJcdTA2MkFcdTA2MkMiLAogICJcdUZDQTIiLAogICJcdTA2MkFcdTA2MkQiLAogICJcdUZDQTMiLAogICJcdTA2MkFcdTA2MkUiLAogICJcdUZDQTQiLAogICJcdTA2MkFcdTA2NDUiLAogICJcdUZDQTUiLAogICJcdTA2MkFcdTA2NDciLAogICJcdUZDQTYiLAogICJcdTA2MkJcdTA2NDUiLAogICJcdUZDQTciLAogICJcdTA2MkNcdTA2MkQiLAogICJcdUZDQTgiLAogICJcdTA2MkNcdTA2NDUiLAogICJcdUZDQTkiLAogICJcdTA2MkRcdTA2MkMiLAogICJcdUZDQUEiLAogICJcdTA2MkRcdTA2NDUiLAogICJcdUZDQUIiLAogICJcdTA2MkVcdTA2MkMiLAogICJcdUZDQUMiLAogICJcdTA2MkVcdTA2NDUiLAogICJcdUZDQUQiLAogICJcdTA2MzNcdTA2MkMiLAogICJcdUZDQUUiLAogICJcdTA2MzNcdTA2MkQiLAogICJcdUZDQUYiLAogICJcdTA2MzNcdTA2MkUiLAogICJcdUZDQjAiLAogICJcdTA2MzNcdTA2NDUiLAogICJcdUZDQjEiLAogICJcdTA2MzVcdTA2MkQiLAogICJcdUZDQjIiLAogICJcdTA2MzVcdTA2MkUiLAogICJcdUZDQjMiLAogICJcdTA2MzVcdTA2NDUiLAogICJcdUZDQjQiLAogICJcdTA2MzZcdTA2MkMiLAogICJcdUZDQjUiLAogICJcdTA2MzZcdTA2MkQiLAogICJcdUZDQjYiLAogICJcdTA2MzZcdTA2MkUiLAogICJcdUZDQjciLAogICJcdTA2MzZcdTA2NDUiLAogICJcdUZDQjgiLAogICJcdTA2MzdcdTA2MkQiLAogICJcdUZDQjkiLAogICJcdTA2MzhcdTA2NDUiLAogICJcdUZDQkEiLAogICJcdTA2MzlcdTA2MkMiLAogICJcdUZDQkIiLAogICJcdTA2MzlcdTA2NDUiLAogICJcdUZDQkMiLAogICJcdTA2M0FcdTA2MkMiLAogICJcdUZDQkQiLAogICJcdTA2M0FcdTA2NDUiLAogICJcdUZDQkUiLAogICJcdTA2NDFcdTA2MkMiLAogICJcdUZDQkYiLAogICJcdTA2NDFcdTA2MkQiLAogICJcdUZDQzAiLAogICJcdTA2NDFcdTA2MkUiLAogICJcdUZDQzEiLAogICJcdTA2NDFcdTA2NDUiLAogICJcdUZDQzIiLAogICJcdTA2NDJcdTA2MkQiLAogICJcdUZDQzMiLAogICJcdTA2NDJcdTA2NDUiLAogICJcdUZDQzQiLAogICJcdTA2NDNcdTA2MkMiLAogICJcdUZDQzUiLAogICJcdTA2NDNcdTA2MkQiLAogICJcdUZDQzYiLAogICJcdTA2NDNcdTA2MkUiLAogICJcdUZDQzciLAogICJcdTA2NDNcdTA2NDQiLAogICJcdUZDQzgiLAogICJcdTA2NDNcdTA2NDUiLAogICJcdUZDQzkiLAogICJcdTA2NDRcdTA2MkMiLAogICJcdUZDQ0EiLAogICJcdTA2NDRcdTA2MkQiLAogICJcdUZDQ0IiLAogICJcdTA2NDRcdTA2MkUiLAogICJcdUZDQ0MiLAogICJcdTA2NDRcdTA2NDUiLAogICJcdUZDQ0QiLAogICJcdTA2NDRcdTA2NDciLAogICJcdUZDQ0UiLAogICJcdTA2NDVcdTA2MkMiLAogICJcdUZDQ0YiLAogICJcdTA2NDVcdTA2MkQiLAogICJcdUZDRDAiLAogICJcdTA2NDVcdTA2MkUiLAogICJcdUZDRDEiLAogICJcdTA2NDVcdTA2NDUiLAogICJcdUZDRDIiLAogICJcdTA2NDZcdTA2MkMiLAogICJcdUZDRDMiLAogICJcdTA2NDZcdTA2MkQiLAogICJcdUZDRDQiLAogICJcdTA2NDZcdTA2MkUiLAogICJcdUZDRDUiLAogICJcdTA2NDZcdTA2NDUiLAogICJcdUZDRDYiLAogICJcdTA2NDZcdTA2NDciLAogICJcdUZDRDciLAogICJcdTA2NDdcdTA2MkMiLAogICJcdUZDRDgiLAogICJcdTA2NDdcdTA2NDUiLAogICJcdUZDRDkiLAogICJcdTA2NDdcdTA2NzAiLAogICJcdUZDREEiLAogICJcdTA2NEFcdTA2MkMiLAogICJcdUZDREIiLAogICJcdTA2NEFcdTA2MkQiLAogICJcdUZDREMiLAogICJcdTA2NEFcdTA2MkUiLAogICJcdUZDREQiLAogICJcdTA2NEFcdTA2NDUiLAogICJcdUZDREUiLAogICJcdTA2NEFcdTA2NDciLAogICJcdUZDREYiLAogICJcdTA2MjZcdTA2NDUiLAogICJcdUZDRTAiLAogICJcdTA2MjZcdTA2NDciLAogICJcdUZDRTEiLAogICJcdTA2MjhcdTA2NDUiLAogICJcdUZDRTIiLAogICJcdTA2MjhcdTA2NDciLAogICJcdUZDRTMiLAogICJcdTA2MkFcdTA2NDUiLAogICJcdUZDRTQiLAogICJcdTA2MkFcdTA2NDciLAogICJcdUZDRTUiLAogICJcdTA2MkJcdTA2NDUiLAogICJcdUZDRTYiLAogICJcdTA2MkJcdTA2NDciLAogICJcdUZDRTciLAogICJcdTA2MzNcdTA2NDUiLAogICJcdUZDRTgiLAogICJcdTA2MzNcdTA2NDciLAogICJcdUZDRTkiLAogICJcdTA2MzRcdTA2NDUiLAogICJcdUZDRUEiLAogICJcdTA2MzRcdTA2NDciLAogICJcdUZDRUIiLAogICJcdTA2NDNcdTA2NDQiLAogICJcdUZDRUMiLAogICJcdTA2NDNcdTA2NDUiLAogICJcdUZDRUQiLAogICJcdTA2NDRcdTA2NDUiLAogICJcdUZDRUUiLAogICJcdTA2NDZcdTA2NDUiLAogICJcdUZDRUYiLAogICJcdTA2NDZcdTA2NDciLAogICJcdUZDRjAiLAogICJcdTA2NEFcdTA2NDUiLAogICJcdUZDRjEiLAogICJcdTA2NEFcdTA2NDciLAogICJcdUZDRjIiLAogICJcdTA2NDBcdTA2NEVcdTA2NTEiLAogICJcdUZDRjMiLAogICJcdTA2NDBcdTA2NEZcdTA2NTEiLAogICJcdUZDRjQiLAogICJcdTA2NDBcdTA2NTBcdTA2NTEiLAogICJcdUZDRjUiLAogICJcdTA2MzdcdTA2NDkiLAogICJcdUZDRjYiLAogICJcdTA2MzdcdTA2NEEiLAogICJcdUZDRjciLAogICJcdTA2MzlcdTA2NDkiLAogICJcdUZDRjgiLAogICJcdTA2MzlcdTA2NEEiLAogICJcdUZDRjkiLAogICJcdTA2M0FcdTA2NDkiLAogICJcdUZDRkEiLAogICJcdTA2M0FcdTA2NEEiLAogICJcdUZDRkIiLAogICJcdTA2MzNcdTA2NDkiLAogICJcdUZDRkMiLAogICJcdTA2MzNcdTA2NEEiLAogICJcdUZDRkQiLAogICJcdTA2MzRcdTA2NDkiLAogICJcdUZDRkUiLAogICJcdTA2MzRcdTA2NEEiLAogICJcdUZDRkYiLAogICJcdTA2MkRcdTA2NDkiLAogICJcdUZEMDAiLAogICJcdTA2MkRcdTA2NEEiLAogICJcdUZEMDEiLAogICJcdTA2MkNcdTA2NDkiLAogICJcdUZEMDIiLAogICJcdTA2MkNcdTA2NEEiLAogICJcdUZEMDMiLAogICJcdTA2MkVcdTA2NDkiLAogICJcdUZEMDQiLAogICJcdTA2MkVcdTA2NEEiLAogICJcdUZEMDUiLAogICJcdTA2MzVcdTA2NDkiLAogICJcdUZEMDYiLAogICJcdTA2MzVcdTA2NEEiLAogICJcdUZEMDciLAogICJcdTA2MzZcdTA2NDkiLAogICJcdUZEMDgiLAogICJcdTA2MzZcdTA2NEEiLAogICJcdUZEMDkiLAogICJcdTA2MzRcdTA2MkMiLAogICJcdUZEMEEiLAogICJcdTA2MzRcdTA2MkQiLAogICJcdUZEMEIiLAogICJcdTA2MzRcdTA2MkUiLAogICJcdUZEMEMiLAogICJcdTA2MzRcdTA2NDUiLAogICJcdUZEMEQiLAogICJcdTA2MzRcdTA2MzEiLAogICJcdUZEMEUiLAogICJcdTA2MzNcdTA2MzEiLAogICJcdUZEMEYiLAogICJcdTA2MzVcdTA2MzEiLAogICJcdUZEMTAiLAogICJcdTA2MzZcdTA2MzEiLAogICJcdUZEMTEiLAogICJcdTA2MzdcdTA2NDkiLAogICJcdUZEMTIiLAogICJcdTA2MzdcdTA2NEEiLAogICJcdUZEMTMiLAogICJcdTA2MzlcdTA2NDkiLAogICJcdUZEMTQiLAogICJcdTA2MzlcdTA2NEEiLAogICJcdUZEMTUiLAogICJcdTA2M0FcdTA2NDkiLAogICJcdUZEMTYiLAogICJcdTA2M0FcdTA2NEEiLAogICJcdUZEMTciLAogICJcdTA2MzNcdTA2NDkiLAogICJcdUZEMTgiLAogICJcdTA2MzNcdTA2NEEiLAogICJcdUZEMTkiLAogICJcdTA2MzRcdTA2NDkiLAogICJcdUZEMUEiLAogICJcdTA2MzRcdTA2NEEiLAogICJcdUZEMUIiLAogICJcdTA2MkRcdTA2NDkiLAogICJcdUZEMUMiLAogICJcdTA2MkRcdTA2NEEiLAogICJcdUZEMUQiLAogICJcdTA2MkNcdTA2NDkiLAogICJcdUZEMUUiLAogICJcdTA2MkNcdTA2NEEiLAogICJcdUZEMUYiLAogICJcdTA2MkVcdTA2NDkiLAogICJcdUZEMjAiLAogICJcdTA2MkVcdTA2NEEiLAogICJcdUZEMjEiLAogICJcdTA2MzVcdTA2NDkiLAogICJcdUZEMjIiLAogICJcdTA2MzVcdTA2NEEiLAogICJcdUZEMjMiLAogICJcdTA2MzZcdTA2NDkiLAogICJcdUZEMjQiLAogICJcdTA2MzZcdTA2NEEiLAogICJcdUZEMjUiLAogICJcdTA2MzRcdTA2MkMiLAogICJcdUZEMjYiLAogICJcdTA2MzRcdTA2MkQiLAogICJcdUZEMjciLAogICJcdTA2MzRcdTA2MkUiLAogICJcdUZEMjgiLAogICJcdTA2MzRcdTA2NDUiLAogICJcdUZEMjkiLAogICJcdTA2MzRcdTA2MzEiLAogICJcdUZEMkEiLAogICJcdTA2MzNcdTA2MzEiLAogICJcdUZEMkIiLAogICJcdTA2MzVcdTA2MzEiLAogICJcdUZEMkMiLAogICJcdTA2MzZcdTA2MzEiLAogICJcdUZEMkQiLAogICJcdTA2MzRcdTA2MkMiLAogICJcdUZEMkUiLAogICJcdTA2MzRcdTA2MkQiLAogICJcdUZEMkYiLAogICJcdTA2MzRcdTA2MkUiLAogICJcdUZEMzAiLAogICJcdTA2MzRcdTA2NDUiLAogICJcdUZEMzEiLAogICJcdTA2MzNcdTA2NDciLAogICJcdUZEMzIiLAogICJcdTA2MzRcdTA2NDciLAogICJcdUZEMzMiLAogICJcdTA2MzdcdTA2NDUiLAogICJcdUZEMzQiLAogICJcdTA2MzNcdTA2MkMiLAogICJcdUZEMzUiLAogICJcdTA2MzNcdTA2MkQiLAogICJcdUZEMzYiLAogICJcdTA2MzNcdTA2MkUiLAogICJcdUZEMzciLAogICJcdTA2MzRcdTA2MkMiLAogICJcdUZEMzgiLAogICJcdTA2MzRcdTA2MkQiLAogICJcdUZEMzkiLAogICJcdTA2MzRcdTA2MkUiLAogICJcdUZEM0EiLAogICJcdTA2MzdcdTA2NDUiLAogICJcdUZEM0IiLAogICJcdTA2MzhcdTA2NDUiLAogICJcdUZEM0MiLAogICJcdTA2MjdcdTA2NEIiLAogICJcdUZEM0QiLAogICJcdTA2MjdcdTA2NEIiLAogICJcdUZENTAiLAogICJcdTA2MkFcdTA2MkNcdTA2NDUiLAogICJcdUZENTEiLAogICJcdTA2MkFcdTA2MkRcdTA2MkMiLAogICJcdUZENTIiLAogICJcdTA2MkFcdTA2MkRcdTA2MkMiLAogICJcdUZENTMiLAogICJcdTA2MkFcdTA2MkRcdTA2NDUiLAogICJcdUZENTQiLAogICJcdTA2MkFcdTA2MkVcdTA2NDUiLAogICJcdUZENTUiLAogICJcdTA2MkFcdTA2NDVcdTA2MkMiLAogICJcdUZENTYiLAogICJcdTA2MkFcdTA2NDVcdTA2MkQiLAogICJcdUZENTciLAogICJcdTA2MkFcdTA2NDVcdTA2MkUiLAogICJcdUZENTgiLAogICJcdTA2MkNcdTA2NDVcdTA2MkQiLAogICJcdUZENTkiLAogICJcdTA2MkNcdTA2NDVcdTA2MkQiLAogICJcdUZENUEiLAogICJcdTA2MkRcdTA2NDVcdTA2NEEiLAogICJcdUZENUIiLAogICJcdTA2MkRcdTA2NDVcdTA2NDkiLAogICJcdUZENUMiLAogICJcdTA2MzNcdTA2MkRcdTA2MkMiLAogICJcdUZENUQiLAogICJcdTA2MzNcdTA2MkNcdTA2MkQiLAogICJcdUZENUUiLAogICJcdTA2MzNcdTA2MkNcdTA2NDkiLAogICJcdUZENUYiLAogICJcdTA2MzNcdTA2NDVcdTA2MkQiLAogICJcdUZENjAiLAogICJcdTA2MzNcdTA2NDVcdTA2MkQiLAogICJcdUZENjEiLAogICJcdTA2MzNcdTA2NDVcdTA2MkMiLAogICJcdUZENjIiLAogICJcdTA2MzNcdTA2NDVcdTA2NDUiLAogICJcdUZENjMiLAogICJcdTA2MzNcdTA2NDVcdTA2NDUiLAogICJcdUZENjQiLAogICJcdTA2MzVcdTA2MkRcdTA2MkQiLAogICJcdUZENjUiLAogICJcdTA2MzVcdTA2MkRcdTA2MkQiLAogICJcdUZENjYiLAogICJcdTA2MzVcdTA2NDVcdTA2NDUiLAogICJcdUZENjciLAogICJcdTA2MzRcdTA2MkRcdTA2NDUiLAogICJcdUZENjgiLAogICJcdTA2MzRcdTA2MkRcdTA2NDUiLAogICJcdUZENjkiLAogICJcdTA2MzRcdTA2MkNcdTA2NEEiLAogICJcdUZENkEiLAogICJcdTA2MzRcdTA2NDVcdTA2MkUiLAogICJcdUZENkIiLAogICJcdTA2MzRcdTA2NDVcdTA2MkUiLAogICJcdUZENkMiLAogICJcdTA2MzRcdTA2NDVcdTA2NDUiLAogICJcdUZENkQiLAogICJcdTA2MzRcdTA2NDVcdTA2NDUiLAogICJcdUZENkUiLAogICJcdTA2MzZcdTA2MkRcdTA2NDkiLAogICJcdUZENkYiLAogICJcdTA2MzZcdTA2MkVcdTA2NDUiLAogICJcdUZENzAiLAogICJcdTA2MzZcdTA2MkVcdTA2NDUiLAogICJcdUZENzEiLAogICJcdTA2MzdcdTA2NDVcdTA2MkQiLAogICJcdUZENzIiLAogICJcdTA2MzdcdTA2NDVcdTA2MkQiLAogICJcdUZENzMiLAogICJcdTA2MzdcdTA2NDVcdTA2NDUiLAogICJcdUZENzQiLAogICJcdTA2MzdcdTA2NDVcdTA2NEEiLAogICJcdUZENzUiLAogICJcdTA2MzlcdTA2MkNcdTA2NDUiLAogICJcdUZENzYiLAogICJcdTA2MzlcdTA2NDVcdTA2NDUiLAogICJcdUZENzciLAogICJcdTA2MzlcdTA2NDVcdTA2NDUiLAogICJcdUZENzgiLAogICJcdTA2MzlcdTA2NDVcdTA2NDkiLAogICJcdUZENzkiLAogICJcdTA2M0FcdTA2NDVcdTA2NDUiLAogICJcdUZEN0EiLAogICJcdTA2M0FcdTA2NDVcdTA2NEEiLAogICJcdUZEN0IiLAogICJcdTA2M0FcdTA2NDVcdTA2NDkiLAogICJcdUZEN0MiLAogICJcdTA2NDFcdTA2MkVcdTA2NDUiLAogICJcdUZEN0QiLAogICJcdTA2NDFcdTA2MkVcdTA2NDUiLAogICJcdUZEN0UiLAogICJcdTA2NDJcdTA2NDVcdTA2MkQiLAogICJcdUZEN0YiLAogICJcdTA2NDJcdTA2NDVcdTA2NDUiLAogICJcdUZEODAiLAogICJcdTA2NDRcdTA2MkRcdTA2NDUiLAogICJcdUZEODEiLAogICJcdTA2NDRcdTA2MkRcdTA2NEEiLAogICJcdUZEODIiLAogICJcdTA2NDRcdTA2MkRcdTA2NDkiLAogICJcdUZEODMiLAogICJcdTA2NDRcdTA2MkNcdTA2MkMiLAogICJcdUZEODQiLAogICJcdTA2NDRcdTA2MkNcdTA2MkMiLAogICJcdUZEODUiLAogICJcdTA2NDRcdTA2MkVcdTA2NDUiLAogICJcdUZEODYiLAogICJcdTA2NDRcdTA2MkVcdTA2NDUiLAogICJcdUZEODciLAogICJcdTA2NDRcdTA2NDVcdTA2MkQiLAogICJcdUZEODgiLAogICJcdTA2NDRcdTA2NDVcdTA2MkQiLAogICJcdUZEODkiLAogICJcdTA2NDVcdTA2MkRcdTA2MkMiLAogICJcdUZEOEEiLAogICJcdTA2NDVcdTA2MkRcdTA2NDUiLAogICJcdUZEOEIiLAogICJcdTA2NDVcdTA2MkRcdTA2NEEiLAogICJcdUZEOEMiLAogICJcdTA2NDVcdTA2MkNcdTA2MkQiLAogICJcdUZEOEQiLAogICJcdTA2NDVcdTA2MkNcdTA2NDUiLAogICJcdUZEOEUiLAogICJcdTA2NDVcdTA2MkVcdTA2MkMiLAogICJcdUZEOEYiLAogICJcdTA2NDVcdTA2MkVcdTA2NDUiLAogICJcdUZEOTIiLAogICJcdTA2NDVcdTA2MkNcdTA2MkUiLAogICJcdUZEOTMiLAogICJcdTA2NDdcdTA2NDVcdTA2MkMiLAogICJcdUZEOTQiLAogICJcdTA2NDdcdTA2NDVcdTA2NDUiLAogICJcdUZEOTUiLAogICJcdTA2NDZcdTA2MkRcdTA2NDUiLAogICJcdUZEOTYiLAogICJcdTA2NDZcdTA2MkRcdTA2NDkiLAogICJcdUZEOTciLAogICJcdTA2NDZcdTA2MkNcdTA2NDUiLAogICJcdUZEOTgiLAogICJcdTA2NDZcdTA2MkNcdTA2NDUiLAogICJcdUZEOTkiLAogICJcdTA2NDZcdTA2MkNcdTA2NDkiLAogICJcdUZEOUEiLAogICJcdTA2NDZcdTA2NDVcdTA2NEEiLAogICJcdUZEOUIiLAogICJcdTA2NDZcdTA2NDVcdTA2NDkiLAogICJcdUZEOUMiLAogICJcdTA2NEFcdTA2NDVcdTA2NDUiLAogICJcdUZEOUQiLAogICJcdTA2NEFcdTA2NDVcdTA2NDUiLAogICJcdUZEOUUiLAogICJcdTA2MjhcdTA2MkVcdTA2NEEiLAogICJcdUZEOUYiLAogICJcdTA2MkFcdTA2MkNcdTA2NEEiLAogICJcdUZEQTAiLAogICJcdTA2MkFcdTA2MkNcdTA2NDkiLAogICJcdUZEQTEiLAogICJcdTA2MkFcdTA2MkVcdTA2NEEiLAogICJcdUZEQTIiLAogICJcdTA2MkFcdTA2MkVcdTA2NDkiLAogICJcdUZEQTMiLAogICJcdTA2MkFcdTA2NDVcdTA2NEEiLAogICJcdUZEQTQiLAogICJcdTA2MkFcdTA2NDVcdTA2NDkiLAogICJcdUZEQTUiLAogICJcdTA2MkNcdTA2NDVcdTA2NEEiLAogICJcdUZEQTYiLAogICJcdTA2MkNcdTA2MkRcdTA2NDkiLAogICJcdUZEQTciLAogICJcdTA2MkNcdTA2NDVcdTA2NDkiLAogICJcdUZEQTgiLAogICJcdTA2MzNcdTA2MkVcdTA2NDkiLAogICJcdUZEQTkiLAogICJcdTA2MzVcdTA2MkRcdTA2NEEiLAogICJcdUZEQUEiLAogICJcdTA2MzRcdTA2MkRcdTA2NEEiLAogICJcdUZEQUIiLAogICJcdTA2MzZcdTA2MkRcdTA2NEEiLAogICJcdUZEQUMiLAogICJcdTA2NDRcdTA2MkNcdTA2NEEiLAogICJcdUZEQUQiLAogICJcdTA2NDRcdTA2NDVcdTA2NEEiLAogICJcdUZEQUUiLAogICJcdTA2NEFcdTA2MkRcdTA2NEEiLAogICJcdUZEQUYiLAogICJcdTA2NEFcdTA2MkNcdTA2NEEiLAogICJcdUZEQjAiLAogICJcdTA2NEFcdTA2NDVcdTA2NEEiLAogICJcdUZEQjEiLAogICJcdTA2NDVcdTA2NDVcdTA2NEEiLAogICJcdUZEQjIiLAogICJcdTA2NDJcdTA2NDVcdTA2NEEiLAogICJcdUZEQjMiLAogICJcdTA2NDZcdTA2MkRcdTA2NEEiLAogICJcdUZEQjQiLAogICJcdTA2NDJcdTA2NDVcdTA2MkQiLAogICJcdUZEQjUiLAogICJcdTA2NDRcdTA2MkRcdTA2NDUiLAogICJcdUZEQjYiLAogICJcdTA2MzlcdTA2NDVcdTA2NEEiLAogICJcdUZEQjciLAogICJcdTA2NDNcdTA2NDVcdTA2NEEiLAogICJcdUZEQjgiLAogICJcdTA2NDZcdTA2MkNcdTA2MkQiLAogICJcdUZEQjkiLAogICJcdTA2NDVcdTA2MkVcdTA2NEEiLAogICJcdUZEQkEiLAogICJcdTA2NDRcdTA2MkNcdTA2NDUiLAogICJcdUZEQkIiLAogICJcdTA2NDNcdTA2NDVcdTA2NDUiLAogICJcdUZEQkMiLAogICJcdTA2NDRcdTA2MkNcdTA2NDUiLAogICJcdUZEQkQiLAogICJcdTA2NDZcdTA2MkNcdTA2MkQiLAogICJcdUZEQkUiLAogICJcdTA2MkNcdTA2MkRcdTA2NEEiLAogICJcdUZEQkYiLAogICJcdTA2MkRcdTA2MkNcdTA2NEEiLAogICJcdUZEQzAiLAogICJcdTA2NDVcdTA2MkNcdTA2NEEiLAogICJcdUZEQzEiLAogICJcdTA2NDFcdTA2NDVcdTA2NEEiLAogICJcdUZEQzIiLAogICJcdTA2MjhcdTA2MkRcdTA2NEEiLAogICJcdUZEQzMiLAogICJcdTA2NDNcdTA2NDVcdTA2NDUiLAogICJcdUZEQzQiLAogICJcdTA2MzlcdTA2MkNcdTA2NDUiLAogICJcdUZEQzUiLAogICJcdTA2MzVcdTA2NDVcdTA2NDUiLAogICJcdUZEQzYiLAogICJcdTA2MzNcdTA2MkVcdTA2NEEiLAogICJcdUZEQzciLAogICJcdTA2NDZcdTA2MkNcdTA2NEEiLAogICJcdUZFNDkiLAogICJcdTIwM0UiLAogICJcdUZFNEEiLAogICJcdTIwM0UiLAogICJcdUZFNEIiLAogICJcdTIwM0UiLAogICJcdUZFNEMiLAogICJcdTIwM0UiLAogICJcdUZFNEQiLAogICJcdTAwNUYiLAogICJcdUZFNEUiLAogICJcdTAwNUYiLAogICJcdUZFNEYiLAogICJcdTAwNUYiLAogICJcdUZFODAiLAogICJcdTA2MjEiLAogICJcdUZFODEiLAogICJcdTA2MjIiLAogICJcdUZFODIiLAogICJcdTA2MjIiLAogICJcdUZFODMiLAogICJcdTA2MjMiLAogICJcdUZFODQiLAogICJcdTA2MjMiLAogICJcdUZFODUiLAogICJcdTA2MjQiLAogICJcdUZFODYiLAogICJcdTA2MjQiLAogICJcdUZFODciLAogICJcdTA2MjUiLAogICJcdUZFODgiLAogICJcdTA2MjUiLAogICJcdUZFODkiLAogICJcdTA2MjYiLAogICJcdUZFOEEiLAogICJcdTA2MjYiLAogICJcdUZFOEIiLAogICJcdTA2MjYiLAogICJcdUZFOEMiLAogICJcdTA2MjYiLAogICJcdUZFOEQiLAogICJcdTA2MjciLAogICJcdUZFOEUiLAogICJcdTA2MjciLAogICJcdUZFOEYiLAogICJcdTA2MjgiLAogICJcdUZFOTAiLAogICJcdTA2MjgiLAogICJcdUZFOTEiLAogICJcdTA2MjgiLAogICJcdUZFOTIiLAogICJcdTA2MjgiLAogICJcdUZFOTMiLAogICJcdTA2MjkiLAogICJcdUZFOTQiLAogICJcdTA2MjkiLAogICJcdUZFOTUiLAogICJcdTA2MkEiLAogICJcdUZFOTYiLAogICJcdTA2MkEiLAogICJcdUZFOTciLAogICJcdTA2MkEiLAogICJcdUZFOTgiLAogICJcdTA2MkEiLAogICJcdUZFOTkiLAogICJcdTA2MkIiLAogICJcdUZFOUEiLAogICJcdTA2MkIiLAogICJcdUZFOUIiLAogICJcdTA2MkIiLAogICJcdUZFOUMiLAogICJcdTA2MkIiLAogICJcdUZFOUQiLAogICJcdTA2MkMiLAogICJcdUZFOUUiLAogICJcdTA2MkMiLAogICJcdUZFOUYiLAogICJcdTA2MkMiLAogICJcdUZFQTAiLAogICJcdTA2MkMiLAogICJcdUZFQTEiLAogICJcdTA2MkQiLAogICJcdUZFQTIiLAogICJcdTA2MkQiLAogICJcdUZFQTMiLAogICJcdTA2MkQiLAogICJcdUZFQTQiLAogICJcdTA2MkQiLAogICJcdUZFQTUiLAogICJcdTA2MkUiLAogICJcdUZFQTYiLAogICJcdTA2MkUiLAogICJcdUZFQTciLAogICJcdTA2MkUiLAogICJcdUZFQTgiLAogICJcdTA2MkUiLAogICJcdUZFQTkiLAogICJcdTA2MkYiLAogICJcdUZFQUEiLAogICJcdTA2MkYiLAogICJcdUZFQUIiLAogICJcdTA2MzAiLAogICJcdUZFQUMiLAogICJcdTA2MzAiLAogICJcdUZFQUQiLAogICJcdTA2MzEiLAogICJcdUZFQUUiLAogICJcdTA2MzEiLAogICJcdUZFQUYiLAogICJcdTA2MzIiLAogICJcdUZFQjAiLAogICJcdTA2MzIiLAogICJcdUZFQjEiLAogICJcdTA2MzMiLAogICJcdUZFQjIiLAogICJcdTA2MzMiLAogICJcdUZFQjMiLAogICJcdTA2MzMiLAogICJcdUZFQjQiLAogICJcdTA2MzMiLAogICJcdUZFQjUiLAogICJcdTA2MzQiLAogICJcdUZFQjYiLAogICJcdTA2MzQiLAogICJcdUZFQjciLAogICJcdTA2MzQiLAogICJcdUZFQjgiLAogICJcdTA2MzQiLAogICJcdUZFQjkiLAogICJcdTA2MzUiLAogICJcdUZFQkEiLAogICJcdTA2MzUiLAogICJcdUZFQkIiLAogICJcdTA2MzUiLAogICJcdUZFQkMiLAogICJcdTA2MzUiLAogICJcdUZFQkQiLAogICJcdTA2MzYiLAogICJcdUZFQkUiLAogICJcdTA2MzYiLAogICJcdUZFQkYiLAogICJcdTA2MzYiLAogICJcdUZFQzAiLAogICJcdTA2MzYiLAogICJcdUZFQzEiLAogICJcdTA2MzciLAogICJcdUZFQzIiLAogICJcdTA2MzciLAogICJcdUZFQzMiLAogICJcdTA2MzciLAogICJcdUZFQzQiLAogICJcdTA2MzciLAogICJcdUZFQzUiLAogICJcdTA2MzgiLAogICJcdUZFQzYiLAogICJcdTA2MzgiLAogICJcdUZFQzciLAogICJcdTA2MzgiLAogICJcdUZFQzgiLAogICJcdTA2MzgiLAogICJcdUZFQzkiLAogICJcdTA2MzkiLAogICJcdUZFQ0EiLAogICJcdTA2MzkiLAogICJcdUZFQ0IiLAogICJcdTA2MzkiLAogICJcdUZFQ0MiLAogICJcdTA2MzkiLAogICJcdUZFQ0QiLAogICJcdTA2M0EiLAogICJcdUZFQ0UiLAogICJcdTA2M0EiLAogICJcdUZFQ0YiLAogICJcdTA2M0EiLAogICJcdUZFRDAiLAogICJcdTA2M0EiLAogICJcdUZFRDEiLAogICJcdTA2NDEiLAogICJcdUZFRDIiLAogICJcdTA2NDEiLAogICJcdUZFRDMiLAogICJcdTA2NDEiLAogICJcdUZFRDQiLAogICJcdTA2NDEiLAogICJcdUZFRDUiLAogICJcdTA2NDIiLAogICJcdUZFRDYiLAogICJcdTA2NDIiLAogICJcdUZFRDciLAogICJcdTA2NDIiLAogICJcdUZFRDgiLAogICJcdTA2NDIiLAogICJcdUZFRDkiLAogICJcdTA2NDMiLAogICJcdUZFREEiLAogICJcdTA2NDMiLAogICJcdUZFREIiLAogICJcdTA2NDMiLAogICJcdUZFREMiLAogICJcdTA2NDMiLAogICJcdUZFREQiLAogICJcdTA2NDQiLAogICJcdUZFREUiLAogICJcdTA2NDQiLAogICJcdUZFREYiLAogICJcdTA2NDQiLAogICJcdUZFRTAiLAogICJcdTA2NDQiLAogICJcdUZFRTEiLAogICJcdTA2NDUiLAogICJcdUZFRTIiLAogICJcdTA2NDUiLAogICJcdUZFRTMiLAogICJcdTA2NDUiLAogICJcdUZFRTQiLAogICJcdTA2NDUiLAogICJcdUZFRTUiLAogICJcdTA2NDYiLAogICJcdUZFRTYiLAogICJcdTA2NDYiLAogICJcdUZFRTciLAogICJcdTA2NDYiLAogICJcdUZFRTgiLAogICJcdTA2NDYiLAogICJcdUZFRTkiLAogICJcdTA2NDciLAogICJcdUZFRUEiLAogICJcdTA2NDciLAogICJcdUZFRUIiLAogICJcdTA2NDciLAogICJcdUZFRUMiLAogICJcdTA2NDciLAogICJcdUZFRUQiLAogICJcdTA2NDgiLAogICJcdUZFRUUiLAogICJcdTA2NDgiLAogICJcdUZFRUYiLAogICJcdTA2NDkiLAogICJcdUZFRjAiLAogICJcdTA2NDkiLAogICJcdUZFRjEiLAogICJcdTA2NEEiLAogICJcdUZFRjIiLAogICJcdTA2NEEiLAogICJcdUZFRjMiLAogICJcdTA2NEEiLAogICJcdUZFRjQiLAogICJcdTA2NEEiLAogICJcdUZFRjUiLAogICJcdTA2NDRcdTA2MjIiLAogICJcdUZFRjYiLAogICJcdTA2NDRcdTA2MjIiLAogICJcdUZFRjciLAogICJcdTA2NDRcdTA2MjMiLAogICJcdUZFRjgiLAogICJcdTA2NDRcdTA2MjMiLAogICJcdUZFRjkiLAogICJcdTA2NDRcdTA2MjUiLAogICJcdUZFRkEiLAogICJcdTA2NDRcdTA2MjUiLAogICJcdUZFRkIiLAogICJcdTA2NDRcdTA2MjciLAogICJcdUZFRkMiLAogICJcdTA2NDRcdTA2MjciCiBdOwp9KTsKZnVuY3Rpb24gcmV2ZXJzZUlmUnRsKGNoYXJzKSB7CiBjb25zdCBjaGFyc0xlbmd0aCA9IGNoYXJzLmxlbmd0aDsKIGlmIChjaGFyc0xlbmd0aCA8PSAxIHx8ICFpc1JUTFJhbmdlRm9yKGNoYXJzLmNoYXJDb2RlQXQoMCkpKSB7CiAgcmV0dXJuIGNoYXJzOwogfQogY29uc3QgYnVmID0gW107CiBmb3IgKGxldCBpaSA9IGNoYXJzTGVuZ3RoIC0gMTsgaWkgPj0gMDsgaWktLSkgewogIGJ1Zi5wdXNoKGNoYXJzW2lpXSk7CiB9CiByZXR1cm4gYnVmLmpvaW4oIiIpOwp9CmNvbnN0IFNwZWNpYWxDaGFyUmVnRXhwID0gbmV3IFJlZ0V4cCgiXihcXHMpfChcXHB7TW59KXwoXFxwe0NmfSkkIiwgInUiKTsKY29uc3QgQ2F0ZWdvcnlDYWNoZSA9IG5ldyBNYXAoKTsKZnVuY3Rpb24gZ2V0Q2hhclVuaWNvZGVDYXRlZ29yeShjaGFyKSB7CiBjb25zdCBjYWNoZWRDYXRlZ29yeSA9IENhdGVnb3J5Q2FjaGUuZ2V0KGNoYXIpOwogaWYgKGNhY2hlZENhdGVnb3J5KSB7CiAgcmV0dXJuIGNhY2hlZENhdGVnb3J5OwogfQogY29uc3QgZ3JvdXBzID0gY2hhci5tYXRjaChTcGVjaWFsQ2hhclJlZ0V4cCk7CiBjb25zdCBjYXRlZ29yeSA9IHsKICBpc1doaXRlc3BhY2U6ICEhKGdyb3VwcyAmJiBncm91cHNbMV0pLAogIGlzWmVyb1dpZHRoRGlhY3JpdGljOiAhIShncm91cHMgJiYgZ3JvdXBzWzJdKSwKICBpc0ludmlzaWJsZUZvcm1hdE1hcms6ICEhKGdyb3VwcyAmJiBncm91cHNbM10pCiB9OwogQ2F0ZWdvcnlDYWNoZS5zZXQoY2hhciwgY2F0ZWdvcnkpOwogcmV0dXJuIGNhdGVnb3J5Owp9CmZ1bmN0aW9uIGNsZWFyVW5pY29kZUNhY2hlcygpIHsKIENhdGVnb3J5Q2FjaGUuY2xlYXIoKTsKfQoKCi8qKiovIH0pLAovKiAxNzYgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLmdldFNlcmlmRm9udHMgPSBleHBvcnRzLmdldE5vblN0ZEZvbnRNYXAgPSBleHBvcnRzLmdldEdseXBoTWFwRm9yU3RhbmRhcmRGb250cyA9IGV4cG9ydHMuZ2V0Rm9udE5hbWVUb0ZpbGVNYXAgPSB2b2lkIDA7CmV4cG9ydHMuZ2V0U3RhbmRhcmRGb250TmFtZSA9IGdldFN0YW5kYXJkRm9udE5hbWU7CmV4cG9ydHMuZ2V0U3ltYm9sc0ZvbnRzID0gZXhwb3J0cy5nZXRTdXBwbGVtZW50YWxHbHlwaE1hcEZvckNhbGlicmkgPSBleHBvcnRzLmdldFN1cHBsZW1lbnRhbEdseXBoTWFwRm9yQXJpYWxCbGFjayA9IGV4cG9ydHMuZ2V0U3RkRm9udE1hcCA9IHZvaWQgMDsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX2ZvbnRzX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNzMpOwpjb25zdCBnZXRTdGRGb250TWFwID0gKDAsIF9jb3JlX3V0aWxzLmdldExvb2t1cFRhYmxlRmFjdG9yeSkoZnVuY3Rpb24gKHQpIHsKICB0WyJUaW1lcy1Sb21hbiJdID0gIlRpbWVzLVJvbWFuIjsKICB0LkhlbHZldGljYSA9ICJIZWx2ZXRpY2EiOwogIHQuQ291cmllciA9ICJDb3VyaWVyIjsKICB0LlN5bWJvbCA9ICJTeW1ib2wiOwogIHRbIlRpbWVzLUJvbGQiXSA9ICJUaW1lcy1Cb2xkIjsKICB0WyJIZWx2ZXRpY2EtQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJDb3VyaWVyLUJvbGQiXSA9ICJDb3VyaWVyLUJvbGQiOwogIHQuWmFwZkRpbmdiYXRzID0gIlphcGZEaW5nYmF0cyI7CiAgdFsiVGltZXMtSXRhbGljIl0gPSAiVGltZXMtSXRhbGljIjsKICB0WyJIZWx2ZXRpY2EtT2JsaXF1ZSJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0WyJDb3VyaWVyLU9ibGlxdWUiXSA9ICJDb3VyaWVyLU9ibGlxdWUiOwogIHRbIlRpbWVzLUJvbGRJdGFsaWMiXSA9ICJUaW1lcy1Cb2xkSXRhbGljIjsKICB0WyJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkNvdXJpZXItQm9sZE9ibGlxdWUiXSA9ICJDb3VyaWVyLUJvbGRPYmxpcXVlIjsKICB0LkFyaWFsTmFycm93ID0gIkhlbHZldGljYSI7CiAgdFsiQXJpYWxOYXJyb3ctQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJBcmlhbE5hcnJvdy1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJBcmlhbE5hcnJvdy1JdGFsaWMiXSA9ICJIZWx2ZXRpY2EtT2JsaXF1ZSI7CiAgdC5BcmlhbEJsYWNrID0gIkhlbHZldGljYSI7CiAgdFsiQXJpYWxCbGFjay1Cb2xkIl0gPSAiSGVsdmV0aWNhLUJvbGQiOwogIHRbIkFyaWFsQmxhY2stQm9sZEl0YWxpYyJdID0gIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSI7CiAgdFsiQXJpYWxCbGFjay1JdGFsaWMiXSA9ICJIZWx2ZXRpY2EtT2JsaXF1ZSI7CiAgdFsiQXJpYWwtQmxhY2siXSA9ICJIZWx2ZXRpY2EiOwogIHRbIkFyaWFsLUJsYWNrLUJvbGQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiQXJpYWwtQmxhY2stQm9sZEl0YWxpYyJdID0gIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSI7CiAgdFsiQXJpYWwtQmxhY2stSXRhbGljIl0gPSAiSGVsdmV0aWNhLU9ibGlxdWUiOwogIHQuQXJpYWwgPSAiSGVsdmV0aWNhIjsKICB0WyJBcmlhbC1Cb2xkIl0gPSAiSGVsdmV0aWNhLUJvbGQiOwogIHRbIkFyaWFsLUJvbGRJdGFsaWMiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkFyaWFsLUl0YWxpYyJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0LkFyaWFsTVQgPSAiSGVsdmV0aWNhIjsKICB0WyJBcmlhbC1Cb2xkSXRhbGljTVQiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkFyaWFsLUJvbGRNVCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJBcmlhbC1JdGFsaWNNVCJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0LkFyaWFsVW5pY29kZU1TID0gIkhlbHZldGljYSI7CiAgdFsiQXJpYWxVbmljb2RlTVMtQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJBcmlhbFVuaWNvZGVNUy1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJBcmlhbFVuaWNvZGVNUy1JdGFsaWMiXSA9ICJIZWx2ZXRpY2EtT2JsaXF1ZSI7CiAgdFsiQ291cmllci1Cb2xkSXRhbGljIl0gPSAiQ291cmllci1Cb2xkT2JsaXF1ZSI7CiAgdFsiQ291cmllci1JdGFsaWMiXSA9ICJDb3VyaWVyLU9ibGlxdWUiOwogIHQuQ291cmllck5ldyA9ICJDb3VyaWVyIjsKICB0WyJDb3VyaWVyTmV3LUJvbGQiXSA9ICJDb3VyaWVyLUJvbGQiOwogIHRbIkNvdXJpZXJOZXctQm9sZEl0YWxpYyJdID0gIkNvdXJpZXItQm9sZE9ibGlxdWUiOwogIHRbIkNvdXJpZXJOZXctSXRhbGljIl0gPSAiQ291cmllci1PYmxpcXVlIjsKICB0WyJDb3VyaWVyTmV3UFMtQm9sZEl0YWxpY01UIl0gPSAiQ291cmllci1Cb2xkT2JsaXF1ZSI7CiAgdFsiQ291cmllck5ld1BTLUJvbGRNVCJdID0gIkNvdXJpZXItQm9sZCI7CiAgdFsiQ291cmllck5ld1BTLUl0YWxpY01UIl0gPSAiQ291cmllci1PYmxpcXVlIjsKICB0LkNvdXJpZXJOZXdQU01UID0gIkNvdXJpZXIiOwogIHRbIkhlbHZldGljYS1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJIZWx2ZXRpY2EtSXRhbGljIl0gPSAiSGVsdmV0aWNhLU9ibGlxdWUiOwogIHRbIlN5bWJvbC1Cb2xkIl0gPSAiU3ltYm9sIjsKICB0WyJTeW1ib2wtQm9sZEl0YWxpYyJdID0gIlN5bWJvbCI7CiAgdFsiU3ltYm9sLUl0YWxpYyJdID0gIlN5bWJvbCI7CiAgdC5UaW1lc05ld1JvbWFuID0gIlRpbWVzLVJvbWFuIjsKICB0WyJUaW1lc05ld1JvbWFuLUJvbGQiXSA9ICJUaW1lcy1Cb2xkIjsKICB0WyJUaW1lc05ld1JvbWFuLUJvbGRJdGFsaWMiXSA9ICJUaW1lcy1Cb2xkSXRhbGljIjsKICB0WyJUaW1lc05ld1JvbWFuLUl0YWxpYyJdID0gIlRpbWVzLUl0YWxpYyI7CiAgdC5UaW1lc05ld1JvbWFuUFMgPSAiVGltZXMtUm9tYW4iOwogIHRbIlRpbWVzTmV3Um9tYW5QUy1Cb2xkIl0gPSAiVGltZXMtQm9sZCI7CiAgdFsiVGltZXNOZXdSb21hblBTLUJvbGRJdGFsaWMiXSA9ICJUaW1lcy1Cb2xkSXRhbGljIjsKICB0WyJUaW1lc05ld1JvbWFuUFMtQm9sZEl0YWxpY01UIl0gPSAiVGltZXMtQm9sZEl0YWxpYyI7CiAgdFsiVGltZXNOZXdSb21hblBTLUJvbGRNVCJdID0gIlRpbWVzLUJvbGQiOwogIHRbIlRpbWVzTmV3Um9tYW5QUy1JdGFsaWMiXSA9ICJUaW1lcy1JdGFsaWMiOwogIHRbIlRpbWVzTmV3Um9tYW5QUy1JdGFsaWNNVCJdID0gIlRpbWVzLUl0YWxpYyI7CiAgdC5UaW1lc05ld1JvbWFuUFNNVCA9ICJUaW1lcy1Sb21hbiI7CiAgdFsiVGltZXNOZXdSb21hblBTTVQtQm9sZCJdID0gIlRpbWVzLUJvbGQiOwogIHRbIlRpbWVzTmV3Um9tYW5QU01ULUJvbGRJdGFsaWMiXSA9ICJUaW1lcy1Cb2xkSXRhbGljIjsKICB0WyJUaW1lc05ld1JvbWFuUFNNVC1JdGFsaWMiXSA9ICJUaW1lcy1JdGFsaWMiOwp9KTsKZXhwb3J0cy5nZXRTdGRGb250TWFwID0gZ2V0U3RkRm9udE1hcDsKY29uc3QgZ2V0Rm9udE5hbWVUb0ZpbGVNYXAgPSAoMCwgX2NvcmVfdXRpbHMuZ2V0TG9va3VwVGFibGVGYWN0b3J5KShmdW5jdGlvbiAodCkgewogIHQuQ291cmllciA9ICJGb3hpdEZpeGVkLnBmYiI7CiAgdFsiQ291cmllci1Cb2xkIl0gPSAiRm94aXRGaXhlZEJvbGQucGZiIjsKICB0WyJDb3VyaWVyLUJvbGRPYmxpcXVlIl0gPSAiRm94aXRGaXhlZEJvbGRJdGFsaWMucGZiIjsKICB0WyJDb3VyaWVyLU9ibGlxdWUiXSA9ICJGb3hpdEZpeGVkSXRhbGljLnBmYiI7CiAgdC5IZWx2ZXRpY2EgPSAiRm94aXRTYW5zLnBmYiI7CiAgdFsiSGVsdmV0aWNhLUJvbGQiXSA9ICJGb3hpdFNhbnNCb2xkLnBmYiI7CiAgdFsiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIl0gPSAiRm94aXRTYW5zQm9sZEl0YWxpYy5wZmIiOwogIHRbIkhlbHZldGljYS1PYmxpcXVlIl0gPSAiRm94aXRTYW5zSXRhbGljLnBmYiI7CiAgdFsiVGltZXMtUm9tYW4iXSA9ICJGb3hpdFNlcmlmLnBmYiI7CiAgdFsiVGltZXMtQm9sZCJdID0gIkZveGl0U2VyaWZCb2xkLnBmYiI7CiAgdFsiVGltZXMtQm9sZEl0YWxpYyJdID0gIkZveGl0U2VyaWZCb2xkSXRhbGljLnBmYiI7CiAgdFsiVGltZXMtSXRhbGljIl0gPSAiRm94aXRTZXJpZkl0YWxpYy5wZmIiOwogIHQuU3ltYm9sID0gIkZveGl0U3ltYm9sLnBmYiI7CiAgdC5aYXBmRGluZ2JhdHMgPSAiRm94aXREaW5nYmF0cy5wZmIiOwogIHRbIkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIiXSA9ICJMaWJlcmF0aW9uU2Fucy1SZWd1bGFyLnR0ZiI7CiAgdFsiTGliZXJhdGlvblNhbnMtQm9sZCJdID0gIkxpYmVyYXRpb25TYW5zLUJvbGQudHRmIjsKICB0WyJMaWJlcmF0aW9uU2Fucy1JdGFsaWMiXSA9ICJMaWJlcmF0aW9uU2Fucy1JdGFsaWMudHRmIjsKICB0WyJMaWJlcmF0aW9uU2Fucy1Cb2xkSXRhbGljIl0gPSAiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYy50dGYiOwp9KTsKZXhwb3J0cy5nZXRGb250TmFtZVRvRmlsZU1hcCA9IGdldEZvbnROYW1lVG9GaWxlTWFwOwpjb25zdCBnZXROb25TdGRGb250TWFwID0gKDAsIF9jb3JlX3V0aWxzLmdldExvb2t1cFRhYmxlRmFjdG9yeSkoZnVuY3Rpb24gKHQpIHsKICB0LkNhbGlicmkgPSAiSGVsdmV0aWNhIjsKICB0WyJDYWxpYnJpLUJvbGQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiQ2FsaWJyaS1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJDYWxpYnJpLUl0YWxpYyJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0LkNlbnR1cnlHb3RoaWMgPSAiSGVsdmV0aWNhIjsKICB0WyJDZW50dXJ5R290aGljLUJvbGQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiQ2VudHVyeUdvdGhpYy1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJDZW50dXJ5R290aGljLUl0YWxpYyJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0LkNvbWljU2Fuc01TID0gIkNvbWljIFNhbnMgTVMiOwogIHRbIkNvbWljU2Fuc01TLUJvbGQiXSA9ICJDb21pYyBTYW5zIE1TLUJvbGQiOwogIHRbIkNvbWljU2Fuc01TLUJvbGRJdGFsaWMiXSA9ICJDb21pYyBTYW5zIE1TLUJvbGRJdGFsaWMiOwogIHRbIkNvbWljU2Fuc01TLUl0YWxpYyJdID0gIkNvbWljIFNhbnMgTVMtSXRhbGljIjsKICB0WyJJdGNTeW1ib2wtQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJJdGNTeW1ib2wtQm9sZEl0YWxpYyJdID0gIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSI7CiAgdFsiSXRjU3ltYm9sLUJvb2siXSA9ICJIZWx2ZXRpY2EiOwogIHRbIkl0Y1N5bWJvbC1Cb29rSXRhbGljIl0gPSAiSGVsdmV0aWNhLU9ibGlxdWUiOwogIHRbIkl0Y1N5bWJvbC1NZWRpdW0iXSA9ICJIZWx2ZXRpY2EiOwogIHRbIkl0Y1N5bWJvbC1NZWRpdW1JdGFsaWMiXSA9ICJIZWx2ZXRpY2EtT2JsaXF1ZSI7CiAgdC5MdWNpZGFDb25zb2xlID0gIkNvdXJpZXIiOwogIHRbIkx1Y2lkYUNvbnNvbGUtQm9sZCJdID0gIkNvdXJpZXItQm9sZCI7CiAgdFsiTHVjaWRhQ29uc29sZS1Cb2xkSXRhbGljIl0gPSAiQ291cmllci1Cb2xkT2JsaXF1ZSI7CiAgdFsiTHVjaWRhQ29uc29sZS1JdGFsaWMiXSA9ICJDb3VyaWVyLU9ibGlxdWUiOwogIHRbIkx1Y2lkYVNhbnMtRGVtaSJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJNUy1Hb3RoaWMiXSA9ICJNUyBHb3RoaWMiOwogIHRbIk1TLUdvdGhpYy1Cb2xkIl0gPSAiTVMgR290aGljLUJvbGQiOwogIHRbIk1TLUdvdGhpYy1Cb2xkSXRhbGljIl0gPSAiTVMgR290aGljLUJvbGRJdGFsaWMiOwogIHRbIk1TLUdvdGhpYy1JdGFsaWMiXSA9ICJNUyBHb3RoaWMtSXRhbGljIjsKICB0WyJNUy1NaW5jaG8iXSA9ICJNUyBNaW5jaG8iOwogIHRbIk1TLU1pbmNoby1Cb2xkIl0gPSAiTVMgTWluY2hvLUJvbGQiOwogIHRbIk1TLU1pbmNoby1Cb2xkSXRhbGljIl0gPSAiTVMgTWluY2hvLUJvbGRJdGFsaWMiOwogIHRbIk1TLU1pbmNoby1JdGFsaWMiXSA9ICJNUyBNaW5jaG8tSXRhbGljIjsKICB0WyJNUy1QR290aGljIl0gPSAiTVMgUEdvdGhpYyI7CiAgdFsiTVMtUEdvdGhpYy1Cb2xkIl0gPSAiTVMgUEdvdGhpYy1Cb2xkIjsKICB0WyJNUy1QR290aGljLUJvbGRJdGFsaWMiXSA9ICJNUyBQR290aGljLUJvbGRJdGFsaWMiOwogIHRbIk1TLVBHb3RoaWMtSXRhbGljIl0gPSAiTVMgUEdvdGhpYy1JdGFsaWMiOwogIHRbIk1TLVBNaW5jaG8iXSA9ICJNUyBQTWluY2hvIjsKICB0WyJNUy1QTWluY2hvLUJvbGQiXSA9ICJNUyBQTWluY2hvLUJvbGQiOwogIHRbIk1TLVBNaW5jaG8tQm9sZEl0YWxpYyJdID0gIk1TIFBNaW5jaG8tQm9sZEl0YWxpYyI7CiAgdFsiTVMtUE1pbmNoby1JdGFsaWMiXSA9ICJNUyBQTWluY2hvLUl0YWxpYyI7CiAgdC5OdXB0aWFsU2NyaXB0ID0gIlRpbWVzLUl0YWxpYyI7CiAgdC5TZWdvZVVJU3ltYm9sID0gIkhlbHZldGljYSI7CiAgdC5XaW5nZGluZ3MgPSAiWmFwZkRpbmdiYXRzIjsKICB0WyJXaW5nZGluZ3MtUmVndWxhciJdID0gIlphcGZEaW5nYmF0cyI7Cn0pOwpleHBvcnRzLmdldE5vblN0ZEZvbnRNYXAgPSBnZXROb25TdGRGb250TWFwOwpjb25zdCBnZXRTZXJpZkZvbnRzID0gKDAsIF9jb3JlX3V0aWxzLmdldExvb2t1cFRhYmxlRmFjdG9yeSkoZnVuY3Rpb24gKHQpIHsKICB0WyJBZG9iZSBKZW5zb24iXSA9IHRydWU7CiAgdFsiQWRvYmUgVGV4dCJdID0gdHJ1ZTsKICB0LkFsYmVydHVzID0gdHJ1ZTsKICB0LkFsZHVzID0gdHJ1ZTsKICB0LkFsZXhhbmRyaWEgPSB0cnVlOwogIHQuQWxnZXJpYW4gPSB0cnVlOwogIHRbIkFtZXJpY2FuIFR5cGV3cml0ZXIiXSA9IHRydWU7CiAgdC5BbnRpcXVhID0gdHJ1ZTsKICB0LkFwZXggPSB0cnVlOwogIHQuQXJubyA9IHRydWU7CiAgdC5Bc3RlciA9IHRydWU7CiAgdC5BdXJvcmEgPSB0cnVlOwogIHQuQmFza2VydmlsbGUgPSB0cnVlOwogIHQuQmVsbCA9IHRydWU7CiAgdC5CZW1ibyA9IHRydWU7CiAgdFsiQmVtYm8gU2Nob29sYm9vayJdID0gdHJ1ZTsKICB0LkJlbmd1aWF0ID0gdHJ1ZTsKICB0WyJCZXJrZWxleSBPbGQgU3R5bGUiXSA9IHRydWU7CiAgdFsiQmVybmhhcmQgTW9kZXJuIl0gPSB0cnVlOwogIHRbIkJlcnRob2xkIENpdHkiXSA9IHRydWU7CiAgdC5Cb2RvbmkgPSB0cnVlOwogIHRbIkJhdWVyIEJvZG9uaSJdID0gdHJ1ZTsKICB0WyJCb29rIEFudGlxdWEiXSA9IHRydWU7CiAgdC5Cb29rbWFuID0gdHJ1ZTsKICB0WyJCb3JkZWF1eCBSb21hbiJdID0gdHJ1ZTsKICB0WyJDYWxpZm9ybmlhbiBGQiJdID0gdHJ1ZTsKICB0LkNhbGlzdG8gPSB0cnVlOwogIHQuQ2FsdmVydCA9IHRydWU7CiAgdC5DYXBpdGFscyA9IHRydWU7CiAgdC5DYW1icmlhID0gdHJ1ZTsKICB0LkNhcnRpZXIgPSB0cnVlOwogIHQuQ2FzbG9uID0gdHJ1ZTsKICB0LkNhdHVsbCA9IHRydWU7CiAgdC5DZW50YXVyID0gdHJ1ZTsKICB0WyJDZW50dXJ5IE9sZCBTdHlsZSJdID0gdHJ1ZTsKICB0WyJDZW50dXJ5IFNjaG9vbGJvb2siXSA9IHRydWU7CiAgdC5DaGFwYXJyYWwgPSB0cnVlOwogIHRbIkNoYXJpcyBTSUwiXSA9IHRydWU7CiAgdC5DaGVsdGVuaGFtID0gdHJ1ZTsKICB0WyJDaG9sbGEgU2xhYiJdID0gdHJ1ZTsKICB0LkNsYXJlbmRvbiA9IHRydWU7CiAgdC5DbGVhcmZhY2UgPSB0cnVlOwogIHQuQ29jaGluID0gdHJ1ZTsKICB0LkNvbG9ubmEgPSB0cnVlOwogIHRbIkNvbXB1dGVyIE1vZGVybiJdID0gdHJ1ZTsKICB0WyJDb25jcmV0ZSBSb21hbiJdID0gdHJ1ZTsKICB0LkNvbnN0YW50aWEgPSB0cnVlOwogIHRbIkNvb3BlciBCbGFjayJdID0gdHJ1ZTsKICB0LkNvcm9uYSA9IHRydWU7CiAgdC5FY290eXBlID0gdHJ1ZTsKICB0LkVneXB0aWVubmUgPSB0cnVlOwogIHQuRWxlcGhhbnQgPSB0cnVlOwogIHQuRXhjZWxzaW9yID0gdHJ1ZTsKICB0LkZhaXJmaWVsZCA9IHRydWU7CiAgdFsiRkYgU2NhbGEiXSA9IHRydWU7CiAgdC5Gb2xrYXJkID0gdHJ1ZTsKICB0LkZvb3RsaWdodCA9IHRydWU7CiAgdC5GcmVlU2VyaWYgPSB0cnVlOwogIHRbIkZyaXogUXVhZHJhdGEiXSA9IHRydWU7CiAgdC5HYXJhbW9uZCA9IHRydWU7CiAgdC5HZW50aXVtID0gdHJ1ZTsKICB0Lkdlb3JnaWEgPSB0cnVlOwogIHQuR2xvdWNlc3RlciA9IHRydWU7CiAgdFsiR291ZHkgT2xkIFN0eWxlIl0gPSB0cnVlOwogIHRbIkdvdWR5IFNjaG9vbGJvb2siXSA9IHRydWU7CiAgdFsiR291ZHkgUHJvIEZvbnQiXSA9IHRydWU7CiAgdC5HcmFuam9uID0gdHJ1ZTsKICB0WyJHdWFyZGlhbiBFZ3lwdGlhbiJdID0gdHJ1ZTsKICB0LkhlYXRoZXIgPSB0cnVlOwogIHQuSGVyY3VsZXMgPSB0cnVlOwogIHRbIkhpZ2ggVG93ZXIgVGV4dCJdID0gdHJ1ZTsKICB0Lkhpcm9zaGlnZSA9IHRydWU7CiAgdFsiSG9lZmxlciBUZXh0Il0gPSB0cnVlOwogIHRbIkh1bWFuYSBTZXJpZiJdID0gdHJ1ZTsKICB0LkltcHJpbnQgPSB0cnVlOwogIHRbIklvbmljIE5vLiA1Il0gPSB0cnVlOwogIHQuSmFuc29uID0gdHJ1ZTsKICB0LkpvYW5uYSA9IHRydWU7CiAgdC5Lb3Jpbm5hID0gdHJ1ZTsKICB0LkxleGljb24gPSB0cnVlOwogIHQuTGliZXJhdGlvblNlcmlmID0gdHJ1ZTsKICB0WyJMaWJlcmF0aW9uIFNlcmlmIl0gPSB0cnVlOwogIHRbIkxpbnV4IExpYmVydGluZSJdID0gdHJ1ZTsKICB0LkxpdGVyYXR1cm5heWEgPSB0cnVlOwogIHQuTHVjaWRhID0gdHJ1ZTsKICB0WyJMdWNpZGEgQnJpZ2h0Il0gPSB0cnVlOwogIHQuTWVsaW9yID0gdHJ1ZTsKICB0Lk1lbXBoaXMgPSB0cnVlOwogIHQuTWlsbGVyID0gdHJ1ZTsKICB0Lk1pbmlvbiA9IHRydWU7CiAgdC5Nb2Rlcm4gPSB0cnVlOwogIHRbIk1vbmEgTGlzYSJdID0gdHJ1ZTsKICB0WyJNcnMgRWF2ZXMiXSA9IHRydWU7CiAgdFsiTVMgU2VyaWYiXSA9IHRydWU7CiAgdFsiTXVzZW8gU2xhYiJdID0gdHJ1ZTsKICB0WyJOZXcgWW9yayJdID0gdHJ1ZTsKICB0WyJOaW1idXMgUm9tYW4iXSA9IHRydWU7CiAgdFsiTlBTIFJhd2xpbnNvbiBSb2Fkd2F5Il0gPSB0cnVlOwogIHQuTnVwdGlhbFNjcmlwdCA9IHRydWU7CiAgdC5QYWxhdGlubyA9IHRydWU7CiAgdC5QZXJwZXR1YSA9IHRydWU7CiAgdC5QbGFudGluID0gdHJ1ZTsKICB0WyJQbGFudGluIFNjaG9vbGJvb2siXSA9IHRydWU7CiAgdC5QbGF5YmlsbCA9IHRydWU7CiAgdFsiUG9vciBSaWNoYXJkIl0gPSB0cnVlOwogIHRbIlJhd2xpbnNvbiBSb2Fkd2F5Il0gPSB0cnVlOwogIHQuUmVuYXVsdCA9IHRydWU7CiAgdC5SZXF1aWVtID0gdHJ1ZTsKICB0LlJvY2t3ZWxsID0gdHJ1ZTsKICB0LlJvbWFuID0gdHJ1ZTsKICB0WyJSb3RpcyBTZXJpZiJdID0gdHJ1ZTsKICB0LlNhYm9uID0gdHJ1ZTsKICB0LlNjYWxhID0gdHJ1ZTsKICB0LlNlYWd1bGwgPSB0cnVlOwogIHQuU2lzdGluYSA9IHRydWU7CiAgdC5Tb3V2ZW5pciA9IHRydWU7CiAgdC5TVElYID0gdHJ1ZTsKICB0WyJTdG9uZSBJbmZvcm1hbCJdID0gdHJ1ZTsKICB0WyJTdG9uZSBTZXJpZiJdID0gdHJ1ZTsKICB0LlN5bGZhZW4gPSB0cnVlOwogIHQuVGltZXMgPSB0cnVlOwogIHQuVHJhamFuID0gdHJ1ZTsKICB0WyJUcmluaXTDqSJdID0gdHJ1ZTsKICB0WyJUcnVtcCBNZWRpYWV2YWwiXSA9IHRydWU7CiAgdC5VdG9waWEgPSB0cnVlOwogIHRbIlZhbGUgVHlwZSJdID0gdHJ1ZTsKICB0WyJCaXRzdHJlYW0gVmVyYSJdID0gdHJ1ZTsKICB0WyJWZXJhIFNlcmlmIl0gPSB0cnVlOwogIHQuVmVyc2FpbGxlcyA9IHRydWU7CiAgdC5XYW50ZWQgPSB0cnVlOwogIHQuV2Vpc3MgPSB0cnVlOwogIHRbIldpZGUgTGF0aW4iXSA9IHRydWU7CiAgdC5XaW5kc29yID0gdHJ1ZTsKICB0LlhJVFMgPSB0cnVlOwp9KTsKZXhwb3J0cy5nZXRTZXJpZkZvbnRzID0gZ2V0U2VyaWZGb250czsKY29uc3QgZ2V0U3ltYm9sc0ZvbnRzID0gKDAsIF9jb3JlX3V0aWxzLmdldExvb2t1cFRhYmxlRmFjdG9yeSkoZnVuY3Rpb24gKHQpIHsKICB0LkRpbmdiYXRzID0gdHJ1ZTsKICB0LlN5bWJvbCA9IHRydWU7CiAgdC5aYXBmRGluZ2JhdHMgPSB0cnVlOwp9KTsKZXhwb3J0cy5nZXRTeW1ib2xzRm9udHMgPSBnZXRTeW1ib2xzRm9udHM7CmNvbnN0IGdldEdseXBoTWFwRm9yU3RhbmRhcmRGb250cyA9ICgwLCBfY29yZV91dGlscy5nZXRMb29rdXBUYWJsZUZhY3RvcnkpKGZ1bmN0aW9uICh0KSB7CiAgdFsyXSA9IDEwOwogIHRbM10gPSAzMjsKICB0WzRdID0gMzM7CiAgdFs1XSA9IDM0OwogIHRbNl0gPSAzNTsKICB0WzddID0gMzY7CiAgdFs4XSA9IDM3OwogIHRbOV0gPSAzODsKICB0WzEwXSA9IDM5OwogIHRbMTFdID0gNDA7CiAgdFsxMl0gPSA0MTsKICB0WzEzXSA9IDQyOwogIHRbMTRdID0gNDM7CiAgdFsxNV0gPSA0NDsKICB0WzE2XSA9IDQ1OwogIHRbMTddID0gNDY7CiAgdFsxOF0gPSA0NzsKICB0WzE5XSA9IDQ4OwogIHRbMjBdID0gNDk7CiAgdFsyMV0gPSA1MDsKICB0WzIyXSA9IDUxOwogIHRbMjNdID0gNTI7CiAgdFsyNF0gPSA1MzsKICB0WzI1XSA9IDU0OwogIHRbMjZdID0gNTU7CiAgdFsyN10gPSA1NjsKICB0WzI4XSA9IDU3OwogIHRbMjldID0gNTg7CiAgdFszMF0gPSA4OTQ7CiAgdFszMV0gPSA2MDsKICB0WzMyXSA9IDYxOwogIHRbMzNdID0gNjI7CiAgdFszNF0gPSA2MzsKICB0WzM1XSA9IDY0OwogIHRbMzZdID0gNjU7CiAgdFszN10gPSA2NjsKICB0WzM4XSA9IDY3OwogIHRbMzldID0gNjg7CiAgdFs0MF0gPSA2OTsKICB0WzQxXSA9IDcwOwogIHRbNDJdID0gNzE7CiAgdFs0M10gPSA3MjsKICB0WzQ0XSA9IDczOwogIHRbNDVdID0gNzQ7CiAgdFs0Nl0gPSA3NTsKICB0WzQ3XSA9IDc2OwogIHRbNDhdID0gNzc7CiAgdFs0OV0gPSA3ODsKICB0WzUwXSA9IDc5OwogIHRbNTFdID0gODA7CiAgdFs1Ml0gPSA4MTsKICB0WzUzXSA9IDgyOwogIHRbNTRdID0gODM7CiAgdFs1NV0gPSA4NDsKICB0WzU2XSA9IDg1OwogIHRbNTddID0gODY7CiAgdFs1OF0gPSA4NzsKICB0WzU5XSA9IDg4OwogIHRbNjBdID0gODk7CiAgdFs2MV0gPSA5MDsKICB0WzYyXSA9IDkxOwogIHRbNjNdID0gOTI7CiAgdFs2NF0gPSA5MzsKICB0WzY1XSA9IDk0OwogIHRbNjZdID0gOTU7CiAgdFs2N10gPSA5NjsKICB0WzY4XSA9IDk3OwogIHRbNjldID0gOTg7CiAgdFs3MF0gPSA5OTsKICB0WzcxXSA9IDEwMDsKICB0WzcyXSA9IDEwMTsKICB0WzczXSA9IDEwMjsKICB0Wzc0XSA9IDEwMzsKICB0Wzc1XSA9IDEwNDsKICB0Wzc2XSA9IDEwNTsKICB0Wzc3XSA9IDEwNjsKICB0Wzc4XSA9IDEwNzsKICB0Wzc5XSA9IDEwODsKICB0WzgwXSA9IDEwOTsKICB0WzgxXSA9IDExMDsKICB0WzgyXSA9IDExMTsKICB0WzgzXSA9IDExMjsKICB0Wzg0XSA9IDExMzsKICB0Wzg1XSA9IDExNDsKICB0Wzg2XSA9IDExNTsKICB0Wzg3XSA9IDExNjsKICB0Wzg4XSA9IDExNzsKICB0Wzg5XSA9IDExODsKICB0WzkwXSA9IDExOTsKICB0WzkxXSA9IDEyMDsKICB0WzkyXSA9IDEyMTsKICB0WzkzXSA9IDEyMjsKICB0Wzk0XSA9IDEyMzsKICB0Wzk1XSA9IDEyNDsKICB0Wzk2XSA9IDEyNTsKICB0Wzk3XSA9IDEyNjsKICB0Wzk4XSA9IDE5NjsKICB0Wzk5XSA9IDE5NzsKICB0WzEwMF0gPSAxOTk7CiAgdFsxMDFdID0gMjAxOwogIHRbMTAyXSA9IDIwOTsKICB0WzEwM10gPSAyMTQ7CiAgdFsxMDRdID0gMjIwOwogIHRbMTA1XSA9IDIyNTsKICB0WzEwNl0gPSAyMjQ7CiAgdFsxMDddID0gMjI2OwogIHRbMTA4XSA9IDIyODsKICB0WzEwOV0gPSAyMjc7CiAgdFsxMTBdID0gMjI5OwogIHRbMTExXSA9IDIzMTsKICB0WzExMl0gPSAyMzM7CiAgdFsxMTNdID0gMjMyOwogIHRbMTE0XSA9IDIzNDsKICB0WzExNV0gPSAyMzU7CiAgdFsxMTZdID0gMjM3OwogIHRbMTE3XSA9IDIzNjsKICB0WzExOF0gPSAyMzg7CiAgdFsxMTldID0gMjM5OwogIHRbMTIwXSA9IDI0MTsKICB0WzEyMV0gPSAyNDM7CiAgdFsxMjJdID0gMjQyOwogIHRbMTIzXSA9IDI0NDsKICB0WzEyNF0gPSAyNDY7CiAgdFsxMjVdID0gMjQ1OwogIHRbMTI2XSA9IDI1MDsKICB0WzEyN10gPSAyNDk7CiAgdFsxMjhdID0gMjUxOwogIHRbMTI5XSA9IDI1MjsKICB0WzEzMF0gPSA4MjI0OwogIHRbMTMxXSA9IDE3NjsKICB0WzEzMl0gPSAxNjI7CiAgdFsxMzNdID0gMTYzOwogIHRbMTM0XSA9IDE2NzsKICB0WzEzNV0gPSA4MjI2OwogIHRbMTM2XSA9IDE4MjsKICB0WzEzN10gPSAyMjM7CiAgdFsxMzhdID0gMTc0OwogIHRbMTM5XSA9IDE2OTsKICB0WzE0MF0gPSA4NDgyOwogIHRbMTQxXSA9IDE4MDsKICB0WzE0Ml0gPSAxNjg7CiAgdFsxNDNdID0gODgwMDsKICB0WzE0NF0gPSAxOTg7CiAgdFsxNDVdID0gMjE2OwogIHRbMTQ2XSA9IDg3MzQ7CiAgdFsxNDddID0gMTc3OwogIHRbMTQ4XSA9IDg4MDQ7CiAgdFsxNDldID0gODgwNTsKICB0WzE1MF0gPSAxNjU7CiAgdFsxNTFdID0gMTgxOwogIHRbMTUyXSA9IDg3MDY7CiAgdFsxNTNdID0gODcyMTsKICB0WzE1NF0gPSA4NzE5OwogIHRbMTU2XSA9IDg3NDc7CiAgdFsxNTddID0gMTcwOwogIHRbMTU4XSA9IDE4NjsKICB0WzE1OV0gPSA4NDg2OwogIHRbMTYwXSA9IDIzMDsKICB0WzE2MV0gPSAyNDg7CiAgdFsxNjJdID0gMTkxOwogIHRbMTYzXSA9IDE2MTsKICB0WzE2NF0gPSAxNzI7CiAgdFsxNjVdID0gODczMDsKICB0WzE2Nl0gPSA0MDI7CiAgdFsxNjddID0gODc3NjsKICB0WzE2OF0gPSA4NzEwOwogIHRbMTY5XSA9IDE3MTsKICB0WzE3MF0gPSAxODc7CiAgdFsxNzFdID0gODIzMDsKICB0WzE3OV0gPSA4MjIwOwogIHRbMTgwXSA9IDgyMjE7CiAgdFsxODFdID0gODIxNjsKICB0WzE4Ml0gPSA4MjE3OwogIHRbMjAwXSA9IDE5MzsKICB0WzIwM10gPSAyMDU7CiAgdFsyMDddID0gMjExOwogIHRbMjEwXSA9IDIxODsKICB0WzIyM10gPSA3MTE7CiAgdFsyMjRdID0gMzIxOwogIHRbMjI1XSA9IDMyMjsKICB0WzIyNl0gPSAzNTI7CiAgdFsyMjddID0gMzUzOwogIHRbMjI4XSA9IDM4MTsKICB0WzIyOV0gPSAzODI7CiAgdFsyMzNdID0gMjIxOwogIHRbMjM0XSA9IDI1MzsKICB0WzI1Ml0gPSAyNjM7CiAgdFsyNTNdID0gMjY4OwogIHRbMjU0XSA9IDI2OTsKICB0WzI1OF0gPSAyNTg7CiAgdFsyNjBdID0gMjYwOwogIHRbMjYxXSA9IDI2MTsKICB0WzI2NV0gPSAyODA7CiAgdFsyNjZdID0gMjgxOwogIHRbMjY3XSA9IDI4MjsKICB0WzI2OF0gPSAyODM7CiAgdFsyNjldID0gMzEzOwogIHRbMjc1XSA9IDMyMzsKICB0WzI3Nl0gPSAzMjQ7CiAgdFsyNzhdID0gMzI4OwogIHRbMjgzXSA9IDM0NDsKICB0WzI4NF0gPSAzNDU7CiAgdFsyODVdID0gMzQ2OwogIHRbMjg2XSA9IDM0NzsKICB0WzI5Ml0gPSAzNjc7CiAgdFsyOTVdID0gMzc3OwogIHRbMjk2XSA9IDM3ODsKICB0WzI5OF0gPSAzODA7CiAgdFszMDVdID0gOTYzOwogIHRbMzA2XSA9IDk2NDsKICB0WzMwN10gPSA5NjY7CiAgdFszMDhdID0gODIxNTsKICB0WzMwOV0gPSA4MjUyOwogIHRbMzEwXSA9IDgzMTk7CiAgdFszMTFdID0gODM1OTsKICB0WzMxMl0gPSA4NTkyOwogIHRbMzEzXSA9IDg1OTM7CiAgdFszMzddID0gOTU1MjsKICB0WzQ5M10gPSAxMDM5OwogIHRbNDk0XSA9IDEwNDA7CiAgdFs2NzJdID0gMTQ4ODsKICB0WzY3M10gPSAxNDg5OwogIHRbNjc0XSA9IDE0OTA7CiAgdFs2NzVdID0gMTQ5MTsKICB0WzY3Nl0gPSAxNDkyOwogIHRbNjc3XSA9IDE0OTM7CiAgdFs2NzhdID0gMTQ5NDsKICB0WzY3OV0gPSAxNDk1OwogIHRbNjgwXSA9IDE0OTY7CiAgdFs2ODFdID0gMTQ5NzsKICB0WzY4Ml0gPSAxNDk4OwogIHRbNjgzXSA9IDE0OTk7CiAgdFs2ODRdID0gMTUwMDsKICB0WzY4NV0gPSAxNTAxOwogIHRbNjg2XSA9IDE1MDI7CiAgdFs2ODddID0gMTUwMzsKICB0WzY4OF0gPSAxNTA0OwogIHRbNjg5XSA9IDE1MDU7CiAgdFs2OTBdID0gMTUwNjsKICB0WzY5MV0gPSAxNTA3OwogIHRbNjkyXSA9IDE1MDg7CiAgdFs2OTNdID0gMTUwOTsKICB0WzY5NF0gPSAxNTEwOwogIHRbNjk1XSA9IDE1MTE7CiAgdFs2OTZdID0gMTUxMjsKICB0WzY5N10gPSAxNTEzOwogIHRbNjk4XSA9IDE1MTQ7CiAgdFs3MDVdID0gMTUyNDsKICB0WzcwNl0gPSA4MzYyOwogIHRbNzEwXSA9IDY0Mjg4OwogIHRbNzExXSA9IDY0Mjk4OwogIHRbNzU5XSA9IDE2MTc7CiAgdFs3NjFdID0gMTc3NjsKICB0Wzc2M10gPSAxNzc4OwogIHRbNzc1XSA9IDE2NTI7CiAgdFs3NzddID0gMTc2NDsKICB0Wzc3OF0gPSAxNzgwOwogIHRbNzc5XSA9IDE3ODE7CiAgdFs3ODBdID0gMTc4MjsKICB0Wzc4Ml0gPSA3NzE7CiAgdFs3ODNdID0gNjQ3MjY7CiAgdFs3ODZdID0gODM2MzsKICB0Wzc4OF0gPSA4NTMyOwogIHRbNzkwXSA9IDc2ODsKICB0Wzc5MV0gPSA3Njk7CiAgdFs3OTJdID0gNzY4OwogIHRbNzk1XSA9IDgwMzsKICB0Wzc5N10gPSA2NDMzNjsKICB0Wzc5OF0gPSA2NDMzNzsKICB0Wzc5OV0gPSA2NDM0MjsKICB0WzgwMF0gPSA2NDM0MzsKICB0WzgwMV0gPSA2NDM0NDsKICB0WzgwMl0gPSA2NDM0NTsKICB0WzgwM10gPSA2NDM2MjsKICB0WzgwNF0gPSA2NDM2MzsKICB0WzgwNV0gPSA2NDM2NDsKICB0WzI0MjRdID0gNzgyMTsKICB0WzI0MjVdID0gNzgyMjsKICB0WzI0MjZdID0gNzgyMzsKICB0WzI0MjddID0gNzgyNDsKICB0WzI0MjhdID0gNzgyNTsKICB0WzI0MjldID0gNzgyNjsKICB0WzI0MzBdID0gNzgyNzsKICB0WzI0MzNdID0gNzY4MjsKICB0WzI2NzhdID0gODA0NTsKICB0WzI2NzldID0gODA0NjsKICB0WzI4MzBdID0gMTU1MjsKICB0WzI4MzhdID0gNjg2OwogIHRbMjg0MF0gPSA3NTE7CiAgdFsyODQyXSA9IDc1MzsKICB0WzI4NDNdID0gNzU0OwogIHRbMjg0NF0gPSA3NTU7CiAgdFsyODQ2XSA9IDc1NzsKICB0WzI4NTZdID0gNzY3OwogIHRbMjg1N10gPSA4NDg7CiAgdFsyODU4XSA9IDg0OTsKICB0WzI4NjJdID0gODUzOwogIHRbMjg2M10gPSA4NTQ7CiAgdFsyODY0XSA9IDg1NTsKICB0WzI4NjVdID0gODYxOwogIHRbMjg2Nl0gPSA4NjI7CiAgdFsyOTA2XSA9IDc0NjA7CiAgdFsyOTA4XSA9IDc0NjI7CiAgdFsyOTA5XSA9IDc0NjM7CiAgdFsyOTEwXSA9IDc0NjQ7CiAgdFsyOTEyXSA9IDc0NjY7CiAgdFsyOTEzXSA9IDc0Njc7CiAgdFsyOTE0XSA9IDc0Njg7CiAgdFsyOTE2XSA9IDc0NzA7CiAgdFsyOTE3XSA9IDc0NzE7CiAgdFsyOTE4XSA9IDc0NzI7CiAgdFsyOTIwXSA9IDc0NzQ7CiAgdFsyOTIxXSA9IDc0NzU7CiAgdFsyOTIyXSA9IDc0NzY7CiAgdFsyOTI0XSA9IDc0Nzg7CiAgdFsyOTI1XSA9IDc0Nzk7CiAgdFsyOTI2XSA9IDc0ODA7CiAgdFsyOTI4XSA9IDc0ODI7CiAgdFsyOTI5XSA9IDc0ODM7CiAgdFsyOTMwXSA9IDc0ODQ7CiAgdFsyOTMyXSA9IDc0ODY7CiAgdFsyOTMzXSA9IDc0ODc7CiAgdFsyOTM0XSA9IDc0ODg7CiAgdFsyOTM2XSA9IDc0OTA7CiAgdFsyOTM3XSA9IDc0OTE7CiAgdFsyOTM4XSA9IDc0OTI7CiAgdFsyOTQwXSA9IDc0OTQ7CiAgdFsyOTQxXSA9IDc0OTU7CiAgdFsyOTQyXSA9IDc0OTY7CiAgdFsyOTQ0XSA9IDc0OTg7CiAgdFsyOTQ2XSA9IDc1MDA7CiAgdFsyOTQ4XSA9IDc1MDI7CiAgdFsyOTUwXSA9IDc1MDQ7CiAgdFsyOTUxXSA9IDc1MDU7CiAgdFsyOTUyXSA9IDc1MDY7CiAgdFsyOTU0XSA9IDc1MDg7CiAgdFsyOTU1XSA9IDc1MDk7CiAgdFsyOTU2XSA9IDc1MTA7CiAgdFsyOTU4XSA9IDc1MTI7CiAgdFsyOTU5XSA9IDc1MTM7CiAgdFsyOTYwXSA9IDc1MTQ7CiAgdFsyOTYyXSA9IDc1MTY7CiAgdFsyOTYzXSA9IDc1MTc7CiAgdFsyOTY0XSA9IDc1MTg7CiAgdFsyOTY2XSA9IDc1MjA7CiAgdFsyOTY3XSA9IDc1MjE7CiAgdFsyOTY4XSA9IDc1MjI7CiAgdFsyOTcwXSA9IDc1MjQ7CiAgdFsyOTcxXSA9IDc1MjU7CiAgdFsyOTcyXSA9IDc1MjY7CiAgdFsyOTc0XSA9IDc1Mjg7CiAgdFsyOTc1XSA9IDc1Mjk7CiAgdFsyOTc2XSA9IDc1MzA7CiAgdFsyOTc4XSA9IDE1Mzc7CiAgdFsyOTc5XSA9IDE1Mzg7CiAgdFsyOTgwXSA9IDE1Mzk7CiAgdFsyOTgyXSA9IDE1NDk7CiAgdFsyOTgzXSA9IDE1NTE7CiAgdFsyOTg0XSA9IDE1NTI7CiAgdFsyOTg2XSA9IDE1NTQ7CiAgdFsyOTg3XSA9IDE1NTU7CiAgdFsyOTg4XSA9IDE1NTY7CiAgdFsyOTkwXSA9IDE2MjM7CiAgdFsyOTkxXSA9IDE2MjQ7CiAgdFsyOTk1XSA9IDE3NzU7CiAgdFsyOTk5XSA9IDE3OTE7CiAgdFszMDAyXSA9IDY0MjkwOwogIHRbMzAwM10gPSA2NDI5MTsKICB0WzMwMDRdID0gNjQyOTI7CiAgdFszMDA2XSA9IDY0Mjk0OwogIHRbMzAwN10gPSA2NDI5NTsKICB0WzMwMDhdID0gNjQyOTY7CiAgdFszMDExXSA9IDE5MDA7CiAgdFszMDE0XSA9IDgyMjM7CiAgdFszMDE1XSA9IDgyNDQ7CiAgdFszMDE3XSA9IDc1MzI7CiAgdFszMDE4XSA9IDc1MzM7CiAgdFszMDE5XSA9IDc1MzQ7CiAgdFszMDc1XSA9IDc1OTA7CiAgdFszMDc2XSA9IDc1OTE7CiAgdFszMDc5XSA9IDc1OTQ7CiAgdFszMDgwXSA9IDc1OTU7CiAgdFszMDgzXSA9IDc1OTg7CiAgdFszMDg0XSA9IDc1OTk7CiAgdFszMDg3XSA9IDc2MDI7CiAgdFszMDg4XSA9IDc2MDM7CiAgdFszMDkxXSA9IDc2MDY7CiAgdFszMDkyXSA9IDc2MDc7CiAgdFszMDk1XSA9IDc2MTA7CiAgdFszMDk2XSA9IDc2MTE7CiAgdFszMDk5XSA9IDc2MTQ7CiAgdFszMTAwXSA9IDc2MTU7CiAgdFszMTAzXSA9IDc2MTg7CiAgdFszMTA0XSA9IDc2MTk7CiAgdFszMTA3XSA9IDgzMzc7CiAgdFszMTA4XSA9IDgzMzg7CiAgdFszMTE2XSA9IDE4ODQ7CiAgdFszMTE5XSA9IDE4ODU7CiAgdFszMTIwXSA9IDE4ODU7CiAgdFszMTIzXSA9IDE4ODY7CiAgdFszMTI0XSA9IDE4ODY7CiAgdFszMTI3XSA9IDE4ODc7CiAgdFszMTI4XSA9IDE4ODc7CiAgdFszMTMxXSA9IDE4ODg7CiAgdFszMTMyXSA9IDE4ODg7CiAgdFszMTM1XSA9IDE4ODk7CiAgdFszMTM2XSA9IDE4ODk7CiAgdFszMTM5XSA9IDE4OTA7CiAgdFszMTQwXSA9IDE4OTA7CiAgdFszMTQzXSA9IDE4OTE7CiAgdFszMTQ0XSA9IDE4OTE7CiAgdFszMTQ3XSA9IDE4OTI7CiAgdFszMTQ4XSA9IDE4OTI7CiAgdFszMTUzXSA9IDU4MDsKICB0WzMxNTRdID0gNTgxOwogIHRbMzE1N10gPSA1ODQ7CiAgdFszMTU4XSA9IDU4NTsKICB0WzMxNjFdID0gNTg4OwogIHRbMzE2Ml0gPSA1ODk7CiAgdFszMTY1XSA9IDg5MTsKICB0WzMxNjZdID0gODkyOwogIHRbMzE2OV0gPSAxMjc0OwogIHRbMzE3MF0gPSAxMjc1OwogIHRbMzE3M10gPSAxMjc4OwogIHRbMzE3NF0gPSAxMjc5OwogIHRbMzE4MV0gPSA3NjIyOwogIHRbMzE4Ml0gPSA3NjIzOwogIHRbMzI4Ml0gPSAxMTc5OTsKICB0WzMzMTZdID0gNTc4OwogIHRbMzM3OV0gPSA0Mjc4NTsKICB0WzMzOTNdID0gMTE1OTsKICB0WzM0MTZdID0gODM3NzsKfSk7CmV4cG9ydHMuZ2V0R2x5cGhNYXBGb3JTdGFuZGFyZEZvbnRzID0gZ2V0R2x5cGhNYXBGb3JTdGFuZGFyZEZvbnRzOwpjb25zdCBnZXRTdXBwbGVtZW50YWxHbHlwaE1hcEZvckFyaWFsQmxhY2sgPSAoMCwgX2NvcmVfdXRpbHMuZ2V0TG9va3VwVGFibGVGYWN0b3J5KShmdW5jdGlvbiAodCkgewogIHRbMjI3XSA9IDMyMjsKICB0WzI2NF0gPSAyNjE7CiAgdFsyOTFdID0gMzQ2Owp9KTsKZXhwb3J0cy5nZXRTdXBwbGVtZW50YWxHbHlwaE1hcEZvckFyaWFsQmxhY2sgPSBnZXRTdXBwbGVtZW50YWxHbHlwaE1hcEZvckFyaWFsQmxhY2s7CmNvbnN0IGdldFN1cHBsZW1lbnRhbEdseXBoTWFwRm9yQ2FsaWJyaSA9ICgwLCBfY29yZV91dGlscy5nZXRMb29rdXBUYWJsZUZhY3RvcnkpKGZ1bmN0aW9uICh0KSB7CiAgdFsxXSA9IDMyOwogIHRbNF0gPSA2NTsKICB0WzVdID0gMTkyOwogIHRbNl0gPSAxOTM7CiAgdFs5XSA9IDE5NjsKICB0WzE3XSA9IDY2OwogIHRbMThdID0gNjc7CiAgdFsyMV0gPSAyNjg7CiAgdFsyNF0gPSA2ODsKICB0WzI4XSA9IDY5OwogIHRbMjldID0gMjAwOwogIHRbMzBdID0gMjAxOwogIHRbMzJdID0gMjgyOwogIHRbMzhdID0gNzA7CiAgdFszOV0gPSA3MTsKICB0WzQ0XSA9IDcyOwogIHRbNDddID0gNzM7CiAgdFs0OF0gPSAyMDQ7CiAgdFs0OV0gPSAyMDU7CiAgdFs1OF0gPSA3NDsKICB0WzYwXSA9IDc1OwogIHRbNjJdID0gNzY7CiAgdFs2OF0gPSA3NzsKICB0WzY5XSA9IDc4OwogIHRbNzVdID0gNzk7CiAgdFs3Nl0gPSAyMTA7CiAgdFs4MF0gPSAyMTQ7CiAgdFs4N10gPSA4MDsKICB0Wzg5XSA9IDgxOwogIHRbOTBdID0gODI7CiAgdFs5Ml0gPSAzNDQ7CiAgdFs5NF0gPSA4MzsKICB0Wzk3XSA9IDM1MjsKICB0WzEwMF0gPSA4NDsKICB0WzEwNF0gPSA4NTsKICB0WzEwOV0gPSAyMjA7CiAgdFsxMTVdID0gODY7CiAgdFsxMTZdID0gODc7CiAgdFsxMjFdID0gODg7CiAgdFsxMjJdID0gODk7CiAgdFsxMjRdID0gMjIxOwogIHRbMTI3XSA9IDkwOwogIHRbMTI5XSA9IDM4MTsKICB0WzI1OF0gPSA5NzsKICB0WzI1OV0gPSAyMjQ7CiAgdFsyNjBdID0gMjI1OwogIHRbMjYzXSA9IDIyODsKICB0WzI2OF0gPSAyNjE7CiAgdFsyNzFdID0gOTg7CiAgdFsyNzJdID0gOTk7CiAgdFsyNzNdID0gMjYzOwogIHRbMjc1XSA9IDI2OTsKICB0WzI4Ml0gPSAxMDA7CiAgdFsyODZdID0gMTAxOwogIHRbMjg3XSA9IDIzMjsKICB0WzI4OF0gPSAyMzM7CiAgdFsyOTBdID0gMjgzOwogIHRbMjk1XSA9IDI4MTsKICB0WzI5Nl0gPSAxMDI7CiAgdFszMzZdID0gMTAzOwogIHRbMzQ2XSA9IDEwNDsKICB0WzM0OV0gPSAxMDU7CiAgdFszNTBdID0gMjM2OwogIHRbMzUxXSA9IDIzNzsKICB0WzM2MV0gPSAxMDY7CiAgdFszNjRdID0gMTA3OwogIHRbMzY3XSA9IDEwODsKICB0WzM3MV0gPSAzMjI7CiAgdFszNzNdID0gMTA5OwogIHRbMzc0XSA9IDExMDsKICB0WzM4MV0gPSAxMTE7CiAgdFszODJdID0gMjQyOwogIHRbMzgzXSA9IDI0MzsKICB0WzM4Nl0gPSAyNDY7CiAgdFszOTNdID0gMTEyOwogIHRbMzk1XSA9IDExMzsKICB0WzM5Nl0gPSAxMTQ7CiAgdFszOThdID0gMzQ1OwogIHRbNDAwXSA9IDExNTsKICB0WzQwMV0gPSAzNDc7CiAgdFs0MDNdID0gMzUzOwogIHRbNDEwXSA9IDExNjsKICB0WzQzN10gPSAxMTc7CiAgdFs0NDJdID0gMjUyOwogIHRbNDQ4XSA9IDExODsKICB0WzQ0OV0gPSAxMTk7CiAgdFs0NTRdID0gMTIwOwogIHRbNDU1XSA9IDEyMTsKICB0WzQ1N10gPSAyNTM7CiAgdFs0NjBdID0gMTIyOwogIHRbNDYyXSA9IDM4MjsKICB0WzQ2M10gPSAzODA7CiAgdFs4NTNdID0gNDQ7CiAgdFs4NTVdID0gNTg7CiAgdFs4NTZdID0gNDY7CiAgdFs4NzZdID0gNDc7CiAgdFs4NzhdID0gNDU7CiAgdFs4ODJdID0gNDU7CiAgdFs4OTRdID0gNDA7CiAgdFs4OTVdID0gNDE7CiAgdFs4OTZdID0gOTE7CiAgdFs4OTddID0gOTM7CiAgdFs5MjNdID0gNjQ7CiAgdFsxMDA0XSA9IDQ4OwogIHRbMTAwNV0gPSA0OTsKICB0WzEwMDZdID0gNTA7CiAgdFsxMDA3XSA9IDUxOwogIHRbMTAwOF0gPSA1MjsKICB0WzEwMDldID0gNTM7CiAgdFsxMDEwXSA9IDU0OwogIHRbMTAxMV0gPSA1NTsKICB0WzEwMTJdID0gNTY7CiAgdFsxMDEzXSA9IDU3OwogIHRbMTA4MV0gPSAzNzsKICB0WzEwODVdID0gNDM7CiAgdFsxMDg2XSA9IDQ1Owp9KTsKZXhwb3J0cy5nZXRTdXBwbGVtZW50YWxHbHlwaE1hcEZvckNhbGlicmkgPSBnZXRTdXBwbGVtZW50YWxHbHlwaE1hcEZvckNhbGlicmk7CmZ1bmN0aW9uIGdldFN0YW5kYXJkRm9udE5hbWUobmFtZSkgewogIGNvbnN0IGZvbnROYW1lID0gKDAsIF9mb250c191dGlscy5ub3JtYWxpemVGb250TmFtZSkobmFtZSk7CiAgY29uc3Qgc3RkRm9udE1hcCA9IGdldFN0ZEZvbnRNYXAoKTsKICByZXR1cm4gc3RkRm9udE1hcFtmb250TmFtZV07Cn0KCi8qKiovIH0pLAovKiAxNzcgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlRvVW5pY29kZU1hcCA9IGV4cG9ydHMuSWRlbnRpdHlUb1VuaWNvZGVNYXAgPSB2b2lkIDA7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CmNsYXNzIFRvVW5pY29kZU1hcCB7CiAgY29uc3RydWN0b3IoKSB7CiAgICBsZXQgY21hcCA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogW107CiAgICB0aGlzLl9tYXAgPSBjbWFwOwogIH0KICBnZXQgbGVuZ3RoKCkgewogICAgcmV0dXJuIHRoaXMuX21hcC5sZW5ndGg7CiAgfQogIGZvckVhY2goY2FsbGJhY2spIHsKICAgIGZvciAoY29uc3QgY2hhckNvZGUgaW4gdGhpcy5fbWFwKSB7CiAgICAgIGNhbGxiYWNrKGNoYXJDb2RlLCB0aGlzLl9tYXBbY2hhckNvZGVdLmNoYXJDb2RlQXQoMCkpOwogICAgfQogIH0KICBoYXMoaSkgewogICAgcmV0dXJuIHRoaXMuX21hcFtpXSAhPT0gdW5kZWZpbmVkOwogIH0KICBnZXQoaSkgewogICAgcmV0dXJuIHRoaXMuX21hcFtpXTsKICB9CiAgY2hhckNvZGVPZih2YWx1ZSkgewogICAgY29uc3QgbWFwID0gdGhpcy5fbWFwOwogICAgaWYgKG1hcC5sZW5ndGggPD0gMHgxMDAwMCkgewogICAgICByZXR1cm4gbWFwLmluZGV4T2YodmFsdWUpOwogICAgfQogICAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBtYXApIHsKICAgICAgaWYgKG1hcFtjaGFyQ29kZV0gPT09IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIGNoYXJDb2RlIHwgMDsKICAgICAgfQogICAgfQogICAgcmV0dXJuIC0xOwogIH0KICBhbWVuZChtYXApIHsKICAgIGZvciAoY29uc3QgY2hhckNvZGUgaW4gbWFwKSB7CiAgICAgIHRoaXMuX21hcFtjaGFyQ29kZV0gPSBtYXBbY2hhckNvZGVdOwogICAgfQogIH0KfQpleHBvcnRzLlRvVW5pY29kZU1hcCA9IFRvVW5pY29kZU1hcDsKY2xhc3MgSWRlbnRpdHlUb1VuaWNvZGVNYXAgewogIGNvbnN0cnVjdG9yKGZpcnN0Q2hhciwgbGFzdENoYXIpIHsKICAgIHRoaXMuZmlyc3RDaGFyID0gZmlyc3RDaGFyOwogICAgdGhpcy5sYXN0Q2hhciA9IGxhc3RDaGFyOwogIH0KICBnZXQgbGVuZ3RoKCkgewogICAgcmV0dXJuIHRoaXMubGFzdENoYXIgKyAxIC0gdGhpcy5maXJzdENoYXI7CiAgfQogIGZvckVhY2goY2FsbGJhY2spIHsKICAgIGZvciAobGV0IGkgPSB0aGlzLmZpcnN0Q2hhciwgaWkgPSB0aGlzLmxhc3RDaGFyOyBpIDw9IGlpOyBpKyspIHsKICAgICAgY2FsbGJhY2soaSwgaSk7CiAgICB9CiAgfQogIGhhcyhpKSB7CiAgICByZXR1cm4gdGhpcy5maXJzdENoYXIgPD0gaSAmJiBpIDw9IHRoaXMubGFzdENoYXI7CiAgfQogIGdldChpKSB7CiAgICBpZiAodGhpcy5maXJzdENoYXIgPD0gaSAmJiBpIDw9IHRoaXMubGFzdENoYXIpIHsKICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoaSk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBjaGFyQ29kZU9mKHYpIHsKICAgIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHYpICYmIHYgPj0gdGhpcy5maXJzdENoYXIgJiYgdiA8PSB0aGlzLmxhc3RDaGFyID8gdiA6IC0xOwogIH0KICBhbWVuZChtYXApIHsKICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIlNob3VsZCBub3QgY2FsbCBhbWVuZCgpIik7CiAgfQp9CmV4cG9ydHMuSWRlbnRpdHlUb1VuaWNvZGVNYXAgPSBJZGVudGl0eVRvVW5pY29kZU1hcDsKCi8qKiovIH0pLAovKiAxNzggKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLkNGRkZvbnQgPSB2b2lkIDA7CnZhciBfY2ZmX3BhcnNlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTcwKTsKdmFyIF9mb250c191dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTczKTsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKY2xhc3MgQ0ZGRm9udCB7CiAgY29uc3RydWN0b3IoZmlsZSwgcHJvcGVydGllcykgewogICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllczsKICAgIGNvbnN0IHBhcnNlciA9IG5ldyBfY2ZmX3BhcnNlci5DRkZQYXJzZXIoZmlsZSwgcHJvcGVydGllcywgX2ZvbnRzX3V0aWxzLlNFQUNfQU5BTFlTSVNfRU5BQkxFRCk7CiAgICB0aGlzLmNmZiA9IHBhcnNlci5wYXJzZSgpOwogICAgdGhpcy5jZmYuZHVwbGljYXRlRmlyc3RHbHlwaCgpOwogICAgY29uc3QgY29tcGlsZXIgPSBuZXcgX2NmZl9wYXJzZXIuQ0ZGQ29tcGlsZXIodGhpcy5jZmYpOwogICAgdGhpcy5zZWFjcyA9IHRoaXMuY2ZmLnNlYWNzOwogICAgdHJ5IHsKICAgICAgdGhpcy5kYXRhID0gY29tcGlsZXIuY29tcGlsZSgpOwogICAgfSBjYXRjaCAoZSkgewogICAgICAoMCwgX3V0aWwud2FybikoIkZhaWxlZCB0byBjb21waWxlIGZvbnQgIiArIHByb3BlcnRpZXMubG9hZGVkTmFtZSk7CiAgICAgIHRoaXMuZGF0YSA9IGZpbGU7CiAgICB9CiAgICB0aGlzLl9jcmVhdGVCdWlsdEluRW5jb2RpbmcoKTsKICB9CiAgZ2V0IG51bUdseXBocygpIHsKICAgIHJldHVybiB0aGlzLmNmZi5jaGFyU3RyaW5ncy5jb3VudDsKICB9CiAgZ2V0Q2hhcnNldCgpIHsKICAgIHJldHVybiB0aGlzLmNmZi5jaGFyc2V0LmNoYXJzZXQ7CiAgfQogIGdldEdseXBoTWFwcGluZygpIHsKICAgIGNvbnN0IGNmZiA9IHRoaXMuY2ZmOwogICAgY29uc3QgcHJvcGVydGllcyA9IHRoaXMucHJvcGVydGllczsKICAgIGNvbnN0IHsKICAgICAgY2lkVG9HaWRNYXAsCiAgICAgIGNNYXAKICAgIH0gPSBwcm9wZXJ0aWVzOwogICAgY29uc3QgY2hhcnNldHMgPSBjZmYuY2hhcnNldC5jaGFyc2V0OwogICAgbGV0IGNoYXJDb2RlVG9HbHlwaElkOwogICAgbGV0IGdseXBoSWQ7CiAgICBpZiAocHJvcGVydGllcy5jb21wb3NpdGUpIHsKICAgICAgbGV0IGludkNpZFRvR2lkTWFwOwogICAgICBpZiAoY2lkVG9HaWRNYXAgJiYgY2lkVG9HaWRNYXAubGVuZ3RoID4gMCkgewogICAgICAgIGludkNpZFRvR2lkTWFwID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBjaWRUb0dpZE1hcC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICBjb25zdCBnaWQgPSBjaWRUb0dpZE1hcFtpXTsKICAgICAgICAgIGlmIChnaWQgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBpbnZDaWRUb0dpZE1hcFtnaWRdID0gaTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgY2hhckNvZGVUb0dseXBoSWQgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBsZXQgY2hhckNvZGU7CiAgICAgIGlmIChjZmYuaXNDSURGb250KSB7CiAgICAgICAgZm9yIChnbHlwaElkID0gMDsgZ2x5cGhJZCA8IGNoYXJzZXRzLmxlbmd0aDsgZ2x5cGhJZCsrKSB7CiAgICAgICAgICBjb25zdCBjaWQgPSBjaGFyc2V0c1tnbHlwaElkXTsKICAgICAgICAgIGNoYXJDb2RlID0gY01hcC5jaGFyQ29kZU9mKGNpZCk7CiAgICAgICAgICBpZiAoaW52Q2lkVG9HaWRNYXAgJiYgaW52Q2lkVG9HaWRNYXBbY2hhckNvZGVdICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgY2hhckNvZGUgPSBpbnZDaWRUb0dpZE1hcFtjaGFyQ29kZV07CiAgICAgICAgICB9CiAgICAgICAgICBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPSBnbHlwaElkOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBmb3IgKGdseXBoSWQgPSAwOyBnbHlwaElkIDwgY2ZmLmNoYXJTdHJpbmdzLmNvdW50OyBnbHlwaElkKyspIHsKICAgICAgICAgIGNoYXJDb2RlID0gY01hcC5jaGFyQ29kZU9mKGdseXBoSWQpOwogICAgICAgICAgY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID0gZ2x5cGhJZDsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIGNoYXJDb2RlVG9HbHlwaElkOwogICAgfQogICAgbGV0IGVuY29kaW5nID0gY2ZmLmVuY29kaW5nID8gY2ZmLmVuY29kaW5nLmVuY29kaW5nIDogbnVsbDsKICAgIGlmIChwcm9wZXJ0aWVzLmlzSW50ZXJuYWxGb250KSB7CiAgICAgIGVuY29kaW5nID0gcHJvcGVydGllcy5kZWZhdWx0RW5jb2Rpbmc7CiAgICB9CiAgICBjaGFyQ29kZVRvR2x5cGhJZCA9ICgwLCBfZm9udHNfdXRpbHMudHlwZTFGb250R2x5cGhNYXBwaW5nKShwcm9wZXJ0aWVzLCBlbmNvZGluZywgY2hhcnNldHMpOwogICAgcmV0dXJuIGNoYXJDb2RlVG9HbHlwaElkOwogIH0KICBoYXNHbHlwaElkKGlkKSB7CiAgICByZXR1cm4gdGhpcy5jZmYuaGFzR2x5cGhJZChpZCk7CiAgfQogIF9jcmVhdGVCdWlsdEluRW5jb2RpbmcoKSB7CiAgICBjb25zdCB7CiAgICAgIGNoYXJzZXQsCiAgICAgIGVuY29kaW5nCiAgICB9ID0gdGhpcy5jZmY7CiAgICBpZiAoIWNoYXJzZXQgfHwgIWVuY29kaW5nKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGNoYXJzZXRzID0gY2hhcnNldC5jaGFyc2V0LAogICAgICBlbmNvZGluZ3MgPSBlbmNvZGluZy5lbmNvZGluZzsKICAgIGNvbnN0IG1hcCA9IFtdOwogICAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBlbmNvZGluZ3MpIHsKICAgICAgY29uc3QgZ2x5cGhJZCA9IGVuY29kaW5nc1tjaGFyQ29kZV07CiAgICAgIGlmIChnbHlwaElkID49IDApIHsKICAgICAgICBjb25zdCBnbHlwaE5hbWUgPSBjaGFyc2V0c1tnbHlwaElkXTsKICAgICAgICBpZiAoZ2x5cGhOYW1lKSB7CiAgICAgICAgICBtYXBbY2hhckNvZGVdID0gZ2x5cGhOYW1lOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKG1hcC5sZW5ndGggPiAwKSB7CiAgICAgIHRoaXMucHJvcGVydGllcy5idWlsdEluRW5jb2RpbmcgPSBtYXA7CiAgICB9CiAgfQp9CmV4cG9ydHMuQ0ZGRm9udCA9IENGRkZvbnQ7CgovKioqLyB9KSwKLyogMTc5ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5Gb250UmVuZGVyZXJGYWN0b3J5ID0gdm9pZCAwOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwp2YXIgX2NmZl9wYXJzZXIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE3MCk7CnZhciBfZ2x5cGhsaXN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygxNzQpOwp2YXIgX2VuY29kaW5ncyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTcyKTsKdmFyIF9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0NCk7CmZ1bmN0aW9uIGdldFVpbnQzMihkYXRhLCBvZmZzZXQpIHsKICByZXR1cm4gKGRhdGFbb2Zmc2V0XSA8PCAyNCB8IGRhdGFbb2Zmc2V0ICsgMV0gPDwgMTYgfCBkYXRhW29mZnNldCArIDJdIDw8IDggfCBkYXRhW29mZnNldCArIDNdKSA+Pj4gMDsKfQpmdW5jdGlvbiBnZXRVaW50MTYoZGF0YSwgb2Zmc2V0KSB7CiAgcmV0dXJuIGRhdGFbb2Zmc2V0XSA8PCA4IHwgZGF0YVtvZmZzZXQgKyAxXTsKfQpmdW5jdGlvbiBnZXRJbnQxNihkYXRhLCBvZmZzZXQpIHsKICByZXR1cm4gKGRhdGFbb2Zmc2V0XSA8PCAyNCB8IGRhdGFbb2Zmc2V0ICsgMV0gPDwgMTYpID4+IDE2Owp9CmZ1bmN0aW9uIGdldEludDgoZGF0YSwgb2Zmc2V0KSB7CiAgcmV0dXJuIGRhdGFbb2Zmc2V0XSA8PCAyNCA+PiAyNDsKfQpmdW5jdGlvbiBnZXRGbG9hdDIxNChkYXRhLCBvZmZzZXQpIHsKICByZXR1cm4gZ2V0SW50MTYoZGF0YSwgb2Zmc2V0KSAvIDE2Mzg0Owp9CmZ1bmN0aW9uIGdldFN1YnJvdXRpbmVCaWFzKHN1YnJzKSB7CiAgY29uc3QgbnVtU3VicnMgPSBzdWJycy5sZW5ndGg7CiAgbGV0IGJpYXMgPSAzMjc2ODsKICBpZiAobnVtU3VicnMgPCAxMjQwKSB7CiAgICBiaWFzID0gMTA3OwogIH0gZWxzZSBpZiAobnVtU3VicnMgPCAzMzkwMCkgewogICAgYmlhcyA9IDExMzE7CiAgfQogIHJldHVybiBiaWFzOwp9CmZ1bmN0aW9uIHBhcnNlQ21hcChkYXRhLCBzdGFydCwgZW5kKSB7CiAgY29uc3Qgb2Zmc2V0ID0gZ2V0VWludDE2KGRhdGEsIHN0YXJ0ICsgMikgPT09IDEgPyBnZXRVaW50MzIoZGF0YSwgc3RhcnQgKyA4KSA6IGdldFVpbnQzMihkYXRhLCBzdGFydCArIDE2KTsKICBjb25zdCBmb3JtYXQgPSBnZXRVaW50MTYoZGF0YSwgc3RhcnQgKyBvZmZzZXQpOwogIGxldCByYW5nZXMsIHAsIGk7CiAgaWYgKGZvcm1hdCA9PT0gNCkgewogICAgZ2V0VWludDE2KGRhdGEsIHN0YXJ0ICsgb2Zmc2V0ICsgMik7CiAgICBjb25zdCBzZWdDb3VudCA9IGdldFVpbnQxNihkYXRhLCBzdGFydCArIG9mZnNldCArIDYpID4+IDE7CiAgICBwID0gc3RhcnQgKyBvZmZzZXQgKyAxNDsKICAgIHJhbmdlcyA9IFtdOwogICAgZm9yIChpID0gMDsgaSA8IHNlZ0NvdW50OyBpKyssIHAgKz0gMikgewogICAgICByYW5nZXNbaV0gPSB7CiAgICAgICAgZW5kOiBnZXRVaW50MTYoZGF0YSwgcCkKICAgICAgfTsKICAgIH0KICAgIHAgKz0gMjsKICAgIGZvciAoaSA9IDA7IGkgPCBzZWdDb3VudDsgaSsrLCBwICs9IDIpIHsKICAgICAgcmFuZ2VzW2ldLnN0YXJ0ID0gZ2V0VWludDE2KGRhdGEsIHApOwogICAgfQogICAgZm9yIChpID0gMDsgaSA8IHNlZ0NvdW50OyBpKyssIHAgKz0gMikgewogICAgICByYW5nZXNbaV0uaWREZWx0YSA9IGdldFVpbnQxNihkYXRhLCBwKTsKICAgIH0KICAgIGZvciAoaSA9IDA7IGkgPCBzZWdDb3VudDsgaSsrLCBwICs9IDIpIHsKICAgICAgbGV0IGlkT2Zmc2V0ID0gZ2V0VWludDE2KGRhdGEsIHApOwogICAgICBpZiAoaWRPZmZzZXQgPT09IDApIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICByYW5nZXNbaV0uaWRzID0gW107CiAgICAgIGZvciAobGV0IGogPSAwLCBqaiA9IHJhbmdlc1tpXS5lbmQgLSByYW5nZXNbaV0uc3RhcnQgKyAxOyBqIDwgamo7IGorKykgewogICAgICAgIHJhbmdlc1tpXS5pZHNbal0gPSBnZXRVaW50MTYoZGF0YSwgcCArIGlkT2Zmc2V0KTsKICAgICAgICBpZE9mZnNldCArPSAyOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcmFuZ2VzOwogIH0gZWxzZSBpZiAoZm9ybWF0ID09PSAxMikgewogICAgY29uc3QgZ3JvdXBzID0gZ2V0VWludDMyKGRhdGEsIHN0YXJ0ICsgb2Zmc2V0ICsgMTIpOwogICAgcCA9IHN0YXJ0ICsgb2Zmc2V0ICsgMTY7CiAgICByYW5nZXMgPSBbXTsKICAgIGZvciAoaSA9IDA7IGkgPCBncm91cHM7IGkrKykgewogICAgICBzdGFydCA9IGdldFVpbnQzMihkYXRhLCBwKTsKICAgICAgcmFuZ2VzLnB1c2goewogICAgICAgIHN0YXJ0LAogICAgICAgIGVuZDogZ2V0VWludDMyKGRhdGEsIHAgKyA0KSwKICAgICAgICBpZERlbHRhOiBnZXRVaW50MzIoZGF0YSwgcCArIDgpIC0gc3RhcnQKICAgICAgfSk7CiAgICAgIHAgKz0gMTI7CiAgICB9CiAgICByZXR1cm4gcmFuZ2VzOwogIH0KICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYHVuc3VwcG9ydGVkIGNtYXA6ICR7Zm9ybWF0fWApOwp9CmZ1bmN0aW9uIHBhcnNlQ2ZmKGRhdGEsIHN0YXJ0LCBlbmQsIHNlYWNBbmFseXNpc0VuYWJsZWQpIHsKICBjb25zdCBwcm9wZXJ0aWVzID0ge307CiAgY29uc3QgcGFyc2VyID0gbmV3IF9jZmZfcGFyc2VyLkNGRlBhcnNlcihuZXcgX3N0cmVhbS5TdHJlYW0oZGF0YSwgc3RhcnQsIGVuZCAtIHN0YXJ0KSwgcHJvcGVydGllcywgc2VhY0FuYWx5c2lzRW5hYmxlZCk7CiAgY29uc3QgY2ZmID0gcGFyc2VyLnBhcnNlKCk7CiAgcmV0dXJuIHsKICAgIGdseXBoczogY2ZmLmNoYXJTdHJpbmdzLm9iamVjdHMsCiAgICBzdWJyczogY2ZmLnRvcERpY3QucHJpdmF0ZURpY3QgJiYgY2ZmLnRvcERpY3QucHJpdmF0ZURpY3Quc3VicnNJbmRleCAmJiBjZmYudG9wRGljdC5wcml2YXRlRGljdC5zdWJyc0luZGV4Lm9iamVjdHMsCiAgICBnc3VicnM6IGNmZi5nbG9iYWxTdWJySW5kZXggJiYgY2ZmLmdsb2JhbFN1YnJJbmRleC5vYmplY3RzLAogICAgaXNDRkZDSURGb250OiBjZmYuaXNDSURGb250LAogICAgZmRTZWxlY3Q6IGNmZi5mZFNlbGVjdCwKICAgIGZkQXJyYXk6IGNmZi5mZEFycmF5CiAgfTsKfQpmdW5jdGlvbiBwYXJzZUdseWZUYWJsZShnbHlmLCBsb2NhLCBpc0dseXBoTG9jYXRpb25zTG9uZykgewogIGxldCBpdGVtU2l6ZSwgaXRlbURlY29kZTsKICBpZiAoaXNHbHlwaExvY2F0aW9uc0xvbmcpIHsKICAgIGl0ZW1TaXplID0gNDsKICAgIGl0ZW1EZWNvZGUgPSBnZXRVaW50MzI7CiAgfSBlbHNlIHsKICAgIGl0ZW1TaXplID0gMjsKICAgIGl0ZW1EZWNvZGUgPSAoZGF0YSwgb2Zmc2V0KSA9PiAyICogZ2V0VWludDE2KGRhdGEsIG9mZnNldCk7CiAgfQogIGNvbnN0IGdseXBocyA9IFtdOwogIGxldCBzdGFydE9mZnNldCA9IGl0ZW1EZWNvZGUobG9jYSwgMCk7CiAgZm9yIChsZXQgaiA9IGl0ZW1TaXplOyBqIDwgbG9jYS5sZW5ndGg7IGogKz0gaXRlbVNpemUpIHsKICAgIGNvbnN0IGVuZE9mZnNldCA9IGl0ZW1EZWNvZGUobG9jYSwgaik7CiAgICBnbHlwaHMucHVzaChnbHlmLnN1YmFycmF5KHN0YXJ0T2Zmc2V0LCBlbmRPZmZzZXQpKTsKICAgIHN0YXJ0T2Zmc2V0ID0gZW5kT2Zmc2V0OwogIH0KICByZXR1cm4gZ2x5cGhzOwp9CmZ1bmN0aW9uIGxvb2t1cENtYXAocmFuZ2VzLCB1bmljb2RlKSB7CiAgY29uc3QgY29kZSA9IHVuaWNvZGUuY29kZVBvaW50QXQoMCk7CiAgbGV0IGdpZCA9IDAsCiAgICBsID0gMCwKICAgIHIgPSByYW5nZXMubGVuZ3RoIC0gMTsKICB3aGlsZSAobCA8IHIpIHsKICAgIGNvbnN0IGMgPSBsICsgciArIDEgPj4gMTsKICAgIGlmIChjb2RlIDwgcmFuZ2VzW2NdLnN0YXJ0KSB7CiAgICAgIHIgPSBjIC0gMTsKICAgIH0gZWxzZSB7CiAgICAgIGwgPSBjOwogICAgfQogIH0KICBpZiAocmFuZ2VzW2xdLnN0YXJ0IDw9IGNvZGUgJiYgY29kZSA8PSByYW5nZXNbbF0uZW5kKSB7CiAgICBnaWQgPSByYW5nZXNbbF0uaWREZWx0YSArIChyYW5nZXNbbF0uaWRzID8gcmFuZ2VzW2xdLmlkc1tjb2RlIC0gcmFuZ2VzW2xdLnN0YXJ0XSA6IGNvZGUpICYgMHhmZmZmOwogIH0KICByZXR1cm4gewogICAgY2hhckNvZGU6IGNvZGUsCiAgICBnbHlwaElkOiBnaWQKICB9Owp9CmZ1bmN0aW9uIGNvbXBpbGVHbHlmKGNvZGUsIGNtZHMsIGZvbnQpIHsKICBmdW5jdGlvbiBtb3ZlVG8oeCwgeSkgewogICAgY21kcy5wdXNoKHsKICAgICAgY21kOiAibW92ZVRvIiwKICAgICAgYXJnczogW3gsIHldCiAgICB9KTsKICB9CiAgZnVuY3Rpb24gbGluZVRvKHgsIHkpIHsKICAgIGNtZHMucHVzaCh7CiAgICAgIGNtZDogImxpbmVUbyIsCiAgICAgIGFyZ3M6IFt4LCB5XQogICAgfSk7CiAgfQogIGZ1bmN0aW9uIHF1YWRyYXRpY0N1cnZlVG8oeGEsIHlhLCB4LCB5KSB7CiAgICBjbWRzLnB1c2goewogICAgICBjbWQ6ICJxdWFkcmF0aWNDdXJ2ZVRvIiwKICAgICAgYXJnczogW3hhLCB5YSwgeCwgeV0KICAgIH0pOwogIH0KICBsZXQgaSA9IDA7CiAgY29uc3QgbnVtYmVyT2ZDb250b3VycyA9IGdldEludDE2KGNvZGUsIGkpOwogIGxldCBmbGFnczsKICBsZXQgeCA9IDAsCiAgICB5ID0gMDsKICBpICs9IDEwOwogIGlmIChudW1iZXJPZkNvbnRvdXJzIDwgMCkgewogICAgZG8gewogICAgICBmbGFncyA9IGdldFVpbnQxNihjb2RlLCBpKTsKICAgICAgY29uc3QgZ2x5cGhJbmRleCA9IGdldFVpbnQxNihjb2RlLCBpICsgMik7CiAgICAgIGkgKz0gNDsKICAgICAgbGV0IGFyZzEsIGFyZzI7CiAgICAgIGlmIChmbGFncyAmIDB4MDEpIHsKICAgICAgICBpZiAoZmxhZ3MgJiAweDAyKSB7CiAgICAgICAgICBhcmcxID0gZ2V0SW50MTYoY29kZSwgaSk7CiAgICAgICAgICBhcmcyID0gZ2V0SW50MTYoY29kZSwgaSArIDIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBhcmcxID0gZ2V0VWludDE2KGNvZGUsIGkpOwogICAgICAgICAgYXJnMiA9IGdldFVpbnQxNihjb2RlLCBpICsgMik7CiAgICAgICAgfQogICAgICAgIGkgKz0gNDsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAoZmxhZ3MgJiAweDAyKSB7CiAgICAgICAgICBhcmcxID0gZ2V0SW50OChjb2RlLCBpKyspOwogICAgICAgICAgYXJnMiA9IGdldEludDgoY29kZSwgaSsrKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgYXJnMSA9IGNvZGVbaSsrXTsKICAgICAgICAgIGFyZzIgPSBjb2RlW2krK107CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChmbGFncyAmIDB4MDIpIHsKICAgICAgICB4ID0gYXJnMTsKICAgICAgICB5ID0gYXJnMjsKICAgICAgfSBlbHNlIHsKICAgICAgICB4ID0gMDsKICAgICAgICB5ID0gMDsKICAgICAgfQogICAgICBsZXQgc2NhbGVYID0gMSwKICAgICAgICBzY2FsZVkgPSAxLAogICAgICAgIHNjYWxlMDEgPSAwLAogICAgICAgIHNjYWxlMTAgPSAwOwogICAgICBpZiAoZmxhZ3MgJiAweDA4KSB7CiAgICAgICAgc2NhbGVYID0gc2NhbGVZID0gZ2V0RmxvYXQyMTQoY29kZSwgaSk7CiAgICAgICAgaSArPSAyOwogICAgICB9IGVsc2UgaWYgKGZsYWdzICYgMHg0MCkgewogICAgICAgIHNjYWxlWCA9IGdldEZsb2F0MjE0KGNvZGUsIGkpOwogICAgICAgIHNjYWxlWSA9IGdldEZsb2F0MjE0KGNvZGUsIGkgKyAyKTsKICAgICAgICBpICs9IDQ7CiAgICAgIH0gZWxzZSBpZiAoZmxhZ3MgJiAweDgwKSB7CiAgICAgICAgc2NhbGVYID0gZ2V0RmxvYXQyMTQoY29kZSwgaSk7CiAgICAgICAgc2NhbGUwMSA9IGdldEZsb2F0MjE0KGNvZGUsIGkgKyAyKTsKICAgICAgICBzY2FsZTEwID0gZ2V0RmxvYXQyMTQoY29kZSwgaSArIDQpOwogICAgICAgIHNjYWxlWSA9IGdldEZsb2F0MjE0KGNvZGUsIGkgKyA2KTsKICAgICAgICBpICs9IDg7CiAgICAgIH0KICAgICAgY29uc3Qgc3ViZ2x5cGggPSBmb250LmdseXBoc1tnbHlwaEluZGV4XTsKICAgICAgaWYgKHN1YmdseXBoKSB7CiAgICAgICAgY21kcy5wdXNoKHsKICAgICAgICAgIGNtZDogInNhdmUiCiAgICAgICAgfSwgewogICAgICAgICAgY21kOiAidHJhbnNmb3JtIiwKICAgICAgICAgIGFyZ3M6IFtzY2FsZVgsIHNjYWxlMDEsIHNjYWxlMTAsIHNjYWxlWSwgeCwgeV0KICAgICAgICB9KTsKICAgICAgICBpZiAoIShmbGFncyAmIDB4MDIpKSB7fQogICAgICAgIGNvbXBpbGVHbHlmKHN1YmdseXBoLCBjbWRzLCBmb250KTsKICAgICAgICBjbWRzLnB1c2goewogICAgICAgICAgY21kOiAicmVzdG9yZSIKICAgICAgICB9KTsKICAgICAgfQogICAgfSB3aGlsZSAoZmxhZ3MgJiAweDIwKTsKICB9IGVsc2UgewogICAgY29uc3QgZW5kUHRzT2ZDb250b3VycyA9IFtdOwogICAgbGV0IGosIGpqOwogICAgZm9yIChqID0gMDsgaiA8IG51bWJlck9mQ29udG91cnM7IGorKykgewogICAgICBlbmRQdHNPZkNvbnRvdXJzLnB1c2goZ2V0VWludDE2KGNvZGUsIGkpKTsKICAgICAgaSArPSAyOwogICAgfQogICAgY29uc3QgaW5zdHJ1Y3Rpb25MZW5ndGggPSBnZXRVaW50MTYoY29kZSwgaSk7CiAgICBpICs9IDIgKyBpbnN0cnVjdGlvbkxlbmd0aDsKICAgIGNvbnN0IG51bWJlck9mUG9pbnRzID0gZW5kUHRzT2ZDb250b3Vycy5hdCgtMSkgKyAxOwogICAgY29uc3QgcG9pbnRzID0gW107CiAgICB3aGlsZSAocG9pbnRzLmxlbmd0aCA8IG51bWJlck9mUG9pbnRzKSB7CiAgICAgIGZsYWdzID0gY29kZVtpKytdOwogICAgICBsZXQgcmVwZWF0ID0gMTsKICAgICAgaWYgKGZsYWdzICYgMHgwOCkgewogICAgICAgIHJlcGVhdCArPSBjb2RlW2krK107CiAgICAgIH0KICAgICAgd2hpbGUgKHJlcGVhdC0tID4gMCkgewogICAgICAgIHBvaW50cy5wdXNoKHsKICAgICAgICAgIGZsYWdzCiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIGZvciAoaiA9IDA7IGogPCBudW1iZXJPZlBvaW50czsgaisrKSB7CiAgICAgIHN3aXRjaCAocG9pbnRzW2pdLmZsYWdzICYgMHgxMikgewogICAgICAgIGNhc2UgMHgwMDoKICAgICAgICAgIHggKz0gZ2V0SW50MTYoY29kZSwgaSk7CiAgICAgICAgICBpICs9IDI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4MDI6CiAgICAgICAgICB4IC09IGNvZGVbaSsrXTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMHgxMjoKICAgICAgICAgIHggKz0gY29kZVtpKytdOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgcG9pbnRzW2pdLnggPSB4OwogICAgfQogICAgZm9yIChqID0gMDsgaiA8IG51bWJlck9mUG9pbnRzOyBqKyspIHsKICAgICAgc3dpdGNoIChwb2ludHNbal0uZmxhZ3MgJiAweDI0KSB7CiAgICAgICAgY2FzZSAweDAwOgogICAgICAgICAgeSArPSBnZXRJbnQxNihjb2RlLCBpKTsKICAgICAgICAgIGkgKz0gMjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMHgwNDoKICAgICAgICAgIHkgLT0gY29kZVtpKytdOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDI0OgogICAgICAgICAgeSArPSBjb2RlW2krK107CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBwb2ludHNbal0ueSA9IHk7CiAgICB9CiAgICBsZXQgc3RhcnRQb2ludCA9IDA7CiAgICBmb3IgKGkgPSAwOyBpIDwgbnVtYmVyT2ZDb250b3VyczsgaSsrKSB7CiAgICAgIGNvbnN0IGVuZFBvaW50ID0gZW5kUHRzT2ZDb250b3Vyc1tpXTsKICAgICAgY29uc3QgY29udG91ciA9IHBvaW50cy5zbGljZShzdGFydFBvaW50LCBlbmRQb2ludCArIDEpOwogICAgICBpZiAoY29udG91clswXS5mbGFncyAmIDEpIHsKICAgICAgICBjb250b3VyLnB1c2goY29udG91clswXSk7CiAgICAgIH0gZWxzZSBpZiAoY29udG91ci5hdCgtMSkuZmxhZ3MgJiAxKSB7CiAgICAgICAgY29udG91ci51bnNoaWZ0KGNvbnRvdXIuYXQoLTEpKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBwID0gewogICAgICAgICAgZmxhZ3M6IDEsCiAgICAgICAgICB4OiAoY29udG91clswXS54ICsgY29udG91ci5hdCgtMSkueCkgLyAyLAogICAgICAgICAgeTogKGNvbnRvdXJbMF0ueSArIGNvbnRvdXIuYXQoLTEpLnkpIC8gMgogICAgICAgIH07CiAgICAgICAgY29udG91ci51bnNoaWZ0KHApOwogICAgICAgIGNvbnRvdXIucHVzaChwKTsKICAgICAgfQogICAgICBtb3ZlVG8oY29udG91clswXS54LCBjb250b3VyWzBdLnkpOwogICAgICBmb3IgKGogPSAxLCBqaiA9IGNvbnRvdXIubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICAgIGlmIChjb250b3VyW2pdLmZsYWdzICYgMSkgewogICAgICAgICAgbGluZVRvKGNvbnRvdXJbal0ueCwgY29udG91cltqXS55KTsKICAgICAgICB9IGVsc2UgaWYgKGNvbnRvdXJbaiArIDFdLmZsYWdzICYgMSkgewogICAgICAgICAgcXVhZHJhdGljQ3VydmVUbyhjb250b3VyW2pdLngsIGNvbnRvdXJbal0ueSwgY29udG91cltqICsgMV0ueCwgY29udG91cltqICsgMV0ueSk7CiAgICAgICAgICBqKys7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHF1YWRyYXRpY0N1cnZlVG8oY29udG91cltqXS54LCBjb250b3VyW2pdLnksIChjb250b3VyW2pdLnggKyBjb250b3VyW2ogKyAxXS54KSAvIDIsIChjb250b3VyW2pdLnkgKyBjb250b3VyW2ogKyAxXS55KSAvIDIpOwogICAgICAgIH0KICAgICAgfQogICAgICBzdGFydFBvaW50ID0gZW5kUG9pbnQgKyAxOwogICAgfQogIH0KfQpmdW5jdGlvbiBjb21waWxlQ2hhclN0cmluZyhjaGFyU3RyaW5nQ29kZSwgY21kcywgZm9udCwgZ2x5cGhJZCkgewogIGZ1bmN0aW9uIG1vdmVUbyh4LCB5KSB7CiAgICBjbWRzLnB1c2goewogICAgICBjbWQ6ICJtb3ZlVG8iLAogICAgICBhcmdzOiBbeCwgeV0KICAgIH0pOwogIH0KICBmdW5jdGlvbiBsaW5lVG8oeCwgeSkgewogICAgY21kcy5wdXNoKHsKICAgICAgY21kOiAibGluZVRvIiwKICAgICAgYXJnczogW3gsIHldCiAgICB9KTsKICB9CiAgZnVuY3Rpb24gYmV6aWVyQ3VydmVUbyh4MSwgeTEsIHgyLCB5MiwgeCwgeSkgewogICAgY21kcy5wdXNoKHsKICAgICAgY21kOiAiYmV6aWVyQ3VydmVUbyIsCiAgICAgIGFyZ3M6IFt4MSwgeTEsIHgyLCB5MiwgeCwgeV0KICAgIH0pOwogIH0KICBjb25zdCBzdGFjayA9IFtdOwogIGxldCB4ID0gMCwKICAgIHkgPSAwOwogIGxldCBzdGVtcyA9IDA7CiAgZnVuY3Rpb24gcGFyc2UoY29kZSkgewogICAgbGV0IGkgPSAwOwogICAgd2hpbGUgKGkgPCBjb2RlLmxlbmd0aCkgewogICAgICBsZXQgc3RhY2tDbGVhbiA9IGZhbHNlOwogICAgICBsZXQgdiA9IGNvZGVbaSsrXTsKICAgICAgbGV0IHhhLCB4YiwgeWEsIHliLCB5MSwgeTIsIHkzLCBuLCBzdWJyQ29kZTsKICAgICAgc3dpdGNoICh2KSB7CiAgICAgICAgY2FzZSAxOgogICAgICAgICAgc3RlbXMgKz0gc3RhY2subGVuZ3RoID4+IDE7CiAgICAgICAgICBzdGFja0NsZWFuID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzoKICAgICAgICAgIHN0ZW1zICs9IHN0YWNrLmxlbmd0aCA+PiAxOwogICAgICAgICAgc3RhY2tDbGVhbiA9IHRydWU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDQ6CiAgICAgICAgICB5ICs9IHN0YWNrLnBvcCgpOwogICAgICAgICAgbW92ZVRvKHgsIHkpOwogICAgICAgICAgc3RhY2tDbGVhbiA9IHRydWU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDU6CiAgICAgICAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgICAgICB4ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHkgKz0gc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgbGluZVRvKHgsIHkpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA2OgogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgeCArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICBsaW5lVG8oeCwgeSk7CiAgICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICB5ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIGxpbmVUbyh4LCB5KTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNzoKICAgICAgICAgIHdoaWxlIChzdGFjay5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIHkgKz0gc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgbGluZVRvKHgsIHkpOwogICAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgeCArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICBsaW5lVG8oeCwgeSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDg6CiAgICAgICAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YSA9IHkgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB4YiA9IHhhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHkgPSB5YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIGJlemllckN1cnZlVG8oeGEsIHlhLCB4YiwgeWIsIHgsIHkpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxMDoKICAgICAgICAgIG4gPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN1YnJDb2RlID0gbnVsbDsKICAgICAgICAgIGlmIChmb250LmlzQ0ZGQ0lERm9udCkgewogICAgICAgICAgICBjb25zdCBmZEluZGV4ID0gZm9udC5mZFNlbGVjdC5nZXRGREluZGV4KGdseXBoSWQpOwogICAgICAgICAgICBpZiAoZmRJbmRleCA+PSAwICYmIGZkSW5kZXggPCBmb250LmZkQXJyYXkubGVuZ3RoKSB7CiAgICAgICAgICAgICAgY29uc3QgZm9udERpY3QgPSBmb250LmZkQXJyYXlbZmRJbmRleF07CiAgICAgICAgICAgICAgbGV0IHN1YnJzOwogICAgICAgICAgICAgIGlmIChmb250RGljdC5wcml2YXRlRGljdCAmJiBmb250RGljdC5wcml2YXRlRGljdC5zdWJyc0luZGV4KSB7CiAgICAgICAgICAgICAgICBzdWJycyA9IGZvbnREaWN0LnByaXZhdGVEaWN0LnN1YnJzSW5kZXgub2JqZWN0czsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKHN1YnJzKSB7CiAgICAgICAgICAgICAgICBuICs9IGdldFN1YnJvdXRpbmVCaWFzKHN1YnJzKTsKICAgICAgICAgICAgICAgIHN1YnJDb2RlID0gc3VicnNbbl07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiSW52YWxpZCBmZCBpbmRleCBmb3IgZ2x5cGggaW5kZXguIik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN1YnJDb2RlID0gZm9udC5zdWJyc1tuICsgZm9udC5zdWJyc0JpYXNdOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHN1YnJDb2RlKSB7CiAgICAgICAgICAgIHBhcnNlKHN1YnJDb2RlKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTE6CiAgICAgICAgICByZXR1cm47CiAgICAgICAgY2FzZSAxMjoKICAgICAgICAgIHYgPSBjb2RlW2krK107CiAgICAgICAgICBzd2l0Y2ggKHYpIHsKICAgICAgICAgICAgY2FzZSAzNDoKICAgICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHkxID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5LCB4YiwgeTEsIHgsIHkxKTsKICAgICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeTEsIHhiLCB5LCB4LCB5KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAzNToKICAgICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB5ID0geWIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIGJlemllckN1cnZlVG8oeGEsIHlhLCB4YiwgeWIsIHgsIHkpOwogICAgICAgICAgICAgIHhhID0geCArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeWEgPSB5ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB4YiA9IHhhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB4ID0geGIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHkgPSB5YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICAgICAgc3RhY2sucG9wKCk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMzY6CiAgICAgICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB5MSA9IHkgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHkyID0geTEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeTEsIHhiLCB5MiwgeCwgeTIpOwogICAgICAgICAgICAgIHhhID0geCArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeTMgPSB5MiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5MiwgeGIsIHkzLCB4LCB5KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAzNzoKICAgICAgICAgICAgICBjb25zdCB4MCA9IHgsCiAgICAgICAgICAgICAgICB5MCA9IHk7CiAgICAgICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB5YSA9IHkgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHliID0geWEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeSA9IHliICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeCA9IHhiOwogICAgICAgICAgICAgIHkgPSB5YjsKICAgICAgICAgICAgICBpZiAoTWF0aC5hYnMoeCAtIHgwKSA+IE1hdGguYWJzKHkgLSB5MCkpIHsKICAgICAgICAgICAgICAgIHggKz0gc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgeSArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYHVua25vd24gb3BlcmF0b3I6IDEyICR7dn1gKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTQ6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoID49IDQpIHsKICAgICAgICAgICAgY29uc3QgYWNoYXIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgICAgY29uc3QgYmNoYXIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgICAgeSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgICB4ID0gc3RhY2sucG9wKCk7CiAgICAgICAgICAgIGNtZHMucHVzaCh7CiAgICAgICAgICAgICAgY21kOiAic2F2ZSIKICAgICAgICAgICAgfSwgewogICAgICAgICAgICAgIGNtZDogInRyYW5zbGF0ZSIsCiAgICAgICAgICAgICAgYXJnczogW3gsIHldCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBsZXQgY21hcCA9IGxvb2t1cENtYXAoZm9udC5jbWFwLCBTdHJpbmcuZnJvbUNoYXJDb2RlKGZvbnQuZ2x5cGhOYW1lTWFwW19lbmNvZGluZ3MuU3RhbmRhcmRFbmNvZGluZ1thY2hhcl1dKSk7CiAgICAgICAgICAgIGNvbXBpbGVDaGFyU3RyaW5nKGZvbnQuZ2x5cGhzW2NtYXAuZ2x5cGhJZF0sIGNtZHMsIGZvbnQsIGNtYXAuZ2x5cGhJZCk7CiAgICAgICAgICAgIGNtZHMucHVzaCh7CiAgICAgICAgICAgICAgY21kOiAicmVzdG9yZSIKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGNtYXAgPSBsb29rdXBDbWFwKGZvbnQuY21hcCwgU3RyaW5nLmZyb21DaGFyQ29kZShmb250LmdseXBoTmFtZU1hcFtfZW5jb2RpbmdzLlN0YW5kYXJkRW5jb2RpbmdbYmNoYXJdXSkpOwogICAgICAgICAgICBjb21waWxlQ2hhclN0cmluZyhmb250LmdseXBoc1tjbWFwLmdseXBoSWRdLCBjbWRzLCBmb250LCBjbWFwLmdseXBoSWQpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuOwogICAgICAgIGNhc2UgMTg6CiAgICAgICAgICBzdGVtcyArPSBzdGFjay5sZW5ndGggPj4gMTsKICAgICAgICAgIHN0YWNrQ2xlYW4gPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAxOToKICAgICAgICAgIHN0ZW1zICs9IHN0YWNrLmxlbmd0aCA+PiAxOwogICAgICAgICAgaSArPSBzdGVtcyArIDcgPj4gMzsKICAgICAgICAgIHN0YWNrQ2xlYW4gPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyMDoKICAgICAgICAgIHN0ZW1zICs9IHN0YWNrLmxlbmd0aCA+PiAxOwogICAgICAgICAgaSArPSBzdGVtcyArIDcgPj4gMzsKICAgICAgICAgIHN0YWNrQ2xlYW4gPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyMToKICAgICAgICAgIHkgKz0gc3RhY2sucG9wKCk7CiAgICAgICAgICB4ICs9IHN0YWNrLnBvcCgpOwogICAgICAgICAgbW92ZVRvKHgsIHkpOwogICAgICAgICAgc3RhY2tDbGVhbiA9IHRydWU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDIyOgogICAgICAgICAgeCArPSBzdGFjay5wb3AoKTsKICAgICAgICAgIG1vdmVUbyh4LCB5KTsKICAgICAgICAgIHN0YWNrQ2xlYW4gPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyMzoKICAgICAgICAgIHN0ZW1zICs9IHN0YWNrLmxlbmd0aCA+PiAxOwogICAgICAgICAgc3RhY2tDbGVhbiA9IHRydWU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI0OgogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDIpIHsKICAgICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWEgPSB5ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHliID0geWEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB4ID0geGIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5ID0geWIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgIH0KICAgICAgICAgIHggKz0gc3RhY2suc2hpZnQoKTsKICAgICAgICAgIHkgKz0gc3RhY2suc2hpZnQoKTsKICAgICAgICAgIGxpbmVUbyh4LCB5KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjU6CiAgICAgICAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gNikgewogICAgICAgICAgICB4ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHkgKz0gc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgbGluZVRvKHgsIHkpOwogICAgICAgICAgfQogICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICB4YiA9IHhhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgIHliID0geWEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgIHkgPSB5YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjY6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoICUgMikgewogICAgICAgICAgICB4ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICB9CiAgICAgICAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgICAgICB4YSA9IHg7CiAgICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeCA9IHhiOwogICAgICAgICAgICB5ID0geWIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjc6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoICUgMikgewogICAgICAgICAgICB5ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICB9CiAgICAgICAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YSA9IHk7CiAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeSA9IHliOwogICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjg6CiAgICAgICAgICBzdGFjay5wdXNoKChjb2RlW2ldIDw8IDI0IHwgY29kZVtpICsgMV0gPDwgMTYpID4+IDE2KTsKICAgICAgICAgIGkgKz0gMjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjk6CiAgICAgICAgICBuID0gc3RhY2sucG9wKCkgKyBmb250LmdzdWJyc0JpYXM7CiAgICAgICAgICBzdWJyQ29kZSA9IGZvbnQuZ3N1YnJzW25dOwogICAgICAgICAgaWYgKHN1YnJDb2RlKSB7CiAgICAgICAgICAgIHBhcnNlKHN1YnJDb2RlKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzA6CiAgICAgICAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgICAgICB4YSA9IHg7CiAgICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeSA9IHliICsgKHN0YWNrLmxlbmd0aCA9PT0gMSA/IHN0YWNrLnNoaWZ0KCkgOiAwKTsKICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YSA9IHk7CiAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeSA9IHliICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeCA9IHhiICsgKHN0YWNrLmxlbmd0aCA9PT0gMSA/IHN0YWNrLnNoaWZ0KCkgOiAwKTsKICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDMxOgogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWEgPSB5OwogICAgICAgICAgICB4YiA9IHhhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHkgPSB5YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHggPSB4YiArIChzdGFjay5sZW5ndGggPT09IDEgPyBzdGFjay5zaGlmdCgpIDogMCk7CiAgICAgICAgICAgIGJlemllckN1cnZlVG8oeGEsIHlhLCB4YiwgeWIsIHgsIHkpOwogICAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgeGEgPSB4OwogICAgICAgICAgICB5YSA9IHkgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB4YiA9IHhhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHkgPSB5YiArIChzdGFjay5sZW5ndGggPT09IDEgPyBzdGFjay5zaGlmdCgpIDogMCk7CiAgICAgICAgICAgIGJlemllckN1cnZlVG8oeGEsIHlhLCB4YiwgeWIsIHgsIHkpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIGlmICh2IDwgMzIpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGB1bmtub3duIG9wZXJhdG9yOiAke3Z9YCk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodiA8IDI0NykgewogICAgICAgICAgICBzdGFjay5wdXNoKHYgLSAxMzkpOwogICAgICAgICAgfSBlbHNlIGlmICh2IDwgMjUxKSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goKHYgLSAyNDcpICogMjU2ICsgY29kZVtpKytdICsgMTA4KTsKICAgICAgICAgIH0gZWxzZSBpZiAodiA8IDI1NSkgewogICAgICAgICAgICBzdGFjay5wdXNoKC0odiAtIDI1MSkgKiAyNTYgLSBjb2RlW2krK10gLSAxMDgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RhY2sucHVzaCgoY29kZVtpXSA8PCAyNCB8IGNvZGVbaSArIDFdIDw8IDE2IHwgY29kZVtpICsgMl0gPDwgOCB8IGNvZGVbaSArIDNdKSAvIDY1NTM2KTsKICAgICAgICAgICAgaSArPSA0OwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKHN0YWNrQ2xlYW4pIHsKICAgICAgICBzdGFjay5sZW5ndGggPSAwOwogICAgICB9CiAgICB9CiAgfQogIHBhcnNlKGNoYXJTdHJpbmdDb2RlKTsKfQpjb25zdCBOT09QID0gW107CmNsYXNzIENvbXBpbGVkRm9udCB7CiAgY29uc3RydWN0b3IoZm9udE1hdHJpeCkgewogICAgaWYgKHRoaXMuY29uc3RydWN0b3IgPT09IENvbXBpbGVkRm9udCkgewogICAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJDYW5ub3QgaW5pdGlhbGl6ZSBDb21waWxlZEZvbnQuIik7CiAgICB9CiAgICB0aGlzLmZvbnRNYXRyaXggPSBmb250TWF0cml4OwogICAgdGhpcy5jb21waWxlZEdseXBocyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB0aGlzLmNvbXBpbGVkQ2hhckNvZGVUb0dseXBoSWQgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIH0KICBnZXRQYXRoSnModW5pY29kZSkgewogICAgY29uc3QgewogICAgICBjaGFyQ29kZSwKICAgICAgZ2x5cGhJZAogICAgfSA9IGxvb2t1cENtYXAodGhpcy5jbWFwLCB1bmljb2RlKTsKICAgIGxldCBmbiA9IHRoaXMuY29tcGlsZWRHbHlwaHNbZ2x5cGhJZF07CiAgICBpZiAoIWZuKSB7CiAgICAgIHRyeSB7CiAgICAgICAgZm4gPSB0aGlzLmNvbXBpbGVHbHlwaCh0aGlzLmdseXBoc1tnbHlwaElkXSwgZ2x5cGhJZCk7CiAgICAgICAgdGhpcy5jb21waWxlZEdseXBoc1tnbHlwaElkXSA9IGZuOwogICAgICB9IGNhdGNoIChleCkgewogICAgICAgIHRoaXMuY29tcGlsZWRHbHlwaHNbZ2x5cGhJZF0gPSBOT09QOwogICAgICAgIGlmICh0aGlzLmNvbXBpbGVkQ2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID09PSB1bmRlZmluZWQpIHsKICAgICAgICAgIHRoaXMuY29tcGlsZWRDaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPSBnbHlwaElkOwogICAgICAgIH0KICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgfQogICAgaWYgKHRoaXMuY29tcGlsZWRDaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPT09IHVuZGVmaW5lZCkgewogICAgICB0aGlzLmNvbXBpbGVkQ2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID0gZ2x5cGhJZDsKICAgIH0KICAgIHJldHVybiBmbjsKICB9CiAgY29tcGlsZUdseXBoKGNvZGUsIGdseXBoSWQpIHsKICAgIGlmICghY29kZSB8fCBjb2RlLmxlbmd0aCA9PT0gMCB8fCBjb2RlWzBdID09PSAxNCkgewogICAgICByZXR1cm4gTk9PUDsKICAgIH0KICAgIGxldCBmb250TWF0cml4ID0gdGhpcy5mb250TWF0cml4OwogICAgaWYgKHRoaXMuaXNDRkZDSURGb250KSB7CiAgICAgIGNvbnN0IGZkSW5kZXggPSB0aGlzLmZkU2VsZWN0LmdldEZESW5kZXgoZ2x5cGhJZCk7CiAgICAgIGlmIChmZEluZGV4ID49IDAgJiYgZmRJbmRleCA8IHRoaXMuZmRBcnJheS5sZW5ndGgpIHsKICAgICAgICBjb25zdCBmb250RGljdCA9IHRoaXMuZmRBcnJheVtmZEluZGV4XTsKICAgICAgICBmb250TWF0cml4ID0gZm9udERpY3QuZ2V0QnlOYW1lKCJGb250TWF0cml4IikgfHwgX3V0aWwuRk9OVF9JREVOVElUWV9NQVRSSVg7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKCJJbnZhbGlkIGZkIGluZGV4IGZvciBnbHlwaCBpbmRleC4iKTsKICAgICAgfQogICAgfQogICAgY29uc3QgY21kcyA9IFt7CiAgICAgIGNtZDogInNhdmUiCiAgICB9LCB7CiAgICAgIGNtZDogInRyYW5zZm9ybSIsCiAgICAgIGFyZ3M6IGZvbnRNYXRyaXguc2xpY2UoKQogICAgfSwgewogICAgICBjbWQ6ICJzY2FsZSIsCiAgICAgIGFyZ3M6IFsic2l6ZSIsICItc2l6ZSJdCiAgICB9XTsKICAgIHRoaXMuY29tcGlsZUdseXBoSW1wbChjb2RlLCBjbWRzLCBnbHlwaElkKTsKICAgIGNtZHMucHVzaCh7CiAgICAgIGNtZDogInJlc3RvcmUiCiAgICB9KTsKICAgIHJldHVybiBjbWRzOwogIH0KICBjb21waWxlR2x5cGhJbXBsKCkgewogICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQ2hpbGRyZW4gY2xhc3NlcyBzaG91bGQgaW1wbGVtZW50IHRoaXMuIik7CiAgfQogIGhhc0J1aWx0UGF0aCh1bmljb2RlKSB7CiAgICBjb25zdCB7CiAgICAgIGNoYXJDb2RlLAogICAgICBnbHlwaElkCiAgICB9ID0gbG9va3VwQ21hcCh0aGlzLmNtYXAsIHVuaWNvZGUpOwogICAgcmV0dXJuIHRoaXMuY29tcGlsZWRHbHlwaHNbZ2x5cGhJZF0gIT09IHVuZGVmaW5lZCAmJiB0aGlzLmNvbXBpbGVkQ2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdICE9PSB1bmRlZmluZWQ7CiAgfQp9CmNsYXNzIFRydWVUeXBlQ29tcGlsZWQgZXh0ZW5kcyBDb21waWxlZEZvbnQgewogIGNvbnN0cnVjdG9yKGdseXBocywgY21hcCwgZm9udE1hdHJpeCkgewogICAgc3VwZXIoZm9udE1hdHJpeCB8fCBbMC4wMDA0ODgsIDAsIDAsIDAuMDAwNDg4LCAwLCAwXSk7CiAgICB0aGlzLmdseXBocyA9IGdseXBoczsKICAgIHRoaXMuY21hcCA9IGNtYXA7CiAgfQogIGNvbXBpbGVHbHlwaEltcGwoY29kZSwgY21kcykgewogICAgY29tcGlsZUdseWYoY29kZSwgY21kcywgdGhpcyk7CiAgfQp9CmNsYXNzIFR5cGUyQ29tcGlsZWQgZXh0ZW5kcyBDb21waWxlZEZvbnQgewogIGNvbnN0cnVjdG9yKGNmZkluZm8sIGNtYXAsIGZvbnRNYXRyaXgsIGdseXBoTmFtZU1hcCkgewogICAgc3VwZXIoZm9udE1hdHJpeCB8fCBbMC4wMDEsIDAsIDAsIDAuMDAxLCAwLCAwXSk7CiAgICB0aGlzLmdseXBocyA9IGNmZkluZm8uZ2x5cGhzOwogICAgdGhpcy5nc3VicnMgPSBjZmZJbmZvLmdzdWJycyB8fCBbXTsKICAgIHRoaXMuc3VicnMgPSBjZmZJbmZvLnN1YnJzIHx8IFtdOwogICAgdGhpcy5jbWFwID0gY21hcDsKICAgIHRoaXMuZ2x5cGhOYW1lTWFwID0gZ2x5cGhOYW1lTWFwIHx8ICgwLCBfZ2x5cGhsaXN0LmdldEdseXBoc1VuaWNvZGUpKCk7CiAgICB0aGlzLmdzdWJyc0JpYXMgPSBnZXRTdWJyb3V0aW5lQmlhcyh0aGlzLmdzdWJycyk7CiAgICB0aGlzLnN1YnJzQmlhcyA9IGdldFN1YnJvdXRpbmVCaWFzKHRoaXMuc3VicnMpOwogICAgdGhpcy5pc0NGRkNJREZvbnQgPSBjZmZJbmZvLmlzQ0ZGQ0lERm9udDsKICAgIHRoaXMuZmRTZWxlY3QgPSBjZmZJbmZvLmZkU2VsZWN0OwogICAgdGhpcy5mZEFycmF5ID0gY2ZmSW5mby5mZEFycmF5OwogIH0KICBjb21waWxlR2x5cGhJbXBsKGNvZGUsIGNtZHMsIGdseXBoSWQpIHsKICAgIGNvbXBpbGVDaGFyU3RyaW5nKGNvZGUsIGNtZHMsIHRoaXMsIGdseXBoSWQpOwogIH0KfQpjbGFzcyBGb250UmVuZGVyZXJGYWN0b3J5IHsKICBzdGF0aWMgY3JlYXRlKGZvbnQsIHNlYWNBbmFseXNpc0VuYWJsZWQpIHsKICAgIGNvbnN0IGRhdGEgPSBuZXcgVWludDhBcnJheShmb250LmRhdGEpOwogICAgbGV0IGNtYXAsIGdseWYsIGxvY2EsIGNmZiwgaW5kZXhUb0xvY0Zvcm1hdCwgdW5pdHNQZXJFbTsKICAgIGNvbnN0IG51bVRhYmxlcyA9IGdldFVpbnQxNihkYXRhLCA0KTsKICAgIGZvciAobGV0IGkgPSAwLCBwID0gMTI7IGkgPCBudW1UYWJsZXM7IGkrKywgcCArPSAxNikgewogICAgICBjb25zdCB0YWcgPSAoMCwgX3V0aWwuYnl0ZXNUb1N0cmluZykoZGF0YS5zdWJhcnJheShwLCBwICsgNCkpOwogICAgICBjb25zdCBvZmZzZXQgPSBnZXRVaW50MzIoZGF0YSwgcCArIDgpOwogICAgICBjb25zdCBsZW5ndGggPSBnZXRVaW50MzIoZGF0YSwgcCArIDEyKTsKICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICBjYXNlICJjbWFwIjoKICAgICAgICAgIGNtYXAgPSBwYXJzZUNtYXAoZGF0YSwgb2Zmc2V0LCBvZmZzZXQgKyBsZW5ndGgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZ2x5ZiI6CiAgICAgICAgICBnbHlmID0gZGF0YS5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIGxlbmd0aCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJsb2NhIjoKICAgICAgICAgIGxvY2EgPSBkYXRhLnN1YmFycmF5KG9mZnNldCwgb2Zmc2V0ICsgbGVuZ3RoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImhlYWQiOgogICAgICAgICAgdW5pdHNQZXJFbSA9IGdldFVpbnQxNihkYXRhLCBvZmZzZXQgKyAxOCk7CiAgICAgICAgICBpbmRleFRvTG9jRm9ybWF0ID0gZ2V0VWludDE2KGRhdGEsIG9mZnNldCArIDUwKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkNGRiAiOgogICAgICAgICAgY2ZmID0gcGFyc2VDZmYoZGF0YSwgb2Zmc2V0LCBvZmZzZXQgKyBsZW5ndGgsIHNlYWNBbmFseXNpc0VuYWJsZWQpOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGlmIChnbHlmKSB7CiAgICAgIGNvbnN0IGZvbnRNYXRyaXggPSAhdW5pdHNQZXJFbSA/IGZvbnQuZm9udE1hdHJpeCA6IFsxIC8gdW5pdHNQZXJFbSwgMCwgMCwgMSAvIHVuaXRzUGVyRW0sIDAsIDBdOwogICAgICByZXR1cm4gbmV3IFRydWVUeXBlQ29tcGlsZWQocGFyc2VHbHlmVGFibGUoZ2x5ZiwgbG9jYSwgaW5kZXhUb0xvY0Zvcm1hdCksIGNtYXAsIGZvbnRNYXRyaXgpOwogICAgfQogICAgcmV0dXJuIG5ldyBUeXBlMkNvbXBpbGVkKGNmZiwgY21hcCwgZm9udC5mb250TWF0cml4LCBmb250LmdseXBoTmFtZU1hcCk7CiAgfQp9CmV4cG9ydHMuRm9udFJlbmRlcmVyRmFjdG9yeSA9IEZvbnRSZW5kZXJlckZhY3Rvcnk7CgovKioqLyB9KSwKLyogMTgwICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5nZXRNZXRyaWNzID0gZXhwb3J0cy5nZXRGb250QmFzaWNNZXRyaWNzID0gdm9pZCAwOwp2YXIgX2NvcmVfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzOSk7CmNvbnN0IGdldE1ldHJpY3MgPSAoMCwgX2NvcmVfdXRpbHMuZ2V0TG9va3VwVGFibGVGYWN0b3J5KShmdW5jdGlvbiAodCkgewogIHQuQ291cmllciA9IDYwMDsKICB0WyJDb3VyaWVyLUJvbGQiXSA9IDYwMDsKICB0WyJDb3VyaWVyLUJvbGRPYmxpcXVlIl0gPSA2MDA7CiAgdFsiQ291cmllci1PYmxpcXVlIl0gPSA2MDA7CiAgdC5IZWx2ZXRpY2EgPSAoMCwgX2NvcmVfdXRpbHMuZ2V0TG9va3VwVGFibGVGYWN0b3J5KShmdW5jdGlvbiAodCkgewogICAgdC5zcGFjZSA9IDI3ODsKICAgIHQuZXhjbGFtID0gMjc4OwogICAgdC5xdW90ZWRibCA9IDM1NTsKICAgIHQubnVtYmVyc2lnbiA9IDU1NjsKICAgIHQuZG9sbGFyID0gNTU2OwogICAgdC5wZXJjZW50ID0gODg5OwogICAgdC5hbXBlcnNhbmQgPSA2Njc7CiAgICB0LnF1b3RlcmlnaHQgPSAyMjI7CiAgICB0LnBhcmVubGVmdCA9IDMzMzsKICAgIHQucGFyZW5yaWdodCA9IDMzMzsKICAgIHQuYXN0ZXJpc2sgPSAzODk7CiAgICB0LnBsdXMgPSA1ODQ7CiAgICB0LmNvbW1hID0gMjc4OwogICAgdC5oeXBoZW4gPSAzMzM7CiAgICB0LnBlcmlvZCA9IDI3ODsKICAgIHQuc2xhc2ggPSAyNzg7CiAgICB0Lnplcm8gPSA1NTY7CiAgICB0Lm9uZSA9IDU1NjsKICAgIHQudHdvID0gNTU2OwogICAgdC50aHJlZSA9IDU1NjsKICAgIHQuZm91ciA9IDU1NjsKICAgIHQuZml2ZSA9IDU1NjsKICAgIHQuc2l4ID0gNTU2OwogICAgdC5zZXZlbiA9IDU1NjsKICAgIHQuZWlnaHQgPSA1NTY7CiAgICB0Lm5pbmUgPSA1NTY7CiAgICB0LmNvbG9uID0gMjc4OwogICAgdC5zZW1pY29sb24gPSAyNzg7CiAgICB0Lmxlc3MgPSA1ODQ7CiAgICB0LmVxdWFsID0gNTg0OwogICAgdC5ncmVhdGVyID0gNTg0OwogICAgdC5xdWVzdGlvbiA9IDU1NjsKICAgIHQuYXQgPSAxMDE1OwogICAgdC5BID0gNjY3OwogICAgdC5CID0gNjY3OwogICAgdC5DID0gNzIyOwogICAgdC5EID0gNzIyOwogICAgdC5FID0gNjY3OwogICAgdC5GID0gNjExOwogICAgdC5HID0gNzc4OwogICAgdC5IID0gNzIyOwogICAgdC5JID0gMjc4OwogICAgdC5KID0gNTAwOwogICAgdC5LID0gNjY3OwogICAgdC5MID0gNTU2OwogICAgdC5NID0gODMzOwogICAgdC5OID0gNzIyOwogICAgdC5PID0gNzc4OwogICAgdC5QID0gNjY3OwogICAgdC5RID0gNzc4OwogICAgdC5SID0gNzIyOwogICAgdC5TID0gNjY3OwogICAgdC5UID0gNjExOwogICAgdC5VID0gNzIyOwogICAgdC5WID0gNjY3OwogICAgdC5XID0gOTQ0OwogICAgdC5YID0gNjY3OwogICAgdC5ZID0gNjY3OwogICAgdC5aID0gNjExOwogICAgdC5icmFja2V0bGVmdCA9IDI3ODsKICAgIHQuYmFja3NsYXNoID0gMjc4OwogICAgdC5icmFja2V0cmlnaHQgPSAyNzg7CiAgICB0LmFzY2lpY2lyY3VtID0gNDY5OwogICAgdC51bmRlcnNjb3JlID0gNTU2OwogICAgdC5xdW90ZWxlZnQgPSAyMjI7CiAgICB0LmEgPSA1NTY7CiAgICB0LmIgPSA1NTY7CiAgICB0LmMgPSA1MDA7CiAgICB0LmQgPSA1NTY7CiAgICB0LmUgPSA1NTY7CiAgICB0LmYgPSAyNzg7CiAgICB0LmcgPSA1NTY7CiAgICB0LmggPSA1NTY7CiAgICB0LmkgPSAyMjI7CiAgICB0LmogPSAyMjI7CiAgICB0LmsgPSA1MDA7CiAgICB0LmwgPSAyMjI7CiAgICB0Lm0gPSA4MzM7CiAgICB0Lm4gPSA1NTY7CiAgICB0Lm8gPSA1NTY7CiAgICB0LnAgPSA1NTY7CiAgICB0LnEgPSA1NTY7CiAgICB0LnIgPSAzMzM7CiAgICB0LnMgPSA1MDA7CiAgICB0LnQgPSAyNzg7CiAgICB0LnUgPSA1NTY7CiAgICB0LnYgPSA1MDA7CiAgICB0LncgPSA3MjI7CiAgICB0LnggPSA1MDA7CiAgICB0LnkgPSA1MDA7CiAgICB0LnogPSA1MDA7CiAgICB0LmJyYWNlbGVmdCA9IDMzNDsKICAgIHQuYmFyID0gMjYwOwogICAgdC5icmFjZXJpZ2h0ID0gMzM0OwogICAgdC5hc2NpaXRpbGRlID0gNTg0OwogICAgdC5leGNsYW1kb3duID0gMzMzOwogICAgdC5jZW50ID0gNTU2OwogICAgdC5zdGVybGluZyA9IDU1NjsKICAgIHQuZnJhY3Rpb24gPSAxNjc7CiAgICB0LnllbiA9IDU1NjsKICAgIHQuZmxvcmluID0gNTU2OwogICAgdC5zZWN0aW9uID0gNTU2OwogICAgdC5jdXJyZW5jeSA9IDU1NjsKICAgIHQucXVvdGVzaW5nbGUgPSAxOTE7CiAgICB0LnF1b3RlZGJsbGVmdCA9IDMzMzsKICAgIHQuZ3VpbGxlbW90bGVmdCA9IDU1NjsKICAgIHQuZ3VpbHNpbmdsbGVmdCA9IDMzMzsKICAgIHQuZ3VpbHNpbmdscmlnaHQgPSAzMzM7CiAgICB0LmZpID0gNTAwOwogICAgdC5mbCA9IDUwMDsKICAgIHQuZW5kYXNoID0gNTU2OwogICAgdC5kYWdnZXIgPSA1NTY7CiAgICB0LmRhZ2dlcmRibCA9IDU1NjsKICAgIHQucGVyaW9kY2VudGVyZWQgPSAyNzg7CiAgICB0LnBhcmFncmFwaCA9IDUzNzsKICAgIHQuYnVsbGV0ID0gMzUwOwogICAgdC5xdW90ZXNpbmdsYmFzZSA9IDIyMjsKICAgIHQucXVvdGVkYmxiYXNlID0gMzMzOwogICAgdC5xdW90ZWRibHJpZ2h0ID0gMzMzOwogICAgdC5ndWlsbGVtb3RyaWdodCA9IDU1NjsKICAgIHQuZWxsaXBzaXMgPSAxMDAwOwogICAgdC5wZXJ0aG91c2FuZCA9IDEwMDA7CiAgICB0LnF1ZXN0aW9uZG93biA9IDYxMTsKICAgIHQuZ3JhdmUgPSAzMzM7CiAgICB0LmFjdXRlID0gMzMzOwogICAgdC5jaXJjdW1mbGV4ID0gMzMzOwogICAgdC50aWxkZSA9IDMzMzsKICAgIHQubWFjcm9uID0gMzMzOwogICAgdC5icmV2ZSA9IDMzMzsKICAgIHQuZG90YWNjZW50ID0gMzMzOwogICAgdC5kaWVyZXNpcyA9IDMzMzsKICAgIHQucmluZyA9IDMzMzsKICAgIHQuY2VkaWxsYSA9IDMzMzsKICAgIHQuaHVuZ2FydW1sYXV0ID0gMzMzOwogICAgdC5vZ29uZWsgPSAzMzM7CiAgICB0LmNhcm9uID0gMzMzOwogICAgdC5lbWRhc2ggPSAxMDAwOwogICAgdC5BRSA9IDEwMDA7CiAgICB0Lm9yZGZlbWluaW5lID0gMzcwOwogICAgdC5Mc2xhc2ggPSA1NTY7CiAgICB0Lk9zbGFzaCA9IDc3ODsKICAgIHQuT0UgPSAxMDAwOwogICAgdC5vcmRtYXNjdWxpbmUgPSAzNjU7CiAgICB0LmFlID0gODg5OwogICAgdC5kb3RsZXNzaSA9IDI3ODsKICAgIHQubHNsYXNoID0gMjIyOwogICAgdC5vc2xhc2ggPSA2MTE7CiAgICB0Lm9lID0gOTQ0OwogICAgdC5nZXJtYW5kYmxzID0gNjExOwogICAgdC5JZGllcmVzaXMgPSAyNzg7CiAgICB0LmVhY3V0ZSA9IDU1NjsKICAgIHQuYWJyZXZlID0gNTU2OwogICAgdC51aHVuZ2FydW1sYXV0ID0gNTU2OwogICAgdC5lY2Fyb24gPSA1NTY7CiAgICB0LllkaWVyZXNpcyA9IDY2NzsKICAgIHQuZGl2aWRlID0gNTg0OwogICAgdC5ZYWN1dGUgPSA2Njc7CiAgICB0LkFjaXJjdW1mbGV4ID0gNjY3OwogICAgdC5hYWN1dGUgPSA1NTY7CiAgICB0LlVjaXJjdW1mbGV4ID0gNzIyOwogICAgdC55YWN1dGUgPSA1MDA7CiAgICB0LnNjb21tYWFjY2VudCA9IDUwMDsKICAgIHQuZWNpcmN1bWZsZXggPSA1NTY7CiAgICB0LlVyaW5nID0gNzIyOwogICAgdC5VZGllcmVzaXMgPSA3MjI7CiAgICB0LmFvZ29uZWsgPSA1NTY7CiAgICB0LlVhY3V0ZSA9IDcyMjsKICAgIHQudW9nb25layA9IDU1NjsKICAgIHQuRWRpZXJlc2lzID0gNjY3OwogICAgdC5EY3JvYXQgPSA3MjI7CiAgICB0LmNvbW1hYWNjZW50ID0gMjUwOwogICAgdC5jb3B5cmlnaHQgPSA3Mzc7CiAgICB0LkVtYWNyb24gPSA2Njc7CiAgICB0LmNjYXJvbiA9IDUwMDsKICAgIHQuYXJpbmcgPSA1NTY7CiAgICB0Lk5jb21tYWFjY2VudCA9IDcyMjsKICAgIHQubGFjdXRlID0gMjIyOwogICAgdC5hZ3JhdmUgPSA1NTY7CiAgICB0LlRjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQ2FjdXRlID0gNzIyOwogICAgdC5hdGlsZGUgPSA1NTY7CiAgICB0LkVkb3RhY2NlbnQgPSA2Njc7CiAgICB0LnNjYXJvbiA9IDUwMDsKICAgIHQuc2NlZGlsbGEgPSA1MDA7CiAgICB0LmlhY3V0ZSA9IDI3ODsKICAgIHQubG96ZW5nZSA9IDQ3MTsKICAgIHQuUmNhcm9uID0gNzIyOwogICAgdC5HY29tbWFhY2NlbnQgPSA3Nzg7CiAgICB0LnVjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5hY2lyY3VtZmxleCA9IDU1NjsKICAgIHQuQW1hY3JvbiA9IDY2NzsKICAgIHQucmNhcm9uID0gMzMzOwogICAgdC5jY2VkaWxsYSA9IDUwMDsKICAgIHQuWmRvdGFjY2VudCA9IDYxMTsKICAgIHQuVGhvcm4gPSA2Njc7CiAgICB0Lk9tYWNyb24gPSA3Nzg7CiAgICB0LlJhY3V0ZSA9IDcyMjsKICAgIHQuU2FjdXRlID0gNjY3OwogICAgdC5kY2Fyb24gPSA2NDM7CiAgICB0LlVtYWNyb24gPSA3MjI7CiAgICB0LnVyaW5nID0gNTU2OwogICAgdC50aHJlZXN1cGVyaW9yID0gMzMzOwogICAgdC5PZ3JhdmUgPSA3Nzg7CiAgICB0LkFncmF2ZSA9IDY2NzsKICAgIHQuQWJyZXZlID0gNjY3OwogICAgdC5tdWx0aXBseSA9IDU4NDsKICAgIHQudWFjdXRlID0gNTU2OwogICAgdC5UY2Fyb24gPSA2MTE7CiAgICB0LnBhcnRpYWxkaWZmID0gNDc2OwogICAgdC55ZGllcmVzaXMgPSA1MDA7CiAgICB0Lk5hY3V0ZSA9IDcyMjsKICAgIHQuaWNpcmN1bWZsZXggPSAyNzg7CiAgICB0LkVjaXJjdW1mbGV4ID0gNjY3OwogICAgdC5hZGllcmVzaXMgPSA1NTY7CiAgICB0LmVkaWVyZXNpcyA9IDU1NjsKICAgIHQuY2FjdXRlID0gNTAwOwogICAgdC5uYWN1dGUgPSA1NTY7CiAgICB0LnVtYWNyb24gPSA1NTY7CiAgICB0Lk5jYXJvbiA9IDcyMjsKICAgIHQuSWFjdXRlID0gMjc4OwogICAgdC5wbHVzbWludXMgPSA1ODQ7CiAgICB0LmJyb2tlbmJhciA9IDI2MDsKICAgIHQucmVnaXN0ZXJlZCA9IDczNzsKICAgIHQuR2JyZXZlID0gNzc4OwogICAgdC5JZG90YWNjZW50ID0gMjc4OwogICAgdC5zdW1tYXRpb24gPSA2MDA7CiAgICB0LkVncmF2ZSA9IDY2NzsKICAgIHQucmFjdXRlID0gMzMzOwogICAgdC5vbWFjcm9uID0gNTU2OwogICAgdC5aYWN1dGUgPSA2MTE7CiAgICB0LlpjYXJvbiA9IDYxMTsKICAgIHQuZ3JlYXRlcmVxdWFsID0gNTQ5OwogICAgdC5FdGggPSA3MjI7CiAgICB0LkNjZWRpbGxhID0gNzIyOwogICAgdC5sY29tbWFhY2NlbnQgPSAyMjI7CiAgICB0LnRjYXJvbiA9IDMxNzsKICAgIHQuZW9nb25layA9IDU1NjsKICAgIHQuVW9nb25layA9IDcyMjsKICAgIHQuQWFjdXRlID0gNjY3OwogICAgdC5BZGllcmVzaXMgPSA2Njc7CiAgICB0LmVncmF2ZSA9IDU1NjsKICAgIHQuemFjdXRlID0gNTAwOwogICAgdC5pb2dvbmVrID0gMjIyOwogICAgdC5PYWN1dGUgPSA3Nzg7CiAgICB0Lm9hY3V0ZSA9IDU1NjsKICAgIHQuYW1hY3JvbiA9IDU1NjsKICAgIHQuc2FjdXRlID0gNTAwOwogICAgdC5pZGllcmVzaXMgPSAyNzg7CiAgICB0Lk9jaXJjdW1mbGV4ID0gNzc4OwogICAgdC5VZ3JhdmUgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC50aG9ybiA9IDU1NjsKICAgIHQudHdvc3VwZXJpb3IgPSAzMzM7CiAgICB0Lk9kaWVyZXNpcyA9IDc3ODsKICAgIHQubXUgPSA1NTY7CiAgICB0LmlncmF2ZSA9IDI3ODsKICAgIHQub2h1bmdhcnVtbGF1dCA9IDU1NjsKICAgIHQuRW9nb25layA9IDY2NzsKICAgIHQuZGNyb2F0ID0gNTU2OwogICAgdC50aHJlZXF1YXJ0ZXJzID0gODM0OwogICAgdC5TY2VkaWxsYSA9IDY2NzsKICAgIHQubGNhcm9uID0gMjk5OwogICAgdC5LY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0LkxhY3V0ZSA9IDU1NjsKICAgIHQudHJhZGVtYXJrID0gMTAwMDsKICAgIHQuZWRvdGFjY2VudCA9IDU1NjsKICAgIHQuSWdyYXZlID0gMjc4OwogICAgdC5JbWFjcm9uID0gMjc4OwogICAgdC5MY2Fyb24gPSA1NTY7CiAgICB0Lm9uZWhhbGYgPSA4MzQ7CiAgICB0Lmxlc3NlcXVhbCA9IDU0OTsKICAgIHQub2NpcmN1bWZsZXggPSA1NTY7CiAgICB0Lm50aWxkZSA9IDU1NjsKICAgIHQuVWh1bmdhcnVtbGF1dCA9IDcyMjsKICAgIHQuRWFjdXRlID0gNjY3OwogICAgdC5lbWFjcm9uID0gNTU2OwogICAgdC5nYnJldmUgPSA1NTY7CiAgICB0Lm9uZXF1YXJ0ZXIgPSA4MzQ7CiAgICB0LlNjYXJvbiA9IDY2NzsKICAgIHQuU2NvbW1hYWNjZW50ID0gNjY3OwogICAgdC5PaHVuZ2FydW1sYXV0ID0gNzc4OwogICAgdC5kZWdyZWUgPSA0MDA7CiAgICB0Lm9ncmF2ZSA9IDU1NjsKICAgIHQuQ2Nhcm9uID0gNzIyOwogICAgdC51Z3JhdmUgPSA1NTY7CiAgICB0LnJhZGljYWwgPSA0NTM7CiAgICB0LkRjYXJvbiA9IDcyMjsKICAgIHQucmNvbW1hYWNjZW50ID0gMzMzOwogICAgdC5OdGlsZGUgPSA3MjI7CiAgICB0Lm90aWxkZSA9IDU1NjsKICAgIHQuUmNvbW1hYWNjZW50ID0gNzIyOwogICAgdC5MY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0LkF0aWxkZSA9IDY2NzsKICAgIHQuQW9nb25layA9IDY2NzsKICAgIHQuQXJpbmcgPSA2Njc7CiAgICB0Lk90aWxkZSA9IDc3ODsKICAgIHQuemRvdGFjY2VudCA9IDUwMDsKICAgIHQuRWNhcm9uID0gNjY3OwogICAgdC5Jb2dvbmVrID0gMjc4OwogICAgdC5rY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0Lm1pbnVzID0gNTg0OwogICAgdC5JY2lyY3VtZmxleCA9IDI3ODsKICAgIHQubmNhcm9uID0gNTU2OwogICAgdC50Y29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LmxvZ2ljYWxub3QgPSA1ODQ7CiAgICB0Lm9kaWVyZXNpcyA9IDU1NjsKICAgIHQudWRpZXJlc2lzID0gNTU2OwogICAgdC5ub3RlcXVhbCA9IDU0OTsKICAgIHQuZ2NvbW1hYWNjZW50ID0gNTU2OwogICAgdC5ldGggPSA1NTY7CiAgICB0LnpjYXJvbiA9IDUwMDsKICAgIHQubmNvbW1hYWNjZW50ID0gNTU2OwogICAgdC5vbmVzdXBlcmlvciA9IDMzMzsKICAgIHQuaW1hY3JvbiA9IDI3ODsKICAgIHQuRXVybyA9IDU1NjsKICB9KTsKICB0WyJIZWx2ZXRpY2EtQm9sZCJdID0gKDAsIF9jb3JlX3V0aWxzLmdldExvb2t1cFRhYmxlRmFjdG9yeSkoZnVuY3Rpb24gKHQpIHsKICAgIHQuc3BhY2UgPSAyNzg7CiAgICB0LmV4Y2xhbSA9IDMzMzsKICAgIHQucXVvdGVkYmwgPSA0NzQ7CiAgICB0Lm51bWJlcnNpZ24gPSA1NTY7CiAgICB0LmRvbGxhciA9IDU1NjsKICAgIHQucGVyY2VudCA9IDg4OTsKICAgIHQuYW1wZXJzYW5kID0gNzIyOwogICAgdC5xdW90ZXJpZ2h0ID0gMjc4OwogICAgdC5wYXJlbmxlZnQgPSAzMzM7CiAgICB0LnBhcmVucmlnaHQgPSAzMzM7CiAgICB0LmFzdGVyaXNrID0gMzg5OwogICAgdC5wbHVzID0gNTg0OwogICAgdC5jb21tYSA9IDI3ODsKICAgIHQuaHlwaGVuID0gMzMzOwogICAgdC5wZXJpb2QgPSAyNzg7CiAgICB0LnNsYXNoID0gMjc4OwogICAgdC56ZXJvID0gNTU2OwogICAgdC5vbmUgPSA1NTY7CiAgICB0LnR3byA9IDU1NjsKICAgIHQudGhyZWUgPSA1NTY7CiAgICB0LmZvdXIgPSA1NTY7CiAgICB0LmZpdmUgPSA1NTY7CiAgICB0LnNpeCA9IDU1NjsKICAgIHQuc2V2ZW4gPSA1NTY7CiAgICB0LmVpZ2h0ID0gNTU2OwogICAgdC5uaW5lID0gNTU2OwogICAgdC5jb2xvbiA9IDMzMzsKICAgIHQuc2VtaWNvbG9uID0gMzMzOwogICAgdC5sZXNzID0gNTg0OwogICAgdC5lcXVhbCA9IDU4NDsKICAgIHQuZ3JlYXRlciA9IDU4NDsKICAgIHQucXVlc3Rpb24gPSA2MTE7CiAgICB0LmF0ID0gOTc1OwogICAgdC5BID0gNzIyOwogICAgdC5CID0gNzIyOwogICAgdC5DID0gNzIyOwogICAgdC5EID0gNzIyOwogICAgdC5FID0gNjY3OwogICAgdC5GID0gNjExOwogICAgdC5HID0gNzc4OwogICAgdC5IID0gNzIyOwogICAgdC5JID0gMjc4OwogICAgdC5KID0gNTU2OwogICAgdC5LID0gNzIyOwogICAgdC5MID0gNjExOwogICAgdC5NID0gODMzOwogICAgdC5OID0gNzIyOwogICAgdC5PID0gNzc4OwogICAgdC5QID0gNjY3OwogICAgdC5RID0gNzc4OwogICAgdC5SID0gNzIyOwogICAgdC5TID0gNjY3OwogICAgdC5UID0gNjExOwogICAgdC5VID0gNzIyOwogICAgdC5WID0gNjY3OwogICAgdC5XID0gOTQ0OwogICAgdC5YID0gNjY3OwogICAgdC5ZID0gNjY3OwogICAgdC5aID0gNjExOwogICAgdC5icmFja2V0bGVmdCA9IDMzMzsKICAgIHQuYmFja3NsYXNoID0gMjc4OwogICAgdC5icmFja2V0cmlnaHQgPSAzMzM7CiAgICB0LmFzY2lpY2lyY3VtID0gNTg0OwogICAgdC51bmRlcnNjb3JlID0gNTU2OwogICAgdC5xdW90ZWxlZnQgPSAyNzg7CiAgICB0LmEgPSA1NTY7CiAgICB0LmIgPSA2MTE7CiAgICB0LmMgPSA1NTY7CiAgICB0LmQgPSA2MTE7CiAgICB0LmUgPSA1NTY7CiAgICB0LmYgPSAzMzM7CiAgICB0LmcgPSA2MTE7CiAgICB0LmggPSA2MTE7CiAgICB0LmkgPSAyNzg7CiAgICB0LmogPSAyNzg7CiAgICB0LmsgPSA1NTY7CiAgICB0LmwgPSAyNzg7CiAgICB0Lm0gPSA4ODk7CiAgICB0Lm4gPSA2MTE7CiAgICB0Lm8gPSA2MTE7CiAgICB0LnAgPSA2MTE7CiAgICB0LnEgPSA2MTE7CiAgICB0LnIgPSAzODk7CiAgICB0LnMgPSA1NTY7CiAgICB0LnQgPSAzMzM7CiAgICB0LnUgPSA2MTE7CiAgICB0LnYgPSA1NTY7CiAgICB0LncgPSA3Nzg7CiAgICB0LnggPSA1NTY7CiAgICB0LnkgPSA1NTY7CiAgICB0LnogPSA1MDA7CiAgICB0LmJyYWNlbGVmdCA9IDM4OTsKICAgIHQuYmFyID0gMjgwOwogICAgdC5icmFjZXJpZ2h0ID0gMzg5OwogICAgdC5hc2NpaXRpbGRlID0gNTg0OwogICAgdC5leGNsYW1kb3duID0gMzMzOwogICAgdC5jZW50ID0gNTU2OwogICAgdC5zdGVybGluZyA9IDU1NjsKICAgIHQuZnJhY3Rpb24gPSAxNjc7CiAgICB0LnllbiA9IDU1NjsKICAgIHQuZmxvcmluID0gNTU2OwogICAgdC5zZWN0aW9uID0gNTU2OwogICAgdC5jdXJyZW5jeSA9IDU1NjsKICAgIHQucXVvdGVzaW5nbGUgPSAyMzg7CiAgICB0LnF1b3RlZGJsbGVmdCA9IDUwMDsKICAgIHQuZ3VpbGxlbW90bGVmdCA9IDU1NjsKICAgIHQuZ3VpbHNpbmdsbGVmdCA9IDMzMzsKICAgIHQuZ3VpbHNpbmdscmlnaHQgPSAzMzM7CiAgICB0LmZpID0gNjExOwogICAgdC5mbCA9IDYxMTsKICAgIHQuZW5kYXNoID0gNTU2OwogICAgdC5kYWdnZXIgPSA1NTY7CiAgICB0LmRhZ2dlcmRibCA9IDU1NjsKICAgIHQucGVyaW9kY2VudGVyZWQgPSAyNzg7CiAgICB0LnBhcmFncmFwaCA9IDU1NjsKICAgIHQuYnVsbGV0ID0gMzUwOwogICAgdC5xdW90ZXNpbmdsYmFzZSA9IDI3ODsKICAgIHQucXVvdGVkYmxiYXNlID0gNTAwOwogICAgdC5xdW90ZWRibHJpZ2h0ID0gNTAwOwogICAgdC5ndWlsbGVtb3RyaWdodCA9IDU1NjsKICAgIHQuZWxsaXBzaXMgPSAxMDAwOwogICAgdC5wZXJ0aG91c2FuZCA9IDEwMDA7CiAgICB0LnF1ZXN0aW9uZG93biA9IDYxMTsKICAgIHQuZ3JhdmUgPSAzMzM7CiAgICB0LmFjdXRlID0gMzMzOwogICAgdC5jaXJjdW1mbGV4ID0gMzMzOwogICAgdC50aWxkZSA9IDMzMzsKICAgIHQubWFjcm9uID0gMzMzOwogICAgdC5icmV2ZSA9IDMzMzsKICAgIHQuZG90YWNjZW50ID0gMzMzOwogICAgdC5kaWVyZXNpcyA9IDMzMzsKICAgIHQucmluZyA9IDMzMzsKICAgIHQuY2VkaWxsYSA9IDMzMzsKICAgIHQuaHVuZ2FydW1sYXV0ID0gMzMzOwogICAgdC5vZ29uZWsgPSAzMzM7CiAgICB0LmNhcm9uID0gMzMzOwogICAgdC5lbWRhc2ggPSAxMDAwOwogICAgdC5BRSA9IDEwMDA7CiAgICB0Lm9yZGZlbWluaW5lID0gMzcwOwogICAgdC5Mc2xhc2ggPSA2MTE7CiAgICB0Lk9zbGFzaCA9IDc3ODsKICAgIHQuT0UgPSAxMDAwOwogICAgdC5vcmRtYXNjdWxpbmUgPSAzNjU7CiAgICB0LmFlID0gODg5OwogICAgdC5kb3RsZXNzaSA9IDI3ODsKICAgIHQubHNsYXNoID0gMjc4OwogICAgdC5vc2xhc2ggPSA2MTE7CiAgICB0Lm9lID0gOTQ0OwogICAgdC5nZXJtYW5kYmxzID0gNjExOwogICAgdC5JZGllcmVzaXMgPSAyNzg7CiAgICB0LmVhY3V0ZSA9IDU1NjsKICAgIHQuYWJyZXZlID0gNTU2OwogICAgdC51aHVuZ2FydW1sYXV0ID0gNjExOwogICAgdC5lY2Fyb24gPSA1NTY7CiAgICB0LllkaWVyZXNpcyA9IDY2NzsKICAgIHQuZGl2aWRlID0gNTg0OwogICAgdC5ZYWN1dGUgPSA2Njc7CiAgICB0LkFjaXJjdW1mbGV4ID0gNzIyOwogICAgdC5hYWN1dGUgPSA1NTY7CiAgICB0LlVjaXJjdW1mbGV4ID0gNzIyOwogICAgdC55YWN1dGUgPSA1NTY7CiAgICB0LnNjb21tYWFjY2VudCA9IDU1NjsKICAgIHQuZWNpcmN1bWZsZXggPSA1NTY7CiAgICB0LlVyaW5nID0gNzIyOwogICAgdC5VZGllcmVzaXMgPSA3MjI7CiAgICB0LmFvZ29uZWsgPSA1NTY7CiAgICB0LlVhY3V0ZSA9IDcyMjsKICAgIHQudW9nb25layA9IDYxMTsKICAgIHQuRWRpZXJlc2lzID0gNjY3OwogICAgdC5EY3JvYXQgPSA3MjI7CiAgICB0LmNvbW1hYWNjZW50ID0gMjUwOwogICAgdC5jb3B5cmlnaHQgPSA3Mzc7CiAgICB0LkVtYWNyb24gPSA2Njc7CiAgICB0LmNjYXJvbiA9IDU1NjsKICAgIHQuYXJpbmcgPSA1NTY7CiAgICB0Lk5jb21tYWFjY2VudCA9IDcyMjsKICAgIHQubGFjdXRlID0gMjc4OwogICAgdC5hZ3JhdmUgPSA1NTY7CiAgICB0LlRjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQ2FjdXRlID0gNzIyOwogICAgdC5hdGlsZGUgPSA1NTY7CiAgICB0LkVkb3RhY2NlbnQgPSA2Njc7CiAgICB0LnNjYXJvbiA9IDU1NjsKICAgIHQuc2NlZGlsbGEgPSA1NTY7CiAgICB0LmlhY3V0ZSA9IDI3ODsKICAgIHQubG96ZW5nZSA9IDQ5NDsKICAgIHQuUmNhcm9uID0gNzIyOwogICAgdC5HY29tbWFhY2NlbnQgPSA3Nzg7CiAgICB0LnVjaXJjdW1mbGV4ID0gNjExOwogICAgdC5hY2lyY3VtZmxleCA9IDU1NjsKICAgIHQuQW1hY3JvbiA9IDcyMjsKICAgIHQucmNhcm9uID0gMzg5OwogICAgdC5jY2VkaWxsYSA9IDU1NjsKICAgIHQuWmRvdGFjY2VudCA9IDYxMTsKICAgIHQuVGhvcm4gPSA2Njc7CiAgICB0Lk9tYWNyb24gPSA3Nzg7CiAgICB0LlJhY3V0ZSA9IDcyMjsKICAgIHQuU2FjdXRlID0gNjY3OwogICAgdC5kY2Fyb24gPSA3NDM7CiAgICB0LlVtYWNyb24gPSA3MjI7CiAgICB0LnVyaW5nID0gNjExOwogICAgdC50aHJlZXN1cGVyaW9yID0gMzMzOwogICAgdC5PZ3JhdmUgPSA3Nzg7CiAgICB0LkFncmF2ZSA9IDcyMjsKICAgIHQuQWJyZXZlID0gNzIyOwogICAgdC5tdWx0aXBseSA9IDU4NDsKICAgIHQudWFjdXRlID0gNjExOwogICAgdC5UY2Fyb24gPSA2MTE7CiAgICB0LnBhcnRpYWxkaWZmID0gNDk0OwogICAgdC55ZGllcmVzaXMgPSA1NTY7CiAgICB0Lk5hY3V0ZSA9IDcyMjsKICAgIHQuaWNpcmN1bWZsZXggPSAyNzg7CiAgICB0LkVjaXJjdW1mbGV4ID0gNjY3OwogICAgdC5hZGllcmVzaXMgPSA1NTY7CiAgICB0LmVkaWVyZXNpcyA9IDU1NjsKICAgIHQuY2FjdXRlID0gNTU2OwogICAgdC5uYWN1dGUgPSA2MTE7CiAgICB0LnVtYWNyb24gPSA2MTE7CiAgICB0Lk5jYXJvbiA9IDcyMjsKICAgIHQuSWFjdXRlID0gMjc4OwogICAgdC5wbHVzbWludXMgPSA1ODQ7CiAgICB0LmJyb2tlbmJhciA9IDI4MDsKICAgIHQucmVnaXN0ZXJlZCA9IDczNzsKICAgIHQuR2JyZXZlID0gNzc4OwogICAgdC5JZG90YWNjZW50ID0gMjc4OwogICAgdC5zdW1tYXRpb24gPSA2MDA7CiAgICB0LkVncmF2ZSA9IDY2NzsKICAgIHQucmFjdXRlID0gMzg5OwogICAgdC5vbWFjcm9uID0gNjExOwogICAgdC5aYWN1dGUgPSA2MTE7CiAgICB0LlpjYXJvbiA9IDYxMTsKICAgIHQuZ3JlYXRlcmVxdWFsID0gNTQ5OwogICAgdC5FdGggPSA3MjI7CiAgICB0LkNjZWRpbGxhID0gNzIyOwogICAgdC5sY29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LnRjYXJvbiA9IDM4OTsKICAgIHQuZW9nb25layA9IDU1NjsKICAgIHQuVW9nb25layA9IDcyMjsKICAgIHQuQWFjdXRlID0gNzIyOwogICAgdC5BZGllcmVzaXMgPSA3MjI7CiAgICB0LmVncmF2ZSA9IDU1NjsKICAgIHQuemFjdXRlID0gNTAwOwogICAgdC5pb2dvbmVrID0gMjc4OwogICAgdC5PYWN1dGUgPSA3Nzg7CiAgICB0Lm9hY3V0ZSA9IDYxMTsKICAgIHQuYW1hY3JvbiA9IDU1NjsKICAgIHQuc2FjdXRlID0gNTU2OwogICAgdC5pZGllcmVzaXMgPSAyNzg7CiAgICB0Lk9jaXJjdW1mbGV4ID0gNzc4OwogICAgdC5VZ3JhdmUgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC50aG9ybiA9IDYxMTsKICAgIHQudHdvc3VwZXJpb3IgPSAzMzM7CiAgICB0Lk9kaWVyZXNpcyA9IDc3ODsKICAgIHQubXUgPSA2MTE7CiAgICB0LmlncmF2ZSA9IDI3ODsKICAgIHQub2h1bmdhcnVtbGF1dCA9IDYxMTsKICAgIHQuRW9nb25layA9IDY2NzsKICAgIHQuZGNyb2F0ID0gNjExOwogICAgdC50aHJlZXF1YXJ0ZXJzID0gODM0OwogICAgdC5TY2VkaWxsYSA9IDY2NzsKICAgIHQubGNhcm9uID0gNDAwOwogICAgdC5LY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LkxhY3V0ZSA9IDYxMTsKICAgIHQudHJhZGVtYXJrID0gMTAwMDsKICAgIHQuZWRvdGFjY2VudCA9IDU1NjsKICAgIHQuSWdyYXZlID0gMjc4OwogICAgdC5JbWFjcm9uID0gMjc4OwogICAgdC5MY2Fyb24gPSA2MTE7CiAgICB0Lm9uZWhhbGYgPSA4MzQ7CiAgICB0Lmxlc3NlcXVhbCA9IDU0OTsKICAgIHQub2NpcmN1bWZsZXggPSA2MTE7CiAgICB0Lm50aWxkZSA9IDYxMTsKICAgIHQuVWh1bmdhcnVtbGF1dCA9IDcyMjsKICAgIHQuRWFjdXRlID0gNjY3OwogICAgdC5lbWFjcm9uID0gNTU2OwogICAgdC5nYnJldmUgPSA2MTE7CiAgICB0Lm9uZXF1YXJ0ZXIgPSA4MzQ7CiAgICB0LlNjYXJvbiA9IDY2NzsKICAgIHQuU2NvbW1hYWNjZW50ID0gNjY3OwogICAgdC5PaHVuZ2FydW1sYXV0ID0gNzc4OwogICAgdC5kZWdyZWUgPSA0MDA7CiAgICB0Lm9ncmF2ZSA9IDYxMTsKICAgIHQuQ2Nhcm9uID0gNzIyOwogICAgdC51Z3JhdmUgPSA2MTE7CiAgICB0LnJhZGljYWwgPSA1NDk7CiAgICB0LkRjYXJvbiA9IDcyMjsKICAgIHQucmNvbW1hYWNjZW50ID0gMzg5OwogICAgdC5OdGlsZGUgPSA3MjI7CiAgICB0Lm90aWxkZSA9IDYxMTsKICAgIHQuUmNvbW1hYWNjZW50ID0gNzIyOwogICAgdC5MY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0LkF0aWxkZSA9IDcyMjsKICAgIHQuQW9nb25layA9IDcyMjsKICAgIHQuQXJpbmcgPSA3MjI7CiAgICB0Lk90aWxkZSA9IDc3ODsKICAgIHQuemRvdGFjY2VudCA9IDUwMDsKICAgIHQuRWNhcm9uID0gNjY3OwogICAgdC5Jb2dvbmVrID0gMjc4OwogICAgdC5rY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0Lm1pbnVzID0gNTg0OwogICAgdC5JY2lyY3VtZmxleCA9IDI3ODsKICAgIHQubmNhcm9uID0gNjExOwogICAgdC50Y29tbWFhY2NlbnQgPSAzMzM7CiAgICB0LmxvZ2ljYWxub3QgPSA1ODQ7CiAgICB0Lm9kaWVyZXNpcyA9IDYxMTsKICAgIHQudWRpZXJlc2lzID0gNjExOwogICAgdC5ub3RlcXVhbCA9IDU0OTsKICAgIHQuZ2NvbW1hYWNjZW50ID0gNjExOwogICAgdC5ldGggPSA2MTE7CiAgICB0LnpjYXJvbiA9IDUwMDsKICAgIHQubmNvbW1hYWNjZW50ID0gNjExOwogICAgdC5vbmVzdXBlcmlvciA9IDMzMzsKICAgIHQuaW1hY3JvbiA9IDI3ODsKICAgIHQuRXVybyA9IDU1NjsKICB9KTsKICB0WyJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiXSA9ICgwLCBfY29yZV91dGlscy5nZXRMb29rdXBUYWJsZUZhY3RvcnkpKGZ1bmN0aW9uICh0KSB7CiAgICB0LnNwYWNlID0gMjc4OwogICAgdC5leGNsYW0gPSAzMzM7CiAgICB0LnF1b3RlZGJsID0gNDc0OwogICAgdC5udW1iZXJzaWduID0gNTU2OwogICAgdC5kb2xsYXIgPSA1NTY7CiAgICB0LnBlcmNlbnQgPSA4ODk7CiAgICB0LmFtcGVyc2FuZCA9IDcyMjsKICAgIHQucXVvdGVyaWdodCA9IDI3ODsKICAgIHQucGFyZW5sZWZ0ID0gMzMzOwogICAgdC5wYXJlbnJpZ2h0ID0gMzMzOwogICAgdC5hc3RlcmlzayA9IDM4OTsKICAgIHQucGx1cyA9IDU4NDsKICAgIHQuY29tbWEgPSAyNzg7CiAgICB0Lmh5cGhlbiA9IDMzMzsKICAgIHQucGVyaW9kID0gMjc4OwogICAgdC5zbGFzaCA9IDI3ODsKICAgIHQuemVybyA9IDU1NjsKICAgIHQub25lID0gNTU2OwogICAgdC50d28gPSA1NTY7CiAgICB0LnRocmVlID0gNTU2OwogICAgdC5mb3VyID0gNTU2OwogICAgdC5maXZlID0gNTU2OwogICAgdC5zaXggPSA1NTY7CiAgICB0LnNldmVuID0gNTU2OwogICAgdC5laWdodCA9IDU1NjsKICAgIHQubmluZSA9IDU1NjsKICAgIHQuY29sb24gPSAzMzM7CiAgICB0LnNlbWljb2xvbiA9IDMzMzsKICAgIHQubGVzcyA9IDU4NDsKICAgIHQuZXF1YWwgPSA1ODQ7CiAgICB0LmdyZWF0ZXIgPSA1ODQ7CiAgICB0LnF1ZXN0aW9uID0gNjExOwogICAgdC5hdCA9IDk3NTsKICAgIHQuQSA9IDcyMjsKICAgIHQuQiA9IDcyMjsKICAgIHQuQyA9IDcyMjsKICAgIHQuRCA9IDcyMjsKICAgIHQuRSA9IDY2NzsKICAgIHQuRiA9IDYxMTsKICAgIHQuRyA9IDc3ODsKICAgIHQuSCA9IDcyMjsKICAgIHQuSSA9IDI3ODsKICAgIHQuSiA9IDU1NjsKICAgIHQuSyA9IDcyMjsKICAgIHQuTCA9IDYxMTsKICAgIHQuTSA9IDgzMzsKICAgIHQuTiA9IDcyMjsKICAgIHQuTyA9IDc3ODsKICAgIHQuUCA9IDY2NzsKICAgIHQuUSA9IDc3ODsKICAgIHQuUiA9IDcyMjsKICAgIHQuUyA9IDY2NzsKICAgIHQuVCA9IDYxMTsKICAgIHQuVSA9IDcyMjsKICAgIHQuViA9IDY2NzsKICAgIHQuVyA9IDk0NDsKICAgIHQuWCA9IDY2NzsKICAgIHQuWSA9IDY2NzsKICAgIHQuWiA9IDYxMTsKICAgIHQuYnJhY2tldGxlZnQgPSAzMzM7CiAgICB0LmJhY2tzbGFzaCA9IDI3ODsKICAgIHQuYnJhY2tldHJpZ2h0ID0gMzMzOwogICAgdC5hc2NpaWNpcmN1bSA9IDU4NDsKICAgIHQudW5kZXJzY29yZSA9IDU1NjsKICAgIHQucXVvdGVsZWZ0ID0gMjc4OwogICAgdC5hID0gNTU2OwogICAgdC5iID0gNjExOwogICAgdC5jID0gNTU2OwogICAgdC5kID0gNjExOwogICAgdC5lID0gNTU2OwogICAgdC5mID0gMzMzOwogICAgdC5nID0gNjExOwogICAgdC5oID0gNjExOwogICAgdC5pID0gMjc4OwogICAgdC5qID0gMjc4OwogICAgdC5rID0gNTU2OwogICAgdC5sID0gMjc4OwogICAgdC5tID0gODg5OwogICAgdC5uID0gNjExOwogICAgdC5vID0gNjExOwogICAgdC5wID0gNjExOwogICAgdC5xID0gNjExOwogICAgdC5yID0gMzg5OwogICAgdC5zID0gNTU2OwogICAgdC50ID0gMzMzOwogICAgdC51ID0gNjExOwogICAgdC52ID0gNTU2OwogICAgdC53ID0gNzc4OwogICAgdC54ID0gNTU2OwogICAgdC55ID0gNTU2OwogICAgdC56ID0gNTAwOwogICAgdC5icmFjZWxlZnQgPSAzODk7CiAgICB0LmJhciA9IDI4MDsKICAgIHQuYnJhY2VyaWdodCA9IDM4OTsKICAgIHQuYXNjaWl0aWxkZSA9IDU4NDsKICAgIHQuZXhjbGFtZG93biA9IDMzMzsKICAgIHQuY2VudCA9IDU1NjsKICAgIHQuc3RlcmxpbmcgPSA1NTY7CiAgICB0LmZyYWN0aW9uID0gMTY3OwogICAgdC55ZW4gPSA1NTY7CiAgICB0LmZsb3JpbiA9IDU1NjsKICAgIHQuc2VjdGlvbiA9IDU1NjsKICAgIHQuY3VycmVuY3kgPSA1NTY7CiAgICB0LnF1b3Rlc2luZ2xlID0gMjM4OwogICAgdC5xdW90ZWRibGxlZnQgPSA1MDA7CiAgICB0Lmd1aWxsZW1vdGxlZnQgPSA1NTY7CiAgICB0Lmd1aWxzaW5nbGxlZnQgPSAzMzM7CiAgICB0Lmd1aWxzaW5nbHJpZ2h0ID0gMzMzOwogICAgdC5maSA9IDYxMTsKICAgIHQuZmwgPSA2MTE7CiAgICB0LmVuZGFzaCA9IDU1NjsKICAgIHQuZGFnZ2VyID0gNTU2OwogICAgdC5kYWdnZXJkYmwgPSA1NTY7CiAgICB0LnBlcmlvZGNlbnRlcmVkID0gMjc4OwogICAgdC5wYXJhZ3JhcGggPSA1NTY7CiAgICB0LmJ1bGxldCA9IDM1MDsKICAgIHQucXVvdGVzaW5nbGJhc2UgPSAyNzg7CiAgICB0LnF1b3RlZGJsYmFzZSA9IDUwMDsKICAgIHQucXVvdGVkYmxyaWdodCA9IDUwMDsKICAgIHQuZ3VpbGxlbW90cmlnaHQgPSA1NTY7CiAgICB0LmVsbGlwc2lzID0gMTAwMDsKICAgIHQucGVydGhvdXNhbmQgPSAxMDAwOwogICAgdC5xdWVzdGlvbmRvd24gPSA2MTE7CiAgICB0LmdyYXZlID0gMzMzOwogICAgdC5hY3V0ZSA9IDMzMzsKICAgIHQuY2lyY3VtZmxleCA9IDMzMzsKICAgIHQudGlsZGUgPSAzMzM7CiAgICB0Lm1hY3JvbiA9IDMzMzsKICAgIHQuYnJldmUgPSAzMzM7CiAgICB0LmRvdGFjY2VudCA9IDMzMzsKICAgIHQuZGllcmVzaXMgPSAzMzM7CiAgICB0LnJpbmcgPSAzMzM7CiAgICB0LmNlZGlsbGEgPSAzMzM7CiAgICB0Lmh1bmdhcnVtbGF1dCA9IDMzMzsKICAgIHQub2dvbmVrID0gMzMzOwogICAgdC5jYXJvbiA9IDMzMzsKICAgIHQuZW1kYXNoID0gMTAwMDsKICAgIHQuQUUgPSAxMDAwOwogICAgdC5vcmRmZW1pbmluZSA9IDM3MDsKICAgIHQuTHNsYXNoID0gNjExOwogICAgdC5Pc2xhc2ggPSA3Nzg7CiAgICB0Lk9FID0gMTAwMDsKICAgIHQub3JkbWFzY3VsaW5lID0gMzY1OwogICAgdC5hZSA9IDg4OTsKICAgIHQuZG90bGVzc2kgPSAyNzg7CiAgICB0LmxzbGFzaCA9IDI3ODsKICAgIHQub3NsYXNoID0gNjExOwogICAgdC5vZSA9IDk0NDsKICAgIHQuZ2VybWFuZGJscyA9IDYxMTsKICAgIHQuSWRpZXJlc2lzID0gMjc4OwogICAgdC5lYWN1dGUgPSA1NTY7CiAgICB0LmFicmV2ZSA9IDU1NjsKICAgIHQudWh1bmdhcnVtbGF1dCA9IDYxMTsKICAgIHQuZWNhcm9uID0gNTU2OwogICAgdC5ZZGllcmVzaXMgPSA2Njc7CiAgICB0LmRpdmlkZSA9IDU4NDsKICAgIHQuWWFjdXRlID0gNjY3OwogICAgdC5BY2lyY3VtZmxleCA9IDcyMjsKICAgIHQuYWFjdXRlID0gNTU2OwogICAgdC5VY2lyY3VtZmxleCA9IDcyMjsKICAgIHQueWFjdXRlID0gNTU2OwogICAgdC5zY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0LmVjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5VcmluZyA9IDcyMjsKICAgIHQuVWRpZXJlc2lzID0gNzIyOwogICAgdC5hb2dvbmVrID0gNTU2OwogICAgdC5VYWN1dGUgPSA3MjI7CiAgICB0LnVvZ29uZWsgPSA2MTE7CiAgICB0LkVkaWVyZXNpcyA9IDY2NzsKICAgIHQuRGNyb2F0ID0gNzIyOwogICAgdC5jb21tYWFjY2VudCA9IDI1MDsKICAgIHQuY29weXJpZ2h0ID0gNzM3OwogICAgdC5FbWFjcm9uID0gNjY3OwogICAgdC5jY2Fyb24gPSA1NTY7CiAgICB0LmFyaW5nID0gNTU2OwogICAgdC5OY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LmxhY3V0ZSA9IDI3ODsKICAgIHQuYWdyYXZlID0gNTU2OwogICAgdC5UY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0LkNhY3V0ZSA9IDcyMjsKICAgIHQuYXRpbGRlID0gNTU2OwogICAgdC5FZG90YWNjZW50ID0gNjY3OwogICAgdC5zY2Fyb24gPSA1NTY7CiAgICB0LnNjZWRpbGxhID0gNTU2OwogICAgdC5pYWN1dGUgPSAyNzg7CiAgICB0LmxvemVuZ2UgPSA0OTQ7CiAgICB0LlJjYXJvbiA9IDcyMjsKICAgIHQuR2NvbW1hYWNjZW50ID0gNzc4OwogICAgdC51Y2lyY3VtZmxleCA9IDYxMTsKICAgIHQuYWNpcmN1bWZsZXggPSA1NTY7CiAgICB0LkFtYWNyb24gPSA3MjI7CiAgICB0LnJjYXJvbiA9IDM4OTsKICAgIHQuY2NlZGlsbGEgPSA1NTY7CiAgICB0Llpkb3RhY2NlbnQgPSA2MTE7CiAgICB0LlRob3JuID0gNjY3OwogICAgdC5PbWFjcm9uID0gNzc4OwogICAgdC5SYWN1dGUgPSA3MjI7CiAgICB0LlNhY3V0ZSA9IDY2NzsKICAgIHQuZGNhcm9uID0gNzQzOwogICAgdC5VbWFjcm9uID0gNzIyOwogICAgdC51cmluZyA9IDYxMTsKICAgIHQudGhyZWVzdXBlcmlvciA9IDMzMzsKICAgIHQuT2dyYXZlID0gNzc4OwogICAgdC5BZ3JhdmUgPSA3MjI7CiAgICB0LkFicmV2ZSA9IDcyMjsKICAgIHQubXVsdGlwbHkgPSA1ODQ7CiAgICB0LnVhY3V0ZSA9IDYxMTsKICAgIHQuVGNhcm9uID0gNjExOwogICAgdC5wYXJ0aWFsZGlmZiA9IDQ5NDsKICAgIHQueWRpZXJlc2lzID0gNTU2OwogICAgdC5OYWN1dGUgPSA3MjI7CiAgICB0LmljaXJjdW1mbGV4ID0gMjc4OwogICAgdC5FY2lyY3VtZmxleCA9IDY2NzsKICAgIHQuYWRpZXJlc2lzID0gNTU2OwogICAgdC5lZGllcmVzaXMgPSA1NTY7CiAgICB0LmNhY3V0ZSA9IDU1NjsKICAgIHQubmFjdXRlID0gNjExOwogICAgdC51bWFjcm9uID0gNjExOwogICAgdC5OY2Fyb24gPSA3MjI7CiAgICB0LklhY3V0ZSA9IDI3ODsKICAgIHQucGx1c21pbnVzID0gNTg0OwogICAgdC5icm9rZW5iYXIgPSAyODA7CiAgICB0LnJlZ2lzdGVyZWQgPSA3Mzc7CiAgICB0LkdicmV2ZSA9IDc3ODsKICAgIHQuSWRvdGFjY2VudCA9IDI3ODsKICAgIHQuc3VtbWF0aW9uID0gNjAwOwogICAgdC5FZ3JhdmUgPSA2Njc7CiAgICB0LnJhY3V0ZSA9IDM4OTsKICAgIHQub21hY3JvbiA9IDYxMTsKICAgIHQuWmFjdXRlID0gNjExOwogICAgdC5aY2Fyb24gPSA2MTE7CiAgICB0LmdyZWF0ZXJlcXVhbCA9IDU0OTsKICAgIHQuRXRoID0gNzIyOwogICAgdC5DY2VkaWxsYSA9IDcyMjsKICAgIHQubGNvbW1hYWNjZW50ID0gMjc4OwogICAgdC50Y2Fyb24gPSAzODk7CiAgICB0LmVvZ29uZWsgPSA1NTY7CiAgICB0LlVvZ29uZWsgPSA3MjI7CiAgICB0LkFhY3V0ZSA9IDcyMjsKICAgIHQuQWRpZXJlc2lzID0gNzIyOwogICAgdC5lZ3JhdmUgPSA1NTY7CiAgICB0LnphY3V0ZSA9IDUwMDsKICAgIHQuaW9nb25layA9IDI3ODsKICAgIHQuT2FjdXRlID0gNzc4OwogICAgdC5vYWN1dGUgPSA2MTE7CiAgICB0LmFtYWNyb24gPSA1NTY7CiAgICB0LnNhY3V0ZSA9IDU1NjsKICAgIHQuaWRpZXJlc2lzID0gMjc4OwogICAgdC5PY2lyY3VtZmxleCA9IDc3ODsKICAgIHQuVWdyYXZlID0gNzIyOwogICAgdC5EZWx0YSA9IDYxMjsKICAgIHQudGhvcm4gPSA2MTE7CiAgICB0LnR3b3N1cGVyaW9yID0gMzMzOwogICAgdC5PZGllcmVzaXMgPSA3Nzg7CiAgICB0Lm11ID0gNjExOwogICAgdC5pZ3JhdmUgPSAyNzg7CiAgICB0Lm9odW5nYXJ1bWxhdXQgPSA2MTE7CiAgICB0LkVvZ29uZWsgPSA2Njc7CiAgICB0LmRjcm9hdCA9IDYxMTsKICAgIHQudGhyZWVxdWFydGVycyA9IDgzNDsKICAgIHQuU2NlZGlsbGEgPSA2Njc7CiAgICB0LmxjYXJvbiA9IDQwMDsKICAgIHQuS2NvbW1hYWNjZW50ID0gNzIyOwogICAgdC5MYWN1dGUgPSA2MTE7CiAgICB0LnRyYWRlbWFyayA9IDEwMDA7CiAgICB0LmVkb3RhY2NlbnQgPSA1NTY7CiAgICB0LklncmF2ZSA9IDI3ODsKICAgIHQuSW1hY3JvbiA9IDI3ODsKICAgIHQuTGNhcm9uID0gNjExOwogICAgdC5vbmVoYWxmID0gODM0OwogICAgdC5sZXNzZXF1YWwgPSA1NDk7CiAgICB0Lm9jaXJjdW1mbGV4ID0gNjExOwogICAgdC5udGlsZGUgPSA2MTE7CiAgICB0LlVodW5nYXJ1bWxhdXQgPSA3MjI7CiAgICB0LkVhY3V0ZSA9IDY2NzsKICAgIHQuZW1hY3JvbiA9IDU1NjsKICAgIHQuZ2JyZXZlID0gNjExOwogICAgdC5vbmVxdWFydGVyID0gODM0OwogICAgdC5TY2Fyb24gPSA2Njc7CiAgICB0LlNjb21tYWFjY2VudCA9IDY2NzsKICAgIHQuT2h1bmdhcnVtbGF1dCA9IDc3ODsKICAgIHQuZGVncmVlID0gNDAwOwogICAgdC5vZ3JhdmUgPSA2MTE7CiAgICB0LkNjYXJvbiA9IDcyMjsKICAgIHQudWdyYXZlID0gNjExOwogICAgdC5yYWRpY2FsID0gNTQ5OwogICAgdC5EY2Fyb24gPSA3MjI7CiAgICB0LnJjb21tYWFjY2VudCA9IDM4OTsKICAgIHQuTnRpbGRlID0gNzIyOwogICAgdC5vdGlsZGUgPSA2MTE7CiAgICB0LlJjb21tYWFjY2VudCA9IDcyMjsKICAgIHQuTGNvbW1hYWNjZW50ID0gNjExOwogICAgdC5BdGlsZGUgPSA3MjI7CiAgICB0LkFvZ29uZWsgPSA3MjI7CiAgICB0LkFyaW5nID0gNzIyOwogICAgdC5PdGlsZGUgPSA3Nzg7CiAgICB0Lnpkb3RhY2NlbnQgPSA1MDA7CiAgICB0LkVjYXJvbiA9IDY2NzsKICAgIHQuSW9nb25layA9IDI3ODsKICAgIHQua2NvbW1hYWNjZW50ID0gNTU2OwogICAgdC5taW51cyA9IDU4NDsKICAgIHQuSWNpcmN1bWZsZXggPSAyNzg7CiAgICB0Lm5jYXJvbiA9IDYxMTsKICAgIHQudGNvbW1hYWNjZW50ID0gMzMzOwogICAgdC5sb2dpY2Fsbm90ID0gNTg0OwogICAgdC5vZGllcmVzaXMgPSA2MTE7CiAgICB0LnVkaWVyZXNpcyA9IDYxMTsKICAgIHQubm90ZXF1YWwgPSA1NDk7CiAgICB0Lmdjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuZXRoID0gNjExOwogICAgdC56Y2Fyb24gPSA1MDA7CiAgICB0Lm5jb21tYWFjY2VudCA9IDYxMTsKICAgIHQub25lc3VwZXJpb3IgPSAzMzM7CiAgICB0LmltYWNyb24gPSAyNzg7CiAgICB0LkV1cm8gPSA1NTY7CiAgfSk7CiAgdFsiSGVsdmV0aWNhLU9ibGlxdWUiXSA9ICgwLCBfY29yZV91dGlscy5nZXRMb29rdXBUYWJsZUZhY3RvcnkpKGZ1bmN0aW9uICh0KSB7CiAgICB0LnNwYWNlID0gMjc4OwogICAgdC5leGNsYW0gPSAyNzg7CiAgICB0LnF1b3RlZGJsID0gMzU1OwogICAgdC5udW1iZXJzaWduID0gNTU2OwogICAgdC5kb2xsYXIgPSA1NTY7CiAgICB0LnBlcmNlbnQgPSA4ODk7CiAgICB0LmFtcGVyc2FuZCA9IDY2NzsKICAgIHQucXVvdGVyaWdodCA9IDIyMjsKICAgIHQucGFyZW5sZWZ0ID0gMzMzOwogICAgdC5wYXJlbnJpZ2h0ID0gMzMzOwogICAgdC5hc3RlcmlzayA9IDM4OTsKICAgIHQucGx1cyA9IDU4NDsKICAgIHQuY29tbWEgPSAyNzg7CiAgICB0Lmh5cGhlbiA9IDMzMzsKICAgIHQucGVyaW9kID0gMjc4OwogICAgdC5zbGFzaCA9IDI3ODsKICAgIHQuemVybyA9IDU1NjsKICAgIHQub25lID0gNTU2OwogICAgdC50d28gPSA1NTY7CiAgICB0LnRocmVlID0gNTU2OwogICAgdC5mb3VyID0gNTU2OwogICAgdC5maXZlID0gNTU2OwogICAgdC5zaXggPSA1NTY7CiAgICB0LnNldmVuID0gNTU2OwogICAgdC5laWdodCA9IDU1NjsKICAgIHQubmluZSA9IDU1NjsKICAgIHQuY29sb24gPSAyNzg7CiAgICB0LnNlbWljb2xvbiA9IDI3ODsKICAgIHQubGVzcyA9IDU4NDsKICAgIHQuZXF1YWwgPSA1ODQ7CiAgICB0LmdyZWF0ZXIgPSA1ODQ7CiAgICB0LnF1ZXN0aW9uID0gNTU2OwogICAgdC5hdCA9IDEwMTU7CiAgICB0LkEgPSA2Njc7CiAgICB0LkIgPSA2Njc7CiAgICB0LkMgPSA3MjI7CiAgICB0LkQgPSA3MjI7CiAgICB0LkUgPSA2Njc7CiAgICB0LkYgPSA2MTE7CiAgICB0LkcgPSA3Nzg7CiAgICB0LkggPSA3MjI7CiAgICB0LkkgPSAyNzg7CiAgICB0LkogPSA1MDA7CiAgICB0LksgPSA2Njc7CiAgICB0LkwgPSA1NTY7CiAgICB0Lk0gPSA4MzM7CiAgICB0Lk4gPSA3MjI7CiAgICB0Lk8gPSA3Nzg7CiAgICB0LlAgPSA2Njc7CiAgICB0LlEgPSA3Nzg7CiAgICB0LlIgPSA3MjI7CiAgICB0LlMgPSA2Njc7CiAgICB0LlQgPSA2MTE7CiAgICB0LlUgPSA3MjI7CiAgICB0LlYgPSA2Njc7CiAgICB0LlcgPSA5NDQ7CiAgICB0LlggPSA2Njc7CiAgICB0LlkgPSA2Njc7CiAgICB0LlogPSA2MTE7CiAgICB0LmJyYWNrZXRsZWZ0ID0gMjc4OwogICAgdC5iYWNrc2xhc2ggPSAyNzg7CiAgICB0LmJyYWNrZXRyaWdodCA9IDI3ODsKICAgIHQuYXNjaWljaXJjdW0gPSA0Njk7CiAgICB0LnVuZGVyc2NvcmUgPSA1NTY7CiAgICB0LnF1b3RlbGVmdCA9IDIyMjsKICAgIHQuYSA9IDU1NjsKICAgIHQuYiA9IDU1NjsKICAgIHQuYyA9IDUwMDsKICAgIHQuZCA9IDU1NjsKICAgIHQuZSA9IDU1NjsKICAgIHQuZiA9IDI3ODsKICAgIHQuZyA9IDU1NjsKICAgIHQuaCA9IDU1NjsKICAgIHQuaSA9IDIyMjsKICAgIHQuaiA9IDIyMjsKICAgIHQuayA9IDUwMDsKICAgIHQubCA9IDIyMjsKICAgIHQubSA9IDgzMzsKICAgIHQubiA9IDU1NjsKICAgIHQubyA9IDU1NjsKICAgIHQucCA9IDU1NjsKICAgIHQucSA9IDU1NjsKICAgIHQuciA9IDMzMzsKICAgIHQucyA9IDUwMDsKICAgIHQudCA9IDI3ODsKICAgIHQudSA9IDU1NjsKICAgIHQudiA9IDUwMDsKICAgIHQudyA9IDcyMjsKICAgIHQueCA9IDUwMDsKICAgIHQueSA9IDUwMDsKICAgIHQueiA9IDUwMDsKICAgIHQuYnJhY2VsZWZ0ID0gMzM0OwogICAgdC5iYXIgPSAyNjA7CiAgICB0LmJyYWNlcmlnaHQgPSAzMzQ7CiAgICB0LmFzY2lpdGlsZGUgPSA1ODQ7CiAgICB0LmV4Y2xhbWRvd24gPSAzMzM7CiAgICB0LmNlbnQgPSA1NTY7CiAgICB0LnN0ZXJsaW5nID0gNTU2OwogICAgdC5mcmFjdGlvbiA9IDE2NzsKICAgIHQueWVuID0gNTU2OwogICAgdC5mbG9yaW4gPSA1NTY7CiAgICB0LnNlY3Rpb24gPSA1NTY7CiAgICB0LmN1cnJlbmN5ID0gNTU2OwogICAgdC5xdW90ZXNpbmdsZSA9IDE5MTsKICAgIHQucXVvdGVkYmxsZWZ0ID0gMzMzOwogICAgdC5ndWlsbGVtb3RsZWZ0ID0gNTU2OwogICAgdC5ndWlsc2luZ2xsZWZ0ID0gMzMzOwogICAgdC5ndWlsc2luZ2xyaWdodCA9IDMzMzsKICAgIHQuZmkgPSA1MDA7CiAgICB0LmZsID0gNTAwOwogICAgdC5lbmRhc2ggPSA1NTY7CiAgICB0LmRhZ2dlciA9IDU1NjsKICAgIHQuZGFnZ2VyZGJsID0gNTU2OwogICAgdC5wZXJpb2RjZW50ZXJlZCA9IDI3ODsKICAgIHQucGFyYWdyYXBoID0gNTM3OwogICAgdC5idWxsZXQgPSAzNTA7CiAgICB0LnF1b3Rlc2luZ2xiYXNlID0gMjIyOwogICAgdC5xdW90ZWRibGJhc2UgPSAzMzM7CiAgICB0LnF1b3RlZGJscmlnaHQgPSAzMzM7CiAgICB0Lmd1aWxsZW1vdHJpZ2h0ID0gNTU2OwogICAgdC5lbGxpcHNpcyA9IDEwMDA7CiAgICB0LnBlcnRob3VzYW5kID0gMTAwMDsKICAgIHQucXVlc3Rpb25kb3duID0gNjExOwogICAgdC5ncmF2ZSA9IDMzMzsKICAgIHQuYWN1dGUgPSAzMzM7CiAgICB0LmNpcmN1bWZsZXggPSAzMzM7CiAgICB0LnRpbGRlID0gMzMzOwogICAgdC5tYWNyb24gPSAzMzM7CiAgICB0LmJyZXZlID0gMzMzOwogICAgdC5kb3RhY2NlbnQgPSAzMzM7CiAgICB0LmRpZXJlc2lzID0gMzMzOwogICAgdC5yaW5nID0gMzMzOwogICAgdC5jZWRpbGxhID0gMzMzOwogICAgdC5odW5nYXJ1bWxhdXQgPSAzMzM7CiAgICB0Lm9nb25layA9IDMzMzsKICAgIHQuY2Fyb24gPSAzMzM7CiAgICB0LmVtZGFzaCA9IDEwMDA7CiAgICB0LkFFID0gMTAwMDsKICAgIHQub3JkZmVtaW5pbmUgPSAzNzA7CiAgICB0LkxzbGFzaCA9IDU1NjsKICAgIHQuT3NsYXNoID0gNzc4OwogICAgdC5PRSA9IDEwMDA7CiAgICB0Lm9yZG1hc2N1bGluZSA9IDM2NTsKICAgIHQuYWUgPSA4ODk7CiAgICB0LmRvdGxlc3NpID0gMjc4OwogICAgdC5sc2xhc2ggPSAyMjI7CiAgICB0Lm9zbGFzaCA9IDYxMTsKICAgIHQub2UgPSA5NDQ7CiAgICB0Lmdlcm1hbmRibHMgPSA2MTE7CiAgICB0LklkaWVyZXNpcyA9IDI3ODsKICAgIHQuZWFjdXRlID0gNTU2OwogICAgdC5hYnJldmUgPSA1NTY7CiAgICB0LnVodW5nYXJ1bWxhdXQgPSA1NTY7CiAgICB0LmVjYXJvbiA9IDU1NjsKICAgIHQuWWRpZXJlc2lzID0gNjY3OwogICAgdC5kaXZpZGUgPSA1ODQ7CiAgICB0LllhY3V0ZSA9IDY2NzsKICAgIHQuQWNpcmN1bWZsZXggPSA2Njc7CiAgICB0LmFhY3V0ZSA9IDU1NjsKICAgIHQuVWNpcmN1bWZsZXggPSA3MjI7CiAgICB0LnlhY3V0ZSA9IDUwMDsKICAgIHQuc2NvbW1hYWNjZW50ID0gNTAwOwogICAgdC5lY2lyY3VtZmxleCA9IDU1NjsKICAgIHQuVXJpbmcgPSA3MjI7CiAgICB0LlVkaWVyZXNpcyA9IDcyMjsKICAgIHQuYW9nb25layA9IDU1NjsKICAgIHQuVWFjdXRlID0gNzIyOwogICAgdC51b2dvbmVrID0gNTU2OwogICAgdC5FZGllcmVzaXMgPSA2Njc7CiAgICB0LkRjcm9hdCA9IDcyMjsKICAgIHQuY29tbWFhY2NlbnQgPSAyNTA7CiAgICB0LmNvcHlyaWdodCA9IDczNzsKICAgIHQuRW1hY3JvbiA9IDY2NzsKICAgIHQuY2Nhcm9uID0gNTAwOwogICAgdC5hcmluZyA9IDU1NjsKICAgIHQuTmNvbW1hYWNjZW50ID0gNzIyOwogICAgdC5sYWN1dGUgPSAyMjI7CiAgICB0LmFncmF2ZSA9IDU1NjsKICAgIHQuVGNvbW1hYWNjZW50ID0gNjExOwogICAgdC5DYWN1dGUgPSA3MjI7CiAgICB0LmF0aWxkZSA9IDU1NjsKICAgIHQuRWRvdGFjY2VudCA9IDY2NzsKICAgIHQuc2Nhcm9uID0gNTAwOwogICAgdC5zY2VkaWxsYSA9IDUwMDsKICAgIHQuaWFjdXRlID0gMjc4OwogICAgdC5sb3plbmdlID0gNDcxOwogICAgdC5SY2Fyb24gPSA3MjI7CiAgICB0Lkdjb21tYWFjY2VudCA9IDc3ODsKICAgIHQudWNpcmN1bWZsZXggPSA1NTY7CiAgICB0LmFjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5BbWFjcm9uID0gNjY3OwogICAgdC5yY2Fyb24gPSAzMzM7CiAgICB0LmNjZWRpbGxhID0gNTAwOwogICAgdC5aZG90YWNjZW50ID0gNjExOwogICAgdC5UaG9ybiA9IDY2NzsKICAgIHQuT21hY3JvbiA9IDc3ODsKICAgIHQuUmFjdXRlID0gNzIyOwogICAgdC5TYWN1dGUgPSA2Njc7CiAgICB0LmRjYXJvbiA9IDY0MzsKICAgIHQuVW1hY3JvbiA9IDcyMjsKICAgIHQudXJpbmcgPSA1NTY7CiAgICB0LnRocmVlc3VwZXJpb3IgPSAzMzM7CiAgICB0Lk9ncmF2ZSA9IDc3ODsKICAgIHQuQWdyYXZlID0gNjY3OwogICAgdC5BYnJldmUgPSA2Njc7CiAgICB0Lm11bHRpcGx5ID0gNTg0OwogICAgdC51YWN1dGUgPSA1NTY7CiAgICB0LlRjYXJvbiA9IDYxMTsKICAgIHQucGFydGlhbGRpZmYgPSA0NzY7CiAgICB0LnlkaWVyZXNpcyA9IDUwMDsKICAgIHQuTmFjdXRlID0gNzIyOwogICAgdC5pY2lyY3VtZmxleCA9IDI3ODsKICAgIHQuRWNpcmN1bWZsZXggPSA2Njc7CiAgICB0LmFkaWVyZXNpcyA9IDU1NjsKICAgIHQuZWRpZXJlc2lzID0gNTU2OwogICAgdC5jYWN1dGUgPSA1MDA7CiAgICB0Lm5hY3V0ZSA9IDU1NjsKICAgIHQudW1hY3JvbiA9IDU1NjsKICAgIHQuTmNhcm9uID0gNzIyOwogICAgdC5JYWN1dGUgPSAyNzg7CiAgICB0LnBsdXNtaW51cyA9IDU4NDsKICAgIHQuYnJva2VuYmFyID0gMjYwOwogICAgdC5yZWdpc3RlcmVkID0gNzM3OwogICAgdC5HYnJldmUgPSA3Nzg7CiAgICB0Lklkb3RhY2NlbnQgPSAyNzg7CiAgICB0LnN1bW1hdGlvbiA9IDYwMDsKICAgIHQuRWdyYXZlID0gNjY3OwogICAgdC5yYWN1dGUgPSAzMzM7CiAgICB0Lm9tYWNyb24gPSA1NTY7CiAgICB0LlphY3V0ZSA9IDYxMTsKICAgIHQuWmNhcm9uID0gNjExOwogICAgdC5ncmVhdGVyZXF1YWwgPSA1NDk7CiAgICB0LkV0aCA9IDcyMjsKICAgIHQuQ2NlZGlsbGEgPSA3MjI7CiAgICB0Lmxjb21tYWFjY2VudCA9IDIyMjsKICAgIHQudGNhcm9uID0gMzE3OwogICAgdC5lb2dvbmVrID0gNTU2OwogICAgdC5Vb2dvbmVrID0gNzIyOwogICAgdC5BYWN1dGUgPSA2Njc7CiAgICB0LkFkaWVyZXNpcyA9IDY2NzsKICAgIHQuZWdyYXZlID0gNTU2OwogICAgdC56YWN1dGUgPSA1MDA7CiAgICB0LmlvZ29uZWsgPSAyMjI7CiAgICB0Lk9hY3V0ZSA9IDc3ODsKICAgIHQub2FjdXRlID0gNTU2OwogICAgdC5hbWFjcm9uID0gNTU2OwogICAgdC5zYWN1dGUgPSA1MDA7CiAgICB0LmlkaWVyZXNpcyA9IDI3ODsKICAgIHQuT2NpcmN1bWZsZXggPSA3Nzg7CiAgICB0LlVncmF2ZSA9IDcyMjsKICAgIHQuRGVsdGEgPSA2MTI7CiAgICB0LnRob3JuID0gNTU2OwogICAgdC50d29zdXBlcmlvciA9IDMzMzsKICAgIHQuT2RpZXJlc2lzID0gNzc4OwogICAgdC5tdSA9IDU1NjsKICAgIHQuaWdyYXZlID0gMjc4OwogICAgdC5vaHVuZ2FydW1sYXV0ID0gNTU2OwogICAgdC5Fb2dvbmVrID0gNjY3OwogICAgdC5kY3JvYXQgPSA1NTY7CiAgICB0LnRocmVlcXVhcnRlcnMgPSA4MzQ7CiAgICB0LlNjZWRpbGxhID0gNjY3OwogICAgdC5sY2Fyb24gPSAyOTk7CiAgICB0Lktjb21tYWFjY2VudCA9IDY2NzsKICAgIHQuTGFjdXRlID0gNTU2OwogICAgdC50cmFkZW1hcmsgPSAxMDAwOwogICAgdC5lZG90YWNjZW50ID0gNTU2OwogICAgdC5JZ3JhdmUgPSAyNzg7CiAgICB0LkltYWNyb24gPSAyNzg7CiAgICB0LkxjYXJvbiA9IDU1NjsKICAgIHQub25laGFsZiA9IDgzNDsKICAgIHQubGVzc2VxdWFsID0gNTQ5OwogICAgdC5vY2lyY3VtZmxleCA9IDU1NjsKICAgIHQubnRpbGRlID0gNTU2OwogICAgdC5VaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5FYWN1dGUgPSA2Njc7CiAgICB0LmVtYWNyb24gPSA1NTY7CiAgICB0LmdicmV2ZSA9IDU1NjsKICAgIHQub25lcXVhcnRlciA9IDgzNDsKICAgIHQuU2Nhcm9uID0gNjY3OwogICAgdC5TY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0Lk9odW5nYXJ1bWxhdXQgPSA3Nzg7CiAgICB0LmRlZ3JlZSA9IDQwMDsKICAgIHQub2dyYXZlID0gNTU2OwogICAgdC5DY2Fyb24gPSA3MjI7CiAgICB0LnVncmF2ZSA9IDU1NjsKICAgIHQucmFkaWNhbCA9IDQ1MzsKICAgIHQuRGNhcm9uID0gNzIyOwogICAgdC5yY29tbWFhY2NlbnQgPSAzMzM7CiAgICB0Lk50aWxkZSA9IDcyMjsKICAgIHQub3RpbGRlID0gNTU2OwogICAgdC5SY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0Lkxjb21tYWFjY2VudCA9IDU1NjsKICAgIHQuQXRpbGRlID0gNjY3OwogICAgdC5Bb2dvbmVrID0gNjY3OwogICAgdC5BcmluZyA9IDY2NzsKICAgIHQuT3RpbGRlID0gNzc4OwogICAgdC56ZG90YWNjZW50ID0gNTAwOwogICAgdC5FY2Fyb24gPSA2Njc7CiAgICB0LklvZ29uZWsgPSAyNzg7CiAgICB0Lmtjb21tYWFjY2VudCA9IDUwMDsKICAgIHQubWludXMgPSA1ODQ7CiAgICB0LkljaXJjdW1mbGV4ID0gMjc4OwogICAgdC5uY2Fyb24gPSA1NTY7CiAgICB0LnRjb21tYWFjY2VudCA9IDI3ODsKICAgIHQubG9naWNhbG5vdCA9IDU4NDsKICAgIHQub2RpZXJlc2lzID0gNTU2OwogICAgdC51ZGllcmVzaXMgPSA1NTY7CiAgICB0Lm5vdGVxdWFsID0gNTQ5OwogICAgdC5nY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0LmV0aCA9IDU1NjsKICAgIHQuemNhcm9uID0gNTAwOwogICAgdC5uY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0Lm9uZXN1cGVyaW9yID0gMzMzOwogICAgdC5pbWFjcm9uID0gMjc4OwogICAgdC5FdXJvID0gNTU2OwogIH0pOwogIHQuU3ltYm9sID0gKDAsIF9jb3JlX3V0aWxzLmdldExvb2t1cFRhYmxlRmFjdG9yeSkoZnVuY3Rpb24gKHQpIHsKICAgIHQuc3BhY2UgPSAyNTA7CiAgICB0LmV4Y2xhbSA9IDMzMzsKICAgIHQudW5pdmVyc2FsID0gNzEzOwogICAgdC5udW1iZXJzaWduID0gNTAwOwogICAgdC5leGlzdGVudGlhbCA9IDU0OTsKICAgIHQucGVyY2VudCA9IDgzMzsKICAgIHQuYW1wZXJzYW5kID0gNzc4OwogICAgdC5zdWNodGhhdCA9IDQzOTsKICAgIHQucGFyZW5sZWZ0ID0gMzMzOwogICAgdC5wYXJlbnJpZ2h0ID0gMzMzOwogICAgdC5hc3Rlcmlza21hdGggPSA1MDA7CiAgICB0LnBsdXMgPSA1NDk7CiAgICB0LmNvbW1hID0gMjUwOwogICAgdC5taW51cyA9IDU0OTsKICAgIHQucGVyaW9kID0gMjUwOwogICAgdC5zbGFzaCA9IDI3ODsKICAgIHQuemVybyA9IDUwMDsKICAgIHQub25lID0gNTAwOwogICAgdC50d28gPSA1MDA7CiAgICB0LnRocmVlID0gNTAwOwogICAgdC5mb3VyID0gNTAwOwogICAgdC5maXZlID0gNTAwOwogICAgdC5zaXggPSA1MDA7CiAgICB0LnNldmVuID0gNTAwOwogICAgdC5laWdodCA9IDUwMDsKICAgIHQubmluZSA9IDUwMDsKICAgIHQuY29sb24gPSAyNzg7CiAgICB0LnNlbWljb2xvbiA9IDI3ODsKICAgIHQubGVzcyA9IDU0OTsKICAgIHQuZXF1YWwgPSA1NDk7CiAgICB0LmdyZWF0ZXIgPSA1NDk7CiAgICB0LnF1ZXN0aW9uID0gNDQ0OwogICAgdC5jb25ncnVlbnQgPSA1NDk7CiAgICB0LkFscGhhID0gNzIyOwogICAgdC5CZXRhID0gNjY3OwogICAgdC5DaGkgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC5FcHNpbG9uID0gNjExOwogICAgdC5QaGkgPSA3NjM7CiAgICB0LkdhbW1hID0gNjAzOwogICAgdC5FdGEgPSA3MjI7CiAgICB0LklvdGEgPSAzMzM7CiAgICB0LnRoZXRhMSA9IDYzMTsKICAgIHQuS2FwcGEgPSA3MjI7CiAgICB0LkxhbWJkYSA9IDY4NjsKICAgIHQuTXUgPSA4ODk7CiAgICB0Lk51ID0gNzIyOwogICAgdC5PbWljcm9uID0gNzIyOwogICAgdC5QaSA9IDc2ODsKICAgIHQuVGhldGEgPSA3NDE7CiAgICB0LlJobyA9IDU1NjsKICAgIHQuU2lnbWEgPSA1OTI7CiAgICB0LlRhdSA9IDYxMTsKICAgIHQuVXBzaWxvbiA9IDY5MDsKICAgIHQuc2lnbWExID0gNDM5OwogICAgdC5PbWVnYSA9IDc2ODsKICAgIHQuWGkgPSA2NDU7CiAgICB0LlBzaSA9IDc5NTsKICAgIHQuWmV0YSA9IDYxMTsKICAgIHQuYnJhY2tldGxlZnQgPSAzMzM7CiAgICB0LnRoZXJlZm9yZSA9IDg2MzsKICAgIHQuYnJhY2tldHJpZ2h0ID0gMzMzOwogICAgdC5wZXJwZW5kaWN1bGFyID0gNjU4OwogICAgdC51bmRlcnNjb3JlID0gNTAwOwogICAgdC5yYWRpY2FsZXggPSA1MDA7CiAgICB0LmFscGhhID0gNjMxOwogICAgdC5iZXRhID0gNTQ5OwogICAgdC5jaGkgPSA1NDk7CiAgICB0LmRlbHRhID0gNDk0OwogICAgdC5lcHNpbG9uID0gNDM5OwogICAgdC5waGkgPSA1MjE7CiAgICB0LmdhbW1hID0gNDExOwogICAgdC5ldGEgPSA2MDM7CiAgICB0LmlvdGEgPSAzMjk7CiAgICB0LnBoaTEgPSA2MDM7CiAgICB0LmthcHBhID0gNTQ5OwogICAgdC5sYW1iZGEgPSA1NDk7CiAgICB0Lm11ID0gNTc2OwogICAgdC5udSA9IDUyMTsKICAgIHQub21pY3JvbiA9IDU0OTsKICAgIHQucGkgPSA1NDk7CiAgICB0LnRoZXRhID0gNTIxOwogICAgdC5yaG8gPSA1NDk7CiAgICB0LnNpZ21hID0gNjAzOwogICAgdC50YXUgPSA0Mzk7CiAgICB0LnVwc2lsb24gPSA1NzY7CiAgICB0Lm9tZWdhMSA9IDcxMzsKICAgIHQub21lZ2EgPSA2ODY7CiAgICB0LnhpID0gNDkzOwogICAgdC5wc2kgPSA2ODY7CiAgICB0LnpldGEgPSA0OTQ7CiAgICB0LmJyYWNlbGVmdCA9IDQ4MDsKICAgIHQuYmFyID0gMjAwOwogICAgdC5icmFjZXJpZ2h0ID0gNDgwOwogICAgdC5zaW1pbGFyID0gNTQ5OwogICAgdC5FdXJvID0gNzUwOwogICAgdC5VcHNpbG9uMSA9IDYyMDsKICAgIHQubWludXRlID0gMjQ3OwogICAgdC5sZXNzZXF1YWwgPSA1NDk7CiAgICB0LmZyYWN0aW9uID0gMTY3OwogICAgdC5pbmZpbml0eSA9IDcxMzsKICAgIHQuZmxvcmluID0gNTAwOwogICAgdC5jbHViID0gNzUzOwogICAgdC5kaWFtb25kID0gNzUzOwogICAgdC5oZWFydCA9IDc1MzsKICAgIHQuc3BhZGUgPSA3NTM7CiAgICB0LmFycm93Ym90aCA9IDEwNDI7CiAgICB0LmFycm93bGVmdCA9IDk4NzsKICAgIHQuYXJyb3d1cCA9IDYwMzsKICAgIHQuYXJyb3dyaWdodCA9IDk4NzsKICAgIHQuYXJyb3dkb3duID0gNjAzOwogICAgdC5kZWdyZWUgPSA0MDA7CiAgICB0LnBsdXNtaW51cyA9IDU0OTsKICAgIHQuc2Vjb25kID0gNDExOwogICAgdC5ncmVhdGVyZXF1YWwgPSA1NDk7CiAgICB0Lm11bHRpcGx5ID0gNTQ5OwogICAgdC5wcm9wb3J0aW9uYWwgPSA3MTM7CiAgICB0LnBhcnRpYWxkaWZmID0gNDk0OwogICAgdC5idWxsZXQgPSA0NjA7CiAgICB0LmRpdmlkZSA9IDU0OTsKICAgIHQubm90ZXF1YWwgPSA1NDk7CiAgICB0LmVxdWl2YWxlbmNlID0gNTQ5OwogICAgdC5hcHByb3hlcXVhbCA9IDU0OTsKICAgIHQuZWxsaXBzaXMgPSAxMDAwOwogICAgdC5hcnJvd3ZlcnRleCA9IDYwMzsKICAgIHQuYXJyb3dob3JpemV4ID0gMTAwMDsKICAgIHQuY2FycmlhZ2VyZXR1cm4gPSA2NTg7CiAgICB0LmFsZXBoID0gODIzOwogICAgdC5JZnJha3R1ciA9IDY4NjsKICAgIHQuUmZyYWt0dXIgPSA3OTU7CiAgICB0LndlaWVyc3RyYXNzID0gOTg3OwogICAgdC5jaXJjbGVtdWx0aXBseSA9IDc2ODsKICAgIHQuY2lyY2xlcGx1cyA9IDc2ODsKICAgIHQuZW1wdHlzZXQgPSA4MjM7CiAgICB0LmludGVyc2VjdGlvbiA9IDc2ODsKICAgIHQudW5pb24gPSA3Njg7CiAgICB0LnByb3BlcnN1cGVyc2V0ID0gNzEzOwogICAgdC5yZWZsZXhzdXBlcnNldCA9IDcxMzsKICAgIHQubm90c3Vic2V0ID0gNzEzOwogICAgdC5wcm9wZXJzdWJzZXQgPSA3MTM7CiAgICB0LnJlZmxleHN1YnNldCA9IDcxMzsKICAgIHQuZWxlbWVudCA9IDcxMzsKICAgIHQubm90ZWxlbWVudCA9IDcxMzsKICAgIHQuYW5nbGUgPSA3Njg7CiAgICB0LmdyYWRpZW50ID0gNzEzOwogICAgdC5yZWdpc3RlcnNlcmlmID0gNzkwOwogICAgdC5jb3B5cmlnaHRzZXJpZiA9IDc5MDsKICAgIHQudHJhZGVtYXJrc2VyaWYgPSA4OTA7CiAgICB0LnByb2R1Y3QgPSA4MjM7CiAgICB0LnJhZGljYWwgPSA1NDk7CiAgICB0LmRvdG1hdGggPSAyNTA7CiAgICB0LmxvZ2ljYWxub3QgPSA3MTM7CiAgICB0LmxvZ2ljYWxhbmQgPSA2MDM7CiAgICB0LmxvZ2ljYWxvciA9IDYwMzsKICAgIHQuYXJyb3dkYmxib3RoID0gMTA0MjsKICAgIHQuYXJyb3dkYmxsZWZ0ID0gOTg3OwogICAgdC5hcnJvd2RibHVwID0gNjAzOwogICAgdC5hcnJvd2RibHJpZ2h0ID0gOTg3OwogICAgdC5hcnJvd2RibGRvd24gPSA2MDM7CiAgICB0LmxvemVuZ2UgPSA0OTQ7CiAgICB0LmFuZ2xlbGVmdCA9IDMyOTsKICAgIHQucmVnaXN0ZXJzYW5zID0gNzkwOwogICAgdC5jb3B5cmlnaHRzYW5zID0gNzkwOwogICAgdC50cmFkZW1hcmtzYW5zID0gNzg2OwogICAgdC5zdW1tYXRpb24gPSA3MTM7CiAgICB0LnBhcmVubGVmdHRwID0gMzg0OwogICAgdC5wYXJlbmxlZnRleCA9IDM4NDsKICAgIHQucGFyZW5sZWZ0YnQgPSAzODQ7CiAgICB0LmJyYWNrZXRsZWZ0dHAgPSAzODQ7CiAgICB0LmJyYWNrZXRsZWZ0ZXggPSAzODQ7CiAgICB0LmJyYWNrZXRsZWZ0YnQgPSAzODQ7CiAgICB0LmJyYWNlbGVmdHRwID0gNDk0OwogICAgdC5icmFjZWxlZnRtaWQgPSA0OTQ7CiAgICB0LmJyYWNlbGVmdGJ0ID0gNDk0OwogICAgdC5icmFjZWV4ID0gNDk0OwogICAgdC5hbmdsZXJpZ2h0ID0gMzI5OwogICAgdC5pbnRlZ3JhbCA9IDI3NDsKICAgIHQuaW50ZWdyYWx0cCA9IDY4NjsKICAgIHQuaW50ZWdyYWxleCA9IDY4NjsKICAgIHQuaW50ZWdyYWxidCA9IDY4NjsKICAgIHQucGFyZW5yaWdodHRwID0gMzg0OwogICAgdC5wYXJlbnJpZ2h0ZXggPSAzODQ7CiAgICB0LnBhcmVucmlnaHRidCA9IDM4NDsKICAgIHQuYnJhY2tldHJpZ2h0dHAgPSAzODQ7CiAgICB0LmJyYWNrZXRyaWdodGV4ID0gMzg0OwogICAgdC5icmFja2V0cmlnaHRidCA9IDM4NDsKICAgIHQuYnJhY2VyaWdodHRwID0gNDk0OwogICAgdC5icmFjZXJpZ2h0bWlkID0gNDk0OwogICAgdC5icmFjZXJpZ2h0YnQgPSA0OTQ7CiAgICB0LmFwcGxlID0gNzkwOwogIH0pOwogIHRbIlRpbWVzLVJvbWFuIl0gPSAoMCwgX2NvcmVfdXRpbHMuZ2V0TG9va3VwVGFibGVGYWN0b3J5KShmdW5jdGlvbiAodCkgewogICAgdC5zcGFjZSA9IDI1MDsKICAgIHQuZXhjbGFtID0gMzMzOwogICAgdC5xdW90ZWRibCA9IDQwODsKICAgIHQubnVtYmVyc2lnbiA9IDUwMDsKICAgIHQuZG9sbGFyID0gNTAwOwogICAgdC5wZXJjZW50ID0gODMzOwogICAgdC5hbXBlcnNhbmQgPSA3Nzg7CiAgICB0LnF1b3RlcmlnaHQgPSAzMzM7CiAgICB0LnBhcmVubGVmdCA9IDMzMzsKICAgIHQucGFyZW5yaWdodCA9IDMzMzsKICAgIHQuYXN0ZXJpc2sgPSA1MDA7CiAgICB0LnBsdXMgPSA1NjQ7CiAgICB0LmNvbW1hID0gMjUwOwogICAgdC5oeXBoZW4gPSAzMzM7CiAgICB0LnBlcmlvZCA9IDI1MDsKICAgIHQuc2xhc2ggPSAyNzg7CiAgICB0Lnplcm8gPSA1MDA7CiAgICB0Lm9uZSA9IDUwMDsKICAgIHQudHdvID0gNTAwOwogICAgdC50aHJlZSA9IDUwMDsKICAgIHQuZm91ciA9IDUwMDsKICAgIHQuZml2ZSA9IDUwMDsKICAgIHQuc2l4ID0gNTAwOwogICAgdC5zZXZlbiA9IDUwMDsKICAgIHQuZWlnaHQgPSA1MDA7CiAgICB0Lm5pbmUgPSA1MDA7CiAgICB0LmNvbG9uID0gMjc4OwogICAgdC5zZW1pY29sb24gPSAyNzg7CiAgICB0Lmxlc3MgPSA1NjQ7CiAgICB0LmVxdWFsID0gNTY0OwogICAgdC5ncmVhdGVyID0gNTY0OwogICAgdC5xdWVzdGlvbiA9IDQ0NDsKICAgIHQuYXQgPSA5MjE7CiAgICB0LkEgPSA3MjI7CiAgICB0LkIgPSA2Njc7CiAgICB0LkMgPSA2Njc7CiAgICB0LkQgPSA3MjI7CiAgICB0LkUgPSA2MTE7CiAgICB0LkYgPSA1NTY7CiAgICB0LkcgPSA3MjI7CiAgICB0LkggPSA3MjI7CiAgICB0LkkgPSAzMzM7CiAgICB0LkogPSAzODk7CiAgICB0LksgPSA3MjI7CiAgICB0LkwgPSA2MTE7CiAgICB0Lk0gPSA4ODk7CiAgICB0Lk4gPSA3MjI7CiAgICB0Lk8gPSA3MjI7CiAgICB0LlAgPSA1NTY7CiAgICB0LlEgPSA3MjI7CiAgICB0LlIgPSA2Njc7CiAgICB0LlMgPSA1NTY7CiAgICB0LlQgPSA2MTE7CiAgICB0LlUgPSA3MjI7CiAgICB0LlYgPSA3MjI7CiAgICB0LlcgPSA5NDQ7CiAgICB0LlggPSA3MjI7CiAgICB0LlkgPSA3MjI7CiAgICB0LlogPSA2MTE7CiAgICB0LmJyYWNrZXRsZWZ0ID0gMzMzOwogICAgdC5iYWNrc2xhc2ggPSAyNzg7CiAgICB0LmJyYWNrZXRyaWdodCA9IDMzMzsKICAgIHQuYXNjaWljaXJjdW0gPSA0Njk7CiAgICB0LnVuZGVyc2NvcmUgPSA1MDA7CiAgICB0LnF1b3RlbGVmdCA9IDMzMzsKICAgIHQuYSA9IDQ0NDsKICAgIHQuYiA9IDUwMDsKICAgIHQuYyA9IDQ0NDsKICAgIHQuZCA9IDUwMDsKICAgIHQuZSA9IDQ0NDsKICAgIHQuZiA9IDMzMzsKICAgIHQuZyA9IDUwMDsKICAgIHQuaCA9IDUwMDsKICAgIHQuaSA9IDI3ODsKICAgIHQuaiA9IDI3ODsKICAgIHQuayA9IDUwMDsKICAgIHQubCA9IDI3ODsKICAgIHQubSA9IDc3ODsKICAgIHQubiA9IDUwMDsKICAgIHQubyA9IDUwMDsKICAgIHQucCA9IDUwMDsKICAgIHQucSA9IDUwMDsKICAgIHQuciA9IDMzMzsKICAgIHQucyA9IDM4OTsKICAgIHQudCA9IDI3ODsKICAgIHQudSA9IDUwMDsKICAgIHQudiA9IDUwMDsKICAgIHQudyA9IDcyMjsKICAgIHQueCA9IDUwMDsKICAgIHQueSA9IDUwMDsKICAgIHQueiA9IDQ0NDsKICAgIHQuYnJhY2VsZWZ0ID0gNDgwOwogICAgdC5iYXIgPSAyMDA7CiAgICB0LmJyYWNlcmlnaHQgPSA0ODA7CiAgICB0LmFzY2lpdGlsZGUgPSA1NDE7CiAgICB0LmV4Y2xhbWRvd24gPSAzMzM7CiAgICB0LmNlbnQgPSA1MDA7CiAgICB0LnN0ZXJsaW5nID0gNTAwOwogICAgdC5mcmFjdGlvbiA9IDE2NzsKICAgIHQueWVuID0gNTAwOwogICAgdC5mbG9yaW4gPSA1MDA7CiAgICB0LnNlY3Rpb24gPSA1MDA7CiAgICB0LmN1cnJlbmN5ID0gNTAwOwogICAgdC5xdW90ZXNpbmdsZSA9IDE4MDsKICAgIHQucXVvdGVkYmxsZWZ0ID0gNDQ0OwogICAgdC5ndWlsbGVtb3RsZWZ0ID0gNTAwOwogICAgdC5ndWlsc2luZ2xsZWZ0ID0gMzMzOwogICAgdC5ndWlsc2luZ2xyaWdodCA9IDMzMzsKICAgIHQuZmkgPSA1NTY7CiAgICB0LmZsID0gNTU2OwogICAgdC5lbmRhc2ggPSA1MDA7CiAgICB0LmRhZ2dlciA9IDUwMDsKICAgIHQuZGFnZ2VyZGJsID0gNTAwOwogICAgdC5wZXJpb2RjZW50ZXJlZCA9IDI1MDsKICAgIHQucGFyYWdyYXBoID0gNDUzOwogICAgdC5idWxsZXQgPSAzNTA7CiAgICB0LnF1b3Rlc2luZ2xiYXNlID0gMzMzOwogICAgdC5xdW90ZWRibGJhc2UgPSA0NDQ7CiAgICB0LnF1b3RlZGJscmlnaHQgPSA0NDQ7CiAgICB0Lmd1aWxsZW1vdHJpZ2h0ID0gNTAwOwogICAgdC5lbGxpcHNpcyA9IDEwMDA7CiAgICB0LnBlcnRob3VzYW5kID0gMTAwMDsKICAgIHQucXVlc3Rpb25kb3duID0gNDQ0OwogICAgdC5ncmF2ZSA9IDMzMzsKICAgIHQuYWN1dGUgPSAzMzM7CiAgICB0LmNpcmN1bWZsZXggPSAzMzM7CiAgICB0LnRpbGRlID0gMzMzOwogICAgdC5tYWNyb24gPSAzMzM7CiAgICB0LmJyZXZlID0gMzMzOwogICAgdC5kb3RhY2NlbnQgPSAzMzM7CiAgICB0LmRpZXJlc2lzID0gMzMzOwogICAgdC5yaW5nID0gMzMzOwogICAgdC5jZWRpbGxhID0gMzMzOwogICAgdC5odW5nYXJ1bWxhdXQgPSAzMzM7CiAgICB0Lm9nb25layA9IDMzMzsKICAgIHQuY2Fyb24gPSAzMzM7CiAgICB0LmVtZGFzaCA9IDEwMDA7CiAgICB0LkFFID0gODg5OwogICAgdC5vcmRmZW1pbmluZSA9IDI3NjsKICAgIHQuTHNsYXNoID0gNjExOwogICAgdC5Pc2xhc2ggPSA3MjI7CiAgICB0Lk9FID0gODg5OwogICAgdC5vcmRtYXNjdWxpbmUgPSAzMTA7CiAgICB0LmFlID0gNjY3OwogICAgdC5kb3RsZXNzaSA9IDI3ODsKICAgIHQubHNsYXNoID0gMjc4OwogICAgdC5vc2xhc2ggPSA1MDA7CiAgICB0Lm9lID0gNzIyOwogICAgdC5nZXJtYW5kYmxzID0gNTAwOwogICAgdC5JZGllcmVzaXMgPSAzMzM7CiAgICB0LmVhY3V0ZSA9IDQ0NDsKICAgIHQuYWJyZXZlID0gNDQ0OwogICAgdC51aHVuZ2FydW1sYXV0ID0gNTAwOwogICAgdC5lY2Fyb24gPSA0NDQ7CiAgICB0LllkaWVyZXNpcyA9IDcyMjsKICAgIHQuZGl2aWRlID0gNTY0OwogICAgdC5ZYWN1dGUgPSA3MjI7CiAgICB0LkFjaXJjdW1mbGV4ID0gNzIyOwogICAgdC5hYWN1dGUgPSA0NDQ7CiAgICB0LlVjaXJjdW1mbGV4ID0gNzIyOwogICAgdC55YWN1dGUgPSA1MDA7CiAgICB0LnNjb21tYWFjY2VudCA9IDM4OTsKICAgIHQuZWNpcmN1bWZsZXggPSA0NDQ7CiAgICB0LlVyaW5nID0gNzIyOwogICAgdC5VZGllcmVzaXMgPSA3MjI7CiAgICB0LmFvZ29uZWsgPSA0NDQ7CiAgICB0LlVhY3V0ZSA9IDcyMjsKICAgIHQudW9nb25layA9IDUwMDsKICAgIHQuRWRpZXJlc2lzID0gNjExOwogICAgdC5EY3JvYXQgPSA3MjI7CiAgICB0LmNvbW1hYWNjZW50ID0gMjUwOwogICAgdC5jb3B5cmlnaHQgPSA3NjA7CiAgICB0LkVtYWNyb24gPSA2MTE7CiAgICB0LmNjYXJvbiA9IDQ0NDsKICAgIHQuYXJpbmcgPSA0NDQ7CiAgICB0Lk5jb21tYWFjY2VudCA9IDcyMjsKICAgIHQubGFjdXRlID0gMjc4OwogICAgdC5hZ3JhdmUgPSA0NDQ7CiAgICB0LlRjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQ2FjdXRlID0gNjY3OwogICAgdC5hdGlsZGUgPSA0NDQ7CiAgICB0LkVkb3RhY2NlbnQgPSA2MTE7CiAgICB0LnNjYXJvbiA9IDM4OTsKICAgIHQuc2NlZGlsbGEgPSAzODk7CiAgICB0LmlhY3V0ZSA9IDI3ODsKICAgIHQubG96ZW5nZSA9IDQ3MTsKICAgIHQuUmNhcm9uID0gNjY3OwogICAgdC5HY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LnVjaXJjdW1mbGV4ID0gNTAwOwogICAgdC5hY2lyY3VtZmxleCA9IDQ0NDsKICAgIHQuQW1hY3JvbiA9IDcyMjsKICAgIHQucmNhcm9uID0gMzMzOwogICAgdC5jY2VkaWxsYSA9IDQ0NDsKICAgIHQuWmRvdGFjY2VudCA9IDYxMTsKICAgIHQuVGhvcm4gPSA1NTY7CiAgICB0Lk9tYWNyb24gPSA3MjI7CiAgICB0LlJhY3V0ZSA9IDY2NzsKICAgIHQuU2FjdXRlID0gNTU2OwogICAgdC5kY2Fyb24gPSA1ODg7CiAgICB0LlVtYWNyb24gPSA3MjI7CiAgICB0LnVyaW5nID0gNTAwOwogICAgdC50aHJlZXN1cGVyaW9yID0gMzAwOwogICAgdC5PZ3JhdmUgPSA3MjI7CiAgICB0LkFncmF2ZSA9IDcyMjsKICAgIHQuQWJyZXZlID0gNzIyOwogICAgdC5tdWx0aXBseSA9IDU2NDsKICAgIHQudWFjdXRlID0gNTAwOwogICAgdC5UY2Fyb24gPSA2MTE7CiAgICB0LnBhcnRpYWxkaWZmID0gNDc2OwogICAgdC55ZGllcmVzaXMgPSA1MDA7CiAgICB0Lk5hY3V0ZSA9IDcyMjsKICAgIHQuaWNpcmN1bWZsZXggPSAyNzg7CiAgICB0LkVjaXJjdW1mbGV4ID0gNjExOwogICAgdC5hZGllcmVzaXMgPSA0NDQ7CiAgICB0LmVkaWVyZXNpcyA9IDQ0NDsKICAgIHQuY2FjdXRlID0gNDQ0OwogICAgdC5uYWN1dGUgPSA1MDA7CiAgICB0LnVtYWNyb24gPSA1MDA7CiAgICB0Lk5jYXJvbiA9IDcyMjsKICAgIHQuSWFjdXRlID0gMzMzOwogICAgdC5wbHVzbWludXMgPSA1NjQ7CiAgICB0LmJyb2tlbmJhciA9IDIwMDsKICAgIHQucmVnaXN0ZXJlZCA9IDc2MDsKICAgIHQuR2JyZXZlID0gNzIyOwogICAgdC5JZG90YWNjZW50ID0gMzMzOwogICAgdC5zdW1tYXRpb24gPSA2MDA7CiAgICB0LkVncmF2ZSA9IDYxMTsKICAgIHQucmFjdXRlID0gMzMzOwogICAgdC5vbWFjcm9uID0gNTAwOwogICAgdC5aYWN1dGUgPSA2MTE7CiAgICB0LlpjYXJvbiA9IDYxMTsKICAgIHQuZ3JlYXRlcmVxdWFsID0gNTQ5OwogICAgdC5FdGggPSA3MjI7CiAgICB0LkNjZWRpbGxhID0gNjY3OwogICAgdC5sY29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LnRjYXJvbiA9IDMyNjsKICAgIHQuZW9nb25layA9IDQ0NDsKICAgIHQuVW9nb25layA9IDcyMjsKICAgIHQuQWFjdXRlID0gNzIyOwogICAgdC5BZGllcmVzaXMgPSA3MjI7CiAgICB0LmVncmF2ZSA9IDQ0NDsKICAgIHQuemFjdXRlID0gNDQ0OwogICAgdC5pb2dvbmVrID0gMjc4OwogICAgdC5PYWN1dGUgPSA3MjI7CiAgICB0Lm9hY3V0ZSA9IDUwMDsKICAgIHQuYW1hY3JvbiA9IDQ0NDsKICAgIHQuc2FjdXRlID0gMzg5OwogICAgdC5pZGllcmVzaXMgPSAyNzg7CiAgICB0Lk9jaXJjdW1mbGV4ID0gNzIyOwogICAgdC5VZ3JhdmUgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC50aG9ybiA9IDUwMDsKICAgIHQudHdvc3VwZXJpb3IgPSAzMDA7CiAgICB0Lk9kaWVyZXNpcyA9IDcyMjsKICAgIHQubXUgPSA1MDA7CiAgICB0LmlncmF2ZSA9IDI3ODsKICAgIHQub2h1bmdhcnVtbGF1dCA9IDUwMDsKICAgIHQuRW9nb25layA9IDYxMTsKICAgIHQuZGNyb2F0ID0gNTAwOwogICAgdC50aHJlZXF1YXJ0ZXJzID0gNzUwOwogICAgdC5TY2VkaWxsYSA9IDU1NjsKICAgIHQubGNhcm9uID0gMzQ0OwogICAgdC5LY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LkxhY3V0ZSA9IDYxMTsKICAgIHQudHJhZGVtYXJrID0gOTgwOwogICAgdC5lZG90YWNjZW50ID0gNDQ0OwogICAgdC5JZ3JhdmUgPSAzMzM7CiAgICB0LkltYWNyb24gPSAzMzM7CiAgICB0LkxjYXJvbiA9IDYxMTsKICAgIHQub25laGFsZiA9IDc1MDsKICAgIHQubGVzc2VxdWFsID0gNTQ5OwogICAgdC5vY2lyY3VtZmxleCA9IDUwMDsKICAgIHQubnRpbGRlID0gNTAwOwogICAgdC5VaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5FYWN1dGUgPSA2MTE7CiAgICB0LmVtYWNyb24gPSA0NDQ7CiAgICB0LmdicmV2ZSA9IDUwMDsKICAgIHQub25lcXVhcnRlciA9IDc1MDsKICAgIHQuU2Nhcm9uID0gNTU2OwogICAgdC5TY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0Lk9odW5nYXJ1bWxhdXQgPSA3MjI7CiAgICB0LmRlZ3JlZSA9IDQwMDsKICAgIHQub2dyYXZlID0gNTAwOwogICAgdC5DY2Fyb24gPSA2Njc7CiAgICB0LnVncmF2ZSA9IDUwMDsKICAgIHQucmFkaWNhbCA9IDQ1MzsKICAgIHQuRGNhcm9uID0gNzIyOwogICAgdC5yY29tbWFhY2NlbnQgPSAzMzM7CiAgICB0Lk50aWxkZSA9IDcyMjsKICAgIHQub3RpbGRlID0gNTAwOwogICAgdC5SY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0Lkxjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQXRpbGRlID0gNzIyOwogICAgdC5Bb2dvbmVrID0gNzIyOwogICAgdC5BcmluZyA9IDcyMjsKICAgIHQuT3RpbGRlID0gNzIyOwogICAgdC56ZG90YWNjZW50ID0gNDQ0OwogICAgdC5FY2Fyb24gPSA2MTE7CiAgICB0LklvZ29uZWsgPSAzMzM7CiAgICB0Lmtjb21tYWFjY2VudCA9IDUwMDsKICAgIHQubWludXMgPSA1NjQ7CiAgICB0LkljaXJjdW1mbGV4ID0gMzMzOwogICAgdC5uY2Fyb24gPSA1MDA7CiAgICB0LnRjb21tYWFjY2VudCA9IDI3ODsKICAgIHQubG9naWNhbG5vdCA9IDU2NDsKICAgIHQub2RpZXJlc2lzID0gNTAwOwogICAgdC51ZGllcmVzaXMgPSA1MDA7CiAgICB0Lm5vdGVxdWFsID0gNTQ5OwogICAgdC5nY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0LmV0aCA9IDUwMDsKICAgIHQuemNhcm9uID0gNDQ0OwogICAgdC5uY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0Lm9uZXN1cGVyaW9yID0gMzAwOwogICAgdC5pbWFjcm9uID0gMjc4OwogICAgdC5FdXJvID0gNTAwOwogIH0pOwogIHRbIlRpbWVzLUJvbGQiXSA9ICgwLCBfY29yZV91dGlscy5nZXRMb29rdXBUYWJsZUZhY3RvcnkpKGZ1bmN0aW9uICh0KSB7CiAgICB0LnNwYWNlID0gMjUwOwogICAgdC5leGNsYW0gPSAzMzM7CiAgICB0LnF1b3RlZGJsID0gNTU1OwogICAgdC5udW1iZXJzaWduID0gNTAwOwogICAgdC5kb2xsYXIgPSA1MDA7CiAgICB0LnBlcmNlbnQgPSAxMDAwOwogICAgdC5hbXBlcnNhbmQgPSA4MzM7CiAgICB0LnF1b3RlcmlnaHQgPSAzMzM7CiAgICB0LnBhcmVubGVmdCA9IDMzMzsKICAgIHQucGFyZW5yaWdodCA9IDMzMzsKICAgIHQuYXN0ZXJpc2sgPSA1MDA7CiAgICB0LnBsdXMgPSA1NzA7CiAgICB0LmNvbW1hID0gMjUwOwogICAgdC5oeXBoZW4gPSAzMzM7CiAgICB0LnBlcmlvZCA9IDI1MDsKICAgIHQuc2xhc2ggPSAyNzg7CiAgICB0Lnplcm8gPSA1MDA7CiAgICB0Lm9uZSA9IDUwMDsKICAgIHQudHdvID0gNTAwOwogICAgdC50aHJlZSA9IDUwMDsKICAgIHQuZm91ciA9IDUwMDsKICAgIHQuZml2ZSA9IDUwMDsKICAgIHQuc2l4ID0gNTAwOwogICAgdC5zZXZlbiA9IDUwMDsKICAgIHQuZWlnaHQgPSA1MDA7CiAgICB0Lm5pbmUgPSA1MDA7CiAgICB0LmNvbG9uID0gMzMzOwogICAgdC5zZW1pY29sb24gPSAzMzM7CiAgICB0Lmxlc3MgPSA1NzA7CiAgICB0LmVxdWFsID0gNTcwOwogICAgdC5ncmVhdGVyID0gNTcwOwogICAgdC5xdWVzdGlvbiA9IDUwMDsKICAgIHQuYXQgPSA5MzA7CiAgICB0LkEgPSA3MjI7CiAgICB0LkIgPSA2Njc7CiAgICB0LkMgPSA3MjI7CiAgICB0LkQgPSA3MjI7CiAgICB0LkUgPSA2Njc7CiAgICB0LkYgPSA2MTE7CiAgICB0LkcgPSA3Nzg7CiAgICB0LkggPSA3Nzg7CiAgICB0LkkgPSAzODk7CiAgICB0LkogPSA1MDA7CiAgICB0LksgPSA3Nzg7CiAgICB0LkwgPSA2Njc7CiAgICB0Lk0gPSA5NDQ7CiAgICB0Lk4gPSA3MjI7CiAgICB0Lk8gPSA3Nzg7CiAgICB0LlAgPSA2MTE7CiAgICB0LlEgPSA3Nzg7CiAgICB0LlIgPSA3MjI7CiAgICB0LlMgPSA1NTY7CiAgICB0LlQgPSA2Njc7CiAgICB0LlUgPSA3MjI7CiAgICB0LlYgPSA3MjI7CiAgICB0LlcgPSAxMDAwOwogICAgdC5YID0gNzIyOwogICAgdC5ZID0gNzIyOwogICAgdC5aID0gNjY3OwogICAgdC5icmFja2V0bGVmdCA9IDMzMzsKICAgIHQuYmFja3NsYXNoID0gMjc4OwogICAgdC5icmFja2V0cmlnaHQgPSAzMzM7CiAgICB0LmFzY2lpY2lyY3VtID0gNTgxOwogICAgdC51bmRlcnNjb3JlID0gNTAwOwogICAgdC5xdW90ZWxlZnQgPSAzMzM7CiAgICB0LmEgPSA1MDA7CiAgICB0LmIgPSA1NTY7CiAgICB0LmMgPSA0NDQ7CiAgICB0LmQgPSA1NTY7CiAgICB0LmUgPSA0NDQ7CiAgICB0LmYgPSAzMzM7CiAgICB0LmcgPSA1MDA7CiAgICB0LmggPSA1NTY7CiAgICB0LmkgPSAyNzg7CiAgICB0LmogPSAzMzM7CiAgICB0LmsgPSA1NTY7CiAgICB0LmwgPSAyNzg7CiAgICB0Lm0gPSA4MzM7CiAgICB0Lm4gPSA1NTY7CiAgICB0Lm8gPSA1MDA7CiAgICB0LnAgPSA1NTY7CiAgICB0LnEgPSA1NTY7CiAgICB0LnIgPSA0NDQ7CiAgICB0LnMgPSAzODk7CiAgICB0LnQgPSAzMzM7CiAgICB0LnUgPSA1NTY7CiAgICB0LnYgPSA1MDA7CiAgICB0LncgPSA3MjI7CiAgICB0LnggPSA1MDA7CiAgICB0LnkgPSA1MDA7CiAgICB0LnogPSA0NDQ7CiAgICB0LmJyYWNlbGVmdCA9IDM5NDsKICAgIHQuYmFyID0gMjIwOwogICAgdC5icmFjZXJpZ2h0ID0gMzk0OwogICAgdC5hc2NpaXRpbGRlID0gNTIwOwogICAgdC5leGNsYW1kb3duID0gMzMzOwogICAgdC5jZW50ID0gNTAwOwogICAgdC5zdGVybGluZyA9IDUwMDsKICAgIHQuZnJhY3Rpb24gPSAxNjc7CiAgICB0LnllbiA9IDUwMDsKICAgIHQuZmxvcmluID0gNTAwOwogICAgdC5zZWN0aW9uID0gNTAwOwogICAgdC5jdXJyZW5jeSA9IDUwMDsKICAgIHQucXVvdGVzaW5nbGUgPSAyNzg7CiAgICB0LnF1b3RlZGJsbGVmdCA9IDUwMDsKICAgIHQuZ3VpbGxlbW90bGVmdCA9IDUwMDsKICAgIHQuZ3VpbHNpbmdsbGVmdCA9IDMzMzsKICAgIHQuZ3VpbHNpbmdscmlnaHQgPSAzMzM7CiAgICB0LmZpID0gNTU2OwogICAgdC5mbCA9IDU1NjsKICAgIHQuZW5kYXNoID0gNTAwOwogICAgdC5kYWdnZXIgPSA1MDA7CiAgICB0LmRhZ2dlcmRibCA9IDUwMDsKICAgIHQucGVyaW9kY2VudGVyZWQgPSAyNTA7CiAgICB0LnBhcmFncmFwaCA9IDU0MDsKICAgIHQuYnVsbGV0ID0gMzUwOwogICAgdC5xdW90ZXNpbmdsYmFzZSA9IDMzMzsKICAgIHQucXVvdGVkYmxiYXNlID0gNTAwOwogICAgdC5xdW90ZWRibHJpZ2h0ID0gNTAwOwogICAgdC5ndWlsbGVtb3RyaWdodCA9IDUwMDsKICAgIHQuZWxsaXBzaXMgPSAxMDAwOwogICAgdC5wZXJ0aG91c2FuZCA9IDEwMDA7CiAgICB0LnF1ZXN0aW9uZG93biA9IDUwMDsKICAgIHQuZ3JhdmUgPSAzMzM7CiAgICB0LmFjdXRlID0gMzMzOwogICAgdC5jaXJjdW1mbGV4ID0gMzMzOwogICAgdC50aWxkZSA9IDMzMzsKICAgIHQubWFjcm9uID0gMzMzOwogICAgdC5icmV2ZSA9IDMzMzsKICAgIHQuZG90YWNjZW50ID0gMzMzOwogICAgdC5kaWVyZXNpcyA9IDMzMzsKICAgIHQucmluZyA9IDMzMzsKICAgIHQuY2VkaWxsYSA9IDMzMzsKICAgIHQuaHVuZ2FydW1sYXV0ID0gMzMzOwogICAgdC5vZ29uZWsgPSAzMzM7CiAgICB0LmNhcm9uID0gMzMzOwogICAgdC5lbWRhc2ggPSAxMDAwOwogICAgdC5BRSA9IDEwMDA7CiAgICB0Lm9yZGZlbWluaW5lID0gMzAwOwogICAgdC5Mc2xhc2ggPSA2Njc7CiAgICB0Lk9zbGFzaCA9IDc3ODsKICAgIHQuT0UgPSAxMDAwOwogICAgdC5vcmRtYXNjdWxpbmUgPSAzMzA7CiAgICB0LmFlID0gNzIyOwogICAgdC5kb3RsZXNzaSA9IDI3ODsKICAgIHQubHNsYXNoID0gMjc4OwogICAgdC5vc2xhc2ggPSA1MDA7CiAgICB0Lm9lID0gNzIyOwogICAgdC5nZXJtYW5kYmxzID0gNTU2OwogICAgdC5JZGllcmVzaXMgPSAzODk7CiAgICB0LmVhY3V0ZSA9IDQ0NDsKICAgIHQuYWJyZXZlID0gNTAwOwogICAgdC51aHVuZ2FydW1sYXV0ID0gNTU2OwogICAgdC5lY2Fyb24gPSA0NDQ7CiAgICB0LllkaWVyZXNpcyA9IDcyMjsKICAgIHQuZGl2aWRlID0gNTcwOwogICAgdC5ZYWN1dGUgPSA3MjI7CiAgICB0LkFjaXJjdW1mbGV4ID0gNzIyOwogICAgdC5hYWN1dGUgPSA1MDA7CiAgICB0LlVjaXJjdW1mbGV4ID0gNzIyOwogICAgdC55YWN1dGUgPSA1MDA7CiAgICB0LnNjb21tYWFjY2VudCA9IDM4OTsKICAgIHQuZWNpcmN1bWZsZXggPSA0NDQ7CiAgICB0LlVyaW5nID0gNzIyOwogICAgdC5VZGllcmVzaXMgPSA3MjI7CiAgICB0LmFvZ29uZWsgPSA1MDA7CiAgICB0LlVhY3V0ZSA9IDcyMjsKICAgIHQudW9nb25layA9IDU1NjsKICAgIHQuRWRpZXJlc2lzID0gNjY3OwogICAgdC5EY3JvYXQgPSA3MjI7CiAgICB0LmNvbW1hYWNjZW50ID0gMjUwOwogICAgdC5jb3B5cmlnaHQgPSA3NDc7CiAgICB0LkVtYWNyb24gPSA2Njc7CiAgICB0LmNjYXJvbiA9IDQ0NDsKICAgIHQuYXJpbmcgPSA1MDA7CiAgICB0Lk5jb21tYWFjY2VudCA9IDcyMjsKICAgIHQubGFjdXRlID0gMjc4OwogICAgdC5hZ3JhdmUgPSA1MDA7CiAgICB0LlRjb21tYWFjY2VudCA9IDY2NzsKICAgIHQuQ2FjdXRlID0gNzIyOwogICAgdC5hdGlsZGUgPSA1MDA7CiAgICB0LkVkb3RhY2NlbnQgPSA2Njc7CiAgICB0LnNjYXJvbiA9IDM4OTsKICAgIHQuc2NlZGlsbGEgPSAzODk7CiAgICB0LmlhY3V0ZSA9IDI3ODsKICAgIHQubG96ZW5nZSA9IDQ5NDsKICAgIHQuUmNhcm9uID0gNzIyOwogICAgdC5HY29tbWFhY2NlbnQgPSA3Nzg7CiAgICB0LnVjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5hY2lyY3VtZmxleCA9IDUwMDsKICAgIHQuQW1hY3JvbiA9IDcyMjsKICAgIHQucmNhcm9uID0gNDQ0OwogICAgdC5jY2VkaWxsYSA9IDQ0NDsKICAgIHQuWmRvdGFjY2VudCA9IDY2NzsKICAgIHQuVGhvcm4gPSA2MTE7CiAgICB0Lk9tYWNyb24gPSA3Nzg7CiAgICB0LlJhY3V0ZSA9IDcyMjsKICAgIHQuU2FjdXRlID0gNTU2OwogICAgdC5kY2Fyb24gPSA2NzI7CiAgICB0LlVtYWNyb24gPSA3MjI7CiAgICB0LnVyaW5nID0gNTU2OwogICAgdC50aHJlZXN1cGVyaW9yID0gMzAwOwogICAgdC5PZ3JhdmUgPSA3Nzg7CiAgICB0LkFncmF2ZSA9IDcyMjsKICAgIHQuQWJyZXZlID0gNzIyOwogICAgdC5tdWx0aXBseSA9IDU3MDsKICAgIHQudWFjdXRlID0gNTU2OwogICAgdC5UY2Fyb24gPSA2Njc7CiAgICB0LnBhcnRpYWxkaWZmID0gNDk0OwogICAgdC55ZGllcmVzaXMgPSA1MDA7CiAgICB0Lk5hY3V0ZSA9IDcyMjsKICAgIHQuaWNpcmN1bWZsZXggPSAyNzg7CiAgICB0LkVjaXJjdW1mbGV4ID0gNjY3OwogICAgdC5hZGllcmVzaXMgPSA1MDA7CiAgICB0LmVkaWVyZXNpcyA9IDQ0NDsKICAgIHQuY2FjdXRlID0gNDQ0OwogICAgdC5uYWN1dGUgPSA1NTY7CiAgICB0LnVtYWNyb24gPSA1NTY7CiAgICB0Lk5jYXJvbiA9IDcyMjsKICAgIHQuSWFjdXRlID0gMzg5OwogICAgdC5wbHVzbWludXMgPSA1NzA7CiAgICB0LmJyb2tlbmJhciA9IDIyMDsKICAgIHQucmVnaXN0ZXJlZCA9IDc0NzsKICAgIHQuR2JyZXZlID0gNzc4OwogICAgdC5JZG90YWNjZW50ID0gMzg5OwogICAgdC5zdW1tYXRpb24gPSA2MDA7CiAgICB0LkVncmF2ZSA9IDY2NzsKICAgIHQucmFjdXRlID0gNDQ0OwogICAgdC5vbWFjcm9uID0gNTAwOwogICAgdC5aYWN1dGUgPSA2Njc7CiAgICB0LlpjYXJvbiA9IDY2NzsKICAgIHQuZ3JlYXRlcmVxdWFsID0gNTQ5OwogICAgdC5FdGggPSA3MjI7CiAgICB0LkNjZWRpbGxhID0gNzIyOwogICAgdC5sY29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LnRjYXJvbiA9IDQxNjsKICAgIHQuZW9nb25layA9IDQ0NDsKICAgIHQuVW9nb25layA9IDcyMjsKICAgIHQuQWFjdXRlID0gNzIyOwogICAgdC5BZGllcmVzaXMgPSA3MjI7CiAgICB0LmVncmF2ZSA9IDQ0NDsKICAgIHQuemFjdXRlID0gNDQ0OwogICAgdC5pb2dvbmVrID0gMjc4OwogICAgdC5PYWN1dGUgPSA3Nzg7CiAgICB0Lm9hY3V0ZSA9IDUwMDsKICAgIHQuYW1hY3JvbiA9IDUwMDsKICAgIHQuc2FjdXRlID0gMzg5OwogICAgdC5pZGllcmVzaXMgPSAyNzg7CiAgICB0Lk9jaXJjdW1mbGV4ID0gNzc4OwogICAgdC5VZ3JhdmUgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC50aG9ybiA9IDU1NjsKICAgIHQudHdvc3VwZXJpb3IgPSAzMDA7CiAgICB0Lk9kaWVyZXNpcyA9IDc3ODsKICAgIHQubXUgPSA1NTY7CiAgICB0LmlncmF2ZSA9IDI3ODsKICAgIHQub2h1bmdhcnVtbGF1dCA9IDUwMDsKICAgIHQuRW9nb25layA9IDY2NzsKICAgIHQuZGNyb2F0ID0gNTU2OwogICAgdC50aHJlZXF1YXJ0ZXJzID0gNzUwOwogICAgdC5TY2VkaWxsYSA9IDU1NjsKICAgIHQubGNhcm9uID0gMzk0OwogICAgdC5LY29tbWFhY2NlbnQgPSA3Nzg7CiAgICB0LkxhY3V0ZSA9IDY2NzsKICAgIHQudHJhZGVtYXJrID0gMTAwMDsKICAgIHQuZWRvdGFjY2VudCA9IDQ0NDsKICAgIHQuSWdyYXZlID0gMzg5OwogICAgdC5JbWFjcm9uID0gMzg5OwogICAgdC5MY2Fyb24gPSA2Njc7CiAgICB0Lm9uZWhhbGYgPSA3NTA7CiAgICB0Lmxlc3NlcXVhbCA9IDU0OTsKICAgIHQub2NpcmN1bWZsZXggPSA1MDA7CiAgICB0Lm50aWxkZSA9IDU1NjsKICAgIHQuVWh1bmdhcnVtbGF1dCA9IDcyMjsKICAgIHQuRWFjdXRlID0gNjY3OwogICAgdC5lbWFjcm9uID0gNDQ0OwogICAgdC5nYnJldmUgPSA1MDA7CiAgICB0Lm9uZXF1YXJ0ZXIgPSA3NTA7CiAgICB0LlNjYXJvbiA9IDU1NjsKICAgIHQuU2NvbW1hYWNjZW50ID0gNTU2OwogICAgdC5PaHVuZ2FydW1sYXV0ID0gNzc4OwogICAgdC5kZWdyZWUgPSA0MDA7CiAgICB0Lm9ncmF2ZSA9IDUwMDsKICAgIHQuQ2Nhcm9uID0gNzIyOwogICAgdC51Z3JhdmUgPSA1NTY7CiAgICB0LnJhZGljYWwgPSA1NDk7CiAgICB0LkRjYXJvbiA9IDcyMjsKICAgIHQucmNvbW1hYWNjZW50ID0gNDQ0OwogICAgdC5OdGlsZGUgPSA3MjI7CiAgICB0Lm90aWxkZSA9IDUwMDsKICAgIHQuUmNvbW1hYWNjZW50ID0gNzIyOwogICAgdC5MY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0LkF0aWxkZSA9IDcyMjsKICAgIHQuQW9nb25layA9IDcyMjsKICAgIHQuQXJpbmcgPSA3MjI7CiAgICB0Lk90aWxkZSA9IDc3ODsKICAgIHQuemRvdGFjY2VudCA9IDQ0NDsKICAgIHQuRWNhcm9uID0gNjY3OwogICAgdC5Jb2dvbmVrID0gMzg5OwogICAgdC5rY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0Lm1pbnVzID0gNTcwOwogICAgdC5JY2lyY3VtZmxleCA9IDM4OTsKICAgIHQubmNhcm9uID0gNTU2OwogICAgdC50Y29tbWFhY2NlbnQgPSAzMzM7CiAgICB0LmxvZ2ljYWxub3QgPSA1NzA7CiAgICB0Lm9kaWVyZXNpcyA9IDUwMDsKICAgIHQudWRpZXJlc2lzID0gNTU2OwogICAgdC5ub3RlcXVhbCA9IDU0OTsKICAgIHQuZ2NvbW1hYWNjZW50ID0gNTAwOwogICAgdC5ldGggPSA1MDA7CiAgICB0LnpjYXJvbiA9IDQ0NDsKICAgIHQubmNvbW1hYWNjZW50ID0gNTU2OwogICAgdC5vbmVzdXBlcmlvciA9IDMwMDsKICAgIHQuaW1hY3JvbiA9IDI3ODsKICAgIHQuRXVybyA9IDUwMDsKICB9KTsKICB0WyJUaW1lcy1Cb2xkSXRhbGljIl0gPSAoMCwgX2NvcmVfdXRpbHMuZ2V0TG9va3VwVGFibGVGYWN0b3J5KShmdW5jdGlvbiAodCkgewogICAgdC5zcGFjZSA9IDI1MDsKICAgIHQuZXhjbGFtID0gMzg5OwogICAgdC5xdW90ZWRibCA9IDU1NTsKICAgIHQubnVtYmVyc2lnbiA9IDUwMDsKICAgIHQuZG9sbGFyID0gNTAwOwogICAgdC5wZXJjZW50ID0gODMzOwogICAgdC5hbXBlcnNhbmQgPSA3Nzg7CiAgICB0LnF1b3RlcmlnaHQgPSAzMzM7CiAgICB0LnBhcmVubGVmdCA9IDMzMzsKICAgIHQucGFyZW5yaWdodCA9IDMzMzsKICAgIHQuYXN0ZXJpc2sgPSA1MDA7CiAgICB0LnBsdXMgPSA1NzA7CiAgICB0LmNvbW1hID0gMjUwOwogICAgdC5oeXBoZW4gPSAzMzM7CiAgICB0LnBlcmlvZCA9IDI1MDsKICAgIHQuc2xhc2ggPSAyNzg7CiAgICB0Lnplcm8gPSA1MDA7CiAgICB0Lm9uZSA9IDUwMDsKICAgIHQudHdvID0gNTAwOwogICAgdC50aHJlZSA9IDUwMDsKICAgIHQuZm91ciA9IDUwMDsKICAgIHQuZml2ZSA9IDUwMDsKICAgIHQuc2l4ID0gNTAwOwogICAgdC5zZXZlbiA9IDUwMDsKICAgIHQuZWlnaHQgPSA1MDA7CiAgICB0Lm5pbmUgPSA1MDA7CiAgICB0LmNvbG9uID0gMzMzOwogICAgdC5zZW1pY29sb24gPSAzMzM7CiAgICB0Lmxlc3MgPSA1NzA7CiAgICB0LmVxdWFsID0gNTcwOwogICAgdC5ncmVhdGVyID0gNTcwOwogICAgdC5xdWVzdGlvbiA9IDUwMDsKICAgIHQuYXQgPSA4MzI7CiAgICB0LkEgPSA2Njc7CiAgICB0LkIgPSA2Njc7CiAgICB0LkMgPSA2Njc7CiAgICB0LkQgPSA3MjI7CiAgICB0LkUgPSA2Njc7CiAgICB0LkYgPSA2Njc7CiAgICB0LkcgPSA3MjI7CiAgICB0LkggPSA3Nzg7CiAgICB0LkkgPSAzODk7CiAgICB0LkogPSA1MDA7CiAgICB0LksgPSA2Njc7CiAgICB0LkwgPSA2MTE7CiAgICB0Lk0gPSA4ODk7CiAgICB0Lk4gPSA3MjI7CiAgICB0Lk8gPSA3MjI7CiAgICB0LlAgPSA2MTE7CiAgICB0LlEgPSA3MjI7CiAgICB0LlIgPSA2Njc7CiAgICB0LlMgPSA1NTY7CiAgICB0LlQgPSA2MTE7CiAgICB0LlUgPSA3MjI7CiAgICB0LlYgPSA2Njc7CiAgICB0LlcgPSA4ODk7CiAgICB0LlggPSA2Njc7CiAgICB0LlkgPSA2MTE7CiAgICB0LlogPSA2MTE7CiAgICB0LmJyYWNrZXRsZWZ0ID0gMzMzOwogICAgdC5iYWNrc2xhc2ggPSAyNzg7CiAgICB0LmJyYWNrZXRyaWdodCA9IDMzMzsKICAgIHQuYXNjaWljaXJjdW0gPSA1NzA7CiAgICB0LnVuZGVyc2NvcmUgPSA1MDA7CiAgICB0LnF1b3RlbGVmdCA9IDMzMzsKICAgIHQuYSA9IDUwMDsKICAgIHQuYiA9IDUwMDsKICAgIHQuYyA9IDQ0NDsKICAgIHQuZCA9IDUwMDsKICAgIHQuZSA9IDQ0NDsKICAgIHQuZiA9IDMzMzsKICAgIHQuZyA9IDUwMDsKICAgIHQuaCA9IDU1NjsKICAgIHQuaSA9IDI3ODsKICAgIHQuaiA9IDI3ODsKICAgIHQuayA9IDUwMDsKICAgIHQubCA9IDI3ODsKICAgIHQubSA9IDc3ODsKICAgIHQubiA9IDU1NjsKICAgIHQubyA9IDUwMDsKICAgIHQucCA9IDUwMDsKICAgIHQucSA9IDUwMDsKICAgIHQuciA9IDM4OTsKICAgIHQucyA9IDM4OTsKICAgIHQudCA9IDI3ODsKICAgIHQudSA9IDU1NjsKICAgIHQudiA9IDQ0NDsKICAgIHQudyA9IDY2NzsKICAgIHQueCA9IDUwMDsKICAgIHQueSA9IDQ0NDsKICAgIHQueiA9IDM4OTsKICAgIHQuYnJhY2VsZWZ0ID0gMzQ4OwogICAgdC5iYXIgPSAyMjA7CiAgICB0LmJyYWNlcmlnaHQgPSAzNDg7CiAgICB0LmFzY2lpdGlsZGUgPSA1NzA7CiAgICB0LmV4Y2xhbWRvd24gPSAzODk7CiAgICB0LmNlbnQgPSA1MDA7CiAgICB0LnN0ZXJsaW5nID0gNTAwOwogICAgdC5mcmFjdGlvbiA9IDE2NzsKICAgIHQueWVuID0gNTAwOwogICAgdC5mbG9yaW4gPSA1MDA7CiAgICB0LnNlY3Rpb24gPSA1MDA7CiAgICB0LmN1cnJlbmN5ID0gNTAwOwogICAgdC5xdW90ZXNpbmdsZSA9IDI3ODsKICAgIHQucXVvdGVkYmxsZWZ0ID0gNTAwOwogICAgdC5ndWlsbGVtb3RsZWZ0ID0gNTAwOwogICAgdC5ndWlsc2luZ2xsZWZ0ID0gMzMzOwogICAgdC5ndWlsc2luZ2xyaWdodCA9IDMzMzsKICAgIHQuZmkgPSA1NTY7CiAgICB0LmZsID0gNTU2OwogICAgdC5lbmRhc2ggPSA1MDA7CiAgICB0LmRhZ2dlciA9IDUwMDsKICAgIHQuZGFnZ2VyZGJsID0gNTAwOwogICAgdC5wZXJpb2RjZW50ZXJlZCA9IDI1MDsKICAgIHQucGFyYWdyYXBoID0gNTAwOwogICAgdC5idWxsZXQgPSAzNTA7CiAgICB0LnF1b3Rlc2luZ2xiYXNlID0gMzMzOwogICAgdC5xdW90ZWRibGJhc2UgPSA1MDA7CiAgICB0LnF1b3RlZGJscmlnaHQgPSA1MDA7CiAgICB0Lmd1aWxsZW1vdHJpZ2h0ID0gNTAwOwogICAgdC5lbGxpcHNpcyA9IDEwMDA7CiAgICB0LnBlcnRob3VzYW5kID0gMTAwMDsKICAgIHQucXVlc3Rpb25kb3duID0gNTAwOwogICAgdC5ncmF2ZSA9IDMzMzsKICAgIHQuYWN1dGUgPSAzMzM7CiAgICB0LmNpcmN1bWZsZXggPSAzMzM7CiAgICB0LnRpbGRlID0gMzMzOwogICAgdC5tYWNyb24gPSAzMzM7CiAgICB0LmJyZXZlID0gMzMzOwogICAgdC5kb3RhY2NlbnQgPSAzMzM7CiAgICB0LmRpZXJlc2lzID0gMzMzOwogICAgdC5yaW5nID0gMzMzOwogICAgdC5jZWRpbGxhID0gMzMzOwogICAgdC5odW5nYXJ1bWxhdXQgPSAzMzM7CiAgICB0Lm9nb25layA9IDMzMzsKICAgIHQuY2Fyb24gPSAzMzM7CiAgICB0LmVtZGFzaCA9IDEwMDA7CiAgICB0LkFFID0gOTQ0OwogICAgdC5vcmRmZW1pbmluZSA9IDI2NjsKICAgIHQuTHNsYXNoID0gNjExOwogICAgdC5Pc2xhc2ggPSA3MjI7CiAgICB0Lk9FID0gOTQ0OwogICAgdC5vcmRtYXNjdWxpbmUgPSAzMDA7CiAgICB0LmFlID0gNzIyOwogICAgdC5kb3RsZXNzaSA9IDI3ODsKICAgIHQubHNsYXNoID0gMjc4OwogICAgdC5vc2xhc2ggPSA1MDA7CiAgICB0Lm9lID0gNzIyOwogICAgdC5nZXJtYW5kYmxzID0gNTAwOwogICAgdC5JZGllcmVzaXMgPSAzODk7CiAgICB0LmVhY3V0ZSA9IDQ0NDsKICAgIHQuYWJyZXZlID0gNTAwOwogICAgdC51aHVuZ2FydW1sYXV0ID0gNTU2OwogICAgdC5lY2Fyb24gPSA0NDQ7CiAgICB0LllkaWVyZXNpcyA9IDYxMTsKICAgIHQuZGl2aWRlID0gNTcwOwogICAgdC5ZYWN1dGUgPSA2MTE7CiAgICB0LkFjaXJjdW1mbGV4ID0gNjY3OwogICAgdC5hYWN1dGUgPSA1MDA7CiAgICB0LlVjaXJjdW1mbGV4ID0gNzIyOwogICAgdC55YWN1dGUgPSA0NDQ7CiAgICB0LnNjb21tYWFjY2VudCA9IDM4OTsKICAgIHQuZWNpcmN1bWZsZXggPSA0NDQ7CiAgICB0LlVyaW5nID0gNzIyOwogICAgdC5VZGllcmVzaXMgPSA3MjI7CiAgICB0LmFvZ29uZWsgPSA1MDA7CiAgICB0LlVhY3V0ZSA9IDcyMjsKICAgIHQudW9nb25layA9IDU1NjsKICAgIHQuRWRpZXJlc2lzID0gNjY3OwogICAgdC5EY3JvYXQgPSA3MjI7CiAgICB0LmNvbW1hYWNjZW50ID0gMjUwOwogICAgdC5jb3B5cmlnaHQgPSA3NDc7CiAgICB0LkVtYWNyb24gPSA2Njc7CiAgICB0LmNjYXJvbiA9IDQ0NDsKICAgIHQuYXJpbmcgPSA1MDA7CiAgICB0Lk5jb21tYWFjY2VudCA9IDcyMjsKICAgIHQubGFjdXRlID0gMjc4OwogICAgdC5hZ3JhdmUgPSA1MDA7CiAgICB0LlRjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQ2FjdXRlID0gNjY3OwogICAgdC5hdGlsZGUgPSA1MDA7CiAgICB0LkVkb3RhY2NlbnQgPSA2Njc7CiAgICB0LnNjYXJvbiA9IDM4OTsKICAgIHQuc2NlZGlsbGEgPSAzODk7CiAgICB0LmlhY3V0ZSA9IDI3ODsKICAgIHQubG96ZW5nZSA9IDQ5NDsKICAgIHQuUmNhcm9uID0gNjY3OwogICAgdC5HY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LnVjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5hY2lyY3VtZmxleCA9IDUwMDsKICAgIHQuQW1hY3JvbiA9IDY2NzsKICAgIHQucmNhcm9uID0gMzg5OwogICAgdC5jY2VkaWxsYSA9IDQ0NDsKICAgIHQuWmRvdGFjY2VudCA9IDYxMTsKICAgIHQuVGhvcm4gPSA2MTE7CiAgICB0Lk9tYWNyb24gPSA3MjI7CiAgICB0LlJhY3V0ZSA9IDY2NzsKICAgIHQuU2FjdXRlID0gNTU2OwogICAgdC5kY2Fyb24gPSA2MDg7CiAgICB0LlVtYWNyb24gPSA3MjI7CiAgICB0LnVyaW5nID0gNTU2OwogICAgdC50aHJlZXN1cGVyaW9yID0gMzAwOwogICAgdC5PZ3JhdmUgPSA3MjI7CiAgICB0LkFncmF2ZSA9IDY2NzsKICAgIHQuQWJyZXZlID0gNjY3OwogICAgdC5tdWx0aXBseSA9IDU3MDsKICAgIHQudWFjdXRlID0gNTU2OwogICAgdC5UY2Fyb24gPSA2MTE7CiAgICB0LnBhcnRpYWxkaWZmID0gNDk0OwogICAgdC55ZGllcmVzaXMgPSA0NDQ7CiAgICB0Lk5hY3V0ZSA9IDcyMjsKICAgIHQuaWNpcmN1bWZsZXggPSAyNzg7CiAgICB0LkVjaXJjdW1mbGV4ID0gNjY3OwogICAgdC5hZGllcmVzaXMgPSA1MDA7CiAgICB0LmVkaWVyZXNpcyA9IDQ0NDsKICAgIHQuY2FjdXRlID0gNDQ0OwogICAgdC5uYWN1dGUgPSA1NTY7CiAgICB0LnVtYWNyb24gPSA1NTY7CiAgICB0Lk5jYXJvbiA9IDcyMjsKICAgIHQuSWFjdXRlID0gMzg5OwogICAgdC5wbHVzbWludXMgPSA1NzA7CiAgICB0LmJyb2tlbmJhciA9IDIyMDsKICAgIHQucmVnaXN0ZXJlZCA9IDc0NzsKICAgIHQuR2JyZXZlID0gNzIyOwogICAgdC5JZG90YWNjZW50ID0gMzg5OwogICAgdC5zdW1tYXRpb24gPSA2MDA7CiAgICB0LkVncmF2ZSA9IDY2NzsKICAgIHQucmFjdXRlID0gMzg5OwogICAgdC5vbWFjcm9uID0gNTAwOwogICAgdC5aYWN1dGUgPSA2MTE7CiAgICB0LlpjYXJvbiA9IDYxMTsKICAgIHQuZ3JlYXRlcmVxdWFsID0gNTQ5OwogICAgdC5FdGggPSA3MjI7CiAgICB0LkNjZWRpbGxhID0gNjY3OwogICAgdC5sY29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LnRjYXJvbiA9IDM2NjsKICAgIHQuZW9nb25layA9IDQ0NDsKICAgIHQuVW9nb25layA9IDcyMjsKICAgIHQuQWFjdXRlID0gNjY3OwogICAgdC5BZGllcmVzaXMgPSA2Njc7CiAgICB0LmVncmF2ZSA9IDQ0NDsKICAgIHQuemFjdXRlID0gMzg5OwogICAgdC5pb2dvbmVrID0gMjc4OwogICAgdC5PYWN1dGUgPSA3MjI7CiAgICB0Lm9hY3V0ZSA9IDUwMDsKICAgIHQuYW1hY3JvbiA9IDUwMDsKICAgIHQuc2FjdXRlID0gMzg5OwogICAgdC5pZGllcmVzaXMgPSAyNzg7CiAgICB0Lk9jaXJjdW1mbGV4ID0gNzIyOwogICAgdC5VZ3JhdmUgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC50aG9ybiA9IDUwMDsKICAgIHQudHdvc3VwZXJpb3IgPSAzMDA7CiAgICB0Lk9kaWVyZXNpcyA9IDcyMjsKICAgIHQubXUgPSA1NzY7CiAgICB0LmlncmF2ZSA9IDI3ODsKICAgIHQub2h1bmdhcnVtbGF1dCA9IDUwMDsKICAgIHQuRW9nb25layA9IDY2NzsKICAgIHQuZGNyb2F0ID0gNTAwOwogICAgdC50aHJlZXF1YXJ0ZXJzID0gNzUwOwogICAgdC5TY2VkaWxsYSA9IDU1NjsKICAgIHQubGNhcm9uID0gMzgyOwogICAgdC5LY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0LkxhY3V0ZSA9IDYxMTsKICAgIHQudHJhZGVtYXJrID0gMTAwMDsKICAgIHQuZWRvdGFjY2VudCA9IDQ0NDsKICAgIHQuSWdyYXZlID0gMzg5OwogICAgdC5JbWFjcm9uID0gMzg5OwogICAgdC5MY2Fyb24gPSA2MTE7CiAgICB0Lm9uZWhhbGYgPSA3NTA7CiAgICB0Lmxlc3NlcXVhbCA9IDU0OTsKICAgIHQub2NpcmN1bWZsZXggPSA1MDA7CiAgICB0Lm50aWxkZSA9IDU1NjsKICAgIHQuVWh1bmdhcnVtbGF1dCA9IDcyMjsKICAgIHQuRWFjdXRlID0gNjY3OwogICAgdC5lbWFjcm9uID0gNDQ0OwogICAgdC5nYnJldmUgPSA1MDA7CiAgICB0Lm9uZXF1YXJ0ZXIgPSA3NTA7CiAgICB0LlNjYXJvbiA9IDU1NjsKICAgIHQuU2NvbW1hYWNjZW50ID0gNTU2OwogICAgdC5PaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5kZWdyZWUgPSA0MDA7CiAgICB0Lm9ncmF2ZSA9IDUwMDsKICAgIHQuQ2Nhcm9uID0gNjY3OwogICAgdC51Z3JhdmUgPSA1NTY7CiAgICB0LnJhZGljYWwgPSA1NDk7CiAgICB0LkRjYXJvbiA9IDcyMjsKICAgIHQucmNvbW1hYWNjZW50ID0gMzg5OwogICAgdC5OdGlsZGUgPSA3MjI7CiAgICB0Lm90aWxkZSA9IDUwMDsKICAgIHQuUmNvbW1hYWNjZW50ID0gNjY3OwogICAgdC5MY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0LkF0aWxkZSA9IDY2NzsKICAgIHQuQW9nb25layA9IDY2NzsKICAgIHQuQXJpbmcgPSA2Njc7CiAgICB0Lk90aWxkZSA9IDcyMjsKICAgIHQuemRvdGFjY2VudCA9IDM4OTsKICAgIHQuRWNhcm9uID0gNjY3OwogICAgdC5Jb2dvbmVrID0gMzg5OwogICAgdC5rY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0Lm1pbnVzID0gNjA2OwogICAgdC5JY2lyY3VtZmxleCA9IDM4OTsKICAgIHQubmNhcm9uID0gNTU2OwogICAgdC50Y29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LmxvZ2ljYWxub3QgPSA2MDY7CiAgICB0Lm9kaWVyZXNpcyA9IDUwMDsKICAgIHQudWRpZXJlc2lzID0gNTU2OwogICAgdC5ub3RlcXVhbCA9IDU0OTsKICAgIHQuZ2NvbW1hYWNjZW50ID0gNTAwOwogICAgdC5ldGggPSA1MDA7CiAgICB0LnpjYXJvbiA9IDM4OTsKICAgIHQubmNvbW1hYWNjZW50ID0gNTU2OwogICAgdC5vbmVzdXBlcmlvciA9IDMwMDsKICAgIHQuaW1hY3JvbiA9IDI3ODsKICAgIHQuRXVybyA9IDUwMDsKICB9KTsKICB0WyJUaW1lcy1JdGFsaWMiXSA9ICgwLCBfY29yZV91dGlscy5nZXRMb29rdXBUYWJsZUZhY3RvcnkpKGZ1bmN0aW9uICh0KSB7CiAgICB0LnNwYWNlID0gMjUwOwogICAgdC5leGNsYW0gPSAzMzM7CiAgICB0LnF1b3RlZGJsID0gNDIwOwogICAgdC5udW1iZXJzaWduID0gNTAwOwogICAgdC5kb2xsYXIgPSA1MDA7CiAgICB0LnBlcmNlbnQgPSA4MzM7CiAgICB0LmFtcGVyc2FuZCA9IDc3ODsKICAgIHQucXVvdGVyaWdodCA9IDMzMzsKICAgIHQucGFyZW5sZWZ0ID0gMzMzOwogICAgdC5wYXJlbnJpZ2h0ID0gMzMzOwogICAgdC5hc3RlcmlzayA9IDUwMDsKICAgIHQucGx1cyA9IDY3NTsKICAgIHQuY29tbWEgPSAyNTA7CiAgICB0Lmh5cGhlbiA9IDMzMzsKICAgIHQucGVyaW9kID0gMjUwOwogICAgdC5zbGFzaCA9IDI3ODsKICAgIHQuemVybyA9IDUwMDsKICAgIHQub25lID0gNTAwOwogICAgdC50d28gPSA1MDA7CiAgICB0LnRocmVlID0gNTAwOwogICAgdC5mb3VyID0gNTAwOwogICAgdC5maXZlID0gNTAwOwogICAgdC5zaXggPSA1MDA7CiAgICB0LnNldmVuID0gNTAwOwogICAgdC5laWdodCA9IDUwMDsKICAgIHQubmluZSA9IDUwMDsKICAgIHQuY29sb24gPSAzMzM7CiAgICB0LnNlbWljb2xvbiA9IDMzMzsKICAgIHQubGVzcyA9IDY3NTsKICAgIHQuZXF1YWwgPSA2NzU7CiAgICB0LmdyZWF0ZXIgPSA2NzU7CiAgICB0LnF1ZXN0aW9uID0gNTAwOwogICAgdC5hdCA9IDkyMDsKICAgIHQuQSA9IDYxMTsKICAgIHQuQiA9IDYxMTsKICAgIHQuQyA9IDY2NzsKICAgIHQuRCA9IDcyMjsKICAgIHQuRSA9IDYxMTsKICAgIHQuRiA9IDYxMTsKICAgIHQuRyA9IDcyMjsKICAgIHQuSCA9IDcyMjsKICAgIHQuSSA9IDMzMzsKICAgIHQuSiA9IDQ0NDsKICAgIHQuSyA9IDY2NzsKICAgIHQuTCA9IDU1NjsKICAgIHQuTSA9IDgzMzsKICAgIHQuTiA9IDY2NzsKICAgIHQuTyA9IDcyMjsKICAgIHQuUCA9IDYxMTsKICAgIHQuUSA9IDcyMjsKICAgIHQuUiA9IDYxMTsKICAgIHQuUyA9IDUwMDsKICAgIHQuVCA9IDU1NjsKICAgIHQuVSA9IDcyMjsKICAgIHQuViA9IDYxMTsKICAgIHQuVyA9IDgzMzsKICAgIHQuWCA9IDYxMTsKICAgIHQuWSA9IDU1NjsKICAgIHQuWiA9IDU1NjsKICAgIHQuYnJhY2tldGxlZnQgPSAzODk7CiAgICB0LmJhY2tzbGFzaCA9IDI3ODsKICAgIHQuYnJhY2tldHJpZ2h0ID0gMzg5OwogICAgdC5hc2NpaWNpcmN1bSA9IDQyMjsKICAgIHQudW5kZXJzY29yZSA9IDUwMDsKICAgIHQucXVvdGVsZWZ0ID0gMzMzOwogICAgdC5hID0gNTAwOwogICAgdC5iID0gNTAwOwogICAgdC5jID0gNDQ0OwogICAgdC5kID0gNTAwOwogICAgdC5lID0gNDQ0OwogICAgdC5mID0gMjc4OwogICAgdC5nID0gNTAwOwogICAgdC5oID0gNTAwOwogICAgdC5pID0gMjc4OwogICAgdC5qID0gMjc4OwogICAgdC5rID0gNDQ0OwogICAgdC5sID0gMjc4OwogICAgdC5tID0gNzIyOwogICAgdC5uID0gNTAwOwogICAgdC5vID0gNTAwOwogICAgdC5wID0gNTAwOwogICAgdC5xID0gNTAwOwogICAgdC5yID0gMzg5OwogICAgdC5zID0gMzg5OwogICAgdC50ID0gMjc4OwogICAgdC51ID0gNTAwOwogICAgdC52ID0gNDQ0OwogICAgdC53ID0gNjY3OwogICAgdC54ID0gNDQ0OwogICAgdC55ID0gNDQ0OwogICAgdC56ID0gMzg5OwogICAgdC5icmFjZWxlZnQgPSA0MDA7CiAgICB0LmJhciA9IDI3NTsKICAgIHQuYnJhY2VyaWdodCA9IDQwMDsKICAgIHQuYXNjaWl0aWxkZSA9IDU0MTsKICAgIHQuZXhjbGFtZG93biA9IDM4OTsKICAgIHQuY2VudCA9IDUwMDsKICAgIHQuc3RlcmxpbmcgPSA1MDA7CiAgICB0LmZyYWN0aW9uID0gMTY3OwogICAgdC55ZW4gPSA1MDA7CiAgICB0LmZsb3JpbiA9IDUwMDsKICAgIHQuc2VjdGlvbiA9IDUwMDsKICAgIHQuY3VycmVuY3kgPSA1MDA7CiAgICB0LnF1b3Rlc2luZ2xlID0gMjE0OwogICAgdC5xdW90ZWRibGxlZnQgPSA1NTY7CiAgICB0Lmd1aWxsZW1vdGxlZnQgPSA1MDA7CiAgICB0Lmd1aWxzaW5nbGxlZnQgPSAzMzM7CiAgICB0Lmd1aWxzaW5nbHJpZ2h0ID0gMzMzOwogICAgdC5maSA9IDUwMDsKICAgIHQuZmwgPSA1MDA7CiAgICB0LmVuZGFzaCA9IDUwMDsKICAgIHQuZGFnZ2VyID0gNTAwOwogICAgdC5kYWdnZXJkYmwgPSA1MDA7CiAgICB0LnBlcmlvZGNlbnRlcmVkID0gMjUwOwogICAgdC5wYXJhZ3JhcGggPSA1MjM7CiAgICB0LmJ1bGxldCA9IDM1MDsKICAgIHQucXVvdGVzaW5nbGJhc2UgPSAzMzM7CiAgICB0LnF1b3RlZGJsYmFzZSA9IDU1NjsKICAgIHQucXVvdGVkYmxyaWdodCA9IDU1NjsKICAgIHQuZ3VpbGxlbW90cmlnaHQgPSA1MDA7CiAgICB0LmVsbGlwc2lzID0gODg5OwogICAgdC5wZXJ0aG91c2FuZCA9IDEwMDA7CiAgICB0LnF1ZXN0aW9uZG93biA9IDUwMDsKICAgIHQuZ3JhdmUgPSAzMzM7CiAgICB0LmFjdXRlID0gMzMzOwogICAgdC5jaXJjdW1mbGV4ID0gMzMzOwogICAgdC50aWxkZSA9IDMzMzsKICAgIHQubWFjcm9uID0gMzMzOwogICAgdC5icmV2ZSA9IDMzMzsKICAgIHQuZG90YWNjZW50ID0gMzMzOwogICAgdC5kaWVyZXNpcyA9IDMzMzsKICAgIHQucmluZyA9IDMzMzsKICAgIHQuY2VkaWxsYSA9IDMzMzsKICAgIHQuaHVuZ2FydW1sYXV0ID0gMzMzOwogICAgdC5vZ29uZWsgPSAzMzM7CiAgICB0LmNhcm9uID0gMzMzOwogICAgdC5lbWRhc2ggPSA4ODk7CiAgICB0LkFFID0gODg5OwogICAgdC5vcmRmZW1pbmluZSA9IDI3NjsKICAgIHQuTHNsYXNoID0gNTU2OwogICAgdC5Pc2xhc2ggPSA3MjI7CiAgICB0Lk9FID0gOTQ0OwogICAgdC5vcmRtYXNjdWxpbmUgPSAzMTA7CiAgICB0LmFlID0gNjY3OwogICAgdC5kb3RsZXNzaSA9IDI3ODsKICAgIHQubHNsYXNoID0gMjc4OwogICAgdC5vc2xhc2ggPSA1MDA7CiAgICB0Lm9lID0gNjY3OwogICAgdC5nZXJtYW5kYmxzID0gNTAwOwogICAgdC5JZGllcmVzaXMgPSAzMzM7CiAgICB0LmVhY3V0ZSA9IDQ0NDsKICAgIHQuYWJyZXZlID0gNTAwOwogICAgdC51aHVuZ2FydW1sYXV0ID0gNTAwOwogICAgdC5lY2Fyb24gPSA0NDQ7CiAgICB0LllkaWVyZXNpcyA9IDU1NjsKICAgIHQuZGl2aWRlID0gNjc1OwogICAgdC5ZYWN1dGUgPSA1NTY7CiAgICB0LkFjaXJjdW1mbGV4ID0gNjExOwogICAgdC5hYWN1dGUgPSA1MDA7CiAgICB0LlVjaXJjdW1mbGV4ID0gNzIyOwogICAgdC55YWN1dGUgPSA0NDQ7CiAgICB0LnNjb21tYWFjY2VudCA9IDM4OTsKICAgIHQuZWNpcmN1bWZsZXggPSA0NDQ7CiAgICB0LlVyaW5nID0gNzIyOwogICAgdC5VZGllcmVzaXMgPSA3MjI7CiAgICB0LmFvZ29uZWsgPSA1MDA7CiAgICB0LlVhY3V0ZSA9IDcyMjsKICAgIHQudW9nb25layA9IDUwMDsKICAgIHQuRWRpZXJlc2lzID0gNjExOwogICAgdC5EY3JvYXQgPSA3MjI7CiAgICB0LmNvbW1hYWNjZW50ID0gMjUwOwogICAgdC5jb3B5cmlnaHQgPSA3NjA7CiAgICB0LkVtYWNyb24gPSA2MTE7CiAgICB0LmNjYXJvbiA9IDQ0NDsKICAgIHQuYXJpbmcgPSA1MDA7CiAgICB0Lk5jb21tYWFjY2VudCA9IDY2NzsKICAgIHQubGFjdXRlID0gMjc4OwogICAgdC5hZ3JhdmUgPSA1MDA7CiAgICB0LlRjb21tYWFjY2VudCA9IDU1NjsKICAgIHQuQ2FjdXRlID0gNjY3OwogICAgdC5hdGlsZGUgPSA1MDA7CiAgICB0LkVkb3RhY2NlbnQgPSA2MTE7CiAgICB0LnNjYXJvbiA9IDM4OTsKICAgIHQuc2NlZGlsbGEgPSAzODk7CiAgICB0LmlhY3V0ZSA9IDI3ODsKICAgIHQubG96ZW5nZSA9IDQ3MTsKICAgIHQuUmNhcm9uID0gNjExOwogICAgdC5HY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LnVjaXJjdW1mbGV4ID0gNTAwOwogICAgdC5hY2lyY3VtZmxleCA9IDUwMDsKICAgIHQuQW1hY3JvbiA9IDYxMTsKICAgIHQucmNhcm9uID0gMzg5OwogICAgdC5jY2VkaWxsYSA9IDQ0NDsKICAgIHQuWmRvdGFjY2VudCA9IDU1NjsKICAgIHQuVGhvcm4gPSA2MTE7CiAgICB0Lk9tYWNyb24gPSA3MjI7CiAgICB0LlJhY3V0ZSA9IDYxMTsKICAgIHQuU2FjdXRlID0gNTAwOwogICAgdC5kY2Fyb24gPSA1NDQ7CiAgICB0LlVtYWNyb24gPSA3MjI7CiAgICB0LnVyaW5nID0gNTAwOwogICAgdC50aHJlZXN1cGVyaW9yID0gMzAwOwogICAgdC5PZ3JhdmUgPSA3MjI7CiAgICB0LkFncmF2ZSA9IDYxMTsKICAgIHQuQWJyZXZlID0gNjExOwogICAgdC5tdWx0aXBseSA9IDY3NTsKICAgIHQudWFjdXRlID0gNTAwOwogICAgdC5UY2Fyb24gPSA1NTY7CiAgICB0LnBhcnRpYWxkaWZmID0gNDc2OwogICAgdC55ZGllcmVzaXMgPSA0NDQ7CiAgICB0Lk5hY3V0ZSA9IDY2NzsKICAgIHQuaWNpcmN1bWZsZXggPSAyNzg7CiAgICB0LkVjaXJjdW1mbGV4ID0gNjExOwogICAgdC5hZGllcmVzaXMgPSA1MDA7CiAgICB0LmVkaWVyZXNpcyA9IDQ0NDsKICAgIHQuY2FjdXRlID0gNDQ0OwogICAgdC5uYWN1dGUgPSA1MDA7CiAgICB0LnVtYWNyb24gPSA1MDA7CiAgICB0Lk5jYXJvbiA9IDY2NzsKICAgIHQuSWFjdXRlID0gMzMzOwogICAgdC5wbHVzbWludXMgPSA2NzU7CiAgICB0LmJyb2tlbmJhciA9IDI3NTsKICAgIHQucmVnaXN0ZXJlZCA9IDc2MDsKICAgIHQuR2JyZXZlID0gNzIyOwogICAgdC5JZG90YWNjZW50ID0gMzMzOwogICAgdC5zdW1tYXRpb24gPSA2MDA7CiAgICB0LkVncmF2ZSA9IDYxMTsKICAgIHQucmFjdXRlID0gMzg5OwogICAgdC5vbWFjcm9uID0gNTAwOwogICAgdC5aYWN1dGUgPSA1NTY7CiAgICB0LlpjYXJvbiA9IDU1NjsKICAgIHQuZ3JlYXRlcmVxdWFsID0gNTQ5OwogICAgdC5FdGggPSA3MjI7CiAgICB0LkNjZWRpbGxhID0gNjY3OwogICAgdC5sY29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LnRjYXJvbiA9IDMwMDsKICAgIHQuZW9nb25layA9IDQ0NDsKICAgIHQuVW9nb25layA9IDcyMjsKICAgIHQuQWFjdXRlID0gNjExOwogICAgdC5BZGllcmVzaXMgPSA2MTE7CiAgICB0LmVncmF2ZSA9IDQ0NDsKICAgIHQuemFjdXRlID0gMzg5OwogICAgdC5pb2dvbmVrID0gMjc4OwogICAgdC5PYWN1dGUgPSA3MjI7CiAgICB0Lm9hY3V0ZSA9IDUwMDsKICAgIHQuYW1hY3JvbiA9IDUwMDsKICAgIHQuc2FjdXRlID0gMzg5OwogICAgdC5pZGllcmVzaXMgPSAyNzg7CiAgICB0Lk9jaXJjdW1mbGV4ID0gNzIyOwogICAgdC5VZ3JhdmUgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC50aG9ybiA9IDUwMDsKICAgIHQudHdvc3VwZXJpb3IgPSAzMDA7CiAgICB0Lk9kaWVyZXNpcyA9IDcyMjsKICAgIHQubXUgPSA1MDA7CiAgICB0LmlncmF2ZSA9IDI3ODsKICAgIHQub2h1bmdhcnVtbGF1dCA9IDUwMDsKICAgIHQuRW9nb25layA9IDYxMTsKICAgIHQuZGNyb2F0ID0gNTAwOwogICAgdC50aHJlZXF1YXJ0ZXJzID0gNzUwOwogICAgdC5TY2VkaWxsYSA9IDUwMDsKICAgIHQubGNhcm9uID0gMzAwOwogICAgdC5LY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0LkxhY3V0ZSA9IDU1NjsKICAgIHQudHJhZGVtYXJrID0gOTgwOwogICAgdC5lZG90YWNjZW50ID0gNDQ0OwogICAgdC5JZ3JhdmUgPSAzMzM7CiAgICB0LkltYWNyb24gPSAzMzM7CiAgICB0LkxjYXJvbiA9IDYxMTsKICAgIHQub25laGFsZiA9IDc1MDsKICAgIHQubGVzc2VxdWFsID0gNTQ5OwogICAgdC5vY2lyY3VtZmxleCA9IDUwMDsKICAgIHQubnRpbGRlID0gNTAwOwogICAgdC5VaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5FYWN1dGUgPSA2MTE7CiAgICB0LmVtYWNyb24gPSA0NDQ7CiAgICB0LmdicmV2ZSA9IDUwMDsKICAgIHQub25lcXVhcnRlciA9IDc1MDsKICAgIHQuU2Nhcm9uID0gNTAwOwogICAgdC5TY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0Lk9odW5nYXJ1bWxhdXQgPSA3MjI7CiAgICB0LmRlZ3JlZSA9IDQwMDsKICAgIHQub2dyYXZlID0gNTAwOwogICAgdC5DY2Fyb24gPSA2Njc7CiAgICB0LnVncmF2ZSA9IDUwMDsKICAgIHQucmFkaWNhbCA9IDQ1MzsKICAgIHQuRGNhcm9uID0gNzIyOwogICAgdC5yY29tbWFhY2NlbnQgPSAzODk7CiAgICB0Lk50aWxkZSA9IDY2NzsKICAgIHQub3RpbGRlID0gNTAwOwogICAgdC5SY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0Lkxjb21tYWFjY2VudCA9IDU1NjsKICAgIHQuQXRpbGRlID0gNjExOwogICAgdC5Bb2dvbmVrID0gNjExOwogICAgdC5BcmluZyA9IDYxMTsKICAgIHQuT3RpbGRlID0gNzIyOwogICAgdC56ZG90YWNjZW50ID0gMzg5OwogICAgdC5FY2Fyb24gPSA2MTE7CiAgICB0LklvZ29uZWsgPSAzMzM7CiAgICB0Lmtjb21tYWFjY2VudCA9IDQ0NDsKICAgIHQubWludXMgPSA2NzU7CiAgICB0LkljaXJjdW1mbGV4ID0gMzMzOwogICAgdC5uY2Fyb24gPSA1MDA7CiAgICB0LnRjb21tYWFjY2VudCA9IDI3ODsKICAgIHQubG9naWNhbG5vdCA9IDY3NTsKICAgIHQub2RpZXJlc2lzID0gNTAwOwogICAgdC51ZGllcmVzaXMgPSA1MDA7CiAgICB0Lm5vdGVxdWFsID0gNTQ5OwogICAgdC5nY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0LmV0aCA9IDUwMDsKICAgIHQuemNhcm9uID0gMzg5OwogICAgdC5uY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0Lm9uZXN1cGVyaW9yID0gMzAwOwogICAgdC5pbWFjcm9uID0gMjc4OwogICAgdC5FdXJvID0gNTAwOwogIH0pOwogIHQuWmFwZkRpbmdiYXRzID0gKDAsIF9jb3JlX3V0aWxzLmdldExvb2t1cFRhYmxlRmFjdG9yeSkoZnVuY3Rpb24gKHQpIHsKICAgIHQuc3BhY2UgPSAyNzg7CiAgICB0LmExID0gOTc0OwogICAgdC5hMiA9IDk2MTsKICAgIHQuYTIwMiA9IDk3NDsKICAgIHQuYTMgPSA5ODA7CiAgICB0LmE0ID0gNzE5OwogICAgdC5hNSA9IDc4OTsKICAgIHQuYTExOSA9IDc5MDsKICAgIHQuYTExOCA9IDc5MTsKICAgIHQuYTExNyA9IDY5MDsKICAgIHQuYTExID0gOTYwOwogICAgdC5hMTIgPSA5Mzk7CiAgICB0LmExMyA9IDU0OTsKICAgIHQuYTE0ID0gODU1OwogICAgdC5hMTUgPSA5MTE7CiAgICB0LmExNiA9IDkzMzsKICAgIHQuYTEwNSA9IDkxMTsKICAgIHQuYTE3ID0gOTQ1OwogICAgdC5hMTggPSA5NzQ7CiAgICB0LmExOSA9IDc1NTsKICAgIHQuYTIwID0gODQ2OwogICAgdC5hMjEgPSA3NjI7CiAgICB0LmEyMiA9IDc2MTsKICAgIHQuYTIzID0gNTcxOwogICAgdC5hMjQgPSA2Nzc7CiAgICB0LmEyNSA9IDc2MzsKICAgIHQuYTI2ID0gNzYwOwogICAgdC5hMjcgPSA3NTk7CiAgICB0LmEyOCA9IDc1NDsKICAgIHQuYTYgPSA0OTQ7CiAgICB0LmE3ID0gNTUyOwogICAgdC5hOCA9IDUzNzsKICAgIHQuYTkgPSA1Nzc7CiAgICB0LmExMCA9IDY5MjsKICAgIHQuYTI5ID0gNzg2OwogICAgdC5hMzAgPSA3ODg7CiAgICB0LmEzMSA9IDc4ODsKICAgIHQuYTMyID0gNzkwOwogICAgdC5hMzMgPSA3OTM7CiAgICB0LmEzNCA9IDc5NDsKICAgIHQuYTM1ID0gODE2OwogICAgdC5hMzYgPSA4MjM7CiAgICB0LmEzNyA9IDc4OTsKICAgIHQuYTM4ID0gODQxOwogICAgdC5hMzkgPSA4MjM7CiAgICB0LmE0MCA9IDgzMzsKICAgIHQuYTQxID0gODE2OwogICAgdC5hNDIgPSA4MzE7CiAgICB0LmE0MyA9IDkyMzsKICAgIHQuYTQ0ID0gNzQ0OwogICAgdC5hNDUgPSA3MjM7CiAgICB0LmE0NiA9IDc0OTsKICAgIHQuYTQ3ID0gNzkwOwogICAgdC5hNDggPSA3OTI7CiAgICB0LmE0OSA9IDY5NTsKICAgIHQuYTUwID0gNzc2OwogICAgdC5hNTEgPSA3Njg7CiAgICB0LmE1MiA9IDc5MjsKICAgIHQuYTUzID0gNzU5OwogICAgdC5hNTQgPSA3MDc7CiAgICB0LmE1NSA9IDcwODsKICAgIHQuYTU2ID0gNjgyOwogICAgdC5hNTcgPSA3MDE7CiAgICB0LmE1OCA9IDgyNjsKICAgIHQuYTU5ID0gODE1OwogICAgdC5hNjAgPSA3ODk7CiAgICB0LmE2MSA9IDc4OTsKICAgIHQuYTYyID0gNzA3OwogICAgdC5hNjMgPSA2ODc7CiAgICB0LmE2NCA9IDY5NjsKICAgIHQuYTY1ID0gNjg5OwogICAgdC5hNjYgPSA3ODY7CiAgICB0LmE2NyA9IDc4NzsKICAgIHQuYTY4ID0gNzEzOwogICAgdC5hNjkgPSA3OTE7CiAgICB0LmE3MCA9IDc4NTsKICAgIHQuYTcxID0gNzkxOwogICAgdC5hNzIgPSA4NzM7CiAgICB0LmE3MyA9IDc2MTsKICAgIHQuYTc0ID0gNzYyOwogICAgdC5hMjAzID0gNzYyOwogICAgdC5hNzUgPSA3NTk7CiAgICB0LmEyMDQgPSA3NTk7CiAgICB0LmE3NiA9IDg5MjsKICAgIHQuYTc3ID0gODkyOwogICAgdC5hNzggPSA3ODg7CiAgICB0LmE3OSA9IDc4NDsKICAgIHQuYTgxID0gNDM4OwogICAgdC5hODIgPSAxMzg7CiAgICB0LmE4MyA9IDI3NzsKICAgIHQuYTg0ID0gNDE1OwogICAgdC5hOTcgPSAzOTI7CiAgICB0LmE5OCA9IDM5MjsKICAgIHQuYTk5ID0gNjY4OwogICAgdC5hMTAwID0gNjY4OwogICAgdC5hODkgPSAzOTA7CiAgICB0LmE5MCA9IDM5MDsKICAgIHQuYTkzID0gMzE3OwogICAgdC5hOTQgPSAzMTc7CiAgICB0LmE5MSA9IDI3NjsKICAgIHQuYTkyID0gMjc2OwogICAgdC5hMjA1ID0gNTA5OwogICAgdC5hODUgPSA1MDk7CiAgICB0LmEyMDYgPSA0MTA7CiAgICB0LmE4NiA9IDQxMDsKICAgIHQuYTg3ID0gMjM0OwogICAgdC5hODggPSAyMzQ7CiAgICB0LmE5NSA9IDMzNDsKICAgIHQuYTk2ID0gMzM0OwogICAgdC5hMTAxID0gNzMyOwogICAgdC5hMTAyID0gNTQ0OwogICAgdC5hMTAzID0gNTQ0OwogICAgdC5hMTA0ID0gOTEwOwogICAgdC5hMTA2ID0gNjY3OwogICAgdC5hMTA3ID0gNzYwOwogICAgdC5hMTA4ID0gNzYwOwogICAgdC5hMTEyID0gNzc2OwogICAgdC5hMTExID0gNTk1OwogICAgdC5hMTEwID0gNjk0OwogICAgdC5hMTA5ID0gNjI2OwogICAgdC5hMTIwID0gNzg4OwogICAgdC5hMTIxID0gNzg4OwogICAgdC5hMTIyID0gNzg4OwogICAgdC5hMTIzID0gNzg4OwogICAgdC5hMTI0ID0gNzg4OwogICAgdC5hMTI1ID0gNzg4OwogICAgdC5hMTI2ID0gNzg4OwogICAgdC5hMTI3ID0gNzg4OwogICAgdC5hMTI4ID0gNzg4OwogICAgdC5hMTI5ID0gNzg4OwogICAgdC5hMTMwID0gNzg4OwogICAgdC5hMTMxID0gNzg4OwogICAgdC5hMTMyID0gNzg4OwogICAgdC5hMTMzID0gNzg4OwogICAgdC5hMTM0ID0gNzg4OwogICAgdC5hMTM1ID0gNzg4OwogICAgdC5hMTM2ID0gNzg4OwogICAgdC5hMTM3ID0gNzg4OwogICAgdC5hMTM4ID0gNzg4OwogICAgdC5hMTM5ID0gNzg4OwogICAgdC5hMTQwID0gNzg4OwogICAgdC5hMTQxID0gNzg4OwogICAgdC5hMTQyID0gNzg4OwogICAgdC5hMTQzID0gNzg4OwogICAgdC5hMTQ0ID0gNzg4OwogICAgdC5hMTQ1ID0gNzg4OwogICAgdC5hMTQ2ID0gNzg4OwogICAgdC5hMTQ3ID0gNzg4OwogICAgdC5hMTQ4ID0gNzg4OwogICAgdC5hMTQ5ID0gNzg4OwogICAgdC5hMTUwID0gNzg4OwogICAgdC5hMTUxID0gNzg4OwogICAgdC5hMTUyID0gNzg4OwogICAgdC5hMTUzID0gNzg4OwogICAgdC5hMTU0ID0gNzg4OwogICAgdC5hMTU1ID0gNzg4OwogICAgdC5hMTU2ID0gNzg4OwogICAgdC5hMTU3ID0gNzg4OwogICAgdC5hMTU4ID0gNzg4OwogICAgdC5hMTU5ID0gNzg4OwogICAgdC5hMTYwID0gODk0OwogICAgdC5hMTYxID0gODM4OwogICAgdC5hMTYzID0gMTAxNjsKICAgIHQuYTE2NCA9IDQ1ODsKICAgIHQuYTE5NiA9IDc0ODsKICAgIHQuYTE2NSA9IDkyNDsKICAgIHQuYTE5MiA9IDc0ODsKICAgIHQuYTE2NiA9IDkxODsKICAgIHQuYTE2NyA9IDkyNzsKICAgIHQuYTE2OCA9IDkyODsKICAgIHQuYTE2OSA9IDkyODsKICAgIHQuYTE3MCA9IDgzNDsKICAgIHQuYTE3MSA9IDg3MzsKICAgIHQuYTE3MiA9IDgyODsKICAgIHQuYTE3MyA9IDkyNDsKICAgIHQuYTE2MiA9IDkyNDsKICAgIHQuYTE3NCA9IDkxNzsKICAgIHQuYTE3NSA9IDkzMDsKICAgIHQuYTE3NiA9IDkzMTsKICAgIHQuYTE3NyA9IDQ2MzsKICAgIHQuYTE3OCA9IDg4MzsKICAgIHQuYTE3OSA9IDgzNjsKICAgIHQuYTE5MyA9IDgzNjsKICAgIHQuYTE4MCA9IDg2NzsKICAgIHQuYTE5OSA9IDg2NzsKICAgIHQuYTE4MSA9IDY5NjsKICAgIHQuYTIwMCA9IDY5NjsKICAgIHQuYTE4MiA9IDg3NDsKICAgIHQuYTIwMSA9IDg3NDsKICAgIHQuYTE4MyA9IDc2MDsKICAgIHQuYTE4NCA9IDk0NjsKICAgIHQuYTE5NyA9IDc3MTsKICAgIHQuYTE4NSA9IDg2NTsKICAgIHQuYTE5NCA9IDc3MTsKICAgIHQuYTE5OCA9IDg4ODsKICAgIHQuYTE4NiA9IDk2NzsKICAgIHQuYTE5NSA9IDg4ODsKICAgIHQuYTE4NyA9IDgzMTsKICAgIHQuYTE4OCA9IDg3MzsKICAgIHQuYTE4OSA9IDkyNzsKICAgIHQuYTE5MCA9IDk3MDsKICAgIHQuYTE5MSA9IDkxODsKICB9KTsKfSk7CmV4cG9ydHMuZ2V0TWV0cmljcyA9IGdldE1ldHJpY3M7CmNvbnN0IGdldEZvbnRCYXNpY01ldHJpY3MgPSAoMCwgX2NvcmVfdXRpbHMuZ2V0TG9va3VwVGFibGVGYWN0b3J5KShmdW5jdGlvbiAodCkgewogIHQuQ291cmllciA9IHsKICAgIGFzY2VudDogNjI5LAogICAgZGVzY2VudDogLTE1NywKICAgIGNhcEhlaWdodDogNTYyLAogICAgeEhlaWdodDogLTQyNgogIH07CiAgdFsiQ291cmllci1Cb2xkIl0gPSB7CiAgICBhc2NlbnQ6IDYyOSwKICAgIGRlc2NlbnQ6IC0xNTcsCiAgICBjYXBIZWlnaHQ6IDU2MiwKICAgIHhIZWlnaHQ6IDQzOQogIH07CiAgdFsiQ291cmllci1PYmxpcXVlIl0gPSB7CiAgICBhc2NlbnQ6IDYyOSwKICAgIGRlc2NlbnQ6IC0xNTcsCiAgICBjYXBIZWlnaHQ6IDU2MiwKICAgIHhIZWlnaHQ6IDQyNgogIH07CiAgdFsiQ291cmllci1Cb2xkT2JsaXF1ZSJdID0gewogICAgYXNjZW50OiA2MjksCiAgICBkZXNjZW50OiAtMTU3LAogICAgY2FwSGVpZ2h0OiA1NjIsCiAgICB4SGVpZ2h0OiA0MjYKICB9OwogIHQuSGVsdmV0aWNhID0gewogICAgYXNjZW50OiA3MTgsCiAgICBkZXNjZW50OiAtMjA3LAogICAgY2FwSGVpZ2h0OiA3MTgsCiAgICB4SGVpZ2h0OiA1MjMKICB9OwogIHRbIkhlbHZldGljYS1Cb2xkIl0gPSB7CiAgICBhc2NlbnQ6IDcxOCwKICAgIGRlc2NlbnQ6IC0yMDcsCiAgICBjYXBIZWlnaHQ6IDcxOCwKICAgIHhIZWlnaHQ6IDUzMgogIH07CiAgdFsiSGVsdmV0aWNhLU9ibGlxdWUiXSA9IHsKICAgIGFzY2VudDogNzE4LAogICAgZGVzY2VudDogLTIwNywKICAgIGNhcEhlaWdodDogNzE4LAogICAgeEhlaWdodDogNTIzCiAgfTsKICB0WyJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiXSA9IHsKICAgIGFzY2VudDogNzE4LAogICAgZGVzY2VudDogLTIwNywKICAgIGNhcEhlaWdodDogNzE4LAogICAgeEhlaWdodDogNTMyCiAgfTsKICB0WyJUaW1lcy1Sb21hbiJdID0gewogICAgYXNjZW50OiA2ODMsCiAgICBkZXNjZW50OiAtMjE3LAogICAgY2FwSGVpZ2h0OiA2NjIsCiAgICB4SGVpZ2h0OiA0NTAKICB9OwogIHRbIlRpbWVzLUJvbGQiXSA9IHsKICAgIGFzY2VudDogNjgzLAogICAgZGVzY2VudDogLTIxNywKICAgIGNhcEhlaWdodDogNjc2LAogICAgeEhlaWdodDogNDYxCiAgfTsKICB0WyJUaW1lcy1JdGFsaWMiXSA9IHsKICAgIGFzY2VudDogNjgzLAogICAgZGVzY2VudDogLTIxNywKICAgIGNhcEhlaWdodDogNjUzLAogICAgeEhlaWdodDogNDQxCiAgfTsKICB0WyJUaW1lcy1Cb2xkSXRhbGljIl0gPSB7CiAgICBhc2NlbnQ6IDY4MywKICAgIGRlc2NlbnQ6IC0yMTcsCiAgICBjYXBIZWlnaHQ6IDY2OSwKICAgIHhIZWlnaHQ6IDQ2MgogIH07CiAgdC5TeW1ib2wgPSB7CiAgICBhc2NlbnQ6IE1hdGguTmFOLAogICAgZGVzY2VudDogTWF0aC5OYU4sCiAgICBjYXBIZWlnaHQ6IE1hdGguTmFOLAogICAgeEhlaWdodDogTWF0aC5OYU4KICB9OwogIHQuWmFwZkRpbmdiYXRzID0gewogICAgYXNjZW50OiBNYXRoLk5hTiwKICAgIGRlc2NlbnQ6IE1hdGguTmFOLAogICAgY2FwSGVpZ2h0OiBNYXRoLk5hTiwKICAgIHhIZWlnaHQ6IE1hdGguTmFOCiAgfTsKfSk7CmV4cG9ydHMuZ2V0Rm9udEJhc2ljTWV0cmljcyA9IGdldEZvbnRCYXNpY01ldHJpY3M7CgovKioqLyB9KSwKLyogMTgxICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMpID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5HbHlmVGFibGUgPSB2b2lkIDA7CmNvbnN0IE9OX0NVUlZFX1BPSU5UID0gMSA8PCAwOwpjb25zdCBYX1NIT1JUX1ZFQ1RPUiA9IDEgPDwgMTsKY29uc3QgWV9TSE9SVF9WRUNUT1IgPSAxIDw8IDI7CmNvbnN0IFJFUEVBVF9GTEFHID0gMSA8PCAzOwpjb25zdCBYX0lTX1NBTUVfT1JfUE9TSVRJVkVfWF9TSE9SVF9WRUNUT1IgPSAxIDw8IDQ7CmNvbnN0IFlfSVNfU0FNRV9PUl9QT1NJVElWRV9ZX1NIT1JUX1ZFQ1RPUiA9IDEgPDwgNTsKY29uc3QgT1ZFUkxBUF9TSU1QTEUgPSAxIDw8IDY7CmNvbnN0IEFSR18xX0FORF8yX0FSRV9XT1JEUyA9IDEgPDwgMDsKY29uc3QgQVJHU19BUkVfWFlfVkFMVUVTID0gMSA8PCAxOwpjb25zdCBXRV9IQVZFX0FfU0NBTEUgPSAxIDw8IDM7CmNvbnN0IE1PUkVfQ09NUE9ORU5UUyA9IDEgPDwgNTsKY29uc3QgV0VfSEFWRV9BTl9YX0FORF9ZX1NDQUxFID0gMSA8PCA2Owpjb25zdCBXRV9IQVZFX0FfVFdPX0JZX1RXTyA9IDEgPDwgNzsKY29uc3QgV0VfSEFWRV9JTlNUUlVDVElPTlMgPSAxIDw8IDg7CmNsYXNzIEdseWZUYWJsZSB7CiAgY29uc3RydWN0b3IoX3JlZikgewogICAgbGV0IHsKICAgICAgZ2x5ZlRhYmxlLAogICAgICBpc0dseXBoTG9jYXRpb25zTG9uZywKICAgICAgbG9jYVRhYmxlLAogICAgICBudW1HbHlwaHMKICAgIH0gPSBfcmVmOwogICAgdGhpcy5nbHlwaHMgPSBbXTsKICAgIGNvbnN0IGxvY2EgPSBuZXcgRGF0YVZpZXcobG9jYVRhYmxlLmJ1ZmZlciwgbG9jYVRhYmxlLmJ5dGVPZmZzZXQsIGxvY2FUYWJsZS5ieXRlTGVuZ3RoKTsKICAgIGNvbnN0IGdseWYgPSBuZXcgRGF0YVZpZXcoZ2x5ZlRhYmxlLmJ1ZmZlciwgZ2x5ZlRhYmxlLmJ5dGVPZmZzZXQsIGdseWZUYWJsZS5ieXRlTGVuZ3RoKTsKICAgIGNvbnN0IG9mZnNldFNpemUgPSBpc0dseXBoTG9jYXRpb25zTG9uZyA/IDQgOiAyOwogICAgbGV0IHByZXYgPSBpc0dseXBoTG9jYXRpb25zTG9uZyA/IGxvY2EuZ2V0VWludDMyKDApIDogMiAqIGxvY2EuZ2V0VWludDE2KDApOwogICAgbGV0IHBvcyA9IDA7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUdseXBoczsgaSsrKSB7CiAgICAgIHBvcyArPSBvZmZzZXRTaXplOwogICAgICBjb25zdCBuZXh0ID0gaXNHbHlwaExvY2F0aW9uc0xvbmcgPyBsb2NhLmdldFVpbnQzMihwb3MpIDogMiAqIGxvY2EuZ2V0VWludDE2KHBvcyk7CiAgICAgIGlmIChuZXh0ID09PSBwcmV2KSB7CiAgICAgICAgdGhpcy5nbHlwaHMucHVzaChuZXcgR2x5cGgoe30pKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBnbHlwaCA9IEdseXBoLnBhcnNlKHByZXYsIGdseWYpOwogICAgICB0aGlzLmdseXBocy5wdXNoKGdseXBoKTsKICAgICAgcHJldiA9IG5leHQ7CiAgICB9CiAgfQogIGdldFNpemUoKSB7CiAgICByZXR1cm4gdGhpcy5nbHlwaHMucmVkdWNlKChhLCBnKSA9PiB7CiAgICAgIGNvbnN0IHNpemUgPSBnLmdldFNpemUoKTsKICAgICAgcmV0dXJuIGEgKyAoc2l6ZSArIDMgJiB+Myk7CiAgICB9LCAwKTsKICB9CiAgd3JpdGUoKSB7CiAgICBjb25zdCB0b3RhbFNpemUgPSB0aGlzLmdldFNpemUoKTsKICAgIGNvbnN0IGdseWZUYWJsZSA9IG5ldyBEYXRhVmlldyhuZXcgQXJyYXlCdWZmZXIodG90YWxTaXplKSk7CiAgICBjb25zdCBpc0xvY2F0aW9uTG9uZyA9IHRvdGFsU2l6ZSA+IDB4MWZmZmU7CiAgICBjb25zdCBvZmZzZXRTaXplID0gaXNMb2NhdGlvbkxvbmcgPyA0IDogMjsKICAgIGNvbnN0IGxvY2FUYWJsZSA9IG5ldyBEYXRhVmlldyhuZXcgQXJyYXlCdWZmZXIoKHRoaXMuZ2x5cGhzLmxlbmd0aCArIDEpICogb2Zmc2V0U2l6ZSkpOwogICAgaWYgKGlzTG9jYXRpb25Mb25nKSB7CiAgICAgIGxvY2FUYWJsZS5zZXRVaW50MzIoMCwgMCk7CiAgICB9IGVsc2UgewogICAgICBsb2NhVGFibGUuc2V0VWludDE2KDAsIDApOwogICAgfQogICAgbGV0IHBvcyA9IDA7CiAgICBsZXQgbG9jYUluZGV4ID0gMDsKICAgIGZvciAoY29uc3QgZ2x5cGggb2YgdGhpcy5nbHlwaHMpIHsKICAgICAgcG9zICs9IGdseXBoLndyaXRlKHBvcywgZ2x5ZlRhYmxlKTsKICAgICAgcG9zID0gcG9zICsgMyAmIH4zOwogICAgICBsb2NhSW5kZXggKz0gb2Zmc2V0U2l6ZTsKICAgICAgaWYgKGlzTG9jYXRpb25Mb25nKSB7CiAgICAgICAgbG9jYVRhYmxlLnNldFVpbnQzMihsb2NhSW5kZXgsIHBvcyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbG9jYVRhYmxlLnNldFVpbnQxNihsb2NhSW5kZXgsIHBvcyA+PiAxKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHsKICAgICAgaXNMb2NhdGlvbkxvbmcsCiAgICAgIGxvY2E6IG5ldyBVaW50OEFycmF5KGxvY2FUYWJsZS5idWZmZXIpLAogICAgICBnbHlmOiBuZXcgVWludDhBcnJheShnbHlmVGFibGUuYnVmZmVyKQogICAgfTsKICB9CiAgc2NhbGUoZmFjdG9ycykgewogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdGhpcy5nbHlwaHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICB0aGlzLmdseXBoc1tpXS5zY2FsZShmYWN0b3JzW2ldKTsKICAgIH0KICB9Cn0KZXhwb3J0cy5HbHlmVGFibGUgPSBHbHlmVGFibGU7CmNsYXNzIEdseXBoIHsKICBjb25zdHJ1Y3RvcihfcmVmMikgewogICAgbGV0IHsKICAgICAgaGVhZGVyID0gbnVsbCwKICAgICAgc2ltcGxlID0gbnVsbCwKICAgICAgY29tcG9zaXRlcyA9IG51bGwKICAgIH0gPSBfcmVmMjsKICAgIHRoaXMuaGVhZGVyID0gaGVhZGVyOwogICAgdGhpcy5zaW1wbGUgPSBzaW1wbGU7CiAgICB0aGlzLmNvbXBvc2l0ZXMgPSBjb21wb3NpdGVzOwogIH0KICBzdGF0aWMgcGFyc2UocG9zLCBnbHlmKSB7CiAgICBjb25zdCBbcmVhZCwgaGVhZGVyXSA9IEdseXBoSGVhZGVyLnBhcnNlKHBvcywgZ2x5Zik7CiAgICBwb3MgKz0gcmVhZDsKICAgIGlmIChoZWFkZXIubnVtYmVyT2ZDb250b3VycyA8IDApIHsKICAgICAgY29uc3QgY29tcG9zaXRlcyA9IFtdOwogICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgIGNvbnN0IFtuLCBjb21wb3NpdGVdID0gQ29tcG9zaXRlR2x5cGgucGFyc2UocG9zLCBnbHlmKTsKICAgICAgICBwb3MgKz0gbjsKICAgICAgICBjb21wb3NpdGVzLnB1c2goY29tcG9zaXRlKTsKICAgICAgICBpZiAoIShjb21wb3NpdGUuZmxhZ3MgJiBNT1JFX0NPTVBPTkVOVFMpKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIG5ldyBHbHlwaCh7CiAgICAgICAgaGVhZGVyLAogICAgICAgIGNvbXBvc2l0ZXMKICAgICAgfSk7CiAgICB9CiAgICBjb25zdCBzaW1wbGUgPSBTaW1wbGVHbHlwaC5wYXJzZShwb3MsIGdseWYsIGhlYWRlci5udW1iZXJPZkNvbnRvdXJzKTsKICAgIHJldHVybiBuZXcgR2x5cGgoewogICAgICBoZWFkZXIsCiAgICAgIHNpbXBsZQogICAgfSk7CiAgfQogIGdldFNpemUoKSB7CiAgICBpZiAoIXRoaXMuaGVhZGVyKSB7CiAgICAgIHJldHVybiAwOwogICAgfQogICAgY29uc3Qgc2l6ZSA9IHRoaXMuc2ltcGxlID8gdGhpcy5zaW1wbGUuZ2V0U2l6ZSgpIDogdGhpcy5jb21wb3NpdGVzLnJlZHVjZSgoYSwgYykgPT4gYSArIGMuZ2V0U2l6ZSgpLCAwKTsKICAgIHJldHVybiB0aGlzLmhlYWRlci5nZXRTaXplKCkgKyBzaXplOwogIH0KICB3cml0ZShwb3MsIGJ1ZikgewogICAgaWYgKCF0aGlzLmhlYWRlcikgewogICAgICByZXR1cm4gMDsKICAgIH0KICAgIGNvbnN0IHNwb3MgPSBwb3M7CiAgICBwb3MgKz0gdGhpcy5oZWFkZXIud3JpdGUocG9zLCBidWYpOwogICAgaWYgKHRoaXMuc2ltcGxlKSB7CiAgICAgIHBvcyArPSB0aGlzLnNpbXBsZS53cml0ZShwb3MsIGJ1Zik7CiAgICB9IGVsc2UgewogICAgICBmb3IgKGNvbnN0IGNvbXBvc2l0ZSBvZiB0aGlzLmNvbXBvc2l0ZXMpIHsKICAgICAgICBwb3MgKz0gY29tcG9zaXRlLndyaXRlKHBvcywgYnVmKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHBvcyAtIHNwb3M7CiAgfQogIHNjYWxlKGZhY3RvcikgewogICAgaWYgKCF0aGlzLmhlYWRlcikgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCB4TWlkZGxlID0gKHRoaXMuaGVhZGVyLnhNaW4gKyB0aGlzLmhlYWRlci54TWF4KSAvIDI7CiAgICB0aGlzLmhlYWRlci5zY2FsZSh4TWlkZGxlLCBmYWN0b3IpOwogICAgaWYgKHRoaXMuc2ltcGxlKSB7CiAgICAgIHRoaXMuc2ltcGxlLnNjYWxlKHhNaWRkbGUsIGZhY3Rvcik7CiAgICB9IGVsc2UgewogICAgICBmb3IgKGNvbnN0IGNvbXBvc2l0ZSBvZiB0aGlzLmNvbXBvc2l0ZXMpIHsKICAgICAgICBjb21wb3NpdGUuc2NhbGUoeE1pZGRsZSwgZmFjdG9yKTsKICAgICAgfQogICAgfQogIH0KfQpjbGFzcyBHbHlwaEhlYWRlciB7CiAgY29uc3RydWN0b3IoX3JlZjMpIHsKICAgIGxldCB7CiAgICAgIG51bWJlck9mQ29udG91cnMsCiAgICAgIHhNaW4sCiAgICAgIHlNaW4sCiAgICAgIHhNYXgsCiAgICAgIHlNYXgKICAgIH0gPSBfcmVmMzsKICAgIHRoaXMubnVtYmVyT2ZDb250b3VycyA9IG51bWJlck9mQ29udG91cnM7CiAgICB0aGlzLnhNaW4gPSB4TWluOwogICAgdGhpcy55TWluID0geU1pbjsKICAgIHRoaXMueE1heCA9IHhNYXg7CiAgICB0aGlzLnlNYXggPSB5TWF4OwogIH0KICBzdGF0aWMgcGFyc2UocG9zLCBnbHlmKSB7CiAgICByZXR1cm4gWzEwLCBuZXcgR2x5cGhIZWFkZXIoewogICAgICBudW1iZXJPZkNvbnRvdXJzOiBnbHlmLmdldEludDE2KHBvcyksCiAgICAgIHhNaW46IGdseWYuZ2V0SW50MTYocG9zICsgMiksCiAgICAgIHlNaW46IGdseWYuZ2V0SW50MTYocG9zICsgNCksCiAgICAgIHhNYXg6IGdseWYuZ2V0SW50MTYocG9zICsgNiksCiAgICAgIHlNYXg6IGdseWYuZ2V0SW50MTYocG9zICsgOCkKICAgIH0pXTsKICB9CiAgZ2V0U2l6ZSgpIHsKICAgIHJldHVybiAxMDsKICB9CiAgd3JpdGUocG9zLCBidWYpIHsKICAgIGJ1Zi5zZXRJbnQxNihwb3MsIHRoaXMubnVtYmVyT2ZDb250b3Vycyk7CiAgICBidWYuc2V0SW50MTYocG9zICsgMiwgdGhpcy54TWluKTsKICAgIGJ1Zi5zZXRJbnQxNihwb3MgKyA0LCB0aGlzLnlNaW4pOwogICAgYnVmLnNldEludDE2KHBvcyArIDYsIHRoaXMueE1heCk7CiAgICBidWYuc2V0SW50MTYocG9zICsgOCwgdGhpcy55TWF4KTsKICAgIHJldHVybiAxMDsKICB9CiAgc2NhbGUoeCwgZmFjdG9yKSB7CiAgICB0aGlzLnhNaW4gPSBNYXRoLnJvdW5kKHggKyAodGhpcy54TWluIC0geCkgKiBmYWN0b3IpOwogICAgdGhpcy54TWF4ID0gTWF0aC5yb3VuZCh4ICsgKHRoaXMueE1heCAtIHgpICogZmFjdG9yKTsKICB9Cn0KY2xhc3MgQ29udG91ciB7CiAgY29uc3RydWN0b3IoX3JlZjQpIHsKICAgIGxldCB7CiAgICAgIGZsYWdzLAogICAgICB4Q29vcmRpbmF0ZXMsCiAgICAgIHlDb29yZGluYXRlcwogICAgfSA9IF9yZWY0OwogICAgdGhpcy54Q29vcmRpbmF0ZXMgPSB4Q29vcmRpbmF0ZXM7CiAgICB0aGlzLnlDb29yZGluYXRlcyA9IHlDb29yZGluYXRlczsKICAgIHRoaXMuZmxhZ3MgPSBmbGFnczsKICB9Cn0KY2xhc3MgU2ltcGxlR2x5cGggewogIGNvbnN0cnVjdG9yKF9yZWY1KSB7CiAgICBsZXQgewogICAgICBjb250b3VycywKICAgICAgaW5zdHJ1Y3Rpb25zCiAgICB9ID0gX3JlZjU7CiAgICB0aGlzLmNvbnRvdXJzID0gY29udG91cnM7CiAgICB0aGlzLmluc3RydWN0aW9ucyA9IGluc3RydWN0aW9uczsKICB9CiAgc3RhdGljIHBhcnNlKHBvcywgZ2x5ZiwgbnVtYmVyT2ZDb250b3VycykgewogICAgY29uc3QgZW5kUHRzT2ZDb250b3VycyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZkNvbnRvdXJzOyBpKyspIHsKICAgICAgY29uc3QgZW5kUHQgPSBnbHlmLmdldFVpbnQxNihwb3MpOwogICAgICBwb3MgKz0gMjsKICAgICAgZW5kUHRzT2ZDb250b3Vycy5wdXNoKGVuZFB0KTsKICAgIH0KICAgIGNvbnN0IG51bWJlck9mUHQgPSBlbmRQdHNPZkNvbnRvdXJzW251bWJlck9mQ29udG91cnMgLSAxXSArIDE7CiAgICBjb25zdCBpbnN0cnVjdGlvbkxlbmd0aCA9IGdseWYuZ2V0VWludDE2KHBvcyk7CiAgICBwb3MgKz0gMjsKICAgIGNvbnN0IGluc3RydWN0aW9ucyA9IG5ldyBVaW50OEFycmF5KGdseWYpLnNsaWNlKHBvcywgcG9zICsgaW5zdHJ1Y3Rpb25MZW5ndGgpOwogICAgcG9zICs9IGluc3RydWN0aW9uTGVuZ3RoOwogICAgY29uc3QgZmxhZ3MgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZQdDsgcG9zKyssIGkrKykgewogICAgICBsZXQgZmxhZyA9IGdseWYuZ2V0VWludDgocG9zKTsKICAgICAgZmxhZ3MucHVzaChmbGFnKTsKICAgICAgaWYgKGZsYWcgJiBSRVBFQVRfRkxBRykgewogICAgICAgIGNvbnN0IGNvdW50ID0gZ2x5Zi5nZXRVaW50OCgrK3Bvcyk7CiAgICAgICAgZmxhZyBePSBSRVBFQVRfRkxBRzsKICAgICAgICBmb3IgKGxldCBtID0gMDsgbSA8IGNvdW50OyBtKyspIHsKICAgICAgICAgIGZsYWdzLnB1c2goZmxhZyk7CiAgICAgICAgfQogICAgICAgIGkgKz0gY291bnQ7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGFsbFhDb29yZGluYXRlcyA9IFtdOwogICAgbGV0IHhDb29yZGluYXRlcyA9IFtdOwogICAgbGV0IHlDb29yZGluYXRlcyA9IFtdOwogICAgbGV0IHBvaW50RmxhZ3MgPSBbXTsKICAgIGNvbnN0IGNvbnRvdXJzID0gW107CiAgICBsZXQgZW5kUHRzT2ZDb250b3Vyc0luZGV4ID0gMDsKICAgIGxldCBsYXN0Q29vcmRpbmF0ZSA9IDA7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlck9mUHQ7IGkrKykgewogICAgICBjb25zdCBmbGFnID0gZmxhZ3NbaV07CiAgICAgIGlmIChmbGFnICYgWF9TSE9SVF9WRUNUT1IpIHsKICAgICAgICBjb25zdCB4ID0gZ2x5Zi5nZXRVaW50OChwb3MrKyk7CiAgICAgICAgbGFzdENvb3JkaW5hdGUgKz0gZmxhZyAmIFhfSVNfU0FNRV9PUl9QT1NJVElWRV9YX1NIT1JUX1ZFQ1RPUiA/IHggOiAteDsKICAgICAgICB4Q29vcmRpbmF0ZXMucHVzaChsYXN0Q29vcmRpbmF0ZSk7CiAgICAgIH0gZWxzZSBpZiAoZmxhZyAmIFhfSVNfU0FNRV9PUl9QT1NJVElWRV9YX1NIT1JUX1ZFQ1RPUikgewogICAgICAgIHhDb29yZGluYXRlcy5wdXNoKGxhc3RDb29yZGluYXRlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBsYXN0Q29vcmRpbmF0ZSArPSBnbHlmLmdldEludDE2KHBvcyk7CiAgICAgICAgcG9zICs9IDI7CiAgICAgICAgeENvb3JkaW5hdGVzLnB1c2gobGFzdENvb3JkaW5hdGUpOwogICAgICB9CiAgICAgIGlmIChlbmRQdHNPZkNvbnRvdXJzW2VuZFB0c09mQ29udG91cnNJbmRleF0gPT09IGkpIHsKICAgICAgICBlbmRQdHNPZkNvbnRvdXJzSW5kZXgrKzsKICAgICAgICBhbGxYQ29vcmRpbmF0ZXMucHVzaCh4Q29vcmRpbmF0ZXMpOwogICAgICAgIHhDb29yZGluYXRlcyA9IFtdOwogICAgICB9CiAgICB9CiAgICBsYXN0Q29vcmRpbmF0ZSA9IDA7CiAgICBlbmRQdHNPZkNvbnRvdXJzSW5kZXggPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZlB0OyBpKyspIHsKICAgICAgY29uc3QgZmxhZyA9IGZsYWdzW2ldOwogICAgICBpZiAoZmxhZyAmIFlfU0hPUlRfVkVDVE9SKSB7CiAgICAgICAgY29uc3QgeSA9IGdseWYuZ2V0VWludDgocG9zKyspOwogICAgICAgIGxhc3RDb29yZGluYXRlICs9IGZsYWcgJiBZX0lTX1NBTUVfT1JfUE9TSVRJVkVfWV9TSE9SVF9WRUNUT1IgPyB5IDogLXk7CiAgICAgICAgeUNvb3JkaW5hdGVzLnB1c2gobGFzdENvb3JkaW5hdGUpOwogICAgICB9IGVsc2UgaWYgKGZsYWcgJiBZX0lTX1NBTUVfT1JfUE9TSVRJVkVfWV9TSE9SVF9WRUNUT1IpIHsKICAgICAgICB5Q29vcmRpbmF0ZXMucHVzaChsYXN0Q29vcmRpbmF0ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbGFzdENvb3JkaW5hdGUgKz0gZ2x5Zi5nZXRJbnQxNihwb3MpOwogICAgICAgIHBvcyArPSAyOwogICAgICAgIHlDb29yZGluYXRlcy5wdXNoKGxhc3RDb29yZGluYXRlKTsKICAgICAgfQogICAgICBwb2ludEZsYWdzLnB1c2goZmxhZyAmIE9OX0NVUlZFX1BPSU5UIHwgZmxhZyAmIE9WRVJMQVBfU0lNUExFKTsKICAgICAgaWYgKGVuZFB0c09mQ29udG91cnNbZW5kUHRzT2ZDb250b3Vyc0luZGV4XSA9PT0gaSkgewogICAgICAgIHhDb29yZGluYXRlcyA9IGFsbFhDb29yZGluYXRlc1tlbmRQdHNPZkNvbnRvdXJzSW5kZXhdOwogICAgICAgIGVuZFB0c09mQ29udG91cnNJbmRleCsrOwogICAgICAgIGNvbnRvdXJzLnB1c2gobmV3IENvbnRvdXIoewogICAgICAgICAgZmxhZ3M6IHBvaW50RmxhZ3MsCiAgICAgICAgICB4Q29vcmRpbmF0ZXMsCiAgICAgICAgICB5Q29vcmRpbmF0ZXMKICAgICAgICB9KSk7CiAgICAgICAgeUNvb3JkaW5hdGVzID0gW107CiAgICAgICAgcG9pbnRGbGFncyA9IFtdOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbmV3IFNpbXBsZUdseXBoKHsKICAgICAgY29udG91cnMsCiAgICAgIGluc3RydWN0aW9ucwogICAgfSk7CiAgfQogIGdldFNpemUoKSB7CiAgICBsZXQgc2l6ZSA9IHRoaXMuY29udG91cnMubGVuZ3RoICogMiArIDIgKyB0aGlzLmluc3RydWN0aW9ucy5sZW5ndGg7CiAgICBsZXQgbGFzdFggPSAwOwogICAgbGV0IGxhc3RZID0gMDsKICAgIGZvciAoY29uc3QgY29udG91ciBvZiB0aGlzLmNvbnRvdXJzKSB7CiAgICAgIHNpemUgKz0gY29udG91ci5mbGFncy5sZW5ndGg7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGNvbnRvdXIueENvb3JkaW5hdGVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb25zdCB4ID0gY29udG91ci54Q29vcmRpbmF0ZXNbaV07CiAgICAgICAgY29uc3QgeSA9IGNvbnRvdXIueUNvb3JkaW5hdGVzW2ldOwogICAgICAgIGxldCBhYnMgPSBNYXRoLmFicyh4IC0gbGFzdFgpOwogICAgICAgIGlmIChhYnMgPiAyNTUpIHsKICAgICAgICAgIHNpemUgKz0gMjsKICAgICAgICB9IGVsc2UgaWYgKGFicyA+IDApIHsKICAgICAgICAgIHNpemUgKz0gMTsKICAgICAgICB9CiAgICAgICAgbGFzdFggPSB4OwogICAgICAgIGFicyA9IE1hdGguYWJzKHkgLSBsYXN0WSk7CiAgICAgICAgaWYgKGFicyA+IDI1NSkgewogICAgICAgICAgc2l6ZSArPSAyOwogICAgICAgIH0gZWxzZSBpZiAoYWJzID4gMCkgewogICAgICAgICAgc2l6ZSArPSAxOwogICAgICAgIH0KICAgICAgICBsYXN0WSA9IHk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaXplOwogIH0KICB3cml0ZShwb3MsIGJ1ZikgewogICAgY29uc3Qgc3BvcyA9IHBvczsKICAgIGNvbnN0IHhDb29yZGluYXRlcyA9IFtdOwogICAgY29uc3QgeUNvb3JkaW5hdGVzID0gW107CiAgICBjb25zdCBmbGFncyA9IFtdOwogICAgbGV0IGxhc3RYID0gMDsKICAgIGxldCBsYXN0WSA9IDA7CiAgICBmb3IgKGNvbnN0IGNvbnRvdXIgb2YgdGhpcy5jb250b3VycykgewogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBjb250b3VyLnhDb29yZGluYXRlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgbGV0IGZsYWcgPSBjb250b3VyLmZsYWdzW2ldOwogICAgICAgIGNvbnN0IHggPSBjb250b3VyLnhDb29yZGluYXRlc1tpXTsKICAgICAgICBsZXQgZGVsdGEgPSB4IC0gbGFzdFg7CiAgICAgICAgaWYgKGRlbHRhID09PSAwKSB7CiAgICAgICAgICBmbGFnIHw9IFhfSVNfU0FNRV9PUl9QT1NJVElWRV9YX1NIT1JUX1ZFQ1RPUjsKICAgICAgICAgIHhDb29yZGluYXRlcy5wdXNoKDApOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb25zdCBhYnMgPSBNYXRoLmFicyhkZWx0YSk7CiAgICAgICAgICBpZiAoYWJzIDw9IDI1NSkgewogICAgICAgICAgICBmbGFnIHw9IGRlbHRhID49IDAgPyBYX1NIT1JUX1ZFQ1RPUiB8IFhfSVNfU0FNRV9PUl9QT1NJVElWRV9YX1NIT1JUX1ZFQ1RPUiA6IFhfU0hPUlRfVkVDVE9SOwogICAgICAgICAgICB4Q29vcmRpbmF0ZXMucHVzaChhYnMpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgeENvb3JkaW5hdGVzLnB1c2goZGVsdGEpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBsYXN0WCA9IHg7CiAgICAgICAgY29uc3QgeSA9IGNvbnRvdXIueUNvb3JkaW5hdGVzW2ldOwogICAgICAgIGRlbHRhID0geSAtIGxhc3RZOwogICAgICAgIGlmIChkZWx0YSA9PT0gMCkgewogICAgICAgICAgZmxhZyB8PSBZX0lTX1NBTUVfT1JfUE9TSVRJVkVfWV9TSE9SVF9WRUNUT1I7CiAgICAgICAgICB5Q29vcmRpbmF0ZXMucHVzaCgwKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgYWJzID0gTWF0aC5hYnMoZGVsdGEpOwogICAgICAgICAgaWYgKGFicyA8PSAyNTUpIHsKICAgICAgICAgICAgZmxhZyB8PSBkZWx0YSA+PSAwID8gWV9TSE9SVF9WRUNUT1IgfCBZX0lTX1NBTUVfT1JfUE9TSVRJVkVfWV9TSE9SVF9WRUNUT1IgOiBZX1NIT1JUX1ZFQ1RPUjsKICAgICAgICAgICAgeUNvb3JkaW5hdGVzLnB1c2goYWJzKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHlDb29yZGluYXRlcy5wdXNoKGRlbHRhKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbGFzdFkgPSB5OwogICAgICAgIGZsYWdzLnB1c2goZmxhZyk7CiAgICAgIH0KICAgICAgYnVmLnNldFVpbnQxNihwb3MsIHhDb29yZGluYXRlcy5sZW5ndGggLSAxKTsKICAgICAgcG9zICs9IDI7CiAgICB9CiAgICBidWYuc2V0VWludDE2KHBvcywgdGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoKTsKICAgIHBvcyArPSAyOwogICAgaWYgKHRoaXMuaW5zdHJ1Y3Rpb25zLmxlbmd0aCkgewogICAgICBuZXcgVWludDhBcnJheShidWYuYnVmZmVyLCAwLCBidWYuYnVmZmVyLmJ5dGVMZW5ndGgpLnNldCh0aGlzLmluc3RydWN0aW9ucywgcG9zKTsKICAgICAgcG9zICs9IHRoaXMuaW5zdHJ1Y3Rpb25zLmxlbmd0aDsKICAgIH0KICAgIGZvciAoY29uc3QgZmxhZyBvZiBmbGFncykgewogICAgICBidWYuc2V0VWludDgocG9zKyssIGZsYWcpOwogICAgfQogICAgZm9yIChsZXQgaSA9IDAsIGlpID0geENvb3JkaW5hdGVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgeCA9IHhDb29yZGluYXRlc1tpXTsKICAgICAgY29uc3QgZmxhZyA9IGZsYWdzW2ldOwogICAgICBpZiAoZmxhZyAmIFhfU0hPUlRfVkVDVE9SKSB7CiAgICAgICAgYnVmLnNldFVpbnQ4KHBvcysrLCB4KTsKICAgICAgfSBlbHNlIGlmICghKGZsYWcgJiBYX0lTX1NBTUVfT1JfUE9TSVRJVkVfWF9TSE9SVF9WRUNUT1IpKSB7CiAgICAgICAgYnVmLnNldEludDE2KHBvcywgeCk7CiAgICAgICAgcG9zICs9IDI7CiAgICAgIH0KICAgIH0KICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHlDb29yZGluYXRlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IHkgPSB5Q29vcmRpbmF0ZXNbaV07CiAgICAgIGNvbnN0IGZsYWcgPSBmbGFnc1tpXTsKICAgICAgaWYgKGZsYWcgJiBZX1NIT1JUX1ZFQ1RPUikgewogICAgICAgIGJ1Zi5zZXRVaW50OChwb3MrKywgeSk7CiAgICAgIH0gZWxzZSBpZiAoIShmbGFnICYgWV9JU19TQU1FX09SX1BPU0lUSVZFX1lfU0hPUlRfVkVDVE9SKSkgewogICAgICAgIGJ1Zi5zZXRJbnQxNihwb3MsIHkpOwogICAgICAgIHBvcyArPSAyOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcG9zIC0gc3BvczsKICB9CiAgc2NhbGUoeCwgZmFjdG9yKSB7CiAgICBmb3IgKGNvbnN0IGNvbnRvdXIgb2YgdGhpcy5jb250b3VycykgewogICAgICBpZiAoY29udG91ci54Q29vcmRpbmF0ZXMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gY29udG91ci54Q29vcmRpbmF0ZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnRvdXIueENvb3JkaW5hdGVzW2ldID0gTWF0aC5yb3VuZCh4ICsgKGNvbnRvdXIueENvb3JkaW5hdGVzW2ldIC0geCkgKiBmYWN0b3IpOwogICAgICB9CiAgICB9CiAgfQp9CmNsYXNzIENvbXBvc2l0ZUdseXBoIHsKICBjb25zdHJ1Y3RvcihfcmVmNikgewogICAgbGV0IHsKICAgICAgZmxhZ3MsCiAgICAgIGdseXBoSW5kZXgsCiAgICAgIGFyZ3VtZW50MSwKICAgICAgYXJndW1lbnQyLAogICAgICB0cmFuc2YsCiAgICAgIGluc3RydWN0aW9ucwogICAgfSA9IF9yZWY2OwogICAgdGhpcy5mbGFncyA9IGZsYWdzOwogICAgdGhpcy5nbHlwaEluZGV4ID0gZ2x5cGhJbmRleDsKICAgIHRoaXMuYXJndW1lbnQxID0gYXJndW1lbnQxOwogICAgdGhpcy5hcmd1bWVudDIgPSBhcmd1bWVudDI7CiAgICB0aGlzLnRyYW5zZiA9IHRyYW5zZjsKICAgIHRoaXMuaW5zdHJ1Y3Rpb25zID0gaW5zdHJ1Y3Rpb25zOwogIH0KICBzdGF0aWMgcGFyc2UocG9zLCBnbHlmKSB7CiAgICBjb25zdCBzcG9zID0gcG9zOwogICAgY29uc3QgdHJhbnNmID0gW107CiAgICBsZXQgZmxhZ3MgPSBnbHlmLmdldFVpbnQxNihwb3MpOwogICAgY29uc3QgZ2x5cGhJbmRleCA9IGdseWYuZ2V0VWludDE2KHBvcyArIDIpOwogICAgcG9zICs9IDQ7CiAgICBsZXQgYXJndW1lbnQxLCBhcmd1bWVudDI7CiAgICBpZiAoZmxhZ3MgJiBBUkdfMV9BTkRfMl9BUkVfV09SRFMpIHsKICAgICAgaWYgKGZsYWdzICYgQVJHU19BUkVfWFlfVkFMVUVTKSB7CiAgICAgICAgYXJndW1lbnQxID0gZ2x5Zi5nZXRJbnQxNihwb3MpOwogICAgICAgIGFyZ3VtZW50MiA9IGdseWYuZ2V0SW50MTYocG9zICsgMik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYXJndW1lbnQxID0gZ2x5Zi5nZXRVaW50MTYocG9zKTsKICAgICAgICBhcmd1bWVudDIgPSBnbHlmLmdldFVpbnQxNihwb3MgKyAyKTsKICAgICAgfQogICAgICBwb3MgKz0gNDsKICAgICAgZmxhZ3MgXj0gQVJHXzFfQU5EXzJfQVJFX1dPUkRTOwogICAgfSBlbHNlIHsKICAgICAgaWYgKGZsYWdzICYgQVJHU19BUkVfWFlfVkFMVUVTKSB7CiAgICAgICAgYXJndW1lbnQxID0gZ2x5Zi5nZXRJbnQ4KHBvcyk7CiAgICAgICAgYXJndW1lbnQyID0gZ2x5Zi5nZXRJbnQ4KHBvcyArIDEpOwogICAgICB9IGVsc2UgewogICAgICAgIGFyZ3VtZW50MSA9IGdseWYuZ2V0VWludDgocG9zKTsKICAgICAgICBhcmd1bWVudDIgPSBnbHlmLmdldFVpbnQ4KHBvcyArIDEpOwogICAgICB9CiAgICAgIHBvcyArPSAyOwogICAgfQogICAgaWYgKGZsYWdzICYgV0VfSEFWRV9BX1NDQUxFKSB7CiAgICAgIHRyYW5zZi5wdXNoKGdseWYuZ2V0VWludDE2KHBvcykpOwogICAgICBwb3MgKz0gMjsKICAgIH0gZWxzZSBpZiAoZmxhZ3MgJiBXRV9IQVZFX0FOX1hfQU5EX1lfU0NBTEUpIHsKICAgICAgdHJhbnNmLnB1c2goZ2x5Zi5nZXRVaW50MTYocG9zKSwgZ2x5Zi5nZXRVaW50MTYocG9zICsgMikpOwogICAgICBwb3MgKz0gNDsKICAgIH0gZWxzZSBpZiAoZmxhZ3MgJiBXRV9IQVZFX0FfVFdPX0JZX1RXTykgewogICAgICB0cmFuc2YucHVzaChnbHlmLmdldFVpbnQxNihwb3MpLCBnbHlmLmdldFVpbnQxNihwb3MgKyAyKSwgZ2x5Zi5nZXRVaW50MTYocG9zICsgNCksIGdseWYuZ2V0VWludDE2KHBvcyArIDYpKTsKICAgICAgcG9zICs9IDg7CiAgICB9CiAgICBsZXQgaW5zdHJ1Y3Rpb25zID0gbnVsbDsKICAgIGlmIChmbGFncyAmIFdFX0hBVkVfSU5TVFJVQ1RJT05TKSB7CiAgICAgIGNvbnN0IGluc3RydWN0aW9uTGVuZ3RoID0gZ2x5Zi5nZXRVaW50MTYocG9zKTsKICAgICAgcG9zICs9IDI7CiAgICAgIGluc3RydWN0aW9ucyA9IG5ldyBVaW50OEFycmF5KGdseWYpLnNsaWNlKHBvcywgcG9zICsgaW5zdHJ1Y3Rpb25MZW5ndGgpOwogICAgICBwb3MgKz0gaW5zdHJ1Y3Rpb25MZW5ndGg7CiAgICB9CiAgICByZXR1cm4gW3BvcyAtIHNwb3MsIG5ldyBDb21wb3NpdGVHbHlwaCh7CiAgICAgIGZsYWdzLAogICAgICBnbHlwaEluZGV4LAogICAgICBhcmd1bWVudDEsCiAgICAgIGFyZ3VtZW50MiwKICAgICAgdHJhbnNmLAogICAgICBpbnN0cnVjdGlvbnMKICAgIH0pXTsKICB9CiAgZ2V0U2l6ZSgpIHsKICAgIGxldCBzaXplID0gMiArIDIgKyB0aGlzLnRyYW5zZi5sZW5ndGggKiAyOwogICAgaWYgKHRoaXMuZmxhZ3MgJiBXRV9IQVZFX0lOU1RSVUNUSU9OUykgewogICAgICBzaXplICs9IDIgKyB0aGlzLmluc3RydWN0aW9ucy5sZW5ndGg7CiAgICB9CiAgICBzaXplICs9IDI7CiAgICBpZiAodGhpcy5mbGFncyAmIDIpIHsKICAgICAgaWYgKCEodGhpcy5hcmd1bWVudDEgPj0gLTEyOCAmJiB0aGlzLmFyZ3VtZW50MSA8PSAxMjcgJiYgdGhpcy5hcmd1bWVudDIgPj0gLTEyOCAmJiB0aGlzLmFyZ3VtZW50MiA8PSAxMjcpKSB7CiAgICAgICAgc2l6ZSArPSAyOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBpZiAoISh0aGlzLmFyZ3VtZW50MSA+PSAwICYmIHRoaXMuYXJndW1lbnQxIDw9IDI1NSAmJiB0aGlzLmFyZ3VtZW50MiA+PSAwICYmIHRoaXMuYXJndW1lbnQyIDw9IDI1NSkpIHsKICAgICAgICBzaXplICs9IDI7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaXplOwogIH0KICB3cml0ZShwb3MsIGJ1ZikgewogICAgY29uc3Qgc3BvcyA9IHBvczsKICAgIGlmICh0aGlzLmZsYWdzICYgQVJHU19BUkVfWFlfVkFMVUVTKSB7CiAgICAgIGlmICghKHRoaXMuYXJndW1lbnQxID49IC0xMjggJiYgdGhpcy5hcmd1bWVudDEgPD0gMTI3ICYmIHRoaXMuYXJndW1lbnQyID49IC0xMjggJiYgdGhpcy5hcmd1bWVudDIgPD0gMTI3KSkgewogICAgICAgIHRoaXMuZmxhZ3MgfD0gQVJHXzFfQU5EXzJfQVJFX1dPUkRTOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBpZiAoISh0aGlzLmFyZ3VtZW50MSA+PSAwICYmIHRoaXMuYXJndW1lbnQxIDw9IDI1NSAmJiB0aGlzLmFyZ3VtZW50MiA+PSAwICYmIHRoaXMuYXJndW1lbnQyIDw9IDI1NSkpIHsKICAgICAgICB0aGlzLmZsYWdzIHw9IEFSR18xX0FORF8yX0FSRV9XT1JEUzsKICAgICAgfQogICAgfQogICAgYnVmLnNldFVpbnQxNihwb3MsIHRoaXMuZmxhZ3MpOwogICAgYnVmLnNldFVpbnQxNihwb3MgKyAyLCB0aGlzLmdseXBoSW5kZXgpOwogICAgcG9zICs9IDQ7CiAgICBpZiAodGhpcy5mbGFncyAmIEFSR18xX0FORF8yX0FSRV9XT1JEUykgewogICAgICBpZiAodGhpcy5mbGFncyAmIEFSR1NfQVJFX1hZX1ZBTFVFUykgewogICAgICAgIGJ1Zi5zZXRJbnQxNihwb3MsIHRoaXMuYXJndW1lbnQxKTsKICAgICAgICBidWYuc2V0SW50MTYocG9zICsgMiwgdGhpcy5hcmd1bWVudDIpOwogICAgICB9IGVsc2UgewogICAgICAgIGJ1Zi5zZXRVaW50MTYocG9zLCB0aGlzLmFyZ3VtZW50MSk7CiAgICAgICAgYnVmLnNldFVpbnQxNihwb3MgKyAyLCB0aGlzLmFyZ3VtZW50Mik7CiAgICAgIH0KICAgICAgcG9zICs9IDQ7CiAgICB9IGVsc2UgewogICAgICBidWYuc2V0VWludDgocG9zLCB0aGlzLmFyZ3VtZW50MSk7CiAgICAgIGJ1Zi5zZXRVaW50OChwb3MgKyAxLCB0aGlzLmFyZ3VtZW50Mik7CiAgICAgIHBvcyArPSAyOwogICAgfQogICAgaWYgKHRoaXMuZmxhZ3MgJiBXRV9IQVZFX0lOU1RSVUNUSU9OUykgewogICAgICBidWYuc2V0VWludDE2KHBvcywgdGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoKTsKICAgICAgcG9zICs9IDI7CiAgICAgIGlmICh0aGlzLmluc3RydWN0aW9ucy5sZW5ndGgpIHsKICAgICAgICBuZXcgVWludDhBcnJheShidWYuYnVmZmVyLCAwLCBidWYuYnVmZmVyLmJ5dGVMZW5ndGgpLnNldCh0aGlzLmluc3RydWN0aW9ucywgcG9zKTsKICAgICAgICBwb3MgKz0gdGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcG9zIC0gc3BvczsKICB9CiAgc2NhbGUoeCwgZmFjdG9yKSB7fQp9CgovKioqLyB9KSwKLyogMTgyICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5PcGVuVHlwZUZpbGVCdWlsZGVyID0gdm9pZCAwOwp2YXIgX2NvcmVfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzOSk7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CmZ1bmN0aW9uIHdyaXRlSW50MTYoZGVzdCwgb2Zmc2V0LCBudW0pIHsKICBkZXN0W29mZnNldF0gPSBudW0gPj4gOCAmIDB4ZmY7CiAgZGVzdFtvZmZzZXQgKyAxXSA9IG51bSAmIDB4ZmY7Cn0KZnVuY3Rpb24gd3JpdGVJbnQzMihkZXN0LCBvZmZzZXQsIG51bSkgewogIGRlc3Rbb2Zmc2V0XSA9IG51bSA+PiAyNCAmIDB4ZmY7CiAgZGVzdFtvZmZzZXQgKyAxXSA9IG51bSA+PiAxNiAmIDB4ZmY7CiAgZGVzdFtvZmZzZXQgKyAyXSA9IG51bSA+PiA4ICYgMHhmZjsKICBkZXN0W29mZnNldCArIDNdID0gbnVtICYgMHhmZjsKfQpmdW5jdGlvbiB3cml0ZURhdGEoZGVzdCwgb2Zmc2V0LCBkYXRhKSB7CiAgaWYgKGRhdGEgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7CiAgICBkZXN0LnNldChkYXRhLCBvZmZzZXQpOwogIH0gZWxzZSBpZiAodHlwZW9mIGRhdGEgPT09ICJzdHJpbmciKSB7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBkYXRhLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgZGVzdFtvZmZzZXQrK10gPSBkYXRhLmNoYXJDb2RlQXQoaSkgJiAweGZmOwogICAgfQogIH0gZWxzZSB7CiAgICBmb3IgKGNvbnN0IG51bSBvZiBkYXRhKSB7CiAgICAgIGRlc3Rbb2Zmc2V0KytdID0gbnVtICYgMHhmZjsKICAgIH0KICB9Cn0KY29uc3QgT1RGX0hFQURFUl9TSVpFID0gMTI7CmNvbnN0IE9URl9UQUJMRV9FTlRSWV9TSVpFID0gMTY7CmNsYXNzIE9wZW5UeXBlRmlsZUJ1aWxkZXIgewogIGNvbnN0cnVjdG9yKHNmbnQpIHsKICAgIHRoaXMuc2ZudCA9IHNmbnQ7CiAgICB0aGlzLnRhYmxlcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgfQogIHN0YXRpYyBnZXRTZWFyY2hQYXJhbXMoZW50cmllc0NvdW50LCBlbnRyeVNpemUpIHsKICAgIGxldCBtYXhQb3dlcjIgPSAxLAogICAgICBsb2cyID0gMDsKICAgIHdoaWxlICgobWF4UG93ZXIyIF4gZW50cmllc0NvdW50KSA+IG1heFBvd2VyMikgewogICAgICBtYXhQb3dlcjIgPDw9IDE7CiAgICAgIGxvZzIrKzsKICAgIH0KICAgIGNvbnN0IHNlYXJjaFJhbmdlID0gbWF4UG93ZXIyICogZW50cnlTaXplOwogICAgcmV0dXJuIHsKICAgICAgcmFuZ2U6IHNlYXJjaFJhbmdlLAogICAgICBlbnRyeTogbG9nMiwKICAgICAgcmFuZ2VTaGlmdDogZW50cnlTaXplICogZW50cmllc0NvdW50IC0gc2VhcmNoUmFuZ2UKICAgIH07CiAgfQogIHRvQXJyYXkoKSB7CiAgICBsZXQgc2ZudCA9IHRoaXMuc2ZudDsKICAgIGNvbnN0IHRhYmxlcyA9IHRoaXMudGFibGVzOwogICAgY29uc3QgdGFibGVzTmFtZXMgPSBPYmplY3Qua2V5cyh0YWJsZXMpOwogICAgdGFibGVzTmFtZXMuc29ydCgpOwogICAgY29uc3QgbnVtVGFibGVzID0gdGFibGVzTmFtZXMubGVuZ3RoOwogICAgbGV0IGksIGosIGpqLCB0YWJsZSwgdGFibGVOYW1lOwogICAgbGV0IG9mZnNldCA9IE9URl9IRUFERVJfU0laRSArIG51bVRhYmxlcyAqIE9URl9UQUJMRV9FTlRSWV9TSVpFOwogICAgY29uc3QgdGFibGVPZmZzZXRzID0gW29mZnNldF07CiAgICBmb3IgKGkgPSAwOyBpIDwgbnVtVGFibGVzOyBpKyspIHsKICAgICAgdGFibGUgPSB0YWJsZXNbdGFibGVzTmFtZXNbaV1dOwogICAgICBjb25zdCBwYWRkZWRMZW5ndGggPSAodGFibGUubGVuZ3RoICsgMyAmIH4zKSA+Pj4gMDsKICAgICAgb2Zmc2V0ICs9IHBhZGRlZExlbmd0aDsKICAgICAgdGFibGVPZmZzZXRzLnB1c2gob2Zmc2V0KTsKICAgIH0KICAgIGNvbnN0IGZpbGUgPSBuZXcgVWludDhBcnJheShvZmZzZXQpOwogICAgZm9yIChpID0gMDsgaSA8IG51bVRhYmxlczsgaSsrKSB7CiAgICAgIHRhYmxlID0gdGFibGVzW3RhYmxlc05hbWVzW2ldXTsKICAgICAgd3JpdGVEYXRhKGZpbGUsIHRhYmxlT2Zmc2V0c1tpXSwgdGFibGUpOwogICAgfQogICAgaWYgKHNmbnQgPT09ICJ0cnVlIikgewogICAgICBzZm50ID0gKDAsIF91dGlsLnN0cmluZzMyKSgweDAwMDEwMDAwKTsKICAgIH0KICAgIGZpbGVbMF0gPSBzZm50LmNoYXJDb2RlQXQoMCkgJiAweGZmOwogICAgZmlsZVsxXSA9IHNmbnQuY2hhckNvZGVBdCgxKSAmIDB4ZmY7CiAgICBmaWxlWzJdID0gc2ZudC5jaGFyQ29kZUF0KDIpICYgMHhmZjsKICAgIGZpbGVbM10gPSBzZm50LmNoYXJDb2RlQXQoMykgJiAweGZmOwogICAgd3JpdGVJbnQxNihmaWxlLCA0LCBudW1UYWJsZXMpOwogICAgY29uc3Qgc2VhcmNoUGFyYW1zID0gT3BlblR5cGVGaWxlQnVpbGRlci5nZXRTZWFyY2hQYXJhbXMobnVtVGFibGVzLCAxNik7CiAgICB3cml0ZUludDE2KGZpbGUsIDYsIHNlYXJjaFBhcmFtcy5yYW5nZSk7CiAgICB3cml0ZUludDE2KGZpbGUsIDgsIHNlYXJjaFBhcmFtcy5lbnRyeSk7CiAgICB3cml0ZUludDE2KGZpbGUsIDEwLCBzZWFyY2hQYXJhbXMucmFuZ2VTaGlmdCk7CiAgICBvZmZzZXQgPSBPVEZfSEVBREVSX1NJWkU7CiAgICBmb3IgKGkgPSAwOyBpIDwgbnVtVGFibGVzOyBpKyspIHsKICAgICAgdGFibGVOYW1lID0gdGFibGVzTmFtZXNbaV07CiAgICAgIGZpbGVbb2Zmc2V0XSA9IHRhYmxlTmFtZS5jaGFyQ29kZUF0KDApICYgMHhmZjsKICAgICAgZmlsZVtvZmZzZXQgKyAxXSA9IHRhYmxlTmFtZS5jaGFyQ29kZUF0KDEpICYgMHhmZjsKICAgICAgZmlsZVtvZmZzZXQgKyAyXSA9IHRhYmxlTmFtZS5jaGFyQ29kZUF0KDIpICYgMHhmZjsKICAgICAgZmlsZVtvZmZzZXQgKyAzXSA9IHRhYmxlTmFtZS5jaGFyQ29kZUF0KDMpICYgMHhmZjsKICAgICAgbGV0IGNoZWNrc3VtID0gMDsKICAgICAgZm9yIChqID0gdGFibGVPZmZzZXRzW2ldLCBqaiA9IHRhYmxlT2Zmc2V0c1tpICsgMV07IGogPCBqajsgaiArPSA0KSB7CiAgICAgICAgY29uc3QgcXVhZCA9ICgwLCBfY29yZV91dGlscy5yZWFkVWludDMyKShmaWxlLCBqKTsKICAgICAgICBjaGVja3N1bSA9IGNoZWNrc3VtICsgcXVhZCA+Pj4gMDsKICAgICAgfQogICAgICB3cml0ZUludDMyKGZpbGUsIG9mZnNldCArIDQsIGNoZWNrc3VtKTsKICAgICAgd3JpdGVJbnQzMihmaWxlLCBvZmZzZXQgKyA4LCB0YWJsZU9mZnNldHNbaV0pOwogICAgICB3cml0ZUludDMyKGZpbGUsIG9mZnNldCArIDEyLCB0YWJsZXNbdGFibGVOYW1lXS5sZW5ndGgpOwogICAgICBvZmZzZXQgKz0gT1RGX1RBQkxFX0VOVFJZX1NJWkU7CiAgICB9CiAgICByZXR1cm4gZmlsZTsKICB9CiAgYWRkVGFibGUodGFnLCBkYXRhKSB7CiAgICBpZiAodGFnIGluIHRoaXMudGFibGVzKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiVGFibGUgIiArIHRhZyArICIgYWxyZWFkeSBleGlzdHMiKTsKICAgIH0KICAgIHRoaXMudGFibGVzW3RhZ10gPSBkYXRhOwogIH0KfQpleHBvcnRzLk9wZW5UeXBlRmlsZUJ1aWxkZXIgPSBPcGVuVHlwZUZpbGVCdWlsZGVyOwoKLyoqKi8gfSksCi8qIDE4MyAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuVHlwZTFGb250ID0gdm9pZCAwOwp2YXIgX2NmZl9wYXJzZXIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE3MCk7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CnZhciBfZm9udHNfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE3Myk7CnZhciBfY29yZV91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTM5KTsKdmFyIF9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0NCk7CnZhciBfdHlwZTFfcGFyc2VyID0gX193X3BkZmpzX3JlcXVpcmVfXygxODQpOwpmdW5jdGlvbiBmaW5kQmxvY2soc3RyZWFtQnl0ZXMsIHNpZ25hdHVyZSwgc3RhcnRJbmRleCkgewogIGNvbnN0IHN0cmVhbUJ5dGVzTGVuZ3RoID0gc3RyZWFtQnl0ZXMubGVuZ3RoOwogIGNvbnN0IHNpZ25hdHVyZUxlbmd0aCA9IHNpZ25hdHVyZS5sZW5ndGg7CiAgY29uc3Qgc2Nhbkxlbmd0aCA9IHN0cmVhbUJ5dGVzTGVuZ3RoIC0gc2lnbmF0dXJlTGVuZ3RoOwogIGxldCBpID0gc3RhcnRJbmRleCwKICAgIGZvdW5kID0gZmFsc2U7CiAgd2hpbGUgKGkgPCBzY2FuTGVuZ3RoKSB7CiAgICBsZXQgaiA9IDA7CiAgICB3aGlsZSAoaiA8IHNpZ25hdHVyZUxlbmd0aCAmJiBzdHJlYW1CeXRlc1tpICsgal0gPT09IHNpZ25hdHVyZVtqXSkgewogICAgICBqKys7CiAgICB9CiAgICBpZiAoaiA+PSBzaWduYXR1cmVMZW5ndGgpIHsKICAgICAgaSArPSBqOwogICAgICB3aGlsZSAoaSA8IHN0cmVhbUJ5dGVzTGVuZ3RoICYmICgwLCBfY29yZV91dGlscy5pc1doaXRlU3BhY2UpKHN0cmVhbUJ5dGVzW2ldKSkgewogICAgICAgIGkrKzsKICAgICAgfQogICAgICBmb3VuZCA9IHRydWU7CiAgICAgIGJyZWFrOwogICAgfQogICAgaSsrOwogIH0KICByZXR1cm4gewogICAgZm91bmQsCiAgICBsZW5ndGg6IGkKICB9Owp9CmZ1bmN0aW9uIGdldEhlYWRlckJsb2NrKHN0cmVhbSwgc3VnZ2VzdGVkTGVuZ3RoKSB7CiAgY29uc3QgRUVYRUNfU0lHTkFUVVJFID0gWzB4NjUsIDB4NjUsIDB4NzgsIDB4NjUsIDB4NjNdOwogIGNvbnN0IHN0cmVhbVN0YXJ0UG9zID0gc3RyZWFtLnBvczsKICBsZXQgaGVhZGVyQnl0ZXMsIGhlYWRlckJ5dGVzTGVuZ3RoLCBibG9jazsKICB0cnkgewogICAgaGVhZGVyQnl0ZXMgPSBzdHJlYW0uZ2V0Qnl0ZXMoc3VnZ2VzdGVkTGVuZ3RoKTsKICAgIGhlYWRlckJ5dGVzTGVuZ3RoID0gaGVhZGVyQnl0ZXMubGVuZ3RoOwogIH0gY2F0Y2ggKGV4KSB7fQogIGlmIChoZWFkZXJCeXRlc0xlbmd0aCA9PT0gc3VnZ2VzdGVkTGVuZ3RoKSB7CiAgICBibG9jayA9IGZpbmRCbG9jayhoZWFkZXJCeXRlcywgRUVYRUNfU0lHTkFUVVJFLCBzdWdnZXN0ZWRMZW5ndGggLSAyICogRUVYRUNfU0lHTkFUVVJFLmxlbmd0aCk7CiAgICBpZiAoYmxvY2suZm91bmQgJiYgYmxvY2subGVuZ3RoID09PSBzdWdnZXN0ZWRMZW5ndGgpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBzdHJlYW06IG5ldyBfc3RyZWFtLlN0cmVhbShoZWFkZXJCeXRlcyksCiAgICAgICAgbGVuZ3RoOiBzdWdnZXN0ZWRMZW5ndGgKICAgICAgfTsKICAgIH0KICB9CiAgKDAsIF91dGlsLndhcm4pKCdJbnZhbGlkICJMZW5ndGgxIiBwcm9wZXJ0eSBpbiBUeXBlMSBmb250IC0tIHRyeWluZyB0byByZWNvdmVyLicpOwogIHN0cmVhbS5wb3MgPSBzdHJlYW1TdGFydFBvczsKICBjb25zdCBTQ0FOX0JMT0NLX0xFTkdUSCA9IDIwNDg7CiAgbGV0IGFjdHVhbExlbmd0aDsKICB3aGlsZSAodHJ1ZSkgewogICAgY29uc3Qgc2NhbkJ5dGVzID0gc3RyZWFtLnBlZWtCeXRlcyhTQ0FOX0JMT0NLX0xFTkdUSCk7CiAgICBibG9jayA9IGZpbmRCbG9jayhzY2FuQnl0ZXMsIEVFWEVDX1NJR05BVFVSRSwgMCk7CiAgICBpZiAoYmxvY2subGVuZ3RoID09PSAwKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgc3RyZWFtLnBvcyArPSBibG9jay5sZW5ndGg7CiAgICBpZiAoYmxvY2suZm91bmQpIHsKICAgICAgYWN0dWFsTGVuZ3RoID0gc3RyZWFtLnBvcyAtIHN0cmVhbVN0YXJ0UG9zOwogICAgICBicmVhazsKICAgIH0KICB9CiAgc3RyZWFtLnBvcyA9IHN0cmVhbVN0YXJ0UG9zOwogIGlmIChhY3R1YWxMZW5ndGgpIHsKICAgIHJldHVybiB7CiAgICAgIHN0cmVhbTogbmV3IF9zdHJlYW0uU3RyZWFtKHN0cmVhbS5nZXRCeXRlcyhhY3R1YWxMZW5ndGgpKSwKICAgICAgbGVuZ3RoOiBhY3R1YWxMZW5ndGgKICAgIH07CiAgfQogICgwLCBfdXRpbC53YXJuKSgnVW5hYmxlIHRvIHJlY292ZXIgIkxlbmd0aDEiIHByb3BlcnR5IGluIFR5cGUxIGZvbnQgLS0gdXNpbmcgYXMgaXMuJyk7CiAgcmV0dXJuIHsKICAgIHN0cmVhbTogbmV3IF9zdHJlYW0uU3RyZWFtKHN0cmVhbS5nZXRCeXRlcyhzdWdnZXN0ZWRMZW5ndGgpKSwKICAgIGxlbmd0aDogc3VnZ2VzdGVkTGVuZ3RoCiAgfTsKfQpmdW5jdGlvbiBnZXRFZXhlY0Jsb2NrKHN0cmVhbSwgc3VnZ2VzdGVkTGVuZ3RoKSB7CiAgY29uc3QgZWV4ZWNCeXRlcyA9IHN0cmVhbS5nZXRCeXRlcygpOwogIGlmIChlZXhlY0J5dGVzLmxlbmd0aCA9PT0gMCkgewogICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJnZXRFZXhlY0Jsb2NrIC0gbm8gZm9udCBwcm9ncmFtIGZvdW5kLiIpOwogIH0KICByZXR1cm4gewogICAgc3RyZWFtOiBuZXcgX3N0cmVhbS5TdHJlYW0oZWV4ZWNCeXRlcyksCiAgICBsZW5ndGg6IGVleGVjQnl0ZXMubGVuZ3RoCiAgfTsKfQpjbGFzcyBUeXBlMUZvbnQgewogIGNvbnN0cnVjdG9yKG5hbWUsIGZpbGUsIHByb3BlcnRpZXMpIHsKICAgIGNvbnN0IFBGQl9IRUFERVJfU0laRSA9IDY7CiAgICBsZXQgaGVhZGVyQmxvY2tMZW5ndGggPSBwcm9wZXJ0aWVzLmxlbmd0aDE7CiAgICBsZXQgZWV4ZWNCbG9ja0xlbmd0aCA9IHByb3BlcnRpZXMubGVuZ3RoMjsKICAgIGxldCBwZmJIZWFkZXIgPSBmaWxlLnBlZWtCeXRlcyhQRkJfSEVBREVSX1NJWkUpOwogICAgY29uc3QgcGZiSGVhZGVyUHJlc2VudCA9IHBmYkhlYWRlclswXSA9PT0gMHg4MCAmJiBwZmJIZWFkZXJbMV0gPT09IDB4MDE7CiAgICBpZiAocGZiSGVhZGVyUHJlc2VudCkgewogICAgICBmaWxlLnNraXAoUEZCX0hFQURFUl9TSVpFKTsKICAgICAgaGVhZGVyQmxvY2tMZW5ndGggPSBwZmJIZWFkZXJbNV0gPDwgMjQgfCBwZmJIZWFkZXJbNF0gPDwgMTYgfCBwZmJIZWFkZXJbM10gPDwgOCB8IHBmYkhlYWRlclsyXTsKICAgIH0KICAgIGNvbnN0IGhlYWRlckJsb2NrID0gZ2V0SGVhZGVyQmxvY2soZmlsZSwgaGVhZGVyQmxvY2tMZW5ndGgpOwogICAgY29uc3QgaGVhZGVyQmxvY2tQYXJzZXIgPSBuZXcgX3R5cGUxX3BhcnNlci5UeXBlMVBhcnNlcihoZWFkZXJCbG9jay5zdHJlYW0sIGZhbHNlLCBfZm9udHNfdXRpbHMuU0VBQ19BTkFMWVNJU19FTkFCTEVEKTsKICAgIGhlYWRlckJsb2NrUGFyc2VyLmV4dHJhY3RGb250SGVhZGVyKHByb3BlcnRpZXMpOwogICAgaWYgKHBmYkhlYWRlclByZXNlbnQpIHsKICAgICAgcGZiSGVhZGVyID0gZmlsZS5nZXRCeXRlcyhQRkJfSEVBREVSX1NJWkUpOwogICAgICBlZXhlY0Jsb2NrTGVuZ3RoID0gcGZiSGVhZGVyWzVdIDw8IDI0IHwgcGZiSGVhZGVyWzRdIDw8IDE2IHwgcGZiSGVhZGVyWzNdIDw8IDggfCBwZmJIZWFkZXJbMl07CiAgICB9CiAgICBjb25zdCBlZXhlY0Jsb2NrID0gZ2V0RWV4ZWNCbG9jayhmaWxlLCBlZXhlY0Jsb2NrTGVuZ3RoKTsKICAgIGNvbnN0IGVleGVjQmxvY2tQYXJzZXIgPSBuZXcgX3R5cGUxX3BhcnNlci5UeXBlMVBhcnNlcihlZXhlY0Jsb2NrLnN0cmVhbSwgdHJ1ZSwgX2ZvbnRzX3V0aWxzLlNFQUNfQU5BTFlTSVNfRU5BQkxFRCk7CiAgICBjb25zdCBkYXRhID0gZWV4ZWNCbG9ja1BhcnNlci5leHRyYWN0Rm9udFByb2dyYW0ocHJvcGVydGllcyk7CiAgICBmb3IgKGNvbnN0IGtleSBpbiBkYXRhLnByb3BlcnRpZXMpIHsKICAgICAgcHJvcGVydGllc1trZXldID0gZGF0YS5wcm9wZXJ0aWVzW2tleV07CiAgICB9CiAgICBjb25zdCBjaGFyc3RyaW5ncyA9IGRhdGEuY2hhcnN0cmluZ3M7CiAgICBjb25zdCB0eXBlMkNoYXJzdHJpbmdzID0gdGhpcy5nZXRUeXBlMkNoYXJzdHJpbmdzKGNoYXJzdHJpbmdzKTsKICAgIGNvbnN0IHN1YnJzID0gdGhpcy5nZXRUeXBlMlN1YnJzKGRhdGEuc3VicnMpOwogICAgdGhpcy5jaGFyc3RyaW5ncyA9IGNoYXJzdHJpbmdzOwogICAgdGhpcy5kYXRhID0gdGhpcy53cmFwKG5hbWUsIHR5cGUyQ2hhcnN0cmluZ3MsIHRoaXMuY2hhcnN0cmluZ3MsIHN1YnJzLCBwcm9wZXJ0aWVzKTsKICAgIHRoaXMuc2VhY3MgPSB0aGlzLmdldFNlYWNzKGRhdGEuY2hhcnN0cmluZ3MpOwogIH0KICBnZXQgbnVtR2x5cGhzKCkgewogICAgcmV0dXJuIHRoaXMuY2hhcnN0cmluZ3MubGVuZ3RoICsgMTsKICB9CiAgZ2V0Q2hhcnNldCgpIHsKICAgIGNvbnN0IGNoYXJzZXQgPSBbIi5ub3RkZWYiXTsKICAgIGZvciAoY29uc3QgewogICAgICBnbHlwaE5hbWUKICAgIH0gb2YgdGhpcy5jaGFyc3RyaW5ncykgewogICAgICBjaGFyc2V0LnB1c2goZ2x5cGhOYW1lKTsKICAgIH0KICAgIHJldHVybiBjaGFyc2V0OwogIH0KICBnZXRHbHlwaE1hcHBpbmcocHJvcGVydGllcykgewogICAgY29uc3QgY2hhcnN0cmluZ3MgPSB0aGlzLmNoYXJzdHJpbmdzOwogICAgaWYgKHByb3BlcnRpZXMuY29tcG9zaXRlKSB7CiAgICAgIGNvbnN0IGNoYXJDb2RlVG9HbHlwaElkID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgZm9yIChsZXQgZ2x5cGhJZCA9IDAsIGNoYXJzdHJpbmdzTGVuID0gY2hhcnN0cmluZ3MubGVuZ3RoOyBnbHlwaElkIDwgY2hhcnN0cmluZ3NMZW47IGdseXBoSWQrKykgewogICAgICAgIGNvbnN0IGNoYXJDb2RlID0gcHJvcGVydGllcy5jTWFwLmNoYXJDb2RlT2YoZ2x5cGhJZCk7CiAgICAgICAgY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID0gZ2x5cGhJZCArIDE7CiAgICAgIH0KICAgICAgcmV0dXJuIGNoYXJDb2RlVG9HbHlwaElkOwogICAgfQogICAgY29uc3QgZ2x5cGhOYW1lcyA9IFsiLm5vdGRlZiJdOwogICAgbGV0IGJ1aWx0SW5FbmNvZGluZywgZ2x5cGhJZDsKICAgIGZvciAoZ2x5cGhJZCA9IDA7IGdseXBoSWQgPCBjaGFyc3RyaW5ncy5sZW5ndGg7IGdseXBoSWQrKykgewogICAgICBnbHlwaE5hbWVzLnB1c2goY2hhcnN0cmluZ3NbZ2x5cGhJZF0uZ2x5cGhOYW1lKTsKICAgIH0KICAgIGNvbnN0IGVuY29kaW5nID0gcHJvcGVydGllcy5idWlsdEluRW5jb2Rpbmc7CiAgICBpZiAoZW5jb2RpbmcpIHsKICAgICAgYnVpbHRJbkVuY29kaW5nID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBlbmNvZGluZykgewogICAgICAgIGdseXBoSWQgPSBnbHlwaE5hbWVzLmluZGV4T2YoZW5jb2RpbmdbY2hhckNvZGVdKTsKICAgICAgICBpZiAoZ2x5cGhJZCA+PSAwKSB7CiAgICAgICAgICBidWlsdEluRW5jb2RpbmdbY2hhckNvZGVdID0gZ2x5cGhJZDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiAoMCwgX2ZvbnRzX3V0aWxzLnR5cGUxRm9udEdseXBoTWFwcGluZykocHJvcGVydGllcywgYnVpbHRJbkVuY29kaW5nLCBnbHlwaE5hbWVzKTsKICB9CiAgaGFzR2x5cGhJZChpZCkgewogICAgaWYgKGlkIDwgMCB8fCBpZCA+PSB0aGlzLm51bUdseXBocykgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAoaWQgPT09IDApIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBjb25zdCBnbHlwaCA9IHRoaXMuY2hhcnN0cmluZ3NbaWQgLSAxXTsKICAgIHJldHVybiBnbHlwaC5jaGFyc3RyaW5nLmxlbmd0aCA+IDA7CiAgfQogIGdldFNlYWNzKGNoYXJzdHJpbmdzKSB7CiAgICBjb25zdCBzZWFjTWFwID0gW107CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBjaGFyc3RyaW5ncy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IGNoYXJzdHJpbmcgPSBjaGFyc3RyaW5nc1tpXTsKICAgICAgaWYgKGNoYXJzdHJpbmcuc2VhYykgewogICAgICAgIHNlYWNNYXBbaSArIDFdID0gY2hhcnN0cmluZy5zZWFjOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2VhY01hcDsKICB9CiAgZ2V0VHlwZTJDaGFyc3RyaW5ncyh0eXBlMUNoYXJzdHJpbmdzKSB7CiAgICBjb25zdCB0eXBlMkNoYXJzdHJpbmdzID0gW107CiAgICBmb3IgKGNvbnN0IHR5cGUxQ2hhcnN0cmluZyBvZiB0eXBlMUNoYXJzdHJpbmdzKSB7CiAgICAgIHR5cGUyQ2hhcnN0cmluZ3MucHVzaCh0eXBlMUNoYXJzdHJpbmcuY2hhcnN0cmluZyk7CiAgICB9CiAgICByZXR1cm4gdHlwZTJDaGFyc3RyaW5nczsKICB9CiAgZ2V0VHlwZTJTdWJycyh0eXBlMVN1YnJzKSB7CiAgICBsZXQgYmlhcyA9IDA7CiAgICBjb25zdCBjb3VudCA9IHR5cGUxU3VicnMubGVuZ3RoOwogICAgaWYgKGNvdW50IDwgMTEzMykgewogICAgICBiaWFzID0gMTA3OwogICAgfSBlbHNlIGlmIChjb3VudCA8IDMzNzY5KSB7CiAgICAgIGJpYXMgPSAxMTMxOwogICAgfSBlbHNlIHsKICAgICAgYmlhcyA9IDMyNzY4OwogICAgfQogICAgY29uc3QgdHlwZTJTdWJycyA9IFtdOwogICAgbGV0IGk7CiAgICBmb3IgKGkgPSAwOyBpIDwgYmlhczsgaSsrKSB7CiAgICAgIHR5cGUyU3VicnMucHVzaChbMHgwYl0pOwogICAgfQogICAgZm9yIChpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgdHlwZTJTdWJycy5wdXNoKHR5cGUxU3VicnNbaV0pOwogICAgfQogICAgcmV0dXJuIHR5cGUyU3VicnM7CiAgfQogIHdyYXAobmFtZSwgZ2x5cGhzLCBjaGFyc3RyaW5ncywgc3VicnMsIHByb3BlcnRpZXMpIHsKICAgIGNvbnN0IGNmZiA9IG5ldyBfY2ZmX3BhcnNlci5DRkYoKTsKICAgIGNmZi5oZWFkZXIgPSBuZXcgX2NmZl9wYXJzZXIuQ0ZGSGVhZGVyKDEsIDAsIDQsIDQpOwogICAgY2ZmLm5hbWVzID0gW25hbWVdOwogICAgY29uc3QgdG9wRGljdCA9IG5ldyBfY2ZmX3BhcnNlci5DRkZUb3BEaWN0KCk7CiAgICB0b3BEaWN0LnNldEJ5TmFtZSgidmVyc2lvbiIsIDM5MSk7CiAgICB0b3BEaWN0LnNldEJ5TmFtZSgiTm90aWNlIiwgMzkyKTsKICAgIHRvcERpY3Quc2V0QnlOYW1lKCJGdWxsTmFtZSIsIDM5Myk7CiAgICB0b3BEaWN0LnNldEJ5TmFtZSgiRmFtaWx5TmFtZSIsIDM5NCk7CiAgICB0b3BEaWN0LnNldEJ5TmFtZSgiV2VpZ2h0IiwgMzk1KTsKICAgIHRvcERpY3Quc2V0QnlOYW1lKCJFbmNvZGluZyIsIG51bGwpOwogICAgdG9wRGljdC5zZXRCeU5hbWUoIkZvbnRNYXRyaXgiLCBwcm9wZXJ0aWVzLmZvbnRNYXRyaXgpOwogICAgdG9wRGljdC5zZXRCeU5hbWUoIkZvbnRCQm94IiwgcHJvcGVydGllcy5iYm94KTsKICAgIHRvcERpY3Quc2V0QnlOYW1lKCJjaGFyc2V0IiwgbnVsbCk7CiAgICB0b3BEaWN0LnNldEJ5TmFtZSgiQ2hhclN0cmluZ3MiLCBudWxsKTsKICAgIHRvcERpY3Quc2V0QnlOYW1lKCJQcml2YXRlIiwgbnVsbCk7CiAgICBjZmYudG9wRGljdCA9IHRvcERpY3Q7CiAgICBjb25zdCBzdHJpbmdzID0gbmV3IF9jZmZfcGFyc2VyLkNGRlN0cmluZ3MoKTsKICAgIHN0cmluZ3MuYWRkKCJWZXJzaW9uIDAuMTEiKTsKICAgIHN0cmluZ3MuYWRkKCJTZWUgb3JpZ2luYWwgbm90aWNlIik7CiAgICBzdHJpbmdzLmFkZChuYW1lKTsKICAgIHN0cmluZ3MuYWRkKG5hbWUpOwogICAgc3RyaW5ncy5hZGQoIk1lZGl1bSIpOwogICAgY2ZmLnN0cmluZ3MgPSBzdHJpbmdzOwogICAgY2ZmLmdsb2JhbFN1YnJJbmRleCA9IG5ldyBfY2ZmX3BhcnNlci5DRkZJbmRleCgpOwogICAgY29uc3QgY291bnQgPSBnbHlwaHMubGVuZ3RoOwogICAgY29uc3QgY2hhcnNldEFycmF5ID0gWyIubm90ZGVmIl07CiAgICBsZXQgaSwgaWk7CiAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQ7IGkrKykgewogICAgICBjb25zdCBnbHlwaE5hbWUgPSBjaGFyc3RyaW5nc1tpXS5nbHlwaE5hbWU7CiAgICAgIGNvbnN0IGluZGV4ID0gX2NmZl9wYXJzZXIuQ0ZGU3RhbmRhcmRTdHJpbmdzLmluZGV4T2YoZ2x5cGhOYW1lKTsKICAgICAgaWYgKGluZGV4ID09PSAtMSkgewogICAgICAgIHN0cmluZ3MuYWRkKGdseXBoTmFtZSk7CiAgICAgIH0KICAgICAgY2hhcnNldEFycmF5LnB1c2goZ2x5cGhOYW1lKTsKICAgIH0KICAgIGNmZi5jaGFyc2V0ID0gbmV3IF9jZmZfcGFyc2VyLkNGRkNoYXJzZXQoZmFsc2UsIDAsIGNoYXJzZXRBcnJheSk7CiAgICBjb25zdCBjaGFyU3RyaW5nc0luZGV4ID0gbmV3IF9jZmZfcGFyc2VyLkNGRkluZGV4KCk7CiAgICBjaGFyU3RyaW5nc0luZGV4LmFkZChbMHg4YiwgMHgwZV0pOwogICAgZm9yIChpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgY2hhclN0cmluZ3NJbmRleC5hZGQoZ2x5cGhzW2ldKTsKICAgIH0KICAgIGNmZi5jaGFyU3RyaW5ncyA9IGNoYXJTdHJpbmdzSW5kZXg7CiAgICBjb25zdCBwcml2YXRlRGljdCA9IG5ldyBfY2ZmX3BhcnNlci5DRkZQcml2YXRlRGljdCgpOwogICAgcHJpdmF0ZURpY3Quc2V0QnlOYW1lKCJTdWJycyIsIG51bGwpOwogICAgY29uc3QgZmllbGRzID0gWyJCbHVlVmFsdWVzIiwgIk90aGVyQmx1ZXMiLCAiRmFtaWx5Qmx1ZXMiLCAiRmFtaWx5T3RoZXJCbHVlcyIsICJTdGVtU25hcEgiLCAiU3RlbVNuYXBWIiwgIkJsdWVTaGlmdCIsICJCbHVlRnV6eiIsICJCbHVlU2NhbGUiLCAiTGFuZ3VhZ2VHcm91cCIsICJFeHBhbnNpb25GYWN0b3IiLCAiRm9yY2VCb2xkIiwgIlN0ZEhXIiwgIlN0ZFZXIl07CiAgICBmb3IgKGkgPSAwLCBpaSA9IGZpZWxkcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IGZpZWxkID0gZmllbGRzW2ldOwogICAgICBpZiAoIShmaWVsZCBpbiBwcm9wZXJ0aWVzLnByaXZhdGVEYXRhKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IHZhbHVlID0gcHJvcGVydGllcy5wcml2YXRlRGF0YVtmaWVsZF07CiAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkgewogICAgICAgIGZvciAobGV0IGogPSB2YWx1ZS5sZW5ndGggLSAxOyBqID4gMDsgai0tKSB7CiAgICAgICAgICB2YWx1ZVtqXSAtPSB2YWx1ZVtqIC0gMV07CiAgICAgICAgfQogICAgICB9CiAgICAgIHByaXZhdGVEaWN0LnNldEJ5TmFtZShmaWVsZCwgdmFsdWUpOwogICAgfQogICAgY2ZmLnRvcERpY3QucHJpdmF0ZURpY3QgPSBwcml2YXRlRGljdDsKICAgIGNvbnN0IHN1YnJJbmRleCA9IG5ldyBfY2ZmX3BhcnNlci5DRkZJbmRleCgpOwogICAgZm9yIChpID0gMCwgaWkgPSBzdWJycy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIHN1YnJJbmRleC5hZGQoc3VicnNbaV0pOwogICAgfQogICAgcHJpdmF0ZURpY3Quc3VicnNJbmRleCA9IHN1YnJJbmRleDsKICAgIGNvbnN0IGNvbXBpbGVyID0gbmV3IF9jZmZfcGFyc2VyLkNGRkNvbXBpbGVyKGNmZik7CiAgICByZXR1cm4gY29tcGlsZXIuY29tcGlsZSgpOwogIH0KfQpleHBvcnRzLlR5cGUxRm9udCA9IFR5cGUxRm9udDsKCi8qKiovIH0pLAovKiAxODQgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlR5cGUxUGFyc2VyID0gdm9pZCAwOwp2YXIgX2VuY29kaW5ncyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTcyKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQ0KTsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKY29uc3QgSElOVElOR19FTkFCTEVEID0gZmFsc2U7CmNvbnN0IENPTU1BTkRfTUFQID0gewogIGhzdGVtOiBbMV0sCiAgdnN0ZW06IFszXSwKICB2bW92ZXRvOiBbNF0sCiAgcmxpbmV0bzogWzVdLAogIGhsaW5ldG86IFs2XSwKICB2bGluZXRvOiBbN10sCiAgcnJjdXJ2ZXRvOiBbOF0sCiAgY2FsbHN1YnI6IFsxMF0sCiAgZmxleDogWzEyLCAzNV0sCiAgZHJvcDogWzEyLCAxOF0sCiAgZW5kY2hhcjogWzE0XSwKICBybW92ZXRvOiBbMjFdLAogIGhtb3ZldG86IFsyMl0sCiAgdmhjdXJ2ZXRvOiBbMzBdLAogIGh2Y3VydmV0bzogWzMxXQp9OwpjbGFzcyBUeXBlMUNoYXJTdHJpbmcgewogIGNvbnN0cnVjdG9yKCkgewogICAgdGhpcy53aWR0aCA9IDA7CiAgICB0aGlzLmxzYiA9IDA7CiAgICB0aGlzLmZsZXhpbmcgPSBmYWxzZTsKICAgIHRoaXMub3V0cHV0ID0gW107CiAgICB0aGlzLnN0YWNrID0gW107CiAgfQogIGNvbnZlcnQoZW5jb2RlZCwgc3VicnMsIHNlYWNBbmFseXNpc0VuYWJsZWQpIHsKICAgIGNvbnN0IGNvdW50ID0gZW5jb2RlZC5sZW5ndGg7CiAgICBsZXQgZXJyb3IgPSBmYWxzZTsKICAgIGxldCB3eCwgc2J4LCBzdWJyTnVtYmVyOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgIGxldCB2YWx1ZSA9IGVuY29kZWRbaV07CiAgICAgIGlmICh2YWx1ZSA8IDMyKSB7CiAgICAgICAgaWYgKHZhbHVlID09PSAxMikgewogICAgICAgICAgdmFsdWUgPSAodmFsdWUgPDwgOCkgKyBlbmNvZGVkWysraV07CiAgICAgICAgfQogICAgICAgIHN3aXRjaCAodmFsdWUpIHsKICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgaWYgKCFISU5USU5HX0VOQUJMRUQpIHsKICAgICAgICAgICAgICB0aGlzLnN0YWNrID0gW107CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDIsIENPTU1BTkRfTUFQLmhzdGVtKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDM6CiAgICAgICAgICAgIGlmICghSElOVElOR19FTkFCTEVEKSB7CiAgICAgICAgICAgICAgdGhpcy5zdGFjayA9IFtdOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCgyLCBDT01NQU5EX01BUC52c3RlbSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICBpZiAodGhpcy5mbGV4aW5nKSB7CiAgICAgICAgICAgICAgaWYgKHRoaXMuc3RhY2subGVuZ3RoIDwgMSkgewogICAgICAgICAgICAgICAgZXJyb3IgPSB0cnVlOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNvbnN0IGR5ID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgICB0aGlzLnN0YWNrLnB1c2goMCwgZHkpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCgxLCBDT01NQU5EX01BUC52bW92ZXRvKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDU6CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCgyLCBDT01NQU5EX01BUC5ybGluZXRvKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDY6CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCgxLCBDT01NQU5EX01BUC5obGluZXRvKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDc6CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCgxLCBDT01NQU5EX01BUC52bGluZXRvKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCg2LCBDT01NQU5EX01BUC5ycmN1cnZldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgOToKICAgICAgICAgICAgdGhpcy5zdGFjayA9IFtdOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMTA6CiAgICAgICAgICAgIGlmICh0aGlzLnN0YWNrLmxlbmd0aCA8IDEpIHsKICAgICAgICAgICAgICBlcnJvciA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3Vick51bWJlciA9IHRoaXMuc3RhY2sucG9wKCk7CiAgICAgICAgICAgIGlmICghc3VicnNbc3Vick51bWJlcl0pIHsKICAgICAgICAgICAgICBlcnJvciA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmNvbnZlcnQoc3VicnNbc3Vick51bWJlcl0sIHN1YnJzLCBzZWFjQW5hbHlzaXNFbmFibGVkKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDExOgogICAgICAgICAgICByZXR1cm4gZXJyb3I7CiAgICAgICAgICBjYXNlIDEzOgogICAgICAgICAgICBpZiAodGhpcy5zdGFjay5sZW5ndGggPCAyKSB7CiAgICAgICAgICAgICAgZXJyb3IgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHd4ID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgc2J4ID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgdGhpcy5sc2IgPSBzYng7CiAgICAgICAgICAgIHRoaXMud2lkdGggPSB3eDsKICAgICAgICAgICAgdGhpcy5zdGFjay5wdXNoKHd4LCBzYngpOwogICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMiwgQ09NTUFORF9NQVAuaG1vdmV0byk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAxNDoKICAgICAgICAgICAgdGhpcy5vdXRwdXQucHVzaChDT01NQU5EX01BUC5lbmRjaGFyWzBdKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDIxOgogICAgICAgICAgICBpZiAodGhpcy5mbGV4aW5nKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDIsIENPTU1BTkRfTUFQLnJtb3ZldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMjI6CiAgICAgICAgICAgIGlmICh0aGlzLmZsZXhpbmcpIHsKICAgICAgICAgICAgICB0aGlzLnN0YWNrLnB1c2goMCk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDEsIENPTU1BTkRfTUFQLmhtb3ZldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMzA6CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCg0LCBDT01NQU5EX01BUC52aGN1cnZldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMzE6CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCg0LCBDT01NQU5EX01BUC5odmN1cnZldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgKDEyIDw8IDgpICsgMDoKICAgICAgICAgICAgdGhpcy5zdGFjayA9IFtdOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgKDEyIDw8IDgpICsgMToKICAgICAgICAgICAgaWYgKCFISU5USU5HX0VOQUJMRUQpIHsKICAgICAgICAgICAgICB0aGlzLnN0YWNrID0gW107CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDIsIENPTU1BTkRfTUFQLnZzdGVtKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICgxMiA8PCA4KSArIDI6CiAgICAgICAgICAgIGlmICghSElOVElOR19FTkFCTEVEKSB7CiAgICAgICAgICAgICAgdGhpcy5zdGFjayA9IFtdOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCgyLCBDT01NQU5EX01BUC5oc3RlbSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAoMTIgPDwgOCkgKyA2OgogICAgICAgICAgICBpZiAoc2VhY0FuYWx5c2lzRW5hYmxlZCkgewogICAgICAgICAgICAgIGNvbnN0IGFzYiA9IHRoaXMuc3RhY2suYXQoLTUpOwogICAgICAgICAgICAgIHRoaXMuc2VhYyA9IHRoaXMuc3RhY2suc3BsaWNlKC00LCA0KTsKICAgICAgICAgICAgICB0aGlzLnNlYWNbMF0gKz0gdGhpcy5sc2IgLSBhc2I7CiAgICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDAsIENPTU1BTkRfTUFQLmVuZGNoYXIpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCg0LCBDT01NQU5EX01BUC5lbmRjaGFyKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgKDEyIDw8IDgpICsgNzoKICAgICAgICAgICAgaWYgKHRoaXMuc3RhY2subGVuZ3RoIDwgNCkgewogICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLnN0YWNrLnBvcCgpOwogICAgICAgICAgICB3eCA9IHRoaXMuc3RhY2sucG9wKCk7CiAgICAgICAgICAgIGNvbnN0IHNieSA9IHRoaXMuc3RhY2sucG9wKCk7CiAgICAgICAgICAgIHNieCA9IHRoaXMuc3RhY2sucG9wKCk7CiAgICAgICAgICAgIHRoaXMubHNiID0gc2J4OwogICAgICAgICAgICB0aGlzLndpZHRoID0gd3g7CiAgICAgICAgICAgIHRoaXMuc3RhY2sucHVzaCh3eCwgc2J4LCBzYnkpOwogICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMywgQ09NTUFORF9NQVAucm1vdmV0byk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAoMTIgPDwgOCkgKyAxMjoKICAgICAgICAgICAgaWYgKHRoaXMuc3RhY2subGVuZ3RoIDwgMikgewogICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBudW0yID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgY29uc3QgbnVtMSA9IHRoaXMuc3RhY2sucG9wKCk7CiAgICAgICAgICAgIHRoaXMuc3RhY2sucHVzaChudW0xIC8gbnVtMik7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAoMTIgPDwgOCkgKyAxNjoKICAgICAgICAgICAgaWYgKHRoaXMuc3RhY2subGVuZ3RoIDwgMikgewogICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdWJyTnVtYmVyID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgY29uc3QgbnVtQXJncyA9IHRoaXMuc3RhY2sucG9wKCk7CiAgICAgICAgICAgIGlmIChzdWJyTnVtYmVyID09PSAwICYmIG51bUFyZ3MgPT09IDMpIHsKICAgICAgICAgICAgICBjb25zdCBmbGV4QXJncyA9IHRoaXMuc3RhY2suc3BsaWNlKC0xNywgMTcpOwogICAgICAgICAgICAgIHRoaXMuc3RhY2sucHVzaChmbGV4QXJnc1syXSArIGZsZXhBcmdzWzBdLCBmbGV4QXJnc1szXSArIGZsZXhBcmdzWzFdLCBmbGV4QXJnc1s0XSwgZmxleEFyZ3NbNV0sIGZsZXhBcmdzWzZdLCBmbGV4QXJnc1s3XSwgZmxleEFyZ3NbOF0sIGZsZXhBcmdzWzldLCBmbGV4QXJnc1sxMF0sIGZsZXhBcmdzWzExXSwgZmxleEFyZ3NbMTJdLCBmbGV4QXJnc1sxM10sIGZsZXhBcmdzWzE0XSk7CiAgICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDEzLCBDT01NQU5EX01BUC5mbGV4LCB0cnVlKTsKICAgICAgICAgICAgICB0aGlzLmZsZXhpbmcgPSBmYWxzZTsKICAgICAgICAgICAgICB0aGlzLnN0YWNrLnB1c2goZmxleEFyZ3NbMTVdLCBmbGV4QXJnc1sxNl0pOwogICAgICAgICAgICB9IGVsc2UgaWYgKHN1YnJOdW1iZXIgPT09IDEgJiYgbnVtQXJncyA9PT0gMCkgewogICAgICAgICAgICAgIHRoaXMuZmxleGluZyA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICgxMiA8PCA4KSArIDE3OgogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgKDEyIDw8IDgpICsgMzM6CiAgICAgICAgICAgIHRoaXMuc3RhY2sgPSBbXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoJ1Vua25vd24gdHlwZSAxIGNoYXJzdHJpbmcgY29tbWFuZCBvZiAiJyArIHZhbHVlICsgJyInKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmIChlcnJvcikgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9IGVsc2UgaWYgKHZhbHVlIDw9IDI0NikgewogICAgICAgIHZhbHVlIC09IDEzOTsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA8PSAyNTApIHsKICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAtIDI0NykgKiAyNTYgKyBlbmNvZGVkWysraV0gKyAxMDg7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPD0gMjU0KSB7CiAgICAgICAgdmFsdWUgPSAtKCh2YWx1ZSAtIDI1MSkgKiAyNTYpIC0gZW5jb2RlZFsrK2ldIC0gMTA4OwogICAgICB9IGVsc2UgewogICAgICAgIHZhbHVlID0gKGVuY29kZWRbKytpXSAmIDB4ZmYpIDw8IDI0IHwgKGVuY29kZWRbKytpXSAmIDB4ZmYpIDw8IDE2IHwgKGVuY29kZWRbKytpXSAmIDB4ZmYpIDw8IDggfCAoZW5jb2RlZFsrK2ldICYgMHhmZikgPDwgMDsKICAgICAgfQogICAgICB0aGlzLnN0YWNrLnB1c2godmFsdWUpOwogICAgfQogICAgcmV0dXJuIGVycm9yOwogIH0KICBleGVjdXRlQ29tbWFuZChob3dNYW55QXJncywgY29tbWFuZCwga2VlcFN0YWNrKSB7CiAgICBjb25zdCBzdGFja0xlbmd0aCA9IHRoaXMuc3RhY2subGVuZ3RoOwogICAgaWYgKGhvd01hbnlBcmdzID4gc3RhY2tMZW5ndGgpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBjb25zdCBzdGFydCA9IHN0YWNrTGVuZ3RoIC0gaG93TWFueUFyZ3M7CiAgICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBzdGFja0xlbmd0aDsgaSsrKSB7CiAgICAgIGxldCB2YWx1ZSA9IHRoaXMuc3RhY2tbaV07CiAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSkgewogICAgICAgIHRoaXMub3V0cHV0LnB1c2goMjgsIHZhbHVlID4+IDggJiAweGZmLCB2YWx1ZSAmIDB4ZmYpOwogICAgICB9IGVsc2UgewogICAgICAgIHZhbHVlID0gNjU1MzYgKiB2YWx1ZSB8IDA7CiAgICAgICAgdGhpcy5vdXRwdXQucHVzaCgyNTUsIHZhbHVlID4+IDI0ICYgMHhmZiwgdmFsdWUgPj4gMTYgJiAweGZmLCB2YWx1ZSA+PiA4ICYgMHhmZiwgdmFsdWUgJiAweGZmKTsKICAgICAgfQogICAgfQogICAgdGhpcy5vdXRwdXQucHVzaCguLi5jb21tYW5kKTsKICAgIGlmIChrZWVwU3RhY2spIHsKICAgICAgdGhpcy5zdGFjay5zcGxpY2Uoc3RhcnQsIGhvd01hbnlBcmdzKTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuc3RhY2subGVuZ3RoID0gMDsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9Cn0KY29uc3QgRUVYRUNfRU5DUllQVF9LRVkgPSA1NTY2NTsKY29uc3QgQ0hBUl9TVFJTX0VOQ1JZUFRfS0VZID0gNDMzMDsKZnVuY3Rpb24gaXNIZXhEaWdpdChjb2RlKSB7CiAgcmV0dXJuIGNvZGUgPj0gNDggJiYgY29kZSA8PSA1NyB8fCBjb2RlID49IDY1ICYmIGNvZGUgPD0gNzAgfHwgY29kZSA+PSA5NyAmJiBjb2RlIDw9IDEwMjsKfQpmdW5jdGlvbiBkZWNyeXB0KGRhdGEsIGtleSwgZGlzY2FyZE51bWJlcikgewogIGlmIChkaXNjYXJkTnVtYmVyID49IGRhdGEubGVuZ3RoKSB7CiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCk7CiAgfQogIGNvbnN0IGMxID0gNTI4NDUsCiAgICBjMiA9IDIyNzE5OwogIGxldCByID0ga2V5IHwgMCwKICAgIGksCiAgICBqOwogIGZvciAoaSA9IDA7IGkgPCBkaXNjYXJkTnVtYmVyOyBpKyspIHsKICAgIHIgPSAoZGF0YVtpXSArIHIpICogYzEgKyBjMiAmICgxIDw8IDE2KSAtIDE7CiAgfQogIGNvbnN0IGNvdW50ID0gZGF0YS5sZW5ndGggLSBkaXNjYXJkTnVtYmVyOwogIGNvbnN0IGRlY3J5cHRlZCA9IG5ldyBVaW50OEFycmF5KGNvdW50KTsKICBmb3IgKGkgPSBkaXNjYXJkTnVtYmVyLCBqID0gMDsgaiA8IGNvdW50OyBpKyssIGorKykgewogICAgY29uc3QgdmFsdWUgPSBkYXRhW2ldOwogICAgZGVjcnlwdGVkW2pdID0gdmFsdWUgXiByID4+IDg7CiAgICByID0gKHZhbHVlICsgcikgKiBjMSArIGMyICYgKDEgPDwgMTYpIC0gMTsKICB9CiAgcmV0dXJuIGRlY3J5cHRlZDsKfQpmdW5jdGlvbiBkZWNyeXB0QXNjaWkoZGF0YSwga2V5LCBkaXNjYXJkTnVtYmVyKSB7CiAgY29uc3QgYzEgPSA1Mjg0NSwKICAgIGMyID0gMjI3MTk7CiAgbGV0IHIgPSBrZXkgfCAwOwogIGNvbnN0IGNvdW50ID0gZGF0YS5sZW5ndGgsCiAgICBtYXliZUxlbmd0aCA9IGNvdW50ID4+PiAxOwogIGNvbnN0IGRlY3J5cHRlZCA9IG5ldyBVaW50OEFycmF5KG1heWJlTGVuZ3RoKTsKICBsZXQgaSwgajsKICBmb3IgKGkgPSAwLCBqID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgIGNvbnN0IGRpZ2l0MSA9IGRhdGFbaV07CiAgICBpZiAoIWlzSGV4RGlnaXQoZGlnaXQxKSkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGkrKzsKICAgIGxldCBkaWdpdDI7CiAgICB3aGlsZSAoaSA8IGNvdW50ICYmICFpc0hleERpZ2l0KGRpZ2l0MiA9IGRhdGFbaV0pKSB7CiAgICAgIGkrKzsKICAgIH0KICAgIGlmIChpIDwgY291bnQpIHsKICAgICAgY29uc3QgdmFsdWUgPSBwYXJzZUludChTdHJpbmcuZnJvbUNoYXJDb2RlKGRpZ2l0MSwgZGlnaXQyKSwgMTYpOwogICAgICBkZWNyeXB0ZWRbaisrXSA9IHZhbHVlIF4gciA+PiA4OwogICAgICByID0gKHZhbHVlICsgcikgKiBjMSArIGMyICYgKDEgPDwgMTYpIC0gMTsKICAgIH0KICB9CiAgcmV0dXJuIGRlY3J5cHRlZC5zbGljZShkaXNjYXJkTnVtYmVyLCBqKTsKfQpmdW5jdGlvbiBpc1NwZWNpYWwoYykgewogIHJldHVybiBjID09PSAweDJmIHx8IGMgPT09IDB4NWIgfHwgYyA9PT0gMHg1ZCB8fCBjID09PSAweDdiIHx8IGMgPT09IDB4N2QgfHwgYyA9PT0gMHgyOCB8fCBjID09PSAweDI5Owp9CmNsYXNzIFR5cGUxUGFyc2VyIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIGVuY3J5cHRlZCwgc2VhY0FuYWx5c2lzRW5hYmxlZCkgewogICAgaWYgKGVuY3J5cHRlZCkgewogICAgICBjb25zdCBkYXRhID0gc3RyZWFtLmdldEJ5dGVzKCk7CiAgICAgIGNvbnN0IGlzQmluYXJ5ID0gISgoaXNIZXhEaWdpdChkYXRhWzBdKSB8fCAoMCwgX2NvcmVfdXRpbHMuaXNXaGl0ZVNwYWNlKShkYXRhWzBdKSkgJiYgaXNIZXhEaWdpdChkYXRhWzFdKSAmJiBpc0hleERpZ2l0KGRhdGFbMl0pICYmIGlzSGV4RGlnaXQoZGF0YVszXSkgJiYgaXNIZXhEaWdpdChkYXRhWzRdKSAmJiBpc0hleERpZ2l0KGRhdGFbNV0pICYmIGlzSGV4RGlnaXQoZGF0YVs2XSkgJiYgaXNIZXhEaWdpdChkYXRhWzddKSk7CiAgICAgIHN0cmVhbSA9IG5ldyBfc3RyZWFtLlN0cmVhbShpc0JpbmFyeSA/IGRlY3J5cHQoZGF0YSwgRUVYRUNfRU5DUllQVF9LRVksIDQpIDogZGVjcnlwdEFzY2lpKGRhdGEsIEVFWEVDX0VOQ1JZUFRfS0VZLCA0KSk7CiAgICB9CiAgICB0aGlzLnNlYWNBbmFseXNpc0VuYWJsZWQgPSAhIXNlYWNBbmFseXNpc0VuYWJsZWQ7CiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTsKICAgIHRoaXMubmV4dENoYXIoKTsKICB9CiAgcmVhZE51bWJlckFycmF5KCkgewogICAgdGhpcy5nZXRUb2tlbigpOwogICAgY29uc3QgYXJyYXkgPSBbXTsKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIGNvbnN0IHRva2VuID0gdGhpcy5nZXRUb2tlbigpOwogICAgICBpZiAodG9rZW4gPT09IG51bGwgfHwgdG9rZW4gPT09ICJdIiB8fCB0b2tlbiA9PT0gIn0iKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgYXJyYXkucHVzaChwYXJzZUZsb2F0KHRva2VuIHx8IDApKTsKICAgIH0KICAgIHJldHVybiBhcnJheTsKICB9CiAgcmVhZE51bWJlcigpIHsKICAgIGNvbnN0IHRva2VuID0gdGhpcy5nZXRUb2tlbigpOwogICAgcmV0dXJuIHBhcnNlRmxvYXQodG9rZW4gfHwgMCk7CiAgfQogIHJlYWRJbnQoKSB7CiAgICBjb25zdCB0b2tlbiA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgIHJldHVybiBwYXJzZUludCh0b2tlbiB8fCAwLCAxMCkgfCAwOwogIH0KICByZWFkQm9vbGVhbigpIHsKICAgIGNvbnN0IHRva2VuID0gdGhpcy5nZXRUb2tlbigpOwogICAgcmV0dXJuIHRva2VuID09PSAidHJ1ZSIgPyAxIDogMDsKICB9CiAgbmV4dENoYXIoKSB7CiAgICByZXR1cm4gdGhpcy5jdXJyZW50Q2hhciA9IHRoaXMuc3RyZWFtLmdldEJ5dGUoKTsKICB9CiAgcHJldkNoYXIoKSB7CiAgICB0aGlzLnN0cmVhbS5za2lwKC0yKTsKICAgIHJldHVybiB0aGlzLmN1cnJlbnRDaGFyID0gdGhpcy5zdHJlYW0uZ2V0Qnl0ZSgpOwogIH0KICBnZXRUb2tlbigpIHsKICAgIGxldCBjb21tZW50ID0gZmFsc2U7CiAgICBsZXQgY2ggPSB0aGlzLmN1cnJlbnRDaGFyOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgaWYgKGNoID09PSAtMSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGlmIChjb21tZW50KSB7CiAgICAgICAgaWYgKGNoID09PSAweDBhIHx8IGNoID09PSAweDBkKSB7CiAgICAgICAgICBjb21tZW50ID0gZmFsc2U7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGNoID09PSAweDI1KSB7CiAgICAgICAgY29tbWVudCA9IHRydWU7CiAgICAgIH0gZWxzZSBpZiAoISgwLCBfY29yZV91dGlscy5pc1doaXRlU3BhY2UpKGNoKSkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgfQogICAgaWYgKGlzU3BlY2lhbChjaCkpIHsKICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICB9CiAgICBsZXQgdG9rZW4gPSAiIjsKICAgIGRvIHsKICAgICAgdG9rZW4gKz0gU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgfSB3aGlsZSAoY2ggPj0gMCAmJiAhKDAsIF9jb3JlX3V0aWxzLmlzV2hpdGVTcGFjZSkoY2gpICYmICFpc1NwZWNpYWwoY2gpKTsKICAgIHJldHVybiB0b2tlbjsKICB9CiAgcmVhZENoYXJTdHJpbmdzKGJ5dGVzLCBsZW5JVikgewogICAgaWYgKGxlbklWID09PSAtMSkgewogICAgICByZXR1cm4gYnl0ZXM7CiAgICB9CiAgICByZXR1cm4gZGVjcnlwdChieXRlcywgQ0hBUl9TVFJTX0VOQ1JZUFRfS0VZLCBsZW5JVik7CiAgfQogIGV4dHJhY3RGb250UHJvZ3JhbShwcm9wZXJ0aWVzKSB7CiAgICBjb25zdCBzdHJlYW0gPSB0aGlzLnN0cmVhbTsKICAgIGNvbnN0IHN1YnJzID0gW10sCiAgICAgIGNoYXJzdHJpbmdzID0gW107CiAgICBjb25zdCBwcml2YXRlRGF0YSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBwcml2YXRlRGF0YS5sZW5JViA9IDQ7CiAgICBjb25zdCBwcm9ncmFtID0gewogICAgICBzdWJyczogW10sCiAgICAgIGNoYXJzdHJpbmdzOiBbXSwKICAgICAgcHJvcGVydGllczogewogICAgICAgIHByaXZhdGVEYXRhCiAgICAgIH0KICAgIH07CiAgICBsZXQgdG9rZW4sIGxlbmd0aCwgZGF0YSwgbGVuSVY7CiAgICB3aGlsZSAoKHRva2VuID0gdGhpcy5nZXRUb2tlbigpKSAhPT0gbnVsbCkgewogICAgICBpZiAodG9rZW4gIT09ICIvIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHRva2VuID0gdGhpcy5nZXRUb2tlbigpOwogICAgICBzd2l0Y2ggKHRva2VuKSB7CiAgICAgICAgY2FzZSAiQ2hhclN0cmluZ3MiOgogICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICAgICAgdG9rZW4gPSB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICAgIGlmICh0b2tlbiA9PT0gbnVsbCB8fCB0b2tlbiA9PT0gImVuZCIpIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodG9rZW4gIT09ICIvIikgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGdseXBoID0gdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICBsZW5ndGggPSB0aGlzLnJlYWRJbnQoKTsKICAgICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICBkYXRhID0gbGVuZ3RoID4gMCA/IHN0cmVhbS5nZXRCeXRlcyhsZW5ndGgpIDogbmV3IFVpbnQ4QXJyYXkoMCk7CiAgICAgICAgICAgIGxlbklWID0gcHJvZ3JhbS5wcm9wZXJ0aWVzLnByaXZhdGVEYXRhLmxlbklWOwogICAgICAgICAgICBjb25zdCBlbmNvZGVkID0gdGhpcy5yZWFkQ2hhclN0cmluZ3MoZGF0YSwgbGVuSVYpOwogICAgICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgICAgIHRva2VuID0gdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICBpZiAodG9rZW4gPT09ICJub2FjY2VzcyIpIHsKICAgICAgICAgICAgICB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAodG9rZW4gPT09ICIvIikgewogICAgICAgICAgICAgIHRoaXMucHJldkNoYXIoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjaGFyc3RyaW5ncy5wdXNoKHsKICAgICAgICAgICAgICBnbHlwaCwKICAgICAgICAgICAgICBlbmNvZGVkCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiU3VicnMiOgogICAgICAgICAgdGhpcy5yZWFkSW50KCk7CiAgICAgICAgICB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICB3aGlsZSAodGhpcy5nZXRUb2tlbigpID09PSAiZHVwIikgewogICAgICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMucmVhZEludCgpOwogICAgICAgICAgICBsZW5ndGggPSB0aGlzLnJlYWRJbnQoKTsKICAgICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICBkYXRhID0gbGVuZ3RoID4gMCA/IHN0cmVhbS5nZXRCeXRlcyhsZW5ndGgpIDogbmV3IFVpbnQ4QXJyYXkoMCk7CiAgICAgICAgICAgIGxlbklWID0gcHJvZ3JhbS5wcm9wZXJ0aWVzLnByaXZhdGVEYXRhLmxlbklWOwogICAgICAgICAgICBjb25zdCBlbmNvZGVkID0gdGhpcy5yZWFkQ2hhclN0cmluZ3MoZGF0YSwgbGVuSVYpOwogICAgICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgICAgIHRva2VuID0gdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICBpZiAodG9rZW4gPT09ICJub2FjY2VzcyIpIHsKICAgICAgICAgICAgICB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3VicnNbaW5kZXhdID0gZW5jb2RlZDsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkJsdWVWYWx1ZXMiOgogICAgICAgIGNhc2UgIk90aGVyQmx1ZXMiOgogICAgICAgIGNhc2UgIkZhbWlseUJsdWVzIjoKICAgICAgICBjYXNlICJGYW1pbHlPdGhlckJsdWVzIjoKICAgICAgICAgIGNvbnN0IGJsdWVBcnJheSA9IHRoaXMucmVhZE51bWJlckFycmF5KCk7CiAgICAgICAgICBpZiAoYmx1ZUFycmF5Lmxlbmd0aCA+IDAgJiYgYmx1ZUFycmF5Lmxlbmd0aCAlIDIgPT09IDAgJiYgSElOVElOR19FTkFCTEVEKSB7CiAgICAgICAgICAgIHByb2dyYW0ucHJvcGVydGllcy5wcml2YXRlRGF0YVt0b2tlbl0gPSBibHVlQXJyYXk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJTdGVtU25hcEgiOgogICAgICAgIGNhc2UgIlN0ZW1TbmFwViI6CiAgICAgICAgICBwcm9ncmFtLnByb3BlcnRpZXMucHJpdmF0ZURhdGFbdG9rZW5dID0gdGhpcy5yZWFkTnVtYmVyQXJyYXkoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlN0ZEhXIjoKICAgICAgICBjYXNlICJTdGRWVyI6CiAgICAgICAgICBwcm9ncmFtLnByb3BlcnRpZXMucHJpdmF0ZURhdGFbdG9rZW5dID0gdGhpcy5yZWFkTnVtYmVyQXJyYXkoKVswXTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkJsdWVTaGlmdCI6CiAgICAgICAgY2FzZSAibGVuSVYiOgogICAgICAgIGNhc2UgIkJsdWVGdXp6IjoKICAgICAgICBjYXNlICJCbHVlU2NhbGUiOgogICAgICAgIGNhc2UgIkxhbmd1YWdlR3JvdXAiOgogICAgICAgICAgcHJvZ3JhbS5wcm9wZXJ0aWVzLnByaXZhdGVEYXRhW3Rva2VuXSA9IHRoaXMucmVhZE51bWJlcigpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiRXhwYW5zaW9uRmFjdG9yIjoKICAgICAgICAgIHByb2dyYW0ucHJvcGVydGllcy5wcml2YXRlRGF0YVt0b2tlbl0gPSB0aGlzLnJlYWROdW1iZXIoKSB8fCAwLjA2OwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiRm9yY2VCb2xkIjoKICAgICAgICAgIHByb2dyYW0ucHJvcGVydGllcy5wcml2YXRlRGF0YVt0b2tlbl0gPSB0aGlzLnJlYWRCb29sZWFuKCk7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgZm9yIChjb25zdCB7CiAgICAgIGVuY29kZWQsCiAgICAgIGdseXBoCiAgICB9IG9mIGNoYXJzdHJpbmdzKSB7CiAgICAgIGNvbnN0IGNoYXJTdHJpbmcgPSBuZXcgVHlwZTFDaGFyU3RyaW5nKCk7CiAgICAgIGNvbnN0IGVycm9yID0gY2hhclN0cmluZy5jb252ZXJ0KGVuY29kZWQsIHN1YnJzLCB0aGlzLnNlYWNBbmFseXNpc0VuYWJsZWQpOwogICAgICBsZXQgb3V0cHV0ID0gY2hhclN0cmluZy5vdXRwdXQ7CiAgICAgIGlmIChlcnJvcikgewogICAgICAgIG91dHB1dCA9IFsxNF07CiAgICAgIH0KICAgICAgY29uc3QgY2hhclN0cmluZ09iamVjdCA9IHsKICAgICAgICBnbHlwaE5hbWU6IGdseXBoLAogICAgICAgIGNoYXJzdHJpbmc6IG91dHB1dCwKICAgICAgICB3aWR0aDogY2hhclN0cmluZy53aWR0aCwKICAgICAgICBsc2I6IGNoYXJTdHJpbmcubHNiLAogICAgICAgIHNlYWM6IGNoYXJTdHJpbmcuc2VhYwogICAgICB9OwogICAgICBpZiAoZ2x5cGggPT09ICIubm90ZGVmIikgewogICAgICAgIHByb2dyYW0uY2hhcnN0cmluZ3MudW5zaGlmdChjaGFyU3RyaW5nT2JqZWN0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBwcm9ncmFtLmNoYXJzdHJpbmdzLnB1c2goY2hhclN0cmluZ09iamVjdCk7CiAgICAgIH0KICAgICAgaWYgKHByb3BlcnRpZXMuYnVpbHRJbkVuY29kaW5nKSB7CiAgICAgICAgY29uc3QgaW5kZXggPSBwcm9wZXJ0aWVzLmJ1aWx0SW5FbmNvZGluZy5pbmRleE9mKGdseXBoKTsKICAgICAgICBpZiAoaW5kZXggPiAtMSAmJiBwcm9wZXJ0aWVzLndpZHRoc1tpbmRleF0gPT09IHVuZGVmaW5lZCAmJiBpbmRleCA+PSBwcm9wZXJ0aWVzLmZpcnN0Q2hhciAmJiBpbmRleCA8PSBwcm9wZXJ0aWVzLmxhc3RDaGFyKSB7CiAgICAgICAgICBwcm9wZXJ0aWVzLndpZHRoc1tpbmRleF0gPSBjaGFyU3RyaW5nLndpZHRoOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIHByb2dyYW07CiAgfQogIGV4dHJhY3RGb250SGVhZGVyKHByb3BlcnRpZXMpIHsKICAgIGxldCB0b2tlbjsKICAgIHdoaWxlICgodG9rZW4gPSB0aGlzLmdldFRva2VuKCkpICE9PSBudWxsKSB7CiAgICAgIGlmICh0b2tlbiAhPT0gIi8iKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgdG9rZW4gPSB0aGlzLmdldFRva2VuKCk7CiAgICAgIHN3aXRjaCAodG9rZW4pIHsKICAgICAgICBjYXNlICJGb250TWF0cml4IjoKICAgICAgICAgIGNvbnN0IG1hdHJpeCA9IHRoaXMucmVhZE51bWJlckFycmF5KCk7CiAgICAgICAgICBwcm9wZXJ0aWVzLmZvbnRNYXRyaXggPSBtYXRyaXg7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJFbmNvZGluZyI6CiAgICAgICAgICBjb25zdCBlbmNvZGluZ0FyZyA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgIGxldCBlbmNvZGluZzsKICAgICAgICAgIGlmICghL15cZCskLy50ZXN0KGVuY29kaW5nQXJnKSkgewogICAgICAgICAgICBlbmNvZGluZyA9ICgwLCBfZW5jb2RpbmdzLmdldEVuY29kaW5nKShlbmNvZGluZ0FyZyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbmNvZGluZyA9IFtdOwogICAgICAgICAgICBjb25zdCBzaXplID0gcGFyc2VJbnQoZW5jb2RpbmdBcmcsIDEwKSB8IDA7CiAgICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBzaXplOyBqKyspIHsKICAgICAgICAgICAgICB0b2tlbiA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgICB3aGlsZSAodG9rZW4gIT09ICJkdXAiICYmIHRva2VuICE9PSAiZGVmIikgewogICAgICAgICAgICAgICAgdG9rZW4gPSB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICAgICAgICBpZiAodG9rZW4gPT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAodG9rZW4gPT09ICJkZWYiKSB7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnJlYWRJbnQoKTsKICAgICAgICAgICAgICB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICAgICAgY29uc3QgZ2x5cGggPSB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICAgICAgZW5jb2RpbmdbaW5kZXhdID0gZ2x5cGg7CiAgICAgICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBwcm9wZXJ0aWVzLmJ1aWx0SW5FbmNvZGluZyA9IGVuY29kaW5nOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiRm9udEJCb3giOgogICAgICAgICAgY29uc3QgZm9udEJCb3ggPSB0aGlzLnJlYWROdW1iZXJBcnJheSgpOwogICAgICAgICAgcHJvcGVydGllcy5hc2NlbnQgPSBNYXRoLm1heChmb250QkJveFszXSwgZm9udEJCb3hbMV0pOwogICAgICAgICAgcHJvcGVydGllcy5kZXNjZW50ID0gTWF0aC5taW4oZm9udEJCb3hbMV0sIGZvbnRCQm94WzNdKTsKICAgICAgICAgIHByb3BlcnRpZXMuYXNjZW50U2NhbGVkID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQp9CmV4cG9ydHMuVHlwZTFQYXJzZXIgPSBUeXBlMVBhcnNlcjsKCi8qKiovIH0pLAovKiAxODUgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlBhdHRlcm4gPSB2b2lkIDA7CmV4cG9ydHMuZ2V0VGlsaW5nUGF0dGVybklSID0gZ2V0VGlsaW5nUGF0dGVybklSOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwp2YXIgX2Jhc2Vfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDEpOwp2YXIgX2NvbG9yc3BhY2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0OCk7CnZhciBfY29yZV91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTM5KTsKY29uc3QgU2hhZGluZ1R5cGUgPSB7CiAgRlVOQ1RJT05fQkFTRUQ6IDEsCiAgQVhJQUw6IDIsCiAgUkFESUFMOiAzLAogIEZSRUVfRk9STV9NRVNIOiA0LAogIExBVFRJQ0VfRk9STV9NRVNIOiA1LAogIENPT05TX1BBVENIX01FU0g6IDYsCiAgVEVOU09SX1BBVENIX01FU0g6IDcKfTsKY2xhc3MgUGF0dGVybiB7CiAgY29uc3RydWN0b3IoKSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJDYW5ub3QgaW5pdGlhbGl6ZSBQYXR0ZXJuLiIpOwogIH0KICBzdGF0aWMgcGFyc2VTaGFkaW5nKHNoYWRpbmcsIHhyZWYsIHJlcywgcGRmRnVuY3Rpb25GYWN0b3J5LCBsb2NhbENvbG9yU3BhY2VDYWNoZSkgewogICAgY29uc3QgZGljdCA9IHNoYWRpbmcgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSA/IHNoYWRpbmcuZGljdCA6IHNoYWRpbmc7CiAgICBjb25zdCB0eXBlID0gZGljdC5nZXQoIlNoYWRpbmdUeXBlIik7CiAgICB0cnkgewogICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICBjYXNlIFNoYWRpbmdUeXBlLkFYSUFMOgogICAgICAgIGNhc2UgU2hhZGluZ1R5cGUuUkFESUFMOgogICAgICAgICAgcmV0dXJuIG5ldyBSYWRpYWxBeGlhbFNoYWRpbmcoZGljdCwgeHJlZiwgcmVzLCBwZGZGdW5jdGlvbkZhY3RvcnksIGxvY2FsQ29sb3JTcGFjZUNhY2hlKTsKICAgICAgICBjYXNlIFNoYWRpbmdUeXBlLkZSRUVfRk9STV9NRVNIOgogICAgICAgIGNhc2UgU2hhZGluZ1R5cGUuTEFUVElDRV9GT1JNX01FU0g6CiAgICAgICAgY2FzZSBTaGFkaW5nVHlwZS5DT09OU19QQVRDSF9NRVNIOgogICAgICAgIGNhc2UgU2hhZGluZ1R5cGUuVEVOU09SX1BBVENIX01FU0g6CiAgICAgICAgICByZXR1cm4gbmV3IE1lc2hTaGFkaW5nKHNoYWRpbmcsIHhyZWYsIHJlcywgcGRmRnVuY3Rpb25GYWN0b3J5LCBsb2NhbENvbG9yU3BhY2VDYWNoZSk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiVW5zdXBwb3J0ZWQgU2hhZGluZ1R5cGU6ICIgKyB0eXBlKTsKICAgICAgfQogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgX2NvcmVfdXRpbHMuTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICAoMCwgX3V0aWwud2FybikoZXgpOwogICAgICByZXR1cm4gbmV3IER1bW15U2hhZGluZygpOwogICAgfQogIH0KfQpleHBvcnRzLlBhdHRlcm4gPSBQYXR0ZXJuOwpjbGFzcyBCYXNlU2hhZGluZyB7CiAgc3RhdGljIGdldCBTTUFMTF9OVU1CRVIoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIlNNQUxMX05VTUJFUiIsIDFlLTYpOwogIH0KICBjb25zdHJ1Y3RvcigpIHsKICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yID09PSBCYXNlU2hhZGluZykgewogICAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJDYW5ub3QgaW5pdGlhbGl6ZSBCYXNlU2hhZGluZy4iKTsKICAgIH0KICB9CiAgZ2V0SVIoKSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJBYnN0cmFjdCBtZXRob2QgYGdldElSYCBjYWxsZWQuIik7CiAgfQp9CmNsYXNzIFJhZGlhbEF4aWFsU2hhZGluZyBleHRlbmRzIEJhc2VTaGFkaW5nIHsKICBjb25zdHJ1Y3RvcihkaWN0LCB4cmVmLCByZXNvdXJjZXMsIHBkZkZ1bmN0aW9uRmFjdG9yeSwgbG9jYWxDb2xvclNwYWNlQ2FjaGUpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLmNvb3Jkc0FyciA9IGRpY3QuZ2V0QXJyYXkoIkNvb3JkcyIpOwogICAgdGhpcy5zaGFkaW5nVHlwZSA9IGRpY3QuZ2V0KCJTaGFkaW5nVHlwZSIpOwogICAgY29uc3QgY3MgPSBfY29sb3JzcGFjZS5Db2xvclNwYWNlLnBhcnNlKHsKICAgICAgY3M6IGRpY3QuZ2V0UmF3KCJDUyIpIHx8IGRpY3QuZ2V0UmF3KCJDb2xvclNwYWNlIiksCiAgICAgIHhyZWYsCiAgICAgIHJlc291cmNlcywKICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgfSk7CiAgICBjb25zdCBiYm94ID0gZGljdC5nZXRBcnJheSgiQkJveCIpOwogICAgaWYgKEFycmF5LmlzQXJyYXkoYmJveCkgJiYgYmJveC5sZW5ndGggPT09IDQpIHsKICAgICAgdGhpcy5iYm94ID0gX3V0aWwuVXRpbC5ub3JtYWxpemVSZWN0KGJib3gpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5iYm94ID0gbnVsbDsKICAgIH0KICAgIGxldCB0MCA9IDAuMCwKICAgICAgdDEgPSAxLjA7CiAgICBpZiAoZGljdC5oYXMoIkRvbWFpbiIpKSB7CiAgICAgIGNvbnN0IGRvbWFpbkFyciA9IGRpY3QuZ2V0QXJyYXkoIkRvbWFpbiIpOwogICAgICB0MCA9IGRvbWFpbkFyclswXTsKICAgICAgdDEgPSBkb21haW5BcnJbMV07CiAgICB9CiAgICBsZXQgZXh0ZW5kU3RhcnQgPSBmYWxzZSwKICAgICAgZXh0ZW5kRW5kID0gZmFsc2U7CiAgICBpZiAoZGljdC5oYXMoIkV4dGVuZCIpKSB7CiAgICAgIGNvbnN0IGV4dGVuZEFyciA9IGRpY3QuZ2V0QXJyYXkoIkV4dGVuZCIpOwogICAgICBleHRlbmRTdGFydCA9IGV4dGVuZEFyclswXTsKICAgICAgZXh0ZW5kRW5kID0gZXh0ZW5kQXJyWzFdOwogICAgfQogICAgaWYgKHRoaXMuc2hhZGluZ1R5cGUgPT09IFNoYWRpbmdUeXBlLlJBRElBTCAmJiAoIWV4dGVuZFN0YXJ0IHx8ICFleHRlbmRFbmQpKSB7CiAgICAgIGNvbnN0IFt4MSwgeTEsIHIxLCB4MiwgeTIsIHIyXSA9IHRoaXMuY29vcmRzQXJyOwogICAgICBjb25zdCBkaXN0YW5jZSA9IE1hdGguaHlwb3QoeDEgLSB4MiwgeTEgLSB5Mik7CiAgICAgIGlmIChyMSA8PSByMiArIGRpc3RhbmNlICYmIHIyIDw9IHIxICsgZGlzdGFuY2UpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoIlVuc3VwcG9ydGVkIHJhZGlhbCBncmFkaWVudC4iKTsKICAgICAgfQogICAgfQogICAgdGhpcy5leHRlbmRTdGFydCA9IGV4dGVuZFN0YXJ0OwogICAgdGhpcy5leHRlbmRFbmQgPSBleHRlbmRFbmQ7CiAgICBjb25zdCBmbk9iaiA9IGRpY3QuZ2V0UmF3KCJGdW5jdGlvbiIpOwogICAgY29uc3QgZm4gPSBwZGZGdW5jdGlvbkZhY3RvcnkuY3JlYXRlRnJvbUFycmF5KGZuT2JqKTsKICAgIGNvbnN0IE5VTUJFUl9PRl9TQU1QTEVTID0gMTA7CiAgICBjb25zdCBzdGVwID0gKHQxIC0gdDApIC8gTlVNQkVSX09GX1NBTVBMRVM7CiAgICBjb25zdCBjb2xvclN0b3BzID0gdGhpcy5jb2xvclN0b3BzID0gW107CiAgICBpZiAodDAgPj0gdDEgfHwgc3RlcCA8PSAwKSB7CiAgICAgICgwLCBfdXRpbC5pbmZvKSgiQmFkIHNoYWRpbmcgZG9tYWluLiIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBjb2xvciA9IG5ldyBGbG9hdDMyQXJyYXkoY3MubnVtQ29tcHMpLAogICAgICByYXRpbyA9IG5ldyBGbG9hdDMyQXJyYXkoMSk7CiAgICBsZXQgcmdiQ29sb3I7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8PSBOVU1CRVJfT0ZfU0FNUExFUzsgaSsrKSB7CiAgICAgIHJhdGlvWzBdID0gdDAgKyBpICogc3RlcDsKICAgICAgZm4ocmF0aW8sIDAsIGNvbG9yLCAwKTsKICAgICAgcmdiQ29sb3IgPSBjcy5nZXRSZ2IoY29sb3IsIDApOwogICAgICBjb25zdCBjc3NDb2xvciA9IF91dGlsLlV0aWwubWFrZUhleENvbG9yKHJnYkNvbG9yWzBdLCByZ2JDb2xvclsxXSwgcmdiQ29sb3JbMl0pOwogICAgICBjb2xvclN0b3BzLnB1c2goW2kgLyBOVU1CRVJfT0ZfU0FNUExFUywgY3NzQ29sb3JdKTsKICAgIH0KICAgIGxldCBiYWNrZ3JvdW5kID0gInRyYW5zcGFyZW50IjsKICAgIGlmIChkaWN0LmhhcygiQmFja2dyb3VuZCIpKSB7CiAgICAgIHJnYkNvbG9yID0gY3MuZ2V0UmdiKGRpY3QuZ2V0KCJCYWNrZ3JvdW5kIiksIDApOwogICAgICBiYWNrZ3JvdW5kID0gX3V0aWwuVXRpbC5tYWtlSGV4Q29sb3IocmdiQ29sb3JbMF0sIHJnYkNvbG9yWzFdLCByZ2JDb2xvclsyXSk7CiAgICB9CiAgICBpZiAoIWV4dGVuZFN0YXJ0KSB7CiAgICAgIGNvbG9yU3RvcHMudW5zaGlmdChbMCwgYmFja2dyb3VuZF0pOwogICAgICBjb2xvclN0b3BzWzFdWzBdICs9IEJhc2VTaGFkaW5nLlNNQUxMX05VTUJFUjsKICAgIH0KICAgIGlmICghZXh0ZW5kRW5kKSB7CiAgICAgIGNvbG9yU3RvcHMuYXQoLTEpWzBdIC09IEJhc2VTaGFkaW5nLlNNQUxMX05VTUJFUjsKICAgICAgY29sb3JTdG9wcy5wdXNoKFsxLCBiYWNrZ3JvdW5kXSk7CiAgICB9CiAgICB0aGlzLmNvbG9yU3RvcHMgPSBjb2xvclN0b3BzOwogIH0KICBnZXRJUigpIHsKICAgIGNvbnN0IGNvb3Jkc0FyciA9IHRoaXMuY29vcmRzQXJyOwogICAgY29uc3Qgc2hhZGluZ1R5cGUgPSB0aGlzLnNoYWRpbmdUeXBlOwogICAgbGV0IHR5cGUsIHAwLCBwMSwgcjAsIHIxOwogICAgaWYgKHNoYWRpbmdUeXBlID09PSBTaGFkaW5nVHlwZS5BWElBTCkgewogICAgICBwMCA9IFtjb29yZHNBcnJbMF0sIGNvb3Jkc0FyclsxXV07CiAgICAgIHAxID0gW2Nvb3Jkc0FyclsyXSwgY29vcmRzQXJyWzNdXTsKICAgICAgcjAgPSBudWxsOwogICAgICByMSA9IG51bGw7CiAgICAgIHR5cGUgPSAiYXhpYWwiOwogICAgfSBlbHNlIGlmIChzaGFkaW5nVHlwZSA9PT0gU2hhZGluZ1R5cGUuUkFESUFMKSB7CiAgICAgIHAwID0gW2Nvb3Jkc0FyclswXSwgY29vcmRzQXJyWzFdXTsKICAgICAgcDEgPSBbY29vcmRzQXJyWzNdLCBjb29yZHNBcnJbNF1dOwogICAgICByMCA9IGNvb3Jkc0FyclsyXTsKICAgICAgcjEgPSBjb29yZHNBcnJbNV07CiAgICAgIHR5cGUgPSAicmFkaWFsIjsKICAgIH0gZWxzZSB7CiAgICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoYGdldFBhdHRlcm4gdHlwZSB1bmtub3duOiAke3NoYWRpbmdUeXBlfWApOwogICAgfQogICAgcmV0dXJuIFsiUmFkaWFsQXhpYWwiLCB0eXBlLCB0aGlzLmJib3gsIHRoaXMuY29sb3JTdG9wcywgcDAsIHAxLCByMCwgcjFdOwogIH0KfQpjbGFzcyBNZXNoU3RyZWFtUmVhZGVyIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIGNvbnRleHQpIHsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDsKICAgIHRoaXMuYnVmZmVyID0gMDsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gMDsKICAgIGNvbnN0IG51bUNvbXBzID0gY29udGV4dC5udW1Db21wczsKICAgIHRoaXMudG1wQ29tcHNCdWYgPSBuZXcgRmxvYXQzMkFycmF5KG51bUNvbXBzKTsKICAgIGNvbnN0IGNzTnVtQ29tcHMgPSBjb250ZXh0LmNvbG9yU3BhY2UubnVtQ29tcHM7CiAgICB0aGlzLnRtcENzQ29tcHNCdWYgPSBjb250ZXh0LmNvbG9yRm4gPyBuZXcgRmxvYXQzMkFycmF5KGNzTnVtQ29tcHMpIDogdGhpcy50bXBDb21wc0J1ZjsKICB9CiAgZ2V0IGhhc0RhdGEoKSB7CiAgICBpZiAodGhpcy5zdHJlYW0uZW5kKSB7CiAgICAgIHJldHVybiB0aGlzLnN0cmVhbS5wb3MgPCB0aGlzLnN0cmVhbS5lbmQ7CiAgICB9CiAgICBpZiAodGhpcy5idWZmZXJMZW5ndGggPiAwKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgY29uc3QgbmV4dEJ5dGUgPSB0aGlzLnN0cmVhbS5nZXRCeXRlKCk7CiAgICBpZiAobmV4dEJ5dGUgPCAwKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHRoaXMuYnVmZmVyID0gbmV4dEJ5dGU7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IDg7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgcmVhZEJpdHMobikgewogICAgbGV0IGJ1ZmZlciA9IHRoaXMuYnVmZmVyOwogICAgbGV0IGJ1ZmZlckxlbmd0aCA9IHRoaXMuYnVmZmVyTGVuZ3RoOwogICAgaWYgKG4gPT09IDMyKSB7CiAgICAgIGlmIChidWZmZXJMZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gKHRoaXMuc3RyZWFtLmdldEJ5dGUoKSA8PCAyNCB8IHRoaXMuc3RyZWFtLmdldEJ5dGUoKSA8PCAxNiB8IHRoaXMuc3RyZWFtLmdldEJ5dGUoKSA8PCA4IHwgdGhpcy5zdHJlYW0uZ2V0Qnl0ZSgpKSA+Pj4gMDsKICAgICAgfQogICAgICBidWZmZXIgPSBidWZmZXIgPDwgMjQgfCB0aGlzLnN0cmVhbS5nZXRCeXRlKCkgPDwgMTYgfCB0aGlzLnN0cmVhbS5nZXRCeXRlKCkgPDwgOCB8IHRoaXMuc3RyZWFtLmdldEJ5dGUoKTsKICAgICAgY29uc3QgbmV4dEJ5dGUgPSB0aGlzLnN0cmVhbS5nZXRCeXRlKCk7CiAgICAgIHRoaXMuYnVmZmVyID0gbmV4dEJ5dGUgJiAoMSA8PCBidWZmZXJMZW5ndGgpIC0gMTsKICAgICAgcmV0dXJuIChidWZmZXIgPDwgOCAtIGJ1ZmZlckxlbmd0aCB8IChuZXh0Qnl0ZSAmIDB4ZmYpID4+IGJ1ZmZlckxlbmd0aCkgPj4+IDA7CiAgICB9CiAgICBpZiAobiA9PT0gOCAmJiBidWZmZXJMZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIHRoaXMuc3RyZWFtLmdldEJ5dGUoKTsKICAgIH0KICAgIHdoaWxlIChidWZmZXJMZW5ndGggPCBuKSB7CiAgICAgIGJ1ZmZlciA9IGJ1ZmZlciA8PCA4IHwgdGhpcy5zdHJlYW0uZ2V0Qnl0ZSgpOwogICAgICBidWZmZXJMZW5ndGggKz0gODsKICAgIH0KICAgIGJ1ZmZlckxlbmd0aCAtPSBuOwogICAgdGhpcy5idWZmZXJMZW5ndGggPSBidWZmZXJMZW5ndGg7CiAgICB0aGlzLmJ1ZmZlciA9IGJ1ZmZlciAmICgxIDw8IGJ1ZmZlckxlbmd0aCkgLSAxOwogICAgcmV0dXJuIGJ1ZmZlciA+PiBidWZmZXJMZW5ndGg7CiAgfQogIGFsaWduKCkgewogICAgdGhpcy5idWZmZXIgPSAwOwogICAgdGhpcy5idWZmZXJMZW5ndGggPSAwOwogIH0KICByZWFkRmxhZygpIHsKICAgIHJldHVybiB0aGlzLnJlYWRCaXRzKHRoaXMuY29udGV4dC5iaXRzUGVyRmxhZyk7CiAgfQogIHJlYWRDb29yZGluYXRlKCkgewogICAgY29uc3QgYml0c1BlckNvb3JkaW5hdGUgPSB0aGlzLmNvbnRleHQuYml0c1BlckNvb3JkaW5hdGU7CiAgICBjb25zdCB4aSA9IHRoaXMucmVhZEJpdHMoYml0c1BlckNvb3JkaW5hdGUpOwogICAgY29uc3QgeWkgPSB0aGlzLnJlYWRCaXRzKGJpdHNQZXJDb29yZGluYXRlKTsKICAgIGNvbnN0IGRlY29kZSA9IHRoaXMuY29udGV4dC5kZWNvZGU7CiAgICBjb25zdCBzY2FsZSA9IGJpdHNQZXJDb29yZGluYXRlIDwgMzIgPyAxIC8gKCgxIDw8IGJpdHNQZXJDb29yZGluYXRlKSAtIDEpIDogMi4zMjgzMDY0MzY1Mzg2OTYzZS0xMDsKICAgIHJldHVybiBbeGkgKiBzY2FsZSAqIChkZWNvZGVbMV0gLSBkZWNvZGVbMF0pICsgZGVjb2RlWzBdLCB5aSAqIHNjYWxlICogKGRlY29kZVszXSAtIGRlY29kZVsyXSkgKyBkZWNvZGVbMl1dOwogIH0KICByZWFkQ29tcG9uZW50cygpIHsKICAgIGNvbnN0IG51bUNvbXBzID0gdGhpcy5jb250ZXh0Lm51bUNvbXBzOwogICAgY29uc3QgYml0c1BlckNvbXBvbmVudCA9IHRoaXMuY29udGV4dC5iaXRzUGVyQ29tcG9uZW50OwogICAgY29uc3Qgc2NhbGUgPSBiaXRzUGVyQ29tcG9uZW50IDwgMzIgPyAxIC8gKCgxIDw8IGJpdHNQZXJDb21wb25lbnQpIC0gMSkgOiAyLjMyODMwNjQzNjUzODY5NjNlLTEwOwogICAgY29uc3QgZGVjb2RlID0gdGhpcy5jb250ZXh0LmRlY29kZTsKICAgIGNvbnN0IGNvbXBvbmVudHMgPSB0aGlzLnRtcENvbXBzQnVmOwogICAgZm9yIChsZXQgaSA9IDAsIGogPSA0OyBpIDwgbnVtQ29tcHM7IGkrKywgaiArPSAyKSB7CiAgICAgIGNvbnN0IGNpID0gdGhpcy5yZWFkQml0cyhiaXRzUGVyQ29tcG9uZW50KTsKICAgICAgY29tcG9uZW50c1tpXSA9IGNpICogc2NhbGUgKiAoZGVjb2RlW2ogKyAxXSAtIGRlY29kZVtqXSkgKyBkZWNvZGVbal07CiAgICB9CiAgICBjb25zdCBjb2xvciA9IHRoaXMudG1wQ3NDb21wc0J1ZjsKICAgIGlmICh0aGlzLmNvbnRleHQuY29sb3JGbikgewogICAgICB0aGlzLmNvbnRleHQuY29sb3JGbihjb21wb25lbnRzLCAwLCBjb2xvciwgMCk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5jb250ZXh0LmNvbG9yU3BhY2UuZ2V0UmdiKGNvbG9yLCAwKTsKICB9Cn0KY29uc3QgZ2V0QiA9IGZ1bmN0aW9uIGdldEJDbG9zdXJlKCkgewogIGZ1bmN0aW9uIGJ1aWxkQihjb3VudCkgewogICAgY29uc3QgbHV0ID0gW107CiAgICBmb3IgKGxldCBpID0gMDsgaSA8PSBjb3VudDsgaSsrKSB7CiAgICAgIGNvbnN0IHQgPSBpIC8gY291bnQsCiAgICAgICAgdF8gPSAxIC0gdDsKICAgICAgbHV0LnB1c2gobmV3IEZsb2F0MzJBcnJheShbdF8gKiB0XyAqIHRfLCAzICogdCAqIHRfICogdF8sIDMgKiB0ICogdCAqIHRfLCB0ICogdCAqIHRdKSk7CiAgICB9CiAgICByZXR1cm4gbHV0OwogIH0KICBjb25zdCBjYWNoZSA9IFtdOwogIHJldHVybiBmdW5jdGlvbiAoY291bnQpIHsKICAgIGlmICghY2FjaGVbY291bnRdKSB7CiAgICAgIGNhY2hlW2NvdW50XSA9IGJ1aWxkQihjb3VudCk7CiAgICB9CiAgICByZXR1cm4gY2FjaGVbY291bnRdOwogIH07Cn0oKTsKY2xhc3MgTWVzaFNoYWRpbmcgZXh0ZW5kcyBCYXNlU2hhZGluZyB7CiAgc3RhdGljIGdldCBNSU5fU1BMSVRfUEFUQ0hfQ0hVTktTX0FNT1VOVCgpIHsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiTUlOX1NQTElUX1BBVENIX0NIVU5LU19BTU9VTlQiLCAzKTsKICB9CiAgc3RhdGljIGdldCBNQVhfU1BMSVRfUEFUQ0hfQ0hVTktTX0FNT1VOVCgpIHsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiTUFYX1NQTElUX1BBVENIX0NIVU5LU19BTU9VTlQiLCAyMCk7CiAgfQogIHN0YXRpYyBnZXQgVFJJQU5HTEVfREVOU0lUWSgpIHsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiVFJJQU5HTEVfREVOU0lUWSIsIDIwKTsKICB9CiAgY29uc3RydWN0b3Ioc3RyZWFtLCB4cmVmLCByZXNvdXJjZXMsIHBkZkZ1bmN0aW9uRmFjdG9yeSwgbG9jYWxDb2xvclNwYWNlQ2FjaGUpIHsKICAgIHN1cGVyKCk7CiAgICBpZiAoIShzdHJlYW0gaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkpIHsKICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJNZXNoIGRhdGEgaXMgbm90IGEgc3RyZWFtIik7CiAgICB9CiAgICBjb25zdCBkaWN0ID0gc3RyZWFtLmRpY3Q7CiAgICB0aGlzLnNoYWRpbmdUeXBlID0gZGljdC5nZXQoIlNoYWRpbmdUeXBlIik7CiAgICBjb25zdCBiYm94ID0gZGljdC5nZXRBcnJheSgiQkJveCIpOwogICAgaWYgKEFycmF5LmlzQXJyYXkoYmJveCkgJiYgYmJveC5sZW5ndGggPT09IDQpIHsKICAgICAgdGhpcy5iYm94ID0gX3V0aWwuVXRpbC5ub3JtYWxpemVSZWN0KGJib3gpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5iYm94ID0gbnVsbDsKICAgIH0KICAgIGNvbnN0IGNzID0gX2NvbG9yc3BhY2UuQ29sb3JTcGFjZS5wYXJzZSh7CiAgICAgIGNzOiBkaWN0LmdldFJhdygiQ1MiKSB8fCBkaWN0LmdldFJhdygiQ29sb3JTcGFjZSIpLAogICAgICB4cmVmLAogICAgICByZXNvdXJjZXMsCiAgICAgIHBkZkZ1bmN0aW9uRmFjdG9yeSwKICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgIH0pOwogICAgdGhpcy5iYWNrZ3JvdW5kID0gZGljdC5oYXMoIkJhY2tncm91bmQiKSA/IGNzLmdldFJnYihkaWN0LmdldCgiQmFja2dyb3VuZCIpLCAwKSA6IG51bGw7CiAgICBjb25zdCBmbk9iaiA9IGRpY3QuZ2V0UmF3KCJGdW5jdGlvbiIpOwogICAgY29uc3QgZm4gPSBmbk9iaiA/IHBkZkZ1bmN0aW9uRmFjdG9yeS5jcmVhdGVGcm9tQXJyYXkoZm5PYmopIDogbnVsbDsKICAgIHRoaXMuY29vcmRzID0gW107CiAgICB0aGlzLmNvbG9ycyA9IFtdOwogICAgdGhpcy5maWd1cmVzID0gW107CiAgICBjb25zdCBkZWNvZGVDb250ZXh0ID0gewogICAgICBiaXRzUGVyQ29vcmRpbmF0ZTogZGljdC5nZXQoIkJpdHNQZXJDb29yZGluYXRlIiksCiAgICAgIGJpdHNQZXJDb21wb25lbnQ6IGRpY3QuZ2V0KCJCaXRzUGVyQ29tcG9uZW50IiksCiAgICAgIGJpdHNQZXJGbGFnOiBkaWN0LmdldCgiQml0c1BlckZsYWciKSwKICAgICAgZGVjb2RlOiBkaWN0LmdldEFycmF5KCJEZWNvZGUiKSwKICAgICAgY29sb3JGbjogZm4sCiAgICAgIGNvbG9yU3BhY2U6IGNzLAogICAgICBudW1Db21wczogZm4gPyAxIDogY3MubnVtQ29tcHMKICAgIH07CiAgICBjb25zdCByZWFkZXIgPSBuZXcgTWVzaFN0cmVhbVJlYWRlcihzdHJlYW0sIGRlY29kZUNvbnRleHQpOwogICAgbGV0IHBhdGNoTWVzaCA9IGZhbHNlOwogICAgc3dpdGNoICh0aGlzLnNoYWRpbmdUeXBlKSB7CiAgICAgIGNhc2UgU2hhZGluZ1R5cGUuRlJFRV9GT1JNX01FU0g6CiAgICAgICAgdGhpcy5fZGVjb2RlVHlwZTRTaGFkaW5nKHJlYWRlcik7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgU2hhZGluZ1R5cGUuTEFUVElDRV9GT1JNX01FU0g6CiAgICAgICAgY29uc3QgdmVydGljZXNQZXJSb3cgPSBkaWN0LmdldCgiVmVydGljZXNQZXJSb3ciKSB8IDA7CiAgICAgICAgaWYgKHZlcnRpY2VzUGVyUm93IDwgMikgewogICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJJbnZhbGlkIFZlcnRpY2VzUGVyUm93Iik7CiAgICAgICAgfQogICAgICAgIHRoaXMuX2RlY29kZVR5cGU1U2hhZGluZyhyZWFkZXIsIHZlcnRpY2VzUGVyUm93KTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBTaGFkaW5nVHlwZS5DT09OU19QQVRDSF9NRVNIOgogICAgICAgIHRoaXMuX2RlY29kZVR5cGU2U2hhZGluZyhyZWFkZXIpOwogICAgICAgIHBhdGNoTWVzaCA9IHRydWU7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgU2hhZGluZ1R5cGUuVEVOU09SX1BBVENIX01FU0g6CiAgICAgICAgdGhpcy5fZGVjb2RlVHlwZTdTaGFkaW5nKHJlYWRlcik7CiAgICAgICAgcGF0Y2hNZXNoID0gdHJ1ZTsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJVbnN1cHBvcnRlZCBtZXNoIHR5cGUuIik7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBpZiAocGF0Y2hNZXNoKSB7CiAgICAgIHRoaXMuX3VwZGF0ZUJvdW5kcygpOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB0aGlzLmZpZ3VyZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIHRoaXMuX2J1aWxkRmlndXJlRnJvbVBhdGNoKGkpOwogICAgICB9CiAgICB9CiAgICB0aGlzLl91cGRhdGVCb3VuZHMoKTsKICAgIHRoaXMuX3BhY2tEYXRhKCk7CiAgfQogIF9kZWNvZGVUeXBlNFNoYWRpbmcocmVhZGVyKSB7CiAgICBjb25zdCBjb29yZHMgPSB0aGlzLmNvb3JkczsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuY29sb3JzOwogICAgY29uc3Qgb3BlcmF0b3JzID0gW107CiAgICBjb25zdCBwcyA9IFtdOwogICAgbGV0IHZlcnRpY2VzTGVmdCA9IDA7CiAgICB3aGlsZSAocmVhZGVyLmhhc0RhdGEpIHsKICAgICAgY29uc3QgZiA9IHJlYWRlci5yZWFkRmxhZygpOwogICAgICBjb25zdCBjb29yZCA9IHJlYWRlci5yZWFkQ29vcmRpbmF0ZSgpOwogICAgICBjb25zdCBjb2xvciA9IHJlYWRlci5yZWFkQ29tcG9uZW50cygpOwogICAgICBpZiAodmVydGljZXNMZWZ0ID09PSAwKSB7CiAgICAgICAgaWYgKCEoMCA8PSBmICYmIGYgPD0gMikpIHsKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiVW5rbm93biB0eXBlNCBmbGFnIik7CiAgICAgICAgfQogICAgICAgIHN3aXRjaCAoZikgewogICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICB2ZXJ0aWNlc0xlZnQgPSAzOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgcHMucHVzaChwcy5hdCgtMiksIHBzLmF0KC0xKSk7CiAgICAgICAgICAgIHZlcnRpY2VzTGVmdCA9IDE7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICBwcy5wdXNoKHBzLmF0KC0zKSwgcHMuYXQoLTEpKTsKICAgICAgICAgICAgdmVydGljZXNMZWZ0ID0gMTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIG9wZXJhdG9ycy5wdXNoKGYpOwogICAgICB9CiAgICAgIHBzLnB1c2goY29vcmRzLmxlbmd0aCk7CiAgICAgIGNvb3Jkcy5wdXNoKGNvb3JkKTsKICAgICAgY29sb3JzLnB1c2goY29sb3IpOwogICAgICB2ZXJ0aWNlc0xlZnQtLTsKICAgICAgcmVhZGVyLmFsaWduKCk7CiAgICB9CiAgICB0aGlzLmZpZ3VyZXMucHVzaCh7CiAgICAgIHR5cGU6ICJ0cmlhbmdsZXMiLAogICAgICBjb29yZHM6IG5ldyBJbnQzMkFycmF5KHBzKSwKICAgICAgY29sb3JzOiBuZXcgSW50MzJBcnJheShwcykKICAgIH0pOwogIH0KICBfZGVjb2RlVHlwZTVTaGFkaW5nKHJlYWRlciwgdmVydGljZXNQZXJSb3cpIHsKICAgIGNvbnN0IGNvb3JkcyA9IHRoaXMuY29vcmRzOwogICAgY29uc3QgY29sb3JzID0gdGhpcy5jb2xvcnM7CiAgICBjb25zdCBwcyA9IFtdOwogICAgd2hpbGUgKHJlYWRlci5oYXNEYXRhKSB7CiAgICAgIGNvbnN0IGNvb3JkID0gcmVhZGVyLnJlYWRDb29yZGluYXRlKCk7CiAgICAgIGNvbnN0IGNvbG9yID0gcmVhZGVyLnJlYWRDb21wb25lbnRzKCk7CiAgICAgIHBzLnB1c2goY29vcmRzLmxlbmd0aCk7CiAgICAgIGNvb3Jkcy5wdXNoKGNvb3JkKTsKICAgICAgY29sb3JzLnB1c2goY29sb3IpOwogICAgfQogICAgdGhpcy5maWd1cmVzLnB1c2goewogICAgICB0eXBlOiAibGF0dGljZSIsCiAgICAgIGNvb3JkczogbmV3IEludDMyQXJyYXkocHMpLAogICAgICBjb2xvcnM6IG5ldyBJbnQzMkFycmF5KHBzKSwKICAgICAgdmVydGljZXNQZXJSb3cKICAgIH0pOwogIH0KICBfZGVjb2RlVHlwZTZTaGFkaW5nKHJlYWRlcikgewogICAgY29uc3QgY29vcmRzID0gdGhpcy5jb29yZHM7CiAgICBjb25zdCBjb2xvcnMgPSB0aGlzLmNvbG9yczsKICAgIGNvbnN0IHBzID0gbmV3IEludDMyQXJyYXkoMTYpOwogICAgY29uc3QgY3MgPSBuZXcgSW50MzJBcnJheSg0KTsKICAgIHdoaWxlIChyZWFkZXIuaGFzRGF0YSkgewogICAgICBjb25zdCBmID0gcmVhZGVyLnJlYWRGbGFnKCk7CiAgICAgIGlmICghKDAgPD0gZiAmJiBmIDw9IDMpKSB7CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJVbmtub3duIHR5cGU2IGZsYWciKTsKICAgICAgfQogICAgICBjb25zdCBwaSA9IGNvb3Jkcy5sZW5ndGg7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGYgIT09IDAgPyA4IDogMTI7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29vcmRzLnB1c2gocmVhZGVyLnJlYWRDb29yZGluYXRlKCkpOwogICAgICB9CiAgICAgIGNvbnN0IGNpID0gY29sb3JzLmxlbmd0aDsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZiAhPT0gMCA/IDIgOiA0OyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbG9ycy5wdXNoKHJlYWRlci5yZWFkQ29tcG9uZW50cygpKTsKICAgICAgfQogICAgICBsZXQgdG1wMSwgdG1wMiwgdG1wMywgdG1wNDsKICAgICAgc3dpdGNoIChmKSB7CiAgICAgICAgY2FzZSAwOgogICAgICAgICAgcHNbMTJdID0gcGkgKyAzOwogICAgICAgICAgcHNbMTNdID0gcGkgKyA0OwogICAgICAgICAgcHNbMTRdID0gcGkgKyA1OwogICAgICAgICAgcHNbMTVdID0gcGkgKyA2OwogICAgICAgICAgcHNbOF0gPSBwaSArIDI7CiAgICAgICAgICBwc1sxMV0gPSBwaSArIDc7CiAgICAgICAgICBwc1s0XSA9IHBpICsgMTsKICAgICAgICAgIHBzWzddID0gcGkgKyA4OwogICAgICAgICAgcHNbMF0gPSBwaTsKICAgICAgICAgIHBzWzFdID0gcGkgKyAxMTsKICAgICAgICAgIHBzWzJdID0gcGkgKyAxMDsKICAgICAgICAgIHBzWzNdID0gcGkgKyA5OwogICAgICAgICAgY3NbMl0gPSBjaSArIDE7CiAgICAgICAgICBjc1szXSA9IGNpICsgMjsKICAgICAgICAgIGNzWzBdID0gY2k7CiAgICAgICAgICBjc1sxXSA9IGNpICsgMzsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMToKICAgICAgICAgIHRtcDEgPSBwc1sxMl07CiAgICAgICAgICB0bXAyID0gcHNbMTNdOwogICAgICAgICAgdG1wMyA9IHBzWzE0XTsKICAgICAgICAgIHRtcDQgPSBwc1sxNV07CiAgICAgICAgICBwc1sxMl0gPSB0bXA0OwogICAgICAgICAgcHNbMTNdID0gcGkgKyAwOwogICAgICAgICAgcHNbMTRdID0gcGkgKyAxOwogICAgICAgICAgcHNbMTVdID0gcGkgKyAyOwogICAgICAgICAgcHNbOF0gPSB0bXAzOwogICAgICAgICAgcHNbMTFdID0gcGkgKyAzOwogICAgICAgICAgcHNbNF0gPSB0bXAyOwogICAgICAgICAgcHNbN10gPSBwaSArIDQ7CiAgICAgICAgICBwc1swXSA9IHRtcDE7CiAgICAgICAgICBwc1sxXSA9IHBpICsgNzsKICAgICAgICAgIHBzWzJdID0gcGkgKyA2OwogICAgICAgICAgcHNbM10gPSBwaSArIDU7CiAgICAgICAgICB0bXAxID0gY3NbMl07CiAgICAgICAgICB0bXAyID0gY3NbM107CiAgICAgICAgICBjc1syXSA9IHRtcDI7CiAgICAgICAgICBjc1szXSA9IGNpOwogICAgICAgICAgY3NbMF0gPSB0bXAxOwogICAgICAgICAgY3NbMV0gPSBjaSArIDE7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI6CiAgICAgICAgICB0bXAxID0gcHNbMTVdOwogICAgICAgICAgdG1wMiA9IHBzWzExXTsKICAgICAgICAgIHBzWzEyXSA9IHBzWzNdOwogICAgICAgICAgcHNbMTNdID0gcGkgKyAwOwogICAgICAgICAgcHNbMTRdID0gcGkgKyAxOwogICAgICAgICAgcHNbMTVdID0gcGkgKyAyOwogICAgICAgICAgcHNbOF0gPSBwc1s3XTsKICAgICAgICAgIHBzWzExXSA9IHBpICsgMzsKICAgICAgICAgIHBzWzRdID0gdG1wMjsKICAgICAgICAgIHBzWzddID0gcGkgKyA0OwogICAgICAgICAgcHNbMF0gPSB0bXAxOwogICAgICAgICAgcHNbMV0gPSBwaSArIDc7CiAgICAgICAgICBwc1syXSA9IHBpICsgNjsKICAgICAgICAgIHBzWzNdID0gcGkgKyA1OwogICAgICAgICAgdG1wMSA9IGNzWzNdOwogICAgICAgICAgY3NbMl0gPSBjc1sxXTsKICAgICAgICAgIGNzWzNdID0gY2k7CiAgICAgICAgICBjc1swXSA9IHRtcDE7CiAgICAgICAgICBjc1sxXSA9IGNpICsgMTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzoKICAgICAgICAgIHBzWzEyXSA9IHBzWzBdOwogICAgICAgICAgcHNbMTNdID0gcGkgKyAwOwogICAgICAgICAgcHNbMTRdID0gcGkgKyAxOwogICAgICAgICAgcHNbMTVdID0gcGkgKyAyOwogICAgICAgICAgcHNbOF0gPSBwc1sxXTsKICAgICAgICAgIHBzWzExXSA9IHBpICsgMzsKICAgICAgICAgIHBzWzRdID0gcHNbMl07CiAgICAgICAgICBwc1s3XSA9IHBpICsgNDsKICAgICAgICAgIHBzWzBdID0gcHNbM107CiAgICAgICAgICBwc1sxXSA9IHBpICsgNzsKICAgICAgICAgIHBzWzJdID0gcGkgKyA2OwogICAgICAgICAgcHNbM10gPSBwaSArIDU7CiAgICAgICAgICBjc1syXSA9IGNzWzBdOwogICAgICAgICAgY3NbM10gPSBjaTsKICAgICAgICAgIGNzWzBdID0gY3NbMV07CiAgICAgICAgICBjc1sxXSA9IGNpICsgMTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHBzWzVdID0gY29vcmRzLmxlbmd0aDsKICAgICAgY29vcmRzLnB1c2goWygtNCAqIGNvb3Jkc1twc1swXV1bMF0gLSBjb29yZHNbcHNbMTVdXVswXSArIDYgKiAoY29vcmRzW3BzWzRdXVswXSArIGNvb3Jkc1twc1sxXV1bMF0pIC0gMiAqIChjb29yZHNbcHNbMTJdXVswXSArIGNvb3Jkc1twc1szXV1bMF0pICsgMyAqIChjb29yZHNbcHNbMTNdXVswXSArIGNvb3Jkc1twc1s3XV1bMF0pKSAvIDksICgtNCAqIGNvb3Jkc1twc1swXV1bMV0gLSBjb29yZHNbcHNbMTVdXVsxXSArIDYgKiAoY29vcmRzW3BzWzRdXVsxXSArIGNvb3Jkc1twc1sxXV1bMV0pIC0gMiAqIChjb29yZHNbcHNbMTJdXVsxXSArIGNvb3Jkc1twc1szXV1bMV0pICsgMyAqIChjb29yZHNbcHNbMTNdXVsxXSArIGNvb3Jkc1twc1s3XV1bMV0pKSAvIDldKTsKICAgICAgcHNbNl0gPSBjb29yZHMubGVuZ3RoOwogICAgICBjb29yZHMucHVzaChbKC00ICogY29vcmRzW3BzWzNdXVswXSAtIGNvb3Jkc1twc1sxMl1dWzBdICsgNiAqIChjb29yZHNbcHNbMl1dWzBdICsgY29vcmRzW3BzWzddXVswXSkgLSAyICogKGNvb3Jkc1twc1swXV1bMF0gKyBjb29yZHNbcHNbMTVdXVswXSkgKyAzICogKGNvb3Jkc1twc1s0XV1bMF0gKyBjb29yZHNbcHNbMTRdXVswXSkpIC8gOSwgKC00ICogY29vcmRzW3BzWzNdXVsxXSAtIGNvb3Jkc1twc1sxMl1dWzFdICsgNiAqIChjb29yZHNbcHNbMl1dWzFdICsgY29vcmRzW3BzWzddXVsxXSkgLSAyICogKGNvb3Jkc1twc1swXV1bMV0gKyBjb29yZHNbcHNbMTVdXVsxXSkgKyAzICogKGNvb3Jkc1twc1s0XV1bMV0gKyBjb29yZHNbcHNbMTRdXVsxXSkpIC8gOV0pOwogICAgICBwc1s5XSA9IGNvb3Jkcy5sZW5ndGg7CiAgICAgIGNvb3Jkcy5wdXNoKFsoLTQgKiBjb29yZHNbcHNbMTJdXVswXSAtIGNvb3Jkc1twc1szXV1bMF0gKyA2ICogKGNvb3Jkc1twc1s4XV1bMF0gKyBjb29yZHNbcHNbMTNdXVswXSkgLSAyICogKGNvb3Jkc1twc1swXV1bMF0gKyBjb29yZHNbcHNbMTVdXVswXSkgKyAzICogKGNvb3Jkc1twc1sxMV1dWzBdICsgY29vcmRzW3BzWzFdXVswXSkpIC8gOSwgKC00ICogY29vcmRzW3BzWzEyXV1bMV0gLSBjb29yZHNbcHNbM11dWzFdICsgNiAqIChjb29yZHNbcHNbOF1dWzFdICsgY29vcmRzW3BzWzEzXV1bMV0pIC0gMiAqIChjb29yZHNbcHNbMF1dWzFdICsgY29vcmRzW3BzWzE1XV1bMV0pICsgMyAqIChjb29yZHNbcHNbMTFdXVsxXSArIGNvb3Jkc1twc1sxXV1bMV0pKSAvIDldKTsKICAgICAgcHNbMTBdID0gY29vcmRzLmxlbmd0aDsKICAgICAgY29vcmRzLnB1c2goWygtNCAqIGNvb3Jkc1twc1sxNV1dWzBdIC0gY29vcmRzW3BzWzBdXVswXSArIDYgKiAoY29vcmRzW3BzWzExXV1bMF0gKyBjb29yZHNbcHNbMTRdXVswXSkgLSAyICogKGNvb3Jkc1twc1sxMl1dWzBdICsgY29vcmRzW3BzWzNdXVswXSkgKyAzICogKGNvb3Jkc1twc1syXV1bMF0gKyBjb29yZHNbcHNbOF1dWzBdKSkgLyA5LCAoLTQgKiBjb29yZHNbcHNbMTVdXVsxXSAtIGNvb3Jkc1twc1swXV1bMV0gKyA2ICogKGNvb3Jkc1twc1sxMV1dWzFdICsgY29vcmRzW3BzWzE0XV1bMV0pIC0gMiAqIChjb29yZHNbcHNbMTJdXVsxXSArIGNvb3Jkc1twc1szXV1bMV0pICsgMyAqIChjb29yZHNbcHNbMl1dWzFdICsgY29vcmRzW3BzWzhdXVsxXSkpIC8gOV0pOwogICAgICB0aGlzLmZpZ3VyZXMucHVzaCh7CiAgICAgICAgdHlwZTogInBhdGNoIiwKICAgICAgICBjb29yZHM6IG5ldyBJbnQzMkFycmF5KHBzKSwKICAgICAgICBjb2xvcnM6IG5ldyBJbnQzMkFycmF5KGNzKQogICAgICB9KTsKICAgIH0KICB9CiAgX2RlY29kZVR5cGU3U2hhZGluZyhyZWFkZXIpIHsKICAgIGNvbnN0IGNvb3JkcyA9IHRoaXMuY29vcmRzOwogICAgY29uc3QgY29sb3JzID0gdGhpcy5jb2xvcnM7CiAgICBjb25zdCBwcyA9IG5ldyBJbnQzMkFycmF5KDE2KTsKICAgIGNvbnN0IGNzID0gbmV3IEludDMyQXJyYXkoNCk7CiAgICB3aGlsZSAocmVhZGVyLmhhc0RhdGEpIHsKICAgICAgY29uc3QgZiA9IHJlYWRlci5yZWFkRmxhZygpOwogICAgICBpZiAoISgwIDw9IGYgJiYgZiA8PSAzKSkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiVW5rbm93biB0eXBlNyBmbGFnIik7CiAgICAgIH0KICAgICAgY29uc3QgcGkgPSBjb29yZHMubGVuZ3RoOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBmICE9PSAwID8gMTIgOiAxNjsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb29yZHMucHVzaChyZWFkZXIucmVhZENvb3JkaW5hdGUoKSk7CiAgICAgIH0KICAgICAgY29uc3QgY2kgPSBjb2xvcnMubGVuZ3RoOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBmICE9PSAwID8gMiA6IDQ7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29sb3JzLnB1c2gocmVhZGVyLnJlYWRDb21wb25lbnRzKCkpOwogICAgICB9CiAgICAgIGxldCB0bXAxLCB0bXAyLCB0bXAzLCB0bXA0OwogICAgICBzd2l0Y2ggKGYpIHsKICAgICAgICBjYXNlIDA6CiAgICAgICAgICBwc1sxMl0gPSBwaSArIDM7CiAgICAgICAgICBwc1sxM10gPSBwaSArIDQ7CiAgICAgICAgICBwc1sxNF0gPSBwaSArIDU7CiAgICAgICAgICBwc1sxNV0gPSBwaSArIDY7CiAgICAgICAgICBwc1s4XSA9IHBpICsgMjsKICAgICAgICAgIHBzWzldID0gcGkgKyAxMzsKICAgICAgICAgIHBzWzEwXSA9IHBpICsgMTQ7CiAgICAgICAgICBwc1sxMV0gPSBwaSArIDc7CiAgICAgICAgICBwc1s0XSA9IHBpICsgMTsKICAgICAgICAgIHBzWzVdID0gcGkgKyAxMjsKICAgICAgICAgIHBzWzZdID0gcGkgKyAxNTsKICAgICAgICAgIHBzWzddID0gcGkgKyA4OwogICAgICAgICAgcHNbMF0gPSBwaTsKICAgICAgICAgIHBzWzFdID0gcGkgKyAxMTsKICAgICAgICAgIHBzWzJdID0gcGkgKyAxMDsKICAgICAgICAgIHBzWzNdID0gcGkgKyA5OwogICAgICAgICAgY3NbMl0gPSBjaSArIDE7CiAgICAgICAgICBjc1szXSA9IGNpICsgMjsKICAgICAgICAgIGNzWzBdID0gY2k7CiAgICAgICAgICBjc1sxXSA9IGNpICsgMzsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMToKICAgICAgICAgIHRtcDEgPSBwc1sxMl07CiAgICAgICAgICB0bXAyID0gcHNbMTNdOwogICAgICAgICAgdG1wMyA9IHBzWzE0XTsKICAgICAgICAgIHRtcDQgPSBwc1sxNV07CiAgICAgICAgICBwc1sxMl0gPSB0bXA0OwogICAgICAgICAgcHNbMTNdID0gcGkgKyAwOwogICAgICAgICAgcHNbMTRdID0gcGkgKyAxOwogICAgICAgICAgcHNbMTVdID0gcGkgKyAyOwogICAgICAgICAgcHNbOF0gPSB0bXAzOwogICAgICAgICAgcHNbOV0gPSBwaSArIDk7CiAgICAgICAgICBwc1sxMF0gPSBwaSArIDEwOwogICAgICAgICAgcHNbMTFdID0gcGkgKyAzOwogICAgICAgICAgcHNbNF0gPSB0bXAyOwogICAgICAgICAgcHNbNV0gPSBwaSArIDg7CiAgICAgICAgICBwc1s2XSA9IHBpICsgMTE7CiAgICAgICAgICBwc1s3XSA9IHBpICsgNDsKICAgICAgICAgIHBzWzBdID0gdG1wMTsKICAgICAgICAgIHBzWzFdID0gcGkgKyA3OwogICAgICAgICAgcHNbMl0gPSBwaSArIDY7CiAgICAgICAgICBwc1szXSA9IHBpICsgNTsKICAgICAgICAgIHRtcDEgPSBjc1syXTsKICAgICAgICAgIHRtcDIgPSBjc1szXTsKICAgICAgICAgIGNzWzJdID0gdG1wMjsKICAgICAgICAgIGNzWzNdID0gY2k7CiAgICAgICAgICBjc1swXSA9IHRtcDE7CiAgICAgICAgICBjc1sxXSA9IGNpICsgMTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjoKICAgICAgICAgIHRtcDEgPSBwc1sxNV07CiAgICAgICAgICB0bXAyID0gcHNbMTFdOwogICAgICAgICAgcHNbMTJdID0gcHNbM107CiAgICAgICAgICBwc1sxM10gPSBwaSArIDA7CiAgICAgICAgICBwc1sxNF0gPSBwaSArIDE7CiAgICAgICAgICBwc1sxNV0gPSBwaSArIDI7CiAgICAgICAgICBwc1s4XSA9IHBzWzddOwogICAgICAgICAgcHNbOV0gPSBwaSArIDk7CiAgICAgICAgICBwc1sxMF0gPSBwaSArIDEwOwogICAgICAgICAgcHNbMTFdID0gcGkgKyAzOwogICAgICAgICAgcHNbNF0gPSB0bXAyOwogICAgICAgICAgcHNbNV0gPSBwaSArIDg7CiAgICAgICAgICBwc1s2XSA9IHBpICsgMTE7CiAgICAgICAgICBwc1s3XSA9IHBpICsgNDsKICAgICAgICAgIHBzWzBdID0gdG1wMTsKICAgICAgICAgIHBzWzFdID0gcGkgKyA3OwogICAgICAgICAgcHNbMl0gPSBwaSArIDY7CiAgICAgICAgICBwc1szXSA9IHBpICsgNTsKICAgICAgICAgIHRtcDEgPSBjc1szXTsKICAgICAgICAgIGNzWzJdID0gY3NbMV07CiAgICAgICAgICBjc1szXSA9IGNpOwogICAgICAgICAgY3NbMF0gPSB0bXAxOwogICAgICAgICAgY3NbMV0gPSBjaSArIDE7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDM6CiAgICAgICAgICBwc1sxMl0gPSBwc1swXTsKICAgICAgICAgIHBzWzEzXSA9IHBpICsgMDsKICAgICAgICAgIHBzWzE0XSA9IHBpICsgMTsKICAgICAgICAgIHBzWzE1XSA9IHBpICsgMjsKICAgICAgICAgIHBzWzhdID0gcHNbMV07CiAgICAgICAgICBwc1s5XSA9IHBpICsgOTsKICAgICAgICAgIHBzWzEwXSA9IHBpICsgMTA7CiAgICAgICAgICBwc1sxMV0gPSBwaSArIDM7CiAgICAgICAgICBwc1s0XSA9IHBzWzJdOwogICAgICAgICAgcHNbNV0gPSBwaSArIDg7CiAgICAgICAgICBwc1s2XSA9IHBpICsgMTE7CiAgICAgICAgICBwc1s3XSA9IHBpICsgNDsKICAgICAgICAgIHBzWzBdID0gcHNbM107CiAgICAgICAgICBwc1sxXSA9IHBpICsgNzsKICAgICAgICAgIHBzWzJdID0gcGkgKyA2OwogICAgICAgICAgcHNbM10gPSBwaSArIDU7CiAgICAgICAgICBjc1syXSA9IGNzWzBdOwogICAgICAgICAgY3NbM10gPSBjaTsKICAgICAgICAgIGNzWzBdID0gY3NbMV07CiAgICAgICAgICBjc1sxXSA9IGNpICsgMTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHRoaXMuZmlndXJlcy5wdXNoKHsKICAgICAgICB0eXBlOiAicGF0Y2giLAogICAgICAgIGNvb3JkczogbmV3IEludDMyQXJyYXkocHMpLAogICAgICAgIGNvbG9yczogbmV3IEludDMyQXJyYXkoY3MpCiAgICAgIH0pOwogICAgfQogIH0KICBfYnVpbGRGaWd1cmVGcm9tUGF0Y2goaW5kZXgpIHsKICAgIGNvbnN0IGZpZ3VyZSA9IHRoaXMuZmlndXJlc1tpbmRleF07CiAgICAoMCwgX3V0aWwuYXNzZXJ0KShmaWd1cmUudHlwZSA9PT0gInBhdGNoIiwgIlVuZXhwZWN0ZWQgcGF0Y2ggbWVzaCBmaWd1cmUiKTsKICAgIGNvbnN0IGNvb3JkcyA9IHRoaXMuY29vcmRzLAogICAgICBjb2xvcnMgPSB0aGlzLmNvbG9yczsKICAgIGNvbnN0IHBpID0gZmlndXJlLmNvb3JkczsKICAgIGNvbnN0IGNpID0gZmlndXJlLmNvbG9yczsKICAgIGNvbnN0IGZpZ3VyZU1pblggPSBNYXRoLm1pbihjb29yZHNbcGlbMF1dWzBdLCBjb29yZHNbcGlbM11dWzBdLCBjb29yZHNbcGlbMTJdXVswXSwgY29vcmRzW3BpWzE1XV1bMF0pOwogICAgY29uc3QgZmlndXJlTWluWSA9IE1hdGgubWluKGNvb3Jkc1twaVswXV1bMV0sIGNvb3Jkc1twaVszXV1bMV0sIGNvb3Jkc1twaVsxMl1dWzFdLCBjb29yZHNbcGlbMTVdXVsxXSk7CiAgICBjb25zdCBmaWd1cmVNYXhYID0gTWF0aC5tYXgoY29vcmRzW3BpWzBdXVswXSwgY29vcmRzW3BpWzNdXVswXSwgY29vcmRzW3BpWzEyXV1bMF0sIGNvb3Jkc1twaVsxNV1dWzBdKTsKICAgIGNvbnN0IGZpZ3VyZU1heFkgPSBNYXRoLm1heChjb29yZHNbcGlbMF1dWzFdLCBjb29yZHNbcGlbM11dWzFdLCBjb29yZHNbcGlbMTJdXVsxXSwgY29vcmRzW3BpWzE1XV1bMV0pOwogICAgbGV0IHNwbGl0WEJ5ID0gTWF0aC5jZWlsKChmaWd1cmVNYXhYIC0gZmlndXJlTWluWCkgKiBNZXNoU2hhZGluZy5UUklBTkdMRV9ERU5TSVRZIC8gKHRoaXMuYm91bmRzWzJdIC0gdGhpcy5ib3VuZHNbMF0pKTsKICAgIHNwbGl0WEJ5ID0gTWF0aC5tYXgoTWVzaFNoYWRpbmcuTUlOX1NQTElUX1BBVENIX0NIVU5LU19BTU9VTlQsIE1hdGgubWluKE1lc2hTaGFkaW5nLk1BWF9TUExJVF9QQVRDSF9DSFVOS1NfQU1PVU5ULCBzcGxpdFhCeSkpOwogICAgbGV0IHNwbGl0WUJ5ID0gTWF0aC5jZWlsKChmaWd1cmVNYXhZIC0gZmlndXJlTWluWSkgKiBNZXNoU2hhZGluZy5UUklBTkdMRV9ERU5TSVRZIC8gKHRoaXMuYm91bmRzWzNdIC0gdGhpcy5ib3VuZHNbMV0pKTsKICAgIHNwbGl0WUJ5ID0gTWF0aC5tYXgoTWVzaFNoYWRpbmcuTUlOX1NQTElUX1BBVENIX0NIVU5LU19BTU9VTlQsIE1hdGgubWluKE1lc2hTaGFkaW5nLk1BWF9TUExJVF9QQVRDSF9DSFVOS1NfQU1PVU5ULCBzcGxpdFlCeSkpOwogICAgY29uc3QgdmVydGljZXNQZXJSb3cgPSBzcGxpdFhCeSArIDE7CiAgICBjb25zdCBmaWd1cmVDb29yZHMgPSBuZXcgSW50MzJBcnJheSgoc3BsaXRZQnkgKyAxKSAqIHZlcnRpY2VzUGVyUm93KTsKICAgIGNvbnN0IGZpZ3VyZUNvbG9ycyA9IG5ldyBJbnQzMkFycmF5KChzcGxpdFlCeSArIDEpICogdmVydGljZXNQZXJSb3cpOwogICAgbGV0IGsgPSAwOwogICAgY29uc3QgY2wgPSBuZXcgVWludDhBcnJheSgzKSwKICAgICAgY3IgPSBuZXcgVWludDhBcnJheSgzKTsKICAgIGNvbnN0IGMwID0gY29sb3JzW2NpWzBdXSwKICAgICAgYzEgPSBjb2xvcnNbY2lbMV1dLAogICAgICBjMiA9IGNvbG9yc1tjaVsyXV0sCiAgICAgIGMzID0gY29sb3JzW2NpWzNdXTsKICAgIGNvbnN0IGJSb3cgPSBnZXRCKHNwbGl0WUJ5KSwKICAgICAgYkNvbCA9IGdldEIoc3BsaXRYQnkpOwogICAgZm9yIChsZXQgcm93ID0gMDsgcm93IDw9IHNwbGl0WUJ5OyByb3crKykgewogICAgICBjbFswXSA9IChjMFswXSAqIChzcGxpdFlCeSAtIHJvdykgKyBjMlswXSAqIHJvdykgLyBzcGxpdFlCeSB8IDA7CiAgICAgIGNsWzFdID0gKGMwWzFdICogKHNwbGl0WUJ5IC0gcm93KSArIGMyWzFdICogcm93KSAvIHNwbGl0WUJ5IHwgMDsKICAgICAgY2xbMl0gPSAoYzBbMl0gKiAoc3BsaXRZQnkgLSByb3cpICsgYzJbMl0gKiByb3cpIC8gc3BsaXRZQnkgfCAwOwogICAgICBjclswXSA9IChjMVswXSAqIChzcGxpdFlCeSAtIHJvdykgKyBjM1swXSAqIHJvdykgLyBzcGxpdFlCeSB8IDA7CiAgICAgIGNyWzFdID0gKGMxWzFdICogKHNwbGl0WUJ5IC0gcm93KSArIGMzWzFdICogcm93KSAvIHNwbGl0WUJ5IHwgMDsKICAgICAgY3JbMl0gPSAoYzFbMl0gKiAoc3BsaXRZQnkgLSByb3cpICsgYzNbMl0gKiByb3cpIC8gc3BsaXRZQnkgfCAwOwogICAgICBmb3IgKGxldCBjb2wgPSAwOyBjb2wgPD0gc3BsaXRYQnk7IGNvbCsrLCBrKyspIHsKICAgICAgICBpZiAoKHJvdyA9PT0gMCB8fCByb3cgPT09IHNwbGl0WUJ5KSAmJiAoY29sID09PSAwIHx8IGNvbCA9PT0gc3BsaXRYQnkpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgbGV0IHggPSAwLAogICAgICAgICAgeSA9IDA7CiAgICAgICAgbGV0IHEgPSAwOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IDM7IGkrKykgewogICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPD0gMzsgaisrLCBxKyspIHsKICAgICAgICAgICAgY29uc3QgbSA9IGJSb3dbcm93XVtpXSAqIGJDb2xbY29sXVtqXTsKICAgICAgICAgICAgeCArPSBjb29yZHNbcGlbcV1dWzBdICogbTsKICAgICAgICAgICAgeSArPSBjb29yZHNbcGlbcV1dWzFdICogbTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZmlndXJlQ29vcmRzW2tdID0gY29vcmRzLmxlbmd0aDsKICAgICAgICBjb29yZHMucHVzaChbeCwgeV0pOwogICAgICAgIGZpZ3VyZUNvbG9yc1trXSA9IGNvbG9ycy5sZW5ndGg7CiAgICAgICAgY29uc3QgbmV3Q29sb3IgPSBuZXcgVWludDhBcnJheSgzKTsKICAgICAgICBuZXdDb2xvclswXSA9IChjbFswXSAqIChzcGxpdFhCeSAtIGNvbCkgKyBjclswXSAqIGNvbCkgLyBzcGxpdFhCeSB8IDA7CiAgICAgICAgbmV3Q29sb3JbMV0gPSAoY2xbMV0gKiAoc3BsaXRYQnkgLSBjb2wpICsgY3JbMV0gKiBjb2wpIC8gc3BsaXRYQnkgfCAwOwogICAgICAgIG5ld0NvbG9yWzJdID0gKGNsWzJdICogKHNwbGl0WEJ5IC0gY29sKSArIGNyWzJdICogY29sKSAvIHNwbGl0WEJ5IHwgMDsKICAgICAgICBjb2xvcnMucHVzaChuZXdDb2xvcik7CiAgICAgIH0KICAgIH0KICAgIGZpZ3VyZUNvb3Jkc1swXSA9IHBpWzBdOwogICAgZmlndXJlQ29sb3JzWzBdID0gY2lbMF07CiAgICBmaWd1cmVDb29yZHNbc3BsaXRYQnldID0gcGlbM107CiAgICBmaWd1cmVDb2xvcnNbc3BsaXRYQnldID0gY2lbMV07CiAgICBmaWd1cmVDb29yZHNbdmVydGljZXNQZXJSb3cgKiBzcGxpdFlCeV0gPSBwaVsxMl07CiAgICBmaWd1cmVDb2xvcnNbdmVydGljZXNQZXJSb3cgKiBzcGxpdFlCeV0gPSBjaVsyXTsKICAgIGZpZ3VyZUNvb3Jkc1t2ZXJ0aWNlc1BlclJvdyAqIHNwbGl0WUJ5ICsgc3BsaXRYQnldID0gcGlbMTVdOwogICAgZmlndXJlQ29sb3JzW3ZlcnRpY2VzUGVyUm93ICogc3BsaXRZQnkgKyBzcGxpdFhCeV0gPSBjaVszXTsKICAgIHRoaXMuZmlndXJlc1tpbmRleF0gPSB7CiAgICAgIHR5cGU6ICJsYXR0aWNlIiwKICAgICAgY29vcmRzOiBmaWd1cmVDb29yZHMsCiAgICAgIGNvbG9yczogZmlndXJlQ29sb3JzLAogICAgICB2ZXJ0aWNlc1BlclJvdwogICAgfTsKICB9CiAgX3VwZGF0ZUJvdW5kcygpIHsKICAgIGxldCBtaW5YID0gdGhpcy5jb29yZHNbMF1bMF0sCiAgICAgIG1pblkgPSB0aGlzLmNvb3Jkc1swXVsxXSwKICAgICAgbWF4WCA9IG1pblgsCiAgICAgIG1heFkgPSBtaW5ZOwogICAgZm9yIChsZXQgaSA9IDEsIGlpID0gdGhpcy5jb29yZHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCB4ID0gdGhpcy5jb29yZHNbaV1bMF0sCiAgICAgICAgeSA9IHRoaXMuY29vcmRzW2ldWzFdOwogICAgICBtaW5YID0gbWluWCA+IHggPyB4IDogbWluWDsKICAgICAgbWluWSA9IG1pblkgPiB5ID8geSA6IG1pblk7CiAgICAgIG1heFggPSBtYXhYIDwgeCA/IHggOiBtYXhYOwogICAgICBtYXhZID0gbWF4WSA8IHkgPyB5IDogbWF4WTsKICAgIH0KICAgIHRoaXMuYm91bmRzID0gW21pblgsIG1pblksIG1heFgsIG1heFldOwogIH0KICBfcGFja0RhdGEoKSB7CiAgICBsZXQgaSwgaWksIGosIGpqOwogICAgY29uc3QgY29vcmRzID0gdGhpcy5jb29yZHM7CiAgICBjb25zdCBjb29yZHNQYWNrZWQgPSBuZXcgRmxvYXQzMkFycmF5KGNvb3Jkcy5sZW5ndGggKiAyKTsKICAgIGZvciAoaSA9IDAsIGogPSAwLCBpaSA9IGNvb3Jkcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IHh5ID0gY29vcmRzW2ldOwogICAgICBjb29yZHNQYWNrZWRbaisrXSA9IHh5WzBdOwogICAgICBjb29yZHNQYWNrZWRbaisrXSA9IHh5WzFdOwogICAgfQogICAgdGhpcy5jb29yZHMgPSBjb29yZHNQYWNrZWQ7CiAgICBjb25zdCBjb2xvcnMgPSB0aGlzLmNvbG9yczsKICAgIGNvbnN0IGNvbG9yc1BhY2tlZCA9IG5ldyBVaW50OEFycmF5KGNvbG9ycy5sZW5ndGggKiAzKTsKICAgIGZvciAoaSA9IDAsIGogPSAwLCBpaSA9IGNvbG9ycy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IGMgPSBjb2xvcnNbaV07CiAgICAgIGNvbG9yc1BhY2tlZFtqKytdID0gY1swXTsKICAgICAgY29sb3JzUGFja2VkW2orK10gPSBjWzFdOwogICAgICBjb2xvcnNQYWNrZWRbaisrXSA9IGNbMl07CiAgICB9CiAgICB0aGlzLmNvbG9ycyA9IGNvbG9yc1BhY2tlZDsKICAgIGNvbnN0IGZpZ3VyZXMgPSB0aGlzLmZpZ3VyZXM7CiAgICBmb3IgKGkgPSAwLCBpaSA9IGZpZ3VyZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBmaWd1cmUgPSBmaWd1cmVzW2ldLAogICAgICAgIHBzID0gZmlndXJlLmNvb3JkcywKICAgICAgICBjcyA9IGZpZ3VyZS5jb2xvcnM7CiAgICAgIGZvciAoaiA9IDAsIGpqID0gcHMubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICAgIHBzW2pdICo9IDI7CiAgICAgICAgY3Nbal0gKj0gMzsKICAgICAgfQogICAgfQogIH0KICBnZXRJUigpIHsKICAgIHJldHVybiBbIk1lc2giLCB0aGlzLnNoYWRpbmdUeXBlLCB0aGlzLmNvb3JkcywgdGhpcy5jb2xvcnMsIHRoaXMuZmlndXJlcywgdGhpcy5ib3VuZHMsIHRoaXMuYmJveCwgdGhpcy5iYWNrZ3JvdW5kXTsKICB9Cn0KY2xhc3MgRHVtbXlTaGFkaW5nIGV4dGVuZHMgQmFzZVNoYWRpbmcgewogIGdldElSKCkgewogICAgcmV0dXJuIFsiRHVtbXkiXTsKICB9Cn0KZnVuY3Rpb24gZ2V0VGlsaW5nUGF0dGVybklSKG9wZXJhdG9yTGlzdCwgZGljdCwgY29sb3IpIHsKICBjb25zdCBtYXRyaXggPSBkaWN0LmdldEFycmF5KCJNYXRyaXgiKTsKICBjb25zdCBiYm94ID0gX3V0aWwuVXRpbC5ub3JtYWxpemVSZWN0KGRpY3QuZ2V0QXJyYXkoIkJCb3giKSk7CiAgY29uc3QgeHN0ZXAgPSBkaWN0LmdldCgiWFN0ZXAiKTsKICBjb25zdCB5c3RlcCA9IGRpY3QuZ2V0KCJZU3RlcCIpOwogIGNvbnN0IHBhaW50VHlwZSA9IGRpY3QuZ2V0KCJQYWludFR5cGUiKTsKICBjb25zdCB0aWxpbmdUeXBlID0gZGljdC5nZXQoIlRpbGluZ1R5cGUiKTsKICBpZiAoYmJveFsyXSAtIGJib3hbMF0gPT09IDAgfHwgYmJveFszXSAtIGJib3hbMV0gPT09IDApIHsKICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgSW52YWxpZCBnZXRUaWxpbmdQYXR0ZXJuSVIgL0JCb3ggYXJyYXk6IFske2Jib3h9XS5gKTsKICB9CiAgcmV0dXJuIFsiVGlsaW5nUGF0dGVybiIsIGNvbG9yLCBvcGVyYXRvckxpc3QsIG1hdHJpeCwgYmJveCwgeHN0ZXAsIHlzdGVwLCBwYWludFR5cGUsIHRpbGluZ1R5cGVdOwp9CgovKioqLyB9KSwKLyogMTg2ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5nZXRYZmFGb250RGljdCA9IGdldFhmYUZvbnREaWN0OwpleHBvcnRzLmdldFhmYUZvbnROYW1lID0gZ2V0WGZhRm9udE5hbWU7CnZhciBfY2FsaWJyaV9mYWN0b3JzID0gX193X3BkZmpzX3JlcXVpcmVfXygxODcpOwp2YXIgX3ByaW1pdGl2ZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MCk7CnZhciBfaGVsdmV0aWNhX2ZhY3RvcnMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE4OCk7CnZhciBfbGliZXJhdGlvbnNhbnNfd2lkdGhzID0gX193X3BkZmpzX3JlcXVpcmVfXygxODkpOwp2YXIgX215cmlhZHByb19mYWN0b3JzID0gX193X3BkZmpzX3JlcXVpcmVfXygxOTApOwp2YXIgX3NlZ29ldWlfZmFjdG9ycyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTkxKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX2ZvbnRzX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNzMpOwpjb25zdCBnZXRYRkFGb250TWFwID0gKDAsIF9jb3JlX3V0aWxzLmdldExvb2t1cFRhYmxlRmFjdG9yeSkoZnVuY3Rpb24gKHQpIHsKICB0WyJNeXJpYWRQcm8tUmVndWxhciJdID0gdFsiUGRmSlMtRmFsbGJhY2stUmVndWxhciJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIiLAogICAgZmFjdG9yczogX215cmlhZHByb19mYWN0b3JzLk15cmlhZFByb1JlZ3VsYXJGYWN0b3JzLAogICAgYmFzZVdpZHRoczogX2xpYmVyYXRpb25zYW5zX3dpZHRocy5MaWJlcmF0aW9uU2Fuc1JlZ3VsYXJXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogX2xpYmVyYXRpb25zYW5zX3dpZHRocy5MaWJlcmF0aW9uU2Fuc1JlZ3VsYXJNYXBwaW5nLAogICAgbWV0cmljczogX215cmlhZHByb19mYWN0b3JzLk15cmlhZFByb1JlZ3VsYXJNZXRyaWNzCiAgfTsKICB0WyJNeXJpYWRQcm8tQm9sZCJdID0gdFsiUGRmSlMtRmFsbGJhY2stQm9sZCJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUJvbGQiLAogICAgZmFjdG9yczogX215cmlhZHByb19mYWN0b3JzLk15cmlhZFByb0JvbGRGYWN0b3JzLAogICAgYmFzZVdpZHRoczogX2xpYmVyYXRpb25zYW5zX3dpZHRocy5MaWJlcmF0aW9uU2Fuc0JvbGRXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogX2xpYmVyYXRpb25zYW5zX3dpZHRocy5MaWJlcmF0aW9uU2Fuc0JvbGRNYXBwaW5nLAogICAgbWV0cmljczogX215cmlhZHByb19mYWN0b3JzLk15cmlhZFByb0JvbGRNZXRyaWNzCiAgfTsKICB0WyJNeXJpYWRQcm8tSXQiXSA9IHRbIk15cmlhZFByby1JdGFsaWMiXSA9IHRbIlBkZkpTLUZhbGxiYWNrLUl0YWxpYyJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUl0YWxpYyIsCiAgICBmYWN0b3JzOiBfbXlyaWFkcHJvX2ZhY3RvcnMuTXlyaWFkUHJvSXRhbGljRmFjdG9ycywKICAgIGJhc2VXaWR0aHM6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNJdGFsaWNXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogX2xpYmVyYXRpb25zYW5zX3dpZHRocy5MaWJlcmF0aW9uU2Fuc0l0YWxpY01hcHBpbmcsCiAgICBtZXRyaWNzOiBfbXlyaWFkcHJvX2ZhY3RvcnMuTXlyaWFkUHJvSXRhbGljTWV0cmljcwogIH07CiAgdFsiTXlyaWFkUHJvLUJvbGRJdCJdID0gdFsiTXlyaWFkUHJvLUJvbGRJdGFsaWMiXSA9IHRbIlBkZkpTLUZhbGxiYWNrLUJvbGRJdGFsaWMiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1Cb2xkSXRhbGljIiwKICAgIGZhY3RvcnM6IF9teXJpYWRwcm9fZmFjdG9ycy5NeXJpYWRQcm9Cb2xkSXRhbGljRmFjdG9ycywKICAgIGJhc2VXaWR0aHM6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNCb2xkSXRhbGljV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNCb2xkSXRhbGljTWFwcGluZywKICAgIG1ldHJpY3M6IF9teXJpYWRwcm9fZmFjdG9ycy5NeXJpYWRQcm9Cb2xkSXRhbGljTWV0cmljcwogIH07CiAgdC5BcmlhbE1UID0gdC5BcmlhbCA9IHRbIkFyaWFsLVJlZ3VsYXIiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1SZWd1bGFyIiwKICAgIGJhc2VXaWR0aHM6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNSZWd1bGFyV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNSZWd1bGFyTWFwcGluZwogIH07CiAgdFsiQXJpYWwtQm9sZE1UIl0gPSB0WyJBcmlhbC1Cb2xkIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZCIsCiAgICBiYXNlV2lkdGhzOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zQm9sZFdpZHRocywKICAgIGJhc2VNYXBwaW5nOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zQm9sZE1hcHBpbmcKICB9OwogIHRbIkFyaWFsLUl0YWxpY01UIl0gPSB0WyJBcmlhbC1JdGFsaWMiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1JdGFsaWMiLAogICAgYmFzZVdpZHRoczogX2xpYmVyYXRpb25zYW5zX3dpZHRocy5MaWJlcmF0aW9uU2Fuc0l0YWxpY1dpZHRocywKICAgIGJhc2VNYXBwaW5nOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zSXRhbGljTWFwcGluZwogIH07CiAgdFsiQXJpYWwtQm9sZEl0YWxpY01UIl0gPSB0WyJBcmlhbC1Cb2xkSXRhbGljIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYyIsCiAgICBiYXNlV2lkdGhzOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zQm9sZEl0YWxpY1dpZHRocywKICAgIGJhc2VNYXBwaW5nOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zQm9sZEl0YWxpY01hcHBpbmcKICB9OwogIHRbIkNhbGlicmktUmVndWxhciJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIiLAogICAgZmFjdG9yczogX2NhbGlicmlfZmFjdG9ycy5DYWxpYnJpUmVndWxhckZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zUmVndWxhcldpZHRocywKICAgIGJhc2VNYXBwaW5nOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zUmVndWxhck1hcHBpbmcsCiAgICBtZXRyaWNzOiBfY2FsaWJyaV9mYWN0b3JzLkNhbGlicmlSZWd1bGFyTWV0cmljcwogIH07CiAgdFsiQ2FsaWJyaS1Cb2xkIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZCIsCiAgICBmYWN0b3JzOiBfY2FsaWJyaV9mYWN0b3JzLkNhbGlicmlCb2xkRmFjdG9ycywKICAgIGJhc2VXaWR0aHM6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNCb2xkV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNCb2xkTWFwcGluZywKICAgIG1ldHJpY3M6IF9jYWxpYnJpX2ZhY3RvcnMuQ2FsaWJyaUJvbGRNZXRyaWNzCiAgfTsKICB0WyJDYWxpYnJpLUl0YWxpYyJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUl0YWxpYyIsCiAgICBmYWN0b3JzOiBfY2FsaWJyaV9mYWN0b3JzLkNhbGlicmlJdGFsaWNGYWN0b3JzLAogICAgYmFzZVdpZHRoczogX2xpYmVyYXRpb25zYW5zX3dpZHRocy5MaWJlcmF0aW9uU2Fuc0l0YWxpY1dpZHRocywKICAgIGJhc2VNYXBwaW5nOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zSXRhbGljTWFwcGluZywKICAgIG1ldHJpY3M6IF9jYWxpYnJpX2ZhY3RvcnMuQ2FsaWJyaUl0YWxpY01ldHJpY3MKICB9OwogIHRbIkNhbGlicmktQm9sZEl0YWxpYyJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUJvbGRJdGFsaWMiLAogICAgZmFjdG9yczogX2NhbGlicmlfZmFjdG9ycy5DYWxpYnJpQm9sZEl0YWxpY0ZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zQm9sZEl0YWxpY1dpZHRocywKICAgIGJhc2VNYXBwaW5nOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zQm9sZEl0YWxpY01hcHBpbmcsCiAgICBtZXRyaWNzOiBfY2FsaWJyaV9mYWN0b3JzLkNhbGlicmlCb2xkSXRhbGljTWV0cmljcwogIH07CiAgdFsiU2Vnb2V1aS1SZWd1bGFyIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtUmVndWxhciIsCiAgICBmYWN0b3JzOiBfc2Vnb2V1aV9mYWN0b3JzLlNlZ29ldWlSZWd1bGFyRmFjdG9ycywKICAgIGJhc2VXaWR0aHM6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNSZWd1bGFyV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNSZWd1bGFyTWFwcGluZywKICAgIG1ldHJpY3M6IF9zZWdvZXVpX2ZhY3RvcnMuU2Vnb2V1aVJlZ3VsYXJNZXRyaWNzCiAgfTsKICB0WyJTZWdvZXVpLUJvbGQiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1Cb2xkIiwKICAgIGZhY3RvcnM6IF9zZWdvZXVpX2ZhY3RvcnMuU2Vnb2V1aUJvbGRGYWN0b3JzLAogICAgYmFzZVdpZHRoczogX2xpYmVyYXRpb25zYW5zX3dpZHRocy5MaWJlcmF0aW9uU2Fuc0JvbGRXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogX2xpYmVyYXRpb25zYW5zX3dpZHRocy5MaWJlcmF0aW9uU2Fuc0JvbGRNYXBwaW5nLAogICAgbWV0cmljczogX3NlZ29ldWlfZmFjdG9ycy5TZWdvZXVpQm9sZE1ldHJpY3MKICB9OwogIHRbIlNlZ29ldWktSXRhbGljIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtSXRhbGljIiwKICAgIGZhY3RvcnM6IF9zZWdvZXVpX2ZhY3RvcnMuU2Vnb2V1aUl0YWxpY0ZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zSXRhbGljV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNJdGFsaWNNYXBwaW5nLAogICAgbWV0cmljczogX3NlZ29ldWlfZmFjdG9ycy5TZWdvZXVpSXRhbGljTWV0cmljcwogIH07CiAgdFsiU2Vnb2V1aS1Cb2xkSXRhbGljIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYyIsCiAgICBmYWN0b3JzOiBfc2Vnb2V1aV9mYWN0b3JzLlNlZ29ldWlCb2xkSXRhbGljRmFjdG9ycywKICAgIGJhc2VXaWR0aHM6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNCb2xkSXRhbGljV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNCb2xkSXRhbGljTWFwcGluZywKICAgIG1ldHJpY3M6IF9zZWdvZXVpX2ZhY3RvcnMuU2Vnb2V1aUJvbGRJdGFsaWNNZXRyaWNzCiAgfTsKICB0WyJIZWx2ZXRpY2EtUmVndWxhciJdID0gdC5IZWx2ZXRpY2EgPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtUmVndWxhciIsCiAgICBmYWN0b3JzOiBfaGVsdmV0aWNhX2ZhY3RvcnMuSGVsdmV0aWNhUmVndWxhckZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zUmVndWxhcldpZHRocywKICAgIGJhc2VNYXBwaW5nOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zUmVndWxhck1hcHBpbmcsCiAgICBtZXRyaWNzOiBfaGVsdmV0aWNhX2ZhY3RvcnMuSGVsdmV0aWNhUmVndWxhck1ldHJpY3MKICB9OwogIHRbIkhlbHZldGljYS1Cb2xkIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZCIsCiAgICBmYWN0b3JzOiBfaGVsdmV0aWNhX2ZhY3RvcnMuSGVsdmV0aWNhQm9sZEZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zQm9sZFdpZHRocywKICAgIGJhc2VNYXBwaW5nOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zQm9sZE1hcHBpbmcsCiAgICBtZXRyaWNzOiBfaGVsdmV0aWNhX2ZhY3RvcnMuSGVsdmV0aWNhQm9sZE1ldHJpY3MKICB9OwogIHRbIkhlbHZldGljYS1JdGFsaWMiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1JdGFsaWMiLAogICAgZmFjdG9yczogX2hlbHZldGljYV9mYWN0b3JzLkhlbHZldGljYUl0YWxpY0ZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zSXRhbGljV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IF9saWJlcmF0aW9uc2Fuc193aWR0aHMuTGliZXJhdGlvblNhbnNJdGFsaWNNYXBwaW5nLAogICAgbWV0cmljczogX2hlbHZldGljYV9mYWN0b3JzLkhlbHZldGljYUl0YWxpY01ldHJpY3MKICB9OwogIHRbIkhlbHZldGljYS1Cb2xkSXRhbGljIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYyIsCiAgICBmYWN0b3JzOiBfaGVsdmV0aWNhX2ZhY3RvcnMuSGVsdmV0aWNhQm9sZEl0YWxpY0ZhY3RvcnMsCiAgICBiYXNlV2lkdGhzOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zQm9sZEl0YWxpY1dpZHRocywKICAgIGJhc2VNYXBwaW5nOiBfbGliZXJhdGlvbnNhbnNfd2lkdGhzLkxpYmVyYXRpb25TYW5zQm9sZEl0YWxpY01hcHBpbmcsCiAgICBtZXRyaWNzOiBfaGVsdmV0aWNhX2ZhY3RvcnMuSGVsdmV0aWNhQm9sZEl0YWxpY01ldHJpY3MKICB9Owp9KTsKZnVuY3Rpb24gZ2V0WGZhRm9udE5hbWUobmFtZSkgewogIGNvbnN0IGZvbnROYW1lID0gKDAsIF9mb250c191dGlscy5ub3JtYWxpemVGb250TmFtZSkobmFtZSk7CiAgY29uc3QgZm9udE1hcCA9IGdldFhGQUZvbnRNYXAoKTsKICByZXR1cm4gZm9udE1hcFtmb250TmFtZV07Cn0KZnVuY3Rpb24gZ2V0WGZhRm9udFdpZHRocyhuYW1lKSB7CiAgY29uc3QgaW5mbyA9IGdldFhmYUZvbnROYW1lKG5hbWUpOwogIGlmICghaW5mbykgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGNvbnN0IHsKICAgIGJhc2VXaWR0aHMsCiAgICBiYXNlTWFwcGluZywKICAgIGZhY3RvcnMKICB9ID0gaW5mbzsKICBsZXQgcmVzY2FsZWRCYXNlV2lkdGhzOwogIGlmICghZmFjdG9ycykgewogICAgcmVzY2FsZWRCYXNlV2lkdGhzID0gYmFzZVdpZHRoczsKICB9IGVsc2UgewogICAgcmVzY2FsZWRCYXNlV2lkdGhzID0gYmFzZVdpZHRocy5tYXAoKHcsIGkpID0+IHcgKiBmYWN0b3JzW2ldKTsKICB9CiAgbGV0IGN1cnJlbnRDb2RlID0gLTI7CiAgbGV0IGN1cnJlbnRBcnJheTsKICBjb25zdCBuZXdXaWR0aHMgPSBbXTsKICBmb3IgKGNvbnN0IFt1bmljb2RlLCBnbHlwaEluZGV4XSBvZiBiYXNlTWFwcGluZy5tYXAoKGNoYXJVbmljb2RlLCBpbmRleCkgPT4gW2NoYXJVbmljb2RlLCBpbmRleF0pLnNvcnQoKF9yZWYsIF9yZWYyKSA9PiB7CiAgICBsZXQgW3VuaWNvZGUxXSA9IF9yZWY7CiAgICBsZXQgW3VuaWNvZGUyXSA9IF9yZWYyOwogICAgcmV0dXJuIHVuaWNvZGUxIC0gdW5pY29kZTI7CiAgfSkpIHsKICAgIGlmICh1bmljb2RlID09PSAtMSkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGlmICh1bmljb2RlID09PSBjdXJyZW50Q29kZSArIDEpIHsKICAgICAgY3VycmVudEFycmF5LnB1c2gocmVzY2FsZWRCYXNlV2lkdGhzW2dseXBoSW5kZXhdKTsKICAgICAgY3VycmVudENvZGUgKz0gMTsKICAgIH0gZWxzZSB7CiAgICAgIGN1cnJlbnRDb2RlID0gdW5pY29kZTsKICAgICAgY3VycmVudEFycmF5ID0gW3Jlc2NhbGVkQmFzZVdpZHRoc1tnbHlwaEluZGV4XV07CiAgICAgIG5ld1dpZHRocy5wdXNoKHVuaWNvZGUsIGN1cnJlbnRBcnJheSk7CiAgICB9CiAgfQogIHJldHVybiBuZXdXaWR0aHM7Cn0KZnVuY3Rpb24gZ2V0WGZhRm9udERpY3QobmFtZSkgewogIGNvbnN0IHdpZHRocyA9IGdldFhmYUZvbnRXaWR0aHMobmFtZSk7CiAgY29uc3QgZGljdCA9IG5ldyBfcHJpbWl0aXZlcy5EaWN0KG51bGwpOwogIGRpY3Quc2V0KCJCYXNlRm9udCIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KG5hbWUpKTsKICBkaWN0LnNldCgiVHlwZSIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJGb250IikpOwogIGRpY3Quc2V0KCJTdWJ0eXBlIiwgX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIkNJREZvbnRUeXBlMiIpKTsKICBkaWN0LnNldCgiRW5jb2RpbmciLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiSWRlbnRpdHktSCIpKTsKICBkaWN0LnNldCgiQ0lEVG9HSURNYXAiLCBfcHJpbWl0aXZlcy5OYW1lLmdldCgiSWRlbnRpdHkiKSk7CiAgZGljdC5zZXQoIlciLCB3aWR0aHMpOwogIGRpY3Quc2V0KCJGaXJzdENoYXIiLCB3aWR0aHNbMF0pOwogIGRpY3Quc2V0KCJMYXN0Q2hhciIsIHdpZHRocy5hdCgtMikgKyB3aWR0aHMuYXQoLTEpLmxlbmd0aCAtIDEpOwogIGNvbnN0IGRlc2NyaXB0b3IgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdChudWxsKTsKICBkaWN0LnNldCgiRm9udERlc2NyaXB0b3IiLCBkZXNjcmlwdG9yKTsKICBjb25zdCBzeXN0ZW1JbmZvID0gbmV3IF9wcmltaXRpdmVzLkRpY3QobnVsbCk7CiAgc3lzdGVtSW5mby5zZXQoIk9yZGVyaW5nIiwgIklkZW50aXR5Iik7CiAgc3lzdGVtSW5mby5zZXQoIlJlZ2lzdHJ5IiwgIkFkb2JlIik7CiAgc3lzdGVtSW5mby5zZXQoIlN1cHBsZW1lbnQiLCAwKTsKICBkaWN0LnNldCgiQ0lEU3lzdGVtSW5mbyIsIHN5c3RlbUluZm8pOwogIHJldHVybiBkaWN0Owp9CgovKioqLyB9KSwKLyogMTg3ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMpID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5DYWxpYnJpUmVndWxhck1ldHJpY3MgPSBleHBvcnRzLkNhbGlicmlSZWd1bGFyRmFjdG9ycyA9IGV4cG9ydHMuQ2FsaWJyaUl0YWxpY01ldHJpY3MgPSBleHBvcnRzLkNhbGlicmlJdGFsaWNGYWN0b3JzID0gZXhwb3J0cy5DYWxpYnJpQm9sZE1ldHJpY3MgPSBleHBvcnRzLkNhbGlicmlCb2xkSXRhbGljTWV0cmljcyA9IGV4cG9ydHMuQ2FsaWJyaUJvbGRJdGFsaWNGYWN0b3JzID0gZXhwb3J0cy5DYWxpYnJpQm9sZEZhY3RvcnMgPSB2b2lkIDA7CmNvbnN0IENhbGlicmlCb2xkRmFjdG9ycyA9IFsxLjM4NzcsIDEsIDEsIDEsIDAuOTc4MDEsIDAuOTI0ODIsIDAuODk1NTIsIDAuOTExMzMsIDAuODE5ODgsIDAuOTc1NjYsIDAuOTgxNTIsIDAuOTM1NDgsIDAuOTM1NDgsIDEuMjc5OCwgMC44NTI4NCwgMC45Mjc5NCwgMSwgMC45NjEzNCwgMS41NDY1NywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC44Mjg0NSwgMC44Mjg0NSwgMC44NTI4NCwgMC44NTI4NCwgMC44NTI4NCwgMC43NTg1OSwgMC45MjEzOCwgMC44MzkwOCwgMC43NzYyLCAwLjczMjkzLCAwLjg3Mjg5LCAwLjczMTMzLCAwLjc1MTQsIDAuODE5MjEsIDAuODczNTYsIDAuOTU5NTgsIDAuNTk1MjYsIDAuNzU3MjcsIDAuNjkyMjUsIDEuMDQ5MjQsIDAuOTEyMSwgMC44Njk0MywgMC43OTc5NSwgMC44ODE5OCwgMC43Nzk1OCwgMC43MDg2NCwgMC44MTA1NSwgMC45MDM5OSwgMC44ODY1MywgMC45NjAxNywgMC44MjU3NywgMC43Nzg5MiwgMC43ODI1NywgMC45NzUwNywgMS41NDY1NywgMC45NzUwNywgMC44NTI4NCwgMC44OTU1MiwgMC45MDE3NiwgMC44ODc2MiwgMC44Nzg1LCAwLjc1MjQxLCAwLjg3ODUsIDAuOTA1MTgsIDAuOTUwMTUsIDAuNzc2MTgsIDAuODc4NSwgMC44ODQwMSwgMC45MTkxNiwgMC44NjMwNCwgMC44ODQwMSwgMC45MTQ4OCwgMC44Nzg1LCAwLjg4MDEsIDAuODc4NSwgMC44Nzg1LCAwLjkxMzQzLCAwLjcxNzMsIDEuMDQxMDYsIDAuODc4NSwgMC44NTA3NSwgMC45NTc5NCwgMC44MjYxNiwgMC44NTE2MiwgMC43OTQ5MiwgMC44ODMzMSwgMS42OTgwOCwgMC44ODMzMSwgMC44NTI4NCwgMC45NzgwMSwgMC44OTU1MiwgMC45MTEzMywgMC44OTU1MiwgMC45MTEzMywgMS43ODAxLCAwLjg5NTUyLCAxLjI0NDg3LCAxLjEzMjU0LCAxLjEyNDAxLCAwLjk2ODM5LCAwLjg1Mjg0LCAwLjY4Nzg3LCAwLjcwNjQ1LCAwLjg1NTkyLCAwLjkwNzQ3LCAxLjAxNDY2LCAxLjAwODgsIDAuOTAzMjMsIDEsIDEuMDc0NjMsIDEsIDAuOTEwNTYsIDAuNzU4MDYsIDEuMTkxMTgsIDAuOTY4MzksIDAuNzg4NjQsIDAuODI4NDUsIDAuODQxMzMsIDAuNzU4NTksIDAuODM5MDgsIDAuODM5MDgsIDAuODM5MDgsIDAuODM5MDgsIDAuODM5MDgsIDAuODM5MDgsIDAuNzc1MzksIDAuNzMyOTMsIDAuNzMxMzMsIDAuNzMxMzMsIDAuNzMxMzMsIDAuNzMxMzMsIDAuOTU5NTgsIDAuOTU5NTgsIDAuOTU5NTgsIDAuOTU5NTgsIDAuODg1MDYsIDAuOTEyMSwgMC44Njk0MywgMC44Njk0MywgMC44Njk0MywgMC44Njk0MywgMC44Njk0MywgMC44NTI4NCwgMC44NzUwOCwgMC45MDM5OSwgMC45MDM5OSwgMC45MDM5OSwgMC45MDM5OSwgMC43Nzg5MiwgMC43OTc5NSwgMC45MDgwNywgMC44ODc2MiwgMC44ODc2MiwgMC44ODc2MiwgMC44ODc2MiwgMC44ODc2MiwgMC44ODc2MiwgMC44NzE1LCAwLjc1MjQxLCAwLjkwNTE4LCAwLjkwNTE4LCAwLjkwNTE4LCAwLjkwNTE4LCAwLjg4NDAxLCAwLjg4NDAxLCAwLjg4NDAxLCAwLjg4NDAxLCAwLjg3ODUsIDAuODc4NSwgMC44ODAxLCAwLjg4MDEsIDAuODgwMSwgMC44ODAxLCAwLjg4MDEsIDAuOTA3NDcsIDAuODkwNDksIDAuODc4NSwgMC44Nzg1LCAwLjg3ODUsIDAuODc4NSwgMC44NTE2MiwgMC44Nzg1LCAwLjg1MTYyLCAwLjgzOTA4LCAwLjg4NzYyLCAwLjgzOTA4LCAwLjg4NzYyLCAwLjgzOTA4LCAwLjg4NzYyLCAwLjczMjkzLCAwLjc1MjQxLCAwLjczMjkzLCAwLjc1MjQxLCAwLjczMjkzLCAwLjc1MjQxLCAwLjczMjkzLCAwLjc1MjQxLCAwLjg3Mjg5LCAwLjgzMDE2LCAwLjg4NTA2LCAwLjkzMTI1LCAwLjczMTMzLCAwLjkwNTE4LCAwLjczMTMzLCAwLjkwNTE4LCAwLjczMTMzLCAwLjkwNTE4LCAwLjczMTMzLCAwLjkwNTE4LCAwLjczMTMzLCAwLjkwNTE4LCAwLjgxOTIxLCAwLjc3NjE4LCAwLjgxOTIxLCAwLjc3NjE4LCAwLjgxOTIxLCAwLjc3NjE4LCAxLCAxLCAwLjg3MzU2LCAwLjg3ODUsIDAuOTEwNzUsIDAuODk2MDgsIDAuOTU5NTgsIDAuODg0MDEsIDAuOTU5NTgsIDAuODg0MDEsIDAuOTU5NTgsIDAuODg0MDEsIDAuOTU5NTgsIDAuODg0MDEsIDAuOTU5NTgsIDAuODg0MDEsIDAuNzYyMjksIDAuOTAxNjcsIDAuNTk1MjYsIDAuOTE5MTYsIDEsIDEsIDAuODYzMDQsIDAuNjkyMjUsIDAuODg0MDEsIDEsIDEsIDAuNzA0MjQsIDAuNzk0NjgsIDAuOTE5MjYsIDAuODgxNzUsIDAuNzA4MjMsIDAuOTQ5MDMsIDAuOTEyMSwgMC44Nzg1LCAxLCAxLCAwLjkxMjEsIDAuODc4NSwgMC44NzgwMiwgMC44ODY1NiwgMC44Nzg1LCAwLjg2OTQzLCAwLjg4MDEsIDAuODY5NDMsIDAuODgwMSwgMC44Njk0MywgMC44ODAxLCAwLjg3NDAyLCAwLjg5MjkxLCAwLjc3OTU4LCAwLjkxMzQzLCAxLCAxLCAwLjc3OTU4LCAwLjkxMzQzLCAwLjcwODY0LCAwLjcxNzMsIDAuNzA4NjQsIDAuNzE3MywgMC43MDg2NCwgMC43MTczLCAwLjcwODY0LCAwLjcxNzMsIDEsIDEsIDAuODEwNTUsIDAuNzU4NDEsIDAuODEwNTUsIDEuMDY0NTIsIDAuOTAzOTksIDAuODc4NSwgMC45MDM5OSwgMC44Nzg1LCAwLjkwMzk5LCAwLjg3ODUsIDAuOTAzOTksIDAuODc4NSwgMC45MDM5OSwgMC44Nzg1LCAwLjkwMzk5LCAwLjg3ODUsIDAuOTYwMTcsIDAuOTU3OTQsIDAuNzc4OTIsIDAuODUxNjIsIDAuNzc4OTIsIDAuNzgyNTcsIDAuNzk0OTIsIDAuNzgyNTcsIDAuNzk0OTIsIDAuNzgyNTcsIDAuNzk0OTIsIDAuOTI5NywgMC41Njg5MiwgMC44MzkwOCwgMC44ODc2MiwgMC43NzUzOSwgMC44NzE1LCAwLjg3NTA4LCAwLjg5MDQ5LCAxLCAxLCAwLjgxMDU1LCAxLjA0MTA2LCAxLjIwNTI4LCAxLjIwNTI4LCAxLCAxLjE1NTQzLCAwLjcwNjc0LCAwLjk4Mzg3LCAwLjk0NzIxLCAxLjMzNDMxLCAxLjQ1ODk0LCAwLjk1MTYxLCAxLjA2MzAzLCAwLjgzOTA4LCAwLjgwMzUyLCAwLjU3MTg0LCAwLjY5NjUsIDAuNTYyODksIDAuODIwMDEsIDAuNTYwMjksIDAuODEyMzUsIDEuMDI5ODgsIDAuODM5MDgsIDAuNzc2MiwgMC42ODE1NiwgMC44MDM2NywgMC43MzEzMywgMC43ODI1NywgMC44NzM1NiwgMC44Njk0MywgMC45NTk1OCwgMC43NTcyNywgMC44OTAxOSwgMS4wNDkyNCwgMC45MTIxLCAwLjc2NDgsIDAuODY5NDMsIDAuODczNTYsIDAuNzk3OTUsIDAuNzgyNzUsIDAuODEwNTUsIDAuNzc4OTIsIDAuOTc2MiwgMC44MjU3NywgMC45OTgxOSwgMC44NDg5NiwgMC45NTk1OCwgMC43Nzg5MiwgMC45NjEwOCwgMS4wMTQwNywgMC44OTA0OSwgMS4wMjk4OCwgMC45NDIxMSwgMC45NjEwOCwgMC44OTM2LCAwLjg0MDIxLCAwLjg3ODQyLCAwLjk2Mzk5LCAwLjc5MTA5LCAwLjg5MDQ5LCAxLjAwODEzLCAxLjAyOTg4LCAwLjg2MDc3LCAwLjg3NDQ1LCAwLjkyMDk5LCAwLjg0NzIzLCAwLjg2NTEzLCAwLjg4MDEsIDAuNzU2MzgsIDAuODU3MTQsIDAuNzgyMTYsIDAuNzk1ODYsIDAuODc5NjUsIDAuOTQyMTEsIDAuOTc3NDcsIDAuNzgyODcsIDAuOTc5MjYsIDAuODQ5NzEsIDEuMDI5ODgsIDAuOTQyMTEsIDAuODgwMSwgMC45NDIxMSwgMC44NDk3MSwgMC43MzEzMywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MDI2NCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MDUxOCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MDU0OCwgMSwgMSwgMSwgMSwgMSwgMSwgMC45NjAxNywgMC45NTc5NCwgMC45NjAxNywgMC45NTc5NCwgMC45NjAxNywgMC45NTc5NCwgMC43Nzg5MiwgMC44NTE2MiwgMSwgMSwgMC44OTU1MiwgMC45MDUyNywgMSwgMC45MDM2MywgMC45Mjc5NCwgMC45Mjc5NCwgMC45Mjc5NCwgMC45Mjc5NCwgMC44NzAxMiwgMC44NzAxMiwgMC44NzAxMiwgMC44OTU1MiwgMC44OTU1MiwgMS40MjI1OSwgMC43MTE0MywgMS4wNjE1MiwgMSwgMSwgMS4wMzM3MiwgMS4wMzM3MiwgMC45NzE3MSwgMS40OTU2LCAyLjI4MDcsIDAuOTM4MzUsIDAuODM0MDYsIDAuOTExMzMsIDAuODQxMDcsIDAuOTExMzMsIDEsIDEsIDEsIDAuNzIwMjEsIDEsIDEuMjMxMDgsIDAuODM0ODksIDAuODg1MjUsIDAuODg1MjUsIDAuODE0OTksIDAuOTA1MjcsIDEuODEwNTUsIDAuOTA1MjcsIDEuODEwNTUsIDEuMzEwMDYsIDEuNTM3MTEsIDAuOTQ0MzQsIDEuMDg2OTYsIDEsIDAuOTUwMTgsIDAuNzcxOTIsIDAuODUyODQsIDAuOTA3NDcsIDEuMTc1MzQsIDAuNjk4MjUsIDAuOTcxNiwgMS4zNzA3NywgMC45MDc0NywgMC45MDc0NywgMC44NTM1NiwgMC45MDc0NywgMC45MDc0NywgMS40NDk0NywgMC44NTI4NCwgMC44OTQxLCAwLjg5NDEsIDAuNzA1NzIsIDAuOCwgMC43MDU3MiwgMC43MDU3MiwgMC43MDU3MiwgMC43MDU3MiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45OTg2MiwgMC45OTg2MiwgMSwgMSwgMSwgMSwgMSwgMS4wODAwNCwgMC45MTAyNywgMSwgMSwgMSwgMC45OTg2MiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MDcyNywgMC45MDcyNywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmV4cG9ydHMuQ2FsaWJyaUJvbGRGYWN0b3JzID0gQ2FsaWJyaUJvbGRGYWN0b3JzOwpjb25zdCBDYWxpYnJpQm9sZE1ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4yMjA3LAogIGxpbmVHYXA6IDAuMjIwNwp9OwpleHBvcnRzLkNhbGlicmlCb2xkTWV0cmljcyA9IENhbGlicmlCb2xkTWV0cmljczsKY29uc3QgQ2FsaWJyaUJvbGRJdGFsaWNGYWN0b3JzID0gWzEuMzg3NywgMSwgMSwgMSwgMC45NzgwMSwgMC45MjQ4MiwgMC44OTU1MiwgMC45MTEzMywgMC44MTk4OCwgMC45NzU2NiwgMC45ODE1MiwgMC45MzU0OCwgMC45MzU0OCwgMS4yNzk4LCAwLjg1Mjg0LCAwLjkyNzk0LCAxLCAwLjk2MTM0LCAxLjU2MjM5LCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjkxMTMzLCAwLjgyODQ1LCAwLjgyODQ1LCAwLjg1Mjg0LCAwLjg1Mjg0LCAwLjg1Mjg0LCAwLjc1ODU5LCAwLjkyMTM4LCAwLjgzOTA4LCAwLjc3NjIsIDAuNzE4MDUsIDAuODcyODksIDAuNzMxMzMsIDAuNzUxNCwgMC44MTkyMSwgMC44NzM1NiwgMC45NTk1OCwgMC41OTUyNiwgMC43NTcyNywgMC42OTIyNSwgMS4wNDkyNCwgMC45MDg3MiwgMC44NTkzOCwgMC43OTc5NSwgMC44NzA2OCwgMC43Nzk1OCwgMC42OTc2NiwgMC44MTA1NSwgMC45MDM5OSwgMC44ODY1MywgMC45NjA2OCwgMC44MjU3NywgMC43Nzg5MiwgMC43ODI1NywgMC45NzUwNywgMS41MjksIDAuOTc1MDcsIDAuODUyODQsIDAuODk1NTIsIDAuOTAxNzYsIDAuOTQ5MDgsIDAuODY0MTEsIDAuNzQwMTIsIDAuODY0MTEsIDAuODgzMjMsIDAuOTUwMTUsIDAuODY0MTEsIDAuODYzMzEsIDAuODg0MDEsIDAuOTE5MTYsIDAuODYzMDQsIDAuODg0MDEsIDAuOTAzOSwgMC44NjMzMSwgMC44NjMzMSwgMC44NjQxMSwgMC44NjQxMSwgMC45MDQ2NCwgMC43MDg1MiwgMS4wNDEwNiwgMC44NjMzMSwgMC44NDM3MiwgMC45NTc5NCwgMC44MjYxNiwgMC44NDU0OCwgMC43OTQ5MiwgMC44ODMzMSwgMS42OTgwOCwgMC44ODMzMSwgMC44NTI4NCwgMC45NzgwMSwgMC44OTU1MiwgMC45MTEzMywgMC44OTU1MiwgMC45MTEzMywgMS43ODAxLCAwLjg5NTUyLCAxLjI0NDg3LCAxLjEzMjU0LCAxLjE5MTI5LCAwLjk2ODM5LCAwLjg1Mjg0LCAwLjY4Nzg3LCAwLjcwNjQ1LCAwLjg1NTkyLCAwLjkwNzQ3LCAxLjAxNDY2LCAxLjAwODgsIDAuOTAzMjMsIDEsIDEuMDc0NjMsIDEsIDAuOTEwNTYsIDAuNzU4MDYsIDEuMTkxMTgsIDAuOTY4MzksIDAuNzg4NjQsIDAuODI4NDUsIDAuODQxMzMsIDAuNzU4NTksIDAuODM5MDgsIDAuODM5MDgsIDAuODM5MDgsIDAuODM5MDgsIDAuODM5MDgsIDAuODM5MDgsIDAuNzc1MzksIDAuNzE4MDUsIDAuNzMxMzMsIDAuNzMxMzMsIDAuNzMxMzMsIDAuNzMxMzMsIDAuOTU5NTgsIDAuOTU5NTgsIDAuOTU5NTgsIDAuOTU5NTgsIDAuODg1MDYsIDAuOTA4NzIsIDAuODU5MzgsIDAuODU5MzgsIDAuODU5MzgsIDAuODU5MzgsIDAuODU5MzgsIDAuODUyODQsIDAuODcwNjgsIDAuOTAzOTksIDAuOTAzOTksIDAuOTAzOTksIDAuOTAzOTksIDAuNzc4OTIsIDAuNzk3OTUsIDAuOTA4MDcsIDAuOTQ5MDgsIDAuOTQ5MDgsIDAuOTQ5MDgsIDAuOTQ5MDgsIDAuOTQ5MDgsIDAuOTQ5MDgsIDAuODU4ODcsIDAuNzQwMTIsIDAuODgzMjMsIDAuODgzMjMsIDAuODgzMjMsIDAuODgzMjMsIDAuODg0MDEsIDAuODg0MDEsIDAuODg0MDEsIDAuODg0MDEsIDAuODc4NSwgMC44NjMzMSwgMC44NjMzMSwgMC44NjMzMSwgMC44NjMzMSwgMC44NjMzMSwgMC44NjMzMSwgMC45MDc0NywgMC44OTA0OSwgMC44NjMzMSwgMC44NjMzMSwgMC44NjMzMSwgMC44NjMzMSwgMC44NDU0OCwgMC44NjQxMSwgMC44NDU0OCwgMC44MzkwOCwgMC45NDkwOCwgMC44MzkwOCwgMC45NDkwOCwgMC44MzkwOCwgMC45NDkwOCwgMC43MTgwNSwgMC43NDAxMiwgMC43MTgwNSwgMC43NDAxMiwgMC43MTgwNSwgMC43NDAxMiwgMC43MTgwNSwgMC43NDAxMiwgMC44NzI4OSwgMC43OTUzOCwgMC44ODUwNiwgMC45MjcyNiwgMC43MzEzMywgMC44ODMyMywgMC43MzEzMywgMC44ODMyMywgMC43MzEzMywgMC44ODMyMywgMC43MzEzMywgMC44ODMyMywgMC43MzEzMywgMC44ODMyMywgMC44MTkyMSwgMC44NjQxMSwgMC44MTkyMSwgMC44NjQxMSwgMC44MTkyMSwgMC44NjQxMSwgMSwgMSwgMC44NzM1NiwgMC44NjMzMSwgMC45MTA3NSwgMC44Nzc3LCAwLjk1OTU4LCAwLjg4NDAxLCAwLjk1OTU4LCAwLjg4NDAxLCAwLjk1OTU4LCAwLjg4NDAxLCAwLjk1OTU4LCAwLjg4NDAxLCAwLjk1OTU4LCAwLjg4NDAxLCAwLjc2NDY3LCAwLjkwMTY3LCAwLjU5NTI2LCAwLjkxOTE2LCAxLCAxLCAwLjg2MzA0LCAwLjY5MjI1LCAwLjg4NDAxLCAxLCAxLCAwLjcwNDI0LCAwLjc3MzEyLCAwLjkxOTI2LCAwLjg4MTc1LCAwLjcwODIzLCAwLjk0OTAzLCAwLjkwODcyLCAwLjg2MzMxLCAxLCAxLCAwLjkwODcyLCAwLjg2MzMxLCAwLjg2OTA2LCAwLjg4MTE2LCAwLjg2MzMxLCAwLjg1OTM4LCAwLjg2MzMxLCAwLjg1OTM4LCAwLjg2MzMxLCAwLjg1OTM4LCAwLjg2MzMxLCAwLjg3NDAyLCAwLjg2NTQ5LCAwLjc3OTU4LCAwLjkwNDY0LCAxLCAxLCAwLjc3OTU4LCAwLjkwNDY0LCAwLjY5NzY2LCAwLjcwODUyLCAwLjY5NzY2LCAwLjcwODUyLCAwLjY5NzY2LCAwLjcwODUyLCAwLjY5NzY2LCAwLjcwODUyLCAxLCAxLCAwLjgxMDU1LCAwLjc1ODQxLCAwLjgxMDU1LCAxLjA2NDUyLCAwLjkwMzk5LCAwLjg2MzMxLCAwLjkwMzk5LCAwLjg2MzMxLCAwLjkwMzk5LCAwLjg2MzMxLCAwLjkwMzk5LCAwLjg2MzMxLCAwLjkwMzk5LCAwLjg2MzMxLCAwLjkwMzk5LCAwLjg2MzMxLCAwLjk2MDY4LCAwLjk1Nzk0LCAwLjc3ODkyLCAwLjg0NTQ4LCAwLjc3ODkyLCAwLjc4MjU3LCAwLjc5NDkyLCAwLjc4MjU3LCAwLjc5NDkyLCAwLjc4MjU3LCAwLjc5NDkyLCAwLjkyOTcsIDAuNTY4OTIsIDAuODM5MDgsIDAuOTQ5MDgsIDAuNzc1MzksIDAuODU4ODcsIDAuODcwNjgsIDAuODkwNDksIDEsIDEsIDAuODEwNTUsIDEuMDQxMDYsIDEuMjA1MjgsIDEuMjA1MjgsIDEsIDEuMTU1NDMsIDAuNzAwODgsIDAuOTgzODcsIDAuOTQ3MjEsIDEuMzM0MzEsIDEuNDU4OTQsIDAuOTUxNjEsIDEuNDgzODcsIDAuODM5MDgsIDAuODAzNTIsIDAuNTcxMTgsIDAuNjk2NSwgMC41NjM0NywgMC43OTE3OSwgMC41NTg1MywgMC44MDM0NiwgMS4wMjk4OCwgMC44MzkwOCwgMC43NzYyLCAwLjY3MTc0LCAwLjg2MDM2LCAwLjczMTMzLCAwLjc4MjU3LCAwLjg3MzU2LCAwLjg2NDQxLCAwLjk1OTU4LCAwLjc1NzI3LCAwLjg5MDE5LCAxLjA0OTI0LCAwLjkwODcyLCAwLjc0ODg5LCAwLjg1OTM4LCAwLjg3ODkxLCAwLjc5Nzk1LCAwLjc5NTcsIDAuODEwNTUsIDAuNzc4OTIsIDAuOTc0NDcsIDAuODI1NzcsIDAuOTc0NjYsIDAuODcxNzksIDAuOTU5NTgsIDAuNzc4OTIsIDAuOTQyNTIsIDAuOTU2MTIsIDAuODc1MywgMS4wMjk4OCwgMC45MjczMywgMC45NDI1MiwgMC44NzQxMSwgMC44NDAyMSwgMC44NzI4LCAwLjk1NjEyLCAwLjc0MDgxLCAwLjg3NTMsIDEuMDIxODksIDEuMDI5ODgsIDAuODQ4MTQsIDAuODc0NDUsIDAuOTE4MjIsIDAuODQ3MjMsIDAuODU2NjgsIDAuODYzMzEsIDAuODEzNDQsIDAuODc1ODEsIDAuNzY0MjIsIDAuODIwNDYsIDAuOTYwNTcsIDAuOTI3MzMsIDAuOTkzNzUsIDAuNzgwMjIsIDAuOTU0NTIsIDAuODYwMTUsIDEuMDI5ODgsIDAuOTI3MzMsIDAuODYzMzEsIDAuOTI3MzMsIDAuODYwMTUsIDAuNzMxMzMsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTA2MzEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuODgzMjMsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuODUxNzQsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTYwNjgsIDAuOTU3OTQsIDAuOTYwNjgsIDAuOTU3OTQsIDAuOTYwNjgsIDAuOTU3OTQsIDAuNzc4OTIsIDAuODQ1NDgsIDEsIDEsIDAuODk1NTIsIDAuOTA1MjcsIDEsIDAuOTAzNjMsIDAuOTI3OTQsIDAuOTI3OTQsIDAuOTI3OTQsIDAuODk4MDcsIDAuODcwMTIsIDAuODcwMTIsIDAuODcwMTIsIDAuODk1NTIsIDAuODk1NTIsIDEuNDIyNTksIDAuNzEwOTQsIDEuMDYxNTIsIDEsIDEsIDEuMDMzNzIsIDEuMDMzNzIsIDAuOTcxNzEsIDEuNDk1NiwgMi4yODA3LCAwLjkyOTcyLCAwLjgzNDA2LCAwLjkxMTMzLCAwLjgzMzI2LCAwLjkxMTMzLCAxLCAxLCAxLCAwLjcyMDIxLCAxLCAxLjIzMTA4LCAwLjgzNDg5LCAwLjg4NTI1LCAwLjg4NTI1LCAwLjgxNDk5LCAwLjkwNjE2LCAxLjgxMDU1LCAwLjkwNTI3LCAxLjgxMDU1LCAxLjMxMDcsIDEuNTM3MTEsIDAuOTQ0MzQsIDEuMDg2OTYsIDEsIDAuOTUwMTgsIDAuNzcxOTIsIDAuODUyODQsIDAuOTA3NDcsIDEuMTc1MzQsIDAuNjk4MjUsIDAuOTcxNiwgMS4zNzA3NywgMC45MDc0NywgMC45MDc0NywgMC44NTM1NiwgMC45MDc0NywgMC45MDc0NywgMS40NDk0NywgMC44NTI4NCwgMC44OTQxLCAwLjg5NDEsIDAuNzA1NzIsIDAuOCwgMC43MDU3MiwgMC43MDU3MiwgMC43MDU3MiwgMC43MDU3MiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45OTg2MiwgMC45OTg2MiwgMSwgMSwgMSwgMSwgMSwgMS4wODAwNCwgMC45MTAyNywgMSwgMSwgMSwgMC45OTg2MiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MDcyNywgMC45MDcyNywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmV4cG9ydHMuQ2FsaWJyaUJvbGRJdGFsaWNGYWN0b3JzID0gQ2FsaWJyaUJvbGRJdGFsaWNGYWN0b3JzOwpjb25zdCBDYWxpYnJpQm9sZEl0YWxpY01ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4yMjA3LAogIGxpbmVHYXA6IDAuMjIwNwp9OwpleHBvcnRzLkNhbGlicmlCb2xkSXRhbGljTWV0cmljcyA9IENhbGlicmlCb2xkSXRhbGljTWV0cmljczsKY29uc3QgQ2FsaWJyaUl0YWxpY0ZhY3RvcnMgPSBbMS4zODc3LCAxLCAxLCAxLCAxLjE3MjIzLCAxLjEyOTMsIDAuODk1NTIsIDAuOTExMzMsIDAuODAzOTUsIDEuMDIyNjksIDEuMTU2MDEsIDAuOTEwNTYsIDAuOTEwNTYsIDEuMjc5OCwgMC44NTI4NCwgMC44OTgwNywgMSwgMC45MDg2MSwgMS4zOTU0MywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45NjMwOSwgMC45NjMwOSwgMC44NTI4NCwgMC44NTI4NCwgMC44NTI4NCwgMC44MzMxOSwgMC44ODA3MSwgMC44Njc1LCAwLjgxNTUyLCAwLjcyMzQ2LCAwLjg1MTkzLCAwLjczMjA2LCAwLjc1MjIsIDAuODExMDUsIDAuODYyNzUsIDAuOTA2ODUsIDAuNjM3NywgMC43Nzg5MiwgMC43NTU5MywgMS4wMjYzOCwgMC44OTI0OSwgMC44NDExOCwgMC43NzQ1MiwgMC44NTM3NCwgMC43NTE4NiwgMC42Nzc4OSwgMC43OTc3NiwgMC44ODg0NCwgMC44NTA2NiwgMC45NDMwOSwgMC43NzgxOCwgMC43MzA2LCAwLjc2NjU5LCAxLjEwMzY5LCAxLjM4MzEzLCAxLjEwMzY5LCAxLjA2MTM5LCAwLjg5NTUyLCAwLjg3MzksIDAuOTI0NSwgMC45MjQ1LCAwLjgzMjAzLCAwLjkyNDUsIDAuODU4NjUsIDEuMDk4NDIsIDAuOTI0NSwgMC45MjQ1LCAxLjAzMjk3LCAxLjA3NjkyLCAwLjkwOTE4LCAxLjAzMjk3LCAwLjk0OTU5LCAwLjkyNDUsIDAuOTIyNzQsIDAuOTI0NSwgMC45MjQ1LCAxLjAyOTMzLCAwLjc3ODMyLCAxLjIwNTYyLCAwLjkyNDUsIDAuODkxNiwgMC45ODk4NiwgMC44NjYyMSwgMC44OTQ1MywgMC43OTAwNCwgMC45NDE1MiwgMS43NzI1NiwgMC45NDE1MiwgMC44NTI4NCwgMC45NzgwMSwgMC44OTU1MiwgMC45MTEzMywgMC44OTU1MiwgMC45MTEzMywgMS45MTcyOSwgMC44OTU1MiwgMS4xNzg4OSwgMS4xMzI1NCwgMS4xNjM1OSwgMC45MjA5OCwgMC44NTI4NCwgMC42ODc4NywgMC43MTM1MywgMC44NDczNywgMC45MDc0NywgMS4wMDg4LCAxLjAwNDQsIDAuODc2ODMsIDEsIDEuMDkwOTEsIDEsIDAuOTIyMjksIDAuNzM5LCAxLjE1NjQyLCAwLjkyMDk4LCAwLjc2Mjg4LCAwLjgwNTA0LCAwLjgwOTcyLCAwLjc1ODU5LCAwLjg2NzUsIDAuODY3NSwgMC44Njc1LCAwLjg2NzUsIDAuODY3NSwgMC44Njc1LCAwLjc2MzE4LCAwLjcyMzQ2LCAwLjczMjA2LCAwLjczMjA2LCAwLjczMjA2LCAwLjczMjA2LCAwLjkwNjg1LCAwLjkwNjg1LCAwLjkwNjg1LCAwLjkwNjg1LCAwLjg2NDc3LCAwLjg5MjQ5LCAwLjg0MTE4LCAwLjg0MTE4LCAwLjg0MTE4LCAwLjg0MTE4LCAwLjg0MTE4LCAwLjg1Mjg0LCAwLjg0NTU3LCAwLjg4ODQ0LCAwLjg4ODQ0LCAwLjg4ODQ0LCAwLjg4ODQ0LCAwLjczMDYsIDAuNzc0NTIsIDAuODYzMzEsIDAuOTI0NSwgMC45MjQ1LCAwLjkyNDUsIDAuOTI0NSwgMC45MjQ1LCAwLjkyNDUsIDAuODQ4NDMsIDAuODMyMDMsIDAuODU4NjUsIDAuODU4NjUsIDAuODU4NjUsIDAuODU4NjUsIDAuODI2MDEsIDAuODI2MDEsIDAuODI2MDEsIDAuODI2MDEsIDAuOTQ0NjksIDAuOTI0NSwgMC45MjI3NCwgMC45MjI3NCwgMC45MjI3NCwgMC45MjI3NCwgMC45MjI3NCwgMC45MDc0NywgMC44NjY1MSwgMC45MjQ1LCAwLjkyNDUsIDAuOTI0NSwgMC45MjQ1LCAwLjg5NDUzLCAwLjkyNDUsIDAuODk0NTMsIDAuODY3NSwgMC45MjQ1LCAwLjg2NzUsIDAuOTI0NSwgMC44Njc1LCAwLjkyNDUsIDAuNzIzNDYsIDAuODMyMDMsIDAuNzIzNDYsIDAuODMyMDMsIDAuNzIzNDYsIDAuODMyMDMsIDAuNzIzNDYsIDAuODMyMDMsIDAuODUxOTMsIDAuODg3NSwgMC44NjQ3NywgMC45OTAzNCwgMC43MzIwNiwgMC44NTg2NSwgMC43MzIwNiwgMC44NTg2NSwgMC43MzIwNiwgMC44NTg2NSwgMC43MzIwNiwgMC44NTg2NSwgMC43MzIwNiwgMC44NTg2NSwgMC44MTEwNSwgMC45MjQ1LCAwLjgxMTA1LCAwLjkyNDUsIDAuODExMDUsIDAuOTI0NSwgMSwgMSwgMC44NjI3NSwgMC45MjQ1LCAwLjkwODcyLCAwLjkzNTkxLCAwLjkwNjg1LCAwLjgyNjAxLCAwLjkwNjg1LCAwLjgyNjAxLCAwLjkwNjg1LCAwLjgyNjAxLCAwLjkwNjg1LCAxLjAzMjk3LCAwLjkwNjg1LCAwLjgyNjAxLCAwLjc3ODk2LCAxLjA1NjExLCAwLjYzNzcsIDEuMDc2OTIsIDEsIDEsIDAuOTA5MTgsIDAuNzU1OTMsIDEuMDMyOTcsIDEsIDEsIDAuNzYwMzIsIDAuOTM3NSwgMC45ODE1NiwgMC45MzQwNywgMC43NzI2MSwgMS4xMTQyOSwgMC44OTI0OSwgMC45MjQ1LCAxLCAxLCAwLjg5MjQ5LCAwLjkyNDUsIDAuOTI1MzQsIDAuODY2OTgsIDAuOTI0NSwgMC44NDExOCwgMC45MjI3NCwgMC44NDExOCwgMC45MjI3NCwgMC44NDExOCwgMC45MjI3NCwgMC44NjY3LCAwLjg2MjkxLCAwLjc1MTg2LCAxLjAyOTMzLCAxLCAxLCAwLjc1MTg2LCAxLjAyOTMzLCAwLjY3Nzg5LCAwLjc3ODMyLCAwLjY3Nzg5LCAwLjc3ODMyLCAwLjY3Nzg5LCAwLjc3ODMyLCAwLjY3Nzg5LCAwLjc3ODMyLCAxLCAxLCAwLjc5Nzc2LCAwLjk3NjU1LCAwLjc5Nzc2LCAxLjIzMDIzLCAwLjg4ODQ0LCAwLjkyNDUsIDAuODg4NDQsIDAuOTI0NSwgMC44ODg0NCwgMC45MjQ1LCAwLjg4ODQ0LCAwLjkyNDUsIDAuODg4NDQsIDAuOTI0NSwgMC44ODg0NCwgMC45MjQ1LCAwLjk0MzA5LCAwLjk4OTg2LCAwLjczMDYsIDAuODk0NTMsIDAuNzMwNiwgMC43NjY1OSwgMC43OTAwNCwgMC43NjY1OSwgMC43OTAwNCwgMC43NjY1OSwgMC43OTAwNCwgMS4wOTIzMSwgMC41NDg3MywgMC44Njc1LCAwLjkyNDUsIDAuNzYzMTgsIDAuODQ4NDMsIDAuODQ1NTcsIDAuODY2NTEsIDEsIDEsIDAuNzk3NzYsIDEuMjA1NjIsIDEuMTg2MjIsIDEuMTg2MjIsIDEsIDEuMTQzNywgMC42NzAwOSwgMC45NjMzNCwgMC45MzY5NSwgMS4zNTE5MSwgMS40MDkwOSwgMC45NTE2MSwgMS40ODM4NywgMC44Njc1LCAwLjkwODYxLCAwLjYxOTIsIDAuNzM2MywgMC42NDgyNCwgMC44MjQxMSwgMC41NjMyMSwgMC44NTY5NiwgMS4yMzUxNiwgMC44Njc1LCAwLjgxNTUyLCAwLjcyODYsIDAuODQxMzQsIDAuNzMyMDYsIDAuNzY2NTksIDAuODYyNzUsIDAuODQzNjksIDAuOTA2ODUsIDAuNzc4OTIsIDAuODU4NzEsIDEuMDI2MzgsIDAuODkyNDksIDAuNzU4MjgsIDAuODQxMTgsIDAuODU5ODQsIDAuNzc0NTIsIDAuNzY0NjYsIDAuNzk3NzYsIDAuNzMwNiwgMC45MDc4MiwgMC43NzgxOCwgMC45MDMsIDAuODcyOTEsIDAuOTA2ODUsIDAuNzMwNiwgMC45OTA1OCwgMS4wMzY2NywgMC45NDYzNSwgMS4yMzUxNiwgMC45ODQ5LCAwLjk5MDU4LCAwLjkyMzkzLCAwLjg5MTYsIDAuOTQyLCAxLjAzNjY3LCAwLjc1MDI2LCAwLjk0NjM1LCAxLjAyOTcsIDEuMjM1MTYsIDAuOTA5MTgsIDAuOTQwNDgsIDAuOTgyMTcsIDAuODk3NDYsIDAuODQxNTMsIDAuOTIyNzQsIDAuODI1MDcsIDAuODg4MzIsIDAuODQ0MzgsIDAuODgxNzgsIDEuMDM1MjUsIDAuOTg0OSwgMS4wMDIyNSwgMC43ODA4NiwgMC45NzI0OCwgMC44OTQwNCwgMS4yMzUxNiwgMC45ODQ5LCAwLjkyMjc0LCAwLjk4NDksIDAuODk0MDQsIDAuNzMyMDYsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuODk2OTMsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuODU4NjUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTA5MzMsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTQzMDksIDAuOTg5ODYsIDAuOTQzMDksIDAuOTg5ODYsIDAuOTQzMDksIDAuOTg5ODYsIDAuNzMwNiwgMC44OTQ1MywgMSwgMSwgMC44OTU1MiwgMC45MDUyNywgMSwgMC45MDE4NiwgMS4xMjMwOCwgMS4xMjMwOCwgMS4xMjMwOCwgMS4xMjMwOCwgMS4yNTY2LCAxLjI1NjYsIDEuMjU2NiwgMC44OTU1MiwgMC44OTU1MiwgMS40MjI1OSwgMC42ODk5NCwgMS4wMzgwOSwgMSwgMSwgMS4wMTc2LCAxLjAxNzYsIDEuMTE1MjMsIDEuNDk1NiwgMi4wMTQ2MiwgMC45Nzg1OCwgMC44MjYxNiwgMC45MTEzMywgMC44MzQzNywgMC45MTEzMywgMSwgMSwgMSwgMC43MDUwOCwgMSwgMS4yMzEwOCwgMC43OTgwMSwgMC44NDQyNiwgMC44NDQyNiwgMC43NzQsIDAuOTA1NzIsIDEuODEwNTUsIDAuOTA3NDksIDEuODEwNTUsIDEuMjg4MDksIDEuNTU0NjksIDAuOTQ0MzQsIDEuMDc4MDYsIDEsIDAuOTcwOTQsIDAuNzU4OSwgMC44NTI4NCwgMC45MDc0NywgMS4xOTY1OCwgMC42OTgyNSwgMC45NzYyMiwgMS4zMzUxMiwgMC45MDc0NywgMC45MDc0NywgMC44NTI4NCwgMC45MDc0NywgMC45MDc0NywgMS40NDk0NywgMC44NTI4NCwgMC44OTQxLCAwLjg5NDEsIDAuNzA1NzIsIDAuOCwgMC43MDU3MiwgMC43MDU3MiwgMC43MDU3MiwgMC43MDU3MiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45OTg2MiwgMC45OTg2MiwgMSwgMSwgMSwgMSwgMSwgMS4wMzM2LCAwLjkxMDI3LCAxLCAxLCAxLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjA1ODU5LCAxLjA1ODU5LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKZXhwb3J0cy5DYWxpYnJpSXRhbGljRmFjdG9ycyA9IENhbGlicmlJdGFsaWNGYWN0b3JzOwpjb25zdCBDYWxpYnJpSXRhbGljTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjIyMDcsCiAgbGluZUdhcDogMC4yMjA3Cn07CmV4cG9ydHMuQ2FsaWJyaUl0YWxpY01ldHJpY3MgPSBDYWxpYnJpSXRhbGljTWV0cmljczsKY29uc3QgQ2FsaWJyaVJlZ3VsYXJGYWN0b3JzID0gWzEuMzg3NywgMSwgMSwgMSwgMS4xNzIyMywgMS4xMjkzLCAwLjg5NTUyLCAwLjkxMTMzLCAwLjgwMzk1LCAxLjAyMjY5LCAxLjE1NjAxLCAwLjkxMDU2LCAwLjkxMDU2LCAxLjI3OTgsIDAuODUyODQsIDAuODk4MDcsIDEsIDAuOTA4NjEsIDEuMzkwMTYsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTYzMDksIDAuOTYzMDksIDAuODUyODQsIDAuODUyODQsIDAuODUyODQsIDAuODMzMTksIDAuODgwNzEsIDAuODY3NSwgMC44MTU1MiwgMC43MzgzNCwgMC44NTE5MywgMC43MzIwNiwgMC43NTIyLCAwLjgxMTA1LCAwLjg2Mjc1LCAwLjkwNjg1LCAwLjYzNzcsIDAuNzc4OTIsIDAuNzU1OTMsIDEuMDI2MzgsIDAuODkzODUsIDAuODUxMjIsIDAuNzc0NTIsIDAuODY1MDMsIDAuNzUxODYsIDAuNjg4ODcsIDAuNzk3NzYsIDAuODg4NDQsIDAuODUwNjYsIDAuOTQyNTgsIDAuNzc4MTgsIDAuNzMwNiwgMC43NjY1OSwgMS4xMDM2OSwgMS4zOTAxNiwgMS4xMDM2OSwgMS4wNjEzOSwgMC44OTU1MiwgMC44NzM5LCAwLjg2MTI4LCAwLjk0NDY5LCAwLjg0NTcsIDAuOTQ0NjksIDAuODk0NjQsIDEuMDk4NDIsIDAuODQ2MzYsIDAuOTQ0NjksIDEuMDMyOTcsIDEuMDc2OTIsIDAuOTA5MTgsIDEuMDMyOTcsIDAuOTU4OTcsIDAuOTQ0NjksIDAuOTQ4MiwgMC45NDQ2OSwgMC45NDQ2OSwgMS4wNDY5MiwgMC43ODIyMywgMS4yMDU2MiwgMC45NDQ2OSwgMC45MDMzMiwgMC45ODk4NiwgMC44NjYyMSwgMC45MDUyNywgMC43OTAwNCwgMC45NDE1MiwgMS43NzI1NiwgMC45NDE1MiwgMC44NTI4NCwgMC45NzgwMSwgMC44OTU1MiwgMC45MTEzMywgMC44OTU1MiwgMC45MTEzMywgMS45MTcyOSwgMC44OTU1MiwgMS4xNzg4OSwgMS4xMzI1NCwgMS4wODcwNywgMC45MjA5OCwgMC44NTI4NCwgMC42ODc4NywgMC43MTM1MywgMC44NDczNywgMC45MDc0NywgMS4wMDg4LCAxLjAwNDQsIDAuODc2ODMsIDEsIDEuMDkwOTEsIDEsIDAuOTIyMjksIDAuNzM5LCAxLjE1NjQyLCAwLjkyMDk4LCAwLjc2Mjg4LCAwLjgwNTA0LCAwLjgwOTcyLCAwLjc1ODU5LCAwLjg2NzUsIDAuODY3NSwgMC44Njc1LCAwLjg2NzUsIDAuODY3NSwgMC44Njc1LCAwLjc2MzE4LCAwLjczODM0LCAwLjczMjA2LCAwLjczMjA2LCAwLjczMjA2LCAwLjczMjA2LCAwLjkwNjg1LCAwLjkwNjg1LCAwLjkwNjg1LCAwLjkwNjg1LCAwLjg2NDc3LCAwLjg5Mzg1LCAwLjg1MTIyLCAwLjg1MTIyLCAwLjg1MTIyLCAwLjg1MTIyLCAwLjg1MTIyLCAwLjg1Mjg0LCAwLjg1MzExLCAwLjg4ODQ0LCAwLjg4ODQ0LCAwLjg4ODQ0LCAwLjg4ODQ0LCAwLjczMDYsIDAuNzc0NTIsIDAuODYzMzEsIDAuODYxMjgsIDAuODYxMjgsIDAuODYxMjgsIDAuODYxMjgsIDAuODYxMjgsIDAuODYxMjgsIDAuODY5MywgMC44NDU3LCAwLjg5NDY0LCAwLjg5NDY0LCAwLjg5NDY0LCAwLjg5NDY0LCAwLjgyNjAxLCAwLjgyNjAxLCAwLjgyNjAxLCAwLjgyNjAxLCAwLjk0NDY5LCAwLjk0NDY5LCAwLjk0ODIsIDAuOTQ4MiwgMC45NDgyLCAwLjk0ODIsIDAuOTQ4MiwgMC45MDc0NywgMC44NjY1MSwgMC45NDQ2OSwgMC45NDQ2OSwgMC45NDQ2OSwgMC45NDQ2OSwgMC45MDUyNywgMC45NDQ2OSwgMC45MDUyNywgMC44Njc1LCAwLjg2MTI4LCAwLjg2NzUsIDAuODYxMjgsIDAuODY3NSwgMC44NjEyOCwgMC43MzgzNCwgMC44NDU3LCAwLjczODM0LCAwLjg0NTcsIDAuNzM4MzQsIDAuODQ1NywgMC43MzgzNCwgMC44NDU3LCAwLjg1MTkzLCAwLjkyNDU0LCAwLjg2NDc3LCAwLjk5MjEsIDAuNzMyMDYsIDAuODk0NjQsIDAuNzMyMDYsIDAuODk0NjQsIDAuNzMyMDYsIDAuODk0NjQsIDAuNzMyMDYsIDAuODk0NjQsIDAuNzMyMDYsIDAuODk0NjQsIDAuODExMDUsIDAuODQ2MzYsIDAuODExMDUsIDAuODQ2MzYsIDAuODExMDUsIDAuODQ2MzYsIDEsIDEsIDAuODYyNzUsIDAuOTQ0NjksIDAuOTA4NzIsIDAuOTU3ODYsIDAuOTA2ODUsIDAuODI2MDEsIDAuOTA2ODUsIDAuODI2MDEsIDAuOTA2ODUsIDAuODI2MDEsIDAuOTA2ODUsIDEuMDMyOTcsIDAuOTA2ODUsIDAuODI2MDEsIDAuNzc3NDEsIDEuMDU2MTEsIDAuNjM3NywgMS4wNzY5MiwgMSwgMSwgMC45MDkxOCwgMC43NTU5MywgMS4wMzI5NywgMSwgMSwgMC43NjAzMiwgMC45MDQ1MiwgMC45ODE1NiwgMS4xMTg0MiwgMC43NzI2MSwgMS4xMTQyOSwgMC44OTM4NSwgMC45NDQ2OSwgMSwgMSwgMC44OTM4NSwgMC45NDQ2OSwgMC45NTg3NywgMC44NjkwMSwgMC45NDQ2OSwgMC44NTEyMiwgMC45NDgyLCAwLjg1MTIyLCAwLjk0ODIsIDAuODUxMjIsIDAuOTQ4MiwgMC44NjY3LCAwLjkwMDE2LCAwLjc1MTg2LCAxLjA0NjkyLCAxLCAxLCAwLjc1MTg2LCAxLjA0NjkyLCAwLjY4ODg3LCAwLjc4MjIzLCAwLjY4ODg3LCAwLjc4MjIzLCAwLjY4ODg3LCAwLjc4MjIzLCAwLjY4ODg3LCAwLjc4MjIzLCAxLCAxLCAwLjc5Nzc2LCAwLjkyMTg4LCAwLjc5Nzc2LCAxLjIzMDIzLCAwLjg4ODQ0LCAwLjk0NDY5LCAwLjg4ODQ0LCAwLjk0NDY5LCAwLjg4ODQ0LCAwLjk0NDY5LCAwLjg4ODQ0LCAwLjk0NDY5LCAwLjg4ODQ0LCAwLjk0NDY5LCAwLjg4ODQ0LCAwLjk0NDY5LCAwLjk0MjU4LCAwLjk4OTg2LCAwLjczMDYsIDAuOTA1MjcsIDAuNzMwNiwgMC43NjY1OSwgMC43OTAwNCwgMC43NjY1OSwgMC43OTAwNCwgMC43NjY1OSwgMC43OTAwNCwgMS4wOTIzMSwgMC41NDg3MywgMC44Njc1LCAwLjg2MTI4LCAwLjc2MzE4LCAwLjg2OTMsIDAuODUzMTEsIDAuODY2NTEsIDEsIDEsIDAuNzk3NzYsIDEuMjA1NjIsIDEuMTg2MjIsIDEuMTg2MjIsIDEsIDEuMTQzNywgMC42Nzc0MiwgMC45NjMzNCwgMC45MzY5NSwgMS4zNTE5MSwgMS40MDkwOSwgMC45NTE2MSwgMS40ODM4NywgMC44NjY4NiwgMC45MDg2MSwgMC42MjI2NywgMC43NDM1OSwgMC42NTY0OSwgMC44NTQ5OCwgMC41Njk2MywgMC44ODI1NCwgMS4yMzUxNiwgMC44Njc1LCAwLjgxNTUyLCAwLjc1NDQzLCAwLjg0NTAzLCAwLjczMjA2LCAwLjc2NjU5LCAwLjg2Mjc1LCAwLjg1MTIyLCAwLjkwNjg1LCAwLjc3ODkyLCAwLjg1NzQ2LCAxLjAyNjM4LCAwLjg5Mzg1LCAwLjc1NjU3LCAwLjg1MTIyLCAwLjg2Mjc1LCAwLjc3NDUyLCAwLjc0MTcxLCAwLjc5Nzc2LCAwLjczMDYsIDAuOTUxNjUsIDAuNzc4MTgsIDAuODk3NzIsIDAuODg4MzEsIDAuOTA2ODUsIDAuNzMwNiwgMC45ODE0MiwgMS4wMjE5MSwgMC45NjU3NiwgMS4yMzUxNiwgMC45OTAxOCwgMC45ODE0MiwgMC45MjM2LCAwLjg5MjU4LCAwLjk0MDM1LCAxLjAyMTkxLCAwLjc4ODQ4LCAwLjk2NTc2LCAwLjk1NjEsIDEuMjM1MTYsIDAuOTA5MTgsIDAuOTI1NzgsIDAuOTU0MjQsIDAuODk3NDYsIDAuODM5NjksIDAuOTQ4MiwgMC44MDExMywgMC44OTQ0MiwgMC44NTIwOCwgMC44NjE1NSwgMC45ODAyMiwgMC45OTAxOCwgMS4wMDQ1MiwgMC44MTIwOSwgMC45OTI0NywgMC44OTE4MSwgMS4yMzUxNiwgMC45OTAxOCwgMC45NDgyLCAwLjk5MDE4LCAwLjg5MTgxLCAwLjczMjA2LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjg4ODQ0LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjg5NDY0LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk2NzY2LCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk0MjU4LCAwLjk4OTg2LCAwLjk0MjU4LCAwLjk4OTg2LCAwLjk0MjU4LCAwLjk4OTg2LCAwLjczMDYsIDAuOTA1MjcsIDEsIDEsIDAuODk1NTIsIDAuOTA1MjcsIDEsIDAuOTAxODYsIDEuMTIzMDgsIDEuMTIzMDgsIDEuMTIzMDgsIDEuMTIzMDgsIDEuMjU2NiwgMS4yNTY2LCAxLjI1NjYsIDAuODk1NTIsIDAuODk1NTIsIDEuNDIyNTksIDAuNjkwNDMsIDEuMDM4MDksIDEsIDEsIDEuMDE3NiwgMS4wMTc2LCAxLjExNTIzLCAxLjQ5NTYsIDIuMDE0NjIsIDAuOTkzMzEsIDAuODI2MTYsIDAuOTExMzMsIDAuODQyODYsIDAuOTExMzMsIDEsIDEsIDEsIDAuNzA1MDgsIDEsIDEuMjMxMDgsIDAuNzk4MDEsIDAuODQ0MjYsIDAuODQ0MjYsIDAuNzc0LCAwLjkwNTI3LCAxLjgxMDU1LCAwLjkwNTI3LCAxLjgxMDU1LCAxLjI4ODA5LCAxLjU1NDY5LCAwLjk0NDM0LCAxLjA3ODA2LCAxLCAwLjk3MDk0LCAwLjc1ODksIDAuODUyODQsIDAuOTA3NDcsIDEuMTk2NTgsIDAuNjk4MjUsIDAuOTc2MjIsIDEuMzM1MTIsIDAuOTA3NDcsIDAuOTA3NDcsIDAuODUzNTYsIDAuOTA3NDcsIDAuOTA3NDcsIDEuNDQ5NDcsIDAuODUyODQsIDAuODk0MSwgMC44OTQxLCAwLjcwNTcyLCAwLjgsIDAuNzA1NzIsIDAuNzA1NzIsIDAuNzA1NzIsIDAuNzA1NzIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTk4NjIsIDAuOTk4NjIsIDEsIDEsIDEsIDEsIDEsIDEuMDMzNiwgMC45MTAyNywgMSwgMSwgMSwgMC45OTg2MiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4wNTg1OSwgMS4wNTg1OSwgMSwgMSwgMSwgMS4wNzE4NSwgMC45OTQxMywgMC45NjMzNCwgMS4wODA2NSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmV4cG9ydHMuQ2FsaWJyaVJlZ3VsYXJGYWN0b3JzID0gQ2FsaWJyaVJlZ3VsYXJGYWN0b3JzOwpjb25zdCBDYWxpYnJpUmVndWxhck1ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4yMjA3LAogIGxpbmVHYXA6IDAuMjIwNwp9OwpleHBvcnRzLkNhbGlicmlSZWd1bGFyTWV0cmljcyA9IENhbGlicmlSZWd1bGFyTWV0cmljczsKCi8qKiovIH0pLAovKiAxODggKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLkhlbHZldGljYVJlZ3VsYXJNZXRyaWNzID0gZXhwb3J0cy5IZWx2ZXRpY2FSZWd1bGFyRmFjdG9ycyA9IGV4cG9ydHMuSGVsdmV0aWNhSXRhbGljTWV0cmljcyA9IGV4cG9ydHMuSGVsdmV0aWNhSXRhbGljRmFjdG9ycyA9IGV4cG9ydHMuSGVsdmV0aWNhQm9sZE1ldHJpY3MgPSBleHBvcnRzLkhlbHZldGljYUJvbGRJdGFsaWNNZXRyaWNzID0gZXhwb3J0cy5IZWx2ZXRpY2FCb2xkSXRhbGljRmFjdG9ycyA9IGV4cG9ydHMuSGVsdmV0aWNhQm9sZEZhY3RvcnMgPSB2b2lkIDA7CmNvbnN0IEhlbHZldGljYUJvbGRGYWN0b3JzID0gWzAuNzYxMTYsIDEsIDEsIDEuMDAwNiwgMC45OTk5OCwgMC45OTk3NCwgMC45OTk3MywgMC45OTk3MywgMC45OTk4MiwgMC45OTk3NywgMS4wMDA4NywgMC45OTk5OCwgMC45OTk5OCwgMC45OTk1OSwgMS4wMDAwMywgMS4wMDA2LCAwLjk5OTk4LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk5OCwgMSwgMS4wMDAwMywgMS4wMDAwMywgMS4wMDAwMywgMS4wMDAyNiwgMC45OTk5LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDI2LCAxLjAwMDIyLCAwLjk5OTc3LCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5OTksIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMDEsIDEuMDAwMjIsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMTYsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5OTgsIDEuMDAwNiwgMC45OTk5OCwgMS4wMDAwMywgMC45OTk3MywgMC45OTk5OCwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk3MywgMC45OTk5OCwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzMsIDEuMDAwNiwgMC45OTk4MiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMC45OTk1OSwgMC45OTk3MywgMC45OTk5OCwgMS4wMDAyNiwgMC45OTk3MywgMS4wMDAyMiwgMC45OTk3MywgMC45OTk3MywgMSwgMC45OTk1OSwgMS4wMDA3NywgMC45OTk1OSwgMS4wMDAwMywgMC45OTk5OCwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wMDA3NywgMC45OTk3MywgMC45OTk5OCwgMS4wMDAyNSwgMC45OTk2OCwgMC45OTk3MywgMS4wMDAwMywgMS4wMDAyNSwgMC42MDI5OSwgMS4wMDAyNCwgMS4wNjQwOSwgMSwgMSwgMC45OTk5OCwgMSwgMC45OTk3MywgMS4wMDA2LCAwLjk5OTk4LCAxLCAwLjk5OTM2LCAwLjk5OTczLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDI2LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAxLCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMDMsIDEuMDAwMjIsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5ODIsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wNjQwOSwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMS4wMzM3NCwgMC45OTk3NywgMS4wMDAyNiwgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAyMiwgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDQyLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDYsIDAuOTk5NzcsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwMjYsIDEuMDAwNiwgMS4wMDAyNiwgMS4wMDA2LCAxLjAwMDI2LCAxLjAzODI4LCAxLjAwMDI2LCAwLjk5OTk5LCAxLjAwMDI2LCAxLjAwMDYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5MywgMC45OTk4LCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLCAxLjAwMDE2LCAwLjk5OTc3LCAwLjk5OTU5LCAwLjk5OTc3LCAwLjk5OTU5LCAwLjk5OTc3LCAwLjk5OTU5LCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTk4LCAxLjAwMDI2LCAwLjgxMjEsIDEuMDAwMjYsIDAuOTk5OTgsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDEuMDAwMTYsIDEuMDAwMjIsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDEuMDAwMjYsIDEsIDEuMDAwMjYsIDEsIDEuMDAwMjYsIDEsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMSwgMC45OTk4MiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMS4wMDAzNCwgMC45OTk3NywgMSwgMC45OTk5NywgMS4wMDAyNiwgMS4wMDA3OCwgMS4wMDAzNiwgMC45OTk3MywgMS4wMDAxMywgMS4wMDA2LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTg4LCAwLjg1MTQ4LCAxLjAwMDAxLCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDYsIDAuOTk5NzcsIDEuMDAwMDEsIDAuOTk5OTksIDAuOTk5NzcsIDEuMDAwNjksIDEuMDAwMjIsIDAuOTk5NzcsIDEuMDAwMDEsIDAuOTk5ODQsIDEuMDAwMjYsIDEuMDAwMDEsIDEuMDAwMjQsIDEuMDAwMDEsIDAuOTk5OSwgMSwgMS4wMDA2LCAxLjAwMDAxLCAxLjAwMDQxLCAwLjk5OTYyLCAxLjAwMDI2LCAxLjAwMDYsIDAuOTk5OTUsIDEuMDAwNDEsIDAuOTk5NDIsIDAuOTk5NzMsIDAuOTk5MjcsIDEuMDAwODIsIDAuOTk5MDIsIDEuMDAwMjYsIDEuMDAwODcsIDEuMDAwNiwgMS4wMDA2OSwgMC45OTk3MywgMC45OTg2NywgMC45OTk3MywgMC45OTkzLCAxLjAwMDI2LCAxLjAwMDQ5LCAxLjAwMDU2LCAxLCAwLjk5OTg4LCAwLjk5OTM1LCAwLjk5OTk1LCAwLjk5OTU0LCAxLjAwMDU1LCAwLjk5OTQ1LCAxLjAwMDMyLCAxLjAwMDYsIDAuOTk5OTUsIDEuMDAwMjYsIDAuOTk5OTUsIDEuMDAwMzIsIDEuMDAwMDEsIDEuMDAwMDgsIDAuOTk5NzEsIDEuMDAwMTksIDAuOTk5NCwgMS4wMDAwMSwgMS4wMDA2LCAxLjAwMDQ0LCAwLjk5OTczLCAxLjAwMDIzLCAxLjAwMDQ3LCAxLCAwLjk5OTQyLCAwLjk5NTYxLCAwLjk5OTg5LCAxLjAwMDM1LCAwLjk5OTc3LCAxLjAwMDM1LCAwLjk5OTc3LCAxLjAwMDE5LCAwLjk5OTQ0LCAxLjAwMDAxLCAxLjAwMDIxLCAwLjk5OTI2LCAxLjAwMDM1LCAxLjAwMDM1LCAwLjk5OTQyLCAxLjAwMDQ4LCAwLjk5OTk5LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDM1LCAxLjAwMDAxLCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTg5LCAxLjAwMDU3LCAxLjAwMDAxLCAwLjk5OTM2LCAxLjAwMDUyLCAxLjAwMDEyLCAwLjk5OTk2LCAxLjAwMDQzLCAxLCAxLjAwMDM1LCAwLjk5OTQsIDAuOTk5NzYsIDEuMDAwMzUsIDAuOTk5NzMsIDEuMDAwNTIsIDEuMDAwNDEsIDEuMDAxMTksIDEuMDAwMzcsIDAuOTk5NzMsIDEuMDAwMDIsIDAuOTk5ODYsIDEuMDAwNDEsIDEuMDAwNDEsIDAuOTk5MDIsIDAuOTk5NiwgMS4wMDAzNCwgMC45OTk5OSwgMS4wMDAyNiwgMC45OTk5OSwgMS4wMDAyNiwgMC45OTk3MywgMS4wMDA1MiwgMC45OTk3MywgMSwgMC45OTk3MywgMS4wMDA0MSwgMS4wMDA3NSwgMC45OTk0LCAxLjAwMDMsIDAuOTk5OTksIDEsIDEuMDAwNDEsIDAuOTk5NTUsIDEsIDAuOTk5MTUsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwMjYsIDEuMDAxMTksIDAuOTk5NTUsIDAuOTk5NzMsIDEuMDAwNiwgMC45OTkxMSwgMS4wMDA2LCAxLjAwMDI2LCAwLjk5OTcyLCAxLjAwMDI2LCAwLjk5OTAyLCAxLjAwMDQxLCAwLjk5OTczLCAwLjk5OTk5LCAxLCAxLCAxLjAwMDM4LCAxLjAwMDUsIDEuMDAwMTYsIDEuMDAwMjIsIDEuMDAwMTYsIDEuMDAwMjIsIDEuMDAwMTYsIDEuMDAwMjIsIDEuMDAwMDEsIDAuOTk5NzMsIDEsIDEsIDAuOTk5NzMsIDEsIDEsIDAuOTk5NTUsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMSwgMSwgMSwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MiwgMSwgMSwgMS4wMDEwNiwgMC45OTk5OSwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OSwgMC45OTk5OCwgMS42NjQ3NSwgMSwgMC45OTk3MywgMC45OTk3MywgMS4wMDAyMywgMC45OTk3MywgMC45OTk3MSwgMS4wMDA0NywgMS4wMDAyMywgMSwgMC45OTk5MSwgMC45OTk4NCwgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDAwMiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45OTk3MiwgMSwgMS4yMDk4NSwgMS4zOTcxMywgMS4wMDAwMywgMS4wMDAzMSwgMS4wMDAxNSwgMSwgMC45OTU2MSwgMS4wMDAyNywgMS4wMDAzMSwgMS4wMDAzMSwgMC45OTkxNSwgMS4wMDAzMSwgMS4wMDAzMSwgMC45OTk5OSwgMS4wMDAwMywgMC45OTk5OSwgMC45OTk5OSwgMS40MTE0NCwgMS42LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQwNTc5LCAxLjQwNTc5LCAxLjM2NjI1LCAwLjk5OTk5LCAxLCAwLjk5ODYxLCAwLjk5ODYxLCAxLCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAwLjk5OTcyLCAwLjk5OTk5LCAwLjk5OTk5LCAwLjk5OTk5LCAwLjk5OTk5LCAxLjQwNDgzLCAxLCAwLjk5OTc3LCAxLjAwMDU0LCAxLCAxLCAwLjk5OTUzLCAwLjk5OTYyLCAxLjAwMDQyLCAwLjk5OTUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpleHBvcnRzLkhlbHZldGljYUJvbGRGYWN0b3JzID0gSGVsdmV0aWNhQm9sZEZhY3RvcnM7CmNvbnN0IEhlbHZldGljYUJvbGRNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMiwKICBsaW5lR2FwOiAwLjIKfTsKZXhwb3J0cy5IZWx2ZXRpY2FCb2xkTWV0cmljcyA9IEhlbHZldGljYUJvbGRNZXRyaWNzOwpjb25zdCBIZWx2ZXRpY2FCb2xkSXRhbGljRmFjdG9ycyA9IFswLjc2MTE2LCAxLCAxLCAxLjAwMDYsIDAuOTk5OTgsIDAuOTk5NzQsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5ODIsIDAuOTk5NzcsIDEuMDAwODcsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5NTksIDEuMDAwMDMsIDEuMDAwNiwgMC45OTk5OCwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5OTgsIDEsIDEuMDAwMDMsIDEuMDAwMDMsIDEuMDAwMDMsIDEuMDAwMjYsIDAuOTk5OSwgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAyNiwgMS4wMDAyMiwgMC45OTk3NywgMS4wMDA2LCAwLjk5OTczLCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTk5LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDAxLCAxLjAwMDIyLCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDE2LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDI2LCAwLjk5OTk4LCAxLjAwMDYsIDAuOTk5OTgsIDEuMDAwMDMsIDAuOTk5NzMsIDAuOTk5OTgsIDAuOTk5NzMsIDEuMDAwMjYsIDAuOTk5NzMsIDEuMDAwMjYsIDAuOTk5NzMsIDAuOTk5OTgsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTczLCAxLjAwMDYsIDAuOTk5ODIsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDAuOTk5NTksIDAuOTk5NzMsIDAuOTk5OTgsIDEuMDAwMjYsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDAuOTk5NzMsIDEsIDAuOTk5NTksIDEuMDAwNzcsIDAuOTk5NTksIDEuMDAwMDMsIDAuOTk5OTgsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNzcsIDAuOTk5NzMsIDAuOTk5OTgsIDEuMDAwMjUsIDAuOTk5NjgsIDAuOTk5NzMsIDEuMDAwMDMsIDEuMDAwMjUsIDAuNjAyOTksIDEuMDAwMjQsIDEuMDY0MDksIDEsIDEsIDAuOTk5OTgsIDEsIDAuOTk5NzMsIDEuMDAwNiwgMC45OTk5OCwgMSwgMC45OTkzNiwgMC45OTk3MywgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDAyNiwgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMSwgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTc3LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDIyLCAxLjAwMDIyLCAxLjAwMDIyLCAxLjAwMDIyLCAxLjAwMDAzLCAxLjAwMDIyLCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDI2LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTgyLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDY0MDksIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDAuOTk5NzMsIDEuMDAwMjYsIDAuOTk5NzMsIDAuOTk5NzcsIDAuOTk5NzMsIDAuOTk5NzcsIDAuOTk5NzMsIDAuOTk5NzcsIDAuOTk5NzMsIDAuOTk5NzcsIDAuOTk5NzMsIDAuOTk5NzcsIDAuOTk5NzMsIDAuOTk5NzcsIDAuOTk5NzMsIDAuOTk5NzcsIDAuOTk5NzMsIDAuOTk5NzcsIDEuMDA0NCwgMC45OTk3NywgMS4wMDAyNiwgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAyMiwgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTcxLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDYsIDAuOTk5NzcsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwMjYsIDEuMDAwNiwgMS4wMDAyNiwgMS4wMDA2LCAxLjAwMDI2LCAxLjAxMDExLCAxLjAwMDI2LCAwLjk5OTk5LCAxLjAwMDI2LCAxLjAwMDYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5MywgMC45OTk4LCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLCAxLjAwMDE2LCAwLjk5OTc3LCAwLjk5OTU5LCAwLjk5OTc3LCAwLjk5OTU5LCAwLjk5OTc3LCAwLjk5OTU5LCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTk4LCAxLjAwMDI2LCAwLjgxMjEsIDEuMDAwMjYsIDAuOTk5OTgsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDEuMDAwMTYsIDEuMDAwMjIsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDEuMDAwMjYsIDEsIDEuMDAwMjYsIDEsIDEuMDAwMjYsIDEsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMSwgMC45OTk4MiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk3NywgMSwgMSwgMS4wMDAyNiwgMC45OTk2OSwgMC45OTk3MiwgMC45OTk4MSwgMC45OTk4LCAxLjAwMDYsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMjIsIDAuOTExNTUsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwNiwgMC45OTk3NywgMS4wMDAwMSwgMC45OTk5OSwgMC45OTk3NywgMC45OTk2NiwgMS4wMDAyMiwgMS4wMDAzMiwgMS4wMDAwMSwgMC45OTk0NCwgMS4wMDAyNiwgMS4wMDAwMSwgMC45OTk2OCwgMS4wMDAwMSwgMS4wMDA0NywgMSwgMS4wMDA2LCAxLjAwMDAxLCAwLjk5OTgxLCAxLjAwMTAxLCAxLjAwMDI2LCAxLjAwMDYsIDAuOTk5NDgsIDAuOTk5ODEsIDEuMDAwNjQsIDAuOTk5NzMsIDAuOTk5NDIsIDEuMDAxMDEsIDEuMDAwNjEsIDEuMDAwMjYsIDEuMDAwNjksIDEuMDAwNiwgMS4wMDAxNCwgMC45OTk3MywgMS4wMTMyMiwgMC45OTk3MywgMS4wMDA2NSwgMS4wMDAyNiwgMS4wMDAxMiwgMC45OTkyMywgMSwgMS4wMDA2NCwgMS4wMDA3NiwgMC45OTk0OCwgMS4wMDA1NSwgMS4wMDA2MywgMS4wMDAwNywgMC45OTk0MywgMS4wMDA2LCAwLjk5OTQ4LCAxLjAwMDI2LCAwLjk5OTQ4LCAwLjk5OTQzLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDI5LCAxLjAwMDM4LCAxLjAwMDM1LCAxLjAwMDAxLCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3OCwgMS4wMDAwMSwgMS4wMDA1NywgMC45OTk4OSwgMC45OTk2NywgMC45OTk2NCwgMC45OTk2NywgMC45OTk3NywgMC45OTk5OSwgMC45OTk3NywgMS4wMDAzOCwgMC45OTk3NywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDA2NiwgMC45OTk2NywgMC45OTk2NywgMS4wMDA0MSwgMC45OTk5OCwgMC45OTk5OSwgMC45OTk3NywgMS4wMDAyMiwgMC45OTk2NywgMS4wMDAwMSwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk2NCwgMS4wMDAzMSwgMS4wMDAwMSwgMC45OTk5OSwgMC45OTk5OSwgMSwgMS4wMDAyMywgMSwgMSwgMC45OTk5OSwgMS4wMDAzNSwgMS4wMDAwMSwgMC45OTk5OSwgMC45OTk3MywgMC45OTk3NywgMC45OTk5OSwgMS4wMDA1OCwgMC45OTk3MywgMC45OTk3MywgMC45OTk1NSwgMC45OTk1LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDMyLCAwLjk5OTg5LCAxLjAwMDM0LCAwLjk5OTk5LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAwLjk5OTczLCAwLjQ1OTk4LCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTk5LCAwLjk5OTgyLCAwLjk5OTk0LCAwLjk5OTk2LCAxLCAxLjAwMDQyLCAxLjAwMDQ0LCAxLjAwMDI5LCAxLjAwMDIzLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTQ5LCAxLjAwMDAyLCAwLjk5OTczLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTc1LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDMyLCAwLjk4Njg1LCAwLjk5OTczLCAxLjAwMDI2LCAxLCAxLCAwLjk5OTY2LCAxLjAwMDQ0LCAxLjAwMDE2LCAxLjAwMDIyLCAxLjAwMDE2LCAxLjAwMDIyLCAxLjAwMDE2LCAxLjAwMDIyLCAxLjAwMDAxLCAwLjk5OTczLCAxLCAxLCAwLjk5OTczLCAxLCAxLCAwLjk5OTU1LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEsIDEsIDEsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzIsIDEsIDEsIDEuMDAxMDYsIDAuOTk5OTksIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTksIDAuOTk5OTgsIDEuNjY0NzUsIDEsIDAuOTk5NzMsIDAuOTk5NzMsIDEsIDAuOTk5NzMsIDAuOTk5NzEsIDAuOTk5NzgsIDEsIDEsIDAuOTk5OTEsIDAuOTk5ODQsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwOTgsIDEsIDEsIDEsIDEuMDAwNDksIDEsIDEsIDAuOTk5NzIsIDEsIDEuMjA5ODUsIDEuMzk3MTMsIDEuMDAwMDMsIDEuMDAwMzEsIDEuMDAwMTUsIDEsIDAuOTk1NjEsIDEuMDAwMjcsIDEuMDAwMzEsIDEuMDAwMzEsIDAuOTk5MTUsIDEuMDAwMzEsIDEuMDAwMzEsIDAuOTk5OTksIDEuMDAwMDMsIDAuOTk5OTksIDAuOTk5OTksIDEuNDExNDQsIDEuNiwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MDU3OSwgMS40MDU3OSwgMS4zNjYyNSwgMC45OTk5OSwgMSwgMC45OTg2MSwgMC45OTg2MSwgMSwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMC45OTk3MiwgMC45OTk5OSwgMC45OTk5OSwgMC45OTk5OSwgMC45OTk5OSwgMS40MDQ4MywgMSwgMC45OTk3NywgMS4wMDA1NCwgMSwgMSwgMC45OTk1MywgMC45OTk2MiwgMS4wMDA0MiwgMC45OTk1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKZXhwb3J0cy5IZWx2ZXRpY2FCb2xkSXRhbGljRmFjdG9ycyA9IEhlbHZldGljYUJvbGRJdGFsaWNGYWN0b3JzOwpjb25zdCBIZWx2ZXRpY2FCb2xkSXRhbGljTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjM1LAogIGxpbmVHYXA6IDAuMgp9OwpleHBvcnRzLkhlbHZldGljYUJvbGRJdGFsaWNNZXRyaWNzID0gSGVsdmV0aWNhQm9sZEl0YWxpY01ldHJpY3M7CmNvbnN0IEhlbHZldGljYUl0YWxpY0ZhY3RvcnMgPSBbMC43NjExNiwgMSwgMSwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwMDYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5ODIsIDEuMDAwMDEsIDEuMDAwNDMsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5NTksIDEuMDAwMDMsIDEuMDAwNiwgMC45OTk5OCwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMSwgMS4wMDAwMywgMS4wMDAwMywgMS4wMDAwMywgMC45OTk3MywgMC45OTk4NywgMS4wMDAwMSwgMS4wMDAwMSwgMC45OTk3NywgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAyNiwgMS4wMDAyMiwgMC45OTk3NywgMS4wMDA2LCAxLCAxLjAwMDAxLCAwLjk5OTczLCAwLjk5OTk5LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDAxLCAxLjAwMDIyLCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDE2LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDI2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTQ5LCAwLjk5OTczLCAwLjk5OTk4LCAwLjk5OTczLCAwLjk5OTczLCAxLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5MjQsIDAuOTk5MjQsIDEsIDAuOTk5MjQsIDAuOTk5OTksIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5OTgsIDEsIDEuMDAwNiwgMC45OTk3MywgMSwgMC45OTk3NywgMSwgMSwgMSwgMS4wMDAwNSwgMS4wMDA5LCAxLjAwMDA1LCAxLjAwMDAzLCAwLjk5OTk4LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDksIDAuOTk5NzMsIDAuOTk5OTgsIDEuMDAwMjUsIDAuOTk5NjgsIDAuOTk5NzMsIDEuMDAwMDMsIDEuMDAwMjUsIDAuNjAyOTksIDEuMDAwMjQsIDEuMDY0MDksIDEsIDEsIDAuOTk5OTgsIDEsIDAuOTk5OCwgMS4wMDA2LCAwLjk5OTk4LCAxLCAwLjk5OTM2LCAwLjk5OTczLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDI2LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMDMsIDEuMDAwMjIsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5ODIsIDEsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wNjQwOSwgMS4wMDAyNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMSwgMC45OTk3MywgMSwgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMC45OTk3NywgMSwgMC45OTk3NywgMSwgMC45OTk3NywgMSwgMC45OTk3NywgMSwgMC45OTk3NywgMS4wMjg4LCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5MjQsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTQ2LCAxLjAwMDM0LCAxLCAwLjk5OTI0LCAxLjAwMDAxLCAxLCAxLCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTczLCAxLjA2MzExLCAwLjk5OTczLCAxLjAwMDI0LCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDQxLCAwLjk5OTgsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDEsIDEuMDAwMTYsIDAuOTk5NzcsIDAuOTk5OTgsIDAuOTk5NzcsIDAuOTk5OTgsIDAuOTk5NzcsIDAuOTk5OTgsIDEuMDAwMDEsIDEsIDEuMDAwMDEsIDEsIDEuMDAwMDEsIDEsIDEuMDAwMDEsIDEsIDEuMDAwMjYsIDEuMDAwNiwgMS4wMDAyNiwgMC44OTU0NywgMS4wMDAyNiwgMS4wMDA2LCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDAxLCAxLCAxLjAwMDAxLCAxLjAwMDI2LCAxLCAxLjAwMDI2LCAxLCAxLjAwMDI2LCAxLCAwLjk5OTI0LCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLCAwLjk5OTgyLCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDAxLCAxLCAxLjAwMDI2LCAxLjAwMDYsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDEuMDAwMDEsIDEsIDEuMDAwNTQsIDAuOTk5NzcsIDEuMDAwODQsIDEuMDAwMDcsIDAuOTk5NzMsIDEuMDAwMTMsIDAuOTk5MjQsIDEuMDAwMDEsIDEuMDAwMDEsIDAuOTk5NDUsIDAuOTEyMjEsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwNiwgMS4wMDAwMSwgMS4wMDAwMSwgMC45OTk5OSwgMC45OTk3NywgMC45OTkzMywgMS4wMDAyMiwgMS4wMDA1NCwgMS4wMDAwMSwgMS4wMDA2NSwgMS4wMDAyNiwgMS4wMDAwMSwgMS4wMDAxLCAxLjAwMDAxLCAxLjAwMDUyLCAxLCAxLjAwMDYsIDEuMDAwMDEsIDAuOTk5NDUsIDAuOTk4OTcsIDAuOTk5NjgsIDAuOTk5MjQsIDEuMDAwMzYsIDAuOTk5NDUsIDAuOTk5NDksIDEsIDEuMDAwNiwgMC45OTg5NywgMC45OTkxOCwgMC45OTk2OCwgMC45OTkxMSwgMC45OTkyNCwgMSwgMC45OTk2MiwgMS4wMTQ4NywgMSwgMS4wMDA1LCAwLjk5OTczLCAxLjAwMDEyLCAxLjAwMDQzLCAxLCAwLjk5OTk1LCAwLjk5OTk0LCAxLjAwMDM2LCAwLjk5OTQ3LCAxLjAwMDE5LCAxLjAwMDYzLCAxLjAwMDI1LCAwLjk5OTI0LCAxLjAwMDM2LCAwLjk5OTczLCAxLjAwMDM2LCAxLjAwMDI1LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDI3LCAxLjAwMDEsIDEuMDAwNjgsIDEuMDAwMDEsIDEuMDAwNiwgMS4wMDA2LCAxLCAxLjAwMDA4LCAwLjk5OTU3LCAwLjk5OTcyLCAwLjk5OTQsIDAuOTk5NTQsIDAuOTk5NzUsIDEuMDAwNTEsIDEuMDAwMDEsIDEuMDAwMTksIDEuMDAwMDEsIDEuMDAwMSwgMC45OTk4NiwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAzOCwgMC45OTk1NCwgMC45OTk1NCwgMC45OTk0LCAxLjAwMDY2LCAwLjk5OTk5LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDU0LCAxLjAwMDAxLCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTc1LCAxLjAwMDEsIDEuMDAwMDEsIDAuOTk5OTMsIDAuOTk5NSwgMC45OTk1NSwgMS4wMDAxNiwgMC45OTk3OCwgMC45OTk3NCwgMS4wMDAxOSwgMS4wMDAyMiwgMC45OTk1NSwgMS4wMDA1MywgMC45OTk3MywgMS4wMDA4OSwgMS4wMDAwNSwgMC45OTk2NywgMS4wMDA0OCwgMC45OTk3MywgMS4wMDAwMiwgMS4wMDAzNCwgMC45OTk3MywgMC45OTk3MywgMC45OTk2NCwgMS4wMDAwNiwgMS4wMDA2NiwgMC45OTk0NywgMC45OTk3MywgMC45ODg5NCwgMC45OTk3MywgMSwgMC40NDg5OCwgMSwgMC45OTk0NiwgMSwgMS4wMDAzOSwgMS4wMDA4MiwgMC45OTk5MSwgMC45OTk5MSwgMC45OTk4NSwgMS4wMDAyMiwgMS4wMDAyMywgMS4wMDA2MSwgMS4wMDAwNiwgMC45OTk2NiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wMDAxOSwgMS4wMDA4LCAxLCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTgzLCAxLjAwMDQ0LCAwLjk5OTczLCAwLjk5OTY0LCAwLjk4MzMyLCAxLCAwLjk5OTczLCAxLCAxLCAwLjk5OTYyLCAwLjk5ODk1LCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDAxLCAxLCAxLCAxLCAwLjk5OTczLCAxLCAxLCAwLjk5OTU1LCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTcyLCAxLCAxLCAxLjAwMjY3LCAwLjk5OTk5LCAwLjk5OTk4LCAwLjk5OTk4LCAxLCAwLjk5OTk4LCAxLjY2NDc1LCAxLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDIzLCAwLjk5OTczLCAxLjAwNDIzLCAwLjk5OTI1LCAwLjk5OTk5LCAxLCAwLjk5OTkxLCAwLjk5OTg0LCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDQ5LCAxLCAxLjAwMjQ1LCAxLCAxLCAxLCAxLCAwLjk2MzI5LCAxLCAxLjIwOTg1LCAxLjM5NzEzLCAxLjAwMDAzLCAwLjgyNTQsIDEuMDAwMTUsIDEsIDEuMDAwMzUsIDEuMDAwMjcsIDEuMDAwMzEsIDEuMDAwMzEsIDEuMDAwMDMsIDEuMDAwMzEsIDEuMDAwMzEsIDAuOTk5OTksIDEuMDAwMDMsIDAuOTk5OTksIDAuOTk5OTksIDEuNDExNDQsIDEuNiwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MDU3OSwgMS40MDU3OSwgMS4zNjYyNSwgMC45OTk5OSwgMSwgMC45OTg2MSwgMC45OTg2MSwgMSwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMC45NTMxNywgMC45OTk5OSwgMC45OTk5OSwgMC45OTk5OSwgMC45OTk5OSwgMS40MDQ4MywgMSwgMC45OTk3NywgMS4wMDA1NCwgMSwgMSwgMC45OTk1MywgMC45OTk2MiwgMS4wMDA0MiwgMC45OTk1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKZXhwb3J0cy5IZWx2ZXRpY2FJdGFsaWNGYWN0b3JzID0gSGVsdmV0aWNhSXRhbGljRmFjdG9yczsKY29uc3QgSGVsdmV0aWNhSXRhbGljTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjM1LAogIGxpbmVHYXA6IDAuMgp9OwpleHBvcnRzLkhlbHZldGljYUl0YWxpY01ldHJpY3MgPSBIZWx2ZXRpY2FJdGFsaWNNZXRyaWNzOwpjb25zdCBIZWx2ZXRpY2FSZWd1bGFyRmFjdG9ycyA9IFswLjc2MTE2LCAxLCAxLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDAwNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk4MiwgMS4wMDAwMSwgMS4wMDA0MywgMC45OTk5OCwgMC45OTk5OCwgMC45OTk1OSwgMS4wMDAwMywgMS4wMDA2LCAwLjk5OTk4LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wMDA2LCAxLCAxLjAwMDAzLCAxLjAwMDAzLCAxLjAwMDAzLCAwLjk5OTczLCAwLjk5OTg3LCAxLjAwMDAxLCAxLjAwMDAxLCAwLjk5OTc3LCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDI2LCAxLjAwMDIyLCAwLjk5OTc3LCAxLjAwMDYsIDEsIDEuMDAwMDEsIDAuOTk5NzMsIDAuOTk5OTksIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMDEsIDEuMDAwMjIsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMTYsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMjYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NDksIDAuOTk5NzMsIDAuOTk5OTgsIDAuOTk5NzMsIDAuOTk5NzMsIDEsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3MywgMC45OTkyNCwgMC45OTkyNCwgMSwgMC45OTkyNCwgMC45OTk5OSwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk5OCwgMSwgMS4wMDA2LCAwLjk5OTczLCAxLCAwLjk5OTc3LCAxLCAxLCAxLCAxLjAwMDA1LCAxLjAwMDksIDEuMDAwMDUsIDEuMDAwMDMsIDAuOTk5OTgsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwOSwgMC45OTk3MywgMC45OTk5OCwgMS4wMDAyNSwgMC45OTk2OCwgMC45OTk3MywgMS4wMDAwMywgMS4wMDAyNSwgMC42MDI5OSwgMS4wMDAyNCwgMS4wNjQwOSwgMSwgMSwgMC45OTk5OCwgMSwgMC45OTk4LCAxLjAwMDYsIDAuOTk5OTgsIDEsIDAuOTk5MzYsIDAuOTk5NzMsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMjYsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3NywgMC45OTk3NywgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAyMiwgMS4wMDAwMywgMS4wMDAyMiwgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAyNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk4MiwgMSwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLjA2NDA5LCAxLjAwMDI2LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLCAwLjk5OTczLCAxLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAwLjk5OTc3LCAxLCAwLjk5OTc3LCAxLCAwLjk5OTc3LCAxLCAwLjk5OTc3LCAxLCAwLjk5OTc3LCAxLjA0NTk2LCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5MjQsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDE5LCAxLjAwMDM0LCAxLCAwLjk5OTI0LCAxLjAwMDAxLCAxLCAxLCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTczLCAxLjAyNTcyLCAwLjk5OTczLCAxLjAwMDA1LCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTk5LCAwLjk5OTgsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDEuMDAwMjIsIDAuOTk5NzMsIDEsIDEuMDAwMTYsIDAuOTk5NzcsIDAuOTk5OTgsIDAuOTk5NzcsIDAuOTk5OTgsIDAuOTk5NzcsIDAuOTk5OTgsIDEuMDAwMDEsIDEsIDEuMDAwMDEsIDEsIDEuMDAwMDEsIDEsIDEuMDAwMDEsIDEsIDEuMDAwMjYsIDEuMDAwNiwgMS4wMDAyNiwgMC44NDUzMywgMS4wMDAyNiwgMS4wMDA2LCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDAxLCAxLCAxLjAwMDAxLCAxLjAwMDI2LCAxLCAxLjAwMDI2LCAxLCAxLjAwMDI2LCAxLCAwLjk5OTI0LCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLCAwLjk5OTgyLCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDAxLCAxLCAxLjAwMDI2LCAxLjAwMDYsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5MjgsIDEsIDAuOTk5NzcsIDEuMDAwMTMsIDEuMDAwNTUsIDAuOTk5NDcsIDAuOTk5NDUsIDAuOTk5NDEsIDAuOTk5MjQsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwNCwgMC45MTYyMSwgMS4wMDAwMSwgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyMiwgMS4wMDA2LCAxLjAwMDAxLCAxLjAwMDA1LCAwLjk5OTk5LCAwLjk5OTc3LCAxLjAwMDE1LCAxLjAwMDIyLCAwLjk5OTc3LCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDI2LCAxLjAwMDAxLCAxLjAwMDE5LCAxLjAwMDAxLCAwLjk5OTQ2LCAxLCAxLjAwMDYsIDEuMDAwMDEsIDAuOTk5NzgsIDEuMDAwNDUsIDAuOTk5NzMsIDAuOTk5MjQsIDEuMDAwMjMsIDAuOTk5NzgsIDAuOTk5NjYsIDEsIDEuMDAwNjUsIDEuMDAwNDUsIDEuMDAwMTksIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5MjQsIDEsIDEsIDAuOTY0OTksIDEsIDEuMDAwNTUsIDAuOTk5NzMsIDEuMDAwMDgsIDEuMDAwMjcsIDEsIDAuOTk5NywgMC45OTk5NSwgMS4wMDAyMywgMC45OTkzMywgMS4wMDAxOSwgMS4wMDAxNSwgMS4wMDAzMSwgMC45OTkyNCwgMS4wMDAyMywgMC45OTk3MywgMS4wMDAyMywgMS4wMDAzMSwgMS4wMDAwMSwgMC45OTkyOCwgMS4wMDAyOSwgMS4wMDA5MiwgMS4wMDAzNSwgMS4wMDAwMSwgMS4wMDA2LCAxLjAwMDYsIDEsIDAuOTk5ODgsIDAuOTk5NzUsIDEsIDEuMDAwODIsIDAuOTk1NjEsIDAuOTk5NiwgMS4wMDAzNSwgMS4wMDAwMSwgMC45OTk2MiwgMS4wMDAwMSwgMS4wMDA5MiwgMC45OTk2NCwgMS4wMDAwMSwgMC45OTk2MywgMC45OTk5OSwgMS4wMDAzNSwgMS4wMDAzNSwgMS4wMDA4MiwgMC45OTk2MiwgMC45OTk5OSwgMC45OTk3NywgMS4wMDAyMiwgMS4wMDAzNSwgMS4wMDAwMSwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk2LCAwLjk5OTY3LCAxLjAwMDAxLCAxLjAwMDM0LCAxLjAwMDc0LCAxLjAwMDU0LCAxLjAwMDUzLCAxLjAwMDYzLCAwLjk5OTcxLCAwLjk5OTYyLCAxLjAwMDM1LCAwLjk5OTc1LCAwLjk5OTc3LCAwLjk5OTczLCAxLjAwMDQzLCAwLjk5OTUzLCAxLjAwMDcsIDAuOTk5MTUsIDAuOTk5NzMsIDEuMDAwMDgsIDAuOTk4OTIsIDEuMDAwNzMsIDEuMDAwNzMsIDEuMDAxMTQsIDAuOTk5MTUsIDEuMDAwNzMsIDAuOTk5NTUsIDAuOTk5NzMsIDEuMDAwOTIsIDAuOTk5NzMsIDEsIDAuOTk5OTgsIDEsIDEuMDAwMywgMSwgMS4wMDA0MywgMS4wMDAwMSwgMC45OTk2OSwgMS4wMDAzLCAxLCAxLjAwMDM1LCAxLjAwMDAxLCAwLjk5OTUsIDEsIDEuMDAwOTIsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNywgMC45OTk1LCAxLCAwLjk5OTI0LCAxLjAwMDYsIDAuOTk5MjQsIDAuOTk5NzIsIDEuMDAwNjIsIDAuOTk5NzMsIDEuMDAxMTQsIDEuMDAwNzMsIDEsIDAuOTk5NTUsIDEsIDEsIDEuMDAwNDcsIDAuOTk5NjgsIDEuMDAwMTYsIDAuOTk5NzcsIDEuMDAwMTYsIDAuOTk5NzcsIDEuMDAwMTYsIDAuOTk5NzcsIDEuMDAwMDEsIDEsIDEsIDEsIDAuOTk5NzMsIDEsIDEsIDAuOTk5NTUsIDAuOTk5MjQsIDAuOTk5MjQsIDAuOTk5MjQsIDAuOTk5MjQsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzIsIDEsIDEsIDEuMDAyNjcsIDAuOTk5OTksIDAuOTk5OTgsIDAuOTk5OTgsIDEsIDAuOTk5OTgsIDEuNjY0NzUsIDEsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwMjMsIDAuOTk5NzMsIDAuOTk5NzEsIDAuOTk5MjUsIDEuMDAwMjMsIDEsIDAuOTk5OTEsIDAuOTk5ODQsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMDIsIDEuMDAwMDIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTYzMjksIDEsIDEuMjA5ODUsIDEuMzk3MTMsIDEuMDAwMDMsIDAuODI1NCwgMS4wMDAxNSwgMSwgMS4wMDAzNSwgMS4wMDAyNywgMS4wMDAzMSwgMS4wMDAzMSwgMC45OTkxNSwgMS4wMDAzMSwgMS4wMDAzMSwgMC45OTk5OSwgMS4wMDAwMywgMC45OTk5OSwgMC45OTk5OSwgMS40MTE0NCwgMS42LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQwNTc5LCAxLjQwNTc5LCAxLjM2NjI1LCAwLjk5OTk5LCAxLCAwLjk5ODYxLCAwLjk5ODYxLCAxLCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAwLjk1MzE3LCAwLjk5OTk5LCAwLjk5OTk5LCAwLjk5OTk5LCAwLjk5OTk5LCAxLjQwNDgzLCAxLCAwLjk5OTc3LCAxLjAwMDU0LCAxLCAxLCAwLjk5OTUzLCAwLjk5OTYyLCAxLjAwMDQyLCAwLjk5OTUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpleHBvcnRzLkhlbHZldGljYVJlZ3VsYXJGYWN0b3JzID0gSGVsdmV0aWNhUmVndWxhckZhY3RvcnM7CmNvbnN0IEhlbHZldGljYVJlZ3VsYXJNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMiwKICBsaW5lR2FwOiAwLjIKfTsKZXhwb3J0cy5IZWx2ZXRpY2FSZWd1bGFyTWV0cmljcyA9IEhlbHZldGljYVJlZ3VsYXJNZXRyaWNzOwoKLyoqKi8gfSksCi8qIDE4OSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuTGliZXJhdGlvblNhbnNSZWd1bGFyV2lkdGhzID0gZXhwb3J0cy5MaWJlcmF0aW9uU2Fuc1JlZ3VsYXJNYXBwaW5nID0gZXhwb3J0cy5MaWJlcmF0aW9uU2Fuc0l0YWxpY1dpZHRocyA9IGV4cG9ydHMuTGliZXJhdGlvblNhbnNJdGFsaWNNYXBwaW5nID0gZXhwb3J0cy5MaWJlcmF0aW9uU2Fuc0JvbGRXaWR0aHMgPSBleHBvcnRzLkxpYmVyYXRpb25TYW5zQm9sZE1hcHBpbmcgPSBleHBvcnRzLkxpYmVyYXRpb25TYW5zQm9sZEl0YWxpY1dpZHRocyA9IGV4cG9ydHMuTGliZXJhdGlvblNhbnNCb2xkSXRhbGljTWFwcGluZyA9IHZvaWQgMDsKY29uc3QgTGliZXJhdGlvblNhbnNCb2xkV2lkdGhzID0gWzM2NSwgMCwgMzMzLCAyNzgsIDMzMywgNDc0LCA1NTYsIDU1NiwgODg5LCA3MjIsIDIzOCwgMzMzLCAzMzMsIDM4OSwgNTg0LCAyNzgsIDMzMywgMjc4LCAyNzgsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMzMzLCAzMzMsIDU4NCwgNTg0LCA1ODQsIDYxMSwgOTc1LCA3MjIsIDcyMiwgNzIyLCA3MjIsIDY2NywgNjExLCA3NzgsIDcyMiwgMjc4LCA1NTYsIDcyMiwgNjExLCA4MzMsIDcyMiwgNzc4LCA2NjcsIDc3OCwgNzIyLCA2NjcsIDYxMSwgNzIyLCA2NjcsIDk0NCwgNjY3LCA2NjcsIDYxMSwgMzMzLCAyNzgsIDMzMywgNTg0LCA1NTYsIDMzMywgNTU2LCA2MTEsIDU1NiwgNjExLCA1NTYsIDMzMywgNjExLCA2MTEsIDI3OCwgMjc4LCA1NTYsIDI3OCwgODg5LCA2MTEsIDYxMSwgNjExLCA2MTEsIDM4OSwgNTU2LCAzMzMsIDYxMSwgNTU2LCA3NzgsIDU1NiwgNTU2LCA1MDAsIDM4OSwgMjgwLCAzODksIDU4NCwgMzMzLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDI4MCwgNTU2LCAzMzMsIDczNywgMzcwLCA1NTYsIDU4NCwgNzM3LCA1NTIsIDQwMCwgNTQ5LCAzMzMsIDMzMywgMzMzLCA1NzYsIDU1NiwgMjc4LCAzMzMsIDMzMywgMzY1LCA1NTYsIDgzNCwgODM0LCA4MzQsIDYxMSwgNzIyLCA3MjIsIDcyMiwgNzIyLCA3MjIsIDcyMiwgMTAwMCwgNzIyLCA2NjcsIDY2NywgNjY3LCA2NjcsIDI3OCwgMjc4LCAyNzgsIDI3OCwgNzIyLCA3MjIsIDc3OCwgNzc4LCA3NzgsIDc3OCwgNzc4LCA1ODQsIDc3OCwgNzIyLCA3MjIsIDcyMiwgNzIyLCA2NjcsIDY2NywgNjExLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA4ODksIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDYxMSwgNjExLCA2MTEsIDYxMSwgNjExLCA2MTEsIDYxMSwgNTQ5LCA2MTEsIDYxMSwgNjExLCA2MTEsIDYxMSwgNTU2LCA2MTEsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNzE5LCA3MjIsIDYxMSwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA3NzgsIDYxMSwgNzc4LCA2MTEsIDc3OCwgNjExLCA3NzgsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDc4NSwgNTU2LCA1NTYsIDI3OCwgNzIyLCA1NTYsIDU1NiwgNjExLCAyNzgsIDYxMSwgMjc4LCA2MTEsIDM4NSwgNjExLCA0NzksIDYxMSwgMjc4LCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA3MDgsIDcyMywgNjExLCA3NzgsIDYxMSwgNzc4LCA2MTEsIDc3OCwgNjExLCAxMDAwLCA5NDQsIDcyMiwgMzg5LCA3MjIsIDM4OSwgNzIyLCAzODksIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2MTEsIDMzMywgNjExLCA0NzksIDYxMSwgMzMzLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA5NDQsIDc3OCwgNjY3LCA1NTYsIDY2NywgNjExLCA1MDAsIDYxMSwgNTAwLCA2MTEsIDUwMCwgMjc4LCA1NTYsIDcyMiwgNTU2LCAxMDAwLCA4ODksIDc3OCwgNjExLCA2NjcsIDU1NiwgNjExLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgNDY1LCA3MjIsIDMzMywgODUzLCA5MDYsIDQ3NCwgODI1LCA5MjcsIDgzOCwgMjc4LCA3MjIsIDcyMiwgNjAxLCA3MTksIDY2NywgNjExLCA3MjIsIDc3OCwgMjc4LCA3MjIsIDY2NywgODMzLCA3MjIsIDY0NCwgNzc4LCA3MjIsIDY2NywgNjAwLCA2MTEsIDY2NywgODIxLCA2NjcsIDgwOSwgODAyLCAyNzgsIDY2NywgNjE1LCA0NTEsIDYxMSwgMjc4LCA1ODIsIDYxNSwgNjEwLCA1NTYsIDYwNiwgNDc1LCA0NjAsIDYxMSwgNTQxLCAyNzgsIDU1OCwgNTU2LCA2MTIsIDU1NiwgNDQ1LCA2MTEsIDc2NiwgNjE5LCA1MjAsIDY4NCwgNDQ2LCA1ODIsIDcxNSwgNTc2LCA3NTMsIDg0NSwgMjc4LCA1ODIsIDYxMSwgNTgyLCA4NDUsIDY2NywgNjY5LCA4ODUsIDU2NywgNzExLCA2NjcsIDI3OCwgMjc2LCA1NTYsIDEwOTQsIDEwNjIsIDg3NSwgNjEwLCA3MjIsIDYyMiwgNzE5LCA3MjIsIDcxOSwgNzIyLCA1NjcsIDcxMiwgNjY3LCA5MDQsIDYyNiwgNzE5LCA3MTksIDYxMCwgNzAyLCA4MzMsIDcyMiwgNzc4LCA3MTksIDY2NywgNzIyLCA2MTEsIDYyMiwgODU0LCA2NjcsIDczMCwgNzAzLCAxMDA1LCAxMDE5LCA4NzAsIDk3OSwgNzE5LCA3MTEsIDEwMzEsIDcxOSwgNTU2LCA2MTgsIDYxNSwgNDE3LCA2MzUsIDU1NiwgNzA5LCA0OTcsIDYxNSwgNjE1LCA1MDAsIDYzNSwgNzQwLCA2MDQsIDYxMSwgNjA0LCA2MTEsIDU1NiwgNDkwLCA1NTYsIDg3NSwgNTU2LCA2MTUsIDU4MSwgODMzLCA4NDQsIDcyOSwgODU0LCA2MTUsIDU1MiwgODU0LCA1ODMsIDU1NiwgNTU2LCA2MTEsIDQxNywgNTUyLCA1NTYsIDI3OCwgMjgxLCAyNzgsIDk2OSwgOTA2LCA2MTEsIDUwMCwgNjE1LCA1NTYsIDYwNCwgNzc4LCA2MTEsIDQ4NywgNDQ3LCA5NDQsIDc3OCwgOTQ0LCA3NzgsIDk0NCwgNzc4LCA2NjcsIDU1NiwgMzMzLCAzMzMsIDU1NiwgMTAwMCwgMTAwMCwgNTUyLCAyNzgsIDI3OCwgMjc4LCAyNzgsIDUwMCwgNTAwLCA1MDAsIDU1NiwgNTU2LCAzNTAsIDEwMDAsIDEwMDAsIDI0MCwgNDc5LCAzMzMsIDMzMywgNjA0LCAzMzMsIDE2NywgMzk2LCA1NTYsIDU1NiwgMTA5NCwgNTU2LCA4ODUsIDQ4OSwgMTExNSwgMTAwMCwgNzY4LCA2MDAsIDgzNCwgODM0LCA4MzQsIDgzNCwgMTAwMCwgNTAwLCAxMDAwLCA1MDAsIDEwMDAsIDUwMCwgNTAwLCA0OTQsIDYxMiwgODIzLCA3MTMsIDU4NCwgNTQ5LCA3MTMsIDk3OSwgNzIyLCAyNzQsIDU0OSwgNTQ5LCA1ODMsIDU0OSwgNTQ5LCA2MDQsIDU4NCwgNjA0LCA2MDQsIDcwOCwgNjI1LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MjksIDYwNCwgNjA0LCAzNTQsIDM1NCwgMTAwMCwgOTkwLCA5OTAsIDk5MCwgOTkwLCA0OTQsIDYwNCwgNjA0LCA2MDQsIDYwNCwgMzU0LCAxMDIxLCAxMDUyLCA5MTcsIDc1MCwgNzUwLCA1MzEsIDY1NiwgNTk0LCA1MTAsIDUwMCwgNzUwLCA3NTAsIDYxMSwgNjExLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMjIyLCAyMjIsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzXTsKZXhwb3J0cy5MaWJlcmF0aW9uU2Fuc0JvbGRXaWR0aHMgPSBMaWJlcmF0aW9uU2Fuc0JvbGRXaWR0aHM7CmNvbnN0IExpYmVyYXRpb25TYW5zQm9sZE1hcHBpbmcgPSBbLTEsIC0xLCAtMSwgMzIsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCwgNDEsIDQyLCA0MywgNDQsIDQ1LCA0NiwgNDcsIDQ4LCA0OSwgNTAsIDUxLCA1MiwgNTMsIDU0LCA1NSwgNTYsIDU3LCA1OCwgNTksIDYwLCA2MSwgNjIsIDYzLCA2NCwgNjUsIDY2LCA2NywgNjgsIDY5LCA3MCwgNzEsIDcyLCA3MywgNzQsIDc1LCA3NiwgNzcsIDc4LCA3OSwgODAsIDgxLCA4MiwgODMsIDg0LCA4NSwgODYsIDg3LCA4OCwgODksIDkwLCA5MSwgOTIsIDkzLCA5NCwgOTUsIDk2LCA5NywgOTgsIDk5LCAxMDAsIDEwMSwgMTAyLCAxMDMsIDEwNCwgMTA1LCAxMDYsIDEwNywgMTA4LCAxMDksIDExMCwgMTExLCAxMTIsIDExMywgMTE0LCAxMTUsIDExNiwgMTE3LCAxMTgsIDExOSwgMTIwLCAxMjEsIDEyMiwgMTIzLCAxMjQsIDEyNSwgMTI2LCAxNjEsIDE2MiwgMTYzLCAxNjQsIDE2NSwgMTY2LCAxNjcsIDE2OCwgMTY5LCAxNzAsIDE3MSwgMTcyLCAxNzQsIDE3NSwgMTc2LCAxNzcsIDE3OCwgMTc5LCAxODAsIDE4MSwgMTgyLCAxODMsIDE4NCwgMTg1LCAxODYsIDE4NywgMTg4LCAxODksIDE5MCwgMTkxLCAxOTIsIDE5MywgMTk0LCAxOTUsIDE5NiwgMTk3LCAxOTgsIDE5OSwgMjAwLCAyMDEsIDIwMiwgMjAzLCAyMDQsIDIwNSwgMjA2LCAyMDcsIDIwOCwgMjA5LCAyMTAsIDIxMSwgMjEyLCAyMTMsIDIxNCwgMjE1LCAyMTYsIDIxNywgMjE4LCAyMTksIDIyMCwgMjIxLCAyMjIsIDIyMywgMjI0LCAyMjUsIDIyNiwgMjI3LCAyMjgsIDIyOSwgMjMwLCAyMzEsIDIzMiwgMjMzLCAyMzQsIDIzNSwgMjM2LCAyMzcsIDIzOCwgMjM5LCAyNDAsIDI0MSwgMjQyLCAyNDMsIDI0NCwgMjQ1LCAyNDYsIDI0NywgMjQ4LCAyNDksIDI1MCwgMjUxLCAyNTIsIDI1MywgMjU0LCAyNTUsIDI1NiwgMjU3LCAyNTgsIDI1OSwgMjYwLCAyNjEsIDI2MiwgMjYzLCAyNjQsIDI2NSwgMjY2LCAyNjcsIDI2OCwgMjY5LCAyNzAsIDI3MSwgMjcyLCAyNzMsIDI3NCwgMjc1LCAyNzYsIDI3NywgMjc4LCAyNzksIDI4MCwgMjgxLCAyODIsIDI4MywgMjg0LCAyODUsIDI4NiwgMjg3LCAyODgsIDI4OSwgMjkwLCAyOTEsIDI5MiwgMjkzLCAyOTQsIDI5NSwgMjk2LCAyOTcsIDI5OCwgMjk5LCAzMDAsIDMwMSwgMzAyLCAzMDMsIDMwNCwgMzA1LCAzMDYsIDMwNywgMzA4LCAzMDksIDMxMCwgMzExLCAzMTIsIDMxMywgMzE0LCAzMTUsIDMxNiwgMzE3LCAzMTgsIDMxOSwgMzIwLCAzMjEsIDMyMiwgMzIzLCAzMjQsIDMyNSwgMzI2LCAzMjcsIDMyOCwgMzI5LCAzMzAsIDMzMSwgMzMyLCAzMzMsIDMzNCwgMzM1LCAzMzYsIDMzNywgMzM4LCAzMzksIDM0MCwgMzQxLCAzNDIsIDM0MywgMzQ0LCAzNDUsIDM0NiwgMzQ3LCAzNDgsIDM0OSwgMzUwLCAzNTEsIDM1MiwgMzUzLCAzNTQsIDM1NSwgMzU2LCAzNTcsIDM1OCwgMzU5LCAzNjAsIDM2MSwgMzYyLCAzNjMsIDM2NCwgMzY1LCAzNjYsIDM2NywgMzY4LCAzNjksIDM3MCwgMzcxLCAzNzIsIDM3MywgMzc0LCAzNzUsIDM3NiwgMzc3LCAzNzgsIDM3OSwgMzgwLCAzODEsIDM4MiwgMzgzLCA0MDIsIDUwNiwgNTA3LCA1MDgsIDUwOSwgNTEwLCA1MTEsIDUzNiwgNTM3LCA1MzgsIDUzOSwgNzEwLCA3MTEsIDcxMywgNzI4LCA3MjksIDczMCwgNzMxLCA3MzIsIDczMywgOTAwLCA5MDEsIDkwMiwgOTAzLCA5MDQsIDkwNSwgOTA2LCA5MDgsIDkxMCwgOTExLCA5MTIsIDkxMywgOTE0LCA5MTUsIDkxNiwgOTE3LCA5MTgsIDkxOSwgOTIwLCA5MjEsIDkyMiwgOTIzLCA5MjQsIDkyNSwgOTI2LCA5MjcsIDkyOCwgOTI5LCA5MzEsIDkzMiwgOTMzLCA5MzQsIDkzNSwgOTM2LCA5MzcsIDkzOCwgOTM5LCA5NDAsIDk0MSwgOTQyLCA5NDMsIDk0NCwgOTQ1LCA5NDYsIDk0NywgOTQ4LCA5NDksIDk1MCwgOTUxLCA5NTIsIDk1MywgOTU0LCA5NTUsIDk1NiwgOTU3LCA5NTgsIDk1OSwgOTYwLCA5NjEsIDk2MiwgOTYzLCA5NjQsIDk2NSwgOTY2LCA5NjcsIDk2OCwgOTY5LCA5NzAsIDk3MSwgOTcyLCA5NzMsIDk3NCwgMTAyNCwgMTAyNSwgMTAyNiwgMTAyNywgMTAyOCwgMTAyOSwgMTAzMCwgMTAzMSwgMTAzMiwgMTAzMywgMTAzNCwgMTAzNSwgMTAzNiwgMTAzNywgMTAzOCwgMTAzOSwgMTA0MCwgMTA0MSwgMTA0MiwgMTA0MywgMTA0NCwgMTA0NSwgMTA0NiwgMTA0NywgMTA0OCwgMTA0OSwgMTA1MCwgMTA1MSwgMTA1MiwgMTA1MywgMTA1NCwgMTA1NSwgMTA1NiwgMTA1NywgMTA1OCwgMTA1OSwgMTA2MCwgMTA2MSwgMTA2MiwgMTA2MywgMTA2NCwgMTA2NSwgMTA2NiwgMTA2NywgMTA2OCwgMTA2OSwgMTA3MCwgMTA3MSwgMTA3MiwgMTA3MywgMTA3NCwgMTA3NSwgMTA3NiwgMTA3NywgMTA3OCwgMTA3OSwgMTA4MCwgMTA4MSwgMTA4MiwgMTA4MywgMTA4NCwgMTA4NSwgMTA4NiwgMTA4NywgMTA4OCwgMTA4OSwgMTA5MCwgMTA5MSwgMTA5MiwgMTA5MywgMTA5NCwgMTA5NSwgMTA5NiwgMTA5NywgMTA5OCwgMTA5OSwgMTEwMCwgMTEwMSwgMTEwMiwgMTEwMywgMTEwNCwgMTEwNSwgMTEwNiwgMTEwNywgMTEwOCwgMTEwOSwgMTExMCwgMTExMSwgMTExMiwgMTExMywgMTExNCwgMTExNSwgMTExNiwgMTExNywgMTExOCwgMTExOSwgMTEzOCwgMTEzOSwgMTE2OCwgMTE2OSwgNzgwOCwgNzgwOSwgNzgxMCwgNzgxMSwgNzgxMiwgNzgxMywgNzkyMiwgNzkyMywgODIwOCwgODIwOSwgODIxMSwgODIxMiwgODIxMywgODIxNSwgODIxNiwgODIxNywgODIxOCwgODIxOSwgODIyMCwgODIyMSwgODIyMiwgODIyNCwgODIyNSwgODIyNiwgODIzMCwgODI0MCwgODI0MiwgODI0MywgODI0OSwgODI1MCwgODI1MiwgODI1NCwgODI2MCwgODMxOSwgODM1NSwgODM1NiwgODM1OSwgODM2NCwgODQ1MywgODQ2NywgODQ3MCwgODQ4MiwgODQ4NiwgODQ5NCwgODUzOSwgODU0MCwgODU0MSwgODU0MiwgODU5MiwgODU5MywgODU5NCwgODU5NSwgODU5NiwgODU5NywgODYxNiwgODcwNiwgODcxMCwgODcxOSwgODcyMSwgODcyMiwgODczMCwgODczNCwgODczNSwgODc0NSwgODc0NywgODc3NiwgODgwMCwgODgwMSwgODgwNCwgODgwNSwgODk2MiwgODk3NiwgODk5MiwgODk5MywgOTQ3MiwgOTQ3NCwgOTQ4NCwgOTQ4OCwgOTQ5MiwgOTQ5NiwgOTUwMCwgOTUwOCwgOTUxNiwgOTUyNCwgOTUzMiwgOTU1MiwgOTU1MywgOTU1NCwgOTU1NSwgOTU1NiwgOTU1NywgOTU1OCwgOTU1OSwgOTU2MCwgOTU2MSwgOTU2MiwgOTU2MywgOTU2NCwgOTU2NSwgOTU2NiwgOTU2NywgOTU2OCwgOTU2OSwgOTU3MCwgOTU3MSwgOTU3MiwgOTU3MywgOTU3NCwgOTU3NSwgOTU3NiwgOTU3NywgOTU3OCwgOTU3OSwgOTU4MCwgOTYwMCwgOTYwNCwgOTYwOCwgOTYxMiwgOTYxNiwgOTYxNywgOTYxOCwgOTYxOSwgOTYzMiwgOTYzMywgOTY0MiwgOTY0MywgOTY0NCwgOTY1MCwgOTY1OCwgOTY2MCwgOTY2OCwgOTY3NCwgOTY3NSwgOTY3OSwgOTY4OCwgOTY4OSwgOTcwMiwgOTc4NiwgOTc4NywgOTc4OCwgOTc5MiwgOTc5NCwgOTgyNCwgOTgyNywgOTgyOSwgOTgzMCwgOTgzNCwgOTgzNSwgOTgzNiwgNjE0NDEsIDYxNDQyLCA2MTQ0NSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xXTsKZXhwb3J0cy5MaWJlcmF0aW9uU2Fuc0JvbGRNYXBwaW5nID0gTGliZXJhdGlvblNhbnNCb2xkTWFwcGluZzsKY29uc3QgTGliZXJhdGlvblNhbnNCb2xkSXRhbGljV2lkdGhzID0gWzM2NSwgMCwgMzMzLCAyNzgsIDMzMywgNDc0LCA1NTYsIDU1NiwgODg5LCA3MjIsIDIzOCwgMzMzLCAzMzMsIDM4OSwgNTg0LCAyNzgsIDMzMywgMjc4LCAyNzgsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMzMzLCAzMzMsIDU4NCwgNTg0LCA1ODQsIDYxMSwgOTc1LCA3MjIsIDcyMiwgNzIyLCA3MjIsIDY2NywgNjExLCA3NzgsIDcyMiwgMjc4LCA1NTYsIDcyMiwgNjExLCA4MzMsIDcyMiwgNzc4LCA2NjcsIDc3OCwgNzIyLCA2NjcsIDYxMSwgNzIyLCA2NjcsIDk0NCwgNjY3LCA2NjcsIDYxMSwgMzMzLCAyNzgsIDMzMywgNTg0LCA1NTYsIDMzMywgNTU2LCA2MTEsIDU1NiwgNjExLCA1NTYsIDMzMywgNjExLCA2MTEsIDI3OCwgMjc4LCA1NTYsIDI3OCwgODg5LCA2MTEsIDYxMSwgNjExLCA2MTEsIDM4OSwgNTU2LCAzMzMsIDYxMSwgNTU2LCA3NzgsIDU1NiwgNTU2LCA1MDAsIDM4OSwgMjgwLCAzODksIDU4NCwgMzMzLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDI4MCwgNTU2LCAzMzMsIDczNywgMzcwLCA1NTYsIDU4NCwgNzM3LCA1NTIsIDQwMCwgNTQ5LCAzMzMsIDMzMywgMzMzLCA1NzYsIDU1NiwgMjc4LCAzMzMsIDMzMywgMzY1LCA1NTYsIDgzNCwgODM0LCA4MzQsIDYxMSwgNzIyLCA3MjIsIDcyMiwgNzIyLCA3MjIsIDcyMiwgMTAwMCwgNzIyLCA2NjcsIDY2NywgNjY3LCA2NjcsIDI3OCwgMjc4LCAyNzgsIDI3OCwgNzIyLCA3MjIsIDc3OCwgNzc4LCA3NzgsIDc3OCwgNzc4LCA1ODQsIDc3OCwgNzIyLCA3MjIsIDcyMiwgNzIyLCA2NjcsIDY2NywgNjExLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA4ODksIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDYxMSwgNjExLCA2MTEsIDYxMSwgNjExLCA2MTEsIDYxMSwgNTQ5LCA2MTEsIDYxMSwgNjExLCA2MTEsIDYxMSwgNTU2LCA2MTEsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNzQwLCA3MjIsIDYxMSwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA3NzgsIDYxMSwgNzc4LCA2MTEsIDc3OCwgNjExLCA3NzgsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDc4MiwgNTU2LCA1NTYsIDI3OCwgNzIyLCA1NTYsIDU1NiwgNjExLCAyNzgsIDYxMSwgMjc4LCA2MTEsIDM5NiwgNjExLCA0NzksIDYxMSwgMjc4LCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA3MDgsIDcyMywgNjExLCA3NzgsIDYxMSwgNzc4LCA2MTEsIDc3OCwgNjExLCAxMDAwLCA5NDQsIDcyMiwgMzg5LCA3MjIsIDM4OSwgNzIyLCAzODksIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2MTEsIDMzMywgNjExLCA0NzksIDYxMSwgMzMzLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA5NDQsIDc3OCwgNjY3LCA1NTYsIDY2NywgNjExLCA1MDAsIDYxMSwgNTAwLCA2MTEsIDUwMCwgMjc4LCA1NTYsIDcyMiwgNTU2LCAxMDAwLCA4ODksIDc3OCwgNjExLCA2NjcsIDU1NiwgNjExLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCA3MjIsIDMzMywgODU0LCA5MDYsIDQ3MywgODQ0LCA5MzAsIDg0NywgMjc4LCA3MjIsIDcyMiwgNjEwLCA2NzEsIDY2NywgNjExLCA3MjIsIDc3OCwgMjc4LCA3MjIsIDY2NywgODMzLCA3MjIsIDY1NywgNzc4LCA3MTgsIDY2NywgNTkwLCA2MTEsIDY2NywgODIyLCA2NjcsIDgyOSwgNzgxLCAyNzgsIDY2NywgNjIwLCA0NzksIDYxMSwgMjc4LCA1OTEsIDYyMCwgNjIxLCA1NTYsIDYxMCwgNDc5LCA0OTIsIDYxMSwgNTU4LCAyNzgsIDU2NiwgNTU2LCA2MDMsIDU1NiwgNDUwLCA2MTEsIDcxMiwgNjA1LCA1MzIsIDY2NCwgNDA5LCA1OTEsIDcwNCwgNTc4LCA3NzMsIDgzNCwgMjc4LCA1OTEsIDYxMSwgNTkxLCA4MzQsIDY2NywgNjY3LCA4ODYsIDYxNCwgNzE5LCA2NjcsIDI3OCwgMjc4LCA1NTYsIDEwOTQsIDEwNDIsIDg1NCwgNjIyLCA3MTksIDY3NywgNzE5LCA3MjIsIDcwOCwgNzIyLCA2MTQsIDcyMiwgNjY3LCA5MjcsIDY0MywgNzE5LCA3MTksIDYxNSwgNjg3LCA4MzMsIDcyMiwgNzc4LCA3MTksIDY2NywgNzIyLCA2MTEsIDY3NywgNzgxLCA2NjcsIDcyOSwgNzA4LCA5NzksIDk4OSwgODU0LCAxMDAwLCA3MDgsIDcxOSwgMTA0MiwgNzI5LCA1NTYsIDYxOSwgNjA0LCA1MzQsIDYxOCwgNTU2LCA3MzYsIDUxMCwgNjExLCA2MTEsIDUwNywgNjIyLCA3NDAsIDYwNCwgNjExLCA2MTEsIDYxMSwgNTU2LCA4ODksIDU1NiwgODg1LCA1NTYsIDY0NiwgNTgzLCA4ODksIDkzNSwgNzA3LCA4NTQsIDU5NCwgNTUyLCA4NjUsIDU4OSwgNTU2LCA1NTYsIDYxMSwgNDY5LCA1NjMsIDU1NiwgMjc4LCAyNzgsIDI3OCwgOTY5LCA5MDYsIDYxMSwgNTA3LCA2MTksIDU1NiwgNjExLCA3NzgsIDYxMSwgNTc1LCA0NjcsIDk0NCwgNzc4LCA5NDQsIDc3OCwgOTQ0LCA3NzgsIDY2NywgNTU2LCAzMzMsIDMzMywgNTU2LCAxMDAwLCAxMDAwLCA1NTIsIDI3OCwgMjc4LCAyNzgsIDI3OCwgNTAwLCA1MDAsIDUwMCwgNTU2LCA1NTYsIDM1MCwgMTAwMCwgMTAwMCwgMjQwLCA0NzksIDMzMywgMzMzLCA2MDQsIDMzMywgMTY3LCAzOTYsIDU1NiwgNTU2LCAxMTA0LCA1NTYsIDg4NSwgNTE2LCAxMTQ2LCAxMDAwLCA3NjgsIDYwMCwgODM0LCA4MzQsIDgzNCwgODM0LCA5OTksIDUwMCwgMTAwMCwgNTAwLCAxMDAwLCA1MDAsIDUwMCwgNDk0LCA2MTIsIDgyMywgNzEzLCA1ODQsIDU0OSwgNzEzLCA5NzksIDcyMiwgMjc0LCA1NDksIDU0OSwgNTgzLCA1NDksIDU0OSwgNjA0LCA1ODQsIDYwNCwgNjA0LCA3MDgsIDYyNSwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzI5LCA2MDQsIDYwNCwgMzU0LCAzNTQsIDEwMDAsIDk5MCwgOTkwLCA5OTAsIDk5MCwgNDk0LCA2MDQsIDYwNCwgNjA0LCA2MDQsIDM1NCwgMTAyMSwgMTA1MiwgOTE3LCA3NTAsIDc1MCwgNTMxLCA2NTYsIDU5NCwgNTEwLCA1MDAsIDc1MCwgNzUwLCA2MTEsIDYxMSwgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDIyMiwgMjIyLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzM107CmV4cG9ydHMuTGliZXJhdGlvblNhbnNCb2xkSXRhbGljV2lkdGhzID0gTGliZXJhdGlvblNhbnNCb2xkSXRhbGljV2lkdGhzOwpjb25zdCBMaWJlcmF0aW9uU2Fuc0JvbGRJdGFsaWNNYXBwaW5nID0gWy0xLCAtMSwgLTEsIDMyLCAzMywgMzQsIDM1LCAzNiwgMzcsIDM4LCAzOSwgNDAsIDQxLCA0MiwgNDMsIDQ0LCA0NSwgNDYsIDQ3LCA0OCwgNDksIDUwLCA1MSwgNTIsIDUzLCA1NCwgNTUsIDU2LCA1NywgNTgsIDU5LCA2MCwgNjEsIDYyLCA2MywgNjQsIDY1LCA2NiwgNjcsIDY4LCA2OSwgNzAsIDcxLCA3MiwgNzMsIDc0LCA3NSwgNzYsIDc3LCA3OCwgNzksIDgwLCA4MSwgODIsIDgzLCA4NCwgODUsIDg2LCA4NywgODgsIDg5LCA5MCwgOTEsIDkyLCA5MywgOTQsIDk1LCA5NiwgOTcsIDk4LCA5OSwgMTAwLCAxMDEsIDEwMiwgMTAzLCAxMDQsIDEwNSwgMTA2LCAxMDcsIDEwOCwgMTA5LCAxMTAsIDExMSwgMTEyLCAxMTMsIDExNCwgMTE1LCAxMTYsIDExNywgMTE4LCAxMTksIDEyMCwgMTIxLCAxMjIsIDEyMywgMTI0LCAxMjUsIDEyNiwgMTYxLCAxNjIsIDE2MywgMTY0LCAxNjUsIDE2NiwgMTY3LCAxNjgsIDE2OSwgMTcwLCAxNzEsIDE3MiwgMTc0LCAxNzUsIDE3NiwgMTc3LCAxNzgsIDE3OSwgMTgwLCAxODEsIDE4MiwgMTgzLCAxODQsIDE4NSwgMTg2LCAxODcsIDE4OCwgMTg5LCAxOTAsIDE5MSwgMTkyLCAxOTMsIDE5NCwgMTk1LCAxOTYsIDE5NywgMTk4LCAxOTksIDIwMCwgMjAxLCAyMDIsIDIwMywgMjA0LCAyMDUsIDIwNiwgMjA3LCAyMDgsIDIwOSwgMjEwLCAyMTEsIDIxMiwgMjEzLCAyMTQsIDIxNSwgMjE2LCAyMTcsIDIxOCwgMjE5LCAyMjAsIDIyMSwgMjIyLCAyMjMsIDIyNCwgMjI1LCAyMjYsIDIyNywgMjI4LCAyMjksIDIzMCwgMjMxLCAyMzIsIDIzMywgMjM0LCAyMzUsIDIzNiwgMjM3LCAyMzgsIDIzOSwgMjQwLCAyNDEsIDI0MiwgMjQzLCAyNDQsIDI0NSwgMjQ2LCAyNDcsIDI0OCwgMjQ5LCAyNTAsIDI1MSwgMjUyLCAyNTMsIDI1NCwgMjU1LCAyNTYsIDI1NywgMjU4LCAyNTksIDI2MCwgMjYxLCAyNjIsIDI2MywgMjY0LCAyNjUsIDI2NiwgMjY3LCAyNjgsIDI2OSwgMjcwLCAyNzEsIDI3MiwgMjczLCAyNzQsIDI3NSwgMjc2LCAyNzcsIDI3OCwgMjc5LCAyODAsIDI4MSwgMjgyLCAyODMsIDI4NCwgMjg1LCAyODYsIDI4NywgMjg4LCAyODksIDI5MCwgMjkxLCAyOTIsIDI5MywgMjk0LCAyOTUsIDI5NiwgMjk3LCAyOTgsIDI5OSwgMzAwLCAzMDEsIDMwMiwgMzAzLCAzMDQsIDMwNSwgMzA2LCAzMDcsIDMwOCwgMzA5LCAzMTAsIDMxMSwgMzEyLCAzMTMsIDMxNCwgMzE1LCAzMTYsIDMxNywgMzE4LCAzMTksIDMyMCwgMzIxLCAzMjIsIDMyMywgMzI0LCAzMjUsIDMyNiwgMzI3LCAzMjgsIDMyOSwgMzMwLCAzMzEsIDMzMiwgMzMzLCAzMzQsIDMzNSwgMzM2LCAzMzcsIDMzOCwgMzM5LCAzNDAsIDM0MSwgMzQyLCAzNDMsIDM0NCwgMzQ1LCAzNDYsIDM0NywgMzQ4LCAzNDksIDM1MCwgMzUxLCAzNTIsIDM1MywgMzU0LCAzNTUsIDM1NiwgMzU3LCAzNTgsIDM1OSwgMzYwLCAzNjEsIDM2MiwgMzYzLCAzNjQsIDM2NSwgMzY2LCAzNjcsIDM2OCwgMzY5LCAzNzAsIDM3MSwgMzcyLCAzNzMsIDM3NCwgMzc1LCAzNzYsIDM3NywgMzc4LCAzNzksIDM4MCwgMzgxLCAzODIsIDM4MywgNDAyLCA1MDYsIDUwNywgNTA4LCA1MDksIDUxMCwgNTExLCA1MzYsIDUzNywgNTM4LCA1MzksIDcxMCwgNzExLCA3MTMsIDcyOCwgNzI5LCA3MzAsIDczMSwgNzMyLCA3MzMsIDkwMCwgOTAxLCA5MDIsIDkwMywgOTA0LCA5MDUsIDkwNiwgOTA4LCA5MTAsIDkxMSwgOTEyLCA5MTMsIDkxNCwgOTE1LCA5MTYsIDkxNywgOTE4LCA5MTksIDkyMCwgOTIxLCA5MjIsIDkyMywgOTI0LCA5MjUsIDkyNiwgOTI3LCA5MjgsIDkyOSwgOTMxLCA5MzIsIDkzMywgOTM0LCA5MzUsIDkzNiwgOTM3LCA5MzgsIDkzOSwgOTQwLCA5NDEsIDk0MiwgOTQzLCA5NDQsIDk0NSwgOTQ2LCA5NDcsIDk0OCwgOTQ5LCA5NTAsIDk1MSwgOTUyLCA5NTMsIDk1NCwgOTU1LCA5NTYsIDk1NywgOTU4LCA5NTksIDk2MCwgOTYxLCA5NjIsIDk2MywgOTY0LCA5NjUsIDk2NiwgOTY3LCA5NjgsIDk2OSwgOTcwLCA5NzEsIDk3MiwgOTczLCA5NzQsIDEwMjQsIDEwMjUsIDEwMjYsIDEwMjcsIDEwMjgsIDEwMjksIDEwMzAsIDEwMzEsIDEwMzIsIDEwMzMsIDEwMzQsIDEwMzUsIDEwMzYsIDEwMzcsIDEwMzgsIDEwMzksIDEwNDAsIDEwNDEsIDEwNDIsIDEwNDMsIDEwNDQsIDEwNDUsIDEwNDYsIDEwNDcsIDEwNDgsIDEwNDksIDEwNTAsIDEwNTEsIDEwNTIsIDEwNTMsIDEwNTQsIDEwNTUsIDEwNTYsIDEwNTcsIDEwNTgsIDEwNTksIDEwNjAsIDEwNjEsIDEwNjIsIDEwNjMsIDEwNjQsIDEwNjUsIDEwNjYsIDEwNjcsIDEwNjgsIDEwNjksIDEwNzAsIDEwNzEsIDEwNzIsIDEwNzMsIDEwNzQsIDEwNzUsIDEwNzYsIDEwNzcsIDEwNzgsIDEwNzksIDEwODAsIDEwODEsIDEwODIsIDEwODMsIDEwODQsIDEwODUsIDEwODYsIDEwODcsIDEwODgsIDEwODksIDEwOTAsIDEwOTEsIDEwOTIsIDEwOTMsIDEwOTQsIDEwOTUsIDEwOTYsIDEwOTcsIDEwOTgsIDEwOTksIDExMDAsIDExMDEsIDExMDIsIDExMDMsIDExMDQsIDExMDUsIDExMDYsIDExMDcsIDExMDgsIDExMDksIDExMTAsIDExMTEsIDExMTIsIDExMTMsIDExMTQsIDExMTUsIDExMTYsIDExMTcsIDExMTgsIDExMTksIDExMzgsIDExMzksIDExNjgsIDExNjksIDc4MDgsIDc4MDksIDc4MTAsIDc4MTEsIDc4MTIsIDc4MTMsIDc5MjIsIDc5MjMsIDgyMDgsIDgyMDksIDgyMTEsIDgyMTIsIDgyMTMsIDgyMTUsIDgyMTYsIDgyMTcsIDgyMTgsIDgyMTksIDgyMjAsIDgyMjEsIDgyMjIsIDgyMjQsIDgyMjUsIDgyMjYsIDgyMzAsIDgyNDAsIDgyNDIsIDgyNDMsIDgyNDksIDgyNTAsIDgyNTIsIDgyNTQsIDgyNjAsIDgzMTksIDgzNTUsIDgzNTYsIDgzNTksIDgzNjQsIDg0NTMsIDg0NjcsIDg0NzAsIDg0ODIsIDg0ODYsIDg0OTQsIDg1MzksIDg1NDAsIDg1NDEsIDg1NDIsIDg1OTIsIDg1OTMsIDg1OTQsIDg1OTUsIDg1OTYsIDg1OTcsIDg2MTYsIDg3MDYsIDg3MTAsIDg3MTksIDg3MjEsIDg3MjIsIDg3MzAsIDg3MzQsIDg3MzUsIDg3NDUsIDg3NDcsIDg3NzYsIDg4MDAsIDg4MDEsIDg4MDQsIDg4MDUsIDg5NjIsIDg5NzYsIDg5OTIsIDg5OTMsIDk0NzIsIDk0NzQsIDk0ODQsIDk0ODgsIDk0OTIsIDk0OTYsIDk1MDAsIDk1MDgsIDk1MTYsIDk1MjQsIDk1MzIsIDk1NTIsIDk1NTMsIDk1NTQsIDk1NTUsIDk1NTYsIDk1NTcsIDk1NTgsIDk1NTksIDk1NjAsIDk1NjEsIDk1NjIsIDk1NjMsIDk1NjQsIDk1NjUsIDk1NjYsIDk1NjcsIDk1NjgsIDk1NjksIDk1NzAsIDk1NzEsIDk1NzIsIDk1NzMsIDk1NzQsIDk1NzUsIDk1NzYsIDk1NzcsIDk1NzgsIDk1NzksIDk1ODAsIDk2MDAsIDk2MDQsIDk2MDgsIDk2MTIsIDk2MTYsIDk2MTcsIDk2MTgsIDk2MTksIDk2MzIsIDk2MzMsIDk2NDIsIDk2NDMsIDk2NDQsIDk2NTAsIDk2NTgsIDk2NjAsIDk2NjgsIDk2NzQsIDk2NzUsIDk2NzksIDk2ODgsIDk2ODksIDk3MDIsIDk3ODYsIDk3ODcsIDk3ODgsIDk3OTIsIDk3OTQsIDk4MjQsIDk4MjcsIDk4MjksIDk4MzAsIDk4MzQsIDk4MzUsIDk4MzYsIDYxNDQxLCA2MTQ0MiwgNjE0NDUsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMV07CmV4cG9ydHMuTGliZXJhdGlvblNhbnNCb2xkSXRhbGljTWFwcGluZyA9IExpYmVyYXRpb25TYW5zQm9sZEl0YWxpY01hcHBpbmc7CmNvbnN0IExpYmVyYXRpb25TYW5zSXRhbGljV2lkdGhzID0gWzM2NSwgMCwgMzMzLCAyNzgsIDI3OCwgMzU1LCA1NTYsIDU1NiwgODg5LCA2NjcsIDE5MSwgMzMzLCAzMzMsIDM4OSwgNTg0LCAyNzgsIDMzMywgMjc4LCAyNzgsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMjc4LCAyNzgsIDU4NCwgNTg0LCA1ODQsIDU1NiwgMTAxNSwgNjY3LCA2NjcsIDcyMiwgNzIyLCA2NjcsIDYxMSwgNzc4LCA3MjIsIDI3OCwgNTAwLCA2NjcsIDU1NiwgODMzLCA3MjIsIDc3OCwgNjY3LCA3NzgsIDcyMiwgNjY3LCA2MTEsIDcyMiwgNjY3LCA5NDQsIDY2NywgNjY3LCA2MTEsIDI3OCwgMjc4LCAyNzgsIDQ2OSwgNTU2LCAzMzMsIDU1NiwgNTU2LCA1MDAsIDU1NiwgNTU2LCAyNzgsIDU1NiwgNTU2LCAyMjIsIDIyMiwgNTAwLCAyMjIsIDgzMywgNTU2LCA1NTYsIDU1NiwgNTU2LCAzMzMsIDUwMCwgMjc4LCA1NTYsIDUwMCwgNzIyLCA1MDAsIDUwMCwgNTAwLCAzMzQsIDI2MCwgMzM0LCA1ODQsIDMzMywgNTU2LCA1NTYsIDU1NiwgNTU2LCAyNjAsIDU1NiwgMzMzLCA3MzcsIDM3MCwgNTU2LCA1ODQsIDczNywgNTUyLCA0MDAsIDU0OSwgMzMzLCAzMzMsIDMzMywgNTc2LCA1MzcsIDI3OCwgMzMzLCAzMzMsIDM2NSwgNTU2LCA4MzQsIDgzNCwgODM0LCA2MTEsIDY2NywgNjY3LCA2NjcsIDY2NywgNjY3LCA2NjcsIDEwMDAsIDcyMiwgNjY3LCA2NjcsIDY2NywgNjY3LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDcyMiwgNzIyLCA3NzgsIDc3OCwgNzc4LCA3NzgsIDc3OCwgNTg0LCA3NzgsIDcyMiwgNzIyLCA3MjIsIDcyMiwgNjY3LCA2NjcsIDYxMSwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgODg5LCA1MDAsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMjc4LCAyNzgsIDI3OCwgMjc4LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU0OSwgNjExLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDUwMCwgNTU2LCA1MDAsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDcyMiwgNTAwLCA3MjIsIDUwMCwgNzIyLCA1MDAsIDcyMiwgNTAwLCA3MjIsIDYyNSwgNzIyLCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNzc4LCA1NTYsIDc3OCwgNTU2LCA3NzgsIDU1NiwgNzc4LCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyMjIsIDI3OCwgMjc4LCA3MzMsIDQ0NCwgNTAwLCAyMjIsIDY2NywgNTAwLCA1MDAsIDU1NiwgMjIyLCA1NTYsIDIyMiwgNTU2LCAyODEsIDU1NiwgNDAwLCA1NTYsIDIyMiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNjE1LCA3MjMsIDU1NiwgNzc4LCA1NTYsIDc3OCwgNTU2LCA3NzgsIDU1NiwgMTAwMCwgOTQ0LCA3MjIsIDMzMywgNzIyLCAzMzMsIDcyMiwgMzMzLCA2NjcsIDUwMCwgNjY3LCA1MDAsIDY2NywgNTAwLCA2NjcsIDUwMCwgNjExLCAyNzgsIDYxMSwgMzU0LCA2MTEsIDI3OCwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgOTQ0LCA3MjIsIDY2NywgNTAwLCA2NjcsIDYxMSwgNTAwLCA2MTEsIDUwMCwgNjExLCA1MDAsIDIyMiwgNTU2LCA2NjcsIDU1NiwgMTAwMCwgODg5LCA3NzgsIDYxMSwgNjY3LCA1MDAsIDYxMSwgMjc4LCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgNjY3LCAyNzgsIDc4OSwgODQ2LCAzODksIDc5NCwgODY1LCA3NzUsIDIyMiwgNjY3LCA2NjcsIDU3MCwgNjcxLCA2NjcsIDYxMSwgNzIyLCA3NzgsIDI3OCwgNjY3LCA2NjcsIDgzMywgNzIyLCA2NDgsIDc3OCwgNzI1LCA2NjcsIDYwMCwgNjExLCA2NjcsIDgzNywgNjY3LCA4MzEsIDc2MSwgMjc4LCA2NjcsIDU3MCwgNDM5LCA1NTUsIDIyMiwgNTUwLCA1NzAsIDU3MSwgNTAwLCA1NTYsIDQzOSwgNDYzLCA1NTUsIDU0MiwgMjIyLCA1MDAsIDQ5MiwgNTQ4LCA1MDAsIDQ0NywgNTU2LCA2NzAsIDU3MywgNDg2LCA2MDMsIDM3NCwgNTUwLCA2NTIsIDU0NiwgNzI4LCA3NzksIDIyMiwgNTUwLCA1NTYsIDU1MCwgNzc5LCA2NjcsIDY2NywgODQzLCA1NDQsIDcwOCwgNjY3LCAyNzgsIDI3OCwgNTAwLCAxMDY2LCA5ODIsIDg0NCwgNTg5LCA3MTUsIDYzOSwgNzI0LCA2NjcsIDY1MSwgNjY3LCA1NDQsIDcwNCwgNjY3LCA5MTcsIDYxNCwgNzE1LCA3MTUsIDU4OSwgNjg2LCA4MzMsIDcyMiwgNzc4LCA3MjUsIDY2NywgNzIyLCA2MTEsIDYzOSwgNzk1LCA2NjcsIDcyNywgNjczLCA5MjAsIDkyMywgODA1LCA4ODYsIDY1MSwgNjk0LCAxMDIyLCA2ODIsIDU1NiwgNTYyLCA1MjIsIDQ5MywgNTUzLCA1NTYsIDY4OCwgNDY1LCA1NTYsIDU1NiwgNDcyLCA1NjQsIDY4NiwgNTUwLCA1NTYsIDU1NiwgNTU2LCA1MDAsIDgzMywgNTAwLCA4MzUsIDUwMCwgNTcyLCA1MTgsIDgzMCwgODUxLCA2MjEsIDczNiwgNTI2LCA0OTIsIDc1MiwgNTM0LCA1NTYsIDU1NiwgNTU2LCAzNzgsIDQ5NiwgNTAwLCAyMjIsIDIyMiwgMjIyLCA5MTAsIDgyOCwgNTU2LCA0NzIsIDU2NSwgNTAwLCA1NTYsIDc3OCwgNTU2LCA0OTIsIDMzOSwgOTQ0LCA3MjIsIDk0NCwgNzIyLCA5NDQsIDcyMiwgNjY3LCA1MDAsIDMzMywgMzMzLCA1NTYsIDEwMDAsIDEwMDAsIDU1MiwgMjIyLCAyMjIsIDIyMiwgMjIyLCAzMzMsIDMzMywgMzMzLCA1NTYsIDU1NiwgMzUwLCAxMDAwLCAxMDAwLCAxODgsIDM1NCwgMzMzLCAzMzMsIDUwMCwgMzMzLCAxNjcsIDM2NSwgNTU2LCA1NTYsIDEwOTQsIDU1NiwgODg1LCAzMjMsIDEwODMsIDEwMDAsIDc2OCwgNjAwLCA4MzQsIDgzNCwgODM0LCA4MzQsIDEwMDAsIDUwMCwgOTk4LCA1MDAsIDEwMDAsIDUwMCwgNTAwLCA0OTQsIDYxMiwgODIzLCA3MTMsIDU4NCwgNTQ5LCA3MTMsIDk3OSwgNzE5LCAyNzQsIDU0OSwgNTQ5LCA1ODQsIDU0OSwgNTQ5LCA2MDQsIDU4NCwgNjA0LCA2MDQsIDcwOCwgNjI1LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MjksIDYwNCwgNjA0LCAzNTQsIDM1NCwgMTAwMCwgOTkwLCA5OTAsIDk5MCwgOTkwLCA0OTQsIDYwNCwgNjA0LCA2MDQsIDYwNCwgMzU0LCAxMDIxLCAxMDUyLCA5MTcsIDc1MCwgNzUwLCA1MzEsIDY1NiwgNTk0LCA1MTAsIDUwMCwgNzUwLCA3NTAsIDUwMCwgNTAwLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMjIyLCAyMjIsIDI5NCwgMjk0LCAzMjQsIDMyNCwgMzE2LCAzMjgsIDM5OCwgMjg1XTsKZXhwb3J0cy5MaWJlcmF0aW9uU2Fuc0l0YWxpY1dpZHRocyA9IExpYmVyYXRpb25TYW5zSXRhbGljV2lkdGhzOwpjb25zdCBMaWJlcmF0aW9uU2Fuc0l0YWxpY01hcHBpbmcgPSBbLTEsIC0xLCAtMSwgMzIsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCwgNDEsIDQyLCA0MywgNDQsIDQ1LCA0NiwgNDcsIDQ4LCA0OSwgNTAsIDUxLCA1MiwgNTMsIDU0LCA1NSwgNTYsIDU3LCA1OCwgNTksIDYwLCA2MSwgNjIsIDYzLCA2NCwgNjUsIDY2LCA2NywgNjgsIDY5LCA3MCwgNzEsIDcyLCA3MywgNzQsIDc1LCA3NiwgNzcsIDc4LCA3OSwgODAsIDgxLCA4MiwgODMsIDg0LCA4NSwgODYsIDg3LCA4OCwgODksIDkwLCA5MSwgOTIsIDkzLCA5NCwgOTUsIDk2LCA5NywgOTgsIDk5LCAxMDAsIDEwMSwgMTAyLCAxMDMsIDEwNCwgMTA1LCAxMDYsIDEwNywgMTA4LCAxMDksIDExMCwgMTExLCAxMTIsIDExMywgMTE0LCAxMTUsIDExNiwgMTE3LCAxMTgsIDExOSwgMTIwLCAxMjEsIDEyMiwgMTIzLCAxMjQsIDEyNSwgMTI2LCAxNjEsIDE2MiwgMTYzLCAxNjQsIDE2NSwgMTY2LCAxNjcsIDE2OCwgMTY5LCAxNzAsIDE3MSwgMTcyLCAxNzQsIDE3NSwgMTc2LCAxNzcsIDE3OCwgMTc5LCAxODAsIDE4MSwgMTgyLCAxODMsIDE4NCwgMTg1LCAxODYsIDE4NywgMTg4LCAxODksIDE5MCwgMTkxLCAxOTIsIDE5MywgMTk0LCAxOTUsIDE5NiwgMTk3LCAxOTgsIDE5OSwgMjAwLCAyMDEsIDIwMiwgMjAzLCAyMDQsIDIwNSwgMjA2LCAyMDcsIDIwOCwgMjA5LCAyMTAsIDIxMSwgMjEyLCAyMTMsIDIxNCwgMjE1LCAyMTYsIDIxNywgMjE4LCAyMTksIDIyMCwgMjIxLCAyMjIsIDIyMywgMjI0LCAyMjUsIDIyNiwgMjI3LCAyMjgsIDIyOSwgMjMwLCAyMzEsIDIzMiwgMjMzLCAyMzQsIDIzNSwgMjM2LCAyMzcsIDIzOCwgMjM5LCAyNDAsIDI0MSwgMjQyLCAyNDMsIDI0NCwgMjQ1LCAyNDYsIDI0NywgMjQ4LCAyNDksIDI1MCwgMjUxLCAyNTIsIDI1MywgMjU0LCAyNTUsIDI1NiwgMjU3LCAyNTgsIDI1OSwgMjYwLCAyNjEsIDI2MiwgMjYzLCAyNjQsIDI2NSwgMjY2LCAyNjcsIDI2OCwgMjY5LCAyNzAsIDI3MSwgMjcyLCAyNzMsIDI3NCwgMjc1LCAyNzYsIDI3NywgMjc4LCAyNzksIDI4MCwgMjgxLCAyODIsIDI4MywgMjg0LCAyODUsIDI4NiwgMjg3LCAyODgsIDI4OSwgMjkwLCAyOTEsIDI5MiwgMjkzLCAyOTQsIDI5NSwgMjk2LCAyOTcsIDI5OCwgMjk5LCAzMDAsIDMwMSwgMzAyLCAzMDMsIDMwNCwgMzA1LCAzMDYsIDMwNywgMzA4LCAzMDksIDMxMCwgMzExLCAzMTIsIDMxMywgMzE0LCAzMTUsIDMxNiwgMzE3LCAzMTgsIDMxOSwgMzIwLCAzMjEsIDMyMiwgMzIzLCAzMjQsIDMyNSwgMzI2LCAzMjcsIDMyOCwgMzI5LCAzMzAsIDMzMSwgMzMyLCAzMzMsIDMzNCwgMzM1LCAzMzYsIDMzNywgMzM4LCAzMzksIDM0MCwgMzQxLCAzNDIsIDM0MywgMzQ0LCAzNDUsIDM0NiwgMzQ3LCAzNDgsIDM0OSwgMzUwLCAzNTEsIDM1MiwgMzUzLCAzNTQsIDM1NSwgMzU2LCAzNTcsIDM1OCwgMzU5LCAzNjAsIDM2MSwgMzYyLCAzNjMsIDM2NCwgMzY1LCAzNjYsIDM2NywgMzY4LCAzNjksIDM3MCwgMzcxLCAzNzIsIDM3MywgMzc0LCAzNzUsIDM3NiwgMzc3LCAzNzgsIDM3OSwgMzgwLCAzODEsIDM4MiwgMzgzLCA0MDIsIDUwNiwgNTA3LCA1MDgsIDUwOSwgNTEwLCA1MTEsIDUzNiwgNTM3LCA1MzgsIDUzOSwgNzEwLCA3MTEsIDcxMywgNzI4LCA3MjksIDczMCwgNzMxLCA3MzIsIDczMywgOTAwLCA5MDEsIDkwMiwgOTAzLCA5MDQsIDkwNSwgOTA2LCA5MDgsIDkxMCwgOTExLCA5MTIsIDkxMywgOTE0LCA5MTUsIDkxNiwgOTE3LCA5MTgsIDkxOSwgOTIwLCA5MjEsIDkyMiwgOTIzLCA5MjQsIDkyNSwgOTI2LCA5MjcsIDkyOCwgOTI5LCA5MzEsIDkzMiwgOTMzLCA5MzQsIDkzNSwgOTM2LCA5MzcsIDkzOCwgOTM5LCA5NDAsIDk0MSwgOTQyLCA5NDMsIDk0NCwgOTQ1LCA5NDYsIDk0NywgOTQ4LCA5NDksIDk1MCwgOTUxLCA5NTIsIDk1MywgOTU0LCA5NTUsIDk1NiwgOTU3LCA5NTgsIDk1OSwgOTYwLCA5NjEsIDk2MiwgOTYzLCA5NjQsIDk2NSwgOTY2LCA5NjcsIDk2OCwgOTY5LCA5NzAsIDk3MSwgOTcyLCA5NzMsIDk3NCwgMTAyNCwgMTAyNSwgMTAyNiwgMTAyNywgMTAyOCwgMTAyOSwgMTAzMCwgMTAzMSwgMTAzMiwgMTAzMywgMTAzNCwgMTAzNSwgMTAzNiwgMTAzNywgMTAzOCwgMTAzOSwgMTA0MCwgMTA0MSwgMTA0MiwgMTA0MywgMTA0NCwgMTA0NSwgMTA0NiwgMTA0NywgMTA0OCwgMTA0OSwgMTA1MCwgMTA1MSwgMTA1MiwgMTA1MywgMTA1NCwgMTA1NSwgMTA1NiwgMTA1NywgMTA1OCwgMTA1OSwgMTA2MCwgMTA2MSwgMTA2MiwgMTA2MywgMTA2NCwgMTA2NSwgMTA2NiwgMTA2NywgMTA2OCwgMTA2OSwgMTA3MCwgMTA3MSwgMTA3MiwgMTA3MywgMTA3NCwgMTA3NSwgMTA3NiwgMTA3NywgMTA3OCwgMTA3OSwgMTA4MCwgMTA4MSwgMTA4MiwgMTA4MywgMTA4NCwgMTA4NSwgMTA4NiwgMTA4NywgMTA4OCwgMTA4OSwgMTA5MCwgMTA5MSwgMTA5MiwgMTA5MywgMTA5NCwgMTA5NSwgMTA5NiwgMTA5NywgMTA5OCwgMTA5OSwgMTEwMCwgMTEwMSwgMTEwMiwgMTEwMywgMTEwNCwgMTEwNSwgMTEwNiwgMTEwNywgMTEwOCwgMTEwOSwgMTExMCwgMTExMSwgMTExMiwgMTExMywgMTExNCwgMTExNSwgMTExNiwgMTExNywgMTExOCwgMTExOSwgMTEzOCwgMTEzOSwgMTE2OCwgMTE2OSwgNzgwOCwgNzgwOSwgNzgxMCwgNzgxMSwgNzgxMiwgNzgxMywgNzkyMiwgNzkyMywgODIwOCwgODIwOSwgODIxMSwgODIxMiwgODIxMywgODIxNSwgODIxNiwgODIxNywgODIxOCwgODIxOSwgODIyMCwgODIyMSwgODIyMiwgODIyNCwgODIyNSwgODIyNiwgODIzMCwgODI0MCwgODI0MiwgODI0MywgODI0OSwgODI1MCwgODI1MiwgODI1NCwgODI2MCwgODMxOSwgODM1NSwgODM1NiwgODM1OSwgODM2NCwgODQ1MywgODQ2NywgODQ3MCwgODQ4MiwgODQ4NiwgODQ5NCwgODUzOSwgODU0MCwgODU0MSwgODU0MiwgODU5MiwgODU5MywgODU5NCwgODU5NSwgODU5NiwgODU5NywgODYxNiwgODcwNiwgODcxMCwgODcxOSwgODcyMSwgODcyMiwgODczMCwgODczNCwgODczNSwgODc0NSwgODc0NywgODc3NiwgODgwMCwgODgwMSwgODgwNCwgODgwNSwgODk2MiwgODk3NiwgODk5MiwgODk5MywgOTQ3MiwgOTQ3NCwgOTQ4NCwgOTQ4OCwgOTQ5MiwgOTQ5NiwgOTUwMCwgOTUwOCwgOTUxNiwgOTUyNCwgOTUzMiwgOTU1MiwgOTU1MywgOTU1NCwgOTU1NSwgOTU1NiwgOTU1NywgOTU1OCwgOTU1OSwgOTU2MCwgOTU2MSwgOTU2MiwgOTU2MywgOTU2NCwgOTU2NSwgOTU2NiwgOTU2NywgOTU2OCwgOTU2OSwgOTU3MCwgOTU3MSwgOTU3MiwgOTU3MywgOTU3NCwgOTU3NSwgOTU3NiwgOTU3NywgOTU3OCwgOTU3OSwgOTU4MCwgOTYwMCwgOTYwNCwgOTYwOCwgOTYxMiwgOTYxNiwgOTYxNywgOTYxOCwgOTYxOSwgOTYzMiwgOTYzMywgOTY0MiwgOTY0MywgOTY0NCwgOTY1MCwgOTY1OCwgOTY2MCwgOTY2OCwgOTY3NCwgOTY3NSwgOTY3OSwgOTY4OCwgOTY4OSwgOTcwMiwgOTc4NiwgOTc4NywgOTc4OCwgOTc5MiwgOTc5NCwgOTgyNCwgOTgyNywgOTgyOSwgOTgzMCwgOTgzNCwgOTgzNSwgOTgzNiwgNjE0NDEsIDYxNDQyLCA2MTQ0NSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xXTsKZXhwb3J0cy5MaWJlcmF0aW9uU2Fuc0l0YWxpY01hcHBpbmcgPSBMaWJlcmF0aW9uU2Fuc0l0YWxpY01hcHBpbmc7CmNvbnN0IExpYmVyYXRpb25TYW5zUmVndWxhcldpZHRocyA9IFszNjUsIDAsIDMzMywgMjc4LCAyNzgsIDM1NSwgNTU2LCA1NTYsIDg4OSwgNjY3LCAxOTEsIDMzMywgMzMzLCAzODksIDU4NCwgMjc4LCAzMzMsIDI3OCwgMjc4LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDI3OCwgMjc4LCA1ODQsIDU4NCwgNTg0LCA1NTYsIDEwMTUsIDY2NywgNjY3LCA3MjIsIDcyMiwgNjY3LCA2MTEsIDc3OCwgNzIyLCAyNzgsIDUwMCwgNjY3LCA1NTYsIDgzMywgNzIyLCA3NzgsIDY2NywgNzc4LCA3MjIsIDY2NywgNjExLCA3MjIsIDY2NywgOTQ0LCA2NjcsIDY2NywgNjExLCAyNzgsIDI3OCwgMjc4LCA0NjksIDU1NiwgMzMzLCA1NTYsIDU1NiwgNTAwLCA1NTYsIDU1NiwgMjc4LCA1NTYsIDU1NiwgMjIyLCAyMjIsIDUwMCwgMjIyLCA4MzMsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMzMzLCA1MDAsIDI3OCwgNTU2LCA1MDAsIDcyMiwgNTAwLCA1MDAsIDUwMCwgMzM0LCAyNjAsIDMzNCwgNTg0LCAzMzMsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMjYwLCA1NTYsIDMzMywgNzM3LCAzNzAsIDU1NiwgNTg0LCA3MzcsIDU1MiwgNDAwLCA1NDksIDMzMywgMzMzLCAzMzMsIDU3NiwgNTM3LCAyNzgsIDMzMywgMzMzLCAzNjUsIDU1NiwgODM0LCA4MzQsIDgzNCwgNjExLCA2NjcsIDY2NywgNjY3LCA2NjcsIDY2NywgNjY3LCAxMDAwLCA3MjIsIDY2NywgNjY3LCA2NjcsIDY2NywgMjc4LCAyNzgsIDI3OCwgMjc4LCA3MjIsIDcyMiwgNzc4LCA3NzgsIDc3OCwgNzc4LCA3NzgsIDU4NCwgNzc4LCA3MjIsIDcyMiwgNzIyLCA3MjIsIDY2NywgNjY3LCA2MTEsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDg4OSwgNTAwLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDI3OCwgMjc4LCAyNzgsIDI3OCwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NDksIDYxMSwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1MDAsIDU1NiwgNTAwLCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA3MjIsIDUwMCwgNzIyLCA1MDAsIDcyMiwgNTAwLCA3MjIsIDUwMCwgNzIyLCA2MTUsIDcyMiwgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDc3OCwgNTU2LCA3NzgsIDU1NiwgNzc4LCA1NTYsIDc3OCwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjIyLCAyNzgsIDI3OCwgNzM1LCA0NDQsIDUwMCwgMjIyLCA2NjcsIDUwMCwgNTAwLCA1NTYsIDIyMiwgNTU2LCAyMjIsIDU1NiwgMjkyLCA1NTYsIDMzNCwgNTU2LCAyMjIsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDYwNCwgNzIzLCA1NTYsIDc3OCwgNTU2LCA3NzgsIDU1NiwgNzc4LCA1NTYsIDEwMDAsIDk0NCwgNzIyLCAzMzMsIDcyMiwgMzMzLCA3MjIsIDMzMywgNjY3LCA1MDAsIDY2NywgNTAwLCA2NjcsIDUwMCwgNjY3LCA1MDAsIDYxMSwgMjc4LCA2MTEsIDM3NSwgNjExLCAyNzgsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDk0NCwgNzIyLCA2NjcsIDUwMCwgNjY3LCA2MTEsIDUwMCwgNjExLCA1MDAsIDYxMSwgNTAwLCAyMjIsIDU1NiwgNjY3LCA1NTYsIDEwMDAsIDg4OSwgNzc4LCA2MTEsIDY2NywgNTAwLCA2MTEsIDI3OCwgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDY2NywgMjc4LCA3ODQsIDgzOCwgMzg0LCA3NzQsIDg1NSwgNzUyLCAyMjIsIDY2NywgNjY3LCA1NTEsIDY2OCwgNjY3LCA2MTEsIDcyMiwgNzc4LCAyNzgsIDY2NywgNjY4LCA4MzMsIDcyMiwgNjUwLCA3NzgsIDcyMiwgNjY3LCA2MTgsIDYxMSwgNjY3LCA3OTgsIDY2NywgODM1LCA3NDgsIDI3OCwgNjY3LCA1NzgsIDQ0NiwgNTU2LCAyMjIsIDU0NywgNTc4LCA1NzUsIDUwMCwgNTU3LCA0NDYsIDQ0MSwgNTU2LCA1NTYsIDIyMiwgNTAwLCA1MDAsIDU3NiwgNTAwLCA0NDgsIDU1NiwgNjkwLCA1NjksIDQ4MiwgNjE3LCAzOTUsIDU0NywgNjQ4LCA1MjUsIDcxMywgNzgxLCAyMjIsIDU0NywgNTU2LCA1NDcsIDc4MSwgNjY3LCA2NjcsIDg2NSwgNTQyLCA3MTksIDY2NywgMjc4LCAyNzgsIDUwMCwgMTA1NywgMTAxMCwgODU0LCA1ODMsIDcyMiwgNjM1LCA3MTksIDY2NywgNjU2LCA2NjcsIDU0MiwgNjc3LCA2NjcsIDkyMywgNjA0LCA3MTksIDcxOSwgNTgzLCA2NTYsIDgzMywgNzIyLCA3NzgsIDcxOSwgNjY3LCA3MjIsIDYxMSwgNjM1LCA3NjAsIDY2NywgNzQwLCA2NjcsIDkxNywgOTM4LCA3OTIsIDg4NSwgNjU2LCA3MTksIDEwMTAsIDcyMiwgNTU2LCA1NzMsIDUzMSwgMzY1LCA1ODMsIDU1NiwgNjY5LCA0NTgsIDU1OSwgNTU5LCA0MzgsIDU4MywgNjg4LCA1NTIsIDU1NiwgNTQyLCA1NTYsIDUwMCwgNDU4LCA1MDAsIDgyMywgNTAwLCA1NzMsIDUyMSwgODAyLCA4MjMsIDYyNSwgNzE5LCA1MjEsIDUxMCwgNzUwLCA1NDIsIDU1NiwgNTU2LCA1NTYsIDM2NSwgNTEwLCA1MDAsIDIyMiwgMjc4LCAyMjIsIDkwNiwgODEyLCA1NTYsIDQzOCwgNTU5LCA1MDAsIDU1MiwgNzc4LCA1NTYsIDQ4OSwgNDExLCA5NDQsIDcyMiwgOTQ0LCA3MjIsIDk0NCwgNzIyLCA2NjcsIDUwMCwgMzMzLCAzMzMsIDU1NiwgMTAwMCwgMTAwMCwgNTUyLCAyMjIsIDIyMiwgMjIyLCAyMjIsIDMzMywgMzMzLCAzMzMsIDU1NiwgNTU2LCAzNTAsIDEwMDAsIDEwMDAsIDE4OCwgMzU0LCAzMzMsIDMzMywgNTAwLCAzMzMsIDE2NywgMzY1LCA1NTYsIDU1NiwgMTA5NCwgNTU2LCA4ODUsIDMyMywgMTA3MywgMTAwMCwgNzY4LCA2MDAsIDgzNCwgODM0LCA4MzQsIDgzNCwgMTAwMCwgNTAwLCAxMDAwLCA1MDAsIDEwMDAsIDUwMCwgNTAwLCA0OTQsIDYxMiwgODIzLCA3MTMsIDU4NCwgNTQ5LCA3MTMsIDk3OSwgNzE5LCAyNzQsIDU0OSwgNTQ5LCA1ODMsIDU0OSwgNTQ5LCA2MDQsIDU4NCwgNjA0LCA2MDQsIDcwOCwgNjI1LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MjksIDYwNCwgNjA0LCAzNTQsIDM1NCwgMTAwMCwgOTkwLCA5OTAsIDk5MCwgOTkwLCA0OTQsIDYwNCwgNjA0LCA2MDQsIDYwNCwgMzU0LCAxMDIxLCAxMDUyLCA5MTcsIDc1MCwgNzUwLCA1MzEsIDY1NiwgNTk0LCA1MTAsIDUwMCwgNzUwLCA3NTAsIDUwMCwgNTAwLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMjIyLCAyMjIsIDI5NCwgMjk0LCAzMjQsIDMyNCwgMzE2LCAzMjgsIDM5OCwgMjg1XTsKZXhwb3J0cy5MaWJlcmF0aW9uU2Fuc1JlZ3VsYXJXaWR0aHMgPSBMaWJlcmF0aW9uU2Fuc1JlZ3VsYXJXaWR0aHM7CmNvbnN0IExpYmVyYXRpb25TYW5zUmVndWxhck1hcHBpbmcgPSBbLTEsIC0xLCAtMSwgMzIsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCwgNDEsIDQyLCA0MywgNDQsIDQ1LCA0NiwgNDcsIDQ4LCA0OSwgNTAsIDUxLCA1MiwgNTMsIDU0LCA1NSwgNTYsIDU3LCA1OCwgNTksIDYwLCA2MSwgNjIsIDYzLCA2NCwgNjUsIDY2LCA2NywgNjgsIDY5LCA3MCwgNzEsIDcyLCA3MywgNzQsIDc1LCA3NiwgNzcsIDc4LCA3OSwgODAsIDgxLCA4MiwgODMsIDg0LCA4NSwgODYsIDg3LCA4OCwgODksIDkwLCA5MSwgOTIsIDkzLCA5NCwgOTUsIDk2LCA5NywgOTgsIDk5LCAxMDAsIDEwMSwgMTAyLCAxMDMsIDEwNCwgMTA1LCAxMDYsIDEwNywgMTA4LCAxMDksIDExMCwgMTExLCAxMTIsIDExMywgMTE0LCAxMTUsIDExNiwgMTE3LCAxMTgsIDExOSwgMTIwLCAxMjEsIDEyMiwgMTIzLCAxMjQsIDEyNSwgMTI2LCAxNjEsIDE2MiwgMTYzLCAxNjQsIDE2NSwgMTY2LCAxNjcsIDE2OCwgMTY5LCAxNzAsIDE3MSwgMTcyLCAxNzQsIDE3NSwgMTc2LCAxNzcsIDE3OCwgMTc5LCAxODAsIDE4MSwgMTgyLCAxODMsIDE4NCwgMTg1LCAxODYsIDE4NywgMTg4LCAxODksIDE5MCwgMTkxLCAxOTIsIDE5MywgMTk0LCAxOTUsIDE5NiwgMTk3LCAxOTgsIDE5OSwgMjAwLCAyMDEsIDIwMiwgMjAzLCAyMDQsIDIwNSwgMjA2LCAyMDcsIDIwOCwgMjA5LCAyMTAsIDIxMSwgMjEyLCAyMTMsIDIxNCwgMjE1LCAyMTYsIDIxNywgMjE4LCAyMTksIDIyMCwgMjIxLCAyMjIsIDIyMywgMjI0LCAyMjUsIDIyNiwgMjI3LCAyMjgsIDIyOSwgMjMwLCAyMzEsIDIzMiwgMjMzLCAyMzQsIDIzNSwgMjM2LCAyMzcsIDIzOCwgMjM5LCAyNDAsIDI0MSwgMjQyLCAyNDMsIDI0NCwgMjQ1LCAyNDYsIDI0NywgMjQ4LCAyNDksIDI1MCwgMjUxLCAyNTIsIDI1MywgMjU0LCAyNTUsIDI1NiwgMjU3LCAyNTgsIDI1OSwgMjYwLCAyNjEsIDI2MiwgMjYzLCAyNjQsIDI2NSwgMjY2LCAyNjcsIDI2OCwgMjY5LCAyNzAsIDI3MSwgMjcyLCAyNzMsIDI3NCwgMjc1LCAyNzYsIDI3NywgMjc4LCAyNzksIDI4MCwgMjgxLCAyODIsIDI4MywgMjg0LCAyODUsIDI4NiwgMjg3LCAyODgsIDI4OSwgMjkwLCAyOTEsIDI5MiwgMjkzLCAyOTQsIDI5NSwgMjk2LCAyOTcsIDI5OCwgMjk5LCAzMDAsIDMwMSwgMzAyLCAzMDMsIDMwNCwgMzA1LCAzMDYsIDMwNywgMzA4LCAzMDksIDMxMCwgMzExLCAzMTIsIDMxMywgMzE0LCAzMTUsIDMxNiwgMzE3LCAzMTgsIDMxOSwgMzIwLCAzMjEsIDMyMiwgMzIzLCAzMjQsIDMyNSwgMzI2LCAzMjcsIDMyOCwgMzI5LCAzMzAsIDMzMSwgMzMyLCAzMzMsIDMzNCwgMzM1LCAzMzYsIDMzNywgMzM4LCAzMzksIDM0MCwgMzQxLCAzNDIsIDM0MywgMzQ0LCAzNDUsIDM0NiwgMzQ3LCAzNDgsIDM0OSwgMzUwLCAzNTEsIDM1MiwgMzUzLCAzNTQsIDM1NSwgMzU2LCAzNTcsIDM1OCwgMzU5LCAzNjAsIDM2MSwgMzYyLCAzNjMsIDM2NCwgMzY1LCAzNjYsIDM2NywgMzY4LCAzNjksIDM3MCwgMzcxLCAzNzIsIDM3MywgMzc0LCAzNzUsIDM3NiwgMzc3LCAzNzgsIDM3OSwgMzgwLCAzODEsIDM4MiwgMzgzLCA0MDIsIDUwNiwgNTA3LCA1MDgsIDUwOSwgNTEwLCA1MTEsIDUzNiwgNTM3LCA1MzgsIDUzOSwgNzEwLCA3MTEsIDcxMywgNzI4LCA3MjksIDczMCwgNzMxLCA3MzIsIDczMywgOTAwLCA5MDEsIDkwMiwgOTAzLCA5MDQsIDkwNSwgOTA2LCA5MDgsIDkxMCwgOTExLCA5MTIsIDkxMywgOTE0LCA5MTUsIDkxNiwgOTE3LCA5MTgsIDkxOSwgOTIwLCA5MjEsIDkyMiwgOTIzLCA5MjQsIDkyNSwgOTI2LCA5MjcsIDkyOCwgOTI5LCA5MzEsIDkzMiwgOTMzLCA5MzQsIDkzNSwgOTM2LCA5MzcsIDkzOCwgOTM5LCA5NDAsIDk0MSwgOTQyLCA5NDMsIDk0NCwgOTQ1LCA5NDYsIDk0NywgOTQ4LCA5NDksIDk1MCwgOTUxLCA5NTIsIDk1MywgOTU0LCA5NTUsIDk1NiwgOTU3LCA5NTgsIDk1OSwgOTYwLCA5NjEsIDk2MiwgOTYzLCA5NjQsIDk2NSwgOTY2LCA5NjcsIDk2OCwgOTY5LCA5NzAsIDk3MSwgOTcyLCA5NzMsIDk3NCwgMTAyNCwgMTAyNSwgMTAyNiwgMTAyNywgMTAyOCwgMTAyOSwgMTAzMCwgMTAzMSwgMTAzMiwgMTAzMywgMTAzNCwgMTAzNSwgMTAzNiwgMTAzNywgMTAzOCwgMTAzOSwgMTA0MCwgMTA0MSwgMTA0MiwgMTA0MywgMTA0NCwgMTA0NSwgMTA0NiwgMTA0NywgMTA0OCwgMTA0OSwgMTA1MCwgMTA1MSwgMTA1MiwgMTA1MywgMTA1NCwgMTA1NSwgMTA1NiwgMTA1NywgMTA1OCwgMTA1OSwgMTA2MCwgMTA2MSwgMTA2MiwgMTA2MywgMTA2NCwgMTA2NSwgMTA2NiwgMTA2NywgMTA2OCwgMTA2OSwgMTA3MCwgMTA3MSwgMTA3MiwgMTA3MywgMTA3NCwgMTA3NSwgMTA3NiwgMTA3NywgMTA3OCwgMTA3OSwgMTA4MCwgMTA4MSwgMTA4MiwgMTA4MywgMTA4NCwgMTA4NSwgMTA4NiwgMTA4NywgMTA4OCwgMTA4OSwgMTA5MCwgMTA5MSwgMTA5MiwgMTA5MywgMTA5NCwgMTA5NSwgMTA5NiwgMTA5NywgMTA5OCwgMTA5OSwgMTEwMCwgMTEwMSwgMTEwMiwgMTEwMywgMTEwNCwgMTEwNSwgMTEwNiwgMTEwNywgMTEwOCwgMTEwOSwgMTExMCwgMTExMSwgMTExMiwgMTExMywgMTExNCwgMTExNSwgMTExNiwgMTExNywgMTExOCwgMTExOSwgMTEzOCwgMTEzOSwgMTE2OCwgMTE2OSwgNzgwOCwgNzgwOSwgNzgxMCwgNzgxMSwgNzgxMiwgNzgxMywgNzkyMiwgNzkyMywgODIwOCwgODIwOSwgODIxMSwgODIxMiwgODIxMywgODIxNSwgODIxNiwgODIxNywgODIxOCwgODIxOSwgODIyMCwgODIyMSwgODIyMiwgODIyNCwgODIyNSwgODIyNiwgODIzMCwgODI0MCwgODI0MiwgODI0MywgODI0OSwgODI1MCwgODI1MiwgODI1NCwgODI2MCwgODMxOSwgODM1NSwgODM1NiwgODM1OSwgODM2NCwgODQ1MywgODQ2NywgODQ3MCwgODQ4MiwgODQ4NiwgODQ5NCwgODUzOSwgODU0MCwgODU0MSwgODU0MiwgODU5MiwgODU5MywgODU5NCwgODU5NSwgODU5NiwgODU5NywgODYxNiwgODcwNiwgODcxMCwgODcxOSwgODcyMSwgODcyMiwgODczMCwgODczNCwgODczNSwgODc0NSwgODc0NywgODc3NiwgODgwMCwgODgwMSwgODgwNCwgODgwNSwgODk2MiwgODk3NiwgODk5MiwgODk5MywgOTQ3MiwgOTQ3NCwgOTQ4NCwgOTQ4OCwgOTQ5MiwgOTQ5NiwgOTUwMCwgOTUwOCwgOTUxNiwgOTUyNCwgOTUzMiwgOTU1MiwgOTU1MywgOTU1NCwgOTU1NSwgOTU1NiwgOTU1NywgOTU1OCwgOTU1OSwgOTU2MCwgOTU2MSwgOTU2MiwgOTU2MywgOTU2NCwgOTU2NSwgOTU2NiwgOTU2NywgOTU2OCwgOTU2OSwgOTU3MCwgOTU3MSwgOTU3MiwgOTU3MywgOTU3NCwgOTU3NSwgOTU3NiwgOTU3NywgOTU3OCwgOTU3OSwgOTU4MCwgOTYwMCwgOTYwNCwgOTYwOCwgOTYxMiwgOTYxNiwgOTYxNywgOTYxOCwgOTYxOSwgOTYzMiwgOTYzMywgOTY0MiwgOTY0MywgOTY0NCwgOTY1MCwgOTY1OCwgOTY2MCwgOTY2OCwgOTY3NCwgOTY3NSwgOTY3OSwgOTY4OCwgOTY4OSwgOTcwMiwgOTc4NiwgOTc4NywgOTc4OCwgOTc5MiwgOTc5NCwgOTgyNCwgOTgyNywgOTgyOSwgOTgzMCwgOTgzNCwgOTgzNSwgOTgzNiwgNjE0NDEsIDYxNDQyLCA2MTQ0NSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xXTsKZXhwb3J0cy5MaWJlcmF0aW9uU2Fuc1JlZ3VsYXJNYXBwaW5nID0gTGliZXJhdGlvblNhbnNSZWd1bGFyTWFwcGluZzsKCi8qKiovIH0pLAovKiAxOTAgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLk15cmlhZFByb1JlZ3VsYXJNZXRyaWNzID0gZXhwb3J0cy5NeXJpYWRQcm9SZWd1bGFyRmFjdG9ycyA9IGV4cG9ydHMuTXlyaWFkUHJvSXRhbGljTWV0cmljcyA9IGV4cG9ydHMuTXlyaWFkUHJvSXRhbGljRmFjdG9ycyA9IGV4cG9ydHMuTXlyaWFkUHJvQm9sZE1ldHJpY3MgPSBleHBvcnRzLk15cmlhZFByb0JvbGRJdGFsaWNNZXRyaWNzID0gZXhwb3J0cy5NeXJpYWRQcm9Cb2xkSXRhbGljRmFjdG9ycyA9IGV4cG9ydHMuTXlyaWFkUHJvQm9sZEZhY3RvcnMgPSB2b2lkIDA7CmNvbnN0IE15cmlhZFByb0JvbGRGYWN0b3JzID0gWzEuMzY4OTgsIDEsIDEsIDAuNzI3MDYsIDAuODA0NzksIDAuODM3MzQsIDAuOTg4OTQsIDAuOTk3OTMsIDAuOTg5NywgMC45Mzg4NCwgMC44NjIwOSwgMC45NDI5MiwgMC45NDI5MiwgMS4xNjY2MSwgMS4wMjA1OCwgMC45MzU4MiwgMC45NjY5NCwgMC45MzU4MiwgMS4xOTEzNywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC45OTc5MywgMC43ODA3NiwgMC43ODA3NiwgMS4wMjA1OCwgMS4wMjA1OCwgMS4wMjA1OCwgMC43Mjg1MSwgMC43ODk2NiwgMC45MDgzOCwgMC44MzYzNywgMC44MjM5MSwgMC45NjM3NiwgMC44MDA2MSwgMC44NjI3NSwgMC44NzY4LCAwLjk1NDA3LCAxLjAyNTgsIDAuNzM5MDEsIDAuODUwMjIsIDAuODM2NTUsIDEuMDE1NiwgMC45NTU0NiwgMC45MjE3OSwgMC44NzEwNywgMC45MjE3OSwgMC44MjExNCwgMC44MDk2LCAwLjg5NzEzLCAwLjk0NDM4LCAwLjk1MzUzLCAwLjk0MDgzLCAwLjkxOTA1LCAwLjkwNDA2LCAwLjk0NDYsIDAuOTQyOTIsIDEuMTg3NzcsIDAuOTQyOTIsIDEuMDIwNTgsIDAuODk5MDMsIDAuOTAwODgsIDAuOTQ5MzgsIDAuOTc4OTgsIDAuODEwOTMsIDAuOTc1NzEsIDAuOTQ5MzgsIDEuMDI0LCAwLjk1NzcsIDAuOTU5MzMsIDAuOTg2MjEsIDEuMDQ3NCwgMC45NzQ1NSwgMC45ODk4MSwgMC45NjcyLCAwLjk1OTMzLCAwLjk0NDYsIDAuOTc4OTgsIDAuOTc0MDcsIDAuOTc2NDYsIDAuNzgwMzYsIDEuMTAyMDgsIDAuOTU0NDIsIDAuOTUyOTgsIDAuOTc1NzksIDAuOTMzMiwgMC45NDAzOSwgMC45MzgsIDAuODA2ODcsIDEuMDExNDksIDAuODA2ODcsIDEuMDIwNTgsIDAuODA0NzksIDAuOTk3OTMsIDAuOTk3OTMsIDAuOTk3OTMsIDAuOTk3OTMsIDEuMDExNDksIDEuMDA4NzIsIDAuOTAwODgsIDAuOTE4ODIsIDEuMDIxMywgMC44MzYxLCAxLjAyMDU4LCAwLjYyMjk1LCAwLjU0MzI0LCAwLjg5MDIyLCAxLjA4NTk1LCAxLCAxLCAwLjkwMDg4LCAxLCAwLjk3NDU1LCAwLjkzNTgyLCAwLjkwMDg4LCAxLCAxLjA1Njg2LCAwLjgzNjEsIDAuOTk2NDIsIDAuOTk2NDIsIDAuOTk2NDIsIDAuNzI4NTEsIDAuOTA4MzgsIDAuOTA4MzgsIDAuOTA4MzgsIDAuOTA4MzgsIDAuOTA4MzgsIDAuOTA4MzgsIDAuODY4LCAwLjgyMzkxLCAwLjgwMDYxLCAwLjgwMDYxLCAwLjgwMDYxLCAwLjgwMDYxLCAxLjAyNTgsIDEuMDI1OCwgMS4wMjU4LCAxLjAyNTgsIDAuOTc0ODQsIDAuOTU1NDYsIDAuOTIxNzksIDAuOTIxNzksIDAuOTIxNzksIDAuOTIxNzksIDAuOTIxNzksIDEuMDIwNTgsIDAuOTIxNzksIDAuOTQ0MzgsIDAuOTQ0MzgsIDAuOTQ0MzgsIDAuOTQ0MzgsIDAuOTA0MDYsIDAuODY5NTgsIDAuOTgyMjUsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTAzMSwgMC44MTA5MywgMC45NDkzOCwgMC45NDkzOCwgMC45NDkzOCwgMC45NDkzOCwgMC45ODYyMSwgMC45ODYyMSwgMC45ODYyMSwgMC45ODYyMSwgMC45Mzk2OSwgMC45NTkzMywgMC45NDQ2LCAwLjk0NDYsIDAuOTQ0NiwgMC45NDQ2LCAwLjk0NDYsIDEuMDg1OTUsIDAuOTQ0NiwgMC45NTQ0MiwgMC45NTQ0MiwgMC45NTQ0MiwgMC45NTQ0MiwgMC45NDAzOSwgMC45Nzg5OCwgMC45NDAzOSwgMC45MDgzOCwgMC45NDkzOCwgMC45MDgzOCwgMC45NDkzOCwgMC45MDgzOCwgMC45NDkzOCwgMC44MjM5MSwgMC44MTA5MywgMC44MjM5MSwgMC44MTA5MywgMC44MjM5MSwgMC44MTA5MywgMC44MjM5MSwgMC44MTA5MywgMC45NjM3NiwgMC44NDMxMywgMC45NzQ4NCwgMC45NzU3MSwgMC44MDA2MSwgMC45NDkzOCwgMC44MDA2MSwgMC45NDkzOCwgMC44MDA2MSwgMC45NDkzOCwgMC44MDA2MSwgMC45NDkzOCwgMC44MDA2MSwgMC45NDkzOCwgMC44NzY4LCAwLjk1NzcsIDAuODc2OCwgMC45NTc3LCAwLjg3NjgsIDAuOTU3NywgMSwgMSwgMC45NTQwNywgMC45NTkzMywgMC45NzA2OSwgMC45NTkzMywgMS4wMjU4LCAwLjk4NjIxLCAxLjAyNTgsIDAuOTg2MjEsIDEuMDI1OCwgMC45ODYyMSwgMS4wMjU4LCAwLjk4NjIxLCAxLjAyNTgsIDAuOTg2MjEsIDAuODg3LCAxLjAxNTkxLCAwLjczOTAxLCAxLjA0NzQsIDEsIDEsIDAuOTc0NTUsIDAuODM2NTUsIDAuOTg5ODEsIDEsIDEsIDAuODM2NTUsIDAuNzM5NzcsIDAuODM2NTUsIDAuNzM5MDMsIDAuODQ2MzgsIDEuMDMzLCAwLjk1NTQ2LCAwLjk1OTMzLCAxLCAxLCAwLjk1NTQ2LCAwLjk1OTMzLCAwLjgyNzEsIDAuOTU0MTcsIDAuOTU5MzMsIDAuOTIxNzksIDAuOTQ0NiwgMC45MjE3OSwgMC45NDQ2LCAwLjkyMTc5LCAwLjk0NDYsIDAuOTM2LCAwLjkxOTY0LCAwLjgyMTE0LCAwLjk3NjQ2LCAxLCAxLCAwLjgyMTE0LCAwLjk3NjQ2LCAwLjgwOTYsIDAuNzgwMzYsIDAuODA5NiwgMC43ODAzNiwgMSwgMSwgMC44MDk2LCAwLjc4MDM2LCAxLCAxLCAwLjg5NzEzLCAwLjc3NDUyLCAwLjg5NzEzLCAxLjEwMjA4LCAwLjk0NDM4LCAwLjk1NDQyLCAwLjk0NDM4LCAwLjk1NDQyLCAwLjk0NDM4LCAwLjk1NDQyLCAwLjk0NDM4LCAwLjk1NDQyLCAwLjk0NDM4LCAwLjk1NDQyLCAwLjk0NDM4LCAwLjk1NDQyLCAwLjk0MDgzLCAwLjk3NTc5LCAwLjkwNDA2LCAwLjk0MDM5LCAwLjkwNDA2LCAwLjk0NDYsIDAuOTM4LCAwLjk0NDYsIDAuOTM4LCAwLjk0NDYsIDAuOTM4LCAxLCAwLjk5NzkzLCAwLjkwODM4LCAwLjk0OTM4LCAwLjg2OCwgMC45MDMxLCAwLjkyMTc5LCAwLjk0NDYsIDEsIDEsIDAuODk3MTMsIDEuMTAyMDgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTA5ODksIDAuOTM1OCwgMC45MTk0NSwgMC44MzE4MSwgMC43NTI2MSwgMC44Nzk5MiwgMC44Mjk3NiwgMC45NjAzNCwgMC44MzY4OSwgMC45NzI2OCwgMS4wMDc4LCAwLjkwODM4LCAwLjgzNjM3LCAwLjgwMTksIDAuOTAxNTcsIDAuODAwNjEsIDAuOTQ0NiwgMC45NTQwNywgMC45MjQzNiwgMS4wMjU4LCAwLjg1MDIyLCAwLjk3MTUzLCAxLjAxNTYsIDAuOTU1NDYsIDAuODkxOTIsIDAuOTIxNzksIDAuOTIzNjEsIDAuODcxMDcsIDAuOTYzMTgsIDAuODk3MTMsIDAuOTM3MDQsIDAuOTU2MzgsIDAuOTE5MDUsIDAuOTE3MDksIDAuOTI3OTYsIDEuMDI1OCwgMC45MzcwNCwgMC45NDgzNiwgMS4wMzczLCAwLjk1OTMzLCAxLjAwNzgsIDAuOTU4NzEsIDAuOTQ4MzYsIDAuOTYxNzQsIDAuOTI2MDEsIDAuOTQ5OCwgMC45ODYwNywgMC45NTc3NiwgMC45NTkzMywgMS4wNTQ1MywgMS4wMDc4LCAwLjk4Mjc1LCAwLjkzMTQsIDAuOTU2MTcsIDAuOTE3MDEsIDEuMDU5OTMsIDAuOTQ0NiwgMC43ODM2NywgMC45NTUzLCAxLCAwLjg2ODMyLCAxLjAxMjgsIDAuOTU4NzEsIDAuOTkzOTQsIDAuODc1NDgsIDAuOTYzNjEsIDAuODY3NzQsIDEuMDA3OCwgMC45NTg3MSwgMC45NDQ2LCAwLjk1ODcxLCAwLjg2Nzc0LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk0MDgzLCAwLjk3NTc5LCAwLjk0MDgzLCAwLjk3NTc5LCAwLjk0MDgzLCAwLjk3NTc5LCAwLjkwNDA2LCAwLjk0MDM5LCAwLjk2Njk0LCAxLCAwLjg5OTAzLCAxLCAxLCAxLCAwLjkzNTgyLCAwLjkzNTgyLCAwLjkzNTgyLCAxLCAwLjkwOCwgMC45MDgsIDAuOTE4LCAwLjk0MjE5LCAwLjk0MjE5LCAwLjk2NTQ0LCAxLCAxLjI4NSwgMSwgMSwgMC44MTA3OSwgMC44MTA3OSwgMSwgMSwgMC43NDg1NCwgMSwgMSwgMSwgMSwgMC45OTc5MywgMSwgMSwgMSwgMC42NSwgMSwgMS4zNjE0NSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4xNzE3MywgMSwgMC44MDUzNSwgMC43NjE2OSwgMS4wMjA1OCwgMS4wNzMyLCAxLjA1NDg2LCAxLCAxLCAxLjMwNjkyLCAxLjA4NTk1LCAxLjA4NTk1LCAxLCAxLjA4NTk1LCAxLjA4NTk1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjE2MTYxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKZXhwb3J0cy5NeXJpYWRQcm9Cb2xkRmFjdG9ycyA9IE15cmlhZFByb0JvbGRGYWN0b3JzOwpjb25zdCBNeXJpYWRQcm9Cb2xkTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjIsCiAgbGluZUdhcDogMC4yCn07CmV4cG9ydHMuTXlyaWFkUHJvQm9sZE1ldHJpY3MgPSBNeXJpYWRQcm9Cb2xkTWV0cmljczsKY29uc3QgTXlyaWFkUHJvQm9sZEl0YWxpY0ZhY3RvcnMgPSBbMS4zNjg5OCwgMSwgMSwgMC42NjIyNywgMC44MDc3OSwgMC44MTYyNSwgMC45NzI3NiwgMC45NzI3NiwgMC45NzczMywgMC45MjIyMiwgMC44MzI2NiwgMC45NDI5MiwgMC45NDI5MiwgMS4xNjE0OCwgMS4wMjA1OCwgMC45MzU4MiwgMC45NjY5NCwgMC45MzU4MiwgMS4xNzMzNywgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC43ODA3NiwgMC43ODA3NiwgMS4wMjA1OCwgMS4wMjA1OCwgMS4wMjA1OCwgMC43MTU0MSwgMC43NjgxMywgMC44NTU3NiwgMC44MDU5MSwgMC44MDcyOSwgMC45NDI5OSwgMC43NzUxMiwgMC44MzY1NSwgMC44NjUyMywgMC45MjIyMiwgMC45ODYyMSwgMC43MTc0MywgMC44MTY5OCwgMC43OTcyNiwgMC45ODU1OCwgMC45MjIyMiwgMC45MDYzNywgMC44MzgwOSwgMC45MDYzNywgMC44MDcyOSwgMC43NjQ2MywgMC44NjI3NSwgMC45MDY5OSwgMC45MTYwNSwgMC45MTU0LCAwLjg1MzA4LCAwLjg1NDU4LCAwLjkwNTMxLCAwLjk0MjkyLCAxLjIxMjk2LCAwLjk0MjkyLCAxLjAyMDU4LCAwLjg5OTAzLCAxLjE4NjE2LCAwLjk5NjEzLCAwLjkxNjc3LCAwLjc4MjE2LCAwLjkxNjc3LCAwLjkwMDgzLCAwLjk4Nzk2LCAwLjkxMzUsIDAuOTIxNjgsIDAuOTUzODEsIDAuOTg5ODEsIDAuOTUyOTgsIDAuOTUzODEsIDAuOTM0NTksIDAuOTIxNjgsIDAuOTE1MTMsIDAuOTIwMDQsIDAuOTE2NzcsIDAuOTUwNzcsIDAuNzQ4LCAxLjA0NTAyLCAwLjkxNjc3LCAwLjkyMDYxLCAwLjk0MjM2LCAwLjg5NTQ0LCAwLjg5MzY0LCAwLjksIDAuODA2ODcsIDAuODU3OCwgMC44MDY4NywgMS4wMjA1OCwgMC44MDc3OSwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC44NTc4LCAwLjk5OTczLCAxLjE4NjE2LCAwLjkxMzM5LCAxLjA4MDc0LCAwLjgyODkxLCAxLjAyMDU4LCAwLjU1NTA5LCAwLjcxNTI2LCAwLjg5MDIyLCAxLjA4NTk1LCAxLCAxLCAxLjE4NjE2LCAxLCAwLjk2NzM2LCAwLjkzNTgyLCAxLjE4NjE2LCAxLCAxLjA0ODY0LCAwLjgyNzExLCAwLjk5MDQzLCAwLjk5MDQzLCAwLjk5MDQzLCAwLjcxNTQxLCAwLjg1NTc2LCAwLjg1NTc2LCAwLjg1NTc2LCAwLjg1NTc2LCAwLjg1NTc2LCAwLjg1NTc2LCAwLjg0NSwgMC44MDcyOSwgMC43NzUxMiwgMC43NzUxMiwgMC43NzUxMiwgMC43NzUxMiwgMC45ODYyMSwgMC45ODYyMSwgMC45ODYyMSwgMC45ODYyMSwgMC45NTk2MSwgMC45MjIyMiwgMC45MDYzNywgMC45MDYzNywgMC45MDYzNywgMC45MDYzNywgMC45MDYzNywgMS4wMjA1OCwgMC45MDI1MSwgMC45MDY5OSwgMC45MDY5OSwgMC45MDY5OSwgMC45MDY5OSwgMC44NTQ1OCwgMC44MzY1OSwgMC45NDk1MSwgMC45OTYxMywgMC45OTYxMywgMC45OTYxMywgMC45OTYxMywgMC45OTYxMywgMC45OTYxMywgMC44NTgxMSwgMC43ODIxNiwgMC45MDA4MywgMC45MDA4MywgMC45MDA4MywgMC45MDA4MywgMC45NTM4MSwgMC45NTM4MSwgMC45NTM4MSwgMC45NTM4MSwgMC45MTM1LCAwLjkyMTY4LCAwLjkxNTEzLCAwLjkxNTEzLCAwLjkxNTEzLCAwLjkxNTEzLCAwLjkxNTEzLCAxLjA4NTk1LCAwLjkxNjc3LCAwLjkxNjc3LCAwLjkxNjc3LCAwLjkxNjc3LCAwLjkxNjc3LCAwLjg5MzY0LCAwLjkyMzMyLCAwLjg5MzY0LCAwLjg1NTc2LCAwLjk5NjEzLCAwLjg1NTc2LCAwLjk5NjEzLCAwLjg1NTc2LCAwLjk5NjEzLCAwLjgwNzI5LCAwLjc4MjE2LCAwLjgwNzI5LCAwLjc4MjE2LCAwLjgwNzI5LCAwLjc4MjE2LCAwLjgwNzI5LCAwLjc4MjE2LCAwLjk0Mjk5LCAwLjc2NzgzLCAwLjk1OTYxLCAwLjkxNjc3LCAwLjc3NTEyLCAwLjkwMDgzLCAwLjc3NTEyLCAwLjkwMDgzLCAwLjc3NTEyLCAwLjkwMDgzLCAwLjc3NTEyLCAwLjkwMDgzLCAwLjc3NTEyLCAwLjkwMDgzLCAwLjg2NTIzLCAwLjkxMzUsIDAuODY1MjMsIDAuOTEzNSwgMC44NjUyMywgMC45MTM1LCAxLCAxLCAwLjkyMjIyLCAwLjkyMTY4LCAwLjkyMjIyLCAwLjkyMTY4LCAwLjk4NjIxLCAwLjk1MzgxLCAwLjk4NjIxLCAwLjk1MzgxLCAwLjk4NjIxLCAwLjk1MzgxLCAwLjk4NjIxLCAwLjk1MzgxLCAwLjk4NjIxLCAwLjk1MzgxLCAwLjg2MDM2LCAwLjk3MDk2LCAwLjcxNzQzLCAwLjk4OTgxLCAxLCAxLCAwLjk1Mjk4LCAwLjc5NzI2LCAwLjk1MzgxLCAxLCAxLCAwLjc5NzI2LCAwLjY4OTQsIDAuNzk3MjYsIDAuNzQzMjEsIDAuODE2OTEsIDEuMDAwNiwgMC45MjIyMiwgMC45MjE2OCwgMSwgMSwgMC45MjIyMiwgMC45MjE2OCwgMC43OTQ2NCwgMC45MjA5OCwgMC45MjE2OCwgMC45MDYzNywgMC45MTUxMywgMC45MDYzNywgMC45MTUxMywgMC45MDYzNywgMC45MTUxMywgMC45MDksIDAuODc1MTQsIDAuODA3MjksIDAuOTUwNzcsIDEsIDEsIDAuODA3MjksIDAuOTUwNzcsIDAuNzY0NjMsIDAuNzQ4LCAwLjc2NDYzLCAwLjc0OCwgMSwgMSwgMC43NjQ2MywgMC43NDgsIDEsIDEsIDAuODYyNzUsIDAuNzI2NTEsIDAuODYyNzUsIDEuMDQ1MDIsIDAuOTA2OTksIDAuOTE2NzcsIDAuOTA2OTksIDAuOTE2NzcsIDAuOTA2OTksIDAuOTE2NzcsIDAuOTA2OTksIDAuOTE2NzcsIDAuOTA2OTksIDAuOTE2NzcsIDAuOTA2OTksIDAuOTE2NzcsIDAuOTE1NCwgMC45NDIzNiwgMC44NTQ1OCwgMC44OTM2NCwgMC44NTQ1OCwgMC45MDUzMSwgMC45LCAwLjkwNTMxLCAwLjksIDAuOTA1MzEsIDAuOSwgMSwgMC45NzI3NiwgMC44NTU3NiwgMC45OTYxMywgMC44NDUsIDAuODU4MTEsIDAuOTAyNTEsIDAuOTE2NzcsIDEsIDEsIDAuODYyNzUsIDEuMDQ1MDIsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMDA4OTksIDEuMzA2MjgsIDAuODU1NzYsIDAuODAxNzgsIDAuNjY4NjIsIDAuNzkyNywgMC42OTMyMywgMC44ODEyNywgMC43MjQ1OSwgMC44OTcxMSwgMC45NTM4MSwgMC44NTU3NiwgMC44MDU5MSwgMC43ODA1LCAwLjk0NzI5LCAwLjc3NTEyLCAwLjkwNTMxLCAwLjkyMjIyLCAwLjkwNjM3LCAwLjk4NjIxLCAwLjgxNjk4LCAwLjkyNjU1LCAwLjk4NTU4LCAwLjkyMjIyLCAwLjg1MzU5LCAwLjkwNjM3LCAwLjkwOTc2LCAwLjgzODA5LCAwLjk0NTIzLCAwLjg2Mjc1LCAwLjgzNTA5LCAwLjkzMTU3LCAwLjg1MzA4LCAwLjgzMzkyLCAwLjkyMzQ2LCAwLjk4NjIxLCAwLjgzNTA5LCAwLjkyODg2LCAwLjkxMzI0LCAwLjkyMTY4LCAwLjk1MzgxLCAwLjkwNjQ2LCAwLjkyODg2LCAwLjkwNTU3LCAwLjg2ODQ3LCAwLjkwMjc2LCAwLjkxMzI0LCAwLjg2ODQyLCAwLjkyMTY4LCAwLjk5NTMxLCAwLjk1MzgxLCAwLjkyMjQsIDAuODU0MDgsIDAuOTI2OTksIDAuODY4NDcsIDEuMDA1MSwgMC45MTUxMywgMC44MDQ4NywgMC45MzQ4MSwgMSwgMC44ODE1OSwgMS4wNTIxNCwgMC45MDY0NiwgMC45NzM1NSwgMC44MTUzOSwgMC44OTM5OCwgMC44NTkyMywgMC45NTM4MSwgMC45MDY0NiwgMC45MTUxMywgMC45MDY0NiwgMC44NTkyMywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MTU0LCAwLjk0MjM2LCAwLjkxNTQsIDAuOTQyMzYsIDAuOTE1NCwgMC45NDIzNiwgMC44NTQ1OCwgMC44OTM2NCwgMC45NjY5NCwgMSwgMC44OTkwMywgMSwgMSwgMSwgMC45MTc4MiwgMC45MTc4MiwgMC45MTc4MiwgMSwgMC44OTYsIDAuODk2LCAwLjg5NiwgMC45MzMyLCAwLjkzMzIsIDAuOTU5NzMsIDEsIDEuMjYsIDEsIDEsIDAuODA0NzksIDAuODAxNzgsIDEsIDEsIDAuODU2MzMsIDEsIDEsIDEsIDEsIDAuOTcyNzYsIDEsIDEsIDEsIDAuNjk4LCAxLCAxLjM2MTQ1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjE0NTQyLCAxLCAwLjc5MTk5LCAwLjc4Njk0LCAxLjAyMDU4LCAxLjAzNDkzLCAxLjA1NDg2LCAxLCAxLCAxLjIzMDI2LCAxLjA4NTk1LCAxLjA4NTk1LCAxLCAxLjA4NTk1LCAxLjA4NTk1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjIwMDA2LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKZXhwb3J0cy5NeXJpYWRQcm9Cb2xkSXRhbGljRmFjdG9ycyA9IE15cmlhZFByb0JvbGRJdGFsaWNGYWN0b3JzOwpjb25zdCBNeXJpYWRQcm9Cb2xkSXRhbGljTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjIsCiAgbGluZUdhcDogMC4yCn07CmV4cG9ydHMuTXlyaWFkUHJvQm9sZEl0YWxpY01ldHJpY3MgPSBNeXJpYWRQcm9Cb2xkSXRhbGljTWV0cmljczsKY29uc3QgTXlyaWFkUHJvSXRhbGljRmFjdG9ycyA9IFsxLjM2ODk4LCAxLCAxLCAwLjY1NTA3LCAwLjg0OTQzLCAwLjg1NjM5LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjg2OTM2LCAwLjg4MzA3LCAwLjg2OTQ4LCAwLjg1MjgzLCAwLjg1MjgzLCAxLjA2MzgzLCAxLjAyMDU4LCAwLjc1OTQ1LCAwLjkyMTksIDAuNzU5NDUsIDEuMTczMzcsIDAuODg0NjUsIDAuODg0NjUsIDAuODg0NjUsIDAuODg0NjUsIDAuODg0NjUsIDAuODg0NjUsIDAuODg0NjUsIDAuODg0NjUsIDAuODg0NjUsIDAuODg0NjUsIDAuNzU5NDUsIDAuNzU5NDUsIDEuMDIwNTgsIDEuMDIwNTgsIDEuMDIwNTgsIDAuNjkwNDYsIDAuNzA5MjYsIDAuODUxNTgsIDAuNzc4MTIsIDAuNzY4NTIsIDAuODk1OTEsIDAuNzA0NjYsIDAuNzYxMjUsIDAuODAwOTQsIDAuODY4MjIsIDAuODM4NjQsIDAuNzI4LCAwLjc3MjEyLCAwLjc5NDc1LCAwLjkzNjM3LCAwLjg3NTE0LCAwLjg1ODgsIDAuNzYwMTMsIDAuODU4OCwgMC43MjQyMSwgMC42OTg2NiwgMC43NzU5OCwgMC44NTk5MSwgMC44MDgxMSwgMC44NzgzMiwgMC43ODExMiwgMC43NzUxMiwgMC44NTYyLCAxLjAyMjIsIDEuMTg0MTcsIDEuMDIyMiwgMS4yNzAxNCwgMC44OTkwMywgMS4xNTAxMiwgMC45Mzg1OSwgMC45NDM5OSwgMC44NDYsIDAuOTQzOTksIDAuODE0NTMsIDEuMDE4NiwgMC45NDIxOSwgMC45NjAxNywgMS4wMzA3NSwgMS4wMjE3NSwgMC45MTIsIDEuMDMwNzUsIDAuOTY5OTgsIDAuOTYwMTcsIDAuOTM4NTksIDAuOTQzOTksIDAuOTQzOTksIDAuOTU0OTMsIDAuNzQ2LCAxLjEyNjU4LCAwLjk0NTc4LCAwLjkxLCAwLjk3OSwgMC44ODIsIDAuODgyLCAwLjgzLCAwLjg1MDM0LCAwLjgzNTM3LCAwLjg1MDM0LCAxLjAyMDU4LCAwLjcwODY5LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjg4NDY1LCAwLjgzNTM3LCAwLjkwMDgzLCAxLjE1MDEyLCAwLjkxNjEsIDAuOTQ1NjUsIDAuNzM1NDEsIDEuMDIwNTgsIDAuNTM2MDksIDAuNjkzNTMsIDAuNzk1MTksIDEuMDg1OTUsIDEsIDEsIDEuMTUwMTIsIDEsIDAuOTE5NzQsIDAuNzU5NDUsIDEuMTUwMTIsIDEsIDAuOTQ0NiwgMC43MzM2MSwgMC45MDA1LCAwLjkwMDUsIDAuOTAwNSwgMC42Mjg2NCwgMC44NTE1OCwgMC44NTE1OCwgMC44NTE1OCwgMC44NTE1OCwgMC44NTE1OCwgMC44NTE1OCwgMC43NzMsIDAuNzY4NTIsIDAuNzA0NjYsIDAuNzA0NjYsIDAuNzA0NjYsIDAuNzA0NjYsIDAuODM4NjQsIDAuODM4NjQsIDAuODM4NjQsIDAuODM4NjQsIDAuOTA1NjEsIDAuODc1MTQsIDAuODU4OCwgMC44NTg4LCAwLjg1ODgsIDAuODU4OCwgMC44NTg4LCAxLjAyMDU4LCAwLjg1NzUxLCAwLjg1OTkxLCAwLjg1OTkxLCAwLjg1OTkxLCAwLjg1OTkxLCAwLjc3NTEyLCAwLjc2MDEzLCAwLjg4MDc1LCAwLjkzODU5LCAwLjkzODU5LCAwLjkzODU5LCAwLjkzODU5LCAwLjkzODU5LCAwLjkzODU5LCAwLjgwNzUsIDAuODQ2LCAwLjgxNDUzLCAwLjgxNDUzLCAwLjgxNDUzLCAwLjgxNDUzLCAwLjgyNDI0LCAwLjgyNDI0LCAwLjgyNDI0LCAwLjgyNDI0LCAwLjkyNzgsIDAuOTYwMTcsIDAuOTM4NTksIDAuOTM4NTksIDAuOTM4NTksIDAuOTM4NTksIDAuOTM4NTksIDEuMDg1OTUsIDAuODU2MiwgMC45NDU3OCwgMC45NDU3OCwgMC45NDU3OCwgMC45NDU3OCwgMC44ODIsIDAuOTQ1NzgsIDAuODgyLCAwLjg1MTU4LCAwLjkzODU5LCAwLjg1MTU4LCAwLjkzODU5LCAwLjg1MTU4LCAwLjkzODU5LCAwLjc2ODUyLCAwLjg0NiwgMC43Njg1MiwgMC44NDYsIDAuNzY4NTIsIDAuODQ2LCAwLjc2ODUyLCAwLjg0NiwgMC44OTU5MSwgMC44NTQ0LCAwLjkwNTYxLCAwLjk0Mzk5LCAwLjcwNDY2LCAwLjgxNDUzLCAwLjcwNDY2LCAwLjgxNDUzLCAwLjcwNDY2LCAwLjgxNDUzLCAwLjcwNDY2LCAwLjgxNDUzLCAwLjcwNDY2LCAwLjgxNDUzLCAwLjgwMDk0LCAwLjk0MjE5LCAwLjgwMDk0LCAwLjk0MjE5LCAwLjgwMDk0LCAwLjk0MjE5LCAxLCAxLCAwLjg2ODIyLCAwLjk2MDE3LCAwLjg2ODIyLCAwLjk2MDE3LCAwLjgzODY0LCAwLjgyNDI0LCAwLjgzODY0LCAwLjgyNDI0LCAwLjgzODY0LCAwLjgyNDI0LCAwLjgzODY0LCAxLjAzMDc1LCAwLjgzODY0LCAwLjgyNDI0LCAwLjgxNDAyLCAxLjAyNzM4LCAwLjcyOCwgMS4wMjE3NSwgMSwgMSwgMC45MTIsIDAuNzk0NzUsIDEuMDMwNzUsIDEsIDEsIDAuNzk0NzUsIDAuODM5MTEsIDAuNzk0NzUsIDAuNjYyNjYsIDAuODA1NTMsIDEuMDY2NzYsIDAuODc1MTQsIDAuOTYwMTcsIDEsIDEsIDAuODc1MTQsIDAuOTYwMTcsIDAuODY4NjUsIDAuODczOTYsIDAuOTYwMTcsIDAuODU4OCwgMC45Mzg1OSwgMC44NTg4LCAwLjkzODU5LCAwLjg1ODgsIDAuOTM4NTksIDAuODY3LCAwLjg0NzU5LCAwLjcyNDIxLCAwLjk1NDkzLCAxLCAxLCAwLjcyNDIxLCAwLjk1NDkzLCAwLjY5ODY2LCAwLjc0NiwgMC42OTg2NiwgMC43NDYsIDEsIDEsIDAuNjk4NjYsIDAuNzQ2LCAxLCAxLCAwLjc3NTk4LCAwLjg4NDE3LCAwLjc3NTk4LCAxLjEyNjU4LCAwLjg1OTkxLCAwLjk0NTc4LCAwLjg1OTkxLCAwLjk0NTc4LCAwLjg1OTkxLCAwLjk0NTc4LCAwLjg1OTkxLCAwLjk0NTc4LCAwLjg1OTkxLCAwLjk0NTc4LCAwLjg1OTkxLCAwLjk0NTc4LCAwLjg3ODMyLCAwLjk3OSwgMC43NzUxMiwgMC44ODIsIDAuNzc1MTIsIDAuODU2MiwgMC44MywgMC44NTYyLCAwLjgzLCAwLjg1NjIsIDAuODMsIDEsIDAuODg0NjUsIDAuODUxNTgsIDAuOTM4NTksIDAuNzczLCAwLjgwNzUsIDAuODU3NTEsIDAuODU2MiwgMSwgMSwgMC43NzU5OCwgMS4xMjY1OCwgMS4xNTAxMiwgMS4xNTAxMiwgMS4xNTAxMiwgMS4xNTAxMiwgMS4xNTAxMiwgMS4xNTMxMywgMS4xNTAxMiwgMS4xNTAxMiwgMS4xNTAxMiwgMS4wODEwNiwgMS4wMzkwMSwgMC44NTE1OCwgMC43NzAyNSwgMC42MjI2NCwgMC43NjQ2LCAwLjY1MzUxLCAwLjg2MDI2LCAwLjY5NDYxLCAwLjg5OTQ3LCAxLjAzMDc1LCAwLjg1MTU4LCAwLjc3ODEyLCAwLjc2NDQ5LCAwLjg4ODM2LCAwLjcwNDY2LCAwLjg1NjIsIDAuODY4MjIsIDAuODU4OCwgMC44Mzg2NCwgMC43NzIxMiwgMC44NTMwOCwgMC45MzYzNywgMC44NzUxNCwgMC44MjM1MiwgMC44NTg4LCAwLjg1NzAxLCAwLjc2MDEzLCAwLjg5MDU4LCAwLjc3NTk4LCAwLjgxNTYsIDAuODI1NjUsIDAuNzgxMTIsIDAuNzc4OTksIDAuODkzODYsIDAuODM4NjQsIDAuODE1NiwgMC45NDg2LCAwLjkyMzg4LCAwLjk2MTg2LCAxLjAzMDc1LCAwLjkxMTIzLCAwLjk0ODYsIDAuOTMyOTgsIDAuODc4LCAwLjkzOTQyLCAwLjkyMzg4LCAwLjg0NTk2LCAwLjk2MTg2LCAwLjk1MTE5LCAxLjAzMDc1LCAwLjkyMiwgMC44ODc4NywgMC45NTgyOSwgMC44OCwgMC45MzU1OSwgMC45Mzg1OSwgMC43ODgxNSwgMC45Mzc1OCwgMSwgMC44OTIxNywgMS4wMzczNywgMC45MTEyMywgMC45Mzk2OSwgMC43NzQ4NywgMC44NTc2OSwgMC44Njc5OSwgMS4wMzA3NSwgMC45MTEyMywgMC45Mzg1OSwgMC45MTEyMywgMC44Njc5OSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC44NzgzMiwgMC45NzksIDAuODc4MzIsIDAuOTc5LCAwLjg3ODMyLCAwLjk3OSwgMC43NzUxMiwgMC44ODIsIDAuOTIxOSwgMSwgMC44OTkwMywgMSwgMSwgMSwgMC44NzMyMSwgMC44NzMyMSwgMC44NzMyMSwgMSwgMS4wMjcsIDEuMDI3LCAxLjAyNywgMC44Njg0NywgMC44Njg0NywgMC43OTEyMSwgMSwgMS4xMjQsIDEsIDEsIDAuNzM1NzIsIDAuNzM1NzIsIDEsIDEsIDAuODUwMzQsIDEsIDEsIDEsIDEsIDAuODg0NjUsIDEsIDEsIDEsIDAuNjY5LCAxLCAxLjM2MTQ1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjA0ODI4LCAxLCAwLjc0OTQ4LCAwLjc1MTg3LCAxLjAyMDU4LCAwLjk4MzkxLCAxLjAyMTE5LCAxLCAxLCAxLjA2MjMzLCAxLjA4NTk1LCAxLjA4NTk1LCAxLCAxLjA4NTk1LCAxLjA4NTk1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjA1MjMzLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKZXhwb3J0cy5NeXJpYWRQcm9JdGFsaWNGYWN0b3JzID0gTXlyaWFkUHJvSXRhbGljRmFjdG9yczsKY29uc3QgTXlyaWFkUHJvSXRhbGljTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjIsCiAgbGluZUdhcDogMC4yCn07CmV4cG9ydHMuTXlyaWFkUHJvSXRhbGljTWV0cmljcyA9IE15cmlhZFByb0l0YWxpY01ldHJpY3M7CmNvbnN0IE15cmlhZFByb1JlZ3VsYXJGYWN0b3JzID0gWzEuMzY4OTgsIDEsIDEsIDAuNzYzMDUsIDAuODI3ODQsIDAuOTQ5MzUsIDAuODkzNjQsIDAuOTIyNDEsIDAuODkwNzMsIDAuOTA3MDYsIDAuOTg0NzIsIDAuODUyODMsIDAuODUyODMsIDEuMDY2NCwgMS4wMjA1OCwgMC43NDUwNSwgMC45MjE5LCAwLjc0NTA1LCAxLjIzNDU2LCAwLjkyMjQxLCAwLjkyMjQxLCAwLjkyMjQxLCAwLjkyMjQxLCAwLjkyMjQxLCAwLjkyMjQxLCAwLjkyMjQxLCAwLjkyMjQxLCAwLjkyMjQxLCAwLjkyMjQxLCAwLjc0NTA1LCAwLjc0NTA1LCAxLjAyMDU4LCAxLjAyMDU4LCAxLjAyMDU4LCAwLjczMDAyLCAwLjcyNjAxLCAwLjkxNzU1LCAwLjgxMjYsIDAuODAzMTQsIDAuOTIyMjIsIDAuNzM3NjQsIDAuNzk3MjYsIDAuODMwNTEsIDAuOTAyODQsIDAuODYwMjMsIDAuNzQsIDAuODEyNiwgMC44NDg2OSwgMC45NjUxOCwgMC45MTExNSwgMC44ODU4LCAwLjc5NzYxLCAwLjg4NTgsIDAuNzQ0OTgsIDAuNzM5MTQsIDAuODEzNjMsIDAuODk1OTEsIDAuODM2NTksIDAuODk2MzMsIDAuODU2MDgsIDAuODExMSwgMC45MDUzMSwgMS4wMjIyLCAxLjIyNzM2LCAxLjAyMjIsIDEuMjcwMTQsIDAuODk5MDMsIDAuOTAwODgsIDAuODY2NjcsIDEuMDIzMSwgMC44OTYsIDEuMDE0MTEsIDAuOTAwODMsIDEuMDUwOTksIDEuMDA1MTIsIDAuOTk3OTMsIDEuMDUzMjYsIDEuMDkzNzcsIDAuOTM4LCAxLjA2MjI2LCAxLjAwMTE5LCAwLjk5NzkzLCAwLjk4NzE0LCAxLjAyMzEsIDEuMDEyMzEsIDAuOTgxOTYsIDAuNzkyLCAxLjE5MTM3LCAwLjk5MDc0LCAwLjk2MiwgMS4wMTkxNSwgMC45MjYsIDAuOTQyLCAwLjg1NiwgMC44NTAzNCwgMC45MjAwNiwgMC44NTAzNCwgMS4wMjA1OCwgMC42OTA2NywgMC45MjI0MSwgMC45MjI0MSwgMC45MjI0MSwgMC45MjI0MSwgMC45MjAwNiwgMC45MzMyLCAwLjkwMDg4LCAwLjkxODgyLCAwLjkzNDg0LCAwLjc1MzM5LCAxLjAyMDU4LCAwLjU2ODY2LCAwLjU0MzI0LCAwLjc5NTE5LCAxLjA4NTk1LCAxLCAxLCAwLjkwMDg4LCAxLCAwLjk1MzI1LCAwLjc0NTA1LCAwLjkwMDg4LCAxLCAwLjk3MTk4LCAwLjc1MzM5LCAwLjkxMDA5LCAwLjkxMDA5LCAwLjkxMDA5LCAwLjY2NDY2LCAwLjkxNzU1LCAwLjkxNzU1LCAwLjkxNzU1LCAwLjkxNzU1LCAwLjkxNzU1LCAwLjkxNzU1LCAwLjc4OCwgMC44MDMxNCwgMC43Mzc2NCwgMC43Mzc2NCwgMC43Mzc2NCwgMC43Mzc2NCwgMC44NjAyMywgMC44NjAyMywgMC44NjAyMywgMC44NjAyMywgMC45MjkxNSwgMC45MTExNSwgMC44ODU4LCAwLjg4NTgsIDAuODg1OCwgMC44ODU4LCAwLjg4NTgsIDEuMDIwNTgsIDAuODg1OCwgMC44OTU5MSwgMC44OTU5MSwgMC44OTU5MSwgMC44OTU5MSwgMC44MTExLCAwLjc5NjExLCAwLjg5NzEzLCAwLjg2NjY3LCAwLjg2NjY3LCAwLjg2NjY3LCAwLjg2NjY3LCAwLjg2NjY3LCAwLjg2NjY3LCAwLjg2OTM2LCAwLjg5NiwgMC45MDA4MywgMC45MDA4MywgMC45MDA4MywgMC45MDA4MywgMC44NDIyNCwgMC44NDIyNCwgMC44NDIyNCwgMC44NDIyNCwgMC45NzI3NiwgMC45OTc5MywgMC45ODcxNCwgMC45ODcxNCwgMC45ODcxNCwgMC45ODcxNCwgMC45ODcxNCwgMS4wODU5NSwgMC44OTg3NiwgMC45OTA3NCwgMC45OTA3NCwgMC45OTA3NCwgMC45OTA3NCwgMC45NDIsIDEuMDIzMSwgMC45NDIsIDAuOTE3NTUsIDAuODY2NjcsIDAuOTE3NTUsIDAuODY2NjcsIDAuOTE3NTUsIDAuODY2NjcsIDAuODAzMTQsIDAuODk2LCAwLjgwMzE0LCAwLjg5NiwgMC44MDMxNCwgMC44OTYsIDAuODAzMTQsIDAuODk2LCAwLjkyMjIyLCAwLjkzMzcyLCAwLjkyOTE1LCAxLjAxNDExLCAwLjczNzY0LCAwLjkwMDgzLCAwLjczNzY0LCAwLjkwMDgzLCAwLjczNzY0LCAwLjkwMDgzLCAwLjczNzY0LCAwLjkwMDgzLCAwLjczNzY0LCAwLjkwMDgzLCAwLjgzMDUxLCAxLjAwNTEyLCAwLjgzMDUxLCAxLjAwNTEyLCAwLjgzMDUxLCAxLjAwNTEyLCAxLCAxLCAwLjkwMjg0LCAwLjk5NzkzLCAwLjkwOTc2LCAwLjk5NzkzLCAwLjg2MDIzLCAwLjg0MjI0LCAwLjg2MDIzLCAwLjg0MjI0LCAwLjg2MDIzLCAwLjg0MjI0LCAwLjg2MDIzLCAxLjA1MzI2LCAwLjg2MDIzLCAwLjg0MjI0LCAwLjgyODczLCAxLjA3NDY5LCAwLjc0LCAxLjA5Mzc3LCAxLCAxLCAwLjkzOCwgMC44NDg2OSwgMS4wNjIyNiwgMSwgMSwgMC44NDg2OSwgMC44MzcwNCwgMC44NDg2OSwgMC44MTQ0MSwgMC44NTU4OCwgMS4wODkyNywgMC45MTExNSwgMC45OTc5MywgMSwgMSwgMC45MTExNSwgMC45OTc5MywgMC45MTg4NywgMC45MDk5MSwgMC45OTc5MywgMC44ODU4LCAwLjk4NzE0LCAwLjg4NTgsIDAuOTg3MTQsIDAuODg1OCwgMC45ODcxNCwgMC44OTQsIDAuOTE0MzQsIDAuNzQ0OTgsIDAuOTgxOTYsIDEsIDEsIDAuNzQ0OTgsIDAuOTgxOTYsIDAuNzM5MTQsIDAuNzkyLCAwLjczOTE0LCAwLjc5MiwgMSwgMSwgMC43MzkxNCwgMC43OTIsIDEsIDEsIDAuODEzNjMsIDAuOTA0LCAwLjgxMzYzLCAxLjE5MTM3LCAwLjg5NTkxLCAwLjk5MDc0LCAwLjg5NTkxLCAwLjk5MDc0LCAwLjg5NTkxLCAwLjk5MDc0LCAwLjg5NTkxLCAwLjk5MDc0LCAwLjg5NTkxLCAwLjk5MDc0LCAwLjg5NTkxLCAwLjk5MDc0LCAwLjg5NjMzLCAxLjAxOTE1LCAwLjgxMTEsIDAuOTQyLCAwLjgxMTEsIDAuOTA1MzEsIDAuODU2LCAwLjkwNTMxLCAwLjg1NiwgMC45MDUzMSwgMC44NTYsIDEsIDAuOTIyNDEsIDAuOTE3NTUsIDAuODY2NjcsIDAuNzg4LCAwLjg2OTM2LCAwLjg4NTgsIDAuODk4NzYsIDEsIDEsIDAuODEzNjMsIDEuMTkxMzcsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAwODgsIDAuOTAzODgsIDEuMDM5MDEsIDAuOTIxMzgsIDAuNzgxMDUsIDAuNzE1NCwgMC44NjE2OSwgMC44MDUxMywgMC45NDAwNywgMC44MjUyOCwgMC45ODYxMiwgMS4wNjIyNiwgMC45MTc1NSwgMC44MTI2LCAwLjgxODg0LCAwLjkyODE5LCAwLjczNzY0LCAwLjkwNTMxLCAwLjkwMjg0LCAwLjg4NTgsIDAuODYwMjMsIDAuODEyNiwgMC45MTE3MiwgMC45NjUxOCwgMC45MTExNSwgMC44MzA4OSwgMC44ODU4LCAwLjg3NzkxLCAwLjc5NzYxLCAwLjg5Mjk3LCAwLjgxMzYzLCAwLjg4MTU3LCAwLjg5OTkyLCAwLjg1NjA4LCAwLjgxOTkyLCAwLjk0MzA3LCAwLjg2MDIzLCAwLjg4MTU3LCAwLjk1MzA4LCAwLjk4Njk5LCAwLjk5NzkzLCAxLjA2MjI2LCAwLjk1ODE3LCAwLjk1MzA4LCAwLjk3MzU4LCAwLjkyOCwgMC45ODA4OCwgMC45ODY5OSwgMC45Mjc2MSwgMC45OTc5MywgMC45NjAxNywgMS4wNjIyNiwgMC45ODYsIDAuOTQ0LCAwLjk1OTc4LCAwLjkzOCwgMC45NjcwNSwgMC45ODcxNCwgMC44MDQ0MiwgMC45ODk3MiwgMSwgMC44OTc2MiwgMS4wNDU1MiwgMC45NTgxNywgMC45OTAwNywgMC44NzA2NCwgMC45MTg3OSwgMC44ODg4OCwgMS4wNjIyNiwgMC45NTgxNywgMC45ODcxNCwgMC45NTgxNywgMC44ODg4OCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC44OTYzMywgMS4wMTkxNSwgMC44OTYzMywgMS4wMTkxNSwgMC44OTYzMywgMS4wMTkxNSwgMC44MTExLCAwLjk0MiwgMC45MjE5LCAxLCAwLjg5OTAzLCAxLCAxLCAxLCAwLjkzMTczLCAwLjkzMTczLCAwLjkzMTczLCAxLCAxLjA2MzA0LCAxLjA2MzA0LCAxLjA2OTA0LCAwLjg5OTAzLCAwLjg5OTAzLCAwLjgwNTQ5LCAxLCAxLjE1NiwgMSwgMSwgMC43NjU3NSwgMC43NjU3NSwgMSwgMSwgMC43MjQ1OCwgMSwgMSwgMSwgMSwgMC45MjI0MSwgMSwgMSwgMSwgMC42MTksIDEsIDEuMzYxNDUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDcyNTcsIDEsIDAuNzQ3MDUsIDAuNzExMTksIDEuMDIwNTgsIDEuMDI0LCAxLjAyMTE5LCAxLCAxLCAxLjE1MzYsIDEuMDg1OTUsIDEuMDg1OTUsIDEsIDEuMDg1OTUsIDEuMDg1OTUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDU2MzgsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpleHBvcnRzLk15cmlhZFByb1JlZ3VsYXJGYWN0b3JzID0gTXlyaWFkUHJvUmVndWxhckZhY3RvcnM7CmNvbnN0IE15cmlhZFByb1JlZ3VsYXJNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMiwKICBsaW5lR2FwOiAwLjIKfTsKZXhwb3J0cy5NeXJpYWRQcm9SZWd1bGFyTWV0cmljcyA9IE15cmlhZFByb1JlZ3VsYXJNZXRyaWNzOwoKLyoqKi8gfSksCi8qIDE5MSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuU2Vnb2V1aVJlZ3VsYXJNZXRyaWNzID0gZXhwb3J0cy5TZWdvZXVpUmVndWxhckZhY3RvcnMgPSBleHBvcnRzLlNlZ29ldWlJdGFsaWNNZXRyaWNzID0gZXhwb3J0cy5TZWdvZXVpSXRhbGljRmFjdG9ycyA9IGV4cG9ydHMuU2Vnb2V1aUJvbGRNZXRyaWNzID0gZXhwb3J0cy5TZWdvZXVpQm9sZEl0YWxpY01ldHJpY3MgPSBleHBvcnRzLlNlZ29ldWlCb2xkSXRhbGljRmFjdG9ycyA9IGV4cG9ydHMuU2Vnb2V1aUJvbGRGYWN0b3JzID0gdm9pZCAwOwpjb25zdCBTZWdvZXVpQm9sZEZhY3RvcnMgPSBbMS43NjczOCwgMSwgMSwgMC45OTI5NywgMC45ODI0LCAxLjA0MDE2LCAxLjA2NDk3LCAxLjAzNDI0LCAwLjk3NTI5LCAxLjE3NjQ3LCAxLjIzMjAzLCAxLjEwODUsIDEuMTA4NSwgMS4xNjkzOSwgMS4yMTA3LCAwLjk3NTQsIDEuMjE0MDgsIDAuOTc1NCwgMS41OTU3OCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMC44MTM3OCwgMC44MTM3OCwgMS4yMTA3LCAxLjIxMDcsIDEuMjEwNywgMC43MTcwMywgMC45Nzg0NywgMC45NzM2MywgMC44ODc3NiwgMC44NjQxLCAxLjAyMDk2LCAwLjc5Nzk1LCAwLjg1MTMyLCAwLjkxNCwgMS4wNjA4NSwgMS4xNDA2LCAwLjgwMDcsIDAuODk4NTgsIDAuODM2OTMsIDEuMTQ4ODksIDEuMDkzOTgsIDAuOTc0ODksIDAuOTIwOTQsIDAuOTc0ODksIDAuOTAzOTksIDAuODQwNDEsIDAuOTU5MjMsIDEuMDAxMzUsIDEsIDEuMDY0NjcsIDAuOTgyNDMsIDAuOTA5OTYsIDAuOTkzNjEsIDEuMTA4NSwgMS41Njk0MiwgMS4xMDg1LCAxLjIxMDcsIDAuNzQ2MjcsIDAuOTQyODIsIDAuOTY3NTIsIDEuMDE1MTksIDAuODYzMDQsIDEuMDEzNTksIDAuOTcyNzgsIDEuMTUxMDMsIDEuMDEzNTksIDAuOTg1NjEsIDEuMDIyODUsIDEuMDIyODUsIDEuMDA1MjcsIDEuMDIyODUsIDEuMDMwMiwgMC45OTA0MSwgMS4wMDA4LCAxLjAxNTE5LCAxLjAxMzU5LCAxLjAyMjU4LCAwLjc5MTA0LCAxLjE2ODYyLCAwLjk5MDQxLCAwLjk3NDU0LCAxLjAyNTExLCAwLjk5Mjk4LCAwLjk2NzUyLCAwLjk1ODAxLCAwLjk0ODU2LCAxLjE2NTc5LCAwLjk0ODU2LCAxLjIxMDcsIDAuOTgyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMSwgMS4wMzQyNCwgMS4xNjU3OSwgMC44NzI3LCAxLjM4NzEsIDEuMTg2MjIsIDEuMTA4MTgsIDEuMDQ0NzgsIDEuMjEwNywgMS4xODYyMiwgMC43NTE1NSwgMC45NDk5NCwgMS4yODgyNiwgMS4yMTQwOCwgMS4yMTQwOCwgMC45MTA1NiwgMSwgMC45MTU3MiwgMC45NzU0LCAwLjY0NjYzLCAxLjE4MzI4LCAxLjI0ODY2LCAxLjA0NDc4LCAxLjE0MTY5LCAxLjE1NzQ5LCAxLjE3Mzg5LCAwLjcxNzAzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjkzNTA2LCAwLjg2NDEsIDAuNzk3OTUsIDAuNzk3OTUsIDAuNzk3OTUsIDAuNzk3OTUsIDEuMTQwNiwgMS4xNDA2LCAxLjE0MDYsIDEuMTQwNiwgMS4wMjA5NiwgMS4wOTM5OCwgMC45NzQyNiwgMC45NzQyNiwgMC45NzQyNiwgMC45NzQyNiwgMC45NzQyNiwgMS4yMTA3LCAwLjk3NDg5LCAxLjAwMTM1LCAxLjAwMTM1LCAxLjAwMTM1LCAxLjAwMTM1LCAwLjkwOTk2LCAwLjkyMDk0LCAxLjAyNzk4LCAwLjk2NzUyLCAwLjk2NzUyLCAwLjk2NzUyLCAwLjk2NzUyLCAwLjk2NzUyLCAwLjk2NzUyLCAwLjkzMTM2LCAwLjg2MzA0LCAwLjk3Mjc4LCAwLjk3Mjc4LCAwLjk3Mjc4LCAwLjk3Mjc4LCAxLjAyMjg1LCAxLjAyMjg1LCAxLjAyMjg1LCAxLjAyMjg1LCAwLjk3MTIyLCAwLjk5MDQxLCAxLCAxLCAxLCAxLCAxLCAxLjI4ODI2LCAxLjAwMDgsIDAuOTkwNDEsIDAuOTkwNDEsIDAuOTkwNDEsIDAuOTkwNDEsIDAuOTY3NTIsIDEuMDE1MTksIDAuOTY3NTIsIDAuOTczNjMsIDAuOTY3NTIsIDAuOTczNjMsIDAuOTY3NTIsIDAuOTczNjMsIDAuOTY3NTIsIDAuODY0MSwgMC44NjMwNCwgMC44NjQxLCAwLjg2MzA0LCAwLjg2NDEsIDAuODYzMDQsIDAuODY0MSwgMC44NjMwNCwgMS4wMjA5NiwgMS4wMzA1NywgMS4wMjA5NiwgMS4wMzUxNywgMC43OTc5NSwgMC45NzI3OCwgMC43OTc5NSwgMC45NzI3OCwgMC43OTc5NSwgMC45NzI3OCwgMC43OTc5NSwgMC45NzI3OCwgMC43OTc5NSwgMC45NzI3OCwgMC45MTQsIDEuMDEzNTksIDAuOTE0LCAxLjAxMzU5LCAwLjkxNCwgMS4wMTM1OSwgMSwgMSwgMS4wNjA4NSwgMC45ODU2MSwgMS4wNjA4NSwgMS4wMDg3OSwgMS4xNDA2LCAxLjAyMjg1LCAxLjE0MDYsIDEuMDIyODUsIDEuMTQwNiwgMS4wMjI4NSwgMS4xNDA2LCAxLjAyMjg1LCAxLjE0MDYsIDEuMDIyODUsIDAuOTcxMzgsIDEuMDg2OTIsIDAuODAwNywgMS4wMjI4NSwgMSwgMSwgMS4wMDUyNywgMC44MzY5MywgMS4wMjI4NSwgMSwgMSwgMC44MzY5MywgMC45NDU1LCAwLjgzNjkzLCAwLjkwNDE4LCAwLjgzNjkzLCAxLjEzMDA1LCAxLjA5Mzk4LCAwLjk5MDQxLCAxLCAxLCAxLjA5Mzk4LCAwLjk5MDQxLCAwLjk2NjkyLCAxLjA5MjUxLCAwLjk5MDQxLCAwLjk3NDg5LCAxLjAwMDgsIDAuOTc0ODksIDEuMDAwOCwgMC45NzQ4OSwgMS4wMDA4LCAwLjkzOTk0LCAwLjk3OTMxLCAwLjkwMzk5LCAxLjAyMjU4LCAxLCAxLCAwLjkwMzk5LCAxLjAyMjU4LCAwLjg0MDQxLCAwLjc5MTA0LCAwLjg0MDQxLCAwLjc5MTA0LCAwLjg0MDQxLCAwLjc5MTA0LCAwLjg0MDQxLCAwLjc5MTA0LCAxLCAxLCAwLjk1OTIzLCAxLjA3MDM0LCAwLjk1OTIzLCAxLjE2ODYyLCAxLjAwMTM1LCAwLjk5MDQxLCAxLjAwMTM1LCAwLjk5MDQxLCAxLjAwMTM1LCAwLjk5MDQxLCAxLjAwMTM1LCAwLjk5MDQxLCAxLjAwMTM1LCAwLjk5MDQxLCAxLjAwMTM1LCAwLjk5MDQxLCAxLjA2NDY3LCAxLjAyNTExLCAwLjkwOTk2LCAwLjk2NzUyLCAwLjkwOTk2LCAwLjk5MzYxLCAwLjk1ODAxLCAwLjk5MzYxLCAwLjk1ODAxLCAwLjk5MzYxLCAwLjk1ODAxLCAxLjA3NzMzLCAxLjAzNDI0LCAwLjk3MzYzLCAwLjk2NzUyLCAwLjkzNTA2LCAwLjkzMTM2LCAwLjk3NDg5LCAxLjAwMDgsIDEsIDEsIDAuOTU5MjMsIDEuMTY4NjIsIDEuMTUxMDMsIDEuMTUxMDMsIDEuMDExNzMsIDEuMDM5NTksIDAuNzU5NTMsIDAuODEzNzgsIDAuNzk5MTIsIDEuMTUxMDMsIDEuMjE5OTQsIDAuOTUxNjEsIDAuODc4MTUsIDEuMDExNDksIDAuODE1MjUsIDAuNzY3NiwgMC45ODE2NywgMS4wMTEzNCwgMS4wMjU0NiwgMC44NDA5NywgMS4wMzA4OSwgMS4xODEwMiwgMC45NzM2MywgMC44ODc3NiwgMC44NTEzNCwgMC45NzgyNiwgMC43OTc5NSwgMC45OTM2MSwgMS4wNjA4NSwgMC45NzQ4OSwgMS4xNDA2LCAwLjg5ODU4LCAxLjAzODgsIDEuMTQ4ODksIDEuMDkzOTgsIDAuODYwMzksIDAuOTc0ODksIDEuMDU5NSwgMC45MjA5NCwgMC45NDc5MywgMC45NTkyMywgMC45MDk5NiwgMC45OTM0NiwgMC45ODI0MywgMS4wMjExMiwgMC45NTQ5MywgMS4xNDA2LCAwLjkwOTk2LCAxLjAzNTc0LCAxLjAyNTk3LCAxLjAwMDgsIDEuMTgxMDIsIDEuMDY2MjgsIDEuMDM1NzQsIDEuMDE5MiwgMS4wMTkzMiwgMS4wMDg4NiwgMC45NzUzMSwgMS4wMTA2LCAxLjAwMDgsIDEuMTMxODksIDEuMTgxMDIsIDEuMDIyNzcsIDAuOTg2ODMsIDEuMDAxNiwgMC45OTU2MSwgMS4wNzIzNywgMS4wMDA4LCAwLjkwNDM0LCAwLjk5OTIxLCAwLjkzODAzLCAwLjg5NjUsIDEuMjMwODUsIDEuMDY2MjgsIDEuMDQ5ODMsIDAuOTYyNjgsIDEuMDQ5OSwgMC45ODQzOSwgMS4xODEwMiwgMS4wNjYyOCwgMS4wMDA4LCAxLjA2NjI4LCAwLjk4NDM5LCAwLjc5Nzk1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjA5NDY2LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk3Mjc4LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjAyMDY1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLjA2NDY3LCAxLjAyNTExLCAxLjA2NDY3LCAxLjAyNTExLCAxLjA2NDY3LCAxLjAyNTExLCAwLjkwOTk2LCAwLjk2NzUyLCAxLCAxLjIxNDA4LCAwLjg5OTAzLCAxLCAxLCAwLjc1MTU1LCAxLjA0Mzk0LCAxLjA0Mzk0LCAxLjA0Mzk0LCAxLjA0Mzk0LCAwLjk4NjMzLCAwLjk4NjMzLCAwLjk4NjMzLCAwLjczMDQ3LCAwLjczMDQ3LCAxLjIwNjQyLCAwLjkxMjExLCAxLjI1NjM1LCAxLjIyMiwgMS4wMjk1NiwgMS4wMzM3MiwgMS4wMzM3MiwgMC45NjAzOSwgMS4yNDYzMywgMSwgMS4xMjQ1NCwgMC45MzUwMywgMS4wMzQyNCwgMS4xOTY4NywgMS4wMzQyNCwgMSwgMSwgMSwgMC43NzEsIDEsIDEsIDEuMTU3NDksIDEuMTU3NDksIDEuMTU3NDksIDEuMTA5NDgsIDAuODYyNzksIDAuOTQ0MzQsIDAuODYyNzksIDAuOTQ0MzQsIDAuODYxODIsIDEsIDEsIDEuMTY4OTcsIDEsIDAuOTYwODUsIDAuOTAxMzcsIDEuMjEwNywgMS4xODQxNiwgMS4xMzk3MywgMC42OTgyNSwgMC45NzE2LCAyLjEwMzM5LCAxLjI5MDA0LCAxLjI5MDA0LCAxLjIxMTcyLCAxLjI5MDA0LCAxLjI5MDA0LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjQyNjAzLCAxLCAwLjk5ODYyLCAwLjk5ODYyLCAxLCAwLjg3MDI1LCAwLjg3MDI1LCAwLjg3MDI1LCAwLjg3MDI1LCAxLjE4ODc0LCAxLjQyNjAzLCAxLCAxLjQyNjAzLCAxLjQyNjAzLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLjI4ODYsIDEuMDQzMTUsIDEuMTUyOTYsIDEuMzQxNjMsIDEsIDEsIDEsIDEuMDkxOTMsIDEuMDkxOTMsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpleHBvcnRzLlNlZ29ldWlCb2xkRmFjdG9ycyA9IFNlZ29ldWlCb2xkRmFjdG9yczsKY29uc3QgU2Vnb2V1aUJvbGRNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMzMwMDgsCiAgbGluZUdhcDogMAp9OwpleHBvcnRzLlNlZ29ldWlCb2xkTWV0cmljcyA9IFNlZ29ldWlCb2xkTWV0cmljczsKY29uc3QgU2Vnb2V1aUJvbGRJdGFsaWNGYWN0b3JzID0gWzEuNzY3MzgsIDEsIDEsIDAuOTg5NDYsIDEuMDM5NTksIDEuMDQwMTYsIDEuMDI4MDksIDEuMDM2LCAwLjk3NjM5LCAxLjEwOTUzLCAxLjIzMjAzLCAxLjExMTQ0LCAxLjExMTQ0LCAxLjE2OTM5LCAxLjIxMjM3LCAwLjk3NTQsIDEuMjEyNjEsIDAuOTc1NCwgMS41OTc1NCwgMS4wMzYsIDEuMDM2LCAxLjAzNiwgMS4wMzYsIDEuMDM2LCAxLjAzNiwgMS4wMzYsIDEuMDM2LCAxLjAzNiwgMS4wMzYsIDAuODEzNzgsIDAuODEzNzgsIDEuMjEyMzcsIDEuMjEyMzcsIDEuMjEyMzcsIDAuNzM1NDEsIDAuOTc4NDcsIDAuOTczNjMsIDAuODk3MjMsIDAuODc4OTcsIDEuMDQyNiwgMC43OTQyOSwgMC44NTI5MiwgMC45MTE0OSwgMS4wNTgxNSwgMS4xNDA2LCAwLjc5NjMxLCAwLjkwMTI4LCAwLjgzODUzLCAxLjA0Mzk2LCAxLjEwNjE1LCAwLjk3NTUyLCAwLjk0NDM2LCAwLjk3NTUyLCAwLjg4NjQxLCAwLjgwNTI3LCAwLjk2MDgzLCAxLjAwMTM1LCAxLCAxLjA2Nzc3LCAwLjk4MTcsIDAuOTExNDIsIDAuOTkzNjEsIDEuMTExNDQsIDEuNTcyOTMsIDEuMTExNDQsIDEuMjEyMzcsIDAuNzQ2MjcsIDEuMzE4MTgsIDEuMDY1ODUsIDAuOTcwNDIsIDAuODMwNTUsIDAuOTcwNDIsIDAuOTM1MDMsIDEuMTI2MSwgMC45NzA0MiwgMC45NzkyMiwgMS4xNDIzNiwgMC45NDU1MiwgMS4wMTA1NCwgMS4xNDIzNiwgMS4wMjQ3MSwgMC45NzkyMiwgMC45NDE2NSwgMC45NzA0MiwgMC45NzA0MiwgMS4wMjc2LCAwLjc4OTI5LCAxLjEyNjEsIDAuOTc5MjIsIDAuOTU4NzQsIDEuMDIxOTcsIDAuOTg1MDcsIDAuOTY3NTIsIDAuOTcxNjgsIDAuOTUxMDcsIDEuMTY1NzksIDAuOTUxMDcsIDEuMjEyMzcsIDEuMDM5NTksIDEuMDM2LCAxLjAzNiwgMSwgMS4wMzYsIDEuMTY1NzksIDAuODczNTcsIDEuMzE4MTgsIDEuMTg3NTQsIDEuMjY3ODEsIDEuMDUzNTYsIDEuMjEyMzcsIDEuMTg2MjIsIDAuNzk0ODcsIDAuOTQ5OTQsIDEuMjkwMDQsIDEuMjQwNDcsIDEuMjQwNDcsIDEuMzE4MTgsIDEsIDAuOTE0ODQsIDAuOTc1NCwgMS4zMTgxOCwgMS4xMzQ5LCAxLjI0ODY2LCAxLjA1MzU2LCAxLjEzOTM0LCAxLjE1NTc0LCAxLjE3Mzg5LCAwLjczNTQxLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk0Mzg1LCAwLjg3ODk3LCAwLjc5NDI5LCAwLjc5NDI5LCAwLjc5NDI5LCAwLjc5NDI5LCAxLjE0MDYsIDEuMTQwNiwgMS4xNDA2LCAxLjE0MDYsIDEuMDQyNiwgMS4xMDYxNSwgMC45NzU1MiwgMC45NzU1MiwgMC45NzU1MiwgMC45NzU1MiwgMC45NzU1MiwgMS4yMTIzNywgMC45NzU1MiwgMS4wMDEzNSwgMS4wMDEzNSwgMS4wMDEzNSwgMS4wMDEzNSwgMC45MTE0MiwgMC45NDQzNiwgMC45ODcyMSwgMS4wNjU4NSwgMS4wNjU4NSwgMS4wNjU4NSwgMS4wNjU4NSwgMS4wNjU4NSwgMS4wNjU4NSwgMC45NjcwNSwgMC44MzA1NSwgMC45MzUwMywgMC45MzUwMywgMC45MzUwMywgMC45MzUwMywgMS4xNDIzNiwgMS4xNDIzNiwgMS4xNDIzNiwgMS4xNDIzNiwgMC45MzEyNSwgMC45NzkyMiwgMC45NDE2NSwgMC45NDE2NSwgMC45NDE2NSwgMC45NDE2NSwgMC45NDE2NSwgMS4yOTAwNCwgMC45NDE2NSwgMC45NzkyMiwgMC45NzkyMiwgMC45NzkyMiwgMC45NzkyMiwgMC45Njc1MiwgMC45NzA0MiwgMC45Njc1MiwgMC45NzM2MywgMS4wNjU4NSwgMC45NzM2MywgMS4wNjU4NSwgMC45NzM2MywgMS4wNjU4NSwgMC44Nzg5NywgMC44MzA1NSwgMC44Nzg5NywgMC44MzA1NSwgMC44Nzg5NywgMC44MzA1NSwgMC44Nzg5NywgMC44MzA1NSwgMS4wNDI2LCAxLjAwMzMsIDEuMDQyNiwgMC45NzA0MiwgMC43OTQyOSwgMC45MzUwMywgMC43OTQyOSwgMC45MzUwMywgMC43OTQyOSwgMC45MzUwMywgMC43OTQyOSwgMC45MzUwMywgMC43OTQyOSwgMC45MzUwMywgMC45MTE0OSwgMC45NzA0MiwgMC45MTE0OSwgMC45NzA0MiwgMC45MTE0OSwgMC45NzA0MiwgMSwgMSwgMS4wNTgxNSwgMC45NzkyMiwgMS4wNTgxNSwgMC45NzkyMiwgMS4xNDA2LCAxLjE0MjM2LCAxLjE0MDYsIDEuMTQyMzYsIDEuMTQwNiwgMS4xNDIzNiwgMS4xNDA2LCAxLjE0MjM2LCAxLjE0MDYsIDEuMTQyMzYsIDAuOTc0NDEsIDEuMDQzMDIsIDAuNzk2MzEsIDEuMDE1ODIsIDEsIDEsIDEuMDEwNTQsIDAuODM4NTMsIDEuMTQyMzYsIDEsIDEsIDAuODM4NTMsIDEuMDkxMjUsIDAuODM4NTMsIDAuOTA0MTgsIDAuODM4NTMsIDEuMTk1MDgsIDEuMTA2MTUsIDAuOTc5MjIsIDEsIDEsIDEuMTA2MTUsIDAuOTc5MjIsIDEuMDEwMzQsIDEuMTA0NjYsIDAuOTc5MjIsIDAuOTc1NTIsIDAuOTQxNjUsIDAuOTc1NTIsIDAuOTQxNjUsIDAuOTc1NTIsIDAuOTQxNjUsIDAuOTE2MDIsIDAuOTE5ODEsIDAuODg2NDEsIDEuMDI3NiwgMSwgMSwgMC44ODY0MSwgMS4wMjc2LCAwLjgwNTI3LCAwLjc4OTI5LCAwLjgwNTI3LCAwLjc4OTI5LCAwLjgwNTI3LCAwLjc4OTI5LCAwLjgwNTI3LCAwLjc4OTI5LCAxLCAxLCAwLjk2MDgzLCAxLjA1NDAzLCAwLjk1OTIzLCAxLjE2ODYyLCAxLjAwMTM1LCAwLjk3OTIyLCAxLjAwMTM1LCAwLjk3OTIyLCAxLjAwMTM1LCAwLjk3OTIyLCAxLjAwMTM1LCAwLjk3OTIyLCAxLjAwMTM1LCAwLjk3OTIyLCAxLjAwMTM1LCAwLjk3OTIyLCAxLjA2Nzc3LCAxLjAyMTk3LCAwLjkxMTQyLCAwLjk2NzUyLCAwLjkxMTQyLCAwLjk5MzYxLCAwLjk3MTY4LCAwLjk5MzYxLCAwLjk3MTY4LCAwLjk5MzYxLCAwLjk3MTY4LCAxLjIzMTk5LCAxLjAzNiwgMC45NzM2MywgMS4wNjU4NSwgMC45NDM4NSwgMC45NjcwNSwgMC45NzU1MiwgMC45NDE2NSwgMSwgMSwgMC45NjA4MywgMS4xMjYxLCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAxLjMxODE4LCAwLjk1MTYxLCAxLjI3MTI2LCAxLjAwODExLCAwLjgzMjg0LCAwLjc3NzAyLCAwLjk5MTM3LCAwLjk1MjUzLCAxLjAzNDcsIDAuODYxNDIsIDEuMDcyMDUsIDEuMTQyMzYsIDAuOTczNjMsIDAuODk3MjMsIDAuODY4NjksIDEuMDk4MTgsIDAuNzk0MjksIDAuOTkzNjEsIDEuMDU4MTUsIDAuOTc1NTIsIDEuMTQwNiwgMC45MDEyOCwgMS4wNjY2MiwgMS4wNDM5NiwgMS4xMDYxNSwgMC44NDkxOCwgMC45NzU1MiwgMS4wNDY5NCwgMC45NDQzNiwgMC45ODAxNSwgMC45NjA4MywgMC45MTE0MiwgMS4wMDM1NiwgMC45ODE3LCAxLjAxOTQ1LCAwLjk4OTk5LCAxLjE0MDYsIDAuOTExNDIsIDEuMDQ5NjEsIDAuOTg5OCwgMS4wMDYzOSwgMS4xNDIzNiwgMS4wNzUxNCwgMS4wNDk2MSwgMC45OTYwNywgMS4wMjg5NywgMS4wMDgsIDAuOTg5OCwgMC45NTEzNCwgMS4wMDYzOSwgMS4xMTEyMSwgMS4xNDIzNiwgMS4wMDUxOCwgMC45Nzk4MSwgMS4wMjE4NiwgMSwgMS4wODU3OCwgMC45NDE2NSwgMC45OTMxNCwgMC45ODM4NywgMC45MzAyOCwgMC45MzM3NywgMS4zNTEyNSwgMS4wNzUxNCwgMS4xMDY4NywgMC45MzQ5MSwgMS4wNDIzMiwgMS4wMDM1MSwgMS4xNDIzNiwgMS4wNzUxNCwgMC45NDE2NSwgMS4wNzUxNCwgMS4wMDM1MSwgMC43OTQyOSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4wOTA5NywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MzUwMywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45NjYwOSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4wNjc3NywgMS4wMjE5NywgMS4wNjc3NywgMS4wMjE5NywgMS4wNjc3NywgMS4wMjE5NywgMC45MTE0MiwgMC45Njc1MiwgMSwgMS4yMTI2MSwgMC44OTkwMywgMSwgMSwgMC43NTE1NSwgMS4wNDc0NSwgMS4wNDc0NSwgMS4wNDc0NSwgMS4wNDM5NCwgMC45ODYzMywgMC45ODYzMywgMC45ODYzMywgMC43Mjk1OSwgMC43Mjk1OSwgMS4yMDUwMiwgMC45MTQwNiwgMS4yNjUxNCwgMS4yMjIsIDEuMDI5NTYsIDEuMDMzNzIsIDEuMDMzNzIsIDAuOTYwMzksIDEuMjQ2MzMsIDEsIDEuMDkxMjUsIDAuOTMzMjcsIDEuMDMzMzYsIDEuMTY1NDEsIDEuMDM2LCAxLCAxLCAxLCAwLjc3MSwgMSwgMSwgMS4xNTU3NCwgMS4xNTU3NCwgMS4xNTU3NCwgMS4xNTU3NCwgMC44NjM2NCwgMC45NDQzNCwgMC44NjI3OSwgMC45NDQzNCwgMC44NjIyNCwgMSwgMSwgMS4xNjc5OCwgMSwgMC45NjA4NSwgMC45MDA2OCwgMS4yMTIzNywgMS4xODQxNiwgMS4xMzkwNCwgMC42OTgyNSwgMC45NzE2LCAyLjEwMzM5LCAxLjI5MDA0LCAxLjI5MDA0LCAxLjIxMzM5LCAxLjI5MDA0LCAxLjI5MDA0LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjQyNjAzLCAxLCAwLjk5ODYyLCAwLjk5ODYyLCAxLCAwLjg3MDI1LCAwLjg3MDI1LCAwLjg3MDI1LCAwLjg3MDI1LCAxLjE4Nzc1LCAxLjQyNjAzLCAxLCAxLjQyNjAzLCAxLjQyNjAzLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLjI4ODYsIDEuMDQzMTUsIDEuMTUyOTYsIDEuMzQxNjMsIDEsIDEsIDEsIDEuMTMyNjksIDEuMTMyNjksIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpleHBvcnRzLlNlZ29ldWlCb2xkSXRhbGljRmFjdG9ycyA9IFNlZ29ldWlCb2xkSXRhbGljRmFjdG9yczsKY29uc3QgU2Vnb2V1aUJvbGRJdGFsaWNNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMzMwMDgsCiAgbGluZUdhcDogMAp9OwpleHBvcnRzLlNlZ29ldWlCb2xkSXRhbGljTWV0cmljcyA9IFNlZ29ldWlCb2xkSXRhbGljTWV0cmljczsKY29uc3QgU2Vnb2V1aUl0YWxpY0ZhY3RvcnMgPSBbMS43NjczOCwgMSwgMSwgMC45ODk0NiwgMS4xNDc2MywgMS4wNTM2NSwgMS4wNjIzNCwgMC45NjkyNywgMC45MjU4NiwgMS4xNTM3MywgMS4xODQxNCwgMC45MTM0OSwgMC45MTM0OSwgMS4wNzQwMywgMS4xNzMwOCwgMC43ODM4MywgMS4yMDA4OCwgMC43ODM4MywgMS40MjUzMSwgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC43ODM4MywgMC43ODM4MywgMS4xNzMwOCwgMS4xNzMwOCwgMS4xNzMwOCwgMC43NzM0OSwgMC45NDU2NSwgMC45NDcyOSwgMC44NTk0NCwgMC44ODUwNiwgMC45ODU4LCAwLjc0ODE3LCAwLjgwMDE2LCAwLjg4NDQ5LCAwLjk4MDM5LCAwLjk1NzgyLCAwLjY5MjM4LCAwLjg5ODk4LCAwLjgzMjMxLCAwLjk4MTgzLCAxLjAzOTg5LCAwLjk2OTI0LCAwLjg2MjM3LCAwLjk2OTI0LCAwLjgwNTk1LCAwLjc0NTI0LCAwLjg2MDkxLCAwLjk1NDAyLCAwLjk0MTQzLCAwLjk4NDQ4LCAwLjg4NTgsIDAuODMwODksIDAuOTMyODUsIDEuMDk0OSwgMS4zOTAxNiwgMS4wOTQ5LCAxLjQ1OTk0LCAwLjc0NjI3LCAxLjA0ODM5LCAwLjk3NDU0LCAwLjk3NDU0LCAwLjg3MjA3LCAwLjk3NDU0LCAwLjg3NTMzLCAxLjA2MTUxLCAwLjk3NDU0LCAxLjAwMTc2LCAxLjE2NDg0LCAxLjA4MTMyLCAwLjk4MDQ3LCAxLjE2NDg0LCAxLjAyOTg5LCAxLjAxMDU0LCAwLjk2MjI1LCAwLjk3NDU0LCAwLjk3NDU0LCAxLjA2NTk4LCAwLjc5MDA0LCAxLjE2MzQ0LCAxLjAwMzUxLCAwLjk0NjI5LCAwLjk5NzMsIDAuOTEwMTYsIDAuOTY3NzcsIDAuOTA0MywgMC45MTA4MiwgMC45MjQ4MSwgMC45MTA4MiwgMS4xNzMwOCwgMC45NTc0OCwgMC45NjkyNywgMC45NjkyNywgMSwgMC45NjkyNywgMC45MjQ4MSwgMC44MDU5NywgMS4wNDgzOSwgMS4yMzM5MywgMS4xNzgxLCAwLjkyNDUsIDEuMTczMDgsIDEuMjA4MDgsIDAuNjMyMTgsIDAuOTQyNjEsIDEuMjQ4MjIsIDEuMDk5NzEsIDEuMDk5NzEsIDEuMDQ4MzksIDEsIDAuODUyNzMsIDAuNzgwMzIsIDEuMDQ4MzksIDEuMDk5NzEsIDEuMjIzMjYsIDAuOTI0NSwgMS4wOTgzNiwgMS4xMzUyNSwgMS4xNTIyMiwgMC43MDQyNCwgMC45NDcyOSwgMC45NDcyOSwgMC45NDcyOSwgMC45NDcyOSwgMC45NDcyOSwgMC45NDcyOSwgMC44NTQ5OCwgMC44ODUwNiwgMC43NDgxNywgMC43NDgxNywgMC43NDgxNywgMC43NDgxNywgMC45NTc4MiwgMC45NTc4MiwgMC45NTc4MiwgMC45NTc4MiwgMC45ODU4LCAxLjAzOTg5LCAwLjk2OTI0LCAwLjk2OTI0LCAwLjk2OTI0LCAwLjk2OTI0LCAwLjk2OTI0LCAxLjE3MzA4LCAwLjk2OTI0LCAwLjk1NDAyLCAwLjk1NDAyLCAwLjk1NDAyLCAwLjk1NDAyLCAwLjgzMDg5LCAwLjg2MjM3LCAwLjg4NDA5LCAwLjk3NDU0LCAwLjk3NDU0LCAwLjk3NDU0LCAwLjk3NDU0LCAwLjk3NDU0LCAwLjk3NDU0LCAwLjkyOTE2LCAwLjg3MjA3LCAwLjg3NTMzLCAwLjg3NTMzLCAwLjg3NTMzLCAwLjg3NTMzLCAwLjkzMTQ2LCAwLjkzMTQ2LCAwLjkzMTQ2LCAwLjkzMTQ2LCAwLjkzODU0LCAxLjAxMDU0LCAwLjk2MjI1LCAwLjk2MjI1LCAwLjk2MjI1LCAwLjk2MjI1LCAwLjk2MjI1LCAxLjI0ODIyLCAwLjg3NjEsIDEuMDAzNTEsIDEuMDAzNTEsIDEuMDAzNTEsIDEuMDAzNTEsIDAuOTY3NzcsIDAuOTc0NTQsIDAuOTY3NzcsIDAuOTQ3MjksIDAuOTc0NTQsIDAuOTQ3MjksIDAuOTc0NTQsIDAuOTQ3MjksIDAuOTc0NTQsIDAuODg1MDYsIDAuODcyMDcsIDAuODg1MDYsIDAuODcyMDcsIDAuODg1MDYsIDAuODcyMDcsIDAuODg1MDYsIDAuODcyMDcsIDAuOTg1OCwgMC45NTM5MSwgMC45ODU4LCAwLjk3NDU0LCAwLjc0ODE3LCAwLjg3NTMzLCAwLjc0ODE3LCAwLjg3NTMzLCAwLjc0ODE3LCAwLjg3NTMzLCAwLjc0ODE3LCAwLjg3NTMzLCAwLjc0ODE3LCAwLjg3NTMzLCAwLjg4NDQ5LCAwLjk3NDU0LCAwLjg4NDQ5LCAwLjk3NDU0LCAwLjg4NDQ5LCAwLjk3NDU0LCAxLCAxLCAwLjk4MDM5LCAxLjAwMTc2LCAwLjk4MDM5LCAxLjAwMTc2LCAwLjk1NzgyLCAwLjkzMTQ2LCAwLjk1NzgyLCAwLjkzMTQ2LCAwLjk1NzgyLCAwLjkzMTQ2LCAwLjk1NzgyLCAxLjE2NDg0LCAwLjk1NzgyLCAwLjkzMTQ2LCAwLjg0NDIxLCAxLjEyNzYxLCAwLjY5MjM4LCAxLjA4MTMyLCAxLCAxLCAwLjk4MDQ3LCAwLjgzMjMxLCAxLjE2NDg0LCAxLCAxLCAwLjg0NzIzLCAxLjA0ODYxLCAwLjg0NzIzLCAwLjc4NzU1LCAwLjgzMjMxLCAxLjIzNzM2LCAxLjAzOTg5LCAxLjAxMDU0LCAxLCAxLCAxLjAzOTg5LCAxLjAxMDU0LCAwLjk4NTcsIDEuMDM4NDksIDEuMDEwNTQsIDAuOTY5MjQsIDAuOTYyMjUsIDAuOTY5MjQsIDAuOTYyMjUsIDAuOTY5MjQsIDAuOTYyMjUsIDAuOTIzODMsIDAuOTAxNzEsIDAuODA1OTUsIDEuMDY1OTgsIDEsIDEsIDAuODA1OTUsIDEuMDY1OTgsIDAuNzQ1MjQsIDAuNzkwMDQsIDAuNzQ1MjQsIDAuNzkwMDQsIDAuNzQ1MjQsIDAuNzkwMDQsIDAuNzQ1MjQsIDAuNzkwMDQsIDEsIDEsIDAuODYwOTEsIDEuMDI3NTksIDAuODU3NzEsIDEuMTYzNDQsIDAuOTU0MDIsIDEuMDAzNTEsIDAuOTU0MDIsIDEuMDAzNTEsIDAuOTU0MDIsIDEuMDAzNTEsIDAuOTU0MDIsIDEuMDAzNTEsIDAuOTU0MDIsIDEuMDAzNTEsIDAuOTU0MDIsIDEuMDAzNTEsIDAuOTg0NDgsIDAuOTk3MywgMC44MzA4OSwgMC45Njc3NywgMC44MzA4OSwgMC45MzI4NSwgMC45MDQzLCAwLjkzMjg1LCAwLjkwNDMsIDAuOTMyODUsIDAuOTA0MywgMS4zMTg2OCwgMC45NjkyNywgMC45NDcyOSwgMC45NzQ1NCwgMC44NTQ5OCwgMC45MjkxNiwgMC45NjkyNCwgMC44NzYxLCAxLCAxLCAwLjg2MDkxLCAxLjE2MzQ0LCAxLjA0ODM5LCAxLjA0ODM5LCAxLjA0ODM5LCAxLjA0ODM5LCAxLjA0ODM5LCAxLjA0ODM5LCAxLjA0ODM5LCAxLjA0ODM5LCAxLjA0ODM5LCAwLjgxOTY1LCAwLjgxOTY1LCAwLjk0NzI5LCAwLjc4MDMyLCAwLjcxMDIyLCAwLjkwODgzLCAwLjg0MTcxLCAwLjk5ODc3LCAwLjc3NTk2LCAxLjA1NzM0LCAxLjIsIDAuOTQ3MjksIDAuODU5NDQsIDAuODI3OTEsIDAuOTYwNywgMC43NDgxNywgMC45MzI4NSwgMC45ODAzOSwgMC45NjkyNCwgMC45NTc4MiwgMC44OTg5OCwgMC45ODMxNiwgMC45ODE4MywgMS4wMzk4OSwgMC43ODYxNCwgMC45NjkyNCwgMC45NzY0MiwgMC44NjIzNywgMC44NjA3NSwgMC44NjA5MSwgMC44MzA4OSwgMC45MDA4MiwgMC44ODU4LCAwLjk3Mjk2LCAxLjAxMjg0LCAwLjk1NzgyLCAwLjgzMDg5LCAxLjA5NzYsIDEuMDQsIDEuMDMzNDIsIDEuMiwgMS4wNjc1LCAxLjA5NzYsIDAuOTgyMDUsIDEuMDM4MDksIDEuMDUwOTcsIDEuMDQsIDAuOTUzNjQsIDEuMDMzNDIsIDEuMDU0MDEsIDEuMiwgMS4wMjE0OCwgMS4wMTE5LCAxLjA0NzI0LCAxLjAxMjcsIDEuMDI3MzIsIDAuOTYyMjUsIDAuODk2NSwgMC45Nzc4MywgMC45MzU3NCwgMC45NDgxOCwgMS4zMDY3OSwgMS4wNjc1LCAxLjExODI2LCAwLjk5ODIxLCAxLjA1NTcsIDEuMDMyNiwgMS4yLCAxLjA2NzUsIDAuOTYyMjUsIDEuMDY3NSwgMS4wMzI2LCAwLjc0ODE3LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjAzNzU0LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjg3NTMzLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk4NzA1LCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk4NDQ4LCAwLjk5NzMsIDAuOTg0NDgsIDAuOTk3MywgMC45ODQ0OCwgMC45OTczLCAwLjgzMDg5LCAwLjk2Nzc3LCAxLCAxLjIwMDg4LCAwLjg5OTAzLCAxLCAxLCAwLjc1MTU1LCAwLjk0OTQ1LCAwLjk0OTQ1LCAwLjk0OTQ1LCAwLjk0OTQ1LCAxLjEyMzE3LCAxLjEyMzE3LCAxLjEyMzE3LCAwLjY3NjAzLCAwLjY3NjAzLCAxLjE1NjIxLCAwLjczNTg0LCAxLjIxMTkxLCAxLjIyMTM1LCAxLjA2NDgzLCAwLjk0ODY4LCAwLjk0ODY4LCAwLjk1OTk2LCAxLjI0NjMzLCAxLCAxLjA3NDk3LCAwLjg3NzA5LCAwLjk2OTI3LCAxLjAxNDczLCAwLjk2OTI3LCAxLCAxLCAxLCAwLjc3Mjk1LCAxLCAxLCAxLjA5ODM2LCAxLjA5ODM2LCAxLjA5ODM2LCAxLjAxNTIyLCAwLjg2MzIxLCAwLjk0NDM0LCAwLjg2NDksIDAuOTQ0MzQsIDAuODYxODIsIDEsIDEsIDEuMDgzLCAxLCAwLjkxNTc4LCAwLjg2NDM4LCAxLjE3MzA4LCAxLjE4NDE2LCAxLjE0NTg5LCAwLjY5ODI1LCAwLjk3NjIyLCAxLjk2NzkxLCAxLjI0ODIyLCAxLjI0ODIyLCAxLjE3MzA4LCAxLjI0ODIyLCAxLjI0ODIyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjQyNjAzLCAxLCAwLjk5ODYyLCAwLjk5ODYyLCAxLCAwLjg3MDI1LCAwLjg3MDI1LCAwLjg3MDI1LCAwLjg3MDI1LCAxLjE3OTg0LCAxLjQyNjAzLCAxLCAxLjQyNjAzLCAxLjQyNjAzLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLjI4ODYsIDEuMDQzMTUsIDEuMTUyOTYsIDEuMzQxNjMsIDEsIDEsIDEsIDEuMTA3NDIsIDEuMTA3NDIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpleHBvcnRzLlNlZ29ldWlJdGFsaWNGYWN0b3JzID0gU2Vnb2V1aUl0YWxpY0ZhY3RvcnM7CmNvbnN0IFNlZ29ldWlJdGFsaWNNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMzMwMDgsCiAgbGluZUdhcDogMAp9OwpleHBvcnRzLlNlZ29ldWlJdGFsaWNNZXRyaWNzID0gU2Vnb2V1aUl0YWxpY01ldHJpY3M7CmNvbnN0IFNlZ29ldWlSZWd1bGFyRmFjdG9ycyA9IFsxLjc2NzM4LCAxLCAxLCAwLjk4NTk0LCAxLjAyMjg1LCAxLjEwNDU0LCAxLjA2MjM0LCAwLjk2OTI3LCAwLjkyMDM3LCAxLjE5OTg1LCAxLjIwNDYsIDAuOTA2MTYsIDAuOTA2MTYsIDEuMDcxNTIsIDEuMTcxNCwgMC43ODAzMiwgMS4yMDA4OCwgMC43ODAzMiwgMS40MDI0NiwgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC45NjkyNywgMC43ODAzMiwgMC43ODAzMiwgMS4xNzE0LCAxLjE3MTQsIDEuMTcxNCwgMC44MDU5NywgMC45NDA4NCwgMC45NjcwNiwgMC44NTk0NCwgMC44NTczNCwgMC45NzA5MywgMC43NTg0MiwgMC43OTkzNiwgMC44ODE5OCwgMC45ODMxLCAwLjk1NzgyLCAwLjcxMzg3LCAwLjg2OTY5LCAwLjg0NjM2LCAxLjA3Nzk2LCAxLjAzNTg0LCAwLjk2OTI0LCAwLjgzOTY4LCAwLjk2OTI0LCAwLjgyODI2LCAwLjc5NjQ5LCAwLjg1NzcxLCAwLjk1MTMyLCAwLjkzMTE5LCAwLjk4OTY1LCAwLjg4NDMzLCAwLjgyODcsIDAuOTMzNjUsIDEuMDg2MTIsIDEuMzYzOCwgMS4wODYxMiwgMS40NTc4NiwgMC43NDYyNywgMC44MDQ5OSwgMC45MTQ4NCwgMS4wNTcwNywgMC45MjM4MywgMS4wNTg4MiwgMC45NDAzLCAxLjEyNjU0LCAxLjA1ODgyLCAxLjAxNzU2LCAxLjA5MDExLCAxLjA5MDExLCAwLjk5NDE0LCAxLjA5MDExLCAxLjAzNCwgMS4wMTc1NiwgMS4wNTM1NiwgMS4wNTcwNywgMS4wNTg4MiwgMS4wNDM5OSwgMC44NDg2MywgMS4yMTk2OCwgMS4wMTc1NiwgMC45NTgwMSwgMS4wMDA2OCwgMC45MTc5NywgMC45Njc3NywgMC45MDQzLCAwLjkwMzUxLCAwLjkyMTA1LCAwLjkwMzUxLCAxLjE3MTQsIDAuODUzMzcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTk5MTIsIDAuOTY5MjcsIDAuOTIxMDUsIDAuODA1OTcsIDEuMjQzNCwgMS4yMDgwOCwgMS4wNTkzNywgMC45MDk1NywgMS4xNzE0LCAxLjIwODA4LCAwLjc1MTU1LCAwLjk0MjYxLCAxLjI0NjQ0LCAxLjA5OTcxLCAxLjA5OTcxLCAwLjg0NzUxLCAxLCAwLjg1MjczLCAwLjc4MDMyLCAwLjYxNTg0LCAxLjA1NDI1LCAxLjE3OTE0LCAwLjkwOTU3LCAxLjA4NjY1LCAxLjExNTkzLCAxLjE0MTY5LCAwLjczMzgxLCAwLjk2NzA2LCAwLjk2NzA2LCAwLjk2NzA2LCAwLjk2NzA2LCAwLjk2NzA2LCAwLjk2NzA2LCAwLjg2MDM1LCAwLjg1NzM0LCAwLjc1ODQyLCAwLjc1ODQyLCAwLjc1ODQyLCAwLjc1ODQyLCAwLjk1NzgyLCAwLjk1NzgyLCAwLjk1NzgyLCAwLjk1NzgyLCAwLjk3MDkzLCAxLjAzNTg0LCAwLjk2OTI0LCAwLjk2OTI0LCAwLjk2OTI0LCAwLjk2OTI0LCAwLjk2OTI0LCAxLjE3MTQsIDAuOTY5MjQsIDAuOTUxMzIsIDAuOTUxMzIsIDAuOTUxMzIsIDAuOTUxMzIsIDAuODI4NywgMC44Mzk2OCwgMC44OTA0OSwgMC45MTQ4NCwgMC45MTQ4NCwgMC45MTQ4NCwgMC45MTQ4NCwgMC45MTQ4NCwgMC45MTQ4NCwgMC45MzU3NSwgMC45MjM4MywgMC45NDAzLCAwLjk0MDMsIDAuOTQwMywgMC45NDAzLCAwLjg3MTcsIDAuODcxNywgMC44NzE3LCAwLjg3MTcsIDEuMDA1MjcsIDEuMDE3NTYsIDEuMDUzNTYsIDEuMDUzNTYsIDEuMDUzNTYsIDEuMDUzNTYsIDEuMDUzNTYsIDEuMjQ2NDQsIDAuOTU5MjMsIDEuMDE3NTYsIDEuMDE3NTYsIDEuMDE3NTYsIDEuMDE3NTYsIDAuOTY3NzcsIDEuMDU3MDcsIDAuOTY3NzcsIDAuOTY3MDYsIDAuOTE0ODQsIDAuOTY3MDYsIDAuOTE0ODQsIDAuOTY3MDYsIDAuOTE0ODQsIDAuODU3MzQsIDAuOTIzODMsIDAuODU3MzQsIDAuOTIzODMsIDAuODU3MzQsIDAuOTIzODMsIDAuODU3MzQsIDAuOTIzODMsIDAuOTcwOTMsIDEuMDk2OSwgMC45NzA5MywgMS4wNTg4MiwgMC43NTg0MiwgMC45NDAzLCAwLjc1ODQyLCAwLjk0MDMsIDAuNzU4NDIsIDAuOTQwMywgMC43NTg0MiwgMC45NDAzLCAwLjc1ODQyLCAwLjk0MDMsIDAuODgxOTgsIDEuMDU4ODIsIDAuODgxOTgsIDEuMDU4ODIsIDAuODgxOTgsIDEuMDU4ODIsIDEsIDEsIDAuOTgzMSwgMS4wMTc1NiwgMC45ODMxLCAxLjAxNzU2LCAwLjk1NzgyLCAwLjg3MTcsIDAuOTU3ODIsIDAuODcxNywgMC45NTc4MiwgMC44NzE3LCAwLjk1NzgyLCAxLjA5MDExLCAwLjk1NzgyLCAwLjg3MTcsIDAuODQ3ODQsIDEuMTE1NTEsIDAuNzEzODcsIDEuMDkwMTEsIDEsIDEsIDAuOTk0MTQsIDAuODQ2MzYsIDEuMDkwMTEsIDEsIDEsIDAuODQ2MzYsIDEuMDUzNiwgMC44NDYzNiwgMC45NDI5OCwgMC44NDYzNiwgMS4yMzI5NywgMS4wMzU4NCwgMS4wMTc1NiwgMSwgMSwgMS4wMzU4NCwgMS4wMTc1NiwgMS4wMDMyMywgMS4wMzQ0NCwgMS4wMTc1NiwgMC45NjkyNCwgMS4wNTM1NiwgMC45NjkyNCwgMS4wNTM1NiwgMC45NjkyNCwgMS4wNTM1NiwgMC45MzA2NiwgMC45ODI5MywgMC44MjgyNiwgMS4wNDM5OSwgMSwgMSwgMC44MjgyNiwgMS4wNDM5OSwgMC43OTY0OSwgMC44NDg2MywgMC43OTY0OSwgMC44NDg2MywgMC43OTY0OSwgMC44NDg2MywgMC43OTY0OSwgMC44NDg2MywgMSwgMSwgMC44NTc3MSwgMS4xNzMxOCwgMC44NTc3MSwgMS4yMTk2OCwgMC45NTEzMiwgMS4wMTc1NiwgMC45NTEzMiwgMS4wMTc1NiwgMC45NTEzMiwgMS4wMTc1NiwgMC45NTEzMiwgMS4wMTc1NiwgMC45NTEzMiwgMS4wMTc1NiwgMC45NTEzMiwgMS4wMTc1NiwgMC45ODk2NSwgMS4wMDA2OCwgMC44Mjg3LCAwLjk2Nzc3LCAwLjgyODcsIDAuOTMzNjUsIDAuOTA0MywgMC45MzM2NSwgMC45MDQzLCAwLjkzMzY1LCAwLjkwNDMsIDEuMDg1NzEsIDAuOTY5MjcsIDAuOTY3MDYsIDAuOTE0ODQsIDAuODYwMzUsIDAuOTM1NzUsIDAuOTY5MjQsIDAuOTU5MjMsIDEsIDEsIDAuODU3NzEsIDEuMjE5NjgsIDEuMTE0MzcsIDEuMTE0MzcsIDAuOTMxMDksIDAuOTEyMDIsIDAuNjA0MTEsIDAuODQxNjQsIDAuNTU1NzIsIDEuMDExNzMsIDAuOTczNjEsIDAuODE4MTgsIDAuODE4MTgsIDAuOTY2MzUsIDAuNzgwMzIsIDAuNzI3MjcsIDAuOTIzNjYsIDAuOTg2MDEsIDEuMDM0MDUsIDAuNzc5NjgsIDEuMDk3OTksIDEuMiwgMC45NjcwNiwgMC44NTk0NCwgMC44NTYzOCwgMC45NjQ5MSwgMC43NTg0MiwgMC45MzM2NSwgMC45ODMxLCAwLjk2OTI0LCAwLjk1NzgyLCAwLjg2OTY5LCAwLjk0MTUyLCAxLjA3Nzk2LCAxLjAzNTg0LCAwLjc4NDM3LCAwLjk2OTI0LCAwLjk4NzE1LCAwLjgzOTY4LCAwLjgzNDkxLCAwLjg1NzcxLCAwLjgyODcsIDAuOTQ0OTIsIDAuODg0MzMsIDAuOTI4NywgMS4wMDk4LCAwLjk1NzgyLCAwLjgyODcsIDEuMDYyNSwgMC45ODI0OCwgMS4wMzQyNCwgMS4yLCAxLjAxMDcxLCAxLjA2MjUsIDAuOTUyNDYsIDEuMDM4MDksIDEuMDQ5MTIsIDAuOTgyNDgsIDEuMDAyMjEsIDEuMDM0MjQsIDEuMDU0NDMsIDEuMiwgMS4wNDc4NSwgMC45OTYwOSwgMS4wMDE2OSwgMS4wNTE3NiwgMC45OTM0NiwgMS4wNTM1NiwgMC45MDg3LCAxLjAzMDA0LCAwLjk1NTQyLCAwLjkzMTE3LCAxLjIzMzYyLCAxLjAxMDcxLCAxLjA3ODMxLCAxLjAyNTEyLCAxLjA1MjA1LCAxLjAzNTAyLCAxLjIsIDEuMDEwNzEsIDEuMDUzNTYsIDEuMDEwNzEsIDEuMDM1MDIsIDAuNzU4NDIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDM3MTksIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTQwMywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4wNDAyMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45ODk2NSwgMS4wMDA2OCwgMC45ODk2NSwgMS4wMDA2OCwgMC45ODk2NSwgMS4wMDA2OCwgMC44Mjg3LCAwLjk2Nzc3LCAxLCAxLjIwMDg4LCAwLjg5OTAzLCAxLCAxLCAwLjc1MTU1LCAxLjAzMDc3LCAxLjAzMDc3LCAxLjAzMDc3LCAxLjAzMDc3LCAxLjEzMTk2LCAxLjEzMTk2LCAxLjEzMTk2LCAwLjY3NDI4LCAwLjY3NDI4LCAxLjE2MDM5LCAwLjczMjkxLCAxLjIwOTk2LCAxLjIyMTM1LCAxLjA2NDgzLCAwLjk0ODY4LCAwLjk0ODY4LCAwLjk1OTk2LCAxLjI0NjMzLCAxLCAxLjA3NDk3LCAwLjg3Nzk2LCAwLjk2OTI3LCAxLjAxNTE4LCAwLjk2OTI3LCAxLCAxLCAxLCAwLjc3Mjk1LCAxLCAxLCAxLjEwNTM5LCAxLjEwNTM5LCAxLjExMzU4LCAxLjA2OTY3LCAwLjg2Mjc5LCAwLjk0NDM0LCAwLjg2Mjc5LCAwLjk0NDM0LCAwLjg2MTgyLCAxLCAxLCAxLjA4MywgMSwgMC45MTU3OCwgMC44NjUwNywgMS4xNzE0LCAxLjE4NDE2LCAxLjE0NTg5LCAwLjY5ODI1LCAwLjk3NjIyLCAxLjk2OTcsIDEuMjQ4MjIsIDEuMjQ4MjIsIDEuMTcyMzgsIDEuMjQ4MjIsIDEuMjQ4MjIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuNDI2MDMsIDEsIDAuOTk4NjIsIDAuOTk4NjIsIDEsIDAuODcwMjUsIDAuODcwMjUsIDAuODcwMjUsIDAuODcwMjUsIDEuMTgwODMsIDEuNDI2MDMsIDEsIDEuNDI2MDMsIDEuNDI2MDMsIDAuOTk4NjIsIDEsIDEsIDEsIDEsIDEsIDEuMjg4NiwgMS4wNDMxNSwgMS4xNTI5NiwgMS4zNDE2MywgMSwgMSwgMSwgMS4xMDkzOCwgMS4xMDkzOCwgMSwgMSwgMSwgMS4wNTQyNSwgMS4wOTk3MSwgMS4wOTk3MSwgMS4wOTk3MSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmV4cG9ydHMuU2Vnb2V1aVJlZ3VsYXJGYWN0b3JzID0gU2Vnb2V1aVJlZ3VsYXJGYWN0b3JzOwpjb25zdCBTZWdvZXVpUmVndWxhck1ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4zMzAwOCwKICBsaW5lR2FwOiAwCn07CmV4cG9ydHMuU2Vnb2V1aVJlZ3VsYXJNZXRyaWNzID0gU2Vnb2V1aVJlZ3VsYXJNZXRyaWNzOwoKLyoqKi8gfSksCi8qIDE5MiAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuUG9zdFNjcmlwdEV2YWx1YXRvciA9IGV4cG9ydHMuUG9zdFNjcmlwdENvbXBpbGVyID0gZXhwb3J0cy5QREZGdW5jdGlvbkZhY3RvcnkgPSB2b2lkIDA7CmV4cG9ydHMuaXNQREZGdW5jdGlvbiA9IGlzUERGRnVuY3Rpb247CnZhciBfcHJpbWl0aXZlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQwKTsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9wc19wYXJzZXIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE5Myk7CnZhciBfYmFzZV9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MSk7CnZhciBfaW1hZ2VfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE5NCk7CmNsYXNzIFBERkZ1bmN0aW9uRmFjdG9yeSB7CiAgY29uc3RydWN0b3IoX3JlZikgewogICAgbGV0IHsKICAgICAgeHJlZiwKICAgICAgaXNFdmFsU3VwcG9ydGVkID0gdHJ1ZQogICAgfSA9IF9yZWY7CiAgICB0aGlzLnhyZWYgPSB4cmVmOwogICAgdGhpcy5pc0V2YWxTdXBwb3J0ZWQgPSBpc0V2YWxTdXBwb3J0ZWQgIT09IGZhbHNlOwogIH0KICBjcmVhdGUoZm4pIHsKICAgIGNvbnN0IGNhY2hlZEZ1bmN0aW9uID0gdGhpcy5nZXRDYWNoZWQoZm4pOwogICAgaWYgKGNhY2hlZEZ1bmN0aW9uKSB7CiAgICAgIHJldHVybiBjYWNoZWRGdW5jdGlvbjsKICAgIH0KICAgIGNvbnN0IHBhcnNlZEZ1bmN0aW9uID0gUERGRnVuY3Rpb24ucGFyc2UoewogICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgIGlzRXZhbFN1cHBvcnRlZDogdGhpcy5pc0V2YWxTdXBwb3J0ZWQsCiAgICAgIGZuOiBmbiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZiA/IHRoaXMueHJlZi5mZXRjaChmbikgOiBmbgogICAgfSk7CiAgICB0aGlzLl9jYWNoZShmbiwgcGFyc2VkRnVuY3Rpb24pOwogICAgcmV0dXJuIHBhcnNlZEZ1bmN0aW9uOwogIH0KICBjcmVhdGVGcm9tQXJyYXkoZm5PYmopIHsKICAgIGNvbnN0IGNhY2hlZEZ1bmN0aW9uID0gdGhpcy5nZXRDYWNoZWQoZm5PYmopOwogICAgaWYgKGNhY2hlZEZ1bmN0aW9uKSB7CiAgICAgIHJldHVybiBjYWNoZWRGdW5jdGlvbjsKICAgIH0KICAgIGNvbnN0IHBhcnNlZEZ1bmN0aW9uID0gUERGRnVuY3Rpb24ucGFyc2VBcnJheSh7CiAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgaXNFdmFsU3VwcG9ydGVkOiB0aGlzLmlzRXZhbFN1cHBvcnRlZCwKICAgICAgZm5PYmo6IGZuT2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmID8gdGhpcy54cmVmLmZldGNoKGZuT2JqKSA6IGZuT2JqCiAgICB9KTsKICAgIHRoaXMuX2NhY2hlKGZuT2JqLCBwYXJzZWRGdW5jdGlvbik7CiAgICByZXR1cm4gcGFyc2VkRnVuY3Rpb247CiAgfQogIGdldENhY2hlZChjYWNoZUtleSkgewogICAgbGV0IGZuUmVmOwogICAgaWYgKGNhY2hlS2V5IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgIGZuUmVmID0gY2FjaGVLZXk7CiAgICB9IGVsc2UgaWYgKGNhY2hlS2V5IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICBmblJlZiA9IGNhY2hlS2V5Lm9iaklkOwogICAgfSBlbHNlIGlmIChjYWNoZUtleSBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSB7CiAgICAgIGZuUmVmID0gY2FjaGVLZXkuZGljdCAmJiBjYWNoZUtleS5kaWN0Lm9iaklkOwogICAgfQogICAgaWYgKGZuUmVmKSB7CiAgICAgIGNvbnN0IGxvY2FsRnVuY3Rpb24gPSB0aGlzLl9sb2NhbEZ1bmN0aW9uQ2FjaGUuZ2V0QnlSZWYoZm5SZWYpOwogICAgICBpZiAobG9jYWxGdW5jdGlvbikgewogICAgICAgIHJldHVybiBsb2NhbEZ1bmN0aW9uOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgX2NhY2hlKGNhY2hlS2V5LCBwYXJzZWRGdW5jdGlvbikgewogICAgaWYgKCFwYXJzZWRGdW5jdGlvbikgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BERkZ1bmN0aW9uRmFjdG9yeS5fY2FjaGUgLSBleHBlY3RlZCAicGFyc2VkRnVuY3Rpb24iIGFyZ3VtZW50LicpOwogICAgfQogICAgbGV0IGZuUmVmOwogICAgaWYgKGNhY2hlS2V5IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgIGZuUmVmID0gY2FjaGVLZXk7CiAgICB9IGVsc2UgaWYgKGNhY2hlS2V5IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICBmblJlZiA9IGNhY2hlS2V5Lm9iaklkOwogICAgfSBlbHNlIGlmIChjYWNoZUtleSBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSB7CiAgICAgIGZuUmVmID0gY2FjaGVLZXkuZGljdCAmJiBjYWNoZUtleS5kaWN0Lm9iaklkOwogICAgfQogICAgaWYgKGZuUmVmKSB7CiAgICAgIHRoaXMuX2xvY2FsRnVuY3Rpb25DYWNoZS5zZXQobnVsbCwgZm5SZWYsIHBhcnNlZEZ1bmN0aW9uKTsKICAgIH0KICB9CiAgZ2V0IF9sb2NhbEZ1bmN0aW9uQ2FjaGUoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIl9sb2NhbEZ1bmN0aW9uQ2FjaGUiLCBuZXcgX2ltYWdlX3V0aWxzLkxvY2FsRnVuY3Rpb25DYWNoZSgpKTsKICB9Cn0KZXhwb3J0cy5QREZGdW5jdGlvbkZhY3RvcnkgPSBQREZGdW5jdGlvbkZhY3Rvcnk7CmZ1bmN0aW9uIHRvTnVtYmVyQXJyYXkoYXJyKSB7CiAgaWYgKCFBcnJheS5pc0FycmF5KGFycikpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBjb25zdCBsZW5ndGggPSBhcnIubGVuZ3RoOwogIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgIGlmICh0eXBlb2YgYXJyW2ldICE9PSAibnVtYmVyIikgewogICAgICBjb25zdCByZXN1bHQgPSBuZXcgQXJyYXkobGVuZ3RoKTsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBsZW5ndGg7IGorKykgewogICAgICAgIHJlc3VsdFtqXSA9ICthcnJbal07CiAgICAgIH0KICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH0KICB9CiAgcmV0dXJuIGFycjsKfQpjbGFzcyBQREZGdW5jdGlvbiB7CiAgc3RhdGljIGdldFNhbXBsZUFycmF5KHNpemUsIG91dHB1dFNpemUsIGJwcywgc3RyZWFtKSB7CiAgICBsZXQgaSwgaWk7CiAgICBsZXQgbGVuZ3RoID0gMTsKICAgIGZvciAoaSA9IDAsIGlpID0gc2l6ZS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGxlbmd0aCAqPSBzaXplW2ldOwogICAgfQogICAgbGVuZ3RoICo9IG91dHB1dFNpemU7CiAgICBjb25zdCBhcnJheSA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgbGV0IGNvZGVTaXplID0gMDsKICAgIGxldCBjb2RlQnVmID0gMDsKICAgIGNvbnN0IHNhbXBsZU11bCA9IDEuMCAvICgyLjAgKiogYnBzIC0gMSk7CiAgICBjb25zdCBzdHJCeXRlcyA9IHN0cmVhbS5nZXRCeXRlcygobGVuZ3RoICogYnBzICsgNykgLyA4KTsKICAgIGxldCBzdHJJZHggPSAwOwogICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIHdoaWxlIChjb2RlU2l6ZSA8IGJwcykgewogICAgICAgIGNvZGVCdWYgPDw9IDg7CiAgICAgICAgY29kZUJ1ZiB8PSBzdHJCeXRlc1tzdHJJZHgrK107CiAgICAgICAgY29kZVNpemUgKz0gODsKICAgICAgfQogICAgICBjb2RlU2l6ZSAtPSBicHM7CiAgICAgIGFycmF5W2ldID0gKGNvZGVCdWYgPj4gY29kZVNpemUpICogc2FtcGxlTXVsOwogICAgICBjb2RlQnVmICY9ICgxIDw8IGNvZGVTaXplKSAtIDE7CiAgICB9CiAgICByZXR1cm4gYXJyYXk7CiAgfQogIHN0YXRpYyBwYXJzZShfcmVmMikgewogICAgbGV0IHsKICAgICAgeHJlZiwKICAgICAgaXNFdmFsU3VwcG9ydGVkLAogICAgICBmbgogICAgfSA9IF9yZWYyOwogICAgY29uc3QgZGljdCA9IGZuLmRpY3QgfHwgZm47CiAgICBjb25zdCB0eXBlTnVtID0gZGljdC5nZXQoIkZ1bmN0aW9uVHlwZSIpOwogICAgc3dpdGNoICh0eXBlTnVtKSB7CiAgICAgIGNhc2UgMDoKICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3RTYW1wbGVkKHsKICAgICAgICAgIHhyZWYsCiAgICAgICAgICBpc0V2YWxTdXBwb3J0ZWQsCiAgICAgICAgICBmbiwKICAgICAgICAgIGRpY3QKICAgICAgICB9KTsKICAgICAgY2FzZSAxOgogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDI6CiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0SW50ZXJwb2xhdGVkKHsKICAgICAgICAgIHhyZWYsCiAgICAgICAgICBpc0V2YWxTdXBwb3J0ZWQsCiAgICAgICAgICBkaWN0CiAgICAgICAgfSk7CiAgICAgIGNhc2UgMzoKICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3RTdGljaGVkKHsKICAgICAgICAgIHhyZWYsCiAgICAgICAgICBpc0V2YWxTdXBwb3J0ZWQsCiAgICAgICAgICBkaWN0CiAgICAgICAgfSk7CiAgICAgIGNhc2UgNDoKICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3RQb3N0U2NyaXB0KHsKICAgICAgICAgIHhyZWYsCiAgICAgICAgICBpc0V2YWxTdXBwb3J0ZWQsCiAgICAgICAgICBmbiwKICAgICAgICAgIGRpY3QKICAgICAgICB9KTsKICAgIH0KICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiVW5rbm93biB0eXBlIG9mIGZ1bmN0aW9uIik7CiAgfQogIHN0YXRpYyBwYXJzZUFycmF5KF9yZWYzKSB7CiAgICBsZXQgewogICAgICB4cmVmLAogICAgICBpc0V2YWxTdXBwb3J0ZWQsCiAgICAgIGZuT2JqCiAgICB9ID0gX3JlZjM7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZm5PYmopKSB7CiAgICAgIHJldHVybiB0aGlzLnBhcnNlKHsKICAgICAgICB4cmVmLAogICAgICAgIGlzRXZhbFN1cHBvcnRlZCwKICAgICAgICBmbjogZm5PYmoKICAgICAgfSk7CiAgICB9CiAgICBjb25zdCBmbkFycmF5ID0gW107CiAgICBmb3IgKGNvbnN0IGZuIG9mIGZuT2JqKSB7CiAgICAgIGZuQXJyYXkucHVzaCh0aGlzLnBhcnNlKHsKICAgICAgICB4cmVmLAogICAgICAgIGlzRXZhbFN1cHBvcnRlZCwKICAgICAgICBmbjogeHJlZi5mZXRjaElmUmVmKGZuKQogICAgICB9KSk7CiAgICB9CiAgICByZXR1cm4gZnVuY3Rpb24gKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGZuQXJyYXkubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGZuQXJyYXlbaV0oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQgKyBpKTsKICAgICAgfQogICAgfTsKICB9CiAgc3RhdGljIGNvbnN0cnVjdFNhbXBsZWQoX3JlZjQpIHsKICAgIGxldCB7CiAgICAgIHhyZWYsCiAgICAgIGlzRXZhbFN1cHBvcnRlZCwKICAgICAgZm4sCiAgICAgIGRpY3QKICAgIH0gPSBfcmVmNDsKICAgIGZ1bmN0aW9uIHRvTXVsdGlBcnJheShhcnIpIHsKICAgICAgY29uc3QgaW5wdXRMZW5ndGggPSBhcnIubGVuZ3RoOwogICAgICBjb25zdCBvdXQgPSBbXTsKICAgICAgbGV0IGluZGV4ID0gMDsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dExlbmd0aDsgaSArPSAyKSB7CiAgICAgICAgb3V0W2luZGV4KytdID0gW2FycltpXSwgYXJyW2kgKyAxXV07CiAgICAgIH0KICAgICAgcmV0dXJuIG91dDsKICAgIH0KICAgIGZ1bmN0aW9uIGludGVycG9sYXRlKHgsIHhtaW4sIHhtYXgsIHltaW4sIHltYXgpIHsKICAgICAgcmV0dXJuIHltaW4gKyAoeCAtIHhtaW4pICogKCh5bWF4IC0geW1pbikgLyAoeG1heCAtIHhtaW4pKTsKICAgIH0KICAgIGxldCBkb21haW4gPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIkRvbWFpbiIpKTsKICAgIGxldCByYW5nZSA9IHRvTnVtYmVyQXJyYXkoZGljdC5nZXRBcnJheSgiUmFuZ2UiKSk7CiAgICBpZiAoIWRvbWFpbiB8fCAhcmFuZ2UpIHsKICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJObyBkb21haW4gb3IgcmFuZ2UiKTsKICAgIH0KICAgIGNvbnN0IGlucHV0U2l6ZSA9IGRvbWFpbi5sZW5ndGggLyAyOwogICAgY29uc3Qgb3V0cHV0U2l6ZSA9IHJhbmdlLmxlbmd0aCAvIDI7CiAgICBkb21haW4gPSB0b011bHRpQXJyYXkoZG9tYWluKTsKICAgIHJhbmdlID0gdG9NdWx0aUFycmF5KHJhbmdlKTsKICAgIGNvbnN0IHNpemUgPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIlNpemUiKSk7CiAgICBjb25zdCBicHMgPSBkaWN0LmdldCgiQml0c1BlclNhbXBsZSIpOwogICAgY29uc3Qgb3JkZXIgPSBkaWN0LmdldCgiT3JkZXIiKSB8fCAxOwogICAgaWYgKG9yZGVyICE9PSAxKSB7CiAgICAgICgwLCBfdXRpbC5pbmZvKSgiTm8gc3VwcG9ydCBmb3IgY3ViaWMgc3BsaW5lIGludGVycG9sYXRpb246ICIgKyBvcmRlcik7CiAgICB9CiAgICBsZXQgZW5jb2RlID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJFbmNvZGUiKSk7CiAgICBpZiAoIWVuY29kZSkgewogICAgICBlbmNvZGUgPSBbXTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dFNpemU7ICsraSkgewogICAgICAgIGVuY29kZS5wdXNoKFswLCBzaXplW2ldIC0gMV0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBlbmNvZGUgPSB0b011bHRpQXJyYXkoZW5jb2RlKTsKICAgIH0KICAgIGxldCBkZWNvZGUgPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIkRlY29kZSIpKTsKICAgIGlmICghZGVjb2RlKSB7CiAgICAgIGRlY29kZSA9IHJhbmdlOwogICAgfSBlbHNlIHsKICAgICAgZGVjb2RlID0gdG9NdWx0aUFycmF5KGRlY29kZSk7CiAgICB9CiAgICBjb25zdCBzYW1wbGVzID0gdGhpcy5nZXRTYW1wbGVBcnJheShzaXplLCBvdXRwdXRTaXplLCBicHMsIGZuKTsKICAgIHJldHVybiBmdW5jdGlvbiBjb25zdHJ1Y3RTYW1wbGVkRm4oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgICAgY29uc3QgY3ViZVZlcnRpY2VzID0gMSA8PCBpbnB1dFNpemU7CiAgICAgIGNvbnN0IGN1YmVOID0gbmV3IEZsb2F0NjRBcnJheShjdWJlVmVydGljZXMpOwogICAgICBjb25zdCBjdWJlVmVydGV4ID0gbmV3IFVpbnQzMkFycmF5KGN1YmVWZXJ0aWNlcyk7CiAgICAgIGxldCBpLCBqOwogICAgICBmb3IgKGogPSAwOyBqIDwgY3ViZVZlcnRpY2VzOyBqKyspIHsKICAgICAgICBjdWJlTltqXSA9IDE7CiAgICAgIH0KICAgICAgbGV0IGsgPSBvdXRwdXRTaXplLAogICAgICAgIHBvcyA9IDE7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBpbnB1dFNpemU7ICsraSkgewogICAgICAgIGNvbnN0IGRvbWFpbl8yaSA9IGRvbWFpbltpXVswXTsKICAgICAgICBjb25zdCBkb21haW5fMmlfMSA9IGRvbWFpbltpXVsxXTsKICAgICAgICBjb25zdCB4aSA9IE1hdGgubWluKE1hdGgubWF4KHNyY1tzcmNPZmZzZXQgKyBpXSwgZG9tYWluXzJpKSwgZG9tYWluXzJpXzEpOwogICAgICAgIGxldCBlID0gaW50ZXJwb2xhdGUoeGksIGRvbWFpbl8yaSwgZG9tYWluXzJpXzEsIGVuY29kZVtpXVswXSwgZW5jb2RlW2ldWzFdKTsKICAgICAgICBjb25zdCBzaXplX2kgPSBzaXplW2ldOwogICAgICAgIGUgPSBNYXRoLm1pbihNYXRoLm1heChlLCAwKSwgc2l6ZV9pIC0gMSk7CiAgICAgICAgY29uc3QgZTAgPSBlIDwgc2l6ZV9pIC0gMSA/IE1hdGguZmxvb3IoZSkgOiBlIC0gMTsKICAgICAgICBjb25zdCBuMCA9IGUwICsgMSAtIGU7CiAgICAgICAgY29uc3QgbjEgPSBlIC0gZTA7CiAgICAgICAgY29uc3Qgb2Zmc2V0MCA9IGUwICogazsKICAgICAgICBjb25zdCBvZmZzZXQxID0gb2Zmc2V0MCArIGs7CiAgICAgICAgZm9yIChqID0gMDsgaiA8IGN1YmVWZXJ0aWNlczsgaisrKSB7CiAgICAgICAgICBpZiAoaiAmIHBvcykgewogICAgICAgICAgICBjdWJlTltqXSAqPSBuMTsKICAgICAgICAgICAgY3ViZVZlcnRleFtqXSArPSBvZmZzZXQxOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgY3ViZU5bal0gKj0gbjA7CiAgICAgICAgICAgIGN1YmVWZXJ0ZXhbal0gKz0gb2Zmc2V0MDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgayAqPSBzaXplX2k7CiAgICAgICAgcG9zIDw8PSAxOwogICAgICB9CiAgICAgIGZvciAoaiA9IDA7IGogPCBvdXRwdXRTaXplOyArK2opIHsKICAgICAgICBsZXQgcmogPSAwOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBjdWJlVmVydGljZXM7IGkrKykgewogICAgICAgICAgcmogKz0gc2FtcGxlc1tjdWJlVmVydGV4W2ldICsgal0gKiBjdWJlTltpXTsKICAgICAgICB9CiAgICAgICAgcmogPSBpbnRlcnBvbGF0ZShyaiwgMCwgMSwgZGVjb2RlW2pdWzBdLCBkZWNvZGVbal1bMV0pOwogICAgICAgIGRlc3RbZGVzdE9mZnNldCArIGpdID0gTWF0aC5taW4oTWF0aC5tYXgocmosIHJhbmdlW2pdWzBdKSwgcmFuZ2Vbal1bMV0pOwogICAgICB9CiAgICB9OwogIH0KICBzdGF0aWMgY29uc3RydWN0SW50ZXJwb2xhdGVkKF9yZWY1KSB7CiAgICBsZXQgewogICAgICB4cmVmLAogICAgICBpc0V2YWxTdXBwb3J0ZWQsCiAgICAgIGRpY3QKICAgIH0gPSBfcmVmNTsKICAgIGNvbnN0IGMwID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJDMCIpKSB8fCBbMF07CiAgICBjb25zdCBjMSA9IHRvTnVtYmVyQXJyYXkoZGljdC5nZXRBcnJheSgiQzEiKSkgfHwgWzFdOwogICAgY29uc3QgbiA9IGRpY3QuZ2V0KCJOIik7CiAgICBjb25zdCBkaWZmID0gW107CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBjMC5sZW5ndGg7IGkgPCBpaTsgKytpKSB7CiAgICAgIGRpZmYucHVzaChjMVtpXSAtIGMwW2ldKTsKICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IGRpZmYubGVuZ3RoOwogICAgcmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdEludGVycG9sYXRlZEZuKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICAgIGNvbnN0IHggPSBuID09PSAxID8gc3JjW3NyY09mZnNldF0gOiBzcmNbc3JjT2Zmc2V0XSAqKiBuOwogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxlbmd0aDsgKytqKSB7CiAgICAgICAgZGVzdFtkZXN0T2Zmc2V0ICsgal0gPSBjMFtqXSArIHggKiBkaWZmW2pdOwogICAgICB9CiAgICB9OwogIH0KICBzdGF0aWMgY29uc3RydWN0U3RpY2hlZChfcmVmNikgewogICAgbGV0IHsKICAgICAgeHJlZiwKICAgICAgaXNFdmFsU3VwcG9ydGVkLAogICAgICBkaWN0CiAgICB9ID0gX3JlZjY7CiAgICBjb25zdCBkb21haW4gPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIkRvbWFpbiIpKTsKICAgIGlmICghZG9tYWluKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiTm8gZG9tYWluIik7CiAgICB9CiAgICBjb25zdCBpbnB1dFNpemUgPSBkb21haW4ubGVuZ3RoIC8gMjsKICAgIGlmIChpbnB1dFNpemUgIT09IDEpIHsKICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJCYWQgZG9tYWluIGZvciBzdGljaGVkIGZ1bmN0aW9uIik7CiAgICB9CiAgICBjb25zdCBmbnMgPSBbXTsKICAgIGZvciAoY29uc3QgZm4gb2YgZGljdC5nZXQoIkZ1bmN0aW9ucyIpKSB7CiAgICAgIGZucy5wdXNoKHRoaXMucGFyc2UoewogICAgICAgIHhyZWYsCiAgICAgICAgaXNFdmFsU3VwcG9ydGVkLAogICAgICAgIGZuOiB4cmVmLmZldGNoSWZSZWYoZm4pCiAgICAgIH0pKTsKICAgIH0KICAgIGNvbnN0IGJvdW5kcyA9IHRvTnVtYmVyQXJyYXkoZGljdC5nZXRBcnJheSgiQm91bmRzIikpOwogICAgY29uc3QgZW5jb2RlID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJFbmNvZGUiKSk7CiAgICBjb25zdCB0bXBCdWYgPSBuZXcgRmxvYXQzMkFycmF5KDEpOwogICAgcmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdFN0aWNoZWRGbihzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgICBjb25zdCBjbGlwID0gZnVuY3Rpb24gY29uc3RydWN0U3RpY2hlZEZyb21JUkNsaXAodiwgbWluLCBtYXgpIHsKICAgICAgICBpZiAodiA+IG1heCkgewogICAgICAgICAgdiA9IG1heDsKICAgICAgICB9IGVsc2UgaWYgKHYgPCBtaW4pIHsKICAgICAgICAgIHYgPSBtaW47CiAgICAgICAgfQogICAgICAgIHJldHVybiB2OwogICAgICB9OwogICAgICBjb25zdCB2ID0gY2xpcChzcmNbc3JjT2Zmc2V0XSwgZG9tYWluWzBdLCBkb21haW5bMV0pOwogICAgICBjb25zdCBsZW5ndGggPSBib3VuZHMubGVuZ3RoOwogICAgICBsZXQgaTsKICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgaWYgKHYgPCBib3VuZHNbaV0pIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBsZXQgZG1pbiA9IGRvbWFpblswXTsKICAgICAgaWYgKGkgPiAwKSB7CiAgICAgICAgZG1pbiA9IGJvdW5kc1tpIC0gMV07CiAgICAgIH0KICAgICAgbGV0IGRtYXggPSBkb21haW5bMV07CiAgICAgIGlmIChpIDwgYm91bmRzLmxlbmd0aCkgewogICAgICAgIGRtYXggPSBib3VuZHNbaV07CiAgICAgIH0KICAgICAgY29uc3Qgcm1pbiA9IGVuY29kZVsyICogaV07CiAgICAgIGNvbnN0IHJtYXggPSBlbmNvZGVbMiAqIGkgKyAxXTsKICAgICAgdG1wQnVmWzBdID0gZG1pbiA9PT0gZG1heCA/IHJtaW4gOiBybWluICsgKHYgLSBkbWluKSAqIChybWF4IC0gcm1pbikgLyAoZG1heCAtIGRtaW4pOwogICAgICBmbnNbaV0odG1wQnVmLCAwLCBkZXN0LCBkZXN0T2Zmc2V0KTsKICAgIH07CiAgfQogIHN0YXRpYyBjb25zdHJ1Y3RQb3N0U2NyaXB0KF9yZWY3KSB7CiAgICBsZXQgewogICAgICB4cmVmLAogICAgICBpc0V2YWxTdXBwb3J0ZWQsCiAgICAgIGZuLAogICAgICBkaWN0CiAgICB9ID0gX3JlZjc7CiAgICBjb25zdCBkb21haW4gPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIkRvbWFpbiIpKTsKICAgIGNvbnN0IHJhbmdlID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJSYW5nZSIpKTsKICAgIGlmICghZG9tYWluKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiTm8gZG9tYWluLiIpOwogICAgfQogICAgaWYgKCFyYW5nZSkgewogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIk5vIHJhbmdlLiIpOwogICAgfQogICAgY29uc3QgbGV4ZXIgPSBuZXcgX3BzX3BhcnNlci5Qb3N0U2NyaXB0TGV4ZXIoZm4pOwogICAgY29uc3QgcGFyc2VyID0gbmV3IF9wc19wYXJzZXIuUG9zdFNjcmlwdFBhcnNlcihsZXhlcik7CiAgICBjb25zdCBjb2RlID0gcGFyc2VyLnBhcnNlKCk7CiAgICBpZiAoaXNFdmFsU3VwcG9ydGVkICYmIF91dGlsLkZlYXR1cmVUZXN0LmlzRXZhbFN1cHBvcnRlZCkgewogICAgICBjb25zdCBjb21waWxlZCA9IG5ldyBQb3N0U2NyaXB0Q29tcGlsZXIoKS5jb21waWxlKGNvZGUsIGRvbWFpbiwgcmFuZ2UpOwogICAgICBpZiAoY29tcGlsZWQpIHsKICAgICAgICByZXR1cm4gbmV3IEZ1bmN0aW9uKCJzcmMiLCAic3JjT2Zmc2V0IiwgImRlc3QiLCAiZGVzdE9mZnNldCIsIGNvbXBpbGVkKTsKICAgICAgfQogICAgfQogICAgKDAsIF91dGlsLmluZm8pKCJVbmFibGUgdG8gY29tcGlsZSBQUyBmdW5jdGlvbiIpOwogICAgY29uc3QgbnVtT3V0cHV0cyA9IHJhbmdlLmxlbmd0aCA+PiAxOwogICAgY29uc3QgbnVtSW5wdXRzID0gZG9tYWluLmxlbmd0aCA+PiAxOwogICAgY29uc3QgZXZhbHVhdG9yID0gbmV3IFBvc3RTY3JpcHRFdmFsdWF0b3IoY29kZSk7CiAgICBjb25zdCBjYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBjb25zdCBNQVhfQ0FDSEVfU0laRSA9IDIwNDggKiA0OwogICAgbGV0IGNhY2hlX2F2YWlsYWJsZSA9IE1BWF9DQUNIRV9TSVpFOwogICAgY29uc3QgdG1wQnVmID0gbmV3IEZsb2F0MzJBcnJheShudW1JbnB1dHMpOwogICAgcmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdFBvc3RTY3JpcHRGbihzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgICBsZXQgaSwgdmFsdWU7CiAgICAgIGxldCBrZXkgPSAiIjsKICAgICAgY29uc3QgaW5wdXQgPSB0bXBCdWY7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1JbnB1dHM7IGkrKykgewogICAgICAgIHZhbHVlID0gc3JjW3NyY09mZnNldCArIGldOwogICAgICAgIGlucHV0W2ldID0gdmFsdWU7CiAgICAgICAga2V5ICs9IHZhbHVlICsgIl8iOwogICAgICB9CiAgICAgIGNvbnN0IGNhY2hlZFZhbHVlID0gY2FjaGVba2V5XTsKICAgICAgaWYgKGNhY2hlZFZhbHVlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBkZXN0LnNldChjYWNoZWRWYWx1ZSwgZGVzdE9mZnNldCk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNvbnN0IG91dHB1dCA9IG5ldyBGbG9hdDMyQXJyYXkobnVtT3V0cHV0cyk7CiAgICAgIGNvbnN0IHN0YWNrID0gZXZhbHVhdG9yLmV4ZWN1dGUoaW5wdXQpOwogICAgICBjb25zdCBzdGFja0luZGV4ID0gc3RhY2subGVuZ3RoIC0gbnVtT3V0cHV0czsKICAgICAgZm9yIChpID0gMDsgaSA8IG51bU91dHB1dHM7IGkrKykgewogICAgICAgIHZhbHVlID0gc3RhY2tbc3RhY2tJbmRleCArIGldOwogICAgICAgIGxldCBib3VuZCA9IHJhbmdlW2kgKiAyXTsKICAgICAgICBpZiAodmFsdWUgPCBib3VuZCkgewogICAgICAgICAgdmFsdWUgPSBib3VuZDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgYm91bmQgPSByYW5nZVtpICogMiArIDFdOwogICAgICAgICAgaWYgKHZhbHVlID4gYm91bmQpIHsKICAgICAgICAgICAgdmFsdWUgPSBib3VuZDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgb3V0cHV0W2ldID0gdmFsdWU7CiAgICAgIH0KICAgICAgaWYgKGNhY2hlX2F2YWlsYWJsZSA+IDApIHsKICAgICAgICBjYWNoZV9hdmFpbGFibGUtLTsKICAgICAgICBjYWNoZVtrZXldID0gb3V0cHV0OwogICAgICB9CiAgICAgIGRlc3Quc2V0KG91dHB1dCwgZGVzdE9mZnNldCk7CiAgICB9OwogIH0KfQpmdW5jdGlvbiBpc1BERkZ1bmN0aW9uKHYpIHsKICBsZXQgZm5EaWN0OwogIGlmICh2IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgZm5EaWN0ID0gdjsKICB9IGVsc2UgaWYgKHYgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkgewogICAgZm5EaWN0ID0gdi5kaWN0OwogIH0gZWxzZSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIHJldHVybiBmbkRpY3QuaGFzKCJGdW5jdGlvblR5cGUiKTsKfQpjbGFzcyBQb3N0U2NyaXB0U3RhY2sgewogIHN0YXRpYyBnZXQgTUFYX1NUQUNLX1NJWkUoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIk1BWF9TVEFDS19TSVpFIiwgMTAwKTsKICB9CiAgY29uc3RydWN0b3IoaW5pdGlhbFN0YWNrKSB7CiAgICB0aGlzLnN0YWNrID0gaW5pdGlhbFN0YWNrID8gQXJyYXkuZnJvbShpbml0aWFsU3RhY2spIDogW107CiAgfQogIHB1c2godmFsdWUpIHsKICAgIGlmICh0aGlzLnN0YWNrLmxlbmd0aCA+PSBQb3N0U2NyaXB0U3RhY2suTUFYX1NUQUNLX1NJWkUpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJQb3N0U2NyaXB0IGZ1bmN0aW9uIHN0YWNrIG92ZXJmbG93LiIpOwogICAgfQogICAgdGhpcy5zdGFjay5wdXNoKHZhbHVlKTsKICB9CiAgcG9wKCkgewogICAgaWYgKHRoaXMuc3RhY2subGVuZ3RoIDw9IDApIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJQb3N0U2NyaXB0IGZ1bmN0aW9uIHN0YWNrIHVuZGVyZmxvdy4iKTsKICAgIH0KICAgIHJldHVybiB0aGlzLnN0YWNrLnBvcCgpOwogIH0KICBjb3B5KG4pIHsKICAgIGlmICh0aGlzLnN0YWNrLmxlbmd0aCArIG4gPj0gUG9zdFNjcmlwdFN0YWNrLk1BWF9TVEFDS19TSVpFKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiUG9zdFNjcmlwdCBmdW5jdGlvbiBzdGFjayBvdmVyZmxvdy4iKTsKICAgIH0KICAgIGNvbnN0IHN0YWNrID0gdGhpcy5zdGFjazsKICAgIGZvciAobGV0IGkgPSBzdGFjay5sZW5ndGggLSBuLCBqID0gbiAtIDE7IGogPj0gMDsgai0tLCBpKyspIHsKICAgICAgc3RhY2sucHVzaChzdGFja1tpXSk7CiAgICB9CiAgfQogIGluZGV4KG4pIHsKICAgIHRoaXMucHVzaCh0aGlzLnN0YWNrW3RoaXMuc3RhY2subGVuZ3RoIC0gbiAtIDFdKTsKICB9CiAgcm9sbChuLCBwKSB7CiAgICBjb25zdCBzdGFjayA9IHRoaXMuc3RhY2s7CiAgICBjb25zdCBsID0gc3RhY2subGVuZ3RoIC0gbjsKICAgIGNvbnN0IHIgPSBzdGFjay5sZW5ndGggLSAxOwogICAgY29uc3QgYyA9IGwgKyAocCAtIE1hdGguZmxvb3IocCAvIG4pICogbik7CiAgICBmb3IgKGxldCBpID0gbCwgaiA9IHI7IGkgPCBqOyBpKyssIGotLSkgewogICAgICBjb25zdCB0ID0gc3RhY2tbaV07CiAgICAgIHN0YWNrW2ldID0gc3RhY2tbal07CiAgICAgIHN0YWNrW2pdID0gdDsKICAgIH0KICAgIGZvciAobGV0IGkgPSBsLCBqID0gYyAtIDE7IGkgPCBqOyBpKyssIGotLSkgewogICAgICBjb25zdCB0ID0gc3RhY2tbaV07CiAgICAgIHN0YWNrW2ldID0gc3RhY2tbal07CiAgICAgIHN0YWNrW2pdID0gdDsKICAgIH0KICAgIGZvciAobGV0IGkgPSBjLCBqID0gcjsgaSA8IGo7IGkrKywgai0tKSB7CiAgICAgIGNvbnN0IHQgPSBzdGFja1tpXTsKICAgICAgc3RhY2tbaV0gPSBzdGFja1tqXTsKICAgICAgc3RhY2tbal0gPSB0OwogICAgfQogIH0KfQpjbGFzcyBQb3N0U2NyaXB0RXZhbHVhdG9yIHsKICBjb25zdHJ1Y3RvcihvcGVyYXRvcnMpIHsKICAgIHRoaXMub3BlcmF0b3JzID0gb3BlcmF0b3JzOwogIH0KICBleGVjdXRlKGluaXRpYWxTdGFjaykgewogICAgY29uc3Qgc3RhY2sgPSBuZXcgUG9zdFNjcmlwdFN0YWNrKGluaXRpYWxTdGFjayk7CiAgICBsZXQgY291bnRlciA9IDA7CiAgICBjb25zdCBvcGVyYXRvcnMgPSB0aGlzLm9wZXJhdG9yczsKICAgIGNvbnN0IGxlbmd0aCA9IG9wZXJhdG9ycy5sZW5ndGg7CiAgICBsZXQgb3BlcmF0b3IsIGEsIGI7CiAgICB3aGlsZSAoY291bnRlciA8IGxlbmd0aCkgewogICAgICBvcGVyYXRvciA9IG9wZXJhdG9yc1tjb3VudGVyKytdOwogICAgICBpZiAodHlwZW9mIG9wZXJhdG9yID09PSAibnVtYmVyIikgewogICAgICAgIHN0YWNrLnB1c2gob3BlcmF0b3IpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHN3aXRjaCAob3BlcmF0b3IpIHsKICAgICAgICBjYXNlICJqeiI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBpZiAoIWEpIHsKICAgICAgICAgICAgY291bnRlciA9IGI7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJqIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGNvdW50ZXIgPSBhOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiYWJzIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goTWF0aC5hYnMoYSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiYWRkIjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYSArIGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiYW5kIjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGlmICh0eXBlb2YgYSA9PT0gImJvb2xlYW4iICYmIHR5cGVvZiBiID09PSAiYm9vbGVhbiIpIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhICYmIGIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhICYgYik7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJhdGFuIjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBNYXRoLmF0YW4yKGEsIGIpIC8gTWF0aC5QSSAqIDE4MDsKICAgICAgICAgIGlmIChhIDwgMCkgewogICAgICAgICAgICBhICs9IDM2MDsKICAgICAgICAgIH0KICAgICAgICAgIHN0YWNrLnB1c2goYSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJiaXRzaGlmdCI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBpZiAoYSA+IDApIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhIDw8IGIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhID4+IGIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiY2VpbGluZyI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKE1hdGguY2VpbChhKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJjb3B5IjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLmNvcHkoYSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJjb3MiOgogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChNYXRoLmNvcyhhICUgMzYwIC8gMTgwICogTWF0aC5QSSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiY3ZpIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKSB8IDA7CiAgICAgICAgICBzdGFjay5wdXNoKGEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiY3ZyIjoKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImRpdiI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgLyBiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImR1cCI6CiAgICAgICAgICBzdGFjay5jb3B5KDEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZXEiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhID09PSBiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImV4Y2giOgogICAgICAgICAgc3RhY2sucm9sbCgyLCAxKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImV4cCI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgKiogYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJmYWxzZSI6CiAgICAgICAgICBzdGFjay5wdXNoKGZhbHNlKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImZsb29yIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goTWF0aC5mbG9vcihhKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJnZSI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgPj0gYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJndCI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgPiBiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImlkaXYiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhIC8gYiB8IDApOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiaW5kZXgiOgogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2suaW5kZXgoYSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJsZSI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgPD0gYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJsbiI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKE1hdGgubG9nKGEpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImxvZyI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKE1hdGgubG9nKGEpIC8gTWF0aC5MTjEwKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImx0IjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYSA8IGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibW9kIjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYSAlIGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibXVsIjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYSAqIGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibmUiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhICE9PSBiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm5lZyI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKC1hKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm5vdCI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBpZiAodHlwZW9mIGEgPT09ICJib29sZWFuIikgewogICAgICAgICAgICBzdGFjay5wdXNoKCFhKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2gofmEpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAib3IiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgaWYgKHR5cGVvZiBhID09PSAiYm9vbGVhbiIgJiYgdHlwZW9mIGIgPT09ICJib29sZWFuIikgewogICAgICAgICAgICBzdGFjay5wdXNoKGEgfHwgYik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdGFjay5wdXNoKGEgfCBiKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInBvcCI6CiAgICAgICAgICBzdGFjay5wb3AoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInJvbGwiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucm9sbChhLCBiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInJvdW5kIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goTWF0aC5yb3VuZChhKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJzaW4iOgogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChNYXRoLnNpbihhICUgMzYwIC8gMTgwICogTWF0aC5QSSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAic3FydCI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKE1hdGguc3FydChhKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJzdWIiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhIC0gYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJ0cnVlIjoKICAgICAgICAgIHN0YWNrLnB1c2godHJ1ZSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJ0cnVuY2F0ZSI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gYSA8IDAgPyBNYXRoLmNlaWwoYSkgOiBNYXRoLmZsb29yKGEpOwogICAgICAgICAgc3RhY2sucHVzaChhKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInhvciI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBpZiAodHlwZW9mIGEgPT09ICJib29sZWFuIiAmJiB0eXBlb2YgYiA9PT0gImJvb2xlYW4iKSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goYSAhPT0gYik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdGFjay5wdXNoKGEgXiBiKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYFVua25vd24gb3BlcmF0b3IgJHtvcGVyYXRvcn1gKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHN0YWNrLnN0YWNrOwogIH0KfQpleHBvcnRzLlBvc3RTY3JpcHRFdmFsdWF0b3IgPSBQb3N0U2NyaXB0RXZhbHVhdG9yOwpjbGFzcyBBc3ROb2RlIHsKICBjb25zdHJ1Y3Rvcih0eXBlKSB7CiAgICB0aGlzLnR5cGUgPSB0eXBlOwogIH0KICB2aXNpdCh2aXNpdG9yKSB7CiAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJhYnN0cmFjdCBtZXRob2QiKTsKICB9Cn0KY2xhc3MgQXN0QXJndW1lbnQgZXh0ZW5kcyBBc3ROb2RlIHsKICBjb25zdHJ1Y3RvcihpbmRleCwgbWluLCBtYXgpIHsKICAgIHN1cGVyKCJhcmdzIik7CiAgICB0aGlzLmluZGV4ID0gaW5kZXg7CiAgICB0aGlzLm1pbiA9IG1pbjsKICAgIHRoaXMubWF4ID0gbWF4OwogIH0KICB2aXNpdCh2aXNpdG9yKSB7CiAgICB2aXNpdG9yLnZpc2l0QXJndW1lbnQodGhpcyk7CiAgfQp9CmNsYXNzIEFzdExpdGVyYWwgZXh0ZW5kcyBBc3ROb2RlIHsKICBjb25zdHJ1Y3RvcihudW1iZXIpIHsKICAgIHN1cGVyKCJsaXRlcmFsIik7CiAgICB0aGlzLm51bWJlciA9IG51bWJlcjsKICAgIHRoaXMubWluID0gbnVtYmVyOwogICAgdGhpcy5tYXggPSBudW1iZXI7CiAgfQogIHZpc2l0KHZpc2l0b3IpIHsKICAgIHZpc2l0b3IudmlzaXRMaXRlcmFsKHRoaXMpOwogIH0KfQpjbGFzcyBBc3RCaW5hcnlPcGVyYXRpb24gZXh0ZW5kcyBBc3ROb2RlIHsKICBjb25zdHJ1Y3RvcihvcCwgYXJnMSwgYXJnMiwgbWluLCBtYXgpIHsKICAgIHN1cGVyKCJiaW5hcnkiKTsKICAgIHRoaXMub3AgPSBvcDsKICAgIHRoaXMuYXJnMSA9IGFyZzE7CiAgICB0aGlzLmFyZzIgPSBhcmcyOwogICAgdGhpcy5taW4gPSBtaW47CiAgICB0aGlzLm1heCA9IG1heDsKICB9CiAgdmlzaXQodmlzaXRvcikgewogICAgdmlzaXRvci52aXNpdEJpbmFyeU9wZXJhdGlvbih0aGlzKTsKICB9Cn0KY2xhc3MgQXN0TWluIGV4dGVuZHMgQXN0Tm9kZSB7CiAgY29uc3RydWN0b3IoYXJnLCBtYXgpIHsKICAgIHN1cGVyKCJtYXgiKTsKICAgIHRoaXMuYXJnID0gYXJnOwogICAgdGhpcy5taW4gPSBhcmcubWluOwogICAgdGhpcy5tYXggPSBtYXg7CiAgfQogIHZpc2l0KHZpc2l0b3IpIHsKICAgIHZpc2l0b3IudmlzaXRNaW4odGhpcyk7CiAgfQp9CmNsYXNzIEFzdFZhcmlhYmxlIGV4dGVuZHMgQXN0Tm9kZSB7CiAgY29uc3RydWN0b3IoaW5kZXgsIG1pbiwgbWF4KSB7CiAgICBzdXBlcigidmFyIik7CiAgICB0aGlzLmluZGV4ID0gaW5kZXg7CiAgICB0aGlzLm1pbiA9IG1pbjsKICAgIHRoaXMubWF4ID0gbWF4OwogIH0KICB2aXNpdCh2aXNpdG9yKSB7CiAgICB2aXNpdG9yLnZpc2l0VmFyaWFibGUodGhpcyk7CiAgfQp9CmNsYXNzIEFzdFZhcmlhYmxlRGVmaW5pdGlvbiBleHRlbmRzIEFzdE5vZGUgewogIGNvbnN0cnVjdG9yKHZhcmlhYmxlLCBhcmcpIHsKICAgIHN1cGVyKCJkZWZpbml0aW9uIik7CiAgICB0aGlzLnZhcmlhYmxlID0gdmFyaWFibGU7CiAgICB0aGlzLmFyZyA9IGFyZzsKICB9CiAgdmlzaXQodmlzaXRvcikgewogICAgdmlzaXRvci52aXNpdFZhcmlhYmxlRGVmaW5pdGlvbih0aGlzKTsKICB9Cn0KY2xhc3MgRXhwcmVzc2lvbkJ1aWxkZXJWaXNpdG9yIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMucGFydHMgPSBbXTsKICB9CiAgdmlzaXRBcmd1bWVudChhcmcpIHsKICAgIHRoaXMucGFydHMucHVzaCgiTWF0aC5tYXgoIiwgYXJnLm1pbiwgIiwgTWF0aC5taW4oIiwgYXJnLm1heCwgIiwgc3JjW3NyY09mZnNldCArICIsIGFyZy5pbmRleCwgIl0pKSIpOwogIH0KICB2aXNpdFZhcmlhYmxlKHZhcmlhYmxlKSB7CiAgICB0aGlzLnBhcnRzLnB1c2goInYiLCB2YXJpYWJsZS5pbmRleCk7CiAgfQogIHZpc2l0TGl0ZXJhbChsaXRlcmFsKSB7CiAgICB0aGlzLnBhcnRzLnB1c2gobGl0ZXJhbC5udW1iZXIpOwogIH0KICB2aXNpdEJpbmFyeU9wZXJhdGlvbihvcGVyYXRpb24pIHsKICAgIHRoaXMucGFydHMucHVzaCgiKCIpOwogICAgb3BlcmF0aW9uLmFyZzEudmlzaXQodGhpcyk7CiAgICB0aGlzLnBhcnRzLnB1c2goIiAiLCBvcGVyYXRpb24ub3AsICIgIik7CiAgICBvcGVyYXRpb24uYXJnMi52aXNpdCh0aGlzKTsKICAgIHRoaXMucGFydHMucHVzaCgiKSIpOwogIH0KICB2aXNpdFZhcmlhYmxlRGVmaW5pdGlvbihkZWZpbml0aW9uKSB7CiAgICB0aGlzLnBhcnRzLnB1c2goInZhciAiKTsKICAgIGRlZmluaXRpb24udmFyaWFibGUudmlzaXQodGhpcyk7CiAgICB0aGlzLnBhcnRzLnB1c2goIiA9ICIpOwogICAgZGVmaW5pdGlvbi5hcmcudmlzaXQodGhpcyk7CiAgICB0aGlzLnBhcnRzLnB1c2goIjsiKTsKICB9CiAgdmlzaXRNaW4obWF4KSB7CiAgICB0aGlzLnBhcnRzLnB1c2goIk1hdGgubWluKCIpOwogICAgbWF4LmFyZy52aXNpdCh0aGlzKTsKICAgIHRoaXMucGFydHMucHVzaCgiLCAiLCBtYXgubWF4LCAiKSIpOwogIH0KICB0b1N0cmluZygpIHsKICAgIHJldHVybiB0aGlzLnBhcnRzLmpvaW4oIiIpOwogIH0KfQpmdW5jdGlvbiBidWlsZEFkZE9wZXJhdGlvbihudW0xLCBudW0yKSB7CiAgaWYgKG51bTIudHlwZSA9PT0gImxpdGVyYWwiICYmIG51bTIubnVtYmVyID09PSAwKSB7CiAgICByZXR1cm4gbnVtMTsKICB9CiAgaWYgKG51bTEudHlwZSA9PT0gImxpdGVyYWwiICYmIG51bTEubnVtYmVyID09PSAwKSB7CiAgICByZXR1cm4gbnVtMjsKICB9CiAgaWYgKG51bTIudHlwZSA9PT0gImxpdGVyYWwiICYmIG51bTEudHlwZSA9PT0gImxpdGVyYWwiKSB7CiAgICByZXR1cm4gbmV3IEFzdExpdGVyYWwobnVtMS5udW1iZXIgKyBudW0yLm51bWJlcik7CiAgfQogIHJldHVybiBuZXcgQXN0QmluYXJ5T3BlcmF0aW9uKCIrIiwgbnVtMSwgbnVtMiwgbnVtMS5taW4gKyBudW0yLm1pbiwgbnVtMS5tYXggKyBudW0yLm1heCk7Cn0KZnVuY3Rpb24gYnVpbGRNdWxPcGVyYXRpb24obnVtMSwgbnVtMikgewogIGlmIChudW0yLnR5cGUgPT09ICJsaXRlcmFsIikgewogICAgaWYgKG51bTIubnVtYmVyID09PSAwKSB7CiAgICAgIHJldHVybiBuZXcgQXN0TGl0ZXJhbCgwKTsKICAgIH0gZWxzZSBpZiAobnVtMi5udW1iZXIgPT09IDEpIHsKICAgICAgcmV0dXJuIG51bTE7CiAgICB9IGVsc2UgaWYgKG51bTEudHlwZSA9PT0gImxpdGVyYWwiKSB7CiAgICAgIHJldHVybiBuZXcgQXN0TGl0ZXJhbChudW0xLm51bWJlciAqIG51bTIubnVtYmVyKTsKICAgIH0KICB9CiAgaWYgKG51bTEudHlwZSA9PT0gImxpdGVyYWwiKSB7CiAgICBpZiAobnVtMS5udW1iZXIgPT09IDApIHsKICAgICAgcmV0dXJuIG5ldyBBc3RMaXRlcmFsKDApOwogICAgfSBlbHNlIGlmIChudW0xLm51bWJlciA9PT0gMSkgewogICAgICByZXR1cm4gbnVtMjsKICAgIH0KICB9CiAgY29uc3QgbWluID0gTWF0aC5taW4obnVtMS5taW4gKiBudW0yLm1pbiwgbnVtMS5taW4gKiBudW0yLm1heCwgbnVtMS5tYXggKiBudW0yLm1pbiwgbnVtMS5tYXggKiBudW0yLm1heCk7CiAgY29uc3QgbWF4ID0gTWF0aC5tYXgobnVtMS5taW4gKiBudW0yLm1pbiwgbnVtMS5taW4gKiBudW0yLm1heCwgbnVtMS5tYXggKiBudW0yLm1pbiwgbnVtMS5tYXggKiBudW0yLm1heCk7CiAgcmV0dXJuIG5ldyBBc3RCaW5hcnlPcGVyYXRpb24oIioiLCBudW0xLCBudW0yLCBtaW4sIG1heCk7Cn0KZnVuY3Rpb24gYnVpbGRTdWJPcGVyYXRpb24obnVtMSwgbnVtMikgewogIGlmIChudW0yLnR5cGUgPT09ICJsaXRlcmFsIikgewogICAgaWYgKG51bTIubnVtYmVyID09PSAwKSB7CiAgICAgIHJldHVybiBudW0xOwogICAgfSBlbHNlIGlmIChudW0xLnR5cGUgPT09ICJsaXRlcmFsIikgewogICAgICByZXR1cm4gbmV3IEFzdExpdGVyYWwobnVtMS5udW1iZXIgLSBudW0yLm51bWJlcik7CiAgICB9CiAgfQogIGlmIChudW0yLnR5cGUgPT09ICJiaW5hcnkiICYmIG51bTIub3AgPT09ICItIiAmJiBudW0xLnR5cGUgPT09ICJsaXRlcmFsIiAmJiBudW0xLm51bWJlciA9PT0gMSAmJiBudW0yLmFyZzEudHlwZSA9PT0gImxpdGVyYWwiICYmIG51bTIuYXJnMS5udW1iZXIgPT09IDEpIHsKICAgIHJldHVybiBudW0yLmFyZzI7CiAgfQogIHJldHVybiBuZXcgQXN0QmluYXJ5T3BlcmF0aW9uKCItIiwgbnVtMSwgbnVtMiwgbnVtMS5taW4gLSBudW0yLm1heCwgbnVtMS5tYXggLSBudW0yLm1pbik7Cn0KZnVuY3Rpb24gYnVpbGRNaW5PcGVyYXRpb24obnVtMSwgbWF4KSB7CiAgaWYgKG51bTEubWluID49IG1heCkgewogICAgcmV0dXJuIG5ldyBBc3RMaXRlcmFsKG1heCk7CiAgfSBlbHNlIGlmIChudW0xLm1heCA8PSBtYXgpIHsKICAgIHJldHVybiBudW0xOwogIH0KICByZXR1cm4gbmV3IEFzdE1pbihudW0xLCBtYXgpOwp9CmNsYXNzIFBvc3RTY3JpcHRDb21waWxlciB7CiAgY29tcGlsZShjb2RlLCBkb21haW4sIHJhbmdlKSB7CiAgICBjb25zdCBzdGFjayA9IFtdOwogICAgY29uc3QgaW5zdHJ1Y3Rpb25zID0gW107CiAgICBjb25zdCBpbnB1dFNpemUgPSBkb21haW4ubGVuZ3RoID4+IDEsCiAgICAgIG91dHB1dFNpemUgPSByYW5nZS5sZW5ndGggPj4gMTsKICAgIGxldCBsYXN0UmVnaXN0ZXIgPSAwOwogICAgbGV0IG4sIGo7CiAgICBsZXQgbnVtMSwgbnVtMiwgYXN0MSwgYXN0MiwgdG1wVmFyLCBpdGVtOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dFNpemU7IGkrKykgewogICAgICBzdGFjay5wdXNoKG5ldyBBc3RBcmd1bWVudChpLCBkb21haW5baSAqIDJdLCBkb21haW5baSAqIDIgKyAxXSkpOwogICAgfQogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gY29kZS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGl0ZW0gPSBjb2RlW2ldOwogICAgICBpZiAodHlwZW9mIGl0ZW0gPT09ICJudW1iZXIiKSB7CiAgICAgICAgc3RhY2sucHVzaChuZXcgQXN0TGl0ZXJhbChpdGVtKSk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgc3dpdGNoIChpdGVtKSB7CiAgICAgICAgY2FzZSAiYWRkIjoKICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPCAyKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgbnVtMiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgbnVtMSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChidWlsZEFkZE9wZXJhdGlvbihudW0xLCBudW0yKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJjdnIiOgogICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA8IDEpIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJtdWwiOgogICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA8IDIpIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBudW0yID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBudW0xID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGJ1aWxkTXVsT3BlcmF0aW9uKG51bTEsIG51bTIpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInN1YiI6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoIDwgMikgewogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIG51bTIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIG51bTEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYnVpbGRTdWJPcGVyYXRpb24obnVtMSwgbnVtMikpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZXhjaCI6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoIDwgMikgewogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIGFzdDEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGFzdDIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYXN0MSwgYXN0Mik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJwb3AiOgogICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA8IDEpIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBzdGFjay5wb3AoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImluZGV4IjoKICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPCAxKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgbnVtMSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgaWYgKG51bTEudHlwZSAhPT0gImxpdGVyYWwiKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgbiA9IG51bTEubnVtYmVyOwogICAgICAgICAgaWYgKG4gPCAwIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKG4pIHx8IHN0YWNrLmxlbmd0aCA8IG4pIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBhc3QxID0gc3RhY2tbc3RhY2subGVuZ3RoIC0gbiAtIDFdOwogICAgICAgICAgaWYgKGFzdDEudHlwZSA9PT0gImxpdGVyYWwiIHx8IGFzdDEudHlwZSA9PT0gInZhciIpIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhc3QxKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICB0bXBWYXIgPSBuZXcgQXN0VmFyaWFibGUobGFzdFJlZ2lzdGVyKyssIGFzdDEubWluLCBhc3QxLm1heCk7CiAgICAgICAgICBzdGFja1tzdGFjay5sZW5ndGggLSBuIC0gMV0gPSB0bXBWYXI7CiAgICAgICAgICBzdGFjay5wdXNoKHRtcFZhcik7CiAgICAgICAgICBpbnN0cnVjdGlvbnMucHVzaChuZXcgQXN0VmFyaWFibGVEZWZpbml0aW9uKHRtcFZhciwgYXN0MSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZHVwIjoKICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPCAxKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHR5cGVvZiBjb2RlW2kgKyAxXSA9PT0gIm51bWJlciIgJiYgY29kZVtpICsgMl0gPT09ICJndCIgJiYgY29kZVtpICsgM10gPT09IGkgKyA3ICYmIGNvZGVbaSArIDRdID09PSAianoiICYmIGNvZGVbaSArIDVdID09PSAicG9wIiAmJiBjb2RlW2kgKyA2XSA9PT0gY29kZVtpICsgMV0pIHsKICAgICAgICAgICAgbnVtMSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgICBzdGFjay5wdXNoKGJ1aWxkTWluT3BlcmF0aW9uKG51bTEsIGNvZGVbaSArIDFdKSk7CiAgICAgICAgICAgIGkgKz0gNjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBhc3QxID0gc3RhY2suYXQoLTEpOwogICAgICAgICAgaWYgKGFzdDEudHlwZSA9PT0gImxpdGVyYWwiIHx8IGFzdDEudHlwZSA9PT0gInZhciIpIHsKICAgICAgICAgICAgc3RhY2sucHVzaChhc3QxKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICB0bXBWYXIgPSBuZXcgQXN0VmFyaWFibGUobGFzdFJlZ2lzdGVyKyssIGFzdDEubWluLCBhc3QxLm1heCk7CiAgICAgICAgICBzdGFja1tzdGFjay5sZW5ndGggLSAxXSA9IHRtcFZhcjsKICAgICAgICAgIHN0YWNrLnB1c2godG1wVmFyKTsKICAgICAgICAgIGluc3RydWN0aW9ucy5wdXNoKG5ldyBBc3RWYXJpYWJsZURlZmluaXRpb24odG1wVmFyLCBhc3QxKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJyb2xsIjoKICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPCAyKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgbnVtMiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgbnVtMSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgaWYgKG51bTIudHlwZSAhPT0gImxpdGVyYWwiIHx8IG51bTEudHlwZSAhPT0gImxpdGVyYWwiKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgaiA9IG51bTIubnVtYmVyOwogICAgICAgICAgbiA9IG51bTEubnVtYmVyOwogICAgICAgICAgaWYgKG4gPD0gMCB8fCAhTnVtYmVyLmlzSW50ZWdlcihuKSB8fCAhTnVtYmVyLmlzSW50ZWdlcihqKSB8fCBzdGFjay5sZW5ndGggPCBuKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgaiA9IChqICUgbiArIG4pICUgbjsKICAgICAgICAgIGlmIChqID09PSAwKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgc3RhY2sucHVzaCguLi5zdGFjay5zcGxpY2Uoc3RhY2subGVuZ3RoIC0gbiwgbiAtIGopKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQogICAgaWYgKHN0YWNrLmxlbmd0aCAhPT0gb3V0cHV0U2l6ZSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHJlc3VsdCA9IFtdOwogICAgZm9yIChjb25zdCBpbnN0cnVjdGlvbiBvZiBpbnN0cnVjdGlvbnMpIHsKICAgICAgY29uc3Qgc3RhdGVtZW50QnVpbGRlciA9IG5ldyBFeHByZXNzaW9uQnVpbGRlclZpc2l0b3IoKTsKICAgICAgaW5zdHJ1Y3Rpb24udmlzaXQoc3RhdGVtZW50QnVpbGRlcik7CiAgICAgIHJlc3VsdC5wdXNoKHN0YXRlbWVudEJ1aWxkZXIudG9TdHJpbmcoKSk7CiAgICB9CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBzdGFjay5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IGV4cHIgPSBzdGFja1tpXSwKICAgICAgICBzdGF0ZW1lbnRCdWlsZGVyID0gbmV3IEV4cHJlc3Npb25CdWlsZGVyVmlzaXRvcigpOwogICAgICBleHByLnZpc2l0KHN0YXRlbWVudEJ1aWxkZXIpOwogICAgICBjb25zdCBtaW4gPSByYW5nZVtpICogMl0sCiAgICAgICAgbWF4ID0gcmFuZ2VbaSAqIDIgKyAxXTsKICAgICAgY29uc3Qgb3V0ID0gW3N0YXRlbWVudEJ1aWxkZXIudG9TdHJpbmcoKV07CiAgICAgIGlmIChtaW4gPiBleHByLm1pbikgewogICAgICAgIG91dC51bnNoaWZ0KCJNYXRoLm1heCgiLCBtaW4sICIsICIpOwogICAgICAgIG91dC5wdXNoKCIpIik7CiAgICAgIH0KICAgICAgaWYgKG1heCA8IGV4cHIubWF4KSB7CiAgICAgICAgb3V0LnVuc2hpZnQoIk1hdGgubWluKCIsIG1heCwgIiwgIik7CiAgICAgICAgb3V0LnB1c2goIikiKTsKICAgICAgfQogICAgICBvdXQudW5zaGlmdCgiZGVzdFtkZXN0T2Zmc2V0ICsgIiwgaSwgIl0gPSAiKTsKICAgICAgb3V0LnB1c2goIjsiKTsKICAgICAgcmVzdWx0LnB1c2gob3V0LmpvaW4oIiIpKTsKICAgIH0KICAgIHJldHVybiByZXN1bHQuam9pbigiXG4iKTsKICB9Cn0KZXhwb3J0cy5Qb3N0U2NyaXB0Q29tcGlsZXIgPSBQb3N0U2NyaXB0Q29tcGlsZXI7CgovKioqLyB9KSwKLyogMTkzICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5Qb3N0U2NyaXB0UGFyc2VyID0gZXhwb3J0cy5Qb3N0U2NyaXB0TGV4ZXIgPSB2b2lkIDA7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CnZhciBfcHJpbWl0aXZlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQwKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwpjbGFzcyBQb3N0U2NyaXB0UGFyc2VyIHsKICBjb25zdHJ1Y3RvcihsZXhlcikgewogICAgdGhpcy5sZXhlciA9IGxleGVyOwogICAgdGhpcy5vcGVyYXRvcnMgPSBbXTsKICAgIHRoaXMudG9rZW4gPSBudWxsOwogICAgdGhpcy5wcmV2ID0gbnVsbDsKICB9CiAgbmV4dFRva2VuKCkgewogICAgdGhpcy5wcmV2ID0gdGhpcy50b2tlbjsKICAgIHRoaXMudG9rZW4gPSB0aGlzLmxleGVyLmdldFRva2VuKCk7CiAgfQogIGFjY2VwdCh0eXBlKSB7CiAgICBpZiAodGhpcy50b2tlbi50eXBlID09PSB0eXBlKSB7CiAgICAgIHRoaXMubmV4dFRva2VuKCk7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KICBleHBlY3QodHlwZSkgewogICAgaWYgKHRoaXMuYWNjZXB0KHR5cGUpKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBVbmV4cGVjdGVkIHN5bWJvbDogZm91bmQgJHt0aGlzLnRva2VuLnR5cGV9IGV4cGVjdGVkICR7dHlwZX0uYCk7CiAgfQogIHBhcnNlKCkgewogICAgdGhpcy5uZXh0VG9rZW4oKTsKICAgIHRoaXMuZXhwZWN0KFBvc3RTY3JpcHRUb2tlblR5cGVzLkxCUkFDRSk7CiAgICB0aGlzLnBhcnNlQmxvY2soKTsKICAgIHRoaXMuZXhwZWN0KFBvc3RTY3JpcHRUb2tlblR5cGVzLlJCUkFDRSk7CiAgICByZXR1cm4gdGhpcy5vcGVyYXRvcnM7CiAgfQogIHBhcnNlQmxvY2soKSB7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBpZiAodGhpcy5hY2NlcHQoUG9zdFNjcmlwdFRva2VuVHlwZXMuTlVNQkVSKSkgewogICAgICAgIHRoaXMub3BlcmF0b3JzLnB1c2godGhpcy5wcmV2LnZhbHVlKTsKICAgICAgfSBlbHNlIGlmICh0aGlzLmFjY2VwdChQb3N0U2NyaXB0VG9rZW5UeXBlcy5PUEVSQVRPUikpIHsKICAgICAgICB0aGlzLm9wZXJhdG9ycy5wdXNoKHRoaXMucHJldi52YWx1ZSk7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5hY2NlcHQoUG9zdFNjcmlwdFRva2VuVHlwZXMuTEJSQUNFKSkgewogICAgICAgIHRoaXMucGFyc2VDb25kaXRpb24oKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgIH0KICB9CiAgcGFyc2VDb25kaXRpb24oKSB7CiAgICBjb25zdCBjb25kaXRpb25Mb2NhdGlvbiA9IHRoaXMub3BlcmF0b3JzLmxlbmd0aDsKICAgIHRoaXMub3BlcmF0b3JzLnB1c2gobnVsbCwgbnVsbCk7CiAgICB0aGlzLnBhcnNlQmxvY2soKTsKICAgIHRoaXMuZXhwZWN0KFBvc3RTY3JpcHRUb2tlblR5cGVzLlJCUkFDRSk7CiAgICBpZiAodGhpcy5hY2NlcHQoUG9zdFNjcmlwdFRva2VuVHlwZXMuSUYpKSB7CiAgICAgIHRoaXMub3BlcmF0b3JzW2NvbmRpdGlvbkxvY2F0aW9uXSA9IHRoaXMub3BlcmF0b3JzLmxlbmd0aDsKICAgICAgdGhpcy5vcGVyYXRvcnNbY29uZGl0aW9uTG9jYXRpb24gKyAxXSA9ICJqeiI7CiAgICB9IGVsc2UgaWYgKHRoaXMuYWNjZXB0KFBvc3RTY3JpcHRUb2tlblR5cGVzLkxCUkFDRSkpIHsKICAgICAgY29uc3QganVtcExvY2F0aW9uID0gdGhpcy5vcGVyYXRvcnMubGVuZ3RoOwogICAgICB0aGlzLm9wZXJhdG9ycy5wdXNoKG51bGwsIG51bGwpOwogICAgICBjb25zdCBlbmRPZlRydWUgPSB0aGlzLm9wZXJhdG9ycy5sZW5ndGg7CiAgICAgIHRoaXMucGFyc2VCbG9jaygpOwogICAgICB0aGlzLmV4cGVjdChQb3N0U2NyaXB0VG9rZW5UeXBlcy5SQlJBQ0UpOwogICAgICB0aGlzLmV4cGVjdChQb3N0U2NyaXB0VG9rZW5UeXBlcy5JRkVMU0UpOwogICAgICB0aGlzLm9wZXJhdG9yc1tqdW1wTG9jYXRpb25dID0gdGhpcy5vcGVyYXRvcnMubGVuZ3RoOwogICAgICB0aGlzLm9wZXJhdG9yc1tqdW1wTG9jYXRpb24gKyAxXSA9ICJqIjsKICAgICAgdGhpcy5vcGVyYXRvcnNbY29uZGl0aW9uTG9jYXRpb25dID0gZW5kT2ZUcnVlOwogICAgICB0aGlzLm9wZXJhdG9yc1tjb25kaXRpb25Mb2NhdGlvbiArIDFdID0gImp6IjsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiUFMgRnVuY3Rpb246IGVycm9yIHBhcnNpbmcgY29uZGl0aW9uYWwuIik7CiAgICB9CiAgfQp9CmV4cG9ydHMuUG9zdFNjcmlwdFBhcnNlciA9IFBvc3RTY3JpcHRQYXJzZXI7CmNvbnN0IFBvc3RTY3JpcHRUb2tlblR5cGVzID0gewogIExCUkFDRTogMCwKICBSQlJBQ0U6IDEsCiAgTlVNQkVSOiAyLAogIE9QRVJBVE9SOiAzLAogIElGOiA0LAogIElGRUxTRTogNQp9OwpjbGFzcyBQb3N0U2NyaXB0VG9rZW4gewogIHN0YXRpYyBnZXQgb3BDYWNoZSgpIHsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAib3BDYWNoZSIsIE9iamVjdC5jcmVhdGUobnVsbCkpOwogIH0KICBjb25zdHJ1Y3Rvcih0eXBlLCB2YWx1ZSkgewogICAgdGhpcy50eXBlID0gdHlwZTsKICAgIHRoaXMudmFsdWUgPSB2YWx1ZTsKICB9CiAgc3RhdGljIGdldE9wZXJhdG9yKG9wKSB7CiAgICBjb25zdCBvcFZhbHVlID0gUG9zdFNjcmlwdFRva2VuLm9wQ2FjaGVbb3BdOwogICAgaWYgKG9wVmFsdWUpIHsKICAgICAgcmV0dXJuIG9wVmFsdWU7CiAgICB9CiAgICByZXR1cm4gUG9zdFNjcmlwdFRva2VuLm9wQ2FjaGVbb3BdID0gbmV3IFBvc3RTY3JpcHRUb2tlbihQb3N0U2NyaXB0VG9rZW5UeXBlcy5PUEVSQVRPUiwgb3ApOwogIH0KICBzdGF0aWMgZ2V0IExCUkFDRSgpIHsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiTEJSQUNFIiwgbmV3IFBvc3RTY3JpcHRUb2tlbihQb3N0U2NyaXB0VG9rZW5UeXBlcy5MQlJBQ0UsICJ7IikpOwogIH0KICBzdGF0aWMgZ2V0IFJCUkFDRSgpIHsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiUkJSQUNFIiwgbmV3IFBvc3RTY3JpcHRUb2tlbihQb3N0U2NyaXB0VG9rZW5UeXBlcy5SQlJBQ0UsICJ9IikpOwogIH0KICBzdGF0aWMgZ2V0IElGKCkgewogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJJRiIsIG5ldyBQb3N0U2NyaXB0VG9rZW4oUG9zdFNjcmlwdFRva2VuVHlwZXMuSUYsICJJRiIpKTsKICB9CiAgc3RhdGljIGdldCBJRkVMU0UoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIklGRUxTRSIsIG5ldyBQb3N0U2NyaXB0VG9rZW4oUG9zdFNjcmlwdFRva2VuVHlwZXMuSUZFTFNFLCAiSUZFTFNFIikpOwogIH0KfQpjbGFzcyBQb3N0U2NyaXB0TGV4ZXIgewogIGNvbnN0cnVjdG9yKHN0cmVhbSkgewogICAgdGhpcy5zdHJlYW0gPSBzdHJlYW07CiAgICB0aGlzLm5leHRDaGFyKCk7CiAgICB0aGlzLnN0ckJ1ZiA9IFtdOwogIH0KICBuZXh0Q2hhcigpIHsKICAgIHJldHVybiB0aGlzLmN1cnJlbnRDaGFyID0gdGhpcy5zdHJlYW0uZ2V0Qnl0ZSgpOwogIH0KICBnZXRUb2tlbigpIHsKICAgIGxldCBjb21tZW50ID0gZmFsc2U7CiAgICBsZXQgY2ggPSB0aGlzLmN1cnJlbnRDaGFyOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgaWYgKGNoIDwgMCkgewogICAgICAgIHJldHVybiBfcHJpbWl0aXZlcy5FT0Y7CiAgICAgIH0KICAgICAgaWYgKGNvbW1lbnQpIHsKICAgICAgICBpZiAoY2ggPT09IDB4MGEgfHwgY2ggPT09IDB4MGQpIHsKICAgICAgICAgIGNvbW1lbnQgPSBmYWxzZTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MjUpIHsKICAgICAgICBjb21tZW50ID0gdHJ1ZTsKICAgICAgfSBlbHNlIGlmICghKDAsIF9jb3JlX3V0aWxzLmlzV2hpdGVTcGFjZSkoY2gpKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICB9CiAgICBzd2l0Y2ggKGNoIHwgMCkgewogICAgICBjYXNlIDB4MzA6CiAgICAgIGNhc2UgMHgzMToKICAgICAgY2FzZSAweDMyOgogICAgICBjYXNlIDB4MzM6CiAgICAgIGNhc2UgMHgzNDoKICAgICAgY2FzZSAweDM1OgogICAgICBjYXNlIDB4MzY6CiAgICAgIGNhc2UgMHgzNzoKICAgICAgY2FzZSAweDM4OgogICAgICBjYXNlIDB4Mzk6CiAgICAgIGNhc2UgMHgyYjoKICAgICAgY2FzZSAweDJkOgogICAgICBjYXNlIDB4MmU6CiAgICAgICAgcmV0dXJuIG5ldyBQb3N0U2NyaXB0VG9rZW4oUG9zdFNjcmlwdFRva2VuVHlwZXMuTlVNQkVSLCB0aGlzLmdldE51bWJlcigpKTsKICAgICAgY2FzZSAweDdiOgogICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICByZXR1cm4gUG9zdFNjcmlwdFRva2VuLkxCUkFDRTsKICAgICAgY2FzZSAweDdkOgogICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICByZXR1cm4gUG9zdFNjcmlwdFRva2VuLlJCUkFDRTsKICAgIH0KICAgIGNvbnN0IHN0ckJ1ZiA9IHRoaXMuc3RyQnVmOwogICAgc3RyQnVmLmxlbmd0aCA9IDA7CiAgICBzdHJCdWZbMF0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKTsKICAgIHdoaWxlICgoY2ggPSB0aGlzLm5leHRDaGFyKCkpID49IDAgJiYgKGNoID49IDB4NDEgJiYgY2ggPD0gMHg1YSB8fCBjaCA+PSAweDYxICYmIGNoIDw9IDB4N2EpKSB7CiAgICAgIHN0ckJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpKTsKICAgIH0KICAgIGNvbnN0IHN0ciA9IHN0ckJ1Zi5qb2luKCIiKTsKICAgIHN3aXRjaCAoc3RyLnRvTG93ZXJDYXNlKCkpIHsKICAgICAgY2FzZSAiaWYiOgogICAgICAgIHJldHVybiBQb3N0U2NyaXB0VG9rZW4uSUY7CiAgICAgIGNhc2UgImlmZWxzZSI6CiAgICAgICAgcmV0dXJuIFBvc3RTY3JpcHRUb2tlbi5JRkVMU0U7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgcmV0dXJuIFBvc3RTY3JpcHRUb2tlbi5nZXRPcGVyYXRvcihzdHIpOwogICAgfQogIH0KICBnZXROdW1iZXIoKSB7CiAgICBsZXQgY2ggPSB0aGlzLmN1cnJlbnRDaGFyOwogICAgY29uc3Qgc3RyQnVmID0gdGhpcy5zdHJCdWY7CiAgICBzdHJCdWYubGVuZ3RoID0gMDsKICAgIHN0ckJ1ZlswXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpOwogICAgd2hpbGUgKChjaCA9IHRoaXMubmV4dENoYXIoKSkgPj0gMCkgewogICAgICBpZiAoY2ggPj0gMHgzMCAmJiBjaCA8PSAweDM5IHx8IGNoID09PSAweDJkIHx8IGNoID09PSAweDJlKSB7CiAgICAgICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjaCkpOwogICAgICB9IGVsc2UgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBjb25zdCB2YWx1ZSA9IHBhcnNlRmxvYXQoc3RyQnVmLmpvaW4oIiIpKTsKICAgIGlmIChpc05hTih2YWx1ZSkpIHsKICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBJbnZhbGlkIGZsb2F0aW5nIHBvaW50IG51bWJlcjogJHt2YWx1ZX1gKTsKICAgIH0KICAgIHJldHVybiB2YWx1ZTsKICB9Cn0KZXhwb3J0cy5Qb3N0U2NyaXB0TGV4ZXIgPSBQb3N0U2NyaXB0TGV4ZXI7CgovKioqLyB9KSwKLyogMTk0ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5Mb2NhbFRpbGluZ1BhdHRlcm5DYWNoZSA9IGV4cG9ydHMuTG9jYWxJbWFnZUNhY2hlID0gZXhwb3J0cy5Mb2NhbEdTdGF0ZUNhY2hlID0gZXhwb3J0cy5Mb2NhbEZ1bmN0aW9uQ2FjaGUgPSBleHBvcnRzLkxvY2FsQ29sb3JTcGFjZUNhY2hlID0gZXhwb3J0cy5HbG9iYWxJbWFnZUNhY2hlID0gdm9pZCAwOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwp2YXIgX3ByaW1pdGl2ZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MCk7CmNsYXNzIEJhc2VMb2NhbENhY2hlIHsKICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICBpZiAodGhpcy5jb25zdHJ1Y3RvciA9PT0gQmFzZUxvY2FsQ2FjaGUpIHsKICAgICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQ2Fubm90IGluaXRpYWxpemUgQmFzZUxvY2FsQ2FjaGUuIik7CiAgICB9CiAgICB0aGlzLl9vbmx5UmVmcyA9IChvcHRpb25zICYmIG9wdGlvbnMub25seVJlZnMpID09PSB0cnVlOwogICAgaWYgKCF0aGlzLl9vbmx5UmVmcykgewogICAgICB0aGlzLl9uYW1lUmVmTWFwID0gbmV3IE1hcCgpOwogICAgICB0aGlzLl9pbWFnZU1hcCA9IG5ldyBNYXAoKTsKICAgIH0KICAgIHRoaXMuX2ltYWdlQ2FjaGUgPSBuZXcgX3ByaW1pdGl2ZXMuUmVmU2V0Q2FjaGUoKTsKICB9CiAgZ2V0QnlOYW1lKG5hbWUpIHsKICAgIGlmICh0aGlzLl9vbmx5UmVmcykgewogICAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJTaG91bGQgbm90IGNhbGwgYGdldEJ5TmFtZWAgbWV0aG9kLiIpOwogICAgfQogICAgY29uc3QgcmVmID0gdGhpcy5fbmFtZVJlZk1hcC5nZXQobmFtZSk7CiAgICBpZiAocmVmKSB7CiAgICAgIHJldHVybiB0aGlzLmdldEJ5UmVmKHJlZik7CiAgICB9CiAgICByZXR1cm4gdGhpcy5faW1hZ2VNYXAuZ2V0KG5hbWUpIHx8IG51bGw7CiAgfQogIGdldEJ5UmVmKHJlZikgewogICAgcmV0dXJuIHRoaXMuX2ltYWdlQ2FjaGUuZ2V0KHJlZikgfHwgbnVsbDsKICB9CiAgc2V0KG5hbWUsIHJlZiwgZGF0YSkgewogICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgiQWJzdHJhY3QgbWV0aG9kIGBzZXRgIGNhbGxlZC4iKTsKICB9Cn0KY2xhc3MgTG9jYWxJbWFnZUNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGUgewogIHNldChuYW1lKSB7CiAgICBsZXQgcmVmID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBudWxsOwogICAgbGV0IGRhdGEgPSBhcmd1bWVudHMubGVuZ3RoID4gMiA/IGFyZ3VtZW50c1syXSA6IHVuZGVmaW5lZDsKICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gInN0cmluZyIpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdMb2NhbEltYWdlQ2FjaGUuc2V0IC0gZXhwZWN0ZWQgIm5hbWUiIGFyZ3VtZW50LicpOwogICAgfQogICAgaWYgKHJlZikgewogICAgICBpZiAodGhpcy5faW1hZ2VDYWNoZS5oYXMocmVmKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICB0aGlzLl9uYW1lUmVmTWFwLnNldChuYW1lLCByZWYpOwogICAgICB0aGlzLl9pbWFnZUNhY2hlLnB1dChyZWYsIGRhdGEpOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAodGhpcy5faW1hZ2VNYXAuaGFzKG5hbWUpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX2ltYWdlTWFwLnNldChuYW1lLCBkYXRhKTsKICB9Cn0KZXhwb3J0cy5Mb2NhbEltYWdlQ2FjaGUgPSBMb2NhbEltYWdlQ2FjaGU7CmNsYXNzIExvY2FsQ29sb3JTcGFjZUNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGUgewogIHNldCgpIHsKICAgIGxldCBuYW1lID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBudWxsOwogICAgbGV0IHJlZiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogbnVsbDsKICAgIGxldCBkYXRhID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgPyBhcmd1bWVudHNbMl0gOiB1bmRlZmluZWQ7CiAgICBpZiAodHlwZW9mIG5hbWUgIT09ICJzdHJpbmciICYmICFyZWYpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdMb2NhbENvbG9yU3BhY2VDYWNoZS5zZXQgLSBleHBlY3RlZCAibmFtZSIgYW5kL29yICJyZWYiIGFyZ3VtZW50LicpOwogICAgfQogICAgaWYgKHJlZikgewogICAgICBpZiAodGhpcy5faW1hZ2VDYWNoZS5oYXMocmVmKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBpZiAobmFtZSAhPT0gbnVsbCkgewogICAgICAgIHRoaXMuX25hbWVSZWZNYXAuc2V0KG5hbWUsIHJlZik7CiAgICAgIH0KICAgICAgdGhpcy5faW1hZ2VDYWNoZS5wdXQocmVmLCBkYXRhKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKHRoaXMuX2ltYWdlTWFwLmhhcyhuYW1lKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9pbWFnZU1hcC5zZXQobmFtZSwgZGF0YSk7CiAgfQp9CmV4cG9ydHMuTG9jYWxDb2xvclNwYWNlQ2FjaGUgPSBMb2NhbENvbG9yU3BhY2VDYWNoZTsKY2xhc3MgTG9jYWxGdW5jdGlvbkNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGUgewogIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHsKICAgIHN1cGVyKHsKICAgICAgb25seVJlZnM6IHRydWUKICAgIH0pOwogIH0KICBzZXQoKSB7CiAgICBsZXQgbmFtZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbnVsbDsKICAgIGxldCByZWYgPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZDsKICAgIGxldCBkYXRhID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgPyBhcmd1bWVudHNbMl0gOiB1bmRlZmluZWQ7CiAgICBpZiAoIXJlZikgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvY2FsRnVuY3Rpb25DYWNoZS5zZXQgLSBleHBlY3RlZCAicmVmIiBhcmd1bWVudC4nKTsKICAgIH0KICAgIGlmICh0aGlzLl9pbWFnZUNhY2hlLmhhcyhyZWYpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX2ltYWdlQ2FjaGUucHV0KHJlZiwgZGF0YSk7CiAgfQp9CmV4cG9ydHMuTG9jYWxGdW5jdGlvbkNhY2hlID0gTG9jYWxGdW5jdGlvbkNhY2hlOwpjbGFzcyBMb2NhbEdTdGF0ZUNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGUgewogIHNldChuYW1lKSB7CiAgICBsZXQgcmVmID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBudWxsOwogICAgbGV0IGRhdGEgPSBhcmd1bWVudHMubGVuZ3RoID4gMiA/IGFyZ3VtZW50c1syXSA6IHVuZGVmaW5lZDsKICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gInN0cmluZyIpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdMb2NhbEdTdGF0ZUNhY2hlLnNldCAtIGV4cGVjdGVkICJuYW1lIiBhcmd1bWVudC4nKTsKICAgIH0KICAgIGlmIChyZWYpIHsKICAgICAgaWYgKHRoaXMuX2ltYWdlQ2FjaGUuaGFzKHJlZikpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhpcy5fbmFtZVJlZk1hcC5zZXQobmFtZSwgcmVmKTsKICAgICAgdGhpcy5faW1hZ2VDYWNoZS5wdXQocmVmLCBkYXRhKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKHRoaXMuX2ltYWdlTWFwLmhhcyhuYW1lKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9pbWFnZU1hcC5zZXQobmFtZSwgZGF0YSk7CiAgfQp9CmV4cG9ydHMuTG9jYWxHU3RhdGVDYWNoZSA9IExvY2FsR1N0YXRlQ2FjaGU7CmNsYXNzIExvY2FsVGlsaW5nUGF0dGVybkNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGUgewogIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHsKICAgIHN1cGVyKHsKICAgICAgb25seVJlZnM6IHRydWUKICAgIH0pOwogIH0KICBzZXQoKSB7CiAgICBsZXQgbmFtZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbnVsbDsKICAgIGxldCByZWYgPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZDsKICAgIGxldCBkYXRhID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgPyBhcmd1bWVudHNbMl0gOiB1bmRlZmluZWQ7CiAgICBpZiAoIXJlZikgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvY2FsVGlsaW5nUGF0dGVybkNhY2hlLnNldCAtIGV4cGVjdGVkICJyZWYiIGFyZ3VtZW50LicpOwogICAgfQogICAgaWYgKHRoaXMuX2ltYWdlQ2FjaGUuaGFzKHJlZikpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5faW1hZ2VDYWNoZS5wdXQocmVmLCBkYXRhKTsKICB9Cn0KZXhwb3J0cy5Mb2NhbFRpbGluZ1BhdHRlcm5DYWNoZSA9IExvY2FsVGlsaW5nUGF0dGVybkNhY2hlOwpjbGFzcyBHbG9iYWxJbWFnZUNhY2hlIHsKICBzdGF0aWMgZ2V0IE5VTV9QQUdFU19USFJFU0hPTEQoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIk5VTV9QQUdFU19USFJFU0hPTEQiLCAyKTsKICB9CiAgc3RhdGljIGdldCBNSU5fSU1BR0VTX1RPX0NBQ0hFKCkgewogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJNSU5fSU1BR0VTX1RPX0NBQ0hFIiwgMTApOwogIH0KICBzdGF0aWMgZ2V0IE1BWF9CWVRFX1NJWkUoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIk1BWF9CWVRFX1NJWkUiLCA1ICogX3V0aWwuTUFYX0lNQUdFX1NJWkVfVE9fQ0FDSEUpOwogIH0KICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMuX3JlZkNhY2hlID0gbmV3IF9wcmltaXRpdmVzLlJlZlNldENhY2hlKCk7CiAgICB0aGlzLl9pbWFnZUNhY2hlID0gbmV3IF9wcmltaXRpdmVzLlJlZlNldENhY2hlKCk7CiAgfQogIGdldCBfYnl0ZVNpemUoKSB7CiAgICBsZXQgYnl0ZVNpemUgPSAwOwogICAgZm9yIChjb25zdCBpbWFnZURhdGEgb2YgdGhpcy5faW1hZ2VDYWNoZSkgewogICAgICBieXRlU2l6ZSArPSBpbWFnZURhdGEuYnl0ZVNpemU7CiAgICB9CiAgICByZXR1cm4gYnl0ZVNpemU7CiAgfQogIGdldCBfY2FjaGVMaW1pdFJlYWNoZWQoKSB7CiAgICBpZiAodGhpcy5faW1hZ2VDYWNoZS5zaXplIDwgR2xvYmFsSW1hZ2VDYWNoZS5NSU5fSU1BR0VTX1RPX0NBQ0hFKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmICh0aGlzLl9ieXRlU2l6ZSA8IEdsb2JhbEltYWdlQ2FjaGUuTUFYX0JZVEVfU0laRSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgc2hvdWxkQ2FjaGUocmVmLCBwYWdlSW5kZXgpIHsKICAgIGNvbnN0IHBhZ2VJbmRleFNldCA9IHRoaXMuX3JlZkNhY2hlLmdldChyZWYpOwogICAgY29uc3QgbnVtUGFnZXMgPSBwYWdlSW5kZXhTZXQgPyBwYWdlSW5kZXhTZXQuc2l6ZSArIChwYWdlSW5kZXhTZXQuaGFzKHBhZ2VJbmRleCkgPyAwIDogMSkgOiAxOwogICAgaWYgKG51bVBhZ2VzIDwgR2xvYmFsSW1hZ2VDYWNoZS5OVU1fUEFHRVNfVEhSRVNIT0xEKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmICghdGhpcy5faW1hZ2VDYWNoZS5oYXMocmVmKSAmJiB0aGlzLl9jYWNoZUxpbWl0UmVhY2hlZCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgYWRkUGFnZUluZGV4KHJlZiwgcGFnZUluZGV4KSB7CiAgICBsZXQgcGFnZUluZGV4U2V0ID0gdGhpcy5fcmVmQ2FjaGUuZ2V0KHJlZik7CiAgICBpZiAoIXBhZ2VJbmRleFNldCkgewogICAgICBwYWdlSW5kZXhTZXQgPSBuZXcgU2V0KCk7CiAgICAgIHRoaXMuX3JlZkNhY2hlLnB1dChyZWYsIHBhZ2VJbmRleFNldCk7CiAgICB9CiAgICBwYWdlSW5kZXhTZXQuYWRkKHBhZ2VJbmRleCk7CiAgfQogIGFkZEJ5dGVTaXplKHJlZiwgYnl0ZVNpemUpIHsKICAgIGNvbnN0IGltYWdlRGF0YSA9IHRoaXMuX2ltYWdlQ2FjaGUuZ2V0KHJlZik7CiAgICBpZiAoIWltYWdlRGF0YSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoaW1hZ2VEYXRhLmJ5dGVTaXplKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGltYWdlRGF0YS5ieXRlU2l6ZSA9IGJ5dGVTaXplOwogIH0KICBnZXREYXRhKHJlZiwgcGFnZUluZGV4KSB7CiAgICBjb25zdCBwYWdlSW5kZXhTZXQgPSB0aGlzLl9yZWZDYWNoZS5nZXQocmVmKTsKICAgIGlmICghcGFnZUluZGV4U2V0KSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKHBhZ2VJbmRleFNldC5zaXplIDwgR2xvYmFsSW1hZ2VDYWNoZS5OVU1fUEFHRVNfVEhSRVNIT0xEKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgaW1hZ2VEYXRhID0gdGhpcy5faW1hZ2VDYWNoZS5nZXQocmVmKTsKICAgIGlmICghaW1hZ2VEYXRhKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgcGFnZUluZGV4U2V0LmFkZChwYWdlSW5kZXgpOwogICAgcmV0dXJuIGltYWdlRGF0YTsKICB9CiAgc2V0RGF0YShyZWYsIGRhdGEpIHsKICAgIGlmICghdGhpcy5fcmVmQ2FjaGUuaGFzKHJlZikpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdHbG9iYWxJbWFnZUNhY2hlLnNldERhdGEgLSBleHBlY3RlZCAiYWRkUGFnZUluZGV4IiB0byBoYXZlIGJlZW4gY2FsbGVkLicpOwogICAgfQogICAgaWYgKHRoaXMuX2ltYWdlQ2FjaGUuaGFzKHJlZikpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKHRoaXMuX2NhY2hlTGltaXRSZWFjaGVkKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKSgiR2xvYmFsSW1hZ2VDYWNoZS5zZXREYXRhIC0gY2FjaGUgbGltaXQgcmVhY2hlZC4iKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5faW1hZ2VDYWNoZS5wdXQocmVmLCBkYXRhKTsKICB9CiAgY2xlYXIoKSB7CiAgICBsZXQgb25seURhdGEgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgaWYgKCFvbmx5RGF0YSkgewogICAgICB0aGlzLl9yZWZDYWNoZS5jbGVhcigpOwogICAgfQogICAgdGhpcy5faW1hZ2VDYWNoZS5jbGVhcigpOwogIH0KfQpleHBvcnRzLkdsb2JhbEltYWdlQ2FjaGUgPSBHbG9iYWxJbWFnZUNhY2hlOwoKLyoqKi8gfSksCi8qIDE5NSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuYmlkaSA9IGJpZGk7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CmNvbnN0IGJhc2VUeXBlcyA9IFsiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiUyIsICJCIiwgIlMiLCAiV1MiLCAiQiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCIiwgIkIiLCAiQiIsICJTIiwgIldTIiwgIk9OIiwgIk9OIiwgIkVUIiwgIkVUIiwgIkVUIiwgIk9OIiwgIk9OIiwgIk9OIiwgIk9OIiwgIk9OIiwgIkVTIiwgIkNTIiwgIkVTIiwgIkNTIiwgIkNTIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkNTIiwgIk9OIiwgIk9OIiwgIk9OIiwgIk9OIiwgIk9OIiwgIk9OIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiT04iLCAiT04iLCAiT04iLCAiT04iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJCTiIsICJDUyIsICJPTiIsICJFVCIsICJFVCIsICJFVCIsICJFVCIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJMIiwgIk9OIiwgIk9OIiwgIkJOIiwgIk9OIiwgIk9OIiwgIkVUIiwgIkVUIiwgIkVOIiwgIkVOIiwgIk9OIiwgIkwiLCAiT04iLCAiT04iLCAiT04iLCAiRU4iLCAiTCIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiT04iLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJPTiIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiXTsKY29uc3QgYXJhYmljVHlwZXMgPSBbIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIk9OIiwgIk9OIiwgIkFMIiwgIkVUIiwgIkVUIiwgIkFMIiwgIkNTIiwgIkFMIiwgIk9OIiwgIk9OIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiQUwiLCAiQUwiLCAiIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkFOIiwgIkVUIiwgIkFOIiwgIkFOIiwgIkFMIiwgIkFMIiwgIkFMIiwgIk5TTSIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiQU4iLCAiT04iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiQUwiLCAiQUwiLCAiTlNNIiwgIk5TTSIsICJPTiIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiQUwiLCAiQUwiLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiRU4iLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiXTsKZnVuY3Rpb24gaXNPZGQoaSkgewogIHJldHVybiAoaSAmIDEpICE9PSAwOwp9CmZ1bmN0aW9uIGlzRXZlbihpKSB7CiAgcmV0dXJuIChpICYgMSkgPT09IDA7Cn0KZnVuY3Rpb24gZmluZFVuZXF1YWwoYXJyLCBzdGFydCwgdmFsdWUpIHsKICBsZXQgaiwgamo7CiAgZm9yIChqID0gc3RhcnQsIGpqID0gYXJyLmxlbmd0aDsgaiA8IGpqOyArK2opIHsKICAgIGlmIChhcnJbal0gIT09IHZhbHVlKSB7CiAgICAgIHJldHVybiBqOwogICAgfQogIH0KICByZXR1cm4gajsKfQpmdW5jdGlvbiBzZXRWYWx1ZXMoYXJyLCBzdGFydCwgZW5kLCB2YWx1ZSkgewogIGZvciAobGV0IGogPSBzdGFydDsgaiA8IGVuZDsgKytqKSB7CiAgICBhcnJbal0gPSB2YWx1ZTsKICB9Cn0KZnVuY3Rpb24gcmV2ZXJzZVZhbHVlcyhhcnIsIHN0YXJ0LCBlbmQpIHsKICBmb3IgKGxldCBpID0gc3RhcnQsIGogPSBlbmQgLSAxOyBpIDwgajsgKytpLCAtLWopIHsKICAgIGNvbnN0IHRlbXAgPSBhcnJbaV07CiAgICBhcnJbaV0gPSBhcnJbal07CiAgICBhcnJbal0gPSB0ZW1wOwogIH0KfQpmdW5jdGlvbiBjcmVhdGVCaWRpVGV4dChzdHIsIGlzTFRSKSB7CiAgbGV0IHZlcnRpY2FsID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBmYWxzZTsKICBsZXQgZGlyID0gImx0ciI7CiAgaWYgKHZlcnRpY2FsKSB7CiAgICBkaXIgPSAidHRiIjsKICB9IGVsc2UgaWYgKCFpc0xUUikgewogICAgZGlyID0gInJ0bCI7CiAgfQogIHJldHVybiB7CiAgICBzdHIsCiAgICBkaXIKICB9Owp9CmNvbnN0IGNoYXJzID0gW107CmNvbnN0IHR5cGVzID0gW107CmZ1bmN0aW9uIGJpZGkoc3RyKSB7CiAgbGV0IHN0YXJ0TGV2ZWwgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IC0xOwogIGxldCB2ZXJ0aWNhbCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogZmFsc2U7CiAgbGV0IGlzTFRSID0gdHJ1ZTsKICBjb25zdCBzdHJMZW5ndGggPSBzdHIubGVuZ3RoOwogIGlmIChzdHJMZW5ndGggPT09IDAgfHwgdmVydGljYWwpIHsKICAgIHJldHVybiBjcmVhdGVCaWRpVGV4dChzdHIsIGlzTFRSLCB2ZXJ0aWNhbCk7CiAgfQogIGNoYXJzLmxlbmd0aCA9IHN0ckxlbmd0aDsKICB0eXBlcy5sZW5ndGggPSBzdHJMZW5ndGg7CiAgbGV0IG51bUJpZGkgPSAwOwogIGxldCBpLCBpaTsKICBmb3IgKGkgPSAwOyBpIDwgc3RyTGVuZ3RoOyArK2kpIHsKICAgIGNoYXJzW2ldID0gc3RyLmNoYXJBdChpKTsKICAgIGNvbnN0IGNoYXJDb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7CiAgICBsZXQgY2hhclR5cGUgPSAiTCI7CiAgICBpZiAoY2hhckNvZGUgPD0gMHgwMGZmKSB7CiAgICAgIGNoYXJUeXBlID0gYmFzZVR5cGVzW2NoYXJDb2RlXTsKICAgIH0gZWxzZSBpZiAoMHgwNTkwIDw9IGNoYXJDb2RlICYmIGNoYXJDb2RlIDw9IDB4MDVmNCkgewogICAgICBjaGFyVHlwZSA9ICJSIjsKICAgIH0gZWxzZSBpZiAoMHgwNjAwIDw9IGNoYXJDb2RlICYmIGNoYXJDb2RlIDw9IDB4MDZmZikgewogICAgICBjaGFyVHlwZSA9IGFyYWJpY1R5cGVzW2NoYXJDb2RlICYgMHhmZl07CiAgICAgIGlmICghY2hhclR5cGUpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoIkJpZGk6IGludmFsaWQgVW5pY29kZSBjaGFyYWN0ZXIgIiArIGNoYXJDb2RlLnRvU3RyaW5nKDE2KSk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoMHgwNzAwIDw9IGNoYXJDb2RlICYmIGNoYXJDb2RlIDw9IDB4MDhhYykgewogICAgICBjaGFyVHlwZSA9ICJBTCI7CiAgICB9CiAgICBpZiAoY2hhclR5cGUgPT09ICJSIiB8fCBjaGFyVHlwZSA9PT0gIkFMIiB8fCBjaGFyVHlwZSA9PT0gIkFOIikgewogICAgICBudW1CaWRpKys7CiAgICB9CiAgICB0eXBlc1tpXSA9IGNoYXJUeXBlOwogIH0KICBpZiAobnVtQmlkaSA9PT0gMCkgewogICAgaXNMVFIgPSB0cnVlOwogICAgcmV0dXJuIGNyZWF0ZUJpZGlUZXh0KHN0ciwgaXNMVFIpOwogIH0KICBpZiAoc3RhcnRMZXZlbCA9PT0gLTEpIHsKICAgIGlmIChudW1CaWRpIC8gc3RyTGVuZ3RoIDwgMC4zICYmIHN0ckxlbmd0aCA+IDQpIHsKICAgICAgaXNMVFIgPSB0cnVlOwogICAgICBzdGFydExldmVsID0gMDsKICAgIH0gZWxzZSB7CiAgICAgIGlzTFRSID0gZmFsc2U7CiAgICAgIHN0YXJ0TGV2ZWwgPSAxOwogICAgfQogIH0KICBjb25zdCBsZXZlbHMgPSBbXTsKICBmb3IgKGkgPSAwOyBpIDwgc3RyTGVuZ3RoOyArK2kpIHsKICAgIGxldmVsc1tpXSA9IHN0YXJ0TGV2ZWw7CiAgfQogIGNvbnN0IGUgPSBpc09kZChzdGFydExldmVsKSA/ICJSIiA6ICJMIjsKICBjb25zdCBzb3IgPSBlOwogIGNvbnN0IGVvciA9IHNvcjsKICBsZXQgbGFzdFR5cGUgPSBzb3I7CiAgZm9yIChpID0gMDsgaSA8IHN0ckxlbmd0aDsgKytpKSB7CiAgICBpZiAodHlwZXNbaV0gPT09ICJOU00iKSB7CiAgICAgIHR5cGVzW2ldID0gbGFzdFR5cGU7CiAgICB9IGVsc2UgewogICAgICBsYXN0VHlwZSA9IHR5cGVzW2ldOwogICAgfQogIH0KICBsYXN0VHlwZSA9IHNvcjsKICBsZXQgdDsKICBmb3IgKGkgPSAwOyBpIDwgc3RyTGVuZ3RoOyArK2kpIHsKICAgIHQgPSB0eXBlc1tpXTsKICAgIGlmICh0ID09PSAiRU4iKSB7CiAgICAgIHR5cGVzW2ldID0gbGFzdFR5cGUgPT09ICJBTCIgPyAiQU4iIDogIkVOIjsKICAgIH0gZWxzZSBpZiAodCA9PT0gIlIiIHx8IHQgPT09ICJMIiB8fCB0ID09PSAiQUwiKSB7CiAgICAgIGxhc3RUeXBlID0gdDsKICAgIH0KICB9CiAgZm9yIChpID0gMDsgaSA8IHN0ckxlbmd0aDsgKytpKSB7CiAgICB0ID0gdHlwZXNbaV07CiAgICBpZiAodCA9PT0gIkFMIikgewogICAgICB0eXBlc1tpXSA9ICJSIjsKICAgIH0KICB9CiAgZm9yIChpID0gMTsgaSA8IHN0ckxlbmd0aCAtIDE7ICsraSkgewogICAgaWYgKHR5cGVzW2ldID09PSAiRVMiICYmIHR5cGVzW2kgLSAxXSA9PT0gIkVOIiAmJiB0eXBlc1tpICsgMV0gPT09ICJFTiIpIHsKICAgICAgdHlwZXNbaV0gPSAiRU4iOwogICAgfQogICAgaWYgKHR5cGVzW2ldID09PSAiQ1MiICYmICh0eXBlc1tpIC0gMV0gPT09ICJFTiIgfHwgdHlwZXNbaSAtIDFdID09PSAiQU4iKSAmJiB0eXBlc1tpICsgMV0gPT09IHR5cGVzW2kgLSAxXSkgewogICAgICB0eXBlc1tpXSA9IHR5cGVzW2kgLSAxXTsKICAgIH0KICB9CiAgZm9yIChpID0gMDsgaSA8IHN0ckxlbmd0aDsgKytpKSB7CiAgICBpZiAodHlwZXNbaV0gPT09ICJFTiIpIHsKICAgICAgZm9yIChsZXQgaiA9IGkgLSAxOyBqID49IDA7IC0taikgewogICAgICAgIGlmICh0eXBlc1tqXSAhPT0gIkVUIikgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHR5cGVzW2pdID0gIkVOIjsKICAgICAgfQogICAgICBmb3IgKGxldCBqID0gaSArIDE7IGogPCBzdHJMZW5ndGg7ICsraikgewogICAgICAgIGlmICh0eXBlc1tqXSAhPT0gIkVUIikgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHR5cGVzW2pdID0gIkVOIjsKICAgICAgfQogICAgfQogIH0KICBmb3IgKGkgPSAwOyBpIDwgc3RyTGVuZ3RoOyArK2kpIHsKICAgIHQgPSB0eXBlc1tpXTsKICAgIGlmICh0ID09PSAiV1MiIHx8IHQgPT09ICJFUyIgfHwgdCA9PT0gIkVUIiB8fCB0ID09PSAiQ1MiKSB7CiAgICAgIHR5cGVzW2ldID0gIk9OIjsKICAgIH0KICB9CiAgbGFzdFR5cGUgPSBzb3I7CiAgZm9yIChpID0gMDsgaSA8IHN0ckxlbmd0aDsgKytpKSB7CiAgICB0ID0gdHlwZXNbaV07CiAgICBpZiAodCA9PT0gIkVOIikgewogICAgICB0eXBlc1tpXSA9IGxhc3RUeXBlID09PSAiTCIgPyAiTCIgOiAiRU4iOwogICAgfSBlbHNlIGlmICh0ID09PSAiUiIgfHwgdCA9PT0gIkwiKSB7CiAgICAgIGxhc3RUeXBlID0gdDsKICAgIH0KICB9CiAgZm9yIChpID0gMDsgaSA8IHN0ckxlbmd0aDsgKytpKSB7CiAgICBpZiAodHlwZXNbaV0gPT09ICJPTiIpIHsKICAgICAgY29uc3QgZW5kID0gZmluZFVuZXF1YWwodHlwZXMsIGkgKyAxLCAiT04iKTsKICAgICAgbGV0IGJlZm9yZSA9IHNvcjsKICAgICAgaWYgKGkgPiAwKSB7CiAgICAgICAgYmVmb3JlID0gdHlwZXNbaSAtIDFdOwogICAgICB9CiAgICAgIGxldCBhZnRlciA9IGVvcjsKICAgICAgaWYgKGVuZCArIDEgPCBzdHJMZW5ndGgpIHsKICAgICAgICBhZnRlciA9IHR5cGVzW2VuZCArIDFdOwogICAgICB9CiAgICAgIGlmIChiZWZvcmUgIT09ICJMIikgewogICAgICAgIGJlZm9yZSA9ICJSIjsKICAgICAgfQogICAgICBpZiAoYWZ0ZXIgIT09ICJMIikgewogICAgICAgIGFmdGVyID0gIlIiOwogICAgICB9CiAgICAgIGlmIChiZWZvcmUgPT09IGFmdGVyKSB7CiAgICAgICAgc2V0VmFsdWVzKHR5cGVzLCBpLCBlbmQsIGJlZm9yZSk7CiAgICAgIH0KICAgICAgaSA9IGVuZCAtIDE7CiAgICB9CiAgfQogIGZvciAoaSA9IDA7IGkgPCBzdHJMZW5ndGg7ICsraSkgewogICAgaWYgKHR5cGVzW2ldID09PSAiT04iKSB7CiAgICAgIHR5cGVzW2ldID0gZTsKICAgIH0KICB9CiAgZm9yIChpID0gMDsgaSA8IHN0ckxlbmd0aDsgKytpKSB7CiAgICB0ID0gdHlwZXNbaV07CiAgICBpZiAoaXNFdmVuKGxldmVsc1tpXSkpIHsKICAgICAgaWYgKHQgPT09ICJSIikgewogICAgICAgIGxldmVsc1tpXSArPSAxOwogICAgICB9IGVsc2UgaWYgKHQgPT09ICJBTiIgfHwgdCA9PT0gIkVOIikgewogICAgICAgIGxldmVsc1tpXSArPSAyOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBpZiAodCA9PT0gIkwiIHx8IHQgPT09ICJBTiIgfHwgdCA9PT0gIkVOIikgewogICAgICAgIGxldmVsc1tpXSArPSAxOwogICAgICB9CiAgICB9CiAgfQogIGxldCBoaWdoZXN0TGV2ZWwgPSAtMTsKICBsZXQgbG93ZXN0T2RkTGV2ZWwgPSA5OTsKICBsZXQgbGV2ZWw7CiAgZm9yIChpID0gMCwgaWkgPSBsZXZlbHMubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgbGV2ZWwgPSBsZXZlbHNbaV07CiAgICBpZiAoaGlnaGVzdExldmVsIDwgbGV2ZWwpIHsKICAgICAgaGlnaGVzdExldmVsID0gbGV2ZWw7CiAgICB9CiAgICBpZiAobG93ZXN0T2RkTGV2ZWwgPiBsZXZlbCAmJiBpc09kZChsZXZlbCkpIHsKICAgICAgbG93ZXN0T2RkTGV2ZWwgPSBsZXZlbDsKICAgIH0KICB9CiAgZm9yIChsZXZlbCA9IGhpZ2hlc3RMZXZlbDsgbGV2ZWwgPj0gbG93ZXN0T2RkTGV2ZWw7IC0tbGV2ZWwpIHsKICAgIGxldCBzdGFydCA9IC0xOwogICAgZm9yIChpID0gMCwgaWkgPSBsZXZlbHMubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICBpZiAobGV2ZWxzW2ldIDwgbGV2ZWwpIHsKICAgICAgICBpZiAoc3RhcnQgPj0gMCkgewogICAgICAgICAgcmV2ZXJzZVZhbHVlcyhjaGFycywgc3RhcnQsIGkpOwogICAgICAgICAgc3RhcnQgPSAtMTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoc3RhcnQgPCAwKSB7CiAgICAgICAgc3RhcnQgPSBpOwogICAgICB9CiAgICB9CiAgICBpZiAoc3RhcnQgPj0gMCkgewogICAgICByZXZlcnNlVmFsdWVzKGNoYXJzLCBzdGFydCwgbGV2ZWxzLmxlbmd0aCk7CiAgICB9CiAgfQogIGZvciAoaSA9IDAsIGlpID0gY2hhcnMubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgY29uc3QgY2ggPSBjaGFyc1tpXTsKICAgIGlmIChjaCA9PT0gIjwiIHx8IGNoID09PSAiPiIpIHsKICAgICAgY2hhcnNbaV0gPSAiIjsKICAgIH0KICB9CiAgcmV0dXJuIGNyZWF0ZUJpZGlUZXh0KGNoYXJzLmpvaW4oIiIpLCBpc0xUUik7Cn0KCi8qKiovIH0pLAovKiAxOTYgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLkltYWdlUmVzaXplciA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKY29uc3QgTUlOX0lNQUdFX0RJTSA9IDIwNDg7CmNvbnN0IE1BWF9JTUFHRV9ESU0gPSA2NTUzNzsKY29uc3QgTUFYX0VSUk9SID0gMTI4OwpjbGFzcyBJbWFnZVJlc2l6ZXIgewogIGNvbnN0cnVjdG9yKGltZ0RhdGEsIGlzTWFzaykgewogICAgdGhpcy5faW1nRGF0YSA9IGltZ0RhdGE7CiAgICB0aGlzLl9pc01hc2sgPSBpc01hc2s7CiAgfQogIHN0YXRpYyBuZWVkc1RvQmVSZXNpemVkKHdpZHRoLCBoZWlnaHQpIHsKICAgIGlmICh3aWR0aCA8PSB0aGlzLl9nb29kU3F1YXJlTGVuZ3RoICYmIGhlaWdodCA8PSB0aGlzLl9nb29kU3F1YXJlTGVuZ3RoKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgTUFYX0RJTQogICAgfSA9IHRoaXM7CiAgICBpZiAod2lkdGggPiBNQVhfRElNIHx8IGhlaWdodCA+IE1BWF9ESU0pIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBjb25zdCBhcmVhID0gd2lkdGggKiBoZWlnaHQ7CiAgICBpZiAodGhpcy5faGFzTWF4QXJlYSkgewogICAgICByZXR1cm4gYXJlYSA+IHRoaXMuTUFYX0FSRUE7CiAgICB9CiAgICBpZiAoYXJlYSA8IHRoaXMuX2dvb2RTcXVhcmVMZW5ndGggKiogMikgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpcy5fYXJlR29vZERpbXMod2lkdGgsIGhlaWdodCkpIHsKICAgICAgdGhpcy5fZ29vZFNxdWFyZUxlbmd0aCA9IE1hdGgubWF4KHRoaXMuX2dvb2RTcXVhcmVMZW5ndGgsIE1hdGguZmxvb3IoTWF0aC5zcXJ0KHdpZHRoICogaGVpZ2h0KSkpOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICB0aGlzLl9nb29kU3F1YXJlTGVuZ3RoID0gdGhpcy5fZ3Vlc3NNYXgodGhpcy5fZ29vZFNxdWFyZUxlbmd0aCwgTUFYX0RJTSwgTUFYX0VSUk9SLCAwKTsKICAgIGNvbnN0IG1heEFyZWEgPSB0aGlzLk1BWF9BUkVBID0gdGhpcy5fZ29vZFNxdWFyZUxlbmd0aCAqKiAyOwogICAgcmV0dXJuIGFyZWEgPiBtYXhBcmVhOwogIH0KICBzdGF0aWMgZ2V0IE1BWF9ESU0oKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIk1BWF9ESU0iLCB0aGlzLl9ndWVzc01heChNSU5fSU1BR0VfRElNLCBNQVhfSU1BR0VfRElNLCAwLCAxKSk7CiAgfQogIHN0YXRpYyBnZXQgTUFYX0FSRUEoKSB7CiAgICB0aGlzLl9oYXNNYXhBcmVhID0gdHJ1ZTsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiTUFYX0FSRUEiLCB0aGlzLl9ndWVzc01heChJbWFnZVJlc2l6ZXIuX2dvb2RTcXVhcmVMZW5ndGgsIHRoaXMuTUFYX0RJTSwgTUFYX0VSUk9SLCAwKSAqKiAyKTsKICB9CiAgc3RhdGljIHNldCBNQVhfQVJFQShhcmVhKSB7CiAgICBpZiAoYXJlYSA+PSAwKSB7CiAgICAgIHRoaXMuX2hhc01heEFyZWEgPSB0cnVlOwogICAgICAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiTUFYX0FSRUEiLCBhcmVhKTsKICAgIH0KICB9CiAgc3RhdGljIHNldE1heEFyZWEoYXJlYSkgewogICAgaWYgKCF0aGlzLl9oYXNNYXhBcmVhKSB7CiAgICAgIHRoaXMuTUFYX0FSRUEgPSBhcmVhID4+IDI7CiAgICB9CiAgfQogIHN0YXRpYyBfYXJlR29vZERpbXMod2lkdGgsIGhlaWdodCkgewogICAgdHJ5IHsKICAgICAgY29uc3QgY2FudmFzID0gbmV3IE9mZnNjcmVlbkNhbnZhcyh3aWR0aCwgaGVpZ2h0KTsKICAgICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgICAgIGN0eC5maWxsUmVjdCgwLCAwLCAxLCAxKTsKICAgICAgY29uc3Qgb3BhY2l0eSA9IGN0eC5nZXRJbWFnZURhdGEoMCwgMCwgMSwgMSkuZGF0YVszXTsKICAgICAgY2FudmFzLndpZHRoID0gY2FudmFzLmhlaWdodCA9IDE7CiAgICAgIHJldHVybiBvcGFjaXR5ICE9PSAwOwogICAgfSBjYXRjaCAoZSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgfQogIHN0YXRpYyBfZ3Vlc3NNYXgoc3RhcnQsIGVuZCwgdG9sZXJhbmNlLCBkZWZhdWx0SGVpZ2h0KSB7CiAgICB3aGlsZSAoc3RhcnQgKyB0b2xlcmFuY2UgKyAxIDwgZW5kKSB7CiAgICAgIGNvbnN0IG1pZGRsZSA9IE1hdGguZmxvb3IoKHN0YXJ0ICsgZW5kKSAvIDIpOwogICAgICBjb25zdCBoZWlnaHQgPSBkZWZhdWx0SGVpZ2h0IHx8IG1pZGRsZTsKICAgICAgaWYgKHRoaXMuX2FyZUdvb2REaW1zKG1pZGRsZSwgaGVpZ2h0KSkgewogICAgICAgIHN0YXJ0ID0gbWlkZGxlOwogICAgICB9IGVsc2UgewogICAgICAgIGVuZCA9IG1pZGRsZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHN0YXJ0OwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlSW1hZ2UoaW1nRGF0YSkgewogICAgbGV0IGlzTWFzayA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogZmFsc2U7CiAgICByZXR1cm4gbmV3IEltYWdlUmVzaXplcihpbWdEYXRhLCBpc01hc2spLl9jcmVhdGVJbWFnZSgpOwogIH0KICBhc3luYyBfY3JlYXRlSW1hZ2UoKSB7CiAgICBjb25zdCBkYXRhID0gdGhpcy5fZW5jb2RlQk1QKCk7CiAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW2RhdGEuYnVmZmVyXSwgewogICAgICB0eXBlOiAiaW1hZ2UvYm1wIgogICAgfSk7CiAgICBjb25zdCBiaXRtYXBQcm9taXNlID0gY3JlYXRlSW1hZ2VCaXRtYXAoYmxvYik7CiAgICBjb25zdCB7CiAgICAgIE1BWF9BUkVBLAogICAgICBNQVhfRElNCiAgICB9ID0gSW1hZ2VSZXNpemVyOwogICAgY29uc3QgewogICAgICBfaW1nRGF0YTogaW1nRGF0YQogICAgfSA9IHRoaXM7CiAgICBjb25zdCB7CiAgICAgIHdpZHRoLAogICAgICBoZWlnaHQKICAgIH0gPSBpbWdEYXRhOwogICAgY29uc3QgbWluRmFjdG9yID0gTWF0aC5tYXgod2lkdGggLyBNQVhfRElNLCBoZWlnaHQgLyBNQVhfRElNLCBNYXRoLnNxcnQod2lkdGggKiBoZWlnaHQgLyBNQVhfQVJFQSkpOwogICAgY29uc3QgZmlyc3RGYWN0b3IgPSBNYXRoLm1heChtaW5GYWN0b3IsIDIpOwogICAgY29uc3QgZmFjdG9yID0gTWF0aC5yb3VuZCgxMCAqIChtaW5GYWN0b3IgKyAxLjI1KSkgLyAxMCAvIGZpcnN0RmFjdG9yOwogICAgY29uc3QgTiA9IE1hdGguZmxvb3IoTWF0aC5sb2cyKGZhY3RvcikpOwogICAgY29uc3Qgc3RlcHMgPSBuZXcgQXJyYXkoTiArIDIpLmZpbGwoMik7CiAgICBzdGVwc1swXSA9IGZpcnN0RmFjdG9yOwogICAgc3RlcHMuc3BsaWNlKC0xLCAxLCBmYWN0b3IgLyAoMSA8PCBOKSk7CiAgICBsZXQgbmV3V2lkdGggPSB3aWR0aDsKICAgIGxldCBuZXdIZWlnaHQgPSBoZWlnaHQ7CiAgICBsZXQgYml0bWFwID0gYXdhaXQgYml0bWFwUHJvbWlzZTsKICAgIGZvciAoY29uc3Qgc3RlcCBvZiBzdGVwcykgewogICAgICBjb25zdCBwcmV2V2lkdGggPSBuZXdXaWR0aDsKICAgICAgY29uc3QgcHJldkhlaWdodCA9IG5ld0hlaWdodDsKICAgICAgbmV3V2lkdGggPSBNYXRoLmZsb29yKG5ld1dpZHRoIC8gc3RlcCkgLSAxOwogICAgICBuZXdIZWlnaHQgPSBNYXRoLmZsb29yKG5ld0hlaWdodCAvIHN0ZXApIC0gMTsKICAgICAgY29uc3QgY2FudmFzID0gbmV3IE9mZnNjcmVlbkNhbnZhcyhuZXdXaWR0aCwgbmV3SGVpZ2h0KTsKICAgICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgICAgIGN0eC5kcmF3SW1hZ2UoYml0bWFwLCAwLCAwLCBwcmV2V2lkdGgsIHByZXZIZWlnaHQsIDAsIDAsIG5ld1dpZHRoLCBuZXdIZWlnaHQpOwogICAgICBiaXRtYXAgPSBjYW52YXMudHJhbnNmZXJUb0ltYWdlQml0bWFwKCk7CiAgICB9CiAgICBpbWdEYXRhLmRhdGEgPSBudWxsOwogICAgaW1nRGF0YS5iaXRtYXAgPSBiaXRtYXA7CiAgICBpbWdEYXRhLndpZHRoID0gbmV3V2lkdGg7CiAgICBpbWdEYXRhLmhlaWdodCA9IG5ld0hlaWdodDsKICAgIHJldHVybiBpbWdEYXRhOwogIH0KICBfZW5jb2RlQk1QKCkgewogICAgY29uc3QgewogICAgICB3aWR0aCwKICAgICAgaGVpZ2h0LAogICAgICBraW5kCiAgICB9ID0gdGhpcy5faW1nRGF0YTsKICAgIGxldCBkYXRhID0gdGhpcy5faW1nRGF0YS5kYXRhOwogICAgbGV0IGJpdFBlclBpeGVsOwogICAgbGV0IGNvbG9yVGFibGUgPSBuZXcgVWludDhBcnJheSgwKTsKICAgIGxldCBtYXNrVGFibGUgPSBjb2xvclRhYmxlOwogICAgbGV0IGNvbXByZXNzaW9uID0gMDsKICAgIHN3aXRjaCAoa2luZCkgewogICAgICBjYXNlIF91dGlsLkltYWdlS2luZC5HUkFZU0NBTEVfMUJQUDoKICAgICAgICB7CiAgICAgICAgICBiaXRQZXJQaXhlbCA9IDE7CiAgICAgICAgICBjb2xvclRhYmxlID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5faXNNYXNrID8gWzI1NSwgMjU1LCAyNTUsIDI1NSwgMCwgMCwgMCwgMF0gOiBbMCwgMCwgMCwgMCwgMjU1LCAyNTUsIDI1NSwgMjU1XSk7CiAgICAgICAgICBjb25zdCByb3dMZW4gPSB3aWR0aCArIDcgPj4gMzsKICAgICAgICAgIGNvbnN0IHJvd1NpemUgPSByb3dMZW4gKyAzICYgLTQ7CiAgICAgICAgICBpZiAocm93TGVuICE9PSByb3dTaXplKSB7CiAgICAgICAgICAgIGNvbnN0IG5ld0RhdGEgPSBuZXcgVWludDhBcnJheShyb3dTaXplICogaGVpZ2h0KTsKICAgICAgICAgICAgbGV0IGsgPSAwOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBoZWlnaHQgKiByb3dMZW47IGkgPCBpaTsgaSArPSByb3dMZW4sIGsgKz0gcm93U2l6ZSkgewogICAgICAgICAgICAgIG5ld0RhdGEuc2V0KGRhdGEuc3ViYXJyYXkoaSwgaSArIHJvd0xlbiksIGspOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRhdGEgPSBuZXdEYXRhOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICBjYXNlIF91dGlsLkltYWdlS2luZC5SR0JfMjRCUFA6CiAgICAgICAgewogICAgICAgICAgYml0UGVyUGl4ZWwgPSAyNDsKICAgICAgICAgIGlmICh3aWR0aCAmIDMpIHsKICAgICAgICAgICAgY29uc3Qgcm93TGVuID0gMyAqIHdpZHRoOwogICAgICAgICAgICBjb25zdCByb3dTaXplID0gcm93TGVuICsgMyAmIC00OwogICAgICAgICAgICBjb25zdCBleHRyYUxlbiA9IHJvd1NpemUgLSByb3dMZW47CiAgICAgICAgICAgIGNvbnN0IG5ld0RhdGEgPSBuZXcgVWludDhBcnJheShyb3dTaXplICogaGVpZ2h0KTsKICAgICAgICAgICAgbGV0IGsgPSAwOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBoZWlnaHQgKiByb3dMZW47IGkgPCBpaTsgaSArPSByb3dMZW4pIHsKICAgICAgICAgICAgICBjb25zdCByb3cgPSBkYXRhLnN1YmFycmF5KGksIGkgKyByb3dMZW4pOwogICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgcm93TGVuOyBqICs9IDMpIHsKICAgICAgICAgICAgICAgIG5ld0RhdGFbaysrXSA9IHJvd1tqICsgMl07CiAgICAgICAgICAgICAgICBuZXdEYXRhW2srK10gPSByb3dbaiArIDFdOwogICAgICAgICAgICAgICAgbmV3RGF0YVtrKytdID0gcm93W2pdOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBrICs9IGV4dHJhTGVuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRhdGEgPSBuZXdEYXRhOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZGF0YS5sZW5ndGg7IGkgPCBpaTsgaSArPSAzKSB7CiAgICAgICAgICAgICAgY29uc3QgdG1wID0gZGF0YVtpXTsKICAgICAgICAgICAgICBkYXRhW2ldID0gZGF0YVtpICsgMl07CiAgICAgICAgICAgICAgZGF0YVtpICsgMl0gPSB0bXA7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgY2FzZSBfdXRpbC5JbWFnZUtpbmQuUkdCQV8zMkJQUDoKICAgICAgICBiaXRQZXJQaXhlbCA9IDMyOwogICAgICAgIGNvbXByZXNzaW9uID0gMzsKICAgICAgICBtYXNrVGFibGUgPSBuZXcgVWludDhBcnJheSg0ICsgNCArIDQgKyA0ICsgNTIpOwogICAgICAgIGNvbnN0IHZpZXcgPSBuZXcgRGF0YVZpZXcobWFza1RhYmxlLmJ1ZmZlcik7CiAgICAgICAgaWYgKF91dGlsLkZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuKSB7CiAgICAgICAgICB2aWV3LnNldFVpbnQzMigwLCAweDAwMDAwMGZmLCB0cnVlKTsKICAgICAgICAgIHZpZXcuc2V0VWludDMyKDQsIDB4MDAwMGZmMDAsIHRydWUpOwogICAgICAgICAgdmlldy5zZXRVaW50MzIoOCwgMHgwMGZmMDAwMCwgdHJ1ZSk7CiAgICAgICAgICB2aWV3LnNldFVpbnQzMigxMiwgMHhmZjAwMDAwMCwgdHJ1ZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZpZXcuc2V0VWludDMyKDAsIDB4ZmYwMDAwMDAsIHRydWUpOwogICAgICAgICAgdmlldy5zZXRVaW50MzIoNCwgMHgwMGZmMDAwMCwgdHJ1ZSk7CiAgICAgICAgICB2aWV3LnNldFVpbnQzMig4LCAweDAwMDBmZjAwLCB0cnVlKTsKICAgICAgICAgIHZpZXcuc2V0VWludDMyKDEyLCAweDAwMDAwMGZmLCB0cnVlKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJpbnZhbGlkIGZvcm1hdCIpOwogICAgfQogICAgbGV0IGkgPSAwOwogICAgY29uc3QgaGVhZGVyTGVuZ3RoID0gNDAgKyBtYXNrVGFibGUubGVuZ3RoOwogICAgY29uc3QgZmlsZUxlbmd0aCA9IDE0ICsgaGVhZGVyTGVuZ3RoICsgY29sb3JUYWJsZS5sZW5ndGggKyBkYXRhLmxlbmd0aDsKICAgIGNvbnN0IGJtcERhdGEgPSBuZXcgVWludDhBcnJheShmaWxlTGVuZ3RoKTsKICAgIGNvbnN0IHZpZXcgPSBuZXcgRGF0YVZpZXcoYm1wRGF0YS5idWZmZXIpOwogICAgdmlldy5zZXRVaW50MTYoaSwgMHg0ZDQyLCB0cnVlKTsKICAgIGkgKz0gMjsKICAgIHZpZXcuc2V0VWludDMyKGksIGZpbGVMZW5ndGgsIHRydWUpOwogICAgaSArPSA0OwogICAgdmlldy5zZXRVaW50MzIoaSwgMCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICB2aWV3LnNldFVpbnQzMihpLCAxNCArIGhlYWRlckxlbmd0aCArIGNvbG9yVGFibGUubGVuZ3RoLCB0cnVlKTsKICAgIGkgKz0gNDsKICAgIHZpZXcuc2V0VWludDMyKGksIGhlYWRlckxlbmd0aCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICB2aWV3LnNldEludDMyKGksIHdpZHRoLCB0cnVlKTsKICAgIGkgKz0gNDsKICAgIHZpZXcuc2V0SW50MzIoaSwgLWhlaWdodCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICB2aWV3LnNldFVpbnQxNihpLCAxLCB0cnVlKTsKICAgIGkgKz0gMjsKICAgIHZpZXcuc2V0VWludDE2KGksIGJpdFBlclBpeGVsLCB0cnVlKTsKICAgIGkgKz0gMjsKICAgIHZpZXcuc2V0VWludDMyKGksIGNvbXByZXNzaW9uLCB0cnVlKTsKICAgIGkgKz0gNDsKICAgIHZpZXcuc2V0VWludDMyKGksIDAsIHRydWUpOwogICAgaSArPSA0OwogICAgdmlldy5zZXRJbnQzMihpLCAwLCB0cnVlKTsKICAgIGkgKz0gNDsKICAgIHZpZXcuc2V0SW50MzIoaSwgMCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICB2aWV3LnNldFVpbnQzMihpLCBjb2xvclRhYmxlLmxlbmd0aCAvIDQsIHRydWUpOwogICAgaSArPSA0OwogICAgdmlldy5zZXRVaW50MzIoaSwgMCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICBibXBEYXRhLnNldChtYXNrVGFibGUsIGkpOwogICAgaSArPSBtYXNrVGFibGUubGVuZ3RoOwogICAgYm1wRGF0YS5zZXQoY29sb3JUYWJsZSwgaSk7CiAgICBpICs9IGNvbG9yVGFibGUubGVuZ3RoOwogICAgYm1wRGF0YS5zZXQoZGF0YSwgaSk7CiAgICByZXR1cm4gYm1wRGF0YTsKICB9Cn0KZXhwb3J0cy5JbWFnZVJlc2l6ZXIgPSBJbWFnZVJlc2l6ZXI7CkltYWdlUmVzaXplci5fZ29vZFNxdWFyZUxlbmd0aCA9IE1JTl9JTUFHRV9ESU07CgovKioqLyB9KSwKLyogMTk3ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5NdXJtdXJIYXNoM182NCA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKY29uc3QgU0VFRCA9IDB4YzNkMmUxZjA7CmNvbnN0IE1BU0tfSElHSCA9IDB4ZmZmZjAwMDA7CmNvbnN0IE1BU0tfTE9XID0gMHhmZmZmOwpjbGFzcyBNdXJtdXJIYXNoM182NCB7CiAgY29uc3RydWN0b3Ioc2VlZCkgewogICAgdGhpcy5oMSA9IHNlZWQgPyBzZWVkICYgMHhmZmZmZmZmZiA6IFNFRUQ7CiAgICB0aGlzLmgyID0gc2VlZCA/IHNlZWQgJiAweGZmZmZmZmZmIDogU0VFRDsKICB9CiAgdXBkYXRlKGlucHV0KSB7CiAgICBsZXQgZGF0YSwgbGVuZ3RoOwogICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gInN0cmluZyIpIHsKICAgICAgZGF0YSA9IG5ldyBVaW50OEFycmF5KGlucHV0Lmxlbmd0aCAqIDIpOwogICAgICBsZW5ndGggPSAwOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBpbnB1dC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3QgY29kZSA9IGlucHV0LmNoYXJDb2RlQXQoaSk7CiAgICAgICAgaWYgKGNvZGUgPD0gMHhmZikgewogICAgICAgICAgZGF0YVtsZW5ndGgrK10gPSBjb2RlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBkYXRhW2xlbmd0aCsrXSA9IGNvZGUgPj4+IDg7CiAgICAgICAgICBkYXRhW2xlbmd0aCsrXSA9IGNvZGUgJiAweGZmOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIGlmICgoMCwgX3V0aWwuaXNBcnJheUJ1ZmZlcikoaW5wdXQpKSB7CiAgICAgIGRhdGEgPSBpbnB1dC5zbGljZSgpOwogICAgICBsZW5ndGggPSBkYXRhLmJ5dGVMZW5ndGg7CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIldyb25nIGRhdGEgZm9ybWF0IGluIE11cm11ckhhc2gzXzY0X3VwZGF0ZS4gIiArICJJbnB1dCBtdXN0IGJlIGEgc3RyaW5nIG9yIGFycmF5LiIpOwogICAgfQogICAgY29uc3QgYmxvY2tDb3VudHMgPSBsZW5ndGggPj4gMjsKICAgIGNvbnN0IHRhaWxMZW5ndGggPSBsZW5ndGggLSBibG9ja0NvdW50cyAqIDQ7CiAgICBjb25zdCBkYXRhVWludDMyID0gbmV3IFVpbnQzMkFycmF5KGRhdGEuYnVmZmVyLCAwLCBibG9ja0NvdW50cyk7CiAgICBsZXQgazEgPSAwLAogICAgICBrMiA9IDA7CiAgICBsZXQgaDEgPSB0aGlzLmgxLAogICAgICBoMiA9IHRoaXMuaDI7CiAgICBjb25zdCBDMSA9IDB4Y2M5ZTJkNTEsCiAgICAgIEMyID0gMHgxYjg3MzU5MzsKICAgIGNvbnN0IEMxX0xPVyA9IEMxICYgTUFTS19MT1csCiAgICAgIEMyX0xPVyA9IEMyICYgTUFTS19MT1c7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGJsb2NrQ291bnRzOyBpKyspIHsKICAgICAgaWYgKGkgJiAxKSB7CiAgICAgICAgazEgPSBkYXRhVWludDMyW2ldOwogICAgICAgIGsxID0gazEgKiBDMSAmIE1BU0tfSElHSCB8IGsxICogQzFfTE9XICYgTUFTS19MT1c7CiAgICAgICAgazEgPSBrMSA8PCAxNSB8IGsxID4+PiAxNzsKICAgICAgICBrMSA9IGsxICogQzIgJiBNQVNLX0hJR0ggfCBrMSAqIEMyX0xPVyAmIE1BU0tfTE9XOwogICAgICAgIGgxIF49IGsxOwogICAgICAgIGgxID0gaDEgPDwgMTMgfCBoMSA+Pj4gMTk7CiAgICAgICAgaDEgPSBoMSAqIDUgKyAweGU2NTQ2YjY0OwogICAgICB9IGVsc2UgewogICAgICAgIGsyID0gZGF0YVVpbnQzMltpXTsKICAgICAgICBrMiA9IGsyICogQzEgJiBNQVNLX0hJR0ggfCBrMiAqIEMxX0xPVyAmIE1BU0tfTE9XOwogICAgICAgIGsyID0gazIgPDwgMTUgfCBrMiA+Pj4gMTc7CiAgICAgICAgazIgPSBrMiAqIEMyICYgTUFTS19ISUdIIHwgazIgKiBDMl9MT1cgJiBNQVNLX0xPVzsKICAgICAgICBoMiBePSBrMjsKICAgICAgICBoMiA9IGgyIDw8IDEzIHwgaDIgPj4+IDE5OwogICAgICAgIGgyID0gaDIgKiA1ICsgMHhlNjU0NmI2NDsKICAgICAgfQogICAgfQogICAgazEgPSAwOwogICAgc3dpdGNoICh0YWlsTGVuZ3RoKSB7CiAgICAgIGNhc2UgMzoKICAgICAgICBrMSBePSBkYXRhW2Jsb2NrQ291bnRzICogNCArIDJdIDw8IDE2OwogICAgICBjYXNlIDI6CiAgICAgICAgazEgXj0gZGF0YVtibG9ja0NvdW50cyAqIDQgKyAxXSA8PCA4OwogICAgICBjYXNlIDE6CiAgICAgICAgazEgXj0gZGF0YVtibG9ja0NvdW50cyAqIDRdOwogICAgICAgIGsxID0gazEgKiBDMSAmIE1BU0tfSElHSCB8IGsxICogQzFfTE9XICYgTUFTS19MT1c7CiAgICAgICAgazEgPSBrMSA8PCAxNSB8IGsxID4+PiAxNzsKICAgICAgICBrMSA9IGsxICogQzIgJiBNQVNLX0hJR0ggfCBrMSAqIEMyX0xPVyAmIE1BU0tfTE9XOwogICAgICAgIGlmIChibG9ja0NvdW50cyAmIDEpIHsKICAgICAgICAgIGgxIF49IGsxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBoMiBePSBrMTsKICAgICAgICB9CiAgICB9CiAgICB0aGlzLmgxID0gaDE7CiAgICB0aGlzLmgyID0gaDI7CiAgfQogIGhleGRpZ2VzdCgpIHsKICAgIGxldCBoMSA9IHRoaXMuaDEsCiAgICAgIGgyID0gdGhpcy5oMjsKICAgIGgxIF49IGgyID4+PiAxOwogICAgaDEgPSBoMSAqIDB4ZWQ1NThjY2QgJiBNQVNLX0hJR0ggfCBoMSAqIDB4OGNjZCAmIE1BU0tfTE9XOwogICAgaDIgPSBoMiAqIDB4ZmY1MWFmZDcgJiBNQVNLX0hJR0ggfCAoKGgyIDw8IDE2IHwgaDEgPj4+IDE2KSAqIDB4YWZkN2VkNTUgJiBNQVNLX0hJR0gpID4+PiAxNjsKICAgIGgxIF49IGgyID4+PiAxOwogICAgaDEgPSBoMSAqIDB4MWE4NWVjNTMgJiBNQVNLX0hJR0ggfCBoMSAqIDB4ZWM1MyAmIE1BU0tfTE9XOwogICAgaDIgPSBoMiAqIDB4YzRjZWI5ZmUgJiBNQVNLX0hJR0ggfCAoKGgyIDw8IDE2IHwgaDEgPj4+IDE2KSAqIDB4YjlmZTFhODUgJiBNQVNLX0hJR0gpID4+PiAxNjsKICAgIGgxIF49IGgyID4+PiAxOwogICAgcmV0dXJuIChoMSA+Pj4gMCkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDgsICIwIikgKyAoaDIgPj4+IDApLnRvU3RyaW5nKDE2KS5wYWRTdGFydCg4LCAiMCIpOwogIH0KfQpleHBvcnRzLk11cm11ckhhc2gzXzY0ID0gTXVybXVySGFzaDNfNjQ7CgovKioqLyB9KSwKLyogMTk4ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5PcGVyYXRvckxpc3QgPSB2b2lkIDA7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CmZ1bmN0aW9uIGFkZFN0YXRlKHBhcmVudFN0YXRlLCBwYXR0ZXJuLCBjaGVja0ZuLCBpdGVyYXRlRm4sIHByb2Nlc3NGbikgewogIGxldCBzdGF0ZSA9IHBhcmVudFN0YXRlOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IHBhdHRlcm4ubGVuZ3RoIC0gMTsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IGl0ZW0gPSBwYXR0ZXJuW2ldOwogICAgc3RhdGUgPSBzdGF0ZVtpdGVtXSB8fCAoc3RhdGVbaXRlbV0gPSBbXSk7CiAgfQogIHN0YXRlW3BhdHRlcm4uYXQoLTEpXSA9IHsKICAgIGNoZWNrRm4sCiAgICBpdGVyYXRlRm4sCiAgICBwcm9jZXNzRm4KICB9Owp9CmNvbnN0IEluaXRpYWxTdGF0ZSA9IFtdOwphZGRTdGF0ZShJbml0aWFsU3RhdGUsIFtfdXRpbC5PUFMuc2F2ZSwgX3V0aWwuT1BTLnRyYW5zZm9ybSwgX3V0aWwuT1BTLnBhaW50SW5saW5lSW1hZ2VYT2JqZWN0LCBfdXRpbC5PUFMucmVzdG9yZV0sIG51bGwsIGZ1bmN0aW9uIGl0ZXJhdGVJbmxpbmVJbWFnZUdyb3VwKGNvbnRleHQsIGkpIHsKICBjb25zdCBmbkFycmF5ID0gY29udGV4dC5mbkFycmF5OwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjb250ZXh0LmlDdXJyIC0gMzsKICBjb25zdCBwb3MgPSAoaSAtIGlGaXJzdFNhdmUpICUgNDsKICBzd2l0Y2ggKHBvcykgewogICAgY2FzZSAwOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gX3V0aWwuT1BTLnNhdmU7CiAgICBjYXNlIDE6CiAgICAgIHJldHVybiBmbkFycmF5W2ldID09PSBfdXRpbC5PUFMudHJhbnNmb3JtOwogICAgY2FzZSAyOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gX3V0aWwuT1BTLnBhaW50SW5saW5lSW1hZ2VYT2JqZWN0OwogICAgY2FzZSAzOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gX3V0aWwuT1BTLnJlc3RvcmU7CiAgfQogIHRocm93IG5ldyBFcnJvcihgaXRlcmF0ZUlubGluZUltYWdlR3JvdXAgLSBpbnZhbGlkIHBvczogJHtwb3N9YCk7Cn0sIGZ1bmN0aW9uIGZvdW5kSW5saW5lSW1hZ2VHcm91cChjb250ZXh0LCBpKSB7CiAgY29uc3QgTUlOX0lNQUdFU19JTl9JTkxJTkVfSU1BR0VTX0JMT0NLID0gMTA7CiAgY29uc3QgTUFYX0lNQUdFU19JTl9JTkxJTkVfSU1BR0VTX0JMT0NLID0gMjAwOwogIGNvbnN0IE1BWF9XSURUSCA9IDEwMDA7CiAgY29uc3QgSU1BR0VfUEFERElORyA9IDE7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheSwKICAgIGFyZ3NBcnJheSA9IGNvbnRleHQuYXJnc0FycmF5OwogIGNvbnN0IGN1cnIgPSBjb250ZXh0LmlDdXJyOwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjdXJyIC0gMzsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RQSUlYTyA9IGN1cnIgLSAxOwogIGNvbnN0IGNvdW50ID0gTWF0aC5taW4oTWF0aC5mbG9vcigoaSAtIGlGaXJzdFNhdmUpIC8gNCksIE1BWF9JTUFHRVNfSU5fSU5MSU5FX0lNQUdFU19CTE9DSyk7CiAgaWYgKGNvdW50IDwgTUlOX0lNQUdFU19JTl9JTkxJTkVfSU1BR0VTX0JMT0NLKSB7CiAgICByZXR1cm4gaSAtIChpIC0gaUZpcnN0U2F2ZSkgJSA0OwogIH0KICBsZXQgbWF4WCA9IDA7CiAgY29uc3QgbWFwID0gW107CiAgbGV0IG1heExpbmVIZWlnaHQgPSAwOwogIGxldCBjdXJyZW50WCA9IElNQUdFX1BBRERJTkcsCiAgICBjdXJyZW50WSA9IElNQUdFX1BBRERJTkc7CiAgZm9yIChsZXQgcSA9IDA7IHEgPCBjb3VudDsgcSsrKSB7CiAgICBjb25zdCB0cmFuc2Zvcm0gPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtICsgKHEgPDwgMildOwogICAgY29uc3QgaW1nID0gYXJnc0FycmF5W2lGaXJzdFBJSVhPICsgKHEgPDwgMildWzBdOwogICAgaWYgKGN1cnJlbnRYICsgaW1nLndpZHRoID4gTUFYX1dJRFRIKSB7CiAgICAgIG1heFggPSBNYXRoLm1heChtYXhYLCBjdXJyZW50WCk7CiAgICAgIGN1cnJlbnRZICs9IG1heExpbmVIZWlnaHQgKyAyICogSU1BR0VfUEFERElORzsKICAgICAgY3VycmVudFggPSAwOwogICAgICBtYXhMaW5lSGVpZ2h0ID0gMDsKICAgIH0KICAgIG1hcC5wdXNoKHsKICAgICAgdHJhbnNmb3JtLAogICAgICB4OiBjdXJyZW50WCwKICAgICAgeTogY3VycmVudFksCiAgICAgIHc6IGltZy53aWR0aCwKICAgICAgaDogaW1nLmhlaWdodAogICAgfSk7CiAgICBjdXJyZW50WCArPSBpbWcud2lkdGggKyAyICogSU1BR0VfUEFERElORzsKICAgIG1heExpbmVIZWlnaHQgPSBNYXRoLm1heChtYXhMaW5lSGVpZ2h0LCBpbWcuaGVpZ2h0KTsKICB9CiAgY29uc3QgaW1nV2lkdGggPSBNYXRoLm1heChtYXhYLCBjdXJyZW50WCkgKyBJTUFHRV9QQURESU5HOwogIGNvbnN0IGltZ0hlaWdodCA9IGN1cnJlbnRZICsgbWF4TGluZUhlaWdodCArIElNQUdFX1BBRERJTkc7CiAgY29uc3QgaW1nRGF0YSA9IG5ldyBVaW50OEFycmF5KGltZ1dpZHRoICogaW1nSGVpZ2h0ICogNCk7CiAgY29uc3QgaW1nUm93U2l6ZSA9IGltZ1dpZHRoIDw8IDI7CiAgZm9yIChsZXQgcSA9IDA7IHEgPCBjb3VudDsgcSsrKSB7CiAgICBjb25zdCBkYXRhID0gYXJnc0FycmF5W2lGaXJzdFBJSVhPICsgKHEgPDwgMildWzBdLmRhdGE7CiAgICBjb25zdCByb3dTaXplID0gbWFwW3FdLncgPDwgMjsKICAgIGxldCBkYXRhT2Zmc2V0ID0gMDsKICAgIGxldCBvZmZzZXQgPSBtYXBbcV0ueCArIG1hcFtxXS55ICogaW1nV2lkdGggPDwgMjsKICAgIGltZ0RhdGEuc2V0KGRhdGEuc3ViYXJyYXkoMCwgcm93U2l6ZSksIG9mZnNldCAtIGltZ1Jvd1NpemUpOwogICAgZm9yIChsZXQgayA9IDAsIGtrID0gbWFwW3FdLmg7IGsgPCBrazsgaysrKSB7CiAgICAgIGltZ0RhdGEuc2V0KGRhdGEuc3ViYXJyYXkoZGF0YU9mZnNldCwgZGF0YU9mZnNldCArIHJvd1NpemUpLCBvZmZzZXQpOwogICAgICBkYXRhT2Zmc2V0ICs9IHJvd1NpemU7CiAgICAgIG9mZnNldCArPSBpbWdSb3dTaXplOwogICAgfQogICAgaW1nRGF0YS5zZXQoZGF0YS5zdWJhcnJheShkYXRhT2Zmc2V0IC0gcm93U2l6ZSwgZGF0YU9mZnNldCksIG9mZnNldCk7CiAgICB3aGlsZSAob2Zmc2V0ID49IDApIHsKICAgICAgZGF0YVtvZmZzZXQgLSA0XSA9IGRhdGFbb2Zmc2V0XTsKICAgICAgZGF0YVtvZmZzZXQgLSAzXSA9IGRhdGFbb2Zmc2V0ICsgMV07CiAgICAgIGRhdGFbb2Zmc2V0IC0gMl0gPSBkYXRhW29mZnNldCArIDJdOwogICAgICBkYXRhW29mZnNldCAtIDFdID0gZGF0YVtvZmZzZXQgKyAzXTsKICAgICAgZGF0YVtvZmZzZXQgKyByb3dTaXplXSA9IGRhdGFbb2Zmc2V0ICsgcm93U2l6ZSAtIDRdOwogICAgICBkYXRhW29mZnNldCArIHJvd1NpemUgKyAxXSA9IGRhdGFbb2Zmc2V0ICsgcm93U2l6ZSAtIDNdOwogICAgICBkYXRhW29mZnNldCArIHJvd1NpemUgKyAyXSA9IGRhdGFbb2Zmc2V0ICsgcm93U2l6ZSAtIDJdOwogICAgICBkYXRhW29mZnNldCArIHJvd1NpemUgKyAzXSA9IGRhdGFbb2Zmc2V0ICsgcm93U2l6ZSAtIDFdOwogICAgICBvZmZzZXQgLT0gaW1nUm93U2l6ZTsKICAgIH0KICB9CiAgY29uc3QgaW1nID0gewogICAgd2lkdGg6IGltZ1dpZHRoLAogICAgaGVpZ2h0OiBpbWdIZWlnaHQKICB9OwogIGlmIChjb250ZXh0LmlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKSB7CiAgICBjb25zdCBjYW52YXMgPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKGltZ1dpZHRoLCBpbWdIZWlnaHQpOwogICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgICBjdHgucHV0SW1hZ2VEYXRhKG5ldyBJbWFnZURhdGEobmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGltZ0RhdGEuYnVmZmVyKSwgaW1nV2lkdGgsIGltZ0hlaWdodCksIDAsIDApOwogICAgaW1nLmJpdG1hcCA9IGNhbnZhcy50cmFuc2ZlclRvSW1hZ2VCaXRtYXAoKTsKICAgIGltZy5kYXRhID0gbnVsbDsKICB9IGVsc2UgewogICAgaW1nLmtpbmQgPSBfdXRpbC5JbWFnZUtpbmQuUkdCQV8zMkJQUDsKICAgIGltZy5kYXRhID0gaW1nRGF0YTsKICB9CiAgZm5BcnJheS5zcGxpY2UoaUZpcnN0U2F2ZSwgY291bnQgKiA0LCBfdXRpbC5PUFMucGFpbnRJbmxpbmVJbWFnZVhPYmplY3RHcm91cCk7CiAgYXJnc0FycmF5LnNwbGljZShpRmlyc3RTYXZlLCBjb3VudCAqIDQsIFtpbWcsIG1hcF0pOwogIHJldHVybiBpRmlyc3RTYXZlICsgMTsKfSk7CmFkZFN0YXRlKEluaXRpYWxTdGF0ZSwgW191dGlsLk9QUy5zYXZlLCBfdXRpbC5PUFMudHJhbnNmb3JtLCBfdXRpbC5PUFMucGFpbnRJbWFnZU1hc2tYT2JqZWN0LCBfdXRpbC5PUFMucmVzdG9yZV0sIG51bGwsIGZ1bmN0aW9uIGl0ZXJhdGVJbWFnZU1hc2tHcm91cChjb250ZXh0LCBpKSB7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheTsKICBjb25zdCBpRmlyc3RTYXZlID0gY29udGV4dC5pQ3VyciAtIDM7CiAgY29uc3QgcG9zID0gKGkgLSBpRmlyc3RTYXZlKSAlIDQ7CiAgc3dpdGNoIChwb3MpIHsKICAgIGNhc2UgMDoKICAgICAgcmV0dXJuIGZuQXJyYXlbaV0gPT09IF91dGlsLk9QUy5zYXZlOwogICAgY2FzZSAxOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gX3V0aWwuT1BTLnRyYW5zZm9ybTsKICAgIGNhc2UgMjoKICAgICAgcmV0dXJuIGZuQXJyYXlbaV0gPT09IF91dGlsLk9QUy5wYWludEltYWdlTWFza1hPYmplY3Q7CiAgICBjYXNlIDM6CiAgICAgIHJldHVybiBmbkFycmF5W2ldID09PSBfdXRpbC5PUFMucmVzdG9yZTsKICB9CiAgdGhyb3cgbmV3IEVycm9yKGBpdGVyYXRlSW1hZ2VNYXNrR3JvdXAgLSBpbnZhbGlkIHBvczogJHtwb3N9YCk7Cn0sIGZ1bmN0aW9uIGZvdW5kSW1hZ2VNYXNrR3JvdXAoY29udGV4dCwgaSkgewogIGNvbnN0IE1JTl9JTUFHRVNfSU5fTUFTS1NfQkxPQ0sgPSAxMDsKICBjb25zdCBNQVhfSU1BR0VTX0lOX01BU0tTX0JMT0NLID0gMTAwOwogIGNvbnN0IE1BWF9TQU1FX0lNQUdFU19JTl9NQVNLU19CTE9DSyA9IDEwMDA7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheSwKICAgIGFyZ3NBcnJheSA9IGNvbnRleHQuYXJnc0FycmF5OwogIGNvbnN0IGN1cnIgPSBjb250ZXh0LmlDdXJyOwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjdXJyIC0gMzsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RQSU1YTyA9IGN1cnIgLSAxOwogIGxldCBjb3VudCA9IE1hdGguZmxvb3IoKGkgLSBpRmlyc3RTYXZlKSAvIDQpOwogIGlmIChjb3VudCA8IE1JTl9JTUFHRVNfSU5fTUFTS1NfQkxPQ0spIHsKICAgIHJldHVybiBpIC0gKGkgLSBpRmlyc3RTYXZlKSAlIDQ7CiAgfQogIGxldCBpc1NhbWVJbWFnZSA9IGZhbHNlOwogIGxldCBpVHJhbnNmb3JtLCB0cmFuc2Zvcm1BcmdzOwogIGNvbnN0IGZpcnN0UElNWE9BcmcwID0gYXJnc0FycmF5W2lGaXJzdFBJTVhPXVswXTsKICBjb25zdCBmaXJzdFRyYW5zZm9ybUFyZzAgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVswXSwKICAgIGZpcnN0VHJhbnNmb3JtQXJnMSA9IGFyZ3NBcnJheVtpRmlyc3RUcmFuc2Zvcm1dWzFdLAogICAgZmlyc3RUcmFuc2Zvcm1BcmcyID0gYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybV1bMl0sCiAgICBmaXJzdFRyYW5zZm9ybUFyZzMgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVszXTsKICBpZiAoZmlyc3RUcmFuc2Zvcm1BcmcxID09PSBmaXJzdFRyYW5zZm9ybUFyZzIpIHsKICAgIGlzU2FtZUltYWdlID0gdHJ1ZTsKICAgIGlUcmFuc2Zvcm0gPSBpRmlyc3RUcmFuc2Zvcm0gKyA0OwogICAgbGV0IGlQSU1YTyA9IGlGaXJzdFBJTVhPICsgNDsKICAgIGZvciAobGV0IHEgPSAxOyBxIDwgY291bnQ7IHErKywgaVRyYW5zZm9ybSArPSA0LCBpUElNWE8gKz0gNCkgewogICAgICB0cmFuc2Zvcm1BcmdzID0gYXJnc0FycmF5W2lUcmFuc2Zvcm1dOwogICAgICBpZiAoYXJnc0FycmF5W2lQSU1YT11bMF0gIT09IGZpcnN0UElNWE9BcmcwIHx8IHRyYW5zZm9ybUFyZ3NbMF0gIT09IGZpcnN0VHJhbnNmb3JtQXJnMCB8fCB0cmFuc2Zvcm1BcmdzWzFdICE9PSBmaXJzdFRyYW5zZm9ybUFyZzEgfHwgdHJhbnNmb3JtQXJnc1syXSAhPT0gZmlyc3RUcmFuc2Zvcm1BcmcyIHx8IHRyYW5zZm9ybUFyZ3NbM10gIT09IGZpcnN0VHJhbnNmb3JtQXJnMykgewogICAgICAgIGlmIChxIDwgTUlOX0lNQUdFU19JTl9NQVNLU19CTE9DSykgewogICAgICAgICAgaXNTYW1lSW1hZ2UgPSBmYWxzZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY291bnQgPSBxOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogIH0KICBpZiAoaXNTYW1lSW1hZ2UpIHsKICAgIGNvdW50ID0gTWF0aC5taW4oY291bnQsIE1BWF9TQU1FX0lNQUdFU19JTl9NQVNLU19CTE9DSyk7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KGNvdW50ICogMik7CiAgICBpVHJhbnNmb3JtID0gaUZpcnN0VHJhbnNmb3JtOwogICAgZm9yIChsZXQgcSA9IDA7IHEgPCBjb3VudDsgcSsrLCBpVHJhbnNmb3JtICs9IDQpIHsKICAgICAgdHJhbnNmb3JtQXJncyA9IGFyZ3NBcnJheVtpVHJhbnNmb3JtXTsKICAgICAgcG9zaXRpb25zW3EgPDwgMV0gPSB0cmFuc2Zvcm1BcmdzWzRdOwogICAgICBwb3NpdGlvbnNbKHEgPDwgMSkgKyAxXSA9IHRyYW5zZm9ybUFyZ3NbNV07CiAgICB9CiAgICBmbkFycmF5LnNwbGljZShpRmlyc3RTYXZlLCBjb3VudCAqIDQsIF91dGlsLk9QUy5wYWludEltYWdlTWFza1hPYmplY3RSZXBlYXQpOwogICAgYXJnc0FycmF5LnNwbGljZShpRmlyc3RTYXZlLCBjb3VudCAqIDQsIFtmaXJzdFBJTVhPQXJnMCwgZmlyc3RUcmFuc2Zvcm1BcmcwLCBmaXJzdFRyYW5zZm9ybUFyZzEsIGZpcnN0VHJhbnNmb3JtQXJnMiwgZmlyc3RUcmFuc2Zvcm1BcmczLCBwb3NpdGlvbnNdKTsKICB9IGVsc2UgewogICAgY291bnQgPSBNYXRoLm1pbihjb3VudCwgTUFYX0lNQUdFU19JTl9NQVNLU19CTE9DSyk7CiAgICBjb25zdCBpbWFnZXMgPSBbXTsKICAgIGZvciAobGV0IHEgPSAwOyBxIDwgY291bnQ7IHErKykgewogICAgICB0cmFuc2Zvcm1BcmdzID0gYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybSArIChxIDw8IDIpXTsKICAgICAgY29uc3QgbWFza1BhcmFtcyA9IGFyZ3NBcnJheVtpRmlyc3RQSU1YTyArIChxIDw8IDIpXVswXTsKICAgICAgaW1hZ2VzLnB1c2goewogICAgICAgIGRhdGE6IG1hc2tQYXJhbXMuZGF0YSwKICAgICAgICB3aWR0aDogbWFza1BhcmFtcy53aWR0aCwKICAgICAgICBoZWlnaHQ6IG1hc2tQYXJhbXMuaGVpZ2h0LAogICAgICAgIGludGVycG9sYXRlOiBtYXNrUGFyYW1zLmludGVycG9sYXRlLAogICAgICAgIGNvdW50OiBtYXNrUGFyYW1zLmNvdW50LAogICAgICAgIHRyYW5zZm9ybTogdHJhbnNmb3JtQXJncwogICAgICB9KTsKICAgIH0KICAgIGZuQXJyYXkuc3BsaWNlKGlGaXJzdFNhdmUsIGNvdW50ICogNCwgX3V0aWwuT1BTLnBhaW50SW1hZ2VNYXNrWE9iamVjdEdyb3VwKTsKICAgIGFyZ3NBcnJheS5zcGxpY2UoaUZpcnN0U2F2ZSwgY291bnQgKiA0LCBbaW1hZ2VzXSk7CiAgfQogIHJldHVybiBpRmlyc3RTYXZlICsgMTsKfSk7CmFkZFN0YXRlKEluaXRpYWxTdGF0ZSwgW191dGlsLk9QUy5zYXZlLCBfdXRpbC5PUFMudHJhbnNmb3JtLCBfdXRpbC5PUFMucGFpbnRJbWFnZVhPYmplY3QsIF91dGlsLk9QUy5yZXN0b3JlXSwgZnVuY3Rpb24gKGNvbnRleHQpIHsKICBjb25zdCBhcmdzQXJyYXkgPSBjb250ZXh0LmFyZ3NBcnJheTsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjb250ZXh0LmlDdXJyIC0gMjsKICByZXR1cm4gYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybV1bMV0gPT09IDAgJiYgYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybV1bMl0gPT09IDA7Cn0sIGZ1bmN0aW9uIGl0ZXJhdGVJbWFnZUdyb3VwKGNvbnRleHQsIGkpIHsKICBjb25zdCBmbkFycmF5ID0gY29udGV4dC5mbkFycmF5LAogICAgYXJnc0FycmF5ID0gY29udGV4dC5hcmdzQXJyYXk7CiAgY29uc3QgaUZpcnN0U2F2ZSA9IGNvbnRleHQuaUN1cnIgLSAzOwogIGNvbnN0IHBvcyA9IChpIC0gaUZpcnN0U2F2ZSkgJSA0OwogIHN3aXRjaCAocG9zKSB7CiAgICBjYXNlIDA6CiAgICAgIHJldHVybiBmbkFycmF5W2ldID09PSBfdXRpbC5PUFMuc2F2ZTsKICAgIGNhc2UgMToKICAgICAgaWYgKGZuQXJyYXlbaV0gIT09IF91dGlsLk9QUy50cmFuc2Zvcm0pIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgY29uc3QgaUZpcnN0VHJhbnNmb3JtID0gY29udGV4dC5pQ3VyciAtIDI7CiAgICAgIGNvbnN0IGZpcnN0VHJhbnNmb3JtQXJnMCA9IGFyZ3NBcnJheVtpRmlyc3RUcmFuc2Zvcm1dWzBdOwogICAgICBjb25zdCBmaXJzdFRyYW5zZm9ybUFyZzMgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVszXTsKICAgICAgaWYgKGFyZ3NBcnJheVtpXVswXSAhPT0gZmlyc3RUcmFuc2Zvcm1BcmcwIHx8IGFyZ3NBcnJheVtpXVsxXSAhPT0gMCB8fCBhcmdzQXJyYXlbaV1bMl0gIT09IDAgfHwgYXJnc0FycmF5W2ldWzNdICE9PSBmaXJzdFRyYW5zZm9ybUFyZzMpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgcmV0dXJuIHRydWU7CiAgICBjYXNlIDI6CiAgICAgIGlmIChmbkFycmF5W2ldICE9PSBfdXRpbC5PUFMucGFpbnRJbWFnZVhPYmplY3QpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgY29uc3QgaUZpcnN0UElYTyA9IGNvbnRleHQuaUN1cnIgLSAxOwogICAgICBjb25zdCBmaXJzdFBJWE9BcmcwID0gYXJnc0FycmF5W2lGaXJzdFBJWE9dWzBdOwogICAgICBpZiAoYXJnc0FycmF5W2ldWzBdICE9PSBmaXJzdFBJWE9BcmcwKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIHJldHVybiB0cnVlOwogICAgY2FzZSAzOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gX3V0aWwuT1BTLnJlc3RvcmU7CiAgfQogIHRocm93IG5ldyBFcnJvcihgaXRlcmF0ZUltYWdlR3JvdXAgLSBpbnZhbGlkIHBvczogJHtwb3N9YCk7Cn0sIGZ1bmN0aW9uIChjb250ZXh0LCBpKSB7CiAgY29uc3QgTUlOX0lNQUdFU19JTl9CTE9DSyA9IDM7CiAgY29uc3QgTUFYX0lNQUdFU19JTl9CTE9DSyA9IDEwMDA7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheSwKICAgIGFyZ3NBcnJheSA9IGNvbnRleHQuYXJnc0FycmF5OwogIGNvbnN0IGN1cnIgPSBjb250ZXh0LmlDdXJyOwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjdXJyIC0gMzsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RQSVhPID0gY3VyciAtIDE7CiAgY29uc3QgZmlyc3RQSVhPQXJnMCA9IGFyZ3NBcnJheVtpRmlyc3RQSVhPXVswXTsKICBjb25zdCBmaXJzdFRyYW5zZm9ybUFyZzAgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVswXTsKICBjb25zdCBmaXJzdFRyYW5zZm9ybUFyZzMgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVszXTsKICBjb25zdCBjb3VudCA9IE1hdGgubWluKE1hdGguZmxvb3IoKGkgLSBpRmlyc3RTYXZlKSAvIDQpLCBNQVhfSU1BR0VTX0lOX0JMT0NLKTsKICBpZiAoY291bnQgPCBNSU5fSU1BR0VTX0lOX0JMT0NLKSB7CiAgICByZXR1cm4gaSAtIChpIC0gaUZpcnN0U2F2ZSkgJSA0OwogIH0KICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KGNvdW50ICogMik7CiAgbGV0IGlUcmFuc2Zvcm0gPSBpRmlyc3RUcmFuc2Zvcm07CiAgZm9yIChsZXQgcSA9IDA7IHEgPCBjb3VudDsgcSsrLCBpVHJhbnNmb3JtICs9IDQpIHsKICAgIGNvbnN0IHRyYW5zZm9ybUFyZ3MgPSBhcmdzQXJyYXlbaVRyYW5zZm9ybV07CiAgICBwb3NpdGlvbnNbcSA8PCAxXSA9IHRyYW5zZm9ybUFyZ3NbNF07CiAgICBwb3NpdGlvbnNbKHEgPDwgMSkgKyAxXSA9IHRyYW5zZm9ybUFyZ3NbNV07CiAgfQogIGNvbnN0IGFyZ3MgPSBbZmlyc3RQSVhPQXJnMCwgZmlyc3RUcmFuc2Zvcm1BcmcwLCBmaXJzdFRyYW5zZm9ybUFyZzMsIHBvc2l0aW9uc107CiAgZm5BcnJheS5zcGxpY2UoaUZpcnN0U2F2ZSwgY291bnQgKiA0LCBfdXRpbC5PUFMucGFpbnRJbWFnZVhPYmplY3RSZXBlYXQpOwogIGFyZ3NBcnJheS5zcGxpY2UoaUZpcnN0U2F2ZSwgY291bnQgKiA0LCBhcmdzKTsKICByZXR1cm4gaUZpcnN0U2F2ZSArIDE7Cn0pOwphZGRTdGF0ZShJbml0aWFsU3RhdGUsIFtfdXRpbC5PUFMuYmVnaW5UZXh0LCBfdXRpbC5PUFMuc2V0Rm9udCwgX3V0aWwuT1BTLnNldFRleHRNYXRyaXgsIF91dGlsLk9QUy5zaG93VGV4dCwgX3V0aWwuT1BTLmVuZFRleHRdLCBudWxsLCBmdW5jdGlvbiBpdGVyYXRlU2hvd1RleHRHcm91cChjb250ZXh0LCBpKSB7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheSwKICAgIGFyZ3NBcnJheSA9IGNvbnRleHQuYXJnc0FycmF5OwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjb250ZXh0LmlDdXJyIC0gNDsKICBjb25zdCBwb3MgPSAoaSAtIGlGaXJzdFNhdmUpICUgNTsKICBzd2l0Y2ggKHBvcykgewogICAgY2FzZSAwOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gX3V0aWwuT1BTLmJlZ2luVGV4dDsKICAgIGNhc2UgMToKICAgICAgcmV0dXJuIGZuQXJyYXlbaV0gPT09IF91dGlsLk9QUy5zZXRGb250OwogICAgY2FzZSAyOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gX3V0aWwuT1BTLnNldFRleHRNYXRyaXg7CiAgICBjYXNlIDM6CiAgICAgIGlmIChmbkFycmF5W2ldICE9PSBfdXRpbC5PUFMuc2hvd1RleHQpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgY29uc3QgaUZpcnN0U2V0Rm9udCA9IGNvbnRleHQuaUN1cnIgLSAzOwogICAgICBjb25zdCBmaXJzdFNldEZvbnRBcmcwID0gYXJnc0FycmF5W2lGaXJzdFNldEZvbnRdWzBdOwogICAgICBjb25zdCBmaXJzdFNldEZvbnRBcmcxID0gYXJnc0FycmF5W2lGaXJzdFNldEZvbnRdWzFdOwogICAgICBpZiAoYXJnc0FycmF5W2ldWzBdICE9PSBmaXJzdFNldEZvbnRBcmcwIHx8IGFyZ3NBcnJheVtpXVsxXSAhPT0gZmlyc3RTZXRGb250QXJnMSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICByZXR1cm4gdHJ1ZTsKICAgIGNhc2UgNDoKICAgICAgcmV0dXJuIGZuQXJyYXlbaV0gPT09IF91dGlsLk9QUy5lbmRUZXh0OwogIH0KICB0aHJvdyBuZXcgRXJyb3IoYGl0ZXJhdGVTaG93VGV4dEdyb3VwIC0gaW52YWxpZCBwb3M6ICR7cG9zfWApOwp9LCBmdW5jdGlvbiAoY29udGV4dCwgaSkgewogIGNvbnN0IE1JTl9DSEFSU19JTl9CTE9DSyA9IDM7CiAgY29uc3QgTUFYX0NIQVJTX0lOX0JMT0NLID0gMTAwMDsKICBjb25zdCBmbkFycmF5ID0gY29udGV4dC5mbkFycmF5LAogICAgYXJnc0FycmF5ID0gY29udGV4dC5hcmdzQXJyYXk7CiAgY29uc3QgY3VyciA9IGNvbnRleHQuaUN1cnI7CiAgY29uc3QgaUZpcnN0QmVnaW5UZXh0ID0gY3VyciAtIDQ7CiAgY29uc3QgaUZpcnN0U2V0Rm9udCA9IGN1cnIgLSAzOwogIGNvbnN0IGlGaXJzdFNldFRleHRNYXRyaXggPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RTaG93VGV4dCA9IGN1cnIgLSAxOwogIGNvbnN0IGlGaXJzdEVuZFRleHQgPSBjdXJyOwogIGNvbnN0IGZpcnN0U2V0Rm9udEFyZzAgPSBhcmdzQXJyYXlbaUZpcnN0U2V0Rm9udF1bMF07CiAgY29uc3QgZmlyc3RTZXRGb250QXJnMSA9IGFyZ3NBcnJheVtpRmlyc3RTZXRGb250XVsxXTsKICBsZXQgY291bnQgPSBNYXRoLm1pbihNYXRoLmZsb29yKChpIC0gaUZpcnN0QmVnaW5UZXh0KSAvIDUpLCBNQVhfQ0hBUlNfSU5fQkxPQ0spOwogIGlmIChjb3VudCA8IE1JTl9DSEFSU19JTl9CTE9DSykgewogICAgcmV0dXJuIGkgLSAoaSAtIGlGaXJzdEJlZ2luVGV4dCkgJSA1OwogIH0KICBsZXQgaUZpcnN0ID0gaUZpcnN0QmVnaW5UZXh0OwogIGlmIChpRmlyc3RCZWdpblRleHQgPj0gNCAmJiBmbkFycmF5W2lGaXJzdEJlZ2luVGV4dCAtIDRdID09PSBmbkFycmF5W2lGaXJzdFNldEZvbnRdICYmIGZuQXJyYXlbaUZpcnN0QmVnaW5UZXh0IC0gM10gPT09IGZuQXJyYXlbaUZpcnN0U2V0VGV4dE1hdHJpeF0gJiYgZm5BcnJheVtpRmlyc3RCZWdpblRleHQgLSAyXSA9PT0gZm5BcnJheVtpRmlyc3RTaG93VGV4dF0gJiYgZm5BcnJheVtpRmlyc3RCZWdpblRleHQgLSAxXSA9PT0gZm5BcnJheVtpRmlyc3RFbmRUZXh0XSAmJiBhcmdzQXJyYXlbaUZpcnN0QmVnaW5UZXh0IC0gNF1bMF0gPT09IGZpcnN0U2V0Rm9udEFyZzAgJiYgYXJnc0FycmF5W2lGaXJzdEJlZ2luVGV4dCAtIDRdWzFdID09PSBmaXJzdFNldEZvbnRBcmcxKSB7CiAgICBjb3VudCsrOwogICAgaUZpcnN0IC09IDU7CiAgfQogIGxldCBpRW5kVGV4dCA9IGlGaXJzdCArIDQ7CiAgZm9yIChsZXQgcSA9IDE7IHEgPCBjb3VudDsgcSsrKSB7CiAgICBmbkFycmF5LnNwbGljZShpRW5kVGV4dCwgMyk7CiAgICBhcmdzQXJyYXkuc3BsaWNlKGlFbmRUZXh0LCAzKTsKICAgIGlFbmRUZXh0ICs9IDI7CiAgfQogIHJldHVybiBpRW5kVGV4dCArIDE7Cn0pOwpjbGFzcyBOdWxsT3B0aW1pemVyIHsKICBjb25zdHJ1Y3RvcihxdWV1ZSkgewogICAgdGhpcy5xdWV1ZSA9IHF1ZXVlOwogIH0KICBfb3B0aW1pemUoKSB7fQogIHB1c2goZm4sIGFyZ3MpIHsKICAgIHRoaXMucXVldWUuZm5BcnJheS5wdXNoKGZuKTsKICAgIHRoaXMucXVldWUuYXJnc0FycmF5LnB1c2goYXJncyk7CiAgICB0aGlzLl9vcHRpbWl6ZSgpOwogIH0KICBmbHVzaCgpIHt9CiAgcmVzZXQoKSB7fQp9CmNsYXNzIFF1ZXVlT3B0aW1pemVyIGV4dGVuZHMgTnVsbE9wdGltaXplciB7CiAgY29uc3RydWN0b3IocXVldWUpIHsKICAgIHN1cGVyKHF1ZXVlKTsKICAgIHRoaXMuc3RhdGUgPSBudWxsOwogICAgdGhpcy5jb250ZXh0ID0gewogICAgICBpQ3VycjogMCwKICAgICAgZm5BcnJheTogcXVldWUuZm5BcnJheSwKICAgICAgYXJnc0FycmF5OiBxdWV1ZS5hcmdzQXJyYXksCiAgICAgIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkOiBmYWxzZQogICAgfTsKICAgIHRoaXMubWF0Y2ggPSBudWxsOwogICAgdGhpcy5sYXN0UHJvY2Vzc2VkID0gMDsKICB9CiAgc2V0IGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKHZhbHVlKSB7CiAgICB0aGlzLmNvbnRleHQuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgPSB2YWx1ZTsKICB9CiAgX29wdGltaXplKCkgewogICAgY29uc3QgZm5BcnJheSA9IHRoaXMucXVldWUuZm5BcnJheTsKICAgIGxldCBpID0gdGhpcy5sYXN0UHJvY2Vzc2VkLAogICAgICBpaSA9IGZuQXJyYXkubGVuZ3RoOwogICAgbGV0IHN0YXRlID0gdGhpcy5zdGF0ZTsKICAgIGxldCBtYXRjaCA9IHRoaXMubWF0Y2g7CiAgICBpZiAoIXN0YXRlICYmICFtYXRjaCAmJiBpICsgMSA9PT0gaWkgJiYgIUluaXRpYWxTdGF0ZVtmbkFycmF5W2ldXSkgewogICAgICB0aGlzLmxhc3RQcm9jZXNzZWQgPSBpaTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgY29udGV4dCA9IHRoaXMuY29udGV4dDsKICAgIHdoaWxlIChpIDwgaWkpIHsKICAgICAgaWYgKG1hdGNoKSB7CiAgICAgICAgY29uc3QgaXRlcmF0ZSA9ICgwLCBtYXRjaC5pdGVyYXRlRm4pKGNvbnRleHQsIGkpOwogICAgICAgIGlmIChpdGVyYXRlKSB7CiAgICAgICAgICBpKys7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaSA9ICgwLCBtYXRjaC5wcm9jZXNzRm4pKGNvbnRleHQsIGkgKyAxKTsKICAgICAgICBpaSA9IGZuQXJyYXkubGVuZ3RoOwogICAgICAgIG1hdGNoID0gbnVsbDsKICAgICAgICBzdGF0ZSA9IG51bGw7CiAgICAgICAgaWYgKGkgPj0gaWkpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBzdGF0ZSA9IChzdGF0ZSB8fCBJbml0aWFsU3RhdGUpW2ZuQXJyYXlbaV1dOwogICAgICBpZiAoIXN0YXRlIHx8IEFycmF5LmlzQXJyYXkoc3RhdGUpKSB7CiAgICAgICAgaSsrOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnRleHQuaUN1cnIgPSBpOwogICAgICBpKys7CiAgICAgIGlmIChzdGF0ZS5jaGVja0ZuICYmICEoMCwgc3RhdGUuY2hlY2tGbikoY29udGV4dCkpIHsKICAgICAgICBzdGF0ZSA9IG51bGw7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgbWF0Y2ggPSBzdGF0ZTsKICAgICAgc3RhdGUgPSBudWxsOwogICAgfQogICAgdGhpcy5zdGF0ZSA9IHN0YXRlOwogICAgdGhpcy5tYXRjaCA9IG1hdGNoOwogICAgdGhpcy5sYXN0UHJvY2Vzc2VkID0gaTsKICB9CiAgZmx1c2goKSB7CiAgICB3aGlsZSAodGhpcy5tYXRjaCkgewogICAgICBjb25zdCBsZW5ndGggPSB0aGlzLnF1ZXVlLmZuQXJyYXkubGVuZ3RoOwogICAgICB0aGlzLmxhc3RQcm9jZXNzZWQgPSAoMCwgdGhpcy5tYXRjaC5wcm9jZXNzRm4pKHRoaXMuY29udGV4dCwgbGVuZ3RoKTsKICAgICAgdGhpcy5tYXRjaCA9IG51bGw7CiAgICAgIHRoaXMuc3RhdGUgPSBudWxsOwogICAgICB0aGlzLl9vcHRpbWl6ZSgpOwogICAgfQogIH0KICByZXNldCgpIHsKICAgIHRoaXMuc3RhdGUgPSBudWxsOwogICAgdGhpcy5tYXRjaCA9IG51bGw7CiAgICB0aGlzLmxhc3RQcm9jZXNzZWQgPSAwOwogIH0KfQpjbGFzcyBPcGVyYXRvckxpc3QgewogIHN0YXRpYyBnZXQgQ0hVTktfU0laRSgpIHsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiQ0hVTktfU0laRSIsIDEwMDApOwogIH0KICBzdGF0aWMgZ2V0IENIVU5LX1NJWkVfQUJPVVQoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIkNIVU5LX1NJWkVfQUJPVVQiLCB0aGlzLkNIVU5LX1NJWkUgLSA1KTsKICB9CiAgY29uc3RydWN0b3IoKSB7CiAgICBsZXQgaW50ZW50ID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiAwOwogICAgbGV0IHN0cmVhbVNpbmsgPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZDsKICAgIHRoaXMuX3N0cmVhbVNpbmsgPSBzdHJlYW1TaW5rOwogICAgdGhpcy5mbkFycmF5ID0gW107CiAgICB0aGlzLmFyZ3NBcnJheSA9IFtdOwogICAgaWYgKHN0cmVhbVNpbmsgJiYgIShpbnRlbnQgJiBfdXRpbC5SZW5kZXJpbmdJbnRlbnRGbGFnLk9QTElTVCkpIHsKICAgICAgdGhpcy5vcHRpbWl6ZXIgPSBuZXcgUXVldWVPcHRpbWl6ZXIodGhpcyk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLm9wdGltaXplciA9IG5ldyBOdWxsT3B0aW1pemVyKHRoaXMpOwogICAgfQogICAgdGhpcy5kZXBlbmRlbmNpZXMgPSBuZXcgU2V0KCk7CiAgICB0aGlzLl90b3RhbExlbmd0aCA9IDA7CiAgICB0aGlzLndlaWdodCA9IDA7CiAgICB0aGlzLl9yZXNvbHZlZCA9IHN0cmVhbVNpbmsgPyBudWxsIDogUHJvbWlzZS5yZXNvbHZlKCk7CiAgfQogIHNldCBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCh2YWx1ZSkgewogICAgdGhpcy5vcHRpbWl6ZXIuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgPSB2YWx1ZTsKICB9CiAgZ2V0IGxlbmd0aCgpIHsKICAgIHJldHVybiB0aGlzLmFyZ3NBcnJheS5sZW5ndGg7CiAgfQogIGdldCByZWFkeSgpIHsKICAgIHJldHVybiB0aGlzLl9yZXNvbHZlZCB8fCB0aGlzLl9zdHJlYW1TaW5rLnJlYWR5OwogIH0KICBnZXQgdG90YWxMZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5fdG90YWxMZW5ndGggKyB0aGlzLmxlbmd0aDsKICB9CiAgYWRkT3AoZm4sIGFyZ3MpIHsKICAgIHRoaXMub3B0aW1pemVyLnB1c2goZm4sIGFyZ3MpOwogICAgdGhpcy53ZWlnaHQrKzsKICAgIGlmICh0aGlzLl9zdHJlYW1TaW5rKSB7CiAgICAgIGlmICh0aGlzLndlaWdodCA+PSBPcGVyYXRvckxpc3QuQ0hVTktfU0laRSkgewogICAgICAgIHRoaXMuZmx1c2goKTsKICAgICAgfSBlbHNlIGlmICh0aGlzLndlaWdodCA+PSBPcGVyYXRvckxpc3QuQ0hVTktfU0laRV9BQk9VVCAmJiAoZm4gPT09IF91dGlsLk9QUy5yZXN0b3JlIHx8IGZuID09PSBfdXRpbC5PUFMuZW5kVGV4dCkpIHsKICAgICAgICB0aGlzLmZsdXNoKCk7CiAgICAgIH0KICAgIH0KICB9CiAgYWRkSW1hZ2VPcHMoZm4sIGFyZ3MsIG9wdGlvbmFsQ29udGVudCkgewogICAgaWYgKG9wdGlvbmFsQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHRoaXMuYWRkT3AoX3V0aWwuT1BTLmJlZ2luTWFya2VkQ29udGVudFByb3BzLCBbIk9DIiwgb3B0aW9uYWxDb250ZW50XSk7CiAgICB9CiAgICB0aGlzLmFkZE9wKGZuLCBhcmdzKTsKICAgIGlmIChvcHRpb25hbENvbnRlbnQgIT09IHVuZGVmaW5lZCkgewogICAgICB0aGlzLmFkZE9wKF91dGlsLk9QUy5lbmRNYXJrZWRDb250ZW50LCBbXSk7CiAgICB9CiAgfQogIGFkZERlcGVuZGVuY3koZGVwZW5kZW5jeSkgewogICAgaWYgKHRoaXMuZGVwZW5kZW5jaWVzLmhhcyhkZXBlbmRlbmN5KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLmRlcGVuZGVuY2llcy5hZGQoZGVwZW5kZW5jeSk7CiAgICB0aGlzLmFkZE9wKF91dGlsLk9QUy5kZXBlbmRlbmN5LCBbZGVwZW5kZW5jeV0pOwogIH0KICBhZGREZXBlbmRlbmNpZXMoZGVwZW5kZW5jaWVzKSB7CiAgICBmb3IgKGNvbnN0IGRlcGVuZGVuY3kgb2YgZGVwZW5kZW5jaWVzKSB7CiAgICAgIHRoaXMuYWRkRGVwZW5kZW5jeShkZXBlbmRlbmN5KTsKICAgIH0KICB9CiAgYWRkT3BMaXN0KG9wTGlzdCkgewogICAgaWYgKCEob3BMaXN0IGluc3RhbmNlb2YgT3BlcmF0b3JMaXN0KSkgewogICAgICAoMCwgX3V0aWwud2FybikoJ2FkZE9wTGlzdCAtIGlnbm9yaW5nIGludmFsaWQgIm9wTGlzdCIgcGFyYW1ldGVyLicpOwogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGNvbnN0IGRlcGVuZGVuY3kgb2Ygb3BMaXN0LmRlcGVuZGVuY2llcykgewogICAgICB0aGlzLmRlcGVuZGVuY2llcy5hZGQoZGVwZW5kZW5jeSk7CiAgICB9CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBvcExpc3QubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICB0aGlzLmFkZE9wKG9wTGlzdC5mbkFycmF5W2ldLCBvcExpc3QuYXJnc0FycmF5W2ldKTsKICAgIH0KICB9CiAgZ2V0SVIoKSB7CiAgICByZXR1cm4gewogICAgICBmbkFycmF5OiB0aGlzLmZuQXJyYXksCiAgICAgIGFyZ3NBcnJheTogdGhpcy5hcmdzQXJyYXksCiAgICAgIGxlbmd0aDogdGhpcy5sZW5ndGgKICAgIH07CiAgfQogIGdldCBfdHJhbnNmZXJzKCkgewogICAgY29uc3QgdHJhbnNmZXJzID0gW107CiAgICBjb25zdCB7CiAgICAgIGZuQXJyYXksCiAgICAgIGFyZ3NBcnJheSwKICAgICAgbGVuZ3RoCiAgICB9ID0gdGhpczsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgc3dpdGNoIChmbkFycmF5W2ldKSB7CiAgICAgICAgY2FzZSBfdXRpbC5PUFMucGFpbnRJbmxpbmVJbWFnZVhPYmplY3Q6CiAgICAgICAgY2FzZSBfdXRpbC5PUFMucGFpbnRJbmxpbmVJbWFnZVhPYmplY3RHcm91cDoKICAgICAgICBjYXNlIF91dGlsLk9QUy5wYWludEltYWdlTWFza1hPYmplY3Q6CiAgICAgICAgICBjb25zdCBhcmcgPSBhcmdzQXJyYXlbaV1bMF07CiAgICAgICAgICBpZiAoIWFyZy5jYWNoZWQgJiYgYXJnLmRhdGEgJiYgYXJnLmRhdGEuYnVmZmVyIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHsKICAgICAgICAgICAgdHJhbnNmZXJzLnB1c2goYXJnLmRhdGEuYnVmZmVyKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHJhbnNmZXJzOwogIH0KICBmbHVzaCgpIHsKICAgIGxldCBsYXN0Q2h1bmsgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgbGV0IHNlcGFyYXRlQW5ub3RzID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBudWxsOwogICAgdGhpcy5vcHRpbWl6ZXIuZmx1c2goKTsKICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMubGVuZ3RoOwogICAgdGhpcy5fdG90YWxMZW5ndGggKz0gbGVuZ3RoOwogICAgdGhpcy5fc3RyZWFtU2luay5lbnF1ZXVlKHsKICAgICAgZm5BcnJheTogdGhpcy5mbkFycmF5LAogICAgICBhcmdzQXJyYXk6IHRoaXMuYXJnc0FycmF5LAogICAgICBsYXN0Q2h1bmssCiAgICAgIHNlcGFyYXRlQW5ub3RzLAogICAgICBsZW5ndGgKICAgIH0sIDEsIHRoaXMuX3RyYW5zZmVycyk7CiAgICB0aGlzLmRlcGVuZGVuY2llcy5jbGVhcigpOwogICAgdGhpcy5mbkFycmF5Lmxlbmd0aCA9IDA7CiAgICB0aGlzLmFyZ3NBcnJheS5sZW5ndGggPSAwOwogICAgdGhpcy53ZWlnaHQgPSAwOwogICAgdGhpcy5vcHRpbWl6ZXIucmVzZXQoKTsKICB9Cn0KZXhwb3J0cy5PcGVyYXRvckxpc3QgPSBPcGVyYXRvckxpc3Q7CgovKioqLyB9KSwKLyogMTk5ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5QREZJbWFnZSA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9pbWFnZV91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTYzKTsKdmFyIF9iYXNlX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQxKTsKdmFyIF9jb2xvcnNwYWNlID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDgpOwp2YXIgX2RlY29kZV9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE1Myk7CnZhciBfaW1hZ2VfcmVzaXplciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTk2KTsKdmFyIF9qcGVnX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTYxKTsKdmFyIF9qcHggPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE2NSk7CnZhciBfcHJpbWl0aXZlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQwKTsKZnVuY3Rpb24gZGVjb2RlQW5kQ2xhbXAodmFsdWUsIGFkZGVuZCwgY29lZmZpY2llbnQsIG1heCkgewogIHZhbHVlID0gYWRkZW5kICsgdmFsdWUgKiBjb2VmZmljaWVudDsKICBpZiAodmFsdWUgPCAwKSB7CiAgICB2YWx1ZSA9IDA7CiAgfSBlbHNlIGlmICh2YWx1ZSA+IG1heCkgewogICAgdmFsdWUgPSBtYXg7CiAgfQogIHJldHVybiB2YWx1ZTsKfQpmdW5jdGlvbiByZXNpemVJbWFnZU1hc2soc3JjLCBicGMsIHcxLCBoMSwgdzIsIGgyKSB7CiAgY29uc3QgbGVuZ3RoID0gdzIgKiBoMjsKICBsZXQgZGVzdDsKICBpZiAoYnBjIDw9IDgpIHsKICAgIGRlc3QgPSBuZXcgVWludDhBcnJheShsZW5ndGgpOwogIH0gZWxzZSBpZiAoYnBjIDw9IDE2KSB7CiAgICBkZXN0ID0gbmV3IFVpbnQxNkFycmF5KGxlbmd0aCk7CiAgfSBlbHNlIHsKICAgIGRlc3QgPSBuZXcgVWludDMyQXJyYXkobGVuZ3RoKTsKICB9CiAgY29uc3QgeFJhdGlvID0gdzEgLyB3MjsKICBjb25zdCB5UmF0aW8gPSBoMSAvIGgyOwogIGxldCBpLAogICAgaiwKICAgIHB5LAogICAgbmV3SW5kZXggPSAwLAogICAgb2xkSW5kZXg7CiAgY29uc3QgeFNjYWxlZCA9IG5ldyBVaW50MTZBcnJheSh3Mik7CiAgY29uc3QgdzFTY2FubGluZSA9IHcxOwogIGZvciAoaSA9IDA7IGkgPCB3MjsgaSsrKSB7CiAgICB4U2NhbGVkW2ldID0gTWF0aC5mbG9vcihpICogeFJhdGlvKTsKICB9CiAgZm9yIChpID0gMDsgaSA8IGgyOyBpKyspIHsKICAgIHB5ID0gTWF0aC5mbG9vcihpICogeVJhdGlvKSAqIHcxU2NhbmxpbmU7CiAgICBmb3IgKGogPSAwOyBqIDwgdzI7IGorKykgewogICAgICBvbGRJbmRleCA9IHB5ICsgeFNjYWxlZFtqXTsKICAgICAgZGVzdFtuZXdJbmRleCsrXSA9IHNyY1tvbGRJbmRleF07CiAgICB9CiAgfQogIHJldHVybiBkZXN0Owp9CmNsYXNzIFBERkltYWdlIHsKICBjb25zdHJ1Y3RvcihfcmVmKSB7CiAgICBsZXQgewogICAgICB4cmVmLAogICAgICByZXMsCiAgICAgIGltYWdlLAogICAgICBpc0lubGluZSA9IGZhbHNlLAogICAgICBzbWFzayA9IG51bGwsCiAgICAgIG1hc2sgPSBudWxsLAogICAgICBpc01hc2sgPSBmYWxzZSwKICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgfSA9IF9yZWY7CiAgICB0aGlzLmltYWdlID0gaW1hZ2U7CiAgICBjb25zdCBkaWN0ID0gaW1hZ2UuZGljdDsKICAgIGNvbnN0IGZpbHRlciA9IGRpY3QuZ2V0KCJGIiwgIkZpbHRlciIpOwogICAgbGV0IGZpbHRlck5hbWU7CiAgICBpZiAoZmlsdGVyIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICBmaWx0ZXJOYW1lID0gZmlsdGVyLm5hbWU7CiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZmlsdGVyKSkgewogICAgICBjb25zdCBmaWx0ZXJaZXJvID0geHJlZi5mZXRjaElmUmVmKGZpbHRlclswXSk7CiAgICAgIGlmIChmaWx0ZXJaZXJvIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICAgIGZpbHRlck5hbWUgPSBmaWx0ZXJaZXJvLm5hbWU7CiAgICAgIH0KICAgIH0KICAgIHN3aXRjaCAoZmlsdGVyTmFtZSkgewogICAgICBjYXNlICJKUFhEZWNvZGUiOgogICAgICAgIGNvbnN0IGpweEltYWdlID0gbmV3IF9qcHguSnB4SW1hZ2UoKTsKICAgICAgICBqcHhJbWFnZS5wYXJzZUltYWdlUHJvcGVydGllcyhpbWFnZS5zdHJlYW0pOwogICAgICAgIGltYWdlLnN0cmVhbS5yZXNldCgpOwogICAgICAgIGltYWdlLndpZHRoID0ganB4SW1hZ2Uud2lkdGg7CiAgICAgICAgaW1hZ2UuaGVpZ2h0ID0ganB4SW1hZ2UuaGVpZ2h0OwogICAgICAgIGltYWdlLmJpdHNQZXJDb21wb25lbnQgPSBqcHhJbWFnZS5iaXRzUGVyQ29tcG9uZW50OwogICAgICAgIGltYWdlLm51bUNvbXBzID0ganB4SW1hZ2UuY29tcG9uZW50c0NvdW50OwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJKQklHMkRlY29kZSI6CiAgICAgICAgaW1hZ2UuYml0c1BlckNvbXBvbmVudCA9IDE7CiAgICAgICAgaW1hZ2UubnVtQ29tcHMgPSAxOwogICAgICAgIGJyZWFrOwogICAgfQogICAgbGV0IHdpZHRoID0gZGljdC5nZXQoIlciLCAiV2lkdGgiKTsKICAgIGxldCBoZWlnaHQgPSBkaWN0LmdldCgiSCIsICJIZWlnaHQiKTsKICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKGltYWdlLndpZHRoKSAmJiBpbWFnZS53aWR0aCA+IDAgJiYgTnVtYmVyLmlzSW50ZWdlcihpbWFnZS5oZWlnaHQpICYmIGltYWdlLmhlaWdodCA+IDAgJiYgKGltYWdlLndpZHRoICE9PSB3aWR0aCB8fCBpbWFnZS5oZWlnaHQgIT09IGhlaWdodCkpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKCJQREZJbWFnZSAtIHVzaW5nIHRoZSBXaWR0aC9IZWlnaHQgb2YgdGhlIGltYWdlIGRhdGEsICIgKyAicmF0aGVyIHRoYW4gdGhlIGltYWdlIGRpY3Rpb25hcnkuIik7CiAgICAgIHdpZHRoID0gaW1hZ2Uud2lkdGg7CiAgICAgIGhlaWdodCA9IGltYWdlLmhlaWdodDsKICAgIH0KICAgIGlmICh3aWR0aCA8IDEgfHwgaGVpZ2h0IDwgMSkgewogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYEludmFsaWQgaW1hZ2Ugd2lkdGg6ICR7d2lkdGh9IG9yIGhlaWdodDogJHtoZWlnaHR9YCk7CiAgICB9CiAgICB0aGlzLndpZHRoID0gd2lkdGg7CiAgICB0aGlzLmhlaWdodCA9IGhlaWdodDsKICAgIHRoaXMuaW50ZXJwb2xhdGUgPSBkaWN0LmdldCgiSSIsICJJbnRlcnBvbGF0ZSIpOwogICAgdGhpcy5pbWFnZU1hc2sgPSBkaWN0LmdldCgiSU0iLCAiSW1hZ2VNYXNrIikgfHwgZmFsc2U7CiAgICB0aGlzLm1hdHRlID0gZGljdC5nZXQoIk1hdHRlIikgfHwgZmFsc2U7CiAgICBsZXQgYml0c1BlckNvbXBvbmVudCA9IGltYWdlLmJpdHNQZXJDb21wb25lbnQ7CiAgICBpZiAoIWJpdHNQZXJDb21wb25lbnQpIHsKICAgICAgYml0c1BlckNvbXBvbmVudCA9IGRpY3QuZ2V0KCJCUEMiLCAiQml0c1BlckNvbXBvbmVudCIpOwogICAgICBpZiAoIWJpdHNQZXJDb21wb25lbnQpIHsKICAgICAgICBpZiAodGhpcy5pbWFnZU1hc2spIHsKICAgICAgICAgIGJpdHNQZXJDb21wb25lbnQgPSAxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYEJpdHMgcGVyIGNvbXBvbmVudCBtaXNzaW5nIGluIGltYWdlOiAke3RoaXMuaW1hZ2VNYXNrfWApOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgdGhpcy5icGMgPSBiaXRzUGVyQ29tcG9uZW50OwogICAgaWYgKCF0aGlzLmltYWdlTWFzaykgewogICAgICBsZXQgY29sb3JTcGFjZSA9IGRpY3QuZ2V0UmF3KCJDUyIpIHx8IGRpY3QuZ2V0UmF3KCJDb2xvclNwYWNlIik7CiAgICAgIGlmICghY29sb3JTcGFjZSkgewogICAgICAgICgwLCBfdXRpbC5pbmZvKSgiSlBYIGltYWdlcyAod2hpY2ggZG8gbm90IHJlcXVpcmUgY29sb3Igc3BhY2VzKSIpOwogICAgICAgIHN3aXRjaCAoaW1hZ2UubnVtQ29tcHMpIHsKICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgY29sb3JTcGFjZSA9IF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJEZXZpY2VHcmF5Iik7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAzOgogICAgICAgICAgICBjb2xvclNwYWNlID0gX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIkRldmljZVJHQiIpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgNDoKICAgICAgICAgICAgY29sb3JTcGFjZSA9IF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJEZXZpY2VDTVlLIik7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBKUFggaW1hZ2VzIHdpdGggJHtpbWFnZS5udW1Db21wc30gY29sb3IgY29tcG9uZW50cyBub3Qgc3VwcG9ydGVkLmApOwogICAgICAgIH0KICAgICAgfQogICAgICB0aGlzLmNvbG9yU3BhY2UgPSBfY29sb3JzcGFjZS5Db2xvclNwYWNlLnBhcnNlKHsKICAgICAgICBjczogY29sb3JTcGFjZSwKICAgICAgICB4cmVmLAogICAgICAgIHJlc291cmNlczogaXNJbmxpbmUgPyByZXMgOiBudWxsLAogICAgICAgIHBkZkZ1bmN0aW9uRmFjdG9yeSwKICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgICB9KTsKICAgICAgdGhpcy5udW1Db21wcyA9IHRoaXMuY29sb3JTcGFjZS5udW1Db21wczsKICAgIH0KICAgIHRoaXMuZGVjb2RlID0gZGljdC5nZXRBcnJheSgiRCIsICJEZWNvZGUiKTsKICAgIHRoaXMubmVlZHNEZWNvZGUgPSBmYWxzZTsKICAgIGlmICh0aGlzLmRlY29kZSAmJiAodGhpcy5jb2xvclNwYWNlICYmICF0aGlzLmNvbG9yU3BhY2UuaXNEZWZhdWx0RGVjb2RlKHRoaXMuZGVjb2RlLCBiaXRzUGVyQ29tcG9uZW50KSB8fCBpc01hc2sgJiYgIV9jb2xvcnNwYWNlLkNvbG9yU3BhY2UuaXNEZWZhdWx0RGVjb2RlKHRoaXMuZGVjb2RlLCAxKSkpIHsKICAgICAgdGhpcy5uZWVkc0RlY29kZSA9IHRydWU7CiAgICAgIGNvbnN0IG1heCA9ICgxIDw8IGJpdHNQZXJDb21wb25lbnQpIC0gMTsKICAgICAgdGhpcy5kZWNvZGVDb2VmZmljaWVudHMgPSBbXTsKICAgICAgdGhpcy5kZWNvZGVBZGRlbmRzID0gW107CiAgICAgIGNvbnN0IGlzSW5kZXhlZCA9IHRoaXMuY29sb3JTcGFjZSAmJiB0aGlzLmNvbG9yU3BhY2UubmFtZSA9PT0gIkluZGV4ZWQiOwogICAgICBmb3IgKGxldCBpID0gMCwgaiA9IDA7IGkgPCB0aGlzLmRlY29kZS5sZW5ndGg7IGkgKz0gMiwgKytqKSB7CiAgICAgICAgY29uc3QgZG1pbiA9IHRoaXMuZGVjb2RlW2ldOwogICAgICAgIGNvbnN0IGRtYXggPSB0aGlzLmRlY29kZVtpICsgMV07CiAgICAgICAgdGhpcy5kZWNvZGVDb2VmZmljaWVudHNbal0gPSBpc0luZGV4ZWQgPyAoZG1heCAtIGRtaW4pIC8gbWF4IDogZG1heCAtIGRtaW47CiAgICAgICAgdGhpcy5kZWNvZGVBZGRlbmRzW2pdID0gaXNJbmRleGVkID8gZG1pbiA6IG1heCAqIGRtaW47CiAgICAgIH0KICAgIH0KICAgIGlmIChzbWFzaykgewogICAgICB0aGlzLnNtYXNrID0gbmV3IFBERkltYWdlKHsKICAgICAgICB4cmVmLAogICAgICAgIHJlcywKICAgICAgICBpbWFnZTogc21hc2ssCiAgICAgICAgaXNJbmxpbmUsCiAgICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgICAgIH0pOwogICAgfSBlbHNlIGlmIChtYXNrKSB7CiAgICAgIGlmIChtYXNrIGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0pIHsKICAgICAgICBjb25zdCBtYXNrRGljdCA9IG1hc2suZGljdCwKICAgICAgICAgIGltYWdlTWFzayA9IG1hc2tEaWN0LmdldCgiSU0iLCAiSW1hZ2VNYXNrIik7CiAgICAgICAgaWYgKCFpbWFnZU1hc2spIHsKICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiSWdub3JpbmcgL01hc2sgaW4gaW1hZ2Ugd2l0aG91dCAvSW1hZ2VNYXNrLiIpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLm1hc2sgPSBuZXcgUERGSW1hZ2UoewogICAgICAgICAgICB4cmVmLAogICAgICAgICAgICByZXMsCiAgICAgICAgICAgIGltYWdlOiBtYXNrLAogICAgICAgICAgICBpc0lubGluZSwKICAgICAgICAgICAgaXNNYXNrOiB0cnVlLAogICAgICAgICAgICBwZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgICAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5tYXNrID0gbWFzazsKICAgICAgfQogICAgfQogIH0KICBzdGF0aWMgYXN5bmMgYnVpbGRJbWFnZShfcmVmMikgewogICAgbGV0IHsKICAgICAgeHJlZiwKICAgICAgcmVzLAogICAgICBpbWFnZSwKICAgICAgaXNJbmxpbmUgPSBmYWxzZSwKICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgfSA9IF9yZWYyOwogICAgY29uc3QgaW1hZ2VEYXRhID0gaW1hZ2U7CiAgICBsZXQgc21hc2tEYXRhID0gbnVsbDsKICAgIGxldCBtYXNrRGF0YSA9IG51bGw7CiAgICBjb25zdCBzbWFzayA9IGltYWdlLmRpY3QuZ2V0KCJTTWFzayIpOwogICAgY29uc3QgbWFzayA9IGltYWdlLmRpY3QuZ2V0KCJNYXNrIik7CiAgICBpZiAoc21hc2spIHsKICAgICAgaWYgKHNtYXNrIGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0pIHsKICAgICAgICBzbWFza0RhdGEgPSBzbWFzazsKICAgICAgfSBlbHNlIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoIlVuc3VwcG9ydGVkIC9TTWFzayBmb3JtYXQuIik7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAobWFzaykgewogICAgICBpZiAobWFzayBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtIHx8IEFycmF5LmlzQXJyYXkobWFzaykpIHsKICAgICAgICBtYXNrRGF0YSA9IG1hc2s7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKCJVbnN1cHBvcnRlZCAvTWFzayBmb3JtYXQuIik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBuZXcgUERGSW1hZ2UoewogICAgICB4cmVmLAogICAgICByZXMsCiAgICAgIGltYWdlOiBpbWFnZURhdGEsCiAgICAgIGlzSW5saW5lLAogICAgICBzbWFzazogc21hc2tEYXRhLAogICAgICBtYXNrOiBtYXNrRGF0YSwKICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgfSk7CiAgfQogIHN0YXRpYyBjcmVhdGVSYXdNYXNrKF9yZWYzKSB7CiAgICBsZXQgewogICAgICBpbWdBcnJheSwKICAgICAgd2lkdGgsCiAgICAgIGhlaWdodCwKICAgICAgaW1hZ2VJc0Zyb21EZWNvZGVTdHJlYW0sCiAgICAgIGludmVyc2VEZWNvZGUsCiAgICAgIGludGVycG9sYXRlCiAgICB9ID0gX3JlZjM7CiAgICBjb25zdCBjb21wdXRlZExlbmd0aCA9ICh3aWR0aCArIDcgPj4gMykgKiBoZWlnaHQ7CiAgICBjb25zdCBhY3R1YWxMZW5ndGggPSBpbWdBcnJheS5ieXRlTGVuZ3RoOwogICAgY29uc3QgaGF2ZUZ1bGxEYXRhID0gY29tcHV0ZWRMZW5ndGggPT09IGFjdHVhbExlbmd0aDsKICAgIGxldCBkYXRhLCBpOwogICAgaWYgKGltYWdlSXNGcm9tRGVjb2RlU3RyZWFtICYmICghaW52ZXJzZURlY29kZSB8fCBoYXZlRnVsbERhdGEpKSB7CiAgICAgIGRhdGEgPSBpbWdBcnJheTsKICAgIH0gZWxzZSBpZiAoIWludmVyc2VEZWNvZGUpIHsKICAgICAgZGF0YSA9IG5ldyBVaW50OEFycmF5KGltZ0FycmF5KTsKICAgIH0gZWxzZSB7CiAgICAgIGRhdGEgPSBuZXcgVWludDhBcnJheShjb21wdXRlZExlbmd0aCk7CiAgICAgIGRhdGEuc2V0KGltZ0FycmF5KTsKICAgICAgZGF0YS5maWxsKDB4ZmYsIGFjdHVhbExlbmd0aCk7CiAgICB9CiAgICBpZiAoaW52ZXJzZURlY29kZSkgewogICAgICBmb3IgKGkgPSAwOyBpIDwgYWN0dWFsTGVuZ3RoOyBpKyspIHsKICAgICAgICBkYXRhW2ldIF49IDB4ZmY7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7CiAgICAgIGRhdGEsCiAgICAgIHdpZHRoLAogICAgICBoZWlnaHQsCiAgICAgIGludGVycG9sYXRlCiAgICB9OwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlTWFzayhfcmVmNCkgewogICAgbGV0IHsKICAgICAgaW1nQXJyYXksCiAgICAgIHdpZHRoLAogICAgICBoZWlnaHQsCiAgICAgIGltYWdlSXNGcm9tRGVjb2RlU3RyZWFtLAogICAgICBpbnZlcnNlRGVjb2RlLAogICAgICBpbnRlcnBvbGF0ZSwKICAgICAgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgPSBmYWxzZQogICAgfSA9IF9yZWY0OwogICAgY29uc3QgaXNTaW5nbGVPcGFxdWVQaXhlbCA9IHdpZHRoID09PSAxICYmIGhlaWdodCA9PT0gMSAmJiBpbnZlcnNlRGVjb2RlID09PSAoaW1nQXJyYXkubGVuZ3RoID09PSAwIHx8ICEhKGltZ0FycmF5WzBdICYgMTI4KSk7CiAgICBpZiAoaXNTaW5nbGVPcGFxdWVQaXhlbCkgewogICAgICByZXR1cm4gewogICAgICAgIGlzU2luZ2xlT3BhcXVlUGl4ZWwKICAgICAgfTsKICAgIH0KICAgIGlmIChpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCkgewogICAgICBpZiAoX2ltYWdlX3Jlc2l6ZXIuSW1hZ2VSZXNpemVyLm5lZWRzVG9CZVJlc2l6ZWQod2lkdGgsIGhlaWdodCkpIHsKICAgICAgICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHdpZHRoICogaGVpZ2h0ICogNCk7CiAgICAgICAgKDAsIF9pbWFnZV91dGlscy5jb252ZXJ0QmxhY2tBbmRXaGl0ZVRvUkdCQSkoewogICAgICAgICAgc3JjOiBpbWdBcnJheSwKICAgICAgICAgIGRlc3Q6IGRhdGEsCiAgICAgICAgICB3aWR0aCwKICAgICAgICAgIGhlaWdodCwKICAgICAgICAgIG5vbkJsYWNrQ29sb3I6IDAsCiAgICAgICAgICBpbnZlcnNlRGVjb2RlCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIF9pbWFnZV9yZXNpemVyLkltYWdlUmVzaXplci5jcmVhdGVJbWFnZSh7CiAgICAgICAgICBraW5kOiBfdXRpbC5JbWFnZUtpbmQuUkdCQV8zMkJQUCwKICAgICAgICAgIGRhdGEsCiAgICAgICAgICB3aWR0aCwKICAgICAgICAgIGhlaWdodCwKICAgICAgICAgIGludGVycG9sYXRlCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgY29uc3QgY2FudmFzID0gbmV3IE9mZnNjcmVlbkNhbnZhcyh3aWR0aCwgaGVpZ2h0KTsKICAgICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgICAgIGNvbnN0IGltZ0RhdGEgPSBjdHguY3JlYXRlSW1hZ2VEYXRhKHdpZHRoLCBoZWlnaHQpOwogICAgICAoMCwgX2ltYWdlX3V0aWxzLmNvbnZlcnRCbGFja0FuZFdoaXRlVG9SR0JBKSh7CiAgICAgICAgc3JjOiBpbWdBcnJheSwKICAgICAgICBkZXN0OiBpbWdEYXRhLmRhdGEsCiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0LAogICAgICAgIG5vbkJsYWNrQ29sb3I6IDAsCiAgICAgICAgaW52ZXJzZURlY29kZQogICAgICB9KTsKICAgICAgY3R4LnB1dEltYWdlRGF0YShpbWdEYXRhLCAwLCAwKTsKICAgICAgY29uc3QgYml0bWFwID0gY2FudmFzLnRyYW5zZmVyVG9JbWFnZUJpdG1hcCgpOwogICAgICByZXR1cm4gewogICAgICAgIGRhdGE6IG51bGwsCiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0LAogICAgICAgIGludGVycG9sYXRlLAogICAgICAgIGJpdG1hcAogICAgICB9OwogICAgfQogICAgcmV0dXJuIHRoaXMuY3JlYXRlUmF3TWFzayh7CiAgICAgIGltZ0FycmF5LAogICAgICB3aWR0aCwKICAgICAgaGVpZ2h0LAogICAgICBpbnZlcnNlRGVjb2RlLAogICAgICBpbWFnZUlzRnJvbURlY29kZVN0cmVhbSwKICAgICAgaW50ZXJwb2xhdGUKICAgIH0pOwogIH0KICBnZXQgZHJhd1dpZHRoKCkgewogICAgcmV0dXJuIE1hdGgubWF4KHRoaXMud2lkdGgsIHRoaXMuc21hc2sgJiYgdGhpcy5zbWFzay53aWR0aCB8fCAwLCB0aGlzLm1hc2sgJiYgdGhpcy5tYXNrLndpZHRoIHx8IDApOwogIH0KICBnZXQgZHJhd0hlaWdodCgpIHsKICAgIHJldHVybiBNYXRoLm1heCh0aGlzLmhlaWdodCwgdGhpcy5zbWFzayAmJiB0aGlzLnNtYXNrLmhlaWdodCB8fCAwLCB0aGlzLm1hc2sgJiYgdGhpcy5tYXNrLmhlaWdodCB8fCAwKTsKICB9CiAgZGVjb2RlQnVmZmVyKGJ1ZmZlcikgewogICAgY29uc3QgYnBjID0gdGhpcy5icGM7CiAgICBjb25zdCBudW1Db21wcyA9IHRoaXMubnVtQ29tcHM7CiAgICBjb25zdCBkZWNvZGVBZGRlbmRzID0gdGhpcy5kZWNvZGVBZGRlbmRzOwogICAgY29uc3QgZGVjb2RlQ29lZmZpY2llbnRzID0gdGhpcy5kZWNvZGVDb2VmZmljaWVudHM7CiAgICBjb25zdCBtYXggPSAoMSA8PCBicGMpIC0gMTsKICAgIGxldCBpLCBpaTsKICAgIGlmIChicGMgPT09IDEpIHsKICAgICAgZm9yIChpID0gMCwgaWkgPSBidWZmZXIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGJ1ZmZlcltpXSA9ICshYnVmZmVyW2ldOwogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KICAgIGxldCBpbmRleCA9IDA7CiAgICBmb3IgKGkgPSAwLCBpaSA9IHRoaXMud2lkdGggKiB0aGlzLmhlaWdodDsgaSA8IGlpOyBpKyspIHsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBudW1Db21wczsgaisrKSB7CiAgICAgICAgYnVmZmVyW2luZGV4XSA9IGRlY29kZUFuZENsYW1wKGJ1ZmZlcltpbmRleF0sIGRlY29kZUFkZGVuZHNbal0sIGRlY29kZUNvZWZmaWNpZW50c1tqXSwgbWF4KTsKICAgICAgICBpbmRleCsrOwogICAgICB9CiAgICB9CiAgfQogIGdldENvbXBvbmVudHMoYnVmZmVyKSB7CiAgICBjb25zdCBicGMgPSB0aGlzLmJwYzsKICAgIGlmIChicGMgPT09IDgpIHsKICAgICAgcmV0dXJuIGJ1ZmZlcjsKICAgIH0KICAgIGNvbnN0IHdpZHRoID0gdGhpcy53aWR0aDsKICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuaGVpZ2h0OwogICAgY29uc3QgbnVtQ29tcHMgPSB0aGlzLm51bUNvbXBzOwogICAgY29uc3QgbGVuZ3RoID0gd2lkdGggKiBoZWlnaHQgKiBudW1Db21wczsKICAgIGxldCBidWZmZXJQb3MgPSAwOwogICAgbGV0IG91dHB1dDsKICAgIGlmIChicGMgPD0gOCkgewogICAgICBvdXRwdXQgPSBuZXcgVWludDhBcnJheShsZW5ndGgpOwogICAgfSBlbHNlIGlmIChicGMgPD0gMTYpIHsKICAgICAgb3V0cHV0ID0gbmV3IFVpbnQxNkFycmF5KGxlbmd0aCk7CiAgICB9IGVsc2UgewogICAgICBvdXRwdXQgPSBuZXcgVWludDMyQXJyYXkobGVuZ3RoKTsKICAgIH0KICAgIGNvbnN0IHJvd0NvbXBzID0gd2lkdGggKiBudW1Db21wczsKICAgIGNvbnN0IG1heCA9ICgxIDw8IGJwYykgLSAxOwogICAgbGV0IGkgPSAwLAogICAgICBpaSwKICAgICAgYnVmOwogICAgaWYgKGJwYyA9PT0gMSkgewogICAgICBsZXQgbWFzaywgbG9vcDFFbmQsIGxvb3AyRW5kOwogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGhlaWdodDsgaisrKSB7CiAgICAgICAgbG9vcDFFbmQgPSBpICsgKHJvd0NvbXBzICYgfjcpOwogICAgICAgIGxvb3AyRW5kID0gaSArIHJvd0NvbXBzOwogICAgICAgIHdoaWxlIChpIDwgbG9vcDFFbmQpIHsKICAgICAgICAgIGJ1ZiA9IGJ1ZmZlcltidWZmZXJQb3MrK107CiAgICAgICAgICBvdXRwdXRbaV0gPSBidWYgPj4gNyAmIDE7CiAgICAgICAgICBvdXRwdXRbaSArIDFdID0gYnVmID4+IDYgJiAxOwogICAgICAgICAgb3V0cHV0W2kgKyAyXSA9IGJ1ZiA+PiA1ICYgMTsKICAgICAgICAgIG91dHB1dFtpICsgM10gPSBidWYgPj4gNCAmIDE7CiAgICAgICAgICBvdXRwdXRbaSArIDRdID0gYnVmID4+IDMgJiAxOwogICAgICAgICAgb3V0cHV0W2kgKyA1XSA9IGJ1ZiA+PiAyICYgMTsKICAgICAgICAgIG91dHB1dFtpICsgNl0gPSBidWYgPj4gMSAmIDE7CiAgICAgICAgICBvdXRwdXRbaSArIDddID0gYnVmICYgMTsKICAgICAgICAgIGkgKz0gODsKICAgICAgICB9CiAgICAgICAgaWYgKGkgPCBsb29wMkVuZCkgewogICAgICAgICAgYnVmID0gYnVmZmVyW2J1ZmZlclBvcysrXTsKICAgICAgICAgIG1hc2sgPSAxMjg7CiAgICAgICAgICB3aGlsZSAoaSA8IGxvb3AyRW5kKSB7CiAgICAgICAgICAgIG91dHB1dFtpKytdID0gKyEhKGJ1ZiAmIG1hc2spOwogICAgICAgICAgICBtYXNrID4+PSAxOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgbGV0IGJpdHMgPSAwOwogICAgICBidWYgPSAwOwogICAgICBmb3IgKGkgPSAwLCBpaSA9IGxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgICAgICBpZiAoaSAlIHJvd0NvbXBzID09PSAwKSB7CiAgICAgICAgICBidWYgPSAwOwogICAgICAgICAgYml0cyA9IDA7CiAgICAgICAgfQogICAgICAgIHdoaWxlIChiaXRzIDwgYnBjKSB7CiAgICAgICAgICBidWYgPSBidWYgPDwgOCB8IGJ1ZmZlcltidWZmZXJQb3MrK107CiAgICAgICAgICBiaXRzICs9IDg7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHJlbWFpbmluZ0JpdHMgPSBiaXRzIC0gYnBjOwogICAgICAgIGxldCB2YWx1ZSA9IGJ1ZiA+PiByZW1haW5pbmdCaXRzOwogICAgICAgIGlmICh2YWx1ZSA8IDApIHsKICAgICAgICAgIHZhbHVlID0gMDsKICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID4gbWF4KSB7CiAgICAgICAgICB2YWx1ZSA9IG1heDsKICAgICAgICB9CiAgICAgICAgb3V0cHV0W2ldID0gdmFsdWU7CiAgICAgICAgYnVmICY9ICgxIDw8IHJlbWFpbmluZ0JpdHMpIC0gMTsKICAgICAgICBiaXRzID0gcmVtYWluaW5nQml0czsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG91dHB1dDsKICB9CiAgZmlsbE9wYWNpdHkocmdiYUJ1Ziwgd2lkdGgsIGhlaWdodCwgYWN0dWFsSGVpZ2h0LCBpbWFnZSkgewogICAgY29uc3Qgc21hc2sgPSB0aGlzLnNtYXNrOwogICAgY29uc3QgbWFzayA9IHRoaXMubWFzazsKICAgIGxldCBhbHBoYUJ1Ziwgc3csIHNoLCBpLCBpaSwgajsKICAgIGlmIChzbWFzaykgewogICAgICBzdyA9IHNtYXNrLndpZHRoOwogICAgICBzaCA9IHNtYXNrLmhlaWdodDsKICAgICAgYWxwaGFCdWYgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoc3cgKiBzaCk7CiAgICAgIHNtYXNrLmZpbGxHcmF5QnVmZmVyKGFscGhhQnVmKTsKICAgICAgaWYgKHN3ICE9PSB3aWR0aCB8fCBzaCAhPT0gaGVpZ2h0KSB7CiAgICAgICAgYWxwaGFCdWYgPSByZXNpemVJbWFnZU1hc2soYWxwaGFCdWYsIHNtYXNrLmJwYywgc3csIHNoLCB3aWR0aCwgaGVpZ2h0KTsKICAgICAgfQogICAgfSBlbHNlIGlmIChtYXNrKSB7CiAgICAgIGlmIChtYXNrIGluc3RhbmNlb2YgUERGSW1hZ2UpIHsKICAgICAgICBzdyA9IG1hc2sud2lkdGg7CiAgICAgICAgc2ggPSBtYXNrLmhlaWdodDsKICAgICAgICBhbHBoYUJ1ZiA9IG5ldyBVaW50OENsYW1wZWRBcnJheShzdyAqIHNoKTsKICAgICAgICBtYXNrLm51bUNvbXBzID0gMTsKICAgICAgICBtYXNrLmZpbGxHcmF5QnVmZmVyKGFscGhhQnVmKTsKICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IHN3ICogc2g7IGkgPCBpaTsgKytpKSB7CiAgICAgICAgICBhbHBoYUJ1ZltpXSA9IDI1NSAtIGFscGhhQnVmW2ldOwogICAgICAgIH0KICAgICAgICBpZiAoc3cgIT09IHdpZHRoIHx8IHNoICE9PSBoZWlnaHQpIHsKICAgICAgICAgIGFscGhhQnVmID0gcmVzaXplSW1hZ2VNYXNrKGFscGhhQnVmLCBtYXNrLmJwYywgc3csIHNoLCB3aWR0aCwgaGVpZ2h0KTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShtYXNrKSkgewogICAgICAgIGFscGhhQnVmID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHdpZHRoICogaGVpZ2h0KTsKICAgICAgICBjb25zdCBudW1Db21wcyA9IHRoaXMubnVtQ29tcHM7CiAgICAgICAgZm9yIChpID0gMCwgaWkgPSB3aWR0aCAqIGhlaWdodDsgaSA8IGlpOyArK2kpIHsKICAgICAgICAgIGxldCBvcGFjaXR5ID0gMDsKICAgICAgICAgIGNvbnN0IGltYWdlT2Zmc2V0ID0gaSAqIG51bUNvbXBzOwogICAgICAgICAgZm9yIChqID0gMDsgaiA8IG51bUNvbXBzOyArK2opIHsKICAgICAgICAgICAgY29uc3QgY29sb3IgPSBpbWFnZVtpbWFnZU9mZnNldCArIGpdOwogICAgICAgICAgICBjb25zdCBtYXNrT2Zmc2V0ID0gaiAqIDI7CiAgICAgICAgICAgIGlmIChjb2xvciA8IG1hc2tbbWFza09mZnNldF0gfHwgY29sb3IgPiBtYXNrW21hc2tPZmZzZXQgKyAxXSkgewogICAgICAgICAgICAgIG9wYWNpdHkgPSAyNTU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGFscGhhQnVmW2ldID0gb3BhY2l0eTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJVbmtub3duIG1hc2sgZm9ybWF0LiIpOwogICAgICB9CiAgICB9CiAgICBpZiAoYWxwaGFCdWYpIHsKICAgICAgZm9yIChpID0gMCwgaiA9IDMsIGlpID0gd2lkdGggKiBhY3R1YWxIZWlnaHQ7IGkgPCBpaTsgKytpLCBqICs9IDQpIHsKICAgICAgICByZ2JhQnVmW2pdID0gYWxwaGFCdWZbaV07CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGZvciAoaSA9IDAsIGogPSAzLCBpaSA9IHdpZHRoICogYWN0dWFsSGVpZ2h0OyBpIDwgaWk7ICsraSwgaiArPSA0KSB7CiAgICAgICAgcmdiYUJ1ZltqXSA9IDI1NTsKICAgICAgfQogICAgfQogIH0KICB1bmRvUHJlYmxlbmQoYnVmZmVyLCB3aWR0aCwgaGVpZ2h0KSB7CiAgICBjb25zdCBtYXR0ZSA9IHRoaXMuc21hc2sgJiYgdGhpcy5zbWFzay5tYXR0ZTsKICAgIGlmICghbWF0dGUpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgbWF0dGVSZ2IgPSB0aGlzLmNvbG9yU3BhY2UuZ2V0UmdiKG1hdHRlLCAwKTsKICAgIGNvbnN0IG1hdHRlUiA9IG1hdHRlUmdiWzBdOwogICAgY29uc3QgbWF0dGVHID0gbWF0dGVSZ2JbMV07CiAgICBjb25zdCBtYXR0ZUIgPSBtYXR0ZVJnYlsyXTsKICAgIGNvbnN0IGxlbmd0aCA9IHdpZHRoICogaGVpZ2h0ICogNDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDQpIHsKICAgICAgY29uc3QgYWxwaGEgPSBidWZmZXJbaSArIDNdOwogICAgICBpZiAoYWxwaGEgPT09IDApIHsKICAgICAgICBidWZmZXJbaV0gPSAyNTU7CiAgICAgICAgYnVmZmVyW2kgKyAxXSA9IDI1NTsKICAgICAgICBidWZmZXJbaSArIDJdID0gMjU1OwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGsgPSAyNTUgLyBhbHBoYTsKICAgICAgYnVmZmVyW2ldID0gKGJ1ZmZlcltpXSAtIG1hdHRlUikgKiBrICsgbWF0dGVSOwogICAgICBidWZmZXJbaSArIDFdID0gKGJ1ZmZlcltpICsgMV0gLSBtYXR0ZUcpICogayArIG1hdHRlRzsKICAgICAgYnVmZmVyW2kgKyAyXSA9IChidWZmZXJbaSArIDJdIC0gbWF0dGVCKSAqIGsgKyBtYXR0ZUI7CiAgICB9CiAgfQogIGFzeW5jIGNyZWF0ZUltYWdlRGF0YSgpIHsKICAgIGxldCBmb3JjZVJHQkEgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgbGV0IGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBmYWxzZTsKICAgIGNvbnN0IGRyYXdXaWR0aCA9IHRoaXMuZHJhd1dpZHRoOwogICAgY29uc3QgZHJhd0hlaWdodCA9IHRoaXMuZHJhd0hlaWdodDsKICAgIGNvbnN0IGltZ0RhdGEgPSB7CiAgICAgIHdpZHRoOiBkcmF3V2lkdGgsCiAgICAgIGhlaWdodDogZHJhd0hlaWdodCwKICAgICAgaW50ZXJwb2xhdGU6IHRoaXMuaW50ZXJwb2xhdGUsCiAgICAgIGtpbmQ6IDAsCiAgICAgIGRhdGE6IG51bGwKICAgIH07CiAgICBjb25zdCBudW1Db21wcyA9IHRoaXMubnVtQ29tcHM7CiAgICBjb25zdCBvcmlnaW5hbFdpZHRoID0gdGhpcy53aWR0aDsKICAgIGNvbnN0IG9yaWdpbmFsSGVpZ2h0ID0gdGhpcy5oZWlnaHQ7CiAgICBjb25zdCBicGMgPSB0aGlzLmJwYzsKICAgIGNvbnN0IHJvd0J5dGVzID0gb3JpZ2luYWxXaWR0aCAqIG51bUNvbXBzICogYnBjICsgNyA+PiAzOwogICAgY29uc3QgbXVzdEJlUmVzaXplZCA9IGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkICYmIF9pbWFnZV9yZXNpemVyLkltYWdlUmVzaXplci5uZWVkc1RvQmVSZXNpemVkKGRyYXdXaWR0aCwgZHJhd0hlaWdodCk7CiAgICBpZiAoIWZvcmNlUkdCQSkgewogICAgICBsZXQga2luZDsKICAgICAgaWYgKHRoaXMuY29sb3JTcGFjZS5uYW1lID09PSAiRGV2aWNlR3JheSIgJiYgYnBjID09PSAxKSB7CiAgICAgICAga2luZCA9IF91dGlsLkltYWdlS2luZC5HUkFZU0NBTEVfMUJQUDsKICAgICAgfSBlbHNlIGlmICh0aGlzLmNvbG9yU3BhY2UubmFtZSA9PT0gIkRldmljZVJHQiIgJiYgYnBjID09PSA4ICYmICF0aGlzLm5lZWRzRGVjb2RlKSB7CiAgICAgICAga2luZCA9IF91dGlsLkltYWdlS2luZC5SR0JfMjRCUFA7CiAgICAgIH0KICAgICAgaWYgKGtpbmQgJiYgIXRoaXMuc21hc2sgJiYgIXRoaXMubWFzayAmJiBkcmF3V2lkdGggPT09IG9yaWdpbmFsV2lkdGggJiYgZHJhd0hlaWdodCA9PT0gb3JpZ2luYWxIZWlnaHQpIHsKICAgICAgICBjb25zdCBkYXRhID0gdGhpcy5nZXRJbWFnZUJ5dGVzKG9yaWdpbmFsSGVpZ2h0ICogcm93Qnl0ZXMsIHt9KTsKICAgICAgICBpZiAoaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpIHsKICAgICAgICAgIGlmIChtdXN0QmVSZXNpemVkKSB7CiAgICAgICAgICAgIHJldHVybiBfaW1hZ2VfcmVzaXplci5JbWFnZVJlc2l6ZXIuY3JlYXRlSW1hZ2UoewogICAgICAgICAgICAgIGRhdGEsCiAgICAgICAgICAgICAga2luZCwKICAgICAgICAgICAgICB3aWR0aDogZHJhd1dpZHRoLAogICAgICAgICAgICAgIGhlaWdodDogZHJhd0hlaWdodCwKICAgICAgICAgICAgICBpbnRlcnBvbGF0ZTogdGhpcy5pbnRlcnBvbGF0ZQogICAgICAgICAgICB9LCB0aGlzLm5lZWRzRGVjb2RlKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUJpdG1hcChraW5kLCBvcmlnaW5hbFdpZHRoLCBvcmlnaW5hbEhlaWdodCwgZGF0YSk7CiAgICAgICAgfQogICAgICAgIGltZ0RhdGEua2luZCA9IGtpbmQ7CiAgICAgICAgaW1nRGF0YS5kYXRhID0gZGF0YTsKICAgICAgICBpZiAodGhpcy5uZWVkc0RlY29kZSkgewogICAgICAgICAgKDAsIF91dGlsLmFzc2VydCkoa2luZCA9PT0gX3V0aWwuSW1hZ2VLaW5kLkdSQVlTQ0FMRV8xQlBQLCAiUERGSW1hZ2UuY3JlYXRlSW1hZ2VEYXRhOiBUaGUgaW1hZ2UgbXVzdCBiZSBncmF5c2NhbGUuIik7CiAgICAgICAgICBjb25zdCBidWZmZXIgPSBpbWdEYXRhLmRhdGE7CiAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBidWZmZXIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgICBidWZmZXJbaV0gXj0gMHhmZjsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGltZ0RhdGE7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuaW1hZ2UgaW5zdGFuY2VvZiBfanBlZ19zdHJlYW0uSnBlZ1N0cmVhbSAmJiAhdGhpcy5zbWFzayAmJiAhdGhpcy5tYXNrKSB7CiAgICAgICAgbGV0IGltYWdlTGVuZ3RoID0gb3JpZ2luYWxIZWlnaHQgKiByb3dCeXRlczsKICAgICAgICBpZiAoaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgJiYgIW11c3RCZVJlc2l6ZWQpIHsKICAgICAgICAgIGxldCBpc0hhbmRsZWQgPSBmYWxzZTsKICAgICAgICAgIHN3aXRjaCAodGhpcy5jb2xvclNwYWNlLm5hbWUpIHsKICAgICAgICAgICAgY2FzZSAiRGV2aWNlR3JheSI6CiAgICAgICAgICAgICAgaW1hZ2VMZW5ndGggKj0gNDsKICAgICAgICAgICAgICBpc0hhbmRsZWQgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJEZXZpY2VSR0IiOgogICAgICAgICAgICAgIGltYWdlTGVuZ3RoID0gaW1hZ2VMZW5ndGggLyAzICogNDsKICAgICAgICAgICAgICBpc0hhbmRsZWQgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlICJEZXZpY2VDTVlLIjoKICAgICAgICAgICAgICBpc0hhbmRsZWQgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGlzSGFuZGxlZCkgewogICAgICAgICAgICBjb25zdCByZ2JhID0gdGhpcy5nZXRJbWFnZUJ5dGVzKGltYWdlTGVuZ3RoLCB7CiAgICAgICAgICAgICAgZHJhd1dpZHRoLAogICAgICAgICAgICAgIGRyYXdIZWlnaHQsCiAgICAgICAgICAgICAgZm9yY2VSR0JBOiB0cnVlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVCaXRtYXAoX3V0aWwuSW1hZ2VLaW5kLlJHQkFfMzJCUFAsIGRyYXdXaWR0aCwgZHJhd0hlaWdodCwgcmdiYSk7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN3aXRjaCAodGhpcy5jb2xvclNwYWNlLm5hbWUpIHsKICAgICAgICAgICAgY2FzZSAiRGV2aWNlR3JheSI6CiAgICAgICAgICAgICAgaW1hZ2VMZW5ndGggKj0gMzsKICAgICAgICAgICAgY2FzZSAiRGV2aWNlUkdCIjoKICAgICAgICAgICAgY2FzZSAiRGV2aWNlQ01ZSyI6CiAgICAgICAgICAgICAgaW1nRGF0YS5raW5kID0gX3V0aWwuSW1hZ2VLaW5kLlJHQl8yNEJQUDsKICAgICAgICAgICAgICBpbWdEYXRhLmRhdGEgPSB0aGlzLmdldEltYWdlQnl0ZXMoaW1hZ2VMZW5ndGgsIHsKICAgICAgICAgICAgICAgIGRyYXdXaWR0aCwKICAgICAgICAgICAgICAgIGRyYXdIZWlnaHQsCiAgICAgICAgICAgICAgICBmb3JjZVJHQjogdHJ1ZQogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgIGlmIChtdXN0QmVSZXNpemVkKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gX2ltYWdlX3Jlc2l6ZXIuSW1hZ2VSZXNpemVyLmNyZWF0ZUltYWdlKGltZ0RhdGEpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICByZXR1cm4gaW1nRGF0YTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGltZ0FycmF5ID0gdGhpcy5nZXRJbWFnZUJ5dGVzKG9yaWdpbmFsSGVpZ2h0ICogcm93Qnl0ZXMsIHsKICAgICAgaW50ZXJuYWw6IHRydWUKICAgIH0pOwogICAgY29uc3QgYWN0dWFsSGVpZ2h0ID0gMCB8IGltZ0FycmF5Lmxlbmd0aCAvIHJvd0J5dGVzICogZHJhd0hlaWdodCAvIG9yaWdpbmFsSGVpZ2h0OwogICAgY29uc3QgY29tcHMgPSB0aGlzLmdldENvbXBvbmVudHMoaW1nQXJyYXkpOwogICAgbGV0IGFscGhhMDEsIG1heWJlVW5kb1ByZWJsZW5kOwogICAgbGV0IGNhbnZhcywgY3R4LCBjYW52YXNJbWdEYXRhLCBkYXRhOwogICAgaWYgKGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkICYmICFtdXN0QmVSZXNpemVkKSB7CiAgICAgIGNhbnZhcyA9IG5ldyBPZmZzY3JlZW5DYW52YXMoZHJhd1dpZHRoLCBkcmF3SGVpZ2h0KTsKICAgICAgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgICAgIGNhbnZhc0ltZ0RhdGEgPSBjdHguY3JlYXRlSW1hZ2VEYXRhKGRyYXdXaWR0aCwgZHJhd0hlaWdodCk7CiAgICAgIGRhdGEgPSBjYW52YXNJbWdEYXRhLmRhdGE7CiAgICB9CiAgICBpbWdEYXRhLmtpbmQgPSBfdXRpbC5JbWFnZUtpbmQuUkdCQV8zMkJQUDsKICAgIGlmICghZm9yY2VSR0JBICYmICF0aGlzLnNtYXNrICYmICF0aGlzLm1hc2spIHsKICAgICAgaWYgKCFpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCB8fCBtdXN0QmVSZXNpemVkKSB7CiAgICAgICAgaW1nRGF0YS5raW5kID0gX3V0aWwuSW1hZ2VLaW5kLlJHQl8yNEJQUDsKICAgICAgICBkYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGRyYXdXaWR0aCAqIGRyYXdIZWlnaHQgKiAzKTsKICAgICAgICBhbHBoYTAxID0gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBhcnIgPSBuZXcgVWludDMyQXJyYXkoZGF0YS5idWZmZXIpOwogICAgICAgIGFyci5maWxsKF91dGlsLkZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuID8gMHhmZjAwMDAwMCA6IDB4MDAwMDAwZmYpOwogICAgICAgIGFscGhhMDEgPSAxOwogICAgICB9CiAgICAgIG1heWJlVW5kb1ByZWJsZW5kID0gZmFsc2U7CiAgICB9IGVsc2UgewogICAgICBpZiAoIWlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkIHx8IG11c3RCZVJlc2l6ZWQpIHsKICAgICAgICBkYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGRyYXdXaWR0aCAqIGRyYXdIZWlnaHQgKiA0KTsKICAgICAgfQogICAgICBhbHBoYTAxID0gMTsKICAgICAgbWF5YmVVbmRvUHJlYmxlbmQgPSB0cnVlOwogICAgICB0aGlzLmZpbGxPcGFjaXR5KGRhdGEsIGRyYXdXaWR0aCwgZHJhd0hlaWdodCwgYWN0dWFsSGVpZ2h0LCBjb21wcyk7CiAgICB9CiAgICBpZiAodGhpcy5uZWVkc0RlY29kZSkgewogICAgICB0aGlzLmRlY29kZUJ1ZmZlcihjb21wcyk7CiAgICB9CiAgICB0aGlzLmNvbG9yU3BhY2UuZmlsbFJnYihkYXRhLCBvcmlnaW5hbFdpZHRoLCBvcmlnaW5hbEhlaWdodCwgZHJhd1dpZHRoLCBkcmF3SGVpZ2h0LCBhY3R1YWxIZWlnaHQsIGJwYywgY29tcHMsIGFscGhhMDEpOwogICAgaWYgKG1heWJlVW5kb1ByZWJsZW5kKSB7CiAgICAgIHRoaXMudW5kb1ByZWJsZW5kKGRhdGEsIGRyYXdXaWR0aCwgYWN0dWFsSGVpZ2h0KTsKICAgIH0KICAgIGlmIChpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCAmJiAhbXVzdEJlUmVzaXplZCkgewogICAgICBjdHgucHV0SW1hZ2VEYXRhKGNhbnZhc0ltZ0RhdGEsIDAsIDApOwogICAgICBjb25zdCBiaXRtYXAgPSBjYW52YXMudHJhbnNmZXJUb0ltYWdlQml0bWFwKCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgZGF0YTogbnVsbCwKICAgICAgICB3aWR0aDogZHJhd1dpZHRoLAogICAgICAgIGhlaWdodDogZHJhd0hlaWdodCwKICAgICAgICBiaXRtYXAsCiAgICAgICAgaW50ZXJwb2xhdGU6IHRoaXMuaW50ZXJwb2xhdGUKICAgICAgfTsKICAgIH0KICAgIGltZ0RhdGEuZGF0YSA9IGRhdGE7CiAgICBpZiAobXVzdEJlUmVzaXplZCkgewogICAgICByZXR1cm4gX2ltYWdlX3Jlc2l6ZXIuSW1hZ2VSZXNpemVyLmNyZWF0ZUltYWdlKGltZ0RhdGEpOwogICAgfQogICAgcmV0dXJuIGltZ0RhdGE7CiAgfQogIGZpbGxHcmF5QnVmZmVyKGJ1ZmZlcikgewogICAgY29uc3QgbnVtQ29tcHMgPSB0aGlzLm51bUNvbXBzOwogICAgaWYgKG51bUNvbXBzICE9PSAxKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgUmVhZGluZyBncmF5IHNjYWxlIGZyb20gYSBjb2xvciBpbWFnZTogJHtudW1Db21wc31gKTsKICAgIH0KICAgIGNvbnN0IHdpZHRoID0gdGhpcy53aWR0aDsKICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuaGVpZ2h0OwogICAgY29uc3QgYnBjID0gdGhpcy5icGM7CiAgICBjb25zdCByb3dCeXRlcyA9IHdpZHRoICogbnVtQ29tcHMgKiBicGMgKyA3ID4+IDM7CiAgICBjb25zdCBpbWdBcnJheSA9IHRoaXMuZ2V0SW1hZ2VCeXRlcyhoZWlnaHQgKiByb3dCeXRlcywgewogICAgICBpbnRlcm5hbDogdHJ1ZQogICAgfSk7CiAgICBjb25zdCBjb21wcyA9IHRoaXMuZ2V0Q29tcG9uZW50cyhpbWdBcnJheSk7CiAgICBsZXQgaSwgbGVuZ3RoOwogICAgaWYgKGJwYyA9PT0gMSkgewogICAgICBsZW5ndGggPSB3aWR0aCAqIGhlaWdodDsKICAgICAgaWYgKHRoaXMubmVlZHNEZWNvZGUpIHsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgIGJ1ZmZlcltpXSA9IGNvbXBzW2ldIC0gMSAmIDI1NTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICBidWZmZXJbaV0gPSAtY29tcHNbaV0gJiAyNTU7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0aGlzLm5lZWRzRGVjb2RlKSB7CiAgICAgIHRoaXMuZGVjb2RlQnVmZmVyKGNvbXBzKTsKICAgIH0KICAgIGxlbmd0aCA9IHdpZHRoICogaGVpZ2h0OwogICAgY29uc3Qgc2NhbGUgPSAyNTUgLyAoKDEgPDwgYnBjKSAtIDEpOwogICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgIGJ1ZmZlcltpXSA9IHNjYWxlICogY29tcHNbaV07CiAgICB9CiAgfQogIGNyZWF0ZUJpdG1hcChraW5kLCB3aWR0aCwgaGVpZ2h0LCBzcmMpIHsKICAgIGNvbnN0IGNhbnZhcyA9IG5ldyBPZmZzY3JlZW5DYW52YXMod2lkdGgsIGhlaWdodCk7CiAgICBjb25zdCBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgiMmQiKTsKICAgIGxldCBpbWdEYXRhOwogICAgaWYgKGtpbmQgPT09IF91dGlsLkltYWdlS2luZC5SR0JBXzMyQlBQKSB7CiAgICAgIGltZ0RhdGEgPSBuZXcgSW1hZ2VEYXRhKHNyYywgd2lkdGgsIGhlaWdodCk7CiAgICB9IGVsc2UgewogICAgICBpbWdEYXRhID0gY3R4LmNyZWF0ZUltYWdlRGF0YSh3aWR0aCwgaGVpZ2h0KTsKICAgICAgKDAsIF9pbWFnZV91dGlscy5jb252ZXJ0VG9SR0JBKSh7CiAgICAgICAga2luZCwKICAgICAgICBzcmMsCiAgICAgICAgZGVzdDogbmV3IFVpbnQzMkFycmF5KGltZ0RhdGEuZGF0YS5idWZmZXIpLAogICAgICAgIHdpZHRoLAogICAgICAgIGhlaWdodCwKICAgICAgICBpbnZlcnNlRGVjb2RlOiB0aGlzLm5lZWRzRGVjb2RlCiAgICAgIH0pOwogICAgfQogICAgY3R4LnB1dEltYWdlRGF0YShpbWdEYXRhLCAwLCAwKTsKICAgIGNvbnN0IGJpdG1hcCA9IGNhbnZhcy50cmFuc2ZlclRvSW1hZ2VCaXRtYXAoKTsKICAgIHJldHVybiB7CiAgICAgIGRhdGE6IG51bGwsCiAgICAgIHdpZHRoLAogICAgICBoZWlnaHQsCiAgICAgIGJpdG1hcCwKICAgICAgaW50ZXJwb2xhdGU6IHRoaXMuaW50ZXJwb2xhdGUKICAgIH07CiAgfQogIGdldEltYWdlQnl0ZXMobGVuZ3RoLCBfcmVmNSkgewogICAgbGV0IHsKICAgICAgZHJhd1dpZHRoLAogICAgICBkcmF3SGVpZ2h0LAogICAgICBmb3JjZVJHQkEgPSBmYWxzZSwKICAgICAgZm9yY2VSR0IgPSBmYWxzZSwKICAgICAgaW50ZXJuYWwgPSBmYWxzZQogICAgfSA9IF9yZWY1OwogICAgdGhpcy5pbWFnZS5yZXNldCgpOwogICAgdGhpcy5pbWFnZS5kcmF3V2lkdGggPSBkcmF3V2lkdGggfHwgdGhpcy53aWR0aDsKICAgIHRoaXMuaW1hZ2UuZHJhd0hlaWdodCA9IGRyYXdIZWlnaHQgfHwgdGhpcy5oZWlnaHQ7CiAgICB0aGlzLmltYWdlLmZvcmNlUkdCQSA9ICEhZm9yY2VSR0JBOwogICAgdGhpcy5pbWFnZS5mb3JjZVJHQiA9ICEhZm9yY2VSR0I7CiAgICBjb25zdCBpbWFnZUJ5dGVzID0gdGhpcy5pbWFnZS5nZXRCeXRlcyhsZW5ndGgpOwogICAgaWYgKGludGVybmFsIHx8IHRoaXMuaW1hZ2UgaW5zdGFuY2VvZiBfZGVjb2RlX3N0cmVhbS5EZWNvZGVTdHJlYW0pIHsKICAgICAgcmV0dXJuIGltYWdlQnl0ZXM7CiAgICB9CiAgICAoMCwgX3V0aWwuYXNzZXJ0KShpbWFnZUJ5dGVzIGluc3RhbmNlb2YgVWludDhBcnJheSwgJ1BERkltYWdlLmdldEltYWdlQnl0ZXM6IFVuc3VwcG9ydGVkICJpbWFnZUJ5dGVzIiB0eXBlLicpOwogICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGltYWdlQnl0ZXMpOwogIH0KfQpleHBvcnRzLlBERkltYWdlID0gUERGSW1hZ2U7CgovKioqLyB9KSwKLyogMjAwICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5pbmNyZW1lbnRhbFVwZGF0ZSA9IGluY3JlbWVudGFsVXBkYXRlOwpleHBvcnRzLndyaXRlRGljdCA9IHdyaXRlRGljdDsKZXhwb3J0cy53cml0ZU9iamVjdCA9IHdyaXRlT2JqZWN0Owp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwp2YXIgX3ByaW1pdGl2ZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MCk7CnZhciBfY29yZV91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTM5KTsKdmFyIF94bWxfcGFyc2VyID0gX193X3BkZmpzX3JlcXVpcmVfXygyMDEpOwp2YXIgX2Jhc2Vfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDEpOwp2YXIgX2NyeXB0byA9IF9fd19wZGZqc19yZXF1aXJlX18oMjAyKTsKZnVuY3Rpb24gd3JpdGVPYmplY3QocmVmLCBvYmosIGJ1ZmZlciwgdHJhbnNmb3JtKSB7CiAgYnVmZmVyLnB1c2goYCR7cmVmLm51bX0gJHtyZWYuZ2VufSBvYmpcbmApOwogIGlmIChvYmogaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICB3cml0ZURpY3Qob2JqLCBidWZmZXIsIHRyYW5zZm9ybSk7CiAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkgewogICAgd3JpdGVTdHJlYW0ob2JqLCBidWZmZXIsIHRyYW5zZm9ybSk7CiAgfQogIGJ1ZmZlci5wdXNoKCJcbmVuZG9ialxuIik7Cn0KZnVuY3Rpb24gd3JpdGVEaWN0KGRpY3QsIGJ1ZmZlciwgdHJhbnNmb3JtKSB7CiAgYnVmZmVyLnB1c2goIjw8Iik7CiAgZm9yIChjb25zdCBrZXkgb2YgZGljdC5nZXRLZXlzKCkpIHsKICAgIGJ1ZmZlci5wdXNoKGAgLyR7KDAsIF9jb3JlX3V0aWxzLmVzY2FwZVBERk5hbWUpKGtleSl9IGApOwogICAgd3JpdGVWYWx1ZShkaWN0LmdldFJhdyhrZXkpLCBidWZmZXIsIHRyYW5zZm9ybSk7CiAgfQogIGJ1ZmZlci5wdXNoKCI+PiIpOwp9CmZ1bmN0aW9uIHdyaXRlU3RyZWFtKHN0cmVhbSwgYnVmZmVyLCB0cmFuc2Zvcm0pIHsKICBsZXQgc3RyaW5nID0gc3RyZWFtLmdldFN0cmluZygpOwogIGlmICh0cmFuc2Zvcm0gIT09IG51bGwpIHsKICAgIHN0cmluZyA9IHRyYW5zZm9ybS5lbmNyeXB0U3RyaW5nKHN0cmluZyk7CiAgfQogIHN0cmVhbS5kaWN0LnNldCgiTGVuZ3RoIiwgc3RyaW5nLmxlbmd0aCk7CiAgd3JpdGVEaWN0KHN0cmVhbS5kaWN0LCBidWZmZXIsIHRyYW5zZm9ybSk7CiAgYnVmZmVyLnB1c2goIiBzdHJlYW1cbiIsIHN0cmluZywgIlxuZW5kc3RyZWFtIik7Cn0KZnVuY3Rpb24gd3JpdGVBcnJheShhcnJheSwgYnVmZmVyLCB0cmFuc2Zvcm0pIHsKICBidWZmZXIucHVzaCgiWyIpOwogIGxldCBmaXJzdCA9IHRydWU7CiAgZm9yIChjb25zdCB2YWwgb2YgYXJyYXkpIHsKICAgIGlmICghZmlyc3QpIHsKICAgICAgYnVmZmVyLnB1c2goIiAiKTsKICAgIH0gZWxzZSB7CiAgICAgIGZpcnN0ID0gZmFsc2U7CiAgICB9CiAgICB3cml0ZVZhbHVlKHZhbCwgYnVmZmVyLCB0cmFuc2Zvcm0pOwogIH0KICBidWZmZXIucHVzaCgiXSIpOwp9CmZ1bmN0aW9uIHdyaXRlVmFsdWUodmFsdWUsIGJ1ZmZlciwgdHJhbnNmb3JtKSB7CiAgaWYgKHZhbHVlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgYnVmZmVyLnB1c2goYC8keygwLCBfY29yZV91dGlscy5lc2NhcGVQREZOYW1lKSh2YWx1ZS5uYW1lKX1gKTsKICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICBidWZmZXIucHVzaChgJHt2YWx1ZS5udW19ICR7dmFsdWUuZ2VufSBSYCk7CiAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkgewogICAgd3JpdGVBcnJheSh2YWx1ZSwgYnVmZmVyLCB0cmFuc2Zvcm0pOwogIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAic3RyaW5nIikgewogICAgaWYgKHRyYW5zZm9ybSAhPT0gbnVsbCkgewogICAgICB2YWx1ZSA9IHRyYW5zZm9ybS5lbmNyeXB0U3RyaW5nKHZhbHVlKTsKICAgIH0KICAgIGJ1ZmZlci5wdXNoKGAoJHsoMCwgX2NvcmVfdXRpbHMuZXNjYXBlU3RyaW5nKSh2YWx1ZSl9KWApOwogIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAibnVtYmVyIikgewogICAgYnVmZmVyLnB1c2goKDAsIF9jb3JlX3V0aWxzLm51bWJlclRvU3RyaW5nKSh2YWx1ZSkpOwogIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAiYm9vbGVhbiIpIHsKICAgIGJ1ZmZlci5wdXNoKHZhbHVlLnRvU3RyaW5nKCkpOwogIH0gZWxzZSBpZiAodmFsdWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICB3cml0ZURpY3QodmFsdWUsIGJ1ZmZlciwgdHJhbnNmb3JtKTsKICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0pIHsKICAgIHdyaXRlU3RyZWFtKHZhbHVlLCBidWZmZXIsIHRyYW5zZm9ybSk7CiAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gbnVsbCkgewogICAgYnVmZmVyLnB1c2goIm51bGwiKTsKICB9IGVsc2UgewogICAgKDAsIF91dGlsLndhcm4pKGBVbmhhbmRsZWQgdmFsdWUgaW4gd3JpdGVyOiAke3R5cGVvZiB2YWx1ZX0sIHBsZWFzZSBmaWxlIGEgYnVnLmApOwogIH0KfQpmdW5jdGlvbiB3cml0ZUludChudW1iZXIsIHNpemUsIG9mZnNldCwgYnVmZmVyKSB7CiAgZm9yIChsZXQgaSA9IHNpemUgKyBvZmZzZXQgLSAxOyBpID4gb2Zmc2V0IC0gMTsgaS0tKSB7CiAgICBidWZmZXJbaV0gPSBudW1iZXIgJiAweGZmOwogICAgbnVtYmVyID4+PSA4OwogIH0KICByZXR1cm4gb2Zmc2V0ICsgc2l6ZTsKfQpmdW5jdGlvbiB3cml0ZVN0cmluZyhzdHJpbmcsIG9mZnNldCwgYnVmZmVyKSB7CiAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IHN0cmluZy5sZW5ndGg7IGkgPCBsZW47IGkrKykgewogICAgYnVmZmVyW29mZnNldCArIGldID0gc3RyaW5nLmNoYXJDb2RlQXQoaSkgJiAweGZmOwogIH0KfQpmdW5jdGlvbiBjb21wdXRlTUQ1KGZpbGVzaXplLCB4cmVmSW5mbykgewogIGNvbnN0IHRpbWUgPSBNYXRoLmZsb29yKERhdGUubm93KCkgLyAxMDAwKTsKICBjb25zdCBmaWxlbmFtZSA9IHhyZWZJbmZvLmZpbGVuYW1lIHx8ICIiOwogIGNvbnN0IG1kNUJ1ZmZlciA9IFt0aW1lLnRvU3RyaW5nKCksIGZpbGVuYW1lLCBmaWxlc2l6ZS50b1N0cmluZygpXTsKICBsZXQgbWQ1QnVmZmVyTGVuID0gbWQ1QnVmZmVyLnJlZHVjZSgoYSwgc3RyKSA9PiBhICsgc3RyLmxlbmd0aCwgMCk7CiAgZm9yIChjb25zdCB2YWx1ZSBvZiBPYmplY3QudmFsdWVzKHhyZWZJbmZvLmluZm8pKSB7CiAgICBtZDVCdWZmZXIucHVzaCh2YWx1ZSk7CiAgICBtZDVCdWZmZXJMZW4gKz0gdmFsdWUubGVuZ3RoOwogIH0KICBjb25zdCBhcnJheSA9IG5ldyBVaW50OEFycmF5KG1kNUJ1ZmZlckxlbik7CiAgbGV0IG9mZnNldCA9IDA7CiAgZm9yIChjb25zdCBzdHIgb2YgbWQ1QnVmZmVyKSB7CiAgICB3cml0ZVN0cmluZyhzdHIsIG9mZnNldCwgYXJyYXkpOwogICAgb2Zmc2V0ICs9IHN0ci5sZW5ndGg7CiAgfQogIHJldHVybiAoMCwgX3V0aWwuYnl0ZXNUb1N0cmluZykoKDAsIF9jcnlwdG8uY2FsY3VsYXRlTUQ1KShhcnJheSkpOwp9CmZ1bmN0aW9uIHdyaXRlWEZBRGF0YUZvckFjcm9mb3JtKHN0ciwgbmV3UmVmcykgewogIGNvbnN0IHhtbCA9IG5ldyBfeG1sX3BhcnNlci5TaW1wbGVYTUxQYXJzZXIoewogICAgaGFzQXR0cmlidXRlczogdHJ1ZQogIH0pLnBhcnNlRnJvbVN0cmluZyhzdHIpOwogIGZvciAoY29uc3QgewogICAgeGZhCiAgfSBvZiBuZXdSZWZzKSB7CiAgICBpZiAoIXhmYSkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgcGF0aCwKICAgICAgdmFsdWUKICAgIH0gPSB4ZmE7CiAgICBpZiAoIXBhdGgpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBjb25zdCBub2RlUGF0aCA9ICgwLCBfY29yZV91dGlscy5wYXJzZVhGQVBhdGgpKHBhdGgpOwogICAgbGV0IG5vZGUgPSB4bWwuZG9jdW1lbnRFbGVtZW50LnNlYXJjaE5vZGUobm9kZVBhdGgsIDApOwogICAgaWYgKCFub2RlICYmIG5vZGVQYXRoLmxlbmd0aCA+IDEpIHsKICAgICAgbm9kZSA9IHhtbC5kb2N1bWVudEVsZW1lbnQuc2VhcmNoTm9kZShbbm9kZVBhdGguYXQoLTEpXSwgMCk7CiAgICB9CiAgICBpZiAobm9kZSkgewogICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgICBub2RlLmNoaWxkTm9kZXMgPSB2YWx1ZS5tYXAodmFsID0+IG5ldyBfeG1sX3BhcnNlci5TaW1wbGVET01Ob2RlKCJ2YWx1ZSIsIHZhbCkpOwogICAgICB9IGVsc2UgewogICAgICAgIG5vZGUuY2hpbGROb2RlcyA9IFtuZXcgX3htbF9wYXJzZXIuU2ltcGxlRE9NTm9kZSgiI3RleHQiLCB2YWx1ZSldOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICAoMCwgX3V0aWwud2FybikoYE5vZGUgbm90IGZvdW5kIGZvciBwYXRoOiAke3BhdGh9YCk7CiAgICB9CiAgfQogIGNvbnN0IGJ1ZmZlciA9IFtdOwogIHhtbC5kb2N1bWVudEVsZW1lbnQuZHVtcChidWZmZXIpOwogIHJldHVybiBidWZmZXIuam9pbigiIik7Cn0KZnVuY3Rpb24gdXBkYXRlQWNyb2Zvcm0oX3JlZikgewogIGxldCB7CiAgICB4cmVmLAogICAgYWNyb0Zvcm0sCiAgICBhY3JvRm9ybVJlZiwKICAgIGhhc1hmYSwKICAgIGhhc1hmYURhdGFzZXRzRW50cnksCiAgICB4ZmFEYXRhc2V0c1JlZiwKICAgIG5lZWRBcHBlYXJhbmNlcywKICAgIG5ld1JlZnMKICB9ID0gX3JlZjsKICBpZiAoaGFzWGZhICYmICFoYXNYZmFEYXRhc2V0c0VudHJ5ICYmICF4ZmFEYXRhc2V0c1JlZikgewogICAgKDAsIF91dGlsLndhcm4pKCJYRkEgLSBDYW5ub3Qgc2F2ZSBpdCIpOwogIH0KICBpZiAoIW5lZWRBcHBlYXJhbmNlcyAmJiAoIWhhc1hmYSB8fCAheGZhRGF0YXNldHNSZWYpKSB7CiAgICByZXR1cm47CiAgfQogIGNvbnN0IGRpY3QgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdCh4cmVmKTsKICBmb3IgKGNvbnN0IGtleSBvZiBhY3JvRm9ybS5nZXRLZXlzKCkpIHsKICAgIGRpY3Quc2V0KGtleSwgYWNyb0Zvcm0uZ2V0UmF3KGtleSkpOwogIH0KICBpZiAoaGFzWGZhICYmICFoYXNYZmFEYXRhc2V0c0VudHJ5KSB7CiAgICBjb25zdCBuZXdYZmEgPSBhY3JvRm9ybS5nZXQoIlhGQSIpLnNsaWNlKCk7CiAgICBuZXdYZmEuc3BsaWNlKDIsIDAsICJkYXRhc2V0cyIpOwogICAgbmV3WGZhLnNwbGljZSgzLCAwLCB4ZmFEYXRhc2V0c1JlZik7CiAgICBkaWN0LnNldCgiWEZBIiwgbmV3WGZhKTsKICB9CiAgaWYgKG5lZWRBcHBlYXJhbmNlcykgewogICAgZGljdC5zZXQoIk5lZWRBcHBlYXJhbmNlcyIsIHRydWUpOwogIH0KICBjb25zdCBlbmNyeXB0ID0geHJlZi5lbmNyeXB0OwogIGxldCB0cmFuc2Zvcm0gPSBudWxsOwogIGlmIChlbmNyeXB0KSB7CiAgICB0cmFuc2Zvcm0gPSBlbmNyeXB0LmNyZWF0ZUNpcGhlclRyYW5zZm9ybShhY3JvRm9ybVJlZi5udW0sIGFjcm9Gb3JtUmVmLmdlbik7CiAgfQogIGNvbnN0IGJ1ZmZlciA9IFtdOwogIHdyaXRlT2JqZWN0KGFjcm9Gb3JtUmVmLCBkaWN0LCBidWZmZXIsIHRyYW5zZm9ybSk7CiAgbmV3UmVmcy5wdXNoKHsKICAgIHJlZjogYWNyb0Zvcm1SZWYsCiAgICBkYXRhOiBidWZmZXIuam9pbigiIikKICB9KTsKfQpmdW5jdGlvbiB1cGRhdGVYRkEoX3JlZjIpIHsKICBsZXQgewogICAgeGZhRGF0YSwKICAgIHhmYURhdGFzZXRzUmVmLAogICAgbmV3UmVmcywKICAgIHhyZWYKICB9ID0gX3JlZjI7CiAgaWYgKHhmYURhdGEgPT09IG51bGwpIHsKICAgIGNvbnN0IGRhdGFzZXRzID0geHJlZi5mZXRjaElmUmVmKHhmYURhdGFzZXRzUmVmKTsKICAgIHhmYURhdGEgPSB3cml0ZVhGQURhdGFGb3JBY3JvZm9ybShkYXRhc2V0cy5nZXRTdHJpbmcoKSwgbmV3UmVmcyk7CiAgfQogIGNvbnN0IGVuY3J5cHQgPSB4cmVmLmVuY3J5cHQ7CiAgaWYgKGVuY3J5cHQpIHsKICAgIGNvbnN0IHRyYW5zZm9ybSA9IGVuY3J5cHQuY3JlYXRlQ2lwaGVyVHJhbnNmb3JtKHhmYURhdGFzZXRzUmVmLm51bSwgeGZhRGF0YXNldHNSZWYuZ2VuKTsKICAgIHhmYURhdGEgPSB0cmFuc2Zvcm0uZW5jcnlwdFN0cmluZyh4ZmFEYXRhKTsKICB9CiAgY29uc3QgZGF0YSA9IGAke3hmYURhdGFzZXRzUmVmLm51bX0gJHt4ZmFEYXRhc2V0c1JlZi5nZW59IG9ialxuYCArIGA8PCAvVHlwZSAvRW1iZWRkZWRGaWxlIC9MZW5ndGggJHt4ZmFEYXRhLmxlbmd0aH0+Plxuc3RyZWFtXG5gICsgeGZhRGF0YSArICJcbmVuZHN0cmVhbVxuZW5kb2JqXG4iOwogIG5ld1JlZnMucHVzaCh7CiAgICByZWY6IHhmYURhdGFzZXRzUmVmLAogICAgZGF0YQogIH0pOwp9CmZ1bmN0aW9uIGluY3JlbWVudGFsVXBkYXRlKF9yZWYzKSB7CiAgbGV0IHsKICAgIG9yaWdpbmFsRGF0YSwKICAgIHhyZWZJbmZvLAogICAgbmV3UmVmcywKICAgIHhyZWYgPSBudWxsLAogICAgaGFzWGZhID0gZmFsc2UsCiAgICB4ZmFEYXRhc2V0c1JlZiA9IG51bGwsCiAgICBoYXNYZmFEYXRhc2V0c0VudHJ5ID0gZmFsc2UsCiAgICBuZWVkQXBwZWFyYW5jZXMsCiAgICBhY3JvRm9ybVJlZiA9IG51bGwsCiAgICBhY3JvRm9ybSA9IG51bGwsCiAgICB4ZmFEYXRhID0gbnVsbAogIH0gPSBfcmVmMzsKICB1cGRhdGVBY3JvZm9ybSh7CiAgICB4cmVmLAogICAgYWNyb0Zvcm0sCiAgICBhY3JvRm9ybVJlZiwKICAgIGhhc1hmYSwKICAgIGhhc1hmYURhdGFzZXRzRW50cnksCiAgICB4ZmFEYXRhc2V0c1JlZiwKICAgIG5lZWRBcHBlYXJhbmNlcywKICAgIG5ld1JlZnMKICB9KTsKICBpZiAoaGFzWGZhKSB7CiAgICB1cGRhdGVYRkEoewogICAgICB4ZmFEYXRhLAogICAgICB4ZmFEYXRhc2V0c1JlZiwKICAgICAgbmV3UmVmcywKICAgICAgeHJlZgogICAgfSk7CiAgfQogIGNvbnN0IG5ld1hyZWYgPSBuZXcgX3ByaW1pdGl2ZXMuRGljdChudWxsKTsKICBjb25zdCByZWZGb3JYcmVmVGFibGUgPSB4cmVmSW5mby5uZXdSZWY7CiAgbGV0IGJ1ZmZlciwgYmFzZU9mZnNldDsKICBjb25zdCBsYXN0Qnl0ZSA9IG9yaWdpbmFsRGF0YS5hdCgtMSk7CiAgaWYgKGxhc3RCeXRlID09PSAweDBhIHx8IGxhc3RCeXRlID09PSAweDBkKSB7CiAgICBidWZmZXIgPSBbXTsKICAgIGJhc2VPZmZzZXQgPSBvcmlnaW5hbERhdGEubGVuZ3RoOwogIH0gZWxzZSB7CiAgICBidWZmZXIgPSBbIlxuIl07CiAgICBiYXNlT2Zmc2V0ID0gb3JpZ2luYWxEYXRhLmxlbmd0aCArIDE7CiAgfQogIG5ld1hyZWYuc2V0KCJTaXplIiwgcmVmRm9yWHJlZlRhYmxlLm51bSArIDEpOwogIG5ld1hyZWYuc2V0KCJQcmV2IiwgeHJlZkluZm8uc3RhcnRYUmVmKTsKICBuZXdYcmVmLnNldCgiVHlwZSIsIF9wcmltaXRpdmVzLk5hbWUuZ2V0KCJYUmVmIikpOwogIGlmICh4cmVmSW5mby5yb290UmVmICE9PSBudWxsKSB7CiAgICBuZXdYcmVmLnNldCgiUm9vdCIsIHhyZWZJbmZvLnJvb3RSZWYpOwogIH0KICBpZiAoeHJlZkluZm8uaW5mb1JlZiAhPT0gbnVsbCkgewogICAgbmV3WHJlZi5zZXQoIkluZm8iLCB4cmVmSW5mby5pbmZvUmVmKTsKICB9CiAgaWYgKHhyZWZJbmZvLmVuY3J5cHRSZWYgIT09IG51bGwpIHsKICAgIG5ld1hyZWYuc2V0KCJFbmNyeXB0IiwgeHJlZkluZm8uZW5jcnlwdFJlZik7CiAgfQogIG5ld1JlZnMucHVzaCh7CiAgICByZWY6IHJlZkZvclhyZWZUYWJsZSwKICAgIGRhdGE6ICIiCiAgfSk7CiAgbmV3UmVmcyA9IG5ld1JlZnMuc29ydCgoYSwgYikgPT4gewogICAgcmV0dXJuIGEucmVmLm51bSAtIGIucmVmLm51bTsKICB9KTsKICBjb25zdCB4cmVmVGFibGVEYXRhID0gW1swLCAxLCAweGZmZmZdXTsKICBjb25zdCBpbmRleGVzID0gWzAsIDFdOwogIGxldCBtYXhPZmZzZXQgPSAwOwogIGZvciAoY29uc3QgewogICAgcmVmLAogICAgZGF0YQogIH0gb2YgbmV3UmVmcykgewogICAgbWF4T2Zmc2V0ID0gTWF0aC5tYXgobWF4T2Zmc2V0LCBiYXNlT2Zmc2V0KTsKICAgIHhyZWZUYWJsZURhdGEucHVzaChbMSwgYmFzZU9mZnNldCwgTWF0aC5taW4ocmVmLmdlbiwgMHhmZmZmKV0pOwogICAgYmFzZU9mZnNldCArPSBkYXRhLmxlbmd0aDsKICAgIGluZGV4ZXMucHVzaChyZWYubnVtLCAxKTsKICAgIGJ1ZmZlci5wdXNoKGRhdGEpOwogIH0KICBuZXdYcmVmLnNldCgiSW5kZXgiLCBpbmRleGVzKTsKICBpZiAoQXJyYXkuaXNBcnJheSh4cmVmSW5mby5maWxlSWRzKSAmJiB4cmVmSW5mby5maWxlSWRzLmxlbmd0aCA+IDApIHsKICAgIGNvbnN0IG1kNSA9IGNvbXB1dGVNRDUoYmFzZU9mZnNldCwgeHJlZkluZm8pOwogICAgbmV3WHJlZi5zZXQoIklEIiwgW3hyZWZJbmZvLmZpbGVJZHNbMF0sIG1kNV0pOwogIH0KICBjb25zdCBvZmZzZXRTaXplID0gTWF0aC5jZWlsKE1hdGgubG9nMihtYXhPZmZzZXQpIC8gOCk7CiAgY29uc3Qgc2l6ZXMgPSBbMSwgb2Zmc2V0U2l6ZSwgMl07CiAgY29uc3Qgc3RydWN0U2l6ZSA9IHNpemVzWzBdICsgc2l6ZXNbMV0gKyBzaXplc1syXTsKICBjb25zdCB0YWJsZUxlbmd0aCA9IHN0cnVjdFNpemUgKiB4cmVmVGFibGVEYXRhLmxlbmd0aDsKICBuZXdYcmVmLnNldCgiVyIsIHNpemVzKTsKICBuZXdYcmVmLnNldCgiTGVuZ3RoIiwgdGFibGVMZW5ndGgpOwogIGJ1ZmZlci5wdXNoKGAke3JlZkZvclhyZWZUYWJsZS5udW19ICR7cmVmRm9yWHJlZlRhYmxlLmdlbn0gb2JqXG5gKTsKICB3cml0ZURpY3QobmV3WHJlZiwgYnVmZmVyLCBudWxsKTsKICBidWZmZXIucHVzaCgiIHN0cmVhbVxuIik7CiAgY29uc3QgYnVmZmVyTGVuID0gYnVmZmVyLnJlZHVjZSgoYSwgc3RyKSA9PiBhICsgc3RyLmxlbmd0aCwgMCk7CiAgY29uc3QgZm9vdGVyID0gYFxuZW5kc3RyZWFtXG5lbmRvYmpcbnN0YXJ0eHJlZlxuJHtiYXNlT2Zmc2V0fVxuJSVFT0ZcbmA7CiAgY29uc3QgYXJyYXkgPSBuZXcgVWludDhBcnJheShvcmlnaW5hbERhdGEubGVuZ3RoICsgYnVmZmVyTGVuICsgdGFibGVMZW5ndGggKyBmb290ZXIubGVuZ3RoKTsKICBhcnJheS5zZXQob3JpZ2luYWxEYXRhKTsKICBsZXQgb2Zmc2V0ID0gb3JpZ2luYWxEYXRhLmxlbmd0aDsKICBmb3IgKGNvbnN0IHN0ciBvZiBidWZmZXIpIHsKICAgIHdyaXRlU3RyaW5nKHN0ciwgb2Zmc2V0LCBhcnJheSk7CiAgICBvZmZzZXQgKz0gc3RyLmxlbmd0aDsKICB9CiAgZm9yIChjb25zdCBbdHlwZSwgb2JqT2Zmc2V0LCBnZW5dIG9mIHhyZWZUYWJsZURhdGEpIHsKICAgIG9mZnNldCA9IHdyaXRlSW50KHR5cGUsIHNpemVzWzBdLCBvZmZzZXQsIGFycmF5KTsKICAgIG9mZnNldCA9IHdyaXRlSW50KG9iak9mZnNldCwgc2l6ZXNbMV0sIG9mZnNldCwgYXJyYXkpOwogICAgb2Zmc2V0ID0gd3JpdGVJbnQoZ2VuLCBzaXplc1syXSwgb2Zmc2V0LCBhcnJheSk7CiAgfQogIHdyaXRlU3RyaW5nKGZvb3Rlciwgb2Zmc2V0LCBhcnJheSk7CiAgcmV0dXJuIGFycmF5Owp9CgovKioqLyB9KSwKLyogMjAxICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5YTUxQYXJzZXJFcnJvckNvZGUgPSBleHBvcnRzLlhNTFBhcnNlckJhc2UgPSBleHBvcnRzLlNpbXBsZVhNTFBhcnNlciA9IGV4cG9ydHMuU2ltcGxlRE9NTm9kZSA9IHZvaWQgMDsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwpjb25zdCBYTUxQYXJzZXJFcnJvckNvZGUgPSB7CiAgTm9FcnJvcjogMCwKICBFbmRPZkRvY3VtZW50OiAtMSwKICBVbnRlcm1pbmF0ZWRDZGF0OiAtMiwKICBVbnRlcm1pbmF0ZWRYbWxEZWNsYXJhdGlvbjogLTMsCiAgVW50ZXJtaW5hdGVkRG9jdHlwZURlY2xhcmF0aW9uOiAtNCwKICBVbnRlcm1pbmF0ZWRDb21tZW50OiAtNSwKICBNYWxmb3JtZWRFbGVtZW50OiAtNiwKICBPdXRPZk1lbW9yeTogLTcsCiAgVW50ZXJtaW5hdGVkQXR0cmlidXRlVmFsdWU6IC04LAogIFVudGVybWluYXRlZEVsZW1lbnQ6IC05LAogIEVsZW1lbnROZXZlckJlZ3VuOiAtMTAKfTsKZXhwb3J0cy5YTUxQYXJzZXJFcnJvckNvZGUgPSBYTUxQYXJzZXJFcnJvckNvZGU7CmZ1bmN0aW9uIGlzV2hpdGVzcGFjZShzLCBpbmRleCkgewogIGNvbnN0IGNoID0gc1tpbmRleF07CiAgcmV0dXJuIGNoID09PSAiICIgfHwgY2ggPT09ICJcbiIgfHwgY2ggPT09ICJcciIgfHwgY2ggPT09ICJcdCI7Cn0KZnVuY3Rpb24gaXNXaGl0ZXNwYWNlU3RyaW5nKHMpIHsKICBmb3IgKGxldCBpID0gMCwgaWkgPSBzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGlmICghaXNXaGl0ZXNwYWNlKHMsIGkpKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9CiAgcmV0dXJuIHRydWU7Cn0KY2xhc3MgWE1MUGFyc2VyQmFzZSB7CiAgX3Jlc29sdmVFbnRpdGllcyhzKSB7CiAgICByZXR1cm4gcy5yZXBsYWNlQWxsKC8mKFteO10rKTsvZywgKGFsbCwgZW50aXR5KSA9PiB7CiAgICAgIGlmIChlbnRpdHkuc3Vic3RyaW5nKDAsIDIpID09PSAiI3giKSB7CiAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KHBhcnNlSW50KGVudGl0eS5zdWJzdHJpbmcoMiksIDE2KSk7CiAgICAgIH0gZWxzZSBpZiAoZW50aXR5LnN1YnN0cmluZygwLCAxKSA9PT0gIiMiKSB7CiAgICAgICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KHBhcnNlSW50KGVudGl0eS5zdWJzdHJpbmcoMSksIDEwKSk7CiAgICAgIH0KICAgICAgc3dpdGNoIChlbnRpdHkpIHsKICAgICAgICBjYXNlICJsdCI6CiAgICAgICAgICByZXR1cm4gIjwiOwogICAgICAgIGNhc2UgImd0IjoKICAgICAgICAgIHJldHVybiAiPiI7CiAgICAgICAgY2FzZSAiYW1wIjoKICAgICAgICAgIHJldHVybiAiJiI7CiAgICAgICAgY2FzZSAicXVvdCI6CiAgICAgICAgICByZXR1cm4gJyInOwogICAgICAgIGNhc2UgImFwb3MiOgogICAgICAgICAgcmV0dXJuICInIjsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5vblJlc29sdmVFbnRpdHkoZW50aXR5KTsKICAgIH0pOwogIH0KICBfcGFyc2VDb250ZW50KHMsIHN0YXJ0KSB7CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gW107CiAgICBsZXQgcG9zID0gc3RhcnQ7CiAgICBmdW5jdGlvbiBza2lwV3MoKSB7CiAgICAgIHdoaWxlIChwb3MgPCBzLmxlbmd0aCAmJiBpc1doaXRlc3BhY2UocywgcG9zKSkgewogICAgICAgICsrcG9zOwogICAgICB9CiAgICB9CiAgICB3aGlsZSAocG9zIDwgcy5sZW5ndGggJiYgIWlzV2hpdGVzcGFjZShzLCBwb3MpICYmIHNbcG9zXSAhPT0gIj4iICYmIHNbcG9zXSAhPT0gIi8iKSB7CiAgICAgICsrcG9zOwogICAgfQogICAgY29uc3QgbmFtZSA9IHMuc3Vic3RyaW5nKHN0YXJ0LCBwb3MpOwogICAgc2tpcFdzKCk7CiAgICB3aGlsZSAocG9zIDwgcy5sZW5ndGggJiYgc1twb3NdICE9PSAiPiIgJiYgc1twb3NdICE9PSAiLyIgJiYgc1twb3NdICE9PSAiPyIpIHsKICAgICAgc2tpcFdzKCk7CiAgICAgIGxldCBhdHRyTmFtZSA9ICIiLAogICAgICAgIGF0dHJWYWx1ZSA9ICIiOwogICAgICB3aGlsZSAocG9zIDwgcy5sZW5ndGggJiYgIWlzV2hpdGVzcGFjZShzLCBwb3MpICYmIHNbcG9zXSAhPT0gIj0iKSB7CiAgICAgICAgYXR0ck5hbWUgKz0gc1twb3NdOwogICAgICAgICsrcG9zOwogICAgICB9CiAgICAgIHNraXBXcygpOwogICAgICBpZiAoc1twb3NdICE9PSAiPSIpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICArK3BvczsKICAgICAgc2tpcFdzKCk7CiAgICAgIGNvbnN0IGF0dHJFbmRDaGFyID0gc1twb3NdOwogICAgICBpZiAoYXR0ckVuZENoYXIgIT09ICciJyAmJiBhdHRyRW5kQ2hhciAhPT0gIiciKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgY29uc3QgYXR0ckVuZEluZGV4ID0gcy5pbmRleE9mKGF0dHJFbmRDaGFyLCArK3Bvcyk7CiAgICAgIGlmIChhdHRyRW5kSW5kZXggPCAwKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgYXR0clZhbHVlID0gcy5zdWJzdHJpbmcocG9zLCBhdHRyRW5kSW5kZXgpOwogICAgICBhdHRyaWJ1dGVzLnB1c2goewogICAgICAgIG5hbWU6IGF0dHJOYW1lLAogICAgICAgIHZhbHVlOiB0aGlzLl9yZXNvbHZlRW50aXRpZXMoYXR0clZhbHVlKQogICAgICB9KTsKICAgICAgcG9zID0gYXR0ckVuZEluZGV4ICsgMTsKICAgICAgc2tpcFdzKCk7CiAgICB9CiAgICByZXR1cm4gewogICAgICBuYW1lLAogICAgICBhdHRyaWJ1dGVzLAogICAgICBwYXJzZWQ6IHBvcyAtIHN0YXJ0CiAgICB9OwogIH0KICBfcGFyc2VQcm9jZXNzaW5nSW5zdHJ1Y3Rpb24ocywgc3RhcnQpIHsKICAgIGxldCBwb3MgPSBzdGFydDsKICAgIGZ1bmN0aW9uIHNraXBXcygpIHsKICAgICAgd2hpbGUgKHBvcyA8IHMubGVuZ3RoICYmIGlzV2hpdGVzcGFjZShzLCBwb3MpKSB7CiAgICAgICAgKytwb3M7CiAgICAgIH0KICAgIH0KICAgIHdoaWxlIChwb3MgPCBzLmxlbmd0aCAmJiAhaXNXaGl0ZXNwYWNlKHMsIHBvcykgJiYgc1twb3NdICE9PSAiPiIgJiYgc1twb3NdICE9PSAiPyIgJiYgc1twb3NdICE9PSAiLyIpIHsKICAgICAgKytwb3M7CiAgICB9CiAgICBjb25zdCBuYW1lID0gcy5zdWJzdHJpbmcoc3RhcnQsIHBvcyk7CiAgICBza2lwV3MoKTsKICAgIGNvbnN0IGF0dHJTdGFydCA9IHBvczsKICAgIHdoaWxlIChwb3MgPCBzLmxlbmd0aCAmJiAoc1twb3NdICE9PSAiPyIgfHwgc1twb3MgKyAxXSAhPT0gIj4iKSkgewogICAgICArK3BvczsKICAgIH0KICAgIGNvbnN0IHZhbHVlID0gcy5zdWJzdHJpbmcoYXR0clN0YXJ0LCBwb3MpOwogICAgcmV0dXJuIHsKICAgICAgbmFtZSwKICAgICAgdmFsdWUsCiAgICAgIHBhcnNlZDogcG9zIC0gc3RhcnQKICAgIH07CiAgfQogIHBhcnNlWG1sKHMpIHsKICAgIGxldCBpID0gMDsKICAgIHdoaWxlIChpIDwgcy5sZW5ndGgpIHsKICAgICAgY29uc3QgY2ggPSBzW2ldOwogICAgICBsZXQgaiA9IGk7CiAgICAgIGlmIChjaCA9PT0gIjwiKSB7CiAgICAgICAgKytqOwogICAgICAgIGNvbnN0IGNoMiA9IHNbal07CiAgICAgICAgbGV0IHE7CiAgICAgICAgc3dpdGNoIChjaDIpIHsKICAgICAgICAgIGNhc2UgIi8iOgogICAgICAgICAgICArK2o7CiAgICAgICAgICAgIHEgPSBzLmluZGV4T2YoIj4iLCBqKTsKICAgICAgICAgICAgaWYgKHEgPCAwKSB7CiAgICAgICAgICAgICAgdGhpcy5vbkVycm9yKFhNTFBhcnNlckVycm9yQ29kZS5VbnRlcm1pbmF0ZWRFbGVtZW50KTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5vbkVuZEVsZW1lbnQocy5zdWJzdHJpbmcoaiwgcSkpOwogICAgICAgICAgICBqID0gcSArIDE7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAiPyI6CiAgICAgICAgICAgICsrajsKICAgICAgICAgICAgY29uc3QgcGkgPSB0aGlzLl9wYXJzZVByb2Nlc3NpbmdJbnN0cnVjdGlvbihzLCBqKTsKICAgICAgICAgICAgaWYgKHMuc3Vic3RyaW5nKGogKyBwaS5wYXJzZWQsIGogKyBwaS5wYXJzZWQgKyAyKSAhPT0gIj8+IikgewogICAgICAgICAgICAgIHRoaXMub25FcnJvcihYTUxQYXJzZXJFcnJvckNvZGUuVW50ZXJtaW5hdGVkWG1sRGVjbGFyYXRpb24pOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aGlzLm9uUGkocGkubmFtZSwgcGkudmFsdWUpOwogICAgICAgICAgICBqICs9IHBpLnBhcnNlZCArIDI7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAiISI6CiAgICAgICAgICAgIGlmIChzLnN1YnN0cmluZyhqICsgMSwgaiArIDMpID09PSAiLS0iKSB7CiAgICAgICAgICAgICAgcSA9IHMuaW5kZXhPZigiLS0+IiwgaiArIDMpOwogICAgICAgICAgICAgIGlmIChxIDwgMCkgewogICAgICAgICAgICAgICAgdGhpcy5vbkVycm9yKFhNTFBhcnNlckVycm9yQ29kZS5VbnRlcm1pbmF0ZWRDb21tZW50KTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdGhpcy5vbkNvbW1lbnQocy5zdWJzdHJpbmcoaiArIDMsIHEpKTsKICAgICAgICAgICAgICBqID0gcSArIDM7CiAgICAgICAgICAgIH0gZWxzZSBpZiAocy5zdWJzdHJpbmcoaiArIDEsIGogKyA4KSA9PT0gIltDREFUQVsiKSB7CiAgICAgICAgICAgICAgcSA9IHMuaW5kZXhPZigiXV0+IiwgaiArIDgpOwogICAgICAgICAgICAgIGlmIChxIDwgMCkgewogICAgICAgICAgICAgICAgdGhpcy5vbkVycm9yKFhNTFBhcnNlckVycm9yQ29kZS5VbnRlcm1pbmF0ZWRDZGF0KTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdGhpcy5vbkNkYXRhKHMuc3Vic3RyaW5nKGogKyA4LCBxKSk7CiAgICAgICAgICAgICAgaiA9IHEgKyAzOwogICAgICAgICAgICB9IGVsc2UgaWYgKHMuc3Vic3RyaW5nKGogKyAxLCBqICsgOCkgPT09ICJET0NUWVBFIikgewogICAgICAgICAgICAgIGNvbnN0IHEyID0gcy5pbmRleE9mKCJbIiwgaiArIDgpOwogICAgICAgICAgICAgIGxldCBjb21wbGV4RG9jdHlwZSA9IGZhbHNlOwogICAgICAgICAgICAgIHEgPSBzLmluZGV4T2YoIj4iLCBqICsgOCk7CiAgICAgICAgICAgICAgaWYgKHEgPCAwKSB7CiAgICAgICAgICAgICAgICB0aGlzLm9uRXJyb3IoWE1MUGFyc2VyRXJyb3JDb2RlLlVudGVybWluYXRlZERvY3R5cGVEZWNsYXJhdGlvbik7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmIChxMiA+IDAgJiYgcSA+IHEyKSB7CiAgICAgICAgICAgICAgICBxID0gcy5pbmRleE9mKCJdPiIsIGogKyA4KTsKICAgICAgICAgICAgICAgIGlmIChxIDwgMCkgewogICAgICAgICAgICAgICAgICB0aGlzLm9uRXJyb3IoWE1MUGFyc2VyRXJyb3JDb2RlLlVudGVybWluYXRlZERvY3R5cGVEZWNsYXJhdGlvbik7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNvbXBsZXhEb2N0eXBlID0gdHJ1ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgZG9jdHlwZUNvbnRlbnQgPSBzLnN1YnN0cmluZyhqICsgOCwgcSArIChjb21wbGV4RG9jdHlwZSA/IDEgOiAwKSk7CiAgICAgICAgICAgICAgdGhpcy5vbkRvY3R5cGUoZG9jdHlwZUNvbnRlbnQpOwogICAgICAgICAgICAgIGogPSBxICsgKGNvbXBsZXhEb2N0eXBlID8gMiA6IDEpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRoaXMub25FcnJvcihYTUxQYXJzZXJFcnJvckNvZGUuTWFsZm9ybWVkRWxlbWVudCk7CiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgY29uc3QgY29udGVudCA9IHRoaXMuX3BhcnNlQ29udGVudChzLCBqKTsKICAgICAgICAgICAgaWYgKGNvbnRlbnQgPT09IG51bGwpIHsKICAgICAgICAgICAgICB0aGlzLm9uRXJyb3IoWE1MUGFyc2VyRXJyb3JDb2RlLk1hbGZvcm1lZEVsZW1lbnQpOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBsZXQgaXNDbG9zZWQgPSBmYWxzZTsKICAgICAgICAgICAgaWYgKHMuc3Vic3RyaW5nKGogKyBjb250ZW50LnBhcnNlZCwgaiArIGNvbnRlbnQucGFyc2VkICsgMikgPT09ICIvPiIpIHsKICAgICAgICAgICAgICBpc0Nsb3NlZCA9IHRydWU7CiAgICAgICAgICAgIH0gZWxzZSBpZiAocy5zdWJzdHJpbmcoaiArIGNvbnRlbnQucGFyc2VkLCBqICsgY29udGVudC5wYXJzZWQgKyAxKSAhPT0gIj4iKSB7CiAgICAgICAgICAgICAgdGhpcy5vbkVycm9yKFhNTFBhcnNlckVycm9yQ29kZS5VbnRlcm1pbmF0ZWRFbGVtZW50KTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5vbkJlZ2luRWxlbWVudChjb250ZW50Lm5hbWUsIGNvbnRlbnQuYXR0cmlidXRlcywgaXNDbG9zZWQpOwogICAgICAgICAgICBqICs9IGNvbnRlbnQucGFyc2VkICsgKGlzQ2xvc2VkID8gMiA6IDEpOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgd2hpbGUgKGogPCBzLmxlbmd0aCAmJiBzW2pdICE9PSAiPCIpIHsKICAgICAgICAgIGorKzsKICAgICAgICB9CiAgICAgICAgY29uc3QgdGV4dCA9IHMuc3Vic3RyaW5nKGksIGopOwogICAgICAgIHRoaXMub25UZXh0KHRoaXMuX3Jlc29sdmVFbnRpdGllcyh0ZXh0KSk7CiAgICAgIH0KICAgICAgaSA9IGo7CiAgICB9CiAgfQogIG9uUmVzb2x2ZUVudGl0eShuYW1lKSB7CiAgICByZXR1cm4gYCYke25hbWV9O2A7CiAgfQogIG9uUGkobmFtZSwgdmFsdWUpIHt9CiAgb25Db21tZW50KHRleHQpIHt9CiAgb25DZGF0YSh0ZXh0KSB7fQogIG9uRG9jdHlwZShkb2N0eXBlQ29udGVudCkge30KICBvblRleHQodGV4dCkge30KICBvbkJlZ2luRWxlbWVudChuYW1lLCBhdHRyaWJ1dGVzLCBpc0VtcHR5KSB7fQogIG9uRW5kRWxlbWVudChuYW1lKSB7fQogIG9uRXJyb3IoY29kZSkge30KfQpleHBvcnRzLlhNTFBhcnNlckJhc2UgPSBYTUxQYXJzZXJCYXNlOwpjbGFzcyBTaW1wbGVET01Ob2RlIHsKICBjb25zdHJ1Y3Rvcihub2RlTmFtZSwgbm9kZVZhbHVlKSB7CiAgICB0aGlzLm5vZGVOYW1lID0gbm9kZU5hbWU7CiAgICB0aGlzLm5vZGVWYWx1ZSA9IG5vZGVWYWx1ZTsKICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAicGFyZW50Tm9kZSIsIHsKICAgICAgdmFsdWU6IG51bGwsCiAgICAgIHdyaXRhYmxlOiB0cnVlCiAgICB9KTsKICB9CiAgZ2V0IGZpcnN0Q2hpbGQoKSB7CiAgICByZXR1cm4gdGhpcy5jaGlsZE5vZGVzICYmIHRoaXMuY2hpbGROb2Rlc1swXTsKICB9CiAgZ2V0IG5leHRTaWJsaW5nKCkgewogICAgY29uc3QgY2hpbGROb2RlcyA9IHRoaXMucGFyZW50Tm9kZS5jaGlsZE5vZGVzOwogICAgaWYgKCFjaGlsZE5vZGVzKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICBjb25zdCBpbmRleCA9IGNoaWxkTm9kZXMuaW5kZXhPZih0aGlzKTsKICAgIGlmIChpbmRleCA9PT0gLTEpIHsKICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgIH0KICAgIHJldHVybiBjaGlsZE5vZGVzW2luZGV4ICsgMV07CiAgfQogIGdldCB0ZXh0Q29udGVudCgpIHsKICAgIGlmICghdGhpcy5jaGlsZE5vZGVzKSB7CiAgICAgIHJldHVybiB0aGlzLm5vZGVWYWx1ZSB8fCAiIjsKICAgIH0KICAgIHJldHVybiB0aGlzLmNoaWxkTm9kZXMubWFwKGZ1bmN0aW9uIChjaGlsZCkgewogICAgICByZXR1cm4gY2hpbGQudGV4dENvbnRlbnQ7CiAgICB9KS5qb2luKCIiKTsKICB9CiAgZ2V0IGNoaWxkcmVuKCkgewogICAgcmV0dXJuIHRoaXMuY2hpbGROb2RlcyB8fCBbXTsKICB9CiAgaGFzQ2hpbGROb2RlcygpIHsKICAgIHJldHVybiB0aGlzLmNoaWxkTm9kZXMgJiYgdGhpcy5jaGlsZE5vZGVzLmxlbmd0aCA+IDA7CiAgfQogIHNlYXJjaE5vZGUocGF0aHMsIHBvcykgewogICAgaWYgKHBvcyA+PSBwYXRocy5sZW5ndGgpIHsKICAgICAgcmV0dXJuIHRoaXM7CiAgICB9CiAgICBjb25zdCBjb21wb25lbnQgPSBwYXRoc1twb3NdOwogICAgY29uc3Qgc3RhY2sgPSBbXTsKICAgIGxldCBub2RlID0gdGhpczsKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIGlmIChjb21wb25lbnQubmFtZSA9PT0gbm9kZS5ub2RlTmFtZSkgewogICAgICAgIGlmIChjb21wb25lbnQucG9zID09PSAwKSB7CiAgICAgICAgICBjb25zdCByZXMgPSBub2RlLnNlYXJjaE5vZGUocGF0aHMsIHBvcyArIDEpOwogICAgICAgICAgaWYgKHJlcyAhPT0gbnVsbCkgewogICAgICAgICAgICByZXR1cm4gcmVzOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoc3RhY2subGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgW3BhcmVudF0gPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGxldCBzaWJsaW5nUG9zID0gMDsKICAgICAgICAgIGZvciAoY29uc3QgY2hpbGQgb2YgcGFyZW50LmNoaWxkTm9kZXMpIHsKICAgICAgICAgICAgaWYgKGNvbXBvbmVudC5uYW1lID09PSBjaGlsZC5ub2RlTmFtZSkgewogICAgICAgICAgICAgIGlmIChzaWJsaW5nUG9zID09PSBjb21wb25lbnQucG9zKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gY2hpbGQuc2VhcmNoTm9kZShwYXRocywgcG9zICsgMSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHNpYmxpbmdQb3MrKzsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG5vZGUuc2VhcmNoTm9kZShwYXRocywgcG9zICsgMSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChub2RlLmNoaWxkTm9kZXMgJiYgbm9kZS5jaGlsZE5vZGVzLmxlbmd0aCAhPT0gMCkgewogICAgICAgIHN0YWNrLnB1c2goW25vZGUsIDBdKTsKICAgICAgICBub2RlID0gbm9kZS5jaGlsZE5vZGVzWzBdOwogICAgICB9IGVsc2UgaWYgKHN0YWNrLmxlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9IGVsc2UgewogICAgICAgIHdoaWxlIChzdGFjay5sZW5ndGggIT09IDApIHsKICAgICAgICAgIGNvbnN0IFtwYXJlbnQsIGN1cnJlbnRQb3NdID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBjb25zdCBuZXdQb3MgPSBjdXJyZW50UG9zICsgMTsKICAgICAgICAgIGlmIChuZXdQb3MgPCBwYXJlbnQuY2hpbGROb2Rlcy5sZW5ndGgpIHsKICAgICAgICAgICAgc3RhY2sucHVzaChbcGFyZW50LCBuZXdQb3NdKTsKICAgICAgICAgICAgbm9kZSA9IHBhcmVudC5jaGlsZE5vZGVzW25ld1Bvc107CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoc3RhY2subGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgZHVtcChidWZmZXIpIHsKICAgIGlmICh0aGlzLm5vZGVOYW1lID09PSAiI3RleHQiKSB7CiAgICAgIGJ1ZmZlci5wdXNoKCgwLCBfY29yZV91dGlscy5lbmNvZGVUb1htbFN0cmluZykodGhpcy5ub2RlVmFsdWUpKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgYnVmZmVyLnB1c2goYDwke3RoaXMubm9kZU5hbWV9YCk7CiAgICBpZiAodGhpcy5hdHRyaWJ1dGVzKSB7CiAgICAgIGZvciAoY29uc3QgYXR0cmlidXRlIG9mIHRoaXMuYXR0cmlidXRlcykgewogICAgICAgIGJ1ZmZlci5wdXNoKGAgJHthdHRyaWJ1dGUubmFtZX09IiR7KDAsIF9jb3JlX3V0aWxzLmVuY29kZVRvWG1sU3RyaW5nKShhdHRyaWJ1dGUudmFsdWUpfSJgKTsKICAgICAgfQogICAgfQogICAgaWYgKHRoaXMuaGFzQ2hpbGROb2RlcygpKSB7CiAgICAgIGJ1ZmZlci5wdXNoKCI+Iik7CiAgICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpcy5jaGlsZE5vZGVzKSB7CiAgICAgICAgY2hpbGQuZHVtcChidWZmZXIpOwogICAgICB9CiAgICAgIGJ1ZmZlci5wdXNoKGA8LyR7dGhpcy5ub2RlTmFtZX0+YCk7CiAgICB9IGVsc2UgaWYgKHRoaXMubm9kZVZhbHVlKSB7CiAgICAgIGJ1ZmZlci5wdXNoKGA+JHsoMCwgX2NvcmVfdXRpbHMuZW5jb2RlVG9YbWxTdHJpbmcpKHRoaXMubm9kZVZhbHVlKX08LyR7dGhpcy5ub2RlTmFtZX0+YCk7CiAgICB9IGVsc2UgewogICAgICBidWZmZXIucHVzaCgiLz4iKTsKICAgIH0KICB9Cn0KZXhwb3J0cy5TaW1wbGVET01Ob2RlID0gU2ltcGxlRE9NTm9kZTsKY2xhc3MgU2ltcGxlWE1MUGFyc2VyIGV4dGVuZHMgWE1MUGFyc2VyQmFzZSB7CiAgY29uc3RydWN0b3IoX3JlZikgewogICAgbGV0IHsKICAgICAgaGFzQXR0cmlidXRlcyA9IGZhbHNlLAogICAgICBsb3dlckNhc2VOYW1lID0gZmFsc2UKICAgIH0gPSBfcmVmOwogICAgc3VwZXIoKTsKICAgIHRoaXMuX2N1cnJlbnRGcmFnbWVudCA9IG51bGw7CiAgICB0aGlzLl9zdGFjayA9IG51bGw7CiAgICB0aGlzLl9lcnJvckNvZGUgPSBYTUxQYXJzZXJFcnJvckNvZGUuTm9FcnJvcjsKICAgIHRoaXMuX2hhc0F0dHJpYnV0ZXMgPSBoYXNBdHRyaWJ1dGVzOwogICAgdGhpcy5fbG93ZXJDYXNlTmFtZSA9IGxvd2VyQ2FzZU5hbWU7CiAgfQogIHBhcnNlRnJvbVN0cmluZyhkYXRhKSB7CiAgICB0aGlzLl9jdXJyZW50RnJhZ21lbnQgPSBbXTsKICAgIHRoaXMuX3N0YWNrID0gW107CiAgICB0aGlzLl9lcnJvckNvZGUgPSBYTUxQYXJzZXJFcnJvckNvZGUuTm9FcnJvcjsKICAgIHRoaXMucGFyc2VYbWwoZGF0YSk7CiAgICBpZiAodGhpcy5fZXJyb3JDb2RlICE9PSBYTUxQYXJzZXJFcnJvckNvZGUuTm9FcnJvcikgewogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfQogICAgY29uc3QgW2RvY3VtZW50RWxlbWVudF0gPSB0aGlzLl9jdXJyZW50RnJhZ21lbnQ7CiAgICBpZiAoIWRvY3VtZW50RWxlbWVudCkgewogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfQogICAgcmV0dXJuIHsKICAgICAgZG9jdW1lbnRFbGVtZW50CiAgICB9OwogIH0KICBvblRleHQodGV4dCkgewogICAgaWYgKGlzV2hpdGVzcGFjZVN0cmluZyh0ZXh0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBub2RlID0gbmV3IFNpbXBsZURPTU5vZGUoIiN0ZXh0IiwgdGV4dCk7CiAgICB0aGlzLl9jdXJyZW50RnJhZ21lbnQucHVzaChub2RlKTsKICB9CiAgb25DZGF0YSh0ZXh0KSB7CiAgICBjb25zdCBub2RlID0gbmV3IFNpbXBsZURPTU5vZGUoIiN0ZXh0IiwgdGV4dCk7CiAgICB0aGlzLl9jdXJyZW50RnJhZ21lbnQucHVzaChub2RlKTsKICB9CiAgb25CZWdpbkVsZW1lbnQobmFtZSwgYXR0cmlidXRlcywgaXNFbXB0eSkgewogICAgaWYgKHRoaXMuX2xvd2VyQ2FzZU5hbWUpIHsKICAgICAgbmFtZSA9IG5hbWUudG9Mb3dlckNhc2UoKTsKICAgIH0KICAgIGNvbnN0IG5vZGUgPSBuZXcgU2ltcGxlRE9NTm9kZShuYW1lKTsKICAgIG5vZGUuY2hpbGROb2RlcyA9IFtdOwogICAgaWYgKHRoaXMuX2hhc0F0dHJpYnV0ZXMpIHsKICAgICAgbm9kZS5hdHRyaWJ1dGVzID0gYXR0cmlidXRlczsKICAgIH0KICAgIHRoaXMuX2N1cnJlbnRGcmFnbWVudC5wdXNoKG5vZGUpOwogICAgaWYgKGlzRW1wdHkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5fc3RhY2sucHVzaCh0aGlzLl9jdXJyZW50RnJhZ21lbnQpOwogICAgdGhpcy5fY3VycmVudEZyYWdtZW50ID0gbm9kZS5jaGlsZE5vZGVzOwogIH0KICBvbkVuZEVsZW1lbnQobmFtZSkgewogICAgdGhpcy5fY3VycmVudEZyYWdtZW50ID0gdGhpcy5fc3RhY2sucG9wKCkgfHwgW107CiAgICBjb25zdCBsYXN0RWxlbWVudCA9IHRoaXMuX2N1cnJlbnRGcmFnbWVudC5hdCgtMSk7CiAgICBpZiAoIWxhc3RFbGVtZW50KSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgZm9yIChjb25zdCBjaGlsZE5vZGUgb2YgbGFzdEVsZW1lbnQuY2hpbGROb2RlcykgewogICAgICBjaGlsZE5vZGUucGFyZW50Tm9kZSA9IGxhc3RFbGVtZW50OwogICAgfQogICAgcmV0dXJuIGxhc3RFbGVtZW50OwogIH0KICBvbkVycm9yKGNvZGUpIHsKICAgIHRoaXMuX2Vycm9yQ29kZSA9IGNvZGU7CiAgfQp9CmV4cG9ydHMuU2ltcGxlWE1MUGFyc2VyID0gU2ltcGxlWE1MUGFyc2VyOwoKLyoqKi8gfSksCi8qIDIwMiAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuY2FsY3VsYXRlU0hBMjU2ID0gZXhwb3J0cy5jYWxjdWxhdGVNRDUgPSBleHBvcnRzLlBERjIwID0gZXhwb3J0cy5QREYxNyA9IGV4cG9ydHMuQ2lwaGVyVHJhbnNmb3JtRmFjdG9yeSA9IGV4cG9ydHMuQVJDRm91ckNpcGhlciA9IGV4cG9ydHMuQUVTMjU2Q2lwaGVyID0gZXhwb3J0cy5BRVMxMjhDaXBoZXIgPSB2b2lkIDA7CmV4cG9ydHMuY2FsY3VsYXRlU0hBMzg0ID0gY2FsY3VsYXRlU0hBMzg0OwpleHBvcnRzLmNhbGN1bGF0ZVNIQTUxMiA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9wcmltaXRpdmVzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDApOwp2YXIgX2RlY3J5cHRfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygyMDMpOwpjbGFzcyBBUkNGb3VyQ2lwaGVyIHsKICBjb25zdHJ1Y3RvcihrZXkpIHsKICAgIHRoaXMuYSA9IDA7CiAgICB0aGlzLmIgPSAwOwogICAgY29uc3QgcyA9IG5ldyBVaW50OEFycmF5KDI1Nik7CiAgICBjb25zdCBrZXlMZW5ndGggPSBrZXkubGVuZ3RoOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCAyNTY7ICsraSkgewogICAgICBzW2ldID0gaTsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwLCBqID0gMDsgaSA8IDI1NjsgKytpKSB7CiAgICAgIGNvbnN0IHRtcCA9IHNbaV07CiAgICAgIGogPSBqICsgdG1wICsga2V5W2kgJSBrZXlMZW5ndGhdICYgMHhmZjsKICAgICAgc1tpXSA9IHNbal07CiAgICAgIHNbal0gPSB0bXA7CiAgICB9CiAgICB0aGlzLnMgPSBzOwogIH0KICBlbmNyeXB0QmxvY2soZGF0YSkgewogICAgbGV0IGEgPSB0aGlzLmEsCiAgICAgIGIgPSB0aGlzLmI7CiAgICBjb25zdCBzID0gdGhpcy5zOwogICAgY29uc3QgbiA9IGRhdGEubGVuZ3RoOwogICAgY29uc3Qgb3V0cHV0ID0gbmV3IFVpbnQ4QXJyYXkobik7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG47ICsraSkgewogICAgICBhID0gYSArIDEgJiAweGZmOwogICAgICBjb25zdCB0bXAgPSBzW2FdOwogICAgICBiID0gYiArIHRtcCAmIDB4ZmY7CiAgICAgIGNvbnN0IHRtcDIgPSBzW2JdOwogICAgICBzW2FdID0gdG1wMjsKICAgICAgc1tiXSA9IHRtcDsKICAgICAgb3V0cHV0W2ldID0gZGF0YVtpXSBeIHNbdG1wICsgdG1wMiAmIDB4ZmZdOwogICAgfQogICAgdGhpcy5hID0gYTsKICAgIHRoaXMuYiA9IGI7CiAgICByZXR1cm4gb3V0cHV0OwogIH0KICBkZWNyeXB0QmxvY2soZGF0YSkgewogICAgcmV0dXJuIHRoaXMuZW5jcnlwdEJsb2NrKGRhdGEpOwogIH0KICBlbmNyeXB0KGRhdGEpIHsKICAgIHJldHVybiB0aGlzLmVuY3J5cHRCbG9jayhkYXRhKTsKICB9Cn0KZXhwb3J0cy5BUkNGb3VyQ2lwaGVyID0gQVJDRm91ckNpcGhlcjsKY29uc3QgY2FsY3VsYXRlTUQ1ID0gZnVuY3Rpb24gY2FsY3VsYXRlTUQ1Q2xvc3VyZSgpIHsKICBjb25zdCByID0gbmV3IFVpbnQ4QXJyYXkoWzcsIDEyLCAxNywgMjIsIDcsIDEyLCAxNywgMjIsIDcsIDEyLCAxNywgMjIsIDcsIDEyLCAxNywgMjIsIDUsIDksIDE0LCAyMCwgNSwgOSwgMTQsIDIwLCA1LCA5LCAxNCwgMjAsIDUsIDksIDE0LCAyMCwgNCwgMTEsIDE2LCAyMywgNCwgMTEsIDE2LCAyMywgNCwgMTEsIDE2LCAyMywgNCwgMTEsIDE2LCAyMywgNiwgMTAsIDE1LCAyMSwgNiwgMTAsIDE1LCAyMSwgNiwgMTAsIDE1LCAyMSwgNiwgMTAsIDE1LCAyMV0pOwogIGNvbnN0IGsgPSBuZXcgSW50MzJBcnJheShbLTY4MDg3NjkzNiwgLTM4OTU2NDU4NiwgNjA2MTA1ODE5LCAtMTA0NDUyNTMzMCwgLTE3NjQxODg5NywgMTIwMDA4MDQyNiwgLTE0NzMyMzEzNDEsIC00NTcwNTk4MywgMTc3MDAzNTQxNiwgLTE5NTg0MTQ0MTcsIC00MjA2MywgLTE5OTA0MDQxNjIsIDE4MDQ2MDM2ODIsIC00MDM0MTEwMSwgLTE1MDIwMDIyOTAsIDEyMzY1MzUzMjksIC0xNjU3OTY1MTAsIC0xMDY5NTAxNjMyLCA2NDM3MTc3MTMsIC0zNzM4OTczMDIsIC03MDE1NTg2OTEsIDM4MDE2MDgzLCAtNjYwNDc4MzM1LCAtNDA1NTM3ODQ4LCA1Njg0NDY0MzgsIC0xMDE5ODAzNjkwLCAtMTg3MzYzOTYxLCAxMTYzNTMxNTAxLCAtMTQ0NDY4MTQ2NywgLTUxNDAzNzg0LCAxNzM1MzI4NDczLCAtMTkyNjYwNzczNCwgLTM3ODU1OCwgLTIwMjI1NzQ0NjMsIDE4MzkwMzA1NjIsIC0zNTMwOTU1NiwgLTE1MzA5OTIwNjAsIDEyNzI4OTMzNTMsIC0xNTU0OTc2MzIsIC0xMDk0NzMwNjQwLCA2ODEyNzkxNzQsIC0zNTg1MzcyMjIsIC03MjI1MjE5NzksIDc2MDI5MTg5LCAtNjQwMzY0NDg3LCAtNDIxODE1ODM1LCA1MzA3NDI1MjAsIC05OTUzMzg2NTEsIC0xOTg2MzA4NDQsIDExMjY4OTE0MTUsIC0xNDE2MzU0OTA1LCAtNTc0MzQwNTUsIDE3MDA0ODU1NzEsIC0xODk0OTg2NjA2LCAtMTA1MTUyMywgLTIwNTQ5MjI3OTksIDE4NzMzMTMzNTksIC0zMDYxMTc0NCwgLTE1NjAxOTgzODAsIDEzMDkxNTE2NDksIC0xNDU1MjMwNzAsIC0xMTIwMjEwMzc5LCA3MTg3ODcyNTksIC0zNDM0ODU1NTFdKTsKICBmdW5jdGlvbiBoYXNoKGRhdGEsIG9mZnNldCwgbGVuZ3RoKSB7CiAgICBsZXQgaDAgPSAxNzMyNTg0MTkzLAogICAgICBoMSA9IC0yNzE3MzM4NzksCiAgICAgIGgyID0gLTE3MzI1ODQxOTQsCiAgICAgIGgzID0gMjcxNzMzODc4OwogICAgY29uc3QgcGFkZGVkTGVuZ3RoID0gbGVuZ3RoICsgNzIgJiB+NjM7CiAgICBjb25zdCBwYWRkZWQgPSBuZXcgVWludDhBcnJheShwYWRkZWRMZW5ndGgpOwogICAgbGV0IGksIGo7CiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgcGFkZGVkW2ldID0gZGF0YVtvZmZzZXQrK107CiAgICB9CiAgICBwYWRkZWRbaSsrXSA9IDB4ODA7CiAgICBjb25zdCBuID0gcGFkZGVkTGVuZ3RoIC0gODsKICAgIHdoaWxlIChpIDwgbikgewogICAgICBwYWRkZWRbaSsrXSA9IDA7CiAgICB9CiAgICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA8PCAzICYgMHhmZjsKICAgIHBhZGRlZFtpKytdID0gbGVuZ3RoID4+IDUgJiAweGZmOwogICAgcGFkZGVkW2krK10gPSBsZW5ndGggPj4gMTMgJiAweGZmOwogICAgcGFkZGVkW2krK10gPSBsZW5ndGggPj4gMjEgJiAweGZmOwogICAgcGFkZGVkW2krK10gPSBsZW5ndGggPj4+IDI5ICYgMHhmZjsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIGNvbnN0IHcgPSBuZXcgSW50MzJBcnJheSgxNik7CiAgICBmb3IgKGkgPSAwOyBpIDwgcGFkZGVkTGVuZ3RoOykgewogICAgICBmb3IgKGogPSAwOyBqIDwgMTY7ICsraiwgaSArPSA0KSB7CiAgICAgICAgd1tqXSA9IHBhZGRlZFtpXSB8IHBhZGRlZFtpICsgMV0gPDwgOCB8IHBhZGRlZFtpICsgMl0gPDwgMTYgfCBwYWRkZWRbaSArIDNdIDw8IDI0OwogICAgICB9CiAgICAgIGxldCBhID0gaDAsCiAgICAgICAgYiA9IGgxLAogICAgICAgIGMgPSBoMiwKICAgICAgICBkID0gaDMsCiAgICAgICAgZiwKICAgICAgICBnOwogICAgICBmb3IgKGogPSAwOyBqIDwgNjQ7ICsraikgewogICAgICAgIGlmIChqIDwgMTYpIHsKICAgICAgICAgIGYgPSBiICYgYyB8IH5iICYgZDsKICAgICAgICAgIGcgPSBqOwogICAgICAgIH0gZWxzZSBpZiAoaiA8IDMyKSB7CiAgICAgICAgICBmID0gZCAmIGIgfCB+ZCAmIGM7CiAgICAgICAgICBnID0gNSAqIGogKyAxICYgMTU7CiAgICAgICAgfSBlbHNlIGlmIChqIDwgNDgpIHsKICAgICAgICAgIGYgPSBiIF4gYyBeIGQ7CiAgICAgICAgICBnID0gMyAqIGogKyA1ICYgMTU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGYgPSBjIF4gKGIgfCB+ZCk7CiAgICAgICAgICBnID0gNyAqIGogJiAxNTsKICAgICAgICB9CiAgICAgICAgY29uc3QgdG1wID0gZCwKICAgICAgICAgIHJvdGF0ZUFyZyA9IGEgKyBmICsga1tqXSArIHdbZ10gfCAwLAogICAgICAgICAgcm90YXRlID0gcltqXTsKICAgICAgICBkID0gYzsKICAgICAgICBjID0gYjsKICAgICAgICBiID0gYiArIChyb3RhdGVBcmcgPDwgcm90YXRlIHwgcm90YXRlQXJnID4+PiAzMiAtIHJvdGF0ZSkgfCAwOwogICAgICAgIGEgPSB0bXA7CiAgICAgIH0KICAgICAgaDAgPSBoMCArIGEgfCAwOwogICAgICBoMSA9IGgxICsgYiB8IDA7CiAgICAgIGgyID0gaDIgKyBjIHwgMDsKICAgICAgaDMgPSBoMyArIGQgfCAwOwogICAgfQogICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFtoMCAmIDB4RkYsIGgwID4+IDggJiAweEZGLCBoMCA+PiAxNiAmIDB4RkYsIGgwID4+PiAyNCAmIDB4RkYsIGgxICYgMHhGRiwgaDEgPj4gOCAmIDB4RkYsIGgxID4+IDE2ICYgMHhGRiwgaDEgPj4+IDI0ICYgMHhGRiwgaDIgJiAweEZGLCBoMiA+PiA4ICYgMHhGRiwgaDIgPj4gMTYgJiAweEZGLCBoMiA+Pj4gMjQgJiAweEZGLCBoMyAmIDB4RkYsIGgzID4+IDggJiAweEZGLCBoMyA+PiAxNiAmIDB4RkYsIGgzID4+PiAyNCAmIDB4RkZdKTsKICB9CiAgcmV0dXJuIGhhc2g7Cn0oKTsKZXhwb3J0cy5jYWxjdWxhdGVNRDUgPSBjYWxjdWxhdGVNRDU7CmNsYXNzIFdvcmQ2NCB7CiAgY29uc3RydWN0b3IoaGlnaEludGVnZXIsIGxvd0ludGVnZXIpIHsKICAgIHRoaXMuaGlnaCA9IGhpZ2hJbnRlZ2VyIHwgMDsKICAgIHRoaXMubG93ID0gbG93SW50ZWdlciB8IDA7CiAgfQogIGFuZCh3b3JkKSB7CiAgICB0aGlzLmhpZ2ggJj0gd29yZC5oaWdoOwogICAgdGhpcy5sb3cgJj0gd29yZC5sb3c7CiAgfQogIHhvcih3b3JkKSB7CiAgICB0aGlzLmhpZ2ggXj0gd29yZC5oaWdoOwogICAgdGhpcy5sb3cgXj0gd29yZC5sb3c7CiAgfQogIG9yKHdvcmQpIHsKICAgIHRoaXMuaGlnaCB8PSB3b3JkLmhpZ2g7CiAgICB0aGlzLmxvdyB8PSB3b3JkLmxvdzsKICB9CiAgc2hpZnRSaWdodChwbGFjZXMpIHsKICAgIGlmIChwbGFjZXMgPj0gMzIpIHsKICAgICAgdGhpcy5sb3cgPSB0aGlzLmhpZ2ggPj4+IHBsYWNlcyAtIDMyIHwgMDsKICAgICAgdGhpcy5oaWdoID0gMDsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMubG93ID0gdGhpcy5sb3cgPj4+IHBsYWNlcyB8IHRoaXMuaGlnaCA8PCAzMiAtIHBsYWNlczsKICAgICAgdGhpcy5oaWdoID0gdGhpcy5oaWdoID4+PiBwbGFjZXMgfCAwOwogICAgfQogIH0KICBzaGlmdExlZnQocGxhY2VzKSB7CiAgICBpZiAocGxhY2VzID49IDMyKSB7CiAgICAgIHRoaXMuaGlnaCA9IHRoaXMubG93IDw8IHBsYWNlcyAtIDMyOwogICAgICB0aGlzLmxvdyA9IDA7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmhpZ2ggPSB0aGlzLmhpZ2ggPDwgcGxhY2VzIHwgdGhpcy5sb3cgPj4+IDMyIC0gcGxhY2VzOwogICAgICB0aGlzLmxvdyA8PD0gcGxhY2VzOwogICAgfQogIH0KICByb3RhdGVSaWdodChwbGFjZXMpIHsKICAgIGxldCBsb3csIGhpZ2g7CiAgICBpZiAocGxhY2VzICYgMzIpIHsKICAgICAgaGlnaCA9IHRoaXMubG93OwogICAgICBsb3cgPSB0aGlzLmhpZ2g7CiAgICB9IGVsc2UgewogICAgICBsb3cgPSB0aGlzLmxvdzsKICAgICAgaGlnaCA9IHRoaXMuaGlnaDsKICAgIH0KICAgIHBsYWNlcyAmPSAzMTsKICAgIHRoaXMubG93ID0gbG93ID4+PiBwbGFjZXMgfCBoaWdoIDw8IDMyIC0gcGxhY2VzOwogICAgdGhpcy5oaWdoID0gaGlnaCA+Pj4gcGxhY2VzIHwgbG93IDw8IDMyIC0gcGxhY2VzOwogIH0KICBub3QoKSB7CiAgICB0aGlzLmhpZ2ggPSB+dGhpcy5oaWdoOwogICAgdGhpcy5sb3cgPSB+dGhpcy5sb3c7CiAgfQogIGFkZCh3b3JkKSB7CiAgICBjb25zdCBsb3dBZGQgPSAodGhpcy5sb3cgPj4+IDApICsgKHdvcmQubG93ID4+PiAwKTsKICAgIGxldCBoaWdoQWRkID0gKHRoaXMuaGlnaCA+Pj4gMCkgKyAod29yZC5oaWdoID4+PiAwKTsKICAgIGlmIChsb3dBZGQgPiAweGZmZmZmZmZmKSB7CiAgICAgIGhpZ2hBZGQgKz0gMTsKICAgIH0KICAgIHRoaXMubG93ID0gbG93QWRkIHwgMDsKICAgIHRoaXMuaGlnaCA9IGhpZ2hBZGQgfCAwOwogIH0KICBjb3B5VG8oYnl0ZXMsIG9mZnNldCkgewogICAgYnl0ZXNbb2Zmc2V0XSA9IHRoaXMuaGlnaCA+Pj4gMjQgJiAweGZmOwogICAgYnl0ZXNbb2Zmc2V0ICsgMV0gPSB0aGlzLmhpZ2ggPj4gMTYgJiAweGZmOwogICAgYnl0ZXNbb2Zmc2V0ICsgMl0gPSB0aGlzLmhpZ2ggPj4gOCAmIDB4ZmY7CiAgICBieXRlc1tvZmZzZXQgKyAzXSA9IHRoaXMuaGlnaCAmIDB4ZmY7CiAgICBieXRlc1tvZmZzZXQgKyA0XSA9IHRoaXMubG93ID4+PiAyNCAmIDB4ZmY7CiAgICBieXRlc1tvZmZzZXQgKyA1XSA9IHRoaXMubG93ID4+IDE2ICYgMHhmZjsKICAgIGJ5dGVzW29mZnNldCArIDZdID0gdGhpcy5sb3cgPj4gOCAmIDB4ZmY7CiAgICBieXRlc1tvZmZzZXQgKyA3XSA9IHRoaXMubG93ICYgMHhmZjsKICB9CiAgYXNzaWduKHdvcmQpIHsKICAgIHRoaXMuaGlnaCA9IHdvcmQuaGlnaDsKICAgIHRoaXMubG93ID0gd29yZC5sb3c7CiAgfQp9CmNvbnN0IGNhbGN1bGF0ZVNIQTI1NiA9IGZ1bmN0aW9uIGNhbGN1bGF0ZVNIQTI1NkNsb3N1cmUoKSB7CiAgZnVuY3Rpb24gcm90cih4LCBuKSB7CiAgICByZXR1cm4geCA+Pj4gbiB8IHggPDwgMzIgLSBuOwogIH0KICBmdW5jdGlvbiBjaCh4LCB5LCB6KSB7CiAgICByZXR1cm4geCAmIHkgXiB+eCAmIHo7CiAgfQogIGZ1bmN0aW9uIG1haih4LCB5LCB6KSB7CiAgICByZXR1cm4geCAmIHkgXiB4ICYgeiBeIHkgJiB6OwogIH0KICBmdW5jdGlvbiBzaWdtYSh4KSB7CiAgICByZXR1cm4gcm90cih4LCAyKSBeIHJvdHIoeCwgMTMpIF4gcm90cih4LCAyMik7CiAgfQogIGZ1bmN0aW9uIHNpZ21hUHJpbWUoeCkgewogICAgcmV0dXJuIHJvdHIoeCwgNikgXiByb3RyKHgsIDExKSBeIHJvdHIoeCwgMjUpOwogIH0KICBmdW5jdGlvbiBsaXR0bGVTaWdtYSh4KSB7CiAgICByZXR1cm4gcm90cih4LCA3KSBeIHJvdHIoeCwgMTgpIF4geCA+Pj4gMzsKICB9CiAgZnVuY3Rpb24gbGl0dGxlU2lnbWFQcmltZSh4KSB7CiAgICByZXR1cm4gcm90cih4LCAxNykgXiByb3RyKHgsIDE5KSBeIHggPj4+IDEwOwogIH0KICBjb25zdCBrID0gWzB4NDI4YTJmOTgsIDB4NzEzNzQ0OTEsIDB4YjVjMGZiY2YsIDB4ZTliNWRiYTUsIDB4Mzk1NmMyNWIsIDB4NTlmMTExZjEsIDB4OTIzZjgyYTQsIDB4YWIxYzVlZDUsIDB4ZDgwN2FhOTgsIDB4MTI4MzViMDEsIDB4MjQzMTg1YmUsIDB4NTUwYzdkYzMsIDB4NzJiZTVkNzQsIDB4ODBkZWIxZmUsIDB4OWJkYzA2YTcsIDB4YzE5YmYxNzQsIDB4ZTQ5YjY5YzEsIDB4ZWZiZTQ3ODYsIDB4MGZjMTlkYzYsIDB4MjQwY2ExY2MsIDB4MmRlOTJjNmYsIDB4NGE3NDg0YWEsIDB4NWNiMGE5ZGMsIDB4NzZmOTg4ZGEsIDB4OTgzZTUxNTIsIDB4YTgzMWM2NmQsIDB4YjAwMzI3YzgsIDB4YmY1OTdmYzcsIDB4YzZlMDBiZjMsIDB4ZDVhNzkxNDcsIDB4MDZjYTYzNTEsIDB4MTQyOTI5NjcsIDB4MjdiNzBhODUsIDB4MmUxYjIxMzgsIDB4NGQyYzZkZmMsIDB4NTMzODBkMTMsIDB4NjUwYTczNTQsIDB4NzY2YTBhYmIsIDB4ODFjMmM5MmUsIDB4OTI3MjJjODUsIDB4YTJiZmU4YTEsIDB4YTgxYTY2NGIsIDB4YzI0YjhiNzAsIDB4Yzc2YzUxYTMsIDB4ZDE5MmU4MTksIDB4ZDY5OTA2MjQsIDB4ZjQwZTM1ODUsIDB4MTA2YWEwNzAsIDB4MTlhNGMxMTYsIDB4MWUzNzZjMDgsIDB4Mjc0ODc3NGMsIDB4MzRiMGJjYjUsIDB4MzkxYzBjYjMsIDB4NGVkOGFhNGEsIDB4NWI5Y2NhNGYsIDB4NjgyZTZmZjMsIDB4NzQ4ZjgyZWUsIDB4NzhhNTYzNmYsIDB4ODRjODc4MTQsIDB4OGNjNzAyMDgsIDB4OTBiZWZmZmEsIDB4YTQ1MDZjZWIsIDB4YmVmOWEzZjcsIDB4YzY3MTc4ZjJdOwogIGZ1bmN0aW9uIGhhc2goZGF0YSwgb2Zmc2V0LCBsZW5ndGgpIHsKICAgIGxldCBoMCA9IDB4NmEwOWU2NjcsCiAgICAgIGgxID0gMHhiYjY3YWU4NSwKICAgICAgaDIgPSAweDNjNmVmMzcyLAogICAgICBoMyA9IDB4YTU0ZmY1M2EsCiAgICAgIGg0ID0gMHg1MTBlNTI3ZiwKICAgICAgaDUgPSAweDliMDU2ODhjLAogICAgICBoNiA9IDB4MWY4M2Q5YWIsCiAgICAgIGg3ID0gMHg1YmUwY2QxOTsKICAgIGNvbnN0IHBhZGRlZExlbmd0aCA9IE1hdGguY2VpbCgobGVuZ3RoICsgOSkgLyA2NCkgKiA2NDsKICAgIGNvbnN0IHBhZGRlZCA9IG5ldyBVaW50OEFycmF5KHBhZGRlZExlbmd0aCk7CiAgICBsZXQgaSwgajsKICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICBwYWRkZWRbaV0gPSBkYXRhW29mZnNldCsrXTsKICAgIH0KICAgIHBhZGRlZFtpKytdID0gMHg4MDsKICAgIGNvbnN0IG4gPSBwYWRkZWRMZW5ndGggLSA4OwogICAgd2hpbGUgKGkgPCBuKSB7CiAgICAgIHBhZGRlZFtpKytdID0gMDsKICAgIH0KICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gbGVuZ3RoID4+PiAyOSAmIDB4ZmY7CiAgICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+PiAyMSAmIDB4ZmY7CiAgICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+PiAxMyAmIDB4ZmY7CiAgICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+PiA1ICYgMHhmZjsKICAgIHBhZGRlZFtpKytdID0gbGVuZ3RoIDw8IDMgJiAweGZmOwogICAgY29uc3QgdyA9IG5ldyBVaW50MzJBcnJheSg2NCk7CiAgICBmb3IgKGkgPSAwOyBpIDwgcGFkZGVkTGVuZ3RoOykgewogICAgICBmb3IgKGogPSAwOyBqIDwgMTY7ICsraikgewogICAgICAgIHdbal0gPSBwYWRkZWRbaV0gPDwgMjQgfCBwYWRkZWRbaSArIDFdIDw8IDE2IHwgcGFkZGVkW2kgKyAyXSA8PCA4IHwgcGFkZGVkW2kgKyAzXTsKICAgICAgICBpICs9IDQ7CiAgICAgIH0KICAgICAgZm9yIChqID0gMTY7IGogPCA2NDsgKytqKSB7CiAgICAgICAgd1tqXSA9IGxpdHRsZVNpZ21hUHJpbWUod1tqIC0gMl0pICsgd1tqIC0gN10gKyBsaXR0bGVTaWdtYSh3W2ogLSAxNV0pICsgd1tqIC0gMTZdIHwgMDsKICAgICAgfQogICAgICBsZXQgYSA9IGgwLAogICAgICAgIGIgPSBoMSwKICAgICAgICBjID0gaDIsCiAgICAgICAgZCA9IGgzLAogICAgICAgIGUgPSBoNCwKICAgICAgICBmID0gaDUsCiAgICAgICAgZyA9IGg2LAogICAgICAgIGggPSBoNywKICAgICAgICB0MSwKICAgICAgICB0MjsKICAgICAgZm9yIChqID0gMDsgaiA8IDY0OyArK2opIHsKICAgICAgICB0MSA9IGggKyBzaWdtYVByaW1lKGUpICsgY2goZSwgZiwgZykgKyBrW2pdICsgd1tqXTsKICAgICAgICB0MiA9IHNpZ21hKGEpICsgbWFqKGEsIGIsIGMpOwogICAgICAgIGggPSBnOwogICAgICAgIGcgPSBmOwogICAgICAgIGYgPSBlOwogICAgICAgIGUgPSBkICsgdDEgfCAwOwogICAgICAgIGQgPSBjOwogICAgICAgIGMgPSBiOwogICAgICAgIGIgPSBhOwogICAgICAgIGEgPSB0MSArIHQyIHwgMDsKICAgICAgfQogICAgICBoMCA9IGgwICsgYSB8IDA7CiAgICAgIGgxID0gaDEgKyBiIHwgMDsKICAgICAgaDIgPSBoMiArIGMgfCAwOwogICAgICBoMyA9IGgzICsgZCB8IDA7CiAgICAgIGg0ID0gaDQgKyBlIHwgMDsKICAgICAgaDUgPSBoNSArIGYgfCAwOwogICAgICBoNiA9IGg2ICsgZyB8IDA7CiAgICAgIGg3ID0gaDcgKyBoIHwgMDsKICAgIH0KICAgIHJldHVybiBuZXcgVWludDhBcnJheShbaDAgPj4gMjQgJiAweEZGLCBoMCA+PiAxNiAmIDB4RkYsIGgwID4+IDggJiAweEZGLCBoMCAmIDB4RkYsIGgxID4+IDI0ICYgMHhGRiwgaDEgPj4gMTYgJiAweEZGLCBoMSA+PiA4ICYgMHhGRiwgaDEgJiAweEZGLCBoMiA+PiAyNCAmIDB4RkYsIGgyID4+IDE2ICYgMHhGRiwgaDIgPj4gOCAmIDB4RkYsIGgyICYgMHhGRiwgaDMgPj4gMjQgJiAweEZGLCBoMyA+PiAxNiAmIDB4RkYsIGgzID4+IDggJiAweEZGLCBoMyAmIDB4RkYsIGg0ID4+IDI0ICYgMHhGRiwgaDQgPj4gMTYgJiAweEZGLCBoNCA+PiA4ICYgMHhGRiwgaDQgJiAweEZGLCBoNSA+PiAyNCAmIDB4RkYsIGg1ID4+IDE2ICYgMHhGRiwgaDUgPj4gOCAmIDB4RkYsIGg1ICYgMHhGRiwgaDYgPj4gMjQgJiAweEZGLCBoNiA+PiAxNiAmIDB4RkYsIGg2ID4+IDggJiAweEZGLCBoNiAmIDB4RkYsIGg3ID4+IDI0ICYgMHhGRiwgaDcgPj4gMTYgJiAweEZGLCBoNyA+PiA4ICYgMHhGRiwgaDcgJiAweEZGXSk7CiAgfQogIHJldHVybiBoYXNoOwp9KCk7CmV4cG9ydHMuY2FsY3VsYXRlU0hBMjU2ID0gY2FsY3VsYXRlU0hBMjU2Owpjb25zdCBjYWxjdWxhdGVTSEE1MTIgPSBmdW5jdGlvbiBjYWxjdWxhdGVTSEE1MTJDbG9zdXJlKCkgewogIGZ1bmN0aW9uIGNoKHJlc3VsdCwgeCwgeSwgeiwgdG1wKSB7CiAgICByZXN1bHQuYXNzaWduKHgpOwogICAgcmVzdWx0LmFuZCh5KTsKICAgIHRtcC5hc3NpZ24oeCk7CiAgICB0bXAubm90KCk7CiAgICB0bXAuYW5kKHopOwogICAgcmVzdWx0Lnhvcih0bXApOwogIH0KICBmdW5jdGlvbiBtYWoocmVzdWx0LCB4LCB5LCB6LCB0bXApIHsKICAgIHJlc3VsdC5hc3NpZ24oeCk7CiAgICByZXN1bHQuYW5kKHkpOwogICAgdG1wLmFzc2lnbih4KTsKICAgIHRtcC5hbmQoeik7CiAgICByZXN1bHQueG9yKHRtcCk7CiAgICB0bXAuYXNzaWduKHkpOwogICAgdG1wLmFuZCh6KTsKICAgIHJlc3VsdC54b3IodG1wKTsKICB9CiAgZnVuY3Rpb24gc2lnbWEocmVzdWx0LCB4LCB0bXApIHsKICAgIHJlc3VsdC5hc3NpZ24oeCk7CiAgICByZXN1bHQucm90YXRlUmlnaHQoMjgpOwogICAgdG1wLmFzc2lnbih4KTsKICAgIHRtcC5yb3RhdGVSaWdodCgzNCk7CiAgICByZXN1bHQueG9yKHRtcCk7CiAgICB0bXAuYXNzaWduKHgpOwogICAgdG1wLnJvdGF0ZVJpZ2h0KDM5KTsKICAgIHJlc3VsdC54b3IodG1wKTsKICB9CiAgZnVuY3Rpb24gc2lnbWFQcmltZShyZXN1bHQsIHgsIHRtcCkgewogICAgcmVzdWx0LmFzc2lnbih4KTsKICAgIHJlc3VsdC5yb3RhdGVSaWdodCgxNCk7CiAgICB0bXAuYXNzaWduKHgpOwogICAgdG1wLnJvdGF0ZVJpZ2h0KDE4KTsKICAgIHJlc3VsdC54b3IodG1wKTsKICAgIHRtcC5hc3NpZ24oeCk7CiAgICB0bXAucm90YXRlUmlnaHQoNDEpOwogICAgcmVzdWx0Lnhvcih0bXApOwogIH0KICBmdW5jdGlvbiBsaXR0bGVTaWdtYShyZXN1bHQsIHgsIHRtcCkgewogICAgcmVzdWx0LmFzc2lnbih4KTsKICAgIHJlc3VsdC5yb3RhdGVSaWdodCgxKTsKICAgIHRtcC5hc3NpZ24oeCk7CiAgICB0bXAucm90YXRlUmlnaHQoOCk7CiAgICByZXN1bHQueG9yKHRtcCk7CiAgICB0bXAuYXNzaWduKHgpOwogICAgdG1wLnNoaWZ0UmlnaHQoNyk7CiAgICByZXN1bHQueG9yKHRtcCk7CiAgfQogIGZ1bmN0aW9uIGxpdHRsZVNpZ21hUHJpbWUocmVzdWx0LCB4LCB0bXApIHsKICAgIHJlc3VsdC5hc3NpZ24oeCk7CiAgICByZXN1bHQucm90YXRlUmlnaHQoMTkpOwogICAgdG1wLmFzc2lnbih4KTsKICAgIHRtcC5yb3RhdGVSaWdodCg2MSk7CiAgICByZXN1bHQueG9yKHRtcCk7CiAgICB0bXAuYXNzaWduKHgpOwogICAgdG1wLnNoaWZ0UmlnaHQoNik7CiAgICByZXN1bHQueG9yKHRtcCk7CiAgfQogIGNvbnN0IGsgPSBbbmV3IFdvcmQ2NCgweDQyOGEyZjk4LCAweGQ3MjhhZTIyKSwgbmV3IFdvcmQ2NCgweDcxMzc0NDkxLCAweDIzZWY2NWNkKSwgbmV3IFdvcmQ2NCgweGI1YzBmYmNmLCAweGVjNGQzYjJmKSwgbmV3IFdvcmQ2NCgweGU5YjVkYmE1LCAweDgxODlkYmJjKSwgbmV3IFdvcmQ2NCgweDM5NTZjMjViLCAweGYzNDhiNTM4KSwgbmV3IFdvcmQ2NCgweDU5ZjExMWYxLCAweGI2MDVkMDE5KSwgbmV3IFdvcmQ2NCgweDkyM2Y4MmE0LCAweGFmMTk0ZjliKSwgbmV3IFdvcmQ2NCgweGFiMWM1ZWQ1LCAweGRhNmQ4MTE4KSwgbmV3IFdvcmQ2NCgweGQ4MDdhYTk4LCAweGEzMDMwMjQyKSwgbmV3IFdvcmQ2NCgweDEyODM1YjAxLCAweDQ1NzA2ZmJlKSwgbmV3IFdvcmQ2NCgweDI0MzE4NWJlLCAweDRlZTRiMjhjKSwgbmV3IFdvcmQ2NCgweDU1MGM3ZGMzLCAweGQ1ZmZiNGUyKSwgbmV3IFdvcmQ2NCgweDcyYmU1ZDc0LCAweGYyN2I4OTZmKSwgbmV3IFdvcmQ2NCgweDgwZGViMWZlLCAweDNiMTY5NmIxKSwgbmV3IFdvcmQ2NCgweDliZGMwNmE3LCAweDI1YzcxMjM1KSwgbmV3IFdvcmQ2NCgweGMxOWJmMTc0LCAweGNmNjkyNjk0KSwgbmV3IFdvcmQ2NCgweGU0OWI2OWMxLCAweDllZjE0YWQyKSwgbmV3IFdvcmQ2NCgweGVmYmU0Nzg2LCAweDM4NGYyNWUzKSwgbmV3IFdvcmQ2NCgweDBmYzE5ZGM2LCAweDhiOGNkNWI1KSwgbmV3IFdvcmQ2NCgweDI0MGNhMWNjLCAweDc3YWM5YzY1KSwgbmV3IFdvcmQ2NCgweDJkZTkyYzZmLCAweDU5MmIwMjc1KSwgbmV3IFdvcmQ2NCgweDRhNzQ4NGFhLCAweDZlYTZlNDgzKSwgbmV3IFdvcmQ2NCgweDVjYjBhOWRjLCAweGJkNDFmYmQ0KSwgbmV3IFdvcmQ2NCgweDc2Zjk4OGRhLCAweDgzMTE1M2I1KSwgbmV3IFdvcmQ2NCgweDk4M2U1MTUyLCAweGVlNjZkZmFiKSwgbmV3IFdvcmQ2NCgweGE4MzFjNjZkLCAweDJkYjQzMjEwKSwgbmV3IFdvcmQ2NCgweGIwMDMyN2M4LCAweDk4ZmIyMTNmKSwgbmV3IFdvcmQ2NCgweGJmNTk3ZmM3LCAweGJlZWYwZWU0KSwgbmV3IFdvcmQ2NCgweGM2ZTAwYmYzLCAweDNkYTg4ZmMyKSwgbmV3IFdvcmQ2NCgweGQ1YTc5MTQ3LCAweDkzMGFhNzI1KSwgbmV3IFdvcmQ2NCgweDA2Y2E2MzUxLCAweGUwMDM4MjZmKSwgbmV3IFdvcmQ2NCgweDE0MjkyOTY3LCAweDBhMGU2ZTcwKSwgbmV3IFdvcmQ2NCgweDI3YjcwYTg1LCAweDQ2ZDIyZmZjKSwgbmV3IFdvcmQ2NCgweDJlMWIyMTM4LCAweDVjMjZjOTI2KSwgbmV3IFdvcmQ2NCgweDRkMmM2ZGZjLCAweDVhYzQyYWVkKSwgbmV3IFdvcmQ2NCgweDUzMzgwZDEzLCAweDlkOTViM2RmKSwgbmV3IFdvcmQ2NCgweDY1MGE3MzU0LCAweDhiYWY2M2RlKSwgbmV3IFdvcmQ2NCgweDc2NmEwYWJiLCAweDNjNzdiMmE4KSwgbmV3IFdvcmQ2NCgweDgxYzJjOTJlLCAweDQ3ZWRhZWU2KSwgbmV3IFdvcmQ2NCgweDkyNzIyYzg1LCAweDE0ODIzNTNiKSwgbmV3IFdvcmQ2NCgweGEyYmZlOGExLCAweDRjZjEwMzY0KSwgbmV3IFdvcmQ2NCgweGE4MWE2NjRiLCAweGJjNDIzMDAxKSwgbmV3IFdvcmQ2NCgweGMyNGI4YjcwLCAweGQwZjg5NzkxKSwgbmV3IFdvcmQ2NCgweGM3NmM1MWEzLCAweDA2NTRiZTMwKSwgbmV3IFdvcmQ2NCgweGQxOTJlODE5LCAweGQ2ZWY1MjE4KSwgbmV3IFdvcmQ2NCgweGQ2OTkwNjI0LCAweDU1NjVhOTEwKSwgbmV3IFdvcmQ2NCgweGY0MGUzNTg1LCAweDU3NzEyMDJhKSwgbmV3IFdvcmQ2NCgweDEwNmFhMDcwLCAweDMyYmJkMWI4KSwgbmV3IFdvcmQ2NCgweDE5YTRjMTE2LCAweGI4ZDJkMGM4KSwgbmV3IFdvcmQ2NCgweDFlMzc2YzA4LCAweDUxNDFhYjUzKSwgbmV3IFdvcmQ2NCgweDI3NDg3NzRjLCAweGRmOGVlYjk5KSwgbmV3IFdvcmQ2NCgweDM0YjBiY2I1LCAweGUxOWI0OGE4KSwgbmV3IFdvcmQ2NCgweDM5MWMwY2IzLCAweGM1Yzk1YTYzKSwgbmV3IFdvcmQ2NCgweDRlZDhhYTRhLCAweGUzNDE4YWNiKSwgbmV3IFdvcmQ2NCgweDViOWNjYTRmLCAweDc3NjNlMzczKSwgbmV3IFdvcmQ2NCgweDY4MmU2ZmYzLCAweGQ2YjJiOGEzKSwgbmV3IFdvcmQ2NCgweDc0OGY4MmVlLCAweDVkZWZiMmZjKSwgbmV3IFdvcmQ2NCgweDc4YTU2MzZmLCAweDQzMTcyZjYwKSwgbmV3IFdvcmQ2NCgweDg0Yzg3ODE0LCAweGExZjBhYjcyKSwgbmV3IFdvcmQ2NCgweDhjYzcwMjA4LCAweDFhNjQzOWVjKSwgbmV3IFdvcmQ2NCgweDkwYmVmZmZhLCAweDIzNjMxZTI4KSwgbmV3IFdvcmQ2NCgweGE0NTA2Y2ViLCAweGRlODJiZGU5KSwgbmV3IFdvcmQ2NCgweGJlZjlhM2Y3LCAweGIyYzY3OTE1KSwgbmV3IFdvcmQ2NCgweGM2NzE3OGYyLCAweGUzNzI1MzJiKSwgbmV3IFdvcmQ2NCgweGNhMjczZWNlLCAweGVhMjY2MTljKSwgbmV3IFdvcmQ2NCgweGQxODZiOGM3LCAweDIxYzBjMjA3KSwgbmV3IFdvcmQ2NCgweGVhZGE3ZGQ2LCAweGNkZTBlYjFlKSwgbmV3IFdvcmQ2NCgweGY1N2Q0ZjdmLCAweGVlNmVkMTc4KSwgbmV3IFdvcmQ2NCgweDA2ZjA2N2FhLCAweDcyMTc2ZmJhKSwgbmV3IFdvcmQ2NCgweDBhNjM3ZGM1LCAweGEyYzg5OGE2KSwgbmV3IFdvcmQ2NCgweDExM2Y5ODA0LCAweGJlZjkwZGFlKSwgbmV3IFdvcmQ2NCgweDFiNzEwYjM1LCAweDEzMWM0NzFiKSwgbmV3IFdvcmQ2NCgweDI4ZGI3N2Y1LCAweDIzMDQ3ZDg0KSwgbmV3IFdvcmQ2NCgweDMyY2FhYjdiLCAweDQwYzcyNDkzKSwgbmV3IFdvcmQ2NCgweDNjOWViZTBhLCAweDE1YzliZWJjKSwgbmV3IFdvcmQ2NCgweDQzMWQ2N2M0LCAweDljMTAwZDRjKSwgbmV3IFdvcmQ2NCgweDRjYzVkNGJlLCAweGNiM2U0MmI2KSwgbmV3IFdvcmQ2NCgweDU5N2YyOTljLCAweGZjNjU3ZTJhKSwgbmV3IFdvcmQ2NCgweDVmY2I2ZmFiLCAweDNhZDZmYWVjKSwgbmV3IFdvcmQ2NCgweDZjNDQxOThjLCAweDRhNDc1ODE3KV07CiAgZnVuY3Rpb24gaGFzaChkYXRhLCBvZmZzZXQsIGxlbmd0aCkgewogICAgbGV0IG1vZGUzODQgPSBhcmd1bWVudHMubGVuZ3RoID4gMyAmJiBhcmd1bWVudHNbM10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1szXSA6IGZhbHNlOwogICAgbGV0IGgwLCBoMSwgaDIsIGgzLCBoNCwgaDUsIGg2LCBoNzsKICAgIGlmICghbW9kZTM4NCkgewogICAgICBoMCA9IG5ldyBXb3JkNjQoMHg2YTA5ZTY2NywgMHhmM2JjYzkwOCk7CiAgICAgIGgxID0gbmV3IFdvcmQ2NCgweGJiNjdhZTg1LCAweDg0Y2FhNzNiKTsKICAgICAgaDIgPSBuZXcgV29yZDY0KDB4M2M2ZWYzNzIsIDB4ZmU5NGY4MmIpOwogICAgICBoMyA9IG5ldyBXb3JkNjQoMHhhNTRmZjUzYSwgMHg1ZjFkMzZmMSk7CiAgICAgIGg0ID0gbmV3IFdvcmQ2NCgweDUxMGU1MjdmLCAweGFkZTY4MmQxKTsKICAgICAgaDUgPSBuZXcgV29yZDY0KDB4OWIwNTY4OGMsIDB4MmIzZTZjMWYpOwogICAgICBoNiA9IG5ldyBXb3JkNjQoMHgxZjgzZDlhYiwgMHhmYjQxYmQ2Yik7CiAgICAgIGg3ID0gbmV3IFdvcmQ2NCgweDViZTBjZDE5LCAweDEzN2UyMTc5KTsKICAgIH0gZWxzZSB7CiAgICAgIGgwID0gbmV3IFdvcmQ2NCgweGNiYmI5ZDVkLCAweGMxMDU5ZWQ4KTsKICAgICAgaDEgPSBuZXcgV29yZDY0KDB4NjI5YTI5MmEsIDB4MzY3Y2Q1MDcpOwogICAgICBoMiA9IG5ldyBXb3JkNjQoMHg5MTU5MDE1YSwgMHgzMDcwZGQxNyk7CiAgICAgIGgzID0gbmV3IFdvcmQ2NCgweDE1MmZlY2Q4LCAweGY3MGU1OTM5KTsKICAgICAgaDQgPSBuZXcgV29yZDY0KDB4NjczMzI2NjcsIDB4ZmZjMDBiMzEpOwogICAgICBoNSA9IG5ldyBXb3JkNjQoMHg4ZWI0NGE4NywgMHg2ODU4MTUxMSk7CiAgICAgIGg2ID0gbmV3IFdvcmQ2NCgweGRiMGMyZTBkLCAweDY0Zjk4ZmE3KTsKICAgICAgaDcgPSBuZXcgV29yZDY0KDB4NDdiNTQ4MWQsIDB4YmVmYTRmYTQpOwogICAgfQogICAgY29uc3QgcGFkZGVkTGVuZ3RoID0gTWF0aC5jZWlsKChsZW5ndGggKyAxNykgLyAxMjgpICogMTI4OwogICAgY29uc3QgcGFkZGVkID0gbmV3IFVpbnQ4QXJyYXkocGFkZGVkTGVuZ3RoKTsKICAgIGxldCBpLCBqOwogICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgIHBhZGRlZFtpXSA9IGRhdGFbb2Zmc2V0KytdOwogICAgfQogICAgcGFkZGVkW2krK10gPSAweDgwOwogICAgY29uc3QgbiA9IHBhZGRlZExlbmd0aCAtIDE2OwogICAgd2hpbGUgKGkgPCBuKSB7CiAgICAgIHBhZGRlZFtpKytdID0gMDsKICAgIH0KICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gMDsKICAgIHBhZGRlZFtpKytdID0gbGVuZ3RoID4+PiAyOSAmIDB4ZmY7CiAgICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+PiAyMSAmIDB4ZmY7CiAgICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+PiAxMyAmIDB4ZmY7CiAgICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+PiA1ICYgMHhmZjsKICAgIHBhZGRlZFtpKytdID0gbGVuZ3RoIDw8IDMgJiAweGZmOwogICAgY29uc3QgdyA9IG5ldyBBcnJheSg4MCk7CiAgICBmb3IgKGkgPSAwOyBpIDwgODA7IGkrKykgewogICAgICB3W2ldID0gbmV3IFdvcmQ2NCgwLCAwKTsKICAgIH0KICAgIGxldCBhID0gbmV3IFdvcmQ2NCgwLCAwKSwKICAgICAgYiA9IG5ldyBXb3JkNjQoMCwgMCksCiAgICAgIGMgPSBuZXcgV29yZDY0KDAsIDApOwogICAgbGV0IGQgPSBuZXcgV29yZDY0KDAsIDApLAogICAgICBlID0gbmV3IFdvcmQ2NCgwLCAwKSwKICAgICAgZiA9IG5ldyBXb3JkNjQoMCwgMCk7CiAgICBsZXQgZyA9IG5ldyBXb3JkNjQoMCwgMCksCiAgICAgIGggPSBuZXcgV29yZDY0KDAsIDApOwogICAgY29uc3QgdDEgPSBuZXcgV29yZDY0KDAsIDApLAogICAgICB0MiA9IG5ldyBXb3JkNjQoMCwgMCk7CiAgICBjb25zdCB0bXAxID0gbmV3IFdvcmQ2NCgwLCAwKSwKICAgICAgdG1wMiA9IG5ldyBXb3JkNjQoMCwgMCk7CiAgICBsZXQgdG1wMzsKICAgIGZvciAoaSA9IDA7IGkgPCBwYWRkZWRMZW5ndGg7KSB7CiAgICAgIGZvciAoaiA9IDA7IGogPCAxNjsgKytqKSB7CiAgICAgICAgd1tqXS5oaWdoID0gcGFkZGVkW2ldIDw8IDI0IHwgcGFkZGVkW2kgKyAxXSA8PCAxNiB8IHBhZGRlZFtpICsgMl0gPDwgOCB8IHBhZGRlZFtpICsgM107CiAgICAgICAgd1tqXS5sb3cgPSBwYWRkZWRbaSArIDRdIDw8IDI0IHwgcGFkZGVkW2kgKyA1XSA8PCAxNiB8IHBhZGRlZFtpICsgNl0gPDwgOCB8IHBhZGRlZFtpICsgN107CiAgICAgICAgaSArPSA4OwogICAgICB9CiAgICAgIGZvciAoaiA9IDE2OyBqIDwgODA7ICsraikgewogICAgICAgIHRtcDMgPSB3W2pdOwogICAgICAgIGxpdHRsZVNpZ21hUHJpbWUodG1wMywgd1tqIC0gMl0sIHRtcDIpOwogICAgICAgIHRtcDMuYWRkKHdbaiAtIDddKTsKICAgICAgICBsaXR0bGVTaWdtYSh0bXAxLCB3W2ogLSAxNV0sIHRtcDIpOwogICAgICAgIHRtcDMuYWRkKHRtcDEpOwogICAgICAgIHRtcDMuYWRkKHdbaiAtIDE2XSk7CiAgICAgIH0KICAgICAgYS5hc3NpZ24oaDApOwogICAgICBiLmFzc2lnbihoMSk7CiAgICAgIGMuYXNzaWduKGgyKTsKICAgICAgZC5hc3NpZ24oaDMpOwogICAgICBlLmFzc2lnbihoNCk7CiAgICAgIGYuYXNzaWduKGg1KTsKICAgICAgZy5hc3NpZ24oaDYpOwogICAgICBoLmFzc2lnbihoNyk7CiAgICAgIGZvciAoaiA9IDA7IGogPCA4MDsgKytqKSB7CiAgICAgICAgdDEuYXNzaWduKGgpOwogICAgICAgIHNpZ21hUHJpbWUodG1wMSwgZSwgdG1wMik7CiAgICAgICAgdDEuYWRkKHRtcDEpOwogICAgICAgIGNoKHRtcDEsIGUsIGYsIGcsIHRtcDIpOwogICAgICAgIHQxLmFkZCh0bXAxKTsKICAgICAgICB0MS5hZGQoa1tqXSk7CiAgICAgICAgdDEuYWRkKHdbal0pOwogICAgICAgIHNpZ21hKHQyLCBhLCB0bXAyKTsKICAgICAgICBtYWoodG1wMSwgYSwgYiwgYywgdG1wMik7CiAgICAgICAgdDIuYWRkKHRtcDEpOwogICAgICAgIHRtcDMgPSBoOwogICAgICAgIGggPSBnOwogICAgICAgIGcgPSBmOwogICAgICAgIGYgPSBlOwogICAgICAgIGQuYWRkKHQxKTsKICAgICAgICBlID0gZDsKICAgICAgICBkID0gYzsKICAgICAgICBjID0gYjsKICAgICAgICBiID0gYTsKICAgICAgICB0bXAzLmFzc2lnbih0MSk7CiAgICAgICAgdG1wMy5hZGQodDIpOwogICAgICAgIGEgPSB0bXAzOwogICAgICB9CiAgICAgIGgwLmFkZChhKTsKICAgICAgaDEuYWRkKGIpOwogICAgICBoMi5hZGQoYyk7CiAgICAgIGgzLmFkZChkKTsKICAgICAgaDQuYWRkKGUpOwogICAgICBoNS5hZGQoZik7CiAgICAgIGg2LmFkZChnKTsKICAgICAgaDcuYWRkKGgpOwogICAgfQogICAgbGV0IHJlc3VsdDsKICAgIGlmICghbW9kZTM4NCkgewogICAgICByZXN1bHQgPSBuZXcgVWludDhBcnJheSg2NCk7CiAgICAgIGgwLmNvcHlUbyhyZXN1bHQsIDApOwogICAgICBoMS5jb3B5VG8ocmVzdWx0LCA4KTsKICAgICAgaDIuY29weVRvKHJlc3VsdCwgMTYpOwogICAgICBoMy5jb3B5VG8ocmVzdWx0LCAyNCk7CiAgICAgIGg0LmNvcHlUbyhyZXN1bHQsIDMyKTsKICAgICAgaDUuY29weVRvKHJlc3VsdCwgNDApOwogICAgICBoNi5jb3B5VG8ocmVzdWx0LCA0OCk7CiAgICAgIGg3LmNvcHlUbyhyZXN1bHQsIDU2KTsKICAgIH0gZWxzZSB7CiAgICAgIHJlc3VsdCA9IG5ldyBVaW50OEFycmF5KDQ4KTsKICAgICAgaDAuY29weVRvKHJlc3VsdCwgMCk7CiAgICAgIGgxLmNvcHlUbyhyZXN1bHQsIDgpOwogICAgICBoMi5jb3B5VG8ocmVzdWx0LCAxNik7CiAgICAgIGgzLmNvcHlUbyhyZXN1bHQsIDI0KTsKICAgICAgaDQuY29weVRvKHJlc3VsdCwgMzIpOwogICAgICBoNS5jb3B5VG8ocmVzdWx0LCA0MCk7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICByZXR1cm4gaGFzaDsKfSgpOwpleHBvcnRzLmNhbGN1bGF0ZVNIQTUxMiA9IGNhbGN1bGF0ZVNIQTUxMjsKZnVuY3Rpb24gY2FsY3VsYXRlU0hBMzg0KGRhdGEsIG9mZnNldCwgbGVuZ3RoKSB7CiAgcmV0dXJuIGNhbGN1bGF0ZVNIQTUxMihkYXRhLCBvZmZzZXQsIGxlbmd0aCwgdHJ1ZSk7Cn0KY2xhc3MgTnVsbENpcGhlciB7CiAgZGVjcnlwdEJsb2NrKGRhdGEpIHsKICAgIHJldHVybiBkYXRhOwogIH0KICBlbmNyeXB0KGRhdGEpIHsKICAgIHJldHVybiBkYXRhOwogIH0KfQpjbGFzcyBBRVNCYXNlQ2lwaGVyIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yID09PSBBRVNCYXNlQ2lwaGVyKSB7CiAgICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIkNhbm5vdCBpbml0aWFsaXplIEFFU0Jhc2VDaXBoZXIuIik7CiAgICB9CiAgICB0aGlzLl9zID0gbmV3IFVpbnQ4QXJyYXkoWzB4NjMsIDB4N2MsIDB4NzcsIDB4N2IsIDB4ZjIsIDB4NmIsIDB4NmYsIDB4YzUsIDB4MzAsIDB4MDEsIDB4NjcsIDB4MmIsIDB4ZmUsIDB4ZDcsIDB4YWIsIDB4NzYsIDB4Y2EsIDB4ODIsIDB4YzksIDB4N2QsIDB4ZmEsIDB4NTksIDB4NDcsIDB4ZjAsIDB4YWQsIDB4ZDQsIDB4YTIsIDB4YWYsIDB4OWMsIDB4YTQsIDB4NzIsIDB4YzAsIDB4YjcsIDB4ZmQsIDB4OTMsIDB4MjYsIDB4MzYsIDB4M2YsIDB4ZjcsIDB4Y2MsIDB4MzQsIDB4YTUsIDB4ZTUsIDB4ZjEsIDB4NzEsIDB4ZDgsIDB4MzEsIDB4MTUsIDB4MDQsIDB4YzcsIDB4MjMsIDB4YzMsIDB4MTgsIDB4OTYsIDB4MDUsIDB4OWEsIDB4MDcsIDB4MTIsIDB4ODAsIDB4ZTIsIDB4ZWIsIDB4MjcsIDB4YjIsIDB4NzUsIDB4MDksIDB4ODMsIDB4MmMsIDB4MWEsIDB4MWIsIDB4NmUsIDB4NWEsIDB4YTAsIDB4NTIsIDB4M2IsIDB4ZDYsIDB4YjMsIDB4MjksIDB4ZTMsIDB4MmYsIDB4ODQsIDB4NTMsIDB4ZDEsIDB4MDAsIDB4ZWQsIDB4MjAsIDB4ZmMsIDB4YjEsIDB4NWIsIDB4NmEsIDB4Y2IsIDB4YmUsIDB4MzksIDB4NGEsIDB4NGMsIDB4NTgsIDB4Y2YsIDB4ZDAsIDB4ZWYsIDB4YWEsIDB4ZmIsIDB4NDMsIDB4NGQsIDB4MzMsIDB4ODUsIDB4NDUsIDB4ZjksIDB4MDIsIDB4N2YsIDB4NTAsIDB4M2MsIDB4OWYsIDB4YTgsIDB4NTEsIDB4YTMsIDB4NDAsIDB4OGYsIDB4OTIsIDB4OWQsIDB4MzgsIDB4ZjUsIDB4YmMsIDB4YjYsIDB4ZGEsIDB4MjEsIDB4MTAsIDB4ZmYsIDB4ZjMsIDB4ZDIsIDB4Y2QsIDB4MGMsIDB4MTMsIDB4ZWMsIDB4NWYsIDB4OTcsIDB4NDQsIDB4MTcsIDB4YzQsIDB4YTcsIDB4N2UsIDB4M2QsIDB4NjQsIDB4NWQsIDB4MTksIDB4NzMsIDB4NjAsIDB4ODEsIDB4NGYsIDB4ZGMsIDB4MjIsIDB4MmEsIDB4OTAsIDB4ODgsIDB4NDYsIDB4ZWUsIDB4YjgsIDB4MTQsIDB4ZGUsIDB4NWUsIDB4MGIsIDB4ZGIsIDB4ZTAsIDB4MzIsIDB4M2EsIDB4MGEsIDB4NDksIDB4MDYsIDB4MjQsIDB4NWMsIDB4YzIsIDB4ZDMsIDB4YWMsIDB4NjIsIDB4OTEsIDB4OTUsIDB4ZTQsIDB4NzksIDB4ZTcsIDB4YzgsIDB4MzcsIDB4NmQsIDB4OGQsIDB4ZDUsIDB4NGUsIDB4YTksIDB4NmMsIDB4NTYsIDB4ZjQsIDB4ZWEsIDB4NjUsIDB4N2EsIDB4YWUsIDB4MDgsIDB4YmEsIDB4NzgsIDB4MjUsIDB4MmUsIDB4MWMsIDB4YTYsIDB4YjQsIDB4YzYsIDB4ZTgsIDB4ZGQsIDB4NzQsIDB4MWYsIDB4NGIsIDB4YmQsIDB4OGIsIDB4OGEsIDB4NzAsIDB4M2UsIDB4YjUsIDB4NjYsIDB4NDgsIDB4MDMsIDB4ZjYsIDB4MGUsIDB4NjEsIDB4MzUsIDB4NTcsIDB4YjksIDB4ODYsIDB4YzEsIDB4MWQsIDB4OWUsIDB4ZTEsIDB4ZjgsIDB4OTgsIDB4MTEsIDB4NjksIDB4ZDksIDB4OGUsIDB4OTQsIDB4OWIsIDB4MWUsIDB4ODcsIDB4ZTksIDB4Y2UsIDB4NTUsIDB4MjgsIDB4ZGYsIDB4OGMsIDB4YTEsIDB4ODksIDB4MGQsIDB4YmYsIDB4ZTYsIDB4NDIsIDB4NjgsIDB4NDEsIDB4OTksIDB4MmQsIDB4MGYsIDB4YjAsIDB4NTQsIDB4YmIsIDB4MTZdKTsKICAgIHRoaXMuX2ludl9zID0gbmV3IFVpbnQ4QXJyYXkoWzB4NTIsIDB4MDksIDB4NmEsIDB4ZDUsIDB4MzAsIDB4MzYsIDB4YTUsIDB4MzgsIDB4YmYsIDB4NDAsIDB4YTMsIDB4OWUsIDB4ODEsIDB4ZjMsIDB4ZDcsIDB4ZmIsIDB4N2MsIDB4ZTMsIDB4MzksIDB4ODIsIDB4OWIsIDB4MmYsIDB4ZmYsIDB4ODcsIDB4MzQsIDB4OGUsIDB4NDMsIDB4NDQsIDB4YzQsIDB4ZGUsIDB4ZTksIDB4Y2IsIDB4NTQsIDB4N2IsIDB4OTQsIDB4MzIsIDB4YTYsIDB4YzIsIDB4MjMsIDB4M2QsIDB4ZWUsIDB4NGMsIDB4OTUsIDB4MGIsIDB4NDIsIDB4ZmEsIDB4YzMsIDB4NGUsIDB4MDgsIDB4MmUsIDB4YTEsIDB4NjYsIDB4MjgsIDB4ZDksIDB4MjQsIDB4YjIsIDB4NzYsIDB4NWIsIDB4YTIsIDB4NDksIDB4NmQsIDB4OGIsIDB4ZDEsIDB4MjUsIDB4NzIsIDB4ZjgsIDB4ZjYsIDB4NjQsIDB4ODYsIDB4NjgsIDB4OTgsIDB4MTYsIDB4ZDQsIDB4YTQsIDB4NWMsIDB4Y2MsIDB4NWQsIDB4NjUsIDB4YjYsIDB4OTIsIDB4NmMsIDB4NzAsIDB4NDgsIDB4NTAsIDB4ZmQsIDB4ZWQsIDB4YjksIDB4ZGEsIDB4NWUsIDB4MTUsIDB4NDYsIDB4NTcsIDB4YTcsIDB4OGQsIDB4OWQsIDB4ODQsIDB4OTAsIDB4ZDgsIDB4YWIsIDB4MDAsIDB4OGMsIDB4YmMsIDB4ZDMsIDB4MGEsIDB4ZjcsIDB4ZTQsIDB4NTgsIDB4MDUsIDB4YjgsIDB4YjMsIDB4NDUsIDB4MDYsIDB4ZDAsIDB4MmMsIDB4MWUsIDB4OGYsIDB4Y2EsIDB4M2YsIDB4MGYsIDB4MDIsIDB4YzEsIDB4YWYsIDB4YmQsIDB4MDMsIDB4MDEsIDB4MTMsIDB4OGEsIDB4NmIsIDB4M2EsIDB4OTEsIDB4MTEsIDB4NDEsIDB4NGYsIDB4NjcsIDB4ZGMsIDB4ZWEsIDB4OTcsIDB4ZjIsIDB4Y2YsIDB4Y2UsIDB4ZjAsIDB4YjQsIDB4ZTYsIDB4NzMsIDB4OTYsIDB4YWMsIDB4NzQsIDB4MjIsIDB4ZTcsIDB4YWQsIDB4MzUsIDB4ODUsIDB4ZTIsIDB4ZjksIDB4MzcsIDB4ZTgsIDB4MWMsIDB4NzUsIDB4ZGYsIDB4NmUsIDB4NDcsIDB4ZjEsIDB4MWEsIDB4NzEsIDB4MWQsIDB4MjksIDB4YzUsIDB4ODksIDB4NmYsIDB4YjcsIDB4NjIsIDB4MGUsIDB4YWEsIDB4MTgsIDB4YmUsIDB4MWIsIDB4ZmMsIDB4NTYsIDB4M2UsIDB4NGIsIDB4YzYsIDB4ZDIsIDB4NzksIDB4MjAsIDB4OWEsIDB4ZGIsIDB4YzAsIDB4ZmUsIDB4NzgsIDB4Y2QsIDB4NWEsIDB4ZjQsIDB4MWYsIDB4ZGQsIDB4YTgsIDB4MzMsIDB4ODgsIDB4MDcsIDB4YzcsIDB4MzEsIDB4YjEsIDB4MTIsIDB4MTAsIDB4NTksIDB4MjcsIDB4ODAsIDB4ZWMsIDB4NWYsIDB4NjAsIDB4NTEsIDB4N2YsIDB4YTksIDB4MTksIDB4YjUsIDB4NGEsIDB4MGQsIDB4MmQsIDB4ZTUsIDB4N2EsIDB4OWYsIDB4OTMsIDB4YzksIDB4OWMsIDB4ZWYsIDB4YTAsIDB4ZTAsIDB4M2IsIDB4NGQsIDB4YWUsIDB4MmEsIDB4ZjUsIDB4YjAsIDB4YzgsIDB4ZWIsIDB4YmIsIDB4M2MsIDB4ODMsIDB4NTMsIDB4OTksIDB4NjEsIDB4MTcsIDB4MmIsIDB4MDQsIDB4N2UsIDB4YmEsIDB4NzcsIDB4ZDYsIDB4MjYsIDB4ZTEsIDB4NjksIDB4MTQsIDB4NjMsIDB4NTUsIDB4MjEsIDB4MGMsIDB4N2RdKTsKICAgIHRoaXMuX21peCA9IG5ldyBVaW50MzJBcnJheShbMHgwMDAwMDAwMCwgMHgwZTA5MGQwYiwgMHgxYzEyMWExNiwgMHgxMjFiMTcxZCwgMHgzODI0MzQyYywgMHgzNjJkMzkyNywgMHgyNDM2MmUzYSwgMHgyYTNmMjMzMSwgMHg3MDQ4Njg1OCwgMHg3ZTQxNjU1MywgMHg2YzVhNzI0ZSwgMHg2MjUzN2Y0NSwgMHg0ODZjNWM3NCwgMHg0NjY1NTE3ZiwgMHg1NDdlNDY2MiwgMHg1YTc3NGI2OSwgMHhlMDkwZDBiMCwgMHhlZTk5ZGRiYiwgMHhmYzgyY2FhNiwgMHhmMjhiYzdhZCwgMHhkOGI0ZTQ5YywgMHhkNmJkZTk5NywgMHhjNGE2ZmU4YSwgMHhjYWFmZjM4MSwgMHg5MGQ4YjhlOCwgMHg5ZWQxYjVlMywgMHg4Y2NhYTJmZSwgMHg4MmMzYWZmNSwgMHhhOGZjOGNjNCwgMHhhNmY1ODFjZiwgMHhiNGVlOTZkMiwgMHhiYWU3OWJkOSwgMHhkYjNiYmI3YiwgMHhkNTMyYjY3MCwgMHhjNzI5YTE2ZCwgMHhjOTIwYWM2NiwgMHhlMzFmOGY1NywgMHhlZDE2ODI1YywgMHhmZjBkOTU0MSwgMHhmMTA0OTg0YSwgMHhhYjczZDMyMywgMHhhNTdhZGUyOCwgMHhiNzYxYzkzNSwgMHhiOTY4YzQzZSwgMHg5MzU3ZTcwZiwgMHg5ZDVlZWEwNCwgMHg4ZjQ1ZmQxOSwgMHg4MTRjZjAxMiwgMHgzYmFiNmJjYiwgMHgzNWEyNjZjMCwgMHgyN2I5NzFkZCwgMHgyOWIwN2NkNiwgMHgwMzhmNWZlNywgMHgwZDg2NTJlYywgMHgxZjlkNDVmMSwgMHgxMTk0NDhmYSwgMHg0YmUzMDM5MywgMHg0NWVhMGU5OCwgMHg1N2YxMTk4NSwgMHg1OWY4MTQ4ZSwgMHg3M2M3MzdiZiwgMHg3ZGNlM2FiNCwgMHg2ZmQ1MmRhOSwgMHg2MWRjMjBhMiwgMHhhZDc2NmRmNiwgMHhhMzdmNjBmZCwgMHhiMTY0NzdlMCwgMHhiZjZkN2FlYiwgMHg5NTUyNTlkYSwgMHg5YjViNTRkMSwgMHg4OTQwNDNjYywgMHg4NzQ5NGVjNywgMHhkZDNlMDVhZSwgMHhkMzM3MDhhNSwgMHhjMTJjMWZiOCwgMHhjZjI1MTJiMywgMHhlNTFhMzE4MiwgMHhlYjEzM2M4OSwgMHhmOTA4MmI5NCwgMHhmNzAxMjY5ZiwgMHg0ZGU2YmQ0NiwgMHg0M2VmYjA0ZCwgMHg1MWY0YTc1MCwgMHg1ZmZkYWE1YiwgMHg3NWMyODk2YSwgMHg3YmNiODQ2MSwgMHg2OWQwOTM3YywgMHg2N2Q5OWU3NywgMHgzZGFlZDUxZSwgMHgzM2E3ZDgxNSwgMHgyMWJjY2YwOCwgMHgyZmI1YzIwMywgMHgwNThhZTEzMiwgMHgwYjgzZWMzOSwgMHgxOTk4ZmIyNCwgMHgxNzkxZjYyZiwgMHg3NjRkZDY4ZCwgMHg3ODQ0ZGI4NiwgMHg2YTVmY2M5YiwgMHg2NDU2YzE5MCwgMHg0ZTY5ZTJhMSwgMHg0MDYwZWZhYSwgMHg1MjdiZjhiNywgMHg1YzcyZjViYywgMHgwNjA1YmVkNSwgMHgwODBjYjNkZSwgMHgxYTE3YTRjMywgMHgxNDFlYTljOCwgMHgzZTIxOGFmOSwgMHgzMDI4ODdmMiwgMHgyMjMzOTBlZiwgMHgyYzNhOWRlNCwgMHg5NmRkMDYzZCwgMHg5OGQ0MGIzNiwgMHg4YWNmMWMyYiwgMHg4NGM2MTEyMCwgMHhhZWY5MzIxMSwgMHhhMGYwM2YxYSwgMHhiMmViMjgwNywgMHhiY2UyMjUwYywgMHhlNjk1NmU2NSwgMHhlODljNjM2ZSwgMHhmYTg3NzQ3MywgMHhmNDhlNzk3OCwgMHhkZWIxNWE0OSwgMHhkMGI4NTc0MiwgMHhjMmEzNDA1ZiwgMHhjY2FhNGQ1NCwgMHg0MWVjZGFmNywgMHg0ZmU1ZDdmYywgMHg1ZGZlYzBlMSwgMHg1M2Y3Y2RlYSwgMHg3OWM4ZWVkYiwgMHg3N2MxZTNkMCwgMHg2NWRhZjRjZCwgMHg2YmQzZjljNiwgMHgzMWE0YjJhZiwgMHgzZmFkYmZhNCwgMHgyZGI2YThiOSwgMHgyM2JmYTViMiwgMHgwOTgwODY4MywgMHgwNzg5OGI4OCwgMHgxNTkyOWM5NSwgMHgxYjliOTE5ZSwgMHhhMTdjMGE0NywgMHhhZjc1MDc0YywgMHhiZDZlMTA1MSwgMHhiMzY3MWQ1YSwgMHg5OTU4M2U2YiwgMHg5NzUxMzM2MCwgMHg4NTRhMjQ3ZCwgMHg4YjQzMjk3NiwgMHhkMTM0NjIxZiwgMHhkZjNkNmYxNCwgMHhjZDI2NzgwOSwgMHhjMzJmNzUwMiwgMHhlOTEwNTYzMywgMHhlNzE5NWIzOCwgMHhmNTAyNGMyNSwgMHhmYjBiNDEyZSwgMHg5YWQ3NjE4YywgMHg5NGRlNmM4NywgMHg4NmM1N2I5YSwgMHg4OGNjNzY5MSwgMHhhMmYzNTVhMCwgMHhhY2ZhNThhYiwgMHhiZWUxNGZiNiwgMHhiMGU4NDJiZCwgMHhlYTlmMDlkNCwgMHhlNDk2MDRkZiwgMHhmNjhkMTNjMiwgMHhmODg0MWVjOSwgMHhkMmJiM2RmOCwgMHhkY2IyMzBmMywgMHhjZWE5MjdlZSwgMHhjMGEwMmFlNSwgMHg3YTQ3YjEzYywgMHg3NDRlYmMzNywgMHg2NjU1YWIyYSwgMHg2ODVjYTYyMSwgMHg0MjYzODUxMCwgMHg0YzZhODgxYiwgMHg1ZTcxOWYwNiwgMHg1MDc4OTIwZCwgMHgwYTBmZDk2NCwgMHgwNDA2ZDQ2ZiwgMHgxNjFkYzM3MiwgMHgxODE0Y2U3OSwgMHgzMjJiZWQ0OCwgMHgzYzIyZTA0MywgMHgyZTM5Zjc1ZSwgMHgyMDMwZmE1NSwgMHhlYzlhYjcwMSwgMHhlMjkzYmEwYSwgMHhmMDg4YWQxNywgMHhmZTgxYTAxYywgMHhkNGJlODMyZCwgMHhkYWI3OGUyNiwgMHhjOGFjOTkzYiwgMHhjNmE1OTQzMCwgMHg5Y2QyZGY1OSwgMHg5MmRiZDI1MiwgMHg4MGMwYzU0ZiwgMHg4ZWM5Yzg0NCwgMHhhNGY2ZWI3NSwgMHhhYWZmZTY3ZSwgMHhiOGU0ZjE2MywgMHhiNmVkZmM2OCwgMHgwYzBhNjdiMSwgMHgwMjAzNmFiYSwgMHgxMDE4N2RhNywgMHgxZTExNzBhYywgMHgzNDJlNTM5ZCwgMHgzYTI3NWU5NiwgMHgyODNjNDk4YiwgMHgyNjM1NDQ4MCwgMHg3YzQyMGZlOSwgMHg3MjRiMDJlMiwgMHg2MDUwMTVmZiwgMHg2ZTU5MThmNCwgMHg0NDY2M2JjNSwgMHg0YTZmMzZjZSwgMHg1ODc0MjFkMywgMHg1NjdkMmNkOCwgMHgzN2ExMGM3YSwgMHgzOWE4MDE3MSwgMHgyYmIzMTY2YywgMHgyNWJhMWI2NywgMHgwZjg1Mzg1NiwgMHgwMThjMzU1ZCwgMHgxMzk3MjI0MCwgMHgxZDllMmY0YiwgMHg0N2U5NjQyMiwgMHg0OWUwNjkyOSwgMHg1YmZiN2UzNCwgMHg1NWYyNzMzZiwgMHg3ZmNkNTAwZSwgMHg3MWM0NWQwNSwgMHg2M2RmNGExOCwgMHg2ZGQ2NDcxMywgMHhkNzMxZGNjYSwgMHhkOTM4ZDFjMSwgMHhjYjIzYzZkYywgMHhjNTJhY2JkNywgMHhlZjE1ZThlNiwgMHhlMTFjZTVlZCwgMHhmMzA3ZjJmMCwgMHhmZDBlZmZmYiwgMHhhNzc5YjQ5MiwgMHhhOTcwYjk5OSwgMHhiYjZiYWU4NCwgMHhiNTYyYTM4ZiwgMHg5ZjVkODBiZSwgMHg5MTU0OGRiNSwgMHg4MzRmOWFhOCwgMHg4ZDQ2OTdhM10pOwogICAgdGhpcy5fbWl4Q29sID0gbmV3IFVpbnQ4QXJyYXkoMjU2KTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMjU2OyBpKyspIHsKICAgICAgaWYgKGkgPCAxMjgpIHsKICAgICAgICB0aGlzLl9taXhDb2xbaV0gPSBpIDw8IDE7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fbWl4Q29sW2ldID0gaSA8PCAxIF4gMHgxYjsKICAgICAgfQogICAgfQogICAgdGhpcy5idWZmZXIgPSBuZXcgVWludDhBcnJheSgxNik7CiAgICB0aGlzLmJ1ZmZlclBvc2l0aW9uID0gMDsKICB9CiAgX2V4cGFuZEtleShjaXBoZXJLZXkpIHsKICAgICgwLCBfdXRpbC51bnJlYWNoYWJsZSkoIkNhbm5vdCBjYWxsIGBfZXhwYW5kS2V5YCBvbiB0aGUgYmFzZSBjbGFzcyIpOwogIH0KICBfZGVjcnlwdChpbnB1dCwga2V5KSB7CiAgICBsZXQgdCwgdSwgdjsKICAgIGNvbnN0IHN0YXRlID0gbmV3IFVpbnQ4QXJyYXkoMTYpOwogICAgc3RhdGUuc2V0KGlucHV0KTsKICAgIGZvciAobGV0IGogPSAwLCBrID0gdGhpcy5fa2V5U2l6ZTsgaiA8IDE2OyArK2osICsraykgewogICAgICBzdGF0ZVtqXSBePSBrZXlba107CiAgICB9CiAgICBmb3IgKGxldCBpID0gdGhpcy5fY3ljbGVzT2ZSZXBldGl0aW9uIC0gMTsgaSA+PSAxOyAtLWkpIHsKICAgICAgdCA9IHN0YXRlWzEzXTsKICAgICAgc3RhdGVbMTNdID0gc3RhdGVbOV07CiAgICAgIHN0YXRlWzldID0gc3RhdGVbNV07CiAgICAgIHN0YXRlWzVdID0gc3RhdGVbMV07CiAgICAgIHN0YXRlWzFdID0gdDsKICAgICAgdCA9IHN0YXRlWzE0XTsKICAgICAgdSA9IHN0YXRlWzEwXTsKICAgICAgc3RhdGVbMTRdID0gc3RhdGVbNl07CiAgICAgIHN0YXRlWzEwXSA9IHN0YXRlWzJdOwogICAgICBzdGF0ZVs2XSA9IHQ7CiAgICAgIHN0YXRlWzJdID0gdTsKICAgICAgdCA9IHN0YXRlWzE1XTsKICAgICAgdSA9IHN0YXRlWzExXTsKICAgICAgdiA9IHN0YXRlWzddOwogICAgICBzdGF0ZVsxNV0gPSBzdGF0ZVszXTsKICAgICAgc3RhdGVbMTFdID0gdDsKICAgICAgc3RhdGVbN10gPSB1OwogICAgICBzdGF0ZVszXSA9IHY7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7ICsraikgewogICAgICAgIHN0YXRlW2pdID0gdGhpcy5faW52X3Nbc3RhdGVbal1dOwogICAgICB9CiAgICAgIGZvciAobGV0IGogPSAwLCBrID0gaSAqIDE2OyBqIDwgMTY7ICsraiwgKytrKSB7CiAgICAgICAgc3RhdGVbal0gXj0ga2V5W2tdOwogICAgICB9CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7IGogKz0gNCkgewogICAgICAgIGNvbnN0IHMwID0gdGhpcy5fbWl4W3N0YXRlW2pdXTsKICAgICAgICBjb25zdCBzMSA9IHRoaXMuX21peFtzdGF0ZVtqICsgMV1dOwogICAgICAgIGNvbnN0IHMyID0gdGhpcy5fbWl4W3N0YXRlW2ogKyAyXV07CiAgICAgICAgY29uc3QgczMgPSB0aGlzLl9taXhbc3RhdGVbaiArIDNdXTsKICAgICAgICB0ID0gczAgXiBzMSA+Pj4gOCBeIHMxIDw8IDI0IF4gczIgPj4+IDE2IF4gczIgPDwgMTYgXiBzMyA+Pj4gMjQgXiBzMyA8PCA4OwogICAgICAgIHN0YXRlW2pdID0gdCA+Pj4gMjQgJiAweGZmOwogICAgICAgIHN0YXRlW2ogKyAxXSA9IHQgPj4gMTYgJiAweGZmOwogICAgICAgIHN0YXRlW2ogKyAyXSA9IHQgPj4gOCAmIDB4ZmY7CiAgICAgICAgc3RhdGVbaiArIDNdID0gdCAmIDB4ZmY7CiAgICAgIH0KICAgIH0KICAgIHQgPSBzdGF0ZVsxM107CiAgICBzdGF0ZVsxM10gPSBzdGF0ZVs5XTsKICAgIHN0YXRlWzldID0gc3RhdGVbNV07CiAgICBzdGF0ZVs1XSA9IHN0YXRlWzFdOwogICAgc3RhdGVbMV0gPSB0OwogICAgdCA9IHN0YXRlWzE0XTsKICAgIHUgPSBzdGF0ZVsxMF07CiAgICBzdGF0ZVsxNF0gPSBzdGF0ZVs2XTsKICAgIHN0YXRlWzEwXSA9IHN0YXRlWzJdOwogICAgc3RhdGVbNl0gPSB0OwogICAgc3RhdGVbMl0gPSB1OwogICAgdCA9IHN0YXRlWzE1XTsKICAgIHUgPSBzdGF0ZVsxMV07CiAgICB2ID0gc3RhdGVbN107CiAgICBzdGF0ZVsxNV0gPSBzdGF0ZVszXTsKICAgIHN0YXRlWzExXSA9IHQ7CiAgICBzdGF0ZVs3XSA9IHU7CiAgICBzdGF0ZVszXSA9IHY7CiAgICBmb3IgKGxldCBqID0gMDsgaiA8IDE2OyArK2opIHsKICAgICAgc3RhdGVbal0gPSB0aGlzLl9pbnZfc1tzdGF0ZVtqXV07CiAgICAgIHN0YXRlW2pdIF49IGtleVtqXTsKICAgIH0KICAgIHJldHVybiBzdGF0ZTsKICB9CiAgX2VuY3J5cHQoaW5wdXQsIGtleSkgewogICAgY29uc3QgcyA9IHRoaXMuX3M7CiAgICBsZXQgdCwgdSwgdjsKICAgIGNvbnN0IHN0YXRlID0gbmV3IFVpbnQ4QXJyYXkoMTYpOwogICAgc3RhdGUuc2V0KGlucHV0KTsKICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7ICsraikgewogICAgICBzdGF0ZVtqXSBePSBrZXlbal07CiAgICB9CiAgICBmb3IgKGxldCBpID0gMTsgaSA8IHRoaXMuX2N5Y2xlc09mUmVwZXRpdGlvbjsgaSsrKSB7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7ICsraikgewogICAgICAgIHN0YXRlW2pdID0gc1tzdGF0ZVtqXV07CiAgICAgIH0KICAgICAgdiA9IHN0YXRlWzFdOwogICAgICBzdGF0ZVsxXSA9IHN0YXRlWzVdOwogICAgICBzdGF0ZVs1XSA9IHN0YXRlWzldOwogICAgICBzdGF0ZVs5XSA9IHN0YXRlWzEzXTsKICAgICAgc3RhdGVbMTNdID0gdjsKICAgICAgdiA9IHN0YXRlWzJdOwogICAgICB1ID0gc3RhdGVbNl07CiAgICAgIHN0YXRlWzJdID0gc3RhdGVbMTBdOwogICAgICBzdGF0ZVs2XSA9IHN0YXRlWzE0XTsKICAgICAgc3RhdGVbMTBdID0gdjsKICAgICAgc3RhdGVbMTRdID0gdTsKICAgICAgdiA9IHN0YXRlWzNdOwogICAgICB1ID0gc3RhdGVbN107CiAgICAgIHQgPSBzdGF0ZVsxMV07CiAgICAgIHN0YXRlWzNdID0gc3RhdGVbMTVdOwogICAgICBzdGF0ZVs3XSA9IHY7CiAgICAgIHN0YXRlWzExXSA9IHU7CiAgICAgIHN0YXRlWzE1XSA9IHQ7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7IGogKz0gNCkgewogICAgICAgIGNvbnN0IHMwID0gc3RhdGVbaiArIDBdOwogICAgICAgIGNvbnN0IHMxID0gc3RhdGVbaiArIDFdOwogICAgICAgIGNvbnN0IHMyID0gc3RhdGVbaiArIDJdOwogICAgICAgIGNvbnN0IHMzID0gc3RhdGVbaiArIDNdOwogICAgICAgIHQgPSBzMCBeIHMxIF4gczIgXiBzMzsKICAgICAgICBzdGF0ZVtqICsgMF0gXj0gdCBeIHRoaXMuX21peENvbFtzMCBeIHMxXTsKICAgICAgICBzdGF0ZVtqICsgMV0gXj0gdCBeIHRoaXMuX21peENvbFtzMSBeIHMyXTsKICAgICAgICBzdGF0ZVtqICsgMl0gXj0gdCBeIHRoaXMuX21peENvbFtzMiBeIHMzXTsKICAgICAgICBzdGF0ZVtqICsgM10gXj0gdCBeIHRoaXMuX21peENvbFtzMyBeIHMwXTsKICAgICAgfQogICAgICBmb3IgKGxldCBqID0gMCwgayA9IGkgKiAxNjsgaiA8IDE2OyArK2osICsraykgewogICAgICAgIHN0YXRlW2pdIF49IGtleVtrXTsKICAgICAgfQogICAgfQogICAgZm9yIChsZXQgaiA9IDA7IGogPCAxNjsgKytqKSB7CiAgICAgIHN0YXRlW2pdID0gc1tzdGF0ZVtqXV07CiAgICB9CiAgICB2ID0gc3RhdGVbMV07CiAgICBzdGF0ZVsxXSA9IHN0YXRlWzVdOwogICAgc3RhdGVbNV0gPSBzdGF0ZVs5XTsKICAgIHN0YXRlWzldID0gc3RhdGVbMTNdOwogICAgc3RhdGVbMTNdID0gdjsKICAgIHYgPSBzdGF0ZVsyXTsKICAgIHUgPSBzdGF0ZVs2XTsKICAgIHN0YXRlWzJdID0gc3RhdGVbMTBdOwogICAgc3RhdGVbNl0gPSBzdGF0ZVsxNF07CiAgICBzdGF0ZVsxMF0gPSB2OwogICAgc3RhdGVbMTRdID0gdTsKICAgIHYgPSBzdGF0ZVszXTsKICAgIHUgPSBzdGF0ZVs3XTsKICAgIHQgPSBzdGF0ZVsxMV07CiAgICBzdGF0ZVszXSA9IHN0YXRlWzE1XTsKICAgIHN0YXRlWzddID0gdjsKICAgIHN0YXRlWzExXSA9IHU7CiAgICBzdGF0ZVsxNV0gPSB0OwogICAgZm9yIChsZXQgaiA9IDAsIGsgPSB0aGlzLl9rZXlTaXplOyBqIDwgMTY7ICsraiwgKytrKSB7CiAgICAgIHN0YXRlW2pdIF49IGtleVtrXTsKICAgIH0KICAgIHJldHVybiBzdGF0ZTsKICB9CiAgX2RlY3J5cHRCbG9jazIoZGF0YSwgZmluYWxpemUpIHsKICAgIGNvbnN0IHNvdXJjZUxlbmd0aCA9IGRhdGEubGVuZ3RoOwogICAgbGV0IGJ1ZmZlciA9IHRoaXMuYnVmZmVyLAogICAgICBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlclBvc2l0aW9uOwogICAgY29uc3QgcmVzdWx0ID0gW107CiAgICBsZXQgaXYgPSB0aGlzLml2OwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzb3VyY2VMZW5ndGg7ICsraSkgewogICAgICBidWZmZXJbYnVmZmVyTGVuZ3RoXSA9IGRhdGFbaV07CiAgICAgICsrYnVmZmVyTGVuZ3RoOwogICAgICBpZiAoYnVmZmVyTGVuZ3RoIDwgMTYpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBwbGFpbiA9IHRoaXMuX2RlY3J5cHQoYnVmZmVyLCB0aGlzLl9rZXkpOwogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IDE2OyArK2opIHsKICAgICAgICBwbGFpbltqXSBePSBpdltqXTsKICAgICAgfQogICAgICBpdiA9IGJ1ZmZlcjsKICAgICAgcmVzdWx0LnB1c2gocGxhaW4pOwogICAgICBidWZmZXIgPSBuZXcgVWludDhBcnJheSgxNik7CiAgICAgIGJ1ZmZlckxlbmd0aCA9IDA7CiAgICB9CiAgICB0aGlzLmJ1ZmZlciA9IGJ1ZmZlcjsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gYnVmZmVyTGVuZ3RoOwogICAgdGhpcy5pdiA9IGl2OwogICAgaWYgKHJlc3VsdC5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KDApOwogICAgfQogICAgbGV0IG91dHB1dExlbmd0aCA9IDE2ICogcmVzdWx0Lmxlbmd0aDsKICAgIGlmIChmaW5hbGl6ZSkgewogICAgICBjb25zdCBsYXN0QmxvY2sgPSByZXN1bHQuYXQoLTEpOwogICAgICBsZXQgcHNMZW4gPSBsYXN0QmxvY2tbMTVdOwogICAgICBpZiAocHNMZW4gPD0gMTYpIHsKICAgICAgICBmb3IgKGxldCBpID0gMTUsIGlpID0gMTYgLSBwc0xlbjsgaSA+PSBpaTsgLS1pKSB7CiAgICAgICAgICBpZiAobGFzdEJsb2NrW2ldICE9PSBwc0xlbikgewogICAgICAgICAgICBwc0xlbiA9IDA7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBvdXRwdXRMZW5ndGggLT0gcHNMZW47CiAgICAgICAgcmVzdWx0W3Jlc3VsdC5sZW5ndGggLSAxXSA9IGxhc3RCbG9jay5zdWJhcnJheSgwLCAxNiAtIHBzTGVuKTsKICAgICAgfQogICAgfQogICAgY29uc3Qgb3V0cHV0ID0gbmV3IFVpbnQ4QXJyYXkob3V0cHV0TGVuZ3RoKTsKICAgIGZvciAobGV0IGkgPSAwLCBqID0gMCwgaWkgPSByZXN1bHQubGVuZ3RoOyBpIDwgaWk7ICsraSwgaiArPSAxNikgewogICAgICBvdXRwdXQuc2V0KHJlc3VsdFtpXSwgaik7CiAgICB9CiAgICByZXR1cm4gb3V0cHV0OwogIH0KICBkZWNyeXB0QmxvY2soZGF0YSwgZmluYWxpemUpIHsKICAgIGxldCBpdiA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogbnVsbDsKICAgIGNvbnN0IHNvdXJjZUxlbmd0aCA9IGRhdGEubGVuZ3RoOwogICAgY29uc3QgYnVmZmVyID0gdGhpcy5idWZmZXI7CiAgICBsZXQgYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJQb3NpdGlvbjsKICAgIGlmIChpdikgewogICAgICB0aGlzLml2ID0gaXY7CiAgICB9IGVsc2UgewogICAgICBmb3IgKGxldCBpID0gMDsgYnVmZmVyTGVuZ3RoIDwgMTYgJiYgaSA8IHNvdXJjZUxlbmd0aDsgKytpLCArK2J1ZmZlckxlbmd0aCkgewogICAgICAgIGJ1ZmZlcltidWZmZXJMZW5ndGhdID0gZGF0YVtpXTsKICAgICAgfQogICAgICBpZiAoYnVmZmVyTGVuZ3RoIDwgMTYpIHsKICAgICAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGJ1ZmZlckxlbmd0aDsKICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCk7CiAgICAgIH0KICAgICAgdGhpcy5pdiA9IGJ1ZmZlcjsKICAgICAgZGF0YSA9IGRhdGEuc3ViYXJyYXkoMTYpOwogICAgfQogICAgdGhpcy5idWZmZXIgPSBuZXcgVWludDhBcnJheSgxNik7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IDA7CiAgICB0aGlzLmRlY3J5cHRCbG9jayA9IHRoaXMuX2RlY3J5cHRCbG9jazI7CiAgICByZXR1cm4gdGhpcy5kZWNyeXB0QmxvY2soZGF0YSwgZmluYWxpemUpOwogIH0KICBlbmNyeXB0KGRhdGEsIGl2KSB7CiAgICBjb25zdCBzb3VyY2VMZW5ndGggPSBkYXRhLmxlbmd0aDsKICAgIGxldCBidWZmZXIgPSB0aGlzLmJ1ZmZlciwKICAgICAgYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJQb3NpdGlvbjsKICAgIGNvbnN0IHJlc3VsdCA9IFtdOwogICAgaWYgKCFpdikgewogICAgICBpdiA9IG5ldyBVaW50OEFycmF5KDE2KTsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc291cmNlTGVuZ3RoOyArK2kpIHsKICAgICAgYnVmZmVyW2J1ZmZlckxlbmd0aF0gPSBkYXRhW2ldOwogICAgICArK2J1ZmZlckxlbmd0aDsKICAgICAgaWYgKGJ1ZmZlckxlbmd0aCA8IDE2KSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCAxNjsgKytqKSB7CiAgICAgICAgYnVmZmVyW2pdIF49IGl2W2pdOwogICAgICB9CiAgICAgIGNvbnN0IGNpcGhlciA9IHRoaXMuX2VuY3J5cHQoYnVmZmVyLCB0aGlzLl9rZXkpOwogICAgICBpdiA9IGNpcGhlcjsKICAgICAgcmVzdWx0LnB1c2goY2lwaGVyKTsKICAgICAgYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoMTYpOwogICAgICBidWZmZXJMZW5ndGggPSAwOwogICAgfQogICAgdGhpcy5idWZmZXIgPSBidWZmZXI7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGJ1ZmZlckxlbmd0aDsKICAgIHRoaXMuaXYgPSBpdjsKICAgIGlmIChyZXN1bHQubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBuZXcgVWludDhBcnJheSgwKTsKICAgIH0KICAgIGNvbnN0IG91dHB1dExlbmd0aCA9IDE2ICogcmVzdWx0Lmxlbmd0aDsKICAgIGNvbnN0IG91dHB1dCA9IG5ldyBVaW50OEFycmF5KG91dHB1dExlbmd0aCk7CiAgICBmb3IgKGxldCBpID0gMCwgaiA9IDAsIGlpID0gcmVzdWx0Lmxlbmd0aDsgaSA8IGlpOyArK2ksIGogKz0gMTYpIHsKICAgICAgb3V0cHV0LnNldChyZXN1bHRbaV0sIGopOwogICAgfQogICAgcmV0dXJuIG91dHB1dDsKICB9Cn0KY2xhc3MgQUVTMTI4Q2lwaGVyIGV4dGVuZHMgQUVTQmFzZUNpcGhlciB7CiAgY29uc3RydWN0b3Ioa2V5KSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5fY3ljbGVzT2ZSZXBldGl0aW9uID0gMTA7CiAgICB0aGlzLl9rZXlTaXplID0gMTYwOwogICAgdGhpcy5fcmNvbiA9IG5ldyBVaW50OEFycmF5KFsweDhkLCAweDAxLCAweDAyLCAweDA0LCAweDA4LCAweDEwLCAweDIwLCAweDQwLCAweDgwLCAweDFiLCAweDM2LCAweDZjLCAweGQ4LCAweGFiLCAweDRkLCAweDlhLCAweDJmLCAweDVlLCAweGJjLCAweDYzLCAweGM2LCAweDk3LCAweDM1LCAweDZhLCAweGQ0LCAweGIzLCAweDdkLCAweGZhLCAweGVmLCAweGM1LCAweDkxLCAweDM5LCAweDcyLCAweGU0LCAweGQzLCAweGJkLCAweDYxLCAweGMyLCAweDlmLCAweDI1LCAweDRhLCAweDk0LCAweDMzLCAweDY2LCAweGNjLCAweDgzLCAweDFkLCAweDNhLCAweDc0LCAweGU4LCAweGNiLCAweDhkLCAweDAxLCAweDAyLCAweDA0LCAweDA4LCAweDEwLCAweDIwLCAweDQwLCAweDgwLCAweDFiLCAweDM2LCAweDZjLCAweGQ4LCAweGFiLCAweDRkLCAweDlhLCAweDJmLCAweDVlLCAweGJjLCAweDYzLCAweGM2LCAweDk3LCAweDM1LCAweDZhLCAweGQ0LCAweGIzLCAweDdkLCAweGZhLCAweGVmLCAweGM1LCAweDkxLCAweDM5LCAweDcyLCAweGU0LCAweGQzLCAweGJkLCAweDYxLCAweGMyLCAweDlmLCAweDI1LCAweDRhLCAweDk0LCAweDMzLCAweDY2LCAweGNjLCAweDgzLCAweDFkLCAweDNhLCAweDc0LCAweGU4LCAweGNiLCAweDhkLCAweDAxLCAweDAyLCAweDA0LCAweDA4LCAweDEwLCAweDIwLCAweDQwLCAweDgwLCAweDFiLCAweDM2LCAweDZjLCAweGQ4LCAweGFiLCAweDRkLCAweDlhLCAweDJmLCAweDVlLCAweGJjLCAweDYzLCAweGM2LCAweDk3LCAweDM1LCAweDZhLCAweGQ0LCAweGIzLCAweDdkLCAweGZhLCAweGVmLCAweGM1LCAweDkxLCAweDM5LCAweDcyLCAweGU0LCAweGQzLCAweGJkLCAweDYxLCAweGMyLCAweDlmLCAweDI1LCAweDRhLCAweDk0LCAweDMzLCAweDY2LCAweGNjLCAweDgzLCAweDFkLCAweDNhLCAweDc0LCAweGU4LCAweGNiLCAweDhkLCAweDAxLCAweDAyLCAweDA0LCAweDA4LCAweDEwLCAweDIwLCAweDQwLCAweDgwLCAweDFiLCAweDM2LCAweDZjLCAweGQ4LCAweGFiLCAweDRkLCAweDlhLCAweDJmLCAweDVlLCAweGJjLCAweDYzLCAweGM2LCAweDk3LCAweDM1LCAweDZhLCAweGQ0LCAweGIzLCAweDdkLCAweGZhLCAweGVmLCAweGM1LCAweDkxLCAweDM5LCAweDcyLCAweGU0LCAweGQzLCAweGJkLCAweDYxLCAweGMyLCAweDlmLCAweDI1LCAweDRhLCAweDk0LCAweDMzLCAweDY2LCAweGNjLCAweDgzLCAweDFkLCAweDNhLCAweDc0LCAweGU4LCAweGNiLCAweDhkLCAweDAxLCAweDAyLCAweDA0LCAweDA4LCAweDEwLCAweDIwLCAweDQwLCAweDgwLCAweDFiLCAweDM2LCAweDZjLCAweGQ4LCAweGFiLCAweDRkLCAweDlhLCAweDJmLCAweDVlLCAweGJjLCAweDYzLCAweGM2LCAweDk3LCAweDM1LCAweDZhLCAweGQ0LCAweGIzLCAweDdkLCAweGZhLCAweGVmLCAweGM1LCAweDkxLCAweDM5LCAweDcyLCAweGU0LCAweGQzLCAweGJkLCAweDYxLCAweGMyLCAweDlmLCAweDI1LCAweDRhLCAweDk0LCAweDMzLCAweDY2LCAweGNjLCAweDgzLCAweDFkLCAweDNhLCAweDc0LCAweGU4LCAweGNiLCAweDhkXSk7CiAgICB0aGlzLl9rZXkgPSB0aGlzLl9leHBhbmRLZXkoa2V5KTsKICB9CiAgX2V4cGFuZEtleShjaXBoZXJLZXkpIHsKICAgIGNvbnN0IGIgPSAxNzY7CiAgICBjb25zdCBzID0gdGhpcy5fczsKICAgIGNvbnN0IHJjb24gPSB0aGlzLl9yY29uOwogICAgY29uc3QgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkoYik7CiAgICByZXN1bHQuc2V0KGNpcGhlcktleSk7CiAgICBmb3IgKGxldCBqID0gMTYsIGkgPSAxOyBqIDwgYjsgKytpKSB7CiAgICAgIGxldCB0MSA9IHJlc3VsdFtqIC0gM107CiAgICAgIGxldCB0MiA9IHJlc3VsdFtqIC0gMl07CiAgICAgIGxldCB0MyA9IHJlc3VsdFtqIC0gMV07CiAgICAgIGxldCB0NCA9IHJlc3VsdFtqIC0gNF07CiAgICAgIHQxID0gc1t0MV07CiAgICAgIHQyID0gc1t0Ml07CiAgICAgIHQzID0gc1t0M107CiAgICAgIHQ0ID0gc1t0NF07CiAgICAgIHQxIF49IHJjb25baV07CiAgICAgIGZvciAobGV0IG4gPSAwOyBuIDwgNDsgKytuKSB7CiAgICAgICAgcmVzdWx0W2pdID0gdDEgXj0gcmVzdWx0W2ogLSAxNl07CiAgICAgICAgaisrOwogICAgICAgIHJlc3VsdFtqXSA9IHQyIF49IHJlc3VsdFtqIC0gMTZdOwogICAgICAgIGorKzsKICAgICAgICByZXN1bHRbal0gPSB0MyBePSByZXN1bHRbaiAtIDE2XTsKICAgICAgICBqKys7CiAgICAgICAgcmVzdWx0W2pdID0gdDQgXj0gcmVzdWx0W2ogLSAxNl07CiAgICAgICAgaisrOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcmVzdWx0OwogIH0KfQpleHBvcnRzLkFFUzEyOENpcGhlciA9IEFFUzEyOENpcGhlcjsKY2xhc3MgQUVTMjU2Q2lwaGVyIGV4dGVuZHMgQUVTQmFzZUNpcGhlciB7CiAgY29uc3RydWN0b3Ioa2V5KSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5fY3ljbGVzT2ZSZXBldGl0aW9uID0gMTQ7CiAgICB0aGlzLl9rZXlTaXplID0gMjI0OwogICAgdGhpcy5fa2V5ID0gdGhpcy5fZXhwYW5kS2V5KGtleSk7CiAgfQogIF9leHBhbmRLZXkoY2lwaGVyS2V5KSB7CiAgICBjb25zdCBiID0gMjQwOwogICAgY29uc3QgcyA9IHRoaXMuX3M7CiAgICBjb25zdCByZXN1bHQgPSBuZXcgVWludDhBcnJheShiKTsKICAgIHJlc3VsdC5zZXQoY2lwaGVyS2V5KTsKICAgIGxldCByID0gMTsKICAgIGxldCB0MSwgdDIsIHQzLCB0NDsKICAgIGZvciAobGV0IGogPSAzMiwgaSA9IDE7IGogPCBiOyArK2kpIHsKICAgICAgaWYgKGogJSAzMiA9PT0gMTYpIHsKICAgICAgICB0MSA9IHNbdDFdOwogICAgICAgIHQyID0gc1t0Ml07CiAgICAgICAgdDMgPSBzW3QzXTsKICAgICAgICB0NCA9IHNbdDRdOwogICAgICB9IGVsc2UgaWYgKGogJSAzMiA9PT0gMCkgewogICAgICAgIHQxID0gcmVzdWx0W2ogLSAzXTsKICAgICAgICB0MiA9IHJlc3VsdFtqIC0gMl07CiAgICAgICAgdDMgPSByZXN1bHRbaiAtIDFdOwogICAgICAgIHQ0ID0gcmVzdWx0W2ogLSA0XTsKICAgICAgICB0MSA9IHNbdDFdOwogICAgICAgIHQyID0gc1t0Ml07CiAgICAgICAgdDMgPSBzW3QzXTsKICAgICAgICB0NCA9IHNbdDRdOwogICAgICAgIHQxIF49IHI7CiAgICAgICAgaWYgKChyIDw8PSAxKSA+PSAyNTYpIHsKICAgICAgICAgIHIgPSAociBeIDB4MWIpICYgMHhmZjsKICAgICAgICB9CiAgICAgIH0KICAgICAgZm9yIChsZXQgbiA9IDA7IG4gPCA0OyArK24pIHsKICAgICAgICByZXN1bHRbal0gPSB0MSBePSByZXN1bHRbaiAtIDMyXTsKICAgICAgICBqKys7CiAgICAgICAgcmVzdWx0W2pdID0gdDIgXj0gcmVzdWx0W2ogLSAzMl07CiAgICAgICAgaisrOwogICAgICAgIHJlc3VsdFtqXSA9IHQzIF49IHJlc3VsdFtqIC0gMzJdOwogICAgICAgIGorKzsKICAgICAgICByZXN1bHRbal0gPSB0NCBePSByZXN1bHRbaiAtIDMyXTsKICAgICAgICBqKys7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQp9CmV4cG9ydHMuQUVTMjU2Q2lwaGVyID0gQUVTMjU2Q2lwaGVyOwpjbGFzcyBQREYxNyB7CiAgY2hlY2tPd25lclBhc3N3b3JkKHBhc3N3b3JkLCBvd25lclZhbGlkYXRpb25TYWx0LCB1c2VyQnl0ZXMsIG93bmVyUGFzc3dvcmQpIHsKICAgIGNvbnN0IGhhc2hEYXRhID0gbmV3IFVpbnQ4QXJyYXkocGFzc3dvcmQubGVuZ3RoICsgNTYpOwogICAgaGFzaERhdGEuc2V0KHBhc3N3b3JkLCAwKTsKICAgIGhhc2hEYXRhLnNldChvd25lclZhbGlkYXRpb25TYWx0LCBwYXNzd29yZC5sZW5ndGgpOwogICAgaGFzaERhdGEuc2V0KHVzZXJCeXRlcywgcGFzc3dvcmQubGVuZ3RoICsgb3duZXJWYWxpZGF0aW9uU2FsdC5sZW5ndGgpOwogICAgY29uc3QgcmVzdWx0ID0gY2FsY3VsYXRlU0hBMjU2KGhhc2hEYXRhLCAwLCBoYXNoRGF0YS5sZW5ndGgpOwogICAgcmV0dXJuICgwLCBfdXRpbC5pc0FycmF5RXF1YWwpKHJlc3VsdCwgb3duZXJQYXNzd29yZCk7CiAgfQogIGNoZWNrVXNlclBhc3N3b3JkKHBhc3N3b3JkLCB1c2VyVmFsaWRhdGlvblNhbHQsIHVzZXJQYXNzd29yZCkgewogICAgY29uc3QgaGFzaERhdGEgPSBuZXcgVWludDhBcnJheShwYXNzd29yZC5sZW5ndGggKyA4KTsKICAgIGhhc2hEYXRhLnNldChwYXNzd29yZCwgMCk7CiAgICBoYXNoRGF0YS5zZXQodXNlclZhbGlkYXRpb25TYWx0LCBwYXNzd29yZC5sZW5ndGgpOwogICAgY29uc3QgcmVzdWx0ID0gY2FsY3VsYXRlU0hBMjU2KGhhc2hEYXRhLCAwLCBoYXNoRGF0YS5sZW5ndGgpOwogICAgcmV0dXJuICgwLCBfdXRpbC5pc0FycmF5RXF1YWwpKHJlc3VsdCwgdXNlclBhc3N3b3JkKTsKICB9CiAgZ2V0T3duZXJLZXkocGFzc3dvcmQsIG93bmVyS2V5U2FsdCwgdXNlckJ5dGVzLCBvd25lckVuY3J5cHRpb24pIHsKICAgIGNvbnN0IGhhc2hEYXRhID0gbmV3IFVpbnQ4QXJyYXkocGFzc3dvcmQubGVuZ3RoICsgNTYpOwogICAgaGFzaERhdGEuc2V0KHBhc3N3b3JkLCAwKTsKICAgIGhhc2hEYXRhLnNldChvd25lcktleVNhbHQsIHBhc3N3b3JkLmxlbmd0aCk7CiAgICBoYXNoRGF0YS5zZXQodXNlckJ5dGVzLCBwYXNzd29yZC5sZW5ndGggKyBvd25lcktleVNhbHQubGVuZ3RoKTsKICAgIGNvbnN0IGtleSA9IGNhbGN1bGF0ZVNIQTI1NihoYXNoRGF0YSwgMCwgaGFzaERhdGEubGVuZ3RoKTsKICAgIGNvbnN0IGNpcGhlciA9IG5ldyBBRVMyNTZDaXBoZXIoa2V5KTsKICAgIHJldHVybiBjaXBoZXIuZGVjcnlwdEJsb2NrKG93bmVyRW5jcnlwdGlvbiwgZmFsc2UsIG5ldyBVaW50OEFycmF5KDE2KSk7CiAgfQogIGdldFVzZXJLZXkocGFzc3dvcmQsIHVzZXJLZXlTYWx0LCB1c2VyRW5jcnlwdGlvbikgewogICAgY29uc3QgaGFzaERhdGEgPSBuZXcgVWludDhBcnJheShwYXNzd29yZC5sZW5ndGggKyA4KTsKICAgIGhhc2hEYXRhLnNldChwYXNzd29yZCwgMCk7CiAgICBoYXNoRGF0YS5zZXQodXNlcktleVNhbHQsIHBhc3N3b3JkLmxlbmd0aCk7CiAgICBjb25zdCBrZXkgPSBjYWxjdWxhdGVTSEEyNTYoaGFzaERhdGEsIDAsIGhhc2hEYXRhLmxlbmd0aCk7CiAgICBjb25zdCBjaXBoZXIgPSBuZXcgQUVTMjU2Q2lwaGVyKGtleSk7CiAgICByZXR1cm4gY2lwaGVyLmRlY3J5cHRCbG9jayh1c2VyRW5jcnlwdGlvbiwgZmFsc2UsIG5ldyBVaW50OEFycmF5KDE2KSk7CiAgfQp9CmV4cG9ydHMuUERGMTcgPSBQREYxNzsKY29uc3QgUERGMjAgPSBmdW5jdGlvbiBQREYyMENsb3N1cmUoKSB7CiAgZnVuY3Rpb24gY2FsY3VsYXRlUERGMjBIYXNoKHBhc3N3b3JkLCBpbnB1dCwgdXNlckJ5dGVzKSB7CiAgICBsZXQgayA9IGNhbGN1bGF0ZVNIQTI1NihpbnB1dCwgMCwgaW5wdXQubGVuZ3RoKS5zdWJhcnJheSgwLCAzMik7CiAgICBsZXQgZSA9IFswXTsKICAgIGxldCBpID0gMDsKICAgIHdoaWxlIChpIDwgNjQgfHwgZS5hdCgtMSkgPiBpIC0gMzIpIHsKICAgICAgY29uc3QgY29tYmluZWRMZW5ndGggPSBwYXNzd29yZC5sZW5ndGggKyBrLmxlbmd0aCArIHVzZXJCeXRlcy5sZW5ndGgsCiAgICAgICAgY29tYmluZWRBcnJheSA9IG5ldyBVaW50OEFycmF5KGNvbWJpbmVkTGVuZ3RoKTsKICAgICAgbGV0IHdyaXRlT2Zmc2V0ID0gMDsKICAgICAgY29tYmluZWRBcnJheS5zZXQocGFzc3dvcmQsIHdyaXRlT2Zmc2V0KTsKICAgICAgd3JpdGVPZmZzZXQgKz0gcGFzc3dvcmQubGVuZ3RoOwogICAgICBjb21iaW5lZEFycmF5LnNldChrLCB3cml0ZU9mZnNldCk7CiAgICAgIHdyaXRlT2Zmc2V0ICs9IGsubGVuZ3RoOwogICAgICBjb21iaW5lZEFycmF5LnNldCh1c2VyQnl0ZXMsIHdyaXRlT2Zmc2V0KTsKICAgICAgY29uc3QgazEgPSBuZXcgVWludDhBcnJheShjb21iaW5lZExlbmd0aCAqIDY0KTsKICAgICAgZm9yIChsZXQgaiA9IDAsIHBvcyA9IDA7IGogPCA2NDsgaisrLCBwb3MgKz0gY29tYmluZWRMZW5ndGgpIHsKICAgICAgICBrMS5zZXQoY29tYmluZWRBcnJheSwgcG9zKTsKICAgICAgfQogICAgICBjb25zdCBjaXBoZXIgPSBuZXcgQUVTMTI4Q2lwaGVyKGsuc3ViYXJyYXkoMCwgMTYpKTsKICAgICAgZSA9IGNpcGhlci5lbmNyeXB0KGsxLCBrLnN1YmFycmF5KDE2LCAzMikpOwogICAgICBjb25zdCByZW1haW5kZXIgPSBlLnNsaWNlKDAsIDE2KS5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKSAlIDM7CiAgICAgIGlmIChyZW1haW5kZXIgPT09IDApIHsKICAgICAgICBrID0gY2FsY3VsYXRlU0hBMjU2KGUsIDAsIGUubGVuZ3RoKTsKICAgICAgfSBlbHNlIGlmIChyZW1haW5kZXIgPT09IDEpIHsKICAgICAgICBrID0gY2FsY3VsYXRlU0hBMzg0KGUsIDAsIGUubGVuZ3RoKTsKICAgICAgfSBlbHNlIGlmIChyZW1haW5kZXIgPT09IDIpIHsKICAgICAgICBrID0gY2FsY3VsYXRlU0hBNTEyKGUsIDAsIGUubGVuZ3RoKTsKICAgICAgfQogICAgICBpKys7CiAgICB9CiAgICByZXR1cm4gay5zdWJhcnJheSgwLCAzMik7CiAgfQogIGNsYXNzIFBERjIwIHsKICAgIGhhc2gocGFzc3dvcmQsIGNvbmNhdEJ5dGVzLCB1c2VyQnl0ZXMpIHsKICAgICAgcmV0dXJuIGNhbGN1bGF0ZVBERjIwSGFzaChwYXNzd29yZCwgY29uY2F0Qnl0ZXMsIHVzZXJCeXRlcyk7CiAgICB9CiAgICBjaGVja093bmVyUGFzc3dvcmQocGFzc3dvcmQsIG93bmVyVmFsaWRhdGlvblNhbHQsIHVzZXJCeXRlcywgb3duZXJQYXNzd29yZCkgewogICAgICBjb25zdCBoYXNoRGF0YSA9IG5ldyBVaW50OEFycmF5KHBhc3N3b3JkLmxlbmd0aCArIDU2KTsKICAgICAgaGFzaERhdGEuc2V0KHBhc3N3b3JkLCAwKTsKICAgICAgaGFzaERhdGEuc2V0KG93bmVyVmFsaWRhdGlvblNhbHQsIHBhc3N3b3JkLmxlbmd0aCk7CiAgICAgIGhhc2hEYXRhLnNldCh1c2VyQnl0ZXMsIHBhc3N3b3JkLmxlbmd0aCArIG93bmVyVmFsaWRhdGlvblNhbHQubGVuZ3RoKTsKICAgICAgY29uc3QgcmVzdWx0ID0gY2FsY3VsYXRlUERGMjBIYXNoKHBhc3N3b3JkLCBoYXNoRGF0YSwgdXNlckJ5dGVzKTsKICAgICAgcmV0dXJuICgwLCBfdXRpbC5pc0FycmF5RXF1YWwpKHJlc3VsdCwgb3duZXJQYXNzd29yZCk7CiAgICB9CiAgICBjaGVja1VzZXJQYXNzd29yZChwYXNzd29yZCwgdXNlclZhbGlkYXRpb25TYWx0LCB1c2VyUGFzc3dvcmQpIHsKICAgICAgY29uc3QgaGFzaERhdGEgPSBuZXcgVWludDhBcnJheShwYXNzd29yZC5sZW5ndGggKyA4KTsKICAgICAgaGFzaERhdGEuc2V0KHBhc3N3b3JkLCAwKTsKICAgICAgaGFzaERhdGEuc2V0KHVzZXJWYWxpZGF0aW9uU2FsdCwgcGFzc3dvcmQubGVuZ3RoKTsKICAgICAgY29uc3QgcmVzdWx0ID0gY2FsY3VsYXRlUERGMjBIYXNoKHBhc3N3b3JkLCBoYXNoRGF0YSwgW10pOwogICAgICByZXR1cm4gKDAsIF91dGlsLmlzQXJyYXlFcXVhbCkocmVzdWx0LCB1c2VyUGFzc3dvcmQpOwogICAgfQogICAgZ2V0T3duZXJLZXkocGFzc3dvcmQsIG93bmVyS2V5U2FsdCwgdXNlckJ5dGVzLCBvd25lckVuY3J5cHRpb24pIHsKICAgICAgY29uc3QgaGFzaERhdGEgPSBuZXcgVWludDhBcnJheShwYXNzd29yZC5sZW5ndGggKyA1Nik7CiAgICAgIGhhc2hEYXRhLnNldChwYXNzd29yZCwgMCk7CiAgICAgIGhhc2hEYXRhLnNldChvd25lcktleVNhbHQsIHBhc3N3b3JkLmxlbmd0aCk7CiAgICAgIGhhc2hEYXRhLnNldCh1c2VyQnl0ZXMsIHBhc3N3b3JkLmxlbmd0aCArIG93bmVyS2V5U2FsdC5sZW5ndGgpOwogICAgICBjb25zdCBrZXkgPSBjYWxjdWxhdGVQREYyMEhhc2gocGFzc3dvcmQsIGhhc2hEYXRhLCB1c2VyQnl0ZXMpOwogICAgICBjb25zdCBjaXBoZXIgPSBuZXcgQUVTMjU2Q2lwaGVyKGtleSk7CiAgICAgIHJldHVybiBjaXBoZXIuZGVjcnlwdEJsb2NrKG93bmVyRW5jcnlwdGlvbiwgZmFsc2UsIG5ldyBVaW50OEFycmF5KDE2KSk7CiAgICB9CiAgICBnZXRVc2VyS2V5KHBhc3N3b3JkLCB1c2VyS2V5U2FsdCwgdXNlckVuY3J5cHRpb24pIHsKICAgICAgY29uc3QgaGFzaERhdGEgPSBuZXcgVWludDhBcnJheShwYXNzd29yZC5sZW5ndGggKyA4KTsKICAgICAgaGFzaERhdGEuc2V0KHBhc3N3b3JkLCAwKTsKICAgICAgaGFzaERhdGEuc2V0KHVzZXJLZXlTYWx0LCBwYXNzd29yZC5sZW5ndGgpOwogICAgICBjb25zdCBrZXkgPSBjYWxjdWxhdGVQREYyMEhhc2gocGFzc3dvcmQsIGhhc2hEYXRhLCBbXSk7CiAgICAgIGNvbnN0IGNpcGhlciA9IG5ldyBBRVMyNTZDaXBoZXIoa2V5KTsKICAgICAgcmV0dXJuIGNpcGhlci5kZWNyeXB0QmxvY2sodXNlckVuY3J5cHRpb24sIGZhbHNlLCBuZXcgVWludDhBcnJheSgxNikpOwogICAgfQogIH0KICByZXR1cm4gUERGMjA7Cn0oKTsKZXhwb3J0cy5QREYyMCA9IFBERjIwOwpjbGFzcyBDaXBoZXJUcmFuc2Zvcm0gewogIGNvbnN0cnVjdG9yKHN0cmluZ0NpcGhlckNvbnN0cnVjdG9yLCBzdHJlYW1DaXBoZXJDb25zdHJ1Y3RvcikgewogICAgdGhpcy5TdHJpbmdDaXBoZXJDb25zdHJ1Y3RvciA9IHN0cmluZ0NpcGhlckNvbnN0cnVjdG9yOwogICAgdGhpcy5TdHJlYW1DaXBoZXJDb25zdHJ1Y3RvciA9IHN0cmVhbUNpcGhlckNvbnN0cnVjdG9yOwogIH0KICBjcmVhdGVTdHJlYW0oc3RyZWFtLCBsZW5ndGgpIHsKICAgIGNvbnN0IGNpcGhlciA9IG5ldyB0aGlzLlN0cmVhbUNpcGhlckNvbnN0cnVjdG9yKCk7CiAgICByZXR1cm4gbmV3IF9kZWNyeXB0X3N0cmVhbS5EZWNyeXB0U3RyZWFtKHN0cmVhbSwgbGVuZ3RoLCBmdW5jdGlvbiBjaXBoZXJUcmFuc2Zvcm1EZWNyeXB0U3RyZWFtKGRhdGEsIGZpbmFsaXplKSB7CiAgICAgIHJldHVybiBjaXBoZXIuZGVjcnlwdEJsb2NrKGRhdGEsIGZpbmFsaXplKTsKICAgIH0pOwogIH0KICBkZWNyeXB0U3RyaW5nKHMpIHsKICAgIGNvbnN0IGNpcGhlciA9IG5ldyB0aGlzLlN0cmluZ0NpcGhlckNvbnN0cnVjdG9yKCk7CiAgICBsZXQgZGF0YSA9ICgwLCBfdXRpbC5zdHJpbmdUb0J5dGVzKShzKTsKICAgIGRhdGEgPSBjaXBoZXIuZGVjcnlwdEJsb2NrKGRhdGEsIHRydWUpOwogICAgcmV0dXJuICgwLCBfdXRpbC5ieXRlc1RvU3RyaW5nKShkYXRhKTsKICB9CiAgZW5jcnlwdFN0cmluZyhzKSB7CiAgICBjb25zdCBjaXBoZXIgPSBuZXcgdGhpcy5TdHJpbmdDaXBoZXJDb25zdHJ1Y3RvcigpOwogICAgaWYgKGNpcGhlciBpbnN0YW5jZW9mIEFFU0Jhc2VDaXBoZXIpIHsKICAgICAgY29uc3Qgc3RyTGVuID0gcy5sZW5ndGg7CiAgICAgIGNvbnN0IHBhZCA9IDE2IC0gc3RyTGVuICUgMTY7CiAgICAgIHMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShwYWQpLnJlcGVhdChwYWQpOwogICAgICBjb25zdCBpdiA9IG5ldyBVaW50OEFycmF5KDE2KTsKICAgICAgaWYgKHR5cGVvZiBjcnlwdG8gIT09ICJ1bmRlZmluZWQiKSB7CiAgICAgICAgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhpdik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxNjsgaSsrKSB7CiAgICAgICAgICBpdltpXSA9IE1hdGguZmxvb3IoMjU2ICogTWF0aC5yYW5kb20oKSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGxldCBkYXRhID0gKDAsIF91dGlsLnN0cmluZ1RvQnl0ZXMpKHMpOwogICAgICBkYXRhID0gY2lwaGVyLmVuY3J5cHQoZGF0YSwgaXYpOwogICAgICBjb25zdCBidWYgPSBuZXcgVWludDhBcnJheSgxNiArIGRhdGEubGVuZ3RoKTsKICAgICAgYnVmLnNldChpdik7CiAgICAgIGJ1Zi5zZXQoZGF0YSwgMTYpOwogICAgICByZXR1cm4gKDAsIF91dGlsLmJ5dGVzVG9TdHJpbmcpKGJ1Zik7CiAgICB9CiAgICBsZXQgZGF0YSA9ICgwLCBfdXRpbC5zdHJpbmdUb0J5dGVzKShzKTsKICAgIGRhdGEgPSBjaXBoZXIuZW5jcnlwdChkYXRhKTsKICAgIHJldHVybiAoMCwgX3V0aWwuYnl0ZXNUb1N0cmluZykoZGF0YSk7CiAgfQp9CmNvbnN0IENpcGhlclRyYW5zZm9ybUZhY3RvcnkgPSBmdW5jdGlvbiBDaXBoZXJUcmFuc2Zvcm1GYWN0b3J5Q2xvc3VyZSgpIHsKICBjb25zdCBkZWZhdWx0UGFzc3dvcmRCeXRlcyA9IG5ldyBVaW50OEFycmF5KFsweDI4LCAweGJmLCAweDRlLCAweDVlLCAweDRlLCAweDc1LCAweDhhLCAweDQxLCAweDY0LCAweDAwLCAweDRlLCAweDU2LCAweGZmLCAweGZhLCAweDAxLCAweDA4LCAweDJlLCAweDJlLCAweDAwLCAweGI2LCAweGQwLCAweDY4LCAweDNlLCAweDgwLCAweDJmLCAweDBjLCAweGE5LCAweGZlLCAweDY0LCAweDUzLCAweDY5LCAweDdhXSk7CiAgZnVuY3Rpb24gY3JlYXRlRW5jcnlwdGlvbktleTIwKHJldmlzaW9uLCBwYXNzd29yZCwgb3duZXJQYXNzd29yZCwgb3duZXJWYWxpZGF0aW9uU2FsdCwgb3duZXJLZXlTYWx0LCB1Qnl0ZXMsIHVzZXJQYXNzd29yZCwgdXNlclZhbGlkYXRpb25TYWx0LCB1c2VyS2V5U2FsdCwgb3duZXJFbmNyeXB0aW9uLCB1c2VyRW5jcnlwdGlvbiwgcGVybXMpIHsKICAgIGlmIChwYXNzd29yZCkgewogICAgICBjb25zdCBwYXNzd29yZExlbmd0aCA9IE1hdGgubWluKDEyNywgcGFzc3dvcmQubGVuZ3RoKTsKICAgICAgcGFzc3dvcmQgPSBwYXNzd29yZC5zdWJhcnJheSgwLCBwYXNzd29yZExlbmd0aCk7CiAgICB9IGVsc2UgewogICAgICBwYXNzd29yZCA9IFtdOwogICAgfQogICAgbGV0IHBkZkFsZ29yaXRobTsKICAgIGlmIChyZXZpc2lvbiA9PT0gNikgewogICAgICBwZGZBbGdvcml0aG0gPSBuZXcgUERGMjAoKTsKICAgIH0gZWxzZSB7CiAgICAgIHBkZkFsZ29yaXRobSA9IG5ldyBQREYxNygpOwogICAgfQogICAgaWYgKHBkZkFsZ29yaXRobS5jaGVja1VzZXJQYXNzd29yZChwYXNzd29yZCwgdXNlclZhbGlkYXRpb25TYWx0LCB1c2VyUGFzc3dvcmQpKSB7CiAgICAgIHJldHVybiBwZGZBbGdvcml0aG0uZ2V0VXNlcktleShwYXNzd29yZCwgdXNlcktleVNhbHQsIHVzZXJFbmNyeXB0aW9uKTsKICAgIH0gZWxzZSBpZiAocGFzc3dvcmQubGVuZ3RoICYmIHBkZkFsZ29yaXRobS5jaGVja093bmVyUGFzc3dvcmQocGFzc3dvcmQsIG93bmVyVmFsaWRhdGlvblNhbHQsIHVCeXRlcywgb3duZXJQYXNzd29yZCkpIHsKICAgICAgcmV0dXJuIHBkZkFsZ29yaXRobS5nZXRPd25lcktleShwYXNzd29yZCwgb3duZXJLZXlTYWx0LCB1Qnl0ZXMsIG93bmVyRW5jcnlwdGlvbik7CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgZnVuY3Rpb24gcHJlcGFyZUtleURhdGEoZmlsZUlkLCBwYXNzd29yZCwgb3duZXJQYXNzd29yZCwgdXNlclBhc3N3b3JkLCBmbGFncywgcmV2aXNpb24sIGtleUxlbmd0aCwgZW5jcnlwdE1ldGFkYXRhKSB7CiAgICBjb25zdCBoYXNoRGF0YVNpemUgPSA0MCArIG93bmVyUGFzc3dvcmQubGVuZ3RoICsgZmlsZUlkLmxlbmd0aDsKICAgIGNvbnN0IGhhc2hEYXRhID0gbmV3IFVpbnQ4QXJyYXkoaGFzaERhdGFTaXplKTsKICAgIGxldCBpID0gMCwKICAgICAgaiwKICAgICAgbjsKICAgIGlmIChwYXNzd29yZCkgewogICAgICBuID0gTWF0aC5taW4oMzIsIHBhc3N3b3JkLmxlbmd0aCk7CiAgICAgIGZvciAoOyBpIDwgbjsgKytpKSB7CiAgICAgICAgaGFzaERhdGFbaV0gPSBwYXNzd29yZFtpXTsKICAgICAgfQogICAgfQogICAgaiA9IDA7CiAgICB3aGlsZSAoaSA8IDMyKSB7CiAgICAgIGhhc2hEYXRhW2krK10gPSBkZWZhdWx0UGFzc3dvcmRCeXRlc1tqKytdOwogICAgfQogICAgZm9yIChqID0gMCwgbiA9IG93bmVyUGFzc3dvcmQubGVuZ3RoOyBqIDwgbjsgKytqKSB7CiAgICAgIGhhc2hEYXRhW2krK10gPSBvd25lclBhc3N3b3JkW2pdOwogICAgfQogICAgaGFzaERhdGFbaSsrXSA9IGZsYWdzICYgMHhmZjsKICAgIGhhc2hEYXRhW2krK10gPSBmbGFncyA+PiA4ICYgMHhmZjsKICAgIGhhc2hEYXRhW2krK10gPSBmbGFncyA+PiAxNiAmIDB4ZmY7CiAgICBoYXNoRGF0YVtpKytdID0gZmxhZ3MgPj4+IDI0ICYgMHhmZjsKICAgIGZvciAoaiA9IDAsIG4gPSBmaWxlSWQubGVuZ3RoOyBqIDwgbjsgKytqKSB7CiAgICAgIGhhc2hEYXRhW2krK10gPSBmaWxlSWRbal07CiAgICB9CiAgICBpZiAocmV2aXNpb24gPj0gNCAmJiAhZW5jcnlwdE1ldGFkYXRhKSB7CiAgICAgIGhhc2hEYXRhW2krK10gPSAweGZmOwogICAgICBoYXNoRGF0YVtpKytdID0gMHhmZjsKICAgICAgaGFzaERhdGFbaSsrXSA9IDB4ZmY7CiAgICAgIGhhc2hEYXRhW2krK10gPSAweGZmOwogICAgfQogICAgbGV0IGhhc2ggPSBjYWxjdWxhdGVNRDUoaGFzaERhdGEsIDAsIGkpOwogICAgY29uc3Qga2V5TGVuZ3RoSW5CeXRlcyA9IGtleUxlbmd0aCA+PiAzOwogICAgaWYgKHJldmlzaW9uID49IDMpIHsKICAgICAgZm9yIChqID0gMDsgaiA8IDUwOyArK2opIHsKICAgICAgICBoYXNoID0gY2FsY3VsYXRlTUQ1KGhhc2gsIDAsIGtleUxlbmd0aEluQnl0ZXMpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gaGFzaC5zdWJhcnJheSgwLCBrZXlMZW5ndGhJbkJ5dGVzKTsKICAgIGxldCBjaXBoZXIsIGNoZWNrRGF0YTsKICAgIGlmIChyZXZpc2lvbiA+PSAzKSB7CiAgICAgIGZvciAoaSA9IDA7IGkgPCAzMjsgKytpKSB7CiAgICAgICAgaGFzaERhdGFbaV0gPSBkZWZhdWx0UGFzc3dvcmRCeXRlc1tpXTsKICAgICAgfQogICAgICBmb3IgKGogPSAwLCBuID0gZmlsZUlkLmxlbmd0aDsgaiA8IG47ICsraikgewogICAgICAgIGhhc2hEYXRhW2krK10gPSBmaWxlSWRbal07CiAgICAgIH0KICAgICAgY2lwaGVyID0gbmV3IEFSQ0ZvdXJDaXBoZXIoZW5jcnlwdGlvbktleSk7CiAgICAgIGNoZWNrRGF0YSA9IGNpcGhlci5lbmNyeXB0QmxvY2soY2FsY3VsYXRlTUQ1KGhhc2hEYXRhLCAwLCBpKSk7CiAgICAgIG4gPSBlbmNyeXB0aW9uS2V5Lmxlbmd0aDsKICAgICAgY29uc3QgZGVyaXZlZEtleSA9IG5ldyBVaW50OEFycmF5KG4pOwogICAgICBmb3IgKGogPSAxOyBqIDw9IDE5OyArK2opIHsKICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IG47ICsraykgewogICAgICAgICAgZGVyaXZlZEtleVtrXSA9IGVuY3J5cHRpb25LZXlba10gXiBqOwogICAgICAgIH0KICAgICAgICBjaXBoZXIgPSBuZXcgQVJDRm91ckNpcGhlcihkZXJpdmVkS2V5KTsKICAgICAgICBjaGVja0RhdGEgPSBjaXBoZXIuZW5jcnlwdEJsb2NrKGNoZWNrRGF0YSk7CiAgICAgIH0KICAgICAgZm9yIChqID0gMCwgbiA9IGNoZWNrRGF0YS5sZW5ndGg7IGogPCBuOyArK2opIHsKICAgICAgICBpZiAodXNlclBhc3N3b3JkW2pdICE9PSBjaGVja0RhdGFbal0pIHsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgY2lwaGVyID0gbmV3IEFSQ0ZvdXJDaXBoZXIoZW5jcnlwdGlvbktleSk7CiAgICAgIGNoZWNrRGF0YSA9IGNpcGhlci5lbmNyeXB0QmxvY2soZGVmYXVsdFBhc3N3b3JkQnl0ZXMpOwogICAgICBmb3IgKGogPSAwLCBuID0gY2hlY2tEYXRhLmxlbmd0aDsgaiA8IG47ICsraikgewogICAgICAgIGlmICh1c2VyUGFzc3dvcmRbal0gIT09IGNoZWNrRGF0YVtqXSkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gZW5jcnlwdGlvbktleTsKICB9CiAgZnVuY3Rpb24gZGVjb2RlVXNlclBhc3N3b3JkKHBhc3N3b3JkLCBvd25lclBhc3N3b3JkLCByZXZpc2lvbiwga2V5TGVuZ3RoKSB7CiAgICBjb25zdCBoYXNoRGF0YSA9IG5ldyBVaW50OEFycmF5KDMyKTsKICAgIGxldCBpID0gMDsKICAgIGNvbnN0IG4gPSBNYXRoLm1pbigzMiwgcGFzc3dvcmQubGVuZ3RoKTsKICAgIGZvciAoOyBpIDwgbjsgKytpKSB7CiAgICAgIGhhc2hEYXRhW2ldID0gcGFzc3dvcmRbaV07CiAgICB9CiAgICBsZXQgaiA9IDA7CiAgICB3aGlsZSAoaSA8IDMyKSB7CiAgICAgIGhhc2hEYXRhW2krK10gPSBkZWZhdWx0UGFzc3dvcmRCeXRlc1tqKytdOwogICAgfQogICAgbGV0IGhhc2ggPSBjYWxjdWxhdGVNRDUoaGFzaERhdGEsIDAsIGkpOwogICAgY29uc3Qga2V5TGVuZ3RoSW5CeXRlcyA9IGtleUxlbmd0aCA+PiAzOwogICAgaWYgKHJldmlzaW9uID49IDMpIHsKICAgICAgZm9yIChqID0gMDsgaiA8IDUwOyArK2opIHsKICAgICAgICBoYXNoID0gY2FsY3VsYXRlTUQ1KGhhc2gsIDAsIGhhc2gubGVuZ3RoKTsKICAgICAgfQogICAgfQogICAgbGV0IGNpcGhlciwgdXNlclBhc3N3b3JkOwogICAgaWYgKHJldmlzaW9uID49IDMpIHsKICAgICAgdXNlclBhc3N3b3JkID0gb3duZXJQYXNzd29yZDsKICAgICAgY29uc3QgZGVyaXZlZEtleSA9IG5ldyBVaW50OEFycmF5KGtleUxlbmd0aEluQnl0ZXMpOwogICAgICBmb3IgKGogPSAxOTsgaiA+PSAwOyBqLS0pIHsKICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IGtleUxlbmd0aEluQnl0ZXM7ICsraykgewogICAgICAgICAgZGVyaXZlZEtleVtrXSA9IGhhc2hba10gXiBqOwogICAgICAgIH0KICAgICAgICBjaXBoZXIgPSBuZXcgQVJDRm91ckNpcGhlcihkZXJpdmVkS2V5KTsKICAgICAgICB1c2VyUGFzc3dvcmQgPSBjaXBoZXIuZW5jcnlwdEJsb2NrKHVzZXJQYXNzd29yZCk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGNpcGhlciA9IG5ldyBBUkNGb3VyQ2lwaGVyKGhhc2guc3ViYXJyYXkoMCwga2V5TGVuZ3RoSW5CeXRlcykpOwogICAgICB1c2VyUGFzc3dvcmQgPSBjaXBoZXIuZW5jcnlwdEJsb2NrKG93bmVyUGFzc3dvcmQpOwogICAgfQogICAgcmV0dXJuIHVzZXJQYXNzd29yZDsKICB9CiAgY29uc3QgaWRlbnRpdHlOYW1lID0gX3ByaW1pdGl2ZXMuTmFtZS5nZXQoIklkZW50aXR5Iik7CiAgZnVuY3Rpb24gYnVpbGRPYmplY3RLZXkobnVtLCBnZW4sIGVuY3J5cHRpb25LZXkpIHsKICAgIGxldCBpc0FlcyA9IGFyZ3VtZW50cy5sZW5ndGggPiAzICYmIGFyZ3VtZW50c1szXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzNdIDogZmFsc2U7CiAgICBjb25zdCBrZXkgPSBuZXcgVWludDhBcnJheShlbmNyeXB0aW9uS2V5Lmxlbmd0aCArIDkpOwogICAgY29uc3QgbiA9IGVuY3J5cHRpb25LZXkubGVuZ3RoOwogICAgbGV0IGk7CiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7CiAgICAgIGtleVtpXSA9IGVuY3J5cHRpb25LZXlbaV07CiAgICB9CiAgICBrZXlbaSsrXSA9IG51bSAmIDB4ZmY7CiAgICBrZXlbaSsrXSA9IG51bSA+PiA4ICYgMHhmZjsKICAgIGtleVtpKytdID0gbnVtID4+IDE2ICYgMHhmZjsKICAgIGtleVtpKytdID0gZ2VuICYgMHhmZjsKICAgIGtleVtpKytdID0gZ2VuID4+IDggJiAweGZmOwogICAgaWYgKGlzQWVzKSB7CiAgICAgIGtleVtpKytdID0gMHg3MzsKICAgICAga2V5W2krK10gPSAweDQxOwogICAgICBrZXlbaSsrXSA9IDB4NmM7CiAgICAgIGtleVtpKytdID0gMHg1NDsKICAgIH0KICAgIGNvbnN0IGhhc2ggPSBjYWxjdWxhdGVNRDUoa2V5LCAwLCBpKTsKICAgIHJldHVybiBoYXNoLnN1YmFycmF5KDAsIE1hdGgubWluKGVuY3J5cHRpb25LZXkubGVuZ3RoICsgNSwgMTYpKTsKICB9CiAgZnVuY3Rpb24gYnVpbGRDaXBoZXJDb25zdHJ1Y3RvcihjZiwgbmFtZSwgbnVtLCBnZW4sIGtleSkgewogICAgaWYgKCEobmFtZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCBjcnlwdCBmaWx0ZXIgbmFtZS4iKTsKICAgIH0KICAgIGNvbnN0IGNyeXB0RmlsdGVyID0gY2YuZ2V0KG5hbWUubmFtZSk7CiAgICBsZXQgY2ZtOwogICAgaWYgKGNyeXB0RmlsdGVyICE9PSBudWxsICYmIGNyeXB0RmlsdGVyICE9PSB1bmRlZmluZWQpIHsKICAgICAgY2ZtID0gY3J5cHRGaWx0ZXIuZ2V0KCJDRk0iKTsKICAgIH0KICAgIGlmICghY2ZtIHx8IGNmbS5uYW1lID09PSAiTm9uZSIpIHsKICAgICAgcmV0dXJuIGZ1bmN0aW9uIGNpcGhlclRyYW5zZm9ybUZhY3RvcnlCdWlsZENpcGhlckNvbnN0cnVjdG9yTm9uZSgpIHsKICAgICAgICByZXR1cm4gbmV3IE51bGxDaXBoZXIoKTsKICAgICAgfTsKICAgIH0KICAgIGlmIChjZm0ubmFtZSA9PT0gIlYyIikgewogICAgICByZXR1cm4gZnVuY3Rpb24gY2lwaGVyVHJhbnNmb3JtRmFjdG9yeUJ1aWxkQ2lwaGVyQ29uc3RydWN0b3JWMigpIHsKICAgICAgICByZXR1cm4gbmV3IEFSQ0ZvdXJDaXBoZXIoYnVpbGRPYmplY3RLZXkobnVtLCBnZW4sIGtleSwgZmFsc2UpKTsKICAgICAgfTsKICAgIH0KICAgIGlmIChjZm0ubmFtZSA9PT0gIkFFU1YyIikgewogICAgICByZXR1cm4gZnVuY3Rpb24gY2lwaGVyVHJhbnNmb3JtRmFjdG9yeUJ1aWxkQ2lwaGVyQ29uc3RydWN0b3JBRVNWMigpIHsKICAgICAgICByZXR1cm4gbmV3IEFFUzEyOENpcGhlcihidWlsZE9iamVjdEtleShudW0sIGdlbiwga2V5LCB0cnVlKSk7CiAgICAgIH07CiAgICB9CiAgICBpZiAoY2ZtLm5hbWUgPT09ICJBRVNWMyIpIHsKICAgICAgcmV0dXJuIGZ1bmN0aW9uIGNpcGhlclRyYW5zZm9ybUZhY3RvcnlCdWlsZENpcGhlckNvbnN0cnVjdG9yQUVTVjMoKSB7CiAgICAgICAgcmV0dXJuIG5ldyBBRVMyNTZDaXBoZXIoa2V5KTsKICAgICAgfTsKICAgIH0KICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiVW5rbm93biBjcnlwdG8gbWV0aG9kIik7CiAgfQogIGNsYXNzIENpcGhlclRyYW5zZm9ybUZhY3RvcnkgewogICAgY29uc3RydWN0b3IoZGljdCwgZmlsZUlkLCBwYXNzd29yZCkgewogICAgICBjb25zdCBmaWx0ZXIgPSBkaWN0LmdldCgiRmlsdGVyIik7CiAgICAgIGlmICghKDAsIF9wcmltaXRpdmVzLmlzTmFtZSkoZmlsdGVyLCAiU3RhbmRhcmQiKSkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigidW5rbm93biBlbmNyeXB0aW9uIG1ldGhvZCIpOwogICAgICB9CiAgICAgIHRoaXMuZmlsdGVyTmFtZSA9IGZpbHRlci5uYW1lOwogICAgICB0aGlzLmRpY3QgPSBkaWN0OwogICAgICBjb25zdCBhbGdvcml0aG0gPSBkaWN0LmdldCgiViIpOwogICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoYWxnb3JpdGhtKSB8fCBhbGdvcml0aG0gIT09IDEgJiYgYWxnb3JpdGhtICE9PSAyICYmIGFsZ29yaXRobSAhPT0gNCAmJiBhbGdvcml0aG0gIT09IDUpIHsKICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoInVuc3VwcG9ydGVkIGVuY3J5cHRpb24gYWxnb3JpdGhtIik7CiAgICAgIH0KICAgICAgdGhpcy5hbGdvcml0aG0gPSBhbGdvcml0aG07CiAgICAgIGxldCBrZXlMZW5ndGggPSBkaWN0LmdldCgiTGVuZ3RoIik7CiAgICAgIGlmICgha2V5TGVuZ3RoKSB7CiAgICAgICAgaWYgKGFsZ29yaXRobSA8PSAzKSB7CiAgICAgICAgICBrZXlMZW5ndGggPSA0MDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgY2ZEaWN0ID0gZGljdC5nZXQoIkNGIik7CiAgICAgICAgICBjb25zdCBzdHJlYW1DcnlwdG9OYW1lID0gZGljdC5nZXQoIlN0bUYiKTsKICAgICAgICAgIGlmIChjZkRpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0ICYmIHN0cmVhbUNyeXB0b05hbWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgICAgICAgIGNmRGljdC5zdXBwcmVzc0VuY3J5cHRpb24gPSB0cnVlOwogICAgICAgICAgICBjb25zdCBoYW5kbGVyRGljdCA9IGNmRGljdC5nZXQoc3RyZWFtQ3J5cHRvTmFtZS5uYW1lKTsKICAgICAgICAgICAga2V5TGVuZ3RoID0gaGFuZGxlckRpY3QgJiYgaGFuZGxlckRpY3QuZ2V0KCJMZW5ndGgiKSB8fCAxMjg7CiAgICAgICAgICAgIGlmIChrZXlMZW5ndGggPCA0MCkgewogICAgICAgICAgICAgIGtleUxlbmd0aCA8PD0gMzsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoa2V5TGVuZ3RoKSB8fCBrZXlMZW5ndGggPCA0MCB8fCBrZXlMZW5ndGggJSA4ICE9PSAwKSB7CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJpbnZhbGlkIGtleSBsZW5ndGgiKTsKICAgICAgfQogICAgICBjb25zdCBvd25lclBhc3N3b3JkID0gKDAsIF91dGlsLnN0cmluZ1RvQnl0ZXMpKGRpY3QuZ2V0KCJPIikpLnN1YmFycmF5KDAsIDMyKTsKICAgICAgY29uc3QgdXNlclBhc3N3b3JkID0gKDAsIF91dGlsLnN0cmluZ1RvQnl0ZXMpKGRpY3QuZ2V0KCJVIikpLnN1YmFycmF5KDAsIDMyKTsKICAgICAgY29uc3QgZmxhZ3MgPSBkaWN0LmdldCgiUCIpOwogICAgICBjb25zdCByZXZpc2lvbiA9IGRpY3QuZ2V0KCJSIik7CiAgICAgIGNvbnN0IGVuY3J5cHRNZXRhZGF0YSA9IChhbGdvcml0aG0gPT09IDQgfHwgYWxnb3JpdGhtID09PSA1KSAmJiBkaWN0LmdldCgiRW5jcnlwdE1ldGFkYXRhIikgIT09IGZhbHNlOwogICAgICB0aGlzLmVuY3J5cHRNZXRhZGF0YSA9IGVuY3J5cHRNZXRhZGF0YTsKICAgICAgY29uc3QgZmlsZUlkQnl0ZXMgPSAoMCwgX3V0aWwuc3RyaW5nVG9CeXRlcykoZmlsZUlkKTsKICAgICAgbGV0IHBhc3N3b3JkQnl0ZXM7CiAgICAgIGlmIChwYXNzd29yZCkgewogICAgICAgIGlmIChyZXZpc2lvbiA9PT0gNikgewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcGFzc3dvcmQgPSAoMCwgX3V0aWwudXRmOFN0cmluZ1RvU3RyaW5nKShwYXNzd29yZCk7CiAgICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoIkNpcGhlclRyYW5zZm9ybUZhY3Rvcnk6ICIgKyAiVW5hYmxlIHRvIGNvbnZlcnQgVVRGOCBlbmNvZGVkIHBhc3N3b3JkLiIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBwYXNzd29yZEJ5dGVzID0gKDAsIF91dGlsLnN0cmluZ1RvQnl0ZXMpKHBhc3N3b3JkKTsKICAgICAgfQogICAgICBsZXQgZW5jcnlwdGlvbktleTsKICAgICAgaWYgKGFsZ29yaXRobSAhPT0gNSkgewogICAgICAgIGVuY3J5cHRpb25LZXkgPSBwcmVwYXJlS2V5RGF0YShmaWxlSWRCeXRlcywgcGFzc3dvcmRCeXRlcywgb3duZXJQYXNzd29yZCwgdXNlclBhc3N3b3JkLCBmbGFncywgcmV2aXNpb24sIGtleUxlbmd0aCwgZW5jcnlwdE1ldGFkYXRhKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBvd25lclZhbGlkYXRpb25TYWx0ID0gKDAsIF91dGlsLnN0cmluZ1RvQnl0ZXMpKGRpY3QuZ2V0KCJPIikpLnN1YmFycmF5KDMyLCA0MCk7CiAgICAgICAgY29uc3Qgb3duZXJLZXlTYWx0ID0gKDAsIF91dGlsLnN0cmluZ1RvQnl0ZXMpKGRpY3QuZ2V0KCJPIikpLnN1YmFycmF5KDQwLCA0OCk7CiAgICAgICAgY29uc3QgdUJ5dGVzID0gKDAsIF91dGlsLnN0cmluZ1RvQnl0ZXMpKGRpY3QuZ2V0KCJVIikpLnN1YmFycmF5KDAsIDQ4KTsKICAgICAgICBjb25zdCB1c2VyVmFsaWRhdGlvblNhbHQgPSAoMCwgX3V0aWwuc3RyaW5nVG9CeXRlcykoZGljdC5nZXQoIlUiKSkuc3ViYXJyYXkoMzIsIDQwKTsKICAgICAgICBjb25zdCB1c2VyS2V5U2FsdCA9ICgwLCBfdXRpbC5zdHJpbmdUb0J5dGVzKShkaWN0LmdldCgiVSIpKS5zdWJhcnJheSg0MCwgNDgpOwogICAgICAgIGNvbnN0IG93bmVyRW5jcnlwdGlvbiA9ICgwLCBfdXRpbC5zdHJpbmdUb0J5dGVzKShkaWN0LmdldCgiT0UiKSk7CiAgICAgICAgY29uc3QgdXNlckVuY3J5cHRpb24gPSAoMCwgX3V0aWwuc3RyaW5nVG9CeXRlcykoZGljdC5nZXQoIlVFIikpOwogICAgICAgIGNvbnN0IHBlcm1zID0gKDAsIF91dGlsLnN0cmluZ1RvQnl0ZXMpKGRpY3QuZ2V0KCJQZXJtcyIpKTsKICAgICAgICBlbmNyeXB0aW9uS2V5ID0gY3JlYXRlRW5jcnlwdGlvbktleTIwKHJldmlzaW9uLCBwYXNzd29yZEJ5dGVzLCBvd25lclBhc3N3b3JkLCBvd25lclZhbGlkYXRpb25TYWx0LCBvd25lcktleVNhbHQsIHVCeXRlcywgdXNlclBhc3N3b3JkLCB1c2VyVmFsaWRhdGlvblNhbHQsIHVzZXJLZXlTYWx0LCBvd25lckVuY3J5cHRpb24sIHVzZXJFbmNyeXB0aW9uLCBwZXJtcyk7CiAgICAgIH0KICAgICAgaWYgKCFlbmNyeXB0aW9uS2V5ICYmICFwYXNzd29yZCkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5QYXNzd29yZEV4Y2VwdGlvbigiTm8gcGFzc3dvcmQgZ2l2ZW4iLCBfdXRpbC5QYXNzd29yZFJlc3BvbnNlcy5ORUVEX1BBU1NXT1JEKTsKICAgICAgfSBlbHNlIGlmICghZW5jcnlwdGlvbktleSAmJiBwYXNzd29yZCkgewogICAgICAgIGNvbnN0IGRlY29kZWRQYXNzd29yZCA9IGRlY29kZVVzZXJQYXNzd29yZChwYXNzd29yZEJ5dGVzLCBvd25lclBhc3N3b3JkLCByZXZpc2lvbiwga2V5TGVuZ3RoKTsKICAgICAgICBlbmNyeXB0aW9uS2V5ID0gcHJlcGFyZUtleURhdGEoZmlsZUlkQnl0ZXMsIGRlY29kZWRQYXNzd29yZCwgb3duZXJQYXNzd29yZCwgdXNlclBhc3N3b3JkLCBmbGFncywgcmV2aXNpb24sIGtleUxlbmd0aCwgZW5jcnlwdE1ldGFkYXRhKTsKICAgICAgfQogICAgICBpZiAoIWVuY3J5cHRpb25LZXkpIHsKICAgICAgICB0aHJvdyBuZXcgX3V0aWwuUGFzc3dvcmRFeGNlcHRpb24oIkluY29ycmVjdCBQYXNzd29yZCIsIF91dGlsLlBhc3N3b3JkUmVzcG9uc2VzLklOQ09SUkVDVF9QQVNTV09SRCk7CiAgICAgIH0KICAgICAgdGhpcy5lbmNyeXB0aW9uS2V5ID0gZW5jcnlwdGlvbktleTsKICAgICAgaWYgKGFsZ29yaXRobSA+PSA0KSB7CiAgICAgICAgY29uc3QgY2YgPSBkaWN0LmdldCgiQ0YiKTsKICAgICAgICBpZiAoY2YgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgICAgICBjZi5zdXBwcmVzc0VuY3J5cHRpb24gPSB0cnVlOwogICAgICAgIH0KICAgICAgICB0aGlzLmNmID0gY2Y7CiAgICAgICAgdGhpcy5zdG1mID0gZGljdC5nZXQoIlN0bUYiKSB8fCBpZGVudGl0eU5hbWU7CiAgICAgICAgdGhpcy5zdHJmID0gZGljdC5nZXQoIlN0ckYiKSB8fCBpZGVudGl0eU5hbWU7CiAgICAgICAgdGhpcy5lZmYgPSBkaWN0LmdldCgiRUZGIikgfHwgdGhpcy5zdG1mOwogICAgICB9CiAgICB9CiAgICBjcmVhdGVDaXBoZXJUcmFuc2Zvcm0obnVtLCBnZW4pIHsKICAgICAgaWYgKHRoaXMuYWxnb3JpdGhtID09PSA0IHx8IHRoaXMuYWxnb3JpdGhtID09PSA1KSB7CiAgICAgICAgcmV0dXJuIG5ldyBDaXBoZXJUcmFuc2Zvcm0oYnVpbGRDaXBoZXJDb25zdHJ1Y3Rvcih0aGlzLmNmLCB0aGlzLnN0cmYsIG51bSwgZ2VuLCB0aGlzLmVuY3J5cHRpb25LZXkpLCBidWlsZENpcGhlckNvbnN0cnVjdG9yKHRoaXMuY2YsIHRoaXMuc3RtZiwgbnVtLCBnZW4sIHRoaXMuZW5jcnlwdGlvbktleSkpOwogICAgICB9CiAgICAgIGNvbnN0IGtleSA9IGJ1aWxkT2JqZWN0S2V5KG51bSwgZ2VuLCB0aGlzLmVuY3J5cHRpb25LZXksIGZhbHNlKTsKICAgICAgY29uc3QgY2lwaGVyQ29uc3RydWN0b3IgPSBmdW5jdGlvbiBidWlsZENpcGhlckNpcGhlckNvbnN0cnVjdG9yKCkgewogICAgICAgIHJldHVybiBuZXcgQVJDRm91ckNpcGhlcihrZXkpOwogICAgICB9OwogICAgICByZXR1cm4gbmV3IENpcGhlclRyYW5zZm9ybShjaXBoZXJDb25zdHJ1Y3RvciwgY2lwaGVyQ29uc3RydWN0b3IpOwogICAgfQogIH0KICByZXR1cm4gQ2lwaGVyVHJhbnNmb3JtRmFjdG9yeTsKfSgpOwpleHBvcnRzLkNpcGhlclRyYW5zZm9ybUZhY3RvcnkgPSBDaXBoZXJUcmFuc2Zvcm1GYWN0b3J5OwoKLyoqKi8gfSksCi8qIDIwMyAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuRGVjcnlwdFN0cmVhbSA9IHZvaWQgMDsKdmFyIF9kZWNvZGVfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNTMpOwpjb25zdCBjaHVua1NpemUgPSA1MTI7CmNsYXNzIERlY3J5cHRTdHJlYW0gZXh0ZW5kcyBfZGVjb2RlX3N0cmVhbS5EZWNvZGVTdHJlYW0gewogIGNvbnN0cnVjdG9yKHN0ciwgbWF5YmVMZW5ndGgsIGRlY3J5cHQpIHsKICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyID0gc3RyOwogICAgdGhpcy5kaWN0ID0gc3RyLmRpY3Q7CiAgICB0aGlzLmRlY3J5cHQgPSBkZWNyeXB0OwogICAgdGhpcy5uZXh0Q2h1bmsgPSBudWxsOwogICAgdGhpcy5pbml0aWFsaXplZCA9IGZhbHNlOwogIH0KICByZWFkQmxvY2soKSB7CiAgICBsZXQgY2h1bms7CiAgICBpZiAodGhpcy5pbml0aWFsaXplZCkgewogICAgICBjaHVuayA9IHRoaXMubmV4dENodW5rOwogICAgfSBlbHNlIHsKICAgICAgY2h1bmsgPSB0aGlzLnN0ci5nZXRCeXRlcyhjaHVua1NpemUpOwogICAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTsKICAgIH0KICAgIGlmICghY2h1bmsgfHwgY2h1bmsubGVuZ3RoID09PSAwKSB7CiAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5uZXh0Q2h1bmsgPSB0aGlzLnN0ci5nZXRCeXRlcyhjaHVua1NpemUpOwogICAgY29uc3QgaGFzTW9yZURhdGEgPSB0aGlzLm5leHRDaHVuayAmJiB0aGlzLm5leHRDaHVuay5sZW5ndGggPiAwOwogICAgY29uc3QgZGVjcnlwdCA9IHRoaXMuZGVjcnlwdDsKICAgIGNodW5rID0gZGVjcnlwdChjaHVuaywgIWhhc01vcmVEYXRhKTsKICAgIGNvbnN0IGJ1ZmZlckxlbmd0aCA9IHRoaXMuYnVmZmVyTGVuZ3RoLAogICAgICBuZXdMZW5ndGggPSBidWZmZXJMZW5ndGggKyBjaHVuay5sZW5ndGgsCiAgICAgIGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKG5ld0xlbmd0aCk7CiAgICBidWZmZXIuc2V0KGNodW5rLCBidWZmZXJMZW5ndGgpOwogICAgdGhpcy5idWZmZXJMZW5ndGggPSBuZXdMZW5ndGg7CiAgfQp9CmV4cG9ydHMuRGVjcnlwdFN0cmVhbSA9IERlY3J5cHRTdHJlYW07CgovKioqLyB9KSwKLyogMjA0ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5DYXRhbG9nID0gdm9pZCAwOwp2YXIgX2NvcmVfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzOSk7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CnZhciBfcHJpbWl0aXZlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQwKTsKdmFyIF9uYW1lX251bWJlcl90cmVlID0gX193X3BkZmpzX3JlcXVpcmVfXygyMDUpOwp2YXIgX2Jhc2Vfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDEpOwp2YXIgX2NsZWFudXBfaGVscGVyID0gX193X3BkZmpzX3JlcXVpcmVfXygyMDYpOwp2YXIgX2NvbG9yc3BhY2UgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0OCk7CnZhciBfZmlsZV9zcGVjID0gX193X3BkZmpzX3JlcXVpcmVfXygyMDcpOwp2YXIgX2ltYWdlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxOTQpOwp2YXIgX21ldGFkYXRhX3BhcnNlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMjA4KTsKdmFyIF9zdHJ1Y3RfdHJlZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjA5KTsKZnVuY3Rpb24gZmV0Y2hEZXN0aW5hdGlvbihkZXN0KSB7CiAgaWYgKGRlc3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICBkZXN0ID0gZGVzdC5nZXQoIkQiKTsKICB9CiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoZGVzdCkgPyBkZXN0IDogbnVsbDsKfQpjbGFzcyBDYXRhbG9nIHsKICBjb25zdHJ1Y3RvcihwZGZNYW5hZ2VyLCB4cmVmKSB7CiAgICB0aGlzLnBkZk1hbmFnZXIgPSBwZGZNYW5hZ2VyOwogICAgdGhpcy54cmVmID0geHJlZjsKICAgIHRoaXMuX2NhdERpY3QgPSB4cmVmLmdldENhdGFsb2dPYmooKTsKICAgIGlmICghKHRoaXMuX2NhdERpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkNhdGFsb2cgb2JqZWN0IGlzIG5vdCBhIGRpY3Rpb25hcnkuIik7CiAgICB9CiAgICB0aGlzLnRvcGxldmVsUGFnZXNEaWN0OwogICAgdGhpcy5fYWN0dWFsTnVtUGFnZXMgPSBudWxsOwogICAgdGhpcy5mb250Q2FjaGUgPSBuZXcgX3ByaW1pdGl2ZXMuUmVmU2V0Q2FjaGUoKTsKICAgIHRoaXMuYnVpbHRJbkNNYXBDYWNoZSA9IG5ldyBNYXAoKTsKICAgIHRoaXMuc3RhbmRhcmRGb250RGF0YUNhY2hlID0gbmV3IE1hcCgpOwogICAgdGhpcy5nbG9iYWxJbWFnZUNhY2hlID0gbmV3IF9pbWFnZV91dGlscy5HbG9iYWxJbWFnZUNhY2hlKCk7CiAgICB0aGlzLnBhZ2VLaWRzQ291bnRDYWNoZSA9IG5ldyBfcHJpbWl0aXZlcy5SZWZTZXRDYWNoZSgpOwogICAgdGhpcy5wYWdlSW5kZXhDYWNoZSA9IG5ldyBfcHJpbWl0aXZlcy5SZWZTZXRDYWNoZSgpOwogICAgdGhpcy5ub25CbGVuZE1vZGVzU2V0ID0gbmV3IF9wcmltaXRpdmVzLlJlZlNldCgpOwogIH0KICBnZXQgdmVyc2lvbigpIHsKICAgIGNvbnN0IHZlcnNpb24gPSB0aGlzLl9jYXREaWN0LmdldCgiVmVyc2lvbiIpOwogICAgaWYgKHZlcnNpb24gaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgIGlmIChfY29yZV91dGlscy5QREZfVkVSU0lPTl9SRUdFWFAudGVzdCh2ZXJzaW9uLm5hbWUpKSB7CiAgICAgICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJ2ZXJzaW9uIiwgdmVyc2lvbi5uYW1lKTsKICAgICAgfQogICAgICAoMCwgX3V0aWwud2FybikoYEludmFsaWQgUERGIGNhdGFsb2cgdmVyc2lvbjogJHt2ZXJzaW9uLm5hbWV9YCk7CiAgICB9CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInZlcnNpb24iLCBudWxsKTsKICB9CiAgZ2V0IGxhbmcoKSB7CiAgICBjb25zdCBsYW5nID0gdGhpcy5fY2F0RGljdC5nZXQoIkxhbmciKTsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAibGFuZyIsIHR5cGVvZiBsYW5nID09PSAic3RyaW5nIiA/ICgwLCBfdXRpbC5zdHJpbmdUb1BERlN0cmluZykobGFuZykgOiBudWxsKTsKICB9CiAgZ2V0IG5lZWRzUmVuZGVyaW5nKCkgewogICAgY29uc3QgbmVlZHNSZW5kZXJpbmcgPSB0aGlzLl9jYXREaWN0LmdldCgiTmVlZHNSZW5kZXJpbmciKTsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAibmVlZHNSZW5kZXJpbmciLCB0eXBlb2YgbmVlZHNSZW5kZXJpbmcgPT09ICJib29sZWFuIiA/IG5lZWRzUmVuZGVyaW5nIDogZmFsc2UpOwogIH0KICBnZXQgY29sbGVjdGlvbigpIHsKICAgIGxldCBjb2xsZWN0aW9uID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIGNvbnN0IG9iaiA9IHRoaXMuX2NhdERpY3QuZ2V0KCJDb2xsZWN0aW9uIik7CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0ICYmIG9iai5zaXplID4gMCkgewogICAgICAgIGNvbGxlY3Rpb24gPSBvYmo7CiAgICAgIH0KICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgKDAsIF91dGlsLmluZm8pKCJDYW5ub3QgZmV0Y2ggQ29sbGVjdGlvbiBlbnRyeTsgYXNzdW1pbmcgbm8gY29sbGVjdGlvbiBpcyBwcmVzZW50LiIpOwogICAgfQogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJjb2xsZWN0aW9uIiwgY29sbGVjdGlvbik7CiAgfQogIGdldCBhY3JvRm9ybSgpIHsKICAgIGxldCBhY3JvRm9ybSA9IG51bGw7CiAgICB0cnkgewogICAgICBjb25zdCBvYmogPSB0aGlzLl9jYXREaWN0LmdldCgiQWNyb0Zvcm0iKTsKICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QgJiYgb2JqLnNpemUgPiAwKSB7CiAgICAgICAgYWNyb0Zvcm0gPSBvYmo7CiAgICAgIH0KICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgKDAsIF91dGlsLmluZm8pKCJDYW5ub3QgZmV0Y2ggQWNyb0Zvcm0gZW50cnk7IGFzc3VtaW5nIG5vIGZvcm1zIGFyZSBwcmVzZW50LiIpOwogICAgfQogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJhY3JvRm9ybSIsIGFjcm9Gb3JtKTsKICB9CiAgZ2V0IGFjcm9Gb3JtUmVmKCkgewogICAgY29uc3QgdmFsdWUgPSB0aGlzLl9jYXREaWN0LmdldFJhdygiQWNyb0Zvcm0iKTsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiYWNyb0Zvcm1SZWYiLCB2YWx1ZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZiA/IHZhbHVlIDogbnVsbCk7CiAgfQogIGdldCBtZXRhZGF0YSgpIHsKICAgIGNvbnN0IHN0cmVhbVJlZiA9IHRoaXMuX2NhdERpY3QuZ2V0UmF3KCJNZXRhZGF0YSIpOwogICAgaWYgKCEoc3RyZWFtUmVmIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSkgewogICAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIm1ldGFkYXRhIiwgbnVsbCk7CiAgICB9CiAgICBsZXQgbWV0YWRhdGEgPSBudWxsOwogICAgdHJ5IHsKICAgICAgY29uc3Qgc3VwcHJlc3NFbmNyeXB0aW9uID0gISh0aGlzLnhyZWYuZW5jcnlwdCAmJiB0aGlzLnhyZWYuZW5jcnlwdC5lbmNyeXB0TWV0YWRhdGEpOwogICAgICBjb25zdCBzdHJlYW0gPSB0aGlzLnhyZWYuZmV0Y2goc3RyZWFtUmVmLCBzdXBwcmVzc0VuY3J5cHRpb24pOwogICAgICBpZiAoc3RyZWFtIGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0gJiYgc3RyZWFtLmRpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgICAgY29uc3QgdHlwZSA9IHN0cmVhbS5kaWN0LmdldCgiVHlwZSIpOwogICAgICAgIGNvbnN0IHN1YnR5cGUgPSBzdHJlYW0uZGljdC5nZXQoIlN1YnR5cGUiKTsKICAgICAgICBpZiAoKDAsIF9wcmltaXRpdmVzLmlzTmFtZSkodHlwZSwgIk1ldGFkYXRhIikgJiYgKDAsIF9wcmltaXRpdmVzLmlzTmFtZSkoc3VidHlwZSwgIlhNTCIpKSB7CiAgICAgICAgICBjb25zdCBkYXRhID0gKDAsIF91dGlsLnN0cmluZ1RvVVRGOFN0cmluZykoc3RyZWFtLmdldFN0cmluZygpKTsKICAgICAgICAgIGlmIChkYXRhKSB7CiAgICAgICAgICAgIG1ldGFkYXRhID0gbmV3IF9tZXRhZGF0YV9wYXJzZXIuTWV0YWRhdGFQYXJzZXIoZGF0YSkuc2VyaWFsaXphYmxlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgX2NvcmVfdXRpbHMuTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICAoMCwgX3V0aWwuaW5mbykoYFNraXBwaW5nIGludmFsaWQgTWV0YWRhdGE6ICIke2V4fSIuYCk7CiAgICB9CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIm1ldGFkYXRhIiwgbWV0YWRhdGEpOwogIH0KICBnZXQgbWFya0luZm8oKSB7CiAgICBsZXQgbWFya0luZm8gPSBudWxsOwogICAgdHJ5IHsKICAgICAgbWFya0luZm8gPSB0aGlzLl9yZWFkTWFya0luZm8oKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgKDAsIF91dGlsLndhcm4pKCJVbmFibGUgdG8gcmVhZCBtYXJrIGluZm8uIik7CiAgICB9CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIm1hcmtJbmZvIiwgbWFya0luZm8pOwogIH0KICBfcmVhZE1hcmtJbmZvKCkgewogICAgY29uc3Qgb2JqID0gdGhpcy5fY2F0RGljdC5nZXQoIk1hcmtJbmZvIik7CiAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IG1hcmtJbmZvID0gewogICAgICBNYXJrZWQ6IGZhbHNlLAogICAgICBVc2VyUHJvcGVydGllczogZmFsc2UsCiAgICAgIFN1c3BlY3RzOiBmYWxzZQogICAgfTsKICAgIGZvciAoY29uc3Qga2V5IGluIG1hcmtJbmZvKSB7CiAgICAgIGNvbnN0IHZhbHVlID0gb2JqLmdldChrZXkpOwogICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAiYm9vbGVhbiIpIHsKICAgICAgICBtYXJrSW5mb1trZXldID0gdmFsdWU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBtYXJrSW5mbzsKICB9CiAgZ2V0IHN0cnVjdFRyZWVSb290KCkgewogICAgbGV0IHN0cnVjdFRyZWUgPSBudWxsOwogICAgdHJ5IHsKICAgICAgc3RydWN0VHJlZSA9IHRoaXMuX3JlYWRTdHJ1Y3RUcmVlUm9vdCgpOwogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgX2NvcmVfdXRpbHMuTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICAoMCwgX3V0aWwud2FybikoIlVuYWJsZSByZWFkIHRvIHN0cnVjdFRyZWVSb290IGluZm8uIik7CiAgICB9CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInN0cnVjdFRyZWVSb290Iiwgc3RydWN0VHJlZSk7CiAgfQogIF9yZWFkU3RydWN0VHJlZVJvb3QoKSB7CiAgICBjb25zdCBvYmogPSB0aGlzLl9jYXREaWN0LmdldCgiU3RydWN0VHJlZVJvb3QiKTsKICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3Qgcm9vdCA9IG5ldyBfc3RydWN0X3RyZWUuU3RydWN0VHJlZVJvb3Qob2JqKTsKICAgIHJvb3QuaW5pdCgpOwogICAgcmV0dXJuIHJvb3Q7CiAgfQogIGdldCB0b3BsZXZlbFBhZ2VzRGljdCgpIHsKICAgIGNvbnN0IHBhZ2VzT2JqID0gdGhpcy5fY2F0RGljdC5nZXQoIlBhZ2VzIik7CiAgICBpZiAoIShwYWdlc09iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCB0b3AtbGV2ZWwgcGFnZXMgZGljdGlvbmFyeS4iKTsKICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAidG9wbGV2ZWxQYWdlc0RpY3QiLCBwYWdlc09iaik7CiAgfQogIGdldCBkb2N1bWVudE91dGxpbmUoKSB7CiAgICBsZXQgb2JqID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIG9iaiA9IHRoaXMuX3JlYWREb2N1bWVudE91dGxpbmUoKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgKDAsIF91dGlsLndhcm4pKCJVbmFibGUgdG8gcmVhZCBkb2N1bWVudCBvdXRsaW5lLiIpOwogICAgfQogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJkb2N1bWVudE91dGxpbmUiLCBvYmopOwogIH0KICBfcmVhZERvY3VtZW50T3V0bGluZSgpIHsKICAgIGxldCBvYmogPSB0aGlzLl9jYXREaWN0LmdldCgiT3V0bGluZXMiKTsKICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgb2JqID0gb2JqLmdldFJhdygiRmlyc3QiKTsKICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCByb290ID0gewogICAgICBpdGVtczogW10KICAgIH07CiAgICBjb25zdCBxdWV1ZSA9IFt7CiAgICAgIG9iaiwKICAgICAgcGFyZW50OiByb290CiAgICB9XTsKICAgIGNvbnN0IHByb2Nlc3NlZCA9IG5ldyBfcHJpbWl0aXZlcy5SZWZTZXQoKTsKICAgIHByb2Nlc3NlZC5wdXQob2JqKTsKICAgIGNvbnN0IHhyZWYgPSB0aGlzLnhyZWYsCiAgICAgIGJsYWNrQ29sb3IgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoMyk7CiAgICB3aGlsZSAocXVldWUubGVuZ3RoID4gMCkgewogICAgICBjb25zdCBpID0gcXVldWUuc2hpZnQoKTsKICAgICAgY29uc3Qgb3V0bGluZURpY3QgPSB4cmVmLmZldGNoSWZSZWYoaS5vYmopOwogICAgICBpZiAob3V0bGluZURpY3QgPT09IG51bGwpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoIW91dGxpbmVEaWN0LmhhcygiVGl0bGUiKSkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCBvdXRsaW5lIGl0ZW0gZW5jb3VudGVyZWQuIik7CiAgICAgIH0KICAgICAgY29uc3QgZGF0YSA9IHsKICAgICAgICB1cmw6IG51bGwsCiAgICAgICAgZGVzdDogbnVsbCwKICAgICAgICBhY3Rpb246IG51bGwKICAgICAgfTsKICAgICAgQ2F0YWxvZy5wYXJzZURlc3REaWN0aW9uYXJ5KHsKICAgICAgICBkZXN0RGljdDogb3V0bGluZURpY3QsCiAgICAgICAgcmVzdWx0T2JqOiBkYXRhLAogICAgICAgIGRvY0Jhc2VVcmw6IHRoaXMucGRmTWFuYWdlci5kb2NCYXNlVXJsLAogICAgICAgIGRvY0F0dGFjaG1lbnRzOiB0aGlzLmF0dGFjaG1lbnRzCiAgICAgIH0pOwogICAgICBjb25zdCB0aXRsZSA9IG91dGxpbmVEaWN0LmdldCgiVGl0bGUiKTsKICAgICAgY29uc3QgZmxhZ3MgPSBvdXRsaW5lRGljdC5nZXQoIkYiKSB8fCAwOwogICAgICBjb25zdCBjb2xvciA9IG91dGxpbmVEaWN0LmdldEFycmF5KCJDIik7CiAgICAgIGNvbnN0IGNvdW50ID0gb3V0bGluZURpY3QuZ2V0KCJDb3VudCIpOwogICAgICBsZXQgcmdiQ29sb3IgPSBibGFja0NvbG9yOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShjb2xvcikgJiYgY29sb3IubGVuZ3RoID09PSAzICYmIChjb2xvclswXSAhPT0gMCB8fCBjb2xvclsxXSAhPT0gMCB8fCBjb2xvclsyXSAhPT0gMCkpIHsKICAgICAgICByZ2JDb2xvciA9IF9jb2xvcnNwYWNlLkNvbG9yU3BhY2Uuc2luZ2xldG9ucy5yZ2IuZ2V0UmdiKGNvbG9yLCAwKTsKICAgICAgfQogICAgICBjb25zdCBvdXRsaW5lSXRlbSA9IHsKICAgICAgICBhY3Rpb246IGRhdGEuYWN0aW9uLAogICAgICAgIGF0dGFjaG1lbnQ6IGRhdGEuYXR0YWNobWVudCwKICAgICAgICBkZXN0OiBkYXRhLmRlc3QsCiAgICAgICAgdXJsOiBkYXRhLnVybCwKICAgICAgICB1bnNhZmVVcmw6IGRhdGEudW5zYWZlVXJsLAogICAgICAgIG5ld1dpbmRvdzogZGF0YS5uZXdXaW5kb3csCiAgICAgICAgc2V0T0NHU3RhdGU6IGRhdGEuc2V0T0NHU3RhdGUsCiAgICAgICAgdGl0bGU6ICgwLCBfdXRpbC5zdHJpbmdUb1BERlN0cmluZykodGl0bGUpLAogICAgICAgIGNvbG9yOiByZ2JDb2xvciwKICAgICAgICBjb3VudDogTnVtYmVyLmlzSW50ZWdlcihjb3VudCkgPyBjb3VudCA6IHVuZGVmaW5lZCwKICAgICAgICBib2xkOiAhIShmbGFncyAmIDIpLAogICAgICAgIGl0YWxpYzogISEoZmxhZ3MgJiAxKSwKICAgICAgICBpdGVtczogW10KICAgICAgfTsKICAgICAgaS5wYXJlbnQuaXRlbXMucHVzaChvdXRsaW5lSXRlbSk7CiAgICAgIG9iaiA9IG91dGxpbmVEaWN0LmdldFJhdygiRmlyc3QiKTsKICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZiAmJiAhcHJvY2Vzc2VkLmhhcyhvYmopKSB7CiAgICAgICAgcXVldWUucHVzaCh7CiAgICAgICAgICBvYmosCiAgICAgICAgICBwYXJlbnQ6IG91dGxpbmVJdGVtCiAgICAgICAgfSk7CiAgICAgICAgcHJvY2Vzc2VkLnB1dChvYmopOwogICAgICB9CiAgICAgIG9iaiA9IG91dGxpbmVEaWN0LmdldFJhdygiTmV4dCIpOwogICAgICBpZiAob2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmICYmICFwcm9jZXNzZWQuaGFzKG9iaikpIHsKICAgICAgICBxdWV1ZS5wdXNoKHsKICAgICAgICAgIG9iaiwKICAgICAgICAgIHBhcmVudDogaS5wYXJlbnQKICAgICAgICB9KTsKICAgICAgICBwcm9jZXNzZWQucHV0KG9iaik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiByb290Lml0ZW1zLmxlbmd0aCA+IDAgPyByb290Lml0ZW1zIDogbnVsbDsKICB9CiAgZ2V0IHBlcm1pc3Npb25zKCkgewogICAgbGV0IHBlcm1pc3Npb25zID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIHBlcm1pc3Npb25zID0gdGhpcy5fcmVhZFBlcm1pc3Npb25zKCk7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBfY29yZV91dGlscy5NaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgICgwLCBfdXRpbC53YXJuKSgiVW5hYmxlIHRvIHJlYWQgcGVybWlzc2lvbnMuIik7CiAgICB9CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInBlcm1pc3Npb25zIiwgcGVybWlzc2lvbnMpOwogIH0KICBfcmVhZFBlcm1pc3Npb25zKCkgewogICAgY29uc3QgZW5jcnlwdCA9IHRoaXMueHJlZi50cmFpbGVyLmdldCgiRW5jcnlwdCIpOwogICAgaWYgKCEoZW5jcnlwdCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgbGV0IGZsYWdzID0gZW5jcnlwdC5nZXQoIlAiKTsKICAgIGlmICh0eXBlb2YgZmxhZ3MgIT09ICJudW1iZXIiKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgZmxhZ3MgKz0gMiAqKiAzMjsKICAgIGNvbnN0IHBlcm1pc3Npb25zID0gW107CiAgICBmb3IgKGNvbnN0IGtleSBpbiBfdXRpbC5QZXJtaXNzaW9uRmxhZykgewogICAgICBjb25zdCB2YWx1ZSA9IF91dGlsLlBlcm1pc3Npb25GbGFnW2tleV07CiAgICAgIGlmIChmbGFncyAmIHZhbHVlKSB7CiAgICAgICAgcGVybWlzc2lvbnMucHVzaCh2YWx1ZSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBwZXJtaXNzaW9uczsKICB9CiAgZ2V0IG9wdGlvbmFsQ29udGVudENvbmZpZygpIHsKICAgIGxldCBjb25maWcgPSBudWxsOwogICAgdHJ5IHsKICAgICAgY29uc3QgcHJvcGVydGllcyA9IHRoaXMuX2NhdERpY3QuZ2V0KCJPQ1Byb3BlcnRpZXMiKTsKICAgICAgaWYgKCFwcm9wZXJ0aWVzKSB7CiAgICAgICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJvcHRpb25hbENvbnRlbnRDb25maWciLCBudWxsKTsKICAgICAgfQogICAgICBjb25zdCBkZWZhdWx0Q29uZmlnID0gcHJvcGVydGllcy5nZXQoIkQiKTsKICAgICAgaWYgKCFkZWZhdWx0Q29uZmlnKSB7CiAgICAgICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJvcHRpb25hbENvbnRlbnRDb25maWciLCBudWxsKTsKICAgICAgfQogICAgICBjb25zdCBncm91cHNEYXRhID0gcHJvcGVydGllcy5nZXQoIk9DR3MiKTsKICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGdyb3Vwc0RhdGEpKSB7CiAgICAgICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJvcHRpb25hbENvbnRlbnRDb25maWciLCBudWxsKTsKICAgICAgfQogICAgICBjb25zdCBncm91cHMgPSBbXTsKICAgICAgY29uc3QgZ3JvdXBSZWZzID0gW107CiAgICAgIGZvciAoY29uc3QgZ3JvdXBSZWYgb2YgZ3JvdXBzRGF0YSkgewogICAgICAgIGlmICghKGdyb3VwUmVmIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGdyb3VwUmVmcy5wdXNoKGdyb3VwUmVmKTsKICAgICAgICBjb25zdCBncm91cCA9IHRoaXMueHJlZi5mZXRjaElmUmVmKGdyb3VwUmVmKTsKICAgICAgICBncm91cHMucHVzaCh7CiAgICAgICAgICBpZDogZ3JvdXBSZWYudG9TdHJpbmcoKSwKICAgICAgICAgIG5hbWU6IHR5cGVvZiBncm91cC5nZXQoIk5hbWUiKSA9PT0gInN0cmluZyIgPyAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGdyb3VwLmdldCgiTmFtZSIpKSA6IG51bGwsCiAgICAgICAgICBpbnRlbnQ6IHR5cGVvZiBncm91cC5nZXQoIkludGVudCIpID09PSAic3RyaW5nIiA/ICgwLCBfdXRpbC5zdHJpbmdUb1BERlN0cmluZykoZ3JvdXAuZ2V0KCJJbnRlbnQiKSkgOiBudWxsCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgY29uZmlnID0gdGhpcy5fcmVhZE9wdGlvbmFsQ29udGVudENvbmZpZyhkZWZhdWx0Q29uZmlnLCBncm91cFJlZnMpOwogICAgICBjb25maWcuZ3JvdXBzID0gZ3JvdXBzOwogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgX2NvcmVfdXRpbHMuTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICAoMCwgX3V0aWwud2FybikoYFVuYWJsZSB0byByZWFkIG9wdGlvbmFsIGNvbnRlbnQgY29uZmlnOiAke2V4fWApOwogICAgfQogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJvcHRpb25hbENvbnRlbnRDb25maWciLCBjb25maWcpOwogIH0KICBfcmVhZE9wdGlvbmFsQ29udGVudENvbmZpZyhjb25maWcsIGNvbnRlbnRHcm91cFJlZnMpIHsKICAgIGZ1bmN0aW9uIHBhcnNlT25PZmYocmVmcykgewogICAgICBjb25zdCBvblBhcnNlZCA9IFtdOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShyZWZzKSkgewogICAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgcmVmcykgewogICAgICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGNvbnRlbnRHcm91cFJlZnMuaW5jbHVkZXModmFsdWUpKSB7CiAgICAgICAgICAgIG9uUGFyc2VkLnB1c2godmFsdWUudG9TdHJpbmcoKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBvblBhcnNlZDsKICAgIH0KICAgIGZ1bmN0aW9uIHBhcnNlT3JkZXIocmVmcykgewogICAgICBsZXQgbmVzdGVkTGV2ZWxzID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiAwOwogICAgICBpZiAoIUFycmF5LmlzQXJyYXkocmVmcykpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBjb25zdCBvcmRlciA9IFtdOwogICAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIHJlZnMpIHsKICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYgJiYgY29udGVudEdyb3VwUmVmcy5pbmNsdWRlcyh2YWx1ZSkpIHsKICAgICAgICAgIHBhcnNlZE9yZGVyUmVmcy5wdXQodmFsdWUpOwogICAgICAgICAgb3JkZXIucHVzaCh2YWx1ZS50b1N0cmluZygpKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBuZXN0ZWRPcmRlciA9IHBhcnNlTmVzdGVkT3JkZXIodmFsdWUsIG5lc3RlZExldmVscyk7CiAgICAgICAgaWYgKG5lc3RlZE9yZGVyKSB7CiAgICAgICAgICBvcmRlci5wdXNoKG5lc3RlZE9yZGVyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKG5lc3RlZExldmVscyA+IDApIHsKICAgICAgICByZXR1cm4gb3JkZXI7CiAgICAgIH0KICAgICAgY29uc3QgaGlkZGVuR3JvdXBzID0gW107CiAgICAgIGZvciAoY29uc3QgZ3JvdXBSZWYgb2YgY29udGVudEdyb3VwUmVmcykgewogICAgICAgIGlmIChwYXJzZWRPcmRlclJlZnMuaGFzKGdyb3VwUmVmKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGhpZGRlbkdyb3Vwcy5wdXNoKGdyb3VwUmVmLnRvU3RyaW5nKCkpOwogICAgICB9CiAgICAgIGlmIChoaWRkZW5Hcm91cHMubGVuZ3RoKSB7CiAgICAgICAgb3JkZXIucHVzaCh7CiAgICAgICAgICBuYW1lOiBudWxsLAogICAgICAgICAgb3JkZXI6IGhpZGRlbkdyb3VwcwogICAgICAgIH0pOwogICAgICB9CiAgICAgIHJldHVybiBvcmRlcjsKICAgIH0KICAgIGZ1bmN0aW9uIHBhcnNlTmVzdGVkT3JkZXIocmVmLCBuZXN0ZWRMZXZlbHMpIHsKICAgICAgaWYgKCsrbmVzdGVkTGV2ZWxzID4gTUFYX05FU1RFRF9MRVZFTFMpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoInBhcnNlTmVzdGVkT3JkZXIgLSByZWFjaGVkIE1BWF9ORVNURURfTEVWRUxTLiIpOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IHZhbHVlID0geHJlZi5mZXRjaElmUmVmKHJlZik7CiAgICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBjb25zdCBuZXN0ZWROYW1lID0geHJlZi5mZXRjaElmUmVmKHZhbHVlWzBdKTsKICAgICAgaWYgKHR5cGVvZiBuZXN0ZWROYW1lICE9PSAic3RyaW5nIikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IG5lc3RlZE9yZGVyID0gcGFyc2VPcmRlcih2YWx1ZS5zbGljZSgxKSwgbmVzdGVkTGV2ZWxzKTsKICAgICAgaWYgKCFuZXN0ZWRPcmRlciB8fCAhbmVzdGVkT3JkZXIubGVuZ3RoKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgcmV0dXJuIHsKICAgICAgICBuYW1lOiAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKG5lc3RlZE5hbWUpLAogICAgICAgIG9yZGVyOiBuZXN0ZWRPcmRlcgogICAgICB9OwogICAgfQogICAgY29uc3QgeHJlZiA9IHRoaXMueHJlZiwKICAgICAgcGFyc2VkT3JkZXJSZWZzID0gbmV3IF9wcmltaXRpdmVzLlJlZlNldCgpLAogICAgICBNQVhfTkVTVEVEX0xFVkVMUyA9IDEwOwogICAgcmV0dXJuIHsKICAgICAgbmFtZTogdHlwZW9mIGNvbmZpZy5nZXQoIk5hbWUiKSA9PT0gInN0cmluZyIgPyAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGNvbmZpZy5nZXQoIk5hbWUiKSkgOiBudWxsLAogICAgICBjcmVhdG9yOiB0eXBlb2YgY29uZmlnLmdldCgiQ3JlYXRvciIpID09PSAic3RyaW5nIiA/ICgwLCBfdXRpbC5zdHJpbmdUb1BERlN0cmluZykoY29uZmlnLmdldCgiQ3JlYXRvciIpKSA6IG51bGwsCiAgICAgIGJhc2VTdGF0ZTogY29uZmlnLmdldCgiQmFzZVN0YXRlIikgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lID8gY29uZmlnLmdldCgiQmFzZVN0YXRlIikubmFtZSA6IG51bGwsCiAgICAgIG9uOiBwYXJzZU9uT2ZmKGNvbmZpZy5nZXQoIk9OIikpLAogICAgICBvZmY6IHBhcnNlT25PZmYoY29uZmlnLmdldCgiT0ZGIikpLAogICAgICBvcmRlcjogcGFyc2VPcmRlcihjb25maWcuZ2V0KCJPcmRlciIpKSwKICAgICAgZ3JvdXBzOiBudWxsCiAgICB9OwogIH0KICBzZXRBY3R1YWxOdW1QYWdlcygpIHsKICAgIGxldCBudW0gPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IG51bGw7CiAgICB0aGlzLl9hY3R1YWxOdW1QYWdlcyA9IG51bTsKICB9CiAgZ2V0IGhhc0FjdHVhbE51bVBhZ2VzKCkgewogICAgcmV0dXJuIHRoaXMuX2FjdHVhbE51bVBhZ2VzICE9PSBudWxsOwogIH0KICBnZXQgX3BhZ2VzQ291bnQoKSB7CiAgICBjb25zdCBvYmogPSB0aGlzLnRvcGxldmVsUGFnZXNEaWN0LmdldCgiQ291bnQiKTsKICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihvYmopKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiUGFnZSBjb3VudCBpbiB0b3AtbGV2ZWwgcGFnZXMgZGljdGlvbmFyeSBpcyBub3QgYW4gaW50ZWdlci4iKTsKICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiX3BhZ2VzQ291bnQiLCBvYmopOwogIH0KICBnZXQgbnVtUGFnZXMoKSB7CiAgICByZXR1cm4gdGhpcy5oYXNBY3R1YWxOdW1QYWdlcyA/IHRoaXMuX2FjdHVhbE51bVBhZ2VzIDogdGhpcy5fcGFnZXNDb3VudDsKICB9CiAgZ2V0IGRlc3RpbmF0aW9ucygpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMuX3JlYWREZXN0cygpLAogICAgICBkZXN0cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBpZiAob2JqIGluc3RhbmNlb2YgX25hbWVfbnVtYmVyX3RyZWUuTmFtZVRyZWUpIHsKICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2Ygb2JqLmdldEFsbCgpKSB7CiAgICAgICAgY29uc3QgZGVzdCA9IGZldGNoRGVzdGluYXRpb24odmFsdWUpOwogICAgICAgIGlmIChkZXN0KSB7CiAgICAgICAgICBkZXN0c1soMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGtleSldID0gZGVzdDsKICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSBpZiAob2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICBvYmouZm9yRWFjaChmdW5jdGlvbiAoa2V5LCB2YWx1ZSkgewogICAgICAgIGNvbnN0IGRlc3QgPSBmZXRjaERlc3RpbmF0aW9uKHZhbHVlKTsKICAgICAgICBpZiAoZGVzdCkgewogICAgICAgICAgZGVzdHNba2V5XSA9IGRlc3Q7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiZGVzdGluYXRpb25zIiwgZGVzdHMpOwogIH0KICBnZXREZXN0aW5hdGlvbihpZCkgewogICAgY29uc3Qgb2JqID0gdGhpcy5fcmVhZERlc3RzKCk7CiAgICBpZiAob2JqIGluc3RhbmNlb2YgX25hbWVfbnVtYmVyX3RyZWUuTmFtZVRyZWUpIHsKICAgICAgY29uc3QgZGVzdCA9IGZldGNoRGVzdGluYXRpb24ob2JqLmdldChpZCkpOwogICAgICBpZiAoZGVzdCkgewogICAgICAgIHJldHVybiBkZXN0OwogICAgICB9CiAgICAgIGNvbnN0IGFsbERlc3QgPSB0aGlzLmRlc3RpbmF0aW9uc1tpZF07CiAgICAgIGlmIChhbGxEZXN0KSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKGBGb3VuZCAiJHtpZH0iIGF0IGFuIGluY29ycmVjdCBwb3NpdGlvbiBpbiB0aGUgTmFtZVRyZWUuYCk7CiAgICAgICAgcmV0dXJuIGFsbERlc3Q7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAob2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICBjb25zdCBkZXN0ID0gZmV0Y2hEZXN0aW5hdGlvbihvYmouZ2V0KGlkKSk7CiAgICAgIGlmIChkZXN0KSB7CiAgICAgICAgcmV0dXJuIGRlc3Q7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICBfcmVhZERlc3RzKCkgewogICAgY29uc3Qgb2JqID0gdGhpcy5fY2F0RGljdC5nZXQoIk5hbWVzIik7CiAgICBpZiAob2JqICYmIG9iai5oYXMoIkRlc3RzIikpIHsKICAgICAgcmV0dXJuIG5ldyBfbmFtZV9udW1iZXJfdHJlZS5OYW1lVHJlZShvYmouZ2V0UmF3KCJEZXN0cyIpLCB0aGlzLnhyZWYpOwogICAgfSBlbHNlIGlmICh0aGlzLl9jYXREaWN0LmhhcygiRGVzdHMiKSkgewogICAgICByZXR1cm4gdGhpcy5fY2F0RGljdC5nZXQoIkRlc3RzIik7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBnZXQgcGFnZUxhYmVscygpIHsKICAgIGxldCBvYmogPSBudWxsOwogICAgdHJ5IHsKICAgICAgb2JqID0gdGhpcy5fcmVhZFBhZ2VMYWJlbHMoKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgKDAsIF91dGlsLndhcm4pKCJVbmFibGUgdG8gcmVhZCBwYWdlIGxhYmVscy4iKTsKICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAicGFnZUxhYmVscyIsIG9iaik7CiAgfQogIF9yZWFkUGFnZUxhYmVscygpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMuX2NhdERpY3QuZ2V0UmF3KCJQYWdlTGFiZWxzIik7CiAgICBpZiAoIW9iaikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHBhZ2VMYWJlbHMgPSBuZXcgQXJyYXkodGhpcy5udW1QYWdlcyk7CiAgICBsZXQgc3R5bGUgPSBudWxsLAogICAgICBwcmVmaXggPSAiIjsKICAgIGNvbnN0IG51bWJlclRyZWUgPSBuZXcgX25hbWVfbnVtYmVyX3RyZWUuTnVtYmVyVHJlZShvYmosIHRoaXMueHJlZik7CiAgICBjb25zdCBudW1zID0gbnVtYmVyVHJlZS5nZXRBbGwoKTsKICAgIGxldCBjdXJyZW50TGFiZWwgPSAiIiwKICAgICAgY3VycmVudEluZGV4ID0gMTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHRoaXMubnVtUGFnZXM7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IGxhYmVsRGljdCA9IG51bXMuZ2V0KGkpOwogICAgICBpZiAobGFiZWxEaWN0ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBpZiAoIShsYWJlbERpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJQYWdlTGFiZWwgaXMgbm90IGEgZGljdGlvbmFyeS4iKTsKICAgICAgICB9CiAgICAgICAgaWYgKGxhYmVsRGljdC5oYXMoIlR5cGUiKSAmJiAhKDAsIF9wcmltaXRpdmVzLmlzTmFtZSkobGFiZWxEaWN0LmdldCgiVHlwZSIpLCAiUGFnZUxhYmVsIikpIHsKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCB0eXBlIGluIFBhZ2VMYWJlbCBkaWN0aW9uYXJ5LiIpOwogICAgICAgIH0KICAgICAgICBpZiAobGFiZWxEaWN0LmhhcygiUyIpKSB7CiAgICAgICAgICBjb25zdCBzID0gbGFiZWxEaWN0LmdldCgiUyIpOwogICAgICAgICAgaWYgKCEocyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCBzdHlsZSBpbiBQYWdlTGFiZWwgZGljdGlvbmFyeS4iKTsKICAgICAgICAgIH0KICAgICAgICAgIHN0eWxlID0gcy5uYW1lOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdHlsZSA9IG51bGw7CiAgICAgICAgfQogICAgICAgIGlmIChsYWJlbERpY3QuaGFzKCJQIikpIHsKICAgICAgICAgIGNvbnN0IHAgPSBsYWJlbERpY3QuZ2V0KCJQIik7CiAgICAgICAgICBpZiAodHlwZW9mIHAgIT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCBwcmVmaXggaW4gUGFnZUxhYmVsIGRpY3Rpb25hcnkuIik7CiAgICAgICAgICB9CiAgICAgICAgICBwcmVmaXggPSAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKHApOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBwcmVmaXggPSAiIjsKICAgICAgICB9CiAgICAgICAgaWYgKGxhYmVsRGljdC5oYXMoIlN0IikpIHsKICAgICAgICAgIGNvbnN0IHN0ID0gbGFiZWxEaWN0LmdldCgiU3QiKTsKICAgICAgICAgIGlmICghKE51bWJlci5pc0ludGVnZXIoc3QpICYmIHN0ID49IDEpKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCBzdGFydCBpbiBQYWdlTGFiZWwgZGljdGlvbmFyeS4iKTsKICAgICAgICAgIH0KICAgICAgICAgIGN1cnJlbnRJbmRleCA9IHN0OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjdXJyZW50SW5kZXggPSAxOwogICAgICAgIH0KICAgICAgfQogICAgICBzd2l0Y2ggKHN0eWxlKSB7CiAgICAgICAgY2FzZSAiRCI6CiAgICAgICAgICBjdXJyZW50TGFiZWwgPSBjdXJyZW50SW5kZXg7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJSIjoKICAgICAgICBjYXNlICJyIjoKICAgICAgICAgIGN1cnJlbnRMYWJlbCA9ICgwLCBfY29yZV91dGlscy50b1JvbWFuTnVtZXJhbHMpKGN1cnJlbnRJbmRleCwgc3R5bGUgPT09ICJyIik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJBIjoKICAgICAgICBjYXNlICJhIjoKICAgICAgICAgIGNvbnN0IExJTUlUID0gMjY7CiAgICAgICAgICBjb25zdCBBX1VQUEVSX0NBU0UgPSAweDQxLAogICAgICAgICAgICBBX0xPV0VSX0NBU0UgPSAweDYxOwogICAgICAgICAgY29uc3QgYmFzZUNoYXJDb2RlID0gc3R5bGUgPT09ICJhIiA/IEFfTE9XRVJfQ0FTRSA6IEFfVVBQRVJfQ0FTRTsKICAgICAgICAgIGNvbnN0IGxldHRlckluZGV4ID0gY3VycmVudEluZGV4IC0gMTsKICAgICAgICAgIGNvbnN0IGNoYXJhY3RlciA9IFN0cmluZy5mcm9tQ2hhckNvZGUoYmFzZUNoYXJDb2RlICsgbGV0dGVySW5kZXggJSBMSU1JVCk7CiAgICAgICAgICBjdXJyZW50TGFiZWwgPSBjaGFyYWN0ZXIucmVwZWF0KE1hdGguZmxvb3IobGV0dGVySW5kZXggLyBMSU1JVCkgKyAxKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBpZiAoc3R5bGUpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBJbnZhbGlkIHN0eWxlICIke3N0eWxlfSIgaW4gUGFnZUxhYmVsIGRpY3Rpb25hcnkuYCk7CiAgICAgICAgICB9CiAgICAgICAgICBjdXJyZW50TGFiZWwgPSAiIjsKICAgICAgfQogICAgICBwYWdlTGFiZWxzW2ldID0gcHJlZml4ICsgY3VycmVudExhYmVsOwogICAgICBjdXJyZW50SW5kZXgrKzsKICAgIH0KICAgIHJldHVybiBwYWdlTGFiZWxzOwogIH0KICBnZXQgcGFnZUxheW91dCgpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMuX2NhdERpY3QuZ2V0KCJQYWdlTGF5b3V0Iik7CiAgICBsZXQgcGFnZUxheW91dCA9ICIiOwogICAgaWYgKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgc3dpdGNoIChvYmoubmFtZSkgewogICAgICAgIGNhc2UgIlNpbmdsZVBhZ2UiOgogICAgICAgIGNhc2UgIk9uZUNvbHVtbiI6CiAgICAgICAgY2FzZSAiVHdvQ29sdW1uTGVmdCI6CiAgICAgICAgY2FzZSAiVHdvQ29sdW1uUmlnaHQiOgogICAgICAgIGNhc2UgIlR3b1BhZ2VMZWZ0IjoKICAgICAgICBjYXNlICJUd29QYWdlUmlnaHQiOgogICAgICAgICAgcGFnZUxheW91dCA9IG9iai5uYW1lOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInBhZ2VMYXlvdXQiLCBwYWdlTGF5b3V0KTsKICB9CiAgZ2V0IHBhZ2VNb2RlKCkgewogICAgY29uc3Qgb2JqID0gdGhpcy5fY2F0RGljdC5nZXQoIlBhZ2VNb2RlIik7CiAgICBsZXQgcGFnZU1vZGUgPSAiVXNlTm9uZSI7CiAgICBpZiAob2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICBzd2l0Y2ggKG9iai5uYW1lKSB7CiAgICAgICAgY2FzZSAiVXNlTm9uZSI6CiAgICAgICAgY2FzZSAiVXNlT3V0bGluZXMiOgogICAgICAgIGNhc2UgIlVzZVRodW1icyI6CiAgICAgICAgY2FzZSAiRnVsbFNjcmVlbiI6CiAgICAgICAgY2FzZSAiVXNlT0MiOgogICAgICAgIGNhc2UgIlVzZUF0dGFjaG1lbnRzIjoKICAgICAgICAgIHBhZ2VNb2RlID0gb2JqLm5hbWU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAicGFnZU1vZGUiLCBwYWdlTW9kZSk7CiAgfQogIGdldCB2aWV3ZXJQcmVmZXJlbmNlcygpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMuX2NhdERpY3QuZ2V0KCJWaWV3ZXJQcmVmZXJlbmNlcyIpOwogICAgaWYgKCEob2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJ2aWV3ZXJQcmVmZXJlbmNlcyIsIG51bGwpOwogICAgfQogICAgbGV0IHByZWZzID0gbnVsbDsKICAgIGZvciAoY29uc3Qga2V5IG9mIG9iai5nZXRLZXlzKCkpIHsKICAgICAgY29uc3QgdmFsdWUgPSBvYmouZ2V0KGtleSk7CiAgICAgIGxldCBwcmVmVmFsdWU7CiAgICAgIHN3aXRjaCAoa2V5KSB7CiAgICAgICAgY2FzZSAiSGlkZVRvb2xiYXIiOgogICAgICAgIGNhc2UgIkhpZGVNZW51YmFyIjoKICAgICAgICBjYXNlICJIaWRlV2luZG93VUkiOgogICAgICAgIGNhc2UgIkZpdFdpbmRvdyI6CiAgICAgICAgY2FzZSAiQ2VudGVyV2luZG93IjoKICAgICAgICBjYXNlICJEaXNwbGF5RG9jVGl0bGUiOgogICAgICAgIGNhc2UgIlBpY2tUcmF5QnlQREZTaXplIjoKICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJib29sZWFuIikgewogICAgICAgICAgICBwcmVmVmFsdWUgPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIk5vbkZ1bGxTY3JlZW5QYWdlTW9kZSI6CiAgICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgICAgICAgIHN3aXRjaCAodmFsdWUubmFtZSkgewogICAgICAgICAgICAgIGNhc2UgIlVzZU5vbmUiOgogICAgICAgICAgICAgIGNhc2UgIlVzZU91dGxpbmVzIjoKICAgICAgICAgICAgICBjYXNlICJVc2VUaHVtYnMiOgogICAgICAgICAgICAgIGNhc2UgIlVzZU9DIjoKICAgICAgICAgICAgICAgIHByZWZWYWx1ZSA9IHZhbHVlLm5hbWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgcHJlZlZhbHVlID0gIlVzZU5vbmUiOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJEaXJlY3Rpb24iOgogICAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICAgICAgICBzd2l0Y2ggKHZhbHVlLm5hbWUpIHsKICAgICAgICAgICAgICBjYXNlICJMMlIiOgogICAgICAgICAgICAgIGNhc2UgIlIyTCI6CiAgICAgICAgICAgICAgICBwcmVmVmFsdWUgPSB2YWx1ZS5uYW1lOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHByZWZWYWx1ZSA9ICJMMlIiOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJWaWV3QXJlYSI6CiAgICAgICAgY2FzZSAiVmlld0NsaXAiOgogICAgICAgIGNhc2UgIlByaW50QXJlYSI6CiAgICAgICAgY2FzZSAiUHJpbnRDbGlwIjoKICAgICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgICAgICAgc3dpdGNoICh2YWx1ZS5uYW1lKSB7CiAgICAgICAgICAgICAgY2FzZSAiTWVkaWFCb3giOgogICAgICAgICAgICAgIGNhc2UgIkNyb3BCb3giOgogICAgICAgICAgICAgIGNhc2UgIkJsZWVkQm94IjoKICAgICAgICAgICAgICBjYXNlICJUcmltQm94IjoKICAgICAgICAgICAgICBjYXNlICJBcnRCb3giOgogICAgICAgICAgICAgICAgcHJlZlZhbHVlID0gdmFsdWUubmFtZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBwcmVmVmFsdWUgPSAiQ3JvcEJveCI7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlByaW50U2NhbGluZyI6CiAgICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgICAgICAgIHN3aXRjaCAodmFsdWUubmFtZSkgewogICAgICAgICAgICAgIGNhc2UgIk5vbmUiOgogICAgICAgICAgICAgIGNhc2UgIkFwcERlZmF1bHQiOgogICAgICAgICAgICAgICAgcHJlZlZhbHVlID0gdmFsdWUubmFtZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBwcmVmVmFsdWUgPSAiQXBwRGVmYXVsdCI7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkR1cGxleCI6CiAgICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgICAgICAgIHN3aXRjaCAodmFsdWUubmFtZSkgewogICAgICAgICAgICAgIGNhc2UgIlNpbXBsZXgiOgogICAgICAgICAgICAgIGNhc2UgIkR1cGxleEZsaXBTaG9ydEVkZ2UiOgogICAgICAgICAgICAgIGNhc2UgIkR1cGxleEZsaXBMb25nRWRnZSI6CiAgICAgICAgICAgICAgICBwcmVmVmFsdWUgPSB2YWx1ZS5uYW1lOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHByZWZWYWx1ZSA9ICJOb25lIjsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiUHJpbnRQYWdlUmFuZ2UiOgogICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCAlIDIgPT09IDApIHsKICAgICAgICAgICAgY29uc3QgaXNWYWxpZCA9IHZhbHVlLmV2ZXJ5KChwYWdlLCBpLCBhcnIpID0+IHsKICAgICAgICAgICAgICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcihwYWdlKSAmJiBwYWdlID4gMCAmJiAoaSA9PT0gMCB8fCBwYWdlID49IGFycltpIC0gMV0pICYmIHBhZ2UgPD0gdGhpcy5udW1QYWdlczsKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGlmIChpc1ZhbGlkKSB7CiAgICAgICAgICAgICAgcHJlZlZhbHVlID0gdmFsdWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIk51bUNvcGllcyI6CiAgICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcih2YWx1ZSkgJiYgdmFsdWUgPiAwKSB7CiAgICAgICAgICAgIHByZWZWYWx1ZSA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgSWdub3Jpbmcgbm9uLXN0YW5kYXJkIGtleSBpbiBWaWV3ZXJQcmVmZXJlbmNlczogJHtrZXl9LmApOwogICAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKHByZWZWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKGBCYWQgdmFsdWUsIGZvciBrZXkgIiR7a2V5fSIsIGluIFZpZXdlclByZWZlcmVuY2VzOiAke3ZhbHVlfS5gKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoIXByZWZzKSB7CiAgICAgICAgcHJlZnMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB9CiAgICAgIHByZWZzW2tleV0gPSBwcmVmVmFsdWU7CiAgICB9CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgInZpZXdlclByZWZlcmVuY2VzIiwgcHJlZnMpOwogIH0KICBnZXQgb3BlbkFjdGlvbigpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMuX2NhdERpY3QuZ2V0KCJPcGVuQWN0aW9uIik7CiAgICBjb25zdCBvcGVuQWN0aW9uID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGlmIChvYmogaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgIGNvbnN0IGRlc3REaWN0ID0gbmV3IF9wcmltaXRpdmVzLkRpY3QodGhpcy54cmVmKTsKICAgICAgZGVzdERpY3Quc2V0KCJBIiwgb2JqKTsKICAgICAgY29uc3QgcmVzdWx0T2JqID0gewogICAgICAgIHVybDogbnVsbCwKICAgICAgICBkZXN0OiBudWxsLAogICAgICAgIGFjdGlvbjogbnVsbAogICAgICB9OwogICAgICBDYXRhbG9nLnBhcnNlRGVzdERpY3Rpb25hcnkoewogICAgICAgIGRlc3REaWN0LAogICAgICAgIHJlc3VsdE9iagogICAgICB9KTsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVzdWx0T2JqLmRlc3QpKSB7CiAgICAgICAgb3BlbkFjdGlvbi5kZXN0ID0gcmVzdWx0T2JqLmRlc3Q7CiAgICAgIH0gZWxzZSBpZiAocmVzdWx0T2JqLmFjdGlvbikgewogICAgICAgIG9wZW5BY3Rpb24uYWN0aW9uID0gcmVzdWx0T2JqLmFjdGlvbjsKICAgICAgfQogICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHsKICAgICAgb3BlbkFjdGlvbi5kZXN0ID0gb2JqOwogICAgfQogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJvcGVuQWN0aW9uIiwgKDAsIF91dGlsLm9iamVjdFNpemUpKG9wZW5BY3Rpb24pID4gMCA/IG9wZW5BY3Rpb24gOiBudWxsKTsKICB9CiAgZ2V0IGF0dGFjaG1lbnRzKCkgewogICAgY29uc3Qgb2JqID0gdGhpcy5fY2F0RGljdC5nZXQoIk5hbWVzIik7CiAgICBsZXQgYXR0YWNobWVudHMgPSBudWxsOwogICAgaWYgKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QgJiYgb2JqLmhhcygiRW1iZWRkZWRGaWxlcyIpKSB7CiAgICAgIGNvbnN0IG5hbWVUcmVlID0gbmV3IF9uYW1lX251bWJlcl90cmVlLk5hbWVUcmVlKG9iai5nZXRSYXcoIkVtYmVkZGVkRmlsZXMiKSwgdGhpcy54cmVmKTsKICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgbmFtZVRyZWUuZ2V0QWxsKCkpIHsKICAgICAgICBjb25zdCBmcyA9IG5ldyBfZmlsZV9zcGVjLkZpbGVTcGVjKHZhbHVlLCB0aGlzLnhyZWYpOwogICAgICAgIGlmICghYXR0YWNobWVudHMpIHsKICAgICAgICAgIGF0dGFjaG1lbnRzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICB9CiAgICAgICAgYXR0YWNobWVudHNbKDAsIF91dGlsLnN0cmluZ1RvUERGU3RyaW5nKShrZXkpXSA9IGZzLnNlcmlhbGl6YWJsZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJhdHRhY2htZW50cyIsIGF0dGFjaG1lbnRzKTsKICB9CiAgZ2V0IHhmYUltYWdlcygpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMuX2NhdERpY3QuZ2V0KCJOYW1lcyIpOwogICAgbGV0IHhmYUltYWdlcyA9IG51bGw7CiAgICBpZiAob2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCAmJiBvYmouaGFzKCJYRkFJbWFnZXMiKSkgewogICAgICBjb25zdCBuYW1lVHJlZSA9IG5ldyBfbmFtZV9udW1iZXJfdHJlZS5OYW1lVHJlZShvYmouZ2V0UmF3KCJYRkFJbWFnZXMiKSwgdGhpcy54cmVmKTsKICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgbmFtZVRyZWUuZ2V0QWxsKCkpIHsKICAgICAgICBpZiAoIXhmYUltYWdlcykgewogICAgICAgICAgeGZhSW1hZ2VzID0gbmV3IF9wcmltaXRpdmVzLkRpY3QodGhpcy54cmVmKTsKICAgICAgICB9CiAgICAgICAgeGZhSW1hZ2VzLnNldCgoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGtleSksIHZhbHVlKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJ4ZmFJbWFnZXMiLCB4ZmFJbWFnZXMpOwogIH0KICBfY29sbGVjdEphdmFTY3JpcHQoKSB7CiAgICBjb25zdCBvYmogPSB0aGlzLl9jYXREaWN0LmdldCgiTmFtZXMiKTsKICAgIGxldCBqYXZhU2NyaXB0ID0gbnVsbDsKICAgIGZ1bmN0aW9uIGFwcGVuZElmSmF2YVNjcmlwdERpY3QobmFtZSwganNEaWN0KSB7CiAgICAgIGlmICghKGpzRGljdCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICghKDAsIF9wcmltaXRpdmVzLmlzTmFtZSkoanNEaWN0LmdldCgiUyIpLCAiSmF2YVNjcmlwdCIpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGxldCBqcyA9IGpzRGljdC5nZXQoIkpTIik7CiAgICAgIGlmIChqcyBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSB7CiAgICAgICAganMgPSBqcy5nZXRTdHJpbmcoKTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YganMgIT09ICJzdHJpbmciKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmIChqYXZhU2NyaXB0ID09PSBudWxsKSB7CiAgICAgICAgamF2YVNjcmlwdCA9IG5ldyBNYXAoKTsKICAgICAgfQogICAgICBqcyA9ICgwLCBfdXRpbC5zdHJpbmdUb1BERlN0cmluZykoanMpLnJlcGxhY2VBbGwoIlx4MDAiLCAiIik7CiAgICAgIGphdmFTY3JpcHQuc2V0KG5hbWUsIGpzKTsKICAgIH0KICAgIGlmIChvYmogaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0ICYmIG9iai5oYXMoIkphdmFTY3JpcHQiKSkgewogICAgICBjb25zdCBuYW1lVHJlZSA9IG5ldyBfbmFtZV9udW1iZXJfdHJlZS5OYW1lVHJlZShvYmouZ2V0UmF3KCJKYXZhU2NyaXB0IiksIHRoaXMueHJlZik7CiAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIG5hbWVUcmVlLmdldEFsbCgpKSB7CiAgICAgICAgYXBwZW5kSWZKYXZhU2NyaXB0RGljdCgoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGtleSksIHZhbHVlKTsKICAgICAgfQogICAgfQogICAgY29uc3Qgb3BlbkFjdGlvbiA9IHRoaXMuX2NhdERpY3QuZ2V0KCJPcGVuQWN0aW9uIik7CiAgICBpZiAob3BlbkFjdGlvbikgewogICAgICBhcHBlbmRJZkphdmFTY3JpcHREaWN0KCJPcGVuQWN0aW9uIiwgb3BlbkFjdGlvbik7CiAgICB9CiAgICByZXR1cm4gamF2YVNjcmlwdDsKICB9CiAgZ2V0IGphdmFTY3JpcHQoKSB7CiAgICBjb25zdCBqYXZhU2NyaXB0ID0gdGhpcy5fY29sbGVjdEphdmFTY3JpcHQoKTsKICAgIHJldHVybiAoMCwgX3V0aWwuc2hhZG93KSh0aGlzLCAiamF2YVNjcmlwdCIsIGphdmFTY3JpcHQgPyBbLi4uamF2YVNjcmlwdC52YWx1ZXMoKV0gOiBudWxsKTsKICB9CiAgZ2V0IGpzQWN0aW9ucygpIHsKICAgIGNvbnN0IGphdmFTY3JpcHQgPSB0aGlzLl9jb2xsZWN0SmF2YVNjcmlwdCgpOwogICAgbGV0IGFjdGlvbnMgPSAoMCwgX2NvcmVfdXRpbHMuY29sbGVjdEFjdGlvbnMpKHRoaXMueHJlZiwgdGhpcy5fY2F0RGljdCwgX3V0aWwuRG9jdW1lbnRBY3Rpb25FdmVudFR5cGUpOwogICAgaWYgKGphdmFTY3JpcHQpIHsKICAgICAgaWYgKCFhY3Rpb25zKSB7CiAgICAgICAgYWN0aW9ucyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBba2V5LCB2YWxdIG9mIGphdmFTY3JpcHQpIHsKICAgICAgICBpZiAoa2V5IGluIGFjdGlvbnMpIHsKICAgICAgICAgIGFjdGlvbnNba2V5XS5wdXNoKHZhbCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGFjdGlvbnNba2V5XSA9IFt2YWxdOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJqc0FjdGlvbnMiLCBhY3Rpb25zKTsKICB9CiAgYXN5bmMgZm9udEZhbGxiYWNrKGlkLCBoYW5kbGVyKSB7CiAgICBjb25zdCB0cmFuc2xhdGVkRm9udHMgPSBhd2FpdCBQcm9taXNlLmFsbCh0aGlzLmZvbnRDYWNoZSk7CiAgICBmb3IgKGNvbnN0IHRyYW5zbGF0ZWRGb250IG9mIHRyYW5zbGF0ZWRGb250cykgewogICAgICBpZiAodHJhbnNsYXRlZEZvbnQubG9hZGVkTmFtZSA9PT0gaWQpIHsKICAgICAgICB0cmFuc2xhdGVkRm9udC5mYWxsYmFjayhoYW5kbGVyKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgIH0KICB9CiAgYXN5bmMgY2xlYW51cCgpIHsKICAgIGxldCBtYW51YWxseVRyaWdnZXJlZCA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogZmFsc2U7CiAgICAoMCwgX2NsZWFudXBfaGVscGVyLmNsZWFyR2xvYmFsQ2FjaGVzKSgpOwogICAgdGhpcy5nbG9iYWxJbWFnZUNhY2hlLmNsZWFyKG1hbnVhbGx5VHJpZ2dlcmVkKTsKICAgIHRoaXMucGFnZUtpZHNDb3VudENhY2hlLmNsZWFyKCk7CiAgICB0aGlzLnBhZ2VJbmRleENhY2hlLmNsZWFyKCk7CiAgICB0aGlzLm5vbkJsZW5kTW9kZXNTZXQuY2xlYXIoKTsKICAgIGNvbnN0IHRyYW5zbGF0ZWRGb250cyA9IGF3YWl0IFByb21pc2UuYWxsKHRoaXMuZm9udENhY2hlKTsKICAgIGZvciAoY29uc3QgewogICAgICBkaWN0CiAgICB9IG9mIHRyYW5zbGF0ZWRGb250cykgewogICAgICBkZWxldGUgZGljdC5jYWNoZUtleTsKICAgIH0KICAgIHRoaXMuZm9udENhY2hlLmNsZWFyKCk7CiAgICB0aGlzLmJ1aWx0SW5DTWFwQ2FjaGUuY2xlYXIoKTsKICAgIHRoaXMuc3RhbmRhcmRGb250RGF0YUNhY2hlLmNsZWFyKCk7CiAgfQogIGFzeW5jIGdldFBhZ2VEaWN0KHBhZ2VJbmRleCkgewogICAgY29uc3Qgbm9kZXNUb1Zpc2l0ID0gW3RoaXMudG9wbGV2ZWxQYWdlc0RpY3RdOwogICAgY29uc3QgdmlzaXRlZE5vZGVzID0gbmV3IF9wcmltaXRpdmVzLlJlZlNldCgpOwogICAgY29uc3QgcGFnZXNSZWYgPSB0aGlzLl9jYXREaWN0LmdldFJhdygiUGFnZXMiKTsKICAgIGlmIChwYWdlc1JlZiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICB2aXNpdGVkTm9kZXMucHV0KHBhZ2VzUmVmKTsKICAgIH0KICAgIGNvbnN0IHhyZWYgPSB0aGlzLnhyZWYsCiAgICAgIHBhZ2VLaWRzQ291bnRDYWNoZSA9IHRoaXMucGFnZUtpZHNDb3VudENhY2hlLAogICAgICBwYWdlSW5kZXhDYWNoZSA9IHRoaXMucGFnZUluZGV4Q2FjaGU7CiAgICBsZXQgY3VycmVudFBhZ2VJbmRleCA9IDA7CiAgICB3aGlsZSAobm9kZXNUb1Zpc2l0Lmxlbmd0aCkgewogICAgICBjb25zdCBjdXJyZW50Tm9kZSA9IG5vZGVzVG9WaXNpdC5wb3AoKTsKICAgICAgaWYgKGN1cnJlbnROb2RlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgICAgY29uc3QgY291bnQgPSBwYWdlS2lkc0NvdW50Q2FjaGUuZ2V0KGN1cnJlbnROb2RlKTsKICAgICAgICBpZiAoY291bnQgPj0gMCAmJiBjdXJyZW50UGFnZUluZGV4ICsgY291bnQgPD0gcGFnZUluZGV4KSB7CiAgICAgICAgICBjdXJyZW50UGFnZUluZGV4ICs9IGNvdW50OwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmICh2aXNpdGVkTm9kZXMuaGFzKGN1cnJlbnROb2RlKSkgewogICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJQYWdlcyB0cmVlIGNvbnRhaW5zIGNpcmN1bGFyIHJlZmVyZW5jZS4iKTsKICAgICAgICB9CiAgICAgICAgdmlzaXRlZE5vZGVzLnB1dChjdXJyZW50Tm9kZSk7CiAgICAgICAgY29uc3Qgb2JqID0gYXdhaXQgeHJlZi5mZXRjaEFzeW5jKGN1cnJlbnROb2RlKTsKICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICAgICAgbGV0IHR5cGUgPSBvYmouZ2V0UmF3KCJUeXBlIik7CiAgICAgICAgICBpZiAodHlwZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgICAgICB0eXBlID0gYXdhaXQgeHJlZi5mZXRjaEFzeW5jKHR5cGUpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCgwLCBfcHJpbWl0aXZlcy5pc05hbWUpKHR5cGUsICJQYWdlIikgfHwgIW9iai5oYXMoIktpZHMiKSkgewogICAgICAgICAgICBpZiAoIXBhZ2VLaWRzQ291bnRDYWNoZS5oYXMoY3VycmVudE5vZGUpKSB7CiAgICAgICAgICAgICAgcGFnZUtpZHNDb3VudENhY2hlLnB1dChjdXJyZW50Tm9kZSwgMSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKCFwYWdlSW5kZXhDYWNoZS5oYXMoY3VycmVudE5vZGUpKSB7CiAgICAgICAgICAgICAgcGFnZUluZGV4Q2FjaGUucHV0KGN1cnJlbnROb2RlLCBjdXJyZW50UGFnZUluZGV4KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoY3VycmVudFBhZ2VJbmRleCA9PT0gcGFnZUluZGV4KSB7CiAgICAgICAgICAgICAgcmV0dXJuIFtvYmosIGN1cnJlbnROb2RlXTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjdXJyZW50UGFnZUluZGV4Kys7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBub2Rlc1RvVmlzaXQucHVzaChvYmopOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICghKGN1cnJlbnROb2RlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIlBhZ2UgZGljdGlvbmFyeSBraWQgcmVmZXJlbmNlIHBvaW50cyB0byB3cm9uZyB0eXBlIG9mIG9iamVjdC4iKTsKICAgICAgfQogICAgICBjb25zdCB7CiAgICAgICAgb2JqSWQKICAgICAgfSA9IGN1cnJlbnROb2RlOwogICAgICBsZXQgY291bnQgPSBjdXJyZW50Tm9kZS5nZXRSYXcoIkNvdW50Iik7CiAgICAgIGlmIChjb3VudCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgIGNvdW50ID0gYXdhaXQgeHJlZi5mZXRjaEFzeW5jKGNvdW50KTsKICAgICAgfQogICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihjb3VudCkgJiYgY291bnQgPj0gMCkgewogICAgICAgIGlmIChvYmpJZCAmJiAhcGFnZUtpZHNDb3VudENhY2hlLmhhcyhvYmpJZCkpIHsKICAgICAgICAgIHBhZ2VLaWRzQ291bnRDYWNoZS5wdXQob2JqSWQsIGNvdW50KTsKICAgICAgICB9CiAgICAgICAgaWYgKGN1cnJlbnRQYWdlSW5kZXggKyBjb3VudCA8PSBwYWdlSW5kZXgpIHsKICAgICAgICAgIGN1cnJlbnRQYWdlSW5kZXggKz0gY291bnQ7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgbGV0IGtpZHMgPSBjdXJyZW50Tm9kZS5nZXRSYXcoIktpZHMiKTsKICAgICAgaWYgKGtpZHMgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpIHsKICAgICAgICBraWRzID0gYXdhaXQgeHJlZi5mZXRjaEFzeW5jKGtpZHMpOwogICAgICB9CiAgICAgIGlmICghQXJyYXkuaXNBcnJheShraWRzKSkgewogICAgICAgIGxldCB0eXBlID0gY3VycmVudE5vZGUuZ2V0UmF3KCJUeXBlIik7CiAgICAgICAgaWYgKHR5cGUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpIHsKICAgICAgICAgIHR5cGUgPSBhd2FpdCB4cmVmLmZldGNoQXN5bmModHlwZSk7CiAgICAgICAgfQogICAgICAgIGlmICgoMCwgX3ByaW1pdGl2ZXMuaXNOYW1lKSh0eXBlLCAiUGFnZSIpIHx8ICFjdXJyZW50Tm9kZS5oYXMoIktpZHMiKSkgewogICAgICAgICAgaWYgKGN1cnJlbnRQYWdlSW5kZXggPT09IHBhZ2VJbmRleCkgewogICAgICAgICAgICByZXR1cm4gW2N1cnJlbnROb2RlLCBudWxsXTsKICAgICAgICAgIH0KICAgICAgICAgIGN1cnJlbnRQYWdlSW5kZXgrKzsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIlBhZ2UgZGljdGlvbmFyeSBraWRzIG9iamVjdCBpcyBub3QgYW4gYXJyYXkuIik7CiAgICAgIH0KICAgICAgZm9yIChsZXQgbGFzdCA9IGtpZHMubGVuZ3RoIC0gMTsgbGFzdCA+PSAwOyBsYXN0LS0pIHsKICAgICAgICBub2Rlc1RvVmlzaXQucHVzaChraWRzW2xhc3RdKTsKICAgICAgfQogICAgfQogICAgdGhyb3cgbmV3IEVycm9yKGBQYWdlIGluZGV4ICR7cGFnZUluZGV4fSBub3QgZm91bmQuYCk7CiAgfQogIGFzeW5jIGdldEFsbFBhZ2VEaWN0cygpIHsKICAgIGxldCByZWNvdmVyeU1vZGUgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgY29uc3QgewogICAgICBpZ25vcmVFcnJvcnMKICAgIH0gPSB0aGlzLnBkZk1hbmFnZXIuZXZhbHVhdG9yT3B0aW9uczsKICAgIGNvbnN0IHF1ZXVlID0gW3sKICAgICAgY3VycmVudE5vZGU6IHRoaXMudG9wbGV2ZWxQYWdlc0RpY3QsCiAgICAgIHBvc0luS2lkczogMAogICAgfV07CiAgICBjb25zdCB2aXNpdGVkTm9kZXMgPSBuZXcgX3ByaW1pdGl2ZXMuUmVmU2V0KCk7CiAgICBjb25zdCBwYWdlc1JlZiA9IHRoaXMuX2NhdERpY3QuZ2V0UmF3KCJQYWdlcyIpOwogICAgaWYgKHBhZ2VzUmVmIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgIHZpc2l0ZWROb2Rlcy5wdXQocGFnZXNSZWYpOwogICAgfQogICAgY29uc3QgbWFwID0gbmV3IE1hcCgpLAogICAgICB4cmVmID0gdGhpcy54cmVmLAogICAgICBwYWdlSW5kZXhDYWNoZSA9IHRoaXMucGFnZUluZGV4Q2FjaGU7CiAgICBsZXQgcGFnZUluZGV4ID0gMDsKICAgIGZ1bmN0aW9uIGFkZFBhZ2VEaWN0KHBhZ2VEaWN0LCBwYWdlUmVmKSB7CiAgICAgIGlmIChwYWdlUmVmICYmICFwYWdlSW5kZXhDYWNoZS5oYXMocGFnZVJlZikpIHsKICAgICAgICBwYWdlSW5kZXhDYWNoZS5wdXQocGFnZVJlZiwgcGFnZUluZGV4KTsKICAgICAgfQogICAgICBtYXAuc2V0KHBhZ2VJbmRleCsrLCBbcGFnZURpY3QsIHBhZ2VSZWZdKTsKICAgIH0KICAgIGZ1bmN0aW9uIGFkZFBhZ2VFcnJvcihlcnJvcikgewogICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBfY29yZV91dGlscy5YUmVmRW50cnlFeGNlcHRpb24gJiYgIXJlY292ZXJ5TW9kZSkgewogICAgICAgIHRocm93IGVycm9yOwogICAgICB9CiAgICAgIGlmIChyZWNvdmVyeU1vZGUgJiYgaWdub3JlRXJyb3JzICYmIHBhZ2VJbmRleCA9PT0gMCkgewogICAgICAgICgwLCBfdXRpbC53YXJuKShgZ2V0QWxsUGFnZURpY3RzIC0gU2tpcHBpbmcgaW52YWxpZCBmaXJzdCBwYWdlOiAiJHtlcnJvcn0iLmApOwogICAgICAgIGVycm9yID0gX3ByaW1pdGl2ZXMuRGljdC5lbXB0eTsKICAgICAgfQogICAgICBtYXAuc2V0KHBhZ2VJbmRleCsrLCBbZXJyb3IsIG51bGxdKTsKICAgIH0KICAgIHdoaWxlIChxdWV1ZS5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IHF1ZXVlSXRlbSA9IHF1ZXVlLmF0KC0xKTsKICAgICAgY29uc3QgewogICAgICAgIGN1cnJlbnROb2RlLAogICAgICAgIHBvc0luS2lkcwogICAgICB9ID0gcXVldWVJdGVtOwogICAgICBsZXQga2lkcyA9IGN1cnJlbnROb2RlLmdldFJhdygiS2lkcyIpOwogICAgICBpZiAoa2lkcyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgIHRyeSB7CiAgICAgICAgICBraWRzID0gYXdhaXQgeHJlZi5mZXRjaEFzeW5jKGtpZHMpOwogICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICBhZGRQYWdlRXJyb3IoZXgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICghQXJyYXkuaXNBcnJheShraWRzKSkgewogICAgICAgIGFkZFBhZ2VFcnJvcihuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIlBhZ2UgZGljdGlvbmFyeSBraWRzIG9iamVjdCBpcyBub3QgYW4gYXJyYXkuIikpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmIChwb3NJbktpZHMgPj0ga2lkcy5sZW5ndGgpIHsKICAgICAgICBxdWV1ZS5wb3AoKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBraWRPYmogPSBraWRzW3Bvc0luS2lkc107CiAgICAgIGxldCBvYmo7CiAgICAgIGlmIChraWRPYmogaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpIHsKICAgICAgICBpZiAodmlzaXRlZE5vZGVzLmhhcyhraWRPYmopKSB7CiAgICAgICAgICBhZGRQYWdlRXJyb3IobmV3IF91dGlsLkZvcm1hdEVycm9yKCJQYWdlcyB0cmVlIGNvbnRhaW5zIGNpcmN1bGFyIHJlZmVyZW5jZS4iKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdmlzaXRlZE5vZGVzLnB1dChraWRPYmopOwogICAgICAgIHRyeSB7CiAgICAgICAgICBvYmogPSBhd2FpdCB4cmVmLmZldGNoQXN5bmMoa2lkT2JqKTsKICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgYWRkUGFnZUVycm9yKGV4KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBvYmogPSBraWRPYmo7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgICBhZGRQYWdlRXJyb3IobmV3IF91dGlsLkZvcm1hdEVycm9yKCJQYWdlIGRpY3Rpb25hcnkga2lkIHJlZmVyZW5jZSBwb2ludHMgdG8gd3JvbmcgdHlwZSBvZiBvYmplY3QuIikpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGxldCB0eXBlID0gb2JqLmdldFJhdygiVHlwZSIpOwogICAgICBpZiAodHlwZSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgIHRyeSB7CiAgICAgICAgICB0eXBlID0gYXdhaXQgeHJlZi5mZXRjaEFzeW5jKHR5cGUpOwogICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICBhZGRQYWdlRXJyb3IoZXgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICgoMCwgX3ByaW1pdGl2ZXMuaXNOYW1lKSh0eXBlLCAiUGFnZSIpIHx8ICFvYmouaGFzKCJLaWRzIikpIHsKICAgICAgICBhZGRQYWdlRGljdChvYmosIGtpZE9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZiA/IGtpZE9iaiA6IG51bGwpOwogICAgICB9IGVsc2UgewogICAgICAgIHF1ZXVlLnB1c2goewogICAgICAgICAgY3VycmVudE5vZGU6IG9iaiwKICAgICAgICAgIHBvc0luS2lkczogMAogICAgICAgIH0pOwogICAgICB9CiAgICAgIHF1ZXVlSXRlbS5wb3NJbktpZHMrKzsKICAgIH0KICAgIHJldHVybiBtYXA7CiAgfQogIGdldFBhZ2VJbmRleChwYWdlUmVmKSB7CiAgICBjb25zdCBjYWNoZWRQYWdlSW5kZXggPSB0aGlzLnBhZ2VJbmRleENhY2hlLmdldChwYWdlUmVmKTsKICAgIGlmIChjYWNoZWRQYWdlSW5kZXggIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGNhY2hlZFBhZ2VJbmRleCk7CiAgICB9CiAgICBjb25zdCB4cmVmID0gdGhpcy54cmVmOwogICAgZnVuY3Rpb24gcGFnZXNCZWZvcmVSZWYoa2lkUmVmKSB7CiAgICAgIGxldCB0b3RhbCA9IDAsCiAgICAgICAgcGFyZW50UmVmOwogICAgICByZXR1cm4geHJlZi5mZXRjaEFzeW5jKGtpZFJlZikudGhlbihmdW5jdGlvbiAobm9kZSkgewogICAgICAgIGlmICgoMCwgX3ByaW1pdGl2ZXMuaXNSZWZzRXF1YWwpKGtpZFJlZiwgcGFnZVJlZikgJiYgISgwLCBfcHJpbWl0aXZlcy5pc0RpY3QpKG5vZGUsICJQYWdlIikgJiYgIShub2RlIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCAmJiAhbm9kZS5oYXMoIlR5cGUiKSAmJiBub2RlLmhhcygiQ29udGVudHMiKSkpIHsKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiVGhlIHJlZmVyZW5jZSBkb2VzIG5vdCBwb2ludCB0byBhIC9QYWdlIGRpY3Rpb25hcnkuIik7CiAgICAgICAgfQogICAgICAgIGlmICghbm9kZSkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIGlmICghKG5vZGUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJOb2RlIG11c3QgYmUgYSBkaWN0aW9uYXJ5LiIpOwogICAgICAgIH0KICAgICAgICBwYXJlbnRSZWYgPSBub2RlLmdldFJhdygiUGFyZW50Iik7CiAgICAgICAgcmV0dXJuIG5vZGUuZ2V0QXN5bmMoIlBhcmVudCIpOwogICAgICB9KS50aGVuKGZ1bmN0aW9uIChwYXJlbnQpIHsKICAgICAgICBpZiAoIXBhcmVudCkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIGlmICghKHBhcmVudCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIlBhcmVudCBtdXN0IGJlIGEgZGljdGlvbmFyeS4iKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHBhcmVudC5nZXRBc3luYygiS2lkcyIpOwogICAgICB9KS50aGVuKGZ1bmN0aW9uIChraWRzKSB7CiAgICAgICAgaWYgKCFraWRzKSB7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgICAgY29uc3Qga2lkUHJvbWlzZXMgPSBbXTsKICAgICAgICBsZXQgZm91bmQgPSBmYWxzZTsKICAgICAgICBmb3IgKGNvbnN0IGtpZCBvZiBraWRzKSB7CiAgICAgICAgICBpZiAoIShraWQgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiS2lkIG11c3QgYmUgYSByZWZlcmVuY2UuIik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoKDAsIF9wcmltaXRpdmVzLmlzUmVmc0VxdWFsKShraWQsIGtpZFJlZikpIHsKICAgICAgICAgICAgZm91bmQgPSB0cnVlOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGtpZFByb21pc2VzLnB1c2goeHJlZi5mZXRjaEFzeW5jKGtpZCkudGhlbihmdW5jdGlvbiAob2JqKSB7CiAgICAgICAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJLaWQgbm9kZSBtdXN0IGJlIGEgZGljdGlvbmFyeS4iKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAob2JqLmhhcygiQ291bnQiKSkgewogICAgICAgICAgICAgIHRvdGFsICs9IG9iai5nZXQoIkNvdW50Iik7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdG90YWwrKzsKICAgICAgICAgICAgfQogICAgICAgICAgfSkpOwogICAgICAgIH0KICAgICAgICBpZiAoIWZvdW5kKSB7CiAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIktpZCByZWZlcmVuY2Ugbm90IGZvdW5kIGluIHBhcmVudCdzIGtpZHMuIik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBQcm9taXNlLmFsbChraWRQcm9taXNlcykudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4gW3RvdGFsLCBwYXJlbnRSZWZdOwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0KICAgIGxldCB0b3RhbCA9IDA7CiAgICBjb25zdCBuZXh0ID0gcmVmID0+IHBhZ2VzQmVmb3JlUmVmKHJlZikudGhlbihhcmdzID0+IHsKICAgICAgaWYgKCFhcmdzKSB7CiAgICAgICAgdGhpcy5wYWdlSW5kZXhDYWNoZS5wdXQocGFnZVJlZiwgdG90YWwpOwogICAgICAgIHJldHVybiB0b3RhbDsKICAgICAgfQogICAgICBjb25zdCBbY291bnQsIHBhcmVudFJlZl0gPSBhcmdzOwogICAgICB0b3RhbCArPSBjb3VudDsKICAgICAgcmV0dXJuIG5leHQocGFyZW50UmVmKTsKICAgIH0pOwogICAgcmV0dXJuIG5leHQocGFnZVJlZik7CiAgfQogIGdldCBiYXNlVXJsKCkgewogICAgY29uc3QgdXJpID0gdGhpcy5fY2F0RGljdC5nZXQoIlVSSSIpOwogICAgaWYgKHVyaSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpIHsKICAgICAgY29uc3QgYmFzZSA9IHVyaS5nZXQoIkJhc2UiKTsKICAgICAgaWYgKHR5cGVvZiBiYXNlID09PSAic3RyaW5nIikgewogICAgICAgIGNvbnN0IGFic29sdXRlVXJsID0gKDAsIF91dGlsLmNyZWF0ZVZhbGlkQWJzb2x1dGVVcmwpKGJhc2UsIG51bGwsIHsKICAgICAgICAgIHRyeUNvbnZlcnRFbmNvZGluZzogdHJ1ZQogICAgICAgIH0pOwogICAgICAgIGlmIChhYnNvbHV0ZVVybCkgewogICAgICAgICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJiYXNlVXJsIiwgYWJzb2x1dGVVcmwuaHJlZik7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgImJhc2VVcmwiLCBudWxsKTsKICB9CiAgc3RhdGljIHBhcnNlRGVzdERpY3Rpb25hcnkocGFyYW1zKSB7CiAgICBjb25zdCBkZXN0RGljdCA9IHBhcmFtcy5kZXN0RGljdDsKICAgIGlmICghKGRlc3REaWN0IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKCJwYXJzZURlc3REaWN0aW9uYXJ5OiBgZGVzdERpY3RgIG11c3QgYmUgYSBkaWN0aW9uYXJ5LiIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCByZXN1bHRPYmogPSBwYXJhbXMucmVzdWx0T2JqOwogICAgaWYgKHR5cGVvZiByZXN1bHRPYmogIT09ICJvYmplY3QiKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKSgicGFyc2VEZXN0RGljdGlvbmFyeTogYHJlc3VsdE9iamAgbXVzdCBiZSBhbiBvYmplY3QuIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGRvY0Jhc2VVcmwgPSBwYXJhbXMuZG9jQmFzZVVybCB8fCBudWxsOwogICAgY29uc3QgZG9jQXR0YWNobWVudHMgPSBwYXJhbXMuZG9jQXR0YWNobWVudHMgfHwgbnVsbDsKICAgIGxldCBhY3Rpb24gPSBkZXN0RGljdC5nZXQoIkEiKSwKICAgICAgdXJsLAogICAgICBkZXN0OwogICAgaWYgKCEoYWN0aW9uIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkpIHsKICAgICAgaWYgKGRlc3REaWN0LmhhcygiRGVzdCIpKSB7CiAgICAgICAgYWN0aW9uID0gZGVzdERpY3QuZ2V0KCJEZXN0Iik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYWN0aW9uID0gZGVzdERpY3QuZ2V0KCJBQSIpOwogICAgICAgIGlmIChhY3Rpb24gaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgICAgICBpZiAoYWN0aW9uLmhhcygiRCIpKSB7CiAgICAgICAgICAgIGFjdGlvbiA9IGFjdGlvbi5nZXQoIkQiKTsKICAgICAgICAgIH0gZWxzZSBpZiAoYWN0aW9uLmhhcygiVSIpKSB7CiAgICAgICAgICAgIGFjdGlvbiA9IGFjdGlvbi5nZXQoIlUiKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChhY3Rpb24gaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgIGNvbnN0IGFjdGlvblR5cGUgPSBhY3Rpb24uZ2V0KCJTIik7CiAgICAgIGlmICghKGFjdGlvblR5cGUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSkgewogICAgICAgICgwLCBfdXRpbC53YXJuKSgicGFyc2VEZXN0RGljdGlvbmFyeTogSW52YWxpZCB0eXBlIGluIEFjdGlvbiBkaWN0aW9uYXJ5LiIpOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBjb25zdCBhY3Rpb25OYW1lID0gYWN0aW9uVHlwZS5uYW1lOwogICAgICBzd2l0Y2ggKGFjdGlvbk5hbWUpIHsKICAgICAgICBjYXNlICJSZXNldEZvcm0iOgogICAgICAgICAgY29uc3QgZmxhZ3MgPSBhY3Rpb24uZ2V0KCJGbGFncyIpOwogICAgICAgICAgY29uc3QgaW5jbHVkZSA9ICgodHlwZW9mIGZsYWdzID09PSAibnVtYmVyIiA/IGZsYWdzIDogMCkgJiAxKSA9PT0gMDsKICAgICAgICAgIGNvbnN0IGZpZWxkcyA9IFtdOwogICAgICAgICAgY29uc3QgcmVmcyA9IFtdOwogICAgICAgICAgZm9yIChjb25zdCBvYmogb2YgYWN0aW9uLmdldCgiRmllbGRzIikgfHwgW10pIHsKICAgICAgICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgICAgICAgIHJlZnMucHVzaChvYmoudG9TdHJpbmcoKSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG9iaiA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICBmaWVsZHMucHVzaCgoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKG9iaikpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHRPYmoucmVzZXRGb3JtID0gewogICAgICAgICAgICBmaWVsZHMsCiAgICAgICAgICAgIHJlZnMsCiAgICAgICAgICAgIGluY2x1ZGUKICAgICAgICAgIH07CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJVUkkiOgogICAgICAgICAgdXJsID0gYWN0aW9uLmdldCgiVVJJIik7CiAgICAgICAgICBpZiAodXJsIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICAgICAgICB1cmwgPSAiLyIgKyB1cmwubmFtZTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkdvVG8iOgogICAgICAgICAgZGVzdCA9IGFjdGlvbi5nZXQoIkQiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkxhdW5jaCI6CiAgICAgICAgY2FzZSAiR29Ub1IiOgogICAgICAgICAgY29uc3QgdXJsRGljdCA9IGFjdGlvbi5nZXQoIkYiKTsKICAgICAgICAgIGlmICh1cmxEaWN0IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICAgICAgICB1cmwgPSB1cmxEaWN0LmdldCgiRiIpIHx8IG51bGw7CiAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB1cmxEaWN0ID09PSAic3RyaW5nIikgewogICAgICAgICAgICB1cmwgPSB1cmxEaWN0OwogICAgICAgICAgfQogICAgICAgICAgbGV0IHJlbW90ZURlc3QgPSBhY3Rpb24uZ2V0KCJEIik7CiAgICAgICAgICBpZiAocmVtb3RlRGVzdCkgewogICAgICAgICAgICBpZiAocmVtb3RlRGVzdCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgICAgICAgICByZW1vdGVEZXN0ID0gcmVtb3RlRGVzdC5uYW1lOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh0eXBlb2YgdXJsID09PSAic3RyaW5nIikgewogICAgICAgICAgICAgIGNvbnN0IGJhc2VVcmwgPSB1cmwuc3BsaXQoIiMiKVswXTsKICAgICAgICAgICAgICBpZiAodHlwZW9mIHJlbW90ZURlc3QgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgICAgICB1cmwgPSBiYXNlVXJsICsgIiMiICsgcmVtb3RlRGVzdDsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkocmVtb3RlRGVzdCkpIHsKICAgICAgICAgICAgICAgIHVybCA9IGJhc2VVcmwgKyAiIyIgKyBKU09OLnN0cmluZ2lmeShyZW1vdGVEZXN0KTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IG5ld1dpbmRvdyA9IGFjdGlvbi5nZXQoIk5ld1dpbmRvdyIpOwogICAgICAgICAgaWYgKHR5cGVvZiBuZXdXaW5kb3cgPT09ICJib29sZWFuIikgewogICAgICAgICAgICByZXN1bHRPYmoubmV3V2luZG93ID0gbmV3V2luZG93OwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiR29Ub0UiOgogICAgICAgICAgY29uc3QgdGFyZ2V0ID0gYWN0aW9uLmdldCgiVCIpOwogICAgICAgICAgbGV0IGF0dGFjaG1lbnQ7CiAgICAgICAgICBpZiAoZG9jQXR0YWNobWVudHMgJiYgdGFyZ2V0IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICAgICAgICBjb25zdCByZWxhdGlvbnNoaXAgPSB0YXJnZXQuZ2V0KCJSIik7CiAgICAgICAgICAgIGNvbnN0IG5hbWUgPSB0YXJnZXQuZ2V0KCJOIik7CiAgICAgICAgICAgIGlmICgoMCwgX3ByaW1pdGl2ZXMuaXNOYW1lKShyZWxhdGlvbnNoaXAsICJDIikgJiYgdHlwZW9mIG5hbWUgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgICAgYXR0YWNobWVudCA9IGRvY0F0dGFjaG1lbnRzWygwLCBfdXRpbC5zdHJpbmdUb1BERlN0cmluZykobmFtZSldOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoYXR0YWNobWVudCkgewogICAgICAgICAgICByZXN1bHRPYmouYXR0YWNobWVudCA9IGF0dGFjaG1lbnQ7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYHBhcnNlRGVzdERpY3Rpb25hcnkgLSB1bmltcGxlbWVudGVkICJHb1RvRSIgYWN0aW9uLmApOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiTmFtZWQiOgogICAgICAgICAgY29uc3QgbmFtZWRBY3Rpb24gPSBhY3Rpb24uZ2V0KCJOIik7CiAgICAgICAgICBpZiAobmFtZWRBY3Rpb24gaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSB7CiAgICAgICAgICAgIHJlc3VsdE9iai5hY3Rpb24gPSBuYW1lZEFjdGlvbi5uYW1lOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiU2V0T0NHU3RhdGUiOgogICAgICAgICAgY29uc3Qgc3RhdGUgPSBhY3Rpb24uZ2V0KCJTdGF0ZSIpOwogICAgICAgICAgY29uc3QgcHJlc2VydmVSQiA9IGFjdGlvbi5nZXQoIlByZXNlcnZlUkIiKTsKICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShzdGF0ZSkgfHwgc3RhdGUubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY29uc3Qgc3RhdGVBcnIgPSBbXTsKICAgICAgICAgIGZvciAoY29uc3QgZWxlbSBvZiBzdGF0ZSkgewogICAgICAgICAgICBpZiAoZWxlbSBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLk5hbWUpIHsKICAgICAgICAgICAgICBzd2l0Y2ggKGVsZW0ubmFtZSkgewogICAgICAgICAgICAgICAgY2FzZSAiT04iOgogICAgICAgICAgICAgICAgY2FzZSAiT0ZGIjoKICAgICAgICAgICAgICAgIGNhc2UgIlRvZ2dsZSI6CiAgICAgICAgICAgICAgICAgIHN0YXRlQXJyLnB1c2goZWxlbS5uYW1lKTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgaWYgKGVsZW0gaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpIHsKICAgICAgICAgICAgICBzdGF0ZUFyci5wdXNoKGVsZW0udG9TdHJpbmcoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChzdGF0ZUFyci5sZW5ndGggIT09IHN0YXRlLmxlbmd0aCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIHJlc3VsdE9iai5zZXRPQ0dTdGF0ZSA9IHsKICAgICAgICAgICAgc3RhdGU6IHN0YXRlQXJyLAogICAgICAgICAgICBwcmVzZXJ2ZVJCOiB0eXBlb2YgcHJlc2VydmVSQiA9PT0gImJvb2xlYW4iID8gcHJlc2VydmVSQiA6IHRydWUKICAgICAgICAgIH07CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJKYXZhU2NyaXB0IjoKICAgICAgICAgIGNvbnN0IGpzQWN0aW9uID0gYWN0aW9uLmdldCgiSlMiKTsKICAgICAgICAgIGxldCBqczsKICAgICAgICAgIGlmIChqc0FjdGlvbiBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSB7CiAgICAgICAgICAgIGpzID0ganNBY3Rpb24uZ2V0U3RyaW5nKCk7CiAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBqc0FjdGlvbiA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAganMgPSBqc0FjdGlvbjsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGpzVVJMID0ganMgJiYgKDAsIF9jb3JlX3V0aWxzLnJlY292ZXJKc1VSTCkoKDAsIF91dGlsLnN0cmluZ1RvUERGU3RyaW5nKShqcykpOwogICAgICAgICAgaWYgKGpzVVJMKSB7CiAgICAgICAgICAgIHVybCA9IGpzVVJMLnVybDsKICAgICAgICAgICAgcmVzdWx0T2JqLm5ld1dpbmRvdyA9IGpzVVJMLm5ld1dpbmRvdzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIGlmIChhY3Rpb25OYW1lID09PSAiSmF2YVNjcmlwdCIgfHwgYWN0aW9uTmFtZSA9PT0gIlN1Ym1pdEZvcm0iKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBwYXJzZURlc3REaWN0aW9uYXJ5IC0gdW5zdXBwb3J0ZWQgYWN0aW9uOiAiJHthY3Rpb25OYW1lfSIuYCk7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgfSBlbHNlIGlmIChkZXN0RGljdC5oYXMoIkRlc3QiKSkgewogICAgICBkZXN0ID0gZGVzdERpY3QuZ2V0KCJEZXN0Iik7CiAgICB9CiAgICBpZiAodHlwZW9mIHVybCA9PT0gInN0cmluZyIpIHsKICAgICAgY29uc3QgYWJzb2x1dGVVcmwgPSAoMCwgX3V0aWwuY3JlYXRlVmFsaWRBYnNvbHV0ZVVybCkodXJsLCBkb2NCYXNlVXJsLCB7CiAgICAgICAgYWRkRGVmYXVsdFByb3RvY29sOiB0cnVlLAogICAgICAgIHRyeUNvbnZlcnRFbmNvZGluZzogdHJ1ZQogICAgICB9KTsKICAgICAgaWYgKGFic29sdXRlVXJsKSB7CiAgICAgICAgcmVzdWx0T2JqLnVybCA9IGFic29sdXRlVXJsLmhyZWY7CiAgICAgIH0KICAgICAgcmVzdWx0T2JqLnVuc2FmZVVybCA9IHVybDsKICAgIH0KICAgIGlmIChkZXN0KSB7CiAgICAgIGlmIChkZXN0IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSkgewogICAgICAgIGRlc3QgPSBkZXN0Lm5hbWU7CiAgICAgIH0KICAgICAgaWYgKHR5cGVvZiBkZXN0ID09PSAic3RyaW5nIikgewogICAgICAgIHJlc3VsdE9iai5kZXN0ID0gKDAsIF91dGlsLnN0cmluZ1RvUERGU3RyaW5nKShkZXN0KTsKICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGRlc3QpKSB7CiAgICAgICAgcmVzdWx0T2JqLmRlc3QgPSBkZXN0OwogICAgICB9CiAgICB9CiAgfQp9CmV4cG9ydHMuQ2F0YWxvZyA9IENhdGFsb2c7CgovKioqLyB9KSwKLyogMjA1ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5OdW1iZXJUcmVlID0gZXhwb3J0cy5OYW1lVHJlZSA9IHZvaWQgMDsKdmFyIF9wcmltaXRpdmVzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDApOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpjbGFzcyBOYW1lT3JOdW1iZXJUcmVlIHsKICBjb25zdHJ1Y3Rvcihyb290LCB4cmVmLCB0eXBlKSB7CiAgICBpZiAodGhpcy5jb25zdHJ1Y3RvciA9PT0gTmFtZU9yTnVtYmVyVHJlZSkgewogICAgICAoMCwgX3V0aWwudW5yZWFjaGFibGUpKCJDYW5ub3QgaW5pdGlhbGl6ZSBOYW1lT3JOdW1iZXJUcmVlLiIpOwogICAgfQogICAgdGhpcy5yb290ID0gcm9vdDsKICAgIHRoaXMueHJlZiA9IHhyZWY7CiAgICB0aGlzLl90eXBlID0gdHlwZTsKICB9CiAgZ2V0QWxsKCkgewogICAgY29uc3QgbWFwID0gbmV3IE1hcCgpOwogICAgaWYgKCF0aGlzLnJvb3QpIHsKICAgICAgcmV0dXJuIG1hcDsKICAgIH0KICAgIGNvbnN0IHhyZWYgPSB0aGlzLnhyZWY7CiAgICBjb25zdCBwcm9jZXNzZWQgPSBuZXcgX3ByaW1pdGl2ZXMuUmVmU2V0KCk7CiAgICBwcm9jZXNzZWQucHV0KHRoaXMucm9vdCk7CiAgICBjb25zdCBxdWV1ZSA9IFt0aGlzLnJvb3RdOwogICAgd2hpbGUgKHF1ZXVlLmxlbmd0aCA+IDApIHsKICAgICAgY29uc3Qgb2JqID0geHJlZi5mZXRjaElmUmVmKHF1ZXVlLnNoaWZ0KCkpOwogICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChvYmouaGFzKCJLaWRzIikpIHsKICAgICAgICBjb25zdCBraWRzID0gb2JqLmdldCgiS2lkcyIpOwogICAgICAgIGlmICghQXJyYXkuaXNBcnJheShraWRzKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGZvciAoY29uc3Qga2lkIG9mIGtpZHMpIHsKICAgICAgICAgIGlmIChwcm9jZXNzZWQuaGFzKGtpZCkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBEdXBsaWNhdGUgZW50cnkgaW4gIiR7dGhpcy5fdHlwZX0iIHRyZWUuYCk7CiAgICAgICAgICB9CiAgICAgICAgICBxdWV1ZS5wdXNoKGtpZCk7CiAgICAgICAgICBwcm9jZXNzZWQucHV0KGtpZCk7CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGVudHJpZXMgPSBvYmouZ2V0KHRoaXMuX3R5cGUpOwogICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZW50cmllcykpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBlbnRyaWVzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgICBtYXAuc2V0KHhyZWYuZmV0Y2hJZlJlZihlbnRyaWVzW2ldKSwgeHJlZi5mZXRjaElmUmVmKGVudHJpZXNbaSArIDFdKSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBtYXA7CiAgfQogIGdldChrZXkpIHsKICAgIGlmICghdGhpcy5yb290KSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgeHJlZiA9IHRoaXMueHJlZjsKICAgIGxldCBraWRzT3JFbnRyaWVzID0geHJlZi5mZXRjaElmUmVmKHRoaXMucm9vdCk7CiAgICBsZXQgbG9vcENvdW50ID0gMDsKICAgIGNvbnN0IE1BWF9MRVZFTFMgPSAxMDsKICAgIHdoaWxlIChraWRzT3JFbnRyaWVzLmhhcygiS2lkcyIpKSB7CiAgICAgIGlmICgrK2xvb3BDb3VudCA+IE1BWF9MRVZFTFMpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYFNlYXJjaCBkZXB0aCBsaW1pdCByZWFjaGVkIGZvciAiJHt0aGlzLl90eXBlfSIgdHJlZS5gKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBjb25zdCBraWRzID0ga2lkc09yRW50cmllcy5nZXQoIktpZHMiKTsKICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGtpZHMpKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgbGV0IGwgPSAwLAogICAgICAgIHIgPSBraWRzLmxlbmd0aCAtIDE7CiAgICAgIHdoaWxlIChsIDw9IHIpIHsKICAgICAgICBjb25zdCBtID0gbCArIHIgPj4gMTsKICAgICAgICBjb25zdCBraWQgPSB4cmVmLmZldGNoSWZSZWYoa2lkc1ttXSk7CiAgICAgICAgY29uc3QgbGltaXRzID0ga2lkLmdldCgiTGltaXRzIik7CiAgICAgICAgaWYgKGtleSA8IHhyZWYuZmV0Y2hJZlJlZihsaW1pdHNbMF0pKSB7CiAgICAgICAgICByID0gbSAtIDE7CiAgICAgICAgfSBlbHNlIGlmIChrZXkgPiB4cmVmLmZldGNoSWZSZWYobGltaXRzWzFdKSkgewogICAgICAgICAgbCA9IG0gKyAxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBraWRzT3JFbnRyaWVzID0ga2lkOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChsID4gcikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICB9CiAgICBjb25zdCBlbnRyaWVzID0ga2lkc09yRW50cmllcy5nZXQodGhpcy5fdHlwZSk7CiAgICBpZiAoQXJyYXkuaXNBcnJheShlbnRyaWVzKSkgewogICAgICBsZXQgbCA9IDAsCiAgICAgICAgciA9IGVudHJpZXMubGVuZ3RoIC0gMjsKICAgICAgd2hpbGUgKGwgPD0gcikgewogICAgICAgIGNvbnN0IHRtcCA9IGwgKyByID4+IDEsCiAgICAgICAgICBtID0gdG1wICsgKHRtcCAmIDEpOwogICAgICAgIGNvbnN0IGN1cnJlbnRLZXkgPSB4cmVmLmZldGNoSWZSZWYoZW50cmllc1ttXSk7CiAgICAgICAgaWYgKGtleSA8IGN1cnJlbnRLZXkpIHsKICAgICAgICAgIHIgPSBtIC0gMjsKICAgICAgICB9IGVsc2UgaWYgKGtleSA+IGN1cnJlbnRLZXkpIHsKICAgICAgICAgIGwgPSBtICsgMjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcmV0dXJuIHhyZWYuZmV0Y2hJZlJlZihlbnRyaWVzW20gKyAxXSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9Cn0KY2xhc3MgTmFtZVRyZWUgZXh0ZW5kcyBOYW1lT3JOdW1iZXJUcmVlIHsKICBjb25zdHJ1Y3Rvcihyb290LCB4cmVmKSB7CiAgICBzdXBlcihyb290LCB4cmVmLCAiTmFtZXMiKTsKICB9Cn0KZXhwb3J0cy5OYW1lVHJlZSA9IE5hbWVUcmVlOwpjbGFzcyBOdW1iZXJUcmVlIGV4dGVuZHMgTmFtZU9yTnVtYmVyVHJlZSB7CiAgY29uc3RydWN0b3Iocm9vdCwgeHJlZikgewogICAgc3VwZXIocm9vdCwgeHJlZiwgIk51bXMiKTsKICB9Cn0KZXhwb3J0cy5OdW1iZXJUcmVlID0gTnVtYmVyVHJlZTsKCi8qKiovIH0pLAovKiAyMDYgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLmNsZWFyR2xvYmFsQ2FjaGVzID0gY2xlYXJHbG9iYWxDYWNoZXM7CnZhciBfcHJpbWl0aXZlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQwKTsKdmFyIF91bmljb2RlID0gX193X3BkZmpzX3JlcXVpcmVfXygxNzUpOwpmdW5jdGlvbiBjbGVhckdsb2JhbENhY2hlcygpIHsKICAoMCwgX3ByaW1pdGl2ZXMuY2xlYXJQcmltaXRpdmVDYWNoZXMpKCk7CiAgKDAsIF91bmljb2RlLmNsZWFyVW5pY29kZUNhY2hlcykoKTsKfQoKLyoqKi8gfSksCi8qIDIwNyAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuRmlsZVNwZWMgPSB2b2lkIDA7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CnZhciBfYmFzZV9zdHJlYW0gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDE0MSk7CnZhciBfcHJpbWl0aXZlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQwKTsKZnVuY3Rpb24gcGlja1BsYXRmb3JtSXRlbShkaWN0KSB7CiAgaWYgKGRpY3QuaGFzKCJVRiIpKSB7CiAgICByZXR1cm4gZGljdC5nZXQoIlVGIik7CiAgfSBlbHNlIGlmIChkaWN0LmhhcygiRiIpKSB7CiAgICByZXR1cm4gZGljdC5nZXQoIkYiKTsKICB9IGVsc2UgaWYgKGRpY3QuaGFzKCJVbml4IikpIHsKICAgIHJldHVybiBkaWN0LmdldCgiVW5peCIpOwogIH0gZWxzZSBpZiAoZGljdC5oYXMoIk1hYyIpKSB7CiAgICByZXR1cm4gZGljdC5nZXQoIk1hYyIpOwogIH0gZWxzZSBpZiAoZGljdC5oYXMoIkRPUyIpKSB7CiAgICByZXR1cm4gZGljdC5nZXQoIkRPUyIpOwogIH0KICByZXR1cm4gbnVsbDsKfQpjbGFzcyBGaWxlU3BlYyB7CiAgY29uc3RydWN0b3Iocm9vdCwgeHJlZikgewogICAgaWYgKCEocm9vdCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMueHJlZiA9IHhyZWY7CiAgICB0aGlzLnJvb3QgPSByb290OwogICAgaWYgKHJvb3QuaGFzKCJGUyIpKSB7CiAgICAgIHRoaXMuZnMgPSByb290LmdldCgiRlMiKTsKICAgIH0KICAgIHRoaXMuZGVzY3JpcHRpb24gPSByb290LmhhcygiRGVzYyIpID8gKDAsIF91dGlsLnN0cmluZ1RvUERGU3RyaW5nKShyb290LmdldCgiRGVzYyIpKSA6ICIiOwogICAgaWYgKHJvb3QuaGFzKCJSRiIpKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKSgiUmVsYXRlZCBmaWxlIHNwZWNpZmljYXRpb25zIGFyZSBub3Qgc3VwcG9ydGVkIik7CiAgICB9CiAgICB0aGlzLmNvbnRlbnRBdmFpbGFibGUgPSB0cnVlOwogICAgaWYgKCFyb290LmhhcygiRUYiKSkgewogICAgICB0aGlzLmNvbnRlbnRBdmFpbGFibGUgPSBmYWxzZTsKICAgICAgKDAsIF91dGlsLndhcm4pKCJOb24tZW1iZWRkZWQgZmlsZSBzcGVjaWZpY2F0aW9ucyBhcmUgbm90IHN1cHBvcnRlZCIpOwogICAgfQogIH0KICBnZXQgZmlsZW5hbWUoKSB7CiAgICBpZiAoIXRoaXMuX2ZpbGVuYW1lICYmIHRoaXMucm9vdCkgewogICAgICBjb25zdCBmaWxlbmFtZSA9IHBpY2tQbGF0Zm9ybUl0ZW0odGhpcy5yb290KSB8fCAidW5uYW1lZCI7CiAgICAgIHRoaXMuX2ZpbGVuYW1lID0gKDAsIF91dGlsLnN0cmluZ1RvUERGU3RyaW5nKShmaWxlbmFtZSkucmVwbGFjZUFsbCgiXFxcXCIsICJcXCIpLnJlcGxhY2VBbGwoIlxcLyIsICIvIikucmVwbGFjZUFsbCgiXFwiLCAiLyIpOwogICAgfQogICAgcmV0dXJuIHRoaXMuX2ZpbGVuYW1lOwogIH0KICBnZXQgY29udGVudCgpIHsKICAgIGlmICghdGhpcy5jb250ZW50QXZhaWxhYmxlKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKCF0aGlzLmNvbnRlbnRSZWYgJiYgdGhpcy5yb290KSB7CiAgICAgIHRoaXMuY29udGVudFJlZiA9IHBpY2tQbGF0Zm9ybUl0ZW0odGhpcy5yb290LmdldCgiRUYiKSk7CiAgICB9CiAgICBsZXQgY29udGVudCA9IG51bGw7CiAgICBpZiAodGhpcy5jb250ZW50UmVmKSB7CiAgICAgIGNvbnN0IGZpbGVPYmogPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZih0aGlzLmNvbnRlbnRSZWYpOwogICAgICBpZiAoZmlsZU9iaiBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSB7CiAgICAgICAgY29udGVudCA9IGZpbGVPYmouZ2V0Qnl0ZXMoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoIkVtYmVkZGVkIGZpbGUgc3BlY2lmaWNhdGlvbiBwb2ludHMgdG8gbm9uLWV4aXN0aW5nL2ludmFsaWQgY29udGVudCIpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICAoMCwgX3V0aWwud2FybikoIkVtYmVkZGVkIGZpbGUgc3BlY2lmaWNhdGlvbiBkb2VzIG5vdCBoYXZlIGEgY29udGVudCIpOwogICAgfQogICAgcmV0dXJuIGNvbnRlbnQ7CiAgfQogIGdldCBzZXJpYWxpemFibGUoKSB7CiAgICByZXR1cm4gewogICAgICBmaWxlbmFtZTogdGhpcy5maWxlbmFtZSwKICAgICAgY29udGVudDogdGhpcy5jb250ZW50CiAgICB9OwogIH0KfQpleHBvcnRzLkZpbGVTcGVjID0gRmlsZVNwZWM7CgovKioqLyB9KSwKLyogMjA4ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5NZXRhZGF0YVBhcnNlciA9IHZvaWQgMDsKdmFyIF94bWxfcGFyc2VyID0gX193X3BkZmpzX3JlcXVpcmVfXygyMDEpOwpjbGFzcyBNZXRhZGF0YVBhcnNlciB7CiAgY29uc3RydWN0b3IoZGF0YSkgewogICAgZGF0YSA9IHRoaXMuX3JlcGFpcihkYXRhKTsKICAgIGNvbnN0IHBhcnNlciA9IG5ldyBfeG1sX3BhcnNlci5TaW1wbGVYTUxQYXJzZXIoewogICAgICBsb3dlckNhc2VOYW1lOiB0cnVlCiAgICB9KTsKICAgIGNvbnN0IHhtbERvY3VtZW50ID0gcGFyc2VyLnBhcnNlRnJvbVN0cmluZyhkYXRhKTsKICAgIHRoaXMuX21ldGFkYXRhTWFwID0gbmV3IE1hcCgpOwogICAgdGhpcy5fZGF0YSA9IGRhdGE7CiAgICBpZiAoeG1sRG9jdW1lbnQpIHsKICAgICAgdGhpcy5fcGFyc2UoeG1sRG9jdW1lbnQpOwogICAgfQogIH0KICBfcmVwYWlyKGRhdGEpIHsKICAgIHJldHVybiBkYXRhLnJlcGxhY2UoL15bXjxdKy8sICIiKS5yZXBsYWNlQWxsKC8+XFwzNzZcXDM3NyhbXjxdKykvZywgZnVuY3Rpb24gKGFsbCwgY29kZXMpIHsKICAgICAgY29uc3QgYnl0ZXMgPSBjb2Rlcy5yZXBsYWNlQWxsKC9cXChbMC0zXSkoWzAtN10pKFswLTddKS9nLCBmdW5jdGlvbiAoY29kZSwgZDEsIGQyLCBkMykgewogICAgICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKGQxICogNjQgKyBkMiAqIDggKyBkMyAqIDEpOwogICAgICB9KS5yZXBsYWNlQWxsKC8mKGFtcHxhcG9zfGd0fGx0fHF1b3QpOy9nLCBmdW5jdGlvbiAoc3RyLCBuYW1lKSB7CiAgICAgICAgc3dpdGNoIChuYW1lKSB7CiAgICAgICAgICBjYXNlICJhbXAiOgogICAgICAgICAgICByZXR1cm4gIiYiOwogICAgICAgICAgY2FzZSAiYXBvcyI6CiAgICAgICAgICAgIHJldHVybiAiJyI7CiAgICAgICAgICBjYXNlICJndCI6CiAgICAgICAgICAgIHJldHVybiAiPiI7CiAgICAgICAgICBjYXNlICJsdCI6CiAgICAgICAgICAgIHJldHVybiAiPCI7CiAgICAgICAgICBjYXNlICJxdW90IjoKICAgICAgICAgICAgcmV0dXJuICciJzsKICAgICAgICB9CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBfcmVwYWlyOiAke25hbWV9IGlzbid0IGRlZmluZWQuYCk7CiAgICAgIH0pOwogICAgICBjb25zdCBjaGFyQnVmID0gWyI+Il07CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGJ5dGVzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgICBjb25zdCBjb2RlID0gYnl0ZXMuY2hhckNvZGVBdChpKSAqIDI1NiArIGJ5dGVzLmNoYXJDb2RlQXQoaSArIDEpOwogICAgICAgIGlmIChjb2RlID49IDMyICYmIGNvZGUgPCAxMjcgJiYgY29kZSAhPT0gNjAgJiYgY29kZSAhPT0gNjIgJiYgY29kZSAhPT0gMzgpIHsKICAgICAgICAgIGNoYXJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNvZGUpKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY2hhckJ1Zi5wdXNoKCImI3giICsgKDB4MTAwMDAgKyBjb2RlKS50b1N0cmluZygxNikuc3Vic3RyaW5nKDEpICsgIjsiKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIGNoYXJCdWYuam9pbigiIik7CiAgICB9KTsKICB9CiAgX2dldFNlcXVlbmNlKGVudHJ5KSB7CiAgICBjb25zdCBuYW1lID0gZW50cnkubm9kZU5hbWU7CiAgICBpZiAobmFtZSAhPT0gInJkZjpiYWciICYmIG5hbWUgIT09ICJyZGY6c2VxIiAmJiBuYW1lICE9PSAicmRmOmFsdCIpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICByZXR1cm4gZW50cnkuY2hpbGROb2Rlcy5maWx0ZXIobm9kZSA9PiBub2RlLm5vZGVOYW1lID09PSAicmRmOmxpIik7CiAgfQogIF9wYXJzZUFycmF5KGVudHJ5KSB7CiAgICBpZiAoIWVudHJ5Lmhhc0NoaWxkTm9kZXMoKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBbc2VxTm9kZV0gPSBlbnRyeS5jaGlsZE5vZGVzOwogICAgY29uc3Qgc2VxdWVuY2UgPSB0aGlzLl9nZXRTZXF1ZW5jZShzZXFOb2RlKSB8fCBbXTsKICAgIHRoaXMuX21ldGFkYXRhTWFwLnNldChlbnRyeS5ub2RlTmFtZSwgc2VxdWVuY2UubWFwKG5vZGUgPT4gbm9kZS50ZXh0Q29udGVudC50cmltKCkpKTsKICB9CiAgX3BhcnNlKHhtbERvY3VtZW50KSB7CiAgICBsZXQgcmRmID0geG1sRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50OwogICAgaWYgKHJkZi5ub2RlTmFtZSAhPT0gInJkZjpyZGYiKSB7CiAgICAgIHJkZiA9IHJkZi5maXJzdENoaWxkOwogICAgICB3aGlsZSAocmRmICYmIHJkZi5ub2RlTmFtZSAhPT0gInJkZjpyZGYiKSB7CiAgICAgICAgcmRmID0gcmRmLm5leHRTaWJsaW5nOwogICAgICB9CiAgICB9CiAgICBpZiAoIXJkZiB8fCByZGYubm9kZU5hbWUgIT09ICJyZGY6cmRmIiB8fCAhcmRmLmhhc0NoaWxkTm9kZXMoKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGNvbnN0IGRlc2Mgb2YgcmRmLmNoaWxkTm9kZXMpIHsKICAgICAgaWYgKGRlc2Mubm9kZU5hbWUgIT09ICJyZGY6ZGVzY3JpcHRpb24iKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiBkZXNjLmNoaWxkTm9kZXMpIHsKICAgICAgICBjb25zdCBuYW1lID0gZW50cnkubm9kZU5hbWU7CiAgICAgICAgc3dpdGNoIChuYW1lKSB7CiAgICAgICAgICBjYXNlICIjdGV4dCI6CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgY2FzZSAiZGM6Y3JlYXRvciI6CiAgICAgICAgICBjYXNlICJkYzpzdWJqZWN0IjoKICAgICAgICAgICAgdGhpcy5fcGFyc2VBcnJheShlbnRyeSk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICB0aGlzLl9tZXRhZGF0YU1hcC5zZXQobmFtZSwgZW50cnkudGV4dENvbnRlbnQudHJpbSgpKTsKICAgICAgfQogICAgfQogIH0KICBnZXQgc2VyaWFsaXphYmxlKCkgewogICAgcmV0dXJuIHsKICAgICAgcGFyc2VkRGF0YTogdGhpcy5fbWV0YWRhdGFNYXAsCiAgICAgIHJhd0RhdGE6IHRoaXMuX2RhdGEKICAgIH07CiAgfQp9CmV4cG9ydHMuTWV0YWRhdGFQYXJzZXIgPSBNZXRhZGF0YVBhcnNlcjsKCi8qKiovIH0pLAovKiAyMDkgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlN0cnVjdFRyZWVSb290ID0gZXhwb3J0cy5TdHJ1Y3RUcmVlUGFnZSA9IHZvaWQgMDsKdmFyIF9wcmltaXRpdmVzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDApOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwp2YXIgX25hbWVfbnVtYmVyX3RyZWUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIwNSk7CmNvbnN0IE1BWF9ERVBUSCA9IDQwOwpjb25zdCBTdHJ1Y3RFbGVtZW50VHlwZSA9IHsKICBQQUdFX0NPTlRFTlQ6ICJQQUdFX0NPTlRFTlQiLAogIFNUUkVBTV9DT05URU5UOiAiU1RSRUFNX0NPTlRFTlQiLAogIE9CSkVDVDogIk9CSkVDVCIsCiAgRUxFTUVOVDogIkVMRU1FTlQiCn07CmNsYXNzIFN0cnVjdFRyZWVSb290IHsKICBjb25zdHJ1Y3Rvcihyb290RGljdCkgewogICAgdGhpcy5kaWN0ID0gcm9vdERpY3Q7CiAgICB0aGlzLnJvbGVNYXAgPSBuZXcgTWFwKCk7CiAgfQogIGluaXQoKSB7CiAgICB0aGlzLnJlYWRSb2xlTWFwKCk7CiAgfQogIHJlYWRSb2xlTWFwKCkgewogICAgY29uc3Qgcm9sZU1hcERpY3QgPSB0aGlzLmRpY3QuZ2V0KCJSb2xlTWFwIik7CiAgICBpZiAoIShyb2xlTWFwRGljdCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHJvbGVNYXBEaWN0LmZvckVhY2goKGtleSwgdmFsdWUpID0+IHsKICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5OYW1lKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICB0aGlzLnJvbGVNYXAuc2V0KGtleSwgdmFsdWUubmFtZSk7CiAgICB9KTsKICB9Cn0KZXhwb3J0cy5TdHJ1Y3RUcmVlUm9vdCA9IFN0cnVjdFRyZWVSb290OwpjbGFzcyBTdHJ1Y3RFbGVtZW50Tm9kZSB7CiAgY29uc3RydWN0b3IodHJlZSwgZGljdCkgewogICAgdGhpcy50cmVlID0gdHJlZTsKICAgIHRoaXMuZGljdCA9IGRpY3Q7CiAgICB0aGlzLmtpZHMgPSBbXTsKICAgIHRoaXMucGFyc2VLaWRzKCk7CiAgfQogIGdldCByb2xlKCkgewogICAgY29uc3QgbmFtZU9iaiA9IHRoaXMuZGljdC5nZXQoIlMiKTsKICAgIGNvbnN0IG5hbWUgPSBuYW1lT2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSA/IG5hbWVPYmoubmFtZSA6ICIiOwogICAgY29uc3QgewogICAgICByb290CiAgICB9ID0gdGhpcy50cmVlOwogICAgaWYgKHJvb3Qucm9sZU1hcC5oYXMobmFtZSkpIHsKICAgICAgcmV0dXJuIHJvb3Qucm9sZU1hcC5nZXQobmFtZSk7CiAgICB9CiAgICByZXR1cm4gbmFtZTsKICB9CiAgcGFyc2VLaWRzKCkgewogICAgbGV0IHBhZ2VPYmpJZCA9IG51bGw7CiAgICBjb25zdCBvYmpSZWYgPSB0aGlzLmRpY3QuZ2V0UmF3KCJQZyIpOwogICAgaWYgKG9ialJlZiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICBwYWdlT2JqSWQgPSBvYmpSZWYudG9TdHJpbmcoKTsKICAgIH0KICAgIGNvbnN0IGtpZHMgPSB0aGlzLmRpY3QuZ2V0KCJLIik7CiAgICBpZiAoQXJyYXkuaXNBcnJheShraWRzKSkgewogICAgICBmb3IgKGNvbnN0IGtpZCBvZiBraWRzKSB7CiAgICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMucGFyc2VLaWQocGFnZU9iaklkLCBraWQpOwogICAgICAgIGlmIChlbGVtZW50KSB7CiAgICAgICAgICB0aGlzLmtpZHMucHVzaChlbGVtZW50KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLnBhcnNlS2lkKHBhZ2VPYmpJZCwga2lkcyk7CiAgICAgIGlmIChlbGVtZW50KSB7CiAgICAgICAgdGhpcy5raWRzLnB1c2goZWxlbWVudCk7CiAgICAgIH0KICAgIH0KICB9CiAgcGFyc2VLaWQocGFnZU9iaklkLCBraWQpIHsKICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKGtpZCkpIHsKICAgICAgaWYgKHRoaXMudHJlZS5wYWdlRGljdC5vYmpJZCAhPT0gcGFnZU9iaklkKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgcmV0dXJuIG5ldyBTdHJ1Y3RFbGVtZW50KHsKICAgICAgICB0eXBlOiBTdHJ1Y3RFbGVtZW50VHlwZS5QQUdFX0NPTlRFTlQsCiAgICAgICAgbWNpZDoga2lkLAogICAgICAgIHBhZ2VPYmpJZAogICAgICB9KTsKICAgIH0KICAgIGxldCBraWREaWN0ID0gbnVsbDsKICAgIGlmIChraWQgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpIHsKICAgICAga2lkRGljdCA9IHRoaXMuZGljdC54cmVmLmZldGNoKGtpZCk7CiAgICB9IGVsc2UgaWYgKGtpZCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpIHsKICAgICAga2lkRGljdCA9IGtpZDsKICAgIH0KICAgIGlmICgha2lkRGljdCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHBhZ2VSZWYgPSBraWREaWN0LmdldFJhdygiUGciKTsKICAgIGlmIChwYWdlUmVmIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgIHBhZ2VPYmpJZCA9IHBhZ2VSZWYudG9TdHJpbmcoKTsKICAgIH0KICAgIGNvbnN0IHR5cGUgPSBraWREaWN0LmdldCgiVHlwZSIpIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuTmFtZSA/IGtpZERpY3QuZ2V0KCJUeXBlIikubmFtZSA6IG51bGw7CiAgICBpZiAodHlwZSA9PT0gIk1DUiIpIHsKICAgICAgaWYgKHRoaXMudHJlZS5wYWdlRGljdC5vYmpJZCAhPT0gcGFnZU9iaklkKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgcmV0dXJuIG5ldyBTdHJ1Y3RFbGVtZW50KHsKICAgICAgICB0eXBlOiBTdHJ1Y3RFbGVtZW50VHlwZS5TVFJFQU1fQ09OVEVOVCwKICAgICAgICByZWZPYmpJZDoga2lkRGljdC5nZXRSYXcoIlN0bSIpIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmID8ga2lkRGljdC5nZXRSYXcoIlN0bSIpLnRvU3RyaW5nKCkgOiBudWxsLAogICAgICAgIHBhZ2VPYmpJZCwKICAgICAgICBtY2lkOiBraWREaWN0LmdldCgiTUNJRCIpCiAgICAgIH0pOwogICAgfQogICAgaWYgKHR5cGUgPT09ICJPQkpSIikgewogICAgICBpZiAodGhpcy50cmVlLnBhZ2VEaWN0Lm9iaklkICE9PSBwYWdlT2JqSWQpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICByZXR1cm4gbmV3IFN0cnVjdEVsZW1lbnQoewogICAgICAgIHR5cGU6IFN0cnVjdEVsZW1lbnRUeXBlLk9CSkVDVCwKICAgICAgICByZWZPYmpJZDoga2lkRGljdC5nZXRSYXcoIk9iaiIpIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmID8ga2lkRGljdC5nZXRSYXcoIk9iaiIpLnRvU3RyaW5nKCkgOiBudWxsLAogICAgICAgIHBhZ2VPYmpJZAogICAgICB9KTsKICAgIH0KICAgIHJldHVybiBuZXcgU3RydWN0RWxlbWVudCh7CiAgICAgIHR5cGU6IFN0cnVjdEVsZW1lbnRUeXBlLkVMRU1FTlQsCiAgICAgIGRpY3Q6IGtpZERpY3QKICAgIH0pOwogIH0KfQpjbGFzcyBTdHJ1Y3RFbGVtZW50IHsKICBjb25zdHJ1Y3RvcihfcmVmKSB7CiAgICBsZXQgewogICAgICB0eXBlLAogICAgICBkaWN0ID0gbnVsbCwKICAgICAgbWNpZCA9IG51bGwsCiAgICAgIHBhZ2VPYmpJZCA9IG51bGwsCiAgICAgIHJlZk9iaklkID0gbnVsbAogICAgfSA9IF9yZWY7CiAgICB0aGlzLnR5cGUgPSB0eXBlOwogICAgdGhpcy5kaWN0ID0gZGljdDsKICAgIHRoaXMubWNpZCA9IG1jaWQ7CiAgICB0aGlzLnBhZ2VPYmpJZCA9IHBhZ2VPYmpJZDsKICAgIHRoaXMucmVmT2JqSWQgPSByZWZPYmpJZDsKICAgIHRoaXMucGFyZW50Tm9kZSA9IG51bGw7CiAgfQp9CmNsYXNzIFN0cnVjdFRyZWVQYWdlIHsKICBjb25zdHJ1Y3RvcihzdHJ1Y3RUcmVlUm9vdCwgcGFnZURpY3QpIHsKICAgIHRoaXMucm9vdCA9IHN0cnVjdFRyZWVSb290OwogICAgdGhpcy5yb290RGljdCA9IHN0cnVjdFRyZWVSb290ID8gc3RydWN0VHJlZVJvb3QuZGljdCA6IG51bGw7CiAgICB0aGlzLnBhZ2VEaWN0ID0gcGFnZURpY3Q7CiAgICB0aGlzLm5vZGVzID0gW107CiAgfQogIHBhcnNlKCkgewogICAgaWYgKCF0aGlzLnJvb3QgfHwgIXRoaXMucm9vdERpY3QpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgcGFyZW50VHJlZSA9IHRoaXMucm9vdERpY3QuZ2V0KCJQYXJlbnRUcmVlIik7CiAgICBpZiAoIXBhcmVudFRyZWUpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgaWQgPSB0aGlzLnBhZ2VEaWN0LmdldCgiU3RydWN0UGFyZW50cyIpOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGlkKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBudW1iZXJUcmVlID0gbmV3IF9uYW1lX251bWJlcl90cmVlLk51bWJlclRyZWUocGFyZW50VHJlZSwgdGhpcy5yb290RGljdC54cmVmKTsKICAgIGNvbnN0IHBhcmVudEFycmF5ID0gbnVtYmVyVHJlZS5nZXQoaWQpOwogICAgaWYgKCFBcnJheS5pc0FycmF5KHBhcmVudEFycmF5KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBtYXAgPSBuZXcgTWFwKCk7CiAgICBmb3IgKGNvbnN0IHJlZiBvZiBwYXJlbnRBcnJheSkgewogICAgICBpZiAocmVmIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgICAgdGhpcy5hZGROb2RlKHRoaXMucm9vdERpY3QueHJlZi5mZXRjaChyZWYpLCBtYXApOwogICAgICB9CiAgICB9CiAgfQogIGFkZE5vZGUoZGljdCwgbWFwKSB7CiAgICBsZXQgbGV2ZWwgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IDA7CiAgICBpZiAobGV2ZWwgPiBNQVhfREVQVEgpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKCJTdHJ1Y3RUcmVlIE1BWF9ERVBUSCByZWFjaGVkLiIpOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGlmIChtYXAuaGFzKGRpY3QpKSB7CiAgICAgIHJldHVybiBtYXAuZ2V0KGRpY3QpOwogICAgfQogICAgY29uc3QgZWxlbWVudCA9IG5ldyBTdHJ1Y3RFbGVtZW50Tm9kZSh0aGlzLCBkaWN0KTsKICAgIG1hcC5zZXQoZGljdCwgZWxlbWVudCk7CiAgICBjb25zdCBwYXJlbnQgPSBkaWN0LmdldCgiUCIpOwogICAgaWYgKCFwYXJlbnQgfHwgKDAsIF9wcmltaXRpdmVzLmlzTmFtZSkocGFyZW50LmdldCgiVHlwZSIpLCAiU3RydWN0VHJlZVJvb3QiKSkgewogICAgICBpZiAoIXRoaXMuYWRkVG9wTGV2ZWxOb2RlKGRpY3QsIGVsZW1lbnQpKSB7CiAgICAgICAgbWFwLmRlbGV0ZShkaWN0KTsKICAgICAgfQogICAgICByZXR1cm4gZWxlbWVudDsKICAgIH0KICAgIGNvbnN0IHBhcmVudE5vZGUgPSB0aGlzLmFkZE5vZGUocGFyZW50LCBtYXAsIGxldmVsICsgMSk7CiAgICBpZiAoIXBhcmVudE5vZGUpIHsKICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9CiAgICBsZXQgc2F2ZSA9IGZhbHNlOwogICAgZm9yIChjb25zdCBraWQgb2YgcGFyZW50Tm9kZS5raWRzKSB7CiAgICAgIGlmIChraWQudHlwZSA9PT0gU3RydWN0RWxlbWVudFR5cGUuRUxFTUVOVCAmJiBraWQuZGljdCA9PT0gZGljdCkgewogICAgICAgIGtpZC5wYXJlbnROb2RlID0gZWxlbWVudDsKICAgICAgICBzYXZlID0gdHJ1ZTsKICAgICAgfQogICAgfQogICAgaWYgKCFzYXZlKSB7CiAgICAgIG1hcC5kZWxldGUoZGljdCk7CiAgICB9CiAgICByZXR1cm4gZWxlbWVudDsKICB9CiAgYWRkVG9wTGV2ZWxOb2RlKGRpY3QsIGVsZW1lbnQpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMucm9vdERpY3QuZ2V0KCJLIik7CiAgICBpZiAoIW9iaikgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAob2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCkgewogICAgICBpZiAob2JqLm9iaklkICE9PSBkaWN0Lm9iaklkKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIHRoaXMubm9kZXNbMF0gPSBlbGVtZW50OwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmICghQXJyYXkuaXNBcnJheShvYmopKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgbGV0IHNhdmUgPSBmYWxzZTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb2JqLmxlbmd0aDsgaSsrKSB7CiAgICAgIGNvbnN0IGtpZFJlZiA9IG9ialtpXTsKICAgICAgaWYgKGtpZFJlZiAmJiBraWRSZWYudG9TdHJpbmcoKSA9PT0gZGljdC5vYmpJZCkgewogICAgICAgIHRoaXMubm9kZXNbaV0gPSBlbGVtZW50OwogICAgICAgIHNhdmUgPSB0cnVlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2F2ZTsKICB9CiAgZ2V0IHNlcmlhbGl6YWJsZSgpIHsKICAgIGZ1bmN0aW9uIG5vZGVUb1NlcmlhbGl6YWJsZShub2RlLCBwYXJlbnQpIHsKICAgICAgbGV0IGxldmVsID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiAwOwogICAgICBpZiAobGV2ZWwgPiBNQVhfREVQVEgpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoIlN0cnVjdFRyZWUgdG9vIGRlZXAgdG8gYmUgZnVsbHkgc2VyaWFsaXplZC4iKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY29uc3Qgb2JqID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgb2JqLnJvbGUgPSBub2RlLnJvbGU7CiAgICAgIG9iai5jaGlsZHJlbiA9IFtdOwogICAgICBwYXJlbnQuY2hpbGRyZW4ucHVzaChvYmopOwogICAgICBjb25zdCBhbHQgPSBub2RlLmRpY3QuZ2V0KCJBbHQiKTsKICAgICAgaWYgKHR5cGVvZiBhbHQgPT09ICJzdHJpbmciKSB7CiAgICAgICAgb2JqLmFsdCA9ICgwLCBfdXRpbC5zdHJpbmdUb1BERlN0cmluZykoYWx0KTsKICAgICAgfQogICAgICBjb25zdCBsYW5nID0gbm9kZS5kaWN0LmdldCgiTGFuZyIpOwogICAgICBpZiAodHlwZW9mIGxhbmcgPT09ICJzdHJpbmciKSB7CiAgICAgICAgb2JqLmxhbmcgPSAoMCwgX3V0aWwuc3RyaW5nVG9QREZTdHJpbmcpKGxhbmcpOwogICAgICB9CiAgICAgIGZvciAoY29uc3Qga2lkIG9mIG5vZGUua2lkcykgewogICAgICAgIGNvbnN0IGtpZEVsZW1lbnQgPSBraWQudHlwZSA9PT0gU3RydWN0RWxlbWVudFR5cGUuRUxFTUVOVCA/IGtpZC5wYXJlbnROb2RlIDogbnVsbDsKICAgICAgICBpZiAoa2lkRWxlbWVudCkgewogICAgICAgICAgbm9kZVRvU2VyaWFsaXphYmxlKGtpZEVsZW1lbnQsIG9iaiwgbGV2ZWwgKyAxKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0gZWxzZSBpZiAoa2lkLnR5cGUgPT09IFN0cnVjdEVsZW1lbnRUeXBlLlBBR0VfQ09OVEVOVCB8fCBraWQudHlwZSA9PT0gU3RydWN0RWxlbWVudFR5cGUuU1RSRUFNX0NPTlRFTlQpIHsKICAgICAgICAgIG9iai5jaGlsZHJlbi5wdXNoKHsKICAgICAgICAgICAgdHlwZTogImNvbnRlbnQiLAogICAgICAgICAgICBpZDogYHBhZ2Uke2tpZC5wYWdlT2JqSWR9X21jaWQke2tpZC5tY2lkfWAKICAgICAgICAgIH0pOwogICAgICAgIH0gZWxzZSBpZiAoa2lkLnR5cGUgPT09IFN0cnVjdEVsZW1lbnRUeXBlLk9CSkVDVCkgewogICAgICAgICAgb2JqLmNoaWxkcmVuLnB1c2goewogICAgICAgICAgICB0eXBlOiAib2JqZWN0IiwKICAgICAgICAgICAgaWQ6IGtpZC5yZWZPYmpJZAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBjb25zdCByb290ID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHJvb3QuY2hpbGRyZW4gPSBbXTsKICAgIHJvb3Qucm9sZSA9ICJSb290IjsKICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpcy5ub2RlcykgewogICAgICBpZiAoIWNoaWxkKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgbm9kZVRvU2VyaWFsaXphYmxlKGNoaWxkLCByb290KTsKICAgIH0KICAgIHJldHVybiByb290OwogIH0KfQpleHBvcnRzLlN0cnVjdFRyZWVQYWdlID0gU3RydWN0VHJlZVBhZ2U7CgovKioqLyB9KSwKLyogMjEwICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5PYmplY3RMb2FkZXIgPSB2b2lkIDA7CnZhciBfcHJpbWl0aXZlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQwKTsKdmFyIF9iYXNlX3N0cmVhbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMTQxKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpmdW5jdGlvbiBtYXlIYXZlQ2hpbGRyZW4odmFsdWUpIHsKICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYgfHwgdmFsdWUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0IHx8IHZhbHVlIGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0gfHwgQXJyYXkuaXNBcnJheSh2YWx1ZSk7Cn0KZnVuY3Rpb24gYWRkQ2hpbGRyZW4obm9kZSwgbm9kZXNUb1Zpc2l0KSB7CiAgaWYgKG5vZGUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICBub2RlID0gbm9kZS5nZXRSYXdWYWx1ZXMoKTsKICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkgewogICAgbm9kZSA9IG5vZGUuZGljdC5nZXRSYXdWYWx1ZXMoKTsKICB9IGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KG5vZGUpKSB7CiAgICByZXR1cm47CiAgfQogIGZvciAoY29uc3QgcmF3VmFsdWUgb2Ygbm9kZSkgewogICAgaWYgKG1heUhhdmVDaGlsZHJlbihyYXdWYWx1ZSkpIHsKICAgICAgbm9kZXNUb1Zpc2l0LnB1c2gocmF3VmFsdWUpOwogICAgfQogIH0KfQpjbGFzcyBPYmplY3RMb2FkZXIgewogIGNvbnN0cnVjdG9yKGRpY3QsIGtleXMsIHhyZWYpIHsKICAgIHRoaXMuZGljdCA9IGRpY3Q7CiAgICB0aGlzLmtleXMgPSBrZXlzOwogICAgdGhpcy54cmVmID0geHJlZjsKICAgIHRoaXMucmVmU2V0ID0gbnVsbDsKICB9CiAgYXN5bmMgbG9hZCgpIHsKICAgIGlmICh0aGlzLnhyZWYuc3RyZWFtLmlzRGF0YUxvYWRlZCkgewogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfQogICAgY29uc3QgewogICAgICBrZXlzLAogICAgICBkaWN0CiAgICB9ID0gdGhpczsKICAgIHRoaXMucmVmU2V0ID0gbmV3IF9wcmltaXRpdmVzLlJlZlNldCgpOwogICAgY29uc3Qgbm9kZXNUb1Zpc2l0ID0gW107CiAgICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7CiAgICAgIGNvbnN0IHJhd1ZhbHVlID0gZGljdC5nZXRSYXcoa2V5KTsKICAgICAgaWYgKHJhd1ZhbHVlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBub2Rlc1RvVmlzaXQucHVzaChyYXdWYWx1ZSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB0aGlzLl93YWxrKG5vZGVzVG9WaXNpdCk7CiAgfQogIGFzeW5jIF93YWxrKG5vZGVzVG9WaXNpdCkgewogICAgY29uc3Qgbm9kZXNUb1JldmlzaXQgPSBbXTsKICAgIGNvbnN0IHBlbmRpbmdSZXF1ZXN0cyA9IFtdOwogICAgd2hpbGUgKG5vZGVzVG9WaXNpdC5sZW5ndGgpIHsKICAgICAgbGV0IGN1cnJlbnROb2RlID0gbm9kZXNUb1Zpc2l0LnBvcCgpOwogICAgICBpZiAoY3VycmVudE5vZGUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpIHsKICAgICAgICBpZiAodGhpcy5yZWZTZXQuaGFzKGN1cnJlbnROb2RlKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIHRyeSB7CiAgICAgICAgICB0aGlzLnJlZlNldC5wdXQoY3VycmVudE5vZGUpOwogICAgICAgICAgY3VycmVudE5vZGUgPSB0aGlzLnhyZWYuZmV0Y2goY3VycmVudE5vZGUpOwogICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICBpZiAoIShleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSkgewogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYE9iamVjdExvYWRlci5fd2FsayAtIHJlcXVlc3RpbmcgYWxsIGRhdGE6ICIke2V4fSIuYCk7CiAgICAgICAgICAgIHRoaXMucmVmU2V0ID0gbnVsbDsKICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgIG1hbmFnZXIKICAgICAgICAgICAgfSA9IHRoaXMueHJlZi5zdHJlYW07CiAgICAgICAgICAgIHJldHVybiBtYW5hZ2VyLnJlcXVlc3RBbGxDaHVua3MoKTsKICAgICAgICAgIH0KICAgICAgICAgIG5vZGVzVG9SZXZpc2l0LnB1c2goY3VycmVudE5vZGUpOwogICAgICAgICAgcGVuZGluZ1JlcXVlc3RzLnB1c2goewogICAgICAgICAgICBiZWdpbjogZXguYmVnaW4sCiAgICAgICAgICAgIGVuZDogZXguZW5kCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGN1cnJlbnROb2RlIGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0pIHsKICAgICAgICBjb25zdCBiYXNlU3RyZWFtcyA9IGN1cnJlbnROb2RlLmdldEJhc2VTdHJlYW1zKCk7CiAgICAgICAgaWYgKGJhc2VTdHJlYW1zKSB7CiAgICAgICAgICBsZXQgZm91bmRNaXNzaW5nRGF0YSA9IGZhbHNlOwogICAgICAgICAgZm9yIChjb25zdCBzdHJlYW0gb2YgYmFzZVN0cmVhbXMpIHsKICAgICAgICAgICAgaWYgKHN0cmVhbS5pc0RhdGFMb2FkZWQpIHsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBmb3VuZE1pc3NpbmdEYXRhID0gdHJ1ZTsKICAgICAgICAgICAgcGVuZGluZ1JlcXVlc3RzLnB1c2goewogICAgICAgICAgICAgIGJlZ2luOiBzdHJlYW0uc3RhcnQsCiAgICAgICAgICAgICAgZW5kOiBzdHJlYW0uZW5kCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGZvdW5kTWlzc2luZ0RhdGEpIHsKICAgICAgICAgICAgbm9kZXNUb1JldmlzaXQucHVzaChjdXJyZW50Tm9kZSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIGFkZENoaWxkcmVuKGN1cnJlbnROb2RlLCBub2Rlc1RvVmlzaXQpOwogICAgfQogICAgaWYgKHBlbmRpbmdSZXF1ZXN0cy5sZW5ndGgpIHsKICAgICAgYXdhaXQgdGhpcy54cmVmLnN0cmVhbS5tYW5hZ2VyLnJlcXVlc3RSYW5nZXMocGVuZGluZ1JlcXVlc3RzKTsKICAgICAgZm9yIChjb25zdCBub2RlIG9mIG5vZGVzVG9SZXZpc2l0KSB7CiAgICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpIHsKICAgICAgICAgIHRoaXMucmVmU2V0LnJlbW92ZShub2RlKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuX3dhbGsobm9kZXNUb1JldmlzaXQpOwogICAgfQogICAgdGhpcy5yZWZTZXQgPSBudWxsOwogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9Cn0KZXhwb3J0cy5PYmplY3RMb2FkZXIgPSBPYmplY3RMb2FkZXI7CgovKioqLyB9KSwKLyogMjExICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5YRkFGYWN0b3J5ID0gdm9pZCAwOwp2YXIgX3hmYV9vYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxMik7CnZhciBfYmluZCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjE2KTsKdmFyIF9kYXRhID0gX193X3BkZmpzX3JlcXVpcmVfXygyMjIpOwp2YXIgX2ZvbnRzID0gX193X3BkZmpzX3JlcXVpcmVfXygyMjApOwp2YXIgX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTMpOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwp2YXIgX3BhcnNlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMjIzKTsKdmFyIF94aHRtbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjMzKTsKY2xhc3MgWEZBRmFjdG9yeSB7CiAgY29uc3RydWN0b3IoZGF0YSkgewogICAgdHJ5IHsKICAgICAgdGhpcy5yb290ID0gbmV3IF9wYXJzZXIuWEZBUGFyc2VyKCkucGFyc2UoWEZBRmFjdG9yeS5fY3JlYXRlRG9jdW1lbnQoZGF0YSkpOwogICAgICBjb25zdCBiaW5kZXIgPSBuZXcgX2JpbmQuQmluZGVyKHRoaXMucm9vdCk7CiAgICAgIHRoaXMuZm9ybSA9IGJpbmRlci5iaW5kKCk7CiAgICAgIHRoaXMuZGF0YUhhbmRsZXIgPSBuZXcgX2RhdGEuRGF0YUhhbmRsZXIodGhpcy5yb290LCBiaW5kZXIuZ2V0RGF0YSgpKTsKICAgICAgdGhpcy5mb3JtW194ZmFfb2JqZWN0LiRnbG9iYWxEYXRhXS50ZW1wbGF0ZSA9IHRoaXMuZm9ybTsKICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKGBYRkEgLSBhbiBlcnJvciBvY2N1cnJlZCBkdXJpbmcgcGFyc2luZyBhbmQgYmluZGluZzogJHtlfWApOwogICAgfQogIH0KICBpc1ZhbGlkKCkgewogICAgcmV0dXJuIHRoaXMucm9vdCAmJiB0aGlzLmZvcm07CiAgfQogIF9jcmVhdGVQYWdlc0hlbHBlcigpIHsKICAgIGNvbnN0IGl0ZXJhdG9yID0gdGhpcy5mb3JtW194ZmFfb2JqZWN0LiR0b1BhZ2VzXSgpOwogICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsKICAgICAgY29uc3QgbmV4dEl0ZXJhdGlvbiA9ICgpID0+IHsKICAgICAgICB0cnkgewogICAgICAgICAgY29uc3QgdmFsdWUgPSBpdGVyYXRvci5uZXh0KCk7CiAgICAgICAgICBpZiAodmFsdWUuZG9uZSkgewogICAgICAgICAgICByZXNvbHZlKHZhbHVlLnZhbHVlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHNldFRpbWVvdXQobmV4dEl0ZXJhdGlvbiwgMCk7CiAgICAgICAgICB9CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgcmVqZWN0KGUpOwogICAgICAgIH0KICAgICAgfTsKICAgICAgc2V0VGltZW91dChuZXh0SXRlcmF0aW9uLCAwKTsKICAgIH0pOwogIH0KICBhc3luYyBfY3JlYXRlUGFnZXMoKSB7CiAgICB0cnkgewogICAgICB0aGlzLnBhZ2VzID0gYXdhaXQgdGhpcy5fY3JlYXRlUGFnZXNIZWxwZXIoKTsKICAgICAgdGhpcy5kaW1zID0gdGhpcy5wYWdlcy5jaGlsZHJlbi5tYXAoYyA9PiB7CiAgICAgICAgY29uc3QgewogICAgICAgICAgd2lkdGgsCiAgICAgICAgICBoZWlnaHQKICAgICAgICB9ID0gYy5hdHRyaWJ1dGVzLnN0eWxlOwogICAgICAgIHJldHVybiBbMCwgMCwgcGFyc2VJbnQod2lkdGgpLCBwYXJzZUludChoZWlnaHQpXTsKICAgICAgfSk7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gYW4gZXJyb3Igb2NjdXJyZWQgZHVyaW5nIGxheW91dDogJHtlfWApOwogICAgfQogIH0KICBnZXRCb3VuZGluZ0JveChwYWdlSW5kZXgpIHsKICAgIHJldHVybiB0aGlzLmRpbXNbcGFnZUluZGV4XTsKICB9CiAgYXN5bmMgZ2V0TnVtUGFnZXMoKSB7CiAgICBpZiAoIXRoaXMucGFnZXMpIHsKICAgICAgYXdhaXQgdGhpcy5fY3JlYXRlUGFnZXMoKTsKICAgIH0KICAgIHJldHVybiB0aGlzLmRpbXMubGVuZ3RoOwogIH0KICBzZXRJbWFnZXMoaW1hZ2VzKSB7CiAgICB0aGlzLmZvcm1bX3hmYV9vYmplY3QuJGdsb2JhbERhdGFdLmltYWdlcyA9IGltYWdlczsKICB9CiAgc2V0Rm9udHMoZm9udHMpIHsKICAgIHRoaXMuZm9ybVtfeGZhX29iamVjdC4kZ2xvYmFsRGF0YV0uZm9udEZpbmRlciA9IG5ldyBfZm9udHMuRm9udEZpbmRlcihmb250cyk7CiAgICBjb25zdCBtaXNzaW5nRm9udHMgPSBbXTsKICAgIGZvciAobGV0IHR5cGVmYWNlIG9mIHRoaXMuZm9ybVtfeGZhX29iamVjdC4kZ2xvYmFsRGF0YV0udXNlZFR5cGVmYWNlcykgewogICAgICB0eXBlZmFjZSA9ICgwLCBfdXRpbHMuc3RyaXBRdW90ZXMpKHR5cGVmYWNlKTsKICAgICAgY29uc3QgZm9udCA9IHRoaXMuZm9ybVtfeGZhX29iamVjdC4kZ2xvYmFsRGF0YV0uZm9udEZpbmRlci5maW5kKHR5cGVmYWNlKTsKICAgICAgaWYgKCFmb250KSB7CiAgICAgICAgbWlzc2luZ0ZvbnRzLnB1c2godHlwZWZhY2UpOwogICAgICB9CiAgICB9CiAgICBpZiAobWlzc2luZ0ZvbnRzLmxlbmd0aCA+IDApIHsKICAgICAgcmV0dXJuIG1pc3NpbmdGb250czsKICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICBhcHBlbmRGb250cyhmb250cywgcmVhbGx5TWlzc2luZ0ZvbnRzKSB7CiAgICB0aGlzLmZvcm1bX3hmYV9vYmplY3QuJGdsb2JhbERhdGFdLmZvbnRGaW5kZXIuYWRkKGZvbnRzLCByZWFsbHlNaXNzaW5nRm9udHMpOwogIH0KICBhc3luYyBnZXRQYWdlcygpIHsKICAgIGlmICghdGhpcy5wYWdlcykgewogICAgICBhd2FpdCB0aGlzLl9jcmVhdGVQYWdlcygpOwogICAgfQogICAgY29uc3QgcGFnZXMgPSB0aGlzLnBhZ2VzOwogICAgdGhpcy5wYWdlcyA9IG51bGw7CiAgICByZXR1cm4gcGFnZXM7CiAgfQogIHNlcmlhbGl6ZURhdGEoc3RvcmFnZSkgewogICAgcmV0dXJuIHRoaXMuZGF0YUhhbmRsZXIuc2VyaWFsaXplKHN0b3JhZ2UpOwogIH0KICBzdGF0aWMgX2NyZWF0ZURvY3VtZW50KGRhdGEpIHsKICAgIGlmICghZGF0YVsiL3hkcDp4ZHAiXSkgewogICAgICByZXR1cm4gZGF0YVsieGRwOnhkcCJdOwogICAgfQogICAgcmV0dXJuIE9iamVjdC52YWx1ZXMoZGF0YSkuam9pbigiIik7CiAgfQogIHN0YXRpYyBnZXRSaWNoVGV4dEFzSHRtbChyYykgewogICAgaWYgKCFyYyB8fCB0eXBlb2YgcmMgIT09ICJzdHJpbmciKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgdHJ5IHsKICAgICAgbGV0IHJvb3QgPSBuZXcgX3BhcnNlci5YRkFQYXJzZXIoX3hodG1sLlhodG1sTmFtZXNwYWNlLCB0cnVlKS5wYXJzZShyYyk7CiAgICAgIGlmICghWyJib2R5IiwgInhodG1sIl0uaW5jbHVkZXMocm9vdFtfeGZhX29iamVjdC4kbm9kZU5hbWVdKSkgewogICAgICAgIGNvbnN0IG5ld1Jvb3QgPSBfeGh0bWwuWGh0bWxOYW1lc3BhY2UuYm9keSh7fSk7CiAgICAgICAgbmV3Um9vdFtfeGZhX29iamVjdC4kYXBwZW5kQ2hpbGRdKHJvb3QpOwogICAgICAgIHJvb3QgPSBuZXdSb290OwogICAgICB9CiAgICAgIGNvbnN0IHJlc3VsdCA9IHJvb3RbX3hmYV9vYmplY3QuJHRvSFRNTF0oKTsKICAgICAgaWYgKCFyZXN1bHQuc3VjY2VzcykgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IHsKICAgICAgICBodG1sCiAgICAgIH0gPSByZXN1bHQ7CiAgICAgIGNvbnN0IHsKICAgICAgICBhdHRyaWJ1dGVzCiAgICAgIH0gPSBodG1sOwogICAgICBpZiAoYXR0cmlidXRlcykgewogICAgICAgIGlmIChhdHRyaWJ1dGVzLmNsYXNzKSB7CiAgICAgICAgICBhdHRyaWJ1dGVzLmNsYXNzID0gYXR0cmlidXRlcy5jbGFzcy5maWx0ZXIoYXR0ciA9PiAhYXR0ci5zdGFydHNXaXRoKCJ4ZmEiKSk7CiAgICAgICAgfQogICAgICAgIGF0dHJpYnV0ZXMuZGlyID0gImF1dG8iOwogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgaHRtbCwKICAgICAgICBzdHI6IHJvb3RbX3hmYV9vYmplY3QuJHRleHRdKCkKICAgICAgfTsKICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKGBYRkEgLSBhbiBlcnJvciBvY2N1cnJlZCBkdXJpbmcgcGFyc2luZyBvZiByaWNoIHRleHQ6ICR7ZX1gKTsKICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KfQpleHBvcnRzLlhGQUZhY3RvcnkgPSBYRkFGYWN0b3J5OwoKLyoqKi8gfSksCi8qIDIxMiAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuWG1sT2JqZWN0ID0gZXhwb3J0cy5YRkFPYmplY3RBcnJheSA9IGV4cG9ydHMuWEZBT2JqZWN0ID0gZXhwb3J0cy5YRkFBdHRyaWJ1dGUgPSBleHBvcnRzLlN0cmluZ09iamVjdCA9IGV4cG9ydHMuT3B0aW9uT2JqZWN0ID0gZXhwb3J0cy5PcHRpb24xMCA9IGV4cG9ydHMuT3B0aW9uMDEgPSBleHBvcnRzLkludGVnZXJPYmplY3QgPSBleHBvcnRzLkNvbnRlbnRPYmplY3QgPSBleHBvcnRzLiR1aWQgPSBleHBvcnRzLiR0b1N0eWxlID0gZXhwb3J0cy4kdG9TdHJpbmcgPSBleHBvcnRzLiR0b1BhZ2VzID0gZXhwb3J0cy4kdG9IVE1MID0gZXhwb3J0cy4kdGV4dCA9IGV4cG9ydHMuJHRhYkluZGV4ID0gZXhwb3J0cy4kc2V0VmFsdWUgPSBleHBvcnRzLiRzZXRTZXRBdHRyaWJ1dGVzID0gZXhwb3J0cy4kc2V0SWQgPSBleHBvcnRzLiRzZWFyY2hOb2RlID0gZXhwb3J0cy4kcm9vdCA9IGV4cG9ydHMuJHJlc29sdmVQcm90b3R5cGVzID0gZXhwb3J0cy4kcmVtb3ZlQ2hpbGQgPSBleHBvcnRzLiRwdXNoUGFyYSA9IGV4cG9ydHMuJHB1c2hHbHlwaHMgPSBleHBvcnRzLiRwb3BQYXJhID0gZXhwb3J0cy4kb25UZXh0ID0gZXhwb3J0cy4kb25DaGlsZENoZWNrID0gZXhwb3J0cy4kb25DaGlsZCA9IGV4cG9ydHMuJG5zQXR0cmlidXRlcyA9IGV4cG9ydHMuJG5vZGVOYW1lID0gZXhwb3J0cy4kbmFtZXNwYWNlSWQgPSBleHBvcnRzLiRpc1VzYWJsZSA9IGV4cG9ydHMuJGlzVHJhbnNwYXJlbnQgPSBleHBvcnRzLiRpc1RoZXJlTW9yZVdpZHRoID0gZXhwb3J0cy4kaXNTcGxpdHRhYmxlID0gZXhwb3J0cy4kaXNOc0Fnbm9zdGljID0gZXhwb3J0cy4kaXNEZXNjZW5kZW50ID0gZXhwb3J0cy4kaXNEYXRhVmFsdWUgPSBleHBvcnRzLiRpc0NEQVRBWG1sID0gZXhwb3J0cy4kaXNCaW5kYWJsZSA9IGV4cG9ydHMuJGluc2VydEF0ID0gZXhwb3J0cy4kaW5kZXhPZiA9IGV4cG9ydHMuJGlkcyA9IGV4cG9ydHMuJGhhc1NldHRhYmxlVmFsdWUgPSBleHBvcnRzLiRnbG9iYWxEYXRhID0gZXhwb3J0cy4kZ2V0VGVtcGxhdGVSb290ID0gZXhwb3J0cy4kZ2V0U3ViZm9ybVBhcmVudCA9IGV4cG9ydHMuJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0ID0gZXhwb3J0cy4kZ2V0UGFyZW50ID0gZXhwb3J0cy4kZ2V0TmV4dFBhZ2UgPSBleHBvcnRzLiRnZXRFeHRyYSA9IGV4cG9ydHMuJGdldERhdGFWYWx1ZSA9IGV4cG9ydHMuJGdldENvbnRhaW5lZENoaWxkcmVuID0gZXhwb3J0cy4kZ2V0Q2hpbGRyZW5CeU5hbWVJdCA9IGV4cG9ydHMuJGdldENoaWxkcmVuQnlOYW1lID0gZXhwb3J0cy4kZ2V0Q2hpbGRyZW5CeUNsYXNzID0gZXhwb3J0cy4kZ2V0Q2hpbGRyZW4gPSBleHBvcnRzLiRnZXRBdmFpbGFibGVTcGFjZSA9IGV4cG9ydHMuJGdldEF0dHJpYnV0ZXMgPSBleHBvcnRzLiRnZXRBdHRyaWJ1dGVJdCA9IGV4cG9ydHMuJGZsdXNoSFRNTCA9IGV4cG9ydHMuJGZpbmFsaXplID0gZXhwb3J0cy4kZXh0cmEgPSBleHBvcnRzLiRkdW1wID0gZXhwb3J0cy4kZGF0YSA9IGV4cG9ydHMuJGNvbnRlbnQgPSBleHBvcnRzLiRjb25zdW1lZCA9IGV4cG9ydHMuJGNsb25lID0gZXhwb3J0cy4kY2xlYW51cCA9IGV4cG9ydHMuJGNsZWFuUGFnZSA9IGV4cG9ydHMuJGNsZWFuID0gZXhwb3J0cy4kY2hpbGRyZW5Ub0hUTUwgPSBleHBvcnRzLiRhcHBlbmRDaGlsZCA9IGV4cG9ydHMuJGFkZEhUTUwgPSBleHBvcnRzLiRhY2NlcHRXaGl0ZXNwYWNlID0gdm9pZCAwOwp2YXIgX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTMpOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwp2YXIgX2NvcmVfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDEzOSk7CnZhciBfbmFtZXNwYWNlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMjE0KTsKdmFyIF9zb20gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxNSk7CmNvbnN0ICRhY2NlcHRXaGl0ZXNwYWNlID0gU3ltYm9sKCk7CmV4cG9ydHMuJGFjY2VwdFdoaXRlc3BhY2UgPSAkYWNjZXB0V2hpdGVzcGFjZTsKY29uc3QgJGFkZEhUTUwgPSBTeW1ib2woKTsKZXhwb3J0cy4kYWRkSFRNTCA9ICRhZGRIVE1MOwpjb25zdCAkYXBwZW5kQ2hpbGQgPSBTeW1ib2woKTsKZXhwb3J0cy4kYXBwZW5kQ2hpbGQgPSAkYXBwZW5kQ2hpbGQ7CmNvbnN0ICRjaGlsZHJlblRvSFRNTCA9IFN5bWJvbCgpOwpleHBvcnRzLiRjaGlsZHJlblRvSFRNTCA9ICRjaGlsZHJlblRvSFRNTDsKY29uc3QgJGNsZWFuID0gU3ltYm9sKCk7CmV4cG9ydHMuJGNsZWFuID0gJGNsZWFuOwpjb25zdCAkY2xlYW5QYWdlID0gU3ltYm9sKCk7CmV4cG9ydHMuJGNsZWFuUGFnZSA9ICRjbGVhblBhZ2U7CmNvbnN0ICRjbGVhbnVwID0gU3ltYm9sKCk7CmV4cG9ydHMuJGNsZWFudXAgPSAkY2xlYW51cDsKY29uc3QgJGNsb25lID0gU3ltYm9sKCk7CmV4cG9ydHMuJGNsb25lID0gJGNsb25lOwpjb25zdCAkY29uc3VtZWQgPSBTeW1ib2woKTsKZXhwb3J0cy4kY29uc3VtZWQgPSAkY29uc3VtZWQ7CmNvbnN0ICRjb250ZW50ID0gU3ltYm9sKCJjb250ZW50Iik7CmV4cG9ydHMuJGNvbnRlbnQgPSAkY29udGVudDsKY29uc3QgJGRhdGEgPSBTeW1ib2woImRhdGEiKTsKZXhwb3J0cy4kZGF0YSA9ICRkYXRhOwpjb25zdCAkZHVtcCA9IFN5bWJvbCgpOwpleHBvcnRzLiRkdW1wID0gJGR1bXA7CmNvbnN0ICRleHRyYSA9IFN5bWJvbCgiZXh0cmEiKTsKZXhwb3J0cy4kZXh0cmEgPSAkZXh0cmE7CmNvbnN0ICRmaW5hbGl6ZSA9IFN5bWJvbCgpOwpleHBvcnRzLiRmaW5hbGl6ZSA9ICRmaW5hbGl6ZTsKY29uc3QgJGZsdXNoSFRNTCA9IFN5bWJvbCgpOwpleHBvcnRzLiRmbHVzaEhUTUwgPSAkZmx1c2hIVE1MOwpjb25zdCAkZ2V0QXR0cmlidXRlSXQgPSBTeW1ib2woKTsKZXhwb3J0cy4kZ2V0QXR0cmlidXRlSXQgPSAkZ2V0QXR0cmlidXRlSXQ7CmNvbnN0ICRnZXRBdHRyaWJ1dGVzID0gU3ltYm9sKCk7CmV4cG9ydHMuJGdldEF0dHJpYnV0ZXMgPSAkZ2V0QXR0cmlidXRlczsKY29uc3QgJGdldEF2YWlsYWJsZVNwYWNlID0gU3ltYm9sKCk7CmV4cG9ydHMuJGdldEF2YWlsYWJsZVNwYWNlID0gJGdldEF2YWlsYWJsZVNwYWNlOwpjb25zdCAkZ2V0Q2hpbGRyZW5CeUNsYXNzID0gU3ltYm9sKCk7CmV4cG9ydHMuJGdldENoaWxkcmVuQnlDbGFzcyA9ICRnZXRDaGlsZHJlbkJ5Q2xhc3M7CmNvbnN0ICRnZXRDaGlsZHJlbkJ5TmFtZSA9IFN5bWJvbCgpOwpleHBvcnRzLiRnZXRDaGlsZHJlbkJ5TmFtZSA9ICRnZXRDaGlsZHJlbkJ5TmFtZTsKY29uc3QgJGdldENoaWxkcmVuQnlOYW1lSXQgPSBTeW1ib2woKTsKZXhwb3J0cy4kZ2V0Q2hpbGRyZW5CeU5hbWVJdCA9ICRnZXRDaGlsZHJlbkJ5TmFtZUl0Owpjb25zdCAkZ2V0RGF0YVZhbHVlID0gU3ltYm9sKCk7CmV4cG9ydHMuJGdldERhdGFWYWx1ZSA9ICRnZXREYXRhVmFsdWU7CmNvbnN0ICRnZXRFeHRyYSA9IFN5bWJvbCgpOwpleHBvcnRzLiRnZXRFeHRyYSA9ICRnZXRFeHRyYTsKY29uc3QgJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0ID0gU3ltYm9sKCk7CmV4cG9ydHMuJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0ID0gJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0Owpjb25zdCAkZ2V0Q2hpbGRyZW4gPSBTeW1ib2woKTsKZXhwb3J0cy4kZ2V0Q2hpbGRyZW4gPSAkZ2V0Q2hpbGRyZW47CmNvbnN0ICRnZXRDb250YWluZWRDaGlsZHJlbiA9IFN5bWJvbCgpOwpleHBvcnRzLiRnZXRDb250YWluZWRDaGlsZHJlbiA9ICRnZXRDb250YWluZWRDaGlsZHJlbjsKY29uc3QgJGdldE5leHRQYWdlID0gU3ltYm9sKCk7CmV4cG9ydHMuJGdldE5leHRQYWdlID0gJGdldE5leHRQYWdlOwpjb25zdCAkZ2V0U3ViZm9ybVBhcmVudCA9IFN5bWJvbCgpOwpleHBvcnRzLiRnZXRTdWJmb3JtUGFyZW50ID0gJGdldFN1YmZvcm1QYXJlbnQ7CmNvbnN0ICRnZXRQYXJlbnQgPSBTeW1ib2woKTsKZXhwb3J0cy4kZ2V0UGFyZW50ID0gJGdldFBhcmVudDsKY29uc3QgJGdldFRlbXBsYXRlUm9vdCA9IFN5bWJvbCgpOwpleHBvcnRzLiRnZXRUZW1wbGF0ZVJvb3QgPSAkZ2V0VGVtcGxhdGVSb290Owpjb25zdCAkZ2xvYmFsRGF0YSA9IFN5bWJvbCgpOwpleHBvcnRzLiRnbG9iYWxEYXRhID0gJGdsb2JhbERhdGE7CmNvbnN0ICRoYXNTZXR0YWJsZVZhbHVlID0gU3ltYm9sKCk7CmV4cG9ydHMuJGhhc1NldHRhYmxlVmFsdWUgPSAkaGFzU2V0dGFibGVWYWx1ZTsKY29uc3QgJGlkcyA9IFN5bWJvbCgpOwpleHBvcnRzLiRpZHMgPSAkaWRzOwpjb25zdCAkaW5kZXhPZiA9IFN5bWJvbCgpOwpleHBvcnRzLiRpbmRleE9mID0gJGluZGV4T2Y7CmNvbnN0ICRpbnNlcnRBdCA9IFN5bWJvbCgpOwpleHBvcnRzLiRpbnNlcnRBdCA9ICRpbnNlcnRBdDsKY29uc3QgJGlzQ0RBVEFYbWwgPSBTeW1ib2woKTsKZXhwb3J0cy4kaXNDREFUQVhtbCA9ICRpc0NEQVRBWG1sOwpjb25zdCAkaXNCaW5kYWJsZSA9IFN5bWJvbCgpOwpleHBvcnRzLiRpc0JpbmRhYmxlID0gJGlzQmluZGFibGU7CmNvbnN0ICRpc0RhdGFWYWx1ZSA9IFN5bWJvbCgpOwpleHBvcnRzLiRpc0RhdGFWYWx1ZSA9ICRpc0RhdGFWYWx1ZTsKY29uc3QgJGlzRGVzY2VuZGVudCA9IFN5bWJvbCgpOwpleHBvcnRzLiRpc0Rlc2NlbmRlbnQgPSAkaXNEZXNjZW5kZW50Owpjb25zdCAkaXNOc0Fnbm9zdGljID0gU3ltYm9sKCk7CmV4cG9ydHMuJGlzTnNBZ25vc3RpYyA9ICRpc05zQWdub3N0aWM7CmNvbnN0ICRpc1NwbGl0dGFibGUgPSBTeW1ib2woKTsKZXhwb3J0cy4kaXNTcGxpdHRhYmxlID0gJGlzU3BsaXR0YWJsZTsKY29uc3QgJGlzVGhlcmVNb3JlV2lkdGggPSBTeW1ib2woKTsKZXhwb3J0cy4kaXNUaGVyZU1vcmVXaWR0aCA9ICRpc1RoZXJlTW9yZVdpZHRoOwpjb25zdCAkaXNUcmFuc3BhcmVudCA9IFN5bWJvbCgpOwpleHBvcnRzLiRpc1RyYW5zcGFyZW50ID0gJGlzVHJhbnNwYXJlbnQ7CmNvbnN0ICRpc1VzYWJsZSA9IFN5bWJvbCgpOwpleHBvcnRzLiRpc1VzYWJsZSA9ICRpc1VzYWJsZTsKY29uc3QgJGxhc3RBdHRyaWJ1dGUgPSBTeW1ib2woKTsKY29uc3QgJG5hbWVzcGFjZUlkID0gU3ltYm9sKCJuYW1lc3BhY2VJZCIpOwpleHBvcnRzLiRuYW1lc3BhY2VJZCA9ICRuYW1lc3BhY2VJZDsKY29uc3QgJG5vZGVOYW1lID0gU3ltYm9sKCJub2RlTmFtZSIpOwpleHBvcnRzLiRub2RlTmFtZSA9ICRub2RlTmFtZTsKY29uc3QgJG5zQXR0cmlidXRlcyA9IFN5bWJvbCgpOwpleHBvcnRzLiRuc0F0dHJpYnV0ZXMgPSAkbnNBdHRyaWJ1dGVzOwpjb25zdCAkb25DaGlsZCA9IFN5bWJvbCgpOwpleHBvcnRzLiRvbkNoaWxkID0gJG9uQ2hpbGQ7CmNvbnN0ICRvbkNoaWxkQ2hlY2sgPSBTeW1ib2woKTsKZXhwb3J0cy4kb25DaGlsZENoZWNrID0gJG9uQ2hpbGRDaGVjazsKY29uc3QgJG9uVGV4dCA9IFN5bWJvbCgpOwpleHBvcnRzLiRvblRleHQgPSAkb25UZXh0Owpjb25zdCAkcHVzaEdseXBocyA9IFN5bWJvbCgpOwpleHBvcnRzLiRwdXNoR2x5cGhzID0gJHB1c2hHbHlwaHM7CmNvbnN0ICRwb3BQYXJhID0gU3ltYm9sKCk7CmV4cG9ydHMuJHBvcFBhcmEgPSAkcG9wUGFyYTsKY29uc3QgJHB1c2hQYXJhID0gU3ltYm9sKCk7CmV4cG9ydHMuJHB1c2hQYXJhID0gJHB1c2hQYXJhOwpjb25zdCAkcmVtb3ZlQ2hpbGQgPSBTeW1ib2woKTsKZXhwb3J0cy4kcmVtb3ZlQ2hpbGQgPSAkcmVtb3ZlQ2hpbGQ7CmNvbnN0ICRyb290ID0gU3ltYm9sKCJyb290Iik7CmV4cG9ydHMuJHJvb3QgPSAkcm9vdDsKY29uc3QgJHJlc29sdmVQcm90b3R5cGVzID0gU3ltYm9sKCk7CmV4cG9ydHMuJHJlc29sdmVQcm90b3R5cGVzID0gJHJlc29sdmVQcm90b3R5cGVzOwpjb25zdCAkc2VhcmNoTm9kZSA9IFN5bWJvbCgpOwpleHBvcnRzLiRzZWFyY2hOb2RlID0gJHNlYXJjaE5vZGU7CmNvbnN0ICRzZXRJZCA9IFN5bWJvbCgpOwpleHBvcnRzLiRzZXRJZCA9ICRzZXRJZDsKY29uc3QgJHNldFNldEF0dHJpYnV0ZXMgPSBTeW1ib2woKTsKZXhwb3J0cy4kc2V0U2V0QXR0cmlidXRlcyA9ICRzZXRTZXRBdHRyaWJ1dGVzOwpjb25zdCAkc2V0VmFsdWUgPSBTeW1ib2woKTsKZXhwb3J0cy4kc2V0VmFsdWUgPSAkc2V0VmFsdWU7CmNvbnN0ICR0YWJJbmRleCA9IFN5bWJvbCgpOwpleHBvcnRzLiR0YWJJbmRleCA9ICR0YWJJbmRleDsKY29uc3QgJHRleHQgPSBTeW1ib2woKTsKZXhwb3J0cy4kdGV4dCA9ICR0ZXh0Owpjb25zdCAkdG9QYWdlcyA9IFN5bWJvbCgpOwpleHBvcnRzLiR0b1BhZ2VzID0gJHRvUGFnZXM7CmNvbnN0ICR0b0hUTUwgPSBTeW1ib2woKTsKZXhwb3J0cy4kdG9IVE1MID0gJHRvSFRNTDsKY29uc3QgJHRvU3RyaW5nID0gU3ltYm9sKCk7CmV4cG9ydHMuJHRvU3RyaW5nID0gJHRvU3RyaW5nOwpjb25zdCAkdG9TdHlsZSA9IFN5bWJvbCgpOwpleHBvcnRzLiR0b1N0eWxlID0gJHRvU3R5bGU7CmNvbnN0ICR1aWQgPSBTeW1ib2woInVpZCIpOwpleHBvcnRzLiR1aWQgPSAkdWlkOwpjb25zdCBfYXBwbHlQcm90b3R5cGUgPSBTeW1ib2woKTsKY29uc3QgX2F0dHJpYnV0ZXMgPSBTeW1ib2woKTsKY29uc3QgX2F0dHJpYnV0ZU5hbWVzID0gU3ltYm9sKCk7CmNvbnN0IF9jaGlsZHJlbiA9IFN5bWJvbCgiX2NoaWxkcmVuIik7CmNvbnN0IF9jbG9uZUF0dHJpYnV0ZSA9IFN5bWJvbCgpOwpjb25zdCBfZGF0YVZhbHVlID0gU3ltYm9sKCk7CmNvbnN0IF9kZWZhdWx0VmFsdWUgPSBTeW1ib2woKTsKY29uc3QgX2ZpbHRlcmVkQ2hpbGRyZW5HZW5lcmF0b3IgPSBTeW1ib2woKTsKY29uc3QgX2dldFByb3RvdHlwZSA9IFN5bWJvbCgpOwpjb25zdCBfZ2V0VW5zZXRBdHRyaWJ1dGVzID0gU3ltYm9sKCk7CmNvbnN0IF9oYXNDaGlsZHJlbiA9IFN5bWJvbCgpOwpjb25zdCBfbWF4ID0gU3ltYm9sKCk7CmNvbnN0IF9vcHRpb25zID0gU3ltYm9sKCk7CmNvbnN0IF9wYXJlbnQgPSBTeW1ib2woInBhcmVudCIpOwpjb25zdCBfcmVzb2x2ZVByb3RvdHlwZXNIZWxwZXIgPSBTeW1ib2woKTsKY29uc3QgX3NldEF0dHJpYnV0ZXMgPSBTeW1ib2woKTsKY29uc3QgX3ZhbGlkYXRvciA9IFN5bWJvbCgpOwpsZXQgdWlkID0gMDsKY29uc3QgTlNfREFUQVNFVFMgPSBfbmFtZXNwYWNlcy5OYW1lc3BhY2VJZHMuZGF0YXNldHMuaWQ7CmNsYXNzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IobnNJZCwgbmFtZSkgewogICAgbGV0IGhhc0NoaWxkcmVuID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBmYWxzZTsKICAgIHRoaXNbJG5hbWVzcGFjZUlkXSA9IG5zSWQ7CiAgICB0aGlzWyRub2RlTmFtZV0gPSBuYW1lOwogICAgdGhpc1tfaGFzQ2hpbGRyZW5dID0gaGFzQ2hpbGRyZW47CiAgICB0aGlzW19wYXJlbnRdID0gbnVsbDsKICAgIHRoaXNbX2NoaWxkcmVuXSA9IFtdOwogICAgdGhpc1skdWlkXSA9IGAke25hbWV9JHt1aWQrK31gOwogICAgdGhpc1skZ2xvYmFsRGF0YV0gPSBudWxsOwogIH0KICBbJG9uQ2hpbGRdKGNoaWxkKSB7CiAgICBpZiAoIXRoaXNbX2hhc0NoaWxkcmVuXSB8fCAhdGhpc1skb25DaGlsZENoZWNrXShjaGlsZCkpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgY29uc3QgbmFtZSA9IGNoaWxkWyRub2RlTmFtZV07CiAgICBjb25zdCBub2RlID0gdGhpc1tuYW1lXTsKICAgIGlmIChub2RlIGluc3RhbmNlb2YgWEZBT2JqZWN0QXJyYXkpIHsKICAgICAgaWYgKG5vZGUucHVzaChjaGlsZCkpIHsKICAgICAgICB0aGlzWyRhcHBlbmRDaGlsZF0oY2hpbGQpOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBpZiAobm9kZSAhPT0gbnVsbCkgewogICAgICAgIHRoaXNbJHJlbW92ZUNoaWxkXShub2RlKTsKICAgICAgfQogICAgICB0aGlzW25hbWVdID0gY2hpbGQ7CiAgICAgIHRoaXNbJGFwcGVuZENoaWxkXShjaGlsZCk7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgbGV0IGlkID0gIiI7CiAgICBpZiAodGhpcy5pZCkgewogICAgICBpZCA9IGAgKGlkOiAke3RoaXMuaWR9KWA7CiAgICB9IGVsc2UgaWYgKHRoaXMubmFtZSkgewogICAgICBpZCA9IGAgKG5hbWU6ICR7dGhpcy5uYW1lfSAke3RoaXMuaC52YWx1ZX0pYDsKICAgIH0KICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gbm9kZSAiJHt0aGlzWyRub2RlTmFtZV19IiR7aWR9IGhhcyBhbHJlYWR5IGVub3VnaCAiJHtuYW1lfSIhYCk7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskb25DaGlsZENoZWNrXShjaGlsZCkgewogICAgcmV0dXJuIHRoaXMuaGFzT3duUHJvcGVydHkoY2hpbGRbJG5vZGVOYW1lXSkgJiYgY2hpbGRbJG5hbWVzcGFjZUlkXSA9PT0gdGhpc1skbmFtZXNwYWNlSWRdOwogIH0KICBbJGlzTnNBZ25vc3RpY10oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskYWNjZXB0V2hpdGVzcGFjZV0oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskaXNDREFUQVhtbF0oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskaXNCaW5kYWJsZV0oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskcG9wUGFyYV0oKSB7CiAgICBpZiAodGhpcy5wYXJhKSB7CiAgICAgIHRoaXNbJGdldFRlbXBsYXRlUm9vdF0oKVskZXh0cmFdLnBhcmFTdGFjay5wb3AoKTsKICAgIH0KICB9CiAgWyRwdXNoUGFyYV0oKSB7CiAgICB0aGlzWyRnZXRUZW1wbGF0ZVJvb3RdKClbJGV4dHJhXS5wYXJhU3RhY2sucHVzaCh0aGlzLnBhcmEpOwogIH0KICBbJHNldElkXShpZHMpIHsKICAgIGlmICh0aGlzLmlkICYmIHRoaXNbJG5hbWVzcGFjZUlkXSA9PT0gX25hbWVzcGFjZXMuTmFtZXNwYWNlSWRzLnRlbXBsYXRlLmlkKSB7CiAgICAgIGlkcy5zZXQodGhpcy5pZCwgdGhpcyk7CiAgICB9CiAgfQogIFskZ2V0VGVtcGxhdGVSb290XSgpIHsKICAgIHJldHVybiB0aGlzWyRnbG9iYWxEYXRhXS50ZW1wbGF0ZTsKICB9CiAgWyRpc1NwbGl0dGFibGVdKCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBbJGlzVGhlcmVNb3JlV2lkdGhdKCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBbJGFwcGVuZENoaWxkXShjaGlsZCkgewogICAgY2hpbGRbX3BhcmVudF0gPSB0aGlzOwogICAgdGhpc1tfY2hpbGRyZW5dLnB1c2goY2hpbGQpOwogICAgaWYgKCFjaGlsZFskZ2xvYmFsRGF0YV0gJiYgdGhpc1skZ2xvYmFsRGF0YV0pIHsKICAgICAgY2hpbGRbJGdsb2JhbERhdGFdID0gdGhpc1skZ2xvYmFsRGF0YV07CiAgICB9CiAgfQogIFskcmVtb3ZlQ2hpbGRdKGNoaWxkKSB7CiAgICBjb25zdCBpID0gdGhpc1tfY2hpbGRyZW5dLmluZGV4T2YoY2hpbGQpOwogICAgdGhpc1tfY2hpbGRyZW5dLnNwbGljZShpLCAxKTsKICB9CiAgWyRoYXNTZXR0YWJsZVZhbHVlXSgpIHsKICAgIHJldHVybiB0aGlzLmhhc093blByb3BlcnR5KCJ2YWx1ZSIpOwogIH0KICBbJHNldFZhbHVlXShfKSB7fQogIFskb25UZXh0XShfKSB7fQogIFskZmluYWxpemVdKCkge30KICBbJGNsZWFuXShidWlsZGVyKSB7CiAgICBkZWxldGUgdGhpc1tfaGFzQ2hpbGRyZW5dOwogICAgaWYgKHRoaXNbJGNsZWFudXBdKSB7CiAgICAgIGJ1aWxkZXIuY2xlYW4odGhpc1skY2xlYW51cF0pOwogICAgICBkZWxldGUgdGhpc1skY2xlYW51cF07CiAgICB9CiAgfQogIFskaW5kZXhPZl0oY2hpbGQpIHsKICAgIHJldHVybiB0aGlzW19jaGlsZHJlbl0uaW5kZXhPZihjaGlsZCk7CiAgfQogIFskaW5zZXJ0QXRdKGksIGNoaWxkKSB7CiAgICBjaGlsZFtfcGFyZW50XSA9IHRoaXM7CiAgICB0aGlzW19jaGlsZHJlbl0uc3BsaWNlKGksIDAsIGNoaWxkKTsKICAgIGlmICghY2hpbGRbJGdsb2JhbERhdGFdICYmIHRoaXNbJGdsb2JhbERhdGFdKSB7CiAgICAgIGNoaWxkWyRnbG9iYWxEYXRhXSA9IHRoaXNbJGdsb2JhbERhdGFdOwogICAgfQogIH0KICBbJGlzVHJhbnNwYXJlbnRdKCkgewogICAgcmV0dXJuICF0aGlzLm5hbWU7CiAgfQogIFskbGFzdEF0dHJpYnV0ZV0oKSB7CiAgICByZXR1cm4gIiI7CiAgfQogIFskdGV4dF0oKSB7CiAgICBpZiAodGhpc1tfY2hpbGRyZW5dLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gdGhpc1skY29udGVudF07CiAgICB9CiAgICByZXR1cm4gdGhpc1tfY2hpbGRyZW5dLm1hcChjID0+IGNbJHRleHRdKCkpLmpvaW4oIiIpOwogIH0KICBnZXQgW19hdHRyaWJ1dGVOYW1lc10oKSB7CiAgICBjb25zdCBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzKTsKICAgIGlmICghcHJvdG8uX2F0dHJpYnV0ZXMpIHsKICAgICAgY29uc3QgYXR0cmlidXRlcyA9IHByb3RvLl9hdHRyaWJ1dGVzID0gbmV3IFNldCgpOwogICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcykpIHsKICAgICAgICBpZiAodGhpc1tuYW1lXSA9PT0gbnVsbCB8fCB0aGlzW25hbWVdIGluc3RhbmNlb2YgWEZBT2JqZWN0IHx8IHRoaXNbbmFtZV0gaW5zdGFuY2VvZiBYRkFPYmplY3RBcnJheSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGF0dHJpYnV0ZXMuYWRkKG5hbWUpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgX2F0dHJpYnV0ZU5hbWVzLCBwcm90by5fYXR0cmlidXRlcyk7CiAgfQogIFskaXNEZXNjZW5kZW50XShwYXJlbnQpIHsKICAgIGxldCBub2RlID0gdGhpczsKICAgIHdoaWxlIChub2RlKSB7CiAgICAgIGlmIChub2RlID09PSBwYXJlbnQpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBub2RlID0gbm9kZVskZ2V0UGFyZW50XSgpOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KICBbJGdldFBhcmVudF0oKSB7CiAgICByZXR1cm4gdGhpc1tfcGFyZW50XTsKICB9CiAgWyRnZXRTdWJmb3JtUGFyZW50XSgpIHsKICAgIHJldHVybiB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgfQogIFskZ2V0Q2hpbGRyZW5dKCkgewogICAgbGV0IG5hbWUgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IG51bGw7CiAgICBpZiAoIW5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXTsKICAgIH0KICAgIHJldHVybiB0aGlzW25hbWVdOwogIH0KICBbJGR1bXBdKCkgewogICAgY29uc3QgZHVtcGVkID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGlmICh0aGlzWyRjb250ZW50XSkgewogICAgICBkdW1wZWQuJGNvbnRlbnQgPSB0aGlzWyRjb250ZW50XTsKICAgIH0KICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSkgewogICAgICBjb25zdCB2YWx1ZSA9IHRoaXNbbmFtZV07CiAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFhGQU9iamVjdCkgewogICAgICAgIGR1bXBlZFtuYW1lXSA9IHZhbHVlWyRkdW1wXSgpOwogICAgICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgWEZBT2JqZWN0QXJyYXkpIHsKICAgICAgICBpZiAoIXZhbHVlLmlzRW1wdHkoKSkgewogICAgICAgICAgZHVtcGVkW25hbWVdID0gdmFsdWUuZHVtcCgpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBkdW1wZWRbbmFtZV0gPSB2YWx1ZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGR1bXBlZDsKICB9CiAgWyR0b1N0eWxlXSgpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBbJHRvSFRNTF0oKSB7CiAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuRU1QVFk7CiAgfQogICpbJGdldENvbnRhaW5lZENoaWxkcmVuXSgpIHsKICAgIGZvciAoY29uc3Qgbm9kZSBvZiB0aGlzWyRnZXRDaGlsZHJlbl0oKSkgewogICAgICB5aWVsZCBub2RlOwogICAgfQogIH0KICAqW19maWx0ZXJlZENoaWxkcmVuR2VuZXJhdG9yXShmaWx0ZXIsIGluY2x1ZGUpIHsKICAgIGZvciAoY29uc3Qgbm9kZSBvZiB0aGlzWyRnZXRDb250YWluZWRDaGlsZHJlbl0oKSkgewogICAgICBpZiAoIWZpbHRlciB8fCBpbmNsdWRlID09PSBmaWx0ZXIuaGFzKG5vZGVbJG5vZGVOYW1lXSkpIHsKICAgICAgICBjb25zdCBhdmFpbGFibGVTcGFjZSA9IHRoaXNbJGdldEF2YWlsYWJsZVNwYWNlXSgpOwogICAgICAgIGNvbnN0IHJlcyA9IG5vZGVbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpOwogICAgICAgIGlmICghcmVzLnN1Y2Nlc3MpIHsKICAgICAgICAgIHRoaXNbJGV4dHJhXS5mYWlsaW5nTm9kZSA9IG5vZGU7CiAgICAgICAgfQogICAgICAgIHlpZWxkIHJlczsKICAgICAgfQogICAgfQogIH0KICBbJGZsdXNoSFRNTF0oKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgWyRhZGRIVE1MXShodG1sLCBiYm94KSB7CiAgICB0aGlzWyRleHRyYV0uY2hpbGRyZW4ucHVzaChodG1sKTsKICB9CiAgWyRnZXRBdmFpbGFibGVTcGFjZV0oKSB7fQogIFskY2hpbGRyZW5Ub0hUTUxdKF9yZWYpIHsKICAgIGxldCB7CiAgICAgIGZpbHRlciA9IG51bGwsCiAgICAgIGluY2x1ZGUgPSB0cnVlCiAgICB9ID0gX3JlZjsKICAgIGlmICghdGhpc1skZXh0cmFdLmdlbmVyYXRvcikgewogICAgICB0aGlzWyRleHRyYV0uZ2VuZXJhdG9yID0gdGhpc1tfZmlsdGVyZWRDaGlsZHJlbkdlbmVyYXRvcl0oZmlsdGVyLCBpbmNsdWRlKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IGF2YWlsYWJsZVNwYWNlID0gdGhpc1skZ2V0QXZhaWxhYmxlU3BhY2VdKCk7CiAgICAgIGNvbnN0IHJlcyA9IHRoaXNbJGV4dHJhXS5mYWlsaW5nTm9kZVskdG9IVE1MXShhdmFpbGFibGVTcGFjZSk7CiAgICAgIGlmICghcmVzLnN1Y2Nlc3MpIHsKICAgICAgICByZXR1cm4gcmVzOwogICAgICB9CiAgICAgIGlmIChyZXMuaHRtbCkgewogICAgICAgIHRoaXNbJGFkZEhUTUxdKHJlcy5odG1sLCByZXMuYmJveCk7CiAgICAgIH0KICAgICAgZGVsZXRlIHRoaXNbJGV4dHJhXS5mYWlsaW5nTm9kZTsKICAgIH0KICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIGNvbnN0IGdlbiA9IHRoaXNbJGV4dHJhXS5nZW5lcmF0b3IubmV4dCgpOwogICAgICBpZiAoZ2VuLmRvbmUpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBjb25zdCByZXMgPSBnZW4udmFsdWU7CiAgICAgIGlmICghcmVzLnN1Y2Nlc3MpIHsKICAgICAgICByZXR1cm4gcmVzOwogICAgICB9CiAgICAgIGlmIChyZXMuaHRtbCkgewogICAgICAgIHRoaXNbJGFkZEhUTUxdKHJlcy5odG1sLCByZXMuYmJveCk7CiAgICAgIH0KICAgIH0KICAgIHRoaXNbJGV4dHJhXS5nZW5lcmF0b3IgPSBudWxsOwogICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LkVNUFRZOwogIH0KICBbJHNldFNldEF0dHJpYnV0ZXNdKGF0dHJpYnV0ZXMpIHsKICAgIHRoaXNbX3NldEF0dHJpYnV0ZXNdID0gbmV3IFNldChPYmplY3Qua2V5cyhhdHRyaWJ1dGVzKSk7CiAgfQogIFtfZ2V0VW5zZXRBdHRyaWJ1dGVzXShwcm90b0F0dHJpYnV0ZXMpIHsKICAgIGNvbnN0IGFsbEF0dHIgPSB0aGlzW19hdHRyaWJ1dGVOYW1lc107CiAgICBjb25zdCBzZXRBdHRyID0gdGhpc1tfc2V0QXR0cmlidXRlc107CiAgICByZXR1cm4gWy4uLnByb3RvQXR0cmlidXRlc10uZmlsdGVyKHggPT4gYWxsQXR0ci5oYXMoeCkgJiYgIXNldEF0dHIuaGFzKHgpKTsKICB9CiAgWyRyZXNvbHZlUHJvdG90eXBlc10oaWRzKSB7CiAgICBsZXQgYW5jZXN0b3JzID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBuZXcgU2V0KCk7CiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHRoaXNbX2NoaWxkcmVuXSkgewogICAgICBjaGlsZFtfcmVzb2x2ZVByb3RvdHlwZXNIZWxwZXJdKGlkcywgYW5jZXN0b3JzKTsKICAgIH0KICB9CiAgW19yZXNvbHZlUHJvdG90eXBlc0hlbHBlcl0oaWRzLCBhbmNlc3RvcnMpIHsKICAgIGNvbnN0IHByb3RvID0gdGhpc1tfZ2V0UHJvdG90eXBlXShpZHMsIGFuY2VzdG9ycyk7CiAgICBpZiAocHJvdG8pIHsKICAgICAgdGhpc1tfYXBwbHlQcm90b3R5cGVdKHByb3RvLCBpZHMsIGFuY2VzdG9ycyk7CiAgICB9IGVsc2UgewogICAgICB0aGlzWyRyZXNvbHZlUHJvdG90eXBlc10oaWRzLCBhbmNlc3RvcnMpOwogICAgfQogIH0KICBbX2dldFByb3RvdHlwZV0oaWRzLCBhbmNlc3RvcnMpIHsKICAgIGNvbnN0IHsKICAgICAgdXNlLAogICAgICB1c2VocmVmCiAgICB9ID0gdGhpczsKICAgIGlmICghdXNlICYmICF1c2VocmVmKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgbGV0IHByb3RvID0gbnVsbDsKICAgIGxldCBzb21FeHByZXNzaW9uID0gbnVsbDsKICAgIGxldCBpZCA9IG51bGw7CiAgICBsZXQgcmVmID0gdXNlOwogICAgaWYgKHVzZWhyZWYpIHsKICAgICAgcmVmID0gdXNlaHJlZjsKICAgICAgaWYgKHVzZWhyZWYuc3RhcnRzV2l0aCgiI3NvbSgiKSAmJiB1c2VocmVmLmVuZHNXaXRoKCIpIikpIHsKICAgICAgICBzb21FeHByZXNzaW9uID0gdXNlaHJlZi5zbGljZSgiI3NvbSgiLmxlbmd0aCwgLTEpOwogICAgICB9IGVsc2UgaWYgKHVzZWhyZWYuc3RhcnRzV2l0aCgiLiNzb20oIikgJiYgdXNlaHJlZi5lbmRzV2l0aCgiKSIpKSB7CiAgICAgICAgc29tRXhwcmVzc2lvbiA9IHVzZWhyZWYuc2xpY2UoIi4jc29tKCIubGVuZ3RoLCAtMSk7CiAgICAgIH0gZWxzZSBpZiAodXNlaHJlZi5zdGFydHNXaXRoKCIjIikpIHsKICAgICAgICBpZCA9IHVzZWhyZWYuc2xpY2UoMSk7CiAgICAgIH0gZWxzZSBpZiAodXNlaHJlZi5zdGFydHNXaXRoKCIuIyIpKSB7CiAgICAgICAgaWQgPSB1c2VocmVmLnNsaWNlKDIpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKHVzZS5zdGFydHNXaXRoKCIjIikpIHsKICAgICAgaWQgPSB1c2Uuc2xpY2UoMSk7CiAgICB9IGVsc2UgewogICAgICBzb21FeHByZXNzaW9uID0gdXNlOwogICAgfQogICAgdGhpcy51c2UgPSB0aGlzLnVzZWhyZWYgPSAiIjsKICAgIGlmIChpZCkgewogICAgICBwcm90byA9IGlkcy5nZXQoaWQpOwogICAgfSBlbHNlIHsKICAgICAgcHJvdG8gPSAoMCwgX3NvbS5zZWFyY2hOb2RlKShpZHMuZ2V0KCRyb290KSwgdGhpcywgc29tRXhwcmVzc2lvbiwgdHJ1ZSwgZmFsc2UpOwogICAgICBpZiAocHJvdG8pIHsKICAgICAgICBwcm90byA9IHByb3RvWzBdOwogICAgICB9CiAgICB9CiAgICBpZiAoIXByb3RvKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gSW52YWxpZCBwcm90b3R5cGUgcmVmZXJlbmNlOiAke3JlZn0uYCk7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKHByb3RvWyRub2RlTmFtZV0gIT09IHRoaXNbJG5vZGVOYW1lXSkgewogICAgICAoMCwgX3V0aWwud2FybikoYFhGQSAtIEluY29tcGF0aWJsZSBwcm90b3R5cGU6ICR7cHJvdG9bJG5vZGVOYW1lXX0gIT09ICR7dGhpc1skbm9kZU5hbWVdfS5gKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBpZiAoYW5jZXN0b3JzLmhhcyhwcm90bykpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKGBYRkEgLSBDeWNsZSBkZXRlY3RlZCBpbiBwcm90b3R5cGVzIHVzZS5gKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBhbmNlc3RvcnMuYWRkKHByb3RvKTsKICAgIGNvbnN0IHByb3RvUHJvdG8gPSBwcm90b1tfZ2V0UHJvdG90eXBlXShpZHMsIGFuY2VzdG9ycyk7CiAgICBpZiAocHJvdG9Qcm90bykgewogICAgICBwcm90b1tfYXBwbHlQcm90b3R5cGVdKHByb3RvUHJvdG8sIGlkcywgYW5jZXN0b3JzKTsKICAgIH0KICAgIHByb3RvWyRyZXNvbHZlUHJvdG90eXBlc10oaWRzLCBhbmNlc3RvcnMpOwogICAgYW5jZXN0b3JzLmRlbGV0ZShwcm90byk7CiAgICByZXR1cm4gcHJvdG87CiAgfQogIFtfYXBwbHlQcm90b3R5cGVdKHByb3RvLCBpZHMsIGFuY2VzdG9ycykgewogICAgaWYgKGFuY2VzdG9ycy5oYXMocHJvdG8pKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gQ3ljbGUgZGV0ZWN0ZWQgaW4gcHJvdG90eXBlcyB1c2UuYCk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICghdGhpc1skY29udGVudF0gJiYgcHJvdG9bJGNvbnRlbnRdKSB7CiAgICAgIHRoaXNbJGNvbnRlbnRdID0gcHJvdG9bJGNvbnRlbnRdOwogICAgfQogICAgY29uc3QgbmV3QW5jZXN0b3JzID0gbmV3IFNldChhbmNlc3RvcnMpOwogICAgbmV3QW5jZXN0b3JzLmFkZChwcm90byk7CiAgICBmb3IgKGNvbnN0IHVuc2V0QXR0ck5hbWUgb2YgdGhpc1tfZ2V0VW5zZXRBdHRyaWJ1dGVzXShwcm90b1tfc2V0QXR0cmlidXRlc10pKSB7CiAgICAgIHRoaXNbdW5zZXRBdHRyTmFtZV0gPSBwcm90b1t1bnNldEF0dHJOYW1lXTsKICAgICAgaWYgKHRoaXNbX3NldEF0dHJpYnV0ZXNdKSB7CiAgICAgICAgdGhpc1tfc2V0QXR0cmlidXRlc10uYWRkKHVuc2V0QXR0ck5hbWUpOwogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcykpIHsKICAgICAgaWYgKHRoaXNbX2F0dHJpYnV0ZU5hbWVzXS5oYXMobmFtZSkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB2YWx1ZSA9IHRoaXNbbmFtZV07CiAgICAgIGNvbnN0IHByb3RvVmFsdWUgPSBwcm90b1tuYW1lXTsKICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgWEZBT2JqZWN0QXJyYXkpIHsKICAgICAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHZhbHVlW19jaGlsZHJlbl0pIHsKICAgICAgICAgIGNoaWxkW19yZXNvbHZlUHJvdG90eXBlc0hlbHBlcl0oaWRzLCBhbmNlc3RvcnMpOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBpID0gdmFsdWVbX2NoaWxkcmVuXS5sZW5ndGgsIGlpID0gcHJvdG9WYWx1ZVtfY2hpbGRyZW5dLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgIGNvbnN0IGNoaWxkID0gcHJvdG9bX2NoaWxkcmVuXVtpXVskY2xvbmVdKCk7CiAgICAgICAgICBpZiAodmFsdWUucHVzaChjaGlsZCkpIHsKICAgICAgICAgICAgY2hpbGRbX3BhcmVudF0gPSB0aGlzOwogICAgICAgICAgICB0aGlzW19jaGlsZHJlbl0ucHVzaChjaGlsZCk7CiAgICAgICAgICAgIGNoaWxkW19yZXNvbHZlUHJvdG90eXBlc0hlbHBlcl0oaWRzLCBhbmNlc3RvcnMpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICh2YWx1ZSAhPT0gbnVsbCkgewogICAgICAgIHZhbHVlWyRyZXNvbHZlUHJvdG90eXBlc10oaWRzLCBhbmNlc3RvcnMpOwogICAgICAgIGlmIChwcm90b1ZhbHVlKSB7CiAgICAgICAgICB2YWx1ZVtfYXBwbHlQcm90b3R5cGVdKHByb3RvVmFsdWUsIGlkcywgYW5jZXN0b3JzKTsKICAgICAgICB9CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKHByb3RvVmFsdWUgIT09IG51bGwpIHsKICAgICAgICBjb25zdCBjaGlsZCA9IHByb3RvVmFsdWVbJGNsb25lXSgpOwogICAgICAgIGNoaWxkW19wYXJlbnRdID0gdGhpczsKICAgICAgICB0aGlzW25hbWVdID0gY2hpbGQ7CiAgICAgICAgdGhpc1tfY2hpbGRyZW5dLnB1c2goY2hpbGQpOwogICAgICAgIGNoaWxkW19yZXNvbHZlUHJvdG90eXBlc0hlbHBlcl0oaWRzLCBhbmNlc3RvcnMpOwogICAgICB9CiAgICB9CiAgfQogIHN0YXRpYyBbX2Nsb25lQXR0cmlidXRlXShvYmopIHsKICAgIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHsKICAgICAgcmV0dXJuIG9iai5tYXAoeCA9PiBYRkFPYmplY3RbX2Nsb25lQXR0cmlidXRlXSh4KSk7CiAgICB9CiAgICBpZiAodHlwZW9mIG9iaiA9PT0gIm9iamVjdCIgJiYgb2JqICE9PSBudWxsKSB7CiAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCBvYmopOwogICAgfQogICAgcmV0dXJuIG9iajsKICB9CiAgWyRjbG9uZV0oKSB7CiAgICBjb25zdCBjbG9uZSA9IE9iamVjdC5jcmVhdGUoT2JqZWN0LmdldFByb3RvdHlwZU9mKHRoaXMpKTsKICAgIGZvciAoY29uc3QgJHN5bWJvbCBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHRoaXMpKSB7CiAgICAgIHRyeSB7CiAgICAgICAgY2xvbmVbJHN5bWJvbF0gPSB0aGlzWyRzeW1ib2xdOwogICAgICB9IGNhdGNoIChfKSB7CiAgICAgICAgKDAsIF91dGlsLnNoYWRvdykoY2xvbmUsICRzeW1ib2wsIHRoaXNbJHN5bWJvbF0pOwogICAgICB9CiAgICB9CiAgICBjbG9uZVskdWlkXSA9IGAke2Nsb25lWyRub2RlTmFtZV19JHt1aWQrK31gOwogICAgY2xvbmVbX2NoaWxkcmVuXSA9IFtdOwogICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKSB7CiAgICAgIGlmICh0aGlzW19hdHRyaWJ1dGVOYW1lc10uaGFzKG5hbWUpKSB7CiAgICAgICAgY2xvbmVbbmFtZV0gPSBYRkFPYmplY3RbX2Nsb25lQXR0cmlidXRlXSh0aGlzW25hbWVdKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB2YWx1ZSA9IHRoaXNbbmFtZV07CiAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFhGQU9iamVjdEFycmF5KSB7CiAgICAgICAgY2xvbmVbbmFtZV0gPSBuZXcgWEZBT2JqZWN0QXJyYXkodmFsdWVbX21heF0pOwogICAgICB9IGVsc2UgewogICAgICAgIGNsb25lW25hbWVdID0gbnVsbDsKICAgICAgfQogICAgfQogICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzW19jaGlsZHJlbl0pIHsKICAgICAgY29uc3QgbmFtZSA9IGNoaWxkWyRub2RlTmFtZV07CiAgICAgIGNvbnN0IGNsb25lZENoaWxkID0gY2hpbGRbJGNsb25lXSgpOwogICAgICBjbG9uZVtfY2hpbGRyZW5dLnB1c2goY2xvbmVkQ2hpbGQpOwogICAgICBjbG9uZWRDaGlsZFtfcGFyZW50XSA9IGNsb25lOwogICAgICBpZiAoY2xvbmVbbmFtZV0gPT09IG51bGwpIHsKICAgICAgICBjbG9uZVtuYW1lXSA9IGNsb25lZENoaWxkOwogICAgICB9IGVsc2UgewogICAgICAgIGNsb25lW25hbWVdW19jaGlsZHJlbl0ucHVzaChjbG9uZWRDaGlsZCk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBjbG9uZTsKICB9CiAgWyRnZXRDaGlsZHJlbl0oKSB7CiAgICBsZXQgbmFtZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbnVsbDsKICAgIGlmICghbmFtZSkgewogICAgICByZXR1cm4gdGhpc1tfY2hpbGRyZW5dOwogICAgfQogICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXS5maWx0ZXIoYyA9PiBjWyRub2RlTmFtZV0gPT09IG5hbWUpOwogIH0KICBbJGdldENoaWxkcmVuQnlDbGFzc10obmFtZSkgewogICAgcmV0dXJuIHRoaXNbbmFtZV07CiAgfQogIFskZ2V0Q2hpbGRyZW5CeU5hbWVdKG5hbWUsIGFsbFRyYW5zcGFyZW50KSB7CiAgICBsZXQgZmlyc3QgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IHRydWU7CiAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzWyRnZXRDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCBhbGxUcmFuc3BhcmVudCwgZmlyc3QpKTsKICB9CiAgWyRnZXRDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCBhbGxUcmFuc3BhcmVudCkgewogICAgdmFyIF90aGlzID0gdGhpczsKICAgIGxldCBmaXJzdCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogdHJ1ZTsKICAgIHJldHVybiBmdW5jdGlvbiogKCkgewogICAgICBpZiAobmFtZSA9PT0gInBhcmVudCIpIHsKICAgICAgICB5aWVsZCBfdGhpc1tfcGFyZW50XTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiBfdGhpc1tfY2hpbGRyZW5dKSB7CiAgICAgICAgaWYgKGNoaWxkWyRub2RlTmFtZV0gPT09IG5hbWUpIHsKICAgICAgICAgIHlpZWxkIGNoaWxkOwogICAgICAgIH0KICAgICAgICBpZiAoY2hpbGQubmFtZSA9PT0gbmFtZSkgewogICAgICAgICAgeWllbGQgY2hpbGQ7CiAgICAgICAgfQogICAgICAgIGlmIChhbGxUcmFuc3BhcmVudCB8fCBjaGlsZFskaXNUcmFuc3BhcmVudF0oKSkgewogICAgICAgICAgeWllbGQqIGNoaWxkWyRnZXRDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCBhbGxUcmFuc3BhcmVudCwgZmFsc2UpOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoZmlyc3QgJiYgX3RoaXNbX2F0dHJpYnV0ZU5hbWVzXS5oYXMobmFtZSkpIHsKICAgICAgICB5aWVsZCBuZXcgWEZBQXR0cmlidXRlKF90aGlzLCBuYW1lLCBfdGhpc1tuYW1lXSk7CiAgICAgIH0KICAgIH0oKTsKICB9Cn0KZXhwb3J0cy5YRkFPYmplY3QgPSBYRkFPYmplY3Q7CmNsYXNzIFhGQU9iamVjdEFycmF5IHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIGxldCBtYXggPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IEluZmluaXR5OwogICAgdGhpc1tfbWF4XSA9IG1heDsKICAgIHRoaXNbX2NoaWxkcmVuXSA9IFtdOwogIH0KICBwdXNoKGNoaWxkKSB7CiAgICBjb25zdCBsZW4gPSB0aGlzW19jaGlsZHJlbl0ubGVuZ3RoOwogICAgaWYgKGxlbiA8PSB0aGlzW19tYXhdKSB7CiAgICAgIHRoaXNbX2NoaWxkcmVuXS5wdXNoKGNoaWxkKTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICAoMCwgX3V0aWwud2FybikoYFhGQSAtIG5vZGUgIiR7Y2hpbGRbJG5vZGVOYW1lXX0iIGFjY2VwdHMgbm8gbW9yZSB0aGFuICR7dGhpc1tfbWF4XX0gY2hpbGRyZW5gKTsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgaXNFbXB0eSgpIHsKICAgIHJldHVybiB0aGlzW19jaGlsZHJlbl0ubGVuZ3RoID09PSAwOwogIH0KICBkdW1wKCkgewogICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXS5sZW5ndGggPT09IDEgPyB0aGlzW19jaGlsZHJlbl1bMF1bJGR1bXBdKCkgOiB0aGlzW19jaGlsZHJlbl0ubWFwKHggPT4geFskZHVtcF0oKSk7CiAgfQogIFskY2xvbmVdKCkgewogICAgY29uc3QgY2xvbmUgPSBuZXcgWEZBT2JqZWN0QXJyYXkodGhpc1tfbWF4XSk7CiAgICBjbG9uZVtfY2hpbGRyZW5dID0gdGhpc1tfY2hpbGRyZW5dLm1hcChjID0+IGNbJGNsb25lXSgpKTsKICAgIHJldHVybiBjbG9uZTsKICB9CiAgZ2V0IGNoaWxkcmVuKCkgewogICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXTsKICB9CiAgY2xlYXIoKSB7CiAgICB0aGlzW19jaGlsZHJlbl0ubGVuZ3RoID0gMDsKICB9Cn0KZXhwb3J0cy5YRkFPYmplY3RBcnJheSA9IFhGQU9iamVjdEFycmF5OwpjbGFzcyBYRkFBdHRyaWJ1dGUgewogIGNvbnN0cnVjdG9yKG5vZGUsIG5hbWUsIHZhbHVlKSB7CiAgICB0aGlzW19wYXJlbnRdID0gbm9kZTsKICAgIHRoaXNbJG5vZGVOYW1lXSA9IG5hbWU7CiAgICB0aGlzWyRjb250ZW50XSA9IHZhbHVlOwogICAgdGhpc1skY29uc3VtZWRdID0gZmFsc2U7CiAgICB0aGlzWyR1aWRdID0gYGF0dHJpYnV0ZSR7dWlkKyt9YDsKICB9CiAgWyRnZXRQYXJlbnRdKCkgewogICAgcmV0dXJuIHRoaXNbX3BhcmVudF07CiAgfQogIFskaXNEYXRhVmFsdWVdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIFskZ2V0RGF0YVZhbHVlXSgpIHsKICAgIHJldHVybiB0aGlzWyRjb250ZW50XS50cmltKCk7CiAgfQogIFskc2V0VmFsdWVdKHZhbHVlKSB7CiAgICB2YWx1ZSA9IHZhbHVlLnZhbHVlIHx8ICIiOwogICAgdGhpc1skY29udGVudF0gPSB2YWx1ZS50b1N0cmluZygpOwogIH0KICBbJHRleHRdKCkgewogICAgcmV0dXJuIHRoaXNbJGNvbnRlbnRdOwogIH0KICBbJGlzRGVzY2VuZGVudF0ocGFyZW50KSB7CiAgICByZXR1cm4gdGhpc1tfcGFyZW50XSA9PT0gcGFyZW50IHx8IHRoaXNbX3BhcmVudF1bJGlzRGVzY2VuZGVudF0ocGFyZW50KTsKICB9Cn0KZXhwb3J0cy5YRkFBdHRyaWJ1dGUgPSBYRkFBdHRyaWJ1dGU7CmNsYXNzIFhtbE9iamVjdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IobnNJZCwgbmFtZSkgewogICAgbGV0IGF0dHJpYnV0ZXMgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IHt9OwogICAgc3VwZXIobnNJZCwgbmFtZSk7CiAgICB0aGlzWyRjb250ZW50XSA9ICIiOwogICAgdGhpc1tfZGF0YVZhbHVlXSA9IG51bGw7CiAgICBpZiAobmFtZSAhPT0gIiN0ZXh0IikgewogICAgICBjb25zdCBtYXAgPSBuZXcgTWFwKCk7CiAgICAgIHRoaXNbX2F0dHJpYnV0ZXNdID0gbWFwOwogICAgICBmb3IgKGNvbnN0IFthdHRyTmFtZSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGF0dHJpYnV0ZXMpKSB7CiAgICAgICAgbWFwLnNldChhdHRyTmFtZSwgbmV3IFhGQUF0dHJpYnV0ZSh0aGlzLCBhdHRyTmFtZSwgdmFsdWUpKTsKICAgICAgfQogICAgICBpZiAoYXR0cmlidXRlcy5oYXNPd25Qcm9wZXJ0eSgkbnNBdHRyaWJ1dGVzKSkgewogICAgICAgIGNvbnN0IGRhdGFOb2RlID0gYXR0cmlidXRlc1skbnNBdHRyaWJ1dGVzXS54ZmEuZGF0YU5vZGU7CiAgICAgICAgaWYgKGRhdGFOb2RlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGlmIChkYXRhTm9kZSA9PT0gImRhdGFHcm91cCIpIHsKICAgICAgICAgICAgdGhpc1tfZGF0YVZhbHVlXSA9IGZhbHNlOwogICAgICAgICAgfSBlbHNlIGlmIChkYXRhTm9kZSA9PT0gImRhdGFWYWx1ZSIpIHsKICAgICAgICAgICAgdGhpc1tfZGF0YVZhbHVlXSA9IHRydWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICB0aGlzWyRjb25zdW1lZF0gPSBmYWxzZTsKICB9CiAgWyR0b1N0cmluZ10oYnVmKSB7CiAgICBjb25zdCB0YWdOYW1lID0gdGhpc1skbm9kZU5hbWVdOwogICAgaWYgKHRhZ05hbWUgPT09ICIjdGV4dCIpIHsKICAgICAgYnVmLnB1c2goKDAsIF9jb3JlX3V0aWxzLmVuY29kZVRvWG1sU3RyaW5nKSh0aGlzWyRjb250ZW50XSkpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCB1dGY4VGFnTmFtZSA9ICgwLCBfdXRpbC51dGY4U3RyaW5nVG9TdHJpbmcpKHRhZ05hbWUpOwogICAgY29uc3QgcHJlZml4ID0gdGhpc1skbmFtZXNwYWNlSWRdID09PSBOU19EQVRBU0VUUyA/ICJ4ZmE6IiA6ICIiOwogICAgYnVmLnB1c2goYDwke3ByZWZpeH0ke3V0ZjhUYWdOYW1lfWApOwogICAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIHRoaXNbX2F0dHJpYnV0ZXNdLmVudHJpZXMoKSkgewogICAgICBjb25zdCB1dGY4TmFtZSA9ICgwLCBfdXRpbC51dGY4U3RyaW5nVG9TdHJpbmcpKG5hbWUpOwogICAgICBidWYucHVzaChgICR7dXRmOE5hbWV9PSIkeygwLCBfY29yZV91dGlscy5lbmNvZGVUb1htbFN0cmluZykodmFsdWVbJGNvbnRlbnRdKX0iYCk7CiAgICB9CiAgICBpZiAodGhpc1tfZGF0YVZhbHVlXSAhPT0gbnVsbCkgewogICAgICBpZiAodGhpc1tfZGF0YVZhbHVlXSkgewogICAgICAgIGJ1Zi5wdXNoKGAgeGZhOmRhdGFOb2RlPSJkYXRhVmFsdWUiYCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnVmLnB1c2goYCB4ZmE6ZGF0YU5vZGU9ImRhdGFHcm91cCJgKTsKICAgICAgfQogICAgfQogICAgaWYgKCF0aGlzWyRjb250ZW50XSAmJiB0aGlzW19jaGlsZHJlbl0ubGVuZ3RoID09PSAwKSB7CiAgICAgIGJ1Zi5wdXNoKCIvPiIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBidWYucHVzaCgiPiIpOwogICAgaWYgKHRoaXNbJGNvbnRlbnRdKSB7CiAgICAgIGlmICh0eXBlb2YgdGhpc1skY29udGVudF0gPT09ICJzdHJpbmciKSB7CiAgICAgICAgYnVmLnB1c2goKDAsIF9jb3JlX3V0aWxzLmVuY29kZVRvWG1sU3RyaW5nKSh0aGlzWyRjb250ZW50XSkpOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXNbJGNvbnRlbnRdWyR0b1N0cmluZ10oYnVmKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzW19jaGlsZHJlbl0pIHsKICAgICAgICBjaGlsZFskdG9TdHJpbmddKGJ1Zik7CiAgICAgIH0KICAgIH0KICAgIGJ1Zi5wdXNoKGA8LyR7cHJlZml4fSR7dXRmOFRhZ05hbWV9PmApOwogIH0KICBbJG9uQ2hpbGRdKGNoaWxkKSB7CiAgICBpZiAodGhpc1skY29udGVudF0pIHsKICAgICAgY29uc3Qgbm9kZSA9IG5ldyBYbWxPYmplY3QodGhpc1skbmFtZXNwYWNlSWRdLCAiI3RleHQiKTsKICAgICAgdGhpc1skYXBwZW5kQ2hpbGRdKG5vZGUpOwogICAgICBub2RlWyRjb250ZW50XSA9IHRoaXNbJGNvbnRlbnRdOwogICAgICB0aGlzWyRjb250ZW50XSA9ICIiOwogICAgfQogICAgdGhpc1skYXBwZW5kQ2hpbGRdKGNoaWxkKTsKICAgIHJldHVybiB0cnVlOwogIH0KICBbJG9uVGV4dF0oc3RyKSB7CiAgICB0aGlzWyRjb250ZW50XSArPSBzdHI7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgaWYgKHRoaXNbJGNvbnRlbnRdICYmIHRoaXNbX2NoaWxkcmVuXS5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IG5vZGUgPSBuZXcgWG1sT2JqZWN0KHRoaXNbJG5hbWVzcGFjZUlkXSwgIiN0ZXh0Iik7CiAgICAgIHRoaXNbJGFwcGVuZENoaWxkXShub2RlKTsKICAgICAgbm9kZVskY29udGVudF0gPSB0aGlzWyRjb250ZW50XTsKICAgICAgZGVsZXRlIHRoaXNbJGNvbnRlbnRdOwogICAgfQogIH0KICBbJHRvSFRNTF0oKSB7CiAgICBpZiAodGhpc1skbm9kZU5hbWVdID09PSAiI3RleHQiKSB7CiAgICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgICBuYW1lOiAiI3RleHQiLAogICAgICAgIHZhbHVlOiB0aGlzWyRjb250ZW50XQogICAgICB9KTsKICAgIH0KICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5FTVBUWTsKICB9CiAgWyRnZXRDaGlsZHJlbl0oKSB7CiAgICBsZXQgbmFtZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbnVsbDsKICAgIGlmICghbmFtZSkgewogICAgICByZXR1cm4gdGhpc1tfY2hpbGRyZW5dOwogICAgfQogICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXS5maWx0ZXIoYyA9PiBjWyRub2RlTmFtZV0gPT09IG5hbWUpOwogIH0KICBbJGdldEF0dHJpYnV0ZXNdKCkgewogICAgcmV0dXJuIHRoaXNbX2F0dHJpYnV0ZXNdOwogIH0KICBbJGdldENoaWxkcmVuQnlDbGFzc10obmFtZSkgewogICAgY29uc3QgdmFsdWUgPSB0aGlzW19hdHRyaWJ1dGVzXS5nZXQobmFtZSk7CiAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gdmFsdWU7CiAgICB9CiAgICByZXR1cm4gdGhpc1skZ2V0Q2hpbGRyZW5dKG5hbWUpOwogIH0KICAqWyRnZXRDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCBhbGxUcmFuc3BhcmVudCkgewogICAgY29uc3QgdmFsdWUgPSB0aGlzW19hdHRyaWJ1dGVzXS5nZXQobmFtZSk7CiAgICBpZiAodmFsdWUpIHsKICAgICAgeWllbGQgdmFsdWU7CiAgICB9CiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHRoaXNbX2NoaWxkcmVuXSkgewogICAgICBpZiAoY2hpbGRbJG5vZGVOYW1lXSA9PT0gbmFtZSkgewogICAgICAgIHlpZWxkIGNoaWxkOwogICAgICB9CiAgICAgIGlmIChhbGxUcmFuc3BhcmVudCkgewogICAgICAgIHlpZWxkKiBjaGlsZFskZ2V0Q2hpbGRyZW5CeU5hbWVJdF0obmFtZSwgYWxsVHJhbnNwYXJlbnQpOwogICAgICB9CiAgICB9CiAgfQogICpbJGdldEF0dHJpYnV0ZUl0XShuYW1lLCBza2lwQ29uc3VtZWQpIHsKICAgIGNvbnN0IHZhbHVlID0gdGhpc1tfYXR0cmlidXRlc10uZ2V0KG5hbWUpOwogICAgaWYgKHZhbHVlICYmICghc2tpcENvbnN1bWVkIHx8ICF2YWx1ZVskY29uc3VtZWRdKSkgewogICAgICB5aWVsZCB2YWx1ZTsKICAgIH0KICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpc1tfY2hpbGRyZW5dKSB7CiAgICAgIHlpZWxkKiBjaGlsZFskZ2V0QXR0cmlidXRlSXRdKG5hbWUsIHNraXBDb25zdW1lZCk7CiAgICB9CiAgfQogICpbJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCBhbGxUcmFuc3BhcmVudCwgc2tpcENvbnN1bWVkKSB7CiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHRoaXNbX2NoaWxkcmVuXSkgewogICAgICBpZiAoY2hpbGRbJG5vZGVOYW1lXSA9PT0gbmFtZSAmJiAoIXNraXBDb25zdW1lZCB8fCAhY2hpbGRbJGNvbnN1bWVkXSkpIHsKICAgICAgICB5aWVsZCBjaGlsZDsKICAgICAgfQogICAgICBpZiAoYWxsVHJhbnNwYXJlbnQpIHsKICAgICAgICB5aWVsZCogY2hpbGRbJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCBhbGxUcmFuc3BhcmVudCwgc2tpcENvbnN1bWVkKTsKICAgICAgfQogICAgfQogIH0KICBbJGlzRGF0YVZhbHVlXSgpIHsKICAgIGlmICh0aGlzW19kYXRhVmFsdWVdID09PSBudWxsKSB7CiAgICAgIHJldHVybiB0aGlzW19jaGlsZHJlbl0ubGVuZ3RoID09PSAwIHx8IHRoaXNbX2NoaWxkcmVuXVswXVskbmFtZXNwYWNlSWRdID09PSBfbmFtZXNwYWNlcy5OYW1lc3BhY2VJZHMueGh0bWwuaWQ7CiAgICB9CiAgICByZXR1cm4gdGhpc1tfZGF0YVZhbHVlXTsKICB9CiAgWyRnZXREYXRhVmFsdWVdKCkgewogICAgaWYgKHRoaXNbX2RhdGFWYWx1ZV0gPT09IG51bGwpIHsKICAgICAgaWYgKHRoaXNbX2NoaWxkcmVuXS5sZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gdGhpc1skY29udGVudF0udHJpbSgpOwogICAgICB9CiAgICAgIGlmICh0aGlzW19jaGlsZHJlbl1bMF1bJG5hbWVzcGFjZUlkXSA9PT0gX25hbWVzcGFjZXMuTmFtZXNwYWNlSWRzLnhodG1sLmlkKSB7CiAgICAgICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXVswXVskdGV4dF0oKS50cmltKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICByZXR1cm4gdGhpc1skY29udGVudF0udHJpbSgpOwogIH0KICBbJHNldFZhbHVlXSh2YWx1ZSkgewogICAgdmFsdWUgPSB2YWx1ZS52YWx1ZSB8fCAiIjsKICAgIHRoaXNbJGNvbnRlbnRdID0gdmFsdWUudG9TdHJpbmcoKTsKICB9CiAgWyRkdW1wXSgpIHsKICAgIGxldCBoYXNOUyA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogZmFsc2U7CiAgICBjb25zdCBkdW1wZWQgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgaWYgKGhhc05TKSB7CiAgICAgIGR1bXBlZC4kbnMgPSB0aGlzWyRuYW1lc3BhY2VJZF07CiAgICB9CiAgICBpZiAodGhpc1skY29udGVudF0pIHsKICAgICAgZHVtcGVkLiRjb250ZW50ID0gdGhpc1skY29udGVudF07CiAgICB9CiAgICBkdW1wZWQuJG5hbWUgPSB0aGlzWyRub2RlTmFtZV07CiAgICBkdW1wZWQuY2hpbGRyZW4gPSBbXTsKICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpc1tfY2hpbGRyZW5dKSB7CiAgICAgIGR1bXBlZC5jaGlsZHJlbi5wdXNoKGNoaWxkWyRkdW1wXShoYXNOUykpOwogICAgfQogICAgZHVtcGVkLmF0dHJpYnV0ZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgZm9yIChjb25zdCBbbmFtZSwgdmFsdWVdIG9mIHRoaXNbX2F0dHJpYnV0ZXNdKSB7CiAgICAgIGR1bXBlZC5hdHRyaWJ1dGVzW25hbWVdID0gdmFsdWVbJGNvbnRlbnRdOwogICAgfQogICAgcmV0dXJuIGR1bXBlZDsKICB9Cn0KZXhwb3J0cy5YbWxPYmplY3QgPSBYbWxPYmplY3Q7CmNsYXNzIENvbnRlbnRPYmplY3QgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKG5zSWQsIG5hbWUpIHsKICAgIHN1cGVyKG5zSWQsIG5hbWUpOwogICAgdGhpc1skY29udGVudF0gPSAiIjsKICB9CiAgWyRvblRleHRdKHRleHQpIHsKICAgIHRoaXNbJGNvbnRlbnRdICs9IHRleHQ7CiAgfQogIFskZmluYWxpemVdKCkge30KfQpleHBvcnRzLkNvbnRlbnRPYmplY3QgPSBDb250ZW50T2JqZWN0OwpjbGFzcyBPcHRpb25PYmplY3QgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3Rvcihuc0lkLCBuYW1lLCBvcHRpb25zKSB7CiAgICBzdXBlcihuc0lkLCBuYW1lKTsKICAgIHRoaXNbX29wdGlvbnNdID0gb3B0aW9uczsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzWyRjb250ZW50XSA9ICgwLCBfdXRpbHMuZ2V0S2V5d29yZCkoewogICAgICBkYXRhOiB0aGlzWyRjb250ZW50XSwKICAgICAgZGVmYXVsdFZhbHVlOiB0aGlzW19vcHRpb25zXVswXSwKICAgICAgdmFsaWRhdGU6IGsgPT4gdGhpc1tfb3B0aW9uc10uaW5jbHVkZXMoaykKICAgIH0pOwogIH0KICBbJGNsZWFuXShidWlsZGVyKSB7CiAgICBzdXBlclskY2xlYW5dKGJ1aWxkZXIpOwogICAgZGVsZXRlIHRoaXNbX29wdGlvbnNdOwogIH0KfQpleHBvcnRzLk9wdGlvbk9iamVjdCA9IE9wdGlvbk9iamVjdDsKY2xhc3MgU3RyaW5nT2JqZWN0IGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzWyRjb250ZW50XSA9IHRoaXNbJGNvbnRlbnRdLnRyaW0oKTsKICB9Cn0KZXhwb3J0cy5TdHJpbmdPYmplY3QgPSBTdHJpbmdPYmplY3Q7CmNsYXNzIEludGVnZXJPYmplY3QgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3Rvcihuc0lkLCBuYW1lLCBkZWZhdWx0VmFsdWUsIHZhbGlkYXRvcikgewogICAgc3VwZXIobnNJZCwgbmFtZSk7CiAgICB0aGlzW19kZWZhdWx0VmFsdWVdID0gZGVmYXVsdFZhbHVlOwogICAgdGhpc1tfdmFsaWRhdG9yXSA9IHZhbGlkYXRvcjsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzWyRjb250ZW50XSA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiB0aGlzWyRjb250ZW50XSwKICAgICAgZGVmYXVsdFZhbHVlOiB0aGlzW19kZWZhdWx0VmFsdWVdLAogICAgICB2YWxpZGF0ZTogdGhpc1tfdmFsaWRhdG9yXQogICAgfSk7CiAgfQogIFskY2xlYW5dKGJ1aWxkZXIpIHsKICAgIHN1cGVyWyRjbGVhbl0oYnVpbGRlcik7CiAgICBkZWxldGUgdGhpc1tfZGVmYXVsdFZhbHVlXTsKICAgIGRlbGV0ZSB0aGlzW192YWxpZGF0b3JdOwogIH0KfQpleHBvcnRzLkludGVnZXJPYmplY3QgPSBJbnRlZ2VyT2JqZWN0OwpjbGFzcyBPcHRpb24wMSBleHRlbmRzIEludGVnZXJPYmplY3QgewogIGNvbnN0cnVjdG9yKG5zSWQsIG5hbWUpIHsKICAgIHN1cGVyKG5zSWQsIG5hbWUsIDAsIG4gPT4gbiA9PT0gMSk7CiAgfQp9CmV4cG9ydHMuT3B0aW9uMDEgPSBPcHRpb24wMTsKY2xhc3MgT3B0aW9uMTAgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3Rvcihuc0lkLCBuYW1lKSB7CiAgICBzdXBlcihuc0lkLCBuYW1lLCAxLCBuID0+IG4gPT09IDApOwogIH0KfQpleHBvcnRzLk9wdGlvbjEwID0gT3B0aW9uMTA7CgovKioqLyB9KSwKLyogMjEzICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5IVE1MUmVzdWx0ID0gdm9pZCAwOwpleHBvcnRzLmdldEJCb3ggPSBnZXRCQm94OwpleHBvcnRzLmdldENvbG9yID0gZ2V0Q29sb3I7CmV4cG9ydHMuZ2V0RmxvYXQgPSBnZXRGbG9hdDsKZXhwb3J0cy5nZXRJbnRlZ2VyID0gZ2V0SW50ZWdlcjsKZXhwb3J0cy5nZXRLZXl3b3JkID0gZ2V0S2V5d29yZDsKZXhwb3J0cy5nZXRNZWFzdXJlbWVudCA9IGdldE1lYXN1cmVtZW50OwpleHBvcnRzLmdldFJhdGlvID0gZ2V0UmF0aW87CmV4cG9ydHMuZ2V0UmVsZXZhbnQgPSBnZXRSZWxldmFudDsKZXhwb3J0cy5nZXRTdHJpbmdPcHRpb24gPSBnZXRTdHJpbmdPcHRpb247CmV4cG9ydHMuc3RyaXBRdW90ZXMgPSBzdHJpcFF1b3RlczsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKY29uc3QgZGltQ29udmVydGVycyA9IHsKICBwdDogeCA9PiB4LAogIGNtOiB4ID0+IHggLyAyLjU0ICogNzIsCiAgbW06IHggPT4geCAvICgxMCAqIDIuNTQpICogNzIsCiAgaW46IHggPT4geCAqIDcyLAogIHB4OiB4ID0+IHgKfTsKY29uc3QgbWVhc3VyZW1lbnRQYXR0ZXJuID0gLyhbKy1dP1xkK1wuP1xkKikoLiopLzsKZnVuY3Rpb24gc3RyaXBRdW90ZXMoc3RyKSB7CiAgaWYgKHN0ci5zdGFydHNXaXRoKCInIikgfHwgc3RyLnN0YXJ0c1dpdGgoJyInKSkgewogICAgcmV0dXJuIHN0ci5zbGljZSgxLCAtMSk7CiAgfQogIHJldHVybiBzdHI7Cn0KZnVuY3Rpb24gZ2V0SW50ZWdlcihfcmVmKSB7CiAgbGV0IHsKICAgIGRhdGEsCiAgICBkZWZhdWx0VmFsdWUsCiAgICB2YWxpZGF0ZQogIH0gPSBfcmVmOwogIGlmICghZGF0YSkgewogICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKICB9CiAgZGF0YSA9IGRhdGEudHJpbSgpOwogIGNvbnN0IG4gPSBwYXJzZUludChkYXRhLCAxMCk7CiAgaWYgKCFpc05hTihuKSAmJiB2YWxpZGF0ZShuKSkgewogICAgcmV0dXJuIG47CiAgfQogIHJldHVybiBkZWZhdWx0VmFsdWU7Cn0KZnVuY3Rpb24gZ2V0RmxvYXQoX3JlZjIpIHsKICBsZXQgewogICAgZGF0YSwKICAgIGRlZmF1bHRWYWx1ZSwKICAgIHZhbGlkYXRlCiAgfSA9IF9yZWYyOwogIGlmICghZGF0YSkgewogICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKICB9CiAgZGF0YSA9IGRhdGEudHJpbSgpOwogIGNvbnN0IG4gPSBwYXJzZUZsb2F0KGRhdGEpOwogIGlmICghaXNOYU4obikgJiYgdmFsaWRhdGUobikpIHsKICAgIHJldHVybiBuOwogIH0KICByZXR1cm4gZGVmYXVsdFZhbHVlOwp9CmZ1bmN0aW9uIGdldEtleXdvcmQoX3JlZjMpIHsKICBsZXQgewogICAgZGF0YSwKICAgIGRlZmF1bHRWYWx1ZSwKICAgIHZhbGlkYXRlCiAgfSA9IF9yZWYzOwogIGlmICghZGF0YSkgewogICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKICB9CiAgZGF0YSA9IGRhdGEudHJpbSgpOwogIGlmICh2YWxpZGF0ZShkYXRhKSkgewogICAgcmV0dXJuIGRhdGE7CiAgfQogIHJldHVybiBkZWZhdWx0VmFsdWU7Cn0KZnVuY3Rpb24gZ2V0U3RyaW5nT3B0aW9uKGRhdGEsIG9wdGlvbnMpIHsKICByZXR1cm4gZ2V0S2V5d29yZCh7CiAgICBkYXRhLAogICAgZGVmYXVsdFZhbHVlOiBvcHRpb25zWzBdLAogICAgdmFsaWRhdGU6IGsgPT4gb3B0aW9ucy5pbmNsdWRlcyhrKQogIH0pOwp9CmZ1bmN0aW9uIGdldE1lYXN1cmVtZW50KHN0cikgewogIGxldCBkZWYgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6ICIwIjsKICBkZWYgPSBkZWYgfHwgIjAiOwogIGlmICghc3RyKSB7CiAgICByZXR1cm4gZ2V0TWVhc3VyZW1lbnQoZGVmKTsKICB9CiAgY29uc3QgbWF0Y2ggPSBzdHIudHJpbSgpLm1hdGNoKG1lYXN1cmVtZW50UGF0dGVybik7CiAgaWYgKCFtYXRjaCkgewogICAgcmV0dXJuIGdldE1lYXN1cmVtZW50KGRlZik7CiAgfQogIGNvbnN0IFssIHZhbHVlU3RyLCB1bml0XSA9IG1hdGNoOwogIGNvbnN0IHZhbHVlID0gcGFyc2VGbG9hdCh2YWx1ZVN0cik7CiAgaWYgKGlzTmFOKHZhbHVlKSkgewogICAgcmV0dXJuIGdldE1lYXN1cmVtZW50KGRlZik7CiAgfQogIGlmICh2YWx1ZSA9PT0gMCkgewogICAgcmV0dXJuIDA7CiAgfQogIGNvbnN0IGNvbnYgPSBkaW1Db252ZXJ0ZXJzW3VuaXRdOwogIGlmIChjb252KSB7CiAgICByZXR1cm4gY29udih2YWx1ZSk7CiAgfQogIHJldHVybiB2YWx1ZTsKfQpmdW5jdGlvbiBnZXRSYXRpbyhkYXRhKSB7CiAgaWYgKCFkYXRhKSB7CiAgICByZXR1cm4gewogICAgICBudW06IDEsCiAgICAgIGRlbjogMQogICAgfTsKICB9CiAgY29uc3QgcmF0aW8gPSBkYXRhLnRyaW0oKS5zcGxpdCgvXHMqOlxzKi8pLm1hcCh4ID0+IHBhcnNlRmxvYXQoeCkpLmZpbHRlcih4ID0+ICFpc05hTih4KSk7CiAgaWYgKHJhdGlvLmxlbmd0aCA9PT0gMSkgewogICAgcmF0aW8ucHVzaCgxKTsKICB9CiAgaWYgKHJhdGlvLmxlbmd0aCA9PT0gMCkgewogICAgcmV0dXJuIHsKICAgICAgbnVtOiAxLAogICAgICBkZW46IDEKICAgIH07CiAgfQogIGNvbnN0IFtudW0sIGRlbl0gPSByYXRpbzsKICByZXR1cm4gewogICAgbnVtLAogICAgZGVuCiAgfTsKfQpmdW5jdGlvbiBnZXRSZWxldmFudChkYXRhKSB7CiAgaWYgKCFkYXRhKSB7CiAgICByZXR1cm4gW107CiAgfQogIHJldHVybiBkYXRhLnRyaW0oKS5zcGxpdCgvXHMrLykubWFwKGUgPT4gewogICAgcmV0dXJuIHsKICAgICAgZXhjbHVkZWQ6IGVbMF0gPT09ICItIiwKICAgICAgdmlld25hbWU6IGUuc3Vic3RyaW5nKDEpCiAgICB9OwogIH0pOwp9CmZ1bmN0aW9uIGdldENvbG9yKGRhdGEpIHsKICBsZXQgZGVmID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBbMCwgMCwgMF07CiAgbGV0IFtyLCBnLCBiXSA9IGRlZjsKICBpZiAoIWRhdGEpIHsKICAgIHJldHVybiB7CiAgICAgIHIsCiAgICAgIGcsCiAgICAgIGIKICAgIH07CiAgfQogIGNvbnN0IGNvbG9yID0gZGF0YS50cmltKCkuc3BsaXQoL1xzKixccyovKS5tYXAoYyA9PiBNYXRoLm1pbihNYXRoLm1heCgwLCBwYXJzZUludChjLnRyaW0oKSwgMTApKSwgMjU1KSkubWFwKGMgPT4gaXNOYU4oYykgPyAwIDogYyk7CiAgaWYgKGNvbG9yLmxlbmd0aCA8IDMpIHsKICAgIHJldHVybiB7CiAgICAgIHIsCiAgICAgIGcsCiAgICAgIGIKICAgIH07CiAgfQogIFtyLCBnLCBiXSA9IGNvbG9yOwogIHJldHVybiB7CiAgICByLAogICAgZywKICAgIGIKICB9Owp9CmZ1bmN0aW9uIGdldEJCb3goZGF0YSkgewogIGNvbnN0IGRlZiA9IC0xOwogIGlmICghZGF0YSkgewogICAgcmV0dXJuIHsKICAgICAgeDogZGVmLAogICAgICB5OiBkZWYsCiAgICAgIHdpZHRoOiBkZWYsCiAgICAgIGhlaWdodDogZGVmCiAgICB9OwogIH0KICBjb25zdCBiYm94ID0gZGF0YS50cmltKCkuc3BsaXQoL1xzKixccyovKS5tYXAobSA9PiBnZXRNZWFzdXJlbWVudChtLCAiLTEiKSk7CiAgaWYgKGJib3gubGVuZ3RoIDwgNCB8fCBiYm94WzJdIDwgMCB8fCBiYm94WzNdIDwgMCkgewogICAgcmV0dXJuIHsKICAgICAgeDogZGVmLAogICAgICB5OiBkZWYsCiAgICAgIHdpZHRoOiBkZWYsCiAgICAgIGhlaWdodDogZGVmCiAgICB9OwogIH0KICBjb25zdCBbeCwgeSwgd2lkdGgsIGhlaWdodF0gPSBiYm94OwogIHJldHVybiB7CiAgICB4LAogICAgeSwKICAgIHdpZHRoLAogICAgaGVpZ2h0CiAgfTsKfQpjbGFzcyBIVE1MUmVzdWx0IHsKICBzdGF0aWMgZ2V0IEZBSUxVUkUoKSB7CiAgICByZXR1cm4gKDAsIF91dGlsLnNoYWRvdykodGhpcywgIkZBSUxVUkUiLCBuZXcgSFRNTFJlc3VsdChmYWxzZSwgbnVsbCwgbnVsbCwgbnVsbCkpOwogIH0KICBzdGF0aWMgZ2V0IEVNUFRZKCkgewogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJFTVBUWSIsIG5ldyBIVE1MUmVzdWx0KHRydWUsIG51bGwsIG51bGwsIG51bGwpKTsKICB9CiAgY29uc3RydWN0b3Ioc3VjY2VzcywgaHRtbCwgYmJveCwgYnJlYWtOb2RlKSB7CiAgICB0aGlzLnN1Y2Nlc3MgPSBzdWNjZXNzOwogICAgdGhpcy5odG1sID0gaHRtbDsKICAgIHRoaXMuYmJveCA9IGJib3g7CiAgICB0aGlzLmJyZWFrTm9kZSA9IGJyZWFrTm9kZTsKICB9CiAgaXNCcmVhaygpIHsKICAgIHJldHVybiAhIXRoaXMuYnJlYWtOb2RlOwogIH0KICBzdGF0aWMgYnJlYWtOb2RlKG5vZGUpIHsKICAgIHJldHVybiBuZXcgSFRNTFJlc3VsdChmYWxzZSwgbnVsbCwgbnVsbCwgbm9kZSk7CiAgfQogIHN0YXRpYyBzdWNjZXNzKGh0bWwpIHsKICAgIGxldCBiYm94ID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBudWxsOwogICAgcmV0dXJuIG5ldyBIVE1MUmVzdWx0KHRydWUsIGh0bWwsIGJib3gsIG51bGwpOwogIH0KfQpleHBvcnRzLkhUTUxSZXN1bHQgPSBIVE1MUmVzdWx0OwoKLyoqKi8gfSksCi8qIDIxNCAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuTmFtZXNwYWNlSWRzID0gZXhwb3J0cy4kYnVpbGRYRkFPYmplY3QgPSB2b2lkIDA7CmNvbnN0ICRidWlsZFhGQU9iamVjdCA9IFN5bWJvbCgpOwpleHBvcnRzLiRidWlsZFhGQU9iamVjdCA9ICRidWlsZFhGQU9iamVjdDsKY29uc3QgTmFtZXNwYWNlSWRzID0gewogIGNvbmZpZzogewogICAgaWQ6IDAsCiAgICBjaGVjazogbnMgPT4gbnMuc3RhcnRzV2l0aCgiaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94Y2kvIikKICB9LAogIGNvbm5lY3Rpb25TZXQ6IHsKICAgIGlkOiAxLAogICAgY2hlY2s6IG5zID0+IG5zLnN0YXJ0c1dpdGgoImh0dHA6Ly93d3cueGZhLm9yZy9zY2hlbWEveGZhLWNvbm5lY3Rpb24tc2V0LyIpCiAgfSwKICBkYXRhc2V0czogewogICAgaWQ6IDIsCiAgICBjaGVjazogbnMgPT4gbnMuc3RhcnRzV2l0aCgiaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtZGF0YS8iKQogIH0sCiAgZm9ybTogewogICAgaWQ6IDMsCiAgICBjaGVjazogbnMgPT4gbnMuc3RhcnRzV2l0aCgiaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtZm9ybS8iKQogIH0sCiAgbG9jYWxlU2V0OiB7CiAgICBpZDogNCwKICAgIGNoZWNrOiBucyA9PiBucy5zdGFydHNXaXRoKCJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS1sb2NhbGUtc2V0LyIpCiAgfSwKICBwZGY6IHsKICAgIGlkOiA1LAogICAgY2hlY2s6IG5zID0+IG5zID09PSAiaHR0cDovL25zLmFkb2JlLmNvbS94ZHAvcGRmLyIKICB9LAogIHNpZ25hdHVyZTogewogICAgaWQ6IDYsCiAgICBjaGVjazogbnMgPT4gbnMgPT09ICJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIgogIH0sCiAgc291cmNlU2V0OiB7CiAgICBpZDogNywKICAgIGNoZWNrOiBucyA9PiBucy5zdGFydHNXaXRoKCJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS1zb3VyY2Utc2V0LyIpCiAgfSwKICBzdHlsZXNoZWV0OiB7CiAgICBpZDogOCwKICAgIGNoZWNrOiBucyA9PiBucyA9PT0gImh0dHA6Ly93d3cudzMub3JnLzE5OTkvWFNML1RyYW5zZm9ybSIKICB9LAogIHRlbXBsYXRlOiB7CiAgICBpZDogOSwKICAgIGNoZWNrOiBucyA9PiBucy5zdGFydHNXaXRoKCJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS10ZW1wbGF0ZS8iKQogIH0sCiAgeGRjOiB7CiAgICBpZDogMTAsCiAgICBjaGVjazogbnMgPT4gbnMuc3RhcnRzV2l0aCgiaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZGMvIikKICB9LAogIHhkcDogewogICAgaWQ6IDExLAogICAgY2hlY2s6IG5zID0+IG5zID09PSAiaHR0cDovL25zLmFkb2JlLmNvbS94ZHAvIgogIH0sCiAgeGZkZjogewogICAgaWQ6IDEyLAogICAgY2hlY2s6IG5zID0+IG5zID09PSAiaHR0cDovL25zLmFkb2JlLmNvbS94ZmRmLyIKICB9LAogIHhodG1sOiB7CiAgICBpZDogMTMsCiAgICBjaGVjazogbnMgPT4gbnMgPT09ICJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIgogIH0sCiAgeG1wbWV0YTogewogICAgaWQ6IDE0LAogICAgY2hlY2s6IG5zID0+IG5zID09PSAiaHR0cDovL25zLmFkb2JlLmNvbS94bXBtZXRhLyIKICB9Cn07CmV4cG9ydHMuTmFtZXNwYWNlSWRzID0gTmFtZXNwYWNlSWRzOwoKLyoqKi8gfSksCi8qIDIxNSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuY3JlYXRlRGF0YU5vZGUgPSBjcmVhdGVEYXRhTm9kZTsKZXhwb3J0cy5zZWFyY2hOb2RlID0gc2VhcmNoTm9kZTsKdmFyIF94ZmFfb2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTIpOwp2YXIgX25hbWVzcGFjZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxNCk7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CmNvbnN0IG5hbWVQYXR0ZXJuID0gL15bXi5bXSsvOwpjb25zdCBpbmRleFBhdHRlcm4gPSAvXlteXF1dKy87CmNvbnN0IG9wZXJhdG9ycyA9IHsKICBkb3Q6IDAsCiAgZG90RG90OiAxLAogIGRvdEhhc2g6IDIsCiAgZG90QnJhY2tldDogMywKICBkb3RQYXJlbjogNAp9Owpjb25zdCBzaG9ydGN1dHMgPSBuZXcgTWFwKFtbIiRkYXRhIiwgKHJvb3QsIGN1cnJlbnQpID0+IHJvb3QuZGF0YXNldHMgPyByb290LmRhdGFzZXRzLmRhdGEgOiByb290XSwgWyIkcmVjb3JkIiwgKHJvb3QsIGN1cnJlbnQpID0+IChyb290LmRhdGFzZXRzID8gcm9vdC5kYXRhc2V0cy5kYXRhIDogcm9vdClbX3hmYV9vYmplY3QuJGdldENoaWxkcmVuXSgpWzBdXSwgWyIkdGVtcGxhdGUiLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdC50ZW1wbGF0ZV0sIFsiJGNvbm5lY3Rpb25TZXQiLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdC5jb25uZWN0aW9uU2V0XSwgWyIkZm9ybSIsIChyb290LCBjdXJyZW50KSA9PiByb290LmZvcm1dLCBbIiRsYXlvdXQiLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdC5sYXlvdXRdLCBbIiRob3N0IiwgKHJvb3QsIGN1cnJlbnQpID0+IHJvb3QuaG9zdF0sIFsiJGRhdGFXaW5kb3ciLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdC5kYXRhV2luZG93XSwgWyIkZXZlbnQiLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdC5ldmVudF0sIFsiISIsIChyb290LCBjdXJyZW50KSA9PiByb290LmRhdGFzZXRzXSwgWyIkeGZhIiwgKHJvb3QsIGN1cnJlbnQpID0+IHJvb3RdLCBbInhmYSIsIChyb290LCBjdXJyZW50KSA9PiByb290XSwgWyIkIiwgKHJvb3QsIGN1cnJlbnQpID0+IGN1cnJlbnRdXSk7CmNvbnN0IHNvbUNhY2hlID0gbmV3IFdlYWtNYXAoKTsKY29uc3QgTlNfREFUQVNFVFMgPSBfbmFtZXNwYWNlcy5OYW1lc3BhY2VJZHMuZGF0YXNldHMuaWQ7CmZ1bmN0aW9uIHBhcnNlSW5kZXgoaW5kZXgpIHsKICBpbmRleCA9IGluZGV4LnRyaW0oKTsKICBpZiAoaW5kZXggPT09ICIqIikgewogICAgcmV0dXJuIEluZmluaXR5OwogIH0KICByZXR1cm4gcGFyc2VJbnQoaW5kZXgsIDEwKSB8fCAwOwp9CmZ1bmN0aW9uIHBhcnNlRXhwcmVzc2lvbihleHByLCBkb3REb3RBbGxvd2VkKSB7CiAgbGV0IG5vRXhwciA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogdHJ1ZTsKICBsZXQgbWF0Y2ggPSBleHByLm1hdGNoKG5hbWVQYXR0ZXJuKTsKICBpZiAoIW1hdGNoKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgbGV0IFtuYW1lXSA9IG1hdGNoOwogIGNvbnN0IHBhcnNlZCA9IFt7CiAgICBuYW1lLAogICAgY2FjaGVOYW1lOiAiLiIgKyBuYW1lLAogICAgaW5kZXg6IDAsCiAgICBqczogbnVsbCwKICAgIGZvcm1DYWxjOiBudWxsLAogICAgb3BlcmF0b3I6IG9wZXJhdG9ycy5kb3QKICB9XTsKICBsZXQgcG9zID0gbmFtZS5sZW5ndGg7CiAgd2hpbGUgKHBvcyA8IGV4cHIubGVuZ3RoKSB7CiAgICBjb25zdCBzcG9zID0gcG9zOwogICAgY29uc3QgY2hhciA9IGV4cHIuY2hhckF0KHBvcysrKTsKICAgIGlmIChjaGFyID09PSAiWyIpIHsKICAgICAgbWF0Y2ggPSBleHByLnNsaWNlKHBvcykubWF0Y2goaW5kZXhQYXR0ZXJuKTsKICAgICAgaWYgKCFtYXRjaCkgewogICAgICAgICgwLCBfdXRpbC53YXJuKSgiWEZBIC0gSW52YWxpZCBpbmRleCBpbiBTT00gZXhwcmVzc2lvbiIpOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHBhcnNlZC5hdCgtMSkuaW5kZXggPSBwYXJzZUluZGV4KG1hdGNoWzBdKTsKICAgICAgcG9zICs9IG1hdGNoWzBdLmxlbmd0aCArIDE7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgbGV0IG9wZXJhdG9yOwogICAgc3dpdGNoIChleHByLmNoYXJBdChwb3MpKSB7CiAgICAgIGNhc2UgIi4iOgogICAgICAgIGlmICghZG90RG90QWxsb3dlZCkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIHBvcysrOwogICAgICAgIG9wZXJhdG9yID0gb3BlcmF0b3JzLmRvdERvdDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiIyI6CiAgICAgICAgcG9zKys7CiAgICAgICAgb3BlcmF0b3IgPSBvcGVyYXRvcnMuZG90SGFzaDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiWyI6CiAgICAgICAgaWYgKG5vRXhwcikgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKCJYRkEgLSBTT00gZXhwcmVzc2lvbiBjb250YWlucyBhIEZvcm1DYWxjIHN1YmV4cHJlc3Npb24gd2hpY2ggaXMgbm90IHN1cHBvcnRlZCBmb3Igbm93LiIpOwogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIG9wZXJhdG9yID0gb3BlcmF0b3JzLmRvdEJyYWNrZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIigiOgogICAgICAgIGlmIChub0V4cHIpIHsKICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiWEZBIC0gU09NIGV4cHJlc3Npb24gY29udGFpbnMgYSBKYXZhU2NyaXB0IHN1YmV4cHJlc3Npb24gd2hpY2ggaXMgbm90IHN1cHBvcnRlZCBmb3Igbm93LiIpOwogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIG9wZXJhdG9yID0gb3BlcmF0b3JzLmRvdFBhcmVuOwogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIG9wZXJhdG9yID0gb3BlcmF0b3JzLmRvdDsKICAgICAgICBicmVhazsKICAgIH0KICAgIG1hdGNoID0gZXhwci5zbGljZShwb3MpLm1hdGNoKG5hbWVQYXR0ZXJuKTsKICAgIGlmICghbWF0Y2gpIHsKICAgICAgYnJlYWs7CiAgICB9CiAgICBbbmFtZV0gPSBtYXRjaDsKICAgIHBvcyArPSBuYW1lLmxlbmd0aDsKICAgIHBhcnNlZC5wdXNoKHsKICAgICAgbmFtZSwKICAgICAgY2FjaGVOYW1lOiBleHByLnNsaWNlKHNwb3MsIHBvcyksCiAgICAgIG9wZXJhdG9yLAogICAgICBpbmRleDogMCwKICAgICAganM6IG51bGwsCiAgICAgIGZvcm1DYWxjOiBudWxsCiAgICB9KTsKICB9CiAgcmV0dXJuIHBhcnNlZDsKfQpmdW5jdGlvbiBzZWFyY2hOb2RlKHJvb3QsIGNvbnRhaW5lciwgZXhwcikgewogIGxldCBkb3REb3RBbGxvd2VkID0gYXJndW1lbnRzLmxlbmd0aCA+IDMgJiYgYXJndW1lbnRzWzNdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbM10gOiB0cnVlOwogIGxldCB1c2VDYWNoZSA9IGFyZ3VtZW50cy5sZW5ndGggPiA0ICYmIGFyZ3VtZW50c1s0XSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzRdIDogdHJ1ZTsKICBjb25zdCBwYXJzZWQgPSBwYXJzZUV4cHJlc3Npb24oZXhwciwgZG90RG90QWxsb3dlZCk7CiAgaWYgKCFwYXJzZWQpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBjb25zdCBmbiA9IHNob3J0Y3V0cy5nZXQocGFyc2VkWzBdLm5hbWUpOwogIGxldCBpID0gMDsKICBsZXQgaXNRdWFsaWZpZWQ7CiAgaWYgKGZuKSB7CiAgICBpc1F1YWxpZmllZCA9IHRydWU7CiAgICByb290ID0gW2ZuKHJvb3QsIGNvbnRhaW5lcildOwogICAgaSA9IDE7CiAgfSBlbHNlIHsKICAgIGlzUXVhbGlmaWVkID0gY29udGFpbmVyID09PSBudWxsOwogICAgcm9vdCA9IFtjb250YWluZXIgfHwgcm9vdF07CiAgfQogIGZvciAobGV0IGlpID0gcGFyc2VkLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IHsKICAgICAgbmFtZSwKICAgICAgY2FjaGVOYW1lLAogICAgICBvcGVyYXRvciwKICAgICAgaW5kZXgKICAgIH0gPSBwYXJzZWRbaV07CiAgICBjb25zdCBub2RlcyA9IFtdOwogICAgZm9yIChjb25zdCBub2RlIG9mIHJvb3QpIHsKICAgICAgaWYgKCEobm9kZSBpbnN0YW5jZW9mIF94ZmFfb2JqZWN0LlhGQU9iamVjdCkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBsZXQgY2hpbGRyZW4sIGNhY2hlZDsKICAgICAgaWYgKHVzZUNhY2hlKSB7CiAgICAgICAgY2FjaGVkID0gc29tQ2FjaGUuZ2V0KG5vZGUpOwogICAgICAgIGlmICghY2FjaGVkKSB7CiAgICAgICAgICBjYWNoZWQgPSBuZXcgTWFwKCk7CiAgICAgICAgICBzb21DYWNoZS5zZXQobm9kZSwgY2FjaGVkKTsKICAgICAgICB9CiAgICAgICAgY2hpbGRyZW4gPSBjYWNoZWQuZ2V0KGNhY2hlTmFtZSk7CiAgICAgIH0KICAgICAgaWYgKCFjaGlsZHJlbikgewogICAgICAgIHN3aXRjaCAob3BlcmF0b3IpIHsKICAgICAgICAgIGNhc2Ugb3BlcmF0b3JzLmRvdDoKICAgICAgICAgICAgY2hpbGRyZW4gPSBub2RlW194ZmFfb2JqZWN0LiRnZXRDaGlsZHJlbkJ5TmFtZV0obmFtZSwgZmFsc2UpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2Ugb3BlcmF0b3JzLmRvdERvdDoKICAgICAgICAgICAgY2hpbGRyZW4gPSBub2RlW194ZmFfb2JqZWN0LiRnZXRDaGlsZHJlbkJ5TmFtZV0obmFtZSwgdHJ1ZSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBvcGVyYXRvcnMuZG90SGFzaDoKICAgICAgICAgICAgY2hpbGRyZW4gPSBub2RlW194ZmFfb2JqZWN0LiRnZXRDaGlsZHJlbkJ5Q2xhc3NdKG5hbWUpOwogICAgICAgICAgICBpZiAoY2hpbGRyZW4gaW5zdGFuY2VvZiBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSkgewogICAgICAgICAgICAgIGNoaWxkcmVuID0gY2hpbGRyZW4uY2hpbGRyZW47CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgY2hpbGRyZW4gPSBbY2hpbGRyZW5dOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmICh1c2VDYWNoZSkgewogICAgICAgICAgY2FjaGVkLnNldChjYWNoZU5hbWUsIGNoaWxkcmVuKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA+IDApIHsKICAgICAgICBub2Rlcy5wdXNoKGNoaWxkcmVuKTsKICAgICAgfQogICAgfQogICAgaWYgKG5vZGVzLmxlbmd0aCA9PT0gMCAmJiAhaXNRdWFsaWZpZWQgJiYgaSA9PT0gMCkgewogICAgICBjb25zdCBwYXJlbnQgPSBjb250YWluZXJbX3hmYV9vYmplY3QuJGdldFBhcmVudF0oKTsKICAgICAgY29udGFpbmVyID0gcGFyZW50OwogICAgICBpZiAoIWNvbnRhaW5lcikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGkgPSAtMTsKICAgICAgcm9vdCA9IFtjb250YWluZXJdOwogICAgICBjb250aW51ZTsKICAgIH0KICAgIGlmIChpc0Zpbml0ZShpbmRleCkpIHsKICAgICAgcm9vdCA9IG5vZGVzLmZpbHRlcihub2RlID0+IGluZGV4IDwgbm9kZS5sZW5ndGgpLm1hcChub2RlID0+IG5vZGVbaW5kZXhdKTsKICAgIH0gZWxzZSB7CiAgICAgIHJvb3QgPSBub2Rlcy5mbGF0KCk7CiAgICB9CiAgfQogIGlmIChyb290Lmxlbmd0aCA9PT0gMCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIHJldHVybiByb290Owp9CmZ1bmN0aW9uIGNyZWF0ZU5vZGVzKHJvb3QsIHBhdGgpIHsKICBsZXQgbm9kZSA9IG51bGw7CiAgZm9yIChjb25zdCB7CiAgICBuYW1lLAogICAgaW5kZXgKICB9IG9mIHBhdGgpIHsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9ICFpc0Zpbml0ZShpbmRleCkgPyAwIDogaW5kZXg7IGkgPD0gaWk7IGkrKykgewogICAgICBjb25zdCBuc0lkID0gcm9vdFtfeGZhX29iamVjdC4kbmFtZXNwYWNlSWRdID09PSBOU19EQVRBU0VUUyA/IC0xIDogcm9vdFtfeGZhX29iamVjdC4kbmFtZXNwYWNlSWRdOwogICAgICBub2RlID0gbmV3IF94ZmFfb2JqZWN0LlhtbE9iamVjdChuc0lkLCBuYW1lKTsKICAgICAgcm9vdFtfeGZhX29iamVjdC4kYXBwZW5kQ2hpbGRdKG5vZGUpOwogICAgfQogICAgcm9vdCA9IG5vZGU7CiAgfQogIHJldHVybiBub2RlOwp9CmZ1bmN0aW9uIGNyZWF0ZURhdGFOb2RlKHJvb3QsIGNvbnRhaW5lciwgZXhwcikgewogIGNvbnN0IHBhcnNlZCA9IHBhcnNlRXhwcmVzc2lvbihleHByKTsKICBpZiAoIXBhcnNlZCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGlmIChwYXJzZWQuc29tZSh4ID0+IHgub3BlcmF0b3IgPT09IG9wZXJhdG9ycy5kb3REb3QpKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgY29uc3QgZm4gPSBzaG9ydGN1dHMuZ2V0KHBhcnNlZFswXS5uYW1lKTsKICBsZXQgaSA9IDA7CiAgaWYgKGZuKSB7CiAgICByb290ID0gZm4ocm9vdCwgY29udGFpbmVyKTsKICAgIGkgPSAxOwogIH0gZWxzZSB7CiAgICByb290ID0gY29udGFpbmVyIHx8IHJvb3Q7CiAgfQogIGZvciAobGV0IGlpID0gcGFyc2VkLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IHsKICAgICAgbmFtZSwKICAgICAgb3BlcmF0b3IsCiAgICAgIGluZGV4CiAgICB9ID0gcGFyc2VkW2ldOwogICAgaWYgKCFpc0Zpbml0ZShpbmRleCkpIHsKICAgICAgcGFyc2VkW2ldLmluZGV4ID0gMDsKICAgICAgcmV0dXJuIGNyZWF0ZU5vZGVzKHJvb3QsIHBhcnNlZC5zbGljZShpKSk7CiAgICB9CiAgICBsZXQgY2hpbGRyZW47CiAgICBzd2l0Y2ggKG9wZXJhdG9yKSB7CiAgICAgIGNhc2Ugb3BlcmF0b3JzLmRvdDoKICAgICAgICBjaGlsZHJlbiA9IHJvb3RbX3hmYV9vYmplY3QuJGdldENoaWxkcmVuQnlOYW1lXShuYW1lLCBmYWxzZSk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2Ugb3BlcmF0b3JzLmRvdERvdDoKICAgICAgICBjaGlsZHJlbiA9IHJvb3RbX3hmYV9vYmplY3QuJGdldENoaWxkcmVuQnlOYW1lXShuYW1lLCB0cnVlKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBvcGVyYXRvcnMuZG90SGFzaDoKICAgICAgICBjaGlsZHJlbiA9IHJvb3RbX3hmYV9vYmplY3QuJGdldENoaWxkcmVuQnlDbGFzc10obmFtZSk7CiAgICAgICAgaWYgKGNoaWxkcmVuIGluc3RhbmNlb2YgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkpIHsKICAgICAgICAgIGNoaWxkcmVuID0gY2hpbGRyZW4uY2hpbGRyZW47CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNoaWxkcmVuID0gW2NoaWxkcmVuXTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBjcmVhdGVOb2Rlcyhyb290LCBwYXJzZWQuc2xpY2UoaSkpOwogICAgfQogICAgaWYgKGluZGV4IDwgY2hpbGRyZW4ubGVuZ3RoKSB7CiAgICAgIGNvbnN0IGNoaWxkID0gY2hpbGRyZW5baW5kZXhdOwogICAgICBpZiAoIShjaGlsZCBpbnN0YW5jZW9mIF94ZmFfb2JqZWN0LlhGQU9iamVjdCkpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYFhGQSAtIENhbm5vdCBjcmVhdGUgYSBub2RlLmApOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHJvb3QgPSBjaGlsZDsKICAgIH0gZWxzZSB7CiAgICAgIHBhcnNlZFtpXS5pbmRleCA9IGluZGV4IC0gY2hpbGRyZW4ubGVuZ3RoOwogICAgICByZXR1cm4gY3JlYXRlTm9kZXMocm9vdCwgcGFyc2VkLnNsaWNlKGkpKTsKICAgIH0KICB9CiAgcmV0dXJuIG51bGw7Cn0KCi8qKiovIH0pLAovKiAyMTYgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLkJpbmRlciA9IHZvaWQgMDsKdmFyIF94ZmFfb2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTIpOwp2YXIgX3RlbXBsYXRlID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTcpOwp2YXIgX3NvbSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjE1KTsKdmFyIF9uYW1lc3BhY2VzID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTQpOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpjb25zdCBOU19EQVRBU0VUUyA9IF9uYW1lc3BhY2VzLk5hbWVzcGFjZUlkcy5kYXRhc2V0cy5pZDsKZnVuY3Rpb24gY3JlYXRlVGV4dChjb250ZW50KSB7CiAgY29uc3Qgbm9kZSA9IG5ldyBfdGVtcGxhdGUuVGV4dCh7fSk7CiAgbm9kZVtfeGZhX29iamVjdC4kY29udGVudF0gPSBjb250ZW50OwogIHJldHVybiBub2RlOwp9CmNsYXNzIEJpbmRlciB7CiAgY29uc3RydWN0b3Iocm9vdCkgewogICAgdGhpcy5yb290ID0gcm9vdDsKICAgIHRoaXMuZGF0YXNldHMgPSByb290LmRhdGFzZXRzOwogICAgaWYgKHJvb3QuZGF0YXNldHMgJiYgcm9vdC5kYXRhc2V0cy5kYXRhKSB7CiAgICAgIHRoaXMuZGF0YSA9IHJvb3QuZGF0YXNldHMuZGF0YTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuZGF0YSA9IG5ldyBfeGZhX29iamVjdC5YbWxPYmplY3QoX25hbWVzcGFjZXMuTmFtZXNwYWNlSWRzLmRhdGFzZXRzLmlkLCAiZGF0YSIpOwogICAgfQogICAgdGhpcy5lbXB0eU1lcmdlID0gdGhpcy5kYXRhW194ZmFfb2JqZWN0LiRnZXRDaGlsZHJlbl0oKS5sZW5ndGggPT09IDA7CiAgICB0aGlzLnJvb3QuZm9ybSA9IHRoaXMuZm9ybSA9IHJvb3QudGVtcGxhdGVbX3hmYV9vYmplY3QuJGNsb25lXSgpOwogIH0KICBfaXNDb25zdW1lRGF0YSgpIHsKICAgIHJldHVybiAhdGhpcy5lbXB0eU1lcmdlICYmIHRoaXMuX21lcmdlTW9kZTsKICB9CiAgX2lzTWF0Y2hUZW1wbGF0ZSgpIHsKICAgIHJldHVybiAhdGhpcy5faXNDb25zdW1lRGF0YSgpOwogIH0KICBiaW5kKCkgewogICAgdGhpcy5fYmluZEVsZW1lbnQodGhpcy5mb3JtLCB0aGlzLmRhdGEpOwogICAgcmV0dXJuIHRoaXMuZm9ybTsKICB9CiAgZ2V0RGF0YSgpIHsKICAgIHJldHVybiB0aGlzLmRhdGE7CiAgfQogIF9iaW5kVmFsdWUoZm9ybU5vZGUsIGRhdGEsIHBpY3R1cmUpIHsKICAgIGZvcm1Ob2RlW194ZmFfb2JqZWN0LiRkYXRhXSA9IGRhdGE7CiAgICBpZiAoZm9ybU5vZGVbX3hmYV9vYmplY3QuJGhhc1NldHRhYmxlVmFsdWVdKCkpIHsKICAgICAgaWYgKGRhdGFbX3hmYV9vYmplY3QuJGlzRGF0YVZhbHVlXSgpKSB7CiAgICAgICAgY29uc3QgdmFsdWUgPSBkYXRhW194ZmFfb2JqZWN0LiRnZXREYXRhVmFsdWVdKCk7CiAgICAgICAgZm9ybU5vZGVbX3hmYV9vYmplY3QuJHNldFZhbHVlXShjcmVhdGVUZXh0KHZhbHVlKSk7CiAgICAgIH0gZWxzZSBpZiAoZm9ybU5vZGUgaW5zdGFuY2VvZiBfdGVtcGxhdGUuRmllbGQgJiYgZm9ybU5vZGUudWkgJiYgZm9ybU5vZGUudWkuY2hvaWNlTGlzdCAmJiBmb3JtTm9kZS51aS5jaG9pY2VMaXN0Lm9wZW4gPT09ICJtdWx0aVNlbGVjdCIpIHsKICAgICAgICBjb25zdCB2YWx1ZSA9IGRhdGFbX3hmYV9vYmplY3QuJGdldENoaWxkcmVuXSgpLm1hcChjaGlsZCA9PiBjaGlsZFtfeGZhX29iamVjdC4kY29udGVudF0udHJpbSgpKS5qb2luKCJcbiIpOwogICAgICAgIGZvcm1Ob2RlW194ZmFfb2JqZWN0LiRzZXRWYWx1ZV0oY3JlYXRlVGV4dCh2YWx1ZSkpOwogICAgICB9IGVsc2UgaWYgKHRoaXMuX2lzQ29uc3VtZURhdGEoKSkgewogICAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gTm9kZXMgaGF2ZW4ndCB0aGUgc2FtZSB0eXBlLmApOwogICAgICB9CiAgICB9IGVsc2UgaWYgKCFkYXRhW194ZmFfb2JqZWN0LiRpc0RhdGFWYWx1ZV0oKSB8fCB0aGlzLl9pc01hdGNoVGVtcGxhdGUoKSkgewogICAgICB0aGlzLl9iaW5kRWxlbWVudChmb3JtTm9kZSwgZGF0YSk7CiAgICB9IGVsc2UgewogICAgICAoMCwgX3V0aWwud2FybikoYFhGQSAtIE5vZGVzIGhhdmVuJ3QgdGhlIHNhbWUgdHlwZS5gKTsKICAgIH0KICB9CiAgX2ZpbmREYXRhQnlOYW1lVG9Db25zdW1lKG5hbWUsIGlzVmFsdWUsIGRhdGFOb2RlLCBnbG9iYWwpIHsKICAgIGlmICghbmFtZSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGxldCBnZW5lcmF0b3IsIG1hdGNoOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCAzOyBpKyspIHsKICAgICAgZ2VuZXJhdG9yID0gZGF0YU5vZGVbX3hmYV9vYmplY3QuJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCBmYWxzZSwgdHJ1ZSk7CiAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgbWF0Y2ggPSBnZW5lcmF0b3IubmV4dCgpLnZhbHVlOwogICAgICAgIGlmICghbWF0Y2gpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAoaXNWYWx1ZSA9PT0gbWF0Y2hbX3hmYV9vYmplY3QuJGlzRGF0YVZhbHVlXSgpKSB7CiAgICAgICAgICByZXR1cm4gbWF0Y2g7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChkYXRhTm9kZVtfeGZhX29iamVjdC4kbmFtZXNwYWNlSWRdID09PSBfbmFtZXNwYWNlcy5OYW1lc3BhY2VJZHMuZGF0YXNldHMuaWQgJiYgZGF0YU5vZGVbX3hmYV9vYmplY3QuJG5vZGVOYW1lXSA9PT0gImRhdGEiKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgZGF0YU5vZGUgPSBkYXRhTm9kZVtfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpOwogICAgfQogICAgaWYgKCFnbG9iYWwpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBnZW5lcmF0b3IgPSB0aGlzLmRhdGFbX3hmYV9vYmplY3QuJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCB0cnVlLCBmYWxzZSk7CiAgICBtYXRjaCA9IGdlbmVyYXRvci5uZXh0KCkudmFsdWU7CiAgICBpZiAobWF0Y2gpIHsKICAgICAgcmV0dXJuIG1hdGNoOwogICAgfQogICAgZ2VuZXJhdG9yID0gdGhpcy5kYXRhW194ZmFfb2JqZWN0LiRnZXRBdHRyaWJ1dGVJdF0obmFtZSwgdHJ1ZSk7CiAgICBtYXRjaCA9IGdlbmVyYXRvci5uZXh0KCkudmFsdWU7CiAgICBpZiAobWF0Y2ggJiYgbWF0Y2hbX3hmYV9vYmplY3QuJGlzRGF0YVZhbHVlXSgpKSB7CiAgICAgIHJldHVybiBtYXRjaDsKICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICBfc2V0UHJvcGVydGllcyhmb3JtTm9kZSwgZGF0YU5vZGUpIHsKICAgIGlmICghZm9ybU5vZGUuaGFzT3duUHJvcGVydHkoInNldFByb3BlcnR5IikpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgZm9yIChjb25zdCB7CiAgICAgIHJlZiwKICAgICAgdGFyZ2V0LAogICAgICBjb25uZWN0aW9uCiAgICB9IG9mIGZvcm1Ob2RlLnNldFByb3BlcnR5LmNoaWxkcmVuKSB7CiAgICAgIGlmIChjb25uZWN0aW9uKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKCFyZWYpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBub2RlcyA9ICgwLCBfc29tLnNlYXJjaE5vZGUpKHRoaXMucm9vdCwgZGF0YU5vZGUsIHJlZiwgZmFsc2UsIGZhbHNlKTsKICAgICAgaWYgKCFub2RlcykgewogICAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gSW52YWxpZCByZWZlcmVuY2U6ICR7cmVmfS5gKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBbbm9kZV0gPSBub2RlczsKICAgICAgaWYgKCFub2RlW194ZmFfb2JqZWN0LiRpc0Rlc2NlbmRlbnRdKHRoaXMuZGF0YSkpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYFhGQSAtIEludmFsaWQgbm9kZTogbXVzdCBiZSBhIGRhdGEgbm9kZS5gKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB0YXJnZXROb2RlcyA9ICgwLCBfc29tLnNlYXJjaE5vZGUpKHRoaXMucm9vdCwgZm9ybU5vZGUsIHRhcmdldCwgZmFsc2UsIGZhbHNlKTsKICAgICAgaWYgKCF0YXJnZXROb2RlcykgewogICAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gSW52YWxpZCB0YXJnZXQ6ICR7dGFyZ2V0fS5gKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBbdGFyZ2V0Tm9kZV0gPSB0YXJnZXROb2RlczsKICAgICAgaWYgKCF0YXJnZXROb2RlW194ZmFfb2JqZWN0LiRpc0Rlc2NlbmRlbnRdKGZvcm1Ob2RlKSkgewogICAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gSW52YWxpZCB0YXJnZXQ6IG11c3QgYmUgYSBwcm9wZXJ0eSBvciBzdWJwcm9wZXJ0eS5gKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB0YXJnZXRQYXJlbnQgPSB0YXJnZXROb2RlW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICAgIGlmICh0YXJnZXROb2RlIGluc3RhbmNlb2YgX3RlbXBsYXRlLlNldFByb3BlcnR5IHx8IHRhcmdldFBhcmVudCBpbnN0YW5jZW9mIF90ZW1wbGF0ZS5TZXRQcm9wZXJ0eSkgewogICAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gSW52YWxpZCB0YXJnZXQ6IGNhbm5vdCBiZSBhIHNldFByb3BlcnR5IG9yIG9uZSBvZiBpdHMgcHJvcGVydGllcy5gKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAodGFyZ2V0Tm9kZSBpbnN0YW5jZW9mIF90ZW1wbGF0ZS5CaW5kSXRlbXMgfHwgdGFyZ2V0UGFyZW50IGluc3RhbmNlb2YgX3RlbXBsYXRlLkJpbmRJdGVtcykgewogICAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gSW52YWxpZCB0YXJnZXQ6IGNhbm5vdCBiZSBhIGJpbmRJdGVtcyBvciBvbmUgb2YgaXRzIHByb3BlcnRpZXMuYCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgY29udGVudCA9IG5vZGVbX3hmYV9vYmplY3QuJHRleHRdKCk7CiAgICAgIGNvbnN0IG5hbWUgPSB0YXJnZXROb2RlW194ZmFfb2JqZWN0LiRub2RlTmFtZV07CiAgICAgIGlmICh0YXJnZXROb2RlIGluc3RhbmNlb2YgX3hmYV9vYmplY3QuWEZBQXR0cmlidXRlKSB7CiAgICAgICAgY29uc3QgYXR0cnMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgIGF0dHJzW25hbWVdID0gY29udGVudDsKICAgICAgICBjb25zdCBvYmogPSBSZWZsZWN0LmNvbnN0cnVjdChPYmplY3QuZ2V0UHJvdG90eXBlT2YodGFyZ2V0UGFyZW50KS5jb25zdHJ1Y3RvciwgW2F0dHJzXSk7CiAgICAgICAgdGFyZ2V0UGFyZW50W25hbWVdID0gb2JqW25hbWVdOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICghdGFyZ2V0Tm9kZS5oYXNPd25Qcm9wZXJ0eShfeGZhX29iamVjdC4kY29udGVudCkpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYFhGQSAtIEludmFsaWQgbm9kZSB0byB1c2UgaW4gc2V0UHJvcGVydHlgKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICB0YXJnZXROb2RlW194ZmFfb2JqZWN0LiRkYXRhXSA9IG5vZGU7CiAgICAgIHRhcmdldE5vZGVbX3hmYV9vYmplY3QuJGNvbnRlbnRdID0gY29udGVudDsKICAgICAgdGFyZ2V0Tm9kZVtfeGZhX29iamVjdC4kZmluYWxpemVdKCk7CiAgICB9CiAgfQogIF9iaW5kSXRlbXMoZm9ybU5vZGUsIGRhdGFOb2RlKSB7CiAgICBpZiAoIWZvcm1Ob2RlLmhhc093blByb3BlcnR5KCJpdGVtcyIpIHx8ICFmb3JtTm9kZS5oYXNPd25Qcm9wZXJ0eSgiYmluZEl0ZW1zIikgfHwgZm9ybU5vZGUuYmluZEl0ZW1zLmlzRW1wdHkoKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgZm9ybU5vZGUuaXRlbXMuY2hpbGRyZW4pIHsKICAgICAgZm9ybU5vZGVbX3hmYV9vYmplY3QuJHJlbW92ZUNoaWxkXShpdGVtKTsKICAgIH0KICAgIGZvcm1Ob2RlLml0ZW1zLmNsZWFyKCk7CiAgICBjb25zdCBsYWJlbHMgPSBuZXcgX3RlbXBsYXRlLkl0ZW1zKHt9KTsKICAgIGNvbnN0IHZhbHVlcyA9IG5ldyBfdGVtcGxhdGUuSXRlbXMoe30pOwogICAgZm9ybU5vZGVbX3hmYV9vYmplY3QuJGFwcGVuZENoaWxkXShsYWJlbHMpOwogICAgZm9ybU5vZGUuaXRlbXMucHVzaChsYWJlbHMpOwogICAgZm9ybU5vZGVbX3hmYV9vYmplY3QuJGFwcGVuZENoaWxkXSh2YWx1ZXMpOwogICAgZm9ybU5vZGUuaXRlbXMucHVzaCh2YWx1ZXMpOwogICAgZm9yIChjb25zdCB7CiAgICAgIHJlZiwKICAgICAgbGFiZWxSZWYsCiAgICAgIHZhbHVlUmVmLAogICAgICBjb25uZWN0aW9uCiAgICB9IG9mIGZvcm1Ob2RlLmJpbmRJdGVtcy5jaGlsZHJlbikgewogICAgICBpZiAoY29ubmVjdGlvbikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICghcmVmKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3Qgbm9kZXMgPSAoMCwgX3NvbS5zZWFyY2hOb2RlKSh0aGlzLnJvb3QsIGRhdGFOb2RlLCByZWYsIGZhbHNlLCBmYWxzZSk7CiAgICAgIGlmICghbm9kZXMpIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYFhGQSAtIEludmFsaWQgcmVmZXJlbmNlOiAke3JlZn0uYCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBub2RlIG9mIG5vZGVzKSB7CiAgICAgICAgaWYgKCFub2RlW194ZmFfb2JqZWN0LiRpc0Rlc2NlbmRlbnRdKHRoaXMuZGF0YXNldHMpKSB7CiAgICAgICAgICAoMCwgX3V0aWwud2FybikoYFhGQSAtIEludmFsaWQgcmVmICgke3JlZn0pOiBtdXN0IGJlIGEgZGF0YXNldHMgY2hpbGQuYCk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbGFiZWxOb2RlcyA9ICgwLCBfc29tLnNlYXJjaE5vZGUpKHRoaXMucm9vdCwgbm9kZSwgbGFiZWxSZWYsIHRydWUsIGZhbHNlKTsKICAgICAgICBpZiAoIWxhYmVsTm9kZXMpIHsKICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gSW52YWxpZCBsYWJlbDogJHtsYWJlbFJlZn0uYCk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgW2xhYmVsTm9kZV0gPSBsYWJlbE5vZGVzOwogICAgICAgIGlmICghbGFiZWxOb2RlW194ZmFfb2JqZWN0LiRpc0Rlc2NlbmRlbnRdKHRoaXMuZGF0YXNldHMpKSB7CiAgICAgICAgICAoMCwgX3V0aWwud2FybikoYFhGQSAtIEludmFsaWQgbGFiZWw6IG11c3QgYmUgYSBkYXRhc2V0cyBjaGlsZC5gKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCB2YWx1ZU5vZGVzID0gKDAsIF9zb20uc2VhcmNoTm9kZSkodGhpcy5yb290LCBub2RlLCB2YWx1ZVJlZiwgdHJ1ZSwgZmFsc2UpOwogICAgICAgIGlmICghdmFsdWVOb2RlcykgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBYRkEgLSBJbnZhbGlkIHZhbHVlOiAke3ZhbHVlUmVmfS5gKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBbdmFsdWVOb2RlXSA9IHZhbHVlTm9kZXM7CiAgICAgICAgaWYgKCF2YWx1ZU5vZGVbX3hmYV9vYmplY3QuJGlzRGVzY2VuZGVudF0odGhpcy5kYXRhc2V0cykpIHsKICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gSW52YWxpZCB2YWx1ZTogbXVzdCBiZSBhIGRhdGFzZXRzIGNoaWxkLmApOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGxhYmVsID0gY3JlYXRlVGV4dChsYWJlbE5vZGVbX3hmYV9vYmplY3QuJHRleHRdKCkpOwogICAgICAgIGNvbnN0IHZhbHVlID0gY3JlYXRlVGV4dCh2YWx1ZU5vZGVbX3hmYV9vYmplY3QuJHRleHRdKCkpOwogICAgICAgIGxhYmVsc1tfeGZhX29iamVjdC4kYXBwZW5kQ2hpbGRdKGxhYmVsKTsKICAgICAgICBsYWJlbHMudGV4dC5wdXNoKGxhYmVsKTsKICAgICAgICB2YWx1ZXNbX3hmYV9vYmplY3QuJGFwcGVuZENoaWxkXSh2YWx1ZSk7CiAgICAgICAgdmFsdWVzLnRleHQucHVzaCh2YWx1ZSk7CiAgICAgIH0KICAgIH0KICB9CiAgX2JpbmRPY2N1cnJlbmNlcyhmb3JtTm9kZSwgbWF0Y2hlcywgcGljdHVyZSkgewogICAgbGV0IGJhc2VDbG9uZTsKICAgIGlmIChtYXRjaGVzLmxlbmd0aCA+IDEpIHsKICAgICAgYmFzZUNsb25lID0gZm9ybU5vZGVbX3hmYV9vYmplY3QuJGNsb25lXSgpOwogICAgICBiYXNlQ2xvbmVbX3hmYV9vYmplY3QuJHJlbW92ZUNoaWxkXShiYXNlQ2xvbmUub2NjdXIpOwogICAgICBiYXNlQ2xvbmUub2NjdXIgPSBudWxsOwogICAgfQogICAgdGhpcy5fYmluZFZhbHVlKGZvcm1Ob2RlLCBtYXRjaGVzWzBdLCBwaWN0dXJlKTsKICAgIHRoaXMuX3NldFByb3BlcnRpZXMoZm9ybU5vZGUsIG1hdGNoZXNbMF0pOwogICAgdGhpcy5fYmluZEl0ZW1zKGZvcm1Ob2RlLCBtYXRjaGVzWzBdKTsKICAgIGlmIChtYXRjaGVzLmxlbmd0aCA9PT0gMSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBwYXJlbnQgPSBmb3JtTm9kZVtfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpOwogICAgY29uc3QgbmFtZSA9IGZvcm1Ob2RlW194ZmFfb2JqZWN0LiRub2RlTmFtZV07CiAgICBjb25zdCBwb3MgPSBwYXJlbnRbX3hmYV9vYmplY3QuJGluZGV4T2ZdKGZvcm1Ob2RlKTsKICAgIGZvciAobGV0IGkgPSAxLCBpaSA9IG1hdGNoZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBtYXRjaCA9IG1hdGNoZXNbaV07CiAgICAgIGNvbnN0IGNsb25lID0gYmFzZUNsb25lW194ZmFfb2JqZWN0LiRjbG9uZV0oKTsKICAgICAgcGFyZW50W25hbWVdLnB1c2goY2xvbmUpOwogICAgICBwYXJlbnRbX3hmYV9vYmplY3QuJGluc2VydEF0XShwb3MgKyBpLCBjbG9uZSk7CiAgICAgIHRoaXMuX2JpbmRWYWx1ZShjbG9uZSwgbWF0Y2gsIHBpY3R1cmUpOwogICAgICB0aGlzLl9zZXRQcm9wZXJ0aWVzKGNsb25lLCBtYXRjaCk7CiAgICAgIHRoaXMuX2JpbmRJdGVtcyhjbG9uZSwgbWF0Y2gpOwogICAgfQogIH0KICBfY3JlYXRlT2NjdXJyZW5jZXMoZm9ybU5vZGUpIHsKICAgIGlmICghdGhpcy5lbXB0eU1lcmdlKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgb2NjdXIKICAgIH0gPSBmb3JtTm9kZTsKICAgIGlmICghb2NjdXIgfHwgb2NjdXIuaW5pdGlhbCA8PSAxKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHBhcmVudCA9IGZvcm1Ob2RlW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBuYW1lID0gZm9ybU5vZGVbX3hmYV9vYmplY3QuJG5vZGVOYW1lXTsKICAgIGlmICghKHBhcmVudFtuYW1lXSBpbnN0YW5jZW9mIF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgY3VycmVudE51bWJlcjsKICAgIGlmIChmb3JtTm9kZS5uYW1lKSB7CiAgICAgIGN1cnJlbnROdW1iZXIgPSBwYXJlbnRbbmFtZV0uY2hpbGRyZW4uZmlsdGVyKGUgPT4gZS5uYW1lID09PSBmb3JtTm9kZS5uYW1lKS5sZW5ndGg7CiAgICB9IGVsc2UgewogICAgICBjdXJyZW50TnVtYmVyID0gcGFyZW50W25hbWVdLmNoaWxkcmVuLmxlbmd0aDsKICAgIH0KICAgIGNvbnN0IHBvcyA9IHBhcmVudFtfeGZhX29iamVjdC4kaW5kZXhPZl0oZm9ybU5vZGUpICsgMTsKICAgIGNvbnN0IGlpID0gb2NjdXIuaW5pdGlhbCAtIGN1cnJlbnROdW1iZXI7CiAgICBpZiAoaWkpIHsKICAgICAgY29uc3Qgbm9kZUNsb25lID0gZm9ybU5vZGVbX3hmYV9vYmplY3QuJGNsb25lXSgpOwogICAgICBub2RlQ2xvbmVbX3hmYV9vYmplY3QuJHJlbW92ZUNoaWxkXShub2RlQ2xvbmUub2NjdXIpOwogICAgICBub2RlQ2xvbmUub2NjdXIgPSBudWxsOwogICAgICBwYXJlbnRbbmFtZV0ucHVzaChub2RlQ2xvbmUpOwogICAgICBwYXJlbnRbX3hmYV9vYmplY3QuJGluc2VydEF0XShwb3MsIG5vZGVDbG9uZSk7CiAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnN0IGNsb25lID0gbm9kZUNsb25lW194ZmFfb2JqZWN0LiRjbG9uZV0oKTsKICAgICAgICBwYXJlbnRbbmFtZV0ucHVzaChjbG9uZSk7CiAgICAgICAgcGFyZW50W194ZmFfb2JqZWN0LiRpbnNlcnRBdF0ocG9zICsgaSwgY2xvbmUpOwogICAgICB9CiAgICB9CiAgfQogIF9nZXRPY2N1ckluZm8oZm9ybU5vZGUpIHsKICAgIGNvbnN0IHsKICAgICAgbmFtZSwKICAgICAgb2NjdXIKICAgIH0gPSBmb3JtTm9kZTsKICAgIGlmICghb2NjdXIgfHwgIW5hbWUpIHsKICAgICAgcmV0dXJuIFsxLCAxXTsKICAgIH0KICAgIGNvbnN0IG1heCA9IG9jY3VyLm1heCA9PT0gLTEgPyBJbmZpbml0eSA6IG9jY3VyLm1heDsKICAgIHJldHVybiBbb2NjdXIubWluLCBtYXhdOwogIH0KICBfc2V0QW5kQmluZChmb3JtTm9kZSwgZGF0YU5vZGUpIHsKICAgIHRoaXMuX3NldFByb3BlcnRpZXMoZm9ybU5vZGUsIGRhdGFOb2RlKTsKICAgIHRoaXMuX2JpbmRJdGVtcyhmb3JtTm9kZSwgZGF0YU5vZGUpOwogICAgdGhpcy5fYmluZEVsZW1lbnQoZm9ybU5vZGUsIGRhdGFOb2RlKTsKICB9CiAgX2JpbmRFbGVtZW50KGZvcm1Ob2RlLCBkYXRhTm9kZSkgewogICAgY29uc3QgdXNlbGVzc05vZGVzID0gW107CiAgICB0aGlzLl9jcmVhdGVPY2N1cnJlbmNlcyhmb3JtTm9kZSk7CiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIGZvcm1Ob2RlW194ZmFfb2JqZWN0LiRnZXRDaGlsZHJlbl0oKSkgewogICAgICBpZiAoY2hpbGRbX3hmYV9vYmplY3QuJGRhdGFdKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuX21lcmdlTW9kZSA9PT0gdW5kZWZpbmVkICYmIGNoaWxkW194ZmFfb2JqZWN0LiRub2RlTmFtZV0gPT09ICJzdWJmb3JtIikgewogICAgICAgIHRoaXMuX21lcmdlTW9kZSA9IGNoaWxkLm1lcmdlTW9kZSA9PT0gImNvbnN1bWVEYXRhIjsKICAgICAgICBjb25zdCBkYXRhQ2hpbGRyZW4gPSBkYXRhTm9kZVtfeGZhX29iamVjdC4kZ2V0Q2hpbGRyZW5dKCk7CiAgICAgICAgaWYgKGRhdGFDaGlsZHJlbi5sZW5ndGggPiAwKSB7CiAgICAgICAgICB0aGlzLl9iaW5kT2NjdXJyZW5jZXMoY2hpbGQsIFtkYXRhQ2hpbGRyZW5bMF1dLCBudWxsKTsKICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZW1wdHlNZXJnZSkgewogICAgICAgICAgY29uc3QgbnNJZCA9IGRhdGFOb2RlW194ZmFfb2JqZWN0LiRuYW1lc3BhY2VJZF0gPT09IE5TX0RBVEFTRVRTID8gLTEgOiBkYXRhTm9kZVtfeGZhX29iamVjdC4kbmFtZXNwYWNlSWRdOwogICAgICAgICAgY29uc3QgZGF0YUNoaWxkID0gY2hpbGRbX3hmYV9vYmplY3QuJGRhdGFdID0gbmV3IF94ZmFfb2JqZWN0LlhtbE9iamVjdChuc0lkLCBjaGlsZC5uYW1lIHx8ICJyb290Iik7CiAgICAgICAgICBkYXRhTm9kZVtfeGZhX29iamVjdC4kYXBwZW5kQ2hpbGRdKGRhdGFDaGlsZCk7CiAgICAgICAgICB0aGlzLl9iaW5kRWxlbWVudChjaGlsZCwgZGF0YUNoaWxkKTsKICAgICAgICB9CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKCFjaGlsZFtfeGZhX29iamVjdC4kaXNCaW5kYWJsZV0oKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGxldCBnbG9iYWwgPSBmYWxzZTsKICAgICAgbGV0IHBpY3R1cmUgPSBudWxsOwogICAgICBsZXQgcmVmID0gbnVsbDsKICAgICAgbGV0IG1hdGNoID0gbnVsbDsKICAgICAgaWYgKGNoaWxkLmJpbmQpIHsKICAgICAgICBzd2l0Y2ggKGNoaWxkLmJpbmQubWF0Y2gpIHsKICAgICAgICAgIGNhc2UgIm5vbmUiOgogICAgICAgICAgICB0aGlzLl9zZXRBbmRCaW5kKGNoaWxkLCBkYXRhTm9kZSk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgY2FzZSAiZ2xvYmFsIjoKICAgICAgICAgICAgZ2xvYmFsID0gdHJ1ZTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICJkYXRhUmVmIjoKICAgICAgICAgICAgaWYgKCFjaGlsZC5iaW5kLnJlZikgewogICAgICAgICAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gcmVmIGlzIGVtcHR5IGluIG5vZGUgJHtjaGlsZFtfeGZhX29iamVjdC4kbm9kZU5hbWVdfS5gKTsKICAgICAgICAgICAgICB0aGlzLl9zZXRBbmRCaW5kKGNoaWxkLCBkYXRhTm9kZSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVmID0gY2hpbGQuYmluZC5yZWY7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmIChjaGlsZC5iaW5kLnBpY3R1cmUpIHsKICAgICAgICAgIHBpY3R1cmUgPSBjaGlsZC5iaW5kLnBpY3R1cmVbX3hmYV9vYmplY3QuJGNvbnRlbnRdOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBbbWluLCBtYXhdID0gdGhpcy5fZ2V0T2NjdXJJbmZvKGNoaWxkKTsKICAgICAgaWYgKHJlZikgewogICAgICAgIG1hdGNoID0gKDAsIF9zb20uc2VhcmNoTm9kZSkodGhpcy5yb290LCBkYXRhTm9kZSwgcmVmLCB0cnVlLCBmYWxzZSk7CiAgICAgICAgaWYgKG1hdGNoID09PSBudWxsKSB7CiAgICAgICAgICBtYXRjaCA9ICgwLCBfc29tLmNyZWF0ZURhdGFOb2RlKSh0aGlzLmRhdGEsIGRhdGFOb2RlLCByZWYpOwogICAgICAgICAgaWYgKCFtYXRjaCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh0aGlzLl9pc0NvbnN1bWVEYXRhKCkpIHsKICAgICAgICAgICAgbWF0Y2hbX3hmYV9vYmplY3QuJGNvbnN1bWVkXSA9IHRydWU7CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLl9zZXRBbmRCaW5kKGNoaWxkLCBtYXRjaCk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaWYgKHRoaXMuX2lzQ29uc3VtZURhdGEoKSkgewogICAgICAgICAgICBtYXRjaCA9IG1hdGNoLmZpbHRlcihub2RlID0+ICFub2RlW194ZmFfb2JqZWN0LiRjb25zdW1lZF0pOwogICAgICAgICAgfQogICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IG1heCkgewogICAgICAgICAgICBtYXRjaCA9IG1hdGNoLnNsaWNlKDAsIG1heCk7CiAgICAgICAgICB9IGVsc2UgaWYgKG1hdGNoLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgICBtYXRjaCA9IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobWF0Y2ggJiYgdGhpcy5faXNDb25zdW1lRGF0YSgpKSB7CiAgICAgICAgICAgIG1hdGNoLmZvckVhY2gobm9kZSA9PiB7CiAgICAgICAgICAgICAgbm9kZVtfeGZhX29iamVjdC4kY29uc3VtZWRdID0gdHJ1ZTsKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGlmICghY2hpbGQubmFtZSkgewogICAgICAgICAgdGhpcy5fc2V0QW5kQmluZChjaGlsZCwgZGF0YU5vZGUpOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmICh0aGlzLl9pc0NvbnN1bWVEYXRhKCkpIHsKICAgICAgICAgIGNvbnN0IG1hdGNoZXMgPSBbXTsKICAgICAgICAgIHdoaWxlIChtYXRjaGVzLmxlbmd0aCA8IG1heCkgewogICAgICAgICAgICBjb25zdCBmb3VuZCA9IHRoaXMuX2ZpbmREYXRhQnlOYW1lVG9Db25zdW1lKGNoaWxkLm5hbWUsIGNoaWxkW194ZmFfb2JqZWN0LiRoYXNTZXR0YWJsZVZhbHVlXSgpLCBkYXRhTm9kZSwgZ2xvYmFsKTsKICAgICAgICAgICAgaWYgKCFmb3VuZCkgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvdW5kW194ZmFfb2JqZWN0LiRjb25zdW1lZF0gPSB0cnVlOwogICAgICAgICAgICBtYXRjaGVzLnB1c2goZm91bmQpOwogICAgICAgICAgfQogICAgICAgICAgbWF0Y2ggPSBtYXRjaGVzLmxlbmd0aCA+IDAgPyBtYXRjaGVzIDogbnVsbDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbWF0Y2ggPSBkYXRhTm9kZVtfeGZhX29iamVjdC4kZ2V0UmVhbENoaWxkcmVuQnlOYW1lSXRdKGNoaWxkLm5hbWUsIGZhbHNlLCB0aGlzLmVtcHR5TWVyZ2UpLm5leHQoKS52YWx1ZTsKICAgICAgICAgIGlmICghbWF0Y2gpIHsKICAgICAgICAgICAgaWYgKG1pbiA9PT0gMCkgewogICAgICAgICAgICAgIHVzZWxlc3NOb2Rlcy5wdXNoKGNoaWxkKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBuc0lkID0gZGF0YU5vZGVbX3hmYV9vYmplY3QuJG5hbWVzcGFjZUlkXSA9PT0gTlNfREFUQVNFVFMgPyAtMSA6IGRhdGFOb2RlW194ZmFfb2JqZWN0LiRuYW1lc3BhY2VJZF07CiAgICAgICAgICAgIG1hdGNoID0gY2hpbGRbX3hmYV9vYmplY3QuJGRhdGFdID0gbmV3IF94ZmFfb2JqZWN0LlhtbE9iamVjdChuc0lkLCBjaGlsZC5uYW1lKTsKICAgICAgICAgICAgaWYgKHRoaXMuZW1wdHlNZXJnZSkgewogICAgICAgICAgICAgIG1hdGNoW194ZmFfb2JqZWN0LiRjb25zdW1lZF0gPSB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRhdGFOb2RlW194ZmFfb2JqZWN0LiRhcHBlbmRDaGlsZF0obWF0Y2gpOwogICAgICAgICAgICB0aGlzLl9zZXRBbmRCaW5kKGNoaWxkLCBtYXRjaCk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHRoaXMuZW1wdHlNZXJnZSkgewogICAgICAgICAgICBtYXRjaFtfeGZhX29iamVjdC4kY29uc3VtZWRdID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICAgIG1hdGNoID0gW21hdGNoXTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKG1hdGNoKSB7CiAgICAgICAgdGhpcy5fYmluZE9jY3VycmVuY2VzKGNoaWxkLCBtYXRjaCwgcGljdHVyZSk7CiAgICAgIH0gZWxzZSBpZiAobWluID4gMCkgewogICAgICAgIHRoaXMuX3NldEFuZEJpbmQoY2hpbGQsIGRhdGFOb2RlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB1c2VsZXNzTm9kZXMucHVzaChjaGlsZCk7CiAgICAgIH0KICAgIH0KICAgIHVzZWxlc3NOb2Rlcy5mb3JFYWNoKG5vZGUgPT4gbm9kZVtfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpW194ZmFfb2JqZWN0LiRyZW1vdmVDaGlsZF0obm9kZSkpOwogIH0KfQpleHBvcnRzLkJpbmRlciA9IEJpbmRlcjsKCi8qKiovIH0pLAovKiAyMTcgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlZhbHVlID0gZXhwb3J0cy5UZXh0ID0gZXhwb3J0cy5UZW1wbGF0ZU5hbWVzcGFjZSA9IGV4cG9ydHMuVGVtcGxhdGUgPSBleHBvcnRzLlNldFByb3BlcnR5ID0gZXhwb3J0cy5JdGVtcyA9IGV4cG9ydHMuRmllbGQgPSBleHBvcnRzLkJpbmRJdGVtcyA9IHZvaWQgMDsKdmFyIF94ZmFfb2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTIpOwp2YXIgX25hbWVzcGFjZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxNCk7CnZhciBfbGF5b3V0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTgpOwp2YXIgX2h0bWxfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxOSk7CnZhciBfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxMyk7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CnZhciBfZm9udHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIyMCk7CnZhciBfY29yZV91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMTM5KTsKdmFyIF9zb20gPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxNSk7CmNvbnN0IFRFTVBMQVRFX05TX0lEID0gX25hbWVzcGFjZXMuTmFtZXNwYWNlSWRzLnRlbXBsYXRlLmlkOwpjb25zdCBTVkdfTlMgPSAiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciOwpjb25zdCBNQVhfQVRURU1QVFNfRk9SX0xSVEJfTEFZT1VUID0gMjsKY29uc3QgTUFYX0VNUFRZX1BBR0VTID0gMzsKY29uc3QgREVGQVVMVF9UQUJfSU5ERVggPSA1MDAwOwpjb25zdCBIRUFESU5HX1BBVFRFUk4gPSAvXkgoXGQrKSQvOwpjb25zdCBNSU1FUyA9IG5ldyBTZXQoWyJpbWFnZS9naWYiLCAiaW1hZ2UvanBlZyIsICJpbWFnZS9qcGciLCAiaW1hZ2UvcGpwZWciLCAiaW1hZ2UvcG5nIiwgImltYWdlL2FwbmciLCAiaW1hZ2UveC1wbmciLCAiaW1hZ2UvYm1wIiwgImltYWdlL3gtbXMtYm1wIiwgImltYWdlL3RpZmYiLCAiaW1hZ2UvdGlmIiwgImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSJdKTsKY29uc3QgSU1BR0VTX0hFQURFUlMgPSBbW1sweDQyLCAweDRkXSwgImltYWdlL2JtcCJdLCBbWzB4ZmYsIDB4ZDgsIDB4ZmZdLCAiaW1hZ2UvanBlZyJdLCBbWzB4NDksIDB4NDksIDB4MmEsIDB4MDBdLCAiaW1hZ2UvdGlmZiJdLCBbWzB4NGQsIDB4NGQsIDB4MDAsIDB4MmFdLCAiaW1hZ2UvdGlmZiJdLCBbWzB4NDcsIDB4NDksIDB4NDYsIDB4MzgsIDB4MzksIDB4NjFdLCAiaW1hZ2UvZ2lmIl0sIFtbMHg4OSwgMHg1MCwgMHg0ZSwgMHg0NywgMHgwZCwgMHgwYSwgMHgxYSwgMHgwYV0sICJpbWFnZS9wbmciXV07CmZ1bmN0aW9uIGdldEJvcmRlckRpbXMobm9kZSkgewogIGlmICghbm9kZSB8fCAhbm9kZS5ib3JkZXIpIHsKICAgIHJldHVybiB7CiAgICAgIHc6IDAsCiAgICAgIGg6IDAKICAgIH07CiAgfQogIGNvbnN0IGJvcmRlckV4dHJhID0gbm9kZS5ib3JkZXJbX3hmYV9vYmplY3QuJGdldEV4dHJhXSgpOwogIGlmICghYm9yZGVyRXh0cmEpIHsKICAgIHJldHVybiB7CiAgICAgIHc6IDAsCiAgICAgIGg6IDAKICAgIH07CiAgfQogIHJldHVybiB7CiAgICB3OiBib3JkZXJFeHRyYS53aWR0aHNbMF0gKyBib3JkZXJFeHRyYS53aWR0aHNbMl0gKyBib3JkZXJFeHRyYS5pbnNldHNbMF0gKyBib3JkZXJFeHRyYS5pbnNldHNbMl0sCiAgICBoOiBib3JkZXJFeHRyYS53aWR0aHNbMV0gKyBib3JkZXJFeHRyYS53aWR0aHNbM10gKyBib3JkZXJFeHRyYS5pbnNldHNbMV0gKyBib3JkZXJFeHRyYS5pbnNldHNbM10KICB9Owp9CmZ1bmN0aW9uIGhhc01hcmdpbihub2RlKSB7CiAgcmV0dXJuIG5vZGUubWFyZ2luICYmIChub2RlLm1hcmdpbi50b3BJbnNldCB8fCBub2RlLm1hcmdpbi5yaWdodEluc2V0IHx8IG5vZGUubWFyZ2luLmJvdHRvbUluc2V0IHx8IG5vZGUubWFyZ2luLmxlZnRJbnNldCk7Cn0KZnVuY3Rpb24gX3NldFZhbHVlKHRlbXBsYXRlTm9kZSwgdmFsdWUpIHsKICBpZiAoIXRlbXBsYXRlTm9kZS52YWx1ZSkgewogICAgY29uc3Qgbm9kZVZhbHVlID0gbmV3IFZhbHVlKHt9KTsKICAgIHRlbXBsYXRlTm9kZVtfeGZhX29iamVjdC4kYXBwZW5kQ2hpbGRdKG5vZGVWYWx1ZSk7CiAgICB0ZW1wbGF0ZU5vZGUudmFsdWUgPSBub2RlVmFsdWU7CiAgfQogIHRlbXBsYXRlTm9kZS52YWx1ZVtfeGZhX29iamVjdC4kc2V0VmFsdWVdKHZhbHVlKTsKfQpmdW5jdGlvbiogZ2V0Q29udGFpbmVkQ2hpbGRyZW4obm9kZSkgewogIGZvciAoY29uc3QgY2hpbGQgb2Ygbm9kZVtfeGZhX29iamVjdC4kZ2V0Q2hpbGRyZW5dKCkpIHsKICAgIGlmIChjaGlsZCBpbnN0YW5jZW9mIFN1YmZvcm1TZXQpIHsKICAgICAgeWllbGQqIGNoaWxkW194ZmFfb2JqZWN0LiRnZXRDb250YWluZWRDaGlsZHJlbl0oKTsKICAgICAgY29udGludWU7CiAgICB9CiAgICB5aWVsZCBjaGlsZDsKICB9Cn0KZnVuY3Rpb24gaXNSZXF1aXJlZChub2RlKSB7CiAgcmV0dXJuIG5vZGUudmFsaWRhdGUgJiYgbm9kZS52YWxpZGF0ZS5udWxsVGVzdCA9PT0gImVycm9yIjsKfQpmdW5jdGlvbiBzZXRUYWJJbmRleChub2RlKSB7CiAgd2hpbGUgKG5vZGUpIHsKICAgIGlmICghbm9kZS50cmF2ZXJzYWwpIHsKICAgICAgbm9kZVtfeGZhX29iamVjdC4kdGFiSW5kZXhdID0gbm9kZVtfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpW194ZmFfb2JqZWN0LiR0YWJJbmRleF07CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChub2RlW194ZmFfb2JqZWN0LiR0YWJJbmRleF0pIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IG5leHQgPSBudWxsOwogICAgZm9yIChjb25zdCBjaGlsZCBvZiBub2RlLnRyYXZlcnNhbFtfeGZhX29iamVjdC4kZ2V0Q2hpbGRyZW5dKCkpIHsKICAgICAgaWYgKGNoaWxkLm9wZXJhdGlvbiA9PT0gIm5leHQiKSB7CiAgICAgICAgbmV4dCA9IGNoaWxkOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBpZiAoIW5leHQgfHwgIW5leHQucmVmKSB7CiAgICAgIG5vZGVbX3hmYV9vYmplY3QuJHRhYkluZGV4XSA9IG5vZGVbX3hmYV9vYmplY3QuJGdldFBhcmVudF0oKVtfeGZhX29iamVjdC4kdGFiSW5kZXhdOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCByb290ID0gbm9kZVtfeGZhX29iamVjdC4kZ2V0VGVtcGxhdGVSb290XSgpOwogICAgbm9kZVtfeGZhX29iamVjdC4kdGFiSW5kZXhdID0gKytyb290W194ZmFfb2JqZWN0LiR0YWJJbmRleF07CiAgICBjb25zdCByZWYgPSByb290W194ZmFfb2JqZWN0LiRzZWFyY2hOb2RlXShuZXh0LnJlZiwgbm9kZSk7CiAgICBpZiAoIXJlZikgewogICAgICByZXR1cm47CiAgICB9CiAgICBub2RlID0gcmVmWzBdOwogIH0KfQpmdW5jdGlvbiBhcHBseUFzc2lzdChvYmosIGF0dHJpYnV0ZXMpIHsKICBjb25zdCBhc3Npc3QgPSBvYmouYXNzaXN0OwogIGlmIChhc3Npc3QpIHsKICAgIGNvbnN0IGFzc2lzdFRpdGxlID0gYXNzaXN0W194ZmFfb2JqZWN0LiR0b0hUTUxdKCk7CiAgICBpZiAoYXNzaXN0VGl0bGUpIHsKICAgICAgYXR0cmlidXRlcy50aXRsZSA9IGFzc2lzdFRpdGxlOwogICAgfQogICAgY29uc3Qgcm9sZSA9IGFzc2lzdC5yb2xlOwogICAgY29uc3QgbWF0Y2ggPSByb2xlLm1hdGNoKEhFQURJTkdfUEFUVEVSTik7CiAgICBpZiAobWF0Y2gpIHsKICAgICAgY29uc3QgYXJpYVJvbGUgPSAiaGVhZGluZyI7CiAgICAgIGNvbnN0IGFyaWFMZXZlbCA9IG1hdGNoWzFdOwogICAgICBhdHRyaWJ1dGVzLnJvbGUgPSBhcmlhUm9sZTsKICAgICAgYXR0cmlidXRlc1siYXJpYS1sZXZlbCJdID0gYXJpYUxldmVsOwogICAgfQogIH0KICBpZiAob2JqLmxheW91dCA9PT0gInRhYmxlIikgewogICAgYXR0cmlidXRlcy5yb2xlID0gInRhYmxlIjsKICB9IGVsc2UgaWYgKG9iai5sYXlvdXQgPT09ICJyb3ciKSB7CiAgICBhdHRyaWJ1dGVzLnJvbGUgPSAicm93IjsKICB9IGVsc2UgewogICAgY29uc3QgcGFyZW50ID0gb2JqW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICBpZiAocGFyZW50LmxheW91dCA9PT0gInJvdyIpIHsKICAgICAgaWYgKHBhcmVudC5hc3Npc3QgJiYgcGFyZW50LmFzc2lzdC5yb2xlID09PSAiVEgiKSB7CiAgICAgICAgYXR0cmlidXRlcy5yb2xlID0gImNvbHVtbmhlYWRlciI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYXR0cmlidXRlcy5yb2xlID0gImNlbGwiOwogICAgICB9CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGFyaWFMYWJlbChvYmopIHsKICBpZiAoIW9iai5hc3Npc3QpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBjb25zdCBhc3Npc3QgPSBvYmouYXNzaXN0OwogIGlmIChhc3Npc3Quc3BlYWsgJiYgYXNzaXN0LnNwZWFrW194ZmFfb2JqZWN0LiRjb250ZW50XSAhPT0gIiIpIHsKICAgIHJldHVybiBhc3Npc3Quc3BlYWtbX3hmYV9vYmplY3QuJGNvbnRlbnRdOwogIH0KICBpZiAoYXNzaXN0LnRvb2xUaXApIHsKICAgIHJldHVybiBhc3Npc3QudG9vbFRpcFtfeGZhX29iamVjdC4kY29udGVudF07CiAgfQogIHJldHVybiBudWxsOwp9CmZ1bmN0aW9uIHZhbHVlVG9IdG1sKHZhbHVlKSB7CiAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgbmFtZTogImRpdiIsCiAgICBhdHRyaWJ1dGVzOiB7CiAgICAgIGNsYXNzOiBbInhmYVJpY2giXSwKICAgICAgc3R5bGU6IE9iamVjdC5jcmVhdGUobnVsbCkKICAgIH0sCiAgICBjaGlsZHJlbjogW3sKICAgICAgbmFtZTogInNwYW4iLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgc3R5bGU6IE9iamVjdC5jcmVhdGUobnVsbCkKICAgICAgfSwKICAgICAgdmFsdWUKICAgIH1dCiAgfSk7Cn0KZnVuY3Rpb24gc2V0Rmlyc3RVbnNwbGl0dGFibGUobm9kZSkgewogIGNvbnN0IHJvb3QgPSBub2RlW194ZmFfb2JqZWN0LiRnZXRUZW1wbGF0ZVJvb3RdKCk7CiAgaWYgKHJvb3RbX3hmYV9vYmplY3QuJGV4dHJhXS5maXJzdFVuc3BsaXR0YWJsZSA9PT0gbnVsbCkgewogICAgcm9vdFtfeGZhX29iamVjdC4kZXh0cmFdLmZpcnN0VW5zcGxpdHRhYmxlID0gbm9kZTsKICAgIHJvb3RbX3hmYV9vYmplY3QuJGV4dHJhXS5ub0xheW91dEZhaWx1cmUgPSB0cnVlOwogIH0KfQpmdW5jdGlvbiB1bnNldEZpcnN0VW5zcGxpdHRhYmxlKG5vZGUpIHsKICBjb25zdCByb290ID0gbm9kZVtfeGZhX29iamVjdC4kZ2V0VGVtcGxhdGVSb290XSgpOwogIGlmIChyb290W194ZmFfb2JqZWN0LiRleHRyYV0uZmlyc3RVbnNwbGl0dGFibGUgPT09IG5vZGUpIHsKICAgIHJvb3RbX3hmYV9vYmplY3QuJGV4dHJhXS5ub0xheW91dEZhaWx1cmUgPSBmYWxzZTsKICB9Cn0KZnVuY3Rpb24gaGFuZGxlQnJlYWsobm9kZSkgewogIGlmIChub2RlW194ZmFfb2JqZWN0LiRleHRyYV0pIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgbm9kZVtfeGZhX29iamVjdC4kZXh0cmFdID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBpZiAobm9kZS50YXJnZXRUeXBlID09PSAiYXV0byIpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgY29uc3Qgcm9vdCA9IG5vZGVbX3hmYV9vYmplY3QuJGdldFRlbXBsYXRlUm9vdF0oKTsKICBsZXQgdGFyZ2V0ID0gbnVsbDsKICBpZiAobm9kZS50YXJnZXQpIHsKICAgIHRhcmdldCA9IHJvb3RbX3hmYV9vYmplY3QuJHNlYXJjaE5vZGVdKG5vZGUudGFyZ2V0LCBub2RlW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCkpOwogICAgaWYgKCF0YXJnZXQpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgdGFyZ2V0ID0gdGFyZ2V0WzBdOwogIH0KICBjb25zdCB7CiAgICBjdXJyZW50UGFnZUFyZWEsCiAgICBjdXJyZW50Q29udGVudEFyZWEKICB9ID0gcm9vdFtfeGZhX29iamVjdC4kZXh0cmFdOwogIGlmIChub2RlLnRhcmdldFR5cGUgPT09ICJwYWdlQXJlYSIpIHsKICAgIGlmICghKHRhcmdldCBpbnN0YW5jZW9mIFBhZ2VBcmVhKSkgewogICAgICB0YXJnZXQgPSBudWxsOwogICAgfQogICAgaWYgKG5vZGUuc3RhcnROZXcpIHsKICAgICAgbm9kZVtfeGZhX29iamVjdC4kZXh0cmFdLnRhcmdldCA9IHRhcmdldCB8fCBjdXJyZW50UGFnZUFyZWE7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSBlbHNlIGlmICh0YXJnZXQgJiYgdGFyZ2V0ICE9PSBjdXJyZW50UGFnZUFyZWEpIHsKICAgICAgbm9kZVtfeGZhX29iamVjdC4kZXh0cmFdLnRhcmdldCA9IHRhcmdldDsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGlmICghKHRhcmdldCBpbnN0YW5jZW9mIENvbnRlbnRBcmVhKSkgewogICAgdGFyZ2V0ID0gbnVsbDsKICB9CiAgY29uc3QgcGFnZUFyZWEgPSB0YXJnZXQgJiYgdGFyZ2V0W194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgbGV0IGluZGV4OwogIGxldCBuZXh0UGFnZUFyZWEgPSBwYWdlQXJlYTsKICBpZiAobm9kZS5zdGFydE5ldykgewogICAgaWYgKHRhcmdldCkgewogICAgICBjb25zdCBjb250ZW50QXJlYXMgPSBwYWdlQXJlYS5jb250ZW50QXJlYS5jaGlsZHJlbjsKICAgICAgY29uc3QgaW5kZXhGb3JDdXJyZW50ID0gY29udGVudEFyZWFzLmluZGV4T2YoY3VycmVudENvbnRlbnRBcmVhKTsKICAgICAgY29uc3QgaW5kZXhGb3JUYXJnZXQgPSBjb250ZW50QXJlYXMuaW5kZXhPZih0YXJnZXQpOwogICAgICBpZiAoaW5kZXhGb3JDdXJyZW50ICE9PSAtMSAmJiBpbmRleEZvckN1cnJlbnQgPCBpbmRleEZvclRhcmdldCkgewogICAgICAgIG5leHRQYWdlQXJlYSA9IG51bGw7CiAgICAgIH0KICAgICAgaW5kZXggPSBpbmRleEZvclRhcmdldCAtIDE7CiAgICB9IGVsc2UgewogICAgICBpbmRleCA9IGN1cnJlbnRQYWdlQXJlYS5jb250ZW50QXJlYS5jaGlsZHJlbi5pbmRleE9mKGN1cnJlbnRDb250ZW50QXJlYSk7CiAgICB9CiAgfSBlbHNlIGlmICh0YXJnZXQgJiYgdGFyZ2V0ICE9PSBjdXJyZW50Q29udGVudEFyZWEpIHsKICAgIGNvbnN0IGNvbnRlbnRBcmVhcyA9IHBhZ2VBcmVhLmNvbnRlbnRBcmVhLmNoaWxkcmVuOwogICAgaW5kZXggPSBjb250ZW50QXJlYXMuaW5kZXhPZih0YXJnZXQpIC0gMTsKICAgIG5leHRQYWdlQXJlYSA9IHBhZ2VBcmVhID09PSBjdXJyZW50UGFnZUFyZWEgPyBudWxsIDogcGFnZUFyZWE7CiAgfSBlbHNlIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgbm9kZVtfeGZhX29iamVjdC4kZXh0cmFdLnRhcmdldCA9IG5leHRQYWdlQXJlYTsKICBub2RlW194ZmFfb2JqZWN0LiRleHRyYV0uaW5kZXggPSBpbmRleDsKICByZXR1cm4gdHJ1ZTsKfQpmdW5jdGlvbiBoYW5kbGVPdmVyZmxvdyhub2RlLCBleHRyYU5vZGUsIHNwYWNlKSB7CiAgY29uc3Qgcm9vdCA9IG5vZGVbX3hmYV9vYmplY3QuJGdldFRlbXBsYXRlUm9vdF0oKTsKICBjb25zdCBzYXZlZCA9IHJvb3RbX3hmYV9vYmplY3QuJGV4dHJhXS5ub0xheW91dEZhaWx1cmU7CiAgY29uc3Qgc2F2ZWRNZXRob2QgPSBleHRyYU5vZGVbX3hmYV9vYmplY3QuJGdldFN1YmZvcm1QYXJlbnRdOwogIGV4dHJhTm9kZVtfeGZhX29iamVjdC4kZ2V0U3ViZm9ybVBhcmVudF0gPSAoKSA9PiBub2RlOwogIHJvb3RbX3hmYV9vYmplY3QuJGV4dHJhXS5ub0xheW91dEZhaWx1cmUgPSB0cnVlOwogIGNvbnN0IHJlcyA9IGV4dHJhTm9kZVtfeGZhX29iamVjdC4kdG9IVE1MXShzcGFjZSk7CiAgbm9kZVtfeGZhX29iamVjdC4kYWRkSFRNTF0ocmVzLmh0bWwsIHJlcy5iYm94KTsKICByb290W194ZmFfb2JqZWN0LiRleHRyYV0ubm9MYXlvdXRGYWlsdXJlID0gc2F2ZWQ7CiAgZXh0cmFOb2RlW194ZmFfb2JqZWN0LiRnZXRTdWJmb3JtUGFyZW50XSA9IHNhdmVkTWV0aG9kOwp9CmNsYXNzIEFwcGVhcmFuY2VGaWx0ZXIgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYXBwZWFyYW5jZUZpbHRlciIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgQXJjIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImFyYyIsIHRydWUpOwogICAgdGhpcy5jaXJjdWxhciA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmNpcmN1bGFyLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy5oYW5kID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuaGFuZCwgWyJldmVuIiwgImxlZnQiLCAicmlnaHQiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMuc3RhcnRBbmdsZSA9ICgwLCBfdXRpbHMuZ2V0RmxvYXQpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5zdGFydEFuZ2xlLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHRydWUKICAgIH0pOwogICAgdGhpcy5zd2VlcEFuZ2xlID0gKDAsIF91dGlscy5nZXRGbG9hdCkoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnN3ZWVwQW5nbGUsCiAgICAgIGRlZmF1bHRWYWx1ZTogMzYwLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmVkZ2UgPSBudWxsOwogICAgdGhpcy5maWxsID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKCkgewogICAgY29uc3QgZWRnZSA9IHRoaXMuZWRnZSB8fCBuZXcgRWRnZSh7fSk7CiAgICBjb25zdCBlZGdlU3R5bGUgPSBlZGdlW194ZmFfb2JqZWN0LiR0b1N0eWxlXSgpOwogICAgY29uc3Qgc3R5bGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgaWYgKHRoaXMuZmlsbCAmJiB0aGlzLmZpbGwucHJlc2VuY2UgPT09ICJ2aXNpYmxlIikgewogICAgICBPYmplY3QuYXNzaWduKHN0eWxlLCB0aGlzLmZpbGxbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCkpOwogICAgfSBlbHNlIHsKICAgICAgc3R5bGUuZmlsbCA9ICJ0cmFuc3BhcmVudCI7CiAgICB9CiAgICBzdHlsZS5zdHJva2VXaWR0aCA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKGVkZ2UucHJlc2VuY2UgPT09ICJ2aXNpYmxlIiA/IGVkZ2UudGhpY2tuZXNzIDogMCk7CiAgICBzdHlsZS5zdHJva2UgPSBlZGdlU3R5bGUuY29sb3I7CiAgICBsZXQgYXJjOwogICAgY29uc3QgYXR0cmlidXRlcyA9IHsKICAgICAgeG1sbnM6IFNWR19OUywKICAgICAgc3R5bGU6IHsKICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgIGhlaWdodDogIjEwMCUiLAogICAgICAgIG92ZXJmbG93OiAidmlzaWJsZSIKICAgICAgfQogICAgfTsKICAgIGlmICh0aGlzLnN3ZWVwQW5nbGUgPT09IDM2MCkgewogICAgICBhcmMgPSB7CiAgICAgICAgbmFtZTogImVsbGlwc2UiLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIHhtbG5zOiBTVkdfTlMsCiAgICAgICAgICBjeDogIjUwJSIsCiAgICAgICAgICBjeTogIjUwJSIsCiAgICAgICAgICByeDogIjUwJSIsCiAgICAgICAgICByeTogIjUwJSIsCiAgICAgICAgICBzdHlsZQogICAgICAgIH0KICAgICAgfTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IHN0YXJ0QW5nbGUgPSB0aGlzLnN0YXJ0QW5nbGUgKiBNYXRoLlBJIC8gMTgwOwogICAgICBjb25zdCBzd2VlcEFuZ2xlID0gdGhpcy5zd2VlcEFuZ2xlICogTWF0aC5QSSAvIDE4MDsKICAgICAgY29uc3QgbGFyZ2VBcmMgPSB0aGlzLnN3ZWVwQW5nbGUgPiAxODAgPyAxIDogMDsKICAgICAgY29uc3QgW3gxLCB5MSwgeDIsIHkyXSA9IFs1MCAqICgxICsgTWF0aC5jb3Moc3RhcnRBbmdsZSkpLCA1MCAqICgxIC0gTWF0aC5zaW4oc3RhcnRBbmdsZSkpLCA1MCAqICgxICsgTWF0aC5jb3Moc3RhcnRBbmdsZSArIHN3ZWVwQW5nbGUpKSwgNTAgKiAoMSAtIE1hdGguc2luKHN0YXJ0QW5nbGUgKyBzd2VlcEFuZ2xlKSldOwogICAgICBhcmMgPSB7CiAgICAgICAgbmFtZTogInBhdGgiLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIHhtbG5zOiBTVkdfTlMsCiAgICAgICAgICBkOiBgTSAke3gxfSAke3kxfSBBIDUwIDUwIDAgJHtsYXJnZUFyY30gMCAke3gyfSAke3kyfWAsCiAgICAgICAgICB2ZWN0b3JFZmZlY3Q6ICJub24tc2NhbGluZy1zdHJva2UiLAogICAgICAgICAgc3R5bGUKICAgICAgICB9CiAgICAgIH07CiAgICAgIE9iamVjdC5hc3NpZ24oYXR0cmlidXRlcywgewogICAgICAgIHZpZXdCb3g6ICIwIDAgMTAwIDEwMCIsCiAgICAgICAgcHJlc2VydmVBc3BlY3RSYXRpbzogIm5vbmUiCiAgICAgIH0pOwogICAgfQogICAgY29uc3Qgc3ZnID0gewogICAgICBuYW1lOiAic3ZnIiwKICAgICAgY2hpbGRyZW46IFthcmNdLAogICAgICBhdHRyaWJ1dGVzCiAgICB9OwogICAgY29uc3QgcGFyZW50ID0gdGhpc1tfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICBpZiAoaGFzTWFyZ2luKHBhcmVudCkpIHsKICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICAgIG5hbWU6ICJkaXYiLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIHN0eWxlOiB7CiAgICAgICAgICAgIGRpc3BsYXk6ICJpbmxpbmUiLAogICAgICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgICAgICBoZWlnaHQ6ICIxMDAlIgogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgY2hpbGRyZW46IFtzdmddCiAgICAgIH0pOwogICAgfQogICAgc3ZnLmF0dHJpYnV0ZXMuc3R5bGUucG9zaXRpb24gPSAiYWJzb2x1dGUiOwogICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3Moc3ZnKTsKICB9Cn0KY2xhc3MgQXJlYSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJhcmVhIiwgdHJ1ZSk7CiAgICB0aGlzLmNvbFNwYW4gPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5jb2xTcGFuLAogICAgICBkZWZhdWx0VmFsdWU6IDEsCiAgICAgIHZhbGlkYXRlOiBuID0+IG4gPj0gMSB8fCBuID09PSAtMQogICAgfSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucmVsZXZhbnQgPSAoMCwgX3V0aWxzLmdldFJlbGV2YW50KShhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnggPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLngsICIwcHQiKTsKICAgIHRoaXMueSA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMueSwgIjBwdCIpOwogICAgdGhpcy5kZXNjID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMuYXJlYSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kcmF3ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4T2JqZWN0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4Y2xHcm91cCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5maWVsZCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zdWJmb3JtID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1YmZvcm1TZXQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9CiAgKltfeGZhX29iamVjdC4kZ2V0Q29udGFpbmVkQ2hpbGRyZW5dKCkgewogICAgeWllbGQqIGdldENvbnRhaW5lZENoaWxkcmVuKHRoaXMpOwogIH0KICBbX3hmYV9vYmplY3QuJGlzVHJhbnNwYXJlbnRdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIFtfeGZhX29iamVjdC4kaXNCaW5kYWJsZV0oKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgW194ZmFfb2JqZWN0LiRhZGRIVE1MXShodG1sLCBiYm94KSB7CiAgICBjb25zdCBbeCwgeSwgdywgaF0gPSBiYm94OwogICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLndpZHRoID0gTWF0aC5tYXgodGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLndpZHRoLCB4ICsgdyk7CiAgICB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uaGVpZ2h0ID0gTWF0aC5tYXgodGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmhlaWdodCwgeSArIGgpOwogICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmNoaWxkcmVuLnB1c2goaHRtbCk7CiAgfQogIFtfeGZhX29iamVjdC4kZ2V0QXZhaWxhYmxlU3BhY2VdKCkgewogICAgcmV0dXJuIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5hdmFpbGFibGVTcGFjZTsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCBzdHlsZSA9ICgwLCBfaHRtbF91dGlscy50b1N0eWxlKSh0aGlzLCAicG9zaXRpb24iKTsKICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSB7CiAgICAgIHN0eWxlLAogICAgICBpZDogdGhpc1tfeGZhX29iamVjdC4kdWlkXSwKICAgICAgY2xhc3M6IFsieGZhQXJlYSJdCiAgICB9OwogICAgaWYgKCgwLCBfaHRtbF91dGlscy5pc1ByaW50T25seSkodGhpcykpIHsKICAgICAgYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFQcmludE9ubHkiKTsKICAgIH0KICAgIGlmICh0aGlzLm5hbWUpIHsKICAgICAgYXR0cmlidXRlcy54ZmFOYW1lID0gdGhpcy5uYW1lOwogICAgfQogICAgY29uc3QgY2hpbGRyZW4gPSBbXTsKICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXSA9IHsKICAgICAgY2hpbGRyZW4sCiAgICAgIHdpZHRoOiAwLAogICAgICBoZWlnaHQ6IDAsCiAgICAgIGF2YWlsYWJsZVNwYWNlCiAgICB9OwogICAgY29uc3QgcmVzdWx0ID0gdGhpc1tfeGZhX29iamVjdC4kY2hpbGRyZW5Ub0hUTUxdKHsKICAgICAgZmlsdGVyOiBuZXcgU2V0KFsiYXJlYSIsICJkcmF3IiwgImZpZWxkIiwgImV4Y2xHcm91cCIsICJzdWJmb3JtIiwgInN1YmZvcm1TZXQiXSksCiAgICAgIGluY2x1ZGU6IHRydWUKICAgIH0pOwogICAgaWYgKCFyZXN1bHQuc3VjY2VzcykgewogICAgICBpZiAocmVzdWx0LmlzQnJlYWsoKSkgewogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KICAgICAgZGVsZXRlIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXTsKICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LkZBSUxVUkU7CiAgICB9CiAgICBzdHlsZS53aWR0aCA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS53aWR0aCk7CiAgICBzdHlsZS5oZWlnaHQgPSAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSh0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uaGVpZ2h0KTsKICAgIGNvbnN0IGh0bWwgPSB7CiAgICAgIG5hbWU6ICJkaXYiLAogICAgICBhdHRyaWJ1dGVzLAogICAgICBjaGlsZHJlbgogICAgfTsKICAgIGNvbnN0IGJib3ggPSBbdGhpcy54LCB0aGlzLnksIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS53aWR0aCwgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmhlaWdodF07CiAgICBkZWxldGUgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdOwogICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3MoaHRtbCwgYmJveCk7CiAgfQp9CmNsYXNzIEFzc2lzdCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJhc3Npc3QiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5yb2xlID0gYXR0cmlidXRlcy5yb2xlIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuc3BlYWsgPSBudWxsOwogICAgdGhpcy50b29sVGlwID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKCkgewogICAgcmV0dXJuIHRoaXMudG9vbFRpcCAmJiB0aGlzLnRvb2xUaXBbX3hmYV9vYmplY3QuJGNvbnRlbnRdID8gdGhpcy50b29sVGlwW194ZmFfb2JqZWN0LiRjb250ZW50XSA6IG51bGw7CiAgfQp9CmNsYXNzIEJhcmNvZGUgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYmFyY29kZSIsIHRydWUpOwogICAgdGhpcy5jaGFyRW5jb2RpbmcgPSAoMCwgX3V0aWxzLmdldEtleXdvcmQpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5jaGFyRW5jb2RpbmcgPyBhdHRyaWJ1dGVzLmNoYXJFbmNvZGluZy50b0xvd2VyQ2FzZSgpIDogIiIsCiAgICAgIGRlZmF1bHRWYWx1ZTogIiIsCiAgICAgIHZhbGlkYXRlOiBrID0+IFsidXRmLTgiLCAiYmlnLWZpdmUiLCAiZm9udHNwZWNpZmljIiwgImdiayIsICJnYi0xODAzMCIsICJnYi0yMzEyIiwgImtzYy01NjAxIiwgIm5vbmUiLCAic2hpZnQtamlzIiwgInVjcy0yIiwgInV0Zi0xNiJdLmluY2x1ZGVzKGspIHx8IGsubWF0Y2goL2lzby04ODU5LVxkezJ9LykKICAgIH0pOwogICAgdGhpcy5jaGVja3N1bSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmNoZWNrc3VtLCBbIm5vbmUiLCAiMW1vZDEwIiwgIjFtb2QxMF8xbW9kMTEiLCAiMm1vZDEwIiwgImF1dG8iXSk7CiAgICB0aGlzLmRhdGFDb2x1bW5Db3VudCA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmRhdGFDb2x1bW5Db3VudCwKICAgICAgZGVmYXVsdFZhbHVlOiAtMSwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwCiAgICB9KTsKICAgIHRoaXMuZGF0YUxlbmd0aCA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmRhdGFMZW5ndGgsCiAgICAgIGRlZmF1bHRWYWx1ZTogLTEsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMAogICAgfSk7CiAgICB0aGlzLmRhdGFQcmVwID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuZGF0YVByZXAsIFsibm9uZSIsICJmbGF0ZUNvbXByZXNzIl0pOwogICAgdGhpcy5kYXRhUm93Q291bnQgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5kYXRhUm93Q291bnQsCiAgICAgIGRlZmF1bHRWYWx1ZTogLTEsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMAogICAgfSk7CiAgICB0aGlzLmVuZENoYXIgPSBhdHRyaWJ1dGVzLmVuZENoYXIgfHwgIiI7CiAgICB0aGlzLmVycm9yQ29ycmVjdGlvbkxldmVsID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZXJyb3JDb3JyZWN0aW9uTGV2ZWwsCiAgICAgIGRlZmF1bHRWYWx1ZTogLTEsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMCAmJiB4IDw9IDgKICAgIH0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm1vZHVsZUhlaWdodCA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMubW9kdWxlSGVpZ2h0LCAiNW1tIik7CiAgICB0aGlzLm1vZHVsZVdpZHRoID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5tb2R1bGVXaWR0aCwgIjAuMjVtbSIpOwogICAgdGhpcy5wcmludENoZWNrRGlnaXQgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5wcmludENoZWNrRGlnaXQsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLnJvd0NvbHVtblJhdGlvID0gKDAsIF91dGlscy5nZXRSYXRpbykoYXR0cmlidXRlcy5yb3dDb2x1bW5SYXRpbyk7CiAgICB0aGlzLnN0YXJ0Q2hhciA9IGF0dHJpYnV0ZXMuc3RhcnRDaGFyIHx8ICIiOwogICAgdGhpcy50ZXh0TG9jYXRpb24gPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy50ZXh0TG9jYXRpb24sIFsiYmVsb3ciLCAiYWJvdmUiLCAiYWJvdmVFbWJlZGRlZCIsICJiZWxvd0VtYmVkZGVkIiwgIm5vbmUiXSk7CiAgICB0aGlzLnRydW5jYXRlID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMudHJ1bmNhdGUsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLnR5cGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy50eXBlID8gYXR0cmlidXRlcy50eXBlLnRvTG93ZXJDYXNlKCkgOiAiIiwgWyJhenRlYyIsICJjb2RhYmFyIiwgImNvZGUyb2Y1aW5kdXN0cmlhbCIsICJjb2RlMm9mNWludGVybGVhdmVkIiwgImNvZGUyb2Y1bWF0cml4IiwgImNvZGUyb2Y1c3RhbmRhcmQiLCAiY29kZTNvZjkiLCAiY29kZTNvZjlleHRlbmRlZCIsICJjb2RlMTEiLCAiY29kZTQ5IiwgImNvZGU5MyIsICJjb2RlMTI4IiwgImNvZGUxMjhhIiwgImNvZGUxMjhiIiwgImNvZGUxMjhjIiwgImNvZGUxMjhzc2NjIiwgImRhdGFtYXRyaXgiLCAiZWFuOCIsICJlYW44YWRkMiIsICJlYW44YWRkNSIsICJlYW4xMyIsICJlYW4xM2FkZDIiLCAiZWFuMTNhZGQ1IiwgImVhbjEzcHdjZCIsICJmaW0iLCAibG9nbWFycyIsICJtYXhpY29kZSIsICJtc2kiLCAicGRmNDE3IiwgInBkZjQxN21hY3JvIiwgInBsZXNzZXkiLCAicG9zdGF1c2N1c3QyIiwgInBvc3RhdXNjdXN0MyIsICJwb3N0YXVzcmVwbHlwYWlkIiwgInBvc3RhdXNzdGFuZGFyZCIsICJwb3N0dWtybTRzY2MiLCAicG9zdHVzZHBiYyIsICJwb3N0dXNpbWIiLCAicG9zdHVzc3RhbmRhcmQiLCAicG9zdHVzNXppcCIsICJxcmNvZGUiLCAicmZpZCIsICJyc3MxNCIsICJyc3MxNGV4cGFuZGVkIiwgInJzczE0bGltaXRlZCIsICJyc3MxNHN0YWNrZWQiLCAicnNzMTRzdGFja2Vkb21uaSIsICJyc3MxNHRydW5jYXRlZCIsICJ0ZWxlcGVuIiwgInVjYzEyOCIsICJ1Y2MxMjhyYW5kb20iLCAidWNjMTI4c3NjYyIsICJ1cGNhIiwgInVwY2FhZGQyIiwgInVwY2FhZGQ1IiwgInVwY2Fwd2NkIiwgInVwY2UiLCAidXBjZWFkZDIiLCAidXBjZWFkZDUiLCAidXBjZWFuMiIsICJ1cGNlYW41IiwgInVwc21heGljb2RlIl0pOwogICAgdGhpcy51cHNNb2RlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMudXBzTW9kZSwgWyJ1c0NhcnJpZXIiLCAiaW50ZXJuYXRpb25hbENhcnJpZXIiLCAic2VjdXJlU3ltYm9sIiwgInN0YW5kYXJkU3ltYm9sIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMud2lkZU5hcnJvd1JhdGlvID0gKDAsIF91dGlscy5nZXRSYXRpbykoYXR0cmlidXRlcy53aWRlTmFycm93UmF0aW8pOwogICAgdGhpcy5lbmNyeXB0ID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9Cn0KY2xhc3MgQmluZCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJiaW5kIiwgdHJ1ZSk7CiAgICB0aGlzLm1hdGNoID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMubWF0Y2gsIFsib25jZSIsICJkYXRhUmVmIiwgImdsb2JhbCIsICJub25lIl0pOwogICAgdGhpcy5yZWYgPSBhdHRyaWJ1dGVzLnJlZiB8fCAiIjsKICAgIHRoaXMucGljdHVyZSA9IG51bGw7CiAgfQp9CmNsYXNzIEJpbmRJdGVtcyBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJiaW5kSXRlbXMiKTsKICAgIHRoaXMuY29ubmVjdGlvbiA9IGF0dHJpYnV0ZXMuY29ubmVjdGlvbiB8fCAiIjsKICAgIHRoaXMubGFiZWxSZWYgPSBhdHRyaWJ1dGVzLmxhYmVsUmVmIHx8ICIiOwogICAgdGhpcy5yZWYgPSBhdHRyaWJ1dGVzLnJlZiB8fCAiIjsKICAgIHRoaXMudmFsdWVSZWYgPSBhdHRyaWJ1dGVzLnZhbHVlUmVmIHx8ICIiOwogIH0KfQpleHBvcnRzLkJpbmRJdGVtcyA9IEJpbmRJdGVtczsKY2xhc3MgQm9va2VuZCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJib29rZW5kIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubGVhZGVyID0gYXR0cmlidXRlcy5sZWFkZXIgfHwgIiI7CiAgICB0aGlzLnRyYWlsZXIgPSBhdHRyaWJ1dGVzLnRyYWlsZXIgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBCb29sZWFuRWxlbWVudCBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImJvb2xlYW4iKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gdmFsdWVUb0h0bWwodGhpc1tfeGZhX29iamVjdC4kY29udGVudF0gPT09IDEgPyAiMSIgOiAiMCIpOwogIH0KfQpjbGFzcyBCb3JkZXIgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYm9yZGVyIiwgdHJ1ZSk7CiAgICB0aGlzLmJyZWFrID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuYnJlYWssIFsiY2xvc2UiLCAib3BlbiJdKTsKICAgIHRoaXMuaGFuZCA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmhhbmQsIFsiZXZlbiIsICJsZWZ0IiwgInJpZ2h0Il0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnByZXNlbmNlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMucHJlc2VuY2UsIFsidmlzaWJsZSIsICJoaWRkZW4iLCAiaW5hY3RpdmUiLCAiaW52aXNpYmxlIl0pOwogICAgdGhpcy5yZWxldmFudCA9ICgwLCBfdXRpbHMuZ2V0UmVsZXZhbnQpKGF0dHJpYnV0ZXMucmVsZXZhbnQpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY29ybmVyID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KDQpOwogICAgdGhpcy5lZGdlID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KDQpOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5maWxsID0gbnVsbDsKICAgIHRoaXMubWFyZ2luID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiRnZXRFeHRyYV0oKSB7CiAgICBpZiAoIXRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXSkgewogICAgICBjb25zdCBlZGdlcyA9IHRoaXMuZWRnZS5jaGlsZHJlbi5zbGljZSgpOwogICAgICBpZiAoZWRnZXMubGVuZ3RoIDwgNCkgewogICAgICAgIGNvbnN0IGRlZmF1bHRFZGdlID0gZWRnZXMuYXQoLTEpIHx8IG5ldyBFZGdlKHt9KTsKICAgICAgICBmb3IgKGxldCBpID0gZWRnZXMubGVuZ3RoOyBpIDwgNDsgaSsrKSB7CiAgICAgICAgICBlZGdlcy5wdXNoKGRlZmF1bHRFZGdlKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3Qgd2lkdGhzID0gZWRnZXMubWFwKGVkZ2UgPT4gZWRnZS50aGlja25lc3MpOwogICAgICBjb25zdCBpbnNldHMgPSBbMCwgMCwgMCwgMF07CiAgICAgIGlmICh0aGlzLm1hcmdpbikgewogICAgICAgIGluc2V0c1swXSA9IHRoaXMubWFyZ2luLnRvcEluc2V0OwogICAgICAgIGluc2V0c1sxXSA9IHRoaXMubWFyZ2luLnJpZ2h0SW5zZXQ7CiAgICAgICAgaW5zZXRzWzJdID0gdGhpcy5tYXJnaW4uYm90dG9tSW5zZXQ7CiAgICAgICAgaW5zZXRzWzNdID0gdGhpcy5tYXJnaW4ubGVmdEluc2V0OwogICAgICB9CiAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXSA9IHsKICAgICAgICB3aWR0aHMsCiAgICAgICAgaW5zZXRzLAogICAgICAgIGVkZ2VzCiAgICAgIH07CiAgICB9CiAgICByZXR1cm4gdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdOwogIH0KICBbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCkgewogICAgY29uc3QgewogICAgICBlZGdlcwogICAgfSA9IHRoaXNbX3hmYV9vYmplY3QuJGdldEV4dHJhXSgpOwogICAgY29uc3QgZWRnZVN0eWxlcyA9IGVkZ2VzLm1hcChub2RlID0+IHsKICAgICAgY29uc3Qgc3R5bGUgPSBub2RlW194ZmFfb2JqZWN0LiR0b1N0eWxlXSgpOwogICAgICBzdHlsZS5jb2xvciA9IHN0eWxlLmNvbG9yIHx8ICIjMDAwMDAwIjsKICAgICAgcmV0dXJuIHN0eWxlOwogICAgfSk7CiAgICBjb25zdCBzdHlsZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBpZiAodGhpcy5tYXJnaW4pIHsKICAgICAgT2JqZWN0LmFzc2lnbihzdHlsZSwgdGhpcy5tYXJnaW5bX3hmYV9vYmplY3QuJHRvU3R5bGVdKCkpOwogICAgfQogICAgaWYgKHRoaXMuZmlsbCAmJiB0aGlzLmZpbGwucHJlc2VuY2UgPT09ICJ2aXNpYmxlIikgewogICAgICBPYmplY3QuYXNzaWduKHN0eWxlLCB0aGlzLmZpbGxbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCkpOwogICAgfQogICAgaWYgKHRoaXMuY29ybmVyLmNoaWxkcmVuLnNvbWUobm9kZSA9PiBub2RlLnJhZGl1cyAhPT0gMCkpIHsKICAgICAgY29uc3QgY29ybmVyU3R5bGVzID0gdGhpcy5jb3JuZXIuY2hpbGRyZW4ubWFwKG5vZGUgPT4gbm9kZVtfeGZhX29iamVjdC4kdG9TdHlsZV0oKSk7CiAgICAgIGlmIChjb3JuZXJTdHlsZXMubGVuZ3RoID09PSAyIHx8IGNvcm5lclN0eWxlcy5sZW5ndGggPT09IDMpIHsKICAgICAgICBjb25zdCBsYXN0ID0gY29ybmVyU3R5bGVzLmF0KC0xKTsKICAgICAgICBmb3IgKGxldCBpID0gY29ybmVyU3R5bGVzLmxlbmd0aDsgaSA8IDQ7IGkrKykgewogICAgICAgICAgY29ybmVyU3R5bGVzLnB1c2gobGFzdCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHN0eWxlLmJvcmRlclJhZGl1cyA9IGNvcm5lclN0eWxlcy5tYXAocyA9PiBzLnJhZGl1cykuam9pbigiICIpOwogICAgfQogICAgc3dpdGNoICh0aGlzLnByZXNlbmNlKSB7CiAgICAgIGNhc2UgImludmlzaWJsZSI6CiAgICAgIGNhc2UgImhpZGRlbiI6CiAgICAgICAgc3R5bGUuYm9yZGVyU3R5bGUgPSAiIjsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiaW5hY3RpdmUiOgogICAgICAgIHN0eWxlLmJvcmRlclN0eWxlID0gIm5vbmUiOwogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHN0eWxlLmJvcmRlclN0eWxlID0gZWRnZVN0eWxlcy5tYXAocyA9PiBzLnN0eWxlKS5qb2luKCIgIik7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBzdHlsZS5ib3JkZXJXaWR0aCA9IGVkZ2VTdHlsZXMubWFwKHMgPT4gcy53aWR0aCkuam9pbigiICIpOwogICAgc3R5bGUuYm9yZGVyQ29sb3IgPSBlZGdlU3R5bGVzLm1hcChzID0+IHMuY29sb3IpLmpvaW4oIiAiKTsKICAgIHJldHVybiBzdHlsZTsKICB9Cn0KY2xhc3MgQnJlYWsgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYnJlYWsiLCB0cnVlKTsKICAgIHRoaXMuYWZ0ZXIgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5hZnRlciwgWyJhdXRvIiwgImNvbnRlbnRBcmVhIiwgInBhZ2VBcmVhIiwgInBhZ2VFdmVuIiwgInBhZ2VPZGQiXSk7CiAgICB0aGlzLmFmdGVyVGFyZ2V0ID0gYXR0cmlidXRlcy5hZnRlclRhcmdldCB8fCAiIjsKICAgIHRoaXMuYmVmb3JlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuYmVmb3JlLCBbImF1dG8iLCAiY29udGVudEFyZWEiLCAicGFnZUFyZWEiLCAicGFnZUV2ZW4iLCAicGFnZU9kZCJdKTsKICAgIHRoaXMuYmVmb3JlVGFyZ2V0ID0gYXR0cmlidXRlcy5iZWZvcmVUYXJnZXQgfHwgIiI7CiAgICB0aGlzLmJvb2tlbmRMZWFkZXIgPSBhdHRyaWJ1dGVzLmJvb2tlbmRMZWFkZXIgfHwgIiI7CiAgICB0aGlzLmJvb2tlbmRUcmFpbGVyID0gYXR0cmlidXRlcy5ib29rZW5kVHJhaWxlciB8fCAiIjsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5vdmVyZmxvd0xlYWRlciA9IGF0dHJpYnV0ZXMub3ZlcmZsb3dMZWFkZXIgfHwgIiI7CiAgICB0aGlzLm92ZXJmbG93VGFyZ2V0ID0gYXR0cmlidXRlcy5vdmVyZmxvd1RhcmdldCB8fCAiIjsKICAgIHRoaXMub3ZlcmZsb3dUcmFpbGVyID0gYXR0cmlidXRlcy5vdmVyZmxvd1RyYWlsZXIgfHwgIiI7CiAgICB0aGlzLnN0YXJ0TmV3ID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuc3RhcnROZXcsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KfQpjbGFzcyBCcmVha0FmdGVyIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImJyZWFrQWZ0ZXIiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5sZWFkZXIgPSBhdHRyaWJ1dGVzLmxlYWRlciB8fCAiIjsKICAgIHRoaXMuc3RhcnROZXcgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5zdGFydE5ldywKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMudGFyZ2V0ID0gYXR0cmlidXRlcy50YXJnZXQgfHwgIiI7CiAgICB0aGlzLnRhcmdldFR5cGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy50YXJnZXRUeXBlLCBbImF1dG8iLCAiY29udGVudEFyZWEiLCAicGFnZUFyZWEiXSk7CiAgICB0aGlzLnRyYWlsZXIgPSBhdHRyaWJ1dGVzLnRyYWlsZXIgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5zY3JpcHQgPSBudWxsOwogIH0KfQpjbGFzcyBCcmVha0JlZm9yZSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJicmVha0JlZm9yZSIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxlYWRlciA9IGF0dHJpYnV0ZXMubGVhZGVyIHx8ICIiOwogICAgdGhpcy5zdGFydE5ldyA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnN0YXJ0TmV3LAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy50YXJnZXQgPSBhdHRyaWJ1dGVzLnRhcmdldCB8fCAiIjsKICAgIHRoaXMudGFyZ2V0VHlwZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnRhcmdldFR5cGUsIFsiYXV0byIsICJjb250ZW50QXJlYSIsICJwYWdlQXJlYSJdKTsKICAgIHRoaXMudHJhaWxlciA9IGF0dHJpYnV0ZXMudHJhaWxlciB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnNjcmlwdCA9IG51bGw7CiAgfQogIFtfeGZhX29iamVjdC4kdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdID0ge307CiAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuRkFJTFVSRTsKICB9Cn0KY2xhc3MgQnV0dG9uIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImJ1dHRvbiIsIHRydWUpOwogICAgdGhpcy5oaWdobGlnaHQgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5oaWdobGlnaHQsIFsiaW52ZXJ0ZWQiLCAibm9uZSIsICJvdXRsaW5lIiwgInB1c2giXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQogIFtfeGZhX29iamVjdC4kdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgY29uc3QgcGFyZW50ID0gdGhpc1tfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpOwogICAgY29uc3QgZ3JhbmRwYSA9IHBhcmVudFtfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpOwogICAgY29uc3QgaHRtbEJ1dHRvbiA9IHsKICAgICAgbmFtZTogImJ1dHRvbiIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBpZDogdGhpc1tfeGZhX29iamVjdC4kdWlkXSwKICAgICAgICBjbGFzczogWyJ4ZmFCdXR0b24iXSwKICAgICAgICBzdHlsZToge30KICAgICAgfSwKICAgICAgY2hpbGRyZW46IFtdCiAgICB9OwogICAgZm9yIChjb25zdCBldmVudCBvZiBncmFuZHBhLmV2ZW50LmNoaWxkcmVuKSB7CiAgICAgIGlmIChldmVudC5hY3Rpdml0eSAhPT0gImNsaWNrIiB8fCAhZXZlbnQuc2NyaXB0KSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QganNVUkwgPSAoMCwgX2NvcmVfdXRpbHMucmVjb3ZlckpzVVJMKShldmVudC5zY3JpcHRbX3hmYV9vYmplY3QuJGNvbnRlbnRdKTsKICAgICAgaWYgKCFqc1VSTCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGhyZWYgPSAoMCwgX2h0bWxfdXRpbHMuZml4VVJMKShqc1VSTC51cmwpOwogICAgICBpZiAoIWhyZWYpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBodG1sQnV0dG9uLmNoaWxkcmVuLnB1c2goewogICAgICAgIG5hbWU6ICJhIiwKICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICBpZDogImxpbmsiICsgdGhpc1tfeGZhX29iamVjdC4kdWlkXSwKICAgICAgICAgIGhyZWYsCiAgICAgICAgICBuZXdXaW5kb3c6IGpzVVJMLm5ld1dpbmRvdywKICAgICAgICAgIGNsYXNzOiBbInhmYUxpbmsiXSwKICAgICAgICAgIHN0eWxlOiB7fQogICAgICAgIH0sCiAgICAgICAgY2hpbGRyZW46IFtdCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3MoaHRtbEJ1dHRvbik7CiAgfQp9CmNsYXNzIENhbGN1bGF0ZSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJjYWxjdWxhdGUiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5vdmVycmlkZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLm92ZXJyaWRlLCBbImRpc2FibGVkIiwgImVycm9yIiwgImlnbm9yZSIsICJ3YXJuaW5nIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMubWVzc2FnZSA9IG51bGw7CiAgICB0aGlzLnNjcmlwdCA9IG51bGw7CiAgfQp9CmNsYXNzIENhcHRpb24gZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiY2FwdGlvbiIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnBsYWNlbWVudCA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnBsYWNlbWVudCwgWyJsZWZ0IiwgImJvdHRvbSIsICJpbmxpbmUiLCAicmlnaHQiLCAidG9wIl0pOwogICAgdGhpcy5wcmVzZW5jZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnByZXNlbmNlLCBbInZpc2libGUiLCAiaGlkZGVuIiwgImluYWN0aXZlIiwgImludmlzaWJsZSJdKTsKICAgIHRoaXMucmVzZXJ2ZSA9IE1hdGguY2VpbCgoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLnJlc2VydmUpKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLmZvbnQgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogICAgdGhpcy5wYXJhID0gbnVsbDsKICAgIHRoaXMudmFsdWUgPSBudWxsOwogIH0KICBbX3hmYV9vYmplY3QuJHNldFZhbHVlXSh2YWx1ZSkgewogICAgX3NldFZhbHVlKHRoaXMsIHZhbHVlKTsKICB9CiAgW194ZmFfb2JqZWN0LiRnZXRFeHRyYV0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGlmICghdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdKSB7CiAgICAgIGxldCB7CiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0CiAgICAgIH0gPSBhdmFpbGFibGVTcGFjZTsKICAgICAgc3dpdGNoICh0aGlzLnBsYWNlbWVudCkgewogICAgICAgIGNhc2UgImxlZnQiOgogICAgICAgIGNhc2UgInJpZ2h0IjoKICAgICAgICBjYXNlICJpbmxpbmUiOgogICAgICAgICAgd2lkdGggPSB0aGlzLnJlc2VydmUgPD0gMCA/IHdpZHRoIDogdGhpcy5yZXNlcnZlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAidG9wIjoKICAgICAgICBjYXNlICJib3R0b20iOgogICAgICAgICAgaGVpZ2h0ID0gdGhpcy5yZXNlcnZlIDw9IDAgPyBoZWlnaHQgOiB0aGlzLnJlc2VydmU7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0gPSAoMCwgX2h0bWxfdXRpbHMubGF5b3V0Tm9kZSkodGhpcywgewogICAgICAgIHdpZHRoLAogICAgICAgIGhlaWdodAogICAgICB9KTsKICAgIH0KICAgIHJldHVybiB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV07CiAgfQogIFtfeGZhX29iamVjdC4kdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgaWYgKCF0aGlzLnZhbHVlKSB7CiAgICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIHRoaXNbX3hmYV9vYmplY3QuJHB1c2hQYXJhXSgpOwogICAgY29uc3QgdmFsdWUgPSB0aGlzLnZhbHVlW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKS5odG1sOwogICAgaWYgKCF2YWx1ZSkgewogICAgICB0aGlzW194ZmFfb2JqZWN0LiRwb3BQYXJhXSgpOwogICAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuRU1QVFk7CiAgICB9CiAgICBjb25zdCBzYXZlZFJlc2VydmUgPSB0aGlzLnJlc2VydmU7CiAgICBpZiAodGhpcy5yZXNlcnZlIDw9IDApIHsKICAgICAgY29uc3QgewogICAgICAgIHcsCiAgICAgICAgaAogICAgICB9ID0gdGhpc1tfeGZhX29iamVjdC4kZ2V0RXh0cmFdKGF2YWlsYWJsZVNwYWNlKTsKICAgICAgc3dpdGNoICh0aGlzLnBsYWNlbWVudCkgewogICAgICAgIGNhc2UgImxlZnQiOgogICAgICAgIGNhc2UgInJpZ2h0IjoKICAgICAgICBjYXNlICJpbmxpbmUiOgogICAgICAgICAgdGhpcy5yZXNlcnZlID0gdzsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInRvcCI6CiAgICAgICAgY2FzZSAiYm90dG9tIjoKICAgICAgICAgIHRoaXMucmVzZXJ2ZSA9IGg7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgY29uc3QgY2hpbGRyZW4gPSBbXTsKICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciKSB7CiAgICAgIGNoaWxkcmVuLnB1c2goewogICAgICAgIG5hbWU6ICIjdGV4dCIsCiAgICAgICAgdmFsdWUKICAgICAgfSk7CiAgICB9IGVsc2UgewogICAgICBjaGlsZHJlbi5wdXNoKHZhbHVlKTsKICAgIH0KICAgIGNvbnN0IHN0eWxlID0gKDAsIF9odG1sX3V0aWxzLnRvU3R5bGUpKHRoaXMsICJmb250IiwgIm1hcmdpbiIsICJ2aXNpYmlsaXR5Iik7CiAgICBzd2l0Y2ggKHRoaXMucGxhY2VtZW50KSB7CiAgICAgIGNhc2UgImxlZnQiOgogICAgICBjYXNlICJyaWdodCI6CiAgICAgICAgaWYgKHRoaXMucmVzZXJ2ZSA+IDApIHsKICAgICAgICAgIHN0eWxlLndpZHRoID0gKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykodGhpcy5yZXNlcnZlKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgInRvcCI6CiAgICAgIGNhc2UgImJvdHRvbSI6CiAgICAgICAgaWYgKHRoaXMucmVzZXJ2ZSA+IDApIHsKICAgICAgICAgIHN0eWxlLmhlaWdodCA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKHRoaXMucmVzZXJ2ZSk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgfQogICAgKDAsIF9odG1sX3V0aWxzLnNldFBhcmEpKHRoaXMsIG51bGwsIHZhbHVlKTsKICAgIHRoaXNbX3hmYV9vYmplY3QuJHBvcFBhcmFdKCk7CiAgICB0aGlzLnJlc2VydmUgPSBzYXZlZFJlc2VydmU7CiAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgIG5hbWU6ICJkaXYiLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgc3R5bGUsCiAgICAgICAgY2xhc3M6IFsieGZhQ2FwdGlvbiJdCiAgICAgIH0sCiAgICAgIGNoaWxkcmVuCiAgICB9KTsKICB9Cn0KY2xhc3MgQ2VydGlmaWNhdGUgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiY2VydGlmaWNhdGUiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgQ2VydGlmaWNhdGVzIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImNlcnRpZmljYXRlcyIsIHRydWUpOwogICAgdGhpcy5jcmVkZW50aWFsU2VydmVyUG9saWN5ID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuY3JlZGVudGlhbFNlcnZlclBvbGljeSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51cmwgPSBhdHRyaWJ1dGVzLnVybCB8fCAiIjsKICAgIHRoaXMudXJsUG9saWN5ID0gYXR0cmlidXRlcy51cmxQb2xpY3kgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5lbmNyeXB0aW9uID0gbnVsbDsKICAgIHRoaXMuaXNzdWVycyA9IG51bGw7CiAgICB0aGlzLmtleVVzYWdlID0gbnVsbDsKICAgIHRoaXMub2lkcyA9IG51bGw7CiAgICB0aGlzLnNpZ25pbmcgPSBudWxsOwogICAgdGhpcy5zdWJqZWN0RE5zID0gbnVsbDsKICB9Cn0KY2xhc3MgQ2hlY2tCdXR0b24gZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiY2hlY2tCdXR0b24iLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5tYXJrID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMubWFyaywgWyJkZWZhdWx0IiwgImNoZWNrIiwgImNpcmNsZSIsICJjcm9zcyIsICJkaWFtb25kIiwgInNxdWFyZSIsICJzdGFyIl0pOwogICAgdGhpcy5zaGFwZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnNoYXBlLCBbInNxdWFyZSIsICJyb3VuZCJdKTsKICAgIHRoaXMuc2l6ZSA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMuc2l6ZSwgIjEwcHQiKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmJvcmRlciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgfQogIFtfeGZhX29iamVjdC4kdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgY29uc3Qgc3R5bGUgPSAoMCwgX2h0bWxfdXRpbHMudG9TdHlsZSkoIm1hcmdpbiIpOwogICAgY29uc3Qgc2l6ZSA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKHRoaXMuc2l6ZSk7CiAgICBzdHlsZS53aWR0aCA9IHN0eWxlLmhlaWdodCA9IHNpemU7CiAgICBsZXQgdHlwZTsKICAgIGxldCBjbGFzc05hbWU7CiAgICBsZXQgZ3JvdXBJZDsKICAgIGNvbnN0IGZpZWxkID0gdGhpc1tfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBpdGVtcyA9IGZpZWxkLml0ZW1zLmNoaWxkcmVuLmxlbmd0aCAmJiBmaWVsZC5pdGVtcy5jaGlsZHJlblswXVtfeGZhX29iamVjdC4kdG9IVE1MXSgpLmh0bWwgfHwgW107CiAgICBjb25zdCBleHBvcnRlZFZhbHVlID0gewogICAgICBvbjogKGl0ZW1zWzBdICE9PSB1bmRlZmluZWQgPyBpdGVtc1swXSA6ICJvbiIpLnRvU3RyaW5nKCksCiAgICAgIG9mZjogKGl0ZW1zWzFdICE9PSB1bmRlZmluZWQgPyBpdGVtc1sxXSA6ICJvZmYiKS50b1N0cmluZygpCiAgICB9OwogICAgY29uc3QgdmFsdWUgPSBmaWVsZC52YWx1ZSAmJiBmaWVsZC52YWx1ZVtfeGZhX29iamVjdC4kdGV4dF0oKSB8fCAib2ZmIjsKICAgIGNvbnN0IGNoZWNrZWQgPSB2YWx1ZSA9PT0gZXhwb3J0ZWRWYWx1ZS5vbiB8fCB1bmRlZmluZWQ7CiAgICBjb25zdCBjb250YWluZXIgPSBmaWVsZFtfeGZhX29iamVjdC4kZ2V0U3ViZm9ybVBhcmVudF0oKTsKICAgIGNvbnN0IGZpZWxkSWQgPSBmaWVsZFtfeGZhX29iamVjdC4kdWlkXTsKICAgIGxldCBkYXRhSWQ7CiAgICBpZiAoY29udGFpbmVyIGluc3RhbmNlb2YgRXhjbEdyb3VwKSB7CiAgICAgIGdyb3VwSWQgPSBjb250YWluZXJbX3hmYV9vYmplY3QuJHVpZF07CiAgICAgIHR5cGUgPSAicmFkaW8iOwogICAgICBjbGFzc05hbWUgPSAieGZhUmFkaW8iOwogICAgICBkYXRhSWQgPSBjb250YWluZXJbX3hmYV9vYmplY3QuJGRhdGFdICYmIGNvbnRhaW5lcltfeGZhX29iamVjdC4kZGF0YV1bX3hmYV9vYmplY3QuJHVpZF0gfHwgY29udGFpbmVyW194ZmFfb2JqZWN0LiR1aWRdOwogICAgfSBlbHNlIHsKICAgICAgdHlwZSA9ICJjaGVja2JveCI7CiAgICAgIGNsYXNzTmFtZSA9ICJ4ZmFDaGVja2JveCI7CiAgICAgIGRhdGFJZCA9IGZpZWxkW194ZmFfb2JqZWN0LiRkYXRhXSAmJiBmaWVsZFtfeGZhX29iamVjdC4kZGF0YV1bX3hmYV9vYmplY3QuJHVpZF0gfHwgZmllbGRbX3hmYV9vYmplY3QuJHVpZF07CiAgICB9CiAgICBjb25zdCBpbnB1dCA9IHsKICAgICAgbmFtZTogImlucHV0IiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGNsYXNzOiBbY2xhc3NOYW1lXSwKICAgICAgICBzdHlsZSwKICAgICAgICBmaWVsZElkLAogICAgICAgIGRhdGFJZCwKICAgICAgICB0eXBlLAogICAgICAgIGNoZWNrZWQsCiAgICAgICAgeGZhT246IGV4cG9ydGVkVmFsdWUub24sCiAgICAgICAgeGZhT2ZmOiBleHBvcnRlZFZhbHVlLm9mZiwKICAgICAgICAiYXJpYS1sYWJlbCI6IGFyaWFMYWJlbChmaWVsZCksCiAgICAgICAgImFyaWEtcmVxdWlyZWQiOiBmYWxzZQogICAgICB9CiAgICB9OwogICAgaWYgKGdyb3VwSWQpIHsKICAgICAgaW5wdXQuYXR0cmlidXRlcy5uYW1lID0gZ3JvdXBJZDsKICAgIH0KICAgIGlmIChpc1JlcXVpcmVkKGZpZWxkKSkgewogICAgICBpbnB1dC5hdHRyaWJ1dGVzWyJhcmlhLXJlcXVpcmVkIl0gPSB0cnVlOwogICAgICBpbnB1dC5hdHRyaWJ1dGVzLnJlcXVpcmVkID0gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImxhYmVsIiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGNsYXNzOiBbInhmYUxhYmVsIl0KICAgICAgfSwKICAgICAgY2hpbGRyZW46IFtpbnB1dF0KICAgIH0pOwogIH0KfQpjbGFzcyBDaG9pY2VMaXN0IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImNob2ljZUxpc3QiLCB0cnVlKTsKICAgIHRoaXMuY29tbWl0T24gPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5jb21taXRPbiwgWyJzZWxlY3QiLCAiZXhpdCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5vcGVuID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMub3BlbiwgWyJ1c2VyQ29udHJvbCIsICJhbHdheXMiLCAibXVsdGlTZWxlY3QiLCAib25FbnRyeSJdKTsKICAgIHRoaXMudGV4dEVudHJ5ID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMudGV4dEVudHJ5LAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuYm9yZGVyID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMubWFyZ2luID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCBzdHlsZSA9ICgwLCBfaHRtbF91dGlscy50b1N0eWxlKSh0aGlzLCAiYm9yZGVyIiwgIm1hcmdpbiIpOwogICAgY29uc3QgdWkgPSB0aGlzW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBmaWVsZCA9IHVpW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBmb250U2l6ZSA9IGZpZWxkLmZvbnQgJiYgZmllbGQuZm9udC5zaXplIHx8IDEwOwogICAgY29uc3Qgb3B0aW9uU3R5bGUgPSB7CiAgICAgIGZvbnRTaXplOiBgY2FsYygke2ZvbnRTaXplfXB4ICogdmFyKC0tc2NhbGUtZmFjdG9yKSlgCiAgICB9OwogICAgY29uc3QgY2hpbGRyZW4gPSBbXTsKICAgIGlmIChmaWVsZC5pdGVtcy5jaGlsZHJlbi5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IGl0ZW1zID0gZmllbGQuaXRlbXM7CiAgICAgIGxldCBkaXNwbGF5ZWRJbmRleCA9IDA7CiAgICAgIGxldCBzYXZlSW5kZXggPSAwOwogICAgICBpZiAoaXRlbXMuY2hpbGRyZW4ubGVuZ3RoID09PSAyKSB7CiAgICAgICAgZGlzcGxheWVkSW5kZXggPSBpdGVtcy5jaGlsZHJlblswXS5zYXZlOwogICAgICAgIHNhdmVJbmRleCA9IDEgLSBkaXNwbGF5ZWRJbmRleDsKICAgICAgfQogICAgICBjb25zdCBkaXNwbGF5ZWQgPSBpdGVtcy5jaGlsZHJlbltkaXNwbGF5ZWRJbmRleF1bX3hmYV9vYmplY3QuJHRvSFRNTF0oKS5odG1sOwogICAgICBjb25zdCB2YWx1ZXMgPSBpdGVtcy5jaGlsZHJlbltzYXZlSW5kZXhdW194ZmFfb2JqZWN0LiR0b0hUTUxdKCkuaHRtbDsKICAgICAgbGV0IHNlbGVjdGVkID0gZmFsc2U7CiAgICAgIGNvbnN0IHZhbHVlID0gZmllbGQudmFsdWUgJiYgZmllbGQudmFsdWVbX3hmYV9vYmplY3QuJHRleHRdKCkgfHwgIiI7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGRpc3BsYXllZC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3Qgb3B0aW9uID0gewogICAgICAgICAgbmFtZTogIm9wdGlvbiIsCiAgICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICAgIHZhbHVlOiB2YWx1ZXNbaV0gfHwgZGlzcGxheWVkW2ldLAogICAgICAgICAgICBzdHlsZTogb3B0aW9uU3R5bGUKICAgICAgICAgIH0sCiAgICAgICAgICB2YWx1ZTogZGlzcGxheWVkW2ldCiAgICAgICAgfTsKICAgICAgICBpZiAodmFsdWVzW2ldID09PSB2YWx1ZSkgewogICAgICAgICAgb3B0aW9uLmF0dHJpYnV0ZXMuc2VsZWN0ZWQgPSBzZWxlY3RlZCA9IHRydWU7CiAgICAgICAgfQogICAgICAgIGNoaWxkcmVuLnB1c2gob3B0aW9uKTsKICAgICAgfQogICAgICBpZiAoIXNlbGVjdGVkKSB7CiAgICAgICAgY2hpbGRyZW4uc3BsaWNlKDAsIDAsIHsKICAgICAgICAgIG5hbWU6ICJvcHRpb24iLAogICAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgICBoaWRkZW46IHRydWUsCiAgICAgICAgICAgIHNlbGVjdGVkOiB0cnVlCiAgICAgICAgICB9LAogICAgICAgICAgdmFsdWU6ICIgIgogICAgICAgIH0pOwogICAgICB9CiAgICB9CiAgICBjb25zdCBzZWxlY3RBdHRyaWJ1dGVzID0gewogICAgICBjbGFzczogWyJ4ZmFTZWxlY3QiXSwKICAgICAgZmllbGRJZDogZmllbGRbX3hmYV9vYmplY3QuJHVpZF0sCiAgICAgIGRhdGFJZDogZmllbGRbX3hmYV9vYmplY3QuJGRhdGFdICYmIGZpZWxkW194ZmFfb2JqZWN0LiRkYXRhXVtfeGZhX29iamVjdC4kdWlkXSB8fCBmaWVsZFtfeGZhX29iamVjdC4kdWlkXSwKICAgICAgc3R5bGUsCiAgICAgICJhcmlhLWxhYmVsIjogYXJpYUxhYmVsKGZpZWxkKSwKICAgICAgImFyaWEtcmVxdWlyZWQiOiBmYWxzZQogICAgfTsKICAgIGlmIChpc1JlcXVpcmVkKGZpZWxkKSkgewogICAgICBzZWxlY3RBdHRyaWJ1dGVzWyJhcmlhLXJlcXVpcmVkIl0gPSB0cnVlOwogICAgICBzZWxlY3RBdHRyaWJ1dGVzLnJlcXVpcmVkID0gdHJ1ZTsKICAgIH0KICAgIGlmICh0aGlzLm9wZW4gPT09ICJtdWx0aVNlbGVjdCIpIHsKICAgICAgc2VsZWN0QXR0cmlidXRlcy5tdWx0aXBsZSA9IHRydWU7CiAgICB9CiAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgIG5hbWU6ICJsYWJlbCIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBjbGFzczogWyJ4ZmFMYWJlbCJdCiAgICAgIH0sCiAgICAgIGNoaWxkcmVuOiBbewogICAgICAgIG5hbWU6ICJzZWxlY3QiLAogICAgICAgIGNoaWxkcmVuLAogICAgICAgIGF0dHJpYnV0ZXM6IHNlbGVjdEF0dHJpYnV0ZXMKICAgICAgfV0KICAgIH0pOwogIH0KfQpjbGFzcyBDb2xvciBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJjb2xvciIsIHRydWUpOwogICAgdGhpcy5jU3BhY2UgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5jU3BhY2UsIFsiU1JHQiJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMudmFsdWUgPSBhdHRyaWJ1dGVzLnZhbHVlID8gKDAsIF91dGlscy5nZXRDb2xvcikoYXR0cmlidXRlcy52YWx1ZSkgOiAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiRoYXNTZXR0YWJsZVZhbHVlXSgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgW194ZmFfb2JqZWN0LiR0b1N0eWxlXSgpIHsKICAgIHJldHVybiB0aGlzLnZhbHVlID8gX3V0aWwuVXRpbC5tYWtlSGV4Q29sb3IodGhpcy52YWx1ZS5yLCB0aGlzLnZhbHVlLmcsIHRoaXMudmFsdWUuYikgOiBudWxsOwogIH0KfQpjbGFzcyBDb21iIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImNvbWIiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5udW1iZXJPZkNlbGxzID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMubnVtYmVyT2ZDZWxscywKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgQ29ubmVjdCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJjb25uZWN0IiwgdHJ1ZSk7CiAgICB0aGlzLmNvbm5lY3Rpb24gPSBhdHRyaWJ1dGVzLmNvbm5lY3Rpb24gfHwgIiI7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMucmVmID0gYXR0cmlidXRlcy5yZWYgfHwgIiI7CiAgICB0aGlzLnVzYWdlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMudXNhZ2UsIFsiZXhwb3J0QW5kSW1wb3J0IiwgImV4cG9ydE9ubHkiLCAiaW1wb3J0T25seSJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnBpY3R1cmUgPSBudWxsOwogIH0KfQpjbGFzcyBDb250ZW50QXJlYSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJjb250ZW50QXJlYSIsIHRydWUpOwogICAgdGhpcy5oID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5oKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5yZWxldmFudCA9ICgwLCBfdXRpbHMuZ2V0UmVsZXZhbnQpKGF0dHJpYnV0ZXMucmVsZXZhbnQpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMudyA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMudyk7CiAgICB0aGlzLnggPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLngsICIwcHQiKTsKICAgIHRoaXMueSA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMueSwgIjBwdCIpOwogICAgdGhpcy5kZXNjID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCBsZWZ0ID0gKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykodGhpcy54KTsKICAgIGNvbnN0IHRvcCA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKHRoaXMueSk7CiAgICBjb25zdCBzdHlsZSA9IHsKICAgICAgbGVmdCwKICAgICAgdG9wLAogICAgICB3aWR0aDogKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykodGhpcy53KSwKICAgICAgaGVpZ2h0OiAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSh0aGlzLmgpCiAgICB9OwogICAgY29uc3QgY2xhc3NOYW1lcyA9IFsieGZhQ29udGVudGFyZWEiXTsKICAgIGlmICgoMCwgX2h0bWxfdXRpbHMuaXNQcmludE9ubHkpKHRoaXMpKSB7CiAgICAgIGNsYXNzTmFtZXMucHVzaCgieGZhUHJpbnRPbmx5Iik7CiAgICB9CiAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgIG5hbWU6ICJkaXYiLAogICAgICBjaGlsZHJlbjogW10sCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBzdHlsZSwKICAgICAgICBjbGFzczogY2xhc3NOYW1lcywKICAgICAgICBpZDogdGhpc1tfeGZhX29iamVjdC4kdWlkXQogICAgICB9CiAgICB9KTsKICB9Cn0KY2xhc3MgQ29ybmVyIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImNvcm5lciIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmludmVydGVkID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuaW52ZXJ0ZWQsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmpvaW4gPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5qb2luLCBbInNxdWFyZSIsICJyb3VuZCJdKTsKICAgIHRoaXMucHJlc2VuY2UgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5wcmVzZW5jZSwgWyJ2aXNpYmxlIiwgImhpZGRlbiIsICJpbmFjdGl2ZSIsICJpbnZpc2libGUiXSk7CiAgICB0aGlzLnJhZGl1cyA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMucmFkaXVzKTsKICAgIHRoaXMuc3Ryb2tlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuc3Ryb2tlLCBbInNvbGlkIiwgImRhc2hEb3QiLCAiZGFzaERvdERvdCIsICJkYXNoZWQiLCAiZG90dGVkIiwgImVtYm9zc2VkIiwgImV0Y2hlZCIsICJsb3dlcmVkIiwgInJhaXNlZCJdKTsKICAgIHRoaXMudGhpY2tuZXNzID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy50aGlja25lc3MsICIwLjVwdCIpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY29sb3IgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCkgewogICAgY29uc3Qgc3R5bGUgPSAoMCwgX2h0bWxfdXRpbHMudG9TdHlsZSkodGhpcywgInZpc2liaWxpdHkiKTsKICAgIHN0eWxlLnJhZGl1cyA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKHRoaXMuam9pbiA9PT0gInNxdWFyZSIgPyAwIDogdGhpcy5yYWRpdXMpOwogICAgcmV0dXJuIHN0eWxlOwogIH0KfQpjbGFzcyBEYXRlRWxlbWVudCBleHRlbmRzIF94ZmFfb2JqZWN0LkNvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZGF0ZSIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KICBbX3hmYV9vYmplY3QuJGZpbmFsaXplXSgpIHsKICAgIGNvbnN0IGRhdGUgPSB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XS50cmltKCk7CiAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA9IGRhdGUgPyBuZXcgRGF0ZShkYXRlKSA6IG51bGw7CiAgfQogIFtfeGZhX29iamVjdC4kdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgcmV0dXJuIHZhbHVlVG9IdG1sKHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdID8gdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0udG9TdHJpbmcoKSA6ICIiKTsKICB9Cn0KY2xhc3MgRGF0ZVRpbWUgZXh0ZW5kcyBfeGZhX29iamVjdC5Db250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImRhdGVUaW1lIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFtfeGZhX29iamVjdC4kZmluYWxpemVdKCkgewogICAgY29uc3QgZGF0ZSA9IHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdLnRyaW0oKTsKICAgIHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdID0gZGF0ZSA/IG5ldyBEYXRlKGRhdGUpIDogbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gdmFsdWVUb0h0bWwodGhpc1tfeGZhX29iamVjdC4kY29udGVudF0gPyB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XS50b1N0cmluZygpIDogIiIpOwogIH0KfQpjbGFzcyBEYXRlVGltZUVkaXQgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZGF0ZVRpbWVFZGl0IiwgdHJ1ZSk7CiAgICB0aGlzLmhTY3JvbGxQb2xpY3kgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5oU2Nyb2xsUG9saWN5LCBbImF1dG8iLCAib2ZmIiwgIm9uIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnBpY2tlciA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnBpY2tlciwgWyJob3N0IiwgIm5vbmUiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5jb21iID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMubWFyZ2luID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCBzdHlsZSA9ICgwLCBfaHRtbF91dGlscy50b1N0eWxlKSh0aGlzLCAiYm9yZGVyIiwgImZvbnQiLCAibWFyZ2luIik7CiAgICBjb25zdCBmaWVsZCA9IHRoaXNbX3hmYV9vYmplY3QuJGdldFBhcmVudF0oKVtfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpOwogICAgY29uc3QgaHRtbCA9IHsKICAgICAgbmFtZTogImlucHV0IiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIHR5cGU6ICJ0ZXh0IiwKICAgICAgICBmaWVsZElkOiBmaWVsZFtfeGZhX29iamVjdC4kdWlkXSwKICAgICAgICBkYXRhSWQ6IGZpZWxkW194ZmFfb2JqZWN0LiRkYXRhXSAmJiBmaWVsZFtfeGZhX29iamVjdC4kZGF0YV1bX3hmYV9vYmplY3QuJHVpZF0gfHwgZmllbGRbX3hmYV9vYmplY3QuJHVpZF0sCiAgICAgICAgY2xhc3M6IFsieGZhVGV4dGZpZWxkIl0sCiAgICAgICAgc3R5bGUsCiAgICAgICAgImFyaWEtbGFiZWwiOiBhcmlhTGFiZWwoZmllbGQpLAogICAgICAgICJhcmlhLXJlcXVpcmVkIjogZmFsc2UKICAgICAgfQogICAgfTsKICAgIGlmIChpc1JlcXVpcmVkKGZpZWxkKSkgewogICAgICBodG1sLmF0dHJpYnV0ZXNbImFyaWEtcmVxdWlyZWQiXSA9IHRydWU7CiAgICAgIGh0bWwuYXR0cmlidXRlcy5yZXF1aXJlZCA9IHRydWU7CiAgICB9CiAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgIG5hbWU6ICJsYWJlbCIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBjbGFzczogWyJ4ZmFMYWJlbCJdCiAgICAgIH0sCiAgICAgIGNoaWxkcmVuOiBbaHRtbF0KICAgIH0pOwogIH0KfQpjbGFzcyBEZWNpbWFsIGV4dGVuZHMgX3hmYV9vYmplY3QuQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJkZWNpbWFsIik7CiAgICB0aGlzLmZyYWNEaWdpdHMgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5mcmFjRGlnaXRzLAogICAgICBkZWZhdWx0VmFsdWU6IDIsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHRydWUKICAgIH0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxlYWREaWdpdHMgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5sZWFkRGlnaXRzLAogICAgICBkZWZhdWx0VmFsdWU6IC0xLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFtfeGZhX29iamVjdC4kZmluYWxpemVdKCkgewogICAgY29uc3QgbnVtYmVyID0gcGFyc2VGbG9hdCh0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XS50cmltKCkpOwogICAgdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0gPSBpc05hTihudW1iZXIpID8gbnVsbCA6IG51bWJlcjsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gdmFsdWVUb0h0bWwodGhpc1tfeGZhX29iamVjdC4kY29udGVudF0gIT09IG51bGwgPyB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XS50b1N0cmluZygpIDogIiIpOwogIH0KfQpjbGFzcyBEZWZhdWx0VWkgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZGVmYXVsdFVpIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQp9CmNsYXNzIERlc2MgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZGVzYyIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5ib29sZWFuID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGUgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGF0ZVRpbWUgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGVjaW1hbCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leERhdGEgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmxvYXQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaW1hZ2UgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaW50ZWdlciA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50ZXh0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRpbWUgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgRGlnZXN0TWV0aG9kIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImRpZ2VzdE1ldGhvZCIsIFsiIiwgIlNIQTEiLCAiU0hBMjU2IiwgIlNIQTUxMiIsICJSSVBFTUQxNjAiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIERpZ2VzdE1ldGhvZHMgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZGlnZXN0TWV0aG9kcyIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZGlnZXN0TWV0aG9kID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIERyYXcgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZHJhdyIsIHRydWUpOwogICAgdGhpcy5hbmNob3JUeXBlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuYW5jaG9yVHlwZSwgWyJ0b3BMZWZ0IiwgImJvdHRvbUNlbnRlciIsICJib3R0b21MZWZ0IiwgImJvdHRvbVJpZ2h0IiwgIm1pZGRsZUNlbnRlciIsICJtaWRkbGVMZWZ0IiwgIm1pZGRsZVJpZ2h0IiwgInRvcENlbnRlciIsICJ0b3BSaWdodCJdKTsKICAgIHRoaXMuY29sU3BhbiA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmNvbFNwYW4sCiAgICAgIGRlZmF1bHRWYWx1ZTogMSwKICAgICAgdmFsaWRhdGU6IG4gPT4gbiA+PSAxIHx8IG4gPT09IC0xCiAgICB9KTsKICAgIHRoaXMuaCA9IGF0dHJpYnV0ZXMuaCA/ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMuaCkgOiAiIjsKICAgIHRoaXMuaEFsaWduID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuaEFsaWduLCBbImxlZnQiLCAiY2VudGVyIiwgImp1c3RpZnkiLCAianVzdGlmeUFsbCIsICJyYWRpeCIsICJyaWdodCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5sb2NhbGUgPSBhdHRyaWJ1dGVzLmxvY2FsZSB8fCAiIjsKICAgIHRoaXMubWF4SCA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMubWF4SCwgIjBwdCIpOwogICAgdGhpcy5tYXhXID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5tYXhXLCAiMHB0Iik7CiAgICB0aGlzLm1pbkggPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLm1pbkgsICIwcHQiKTsKICAgIHRoaXMubWluVyA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMubWluVywgIjBwdCIpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5wcmVzZW5jZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnByZXNlbmNlLCBbInZpc2libGUiLCAiaGlkZGVuIiwgImluYWN0aXZlIiwgImludmlzaWJsZSJdKTsKICAgIHRoaXMucmVsZXZhbnQgPSAoMCwgX3V0aWxzLmdldFJlbGV2YW50KShhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMucm90YXRlID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMucm90YXRlLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggJSA5MCA9PT0gMAogICAgfSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy53ID0gYXR0cmlidXRlcy53ID8gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy53KSA6ICIiOwogICAgdGhpcy54ID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy54LCAiMHB0Iik7CiAgICB0aGlzLnkgPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLnksICIwcHQiKTsKICAgIHRoaXMuYXNzaXN0ID0gbnVsbDsKICAgIHRoaXMuYm9yZGVyID0gbnVsbDsKICAgIHRoaXMuY2FwdGlvbiA9IG51bGw7CiAgICB0aGlzLmRlc2MgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5mb250ID0gbnVsbDsKICAgIHRoaXMua2VlcCA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgICB0aGlzLnBhcmEgPSBudWxsOwogICAgdGhpcy50cmF2ZXJzYWwgPSBudWxsOwogICAgdGhpcy51aSA9IG51bGw7CiAgICB0aGlzLnZhbHVlID0gbnVsbDsKICAgIHRoaXMuc2V0UHJvcGVydHkgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9CiAgW194ZmFfb2JqZWN0LiRzZXRWYWx1ZV0odmFsdWUpIHsKICAgIF9zZXRWYWx1ZSh0aGlzLCB2YWx1ZSk7CiAgfQogIFtfeGZhX29iamVjdC4kdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgc2V0VGFiSW5kZXgodGhpcyk7CiAgICBpZiAodGhpcy5wcmVzZW5jZSA9PT0gImhpZGRlbiIgfHwgdGhpcy5wcmVzZW5jZSA9PT0gImluYWN0aXZlIikgewogICAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuRU1QVFk7CiAgICB9CiAgICAoMCwgX2h0bWxfdXRpbHMuZml4RGltZW5zaW9ucykodGhpcyk7CiAgICB0aGlzW194ZmFfb2JqZWN0LiRwdXNoUGFyYV0oKTsKICAgIGNvbnN0IHNhdmVkVyA9IHRoaXMudzsKICAgIGNvbnN0IHNhdmVkSCA9IHRoaXMuaDsKICAgIGNvbnN0IHsKICAgICAgdywKICAgICAgaCwKICAgICAgaXNCcm9rZW4KICAgIH0gPSAoMCwgX2h0bWxfdXRpbHMubGF5b3V0Tm9kZSkodGhpcywgYXZhaWxhYmxlU3BhY2UpOwogICAgaWYgKHcgJiYgdGhpcy53ID09PSAiIikgewogICAgICBpZiAoaXNCcm9rZW4gJiYgdGhpc1tfeGZhX29iamVjdC4kZ2V0U3ViZm9ybVBhcmVudF0oKVtfeGZhX29iamVjdC4kaXNUaGVyZU1vcmVXaWR0aF0oKSkgewogICAgICAgIHRoaXNbX3hmYV9vYmplY3QuJHBvcFBhcmFdKCk7CiAgICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LkZBSUxVUkU7CiAgICAgIH0KICAgICAgdGhpcy53ID0gdzsKICAgIH0KICAgIGlmIChoICYmIHRoaXMuaCA9PT0gIiIpIHsKICAgICAgdGhpcy5oID0gaDsKICAgIH0KICAgIHNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgaWYgKCEoMCwgX2xheW91dC5jaGVja0RpbWVuc2lvbnMpKHRoaXMsIGF2YWlsYWJsZVNwYWNlKSkgewogICAgICB0aGlzLncgPSBzYXZlZFc7CiAgICAgIHRoaXMuaCA9IHNhdmVkSDsKICAgICAgdGhpc1tfeGZhX29iamVjdC4kcG9wUGFyYV0oKTsKICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LkZBSUxVUkU7CiAgICB9CiAgICB1bnNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgY29uc3Qgc3R5bGUgPSAoMCwgX2h0bWxfdXRpbHMudG9TdHlsZSkodGhpcywgImZvbnQiLCAiaEFsaWduIiwgImRpbWVuc2lvbnMiLCAicG9zaXRpb24iLCAicHJlc2VuY2UiLCAicm90YXRlIiwgImFuY2hvclR5cGUiLCAiYm9yZGVyIiwgIm1hcmdpbiIpOwogICAgKDAsIF9odG1sX3V0aWxzLnNldE1pbk1heERpbWVuc2lvbnMpKHRoaXMsIHN0eWxlKTsKICAgIGlmIChzdHlsZS5tYXJnaW4pIHsKICAgICAgc3R5bGUucGFkZGluZyA9IHN0eWxlLm1hcmdpbjsKICAgICAgZGVsZXRlIHN0eWxlLm1hcmdpbjsKICAgIH0KICAgIGNvbnN0IGNsYXNzTmFtZXMgPSBbInhmYURyYXciXTsKICAgIGlmICh0aGlzLmZvbnQpIHsKICAgICAgY2xhc3NOYW1lcy5wdXNoKCJ4ZmFGb250Iik7CiAgICB9CiAgICBpZiAoKDAsIF9odG1sX3V0aWxzLmlzUHJpbnRPbmx5KSh0aGlzKSkgewogICAgICBjbGFzc05hbWVzLnB1c2goInhmYVByaW50T25seSIpOwogICAgfQogICAgY29uc3QgYXR0cmlidXRlcyA9IHsKICAgICAgc3R5bGUsCiAgICAgIGlkOiB0aGlzW194ZmFfb2JqZWN0LiR1aWRdLAogICAgICBjbGFzczogY2xhc3NOYW1lcwogICAgfTsKICAgIGlmICh0aGlzLm5hbWUpIHsKICAgICAgYXR0cmlidXRlcy54ZmFOYW1lID0gdGhpcy5uYW1lOwogICAgfQogICAgY29uc3QgaHRtbCA9IHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGNoaWxkcmVuOiBbXQogICAgfTsKICAgIGFwcGx5QXNzaXN0KHRoaXMsIGF0dHJpYnV0ZXMpOwogICAgY29uc3QgYmJveCA9ICgwLCBfaHRtbF91dGlscy5jb21wdXRlQmJveCkodGhpcywgaHRtbCwgYXZhaWxhYmxlU3BhY2UpOwogICAgY29uc3QgdmFsdWUgPSB0aGlzLnZhbHVlID8gdGhpcy52YWx1ZVtfeGZhX29iamVjdC4kdG9IVE1MXShhdmFpbGFibGVTcGFjZSkuaHRtbCA6IG51bGw7CiAgICBpZiAodmFsdWUgPT09IG51bGwpIHsKICAgICAgdGhpcy53ID0gc2F2ZWRXOwogICAgICB0aGlzLmggPSBzYXZlZEg7CiAgICAgIHRoaXNbX3hmYV9vYmplY3QuJHBvcFBhcmFdKCk7CiAgICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5zdWNjZXNzKCgwLCBfaHRtbF91dGlscy5jcmVhdGVXcmFwcGVyKSh0aGlzLCBodG1sKSwgYmJveCk7CiAgICB9CiAgICBodG1sLmNoaWxkcmVuLnB1c2godmFsdWUpOwogICAgKDAsIF9odG1sX3V0aWxzLnNldFBhcmEpKHRoaXMsIHN0eWxlLCB2YWx1ZSk7CiAgICB0aGlzLncgPSBzYXZlZFc7CiAgICB0aGlzLmggPSBzYXZlZEg7CiAgICB0aGlzW194ZmFfb2JqZWN0LiRwb3BQYXJhXSgpOwogICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3MoKDAsIF9odG1sX3V0aWxzLmNyZWF0ZVdyYXBwZXIpKHRoaXMsIGh0bWwpLCBiYm94KTsKICB9Cn0KY2xhc3MgRWRnZSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJlZGdlIiwgdHJ1ZSk7CiAgICB0aGlzLmNhcCA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmNhcCwgWyJzcXVhcmUiLCAiYnV0dCIsICJyb3VuZCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5wcmVzZW5jZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnByZXNlbmNlLCBbInZpc2libGUiLCAiaGlkZGVuIiwgImluYWN0aXZlIiwgImludmlzaWJsZSJdKTsKICAgIHRoaXMuc3Ryb2tlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuc3Ryb2tlLCBbInNvbGlkIiwgImRhc2hEb3QiLCAiZGFzaERvdERvdCIsICJkYXNoZWQiLCAiZG90dGVkIiwgImVtYm9zc2VkIiwgImV0Y2hlZCIsICJsb3dlcmVkIiwgInJhaXNlZCJdKTsKICAgIHRoaXMudGhpY2tuZXNzID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy50aGlja25lc3MsICIwLjVwdCIpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY29sb3IgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCkgewogICAgY29uc3Qgc3R5bGUgPSAoMCwgX2h0bWxfdXRpbHMudG9TdHlsZSkodGhpcywgInZpc2liaWxpdHkiKTsKICAgIE9iamVjdC5hc3NpZ24oc3R5bGUsIHsKICAgICAgbGluZWNhcDogdGhpcy5jYXAsCiAgICAgIHdpZHRoOiAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSh0aGlzLnRoaWNrbmVzcyksCiAgICAgIGNvbG9yOiB0aGlzLmNvbG9yID8gdGhpcy5jb2xvcltfeGZhX29iamVjdC4kdG9TdHlsZV0oKSA6ICIjMDAwMDAwIiwKICAgICAgc3R5bGU6ICIiCiAgICB9KTsKICAgIGlmICh0aGlzLnByZXNlbmNlICE9PSAidmlzaWJsZSIpIHsKICAgICAgc3R5bGUuc3R5bGUgPSAibm9uZSI7CiAgICB9IGVsc2UgewogICAgICBzd2l0Y2ggKHRoaXMuc3Ryb2tlKSB7CiAgICAgICAgY2FzZSAic29saWQiOgogICAgICAgICAgc3R5bGUuc3R5bGUgPSAic29saWQiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZGFzaERvdCI6CiAgICAgICAgICBzdHlsZS5zdHlsZSA9ICJkYXNoZWQiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZGFzaERvdERvdCI6CiAgICAgICAgICBzdHlsZS5zdHlsZSA9ICJkYXNoZWQiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZGFzaGVkIjoKICAgICAgICAgIHN0eWxlLnN0eWxlID0gImRhc2hlZCI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJkb3R0ZWQiOgogICAgICAgICAgc3R5bGUuc3R5bGUgPSAiZG90dGVkIjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImVtYm9zc2VkIjoKICAgICAgICAgIHN0eWxlLnN0eWxlID0gInJpZGdlIjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImV0Y2hlZCI6CiAgICAgICAgICBzdHlsZS5zdHlsZSA9ICJncm9vdmUiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibG93ZXJlZCI6CiAgICAgICAgICBzdHlsZS5zdHlsZSA9ICJpbnNldCI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJyYWlzZWQiOgogICAgICAgICAgc3R5bGUuc3R5bGUgPSAib3V0c2V0IjsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc3R5bGU7CiAgfQp9CmNsYXNzIEVuY29kaW5nIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImVuY29kaW5nIiwgWyJhZGJlLng1MDkucnNhX3NoYTEiLCAiYWRiZS5wa2NzNy5kZXRhY2hlZCIsICJhZGJlLnBrY3M3LnNoYTEiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIEVuY29kaW5ncyBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJlbmNvZGluZ3MiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmVuY29kaW5nID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIEVuY3J5cHQgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZW5jcnlwdCIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5jZXJ0aWZpY2F0ZSA9IG51bGw7CiAgfQp9CmNsYXNzIEVuY3J5cHREYXRhIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImVuY3J5cHREYXRhIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMub3BlcmF0aW9uID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMub3BlcmF0aW9uLCBbImVuY3J5cHQiLCAiZGVjcnlwdCJdKTsKICAgIHRoaXMudGFyZ2V0ID0gYXR0cmlidXRlcy50YXJnZXQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5maWx0ZXIgPSBudWxsOwogICAgdGhpcy5tYW5pZmVzdCA9IG51bGw7CiAgfQp9CmNsYXNzIEVuY3J5cHRpb24gZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZW5jcnlwdGlvbiIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY2VydGlmaWNhdGUgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgRW5jcnlwdGlvbk1ldGhvZCBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJlbmNyeXB0aW9uTWV0aG9kIiwgWyIiLCAiQUVTMjU2LUNCQyIsICJUUklQTEVERVMtQ0JDIiwgIkFFUzEyOC1DQkMiLCAiQUVTMTkyLUNCQyJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgRW5jcnlwdGlvbk1ldGhvZHMgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZW5jcnlwdGlvbk1ldGhvZHMiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmVuY3J5cHRpb25NZXRob2QgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgRXZlbnQgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZXZlbnQiLCB0cnVlKTsKICAgIHRoaXMuYWN0aXZpdHkgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5hY3Rpdml0eSwgWyJjbGljayIsICJjaGFuZ2UiLCAiZG9jQ2xvc2UiLCAiZG9jUmVhZHkiLCAiZW50ZXIiLCAiZXhpdCIsICJmdWxsIiwgImluZGV4Q2hhbmdlIiwgImluaXRpYWxpemUiLCAibW91c2VEb3duIiwgIm1vdXNlRW50ZXIiLCAibW91c2VFeGl0IiwgIm1vdXNlVXAiLCAicG9zdEV4ZWN1dGUiLCAicG9zdE9wZW4iLCAicG9zdFByaW50IiwgInBvc3RTYXZlIiwgInBvc3RTaWduIiwgInBvc3RTdWJtaXQiLCAicHJlRXhlY3V0ZSIsICJwcmVPcGVuIiwgInByZVByaW50IiwgInByZVNhdmUiLCAicHJlU2lnbiIsICJwcmVTdWJtaXQiLCAicmVhZHkiLCAidmFsaWRhdGlvblN0YXRlIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxpc3RlbiA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmxpc3RlbiwgWyJyZWZPbmx5IiwgInJlZkFuZERlc2NlbmRlbnRzIl0pOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5yZWYgPSBhdHRyaWJ1dGVzLnJlZiB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLmVuY3J5cHREYXRhID0gbnVsbDsKICAgIHRoaXMuZXhlY3V0ZSA9IG51bGw7CiAgICB0aGlzLnNjcmlwdCA9IG51bGw7CiAgICB0aGlzLnNpZ25EYXRhID0gbnVsbDsKICAgIHRoaXMuc3VibWl0ID0gbnVsbDsKICB9Cn0KY2xhc3MgRXhEYXRhIGV4dGVuZHMgX3hmYV9vYmplY3QuQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJleERhdGEiKTsKICAgIHRoaXMuY29udGVudFR5cGUgPSBhdHRyaWJ1dGVzLmNvbnRlbnRUeXBlIHx8ICIiOwogICAgdGhpcy5ocmVmID0gYXR0cmlidXRlcy5ocmVmIHx8ICIiOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm1heExlbmd0aCA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLm1heExlbmd0aCwKICAgICAgZGVmYXVsdFZhbHVlOiAtMSwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAtMQogICAgfSk7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnJpZCA9IGF0dHJpYnV0ZXMucmlkIHx8ICIiOwogICAgdGhpcy50cmFuc2ZlckVuY29kaW5nID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMudHJhbnNmZXJFbmNvZGluZywgWyJub25lIiwgImJhc2U2NCIsICJwYWNrYWdlIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgW194ZmFfb2JqZWN0LiRpc0NEQVRBWG1sXSgpIHsKICAgIHJldHVybiB0aGlzLmNvbnRlbnRUeXBlID09PSAidGV4dC9odG1sIjsKICB9CiAgW194ZmFfb2JqZWN0LiRvbkNoaWxkXShjaGlsZCkgewogICAgaWYgKHRoaXMuY29udGVudFR5cGUgPT09ICJ0ZXh0L2h0bWwiICYmIGNoaWxkW194ZmFfb2JqZWN0LiRuYW1lc3BhY2VJZF0gPT09IF9uYW1lc3BhY2VzLk5hbWVzcGFjZUlkcy54aHRtbC5pZCkgewogICAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA9IGNoaWxkOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmICh0aGlzLmNvbnRlbnRUeXBlID09PSAidGV4dC94bWwiKSB7CiAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdID0gY2hpbGQ7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KICBbX3hmYV9vYmplY3QuJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGlmICh0aGlzLmNvbnRlbnRUeXBlICE9PSAidGV4dC9odG1sIiB8fCAhdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0pIHsKICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgcmV0dXJuIHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKTsKICB9Cn0KY2xhc3MgRXhPYmplY3QgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZXhPYmplY3QiLCB0cnVlKTsKICAgIHRoaXMuYXJjaGl2ZSA9IGF0dHJpYnV0ZXMuYXJjaGl2ZSB8fCAiIjsKICAgIHRoaXMuY2xhc3NJZCA9IGF0dHJpYnV0ZXMuY2xhc3NJZCB8fCAiIjsKICAgIHRoaXMuY29kZUJhc2UgPSBhdHRyaWJ1dGVzLmNvZGVCYXNlIHx8ICIiOwogICAgdGhpcy5jb2RlVHlwZSA9IGF0dHJpYnV0ZXMuY29kZVR5cGUgfHwgIiI7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLmJvb2xlYW4gPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGF0ZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlVGltZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZWNpbWFsID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4RGF0YSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leE9iamVjdCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5mbG9hdCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbWFnZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbnRlZ2VyID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRleHQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGltZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBFeGNsR3JvdXAgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZXhjbEdyb3VwIiwgdHJ1ZSk7CiAgICB0aGlzLmFjY2VzcyA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmFjY2VzcywgWyJvcGVuIiwgIm5vbkludGVyYWN0aXZlIiwgInByb3RlY3RlZCIsICJyZWFkT25seSJdKTsKICAgIHRoaXMuYWNjZXNzS2V5ID0gYXR0cmlidXRlcy5hY2Nlc3NLZXkgfHwgIiI7CiAgICB0aGlzLmFuY2hvclR5cGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5hbmNob3JUeXBlLCBbInRvcExlZnQiLCAiYm90dG9tQ2VudGVyIiwgImJvdHRvbUxlZnQiLCAiYm90dG9tUmlnaHQiLCAibWlkZGxlQ2VudGVyIiwgIm1pZGRsZUxlZnQiLCAibWlkZGxlUmlnaHQiLCAidG9wQ2VudGVyIiwgInRvcFJpZ2h0Il0pOwogICAgdGhpcy5jb2xTcGFuID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuY29sU3BhbiwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogbiA9PiBuID49IDEgfHwgbiA9PT0gLTEKICAgIH0pOwogICAgdGhpcy5oID0gYXR0cmlidXRlcy5oID8gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5oKSA6ICIiOwogICAgdGhpcy5oQWxpZ24gPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5oQWxpZ24sIFsibGVmdCIsICJjZW50ZXIiLCAianVzdGlmeSIsICJqdXN0aWZ5QWxsIiwgInJhZGl4IiwgInJpZ2h0Il0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxheW91dCA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmxheW91dCwgWyJwb3NpdGlvbiIsICJsci10YiIsICJybC1yb3ciLCAicmwtdGIiLCAicm93IiwgInRhYmxlIiwgInRiIl0pOwogICAgdGhpcy5tYXhIID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5tYXhILCAiMHB0Iik7CiAgICB0aGlzLm1heFcgPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLm1heFcsICIwcHQiKTsKICAgIHRoaXMubWluSCA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMubWluSCwgIjBwdCIpOwogICAgdGhpcy5taW5XID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5taW5XLCAiMHB0Iik7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnByZXNlbmNlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMucHJlc2VuY2UsIFsidmlzaWJsZSIsICJoaWRkZW4iLCAiaW5hY3RpdmUiLCAiaW52aXNpYmxlIl0pOwogICAgdGhpcy5yZWxldmFudCA9ICgwLCBfdXRpbHMuZ2V0UmVsZXZhbnQpKGF0dHJpYnV0ZXMucmVsZXZhbnQpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMudyA9IGF0dHJpYnV0ZXMudyA/ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMudykgOiAiIjsKICAgIHRoaXMueCA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMueCwgIjBwdCIpOwogICAgdGhpcy55ID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy55LCAiMHB0Iik7CiAgICB0aGlzLmFzc2lzdCA9IG51bGw7CiAgICB0aGlzLmJpbmQgPSBudWxsOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5jYWxjdWxhdGUgPSBudWxsOwogICAgdGhpcy5jYXB0aW9uID0gbnVsbDsKICAgIHRoaXMuZGVzYyA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgICB0aGlzLnBhcmEgPSBudWxsOwogICAgdGhpcy50cmF2ZXJzYWwgPSBudWxsOwogICAgdGhpcy52YWxpZGF0ZSA9IG51bGw7CiAgICB0aGlzLmNvbm5lY3QgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXZlbnQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmllbGQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2V0UHJvcGVydHkgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9CiAgW194ZmFfb2JqZWN0LiRpc0JpbmRhYmxlXSgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBbX3hmYV9vYmplY3QuJGhhc1NldHRhYmxlVmFsdWVdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIFtfeGZhX29iamVjdC4kc2V0VmFsdWVdKHZhbHVlKSB7CiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHRoaXMuZmllbGQuY2hpbGRyZW4pIHsKICAgICAgaWYgKCFmaWVsZC52YWx1ZSkgewogICAgICAgIGNvbnN0IG5vZGVWYWx1ZSA9IG5ldyBWYWx1ZSh7fSk7CiAgICAgICAgZmllbGRbX3hmYV9vYmplY3QuJGFwcGVuZENoaWxkXShub2RlVmFsdWUpOwogICAgICAgIGZpZWxkLnZhbHVlID0gbm9kZVZhbHVlOwogICAgICB9CiAgICAgIGZpZWxkLnZhbHVlW194ZmFfb2JqZWN0LiRzZXRWYWx1ZV0odmFsdWUpOwogICAgfQogIH0KICBbX3hmYV9vYmplY3QuJGlzVGhlcmVNb3JlV2lkdGhdKCkgewogICAgcmV0dXJuIHRoaXMubGF5b3V0LmVuZHNXaXRoKCItdGIiKSAmJiB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uYXR0ZW1wdCA9PT0gMCAmJiB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0ubnVtYmVySW5MaW5lID4gMCB8fCB0aGlzW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKClbX3hmYV9vYmplY3QuJGlzVGhlcmVNb3JlV2lkdGhdKCk7CiAgfQogIFtfeGZhX29iamVjdC4kaXNTcGxpdHRhYmxlXSgpIHsKICAgIGNvbnN0IHBhcmVudCA9IHRoaXNbX3hmYV9vYmplY3QuJGdldFN1YmZvcm1QYXJlbnRdKCk7CiAgICBpZiAoIXBhcmVudFtfeGZhX29iamVjdC4kaXNTcGxpdHRhYmxlXSgpKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmICh0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uX2lzU3BsaXR0YWJsZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uX2lzU3BsaXR0YWJsZTsKICAgIH0KICAgIGlmICh0aGlzLmxheW91dCA9PT0gInBvc2l0aW9uIiB8fCB0aGlzLmxheW91dC5pbmNsdWRlcygicm93IikpIHsKICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLl9pc1NwbGl0dGFibGUgPSBmYWxzZTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKHBhcmVudC5sYXlvdXQgJiYgcGFyZW50LmxheW91dC5lbmRzV2l0aCgiLXRiIikgJiYgcGFyZW50W194ZmFfb2JqZWN0LiRleHRyYV0ubnVtYmVySW5MaW5lICE9PSAwKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5faXNTcGxpdHRhYmxlID0gdHJ1ZTsKICAgIHJldHVybiB0cnVlOwogIH0KICBbX3hmYV9vYmplY3QuJGZsdXNoSFRNTF0oKSB7CiAgICByZXR1cm4gKDAsIF9sYXlvdXQuZmx1c2hIVE1MKSh0aGlzKTsKICB9CiAgW194ZmFfb2JqZWN0LiRhZGRIVE1MXShodG1sLCBiYm94KSB7CiAgICAoMCwgX2xheW91dC5hZGRIVE1MKSh0aGlzLCBodG1sLCBiYm94KTsKICB9CiAgW194ZmFfb2JqZWN0LiRnZXRBdmFpbGFibGVTcGFjZV0oKSB7CiAgICByZXR1cm4gKDAsIF9sYXlvdXQuZ2V0QXZhaWxhYmxlU3BhY2UpKHRoaXMpOwogIH0KICBbX3hmYV9vYmplY3QuJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIHNldFRhYkluZGV4KHRoaXMpOwogICAgaWYgKHRoaXMucHJlc2VuY2UgPT09ICJoaWRkZW4iIHx8IHRoaXMucHJlc2VuY2UgPT09ICJpbmFjdGl2ZSIgfHwgdGhpcy5oID09PSAwIHx8IHRoaXMudyA9PT0gMCkgewogICAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuRU1QVFk7CiAgICB9CiAgICAoMCwgX2h0bWxfdXRpbHMuZml4RGltZW5zaW9ucykodGhpcyk7CiAgICBjb25zdCBjaGlsZHJlbiA9IFtdOwogICAgY29uc3QgYXR0cmlidXRlcyA9IHsKICAgICAgaWQ6IHRoaXNbX3hmYV9vYmplY3QuJHVpZF0sCiAgICAgIGNsYXNzOiBbXQogICAgfTsKICAgICgwLCBfaHRtbF91dGlscy5zZXRBY2Nlc3MpKHRoaXMsIGF0dHJpYnV0ZXMuY2xhc3MpOwogICAgaWYgKCF0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0pIHsKICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIH0KICAgIE9iamVjdC5hc3NpZ24odGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLCB7CiAgICAgIGNoaWxkcmVuLAogICAgICBhdHRyaWJ1dGVzLAogICAgICBhdHRlbXB0OiAwLAogICAgICBsaW5lOiBudWxsLAogICAgICBudW1iZXJJbkxpbmU6IDAsCiAgICAgIGF2YWlsYWJsZVNwYWNlOiB7CiAgICAgICAgd2lkdGg6IE1hdGgubWluKHRoaXMudyB8fCBJbmZpbml0eSwgYXZhaWxhYmxlU3BhY2Uud2lkdGgpLAogICAgICAgIGhlaWdodDogTWF0aC5taW4odGhpcy5oIHx8IEluZmluaXR5LCBhdmFpbGFibGVTcGFjZS5oZWlnaHQpCiAgICAgIH0sCiAgICAgIHdpZHRoOiAwLAogICAgICBoZWlnaHQ6IDAsCiAgICAgIHByZXZIZWlnaHQ6IDAsCiAgICAgIGN1cnJlbnRXaWR0aDogMAogICAgfSk7CiAgICBjb25zdCBpc1NwbGl0dGFibGUgPSB0aGlzW194ZmFfb2JqZWN0LiRpc1NwbGl0dGFibGVdKCk7CiAgICBpZiAoIWlzU3BsaXR0YWJsZSkgewogICAgICBzZXRGaXJzdFVuc3BsaXR0YWJsZSh0aGlzKTsKICAgIH0KICAgIGlmICghKDAsIF9sYXlvdXQuY2hlY2tEaW1lbnNpb25zKSh0aGlzLCBhdmFpbGFibGVTcGFjZSkpIHsKICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LkZBSUxVUkU7CiAgICB9CiAgICBjb25zdCBmaWx0ZXIgPSBuZXcgU2V0KFsiZmllbGQiXSk7CiAgICBpZiAodGhpcy5sYXlvdXQuaW5jbHVkZXMoInJvdyIpKSB7CiAgICAgIGNvbnN0IGNvbHVtbldpZHRocyA9IHRoaXNbX3hmYV9vYmplY3QuJGdldFN1YmZvcm1QYXJlbnRdKCkuY29sdW1uV2lkdGhzOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShjb2x1bW5XaWR0aHMpICYmIGNvbHVtbldpZHRocy5sZW5ndGggPiAwKSB7CiAgICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmNvbHVtbldpZHRocyA9IGNvbHVtbldpZHRoczsKICAgICAgICB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uY3VycmVudENvbHVtbiA9IDA7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHN0eWxlID0gKDAsIF9odG1sX3V0aWxzLnRvU3R5bGUpKHRoaXMsICJhbmNob3JUeXBlIiwgImRpbWVuc2lvbnMiLCAicG9zaXRpb24iLCAicHJlc2VuY2UiLCAiYm9yZGVyIiwgIm1hcmdpbiIsICJoQWxpZ24iKTsKICAgIGNvbnN0IGNsYXNzTmFtZXMgPSBbInhmYUV4Y2xncm91cCJdOwogICAgY29uc3QgY2wgPSAoMCwgX2h0bWxfdXRpbHMubGF5b3V0Q2xhc3MpKHRoaXMpOwogICAgaWYgKGNsKSB7CiAgICAgIGNsYXNzTmFtZXMucHVzaChjbCk7CiAgICB9CiAgICBpZiAoKDAsIF9odG1sX3V0aWxzLmlzUHJpbnRPbmx5KSh0aGlzKSkgewogICAgICBjbGFzc05hbWVzLnB1c2goInhmYVByaW50T25seSIpOwogICAgfQogICAgYXR0cmlidXRlcy5zdHlsZSA9IHN0eWxlOwogICAgYXR0cmlidXRlcy5jbGFzcyA9IGNsYXNzTmFtZXM7CiAgICBpZiAodGhpcy5uYW1lKSB7CiAgICAgIGF0dHJpYnV0ZXMueGZhTmFtZSA9IHRoaXMubmFtZTsKICAgIH0KICAgIHRoaXNbX3hmYV9vYmplY3QuJHB1c2hQYXJhXSgpOwogICAgY29uc3QgaXNMclRiID0gdGhpcy5sYXlvdXQgPT09ICJsci10YiIgfHwgdGhpcy5sYXlvdXQgPT09ICJybC10YiI7CiAgICBjb25zdCBtYXhSdW4gPSBpc0xyVGIgPyBNQVhfQVRURU1QVFNfRk9SX0xSVEJfTEFZT1VUIDogMTsKICAgIGZvciAoOyB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uYXR0ZW1wdCA8IG1heFJ1bjsgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmF0dGVtcHQrKykgewogICAgICBpZiAoaXNMclRiICYmIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5hdHRlbXB0ID09PSBNQVhfQVRURU1QVFNfRk9SX0xSVEJfTEFZT1VUIC0gMSkgewogICAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5udW1iZXJJbkxpbmUgPSAwOwogICAgICB9CiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXNbX3hmYV9vYmplY3QuJGNoaWxkcmVuVG9IVE1MXSh7CiAgICAgICAgZmlsdGVyLAogICAgICAgIGluY2x1ZGU6IHRydWUKICAgICAgfSk7CiAgICAgIGlmIChyZXN1bHQuc3VjY2VzcykgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmIChyZXN1bHQuaXNCcmVhaygpKSB7CiAgICAgICAgdGhpc1tfeGZhX29iamVjdC4kcG9wUGFyYV0oKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CiAgICAgIGlmIChpc0xyVGIgJiYgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmF0dGVtcHQgPT09IDAgJiYgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLm51bWJlckluTGluZSA9PT0gMCAmJiAhdGhpc1tfeGZhX29iamVjdC4kZ2V0VGVtcGxhdGVSb290XSgpW194ZmFfb2JqZWN0LiRleHRyYV0ubm9MYXlvdXRGYWlsdXJlKSB7CiAgICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmF0dGVtcHQgPSBtYXhSdW47CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHRoaXNbX3hmYV9vYmplY3QuJHBvcFBhcmFdKCk7CiAgICBpZiAoIWlzU3BsaXR0YWJsZSkgewogICAgICB1bnNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgfQogICAgaWYgKHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5hdHRlbXB0ID09PSBtYXhSdW4pIHsKICAgICAgaWYgKCFpc1NwbGl0dGFibGUpIHsKICAgICAgICBkZWxldGUgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdOwogICAgICB9CiAgICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5GQUlMVVJFOwogICAgfQogICAgbGV0IG1hcmdpbkggPSAwOwogICAgbGV0IG1hcmdpblYgPSAwOwogICAgaWYgKHRoaXMubWFyZ2luKSB7CiAgICAgIG1hcmdpbkggPSB0aGlzLm1hcmdpbi5sZWZ0SW5zZXQgKyB0aGlzLm1hcmdpbi5yaWdodEluc2V0OwogICAgICBtYXJnaW5WID0gdGhpcy5tYXJnaW4udG9wSW5zZXQgKyB0aGlzLm1hcmdpbi5ib3R0b21JbnNldDsKICAgIH0KICAgIGNvbnN0IHdpZHRoID0gTWF0aC5tYXgodGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLndpZHRoICsgbWFyZ2luSCwgdGhpcy53IHx8IDApOwogICAgY29uc3QgaGVpZ2h0ID0gTWF0aC5tYXgodGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmhlaWdodCArIG1hcmdpblYsIHRoaXMuaCB8fCAwKTsKICAgIGNvbnN0IGJib3ggPSBbdGhpcy54LCB0aGlzLnksIHdpZHRoLCBoZWlnaHRdOwogICAgaWYgKHRoaXMudyA9PT0gIiIpIHsKICAgICAgc3R5bGUud2lkdGggPSAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSh3aWR0aCk7CiAgICB9CiAgICBpZiAodGhpcy5oID09PSAiIikgewogICAgICBzdHlsZS5oZWlnaHQgPSAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKShoZWlnaHQpOwogICAgfQogICAgY29uc3QgaHRtbCA9IHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGNoaWxkcmVuCiAgICB9OwogICAgYXBwbHlBc3Npc3QodGhpcywgYXR0cmlidXRlcyk7CiAgICBkZWxldGUgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdOwogICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3MoKDAsIF9odG1sX3V0aWxzLmNyZWF0ZVdyYXBwZXIpKHRoaXMsIGh0bWwpLCBiYm94KTsKICB9Cn0KY2xhc3MgRXhlY3V0ZSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJleGVjdXRlIik7CiAgICB0aGlzLmNvbm5lY3Rpb24gPSBhdHRyaWJ1dGVzLmNvbm5lY3Rpb24gfHwgIiI7CiAgICB0aGlzLmV4ZWN1dGVUeXBlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuZXhlY3V0ZVR5cGUsIFsiaW1wb3J0IiwgInJlbWVyZ2UiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMucnVuQXQgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5ydW5BdCwgWyJjbGllbnQiLCAiYm90aCIsICJzZXJ2ZXIiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBFeHRyYXMgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZXh0cmFzIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmJvb2xlYW4gPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGF0ZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlVGltZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZWNpbWFsID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4RGF0YSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leHRyYXMgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmxvYXQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaW1hZ2UgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaW50ZWdlciA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50ZXh0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRpbWUgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgRmllbGQgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZmllbGQiLCB0cnVlKTsKICAgIHRoaXMuYWNjZXNzID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuYWNjZXNzLCBbIm9wZW4iLCAibm9uSW50ZXJhY3RpdmUiLCAicHJvdGVjdGVkIiwgInJlYWRPbmx5Il0pOwogICAgdGhpcy5hY2Nlc3NLZXkgPSBhdHRyaWJ1dGVzLmFjY2Vzc0tleSB8fCAiIjsKICAgIHRoaXMuYW5jaG9yVHlwZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmFuY2hvclR5cGUsIFsidG9wTGVmdCIsICJib3R0b21DZW50ZXIiLCAiYm90dG9tTGVmdCIsICJib3R0b21SaWdodCIsICJtaWRkbGVDZW50ZXIiLCAibWlkZGxlTGVmdCIsICJtaWRkbGVSaWdodCIsICJ0b3BDZW50ZXIiLCAidG9wUmlnaHQiXSk7CiAgICB0aGlzLmNvbFNwYW4gPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5jb2xTcGFuLAogICAgICBkZWZhdWx0VmFsdWU6IDEsCiAgICAgIHZhbGlkYXRlOiBuID0+IG4gPj0gMSB8fCBuID09PSAtMQogICAgfSk7CiAgICB0aGlzLmggPSBhdHRyaWJ1dGVzLmggPyAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLmgpIDogIiI7CiAgICB0aGlzLmhBbGlnbiA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmhBbGlnbiwgWyJsZWZ0IiwgImNlbnRlciIsICJqdXN0aWZ5IiwgImp1c3RpZnlBbGwiLCAicmFkaXgiLCAicmlnaHQiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubG9jYWxlID0gYXR0cmlidXRlcy5sb2NhbGUgfHwgIiI7CiAgICB0aGlzLm1heEggPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLm1heEgsICIwcHQiKTsKICAgIHRoaXMubWF4VyA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMubWF4VywgIjBwdCIpOwogICAgdGhpcy5taW5IID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5taW5ILCAiMHB0Iik7CiAgICB0aGlzLm1pblcgPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLm1pblcsICIwcHQiKTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucHJlc2VuY2UgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5wcmVzZW5jZSwgWyJ2aXNpYmxlIiwgImhpZGRlbiIsICJpbmFjdGl2ZSIsICJpbnZpc2libGUiXSk7CiAgICB0aGlzLnJlbGV2YW50ID0gKDAsIF91dGlscy5nZXRSZWxldmFudCkoYXR0cmlidXRlcy5yZWxldmFudCk7CiAgICB0aGlzLnJvdGF0ZSA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnJvdGF0ZSwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ICUgOTAgPT09IDAKICAgIH0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMudyA9IGF0dHJpYnV0ZXMudyA/ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMudykgOiAiIjsKICAgIHRoaXMueCA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMueCwgIjBwdCIpOwogICAgdGhpcy55ID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy55LCAiMHB0Iik7CiAgICB0aGlzLmFzc2lzdCA9IG51bGw7CiAgICB0aGlzLmJpbmQgPSBudWxsOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5jYWxjdWxhdGUgPSBudWxsOwogICAgdGhpcy5jYXB0aW9uID0gbnVsbDsKICAgIHRoaXMuZGVzYyA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLmZvbnQgPSBudWxsOwogICAgdGhpcy5mb3JtYXQgPSBudWxsOwogICAgdGhpcy5pdGVtcyA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgyKTsKICAgIHRoaXMua2VlcCA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgICB0aGlzLnBhcmEgPSBudWxsOwogICAgdGhpcy50cmF2ZXJzYWwgPSBudWxsOwogICAgdGhpcy51aSA9IG51bGw7CiAgICB0aGlzLnZhbGlkYXRlID0gbnVsbDsKICAgIHRoaXMudmFsdWUgPSBudWxsOwogICAgdGhpcy5iaW5kSXRlbXMgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY29ubmVjdCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5ldmVudCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zZXRQcm9wZXJ0eSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KICBbX3hmYV9vYmplY3QuJGlzQmluZGFibGVdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIFtfeGZhX29iamVjdC4kc2V0VmFsdWVdKHZhbHVlKSB7CiAgICBfc2V0VmFsdWUodGhpcywgdmFsdWUpOwogIH0KICBbX3hmYV9vYmplY3QuJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIHNldFRhYkluZGV4KHRoaXMpOwogICAgaWYgKCF0aGlzLnVpKSB7CiAgICAgIHRoaXMudWkgPSBuZXcgVWkoe30pOwogICAgICB0aGlzLnVpW194ZmFfb2JqZWN0LiRnbG9iYWxEYXRhXSA9IHRoaXNbX3hmYV9vYmplY3QuJGdsb2JhbERhdGFdOwogICAgICB0aGlzW194ZmFfb2JqZWN0LiRhcHBlbmRDaGlsZF0odGhpcy51aSk7CiAgICAgIGxldCBub2RlOwogICAgICBzd2l0Y2ggKHRoaXMuaXRlbXMuY2hpbGRyZW4ubGVuZ3RoKSB7CiAgICAgICAgY2FzZSAwOgogICAgICAgICAgbm9kZSA9IG5ldyBUZXh0RWRpdCh7fSk7CiAgICAgICAgICB0aGlzLnVpLnRleHRFZGl0ID0gbm9kZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMToKICAgICAgICAgIG5vZGUgPSBuZXcgQ2hlY2tCdXR0b24oe30pOwogICAgICAgICAgdGhpcy51aS5jaGVja0J1dHRvbiA9IG5vZGU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI6CiAgICAgICAgICBub2RlID0gbmV3IENob2ljZUxpc3Qoe30pOwogICAgICAgICAgdGhpcy51aS5jaG9pY2VMaXN0ID0gbm9kZTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHRoaXMudWlbX3hmYV9vYmplY3QuJGFwcGVuZENoaWxkXShub2RlKTsKICAgIH0KICAgIGlmICghdGhpcy51aSB8fCB0aGlzLnByZXNlbmNlID09PSAiaGlkZGVuIiB8fCB0aGlzLnByZXNlbmNlID09PSAiaW5hY3RpdmUiIHx8IHRoaXMuaCA9PT0gMCB8fCB0aGlzLncgPT09IDApIHsKICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgaWYgKHRoaXMuY2FwdGlvbikgewogICAgICBkZWxldGUgdGhpcy5jYXB0aW9uW194ZmFfb2JqZWN0LiRleHRyYV07CiAgICB9CiAgICB0aGlzW194ZmFfb2JqZWN0LiRwdXNoUGFyYV0oKTsKICAgIGNvbnN0IGNhcHRpb24gPSB0aGlzLmNhcHRpb24gPyB0aGlzLmNhcHRpb25bX3hmYV9vYmplY3QuJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpLmh0bWwgOiBudWxsOwogICAgY29uc3Qgc2F2ZWRXID0gdGhpcy53OwogICAgY29uc3Qgc2F2ZWRIID0gdGhpcy5oOwogICAgbGV0IG1hcmdpbkggPSAwOwogICAgbGV0IG1hcmdpblYgPSAwOwogICAgaWYgKHRoaXMubWFyZ2luKSB7CiAgICAgIG1hcmdpbkggPSB0aGlzLm1hcmdpbi5sZWZ0SW5zZXQgKyB0aGlzLm1hcmdpbi5yaWdodEluc2V0OwogICAgICBtYXJnaW5WID0gdGhpcy5tYXJnaW4udG9wSW5zZXQgKyB0aGlzLm1hcmdpbi5ib3R0b21JbnNldDsKICAgIH0KICAgIGxldCBib3JkZXJEaW1zID0gbnVsbDsKICAgIGlmICh0aGlzLncgPT09ICIiIHx8IHRoaXMuaCA9PT0gIiIpIHsKICAgICAgbGV0IHdpZHRoID0gbnVsbDsKICAgICAgbGV0IGhlaWdodCA9IG51bGw7CiAgICAgIGxldCB1aVcgPSAwOwogICAgICBsZXQgdWlIID0gMDsKICAgICAgaWYgKHRoaXMudWkuY2hlY2tCdXR0b24pIHsKICAgICAgICB1aVcgPSB1aUggPSB0aGlzLnVpLmNoZWNrQnV0dG9uLnNpemU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgewogICAgICAgICAgdywKICAgICAgICAgIGgKICAgICAgICB9ID0gKDAsIF9odG1sX3V0aWxzLmxheW91dE5vZGUpKHRoaXMsIGF2YWlsYWJsZVNwYWNlKTsKICAgICAgICBpZiAodyAhPT0gbnVsbCkgewogICAgICAgICAgdWlXID0gdzsKICAgICAgICAgIHVpSCA9IGg7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHVpSCA9ICgwLCBfZm9udHMuZ2V0TWV0cmljcykodGhpcy5mb250LCB0cnVlKS5saW5lTm9HYXA7CiAgICAgICAgfQogICAgICB9CiAgICAgIGJvcmRlckRpbXMgPSBnZXRCb3JkZXJEaW1zKHRoaXMudWlbX3hmYV9vYmplY3QuJGdldEV4dHJhXSgpKTsKICAgICAgdWlXICs9IGJvcmRlckRpbXMudzsKICAgICAgdWlIICs9IGJvcmRlckRpbXMuaDsKICAgICAgaWYgKHRoaXMuY2FwdGlvbikgewogICAgICAgIGNvbnN0IHsKICAgICAgICAgIHcsCiAgICAgICAgICBoLAogICAgICAgICAgaXNCcm9rZW4KICAgICAgICB9ID0gdGhpcy5jYXB0aW9uW194ZmFfb2JqZWN0LiRnZXRFeHRyYV0oYXZhaWxhYmxlU3BhY2UpOwogICAgICAgIGlmIChpc0Jyb2tlbiAmJiB0aGlzW194ZmFfb2JqZWN0LiRnZXRTdWJmb3JtUGFyZW50XSgpW194ZmFfb2JqZWN0LiRpc1RoZXJlTW9yZVdpZHRoXSgpKSB7CiAgICAgICAgICB0aGlzW194ZmFfb2JqZWN0LiRwb3BQYXJhXSgpOwogICAgICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LkZBSUxVUkU7CiAgICAgICAgfQogICAgICAgIHdpZHRoID0gdzsKICAgICAgICBoZWlnaHQgPSBoOwogICAgICAgIHN3aXRjaCAodGhpcy5jYXB0aW9uLnBsYWNlbWVudCkgewogICAgICAgICAgY2FzZSAibGVmdCI6CiAgICAgICAgICBjYXNlICJyaWdodCI6CiAgICAgICAgICBjYXNlICJpbmxpbmUiOgogICAgICAgICAgICB3aWR0aCArPSB1aVc7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAidG9wIjoKICAgICAgICAgIGNhc2UgImJvdHRvbSI6CiAgICAgICAgICAgIGhlaWdodCArPSB1aUg7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB3aWR0aCA9IHVpVzsKICAgICAgICBoZWlnaHQgPSB1aUg7CiAgICAgIH0KICAgICAgaWYgKHdpZHRoICYmIHRoaXMudyA9PT0gIiIpIHsKICAgICAgICB3aWR0aCArPSBtYXJnaW5IOwogICAgICAgIHRoaXMudyA9IE1hdGgubWluKHRoaXMubWF4VyA8PSAwID8gSW5maW5pdHkgOiB0aGlzLm1heFcsIHRoaXMubWluVyArIDEgPCB3aWR0aCA/IHdpZHRoIDogdGhpcy5taW5XKTsKICAgICAgfQogICAgICBpZiAoaGVpZ2h0ICYmIHRoaXMuaCA9PT0gIiIpIHsKICAgICAgICBoZWlnaHQgKz0gbWFyZ2luVjsKICAgICAgICB0aGlzLmggPSBNYXRoLm1pbih0aGlzLm1heEggPD0gMCA/IEluZmluaXR5IDogdGhpcy5tYXhILCB0aGlzLm1pbkggKyAxIDwgaGVpZ2h0ID8gaGVpZ2h0IDogdGhpcy5taW5IKTsKICAgICAgfQogICAgfQogICAgdGhpc1tfeGZhX29iamVjdC4kcG9wUGFyYV0oKTsKICAgICgwLCBfaHRtbF91dGlscy5maXhEaW1lbnNpb25zKSh0aGlzKTsKICAgIHNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgaWYgKCEoMCwgX2xheW91dC5jaGVja0RpbWVuc2lvbnMpKHRoaXMsIGF2YWlsYWJsZVNwYWNlKSkgewogICAgICB0aGlzLncgPSBzYXZlZFc7CiAgICAgIHRoaXMuaCA9IHNhdmVkSDsKICAgICAgdGhpc1tfeGZhX29iamVjdC4kcG9wUGFyYV0oKTsKICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LkZBSUxVUkU7CiAgICB9CiAgICB1bnNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgY29uc3Qgc3R5bGUgPSAoMCwgX2h0bWxfdXRpbHMudG9TdHlsZSkodGhpcywgImZvbnQiLCAiZGltZW5zaW9ucyIsICJwb3NpdGlvbiIsICJyb3RhdGUiLCAiYW5jaG9yVHlwZSIsICJwcmVzZW5jZSIsICJtYXJnaW4iLCAiaEFsaWduIik7CiAgICAoMCwgX2h0bWxfdXRpbHMuc2V0TWluTWF4RGltZW5zaW9ucykodGhpcywgc3R5bGUpOwogICAgY29uc3QgY2xhc3NOYW1lcyA9IFsieGZhRmllbGQiXTsKICAgIGlmICh0aGlzLmZvbnQpIHsKICAgICAgY2xhc3NOYW1lcy5wdXNoKCJ4ZmFGb250Iik7CiAgICB9CiAgICBpZiAoKDAsIF9odG1sX3V0aWxzLmlzUHJpbnRPbmx5KSh0aGlzKSkgewogICAgICBjbGFzc05hbWVzLnB1c2goInhmYVByaW50T25seSIpOwogICAgfQogICAgY29uc3QgYXR0cmlidXRlcyA9IHsKICAgICAgc3R5bGUsCiAgICAgIGlkOiB0aGlzW194ZmFfb2JqZWN0LiR1aWRdLAogICAgICBjbGFzczogY2xhc3NOYW1lcwogICAgfTsKICAgIGlmIChzdHlsZS5tYXJnaW4pIHsKICAgICAgc3R5bGUucGFkZGluZyA9IHN0eWxlLm1hcmdpbjsKICAgICAgZGVsZXRlIHN0eWxlLm1hcmdpbjsKICAgIH0KICAgICgwLCBfaHRtbF91dGlscy5zZXRBY2Nlc3MpKHRoaXMsIGNsYXNzTmFtZXMpOwogICAgaWYgKHRoaXMubmFtZSkgewogICAgICBhdHRyaWJ1dGVzLnhmYU5hbWUgPSB0aGlzLm5hbWU7CiAgICB9CiAgICBjb25zdCBjaGlsZHJlbiA9IFtdOwogICAgY29uc3QgaHRtbCA9IHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGNoaWxkcmVuCiAgICB9OwogICAgYXBwbHlBc3Npc3QodGhpcywgYXR0cmlidXRlcyk7CiAgICBjb25zdCBib3JkZXJTdHlsZSA9IHRoaXMuYm9yZGVyID8gdGhpcy5ib3JkZXJbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCkgOiBudWxsOwogICAgY29uc3QgYmJveCA9ICgwLCBfaHRtbF91dGlscy5jb21wdXRlQmJveCkodGhpcywgaHRtbCwgYXZhaWxhYmxlU3BhY2UpOwogICAgY29uc3QgdWkgPSB0aGlzLnVpW194ZmFfb2JqZWN0LiR0b0hUTUxdKCkuaHRtbDsKICAgIGlmICghdWkpIHsKICAgICAgT2JqZWN0LmFzc2lnbihzdHlsZSwgYm9yZGVyU3R5bGUpOwogICAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2VzcygoMCwgX2h0bWxfdXRpbHMuY3JlYXRlV3JhcHBlcikodGhpcywgaHRtbCksIGJib3gpOwogICAgfQogICAgaWYgKHRoaXNbX3hmYV9vYmplY3QuJHRhYkluZGV4XSkgewogICAgICBpZiAodWkuY2hpbGRyZW4gJiYgdWkuY2hpbGRyZW5bMF0pIHsKICAgICAgICB1aS5jaGlsZHJlblswXS5hdHRyaWJ1dGVzLnRhYmluZGV4ID0gdGhpc1tfeGZhX29iamVjdC4kdGFiSW5kZXhdOwogICAgICB9IGVsc2UgewogICAgICAgIHVpLmF0dHJpYnV0ZXMudGFiaW5kZXggPSB0aGlzW194ZmFfb2JqZWN0LiR0YWJJbmRleF07CiAgICAgIH0KICAgIH0KICAgIGlmICghdWkuYXR0cmlidXRlcy5zdHlsZSkgewogICAgICB1aS5hdHRyaWJ1dGVzLnN0eWxlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIH0KICAgIGxldCBhRWxlbWVudCA9IG51bGw7CiAgICBpZiAodGhpcy51aS5idXR0b24pIHsKICAgICAgaWYgKHVpLmNoaWxkcmVuLmxlbmd0aCA9PT0gMSkgewogICAgICAgIFthRWxlbWVudF0gPSB1aS5jaGlsZHJlbi5zcGxpY2UoMCwgMSk7CiAgICAgIH0KICAgICAgT2JqZWN0LmFzc2lnbih1aS5hdHRyaWJ1dGVzLnN0eWxlLCBib3JkZXJTdHlsZSk7CiAgICB9IGVsc2UgewogICAgICBPYmplY3QuYXNzaWduKHN0eWxlLCBib3JkZXJTdHlsZSk7CiAgICB9CiAgICBjaGlsZHJlbi5wdXNoKHVpKTsKICAgIGlmICh0aGlzLnZhbHVlKSB7CiAgICAgIGlmICh0aGlzLnVpLmltYWdlRWRpdCkgewogICAgICAgIHVpLmNoaWxkcmVuLnB1c2godGhpcy52YWx1ZVtfeGZhX29iamVjdC4kdG9IVE1MXSgpLmh0bWwpOwogICAgICB9IGVsc2UgaWYgKCF0aGlzLnVpLmJ1dHRvbikgewogICAgICAgIGxldCB2YWx1ZSA9ICIiOwogICAgICAgIGlmICh0aGlzLnZhbHVlLmV4RGF0YSkgewogICAgICAgICAgdmFsdWUgPSB0aGlzLnZhbHVlLmV4RGF0YVtfeGZhX29iamVjdC4kdGV4dF0oKTsKICAgICAgICB9IGVsc2UgaWYgKHRoaXMudmFsdWUudGV4dCkgewogICAgICAgICAgdmFsdWUgPSB0aGlzLnZhbHVlLnRleHRbX3hmYV9vYmplY3QuJGdldEV4dHJhXSgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb25zdCBodG1sVmFsdWUgPSB0aGlzLnZhbHVlW194ZmFfb2JqZWN0LiR0b0hUTUxdKCkuaHRtbDsKICAgICAgICAgIGlmIChodG1sVmFsdWUgIT09IG51bGwpIHsKICAgICAgICAgICAgdmFsdWUgPSBodG1sVmFsdWUuY2hpbGRyZW5bMF0udmFsdWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICh0aGlzLnVpLnRleHRFZGl0ICYmIHRoaXMudmFsdWUudGV4dCAmJiB0aGlzLnZhbHVlLnRleHQubWF4Q2hhcnMpIHsKICAgICAgICAgIHVpLmNoaWxkcmVuWzBdLmF0dHJpYnV0ZXMubWF4TGVuZ3RoID0gdGhpcy52YWx1ZS50ZXh0Lm1heENoYXJzOwogICAgICAgIH0KICAgICAgICBpZiAodmFsdWUpIHsKICAgICAgICAgIGlmICh0aGlzLnVpLm51bWVyaWNFZGl0KSB7CiAgICAgICAgICAgIHZhbHVlID0gcGFyc2VGbG9hdCh2YWx1ZSk7CiAgICAgICAgICAgIHZhbHVlID0gaXNOYU4odmFsdWUpID8gIiIgOiB2YWx1ZS50b1N0cmluZygpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHVpLmNoaWxkcmVuWzBdLm5hbWUgPT09ICJ0ZXh0YXJlYSIpIHsKICAgICAgICAgICAgdWkuY2hpbGRyZW5bMF0uYXR0cmlidXRlcy50ZXh0Q29udGVudCA9IHZhbHVlOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdWkuY2hpbGRyZW5bMF0uYXR0cmlidXRlcy52YWx1ZSA9IHZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKCF0aGlzLnVpLmltYWdlRWRpdCAmJiB1aS5jaGlsZHJlbiAmJiB1aS5jaGlsZHJlblswXSAmJiB0aGlzLmgpIHsKICAgICAgYm9yZGVyRGltcyA9IGJvcmRlckRpbXMgfHwgZ2V0Qm9yZGVyRGltcyh0aGlzLnVpW194ZmFfb2JqZWN0LiRnZXRFeHRyYV0oKSk7CiAgICAgIGxldCBjYXB0aW9uSGVpZ2h0ID0gMDsKICAgICAgaWYgKHRoaXMuY2FwdGlvbiAmJiBbInRvcCIsICJib3R0b20iXS5pbmNsdWRlcyh0aGlzLmNhcHRpb24ucGxhY2VtZW50KSkgewogICAgICAgIGNhcHRpb25IZWlnaHQgPSB0aGlzLmNhcHRpb24ucmVzZXJ2ZTsKICAgICAgICBpZiAoY2FwdGlvbkhlaWdodCA8PSAwKSB7CiAgICAgICAgICBjYXB0aW9uSGVpZ2h0ID0gdGhpcy5jYXB0aW9uW194ZmFfb2JqZWN0LiRnZXRFeHRyYV0oYXZhaWxhYmxlU3BhY2UpLmg7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGlucHV0SGVpZ2h0ID0gdGhpcy5oIC0gY2FwdGlvbkhlaWdodCAtIG1hcmdpblYgLSBib3JkZXJEaW1zLmg7CiAgICAgICAgdWkuY2hpbGRyZW5bMF0uYXR0cmlidXRlcy5zdHlsZS5oZWlnaHQgPSAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKShpbnB1dEhlaWdodCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdWkuY2hpbGRyZW5bMF0uYXR0cmlidXRlcy5zdHlsZS5oZWlnaHQgPSAiMTAwJSI7CiAgICAgIH0KICAgIH0KICAgIGlmIChhRWxlbWVudCkgewogICAgICB1aS5jaGlsZHJlbi5wdXNoKGFFbGVtZW50KTsKICAgIH0KICAgIGlmICghY2FwdGlvbikgewogICAgICBpZiAodWkuYXR0cmlidXRlcy5jbGFzcykgewogICAgICAgIHVpLmF0dHJpYnV0ZXMuY2xhc3MucHVzaCgieGZhTGVmdCIpOwogICAgICB9CiAgICAgIHRoaXMudyA9IHNhdmVkVzsKICAgICAgdGhpcy5oID0gc2F2ZWRIOwogICAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2VzcygoMCwgX2h0bWxfdXRpbHMuY3JlYXRlV3JhcHBlcikodGhpcywgaHRtbCksIGJib3gpOwogICAgfQogICAgaWYgKHRoaXMudWkuYnV0dG9uKSB7CiAgICAgIGlmIChzdHlsZS5wYWRkaW5nKSB7CiAgICAgICAgZGVsZXRlIHN0eWxlLnBhZGRpbmc7CiAgICAgIH0KICAgICAgaWYgKGNhcHRpb24ubmFtZSA9PT0gImRpdiIpIHsKICAgICAgICBjYXB0aW9uLm5hbWUgPSAic3BhbiI7CiAgICAgIH0KICAgICAgdWkuY2hpbGRyZW4ucHVzaChjYXB0aW9uKTsKICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3MoaHRtbCwgYmJveCk7CiAgICB9IGVsc2UgaWYgKHRoaXMudWkuY2hlY2tCdXR0b24pIHsKICAgICAgY2FwdGlvbi5hdHRyaWJ1dGVzLmNsYXNzWzBdID0gInhmYUNhcHRpb25Gb3JDaGVja0J1dHRvbiI7CiAgICB9CiAgICBpZiAoIXVpLmF0dHJpYnV0ZXMuY2xhc3MpIHsKICAgICAgdWkuYXR0cmlidXRlcy5jbGFzcyA9IFtdOwogICAgfQogICAgdWkuY2hpbGRyZW4uc3BsaWNlKDAsIDAsIGNhcHRpb24pOwogICAgc3dpdGNoICh0aGlzLmNhcHRpb24ucGxhY2VtZW50KSB7CiAgICAgIGNhc2UgImxlZnQiOgogICAgICAgIHVpLmF0dHJpYnV0ZXMuY2xhc3MucHVzaCgieGZhTGVmdCIpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJyaWdodCI6CiAgICAgICAgdWkuYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFSaWdodCIpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJ0b3AiOgogICAgICAgIHVpLmF0dHJpYnV0ZXMuY2xhc3MucHVzaCgieGZhVG9wIik7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgImJvdHRvbSI6CiAgICAgICAgdWkuYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFCb3R0b20iKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiaW5saW5lIjoKICAgICAgICB1aS5hdHRyaWJ1dGVzLmNsYXNzLnB1c2goInhmYUxlZnQiKTsKICAgICAgICBicmVhazsKICAgIH0KICAgIHRoaXMudyA9IHNhdmVkVzsKICAgIHRoaXMuaCA9IHNhdmVkSDsKICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5zdWNjZXNzKCgwLCBfaHRtbF91dGlscy5jcmVhdGVXcmFwcGVyKSh0aGlzLCBodG1sKSwgYmJveCk7CiAgfQp9CmV4cG9ydHMuRmllbGQgPSBGaWVsZDsKY2xhc3MgRmlsbCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJmaWxsIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMucHJlc2VuY2UgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5wcmVzZW5jZSwgWyJ2aXNpYmxlIiwgImhpZGRlbiIsICJpbmFjdGl2ZSIsICJpbnZpc2libGUiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5jb2xvciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLmxpbmVhciA9IG51bGw7CiAgICB0aGlzLnBhdHRlcm4gPSBudWxsOwogICAgdGhpcy5yYWRpYWwgPSBudWxsOwogICAgdGhpcy5zb2xpZCA9IG51bGw7CiAgICB0aGlzLnN0aXBwbGUgPSBudWxsOwogIH0KICBbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCkgewogICAgY29uc3QgcGFyZW50ID0gdGhpc1tfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpOwogICAgY29uc3QgZ3JhbmRwYSA9IHBhcmVudFtfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpOwogICAgY29uc3QgZ2dyYW5kcGEgPSBncmFuZHBhW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBzdHlsZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBsZXQgcHJvcE5hbWUgPSAiY29sb3IiOwogICAgbGV0IGFsdFByb3BOYW1lID0gcHJvcE5hbWU7CiAgICBpZiAocGFyZW50IGluc3RhbmNlb2YgQm9yZGVyKSB7CiAgICAgIHByb3BOYW1lID0gImJhY2tncm91bmQtY29sb3IiOwogICAgICBhbHRQcm9wTmFtZSA9ICJiYWNrZ3JvdW5kIjsKICAgICAgaWYgKGdncmFuZHBhIGluc3RhbmNlb2YgVWkpIHsKICAgICAgICBzdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSAid2hpdGUiOwogICAgICB9CiAgICB9CiAgICBpZiAocGFyZW50IGluc3RhbmNlb2YgUmVjdGFuZ2xlIHx8IHBhcmVudCBpbnN0YW5jZW9mIEFyYykgewogICAgICBwcm9wTmFtZSA9IGFsdFByb3BOYW1lID0gImZpbGwiOwogICAgICBzdHlsZS5maWxsID0gIndoaXRlIjsKICAgIH0KICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSkgewogICAgICBpZiAobmFtZSA9PT0gImV4dHJhcyIgfHwgbmFtZSA9PT0gImNvbG9yIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IG9iaiA9IHRoaXNbbmFtZV07CiAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIF94ZmFfb2JqZWN0LlhGQU9iamVjdCkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBjb2xvciA9IG9ialtfeGZhX29iamVjdC4kdG9TdHlsZV0odGhpcy5jb2xvcik7CiAgICAgIGlmIChjb2xvcikgewogICAgICAgIHN0eWxlW2NvbG9yLnN0YXJ0c1dpdGgoIiMiKSA/IHByb3BOYW1lIDogYWx0UHJvcE5hbWVdID0gY29sb3I7CiAgICAgIH0KICAgICAgcmV0dXJuIHN0eWxlOwogICAgfQogICAgaWYgKHRoaXMuY29sb3IgJiYgdGhpcy5jb2xvci52YWx1ZSkgewogICAgICBjb25zdCBjb2xvciA9IHRoaXMuY29sb3JbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCk7CiAgICAgIHN0eWxlW2NvbG9yLnN0YXJ0c1dpdGgoIiMiKSA/IHByb3BOYW1lIDogYWx0UHJvcE5hbWVdID0gY29sb3I7CiAgICB9CiAgICByZXR1cm4gc3R5bGU7CiAgfQp9CmNsYXNzIEZpbHRlciBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJmaWx0ZXIiLCB0cnVlKTsKICAgIHRoaXMuYWRkUmV2b2NhdGlvbkluZm8gPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5hZGRSZXZvY2F0aW9uSW5mbywgWyIiLCAicmVxdWlyZWQiLCAib3B0aW9uYWwiLCAibm9uZSJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMudmVyc2lvbiA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiB0aGlzLnZlcnNpb24sCiAgICAgIGRlZmF1bHRWYWx1ZTogNSwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAxICYmIHggPD0gNQogICAgfSk7CiAgICB0aGlzLmFwcGVhcmFuY2VGaWx0ZXIgPSBudWxsOwogICAgdGhpcy5jZXJ0aWZpY2F0ZXMgPSBudWxsOwogICAgdGhpcy5kaWdlc3RNZXRob2RzID0gbnVsbDsKICAgIHRoaXMuZW5jb2RpbmdzID0gbnVsbDsKICAgIHRoaXMuZW5jcnlwdGlvbk1ldGhvZHMgPSBudWxsOwogICAgdGhpcy5oYW5kbGVyID0gbnVsbDsKICAgIHRoaXMubG9ja0RvY3VtZW50ID0gbnVsbDsKICAgIHRoaXMubWRwID0gbnVsbDsKICAgIHRoaXMucmVhc29ucyA9IG51bGw7CiAgICB0aGlzLnRpbWVTdGFtcCA9IG51bGw7CiAgfQp9CmNsYXNzIEZsb2F0IGV4dGVuZHMgX3hmYV9vYmplY3QuQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJmbG9hdCIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KICBbX3hmYV9vYmplY3QuJGZpbmFsaXplXSgpIHsKICAgIGNvbnN0IG51bWJlciA9IHBhcnNlRmxvYXQodGhpc1tfeGZhX29iamVjdC4kY29udGVudF0udHJpbSgpKTsKICAgIHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdID0gaXNOYU4obnVtYmVyKSA/IG51bGwgOiBudW1iZXI7CiAgfQogIFtfeGZhX29iamVjdC4kdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgcmV0dXJuIHZhbHVlVG9IdG1sKHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdICE9PSBudWxsID8gdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0udG9TdHJpbmcoKSA6ICIiKTsKICB9Cn0KY2xhc3MgRm9udCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJmb250IiwgdHJ1ZSk7CiAgICB0aGlzLmJhc2VsaW5lU2hpZnQgPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLmJhc2VsaW5lU2hpZnQpOwogICAgdGhpcy5mb250SG9yaXpvbnRhbFNjYWxlID0gKDAsIF91dGlscy5nZXRGbG9hdCkoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmZvbnRIb3Jpem9udGFsU2NhbGUsCiAgICAgIGRlZmF1bHRWYWx1ZTogMTAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy5mb250VmVydGljYWxTY2FsZSA9ICgwLCBfdXRpbHMuZ2V0RmxvYXQpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5mb250VmVydGljYWxTY2FsZSwKICAgICAgZGVmYXVsdFZhbHVlOiAxMDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMAogICAgfSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMua2VybmluZ01vZGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5rZXJuaW5nTW9kZSwgWyJub25lIiwgInBhaXIiXSk7CiAgICB0aGlzLmxldHRlclNwYWNpbmcgPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLmxldHRlclNwYWNpbmcsICIwIik7CiAgICB0aGlzLmxpbmVUaHJvdWdoID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMubGluZVRocm91Z2gsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMSB8fCB4ID09PSAyCiAgICB9KTsKICAgIHRoaXMubGluZVRocm91Z2hQZXJpb2QgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5saW5lVGhyb3VnaFBlcmlvZCwgWyJhbGwiLCAid29yZCJdKTsKICAgIHRoaXMub3ZlcmxpbmUgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5vdmVybGluZSwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxIHx8IHggPT09IDIKICAgIH0pOwogICAgdGhpcy5vdmVybGluZVBlcmlvZCA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLm92ZXJsaW5lUGVyaW9kLCBbImFsbCIsICJ3b3JkIl0pOwogICAgdGhpcy5wb3N0dXJlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMucG9zdHVyZSwgWyJub3JtYWwiLCAiaXRhbGljIl0pOwogICAgdGhpcy5zaXplID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5zaXplLCAiMTBwdCIpOwogICAgdGhpcy50eXBlZmFjZSA9IGF0dHJpYnV0ZXMudHlwZWZhY2UgfHwgIkNvdXJpZXIiOwogICAgdGhpcy51bmRlcmxpbmUgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy51bmRlcmxpbmUsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMSB8fCB4ID09PSAyCiAgICB9KTsKICAgIHRoaXMudW5kZXJsaW5lUGVyaW9kID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMudW5kZXJsaW5lUGVyaW9kLCBbImFsbCIsICJ3b3JkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMud2VpZ2h0ID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMud2VpZ2h0LCBbIm5vcm1hbCIsICJib2xkIl0pOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5maWxsID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiRjbGVhbl0oYnVpbGRlcikgewogICAgc3VwZXJbX3hmYV9vYmplY3QuJGNsZWFuXShidWlsZGVyKTsKICAgIHRoaXNbX3hmYV9vYmplY3QuJGdsb2JhbERhdGFdLnVzZWRUeXBlZmFjZXMuYWRkKHRoaXMudHlwZWZhY2UpOwogIH0KICBbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCkgewogICAgY29uc3Qgc3R5bGUgPSAoMCwgX2h0bWxfdXRpbHMudG9TdHlsZSkodGhpcywgImZpbGwiKTsKICAgIGNvbnN0IGNvbG9yID0gc3R5bGUuY29sb3I7CiAgICBpZiAoY29sb3IpIHsKICAgICAgaWYgKGNvbG9yID09PSAiIzAwMDAwMCIpIHsKICAgICAgICBkZWxldGUgc3R5bGUuY29sb3I7CiAgICAgIH0gZWxzZSBpZiAoIWNvbG9yLnN0YXJ0c1dpdGgoIiMiKSkgewogICAgICAgIHN0eWxlLmJhY2tncm91bmQgPSBjb2xvcjsKICAgICAgICBzdHlsZS5iYWNrZ3JvdW5kQ2xpcCA9ICJ0ZXh0IjsKICAgICAgICBzdHlsZS5jb2xvciA9ICJ0cmFuc3BhcmVudCI7CiAgICAgIH0KICAgIH0KICAgIGlmICh0aGlzLmJhc2VsaW5lU2hpZnQpIHsKICAgICAgc3R5bGUudmVydGljYWxBbGlnbiA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKHRoaXMuYmFzZWxpbmVTaGlmdCk7CiAgICB9CiAgICBzdHlsZS5mb250S2VybmluZyA9IHRoaXMua2VybmluZ01vZGUgPT09ICJub25lIiA/ICJub25lIiA6ICJub3JtYWwiOwogICAgc3R5bGUubGV0dGVyU3BhY2luZyA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKHRoaXMubGV0dGVyU3BhY2luZyk7CiAgICBpZiAodGhpcy5saW5lVGhyb3VnaCAhPT0gMCkgewogICAgICBzdHlsZS50ZXh0RGVjb3JhdGlvbiA9ICJsaW5lLXRocm91Z2giOwogICAgICBpZiAodGhpcy5saW5lVGhyb3VnaCA9PT0gMikgewogICAgICAgIHN0eWxlLnRleHREZWNvcmF0aW9uU3R5bGUgPSAiZG91YmxlIjsKICAgICAgfQogICAgfQogICAgaWYgKHRoaXMub3ZlcmxpbmUgIT09IDApIHsKICAgICAgc3R5bGUudGV4dERlY29yYXRpb24gPSAib3ZlcmxpbmUiOwogICAgICBpZiAodGhpcy5vdmVybGluZSA9PT0gMikgewogICAgICAgIHN0eWxlLnRleHREZWNvcmF0aW9uU3R5bGUgPSAiZG91YmxlIjsKICAgICAgfQogICAgfQogICAgc3R5bGUuZm9udFN0eWxlID0gdGhpcy5wb3N0dXJlOwogICAgc3R5bGUuZm9udFNpemUgPSAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSgwLjk5ICogdGhpcy5zaXplKTsKICAgICgwLCBfaHRtbF91dGlscy5zZXRGb250RmFtaWx5KSh0aGlzLCB0aGlzLCB0aGlzW194ZmFfb2JqZWN0LiRnbG9iYWxEYXRhXS5mb250RmluZGVyLCBzdHlsZSk7CiAgICBpZiAodGhpcy51bmRlcmxpbmUgIT09IDApIHsKICAgICAgc3R5bGUudGV4dERlY29yYXRpb24gPSAidW5kZXJsaW5lIjsKICAgICAgaWYgKHRoaXMudW5kZXJsaW5lID09PSAyKSB7CiAgICAgICAgc3R5bGUudGV4dERlY29yYXRpb25TdHlsZSA9ICJkb3VibGUiOwogICAgICB9CiAgICB9CiAgICBzdHlsZS5mb250V2VpZ2h0ID0gdGhpcy53ZWlnaHQ7CiAgICByZXR1cm4gc3R5bGU7CiAgfQp9CmNsYXNzIEZvcm1hdCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJmb3JtYXQiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMucGljdHVyZSA9IG51bGw7CiAgfQp9CmNsYXNzIEhhbmRsZXIgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiaGFuZGxlciIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgSHlwaGVuYXRpb24gZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiaHlwaGVuYXRpb24iKTsKICAgIHRoaXMuZXhjbHVkZUFsbENhcHMgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5leGNsdWRlQWxsQ2FwcywKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMuZXhjbHVkZUluaXRpYWxDYXAgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5leGNsdWRlSW5pdGlhbENhcCwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMuaHlwaGVuYXRlID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuaHlwaGVuYXRlLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnB1c2hDaGFyYWN0ZXJDb3VudCA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnB1c2hDaGFyYWN0ZXJDb3VudCwKICAgICAgZGVmYXVsdFZhbHVlOiAzLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy5yZW1haW5DaGFyYWN0ZXJDb3VudCA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnJlbWFpbkNoYXJhY3RlckNvdW50LAogICAgICBkZWZhdWx0VmFsdWU6IDMsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMAogICAgfSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy53b3JkQ2hhcmFjdGVyQ291bnQgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy53b3JkQ2hhcmFjdGVyQ291bnQsCiAgICAgIGRlZmF1bHRWYWx1ZTogNywKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwCiAgICB9KTsKICB9Cn0KY2xhc3MgSW1hZ2UgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiaW1hZ2UiKTsKICAgIHRoaXMuYXNwZWN0ID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuYXNwZWN0LCBbImZpdCIsICJhY3R1YWwiLCAiaGVpZ2h0IiwgIm5vbmUiLCAid2lkdGgiXSk7CiAgICB0aGlzLmNvbnRlbnRUeXBlID0gYXR0cmlidXRlcy5jb250ZW50VHlwZSB8fCAiIjsKICAgIHRoaXMuaHJlZiA9IGF0dHJpYnV0ZXMuaHJlZiB8fCAiIjsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy50cmFuc2ZlckVuY29kaW5nID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMudHJhbnNmZXJFbmNvZGluZywgWyJiYXNlNjQiLCAibm9uZSIsICJwYWNrYWdlIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKCkgewogICAgaWYgKHRoaXMuY29udGVudFR5cGUgJiYgIU1JTUVTLmhhcyh0aGlzLmNvbnRlbnRUeXBlLnRvTG93ZXJDYXNlKCkpKSB7CiAgICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGxldCBidWZmZXIgPSB0aGlzW194ZmFfb2JqZWN0LiRnbG9iYWxEYXRhXS5pbWFnZXMgJiYgdGhpc1tfeGZhX29iamVjdC4kZ2xvYmFsRGF0YV0uaW1hZ2VzLmdldCh0aGlzLmhyZWYpOwogICAgaWYgKCFidWZmZXIgJiYgKHRoaXMuaHJlZiB8fCAhdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0pKSB7CiAgICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGlmICghYnVmZmVyICYmIHRoaXMudHJhbnNmZXJFbmNvZGluZyA9PT0gImJhc2U2NCIpIHsKICAgICAgYnVmZmVyID0gKDAsIF91dGlsLnN0cmluZ1RvQnl0ZXMpKGF0b2IodGhpc1tfeGZhX29iamVjdC4kY29udGVudF0pKTsKICAgIH0KICAgIGlmICghYnVmZmVyKSB7CiAgICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGlmICghdGhpcy5jb250ZW50VHlwZSkgewogICAgICBmb3IgKGNvbnN0IFtoZWFkZXIsIHR5cGVdIG9mIElNQUdFU19IRUFERVJTKSB7CiAgICAgICAgaWYgKGJ1ZmZlci5sZW5ndGggPiBoZWFkZXIubGVuZ3RoICYmIGhlYWRlci5ldmVyeSgoeCwgaSkgPT4geCA9PT0gYnVmZmVyW2ldKSkgewogICAgICAgICAgdGhpcy5jb250ZW50VHlwZSA9IHR5cGU7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCF0aGlzLmNvbnRlbnRUeXBlKSB7CiAgICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LkVNUFRZOwogICAgICB9CiAgICB9CiAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW2J1ZmZlcl0sIHsKICAgICAgdHlwZTogdGhpcy5jb250ZW50VHlwZQogICAgfSk7CiAgICBsZXQgc3R5bGU7CiAgICBzd2l0Y2ggKHRoaXMuYXNwZWN0KSB7CiAgICAgIGNhc2UgImZpdCI6CiAgICAgIGNhc2UgImFjdHVhbCI6CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgImhlaWdodCI6CiAgICAgICAgc3R5bGUgPSB7CiAgICAgICAgICBoZWlnaHQ6ICIxMDAlIiwKICAgICAgICAgIG9iamVjdEZpdDogImZpbGwiCiAgICAgICAgfTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAibm9uZSI6CiAgICAgICAgc3R5bGUgPSB7CiAgICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgICAgaGVpZ2h0OiAiMTAwJSIsCiAgICAgICAgICBvYmplY3RGaXQ6ICJmaWxsIgogICAgICAgIH07CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIndpZHRoIjoKICAgICAgICBzdHlsZSA9IHsKICAgICAgICAgIHdpZHRoOiAiMTAwJSIsCiAgICAgICAgICBvYmplY3RGaXQ6ICJmaWxsIgogICAgICAgIH07CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgIG5hbWU6ICJpbWciLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgY2xhc3M6IFsieGZhSW1hZ2UiXSwKICAgICAgICBzdHlsZSwKICAgICAgICBzcmM6IFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYiksCiAgICAgICAgYWx0OiBwYXJlbnQgPyBhcmlhTGFiZWwocGFyZW50W194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCkpIDogbnVsbAogICAgICB9CiAgICB9KTsKICB9Cn0KY2xhc3MgSW1hZ2VFZGl0IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImltYWdlRWRpdCIsIHRydWUpOwogICAgdGhpcy5kYXRhID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuZGF0YSwgWyJsaW5rIiwgImVtYmVkIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogIH0KICBbX3hmYV9vYmplY3QuJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGlmICh0aGlzLmRhdGEgPT09ICJlbWJlZCIpIHsKICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICAgIG5hbWU6ICJkaXYiLAogICAgICAgIGNoaWxkcmVuOiBbXSwKICAgICAgICBhdHRyaWJ1dGVzOiB7fQogICAgICB9KTsKICAgIH0KICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5FTVBUWTsKICB9Cn0KY2xhc3MgSW50ZWdlciBleHRlbmRzIF94ZmFfb2JqZWN0LkNvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiaW50ZWdlciIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KICBbX3hmYV9vYmplY3QuJGZpbmFsaXplXSgpIHsKICAgIGNvbnN0IG51bWJlciA9IHBhcnNlSW50KHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdLnRyaW0oKSwgMTApOwogICAgdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0gPSBpc05hTihudW1iZXIpID8gbnVsbCA6IG51bWJlcjsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gdmFsdWVUb0h0bWwodGhpc1tfeGZhX29iamVjdC4kY29udGVudF0gIT09IG51bGwgPyB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XS50b1N0cmluZygpIDogIiIpOwogIH0KfQpjbGFzcyBJc3N1ZXJzIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImlzc3VlcnMiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNlcnRpZmljYXRlID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIEl0ZW1zIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgIml0ZW1zIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucHJlc2VuY2UgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5wcmVzZW5jZSwgWyJ2aXNpYmxlIiwgImhpZGRlbiIsICJpbmFjdGl2ZSIsICJpbnZpc2libGUiXSk7CiAgICB0aGlzLnJlZiA9IGF0dHJpYnV0ZXMucmVmIHx8ICIiOwogICAgdGhpcy5zYXZlID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuc2F2ZSwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmJvb2xlYW4gPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGF0ZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlVGltZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZWNpbWFsID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4RGF0YSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5mbG9hdCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbWFnZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbnRlZ2VyID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRleHQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGltZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KICBbX3hmYV9vYmplY3QuJHRvSFRNTF0oKSB7CiAgICBjb25zdCBvdXRwdXQgPSBbXTsKICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpc1tfeGZhX29iamVjdC4kZ2V0Q2hpbGRyZW5dKCkpIHsKICAgICAgb3V0cHV0LnB1c2goY2hpbGRbX3hmYV9vYmplY3QuJHRleHRdKCkpOwogICAgfQogICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3Mob3V0cHV0KTsKICB9Cn0KZXhwb3J0cy5JdGVtcyA9IEl0ZW1zOwpjbGFzcyBLZWVwIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImtlZXAiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgY29uc3Qgb3B0aW9ucyA9IFsibm9uZSIsICJjb250ZW50QXJlYSIsICJwYWdlQXJlYSJdOwogICAgdGhpcy5pbnRhY3QgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5pbnRhY3QsIG9wdGlvbnMpOwogICAgdGhpcy5uZXh0ID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMubmV4dCwgb3B0aW9ucyk7CiAgICB0aGlzLnByZXZpb3VzID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMucHJldmlvdXMsIG9wdGlvbnMpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9Cn0KY2xhc3MgS2V5VXNhZ2UgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAia2V5VXNhZ2UiKTsKICAgIGNvbnN0IG9wdGlvbnMgPSBbIiIsICJ5ZXMiLCAibm8iXTsKICAgIHRoaXMuY3JsU2lnbiA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmNybFNpZ24sIG9wdGlvbnMpOwogICAgdGhpcy5kYXRhRW5jaXBoZXJtZW50ID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuZGF0YUVuY2lwaGVybWVudCwgb3B0aW9ucyk7CiAgICB0aGlzLmRlY2lwaGVyT25seSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmRlY2lwaGVyT25seSwgb3B0aW9ucyk7CiAgICB0aGlzLmRpZ2l0YWxTaWduYXR1cmUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5kaWdpdGFsU2lnbmF0dXJlLCBvcHRpb25zKTsKICAgIHRoaXMuZW5jaXBoZXJPbmx5ID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuZW5jaXBoZXJPbmx5LCBvcHRpb25zKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5rZXlBZ3JlZW1lbnQgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5rZXlBZ3JlZW1lbnQsIG9wdGlvbnMpOwogICAgdGhpcy5rZXlDZXJ0U2lnbiA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmtleUNlcnRTaWduLCBvcHRpb25zKTsKICAgIHRoaXMua2V5RW5jaXBoZXJtZW50ID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMua2V5RW5jaXBoZXJtZW50LCBvcHRpb25zKTsKICAgIHRoaXMubm9uUmVwdWRpYXRpb24gPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5ub25SZXB1ZGlhdGlvbiwgb3B0aW9ucyk7CiAgICB0aGlzLnR5cGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgTGluZSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJsaW5lIiwgdHJ1ZSk7CiAgICB0aGlzLmhhbmQgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5oYW5kLCBbImV2ZW4iLCAibGVmdCIsICJyaWdodCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5zbG9wZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnNsb3BlLCBbIlxcIiwgIi8iXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5lZGdlID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKCkgewogICAgY29uc3QgcGFyZW50ID0gdGhpc1tfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBlZGdlID0gdGhpcy5lZGdlIHx8IG5ldyBFZGdlKHt9KTsKICAgIGNvbnN0IGVkZ2VTdHlsZSA9IGVkZ2VbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCk7CiAgICBjb25zdCBzdHlsZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBjb25zdCB0aGlja25lc3MgPSBlZGdlLnByZXNlbmNlID09PSAidmlzaWJsZSIgPyBlZGdlLnRoaWNrbmVzcyA6IDA7CiAgICBzdHlsZS5zdHJva2VXaWR0aCA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKHRoaWNrbmVzcyk7CiAgICBzdHlsZS5zdHJva2UgPSBlZGdlU3R5bGUuY29sb3I7CiAgICBsZXQgeDEsIHkxLCB4MiwgeTI7CiAgICBsZXQgd2lkdGggPSAiMTAwJSI7CiAgICBsZXQgaGVpZ2h0ID0gIjEwMCUiOwogICAgaWYgKHBhcmVudC53IDw9IHRoaWNrbmVzcykgewogICAgICBbeDEsIHkxLCB4MiwgeTJdID0gWyI1MCUiLCAwLCAiNTAlIiwgIjEwMCUiXTsKICAgICAgd2lkdGggPSBzdHlsZS5zdHJva2VXaWR0aDsKICAgIH0gZWxzZSBpZiAocGFyZW50LmggPD0gdGhpY2tuZXNzKSB7CiAgICAgIFt4MSwgeTEsIHgyLCB5Ml0gPSBbMCwgIjUwJSIsICIxMDAlIiwgIjUwJSJdOwogICAgICBoZWlnaHQgPSBzdHlsZS5zdHJva2VXaWR0aDsKICAgIH0gZWxzZSB7CiAgICAgIGlmICh0aGlzLnNsb3BlID09PSAiXFwiKSB7CiAgICAgICAgW3gxLCB5MSwgeDIsIHkyXSA9IFswLCAwLCAiMTAwJSIsICIxMDAlIl07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgW3gxLCB5MSwgeDIsIHkyXSA9IFswLCAiMTAwJSIsICIxMDAlIiwgMF07CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGxpbmUgPSB7CiAgICAgIG5hbWU6ICJsaW5lIiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIHhtbG5zOiBTVkdfTlMsCiAgICAgICAgeDEsCiAgICAgICAgeTEsCiAgICAgICAgeDIsCiAgICAgICAgeTIsCiAgICAgICAgc3R5bGUKICAgICAgfQogICAgfTsKICAgIGNvbnN0IHN2ZyA9IHsKICAgICAgbmFtZTogInN2ZyIsCiAgICAgIGNoaWxkcmVuOiBbbGluZV0sCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICB4bWxuczogU1ZHX05TLAogICAgICAgIHdpZHRoLAogICAgICAgIGhlaWdodCwKICAgICAgICBzdHlsZTogewogICAgICAgICAgb3ZlcmZsb3c6ICJ2aXNpYmxlIgogICAgICAgIH0KICAgICAgfQogICAgfTsKICAgIGlmIChoYXNNYXJnaW4ocGFyZW50KSkgewogICAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgICAgbmFtZTogImRpdiIsCiAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgc3R5bGU6IHsKICAgICAgICAgICAgZGlzcGxheTogImlubGluZSIsCiAgICAgICAgICAgIHdpZHRoOiAiMTAwJSIsCiAgICAgICAgICAgIGhlaWdodDogIjEwMCUiCiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICBjaGlsZHJlbjogW3N2Z10KICAgICAgfSk7CiAgICB9CiAgICBzdmcuYXR0cmlidXRlcy5zdHlsZS5wb3NpdGlvbiA9ICJhYnNvbHV0ZSI7CiAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2VzcyhzdmcpOwogIH0KfQpjbGFzcyBMaW5lYXIgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAibGluZWFyIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnR5cGUsIFsidG9SaWdodCIsICJ0b0JvdHRvbSIsICJ0b0xlZnQiLCAidG9Ub3AiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5jb2xvciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQogIFtfeGZhX29iamVjdC4kdG9TdHlsZV0oc3RhcnRDb2xvcikgewogICAgc3RhcnRDb2xvciA9IHN0YXJ0Q29sb3IgPyBzdGFydENvbG9yW194ZmFfb2JqZWN0LiR0b1N0eWxlXSgpIDogIiNGRkZGRkYiOwogICAgY29uc3QgdHJhbnNmID0gdGhpcy50eXBlLnJlcGxhY2UoLyhbUkJMVF0pLywgIiAkMSIpLnRvTG93ZXJDYXNlKCk7CiAgICBjb25zdCBlbmRDb2xvciA9IHRoaXMuY29sb3IgPyB0aGlzLmNvbG9yW194ZmFfb2JqZWN0LiR0b1N0eWxlXSgpIDogIiMwMDAwMDAiOwogICAgcmV0dXJuIGBsaW5lYXItZ3JhZGllbnQoJHt0cmFuc2Z9LCAke3N0YXJ0Q29sb3J9LCAke2VuZENvbG9yfSlgOwogIH0KfQpjbGFzcyBMb2NrRG9jdW1lbnQgZXh0ZW5kcyBfeGZhX29iamVjdC5Db250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImxvY2tEb2N1bWVudCIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgW194ZmFfb2JqZWN0LiRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKSh0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSwgWyJhdXRvIiwgIjAiLCAiMSJdKTsKICB9Cn0KY2xhc3MgTWFuaWZlc3QgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAibWFuaWZlc3QiLCB0cnVlKTsKICAgIHRoaXMuYWN0aW9uID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuYWN0aW9uLCBbImluY2x1ZGUiLCAiYWxsIiwgImV4Y2x1ZGUiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLnJlZiA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBNYXJnaW4gZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAibWFyZ2luIiwgdHJ1ZSk7CiAgICB0aGlzLmJvdHRvbUluc2V0ID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5ib3R0b21JbnNldCwgIjAiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5sZWZ0SW5zZXQgPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLmxlZnRJbnNldCwgIjAiKTsKICAgIHRoaXMucmlnaHRJbnNldCA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMucmlnaHRJbnNldCwgIjAiKTsKICAgIHRoaXMudG9wSW5zZXQgPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLnRvcEluc2V0LCAiMCIpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiR0b1N0eWxlXSgpIHsKICAgIHJldHVybiB7CiAgICAgIG1hcmdpbjogKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykodGhpcy50b3BJbnNldCkgKyAiICIgKyAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSh0aGlzLnJpZ2h0SW5zZXQpICsgIiAiICsgKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykodGhpcy5ib3R0b21JbnNldCkgKyAiICIgKyAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSh0aGlzLmxlZnRJbnNldCkKICAgIH07CiAgfQp9CmNsYXNzIE1kcCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJtZHAiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5wZXJtaXNzaW9ucyA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnBlcm1pc3Npb25zLAogICAgICBkZWZhdWx0VmFsdWU6IDIsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEgfHwgeCA9PT0gMwogICAgfSk7CiAgICB0aGlzLnNpZ25hdHVyZVR5cGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5zaWduYXR1cmVUeXBlLCBbImZpbGxlciIsICJhdXRob3IiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBNZWRpdW0gZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAibWVkaXVtIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMuaW1hZ2luZ0JCb3ggPSAoMCwgX3V0aWxzLmdldEJCb3gpKGF0dHJpYnV0ZXMuaW1hZ2luZ0JCb3gpOwogICAgdGhpcy5sb25nID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5sb25nKTsKICAgIHRoaXMub3JpZW50YXRpb24gPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5vcmllbnRhdGlvbiwgWyJwb3J0cmFpdCIsICJsYW5kc2NhcGUiXSk7CiAgICB0aGlzLnNob3J0ID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5zaG9ydCk7CiAgICB0aGlzLnN0b2NrID0gYXR0cmlidXRlcy5zdG9jayB8fCAiIjsKICAgIHRoaXMudHJheUluID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMudHJheUluLCBbImF1dG8iLCAiZGVsZWdhdGUiLCAicGFnZUZyb250Il0pOwogICAgdGhpcy50cmF5T3V0ID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMudHJheU91dCwgWyJhdXRvIiwgImRlbGVnYXRlIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgTWVzc2FnZSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJtZXNzYWdlIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnRleHQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgTnVtZXJpY0VkaXQgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAibnVtZXJpY0VkaXQiLCB0cnVlKTsKICAgIHRoaXMuaFNjcm9sbFBvbGljeSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmhTY3JvbGxQb2xpY3ksIFsiYXV0byIsICJvZmYiLCAib24iXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmJvcmRlciA9IG51bGw7CiAgICB0aGlzLmNvbWIgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogIH0KICBbX3hmYV9vYmplY3QuJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IHN0eWxlID0gKDAsIF9odG1sX3V0aWxzLnRvU3R5bGUpKHRoaXMsICJib3JkZXIiLCAiZm9udCIsICJtYXJnaW4iKTsKICAgIGNvbnN0IGZpZWxkID0gdGhpc1tfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBodG1sID0gewogICAgICBuYW1lOiAiaW5wdXQiLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgdHlwZTogInRleHQiLAogICAgICAgIGZpZWxkSWQ6IGZpZWxkW194ZmFfb2JqZWN0LiR1aWRdLAogICAgICAgIGRhdGFJZDogZmllbGRbX3hmYV9vYmplY3QuJGRhdGFdICYmIGZpZWxkW194ZmFfb2JqZWN0LiRkYXRhXVtfeGZhX29iamVjdC4kdWlkXSB8fCBmaWVsZFtfeGZhX29iamVjdC4kdWlkXSwKICAgICAgICBjbGFzczogWyJ4ZmFUZXh0ZmllbGQiXSwKICAgICAgICBzdHlsZSwKICAgICAgICAiYXJpYS1sYWJlbCI6IGFyaWFMYWJlbChmaWVsZCksCiAgICAgICAgImFyaWEtcmVxdWlyZWQiOiBmYWxzZQogICAgICB9CiAgICB9OwogICAgaWYgKGlzUmVxdWlyZWQoZmllbGQpKSB7CiAgICAgIGh0bWwuYXR0cmlidXRlc1siYXJpYS1yZXF1aXJlZCJdID0gdHJ1ZTsKICAgICAgaHRtbC5hdHRyaWJ1dGVzLnJlcXVpcmVkID0gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImxhYmVsIiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGNsYXNzOiBbInhmYUxhYmVsIl0KICAgICAgfSwKICAgICAgY2hpbGRyZW46IFtodG1sXQogICAgfSk7CiAgfQp9CmNsYXNzIE9jY3VyIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgIm9jY3VyIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMuaW5pdGlhbCA9IGF0dHJpYnV0ZXMuaW5pdGlhbCAhPT0gIiIgPyAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5pbml0aWFsLAogICAgICBkZWZhdWx0VmFsdWU6ICIiLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KSA6ICIiOwogICAgdGhpcy5tYXggPSBhdHRyaWJ1dGVzLm1heCAhPT0gIiIgPyAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5tYXgsCiAgICAgIGRlZmF1bHRWYWx1ZTogMSwKICAgICAgdmFsaWRhdGU6IHggPT4gdHJ1ZQogICAgfSkgOiAiIjsKICAgIHRoaXMubWluID0gYXR0cmlidXRlcy5taW4gIT09ICIiID8gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMubWluLAogICAgICBkZWZhdWx0VmFsdWU6IDEsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHRydWUKICAgIH0pIDogIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbX3hmYV9vYmplY3QuJGNsZWFuXSgpIHsKICAgIGNvbnN0IHBhcmVudCA9IHRoaXNbX3hmYV9vYmplY3QuJGdldFBhcmVudF0oKTsKICAgIGNvbnN0IG9yaWdpbmFsTWluID0gdGhpcy5taW47CiAgICBpZiAodGhpcy5taW4gPT09ICIiKSB7CiAgICAgIHRoaXMubWluID0gcGFyZW50IGluc3RhbmNlb2YgUGFnZUFyZWEgfHwgcGFyZW50IGluc3RhbmNlb2YgUGFnZVNldCA/IDAgOiAxOwogICAgfQogICAgaWYgKHRoaXMubWF4ID09PSAiIikgewogICAgICBpZiAob3JpZ2luYWxNaW4gPT09ICIiKSB7CiAgICAgICAgdGhpcy5tYXggPSBwYXJlbnQgaW5zdGFuY2VvZiBQYWdlQXJlYSB8fCBwYXJlbnQgaW5zdGFuY2VvZiBQYWdlU2V0ID8gLTEgOiAxOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMubWF4ID0gdGhpcy5taW47CiAgICAgIH0KICAgIH0KICAgIGlmICh0aGlzLm1heCAhPT0gLTEgJiYgdGhpcy5tYXggPCB0aGlzLm1pbikgewogICAgICB0aGlzLm1heCA9IHRoaXMubWluOwogICAgfQogICAgaWYgKHRoaXMuaW5pdGlhbCA9PT0gIiIpIHsKICAgICAgdGhpcy5pbml0aWFsID0gcGFyZW50IGluc3RhbmNlb2YgVGVtcGxhdGUgPyAxIDogdGhpcy5taW47CiAgICB9CiAgfQp9CmNsYXNzIE9pZCBleHRlbmRzIF94ZmFfb2JqZWN0LlN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJvaWQiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgT2lkcyBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJvaWRzIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnR5cGUsIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5vaWQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgT3ZlcmZsb3cgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAib3ZlcmZsb3ciKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5sZWFkZXIgPSBhdHRyaWJ1dGVzLmxlYWRlciB8fCAiIjsKICAgIHRoaXMudGFyZ2V0ID0gYXR0cmlidXRlcy50YXJnZXQgfHwgIiI7CiAgICB0aGlzLnRyYWlsZXIgPSBhdHRyaWJ1dGVzLnRyYWlsZXIgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KICBbX3hmYV9vYmplY3QuJGdldEV4dHJhXSgpIHsKICAgIGlmICghdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdKSB7CiAgICAgIGNvbnN0IHBhcmVudCA9IHRoaXNbX3hmYV9vYmplY3QuJGdldFBhcmVudF0oKTsKICAgICAgY29uc3Qgcm9vdCA9IHRoaXNbX3hmYV9vYmplY3QuJGdldFRlbXBsYXRlUm9vdF0oKTsKICAgICAgY29uc3QgdGFyZ2V0ID0gcm9vdFtfeGZhX29iamVjdC4kc2VhcmNoTm9kZV0odGhpcy50YXJnZXQsIHBhcmVudCk7CiAgICAgIGNvbnN0IGxlYWRlciA9IHJvb3RbX3hmYV9vYmplY3QuJHNlYXJjaE5vZGVdKHRoaXMubGVhZGVyLCBwYXJlbnQpOwogICAgICBjb25zdCB0cmFpbGVyID0gcm9vdFtfeGZhX29iamVjdC4kc2VhcmNoTm9kZV0odGhpcy50cmFpbGVyLCBwYXJlbnQpOwogICAgICB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0gPSB7CiAgICAgICAgdGFyZ2V0OiB0YXJnZXQgJiYgdGFyZ2V0WzBdIHx8IG51bGwsCiAgICAgICAgbGVhZGVyOiBsZWFkZXIgJiYgbGVhZGVyWzBdIHx8IG51bGwsCiAgICAgICAgdHJhaWxlcjogdHJhaWxlciAmJiB0cmFpbGVyWzBdIHx8IG51bGwsCiAgICAgICAgYWRkTGVhZGVyOiBmYWxzZSwKICAgICAgICBhZGRUcmFpbGVyOiBmYWxzZQogICAgICB9OwogICAgfQogICAgcmV0dXJuIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXTsKICB9Cn0KY2xhc3MgUGFnZUFyZWEgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAicGFnZUFyZWEiLCB0cnVlKTsKICAgIHRoaXMuYmxhbmtPck5vdEJsYW5rID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuYmxhbmtPck5vdEJsYW5rLCBbImFueSIsICJibGFuayIsICJub3RCbGFuayJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5pbml0aWFsTnVtYmVyID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuaW5pdGlhbE51bWJlciwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMubnVtYmVyZWQgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5udW1iZXJlZCwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KTsKICAgIHRoaXMub2RkT3JFdmVuID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMub2RkT3JFdmVuLCBbImFueSIsICJldmVuIiwgIm9kZCJdKTsKICAgIHRoaXMucGFnZVBvc2l0aW9uID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMucGFnZVBvc2l0aW9uLCBbImFueSIsICJmaXJzdCIsICJsYXN0IiwgIm9ubHkiLCAicmVzdCJdKTsKICAgIHRoaXMucmVsZXZhbnQgPSAoMCwgX3V0aWxzLmdldFJlbGV2YW50KShhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmRlc2MgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tZWRpdW0gPSBudWxsOwogICAgdGhpcy5vY2N1ciA9IG51bGw7CiAgICB0aGlzLmFyZWEgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY29udGVudEFyZWEgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZHJhdyA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leGNsR3JvdXAgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmllbGQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3ViZm9ybSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KICBbX3hmYV9vYmplY3QuJGlzVXNhYmxlXSgpIHsKICAgIGlmICghdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdKSB7CiAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXSA9IHsKICAgICAgICBudW1iZXJPZlVzZTogMAogICAgICB9OwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiAhdGhpcy5vY2N1ciB8fCB0aGlzLm9jY3VyLm1heCA9PT0gLTEgfHwgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLm51bWJlck9mVXNlIDwgdGhpcy5vY2N1ci5tYXg7CiAgfQogIFtfeGZhX29iamVjdC4kY2xlYW5QYWdlXSgpIHsKICAgIGRlbGV0ZSB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV07CiAgfQogIFtfeGZhX29iamVjdC4kZ2V0TmV4dFBhZ2VdKCkgewogICAgaWYgKCF0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0pIHsKICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdID0gewogICAgICAgIG51bWJlck9mVXNlOiAwCiAgICAgIH07CiAgICB9CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICBpZiAocGFyZW50LnJlbGF0aW9uID09PSAib3JkZXJlZE9jY3VycmVuY2UiKSB7CiAgICAgIGlmICh0aGlzW194ZmFfb2JqZWN0LiRpc1VzYWJsZV0oKSkgewogICAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5udW1iZXJPZlVzZSArPSAxOwogICAgICAgIHJldHVybiB0aGlzOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcGFyZW50W194ZmFfb2JqZWN0LiRnZXROZXh0UGFnZV0oKTsKICB9CiAgW194ZmFfb2JqZWN0LiRnZXRBdmFpbGFibGVTcGFjZV0oKSB7CiAgICByZXR1cm4gdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLnNwYWNlIHx8IHsKICAgICAgd2lkdGg6IDAsCiAgICAgIGhlaWdodDogMAogICAgfTsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKCkgewogICAgaWYgKCF0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0pIHsKICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdID0gewogICAgICAgIG51bWJlck9mVXNlOiAxCiAgICAgIH07CiAgICB9CiAgICBjb25zdCBjaGlsZHJlbiA9IFtdOwogICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmNoaWxkcmVuID0gY2hpbGRyZW47CiAgICBjb25zdCBzdHlsZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBpZiAodGhpcy5tZWRpdW0gJiYgdGhpcy5tZWRpdW0uc2hvcnQgJiYgdGhpcy5tZWRpdW0ubG9uZykgewogICAgICBzdHlsZS53aWR0aCA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKHRoaXMubWVkaXVtLnNob3J0KTsKICAgICAgc3R5bGUuaGVpZ2h0ID0gKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykodGhpcy5tZWRpdW0ubG9uZyk7CiAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5zcGFjZSA9IHsKICAgICAgICB3aWR0aDogdGhpcy5tZWRpdW0uc2hvcnQsCiAgICAgICAgaGVpZ2h0OiB0aGlzLm1lZGl1bS5sb25nCiAgICAgIH07CiAgICAgIGlmICh0aGlzLm1lZGl1bS5vcmllbnRhdGlvbiA9PT0gImxhbmRzY2FwZSIpIHsKICAgICAgICBjb25zdCB4ID0gc3R5bGUud2lkdGg7CiAgICAgICAgc3R5bGUud2lkdGggPSBzdHlsZS5oZWlnaHQ7CiAgICAgICAgc3R5bGUuaGVpZ2h0ID0geDsKICAgICAgICB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uc3BhY2UgPSB7CiAgICAgICAgICB3aWR0aDogdGhpcy5tZWRpdW0ubG9uZywKICAgICAgICAgIGhlaWdodDogdGhpcy5tZWRpdW0uc2hvcnQKICAgICAgICB9OwogICAgICB9CiAgICB9IGVsc2UgewogICAgICAoMCwgX3V0aWwud2FybikoIlhGQSAtIE5vIG1lZGl1bSBzcGVjaWZpZWQgaW4gcGFnZUFyZWE6IHBsZWFzZSBmaWxlIGEgYnVnLiIpOwogICAgfQogICAgdGhpc1tfeGZhX29iamVjdC4kY2hpbGRyZW5Ub0hUTUxdKHsKICAgICAgZmlsdGVyOiBuZXcgU2V0KFsiYXJlYSIsICJkcmF3IiwgImZpZWxkIiwgInN1YmZvcm0iXSksCiAgICAgIGluY2x1ZGU6IHRydWUKICAgIH0pOwogICAgdGhpc1tfeGZhX29iamVjdC4kY2hpbGRyZW5Ub0hUTUxdKHsKICAgICAgZmlsdGVyOiBuZXcgU2V0KFsiY29udGVudEFyZWEiXSksCiAgICAgIGluY2x1ZGU6IHRydWUKICAgIH0pOwogICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICBuYW1lOiAiZGl2IiwKICAgICAgY2hpbGRyZW4sCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBjbGFzczogWyJ4ZmFQYWdlIl0sCiAgICAgICAgaWQ6IHRoaXNbX3hmYV9vYmplY3QuJHVpZF0sCiAgICAgICAgc3R5bGUsCiAgICAgICAgeGZhTmFtZTogdGhpcy5uYW1lCiAgICAgIH0KICAgIH0pOwogIH0KfQpjbGFzcyBQYWdlU2V0IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInBhZ2VTZXQiLCB0cnVlKTsKICAgIHRoaXMuZHVwbGV4SW1wb3NpdGlvbiA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmR1cGxleEltcG9zaXRpb24sIFsibG9uZ0VkZ2UiLCAic2hvcnRFZGdlIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnJlbGF0aW9uID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMucmVsYXRpb24sIFsib3JkZXJlZE9jY3VycmVuY2UiLCAiZHVwbGV4UGFnaW5hdGVkIiwgInNpbXBsZXhQYWdpbmF0ZWQiXSk7CiAgICB0aGlzLnJlbGV2YW50ID0gKDAsIF91dGlscy5nZXRSZWxldmFudCkoYXR0cmlidXRlcy5yZWxldmFudCk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5vY2N1ciA9IG51bGw7CiAgICB0aGlzLnBhZ2VBcmVhID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnBhZ2VTZXQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9CiAgW194ZmFfb2JqZWN0LiRjbGVhblBhZ2VdKCkgewogICAgZm9yIChjb25zdCBwYWdlIG9mIHRoaXMucGFnZUFyZWEuY2hpbGRyZW4pIHsKICAgICAgcGFnZVtfeGZhX29iamVjdC4kY2xlYW5QYWdlXSgpOwogICAgfQogICAgZm9yIChjb25zdCBwYWdlIG9mIHRoaXMucGFnZVNldC5jaGlsZHJlbikgewogICAgICBwYWdlW194ZmFfb2JqZWN0LiRjbGVhblBhZ2VdKCk7CiAgICB9CiAgfQogIFtfeGZhX29iamVjdC4kaXNVc2FibGVdKCkgewogICAgcmV0dXJuICF0aGlzLm9jY3VyIHx8IHRoaXMub2NjdXIubWF4ID09PSAtMSB8fCB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0ubnVtYmVyT2ZVc2UgPCB0aGlzLm9jY3VyLm1heDsKICB9CiAgW194ZmFfb2JqZWN0LiRnZXROZXh0UGFnZV0oKSB7CiAgICBpZiAoIXRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXSkgewogICAgICB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0gPSB7CiAgICAgICAgbnVtYmVyT2ZVc2U6IDEsCiAgICAgICAgcGFnZUluZGV4OiAtMSwKICAgICAgICBwYWdlU2V0SW5kZXg6IC0xCiAgICAgIH07CiAgICB9CiAgICBpZiAodGhpcy5yZWxhdGlvbiA9PT0gIm9yZGVyZWRPY2N1cnJlbmNlIikgewogICAgICBpZiAodGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLnBhZ2VJbmRleCArIDEgPCB0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuLmxlbmd0aCkgewogICAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5wYWdlSW5kZXggKz0gMTsKICAgICAgICBjb25zdCBwYWdlQXJlYSA9IHRoaXMucGFnZUFyZWEuY2hpbGRyZW5bdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLnBhZ2VJbmRleF07CiAgICAgICAgcmV0dXJuIHBhZ2VBcmVhW194ZmFfb2JqZWN0LiRnZXROZXh0UGFnZV0oKTsKICAgICAgfQogICAgICBpZiAodGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLnBhZ2VTZXRJbmRleCArIDEgPCB0aGlzLnBhZ2VTZXQuY2hpbGRyZW4ubGVuZ3RoKSB7CiAgICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLnBhZ2VTZXRJbmRleCArPSAxOwogICAgICAgIHJldHVybiB0aGlzLnBhZ2VTZXQuY2hpbGRyZW5bdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLnBhZ2VTZXRJbmRleF1bX3hmYV9vYmplY3QuJGdldE5leHRQYWdlXSgpOwogICAgICB9CiAgICAgIGlmICh0aGlzW194ZmFfb2JqZWN0LiRpc1VzYWJsZV0oKSkgewogICAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5udW1iZXJPZlVzZSArPSAxOwogICAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5wYWdlSW5kZXggPSAtMTsKICAgICAgICB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0ucGFnZVNldEluZGV4ID0gLTE7CiAgICAgICAgcmV0dXJuIHRoaXNbX3hmYV9vYmplY3QuJGdldE5leHRQYWdlXSgpOwogICAgICB9CiAgICAgIGNvbnN0IHBhcmVudCA9IHRoaXNbX3hmYV9vYmplY3QuJGdldFBhcmVudF0oKTsKICAgICAgaWYgKHBhcmVudCBpbnN0YW5jZW9mIFBhZ2VTZXQpIHsKICAgICAgICByZXR1cm4gcGFyZW50W194ZmFfb2JqZWN0LiRnZXROZXh0UGFnZV0oKTsKICAgICAgfQogICAgICB0aGlzW194ZmFfb2JqZWN0LiRjbGVhblBhZ2VdKCk7CiAgICAgIHJldHVybiB0aGlzW194ZmFfb2JqZWN0LiRnZXROZXh0UGFnZV0oKTsKICAgIH0KICAgIGNvbnN0IHBhZ2VOdW1iZXIgPSB0aGlzW194ZmFfb2JqZWN0LiRnZXRUZW1wbGF0ZVJvb3RdKClbX3hmYV9vYmplY3QuJGV4dHJhXS5wYWdlTnVtYmVyOwogICAgY29uc3QgcGFyaXR5ID0gcGFnZU51bWJlciAlIDIgPT09IDAgPyAiZXZlbiIgOiAib2RkIjsKICAgIGNvbnN0IHBvc2l0aW9uID0gcGFnZU51bWJlciA9PT0gMCA/ICJmaXJzdCIgOiAicmVzdCI7CiAgICBsZXQgcGFnZSA9IHRoaXMucGFnZUFyZWEuY2hpbGRyZW4uZmluZChwID0+IHAub2RkT3JFdmVuID09PSBwYXJpdHkgJiYgcC5wYWdlUG9zaXRpb24gPT09IHBvc2l0aW9uKTsKICAgIGlmIChwYWdlKSB7CiAgICAgIHJldHVybiBwYWdlOwogICAgfQogICAgcGFnZSA9IHRoaXMucGFnZUFyZWEuY2hpbGRyZW4uZmluZChwID0+IHAub2RkT3JFdmVuID09PSAiYW55IiAmJiBwLnBhZ2VQb3NpdGlvbiA9PT0gcG9zaXRpb24pOwogICAgaWYgKHBhZ2UpIHsKICAgICAgcmV0dXJuIHBhZ2U7CiAgICB9CiAgICBwYWdlID0gdGhpcy5wYWdlQXJlYS5jaGlsZHJlbi5maW5kKHAgPT4gcC5vZGRPckV2ZW4gPT09ICJhbnkiICYmIHAucGFnZVBvc2l0aW9uID09PSAiYW55Iik7CiAgICBpZiAocGFnZSkgewogICAgICByZXR1cm4gcGFnZTsKICAgIH0KICAgIHJldHVybiB0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuWzBdOwogIH0KfQpjbGFzcyBQYXJhIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInBhcmEiLCB0cnVlKTsKICAgIHRoaXMuaEFsaWduID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuaEFsaWduLCBbImxlZnQiLCAiY2VudGVyIiwgImp1c3RpZnkiLCAianVzdGlmeUFsbCIsICJyYWRpeCIsICJyaWdodCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5saW5lSGVpZ2h0ID0gYXR0cmlidXRlcy5saW5lSGVpZ2h0ID8gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5saW5lSGVpZ2h0LCAiMHB0IikgOiAiIjsKICAgIHRoaXMubWFyZ2luTGVmdCA9IGF0dHJpYnV0ZXMubWFyZ2luTGVmdCA/ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMubWFyZ2luTGVmdCwgIjBwdCIpIDogIiI7CiAgICB0aGlzLm1hcmdpblJpZ2h0ID0gYXR0cmlidXRlcy5tYXJnaW5SaWdodCA/ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMubWFyZ2luUmlnaHQsICIwcHQiKSA6ICIiOwogICAgdGhpcy5vcnBoYW5zID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMub3JwaGFucywKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy5wcmVzZXJ2ZSA9IGF0dHJpYnV0ZXMucHJlc2VydmUgfHwgIiI7CiAgICB0aGlzLnJhZGl4T2Zmc2V0ID0gYXR0cmlidXRlcy5yYWRpeE9mZnNldCA/ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMucmFkaXhPZmZzZXQsICIwcHQiKSA6ICIiOwogICAgdGhpcy5zcGFjZUFib3ZlID0gYXR0cmlidXRlcy5zcGFjZUFib3ZlID8gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5zcGFjZUFib3ZlLCAiMHB0IikgOiAiIjsKICAgIHRoaXMuc3BhY2VCZWxvdyA9IGF0dHJpYnV0ZXMuc3BhY2VCZWxvdyA/ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMuc3BhY2VCZWxvdywgIjBwdCIpIDogIiI7CiAgICB0aGlzLnRhYkRlZmF1bHQgPSBhdHRyaWJ1dGVzLnRhYkRlZmF1bHQgPyAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KSh0aGlzLnRhYkRlZmF1bHQpIDogIiI7CiAgICB0aGlzLnRhYlN0b3BzID0gKGF0dHJpYnV0ZXMudGFiU3RvcHMgfHwgIiIpLnRyaW0oKS5zcGxpdCgvXHMrLykubWFwKCh4LCBpKSA9PiBpICUgMiA9PT0gMSA/ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHgpIDogeCk7CiAgICB0aGlzLnRleHRJbmRlbnQgPSBhdHRyaWJ1dGVzLnRleHRJbmRlbnQgPyAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLnRleHRJbmRlbnQsICIwcHQiKSA6ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMudkFsaWduID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMudkFsaWduLCBbInRvcCIsICJib3R0b20iLCAibWlkZGxlIl0pOwogICAgdGhpcy53aWRvd3MgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy53aWRvd3MsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwCiAgICB9KTsKICAgIHRoaXMuaHlwaGVuYXRpb24gPSBudWxsOwogIH0KICBbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCkgewogICAgY29uc3Qgc3R5bGUgPSAoMCwgX2h0bWxfdXRpbHMudG9TdHlsZSkodGhpcywgImhBbGlnbiIpOwogICAgaWYgKHRoaXMubWFyZ2luTGVmdCAhPT0gIiIpIHsKICAgICAgc3R5bGUucGFkZGluZ0xlZnQgPSAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSh0aGlzLm1hcmdpbkxlZnQpOwogICAgfQogICAgaWYgKHRoaXMubWFyZ2luUmlnaHQgIT09ICIiKSB7CiAgICAgIHN0eWxlLnBhZGRpbmdpZ2h0ID0gKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykodGhpcy5tYXJnaW5SaWdodCk7CiAgICB9CiAgICBpZiAodGhpcy5zcGFjZUFib3ZlICE9PSAiIikgewogICAgICBzdHlsZS5wYWRkaW5nVG9wID0gKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykodGhpcy5zcGFjZUFib3ZlKTsKICAgIH0KICAgIGlmICh0aGlzLnNwYWNlQmVsb3cgIT09ICIiKSB7CiAgICAgIHN0eWxlLnBhZGRpbmdCb3R0b20gPSAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSh0aGlzLnNwYWNlQmVsb3cpOwogICAgfQogICAgaWYgKHRoaXMudGV4dEluZGVudCAhPT0gIiIpIHsKICAgICAgc3R5bGUudGV4dEluZGVudCA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKHRoaXMudGV4dEluZGVudCk7CiAgICAgICgwLCBfaHRtbF91dGlscy5maXhUZXh0SW5kZW50KShzdHlsZSk7CiAgICB9CiAgICBpZiAodGhpcy5saW5lSGVpZ2h0ID4gMCkgewogICAgICBzdHlsZS5saW5lSGVpZ2h0ID0gKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykodGhpcy5saW5lSGVpZ2h0KTsKICAgIH0KICAgIGlmICh0aGlzLnRhYkRlZmF1bHQgIT09ICIiKSB7CiAgICAgIHN0eWxlLnRhYlNpemUgPSAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSh0aGlzLnRhYkRlZmF1bHQpOwogICAgfQogICAgaWYgKHRoaXMudGFiU3RvcHMubGVuZ3RoID4gMCkge30KICAgIGlmICh0aGlzLmh5cGhlbmF0YXRpb24pIHsKICAgICAgT2JqZWN0LmFzc2lnbihzdHlsZSwgdGhpcy5oeXBoZW5hdGF0aW9uW194ZmFfb2JqZWN0LiR0b1N0eWxlXSgpKTsKICAgIH0KICAgIHJldHVybiBzdHlsZTsKICB9Cn0KY2xhc3MgUGFzc3dvcmRFZGl0IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInBhc3N3b3JkRWRpdCIsIHRydWUpOwogICAgdGhpcy5oU2Nyb2xsUG9saWN5ID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuaFNjcm9sbFBvbGljeSwgWyJhdXRvIiwgIm9mZiIsICJvbiJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5wYXNzd29yZENoYXIgPSBhdHRyaWJ1dGVzLnBhc3N3b3JkQ2hhciB8fCAiKiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogIH0KfQpjbGFzcyBQYXR0ZXJuIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInBhdHRlcm4iLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMudHlwZSwgWyJjcm9zc0hhdGNoIiwgImNyb3NzRGlhZ29uYWwiLCAiZGlhZ29uYWxMZWZ0IiwgImRpYWdvbmFsUmlnaHQiLCAiaG9yaXpvbnRhbCIsICJ2ZXJ0aWNhbCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNvbG9yID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiR0b1N0eWxlXShzdGFydENvbG9yKSB7CiAgICBzdGFydENvbG9yID0gc3RhcnRDb2xvciA/IHN0YXJ0Q29sb3JbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCkgOiAiI0ZGRkZGRiI7CiAgICBjb25zdCBlbmRDb2xvciA9IHRoaXMuY29sb3IgPyB0aGlzLmNvbG9yW194ZmFfb2JqZWN0LiR0b1N0eWxlXSgpIDogIiMwMDAwMDAiOwogICAgY29uc3Qgd2lkdGggPSA1OwogICAgY29uc3QgY21kID0gInJlcGVhdGluZy1saW5lYXItZ3JhZGllbnQiOwogICAgY29uc3QgY29sb3JzID0gYCR7c3RhcnRDb2xvcn0sJHtzdGFydENvbG9yfSAke3dpZHRofXB4LCR7ZW5kQ29sb3J9ICR7d2lkdGh9cHgsJHtlbmRDb2xvcn0gJHsyICogd2lkdGh9cHhgOwogICAgc3dpdGNoICh0aGlzLnR5cGUpIHsKICAgICAgY2FzZSAiY3Jvc3NIYXRjaCI6CiAgICAgICAgcmV0dXJuIGAke2NtZH0odG8gdG9wLCR7Y29sb3JzfSkgJHtjbWR9KHRvIHJpZ2h0LCR7Y29sb3JzfSlgOwogICAgICBjYXNlICJjcm9zc0RpYWdvbmFsIjoKICAgICAgICByZXR1cm4gYCR7Y21kfSg0NWRlZywke2NvbG9yc30pICR7Y21kfSgtNDVkZWcsJHtjb2xvcnN9KWA7CiAgICAgIGNhc2UgImRpYWdvbmFsTGVmdCI6CiAgICAgICAgcmV0dXJuIGAke2NtZH0oNDVkZWcsJHtjb2xvcnN9KWA7CiAgICAgIGNhc2UgImRpYWdvbmFsUmlnaHQiOgogICAgICAgIHJldHVybiBgJHtjbWR9KC00NWRlZywke2NvbG9yc30pYDsKICAgICAgY2FzZSAiaG9yaXpvbnRhbCI6CiAgICAgICAgcmV0dXJuIGAke2NtZH0odG8gdG9wLCR7Y29sb3JzfSlgOwogICAgICBjYXNlICJ2ZXJ0aWNhbCI6CiAgICAgICAgcmV0dXJuIGAke2NtZH0odG8gcmlnaHQsJHtjb2xvcnN9KWA7CiAgICB9CiAgICByZXR1cm4gIiI7CiAgfQp9CmNsYXNzIFBpY3R1cmUgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAicGljdHVyZSIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBQcm90byBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJwcm90byIsIHRydWUpOwogICAgdGhpcy5hcHBlYXJhbmNlRmlsdGVyID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmFyYyA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5hcmVhID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmFzc2lzdCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5iYXJjb2RlID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmJpbmRJdGVtcyA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5ib29rZW5kID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmJvb2xlYW4gPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYm9yZGVyID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmJyZWFrID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmJyZWFrQWZ0ZXIgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYnJlYWtCZWZvcmUgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYnV0dG9uID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNhbGN1bGF0ZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5jYXB0aW9uID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNlcnRpZmljYXRlID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNlcnRpZmljYXRlcyA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5jaGVja0J1dHRvbiA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5jaG9pY2VMaXN0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNvbG9yID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNvbWIgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY29ubmVjdCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5jb250ZW50QXJlYSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5jb3JuZXIgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGF0ZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlVGltZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlVGltZUVkaXQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGVjaW1hbCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZWZhdWx0VWkgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGVzYyA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kaWdlc3RNZXRob2QgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGlnZXN0TWV0aG9kcyA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kcmF3ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmVkZ2UgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZW5jb2RpbmcgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZW5jb2RpbmdzID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmVuY3J5cHQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZW5jcnlwdERhdGEgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZW5jcnlwdGlvbiA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5lbmNyeXB0aW9uTWV0aG9kID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmVuY3J5cHRpb25NZXRob2RzID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV2ZW50ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4RGF0YSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leE9iamVjdCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leGNsR3JvdXAgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXhlY3V0ZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leHRyYXMgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmllbGQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmlsbCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5maWx0ZXIgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmxvYXQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZm9udCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5mb3JtYXQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaGFuZGxlciA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5oeXBoZW5hdGlvbiA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbWFnZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbWFnZUVkaXQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaW50ZWdlciA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pc3N1ZXJzID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLml0ZW1zID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmtlZXAgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMua2V5VXNhZ2UgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubGluZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5saW5lYXIgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubG9ja0RvY3VtZW50ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLm1hbmlmZXN0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLm1hcmdpbiA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5tZHAgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubWVkaXVtID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLm1lc3NhZ2UgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubnVtZXJpY0VkaXQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMub2NjdXIgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMub2lkID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLm9pZHMgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMub3ZlcmZsb3cgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucGFnZUFyZWEgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucGFnZVNldCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wYXJhID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnBhc3N3b3JkRWRpdCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wYXR0ZXJuID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnBpY3R1cmUgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucmFkaWFsID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnJlYXNvbiA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5yZWFzb25zID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnJlY3RhbmdsZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5yZWYgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2NyaXB0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnNldFByb3BlcnR5ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnNpZ25EYXRhID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnNpZ25hdHVyZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zaWduaW5nID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnNvbGlkID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnNwZWFrID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN0aXBwbGUgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3ViZm9ybSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zdWJmb3JtU2V0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1YmplY3RETiA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zdWJqZWN0RE5zID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1Ym1pdCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50ZXh0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRleHRFZGl0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRpbWUgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGltZVN0YW1wID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRvb2xUaXAgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudHJhdmVyc2FsID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRyYXZlcnNlID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnVpID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnZhbGlkYXRlID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnZhbHVlID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnZhcmlhYmxlcyA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBSYWRpYWwgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAicmFkaWFsIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnR5cGUsIFsidG9FZGdlIiwgInRvQ2VudGVyIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY29sb3IgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbX3hmYV9vYmplY3QuJHRvU3R5bGVdKHN0YXJ0Q29sb3IpIHsKICAgIHN0YXJ0Q29sb3IgPSBzdGFydENvbG9yID8gc3RhcnRDb2xvcltfeGZhX29iamVjdC4kdG9TdHlsZV0oKSA6ICIjRkZGRkZGIjsKICAgIGNvbnN0IGVuZENvbG9yID0gdGhpcy5jb2xvciA/IHRoaXMuY29sb3JbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCkgOiAiIzAwMDAwMCI7CiAgICBjb25zdCBjb2xvcnMgPSB0aGlzLnR5cGUgPT09ICJ0b0VkZ2UiID8gYCR7c3RhcnRDb2xvcn0sJHtlbmRDb2xvcn1gIDogYCR7ZW5kQ29sb3J9LCR7c3RhcnRDb2xvcn1gOwogICAgcmV0dXJuIGByYWRpYWwtZ3JhZGllbnQoY2lyY2xlIGF0IGNlbnRlciwgJHtjb2xvcnN9KWA7CiAgfQp9CmNsYXNzIFJlYXNvbiBleHRlbmRzIF94ZmFfb2JqZWN0LlN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJyZWFzb24iKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgUmVhc29ucyBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJyZWFzb25zIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnR5cGUsIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5yZWFzb24gPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgUmVjdGFuZ2xlIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInJlY3RhbmdsZSIsIHRydWUpOwogICAgdGhpcy5oYW5kID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuaGFuZCwgWyJldmVuIiwgImxlZnQiLCAicmlnaHQiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNvcm5lciA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSg0KTsKICAgIHRoaXMuZWRnZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSg0KTsKICAgIHRoaXMuZmlsbCA9IG51bGw7CiAgfQogIFtfeGZhX29iamVjdC4kdG9IVE1MXSgpIHsKICAgIGNvbnN0IGVkZ2UgPSB0aGlzLmVkZ2UuY2hpbGRyZW4ubGVuZ3RoID8gdGhpcy5lZGdlLmNoaWxkcmVuWzBdIDogbmV3IEVkZ2Uoe30pOwogICAgY29uc3QgZWRnZVN0eWxlID0gZWRnZVtfeGZhX29iamVjdC4kdG9TdHlsZV0oKTsKICAgIGNvbnN0IHN0eWxlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGlmICh0aGlzLmZpbGwgJiYgdGhpcy5maWxsLnByZXNlbmNlID09PSAidmlzaWJsZSIpIHsKICAgICAgT2JqZWN0LmFzc2lnbihzdHlsZSwgdGhpcy5maWxsW194ZmFfb2JqZWN0LiR0b1N0eWxlXSgpKTsKICAgIH0gZWxzZSB7CiAgICAgIHN0eWxlLmZpbGwgPSAidHJhbnNwYXJlbnQiOwogICAgfQogICAgc3R5bGUuc3Ryb2tlV2lkdGggPSAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKShlZGdlLnByZXNlbmNlID09PSAidmlzaWJsZSIgPyBlZGdlLnRoaWNrbmVzcyA6IDApOwogICAgc3R5bGUuc3Ryb2tlID0gZWRnZVN0eWxlLmNvbG9yOwogICAgY29uc3QgY29ybmVyID0gdGhpcy5jb3JuZXIuY2hpbGRyZW4ubGVuZ3RoID8gdGhpcy5jb3JuZXIuY2hpbGRyZW5bMF0gOiBuZXcgQ29ybmVyKHt9KTsKICAgIGNvbnN0IGNvcm5lclN0eWxlID0gY29ybmVyW194ZmFfb2JqZWN0LiR0b1N0eWxlXSgpOwogICAgY29uc3QgcmVjdCA9IHsKICAgICAgbmFtZTogInJlY3QiLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgeG1sbnM6IFNWR19OUywKICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgIGhlaWdodDogIjEwMCUiLAogICAgICAgIHg6IDAsCiAgICAgICAgeTogMCwKICAgICAgICByeDogY29ybmVyU3R5bGUucmFkaXVzLAogICAgICAgIHJ5OiBjb3JuZXJTdHlsZS5yYWRpdXMsCiAgICAgICAgc3R5bGUKICAgICAgfQogICAgfTsKICAgIGNvbnN0IHN2ZyA9IHsKICAgICAgbmFtZTogInN2ZyIsCiAgICAgIGNoaWxkcmVuOiBbcmVjdF0sCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICB4bWxuczogU1ZHX05TLAogICAgICAgIHN0eWxlOiB7CiAgICAgICAgICBvdmVyZmxvdzogInZpc2libGUiCiAgICAgICAgfSwKICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgIGhlaWdodDogIjEwMCUiCiAgICAgIH0KICAgIH07CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKClbX3hmYV9vYmplY3QuJGdldFBhcmVudF0oKTsKICAgIGlmIChoYXNNYXJnaW4ocGFyZW50KSkgewogICAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgICAgbmFtZTogImRpdiIsCiAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgc3R5bGU6IHsKICAgICAgICAgICAgZGlzcGxheTogImlubGluZSIsCiAgICAgICAgICAgIHdpZHRoOiAiMTAwJSIsCiAgICAgICAgICAgIGhlaWdodDogIjEwMCUiCiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICBjaGlsZHJlbjogW3N2Z10KICAgICAgfSk7CiAgICB9CiAgICBzdmcuYXR0cmlidXRlcy5zdHlsZS5wb3NpdGlvbiA9ICJhYnNvbHV0ZSI7CiAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2VzcyhzdmcpOwogIH0KfQpjbGFzcyBSZWZFbGVtZW50IGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInJlZiIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBTY3JpcHQgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAic2NyaXB0Iik7CiAgICB0aGlzLmJpbmRpbmcgPSBhdHRyaWJ1dGVzLmJpbmRpbmcgfHwgIiI7CiAgICB0aGlzLmNvbnRlbnRUeXBlID0gYXR0cmlidXRlcy5jb250ZW50VHlwZSB8fCAiIjsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5ydW5BdCA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnJ1bkF0LCBbImNsaWVudCIsICJib3RoIiwgInNlcnZlciJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIFNldFByb3BlcnR5IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInNldFByb3BlcnR5Iik7CiAgICB0aGlzLmNvbm5lY3Rpb24gPSBhdHRyaWJ1dGVzLmNvbm5lY3Rpb24gfHwgIiI7CiAgICB0aGlzLnJlZiA9IGF0dHJpYnV0ZXMucmVmIHx8ICIiOwogICAgdGhpcy50YXJnZXQgPSBhdHRyaWJ1dGVzLnRhcmdldCB8fCAiIjsKICB9Cn0KZXhwb3J0cy5TZXRQcm9wZXJ0eSA9IFNldFByb3BlcnR5OwpjbGFzcyBTaWduRGF0YSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzaWduRGF0YSIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm9wZXJhdGlvbiA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLm9wZXJhdGlvbiwgWyJzaWduIiwgImNsZWFyIiwgInZlcmlmeSJdKTsKICAgIHRoaXMucmVmID0gYXR0cmlidXRlcy5yZWYgfHwgIiI7CiAgICB0aGlzLnRhcmdldCA9IGF0dHJpYnV0ZXMudGFyZ2V0IHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZmlsdGVyID0gbnVsbDsKICAgIHRoaXMubWFuaWZlc3QgPSBudWxsOwogIH0KfQpjbGFzcyBTaWduYXR1cmUgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAic2lnbmF0dXJlIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnR5cGUsIFsiUERGMS4zIiwgIlBERjEuNiJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmJvcmRlciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLmZpbHRlciA9IG51bGw7CiAgICB0aGlzLm1hbmlmZXN0ID0gbnVsbDsKICAgIHRoaXMubWFyZ2luID0gbnVsbDsKICB9Cn0KY2xhc3MgU2lnbmluZyBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzaWduaW5nIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnR5cGUsIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5jZXJ0aWZpY2F0ZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBTb2xpZCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzb2xpZCIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbX3hmYV9vYmplY3QuJHRvU3R5bGVdKHN0YXJ0Q29sb3IpIHsKICAgIHJldHVybiBzdGFydENvbG9yID8gc3RhcnRDb2xvcltfeGZhX29iamVjdC4kdG9TdHlsZV0oKSA6ICIjRkZGRkZGIjsKICB9Cn0KY2xhc3MgU3BlYWsgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAic3BlYWsiKTsKICAgIHRoaXMuZGlzYWJsZSA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmRpc2FibGUsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMucHJpb3JpdHkgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5wcmlvcml0eSwgWyJjdXN0b20iLCAiY2FwdGlvbiIsICJuYW1lIiwgInRvb2xUaXAiXSk7CiAgICB0aGlzLnJpZCA9IGF0dHJpYnV0ZXMucmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgU3RpcHBsZSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzdGlwcGxlIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMucmF0ZSA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnJhdGUsCiAgICAgIGRlZmF1bHRWYWx1ZTogNTAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMCAmJiB4IDw9IDEwMAogICAgfSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5jb2xvciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQogIFtfeGZhX29iamVjdC4kdG9TdHlsZV0oYmdDb2xvcikgewogICAgY29uc3QgYWxwaGEgPSB0aGlzLnJhdGUgLyAxMDA7CiAgICByZXR1cm4gX3V0aWwuVXRpbC5tYWtlSGV4Q29sb3IoTWF0aC5yb3VuZChiZ0NvbG9yLnZhbHVlLnIgKiAoMSAtIGFscGhhKSArIHRoaXMudmFsdWUuciAqIGFscGhhKSwgTWF0aC5yb3VuZChiZ0NvbG9yLnZhbHVlLmcgKiAoMSAtIGFscGhhKSArIHRoaXMudmFsdWUuZyAqIGFscGhhKSwgTWF0aC5yb3VuZChiZ0NvbG9yLnZhbHVlLmIgKiAoMSAtIGFscGhhKSArIHRoaXMudmFsdWUuYiAqIGFscGhhKSk7CiAgfQp9CmNsYXNzIFN1YmZvcm0gZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAic3ViZm9ybSIsIHRydWUpOwogICAgdGhpcy5hY2Nlc3MgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5hY2Nlc3MsIFsib3BlbiIsICJub25JbnRlcmFjdGl2ZSIsICJwcm90ZWN0ZWQiLCAicmVhZE9ubHkiXSk7CiAgICB0aGlzLmFsbG93TWFjcm8gPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5hbGxvd01hY3JvLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy5hbmNob3JUeXBlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuYW5jaG9yVHlwZSwgWyJ0b3BMZWZ0IiwgImJvdHRvbUNlbnRlciIsICJib3R0b21MZWZ0IiwgImJvdHRvbVJpZ2h0IiwgIm1pZGRsZUNlbnRlciIsICJtaWRkbGVMZWZ0IiwgIm1pZGRsZVJpZ2h0IiwgInRvcENlbnRlciIsICJ0b3BSaWdodCJdKTsKICAgIHRoaXMuY29sU3BhbiA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmNvbFNwYW4sCiAgICAgIGRlZmF1bHRWYWx1ZTogMSwKICAgICAgdmFsaWRhdGU6IG4gPT4gbiA+PSAxIHx8IG4gPT09IC0xCiAgICB9KTsKICAgIHRoaXMuY29sdW1uV2lkdGhzID0gKGF0dHJpYnV0ZXMuY29sdW1uV2lkdGhzIHx8ICIiKS50cmltKCkuc3BsaXQoL1xzKy8pLm1hcCh4ID0+IHggPT09ICItMSIgPyAtMSA6ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHgpKTsKICAgIHRoaXMuaCA9IGF0dHJpYnV0ZXMuaCA/ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMuaCkgOiAiIjsKICAgIHRoaXMuaEFsaWduID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuaEFsaWduLCBbImxlZnQiLCAiY2VudGVyIiwgImp1c3RpZnkiLCAianVzdGlmeUFsbCIsICJyYWRpeCIsICJyaWdodCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5sYXlvdXQgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5sYXlvdXQsIFsicG9zaXRpb24iLCAibHItdGIiLCAicmwtcm93IiwgInJsLXRiIiwgInJvdyIsICJ0YWJsZSIsICJ0YiJdKTsKICAgIHRoaXMubG9jYWxlID0gYXR0cmlidXRlcy5sb2NhbGUgfHwgIiI7CiAgICB0aGlzLm1heEggPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShhdHRyaWJ1dGVzLm1heEgsICIwcHQiKTsKICAgIHRoaXMubWF4VyA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMubWF4VywgIjBwdCIpOwogICAgdGhpcy5tZXJnZU1vZGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5tZXJnZU1vZGUsIFsiY29uc3VtZURhdGEiLCAibWF0Y2hUZW1wbGF0ZSJdKTsKICAgIHRoaXMubWluSCA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMubWluSCwgIjBwdCIpOwogICAgdGhpcy5taW5XID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy5taW5XLCAiMHB0Iik7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnByZXNlbmNlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMucHJlc2VuY2UsIFsidmlzaWJsZSIsICJoaWRkZW4iLCAiaW5hY3RpdmUiLCAiaW52aXNpYmxlIl0pOwogICAgdGhpcy5yZWxldmFudCA9ICgwLCBfdXRpbHMuZ2V0UmVsZXZhbnQpKGF0dHJpYnV0ZXMucmVsZXZhbnQpOwogICAgdGhpcy5yZXN0b3JlU3RhdGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5yZXN0b3JlU3RhdGUsIFsibWFudWFsIiwgImF1dG8iXSk7CiAgICB0aGlzLnNjb3BlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuc2NvcGUsIFsibmFtZSIsICJub25lIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMudyA9IGF0dHJpYnV0ZXMudyA/ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMudykgOiAiIjsKICAgIHRoaXMueCA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKGF0dHJpYnV0ZXMueCwgIjBwdCIpOwogICAgdGhpcy55ID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkoYXR0cmlidXRlcy55LCAiMHB0Iik7CiAgICB0aGlzLmFzc2lzdCA9IG51bGw7CiAgICB0aGlzLmJpbmQgPSBudWxsOwogICAgdGhpcy5ib29rZW5kID0gbnVsbDsKICAgIHRoaXMuYm9yZGVyID0gbnVsbDsKICAgIHRoaXMuYnJlYWsgPSBudWxsOwogICAgdGhpcy5jYWxjdWxhdGUgPSBudWxsOwogICAgdGhpcy5kZXNjID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMua2VlcCA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgICB0aGlzLm9jY3VyID0gbnVsbDsKICAgIHRoaXMub3ZlcmZsb3cgPSBudWxsOwogICAgdGhpcy5wYWdlU2V0ID0gbnVsbDsKICAgIHRoaXMucGFyYSA9IG51bGw7CiAgICB0aGlzLnRyYXZlcnNhbCA9IG51bGw7CiAgICB0aGlzLnZhbGlkYXRlID0gbnVsbDsKICAgIHRoaXMudmFyaWFibGVzID0gbnVsbDsKICAgIHRoaXMuYXJlYSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5icmVha0FmdGVyID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmJyZWFrQmVmb3JlID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNvbm5lY3QgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZHJhdyA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5ldmVudCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leE9iamVjdCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leGNsR3JvdXAgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmllbGQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucHJvdG8gPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2V0UHJvcGVydHkgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3ViZm9ybSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zdWJmb3JtU2V0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgfQogIFtfeGZhX29iamVjdC4kZ2V0U3ViZm9ybVBhcmVudF0oKSB7CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICBpZiAocGFyZW50IGluc3RhbmNlb2YgU3ViZm9ybVNldCkgewogICAgICByZXR1cm4gcGFyZW50W194ZmFfb2JqZWN0LiRnZXRTdWJmb3JtUGFyZW50XSgpOwogICAgfQogICAgcmV0dXJuIHBhcmVudDsKICB9CiAgW194ZmFfb2JqZWN0LiRpc0JpbmRhYmxlXSgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBbX3hmYV9vYmplY3QuJGlzVGhlcmVNb3JlV2lkdGhdKCkgewogICAgcmV0dXJuIHRoaXMubGF5b3V0LmVuZHNXaXRoKCItdGIiKSAmJiB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uYXR0ZW1wdCA9PT0gMCAmJiB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0ubnVtYmVySW5MaW5lID4gMCB8fCB0aGlzW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKClbX3hmYV9vYmplY3QuJGlzVGhlcmVNb3JlV2lkdGhdKCk7CiAgfQogICpbX3hmYV9vYmplY3QuJGdldENvbnRhaW5lZENoaWxkcmVuXSgpIHsKICAgIHlpZWxkKiBnZXRDb250YWluZWRDaGlsZHJlbih0aGlzKTsKICB9CiAgW194ZmFfb2JqZWN0LiRmbHVzaEhUTUxdKCkgewogICAgcmV0dXJuICgwLCBfbGF5b3V0LmZsdXNoSFRNTCkodGhpcyk7CiAgfQogIFtfeGZhX29iamVjdC4kYWRkSFRNTF0oaHRtbCwgYmJveCkgewogICAgKDAsIF9sYXlvdXQuYWRkSFRNTCkodGhpcywgaHRtbCwgYmJveCk7CiAgfQogIFtfeGZhX29iamVjdC4kZ2V0QXZhaWxhYmxlU3BhY2VdKCkgewogICAgcmV0dXJuICgwLCBfbGF5b3V0LmdldEF2YWlsYWJsZVNwYWNlKSh0aGlzKTsKICB9CiAgW194ZmFfb2JqZWN0LiRpc1NwbGl0dGFibGVdKCkgewogICAgY29uc3QgcGFyZW50ID0gdGhpc1tfeGZhX29iamVjdC4kZ2V0U3ViZm9ybVBhcmVudF0oKTsKICAgIGlmICghcGFyZW50W194ZmFfb2JqZWN0LiRpc1NwbGl0dGFibGVdKCkpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5faXNTcGxpdHRhYmxlICE9PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5faXNTcGxpdHRhYmxlOwogICAgfQogICAgaWYgKHRoaXMubGF5b3V0ID09PSAicG9zaXRpb24iIHx8IHRoaXMubGF5b3V0LmluY2x1ZGVzKCJyb3ciKSkgewogICAgICB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uX2lzU3BsaXR0YWJsZSA9IGZhbHNlOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpcy5rZWVwICYmIHRoaXMua2VlcC5pbnRhY3QgIT09ICJub25lIikgewogICAgICB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uX2lzU3BsaXR0YWJsZSA9IGZhbHNlOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAocGFyZW50LmxheW91dCAmJiBwYXJlbnQubGF5b3V0LmVuZHNXaXRoKCItdGIiKSAmJiBwYXJlbnRbX3hmYV9vYmplY3QuJGV4dHJhXS5udW1iZXJJbkxpbmUgIT09IDApIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLl9pc1NwbGl0dGFibGUgPSB0cnVlOwogICAgcmV0dXJuIHRydWU7CiAgfQogIFtfeGZhX29iamVjdC4kdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgc2V0VGFiSW5kZXgodGhpcyk7CiAgICBpZiAodGhpcy5icmVhaykgewogICAgICBpZiAodGhpcy5icmVhay5hZnRlciAhPT0gImF1dG8iIHx8IHRoaXMuYnJlYWsuYWZ0ZXJUYXJnZXQgIT09ICIiKSB7CiAgICAgICAgY29uc3Qgbm9kZSA9IG5ldyBCcmVha0FmdGVyKHsKICAgICAgICAgIHRhcmdldFR5cGU6IHRoaXMuYnJlYWsuYWZ0ZXIsCiAgICAgICAgICB0YXJnZXQ6IHRoaXMuYnJlYWsuYWZ0ZXJUYXJnZXQsCiAgICAgICAgICBzdGFydE5ldzogdGhpcy5icmVhay5zdGFydE5ldy50b1N0cmluZygpCiAgICAgICAgfSk7CiAgICAgICAgbm9kZVtfeGZhX29iamVjdC4kZ2xvYmFsRGF0YV0gPSB0aGlzW194ZmFfb2JqZWN0LiRnbG9iYWxEYXRhXTsKICAgICAgICB0aGlzW194ZmFfb2JqZWN0LiRhcHBlbmRDaGlsZF0obm9kZSk7CiAgICAgICAgdGhpcy5icmVha0FmdGVyLnB1c2gobm9kZSk7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuYnJlYWsuYmVmb3JlICE9PSAiYXV0byIgfHwgdGhpcy5icmVhay5iZWZvcmVUYXJnZXQgIT09ICIiKSB7CiAgICAgICAgY29uc3Qgbm9kZSA9IG5ldyBCcmVha0JlZm9yZSh7CiAgICAgICAgICB0YXJnZXRUeXBlOiB0aGlzLmJyZWFrLmJlZm9yZSwKICAgICAgICAgIHRhcmdldDogdGhpcy5icmVhay5iZWZvcmVUYXJnZXQsCiAgICAgICAgICBzdGFydE5ldzogdGhpcy5icmVhay5zdGFydE5ldy50b1N0cmluZygpCiAgICAgICAgfSk7CiAgICAgICAgbm9kZVtfeGZhX29iamVjdC4kZ2xvYmFsRGF0YV0gPSB0aGlzW194ZmFfb2JqZWN0LiRnbG9iYWxEYXRhXTsKICAgICAgICB0aGlzW194ZmFfb2JqZWN0LiRhcHBlbmRDaGlsZF0obm9kZSk7CiAgICAgICAgdGhpcy5icmVha0JlZm9yZS5wdXNoKG5vZGUpOwogICAgICB9CiAgICAgIGlmICh0aGlzLmJyZWFrLm92ZXJmbG93VGFyZ2V0ICE9PSAiIikgewogICAgICAgIGNvbnN0IG5vZGUgPSBuZXcgT3ZlcmZsb3coewogICAgICAgICAgdGFyZ2V0OiB0aGlzLmJyZWFrLm92ZXJmbG93VGFyZ2V0LAogICAgICAgICAgbGVhZGVyOiB0aGlzLmJyZWFrLm92ZXJmbG93TGVhZGVyLAogICAgICAgICAgdHJhaWxlcjogdGhpcy5icmVhay5vdmVyZmxvd1RyYWlsZXIKICAgICAgICB9KTsKICAgICAgICBub2RlW194ZmFfb2JqZWN0LiRnbG9iYWxEYXRhXSA9IHRoaXNbX3hmYV9vYmplY3QuJGdsb2JhbERhdGFdOwogICAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGFwcGVuZENoaWxkXShub2RlKTsKICAgICAgICB0aGlzLm92ZXJmbG93LnB1c2gobm9kZSk7CiAgICAgIH0KICAgICAgdGhpc1tfeGZhX29iamVjdC4kcmVtb3ZlQ2hpbGRdKHRoaXMuYnJlYWspOwogICAgICB0aGlzLmJyZWFrID0gbnVsbDsKICAgIH0KICAgIGlmICh0aGlzLnByZXNlbmNlID09PSAiaGlkZGVuIiB8fCB0aGlzLnByZXNlbmNlID09PSAiaW5hY3RpdmUiKSB7CiAgICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGlmICh0aGlzLmJyZWFrQmVmb3JlLmNoaWxkcmVuLmxlbmd0aCA+IDEgfHwgdGhpcy5icmVha0FmdGVyLmNoaWxkcmVuLmxlbmd0aCA+IDEpIHsKICAgICAgKDAsIF91dGlsLndhcm4pKCJYRkEgLSBTZXZlcmFsIGJyZWFrQmVmb3JlIG9yIGJyZWFrQWZ0ZXIgaW4gc3ViZm9ybXM6IHBsZWFzZSBmaWxlIGEgYnVnLiIpOwogICAgfQogICAgaWYgKHRoaXMuYnJlYWtCZWZvcmUuY2hpbGRyZW4ubGVuZ3RoID49IDEpIHsKICAgICAgY29uc3QgYnJlYWtCZWZvcmUgPSB0aGlzLmJyZWFrQmVmb3JlLmNoaWxkcmVuWzBdOwogICAgICBpZiAoaGFuZGxlQnJlYWsoYnJlYWtCZWZvcmUpKSB7CiAgICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LmJyZWFrTm9kZShicmVha0JlZm9yZSk7CiAgICAgIH0KICAgIH0KICAgIGlmICh0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0gJiYgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmFmdGVyQnJlYWtBZnRlcikgewogICAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuRU1QVFk7CiAgICB9CiAgICAoMCwgX2h0bWxfdXRpbHMuZml4RGltZW5zaW9ucykodGhpcyk7CiAgICBjb25zdCBjaGlsZHJlbiA9IFtdOwogICAgY29uc3QgYXR0cmlidXRlcyA9IHsKICAgICAgaWQ6IHRoaXNbX3hmYV9vYmplY3QuJHVpZF0sCiAgICAgIGNsYXNzOiBbXQogICAgfTsKICAgICgwLCBfaHRtbF91dGlscy5zZXRBY2Nlc3MpKHRoaXMsIGF0dHJpYnV0ZXMuY2xhc3MpOwogICAgaWYgKCF0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0pIHsKICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIH0KICAgIE9iamVjdC5hc3NpZ24odGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLCB7CiAgICAgIGNoaWxkcmVuLAogICAgICBsaW5lOiBudWxsLAogICAgICBhdHRyaWJ1dGVzLAogICAgICBhdHRlbXB0OiAwLAogICAgICBudW1iZXJJbkxpbmU6IDAsCiAgICAgIGF2YWlsYWJsZVNwYWNlOiB7CiAgICAgICAgd2lkdGg6IE1hdGgubWluKHRoaXMudyB8fCBJbmZpbml0eSwgYXZhaWxhYmxlU3BhY2Uud2lkdGgpLAogICAgICAgIGhlaWdodDogTWF0aC5taW4odGhpcy5oIHx8IEluZmluaXR5LCBhdmFpbGFibGVTcGFjZS5oZWlnaHQpCiAgICAgIH0sCiAgICAgIHdpZHRoOiAwLAogICAgICBoZWlnaHQ6IDAsCiAgICAgIHByZXZIZWlnaHQ6IDAsCiAgICAgIGN1cnJlbnRXaWR0aDogMAogICAgfSk7CiAgICBjb25zdCByb290ID0gdGhpc1tfeGZhX29iamVjdC4kZ2V0VGVtcGxhdGVSb290XSgpOwogICAgY29uc3Qgc2F2ZWROb0xheW91dEZhaWx1cmUgPSByb290W194ZmFfb2JqZWN0LiRleHRyYV0ubm9MYXlvdXRGYWlsdXJlOwogICAgY29uc3QgaXNTcGxpdHRhYmxlID0gdGhpc1tfeGZhX29iamVjdC4kaXNTcGxpdHRhYmxlXSgpOwogICAgaWYgKCFpc1NwbGl0dGFibGUpIHsKICAgICAgc2V0Rmlyc3RVbnNwbGl0dGFibGUodGhpcyk7CiAgICB9CiAgICBpZiAoISgwLCBfbGF5b3V0LmNoZWNrRGltZW5zaW9ucykodGhpcywgYXZhaWxhYmxlU3BhY2UpKSB7CiAgICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5GQUlMVVJFOwogICAgfQogICAgY29uc3QgZmlsdGVyID0gbmV3IFNldChbImFyZWEiLCAiZHJhdyIsICJleGNsR3JvdXAiLCAiZmllbGQiLCAic3ViZm9ybSIsICJzdWJmb3JtU2V0Il0pOwogICAgaWYgKHRoaXMubGF5b3V0LmluY2x1ZGVzKCJyb3ciKSkgewogICAgICBjb25zdCBjb2x1bW5XaWR0aHMgPSB0aGlzW194ZmFfb2JqZWN0LiRnZXRTdWJmb3JtUGFyZW50XSgpLmNvbHVtbldpZHRoczsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29sdW1uV2lkdGhzKSAmJiBjb2x1bW5XaWR0aHMubGVuZ3RoID4gMCkgewogICAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5jb2x1bW5XaWR0aHMgPSBjb2x1bW5XaWR0aHM7CiAgICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmN1cnJlbnRDb2x1bW4gPSAwOwogICAgICB9CiAgICB9CiAgICBjb25zdCBzdHlsZSA9ICgwLCBfaHRtbF91dGlscy50b1N0eWxlKSh0aGlzLCAiYW5jaG9yVHlwZSIsICJkaW1lbnNpb25zIiwgInBvc2l0aW9uIiwgInByZXNlbmNlIiwgImJvcmRlciIsICJtYXJnaW4iLCAiaEFsaWduIik7CiAgICBjb25zdCBjbGFzc05hbWVzID0gWyJ4ZmFTdWJmb3JtIl07CiAgICBjb25zdCBjbCA9ICgwLCBfaHRtbF91dGlscy5sYXlvdXRDbGFzcykodGhpcyk7CiAgICBpZiAoY2wpIHsKICAgICAgY2xhc3NOYW1lcy5wdXNoKGNsKTsKICAgIH0KICAgIGF0dHJpYnV0ZXMuc3R5bGUgPSBzdHlsZTsKICAgIGF0dHJpYnV0ZXMuY2xhc3MgPSBjbGFzc05hbWVzOwogICAgaWYgKHRoaXMubmFtZSkgewogICAgICBhdHRyaWJ1dGVzLnhmYU5hbWUgPSB0aGlzLm5hbWU7CiAgICB9CiAgICBpZiAodGhpcy5vdmVyZmxvdykgewogICAgICBjb25zdCBvdmVyZmxvd0V4dHJhID0gdGhpcy5vdmVyZmxvd1tfeGZhX29iamVjdC4kZ2V0RXh0cmFdKCk7CiAgICAgIGlmIChvdmVyZmxvd0V4dHJhLmFkZExlYWRlcikgewogICAgICAgIG92ZXJmbG93RXh0cmEuYWRkTGVhZGVyID0gZmFsc2U7CiAgICAgICAgaGFuZGxlT3ZlcmZsb3codGhpcywgb3ZlcmZsb3dFeHRyYS5sZWFkZXIsIGF2YWlsYWJsZVNwYWNlKTsKICAgICAgfQogICAgfQogICAgdGhpc1tfeGZhX29iamVjdC4kcHVzaFBhcmFdKCk7CiAgICBjb25zdCBpc0xyVGIgPSB0aGlzLmxheW91dCA9PT0gImxyLXRiIiB8fCB0aGlzLmxheW91dCA9PT0gInJsLXRiIjsKICAgIGNvbnN0IG1heFJ1biA9IGlzTHJUYiA/IE1BWF9BVFRFTVBUU19GT1JfTFJUQl9MQVlPVVQgOiAxOwogICAgZm9yICg7IHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5hdHRlbXB0IDwgbWF4UnVuOyB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uYXR0ZW1wdCsrKSB7CiAgICAgIGlmIChpc0xyVGIgJiYgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmF0dGVtcHQgPT09IE1BWF9BVFRFTVBUU19GT1JfTFJUQl9MQVlPVVQgLSAxKSB7CiAgICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLm51bWJlckluTGluZSA9IDA7CiAgICAgIH0KICAgICAgY29uc3QgcmVzdWx0ID0gdGhpc1tfeGZhX29iamVjdC4kY2hpbGRyZW5Ub0hUTUxdKHsKICAgICAgICBmaWx0ZXIsCiAgICAgICAgaW5jbHVkZTogdHJ1ZQogICAgICB9KTsKICAgICAgaWYgKHJlc3VsdC5zdWNjZXNzKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKHJlc3VsdC5pc0JyZWFrKCkpIHsKICAgICAgICB0aGlzW194ZmFfb2JqZWN0LiRwb3BQYXJhXSgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KICAgICAgaWYgKGlzTHJUYiAmJiB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uYXR0ZW1wdCA9PT0gMCAmJiB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0ubnVtYmVySW5MaW5lID09PSAwICYmICFyb290W194ZmFfb2JqZWN0LiRleHRyYV0ubm9MYXlvdXRGYWlsdXJlKSB7CiAgICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmF0dGVtcHQgPSBtYXhSdW47CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHRoaXNbX3hmYV9vYmplY3QuJHBvcFBhcmFdKCk7CiAgICBpZiAoIWlzU3BsaXR0YWJsZSkgewogICAgICB1bnNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgfQogICAgcm9vdFtfeGZhX29iamVjdC4kZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSA9IHNhdmVkTm9MYXlvdXRGYWlsdXJlOwogICAgaWYgKHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5hdHRlbXB0ID09PSBtYXhSdW4pIHsKICAgICAgaWYgKHRoaXMub3ZlcmZsb3cpIHsKICAgICAgICB0aGlzW194ZmFfb2JqZWN0LiRnZXRUZW1wbGF0ZVJvb3RdKClbX3hmYV9vYmplY3QuJGV4dHJhXS5vdmVyZmxvd05vZGUgPSB0aGlzLm92ZXJmbG93OwogICAgICB9CiAgICAgIGlmICghaXNTcGxpdHRhYmxlKSB7CiAgICAgICAgZGVsZXRlIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXTsKICAgICAgfQogICAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuRkFJTFVSRTsKICAgIH0KICAgIGlmICh0aGlzLm92ZXJmbG93KSB7CiAgICAgIGNvbnN0IG92ZXJmbG93RXh0cmEgPSB0aGlzLm92ZXJmbG93W194ZmFfb2JqZWN0LiRnZXRFeHRyYV0oKTsKICAgICAgaWYgKG92ZXJmbG93RXh0cmEuYWRkVHJhaWxlcikgewogICAgICAgIG92ZXJmbG93RXh0cmEuYWRkVHJhaWxlciA9IGZhbHNlOwogICAgICAgIGhhbmRsZU92ZXJmbG93KHRoaXMsIG92ZXJmbG93RXh0cmEudHJhaWxlciwgYXZhaWxhYmxlU3BhY2UpOwogICAgICB9CiAgICB9CiAgICBsZXQgbWFyZ2luSCA9IDA7CiAgICBsZXQgbWFyZ2luViA9IDA7CiAgICBpZiAodGhpcy5tYXJnaW4pIHsKICAgICAgbWFyZ2luSCA9IHRoaXMubWFyZ2luLmxlZnRJbnNldCArIHRoaXMubWFyZ2luLnJpZ2h0SW5zZXQ7CiAgICAgIG1hcmdpblYgPSB0aGlzLm1hcmdpbi50b3BJbnNldCArIHRoaXMubWFyZ2luLmJvdHRvbUluc2V0OwogICAgfQogICAgY29uc3Qgd2lkdGggPSBNYXRoLm1heCh0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0ud2lkdGggKyBtYXJnaW5ILCB0aGlzLncgfHwgMCk7CiAgICBjb25zdCBoZWlnaHQgPSBNYXRoLm1heCh0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0uaGVpZ2h0ICsgbWFyZ2luViwgdGhpcy5oIHx8IDApOwogICAgY29uc3QgYmJveCA9IFt0aGlzLngsIHRoaXMueSwgd2lkdGgsIGhlaWdodF07CiAgICBpZiAodGhpcy53ID09PSAiIikgewogICAgICBzdHlsZS53aWR0aCA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKHdpZHRoKTsKICAgIH0KICAgIGlmICh0aGlzLmggPT09ICIiKSB7CiAgICAgIHN0eWxlLmhlaWdodCA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKGhlaWdodCk7CiAgICB9CiAgICBpZiAoKHN0eWxlLndpZHRoID09PSAiMHB4IiB8fCBzdHlsZS5oZWlnaHQgPT09ICIwcHgiKSAmJiBjaGlsZHJlbi5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgY29uc3QgaHRtbCA9IHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGNoaWxkcmVuCiAgICB9OwogICAgYXBwbHlBc3Npc3QodGhpcywgYXR0cmlidXRlcyk7CiAgICBjb25zdCByZXN1bHQgPSBfdXRpbHMuSFRNTFJlc3VsdC5zdWNjZXNzKCgwLCBfaHRtbF91dGlscy5jcmVhdGVXcmFwcGVyKSh0aGlzLCBodG1sKSwgYmJveCk7CiAgICBpZiAodGhpcy5icmVha0FmdGVyLmNoaWxkcmVuLmxlbmd0aCA+PSAxKSB7CiAgICAgIGNvbnN0IGJyZWFrQWZ0ZXIgPSB0aGlzLmJyZWFrQWZ0ZXIuY2hpbGRyZW5bMF07CiAgICAgIGlmIChoYW5kbGVCcmVhayhicmVha0FmdGVyKSkgewogICAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5hZnRlckJyZWFrQWZ0ZXIgPSByZXN1bHQ7CiAgICAgICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LmJyZWFrTm9kZShicmVha0FmdGVyKTsKICAgICAgfQogICAgfQogICAgZGVsZXRlIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXTsKICAgIHJldHVybiByZXN1bHQ7CiAgfQp9CmNsYXNzIFN1YmZvcm1TZXQgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAic3ViZm9ybVNldCIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnJlbGF0aW9uID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMucmVsYXRpb24sIFsib3JkZXJlZCIsICJjaG9pY2UiLCAidW5vcmRlcmVkIl0pOwogICAgdGhpcy5yZWxldmFudCA9ICgwLCBfdXRpbHMuZ2V0UmVsZXZhbnQpKGF0dHJpYnV0ZXMucmVsZXZhbnQpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuYm9va2VuZCA9IG51bGw7CiAgICB0aGlzLmJyZWFrID0gbnVsbDsKICAgIHRoaXMuZGVzYyA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLm9jY3VyID0gbnVsbDsKICAgIHRoaXMub3ZlcmZsb3cgPSBudWxsOwogICAgdGhpcy5icmVha0FmdGVyID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmJyZWFrQmVmb3JlID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1YmZvcm0gPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3ViZm9ybVNldCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KICAqW194ZmFfb2JqZWN0LiRnZXRDb250YWluZWRDaGlsZHJlbl0oKSB7CiAgICB5aWVsZCogZ2V0Q29udGFpbmVkQ2hpbGRyZW4odGhpcyk7CiAgfQogIFtfeGZhX29iamVjdC4kZ2V0U3ViZm9ybVBhcmVudF0oKSB7CiAgICBsZXQgcGFyZW50ID0gdGhpc1tfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpOwogICAgd2hpbGUgKCEocGFyZW50IGluc3RhbmNlb2YgU3ViZm9ybSkpIHsKICAgICAgcGFyZW50ID0gcGFyZW50W194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICB9CiAgICByZXR1cm4gcGFyZW50OwogIH0KICBbX3hmYV9vYmplY3QuJGlzQmluZGFibGVdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQp9CmNsYXNzIFN1YmplY3RETiBleHRlbmRzIF94ZmFfb2JqZWN0LkNvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAic3ViamVjdEROIik7CiAgICB0aGlzLmRlbGltaXRlciA9IGF0dHJpYnV0ZXMuZGVsaW1pdGVyIHx8ICIsIjsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgW194ZmFfb2JqZWN0LiRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA9IG5ldyBNYXAodGhpc1tfeGZhX29iamVjdC4kY29udGVudF0uc3BsaXQodGhpcy5kZWxpbWl0ZXIpLm1hcChrdiA9PiB7CiAgICAgIGt2ID0ga3Yuc3BsaXQoIj0iLCAyKTsKICAgICAga3ZbMF0gPSBrdlswXS50cmltKCk7CiAgICAgIHJldHVybiBrdjsKICAgIH0pKTsKICB9Cn0KY2xhc3MgU3ViamVjdEROcyBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzdWJqZWN0RE5zIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnR5cGUsIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5zdWJqZWN0RE4gPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgU3VibWl0IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInN1Ym1pdCIsIHRydWUpOwogICAgdGhpcy5lbWJlZFBERiA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmVtYmVkUERGLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy5mb3JtYXQgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5mb3JtYXQsIFsieGRwIiwgImZvcm1kYXRhIiwgInBkZiIsICJ1cmxlbmNvZGVkIiwgInhmZCIsICJ4bWwiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudGFyZ2V0ID0gYXR0cmlidXRlcy50YXJnZXQgfHwgIiI7CiAgICB0aGlzLnRleHRFbmNvZGluZyA9ICgwLCBfdXRpbHMuZ2V0S2V5d29yZCkoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnRleHRFbmNvZGluZyA/IGF0dHJpYnV0ZXMudGV4dEVuY29kaW5nLnRvTG93ZXJDYXNlKCkgOiAiIiwKICAgICAgZGVmYXVsdFZhbHVlOiAiIiwKICAgICAgdmFsaWRhdGU6IGsgPT4gWyJ1dGYtOCIsICJiaWctZml2ZSIsICJmb250c3BlY2lmaWMiLCAiZ2JrIiwgImdiLTE4MDMwIiwgImdiLTIzMTIiLCAia3NjLTU2MDEiLCAibm9uZSIsICJzaGlmdC1qaXMiLCAidWNzLTIiLCAidXRmLTE2Il0uaW5jbHVkZXMoaykgfHwgay5tYXRjaCgvaXNvLTg4NTktXGR7Mn0vKQogICAgfSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy54ZHBDb250ZW50ID0gYXR0cmlidXRlcy54ZHBDb250ZW50IHx8ICIiOwogICAgdGhpcy5lbmNyeXB0ID0gbnVsbDsKICAgIHRoaXMuZW5jcnlwdERhdGEgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2lnbkRhdGEgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgVGVtcGxhdGUgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAidGVtcGxhdGUiLCB0cnVlKTsKICAgIHRoaXMuYmFzZVByb2ZpbGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5iYXNlUHJvZmlsZSwgWyJmdWxsIiwgImludGVyYWN0aXZlRm9ybXMiXSk7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLnN1YmZvcm0gPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9CiAgW194ZmFfb2JqZWN0LiRmaW5hbGl6ZV0oKSB7CiAgICBpZiAodGhpcy5zdWJmb3JtLmNoaWxkcmVuLmxlbmd0aCA9PT0gMCkgewogICAgICAoMCwgX3V0aWwud2FybikoIlhGQSAtIE5vIHN1YmZvcm1zIGluIHRlbXBsYXRlIG5vZGUuIik7CiAgICB9CiAgICBpZiAodGhpcy5zdWJmb3JtLmNoaWxkcmVuLmxlbmd0aCA+PSAyKSB7CiAgICAgICgwLCBfdXRpbC53YXJuKSgiWEZBIC0gU2V2ZXJhbCBzdWJmb3JtcyBpbiB0ZW1wbGF0ZSBub2RlOiBwbGVhc2UgZmlsZSBhIGJ1Zy4iKTsKICAgIH0KICAgIHRoaXNbX3hmYV9vYmplY3QuJHRhYkluZGV4XSA9IERFRkFVTFRfVEFCX0lOREVYOwogIH0KICBbX3hmYV9vYmplY3QuJGlzU3BsaXR0YWJsZV0oKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgW194ZmFfb2JqZWN0LiRzZWFyY2hOb2RlXShleHByLCBjb250YWluZXIpIHsKICAgIGlmIChleHByLnN0YXJ0c1dpdGgoIiMiKSkgewogICAgICByZXR1cm4gW3RoaXNbX3hmYV9vYmplY3QuJGlkc10uZ2V0KGV4cHIuc2xpY2UoMSkpXTsKICAgIH0KICAgIHJldHVybiAoMCwgX3NvbS5zZWFyY2hOb2RlKSh0aGlzLCBjb250YWluZXIsIGV4cHIsIHRydWUsIHRydWUpOwogIH0KICAqW194ZmFfb2JqZWN0LiR0b1BhZ2VzXSgpIHsKICAgIGlmICghdGhpcy5zdWJmb3JtLmNoaWxkcmVuLmxlbmd0aCkgewogICAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgICAgbmFtZTogImRpdiIsCiAgICAgICAgY2hpbGRyZW46IFtdCiAgICAgIH0pOwogICAgfQogICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdID0gewogICAgICBvdmVyZmxvd05vZGU6IG51bGwsCiAgICAgIGZpcnN0VW5zcGxpdHRhYmxlOiBudWxsLAogICAgICBjdXJyZW50Q29udGVudEFyZWE6IG51bGwsCiAgICAgIGN1cnJlbnRQYWdlQXJlYTogbnVsbCwKICAgICAgbm9MYXlvdXRGYWlsdXJlOiBmYWxzZSwKICAgICAgcGFnZU51bWJlcjogMSwKICAgICAgcGFnZVBvc2l0aW9uOiAiZmlyc3QiLAogICAgICBvZGRPckV2ZW46ICJvZGQiLAogICAgICBibGFua09yTm90Qmxhbms6ICJub25CbGFuayIsCiAgICAgIHBhcmFTdGFjazogW10KICAgIH07CiAgICBjb25zdCByb290ID0gdGhpcy5zdWJmb3JtLmNoaWxkcmVuWzBdOwogICAgcm9vdC5wYWdlU2V0W194ZmFfb2JqZWN0LiRjbGVhblBhZ2VdKCk7CiAgICBjb25zdCBwYWdlQXJlYXMgPSByb290LnBhZ2VTZXQucGFnZUFyZWEuY2hpbGRyZW47CiAgICBjb25zdCBtYWluSHRtbCA9IHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGNoaWxkcmVuOiBbXQogICAgfTsKICAgIGxldCBwYWdlQXJlYSA9IG51bGw7CiAgICBsZXQgYnJlYWtCZWZvcmUgPSBudWxsOwogICAgbGV0IGJyZWFrQmVmb3JlVGFyZ2V0ID0gbnVsbDsKICAgIGlmIChyb290LmJyZWFrQmVmb3JlLmNoaWxkcmVuLmxlbmd0aCA+PSAxKSB7CiAgICAgIGJyZWFrQmVmb3JlID0gcm9vdC5icmVha0JlZm9yZS5jaGlsZHJlblswXTsKICAgICAgYnJlYWtCZWZvcmVUYXJnZXQgPSBicmVha0JlZm9yZS50YXJnZXQ7CiAgICB9IGVsc2UgaWYgKHJvb3Quc3ViZm9ybS5jaGlsZHJlbi5sZW5ndGggPj0gMSAmJiByb290LnN1YmZvcm0uY2hpbGRyZW5bMF0uYnJlYWtCZWZvcmUuY2hpbGRyZW4ubGVuZ3RoID49IDEpIHsKICAgICAgYnJlYWtCZWZvcmUgPSByb290LnN1YmZvcm0uY2hpbGRyZW5bMF0uYnJlYWtCZWZvcmUuY2hpbGRyZW5bMF07CiAgICAgIGJyZWFrQmVmb3JlVGFyZ2V0ID0gYnJlYWtCZWZvcmUudGFyZ2V0OwogICAgfSBlbHNlIGlmIChyb290LmJyZWFrICYmIHJvb3QuYnJlYWsuYmVmb3JlVGFyZ2V0KSB7CiAgICAgIGJyZWFrQmVmb3JlID0gcm9vdC5icmVhazsKICAgICAgYnJlYWtCZWZvcmVUYXJnZXQgPSBicmVha0JlZm9yZS5iZWZvcmVUYXJnZXQ7CiAgICB9IGVsc2UgaWYgKHJvb3Quc3ViZm9ybS5jaGlsZHJlbi5sZW5ndGggPj0gMSAmJiByb290LnN1YmZvcm0uY2hpbGRyZW5bMF0uYnJlYWsgJiYgcm9vdC5zdWJmb3JtLmNoaWxkcmVuWzBdLmJyZWFrLmJlZm9yZVRhcmdldCkgewogICAgICBicmVha0JlZm9yZSA9IHJvb3Quc3ViZm9ybS5jaGlsZHJlblswXS5icmVhazsKICAgICAgYnJlYWtCZWZvcmVUYXJnZXQgPSBicmVha0JlZm9yZS5iZWZvcmVUYXJnZXQ7CiAgICB9CiAgICBpZiAoYnJlYWtCZWZvcmUpIHsKICAgICAgY29uc3QgdGFyZ2V0ID0gdGhpc1tfeGZhX29iamVjdC4kc2VhcmNoTm9kZV0oYnJlYWtCZWZvcmVUYXJnZXQsIGJyZWFrQmVmb3JlW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCkpOwogICAgICBpZiAodGFyZ2V0IGluc3RhbmNlb2YgUGFnZUFyZWEpIHsKICAgICAgICBwYWdlQXJlYSA9IHRhcmdldDsKICAgICAgICBicmVha0JlZm9yZVtfeGZhX29iamVjdC4kZXh0cmFdID0ge307CiAgICAgIH0KICAgIH0KICAgIGlmICghcGFnZUFyZWEpIHsKICAgICAgcGFnZUFyZWEgPSBwYWdlQXJlYXNbMF07CiAgICB9CiAgICBwYWdlQXJlYVtfeGZhX29iamVjdC4kZXh0cmFdID0gewogICAgICBudW1iZXJPZlVzZTogMQogICAgfTsKICAgIGNvbnN0IHBhZ2VBcmVhUGFyZW50ID0gcGFnZUFyZWFbX3hmYV9vYmplY3QuJGdldFBhcmVudF0oKTsKICAgIHBhZ2VBcmVhUGFyZW50W194ZmFfb2JqZWN0LiRleHRyYV0gPSB7CiAgICAgIG51bWJlck9mVXNlOiAxLAogICAgICBwYWdlSW5kZXg6IHBhZ2VBcmVhUGFyZW50LnBhZ2VBcmVhLmNoaWxkcmVuLmluZGV4T2YocGFnZUFyZWEpLAogICAgICBwYWdlU2V0SW5kZXg6IDAKICAgIH07CiAgICBsZXQgdGFyZ2V0UGFnZUFyZWE7CiAgICBsZXQgbGVhZGVyID0gbnVsbDsKICAgIGxldCB0cmFpbGVyID0gbnVsbDsKICAgIGxldCBoYXNTb21ldGhpbmcgPSB0cnVlOwogICAgbGV0IGhhc1NvbWV0aGluZ0NvdW50ZXIgPSAwOwogICAgbGV0IHN0YXJ0SW5kZXggPSAwOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgaWYgKCFoYXNTb21ldGhpbmcpIHsKICAgICAgICBtYWluSHRtbC5jaGlsZHJlbi5wb3AoKTsKICAgICAgICBpZiAoKytoYXNTb21ldGhpbmdDb3VudGVyID09PSBNQVhfRU1QVFlfUEFHRVMpIHsKICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgiWEZBIC0gU29tZXRoaW5nIGdvZXMgd3Jvbmc6IHBsZWFzZSBmaWxlIGEgYnVnLiIpOwogICAgICAgICAgcmV0dXJuIG1haW5IdG1sOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBoYXNTb21ldGhpbmdDb3VudGVyID0gMDsKICAgICAgfQogICAgICB0YXJnZXRQYWdlQXJlYSA9IG51bGw7CiAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5jdXJyZW50UGFnZUFyZWEgPSBwYWdlQXJlYTsKICAgICAgY29uc3QgcGFnZSA9IHBhZ2VBcmVhW194ZmFfb2JqZWN0LiR0b0hUTUxdKCkuaHRtbDsKICAgICAgbWFpbkh0bWwuY2hpbGRyZW4ucHVzaChwYWdlKTsKICAgICAgaWYgKGxlYWRlcikgewogICAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5ub0xheW91dEZhaWx1cmUgPSB0cnVlOwogICAgICAgIHBhZ2UuY2hpbGRyZW4ucHVzaChsZWFkZXJbX3hmYV9vYmplY3QuJHRvSFRNTF0ocGFnZUFyZWFbX3hmYV9vYmplY3QuJGV4dHJhXS5zcGFjZSkuaHRtbCk7CiAgICAgICAgbGVhZGVyID0gbnVsbDsKICAgICAgfQogICAgICBpZiAodHJhaWxlcikgewogICAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5ub0xheW91dEZhaWx1cmUgPSB0cnVlOwogICAgICAgIHBhZ2UuY2hpbGRyZW4ucHVzaCh0cmFpbGVyW194ZmFfb2JqZWN0LiR0b0hUTUxdKHBhZ2VBcmVhW194ZmFfb2JqZWN0LiRleHRyYV0uc3BhY2UpLmh0bWwpOwogICAgICAgIHRyYWlsZXIgPSBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IGNvbnRlbnRBcmVhcyA9IHBhZ2VBcmVhLmNvbnRlbnRBcmVhLmNoaWxkcmVuOwogICAgICBjb25zdCBodG1sQ29udGVudEFyZWFzID0gcGFnZS5jaGlsZHJlbi5maWx0ZXIobm9kZSA9PiBub2RlLmF0dHJpYnV0ZXMuY2xhc3MuaW5jbHVkZXMoInhmYUNvbnRlbnRhcmVhIikpOwogICAgICBoYXNTb21ldGhpbmcgPSBmYWxzZTsKICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmZpcnN0VW5zcGxpdHRhYmxlID0gbnVsbDsKICAgICAgdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSA9IGZhbHNlOwogICAgICBjb25zdCBmbHVzaCA9IGluZGV4ID0+IHsKICAgICAgICBjb25zdCBodG1sID0gcm9vdFtfeGZhX29iamVjdC4kZmx1c2hIVE1MXSgpOwogICAgICAgIGlmIChodG1sKSB7CiAgICAgICAgICBoYXNTb21ldGhpbmcgPSBoYXNTb21ldGhpbmcgfHwgaHRtbC5jaGlsZHJlbiAmJiBodG1sLmNoaWxkcmVuLmxlbmd0aCAhPT0gMDsKICAgICAgICAgIGh0bWxDb250ZW50QXJlYXNbaW5kZXhdLmNoaWxkcmVuLnB1c2goaHRtbCk7CiAgICAgICAgfQogICAgICB9OwogICAgICBmb3IgKGxldCBpID0gc3RhcnRJbmRleCwgaWkgPSBjb250ZW50QXJlYXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnN0IGNvbnRlbnRBcmVhID0gdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLmN1cnJlbnRDb250ZW50QXJlYSA9IGNvbnRlbnRBcmVhc1tpXTsKICAgICAgICBjb25zdCBzcGFjZSA9IHsKICAgICAgICAgIHdpZHRoOiBjb250ZW50QXJlYS53LAogICAgICAgICAgaGVpZ2h0OiBjb250ZW50QXJlYS5oCiAgICAgICAgfTsKICAgICAgICBzdGFydEluZGV4ID0gMDsKICAgICAgICBpZiAobGVhZGVyKSB7CiAgICAgICAgICBodG1sQ29udGVudEFyZWFzW2ldLmNoaWxkcmVuLnB1c2gobGVhZGVyW194ZmFfb2JqZWN0LiR0b0hUTUxdKHNwYWNlKS5odG1sKTsKICAgICAgICAgIGxlYWRlciA9IG51bGw7CiAgICAgICAgfQogICAgICAgIGlmICh0cmFpbGVyKSB7CiAgICAgICAgICBodG1sQ29udGVudEFyZWFzW2ldLmNoaWxkcmVuLnB1c2godHJhaWxlcltfeGZhX29iamVjdC4kdG9IVE1MXShzcGFjZSkuaHRtbCk7CiAgICAgICAgICB0cmFpbGVyID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgY29uc3QgaHRtbCA9IHJvb3RbX3hmYV9vYmplY3QuJHRvSFRNTF0oc3BhY2UpOwogICAgICAgIGlmIChodG1sLnN1Y2Nlc3MpIHsKICAgICAgICAgIGlmIChodG1sLmh0bWwpIHsKICAgICAgICAgICAgaGFzU29tZXRoaW5nID0gaGFzU29tZXRoaW5nIHx8IGh0bWwuaHRtbC5jaGlsZHJlbiAmJiBodG1sLmh0bWwuY2hpbGRyZW4ubGVuZ3RoICE9PSAwOwogICAgICAgICAgICBodG1sQ29udGVudEFyZWFzW2ldLmNoaWxkcmVuLnB1c2goaHRtbC5odG1sKTsKICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1NvbWV0aGluZyAmJiBtYWluSHRtbC5jaGlsZHJlbi5sZW5ndGggPiAxKSB7CiAgICAgICAgICAgIG1haW5IdG1sLmNoaWxkcmVuLnBvcCgpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG1haW5IdG1sOwogICAgICAgIH0KICAgICAgICBpZiAoaHRtbC5pc0JyZWFrKCkpIHsKICAgICAgICAgIGNvbnN0IG5vZGUgPSBodG1sLmJyZWFrTm9kZTsKICAgICAgICAgIGZsdXNoKGkpOwogICAgICAgICAgaWYgKG5vZGUudGFyZ2V0VHlwZSA9PT0gImF1dG8iKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKG5vZGUubGVhZGVyKSB7CiAgICAgICAgICAgIGxlYWRlciA9IHRoaXNbX3hmYV9vYmplY3QuJHNlYXJjaE5vZGVdKG5vZGUubGVhZGVyLCBub2RlW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCkpOwogICAgICAgICAgICBsZWFkZXIgPSBsZWFkZXIgPyBsZWFkZXJbMF0gOiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgaWYgKG5vZGUudHJhaWxlcikgewogICAgICAgICAgICB0cmFpbGVyID0gdGhpc1tfeGZhX29iamVjdC4kc2VhcmNoTm9kZV0obm9kZS50cmFpbGVyLCBub2RlW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCkpOwogICAgICAgICAgICB0cmFpbGVyID0gdHJhaWxlciA/IHRyYWlsZXJbMF0gOiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgaWYgKG5vZGUudGFyZ2V0VHlwZSA9PT0gInBhZ2VBcmVhIikgewogICAgICAgICAgICB0YXJnZXRQYWdlQXJlYSA9IG5vZGVbX3hmYV9vYmplY3QuJGV4dHJhXS50YXJnZXQ7CiAgICAgICAgICAgIGkgPSBJbmZpbml0eTsKICAgICAgICAgIH0gZWxzZSBpZiAoIW5vZGVbX3hmYV9vYmplY3QuJGV4dHJhXS50YXJnZXQpIHsKICAgICAgICAgICAgaSA9IG5vZGVbX3hmYV9vYmplY3QuJGV4dHJhXS5pbmRleDsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRhcmdldFBhZ2VBcmVhID0gbm9kZVtfeGZhX29iamVjdC4kZXh0cmFdLnRhcmdldDsKICAgICAgICAgICAgc3RhcnRJbmRleCA9IG5vZGVbX3hmYV9vYmplY3QuJGV4dHJhXS5pbmRleCArIDE7CiAgICAgICAgICAgIGkgPSBJbmZpbml0eTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBpZiAodGhpc1tfeGZhX29iamVjdC4kZXh0cmFdLm92ZXJmbG93Tm9kZSkgewogICAgICAgICAgY29uc3Qgbm9kZSA9IHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5vdmVyZmxvd05vZGU7CiAgICAgICAgICB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0ub3ZlcmZsb3dOb2RlID0gbnVsbDsKICAgICAgICAgIGNvbnN0IG92ZXJmbG93RXh0cmEgPSBub2RlW194ZmFfb2JqZWN0LiRnZXRFeHRyYV0oKTsKICAgICAgICAgIGNvbnN0IHRhcmdldCA9IG92ZXJmbG93RXh0cmEudGFyZ2V0OwogICAgICAgICAgb3ZlcmZsb3dFeHRyYS5hZGRMZWFkZXIgPSBvdmVyZmxvd0V4dHJhLmxlYWRlciAhPT0gbnVsbDsKICAgICAgICAgIG92ZXJmbG93RXh0cmEuYWRkVHJhaWxlciA9IG92ZXJmbG93RXh0cmEudHJhaWxlciAhPT0gbnVsbDsKICAgICAgICAgIGZsdXNoKGkpOwogICAgICAgICAgY29uc3QgY3VycmVudEluZGV4ID0gaTsKICAgICAgICAgIGkgPSBJbmZpbml0eTsKICAgICAgICAgIGlmICh0YXJnZXQgaW5zdGFuY2VvZiBQYWdlQXJlYSkgewogICAgICAgICAgICB0YXJnZXRQYWdlQXJlYSA9IHRhcmdldDsKICAgICAgICAgIH0gZWxzZSBpZiAodGFyZ2V0IGluc3RhbmNlb2YgQ29udGVudEFyZWEpIHsKICAgICAgICAgICAgY29uc3QgaW5kZXggPSBjb250ZW50QXJlYXMuaW5kZXhPZih0YXJnZXQpOwogICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7CiAgICAgICAgICAgICAgaWYgKGluZGV4ID4gY3VycmVudEluZGV4KSB7CiAgICAgICAgICAgICAgICBpID0gaW5kZXggLSAxOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBzdGFydEluZGV4ID0gaW5kZXg7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRhcmdldFBhZ2VBcmVhID0gdGFyZ2V0W194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICAgICAgICAgICAgc3RhcnRJbmRleCA9IHRhcmdldFBhZ2VBcmVhLmNvbnRlbnRBcmVhLmNoaWxkcmVuLmluZGV4T2YodGFyZ2V0KTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGZsdXNoKGkpOwogICAgICB9CiAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXS5wYWdlTnVtYmVyICs9IDE7CiAgICAgIGlmICh0YXJnZXRQYWdlQXJlYSkgewogICAgICAgIGlmICh0YXJnZXRQYWdlQXJlYVtfeGZhX29iamVjdC4kaXNVc2FibGVdKCkpIHsKICAgICAgICAgIHRhcmdldFBhZ2VBcmVhW194ZmFfb2JqZWN0LiRleHRyYV0ubnVtYmVyT2ZVc2UgKz0gMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGFyZ2V0UGFnZUFyZWEgPSBudWxsOwogICAgICAgIH0KICAgICAgfQogICAgICBwYWdlQXJlYSA9IHRhcmdldFBhZ2VBcmVhIHx8IHBhZ2VBcmVhW194ZmFfb2JqZWN0LiRnZXROZXh0UGFnZV0oKTsKICAgICAgeWllbGQgbnVsbDsKICAgIH0KICB9Cn0KZXhwb3J0cy5UZW1wbGF0ZSA9IFRlbXBsYXRlOwpjbGFzcyBUZXh0IGV4dGVuZHMgX3hmYV9vYmplY3QuQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0ZXh0Iik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubWF4Q2hhcnMgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5tYXhDaGFycywKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5yaWQgPSBhdHRyaWJ1dGVzLnJpZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFtfeGZhX29iamVjdC4kYWNjZXB0V2hpdGVzcGFjZV0oKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgW194ZmFfb2JqZWN0LiRvbkNoaWxkXShjaGlsZCkgewogICAgaWYgKGNoaWxkW194ZmFfb2JqZWN0LiRuYW1lc3BhY2VJZF0gPT09IF9uYW1lc3BhY2VzLk5hbWVzcGFjZUlkcy54aHRtbC5pZCkgewogICAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA9IGNoaWxkOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gSW52YWxpZCBjb250ZW50IGluIFRleHQ6ICR7Y2hpbGRbX3hmYV9vYmplY3QuJG5vZGVOYW1lXX0uYCk7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFtfeGZhX29iamVjdC4kb25UZXh0XShzdHIpIHsKICAgIGlmICh0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSBpbnN0YW5jZW9mIF94ZmFfb2JqZWN0LlhGQU9iamVjdCkgewogICAgICByZXR1cm47CiAgICB9CiAgICBzdXBlcltfeGZhX29iamVjdC4kb25UZXh0XShzdHIpOwogIH0KICBbX3hmYV9vYmplY3QuJGZpbmFsaXplXSgpIHsKICAgIGlmICh0eXBlb2YgdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0gPT09ICJzdHJpbmciKSB7CiAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdID0gdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0ucmVwbGFjZUFsbCgiXHJcbiIsICJcbiIpOwogICAgfQogIH0KICBbX3hmYV9vYmplY3QuJGdldEV4dHJhXSgpIHsKICAgIGlmICh0eXBlb2YgdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0gPT09ICJzdHJpbmciKSB7CiAgICAgIHJldHVybiB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XS5zcGxpdCgvW1x1MjAyOVx1MjAyOFxuXS8pLnJlZHVjZSgoYWNjLCBsaW5lKSA9PiB7CiAgICAgICAgaWYgKGxpbmUpIHsKICAgICAgICAgIGFjYy5wdXNoKGxpbmUpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYWNjOwogICAgICB9LCBbXSkuam9pbigiXG4iKTsKICAgIH0KICAgIHJldHVybiB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XVtfeGZhX29iamVjdC4kdGV4dF0oKTsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBpZiAodHlwZW9mIHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdID09PSAic3RyaW5nIikgewogICAgICBjb25zdCBodG1sID0gdmFsdWVUb0h0bWwodGhpc1tfeGZhX29iamVjdC4kY29udGVudF0pLmh0bWw7CiAgICAgIGlmICh0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XS5pbmNsdWRlcygiXHUyMDI5IikpIHsKICAgICAgICBodG1sLm5hbWUgPSAiZGl2IjsKICAgICAgICBodG1sLmNoaWxkcmVuID0gW107CiAgICAgICAgdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0uc3BsaXQoIlx1MjAyOSIpLm1hcChwYXJhID0+IHBhcmEuc3BsaXQoL1tcdTIwMjhcbl0vKS5yZWR1Y2UoKGFjYywgbGluZSkgPT4gewogICAgICAgICAgYWNjLnB1c2goewogICAgICAgICAgICBuYW1lOiAic3BhbiIsCiAgICAgICAgICAgIHZhbHVlOiBsaW5lCiAgICAgICAgICB9LCB7CiAgICAgICAgICAgIG5hbWU6ICJiciIKICAgICAgICAgIH0pOwogICAgICAgICAgcmV0dXJuIGFjYzsKICAgICAgICB9LCBbXSkpLmZvckVhY2gobGluZXMgPT4gewogICAgICAgICAgaHRtbC5jaGlsZHJlbi5wdXNoKHsKICAgICAgICAgICAgbmFtZTogInAiLAogICAgICAgICAgICBjaGlsZHJlbjogbGluZXMKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgaWYgKC9bXHUyMDI4XG5dLy50ZXN0KHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdKSkgewogICAgICAgIGh0bWwubmFtZSA9ICJkaXYiOwogICAgICAgIGh0bWwuY2hpbGRyZW4gPSBbXTsKICAgICAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XS5zcGxpdCgvW1x1MjAyOFxuXS8pLmZvckVhY2gobGluZSA9PiB7CiAgICAgICAgICBodG1sLmNoaWxkcmVuLnB1c2goewogICAgICAgICAgICBuYW1lOiAic3BhbiIsCiAgICAgICAgICAgIHZhbHVlOiBsaW5lCiAgICAgICAgICB9LCB7CiAgICAgICAgICAgIG5hbWU6ICJiciIKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICB9CiAgICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5zdWNjZXNzKGh0bWwpOwogICAgfQogICAgcmV0dXJuIHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKTsKICB9Cn0KZXhwb3J0cy5UZXh0ID0gVGV4dDsKY2xhc3MgVGV4dEVkaXQgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAidGV4dEVkaXQiLCB0cnVlKTsKICAgIHRoaXMuYWxsb3dSaWNoVGV4dCA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmFsbG93UmljaFRleHQsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmhTY3JvbGxQb2xpY3kgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5oU2Nyb2xsUG9saWN5LCBbImF1dG8iLCAib2ZmIiwgIm9uIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm11bHRpTGluZSA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLm11bHRpTGluZSwKICAgICAgZGVmYXVsdFZhbHVlOiAiIiwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMCB8fCB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnZTY3JvbGxQb2xpY3kgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy52U2Nyb2xsUG9saWN5LCBbImF1dG8iLCAib2ZmIiwgIm9uIl0pOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5jb21iID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMubWFyZ2luID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCBzdHlsZSA9ICgwLCBfaHRtbF91dGlscy50b1N0eWxlKSh0aGlzLCAiYm9yZGVyIiwgImZvbnQiLCAibWFyZ2luIik7CiAgICBsZXQgaHRtbDsKICAgIGNvbnN0IGZpZWxkID0gdGhpc1tfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICBpZiAodGhpcy5tdWx0aUxpbmUgPT09ICIiKSB7CiAgICAgIHRoaXMubXVsdGlMaW5lID0gZmllbGQgaW5zdGFuY2VvZiBEcmF3ID8gMSA6IDA7CiAgICB9CiAgICBpZiAodGhpcy5tdWx0aUxpbmUgPT09IDEpIHsKICAgICAgaHRtbCA9IHsKICAgICAgICBuYW1lOiAidGV4dGFyZWEiLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIGRhdGFJZDogZmllbGRbX3hmYV9vYmplY3QuJGRhdGFdICYmIGZpZWxkW194ZmFfb2JqZWN0LiRkYXRhXVtfeGZhX29iamVjdC4kdWlkXSB8fCBmaWVsZFtfeGZhX29iamVjdC4kdWlkXSwKICAgICAgICAgIGZpZWxkSWQ6IGZpZWxkW194ZmFfb2JqZWN0LiR1aWRdLAogICAgICAgICAgY2xhc3M6IFsieGZhVGV4dGZpZWxkIl0sCiAgICAgICAgICBzdHlsZSwKICAgICAgICAgICJhcmlhLWxhYmVsIjogYXJpYUxhYmVsKGZpZWxkKSwKICAgICAgICAgICJhcmlhLXJlcXVpcmVkIjogZmFsc2UKICAgICAgICB9CiAgICAgIH07CiAgICB9IGVsc2UgewogICAgICBodG1sID0gewogICAgICAgIG5hbWU6ICJpbnB1dCIsCiAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgdHlwZTogInRleHQiLAogICAgICAgICAgZGF0YUlkOiBmaWVsZFtfeGZhX29iamVjdC4kZGF0YV0gJiYgZmllbGRbX3hmYV9vYmplY3QuJGRhdGFdW194ZmFfb2JqZWN0LiR1aWRdIHx8IGZpZWxkW194ZmFfb2JqZWN0LiR1aWRdLAogICAgICAgICAgZmllbGRJZDogZmllbGRbX3hmYV9vYmplY3QuJHVpZF0sCiAgICAgICAgICBjbGFzczogWyJ4ZmFUZXh0ZmllbGQiXSwKICAgICAgICAgIHN0eWxlLAogICAgICAgICAgImFyaWEtbGFiZWwiOiBhcmlhTGFiZWwoZmllbGQpLAogICAgICAgICAgImFyaWEtcmVxdWlyZWQiOiBmYWxzZQogICAgICAgIH0KICAgICAgfTsKICAgIH0KICAgIGlmIChpc1JlcXVpcmVkKGZpZWxkKSkgewogICAgICBodG1sLmF0dHJpYnV0ZXNbImFyaWEtcmVxdWlyZWQiXSA9IHRydWU7CiAgICAgIGh0bWwuYXR0cmlidXRlcy5yZXF1aXJlZCA9IHRydWU7CiAgICB9CiAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgIG5hbWU6ICJsYWJlbCIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBjbGFzczogWyJ4ZmFMYWJlbCJdCiAgICAgIH0sCiAgICAgIGNoaWxkcmVuOiBbaHRtbF0KICAgIH0pOwogIH0KfQpjbGFzcyBUaW1lIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInRpbWUiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgW194ZmFfb2JqZWN0LiRmaW5hbGl6ZV0oKSB7CiAgICBjb25zdCBkYXRlID0gdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0udHJpbSgpOwogICAgdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0gPSBkYXRlID8gbmV3IERhdGUoZGF0ZSkgOiBudWxsOwogIH0KICBbX3hmYV9vYmplY3QuJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIHJldHVybiB2YWx1ZVRvSHRtbCh0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA/IHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdLnRvU3RyaW5nKCkgOiAiIik7CiAgfQp9CmNsYXNzIFRpbWVTdGFtcCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0aW1lU3RhbXAiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5zZXJ2ZXIgPSBhdHRyaWJ1dGVzLnNlcnZlciB8fCAiIjsKICAgIHRoaXMudHlwZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnR5cGUsIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBUb29sVGlwIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInRvb2xUaXAiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5yaWQgPSBhdHRyaWJ1dGVzLnJpZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIFRyYXZlcnNhbCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0cmF2ZXJzYWwiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMudHJhdmVyc2UgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgVHJhdmVyc2UgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAidHJhdmVyc2UiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5vcGVyYXRpb24gPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5vcGVyYXRpb24sIFsibmV4dCIsICJiYWNrIiwgImRvd24iLCAiZmlyc3QiLCAibGVmdCIsICJyaWdodCIsICJ1cCJdKTsKICAgIHRoaXMucmVmID0gYXR0cmlidXRlcy5yZWYgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5zY3JpcHQgPSBudWxsOwogIH0KICBnZXQgbmFtZSgpIHsKICAgIHJldHVybiB0aGlzLm9wZXJhdGlvbjsKICB9CiAgW194ZmFfb2JqZWN0LiRpc1RyYW5zcGFyZW50XSgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9Cn0KY2xhc3MgVWkgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAidWkiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMucGljdHVyZSA9IG51bGw7CiAgICB0aGlzLmJhcmNvZGUgPSBudWxsOwogICAgdGhpcy5idXR0b24gPSBudWxsOwogICAgdGhpcy5jaGVja0J1dHRvbiA9IG51bGw7CiAgICB0aGlzLmNob2ljZUxpc3QgPSBudWxsOwogICAgdGhpcy5kYXRlVGltZUVkaXQgPSBudWxsOwogICAgdGhpcy5kZWZhdWx0VWkgPSBudWxsOwogICAgdGhpcy5pbWFnZUVkaXQgPSBudWxsOwogICAgdGhpcy5udW1lcmljRWRpdCA9IG51bGw7CiAgICB0aGlzLnBhc3N3b3JkRWRpdCA9IG51bGw7CiAgICB0aGlzLnNpZ25hdHVyZSA9IG51bGw7CiAgICB0aGlzLnRleHRFZGl0ID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiRnZXRFeHRyYV0oKSB7CiAgICBpZiAodGhpc1tfeGZhX29iamVjdC4kZXh0cmFdID09PSB1bmRlZmluZWQpIHsKICAgICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKSB7CiAgICAgICAgaWYgKG5hbWUgPT09ICJleHRyYXMiIHx8IG5hbWUgPT09ICJwaWN0dXJlIikgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG9iaiA9IHRoaXNbbmFtZV07CiAgICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgX3hmYV9vYmplY3QuWEZBT2JqZWN0KSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXSA9IG9iajsKICAgICAgICByZXR1cm4gb2JqOwogICAgICB9CiAgICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXSA9IG51bGw7CiAgICB9CiAgICByZXR1cm4gdGhpc1tfeGZhX29iamVjdC4kZXh0cmFdOwogIH0KICBbX3hmYV9vYmplY3QuJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXNbX3hmYV9vYmplY3QuJGdldEV4dHJhXSgpOwogICAgaWYgKG9iaikgewogICAgICByZXR1cm4gb2JqW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKTsKICAgIH0KICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5FTVBUWTsKICB9Cn0KY2xhc3MgVmFsaWRhdGUgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAidmFsaWRhdGUiLCB0cnVlKTsKICAgIHRoaXMuZm9ybWF0VGVzdCA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLmZvcm1hdFRlc3QsIFsid2FybmluZyIsICJkaXNhYmxlZCIsICJlcnJvciJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5udWxsVGVzdCA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLm51bGxUZXN0LCBbImRpc2FibGVkIiwgImVycm9yIiwgIndhcm5pbmciXSk7CiAgICB0aGlzLnNjcmlwdFRlc3QgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5zY3JpcHRUZXN0LCBbImVycm9yIiwgImRpc2FibGVkIiwgIndhcm5pbmciXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tZXNzYWdlID0gbnVsbDsKICAgIHRoaXMucGljdHVyZSA9IG51bGw7CiAgICB0aGlzLnNjcmlwdCA9IG51bGw7CiAgfQp9CmNsYXNzIFZhbHVlIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInZhbHVlIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMub3ZlcnJpZGUgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5vdmVycmlkZSwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMucmVsZXZhbnQgPSAoMCwgX3V0aWxzLmdldFJlbGV2YW50KShhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmFyYyA9IG51bGw7CiAgICB0aGlzLmJvb2xlYW4gPSBudWxsOwogICAgdGhpcy5kYXRlID0gbnVsbDsKICAgIHRoaXMuZGF0ZVRpbWUgPSBudWxsOwogICAgdGhpcy5kZWNpbWFsID0gbnVsbDsKICAgIHRoaXMuZXhEYXRhID0gbnVsbDsKICAgIHRoaXMuZmxvYXQgPSBudWxsOwogICAgdGhpcy5pbWFnZSA9IG51bGw7CiAgICB0aGlzLmludGVnZXIgPSBudWxsOwogICAgdGhpcy5saW5lID0gbnVsbDsKICAgIHRoaXMucmVjdGFuZ2xlID0gbnVsbDsKICAgIHRoaXMudGV4dCA9IG51bGw7CiAgICB0aGlzLnRpbWUgPSBudWxsOwogIH0KICBbX3hmYV9vYmplY3QuJHNldFZhbHVlXSh2YWx1ZSkgewogICAgY29uc3QgcGFyZW50ID0gdGhpc1tfeGZhX29iamVjdC4kZ2V0UGFyZW50XSgpOwogICAgaWYgKHBhcmVudCBpbnN0YW5jZW9mIEZpZWxkKSB7CiAgICAgIGlmIChwYXJlbnQudWkgJiYgcGFyZW50LnVpLmltYWdlRWRpdCkgewogICAgICAgIGlmICghdGhpcy5pbWFnZSkgewogICAgICAgICAgdGhpcy5pbWFnZSA9IG5ldyBJbWFnZSh7fSk7CiAgICAgICAgICB0aGlzW194ZmFfb2JqZWN0LiRhcHBlbmRDaGlsZF0odGhpcy5pbWFnZSk7CiAgICAgICAgfQogICAgICAgIHRoaXMuaW1hZ2VbX3hmYV9vYmplY3QuJGNvbnRlbnRdID0gdmFsdWVbX3hmYV9vYmplY3QuJGNvbnRlbnRdOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgfQogICAgY29uc3QgdmFsdWVOYW1lID0gdmFsdWVbX3hmYV9vYmplY3QuJG5vZGVOYW1lXTsKICAgIGlmICh0aGlzW3ZhbHVlTmFtZV0gIT09IG51bGwpIHsKICAgICAgdGhpc1t2YWx1ZU5hbWVdW194ZmFfb2JqZWN0LiRjb250ZW50XSA9IHZhbHVlW194ZmFfb2JqZWN0LiRjb250ZW50XTsKICAgICAgcmV0dXJuOwogICAgfQogICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKSB7CiAgICAgIGNvbnN0IG9iaiA9IHRoaXNbbmFtZV07CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBfeGZhX29iamVjdC5YRkFPYmplY3QpIHsKICAgICAgICB0aGlzW25hbWVdID0gbnVsbDsKICAgICAgICB0aGlzW194ZmFfb2JqZWN0LiRyZW1vdmVDaGlsZF0ob2JqKTsKICAgICAgfQogICAgfQogICAgdGhpc1t2YWx1ZVtfeGZhX29iamVjdC4kbm9kZU5hbWVdXSA9IHZhbHVlOwogICAgdGhpc1tfeGZhX29iamVjdC4kYXBwZW5kQ2hpbGRdKHZhbHVlKTsKICB9CiAgW194ZmFfb2JqZWN0LiR0ZXh0XSgpIHsKICAgIGlmICh0aGlzLmV4RGF0YSkgewogICAgICBpZiAodHlwZW9mIHRoaXMuZXhEYXRhW194ZmFfb2JqZWN0LiRjb250ZW50XSA9PT0gInN0cmluZyIpIHsKICAgICAgICByZXR1cm4gdGhpcy5leERhdGFbX3hmYV9vYmplY3QuJGNvbnRlbnRdLnRyaW0oKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5leERhdGFbX3hmYV9vYmplY3QuJGNvbnRlbnRdW194ZmFfb2JqZWN0LiR0ZXh0XSgpLnRyaW0oKTsKICAgIH0KICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSkgewogICAgICBpZiAobmFtZSA9PT0gImltYWdlIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IG9iaiA9IHRoaXNbbmFtZV07CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBfeGZhX29iamVjdC5YRkFPYmplY3QpIHsKICAgICAgICByZXR1cm4gKG9ialtfeGZhX29iamVjdC4kY29udGVudF0gfHwgIiIpLnRvU3RyaW5nKCkudHJpbSgpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcykpIHsKICAgICAgY29uc3Qgb2JqID0gdGhpc1tuYW1lXTsKICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgX3hmYV9vYmplY3QuWEZBT2JqZWN0KSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHJldHVybiBvYmpbX3hmYV9vYmplY3QuJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpOwogICAgfQogICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LkVNUFRZOwogIH0KfQpleHBvcnRzLlZhbHVlID0gVmFsdWU7CmNsYXNzIFZhcmlhYmxlcyBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ2YXJpYWJsZXMiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuYm9vbGVhbiA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGVUaW1lID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRlY2ltYWwgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXhEYXRhID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmZsb2F0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmltYWdlID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmludGVnZXIgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubWFuaWZlc3QgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2NyaXB0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRleHQgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGltZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KICBbX3hmYV9vYmplY3QuJGlzVHJhbnNwYXJlbnRdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQp9CmNsYXNzIFRlbXBsYXRlTmFtZXNwYWNlIHsKICBzdGF0aWMgW19uYW1lc3BhY2VzLiRidWlsZFhGQU9iamVjdF0obmFtZSwgYXR0cmlidXRlcykgewogICAgaWYgKFRlbXBsYXRlTmFtZXNwYWNlLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgIGNvbnN0IG5vZGUgPSBUZW1wbGF0ZU5hbWVzcGFjZVtuYW1lXShhdHRyaWJ1dGVzKTsKICAgICAgbm9kZVtfeGZhX29iamVjdC4kc2V0U2V0QXR0cmlidXRlc10oYXR0cmlidXRlcyk7CiAgICAgIHJldHVybiBub2RlOwogICAgfQogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9CiAgc3RhdGljIGFwcGVhcmFuY2VGaWx0ZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQXBwZWFyYW5jZUZpbHRlcihhdHRycyk7CiAgfQogIHN0YXRpYyBhcmMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQXJjKGF0dHJzKTsKICB9CiAgc3RhdGljIGFyZWEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQXJlYShhdHRycyk7CiAgfQogIHN0YXRpYyBhc3Npc3QoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQXNzaXN0KGF0dHJzKTsKICB9CiAgc3RhdGljIGJhcmNvZGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQmFyY29kZShhdHRycyk7CiAgfQogIHN0YXRpYyBiaW5kKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJpbmQoYXR0cnMpOwogIH0KICBzdGF0aWMgYmluZEl0ZW1zKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJpbmRJdGVtcyhhdHRycyk7CiAgfQogIHN0YXRpYyBib29rZW5kKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJvb2tlbmQoYXR0cnMpOwogIH0KICBzdGF0aWMgYm9vbGVhbihhdHRycykgewogICAgcmV0dXJuIG5ldyBCb29sZWFuRWxlbWVudChhdHRycyk7CiAgfQogIHN0YXRpYyBib3JkZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQm9yZGVyKGF0dHJzKTsKICB9CiAgc3RhdGljIGJyZWFrKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJyZWFrKGF0dHJzKTsKICB9CiAgc3RhdGljIGJyZWFrQWZ0ZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQnJlYWtBZnRlcihhdHRycyk7CiAgfQogIHN0YXRpYyBicmVha0JlZm9yZShhdHRycykgewogICAgcmV0dXJuIG5ldyBCcmVha0JlZm9yZShhdHRycyk7CiAgfQogIHN0YXRpYyBidXR0b24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQnV0dG9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGNhbGN1bGF0ZShhdHRycykgewogICAgcmV0dXJuIG5ldyBDYWxjdWxhdGUoYXR0cnMpOwogIH0KICBzdGF0aWMgY2FwdGlvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBDYXB0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGNlcnRpZmljYXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENlcnRpZmljYXRlKGF0dHJzKTsKICB9CiAgc3RhdGljIGNlcnRpZmljYXRlcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBDZXJ0aWZpY2F0ZXMoYXR0cnMpOwogIH0KICBzdGF0aWMgY2hlY2tCdXR0b24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ2hlY2tCdXR0b24oYXR0cnMpOwogIH0KICBzdGF0aWMgY2hvaWNlTGlzdChhdHRycykgewogICAgcmV0dXJuIG5ldyBDaG9pY2VMaXN0KGF0dHJzKTsKICB9CiAgc3RhdGljIGNvbG9yKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbG9yKGF0dHJzKTsKICB9CiAgc3RhdGljIGNvbWIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29tYihhdHRycyk7CiAgfQogIHN0YXRpYyBjb25uZWN0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbm5lY3QoYXR0cnMpOwogIH0KICBzdGF0aWMgY29udGVudEFyZWEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29udGVudEFyZWEoYXR0cnMpOwogIH0KICBzdGF0aWMgY29ybmVyKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvcm5lcihhdHRycyk7CiAgfQogIHN0YXRpYyBkYXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGVFbGVtZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIGRhdGVUaW1lKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGVUaW1lKGF0dHJzKTsKICB9CiAgc3RhdGljIGRhdGVUaW1lRWRpdChhdHRycykgewogICAgcmV0dXJuIG5ldyBEYXRlVGltZUVkaXQoYXR0cnMpOwogIH0KICBzdGF0aWMgZGVjaW1hbChhdHRycykgewogICAgcmV0dXJuIG5ldyBEZWNpbWFsKGF0dHJzKTsKICB9CiAgc3RhdGljIGRlZmF1bHRVaShhdHRycykgewogICAgcmV0dXJuIG5ldyBEZWZhdWx0VWkoYXR0cnMpOwogIH0KICBzdGF0aWMgZGVzYyhhdHRycykgewogICAgcmV0dXJuIG5ldyBEZXNjKGF0dHJzKTsKICB9CiAgc3RhdGljIGRpZ2VzdE1ldGhvZChhdHRycykgewogICAgcmV0dXJuIG5ldyBEaWdlc3RNZXRob2QoYXR0cnMpOwogIH0KICBzdGF0aWMgZGlnZXN0TWV0aG9kcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBEaWdlc3RNZXRob2RzKGF0dHJzKTsKICB9CiAgc3RhdGljIGRyYXcoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRHJhdyhhdHRycyk7CiAgfQogIHN0YXRpYyBlZGdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVkZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jb2RpbmcoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRW5jb2RpbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jb2RpbmdzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVuY29kaW5ncyhhdHRycyk7CiAgfQogIHN0YXRpYyBlbmNyeXB0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVuY3J5cHQoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jcnlwdERhdGEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRW5jcnlwdERhdGEoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jcnlwdGlvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBFbmNyeXB0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGVuY3J5cHRpb25NZXRob2QoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRW5jcnlwdGlvbk1ldGhvZChhdHRycyk7CiAgfQogIHN0YXRpYyBlbmNyeXB0aW9uTWV0aG9kcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBFbmNyeXB0aW9uTWV0aG9kcyhhdHRycyk7CiAgfQogIHN0YXRpYyBldmVudChhdHRycykgewogICAgcmV0dXJuIG5ldyBFdmVudChhdHRycyk7CiAgfQogIHN0YXRpYyBleERhdGEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRXhEYXRhKGF0dHJzKTsKICB9CiAgc3RhdGljIGV4T2JqZWN0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEV4T2JqZWN0KGF0dHJzKTsKICB9CiAgc3RhdGljIGV4Y2xHcm91cChhdHRycykgewogICAgcmV0dXJuIG5ldyBFeGNsR3JvdXAoYXR0cnMpOwogIH0KICBzdGF0aWMgZXhlY3V0ZShhdHRycykgewogICAgcmV0dXJuIG5ldyBFeGVjdXRlKGF0dHJzKTsKICB9CiAgc3RhdGljIGV4dHJhcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBFeHRyYXMoYXR0cnMpOwogIH0KICBzdGF0aWMgZmllbGQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRmllbGQoYXR0cnMpOwogIH0KICBzdGF0aWMgZmlsbChhdHRycykgewogICAgcmV0dXJuIG5ldyBGaWxsKGF0dHJzKTsKICB9CiAgc3RhdGljIGZpbHRlcihhdHRycykgewogICAgcmV0dXJuIG5ldyBGaWx0ZXIoYXR0cnMpOwogIH0KICBzdGF0aWMgZmxvYXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRmxvYXQoYXR0cnMpOwogIH0KICBzdGF0aWMgZm9udChhdHRycykgewogICAgcmV0dXJuIG5ldyBGb250KGF0dHJzKTsKICB9CiAgc3RhdGljIGZvcm1hdChhdHRycykgewogICAgcmV0dXJuIG5ldyBGb3JtYXQoYXR0cnMpOwogIH0KICBzdGF0aWMgaGFuZGxlcihhdHRycykgewogICAgcmV0dXJuIG5ldyBIYW5kbGVyKGF0dHJzKTsKICB9CiAgc3RhdGljIGh5cGhlbmF0aW9uKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEh5cGhlbmF0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGltYWdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEltYWdlKGF0dHJzKTsKICB9CiAgc3RhdGljIGltYWdlRWRpdChhdHRycykgewogICAgcmV0dXJuIG5ldyBJbWFnZUVkaXQoYXR0cnMpOwogIH0KICBzdGF0aWMgaW50ZWdlcihhdHRycykgewogICAgcmV0dXJuIG5ldyBJbnRlZ2VyKGF0dHJzKTsKICB9CiAgc3RhdGljIGlzc3VlcnMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgSXNzdWVycyhhdHRycyk7CiAgfQogIHN0YXRpYyBpdGVtcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBJdGVtcyhhdHRycyk7CiAgfQogIHN0YXRpYyBrZWVwKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEtlZXAoYXR0cnMpOwogIH0KICBzdGF0aWMga2V5VXNhZ2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgS2V5VXNhZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgbGluZShhdHRycykgewogICAgcmV0dXJuIG5ldyBMaW5lKGF0dHJzKTsKICB9CiAgc3RhdGljIGxpbmVhcihhdHRycykgewogICAgcmV0dXJuIG5ldyBMaW5lYXIoYXR0cnMpOwogIH0KICBzdGF0aWMgbG9ja0RvY3VtZW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IExvY2tEb2N1bWVudChhdHRycyk7CiAgfQogIHN0YXRpYyBtYW5pZmVzdChhdHRycykgewogICAgcmV0dXJuIG5ldyBNYW5pZmVzdChhdHRycyk7CiAgfQogIHN0YXRpYyBtYXJnaW4oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTWFyZ2luKGF0dHJzKTsKICB9CiAgc3RhdGljIG1kcChhdHRycykgewogICAgcmV0dXJuIG5ldyBNZHAoYXR0cnMpOwogIH0KICBzdGF0aWMgbWVkaXVtKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1lZGl1bShhdHRycyk7CiAgfQogIHN0YXRpYyBtZXNzYWdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1lc3NhZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgbnVtZXJpY0VkaXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTnVtZXJpY0VkaXQoYXR0cnMpOwogIH0KICBzdGF0aWMgb2NjdXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT2NjdXIoYXR0cnMpOwogIH0KICBzdGF0aWMgb2lkKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE9pZChhdHRycyk7CiAgfQogIHN0YXRpYyBvaWRzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE9pZHMoYXR0cnMpOwogIH0KICBzdGF0aWMgb3ZlcmZsb3coYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT3ZlcmZsb3coYXR0cnMpOwogIH0KICBzdGF0aWMgcGFnZUFyZWEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGFnZUFyZWEoYXR0cnMpOwogIH0KICBzdGF0aWMgcGFnZVNldChhdHRycykgewogICAgcmV0dXJuIG5ldyBQYWdlU2V0KGF0dHJzKTsKICB9CiAgc3RhdGljIHBhcmEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGFyYShhdHRycyk7CiAgfQogIHN0YXRpYyBwYXNzd29yZEVkaXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGFzc3dvcmRFZGl0KGF0dHJzKTsKICB9CiAgc3RhdGljIHBhdHRlcm4oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGF0dGVybihhdHRycyk7CiAgfQogIHN0YXRpYyBwaWN0dXJlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBpY3R1cmUoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJvdG8oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHJvdG8oYXR0cnMpOwogIH0KICBzdGF0aWMgcmFkaWFsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFJhZGlhbChhdHRycyk7CiAgfQogIHN0YXRpYyByZWFzb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVhc29uKGF0dHJzKTsKICB9CiAgc3RhdGljIHJlYXNvbnMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVhc29ucyhhdHRycyk7CiAgfQogIHN0YXRpYyByZWN0YW5nbGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVjdGFuZ2xlKGF0dHJzKTsKICB9CiAgc3RhdGljIHJlZihhdHRycykgewogICAgcmV0dXJuIG5ldyBSZWZFbGVtZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHNjcmlwdChhdHRycykgewogICAgcmV0dXJuIG5ldyBTY3JpcHQoYXR0cnMpOwogIH0KICBzdGF0aWMgc2V0UHJvcGVydHkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU2V0UHJvcGVydHkoYXR0cnMpOwogIH0KICBzdGF0aWMgc2lnbkRhdGEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU2lnbkRhdGEoYXR0cnMpOwogIH0KICBzdGF0aWMgc2lnbmF0dXJlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNpZ25hdHVyZShhdHRycyk7CiAgfQogIHN0YXRpYyBzaWduaW5nKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNpZ25pbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgc29saWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU29saWQoYXR0cnMpOwogIH0KICBzdGF0aWMgc3BlYWsoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU3BlYWsoYXR0cnMpOwogIH0KICBzdGF0aWMgc3RpcHBsZShhdHRycykgewogICAgcmV0dXJuIG5ldyBTdGlwcGxlKGF0dHJzKTsKICB9CiAgc3RhdGljIHN1YmZvcm0oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU3ViZm9ybShhdHRycyk7CiAgfQogIHN0YXRpYyBzdWJmb3JtU2V0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1YmZvcm1TZXQoYXR0cnMpOwogIH0KICBzdGF0aWMgc3ViamVjdEROKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1YmplY3RETihhdHRycyk7CiAgfQogIHN0YXRpYyBzdWJqZWN0RE5zKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1YmplY3RETnMoYXR0cnMpOwogIH0KICBzdGF0aWMgc3VibWl0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1Ym1pdChhdHRycyk7CiAgfQogIHN0YXRpYyB0ZW1wbGF0ZShhdHRycykgewogICAgcmV0dXJuIG5ldyBUZW1wbGF0ZShhdHRycyk7CiAgfQogIHN0YXRpYyB0ZXh0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFRleHQoYXR0cnMpOwogIH0KICBzdGF0aWMgdGV4dEVkaXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVGV4dEVkaXQoYXR0cnMpOwogIH0KICBzdGF0aWMgdGltZShhdHRycykgewogICAgcmV0dXJuIG5ldyBUaW1lKGF0dHJzKTsKICB9CiAgc3RhdGljIHRpbWVTdGFtcChhdHRycykgewogICAgcmV0dXJuIG5ldyBUaW1lU3RhbXAoYXR0cnMpOwogIH0KICBzdGF0aWMgdG9vbFRpcChhdHRycykgewogICAgcmV0dXJuIG5ldyBUb29sVGlwKGF0dHJzKTsKICB9CiAgc3RhdGljIHRyYXZlcnNhbChhdHRycykgewogICAgcmV0dXJuIG5ldyBUcmF2ZXJzYWwoYXR0cnMpOwogIH0KICBzdGF0aWMgdHJhdmVyc2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVHJhdmVyc2UoYXR0cnMpOwogIH0KICBzdGF0aWMgdWkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVWkoYXR0cnMpOwogIH0KICBzdGF0aWMgdmFsaWRhdGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVmFsaWRhdGUoYXR0cnMpOwogIH0KICBzdGF0aWMgdmFsdWUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVmFsdWUoYXR0cnMpOwogIH0KICBzdGF0aWMgdmFyaWFibGVzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFZhcmlhYmxlcyhhdHRycyk7CiAgfQp9CmV4cG9ydHMuVGVtcGxhdGVOYW1lc3BhY2UgPSBUZW1wbGF0ZU5hbWVzcGFjZTsKCi8qKiovIH0pLAovKiAyMTggKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLmFkZEhUTUwgPSBhZGRIVE1MOwpleHBvcnRzLmNoZWNrRGltZW5zaW9ucyA9IGNoZWNrRGltZW5zaW9uczsKZXhwb3J0cy5mbHVzaEhUTUwgPSBmbHVzaEhUTUw7CmV4cG9ydHMuZ2V0QXZhaWxhYmxlU3BhY2UgPSBnZXRBdmFpbGFibGVTcGFjZTsKdmFyIF94ZmFfb2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTIpOwp2YXIgX2h0bWxfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxOSk7CmZ1bmN0aW9uIGNyZWF0ZUxpbmUobm9kZSwgY2hpbGRyZW4pIHsKICByZXR1cm4gewogICAgbmFtZTogImRpdiIsCiAgICBhdHRyaWJ1dGVzOiB7CiAgICAgIGNsYXNzOiBbbm9kZS5sYXlvdXQgPT09ICJsci10YiIgPyAieGZhTHIiIDogInhmYVJsIl0KICAgIH0sCiAgICBjaGlsZHJlbgogIH07Cn0KZnVuY3Rpb24gZmx1c2hIVE1MKG5vZGUpIHsKICBpZiAoIW5vZGVbX3hmYV9vYmplY3QuJGV4dHJhXSkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGNvbnN0IGF0dHJpYnV0ZXMgPSBub2RlW194ZmFfb2JqZWN0LiRleHRyYV0uYXR0cmlidXRlczsKICBjb25zdCBodG1sID0gewogICAgbmFtZTogImRpdiIsCiAgICBhdHRyaWJ1dGVzLAogICAgY2hpbGRyZW46IG5vZGVbX3hmYV9vYmplY3QuJGV4dHJhXS5jaGlsZHJlbgogIH07CiAgaWYgKG5vZGVbX3hmYV9vYmplY3QuJGV4dHJhXS5mYWlsaW5nTm9kZSkgewogICAgY29uc3QgaHRtbEZyb21GYWlsaW5nID0gbm9kZVtfeGZhX29iamVjdC4kZXh0cmFdLmZhaWxpbmdOb2RlW194ZmFfb2JqZWN0LiRmbHVzaEhUTUxdKCk7CiAgICBpZiAoaHRtbEZyb21GYWlsaW5nKSB7CiAgICAgIGlmIChub2RlLmxheW91dC5lbmRzV2l0aCgiLXRiIikpIHsKICAgICAgICBodG1sLmNoaWxkcmVuLnB1c2goY3JlYXRlTGluZShub2RlLCBbaHRtbEZyb21GYWlsaW5nXSkpOwogICAgICB9IGVsc2UgewogICAgICAgIGh0bWwuY2hpbGRyZW4ucHVzaChodG1sRnJvbUZhaWxpbmcpOwogICAgICB9CiAgICB9CiAgfQogIGlmIChodG1sLmNoaWxkcmVuLmxlbmd0aCA9PT0gMCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIHJldHVybiBodG1sOwp9CmZ1bmN0aW9uIGFkZEhUTUwobm9kZSwgaHRtbCwgYmJveCkgewogIGNvbnN0IGV4dHJhID0gbm9kZVtfeGZhX29iamVjdC4kZXh0cmFdOwogIGNvbnN0IGF2YWlsYWJsZVNwYWNlID0gZXh0cmEuYXZhaWxhYmxlU3BhY2U7CiAgY29uc3QgW3gsIHksIHcsIGhdID0gYmJveDsKICBzd2l0Y2ggKG5vZGUubGF5b3V0KSB7CiAgICBjYXNlICJwb3NpdGlvbiI6CiAgICAgIHsKICAgICAgICBleHRyYS53aWR0aCA9IE1hdGgubWF4KGV4dHJhLndpZHRoLCB4ICsgdyk7CiAgICAgICAgZXh0cmEuaGVpZ2h0ID0gTWF0aC5tYXgoZXh0cmEuaGVpZ2h0LCB5ICsgaCk7CiAgICAgICAgZXh0cmEuY2hpbGRyZW4ucHVzaChodG1sKTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgY2FzZSAibHItdGIiOgogICAgY2FzZSAicmwtdGIiOgogICAgICBpZiAoIWV4dHJhLmxpbmUgfHwgZXh0cmEuYXR0ZW1wdCA9PT0gMSkgewogICAgICAgIGV4dHJhLmxpbmUgPSBjcmVhdGVMaW5lKG5vZGUsIFtdKTsKICAgICAgICBleHRyYS5jaGlsZHJlbi5wdXNoKGV4dHJhLmxpbmUpOwogICAgICAgIGV4dHJhLm51bWJlckluTGluZSA9IDA7CiAgICAgIH0KICAgICAgZXh0cmEubnVtYmVySW5MaW5lICs9IDE7CiAgICAgIGV4dHJhLmxpbmUuY2hpbGRyZW4ucHVzaChodG1sKTsKICAgICAgaWYgKGV4dHJhLmF0dGVtcHQgPT09IDApIHsKICAgICAgICBleHRyYS5jdXJyZW50V2lkdGggKz0gdzsKICAgICAgICBleHRyYS5oZWlnaHQgPSBNYXRoLm1heChleHRyYS5oZWlnaHQsIGV4dHJhLnByZXZIZWlnaHQgKyBoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBleHRyYS5jdXJyZW50V2lkdGggPSB3OwogICAgICAgIGV4dHJhLnByZXZIZWlnaHQgPSBleHRyYS5oZWlnaHQ7CiAgICAgICAgZXh0cmEuaGVpZ2h0ICs9IGg7CiAgICAgICAgZXh0cmEuYXR0ZW1wdCA9IDA7CiAgICAgIH0KICAgICAgZXh0cmEud2lkdGggPSBNYXRoLm1heChleHRyYS53aWR0aCwgZXh0cmEuY3VycmVudFdpZHRoKTsKICAgICAgYnJlYWs7CiAgICBjYXNlICJybC1yb3ciOgogICAgY2FzZSAicm93IjoKICAgICAgewogICAgICAgIGV4dHJhLmNoaWxkcmVuLnB1c2goaHRtbCk7CiAgICAgICAgZXh0cmEud2lkdGggKz0gdzsKICAgICAgICBleHRyYS5oZWlnaHQgPSBNYXRoLm1heChleHRyYS5oZWlnaHQsIGgpOwogICAgICAgIGNvbnN0IGhlaWdodCA9ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKGV4dHJhLmhlaWdodCk7CiAgICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiBleHRyYS5jaGlsZHJlbikgewogICAgICAgICAgY2hpbGQuYXR0cmlidXRlcy5zdHlsZS5oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICB9CiAgICBjYXNlICJ0YWJsZSI6CiAgICAgIHsKICAgICAgICBleHRyYS53aWR0aCA9IE1hdGgubWluKGF2YWlsYWJsZVNwYWNlLndpZHRoLCBNYXRoLm1heChleHRyYS53aWR0aCwgdykpOwogICAgICAgIGV4dHJhLmhlaWdodCArPSBoOwogICAgICAgIGV4dHJhLmNoaWxkcmVuLnB1c2goaHRtbCk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIGNhc2UgInRiIjoKICAgICAgewogICAgICAgIGV4dHJhLndpZHRoID0gTWF0aC5taW4oYXZhaWxhYmxlU3BhY2Uud2lkdGgsIE1hdGgubWF4KGV4dHJhLndpZHRoLCB3KSk7CiAgICAgICAgZXh0cmEuaGVpZ2h0ICs9IGg7CiAgICAgICAgZXh0cmEuY2hpbGRyZW4ucHVzaChodG1sKTsKICAgICAgICBicmVhazsKICAgICAgfQogIH0KfQpmdW5jdGlvbiBnZXRBdmFpbGFibGVTcGFjZShub2RlKSB7CiAgY29uc3QgYXZhaWxhYmxlU3BhY2UgPSBub2RlW194ZmFfb2JqZWN0LiRleHRyYV0uYXZhaWxhYmxlU3BhY2U7CiAgY29uc3QgbWFyZ2luViA9IG5vZGUubWFyZ2luID8gbm9kZS5tYXJnaW4udG9wSW5zZXQgKyBub2RlLm1hcmdpbi5ib3R0b21JbnNldCA6IDA7CiAgY29uc3QgbWFyZ2luSCA9IG5vZGUubWFyZ2luID8gbm9kZS5tYXJnaW4ubGVmdEluc2V0ICsgbm9kZS5tYXJnaW4ucmlnaHRJbnNldCA6IDA7CiAgc3dpdGNoIChub2RlLmxheW91dCkgewogICAgY2FzZSAibHItdGIiOgogICAgY2FzZSAicmwtdGIiOgogICAgICBpZiAobm9kZVtfeGZhX29iamVjdC4kZXh0cmFdLmF0dGVtcHQgPT09IDApIHsKICAgICAgICByZXR1cm4gewogICAgICAgICAgd2lkdGg6IGF2YWlsYWJsZVNwYWNlLndpZHRoIC0gbWFyZ2luSCAtIG5vZGVbX3hmYV9vYmplY3QuJGV4dHJhXS5jdXJyZW50V2lkdGgsCiAgICAgICAgICBoZWlnaHQ6IGF2YWlsYWJsZVNwYWNlLmhlaWdodCAtIG1hcmdpblYgLSBub2RlW194ZmFfb2JqZWN0LiRleHRyYV0ucHJldkhlaWdodAogICAgICAgIH07CiAgICAgIH0KICAgICAgcmV0dXJuIHsKICAgICAgICB3aWR0aDogYXZhaWxhYmxlU3BhY2Uud2lkdGggLSBtYXJnaW5ILAogICAgICAgIGhlaWdodDogYXZhaWxhYmxlU3BhY2UuaGVpZ2h0IC0gbWFyZ2luViAtIG5vZGVbX3hmYV9vYmplY3QuJGV4dHJhXS5oZWlnaHQKICAgICAgfTsKICAgIGNhc2UgInJsLXJvdyI6CiAgICBjYXNlICJyb3ciOgogICAgICBjb25zdCB3aWR0aCA9IG5vZGVbX3hmYV9vYmplY3QuJGV4dHJhXS5jb2x1bW5XaWR0aHMuc2xpY2Uobm9kZVtfeGZhX29iamVjdC4kZXh0cmFdLmN1cnJlbnRDb2x1bW4pLnJlZHVjZSgoYSwgeCkgPT4gYSArIHgpOwogICAgICByZXR1cm4gewogICAgICAgIHdpZHRoLAogICAgICAgIGhlaWdodDogYXZhaWxhYmxlU3BhY2UuaGVpZ2h0IC0gbWFyZ2luSAogICAgICB9OwogICAgY2FzZSAidGFibGUiOgogICAgY2FzZSAidGIiOgogICAgICByZXR1cm4gewogICAgICAgIHdpZHRoOiBhdmFpbGFibGVTcGFjZS53aWR0aCAtIG1hcmdpbkgsCiAgICAgICAgaGVpZ2h0OiBhdmFpbGFibGVTcGFjZS5oZWlnaHQgLSBtYXJnaW5WIC0gbm9kZVtfeGZhX29iamVjdC4kZXh0cmFdLmhlaWdodAogICAgICB9OwogICAgY2FzZSAicG9zaXRpb24iOgogICAgZGVmYXVsdDoKICAgICAgcmV0dXJuIGF2YWlsYWJsZVNwYWNlOwogIH0KfQpmdW5jdGlvbiBnZXRUcmFuc2Zvcm1lZEJCb3gobm9kZSkgewogIGxldCB3ID0gbm9kZS53ID09PSAiIiA/IE5hTiA6IG5vZGUudzsKICBsZXQgaCA9IG5vZGUuaCA9PT0gIiIgPyBOYU4gOiBub2RlLmg7CiAgbGV0IFtjZW50ZXJYLCBjZW50ZXJZXSA9IFswLCAwXTsKICBzd2l0Y2ggKG5vZGUuYW5jaG9yVHlwZSB8fCAiIikgewogICAgY2FzZSAiYm90dG9tQ2VudGVyIjoKICAgICAgW2NlbnRlclgsIGNlbnRlclldID0gW3cgLyAyLCBoXTsKICAgICAgYnJlYWs7CiAgICBjYXNlICJib3R0b21MZWZ0IjoKICAgICAgW2NlbnRlclgsIGNlbnRlclldID0gWzAsIGhdOwogICAgICBicmVhazsKICAgIGNhc2UgImJvdHRvbVJpZ2h0IjoKICAgICAgW2NlbnRlclgsIGNlbnRlclldID0gW3csIGhdOwogICAgICBicmVhazsKICAgIGNhc2UgIm1pZGRsZUNlbnRlciI6CiAgICAgIFtjZW50ZXJYLCBjZW50ZXJZXSA9IFt3IC8gMiwgaCAvIDJdOwogICAgICBicmVhazsKICAgIGNhc2UgIm1pZGRsZUxlZnQiOgogICAgICBbY2VudGVyWCwgY2VudGVyWV0gPSBbMCwgaCAvIDJdOwogICAgICBicmVhazsKICAgIGNhc2UgIm1pZGRsZVJpZ2h0IjoKICAgICAgW2NlbnRlclgsIGNlbnRlclldID0gW3csIGggLyAyXTsKICAgICAgYnJlYWs7CiAgICBjYXNlICJ0b3BDZW50ZXIiOgogICAgICBbY2VudGVyWCwgY2VudGVyWV0gPSBbdyAvIDIsIDBdOwogICAgICBicmVhazsKICAgIGNhc2UgInRvcFJpZ2h0IjoKICAgICAgW2NlbnRlclgsIGNlbnRlclldID0gW3csIDBdOwogICAgICBicmVhazsKICB9CiAgbGV0IHgsIHk7CiAgc3dpdGNoIChub2RlLnJvdGF0ZSB8fCAwKSB7CiAgICBjYXNlIDA6CiAgICAgIFt4LCB5XSA9IFstY2VudGVyWCwgLWNlbnRlclldOwogICAgICBicmVhazsKICAgIGNhc2UgOTA6CiAgICAgIFt4LCB5XSA9IFstY2VudGVyWSwgY2VudGVyWF07CiAgICAgIFt3LCBoXSA9IFtoLCAtd107CiAgICAgIGJyZWFrOwogICAgY2FzZSAxODA6CiAgICAgIFt4LCB5XSA9IFtjZW50ZXJYLCBjZW50ZXJZXTsKICAgICAgW3csIGhdID0gWy13LCAtaF07CiAgICAgIGJyZWFrOwogICAgY2FzZSAyNzA6CiAgICAgIFt4LCB5XSA9IFtjZW50ZXJZLCAtY2VudGVyWF07CiAgICAgIFt3LCBoXSA9IFstaCwgd107CiAgICAgIGJyZWFrOwogIH0KICByZXR1cm4gW25vZGUueCArIHggKyBNYXRoLm1pbigwLCB3KSwgbm9kZS55ICsgeSArIE1hdGgubWluKDAsIGgpLCBNYXRoLmFicyh3KSwgTWF0aC5hYnMoaCldOwp9CmZ1bmN0aW9uIGNoZWNrRGltZW5zaW9ucyhub2RlLCBzcGFjZSkgewogIGlmIChub2RlW194ZmFfb2JqZWN0LiRnZXRUZW1wbGF0ZVJvb3RdKClbX3hmYV9vYmplY3QuJGV4dHJhXS5maXJzdFVuc3BsaXR0YWJsZSA9PT0gbnVsbCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIGlmIChub2RlLncgPT09IDAgfHwgbm9kZS5oID09PSAwKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgY29uc3QgRVJST1IgPSAyOwogIGNvbnN0IHBhcmVudCA9IG5vZGVbX3hmYV9vYmplY3QuJGdldFN1YmZvcm1QYXJlbnRdKCk7CiAgY29uc3QgYXR0ZW1wdCA9IHBhcmVudFtfeGZhX29iamVjdC4kZXh0cmFdICYmIHBhcmVudFtfeGZhX29iamVjdC4kZXh0cmFdLmF0dGVtcHQgfHwgMDsKICBjb25zdCBbLCB5LCB3LCBoXSA9IGdldFRyYW5zZm9ybWVkQkJveChub2RlKTsKICBzd2l0Y2ggKHBhcmVudC5sYXlvdXQpIHsKICAgIGNhc2UgImxyLXRiIjoKICAgIGNhc2UgInJsLXRiIjoKICAgICAgaWYgKGF0dGVtcHQgPT09IDApIHsKICAgICAgICBpZiAoIW5vZGVbX3hmYV9vYmplY3QuJGdldFRlbXBsYXRlUm9vdF0oKVtfeGZhX29iamVjdC4kZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSkgewogICAgICAgICAgaWYgKG5vZGUuaCAhPT0gIiIgJiYgTWF0aC5yb3VuZChoIC0gc3BhY2UuaGVpZ2h0KSA+IEVSUk9SKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChub2RlLncgIT09ICIiKSB7CiAgICAgICAgICAgIGlmIChNYXRoLnJvdW5kKHcgLSBzcGFjZS53aWR0aCkgPD0gRVJST1IpIHsKICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocGFyZW50W194ZmFfb2JqZWN0LiRleHRyYV0ubnVtYmVySW5MaW5lID09PSAwKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHNwYWNlLmhlaWdodCA+IEVSUk9SOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBzcGFjZS53aWR0aCA+IEVSUk9SOwogICAgICAgIH0KICAgICAgICBpZiAobm9kZS53ICE9PSAiIikgewogICAgICAgICAgcmV0dXJuIE1hdGgucm91bmQodyAtIHNwYWNlLndpZHRoKSA8PSBFUlJPUjsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHNwYWNlLndpZHRoID4gRVJST1I7CiAgICAgIH0KICAgICAgaWYgKG5vZGVbX3hmYV9vYmplY3QuJGdldFRlbXBsYXRlUm9vdF0oKVtfeGZhX29iamVjdC4kZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmIChub2RlLmggIT09ICIiICYmIE1hdGgucm91bmQoaCAtIHNwYWNlLmhlaWdodCkgPiBFUlJPUikgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAobm9kZS53ID09PSAiIiB8fCBNYXRoLnJvdW5kKHcgLSBzcGFjZS53aWR0aCkgPD0gRVJST1IpIHsKICAgICAgICByZXR1cm4gc3BhY2UuaGVpZ2h0ID4gRVJST1I7CiAgICAgIH0KICAgICAgaWYgKHBhcmVudFtfeGZhX29iamVjdC4kaXNUaGVyZU1vcmVXaWR0aF0oKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICByZXR1cm4gc3BhY2UuaGVpZ2h0ID4gRVJST1I7CiAgICBjYXNlICJ0YWJsZSI6CiAgICBjYXNlICJ0YiI6CiAgICAgIGlmIChub2RlW194ZmFfb2JqZWN0LiRnZXRUZW1wbGF0ZVJvb3RdKClbX3hmYV9vYmplY3QuJGV4dHJhXS5ub0xheW91dEZhaWx1cmUpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAobm9kZS5oICE9PSAiIiAmJiAhbm9kZVtfeGZhX29iamVjdC4kaXNTcGxpdHRhYmxlXSgpKSB7CiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQoaCAtIHNwYWNlLmhlaWdodCkgPD0gRVJST1I7CiAgICAgIH0KICAgICAgaWYgKG5vZGUudyA9PT0gIiIgfHwgTWF0aC5yb3VuZCh3IC0gc3BhY2Uud2lkdGgpIDw9IEVSUk9SKSB7CiAgICAgICAgcmV0dXJuIHNwYWNlLmhlaWdodCA+IEVSUk9SOwogICAgICB9CiAgICAgIGlmIChwYXJlbnRbX3hmYV9vYmplY3QuJGlzVGhlcmVNb3JlV2lkdGhdKCkpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgcmV0dXJuIHNwYWNlLmhlaWdodCA+IEVSUk9SOwogICAgY2FzZSAicG9zaXRpb24iOgogICAgICBpZiAobm9kZVtfeGZhX29iamVjdC4kZ2V0VGVtcGxhdGVSb290XSgpW194ZmFfb2JqZWN0LiRleHRyYV0ubm9MYXlvdXRGYWlsdXJlKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKG5vZGUuaCA9PT0gIiIgfHwgTWF0aC5yb3VuZChoICsgeSAtIHNwYWNlLmhlaWdodCkgPD0gRVJST1IpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBjb25zdCBhcmVhID0gbm9kZVtfeGZhX29iamVjdC4kZ2V0VGVtcGxhdGVSb290XSgpW194ZmFfb2JqZWN0LiRleHRyYV0uY3VycmVudENvbnRlbnRBcmVhOwogICAgICByZXR1cm4gaCArIHkgPiBhcmVhLmg7CiAgICBjYXNlICJybC1yb3ciOgogICAgY2FzZSAicm93IjoKICAgICAgaWYgKG5vZGVbX3hmYV9vYmplY3QuJGdldFRlbXBsYXRlUm9vdF0oKVtfeGZhX29iamVjdC4kZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmIChub2RlLmggIT09ICIiKSB7CiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQoaCAtIHNwYWNlLmhlaWdodCkgPD0gRVJST1I7CiAgICAgIH0KICAgICAgcmV0dXJuIHRydWU7CiAgICBkZWZhdWx0OgogICAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KCi8qKiovIH0pLAovKiAyMTkgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLmNvbXB1dGVCYm94ID0gY29tcHV0ZUJib3g7CmV4cG9ydHMuY3JlYXRlV3JhcHBlciA9IGNyZWF0ZVdyYXBwZXI7CmV4cG9ydHMuZml4RGltZW5zaW9ucyA9IGZpeERpbWVuc2lvbnM7CmV4cG9ydHMuZml4VGV4dEluZGVudCA9IGZpeFRleHRJbmRlbnQ7CmV4cG9ydHMuZml4VVJMID0gZml4VVJMOwpleHBvcnRzLmlzUHJpbnRPbmx5ID0gaXNQcmludE9ubHk7CmV4cG9ydHMubGF5b3V0Q2xhc3MgPSBsYXlvdXRDbGFzczsKZXhwb3J0cy5sYXlvdXROb2RlID0gbGF5b3V0Tm9kZTsKZXhwb3J0cy5tZWFzdXJlVG9TdHJpbmcgPSBtZWFzdXJlVG9TdHJpbmc7CmV4cG9ydHMuc2V0QWNjZXNzID0gc2V0QWNjZXNzOwpleHBvcnRzLnNldEZvbnRGYW1pbHkgPSBzZXRGb250RmFtaWx5OwpleHBvcnRzLnNldE1pbk1heERpbWVuc2lvbnMgPSBzZXRNaW5NYXhEaW1lbnNpb25zOwpleHBvcnRzLnNldFBhcmEgPSBzZXRQYXJhOwpleHBvcnRzLnRvU3R5bGUgPSB0b1N0eWxlOwp2YXIgX3hmYV9vYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxMik7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CnZhciBfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxMyk7CnZhciBfZm9udHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIyMCk7CnZhciBfdGV4dCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjIxKTsKZnVuY3Rpb24gbWVhc3VyZVRvU3RyaW5nKG0pIHsKICBpZiAodHlwZW9mIG0gPT09ICJzdHJpbmciKSB7CiAgICByZXR1cm4gIjBweCI7CiAgfQogIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKG0pID8gYCR7bX1weGAgOiBgJHttLnRvRml4ZWQoMil9cHhgOwp9CmNvbnN0IGNvbnZlcnRlcnMgPSB7CiAgYW5jaG9yVHlwZShub2RlLCBzdHlsZSkgewogICAgY29uc3QgcGFyZW50ID0gbm9kZVtfeGZhX29iamVjdC4kZ2V0U3ViZm9ybVBhcmVudF0oKTsKICAgIGlmICghcGFyZW50IHx8IHBhcmVudC5sYXlvdXQgJiYgcGFyZW50LmxheW91dCAhPT0gInBvc2l0aW9uIikgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoISgidHJhbnNmb3JtIiBpbiBzdHlsZSkpIHsKICAgICAgc3R5bGUudHJhbnNmb3JtID0gIiI7CiAgICB9CiAgICBzd2l0Y2ggKG5vZGUuYW5jaG9yVHlwZSkgewogICAgICBjYXNlICJib3R0b21DZW50ZXIiOgogICAgICAgIHN0eWxlLnRyYW5zZm9ybSArPSAidHJhbnNsYXRlKC01MCUsIC0xMDAlKSI7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgImJvdHRvbUxlZnQiOgogICAgICAgIHN0eWxlLnRyYW5zZm9ybSArPSAidHJhbnNsYXRlKDAsLTEwMCUpIjsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiYm90dG9tUmlnaHQiOgogICAgICAgIHN0eWxlLnRyYW5zZm9ybSArPSAidHJhbnNsYXRlKC0xMDAlLC0xMDAlKSI7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIm1pZGRsZUNlbnRlciI6CiAgICAgICAgc3R5bGUudHJhbnNmb3JtICs9ICJ0cmFuc2xhdGUoLTUwJSwtNTAlKSI7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIm1pZGRsZUxlZnQiOgogICAgICAgIHN0eWxlLnRyYW5zZm9ybSArPSAidHJhbnNsYXRlKDAsLTUwJSkiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJtaWRkbGVSaWdodCI6CiAgICAgICAgc3R5bGUudHJhbnNmb3JtICs9ICJ0cmFuc2xhdGUoLTEwMCUsLTUwJSkiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJ0b3BDZW50ZXIiOgogICAgICAgIHN0eWxlLnRyYW5zZm9ybSArPSAidHJhbnNsYXRlKC01MCUsMCkiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJ0b3BSaWdodCI6CiAgICAgICAgc3R5bGUudHJhbnNmb3JtICs9ICJ0cmFuc2xhdGUoLTEwMCUsMCkiOwogICAgICAgIGJyZWFrOwogICAgfQogIH0sCiAgZGltZW5zaW9ucyhub2RlLCBzdHlsZSkgewogICAgY29uc3QgcGFyZW50ID0gbm9kZVtfeGZhX29iamVjdC4kZ2V0U3ViZm9ybVBhcmVudF0oKTsKICAgIGxldCB3aWR0aCA9IG5vZGUudzsKICAgIGNvbnN0IGhlaWdodCA9IG5vZGUuaDsKICAgIGlmIChwYXJlbnQubGF5b3V0ICYmIHBhcmVudC5sYXlvdXQuaW5jbHVkZXMoInJvdyIpKSB7CiAgICAgIGNvbnN0IGV4dHJhID0gcGFyZW50W194ZmFfb2JqZWN0LiRleHRyYV07CiAgICAgIGNvbnN0IGNvbFNwYW4gPSBub2RlLmNvbFNwYW47CiAgICAgIGxldCB3OwogICAgICBpZiAoY29sU3BhbiA9PT0gLTEpIHsKICAgICAgICB3ID0gZXh0cmEuY29sdW1uV2lkdGhzLnNsaWNlKGV4dHJhLmN1cnJlbnRDb2x1bW4pLnJlZHVjZSgoYSwgeCkgPT4gYSArIHgsIDApOwogICAgICAgIGV4dHJhLmN1cnJlbnRDb2x1bW4gPSAwOwogICAgICB9IGVsc2UgewogICAgICAgIHcgPSBleHRyYS5jb2x1bW5XaWR0aHMuc2xpY2UoZXh0cmEuY3VycmVudENvbHVtbiwgZXh0cmEuY3VycmVudENvbHVtbiArIGNvbFNwYW4pLnJlZHVjZSgoYSwgeCkgPT4gYSArIHgsIDApOwogICAgICAgIGV4dHJhLmN1cnJlbnRDb2x1bW4gPSAoZXh0cmEuY3VycmVudENvbHVtbiArIG5vZGUuY29sU3BhbikgJSBleHRyYS5jb2x1bW5XaWR0aHMubGVuZ3RoOwogICAgICB9CiAgICAgIGlmICghaXNOYU4odykpIHsKICAgICAgICB3aWR0aCA9IG5vZGUudyA9IHc7CiAgICAgIH0KICAgIH0KICAgIGlmICh3aWR0aCAhPT0gIiIpIHsKICAgICAgc3R5bGUud2lkdGggPSBtZWFzdXJlVG9TdHJpbmcod2lkdGgpOwogICAgfSBlbHNlIHsKICAgICAgc3R5bGUud2lkdGggPSAiYXV0byI7CiAgICB9CiAgICBpZiAoaGVpZ2h0ICE9PSAiIikgewogICAgICBzdHlsZS5oZWlnaHQgPSBtZWFzdXJlVG9TdHJpbmcoaGVpZ2h0KTsKICAgIH0gZWxzZSB7CiAgICAgIHN0eWxlLmhlaWdodCA9ICJhdXRvIjsKICAgIH0KICB9LAogIHBvc2l0aW9uKG5vZGUsIHN0eWxlKSB7CiAgICBjb25zdCBwYXJlbnQgPSBub2RlW194ZmFfb2JqZWN0LiRnZXRTdWJmb3JtUGFyZW50XSgpOwogICAgaWYgKHBhcmVudCAmJiBwYXJlbnQubGF5b3V0ICYmIHBhcmVudC5sYXlvdXQgIT09ICJwb3NpdGlvbiIpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgc3R5bGUucG9zaXRpb24gPSAiYWJzb2x1dGUiOwogICAgc3R5bGUubGVmdCA9IG1lYXN1cmVUb1N0cmluZyhub2RlLngpOwogICAgc3R5bGUudG9wID0gbWVhc3VyZVRvU3RyaW5nKG5vZGUueSk7CiAgfSwKICByb3RhdGUobm9kZSwgc3R5bGUpIHsKICAgIGlmIChub2RlLnJvdGF0ZSkgewogICAgICBpZiAoISgidHJhbnNmb3JtIiBpbiBzdHlsZSkpIHsKICAgICAgICBzdHlsZS50cmFuc2Zvcm0gPSAiIjsKICAgICAgfQogICAgICBzdHlsZS50cmFuc2Zvcm0gKz0gYHJvdGF0ZSgtJHtub2RlLnJvdGF0ZX1kZWcpYDsKICAgICAgc3R5bGUudHJhbnNmb3JtT3JpZ2luID0gInRvcCBsZWZ0IjsKICAgIH0KICB9LAogIHByZXNlbmNlKG5vZGUsIHN0eWxlKSB7CiAgICBzd2l0Y2ggKG5vZGUucHJlc2VuY2UpIHsKICAgICAgY2FzZSAiaW52aXNpYmxlIjoKICAgICAgICBzdHlsZS52aXNpYmlsaXR5ID0gImhpZGRlbiI7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgImhpZGRlbiI6CiAgICAgIGNhc2UgImluYWN0aXZlIjoKICAgICAgICBzdHlsZS5kaXNwbGF5ID0gIm5vbmUiOwogICAgICAgIGJyZWFrOwogICAgfQogIH0sCiAgaEFsaWduKG5vZGUsIHN0eWxlKSB7CiAgICBpZiAobm9kZVtfeGZhX29iamVjdC4kbm9kZU5hbWVdID09PSAicGFyYSIpIHsKICAgICAgc3dpdGNoIChub2RlLmhBbGlnbikgewogICAgICAgIGNhc2UgImp1c3RpZnlBbGwiOgogICAgICAgICAgc3R5bGUudGV4dEFsaWduID0gImp1c3RpZnktYWxsIjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInJhZGl4IjoKICAgICAgICAgIHN0eWxlLnRleHRBbGlnbiA9ICJsZWZ0IjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBzdHlsZS50ZXh0QWxpZ24gPSBub2RlLmhBbGlnbjsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgc3dpdGNoIChub2RlLmhBbGlnbikgewogICAgICAgIGNhc2UgImxlZnQiOgogICAgICAgICAgc3R5bGUuYWxpZ25TZWxmID0gInN0YXJ0IjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImNlbnRlciI6CiAgICAgICAgICBzdHlsZS5hbGlnblNlbGYgPSAiY2VudGVyIjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInJpZ2h0IjoKICAgICAgICAgIHN0eWxlLmFsaWduU2VsZiA9ICJlbmQiOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICB9LAogIG1hcmdpbihub2RlLCBzdHlsZSkgewogICAgaWYgKG5vZGUubWFyZ2luKSB7CiAgICAgIHN0eWxlLm1hcmdpbiA9IG5vZGUubWFyZ2luW194ZmFfb2JqZWN0LiR0b1N0eWxlXSgpLm1hcmdpbjsKICAgIH0KICB9Cn07CmZ1bmN0aW9uIHNldE1pbk1heERpbWVuc2lvbnMobm9kZSwgc3R5bGUpIHsKICBjb25zdCBwYXJlbnQgPSBub2RlW194ZmFfb2JqZWN0LiRnZXRTdWJmb3JtUGFyZW50XSgpOwogIGlmIChwYXJlbnQubGF5b3V0ID09PSAicG9zaXRpb24iKSB7CiAgICBpZiAobm9kZS5taW5XID4gMCkgewogICAgICBzdHlsZS5taW5XaWR0aCA9IG1lYXN1cmVUb1N0cmluZyhub2RlLm1pblcpOwogICAgfQogICAgaWYgKG5vZGUubWF4VyA+IDApIHsKICAgICAgc3R5bGUubWF4V2lkdGggPSBtZWFzdXJlVG9TdHJpbmcobm9kZS5tYXhXKTsKICAgIH0KICAgIGlmIChub2RlLm1pbkggPiAwKSB7CiAgICAgIHN0eWxlLm1pbkhlaWdodCA9IG1lYXN1cmVUb1N0cmluZyhub2RlLm1pbkgpOwogICAgfQogICAgaWYgKG5vZGUubWF4SCA+IDApIHsKICAgICAgc3R5bGUubWF4SGVpZ2h0ID0gbWVhc3VyZVRvU3RyaW5nKG5vZGUubWF4SCk7CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGxheW91dFRleHQodGV4dCwgeGZhRm9udCwgbWFyZ2luLCBsaW5lSGVpZ2h0LCBmb250RmluZGVyLCB3aWR0aCkgewogIGNvbnN0IG1lYXN1cmUgPSBuZXcgX3RleHQuVGV4dE1lYXN1cmUoeGZhRm9udCwgbWFyZ2luLCBsaW5lSGVpZ2h0LCBmb250RmluZGVyKTsKICBpZiAodHlwZW9mIHRleHQgPT09ICJzdHJpbmciKSB7CiAgICBtZWFzdXJlLmFkZFN0cmluZyh0ZXh0KTsKICB9IGVsc2UgewogICAgdGV4dFtfeGZhX29iamVjdC4kcHVzaEdseXBoc10obWVhc3VyZSk7CiAgfQogIHJldHVybiBtZWFzdXJlLmNvbXB1dGUod2lkdGgpOwp9CmZ1bmN0aW9uIGxheW91dE5vZGUobm9kZSwgYXZhaWxhYmxlU3BhY2UpIHsKICBsZXQgaGVpZ2h0ID0gbnVsbDsKICBsZXQgd2lkdGggPSBudWxsOwogIGxldCBpc0Jyb2tlbiA9IGZhbHNlOwogIGlmICgoIW5vZGUudyB8fCAhbm9kZS5oKSAmJiBub2RlLnZhbHVlKSB7CiAgICBsZXQgbWFyZ2luSCA9IDA7CiAgICBsZXQgbWFyZ2luViA9IDA7CiAgICBpZiAobm9kZS5tYXJnaW4pIHsKICAgICAgbWFyZ2luSCA9IG5vZGUubWFyZ2luLmxlZnRJbnNldCArIG5vZGUubWFyZ2luLnJpZ2h0SW5zZXQ7CiAgICAgIG1hcmdpblYgPSBub2RlLm1hcmdpbi50b3BJbnNldCArIG5vZGUubWFyZ2luLmJvdHRvbUluc2V0OwogICAgfQogICAgbGV0IGxpbmVIZWlnaHQgPSBudWxsOwogICAgbGV0IG1hcmdpbiA9IG51bGw7CiAgICBpZiAobm9kZS5wYXJhKSB7CiAgICAgIG1hcmdpbiA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIGxpbmVIZWlnaHQgPSBub2RlLnBhcmEubGluZUhlaWdodCA9PT0gIiIgPyBudWxsIDogbm9kZS5wYXJhLmxpbmVIZWlnaHQ7CiAgICAgIG1hcmdpbi50b3AgPSBub2RlLnBhcmEuc3BhY2VBYm92ZSA9PT0gIiIgPyAwIDogbm9kZS5wYXJhLnNwYWNlQWJvdmU7CiAgICAgIG1hcmdpbi5ib3R0b20gPSBub2RlLnBhcmEuc3BhY2VCZWxvdyA9PT0gIiIgPyAwIDogbm9kZS5wYXJhLnNwYWNlQmVsb3c7CiAgICAgIG1hcmdpbi5sZWZ0ID0gbm9kZS5wYXJhLm1hcmdpbkxlZnQgPT09ICIiID8gMCA6IG5vZGUucGFyYS5tYXJnaW5MZWZ0OwogICAgICBtYXJnaW4ucmlnaHQgPSBub2RlLnBhcmEubWFyZ2luUmlnaHQgPT09ICIiID8gMCA6IG5vZGUucGFyYS5tYXJnaW5SaWdodDsKICAgIH0KICAgIGxldCBmb250ID0gbm9kZS5mb250OwogICAgaWYgKCFmb250KSB7CiAgICAgIGNvbnN0IHJvb3QgPSBub2RlW194ZmFfb2JqZWN0LiRnZXRUZW1wbGF0ZVJvb3RdKCk7CiAgICAgIGxldCBwYXJlbnQgPSBub2RlW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICAgIHdoaWxlIChwYXJlbnQgJiYgcGFyZW50ICE9PSByb290KSB7CiAgICAgICAgaWYgKHBhcmVudC5mb250KSB7CiAgICAgICAgICBmb250ID0gcGFyZW50LmZvbnQ7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgcGFyZW50ID0gcGFyZW50W194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKCk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IG1heFdpZHRoID0gKG5vZGUudyB8fCBhdmFpbGFibGVTcGFjZS53aWR0aCkgLSBtYXJnaW5IOwogICAgY29uc3QgZm9udEZpbmRlciA9IG5vZGVbX3hmYV9vYmplY3QuJGdsb2JhbERhdGFdLmZvbnRGaW5kZXI7CiAgICBpZiAobm9kZS52YWx1ZS5leERhdGEgJiYgbm9kZS52YWx1ZS5leERhdGFbX3hmYV9vYmplY3QuJGNvbnRlbnRdICYmIG5vZGUudmFsdWUuZXhEYXRhLmNvbnRlbnRUeXBlID09PSAidGV4dC9odG1sIikgewogICAgICBjb25zdCByZXMgPSBsYXlvdXRUZXh0KG5vZGUudmFsdWUuZXhEYXRhW194ZmFfb2JqZWN0LiRjb250ZW50XSwgZm9udCwgbWFyZ2luLCBsaW5lSGVpZ2h0LCBmb250RmluZGVyLCBtYXhXaWR0aCk7CiAgICAgIHdpZHRoID0gcmVzLndpZHRoOwogICAgICBoZWlnaHQgPSByZXMuaGVpZ2h0OwogICAgICBpc0Jyb2tlbiA9IHJlcy5pc0Jyb2tlbjsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IHRleHQgPSBub2RlLnZhbHVlW194ZmFfb2JqZWN0LiR0ZXh0XSgpOwogICAgICBpZiAodGV4dCkgewogICAgICAgIGNvbnN0IHJlcyA9IGxheW91dFRleHQodGV4dCwgZm9udCwgbWFyZ2luLCBsaW5lSGVpZ2h0LCBmb250RmluZGVyLCBtYXhXaWR0aCk7CiAgICAgICAgd2lkdGggPSByZXMud2lkdGg7CiAgICAgICAgaGVpZ2h0ID0gcmVzLmhlaWdodDsKICAgICAgICBpc0Jyb2tlbiA9IHJlcy5pc0Jyb2tlbjsKICAgICAgfQogICAgfQogICAgaWYgKHdpZHRoICE9PSBudWxsICYmICFub2RlLncpIHsKICAgICAgd2lkdGggKz0gbWFyZ2luSDsKICAgIH0KICAgIGlmIChoZWlnaHQgIT09IG51bGwgJiYgIW5vZGUuaCkgewogICAgICBoZWlnaHQgKz0gbWFyZ2luVjsKICAgIH0KICB9CiAgcmV0dXJuIHsKICAgIHc6IHdpZHRoLAogICAgaDogaGVpZ2h0LAogICAgaXNCcm9rZW4KICB9Owp9CmZ1bmN0aW9uIGNvbXB1dGVCYm94KG5vZGUsIGh0bWwsIGF2YWlsYWJsZVNwYWNlKSB7CiAgbGV0IGJib3g7CiAgaWYgKG5vZGUudyAhPT0gIiIgJiYgbm9kZS5oICE9PSAiIikgewogICAgYmJveCA9IFtub2RlLngsIG5vZGUueSwgbm9kZS53LCBub2RlLmhdOwogIH0gZWxzZSB7CiAgICBpZiAoIWF2YWlsYWJsZVNwYWNlKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgbGV0IHdpZHRoID0gbm9kZS53OwogICAgaWYgKHdpZHRoID09PSAiIikgewogICAgICBpZiAobm9kZS5tYXhXID09PSAwKSB7CiAgICAgICAgY29uc3QgcGFyZW50ID0gbm9kZVtfeGZhX29iamVjdC4kZ2V0U3ViZm9ybVBhcmVudF0oKTsKICAgICAgICBpZiAocGFyZW50LmxheW91dCA9PT0gInBvc2l0aW9uIiAmJiBwYXJlbnQudyAhPT0gIiIpIHsKICAgICAgICAgIHdpZHRoID0gMDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgd2lkdGggPSBub2RlLm1pblc7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHdpZHRoID0gTWF0aC5taW4obm9kZS5tYXhXLCBhdmFpbGFibGVTcGFjZS53aWR0aCk7CiAgICAgIH0KICAgICAgaHRtbC5hdHRyaWJ1dGVzLnN0eWxlLndpZHRoID0gbWVhc3VyZVRvU3RyaW5nKHdpZHRoKTsKICAgIH0KICAgIGxldCBoZWlnaHQgPSBub2RlLmg7CiAgICBpZiAoaGVpZ2h0ID09PSAiIikgewogICAgICBpZiAobm9kZS5tYXhIID09PSAwKSB7CiAgICAgICAgY29uc3QgcGFyZW50ID0gbm9kZVtfeGZhX29iamVjdC4kZ2V0U3ViZm9ybVBhcmVudF0oKTsKICAgICAgICBpZiAocGFyZW50LmxheW91dCA9PT0gInBvc2l0aW9uIiAmJiBwYXJlbnQuaCAhPT0gIiIpIHsKICAgICAgICAgIGhlaWdodCA9IDA7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGhlaWdodCA9IG5vZGUubWluSDsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaGVpZ2h0ID0gTWF0aC5taW4obm9kZS5tYXhILCBhdmFpbGFibGVTcGFjZS5oZWlnaHQpOwogICAgICB9CiAgICAgIGh0bWwuYXR0cmlidXRlcy5zdHlsZS5oZWlnaHQgPSBtZWFzdXJlVG9TdHJpbmcoaGVpZ2h0KTsKICAgIH0KICAgIGJib3ggPSBbbm9kZS54LCBub2RlLnksIHdpZHRoLCBoZWlnaHRdOwogIH0KICByZXR1cm4gYmJveDsKfQpmdW5jdGlvbiBmaXhEaW1lbnNpb25zKG5vZGUpIHsKICBjb25zdCBwYXJlbnQgPSBub2RlW194ZmFfb2JqZWN0LiRnZXRTdWJmb3JtUGFyZW50XSgpOwogIGlmIChwYXJlbnQubGF5b3V0ICYmIHBhcmVudC5sYXlvdXQuaW5jbHVkZXMoInJvdyIpKSB7CiAgICBjb25zdCBleHRyYSA9IHBhcmVudFtfeGZhX29iamVjdC4kZXh0cmFdOwogICAgY29uc3QgY29sU3BhbiA9IG5vZGUuY29sU3BhbjsKICAgIGxldCB3aWR0aDsKICAgIGlmIChjb2xTcGFuID09PSAtMSkgewogICAgICB3aWR0aCA9IGV4dHJhLmNvbHVtbldpZHRocy5zbGljZShleHRyYS5jdXJyZW50Q29sdW1uKS5yZWR1Y2UoKGEsIHcpID0+IGEgKyB3LCAwKTsKICAgIH0gZWxzZSB7CiAgICAgIHdpZHRoID0gZXh0cmEuY29sdW1uV2lkdGhzLnNsaWNlKGV4dHJhLmN1cnJlbnRDb2x1bW4sIGV4dHJhLmN1cnJlbnRDb2x1bW4gKyBjb2xTcGFuKS5yZWR1Y2UoKGEsIHcpID0+IGEgKyB3LCAwKTsKICAgIH0KICAgIGlmICghaXNOYU4od2lkdGgpKSB7CiAgICAgIG5vZGUudyA9IHdpZHRoOwogICAgfQogIH0KICBpZiAocGFyZW50LmxheW91dCAmJiBwYXJlbnQubGF5b3V0ICE9PSAicG9zaXRpb24iKSB7CiAgICBub2RlLnggPSBub2RlLnkgPSAwOwogIH0KICBpZiAobm9kZS5sYXlvdXQgPT09ICJ0YWJsZSIpIHsKICAgIGlmIChub2RlLncgPT09ICIiICYmIEFycmF5LmlzQXJyYXkobm9kZS5jb2x1bW5XaWR0aHMpKSB7CiAgICAgIG5vZGUudyA9IG5vZGUuY29sdW1uV2lkdGhzLnJlZHVjZSgoYSwgeCkgPT4gYSArIHgsIDApOwogICAgfQogIH0KfQpmdW5jdGlvbiBsYXlvdXRDbGFzcyhub2RlKSB7CiAgc3dpdGNoIChub2RlLmxheW91dCkgewogICAgY2FzZSAicG9zaXRpb24iOgogICAgICByZXR1cm4gInhmYVBvc2l0aW9uIjsKICAgIGNhc2UgImxyLXRiIjoKICAgICAgcmV0dXJuICJ4ZmFMclRiIjsKICAgIGNhc2UgInJsLXJvdyI6CiAgICAgIHJldHVybiAieGZhUmxSb3ciOwogICAgY2FzZSAicmwtdGIiOgogICAgICByZXR1cm4gInhmYVJsVGIiOwogICAgY2FzZSAicm93IjoKICAgICAgcmV0dXJuICJ4ZmFSb3ciOwogICAgY2FzZSAidGFibGUiOgogICAgICByZXR1cm4gInhmYVRhYmxlIjsKICAgIGNhc2UgInRiIjoKICAgICAgcmV0dXJuICJ4ZmFUYiI7CiAgICBkZWZhdWx0OgogICAgICByZXR1cm4gInhmYVBvc2l0aW9uIjsKICB9Cn0KZnVuY3Rpb24gdG9TdHlsZShub2RlKSB7CiAgY29uc3Qgc3R5bGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBuYW1lcyA9IG5ldyBBcnJheShfbGVuID4gMSA/IF9sZW4gLSAxIDogMCksIF9rZXkgPSAxOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7CiAgICBuYW1lc1tfa2V5IC0gMV0gPSBhcmd1bWVudHNbX2tleV07CiAgfQogIGZvciAoY29uc3QgbmFtZSBvZiBuYW1lcykgewogICAgY29uc3QgdmFsdWUgPSBub2RlW25hbWVdOwogICAgaWYgKHZhbHVlID09PSBudWxsKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgaWYgKGNvbnZlcnRlcnMuaGFzT3duUHJvcGVydHkobmFtZSkpIHsKICAgICAgY29udmVydGVyc1tuYW1lXShub2RlLCBzdHlsZSk7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgX3hmYV9vYmplY3QuWEZBT2JqZWN0KSB7CiAgICAgIGNvbnN0IG5ld1N0eWxlID0gdmFsdWVbX3hmYV9vYmplY3QuJHRvU3R5bGVdKCk7CiAgICAgIGlmIChuZXdTdHlsZSkgewogICAgICAgIE9iamVjdC5hc3NpZ24oc3R5bGUsIG5ld1N0eWxlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICAoMCwgX3V0aWwud2FybikoYChERUJVRykgLSBYRkEgLSBzdHlsZSBmb3IgJHtuYW1lfSBub3QgaW1wbGVtZW50ZWQgeWV0YCk7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIHN0eWxlOwp9CmZ1bmN0aW9uIGNyZWF0ZVdyYXBwZXIobm9kZSwgaHRtbCkgewogIGNvbnN0IHsKICAgIGF0dHJpYnV0ZXMKICB9ID0gaHRtbDsKICBjb25zdCB7CiAgICBzdHlsZQogIH0gPSBhdHRyaWJ1dGVzOwogIGNvbnN0IHdyYXBwZXIgPSB7CiAgICBuYW1lOiAiZGl2IiwKICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgY2xhc3M6IFsieGZhV3JhcHBlciJdLAogICAgICBzdHlsZTogT2JqZWN0LmNyZWF0ZShudWxsKQogICAgfSwKICAgIGNoaWxkcmVuOiBbXQogIH07CiAgYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFXcmFwcGVkIik7CiAgaWYgKG5vZGUuYm9yZGVyKSB7CiAgICBjb25zdCB7CiAgICAgIHdpZHRocywKICAgICAgaW5zZXRzCiAgICB9ID0gbm9kZS5ib3JkZXJbX3hmYV9vYmplY3QuJGV4dHJhXTsKICAgIGxldCB3aWR0aCwgaGVpZ2h0OwogICAgbGV0IHRvcCA9IGluc2V0c1swXTsKICAgIGxldCBsZWZ0ID0gaW5zZXRzWzNdOwogICAgY29uc3QgaW5zZXRzSCA9IGluc2V0c1swXSArIGluc2V0c1syXTsKICAgIGNvbnN0IGluc2V0c1cgPSBpbnNldHNbMV0gKyBpbnNldHNbM107CiAgICBzd2l0Y2ggKG5vZGUuYm9yZGVyLmhhbmQpIHsKICAgICAgY2FzZSAiZXZlbiI6CiAgICAgICAgdG9wIC09IHdpZHRoc1swXSAvIDI7CiAgICAgICAgbGVmdCAtPSB3aWR0aHNbM10gLyAyOwogICAgICAgIHdpZHRoID0gYGNhbGMoMTAwJSArICR7KHdpZHRoc1sxXSArIHdpZHRoc1szXSkgLyAyIC0gaW5zZXRzV31weClgOwogICAgICAgIGhlaWdodCA9IGBjYWxjKDEwMCUgKyAkeyh3aWR0aHNbMF0gKyB3aWR0aHNbMl0pIC8gMiAtIGluc2V0c0h9cHgpYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAibGVmdCI6CiAgICAgICAgdG9wIC09IHdpZHRoc1swXTsKICAgICAgICBsZWZ0IC09IHdpZHRoc1szXTsKICAgICAgICB3aWR0aCA9IGBjYWxjKDEwMCUgKyAke3dpZHRoc1sxXSArIHdpZHRoc1szXSAtIGluc2V0c1d9cHgpYDsKICAgICAgICBoZWlnaHQgPSBgY2FsYygxMDAlICsgJHt3aWR0aHNbMF0gKyB3aWR0aHNbMl0gLSBpbnNldHNIfXB4KWA7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgInJpZ2h0IjoKICAgICAgICB3aWR0aCA9IGluc2V0c1cgPyBgY2FsYygxMDAlIC0gJHtpbnNldHNXfXB4KWAgOiAiMTAwJSI7CiAgICAgICAgaGVpZ2h0ID0gaW5zZXRzSCA/IGBjYWxjKDEwMCUgLSAke2luc2V0c0h9cHgpYCA6ICIxMDAlIjsKICAgICAgICBicmVhazsKICAgIH0KICAgIGNvbnN0IGNsYXNzTmFtZXMgPSBbInhmYUJvcmRlciJdOwogICAgaWYgKGlzUHJpbnRPbmx5KG5vZGUuYm9yZGVyKSkgewogICAgICBjbGFzc05hbWVzLnB1c2goInhmYVByaW50T25seSIpOwogICAgfQogICAgY29uc3QgYm9yZGVyID0gewogICAgICBuYW1lOiAiZGl2IiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGNsYXNzOiBjbGFzc05hbWVzLAogICAgICAgIHN0eWxlOiB7CiAgICAgICAgICB0b3A6IGAke3RvcH1weGAsCiAgICAgICAgICBsZWZ0OiBgJHtsZWZ0fXB4YCwKICAgICAgICAgIHdpZHRoLAogICAgICAgICAgaGVpZ2h0CiAgICAgICAgfQogICAgICB9LAogICAgICBjaGlsZHJlbjogW10KICAgIH07CiAgICBmb3IgKGNvbnN0IGtleSBvZiBbImJvcmRlciIsICJib3JkZXJXaWR0aCIsICJib3JkZXJDb2xvciIsICJib3JkZXJSYWRpdXMiLCAiYm9yZGVyU3R5bGUiXSkgewogICAgICBpZiAoc3R5bGVba2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgYm9yZGVyLmF0dHJpYnV0ZXMuc3R5bGVba2V5XSA9IHN0eWxlW2tleV07CiAgICAgICAgZGVsZXRlIHN0eWxlW2tleV07CiAgICAgIH0KICAgIH0KICAgIHdyYXBwZXIuY2hpbGRyZW4ucHVzaChib3JkZXIsIGh0bWwpOwogIH0gZWxzZSB7CiAgICB3cmFwcGVyLmNoaWxkcmVuLnB1c2goaHRtbCk7CiAgfQogIGZvciAoY29uc3Qga2V5IG9mIFsiYmFja2dyb3VuZCIsICJiYWNrZ3JvdW5kQ2xpcCIsICJ0b3AiLCAibGVmdCIsICJ3aWR0aCIsICJoZWlnaHQiLCAibWluV2lkdGgiLCAibWluSGVpZ2h0IiwgIm1heFdpZHRoIiwgIm1heEhlaWdodCIsICJ0cmFuc2Zvcm0iLCAidHJhbnNmb3JtT3JpZ2luIiwgInZpc2liaWxpdHkiXSkgewogICAgaWYgKHN0eWxlW2tleV0gIT09IHVuZGVmaW5lZCkgewogICAgICB3cmFwcGVyLmF0dHJpYnV0ZXMuc3R5bGVba2V5XSA9IHN0eWxlW2tleV07CiAgICAgIGRlbGV0ZSBzdHlsZVtrZXldOwogICAgfQogIH0KICBpZiAoc3R5bGUucG9zaXRpb24gPT09ICJhYnNvbHV0ZSIpIHsKICAgIHdyYXBwZXIuYXR0cmlidXRlcy5zdHlsZS5wb3NpdGlvbiA9ICJhYnNvbHV0ZSI7CiAgfSBlbHNlIHsKICAgIHdyYXBwZXIuYXR0cmlidXRlcy5zdHlsZS5wb3NpdGlvbiA9ICJyZWxhdGl2ZSI7CiAgfQogIGRlbGV0ZSBzdHlsZS5wb3NpdGlvbjsKICBpZiAoc3R5bGUuYWxpZ25TZWxmKSB7CiAgICB3cmFwcGVyLmF0dHJpYnV0ZXMuc3R5bGUuYWxpZ25TZWxmID0gc3R5bGUuYWxpZ25TZWxmOwogICAgZGVsZXRlIHN0eWxlLmFsaWduU2VsZjsKICB9CiAgcmV0dXJuIHdyYXBwZXI7Cn0KZnVuY3Rpb24gZml4VGV4dEluZGVudChzdHlsZXMpIHsKICBjb25zdCBpbmRlbnQgPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShzdHlsZXMudGV4dEluZGVudCwgIjBweCIpOwogIGlmIChpbmRlbnQgPj0gMCkgewogICAgcmV0dXJuOwogIH0KICBjb25zdCBhbGlnbiA9IHN0eWxlcy50ZXh0QWxpZ24gPT09ICJyaWdodCIgPyAicmlnaHQiIDogImxlZnQiOwogIGNvbnN0IG5hbWUgPSAicGFkZGluZyIgKyAoYWxpZ24gPT09ICJsZWZ0IiA/ICJMZWZ0IiA6ICJSaWdodCIpOwogIGNvbnN0IHBhZGRpbmcgPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KShzdHlsZXNbbmFtZV0sICIwcHgiKTsKICBzdHlsZXNbbmFtZV0gPSBgJHtwYWRkaW5nIC0gaW5kZW50fXB4YDsKfQpmdW5jdGlvbiBzZXRBY2Nlc3Mobm9kZSwgY2xhc3NOYW1lcykgewogIHN3aXRjaCAobm9kZS5hY2Nlc3MpIHsKICAgIGNhc2UgIm5vbkludGVyYWN0aXZlIjoKICAgICAgY2xhc3NOYW1lcy5wdXNoKCJ4ZmFOb25JbnRlcmFjdGl2ZSIpOwogICAgICBicmVhazsKICAgIGNhc2UgInJlYWRPbmx5IjoKICAgICAgY2xhc3NOYW1lcy5wdXNoKCJ4ZmFSZWFkT25seSIpOwogICAgICBicmVhazsKICAgIGNhc2UgInByb3RlY3RlZCI6CiAgICAgIGNsYXNzTmFtZXMucHVzaCgieGZhRGlzYWJsZWQiKTsKICAgICAgYnJlYWs7CiAgfQp9CmZ1bmN0aW9uIGlzUHJpbnRPbmx5KG5vZGUpIHsKICByZXR1cm4gbm9kZS5yZWxldmFudC5sZW5ndGggPiAwICYmICFub2RlLnJlbGV2YW50WzBdLmV4Y2x1ZGVkICYmIG5vZGUucmVsZXZhbnRbMF0udmlld25hbWUgPT09ICJwcmludCI7Cn0KZnVuY3Rpb24gZ2V0Q3VycmVudFBhcmEobm9kZSkgewogIGNvbnN0IHN0YWNrID0gbm9kZVtfeGZhX29iamVjdC4kZ2V0VGVtcGxhdGVSb290XSgpW194ZmFfb2JqZWN0LiRleHRyYV0ucGFyYVN0YWNrOwogIHJldHVybiBzdGFjay5sZW5ndGggPyBzdGFjay5hdCgtMSkgOiBudWxsOwp9CmZ1bmN0aW9uIHNldFBhcmEobm9kZSwgbm9kZVN0eWxlLCB2YWx1ZSkgewogIGlmICh2YWx1ZS5hdHRyaWJ1dGVzLmNsYXNzICYmIHZhbHVlLmF0dHJpYnV0ZXMuY2xhc3MuaW5jbHVkZXMoInhmYVJpY2giKSkgewogICAgaWYgKG5vZGVTdHlsZSkgewogICAgICBpZiAobm9kZS5oID09PSAiIikgewogICAgICAgIG5vZGVTdHlsZS5oZWlnaHQgPSAiYXV0byI7CiAgICAgIH0KICAgICAgaWYgKG5vZGUudyA9PT0gIiIpIHsKICAgICAgICBub2RlU3R5bGUud2lkdGggPSAiYXV0byI7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHBhcmEgPSBnZXRDdXJyZW50UGFyYShub2RlKTsKICAgIGlmIChwYXJhKSB7CiAgICAgIGNvbnN0IHZhbHVlU3R5bGUgPSB2YWx1ZS5hdHRyaWJ1dGVzLnN0eWxlOwogICAgICB2YWx1ZVN0eWxlLmRpc3BsYXkgPSAiZmxleCI7CiAgICAgIHZhbHVlU3R5bGUuZmxleERpcmVjdGlvbiA9ICJjb2x1bW4iOwogICAgICBzd2l0Y2ggKHBhcmEudkFsaWduKSB7CiAgICAgICAgY2FzZSAidG9wIjoKICAgICAgICAgIHZhbHVlU3R5bGUuanVzdGlmeUNvbnRlbnQgPSAic3RhcnQiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiYm90dG9tIjoKICAgICAgICAgIHZhbHVlU3R5bGUuanVzdGlmeUNvbnRlbnQgPSAiZW5kIjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm1pZGRsZSI6CiAgICAgICAgICB2YWx1ZVN0eWxlLmp1c3RpZnlDb250ZW50ID0gImNlbnRlciI7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBjb25zdCBwYXJhU3R5bGUgPSBwYXJhW194ZmFfb2JqZWN0LiR0b1N0eWxlXSgpOwogICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgT2JqZWN0LmVudHJpZXMocGFyYVN0eWxlKSkgewogICAgICAgIGlmICghKGtleSBpbiB2YWx1ZVN0eWxlKSkgewogICAgICAgICAgdmFsdWVTdHlsZVtrZXldID0gdmFsOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KfQpmdW5jdGlvbiBzZXRGb250RmFtaWx5KHhmYUZvbnQsIG5vZGUsIGZvbnRGaW5kZXIsIHN0eWxlKSB7CiAgaWYgKCFmb250RmluZGVyKSB7CiAgICBkZWxldGUgc3R5bGUuZm9udEZhbWlseTsKICAgIHJldHVybjsKICB9CiAgY29uc3QgbmFtZSA9ICgwLCBfdXRpbHMuc3RyaXBRdW90ZXMpKHhmYUZvbnQudHlwZWZhY2UpOwogIHN0eWxlLmZvbnRGYW1pbHkgPSBgIiR7bmFtZX0iYDsKICBjb25zdCB0eXBlZmFjZSA9IGZvbnRGaW5kZXIuZmluZChuYW1lKTsKICBpZiAodHlwZWZhY2UpIHsKICAgIGNvbnN0IHsKICAgICAgZm9udEZhbWlseQogICAgfSA9IHR5cGVmYWNlLnJlZ3VsYXIuY3NzRm9udEluZm87CiAgICBpZiAoZm9udEZhbWlseSAhPT0gbmFtZSkgewogICAgICBzdHlsZS5mb250RmFtaWx5ID0gYCIke2ZvbnRGYW1pbHl9ImA7CiAgICB9CiAgICBjb25zdCBwYXJhID0gZ2V0Q3VycmVudFBhcmEobm9kZSk7CiAgICBpZiAocGFyYSAmJiBwYXJhLmxpbmVIZWlnaHQgIT09ICIiKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChzdHlsZS5saW5lSGVpZ2h0KSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHBkZkZvbnQgPSAoMCwgX2ZvbnRzLnNlbGVjdEZvbnQpKHhmYUZvbnQsIHR5cGVmYWNlKTsKICAgIGlmIChwZGZGb250KSB7CiAgICAgIHN0eWxlLmxpbmVIZWlnaHQgPSBNYXRoLm1heCgxLjIsIHBkZkZvbnQubGluZUhlaWdodCk7CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGZpeFVSTChzdHIpIHsKICBjb25zdCBhYnNvbHV0ZVVybCA9ICgwLCBfdXRpbC5jcmVhdGVWYWxpZEFic29sdXRlVXJsKShzdHIsIG51bGwsIHsKICAgIGFkZERlZmF1bHRQcm90b2NvbDogdHJ1ZSwKICAgIHRyeUNvbnZlcnRFbmNvZGluZzogdHJ1ZQogIH0pOwogIHJldHVybiBhYnNvbHV0ZVVybCA/IGFic29sdXRlVXJsLmhyZWYgOiBudWxsOwp9CgovKioqLyB9KSwKLyogMjIwICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5Gb250RmluZGVyID0gdm9pZCAwOwpleHBvcnRzLmdldE1ldHJpY3MgPSBnZXRNZXRyaWNzOwpleHBvcnRzLnNlbGVjdEZvbnQgPSBzZWxlY3RGb250Owp2YXIgX3hmYV9vYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxMik7CnZhciBfdXRpbHMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxMyk7CnZhciBfdXRpbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMik7CmNsYXNzIEZvbnRGaW5kZXIgewogIGNvbnN0cnVjdG9yKHBkZkZvbnRzKSB7CiAgICB0aGlzLmZvbnRzID0gbmV3IE1hcCgpOwogICAgdGhpcy5jYWNoZSA9IG5ldyBNYXAoKTsKICAgIHRoaXMud2FybmVkID0gbmV3IFNldCgpOwogICAgdGhpcy5kZWZhdWx0Rm9udCA9IG51bGw7CiAgICB0aGlzLmFkZChwZGZGb250cyk7CiAgfQogIGFkZChwZGZGb250cykgewogICAgbGV0IHJlYWxseU1pc3NpbmdGb250cyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogbnVsbDsKICAgIGZvciAoY29uc3QgcGRmRm9udCBvZiBwZGZGb250cykgewogICAgICB0aGlzLmFkZFBkZkZvbnQocGRmRm9udCk7CiAgICB9CiAgICBmb3IgKGNvbnN0IHBkZkZvbnQgb2YgdGhpcy5mb250cy52YWx1ZXMoKSkgewogICAgICBpZiAoIXBkZkZvbnQucmVndWxhcikgewogICAgICAgIHBkZkZvbnQucmVndWxhciA9IHBkZkZvbnQuaXRhbGljIHx8IHBkZkZvbnQuYm9sZCB8fCBwZGZGb250LmJvbGRpdGFsaWM7CiAgICAgIH0KICAgIH0KICAgIGlmICghcmVhbGx5TWlzc2luZ0ZvbnRzIHx8IHJlYWxseU1pc3NpbmdGb250cy5zaXplID09PSAwKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG15cmlhZCA9IHRoaXMuZm9udHMuZ2V0KCJQZGZKUy1GYWxsYmFjay1QZGZKUy1YRkEiKTsKICAgIGZvciAoY29uc3QgbWlzc2luZyBvZiByZWFsbHlNaXNzaW5nRm9udHMpIHsKICAgICAgdGhpcy5mb250cy5zZXQobWlzc2luZywgbXlyaWFkKTsKICAgIH0KICB9CiAgYWRkUGRmRm9udChwZGZGb250KSB7CiAgICBjb25zdCBjc3NGb250SW5mbyA9IHBkZkZvbnQuY3NzRm9udEluZm87CiAgICBjb25zdCBuYW1lID0gY3NzRm9udEluZm8uZm9udEZhbWlseTsKICAgIGxldCBmb250ID0gdGhpcy5mb250cy5nZXQobmFtZSk7CiAgICBpZiAoIWZvbnQpIHsKICAgICAgZm9udCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIHRoaXMuZm9udHMuc2V0KG5hbWUsIGZvbnQpOwogICAgICBpZiAoIXRoaXMuZGVmYXVsdEZvbnQpIHsKICAgICAgICB0aGlzLmRlZmF1bHRGb250ID0gZm9udDsKICAgICAgfQogICAgfQogICAgbGV0IHByb3BlcnR5ID0gIiI7CiAgICBjb25zdCBmb250V2VpZ2h0ID0gcGFyc2VGbG9hdChjc3NGb250SW5mby5mb250V2VpZ2h0KTsKICAgIGlmIChwYXJzZUZsb2F0KGNzc0ZvbnRJbmZvLml0YWxpY0FuZ2xlKSAhPT0gMCkgewogICAgICBwcm9wZXJ0eSA9IGZvbnRXZWlnaHQgPj0gNzAwID8gImJvbGRpdGFsaWMiIDogIml0YWxpYyI7CiAgICB9IGVsc2UgaWYgKGZvbnRXZWlnaHQgPj0gNzAwKSB7CiAgICAgIHByb3BlcnR5ID0gImJvbGQiOwogICAgfQogICAgaWYgKCFwcm9wZXJ0eSkgewogICAgICBpZiAocGRmRm9udC5uYW1lLmluY2x1ZGVzKCJCb2xkIikgfHwgcGRmRm9udC5wc05hbWUgJiYgcGRmRm9udC5wc05hbWUuaW5jbHVkZXMoIkJvbGQiKSkgewogICAgICAgIHByb3BlcnR5ID0gImJvbGQiOwogICAgICB9CiAgICAgIGlmIChwZGZGb250Lm5hbWUuaW5jbHVkZXMoIkl0YWxpYyIpIHx8IHBkZkZvbnQubmFtZS5lbmRzV2l0aCgiSXQiKSB8fCBwZGZGb250LnBzTmFtZSAmJiAocGRmRm9udC5wc05hbWUuaW5jbHVkZXMoIkl0YWxpYyIpIHx8IHBkZkZvbnQucHNOYW1lLmVuZHNXaXRoKCJJdCIpKSkgewogICAgICAgIHByb3BlcnR5ICs9ICJpdGFsaWMiOwogICAgICB9CiAgICB9CiAgICBpZiAoIXByb3BlcnR5KSB7CiAgICAgIHByb3BlcnR5ID0gInJlZ3VsYXIiOwogICAgfQogICAgZm9udFtwcm9wZXJ0eV0gPSBwZGZGb250OwogIH0KICBnZXREZWZhdWx0KCkgewogICAgcmV0dXJuIHRoaXMuZGVmYXVsdEZvbnQ7CiAgfQogIGZpbmQoZm9udE5hbWUpIHsKICAgIGxldCBtdXN0V2FybiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogdHJ1ZTsKICAgIGxldCBmb250ID0gdGhpcy5mb250cy5nZXQoZm9udE5hbWUpIHx8IHRoaXMuY2FjaGUuZ2V0KGZvbnROYW1lKTsKICAgIGlmIChmb250KSB7CiAgICAgIHJldHVybiBmb250OwogICAgfQogICAgY29uc3QgcGF0dGVybiA9IC8sfC18X3wgfGJvbGRpdGFsaWN8Ym9sZHxpdGFsaWN8cmVndWxhcnxpdC9naTsKICAgIGxldCBuYW1lID0gZm9udE5hbWUucmVwbGFjZUFsbChwYXR0ZXJuLCAiIik7CiAgICBmb250ID0gdGhpcy5mb250cy5nZXQobmFtZSk7CiAgICBpZiAoZm9udCkgewogICAgICB0aGlzLmNhY2hlLnNldChmb250TmFtZSwgZm9udCk7CiAgICAgIHJldHVybiBmb250OwogICAgfQogICAgbmFtZSA9IG5hbWUudG9Mb3dlckNhc2UoKTsKICAgIGNvbnN0IG1heWJlID0gW107CiAgICBmb3IgKGNvbnN0IFtmYW1pbHksIHBkZkZvbnRdIG9mIHRoaXMuZm9udHMuZW50cmllcygpKSB7CiAgICAgIGlmIChmYW1pbHkucmVwbGFjZUFsbChwYXR0ZXJuLCAiIikudG9Mb3dlckNhc2UoKS5zdGFydHNXaXRoKG5hbWUpKSB7CiAgICAgICAgbWF5YmUucHVzaChwZGZGb250KTsKICAgICAgfQogICAgfQogICAgaWYgKG1heWJlLmxlbmd0aCA9PT0gMCkgewogICAgICBmb3IgKGNvbnN0IFssIHBkZkZvbnRdIG9mIHRoaXMuZm9udHMuZW50cmllcygpKSB7CiAgICAgICAgaWYgKHBkZkZvbnQucmVndWxhci5uYW1lICYmIHBkZkZvbnQucmVndWxhci5uYW1lLnJlcGxhY2VBbGwocGF0dGVybiwgIiIpLnRvTG93ZXJDYXNlKCkuc3RhcnRzV2l0aChuYW1lKSkgewogICAgICAgICAgbWF5YmUucHVzaChwZGZGb250KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChtYXliZS5sZW5ndGggPT09IDApIHsKICAgICAgbmFtZSA9IG5hbWUucmVwbGFjZUFsbCgvcHNtdHxtdC9naSwgIiIpOwogICAgICBmb3IgKGNvbnN0IFtmYW1pbHksIHBkZkZvbnRdIG9mIHRoaXMuZm9udHMuZW50cmllcygpKSB7CiAgICAgICAgaWYgKGZhbWlseS5yZXBsYWNlQWxsKHBhdHRlcm4sICIiKS50b0xvd2VyQ2FzZSgpLnN0YXJ0c1dpdGgobmFtZSkpIHsKICAgICAgICAgIG1heWJlLnB1c2gocGRmRm9udCk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAobWF5YmUubGVuZ3RoID09PSAwKSB7CiAgICAgIGZvciAoY29uc3QgcGRmRm9udCBvZiB0aGlzLmZvbnRzLnZhbHVlcygpKSB7CiAgICAgICAgaWYgKHBkZkZvbnQucmVndWxhci5uYW1lICYmIHBkZkZvbnQucmVndWxhci5uYW1lLnJlcGxhY2VBbGwocGF0dGVybiwgIiIpLnRvTG93ZXJDYXNlKCkuc3RhcnRzV2l0aChuYW1lKSkgewogICAgICAgICAgbWF5YmUucHVzaChwZGZGb250KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChtYXliZS5sZW5ndGggPj0gMSkgewogICAgICBpZiAobWF5YmUubGVuZ3RoICE9PSAxICYmIG11c3RXYXJuKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKGBYRkEgLSBUb28gbWFueSBjaG9pY2VzIHRvIGd1ZXNzIHRoZSBjb3JyZWN0IGZvbnQ6ICR7Zm9udE5hbWV9YCk7CiAgICAgIH0KICAgICAgdGhpcy5jYWNoZS5zZXQoZm9udE5hbWUsIG1heWJlWzBdKTsKICAgICAgcmV0dXJuIG1heWJlWzBdOwogICAgfQogICAgaWYgKG11c3RXYXJuICYmICF0aGlzLndhcm5lZC5oYXMoZm9udE5hbWUpKSB7CiAgICAgIHRoaXMud2FybmVkLmFkZChmb250TmFtZSk7CiAgICAgICgwLCBfdXRpbC53YXJuKShgWEZBIC0gQ2Fubm90IGZpbmQgdGhlIGZvbnQ6ICR7Zm9udE5hbWV9YCk7CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9Cn0KZXhwb3J0cy5Gb250RmluZGVyID0gRm9udEZpbmRlcjsKZnVuY3Rpb24gc2VsZWN0Rm9udCh4ZmFGb250LCB0eXBlZmFjZSkgewogIGlmICh4ZmFGb250LnBvc3R1cmUgPT09ICJpdGFsaWMiKSB7CiAgICBpZiAoeGZhRm9udC53ZWlnaHQgPT09ICJib2xkIikgewogICAgICByZXR1cm4gdHlwZWZhY2UuYm9sZGl0YWxpYzsKICAgIH0KICAgIHJldHVybiB0eXBlZmFjZS5pdGFsaWM7CiAgfSBlbHNlIGlmICh4ZmFGb250LndlaWdodCA9PT0gImJvbGQiKSB7CiAgICByZXR1cm4gdHlwZWZhY2UuYm9sZDsKICB9CiAgcmV0dXJuIHR5cGVmYWNlLnJlZ3VsYXI7Cn0KZnVuY3Rpb24gZ2V0TWV0cmljcyh4ZmFGb250KSB7CiAgbGV0IHJlYWwgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IGZhbHNlOwogIGxldCBwZGZGb250ID0gbnVsbDsKICBpZiAoeGZhRm9udCkgewogICAgY29uc3QgbmFtZSA9ICgwLCBfdXRpbHMuc3RyaXBRdW90ZXMpKHhmYUZvbnQudHlwZWZhY2UpOwogICAgY29uc3QgdHlwZWZhY2UgPSB4ZmFGb250W194ZmFfb2JqZWN0LiRnbG9iYWxEYXRhXS5mb250RmluZGVyLmZpbmQobmFtZSk7CiAgICBwZGZGb250ID0gc2VsZWN0Rm9udCh4ZmFGb250LCB0eXBlZmFjZSk7CiAgfQogIGlmICghcGRmRm9udCkgewogICAgcmV0dXJuIHsKICAgICAgbGluZUhlaWdodDogMTIsCiAgICAgIGxpbmVHYXA6IDIsCiAgICAgIGxpbmVOb0dhcDogMTAKICAgIH07CiAgfQogIGNvbnN0IHNpemUgPSB4ZmFGb250LnNpemUgfHwgMTA7CiAgY29uc3QgbGluZUhlaWdodCA9IHBkZkZvbnQubGluZUhlaWdodCA/IE1hdGgubWF4KHJlYWwgPyAwIDogMS4yLCBwZGZGb250LmxpbmVIZWlnaHQpIDogMS4yOwogIGNvbnN0IGxpbmVHYXAgPSBwZGZGb250LmxpbmVHYXAgPT09IHVuZGVmaW5lZCA/IDAuMiA6IHBkZkZvbnQubGluZUdhcDsKICByZXR1cm4gewogICAgbGluZUhlaWdodDogbGluZUhlaWdodCAqIHNpemUsCiAgICBsaW5lR2FwOiBsaW5lR2FwICogc2l6ZSwKICAgIGxpbmVOb0dhcDogTWF0aC5tYXgoMSwgbGluZUhlaWdodCAtIGxpbmVHYXApICogc2l6ZQogIH07Cn0KCi8qKiovIH0pLAovKiAyMjEgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlRleHRNZWFzdXJlID0gdm9pZCAwOwp2YXIgX2ZvbnRzID0gX193X3BkZmpzX3JlcXVpcmVfXygyMjApOwpjb25zdCBXSURUSF9GQUNUT1IgPSAxLjAyOwpjbGFzcyBGb250SW5mbyB7CiAgY29uc3RydWN0b3IoeGZhRm9udCwgbWFyZ2luLCBsaW5lSGVpZ2h0LCBmb250RmluZGVyKSB7CiAgICB0aGlzLmxpbmVIZWlnaHQgPSBsaW5lSGVpZ2h0OwogICAgdGhpcy5wYXJhTWFyZ2luID0gbWFyZ2luIHx8IHsKICAgICAgdG9wOiAwLAogICAgICBib3R0b206IDAsCiAgICAgIGxlZnQ6IDAsCiAgICAgIHJpZ2h0OiAwCiAgICB9OwogICAgaWYgKCF4ZmFGb250KSB7CiAgICAgIFt0aGlzLnBkZkZvbnQsIHRoaXMueGZhRm9udF0gPSB0aGlzLmRlZmF1bHRGb250KGZvbnRGaW5kZXIpOwogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLnhmYUZvbnQgPSB7CiAgICAgIHR5cGVmYWNlOiB4ZmFGb250LnR5cGVmYWNlLAogICAgICBwb3N0dXJlOiB4ZmFGb250LnBvc3R1cmUsCiAgICAgIHdlaWdodDogeGZhRm9udC53ZWlnaHQsCiAgICAgIHNpemU6IHhmYUZvbnQuc2l6ZSwKICAgICAgbGV0dGVyU3BhY2luZzogeGZhRm9udC5sZXR0ZXJTcGFjaW5nCiAgICB9OwogICAgY29uc3QgdHlwZWZhY2UgPSBmb250RmluZGVyLmZpbmQoeGZhRm9udC50eXBlZmFjZSk7CiAgICBpZiAoIXR5cGVmYWNlKSB7CiAgICAgIFt0aGlzLnBkZkZvbnQsIHRoaXMueGZhRm9udF0gPSB0aGlzLmRlZmF1bHRGb250KGZvbnRGaW5kZXIpOwogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLnBkZkZvbnQgPSAoMCwgX2ZvbnRzLnNlbGVjdEZvbnQpKHhmYUZvbnQsIHR5cGVmYWNlKTsKICAgIGlmICghdGhpcy5wZGZGb250KSB7CiAgICAgIFt0aGlzLnBkZkZvbnQsIHRoaXMueGZhRm9udF0gPSB0aGlzLmRlZmF1bHRGb250KGZvbnRGaW5kZXIpOwogICAgfQogIH0KICBkZWZhdWx0Rm9udChmb250RmluZGVyKSB7CiAgICBjb25zdCBmb250ID0gZm9udEZpbmRlci5maW5kKCJIZWx2ZXRpY2EiLCBmYWxzZSkgfHwgZm9udEZpbmRlci5maW5kKCJNeXJpYWQgUHJvIiwgZmFsc2UpIHx8IGZvbnRGaW5kZXIuZmluZCgiQXJpYWwiLCBmYWxzZSkgfHwgZm9udEZpbmRlci5nZXREZWZhdWx0KCk7CiAgICBpZiAoZm9udCAmJiBmb250LnJlZ3VsYXIpIHsKICAgICAgY29uc3QgcGRmRm9udCA9IGZvbnQucmVndWxhcjsKICAgICAgY29uc3QgaW5mbyA9IHBkZkZvbnQuY3NzRm9udEluZm87CiAgICAgIGNvbnN0IHhmYUZvbnQgPSB7CiAgICAgICAgdHlwZWZhY2U6IGluZm8uZm9udEZhbWlseSwKICAgICAgICBwb3N0dXJlOiAibm9ybWFsIiwKICAgICAgICB3ZWlnaHQ6ICJub3JtYWwiLAogICAgICAgIHNpemU6IDEwLAogICAgICAgIGxldHRlclNwYWNpbmc6IDAKICAgICAgfTsKICAgICAgcmV0dXJuIFtwZGZGb250LCB4ZmFGb250XTsKICAgIH0KICAgIGNvbnN0IHhmYUZvbnQgPSB7CiAgICAgIHR5cGVmYWNlOiAiQ291cmllciIsCiAgICAgIHBvc3R1cmU6ICJub3JtYWwiLAogICAgICB3ZWlnaHQ6ICJub3JtYWwiLAogICAgICBzaXplOiAxMCwKICAgICAgbGV0dGVyU3BhY2luZzogMAogICAgfTsKICAgIHJldHVybiBbbnVsbCwgeGZhRm9udF07CiAgfQp9CmNsYXNzIEZvbnRTZWxlY3RvciB7CiAgY29uc3RydWN0b3IoZGVmYXVsdFhmYUZvbnQsIGRlZmF1bHRQYXJhTWFyZ2luLCBkZWZhdWx0TGluZUhlaWdodCwgZm9udEZpbmRlcikgewogICAgdGhpcy5mb250RmluZGVyID0gZm9udEZpbmRlcjsKICAgIHRoaXMuc3RhY2sgPSBbbmV3IEZvbnRJbmZvKGRlZmF1bHRYZmFGb250LCBkZWZhdWx0UGFyYU1hcmdpbiwgZGVmYXVsdExpbmVIZWlnaHQsIGZvbnRGaW5kZXIpXTsKICB9CiAgcHVzaERhdGEoeGZhRm9udCwgbWFyZ2luLCBsaW5lSGVpZ2h0KSB7CiAgICBjb25zdCBsYXN0Rm9udCA9IHRoaXMuc3RhY2suYXQoLTEpOwogICAgZm9yIChjb25zdCBuYW1lIG9mIFsidHlwZWZhY2UiLCAicG9zdHVyZSIsICJ3ZWlnaHQiLCAic2l6ZSIsICJsZXR0ZXJTcGFjaW5nIl0pIHsKICAgICAgaWYgKCF4ZmFGb250W25hbWVdKSB7CiAgICAgICAgeGZhRm9udFtuYW1lXSA9IGxhc3RGb250LnhmYUZvbnRbbmFtZV07CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgbmFtZSBvZiBbInRvcCIsICJib3R0b20iLCAibGVmdCIsICJyaWdodCJdKSB7CiAgICAgIGlmIChpc05hTihtYXJnaW5bbmFtZV0pKSB7CiAgICAgICAgbWFyZ2luW25hbWVdID0gbGFzdEZvbnQucGFyYU1hcmdpbltuYW1lXTsKICAgICAgfQogICAgfQogICAgY29uc3QgZm9udEluZm8gPSBuZXcgRm9udEluZm8oeGZhRm9udCwgbWFyZ2luLCBsaW5lSGVpZ2h0IHx8IGxhc3RGb250LmxpbmVIZWlnaHQsIHRoaXMuZm9udEZpbmRlcik7CiAgICBpZiAoIWZvbnRJbmZvLnBkZkZvbnQpIHsKICAgICAgZm9udEluZm8ucGRmRm9udCA9IGxhc3RGb250LnBkZkZvbnQ7CiAgICB9CiAgICB0aGlzLnN0YWNrLnB1c2goZm9udEluZm8pOwogIH0KICBwb3BGb250KCkgewogICAgdGhpcy5zdGFjay5wb3AoKTsKICB9CiAgdG9wRm9udCgpIHsKICAgIHJldHVybiB0aGlzLnN0YWNrLmF0KC0xKTsKICB9Cn0KY2xhc3MgVGV4dE1lYXN1cmUgewogIGNvbnN0cnVjdG9yKGRlZmF1bHRYZmFGb250LCBkZWZhdWx0UGFyYU1hcmdpbiwgZGVmYXVsdExpbmVIZWlnaHQsIGZvbnRzKSB7CiAgICB0aGlzLmdseXBocyA9IFtdOwogICAgdGhpcy5mb250U2VsZWN0b3IgPSBuZXcgRm9udFNlbGVjdG9yKGRlZmF1bHRYZmFGb250LCBkZWZhdWx0UGFyYU1hcmdpbiwgZGVmYXVsdExpbmVIZWlnaHQsIGZvbnRzKTsKICAgIHRoaXMuZXh0cmFIZWlnaHQgPSAwOwogIH0KICBwdXNoRGF0YSh4ZmFGb250LCBtYXJnaW4sIGxpbmVIZWlnaHQpIHsKICAgIHRoaXMuZm9udFNlbGVjdG9yLnB1c2hEYXRhKHhmYUZvbnQsIG1hcmdpbiwgbGluZUhlaWdodCk7CiAgfQogIHBvcEZvbnQoeGZhRm9udCkgewogICAgcmV0dXJuIHRoaXMuZm9udFNlbGVjdG9yLnBvcEZvbnQoKTsKICB9CiAgYWRkUGFyYSgpIHsKICAgIGNvbnN0IGxhc3RGb250ID0gdGhpcy5mb250U2VsZWN0b3IudG9wRm9udCgpOwogICAgdGhpcy5leHRyYUhlaWdodCArPSBsYXN0Rm9udC5wYXJhTWFyZ2luLnRvcCArIGxhc3RGb250LnBhcmFNYXJnaW4uYm90dG9tOwogIH0KICBhZGRTdHJpbmcoc3RyKSB7CiAgICBpZiAoIXN0cikgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBsYXN0Rm9udCA9IHRoaXMuZm9udFNlbGVjdG9yLnRvcEZvbnQoKTsKICAgIGNvbnN0IGZvbnRTaXplID0gbGFzdEZvbnQueGZhRm9udC5zaXplOwogICAgaWYgKGxhc3RGb250LnBkZkZvbnQpIHsKICAgICAgY29uc3QgbGV0dGVyU3BhY2luZyA9IGxhc3RGb250LnhmYUZvbnQubGV0dGVyU3BhY2luZzsKICAgICAgY29uc3QgcGRmRm9udCA9IGxhc3RGb250LnBkZkZvbnQ7CiAgICAgIGNvbnN0IGZvbnRMaW5lSGVpZ2h0ID0gcGRmRm9udC5saW5lSGVpZ2h0IHx8IDEuMjsKICAgICAgY29uc3QgbGluZUhlaWdodCA9IGxhc3RGb250LmxpbmVIZWlnaHQgfHwgTWF0aC5tYXgoMS4yLCBmb250TGluZUhlaWdodCkgKiBmb250U2l6ZTsKICAgICAgY29uc3QgbGluZUdhcCA9IHBkZkZvbnQubGluZUdhcCA9PT0gdW5kZWZpbmVkID8gMC4yIDogcGRmRm9udC5saW5lR2FwOwogICAgICBjb25zdCBub0dhcCA9IGZvbnRMaW5lSGVpZ2h0IC0gbGluZUdhcDsKICAgICAgY29uc3QgZmlyc3RMaW5lSGVpZ2h0ID0gTWF0aC5tYXgoMSwgbm9HYXApICogZm9udFNpemU7CiAgICAgIGNvbnN0IHNjYWxlID0gZm9udFNpemUgLyAxMDAwOwogICAgICBjb25zdCBmYWxsYmFja1dpZHRoID0gcGRmRm9udC5kZWZhdWx0V2lkdGggfHwgcGRmRm9udC5jaGFyc1RvR2x5cGhzKCIgIilbMF0ud2lkdGg7CiAgICAgIGZvciAoY29uc3QgbGluZSBvZiBzdHIuc3BsaXQoL1tcdTIwMjlcbl0vKSkgewogICAgICAgIGNvbnN0IGVuY29kZWRMaW5lID0gcGRmRm9udC5lbmNvZGVTdHJpbmcobGluZSkuam9pbigiIik7CiAgICAgICAgY29uc3QgZ2x5cGhzID0gcGRmRm9udC5jaGFyc1RvR2x5cGhzKGVuY29kZWRMaW5lKTsKICAgICAgICBmb3IgKGNvbnN0IGdseXBoIG9mIGdseXBocykgewogICAgICAgICAgY29uc3Qgd2lkdGggPSBnbHlwaC53aWR0aCB8fCBmYWxsYmFja1dpZHRoOwogICAgICAgICAgdGhpcy5nbHlwaHMucHVzaChbd2lkdGggKiBzY2FsZSArIGxldHRlclNwYWNpbmcsIGxpbmVIZWlnaHQsIGZpcnN0TGluZUhlaWdodCwgZ2x5cGgudW5pY29kZSwgZmFsc2VdKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5nbHlwaHMucHVzaChbMCwgMCwgMCwgIlxuIiwgdHJ1ZV0pOwogICAgICB9CiAgICAgIHRoaXMuZ2x5cGhzLnBvcCgpOwogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGNvbnN0IGxpbmUgb2Ygc3RyLnNwbGl0KC9bXHUyMDI5XG5dLykpIHsKICAgICAgZm9yIChjb25zdCBjaGFyIG9mIGxpbmUuc3BsaXQoIiIpKSB7CiAgICAgICAgdGhpcy5nbHlwaHMucHVzaChbZm9udFNpemUsIDEuMiAqIGZvbnRTaXplLCBmb250U2l6ZSwgY2hhciwgZmFsc2VdKTsKICAgICAgfQogICAgICB0aGlzLmdseXBocy5wdXNoKFswLCAwLCAwLCAiXG4iLCB0cnVlXSk7CiAgICB9CiAgICB0aGlzLmdseXBocy5wb3AoKTsKICB9CiAgY29tcHV0ZShtYXhXaWR0aCkgewogICAgbGV0IGxhc3RTcGFjZVBvcyA9IC0xLAogICAgICBsYXN0U3BhY2VXaWR0aCA9IDAsCiAgICAgIHdpZHRoID0gMCwKICAgICAgaGVpZ2h0ID0gMCwKICAgICAgY3VycmVudExpbmVXaWR0aCA9IDAsCiAgICAgIGN1cnJlbnRMaW5lSGVpZ2h0ID0gMDsKICAgIGxldCBpc0Jyb2tlbiA9IGZhbHNlOwogICAgbGV0IGlzRmlyc3RMaW5lID0gdHJ1ZTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHRoaXMuZ2x5cGhzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgW2dseXBoV2lkdGgsIGxpbmVIZWlnaHQsIGZpcnN0TGluZUhlaWdodCwgY2hhciwgaXNFT0xdID0gdGhpcy5nbHlwaHNbaV07CiAgICAgIGNvbnN0IGlzU3BhY2UgPSBjaGFyID09PSAiICI7CiAgICAgIGNvbnN0IGdseXBoSGVpZ2h0ID0gaXNGaXJzdExpbmUgPyBmaXJzdExpbmVIZWlnaHQgOiBsaW5lSGVpZ2h0OwogICAgICBpZiAoaXNFT0wpIHsKICAgICAgICB3aWR0aCA9IE1hdGgubWF4KHdpZHRoLCBjdXJyZW50TGluZVdpZHRoKTsKICAgICAgICBjdXJyZW50TGluZVdpZHRoID0gMDsKICAgICAgICBoZWlnaHQgKz0gY3VycmVudExpbmVIZWlnaHQ7CiAgICAgICAgY3VycmVudExpbmVIZWlnaHQgPSBnbHlwaEhlaWdodDsKICAgICAgICBsYXN0U3BhY2VQb3MgPSAtMTsKICAgICAgICBsYXN0U3BhY2VXaWR0aCA9IDA7CiAgICAgICAgaXNGaXJzdExpbmUgPSBmYWxzZTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoaXNTcGFjZSkgewogICAgICAgIGlmIChjdXJyZW50TGluZVdpZHRoICsgZ2x5cGhXaWR0aCA+IG1heFdpZHRoKSB7CiAgICAgICAgICB3aWR0aCA9IE1hdGgubWF4KHdpZHRoLCBjdXJyZW50TGluZVdpZHRoKTsKICAgICAgICAgIGN1cnJlbnRMaW5lV2lkdGggPSAwOwogICAgICAgICAgaGVpZ2h0ICs9IGN1cnJlbnRMaW5lSGVpZ2h0OwogICAgICAgICAgY3VycmVudExpbmVIZWlnaHQgPSBnbHlwaEhlaWdodDsKICAgICAgICAgIGxhc3RTcGFjZVBvcyA9IC0xOwogICAgICAgICAgbGFzdFNwYWNlV2lkdGggPSAwOwogICAgICAgICAgaXNCcm9rZW4gPSB0cnVlOwogICAgICAgICAgaXNGaXJzdExpbmUgPSBmYWxzZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY3VycmVudExpbmVIZWlnaHQgPSBNYXRoLm1heChnbHlwaEhlaWdodCwgY3VycmVudExpbmVIZWlnaHQpOwogICAgICAgICAgbGFzdFNwYWNlV2lkdGggPSBjdXJyZW50TGluZVdpZHRoOwogICAgICAgICAgY3VycmVudExpbmVXaWR0aCArPSBnbHlwaFdpZHRoOwogICAgICAgICAgbGFzdFNwYWNlUG9zID0gaTsKICAgICAgICB9CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGN1cnJlbnRMaW5lV2lkdGggKyBnbHlwaFdpZHRoID4gbWF4V2lkdGgpIHsKICAgICAgICBoZWlnaHQgKz0gY3VycmVudExpbmVIZWlnaHQ7CiAgICAgICAgY3VycmVudExpbmVIZWlnaHQgPSBnbHlwaEhlaWdodDsKICAgICAgICBpZiAobGFzdFNwYWNlUG9zICE9PSAtMSkgewogICAgICAgICAgaSA9IGxhc3RTcGFjZVBvczsKICAgICAgICAgIHdpZHRoID0gTWF0aC5tYXgod2lkdGgsIGxhc3RTcGFjZVdpZHRoKTsKICAgICAgICAgIGN1cnJlbnRMaW5lV2lkdGggPSAwOwogICAgICAgICAgbGFzdFNwYWNlUG9zID0gLTE7CiAgICAgICAgICBsYXN0U3BhY2VXaWR0aCA9IDA7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHdpZHRoID0gTWF0aC5tYXgod2lkdGgsIGN1cnJlbnRMaW5lV2lkdGgpOwogICAgICAgICAgY3VycmVudExpbmVXaWR0aCA9IGdseXBoV2lkdGg7CiAgICAgICAgfQogICAgICAgIGlzQnJva2VuID0gdHJ1ZTsKICAgICAgICBpc0ZpcnN0TGluZSA9IGZhbHNlOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGN1cnJlbnRMaW5lV2lkdGggKz0gZ2x5cGhXaWR0aDsKICAgICAgY3VycmVudExpbmVIZWlnaHQgPSBNYXRoLm1heChnbHlwaEhlaWdodCwgY3VycmVudExpbmVIZWlnaHQpOwogICAgfQogICAgd2lkdGggPSBNYXRoLm1heCh3aWR0aCwgY3VycmVudExpbmVXaWR0aCk7CiAgICBoZWlnaHQgKz0gY3VycmVudExpbmVIZWlnaHQgKyB0aGlzLmV4dHJhSGVpZ2h0OwogICAgcmV0dXJuIHsKICAgICAgd2lkdGg6IFdJRFRIX0ZBQ1RPUiAqIHdpZHRoLAogICAgICBoZWlnaHQsCiAgICAgIGlzQnJva2VuCiAgICB9OwogIH0KfQpleHBvcnRzLlRleHRNZWFzdXJlID0gVGV4dE1lYXN1cmU7CgovKioqLyB9KSwKLyogMjIyICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5EYXRhSGFuZGxlciA9IHZvaWQgMDsKdmFyIF94ZmFfb2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTIpOwpjbGFzcyBEYXRhSGFuZGxlciB7CiAgY29uc3RydWN0b3Iocm9vdCwgZGF0YSkgewogICAgdGhpcy5kYXRhID0gZGF0YTsKICAgIHRoaXMuZGF0YXNldCA9IHJvb3QuZGF0YXNldHMgfHwgbnVsbDsKICB9CiAgc2VyaWFsaXplKHN0b3JhZ2UpIHsKICAgIGNvbnN0IHN0YWNrID0gW1stMSwgdGhpcy5kYXRhW194ZmFfb2JqZWN0LiRnZXRDaGlsZHJlbl0oKV1dOwogICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgbGFzdCA9IHN0YWNrLmF0KC0xKTsKICAgICAgY29uc3QgW2ksIGNoaWxkcmVuXSA9IGxhc3Q7CiAgICAgIGlmIChpICsgMSA9PT0gY2hpbGRyZW4ubGVuZ3RoKSB7CiAgICAgICAgc3RhY2sucG9wKCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgY2hpbGQgPSBjaGlsZHJlblsrK2xhc3RbMF1dOwogICAgICBjb25zdCBzdG9yYWdlRW50cnkgPSBzdG9yYWdlLmdldChjaGlsZFtfeGZhX29iamVjdC4kdWlkXSk7CiAgICAgIGlmIChzdG9yYWdlRW50cnkpIHsKICAgICAgICBjaGlsZFtfeGZhX29iamVjdC4kc2V0VmFsdWVdKHN0b3JhZ2VFbnRyeSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IGNoaWxkW194ZmFfb2JqZWN0LiRnZXRBdHRyaWJ1dGVzXSgpOwogICAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgYXR0cmlidXRlcy52YWx1ZXMoKSkgewogICAgICAgICAgY29uc3QgZW50cnkgPSBzdG9yYWdlLmdldCh2YWx1ZVtfeGZhX29iamVjdC4kdWlkXSk7CiAgICAgICAgICBpZiAoZW50cnkpIHsKICAgICAgICAgICAgdmFsdWVbX3hmYV9vYmplY3QuJHNldFZhbHVlXShlbnRyeSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBub2RlcyA9IGNoaWxkW194ZmFfb2JqZWN0LiRnZXRDaGlsZHJlbl0oKTsKICAgICAgaWYgKG5vZGVzLmxlbmd0aCA+IDApIHsKICAgICAgICBzdGFjay5wdXNoKFstMSwgbm9kZXNdKTsKICAgICAgfQogICAgfQogICAgY29uc3QgYnVmID0gW2A8eGZhOmRhdGFzZXRzIHhtbG5zOnhmYT0iaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtZGF0YS8xLjAvIj5gXTsKICAgIGlmICh0aGlzLmRhdGFzZXQpIHsKICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzLmRhdGFzZXRbX3hmYV9vYmplY3QuJGdldENoaWxkcmVuXSgpKSB7CiAgICAgICAgaWYgKGNoaWxkW194ZmFfb2JqZWN0LiRub2RlTmFtZV0gIT09ICJkYXRhIikgewogICAgICAgICAgY2hpbGRbX3hmYV9vYmplY3QuJHRvU3RyaW5nXShidWYpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgdGhpcy5kYXRhW194ZmFfb2JqZWN0LiR0b1N0cmluZ10oYnVmKTsKICAgIGJ1Zi5wdXNoKCI8L3hmYTpkYXRhc2V0cz4iKTsKICAgIHJldHVybiBidWYuam9pbigiIik7CiAgfQp9CmV4cG9ydHMuRGF0YUhhbmRsZXIgPSBEYXRhSGFuZGxlcjsKCi8qKiovIH0pLAovKiAyMjMgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlhGQVBhcnNlciA9IHZvaWQgMDsKdmFyIF94ZmFfb2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTIpOwp2YXIgX3htbF9wYXJzZXIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIwMSk7CnZhciBfYnVpbGRlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMjI0KTsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKY2xhc3MgWEZBUGFyc2VyIGV4dGVuZHMgX3htbF9wYXJzZXIuWE1MUGFyc2VyQmFzZSB7CiAgY29uc3RydWN0b3IoKSB7CiAgICBsZXQgcm9vdE5hbWVTcGFjZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbnVsbDsKICAgIGxldCByaWNoVGV4dCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogZmFsc2U7CiAgICBzdXBlcigpOwogICAgdGhpcy5fYnVpbGRlciA9IG5ldyBfYnVpbGRlci5CdWlsZGVyKHJvb3ROYW1lU3BhY2UpOwogICAgdGhpcy5fc3RhY2sgPSBbXTsKICAgIHRoaXMuX2dsb2JhbERhdGEgPSB7CiAgICAgIHVzZWRUeXBlZmFjZXM6IG5ldyBTZXQoKQogICAgfTsKICAgIHRoaXMuX2lkcyA9IG5ldyBNYXAoKTsKICAgIHRoaXMuX2N1cnJlbnQgPSB0aGlzLl9idWlsZGVyLmJ1aWxkUm9vdCh0aGlzLl9pZHMpOwogICAgdGhpcy5fZXJyb3JDb2RlID0gX3htbF9wYXJzZXIuWE1MUGFyc2VyRXJyb3JDb2RlLk5vRXJyb3I7CiAgICB0aGlzLl93aGl0ZVJlZ2V4ID0gL15ccyskLzsKICAgIHRoaXMuX25ic3BzID0gL1x4YTArL2c7CiAgICB0aGlzLl9yaWNoVGV4dCA9IHJpY2hUZXh0OwogIH0KICBwYXJzZShkYXRhKSB7CiAgICB0aGlzLnBhcnNlWG1sKGRhdGEpOwogICAgaWYgKHRoaXMuX2Vycm9yQ29kZSAhPT0gX3htbF9wYXJzZXIuWE1MUGFyc2VyRXJyb3JDb2RlLk5vRXJyb3IpIHsKICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgIH0KICAgIHRoaXMuX2N1cnJlbnRbX3hmYV9vYmplY3QuJGZpbmFsaXplXSgpOwogICAgcmV0dXJuIHRoaXMuX2N1cnJlbnQuZWxlbWVudDsKICB9CiAgb25UZXh0KHRleHQpIHsKICAgIHRleHQgPSB0ZXh0LnJlcGxhY2UodGhpcy5fbmJzcHMsIG1hdGNoID0+IG1hdGNoLnNsaWNlKDEpICsgIiAiKTsKICAgIGlmICh0aGlzLl9yaWNoVGV4dCB8fCB0aGlzLl9jdXJyZW50W194ZmFfb2JqZWN0LiRhY2NlcHRXaGl0ZXNwYWNlXSgpKSB7CiAgICAgIHRoaXMuX2N1cnJlbnRbX3hmYV9vYmplY3QuJG9uVGV4dF0odGV4dCwgdGhpcy5fcmljaFRleHQpOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAodGhpcy5fd2hpdGVSZWdleC50ZXN0KHRleHQpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX2N1cnJlbnRbX3hmYV9vYmplY3QuJG9uVGV4dF0odGV4dC50cmltKCkpOwogIH0KICBvbkNkYXRhKHRleHQpIHsKICAgIHRoaXMuX2N1cnJlbnRbX3hmYV9vYmplY3QuJG9uVGV4dF0odGV4dCk7CiAgfQogIF9ta0F0dHJpYnV0ZXMoYXR0cmlidXRlcywgdGFnTmFtZSkgewogICAgbGV0IG5hbWVzcGFjZSA9IG51bGw7CiAgICBsZXQgcHJlZml4ZXMgPSBudWxsOwogICAgY29uc3QgYXR0cmlidXRlT2JqID0gT2JqZWN0LmNyZWF0ZSh7fSk7CiAgICBmb3IgKGNvbnN0IHsKICAgICAgbmFtZSwKICAgICAgdmFsdWUKICAgIH0gb2YgYXR0cmlidXRlcykgewogICAgICBpZiAobmFtZSA9PT0gInhtbG5zIikgewogICAgICAgIGlmICghbmFtZXNwYWNlKSB7CiAgICAgICAgICBuYW1lc3BhY2UgPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBYRkEgLSBtdWx0aXBsZSBuYW1lc3BhY2UgZGVmaW5pdGlvbiBpbiA8JHt0YWdOYW1lfT5gKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAobmFtZS5zdGFydHNXaXRoKCJ4bWxuczoiKSkgewogICAgICAgIGNvbnN0IHByZWZpeCA9IG5hbWUuc3Vic3RyaW5nKCJ4bWxuczoiLmxlbmd0aCk7CiAgICAgICAgaWYgKCFwcmVmaXhlcykgewogICAgICAgICAgcHJlZml4ZXMgPSBbXTsKICAgICAgICB9CiAgICAgICAgcHJlZml4ZXMucHVzaCh7CiAgICAgICAgICBwcmVmaXgsCiAgICAgICAgICB2YWx1ZQogICAgICAgIH0pOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IGkgPSBuYW1lLmluZGV4T2YoIjoiKTsKICAgICAgICBpZiAoaSA9PT0gLTEpIHsKICAgICAgICAgIGF0dHJpYnV0ZU9ialtuYW1lXSA9IHZhbHVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBsZXQgbnNBdHRycyA9IGF0dHJpYnV0ZU9ialtfeGZhX29iamVjdC4kbnNBdHRyaWJ1dGVzXTsKICAgICAgICAgIGlmICghbnNBdHRycykgewogICAgICAgICAgICBuc0F0dHJzID0gYXR0cmlidXRlT2JqW194ZmFfb2JqZWN0LiRuc0F0dHJpYnV0ZXNdID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IFtucywgYXR0ck5hbWVdID0gW25hbWUuc2xpY2UoMCwgaSksIG5hbWUuc2xpY2UoaSArIDEpXTsKICAgICAgICAgIGxldCBhdHRycyA9IG5zQXR0cnNbbnNdOwogICAgICAgICAgaWYgKCFhdHRycykgewogICAgICAgICAgICBhdHRycyA9IG5zQXR0cnNbbnNdID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgIH0KICAgICAgICAgIGF0dHJzW2F0dHJOYW1lXSA9IHZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIFtuYW1lc3BhY2UsIHByZWZpeGVzLCBhdHRyaWJ1dGVPYmpdOwogIH0KICBfZ2V0TmFtZUFuZFByZWZpeChuYW1lLCBuc0Fnbm9zdGljKSB7CiAgICBjb25zdCBpID0gbmFtZS5pbmRleE9mKCI6Iik7CiAgICBpZiAoaSA9PT0gLTEpIHsKICAgICAgcmV0dXJuIFtuYW1lLCBudWxsXTsKICAgIH0KICAgIHJldHVybiBbbmFtZS5zdWJzdHJpbmcoaSArIDEpLCBuc0Fnbm9zdGljID8gIiIgOiBuYW1lLnN1YnN0cmluZygwLCBpKV07CiAgfQogIG9uQmVnaW5FbGVtZW50KHRhZ05hbWUsIGF0dHJpYnV0ZXMsIGlzRW1wdHkpIHsKICAgIGNvbnN0IFtuYW1lc3BhY2UsIHByZWZpeGVzLCBhdHRyaWJ1dGVzT2JqXSA9IHRoaXMuX21rQXR0cmlidXRlcyhhdHRyaWJ1dGVzLCB0YWdOYW1lKTsKICAgIGNvbnN0IFtuYW1lLCBuc1ByZWZpeF0gPSB0aGlzLl9nZXROYW1lQW5kUHJlZml4KHRhZ05hbWUsIHRoaXMuX2J1aWxkZXIuaXNOc0Fnbm9zdGljKCkpOwogICAgY29uc3Qgbm9kZSA9IHRoaXMuX2J1aWxkZXIuYnVpbGQoewogICAgICBuc1ByZWZpeCwKICAgICAgbmFtZSwKICAgICAgYXR0cmlidXRlczogYXR0cmlidXRlc09iaiwKICAgICAgbmFtZXNwYWNlLAogICAgICBwcmVmaXhlcwogICAgfSk7CiAgICBub2RlW194ZmFfb2JqZWN0LiRnbG9iYWxEYXRhXSA9IHRoaXMuX2dsb2JhbERhdGE7CiAgICBpZiAoaXNFbXB0eSkgewogICAgICBub2RlW194ZmFfb2JqZWN0LiRmaW5hbGl6ZV0oKTsKICAgICAgaWYgKHRoaXMuX2N1cnJlbnRbX3hmYV9vYmplY3QuJG9uQ2hpbGRdKG5vZGUpKSB7CiAgICAgICAgbm9kZVtfeGZhX29iamVjdC4kc2V0SWRdKHRoaXMuX2lkcyk7CiAgICAgIH0KICAgICAgbm9kZVtfeGZhX29iamVjdC4kY2xlYW5dKHRoaXMuX2J1aWxkZXIpOwogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9zdGFjay5wdXNoKHRoaXMuX2N1cnJlbnQpOwogICAgdGhpcy5fY3VycmVudCA9IG5vZGU7CiAgfQogIG9uRW5kRWxlbWVudChuYW1lKSB7CiAgICBjb25zdCBub2RlID0gdGhpcy5fY3VycmVudDsKICAgIGlmIChub2RlW194ZmFfb2JqZWN0LiRpc0NEQVRBWG1sXSgpICYmIHR5cGVvZiBub2RlW194ZmFfb2JqZWN0LiRjb250ZW50XSA9PT0gInN0cmluZyIpIHsKICAgICAgY29uc3QgcGFyc2VyID0gbmV3IFhGQVBhcnNlcigpOwogICAgICBwYXJzZXIuX2dsb2JhbERhdGEgPSB0aGlzLl9nbG9iYWxEYXRhOwogICAgICBjb25zdCByb290ID0gcGFyc2VyLnBhcnNlKG5vZGVbX3hmYV9vYmplY3QuJGNvbnRlbnRdKTsKICAgICAgbm9kZVtfeGZhX29iamVjdC4kY29udGVudF0gPSBudWxsOwogICAgICBub2RlW194ZmFfb2JqZWN0LiRvbkNoaWxkXShyb290KTsKICAgIH0KICAgIG5vZGVbX3hmYV9vYmplY3QuJGZpbmFsaXplXSgpOwogICAgdGhpcy5fY3VycmVudCA9IHRoaXMuX3N0YWNrLnBvcCgpOwogICAgaWYgKHRoaXMuX2N1cnJlbnRbX3hmYV9vYmplY3QuJG9uQ2hpbGRdKG5vZGUpKSB7CiAgICAgIG5vZGVbX3hmYV9vYmplY3QuJHNldElkXSh0aGlzLl9pZHMpOwogICAgfQogICAgbm9kZVtfeGZhX29iamVjdC4kY2xlYW5dKHRoaXMuX2J1aWxkZXIpOwogIH0KICBvbkVycm9yKGNvZGUpIHsKICAgIHRoaXMuX2Vycm9yQ29kZSA9IGNvZGU7CiAgfQp9CmV4cG9ydHMuWEZBUGFyc2VyID0gWEZBUGFyc2VyOwoKLyoqKi8gfSksCi8qIDIyNCAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuQnVpbGRlciA9IHZvaWQgMDsKdmFyIF9uYW1lc3BhY2VzID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTQpOwp2YXIgX3hmYV9vYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxMik7CnZhciBfc2V0dXAgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIyNSk7CnZhciBfdGVtcGxhdGUgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxNyk7CnZhciBfdW5rbm93biA9IF9fd19wZGZqc19yZXF1aXJlX18oMjM0KTsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKY2xhc3MgUm9vdCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoaWRzKSB7CiAgICBzdXBlcigtMSwgInJvb3QiLCBPYmplY3QuY3JlYXRlKG51bGwpKTsKICAgIHRoaXMuZWxlbWVudCA9IG51bGw7CiAgICB0aGlzW194ZmFfb2JqZWN0LiRpZHNdID0gaWRzOwogIH0KICBbX3hmYV9vYmplY3QuJG9uQ2hpbGRdKGNoaWxkKSB7CiAgICB0aGlzLmVsZW1lbnQgPSBjaGlsZDsKICAgIHJldHVybiB0cnVlOwogIH0KICBbX3hmYV9vYmplY3QuJGZpbmFsaXplXSgpIHsKICAgIHN1cGVyW194ZmFfb2JqZWN0LiRmaW5hbGl6ZV0oKTsKICAgIGlmICh0aGlzLmVsZW1lbnQudGVtcGxhdGUgaW5zdGFuY2VvZiBfdGVtcGxhdGUuVGVtcGxhdGUpIHsKICAgICAgdGhpc1tfeGZhX29iamVjdC4kaWRzXS5zZXQoX3hmYV9vYmplY3QuJHJvb3QsIHRoaXMuZWxlbWVudCk7CiAgICAgIHRoaXMuZWxlbWVudC50ZW1wbGF0ZVtfeGZhX29iamVjdC4kcmVzb2x2ZVByb3RvdHlwZXNdKHRoaXNbX3hmYV9vYmplY3QuJGlkc10pOwogICAgICB0aGlzLmVsZW1lbnQudGVtcGxhdGVbX3hmYV9vYmplY3QuJGlkc10gPSB0aGlzW194ZmFfb2JqZWN0LiRpZHNdOwogICAgfQogIH0KfQpjbGFzcyBFbXB0eSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoKSB7CiAgICBzdXBlcigtMSwgIiIsIE9iamVjdC5jcmVhdGUobnVsbCkpOwogIH0KICBbX3hmYV9vYmplY3QuJG9uQ2hpbGRdKF8pIHsKICAgIHJldHVybiBmYWxzZTsKICB9Cn0KY2xhc3MgQnVpbGRlciB7CiAgY29uc3RydWN0b3IoKSB7CiAgICBsZXQgcm9vdE5hbWVTcGFjZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogbnVsbDsKICAgIHRoaXMuX25hbWVzcGFjZVN0YWNrID0gW107CiAgICB0aGlzLl9uc0Fnbm9zdGljTGV2ZWwgPSAwOwogICAgdGhpcy5fbmFtZXNwYWNlUHJlZml4ZXMgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9uYW1lc3BhY2VzID0gbmV3IE1hcCgpOwogICAgdGhpcy5fbmV4dE5zSWQgPSBNYXRoLm1heCguLi5PYmplY3QudmFsdWVzKF9uYW1lc3BhY2VzLk5hbWVzcGFjZUlkcykubWFwKF9yZWYgPT4gewogICAgICBsZXQgewogICAgICAgIGlkCiAgICAgIH0gPSBfcmVmOwogICAgICByZXR1cm4gaWQ7CiAgICB9KSk7CiAgICB0aGlzLl9jdXJyZW50TmFtZXNwYWNlID0gcm9vdE5hbWVTcGFjZSB8fCBuZXcgX3Vua25vd24uVW5rbm93bk5hbWVzcGFjZSgrK3RoaXMuX25leHROc0lkKTsKICB9CiAgYnVpbGRSb290KGlkcykgewogICAgcmV0dXJuIG5ldyBSb290KGlkcyk7CiAgfQogIGJ1aWxkKF9yZWYyKSB7CiAgICBsZXQgewogICAgICBuc1ByZWZpeCwKICAgICAgbmFtZSwKICAgICAgYXR0cmlidXRlcywKICAgICAgbmFtZXNwYWNlLAogICAgICBwcmVmaXhlcwogICAgfSA9IF9yZWYyOwogICAgY29uc3QgaGFzTmFtZXNwYWNlRGVmID0gbmFtZXNwYWNlICE9PSBudWxsOwogICAgaWYgKGhhc05hbWVzcGFjZURlZikgewogICAgICB0aGlzLl9uYW1lc3BhY2VTdGFjay5wdXNoKHRoaXMuX2N1cnJlbnROYW1lc3BhY2UpOwogICAgICB0aGlzLl9jdXJyZW50TmFtZXNwYWNlID0gdGhpcy5fc2VhcmNoTmFtZXNwYWNlKG5hbWVzcGFjZSk7CiAgICB9CiAgICBpZiAocHJlZml4ZXMpIHsKICAgICAgdGhpcy5fYWRkTmFtZXNwYWNlUHJlZml4KHByZWZpeGVzKTsKICAgIH0KICAgIGlmIChhdHRyaWJ1dGVzLmhhc093blByb3BlcnR5KF94ZmFfb2JqZWN0LiRuc0F0dHJpYnV0ZXMpKSB7CiAgICAgIGNvbnN0IGRhdGFUZW1wbGF0ZSA9IF9zZXR1cC5OYW1lc3BhY2VTZXRVcC5kYXRhc2V0czsKICAgICAgY29uc3QgbnNBdHRycyA9IGF0dHJpYnV0ZXNbX3hmYV9vYmplY3QuJG5zQXR0cmlidXRlc107CiAgICAgIGxldCB4ZmFBdHRycyA9IG51bGw7CiAgICAgIGZvciAoY29uc3QgW25zLCBhdHRyc10gb2YgT2JqZWN0LmVudHJpZXMobnNBdHRycykpIHsKICAgICAgICBjb25zdCBuc1RvVXNlID0gdGhpcy5fZ2V0TmFtZXNwYWNlVG9Vc2UobnMpOwogICAgICAgIGlmIChuc1RvVXNlID09PSBkYXRhVGVtcGxhdGUpIHsKICAgICAgICAgIHhmYUF0dHJzID0gewogICAgICAgICAgICB4ZmE6IGF0dHJzCiAgICAgICAgICB9OwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICh4ZmFBdHRycykgewogICAgICAgIGF0dHJpYnV0ZXNbX3hmYV9vYmplY3QuJG5zQXR0cmlidXRlc10gPSB4ZmFBdHRyczsKICAgICAgfSBlbHNlIHsKICAgICAgICBkZWxldGUgYXR0cmlidXRlc1tfeGZhX29iamVjdC4kbnNBdHRyaWJ1dGVzXTsKICAgICAgfQogICAgfQogICAgY29uc3QgbmFtZXNwYWNlVG9Vc2UgPSB0aGlzLl9nZXROYW1lc3BhY2VUb1VzZShuc1ByZWZpeCk7CiAgICBjb25zdCBub2RlID0gbmFtZXNwYWNlVG9Vc2UgJiYgbmFtZXNwYWNlVG9Vc2VbX25hbWVzcGFjZXMuJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB8fCBuZXcgRW1wdHkoKTsKICAgIGlmIChub2RlW194ZmFfb2JqZWN0LiRpc05zQWdub3N0aWNdKCkpIHsKICAgICAgdGhpcy5fbnNBZ25vc3RpY0xldmVsKys7CiAgICB9CiAgICBpZiAoaGFzTmFtZXNwYWNlRGVmIHx8IHByZWZpeGVzIHx8IG5vZGVbX3hmYV9vYmplY3QuJGlzTnNBZ25vc3RpY10oKSkgewogICAgICBub2RlW194ZmFfb2JqZWN0LiRjbGVhbnVwXSA9IHsKICAgICAgICBoYXNOYW1lc3BhY2U6IGhhc05hbWVzcGFjZURlZiwKICAgICAgICBwcmVmaXhlcywKICAgICAgICBuc0Fnbm9zdGljOiBub2RlW194ZmFfb2JqZWN0LiRpc05zQWdub3N0aWNdKCkKICAgICAgfTsKICAgIH0KICAgIHJldHVybiBub2RlOwogIH0KICBpc05zQWdub3N0aWMoKSB7CiAgICByZXR1cm4gdGhpcy5fbnNBZ25vc3RpY0xldmVsID4gMDsKICB9CiAgX3NlYXJjaE5hbWVzcGFjZShuc05hbWUpIHsKICAgIGxldCBucyA9IHRoaXMuX25hbWVzcGFjZXMuZ2V0KG5zTmFtZSk7CiAgICBpZiAobnMpIHsKICAgICAgcmV0dXJuIG5zOwogICAgfQogICAgZm9yIChjb25zdCBbbmFtZSwgewogICAgICBjaGVjawogICAgfV0gb2YgT2JqZWN0LmVudHJpZXMoX25hbWVzcGFjZXMuTmFtZXNwYWNlSWRzKSkgewogICAgICBpZiAoY2hlY2sobnNOYW1lKSkgewogICAgICAgIG5zID0gX3NldHVwLk5hbWVzcGFjZVNldFVwW25hbWVdOwogICAgICAgIGlmIChucykgewogICAgICAgICAgdGhpcy5fbmFtZXNwYWNlcy5zZXQobnNOYW1lLCBucyk7CiAgICAgICAgICByZXR1cm4gbnM7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBucyA9IG5ldyBfdW5rbm93bi5Vbmtub3duTmFtZXNwYWNlKCsrdGhpcy5fbmV4dE5zSWQpOwogICAgdGhpcy5fbmFtZXNwYWNlcy5zZXQobnNOYW1lLCBucyk7CiAgICByZXR1cm4gbnM7CiAgfQogIF9hZGROYW1lc3BhY2VQcmVmaXgocHJlZml4ZXMpIHsKICAgIGZvciAoY29uc3QgewogICAgICBwcmVmaXgsCiAgICAgIHZhbHVlCiAgICB9IG9mIHByZWZpeGVzKSB7CiAgICAgIGNvbnN0IG5hbWVzcGFjZSA9IHRoaXMuX3NlYXJjaE5hbWVzcGFjZSh2YWx1ZSk7CiAgICAgIGxldCBwcmVmaXhTdGFjayA9IHRoaXMuX25hbWVzcGFjZVByZWZpeGVzLmdldChwcmVmaXgpOwogICAgICBpZiAoIXByZWZpeFN0YWNrKSB7CiAgICAgICAgcHJlZml4U3RhY2sgPSBbXTsKICAgICAgICB0aGlzLl9uYW1lc3BhY2VQcmVmaXhlcy5zZXQocHJlZml4LCBwcmVmaXhTdGFjayk7CiAgICAgIH0KICAgICAgcHJlZml4U3RhY2sucHVzaChuYW1lc3BhY2UpOwogICAgfQogIH0KICBfZ2V0TmFtZXNwYWNlVG9Vc2UocHJlZml4KSB7CiAgICBpZiAoIXByZWZpeCkgewogICAgICByZXR1cm4gdGhpcy5fY3VycmVudE5hbWVzcGFjZTsKICAgIH0KICAgIGNvbnN0IHByZWZpeFN0YWNrID0gdGhpcy5fbmFtZXNwYWNlUHJlZml4ZXMuZ2V0KHByZWZpeCk7CiAgICBpZiAocHJlZml4U3RhY2sgJiYgcHJlZml4U3RhY2subGVuZ3RoID4gMCkgewogICAgICByZXR1cm4gcHJlZml4U3RhY2suYXQoLTEpOwogICAgfQogICAgKDAsIF91dGlsLndhcm4pKGBVbmtub3duIG5hbWVzcGFjZSBwcmVmaXg6ICR7cHJlZml4fS5gKTsKICAgIHJldHVybiBudWxsOwogIH0KICBjbGVhbihkYXRhKSB7CiAgICBjb25zdCB7CiAgICAgIGhhc05hbWVzcGFjZSwKICAgICAgcHJlZml4ZXMsCiAgICAgIG5zQWdub3N0aWMKICAgIH0gPSBkYXRhOwogICAgaWYgKGhhc05hbWVzcGFjZSkgewogICAgICB0aGlzLl9jdXJyZW50TmFtZXNwYWNlID0gdGhpcy5fbmFtZXNwYWNlU3RhY2sucG9wKCk7CiAgICB9CiAgICBpZiAocHJlZml4ZXMpIHsKICAgICAgcHJlZml4ZXMuZm9yRWFjaChfcmVmMyA9PiB7CiAgICAgICAgbGV0IHsKICAgICAgICAgIHByZWZpeAogICAgICAgIH0gPSBfcmVmMzsKICAgICAgICB0aGlzLl9uYW1lc3BhY2VQcmVmaXhlcy5nZXQocHJlZml4KS5wb3AoKTsKICAgICAgfSk7CiAgICB9CiAgICBpZiAobnNBZ25vc3RpYykgewogICAgICB0aGlzLl9uc0Fnbm9zdGljTGV2ZWwtLTsKICAgIH0KICB9Cn0KZXhwb3J0cy5CdWlsZGVyID0gQnVpbGRlcjsKCi8qKiovIH0pLAovKiAyMjUgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLk5hbWVzcGFjZVNldFVwID0gdm9pZCAwOwp2YXIgX2NvbmZpZyA9IF9fd19wZGZqc19yZXF1aXJlX18oMjI2KTsKdmFyIF9jb25uZWN0aW9uX3NldCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjI3KTsKdmFyIF9kYXRhc2V0cyA9IF9fd19wZGZqc19yZXF1aXJlX18oMjI4KTsKdmFyIF9sb2NhbGVfc2V0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMjkpOwp2YXIgX3NpZ25hdHVyZSA9IF9fd19wZGZqc19yZXF1aXJlX18oMjMwKTsKdmFyIF9zdHlsZXNoZWV0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMzEpOwp2YXIgX3RlbXBsYXRlID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTcpOwp2YXIgX3hkcCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjMyKTsKdmFyIF94aHRtbCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjMzKTsKY29uc3QgTmFtZXNwYWNlU2V0VXAgPSB7CiAgY29uZmlnOiBfY29uZmlnLkNvbmZpZ05hbWVzcGFjZSwKICBjb25uZWN0aW9uOiBfY29ubmVjdGlvbl9zZXQuQ29ubmVjdGlvblNldE5hbWVzcGFjZSwKICBkYXRhc2V0czogX2RhdGFzZXRzLkRhdGFzZXRzTmFtZXNwYWNlLAogIGxvY2FsZVNldDogX2xvY2FsZV9zZXQuTG9jYWxlU2V0TmFtZXNwYWNlLAogIHNpZ25hdHVyZTogX3NpZ25hdHVyZS5TaWduYXR1cmVOYW1lc3BhY2UsCiAgc3R5bGVzaGVldDogX3N0eWxlc2hlZXQuU3R5bGVzaGVldE5hbWVzcGFjZSwKICB0ZW1wbGF0ZTogX3RlbXBsYXRlLlRlbXBsYXRlTmFtZXNwYWNlLAogIHhkcDogX3hkcC5YZHBOYW1lc3BhY2UsCiAgeGh0bWw6IF94aHRtbC5YaHRtbE5hbWVzcGFjZQp9OwpleHBvcnRzLk5hbWVzcGFjZVNldFVwID0gTmFtZXNwYWNlU2V0VXA7CgovKioqLyB9KSwKLyogMjI2ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5Db25maWdOYW1lc3BhY2UgPSB2b2lkIDA7CnZhciBfbmFtZXNwYWNlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMjE0KTsKdmFyIF94ZmFfb2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTIpOwp2YXIgX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTMpOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpjb25zdCBDT05GSUdfTlNfSUQgPSBfbmFtZXNwYWNlcy5OYW1lc3BhY2VJZHMuY29uZmlnLmlkOwpjbGFzcyBBY3JvYmF0IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhY3JvYmF0IiwgdHJ1ZSk7CiAgICB0aGlzLmFjcm9iYXQ3ID0gbnVsbDsKICAgIHRoaXMuYXV0b1NhdmUgPSBudWxsOwogICAgdGhpcy5jb21tb24gPSBudWxsOwogICAgdGhpcy52YWxpZGF0ZSA9IG51bGw7CiAgICB0aGlzLnZhbGlkYXRlQXBwcm92YWxTaWduYXR1cmVzID0gbnVsbDsKICAgIHRoaXMuc3VibWl0VXJsID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIEFjcm9iYXQ3IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhY3JvYmF0NyIsIHRydWUpOwogICAgdGhpcy5keW5hbWljUmVuZGVyID0gbnVsbDsKICB9Cn0KY2xhc3MgQURCRV9KU0NvbnNvbGUgZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIkFEQkVfSlNDb25zb2xlIiwgWyJkZWxlZ2F0ZSIsICJFbmFibGUiLCAiRGlzYWJsZSJdKTsKICB9Cn0KY2xhc3MgQURCRV9KU0RlYnVnZ2VyIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJBREJFX0pTRGVidWdnZXIiLCBbImRlbGVnYXRlIiwgIkVuYWJsZSIsICJEaXNhYmxlIl0pOwogIH0KfQpjbGFzcyBBZGRTaWxlbnRQcmludCBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhZGRTaWxlbnRQcmludCIpOwogIH0KfQpjbGFzcyBBZGRWaWV3ZXJQcmVmZXJlbmNlcyBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhZGRWaWV3ZXJQcmVmZXJlbmNlcyIpOwogIH0KfQpjbGFzcyBBZGp1c3REYXRhIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uMTAgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImFkanVzdERhdGEiKTsKICB9Cn0KY2xhc3MgQWRvYmVFeHRlbnNpb25MZXZlbCBleHRlbmRzIF94ZmFfb2JqZWN0LkludGVnZXJPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImFkb2JlRXh0ZW5zaW9uTGV2ZWwiLCAwLCBuID0+IG4gPj0gMSAmJiBuIDw9IDgpOwogIH0KfQpjbGFzcyBBZ2VudCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYWdlbnQiLCB0cnVlKTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSA/IGF0dHJpYnV0ZXMubmFtZS50cmltKCkgOiAiIjsKICAgIHRoaXMuY29tbW9uID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIEFsd2F5c0VtYmVkIGV4dGVuZHMgX3hmYV9vYmplY3QuQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYWx3YXlzRW1iZWQiKTsKICB9Cn0KY2xhc3MgQW1kIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhbWQiKTsKICB9Cn0KY2xhc3MgQXJlYSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYXJlYSIpOwogICAgdGhpcy5sZXZlbCA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmxldmVsLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiBuID0+IG4gPj0gMSAmJiBuIDw9IDMKICAgIH0pOwogICAgdGhpcy5uYW1lID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMubmFtZSwgWyIiLCAiYmFyY29kZSIsICJjb3JlaW5pdCIsICJkZXZpY2VEcml2ZXIiLCAiZm9udCIsICJnZW5lcmFsIiwgImxheW91dCIsICJtZXJnZSIsICJzY3JpcHQiLCAic2lnbmF0dXJlIiwgInNvdXJjZVNldCIsICJ0ZW1wbGF0ZUNhY2hlIl0pOwogIH0KfQpjbGFzcyBBdHRyaWJ1dGVzIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhdHRyaWJ1dGVzIiwgWyJwcmVzZXJ2ZSIsICJkZWxlZ2F0ZSIsICJpZ25vcmUiXSk7CiAgfQp9CmNsYXNzIEF1dG9TYXZlIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhdXRvU2F2ZSIsIFsiZGlzYWJsZWQiLCAiZW5hYmxlZCJdKTsKICB9Cn0KY2xhc3MgQmFzZSBleHRlbmRzIF94ZmFfb2JqZWN0LlN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYmFzZSIpOwogIH0KfQpjbGFzcyBCYXRjaE91dHB1dCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYmF0Y2hPdXRwdXQiKTsKICAgIHRoaXMuZm9ybWF0ID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuZm9ybWF0LCBbIm5vbmUiLCAiY29uY2F0IiwgInppcCIsICJ6aXBDb21wcmVzcyJdKTsKICB9Cn0KY2xhc3MgQmVoYXZpb3JPdmVycmlkZSBleHRlbmRzIF94ZmFfb2JqZWN0LkNvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImJlaGF2aW9yT3ZlcnJpZGUiKTsKICB9CiAgW194ZmFfb2JqZWN0LiRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA9IG5ldyBNYXAodGhpc1tfeGZhX29iamVjdC4kY29udGVudF0udHJpbSgpLnNwbGl0KC9ccysvKS5maWx0ZXIoeCA9PiB4LmluY2x1ZGVzKCI6IikpLm1hcCh4ID0+IHguc3BsaXQoIjoiLCAyKSkpOwogIH0KfQpjbGFzcyBDYWNoZSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiY2FjaGUiLCB0cnVlKTsKICAgIHRoaXMudGVtcGxhdGVDYWNoZSA9IG51bGw7CiAgfQp9CmNsYXNzIENoYW5nZSBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjaGFuZ2UiKTsKICB9Cn0KY2xhc3MgQ29tbW9uIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjb21tb24iLCB0cnVlKTsKICAgIHRoaXMuZGF0YSA9IG51bGw7CiAgICB0aGlzLmxvY2FsZSA9IG51bGw7CiAgICB0aGlzLmxvY2FsZVNldCA9IG51bGw7CiAgICB0aGlzLm1lc3NhZ2luZyA9IG51bGw7CiAgICB0aGlzLnN1cHByZXNzQmFubmVyID0gbnVsbDsKICAgIHRoaXMudGVtcGxhdGUgPSBudWxsOwogICAgdGhpcy52YWxpZGF0aW9uTWVzc2FnaW5nID0gbnVsbDsKICAgIHRoaXMudmVyc2lvbkNvbnRyb2wgPSBudWxsOwogICAgdGhpcy5sb2cgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgQ29tcHJlc3MgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImNvbXByZXNzIik7CiAgICB0aGlzLnNjb3BlID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMuc2NvcGUsIFsiaW1hZ2VPbmx5IiwgImRvY3VtZW50Il0pOwogIH0KfQpjbGFzcyBDb21wcmVzc0xvZ2ljYWxTdHJ1Y3R1cmUgZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiY29tcHJlc3NMb2dpY2FsU3RydWN0dXJlIik7CiAgfQp9CmNsYXNzIENvbXByZXNzT2JqZWN0U3RyZWFtIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uMTAgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImNvbXByZXNzT2JqZWN0U3RyZWFtIik7CiAgfQp9CmNsYXNzIENvbXByZXNzaW9uIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjb21wcmVzc2lvbiIsIHRydWUpOwogICAgdGhpcy5jb21wcmVzc0xvZ2ljYWxTdHJ1Y3R1cmUgPSBudWxsOwogICAgdGhpcy5jb21wcmVzc09iamVjdFN0cmVhbSA9IG51bGw7CiAgICB0aGlzLmxldmVsID0gbnVsbDsKICAgIHRoaXMudHlwZSA9IG51bGw7CiAgfQp9CmNsYXNzIENvbmZpZyBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiY29uZmlnIiwgdHJ1ZSk7CiAgICB0aGlzLmFjcm9iYXQgPSBudWxsOwogICAgdGhpcy5wcmVzZW50ID0gbnVsbDsKICAgIHRoaXMudHJhY2UgPSBudWxsOwogICAgdGhpcy5hZ2VudCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBDb25mb3JtYW5jZSBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiY29uZm9ybWFuY2UiLCBbIkEiLCAiQiJdKTsKICB9Cn0KY2xhc3MgQ29udGVudENvcHkgZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiY29udGVudENvcHkiKTsKICB9Cn0KY2xhc3MgQ29waWVzIGV4dGVuZHMgX3hmYV9vYmplY3QuSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiY29waWVzIiwgMSwgbiA9PiBuID49IDEpOwogIH0KfQpjbGFzcyBDcmVhdG9yIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjcmVhdG9yIik7CiAgfQp9CmNsYXNzIEN1cnJlbnRQYWdlIGV4dGVuZHMgX3hmYV9vYmplY3QuSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiY3VycmVudFBhZ2UiLCAwLCBuID0+IG4gPj0gMCk7CiAgfQp9CmNsYXNzIERhdGEgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImRhdGEiLCB0cnVlKTsKICAgIHRoaXMuYWRqdXN0RGF0YSA9IG51bGw7CiAgICB0aGlzLmF0dHJpYnV0ZXMgPSBudWxsOwogICAgdGhpcy5pbmNyZW1lbnRhbExvYWQgPSBudWxsOwogICAgdGhpcy5vdXRwdXRYU0wgPSBudWxsOwogICAgdGhpcy5yYW5nZSA9IG51bGw7CiAgICB0aGlzLnJlY29yZCA9IG51bGw7CiAgICB0aGlzLnN0YXJ0Tm9kZSA9IG51bGw7CiAgICB0aGlzLnVyaSA9IG51bGw7CiAgICB0aGlzLndpbmRvdyA9IG51bGw7CiAgICB0aGlzLnhzbCA9IG51bGw7CiAgICB0aGlzLmV4Y2x1ZGVOUyA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50cmFuc2Zvcm0gPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgRGVidWcgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImRlYnVnIiwgdHJ1ZSk7CiAgICB0aGlzLnVyaSA9IG51bGw7CiAgfQp9CmNsYXNzIERlZmF1bHRUeXBlZmFjZSBleHRlbmRzIF94ZmFfb2JqZWN0LkNvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImRlZmF1bHRUeXBlZmFjZSIpOwogICAgdGhpcy53cml0aW5nU2NyaXB0ID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMud3JpdGluZ1NjcmlwdCwgWyIqIiwgIkFyYWJpYyIsICJDeXJpbGxpYyIsICJFYXN0RXVyb3BlYW5Sb21hbiIsICJHcmVlayIsICJIZWJyZXciLCAiSmFwYW5lc2UiLCAiS29yZWFuIiwgIlJvbWFuIiwgIlNpbXBsaWZpZWRDaGluZXNlIiwgIlRoYWkiLCAiVHJhZGl0aW9uYWxDaGluZXNlIiwgIlZpZXRuYW1lc2UiXSk7CiAgfQp9CmNsYXNzIERlc3RpbmF0aW9uIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJkZXN0aW5hdGlvbiIsIFsicGRmIiwgInBjbCIsICJwcyIsICJ3ZWJDbGllbnQiLCAienBsIl0pOwogIH0KfQpjbGFzcyBEb2N1bWVudEFzc2VtYmx5IGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImRvY3VtZW50QXNzZW1ibHkiKTsKICB9Cn0KY2xhc3MgRHJpdmVyIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJkcml2ZXIiLCB0cnVlKTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSA/IGF0dHJpYnV0ZXMubmFtZS50cmltKCkgOiAiIjsKICAgIHRoaXMuZm9udEluZm8gPSBudWxsOwogICAgdGhpcy54ZGMgPSBudWxsOwogIH0KfQpjbGFzcyBEdXBsZXhPcHRpb24gZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImR1cGxleE9wdGlvbiIsIFsic2ltcGxleCIsICJkdXBsZXhGbGlwTG9uZ0VkZ2UiLCAiZHVwbGV4RmxpcFNob3J0RWRnZSJdKTsKICB9Cn0KY2xhc3MgRHluYW1pY1JlbmRlciBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZHluYW1pY1JlbmRlciIsIFsiZm9yYmlkZGVuIiwgInJlcXVpcmVkIl0pOwogIH0KfQpjbGFzcyBFbWJlZCBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJlbWJlZCIpOwogIH0KfQpjbGFzcyBFbmNyeXB0IGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImVuY3J5cHQiKTsKICB9Cn0KY2xhc3MgRW5jcnlwdGlvbiBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZW5jcnlwdGlvbiIsIHRydWUpOwogICAgdGhpcy5lbmNyeXB0ID0gbnVsbDsKICAgIHRoaXMuZW5jcnlwdGlvbkxldmVsID0gbnVsbDsKICAgIHRoaXMucGVybWlzc2lvbnMgPSBudWxsOwogIH0KfQpjbGFzcyBFbmNyeXB0aW9uTGV2ZWwgZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImVuY3J5cHRpb25MZXZlbCIsIFsiNDBiaXQiLCAiMTI4Yml0Il0pOwogIH0KfQpjbGFzcyBFbmZvcmNlIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJlbmZvcmNlIik7CiAgfQp9CmNsYXNzIEVxdWF0ZSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZXF1YXRlIik7CiAgICB0aGlzLmZvcmNlID0gKDAsIF91dGlscy5nZXRJbnRlZ2VyKSh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZm9yY2UsCiAgICAgIGRlZmF1bHRWYWx1ZTogMSwKICAgICAgdmFsaWRhdGU6IG4gPT4gbiA9PT0gMAogICAgfSk7CiAgICB0aGlzLmZyb20gPSBhdHRyaWJ1dGVzLmZyb20gfHwgIiI7CiAgICB0aGlzLnRvID0gYXR0cmlidXRlcy50byB8fCAiIjsKICB9Cn0KY2xhc3MgRXF1YXRlUmFuZ2UgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImVxdWF0ZVJhbmdlIik7CiAgICB0aGlzLmZyb20gPSBhdHRyaWJ1dGVzLmZyb20gfHwgIiI7CiAgICB0aGlzLnRvID0gYXR0cmlidXRlcy50byB8fCAiIjsKICAgIHRoaXMuX3VuaWNvZGVSYW5nZSA9IGF0dHJpYnV0ZXMudW5pY29kZVJhbmdlIHx8ICIiOwogIH0KICBnZXQgdW5pY29kZVJhbmdlKCkgewogICAgY29uc3QgcmFuZ2VzID0gW107CiAgICBjb25zdCB1bmljb2RlUmVnZXggPSAvVVwrKFswLTlhLWZBLUZdKykvOwogICAgY29uc3QgdW5pY29kZVJhbmdlID0gdGhpcy5fdW5pY29kZVJhbmdlOwogICAgZm9yIChsZXQgcmFuZ2Ugb2YgdW5pY29kZVJhbmdlLnNwbGl0KCIsIikubWFwKHggPT4geC50cmltKCkpLmZpbHRlcih4ID0+ICEheCkpIHsKICAgICAgcmFuZ2UgPSByYW5nZS5zcGxpdCgiLSIsIDIpLm1hcCh4ID0+IHsKICAgICAgICBjb25zdCBmb3VuZCA9IHgubWF0Y2godW5pY29kZVJlZ2V4KTsKICAgICAgICBpZiAoIWZvdW5kKSB7CiAgICAgICAgICByZXR1cm4gMDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHBhcnNlSW50KGZvdW5kWzFdLCAxNik7CiAgICAgIH0pOwogICAgICBpZiAocmFuZ2UubGVuZ3RoID09PSAxKSB7CiAgICAgICAgcmFuZ2UucHVzaChyYW5nZVswXSk7CiAgICAgIH0KICAgICAgcmFuZ2VzLnB1c2gocmFuZ2UpOwogICAgfQogICAgcmV0dXJuICgwLCBfdXRpbC5zaGFkb3cpKHRoaXMsICJ1bmljb2RlUmFuZ2UiLCByYW5nZXMpOwogIH0KfQpjbGFzcyBFeGNsdWRlIGV4dGVuZHMgX3hmYV9vYmplY3QuQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZXhjbHVkZSIpOwogIH0KICBbX3hmYV9vYmplY3QuJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdID0gdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0udHJpbSgpLnNwbGl0KC9ccysvKS5maWx0ZXIoeCA9PiB4ICYmIFsiY2FsY3VsYXRlIiwgImNsb3NlIiwgImVudGVyIiwgImV4aXQiLCAiaW5pdGlhbGl6ZSIsICJyZWFkeSIsICJ2YWxpZGF0ZSJdLmluY2x1ZGVzKHgpKTsKICB9Cn0KY2xhc3MgRXhjbHVkZU5TIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJleGNsdWRlTlMiKTsKICB9Cn0KY2xhc3MgRmxpcExhYmVsIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJmbGlwTGFiZWwiLCBbInVzZVByaW50ZXJTZXR0aW5nIiwgIm9uIiwgIm9mZiJdKTsKICB9Cn0KY2xhc3MgRm9udEluZm8gZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImZvbnRJbmZvIiwgdHJ1ZSk7CiAgICB0aGlzLmVtYmVkID0gbnVsbDsKICAgIHRoaXMubWFwID0gbnVsbDsKICAgIHRoaXMuc3Vic2V0QmVsb3cgPSBudWxsOwogICAgdGhpcy5hbHdheXNFbWJlZCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZWZhdWx0VHlwZWZhY2UgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubmV2ZXJFbWJlZCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBGb3JtRmllbGRGaWxsaW5nIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImZvcm1GaWVsZEZpbGxpbmciKTsKICB9Cn0KY2xhc3MgR3JvdXBQYXJlbnQgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImdyb3VwUGFyZW50Iik7CiAgfQp9CmNsYXNzIElmRW1wdHkgZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImlmRW1wdHkiLCBbImRhdGFWYWx1ZSIsICJkYXRhR3JvdXAiLCAiaWdub3JlIiwgInJlbW92ZSJdKTsKICB9Cn0KY2xhc3MgSW5jbHVkZVhEUENvbnRlbnQgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImluY2x1ZGVYRFBDb250ZW50Iik7CiAgfQp9CmNsYXNzIEluY3JlbWVudGFsTG9hZCBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiaW5jcmVtZW50YWxMb2FkIiwgWyJub25lIiwgImZvcndhcmRPbmx5Il0pOwogIH0KfQpjbGFzcyBJbmNyZW1lbnRhbE1lcmdlIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImluY3JlbWVudGFsTWVyZ2UiKTsKICB9Cn0KY2xhc3MgSW50ZXJhY3RpdmUgZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiaW50ZXJhY3RpdmUiKTsKICB9Cn0KY2xhc3MgSm9nIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJqb2ciLCBbInVzZVByaW50ZXJTZXR0aW5nIiwgIm5vbmUiLCAicGFnZVNldCJdKTsKICB9Cn0KY2xhc3MgTGFiZWxQcmludGVyIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsYWJlbFByaW50ZXIiLCB0cnVlKTsKICAgIHRoaXMubmFtZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLm5hbWUsIFsienBsIiwgImRwbCIsICJpcGwiLCAidGNwbCJdKTsKICAgIHRoaXMuYmF0Y2hPdXRwdXQgPSBudWxsOwogICAgdGhpcy5mbGlwTGFiZWwgPSBudWxsOwogICAgdGhpcy5mb250SW5mbyA9IG51bGw7CiAgICB0aGlzLnhkYyA9IG51bGw7CiAgfQp9CmNsYXNzIExheW91dCBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAibGF5b3V0IiwgWyJwYWdpbmF0ZSIsICJwYW5lbCJdKTsKICB9Cn0KY2xhc3MgTGV2ZWwgZXh0ZW5kcyBfeGZhX29iamVjdC5JbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsZXZlbCIsIDAsIG4gPT4gbiA+IDApOwogIH0KfQpjbGFzcyBMaW5lYXJpemVkIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImxpbmVhcml6ZWQiKTsKICB9Cn0KY2xhc3MgTG9jYWxlIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsb2NhbGUiKTsKICB9Cn0KY2xhc3MgTG9jYWxlU2V0IGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsb2NhbGVTZXQiKTsKICB9Cn0KY2xhc3MgTG9nIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsb2ciLCB0cnVlKTsKICAgIHRoaXMubW9kZSA9IG51bGw7CiAgICB0aGlzLnRocmVzaG9sZCA9IG51bGw7CiAgICB0aGlzLnRvID0gbnVsbDsKICAgIHRoaXMudXJpID0gbnVsbDsKICB9Cn0KY2xhc3MgTWFwRWxlbWVudCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAibWFwIiwgdHJ1ZSk7CiAgICB0aGlzLmVxdWF0ZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5lcXVhdGVSYW5nZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBNZWRpdW1JbmZvIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJtZWRpdW1JbmZvIiwgdHJ1ZSk7CiAgICB0aGlzLm1hcCA9IG51bGw7CiAgfQp9CmNsYXNzIE1lc3NhZ2UgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm1lc3NhZ2UiLCB0cnVlKTsKICAgIHRoaXMubXNnSWQgPSBudWxsOwogICAgdGhpcy5zZXZlcml0eSA9IG51bGw7CiAgfQp9CmNsYXNzIE1lc3NhZ2luZyBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAibWVzc2FnaW5nIiwgdHJ1ZSk7CiAgICB0aGlzLm1lc3NhZ2UgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgTW9kZSBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAibW9kZSIsIFsiYXBwZW5kIiwgIm92ZXJ3cml0ZSJdKTsKICB9Cn0KY2xhc3MgTW9kaWZ5QW5ub3RzIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm1vZGlmeUFubm90cyIpOwogIH0KfQpjbGFzcyBNc2dJZCBleHRlbmRzIF94ZmFfb2JqZWN0LkludGVnZXJPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm1zZ0lkIiwgMSwgbiA9PiBuID49IDEpOwogIH0KfQpjbGFzcyBOYW1lQXR0ciBleHRlbmRzIF94ZmFfb2JqZWN0LlN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAibmFtZUF0dHIiKTsKICB9Cn0KY2xhc3MgTmV2ZXJFbWJlZCBleHRlbmRzIF94ZmFfb2JqZWN0LkNvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm5ldmVyRW1iZWQiKTsKICB9Cn0KY2xhc3MgTnVtYmVyT2ZDb3BpZXMgZXh0ZW5kcyBfeGZhX29iamVjdC5JbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJudW1iZXJPZkNvcGllcyIsIG51bGwsIG4gPT4gbiA+PSAyICYmIG4gPD0gNSk7CiAgfQp9CmNsYXNzIE9wZW5BY3Rpb24gZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm9wZW5BY3Rpb24iLCB0cnVlKTsKICAgIHRoaXMuZGVzdGluYXRpb24gPSBudWxsOwogIH0KfQpjbGFzcyBPdXRwdXQgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm91dHB1dCIsIHRydWUpOwogICAgdGhpcy50byA9IG51bGw7CiAgICB0aGlzLnR5cGUgPSBudWxsOwogICAgdGhpcy51cmkgPSBudWxsOwogIH0KfQpjbGFzcyBPdXRwdXRCaW4gZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm91dHB1dEJpbiIpOwogIH0KfQpjbGFzcyBPdXRwdXRYU0wgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm91dHB1dFhTTCIsIHRydWUpOwogICAgdGhpcy51cmkgPSBudWxsOwogIH0KfQpjbGFzcyBPdmVycHJpbnQgZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm92ZXJwcmludCIsIFsibm9uZSIsICJib3RoIiwgImRyYXciLCAiZmllbGQiXSk7CiAgfQp9CmNsYXNzIFBhY2tldHMgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBhY2tldHMiKTsKICB9CiAgW194ZmFfb2JqZWN0LiRmaW5hbGl6ZV0oKSB7CiAgICBpZiAodGhpc1tfeGZhX29iamVjdC4kY29udGVudF0gPT09ICIqIikgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA9IHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdLnRyaW0oKS5zcGxpdCgvXHMrLykuZmlsdGVyKHggPT4gWyJjb25maWciLCAiZGF0YXNldHMiLCAidGVtcGxhdGUiLCAieGZkZiIsICJ4c2x0Il0uaW5jbHVkZXMoeCkpOwogIH0KfQpjbGFzcyBQYWdlT2Zmc2V0IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwYWdlT2Zmc2V0Iik7CiAgICB0aGlzLnggPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy54LAogICAgICBkZWZhdWx0VmFsdWU6ICJ1c2VYRENTZXR0aW5nIiwKICAgICAgdmFsaWRhdGU6IG4gPT4gdHJ1ZQogICAgfSk7CiAgICB0aGlzLnkgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy55LAogICAgICBkZWZhdWx0VmFsdWU6ICJ1c2VYRENTZXR0aW5nIiwKICAgICAgdmFsaWRhdGU6IG4gPT4gdHJ1ZQogICAgfSk7CiAgfQp9CmNsYXNzIFBhZ2VSYW5nZSBleHRlbmRzIF94ZmFfb2JqZWN0LlN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGFnZVJhbmdlIik7CiAgfQogIFtfeGZhX29iamVjdC4kZmluYWxpemVdKCkgewogICAgY29uc3QgbnVtYmVycyA9IHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdLnRyaW0oKS5zcGxpdCgvXHMrLykubWFwKHggPT4gcGFyc2VJbnQoeCwgMTApKTsKICAgIGNvbnN0IHJhbmdlcyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gbnVtYmVycy5sZW5ndGg7IGkgPCBpaTsgaSArPSAyKSB7CiAgICAgIHJhbmdlcy5wdXNoKG51bWJlcnMuc2xpY2UoaSwgaSArIDIpKTsKICAgIH0KICAgIHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdID0gcmFuZ2VzOwogIH0KfQpjbGFzcyBQYWdpbmF0aW9uIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwYWdpbmF0aW9uIiwgWyJzaW1wbGV4IiwgImR1cGxleFNob3J0RWRnZSIsICJkdXBsZXhMb25nRWRnZSJdKTsKICB9Cn0KY2xhc3MgUGFnaW5hdGlvbk92ZXJyaWRlIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwYWdpbmF0aW9uT3ZlcnJpZGUiLCBbIm5vbmUiLCAiZm9yY2VEdXBsZXgiLCAiZm9yY2VEdXBsZXhMb25nRWRnZSIsICJmb3JjZUR1cGxleFNob3J0RWRnZSIsICJmb3JjZVNpbXBsZXgiXSk7CiAgfQp9CmNsYXNzIFBhcnQgZXh0ZW5kcyBfeGZhX29iamVjdC5JbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwYXJ0IiwgMSwgbiA9PiBmYWxzZSk7CiAgfQp9CmNsYXNzIFBjbCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGNsIiwgdHJ1ZSk7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLmJhdGNoT3V0cHV0ID0gbnVsbDsKICAgIHRoaXMuZm9udEluZm8gPSBudWxsOwogICAgdGhpcy5qb2cgPSBudWxsOwogICAgdGhpcy5tZWRpdW1JbmZvID0gbnVsbDsKICAgIHRoaXMub3V0cHV0QmluID0gbnVsbDsKICAgIHRoaXMucGFnZU9mZnNldCA9IG51bGw7CiAgICB0aGlzLnN0YXBsZSA9IG51bGw7CiAgICB0aGlzLnhkYyA9IG51bGw7CiAgfQp9CmNsYXNzIFBkZiBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGRmIiwgdHJ1ZSk7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLmFkb2JlRXh0ZW5zaW9uTGV2ZWwgPSBudWxsOwogICAgdGhpcy5iYXRjaE91dHB1dCA9IG51bGw7CiAgICB0aGlzLmNvbXByZXNzaW9uID0gbnVsbDsKICAgIHRoaXMuY3JlYXRvciA9IG51bGw7CiAgICB0aGlzLmVuY3J5cHRpb24gPSBudWxsOwogICAgdGhpcy5mb250SW5mbyA9IG51bGw7CiAgICB0aGlzLmludGVyYWN0aXZlID0gbnVsbDsKICAgIHRoaXMubGluZWFyaXplZCA9IG51bGw7CiAgICB0aGlzLm9wZW5BY3Rpb24gPSBudWxsOwogICAgdGhpcy5wZGZhID0gbnVsbDsKICAgIHRoaXMucHJvZHVjZXIgPSBudWxsOwogICAgdGhpcy5yZW5kZXJQb2xpY3kgPSBudWxsOwogICAgdGhpcy5zY3JpcHRNb2RlbCA9IG51bGw7CiAgICB0aGlzLnNpbGVudFByaW50ID0gbnVsbDsKICAgIHRoaXMuc3VibWl0Rm9ybWF0ID0gbnVsbDsKICAgIHRoaXMudGFnZ2VkID0gbnVsbDsKICAgIHRoaXMudmVyc2lvbiA9IG51bGw7CiAgICB0aGlzLnZpZXdlclByZWZlcmVuY2VzID0gbnVsbDsKICAgIHRoaXMueGRjID0gbnVsbDsKICB9Cn0KY2xhc3MgUGRmYSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGRmYSIsIHRydWUpOwogICAgdGhpcy5hbWQgPSBudWxsOwogICAgdGhpcy5jb25mb3JtYW5jZSA9IG51bGw7CiAgICB0aGlzLmluY2x1ZGVYRFBDb250ZW50ID0gbnVsbDsKICAgIHRoaXMucGFydCA9IG51bGw7CiAgfQp9CmNsYXNzIFBlcm1pc3Npb25zIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwZXJtaXNzaW9ucyIsIHRydWUpOwogICAgdGhpcy5hY2Nlc3NpYmxlQ29udGVudCA9IG51bGw7CiAgICB0aGlzLmNoYW5nZSA9IG51bGw7CiAgICB0aGlzLmNvbnRlbnRDb3B5ID0gbnVsbDsKICAgIHRoaXMuZG9jdW1lbnRBc3NlbWJseSA9IG51bGw7CiAgICB0aGlzLmZvcm1GaWVsZEZpbGxpbmcgPSBudWxsOwogICAgdGhpcy5tb2RpZnlBbm5vdHMgPSBudWxsOwogICAgdGhpcy5wbGFpbnRleHRNZXRhZGF0YSA9IG51bGw7CiAgICB0aGlzLnByaW50ID0gbnVsbDsKICAgIHRoaXMucHJpbnRIaWdoUXVhbGl0eSA9IG51bGw7CiAgfQp9CmNsYXNzIFBpY2tUcmF5QnlQREZTaXplIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBpY2tUcmF5QnlQREZTaXplIik7CiAgfQp9CmNsYXNzIFBpY3R1cmUgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBpY3R1cmUiKTsKICB9Cn0KY2xhc3MgUGxhaW50ZXh0TWV0YWRhdGEgZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGxhaW50ZXh0TWV0YWRhdGEiKTsKICB9Cn0KY2xhc3MgUHJlc2VuY2UgZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInByZXNlbmNlIiwgWyJwcmVzZXJ2ZSIsICJkaXNzb2x2ZSIsICJkaXNzb2x2ZVN0cnVjdHVyZSIsICJpZ25vcmUiLCAicmVtb3ZlIl0pOwogIH0KfQpjbGFzcyBQcmVzZW50IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwcmVzZW50IiwgdHJ1ZSk7CiAgICB0aGlzLmJlaGF2aW9yT3ZlcnJpZGUgPSBudWxsOwogICAgdGhpcy5jYWNoZSA9IG51bGw7CiAgICB0aGlzLmNvbW1vbiA9IG51bGw7CiAgICB0aGlzLmNvcGllcyA9IG51bGw7CiAgICB0aGlzLmRlc3RpbmF0aW9uID0gbnVsbDsKICAgIHRoaXMuaW5jcmVtZW50YWxNZXJnZSA9IG51bGw7CiAgICB0aGlzLmxheW91dCA9IG51bGw7CiAgICB0aGlzLm91dHB1dCA9IG51bGw7CiAgICB0aGlzLm92ZXJwcmludCA9IG51bGw7CiAgICB0aGlzLnBhZ2luYXRpb24gPSBudWxsOwogICAgdGhpcy5wYWdpbmF0aW9uT3ZlcnJpZGUgPSBudWxsOwogICAgdGhpcy5zY3JpcHQgPSBudWxsOwogICAgdGhpcy52YWxpZGF0ZSA9IG51bGw7CiAgICB0aGlzLnhkcCA9IG51bGw7CiAgICB0aGlzLmRyaXZlciA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5sYWJlbFByaW50ZXIgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucGNsID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnBkZiA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wcyA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zdWJtaXRVcmwgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMud2ViQ2xpZW50ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnpwbCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBQcmludCBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwcmludCIpOwogIH0KfQpjbGFzcyBQcmludEhpZ2hRdWFsaXR5IGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInByaW50SGlnaFF1YWxpdHkiKTsKICB9Cn0KY2xhc3MgUHJpbnRTY2FsaW5nIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwcmludFNjYWxpbmciLCBbImFwcGRlZmF1bHQiLCAibm9TY2FsaW5nIl0pOwogIH0KfQpjbGFzcyBQcmludGVyTmFtZSBleHRlbmRzIF94ZmFfb2JqZWN0LlN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicHJpbnRlck5hbWUiKTsKICB9Cn0KY2xhc3MgUHJvZHVjZXIgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInByb2R1Y2VyIik7CiAgfQp9CmNsYXNzIFBzIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwcyIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5iYXRjaE91dHB1dCA9IG51bGw7CiAgICB0aGlzLmZvbnRJbmZvID0gbnVsbDsKICAgIHRoaXMuam9nID0gbnVsbDsKICAgIHRoaXMubWVkaXVtSW5mbyA9IG51bGw7CiAgICB0aGlzLm91dHB1dEJpbiA9IG51bGw7CiAgICB0aGlzLnN0YXBsZSA9IG51bGw7CiAgICB0aGlzLnhkYyA9IG51bGw7CiAgfQp9CmNsYXNzIFJhbmdlIGV4dGVuZHMgX3hmYV9vYmplY3QuQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicmFuZ2UiKTsKICB9CiAgW194ZmFfb2JqZWN0LiRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA9IHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdLnRyaW0oKS5zcGxpdCgvXHMqLFxzKi8sIDIpLm1hcChyYW5nZSA9PiByYW5nZS5zcGxpdCgiLSIpLm1hcCh4ID0+IHBhcnNlSW50KHgudHJpbSgpLCAxMCkpKS5maWx0ZXIocmFuZ2UgPT4gcmFuZ2UuZXZlcnkoeCA9PiAhaXNOYU4oeCkpKS5tYXAocmFuZ2UgPT4gewogICAgICBpZiAocmFuZ2UubGVuZ3RoID09PSAxKSB7CiAgICAgICAgcmFuZ2UucHVzaChyYW5nZVswXSk7CiAgICAgIH0KICAgICAgcmV0dXJuIHJhbmdlOwogICAgfSk7CiAgfQp9CmNsYXNzIFJlY29yZCBleHRlbmRzIF94ZmFfb2JqZWN0LkNvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInJlY29yZCIpOwogIH0KICBbX3hmYV9vYmplY3QuJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdID0gdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0udHJpbSgpOwogICAgY29uc3QgbiA9IHBhcnNlSW50KHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdLCAxMCk7CiAgICBpZiAoIWlzTmFOKG4pICYmIG4gPj0gMCkgewogICAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA9IG47CiAgICB9CiAgfQp9CmNsYXNzIFJlbGV2YW50IGV4dGVuZHMgX3hmYV9vYmplY3QuQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicmVsZXZhbnQiKTsKICB9CiAgW194ZmFfb2JqZWN0LiRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA9IHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdLnRyaW0oKS5zcGxpdCgvXHMrLyk7CiAgfQp9CmNsYXNzIFJlbmFtZSBleHRlbmRzIF94ZmFfb2JqZWN0LkNvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInJlbmFtZSIpOwogIH0KICBbX3hmYV9vYmplY3QuJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdID0gdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0udHJpbSgpOwogICAgaWYgKHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdLnRvTG93ZXJDYXNlKCkuc3RhcnRzV2l0aCgieG1sIikgfHwgbmV3IFJlZ0V4cCgiW1xccHtMfV9dW1xccHtMfVxcZC5fXFxwe019LV0qIiwgInUiKS50ZXN0KHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdKSkgewogICAgICAoMCwgX3V0aWwud2FybikoIlhGQSAtIFJlbmFtZTogaW52YWxpZCBYRkEgbmFtZSIpOwogICAgfQogIH0KfQpjbGFzcyBSZW5kZXJQb2xpY3kgZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInJlbmRlclBvbGljeSIsIFsic2VydmVyIiwgImNsaWVudCJdKTsKICB9Cn0KY2xhc3MgUnVuU2NyaXB0cyBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicnVuU2NyaXB0cyIsIFsiYm90aCIsICJjbGllbnQiLCAibm9uZSIsICJzZXJ2ZXIiXSk7CiAgfQp9CmNsYXNzIFNjcmlwdCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic2NyaXB0IiwgdHJ1ZSk7CiAgICB0aGlzLmN1cnJlbnRQYWdlID0gbnVsbDsKICAgIHRoaXMuZXhjbHVkZSA9IG51bGw7CiAgICB0aGlzLnJ1blNjcmlwdHMgPSBudWxsOwogIH0KfQpjbGFzcyBTY3JpcHRNb2RlbCBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic2NyaXB0TW9kZWwiLCBbIlhGQSIsICJub25lIl0pOwogIH0KfQpjbGFzcyBTZXZlcml0eSBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic2V2ZXJpdHkiLCBbImlnbm9yZSIsICJlcnJvciIsICJpbmZvcm1hdGlvbiIsICJ0cmFjZSIsICJ3YXJuaW5nIl0pOwogIH0KfQpjbGFzcyBTaWxlbnRQcmludCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic2lsZW50UHJpbnQiLCB0cnVlKTsKICAgIHRoaXMuYWRkU2lsZW50UHJpbnQgPSBudWxsOwogICAgdGhpcy5wcmludGVyTmFtZSA9IG51bGw7CiAgfQp9CmNsYXNzIFN0YXBsZSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3RhcGxlIik7CiAgICB0aGlzLm1vZGUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5tb2RlLCBbInVzZVByaW50ZXJTZXR0aW5nIiwgIm9uIiwgIm9mZiJdKTsKICB9Cn0KY2xhc3MgU3RhcnROb2RlIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJzdGFydE5vZGUiKTsKICB9Cn0KY2xhc3MgU3RhcnRQYWdlIGV4dGVuZHMgX3hmYV9vYmplY3QuSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3RhcnRQYWdlIiwgMCwgbiA9PiB0cnVlKTsKICB9Cn0KY2xhc3MgU3VibWl0Rm9ybWF0IGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJzdWJtaXRGb3JtYXQiLCBbImh0bWwiLCAiZGVsZWdhdGUiLCAiZmRmIiwgInhtbCIsICJwZGYiXSk7CiAgfQp9CmNsYXNzIFN1Ym1pdFVybCBleHRlbmRzIF94ZmFfb2JqZWN0LlN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3VibWl0VXJsIik7CiAgfQp9CmNsYXNzIFN1YnNldEJlbG93IGV4dGVuZHMgX3hmYV9vYmplY3QuSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3Vic2V0QmVsb3ciLCAxMDAsIG4gPT4gbiA+PSAwICYmIG4gPD0gMTAwKTsKICB9Cn0KY2xhc3MgU3VwcHJlc3NCYW5uZXIgZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3VwcHJlc3NCYW5uZXIiKTsKICB9Cn0KY2xhc3MgVGFnZ2VkIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInRhZ2dlZCIpOwogIH0KfQpjbGFzcyBUZW1wbGF0ZSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidGVtcGxhdGUiLCB0cnVlKTsKICAgIHRoaXMuYmFzZSA9IG51bGw7CiAgICB0aGlzLnJlbGV2YW50ID0gbnVsbDsKICAgIHRoaXMuc3RhcnRQYWdlID0gbnVsbDsKICAgIHRoaXMudXJpID0gbnVsbDsKICAgIHRoaXMueHNsID0gbnVsbDsKICB9Cn0KY2xhc3MgVGhyZXNob2xkIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ0aHJlc2hvbGQiLCBbInRyYWNlIiwgImVycm9yIiwgImluZm9ybWF0aW9uIiwgIndhcm5pbmciXSk7CiAgfQp9CmNsYXNzIFRvIGV4dGVuZHMgX3hmYV9vYmplY3QuT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ0byIsIFsibnVsbCIsICJtZW1vcnkiLCAic3RkZXJyIiwgInN0ZG91dCIsICJzeXN0ZW0iLCAidXJpIl0pOwogIH0KfQpjbGFzcyBUZW1wbGF0ZUNhY2hlIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ0ZW1wbGF0ZUNhY2hlIik7CiAgICB0aGlzLm1heEVudHJpZXMgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5tYXhFbnRyaWVzLAogICAgICBkZWZhdWx0VmFsdWU6IDUsCiAgICAgIHZhbGlkYXRlOiBuID0+IG4gPj0gMAogICAgfSk7CiAgfQp9CmNsYXNzIFRyYWNlIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ0cmFjZSIsIHRydWUpOwogICAgdGhpcy5hcmVhID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIFRyYW5zZm9ybSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidHJhbnNmb3JtIiwgdHJ1ZSk7CiAgICB0aGlzLmdyb3VwUGFyZW50ID0gbnVsbDsKICAgIHRoaXMuaWZFbXB0eSA9IG51bGw7CiAgICB0aGlzLm5hbWVBdHRyID0gbnVsbDsKICAgIHRoaXMucGljdHVyZSA9IG51bGw7CiAgICB0aGlzLnByZXNlbmNlID0gbnVsbDsKICAgIHRoaXMucmVuYW1lID0gbnVsbDsKICAgIHRoaXMud2hpdGVzcGFjZSA9IG51bGw7CiAgfQp9CmNsYXNzIFR5cGUgZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInR5cGUiLCBbIm5vbmUiLCAiYXNjaWk4NSIsICJhc2NpaUhleCIsICJjY2l0dGZheCIsICJmbGF0ZSIsICJsenciLCAicnVuTGVuZ3RoIiwgIm5hdGl2ZSIsICJ4ZHAiLCAibWVyZ2VkWERQIl0pOwogIH0KfQpjbGFzcyBVcmkgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInVyaSIpOwogIH0KfQpjbGFzcyBWYWxpZGF0ZSBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidmFsaWRhdGUiLCBbInByZVN1Ym1pdCIsICJwcmVQcmludCIsICJwcmVFeGVjdXRlIiwgInByZVNhdmUiXSk7CiAgfQp9CmNsYXNzIFZhbGlkYXRlQXBwcm92YWxTaWduYXR1cmVzIGV4dGVuZHMgX3hmYV9vYmplY3QuQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidmFsaWRhdGVBcHByb3ZhbFNpZ25hdHVyZXMiKTsKICB9CiAgW194ZmFfb2JqZWN0LiRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA9IHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdLnRyaW0oKS5zcGxpdCgvXHMrLykuZmlsdGVyKHggPT4gWyJkb2NSZWFkeSIsICJwb3N0U2lnbiJdLmluY2x1ZGVzKHgpKTsKICB9Cn0KY2xhc3MgVmFsaWRhdGlvbk1lc3NhZ2luZyBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidmFsaWRhdGlvbk1lc3NhZ2luZyIsIFsiYWxsTWVzc2FnZXNJbmRpdmlkdWFsbHkiLCAiYWxsTWVzc2FnZXNUb2dldGhlciIsICJmaXJzdE1lc3NhZ2VPbmx5IiwgIm5vTWVzc2FnZXMiXSk7CiAgfQp9CmNsYXNzIFZlcnNpb24gZXh0ZW5kcyBfeGZhX29iamVjdC5PcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInZlcnNpb24iLCBbIjEuNyIsICIxLjYiLCAiMS41IiwgIjEuNCIsICIxLjMiLCAiMS4yIl0pOwogIH0KfQpjbGFzcyBWZXJzaW9uQ29udHJvbCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiVmVyc2lvbkNvbnRyb2wiKTsKICAgIHRoaXMub3V0cHV0QmVsb3cgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5vdXRwdXRCZWxvdywgWyJ3YXJuIiwgImVycm9yIiwgInVwZGF0ZSJdKTsKICAgIHRoaXMuc291cmNlQWJvdmUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5zb3VyY2VBYm92ZSwgWyJ3YXJuIiwgImVycm9yIl0pOwogICAgdGhpcy5zb3VyY2VCZWxvdyA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLnNvdXJjZUJlbG93LCBbInVwZGF0ZSIsICJtYWludGFpbiJdKTsKICB9Cn0KY2xhc3MgVmlld2VyUHJlZmVyZW5jZXMgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInZpZXdlclByZWZlcmVuY2VzIiwgdHJ1ZSk7CiAgICB0aGlzLkFEQkVfSlNDb25zb2xlID0gbnVsbDsKICAgIHRoaXMuQURCRV9KU0RlYnVnZ2VyID0gbnVsbDsKICAgIHRoaXMuYWRkVmlld2VyUHJlZmVyZW5jZXMgPSBudWxsOwogICAgdGhpcy5kdXBsZXhPcHRpb24gPSBudWxsOwogICAgdGhpcy5lbmZvcmNlID0gbnVsbDsKICAgIHRoaXMubnVtYmVyT2ZDb3BpZXMgPSBudWxsOwogICAgdGhpcy5wYWdlUmFuZ2UgPSBudWxsOwogICAgdGhpcy5waWNrVHJheUJ5UERGU2l6ZSA9IG51bGw7CiAgICB0aGlzLnByaW50U2NhbGluZyA9IG51bGw7CiAgfQp9CmNsYXNzIFdlYkNsaWVudCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAid2ViQ2xpZW50IiwgdHJ1ZSk7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgPyBhdHRyaWJ1dGVzLm5hbWUudHJpbSgpIDogIiI7CiAgICB0aGlzLmZvbnRJbmZvID0gbnVsbDsKICAgIHRoaXMueGRjID0gbnVsbDsKICB9Cn0KY2xhc3MgV2hpdGVzcGFjZSBleHRlbmRzIF94ZmFfb2JqZWN0Lk9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAid2hpdGVzcGFjZSIsIFsicHJlc2VydmUiLCAibHRyaW0iLCAibm9ybWFsaXplIiwgInJ0cmltIiwgInRyaW0iXSk7CiAgfQp9CmNsYXNzIFdpbmRvdyBleHRlbmRzIF94ZmFfb2JqZWN0LkNvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIndpbmRvdyIpOwogIH0KICBbX3hmYV9vYmplY3QuJGZpbmFsaXplXSgpIHsKICAgIGNvbnN0IHBhaXIgPSB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XS50cmltKCkuc3BsaXQoL1xzKixccyovLCAyKS5tYXAoeCA9PiBwYXJzZUludCh4LCAxMCkpOwogICAgaWYgKHBhaXIuc29tZSh4ID0+IGlzTmFOKHgpKSkgewogICAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA9IFswLCAwXTsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKHBhaXIubGVuZ3RoID09PSAxKSB7CiAgICAgIHBhaXIucHVzaChwYWlyWzBdKTsKICAgIH0KICAgIHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdID0gcGFpcjsKICB9Cn0KY2xhc3MgWGRjIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ4ZGMiLCB0cnVlKTsKICAgIHRoaXMudXJpID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnhzbCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBYZHAgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInhkcCIsIHRydWUpOwogICAgdGhpcy5wYWNrZXRzID0gbnVsbDsKICB9Cn0KY2xhc3MgWHNsIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ4c2wiLCB0cnVlKTsKICAgIHRoaXMuZGVidWcgPSBudWxsOwogICAgdGhpcy51cmkgPSBudWxsOwogIH0KfQpjbGFzcyBacGwgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInpwbCIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lID8gYXR0cmlidXRlcy5uYW1lLnRyaW0oKSA6ICIiOwogICAgdGhpcy5iYXRjaE91dHB1dCA9IG51bGw7CiAgICB0aGlzLmZsaXBMYWJlbCA9IG51bGw7CiAgICB0aGlzLmZvbnRJbmZvID0gbnVsbDsKICAgIHRoaXMueGRjID0gbnVsbDsKICB9Cn0KY2xhc3MgQ29uZmlnTmFtZXNwYWNlIHsKICBzdGF0aWMgW19uYW1lc3BhY2VzLiRidWlsZFhGQU9iamVjdF0obmFtZSwgYXR0cmlidXRlcykgewogICAgaWYgKENvbmZpZ05hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICByZXR1cm4gQ29uZmlnTmFtZXNwYWNlW25hbWVdKGF0dHJpYnV0ZXMpOwogICAgfQogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9CiAgc3RhdGljIGFjcm9iYXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQWNyb2JhdChhdHRycyk7CiAgfQogIHN0YXRpYyBhY3JvYmF0NyhhdHRycykgewogICAgcmV0dXJuIG5ldyBBY3JvYmF0NyhhdHRycyk7CiAgfQogIHN0YXRpYyBBREJFX0pTQ29uc29sZShhdHRycykgewogICAgcmV0dXJuIG5ldyBBREJFX0pTQ29uc29sZShhdHRycyk7CiAgfQogIHN0YXRpYyBBREJFX0pTRGVidWdnZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQURCRV9KU0RlYnVnZ2VyKGF0dHJzKTsKICB9CiAgc3RhdGljIGFkZFNpbGVudFByaW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEFkZFNpbGVudFByaW50KGF0dHJzKTsKICB9CiAgc3RhdGljIGFkZFZpZXdlclByZWZlcmVuY2VzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEFkZFZpZXdlclByZWZlcmVuY2VzKGF0dHJzKTsKICB9CiAgc3RhdGljIGFkanVzdERhdGEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQWRqdXN0RGF0YShhdHRycyk7CiAgfQogIHN0YXRpYyBhZG9iZUV4dGVuc2lvbkxldmVsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEFkb2JlRXh0ZW5zaW9uTGV2ZWwoYXR0cnMpOwogIH0KICBzdGF0aWMgYWdlbnQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQWdlbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgYWx3YXlzRW1iZWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQWx3YXlzRW1iZWQoYXR0cnMpOwogIH0KICBzdGF0aWMgYW1kKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEFtZChhdHRycyk7CiAgfQogIHN0YXRpYyBhcmVhKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEFyZWEoYXR0cnMpOwogIH0KICBzdGF0aWMgYXR0cmlidXRlcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBBdHRyaWJ1dGVzKGF0dHJzKTsKICB9CiAgc3RhdGljIGF1dG9TYXZlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEF1dG9TYXZlKGF0dHJzKTsKICB9CiAgc3RhdGljIGJhc2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQmFzZShhdHRycyk7CiAgfQogIHN0YXRpYyBiYXRjaE91dHB1dChhdHRycykgewogICAgcmV0dXJuIG5ldyBCYXRjaE91dHB1dChhdHRycyk7CiAgfQogIHN0YXRpYyBiZWhhdmlvck92ZXJyaWRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJlaGF2aW9yT3ZlcnJpZGUoYXR0cnMpOwogIH0KICBzdGF0aWMgY2FjaGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ2FjaGUoYXR0cnMpOwogIH0KICBzdGF0aWMgY2hhbmdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENoYW5nZShhdHRycyk7CiAgfQogIHN0YXRpYyBjb21tb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29tbW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGNvbXByZXNzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbXByZXNzKGF0dHJzKTsKICB9CiAgc3RhdGljIGNvbXByZXNzTG9naWNhbFN0cnVjdHVyZShhdHRycykgewogICAgcmV0dXJuIG5ldyBDb21wcmVzc0xvZ2ljYWxTdHJ1Y3R1cmUoYXR0cnMpOwogIH0KICBzdGF0aWMgY29tcHJlc3NPYmplY3RTdHJlYW0oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29tcHJlc3NPYmplY3RTdHJlYW0oYXR0cnMpOwogIH0KICBzdGF0aWMgY29tcHJlc3Npb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29tcHJlc3Npb24oYXR0cnMpOwogIH0KICBzdGF0aWMgY29uZmlnKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbmZpZyhhdHRycyk7CiAgfQogIHN0YXRpYyBjb25mb3JtYW5jZShhdHRycykgewogICAgcmV0dXJuIG5ldyBDb25mb3JtYW5jZShhdHRycyk7CiAgfQogIHN0YXRpYyBjb250ZW50Q29weShhdHRycykgewogICAgcmV0dXJuIG5ldyBDb250ZW50Q29weShhdHRycyk7CiAgfQogIHN0YXRpYyBjb3BpZXMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29waWVzKGF0dHJzKTsKICB9CiAgc3RhdGljIGNyZWF0b3IoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ3JlYXRvcihhdHRycyk7CiAgfQogIHN0YXRpYyBjdXJyZW50UGFnZShhdHRycykgewogICAgcmV0dXJuIG5ldyBDdXJyZW50UGFnZShhdHRycyk7CiAgfQogIHN0YXRpYyBkYXRhKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGEoYXR0cnMpOwogIH0KICBzdGF0aWMgZGVidWcoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRGVidWcoYXR0cnMpOwogIH0KICBzdGF0aWMgZGVmYXVsdFR5cGVmYWNlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERlZmF1bHRUeXBlZmFjZShhdHRycyk7CiAgfQogIHN0YXRpYyBkZXN0aW5hdGlvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBEZXN0aW5hdGlvbihhdHRycyk7CiAgfQogIHN0YXRpYyBkb2N1bWVudEFzc2VtYmx5KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERvY3VtZW50QXNzZW1ibHkoYXR0cnMpOwogIH0KICBzdGF0aWMgZHJpdmVyKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERyaXZlcihhdHRycyk7CiAgfQogIHN0YXRpYyBkdXBsZXhPcHRpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRHVwbGV4T3B0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGR5bmFtaWNSZW5kZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRHluYW1pY1JlbmRlcihhdHRycyk7CiAgfQogIHN0YXRpYyBlbWJlZChhdHRycykgewogICAgcmV0dXJuIG5ldyBFbWJlZChhdHRycyk7CiAgfQogIHN0YXRpYyBlbmNyeXB0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVuY3J5cHQoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jcnlwdGlvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBFbmNyeXB0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGVuY3J5cHRpb25MZXZlbChhdHRycykgewogICAgcmV0dXJuIG5ldyBFbmNyeXB0aW9uTGV2ZWwoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5mb3JjZShhdHRycykgewogICAgcmV0dXJuIG5ldyBFbmZvcmNlKGF0dHJzKTsKICB9CiAgc3RhdGljIGVxdWF0ZShhdHRycykgewogICAgcmV0dXJuIG5ldyBFcXVhdGUoYXR0cnMpOwogIH0KICBzdGF0aWMgZXF1YXRlUmFuZ2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRXF1YXRlUmFuZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgZXhjbHVkZShhdHRycykgewogICAgcmV0dXJuIG5ldyBFeGNsdWRlKGF0dHJzKTsKICB9CiAgc3RhdGljIGV4Y2x1ZGVOUyhhdHRycykgewogICAgcmV0dXJuIG5ldyBFeGNsdWRlTlMoYXR0cnMpOwogIH0KICBzdGF0aWMgZmxpcExhYmVsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEZsaXBMYWJlbChhdHRycyk7CiAgfQogIHN0YXRpYyBmb250SW5mbyhhdHRycykgewogICAgcmV0dXJuIG5ldyBGb250SW5mbyhhdHRycyk7CiAgfQogIHN0YXRpYyBmb3JtRmllbGRGaWxsaW5nKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEZvcm1GaWVsZEZpbGxpbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgZ3JvdXBQYXJlbnQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgR3JvdXBQYXJlbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgaWZFbXB0eShhdHRycykgewogICAgcmV0dXJuIG5ldyBJZkVtcHR5KGF0dHJzKTsKICB9CiAgc3RhdGljIGluY2x1ZGVYRFBDb250ZW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEluY2x1ZGVYRFBDb250ZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIGluY3JlbWVudGFsTG9hZChhdHRycykgewogICAgcmV0dXJuIG5ldyBJbmNyZW1lbnRhbExvYWQoYXR0cnMpOwogIH0KICBzdGF0aWMgaW5jcmVtZW50YWxNZXJnZShhdHRycykgewogICAgcmV0dXJuIG5ldyBJbmNyZW1lbnRhbE1lcmdlKGF0dHJzKTsKICB9CiAgc3RhdGljIGludGVyYWN0aXZlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEludGVyYWN0aXZlKGF0dHJzKTsKICB9CiAgc3RhdGljIGpvZyhhdHRycykgewogICAgcmV0dXJuIG5ldyBKb2coYXR0cnMpOwogIH0KICBzdGF0aWMgbGFiZWxQcmludGVyKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IExhYmVsUHJpbnRlcihhdHRycyk7CiAgfQogIHN0YXRpYyBsYXlvdXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTGF5b3V0KGF0dHJzKTsKICB9CiAgc3RhdGljIGxldmVsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IExldmVsKGF0dHJzKTsKICB9CiAgc3RhdGljIGxpbmVhcml6ZWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTGluZWFyaXplZChhdHRycyk7CiAgfQogIHN0YXRpYyBsb2NhbGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTG9jYWxlKGF0dHJzKTsKICB9CiAgc3RhdGljIGxvY2FsZVNldChhdHRycykgewogICAgcmV0dXJuIG5ldyBMb2NhbGVTZXQoYXR0cnMpOwogIH0KICBzdGF0aWMgbG9nKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IExvZyhhdHRycyk7CiAgfQogIHN0YXRpYyBtYXAoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTWFwRWxlbWVudChhdHRycyk7CiAgfQogIHN0YXRpYyBtZWRpdW1JbmZvKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1lZGl1bUluZm8oYXR0cnMpOwogIH0KICBzdGF0aWMgbWVzc2FnZShhdHRycykgewogICAgcmV0dXJuIG5ldyBNZXNzYWdlKGF0dHJzKTsKICB9CiAgc3RhdGljIG1lc3NhZ2luZyhhdHRycykgewogICAgcmV0dXJuIG5ldyBNZXNzYWdpbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgbW9kZShhdHRycykgewogICAgcmV0dXJuIG5ldyBNb2RlKGF0dHJzKTsKICB9CiAgc3RhdGljIG1vZGlmeUFubm90cyhhdHRycykgewogICAgcmV0dXJuIG5ldyBNb2RpZnlBbm5vdHMoYXR0cnMpOwogIH0KICBzdGF0aWMgbXNnSWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTXNnSWQoYXR0cnMpOwogIH0KICBzdGF0aWMgbmFtZUF0dHIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTmFtZUF0dHIoYXR0cnMpOwogIH0KICBzdGF0aWMgbmV2ZXJFbWJlZChhdHRycykgewogICAgcmV0dXJuIG5ldyBOZXZlckVtYmVkKGF0dHJzKTsKICB9CiAgc3RhdGljIG51bWJlck9mQ29waWVzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE51bWJlck9mQ29waWVzKGF0dHJzKTsKICB9CiAgc3RhdGljIG9wZW5BY3Rpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT3BlbkFjdGlvbihhdHRycyk7CiAgfQogIHN0YXRpYyBvdXRwdXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT3V0cHV0KGF0dHJzKTsKICB9CiAgc3RhdGljIG91dHB1dEJpbihhdHRycykgewogICAgcmV0dXJuIG5ldyBPdXRwdXRCaW4oYXR0cnMpOwogIH0KICBzdGF0aWMgb3V0cHV0WFNMKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE91dHB1dFhTTChhdHRycyk7CiAgfQogIHN0YXRpYyBvdmVycHJpbnQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT3ZlcnByaW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHBhY2tldHMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGFja2V0cyhhdHRycyk7CiAgfQogIHN0YXRpYyBwYWdlT2Zmc2V0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBhZ2VPZmZzZXQoYXR0cnMpOwogIH0KICBzdGF0aWMgcGFnZVJhbmdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBhZ2VSYW5nZShhdHRycyk7CiAgfQogIHN0YXRpYyBwYWdpbmF0aW9uKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBhZ2luYXRpb24oYXR0cnMpOwogIH0KICBzdGF0aWMgcGFnaW5hdGlvbk92ZXJyaWRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBhZ2luYXRpb25PdmVycmlkZShhdHRycyk7CiAgfQogIHN0YXRpYyBwYXJ0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBhcnQoYXR0cnMpOwogIH0KICBzdGF0aWMgcGNsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBjbChhdHRycyk7CiAgfQogIHN0YXRpYyBwZGYoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGRmKGF0dHJzKTsKICB9CiAgc3RhdGljIHBkZmEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGRmYShhdHRycyk7CiAgfQogIHN0YXRpYyBwZXJtaXNzaW9ucyhhdHRycykgewogICAgcmV0dXJuIG5ldyBQZXJtaXNzaW9ucyhhdHRycyk7CiAgfQogIHN0YXRpYyBwaWNrVHJheUJ5UERGU2l6ZShhdHRycykgewogICAgcmV0dXJuIG5ldyBQaWNrVHJheUJ5UERGU2l6ZShhdHRycyk7CiAgfQogIHN0YXRpYyBwaWN0dXJlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBpY3R1cmUoYXR0cnMpOwogIH0KICBzdGF0aWMgcGxhaW50ZXh0TWV0YWRhdGEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGxhaW50ZXh0TWV0YWRhdGEoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJlc2VuY2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHJlc2VuY2UoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJlc2VudChhdHRycykgewogICAgcmV0dXJuIG5ldyBQcmVzZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHByaW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFByaW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHByaW50SGlnaFF1YWxpdHkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHJpbnRIaWdoUXVhbGl0eShhdHRycyk7CiAgfQogIHN0YXRpYyBwcmludFNjYWxpbmcoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHJpbnRTY2FsaW5nKGF0dHJzKTsKICB9CiAgc3RhdGljIHByaW50ZXJOYW1lKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFByaW50ZXJOYW1lKGF0dHJzKTsKICB9CiAgc3RhdGljIHByb2R1Y2VyKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFByb2R1Y2VyKGF0dHJzKTsKICB9CiAgc3RhdGljIHBzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBzKGF0dHJzKTsKICB9CiAgc3RhdGljIHJhbmdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFJhbmdlKGF0dHJzKTsKICB9CiAgc3RhdGljIHJlY29yZChhdHRycykgewogICAgcmV0dXJuIG5ldyBSZWNvcmQoYXR0cnMpOwogIH0KICBzdGF0aWMgcmVsZXZhbnQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVsZXZhbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgcmVuYW1lKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFJlbmFtZShhdHRycyk7CiAgfQogIHN0YXRpYyByZW5kZXJQb2xpY3koYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVuZGVyUG9saWN5KGF0dHJzKTsKICB9CiAgc3RhdGljIHJ1blNjcmlwdHMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUnVuU2NyaXB0cyhhdHRycyk7CiAgfQogIHN0YXRpYyBzY3JpcHQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU2NyaXB0KGF0dHJzKTsKICB9CiAgc3RhdGljIHNjcmlwdE1vZGVsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNjcmlwdE1vZGVsKGF0dHJzKTsKICB9CiAgc3RhdGljIHNldmVyaXR5KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNldmVyaXR5KGF0dHJzKTsKICB9CiAgc3RhdGljIHNpbGVudFByaW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNpbGVudFByaW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHN0YXBsZShhdHRycykgewogICAgcmV0dXJuIG5ldyBTdGFwbGUoYXR0cnMpOwogIH0KICBzdGF0aWMgc3RhcnROb2RlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN0YXJ0Tm9kZShhdHRycyk7CiAgfQogIHN0YXRpYyBzdGFydFBhZ2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU3RhcnRQYWdlKGF0dHJzKTsKICB9CiAgc3RhdGljIHN1Ym1pdEZvcm1hdChhdHRycykgewogICAgcmV0dXJuIG5ldyBTdWJtaXRGb3JtYXQoYXR0cnMpOwogIH0KICBzdGF0aWMgc3VibWl0VXJsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1Ym1pdFVybChhdHRycyk7CiAgfQogIHN0YXRpYyBzdWJzZXRCZWxvdyhhdHRycykgewogICAgcmV0dXJuIG5ldyBTdWJzZXRCZWxvdyhhdHRycyk7CiAgfQogIHN0YXRpYyBzdXBwcmVzc0Jhbm5lcihhdHRycykgewogICAgcmV0dXJuIG5ldyBTdXBwcmVzc0Jhbm5lcihhdHRycyk7CiAgfQogIHN0YXRpYyB0YWdnZWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVGFnZ2VkKGF0dHJzKTsKICB9CiAgc3RhdGljIHRlbXBsYXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFRlbXBsYXRlKGF0dHJzKTsKICB9CiAgc3RhdGljIHRlbXBsYXRlQ2FjaGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVGVtcGxhdGVDYWNoZShhdHRycyk7CiAgfQogIHN0YXRpYyB0aHJlc2hvbGQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVGhyZXNob2xkKGF0dHJzKTsKICB9CiAgc3RhdGljIHRvKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFRvKGF0dHJzKTsKICB9CiAgc3RhdGljIHRyYWNlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFRyYWNlKGF0dHJzKTsKICB9CiAgc3RhdGljIHRyYW5zZm9ybShhdHRycykgewogICAgcmV0dXJuIG5ldyBUcmFuc2Zvcm0oYXR0cnMpOwogIH0KICBzdGF0aWMgdHlwZShhdHRycykgewogICAgcmV0dXJuIG5ldyBUeXBlKGF0dHJzKTsKICB9CiAgc3RhdGljIHVyaShhdHRycykgewogICAgcmV0dXJuIG5ldyBVcmkoYXR0cnMpOwogIH0KICBzdGF0aWMgdmFsaWRhdGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVmFsaWRhdGUoYXR0cnMpOwogIH0KICBzdGF0aWMgdmFsaWRhdGVBcHByb3ZhbFNpZ25hdHVyZXMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVmFsaWRhdGVBcHByb3ZhbFNpZ25hdHVyZXMoYXR0cnMpOwogIH0KICBzdGF0aWMgdmFsaWRhdGlvbk1lc3NhZ2luZyhhdHRycykgewogICAgcmV0dXJuIG5ldyBWYWxpZGF0aW9uTWVzc2FnaW5nKGF0dHJzKTsKICB9CiAgc3RhdGljIHZlcnNpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVmVyc2lvbihhdHRycyk7CiAgfQogIHN0YXRpYyB2ZXJzaW9uQ29udHJvbChhdHRycykgewogICAgcmV0dXJuIG5ldyBWZXJzaW9uQ29udHJvbChhdHRycyk7CiAgfQogIHN0YXRpYyB2aWV3ZXJQcmVmZXJlbmNlcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBWaWV3ZXJQcmVmZXJlbmNlcyhhdHRycyk7CiAgfQogIHN0YXRpYyB3ZWJDbGllbnQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgV2ViQ2xpZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHdoaXRlc3BhY2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgV2hpdGVzcGFjZShhdHRycyk7CiAgfQogIHN0YXRpYyB3aW5kb3coYXR0cnMpIHsKICAgIHJldHVybiBuZXcgV2luZG93KGF0dHJzKTsKICB9CiAgc3RhdGljIHhkYyhhdHRycykgewogICAgcmV0dXJuIG5ldyBYZGMoYXR0cnMpOwogIH0KICBzdGF0aWMgeGRwKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFhkcChhdHRycyk7CiAgfQogIHN0YXRpYyB4c2woYXR0cnMpIHsKICAgIHJldHVybiBuZXcgWHNsKGF0dHJzKTsKICB9CiAgc3RhdGljIHpwbChhdHRycykgewogICAgcmV0dXJuIG5ldyBacGwoYXR0cnMpOwogIH0KfQpleHBvcnRzLkNvbmZpZ05hbWVzcGFjZSA9IENvbmZpZ05hbWVzcGFjZTsKCi8qKiovIH0pLAovKiAyMjcgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLkNvbm5lY3Rpb25TZXROYW1lc3BhY2UgPSB2b2lkIDA7CnZhciBfbmFtZXNwYWNlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMjE0KTsKdmFyIF94ZmFfb2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTIpOwpjb25zdCBDT05ORUNUSU9OX1NFVF9OU19JRCA9IF9uYW1lc3BhY2VzLk5hbWVzcGFjZUlkcy5jb25uZWN0aW9uU2V0LmlkOwpjbGFzcyBDb25uZWN0aW9uU2V0IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgImNvbm5lY3Rpb25TZXQiLCB0cnVlKTsKICAgIHRoaXMud3NkbENvbm5lY3Rpb24gPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMueG1sQ29ubmVjdGlvbiA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy54c2RDb25uZWN0aW9uID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIEVmZmVjdGl2ZUlucHV0UG9saWN5IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgImVmZmVjdGl2ZUlucHV0UG9saWN5Iik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIEVmZmVjdGl2ZU91dHB1dFBvbGljeSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJlZmZlY3RpdmVPdXRwdXRQb2xpY3kiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgT3BlcmF0aW9uIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgIm9wZXJhdGlvbiIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmlucHV0ID0gYXR0cmlidXRlcy5pbnB1dCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMub3V0cHV0ID0gYXR0cmlidXRlcy5vdXRwdXQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBSb290RWxlbWVudCBleHRlbmRzIF94ZmFfb2JqZWN0LlN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJyb290RWxlbWVudCIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBTb2FwQWN0aW9uIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgInNvYXBBY3Rpb24iKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgU29hcEFkZHJlc3MgZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTk5FQ1RJT05fU0VUX05TX0lELCAic29hcEFkZHJlc3MiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgVXJpIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgInVyaSIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBXc2RsQWRkcmVzcyBleHRlbmRzIF94ZmFfb2JqZWN0LlN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJ3c2RsQWRkcmVzcyIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBXc2RsQ29ubmVjdGlvbiBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJ3c2RsQ29ubmVjdGlvbiIsIHRydWUpOwogICAgdGhpcy5kYXRhRGVzY3JpcHRpb24gPSBhdHRyaWJ1dGVzLmRhdGFEZXNjcmlwdGlvbiB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMuZWZmZWN0aXZlSW5wdXRQb2xpY3kgPSBudWxsOwogICAgdGhpcy5lZmZlY3RpdmVPdXRwdXRQb2xpY3kgPSBudWxsOwogICAgdGhpcy5vcGVyYXRpb24gPSBudWxsOwogICAgdGhpcy5zb2FwQWN0aW9uID0gbnVsbDsKICAgIHRoaXMuc29hcEFkZHJlc3MgPSBudWxsOwogICAgdGhpcy53c2RsQWRkcmVzcyA9IG51bGw7CiAgfQp9CmNsYXNzIFhtbENvbm5lY3Rpb24gZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTk5FQ1RJT05fU0VUX05TX0lELCAieG1sQ29ubmVjdGlvbiIsIHRydWUpOwogICAgdGhpcy5kYXRhRGVzY3JpcHRpb24gPSBhdHRyaWJ1dGVzLmRhdGFEZXNjcmlwdGlvbiB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXJpID0gbnVsbDsKICB9Cn0KY2xhc3MgWHNkQ29ubmVjdGlvbiBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJ4c2RDb25uZWN0aW9uIiwgdHJ1ZSk7CiAgICB0aGlzLmRhdGFEZXNjcmlwdGlvbiA9IGF0dHJpYnV0ZXMuZGF0YURlc2NyaXB0aW9uIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5yb290RWxlbWVudCA9IG51bGw7CiAgICB0aGlzLnVyaSA9IG51bGw7CiAgfQp9CmNsYXNzIENvbm5lY3Rpb25TZXROYW1lc3BhY2UgewogIHN0YXRpYyBbX25hbWVzcGFjZXMuJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoQ29ubmVjdGlvblNldE5hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICByZXR1cm4gQ29ubmVjdGlvblNldE5hbWVzcGFjZVtuYW1lXShhdHRyaWJ1dGVzKTsKICAgIH0KICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQogIHN0YXRpYyBjb25uZWN0aW9uU2V0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbm5lY3Rpb25TZXQoYXR0cnMpOwogIH0KICBzdGF0aWMgZWZmZWN0aXZlSW5wdXRQb2xpY3koYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRWZmZWN0aXZlSW5wdXRQb2xpY3koYXR0cnMpOwogIH0KICBzdGF0aWMgZWZmZWN0aXZlT3V0cHV0UG9saWN5KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVmZmVjdGl2ZU91dHB1dFBvbGljeShhdHRycyk7CiAgfQogIHN0YXRpYyBvcGVyYXRpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT3BlcmF0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIHJvb3RFbGVtZW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFJvb3RFbGVtZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHNvYXBBY3Rpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU29hcEFjdGlvbihhdHRycyk7CiAgfQogIHN0YXRpYyBzb2FwQWRkcmVzcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBTb2FwQWRkcmVzcyhhdHRycyk7CiAgfQogIHN0YXRpYyB1cmkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVXJpKGF0dHJzKTsKICB9CiAgc3RhdGljIHdzZGxBZGRyZXNzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFdzZGxBZGRyZXNzKGF0dHJzKTsKICB9CiAgc3RhdGljIHdzZGxDb25uZWN0aW9uKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFdzZGxDb25uZWN0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIHhtbENvbm5lY3Rpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgWG1sQ29ubmVjdGlvbihhdHRycyk7CiAgfQogIHN0YXRpYyB4c2RDb25uZWN0aW9uKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFhzZENvbm5lY3Rpb24oYXR0cnMpOwogIH0KfQpleHBvcnRzLkNvbm5lY3Rpb25TZXROYW1lc3BhY2UgPSBDb25uZWN0aW9uU2V0TmFtZXNwYWNlOwoKLyoqKi8gfSksCi8qIDIyOCAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuRGF0YXNldHNOYW1lc3BhY2UgPSB2b2lkIDA7CnZhciBfeGZhX29iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjEyKTsKdmFyIF9uYW1lc3BhY2VzID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTQpOwpjb25zdCBEQVRBU0VUU19OU19JRCA9IF9uYW1lc3BhY2VzLk5hbWVzcGFjZUlkcy5kYXRhc2V0cy5pZDsKY2xhc3MgRGF0YSBleHRlbmRzIF94ZmFfb2JqZWN0LlhtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoREFUQVNFVFNfTlNfSUQsICJkYXRhIiwgYXR0cmlidXRlcyk7CiAgfQogIFtfeGZhX29iamVjdC4kaXNOc0Fnbm9zdGljXSgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KfQpjbGFzcyBEYXRhc2V0cyBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoREFUQVNFVFNfTlNfSUQsICJkYXRhc2V0cyIsIHRydWUpOwogICAgdGhpcy5kYXRhID0gbnVsbDsKICAgIHRoaXMuU2lnbmF0dXJlID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiRvbkNoaWxkXShjaGlsZCkgewogICAgY29uc3QgbmFtZSA9IGNoaWxkW194ZmFfb2JqZWN0LiRub2RlTmFtZV07CiAgICBpZiAobmFtZSA9PT0gImRhdGEiICYmIGNoaWxkW194ZmFfb2JqZWN0LiRuYW1lc3BhY2VJZF0gPT09IERBVEFTRVRTX05TX0lEIHx8IG5hbWUgPT09ICJTaWduYXR1cmUiICYmIGNoaWxkW194ZmFfb2JqZWN0LiRuYW1lc3BhY2VJZF0gPT09IF9uYW1lc3BhY2VzLk5hbWVzcGFjZUlkcy5zaWduYXR1cmUuaWQpIHsKICAgICAgdGhpc1tuYW1lXSA9IGNoaWxkOwogICAgfQogICAgdGhpc1tfeGZhX29iamVjdC4kYXBwZW5kQ2hpbGRdKGNoaWxkKTsKICB9Cn0KY2xhc3MgRGF0YXNldHNOYW1lc3BhY2UgewogIHN0YXRpYyBbX25hbWVzcGFjZXMuJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoRGF0YXNldHNOYW1lc3BhY2UuaGFzT3duUHJvcGVydHkobmFtZSkpIHsKICAgICAgcmV0dXJuIERhdGFzZXRzTmFtZXNwYWNlW25hbWVdKGF0dHJpYnV0ZXMpOwogICAgfQogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9CiAgc3RhdGljIGRhdGFzZXRzKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgRGF0YXNldHMoYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyBkYXRhKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgRGF0YShhdHRyaWJ1dGVzKTsKICB9Cn0KZXhwb3J0cy5EYXRhc2V0c05hbWVzcGFjZSA9IERhdGFzZXRzTmFtZXNwYWNlOwoKLyoqKi8gfSksCi8qIDIyOSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuTG9jYWxlU2V0TmFtZXNwYWNlID0gdm9pZCAwOwp2YXIgX25hbWVzcGFjZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxNCk7CnZhciBfeGZhX29iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjEyKTsKdmFyIF91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMjEzKTsKY29uc3QgTE9DQUxFX1NFVF9OU19JRCA9IF9uYW1lc3BhY2VzLk5hbWVzcGFjZUlkcy5sb2NhbGVTZXQuaWQ7CmNsYXNzIENhbGVuZGFyU3ltYm9scyBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImNhbGVuZGFyU3ltYm9scyIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gImdyZWdvcmlhbiI7CiAgICB0aGlzLmRheU5hbWVzID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KDIpOwogICAgdGhpcy5lcmFOYW1lcyA9IG51bGw7CiAgICB0aGlzLm1lcmlkaWVtTmFtZXMgPSBudWxsOwogICAgdGhpcy5tb250aE5hbWVzID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KDIpOwogIH0KfQpjbGFzcyBDdXJyZW5jeVN5bWJvbCBleHRlbmRzIF94ZmFfb2JqZWN0LlN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImN1cnJlbmN5U3ltYm9sIik7CiAgICB0aGlzLm5hbWUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5uYW1lLCBbInN5bWJvbCIsICJpc29uYW1lIiwgImRlY2ltYWwiXSk7CiAgfQp9CmNsYXNzIEN1cnJlbmN5U3ltYm9scyBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImN1cnJlbmN5U3ltYm9scyIsIHRydWUpOwogICAgdGhpcy5jdXJyZW5jeVN5bWJvbCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgzKTsKICB9Cn0KY2xhc3MgRGF0ZVBhdHRlcm4gZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJkYXRlUGF0dGVybiIpOwogICAgdGhpcy5uYW1lID0gKDAsIF91dGlscy5nZXRTdHJpbmdPcHRpb24pKGF0dHJpYnV0ZXMubmFtZSwgWyJmdWxsIiwgImxvbmciLCAibWVkIiwgInNob3J0Il0pOwogIH0KfQpjbGFzcyBEYXRlUGF0dGVybnMgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJkYXRlUGF0dGVybnMiLCB0cnVlKTsKICAgIHRoaXMuZGF0ZVBhdHRlcm4gPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoNCk7CiAgfQp9CmNsYXNzIERhdGVUaW1lU3ltYm9scyBleHRlbmRzIF94ZmFfb2JqZWN0LkNvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJkYXRlVGltZVN5bWJvbHMiKTsKICB9Cn0KY2xhc3MgRGF5IGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAiZGF5Iik7CiAgfQp9CmNsYXNzIERheU5hbWVzIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAiZGF5TmFtZXMiLCB0cnVlKTsKICAgIHRoaXMuYWJiciA9ICgwLCBfdXRpbHMuZ2V0SW50ZWdlcikoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmFiYnIsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmRheSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSg3KTsKICB9Cn0KY2xhc3MgRXJhIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAiZXJhIik7CiAgfQp9CmNsYXNzIEVyYU5hbWVzIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAiZXJhTmFtZXMiLCB0cnVlKTsKICAgIHRoaXMuZXJhID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KDIpOwogIH0KfQpjbGFzcyBMb2NhbGUgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJsb2NhbGUiLCB0cnVlKTsKICAgIHRoaXMuZGVzYyA9IGF0dHJpYnV0ZXMuZGVzYyB8fCAiIjsKICAgIHRoaXMubmFtZSA9ICJpc29uYW1lIjsKICAgIHRoaXMuY2FsZW5kYXJTeW1ib2xzID0gbnVsbDsKICAgIHRoaXMuY3VycmVuY3lTeW1ib2xzID0gbnVsbDsKICAgIHRoaXMuZGF0ZVBhdHRlcm5zID0gbnVsbDsKICAgIHRoaXMuZGF0ZVRpbWVTeW1ib2xzID0gbnVsbDsKICAgIHRoaXMubnVtYmVyUGF0dGVybnMgPSBudWxsOwogICAgdGhpcy5udW1iZXJTeW1ib2xzID0gbnVsbDsKICAgIHRoaXMudGltZVBhdHRlcm5zID0gbnVsbDsKICAgIHRoaXMudHlwZUZhY2VzID0gbnVsbDsKICB9Cn0KY2xhc3MgTG9jYWxlU2V0IGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAibG9jYWxlU2V0IiwgdHJ1ZSk7CiAgICB0aGlzLmxvY2FsZSA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBNZXJpZGllbSBleHRlbmRzIF94ZmFfb2JqZWN0LlN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgIm1lcmlkaWVtIik7CiAgfQp9CmNsYXNzIE1lcmlkaWVtTmFtZXMgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJtZXJpZGllbU5hbWVzIiwgdHJ1ZSk7CiAgICB0aGlzLm1lcmlkaWVtID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KDIpOwogIH0KfQpjbGFzcyBNb250aCBleHRlbmRzIF94ZmFfb2JqZWN0LlN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgIm1vbnRoIik7CiAgfQp9CmNsYXNzIE1vbnRoTmFtZXMgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJtb250aE5hbWVzIiwgdHJ1ZSk7CiAgICB0aGlzLmFiYnIgPSAoMCwgX3V0aWxzLmdldEludGVnZXIpKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5hYmJyLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy5tb250aCA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSgxMik7CiAgfQp9CmNsYXNzIE51bWJlclBhdHRlcm4gZXh0ZW5kcyBfeGZhX29iamVjdC5TdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJudW1iZXJQYXR0ZXJuIik7CiAgICB0aGlzLm5hbWUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5uYW1lLCBbImZ1bGwiLCAibG9uZyIsICJtZWQiLCAic2hvcnQiXSk7CiAgfQp9CmNsYXNzIE51bWJlclBhdHRlcm5zIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAibnVtYmVyUGF0dGVybnMiLCB0cnVlKTsKICAgIHRoaXMubnVtYmVyUGF0dGVybiA9IG5ldyBfeGZhX29iamVjdC5YRkFPYmplY3RBcnJheSg0KTsKICB9Cn0KY2xhc3MgTnVtYmVyU3ltYm9sIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAibnVtYmVyU3ltYm9sIik7CiAgICB0aGlzLm5hbWUgPSAoMCwgX3V0aWxzLmdldFN0cmluZ09wdGlvbikoYXR0cmlidXRlcy5uYW1lLCBbImRlY2ltYWwiLCAiZ3JvdXBpbmciLCAicGVyY2VudCIsICJtaW51cyIsICJ6ZXJvIl0pOwogIH0KfQpjbGFzcyBOdW1iZXJTeW1ib2xzIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAibnVtYmVyU3ltYm9scyIsIHRydWUpOwogICAgdGhpcy5udW1iZXJTeW1ib2wgPSBuZXcgX3hmYV9vYmplY3QuWEZBT2JqZWN0QXJyYXkoNSk7CiAgfQp9CmNsYXNzIFRpbWVQYXR0ZXJuIGV4dGVuZHMgX3hmYV9vYmplY3QuU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAidGltZVBhdHRlcm4iKTsKICAgIHRoaXMubmFtZSA9ICgwLCBfdXRpbHMuZ2V0U3RyaW5nT3B0aW9uKShhdHRyaWJ1dGVzLm5hbWUsIFsiZnVsbCIsICJsb25nIiwgIm1lZCIsICJzaG9ydCJdKTsKICB9Cn0KY2xhc3MgVGltZVBhdHRlcm5zIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAidGltZVBhdHRlcm5zIiwgdHJ1ZSk7CiAgICB0aGlzLnRpbWVQYXR0ZXJuID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KDQpOwogIH0KfQpjbGFzcyBUeXBlRmFjZSBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgInR5cGVGYWNlIiwgdHJ1ZSk7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfCAiIjsKICB9Cn0KY2xhc3MgVHlwZUZhY2VzIGV4dGVuZHMgX3hmYV9vYmplY3QuWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAidHlwZUZhY2VzIiwgdHJ1ZSk7CiAgICB0aGlzLnR5cGVGYWNlID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIExvY2FsZVNldE5hbWVzcGFjZSB7CiAgc3RhdGljIFtfbmFtZXNwYWNlcy4kYnVpbGRYRkFPYmplY3RdKG5hbWUsIGF0dHJpYnV0ZXMpIHsKICAgIGlmIChMb2NhbGVTZXROYW1lc3BhY2UuaGFzT3duUHJvcGVydHkobmFtZSkpIHsKICAgICAgcmV0dXJuIExvY2FsZVNldE5hbWVzcGFjZVtuYW1lXShhdHRyaWJ1dGVzKTsKICAgIH0KICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQogIHN0YXRpYyBjYWxlbmRhclN5bWJvbHMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ2FsZW5kYXJTeW1ib2xzKGF0dHJzKTsKICB9CiAgc3RhdGljIGN1cnJlbmN5U3ltYm9sKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEN1cnJlbmN5U3ltYm9sKGF0dHJzKTsKICB9CiAgc3RhdGljIGN1cnJlbmN5U3ltYm9scyhhdHRycykgewogICAgcmV0dXJuIG5ldyBDdXJyZW5jeVN5bWJvbHMoYXR0cnMpOwogIH0KICBzdGF0aWMgZGF0ZVBhdHRlcm4oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRGF0ZVBhdHRlcm4oYXR0cnMpOwogIH0KICBzdGF0aWMgZGF0ZVBhdHRlcm5zKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGVQYXR0ZXJucyhhdHRycyk7CiAgfQogIHN0YXRpYyBkYXRlVGltZVN5bWJvbHMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRGF0ZVRpbWVTeW1ib2xzKGF0dHJzKTsKICB9CiAgc3RhdGljIGRheShhdHRycykgewogICAgcmV0dXJuIG5ldyBEYXkoYXR0cnMpOwogIH0KICBzdGF0aWMgZGF5TmFtZXMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRGF5TmFtZXMoYXR0cnMpOwogIH0KICBzdGF0aWMgZXJhKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVyYShhdHRycyk7CiAgfQogIHN0YXRpYyBlcmFOYW1lcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBFcmFOYW1lcyhhdHRycyk7CiAgfQogIHN0YXRpYyBsb2NhbGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTG9jYWxlKGF0dHJzKTsKICB9CiAgc3RhdGljIGxvY2FsZVNldChhdHRycykgewogICAgcmV0dXJuIG5ldyBMb2NhbGVTZXQoYXR0cnMpOwogIH0KICBzdGF0aWMgbWVyaWRpZW0oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTWVyaWRpZW0oYXR0cnMpOwogIH0KICBzdGF0aWMgbWVyaWRpZW1OYW1lcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBNZXJpZGllbU5hbWVzKGF0dHJzKTsKICB9CiAgc3RhdGljIG1vbnRoKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1vbnRoKGF0dHJzKTsKICB9CiAgc3RhdGljIG1vbnRoTmFtZXMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTW9udGhOYW1lcyhhdHRycyk7CiAgfQogIHN0YXRpYyBudW1iZXJQYXR0ZXJuKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE51bWJlclBhdHRlcm4oYXR0cnMpOwogIH0KICBzdGF0aWMgbnVtYmVyUGF0dGVybnMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTnVtYmVyUGF0dGVybnMoYXR0cnMpOwogIH0KICBzdGF0aWMgbnVtYmVyU3ltYm9sKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE51bWJlclN5bWJvbChhdHRycyk7CiAgfQogIHN0YXRpYyBudW1iZXJTeW1ib2xzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE51bWJlclN5bWJvbHMoYXR0cnMpOwogIH0KICBzdGF0aWMgdGltZVBhdHRlcm4oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVGltZVBhdHRlcm4oYXR0cnMpOwogIH0KICBzdGF0aWMgdGltZVBhdHRlcm5zKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFRpbWVQYXR0ZXJucyhhdHRycyk7CiAgfQogIHN0YXRpYyB0eXBlRmFjZShhdHRycykgewogICAgcmV0dXJuIG5ldyBUeXBlRmFjZShhdHRycyk7CiAgfQogIHN0YXRpYyB0eXBlRmFjZXMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVHlwZUZhY2VzKGF0dHJzKTsKICB9Cn0KZXhwb3J0cy5Mb2NhbGVTZXROYW1lc3BhY2UgPSBMb2NhbGVTZXROYW1lc3BhY2U7CgovKioqLyB9KSwKLyogMjMwICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5TaWduYXR1cmVOYW1lc3BhY2UgPSB2b2lkIDA7CnZhciBfbmFtZXNwYWNlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMjE0KTsKdmFyIF94ZmFfb2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTIpOwpjb25zdCBTSUdOQVRVUkVfTlNfSUQgPSBfbmFtZXNwYWNlcy5OYW1lc3BhY2VJZHMuc2lnbmF0dXJlLmlkOwpjbGFzcyBTaWduYXR1cmUgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFNJR05BVFVSRV9OU19JRCwgInNpZ25hdHVyZSIsIHRydWUpOwogIH0KfQpjbGFzcyBTaWduYXR1cmVOYW1lc3BhY2UgewogIHN0YXRpYyBbX25hbWVzcGFjZXMuJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoU2lnbmF0dXJlTmFtZXNwYWNlLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgIHJldHVybiBTaWduYXR1cmVOYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgc2lnbmF0dXJlKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgU2lnbmF0dXJlKGF0dHJpYnV0ZXMpOwogIH0KfQpleHBvcnRzLlNpZ25hdHVyZU5hbWVzcGFjZSA9IFNpZ25hdHVyZU5hbWVzcGFjZTsKCi8qKiovIH0pLAovKiAyMzEgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlN0eWxlc2hlZXROYW1lc3BhY2UgPSB2b2lkIDA7CnZhciBfbmFtZXNwYWNlcyA9IF9fd19wZGZqc19yZXF1aXJlX18oMjE0KTsKdmFyIF94ZmFfb2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTIpOwpjb25zdCBTVFlMRVNIRUVUX05TX0lEID0gX25hbWVzcGFjZXMuTmFtZXNwYWNlSWRzLnN0eWxlc2hlZXQuaWQ7CmNsYXNzIFN0eWxlc2hlZXQgZXh0ZW5kcyBfeGZhX29iamVjdC5YRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFNUWUxFU0hFRVRfTlNfSUQsICJzdHlsZXNoZWV0IiwgdHJ1ZSk7CiAgfQp9CmNsYXNzIFN0eWxlc2hlZXROYW1lc3BhY2UgewogIHN0YXRpYyBbX25hbWVzcGFjZXMuJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoU3R5bGVzaGVldE5hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICByZXR1cm4gU3R5bGVzaGVldE5hbWVzcGFjZVtuYW1lXShhdHRyaWJ1dGVzKTsKICAgIH0KICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQogIHN0YXRpYyBzdHlsZXNoZWV0KGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgU3R5bGVzaGVldChhdHRyaWJ1dGVzKTsKICB9Cn0KZXhwb3J0cy5TdHlsZXNoZWV0TmFtZXNwYWNlID0gU3R5bGVzaGVldE5hbWVzcGFjZTsKCi8qKiovIH0pLAovKiAyMzIgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlhkcE5hbWVzcGFjZSA9IHZvaWQgMDsKdmFyIF9uYW1lc3BhY2VzID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTQpOwp2YXIgX3hmYV9vYmplY3QgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxMik7CmNvbnN0IFhEUF9OU19JRCA9IF9uYW1lc3BhY2VzLk5hbWVzcGFjZUlkcy54ZHAuaWQ7CmNsYXNzIFhkcCBleHRlbmRzIF94ZmFfb2JqZWN0LlhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoWERQX05TX0lELCAieGRwIiwgdHJ1ZSk7CiAgICB0aGlzLnV1aWQgPSBhdHRyaWJ1dGVzLnV1aWQgfHwgIiI7CiAgICB0aGlzLnRpbWVTdGFtcCA9IGF0dHJpYnV0ZXMudGltZVN0YW1wIHx8ICIiOwogICAgdGhpcy5jb25maWcgPSBudWxsOwogICAgdGhpcy5jb25uZWN0aW9uU2V0ID0gbnVsbDsKICAgIHRoaXMuZGF0YXNldHMgPSBudWxsOwogICAgdGhpcy5sb2NhbGVTZXQgPSBudWxsOwogICAgdGhpcy5zdHlsZXNoZWV0ID0gbmV3IF94ZmFfb2JqZWN0LlhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRlbXBsYXRlID0gbnVsbDsKICB9CiAgW194ZmFfb2JqZWN0LiRvbkNoaWxkQ2hlY2tdKGNoaWxkKSB7CiAgICBjb25zdCBucyA9IF9uYW1lc3BhY2VzLk5hbWVzcGFjZUlkc1tjaGlsZFtfeGZhX29iamVjdC4kbm9kZU5hbWVdXTsKICAgIHJldHVybiBucyAmJiBjaGlsZFtfeGZhX29iamVjdC4kbmFtZXNwYWNlSWRdID09PSBucy5pZDsKICB9Cn0KY2xhc3MgWGRwTmFtZXNwYWNlIHsKICBzdGF0aWMgW19uYW1lc3BhY2VzLiRidWlsZFhGQU9iamVjdF0obmFtZSwgYXR0cmlidXRlcykgewogICAgaWYgKFhkcE5hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICByZXR1cm4gWGRwTmFtZXNwYWNlW25hbWVdKGF0dHJpYnV0ZXMpOwogICAgfQogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9CiAgc3RhdGljIHhkcChhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IFhkcChhdHRyaWJ1dGVzKTsKICB9Cn0KZXhwb3J0cy5YZHBOYW1lc3BhY2UgPSBYZHBOYW1lc3BhY2U7CgovKioqLyB9KSwKLyogMjMzICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5YaHRtbE5hbWVzcGFjZSA9IHZvaWQgMDsKdmFyIF94ZmFfb2JqZWN0ID0gX193X3BkZmpzX3JlcXVpcmVfXygyMTIpOwp2YXIgX25hbWVzcGFjZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxNCk7CnZhciBfaHRtbF91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMjE5KTsKdmFyIF91dGlscyA9IF9fd19wZGZqc19yZXF1aXJlX18oMjEzKTsKY29uc3QgWEhUTUxfTlNfSUQgPSBfbmFtZXNwYWNlcy5OYW1lc3BhY2VJZHMueGh0bWwuaWQ7CmNvbnN0ICRyaWNoVGV4dCA9IFN5bWJvbCgpOwpjb25zdCBWQUxJRF9TVFlMRVMgPSBuZXcgU2V0KFsiY29sb3IiLCAiZm9udCIsICJmb250LWZhbWlseSIsICJmb250LXNpemUiLCAiZm9udC1zdHJldGNoIiwgImZvbnQtc3R5bGUiLCAiZm9udC13ZWlnaHQiLCAibWFyZ2luIiwgIm1hcmdpbi1ib3R0b20iLCAibWFyZ2luLWxlZnQiLCAibWFyZ2luLXJpZ2h0IiwgIm1hcmdpbi10b3AiLCAibGV0dGVyLXNwYWNpbmciLCAibGluZS1oZWlnaHQiLCAib3JwaGFucyIsICJwYWdlLWJyZWFrLWFmdGVyIiwgInBhZ2UtYnJlYWstYmVmb3JlIiwgInBhZ2UtYnJlYWstaW5zaWRlIiwgInRhYi1pbnRlcnZhbCIsICJ0YWItc3RvcCIsICJ0ZXh0LWFsaWduIiwgInRleHQtZGVjb3JhdGlvbiIsICJ0ZXh0LWluZGVudCIsICJ2ZXJ0aWNhbC1hbGlnbiIsICJ3aWRvd3MiLCAia2VybmluZy1tb2RlIiwgInhmYS1mb250LWhvcml6b250YWwtc2NhbGUiLCAieGZhLWZvbnQtdmVydGljYWwtc2NhbGUiLCAieGZhLXNwYWNlcnVuIiwgInhmYS10YWItc3RvcHMiXSk7CmNvbnN0IFN0eWxlTWFwcGluZyA9IG5ldyBNYXAoW1sicGFnZS1icmVhay1hZnRlciIsICJicmVha0FmdGVyIl0sIFsicGFnZS1icmVhay1iZWZvcmUiLCAiYnJlYWtCZWZvcmUiXSwgWyJwYWdlLWJyZWFrLWluc2lkZSIsICJicmVha0luc2lkZSJdLCBbImtlcm5pbmctbW9kZSIsIHZhbHVlID0+IHZhbHVlID09PSAibm9uZSIgPyAibm9uZSIgOiAibm9ybWFsIl0sIFsieGZhLWZvbnQtaG9yaXpvbnRhbC1zY2FsZSIsIHZhbHVlID0+IGBzY2FsZVgoJHtNYXRoLm1heCgwLCBNYXRoLm1pbihwYXJzZUludCh2YWx1ZSkgLyAxMDApKS50b0ZpeGVkKDIpfSlgXSwgWyJ4ZmEtZm9udC12ZXJ0aWNhbC1zY2FsZSIsIHZhbHVlID0+IGBzY2FsZVkoJHtNYXRoLm1heCgwLCBNYXRoLm1pbihwYXJzZUludCh2YWx1ZSkgLyAxMDApKS50b0ZpeGVkKDIpfSlgXSwgWyJ4ZmEtc3BhY2VydW4iLCAiIl0sIFsieGZhLXRhYi1zdG9wcyIsICIiXSwgWyJmb250LXNpemUiLCAodmFsdWUsIG9yaWdpbmFsKSA9PiB7CiAgdmFsdWUgPSBvcmlnaW5hbC5mb250U2l6ZSA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHZhbHVlKTsKICByZXR1cm4gKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykoMC45OSAqIHZhbHVlKTsKfV0sIFsibGV0dGVyLXNwYWNpbmciLCB2YWx1ZSA9PiAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSgoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KSh2YWx1ZSkpXSwgWyJsaW5lLWhlaWdodCIsIHZhbHVlID0+ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKCgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHZhbHVlKSldLCBbIm1hcmdpbiIsIHZhbHVlID0+ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKCgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHZhbHVlKSldLCBbIm1hcmdpbi1ib3R0b20iLCB2YWx1ZSA9PiAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSgoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KSh2YWx1ZSkpXSwgWyJtYXJnaW4tbGVmdCIsIHZhbHVlID0+ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKCgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHZhbHVlKSldLCBbIm1hcmdpbi1yaWdodCIsIHZhbHVlID0+ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKCgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHZhbHVlKSldLCBbIm1hcmdpbi10b3AiLCB2YWx1ZSA9PiAoMCwgX2h0bWxfdXRpbHMubWVhc3VyZVRvU3RyaW5nKSgoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KSh2YWx1ZSkpXSwgWyJ0ZXh0LWluZGVudCIsIHZhbHVlID0+ICgwLCBfaHRtbF91dGlscy5tZWFzdXJlVG9TdHJpbmcpKCgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHZhbHVlKSldLCBbImZvbnQtZmFtaWx5IiwgdmFsdWUgPT4gdmFsdWVdLCBbInZlcnRpY2FsLWFsaWduIiwgdmFsdWUgPT4gKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykoKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkodmFsdWUpKV1dKTsKY29uc3Qgc3BhY2VzUmVnRXhwID0gL1xzKy9nOwpjb25zdCBjcmxmUmVnRXhwID0gL1tcclxuXSsvZzsKY29uc3QgY3JsZkZvclJpY2hUZXh0UmVnRXhwID0gL1xyXG4/L2c7CmZ1bmN0aW9uIG1hcFN0eWxlKHN0eWxlU3RyLCBub2RlLCByaWNoVGV4dCkgewogIGNvbnN0IHN0eWxlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBpZiAoIXN0eWxlU3RyKSB7CiAgICByZXR1cm4gc3R5bGU7CiAgfQogIGNvbnN0IG9yaWdpbmFsID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBzdHlsZVN0ci5zcGxpdCgiOyIpLm1hcChzID0+IHMuc3BsaXQoIjoiLCAyKSkpIHsKICAgIGNvbnN0IG1hcHBpbmcgPSBTdHlsZU1hcHBpbmcuZ2V0KGtleSk7CiAgICBpZiAobWFwcGluZyA9PT0gIiIpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBsZXQgbmV3VmFsdWUgPSB2YWx1ZTsKICAgIGlmIChtYXBwaW5nKSB7CiAgICAgIGlmICh0eXBlb2YgbWFwcGluZyA9PT0gInN0cmluZyIpIHsKICAgICAgICBuZXdWYWx1ZSA9IG1hcHBpbmc7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmV3VmFsdWUgPSBtYXBwaW5nKHZhbHVlLCBvcmlnaW5hbCk7CiAgICAgIH0KICAgIH0KICAgIGlmIChrZXkuZW5kc1dpdGgoInNjYWxlIikpIHsKICAgICAgaWYgKHN0eWxlLnRyYW5zZm9ybSkgewogICAgICAgIHN0eWxlLnRyYW5zZm9ybSA9IGAke3N0eWxlW2tleV19ICR7bmV3VmFsdWV9YDsKICAgICAgfSBlbHNlIHsKICAgICAgICBzdHlsZS50cmFuc2Zvcm0gPSBuZXdWYWx1ZTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgc3R5bGVba2V5LnJlcGxhY2VBbGwoLy0oW2EtekEtWl0pL2csIChfLCB4KSA9PiB4LnRvVXBwZXJDYXNlKCkpXSA9IG5ld1ZhbHVlOwogICAgfQogIH0KICBpZiAoc3R5bGUuZm9udEZhbWlseSkgewogICAgKDAsIF9odG1sX3V0aWxzLnNldEZvbnRGYW1pbHkpKHsKICAgICAgdHlwZWZhY2U6IHN0eWxlLmZvbnRGYW1pbHksCiAgICAgIHdlaWdodDogc3R5bGUuZm9udFdlaWdodCB8fCAibm9ybWFsIiwKICAgICAgcG9zdHVyZTogc3R5bGUuZm9udFN0eWxlIHx8ICJub3JtYWwiLAogICAgICBzaXplOiBvcmlnaW5hbC5mb250U2l6ZSB8fCAwCiAgICB9LCBub2RlLCBub2RlW194ZmFfb2JqZWN0LiRnbG9iYWxEYXRhXS5mb250RmluZGVyLCBzdHlsZSk7CiAgfQogIGlmIChyaWNoVGV4dCAmJiBzdHlsZS52ZXJ0aWNhbEFsaWduICYmIHN0eWxlLnZlcnRpY2FsQWxpZ24gIT09ICIwcHgiICYmIHN0eWxlLmZvbnRTaXplKSB7CiAgICBjb25zdCBTVUJfU1VQRVJfU0NSSVBUX0ZBQ1RPUiA9IDAuNTgzOwogICAgY29uc3QgVkVSVElDQUxfRkFDVE9SID0gMC4zMzM7CiAgICBjb25zdCBmb250U2l6ZSA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHN0eWxlLmZvbnRTaXplKTsKICAgIHN0eWxlLmZvbnRTaXplID0gKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykoZm9udFNpemUgKiBTVUJfU1VQRVJfU0NSSVBUX0ZBQ1RPUik7CiAgICBzdHlsZS52ZXJ0aWNhbEFsaWduID0gKDAsIF9odG1sX3V0aWxzLm1lYXN1cmVUb1N0cmluZykoTWF0aC5zaWduKCgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHN0eWxlLnZlcnRpY2FsQWxpZ24pKSAqIGZvbnRTaXplICogVkVSVElDQUxfRkFDVE9SKTsKICB9CiAgaWYgKHJpY2hUZXh0ICYmIHN0eWxlLmZvbnRTaXplKSB7CiAgICBzdHlsZS5mb250U2l6ZSA9IGBjYWxjKCR7c3R5bGUuZm9udFNpemV9ICogdmFyKC0tc2NhbGUtZmFjdG9yKSlgOwogIH0KICAoMCwgX2h0bWxfdXRpbHMuZml4VGV4dEluZGVudCkoc3R5bGUpOwogIHJldHVybiBzdHlsZTsKfQpmdW5jdGlvbiBjaGVja1N0eWxlKG5vZGUpIHsKICBpZiAoIW5vZGUuc3R5bGUpIHsKICAgIHJldHVybiAiIjsKICB9CiAgcmV0dXJuIG5vZGUuc3R5bGUudHJpbSgpLnNwbGl0KC9ccyo7XHMqLykuZmlsdGVyKHMgPT4gISFzKS5tYXAocyA9PiBzLnNwbGl0KC9ccyo6XHMqLywgMikpLmZpbHRlcihfcmVmID0+IHsKICAgIGxldCBba2V5LCB2YWx1ZV0gPSBfcmVmOwogICAgaWYgKGtleSA9PT0gImZvbnQtZmFtaWx5IikgewogICAgICBub2RlW194ZmFfb2JqZWN0LiRnbG9iYWxEYXRhXS51c2VkVHlwZWZhY2VzLmFkZCh2YWx1ZSk7CiAgICB9CiAgICByZXR1cm4gVkFMSURfU1RZTEVTLmhhcyhrZXkpOwogIH0pLm1hcChrdiA9PiBrdi5qb2luKCI6IikpLmpvaW4oIjsiKTsKfQpjb25zdCBOb1doaXRlcyA9IG5ldyBTZXQoWyJib2R5IiwgImh0bWwiXSk7CmNsYXNzIFhodG1sT2JqZWN0IGV4dGVuZHMgX3hmYV9vYmplY3QuWG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzLCBuYW1lKSB7CiAgICBzdXBlcihYSFRNTF9OU19JRCwgbmFtZSk7CiAgICB0aGlzWyRyaWNoVGV4dF0gPSBmYWxzZTsKICAgIHRoaXMuc3R5bGUgPSBhdHRyaWJ1dGVzLnN0eWxlIHx8ICIiOwogIH0KICBbX3hmYV9vYmplY3QuJGNsZWFuXShidWlsZGVyKSB7CiAgICBzdXBlcltfeGZhX29iamVjdC4kY2xlYW5dKGJ1aWxkZXIpOwogICAgdGhpcy5zdHlsZSA9IGNoZWNrU3R5bGUodGhpcyk7CiAgfQogIFtfeGZhX29iamVjdC4kYWNjZXB0V2hpdGVzcGFjZV0oKSB7CiAgICByZXR1cm4gIU5vV2hpdGVzLmhhcyh0aGlzW194ZmFfb2JqZWN0LiRub2RlTmFtZV0pOwogIH0KICBbX3hmYV9vYmplY3QuJG9uVGV4dF0oc3RyKSB7CiAgICBsZXQgcmljaFRleHQgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IGZhbHNlOwogICAgaWYgKCFyaWNoVGV4dCkgewogICAgICBzdHIgPSBzdHIucmVwbGFjZUFsbChjcmxmUmVnRXhwLCAiIik7CiAgICAgIGlmICghdGhpcy5zdHlsZS5pbmNsdWRlcygieGZhLXNwYWNlcnVuOnllcyIpKSB7CiAgICAgICAgc3RyID0gc3RyLnJlcGxhY2VBbGwoc3BhY2VzUmVnRXhwLCAiICIpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzWyRyaWNoVGV4dF0gPSB0cnVlOwogICAgfQogICAgaWYgKHN0cikgewogICAgICB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSArPSBzdHI7CiAgICB9CiAgfQogIFtfeGZhX29iamVjdC4kcHVzaEdseXBoc10obWVhc3VyZSkgewogICAgbGV0IG11c3RQb3AgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHRydWU7CiAgICBjb25zdCB4ZmFGb250ID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGNvbnN0IG1hcmdpbiA9IHsKICAgICAgdG9wOiBOYU4sCiAgICAgIGJvdHRvbTogTmFOLAogICAgICBsZWZ0OiBOYU4sCiAgICAgIHJpZ2h0OiBOYU4KICAgIH07CiAgICBsZXQgbGluZUhlaWdodCA9IG51bGw7CiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiB0aGlzLnN0eWxlLnNwbGl0KCI7IikubWFwKHMgPT4gcy5zcGxpdCgiOiIsIDIpKSkgewogICAgICBzd2l0Y2ggKGtleSkgewogICAgICAgIGNhc2UgImZvbnQtZmFtaWx5IjoKICAgICAgICAgIHhmYUZvbnQudHlwZWZhY2UgPSAoMCwgX3V0aWxzLnN0cmlwUXVvdGVzKSh2YWx1ZSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJmb250LXNpemUiOgogICAgICAgICAgeGZhRm9udC5zaXplID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkodmFsdWUpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZm9udC13ZWlnaHQiOgogICAgICAgICAgeGZhRm9udC53ZWlnaHQgPSB2YWx1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImZvbnQtc3R5bGUiOgogICAgICAgICAgeGZhRm9udC5wb3N0dXJlID0gdmFsdWU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJsZXR0ZXItc3BhY2luZyI6CiAgICAgICAgICB4ZmFGb250LmxldHRlclNwYWNpbmcgPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KSh2YWx1ZSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJtYXJnaW4iOgogICAgICAgICAgY29uc3QgdmFsdWVzID0gdmFsdWUuc3BsaXQoLyBcdC8pLm1hcCh4ID0+ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHgpKTsKICAgICAgICAgIHN3aXRjaCAodmFsdWVzLmxlbmd0aCkgewogICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgbWFyZ2luLnRvcCA9IG1hcmdpbi5ib3R0b20gPSBtYXJnaW4ubGVmdCA9IG1hcmdpbi5yaWdodCA9IHZhbHVlc1swXTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICAgIG1hcmdpbi50b3AgPSBtYXJnaW4uYm90dG9tID0gdmFsdWVzWzBdOwogICAgICAgICAgICAgIG1hcmdpbi5sZWZ0ID0gbWFyZ2luLnJpZ2h0ID0gdmFsdWVzWzFdOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDM6CiAgICAgICAgICAgICAgbWFyZ2luLnRvcCA9IHZhbHVlc1swXTsKICAgICAgICAgICAgICBtYXJnaW4uYm90dG9tID0gdmFsdWVzWzJdOwogICAgICAgICAgICAgIG1hcmdpbi5sZWZ0ID0gbWFyZ2luLnJpZ2h0ID0gdmFsdWVzWzFdOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDQ6CiAgICAgICAgICAgICAgbWFyZ2luLnRvcCA9IHZhbHVlc1swXTsKICAgICAgICAgICAgICBtYXJnaW4ubGVmdCA9IHZhbHVlc1sxXTsKICAgICAgICAgICAgICBtYXJnaW4uYm90dG9tID0gdmFsdWVzWzJdOwogICAgICAgICAgICAgIG1hcmdpbi5yaWdodCA9IHZhbHVlc1szXTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm1hcmdpbi10b3AiOgogICAgICAgICAgbWFyZ2luLnRvcCA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHZhbHVlKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm1hcmdpbi1ib3R0b20iOgogICAgICAgICAgbWFyZ2luLmJvdHRvbSA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHZhbHVlKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm1hcmdpbi1sZWZ0IjoKICAgICAgICAgIG1hcmdpbi5sZWZ0ID0gKDAsIF91dGlscy5nZXRNZWFzdXJlbWVudCkodmFsdWUpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibWFyZ2luLXJpZ2h0IjoKICAgICAgICAgIG1hcmdpbi5yaWdodCA9ICgwLCBfdXRpbHMuZ2V0TWVhc3VyZW1lbnQpKHZhbHVlKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImxpbmUtaGVpZ2h0IjoKICAgICAgICAgIGxpbmVIZWlnaHQgPSAoMCwgX3V0aWxzLmdldE1lYXN1cmVtZW50KSh2YWx1ZSk7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgbWVhc3VyZS5wdXNoRGF0YSh4ZmFGb250LCBtYXJnaW4sIGxpbmVIZWlnaHQpOwogICAgaWYgKHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdKSB7CiAgICAgIG1lYXN1cmUuYWRkU3RyaW5nKHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdKTsKICAgIH0gZWxzZSB7CiAgICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpc1tfeGZhX29iamVjdC4kZ2V0Q2hpbGRyZW5dKCkpIHsKICAgICAgICBpZiAoY2hpbGRbX3hmYV9vYmplY3QuJG5vZGVOYW1lXSA9PT0gIiN0ZXh0IikgewogICAgICAgICAgbWVhc3VyZS5hZGRTdHJpbmcoY2hpbGRbX3hmYV9vYmplY3QuJGNvbnRlbnRdKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjaGlsZFtfeGZhX29iamVjdC4kcHVzaEdseXBoc10obWVhc3VyZSk7CiAgICAgIH0KICAgIH0KICAgIGlmIChtdXN0UG9wKSB7CiAgICAgIG1lYXN1cmUucG9wRm9udCgpOwogICAgfQogIH0KICBbX3hmYV9vYmplY3QuJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IGNoaWxkcmVuID0gW107CiAgICB0aGlzW194ZmFfb2JqZWN0LiRleHRyYV0gPSB7CiAgICAgIGNoaWxkcmVuCiAgICB9OwogICAgdGhpc1tfeGZhX29iamVjdC4kY2hpbGRyZW5Ub0hUTUxdKHt9KTsKICAgIGlmIChjaGlsZHJlbi5sZW5ndGggPT09IDAgJiYgIXRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdKSB7CiAgICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGxldCB2YWx1ZTsKICAgIGlmICh0aGlzWyRyaWNoVGV4dF0pIHsKICAgICAgdmFsdWUgPSB0aGlzW194ZmFfb2JqZWN0LiRjb250ZW50XSA/IHRoaXNbX3hmYV9vYmplY3QuJGNvbnRlbnRdLnJlcGxhY2VBbGwoY3JsZkZvclJpY2hUZXh0UmVnRXhwLCAiXG4iKSA6IHVuZGVmaW5lZDsKICAgIH0gZWxzZSB7CiAgICAgIHZhbHVlID0gdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0gfHwgdW5kZWZpbmVkOwogICAgfQogICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICBuYW1lOiB0aGlzW194ZmFfb2JqZWN0LiRub2RlTmFtZV0sCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBocmVmOiB0aGlzLmhyZWYsCiAgICAgICAgc3R5bGU6IG1hcFN0eWxlKHRoaXMuc3R5bGUsIHRoaXMsIHRoaXNbJHJpY2hUZXh0XSkKICAgICAgfSwKICAgICAgY2hpbGRyZW4sCiAgICAgIHZhbHVlCiAgICB9KTsKICB9Cn0KY2xhc3MgQSBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAiYSIpOwogICAgdGhpcy5ocmVmID0gKDAsIF9odG1sX3V0aWxzLmZpeFVSTCkoYXR0cmlidXRlcy5ocmVmKSB8fCAiIjsKICB9Cn0KY2xhc3MgQiBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAiYiIpOwogIH0KICBbX3hmYV9vYmplY3QuJHB1c2hHbHlwaHNdKG1lYXN1cmUpIHsKICAgIG1lYXN1cmUucHVzaEZvbnQoewogICAgICB3ZWlnaHQ6ICJib2xkIgogICAgfSk7CiAgICBzdXBlcltfeGZhX29iamVjdC4kcHVzaEdseXBoc10obWVhc3VyZSk7CiAgICBtZWFzdXJlLnBvcEZvbnQoKTsKICB9Cn0KY2xhc3MgQm9keSBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAiYm9keSIpOwogIH0KICBbX3hmYV9vYmplY3QuJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IHJlcyA9IHN1cGVyW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKTsKICAgIGNvbnN0IHsKICAgICAgaHRtbAogICAgfSA9IHJlczsKICAgIGlmICghaHRtbCkgewogICAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuRU1QVFk7CiAgICB9CiAgICBodG1sLm5hbWUgPSAiZGl2IjsKICAgIGh0bWwuYXR0cmlidXRlcy5jbGFzcyA9IFsieGZhUmljaCJdOwogICAgcmV0dXJuIHJlczsKICB9Cn0KY2xhc3MgQnIgZXh0ZW5kcyBYaHRtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoYXR0cmlidXRlcywgImJyIik7CiAgfQogIFtfeGZhX29iamVjdC4kdGV4dF0oKSB7CiAgICByZXR1cm4gIlxuIjsKICB9CiAgW194ZmFfb2JqZWN0LiRwdXNoR2x5cGhzXShtZWFzdXJlKSB7CiAgICBtZWFzdXJlLmFkZFN0cmluZygiXG4iKTsKICB9CiAgW194ZmFfb2JqZWN0LiR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgIG5hbWU6ICJiciIKICAgIH0pOwogIH0KfQpjbGFzcyBIdG1sIGV4dGVuZHMgWGh0bWxPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKGF0dHJpYnV0ZXMsICJodG1sIik7CiAgfQogIFtfeGZhX29iamVjdC4kdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgY29uc3QgY2hpbGRyZW4gPSBbXTsKICAgIHRoaXNbX3hmYV9vYmplY3QuJGV4dHJhXSA9IHsKICAgICAgY2hpbGRyZW4KICAgIH07CiAgICB0aGlzW194ZmFfb2JqZWN0LiRjaGlsZHJlblRvSFRNTF0oe30pOwogICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gX3V0aWxzLkhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgICAgbmFtZTogImRpdiIsCiAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgY2xhc3M6IFsieGZhUmljaCJdLAogICAgICAgICAgc3R5bGU6IHt9CiAgICAgICAgfSwKICAgICAgICB2YWx1ZTogdGhpc1tfeGZhX29iamVjdC4kY29udGVudF0gfHwgIiIKICAgICAgfSk7CiAgICB9CiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID09PSAxKSB7CiAgICAgIGNvbnN0IGNoaWxkID0gY2hpbGRyZW5bMF07CiAgICAgIGlmIChjaGlsZC5hdHRyaWJ1dGVzICYmIGNoaWxkLmF0dHJpYnV0ZXMuY2xhc3MuaW5jbHVkZXMoInhmYVJpY2giKSkgewogICAgICAgIHJldHVybiBfdXRpbHMuSFRNTFJlc3VsdC5zdWNjZXNzKGNoaWxkKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIF91dGlscy5IVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICBuYW1lOiAiZGl2IiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGNsYXNzOiBbInhmYVJpY2giXSwKICAgICAgICBzdHlsZToge30KICAgICAgfSwKICAgICAgY2hpbGRyZW4KICAgIH0pOwogIH0KfQpjbGFzcyBJIGV4dGVuZHMgWGh0bWxPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKGF0dHJpYnV0ZXMsICJpIik7CiAgfQogIFtfeGZhX29iamVjdC4kcHVzaEdseXBoc10obWVhc3VyZSkgewogICAgbWVhc3VyZS5wdXNoRm9udCh7CiAgICAgIHBvc3R1cmU6ICJpdGFsaWMiCiAgICB9KTsKICAgIHN1cGVyW194ZmFfb2JqZWN0LiRwdXNoR2x5cGhzXShtZWFzdXJlKTsKICAgIG1lYXN1cmUucG9wRm9udCgpOwogIH0KfQpjbGFzcyBMaSBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAibGkiKTsKICB9Cn0KY2xhc3MgT2wgZXh0ZW5kcyBYaHRtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoYXR0cmlidXRlcywgIm9sIik7CiAgfQp9CmNsYXNzIFAgZXh0ZW5kcyBYaHRtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoYXR0cmlidXRlcywgInAiKTsKICB9CiAgW194ZmFfb2JqZWN0LiRwdXNoR2x5cGhzXShtZWFzdXJlKSB7CiAgICBzdXBlcltfeGZhX29iamVjdC4kcHVzaEdseXBoc10obWVhc3VyZSwgZmFsc2UpOwogICAgbWVhc3VyZS5hZGRTdHJpbmcoIlxuIik7CiAgICBtZWFzdXJlLmFkZFBhcmEoKTsKICAgIG1lYXN1cmUucG9wRm9udCgpOwogIH0KICBbX3hmYV9vYmplY3QuJHRleHRdKCkgewogICAgY29uc3Qgc2libGluZ3MgPSB0aGlzW194ZmFfb2JqZWN0LiRnZXRQYXJlbnRdKClbX3hmYV9vYmplY3QuJGdldENoaWxkcmVuXSgpOwogICAgaWYgKHNpYmxpbmdzLmF0KC0xKSA9PT0gdGhpcykgewogICAgICByZXR1cm4gc3VwZXJbX3hmYV9vYmplY3QuJHRleHRdKCk7CiAgICB9CiAgICByZXR1cm4gc3VwZXJbX3hmYV9vYmplY3QuJHRleHRdKCkgKyAiXG4iOwogIH0KfQpjbGFzcyBTcGFuIGV4dGVuZHMgWGh0bWxPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKGF0dHJpYnV0ZXMsICJzcGFuIik7CiAgfQp9CmNsYXNzIFN1YiBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAic3ViIik7CiAgfQp9CmNsYXNzIFN1cCBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAic3VwIik7CiAgfQp9CmNsYXNzIFVsIGV4dGVuZHMgWGh0bWxPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKGF0dHJpYnV0ZXMsICJ1bCIpOwogIH0KfQpjbGFzcyBYaHRtbE5hbWVzcGFjZSB7CiAgc3RhdGljIFtfbmFtZXNwYWNlcy4kYnVpbGRYRkFPYmplY3RdKG5hbWUsIGF0dHJpYnV0ZXMpIHsKICAgIGlmIChYaHRtbE5hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICByZXR1cm4gWGh0bWxOYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgYShhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IEEoYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyBiKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgQihhdHRyaWJ1dGVzKTsKICB9CiAgc3RhdGljIGJvZHkoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBCb2R5KGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgYnIoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBCcihhdHRyaWJ1dGVzKTsKICB9CiAgc3RhdGljIGh0bWwoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBIdG1sKGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgaShhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IEkoYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyBsaShhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IExpKGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgb2woYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBPbChhdHRyaWJ1dGVzKTsKICB9CiAgc3RhdGljIHAoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBQKGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgc3BhbihhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IFNwYW4oYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyBzdWIoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBTdWIoYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyBzdXAoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBTdXAoYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyB1bChhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IFVsKGF0dHJpYnV0ZXMpOwogIH0KfQpleHBvcnRzLlhodG1sTmFtZXNwYWNlID0gWGh0bWxOYW1lc3BhY2U7CgovKioqLyB9KSwKLyogMjM0ICovCi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd19wZGZqc19yZXF1aXJlX18pID0+IHsKCiJ1c2Ugc3RyaWN0IjsKCgpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIl9fZXNNb2R1bGUiLCAoewogIHZhbHVlOiB0cnVlCn0pKTsKZXhwb3J0cy5Vbmtub3duTmFtZXNwYWNlID0gdm9pZCAwOwp2YXIgX25hbWVzcGFjZXMgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIxNCk7CnZhciBfeGZhX29iamVjdCA9IF9fd19wZGZqc19yZXF1aXJlX18oMjEyKTsKY2xhc3MgVW5rbm93bk5hbWVzcGFjZSB7CiAgY29uc3RydWN0b3IobnNJZCkgewogICAgdGhpcy5uYW1lc3BhY2VJZCA9IG5zSWQ7CiAgfQogIFtfbmFtZXNwYWNlcy4kYnVpbGRYRkFPYmplY3RdKG5hbWUsIGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgX3hmYV9vYmplY3QuWG1sT2JqZWN0KHRoaXMubmFtZXNwYWNlSWQsIG5hbWUsIGF0dHJpYnV0ZXMpOwogIH0KfQpleHBvcnRzLlVua25vd25OYW1lc3BhY2UgPSBVbmtub3duTmFtZXNwYWNlOwoKLyoqKi8gfSksCi8qIDIzNSAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuRGF0YXNldFJlYWRlciA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX3htbF9wYXJzZXIgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIwMSk7CmZ1bmN0aW9uIGRlY29kZVN0cmluZyhzdHIpIHsKICB0cnkgewogICAgcmV0dXJuICgwLCBfdXRpbC5zdHJpbmdUb1VURjhTdHJpbmcpKHN0cik7CiAgfSBjYXRjaCAoZXgpIHsKICAgICgwLCBfdXRpbC53YXJuKShgVVRGLTggZGVjb2RpbmcgZmFpbGVkOiAiJHtleH0iLmApOwogICAgcmV0dXJuIHN0cjsKICB9Cn0KY2xhc3MgRGF0YXNldFhNTFBhcnNlciBleHRlbmRzIF94bWxfcGFyc2VyLlNpbXBsZVhNTFBhcnNlciB7CiAgY29uc3RydWN0b3Iob3B0aW9ucykgewogICAgc3VwZXIob3B0aW9ucyk7CiAgICB0aGlzLm5vZGUgPSBudWxsOwogIH0KICBvbkVuZEVsZW1lbnQobmFtZSkgewogICAgY29uc3Qgbm9kZSA9IHN1cGVyLm9uRW5kRWxlbWVudChuYW1lKTsKICAgIGlmIChub2RlICYmIG5hbWUgPT09ICJ4ZmE6ZGF0YXNldHMiKSB7CiAgICAgIHRoaXMubm9kZSA9IG5vZGU7CiAgICAgIHRocm93IG5ldyBFcnJvcigiQWJvcnRpbmcgRGF0YXNldFhNTFBhcnNlci4iKTsKICAgIH0KICB9Cn0KY2xhc3MgRGF0YXNldFJlYWRlciB7CiAgY29uc3RydWN0b3IoZGF0YSkgewogICAgaWYgKGRhdGEuZGF0YXNldHMpIHsKICAgICAgdGhpcy5ub2RlID0gbmV3IF94bWxfcGFyc2VyLlNpbXBsZVhNTFBhcnNlcih7CiAgICAgICAgaGFzQXR0cmlidXRlczogdHJ1ZQogICAgICB9KS5wYXJzZUZyb21TdHJpbmcoZGF0YS5kYXRhc2V0cykuZG9jdW1lbnRFbGVtZW50OwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgcGFyc2VyID0gbmV3IERhdGFzZXRYTUxQYXJzZXIoewogICAgICAgIGhhc0F0dHJpYnV0ZXM6IHRydWUKICAgICAgfSk7CiAgICAgIHRyeSB7CiAgICAgICAgcGFyc2VyLnBhcnNlRnJvbVN0cmluZyhkYXRhWyJ4ZHA6eGRwIl0pOwogICAgICB9IGNhdGNoIChfKSB7fQogICAgICB0aGlzLm5vZGUgPSBwYXJzZXIubm9kZTsKICAgIH0KICB9CiAgZ2V0VmFsdWUocGF0aCkgewogICAgaWYgKCF0aGlzLm5vZGUgfHwgIXBhdGgpIHsKICAgICAgcmV0dXJuICIiOwogICAgfQogICAgY29uc3Qgbm9kZSA9IHRoaXMubm9kZS5zZWFyY2hOb2RlKCgwLCBfY29yZV91dGlscy5wYXJzZVhGQVBhdGgpKHBhdGgpLCAwKTsKICAgIGlmICghbm9kZSkgewogICAgICByZXR1cm4gIiI7CiAgICB9CiAgICBjb25zdCBmaXJzdCA9IG5vZGUuZmlyc3RDaGlsZDsKICAgIGlmIChmaXJzdCAmJiBmaXJzdC5ub2RlTmFtZSA9PT0gInZhbHVlIikgewogICAgICByZXR1cm4gbm9kZS5jaGlsZHJlbi5tYXAoY2hpbGQgPT4gZGVjb2RlU3RyaW5nKGNoaWxkLnRleHRDb250ZW50KSk7CiAgICB9CiAgICByZXR1cm4gZGVjb2RlU3RyaW5nKG5vZGUudGV4dENvbnRlbnQpOwogIH0KfQpleHBvcnRzLkRhdGFzZXRSZWFkZXIgPSBEYXRhc2V0UmVhZGVyOwoKLyoqKi8gfSksCi8qIDIzNiAqLwovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKSA9PiB7CgoidXNlIHN0cmljdCI7CgoKT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICJfX2VzTW9kdWxlIiwgKHsKICB2YWx1ZTogdHJ1ZQp9KSk7CmV4cG9ydHMuWFJlZiA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKdmFyIF9wcmltaXRpdmVzID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDApOwp2YXIgX3BhcnNlciA9IF9fd19wZGZqc19yZXF1aXJlX18oMTUxKTsKdmFyIF9jb3JlX3V0aWxzID0gX193X3BkZmpzX3JlcXVpcmVfXygxMzkpOwp2YXIgX2Jhc2Vfc3RyZWFtID0gX193X3BkZmpzX3JlcXVpcmVfXygxNDEpOwp2YXIgX2NyeXB0byA9IF9fd19wZGZqc19yZXF1aXJlX18oMjAyKTsKY2xhc3MgWFJlZiB7CiAgY29uc3RydWN0b3Ioc3RyZWFtLCBwZGZNYW5hZ2VyKSB7CiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTsKICAgIHRoaXMucGRmTWFuYWdlciA9IHBkZk1hbmFnZXI7CiAgICB0aGlzLmVudHJpZXMgPSBbXTsKICAgIHRoaXMuX3hyZWZTdG1zID0gbmV3IFNldCgpOwogICAgdGhpcy5fY2FjaGVNYXAgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9wZW5kaW5nUmVmcyA9IG5ldyBfcHJpbWl0aXZlcy5SZWZTZXQoKTsKICAgIHRoaXMuX25ld1BlcnNpc3RlbnRSZWZOdW0gPSBudWxsOwogICAgdGhpcy5fbmV3VGVtcG9yYXJ5UmVmTnVtID0gbnVsbDsKICB9CiAgZ2V0TmV3UGVyc2lzdGVudFJlZihvYmopIHsKICAgIGlmICh0aGlzLl9uZXdQZXJzaXN0ZW50UmVmTnVtID09PSBudWxsKSB7CiAgICAgIHRoaXMuX25ld1BlcnNpc3RlbnRSZWZOdW0gPSB0aGlzLmVudHJpZXMubGVuZ3RoIHx8IDE7CiAgICB9CiAgICBjb25zdCBudW0gPSB0aGlzLl9uZXdQZXJzaXN0ZW50UmVmTnVtKys7CiAgICB0aGlzLl9jYWNoZU1hcC5zZXQobnVtLCBvYmopOwogICAgcmV0dXJuIF9wcmltaXRpdmVzLlJlZi5nZXQobnVtLCAwKTsKICB9CiAgZ2V0TmV3VGVtcG9yYXJ5UmVmKCkgewogICAgaWYgKHRoaXMuX25ld1RlbXBvcmFyeVJlZk51bSA9PT0gbnVsbCkgewogICAgICB0aGlzLl9uZXdUZW1wb3JhcnlSZWZOdW0gPSB0aGlzLmVudHJpZXMubGVuZ3RoIHx8IDE7CiAgICB9CiAgICByZXR1cm4gX3ByaW1pdGl2ZXMuUmVmLmdldCh0aGlzLl9uZXdUZW1wb3JhcnlSZWZOdW0rKywgMCk7CiAgfQogIHJlc2V0TmV3VGVtcG9yYXJ5UmVmKCkgewogICAgdGhpcy5fbmV3VGVtcG9yYXJ5UmVmTnVtID0gbnVsbDsKICB9CiAgc2V0U3RhcnRYUmVmKHN0YXJ0WFJlZikgewogICAgdGhpcy5zdGFydFhSZWZRdWV1ZSA9IFtzdGFydFhSZWZdOwogIH0KICBwYXJzZSgpIHsKICAgIGxldCByZWNvdmVyeU1vZGUgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IGZhbHNlOwogICAgbGV0IHRyYWlsZXJEaWN0OwogICAgaWYgKCFyZWNvdmVyeU1vZGUpIHsKICAgICAgdHJhaWxlckRpY3QgPSB0aGlzLnJlYWRYUmVmKCk7CiAgICB9IGVsc2UgewogICAgICAoMCwgX3V0aWwud2FybikoIkluZGV4aW5nIGFsbCBQREYgb2JqZWN0cyIpOwogICAgICB0cmFpbGVyRGljdCA9IHRoaXMuaW5kZXhPYmplY3RzKCk7CiAgICB9CiAgICB0cmFpbGVyRGljdC5hc3NpZ25YcmVmKHRoaXMpOwogICAgdGhpcy50cmFpbGVyID0gdHJhaWxlckRpY3Q7CiAgICBsZXQgZW5jcnlwdDsKICAgIHRyeSB7CiAgICAgIGVuY3J5cHQgPSB0cmFpbGVyRGljdC5nZXQoIkVuY3J5cHQiKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgKDAsIF91dGlsLndhcm4pKGBYUmVmLnBhcnNlIC0gSW52YWxpZCAiRW5jcnlwdCIgcmVmZXJlbmNlOiAiJHtleH0iLmApOwogICAgfQogICAgaWYgKGVuY3J5cHQgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgIGNvbnN0IGlkcyA9IHRyYWlsZXJEaWN0LmdldCgiSUQiKTsKICAgICAgY29uc3QgZmlsZUlkID0gaWRzICYmIGlkcy5sZW5ndGggPyBpZHNbMF0gOiAiIjsKICAgICAgZW5jcnlwdC5zdXBwcmVzc0VuY3J5cHRpb24gPSB0cnVlOwogICAgICB0aGlzLmVuY3J5cHQgPSBuZXcgX2NyeXB0by5DaXBoZXJUcmFuc2Zvcm1GYWN0b3J5KGVuY3J5cHQsIGZpbGVJZCwgdGhpcy5wZGZNYW5hZ2VyLnBhc3N3b3JkKTsKICAgIH0KICAgIGxldCByb290OwogICAgdHJ5IHsKICAgICAgcm9vdCA9IHRyYWlsZXJEaWN0LmdldCgiUm9vdCIpOwogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgX2NvcmVfdXRpbHMuTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICAoMCwgX3V0aWwud2FybikoYFhSZWYucGFyc2UgLSBJbnZhbGlkICJSb290IiByZWZlcmVuY2U6ICIke2V4fSIuYCk7CiAgICB9CiAgICBpZiAocm9vdCBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpIHsKICAgICAgdHJ5IHsKICAgICAgICBjb25zdCBwYWdlcyA9IHJvb3QuZ2V0KCJQYWdlcyIpOwogICAgICAgIGlmIChwYWdlcyBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLkRpY3QpIHsKICAgICAgICAgIHRoaXMucm9vdCA9IHJvb3Q7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICB9IGNhdGNoIChleCkgewogICAgICAgIGlmIChleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgICB0aHJvdyBleDsKICAgICAgICB9CiAgICAgICAgKDAsIF91dGlsLndhcm4pKGBYUmVmLnBhcnNlIC0gSW52YWxpZCAiUGFnZXMiIHJlZmVyZW5jZTogIiR7ZXh9Ii5gKTsKICAgICAgfQogICAgfQogICAgaWYgKCFyZWNvdmVyeU1vZGUpIHsKICAgICAgdGhyb3cgbmV3IF9jb3JlX3V0aWxzLlhSZWZQYXJzZUV4Y2VwdGlvbigpOwogICAgfQogICAgdGhyb3cgbmV3IF91dGlsLkludmFsaWRQREZFeGNlcHRpb24oIkludmFsaWQgUm9vdCByZWZlcmVuY2UuIik7CiAgfQogIHByb2Nlc3NYUmVmVGFibGUocGFyc2VyKSB7CiAgICBpZiAoISgidGFibGVTdGF0ZSIgaW4gdGhpcykpIHsKICAgICAgdGhpcy50YWJsZVN0YXRlID0gewogICAgICAgIGVudHJ5TnVtOiAwLAogICAgICAgIHN0cmVhbVBvczogcGFyc2VyLmxleGVyLnN0cmVhbS5wb3MsCiAgICAgICAgcGFyc2VyQnVmMTogcGFyc2VyLmJ1ZjEsCiAgICAgICAgcGFyc2VyQnVmMjogcGFyc2VyLmJ1ZjIKICAgICAgfTsKICAgIH0KICAgIGNvbnN0IG9iaiA9IHRoaXMucmVhZFhSZWZUYWJsZShwYXJzZXIpOwogICAgaWYgKCEoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKG9iaiwgInRyYWlsZXIiKSkgewogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkludmFsaWQgWFJlZiB0YWJsZTogY291bGQgbm90IGZpbmQgdHJhaWxlciBkaWN0aW9uYXJ5Iik7CiAgICB9CiAgICBsZXQgZGljdCA9IHBhcnNlci5nZXRPYmooKTsKICAgIGlmICghKGRpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSAmJiBkaWN0LmRpY3QpIHsKICAgICAgZGljdCA9IGRpY3QuZGljdDsKICAgIH0KICAgIGlmICghKGRpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkludmFsaWQgWFJlZiB0YWJsZTogY291bGQgbm90IHBhcnNlIHRyYWlsZXIgZGljdGlvbmFyeSIpOwogICAgfQogICAgZGVsZXRlIHRoaXMudGFibGVTdGF0ZTsKICAgIHJldHVybiBkaWN0OwogIH0KICByZWFkWFJlZlRhYmxlKHBhcnNlcikgewogICAgY29uc3Qgc3RyZWFtID0gcGFyc2VyLmxleGVyLnN0cmVhbTsKICAgIGNvbnN0IHRhYmxlU3RhdGUgPSB0aGlzLnRhYmxlU3RhdGU7CiAgICBzdHJlYW0ucG9zID0gdGFibGVTdGF0ZS5zdHJlYW1Qb3M7CiAgICBwYXJzZXIuYnVmMSA9IHRhYmxlU3RhdGUucGFyc2VyQnVmMTsKICAgIHBhcnNlci5idWYyID0gdGFibGVTdGF0ZS5wYXJzZXJCdWYyOwogICAgbGV0IG9iajsKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIGlmICghKCJmaXJzdEVudHJ5TnVtIiBpbiB0YWJsZVN0YXRlKSB8fCAhKCJlbnRyeUNvdW50IiBpbiB0YWJsZVN0YXRlKSkgewogICAgICAgIGlmICgoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKG9iaiA9IHBhcnNlci5nZXRPYmooKSwgInRyYWlsZXIiKSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHRhYmxlU3RhdGUuZmlyc3RFbnRyeU51bSA9IG9iajsKICAgICAgICB0YWJsZVN0YXRlLmVudHJ5Q291bnQgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgIH0KICAgICAgbGV0IGZpcnN0ID0gdGFibGVTdGF0ZS5maXJzdEVudHJ5TnVtOwogICAgICBjb25zdCBjb3VudCA9IHRhYmxlU3RhdGUuZW50cnlDb3VudDsKICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGZpcnN0KSB8fCAhTnVtYmVyLmlzSW50ZWdlcihjb3VudCkpIHsKICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkludmFsaWQgWFJlZiB0YWJsZTogd3JvbmcgdHlwZXMgaW4gc3Vic2VjdGlvbiBoZWFkZXIiKTsKICAgICAgfQogICAgICBmb3IgKGxldCBpID0gdGFibGVTdGF0ZS5lbnRyeU51bTsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgICB0YWJsZVN0YXRlLnN0cmVhbVBvcyA9IHN0cmVhbS5wb3M7CiAgICAgICAgdGFibGVTdGF0ZS5lbnRyeU51bSA9IGk7CiAgICAgICAgdGFibGVTdGF0ZS5wYXJzZXJCdWYxID0gcGFyc2VyLmJ1ZjE7CiAgICAgICAgdGFibGVTdGF0ZS5wYXJzZXJCdWYyID0gcGFyc2VyLmJ1ZjI7CiAgICAgICAgY29uc3QgZW50cnkgPSB7fTsKICAgICAgICBlbnRyeS5vZmZzZXQgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgICAgZW50cnkuZ2VuID0gcGFyc2VyLmdldE9iaigpOwogICAgICAgIGNvbnN0IHR5cGUgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgICAgaWYgKHR5cGUgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5DbWQpIHsKICAgICAgICAgIHN3aXRjaCAodHlwZS5jbWQpIHsKICAgICAgICAgICAgY2FzZSAiZiI6CiAgICAgICAgICAgICAgZW50cnkuZnJlZSA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgIm4iOgogICAgICAgICAgICAgIGVudHJ5LnVuY29tcHJlc3NlZCA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihlbnRyeS5vZmZzZXQpIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKGVudHJ5LmdlbikgfHwgIShlbnRyeS5mcmVlIHx8IGVudHJ5LnVuY29tcHJlc3NlZCkpIHsKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgSW52YWxpZCBlbnRyeSBpbiBYUmVmIHN1YnNlY3Rpb246ICR7Zmlyc3R9LCAke2NvdW50fWApOwogICAgICAgIH0KICAgICAgICBpZiAoaSA9PT0gMCAmJiBlbnRyeS5mcmVlICYmIGZpcnN0ID09PSAxKSB7CiAgICAgICAgICBmaXJzdCA9IDA7CiAgICAgICAgfQogICAgICAgIGlmICghdGhpcy5lbnRyaWVzW2kgKyBmaXJzdF0pIHsKICAgICAgICAgIHRoaXMuZW50cmllc1tpICsgZmlyc3RdID0gZW50cnk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHRhYmxlU3RhdGUuZW50cnlOdW0gPSAwOwogICAgICB0YWJsZVN0YXRlLnN0cmVhbVBvcyA9IHN0cmVhbS5wb3M7CiAgICAgIHRhYmxlU3RhdGUucGFyc2VyQnVmMSA9IHBhcnNlci5idWYxOwogICAgICB0YWJsZVN0YXRlLnBhcnNlckJ1ZjIgPSBwYXJzZXIuYnVmMjsKICAgICAgZGVsZXRlIHRhYmxlU3RhdGUuZmlyc3RFbnRyeU51bTsKICAgICAgZGVsZXRlIHRhYmxlU3RhdGUuZW50cnlDb3VudDsKICAgIH0KICAgIGlmICh0aGlzLmVudHJpZXNbMF0gJiYgIXRoaXMuZW50cmllc1swXS5mcmVlKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIHRhYmxlOiB1bmV4cGVjdGVkIGZpcnN0IG9iamVjdCIpOwogICAgfQogICAgcmV0dXJuIG9iajsKICB9CiAgcHJvY2Vzc1hSZWZTdHJlYW0oc3RyZWFtKSB7CiAgICBpZiAoISgic3RyZWFtU3RhdGUiIGluIHRoaXMpKSB7CiAgICAgIGNvbnN0IHN0cmVhbVBhcmFtZXRlcnMgPSBzdHJlYW0uZGljdDsKICAgICAgY29uc3QgYnl0ZVdpZHRocyA9IHN0cmVhbVBhcmFtZXRlcnMuZ2V0KCJXIik7CiAgICAgIGxldCByYW5nZSA9IHN0cmVhbVBhcmFtZXRlcnMuZ2V0KCJJbmRleCIpOwogICAgICBpZiAoIXJhbmdlKSB7CiAgICAgICAgcmFuZ2UgPSBbMCwgc3RyZWFtUGFyYW1ldGVycy5nZXQoIlNpemUiKV07CiAgICAgIH0KICAgICAgdGhpcy5zdHJlYW1TdGF0ZSA9IHsKICAgICAgICBlbnRyeVJhbmdlczogcmFuZ2UsCiAgICAgICAgYnl0ZVdpZHRocywKICAgICAgICBlbnRyeU51bTogMCwKICAgICAgICBzdHJlYW1Qb3M6IHN0cmVhbS5wb3MKICAgICAgfTsKICAgIH0KICAgIHRoaXMucmVhZFhSZWZTdHJlYW0oc3RyZWFtKTsKICAgIGRlbGV0ZSB0aGlzLnN0cmVhbVN0YXRlOwogICAgcmV0dXJuIHN0cmVhbS5kaWN0OwogIH0KICByZWFkWFJlZlN0cmVhbShzdHJlYW0pIHsKICAgIGNvbnN0IHN0cmVhbVN0YXRlID0gdGhpcy5zdHJlYW1TdGF0ZTsKICAgIHN0cmVhbS5wb3MgPSBzdHJlYW1TdGF0ZS5zdHJlYW1Qb3M7CiAgICBjb25zdCBbdHlwZUZpZWxkV2lkdGgsIG9mZnNldEZpZWxkV2lkdGgsIGdlbmVyYXRpb25GaWVsZFdpZHRoXSA9IHN0cmVhbVN0YXRlLmJ5dGVXaWR0aHM7CiAgICBjb25zdCBlbnRyeVJhbmdlcyA9IHN0cmVhbVN0YXRlLmVudHJ5UmFuZ2VzOwogICAgd2hpbGUgKGVudHJ5UmFuZ2VzLmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgW2ZpcnN0LCBuXSA9IGVudHJ5UmFuZ2VzOwogICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoZmlyc3QpIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKG4pKSB7CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBJbnZhbGlkIFhSZWYgcmFuZ2UgZmllbGRzOiAke2ZpcnN0fSwgJHtufWApOwogICAgICB9CiAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcih0eXBlRmllbGRXaWR0aCkgfHwgIU51bWJlci5pc0ludGVnZXIob2Zmc2V0RmllbGRXaWR0aCkgfHwgIU51bWJlci5pc0ludGVnZXIoZ2VuZXJhdGlvbkZpZWxkV2lkdGgpKSB7CiAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKGBJbnZhbGlkIFhSZWYgZW50cnkgZmllbGRzIGxlbmd0aDogJHtmaXJzdH0sICR7bn1gKTsKICAgICAgfQogICAgICBmb3IgKGxldCBpID0gc3RyZWFtU3RhdGUuZW50cnlOdW07IGkgPCBuOyArK2kpIHsKICAgICAgICBzdHJlYW1TdGF0ZS5lbnRyeU51bSA9IGk7CiAgICAgICAgc3RyZWFtU3RhdGUuc3RyZWFtUG9zID0gc3RyZWFtLnBvczsKICAgICAgICBsZXQgdHlwZSA9IDAsCiAgICAgICAgICBvZmZzZXQgPSAwLAogICAgICAgICAgZ2VuZXJhdGlvbiA9IDA7CiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0eXBlRmllbGRXaWR0aDsgKytqKSB7CiAgICAgICAgICBjb25zdCB0eXBlQnl0ZSA9IHN0cmVhbS5nZXRCeXRlKCk7CiAgICAgICAgICBpZiAodHlwZUJ5dGUgPT09IC0xKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIGJ5dGVXaWR0aHMgJ3R5cGUnLiIpOwogICAgICAgICAgfQogICAgICAgICAgdHlwZSA9IHR5cGUgPDwgOCB8IHR5cGVCeXRlOwogICAgICAgIH0KICAgICAgICBpZiAodHlwZUZpZWxkV2lkdGggPT09IDApIHsKICAgICAgICAgIHR5cGUgPSAxOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG9mZnNldEZpZWxkV2lkdGg7ICsraikgewogICAgICAgICAgY29uc3Qgb2Zmc2V0Qnl0ZSA9IHN0cmVhbS5nZXRCeXRlKCk7CiAgICAgICAgICBpZiAob2Zmc2V0Qnl0ZSA9PT0gLTEpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgYnl0ZVdpZHRocyAnb2Zmc2V0Jy4iKTsKICAgICAgICAgIH0KICAgICAgICAgIG9mZnNldCA9IG9mZnNldCA8PCA4IHwgb2Zmc2V0Qnl0ZTsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBnZW5lcmF0aW9uRmllbGRXaWR0aDsgKytqKSB7CiAgICAgICAgICBjb25zdCBnZW5lcmF0aW9uQnl0ZSA9IHN0cmVhbS5nZXRCeXRlKCk7CiAgICAgICAgICBpZiAoZ2VuZXJhdGlvbkJ5dGUgPT09IC0xKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIGJ5dGVXaWR0aHMgJ2dlbmVyYXRpb24nLiIpOwogICAgICAgICAgfQogICAgICAgICAgZ2VuZXJhdGlvbiA9IGdlbmVyYXRpb24gPDwgOCB8IGdlbmVyYXRpb25CeXRlOwogICAgICAgIH0KICAgICAgICBjb25zdCBlbnRyeSA9IHt9OwogICAgICAgIGVudHJ5Lm9mZnNldCA9IG9mZnNldDsKICAgICAgICBlbnRyeS5nZW4gPSBnZW5lcmF0aW9uOwogICAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICBlbnRyeS5mcmVlID0gdHJ1ZTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIGVudHJ5LnVuY29tcHJlc3NlZCA9IHRydWU7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAyOgogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgSW52YWxpZCBYUmVmIGVudHJ5IHR5cGU6ICR7dHlwZX1gKTsKICAgICAgICB9CiAgICAgICAgaWYgKCF0aGlzLmVudHJpZXNbZmlyc3QgKyBpXSkgewogICAgICAgICAgdGhpcy5lbnRyaWVzW2ZpcnN0ICsgaV0gPSBlbnRyeTsKICAgICAgICB9CiAgICAgIH0KICAgICAgc3RyZWFtU3RhdGUuZW50cnlOdW0gPSAwOwogICAgICBzdHJlYW1TdGF0ZS5zdHJlYW1Qb3MgPSBzdHJlYW0ucG9zOwogICAgICBlbnRyeVJhbmdlcy5zcGxpY2UoMCwgMik7CiAgICB9CiAgfQogIGluZGV4T2JqZWN0cygpIHsKICAgIGNvbnN0IFRBQiA9IDB4OSwKICAgICAgTEYgPSAweGEsCiAgICAgIENSID0gMHhkLAogICAgICBTUEFDRSA9IDB4MjA7CiAgICBjb25zdCBQRVJDRU5UID0gMHgyNSwKICAgICAgTFQgPSAweDNjOwogICAgZnVuY3Rpb24gcmVhZFRva2VuKGRhdGEsIG9mZnNldCkgewogICAgICBsZXQgdG9rZW4gPSAiIiwKICAgICAgICBjaCA9IGRhdGFbb2Zmc2V0XTsKICAgICAgd2hpbGUgKGNoICE9PSBMRiAmJiBjaCAhPT0gQ1IgJiYgY2ggIT09IExUKSB7CiAgICAgICAgaWYgKCsrb2Zmc2V0ID49IGRhdGEubGVuZ3RoKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdG9rZW4gKz0gU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICAgICAgY2ggPSBkYXRhW29mZnNldF07CiAgICAgIH0KICAgICAgcmV0dXJuIHRva2VuOwogICAgfQogICAgZnVuY3Rpb24gc2tpcFVudGlsKGRhdGEsIG9mZnNldCwgd2hhdCkgewogICAgICBjb25zdCBsZW5ndGggPSB3aGF0Lmxlbmd0aCwKICAgICAgICBkYXRhTGVuZ3RoID0gZGF0YS5sZW5ndGg7CiAgICAgIGxldCBza2lwcGVkID0gMDsKICAgICAgd2hpbGUgKG9mZnNldCA8IGRhdGFMZW5ndGgpIHsKICAgICAgICBsZXQgaSA9IDA7CiAgICAgICAgd2hpbGUgKGkgPCBsZW5ndGggJiYgZGF0YVtvZmZzZXQgKyBpXSA9PT0gd2hhdFtpXSkgewogICAgICAgICAgKytpOwogICAgICAgIH0KICAgICAgICBpZiAoaSA+PSBsZW5ndGgpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBvZmZzZXQrKzsKICAgICAgICBza2lwcGVkKys7CiAgICAgIH0KICAgICAgcmV0dXJuIHNraXBwZWQ7CiAgICB9CiAgICBjb25zdCBnRW5kb2JqUmVnRXhwID0gL1xiKGVuZG9ianxcZCtccytcZCtccytvYmp8eHJlZnx0cmFpbGVyKVxiL2c7CiAgICBjb25zdCBnU3RhcnR4cmVmUmVnRXhwID0gL1xiKHN0YXJ0eHJlZnxcZCtccytcZCtccytvYmopXGIvZzsKICAgIGNvbnN0IG9ialJlZ0V4cCA9IC9eKFxkKylccysoXGQrKVxzK29ialxiLzsKICAgIGNvbnN0IHRyYWlsZXJCeXRlcyA9IG5ldyBVaW50OEFycmF5KFsxMTYsIDExNCwgOTcsIDEwNSwgMTA4LCAxMDEsIDExNF0pOwogICAgY29uc3Qgc3RhcnR4cmVmQnl0ZXMgPSBuZXcgVWludDhBcnJheShbMTE1LCAxMTYsIDk3LCAxMTQsIDExNiwgMTIwLCAxMTQsIDEwMSwgMTAyXSk7CiAgICBjb25zdCB4cmVmQnl0ZXMgPSBuZXcgVWludDhBcnJheShbNDcsIDg4LCA4MiwgMTAxLCAxMDJdKTsKICAgIHRoaXMuZW50cmllcy5sZW5ndGggPSAwOwogICAgdGhpcy5fY2FjaGVNYXAuY2xlYXIoKTsKICAgIGNvbnN0IHN0cmVhbSA9IHRoaXMuc3RyZWFtOwogICAgc3RyZWFtLnBvcyA9IDA7CiAgICBjb25zdCBidWZmZXIgPSBzdHJlYW0uZ2V0Qnl0ZXMoKSwKICAgICAgYnVmZmVyU3RyID0gKDAsIF91dGlsLmJ5dGVzVG9TdHJpbmcpKGJ1ZmZlciksCiAgICAgIGxlbmd0aCA9IGJ1ZmZlci5sZW5ndGg7CiAgICBsZXQgcG9zaXRpb24gPSBzdHJlYW0uc3RhcnQ7CiAgICBjb25zdCB0cmFpbGVycyA9IFtdLAogICAgICB4cmVmU3RtcyA9IFtdOwogICAgd2hpbGUgKHBvc2l0aW9uIDwgbGVuZ3RoKSB7CiAgICAgIGxldCBjaCA9IGJ1ZmZlcltwb3NpdGlvbl07CiAgICAgIGlmIChjaCA9PT0gVEFCIHx8IGNoID09PSBMRiB8fCBjaCA9PT0gQ1IgfHwgY2ggPT09IFNQQUNFKSB7CiAgICAgICAgKytwb3NpdGlvbjsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoY2ggPT09IFBFUkNFTlQpIHsKICAgICAgICBkbyB7CiAgICAgICAgICArK3Bvc2l0aW9uOwogICAgICAgICAgaWYgKHBvc2l0aW9uID49IGxlbmd0aCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNoID0gYnVmZmVyW3Bvc2l0aW9uXTsKICAgICAgICB9IHdoaWxlIChjaCAhPT0gTEYgJiYgY2ggIT09IENSKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB0b2tlbiA9IHJlYWRUb2tlbihidWZmZXIsIHBvc2l0aW9uKTsKICAgICAgbGV0IG07CiAgICAgIGlmICh0b2tlbi5zdGFydHNXaXRoKCJ4cmVmIikgJiYgKHRva2VuLmxlbmd0aCA9PT0gNCB8fCAvXHMvLnRlc3QodG9rZW5bNF0pKSkgewogICAgICAgIHBvc2l0aW9uICs9IHNraXBVbnRpbChidWZmZXIsIHBvc2l0aW9uLCB0cmFpbGVyQnl0ZXMpOwogICAgICAgIHRyYWlsZXJzLnB1c2gocG9zaXRpb24pOwogICAgICAgIHBvc2l0aW9uICs9IHNraXBVbnRpbChidWZmZXIsIHBvc2l0aW9uLCBzdGFydHhyZWZCeXRlcyk7CiAgICAgIH0gZWxzZSBpZiAobSA9IG9ialJlZ0V4cC5leGVjKHRva2VuKSkgewogICAgICAgIGNvbnN0IG51bSA9IG1bMV0gfCAwLAogICAgICAgICAgZ2VuID0gbVsyXSB8IDA7CiAgICAgICAgY29uc3Qgc3RhcnRQb3MgPSBwb3NpdGlvbiArIHRva2VuLmxlbmd0aDsKICAgICAgICBsZXQgY29udGVudExlbmd0aCwKICAgICAgICAgIHVwZGF0ZUVudHJpZXMgPSBmYWxzZTsKICAgICAgICBpZiAoIXRoaXMuZW50cmllc1tudW1dKSB7CiAgICAgICAgICB1cGRhdGVFbnRyaWVzID0gdHJ1ZTsKICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZW50cmllc1tudW1dLmdlbiA9PT0gZ2VuKSB7CiAgICAgICAgICB0cnkgewogICAgICAgICAgICBjb25zdCBwYXJzZXIgPSBuZXcgX3BhcnNlci5QYXJzZXIoewogICAgICAgICAgICAgIGxleGVyOiBuZXcgX3BhcnNlci5MZXhlcihzdHJlYW0ubWFrZVN1YlN0cmVhbShzdGFydFBvcykpCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgICAgICAgIHVwZGF0ZUVudHJpZXMgPSB0cnVlOwogICAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgX2NvcmVfdXRpbHMuUGFyc2VyRU9GRXhjZXB0aW9uKSB7CiAgICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBpbmRleE9iamVjdHMgLS0gY2hlY2tpbmcgb2JqZWN0ICgke3Rva2VufSk6ICIke2V4fSIuYCk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdXBkYXRlRW50cmllcyA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHVwZGF0ZUVudHJpZXMpIHsKICAgICAgICAgIHRoaXMuZW50cmllc1tudW1dID0gewogICAgICAgICAgICBvZmZzZXQ6IHBvc2l0aW9uIC0gc3RyZWFtLnN0YXJ0LAogICAgICAgICAgICBnZW4sCiAgICAgICAgICAgIHVuY29tcHJlc3NlZDogdHJ1ZQogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgICAgZ0VuZG9ialJlZ0V4cC5sYXN0SW5kZXggPSBzdGFydFBvczsKICAgICAgICBjb25zdCBtYXRjaCA9IGdFbmRvYmpSZWdFeHAuZXhlYyhidWZmZXJTdHIpOwogICAgICAgIGlmIChtYXRjaCkgewogICAgICAgICAgY29uc3QgZW5kUG9zID0gZ0VuZG9ialJlZ0V4cC5sYXN0SW5kZXggKyAxOwogICAgICAgICAgY29udGVudExlbmd0aCA9IGVuZFBvcyAtIHBvc2l0aW9uOwogICAgICAgICAgaWYgKG1hdGNoWzFdICE9PSAiZW5kb2JqIikgewogICAgICAgICAgICAoMCwgX3V0aWwud2FybikoYGluZGV4T2JqZWN0czogRm91bmQgIiR7bWF0Y2hbMV19IiBpbnNpZGUgb2YgYW5vdGhlciAib2JqIiwgYCArICdjYXVzZWQgYnkgbWlzc2luZyAiZW5kb2JqIiAtLSB0cnlpbmcgdG8gcmVjb3Zlci4nKTsKICAgICAgICAgICAgY29udGVudExlbmd0aCAtPSBtYXRjaFsxXS5sZW5ndGggKyAxOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb250ZW50TGVuZ3RoID0gbGVuZ3RoIC0gcG9zaXRpb247CiAgICAgICAgfQogICAgICAgIGNvbnN0IGNvbnRlbnQgPSBidWZmZXIuc3ViYXJyYXkocG9zaXRpb24sIHBvc2l0aW9uICsgY29udGVudExlbmd0aCk7CiAgICAgICAgY29uc3QgeHJlZlRhZ09mZnNldCA9IHNraXBVbnRpbChjb250ZW50LCAwLCB4cmVmQnl0ZXMpOwogICAgICAgIGlmICh4cmVmVGFnT2Zmc2V0IDwgY29udGVudExlbmd0aCAmJiBjb250ZW50W3hyZWZUYWdPZmZzZXQgKyA1XSA8IDY0KSB7CiAgICAgICAgICB4cmVmU3Rtcy5wdXNoKHBvc2l0aW9uIC0gc3RyZWFtLnN0YXJ0KTsKICAgICAgICAgIHRoaXMuX3hyZWZTdG1zLmFkZChwb3NpdGlvbiAtIHN0cmVhbS5zdGFydCk7CiAgICAgICAgfQogICAgICAgIHBvc2l0aW9uICs9IGNvbnRlbnRMZW5ndGg7CiAgICAgIH0gZWxzZSBpZiAodG9rZW4uc3RhcnRzV2l0aCgidHJhaWxlciIpICYmICh0b2tlbi5sZW5ndGggPT09IDcgfHwgL1xzLy50ZXN0KHRva2VuWzddKSkpIHsKICAgICAgICB0cmFpbGVycy5wdXNoKHBvc2l0aW9uKTsKICAgICAgICBjb25zdCBzdGFydFBvcyA9IHBvc2l0aW9uICsgdG9rZW4ubGVuZ3RoOwogICAgICAgIGxldCBjb250ZW50TGVuZ3RoOwogICAgICAgIGdTdGFydHhyZWZSZWdFeHAubGFzdEluZGV4ID0gc3RhcnRQb3M7CiAgICAgICAgY29uc3QgbWF0Y2ggPSBnU3RhcnR4cmVmUmVnRXhwLmV4ZWMoYnVmZmVyU3RyKTsKICAgICAgICBpZiAobWF0Y2gpIHsKICAgICAgICAgIGNvbnN0IGVuZFBvcyA9IGdTdGFydHhyZWZSZWdFeHAubGFzdEluZGV4ICsgMTsKICAgICAgICAgIGNvbnRlbnRMZW5ndGggPSBlbmRQb3MgLSBwb3NpdGlvbjsKICAgICAgICAgIGlmIChtYXRjaFsxXSAhPT0gInN0YXJ0eHJlZiIpIHsKICAgICAgICAgICAgKDAsIF91dGlsLndhcm4pKGBpbmRleE9iamVjdHM6IEZvdW5kICIke21hdGNoWzFdfSIgYWZ0ZXIgInRyYWlsZXIiLCBgICsgJ2NhdXNlZCBieSBtaXNzaW5nICJzdGFydHhyZWYiIC0tIHRyeWluZyB0byByZWNvdmVyLicpOwogICAgICAgICAgICBjb250ZW50TGVuZ3RoIC09IG1hdGNoWzFdLmxlbmd0aCArIDE7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNvbnRlbnRMZW5ndGggPSBsZW5ndGggLSBwb3NpdGlvbjsKICAgICAgICB9CiAgICAgICAgcG9zaXRpb24gKz0gY29udGVudExlbmd0aDsKICAgICAgfSBlbHNlIHsKICAgICAgICBwb3NpdGlvbiArPSB0b2tlbi5sZW5ndGggKyAxOwogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IHhyZWZTdG0gb2YgeHJlZlN0bXMpIHsKICAgICAgdGhpcy5zdGFydFhSZWZRdWV1ZS5wdXNoKHhyZWZTdG0pOwogICAgICB0aGlzLnJlYWRYUmVmKHRydWUpOwogICAgfQogICAgY29uc3QgdHJhaWxlckRpY3RzID0gW107CiAgICBsZXQgaXNFbmNyeXB0ZWQgPSBmYWxzZTsKICAgIGZvciAoY29uc3QgdHJhaWxlciBvZiB0cmFpbGVycykgewogICAgICBzdHJlYW0ucG9zID0gdHJhaWxlcjsKICAgICAgY29uc3QgcGFyc2VyID0gbmV3IF9wYXJzZXIuUGFyc2VyKHsKICAgICAgICBsZXhlcjogbmV3IF9wYXJzZXIuTGV4ZXIoc3RyZWFtKSwKICAgICAgICB4cmVmOiB0aGlzLAogICAgICAgIGFsbG93U3RyZWFtczogdHJ1ZSwKICAgICAgICByZWNvdmVyeU1vZGU6IHRydWUKICAgICAgfSk7CiAgICAgIGNvbnN0IG9iaiA9IHBhcnNlci5nZXRPYmooKTsKICAgICAgaWYgKCEoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKG9iaiwgInRyYWlsZXIiKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGRpY3QgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgIGlmICghKGRpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHRyYWlsZXJEaWN0cy5wdXNoKGRpY3QpOwogICAgICBpZiAoZGljdC5oYXMoIkVuY3J5cHQiKSkgewogICAgICAgIGlzRW5jcnlwdGVkID0gdHJ1ZTsKICAgICAgfQogICAgfQogICAgbGV0IHRyYWlsZXJEaWN0LCB0cmFpbGVyRXJyb3I7CiAgICBmb3IgKGNvbnN0IGRpY3Qgb2YgWy4uLnRyYWlsZXJEaWN0cywgImdlbkZhbGxiYWNrIiwgLi4udHJhaWxlckRpY3RzXSkgewogICAgICBpZiAoZGljdCA9PT0gImdlbkZhbGxiYWNrIikgewogICAgICAgIGlmICghdHJhaWxlckVycm9yKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdGhpcy5fZ2VuZXJhdGlvbkZhbGxiYWNrID0gdHJ1ZTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBsZXQgdmFsaWRQYWdlc0RpY3QgPSBmYWxzZTsKICAgICAgdHJ5IHsKICAgICAgICBjb25zdCByb290RGljdCA9IGRpY3QuZ2V0KCJSb290Iik7CiAgICAgICAgaWYgKCEocm9vdERpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHBhZ2VzRGljdCA9IHJvb3REaWN0LmdldCgiUGFnZXMiKTsKICAgICAgICBpZiAoIShwYWdlc0RpY3QgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHBhZ2VzQ291bnQgPSBwYWdlc0RpY3QuZ2V0KCJDb3VudCIpOwogICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHBhZ2VzQ291bnQpKSB7CiAgICAgICAgICB2YWxpZFBhZ2VzRGljdCA9IHRydWU7CiAgICAgICAgfQogICAgICB9IGNhdGNoIChleCkgewogICAgICAgIHRyYWlsZXJFcnJvciA9IGV4OwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICh2YWxpZFBhZ2VzRGljdCAmJiAoIWlzRW5jcnlwdGVkIHx8IGRpY3QuaGFzKCJFbmNyeXB0IikpICYmIGRpY3QuaGFzKCJJRCIpKSB7CiAgICAgICAgcmV0dXJuIGRpY3Q7CiAgICAgIH0KICAgICAgdHJhaWxlckRpY3QgPSBkaWN0OwogICAgfQogICAgaWYgKHRyYWlsZXJEaWN0KSB7CiAgICAgIHJldHVybiB0cmFpbGVyRGljdDsKICAgIH0KICAgIGlmICh0aGlzLnRvcERpY3QpIHsKICAgICAgcmV0dXJuIHRoaXMudG9wRGljdDsKICAgIH0KICAgIHRocm93IG5ldyBfdXRpbC5JbnZhbGlkUERGRXhjZXB0aW9uKCJJbnZhbGlkIFBERiBzdHJ1Y3R1cmUuIik7CiAgfQogIHJlYWRYUmVmKCkgewogICAgbGV0IHJlY292ZXJ5TW9kZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogZmFsc2U7CiAgICBjb25zdCBzdHJlYW0gPSB0aGlzLnN0cmVhbTsKICAgIGNvbnN0IHN0YXJ0WFJlZlBhcnNlZENhY2hlID0gbmV3IFNldCgpOwogICAgd2hpbGUgKHRoaXMuc3RhcnRYUmVmUXVldWUubGVuZ3RoKSB7CiAgICAgIHRyeSB7CiAgICAgICAgY29uc3Qgc3RhcnRYUmVmID0gdGhpcy5zdGFydFhSZWZRdWV1ZVswXTsKICAgICAgICBpZiAoc3RhcnRYUmVmUGFyc2VkQ2FjaGUuaGFzKHN0YXJ0WFJlZikpIHsKICAgICAgICAgICgwLCBfdXRpbC53YXJuKSgicmVhZFhSZWYgLSBza2lwcGluZyBYUmVmIHRhYmxlIHNpbmNlIGl0IHdhcyBhbHJlYWR5IHBhcnNlZC4iKTsKICAgICAgICAgIHRoaXMuc3RhcnRYUmVmUXVldWUuc2hpZnQoKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBzdGFydFhSZWZQYXJzZWRDYWNoZS5hZGQoc3RhcnRYUmVmKTsKICAgICAgICBzdHJlYW0ucG9zID0gc3RhcnRYUmVmICsgc3RyZWFtLnN0YXJ0OwogICAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBfcGFyc2VyLlBhcnNlcih7CiAgICAgICAgICBsZXhlcjogbmV3IF9wYXJzZXIuTGV4ZXIoc3RyZWFtKSwKICAgICAgICAgIHhyZWY6IHRoaXMsCiAgICAgICAgICBhbGxvd1N0cmVhbXM6IHRydWUKICAgICAgICB9KTsKICAgICAgICBsZXQgb2JqID0gcGFyc2VyLmdldE9iaigpOwogICAgICAgIGxldCBkaWN0OwogICAgICAgIGlmICgoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKG9iaiwgInhyZWYiKSkgewogICAgICAgICAgZGljdCA9IHRoaXMucHJvY2Vzc1hSZWZUYWJsZShwYXJzZXIpOwogICAgICAgICAgaWYgKCF0aGlzLnRvcERpY3QpIHsKICAgICAgICAgICAgdGhpcy50b3BEaWN0ID0gZGljdDsKICAgICAgICAgIH0KICAgICAgICAgIG9iaiA9IGRpY3QuZ2V0KCJYUmVmU3RtIik7CiAgICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihvYmopICYmICF0aGlzLl94cmVmU3Rtcy5oYXMob2JqKSkgewogICAgICAgICAgICB0aGlzLl94cmVmU3Rtcy5hZGQob2JqKTsKICAgICAgICAgICAgdGhpcy5zdGFydFhSZWZRdWV1ZS5wdXNoKG9iaik7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChOdW1iZXIuaXNJbnRlZ2VyKG9iaikpIHsKICAgICAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihwYXJzZXIuZ2V0T2JqKCkpIHx8ICEoMCwgX3ByaW1pdGl2ZXMuaXNDbWQpKHBhcnNlci5nZXRPYmooKSwgIm9iaiIpIHx8ICEoKG9iaiA9IHBhcnNlci5nZXRPYmooKSkgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgc3RyZWFtIik7CiAgICAgICAgICB9CiAgICAgICAgICBkaWN0ID0gdGhpcy5wcm9jZXNzWFJlZlN0cmVhbShvYmopOwogICAgICAgICAgaWYgKCF0aGlzLnRvcERpY3QpIHsKICAgICAgICAgICAgdGhpcy50b3BEaWN0ID0gZGljdDsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghZGljdCkgewogICAgICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoIkZhaWxlZCB0byByZWFkIFhSZWYgc3RyZWFtIik7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIHN0cmVhbSBoZWFkZXIiKTsKICAgICAgICB9CiAgICAgICAgb2JqID0gZGljdC5nZXQoIlByZXYiKTsKICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihvYmopKSB7CiAgICAgICAgICB0aGlzLnN0YXJ0WFJlZlF1ZXVlLnB1c2gob2JqKTsKICAgICAgICB9IGVsc2UgaWYgKG9iaiBpbnN0YW5jZW9mIF9wcmltaXRpdmVzLlJlZikgewogICAgICAgICAgdGhpcy5zdGFydFhSZWZRdWV1ZS5wdXNoKG9iai5udW0pOwogICAgICAgIH0KICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgIGlmIChlIGluc3RhbmNlb2YgX2NvcmVfdXRpbHMuTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICAgIHRocm93IGU7CiAgICAgICAgfQogICAgICAgICgwLCBfdXRpbC5pbmZvKSgiKHdoaWxlIHJlYWRpbmcgWFJlZik6ICIgKyBlKTsKICAgICAgfQogICAgICB0aGlzLnN0YXJ0WFJlZlF1ZXVlLnNoaWZ0KCk7CiAgICB9CiAgICBpZiAodGhpcy50b3BEaWN0KSB7CiAgICAgIHJldHVybiB0aGlzLnRvcERpY3Q7CiAgICB9CiAgICBpZiAocmVjb3ZlcnlNb2RlKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICB0aHJvdyBuZXcgX2NvcmVfdXRpbHMuWFJlZlBhcnNlRXhjZXB0aW9uKCk7CiAgfQogIGdldCBsYXN0WFJlZlN0cmVhbVBvcygpIHsKICAgIHJldHVybiB0aGlzLl94cmVmU3Rtcy5zaXplID4gMCA/IE1hdGgubWF4KC4uLnRoaXMuX3hyZWZTdG1zKSA6IG51bGw7CiAgfQogIGdldEVudHJ5KGkpIHsKICAgIGNvbnN0IHhyZWZFbnRyeSA9IHRoaXMuZW50cmllc1tpXTsKICAgIGlmICh4cmVmRW50cnkgJiYgIXhyZWZFbnRyeS5mcmVlICYmIHhyZWZFbnRyeS5vZmZzZXQpIHsKICAgICAgcmV0dXJuIHhyZWZFbnRyeTsKICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICBmZXRjaElmUmVmKG9iaikgewogICAgbGV0IHN1cHByZXNzRW5jcnlwdGlvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogZmFsc2U7CiAgICBpZiAob2JqIGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuUmVmKSB7CiAgICAgIHJldHVybiB0aGlzLmZldGNoKG9iaiwgc3VwcHJlc3NFbmNyeXB0aW9uKTsKICAgIH0KICAgIHJldHVybiBvYmo7CiAgfQogIGZldGNoKHJlZikgewogICAgbGV0IHN1cHByZXNzRW5jcnlwdGlvbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogZmFsc2U7CiAgICBpZiAoIShyZWYgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigicmVmIG9iamVjdCBpcyBub3QgYSByZWZlcmVuY2UiKTsKICAgIH0KICAgIGNvbnN0IG51bSA9IHJlZi5udW07CiAgICBjb25zdCBjYWNoZUVudHJ5ID0gdGhpcy5fY2FjaGVNYXAuZ2V0KG51bSk7CiAgICBpZiAoY2FjaGVFbnRyeSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmIChjYWNoZUVudHJ5IGluc3RhbmNlb2YgX3ByaW1pdGl2ZXMuRGljdCAmJiAhY2FjaGVFbnRyeS5vYmpJZCkgewogICAgICAgIGNhY2hlRW50cnkub2JqSWQgPSByZWYudG9TdHJpbmcoKTsKICAgICAgfQogICAgICByZXR1cm4gY2FjaGVFbnRyeTsKICAgIH0KICAgIGxldCB4cmVmRW50cnkgPSB0aGlzLmdldEVudHJ5KG51bSk7CiAgICBpZiAoeHJlZkVudHJ5ID09PSBudWxsKSB7CiAgICAgIHRoaXMuX2NhY2hlTWFwLnNldChudW0sIHhyZWZFbnRyeSk7CiAgICAgIHJldHVybiB4cmVmRW50cnk7CiAgICB9CiAgICBpZiAodGhpcy5fcGVuZGluZ1JlZnMuaGFzKHJlZikpIHsKICAgICAgdGhpcy5fcGVuZGluZ1JlZnMucmVtb3ZlKHJlZik7CiAgICAgICgwLCBfdXRpbC53YXJuKShgSWdub3JpbmcgY2lyY3VsYXIgcmVmZXJlbmNlOiAke3JlZn0uYCk7CiAgICAgIHJldHVybiBfcHJpbWl0aXZlcy5DSVJDVUxBUl9SRUY7CiAgICB9CiAgICB0aGlzLl9wZW5kaW5nUmVmcy5wdXQocmVmKTsKICAgIHRyeSB7CiAgICAgIGlmICh4cmVmRW50cnkudW5jb21wcmVzc2VkKSB7CiAgICAgICAgeHJlZkVudHJ5ID0gdGhpcy5mZXRjaFVuY29tcHJlc3NlZChyZWYsIHhyZWZFbnRyeSwgc3VwcHJlc3NFbmNyeXB0aW9uKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB4cmVmRW50cnkgPSB0aGlzLmZldGNoQ29tcHJlc3NlZChyZWYsIHhyZWZFbnRyeSwgc3VwcHJlc3NFbmNyeXB0aW9uKTsKICAgICAgfQogICAgICB0aGlzLl9wZW5kaW5nUmVmcy5yZW1vdmUocmVmKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIHRoaXMuX3BlbmRpbmdSZWZzLnJlbW92ZShyZWYpOwogICAgICB0aHJvdyBleDsKICAgIH0KICAgIGlmICh4cmVmRW50cnkgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5EaWN0KSB7CiAgICAgIHhyZWZFbnRyeS5vYmpJZCA9IHJlZi50b1N0cmluZygpOwogICAgfSBlbHNlIGlmICh4cmVmRW50cnkgaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkgewogICAgICB4cmVmRW50cnkuZGljdC5vYmpJZCA9IHJlZi50b1N0cmluZygpOwogICAgfQogICAgcmV0dXJuIHhyZWZFbnRyeTsKICB9CiAgZmV0Y2hVbmNvbXByZXNzZWQocmVmLCB4cmVmRW50cnkpIHsKICAgIGxldCBzdXBwcmVzc0VuY3J5cHRpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IGZhbHNlOwogICAgY29uc3QgZ2VuID0gcmVmLmdlbjsKICAgIGxldCBudW0gPSByZWYubnVtOwogICAgaWYgKHhyZWZFbnRyeS5nZW4gIT09IGdlbikgewogICAgICBjb25zdCBtc2cgPSBgSW5jb25zaXN0ZW50IGdlbmVyYXRpb24gaW4gWFJlZjogJHtyZWZ9YDsKICAgICAgaWYgKHRoaXMuX2dlbmVyYXRpb25GYWxsYmFjayAmJiB4cmVmRW50cnkuZ2VuIDwgZ2VuKSB7CiAgICAgICAgKDAsIF91dGlsLndhcm4pKG1zZyk7CiAgICAgICAgcmV0dXJuIHRoaXMuZmV0Y2hVbmNvbXByZXNzZWQoX3ByaW1pdGl2ZXMuUmVmLmdldChudW0sIHhyZWZFbnRyeS5nZW4pLCB4cmVmRW50cnksIHN1cHByZXNzRW5jcnlwdGlvbik7CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IF9jb3JlX3V0aWxzLlhSZWZFbnRyeUV4Y2VwdGlvbihtc2cpOwogICAgfQogICAgY29uc3Qgc3RyZWFtID0gdGhpcy5zdHJlYW0ubWFrZVN1YlN0cmVhbSh4cmVmRW50cnkub2Zmc2V0ICsgdGhpcy5zdHJlYW0uc3RhcnQpOwogICAgY29uc3QgcGFyc2VyID0gbmV3IF9wYXJzZXIuUGFyc2VyKHsKICAgICAgbGV4ZXI6IG5ldyBfcGFyc2VyLkxleGVyKHN0cmVhbSksCiAgICAgIHhyZWY6IHRoaXMsCiAgICAgIGFsbG93U3RyZWFtczogdHJ1ZQogICAgfSk7CiAgICBjb25zdCBvYmoxID0gcGFyc2VyLmdldE9iaigpOwogICAgY29uc3Qgb2JqMiA9IHBhcnNlci5nZXRPYmooKTsKICAgIGNvbnN0IG9iajMgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICBpZiAob2JqMSAhPT0gbnVtIHx8IG9iajIgIT09IGdlbiB8fCAhKG9iajMgaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5DbWQpKSB7CiAgICAgIHRocm93IG5ldyBfY29yZV91dGlscy5YUmVmRW50cnlFeGNlcHRpb24oYEJhZCAodW5jb21wcmVzc2VkKSBYUmVmIGVudHJ5OiAke3JlZn1gKTsKICAgIH0KICAgIGlmIChvYmozLmNtZCAhPT0gIm9iaiIpIHsKICAgICAgaWYgKG9iajMuY21kLnN0YXJ0c1dpdGgoIm9iaiIpKSB7CiAgICAgICAgbnVtID0gcGFyc2VJbnQob2JqMy5jbWQuc3Vic3RyaW5nKDMpLCAxMCk7CiAgICAgICAgaWYgKCFOdW1iZXIuaXNOYU4obnVtKSkgewogICAgICAgICAgcmV0dXJuIG51bTsKICAgICAgICB9CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IF9jb3JlX3V0aWxzLlhSZWZFbnRyeUV4Y2VwdGlvbihgQmFkICh1bmNvbXByZXNzZWQpIFhSZWYgZW50cnk6ICR7cmVmfWApOwogICAgfQogICAgaWYgKHRoaXMuZW5jcnlwdCAmJiAhc3VwcHJlc3NFbmNyeXB0aW9uKSB7CiAgICAgIHhyZWZFbnRyeSA9IHBhcnNlci5nZXRPYmoodGhpcy5lbmNyeXB0LmNyZWF0ZUNpcGhlclRyYW5zZm9ybShudW0sIGdlbikpOwogICAgfSBlbHNlIHsKICAgICAgeHJlZkVudHJ5ID0gcGFyc2VyLmdldE9iaigpOwogICAgfQogICAgaWYgKCEoeHJlZkVudHJ5IGluc3RhbmNlb2YgX2Jhc2Vfc3RyZWFtLkJhc2VTdHJlYW0pKSB7CiAgICAgIHRoaXMuX2NhY2hlTWFwLnNldChudW0sIHhyZWZFbnRyeSk7CiAgICB9CiAgICByZXR1cm4geHJlZkVudHJ5OwogIH0KICBmZXRjaENvbXByZXNzZWQocmVmLCB4cmVmRW50cnkpIHsKICAgIGxldCBzdXBwcmVzc0VuY3J5cHRpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IGZhbHNlOwogICAgY29uc3QgdGFibGVPZmZzZXQgPSB4cmVmRW50cnkub2Zmc2V0OwogICAgY29uc3Qgc3RyZWFtID0gdGhpcy5mZXRjaChfcHJpbWl0aXZlcy5SZWYuZ2V0KHRhYmxlT2Zmc2V0LCAwKSk7CiAgICBpZiAoIShzdHJlYW0gaW5zdGFuY2VvZiBfYmFzZV9zdHJlYW0uQmFzZVN0cmVhbSkpIHsKICAgICAgdGhyb3cgbmV3IF91dGlsLkZvcm1hdEVycm9yKCJiYWQgT2JqU3RtIHN0cmVhbSIpOwogICAgfQogICAgY29uc3QgZmlyc3QgPSBzdHJlYW0uZGljdC5nZXQoIkZpcnN0Iik7CiAgICBjb25zdCBuID0gc3RyZWFtLmRpY3QuZ2V0KCJOIik7CiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoZmlyc3QpIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKG4pKSB7CiAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiaW52YWxpZCBmaXJzdCBhbmQgbiBwYXJhbWV0ZXJzIGZvciBPYmpTdG0gc3RyZWFtIik7CiAgICB9CiAgICBsZXQgcGFyc2VyID0gbmV3IF9wYXJzZXIuUGFyc2VyKHsKICAgICAgbGV4ZXI6IG5ldyBfcGFyc2VyLkxleGVyKHN0cmVhbSksCiAgICAgIHhyZWY6IHRoaXMsCiAgICAgIGFsbG93U3RyZWFtczogdHJ1ZQogICAgfSk7CiAgICBjb25zdCBudW1zID0gbmV3IEFycmF5KG4pOwogICAgY29uc3Qgb2Zmc2V0cyA9IG5ldyBBcnJheShuKTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgKytpKSB7CiAgICAgIGNvbnN0IG51bSA9IHBhcnNlci5nZXRPYmooKTsKICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKG51bSkpIHsKICAgICAgICB0aHJvdyBuZXcgX3V0aWwuRm9ybWF0RXJyb3IoYGludmFsaWQgb2JqZWN0IG51bWJlciBpbiB0aGUgT2JqU3RtIHN0cmVhbTogJHtudW19YCk7CiAgICAgIH0KICAgICAgY29uc3Qgb2Zmc2V0ID0gcGFyc2VyLmdldE9iaigpOwogICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIob2Zmc2V0KSkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcihgaW52YWxpZCBvYmplY3Qgb2Zmc2V0IGluIHRoZSBPYmpTdG0gc3RyZWFtOiAke29mZnNldH1gKTsKICAgICAgfQogICAgICBudW1zW2ldID0gbnVtOwogICAgICBvZmZzZXRzW2ldID0gb2Zmc2V0OwogICAgfQogICAgY29uc3Qgc3RhcnQgPSAoc3RyZWFtLnN0YXJ0IHx8IDApICsgZmlyc3Q7CiAgICBjb25zdCBlbnRyaWVzID0gbmV3IEFycmF5KG4pOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyArK2kpIHsKICAgICAgY29uc3QgbGVuZ3RoID0gaSA8IG4gLSAxID8gb2Zmc2V0c1tpICsgMV0gLSBvZmZzZXRzW2ldIDogdW5kZWZpbmVkOwogICAgICBpZiAobGVuZ3RoIDwgMCkgewogICAgICAgIHRocm93IG5ldyBfdXRpbC5Gb3JtYXRFcnJvcigiSW52YWxpZCBvZmZzZXQgaW4gdGhlIE9ialN0bSBzdHJlYW0uIik7CiAgICAgIH0KICAgICAgcGFyc2VyID0gbmV3IF9wYXJzZXIuUGFyc2VyKHsKICAgICAgICBsZXhlcjogbmV3IF9wYXJzZXIuTGV4ZXIoc3RyZWFtLm1ha2VTdWJTdHJlYW0oc3RhcnQgKyBvZmZzZXRzW2ldLCBsZW5ndGgsIHN0cmVhbS5kaWN0KSksCiAgICAgICAgeHJlZjogdGhpcywKICAgICAgICBhbGxvd1N0cmVhbXM6IHRydWUKICAgICAgfSk7CiAgICAgIGNvbnN0IG9iaiA9IHBhcnNlci5nZXRPYmooKTsKICAgICAgZW50cmllc1tpXSA9IG9iajsKICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIF9iYXNlX3N0cmVhbS5CYXNlU3RyZWFtKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgbnVtID0gbnVtc1tpXSwKICAgICAgICBlbnRyeSA9IHRoaXMuZW50cmllc1tudW1dOwogICAgICBpZiAoZW50cnkgJiYgZW50cnkub2Zmc2V0ID09PSB0YWJsZU9mZnNldCAmJiBlbnRyeS5nZW4gPT09IGkpIHsKICAgICAgICB0aGlzLl9jYWNoZU1hcC5zZXQobnVtLCBvYmopOwogICAgICB9CiAgICB9CiAgICB4cmVmRW50cnkgPSBlbnRyaWVzW3hyZWZFbnRyeS5nZW5dOwogICAgaWYgKHhyZWZFbnRyeSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHRocm93IG5ldyBfY29yZV91dGlscy5YUmVmRW50cnlFeGNlcHRpb24oYEJhZCAoY29tcHJlc3NlZCkgWFJlZiBlbnRyeTogJHtyZWZ9YCk7CiAgICB9CiAgICByZXR1cm4geHJlZkVudHJ5OwogIH0KICBhc3luYyBmZXRjaElmUmVmQXN5bmMob2JqLCBzdXBwcmVzc0VuY3J5cHRpb24pIHsKICAgIGlmIChvYmogaW5zdGFuY2VvZiBfcHJpbWl0aXZlcy5SZWYpIHsKICAgICAgcmV0dXJuIHRoaXMuZmV0Y2hBc3luYyhvYmosIHN1cHByZXNzRW5jcnlwdGlvbik7CiAgICB9CiAgICByZXR1cm4gb2JqOwogIH0KICBhc3luYyBmZXRjaEFzeW5jKHJlZiwgc3VwcHJlc3NFbmNyeXB0aW9uKSB7CiAgICB0cnkgewogICAgICByZXR1cm4gdGhpcy5mZXRjaChyZWYsIHN1cHByZXNzRW5jcnlwdGlvbik7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoIShleCBpbnN0YW5jZW9mIF9jb3JlX3V0aWxzLk1pc3NpbmdEYXRhRXhjZXB0aW9uKSkgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIGF3YWl0IHRoaXMucGRmTWFuYWdlci5yZXF1ZXN0UmFuZ2UoZXguYmVnaW4sIGV4LmVuZCk7CiAgICAgIHJldHVybiB0aGlzLmZldGNoQXN5bmMocmVmLCBzdXBwcmVzc0VuY3J5cHRpb24pOwogICAgfQogIH0KICBnZXRDYXRhbG9nT2JqKCkgewogICAgcmV0dXJuIHRoaXMucm9vdDsKICB9Cn0KZXhwb3J0cy5YUmVmID0gWFJlZjsKCi8qKiovIH0pLAovKiAyMzcgKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLk1lc3NhZ2VIYW5kbGVyID0gdm9pZCAwOwp2YXIgX3V0aWwgPSBfX3dfcGRmanNfcmVxdWlyZV9fKDIpOwpjb25zdCBDYWxsYmFja0tpbmQgPSB7CiAgVU5LTk9XTjogMCwKICBEQVRBOiAxLAogIEVSUk9SOiAyCn07CmNvbnN0IFN0cmVhbUtpbmQgPSB7CiAgVU5LTk9XTjogMCwKICBDQU5DRUw6IDEsCiAgQ0FOQ0VMX0NPTVBMRVRFOiAyLAogIENMT1NFOiAzLAogIEVOUVVFVUU6IDQsCiAgRVJST1I6IDUsCiAgUFVMTDogNiwKICBQVUxMX0NPTVBMRVRFOiA3LAogIFNUQVJUX0NPTVBMRVRFOiA4Cn07CmZ1bmN0aW9uIHdyYXBSZWFzb24ocmVhc29uKSB7CiAgaWYgKCEocmVhc29uIGluc3RhbmNlb2YgRXJyb3IgfHwgdHlwZW9mIHJlYXNvbiA9PT0gIm9iamVjdCIgJiYgcmVhc29uICE9PSBudWxsKSkgewogICAgKDAsIF91dGlsLnVucmVhY2hhYmxlKSgnd3JhcFJlYXNvbjogRXhwZWN0ZWQgInJlYXNvbiIgdG8gYmUgYSAocG9zc2libHkgY2xvbmVkKSBFcnJvci4nKTsKICB9CiAgc3dpdGNoIChyZWFzb24ubmFtZSkgewogICAgY2FzZSAiQWJvcnRFeGNlcHRpb24iOgogICAgICByZXR1cm4gbmV3IF91dGlsLkFib3J0RXhjZXB0aW9uKHJlYXNvbi5tZXNzYWdlKTsKICAgIGNhc2UgIk1pc3NpbmdQREZFeGNlcHRpb24iOgogICAgICByZXR1cm4gbmV3IF91dGlsLk1pc3NpbmdQREZFeGNlcHRpb24ocmVhc29uLm1lc3NhZ2UpOwogICAgY2FzZSAiUGFzc3dvcmRFeGNlcHRpb24iOgogICAgICByZXR1cm4gbmV3IF91dGlsLlBhc3N3b3JkRXhjZXB0aW9uKHJlYXNvbi5tZXNzYWdlLCByZWFzb24uY29kZSk7CiAgICBjYXNlICJVbmV4cGVjdGVkUmVzcG9uc2VFeGNlcHRpb24iOgogICAgICByZXR1cm4gbmV3IF91dGlsLlVuZXhwZWN0ZWRSZXNwb25zZUV4Y2VwdGlvbihyZWFzb24ubWVzc2FnZSwgcmVhc29uLnN0YXR1cyk7CiAgICBjYXNlICJVbmtub3duRXJyb3JFeGNlcHRpb24iOgogICAgICByZXR1cm4gbmV3IF91dGlsLlVua25vd25FcnJvckV4Y2VwdGlvbihyZWFzb24ubWVzc2FnZSwgcmVhc29uLmRldGFpbHMpOwogICAgZGVmYXVsdDoKICAgICAgcmV0dXJuIG5ldyBfdXRpbC5Vbmtub3duRXJyb3JFeGNlcHRpb24ocmVhc29uLm1lc3NhZ2UsIHJlYXNvbi50b1N0cmluZygpKTsKICB9Cn0KY2xhc3MgTWVzc2FnZUhhbmRsZXIgewogIGNvbnN0cnVjdG9yKHNvdXJjZU5hbWUsIHRhcmdldE5hbWUsIGNvbU9iaikgewogICAgdGhpcy5zb3VyY2VOYW1lID0gc291cmNlTmFtZTsKICAgIHRoaXMudGFyZ2V0TmFtZSA9IHRhcmdldE5hbWU7CiAgICB0aGlzLmNvbU9iaiA9IGNvbU9iajsKICAgIHRoaXMuY2FsbGJhY2tJZCA9IDE7CiAgICB0aGlzLnN0cmVhbUlkID0gMTsKICAgIHRoaXMuc3RyZWFtU2lua3MgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgdGhpcy5zdHJlYW1Db250cm9sbGVycyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHRoaXMuYWN0aW9uSGFuZGxlciA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB0aGlzLl9vbkNvbU9iak9uTWVzc2FnZSA9IGV2ZW50ID0+IHsKICAgICAgY29uc3QgZGF0YSA9IGV2ZW50LmRhdGE7CiAgICAgIGlmIChkYXRhLnRhcmdldE5hbWUgIT09IHRoaXMuc291cmNlTmFtZSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBpZiAoZGF0YS5zdHJlYW0pIHsKICAgICAgICB0aGlzLl9wcm9jZXNzU3RyZWFtTWVzc2FnZShkYXRhKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgaWYgKGRhdGEuY2FsbGJhY2spIHsKICAgICAgICBjb25zdCBjYWxsYmFja0lkID0gZGF0YS5jYWxsYmFja0lkOwogICAgICAgIGNvbnN0IGNhcGFiaWxpdHkgPSB0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzW2NhbGxiYWNrSWRdOwogICAgICAgIGlmICghY2FwYWJpbGl0eSkgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgcmVzb2x2ZSBjYWxsYmFjayAke2NhbGxiYWNrSWR9YCk7CiAgICAgICAgfQogICAgICAgIGRlbGV0ZSB0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzW2NhbGxiYWNrSWRdOwogICAgICAgIGlmIChkYXRhLmNhbGxiYWNrID09PSBDYWxsYmFja0tpbmQuREFUQSkgewogICAgICAgICAgY2FwYWJpbGl0eS5yZXNvbHZlKGRhdGEuZGF0YSk7CiAgICAgICAgfSBlbHNlIGlmIChkYXRhLmNhbGxiYWNrID09PSBDYWxsYmFja0tpbmQuRVJST1IpIHsKICAgICAgICAgIGNhcGFiaWxpdHkucmVqZWN0KHdyYXBSZWFzb24oZGF0YS5yZWFzb24pKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJVbmV4cGVjdGVkIGNhbGxiYWNrIGNhc2UiKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNvbnN0IGFjdGlvbiA9IHRoaXMuYWN0aW9uSGFuZGxlcltkYXRhLmFjdGlvbl07CiAgICAgIGlmICghYWN0aW9uKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIGFjdGlvbiBmcm9tIHdvcmtlcjogJHtkYXRhLmFjdGlvbn1gKTsKICAgICAgfQogICAgICBpZiAoZGF0YS5jYWxsYmFja0lkKSB7CiAgICAgICAgY29uc3QgY2JTb3VyY2VOYW1lID0gdGhpcy5zb3VyY2VOYW1lOwogICAgICAgIGNvbnN0IGNiVGFyZ2V0TmFtZSA9IGRhdGEuc291cmNlTmFtZTsKICAgICAgICBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkgewogICAgICAgICAgcmVzb2x2ZShhY3Rpb24oZGF0YS5kYXRhKSk7CiAgICAgICAgfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7CiAgICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICBzb3VyY2VOYW1lOiBjYlNvdXJjZU5hbWUsCiAgICAgICAgICAgIHRhcmdldE5hbWU6IGNiVGFyZ2V0TmFtZSwKICAgICAgICAgICAgY2FsbGJhY2s6IENhbGxiYWNrS2luZC5EQVRBLAogICAgICAgICAgICBjYWxsYmFja0lkOiBkYXRhLmNhbGxiYWNrSWQsCiAgICAgICAgICAgIGRhdGE6IHJlc3VsdAogICAgICAgICAgfSk7CiAgICAgICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgc291cmNlTmFtZTogY2JTb3VyY2VOYW1lLAogICAgICAgICAgICB0YXJnZXROYW1lOiBjYlRhcmdldE5hbWUsCiAgICAgICAgICAgIGNhbGxiYWNrOiBDYWxsYmFja0tpbmQuRVJST1IsCiAgICAgICAgICAgIGNhbGxiYWNrSWQ6IGRhdGEuY2FsbGJhY2tJZCwKICAgICAgICAgICAgcmVhc29uOiB3cmFwUmVhc29uKHJlYXNvbikKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBpZiAoZGF0YS5zdHJlYW1JZCkgewogICAgICAgIHRoaXMuX2NyZWF0ZVN0cmVhbVNpbmsoZGF0YSk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGFjdGlvbihkYXRhLmRhdGEpOwogICAgfTsKICAgIGNvbU9iai5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIiwgdGhpcy5fb25Db21PYmpPbk1lc3NhZ2UpOwogIH0KICBvbihhY3Rpb25OYW1lLCBoYW5kbGVyKSB7CiAgICBjb25zdCBhaCA9IHRoaXMuYWN0aW9uSGFuZGxlcjsKICAgIGlmIChhaFthY3Rpb25OYW1lXSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZXJlIGlzIGFscmVhZHkgYW4gYWN0aW9uTmFtZSBjYWxsZWQgIiR7YWN0aW9uTmFtZX0iYCk7CiAgICB9CiAgICBhaFthY3Rpb25OYW1lXSA9IGhhbmRsZXI7CiAgfQogIHNlbmQoYWN0aW9uTmFtZSwgZGF0YSwgdHJhbnNmZXJzKSB7CiAgICB0aGlzLmNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgIHNvdXJjZU5hbWU6IHRoaXMuc291cmNlTmFtZSwKICAgICAgdGFyZ2V0TmFtZTogdGhpcy50YXJnZXROYW1lLAogICAgICBhY3Rpb246IGFjdGlvbk5hbWUsCiAgICAgIGRhdGEKICAgIH0sIHRyYW5zZmVycyk7CiAgfQogIHNlbmRXaXRoUHJvbWlzZShhY3Rpb25OYW1lLCBkYXRhLCB0cmFuc2ZlcnMpIHsKICAgIGNvbnN0IGNhbGxiYWNrSWQgPSB0aGlzLmNhbGxiYWNrSWQrKzsKICAgIGNvbnN0IGNhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICB0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzW2NhbGxiYWNrSWRdID0gY2FwYWJpbGl0eTsKICAgIHRyeSB7CiAgICAgIHRoaXMuY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICBzb3VyY2VOYW1lOiB0aGlzLnNvdXJjZU5hbWUsCiAgICAgICAgdGFyZ2V0TmFtZTogdGhpcy50YXJnZXROYW1lLAogICAgICAgIGFjdGlvbjogYWN0aW9uTmFtZSwKICAgICAgICBjYWxsYmFja0lkLAogICAgICAgIGRhdGEKICAgICAgfSwgdHJhbnNmZXJzKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGNhcGFiaWxpdHkucmVqZWN0KGV4KTsKICAgIH0KICAgIHJldHVybiBjYXBhYmlsaXR5LnByb21pc2U7CiAgfQogIHNlbmRXaXRoU3RyZWFtKGFjdGlvbk5hbWUsIGRhdGEsIHF1ZXVlaW5nU3RyYXRlZ3ksIHRyYW5zZmVycykgewogICAgY29uc3Qgc3RyZWFtSWQgPSB0aGlzLnN0cmVhbUlkKyssCiAgICAgIHNvdXJjZU5hbWUgPSB0aGlzLnNvdXJjZU5hbWUsCiAgICAgIHRhcmdldE5hbWUgPSB0aGlzLnRhcmdldE5hbWUsCiAgICAgIGNvbU9iaiA9IHRoaXMuY29tT2JqOwogICAgcmV0dXJuIG5ldyBSZWFkYWJsZVN0cmVhbSh7CiAgICAgIHN0YXJ0OiBjb250cm9sbGVyID0+IHsKICAgICAgICBjb25zdCBzdGFydENhcGFiaWxpdHkgPSAoMCwgX3V0aWwuY3JlYXRlUHJvbWlzZUNhcGFiaWxpdHkpKCk7CiAgICAgICAgdGhpcy5zdHJlYW1Db250cm9sbGVyc1tzdHJlYW1JZF0gPSB7CiAgICAgICAgICBjb250cm9sbGVyLAogICAgICAgICAgc3RhcnRDYWxsOiBzdGFydENhcGFiaWxpdHksCiAgICAgICAgICBwdWxsQ2FsbDogbnVsbCwKICAgICAgICAgIGNhbmNlbENhbGw6IG51bGwsCiAgICAgICAgICBpc0Nsb3NlZDogZmFsc2UKICAgICAgICB9OwogICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgIGFjdGlvbjogYWN0aW9uTmFtZSwKICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgZGF0YSwKICAgICAgICAgIGRlc2lyZWRTaXplOiBjb250cm9sbGVyLmRlc2lyZWRTaXplCiAgICAgICAgfSwgdHJhbnNmZXJzKTsKICAgICAgICByZXR1cm4gc3RhcnRDYXBhYmlsaXR5LnByb21pc2U7CiAgICAgIH0sCiAgICAgIHB1bGw6IGNvbnRyb2xsZXIgPT4gewogICAgICAgIGNvbnN0IHB1bGxDYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogICAgICAgIHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdLnB1bGxDYWxsID0gcHVsbENhcGFiaWxpdHk7CiAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLlBVTEwsCiAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgIGRlc2lyZWRTaXplOiBjb250cm9sbGVyLmRlc2lyZWRTaXplCiAgICAgICAgfSk7CiAgICAgICAgcmV0dXJuIHB1bGxDYXBhYmlsaXR5LnByb21pc2U7CiAgICAgIH0sCiAgICAgIGNhbmNlbDogcmVhc29uID0+IHsKICAgICAgICAoMCwgX3V0aWwuYXNzZXJ0KShyZWFzb24gaW5zdGFuY2VvZiBFcnJvciwgImNhbmNlbCBtdXN0IGhhdmUgYSB2YWxpZCByZWFzb24iKTsKICAgICAgICBjb25zdCBjYW5jZWxDYXBhYmlsaXR5ID0gKDAsIF91dGlsLmNyZWF0ZVByb21pc2VDYXBhYmlsaXR5KSgpOwogICAgICAgIHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdLmNhbmNlbENhbGwgPSBjYW5jZWxDYXBhYmlsaXR5OwogICAgICAgIHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdLmlzQ2xvc2VkID0gdHJ1ZTsKICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuQ0FOQ0VMLAogICAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgICByZWFzb246IHdyYXBSZWFzb24ocmVhc29uKQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBjYW5jZWxDYXBhYmlsaXR5LnByb21pc2U7CiAgICAgIH0KICAgIH0sIHF1ZXVlaW5nU3RyYXRlZ3kpOwogIH0KICBfY3JlYXRlU3RyZWFtU2luayhkYXRhKSB7CiAgICBjb25zdCBzdHJlYW1JZCA9IGRhdGEuc3RyZWFtSWQsCiAgICAgIHNvdXJjZU5hbWUgPSB0aGlzLnNvdXJjZU5hbWUsCiAgICAgIHRhcmdldE5hbWUgPSBkYXRhLnNvdXJjZU5hbWUsCiAgICAgIGNvbU9iaiA9IHRoaXMuY29tT2JqOwogICAgY29uc3Qgc2VsZiA9IHRoaXMsCiAgICAgIGFjdGlvbiA9IHRoaXMuYWN0aW9uSGFuZGxlcltkYXRhLmFjdGlvbl07CiAgICBjb25zdCBzdHJlYW1TaW5rID0gewogICAgICBlbnF1ZXVlKGNodW5rKSB7CiAgICAgICAgbGV0IHNpemUgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IDE7CiAgICAgICAgbGV0IHRyYW5zZmVycyA9IGFyZ3VtZW50cy5sZW5ndGggPiAyID8gYXJndW1lbnRzWzJdIDogdW5kZWZpbmVkOwogICAgICAgIGlmICh0aGlzLmlzQ2FuY2VsbGVkKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IGxhc3REZXNpcmVkU2l6ZSA9IHRoaXMuZGVzaXJlZFNpemU7CiAgICAgICAgdGhpcy5kZXNpcmVkU2l6ZSAtPSBzaXplOwogICAgICAgIGlmIChsYXN0RGVzaXJlZFNpemUgPiAwICYmIHRoaXMuZGVzaXJlZFNpemUgPD0gMCkgewogICAgICAgICAgdGhpcy5zaW5rQ2FwYWJpbGl0eSA9ICgwLCBfdXRpbC5jcmVhdGVQcm9taXNlQ2FwYWJpbGl0eSkoKTsKICAgICAgICAgIHRoaXMucmVhZHkgPSB0aGlzLnNpbmtDYXBhYmlsaXR5LnByb21pc2U7CiAgICAgICAgfQogICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5FTlFVRVVFLAogICAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgICBjaHVuawogICAgICAgIH0sIHRyYW5zZmVycyk7CiAgICAgIH0sCiAgICAgIGNsb3NlKCkgewogICAgICAgIGlmICh0aGlzLmlzQ2FuY2VsbGVkKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIHRoaXMuaXNDYW5jZWxsZWQgPSB0cnVlOwogICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5DTE9TRSwKICAgICAgICAgIHN0cmVhbUlkCiAgICAgICAgfSk7CiAgICAgICAgZGVsZXRlIHNlbGYuc3RyZWFtU2lua3Nbc3RyZWFtSWRdOwogICAgICB9LAogICAgICBlcnJvcihyZWFzb24pIHsKICAgICAgICAoMCwgX3V0aWwuYXNzZXJ0KShyZWFzb24gaW5zdGFuY2VvZiBFcnJvciwgImVycm9yIG11c3QgaGF2ZSBhIHZhbGlkIHJlYXNvbiIpOwogICAgICAgIGlmICh0aGlzLmlzQ2FuY2VsbGVkKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIHRoaXMuaXNDYW5jZWxsZWQgPSB0cnVlOwogICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5FUlJPUiwKICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgcmVhc29uOiB3cmFwUmVhc29uKHJlYXNvbikKICAgICAgICB9KTsKICAgICAgfSwKICAgICAgc2lua0NhcGFiaWxpdHk6ICgwLCBfdXRpbC5jcmVhdGVQcm9taXNlQ2FwYWJpbGl0eSkoKSwKICAgICAgb25QdWxsOiBudWxsLAogICAgICBvbkNhbmNlbDogbnVsbCwKICAgICAgaXNDYW5jZWxsZWQ6IGZhbHNlLAogICAgICBkZXNpcmVkU2l6ZTogZGF0YS5kZXNpcmVkU2l6ZSwKICAgICAgcmVhZHk6IG51bGwKICAgIH07CiAgICBzdHJlYW1TaW5rLnNpbmtDYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgIHN0cmVhbVNpbmsucmVhZHkgPSBzdHJlYW1TaW5rLnNpbmtDYXBhYmlsaXR5LnByb21pc2U7CiAgICB0aGlzLnN0cmVhbVNpbmtzW3N0cmVhbUlkXSA9IHN0cmVhbVNpbms7CiAgICBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkgewogICAgICByZXNvbHZlKGFjdGlvbihkYXRhLmRhdGEsIHN0cmVhbVNpbmspKTsKICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuU1RBUlRfQ09NUExFVEUsCiAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgc3VjY2VzczogdHJ1ZQogICAgICB9KTsKICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLlNUQVJUX0NPTVBMRVRFLAogICAgICAgIHN0cmVhbUlkLAogICAgICAgIHJlYXNvbjogd3JhcFJlYXNvbihyZWFzb24pCiAgICAgIH0pOwogICAgfSk7CiAgfQogIF9wcm9jZXNzU3RyZWFtTWVzc2FnZShkYXRhKSB7CiAgICBjb25zdCBzdHJlYW1JZCA9IGRhdGEuc3RyZWFtSWQsCiAgICAgIHNvdXJjZU5hbWUgPSB0aGlzLnNvdXJjZU5hbWUsCiAgICAgIHRhcmdldE5hbWUgPSBkYXRhLnNvdXJjZU5hbWUsCiAgICAgIGNvbU9iaiA9IHRoaXMuY29tT2JqOwogICAgY29uc3Qgc3RyZWFtQ29udHJvbGxlciA9IHRoaXMuc3RyZWFtQ29udHJvbGxlcnNbc3RyZWFtSWRdLAogICAgICBzdHJlYW1TaW5rID0gdGhpcy5zdHJlYW1TaW5rc1tzdHJlYW1JZF07CiAgICBzd2l0Y2ggKGRhdGEuc3RyZWFtKSB7CiAgICAgIGNhc2UgU3RyZWFtS2luZC5TVEFSVF9DT01QTEVURToKICAgICAgICBpZiAoZGF0YS5zdWNjZXNzKSB7CiAgICAgICAgICBzdHJlYW1Db250cm9sbGVyLnN0YXJ0Q2FsbC5yZXNvbHZlKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN0cmVhbUNvbnRyb2xsZXIuc3RhcnRDYWxsLnJlamVjdCh3cmFwUmVhc29uKGRhdGEucmVhc29uKSk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFN0cmVhbUtpbmQuUFVMTF9DT01QTEVURToKICAgICAgICBpZiAoZGF0YS5zdWNjZXNzKSB7CiAgICAgICAgICBzdHJlYW1Db250cm9sbGVyLnB1bGxDYWxsLnJlc29sdmUoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgc3RyZWFtQ29udHJvbGxlci5wdWxsQ2FsbC5yZWplY3Qod3JhcFJlYXNvbihkYXRhLnJlYXNvbikpOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSBTdHJlYW1LaW5kLlBVTEw6CiAgICAgICAgaWYgKCFzdHJlYW1TaW5rKSB7CiAgICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuUFVMTF9DT01QTEVURSwKICAgICAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUKICAgICAgICAgIH0pOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmIChzdHJlYW1TaW5rLmRlc2lyZWRTaXplIDw9IDAgJiYgZGF0YS5kZXNpcmVkU2l6ZSA+IDApIHsKICAgICAgICAgIHN0cmVhbVNpbmsuc2lua0NhcGFiaWxpdHkucmVzb2x2ZSgpOwogICAgICAgIH0KICAgICAgICBzdHJlYW1TaW5rLmRlc2lyZWRTaXplID0gZGF0YS5kZXNpcmVkU2l6ZTsKICAgICAgICBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkgewogICAgICAgICAgcmVzb2x2ZShzdHJlYW1TaW5rLm9uUHVsbCAmJiBzdHJlYW1TaW5rLm9uUHVsbCgpKTsKICAgICAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5QVUxMX0NPTVBMRVRFLAogICAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgICAgc3VjY2VzczogdHJ1ZQogICAgICAgICAgfSk7CiAgICAgICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLlBVTExfQ09NUExFVEUsCiAgICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgICByZWFzb246IHdyYXBSZWFzb24ocmVhc29uKQogICAgICAgICAgfSk7CiAgICAgICAgfSk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgU3RyZWFtS2luZC5FTlFVRVVFOgogICAgICAgICgwLCBfdXRpbC5hc3NlcnQpKHN0cmVhbUNvbnRyb2xsZXIsICJlbnF1ZXVlIHNob3VsZCBoYXZlIHN0cmVhbSBjb250cm9sbGVyIik7CiAgICAgICAgaWYgKHN0cmVhbUNvbnRyb2xsZXIuaXNDbG9zZWQpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBzdHJlYW1Db250cm9sbGVyLmNvbnRyb2xsZXIuZW5xdWV1ZShkYXRhLmNodW5rKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBTdHJlYW1LaW5kLkNMT1NFOgogICAgICAgICgwLCBfdXRpbC5hc3NlcnQpKHN0cmVhbUNvbnRyb2xsZXIsICJjbG9zZSBzaG91bGQgaGF2ZSBzdHJlYW0gY29udHJvbGxlciIpOwogICAgICAgIGlmIChzdHJlYW1Db250cm9sbGVyLmlzQ2xvc2VkKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgc3RyZWFtQ29udHJvbGxlci5pc0Nsb3NlZCA9IHRydWU7CiAgICAgICAgc3RyZWFtQ29udHJvbGxlci5jb250cm9sbGVyLmNsb3NlKCk7CiAgICAgICAgdGhpcy5fZGVsZXRlU3RyZWFtQ29udHJvbGxlcihzdHJlYW1Db250cm9sbGVyLCBzdHJlYW1JZCk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgU3RyZWFtS2luZC5FUlJPUjoKICAgICAgICAoMCwgX3V0aWwuYXNzZXJ0KShzdHJlYW1Db250cm9sbGVyLCAiZXJyb3Igc2hvdWxkIGhhdmUgc3RyZWFtIGNvbnRyb2xsZXIiKTsKICAgICAgICBzdHJlYW1Db250cm9sbGVyLmNvbnRyb2xsZXIuZXJyb3Iod3JhcFJlYXNvbihkYXRhLnJlYXNvbikpOwogICAgICAgIHRoaXMuX2RlbGV0ZVN0cmVhbUNvbnRyb2xsZXIoc3RyZWFtQ29udHJvbGxlciwgc3RyZWFtSWQpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFN0cmVhbUtpbmQuQ0FOQ0VMX0NPTVBMRVRFOgogICAgICAgIGlmIChkYXRhLnN1Y2Nlc3MpIHsKICAgICAgICAgIHN0cmVhbUNvbnRyb2xsZXIuY2FuY2VsQ2FsbC5yZXNvbHZlKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN0cmVhbUNvbnRyb2xsZXIuY2FuY2VsQ2FsbC5yZWplY3Qod3JhcFJlYXNvbihkYXRhLnJlYXNvbikpOwogICAgICAgIH0KICAgICAgICB0aGlzLl9kZWxldGVTdHJlYW1Db250cm9sbGVyKHN0cmVhbUNvbnRyb2xsZXIsIHN0cmVhbUlkKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBTdHJlYW1LaW5kLkNBTkNFTDoKICAgICAgICBpZiAoIXN0cmVhbVNpbmspIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSkgewogICAgICAgICAgcmVzb2x2ZShzdHJlYW1TaW5rLm9uQ2FuY2VsICYmIHN0cmVhbVNpbmsub25DYW5jZWwod3JhcFJlYXNvbihkYXRhLnJlYXNvbikpKTsKICAgICAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5DQU5DRUxfQ09NUExFVEUsCiAgICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgICBzdWNjZXNzOiB0cnVlCiAgICAgICAgICB9KTsKICAgICAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuQ0FOQ0VMX0NPTVBMRVRFLAogICAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgICAgcmVhc29uOiB3cmFwUmVhc29uKHJlYXNvbikKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICAgIHN0cmVhbVNpbmsuc2lua0NhcGFiaWxpdHkucmVqZWN0KHdyYXBSZWFzb24oZGF0YS5yZWFzb24pKTsKICAgICAgICBzdHJlYW1TaW5rLmlzQ2FuY2VsbGVkID0gdHJ1ZTsKICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW1TaW5rc1tzdHJlYW1JZF07CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJVbmV4cGVjdGVkIHN0cmVhbSBjYXNlIik7CiAgICB9CiAgfQogIGFzeW5jIF9kZWxldGVTdHJlYW1Db250cm9sbGVyKHN0cmVhbUNvbnRyb2xsZXIsIHN0cmVhbUlkKSB7CiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoW3N0cmVhbUNvbnRyb2xsZXIuc3RhcnRDYWxsICYmIHN0cmVhbUNvbnRyb2xsZXIuc3RhcnRDYWxsLnByb21pc2UsIHN0cmVhbUNvbnRyb2xsZXIucHVsbENhbGwgJiYgc3RyZWFtQ29udHJvbGxlci5wdWxsQ2FsbC5wcm9taXNlLCBzdHJlYW1Db250cm9sbGVyLmNhbmNlbENhbGwgJiYgc3RyZWFtQ29udHJvbGxlci5jYW5jZWxDYWxsLnByb21pc2VdKTsKICAgIGRlbGV0ZSB0aGlzLnN0cmVhbUNvbnRyb2xsZXJzW3N0cmVhbUlkXTsKICB9CiAgZGVzdHJveSgpIHsKICAgIHRoaXMuY29tT2JqLnJlbW92ZUV2ZW50TGlzdGVuZXIoIm1lc3NhZ2UiLCB0aGlzLl9vbkNvbU9iak9uTWVzc2FnZSk7CiAgfQp9CmV4cG9ydHMuTWVzc2FnZUhhbmRsZXIgPSBNZXNzYWdlSGFuZGxlcjsKCi8qKiovIH0pLAovKiAyMzggKi8KLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193X3BkZmpzX3JlcXVpcmVfXykgPT4gewoKInVzZSBzdHJpY3QiOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpleHBvcnRzLlBERldvcmtlclN0cmVhbSA9IHZvaWQgMDsKdmFyIF91dGlsID0gX193X3BkZmpzX3JlcXVpcmVfXygyKTsKY2xhc3MgUERGV29ya2VyU3RyZWFtIHsKICBjb25zdHJ1Y3Rvcihtc2dIYW5kbGVyKSB7CiAgICB0aGlzLl9tc2dIYW5kbGVyID0gbXNnSGFuZGxlcjsKICAgIHRoaXMuX2NvbnRlbnRMZW5ndGggPSBudWxsOwogICAgdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXIgPSBudWxsOwogICAgdGhpcy5fcmFuZ2VSZXF1ZXN0UmVhZGVycyA9IFtdOwogIH0KICBnZXRGdWxsUmVhZGVyKCkgewogICAgKDAsIF91dGlsLmFzc2VydCkoIXRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyLCAiUERGV29ya2VyU3RyZWFtLmdldEZ1bGxSZWFkZXIgY2FuIG9ubHkgYmUgY2FsbGVkIG9uY2UuIik7CiAgICB0aGlzLl9mdWxsUmVxdWVzdFJlYWRlciA9IG5ldyBQREZXb3JrZXJTdHJlYW1SZWFkZXIodGhpcy5fbXNnSGFuZGxlcik7CiAgICByZXR1cm4gdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXI7CiAgfQogIGdldFJhbmdlUmVhZGVyKGJlZ2luLCBlbmQpIHsKICAgIGNvbnN0IHJlYWRlciA9IG5ldyBQREZXb3JrZXJTdHJlYW1SYW5nZVJlYWRlcihiZWdpbiwgZW5kLCB0aGlzLl9tc2dIYW5kbGVyKTsKICAgIHRoaXMuX3JhbmdlUmVxdWVzdFJlYWRlcnMucHVzaChyZWFkZXIpOwogICAgcmV0dXJuIHJlYWRlcjsKICB9CiAgY2FuY2VsQWxsUmVxdWVzdHMocmVhc29uKSB7CiAgICBpZiAodGhpcy5fZnVsbFJlcXVlc3RSZWFkZXIpIHsKICAgICAgdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXIuY2FuY2VsKHJlYXNvbik7CiAgICB9CiAgICBmb3IgKGNvbnN0IHJlYWRlciBvZiB0aGlzLl9yYW5nZVJlcXVlc3RSZWFkZXJzLnNsaWNlKDApKSB7CiAgICAgIHJlYWRlci5jYW5jZWwocmVhc29uKTsKICAgIH0KICB9Cn0KZXhwb3J0cy5QREZXb3JrZXJTdHJlYW0gPSBQREZXb3JrZXJTdHJlYW07CmNsYXNzIFBERldvcmtlclN0cmVhbVJlYWRlciB7CiAgY29uc3RydWN0b3IobXNnSGFuZGxlcikgewogICAgdGhpcy5fbXNnSGFuZGxlciA9IG1zZ0hhbmRsZXI7CiAgICB0aGlzLm9uUHJvZ3Jlc3MgPSBudWxsOwogICAgdGhpcy5fY29udGVudExlbmd0aCA9IG51bGw7CiAgICB0aGlzLl9pc1JhbmdlU3VwcG9ydGVkID0gZmFsc2U7CiAgICB0aGlzLl9pc1N0cmVhbWluZ1N1cHBvcnRlZCA9IGZhbHNlOwogICAgY29uc3QgcmVhZGFibGVTdHJlYW0gPSB0aGlzLl9tc2dIYW5kbGVyLnNlbmRXaXRoU3RyZWFtKCJHZXRSZWFkZXIiKTsKICAgIHRoaXMuX3JlYWRlciA9IHJlYWRhYmxlU3RyZWFtLmdldFJlYWRlcigpOwogICAgdGhpcy5faGVhZGVyc1JlYWR5ID0gdGhpcy5fbXNnSGFuZGxlci5zZW5kV2l0aFByb21pc2UoIlJlYWRlckhlYWRlcnNSZWFkeSIpLnRoZW4oZGF0YSA9PiB7CiAgICAgIHRoaXMuX2lzU3RyZWFtaW5nU3VwcG9ydGVkID0gZGF0YS5pc1N0cmVhbWluZ1N1cHBvcnRlZDsKICAgICAgdGhpcy5faXNSYW5nZVN1cHBvcnRlZCA9IGRhdGEuaXNSYW5nZVN1cHBvcnRlZDsKICAgICAgdGhpcy5fY29udGVudExlbmd0aCA9IGRhdGEuY29udGVudExlbmd0aDsKICAgIH0pOwogIH0KICBnZXQgaGVhZGVyc1JlYWR5KCkgewogICAgcmV0dXJuIHRoaXMuX2hlYWRlcnNSZWFkeTsKICB9CiAgZ2V0IGNvbnRlbnRMZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5fY29udGVudExlbmd0aDsKICB9CiAgZ2V0IGlzU3RyZWFtaW5nU3VwcG9ydGVkKCkgewogICAgcmV0dXJuIHRoaXMuX2lzU3RyZWFtaW5nU3VwcG9ydGVkOwogIH0KICBnZXQgaXNSYW5nZVN1cHBvcnRlZCgpIHsKICAgIHJldHVybiB0aGlzLl9pc1JhbmdlU3VwcG9ydGVkOwogIH0KICBhc3luYyByZWFkKCkgewogICAgY29uc3QgewogICAgICB2YWx1ZSwKICAgICAgZG9uZQogICAgfSA9IGF3YWl0IHRoaXMuX3JlYWRlci5yZWFkKCk7CiAgICBpZiAoZG9uZSkgewogICAgICByZXR1cm4gewogICAgICAgIHZhbHVlOiB1bmRlZmluZWQsCiAgICAgICAgZG9uZTogdHJ1ZQogICAgICB9OwogICAgfQogICAgcmV0dXJuIHsKICAgICAgdmFsdWU6IHZhbHVlLmJ1ZmZlciwKICAgICAgZG9uZTogZmFsc2UKICAgIH07CiAgfQogIGNhbmNlbChyZWFzb24pIHsKICAgIHRoaXMuX3JlYWRlci5jYW5jZWwocmVhc29uKTsKICB9Cn0KY2xhc3MgUERGV29ya2VyU3RyZWFtUmFuZ2VSZWFkZXIgewogIGNvbnN0cnVjdG9yKGJlZ2luLCBlbmQsIG1zZ0hhbmRsZXIpIHsKICAgIHRoaXMuX21zZ0hhbmRsZXIgPSBtc2dIYW5kbGVyOwogICAgdGhpcy5vblByb2dyZXNzID0gbnVsbDsKICAgIGNvbnN0IHJlYWRhYmxlU3RyZWFtID0gdGhpcy5fbXNnSGFuZGxlci5zZW5kV2l0aFN0cmVhbSgiR2V0UmFuZ2VSZWFkZXIiLCB7CiAgICAgIGJlZ2luLAogICAgICBlbmQKICAgIH0pOwogICAgdGhpcy5fcmVhZGVyID0gcmVhZGFibGVTdHJlYW0uZ2V0UmVhZGVyKCk7CiAgfQogIGdldCBpc1N0cmVhbWluZ1N1cHBvcnRlZCgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgYXN5bmMgcmVhZCgpIHsKICAgIGNvbnN0IHsKICAgICAgdmFsdWUsCiAgICAgIGRvbmUKICAgIH0gPSBhd2FpdCB0aGlzLl9yZWFkZXIucmVhZCgpOwogICAgaWYgKGRvbmUpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICB2YWx1ZTogdW5kZWZpbmVkLAogICAgICAgIGRvbmU6IHRydWUKICAgICAgfTsKICAgIH0KICAgIHJldHVybiB7CiAgICAgIHZhbHVlOiB2YWx1ZS5idWZmZXIsCiAgICAgIGRvbmU6IGZhbHNlCiAgICB9OwogIH0KICBjYW5jZWwocmVhc29uKSB7CiAgICB0aGlzLl9yZWFkZXIuY2FuY2VsKHJlYXNvbik7CiAgfQp9CgovKioqLyB9KQovKioqKioqLyAJXSk7Ci8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCi8qKioqKiovIAkvLyBUaGUgbW9kdWxlIGNhY2hlCi8qKioqKiovIAl2YXIgX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fID0ge307Ci8qKioqKiovIAkKLyoqKioqKi8gCS8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uCi8qKioqKiovIAlmdW5jdGlvbiBfX3dfcGRmanNfcmVxdWlyZV9fKG1vZHVsZUlkKSB7Ci8qKioqKiovIAkJLy8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlCi8qKioqKiovIAkJdmFyIGNhY2hlZE1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF07Ci8qKioqKiovIAkJaWYgKGNhY2hlZE1vZHVsZSAhPT0gdW5kZWZpbmVkKSB7Ci8qKioqKiovIAkJCXJldHVybiBjYWNoZWRNb2R1bGUuZXhwb3J0czsKLyoqKioqKi8gCQl9Ci8qKioqKiovIAkJLy8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSkKLyoqKioqKi8gCQl2YXIgbW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXSA9IHsKLyoqKioqKi8gCQkJLy8gbm8gbW9kdWxlLmlkIG5lZWRlZAovKioqKioqLyAJCQkvLyBubyBtb2R1bGUubG9hZGVkIG5lZWRlZAovKioqKioqLyAJCQlleHBvcnRzOiB7fQovKioqKioqLyAJCX07Ci8qKioqKiovIAkKLyoqKioqKi8gCQkvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb24KLyoqKioqKi8gCQlfX3dlYnBhY2tfbW9kdWxlc19fW21vZHVsZUlkXShtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dfcGRmanNfcmVxdWlyZV9fKTsKLyoqKioqKi8gCQovKioqKioqLyAJCS8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlCi8qKioqKiovIAkJcmV0dXJuIG1vZHVsZS5leHBvcnRzOwovKioqKioqLyAJfQovKioqKioqLyAJCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCi8qKioqKiovIAkvKiB3ZWJwYWNrL3J1bnRpbWUvZGVmaW5lIHByb3BlcnR5IGdldHRlcnMgKi8KLyoqKioqKi8gCSgoKSA9PiB7Ci8qKioqKiovIAkJLy8gZGVmaW5lIGdldHRlciBmdW5jdGlvbnMgZm9yIGhhcm1vbnkgZXhwb3J0cwovKioqKioqLyAJCV9fd19wZGZqc19yZXF1aXJlX18uZCA9IChleHBvcnRzLCBkZWZpbml0aW9uKSA9PiB7Ci8qKioqKiovIAkJCWZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHsKLyoqKioqKi8gCQkJCWlmKF9fd19wZGZqc19yZXF1aXJlX18ubyhkZWZpbml0aW9uLCBrZXkpICYmICFfX3dfcGRmanNfcmVxdWlyZV9fLm8oZXhwb3J0cywga2V5KSkgewovKioqKioqLyAJCQkJCU9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7Ci8qKioqKiovIAkJCQl9Ci8qKioqKiovIAkJCX0KLyoqKioqKi8gCQl9OwovKioqKioqLyAJfSkoKTsKLyoqKioqKi8gCQovKioqKioqLyAJLyogd2VicGFjay9ydW50aW1lL2hhc093blByb3BlcnR5IHNob3J0aGFuZCAqLwovKioqKioqLyAJKCgpID0+IHsKLyoqKioqKi8gCQlfX3dfcGRmanNfcmVxdWlyZV9fLm8gPSAob2JqLCBwcm9wKSA9PiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCkpCi8qKioqKiovIAl9KSgpOwovKioqKioqLyAJCi8qKioqKiovIAkvKiB3ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0ICovCi8qKioqKiovIAkoKCkgPT4gewovKioqKioqLyAJCS8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHMKLyoqKioqKi8gCQlfX3dfcGRmanNfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4gewovKioqKioqLyAJCQlpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHsKLyoqKioqKi8gCQkJCU9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBTeW1ib2wudG9TdHJpbmdUYWcsIHsgdmFsdWU6ICdNb2R1bGUnIH0pOwovKioqKioqLyAJCQl9Ci8qKioqKiovIAkJCU9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7Ci8qKioqKiovIAkJfTsKLyoqKioqKi8gCX0pKCk7Ci8qKioqKiovIAkKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KdmFyIF9fd2VicGFja19leHBvcnRzX18gPSB7fTsKLy8gVGhpcyBlbnRyeSBuZWVkIHRvIGJlIHdyYXBwZWQgaW4gYW4gSUlGRSBiZWNhdXNlIGl0IG5lZWQgdG8gYmUgaW4gc3RyaWN0IG1vZGUuCigoKSA9PiB7CiJ1c2Ugc3RyaWN0IjsKdmFyIGV4cG9ydHMgPSBfX3dlYnBhY2tfZXhwb3J0c19fOwoKCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAiX19lc01vZHVsZSIsICh7CiAgdmFsdWU6IHRydWUKfSkpOwpPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgIldvcmtlck1lc3NhZ2VIYW5kbGVyIiwgKHsKICBlbnVtZXJhYmxlOiB0cnVlLAogIGdldDogZnVuY3Rpb24gKCkgewogICAgcmV0dXJuIF93b3JrZXIuV29ya2VyTWVzc2FnZUhhbmRsZXI7CiAgfQp9KSk7CnZhciBfd29ya2VyID0gX193X3BkZmpzX3JlcXVpcmVfXygxKTsKY29uc3QgcGRmanNWZXJzaW9uID0gJzMuNS4xMjInOwpjb25zdCBwZGZqc0J1aWxkID0gJzYyMjQ2NWRjMic7Cn0pKCk7CgovKioqKioqLyAJcmV0dXJuIF9fd2VicGFja19leHBvcnRzX187Ci8qKioqKiovIH0pKCkKOwp9KTsKLy8jIHNvdXJjZU1hcHBpbmdVUkw9cGRmLndvcmtlci5qcy5tYXA=",H=`data:text/javascript;base64,${o}`,K=`data:text/javascript;base64,${h}`;class J{constructor(I,g){C(this,"pdfDoc"),C(this,"pageNumber"),C(this,"total"),C(this,"dom"),C(this,"pdf"),C(this,"onError"),C(this,"onLoad"),C(this,"getPdfPage",G=>new Promise((b,Y)=>{this.pdfDoc?this.pdfDoc.getPage(G).then(W=>{const l=W.getViewport(),d=document.createElement("canvas");this.dom.appendChild(d);const w=d.getContext("2d"),B=document.body.clientWidth-20,[a,M,m,i]=l.viewBox,V=m>B?B/m:1;d.width=m,d.height=i,l.width=m,l.height=i,d.style.width=Math.floor(l.width)*V+"px",d.style.height=Math.floor(l.height)*V+"px";const R={canvasContext:w,viewport:l,transform:[1,0,0,-1,0,l.height]};W.render(R),b({success:!0,data:W})}):Y({success:!1,data:null,message:"pdfDoc is undefined"})})),C(this,"pdfPreview",()=>{N(H).then(()=>{window.pdfjsLib.GlobalWorkerOptions.workerSrc=K,window.pdfjsLib.getDocument(this.pdf).promise.then(async G=>{this.pdfDoc=G,this.total=G.numPages,this.onLoad&&this.onLoad({success:!0,data:this.pdfDoc});for(let b=1;b<=this.total;b++)await this.getPdfPage(b)})}).catch(G=>{this.onError&&this.onError({success:!1,data:G,message:G})})}),C(this,"prevPage",()=>{this.pageNumber>1?this.pageNumber-=1:this.pageNumber=1,this.getPdfPage(this.pageNumber)}),C(this,"nextPage",()=>{this.pageNumbernew Promise((I,g)=>{const Z=new FileReader;Z.readAsDataURL(A),Z.onload=()=>{I(Z.result)},Z.onerror=c=>{g(c)},Z.onabort=c=>{g(c)}}),u=async(A,I)=>{try{if(typeof window<"u"){const g=await F(A);g&&new J(g,I).pdfPreview()}}catch{}};export{u as renderPdf}; diff --git a/assets/chunks/power-off-lQRbiBak.r13EH4bb.js b/assets/chunks/power-off-lQRbiBak.r13EH4bb.js new file mode 100644 index 0000000000..004f5612e2 --- /dev/null +++ b/assets/chunks/power-off-lQRbiBak.r13EH4bb.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/preview-CJbz9GjO.C8N16-9H.js b/assets/chunks/preview-CJbz9GjO.C8N16-9H.js new file mode 100644 index 0000000000..c0873285fd --- /dev/null +++ b/assets/chunks/preview-CJbz9GjO.C8N16-9H.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/pwa-install.es.Bwp47-dV.js b/assets/chunks/pwa-install.es.Bwp47-dV.js new file mode 100644 index 0000000000..f19dbc107f --- /dev/null +++ b/assets/chunks/pwa-install.es.Bwp47-dV.js @@ -0,0 +1,39 @@ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const F=globalThis,je=F.ShadowRoot&&(F.ShadyCSS===void 0||F.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,Ce=Symbol(),Le=new WeakMap;let Qe=class{constructor(e,t,i){if(this._$cssResult$=!0,i!==Ce)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=e,this.t=t}get styleSheet(){let e=this.o;const t=this.t;if(je&&e===void 0){const i=t!==void 0&&t.length===1;i&&(e=Le.get(t)),e===void 0&&((this.o=e=new CSSStyleSheet).replaceSync(this.cssText),i&&Le.set(t,e))}return e}toString(){return this.cssText}};const ht=a=>new Qe(typeof a=="string"?a:a+"",void 0,Ce),gt=(a,...e)=>{const t=a.length===1?a[0]:e.reduce((i,o,s)=>i+(l=>{if(l._$cssResult$===!0)return l.cssText;if(typeof l=="number")return l;throw Error("Value passed to 'css' function must be a 'css' function result: "+l+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(o)+a[s+1],a[0]);return new Qe(t,a,Ce)},bt=(a,e)=>{if(je)a.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const t of e){const i=document.createElement("style"),o=F.litNonce;o!==void 0&&i.setAttribute("nonce",o),i.textContent=t.cssText,a.appendChild(i)}},Ie=je?a=>a:a=>a instanceof CSSStyleSheet?(e=>{let t="";for(const i of e.cssRules)t+=i.cssText;return ht(t)})(a):a;/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const{is:mt,defineProperty:ut,getOwnPropertyDescriptor:ft,getOwnPropertyNames:vt,getOwnPropertySymbols:wt,getPrototypeOf:yt}=Object,E=globalThis,Ue=E.trustedTypes,xt=Ue?Ue.emptyScript:"",ee=E.reactiveElementPolyfillSupport,O=(a,e)=>a,G={toAttribute(a,e){switch(e){case Boolean:a=a?xt:null;break;case Object:case Array:a=a==null?a:JSON.stringify(a)}return a},fromAttribute(a,e){let t=a;switch(e){case Boolean:t=a!==null;break;case Number:t=a===null?null:Number(a);break;case Object:case Array:try{t=JSON.parse(a)}catch{t=null}}return t}},Te=(a,e)=>!mt(a,e),He={attribute:!0,type:String,converter:G,reflect:!1,hasChanged:Te};Symbol.metadata??(Symbol.metadata=Symbol("metadata")),E.litPropertyMetadata??(E.litPropertyMetadata=new WeakMap);let R=class extends HTMLElement{static addInitializer(e){this._$Ei(),(this.l??(this.l=[])).push(e)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(e,t=He){if(t.state&&(t.attribute=!1),this._$Ei(),this.elementProperties.set(e,t),!t.noAccessor){const i=Symbol(),o=this.getPropertyDescriptor(e,i,t);o!==void 0&&ut(this.prototype,e,o)}}static getPropertyDescriptor(e,t,i){const{get:o,set:s}=ft(this.prototype,e)??{get(){return this[t]},set(l){this[t]=l}};return{get(){return o==null?void 0:o.call(this)},set(l){const n=o==null?void 0:o.call(this);s.call(this,l),this.requestUpdate(e,n,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(e){return this.elementProperties.get(e)??He}static _$Ei(){if(this.hasOwnProperty(O("elementProperties")))return;const e=yt(this);e.finalize(),e.l!==void 0&&(this.l=[...e.l]),this.elementProperties=new Map(e.elementProperties)}static finalize(){if(this.hasOwnProperty(O("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(O("properties"))){const t=this.properties,i=[...vt(t),...wt(t)];for(const o of i)this.createProperty(o,t[o])}const e=this[Symbol.metadata];if(e!==null){const t=litPropertyMetadata.get(e);if(t!==void 0)for(const[i,o]of t)this.elementProperties.set(i,o)}this._$Eh=new Map;for(const[t,i]of this.elementProperties){const o=this._$Eu(t,i);o!==void 0&&this._$Eh.set(o,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(e){const t=[];if(Array.isArray(e)){const i=new Set(e.flat(1/0).reverse());for(const o of i)t.unshift(Ie(o))}else e!==void 0&&t.push(Ie(e));return t}static _$Eu(e,t){const i=t.attribute;return i===!1?void 0:typeof i=="string"?i:typeof e=="string"?e.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){var e;this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),(e=this.constructor.l)==null||e.forEach(t=>t(this))}addController(e){var t;(this._$EO??(this._$EO=new Set)).add(e),this.renderRoot!==void 0&&this.isConnected&&((t=e.hostConnected)==null||t.call(e))}removeController(e){var t;(t=this._$EO)==null||t.delete(e)}_$E_(){const e=new Map,t=this.constructor.elementProperties;for(const i of t.keys())this.hasOwnProperty(i)&&(e.set(i,this[i]),delete this[i]);e.size>0&&(this._$Ep=e)}createRenderRoot(){const e=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return bt(e,this.constructor.elementStyles),e}connectedCallback(){var e;this.renderRoot??(this.renderRoot=this.createRenderRoot()),this.enableUpdating(!0),(e=this._$EO)==null||e.forEach(t=>{var i;return(i=t.hostConnected)==null?void 0:i.call(t)})}enableUpdating(e){}disconnectedCallback(){var e;(e=this._$EO)==null||e.forEach(t=>{var i;return(i=t.hostDisconnected)==null?void 0:i.call(t)})}attributeChangedCallback(e,t,i){this._$AK(e,i)}_$EC(e,t){var s;const i=this.constructor.elementProperties.get(e),o=this.constructor._$Eu(e,i);if(o!==void 0&&i.reflect===!0){const l=(((s=i.converter)==null?void 0:s.toAttribute)!==void 0?i.converter:G).toAttribute(t,i.type);this._$Em=e,l==null?this.removeAttribute(o):this.setAttribute(o,l),this._$Em=null}}_$AK(e,t){var s;const i=this.constructor,o=i._$Eh.get(e);if(o!==void 0&&this._$Em!==o){const l=i.getPropertyOptions(o),n=typeof l.converter=="function"?{fromAttribute:l.converter}:((s=l.converter)==null?void 0:s.fromAttribute)!==void 0?l.converter:G;this._$Em=o,this[o]=n.fromAttribute(t,l.type),this._$Em=null}}requestUpdate(e,t,i){if(e!==void 0){if(i??(i=this.constructor.getPropertyOptions(e)),!(i.hasChanged??Te)(this[e],t))return;this.P(e,t,i)}this.isUpdatePending===!1&&(this._$ES=this._$ET())}P(e,t,i){this._$AL.has(e)||this._$AL.set(e,t),i.reflect===!0&&this._$Em!==e&&(this._$Ej??(this._$Ej=new Set)).add(e)}async _$ET(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const e=this.scheduleUpdate();return e!=null&&await e,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){var i;if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??(this.renderRoot=this.createRenderRoot()),this._$Ep){for(const[s,l]of this._$Ep)this[s]=l;this._$Ep=void 0}const o=this.constructor.elementProperties;if(o.size>0)for(const[s,l]of o)l.wrapped!==!0||this._$AL.has(s)||this[s]===void 0||this.P(s,this[s],l)}let e=!1;const t=this._$AL;try{e=this.shouldUpdate(t),e?(this.willUpdate(t),(i=this._$EO)==null||i.forEach(o=>{var s;return(s=o.hostUpdate)==null?void 0:s.call(o)}),this.update(t)):this._$EU()}catch(o){throw e=!1,this._$EU(),o}e&&this._$AE(t)}willUpdate(e){}_$AE(e){var t;(t=this._$EO)==null||t.forEach(i=>{var o;return(o=i.hostUpdated)==null?void 0:o.call(i)}),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(e)),this.updated(e)}_$EU(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(e){return!0}update(e){this._$Ej&&(this._$Ej=this._$Ej.forEach(t=>this._$EC(t,this[t]))),this._$EU()}updated(e){}firstUpdated(e){}};R.elementStyles=[],R.shadowRootOptions={mode:"open"},R[O("elementProperties")]=new Map,R[O("finalized")]=new Map,ee==null||ee({ReactiveElement:R}),(E.reactiveElementVersions??(E.reactiveElementVersions=[])).push("2.0.4");/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const B=globalThis,K=B.trustedTypes,Oe=K?K.createPolicy("lit-html",{createHTML:a=>a}):void 0,Xe="$lit$",A=`lit$${Math.random().toFixed(9).slice(2)}$`,et="?"+A,kt=`<${et}>`,j=document,q=()=>j.createComment(""),W=a=>a===null||typeof a!="object"&&typeof a!="function",Re=Array.isArray,$t=a=>Re(a)||typeof(a==null?void 0:a[Symbol.iterator])=="function",te=`[ +\f\r]`,L=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Be=/-->/g,Ne=/>/g,S=RegExp(`>|${te}(?:([^\\s"'>=/]+)(${te}*=${te}*(?:[^ +\f\r"'\`<>=]|("|')|))|$)`,"g"),qe=/'/g,We=/"/g,tt=/^(?:script|style|textarea|title)$/i,_t=a=>(e,...t)=>({_$litType$:a,strings:e,values:t}),At=_t(1),C=Symbol.for("lit-noChange"),u=Symbol.for("lit-nothing"),Ze=new WeakMap,z=j.createTreeWalker(j,129);function at(a,e){if(!Re(a)||!a.hasOwnProperty("raw"))throw Error("invalid template strings array");return Oe!==void 0?Oe.createHTML(e):e}const Et=(a,e)=>{const t=a.length-1,i=[];let o,s=e===2?"":e===3?"":"",l=L;for(let n=0;n"?(l=o??L,d=-1):p[1]===void 0?d=-2:(d=l.lastIndex-p[2].length,g=p[1],l=p[3]===void 0?S:p[3]==='"'?We:qe):l===We||l===qe?l=S:l===Be||l===Ne?l=L:(l=S,o=void 0);const x=l===S&&a[n+1].startsWith("/>")?" ":"";s+=l===L?r+kt:d>=0?(i.push(g),r.slice(0,d)+Xe+r.slice(d)+A+x):r+A+(d===-2?n:x)}return[at(a,s+(a[t]||"")+(e===2?"":e===3?"":"")),i]};let ne=class it{constructor({strings:e,_$litType$:t},i){let o;this.parts=[];let s=0,l=0;const n=e.length-1,r=this.parts,[g,p]=Et(e,t);if(this.el=it.createElement(g,i),z.currentNode=this.el.content,t===2||t===3){const d=this.el.content.firstChild;d.replaceWith(...d.childNodes)}for(;(o=z.nextNode())!==null&&r.length0){o.textContent=K?K.emptyScript:"";for(let x=0;x2||i[0]!==""||i[1]!==""?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=u}_$AI(e,t=this,i,o){const s=this.strings;let l=!1;if(s===void 0)e=M(this,e,t,0),l=!W(e)||e!==this._$AH&&e!==C,l&&(this._$AH=e);else{const n=e;let r,g;for(e=s[0],r=0;r{const i=(t==null?void 0:t.renderBefore)??e;let o=i._$litPart$;if(o===void 0){const s=(t==null?void 0:t.renderBefore)??null;i._$litPart$=o=new Z(e.insertBefore(q(),s),s,void 0,t??{})}return o._$AI(a),o};/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */let N=class extends R{constructor(){super(...arguments),this.renderOptions={host:this},this.o=void 0}createRenderRoot(){var t;const e=super.createRenderRoot();return(t=this.renderOptions).renderBefore??(t.renderBefore=e.firstChild),e}update(e){const t=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(e),this.o=Ct(t,this.renderRoot,this.renderOptions)}connectedCallback(){var e;super.connectedCallback(),(e=this.o)==null||e.setConnected(!0)}disconnectedCallback(){var e;super.disconnectedCallback(),(e=this.o)==null||e.setConnected(!1)}render(){return C}};var Je;N._$litElement$=!0,N.finalized=!0,(Je=globalThis.litElementHydrateSupport)==null||Je.call(globalThis,{LitElement:N});const ie=globalThis.litElementPolyfillSupport;ie==null||ie({LitElement:N});(globalThis.litElementVersions??(globalThis.litElementVersions=[])).push("4.1.0");/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const Tt=a=>(e,t)=>{t!==void 0?t.addInitializer(()=>{customElements.define(a,e)}):customElements.define(a,e)};/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const Rt={attribute:!0,type:String,converter:G,reflect:!1,hasChanged:Te},Mt=(a=Rt,e,t)=>{const{kind:i,metadata:o}=t;let s=globalThis.litPropertyMetadata.get(o);if(s===void 0&&globalThis.litPropertyMetadata.set(o,s=new Map),s.set(t.name,a),i==="accessor"){const{name:l}=t;return{set(n){const r=e.get.call(this);e.set.call(this,n),this.requestUpdate(l,r,a)},init(n){return n!==void 0&&this.P(l,void 0,a),n}}}if(i==="setter"){const{name:l}=t;return function(n){const r=this[l];e.call(this,n),this.requestUpdate(l,r,a)}}throw Error("Unsupported decorator location: "+i)};function ot(a){return(e,t)=>typeof t=="object"?Mt(a,e,t):((i,o,s)=>{const l=o.hasOwnProperty(s);return o.constructor.createProperty(s,l?{...i,wrapped:!0}:i),l?Object.getOwnPropertyDescriptor(o,s):void 0})(a,e,t)}/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */function Lt(a){return ot({...a,state:!0,attribute:!1})}/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const It={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},Ut=a=>(...e)=>({_$litDirective$:a,values:e});let Ht=class{constructor(e){}get _$AU(){return this._$AM._$AU}_$AT(e,t,i){this.t=e,this._$AM=t,this.i=i}_$AS(e,t){return this.update(e,t)}update(e,t){return this.render(...t)}};/** + * @license + * Copyright 2018 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */const Ot=Ut(class extends Ht{constructor(a){var e;if(super(a),a.type!==It.ATTRIBUTE||a.name!=="class"||((e=a.strings)==null?void 0:e.length)>2)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(a){return" "+Object.keys(a).filter(e=>a[e]).join(" ")+" "}update(a,[e]){var i,o;if(this.st===void 0){this.st=new Set,a.strings!==void 0&&(this.nt=new Set(a.strings.join(" ").split(/\s/).filter(s=>s!=="")));for(const s in e)e[s]&&!((i=this.nt)!=null&&i.has(s))&&this.st.add(s);return this.render(e)}const t=a.element.classList;for(const s of this.st)s in e||(t.remove(s),this.st.delete(s));for(const s in e){const l=!!e[s];l===this.st.has(s)||(o=this.nt)!=null&&o.has(s)||(l?(t.add(s),this.st.add(s)):(t.remove(s),this.st.delete(s)))}return C}});var c={d:(a,e)=>{for(var t in e)c.o(e,t)&&!c.o(a,t)&&Object.defineProperty(a,t,{enumerable:!0,get:e[t]})},o:(a,e)=>Object.prototype.hasOwnProperty.call(a,e),r:a=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(a,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(a,"__esModule",{value:!0})}},st={};c.d(st,{w:()=>f});var re={};c.r(re),c.d(re,{templates:()=>Jt});var de={};c.r(de),c.d(de,{templates:()=>Qt});var ce={};c.r(ce),c.d(ce,{templates:()=>Xt});var pe={};c.r(pe),c.d(pe,{templates:()=>ea});var he={};c.r(he),c.d(he,{templates:()=>ta});var ge={};c.r(ge),c.d(ge,{templates:()=>aa});var be={};c.r(be),c.d(be,{templates:()=>ia});var me={};c.r(me),c.d(me,{templates:()=>oa});var ue={};c.r(ue),c.d(ue,{templates:()=>sa});var fe={};c.r(fe),c.d(fe,{templates:()=>la});var ve={};c.r(ve),c.d(ve,{templates:()=>na});var we={};c.r(we),c.d(we,{templates:()=>ra});var ye={};c.r(ye),c.d(ye,{templates:()=>da});var xe={};c.r(xe),c.d(xe,{templates:()=>ca});var ke={};c.r(ke),c.d(ke,{templates:()=>pa});var $e={};c.r($e),c.d($e,{templates:()=>ha});var _e={};c.r(_e),c.d(_e,{templates:()=>ga});var Ae={};c.r(Ae),c.d(Ae,{templates:()=>ba});var Ee={};c.r(Ee),c.d(Ee,{templates:()=>ma});var Se={};c.r(Se),c.d(Se,{templates:()=>ua});const h=(a=>{var e={};return c.d(e,a),e})({LitElement:()=>N,css:()=>gt,html:()=>At}),lt=(a,e,t)=>{let i=a[0];for(let o=1;o{return typeof(e=a)!="string"&&"strTag"in e?lt(a.strings,a.values):a;var e};let k=nt,Ye=!1;const De="lit-localize-status";class Bt{constructor(e){this.__litLocalizeEventHandler=t=>{t.detail.status==="ready"&&this.host.requestUpdate()},this.host=e}hostConnected(){window.addEventListener(De,this.__litLocalizeEventHandler)}hostDisconnected(){window.removeEventListener(De,this.__litLocalizeEventHandler)}}const Nt=a=>a.addController(new Bt(a));class rt{constructor(){this.settled=!1,this.promise=new Promise((e,t)=>{this._resolve=e,this._reject=t})}resolve(e){this.settled=!0,this._resolve(e)}reject(e){this.settled=!0,this._reject(e)}}const _=[];for(let a=0;a<256;a++)_[a]=(a>>4&15).toString(16)+(15&a).toString(16);const qt="",Wt="h",Zt="s";function Yt(a,e){return(e?Wt:Zt)+function(t){let i=0,o=8997,s=0,l=33826,n=0,r=40164,g=0,p=52210;for(let d=0;d>>16,o=65535&i,n+=s>>>16,l=65535&s,p=g+(n>>>16)&65535,r=65535&n;return _[p>>8]+_[255&p]+_[r>>8]+_[255&r]+_[l>>8]+_[255&l]+_[o>>8]+_[255&o]}(typeof a=="string"?a:a.join(qt))}const Ve=new WeakMap,Fe=new Map;function Vt(a,e,t){if(a){const i=(t==null?void 0:t.id)??function(s){const l=typeof s=="string"?s:s.strings;let n=Fe.get(l);return n===void 0&&(n=Yt(l,typeof s!="string"&&!("strTag"in s)),Fe.set(l,n)),n}(e),o=a[i];if(o){if(typeof o=="string")return o;if("strTag"in o)return lt(o.strings,e.values,o.values);{let s=Ve.get(o);return s===void 0&&(s=o.values,Ve.set(o,s)),{...o,values:s.map(l=>e.values[l])}}}}return nt(e)}function oe(a){window.dispatchEvent(new CustomEvent(De,{detail:a}))}let se,dt,J,Pe,ct,Q="",D=new rt;D.resolve();let Y=0;const Ft=()=>Q,Gt=a=>{if(a===(se??Q))return D.promise;if(!J||!Pe)throw Error("Internal error");if(!J.has(a))throw Error("Invalid locale code");Y++;const e=Y;return se=a,D.settled&&(D=new rt),oe({status:"loading",loadingLocale:a}),(a===dt?Promise.resolve({templates:void 0}):Pe(a)).then(t=>{Y===e&&(Q=a,se=void 0,ct=t.templates,oe({status:"ready",readyLocale:a}),D.resolve())},t=>{Y===e&&(oe({status:"error",errorLocale:a,errorMessage:t.toString()}),D.reject(t))}),D.promise},b=(a=>{var e={};return c.d(e,a),e})({customElement:()=>Tt,property:()=>ot,state:()=>Lt}),Kt=["cs","de","el","es","fr","it","ja","km","ko","nl","no","pl","pt","ru","sr","sv","tr","uk","zh","zh-CN"],Jt={s182ab2d6c997515f:"Добавьте его на главный экран, чтобы получить дополнительные возможности и удобство использования.",s1b9047d53d9f9d22:'2) Нажать "Поделиться"',s37a9e8aec5713460:"Подробнее",s5c6aad7a7e4a1437:'3) Нажать "На экран «Домой»"',s6196153c4b0c1ea0:"Установить",s922329d6f6213590:"Добавить в Dock",sa5ef80b4bb9b39f8:"Свернуть",sa7551383d1897fcc:'2) Нажмите "Добавить в Dock"',sba52286c21552a4e:"Установите это на ваше устройство, чтобы получить дополнительные возможности и удобство использования.",sc79fd7641eb9a975:"Спрятать Инструкцию",scdaf4bbff76674c8:"На экран «Домой»",sdfe23506a3b0cdc8:"1) Открыть в Safari браузере",se740f75b95a51807:"Добавьте его в Dock, чтобы получить дополнительные возможности и удобство использования.",sfea652f6580ff086:"Этот веб-сайт имеет функционал приложения."},Qt={s182ab2d6c997515f:"Daha iyi bir deneyim ve kolay erişim için Ana Ekranınıza ekleyin.",s1b9047d53d9f9d22:"2) Gezinme çubuğunda Paylaş'a basın",s37a9e8aec5713460:"Daha Fazla",s5c6aad7a7e4a1437:"3) Ana Ekrana Ekle'ye basın",s6196153c4b0c1ea0:"Yükle",s922329d6f6213590:"Dock’a Ekle",sa5ef80b4bb9b39f8:"Küçült",sa7551383d1897fcc:"2) Dock’a ekleye basın",sba52286c21552a4e:"Daha iyi bir deneyim ve kolay erişim için cihazınıza yükleyin.",sc79fd7641eb9a975:"Talimatları gizle",scdaf4bbff76674c8:"Ana Ekrana Ekle",sdfe23506a3b0cdc8:"1) Safari tarayıcısında açın",se740f75b95a51807:"Daha iyi bir deneyim ve kolay erişim için Dock’a ekleyin.",sfea652f6580ff086:"Bu site uygulama işlevselliğine sahiptir."},Xt={s182ab2d6c997515f:"Fügen Sie es zu Ihrem Startbildschirm hinzu, um eine umfassende Erfahrung und einen leichten Zugriff zu erhalten.",s1b9047d53d9f9d22:"2) Drücken Sie auf Teilen in der Navigationsleiste",s37a9e8aec5713460:"Mehr",s5c6aad7a7e4a1437:"3) Drücken Sie Hinzufügen zum Startbildschirm",s6196153c4b0c1ea0:"Installieren",s922329d6f6213590:"Zum Dock hinzufügen",sa5ef80b4bb9b39f8:"Weniger",sa7551383d1897fcc:"2) Drücken Sie auf Zum Dock hinzufügen",sba52286c21552a4e:"Installieren Sie es auf Ihrem Gerät für eine umfassende Erfahrung und einen leichten Zugriff.",sc79fd7641eb9a975:"Anleitung ausblenden",scdaf4bbff76674c8:"Hinzufügen zum Startbildschirm",sdfe23506a3b0cdc8:"1) In Safari-Browser öffnen",se740f75b95a51807:"Fügen Sie es zu Ihrem Dock hinzu, um eine umfassende Erfahrung und einen leichten Zugriff zu erhalten.",sfea652f6580ff086:"Diese Website verfügt über App-Funktionalität."},ea={s182ab2d6c997515f:"Añádelo a tu pantalla de inicio para una experiencia amplia y acceso fácil.",s1b9047d53d9f9d22:"2) Presionar Compartir en la barra de direcciones",s37a9e8aec5713460:"Más",s5c6aad7a7e4a1437:"3) Presionar Añadir a pantalla de inicio",s6196153c4b0c1ea0:"Instalar",s922329d6f6213590:"Añadir al Dock",sa5ef80b4bb9b39f8:"Menos",sa7551383d1897fcc:"2) Presionar Añadir al Dock",sba52286c21552a4e:"Instálalo en tu dispositivo para una experiencia amplia y acceso fácil.",sc79fd7641eb9a975:"Esconder instrucciones",scdaf4bbff76674c8:"Añadir a pantalla de inicio",sdfe23506a3b0cdc8:"1) Abrir en el navegador web Safari",se740f75b95a51807:"Añádelo a tu Dock para una experiencia amplia y acceso fácil.",sfea652f6580ff086:"Este sitio tiene funcionalidad de aplicación."},ta={s182ab2d6c997515f:"Voeg het toe aan je startscherm voor een uitgebreide ervaring en gemakkelijke toegang.",s1b9047d53d9f9d22:"2) Druk op delen in de navigatiebalk",s37a9e8aec5713460:"Meer",s5c6aad7a7e4a1437:"3) Druk op Toevoegen aan het startscherm",s6196153c4b0c1ea0:"Installeren",s922329d6f6213590:"Toevoegen aan Dock",sa5ef80b4bb9b39f8:"Minder",sa7551383d1897fcc:"2) Druk op Toevoegen aan Dock",sba52286c21552a4e:"Installeer het op je apparaat voor een uitgebreide ervaring en gemakkelijke toegang.",sc79fd7641eb9a975:"Instructie verbergen",scdaf4bbff76674c8:"Toevoegen aan het startscherm",sdfe23506a3b0cdc8:"1) Open in Safari-browser",se740f75b95a51807:"Voeg het toe aan je Dock voor een uitgebreide ervaring en makkelijke toegang.",sfea652f6580ff086:"Deze site heeft app-functionaliteit."},aa={s182ab2d6c997515f:"Προσθέστε το στην οθόνη Αφετηρίας για εκτεταμένη εμπειρία και εύκολη πρόσβαση.",s1b9047d53d9f9d22:"2) Πατήστε Κοινοποίηση στη γραμμή πλοήγησης",s37a9e8aec5713460:"Περισσότερα",s5c6aad7a7e4a1437:"3) Πατήστε Προσθήκη στην οθόνη Αφετηρίας",s6196153c4b0c1ea0:"Εγκατάσταση",s922329d6f6213590:"Προσθήκη στην Πρόσβαση",sa5ef80b4bb9b39f8:"Λιγότερα",sa7551383d1897fcc:"2) Πατήστε Προσθήκη στην Πρόσβαση",sba52286c21552a4e:"Εγκαταστήστε το στη συσκευή σας για εκτεταμένη εμπειρία και εύκολη πρόσβαση.",sc79fd7641eb9a975:"Απόκρυψη Οδηγιών",scdaf4bbff76674c8:"Προσθήκη στην Οθόνη Αφετηρίας",sdfe23506a3b0cdc8:"1) Ανοίξτε τον περιηγητή Safari",se740f75b95a51807:"Προσθέστε το στην Πρόσβαση για εκτεταμένη εμπειρία και εύκολη πρόσβαση.",sfea652f6580ff086:"Αυτός ο ιστότοπος έχει λειτουργική εφαρμογής."},ia={s182ab2d6c997515f:"Ajoutez-le à votre écran d'accueil pour une expérience étendue et un accès facile.",s1b9047d53d9f9d22:"2) Appuyez sur Partager dans la barre de navigation",s37a9e8aec5713460:"Plus",s5c6aad7a7e4a1437:"3) Appuyez sur Ajouter à l'écran d'accueil",s6196153c4b0c1ea0:"Installer",s922329d6f6213590:"Ajouter au Dock",sa5ef80b4bb9b39f8:"Moins",sa7551383d1897fcc:"2) Appuyez sur Ajouter au Dock",sba52286c21552a4e:"Installez-le sur votre appareil pour une expérience complète et un accès facile.",sc79fd7641eb9a975:"Masquer les instructions",scdaf4bbff76674c8:"Ajouter à l'écran d'accueil",sdfe23506a3b0cdc8:"1) Ouvrir dans le navigateur Safari",se740f75b95a51807:"Ajoutez-le à votre Dock pour une expérience étendue et un accès facile.",sfea652f6580ff086:"Ce site possède des fonctionnalités d'application."},oa={s182ab2d6c997515f:"Додајте га на Home Screen за широке могућности и лак приступ.",s1b9047d53d9f9d22:"2) Притисните Share у навигационој траци",s37a9e8aec5713460:"Више",s5c6aad7a7e4a1437:"3) Притисните Add to Home Screen",s6196153c4b0c1ea0:"Инсталирај",sa5ef80b4bb9b39f8:"Мање",sa7551383d1897fcc:"3) Притисните Add to Dock",sba52286c21552a4e:"Инсталирајте га на вашем уређају за широке могућности и лак приступ.",sc79fd7641eb9a975:"Сакриј упутство",sdfe23506a3b0cdc8:"1) Отворите у Safari прегледачу",se740f75b95a51807:"Додајте га у вашу Dock за широке могућности и лак приступ.",sfea652f6580ff086:"Овај сајт има функционалност апликације.",s922329d6f6213590:"Add to Dock",scdaf4bbff76674c8:"Add to Home Screen"},sa={s182ab2d6c997515f:"Dodaj do swojego Ekranu Głównego, aby uzyskać bogate doświadczenie i łatwy dostęp.",s1b9047d53d9f9d22:'2) Wybierz "Udostępnij"',s37a9e8aec5713460:"Więcej",s5c6aad7a7e4a1437:'3) Wybierz "Dodaj do Ekranu Głównego"',s6196153c4b0c1ea0:"Zainstaluj",s922329d6f6213590:"Dodaj do Docka",sa5ef80b4bb9b39f8:"Mniej",sa7551383d1897fcc:'2) Wybierz "Dodaj do Docka"',sba52286c21552a4e:"Zainstaluj na swoim urządzeniu, aby uzyskać bogate doświadczenie i łatwy dostęp.",sc79fd7641eb9a975:"Ukryj instrukcję",scdaf4bbff76674c8:"Dodaj do Ekranu Głównego",sdfe23506a3b0cdc8:"1) Otwórz przeglądarkę Safari",se740f75b95a51807:"Dodaj do swojego Docka, aby uzyskać bogate doświadczenie i łatwy dostęp.",sfea652f6580ff086:"Ta strona posiada funkcje aplikacji."},la={s182ab2d6c997515f:"Додайте на Домашній екран для зручного доступу та ширших можливостей.",s1b9047d53d9f9d22:"2) Натиснути «Поділитися»",s37a9e8aec5713460:"Детальніше",s5c6aad7a7e4a1437:"3) Натиснути «На Початковий екран»",s6196153c4b0c1ea0:"Встановити",s922329d6f6213590:"Додати на Dock",sa5ef80b4bb9b39f8:"Згорнути",sa7551383d1897fcc:"2) Натиснути «Додати на Dock»",sba52286c21552a4e:"Встановіть на ваш пристрій для зручного доступу та ширших можливостей.",sc79fd7641eb9a975:"Сховати Інструкцію",scdaf4bbff76674c8:"На Початковий экран",sdfe23506a3b0cdc8:"1) Відкрити в Safari браузері",se740f75b95a51807:"Додайте на панель Dock для зручного доступу та ширших можливостей.",sfea652f6580ff086:"Цей сайт має функції додатку."},na={s182ab2d6c997515f:"將其加入主屏幕,以獲得更豐富的體驗和便捷訪問。",s1b9047d53d9f9d22:"2) 點擊列表上的分享按鈕",s37a9e8aec5713460:"詳細資訊",s5c6aad7a7e4a1437:"3) 點擊加入主畫面",s6196153c4b0c1ea0:"安裝",s922329d6f6213590:"添加到Dock欄",sa5ef80b4bb9b39f8:"簡短資訊",sa7551383d1897fcc:"2) 點選添加到Dock欄",sba52286c21552a4e:"在您的裝置上安裝它,以獲得更豐富的體驗和便捷訪問。",sc79fd7641eb9a975:"隱藏安裝流程",scdaf4bbff76674c8:"將App加入主畫面",sdfe23506a3b0cdc8:"1) 在Safari上瀏覽此網頁",se740f75b95a51807:"將其加入你的Dock欄,以獲得更豐富的體驗和便捷訪問。",sfea652f6580ff086:"此網站具有應用程式功能。"},ra={s182ab2d6c997515f:"将其添加到主屏幕,以享受更全面的体验并便于访问。",s1b9047d53d9f9d22:"2) 点击列表上的分享按钮",s37a9e8aec5713460:"详细资讯",s5c6aad7a7e4a1437:"3) 点击添加到主屏幕",s6196153c4b0c1ea0:"安装",s922329d6f6213590:"添加到Dock",sa5ef80b4bb9b39f8:"简短资讯",sa7551383d1897fcc:"2) 按下添加到Dock",sba52286c21552a4e:"在您的设备上安装,以享有更全面的体验和便捷的访问。",sc79fd7641eb9a975:"隐藏安装流程",scdaf4bbff76674c8:"将App添加到主屏幕",sdfe23506a3b0cdc8:"1) 在Safari上浏览此网页",se740f75b95a51807:"将其添加到您的Dock,以享受更全面的体验并便于访问。",sfea652f6580ff086:"此网站具备app的功能性。"},da={s182ab2d6c997515f:"Aggiungilo alla schermata principale per un'esperienza più completa e un accesso facile.",s1b9047d53d9f9d22:"2) Premi Condividi nella barra di navigazione",s37a9e8aec5713460:"Più",s5c6aad7a7e4a1437:"3) Premi Aggiungi alla schermata principale",s6196153c4b0c1ea0:"Installa",s922329d6f6213590:"Aggiungi al Dock",sa5ef80b4bb9b39f8:"Meno",sa7551383d1897fcc:"2) Premi Aggiungi al Dock",sba52286c21552a4e:"Installalo sul tuo dispositivo per un'esperienza più completa e un accesso facile.",sc79fd7641eb9a975:"Nascondi istruzioni",scdaf4bbff76674c8:"Aggiungi alla schermata principale",sdfe23506a3b0cdc8:"1) Apri nel browser Safari",se740f75b95a51807:"Aggiungilo al Dock per un'esperienza più completa e un accesso facile.",sfea652f6580ff086:"Questo sito ha funzionalità di app."},ca={s182ab2d6c997515f:"Přidejte jej na plochu pro rozšířené využití a snadný přístup.",s1b9047d53d9f9d22:"2) Stiskněte tlačítko Sdílet na navigačním panelu",s37a9e8aec5713460:"Vice",s5c6aad7a7e4a1437:"3) Stiskněte tlačítko Přidat na plochu",s6196153c4b0c1ea0:"Nainstalovat",s922329d6f6213590:"Přidat do Docku",sa5ef80b4bb9b39f8:"Méně",sa7551383d1897fcc:"2) Stiskněte Přidat do Docku",sba52286c21552a4e:"Nainstalujte si jej na své zařízení pro rozšířené využití a snadný přístup.",sc79fd7641eb9a975:"Skrýt instrukce",scdaf4bbff76674c8:"Přidat na plochu",sdfe23506a3b0cdc8:"1) Otevřete v prohlížeči Safari",se740f75b95a51807:"Přidejte jej do svého Docku pro rozšířené využití a snadný přístup.",sfea652f6580ff086:"Tento web má funkce aplikace."},pa={s182ab2d6c997515f:"Legg den til på Hjem-skjermen din for å få en bedre brukeropplevelse og raskere tilgang.",s1b9047d53d9f9d22:"2) Trykk på Del-knappen i navigasjonslinjen",s37a9e8aec5713460:"Mer",s5c6aad7a7e4a1437:"3) Velg Legg til på Hjem-skjerm",s6196153c4b0c1ea0:"Installer",s922329d6f6213590:"Legg til i Dock",sa5ef80b4bb9b39f8:"Mindre",sa7551383d1897fcc:"2) Velg Legg til i Dock",sba52286c21552a4e:"Installer den på enheten din for å få en bedre brukeropplevelse og raskere tilgang.",sc79fd7641eb9a975:"Skjul instruksjoner",scdaf4bbff76674c8:"Legg til på Hjem-skjerm",sdfe23506a3b0cdc8:"1) Åpne i Safari",se740f75b95a51807:"Legg den til i Docken din for å få en bedre brukeropplevelse og raskere tilgang.",sfea652f6580ff086:"Denne siden har app-funksjonalitet."},ha={s182ab2d6c997515f:"Adicione à Tela de Início para uma melhor experiência e mais fácil acesso.",s1b9047d53d9f9d22:"2) Pressione Compartilhar na barra de endereço",s37a9e8aec5713460:"Mais",s5c6aad7a7e4a1437:"3) Pressione Adicionar à Tela de Início",s6196153c4b0c1ea0:"Instalar",s922329d6f6213590:"Adicionar ao Dock",sa5ef80b4bb9b39f8:"Menos",sa7551383d1897fcc:"2) Pressione Adicionar ao Dock",sba52286c21552a4e:"Instale no dispositivo para uma melhor experiência e mais fácil acesso.",sc79fd7641eb9a975:"Ocultar Instruções",scdaf4bbff76674c8:"Adicionar à Tela de Início",sdfe23506a3b0cdc8:"1) Abra no navegador Safari",se740f75b95a51807:"Adicione ao Dock para uma melhor experiência e mais fácil acesso.",sfea652f6580ff086:"Este site possui funcionalidade de aplicativo."},ga={s182ab2d6c997515f:"ホーム画面に追加して、幅広い体験と簡単なアクセスを実現してください。",s1b9047d53d9f9d22:"2) ナビゲーションバーで共有を押す",s37a9e8aec5713460:"展開",s5c6aad7a7e4a1437:"3) 「ホーム画面に追加」を押す",s6196153c4b0c1ea0:"インストール",s922329d6f6213590:"Dockに追加",sa5ef80b4bb9b39f8:"折りたたむ",sa7551383d1897fcc:"2) 「Dockに追加」を押す",sba52286c21552a4e:"デバイスにインストールすることで、より充実した体験と簡単なアクセスを実現できます。",sc79fd7641eb9a975:"説明を非表示",scdaf4bbff76674c8:"ホーム画面に追加",sdfe23506a3b0cdc8:"1) Safariで開く",se740f75b95a51807:"ドックに追加して、幅広い体験と簡単なアクセスを実現してください。",sfea652f6580ff086:"このサイトはアプリ機能があります。"},ba={s182ab2d6c997515f:"Lägg till på hemskärmen för att få en bättre användarupplevelse och enklare åtkomst.",s1b9047d53d9f9d22:"2) Tryck på Dela-knappen i verktygsfältet",s37a9e8aec5713460:"Mer",s5c6aad7a7e4a1437:"3) Välj Lägg till på hemskärmen",s6196153c4b0c1ea0:"Installera",s922329d6f6213590:"Lägg till i Dock",sa5ef80b4bb9b39f8:"Mindre",sa7551383d1897fcc:"2) Välj Lägg till i Dock",sba52286c21552a4e:"Installera den på din enhet för att få en bättre användarupplevelse och enklare åtkomst.",sc79fd7641eb9a975:"Göm instruktioner",scdaf4bbff76674c8:"Lägg till på hemskärmen",sdfe23506a3b0cdc8:"1) Öppna i Safari",se740f75b95a51807:"Lägg till i Dock för att få en bättre användarupplevelse och enklare åtkomst.",sfea652f6580ff086:"Denna webbsajt har app-funktionalitet."},ma={s182ab2d6c997515f:"더 많은 기능과 쉬운 접근을 위해 홈 화면에 추가해주세요.",s1b9047d53d9f9d22:"2) 내비게이션 바에서 공유 버튼 누르기",s37a9e8aec5713460:"더보기",s5c6aad7a7e4a1437:"3) 홈 화면에 추가 버튼 누르기",s6196153c4b0c1ea0:"설치",s922329d6f6213590:"Dock에 추가",sa5ef80b4bb9b39f8:"닫기",sa7551383d1897fcc:"2) Dock에 추가 버튼 누르기",sba52286c21552a4e:"더 많은 기능과 쉬운 접근을 위해 기기에 설치해주세요.",sc79fd7641eb9a975:"안내 숨기기",scdaf4bbff76674c8:"홈 화면에 추가",sdfe23506a3b0cdc8:"1) Safari 브라우저에서 열기",se740f75b95a51807:"더 많은 기능과 쉬운 접근을 위해 Dock에 추가해주세요.",sfea652f6580ff086:"이 사이트는 앱 기능을 가지고 있습니다."},ua={s182ab2d6c997515f:"បន្ថែមវាទៅកាន់ផ្ទាំងអេក្រង់ដើមដើម្បីទទួលបាននូវបទពិសោធន៍កាន់តែល្អនិងងាយស្រួលប្រើ។",s1b9047d53d9f9d22:"2) ចុចលើ ប៊ូតុងចែករំលែក នៅក្នុងរបារទិសដៅ",s37a9e8aec5713460:"បង្ហាញបន្ថែម",s5c6aad7a7e4a1437:"3) ចុចលើ បន្ថែមទៅកាន់ផ្ទាំងអេក្រង់ដើម",s6196153c4b0c1ea0:"តំឡើង",s922329d6f6213590:"បន្ថែមទៅកាន់ Dock",sa5ef80b4bb9b39f8:"បង្ហាញតិច",sa7551383d1897fcc:"2) ចុចលើ បន្ថែមទៅកាន់ Dock",sba52286c21552a4e:"តំឡើងវានៅលើឧបករណ៍របស់អ្នកដើម្បីទទួលបាននូវបទពិសោធន៍កាន់តែល្អនិងងាយស្រួលប្រើ។",sc79fd7641eb9a975:"បិទការណែនាំ",scdaf4bbff76674c8:"បន្ថែមទៅកាន់ផ្ទាំងអេក្រង់ដើម",sdfe23506a3b0cdc8:"1) បើកនៅក្នុងកម្មវិធី Safari",se740f75b95a51807:"បន្ថែមវាទៅកាន់ Dock ដើម្បីទទួលបាននូវបទពិសោធន៍កាន់តែល្អនិងងាយស្រួលប្រើ។",sfea652f6580ff086:"គេហទំព័រនេះមានមុខងារជាកម្មវិធី។"},pt=new Map([["ru",re],["tr",de],["de",ce],["es",pe],["nl",he],["el",ge],["fr",be],["sr",me],["pl",ue],["uk",fe],["zh",ve],["zh-CN",we],["it",ye],["cs",xe],["no",ke],["pt",$e],["ja",_e],["sv",Ae],["ko",Ee],["km",Se]]),{getLocale:Ia,setLocale:Ge}=(I={sourceLocale:"en",targetLocales:Kt,loadLocale:async a=>pt.get(a)},function(a){if(Ye)throw Error("lit-localize can only be configured once");k=a,Ye=!0}((a,e)=>Vt(ct,a,e)),Q=dt=I.sourceLocale,J=new Set(I.targetLocales),J.add(I.sourceLocale),Pe=I.loadLocale,{getLocale:Ft,setLocale:Gt});var I;class fa{constructor(){this.icons=[{src:""}],this.screenshots=void 0,this.short_name="PWA",this.name="Progressive web application",this.description="Progressive web application"}}const va=h.css`.gallery{position:relative;--scrollbar-background-color:#fff;--scrollbar-thumb-color:rgb(146, 146, 146);--scrollbar-thumb-hover-color:rgb(100, 100, 100);--nav-btn-background-color:#fff;--nav-btn-fill-color:#141414}.gallery .gallery_scroller{scroll-snap-type:x mandatory;overflow-x:auto;overflow-y:hidden;display:flex;align-items:center;padding:10px 13px;padding-bottom:10px;margin:0 10px;-webkit-overflow-scrolling:touch}.gallery .gallery_scroller img{border-radius:6px;max-height:min(45vh,500px);box-shadow:0 3px 10px 0 rgba(0,0,0,.15);scroll-snap-align:center;scroll-snap-stop:always;position:relative}.gallery .gallery_scroller img+img{margin-left:15px}.gallery .gallery_scroller::-webkit-scrollbar{width:4px;height:2px}.gallery .gallery_scroller::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb-color);border-radius:4px}.gallery .gallery_scroller::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover-color)}.gallery .gallery_scroller::-webkit-scrollbar-track{background:var(--scrollbar-background-color);border-radius:4px}.gallery .gallery_scroller .scroller_wrap{display:flex;flex-direction:row;padding-right:13px}.gallery .btn{position:absolute;display:flex;align-items:center;-webkit-user-select:none;user-select:none;top:50%;transform:translateY(-50%);height:30px;width:30px;border-radius:50%;background-color:var(--nav-btn-background-color);box-shadow:rgba(0,0,0,.3) 2px 4px 4px 1px;background-repeat:no-repeat;opacity:.8;z-index:1}.gallery .btn.prev{left:5px}.gallery .btn.prev svg{margin-left:4px}.gallery .btn.next{right:5px}.gallery .btn.next svg{transform:rotate(180deg);margin-left:6px}.gallery .btn:hover{box-shadow:rgba(0,0,0,.5) 2px 4px 4px 1px;cursor:pointer;opacity:1}.gallery .btn svg{width:20px;height:20px}.gallery .btn svg path{fill:var(--nav-btn-fill-color)}.gallery.apple_desktop{--scrollbar-background-color:rgba(0, 0, 0, 0.1);--scrollbar-thumb-color:rgb(100, 100, 100);--scrollbar-thumb-hover-color:rgba(0, 0, 0, 0.85)}.gallery.apple_desktop .gallery_scroller{margin:0;padding-top:15px}.gallery.apple_desktop .btn{height:26px;width:26px;box-shadow:rgba(0,0,0,.3) 0 2px 2px 1px}.gallery.apple_desktop .btn:hover{box-shadow:rgba(0,0,0,.3) 0 2px 2px 1px}.gallery.apple_desktop .btn:active{filter:brightness(95%)}.gallery.apple_desktop .btn:active .svg{filter:brightness(110%)}.gallery.apple_desktop .btn svg{width:12px;height:auto;opacity:1}.gallery.apple_desktop .btn svg{margin-left:7px}.gallery.apple_mobile .btn.prev svg{margin-left:7px}.gallery.apple_mobile .btn svg{width:16px;height:auto}.gallery.apple_desktop .btn,.gallery.apple_mobile .btn{opacity:1}@media(hover:none)and (pointer:coarse){.gallery .btn.next,.gallery .btn.prev{display:none}.gallery_scroller::-webkit-scrollbar{display:none}}@media(prefers-color-scheme:dark){.gallery{--scrollbar-background-color:#424242;--nav-btn-background-color:#555555;--nav-btn-fill-color:#fff}.gallery.apple_desktop{--scrollbar-thumb-color:var(--nav-btn-fill-color);--scrollbar-background-color:var(--nav-btn-background-color);--scrollbar-thumb-hover-color:var(--nav-btn-fill-color)}.gallery.apple_desktop .btn:active{filter:brightness(110%)}.gallery.apple_desktop .btn:active .svg{filter:brightness(90%)}}`,wa=(a,e,t,i)=>h.html`${a?h.html``:""}`;var le=function(a,e,t,i){var o,s=arguments.length,l=s<3?e:i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")l=Reflect.decorate(a,e,t,i);else for(var n=a.length-1;n>=0;n--)(o=a[n])&&(l=(s<3?o(l):s>3?o(e,t,l):o(e,t))||l);return s>3&&l&&Object.defineProperty(e,t,l),l},Ke=function(a,e){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(a,e)};let H=class extends h.LitElement{constructor(){super(...arguments),this.screenshots=[],this.theme="default",this.calcScrollSize=()=>{const a=this.shadowRoot.querySelector("#paginated_gallery");if(!a)return;const e=a.querySelector(".gallery_scroller");if(!e)return;const t=Array.from(e.querySelectorAll("img"));if(!t)return;const i=t.find(o=>o.offsetWidth+o.offsetLeft>=e.scrollLeft);return i?{scroller:e,item:i}:void 0},this.scrollToNextPage=()=>{const a=this.calcScrollSize();a&&a.item.nextElementSibling&&a.scroller.scrollTo({top:0,left:a.scroller.scrollLeft+a.scroller.clientWidth+a.item.nextElementSibling.clientWidth/2,behavior:"smooth"})},this.scrollToPrevPage=()=>{const a=this.calcScrollSize();a&&a.item.previousElementSibling&&a.scroller.scrollTo({top:0,left:a.scroller.scrollLeft-a.scroller.clientWidth-a.item.previousElementSibling.clientWidth/2,behavior:"smooth"})},this._init=()=>{}}static get styles(){return va}firstUpdated(){const a=this.calcScrollSize();a&&setTimeout(()=>{a.scroller.scrollTo({top:0,left:0})},300)}connectedCallback(){super.connectedCallback(),this._init()}render(){return h.html`${wa(this.screenshots,this.theme,this.scrollToNextPage,this.scrollToPrevPage)}`}};le([(0,b.property)(),Ke("design:type",Object)],H.prototype,"screenshots",void 0),le([(0,b.property)(),Ke("design:type",String)],H.prototype,"theme",void 0),H=le([(0,b.customElement)("pwa-gallery")],H);const ya=H,xa=(a,e,t,i)=>h.html`
icon
${location.hostname}
${e?h.html`
${e}
`:""}`,T=(a,e,t)=>{const i=new CustomEvent(e,{detail:{message:t}});a.dispatchEvent(i)};class v{static isAppleMobile(){return!(!(["iPhone","iPad","iPod"].includes(navigator.platform)||navigator.userAgent.match(/Mac/)&&navigator.maxTouchPoints&&navigator.maxTouchPoints>2)||!("serviceWorker"in navigator))}static isAppleDesktop(){const e=navigator.userAgent.toLowerCase();if(navigator.maxTouchPoints||!e.match(/macintosh/))return!1;const t=/version\/(\d{2})\./.exec(e);if(!(t&&t[1]&&parseInt(t[1])>=17))return!1;const i=!!document.createElement("audio").canPlayType('audio/wav; codecs="1"'),o=!!new OffscreenCanvas(1,1).getContext("webgl");return i&&o}static isStandalone(){return!!(window.matchMedia("(display-mode: standalone)").matches||"standalone"in navigator&&navigator.standalone===!0)}static async getInstalledRelatedApps(){if("getInstalledRelatedApps"in navigator)try{await navigator.getInstalledRelatedApps().then(e=>e)}catch{}return[]}static async isRelatedAppsInstalled(){return!!(await this.getInstalledRelatedApps()).length}static eventInstalledSuccess(e){T(e,"pwa-install-success-event","App install success (Chromium/Android only)")}static eventInstalledFail(e){T(e,"pwa-install-fail-event","App install failed (Chromium/Android only)")}static eventUserChoiceResult(e,t){T(e,"pwa-user-choice-result-event",t)}static eventInstallAvailable(e){T(e,"pwa-install-available-event","App install available")}static eventInstallHowTo(e){T(e,"pwa-install-how-to-event","App install instruction showed")}static eventGallery(e){T(e,"pwa-install-gallery-event","App install gallery showed")}static normalizeManifestAssetUrls(e,t){const i=new URL(t,document.location.href);[...e.icons||[],...e.screenshots||[]].forEach(o=>{o.src=new URL(o.src,i).href})}}var U=function(a,e,t,i){var o,s=arguments.length,l=s<3?e:i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")l=Reflect.decorate(a,e,t,i);else for(var n=a.length-1;n>=0;n--)(o=a[n])&&(l=(s<3?o(l):s>3?o(e,t,l):o(e,t))||l);return s>3&&l&&Object.defineProperty(e,t,l),l},V=function(a,e){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(a,e)};let P=class extends h.LitElement{constructor(){super(...arguments),this.props={name:"",description:"",icon:""},this.install={handleEvent:()=>{}},this.hideDialog=()=>{},this.disableClose=!1,this._callInstall=()=>{this.install.handleEvent()},this._callHide=()=>{this.hideDialog(),this.setupAppearence()},this.bindedElement=null,this._saveBodyStyle=document.body.style.overscrollBehaviorY,this.dragMobileSheet=(a,e,t)=>{if(!a||!e||!t)return null;let i=0;const o=e.clientHeight+t.clientHeight,s=p=>p.clientY||(p.changedTouches&&p.changedTouches.length?p.changedTouches[0].clientY:0),l=p=>{window.addEventListener("mouseup",n),window.addEventListener("mousemove",r),window.addEventListener("touchend",n),window.addEventListener("touchmove",r),i=s(p)-e.getBoundingClientRect().top,document.body.style.overscrollBehaviorY="none"},n=p=>{if(document.body.style.overscrollBehaviorY=this._saveBodyStyle,!this.disableClose&&s(p)>=window.innerHeight-25)g(p,window.innerHeight+50,!0);else if(window.innerHeight-s(p)>a.clientHeight/2.5){g(p,window.innerHeight-a.clientHeight);try{v.eventGallery(this.getRootNode().host)}catch{}}else g(p,window.innerHeight-o-35)},r=p=>{const d=s(p);this.disableClose&&window.innerHeight-d<70||d<=window.innerHeight-a.clientHeight+i||(a.style.setProperty("transition","none"),a.style.setProperty("--translateY",`translateY(${d-i}px)`))},g=(p,d,m)=>{window.removeEventListener("mouseup",n),window.removeEventListener("mousemove",r),window.removeEventListener("touchend",n),window.removeEventListener("touchmove",r),window.innerWidth>=768||(!d&&s(p)>=window.innerHeight-o?a.style.setProperty("--translateY",`translateY(calc(100vh - ${o}px))`):a.style.setProperty("--translateY",`translateY(${(d||s(p))+35}px)`),a.style.setProperty("transition","transform 500ms cubic-bezier(0.4, 0, 0, 1) 0s"),m&&(e.removeEventListener("mousedown",l),e.removeEventListener("touchstart",l),setTimeout(this._callHide,250)))};return e.addEventListener("mousedown",l),e.addEventListener("touchstart",l,{passive:!0}),g(new MouseEvent("mouseup"),window.innerHeight-o-35),{touchElement:e,listener:l}},this.setupAppearence=()=>{var a,e,t;this.bindedElement&&(this.bindedElement.touchElement.removeEventListener("mousedown",this.bindedElement.listener),this.bindedElement.touchElement.removeEventListener("touchstart",this.bindedElement.listener)),this.bindedElement=this.dragMobileSheet((a=this.parentElement)==null?void 0:a.parentElement,(e=this.parentElement)==null?void 0:e.getElementsByClassName("touch-header")[0],(t=this.parentElement)==null?void 0:t.getElementsByClassName("body-header")[0])},this._init=()=>{this.setupAppearence(),window.addEventListener("resize",this.setupAppearence)}}firstUpdated(){this._init()}createRenderRoot(){return this}connectedCallback(){super.connectedCallback()}render(){return h.html`${xa(this.props.name,this.props.description,this.props.icon,this._callInstall)}`}};U([(0,b.property)({type:Object}),V("design:type",Object)],P.prototype,"props",void 0),U([(0,b.property)({type:Object}),V("design:type",Object)],P.prototype,"install",void 0),U([(0,b.property)(),V("design:type",Object)],P.prototype,"hideDialog",void 0),U([(0,b.property)(),V("design:type",Object)],P.prototype,"disableClose",void 0),P=U([(0,b.customElement)("pwa-bottom-sheet")],P);const ka=P,$a=h.css`#pwa-install-element{-webkit-user-select:none;user-select:none}#pwa-install-element .install-dialog{--text-color-normal:#212121;--background-color:#fff;--border-bottom-color:#DBDCDE;--scrollbar-background-color:#fff;font-family:Roboto,"Segoe UI",system-ui;position:fixed;display:inline-block;opacity:0;visibility:hidden;z-index:2147483001}#pwa-install-element .install-dialog.chrome{max-width:380px;width:90%;min-height:90px;margin:0 auto;right:150px;left:auto;background-color:var(--background-color);filter:drop-shadow(0 5px 15px rgba(0, 0, 0, .3));font-size:15px;color:var(--text-color-normal);border-radius:8px;top:-100px;transition:top .5s ease-in-out,opacity .8s ease-in-out,max-height .35s ease-in-out}#pwa-install-element .install-dialog.chrome.available{opacity:1;top:28px;visibility:visible}#pwa-install-element .install-dialog.chrome .dialog-body{display:grid;grid-template-columns:70px 1fr}#pwa-install-element .install-dialog.chrome .dialog-body .icon{display:flex;align-items:flex-start}#pwa-install-element .install-dialog.chrome .dialog-body .icon .icon-image{width:48px;height:48px;margin:0 auto;margin-top:10px;border-radius:6px}#pwa-install-element .install-dialog.chrome .dialog-body .about{display:grid;grid-template-rows:30px auto}#pwa-install-element .install-dialog.chrome .dialog-body .about .hostname,#pwa-install-element .install-dialog.chrome .dialog-body .about .name{padding:0 5px;overflow:hidden}#pwa-install-element .install-dialog.chrome .dialog-body .about .name{font-weight:500;font-size:18px;line-height:24px;margin-top:5px;align-items:flex-start;display:flex}#pwa-install-element .install-dialog.chrome .dialog-body .about .name label{text-overflow:ellipsis;word-break:break-all;white-space:nowrap;overflow:hidden}#pwa-install-element .install-dialog.chrome .dialog-body .about .hostname{font-size:13px;font-weight:400;opacity:.7;line-height:14px;overflow-x:hidden;text-overflow:ellipsis;text-align:left;word-break:break-all;white-space:nowrap}#pwa-install-element .install-dialog.chrome .dialog-body .about+hr{margin-top:10px}#pwa-install-element .install-dialog.chrome .dialog-body .description{font-weight:400;line-height:20px;grid-column:1/3;padding:0 6px;margin:10px 5px 5px;display:-webkit-box;-webkit-line-clamp:5;-webkit-box-orient:vertical;max-height:115px;overflow:hidden;overflow-y:auto;text-overflow:ellipsis;text-align:left}#pwa-install-element .install-dialog.chrome .dialog-body .app-description{font-size:13px;margin-bottom:10px}#pwa-install-element .install-dialog.chrome .dialog-body .app-description::-webkit-scrollbar{width:4px;height:4px}#pwa-install-element .install-dialog.chrome .dialog-body .app-description::-webkit-scrollbar-thumb{background:#929292;border-radius:4px}#pwa-install-element .install-dialog.chrome .dialog-body .app-description::-webkit-scrollbar-thumb:hover{background:#646464}#pwa-install-element .install-dialog.chrome .dialog-body .app-description::-webkit-scrollbar-track{background:var(--scrollbar-background-color);border-radius:4px}#pwa-install-element .install-dialog.chrome .dialog-body .install-description{font-size:14px}#pwa-install-element .install-dialog.chrome .dialog-body hr{height:1px;width:100%;grid-column:1/3;background-color:var(--border-bottom-color);border:none;margin:0}#pwa-install-element .install-dialog.chrome .dialog-body .action-buttons{display:grid;grid-template-columns:50% auto;grid-column-start:1;grid-column-end:3;gap:10px;padding:10px 10px}#pwa-install-element .install-dialog.chrome .dialog-body .action-buttons .primary{grid-column-start:2}#pwa-install-element .install-dialog.chrome .dialog-body pwa-gallery{grid-column:1/3;max-height:0;opacity:0;transition:opacity ease-in-out .5s,max-height .5s ease-in-out;overflow:hidden}#pwa-install-element .install-dialog.chrome.gallery pwa-gallery{transition:opacity .3s ease-in-out .2s,max-height .5s ease-in-out;max-height:70vh;opacity:1}#pwa-install-element .install-dialog.mobile{--touch-header-color:#DBDCE0;top:0;max-width:414px;width:100%;bottom:auto;left:0;right:0;transition:none;transform:translateY(100vh);border-radius:0;border-top-left-radius:15px;border-top-right-radius:15px;padding-bottom:35px}#pwa-install-element .install-dialog.mobile .dialog-body{grid-template-columns:1fr}#pwa-install-element .install-dialog.mobile .dialog-body .touch-header{height:30px;width:100%;padding-top:10px;box-sizing:border-box;cursor:grab}#pwa-install-element .install-dialog.mobile .dialog-body .touch-header:active{cursor:grabbing}#pwa-install-element .install-dialog.mobile .dialog-body .touch-header::before{content:"";width:40px;height:5px;border-radius:3px;background:var(--touch-header-color);margin:0 auto;display:block}#pwa-install-element .install-dialog.mobile .dialog-body .body-header{display:grid;grid-template-columns:max-content 1fr max-content;grid-gap:15px;padding:18px 20px;padding-top:0;border-bottom:1px solid var(--border-bottom-color)}#pwa-install-element .install-dialog.mobile .dialog-body .body-header .install{text-transform:capitalize;height:40px;padding:0 23px}#pwa-install-element .install-dialog.mobile .dialog-body .body-header .about{grid-template-rows:auto auto;grid-gap:6px}#pwa-install-element .install-dialog.mobile .dialog-body .body-header .about .name{padding:0;line-height:20px;font-size:16px}#pwa-install-element .install-dialog.mobile .dialog-body .body-header .about .hostname{font-size:14px;font-weight:400;opacity:.7;line-height:14px;overflow-x:hidden;text-overflow:ellipsis;word-break:break-all;white-space:nowrap;padding:0}#pwa-install-element .install-dialog.mobile .dialog-body .body-header .icon .icon-image{margin:0;width:45px;height:45px}#pwa-install-element .install-dialog.mobile .dialog-body .description{padding:15px 20px 0;margin:0;margin-bottom:15px;-webkit-line-clamp:6;max-height:150px}#pwa-install-element .install-dialog.mobile .dialog-body pwa-gallery{max-height:100%;padding-bottom:15px;opacity:1}#pwa-install-element .install-dialog.mobile .material-button{border-radius:20px}#pwa-install-element .install-dialog.mobile.available{--translateY:translateY(calc(100vh - 85px));opacity:1;top:0;visibility:visible;transform:var(--translateY)}#pwa-install-element .material-button{--text-color-primary:#fff;--text-color-secondary:#374fc6;--background-color-primary:#374fc6;--background-color-ripple:#fff;position:relative;display:inline-block;box-sizing:border-box;border:none;border-radius:6px;padding:0 16px;min-width:64px;height:36px;vertical-align:middle;text-align:center;text-overflow:ellipsis;text-transform:uppercase;box-shadow:0 3px 1px -2px rgba(0,0,0,.2),0 2px 2px 0 rgba(0,0,0,.14),0 1px 5px 0 rgba(0,0,0,.12);font-family:Roboto,"Segoe UI",BlinkMacSystemFont,system-ui,-apple-system;font-size:14px;font-weight:500;line-height:37px;overflow:hidden;outline:0;cursor:pointer;transition:box-shadow .2s}#pwa-install-element .material-button.primary{color:var(--text-color-primary);background-color:var(--background-color-primary)}#pwa-install-element .material-button.secondary{background-color:rgba(0,0,0,0);color:var(--text-color-secondary);box-shadow:none}#pwa-install-element .material-button.secondary::after,#pwa-install-element .material-button.secondary::before{background-color:var(--background-color-primary)}#pwa-install-element .material-button.secondary:active,#pwa-install-element .material-button.secondary:hover{box-shadow:none}#pwa-install-element .material-button.secondary.close{height:26px;min-width:26px;line-height:0;margin-right:0;margin-left:auto;padding:0;border-radius:50%}#pwa-install-element .material-button.secondary.close svg{width:16px;fill:var(--text-color-secondary)}#pwa-install-element .material-button.secondary.close::after{width:25px;height:25px;border-radius:50%}#pwa-install-element .material-button.secondary.close::before{border-radius:50%}#pwa-install-element .material-button::before{content:"";position:absolute;top:0;bottom:0;left:0;right:0;background-color:var(--background-color-ripple);opacity:0;transition:opacity .2s}#pwa-install-element .material-button::after{content:"";position:absolute;left:50%;top:50%;border-radius:50%;padding:50%;width:32px;height:32px;background-color:var(--background-color-ripple);opacity:0;transform:translate(-50%,-50%) scale(1);transition:opacity 1s,transform .5s}#pwa-install-element .material-button:hover{box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12)}#pwa-install-element .material-button:hover::before{opacity:.08}#pwa-install-element .material-button:hover:focus::before{opacity:.3}#pwa-install-element .material-button:active{box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12)}#pwa-install-element .material-button:active::after{opacity:.32;transform:translate(-50%,-50%) scale(0);transition:transform 0s}@media(prefers-color-scheme:dark){#pwa-install-element .install-dialog{--text-color-normal:#fff;--background-color:#1e1e1e;--border-bottom-color:#404140;--scrollbar-background-color:#424242}#pwa-install-element .install-dialog.mobile{--touch-header-color:#3f403f}#pwa-install-element .install-dialog .material-button{--text-color-primary:#1B222C;--text-color-secondary:#a7c7fa;--background-color-primary:#a7c7fa}}@media(max-width:767px)and (min-height:495px){#pwa-install-element .install-dialog.chrome.mobile{display:inline-block}#pwa-install-element .install-dialog.chrome{display:none}}@media(min-width:768px),(max-height:495px){#pwa-install-element .install-dialog.chrome.mobile{display:none}#pwa-install-element .install-dialog.chrome{display:inline-block}}@media(max-height:420px){#pwa-install-element .install-dialog.chrome .dialog-body .description{-webkit-line-clamp:3;max-height:70px}}@media(hover:none)and (pointer:coarse){#pwa-install-element .install-dialog.chrome .dialog-body .description::-webkit-scrollbar{display:none}}`,_a=h.css`#pwa-install-element .install-dialog.apple{--text-color-normal:#333;--text-color-description:#333;--background-color:rgba(255, 255, 255, 0.8);--text-color-button:#fff;--background-color-button:#fff;--background-color-button-active:#DBDAE0;--border-bottom-color:rgba(0, 0, 0, 0.1);--icon-how-to-color:#527AFB;font-family:system-ui,-apple-system,HelveticaNeue,BlinkMacSystemFont,Roboto,"Segoe UI";max-width:380px;width:auto;margin:0 auto;right:0;left:0;font-size:15px;color:var(--text-color-normal);bottom:0;transition:transform .4s cubic-bezier(.33,1,.66,1),opacity .5s cubic-bezier(1,0,1,-2),border .35s ease-in-out;overflow:hidden;pointer-events:none;opacity:0;visibility:visible;transform:translateY(100%);will-change:opacity,transform}#pwa-install-element .install-dialog.apple.dialog-body{display:grid;grid-template-columns:95px 1fr;grid-template-rows:1fr auto;grid-template-areas:"icon description" "welcome welcome" "how-to how-to" "gallery gallery" "button button";border-radius:10px;border-bottom:1px solid transparent;background-color:var(--background-color);filter:drop-shadow(0 5px 15px rgba(0, 0, 0, .5));backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}#pwa-install-element .install-dialog.apple.dialog-body .icon{display:flex;align-items:center;grid-area:icon;border-bottom:1px solid var(--border-bottom-color)}#pwa-install-element .install-dialog.apple.dialog-body .icon .icon-image{width:64px;height:64px;margin:0 auto;border-radius:6px}#pwa-install-element .install-dialog.apple.dialog-body .close{height:26px;min-width:26px;line-height:0;margin-right:7px;margin-top:7px;margin-left:auto;padding:0;border-radius:50%;opacity:.5;outline:0;color:var(--text-color-normal);border:none;background-color:rgba(0,0,0,0);cursor:pointer;transition:opacity .2s ease-in-out,background-color .2s ease-in-out;grid-area:description}#pwa-install-element .install-dialog.apple.dialog-body .close svg{fill:var(--text-color-normal);width:18px}#pwa-install-element .install-dialog.apple.dialog-body .close:active,#pwa-install-element .install-dialog.apple.dialog-body .close:hover{opacity:1;background-color:var(--background-color-button)}#pwa-install-element .install-dialog.apple.dialog-body .about{display:grid;grid-template-rows:35px 60px;border-bottom:1px solid var(--border-bottom-color);grid-area:description}#pwa-install-element .install-dialog.apple.dialog-body .about .description,#pwa-install-element .install-dialog.apple.dialog-body .about .name{padding-right:15px;overflow:hidden}#pwa-install-element .install-dialog.apple.dialog-body .about .name{font-weight:600;padding-top:10px;padding-right:10px;line-height:22px;align-items:flex-start;display:flex}#pwa-install-element .install-dialog.apple.dialog-body .about .description{font-size:12px;line-height:15px;margin-bottom:15px;overflow-y:auto;color:var(--text-color-description)}#pwa-install-element .install-dialog.apple.dialog-body .welcome-to-install{font-size:15px;grid-area:welcome;text-align:left;font-weight:400;padding:15px;width:auto;border-bottom:1px solid var(--border-bottom-color)}#pwa-install-element .install-dialog.apple .action-buttons{grid-area:button;grid-column-start:1;grid-column-end:3;padding:15px}#pwa-install-element .install-dialog.apple .dialog-button{display:grid;height:50px;width:100%;line-height:50px;border-radius:8px;color:var(--text-color-normal)}#pwa-install-element .install-dialog.apple .dialog-button.button{border:none;outline:0;font-family:system-ui,-apple-system,HelveticaNeue,BlinkMacSystemFont;cursor:pointer;-webkit-user-select:none;user-select:none;font-weight:400;font-size:17px;padding:0;margin:0;background-color:var(--background-color-button)}#pwa-install-element .install-dialog.apple .dialog-button.button.install{padding:0 15px;text-align:left}#pwa-install-element .install-dialog.apple .dialog-button.button.install .button-text{opacity:0;display:flex;align-items:center;justify-content:space-between;transition:opacity .4s ease-in-out .1s;overflow:hidden}#pwa-install-element .install-dialog.apple .dialog-button.button.install .button-text>span{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}#pwa-install-element .install-dialog.apple .dialog-button.button.install .button-text>svg{flex-shrink:0;width:20px}#pwa-install-element .install-dialog.apple .dialog-button.button.install .button-text.show{opacity:1;visibility:visible;width:auto;height:auto}#pwa-install-element .install-dialog.apple .dialog-button.button.install .button-text.hide{opacity:0;position:absolute;width:0;height:0;visibility:hidden}#pwa-install-element .install-dialog.apple .dialog-button.button.gallery{display:flex;align-items:center;min-width:50px;width:auto;margin-right:15px}#pwa-install-element .install-dialog.apple .dialog-button.button.gallery #pwa-gallery{margin:0 auto;width:23px;fill:var(--text-color-normal)}#pwa-install-element .install-dialog.apple .dialog-button.button:active{background-color:var(--background-color-button-active)}#pwa-install-element .install-dialog.apple .how-to-body{opacity:0;max-height:0;overflow:hidden;transition:opacity ease-in-out .5s,max-height .5s ease-in-out;grid-area:how-to}#pwa-install-element .install-dialog.apple .how-to-body .how-to-description{display:grid;-webkit-user-select:none;user-select:none;grid-auto-columns:1fr;grid-template-rows:1fr 1fr 1fr;gap:10px;padding:15px;padding-bottom:0}#pwa-install-element .install-dialog.apple .how-to-body .how-to-description .description-step{display:inline-flex;flex-direction:row;gap:15px;align-items:center;font-size:14px}#pwa-install-element .install-dialog.apple .how-to-body .how-to-description .description-step .svg-wrap{position:relative;display:inline-flex;flex-shrink:0;color:var(--icon-how-to-color);width:50px;height:50px;align-items:center;border-radius:6px}#pwa-install-element .install-dialog.apple .how-to-body .how-to-description .description-step .svg-wrap #pwa-add,#pwa-install-element .install-dialog.apple .how-to-body .how-to-description .description-step .svg-wrap #pwa-safari,#pwa-install-element .install-dialog.apple .how-to-body .how-to-description .description-step .svg-wrap #pwa-share{margin:0 auto}#pwa-install-element .install-dialog.apple .how-to-body .how-to-description .description-step .svg-wrap #pwa-share{margin-bottom:4px;transform:scale(.9)}#pwa-install-element .install-dialog.apple .how-to-body .how-to-description .description-step .svg-wrap #pwa-add{transform:scale(.8);fill:var(--text-color-normal)}#pwa-install-element .install-dialog.apple .how-to-body .how-to-description .description-step .svg-wrap #pwa-safari{transform:scale(.92)}#pwa-install-element .install-dialog.apple .how-to-body .how-to-description .description-step .svg-wrap .step-count{position:absolute;line-height:12px;top:3px;left:4px}#pwa-install-element .install-dialog.apple .how-to-body .how-to-description .description-step .step-text{font-weight:600;text-align:left}#pwa-install-element .install-dialog.apple pwa-gallery{grid-column:1/3;max-height:0;opacity:0;transition:opacity ease-in-out .5s,max-height .5s ease-in-out;overflow:hidden}#pwa-install-element .install-dialog.apple pwa-gallery+.action-buttons{display:flex}#pwa-install-element .install-dialog.apple.available{opacity:1;pointer-events:unset;transform:translateY(0);transition:transform .5s cubic-bezier(.33,1,.66,1),border .35s ease-in-out}#pwa-install-element .install-dialog.apple.gallery pwa-gallery{transition:opacity .3s ease-in-out .2s,max-height .5s ease-in-out;max-height:70vh;opacity:1}#pwa-install-element .install-dialog.apple.how-to .dialog-body{border-bottom:1px solid #e0e0e0}#pwa-install-element .install-dialog.apple.how-to .how-to-body{opacity:1;max-height:400px;overflow-y:auto;transition:opacity .3s ease-in-out .2s,max-height .5s ease-in-out}#pwa-install-element .install-dialog.apple.desktop{--text-color-normal:rgba(0, 0, 0, 0.85);--text-color-description:rgba(0, 0, 0, 0.85);--icon-how-to-color:rgba(0, 0, 0, 0.50);--background-color:rgb(246 246 246 / 85%);--background-color-button:#c6c1c6;--background-color-button-active:linear-gradient(0deg, rgba(64,121,250,1) 0%, rgba(84,144,251,1) 100%);--border-bottom-color:rgb(185 185 185);grid-template-columns:1fr;grid-template-rows:1fr auto;grid-template-areas:"icon" "description" "welcome" "how-to" "gallery" "button";gap:0;column-gap:0;padding:16px;max-width:260px;background:var(--background-color);border:1px solid var(--border-bottom-color)}#pwa-install-element .install-dialog.apple.desktop .icon{height:64px;padding-bottom:16px}#pwa-install-element .install-dialog.apple.desktop .icon .icon-image{border-radius:10px;width:52px;height:52px;filter:drop-shadow(0 1px 1px rgba(0, 0, 0, .15))}#pwa-install-element .install-dialog.apple.desktop .close{grid-area:icon;background:var(--background-color-button);opacity:1;height:20px;min-width:20px;margin-right:-5px;margin-top:-5px}#pwa-install-element .install-dialog.apple.desktop .close svg{width:14px}#pwa-install-element .install-dialog.apple.desktop .about{display:flex;flex-direction:column;align-items:center}#pwa-install-element .install-dialog.apple.desktop .about .name{font-size:13px;line-height:16px;font-weight:700;padding:0}#pwa-install-element .install-dialog.apple.desktop .about .description{padding:16px 0;margin:0;padding-top:10px;border-bottom:1px solid var(--border-bottom-color);min-width:100%}#pwa-install-element .install-dialog.apple.desktop .about .description,#pwa-install-element .install-dialog.apple.desktop .welcome-to-install{text-align:center;font-size:11px;line-height:14px}#pwa-install-element .install-dialog.apple.desktop .about,#pwa-install-element .install-dialog.apple.desktop .icon,#pwa-install-element .install-dialog.apple.desktop .welcome-to-install{border:none}#pwa-install-element .install-dialog.apple.desktop .welcome-to-install{padding:0;padding-top:16px}#pwa-install-element .install-dialog.apple.desktop .action-buttons{padding:0;padding-top:16px}#pwa-install-element .install-dialog.apple.desktop .action-buttons .dialog-button.button{font-size:13px;font-weight:400;padding:6px 8px;border-radius:6px;height:auto;line-height:18px}#pwa-install-element .install-dialog.apple.desktop .action-buttons .dialog-button.button.install{color:#fff;background:var(--background-color-button-active);transition:background .3s ease-in-out .1s,color .3s ease-in-out}#pwa-install-element .install-dialog.apple.desktop .action-buttons .dialog-button.button.install svg{transform:none;width:18px}#pwa-install-element .install-dialog.apple.desktop .action-buttons .dialog-button.button.gallery{width:30px;min-width:30px;margin-right:10px;background:var(--background-color-button)}#pwa-install-element .install-dialog.apple.desktop .action-buttons .dialog-button.button.gallery #pwa-gallery{width:14px;transition:transform .4s ease-in-out}#pwa-install-element .install-dialog.apple.desktop .close:active,#pwa-install-element .install-dialog.apple.desktop .dialog-button.button:active{filter:brightness(105%)}#pwa-install-element .install-dialog.apple.desktop .close:active .button-text,#pwa-install-element .install-dialog.apple.desktop .dialog-button.button:active .button-text{filter:brightness(90%)}#pwa-install-element .install-dialog.apple.desktop .how-to-body .how-to-description{padding:0;padding-top:16px;grid-template-rows:1fr 1fr}#pwa-install-element .install-dialog.apple.desktop .how-to-body .how-to-description .description-step{font-size:12px;gap:16px}#pwa-install-element .install-dialog.apple.desktop .how-to-body .how-to-description .description-step .svg-wrap{width:32px;height:32px;color:var(--icon-how-to-color)}#pwa-install-element .install-dialog.apple.desktop .how-to-body .how-to-description .description-step .svg-wrap #pwa-share{width:16px;margin-bottom:2px;transform:none}#pwa-install-element .install-dialog.apple.desktop .how-to-body .how-to-description .description-step .svg-wrap #pwa-add{width:18px;transform:none}#pwa-install-element .install-dialog.apple.desktop.gallery #pwa-gallery{transform:rotate(180deg)}#pwa-install-element .install-dialog.apple.desktop.how-to .action-buttons .dialog-button.button.install{color:var(--text-color-normal);background:var(--background-color-button)}@media(min-width:667px){#pwa-install-element .install-dialog.apple{top:0;bottom:unset;transform:translateY(calc(-100% - 40px));right:28px;left:auto}#pwa-install-element .install-dialog.apple.available{top:28px;bottom:auto;max-height:calc(95vh - 28px)}}@media(min-width:667px)and (max-width:1366px){#pwa-install-element .install-dialog.apple{right:max(28px,env(safe-area-inset-right,28px));left:auto}}@media(max-width:666px){#pwa-install-element .install-dialog.apple .description-step .step-text{font-size:13px}#pwa-install-element .install-dialog.apple.available{bottom:20px;max-height:calc(85vh - 20px)}#pwa-install-element .install-dialog.apple.dialog-body{filter:drop-shadow(rgba(0, 0, 0, .5) 0 0 15px)}}@media(max-width:428px){#pwa-install-element .install-dialog.apple.dialog-body{max-width:100vw;filter:drop-shadow(rgba(0, 0, 0, .5) 0 -5px 10px);border-bottom-left-radius:0;border-bottom-right-radius:0}#pwa-install-element .install-dialog.apple.dialog-body .action-buttons{padding-bottom:max(15px,env(safe-area-inset-bottom))}#pwa-install-element .install-dialog.apple.dialog-body.available{bottom:0;max-height:85vh}}@media(max-height:548px){#pwa-install-element .install-dialog.apple.dialog-body.available{overflow-y:auto;max-height:calc(90vh - 28px - env(safe-area-inset-bottom,0px))}}@media(max-height:600px){#pwa-install-element .install-dialog.apple pwa-gallery{overflow-y:auto}}@media(prefers-color-scheme:dark){#pwa-install-element .install-dialog.apple.dialog-body{--text-color-normal:#fff;--text-color-description:#9E9AA1;--background-color:rgb(25 25 25 / 90%);--background-color-button:#353535;--background-color-button-active:#454545;--border-bottom-color:#353535}#pwa-install-element .install-dialog.apple.dialog-body .close:active,#pwa-install-element .install-dialog.apple.dialog-body .dialog-button.button:active{filter:brightness(105%)}#pwa-install-element .install-dialog.apple.dialog-body .close:active .button-text,#pwa-install-element .install-dialog.apple.dialog-body .dialog-button.button:active .button-text{filter:brightness(90%)}#pwa-install-element .install-dialog.apple.dialog-body.desktop{--text-color-description:var(--text-color-normal);--icon-how-to-color:#bcb8b6;--background-color:rgb(45 45 45 / 90%);--border-bottom-color:#5b5b5b;--background-color-button:#6d6765;--background-color-button-active:linear-gradient(0deg, rgba(59,108,200,1) 0%, rgba(66,123,250,1) 100%);outline:1px solid #1c1c1c;color-scheme:dark}}`,ze=(a=>{var e={};return c.d(e,a),e})({classMap:()=>Ot}),Aa=(a,e,t,i,o,s,l,n,r,g,p,d,m)=>{const x=()=>({available:r,gallery:m}),$=!o&&n.screenshots&&n.screenshots.length;return h.html`
icon
${s?"":h.html``}
${location.hostname}
${e?h.html`
${e}
`:""} ${i?"":h.html`
${t||`${k("This site has app functionality.")} ${k("Install it on your device for extensive experience and easy access.")}`}
`} ${$?h.html``:""}
${$?h.html``:""}
${$?h.html``:""}
`},Ea=(a,e,t,i,o,s,l,n,r,g,p,d,m,x,$)=>{const Me=!o&&n.screenshots&&n.screenshots.length;return h.html``};var w=function(a,e,t,i){var o,s=arguments.length,l=s<3?e:i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")l=Reflect.decorate(a,e,t,i);else for(var n=a.length-1;n>=0;n--)(o=a[n])&&(l=(s<3?o(l):s>3?o(e,t,l):o(e,t))||l);return s>3&&l&&Object.defineProperty(e,t,l),l},y=function(a,e){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(a,e)};let f=class extends h.LitElement{constructor(){super(...arguments),this.manifestUrl="/manifest.json",this.icon="",this.name="",this.description="",this.installDescription="",this.disableDescription=!1,this.disableScreenshots=!1,this.disableScreenshotsApple=!1,this.disableScreenshotsChrome=!1,this.manualApple=!1,this.manualChrome=!1,this.disableChrome=!1,this.disableClose=!1,this.externalPromptEvent=null,this.platforms=[],this.userChoiceResult="",this.isDialogHidden=JSON.parse(window.sessionStorage.getItem("pwa-hide-install")||"false"),this.isInstallAvailable=!1,this.isAppleMobilePlatform=!1,this.isAppleDesktopPlatform=!1,this.isUnderStandaloneMode=!1,this.isRelatedAppsInstalled=!1,this._manifest=new fa,this._howToRequested=!1,this._galleryRequested=!1,this._install={handleEvent:()=>{window.defferedPromptEvent&&(this.hideDialog(),window.defferedPromptEvent.prompt(),window.defferedPromptEvent.userChoice.then(a=>{this.userChoiceResult=a.outcome,v.eventUserChoiceResult(this,this.userChoiceResult)}).catch(a=>{v.eventInstalledFail(this)}),window.defferedPromptEvent=null)},passive:!0},this.install=()=>{this.isAppleMobilePlatform||this.isAppleDesktopPlatform?(this._howToRequested=!0,this.requestUpdate()):this._install.handleEvent()},this._hideDialog={handleEvent:()=>{this.isDialogHidden=!0,window.sessionStorage.setItem("pwa-hide-install","true"),this.requestUpdate()},passive:!0},this._hideDialogUser=()=>{v.eventUserChoiceResult(this,"dismissed"),this.userChoiceResult="dismissed",this.hideDialog()},this.hideDialog=()=>{this._hideDialog.handleEvent()},this.showDialog=(a=!1)=>{this.isDialogHidden=!1,a&&(this.isInstallAvailable=!0),window.sessionStorage.setItem("pwa-hide-install","false"),this.requestUpdate()},this.getInstalledRelatedApps=async()=>await v.getInstalledRelatedApps(),this._howToForApple={handleEvent:()=>{this._howToRequested=!this._howToRequested,this._howToRequested&&this._galleryRequested&&(this._galleryRequested=!1),this.requestUpdate(),this._howToRequested&&v.eventInstallHowTo(this)},passive:!0},this._toggleGallery={handleEvent:()=>{this._galleryRequested=!this._galleryRequested,this._howToRequested&&this._galleryRequested&&(this._howToRequested=!1),this._galleryRequested&&v.eventGallery(this),this.requestUpdate()},passive:!0},this._init=async()=>{var a,e;if(window.defferedPromptEvent=null,this._checkInstalled(),!this.disableChrome){const t=i=>{window.defferedPromptEvent=i,i.preventDefault(),this.platforms=i.platforms,this.isRelatedAppsInstalled||this.isUnderStandaloneMode?this.isInstallAvailable=!1:(this.isInstallAvailable=!0,v.eventInstallAvailable(this)),this.userChoiceResult==="accepted"&&(this.isDialogHidden=!0,v.eventInstalledSuccess(this)),this.requestUpdate()};this.externalPromptEvent!=null?setTimeout(()=>t(this.externalPromptEvent),300):window.addEventListener("beforeinstallprompt",t)}window.addEventListener("appinstalled",t=>{window.defferedPromptEvent=null,this.isInstallAvailable=!1,this.requestUpdate(),v.eventInstalledSuccess(this)});try{const t=await fetch(this.manifestUrl),i=await t.json();if(!t.ok||!i||!Object.keys(i))throw Error("Manifest not found");v.normalizeManifestAssetUrls(i,this.manifestUrl),this.icon=this.icon||(a=i.icons)!=null&&a.length?i.icons[0].src:"",this.name=this.name||i.short_name||i.name||"",this.description=this.description||i.description||"",this._manifest=i}catch{this.icon=this.icon||((e=this._manifest.icons)==null?void 0:e[0].src)||"",this.name=this.name||this._manifest.short_name||"",this.description=this.description||this._manifest.description||""}},this._requestUpdate=()=>{this.requestUpdate()}}static get styles(){return[$a,_a]}async _checkInstalled(){this.isUnderStandaloneMode=v.isStandalone(),this.isRelatedAppsInstalled=await v.isRelatedAppsInstalled(),this.isAppleMobilePlatform=v.isAppleMobile(),this.isAppleDesktopPlatform=v.isAppleDesktop(),this.isAppleMobilePlatform||this.isAppleDesktopPlatform?this.isUnderStandaloneMode||(this.manualApple&&this.hideDialog(),setTimeout(()=>{this.isInstallAvailable=!0,this.requestUpdate(),v.eventInstallAvailable(this)},1e3)):this.manualChrome&&this.hideDialog()}connectedCallback(){(a=>{a.slice(0,2)==="nb"&&(a="no");try{pt.get(a)?Ge(a):Ge(a.slice(0,2))}catch{}})(navigator.language),this._init(),ya.finalized,ka.finalized,super.connectedCallback()}willUpdate(a){this.externalPromptEvent&&a.has("externalPromptEvent")&&typeof this.externalPromptEvent=="object"&&this._init()}render(){return this.isAppleMobilePlatform||this.isAppleDesktopPlatform?h.html`${Ea(this.name,this.description,this.installDescription,this.disableDescription,this.disableScreenshots||this.disableScreenshotsApple,this.disableClose,this.icon,this._manifest,this.isInstallAvailable&&!this.isDialogHidden,this._hideDialogUser,this._howToForApple,this.isAppleDesktopPlatform,this._howToRequested,this._toggleGallery,this._galleryRequested)}`:h.html`${Aa(this.name,this.description,this.installDescription,this.disableDescription,this.disableScreenshots||this.disableScreenshotsChrome,this.disableClose,this.icon,this._manifest,this.isInstallAvailable&&!this.isDialogHidden,this._hideDialogUser,this._install,this._toggleGallery,this._galleryRequested)}`}};w([(0,b.property)({attribute:"manifest-url"}),y("design:type",Object)],f.prototype,"manifestUrl",void 0),w([(0,b.property)(),y("design:type",Object)],f.prototype,"icon",void 0),w([(0,b.property)(),y("design:type",Object)],f.prototype,"name",void 0),w([(0,b.property)(),y("design:type",Object)],f.prototype,"description",void 0),w([(0,b.property)({attribute:"install-description"}),y("design:type",Object)],f.prototype,"installDescription",void 0),w([(0,b.property)({attribute:"disable-install-description",type:Boolean}),y("design:type",Object)],f.prototype,"disableDescription",void 0),w([(0,b.property)({attribute:"disable-screenshots",type:Boolean}),y("design:type",Object)],f.prototype,"disableScreenshots",void 0),w([(0,b.property)({attribute:"disable-screenshots-apple",type:Boolean}),y("design:type",Object)],f.prototype,"disableScreenshotsApple",void 0),w([(0,b.property)({attribute:"disable-screenshots-chrome",type:Boolean}),y("design:type",Object)],f.prototype,"disableScreenshotsChrome",void 0),w([(0,b.property)({attribute:"manual-apple",type:Boolean}),y("design:type",Object)],f.prototype,"manualApple",void 0),w([(0,b.property)({attribute:"manual-chrome",type:Boolean}),y("design:type",Object)],f.prototype,"manualChrome",void 0),w([(0,b.property)({attribute:"disable-chrome",type:Boolean}),y("design:type",Object)],f.prototype,"disableChrome",void 0),w([(0,b.property)({attribute:"disable-close",type:Boolean}),y("design:type",Object)],f.prototype,"disableClose",void 0),w([(0,b.state)(),y("design:type",Object)],f.prototype,"externalPromptEvent",void 0),f=w([(a,e)=>(a.addInitializer(Nt),a),(0,b.customElement)("pwa-install")],f);var Ua=st.w;export{Ua as PWAInstallElement}; diff --git a/assets/chunks/quick.WcLzRUPH.js b/assets/chunks/quick.WcLzRUPH.js new file mode 100644 index 0000000000..1b3115c89f --- /dev/null +++ b/assets/chunks/quick.WcLzRUPH.js @@ -0,0 +1 @@ +const s="/ran/assets/quick.DD28bswc.gif";export{s as _}; diff --git a/assets/chunks/radix.CHOmrmB0.js b/assets/chunks/radix.CHOmrmB0.js new file mode 100644 index 0000000000..2940279d19 --- /dev/null +++ b/assets/chunks/radix.CHOmrmB0.js @@ -0,0 +1 @@ +const s="/ran/assets/radix.Bwrylu8F.gif";export{s as _}; diff --git a/assets/chunks/select.BGReufCV.js b/assets/chunks/select.BGReufCV.js new file mode 100644 index 0000000000..da7f227111 --- /dev/null +++ b/assets/chunks/select.BGReufCV.js @@ -0,0 +1 @@ +const s="/ran/assets/select.B8GwndZy.gif";export{s as _}; diff --git a/assets/chunks/setting-DemlgzVC.DkD4YPwp.js b/assets/chunks/setting-DemlgzVC.DkD4YPwp.js new file mode 100644 index 0000000000..9b701ea56c --- /dev/null +++ b/assets/chunks/setting-DemlgzVC.DkD4YPwp.js @@ -0,0 +1 @@ +const c={success:!0,_identification:!0,data:''};export{c as default}; diff --git a/assets/chunks/shell.CGEkKxrp.js b/assets/chunks/shell.CGEkKxrp.js new file mode 100644 index 0000000000..4d290d5cdf --- /dev/null +++ b/assets/chunks/shell.CGEkKxrp.js @@ -0,0 +1 @@ +const s="/ran/assets/shell.CZ-z1IVg.gif";export{s as _}; diff --git a/assets/chunks/sprite-CH2zLtZy.Djo3sTkk.js b/assets/chunks/sprite-CH2zLtZy.Djo3sTkk.js new file mode 100644 index 0000000000..bf453a981d --- /dev/null +++ b/assets/chunks/sprite-CH2zLtZy.Djo3sTkk.js @@ -0,0 +1,138 @@ +const L={success:!0,_identification:!0,data:` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`};export{L as default}; diff --git a/assets/chunks/team-tl4NJXPC.D7881a1v.js b/assets/chunks/team-tl4NJXPC.D7881a1v.js new file mode 100644 index 0000000000..60c83427bd --- /dev/null +++ b/assets/chunks/team-tl4NJXPC.D7881a1v.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/theme.CPGewkGm.js b/assets/chunks/theme.CPGewkGm.js new file mode 100644 index 0000000000..75fea7168d --- /dev/null +++ b/assets/chunks/theme.CPGewkGm.js @@ -0,0 +1,20 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/chunks/index.CBA5mFK_.js","assets/chunks/framework.C-ai2y4t.js"])))=>i.map(i=>d[i]); +import{d as R,o as _,c as A,r as C,a as Ve,t as Z,n as ue,b as K,w as M,e as j,T as _n,_ as q,u as hr,i as io,f as lo,g as vn,h as U,j as w,k as v,l as pt,m as Bn,p as X,q as pe,s as it,v as Ye,x as gn,y as mr,z as co,A as uo,B as lt,F as he,C as Ce,D as bn,E as yn,G as x,H as Bs,I as We,J as Yt,K as at,L as Nt,M as fo,N as Ws,O as ho,P as Ue,Q as js,R as wn,S as xs,U as Bt,V as pr,W as kn,X as mo,Y as Ks,Z as Gs,$ as po,a0 as Ct,a1 as Ys,a2 as zs,a3 as _o,a4 as vo,a5 as go,a6 as Xs,a7 as bo,a8 as yo,a9 as wo,aa as ko,ab as Lo,ac as So,ad as Wt,ae as Eo,af as Oo,ag as cn}from"./framework.C-ai2y4t.js";const Co=R({__name:"VPBadge",props:{text:{},type:{default:"tip"}},setup(t){return(e,n)=>(_(),A("span",{class:ue(["VPBadge",e.type])},[C(e.$slots,"default",{},()=>[Ve(Z(e.text),1)])],2))}}),Ao={key:0,class:"VPBackdrop"},Io=R({__name:"VPBackdrop",props:{show:{type:Boolean}},setup(t){return(e,n)=>(_(),K(_n,{name:"fade"},{default:M(()=>[e.show?(_(),A("div",Ao)):j("",!0)]),_:1}))}}),Mo=q(Io,[["__scopeId","data-v-aa2f5bb7"]]),se=hr;function No(t,e){let n,r=!1;return()=>{n&&clearTimeout(n),r?n=setTimeout(t,e):(t(),(r=!0)&&setTimeout(()=>r=!1,e))}}function Wn(t){return/^\//.test(t)?t:`/${t}`}function _r(t){const{pathname:e,search:n,hash:r,protocol:s}=new URL(t,"http://a.com");if(io(t)||t.startsWith("#")||!s.startsWith("http")||!lo(e))return t;const{site:a}=se(),o=e.endsWith("/")||e.endsWith(".html")?t:t.replace(/(?:(^\.+)\/)?.*$/,`$1${e.replace(/(\.md)?$/,a.value.cleanUrls?"":".html")}${n}${r}`);return vn(o)}function zt({correspondingLink:t=!1}={}){const{site:e,localeIndex:n,page:r,theme:s,hash:a}=se(),o=U(()=>{var l,c;return{label:(l=e.value.locales[n.value])==null?void 0:l.label,link:((c=e.value.locales[n.value])==null?void 0:c.link)||(n.value==="root"?"/":`/${n.value}/`)}});return{localeLinks:U(()=>Object.entries(e.value.locales).flatMap(([l,c])=>o.value.label===c.label?[]:{text:c.label,link:$o(c.link||(l==="root"?"/":`/${l}/`),s.value.i18nRouting!==!1&&t,r.value.relativePath.slice(o.value.link.length-1),!e.value.cleanUrls)+a.value})),currentLang:o}}function $o(t,e,n,r){return e?t.replace(/\/$/,"")+Wn(n.replace(/(^|\/)index\.md$/,"$1").replace(/\.md$/,r?".html":"")):t}const Po={class:"NotFound"},To={class:"code"},Fo={class:"title"},Ro={class:"quote"},Vo={class:"action"},Do=["href","aria-label"],Ho=R({__name:"NotFound",setup(t){const{theme:e}=se(),{currentLang:n}=zt();return(r,s)=>{var a,o,i,l,c;return _(),A("div",Po,[w("p",To,Z(((a=v(e).notFound)==null?void 0:a.code)??"404"),1),w("h1",Fo,Z(((o=v(e).notFound)==null?void 0:o.title)??"PAGE NOT FOUND"),1),s[0]||(s[0]=w("div",{class:"divider"},null,-1)),w("blockquote",Ro,Z(((i=v(e).notFound)==null?void 0:i.quote)??"But if you don't change your direction, and if you keep looking, you may end up where you are heading."),1),w("div",Vo,[w("a",{class:"link",href:v(vn)(v(n).link),"aria-label":((l=v(e).notFound)==null?void 0:l.linkLabel)??"go to home"},Z(((c=v(e).notFound)==null?void 0:c.linkText)??"Take me home"),9,Do)])])}}}),Uo=q(Ho,[["__scopeId","data-v-46f27357"]]);function qs(t,e){if(Array.isArray(t))return sn(t);if(t==null)return[];e=Wn(e);const n=Object.keys(t).sort((s,a)=>a.split("/").length-s.split("/").length).find(s=>e.startsWith(Wn(s))),r=n?t[n]:[];return Array.isArray(r)?sn(r):sn(r.items,r.base)}function Bo(t){const e=[];let n=0;for(const r in t){const s=t[r];if(s.items){n=e.push(s);continue}e[n]||e.push({items:[]}),e[n].items.push(s)}return e}function Wo(t){const e=[];function n(r){for(const s of r)s.text&&s.link&&e.push({text:s.text,link:s.link,docFooterText:s.docFooterText}),s.items&&n(s.items)}return n(t),e}function jn(t,e){return Array.isArray(e)?e.some(n=>jn(t,n)):pt(t,e.link)?!0:e.items?jn(t,e.items):!1}function sn(t,e){return[...t].map(n=>{const r={...n},s=r.base||e;return s&&r.link&&(r.link=s+r.link),r.items&&(r.items=sn(r.items,s)),r})}function et(){const{frontmatter:t,page:e,theme:n}=se(),r=Bn("(min-width: 960px)"),s=X(!1),a=U(()=>{const g=n.value.sidebar,b=e.value.relativePath;return g?qs(g,b):[]}),o=X(a.value);pe(a,(g,b)=>{JSON.stringify(g)!==JSON.stringify(b)&&(o.value=a.value)});const i=U(()=>t.value.sidebar!==!1&&o.value.length>0&&t.value.layout!=="home"),l=U(()=>c?t.value.aside==null?n.value.aside==="left":t.value.aside==="left":!1),c=U(()=>t.value.layout==="home"?!1:t.value.aside!=null?!!t.value.aside:n.value.aside!==!1),u=U(()=>i.value&&r.value),d=U(()=>i.value?Bo(o.value):[]);function f(){s.value=!0}function y(){s.value=!1}function S(){s.value?y():f()}return{isOpen:s,sidebar:o,sidebarGroups:d,hasSidebar:i,hasAside:c,leftAside:l,isSidebarEnabled:u,open:f,close:y,toggle:S}}function jo(t,e){let n;it(()=>{n=t.value?document.activeElement:void 0}),Ye(()=>{window.addEventListener("keyup",r)}),gn(()=>{window.removeEventListener("keyup",r)});function r(s){s.key==="Escape"&&t.value&&(e(),n==null||n.focus())}}function xo(t){const{page:e,hash:n}=se(),r=X(!1),s=U(()=>t.value.collapsed!=null),a=U(()=>!!t.value.link),o=X(!1),i=()=>{o.value=pt(e.value.relativePath,t.value.link)};pe([e,t,n],i),Ye(i);const l=U(()=>o.value?!0:t.value.items?jn(e.value.relativePath,t.value.items):!1),c=U(()=>!!(t.value.items&&t.value.items.length));it(()=>{r.value=!!(s.value&&t.value.collapsed)}),mr(()=>{(o.value||l.value)&&(r.value=!1)});function u(){s.value&&(r.value=!r.value)}return{collapsed:r,collapsible:s,isLink:a,isActiveLink:o,hasActiveLink:l,hasChildren:c,toggle:u}}function Ko(){const{hasSidebar:t}=et(),e=Bn("(min-width: 960px)"),n=Bn("(min-width: 1280px)");return{isAsideEnabled:U(()=>!n.value&&!e.value?!1:t.value?n.value:e.value)}}const xn=[];function Js(t){return typeof t.outline=="object"&&!Array.isArray(t.outline)&&t.outline.label||t.outlineTitle||"On this page"}function vr(t){const e=[...document.querySelectorAll(".VPDoc :where(h1,h2,h3,h4,h5,h6)")].filter(n=>n.id&&n.hasChildNodes()).map(n=>{const r=Number(n.tagName[1]);return{element:n,title:Go(n),link:"#"+n.id,level:r}});return Yo(e,t)}function Go(t){let e="";for(const n of t.childNodes)if(n.nodeType===1){if(n.classList.contains("VPBadge")||n.classList.contains("header-anchor")||n.classList.contains("ignore-header"))continue;e+=n.textContent}else n.nodeType===3&&(e+=n.textContent);return e.trim()}function Yo(t,e){if(e===!1)return[];const n=(typeof e=="object"&&!Array.isArray(e)?e.level:e)||2,[r,s]=typeof n=="number"?[n,n]:n==="deep"?[2,6]:n;t=t.filter(o=>o.level>=r&&o.level<=s),xn.length=0;for(const{element:o,link:i}of t)xn.push({element:o,link:i});const a=[];e:for(let o=0;o=0;l--){const c=t[l];if(c.level{requestAnimationFrame(a),window.addEventListener("scroll",r)}),co(()=>{o(location.hash)}),gn(()=>{window.removeEventListener("scroll",r)});function a(){if(!n.value)return;const i=window.scrollY,l=window.innerHeight,c=document.body.offsetHeight,u=Math.abs(i+l-c)<1,d=xn.map(({element:y,link:S})=>({link:S,top:Xo(y)})).filter(({top:y})=>!Number.isNaN(y)).sort((y,S)=>y.top-S.top);if(!d.length){o(null);return}if(i<1){o(null);return}if(u){o(d[d.length-1].link);return}let f=null;for(const{link:y,top:S}of d){if(S>i+uo()+4)break;f=y}o(f)}function o(i){s&&s.classList.remove("active"),i==null?s=null:s=t.value.querySelector(`a[href="${decodeURIComponent(i)}"]`);const l=s;l?(l.classList.add("active"),e.value.style.top=l.offsetTop+39+"px",e.value.style.opacity="1"):(e.value.style.top="33px",e.value.style.opacity="0")}}function Xo(t){let e=0;for(;t!==document.body;){if(t===null)return NaN;e+=t.offsetTop,t=t.offsetParent}return e}const qo=["href","title"],Jo=R({__name:"VPDocOutlineItem",props:{headers:{},root:{type:Boolean}},setup(t){function e({target:n}){const r=n.href.split("#")[1],s=document.getElementById(decodeURIComponent(r));s==null||s.focus({preventScroll:!0})}return(n,r)=>{const s=lt("VPDocOutlineItem",!0);return _(),A("ul",{class:ue(["VPDocOutlineItem",n.root?"root":"nested"])},[(_(!0),A(he,null,Ce(n.headers,({children:a,link:o,title:i})=>(_(),A("li",null,[w("a",{class:"outline-link",href:o,onClick:e,title:i},Z(i),9,qo),a!=null&&a.length?(_(),K(s,{key:0,headers:a},null,8,["headers"])):j("",!0)]))),256))],2)}}}),Qs=q(Jo,[["__scopeId","data-v-fc78d431"]]),Qo={class:"content"},Zo={"aria-level":"2",class:"outline-title",id:"doc-outline-aria-label",role:"heading"},ei=R({__name:"VPDocAsideOutline",setup(t){const{frontmatter:e,theme:n}=se(),r=bn([]);yn(()=>{r.value=vr(e.value.outline??n.value.outline)});const s=X(),a=X();return zo(s,a),(o,i)=>(_(),A("nav",{"aria-labelledby":"doc-outline-aria-label",class:ue(["VPDocAsideOutline",{"has-outline":r.value.length>0}]),ref_key:"container",ref:s},[w("div",Qo,[w("div",{class:"outline-marker",ref_key:"marker",ref:a},null,512),w("div",Zo,Z(v(Js)(v(n))),1),x(Qs,{headers:r.value,root:!0},null,8,["headers"])])],2))}}),ti=q(ei,[["__scopeId","data-v-e95709bb"]]),ni={class:"VPDocAsideCarbonAds"},ri=R({__name:"VPDocAsideCarbonAds",props:{carbonAds:{}},setup(t){const e=()=>null;return(n,r)=>(_(),A("div",ni,[x(v(e),{"carbon-ads":n.carbonAds},null,8,["carbon-ads"])]))}}),si={class:"VPDocAside"},ai=R({__name:"VPDocAside",setup(t){const{theme:e}=se();return(n,r)=>(_(),A("div",si,[C(n.$slots,"aside-top",{},void 0,!0),C(n.$slots,"aside-outline-before",{},void 0,!0),x(ti),C(n.$slots,"aside-outline-after",{},void 0,!0),r[0]||(r[0]=w("div",{class:"spacer"},null,-1)),C(n.$slots,"aside-ads-before",{},void 0,!0),v(e).carbonAds?(_(),K(ri,{key:0,"carbon-ads":v(e).carbonAds},null,8,["carbon-ads"])):j("",!0),C(n.$slots,"aside-ads-after",{},void 0,!0),C(n.$slots,"aside-bottom",{},void 0,!0)]))}}),oi=q(ai,[["__scopeId","data-v-4bbff643"]]);function ii(){const{theme:t,page:e}=se();return U(()=>{const{text:n="Edit this page",pattern:r=""}=t.value.editLink||{};let s;return typeof r=="function"?s=r(e.value):s=r.replace(/:path/g,e.value.filePath),{url:s,text:n}})}function li(){const{page:t,theme:e,frontmatter:n}=se();return U(()=>{var c,u,d,f,y,S,g,b;const r=qs(e.value.sidebar,t.value.relativePath),s=Wo(r),a=ci(s,p=>p.link.replace(/[?#].*$/,"")),o=a.findIndex(p=>pt(t.value.relativePath,p.link)),i=((c=e.value.docFooter)==null?void 0:c.prev)===!1&&!n.value.prev||n.value.prev===!1,l=((u=e.value.docFooter)==null?void 0:u.next)===!1&&!n.value.next||n.value.next===!1;return{prev:i?void 0:{text:(typeof n.value.prev=="string"?n.value.prev:typeof n.value.prev=="object"?n.value.prev.text:void 0)??((d=a[o-1])==null?void 0:d.docFooterText)??((f=a[o-1])==null?void 0:f.text),link:(typeof n.value.prev=="object"?n.value.prev.link:void 0)??((y=a[o-1])==null?void 0:y.link)},next:l?void 0:{text:(typeof n.value.next=="string"?n.value.next:typeof n.value.next=="object"?n.value.next.text:void 0)??((S=a[o+1])==null?void 0:S.docFooterText)??((g=a[o+1])==null?void 0:g.text),link:(typeof n.value.next=="object"?n.value.next.link:void 0)??((b=a[o+1])==null?void 0:b.link)}}})}function ci(t,e){const n=new Set;return t.filter(r=>{const s=e(r);return n.has(s)?!1:n.add(s)})}const je=R({__name:"VPLink",props:{tag:{},href:{},noIcon:{type:Boolean},target:{},rel:{}},setup(t){const e=t,n=U(()=>e.tag??(e.href?"a":"span")),r=U(()=>e.href&&Bs.test(e.href)||e.target==="_blank");return(s,a)=>(_(),K(We(n.value),{class:ue(["VPLink",{link:s.href,"vp-external-link-icon":r.value,"no-icon":s.noIcon}]),href:s.href?v(_r)(s.href):void 0,target:s.target??(r.value?"_blank":void 0),rel:s.rel??(r.value?"noreferrer":void 0)},{default:M(()=>[C(s.$slots,"default")]),_:3},8,["class","href","target","rel"]))}}),ui={class:"VPLastUpdated"},di=["datetime"],fi=R({__name:"VPDocFooterLastUpdated",setup(t){const{theme:e,page:n,lang:r}=se(),s=U(()=>new Date(n.value.lastUpdated)),a=U(()=>s.value.toISOString()),o=X("");return Ye(()=>{it(()=>{var i,l,c;o.value=new Intl.DateTimeFormat((l=(i=e.value.lastUpdated)==null?void 0:i.formatOptions)!=null&&l.forceLocale?r.value:void 0,((c=e.value.lastUpdated)==null?void 0:c.formatOptions)??{dateStyle:"short",timeStyle:"short"}).format(s.value)})}),(i,l)=>{var c;return _(),A("p",ui,[Ve(Z(((c=v(e).lastUpdated)==null?void 0:c.text)||v(e).lastUpdatedText||"Last updated")+": ",1),w("time",{datetime:a.value},Z(o.value),9,di)])}}}),hi=q(fi,[["__scopeId","data-v-3c231858"]]),mi={key:0,class:"VPDocFooter"},pi={key:0,class:"edit-info"},_i={key:0,class:"edit-link"},vi={key:1,class:"last-updated"},gi={key:1,class:"prev-next","aria-labelledby":"doc-footer-aria-label"},bi={class:"pager"},yi=["innerHTML"],wi=["innerHTML"],ki={class:"pager"},Li=["innerHTML"],Si=["innerHTML"],Ei=R({__name:"VPDocFooter",setup(t){const{theme:e,page:n,frontmatter:r}=se(),s=ii(),a=li(),o=U(()=>e.value.editLink&&r.value.editLink!==!1),i=U(()=>n.value.lastUpdated),l=U(()=>o.value||i.value||a.value.prev||a.value.next);return(c,u)=>{var d,f,y,S;return l.value?(_(),A("footer",mi,[C(c.$slots,"doc-footer-before",{},void 0,!0),o.value||i.value?(_(),A("div",pi,[o.value?(_(),A("div",_i,[x(je,{class:"edit-link-button",href:v(s).url,"no-icon":!0},{default:M(()=>[u[0]||(u[0]=w("span",{class:"vpi-square-pen edit-link-icon"},null,-1)),Ve(" "+Z(v(s).text),1)]),_:1},8,["href"])])):j("",!0),i.value?(_(),A("div",vi,[x(hi)])):j("",!0)])):j("",!0),(d=v(a).prev)!=null&&d.link||(f=v(a).next)!=null&&f.link?(_(),A("nav",gi,[u[1]||(u[1]=w("span",{class:"visually-hidden",id:"doc-footer-aria-label"},"Pager",-1)),w("div",bi,[(y=v(a).prev)!=null&&y.link?(_(),K(je,{key:0,class:"pager-link prev",href:v(a).prev.link},{default:M(()=>{var g;return[w("span",{class:"desc",innerHTML:((g=v(e).docFooter)==null?void 0:g.prev)||"Previous page"},null,8,yi),w("span",{class:"title",innerHTML:v(a).prev.text},null,8,wi)]}),_:1},8,["href"])):j("",!0)]),w("div",ki,[(S=v(a).next)!=null&&S.link?(_(),K(je,{key:0,class:"pager-link next",href:v(a).next.link},{default:M(()=>{var g;return[w("span",{class:"desc",innerHTML:((g=v(e).docFooter)==null?void 0:g.next)||"Next page"},null,8,Li),w("span",{class:"title",innerHTML:v(a).next.text},null,8,Si)]}),_:1},8,["href"])):j("",!0)])])):j("",!0)])):j("",!0)}}}),Oi=q(Ei,[["__scopeId","data-v-00ab7d08"]]),Ci={class:"container"},Ai={class:"aside-container"},Ii={class:"aside-content"},Mi={class:"content"},Ni={class:"content-container"},$i={class:"main"},Pi=R({__name:"VPDoc",setup(t){const{theme:e}=se(),n=Yt(),{hasSidebar:r,hasAside:s,leftAside:a}=et(),o=U(()=>n.path.replace(/[./]+/g,"_").replace(/_html$/,""));return(i,l)=>{const c=lt("Content");return _(),A("div",{class:ue(["VPDoc",{"has-sidebar":v(r),"has-aside":v(s)}])},[C(i.$slots,"doc-top",{},void 0,!0),w("div",Ci,[v(s)?(_(),A("div",{key:0,class:ue(["aside",{"left-aside":v(a)}])},[l[0]||(l[0]=w("div",{class:"aside-curtain"},null,-1)),w("div",Ai,[w("div",Ii,[x(oi,null,{"aside-top":M(()=>[C(i.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":M(()=>[C(i.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":M(()=>[C(i.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":M(()=>[C(i.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":M(()=>[C(i.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":M(()=>[C(i.$slots,"aside-ads-after",{},void 0,!0)]),_:3})])])],2)):j("",!0),w("div",Mi,[w("div",Ni,[C(i.$slots,"doc-before",{},void 0,!0),w("main",$i,[x(c,{class:ue(["vp-doc",[o.value,v(e).externalLinkIcon&&"external-link-icon-enabled"]])},null,8,["class"])]),x(Oi,null,{"doc-footer-before":M(()=>[C(i.$slots,"doc-footer-before",{},void 0,!0)]),_:3}),C(i.$slots,"doc-after",{},void 0,!0)])])]),C(i.$slots,"doc-bottom",{},void 0,!0)],2)}}}),Ti=q(Pi,[["__scopeId","data-v-9f8645df"]]),Fi=R({__name:"VPButton",props:{tag:{},size:{default:"medium"},theme:{default:"brand"},text:{},href:{},target:{},rel:{}},setup(t){const e=t,n=U(()=>e.href&&Bs.test(e.href)),r=U(()=>e.tag||e.href?"a":"button");return(s,a)=>(_(),K(We(r.value),{class:ue(["VPButton",[s.size,s.theme]]),href:s.href?v(_r)(s.href):void 0,target:e.target??(n.value?"_blank":void 0),rel:e.rel??(n.value?"noreferrer":void 0)},{default:M(()=>[Ve(Z(s.text),1)]),_:1},8,["class","href","target","rel"]))}}),Ri=q(Fi,[["__scopeId","data-v-bbea5d5d"]]),Vi=["src","alt"],Di=R({inheritAttrs:!1,__name:"VPImage",props:{image:{},alt:{}},setup(t){return(e,n)=>{const r=lt("VPImage",!0);return e.image?(_(),A(he,{key:0},[typeof e.image=="string"||"src"in e.image?(_(),A("img",at({key:0,class:"VPImage"},typeof e.image=="string"?e.$attrs:{...e.image,...e.$attrs},{src:v(vn)(typeof e.image=="string"?e.image:e.image.src),alt:e.alt??(typeof e.image=="string"?"":e.image.alt||"")}),null,16,Vi)):(_(),A(he,{key:1},[x(r,at({class:"dark",image:e.image.dark,alt:e.image.alt},e.$attrs),null,16,["image","alt"]),x(r,at({class:"light",image:e.image.light,alt:e.image.alt},e.$attrs),null,16,["image","alt"])],64))],64)):j("",!0)}}}),un=q(Di,[["__scopeId","data-v-7b8f395d"]]),Hi={class:"container"},Ui={class:"main"},Bi={key:0,class:"name"},Wi=["innerHTML"],ji=["innerHTML"],xi=["innerHTML"],Ki={key:0,class:"actions"},Gi={key:0,class:"image"},Yi={class:"image-container"},zi=R({__name:"VPHero",props:{name:{},text:{},tagline:{},image:{},actions:{}},setup(t){const e=Nt("hero-image-slot-exists");return(n,r)=>(_(),A("div",{class:ue(["VPHero",{"has-image":n.image||v(e)}])},[w("div",Hi,[w("div",Ui,[C(n.$slots,"home-hero-info-before",{},void 0,!0),C(n.$slots,"home-hero-info",{},()=>[n.name?(_(),A("h1",Bi,[w("span",{innerHTML:n.name,class:"clip"},null,8,Wi)])):j("",!0),n.text?(_(),A("p",{key:1,innerHTML:n.text,class:"text"},null,8,ji)):j("",!0),n.tagline?(_(),A("p",{key:2,innerHTML:n.tagline,class:"tagline"},null,8,xi)):j("",!0)],!0),C(n.$slots,"home-hero-info-after",{},void 0,!0),n.actions?(_(),A("div",Ki,[(_(!0),A(he,null,Ce(n.actions,s=>(_(),A("div",{key:s.link,class:"action"},[x(Ri,{tag:"a",size:"medium",theme:s.theme,text:s.text,href:s.link,target:s.target,rel:s.rel},null,8,["theme","text","href","target","rel"])]))),128))])):j("",!0),C(n.$slots,"home-hero-actions-after",{},void 0,!0)]),n.image||v(e)?(_(),A("div",Gi,[w("div",Yi,[r[0]||(r[0]=w("div",{class:"image-bg"},null,-1)),C(n.$slots,"home-hero-image",{},()=>[n.image?(_(),K(un,{key:0,class:"image-src",image:n.image},null,8,["image"])):j("",!0)],!0)])])):j("",!0)])],2))}}),Xi=q(zi,[["__scopeId","data-v-0313f8fa"]]),qi=R({__name:"VPHomeHero",setup(t){const{frontmatter:e}=se();return(n,r)=>v(e).hero?(_(),K(Xi,{key:0,class:"VPHomeHero",name:v(e).hero.name,text:v(e).hero.text,tagline:v(e).hero.tagline,image:v(e).hero.image,actions:v(e).hero.actions},{"home-hero-info-before":M(()=>[C(n.$slots,"home-hero-info-before")]),"home-hero-info":M(()=>[C(n.$slots,"home-hero-info")]),"home-hero-info-after":M(()=>[C(n.$slots,"home-hero-info-after")]),"home-hero-actions-after":M(()=>[C(n.$slots,"home-hero-actions-after")]),"home-hero-image":M(()=>[C(n.$slots,"home-hero-image")]),_:3},8,["name","text","tagline","image","actions"])):j("",!0)}}),Ji={class:"box"},Qi={key:0,class:"icon"},Zi=["innerHTML"],el=["innerHTML"],tl=["innerHTML"],nl={key:4,class:"link-text"},rl={class:"link-text-value"},sl=R({__name:"VPFeature",props:{icon:{},title:{},details:{},link:{},linkText:{},rel:{},target:{}},setup(t){return(e,n)=>(_(),K(je,{class:"VPFeature",href:e.link,rel:e.rel,target:e.target,"no-icon":!0,tag:e.link?"a":"div"},{default:M(()=>[w("article",Ji,[typeof e.icon=="object"&&e.icon.wrap?(_(),A("div",Qi,[x(un,{image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])])):typeof e.icon=="object"?(_(),K(un,{key:1,image:e.icon,alt:e.icon.alt,height:e.icon.height||48,width:e.icon.width||48},null,8,["image","alt","height","width"])):e.icon?(_(),A("div",{key:2,class:"icon",innerHTML:e.icon},null,8,Zi)):j("",!0),w("h2",{class:"title",innerHTML:e.title},null,8,el),e.details?(_(),A("p",{key:3,class:"details",innerHTML:e.details},null,8,tl)):j("",!0),e.linkText?(_(),A("div",nl,[w("p",rl,[Ve(Z(e.linkText)+" ",1),n[0]||(n[0]=w("span",{class:"vpi-arrow-right link-text-icon"},null,-1))])])):j("",!0)])]),_:1},8,["href","rel","target","tag"]))}}),al=q(sl,[["__scopeId","data-v-ce15ebd4"]]),ol={key:0,class:"VPFeatures"},il={class:"container"},ll={class:"items"},cl=R({__name:"VPFeatures",props:{features:{}},setup(t){const e=t,n=U(()=>{const r=e.features.length;if(r){if(r===2)return"grid-2";if(r===3)return"grid-3";if(r%3===0)return"grid-6";if(r>3)return"grid-4"}else return});return(r,s)=>r.features?(_(),A("div",ol,[w("div",il,[w("div",ll,[(_(!0),A(he,null,Ce(r.features,a=>(_(),A("div",{key:a.title,class:ue(["item",[n.value]])},[x(al,{icon:a.icon,title:a.title,details:a.details,link:a.link,"link-text":a.linkText,rel:a.rel,target:a.target},null,8,["icon","title","details","link","link-text","rel","target"])],2))),128))])])])):j("",!0)}}),ul=q(cl,[["__scopeId","data-v-b79e191c"]]),dl=R({__name:"VPHomeFeatures",setup(t){const{frontmatter:e}=se();return(n,r)=>v(e).features?(_(),K(ul,{key:0,class:"VPHomeFeatures",features:v(e).features},null,8,["features"])):j("",!0)}}),fl=R({__name:"VPHomeContent",setup(t){const{width:e}=fo({initialWidth:0,includeScrollbar:!1});return(n,r)=>(_(),A("div",{class:"vp-doc container",style:Ws(v(e)?{"--vp-offset":`calc(50% - ${v(e)/2}px)`}:{})},[C(n.$slots,"default",{},void 0,!0)],4))}}),hl=q(fl,[["__scopeId","data-v-269c2bad"]]),ml={class:"VPHome"},pl=R({__name:"VPHome",setup(t){const{frontmatter:e}=se();return(n,r)=>{const s=lt("Content");return _(),A("div",ml,[C(n.$slots,"home-hero-before",{},void 0,!0),x(qi,null,{"home-hero-info-before":M(()=>[C(n.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":M(()=>[C(n.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":M(()=>[C(n.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":M(()=>[C(n.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":M(()=>[C(n.$slots,"home-hero-image",{},void 0,!0)]),_:3}),C(n.$slots,"home-hero-after",{},void 0,!0),C(n.$slots,"home-features-before",{},void 0,!0),x(dl),C(n.$slots,"home-features-after",{},void 0,!0),v(e).markdownStyles!==!1?(_(),K(hl,{key:0},{default:M(()=>[x(s)]),_:1})):(_(),K(s,{key:1}))])}}}),_l=q(pl,[["__scopeId","data-v-c1e44215"]]),vl={},gl={class:"VPPage"};function bl(t,e){const n=lt("Content");return _(),A("div",gl,[C(t.$slots,"page-top"),x(n),C(t.$slots,"page-bottom")])}const yl=q(vl,[["render",bl]]),wl=R({__name:"VPContent",setup(t){const{page:e,frontmatter:n}=se(),{hasSidebar:r}=et();return(s,a)=>(_(),A("div",{class:ue(["VPContent",{"has-sidebar":v(r),"is-home":v(n).layout==="home"}]),id:"VPContent"},[v(e).isNotFound?C(s.$slots,"not-found",{key:0},()=>[x(Uo)],!0):v(n).layout==="page"?(_(),K(yl,{key:1},{"page-top":M(()=>[C(s.$slots,"page-top",{},void 0,!0)]),"page-bottom":M(()=>[C(s.$slots,"page-bottom",{},void 0,!0)]),_:3})):v(n).layout==="home"?(_(),K(_l,{key:2},{"home-hero-before":M(()=>[C(s.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":M(()=>[C(s.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":M(()=>[C(s.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":M(()=>[C(s.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":M(()=>[C(s.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":M(()=>[C(s.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":M(()=>[C(s.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":M(()=>[C(s.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":M(()=>[C(s.$slots,"home-features-after",{},void 0,!0)]),_:3})):v(n).layout&&v(n).layout!=="doc"?(_(),K(We(v(n).layout),{key:3})):(_(),K(Ti,{key:4},{"doc-top":M(()=>[C(s.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":M(()=>[C(s.$slots,"doc-bottom",{},void 0,!0)]),"doc-footer-before":M(()=>[C(s.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":M(()=>[C(s.$slots,"doc-before",{},void 0,!0)]),"doc-after":M(()=>[C(s.$slots,"doc-after",{},void 0,!0)]),"aside-top":M(()=>[C(s.$slots,"aside-top",{},void 0,!0)]),"aside-outline-before":M(()=>[C(s.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":M(()=>[C(s.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":M(()=>[C(s.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":M(()=>[C(s.$slots,"aside-ads-after",{},void 0,!0)]),"aside-bottom":M(()=>[C(s.$slots,"aside-bottom",{},void 0,!0)]),_:3}))],2))}}),kl=q(wl,[["__scopeId","data-v-c575eed1"]]),Ll={class:"container"},Sl=["innerHTML"],El=["innerHTML"],Ol=R({__name:"VPFooter",setup(t){const{theme:e,frontmatter:n}=se(),{hasSidebar:r}=et();return(s,a)=>v(e).footer&&v(n).footer!==!1?(_(),A("footer",{key:0,class:ue(["VPFooter",{"has-sidebar":v(r)}])},[w("div",Ll,[v(e).footer.message?(_(),A("p",{key:0,class:"message",innerHTML:v(e).footer.message},null,8,Sl)):j("",!0),v(e).footer.copyright?(_(),A("p",{key:1,class:"copyright",innerHTML:v(e).footer.copyright},null,8,El)):j("",!0)])],2)):j("",!0)}}),Cl=q(Ol,[["__scopeId","data-v-042815a5"]]);function Al(){const{theme:t,frontmatter:e}=se(),n=bn([]),r=U(()=>n.value.length>0);return yn(()=>{n.value=vr(e.value.outline??t.value.outline)}),{headers:n,hasLocalNav:r}}const Il={class:"menu-text"},Ml={class:"header"},Nl={class:"outline"},$l=R({__name:"VPLocalNavOutlineDropdown",props:{headers:{},navHeight:{}},setup(t){const e=t,{theme:n}=se(),r=X(!1),s=X(0),a=X(),o=X();function i(d){var f;(f=a.value)!=null&&f.contains(d.target)||(r.value=!1)}pe(r,d=>{if(d){document.addEventListener("click",i);return}document.removeEventListener("click",i)}),ho("Escape",()=>{r.value=!1}),yn(()=>{r.value=!1});function l(){r.value=!r.value,s.value=window.innerHeight+Math.min(window.scrollY-e.navHeight,0)}function c(d){d.target.classList.contains("outline-link")&&(o.value&&(o.value.style.transition="none"),Ue(()=>{r.value=!1}))}function u(){r.value=!1,window.scrollTo({top:0,left:0,behavior:"smooth"})}return(d,f)=>(_(),A("div",{class:"VPLocalNavOutlineDropdown",style:Ws({"--vp-vh":s.value+"px"}),ref_key:"main",ref:a},[d.headers.length>0?(_(),A("button",{key:0,onClick:l,class:ue({open:r.value})},[w("span",Il,Z(v(Js)(v(n))),1),f[0]||(f[0]=w("span",{class:"vpi-chevron-right icon"},null,-1))],2)):(_(),A("button",{key:1,onClick:u},Z(v(n).returnToTopLabel||"Return to top"),1)),x(_n,{name:"flyout"},{default:M(()=>[r.value?(_(),A("div",{key:0,ref_key:"items",ref:o,class:"items",onClick:c},[w("div",Ml,[w("a",{class:"top-link",href:"#",onClick:u},Z(v(n).returnToTopLabel||"Return to top"),1)]),w("div",Nl,[x(Qs,{headers:d.headers},null,8,["headers"])])],512)):j("",!0)]),_:1})],4))}}),Pl=q($l,[["__scopeId","data-v-fd549330"]]),Tl={class:"container"},Fl=["aria-expanded"],Rl={class:"menu-text"},Vl=R({__name:"VPLocalNav",props:{open:{type:Boolean}},emits:["open-menu"],setup(t){const{theme:e,frontmatter:n}=se(),{hasSidebar:r}=et(),{headers:s}=Al(),{y:a}=js(),o=X(0);Ye(()=>{o.value=parseInt(getComputedStyle(document.documentElement).getPropertyValue("--vp-nav-height"))}),yn(()=>{s.value=vr(n.value.outline??e.value.outline)});const i=U(()=>s.value.length===0),l=U(()=>i.value&&!r.value),c=U(()=>({VPLocalNav:!0,"has-sidebar":r.value,empty:i.value,fixed:l.value}));return(u,d)=>v(n).layout!=="home"&&(!l.value||v(a)>=o.value)?(_(),A("div",{key:0,class:ue(c.value)},[w("div",Tl,[v(r)?(_(),A("button",{key:0,class:"menu","aria-expanded":u.open,"aria-controls":"VPSidebarNav",onClick:d[0]||(d[0]=f=>u.$emit("open-menu"))},[d[1]||(d[1]=w("span",{class:"vpi-align-left menu-icon"},null,-1)),w("span",Rl,Z(v(e).sidebarMenuLabel||"Menu"),1)],8,Fl)):j("",!0),x(Pl,{headers:v(s),navHeight:o.value},null,8,["headers","navHeight"])])],2)):j("",!0)}}),Dl=q(Vl,[["__scopeId","data-v-6c3804f2"]]);function Hl(){const t=X(!1);function e(){t.value=!0,window.addEventListener("resize",s)}function n(){t.value=!1,window.removeEventListener("resize",s)}function r(){t.value?n():e()}function s(){window.outerWidth>=768&&n()}const a=Yt();return pe(()=>a.path,n),{isScreenOpen:t,openScreen:e,closeScreen:n,toggleScreen:r}}const Ul={},Bl={class:"VPSwitch",type:"button",role:"switch"},Wl={class:"check"},jl={key:0,class:"icon"};function xl(t,e){return _(),A("button",Bl,[w("span",Wl,[t.$slots.default?(_(),A("span",jl,[C(t.$slots,"default",{},void 0,!0)])):j("",!0)])])}const Kl=q(Ul,[["render",xl],["__scopeId","data-v-bdb57495"]]),Gl=R({__name:"VPSwitchAppearance",setup(t){const{isDark:e,theme:n}=se(),r=Nt("toggle-appearance",()=>{e.value=!e.value}),s=X("");return mr(()=>{s.value=e.value?n.value.lightModeSwitchTitle||"Switch to light theme":n.value.darkModeSwitchTitle||"Switch to dark theme"}),(a,o)=>(_(),K(Kl,{title:s.value,class:"VPSwitchAppearance","aria-checked":v(e),onClick:v(r)},{default:M(()=>o[0]||(o[0]=[w("span",{class:"vpi-sun sun"},null,-1),w("span",{class:"vpi-moon moon"},null,-1)])),_:1},8,["title","aria-checked","onClick"]))}}),gr=q(Gl,[["__scopeId","data-v-41f06fec"]]),Yl={key:0,class:"VPNavBarAppearance"},zl=R({__name:"VPNavBarAppearance",setup(t){const{site:e}=se();return(n,r)=>v(e).appearance&&v(e).appearance!=="force-dark"&&v(e).appearance!=="force-auto"?(_(),A("div",Yl,[x(gr)])):j("",!0)}}),Xl=q(zl,[["__scopeId","data-v-12ad808b"]]),br=X();let Zs=!1,Pn=0;function ql(t){const e=X(!1);if(wn){!Zs&&Jl(),Pn++;const n=pe(br,r=>{var s,a,o;r===t.el.value||(s=t.el.value)!=null&&s.contains(r)?(e.value=!0,(a=t.onFocus)==null||a.call(t)):(e.value=!1,(o=t.onBlur)==null||o.call(t))});gn(()=>{n(),Pn--,Pn||Ql()})}return xs(e)}function Jl(){document.addEventListener("focusin",ea),Zs=!0,br.value=document.activeElement}function Ql(){document.removeEventListener("focusin",ea)}function ea(){br.value=document.activeElement}const Zl={class:"VPMenuLink"},ec=R({__name:"VPMenuLink",props:{item:{}},setup(t){const{page:e}=se();return(n,r)=>(_(),A("div",Zl,[x(je,{class:ue({active:v(pt)(v(e).relativePath,n.item.activeMatch||n.item.link,!!n.item.activeMatch)}),href:n.item.link,target:n.item.target,rel:n.item.rel},{default:M(()=>[Ve(Z(n.item.text),1)]),_:1},8,["class","href","target","rel"])]))}}),Ln=q(ec,[["__scopeId","data-v-7e61137e"]]),tc={class:"VPMenuGroup"},nc={key:0,class:"title"},rc=R({__name:"VPMenuGroup",props:{text:{},items:{}},setup(t){return(e,n)=>(_(),A("div",tc,[e.text?(_(),A("p",nc,Z(e.text),1)):j("",!0),(_(!0),A(he,null,Ce(e.items,r=>(_(),A(he,null,["link"in r?(_(),K(Ln,{key:0,item:r},null,8,["item"])):j("",!0)],64))),256))]))}}),sc=q(rc,[["__scopeId","data-v-b7ccc091"]]),ac={class:"VPMenu"},oc={key:0,class:"items"},ic=R({__name:"VPMenu",props:{items:{}},setup(t){return(e,n)=>(_(),A("div",ac,[e.items?(_(),A("div",oc,[(_(!0),A(he,null,Ce(e.items,r=>(_(),A(he,{key:JSON.stringify(r)},["link"in r?(_(),K(Ln,{key:0,item:r},null,8,["item"])):"component"in r?(_(),K(We(r.component),at({key:1,ref_for:!0},r.props),null,16)):(_(),K(sc,{key:2,text:r.text,items:r.items},null,8,["text","items"]))],64))),128))])):j("",!0),C(e.$slots,"default",{},void 0,!0)]))}}),lc=q(ic,[["__scopeId","data-v-e8a1c26e"]]),cc=["aria-expanded","aria-label"],uc={key:0,class:"text"},dc=["innerHTML"],fc={key:1,class:"vpi-more-horizontal icon"},hc={class:"menu"},mc=R({__name:"VPFlyout",props:{icon:{},button:{},label:{},items:{}},setup(t){const e=X(!1),n=X();ql({el:n,onBlur:r});function r(){e.value=!1}return(s,a)=>(_(),A("div",{class:"VPFlyout",ref_key:"el",ref:n,onMouseenter:a[1]||(a[1]=o=>e.value=!0),onMouseleave:a[2]||(a[2]=o=>e.value=!1)},[w("button",{type:"button",class:"button","aria-haspopup":"true","aria-expanded":e.value,"aria-label":s.label,onClick:a[0]||(a[0]=o=>e.value=!e.value)},[s.button||s.icon?(_(),A("span",uc,[s.icon?(_(),A("span",{key:0,class:ue([s.icon,"option-icon"])},null,2)):j("",!0),s.button?(_(),A("span",{key:1,innerHTML:s.button},null,8,dc)):j("",!0),a[3]||(a[3]=w("span",{class:"vpi-chevron-down text-icon"},null,-1))])):(_(),A("span",fc))],8,cc),w("div",hc,[x(lc,{items:s.items},{default:M(()=>[C(s.$slots,"default",{},void 0,!0)]),_:3},8,["items"])])],544))}}),yr=q(mc,[["__scopeId","data-v-7e42a472"]]),pc=["href","aria-label","innerHTML"],_c=R({__name:"VPSocialLink",props:{icon:{},link:{},ariaLabel:{}},setup(t){const e=t,n=U(()=>typeof e.icon=="object"?e.icon.svg:``);return(r,s)=>(_(),A("a",{class:"VPSocialLink no-icon",href:r.link,"aria-label":r.ariaLabel??(typeof r.icon=="string"?r.icon:""),target:"_blank",rel:"noopener",innerHTML:n.value},null,8,pc))}}),vc=q(_c,[["__scopeId","data-v-1d65eafe"]]),gc={class:"VPSocialLinks"},bc=R({__name:"VPSocialLinks",props:{links:{}},setup(t){return(e,n)=>(_(),A("div",gc,[(_(!0),A(he,null,Ce(e.links,({link:r,icon:s,ariaLabel:a})=>(_(),K(vc,{key:r,icon:s,link:r,ariaLabel:a},null,8,["icon","link","ariaLabel"]))),128))]))}}),wr=q(bc,[["__scopeId","data-v-259de3d6"]]),yc={key:0,class:"group translations"},wc={class:"trans-title"},kc={key:1,class:"group"},Lc={class:"item appearance"},Sc={class:"label"},Ec={class:"appearance-action"},Oc={key:2,class:"group"},Cc={class:"item social-links"},Ac=R({__name:"VPNavBarExtra",setup(t){const{site:e,theme:n}=se(),{localeLinks:r,currentLang:s}=zt({correspondingLink:!0}),a=U(()=>r.value.length&&s.value.label||e.value.appearance||n.value.socialLinks);return(o,i)=>a.value?(_(),K(yr,{key:0,class:"VPNavBarExtra",label:"extra navigation"},{default:M(()=>[v(r).length&&v(s).label?(_(),A("div",yc,[w("p",wc,Z(v(s).label),1),(_(!0),A(he,null,Ce(v(r),l=>(_(),K(Ln,{key:l.link,item:l},null,8,["item"]))),128))])):j("",!0),v(e).appearance&&v(e).appearance!=="force-dark"&&v(e).appearance!=="force-auto"?(_(),A("div",kc,[w("div",Lc,[w("p",Sc,Z(v(n).darkModeSwitchLabel||"Appearance"),1),w("div",Ec,[x(gr)])])])):j("",!0),v(n).socialLinks?(_(),A("div",Oc,[w("div",Cc,[x(wr,{class:"social-links-list",links:v(n).socialLinks},null,8,["links"])])])):j("",!0)]),_:1})):j("",!0)}}),Ic=q(Ac,[["__scopeId","data-v-1b59c413"]]),Mc=["aria-expanded"],Nc=R({__name:"VPNavBarHamburger",props:{active:{type:Boolean}},emits:["click"],setup(t){return(e,n)=>(_(),A("button",{type:"button",class:ue(["VPNavBarHamburger",{active:e.active}]),"aria-label":"mobile navigation","aria-expanded":e.active,"aria-controls":"VPNavScreen",onClick:n[0]||(n[0]=r=>e.$emit("click"))},n[1]||(n[1]=[w("span",{class:"container"},[w("span",{class:"top"}),w("span",{class:"middle"}),w("span",{class:"bottom"})],-1)]),10,Mc))}}),$c=q(Nc,[["__scopeId","data-v-0fa0fd27"]]),Pc=["innerHTML"],Tc=R({__name:"VPNavBarMenuLink",props:{item:{}},setup(t){const{page:e}=se();return(n,r)=>(_(),K(je,{class:ue({VPNavBarMenuLink:!0,active:v(pt)(v(e).relativePath,n.item.activeMatch||n.item.link,!!n.item.activeMatch)}),href:n.item.link,noIcon:n.item.noIcon,target:n.item.target,rel:n.item.rel,tabindex:"0"},{default:M(()=>[w("span",{innerHTML:n.item.text},null,8,Pc)]),_:1},8,["class","href","noIcon","target","rel"]))}}),Fc=q(Tc,[["__scopeId","data-v-e692fe86"]]),Rc=R({__name:"VPNavBarMenuGroup",props:{item:{}},setup(t){const e=t,{page:n}=se(),r=a=>"component"in a?!1:"link"in a?pt(n.value.relativePath,a.link,!!e.item.activeMatch):a.items.some(r),s=U(()=>r(e.item));return(a,o)=>(_(),K(yr,{class:ue({VPNavBarMenuGroup:!0,active:v(pt)(v(n).relativePath,a.item.activeMatch,!!a.item.activeMatch)||s.value}),button:a.item.text,items:a.item.items},null,8,["class","button","items"]))}}),Vc={key:0,"aria-labelledby":"main-nav-aria-label",class:"VPNavBarMenu"},Dc=R({__name:"VPNavBarMenu",setup(t){const{theme:e}=se();return(n,r)=>v(e).nav?(_(),A("nav",Vc,[r[0]||(r[0]=w("span",{id:"main-nav-aria-label",class:"visually-hidden"}," Main Navigation ",-1)),(_(!0),A(he,null,Ce(v(e).nav,s=>(_(),A(he,{key:JSON.stringify(s)},["link"in s?(_(),K(Fc,{key:0,item:s},null,8,["item"])):"component"in s?(_(),K(We(s.component),at({key:1,ref_for:!0},s.props),null,16)):(_(),K(Rc,{key:2,item:s},null,8,["item"]))],64))),128))])):j("",!0)}}),Hc=q(Dc,[["__scopeId","data-v-30753f5b"]]);var Nr;const ta=typeof window<"u",Uc=t=>typeof t=="string",an=()=>{};ta&&((Nr=window==null?void 0:window.navigator)!=null&&Nr.userAgent)&&/iP(ad|hone|od)/.test(window.navigator.userAgent);function Kn(t){return typeof t=="function"?t():v(t)}function Bc(t,e){function n(...r){t(()=>e.apply(this,r),{fn:e,thisArg:this,args:r})}return n}function Wc(t,e={}){let n,r;return s=>{const a=Kn(t),o=Kn(e.maxWait);if(n&&clearTimeout(n),a<=0||o!==void 0&&o<=0)return r&&(clearTimeout(r),r=null),s();o&&!r&&(r=setTimeout(()=>{n&&clearTimeout(n),r=null,s()},o)),n=setTimeout(()=>{r&&clearTimeout(r),r=null,s()},a)}}function jc(t){return t}function xc(t){return Ys()?(zs(t),!0):!1}function na(t,e=200,n={}){return Bc(Wc(e,n),t)}function Tn(t,e=200,n={}){if(e<=0)return t;const r=X(t.value),s=na(()=>{r.value=t.value},e,n);return pe(t,()=>s()),r}function ra(t,e,n){return pe(t,(r,s,a)=>{r&&e(r,s,a)},n)}function Kc(t){var e;const n=Kn(t);return(e=n==null?void 0:n.$el)!=null?e:n}const sa=ta?window:void 0;function en(...t){let e,n,r,s;if(Uc(t[0])?([n,r,s]=t,e=sa):[e,n,r,s]=t,!e)return an;let a=an;const o=pe(()=>Kc(e),l=>{a(),l&&(l.addEventListener(n,r,s),a=()=>{l.removeEventListener(n,r,s),a=an})},{immediate:!0,flush:"post"}),i=()=>{o(),a()};return xc(i),i}const $r=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},Pr="__vueuse_ssr_handlers__";$r[Pr]=$r[Pr]||{};const Gc={ctrl:"control",command:"meta",cmd:"meta",option:"alt",up:"arrowup",down:"arrowdown",left:"arrowleft",right:"arrowright"};function Yc(t={}){const{reactive:e=!1,target:n=sa,aliasMap:r=Gc,passive:s=!0,onEventFired:a=an}=t,o=Bt(new Set),i={toJSON(){return{}},current:o},l=e?Bt(i):i,c=new Set,u=new Set;function d(g,b){g in l&&(e?l[g]=b:l[g].value=b)}function f(){for(const g of u)d(g,!1)}function y(g,b){var p,E;const I=(p=g.key)==null?void 0:p.toLowerCase(),L=[(E=g.code)==null?void 0:E.toLowerCase(),I].filter(Boolean);I&&(b?o.add(I):o.delete(I));for(const P of L)u.add(P),d(P,b);I==="meta"&&!b?(c.forEach(P=>{o.delete(P),d(P,!1)}),c.clear()):typeof g.getModifierState=="function"&&g.getModifierState("Meta")&&b&&[...o,...L].forEach(P=>c.add(P))}en(n,"keydown",g=>(y(g,!0),a(g)),{passive:s}),en(n,"keyup",g=>(y(g,!1),a(g)),{passive:s}),en("blur",f,{passive:!0}),en("focus",f,{passive:!0});const S=new Proxy(l,{get(g,b,p){if(typeof b!="string")return Reflect.get(g,b,p);if(b=b.toLowerCase(),b in r&&(b=r[b]),!(b in l))if(/[+_-]/.test(b)){const I=b.split(/[+_-]/g).map(L=>L.trim());l[b]=U(()=>I.every(L=>v(S[L])))}else l[b]=X(!1);const E=Reflect.get(g,b,p);return e?v(E):E}});return S}var Tr;(function(t){t.UP="UP",t.RIGHT="RIGHT",t.DOWN="DOWN",t.LEFT="LEFT",t.NONE="NONE"})(Tr||(Tr={}));var zc=Object.defineProperty,Fr=Object.getOwnPropertySymbols,Xc=Object.prototype.hasOwnProperty,qc=Object.prototype.propertyIsEnumerable,Rr=(t,e,n)=>e in t?zc(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,Jc=(t,e)=>{for(var n in e||(e={}))Xc.call(e,n)&&Rr(t,n,e[n]);if(Fr)for(var n of Fr(e))qc.call(e,n)&&Rr(t,n,e[n]);return t};const Qc={easeInSine:[.12,0,.39,0],easeOutSine:[.61,1,.88,1],easeInOutSine:[.37,0,.63,1],easeInQuad:[.11,0,.5,0],easeOutQuad:[.5,1,.89,1],easeInOutQuad:[.45,0,.55,1],easeInCubic:[.32,0,.67,0],easeOutCubic:[.33,1,.68,1],easeInOutCubic:[.65,0,.35,1],easeInQuart:[.5,0,.75,0],easeOutQuart:[.25,1,.5,1],easeInOutQuart:[.76,0,.24,1],easeInQuint:[.64,0,.78,0],easeOutQuint:[.22,1,.36,1],easeInOutQuint:[.83,0,.17,1],easeInExpo:[.7,0,.84,0],easeOutExpo:[.16,1,.3,1],easeInOutExpo:[.87,0,.13,1],easeInCirc:[.55,0,1,.45],easeOutCirc:[0,.55,.45,1],easeInOutCirc:[.85,0,.15,1],easeInBack:[.36,0,.66,-.56],easeOutBack:[.34,1.56,.64,1],easeInOutBack:[.68,-.6,.32,1.6]};Jc({linear:jc},Qc);function Ze(t){return Array.isArray?Array.isArray(t):ia(t)==="[object Array]"}const Zc=1/0;function eu(t){if(typeof t=="string")return t;let e=t+"";return e=="0"&&1/t==-Zc?"-0":e}function tu(t){return t==null?"":eu(t)}function Be(t){return typeof t=="string"}function aa(t){return typeof t=="number"}function nu(t){return t===!0||t===!1||ru(t)&&ia(t)=="[object Boolean]"}function oa(t){return typeof t=="object"}function ru(t){return oa(t)&&t!==null}function $e(t){return t!=null}function Fn(t){return!t.trim().length}function ia(t){return t==null?t===void 0?"[object Undefined]":"[object Null]":Object.prototype.toString.call(t)}const su="Incorrect 'index' type",au=t=>`Invalid value for key ${t}`,ou=t=>`Pattern length exceeds max of ${t}.`,iu=t=>`Missing ${t} property in key`,lu=t=>`Property 'weight' in key '${t}' must be a positive integer`,Vr=Object.prototype.hasOwnProperty;class cu{constructor(e){this._keys=[],this._keyMap={};let n=0;e.forEach(r=>{let s=la(r);n+=s.weight,this._keys.push(s),this._keyMap[s.id]=s,n+=s.weight}),this._keys.forEach(r=>{r.weight/=n})}get(e){return this._keyMap[e]}keys(){return this._keys}toJSON(){return JSON.stringify(this._keys)}}function la(t){let e=null,n=null,r=null,s=1,a=null;if(Be(t)||Ze(t))r=t,e=Dr(t),n=Gn(t);else{if(!Vr.call(t,"name"))throw new Error(iu("name"));const o=t.name;if(r=o,Vr.call(t,"weight")&&(s=t.weight,s<=0))throw new Error(lu(o));e=Dr(o),n=Gn(o),a=t.getFn}return{path:e,id:n,weight:s,src:r,getFn:a}}function Dr(t){return Ze(t)?t:t.split(".")}function Gn(t){return Ze(t)?t.join("."):t}function uu(t,e){let n=[],r=!1;const s=(a,o,i)=>{if($e(a))if(!o[i])n.push(a);else{let l=o[i];const c=a[l];if(!$e(c))return;if(i===o.length-1&&(Be(c)||aa(c)||nu(c)))n.push(tu(c));else if(Ze(c)){r=!0;for(let u=0,d=c.length;ut.score===e.score?t.idx{this._keysMap[n.id]=r})}create(){this.isCreated||!this.docs.length||(this.isCreated=!0,Be(this.docs[0])?this.docs.forEach((e,n)=>{this._addString(e,n)}):this.docs.forEach((e,n)=>{this._addObject(e,n)}),this.norm.clear())}add(e){const n=this.size();Be(e)?this._addString(e,n):this._addObject(e,n)}removeAt(e){this.records.splice(e,1);for(let n=e,r=this.size();n{let o=s.getFn?s.getFn(e):this.getFn(e,s.path);if($e(o)){if(Ze(o)){let i=[];const l=[{nestedArrIndex:-1,value:o}];for(;l.length;){const{nestedArrIndex:c,value:u}=l.pop();if($e(u))if(Be(u)&&!Fn(u)){let d={v:u,i:c,n:this.norm.get(u)};i.push(d)}else Ze(u)&&u.forEach((d,f)=>{l.push({nestedArrIndex:f,value:d})})}r.$[a]=i}else if(Be(o)&&!Fn(o)){let i={v:o,n:this.norm.get(o)};r.$[a]=i}}}),this.records.push(r)}toJSON(){return{keys:this.keys,records:this.records}}}function ca(t,e,{getFn:n=Q.getFn,fieldNormWeight:r=Q.fieldNormWeight}={}){const s=new kr({getFn:n,fieldNormWeight:r});return s.setKeys(t.map(la)),s.setSources(e),s.create(),s}function vu(t,{getFn:e=Q.getFn,fieldNormWeight:n=Q.fieldNormWeight}={}){const{keys:r,records:s}=t,a=new kr({getFn:e,fieldNormWeight:n});return a.setKeys(r),a.setIndexRecords(s),a}function tn(t,{errors:e=0,currentLocation:n=0,expectedLocation:r=0,distance:s=Q.distance,ignoreLocation:a=Q.ignoreLocation}={}){const o=e/t.length;if(a)return o;const i=Math.abs(r-n);return s?o+i/s:i?1:o}function gu(t=[],e=Q.minMatchCharLength){let n=[],r=-1,s=-1,a=0;for(let o=t.length;a=e&&n.push([r,s]),r=-1)}return t[a-1]&&a-r>=e&&n.push([r,a-1]),n}const ht=32;function bu(t,e,n,{location:r=Q.location,distance:s=Q.distance,threshold:a=Q.threshold,findAllMatches:o=Q.findAllMatches,minMatchCharLength:i=Q.minMatchCharLength,includeMatches:l=Q.includeMatches,ignoreLocation:c=Q.ignoreLocation}={}){if(e.length>ht)throw new Error(ou(ht));const u=e.length,d=t.length,f=Math.max(0,Math.min(r,d));let y=a,S=f;const g=i>1||l,b=g?Array(d):[];let p;for(;(p=t.indexOf(e,S))>-1;){let N=tn(e,{currentLocation:p,expectedLocation:f,distance:s,ignoreLocation:c});if(y=Math.min(N,y),S=p+u,g){let B=0;for(;B=le;_e-=1){let Ne=_e-1,Te=n[t.charAt(Ne)];if(g&&(b[Ne]=+!!Te),ae[_e]=(ae[_e+1]<<1|1)&Te,N&&(ae[_e]|=(E[_e+1]|E[_e])<<1|1|E[_e+1]),ae[_e]&P&&(I=tn(e,{errors:N,currentLocation:Ne,expectedLocation:f,distance:s,ignoreLocation:c}),I<=y)){if(y=I,S=Ne,S<=f)break;le=Math.max(1,2*f-S)}}if(tn(e,{errors:N+1,currentLocation:f,expectedLocation:f,distance:s,ignoreLocation:c})>y)break;E=ae}const T={isMatch:S>=0,score:Math.max(.001,I)};if(g){const N=gu(b,i);N.length?l&&(T.indices=N):T.isMatch=!1}return T}function yu(t){let e={};for(let n=0,r=t.length;n{this.chunks.push({pattern:f,alphabet:yu(f),startIndex:y})},d=this.pattern.length;if(d>ht){let f=0;const y=d%ht,S=d-y;for(;f{const{isMatch:p,score:E,indices:I}=bu(e,S,g,{location:s+b,distance:a,threshold:o,findAllMatches:i,minMatchCharLength:l,includeMatches:r,ignoreLocation:c});p&&(f=!0),d+=E,p&&I&&(u=[...u,...I])});let y={isMatch:f,score:f?d/this.chunks.length:1};return f&&r&&(y.indices=u),y}}class ct{constructor(e){this.pattern=e}static isMultiMatch(e){return Hr(e,this.multiRegex)}static isSingleMatch(e){return Hr(e,this.singleRegex)}search(){}}function Hr(t,e){const n=t.match(e);return n?n[1]:null}class wu extends ct{constructor(e){super(e)}static get type(){return"exact"}static get multiRegex(){return/^="(.*)"$/}static get singleRegex(){return/^=(.*)$/}search(e){const n=e===this.pattern;return{isMatch:n,score:n?0:1,indices:[0,this.pattern.length-1]}}}class ku extends ct{constructor(e){super(e)}static get type(){return"inverse-exact"}static get multiRegex(){return/^!"(.*)"$/}static get singleRegex(){return/^!(.*)$/}search(e){const n=e.indexOf(this.pattern)===-1;return{isMatch:n,score:n?0:1,indices:[0,e.length-1]}}}class Lu extends ct{constructor(e){super(e)}static get type(){return"prefix-exact"}static get multiRegex(){return/^\^"(.*)"$/}static get singleRegex(){return/^\^(.*)$/}search(e){const n=e.startsWith(this.pattern);return{isMatch:n,score:n?0:1,indices:[0,this.pattern.length-1]}}}class Su extends ct{constructor(e){super(e)}static get type(){return"inverse-prefix-exact"}static get multiRegex(){return/^!\^"(.*)"$/}static get singleRegex(){return/^!\^(.*)$/}search(e){const n=!e.startsWith(this.pattern);return{isMatch:n,score:n?0:1,indices:[0,e.length-1]}}}class Eu extends ct{constructor(e){super(e)}static get type(){return"suffix-exact"}static get multiRegex(){return/^"(.*)"\$$/}static get singleRegex(){return/^(.*)\$$/}search(e){const n=e.endsWith(this.pattern);return{isMatch:n,score:n?0:1,indices:[e.length-this.pattern.length,e.length-1]}}}class Ou extends ct{constructor(e){super(e)}static get type(){return"inverse-suffix-exact"}static get multiRegex(){return/^!"(.*)"\$$/}static get singleRegex(){return/^!(.*)\$$/}search(e){const n=!e.endsWith(this.pattern);return{isMatch:n,score:n?0:1,indices:[0,e.length-1]}}}class da extends ct{constructor(e,{location:n=Q.location,threshold:r=Q.threshold,distance:s=Q.distance,includeMatches:a=Q.includeMatches,findAllMatches:o=Q.findAllMatches,minMatchCharLength:i=Q.minMatchCharLength,isCaseSensitive:l=Q.isCaseSensitive,ignoreLocation:c=Q.ignoreLocation}={}){super(e),this._bitapSearch=new ua(e,{location:n,threshold:r,distance:s,includeMatches:a,findAllMatches:o,minMatchCharLength:i,isCaseSensitive:l,ignoreLocation:c})}static get type(){return"fuzzy"}static get multiRegex(){return/^"(.*)"$/}static get singleRegex(){return/^(.*)$/}search(e){return this._bitapSearch.searchIn(e)}}class fa extends ct{constructor(e){super(e)}static get type(){return"include"}static get multiRegex(){return/^'"(.*)"$/}static get singleRegex(){return/^'(.*)$/}search(e){let n=0,r;const s=[],a=this.pattern.length;for(;(r=e.indexOf(this.pattern,n))>-1;)n=r+a,s.push([r,n-1]);const o=!!s.length;return{isMatch:o,score:o?0:1,indices:s}}}const Yn=[wu,fa,Lu,Su,Ou,Eu,ku,da],Ur=Yn.length,Cu=/ +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,Au="|";function Iu(t,e={}){return t.split(Au).map(n=>{let r=n.trim().split(Cu).filter(a=>a&&!!a.trim()),s=[];for(let a=0,o=r.length;a!!(t[dn.AND]||t[dn.OR]),Pu=t=>!!t[qn.PATH],Tu=t=>!Ze(t)&&oa(t)&&!Jn(t),Br=t=>({[dn.AND]:Object.keys(t).map(e=>({[e]:t[e]}))});function ha(t,e,{auto:n=!0}={}){const r=s=>{let a=Object.keys(s);const o=Pu(s);if(!o&&a.length>1&&!Jn(s))return r(Br(s));if(Tu(s)){const l=o?s[qn.PATH]:a[0],c=o?s[qn.PATTERN]:s[l];if(!Be(c))throw new Error(au(l));const u={keyId:Gn(l),pattern:c};return n&&(u.searcher=Xn(c,e)),u}let i={children:[],operator:a[0]};return a.forEach(l=>{const c=s[l];Ze(c)&&c.forEach(u=>{i.children.push(r(u))})}),i};return Jn(t)||(t=Br(t)),r(t)}function Fu(t,{ignoreFieldNorm:e=Q.ignoreFieldNorm}){t.forEach(n=>{let r=1;n.matches.forEach(({key:s,norm:a,score:o})=>{const i=s?s.weight:null;r*=Math.pow(o===0&&i?Number.EPSILON:o,(i||1)*(e?1:a))}),n.score=r})}function Ru(t,e){const n=t.matches;e.matches=[],$e(n)&&n.forEach(r=>{if(!$e(r.indices)||!r.indices.length)return;const{indices:s,value:a}=r;let o={indices:s,value:a};r.key&&(o.key=r.key.src),r.idx>-1&&(o.refIndex=r.idx),e.matches.push(o)})}function Vu(t,e){e.score=t.score}function Du(t,e,{includeMatches:n=Q.includeMatches,includeScore:r=Q.includeScore}={}){const s=[];return n&&s.push(Ru),r&&s.push(Vu),t.map(a=>{const{idx:o}=a,i={item:e[o],refIndex:o};return s.length&&s.forEach(l=>{l(a,i)}),i})}class _t{constructor(e,n={},r){this.options={...Q,...n},this.options.useExtendedSearch,this._keyStore=new cu(this.options.keys),this.setCollection(e,r)}setCollection(e,n){if(this._docs=e,n&&!(n instanceof kr))throw new Error(su);this._myIndex=n||ca(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}add(e){!$e(e)||(this._docs.push(e),this._myIndex.add(e))}remove(e=()=>!1){const n=[];for(let r=0,s=this._docs.length;r-1&&(l=l.slice(0,n)),Du(l,this._docs,{includeMatches:r,includeScore:s})}_searchStringList(e){const n=Xn(e,this.options),{records:r}=this._myIndex,s=[];return r.forEach(({v:a,i:o,n:i})=>{if(!$e(a))return;const{isMatch:l,score:c,indices:u}=n.searchIn(a);l&&s.push({item:a,idx:o,matches:[{score:c,value:a,norm:i,indices:u}]})}),s}_searchLogical(e){const n=ha(e,this.options),r=(i,l,c)=>{if(!i.children){const{keyId:d,searcher:f}=i,y=this._findMatches({key:this._keyStore.get(d),value:this._myIndex.getValueForItemAtKeyId(l,d),searcher:f});return y&&y.length?[{idx:c,item:l,matches:y}]:[]}const u=[];for(let d=0,f=i.children.length;d{if($e(i)){let c=r(n,i,l);c.length&&(a[l]||(a[l]={idx:l,item:i,matches:[]},o.push(a[l])),c.forEach(({matches:u})=>{a[l].matches.push(...u)}))}}),o}_searchObjectList(e){const n=Xn(e,this.options),{keys:r,records:s}=this._myIndex,a=[];return s.forEach(({$:o,i})=>{if(!$e(o))return;let l=[];r.forEach((c,u)=>{l.push(...this._findMatches({key:c,value:o[u],searcher:n}))}),l.length&&a.push({idx:i,item:o,matches:l})}),a}_findMatches({key:e,value:n,searcher:r}){if(!$e(n))return[];let s=[];if(Ze(n))n.forEach(({v:a,i:o,n:i})=>{if(!$e(a))return;const{isMatch:l,score:c,indices:u}=r.searchIn(a);l&&s.push({score:c,key:e,value:a,idx:o,norm:i,indices:u})});else{const{v:a,n:o}=n,{isMatch:i,score:l,indices:c}=r.searchIn(a);i&&s.push({score:l,key:e,value:a,norm:o,indices:c})}return s}}_t.version="6.6.2";_t.createIndex=ca;_t.parseIndex=vu;_t.config=Q;_t.parseQuery=ha;$u(Nu);const Wr=Bt({selectedNode:"",selectedGroup:"",search:"",dataValue:"",filtered:{count:0,items:new Map,groups:new Set}}),$t=()=>({isSearching:U(()=>Wr.search!==""),...po(Wr)});function Hu(t){return{all:t=t||new Map,on:function(e,n){var r=t.get(e);r?r.push(n):t.set(e,[n])},off:function(e,n){var r=t.get(e);r&&(n?r.splice(r.indexOf(n)>>>0,1):t.set(e,[]))},emit:function(e,n){var r=t.get(e);r&&r.slice().map(function(s){s(n)}),(r=t.get("*"))&&r.slice().map(function(s){s(e,n)})}}}const Uu=Hu(),Sn=()=>({emitter:Uu});function Bu(t,e){let n=t.nextElementSibling;for(;n;){if(n.matches(e))return n;n=n.nextElementSibling}}function Wu(t,e){let n=t.previousElementSibling;for(;n;){if(n.matches(e))return n;n=n.previousElementSibling}}const ju=["command-theme"],xu={"command-root":""},Ku=R({name:"Command"}),Gu=R({...Ku,props:{theme:{type:String,default:"default"},fuseOptions:{type:Object,default:()=>({threshold:.2,keys:["label"]})}},emits:["select-item"],setup(t,{emit:e}){const n=t,r='[command-item=""]',s="command-item-key",a='[command-group=""]',o="command-group-key",i='[command-group-heading=""]',l=`${r}:not([aria-disabled="true"])`,c=`${r}[aria-selected="true"]`,u="command-item-select",d="data-value";pr("theme",n.theme||"default");const{selectedNode:f,search:y,dataValue:S,filtered:g}=$t(),{emitter:b}=Sn(),p=X(),E=Tn(X(new Map),333),I=Tn(X(new Set),333),L=Tn(X(new Map)),P=U(()=>{const V=[];for(const[re,Y]of E.value.entries())V.push({key:re,label:Y});return V}),T=U(()=>{const V=_t.createIndex(n.fuseOptions.keys,P.value);return new _t(P.value,n.fuseOptions,V)}),N=()=>{var V,re,Y;const oe=B();oe&&(((V=oe.parentElement)==null?void 0:V.firstElementChild)===oe&&((Y=(re=oe.closest(a))==null?void 0:re.querySelector(i))==null||Y.scrollIntoView({block:"nearest"})),oe.scrollIntoView({block:"nearest"}))},B=()=>{var V;return(V=p.value)==null?void 0:V.querySelector(c)},G=(V=p.value)=>{const re=V==null?void 0:V.querySelectorAll(l);return re?Array.from(re):[]},le=()=>{var V;const re=(V=p.value)==null?void 0:V.querySelectorAll(a);return re?Array.from(re):[]},ge=()=>{const[V]=G();V&&V.getAttribute(s)&&(f.value=V.getAttribute(s)||"")},ae=V=>{const re=G()[V];re&&(f.value=re.getAttribute(s)||"")},_e=V=>{const re=B(),Y=G(),oe=Y.findIndex(Se=>Se===re),Le=Y[oe+V];Le?f.value=Le.getAttribute(s)||"":V>0?ae(0):ae(Y.length-1)},Ne=V=>{const re=B();let Y=re==null?void 0:re.closest(a),oe=null;for(;Y&&!oe;)Y=V>0?Bu(Y,a):Wu(Y,a),oe=Y==null?void 0:Y.querySelector(l);oe?f.value=oe.getAttribute(s)||"":_e(V)},Te=()=>ae(0),tt=()=>ae(G().length-1),De=V=>{V.preventDefault(),V.metaKey?tt():V.altKey?Ne(1):_e(1)},nt=V=>{V.preventDefault(),V.metaKey?Te():V.altKey?Ne(-1):_e(-1)},Ee=V=>{switch(V.key){case"n":case"j":{V.ctrlKey&&De(V);break}case"ArrowDown":{De(V);break}case"p":case"k":{V.ctrlKey&&nt(V);break}case"ArrowUp":{nt(V);break}case"Home":{Te();break}case"End":{tt();break}case"Enter":{const re=B();if(re){const Y=new Event(u);re.dispatchEvent(Y)}}}},rt=()=>{if(!y.value){g.value.count=I.value.size;return}g.value.groups=new Set("");const V=new Map,re=T.value.search(y.value).map(Y=>Y.item);for(const{key:Y,label:oe}of re)V.set(Y,oe);for(const[Y,oe]of L.value)for(const Le of oe)V.get(Le)&&g.value.groups.add(Y);Ue(()=>{g.value.count=V.size,g.value.items=V})},J=()=>{const V=G(),re=le();for(const Y of V){const oe=Y.getAttribute(s)||"",Le=Y.getAttribute(d)||"";I.value.add(oe),E.value.set(oe,Le),g.value.count=E.value.size}for(const Y of re){const oe=G(Y),Le=Y.getAttribute(o)||"",Se=new Set("");for(const vt of oe){const Fe=vt.getAttribute(s)||"";Se.add(Fe)}L.value.set(Le,Se)}};pe(()=>f.value,V=>{V&&Ue(N)},{deep:!0}),pe(()=>y.value,V=>{rt(),Ue(ge)}),b.on("selectItem",V=>{e("select-item",V)});const te=na(V=>{V&&(J(),Ue(ge))},100);return b.on("rerenderList",te),Ye(()=>{J(),ge()}),(V,re)=>(_(),A("div",{class:ue(t.theme),onKeydown:Ee,ref_key:"commandRef",ref:p,"command-theme":t.theme},[w("div",xu,[C(V.$slots,"default")])],42,ju))}}),Pt=(t,e)=>{const n=t.__vccOpts||t;for(const[r,s]of e)n[r]=s;return n},Qn=Pt(Gu,[["__file","/Users/xiaoyunwei/Documents/GitHub/oss/vue-command-palette/packages/Command.vue"]]),Yu={"command-dialog":""},zu={"command-dialog-mask":""},Xu={"command-dialog-wrapper":""},qu={"command-dialog-header":""},Ju={"command-dialog-body":""},Qu={key:0,"command-dialog-footer":""},Zu=R({name:"Command.Dialog"}),ed=R({...Zu,props:{visible:{type:Boolean,required:!0},theme:{type:String,required:!0}},emits:["select-item"],setup(t,{emit:e}){const n=t,{search:r,filtered:s}=$t(),{emitter:a}=Sn(),o=X();a.on("selectItem",l=>{e("select-item",l)});const i=()=>{r.value="",s.value.count=0,s.value.items=new Map,s.value.groups=new Set};return ra(()=>n.visible,i),kn(i),(l,c)=>(_(),K(mo,{to:"body",ref_key:"dialogRef",ref:o},[x(_n,{name:"command-dialog",appear:""},{default:M(()=>[t.visible?(_(),K(Qn,{key:0,theme:t.theme},{default:M(()=>[w("div",Yu,[w("div",zu,[w("div",Xu,[w("div",qu,[C(l.$slots,"header")]),w("div",Ju,[C(l.$slots,"body")]),l.$slots.footer?(_(),A("div",Qu,[C(l.$slots,"footer")])):j("v-if",!0)])])])]),_:3},8,["theme"])):j("v-if",!0)]),_:3})],512))}}),td=Pt(ed,[["__file","/Users/xiaoyunwei/Documents/GitHub/oss/vue-command-palette/packages/CommandDialog.vue"]]);let ma=(t=21)=>crypto.getRandomValues(new Uint8Array(t)).reduce((e,n)=>(n&=63,n<36?e+=n.toString(36):n<62?e+=(n-26).toString(36).toUpperCase():n>62?e+="-":e+="_",e),"");const nd=["command-group-key","data-value"],rd={key:0,"command-group-heading":""},sd={"command-group-items":"",role:"group"},ad=R({name:"Command.Group"}),od=R({...ad,props:{heading:{type:String,required:!0}},setup(t){const e=U(()=>`command-group-${ma()}`),{filtered:n,isSearching:r}=$t(),s=U(()=>r.value?n.value.groups.has(e.value):!0);return(a,o)=>Ks((_(),A("div",{"command-group":"",role:"presentation",key:v(e),"command-group-key":v(e),"data-value":t.heading},[t.heading?(_(),A("div",rd,Z(t.heading),1)):j("v-if",!0),w("div",sd,[C(a.$slots,"default")])],8,nd)),[[Gs,v(s)]])}}),id=Pt(od,[["__file","/Users/xiaoyunwei/Documents/GitHub/oss/vue-command-palette/packages/CommandGroup.vue"]]),ld=["placeholder","value"],cd=R({name:"Command.Input"}),ud=R({...cd,props:{placeholder:{type:String,required:!0},value:{type:String,required:!1}},emits:["input","update:value"],setup(t,{emit:e}){const n=X(null),{search:r}=$t(),s=U(()=>r.value),a=o=>{const i=o,l=o.target;r.value=l==null?void 0:l.value,e("input",i),e("update:value",r.value)};return it(()=>{var o;(o=n.value)==null||o.focus()}),(o,i)=>(_(),A("input",{ref_key:"inputRef",ref:n,"command-input":"","auto-focus":"","auto-complete":"off","auto-correct":"off","spell-check":!1,"aria-autocomplete":"list",role:"combobox","aria-expanded":!0,placeholder:t.placeholder,value:v(s),onInput:a},null,40,ld))}}),dd=Pt(ud,[["__file","/Users/xiaoyunwei/Documents/GitHub/oss/vue-command-palette/packages/CommandInput.vue"]]),fd=["aria-selected","aria-disabled","command-item-key"],hd=R({name:"Command.Item"}),md=R({...hd,props:{shortcut:{type:Array,required:!1},perform:{type:null,required:!1}},emits:["select"],setup(t,{emit:e}){const n=t,r="command-item-select",s="data-value",{current:a}=Yc(),{selectedNode:o,filtered:i,isSearching:l}=$t(),{emitter:c}=Sn(),u=X(),d=U(()=>`command-item-${ma()}`),f=U(()=>{const g=i.value.items.get(d.value);return l.value?g!==void 0:!0}),y=U(()=>Array.from(a)),S=()=>{var g;const b={key:d.value,value:((g=u.value)==null?void 0:g.getAttribute(s))||""};e("select",b),c.emit("selectItem",b)};return ra(y,g=>{n.shortcut&&n.shortcut.length>0&&n.shortcut.every(b=>a.has(b.toLowerCase()))&&n.perform&&n.perform()}),it(()=>{var g;(g=u.value)==null||g.addEventListener(r,S)}),kn(()=>{var g;(g=u.value)==null||g.removeEventListener(r,S)}),(g,b)=>Ks((_(),A("div",{ref_key:"itemRef",ref:u,"command-item":"",role:"option","aria-selected":v(o)===v(d),"aria-disabled":!v(f),key:v(d),"command-item-key":v(d),onClick:S},[C(g.$slots,"default")],8,fd)),[[Gs,v(f)]])}}),pd=Pt(md,[["__file","/Users/xiaoyunwei/Documents/GitHub/oss/vue-command-palette/packages/CommandItem.vue"]]),_d=R({name:"Command.List"}),vd=R({..._d,setup(t){const{emitter:e}=Sn(),n=X(),r=X();let s=null,a;return it(()=>{a=r.value;const o=n.value;a&&o&&(s=new ResizeObserver(i=>{Ue(()=>{const l=a==null?void 0:a.offsetHeight;o==null||o.style.setProperty("--command-list-height",`${l==null?void 0:l.toFixed(1)}px`),e.emit("rerenderList",!0)})}),s.observe(a))}),kn(()=>{s!==null&&a&&s.unobserve(a)}),(o,i)=>(_(),A("div",{"command-list":"",role:"listbox","aria-label":"Suggestions",ref_key:"listRef",ref:n},[w("div",{"command-list-sizer":"",ref_key:"heightRef",ref:r},[C(o.$slots,"default")],512)],512))}}),gd=Pt(vd,[["__file","/Users/xiaoyunwei/Documents/GitHub/oss/vue-command-palette/packages/CommandList.vue"]]),bd=R({name:"Command.Empty",setup(t,{attrs:e,slots:n}){const{filtered:r}=$t(),s=U(()=>r.value.count===0);return()=>s.value?Ct("div",{"command-empty":"",role:"presentation",...e},n):Ct("div",{"command-empty":"hidden",role:"presentation",style:{display:"none"},...e})}}),yd=R({name:"Command.Loading",setup(t,{attrs:e,slots:n}){return()=>Ct("div",{"command-loading":"",role:"progressbar",...e},n)}}),wd=R({name:"Command.Separator",setup(t,{attrs:e,slots:n}){return()=>Ct("div",{"command-separator":"",role:"separator",...e})}}),wt=Object.assign(Qn,{Dialog:td,Empty:bd,Group:id,Input:dd,Item:pd,List:gd,Loading:yd,Separator:wd,Root:Qn});var jr;const pa=typeof window<"u",kd=t=>typeof t=="function",Ld=t=>typeof t=="string",_a=()=>{};pa&&((jr=window==null?void 0:window.navigator)!=null&&jr.userAgent)&&/iP(ad|hone|od)/.test(window.navigator.userAgent);function Lr(t){return typeof t=="function"?t():v(t)}function Sd(t,e){function n(...r){return new Promise((s,a)=>{Promise.resolve(t(()=>e.apply(this,r),{fn:e,thisArg:this,args:r})).then(s).catch(a)})}return n}const va=t=>t();function Ed(t=va){const e=X(!0);function n(){e.value=!1}function r(){e.value=!0}const s=(...a)=>{e.value&&t(...a)};return{isActive:xs(e),pause:n,resume:r,eventFilter:s}}function Od(t){return t}function Cd(t){return Ys()?(zs(t),!0):!1}var xr=Object.getOwnPropertySymbols,Ad=Object.prototype.hasOwnProperty,Id=Object.prototype.propertyIsEnumerable,Md=(t,e)=>{var n={};for(var r in t)Ad.call(t,r)&&e.indexOf(r)<0&&(n[r]=t[r]);if(t!=null&&xr)for(var r of xr(t))e.indexOf(r)<0&&Id.call(t,r)&&(n[r]=t[r]);return n};function Nd(t,e,n={}){const r=n,{eventFilter:s=va}=r,a=Md(r,["eventFilter"]);return pe(t,Sd(s,e),a)}var $d=Object.defineProperty,Pd=Object.defineProperties,Td=Object.getOwnPropertyDescriptors,fn=Object.getOwnPropertySymbols,ga=Object.prototype.hasOwnProperty,ba=Object.prototype.propertyIsEnumerable,Kr=(t,e,n)=>e in t?$d(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,Fd=(t,e)=>{for(var n in e||(e={}))ga.call(e,n)&&Kr(t,n,e[n]);if(fn)for(var n of fn(e))ba.call(e,n)&&Kr(t,n,e[n]);return t},Rd=(t,e)=>Pd(t,Td(e)),Vd=(t,e)=>{var n={};for(var r in t)ga.call(t,r)&&e.indexOf(r)<0&&(n[r]=t[r]);if(t!=null&&fn)for(var r of fn(t))e.indexOf(r)<0&&ba.call(t,r)&&(n[r]=t[r]);return n};function Dd(t,e,n={}){const r=n,{eventFilter:s}=r,a=Vd(r,["eventFilter"]),{eventFilter:o,pause:i,resume:l,isActive:c}=Ed(s);return{stop:Nd(t,e,Rd(Fd({},a),{eventFilter:o})),pause:i,resume:l,isActive:c}}function Hd(t){var e;const n=Lr(t);return(e=n==null?void 0:n.$el)!=null?e:n}const jt=pa?window:void 0;function Et(...t){let e,n,r,s;if(Ld(t[0])||Array.isArray(t[0])?([n,r,s]=t,e=jt):[e,n,r,s]=t,!e)return _a;Array.isArray(n)||(n=[n]),Array.isArray(r)||(r=[r]);const a=[],o=()=>{a.forEach(u=>u()),a.length=0},i=(u,d,f,y)=>(u.addEventListener(d,f,y),()=>u.removeEventListener(d,f,y)),l=pe(()=>[Hd(e),Lr(s)],([u,d])=>{o(),u&&a.push(...n.flatMap(f=>r.map(y=>i(u,f,y,d))))},{immediate:!0,flush:"post"}),c=()=>{l(),o()};return Cd(c),c}const Zn=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},er="__vueuse_ssr_handlers__";Zn[er]=Zn[er]||{};const Ud=Zn[er];function Bd(t,e){return Ud[t]||e}function Wd(t){return t==null?"any":t instanceof Set?"set":t instanceof Map?"map":t instanceof Date?"date":typeof t=="boolean"?"boolean":typeof t=="string"?"string":typeof t=="object"?"object":Number.isNaN(t)?"any":"number"}var jd=Object.defineProperty,Gr=Object.getOwnPropertySymbols,xd=Object.prototype.hasOwnProperty,Kd=Object.prototype.propertyIsEnumerable,Yr=(t,e,n)=>e in t?jd(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,zr=(t,e)=>{for(var n in e||(e={}))xd.call(e,n)&&Yr(t,n,e[n]);if(Gr)for(var n of Gr(e))Kd.call(e,n)&&Yr(t,n,e[n]);return t};const Gd={boolean:{read:t=>t==="true",write:t=>String(t)},object:{read:t=>JSON.parse(t),write:t=>JSON.stringify(t)},number:{read:t=>Number.parseFloat(t),write:t=>String(t)},any:{read:t=>t,write:t=>String(t)},string:{read:t=>t,write:t=>String(t)},map:{read:t=>new Map(JSON.parse(t)),write:t=>JSON.stringify(Array.from(t.entries()))},set:{read:t=>new Set(JSON.parse(t)),write:t=>JSON.stringify(Array.from(t))},date:{read:t=>new Date(t),write:t=>t.toISOString()}},Xr="vueuse-storage";function Yd(t,e,n,r={}){var s;const{flush:a="pre",deep:o=!0,listenToStorageChanges:i=!0,writeDefaults:l=!0,mergeDefaults:c=!1,shallow:u,window:d=jt,eventFilter:f,onError:y=B=>{console.error(B)}}=r,S=(u?bn:X)(e);if(!n)try{n=Bd("getDefaultStorage",()=>{var B;return(B=jt)==null?void 0:B.localStorage})()}catch(B){y(B)}if(!n)return S;const g=Lr(e),b=Wd(g),p=(s=r.serializer)!=null?s:Gd[b],{pause:E,resume:I}=Dd(S,()=>L(S.value),{flush:a,deep:o,eventFilter:f});return d&&i&&(Et(d,"storage",N),Et(d,Xr,T)),N(),S;function L(B){try{if(B==null)n.removeItem(t);else{const G=p.write(B),le=n.getItem(t);le!==G&&(n.setItem(t,G),d&&d.dispatchEvent(new CustomEvent(Xr,{detail:{key:t,oldValue:le,newValue:G,storageArea:n}})))}}catch(G){y(G)}}function P(B){const G=B?B.newValue:n.getItem(t);if(G==null)return l&&g!==null&&n.setItem(t,p.write(g)),g;if(!B&&c){const le=p.read(G);return kd(c)?c(le,g):b==="object"&&!Array.isArray(le)?zr(zr({},g),le):le}else return typeof G!="string"?G:p.read(G)}function T(B){N(B.detail)}function N(B){if(!(B&&B.storageArea!==n)){if(B&&B.key==null){S.value=g;return}if(!(B&&B.key!==t)){E();try{S.value=P(B)}catch(G){y(G)}finally{B?Ue(I):I()}}}}}function zd(t,e,n={}){const{window:r=jt}=n;return Yd(t,e,r==null?void 0:r.localStorage,n)}const Xd={ctrl:"control",command:"meta",cmd:"meta",option:"alt",up:"arrowup",down:"arrowdown",left:"arrowleft",right:"arrowright"};function qd(t={}){const{reactive:e=!1,target:n=jt,aliasMap:r=Xd,passive:s=!0,onEventFired:a=_a}=t,o=Bt(new Set),i={toJSON(){return{}},current:o},l=e?Bt(i):i,c=new Set,u=new Set;function d(g,b){g in l&&(e?l[g]=b:l[g].value=b)}function f(){o.clear();for(const g of u)d(g,!1)}function y(g,b){var p,E;const I=(p=g.key)==null?void 0:p.toLowerCase(),P=[(E=g.code)==null?void 0:E.toLowerCase(),I].filter(Boolean);I&&(b?o.add(I):o.delete(I));for(const T of P)u.add(T),d(T,b);I==="meta"&&!b?(c.forEach(T=>{o.delete(T),d(T,!1)}),c.clear()):typeof g.getModifierState=="function"&&g.getModifierState("Meta")&&b&&[...o,...P].forEach(T=>c.add(T))}Et(n,"keydown",g=>(y(g,!0),a(g)),{passive:s}),Et(n,"keyup",g=>(y(g,!1),a(g)),{passive:s}),Et("blur",f,{passive:!0}),Et("focus",f,{passive:!0});const S=new Proxy(l,{get(g,b,p){if(typeof b!="string")return Reflect.get(g,b,p);if(b=b.toLowerCase(),b in r&&(b=r[b]),!(b in l))if(/[+_-]/.test(b)){const I=b.split(/[+_-]/g).map(L=>L.trim());l[b]=U(()=>I.every(L=>v(S[L])))}else l[b]=X(!1);const E=Reflect.get(g,b,p);return e?v(E):E}});return S}var qr;(function(t){t.UP="UP",t.RIGHT="RIGHT",t.DOWN="DOWN",t.LEFT="LEFT",t.NONE="NONE"})(qr||(qr={}));var Jd=Object.defineProperty,Jr=Object.getOwnPropertySymbols,Qd=Object.prototype.hasOwnProperty,Zd=Object.prototype.propertyIsEnumerable,Qr=(t,e,n)=>e in t?Jd(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,ef=(t,e)=>{for(var n in e||(e={}))Qd.call(e,n)&&Qr(t,n,e[n]);if(Jr)for(var n of Jr(e))Zd.call(e,n)&&Qr(t,n,e[n]);return t};const tf={easeInSine:[.12,0,.39,0],easeOutSine:[.61,1,.88,1],easeInOutSine:[.37,0,.63,1],easeInQuad:[.11,0,.5,0],easeOutQuad:[.5,1,.89,1],easeInOutQuad:[.45,0,.55,1],easeInCubic:[.32,0,.67,0],easeOutCubic:[.33,1,.68,1],easeInOutCubic:[.65,0,.35,1],easeInQuart:[.5,0,.75,0],easeOutQuart:[.25,1,.5,1],easeInOutQuart:[.76,0,.24,1],easeInQuint:[.64,0,.78,0],easeOutQuint:[.22,1,.36,1],easeInOutQuint:[.83,0,.17,1],easeInExpo:[.7,0,.84,0],easeOutExpo:[.16,1,.3,1],easeInOutExpo:[.87,0,.13,1],easeInCirc:[.55,0,1,.45],easeOutCirc:[0,.55,.45,1],easeInOutCirc:[.85,0,.15,1],easeInBack:[.36,0,.66,-.56],easeOutBack:[.34,1.56,.64,1],easeInOutBack:[.68,-.6,.32,1.6]};ef({linear:Od},tf);const nf={locales:{root:{btnPlaceholder:"Search",placeholder:"Search Docs...",emptyText:"No results",heading:"Total: {{searchResult}} search results."},zh:{customSearchQuery(t){return t.replace(/[\u4e00-\u9fa5]/g," $& ").replace(/\s+/g," ").trim()},btnPlaceholder:"搜索",placeholder:"搜索文档",emptyText:"空空如也",heading:"共:{{searchResult}} 条结果",showDate:!1}}},rf={},sf={width:"594",height:"112",viewBox:"0 0 594 112",fill:"none",xmlns:"http://www.w3.org/2000/svg"};function af(t,e){return _(),A("svg",sf,e[0]||(e[0]=[_o('',11)]))}const of=q(rf,[["render",af]]);function lf(t){if(!t)return{};try{const e=decodeURIComponent(atob(t));return JSON.parse(e)}catch{return{}}}function cf(t,e=1){const{sub_results:n,anchors:r,weighted_locations:s}=t;s.sort((i,l)=>l.weight===i.weight?i.location-l.location:l.weight-i.weight);const a=[];for(const{location:i}of s){const c=n.filter(u=>{const{locations:d}=u,[f]=d||[];if(!f)return!1;const y=d.length===1?Number.POSITIVE_INFINITY:d[d.length-1];return f<=i&&i<=y}).reduce((u,d)=>u&&u.locations.length>d.locations.length?u:d,null);if(c&&(a.push(c),a.length>=e))break}a.sort((i,l)=>{const[c]=i.locations||[],[u]=l.locations||[];return!c||!u?0:c-u});const o=new Map;return a.map(i=>uf(i,r,t)).filter(i=>o.has(i.meta.title)?!1:(o.set(i.meta.title,i),!0))}function uf(t,e,n){const r=(t==null?void 0:t.url)||(n==null?void 0:n.url),s=(t==null?void 0:t.excerpt)||(n==null?void 0:n.excerpt),a=(e==null?void 0:e.filter(u=>t?u.location<=t.anchor.location&&u.element<=t.anchor.element:!1))||[];a.reverse();const o=a.reduce((u,d)=>(u.some(y=>y.element===d.element)||u.unshift(d),u),[]),i=o.length?o.map(u=>u.text.trim()).filter(u=>!!u).join(" > "):n.meta.title,{base64:l,...c}=n.meta;return{route:r,meta:{...lf(l),...c,title:i,description:s},result:n}}function df(t,e="yyyy-MM-dd hh:mm:ss"){t instanceof Date||(t=new Date(t));const n={"M+":t.getMonth()+1,"d+":t.getDate(),"h+":t.getHours(),"m+":t.getMinutes(),"s+":t.getSeconds(),"q+":Math.floor((t.getMonth()+3)/3),S:t.getMilliseconds()};/(y+)/.test(e)&&(e=e.replace(RegExp.$1,`${t.getFullYear()}`.substr(4-RegExp.$1.length)));for(const r in n)new RegExp(`(${r})`).test(e)&&(e=e.replace(RegExp.$1,RegExp.$1.length===1?n[r]:`00${n[r]}`.substr(`${n[r]}`.length)));return e}function ff(t,e){const n=+new Date(t),s=+new Date-n,a=1e3,o=a*60,i=o*60,l=i*24,c=l*7,u={"zh-cn":{justNow:"刚刚",secondsAgo:"秒前",minutesAgo:"分钟前",hoursAgo:"小时前",daysAgo:"天前",weeksAgo:"周前"},"en-us":{justNow:" just now",secondsAgo:" seconds ago",minutesAgo:" minutes ago",hoursAgo:" hours ago",daysAgo:" days ago",weeksAgo:" weeks ago"}},d=u[e.toLowerCase()]||u["en-us"];return s<10?d.justNow:s{var J;return{...n,...((J=n==null?void 0:n.locales)==null?void 0:J[r.value])||{}}}),i=U(()=>{var J;return((J=o.value)==null?void 0:J.ignorePublish)??!1}),l=U(()=>{var J;return((J=o.value)==null?void 0:J.showDate)??!1}),c=U(()=>typeof o.value.showDate=="function"?o.value.showDate:ff),u=U(()=>{var J;return(J=o.value)!=null&&J.heading?o.value.heading.replace(/\{\{searchResult\}\}/,`${e.value.length}`):`Total: ${e.value.length} search results.`}),d=X("");Ye(()=>{d.value=/(Mac|iPhone|iPod|iPad)/i.test(navigator==null?void 0:navigator.platform)?"⌘":"Ctrl"});const f=X(!1);function y(){f.value=!0}function S(){f.value=!1}const g=qd({passive:!1,onEventFired(J){J.ctrlKey&&J.key==="k"&&J.type==="keydown"&&J.preventDefault()}}),b=g["Meta+K"],p=g["Ctrl+K"],E=g.Escape;pe(b,J=>{J&&y()}),pe(p,J=>{J&&y()}),pe(E,J=>{J&&S()});const I=X("");function L(){if(!I.value){e.value=[];return}e.value=[{route:"#",meta:{title:"只在构建后才生效",description:"only support after build, only support after build"}}]}const P=/[\u4E00-\u9FA5]/g,T=(Intl==null?void 0:Intl.Segmenter)&&new Intl.Segmenter("ch",{granularity:"word"});function N(J){return T?Array.from(T==null?void 0:T.segment(J)).map(V=>V.segment).join(" "):J.replace(P," $& ").replace(/\s+/g," ").trim()}const B=U(()=>{var J;return((J=o.value)==null?void 0:J.delay)??300});pe(()=>I.value,async()=>{var te,V,re;if(!((te=window==null?void 0:window.__pagefind__)!=null&&te.search)){L();return}const J=typeof o.value.customSearchQuery=="function"?o.value.customSearchQuery(I.value):P.test(I.value)?N(I.value):I.value;await((re=(V=window==null?void 0:window.__pagefind__)==null?void 0:V.debouncedSearch)==null?void 0:re.call(V,J,{},B.value).then(async Y=>{if(Y===null)return;const Le=(await Promise.all(Y.results.map(Se=>Se.data()))).map(Se=>cf(Se,o.value.pageResultCount||1).map(Fe=>(Fe.route=Fe.route.startsWith(s.value.base)?Fe.route:vn(Fe.route),Fe))).flat().filter(Se=>i.value||Se.meta.publish!==!1);o.value.sort&&Le.sort(o.value.sort),e.value=Le.filter(o.value.filter??(()=>!0))})),Ue(()=>{document.querySelectorAll('div[aria-disabled="true"]').forEach(Y=>{Y.setAttribute("aria-disabled","false")})})});function G(J){J.target===J.currentTarget&&S()}pe(()=>f.value,J=>{var te;J?Ue(()=>{var V;(V=document.querySelector("div[command-dialog-mask]"))==null||V.addEventListener("click",G)}):(te=document.querySelector("div[command-dialog-mask]"))==null||te.removeEventListener("click",G)});const le=X(999),ge=X(0),ae=U(()=>{const te=ge.value%Math.ceil(e.value.length/le.value)*le.value;return e.value.slice(te,te+le.value)}),_e=vo(),Ne=Yt();function Te(J){S(),Ne.path!==J.value&&_e.go(J.value)}const tt=U(()=>o.value.langReload??!0);pe(()=>a.value,()=>{tt.value&&window.location.reload()});const De=X();function nt(){I.value="",Ue(()=>{De.value&&(De.value.$el.value="")})}const Ee=zd("pagefind-search-showDetail",!1);function rt(){Ee.value=!Ee.value}return(J,te)=>{var re;const V=lt("ClientOnly");return _(),A("div",hf,[w("div",{class:"nav-search-btn-wait",onClick:te[0]||(te[0]=Y=>f.value=!0)},[te[3]||(te[3]=w("span",null,[w("svg",{width:"14",height:"14",viewBox:"0 0 20 20"},[w("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none","fill-rule":"evenodd","stroke-linecap":"round","stroke-linejoin":"round"})])],-1)),w("span",mf,Z(((re=o.value)==null?void 0:re.btnPlaceholder)||"Search"),1),w("span",pf,Z(d.value)+" K ",1)]),x(V,null,{default:M(()=>[x(v(wt).Dialog,{visible:f.value,theme:"algolia"},go({header:M(()=>{var Y;return[w("div",_f,[w("div",vf,[w("button",{class:"back-button",title:"Close search",onClick:te[1]||(te[1]=oe=>f.value=!1)},te[4]||(te[4]=[w("span",{class:"vpi-arrow-left local-search-icon"},null,-1)]))]),x(v(wt).Input,{ref_key:"searchInput",ref:De,value:I.value,"onUpdate:value":te[2]||(te[2]=oe=>I.value=oe),placeholder:((Y=o.value)==null?void 0:Y.placeholder)||"Search Docs"},null,8,["value","placeholder"]),w("div",gf,[w("button",{class:ue([{active:v(Ee)},"toggle-layout-button"]),type:"button",title:"Display detailed list",onClick:rt},te[5]||(te[5]=[w("span",{class:"vpi-layout-list local-search-icon"},null,-1)]),2),w("button",{disabled:!I.value,class:"clear-button",type:"reset",title:"Reset search",onClick:nt},te[6]||(te[6]=[w("span",{class:"vpi-delete local-search-icon"},null,-1)]),8,bf)])])]}),body:M(()=>[w("div",{class:ue(["search-dialog",{"detail-list":v(Ee)}])},[x(v(wt).List,null,{default:M(()=>[e.value.length?(_(),K(v(wt).Group,{key:1,heading:u.value},{default:M(()=>[(_(!0),A(he,null,Ce(ae.value,Y=>(_(),K(v(wt).Item,{key:Y.route,"data-value":Y.route,onSelect:Te},{default:M(()=>[w("div",yf,[w("div",wf,[w("span",kf,[Y.meta.title?(_(),A("i",Lf,"# ")):j("",!0),Ve(Z(Y.meta.title),1)]),l.value&&Y.meta.date?(_(),A("span",Sf,Z(c.value(Y.meta.date,v(a))),1)):j("",!0)]),w("div",{class:"des",innerHTML:Y.meta.description},null,8,Ef)])]),_:2},1032,["data-value"]))),128))]),_:1},8,["heading"])):(_(),K(v(wt).Empty,{key:0},{default:M(()=>{var Y;return[Ve(Z(((Y=o.value)==null?void 0:Y.emptyText)||"No results found."),1)]}),_:1}))]),_:1})],2)]),_:2},[e.value.length?{name:"footer",fn:M(()=>{var Y,oe,Le,Se;return[w("div",Of,[w("a",Cf,[w("span",Af,Z(((Y=o.value)==null?void 0:Y.searchBy)||"Search by"),1),x(of,{style:{width:"77px"}})])]),w("ul",If,[w("li",null,[te[7]||(te[7]=w("kbd",{class:"command-palette-commands-key"},[w("svg",{width:"15",height:"15","aria-label":"Enter key",role:"img"},[w("g",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"1.2"},[w("path",{d:"M12 3.53088v3c0 1-1 2-2 2H4M7 11.53088l-3-3 3-3"})])])],-1)),w("span",Mf,Z(((oe=o.value)==null?void 0:oe.toSelect)||"to select"),1)]),w("li",null,[te[8]||(te[8]=w("kbd",{class:"command-palette-commands-key"},[w("svg",{width:"15",height:"15","aria-label":"Arrow down",role:"img"},[w("g",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"1.2"},[w("path",{d:"M7.5 3.5v8M10.5 8.5l-3 3-3-3"})])])],-1)),te[9]||(te[9]=w("kbd",{class:"command-palette-commands-key"},[w("svg",{width:"15",height:"15","aria-label":"Arrow up",role:"img"},[w("g",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"1.2"},[w("path",{d:"M7.5 11.5v-8M10.5 6.5l-3-3-3 3"})])])],-1)),w("span",Nf,Z(((Le=o.value)==null?void 0:Le.toNavigate)||"to navigate"),1)]),w("li",null,[te[10]||(te[10]=w("kbd",{class:"command-palette-commands-key"},[w("svg",{width:"15",height:"15","aria-label":"Escape key",role:"img"},[w("g",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"1.2"},[w("path",{d:"M13.6167 8.936c-.1065.3583-.6883.962-1.4875.962-.7993 0-1.653-.9165-1.653-2.1258v-.5678c0-1.2548.7896-2.1016 1.653-2.1016.8634 0 1.3601.4778 1.4875 1.0724M9 6c-.1352-.4735-.7506-.9219-1.46-.8972-.7092.0246-1.344.57-1.344 1.2166s.4198.8812 1.3445.9805C8.465 7.3992 8.968 7.9337 9 8.5c.032.5663-.454 1.398-1.4595 1.398C6.6593 9.898 6 9 5.963 8.4851m-1.4748.5368c-.2635.5941-.8099.876-1.5443.876s-1.7073-.6248-1.7073-2.204v-.4603c0-1.0416.721-2.131 1.7073-2.131.9864 0 1.6425 1.031 1.5443 2.2492h-2.956"})])])],-1)),w("span",$f,Z(((Se=o.value)==null?void 0:Se.toClose)||"to close"),1)])])]}),key:"0"}:void 0]),1032,["visible"])]),_:1})])}}}),Tf=q(Pf,[["__scopeId","data-v-fd998d3a"]]),Ff=R({__name:"VPNavBarSocialLinks",setup(t){const{theme:e}=se();return(n,r)=>v(e).socialLinks?(_(),K(wr,{key:0,class:"VPNavBarSocialLinks",links:v(e).socialLinks},null,8,["links"])):j("",!0)}}),Rf=q(Ff,[["__scopeId","data-v-b7887d5a"]]),Vf=["href","rel","target"],Df={key:1},Hf={key:2},Uf=R({__name:"VPNavBarTitle",setup(t){const{site:e,theme:n}=se(),{hasSidebar:r}=et(),{currentLang:s}=zt(),a=U(()=>{var l;return typeof n.value.logoLink=="string"?n.value.logoLink:(l=n.value.logoLink)==null?void 0:l.link}),o=U(()=>{var l;return typeof n.value.logoLink=="string"||(l=n.value.logoLink)==null?void 0:l.rel}),i=U(()=>{var l;return typeof n.value.logoLink=="string"||(l=n.value.logoLink)==null?void 0:l.target});return(l,c)=>(_(),A("div",{class:ue(["VPNavBarTitle",{"has-sidebar":v(r)}])},[w("a",{class:"title",href:a.value??v(_r)(v(s).link),rel:o.value,target:i.value},[C(l.$slots,"nav-bar-title-before",{},void 0,!0),v(n).logo?(_(),K(un,{key:0,class:"logo",image:v(n).logo},null,8,["image"])):j("",!0),v(n).siteTitle?(_(),A("span",Df,Z(v(n).siteTitle),1)):v(n).siteTitle===void 0?(_(),A("span",Hf,Z(v(e).title),1)):j("",!0),C(l.$slots,"nav-bar-title-after",{},void 0,!0)],8,Vf)],2))}}),Bf=q(Uf,[["__scopeId","data-v-9f785053"]]),Wf={class:"items"},jf={class:"title"},xf=R({__name:"VPNavBarTranslations",setup(t){const{theme:e}=se(),{localeLinks:n,currentLang:r}=zt({correspondingLink:!0});return(s,a)=>v(n).length&&v(r).label?(_(),K(yr,{key:0,class:"VPNavBarTranslations",icon:"vpi-languages",label:v(e).langMenuLabel||"Change language"},{default:M(()=>[w("div",Wf,[w("p",jf,Z(v(r).label),1),(_(!0),A(he,null,Ce(v(n),o=>(_(),K(Ln,{key:o.link,item:o},null,8,["item"]))),128))])]),_:1},8,["label"])):j("",!0)}}),Kf=q(xf,[["__scopeId","data-v-d78d18d0"]]),Gf={class:"wrapper"},Yf={class:"container"},zf={class:"title"},Xf={class:"content"},qf={class:"content-body"},Jf=R({__name:"VPNavBar",props:{isScreenOpen:{type:Boolean}},emits:["toggle-screen"],setup(t){const e=t,{y:n}=js(),{hasSidebar:r}=et(),{frontmatter:s}=se(),a=X({});return mr(()=>{a.value={"has-sidebar":r.value,home:s.value.layout==="home",top:n.value===0,"screen-open":e.isScreenOpen}}),(o,i)=>(_(),A("div",{class:ue(["VPNavBar",a.value])},[w("div",Gf,[w("div",Yf,[w("div",zf,[x(Bf,null,{"nav-bar-title-before":M(()=>[C(o.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":M(()=>[C(o.$slots,"nav-bar-title-after",{},void 0,!0)]),_:3})]),w("div",Xf,[w("div",qf,[C(o.$slots,"nav-bar-content-before",{},void 0,!0),x(Tf,{class:"search"}),x(Hc,{class:"menu"}),x(Kf,{class:"translations"}),x(Xl,{class:"appearance"}),x(Rf,{class:"social-links"}),x(Ic,{class:"extra"}),C(o.$slots,"nav-bar-content-after",{},void 0,!0),x($c,{class:"hamburger",active:o.isScreenOpen,onClick:i[0]||(i[0]=l=>o.$emit("toggle-screen"))},null,8,["active"])])])])]),i[1]||(i[1]=w("div",{class:"divider"},[w("div",{class:"divider-line"})],-1))],2))}}),Qf=q(Jf,[["__scopeId","data-v-f9756f2d"]]),Zf={key:0,class:"VPNavScreenAppearance"},eh={class:"text"},th=R({__name:"VPNavScreenAppearance",setup(t){const{site:e,theme:n}=se();return(r,s)=>v(e).appearance&&v(e).appearance!=="force-dark"&&v(e).appearance!=="force-auto"?(_(),A("div",Zf,[w("p",eh,Z(v(n).darkModeSwitchLabel||"Appearance"),1),x(gr)])):j("",!0)}}),nh=q(th,[["__scopeId","data-v-f7aa697b"]]),rh=R({__name:"VPNavScreenMenuLink",props:{item:{}},setup(t){const e=Nt("close-screen");return(n,r)=>(_(),K(je,{class:"VPNavScreenMenuLink",href:n.item.link,target:n.item.target,rel:n.item.rel,onClick:v(e),innerHTML:n.item.text},null,8,["href","target","rel","onClick","innerHTML"]))}}),sh=q(rh,[["__scopeId","data-v-8f3b9429"]]),ah=R({__name:"VPNavScreenMenuGroupLink",props:{item:{}},setup(t){const e=Nt("close-screen");return(n,r)=>(_(),K(je,{class:"VPNavScreenMenuGroupLink",href:n.item.link,target:n.item.target,rel:n.item.rel,onClick:v(e)},{default:M(()=>[Ve(Z(n.item.text),1)]),_:1},8,["href","target","rel","onClick"]))}}),ya=q(ah,[["__scopeId","data-v-7b9fb56c"]]),oh={class:"VPNavScreenMenuGroupSection"},ih={key:0,class:"title"},lh=R({__name:"VPNavScreenMenuGroupSection",props:{text:{},items:{}},setup(t){return(e,n)=>(_(),A("div",oh,[e.text?(_(),A("p",ih,Z(e.text),1)):j("",!0),(_(!0),A(he,null,Ce(e.items,r=>(_(),K(ya,{key:r.text,item:r},null,8,["item"]))),128))]))}}),ch=q(lh,[["__scopeId","data-v-4af57996"]]),uh=["aria-controls","aria-expanded"],dh=["innerHTML"],fh=["id"],hh={key:0,class:"item"},mh={key:1,class:"item"},ph={key:2,class:"group"},_h=R({__name:"VPNavScreenMenuGroup",props:{text:{},items:{}},setup(t){const e=t,n=X(!1),r=U(()=>`NavScreenGroup-${e.text.replace(" ","-").toLowerCase()}`);function s(){n.value=!n.value}return(a,o)=>(_(),A("div",{class:ue(["VPNavScreenMenuGroup",{open:n.value}])},[w("button",{class:"button","aria-controls":r.value,"aria-expanded":n.value,onClick:s},[w("span",{class:"button-text",innerHTML:a.text},null,8,dh),o[0]||(o[0]=w("span",{class:"vpi-plus button-icon"},null,-1))],8,uh),w("div",{id:r.value,class:"items"},[(_(!0),A(he,null,Ce(a.items,i=>(_(),A(he,{key:JSON.stringify(i)},["link"in i?(_(),A("div",hh,[x(ya,{item:i},null,8,["item"])])):"component"in i?(_(),A("div",mh,[(_(),K(We(i.component),at({ref_for:!0},i.props,{"screen-menu":""}),null,16))])):(_(),A("div",ph,[x(ch,{text:i.text,items:i.items},null,8,["text","items"])]))],64))),128))],8,fh)],2))}}),vh=q(_h,[["__scopeId","data-v-9e6433b0"]]),gh={key:0,class:"VPNavScreenMenu"},bh=R({__name:"VPNavScreenMenu",setup(t){const{theme:e}=se();return(n,r)=>v(e).nav?(_(),A("nav",gh,[(_(!0),A(he,null,Ce(v(e).nav,s=>(_(),A(he,{key:JSON.stringify(s)},["link"in s?(_(),K(sh,{key:0,item:s},null,8,["item"])):"component"in s?(_(),K(We(s.component),at({key:1,ref_for:!0},s.props,{"screen-menu":""}),null,16)):(_(),K(vh,{key:2,text:s.text||"",items:s.items},null,8,["text","items"]))],64))),128))])):j("",!0)}}),yh=R({__name:"VPNavScreenSocialLinks",setup(t){const{theme:e}=se();return(n,r)=>v(e).socialLinks?(_(),K(wr,{key:0,class:"VPNavScreenSocialLinks",links:v(e).socialLinks},null,8,["links"])):j("",!0)}}),wh={class:"list"},kh=R({__name:"VPNavScreenTranslations",setup(t){const{localeLinks:e,currentLang:n}=zt({correspondingLink:!0}),r=X(!1);function s(){r.value=!r.value}return(a,o)=>v(e).length&&v(n).label?(_(),A("div",{key:0,class:ue(["VPNavScreenTranslations",{open:r.value}])},[w("button",{class:"title",onClick:s},[o[0]||(o[0]=w("span",{class:"vpi-languages icon lang"},null,-1)),Ve(" "+Z(v(n).label)+" ",1),o[1]||(o[1]=w("span",{class:"vpi-chevron-down icon chevron"},null,-1))]),w("ul",wh,[(_(!0),A(he,null,Ce(v(e),i=>(_(),A("li",{key:i.link,class:"item"},[x(je,{class:"link",href:i.link},{default:M(()=>[Ve(Z(i.text),1)]),_:2},1032,["href"])]))),128))])],2)):j("",!0)}}),Lh=q(kh,[["__scopeId","data-v-642b9e57"]]),Sh={class:"container"},Eh=R({__name:"VPNavScreen",props:{open:{type:Boolean}},setup(t){const e=X(null),n=Xs(wn?document.body:null);return(r,s)=>(_(),K(_n,{name:"fade",onEnter:s[0]||(s[0]=a=>n.value=!0),onAfterLeave:s[1]||(s[1]=a=>n.value=!1)},{default:M(()=>[r.open?(_(),A("div",{key:0,class:"VPNavScreen",ref_key:"screen",ref:e,id:"VPNavScreen"},[w("div",Sh,[C(r.$slots,"nav-screen-content-before",{},void 0,!0),x(bh,{class:"menu"}),x(Lh,{class:"translations"}),x(nh,{class:"appearance"}),x(yh,{class:"social-links"}),C(r.$slots,"nav-screen-content-after",{},void 0,!0)])],512)):j("",!0)]),_:3}))}}),Oh=q(Eh,[["__scopeId","data-v-1b440f23"]]),Ch={key:0,class:"VPNav"},Ah=R({__name:"VPNav",setup(t){const{isScreenOpen:e,closeScreen:n,toggleScreen:r}=Hl(),{frontmatter:s}=se(),a=U(()=>s.value.navbar!==!1);return pr("close-screen",n),it(()=>{wn&&document.documentElement.classList.toggle("hide-nav",!a.value)}),(o,i)=>a.value?(_(),A("header",Ch,[x(Qf,{"is-screen-open":v(e),onToggleScreen:v(r)},{"nav-bar-title-before":M(()=>[C(o.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":M(()=>[C(o.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":M(()=>[C(o.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":M(()=>[C(o.$slots,"nav-bar-content-after",{},void 0,!0)]),_:3},8,["is-screen-open","onToggleScreen"]),x(Oh,{open:v(e)},{"nav-screen-content-before":M(()=>[C(o.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":M(()=>[C(o.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3},8,["open"])])):j("",!0)}}),Ih=q(Ah,[["__scopeId","data-v-a62deceb"]]),Mh=["role","tabindex"],Nh={key:1,class:"items"},$h=R({__name:"VPSidebarItem",props:{item:{},depth:{}},setup(t){const e=t,{collapsed:n,collapsible:r,isLink:s,isActiveLink:a,hasActiveLink:o,hasChildren:i,toggle:l}=xo(U(()=>e.item)),c=U(()=>i.value?"section":"div"),u=U(()=>s.value?"a":"div"),d=U(()=>i.value?e.depth+2===7?"p":`h${e.depth+2}`:"p"),f=U(()=>s.value?void 0:"button"),y=U(()=>[[`level-${e.depth}`],{collapsible:r.value},{collapsed:n.value},{"is-link":s.value},{"is-active":a.value},{"has-active":o.value}]);function S(b){"key"in b&&b.key!=="Enter"||!e.item.link&&l()}function g(){e.item.link&&l()}return(b,p)=>{const E=lt("VPSidebarItem",!0);return _(),K(We(c.value),{class:ue(["VPSidebarItem",y.value])},{default:M(()=>[b.item.text?(_(),A("div",at({key:0,class:"item",role:f.value},bo(b.item.items?{click:S,keydown:S}:{},!0),{tabindex:b.item.items&&0}),[p[1]||(p[1]=w("div",{class:"indicator"},null,-1)),b.item.link?(_(),K(je,{key:0,tag:u.value,class:"link",href:b.item.link,rel:b.item.rel,target:b.item.target},{default:M(()=>[(_(),K(We(d.value),{class:"text",innerHTML:b.item.text},null,8,["innerHTML"]))]),_:1},8,["tag","href","rel","target"])):(_(),K(We(d.value),{key:1,class:"text",innerHTML:b.item.text},null,8,["innerHTML"])),b.item.collapsed!=null&&b.item.items&&b.item.items.length?(_(),A("div",{key:2,class:"caret",role:"button","aria-label":"toggle section",onClick:g,onKeydown:yo(g,["enter"]),tabindex:"0"},p[0]||(p[0]=[w("span",{class:"vpi-chevron-right caret-icon"},null,-1)]),32)):j("",!0)],16,Mh)):j("",!0),b.item.items&&b.item.items.length?(_(),A("div",Nh,[b.depth<5?(_(!0),A(he,{key:0},Ce(b.item.items,I=>(_(),K(E,{key:I.text,item:I,depth:b.depth+1},null,8,["item","depth"]))),128)):j("",!0)])):j("",!0)]),_:1},8,["class"])}}}),Ph=q($h,[["__scopeId","data-v-3d6ff150"]]),Th=R({__name:"VPSidebarGroup",props:{items:{}},setup(t){const e=X(!0);let n=null;return Ye(()=>{n=setTimeout(()=>{n=null,e.value=!1},300)}),kn(()=>{n!=null&&(clearTimeout(n),n=null)}),(r,s)=>(_(!0),A(he,null,Ce(r.items,a=>(_(),A("div",{key:a.text,class:ue(["group",{"no-transition":e.value}])},[x(Ph,{item:a,depth:0},null,8,["item"])],2))),128))}}),Fh=q(Th,[["__scopeId","data-v-1952544a"]]),Rh={class:"nav",id:"VPSidebarNav","aria-labelledby":"sidebar-aria-label",tabindex:"-1"},Vh=R({__name:"VPSidebar",props:{open:{type:Boolean}},setup(t){const{sidebarGroups:e,hasSidebar:n}=et(),r=t,s=X(null),a=Xs(wn?document.body:null);pe([r,s],()=>{var i;r.open?(a.value=!0,(i=s.value)==null||i.focus()):a.value=!1},{immediate:!0,flush:"post"});const o=X(0);return pe(e,()=>{o.value+=1},{deep:!0}),(i,l)=>v(n)?(_(),A("aside",{key:0,class:ue(["VPSidebar",{open:i.open}]),ref_key:"navEl",ref:s,onClick:l[0]||(l[0]=wo(()=>{},["stop"]))},[l[2]||(l[2]=w("div",{class:"curtain"},null,-1)),w("nav",Rh,[l[1]||(l[1]=w("span",{class:"visually-hidden",id:"sidebar-aria-label"}," Sidebar Navigation ",-1)),C(i.$slots,"sidebar-nav-before",{},void 0,!0),(_(),K(Fh,{items:v(e),key:o.value},null,8,["items"])),C(i.$slots,"sidebar-nav-after",{},void 0,!0)])],2)):j("",!0)}}),Dh=q(Vh,[["__scopeId","data-v-452d748b"]]),Hh=R({__name:"VPSkipLink",setup(t){const e=Yt(),n=X();pe(()=>e.path,()=>n.value.focus());function r({target:s}){const a=document.getElementById(decodeURIComponent(s.hash).slice(1));if(a){const o=()=>{a.removeAttribute("tabindex"),a.removeEventListener("blur",o)};a.setAttribute("tabindex","-1"),a.addEventListener("blur",o),a.focus(),window.scrollTo(0,0)}}return(s,a)=>(_(),A(he,null,[w("span",{ref_key:"backToTop",ref:n,tabindex:"-1"},null,512),w("a",{href:"#VPContent",class:"VPSkipLink visually-hidden",onClick:r}," Skip to content ")],64))}}),Uh=q(Hh,[["__scopeId","data-v-e8369309"]]),Bh=R({__name:"Layout",setup(t){const{isOpen:e,open:n,close:r}=et(),s=Yt();pe(()=>s.path,r),jo(e,r);const{frontmatter:a}=se(),o=ko(),i=U(()=>!!o["home-hero-image"]);return pr("hero-image-slot-exists",i),(l,c)=>{const u=lt("Content");return v(a).layout!==!1?(_(),A("div",{key:0,class:ue(["Layout",v(a).pageClass])},[C(l.$slots,"layout-top",{},void 0,!0),x(Uh),x(Mo,{class:"backdrop",show:v(e),onClick:v(r)},null,8,["show","onClick"]),x(Ih,null,{"nav-bar-title-before":M(()=>[C(l.$slots,"nav-bar-title-before",{},void 0,!0)]),"nav-bar-title-after":M(()=>[C(l.$slots,"nav-bar-title-after",{},void 0,!0)]),"nav-bar-content-before":M(()=>[C(l.$slots,"nav-bar-content-before",{},void 0,!0)]),"nav-bar-content-after":M(()=>[C(l.$slots,"nav-bar-content-after",{},void 0,!0)]),"nav-screen-content-before":M(()=>[C(l.$slots,"nav-screen-content-before",{},void 0,!0)]),"nav-screen-content-after":M(()=>[C(l.$slots,"nav-screen-content-after",{},void 0,!0)]),_:3}),x(Dl,{open:v(e),onOpenMenu:v(n)},null,8,["open","onOpenMenu"]),x(Dh,{open:v(e)},{"sidebar-nav-before":M(()=>[C(l.$slots,"sidebar-nav-before",{},void 0,!0)]),"sidebar-nav-after":M(()=>[C(l.$slots,"sidebar-nav-after",{},void 0,!0)]),_:3},8,["open"]),x(kl,null,{"page-top":M(()=>[C(l.$slots,"page-top",{},void 0,!0)]),"page-bottom":M(()=>[C(l.$slots,"page-bottom",{},void 0,!0)]),"not-found":M(()=>[C(l.$slots,"not-found",{},void 0,!0)]),"home-hero-before":M(()=>[C(l.$slots,"home-hero-before",{},void 0,!0)]),"home-hero-info-before":M(()=>[C(l.$slots,"home-hero-info-before",{},void 0,!0)]),"home-hero-info":M(()=>[C(l.$slots,"home-hero-info",{},void 0,!0)]),"home-hero-info-after":M(()=>[C(l.$slots,"home-hero-info-after",{},void 0,!0)]),"home-hero-actions-after":M(()=>[C(l.$slots,"home-hero-actions-after",{},void 0,!0)]),"home-hero-image":M(()=>[C(l.$slots,"home-hero-image",{},void 0,!0)]),"home-hero-after":M(()=>[C(l.$slots,"home-hero-after",{},void 0,!0)]),"home-features-before":M(()=>[C(l.$slots,"home-features-before",{},void 0,!0)]),"home-features-after":M(()=>[C(l.$slots,"home-features-after",{},void 0,!0)]),"doc-footer-before":M(()=>[C(l.$slots,"doc-footer-before",{},void 0,!0)]),"doc-before":M(()=>[C(l.$slots,"doc-before",{},void 0,!0)]),"doc-after":M(()=>[C(l.$slots,"doc-after",{},void 0,!0)]),"doc-top":M(()=>[C(l.$slots,"doc-top",{},void 0,!0)]),"doc-bottom":M(()=>[C(l.$slots,"doc-bottom",{},void 0,!0)]),"aside-top":M(()=>[C(l.$slots,"aside-top",{},void 0,!0)]),"aside-bottom":M(()=>[C(l.$slots,"aside-bottom",{},void 0,!0)]),"aside-outline-before":M(()=>[C(l.$slots,"aside-outline-before",{},void 0,!0)]),"aside-outline-after":M(()=>[C(l.$slots,"aside-outline-after",{},void 0,!0)]),"aside-ads-before":M(()=>[C(l.$slots,"aside-ads-before",{},void 0,!0)]),"aside-ads-after":M(()=>[C(l.$slots,"aside-ads-after",{},void 0,!0)]),_:3}),x(Cl),C(l.$slots,"layout-bottom",{},void 0,!0)],2)):(_(),K(u,{key:1}))}}}),Wh=q(Bh,[["__scopeId","data-v-1e8cdb3b"]]),wa={Layout:Wh,enhanceApp:({app:t})=>{t.component("Badge",Co)}};var jh=Object.defineProperty,xh=(t,e,n)=>e in t?jh(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,D=(t,e,n)=>xh(t,typeof e!="symbol"?e+"":e,n),ka=(t=>(t.IPAD="ipad",t.ANDROID="android",t.IPhONE="iphone",t.PC="pc",t))(ka||{});const La=()=>{if(typeof window<"u"){const t=navigator.userAgent.toLowerCase();return/ipad|ipod/.test(t)?"ipad":/android/.test(t)?"android":/iphone/.test(t)?"iphone":"pc"}return"pc"},Xt=typeof window<"u",Kh=()=>Xt?window.navigator.userAgent.toLowerCase().includes("micromessenger"):!1,Gh=()=>{if(!Xt)return!1;const t=window.navigator.userAgent;return!!/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(t)},Yh=()=>{if(!Xt)return!1;const t=/iphone/i.test(window.navigator.userAgent),e=window.devicePixelRatio&&window.devicePixelRatio===2,n=window.devicePixelRatio&&window.devicePixelRatio===3,r=window.screen.width===360&&window.screen.height===780,s=window.screen.width===375&&window.screen.height===812,a=window.screen.width===390&&window.screen.height===844,o=window.screen.width===414&&window.screen.height===896,i=window.screen.width===428&&window.screen.height===926;switch(!0){case(t&&n&&r):case(t&&n&&s):case(t&&n&&a):case(t&&e&&o):case(t&&n&&o):case(t&&n&&i):return!0;default:return!1}},Sa="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",Ea="ARRAYBUFFER not supported by this environment",Oa="UINT8ARRAY not supported by this environment";function zh(t,e,n,r,s){let a,o,i=0,l,c,u,d,f,y;r=r||0;const S=n||[0],g=r>>>3;if(e==="UTF8")for(f=s===-1?3:0,l=0;la?o.push(a):2048>a?(o.push(192|a>>>6),o.push(128|a&63)):55296>a||57344<=a?o.push(224|a>>>12,128|a>>>6&63,128|a&63):(l+=1,a=65536+((a&1023)<<10|t.charCodeAt(l)&1023),o.push(240|a>>>18,128|a>>>12&63,128|a>>>6&63,128|a&63)),c=0;c>>2;S.length<=u;)S.push(0);S[u]|=o[c]<<8*(f+s*(d%4)),i+=1}else for(f=s===-1?2:0,y=e==="UTF16LE"&&s!==1||e!=="UTF16LE"&&s===1,l=0;l>>8),d=i+g,u=d>>>2;S.length<=u;)S.push(0);S[u]|=a<<8*(f+s*(d%4)),i+=2}return{value:S,binLen:i*8+r}}function Xh(t,e,n,r){let s,a,o,i;if(t.length%2!==0)throw new Error("String of HEX type must be in byte increments");n=n||0;const l=e||[0],c=n>>>3,u=r===-1?3:0;for(s=0;s>>1)+c,o=i>>>2;l.length<=o;)l.push(0);l[o]|=a<<8*(u+r*(i%4))}return{value:l,binLen:t.length*4+n}}function qh(t,e,n,r){let s,a,o,i;n=n||0;const l=e||[0],c=n>>>3,u=r===-1?3:0;for(a=0;a>>2,l.length<=o&&l.push(0),l[o]|=s<<8*(u+r*(i%4));return{value:l,binLen:t.length*8+n}}function Jh(t,e,n,r){let s=0,a,o,i,l,c,u,d;n=n||0;const f=e||[0],y=n>>>3,S=r===-1?3:0,g=t.indexOf("=");if(t.search(/^[a-z\d=+/]+$/i)===-1)throw new Error("Invalid character in base-64 string");if(t=t.replace(/=/g,""),g!==-1&&g{const[n,r]=e.toString().split(".");return r?r.length:0}),D(this,"amend",(e,n=15)=>parseFloat(Number(e).toPrecision(n))),D(this,"power",(e,n)=>Math.pow(10,Math.max(this.getDecimalLength(e),this.getDecimalLength(n))))}};D(Ge,"handleMethod",(t,e)=>{const n=new Ge,{power:r,amend:s}=n,a=r(t,e),o=s(t*a),i=s(e*a);return l=>{switch(l){case"+":return(o+i)/a;case"-":return(o-i)/a;case"*":return o*i/(a*a);case"/":return o/i}}});D(Ge,"add",(t,e)=>Ge.handleMethod(t,e)("+"));D(Ge,"divide",(t,e)=>Ge.handleMethod(t,e)("/"));D(Ge,"multiply",(t,e)=>Ge.handleMethod(t,e)("*"));D(Ge,"subtract",(t,e)=>Ge.handleMethod(t,e)("-"));var Lt=(t=>(t.NORMAL="normal",t.ERROR="error",t.WARNING="warning",t))(Lt||{}),Qt=(t=>(t.EN="en",t.ZH_CN="zh-CN",t))(Qt||{});const Va="ran_chaxus_lang",is=[],jm={"zh-CN":{lang:"简体中文"},en:{lang:"English"}};var Da=(t=>(t.LEGACY="legacy",t))(Da||{});const ls="PWA_INSTALL_ID",xm="pwa-install",Km="/ran/manifest.json",Gm=!1;Dm();const nr={isDev:Gm,locale:Qt.EN,currentDevice:La(),isWeiXin:Kh(),isMobile:Gh(),isBang:Yh()},Ym={install:t=>{t.config.globalProperties.$env=nr,t.provide("$env",nr)}};/*! + * shared v10.0.1 + * (c) 2024 kazuya kawaguchi + * Released under the MIT License. + */const mn=typeof window<"u",ut=(t,e=!1)=>e?Symbol.for(t):Symbol(t),zm=(t,e,n)=>Xm({l:t,k:e,s:n}),Xm=t=>JSON.stringify(t).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029").replace(/\u0027/g,"\\u0027"),we=t=>typeof t=="number"&&isFinite(t),qm=t=>Ua(t)==="[object Date]",At=t=>Ua(t)==="[object RegExp]",On=t=>ee(t)&&Object.keys(t).length===0,ke=Object.assign;let cs;const mt=()=>cs||(cs=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function us(t){return t.replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}const Jm=Object.prototype.hasOwnProperty;function pn(t,e){return Jm.call(t,e)}const ve=Array.isArray,me=t=>typeof t=="function",H=t=>typeof t=="string",ie=t=>typeof t=="boolean",ce=t=>t!==null&&typeof t=="object",Qm=t=>ce(t)&&me(t.then)&&me(t.catch),Ha=Object.prototype.toString,Ua=t=>Ha.call(t),ee=t=>{if(!ce(t))return!1;const e=Object.getPrototypeOf(t);return e===null||e.constructor===Object},Zm=t=>t==null?"":ve(t)||ee(t)&&t.toString===Ha?JSON.stringify(t,null,2):String(t);function Sr(t,e=""){return t.reduce((n,r,s)=>s===0?n+r:n+e+r,"")}function ep(t,e){typeof console<"u"&&(console.warn("[intlify] "+t),e&&console.warn(e.stack))}const nn=t=>!ce(t)||ve(t);function ln(t,e){if(nn(t)||nn(e))throw new Error("Invalid value");const n=[{src:t,des:e}];for(;n.length;){const{src:r,des:s}=n.pop();Object.keys(r).forEach(a=>{nn(r[a])||nn(s[a])?s[a]=r[a]:n.push({src:r[a],des:s[a]})})}}/*! + * message-compiler v10.0.1 + * (c) 2024 kazuya kawaguchi + * Released under the MIT License. + */function tp(t,e,n){return{line:t,column:e,offset:n}}function rr(t,e,n){return{start:t,end:e}}const de={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,MUST_HAVE_MESSAGES_IN_PLURAL:11,UNEXPECTED_EMPTY_LINKED_MODIFIER:12,UNEXPECTED_EMPTY_LINKED_KEY:13,UNEXPECTED_LEXICAL_ANALYSIS:14,UNHANDLED_CODEGEN_NODE_TYPE:15,UNHANDLED_MINIFIER_NODE_TYPE:16},np=17;function Cn(t,e,n={}){const{domain:r,messages:s,args:a}=n,o=t,i=new SyntaxError(String(o));return i.code=t,e&&(i.location=e),i.domain=r,i}function rp(t){throw t}const ze=" ",sp="\r",Ae=` +`,ap="\u2028",op="\u2029";function ip(t){const e=t;let n=0,r=1,s=1,a=0;const o=N=>e[N]===sp&&e[N+1]===Ae,i=N=>e[N]===Ae,l=N=>e[N]===op,c=N=>e[N]===ap,u=N=>o(N)||i(N)||l(N)||c(N),d=()=>n,f=()=>r,y=()=>s,S=()=>a,g=N=>o(N)||l(N)||c(N)?Ae:e[N],b=()=>g(n),p=()=>g(n+a);function E(){return a=0,u(n)&&(r++,s=0),o(n)&&n++,n++,s++,e[n]}function I(){return o(n+a)&&a++,a++,e[n+a]}function L(){n=0,r=1,s=1,a=0}function P(N=0){a=N}function T(){const N=n+a;for(;N!==n;)E();a=0}return{index:d,line:f,column:y,peekOffset:S,charAt:g,currentChar:b,currentPeek:p,next:E,peek:I,reset:L,resetPeek:P,skipToPeek:T}}const st=void 0,lp=".",ds="'",cp="tokenizer";function up(t,e={}){const n=e.location!==!1,r=ip(t),s=()=>r.index(),a=()=>tp(r.line(),r.column(),r.index()),o=a(),i=s(),l={currentType:13,offset:i,startLoc:o,endLoc:o,lastType:13,lastOffset:i,lastStartLoc:o,lastEndLoc:o,braceNest:0,inLinked:!1,text:""},c=()=>l,{onError:u}=e;function d(h,m,$,...z){const be=c();if(m.column+=$,m.offset+=$,u){const ne=n?rr(be.startLoc,m):null,O=Cn(h,ne,{domain:cp,args:z});u(O)}}function f(h,m,$){h.endLoc=a(),h.currentType=m;const z={type:m};return n&&(z.loc=rr(h.startLoc,h.endLoc)),$!=null&&(z.value=$),z}const y=h=>f(h,13);function S(h,m){return h.currentChar()===m?(h.next(),m):(d(de.EXPECTED_TOKEN,a(),0,m),"")}function g(h){let m="";for(;h.currentPeek()===ze||h.currentPeek()===Ae;)m+=h.currentPeek(),h.peek();return m}function b(h){const m=g(h);return h.skipToPeek(),m}function p(h){if(h===st)return!1;const m=h.charCodeAt(0);return m>=97&&m<=122||m>=65&&m<=90||m===95}function E(h){if(h===st)return!1;const m=h.charCodeAt(0);return m>=48&&m<=57}function I(h,m){const{currentType:$}=m;if($!==2)return!1;g(h);const z=p(h.currentPeek());return h.resetPeek(),z}function L(h,m){const{currentType:$}=m;if($!==2)return!1;g(h);const z=h.currentPeek()==="-"?h.peek():h.currentPeek(),be=E(z);return h.resetPeek(),be}function P(h,m){const{currentType:$}=m;if($!==2)return!1;g(h);const z=h.currentPeek()===ds;return h.resetPeek(),z}function T(h,m){const{currentType:$}=m;if($!==7)return!1;g(h);const z=h.currentPeek()===".";return h.resetPeek(),z}function N(h,m){const{currentType:$}=m;if($!==8)return!1;g(h);const z=p(h.currentPeek());return h.resetPeek(),z}function B(h,m){const{currentType:$}=m;if(!($===7||$===11))return!1;g(h);const z=h.currentPeek()===":";return h.resetPeek(),z}function G(h,m){const{currentType:$}=m;if($!==9)return!1;const z=()=>{const ne=h.currentPeek();return ne==="{"?p(h.peek()):ne==="@"||ne==="|"||ne===":"||ne==="."||ne===ze||!ne?!1:ne===Ae?(h.peek(),z()):ge(h,!1)},be=z();return h.resetPeek(),be}function le(h){g(h);const m=h.currentPeek()==="|";return h.resetPeek(),m}function ge(h,m=!0){const $=(be=!1,ne="")=>{const O=h.currentPeek();return O==="{"||O==="@"||!O?be:O==="|"?!(ne===ze||ne===Ae):O===ze?(h.peek(),$(!0,ze)):O===Ae?(h.peek(),$(!0,Ae)):!0},z=$();return m&&h.resetPeek(),z}function ae(h,m){const $=h.currentChar();return $===st?st:m($)?(h.next(),$):null}function _e(h){const m=h.charCodeAt(0);return m>=97&&m<=122||m>=65&&m<=90||m>=48&&m<=57||m===95||m===36}function Ne(h){return ae(h,_e)}function Te(h){const m=h.charCodeAt(0);return m>=97&&m<=122||m>=65&&m<=90||m>=48&&m<=57||m===95||m===36||m===45}function tt(h){return ae(h,Te)}function De(h){const m=h.charCodeAt(0);return m>=48&&m<=57}function nt(h){return ae(h,De)}function Ee(h){const m=h.charCodeAt(0);return m>=48&&m<=57||m>=65&&m<=70||m>=97&&m<=102}function rt(h){return ae(h,Ee)}function J(h){let m="",$="";for(;m=nt(h);)$+=m;return $}function te(h){let m="";for(;;){const $=h.currentChar();if($==="{"||$==="}"||$==="@"||$==="|"||!$)break;if($===ze||$===Ae)if(ge(h))m+=$,h.next();else{if(le(h))break;m+=$,h.next()}else m+=$,h.next()}return m}function V(h){b(h);let m="",$="";for(;m=tt(h);)$+=m;return h.currentChar()===st&&d(de.UNTERMINATED_CLOSING_BRACE,a(),0),$}function re(h){b(h);let m="";return h.currentChar()==="-"?(h.next(),m+=`-${J(h)}`):m+=J(h),h.currentChar()===st&&d(de.UNTERMINATED_CLOSING_BRACE,a(),0),m}function Y(h){return h!==ds&&h!==Ae}function oe(h){b(h),S(h,"'");let m="",$="";for(;m=ae(h,Y);)m==="\\"?$+=Le(h):$+=m;const z=h.currentChar();return z===Ae||z===st?(d(de.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER,a(),0),z===Ae&&(h.next(),S(h,"'")),$):(S(h,"'"),$)}function Le(h){const m=h.currentChar();switch(m){case"\\":case"'":return h.next(),`\\${m}`;case"u":return Se(h,m,4);case"U":return Se(h,m,6);default:return d(de.UNKNOWN_ESCAPE_SEQUENCE,a(),0,m),""}}function Se(h,m,$){S(h,m);let z="";for(let be=0;be<$;be++){const ne=rt(h);if(!ne){d(de.INVALID_UNICODE_ESCAPE_SEQUENCE,a(),0,`\\${m}${z}${h.currentChar()}`);break}z+=ne}return`\\${m}${z}`}function vt(h){return h!=="{"&&h!=="}"&&h!==ze&&h!==Ae}function Fe(h){b(h);let m="",$="";for(;m=ae(h,vt);)$+=m;return $}function Mn(h){let m="",$="";for(;m=Ne(h);)$+=m;return $}function Nn(h){const m=$=>{const z=h.currentChar();return z==="{"||z==="@"||z==="|"||z==="("||z===")"||!z||z===ze?$:($+=z,h.next(),m($))};return m("")}function Ft(h){b(h);const m=S(h,"|");return b(h),m}function gt(h,m){let $=null;switch(h.currentChar()){case"{":return m.braceNest>=1&&d(de.NOT_ALLOW_NEST_PLACEHOLDER,a(),0),h.next(),$=f(m,2,"{"),b(h),m.braceNest++,$;case"}":return m.braceNest>0&&m.currentType===2&&d(de.EMPTY_PLACEHOLDER,a(),0),h.next(),$=f(m,3,"}"),m.braceNest--,m.braceNest>0&&b(h),m.inLinked&&m.braceNest===0&&(m.inLinked=!1),$;case"@":return m.braceNest>0&&d(de.UNTERMINATED_CLOSING_BRACE,a(),0),$=bt(h,m)||y(m),m.braceNest=0,$;default:{let be=!0,ne=!0,O=!0;if(le(h))return m.braceNest>0&&d(de.UNTERMINATED_CLOSING_BRACE,a(),0),$=f(m,1,Ft(h)),m.braceNest=0,m.inLinked=!1,$;if(m.braceNest>0&&(m.currentType===4||m.currentType===5||m.currentType===6))return d(de.UNTERMINATED_CLOSING_BRACE,a(),0),m.braceNest=0,Rt(h,m);if(be=I(h,m))return $=f(m,4,V(h)),b(h),$;if(ne=L(h,m))return $=f(m,5,re(h)),b(h),$;if(O=P(h,m))return $=f(m,6,oe(h)),b(h),$;if(!be&&!ne&&!O)return $=f(m,12,Fe(h)),d(de.INVALID_TOKEN_IN_PLACEHOLDER,a(),0,$.value),b(h),$;break}}return $}function bt(h,m){const{currentType:$}=m;let z=null;const be=h.currentChar();switch(($===7||$===8||$===11||$===9)&&(be===Ae||be===ze)&&d(de.INVALID_LINKED_FORMAT,a(),0),be){case"@":return h.next(),z=f(m,7,"@"),m.inLinked=!0,z;case".":return b(h),h.next(),f(m,8,".");case":":return b(h),h.next(),f(m,9,":");default:return le(h)?(z=f(m,1,Ft(h)),m.braceNest=0,m.inLinked=!1,z):T(h,m)||B(h,m)?(b(h),bt(h,m)):N(h,m)?(b(h),f(m,11,Mn(h))):G(h,m)?(b(h),be==="{"?gt(h,m)||z:f(m,10,Nn(h))):($===7&&d(de.INVALID_LINKED_FORMAT,a(),0),m.braceNest=0,m.inLinked=!1,Rt(h,m))}}function Rt(h,m){let $={type:13};if(m.braceNest>0)return gt(h,m)||y(m);if(m.inLinked)return bt(h,m)||y(m);switch(h.currentChar()){case"{":return gt(h,m)||y(m);case"}":return d(de.UNBALANCED_CLOSING_BRACE,a(),0),h.next(),f(m,3,"}");case"@":return bt(h,m)||y(m);default:{if(le(h))return $=f(m,1,Ft(h)),m.braceNest=0,m.inLinked=!1,$;if(ge(h))return f(m,0,te(h));break}}return $}function $n(){const{currentType:h,offset:m,startLoc:$,endLoc:z}=l;return l.lastType=h,l.lastOffset=m,l.lastStartLoc=$,l.lastEndLoc=z,l.offset=s(),l.startLoc=a(),r.currentChar()===st?f(l,13):Rt(r,l)}return{nextToken:$n,currentOffset:s,currentPosition:a,context:c}}const dp="parser",fp=/(?:\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6}))/g;function hp(t,e,n){switch(t){case"\\\\":return"\\";case"\\'":return"'";default:{const r=parseInt(e||n,16);return r<=55295||r>=57344?String.fromCodePoint(r):"�"}}}function mp(t={}){const e=t.location!==!1,{onError:n}=t;function r(p,E,I,L,...P){const T=p.currentPosition();if(T.offset+=L,T.column+=L,n){const N=e?rr(I,T):null,B=Cn(E,N,{domain:dp,args:P});n(B)}}function s(p,E,I){const L={type:p};return e&&(L.start=E,L.end=E,L.loc={start:I,end:I}),L}function a(p,E,I,L){e&&(p.end=E,p.loc&&(p.loc.end=I))}function o(p,E){const I=p.context(),L=s(3,I.offset,I.startLoc);return L.value=E,a(L,p.currentOffset(),p.currentPosition()),L}function i(p,E){const I=p.context(),{lastOffset:L,lastStartLoc:P}=I,T=s(5,L,P);return T.index=parseInt(E,10),p.nextToken(),a(T,p.currentOffset(),p.currentPosition()),T}function l(p,E){const I=p.context(),{lastOffset:L,lastStartLoc:P}=I,T=s(4,L,P);return T.key=E,p.nextToken(),a(T,p.currentOffset(),p.currentPosition()),T}function c(p,E){const I=p.context(),{lastOffset:L,lastStartLoc:P}=I,T=s(9,L,P);return T.value=E.replace(fp,hp),p.nextToken(),a(T,p.currentOffset(),p.currentPosition()),T}function u(p){const E=p.nextToken(),I=p.context(),{lastOffset:L,lastStartLoc:P}=I,T=s(8,L,P);return E.type!==11?(r(p,de.UNEXPECTED_EMPTY_LINKED_MODIFIER,I.lastStartLoc,0),T.value="",a(T,L,P),{nextConsumeToken:E,node:T}):(E.value==null&&r(p,de.UNEXPECTED_LEXICAL_ANALYSIS,I.lastStartLoc,0,He(E)),T.value=E.value||"",a(T,p.currentOffset(),p.currentPosition()),{node:T})}function d(p,E){const I=p.context(),L=s(7,I.offset,I.startLoc);return L.value=E,a(L,p.currentOffset(),p.currentPosition()),L}function f(p){const E=p.context(),I=s(6,E.offset,E.startLoc);let L=p.nextToken();if(L.type===8){const P=u(p);I.modifier=P.node,L=P.nextConsumeToken||p.nextToken()}switch(L.type!==9&&r(p,de.UNEXPECTED_LEXICAL_ANALYSIS,E.lastStartLoc,0,He(L)),L=p.nextToken(),L.type===2&&(L=p.nextToken()),L.type){case 10:L.value==null&&r(p,de.UNEXPECTED_LEXICAL_ANALYSIS,E.lastStartLoc,0,He(L)),I.key=d(p,L.value||"");break;case 4:L.value==null&&r(p,de.UNEXPECTED_LEXICAL_ANALYSIS,E.lastStartLoc,0,He(L)),I.key=l(p,L.value||"");break;case 5:L.value==null&&r(p,de.UNEXPECTED_LEXICAL_ANALYSIS,E.lastStartLoc,0,He(L)),I.key=i(p,L.value||"");break;case 6:L.value==null&&r(p,de.UNEXPECTED_LEXICAL_ANALYSIS,E.lastStartLoc,0,He(L)),I.key=c(p,L.value||"");break;default:{r(p,de.UNEXPECTED_EMPTY_LINKED_KEY,E.lastStartLoc,0);const P=p.context(),T=s(7,P.offset,P.startLoc);return T.value="",a(T,P.offset,P.startLoc),I.key=T,a(I,P.offset,P.startLoc),{nextConsumeToken:L,node:I}}}return a(I,p.currentOffset(),p.currentPosition()),{node:I}}function y(p){const E=p.context(),I=E.currentType===1?p.currentOffset():E.offset,L=E.currentType===1?E.endLoc:E.startLoc,P=s(2,I,L);P.items=[];let T=null;do{const G=T||p.nextToken();switch(T=null,G.type){case 0:G.value==null&&r(p,de.UNEXPECTED_LEXICAL_ANALYSIS,E.lastStartLoc,0,He(G)),P.items.push(o(p,G.value||""));break;case 5:G.value==null&&r(p,de.UNEXPECTED_LEXICAL_ANALYSIS,E.lastStartLoc,0,He(G)),P.items.push(i(p,G.value||""));break;case 4:G.value==null&&r(p,de.UNEXPECTED_LEXICAL_ANALYSIS,E.lastStartLoc,0,He(G)),P.items.push(l(p,G.value||""));break;case 6:G.value==null&&r(p,de.UNEXPECTED_LEXICAL_ANALYSIS,E.lastStartLoc,0,He(G)),P.items.push(c(p,G.value||""));break;case 7:{const le=f(p);P.items.push(le.node),T=le.nextConsumeToken||null;break}}}while(E.currentType!==13&&E.currentType!==1);const N=E.currentType===1?E.lastOffset:p.currentOffset(),B=E.currentType===1?E.lastEndLoc:p.currentPosition();return a(P,N,B),P}function S(p,E,I,L){const P=p.context();let T=L.items.length===0;const N=s(1,E,I);N.cases=[],N.cases.push(L);do{const B=y(p);T||(T=B.items.length===0),N.cases.push(B)}while(P.currentType!==13);return T&&r(p,de.MUST_HAVE_MESSAGES_IN_PLURAL,I,0),a(N,p.currentOffset(),p.currentPosition()),N}function g(p){const E=p.context(),{offset:I,startLoc:L}=E,P=y(p);return E.currentType===13?P:S(p,I,L,P)}function b(p){const E=up(p,ke({},t)),I=E.context(),L=s(0,I.offset,I.startLoc);return e&&L.loc&&(L.loc.source=p),L.body=g(E),t.onCacheKey&&(L.cacheKey=t.onCacheKey(p)),I.currentType!==13&&r(E,de.UNEXPECTED_LEXICAL_ANALYSIS,I.lastStartLoc,0,p[I.offset]||""),a(L,E.currentOffset(),E.currentPosition()),L}return{parse:b}}function He(t){if(t.type===13)return"EOF";const e=(t.value||"").replace(/\r?\n/gu,"\\n");return e.length>10?e.slice(0,9)+"…":e}function pp(t,e={}){const n={ast:t,helpers:new Set};return{context:()=>n,helper:a=>(n.helpers.add(a),a)}}function fs(t,e){for(let n=0;nhs(n)),t}function hs(t){if(t.items.length===1){const e=t.items[0];(e.type===3||e.type===9)&&(t.static=e.value,delete e.value)}else{const e=[];for(let n=0;ni;function c(b,p){i.code+=b}function u(b,p=!0){const E=p?s:"";c(a?E+" ".repeat(b):E)}function d(b=!0){const p=++i.indentLevel;b&&u(p)}function f(b=!0){const p=--i.indentLevel;b&&u(p)}function y(){u(i.indentLevel)}return{context:l,push:c,indent:d,deindent:f,newline:y,helper:b=>`_${b}`,needIndent:()=>i.needIndent}}function bp(t,e){const{helper:n}=t;t.push(`${n("linked")}(`),It(t,e.key),e.modifier?(t.push(", "),It(t,e.modifier),t.push(", _type")):t.push(", undefined, _type"),t.push(")")}function yp(t,e){const{helper:n,needIndent:r}=t;t.push(`${n("normalize")}([`),t.indent(r());const s=e.items.length;for(let a=0;a1){t.push(`${n("plural")}([`),t.indent(r());const s=e.cases.length;for(let a=0;a{const n=H(e.mode)?e.mode:"normal",r=H(e.filename)?e.filename:"message.intl",s=!!e.sourceMap,a=e.breakLineCode!=null?e.breakLineCode:n==="arrow"?";":` +`,o=e.needIndent?e.needIndent:n!=="arrow",i=t.helpers||[],l=gp(t,{mode:n,filename:r,sourceMap:s,breakLineCode:a,needIndent:o});l.push(n==="normal"?"function __msg__ (ctx) {":"(ctx) => {"),l.indent(o),i.length>0&&(l.push(`const { ${Sr(i.map(d=>`${d}: _${d}`),", ")} } = ctx`),l.newline()),l.push("return "),It(l,t),l.deindent(o),l.push("}"),delete t.helpers;const{code:c,map:u}=l.context();return{ast:t,code:c,map:u?u.toJSON():void 0}};function Sp(t,e={}){const n=ke({},e),r=!!n.jit,s=!!n.minify,a=n.optimize==null?!0:n.optimize,i=mp(n).parse(t);return r?(a&&vp(i),s&&St(i),{ast:i,code:""}):(_p(i,n),Lp(i,n))}/*! + * core-base v10.0.1 + * (c) 2024 kazuya kawaguchi + * Released under the MIT License. + */function Ep(){typeof __INTLIFY_PROD_DEVTOOLS__!="boolean"&&(mt().__INTLIFY_PROD_DEVTOOLS__=!1),typeof __INTLIFY_DROP_MESSAGE_COMPILER__!="boolean"&&(mt().__INTLIFY_DROP_MESSAGE_COMPILER__=!1)}function Dn(t){return n=>Op(n,t)}function Op(t,e){const n=e.b||e.body;if((n.t||n.type)===1){const r=n,s=r.c||r.cases;return t.plural(s.reduce((a,o)=>[...a,ms(t,o)],[]))}else return ms(t,n)}function ms(t,e){const n=e.s||e.static;if(n)return t.type==="text"?n:t.normalize([n]);{const r=(e.i||e.items).reduce((s,a)=>[...s,sr(t,a)],[]);return t.normalize(r)}}function sr(t,e){const n=e.t||e.type;switch(n){case 3:{const r=e;return r.v||r.value}case 9:{const r=e;return r.v||r.value}case 4:{const r=e;return t.interpolate(t.named(r.k||r.key))}case 5:{const r=e;return t.interpolate(t.list(r.i!=null?r.i:r.index))}case 6:{const r=e,s=r.m||r.modifier;return t.linked(sr(t,r.k||r.key),s?sr(t,s):void 0,t.type)}case 7:{const r=e;return r.v||r.value}case 8:{const r=e;return r.v||r.value}default:throw new Error(`unhandled node type on format message part: ${n}`)}}const Cp=t=>t;let rn=Object.create(null);const Mt=t=>ce(t)&&(t.t===0||t.type===0)&&("b"in t||"body"in t);function Ap(t,e={}){let n=!1;const r=e.onError||rp;return e.onError=s=>{n=!0,r(s)},{...Sp(t,e),detectError:n}}function Ip(t,e){if(!__INTLIFY_DROP_MESSAGE_COMPILER__&&H(t)){ie(e.warnHtmlMessage)&&e.warnHtmlMessage;const r=(e.onCacheKey||Cp)(t),s=rn[r];if(s)return s;const{ast:a,detectError:o}=Ap(t,{...e,location:!1,jit:!0}),i=Dn(a);return o?i:rn[r]=i}else{const n=t.cacheKey;if(n){const r=rn[n];return r||(rn[n]=Dn(t))}else return Dn(t)}}let xt=null;function Mp(t){xt=t}function Np(t,e,n){xt&&xt.emit("i18n:init",{timestamp:Date.now(),i18n:t,version:e,meta:n})}const $p=Pp("function:translate");function Pp(t){return e=>xt&&xt.emit(t,e)}const Je={INVALID_ARGUMENT:np,INVALID_DATE_ARGUMENT:18,INVALID_ISO_DATE_ARGUMENT:19,NOT_SUPPORT_NON_STRING_MESSAGE:20,NOT_SUPPORT_LOCALE_PROMISE_VALUE:21,NOT_SUPPORT_LOCALE_ASYNC_FUNCTION:22,NOT_SUPPORT_LOCALE_TYPE:23},Tp=24;function Qe(t){return Cn(t,null,void 0)}function Or(t,e){return e.locale!=null?ps(e.locale):ps(t.locale)}let Hn;function ps(t){if(H(t))return t;if(me(t)){if(t.resolvedOnce&&Hn!=null)return Hn;if(t.constructor.name==="Function"){const e=t();if(Qm(e))throw Qe(Je.NOT_SUPPORT_LOCALE_PROMISE_VALUE);return Hn=e}else throw Qe(Je.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION)}else throw Qe(Je.NOT_SUPPORT_LOCALE_TYPE)}function Fp(t,e,n){return[...new Set([n,...ve(e)?e:ce(e)?Object.keys(e):H(e)?[e]:[n]])]}function Ba(t,e,n){const r=H(n)?n:Kt,s=t;s.__localeChainCache||(s.__localeChainCache=new Map);let a=s.__localeChainCache.get(r);if(!a){a=[];let o=[n];for(;ve(o);)o=_s(a,o,e);const i=ve(e)||!ee(e)?e:e.default?e.default:null;o=H(i)?[i]:i,ve(o)&&_s(a,o,!1),s.__localeChainCache.set(r,a)}return a}function _s(t,e,n){let r=!0;for(let s=0;s{o===void 0?o=i:o+=i},f[1]=()=>{o!==void 0&&(e.push(o),o=void 0)},f[2]=()=>{f[0](),s++},f[3]=()=>{if(s>0)s--,r=4,f[0]();else{if(s=0,o===void 0||(o=Wp(o),o===!1))return!1;f[1]()}};function y(){const S=t[n+1];if(r===5&&S==="'"||r===6&&S==='"')return n++,i="\\"+S,f[0](),!0}for(;r!==null;)if(n++,a=t[n],!(a==="\\"&&y())){if(l=Bp(a),d=dt[r],c=d[l]||d.l||8,c===8||(r=c[0],c[1]!==void 0&&(u=f[c[1]],u&&(i=a,u()===!1))))return;if(r===7)return e}}const vs=new Map;function xp(t,e){return ce(t)?t[e]:null}function Kp(t,e){if(!ce(t))return null;let n=vs.get(e);if(n||(n=jp(e),n&&vs.set(e,n)),!n)return null;const r=n.length;let s=t,a=0;for(;a`${t.charAt(0).toLocaleUpperCase()}${t.substr(1)}`;function Yp(){return{upper:(t,e)=>e==="text"&&H(t)?t.toUpperCase():e==="vnode"&&ce(t)&&"__v_isVNode"in t?t.children.toUpperCase():t,lower:(t,e)=>e==="text"&&H(t)?t.toLowerCase():e==="vnode"&&ce(t)&&"__v_isVNode"in t?t.children.toLowerCase():t,capitalize:(t,e)=>e==="text"&&H(t)?bs(t):e==="vnode"&&ce(t)&&"__v_isVNode"in t?bs(t.children):t}}let Wa;function zp(t){Wa=t}let ja;function Xp(t){ja=t}let xa;function qp(t){xa=t}let Ka=null;const Jp=t=>{Ka=t},Qp=()=>Ka;let Ga=null;const ys=t=>{Ga=t},Zp=()=>Ga;let ws=0;function e1(t={}){const e=me(t.onWarn)?t.onWarn:ep,n=H(t.version)?t.version:Gp,r=H(t.locale)||me(t.locale)?t.locale:Kt,s=me(r)?Kt:r,a=ve(t.fallbackLocale)||ee(t.fallbackLocale)||H(t.fallbackLocale)||t.fallbackLocale===!1?t.fallbackLocale:s,o=ee(t.messages)?t.messages:{[s]:{}},i=ee(t.datetimeFormats)?t.datetimeFormats:{[s]:{}},l=ee(t.numberFormats)?t.numberFormats:{[s]:{}},c=ke({},t.modifiers||{},Yp()),u=t.pluralRules||{},d=me(t.missing)?t.missing:null,f=ie(t.missingWarn)||At(t.missingWarn)?t.missingWarn:!0,y=ie(t.fallbackWarn)||At(t.fallbackWarn)?t.fallbackWarn:!0,S=!!t.fallbackFormat,g=!!t.unresolving,b=me(t.postTranslation)?t.postTranslation:null,p=ee(t.processor)?t.processor:null,E=ie(t.warnHtmlMessage)?t.warnHtmlMessage:!0,I=!!t.escapeParameter,L=me(t.messageCompiler)?t.messageCompiler:Wa,P=me(t.messageResolver)?t.messageResolver:ja||xp,T=me(t.localeFallbacker)?t.localeFallbacker:xa||Fp,N=ce(t.fallbackContext)?t.fallbackContext:void 0,B=t,G=ce(B.__datetimeFormatters)?B.__datetimeFormatters:new Map,le=ce(B.__numberFormatters)?B.__numberFormatters:new Map,ge=ce(B.__meta)?B.__meta:{};ws++;const ae={version:n,cid:ws,locale:r,fallbackLocale:a,messages:o,modifiers:c,pluralRules:u,missing:d,missingWarn:f,fallbackWarn:y,fallbackFormat:S,unresolving:g,postTranslation:b,processor:p,warnHtmlMessage:E,escapeParameter:I,messageCompiler:L,messageResolver:P,localeFallbacker:T,fallbackContext:N,onWarn:e,__meta:ge};return ae.datetimeFormats=i,ae.numberFormats=l,ae.__datetimeFormatters=G,ae.__numberFormatters=le,__INTLIFY_PROD_DEVTOOLS__&&Np(ae,n,ge),ae}function Cr(t,e,n,r,s){const{missing:a,onWarn:o}=t;if(a!==null){const i=a(t,n,e,s);return H(i)?i:e}else return e}function Ht(t,e,n){const r=t;r.__localeChainCache=new Map,t.localeFallbacker(t,n,e)}function t1(t,e){return t===e?!1:t.split("-")[0]===e.split("-")[0]}function n1(t,e){const n=e.indexOf(t);if(n===-1)return!1;for(let r=n+1;r{Ya.includes(l)?o[l]=n[l]:a[l]=n[l]}),H(r)?a.locale=r:ee(r)&&(o=r),ee(s)&&(o=s),[a.key||"",i,a,o]}function Ls(t,e,n){const r=t;for(const s in n){const a=`${e}__${s}`;r.__datetimeFormatters.has(a)&&r.__datetimeFormatters.delete(a)}}function Ss(t,...e){const{numberFormats:n,unresolving:r,fallbackLocale:s,onWarn:a,localeFallbacker:o}=t,{__numberFormatters:i}=t,[l,c,u,d]=or(...e),f=ie(u.missingWarn)?u.missingWarn:t.missingWarn;ie(u.fallbackWarn)?u.fallbackWarn:t.fallbackWarn;const y=!!u.part,S=Or(t,u),g=o(t,s,S);if(!H(l)||l==="")return new Intl.NumberFormat(S,d).format(c);let b={},p,E=null;const I="number format";for(let T=0;T{za.includes(l)?o[l]=n[l]:a[l]=n[l]}),H(r)?a.locale=r:ee(r)&&(o=r),ee(s)&&(o=s),[a.key||"",i,a,o]}function Es(t,e,n){const r=t;for(const s in n){const a=`${e}__${s}`;r.__numberFormatters.has(a)&&r.__numberFormatters.delete(a)}}const r1=t=>t,s1=t=>"",a1="text",o1=t=>t.length===0?"":Sr(t),i1=Zm;function Os(t,e){return t=Math.abs(t),e===2?t?t>1?1:0:1:t?Math.min(t,2):0}function l1(t){const e=we(t.pluralIndex)?t.pluralIndex:-1;return t.named&&(we(t.named.count)||we(t.named.n))?we(t.named.count)?t.named.count:we(t.named.n)?t.named.n:e:e}function c1(t,e){e.count||(e.count=t),e.n||(e.n=t)}function u1(t={}){const e=t.locale,n=l1(t),r=ce(t.pluralRules)&&H(e)&&me(t.pluralRules[e])?t.pluralRules[e]:Os,s=ce(t.pluralRules)&&H(e)&&me(t.pluralRules[e])?Os:void 0,a=p=>p[r(n,p.length,s)],o=t.list||[],i=p=>o[p],l=t.named||{};we(t.pluralIndex)&&c1(n,l);const c=p=>l[p];function u(p,E){const I=me(t.messages)?t.messages(p,!!E):ce(t.messages)?t.messages[p]:!1;return I||(t.parent?t.parent.message(p):s1)}const d=p=>t.modifiers?t.modifiers[p]:r1,f=ee(t.processor)&&me(t.processor.normalize)?t.processor.normalize:o1,y=ee(t.processor)&&me(t.processor.interpolate)?t.processor.interpolate:i1,S=ee(t.processor)&&H(t.processor.type)?t.processor.type:a1,b={list:i,named:c,plural:a,linked:(p,...E)=>{const[I,L]=E;let P="text",T="";E.length===1?ce(I)?(T=I.modifier||T,P=I.type||P):H(I)&&(T=I||T):E.length===2&&(H(I)&&(T=I||T),H(L)&&(P=L||P));const N=u(p,!0)(b),B=P==="vnode"&&ve(N)&&T?N[0]:N;return T?d(T)(B,P):B},message:u,type:S,interpolate:y,normalize:f,values:ke({},o,l)};return b}const Cs=()=>"",Pe=t=>me(t);function As(t,...e){const{fallbackFormat:n,postTranslation:r,unresolving:s,messageCompiler:a,fallbackLocale:o,messages:i}=t,[l,c]=ir(...e),u=ie(c.missingWarn)?c.missingWarn:t.missingWarn,d=ie(c.fallbackWarn)?c.fallbackWarn:t.fallbackWarn,f=ie(c.escapeParameter)?c.escapeParameter:t.escapeParameter,y=!!c.resolvedMessage,S=H(c.default)||ie(c.default)?ie(c.default)?a?l:()=>l:c.default:n?a?l:()=>l:null,g=n||S!=null&&(H(S)||me(S)),b=Or(t,c);f&&d1(c);let[p,E,I]=y?[l,b,i[b]||{}]:Xa(t,l,b,o,d,u),L=p,P=l;if(!y&&!(H(L)||Mt(L)||Pe(L))&&g&&(L=S,P=L),!y&&(!(H(L)||Mt(L)||Pe(L))||!H(E)))return s?An:l;let T=!1;const N=()=>{T=!0},B=Pe(L)?L:qa(t,l,E,L,P,N);if(T)return L;const G=m1(t,E,I,c),le=u1(G),ge=f1(t,B,le),ae=r?r(ge,l):ge;if(__INTLIFY_PROD_DEVTOOLS__){const _e={timestamp:Date.now(),key:H(l)?l:Pe(L)?L.key:"",locale:E||(Pe(L)?L.locale:""),format:H(L)?L:Pe(L)?L.source:"",message:ae};_e.meta=ke({},t.__meta,Qp()||{}),$p(_e)}return ae}function d1(t){ve(t.list)?t.list=t.list.map(e=>H(e)?us(e):e):ce(t.named)&&Object.keys(t.named).forEach(e=>{H(t.named[e])&&(t.named[e]=us(t.named[e]))})}function Xa(t,e,n,r,s,a){const{messages:o,onWarn:i,messageResolver:l,localeFallbacker:c}=t,u=c(t,r,n);let d={},f,y=null;const S="translate";for(let g=0;gr;return c.locale=n,c.key=e,c}const l=o(r,h1(t,n,s,r,i,a));return l.locale=n,l.key=e,l.source=r,l}function f1(t,e,n){return e(n)}function ir(...t){const[e,n,r]=t,s={};if(!H(e)&&!we(e)&&!Pe(e)&&!Mt(e))throw Qe(Je.INVALID_ARGUMENT);const a=we(e)?String(e):(Pe(e),e);return we(n)?s.plural=n:H(n)?s.default=n:ee(n)&&!On(n)?s.named=n:ve(n)&&(s.list=n),we(r)?s.plural=r:H(r)?s.default=r:ee(r)&&ke(s,r),[a,s]}function h1(t,e,n,r,s,a){return{locale:e,key:n,warnHtmlMessage:s,onError:o=>{throw a&&a(o),o},onCacheKey:o=>zm(e,n,o)}}function m1(t,e,n,r){const{modifiers:s,pluralRules:a,messageResolver:o,fallbackLocale:i,fallbackWarn:l,missingWarn:c,fallbackContext:u}=t,f={locale:e,modifiers:s,pluralRules:a,messages:(y,S)=>{let g=o(n,y);if(g==null&&(u||S)){const[,,b]=Xa(u||t,y,e,i,l,c);g=o(b,y)}if(H(g)||Mt(g)){let b=!1;const E=qa(t,y,e,g,y,()=>{b=!0});return b?Cs:E}else return Pe(g)?g:Cs}};return t.processor&&(f.processor=t.processor),r.list&&(f.list=r.list),r.named&&(f.named=r.named),we(r.plural)&&(f.pluralIndex=r.plural),f}Ep();/*! + * vue-i18n v10.0.1 + * (c) 2024 kazuya kawaguchi + * Released under the MIT License. + */const p1="10.0.1";function _1(){typeof __VUE_I18N_FULL_INSTALL__!="boolean"&&(mt().__VUE_I18N_FULL_INSTALL__=!0),typeof __VUE_I18N_LEGACY_API__!="boolean"&&(mt().__VUE_I18N_LEGACY_API__=!0),typeof __INTLIFY_DROP_MESSAGE_COMPILER__!="boolean"&&(mt().__INTLIFY_DROP_MESSAGE_COMPILER__=!1),typeof __INTLIFY_PROD_DEVTOOLS__!="boolean"&&(mt().__INTLIFY_PROD_DEVTOOLS__=!1)}const Ie={UNEXPECTED_RETURN_TYPE:Tp,INVALID_ARGUMENT:25,MUST_BE_CALL_SETUP_TOP:26,NOT_INSTALLED:27,REQUIRED_VALUE:28,INVALID_VALUE:29,CANNOT_SETUP_VUE_DEVTOOLS_PLUGIN:30,NOT_INSTALLED_WITH_PROVIDE:31,UNEXPECTED_ERROR:32,NOT_COMPATIBLE_LEGACY_VUE_I18N:33,NOT_AVAILABLE_COMPOSITION_IN_LEGACY:34};function Me(t,...e){return Cn(t,null,void 0)}const lr=ut("__translateVNode"),cr=ut("__datetimeParts"),ur=ut("__numberParts"),Ja=ut("__setPluralRules"),Qa=ut("__injectWithOption"),dr=ut("__dispose");function Gt(t){if(!ce(t))return t;for(const e in t)if(pn(t,e))if(!e.includes("."))ce(t[e])&&Gt(t[e]);else{const n=e.split("."),r=n.length-1;let s=t,a=!1;for(let o=0;o{if("locale"in i&&"resource"in i){const{locale:l,resource:c}=i;l?(o[l]=o[l]||{},ln(c,o[l])):ln(c,o)}else H(i)&&ln(JSON.parse(i),o)}),s==null&&a)for(const i in o)pn(o,i)&&Gt(o[i]);return o}function Za(t){return t.type}function eo(t,e,n){let r=ce(e.messages)?e.messages:{};"__i18nGlobal"in n&&(r=Ar(t.locale.value,{messages:r,__i18n:n.__i18nGlobal}));const s=Object.keys(r);s.length&&s.forEach(a=>{t.mergeLocaleMessage(a,r[a])});{if(ce(e.datetimeFormats)){const a=Object.keys(e.datetimeFormats);a.length&&a.forEach(o=>{t.mergeDateTimeFormat(o,e.datetimeFormats[o])})}if(ce(e.numberFormats)){const a=Object.keys(e.numberFormats);a.length&&a.forEach(o=>{t.mergeNumberFormat(o,e.numberFormats[o])})}}}function Is(t){return x(Eo,null,t,0)}const Ms="__INTLIFY_META__",Ns=()=>[],v1=()=>!1;let $s=0;function Ps(t){return(e,n,r,s)=>t(n,r,Wt()||void 0,s)}const g1=()=>{const t=Wt();let e=null;return t&&(e=Za(t)[Ms])?{[Ms]:e}:null};function Ir(t={}){const{__root:e,__injectWithOption:n}=t,r=e===void 0,s=t.flatJson,a=mn?X:bn;let o=ie(t.inheritLocale)?t.inheritLocale:!0;const i=a(e&&o?e.locale.value:H(t.locale)?t.locale:Kt),l=a(e&&o?e.fallbackLocale.value:H(t.fallbackLocale)||ve(t.fallbackLocale)||ee(t.fallbackLocale)||t.fallbackLocale===!1?t.fallbackLocale:i.value),c=a(Ar(i.value,t)),u=a(ee(t.datetimeFormats)?t.datetimeFormats:{[i.value]:{}}),d=a(ee(t.numberFormats)?t.numberFormats:{[i.value]:{}});let f=e?e.missingWarn:ie(t.missingWarn)||At(t.missingWarn)?t.missingWarn:!0,y=e?e.fallbackWarn:ie(t.fallbackWarn)||At(t.fallbackWarn)?t.fallbackWarn:!0,S=e?e.fallbackRoot:ie(t.fallbackRoot)?t.fallbackRoot:!0,g=!!t.fallbackFormat,b=me(t.missing)?t.missing:null,p=me(t.missing)?Ps(t.missing):null,E=me(t.postTranslation)?t.postTranslation:null,I=e?e.warnHtmlMessage:ie(t.warnHtmlMessage)?t.warnHtmlMessage:!0,L=!!t.escapeParameter;const P=e?e.modifiers:ee(t.modifiers)?t.modifiers:{};let T=t.pluralRules||e&&e.pluralRules,N;N=(()=>{r&&ys(null);const O={version:p1,locale:i.value,fallbackLocale:l.value,messages:c.value,modifiers:P,pluralRules:T,missing:p===null?void 0:p,missingWarn:f,fallbackWarn:y,fallbackFormat:g,unresolving:!0,postTranslation:E===null?void 0:E,warnHtmlMessage:I,escapeParameter:L,messageResolver:t.messageResolver,messageCompiler:t.messageCompiler,__meta:{framework:"vue"}};O.datetimeFormats=u.value,O.numberFormats=d.value,O.__datetimeFormatters=ee(N)?N.__datetimeFormatters:void 0,O.__numberFormatters=ee(N)?N.__numberFormatters:void 0;const F=e1(O);return r&&ys(F),F})(),Ht(N,i.value,l.value);function G(){return[i.value,l.value,c.value,u.value,d.value]}const le=U({get:()=>i.value,set:O=>{i.value=O,N.locale=i.value}}),ge=U({get:()=>l.value,set:O=>{l.value=O,N.fallbackLocale=l.value,Ht(N,i.value,O)}}),ae=U(()=>c.value),_e=U(()=>u.value),Ne=U(()=>d.value);function Te(){return me(E)?E:null}function tt(O){E=O,N.postTranslation=O}function De(){return b}function nt(O){O!==null&&(p=Ps(O)),b=O,N.missing=p}const Ee=(O,F,fe,ye,ft,Zt)=>{G();let yt;try{__INTLIFY_PROD_DEVTOOLS__,r||(N.fallbackContext=e?Zp():void 0),yt=O(N)}finally{__INTLIFY_PROD_DEVTOOLS__,r||(N.fallbackContext=void 0)}if(fe!=="translate exists"&&we(yt)&&yt===An||fe==="translate exists"&&!yt){const[oo,q1]=F();return e&&S?ye(e):ft(oo)}else{if(Zt(yt))return yt;throw Me(Ie.UNEXPECTED_RETURN_TYPE)}};function rt(...O){return Ee(F=>Reflect.apply(As,null,[F,...O]),()=>ir(...O),"translate",F=>Reflect.apply(F.t,F,[...O]),F=>F,F=>H(F))}function J(...O){const[F,fe,ye]=O;if(ye&&!ce(ye))throw Me(Ie.INVALID_ARGUMENT);return rt(F,fe,ke({resolvedMessage:!0},ye||{}))}function te(...O){return Ee(F=>Reflect.apply(ks,null,[F,...O]),()=>ar(...O),"datetime format",F=>Reflect.apply(F.d,F,[...O]),()=>gs,F=>H(F))}function V(...O){return Ee(F=>Reflect.apply(Ss,null,[F,...O]),()=>or(...O),"number format",F=>Reflect.apply(F.n,F,[...O]),()=>gs,F=>H(F))}function re(O){return O.map(F=>H(F)||we(F)||ie(F)?Is(String(F)):F)}const oe={normalize:re,interpolate:O=>O,type:"vnode"};function Le(...O){return Ee(F=>{let fe;const ye=F;try{ye.processor=oe,fe=Reflect.apply(As,null,[ye,...O])}finally{ye.processor=null}return fe},()=>ir(...O),"translate",F=>F[lr](...O),F=>[Is(F)],F=>ve(F))}function Se(...O){return Ee(F=>Reflect.apply(Ss,null,[F,...O]),()=>or(...O),"number format",F=>F[ur](...O),Ns,F=>H(F)||ve(F))}function vt(...O){return Ee(F=>Reflect.apply(ks,null,[F,...O]),()=>ar(...O),"datetime format",F=>F[cr](...O),Ns,F=>H(F)||ve(F))}function Fe(O){T=O,N.pluralRules=T}function Mn(O,F){return Ee(()=>{if(!O)return!1;const fe=H(F)?F:i.value,ye=gt(fe),ft=N.messageResolver(ye,O);return Mt(ft)||Pe(ft)||H(ft)},()=>[O],"translate exists",fe=>Reflect.apply(fe.te,fe,[O,F]),v1,fe=>ie(fe))}function Nn(O){let F=null;const fe=Ba(N,l.value,i.value);for(let ye=0;ye{o&&(i.value=O,N.locale=O,Ht(N,i.value,l.value))}),pe(e.fallbackLocale,O=>{o&&(l.value=O,N.fallbackLocale=O,Ht(N,i.value,l.value))}));const ne={id:$s,locale:le,fallbackLocale:ge,get inheritLocale(){return o},set inheritLocale(O){o=O,O&&e&&(i.value=e.locale.value,l.value=e.fallbackLocale.value,Ht(N,i.value,l.value))},get availableLocales(){return Object.keys(c.value).sort()},messages:ae,get modifiers(){return P},get pluralRules(){return T||{}},get isGlobal(){return r},get missingWarn(){return f},set missingWarn(O){f=O,N.missingWarn=f},get fallbackWarn(){return y},set fallbackWarn(O){y=O,N.fallbackWarn=y},get fallbackRoot(){return S},set fallbackRoot(O){S=O},get fallbackFormat(){return g},set fallbackFormat(O){g=O,N.fallbackFormat=g},get warnHtmlMessage(){return I},set warnHtmlMessage(O){I=O,N.warnHtmlMessage=O},get escapeParameter(){return L},set escapeParameter(O){L=O,N.escapeParameter=O},t:rt,getLocaleMessage:gt,setLocaleMessage:bt,mergeLocaleMessage:Rt,getPostTranslationHandler:Te,setPostTranslationHandler:tt,getMissingHandler:De,setMissingHandler:nt,[Ja]:Fe};return ne.datetimeFormats=_e,ne.numberFormats=Ne,ne.rt=J,ne.te=Mn,ne.tm=Ft,ne.d=te,ne.n=V,ne.getDateTimeFormat=$n,ne.setDateTimeFormat=h,ne.mergeDateTimeFormat=m,ne.getNumberFormat=$,ne.setNumberFormat=z,ne.mergeNumberFormat=be,ne[Qa]=n,ne[lr]=Le,ne[cr]=vt,ne[ur]=Se,ne}function b1(t){const e=H(t.locale)?t.locale:Kt,n=H(t.fallbackLocale)||ve(t.fallbackLocale)||ee(t.fallbackLocale)||t.fallbackLocale===!1?t.fallbackLocale:e,r=me(t.missing)?t.missing:void 0,s=ie(t.silentTranslationWarn)||At(t.silentTranslationWarn)?!t.silentTranslationWarn:!0,a=ie(t.silentFallbackWarn)||At(t.silentFallbackWarn)?!t.silentFallbackWarn:!0,o=ie(t.fallbackRoot)?t.fallbackRoot:!0,i=!!t.formatFallbackMessages,l=ee(t.modifiers)?t.modifiers:{},c=t.pluralizationRules,u=me(t.postTranslation)?t.postTranslation:void 0,d=H(t.warnHtmlInMessage)?t.warnHtmlInMessage!=="off":!0,f=!!t.escapeParameterHtml,y=ie(t.sync)?t.sync:!0;let S=t.messages;if(ee(t.sharedMessages)){const P=t.sharedMessages;S=Object.keys(P).reduce((N,B)=>{const G=N[B]||(N[B]={});return ke(G,P[B]),N},S||{})}const{__i18n:g,__root:b,__injectWithOption:p}=t,E=t.datetimeFormats,I=t.numberFormats,L=t.flatJson;return{locale:e,fallbackLocale:n,messages:S,flatJson:L,datetimeFormats:E,numberFormats:I,missing:r,missingWarn:s,fallbackWarn:a,fallbackRoot:o,fallbackFormat:i,modifiers:l,pluralRules:c,postTranslation:u,warnHtmlMessage:d,escapeParameter:f,messageResolver:t.messageResolver,inheritLocale:y,__i18n:g,__root:b,__injectWithOption:p}}function fr(t={}){const e=Ir(b1(t)),{__extender:n}=t,r={id:e.id,get locale(){return e.locale.value},set locale(s){e.locale.value=s},get fallbackLocale(){return e.fallbackLocale.value},set fallbackLocale(s){e.fallbackLocale.value=s},get messages(){return e.messages.value},get datetimeFormats(){return e.datetimeFormats.value},get numberFormats(){return e.numberFormats.value},get availableLocales(){return e.availableLocales},get missing(){return e.getMissingHandler()},set missing(s){e.setMissingHandler(s)},get silentTranslationWarn(){return ie(e.missingWarn)?!e.missingWarn:e.missingWarn},set silentTranslationWarn(s){e.missingWarn=ie(s)?!s:s},get silentFallbackWarn(){return ie(e.fallbackWarn)?!e.fallbackWarn:e.fallbackWarn},set silentFallbackWarn(s){e.fallbackWarn=ie(s)?!s:s},get modifiers(){return e.modifiers},get formatFallbackMessages(){return e.fallbackFormat},set formatFallbackMessages(s){e.fallbackFormat=s},get postTranslation(){return e.getPostTranslationHandler()},set postTranslation(s){e.setPostTranslationHandler(s)},get sync(){return e.inheritLocale},set sync(s){e.inheritLocale=s},get warnHtmlInMessage(){return e.warnHtmlMessage?"warn":"off"},set warnHtmlInMessage(s){e.warnHtmlMessage=s!=="off"},get escapeParameterHtml(){return e.escapeParameter},set escapeParameterHtml(s){e.escapeParameter=s},get pluralizationRules(){return e.pluralRules||{}},__composer:e,t(...s){return Reflect.apply(e.t,e,[...s])},rt(...s){return Reflect.apply(e.rt,e,[...s])},tc(...s){const[a,o,i]=s,l={plural:1};let c=null,u=null;if(!H(a))throw Me(Ie.INVALID_ARGUMENT);const d=a;return H(o)?l.locale=o:we(o)?l.plural=o:ve(o)?c=o:ee(o)&&(u=o),H(i)?l.locale=i:ve(i)?c=i:ee(i)&&(u=i),Reflect.apply(e.t,e,[d,c||u||{},l])},te(s,a){return e.te(s,a)},tm(s){return e.tm(s)},getLocaleMessage(s){return e.getLocaleMessage(s)},setLocaleMessage(s,a){e.setLocaleMessage(s,a)},mergeLocaleMessage(s,a){e.mergeLocaleMessage(s,a)},d(...s){return Reflect.apply(e.d,e,[...s])},getDateTimeFormat(s){return e.getDateTimeFormat(s)},setDateTimeFormat(s,a){e.setDateTimeFormat(s,a)},mergeDateTimeFormat(s,a){e.mergeDateTimeFormat(s,a)},n(...s){return Reflect.apply(e.n,e,[...s])},getNumberFormat(s){return e.getNumberFormat(s)},setNumberFormat(s,a){e.setNumberFormat(s,a)},mergeNumberFormat(s,a){e.mergeNumberFormat(s,a)}};return r.__extender=n,r}function y1(t,e,n){return{beforeCreate(){const r=Wt();if(!r)throw Me(Ie.UNEXPECTED_ERROR);const s=this.$options;if(s.i18n){const a=s.i18n;if(s.__i18n&&(a.__i18n=s.__i18n),a.__root=e,this===this.$root)this.$i18n=Ts(t,a);else{a.__injectWithOption=!0,a.__extender=n.__vueI18nExtend,this.$i18n=fr(a);const o=this.$i18n;o.__extender&&(o.__disposer=o.__extender(this.$i18n))}}else if(s.__i18n)if(this===this.$root)this.$i18n=Ts(t,s);else{this.$i18n=fr({__i18n:s.__i18n,__injectWithOption:!0,__extender:n.__vueI18nExtend,__root:e});const a=this.$i18n;a.__extender&&(a.__disposer=a.__extender(this.$i18n))}else this.$i18n=t;s.__i18nGlobal&&eo(e,s,s),this.$t=(...a)=>this.$i18n.t(...a),this.$rt=(...a)=>this.$i18n.rt(...a),this.$tc=(...a)=>this.$i18n.tc(...a),this.$te=(a,o)=>this.$i18n.te(a,o),this.$d=(...a)=>this.$i18n.d(...a),this.$n=(...a)=>this.$i18n.n(...a),this.$tm=a=>this.$i18n.tm(a),n.__setInstance(r,this.$i18n)},mounted(){},unmounted(){const r=Wt();if(!r)throw Me(Ie.UNEXPECTED_ERROR);const s=this.$i18n;delete this.$t,delete this.$rt,delete this.$tc,delete this.$te,delete this.$d,delete this.$n,delete this.$tm,s.__disposer&&(s.__disposer(),delete s.__disposer,delete s.__extender),n.__deleteInstance(r),delete this.$i18n}}}function Ts(t,e){t.locale=e.locale||t.locale,t.fallbackLocale=e.fallbackLocale||t.fallbackLocale,t.missing=e.missing||t.missing,t.silentTranslationWarn=e.silentTranslationWarn||t.silentFallbackWarn,t.silentFallbackWarn=e.silentFallbackWarn||t.silentFallbackWarn,t.formatFallbackMessages=e.formatFallbackMessages||t.formatFallbackMessages,t.postTranslation=e.postTranslation||t.postTranslation,t.warnHtmlInMessage=e.warnHtmlInMessage||t.warnHtmlInMessage,t.escapeParameterHtml=e.escapeParameterHtml||t.escapeParameterHtml,t.sync=e.sync||t.sync,t.__composer[Ja](e.pluralizationRules||t.pluralizationRules);const n=Ar(t.locale,{messages:e.messages,__i18n:e.__i18n});return Object.keys(n).forEach(r=>t.mergeLocaleMessage(r,n[r])),e.datetimeFormats&&Object.keys(e.datetimeFormats).forEach(r=>t.mergeDateTimeFormat(r,e.datetimeFormats[r])),e.numberFormats&&Object.keys(e.numberFormats).forEach(r=>t.mergeNumberFormat(r,e.numberFormats[r])),t}const Mr={tag:{type:[String,Object]},locale:{type:String},scope:{type:String,validator:t=>t==="parent"||t==="global",default:"parent"},i18n:{type:Object}};function w1({slots:t},e){return e.length===1&&e[0]==="default"?(t.default?t.default():[]).reduce((r,s)=>[...r,...s.type===he?s.children:[s]],[]):e.reduce((n,r)=>{const s=t[r];return s&&(n[r]=s()),n},{})}function to(){return he}const k1=R({name:"i18n-t",props:ke({keypath:{type:String,required:!0},plural:{type:[Number,String],validator:t=>we(t)||!isNaN(t)}},Mr),setup(t,e){const{slots:n,attrs:r}=e,s=t.i18n||In({useScope:t.scope,__useComponent:!0});return()=>{const a=Object.keys(n).filter(d=>d!=="_"),o={};t.locale&&(o.locale=t.locale),t.plural!==void 0&&(o.plural=H(t.plural)?+t.plural:t.plural);const i=w1(e,a),l=s[lr](t.keypath,i,o),c=ke({},r),u=H(t.tag)||ce(t.tag)?t.tag:to();return Ct(u,c,l)}}}),Fs=k1;function L1(t){return ve(t)&&!H(t[0])}function no(t,e,n,r){const{slots:s,attrs:a}=e;return()=>{const o={part:!0};let i={};t.locale&&(o.locale=t.locale),H(t.format)?o.key=t.format:ce(t.format)&&(H(t.format.key)&&(o.key=t.format.key),i=Object.keys(t.format).reduce((f,y)=>n.includes(y)?ke({},f,{[y]:t.format[y]}):f,{}));const l=r(t.value,o,i);let c=[o.key];ve(l)?c=l.map((f,y)=>{const S=s[f.type],g=S?S({[f.type]:f.value,index:y,parts:l}):[f.value];return L1(g)&&(g[0].key=`${f.type}-${y}`),g}):H(l)&&(c=[l]);const u=ke({},a),d=H(t.tag)||ce(t.tag)?t.tag:to();return Ct(d,u,c)}}const S1=R({name:"i18n-n",props:ke({value:{type:Number,required:!0},format:{type:[String,Object]}},Mr),setup(t,e){const n=t.i18n||In({useScope:t.scope,__useComponent:!0});return no(t,e,za,(...r)=>n[ur](...r))}}),Rs=S1,E1=R({name:"i18n-d",props:ke({value:{type:[Number,Date],required:!0},format:{type:[String,Object]}},Mr),setup(t,e){const n=t.i18n||In({useScope:t.scope,__useComponent:!0});return no(t,e,Ya,(...r)=>n[cr](...r))}}),Vs=E1;function O1(t,e){const n=t;if(t.mode==="composition")return n.__getInstance(e)||t.global;{const r=n.__getInstance(e);return r!=null?r.__composer:t.global.__composer}}function C1(t){const e=o=>{const{instance:i,value:l}=o;if(!i||!i.$)throw Me(Ie.UNEXPECTED_ERROR);const c=O1(t,i.$),u=Ds(l);return[Reflect.apply(c.t,c,[...Hs(u)]),c]};return{created:(o,i)=>{const[l,c]=e(i);mn&&t.global===c&&(o.__i18nWatcher=pe(c.locale,()=>{i.instance&&i.instance.$forceUpdate()})),o.__composer=c,o.textContent=l},unmounted:o=>{mn&&o.__i18nWatcher&&(o.__i18nWatcher(),o.__i18nWatcher=void 0,delete o.__i18nWatcher),o.__composer&&(o.__composer=void 0,delete o.__composer)},beforeUpdate:(o,{value:i})=>{if(o.__composer){const l=o.__composer,c=Ds(i);o.textContent=Reflect.apply(l.t,l,[...Hs(c)])}},getSSRProps:o=>{const[i]=e(o);return{textContent:i}}}}function Ds(t){if(H(t))return{path:t};if(ee(t)){if(!("path"in t))throw Me(Ie.REQUIRED_VALUE,"path");return t}else throw Me(Ie.INVALID_VALUE)}function Hs(t){const{path:e,locale:n,args:r,choice:s,plural:a}=t,o={},i=r||{};return H(n)&&(o.locale=n),we(s)&&(o.plural=s),we(a)&&(o.plural=a),[e,i,o]}function A1(t,e,...n){const r=ee(n[0])?n[0]:{};(ie(r.globalInstall)?r.globalInstall:!0)&&([Fs.name,"I18nT"].forEach(a=>t.component(a,Fs)),[Rs.name,"I18nN"].forEach(a=>t.component(a,Rs)),[Vs.name,"I18nD"].forEach(a=>t.component(a,Vs))),t.directive("t",C1(e))}const I1=ut("global-vue-i18n");function M1(t={},e){const n=__VUE_I18N_LEGACY_API__&&ie(t.legacy)?t.legacy:__VUE_I18N_LEGACY_API__,r=ie(t.globalInjection)?t.globalInjection:!0,s=new Map,[a,o]=N1(t,n),i=ut("");function l(f){return s.get(f)||null}function c(f,y){s.set(f,y)}function u(f){s.delete(f)}const d={get mode(){return __VUE_I18N_LEGACY_API__&&n?"legacy":"composition"},async install(f,...y){if(f.__VUE_I18N_SYMBOL__=i,f.provide(f.__VUE_I18N_SYMBOL__,d),ee(y[0])){const b=y[0];d.__composerExtend=b.__composerExtend,d.__vueI18nExtend=b.__vueI18nExtend}let S=null;!n&&r&&(S=H1(f,d.global)),__VUE_I18N_FULL_INSTALL__&&A1(f,d,...y),__VUE_I18N_LEGACY_API__&&n&&f.mixin(y1(o,o.__composer,d));const g=f.unmount;f.unmount=()=>{S&&S(),d.dispose(),g()}},get global(){return o},dispose(){a.stop()},__instances:s,__getInstance:l,__setInstance:c,__deleteInstance:u};return d}function In(t={}){const e=Wt();if(e==null)throw Me(Ie.MUST_BE_CALL_SETUP_TOP);if(!e.isCE&&e.appContext.app!=null&&!e.appContext.app.__VUE_I18N_SYMBOL__)throw Me(Ie.NOT_INSTALLED);const n=$1(e),r=T1(n),s=Za(e),a=P1(t,s);if(a==="global")return eo(r,t,s),r;if(a==="parent"){let l=F1(n,e,t.__useComponent);return l==null&&(l=r),l}const o=n;let i=o.__getInstance(e);if(i==null){const l=ke({},t);"__i18n"in s&&(l.__i18n=s.__i18n),r&&(l.__root=r),i=Ir(l),o.__composerExtend&&(i[dr]=o.__composerExtend(i)),V1(o,e,i),o.__setInstance(e,i)}return i}function N1(t,e,n){const r=Lo(),s=__VUE_I18N_LEGACY_API__&&e?r.run(()=>fr(t)):r.run(()=>Ir(t));if(s==null)throw Me(Ie.UNEXPECTED_ERROR);return[r,s]}function $1(t){const e=Nt(t.isCE?I1:t.appContext.app.__VUE_I18N_SYMBOL__);if(!e)throw Me(t.isCE?Ie.NOT_INSTALLED_WITH_PROVIDE:Ie.UNEXPECTED_ERROR);return e}function P1(t,e){return On(t)?"__i18n"in e?"local":"global":t.useScope?t.useScope:"local"}function T1(t){return t.mode==="composition"?t.global:t.global.__composer}function F1(t,e,n=!1){let r=null;const s=e.root;let a=R1(e,n);for(;a!=null;){const o=t;if(t.mode==="composition")r=o.__getInstance(a);else if(__VUE_I18N_LEGACY_API__){const i=o.__getInstance(a);i!=null&&(r=i.__composer,n&&r&&!r[Qa]&&(r=null))}if(r!=null||s===a)break;a=a.parent}return r}function R1(t,e=!1){return t==null?null:e&&t.vnode.ctx||t.parent}function V1(t,e,n){Ye(()=>{},e),gn(()=>{const r=n;t.__deleteInstance(e);const s=r[dr];s&&(s(),delete r[dr])},e)}const D1=["locale","fallbackLocale","availableLocales"],Us=["t","rt","d","n","tm","te"];function H1(t,e){const n=Object.create(null);return D1.forEach(s=>{const a=Object.getOwnPropertyDescriptor(e,s);if(!a)throw Me(Ie.UNEXPECTED_ERROR);const o=So(a.value)?{get(){return a.value.value},set(i){a.value.value=i}}:{get(){return a.get&&a.get()}};Object.defineProperty(n,s,o)}),t.config.globalProperties.$i18n=n,Us.forEach(s=>{const a=Object.getOwnPropertyDescriptor(e,s);if(!a||!a.value)throw Me(Ie.UNEXPECTED_ERROR);Object.defineProperty(t.config.globalProperties,`$${s}`,a)}),()=>{delete t.config.globalProperties.$i18n,Us.forEach(s=>{delete t.config.globalProperties[`$${s}`]})}}_1();zp(Ip);Xp(Kp);qp(Ba);if(__INTLIFY_PROD_DEVTOOLS__){const t=mt();t.__INTLIFY__=!0,Mp(t.__INTLIFY_DEVTOOLS_GLOBAL_HOOK__)}const ro=()=>{const t=Nt("$env"),{t:e,locale:n}=In();return{locale:n,$env:t,t:e}},U1={class:"text-slate-600 text-base mt-2"},B1={class:"flex flex-row justify-start items-start mt-4"},W1={class:"relative h-14"},j1=["label","status"],x1={key:0,class:"absolute bottom-0 left-0 text-sm text-[#ff4d4f]"},K1={class:"text-[#3451b2] text-base"},G1=R({__name:"TOTP",setup(t){const{t:e,$env:n,locale:r}=ro(),s=X(""),a=X(Lt.NORMAL),o=X(""),i=X({code:"",expires:""}),l=u=>{s.value=u.detail.value,a.value=Lt.NORMAL},c=()=>{if(s.value.length<=0)o.value=e("components_totp_3"),a.value=Lt.ERROR;else try{const{otp:u,expires:d}=Tm.generate(s.value);i.value.code=u,i.value.expires=Vm(d).format()}catch{o.value=e("components_totp_5"),a.value=Lt.ERROR}};return(u,d)=>(_(),A("div",null,[w("div",U1,Z(v(e)("components_totp_6")),1),w("div",B1,[w("div",W1,[w("r-input",{label:v(e)("components_totp_2"),class:"w-64 h-8 rounded-lg block text-lg",status:a.value,onInput:l},null,40,j1),a.value===v(Lt).ERROR?(_(),A("div",x1,Z(o.value),1)):j("",!0)]),w("r-button",{class:"ml-1 h-8",onClick:c},Z(v(e)("components_totp_1")),1)]),w("div",K1,[w("div",null,"code: "+Z(i.value.code),1),w("div",null,Z(v(e)("components_totp_4"))+": "+Z(i.value.expires),1)])]))}}),so=nr.locale,Ot=M1({legacy:!1,locale:so,fallbackLocale:Qt.EN,messages:jm,devtools:!1}),Un=t=>(Ot.mode===Da.LEGACY?Ot.global.locale=t:Ot.global.locale.value=t,t),Y1=(t,e=so)=>{Ot.global.mergeLocaleMessage(e,t)},ao=t=>t?Ot.global.locale===t||is.includes(t)?Promise.resolve(Un(t)):Oo(Object.assign({"./en.json":()=>cn(()=>import("./en.Bkn4-Vvy.js"),[]),"./zh-CN.json":()=>cn(()=>import("./zh-CN.PUkQxDBJ.js"),[])}),`./${t}.json`,2).then(e=>(Y1(e.default,t),is.push(t),Un(t))):Promise.reject("lang is undefined"),z1=R({__name:"Layout",setup(t){const{$env:e,locale:n}=ro(),{lang:r}=hr(),s=()=>{const a=r.value||Qt.EN;n.value=a,e.locale=a,ao(a).catch(o=>{console.log("error",o)}),Fm(Va,a)};return it(()=>{s()}),Ye(()=>{Um()}),(a,o)=>(_(),K(v(wa).Layout))}}),X1=()=>{cn(()=>import("./pwa-install.es.Bwp47-dV.js"),[]).then(()=>{let t=document.getElementById(ls);t||(t=document.createElement(xm),t.setAttribute("manifest-url",Km),t.setAttribute("id",ls),document.body.appendChild(t))})},r_={extends:wa,enhanceApp({app:t,router:e,siteData:n}){cn(()=>import("./index.CBA5mFK_.js").then(s=>s.i),__vite__mapDeps([0,1])),X1(),t.use(Ym);const r=Rm(Va)||Qt.EN;ao(r).then(()=>{Hm("__VUE_PROD_DEVTOOLS__",!1),t.use(Ot),t.component("Layout",z1),t.component("TOTP",G1)}).catch(s=>{console.log("error",s)})}};export{r_ as R}; diff --git a/assets/chunks/unlock-CeU74z9n.58atcEuH.js b/assets/chunks/unlock-CeU74z9n.58atcEuH.js new file mode 100644 index 0000000000..c8831a9a92 --- /dev/null +++ b/assets/chunks/unlock-CeU74z9n.58atcEuH.js @@ -0,0 +1,4 @@ +const c={success:!0,_identification:!0,data:` + + +`};export{c as default}; diff --git a/assets/chunks/user-B-eVXwuk.DyoYYAjs.js b/assets/chunks/user-B-eVXwuk.DyoYYAjs.js new file mode 100644 index 0000000000..d1cf1364e1 --- /dev/null +++ b/assets/chunks/user-B-eVXwuk.DyoYYAjs.js @@ -0,0 +1 @@ +const c={success:!0,_identification:!0,data:''};export{c as default}; diff --git a/assets/chunks/warning-circle-DDUgEDIv.1BX6MOiy.js b/assets/chunks/warning-circle-DDUgEDIv.1BX6MOiy.js new file mode 100644 index 0000000000..e4c17cfd07 --- /dev/null +++ b/assets/chunks/warning-circle-DDUgEDIv.1BX6MOiy.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/warning-circle-fill-lODUKz0i.7RyGfSeR.js b/assets/chunks/warning-circle-fill-lODUKz0i.7RyGfSeR.js new file mode 100644 index 0000000000..90799b292e --- /dev/null +++ b/assets/chunks/warning-circle-fill-lODUKz0i.7RyGfSeR.js @@ -0,0 +1 @@ +const t={success:!0,_identification:!0,data:''};export{t as default}; diff --git a/assets/chunks/zh-CN.PUkQxDBJ.js b/assets/chunks/zh-CN.PUkQxDBJ.js new file mode 100644 index 0000000000..7c6446600a --- /dev/null +++ b/assets/chunks/zh-CN.PUkQxDBJ.js @@ -0,0 +1 @@ +const t="简体中文",o="生成结果",n="请输入 2FA 的 key",p="你还没有输入 2FA 的 key",_="有效期",s="输入的 key 值无效",c="2FA 验证",e={lang:t,components_totp_1:o,components_totp_2:n,components_totp_3:p,components_totp_4:_,components_totp_5:s,components_totp_6:c};export{o as components_totp_1,n as components_totp_2,p as components_totp_3,_ as components_totp_4,s as components_totp_5,c as components_totp_6,e as default,t as lang}; diff --git "a/assets/chunks/\350\256\277\351\227\256\350\200\205._0swtoJg.js" "b/assets/chunks/\350\256\277\351\227\256\350\200\205._0swtoJg.js" new file mode 100644 index 0000000000..21364f1323 --- /dev/null +++ "b/assets/chunks/\350\256\277\351\227\256\350\200\205._0swtoJg.js" @@ -0,0 +1 @@ +const A="/ran/assets/%E7%BB%A7%E6%89%BF.Dta6_xdc.png",E="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAmQAAAFCCAMAAABo0jE4AAAAtFBMVEX///8yMjKYmJjS0tL6+vqrq6uFhYXv7+/9/f319fXNzc1CQkLX19dVVVVlZWVJSUk1NTVwcHA4ODhYWFjz8/Pn5+evr6+KiopNTU08PDzj4+PIyMjy8vJAQEDc3NyNjY1QUFDDw8O8vLxra2vs7OyTk5OGhoZ0dHRFRUVdXV2ysrKlpaWgoKDZ2dm2trZ/f3+bm5vPz8+EhITe3t78/Px6enphYWHp6enU1NT39/fKysqQkJDndjM/AAAKY0lEQVR42uza2W7aYBQE4JlghDFgg9l3AqRszdKkSdP2/d+rQAJqSyOo2uDlzCdFP0i+OaORrZgDERERERERERERERERERERERERERERERERERERERERERERERERkffkNvwCU63gN1xIhNwKDaioZVFqsOTVkGo1r8QGJDo+PaSeRx8SnQJTfh/bqLEAiQ4JA2xMGVs24rcxZWzZiN/GlLFlI34bU8aWjfhtTBlbNuK3MWVsnSF+n1dAr8wVsOQEXAO4cfH65VDyppRI47+jD4zJGfCBH9HkpnRk8+qq+/rlUPKmlEjjz7Dt4p7tArBgETkSAJkDsP3yR4mbUiKN321zgFbL54MT9l2VzJ5zxF9ho8P7C2afOXvp1e5xqZKZcI74V7zPcuzxccXsvmQbFyqZCeeIf8DqjDknDG75AD0u7TlL/PNwXgV8BgFUMoPOEv8jOQTuyFtg/wojB0CvMEw4S/wN8hLIkEsAXNuVTC9jTbARv40pY8tG/DamjC0b8duYMrZsxG9jytiyEb+NKWPLRvw2powtG/HbmDK2bMRvY8rYshG/jSlji0ZATqaSqWTJYyN+G1PGlo34bUwZW/83/soEQL58B2BVcEkiw7USNh+B8aLeusYpYj2lRBV/Z+QA2bYDjMtPAGaPyNBZ/+UBbD8i1y9iWXJxXGynlMji39eoTg+498t5uP3lQcmuJoAb3OAEcZ1S/j3+XSc23I+tclCEcxWUgzsXGXarYam4P+E0++3H2v46rgGlCyC4bF+iyOlByVpLAMMKTqOSpcbbJRu2PjmDOm5L104muECGs2lvUt2fuH2q5/zb/XXbGmH4hIfwa2WIVQm/l2zKAYCbAk6jkqXGL/GH3Fhgo1f+hrUcPwFYzpFhB7ikuztzvF6f7d11ryXrlvOrCbIlVIa7kq01tx+L7AHw6OAUKll6vHkn21Rif3zalCu/rc3uLHJjc/Z+KpnTvpx8RIdf2t2f72QqmWlvlqzOZ6xNmQGwDPB7yeqs7677qWSofAgHQKsZOgcl+8IHAOM+TqSSpcWbJUOlev252MFsfWSC1UHJ4M/qn6+7++se2O0ByPbnAD60JzgoGYIbAN8nOI1Klhpvx5//UAirA3xtzsujLA5LNp21w2p3fx3uwzmADm8BjLkCQHJXMpIv/1i6rSVOoZKlyDnjn/YHuBk5OEGCp5Ro4x8vvoyKOEWSpxSb8duYMrZsxG9jytiyEb+NKWPLRvw2powt8shqRX3kJn/BTCWL0vGSpWLBTCX7K8kpWZwWzFSySBz/Wak3C4O7lzf8q3nYTPSCmUoWieMlq/jT6dO2ZB1288+JXjBTyaJwfJ9symeguy1ZncuEL5ipZNE4vk9W2/8gfjMveYleMFPJonC8ZB0OgPFrh5zhPNELZipZFI6XDKVKr7N4eVx+crJtN8kLZipZpAqs4c8Gi/Kise1QZ1QeXSZ5wazGAiQ6Pj38lSQumHn0IdFpsOTV8DcSt2BW80psQKLjVmhAxYVEyG34BaZawW+oY2ngeXhPzSbEvPdtgRsEuheZ984tyJAZiHHv3ILv5HeIcT/Yu6OVtoIoDKN7H2IoaqEgghos9aIFQVAovv+rlZQScA60I3XijLPWjZzbjx/nECak7Qo+XWVeOS8n13gF53l2lufB1Bqv4Hv+2OYSTK3xCr7lbpefg6m1XcHXvN1sbvNnMLHGK3jKx4jHfAom1ngFF3kXcZcXwcTaruAmrzcRm+u8CabVeAUP+bz/85wPwbQar+A+/7gPptV2BZd5cBlM6q8r8EUQRlmBkWFkrI22AiPDyFizAsZjZDR3chIAOI15DSOjge02XjAyRluBkWFkrI22AiPDyFgbbQVGhpGxNtoKjAwrYM3IGI9bGABOY17JyNhzC4PR+JyM0mgrMDKMjLXRVmBkGBlro63AyDAy1qyA8RgZa25hAPyD03gW24MjPL1kZLPIgyM8NZW57J1GxOmy95ZP/I+TgyM8NfUlf1siYsnMN3zyY60d3/A6rt3S7j+Zw9hrzJpU3VBOqpJy1aTqhnJSlZSrJlU3lJOqpFw1qbqhnFQl5apJ1Q03vAAA3t+HuoVR8uLfB+WkKilXTapuKCdVSblqUnVDOalKylWTqhvKSVVSrppU3VBOqjW3MAAAPhy3MLz4l5SrJlU3lJOqpFw1qbqhnFQl5apJ1Q3lpCopV02qbignVUm5alJ1wy0MAID35xaGF/+SctWk6oZyUpWUqyZVN5STqqRcNal+sXM2O21DURi8B6XCjbGTQOok0JAUSgiFIqCI/rz/gzUXsXBP5eoSyeXDzEgs7MVB32gQsIkMmEOVB3PJoEoGzKHKg7lkUNVAVpW5dZq8rDJUtaAqmWxkb4BRhqoWVKVSWdEfh04z7hdWoaoFVamU1g+dp28lqlpQlUpuHf/hjIwtR9WzVfH/y3NXqhyRx+x13NSDyIjMo7kSVUo39SAyIvNorkSV0k09iKyzkR1Me8HMhoPFz/iNdkM6iivbj8xLq9NoUFHVfzR3/S7en9zN7Y7ItpBGZIlEM0c2J7ItpBFZoqv4dWj78eGk2D/YCyG7XA4HO/dPb4rNm3BysL9e9EIdwZUNR9qU9vk8H15EZ2f57IzI/uHr48pG8WGwKuwihEtbT5a2iG+mq2V8c23LxYNNQg3FlQ1H2pR2W0xOrQjhyvLJksgafUWWH+LDbfhqwxCmdhSObZY9vtmLbwpbna0sDzUUVzYcaVNar3d8bfY+TO1TOCSyZl+TnZPe08Nu/G5D+x7uzcb1N4+EOoIrG460Ke16Nivji+gsI7JmX9FMPbKB/QrHNs/qb/aCR3Blw5E2pc3t2258yDfOfhBZemRXNpgs7ab25sbWq8XpSagjuPJFIhs9xIc7W0+mRJYeWXY1HQ6usj/eLIezh+NQR3DlC0T2ZZ5X8WF8vr+uiEybVxTZM9FUhTlUEdkGzZWoUrqpB5ERmUdzJaqUbupBZETm0VyJKqWbehAZkXk0V6JqW+yNgKpEiIzI/kZRFb8DUMXfZBs0V6JK6aYeREZkHs2VqFK6qQeREZlHcyWqlG7qQWRE5tFciSqlm3oQGZF5NFeiSummHkRGZB7NlahSuqkHkRGZR3MlqpRu6kFkRObRXIkqpZt6EBmReTRXokrpph5ERmQezZWoUrqpB5ERmUdzJaqUbupBZETm0VyJKqWbehAZkXk0V6JK6aYeREZkHs2VqOJTRPjAFR1VmEMVn+qzQXMlqpRu6kFkRObRXIkqpZt6EBmReTRXokrpph5ERmQezZWoUrqpB5ERmUdzJaqUbupBZETm0VyJKqWbehAZkXk0V6JK6aYeREZkHs2VqFK6qQeREZlHcyWqlG7qQWRE5tFciSqlm3oQGZF5NFeiSummHkRGZB7NlahSuqkHkRGZR3MlqrYlt3HoPGPLUdWCqlRK64fO07cSVS2oSqWyot/xH9Bxv7AKVS2oSiUb2RtglKGqBVXJZFWZW6fJyypDVboqAAAAAPjdHhwSAAAAAAj6/9oVNgAAAAAAAAAAAAAAAAAAeAWUZqBodi/NSgAAAABJRU5ErkJggg==",R="/ran/assets/%E7%BB%84%E5%90%88.StqZ1pDc.png",a="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfIAAAEiCAMAAAA1caDNAAAAjVBMVEX///8yMjKYmJj8/Pz09PRkZGSvr69CQkL6+vrS0tJDQ0NBQUFWVlbOzs7Nzc1vb287Ozs+Pj7Hx8c0NDTv7++JiYl/f3/AwMCmpqY2Njb+/v5mZmb39/eOjo5NTU3f39/W1tafn590dHRxcXFbW1v29vbo6Ojk5ORGRkarq6vn5+fZ2dm3t7ezs7N4eHiKJ4owAAAGMElEQVR42uzdy07bUBSF4bXrKyY3nMQkzYUQQkBF5f0fr0mZdeRItWSz/k86kz3x4JftozM5AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP6XJM+K6FCR5YnQI8k0OjeleZ/kMRqn6lA6HkUu9EcWY3VsEpnQH0Wk6lgahdAfEfrXIJ+BXuUgea+Q3A7J7ZDcDsntkNwOye2Q3A7J7ZDcDsntkNwOye2Q3A7J7ZDcDsntkNwOye2Q3A7J7ZDcDsntkNwOye20yBFfSP5NtMpxFyVv+bdBcjs3JC+X97PPVKpP6319mf1+f69X99UjyYflhuRNdl5sGunxUO72l9kubapl2uxJPiztky/iQ6ofJG0PP6K8izfVlzWJhOSD0j75If4qtatePq/J0+v8ukg+KO2Tn+OXrt7iSTXJh6t9cmXHc/JR6ynqxZTkw3VD8sVxtj7V0nK2X5F8uDhwtUNyOyS3Q3I7JLdDcjskt0NyOyS3Q3I7JLdDcjskt0NyOyS3Q3I7JLdDcjskt0NyOyS3Q3I7JLdDcjskt0NyO1xmbYcr6+3kMZqk6lA6GUUu9Ecyjc5Nfwo9kuRZER0qsjwRBu3En9nMa8Sr4GQTsRGMlHFRCj5eoqriKNhIIlarmLMH99FEtd1W0Qgu5vEsPcdcMLGM+1RKH2IneFjH8qv8WvBAcjt82P38Yd/ebiAEoQCICtuB9t/rduCfyQ1zTgWYCUZ5+HzL8ZOW83ssxdRYcM2xrdJj8zTHEYkeFxFyJM+RPEfyHMlzJM+RPEfyHMlzJM+RPEfyHMlzJM+RPEfyHMlzJM+RPEfyj917mrX2JPd1mmfx5sB3zrA5tafN8iOTX8PMGtGs0Rz6SH/u50AGAAAAYJC/9TXaDcoSWZppyRJZmmnJElmaackSWZppyRJZmmnJElmaackSWZppyRJZmmnJElmaackSWZppyRJZmmnJElmaackSWZppyRJZmmnJElmaackSWZppyRJZmmnJElmaackSWZppyRJZmmnJElmaackSWZppyRJZmmnJElmaackSWZppyRJZmmnJElmaackSWZppyRJZmmnJElmaackSxZ657DQOBFG0S207JNgQE8+YxwzhJSAI/v/3ME1gxQrFqlOluhINC6R7ro4MjWHROJ3EImLROJ3EImLROJ3EImLROJ3EImLROJ3EImLROJ3EImLROJ3EImLR/JTc1AuZMYu6yZaJWDSHSD6V2XOa7RKxaA6SRtquSjOm6lpp7BKxaA6SWro0c06ktkvEojlIFlKlmVPJwi4Ri8bM/VLELhGLxkxdKNfvQE9iEbFozNSFcv0O9CQWEYvGTF0o1+9AT2IRsWjM1IVy/Q70JBYRi8ZMXSjX70BPYhGxaMzUhXL9DvQkFhGLxkxdKNfvQE9iEbFozNSFcv0O9CQWEYvGTF0o1+9AT2IRsWjM1IVy/Q70JBYRi8ZMXSjX70BPYhGxaMzUhXL9DvQkFhGLxkxdKNfv+G2dHE/5PCDK5St/AcrXJVLO0Yvy74OiPJdUd9c3AOWf2WRXTzlOeclLezVwfrDLpSvlqynlIClfrv5kxO/yLP0U+fjIbpQTn/JxvYNc37JMx0k7HaF8TuW7/oxyYy/K71evrpTjbuzpdnWTSsaBoDz/b4d650k57ilvnrf7r9oRoHz5cDWk6uHVj/Lu23bHUJ6Pz9I+/RagfPv2cV0fHv0oLxHQ27dqM6aSf+d9Bigvn46OhlAus333+fPFuu/XF5vrEXJ9S2kpcu/m7/KSmqR8//7tEnFjT09fSH5excS/Vfax5wA9iUXEojFTF8r1O9CTWEQsGjN1oVy/Az2JRcSiMVMXyvU70JNYRCwaM3WhXL8DPYlFxKIxUxfK39u7YxsIYSCIorI4TIIgv/4LvRYusLWz0nsNzF+ZnPqN6JOyirJq2sx58vqN6JOyirJq2sx58vqN6JOyirJq2sx58vqN6JOyirJq2sx58vqN6JOyirJq2sx58vqN6JOyirJq2sx58vqN6JOyirJq/Mzaz6z9st4v6/8wx/1s/Y4/zz1m36KsmiWOd2z3fvsWZdWscczzGhtd5zw6F2XVAAAAAAAAAAAAAAAAACzxA5TVMRW7CUShAAAAAElFTkSuQmCC",l="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAY0AAACLCAMAAACqVzVKAAAAkFBMVEX///8yMjL8/Pw7Ozvz8/NkZGQ4ODhCQkKvr69OTk5VVVXl5eVEREQ0NDTu7u7Nzc1AQED5+fnp6enOzs5ISEj19fVvb29WVlaVlZX+/v7b29vU1NSenp6NjY2EhITw8PDr6+vg4ODJycm3t7ezs7OlpaV2dnZsbGxoaGhSUlLDw8O/v79xcXE9PT16enpaWlpyuPDWAAADTUlEQVR42u3d2VLiUBgE4D4nCyBJSGKi7OAuru//dpMAgjUXjGMVFv3bX1mVO9Jt1wHlJhARERERERERERERERERERERERERERERkd/Hd6OOO6JO1PU4RI32/IU7uotD4dXok667PA9xROH5peviADXai9w5jmzgIhyiRjsdF+LIQtfBAWq05xz+RnkPG42Ys9trxJzdXiPm7PYaMWe314g5u71GzNntNWLObq8Rc3Z7jZiz22vEnN1eI+bs9hoxZ7fXiDm7vUbM2e01Ys5urxFzdnuNmLPba8Sc3V4j5uz2GjFnt9eIObu9RszZ7TVizm6v0f+8buhPK/v377as+ddw/dPK/v27PUzxYewB9EM0Jh6Ea+R5XsG7IAgc4xq9Xi+teg00irzEvJy364yiNz9tSwWN017Dl+s1MjSC9sc7AJRruM/XmxdMev6qUwKo34doOH/yZ+N51a5xlYcG1jjbcGi8XyO6BYZRASCrSdZ4ma7PxsVwv0aSJJxrfLo+x7iLRoB/eMymSQW8MqzRj7P1GpOgvVZVDJ9+/Wz8qK+fjdEwW8WDpI9GcR8BKRAzrDG7336KR7Pt2ahz2jU+rvPH6TwOu5WrqipdLnZrvL4mJ73GIphs13gKss0aZUr/TnW2GBcx4OMRkNegORuzh91fuGfDzRrX95yf4ue9jdy5Jda//fGqvfp2jcUNwxqD8W6NSQaX5xVmt5xrbNTD5M5hs8Z8BhQBgCK9fGZYoxH6vltibQ7galXwrlEOk1mG7Rq3Sekx6LXHJr6meKdqvDn3OMKHfu8J3pcp4RrZ7UMyLGs/yddrjJPJOA06N2hcPQVu+794eNpr1MsMe493wHXq7vnWKIOXmwKL1AV3aIxRA/An8s3bN1+3QMszfmtYGPlG/ZTvYaMRc3Z7jZiz22vEnN1eI+bs9hoxZ7fXiDm7vUbM2e01Ys5urxFzdnuNmLPba8Sc3V4j5uz2GjFnt9eIObu9RszZ7TVizm6vEXN2e42Ys9trxJzdXiPm7PYaMWe314g5u71GzM9HsNeI+dkh9hp13eUgxBGFg388V0eNfviZU6MDAdTIyPPYfk0jEREREREREREREREREREREREREREREREREREROYo/dWMhiL/l5rAAAAAASUVORK5CYII=",V="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZEAAACDCAMAAAB7ltZBAAAApVBMVEX///8yMjL8/PxBQUE7Ozuvr69kZGTl5eUzMzP09PTNzc3z8/Pu7u5WVlZSUlLY2Nhubm5HR0f+/v7s7OzOzs7KyspwcHBEREQ3Nzf29vbo6OihoaGOjo52dnZMTEw+Pj7Dw8NmZmb4+Pjw8PDg4OC8vLybm5uWlpaCgoJ/f396enpycnJpaWlfX1/c3Ny3t7eTk5OGhoZbW1uzs7Opqamnp6fS0tIlKBnqAAADP0lEQVR42u3dWVMaURQE4D73zsAMDLvIviPKEuMS8/9/WgBRgw9EqCLMOfZXVlm+cLvtYn8YEBERERERERERERERERERERERERERERERERHRV7kw4+WMfCZ0OISN9rmynN31oQJs9EkohasYZxRfFSTEIWy0JyNXOLOcZHAIG+3xEuPM8uJxCBvtEcFnKs+w00h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7/q16y1Aj7fk3Ss1iyU4j7fk3SkVp/qpaaXTMbedd+vJvxXci18k3XESy6cu/83MglfoJp+UfAdR68WycmkanLOK9r8BJEARy8fxvsj8kunVHnxYuAbT71e5I3SKuvV0kwVqw+XECID2LwD1E8iN77GlPgfeoVTC5GSbKFrkpbhaZ+nxaFwHqFRncHHfa8KkKzEfRqvc4yypb5LqzWQTl249FGo1GqhZBUha5ax1z2qrYaCxctelS9Mz4xdtuN2vbRX4H699RpdKEi464j3zA2ln/Kh7z36ohAlr3fva46nd0LdLt7Z7ZR93dfaQ1MLAINos89QfLzvB+rGqRSVDaLTIMktdF2pGBR61rL74AzEN0HnQ9anXL769+i7evi9R7Bp7ZgQhr4eK5X9O1SK70vkgpgXhfQfc5XYuc9uoXEXJAEvSn7YWqRdZil5Uatu4ATIvjVC1y4jtEF80L7j7jl66+1LbIQmRUxZtsfwjn2tHF8//1KUruhNNyzdmk5zutUab8om2RuJbgw6oD1KOod/H8W/H85E8ap+s1J4B76cbaFtk3xoa7fP7v/Wl8Ws/gN1apO4Pf6qbwDDuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtOe310h7fnuNtF8bwl4j7ddPsdcolEIujzPK5/51jSE2+v/X4aoeCMBGxq5V9y0aEREREREREREREREREREREREREan0Byk3I1baApDQAAAAAElFTkSuQmCC",J="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAcoAAAGBCAMAAADR3QFBAAAAt1BMVEX///8yMjKrq6uFhYX8/Pw4ODiYmJj19fVZWVlISEhEREQ7Ozv5+flRUVFOTk5BQUFCQkLz8/NlZWWvr6/y8vI+Pj7r6+vNzc3Y2Nhvb2/l5eXh4eFhYWGKioo0NDTOzs5VVVVeXl7+/v7Jycm7u7uenp5KSkro6Ojd3d2BgYGTk5Pv7+/FxcV4eHi0tLRWVlbT09OoqKhqamp9fX2/v79ycnLt7e24uLiioqKOjo7Q0NCHh4fa2toZwSUUAAAMWUlEQVR42uzd627aMACG4c/gNE0akgCDciYUCAdx6KBr2br7v645h3Vs1YQiLay2vkeAhBKElFcxTvhhEBERERERERERERERERERERERERERERERERERERERERERERERkZlksxGKEoWNpgRdgeyK0nXZ8hqaYj+uo0T18V40QeVriDFKdi8aoPKFoo6S1UUIKp8Q+JOW30FMaQ6mNAZTGoMpjcGUxmBKYzClMf5Lyh4ooXvK/nzCszSjdcrlzV4IDrg5bVM+dNY1lbF1ZMqcninl41dfdQxWG4/ToJyWKe+HjuoYVqcyfX+B1QF91JTjQilFFfRRUxYaYKuiAvq4Kc+nPUyZ0zZldjFyKwRT5rROmd0iYMqM7imVHlOmDEgJpkwxJTGl2ZjSGExpDCFwkfzUH88qEkAXiS/IzAYefnpaABaAXY8pCyg35do6g44T3LWcaPBl1UYaSwmQ2ljurTLNUvqPaqt9jJZMeW2XD/OnZNNLVwKvHhJSWvIt5cMp6gPoTGykxhWVcjP0OMAWcNWU89dkpyxXLRax6/v+yPeD+kD4URTFbhz5AAY1RdQSW6YsoOSUgeM4QZ6yOs9SZiy4yfbkMY0B9FwJxEjI09YazjxOewooP6VInnnKw8tfUiKOoshtqZcRlM1kKK3l0B9+Z8oCrplybynCStjy+6jxK+UM3wZBX+32WT392gaYA3bFb0imvL7LKZUOIGypXu1WbdR3k9MwigLv6WvtMD3E/XmsCuJRAs8hFPnIs/JqLqd0Xfct5c2tp1L24h3QPhtg5fG0/OzPV0FtAcVRWqLlKBOmLKDklKPzGazfTn8r+85n4Czlw+wYrjrVSfT0FbnDMXrm3Z5ru3yYPeCbBaz9hSfbQr1bhrvzlFhXlnNnbbvoVrIPrA7yFM8emLKAq6Tcju7Eq8r5jJ0YdaF02s/Pd0iuK0PfD+xmN6wuZXOA+mQLb7p2VjYwnvjDXZ0pCyg/Zb29eJfEvxvCRSqQw5nXd9xJB5B92If1EqnOTZUz2II0/mdELpgypXlKOa26VaZM6ZzS26wCIQRTZrRNac+2LdUxcpkyp2fK+suXO9Xxdr5EhSlzOqbcdYUyOfWgVMTvGkypX8p5/31KhSk1SgnYL9t0gL15N8AypWYpFfvpmE57QqbMaZvy7WKEKXM6p8xvETBlRvOUilwwZUr/lABTZpiSmNJoTGkMpjQGUxqDKY3BlMZgSmMwpTGY0hhMaYz/v+ghU8KUpUiZ8h9piv19uQsE3+9Fkykv0mTZ7gemvMyAxfSZ0hhMaQymNAZTGoMpjcGUxmBKYzClMZjSGExpDKY0BlMagymNwZTGYEpjMKUxmNIYTGkMpjQGUxrjB3t3upM6FIVh+Fu4aSm0ZS5DQZRZJhXn4f6v6xRFc5QoakTo4nuTGsj+geGxA5vGTUo1kVJNpFQTKdVESjWRUk2kVBMp1URKNZFSTaRUEynVREo1kVJNpFQTKdVESjWRUk2kVBMp1URKNZFSTaRUEynVREo1kVJNpFQTKdVESjWRUk2kVBMp1URK/ht8toXFKQwp/6CinLY2u2RMi0vGfBwXcmJcXk1zXPRQTaRUEynVREo1kVJNpFQTKdVESjWRUk2kVBMp1URKNZFSTaRUEynVREo1kVJNpFQTKdVESjWRMs51bFLqqJr0HkmpoqonyfM2KTVkn4hcjUmpopuyOJ1fpDSlsNVNGFJuofqxiGU+fZtHyf9C5rXxu5Gqk82UnaPG1UlAym1kRiKN+pf2ypIAkKWTkfG7kZuaAR5cHmC3Vyct5e4vUPYeAIhNyi02romc2CL4qKzjONlVyncjBz1SbrTOoYggSl5afdYWEU8EH/VEuEr5bmR+s57y00j5eZb8FeVpMkqSi+yfURZI+TmlhTVdrxxgf0QJVAGxTfXn87yk/B7l9y97JJ1Of0D53wislAux6/0ZKZdtmvL7H0YOP7iCfTvS8wNAbITOOSmj/ppy/RTBMhe4TwKQzDIZvx0Z+QPXBOICw9yMlMDGKVcn7ipfepunhxl5ADAv4Skzz78dub/GTA5riKoGpNxAFavyK9Pp+WCQ/+IIL3u+ntIvuUip5qtnUqq5IYSUa8+VcblNi5Rrr2BJqSNSqomUaiKlmkipJlKqiZRqIqWaSKkmzvbsX6RUEynVRMpdj+fK/YuUccgmZVxXD+ze46lBHWUMAzvpkjKeqwcm/Efcni0eFFBuNyqdI7xk7rLlUZuU8Vg90H6Yj2E66VvAzOvlsxM0T/BSzxsMc0VSxmP1wJrk0n3vuOA14XneoedNck4/m3n268+AUYGU8Vg9cGzjogfAHgJhIWnZtxLAusOiQELgsryLv/ZOUm73z9v3/cOc72eizRs1wvLlcbMwwbSIRVUpAS0xO3gwIeVqbathu7PWURXtrml2UcJ50+TqWHQmeeBezAen+MpmT/GVUymS8uuvERamwbnfzFf9u8DzxfO88SB3frwclDpwmdvehXeblF9+jdBJTJ1m/X4+yzezYT9E9cjgQi6XXOUuYNV29OMwKd/m4qyeSDUm1z3XrU+Pi14L5kq6eK6ZCobpCWLSnlPiJtW/qwaW03MBt5lJn5uLxmUmsYS+yDgJxKV9pwzCQaLmWNdA/qLfvB7eFmo2JuUi4te+U9453sHExaJLG1GVNoCBi/i175SBDS3tOyVW77iLa6QkJSl3LVKSkpS7FilJScpdi5Qr98HGNVKqiZRqIqWaSMlzpU5KXsGScgciJSn/4sZGgyhDyvhTTu8AdI7xVOfKBjArkjKGlBPxUqlRI52KfgLuVcOg5IeIktdSb54dkHIrrb9HddiyUJwOLwwAz0knHScbbQBMVChmEQB5tJe5pPxWf0U5nfVKhZI1aE/vAWQQJcsHi+qCZRLyALvblMZczTupp3wg40fJYiNl7CjRtWd4LvPZXtmWOtYkr32+DB5nezZEWQaS0S6ZXEPpSvBblPGert1tSgfR9kzpRMlie085EHf9a+zUjMW/9u6GJ20oCsDwuVtraUXRyUdRhkNQRKebZqib+/+/a7RULHihNWFy7+V9EjKWsGw571oLKCezXSn9Xq83PSpbL0dlazFlPxRSmp9ydlRGKRUlnuZT/r4hpQUpu5WJJOWUkkwuZXP3OyktSJlUCqrDaD6lymmN7oWUFqRM3EUXL//EsbxVb5LS+JRlkZKUpCSlmUjpDFI6g5TOIKUzSOlMdVKSkpSmISUpSWkaUpKSlKYhJSlJaRpSOoOUb9j6saKkfLtezcbP9SVlwXq106+eyTv+SFl6vVoUqarBO/5IWX69WvxTVY3d8UfKsuvVUpOUxu74I2Xp9WpZSmN3/JmXckMDKV6vlqU09T+hgSk3cZoqXq9GygLGbQ9ctl6NlMau7T5753o1Ulq4TH/lejWVIqUdlq1XM/7am5Rl16uR0jrNwNJnxKQUV17cICUpQUrbGPZtQKQkJUjpDlI6g5TOIKUzSOkMUjqDlM4g5ZboB6R0Q+zv/SWlE+I95d+dkdIFwUip8TUprVA0u8eGCvvvH/ORLOHVT04HnzxSrl3x7I57Su14Kx/6uJvo+ukvvUqiW0n8uvJzJA5ru43wW2c8apJy/Ypn510p1TkufuiXgbxqyLy6SpK3PZHnKifYdSs/u36kGoPChx4MZcrvdDrdyS1cTHn+nPyFASkzG0gp122lRsHyh3qqllGLKWthGNaylJ/PSfkfqcTszqrf7a1Kmb8zzk6w7fSPJrcs5f1jiZSfVWmknNNbd8p4dtnTWEz5w59QfiJYR0o/FrzTQ+EJNsqo3GVPNJ8yEYuowIu3/ROHNie77Cl3VFZS3fR2JJJEnqXcqVRFBccXt6TciOzJSNmUp68pZaKbv4Ldb6ZfK0/CO1JuQPYSQcmU+RNsRTJVkT++yNX+sOo1VVXk8uCWlB8re+GuJamyT0akHlxeSM5Nd1c9T3I+yK3qtmUibpLyQ+lfTi8+KgeN2pPkHDaHhwa9vb2VSr/J5c3uWPBzKVvJ7Lee4cw3hMDoMZNSx8oxk1LHyjGTUsfKMZNSx8oxk1LHyjGTUsfKMZNSx8oxk1LHyjGTUsfKMZNSx8oxk1LHyjGTUsfKMZNSx8oxk1LHyjGTUsfKMZNSx8oxk1LHyjGTUsfKMZNSx8oxk1LHyjGTcjU3dvxBHNnxBxE3dvxhyoUdf0g5seMPAAAAAAAAAAAAAAAAAAAAa/YPuWzT64OsNxgAAAAASUVORK5CYII=",k="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfMAAAERCAMAAABYXb7wAAAAw1BMVEX///8yMjI4ODj7+/v9/f1BQUHy8vJEREQ7OztVVVX19fVISEhCQkJwcHCvr69YWFjNzc1cXFxhYWFOTk75+fn09PTj4+OFhYU+Pj5RUVHf39/s7OzY2Ni5ubllZWXr6+v39/fo6OjJycnu7u7l5eW9vb20tLRLS0t5eXlkZGSrq6uTk5OCgoLPz8+Li4udnZ2goKBpaWnExMSHh4epqalZWVl/f3/29vbw8PDa2tqkpKSGhoaWlpbV1dV1dXVtbW3AwMC629LZAAAKu0lEQVR42uzBgQAAAACAoP2pF6kCAAAAAAAAAAAAAAAAAACYXXNRThMIo/A5sIhctCpoFDVeWsV4wUtT05gmzfs/VcHaYDtNIyUqMH4jOI7D7Jz9hp2f/Tknonhj8miYN0WBV7mEOQuiwCNTEHiFS5jT0BP4jSK1UhVHo1rSWMTxyHCY9+NKfejLCLlhCUelxGsclayGeUfnJJX1ysYOk1UclRxNHJtMhnlP56pGsj4adBFA4ni8MUIKhyKRPq44hjP/QjL/1K5mbJoyFebflBmFMXxqi+1FhWGmpun0YUQP54EX52dxLvcf1CucB/I/13Y9Y8vhKcPYq7VCMh3OzUsNF3uE7mBUJ6mpKXFOKtOVncmy5zRhqu2nPMkvcwfjdDgP9mSyWuqeIsywQJ/yogafMQ/iGj7ni9oTyO7jTVKdEz7JiXpxHnkEPerafnEeksKh/qjhzFQ4j7W2FxDwhJ+0K1384rkHSACGtYQ7l786s8FYxA9jr6YKmQrnb9dwfOHD/q8gnYQABVtWkvrBp4+AZ+sREvS15iTK+UTaAy1DydcNrVKYdhAvTLgnkwrnYV/tlWtlnxqDswDAe32HLWRJfpkmsdnOSKuiY8tsDAkrz07o2p4jgPZ3AXy2EfBOYUQvFc4P6at9InYwXN8aLl3VsixalpKr0NI0zVVdzQJQafiwETBKrvPFZwDU44VJSJlBxuirHe4ckKACUIJP3wVQUwXgIkBsRpI3sBNXwymGYSg751eLrfMoYVLqvBy9xxI6F685h6tpmlr3TxJ8VmVPlu49y7tPmHMGx875sr11HiFMWp0zjnObHfxC3PM6nKY2ZhWlBnzd+IfVWAFz4O7WuhGJdf5B8qEUcHdomLQ6j9xXC533aGPHXb1BR9U0jZqm2AOvsex/d525OwfwKICPJnzEY3Lvc6AFUJdbh4dJ7X0eua8WOu8beKG5txyK9ca5tRZrpdGDj+FTZz34qiTMuaqqL86/fbFBveYODw6T0rqdjNxXC517I4TsT9NgbU5bD2Xt2cOO5UhrJm8fjnt1+9zqANRRM24PDJPW53Myal8tdN7Jr/7uHJOxMzcmuorCLQK606XYuAORNOcBNjCTgInVs+UOu4BjDmOHsVfr5O7DkZH2XrlHabpESLOZR/BIa1qW0i0WzCtHLlaQK4/Q7U+MaRcolS1vmEuc8xHz/AzMmhiSBfi0mrHChO9MpMJ5tH9zHYRYeQ8qtiiy1+46hlp5BOQa9OXEwZbWt4dk1e0B1U6vipC4YarJ76uRiWhF/YUUDvVG//z64vwHO3eQgjAQRUEwgrjMEQLe/5IqiLgShCQk09U3+NRuGF7O/MJ8RPNffyaYj2r+/WeCecb882eCecn8/SbDvGX+7HpnXjOfJubMmTM/oPlQcxx7HDOA+VCzO3scM4D5a17rNm3WbfV5rSMfcxLzoWb09jhmAPPpOi9bzmUu88rkRz7mLOb6K+ZiHo95L+a9mPdi3ot5L+a9mPdi3ot5L+a9mPdi3ot5L+a9mPdi3ot5L+a9mPdi3ot5L+a9mPdi3ot5L+a9mPdi3ot5L+a9mPdi3ot5L+a9mPdi3ot5L+a9mPdi3ot5L+a9mPdi3uvB3rk2pQ0FYfjdJFyaiBcMiAqkgFIp0EqxVTt2/P//qoRmQggNbbhusvvMBMHzYXn3GTK5zTnqXB7qXB7qXB7qXB5ZcW6dDva5hMlg1+uxcA6TEeeWrrskbt0lf0myGvZGbefrq3EOkxHnA11HUdw6iie6Xqq49VJJ10UWty4yqXN1DmROBJsw6lydq/MVMlhKnTMRwSaMOlfn6nwvdD8yCqPOD1GhaVy/8gmjzg/i/JqMJ4tLGHV+kAr2iKjSYxImF85PkYD5cjO+/2wd3znQapDTTSi1eTIhzltlHzLKPhdnPjR/vR8aEdB0CuWG86FaGXkAhZwh+unqYM5RrxK9mQmlNk0mxPkf2vdY0MAyRQLQereAqYs55ow6+a8WAHq1A9zDOYc5JKreJZVKn0zcvv2kgz8Y1WqVZpsT78zjFADZCLkjBFD9OOfn3RI1Wgml0ieT5NykQgDFO1NwHKcQdObqkZ1z9CpEo+d4qfTJcuN8HcvOo28qABrBX5C/BZ2ZtJKcW39zHq+1v0/Xyc5TJdu4mWyctzdy/uvCh2ZbI96ZM2MGGT7Py85d8vg7T5EstfM2E+frWXZeCqDIkU4p3hmgCZBtNld+5x1yj7Vvf1+3b0+fLAkiJlcodud88eZsDs23U8DvWdiZt+8uyK5/6seddx3wPIZLnUyk83G4B5z/kyJHt18vPYBs1J2nmPMvDwhhda6WPplE54s94HcEuMDYAIaXHdf06CNwc9Jfcu6Vvx3Def0i4ZrMVsnEOI+e0aBo33xChAcq0xQY36JPVMGM5i1FOB9NjnXt9Tyh1BbJxDhfenPfKPxEhJrXqWEdRe/wzu0fyfdYNk8m5xgOZviGybfb7l5qqmRSnfuw+nYZe2ZCnct7Nkqdy3sGUp2rc3W+QgZLqXMmFbiHUecLMlhKnTOpwD2MOl+QwVK5cH6ic4ukC5MD5wOdQyhdmBw496fXKmJvFDeYKyx3Ybg5t3ROwHRhcuAc1ml7n9NlttPP/Zm7MOycK3Ey4Ued80ady0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody0Ody4Odc+t0sM+plgbpp1rKXRhuzplOqZarMNyc+1Mn1rA3ahtMnZi7MNycM50iNVdhuDlnOhVyrsJwc850ynOupXIxfzvTNnEtpc6ZVOAeRp0vyGApdc6kAvcw6nxBBkupcyYVuIdR53N0XWR1ruufq/P/dn5NxpPFPIw63y32iKjS4x0mJ87Nl5vx/Wfr+M6BVoOc7tal4smEOB8aEVAOeYmNNJ1CueF8qFZGHkAhZ4h+ujqYc9SrRG9mQqlNkwlxHlIkAHSLOSb1YiOtdwuYusHwjDr5rxYAerUD3MM5hzkkqt4llUqfTOK+/R+deZwCIBshd4QAqh/n/LxbokYroVT6ZKKcFxzHKax2JjZy9cjOOXoVotFzvFT6ZBlyvg1YQP622pnYyKSV5Nz6m/N4rf19uk5obtpku281dk77sM7PjBlk+DwvO3fJy7TzaLJdOm+DFamd+zQBss3myu+8Q+6x9u3va/bt6ZNxuHkQYa/OS6VSQmciI3j77oLs+qd+3HnXAdNjuLTJBDlPPLqNjny99ACyUXeeYs6/PCCE17la6mRinPu4wNgAQOUA6i2PDC87runRR+DmpL/k3Ct/O0ab6hcJ12S2SibJ+QOVaQpg8oI51qS2PDK+RZ+oghnNW4pwPpoc69rreUKpLZJJcl7zOjVEiY8kU/SOcI/lR/I9llTJONwwWguP6zkMKmTiXio3Mt6mTDwzwY2stykLz0ZxI1dtylWYkAyGUOfcyFWbchUmJIMh1Dk3ctWmXIX53c4d2wAMAkEQdGARugT6L9MZAQESwUtwmung/vMdLhzh56eJOlPUmFl8jsOYWX52x5gaI6/VnjJtmdcyZk92Rs+YSu/XK3OZfZXLNAYAAAAAAAAAAAAArvMD6brkIaU8kEwAAAAASUVORK5CYII=",y="/ran/assets/%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82.DlwNEriZ.png",s="/ran/assets/%E5%8D%95%E4%BE%8B.B4dKFqxx.jpg",m="/ran/assets/%E5%BB%BA%E9%80%A0%E8%80%85.B6neb_7R.jpeg",p="/ran/assets/%E5%8E%9F%E5%9E%8B.DYbH0CSA.jpg",t="/ran/assets/%E8%A3%85%E9%A5%B0.CuuWN9YK.jpg",S="/ran/assets/%E5%A4%96%E8%A7%82.Cm0-J0eF.png",N="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAs8AAACQCAMAAADA63aOAAAAvVBMVEX///8yMjJERET9/f0+Pj5OTk47Ozvy8vJKSkr6+vpBQUHOzs7g4OBUVFRRUVH09PRkZGRXV1c3Nzfv7+9CQkL29vaCgoKvr6+5ubnKyspHR0erq6s0NDS+vr6np6eVlZX8/Pzc3NzY2Nhvb2+1tbWJiYnl5eWamprFxcVgYGBdXV2SkpJNTU2ysrKNjY1oaGjr6+vX19d+fn5ycnLS0tKioqJ5eXnp6ena2tqenp52dnbn5+dsbGwzMzN/f39aW3v0AAAJD0lEQVR42uzBgQAAAACAoP2pF6kCAAAAAAAAAAAAAAAAAACYXTvaTRQIowB8jqOgBQFdqlWQbletsba1S6WN3dT3f6xFG0ftLt4JE5jvwsQLE//zn5iJjKZpWrmJvuez7HyvL3Q458IpCzFmNYyFDifTuDSF7rNjuSg71+qwr8M5F05JeLRQBRY9Hc65cErCZ/l/gLZM+jqcc+GUBIlqIHU4FRi0PJPoPusWlGkS3WfdgjJNovusW5DHJC0oQfe5EoNeehLL6EAS85qAxDokK4pcfFP8oCRyNAuwZ0YznKVAOGq65CQxJaC3VeNH+jr9p892neEApxQYlEQ+bEruU5Ik60/OkhSyKBDOZa8DyCfxCq0s5m20UyPAAwPOFkMntQTw55FLXv3CqeJXRiIfLTvFRzslHB4giwLh5HMdYCzUWVna52CnRqSsxghwnZkAeNAEVkPGYsb6CMcUWFl+v8+HPt87tIMvjuJ9vuh1APkkXp2VxZSQujPqNp45BcDh/rzBZmvd5VQAUcjNO44VvjIS+bii9Bh7T/wSe8iiQDi5XAew6Kmzspgr00yMhWma18C01w4/NmEY95KTPn/QiEwAL6MmHwROVaTP+O203+4boRiwh9ZgWucErWjuIosC4eRyHcCkr87K3igtge7hzUmf7dd7hwJg4/r2DscKX1l+5435c7T+Wfexun1ZdD+9BedRk8MBsigQzn8/Vfg3I3ExYwYTw59sDdD67EA6PT/DIQA28E3hKyORD/dmU1u98AGp9+Cm1+2QXcNEtuLDqV6f26H4wZ0NcMclJIb7/zd2fR52q91nm0cWPr2Jx3nCBJkUCKdyfTbDNgK+BsErp8CaC0jBZH/emIwAm+1q9/kv++bakzgUhOF3ej9AqRRbClJucr+KsIqK/v+ftS0lG9lY42ax1HaeD6YlJod55wk5TA+W53n9DVGjHVxsZ/7ANq81S7J5v5Emn2/IHV43u0J+oxGEQVucQgoiNjTLt8+d9cJtkHGv0bRWHU2I3JJmwydtiBhSEE7ufHapJtEAEyLyMX6dIsbnARXu8u2zXCGaP1mwWiapm8KgTkR7oOUjjhSEkzufxQzLhw5GZqUtA/4WfzGY4cBCqSPfPmNb6yKiOLYEMFs+6fiMFISTO5+/TEzrLt+yNITzEakIh33+Fy4eDIeTinjYZ/aZfc4B7DP7nCXYZ/Y5S7DP7HOWYJ9z4nNuQACH8yHs8w+Efc6Fz8gHvN/IyX4D+YB9Zp+zBPvMPmcJ9pl9zhLsM/ucJdjnrPpcd7hlHE5mfO7Z5o5bxuFkxucy2S2ZW8bhZMNnWC7Rpsot43CS83mJd5TaZ17DU6hR55ZxOEn4LAoBVAgp4YA+L555jeGEXtsdbhmHk9DnMyGiQ8of6IxriPYrTYbcMg4naZ+Bk8uzrVFvkOJxyzic7/ZZkppSAEmSMgK6UnCvSAF697zvrHpL5DrcMg7ne32GPlg9QbeB5xICxEypAvJi9x1Hdss5ahkRh3MJnx8GxS18FQechbm8ctG7Kozki/t8h58LBXA4l/BZ+JuuZT4jZKg891qVyqo5cIDk9xtLvOdF+sE9iwrlcJLfP4copEkBFqzS7aprTsemAyTwfTB2bGiE2NfBHwDaEQpv/OnLvIfUExXK4VxiviG3bLpfI6C6Mmpds21gcKWfcw0x+9JIik6vTl962ZeLQLXQQ9+UkXaiQjmc5H2+u6lMhsU3e+p1gLH1y/CFBtmVbpzzPU+ZRo8M/qdltcJMAGjvAdnoI+1EhXI4SftcNZWHOgL0X8ZU1tvG/dpZVAAs5ttzrdGPeaQbPzYEqSFzVSVE7Cs9hMwXAJa3SDtRoRxO0j5jJ+OI/AIxGsqNQnl8uD3TGtZb7JGb+LEhIWA3FeghgqoIuaMuAO8aaScqlMPJ3Pm6mCORn48NBd2rKqkH2loIaQfWpAMokkDKiQrlcLLnc9yR9Q4RrT4eG6KqAcJGyOlHUMZaxuH8OJ9jflL0+diwWAbWTTXAkE9a9kglAF4BaScqlMPJns+x/x8/NsTTA+C6ABwFJy1Dow9gtkfaiQrlcHLr8/uxoVB9eSQ9ygL1yl8tW24AWV0g7USFcjg59fl0bDieiqtKCU7TVvqHF/UdOcfOKl145dTvEI+Fcjg59fl0bAgdPfndzPCGmi6OeJNHdY3UExXK4fxm54x61ASiKHxmxgoKCiiIUFEMcZ2m1k1aI9Xd/v+/1QESI3a7D2QfZrnzxeiDT3fup5mEk0PV5/cR+j/DfXNQczjG535g+pEo+xxFAMQcd8zxqTE+U/b5WdaXP1RcEkD+BsObuBt8CozPhH3O/gRB8OOQqvc9ZPiC1xMYKviNobwvU9A+62t8puuzm7pnicV5XkRQnI/5wLaZbdtLABYUJ2BatsoUdM/6Gp/p+nxcwt2IjYVNBoUn5A5gaChetxAMJ79dpqB71tf4TNdnJOCYNKyhWDg3nyMR83g0Q7xslynonvU1PhP2OcUYCg7FfjB7sRXMVmBrr/OynFdft8oUtM/6Gp+J++xPJiv1/wxgBiD0sEJF+Wviwj38U6agezbS+EzN5ybie/OZo341PudDgRWEA0UWIXt+KFPQP+trfKbm8x2pGLR9lt+AFeZpwmvYgCvuyhT0z/oanyn7vA0amcW49vnpS6I+rMRHzVe2zx/KFLTP+hqfCfuM3ab2+XIoEO1n8ioB7KeBhMI78uw6SfBQpqB51rfL4YfMAwUsFvbbZ9mUV3EIYH1++pmOQ87Hg2Gaj5zj+FwCWbqw2mUKmmd9uxy+zxxQwGF+v312ElTsoBgJAHnkWV40ykfT6XcXFdb10ipT0D3r2+XwYxY4FvqO5QQs7rfP/yfCDW0fbX/Y4YuC0aAQgJbXMYuF+v3GtKDToCL2Q9Z3Qj8WALS8jjnMNz7THrQrGl7H6puQWTPtQbui53WsEGbNtAftiobXseomZNZMfFDakFkzmUFpQ2bNZAalDZk1kxmUNmTWTGZQ2pBZM5lBaUNmzWQGpQ2ZNZMZlDYm4vu3XTsQAAAAYBjkb32PvTiiRPGlRPGlRPElRfEFAAAAAAAAAAAAAAAAAAAAAIADA572v7F9OdVZAAAAAElFTkSuQmCC",Q="/ran/assets/%E4%BA%AB%E5%85%83.EIifVVTy.png",M="/ran/assets/%E6%A1%A5%E6%8E%A5.DX0mO5JC.png",j="/ran/assets/%E9%80%82%E9%85%8D%E5%99%A8.C2VH4lXy.png",O="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAvYAAACUCAMAAADPnJ1qAAAAvVBMVEX///8yMjLS0tL9/f319fU+Pj5kZGT5+fn7+/vx8fGvr69vb2/o6OjOzs5RUVFCQkLz8/PKyso7Ozvh4eE4ODiTk5Ps7OwzMzOWlpZKSko2NjaMjIxoaGhWVlZAQEDZ2dlgYGBcXFzu7u7d3d3FxcXj4+Orq6tZWVlHR0e3t7dERET39/dycnLQ0NC/v793d3fW1ta7u7vY2Nh/f398fHzl5eWCgoKgoKCHh4dOTk6bm5uzs7Pb29tGRkampqZfzCWkAAAJR0lEQVR42uzBgQAAAACAoP2pF6kCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABm31y4EgXCMPx+3AYQzAsL4hVvWVrplpV28f//rBVkM8t2bYvlw8N7TjMnR5nnfOc5yICTJ+uRTe2EEsyJZspZZOHIw5ePD8mBvAVKPAU5eywcefjy8SE5MCa17BISTMlukZk9Fo48fPn4kBwYjWwkHJu07LFw5OHLx4fkwJxQCQmnRCfZY+HIw5ePD8mBIULiIcoeC0cevnx8SDJXOl4sHHn48vEhyVzpeLFw5OHLx4ckc6XjxcKRhy8fH5LMle6TLLoLkWv/Prn2WQP+FEvfFy0TceZ6etrbtm8Xbbu6iLkaOpRKrj2AXPvvZ7HO4M5LiCKTnJ725kPL7Jrmwg+C4An4cQEolLL2Ein4cx6X3n1cyKUcvz157eP5DiLKtd+NrEbxwobCuMJDetorflfTtE7l0W3rgNJ2Qqz1X4uD9tWiiNvdWN5PMXn99tTP9rtEufbvolNkm4MwgoCW49Udx3tKR/vCSNPQrZZH8xsAtTtwOttLJOJ2N9ErrLSPiHLt/6a97Mm4siLtAX8I+NV0tJ8F6GIELMgE8KPHQ/vBqN6SAFpn04avFZ1CiIf4lfKo7g9CwxLQfjV2GoBYtCvTEiQy2w00bwA0G+Fk8v2y7s/i4X1EufZ7tFfXESfupH0da6/2gLGVjvaYas+j+eXDYlCYTkw1CkVtmtpfWEahtXO2l2jqWqP5q3Pr1Uw0lsloP6SyIgHzwOqtbZdoXirhXBVwvadwssbyUu/fxsNviXLt90Y4gOxhJJ02sdHecGSg3UtHey1M1wnWbTBjcgNToiow8ORd7fvAeeWVZJjMaqQnor3lmQB6XgcYqJDoGoBQr7AKQqmNehnb4XdEufb70nsGFBXT1ViKtBfyTw2Ao7C4b9/+HTnta3uJxK72CmCTvJXsx/hiSiIR7XF+1rIxoyhCohIALOboPoYcMzIAvAy/Jcq135dOF7B8rCp3EMaAmu1ecAroJKekvaXFKQMA6cCmZ6e9BZhneJFsSH0MktIeojGGRdYWB5AqHXUS/mORBOBleJco135/zucC5xpMz8C80nywxf1SACUHKWnf0+IM+GlfpbKBqI0usKvL2layPg2MQkLa39r6qSpDu7D0Tvm39mhpiw1bYdTRr4fx8BuiXPv9uTmdOu1BdRw8oikBck2dlQSulmlpj2IzShH8tMedM8amleh0rC7EVjI0nOUqIe2HxXrxCnCnlfpoq/09dTZsyuLEGfXj4TdEufZ7Y7Rd6Lj1H/v+5fMEcnN5jRV5jvkdc5Qn/8C9fN3ReJOktI8JP//ZdyZ9gS/iYGrRkWpvL8L28h64OrsDYAlAVgz9O+a4rhc7n+fuNqOMEOYJiPsk6h8RctA+5OBp0ZFqDz05lk6RnFOZY212CdPXnn+ljk37JFmUO6KLHh+ejwjT5+NfKeaq8WI5V+mszIjnA0IGfPwrxVY1hgujYUBeTefD8xFh+nz8K8VUe5YLI/2HR8EtH56PCNPn418pntozXRiVn0n9yYjnA0IGfPwrxVF7rgujXoHoTuHDs5+QAx//SnHUfndhxCtFysOqUgy0l0h8zxzxwijXPsPJtd8/R9aWkPy/uvOLnKxrz29hxI0nX9KmoP3LzseaX/cfZMC4cPwHEvFWyEPmyNTZleG3T34DMwXt452PN62OfunXgILmugGJ7VbIv4QOS5FH8YZd7g9hhl0mj6vYV+orB3vZ+XgJwBzDpRkwIBFvhTwy7fk/cs9/nPBfDjYjY9vZJM+oBEgkZhRFHNNFjnLD8jnCDiGTn6Kxr9QXDxbvfHSj7tFHlfrATxIWWce2pGX61PgdYfp8/Cv15YPFOx+n607yV0CrYAy7JOKtkMd0A/MX+Wa7mygUhOE5RVooLkYQqtC6pX5/x9raptvd+7+sVTJ60jHVSXpIhjB/3sQ80SeTN8QTQOQzQieGEvzkb+rHX4ZvPs7SaeIPAeAzS7JbdYOvQnJ+ozRHSIFPhJ4YyvCTv6nyPJygPw5X3db9AMBKu3Zk6dRDyXgedNuWTrOvkKeNZHTF0EGQYWP8FfJrVWMIImluX5S6Urt5Z5ggSU2qUPtvD0ZvQzf2Hnfp13uNW516KJmt3NAf6jRb+7Xrbv9aDB0EqU3xtZ9MVY2zLySJocna1/bBMEGSmFSg9t8fjPYfNu8s6PwBiK7hkHooGao6wCQDTJO1x2kmDB0EqU3xta91/qkaMASRJIama88wQZKaVKD25w9GkynEKgRY2sfUQ8nf+6U1W4c0XnurPk8ZOghSm+JrH212LWIIIkkNTdeeYYIkNalA7c8ejJysDc/Kze8VHBL0ENLpbNz6vXIOabj2TaW8G4YOgtSm8NqHjXjXIo4gktTQYO2VvXrimCBJTSpQ+3PcNruB/NbY4s7CxOWlrc7H08T7QsLnY+J/tDALuNr3sheGDoLUpvDae2/5xZMhiKSxfVHKmTnPI49hgiQxqcTV/gyX+jHAQL0CLBvHzCdUi8G7Pf71hczn9kGn8f/2/cS6rIMgsSm89kvfyct8WRBJs/tCir+qM7uqdu2jvMuWvQZoe8c8DiFx7ts6zdc+YOggSGwKr/08sO1A2f0zgoQ0ui9KLVmrQpKYVLr27Yc4z3QU96Z9nXoouXDdaOzqNFr73mRWf9wwdBAkNoXXHk+IDEEkze2LUuuBc+WnDBMkqUmla394zG32EoyHAJh6TskoCLwQANNw7V9HSXdbg8s6CHJszNeeIahJU/uiVGTfddoOwwRJYlKRu7RCXST6yPWTY1K61clykegj10+OSelWJ8tFoo9cPzkmpVudLBeJPnL95JiUbnWyXCT6yPWTY1K61cly+c+eHaNAEAJBFO1GMHAQvcDc/5rrBpttMoFQ5fx3gk9TWSv26PbplNidLmLkjM1mjlg8e3T7dEoMZ1+zx2Y9ayyePbp9OiWGs2959xkbzX5ni8WzR7dPp8Rw9uXK7a4Si2ePbp9OieHso7Q6cqNRW4kv0x7dPp0Sw9kDf1lOktlDDLPHCzF7vBCzxwvZ/deAnxM+fcBDJ3z6gIdO+PQBz5zx6QMA4NMeHBIAAAAACPr/2hFWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgCPlb/qJsAOgkAAAAASUVORK5CYII=",n="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAmUAAAE9CAMAAAB9ZOUSAAAAulBMVEX///8yMjKbm5uVlZVBQUH9/f1ISEg+Pj5VVVU3Nzc0NDT09PRlZWX19fVERETNzc1OTk77+/uvr687OztRUVFYWFjw8PDl5eX39/fT09P5+fnt7e3Z2dldXV3d3d3IyMiqqqq2trZubm6CgoJKSkro6Ojh4eF+fn6+vr5hYWFwcHCKiop7e3t2dnagoKC7u7uFhYWkpKSZmZmSkpK5ublzc3PExMSNjY2GhoZoaGjPz8+tra1DQ0PKysr02ohKAAANMUlEQVR42uzSS0rEUBBA0SpJMJDQwYggDvyBKKLgSNz/ypx3xi/0o87ZwJ3cAAAAAAAAAAAAAAAAAAAAAAAAAGBv3JYhGxqWbQxqG1+zuU+bFbfltM7R0LxOuQWlLblGY2suQWlDztHYnENQWmac67LBJXMZO10e4LLqXMZOlwe4rDqXsdPlAS6rzmXsdHnAeWN8C0o5/LKbp7/TT1DKsZc9/L4PmemyYg687P7j6zozp5PLqjnqsvnl+zYz764e49ll/+zca3OaQBiG4WeVw6JCl0oFD+AJQYvVahONafL//1YXSU3aGpuZ1gj4XpMw40y+7T1ZXJa9Nu9T2ccRk/yFC2nATqFtQiX0PpUNP2eVRX+vjJY9Sui9Zkzz5uWMSYtr1+UCd/8PVNm1ee+VjLHCGFV2bXK3KkuVlVDunjBRZSWUu6flVFk59D2qjJxZz3B6VBk5r57DjIFKlZGzMseMfW5RZeS8bnSmPZ4c1Jv4Hs/6LjKfkbpFZjnz8NN0AhgAhi5VRjKuz1jVfn1Qh81tOMFPAyNGxkBKwd7GsD5J/awy0YYBM+YBVUae2FXGZu4rg+olWhvfwzYyQy1qrCGptmEfKlNXPALQ803s3Q9gYLPt0IxJnj1aTL85NqjqUsQtAH3tbpJ+XGgB6rOxBzghCy0hRE0IpT5jgnMeWiEXAGaOxJzUF6qMHLRGjI3NPwbV5I17bc9NNBPRzp8s1vDmYgrAgAVASX/6IQDXUoEwi3M1N5Jph+7+r0ODZSAx6eQn589BdZ8ilDr43vxmoytWwNC6/aUyhJxzS5cXA9LGT2wjSETSo8quAfvHyiB0XQdqQtSASQApSNOpR2qvtnuubIn7mRIBrZX8Fc4GWADmQDRUqqz83jpM3aMz5iEifX9FW88YDKbu1CKLc17jXOlMt86uPwqjRVhJ/0wFug+Q1Db9L7sCbxymfnb3f7qyg65YyMuLGVONV8FALGLFmUDSJJ3pmuRTZSRjf8tWMk5V5jWRWm89dHkF0svKprEy7t35fLPFk92cd2ntn7xtVVbRtBqgJ8YtUq25mDoV/FYZqoOgolVNC6MBUt54p67CqUqVkcxQZ9qHVwd1DFQAHQdL/VMHUrfbhCWEeBBC8T6OlK+B/XGGuj+H9/hNG3vAB18kwzpVRmDGb3laPsMz119DEs0EFvYUO1l6kWb5bcCOYO6qAfZ66zv6jnkFGPv/O386Nu3JIC8xRrsYybkxRjuyybkxlve3S+gdpuLLeWX0PmYp5Lmyziamd8tLIbeVHU7Jo8qKL5+V1Yd05k+Z5LGyk6fkNaiy4sljZadPyaPKyu7yp+RRZeV3+VPyqLLyu/wpeVRZ+V1+VZYqK6I83v3//oSJKiu6/FcGUGVFR5WRY6gyqqxoqDJyDFVGlRUNVUaOocqosqKhysgxVBlVVm4/2DmDFIZhGIDV0EIhgUCesOP+/8A9IJcNFhK50rkYg3QopfiMckymxGllz6ZGOybTolrZs+lxt3JMpLQ7upU9m+sV03lfVpaNHzVdvZ4xkbP267CybNA0WRkRmiYrI0LTZGVEaJqsjAhNk5URoWmyMiI0TVZGhKbJyojQNFmZDFiZALEyGbAyAWJlRGiarIwITZOVEaFpsjIiNE1WRoSmycqI0DRZGRGaJisjQtNkZURomqyMCE2TlcmAlQkQK5MBK/sTrAsA9P2tjHDNZLTG2t/KCJeZRmus/a2McGVutMba38oIFzNHa6z9rWyPb6ARuzzt9eKvsbKt9rcygiUry896S1aWn/WWrCw/6y1ZWX7WW9p3tpXlsbTvbCvLY2nf2VaWx9K+s60sjyXf/vOz3pKV5We9JSvLz3pLVkb9S/jD3rk2pQ1EYfjdNtm4iwlJc4OEq+EiAjIoiLf+/7/VDZTql1q1zHiSOc/IDvngm7NznjFxs0qVusSW1WWXM+UusWV12eVMuUtsWV12OVPuEltWl13OlLvEltWlc1WqlS2ryszrWSvN+tmyetVKs362rF610qyfLatXrTTrZ8uqWCvf/Vdl5qfL6dkA7Ma411wB2MDQmVTOss30ES/0U7aMlmX3O6ylH8+upoULaBgu/QSGQMWxghebkbplw3A3GuPIQE3xmzuxZssIWNaKOsE2eVzibglAw7MsKzQvIBgBEhLAiLZlrbls42nUPionJ+c3OLD0Y7aMgGUIgKcVBtk2h2UJS2CPrszPMnvlTxMAfXk/Lg+vZQ+NWdGCIVF3usOWEbDMcCXPSjJAYxjsbvB9OATsB2DxtOhvJ0vClrln549yTzqXLiYP3fH1DVoL/xLAIMbDnC37csu+WSGaBeBhj8563aULd7tsICpRUeQ40TneRLwChrePTuxkij2JIcNTeBsg99fA0NsC3TWGzwH+hXgTtuwEOSGu04NldnsgvPkABrtoA0gGUXM2aAA4pWWn/p96vuM4gPZ9DYx7MPQ6ABoT9HQON7z8X8vO2bITWHZm0OYVjxY66cgD6Cwjbz5Gaz2LLxYZ4VVZa//l7Ee0nQNKANgJ805v33EOYs2vo2V4ADzgHIAGjmNrFcZxjIc4jlSb8tr/a8uO5P41EHjrNE2HKmfLKFj2vFo5q5V8bVmJPK5kSNJPmI6WtUKU3OxayM++AbhTCYDgec2WfbFl7lRvWrd7KmuZlBpw5mqLkmThX0bfYFheoOQ+Zsu+2LL1tr0cSel5nuVYvVzBMQjzKoD9epmMzUjasgIwUjn4w8qJM7yC78u+2rLMRoltB1mWdfUCr5gAKdLyDWnLDszwQtq9YcsoWUb+HJ/KzgK2jC0jkk3Osn6L8syr1CVC2dQs66ioQ3jmVeoSoWxylkVCDWyyM69SlwhlU7MMbiHEVUJ15lXqEqFscpYBG0fInx8+katxoPODLaOWTdAypF0hvgcftUwcv9vJoaVBsGVUsilahuC7ELP03SdyRWg4DAGwSaBh0GwZlWySlgE/PeFs3m/ZyxCUj3BSDWi2jE42UcuQXAhRuJ+wDOh0Aw2EbBmd7L/twiRxFL3XMs9wGAKksg2NbMSW0cmuh2UvQ9CWatnQyC/YMjrZVK+Y+SevmJn1Qw0Kjb5gy+hkE7WsX979f+Z3zKwJZY9j3CrEbBmVbJKWBbcfXMk4DkCxgiotNZZhmrJlNLIpWvbhVdkAQKYTAI1REwrYjPLQtWXOltHIJmjZ0BGy+fET7ZwwDNXWhurNVB+F513wFZNINjnL3On/Pi3387jNzzFJZVOzjHf+sGW8i7FCXSKUTc0y3pHNlvFfl9Sj1krUz5ZVvNZK1M+WVfwzoypRP1tW8c+/q0T9v9i7t6W0oSgAw2sjCRBQECxHgVIFxQOOWKvF93+vQqhwkRRxwrZZ2f83jjO5kpn1j+SwGKhM+Xd5qnj9VKb8e4lVvH4qU/4d6ypeP5UhQtdghm0qg+XBdILigMpgdzDnNVN686gMNgcTrv7cN6nMeZYHM2oYf0FlrrM9mEnfBHOPytxmfTDdJ2MqYypz2hcMZnhi8tdU5jI7g4l+7PeVyhy2ezC/ArOWE5EjYxIcUZnDdg/myFAZ7FeW4x0TlgfjnXqc/SP9g1nfyUjhljB20VXZ6q5szkvjljB2UVXZqGEuF+ncEsae7J/9B7nkT8tTuiWMDyi5xlxv/qR1Sxj/pqmycIsRsFqZDLsC7FMZQGXQ/kk5KlMpddfzVJZBqbs3SWUZlLrnLFSWQal7ZvzRTgY3OhVK3f4LyzIZRGWIQWVQR1llRwFn/wppq4xrTI2oDLGoDMpQGWJRGZShMsSiMihDZYhFZVBGWWXsZKikrDKoRGWIQWVQR1ll7GSopK0yrjE1ojLEojIoQ2WIRWVQhsoQi8qgzJ4F/LxayNawRWU4eAGjxsvlWN59L13JSseYoD+gMhyigPat35G3y857cv6kMl9Xdly+77OTgeQFeA+1q6aIDP3X8epw5g+kPL1oh5XJ0Hg8x0TSoR4XKws/1Lr1j2Xyuz+ezaV9V7sOK7v2eVqO5ENtSai51JW3xtOp9GqPIqOT52VlvemjfMh8BpVl0B5DrRUKBZGgVgtExgNZGpyLSHnSMcacjbwDV1ZhJyNz9qgsH/4Uwt/SKayVTHhe5rXunw/9Jsg1ZuZ8rrKNXm0WViZSNR6V4WCVtRuyMn9pS6+Yk7//y26m/C/DASrz/UCkcFt6lpXm8vLyLCdhZcbk73pUhuQFXIjkRAqy8VD41pUtKsOhCpjKVqs/pzLYLqB7SmVI1612KnMdlSEqxQUc6m+wk5E5yiqDSlSGCJUFUJnrlFXGToZK2irjGlMjKkNUigugMvzXynIbspTgyFCZRl9T2ZYsJTqaCdT5msqONmQpydG8J1BH2XkZVKIyRKgsgMpcR2WIUFkAlbmOyhChsgAqcx2VIUJlAVTmOiqDfXlTFsvKJi9wWsVUxbKqqQicVjfFalksKleLpi5wmvfDWHfDZyhd59UreWNRvlInMgDAn/bgkAAAAABA0P/XZj8AAAAAAAAAAAAAAABcU0a/LI+gWFgAAAAASUVORK5CYII=",Z="/ran/assets/%E8%A7%A3%E9%87%8A%E5%99%A8.DymUKGTa.jpg",f="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfoAAACYCAMAAAA7gNueAAAAvVBMVEX///8yMjL8/PzS0tJBQUH6+vr19fVRUVFYWFhHR0fOzs5OTk5VVVVlZWXu7u6vr68+Pj48PDzZ2dk3NzdeXl59fX1ERETy8vL+/v7p6elubm709PTJyclxcXFhYWHk5OSnp6eDg4NKSkq6urrW1tZqamrFxcWysrI2Njbg4OCJiYl2dnbw8PC3t7erq6uXl5eNjY339/dSUlLm5ubBwcHd3d1ZWVnr6+uioqKcnJyRkZGUlJQ5OTnQ0NC8vLxkx+d3AAAISElEQVR42uydiXKiQBRF72tpEUEFFdz3fYlLxqyz/P9nDRBl9pCZiTPd8Z0qJYU23PSp1qYfVYJhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhmMtElAoGnRGjUBJgFEQ06ex02L2KlMjJt3BGWnmHSmDUo0B5nJk8FcCoh0EtnJkaGWDUgwjfo+U5GCW1sHolYfUXC6u/WFj9xZKmRQpEfERM3e+hNhG9LKvXnzQtDx2JzQMqAhFtSyJL8sHpAWKey1UQ5HK5D6xex7XyNC315iMmhkWWZU2B5j0gqIb7awExBCxYAIap53iz3afzWnmqlqzodSHmiCjTGoDXw7qd/61R/2a7T+e18hdoebyHrCCiQHf9R79iecPuAKIA+CV/2lmsUs/xZrtP57XyFC0bg7Bfo2bE/Z+j9XZzqG4EQsyID6bpuWYh7Rxvtvt0XitP1UKwLCuohE/V7piyAJZbPFHcmPnupoU0iN5s96lygUN0FvUhW7sM4A6x+tkEIePVdbBsYN/v5ia+TDnHm+0+nbO/SH3p+pAbrIEn9Y1K9LwffQhneJjkcuY8A1avX/bUiztCuTApQj5Y46N6dPvhowjrdHFngdVrmD2lTbFp7spTRNyIk/pp0Gh8EKxe8+wpba4G4uHaMILAMLyhPKrHcthpAvNcbg4rFz6zeh2zp7QRAhF1EQKgKREzGyyAHtCLntBj9TpmVzWXnjG1yq5qLj1japVd1Vx6xtQqu6q59IypVXZVc+kZU6vsqubSM6ZW2VXNpWdMrbLTP4DVf48S56Cfwep1OC5/4KsUU6vsqubSM6ZW2VXNpWdMrbKrmkvPmFplVzWXnjG1yq5qLj1jqp69vVcz17fU8op2nzLH/f1zlCvXZRVzfUt9RVuhfkzN1JtU6dfVy/Ut4j1R952C3Xe248p/cI7sgKhTVL5P2xa5o988xF5D9cJfIGTTRERjKb972X3V7FceWW3V1aPYJBpkX3SIRg8ubu6yFYmIA75CXtXRr6mrHvdWD8DeXsRpq82pF0NH9dG27IvXyt6rEm2F4upR71fouvySQ2wKcOvdfNtBjAvTNiMMAP4KuL9SWD1204cgCIwgBLgrrBFDAOwQsu3JsPR62WX0VdpTXH0yL0n/0Jy8czMD7AaJ+iIiDIjlPLpdPBdRVFR9BGUT4Ue+jPqMeXi1Lk6+SlVXn8xLUg5hmiaZ5tSwhoZXMg0yzGsnwsg2C5VqtRo9qn01R/3ANb5V70YAhLYdQfbcDTevlj35KlVcPTCK5iWph1gUKtvsPTXwsEtG/QDwxWPWAmApPM2LdQuyIrIgwED8IMS0C7vWWWrv1/9E/V/z/vmY8rG7cD9Vd4UpVrNEvYEY1Ud9LHlPAsBcfqc+O7slwzRNh9X/gvpILEeoob8UQQ9yXKl+eJof2XlAi1H/LvIt5/hGfcYPSJ7ewR/4P8e0yTTNYsPoVyHtlbewRDLq57kTDVXVFweHbmQkFg5yXTfaYDpZEGJImWlewxb4FZ+q7+zyv57mrYcLjB0Bnw4IcesGHIccpwPgI4ChyqM+S/bG3wK4sWPJ1a90Uy6GoMHFXdEoY+aIf3xx11tVS2YeokOjWP27HIwojImO4zg2keeEKKq+PRyXvUarJTaFHy7uKPlb/SWd901ADK/+8ZIO5NIL+tLvHrxNpP7KP6kHxOh2NtwO3ik76lGTZh9XRMYhkdwSN17c1oyhV13Izf+0TYayyV/T60qzGG5nxhJyaXirGiY+gMkyepd8P5wPH8RTiwxJ9IPKErBnAHadf7uQW/OHy+LNfaGZxdQt3b0LmiWQ4zjXphhvc7s1hhhPmiV1l3QyAIREiIsYe+49IGSKmOlrlW/8+PszVf2q2Lj1w63fqsHvNoqh95ErcUc30bt8pyw/DreJ+h61sxkU6QbAVfAa5Zvg5eWbwx4h+TqAhrx1t4/r46jP+qUWgC6A8q6srPr/X7StUMTtUf0CGHnhtgwUo6epB+ke0O9Guov0EcAsSNQ3aAZgTOvIAcm/Lto+/k3Rtq6SIoXUJ7dqpIz6bORQZKgVGY2RGPiozqLXxlRD/PpJPa4sJ4/Tbsm3aqiYvb3Hi9Q3gJL1tKdB7457vbK7j/bdUQbAbIgyFYFp5FruAjRoAWBk8A1a6md/Rr3fWtjvj3sKnYYotwE4heXTu1a5ssgM+9h799hPSL7Ly75bh3UF4HHCt2Wqn/2XbTK0CbyBPKovrrzKbaT+nspP6vfLYG5uABxsu3tPsmfOzcPT5L5uz1i9+tmfUZ/FH3Dn3mBkSlavfvbXVo9RtWGP+T58DbI/p16h/13V7tM5u6q59IypVXZVc+kZU6vsqubSM6ZW2VPaPF+WZ/U6Z//tNgtTfinLs3qNs/92mwzJL2V5Vq9x9mcWctu3FWeMU6l+Y6yR93qgkKQsz+o1zv5cvf5u3bzFqVRf7+7Ebf9p1CdleVavcfbn6/VTEqdSPW68x0L9qD4py7N6fbM/W6+PPCeleviUR6K+xuqhefZU9UmpvmesJkf1SVmeP/A1zp6q/lSqF91tKygBC2qvcSrLs3qNs/+qTaL+VKp/sCVmXgMYVIKkLM/qNc5OhL8oy7N6jbMT4c/L8ryQq3N2VXPpGVOrX+HWpE9V7T6df3tfE/Wqdt9LKJGTr+GM1PIOld6selW77yWIJp2dTv3Nqle1+16EKBUMOiNGoSQUmtt8DdGb7T6d0UU9o6UWVq8krP5iYfUXC6u/WFj9xcLqLxadF8eZi10cZy52cZy53MVxhhfHmc/twSEBAAAAgKD/rz1hBAAAAAAAAAAAAAAAAAAAAGAUHN+OiDiImkUAAAAASUVORK5CYII=",o="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAhoAAAGzCAMAAABenE6vAAAAn1BMVEX///8yMjKYmJhOTk43NzdRUVFISEj4+Pg7Ozv9/f3R0dFYWFg0NDT19fVVVVXHx8c9PT0/Pz9+fn5lZWXAwMBdXV36+vppaWng4OBiYmKNjY3k5ORtbW3o6Ojs7Oytra3Y2NjJycmmpqZDQ0NwcHC4uLjy8vJLS0uWlpbOzs7b29t2dnbMzMzExMSxsbGHh4efn5+6urrT09ORkZHu7u7oe41mAAANOklEQVR42uzOsRGDAADDwDBDLvuvmoKWmkPmfwBbHwAAAAAAAAAAAAAAAAAAAAAAAAAAIOt33OD7lsyR7NNxi7dkjmSfLoaf+BHJHMlOxUcyR7JT8ZHMkexUfCRzJDsVH8kcyU7FRzJHslPxkcyR7FR8JHMkOxUfyRzJTsVHMkeyU/GRzJHsVHwkcyQ7FR/JHMlOxUcyR7JT8ZHMPzt32psoFIZh+Hll88BhkSqKuOLSVp0uM/3/v23KsdRJJkEmDvE9hKdJ+6HJ4Qq5g00b2xK2VnhNmC1ha4XXhNkStlZ4TZgtYWuF14TZErZWeE2YLWFrhdeE2RK2VnhNmC1ha4XXhNkStlZ4VsxQ3v09Il0aPJm9+799qEuDJ7NHPR3ZbA7u0uDGZnNwlwY39n8/2HFXjuPg74mIUxoVTM5p8Li7/3zw1AzMIH2c7ezABPrfG3zhCcAhFgCGlFdfgwHTJZKjCZ80at/d5M0zTWvFKg0Y6gOwYUBtQaL81ufIMMb2EgCOhld9DQZMl/z9ccQnjZpsOGl6cvxwwjGNrfONnxMuEwTXGgLA3gzlqvIaDJgu+ViT4JbGNTamnsPvBQUDz4SB4ILPTKiFxrlrc/D5Bcg9jKeV12DALNJ4txk9Neqxk/6Q4c8aX11bCm+qkfp8xoYPUx9qoxwvm+SW/00jw8aZLvmLNGeURj32gRYc0yi6LvFqOZUJ+y8eDSzLCgq9XMCvipuuL22c6RKRtWP0glKPvaIPjmmorl+lKPHCmo5R7Ge8oQTFJIApRVEktzfge9RrnOmSL7Ljlk8a9dh7OjFNYx28RbDxiGK/ApG+A0A4mxBKvNjkWZbtzI87plHNLNMATiQ4pVGDjfGMYRq7fiBjJxxhYG8BiKf+ChN7DTXy1CQwNPdQgdyURuNM9dTYpmyeGjXZmGyOB7EfHlilsVzODYg0h42C+BCdALibJx8ALl0fz1m/ejel0TjTJaJBvGCTRk02MI9tGaXMfq8BGE48Sgp8EsuHDMWycfQMgCw1ictuSkMH5h9cne5uM2nM5sc9MAawHqLccwLgB9RCFmlcZ7JM4zqbcRrXxyKN7i+vAPQ5uEuDG/s3O/VuAiAAhDEYZxD3X9VCCzsfhXwH+QcI4QjHgEtD02bApaFpM+DS0LQZcGlo2gy4NDRtBlwamjYDLg1NmwGXhqbNgEtD02bApaFpM+DS0LQZcGlo2gy4NDRtBlwamjYDLg1NmwGXhqbNgEtD02bApaFpM+DS0LQZcGlo2gy4NDRtBlwamjYDLg1NmwGXhqbNgEtD034N/mFP0pigedGddN2vW5cftt3feoLmRXfSdUfvvPWMP3votp1dOqYBAAaCGMafdQl0P33kQIj87cRrNBKhITS0f41GIjSEhvav0UiEhtDQ/jUaidAQGtq/RiMRGkJD+9doJEJDaGj/Go1EaAgN7V+jkQgNoaH9azQSoSE0tH+NRiI0hIb2r9FIhIbQ0P41GonQEBrav0YjERpCQ/vXaCRCQ2ho/xqNRGgIDe1fo5EIDaGh/Ws0EqEhNLR/jUYiNISG9q/RSISG0HjslMFKwwAQBVMIRqWkgggqIl7Ek///ex6EEhFMVMjOW2YuvZSXYTNE6m9tGi0wDTENqb+1abTANMQ0pP7WptEC0xDTkPpbm0YLTENMQ+pvbRotMA0xDam/tWm0wDTENKT+1qbRAtMQ05D6W5tGC0xDTEPqb20a/+XusAO367dO0FzoJl33rxx2Yf3WCZoL3aTrAr+7Z7akkaC50E26Lm7YNGjamGHToGljhk2Dpo0ZNg2aNmbYNGjamGHToGljhk2Dpo0ZNg2aNmbYNGjamGHToGljhk2Dpo0ZNg2aNmbYNGjamGHToGljhn+XxhoITdPY/xmno2nw3mCI/C6amzEN0DNYaRxPKO3P35zhxDQSJk0jU7OJdpR8iGYT7Sj5EM0m2lHyIZpNtKPkQzSbaEfJh2g20Y6SD9Fsoh0lH6LZRHvb8HT9Mk3T8J2rG1oaz1/+c/++dMWm8cN9uWk8jvM4P7w9vV7M4zBcnvlg5+x20waCKDxb/+FgDDYBGwghQCD/oWny/s/W9WITU1XFtGp8ZjUnkuNcePLp6NOAfLFJiV48+JiGF0qpJHtDU+N6PcjJpMYKpcYZ/aoYSw1yzA+RT07VfVWuo6McJ/MXdKF64cfGS0MoNYLJbuVtf2EF2xqN+4XbGiX6bXBAnysyqay+8C6pRN/erVpVQw10ikvHsPaGw4DS7vURK9oHSqN+MdVIuq6Gjj/RZy6Z9J291W6if5Xoq7hdNXrl1rgpWB+9LCAKU//lmBVLjWb9Qqqxt9oz6K6JMtfLPf9waphL9Oco/L9n0zRX42PnTl+JKHxduNljxdrSETpE/9Qv9NbYo5usVLWUe69dlXieFx/Q+y6hqJHHyyAiokDR7Cn/ZEVTo2m/OlMwNYzVuyis0ENvmpmbH+lajc1ddFDj2wjnu0ZI245R45gV8rvGiX5Bt4YGX8bfB+TTnfn7PQ4nb2ZDXOWKjtHn602raoyCcmvkT6Qz840aFSusGn/oF1mNTSeO0qA/osS/LZy+79xQ7i/Lx7ome/TwenM3hXqv0Z8YNY5Y0dRo0i+oGovF3KFwsiKfdPLh4Jk06PrekNatViq5esF65ZW+19QA3RrN+9XZQqmh4wTpaFygj9NoOKMis2zwUDzmmUSYL8oX63lNjZIVTY1G/WK+KNe5mj9pXTMiWl5SlYexvpRboo+kRm9X3jz7N1SpUWPFU+N0v7Bq4PyP80b0UKpg0i5reCaYlmCzgmeCaQk2K3gmmJZgs4JngmkJNit4JpiWYLOCZ4JpCTYreCaYlmCzgmeCaQk2K3g5X0PUYKGGmkBhkwmfwXKWF0q7cIPlBECUduEGy7mhaNgwg0UNNGyYwaIGGjbMYFEDDRtmsKiBhg0zWNRAw4YZLGqgYcMMFjXQsGEGixpo2DCDRQ00bJjBogYaNsxgUQMNG2awqIGGDTNY1EDDPjfqC9JEDQ6YNVxO7f5thuoLMjrdNQfMGi6ndlmn7JrHnt3jSn4bFl2LGlZE1JCIGpL2uxY1rIioIRE1JO13LWpYEVFDImpI2u9a1LAiooZE1JC037WoYUVEDYmo8ZO9O7ZtIICBIAjXYLj/Vp0qUyBA3D/MVkCQk1P3u0ZjIjSEhu53jcZEaAgN3e8ajYnQEBq63zUaE6EhNHS/azQmQkNo6H7XaEyEhtDQ/a7RmAgNoaH7XaMxERpCQ/e7RmMiNISG7neNxkRoCA3d7xqNidAQGrrfNRoToSE0dL9rNCZCQ2g8qL+fL/T7ftdPGPNl3Cdt13foj/MdOvj13E/54gUTw6NRvGBieDSKF0wMj0bxgonh0SheMDE8GsULJoZHo3jBxPBoFC+YGB6N4gUTw6NRvGBieDSKF0wMj0bxgonh0SheMDE8GsULJoZHo3jBxPD/7NtpT+pAGMXxM+kOpRQoZd8R8F4X7vL9P9tth4u+MIFJiOl5JnNM9IWJ/sL8HU0TXRqMJ0iBd2kwniAF3qXBeIIUeJcG4wlS4F0ajCdIgXdpMJ4gBd6lwXiCFHiXBuMJUuBdGownSIF3aTCeIAVeXBqN/2eZS4OLeV0RuzRcGnxfkimNqLWOoghfl+Q8adxAUqdxw02dxtTP/GxynD+FmQ/EH+v91ysAP/pJS1XLGknDHAkkb5M83c0TkjSMX9wOgJaKuNKAp9+AEB70liq5fqqa8rxRuMJF30ga5kgk+/ZrJ1pPS5I0DN3caeyjD/1CQe8adisowJHGPSROWYfrF4qRmzaNXtuHh+xTP/Oh1/UuYfu96kODaZgjy7wg+1vDzM2axiXsQOt9PaXfF6jXHUx1EwZp3JtBGg8ix2pJloaJm/3WuOj1tqrAZZ23tuoFQZDV7mrTh9KICwPmQ8i1+guclVIRSxqmL64eXRo67Pc0ueqTYDpCvd/9nSpRLzW6Nb6LaY48pC/6h5AnDRM3761R2TfZOUeII+r9yZLJL1TrzscKPGkYILGf86Vxw02exlOcpf2oO0Qv3ANITvEa43ADPdXWazwNQyQW4X5dHrY0aZi4edNYrRYekskWIaqNB/lLrdyddAkst4YhEli+H9N4eGZ55HXTTX9rVPOi/rCs9WU/HcxQbzbKnwGoQC+FXiNpmCM5H5Tfd9M+KK82X/w8ACMAmwLXPZcAXqHXJUjjPpIzjftu5jRYvocQpiVsUXghTEvYovBCmJawReGFMC1hi8ILYVrCFoUXwrSELQovhGkJWxReCNMStii8EKYlbFF4IUxL2KLwQpiWsEXhhTAtYYvCC2FawhaFF8K0hC0KL4RpCVsUXgjTErYovBCmJWxReCFMS9ii8EKYlrBF4YUwLWGLwgthWsIWhRfCtIQtCv+v3TmmAQAEYAAWNBD8W+XAA2GjVdCQZkk7Kh/SLGlH5UOaJe2ofEizpB2VD2mWtI9xxS/NkvYxxwXrl2ZJGwAAAAAAAAAAAAAAAAAAAAAAAAAAgEdsIf68N/uisesAAAAASUVORK5CYII=",c="/ran/assets/%E5%A4%87%E5%BF%98%E5%BD%95.meL0YZxn.jpg",h="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAkgAAAE0CAMAAADgyDy6AAABHVBMVEUAAAAxMTEyMjIQEBAyMjIyMjIyMjIyMjIyMjIyMjIyMjIxMTEyMjIyMjIwMDAAAAAxMTExMTEyMjIyMjIyMjIyMjIxMTExMTExMTH///8yMjLS0tJRUVH5+fn19fXz8/M3Nzf8/PzNzc3n5+eIiIjJycmYmJg8PDzg4OA0NDSOjo55eXnX19ft7e3v7+/c3Nza2tqzs7OmpqaLi4tISEjFxcWBgYFERERZWVlUVFTj4+OFhYVoaGhOTk5WVlZAQEA+Pj6VlZW7u7tycnJkZGRhYWHp6emwsLBLS0t7e3tsbGxBQUGfn591dXVcXFz+/v6qqqp+fn7l5eXBwcGjo6OSkpK3t7dwcHD7+/s7Ozv4+Pibm5vU1NTPz899fX2psSS+AAAAGXRSTlMAaJgC68FjPdbjMCGzsg4ByI+EevjxnFcqZlaxPAAADetJREFUeNrswYEAAAAAgKD9qRepAgAAAAAAAAAAAAAAAAAAmH16OQEYBmIgKvDnlBRgXQwuJP2XlQTjHnZhXgmDBAAAAAA5ld6qU6mtF31IsVPEUC4ndBeJFDtFkCV1P2uOVOZ63CVSnBQhNK+RznKTSHFShFCd7IS/6SqR4qQIwR4J2RIpTooQqEcK6r3s1llz0mAYxXGXC7cL1wvP8Qkm0oQEKFjapuwkIJbIVpaAivX7fwwDQTNoL5zqDGmmv8lMJpf5z5nkvU1xO6QY1rtNcVsvVik0RA4L+N1NSLHXIenHp/hlXGsWtQACabeEwKdazOv9nxRvnAoiFAQUwKgoAJaVP/NgthqDAq2Wj02KfQ5JaXBihApQPIY0AIcZtbppmsQhrWzb9oUbmDACvA1SsL/uIXnYVAAIEdjNgwmXKYrSYTY2KfY5JJe/mN+aNIrFmWO5ioKyfMmIALTOzpaJG1KZZFnoeV6GmPDANYtz3TSHKpDm1vLk/YHQnvt+i77vYycPMD7ufqUUGm58UuxxSLqlGqVQFSVG8CW8gZbjfErckA51xRoKv57UhUjp6tDMq+67d++m0I3wi+Q2rZqhklaZod08YCQXlxT7HBINbrUB5qbTkVWcTnNE9UhLH8yS+mvzMqdcCd9yJEShQXL0nf0WDfhkBDYVj5D1tZsHwdy6JDM5w2j/jxRP7vyNeNS7igtEGEGW+RlrSR1S1TrjpfAj60Kt3MouVNe0sp9aVQQ03VP7F2MEbB4OoyFFAN2v8ANbFTZX6X9O8eTls79LE496V7nklmAdp0FrYeazmQHavBhwwY3kDQk19jThN9aEGJQ6lPemR0sH3g86DkOiZRvkiG5/fe3mwYqtgba60BbCf/wivX75kORNH1LaCFGAIcV3eXbcZ7mNKe0cP1IVUZM4pDa7EF4wJ8TXXqbHwIjDIhYkSxuUMclcnaHdPCicp5BiF9DOP18/xdPHL9YrcrwbP6SfKGOY59kT22ZGeArAKVcEFEASOKTPFVLvlLukXYevNvNmoNihWk3NezzaoOCNF52RdvO8YeTkminuP3j+iGTLPlWQmCFlejPfVSdHdXF6aaeVB9rn1qid1CEdc2mNMKdFHOilObcujwAItwQ7h+2dPOls4IulOsFtda0U4Yr6Nf0zAozcDV7q3hVPrx7fuROPej/YN9OmtKEoDHf50N12Ol3mPRBIoMi+h7KmyiJQioCKglv//88oSYx4W6plipKE8874gXMvZ+555zG5G7epLG/XDnMtih/unOIoGm4UaaYDl77alG75rH7+ldQDqkSbmf6gP9RIaTb7gakOUsCQDlJ8BpI1RxLsARBoUTVHrQvgYUCiJ48e2cK9W5UnitWoFqOonAUapbZK3ng/49bJdqgCtEiL9IloFFM7PaJdtMdlryQ8kbwUVaztbAj2JPeLFI0pGEdJO36QV9sTnSl7uHebkq3ubJaA1HY/iJmGSPitQ6fSqftA0lU59kHKjhuKT8LlqJPGTHrR4+O0oeMxYq3Zn4aZel4I9qD6rX6ImSIHP0L/PdkOf3cNSLfIjftIq9QQK1j+M0gMEsAbkneJQfon8RHJXWKQruQMK9g9tuIfxe4xSHdZwZNtBsnRIDlTq6n+2dYGWsEgrRyklx+ev9w8K/jVNteqQHpOHx6/3TQrGKTVz5G2PhG92dowKxik+5hsf/5IL565yopXDNJaVm2v3hG9f+oWK2ZHJHzWtqbl/9P3RO9eucEKPrRd8z7Ssxf08bPDrbDubPM1knVuSG69Jvq05VwrXHln+0FE96DnTrVCvGq78JLtn2KQGCQGiV9tpvjVZhvxZJvvbNsOJPcv/2fkMEi8IbnshiSDxEckqzkiYZD40HYlVjBIfI2EQbpLNgVpdrFtA6xgkP6q1V213QQrbAZSUFPwNzV7AHzyOYBc8bqjh3wwlayqspr3m6Hl1BgEtYxNLv8vMXrBkeHdycR6XQ3SXBGvBFGj8BRoRFu6g3Gry9yqthqPSOlJybc8SKkfCWTLiuNAEh0RJLqzuN7NAMlDEkQFKQBUW7IPw52s1WVuVbw2BKCU6suDVO8BSvfEcSCJjggS3Vlc78pBuncRLbDKQ50feUhfdk7jfiDVlLvnJOlNuaKcB2gmWM1m3/I20D0KF5Cg9qyj2cVDhZJc9uBMDkHXSNNDZbmXgplJzNE7AFDLi0EtCyA2eWiQRGqkeldWz5VlRi84ch0MleRuAaI7C+t1/C9tLZDifj9+7gVTta9Ar9Vu7xkgVSjku7CeSGbzVd/YHtLyWTOGcVnPYf3PTdqp3jekKQldoajiof1kuxSHmUnMcbIrIRlNC8EkpQGcFNcL0kE5M/WodSwxesGR62DjQsprEN1ZWK/DQZJJ1wAeSgBJygCFMJJ0ARQMkILUsZ7MVrPe12DEN65h9A2T2E2QIvo3lQSloCsQNUMnYZiZxBzS7hFye2LQ/GqApg8HkmiFrhRdAugUlxi94Mg8iLPENk1FdxbX62yQ5k8kv16TISlBfoMdvelELQeMD/Nmoy+k06PaGBVqhws3QfIZnf3Rq1db2QwFSDEziTlQ/Y5BVgwmjJYASet7IlmDuCRlidELjlwHj4vNOEmiO4vrdfrPkSyQfECQgtBVoTTQMEGClC+aIFnNlt+TqpwBtLws/QkSehMYk+0+PNQGOirMTGIOXIQzu2disE0RAI0drBOkNnkAZNUlRi84IlhZ+B2khfU6ftV2AyS0mkElEwLKk1RlYIB0eDkd7Q4RoVDKarZsHO2oAKrhGvSI0WUOUuXH18o00xvoFv70R7RtXGUSc6Dc+gKIQdWYfPbWChL2SxnF080tMXrRESsYoUKqR5LozsJ6HQ/STQ+T+2G5FALSA3nQMZ7rFa/sPdLdkYtWs2XjIR0AOKIx9IjRZW4VKt+LslY3Po2K4S9TXGUSc2BMGQhBcwEz1DrrXf6f5YtR72iZ0QuOzIN5WcuRJLqzsF6XgPSnsirWo+RuGideyR77SPcpsV5XgtSoKJ7uNtakxl5bS9jkiOQeJdbrziOSvip36wrsJBeD5P5DWzuJQWKQGCQGyT5ikBgkBulf5PjTf4eIQbL7WZtDxCAxSPZ1j61g99gKu53+O0QMEq/afrF3dz1NBFEcxhv64o0N1+dvcdumIlAB1yAqJMQLwIbwEjVIAPn+X0O6LLYktE2TXXJm+vwuIL1/0p3pTM4SEiH5QUiEREiE5EcpIdWUWHAS1QjJWUh1dS04XdUJyVlIDR10A/tOSroHahCSs5CqrxWg5jIhOQupUm3UawpKrd6oVgjJW0ix4vSfkMJBSCAk+EFIC4fFNiE9h10bIU1CSBMQ0nwIaQJCmg8hTUBI8yGkCQhpPiGGFO0lHMwOiUs4qlfgK6RoL+FgdkhcwmkuV+Dr9D/aSzgAAGBBDJdMgNNdG+JHSCAk+EFIICT4QUggJPhBSCAk+EE5AAAALJmQY9cGlwgJhAQ/CAmEBD8ICYQEPwgJhAQ/KAcAAIAlE3Ls2uASIc2y8MPr/k+wIyRHwhynmWlWCcmPAAf8jqb8EpIfQY4cf5w7Tkh+BPkShEyiGiH5EeZrWTISIflBSCAkfsr2I9qQMBUhEZJPhARC4vTfj2hDYtc2FSERkk/lhNRZsWcQUsTKCem3di1z23t0a2aEFK/iQ/p571xfh//MWnrUIqSoFR+SRoYh2QNCilwJIbUs1feLh4ha6j0gpMgVH9L5WbIj3Vnn9AOPtsUhWdE6V9q/7t9cKc0fbSfasxJIS8pllTz9JEKaJoCQOn1ppadvOtrOH20tnd3//fyyIS3VXlUwkf+Qfh1KsuP3Wr2w8UebVi3DWVucCg9pQ4cDmaUa3Fn+aNvTidmaGSFFrPCQkt2bgdZuNy6l/towpK0f1monm+2UkGImWdGO1yX17VO7vW1ftNse2Kl6qS4tw+l/nEoIaWv9+izdNPuY2l9J1/v2dkfSG0KKmWSFe3djuc7R4Z/hh+3z9oaZEVK8JCvTio0hpIhFex+JkKYiJELyiZBASITkByGBkAjJj0UJCU8REiH5FO2gLczA6L+x0X9wI9phpCy2Z2M8cqa5TEiOxDqwnZAwwktt4AwhgZDgByGBkPCvvTtYbSIAAjC86M2LFy8zbJRIkdpSxVYNVgWxhLYSpeCt6Pu/hkkkjbHiKUsnu993Su4/ySQsM3UICSEBAEBlhm2ERB1CQkjUISSERB1CQkjUISSEBAAAlRm2ERJ1CAkhUYeQEBJ1CAkhUYeQEBIAAFRm2P6bhe0Wtle0yyck7gupDkdtcGZLSHUM5fCfkP7FKVLHkasREkISUh1CQkgNZQgJITWUISSEZNiuIzM6d/04loTUYx2EdPUmjqfX8WP2JCJOn47jdcaSkHqsg5C+fjqd5bPRuzyLiIO8EtIQbD+kg8s83MsPXzLfzmI0yVMhDcH2Q8q1Nl7ljZmQ+qyDkNr1q+uLvGjb59nOnQupz7Yf0sksf9s/mX3O6Ti6+2q7lyuLSv7/TkgbdiCkiJO5jzk5ihh9O25Xn0gRdxrSowcNazsRUsT4LA9fxNzoPFdixT/bfZQZ2/U9/xALJX61sal+SC/35t7nZG9BSIORGVs3jv2cxlLb3sxIUyH1WSfDdmYexlKuTYTUZ12E9PPy8uAobhNSjw3lMRI2CUlINQkJITWUISSE1FCGkBBSQxlCwqKthjKGsvqPWywjXS8jpYxdXo/8sKGOgSxsBwAAAAAAAAAAAAAAAOjIL80euGfYQpNTAAAAAElFTkSuQmCC",U="/ran/assets/%E7%8A%B6%E6%80%81.Bt_a2OKX.png",I="/ran/assets/%E7%AD%96%E7%95%A5.BAijEgGz.png",e="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYkAAAFeCAMAAABHOBMYAAABBVBMVEUAAAAyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIxMTEyMjIyMjL///8yMjLS0tL5+fnv7+/8/Pz09PRQUFA8PDxAQECNjY1ISEiKiorm5ubNzc1NTU3y8vLo6OhEREQ2Njbu7u7+/v7X19e4uLiFhYU+Pj5VVVXp6emzs7M0NDTd3d2wsLD7+/vf39+bm5tgYGA4ODjZ2dlsbGxZWVl2dnaSkpJkZGRLS0vJycmnp6doaGi6urrPz8/ExMSfn5+AgIB6enpwcHBTU1O1tbWrq6uVlZV9fX2jo6NFRUWYmJjr6+vIyMjY2NhdXV3j4+PBwcG8vLyWlpaPj49zc3P29vbh4eHMzMxC5nCpAAAADHRSTlMA62OEwcA3I9zNs7IAkUR/AAANm0lEQVR42uzX3VLaUBSGYey0J+33kYQQCKAECkQCCrUSVIr4hyIWR1Hr/V9KQ8CGDrUzPens4HpO9oKsnPBOMkNCCCGEEEIIIYQQQgghhBBCCCGEWHfv3m9wrW28f5eIg498Az4l1PeObj6FtZbKu4zBU/Geeay9PD8klLfBNX8iZja5kVAeiTeATChPSqhCSqhCSqhCSqhCvRK0gZEFWAMAXgeAlss37Tpw1yqDJozqRErM3XfTTraOVaQ+PxewrIwV+wVt5V7QPuZCalbCTodzFzjhWYqm9sgHKRF6YPoq02v9pYTv26Tv+4hcXetYcTFcubc/5u2oX2W/z5P+0GTaPGXRPfOPNaBstzWaunkpb6fQHbM5ADuvlQjp5CuXIuU/LQxIdnNzmy0GTok5RjpSItBjHaHykelkp8bSQOrbNVaiEqQ+Hznz2+bIGoeXbx4t53YSpbqnDc7Z2GUHpwxlMB6P2yTTp+PxNykRqDGH0IhZ22RmaSD1r7NztYRP2v7yZjDch5f7rt2jG5Xo8HqPTi1AG1O6u6e86l116ePQP2eXlku3tSUlAg63ECrwOxpMG9FADtg1VkssJixv3i2+1LS9Cpl6KbHl8EuBJ3qAtlYknVuOXNg8RIvWwGgNjYpJeSZmTN4j5HEbBpmKBjLLC7xeYnnzZvFlpZbuBudLiXGR1WfO2SOP3Wa7dsSLmlmG3kwhxTZgNHekRGDKcx2AhgM+o0GrHA3kN1pbSyUc/kBjUWIbWN7UFyUsNkpLJY582puTySTdnkwaR6dex0i7KctjBUlGslIi8LTPYjXTHWMQvvRbiAZSt9k2ohJt9oa34ZhltxptLpWo8bG9VCJZoj3gwiTnde5oa71Z31wmkPacWnC0pMRM6tJ0vpzfozw48A4GBqKB1J9MPkQl9va9wjAcjwteNtpcKlG3rGZUIkAb277XNs/rOuA97nPk0mI6UwbyXVZH7Cbl/8R/QXtMp5oqnbGwA+/r7eOQV09Tb1rqXNN7MDDyWPClxH8wOrw5ukHgcx9oPpdKRn/2QUPVneYQ2D2xDqWEGsrydoorKaEKKaEKKaEKKaEKKaGKeJR4GxLK4xuRUJ68nVQhJVQhJVQhJVQhJVQhJVQhJVQhJVQhJVQhJVQhJVQhJVQhJVQhJVQhJVQhJVQhJVQhJVTxbyWSTCF0f5sr7CE21reEbk1Qdw3ExfqWuPwKGAcVxEV8SxiDgpP9DO3ywMm2DLwMYQn/+gcKdQCZM8RFfEtkCv2dRg4n7t5OMjvFyzArcWQ1UGIDQKWIuIhtiU3vGQGdfQDNYjQkWa8lgc/cBJDnDmIiZiUMkj0A4S8dHX0av4Yki1VEJTTERMxKRLaYROAmPOrZaEjyOT0EtrkL4JuFuPjJzpntpg2EYfQF/rFjY7YEMGtpWMRikkISBIEUKDSgFuj7P0pH1kArBTnceb7RfyTL47mcI7DlozGsCXoNes7PLQ3kyfo2ovPAEu7YnxOl5UG/+4QCrgm3WugGDTpkVveJN6LzQJqgr/4ufGwq3TUJBVwTn7GuNaiSgLlNGGyCnjv1RJlgMNgEGGxCF9iELrAJXTDThPOSaqE1CnQTx4vPqauVsNEaBboJS1wyUZbTaI0C18Ro1c0QCQmRnUl605zUMp51+zdnQVCNAtbEVgxd67Tki07+5mkiLwbFejA9mcBqFLAm8qJ5/ncqih7R2JMXbaKKp6bBGgWYiX99gubpL7dqycsixA4T9q1wwmm0RgFm4n/sVEEteV5k1e27TtRMq98EWKOANZF9aY1qJWqLYY7ocZ93ekOyxMJt330/mcBqFLAmtgk/sZPnardAVBx4frAhS7wVvKp0IEIIqlHAmriEJVzcRmG2CaRGYbgJIIwyAQ2b0AU2oQtmmjgOkt2nLfcJRYx9YjnKFfsd7hOKGPuEI4+NcLhPKGLsE5J5gfuEIsY+IWkFv7hPKGLsE5LJu819QhFnn6BUosh9QhFrn3iYrblPKGLtEz9mReI+odCgT9jcJ0J0eBfLfUIXE9wntDEBhFEmoGETusAmdMFME6nCfWBh5Ql4E5f7xHMuN1mVoPIEvAnVJz7yx8fKE8AmIvtEKbvPYOUJXBORfWIjxKuNlSdwTUT3CafxPsXKE2gmru4TNPYdqDyBZuLaPiFNdLHyBK6JqD7RqNjZzgQrT+CaiOoT2cBPVg9Y2ydwTVzCEi5snjDbBFKeMNwEEkaZgIZN6AKb0AVjTTwKFytQoJtQfeIDlZVwef+EIs4+cUgvhcvfd1LE2SceFpZwsQIFrInIPnFMrqUJrEABayKyT/SXJE1gBQowE9f1id2sRXLM+ycU8fWJvVereaI2hgoUsCYi+oSy4mIFClgTUX1CmcAKFLAmeP/E52hkAilQGG4CCKNMQMMmdIFN6AKb0AU2oQtsQhfYhC6wCV34y96dtSURhmEcR23vvhmGYdg3FVATARfQ3FBc0dyt7/9RwnEUzIo6qHlefH4HMZed8b94Se4ctYQUWkIKLSGFlpDChBJjJn+w96eyHAuJ94ppjLw0X4fEG2clncVIy6YrHA/J94EvwMeQCcZfj3Gkjb024RURhDdvQkqEiYmQEmHsXUhJ8IbU40mECVKPJxHekXo8SfCGrqvHkwQTLJX0eJLgHU9P9XgS4C3datXl25AK2ATbQFuPp+C95xawxfchFay3LFuAFdPjKWgTPETPjh5PQXvPe3o8BewtH+jxJIAJ/9HiZdASUmgJKbSEFFpCCi0hhZaQQktIoSWk0BJSaAkptIQUWkIKLSGFlpBCS0ihJaTQElJoCSm0hBRaQgotIYWWkEJLSKElpNASUmgJKbSEFFpCCi0hhZaQQktIoSWk0BJSaAkptMQvjL8a9TsyvjLjjox6l1IhxllJj/j9rKNm3LlX72Ythd7hXQr9rQdSaAkptIQUWkIKLSGFgBKzDy4BnN3cAnTguahNgg7s0hct8QcuW7FCYhbPkRH/saeL5Yw1+Dd9fOAAKVbQL9HmbpSOdcNrLTHcNWOH8fXab0skm81T7O3jFyVWwx46wD5rpVKJ5d4f88Bksm7RiTgHejoNd8FECkD1tyUi8A19TawzRd8O2LeiJYZZ5yw8k5+dQuLKHrggIzNlTvvPu/cQrjfKNYDcqBSWp3CPmZSHDopzBDbnOFeOAuh2u3WSsZ1ud0NLDFNmCp4jJpIO4wMXZGSJ8YfTySuR4G6pCZCryQ7Pnr8maiSw0qJzXAOw1uywRbfCSi2nJYYpMAdPhqf4xJjdvyC32bIf3rG9EnnuVwGQm1hkAfeYyXnoYIlEmPt0rhuLQI3utl3bt6cd6mtiKIeX8MxxBjYZ7V+QCe4Bg6fTRYL52fvLCPn8NXFwxttO/pZOqpA5QWQ+iijrgD1f1RLDXLETAWBhld/wie5k/4LcoJt7UsK2N9iwnpRYq9GteXqPJ03uch90EKeTZl9CSwxzu8x8Kd7qYtt7e6ihf0FGkqzbgyU6yRW69pMScQ5Ak+sO7zQ6pVS8JzZXKPcealpiqOiBU2h0LjG5vTq3um2jf0FGbh1eD5ZoxRr19A+nU/W05MZhZZavvgBNRtLtNsvtZC4LIN1i6YitsH4/8R9YGXJ5HtkDh+yiSTx+j11cOebctY2jOWaaWuLf2yhNwTOVPMe3bfTU9nGnVLlKoWeh7a5pCRkm9XQaEVpCCi0hhZaQQktIoSWkMKPEyxASjy9ESDw9naTQElJoCSm0hBRaQgotIYWWkEJLSKElpNASUmgJKbSEFFpCCi0hhZaQQktIoSWk0BJS/H0JezNexZ3Ls1RmEUYwvcRXx8Jzx8f0vhxxv2C2YsMEppcI08JzU/6XD5YAe3UaJjC3xOfjRhJgD2Al3dhOFmFudRpLkX6gzCyA+C5MYGyJc65Fww9P+WE9F1lvI8yV4szyzmOJIj8BmM7DBMaWyHH+8XQqchHYiiHMBWA69lhiilkAaVZhAMNK2CTX4dlLVNL+Uz5FjxVmFEjT/rGEBQMYVmKQFc/7T3mOKf/tewaYT+ChxAwXAGy4MIGxJVKb1c/lSSxwLQu0bnL24hrCPIwuZA4eSyCxB+B6CSYwtsS5U3AuAJQaeaC4EissnyLM/XysZAH03P+zaTIzDxMYW+JnwoziiZPyJ0w7RrxNjHgJbNRnnCkYYcRLGGSkShhNS0ihJaQYzRJfV9zG+rnuE74A94mjz9niUl33CU+g+4QN4JS27hOeAPcJz15e9wlfkPsEUF2+0n3CE+w+AbTPLN0nfEHuE4g7Rd0nfIHuE83Oie4TvkD3iW6nCN0nfAL2CUv3CY+Ez2J1n5BSQvcJMSUMMlIljKYlpNASUoxsiRajuk/4AtwngOljRnWf8AS6T+A2ccSo/vyEL8h9onkYZlT3CV+A+8RX96RXQvcJT6D7xNIReiV0n/AFt09cdKp3JXSf8AS5T9zEyuUYy1u6T3iC2yf8KlHdJzxB7hN+Cf35iXsSPovVfUJKCd0nvrdjxzYMw1AMBSUjbhL/BQTV3n/ErJAiBSXfrfDAhjElFrJViaUpkUKJFEqkUCKFEimUSKFECiVSKJFCiRRKpFihRF/52PvVrN7ivWpc2xt1tnhH3WNeW5vjrqPle9cDfNoKjrPX1vq5wiIAAAAAAAAAAPiXLxzIGjRPzWNQAAAAAElFTkSuQmCC",i="/ran/assets/%E8%AE%BF%E9%97%AE%E8%80%85.aEI4m-5a.png";export{e as A,i as B,A as _,E as a,R as b,a as c,l as d,V as e,J as f,k as g,y as h,s as i,m as j,p as k,t as l,S as m,N as n,Q as o,M as p,j as q,O as r,n as s,Z as t,f as u,o as v,c as w,h as x,U as y,I as z}; diff --git a/assets/cn_index.md.Ci9FwTgY.js b/assets/cn_index.md.Ci9FwTgY.js new file mode 100644 index 0000000000..bb18c26796 --- /dev/null +++ b/assets/cn_index.md.Ci9FwTgY.js @@ -0,0 +1 @@ +import{_ as t,o as e,c as a}from"./chunks/framework.C-ai2y4t.js";const m=JSON.parse('{"title":"Home","description":"","frontmatter":{"layout":"home","title":"Home","hero":{"name":"ran","text":"风起于青萍之末","tagline":"A ship in harbor is safe, but that is not what ships are built for.","image":{"src":"/home.svg","alt":"logo"},"actions":[{"theme":"alt","text":"更多详情","link":"https://github.com/chaxus/ran"},{"theme":"alt","text":"访问我的 GitHub","link":"https://github.com/chaxus/ran"}]},"features":[{"icon":"⚡️","title":"记录","details":"每段旅程都有终点"},{"icon":"🛠️","title":"解决","details":"无法衡量,无法改进"},{"icon":"🖖","title":"分享","details":"一个人可以走得很快,一群人可以走的很远"}]},"headers":[],"relativePath":"cn/index.md","filePath":"cn/index.md","lastUpdated":1726550590000}'),i={name:"cn/index.md"};function n(o,s,r,c,l,h){return e(),a("div")}const p=t(i,[["render",n]]);export{m as __pageData,p as default}; diff --git a/assets/cn_index.md.Ci9FwTgY.lean.js b/assets/cn_index.md.Ci9FwTgY.lean.js new file mode 100644 index 0000000000..bb18c26796 --- /dev/null +++ b/assets/cn_index.md.Ci9FwTgY.lean.js @@ -0,0 +1 @@ +import{_ as t,o as e,c as a}from"./chunks/framework.C-ai2y4t.js";const m=JSON.parse('{"title":"Home","description":"","frontmatter":{"layout":"home","title":"Home","hero":{"name":"ran","text":"风起于青萍之末","tagline":"A ship in harbor is safe, but that is not what ships are built for.","image":{"src":"/home.svg","alt":"logo"},"actions":[{"theme":"alt","text":"更多详情","link":"https://github.com/chaxus/ran"},{"theme":"alt","text":"访问我的 GitHub","link":"https://github.com/chaxus/ran"}]},"features":[{"icon":"⚡️","title":"记录","details":"每段旅程都有终点"},{"icon":"🛠️","title":"解决","details":"无法衡量,无法改进"},{"icon":"🖖","title":"分享","details":"一个人可以走得很快,一群人可以走的很远"}]},"headers":[],"relativePath":"cn/index.md","filePath":"cn/index.md","lastUpdated":1726550590000}'),i={name:"cn/index.md"};function n(o,s,r,c,l,h){return e(),a("div")}const p=t(i,[["render",n]]);export{m as __pageData,p as default}; diff --git a/assets/cn_src_article_astParse_tokenizer.md.CPQ5Q4qA.js b/assets/cn_src_article_astParse_tokenizer.md.CPQ5Q4qA.js new file mode 100644 index 0000000000..dfe477f05f --- /dev/null +++ b/assets/cn_src_article_astParse_tokenizer.md.CPQ5Q4qA.js @@ -0,0 +1,184 @@ +import{_ as a,a as n,b as h,c as p,d as k,e as t,f as l,g as e,h as d,i as E,j as r,k as g,l as c,m as i,n as y}from"./chunks/extra.Cu56q3CZ.js";import{_ as o,o as F,c as C,a3 as A}from"./chunks/framework.C-ai2y4t.js";const S=JSON.parse('{"title":"Abstract Syntax Tree","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/astParse/tokenizer.md","filePath":"cn/src/article/astParse/tokenizer.md","lastUpdated":1726550590000}'),u={name:"cn/src/article/astParse/tokenizer.md"};function D(B,s,m,b,v,T){return F(),C("div",{"data-pagefind-body":!0},s[0]||(s[0]=[A('

Abstract Syntax Tree

一.(abstract syntax tree)抽象语法树的作用

源码是一串按照语法格式来组织的字符串,人能够认识,但是计算机并不认识,想让计算机认识就要转成一种数据结构,通过不同的对象来保存不同的数据,并且按照依赖关系组织起来,这种数据结构就是抽象语法树(abstract syntax tree)。

之所以叫“抽象”语法树是因为数据结构中省略掉了一些无具体意义的分隔符比如 ; { } 等。

有了 AST,计算机就能理解源码字符串的意思,而理解是能够转换的前提,所以编译的第一步需要把源码 parseAST

转成 AST 之后就可以通过修改 AST ,分析 AST 的方式来修改和分析代码,比如 babel 就通过这种方式进行代码的转换,比如 rollupTree Shaking ,就是通过分析 AST的 导入导出语法,从而分析出没有使用的代码,进行去除。

二。常见的 AST 节点

常见的 AST 节点 AST 是对源码的抽象,字面量、标识符、表达式、语句、模块语法、class 语法都有各自的 AST。

我们分别来了解一下:

Literal

Literal 是字面量的意思,比如 let name = 'value'中,'value'就是一个字符串字面量 StringLiteral,相应的还有数字字面量 NumericLiteral,布尔字面量 BooleanLiteral,字符串字面量 StringLiteral,正则表达式字面量 RegExpLiteral 等。

下面这些字面量都有对应的 Literal 节点:

代码中的字面量很多,babel 就是通过 xxLiteral 来抽象这部分内容的。

Identifier

Identifer 是标识符的意思,变量名、属性名、参数名等各种声明和引用的名字,都是Identifer

我们知道, JS 中的标识符只能包含字母或数字或下划线 (“_”) 或美元符号 (“$”) ,且不能以数字开头。这是 Identifier 的词法特点。

尝试分析一下,下面这一段代码里面有多少 Identifier 呢?

js
const name = 'value';
+
+function say(name) {
+  console.log(name);
+}
+
+const obj = {
+  name: 'guang',
+};

答案是这些

Statement

statement 是语句,它是可以独立执行的单位,比如 break、continue、debugger、return 或者 if 语句、while 语句、for 语句,还有声明语句,表达式语句等。我们写的每一条可以独立执行的代码都是语句。

语句末尾一般会加一个分号分隔,或者用换行分隔。

下面这些我们经常写的代码,每一行都是一个 Statement

js
break;
+continue;
+return;
+debugger;
+throw Error();
+{}
+try {} catch(e) {} finally{}
+for (let key in obj) {}
+for (let i = 0;i < 10;i ++) {}
+while (true) {}
+do {} while (true)
+switch (v){case 1: break;default:;}
+label: console.log();
+with (a){}

它们对应的 AST 节点如下图所示:

语句是代码执行的最小单位,可以说,代码是由语句 (Statement) 构成的。

Declaration

声明语句是一种特殊的语句,它执行的逻辑是在作用域内声明一个变量、函数、 class、import、export 等。

比如下面这些语句都是声明语句:

js
const a = 1;
+function b() {}
+class C {}
+
+import d from 'e';
+
+export default e = 1;
+export { e };
+export * from 'e';

它们对应的 AST 节点如下图:

声明语句用于定义变量,这也是代码中一个基础组成部分。

Expression

expression 是表达式,特点是执行完以后有返回值,这是和语句 (statement) 的区别。

下面是一些常见的表达式

js
[1,2,3]
+a = 1
+1 + 2;
+-1;
+function(){};
+() => {};
+class{};
+a;
+this;
+super;
+a::b;

它们对应的 AST 如图:

细心的同学可能会问 identifiersuper 怎么也是表达式呢?

因为 identifier、super 有返回值,符合表达式的特点,所以也是 expression

我们判断 AST 节点是不是某种类型要看它是不是符合该种类型的特点,比如语句的特点是能够单独执行,表达式的特点是有返回值。

有的表达式可以单独执行,符合语句的特点,所以也是语句,比如赋值表达式、数组表达式等。

js
a = 1;
+[1, 2, 3];

但有的表达式不能单独执行,需要和其他类型的节点组合在一起构成语句。

比如匿名函数表达式和匿名 class 表达式单独执行会报错:

js
function(){};
+class{}

需要和其他部分一起构成一条语句,比如组成赋值语句:

js
a = function () {};
+b = class {};

这条赋值语句对应的 AST 是这样的:

你会发现赋值语句的 AST 节点 AssignmentExpression 包裹了一层 ExpressionStatement 的节点,代表这个表达式是被当成语句执行的。

Class

class 的语法也有专门的 AST 节点来表示。

整个 class 的内容是 ClassBody ,属性是 ClassProperty ,方法是 ClassMethod (通过 kind 属性来区分是 constructor 还是 method )。

比如下面的代码

js
class Guang extends Person {
+  name = 'guang';
+  constructor() {}
+  eat() {}
+}

对应的 AST 是这样的

classes next 的语法, babel 中有专门的 AST 来表示它的内容。

Modules

es module 是语法级别的模块规范,所以也有专门的 AST 节点。

importimport 有 3 种语法:

named import

js
import { c, d } from 'c';

default import

js
import a from 'a';

namespaced import:

js
import * as b from 'b';

这 3 种语法都对应 ImportDeclaration 节点,但是 specifiers 属性不同,分别对应 ImportSpicifier 、ImportDefaultSpecifier 、ImportNamespaceSpcifier

图中黄框标出的就是 specifier 部分。可以直观的看出整体结构相同,只是 specifier 部分不同,所以 import 语法的 AST 的结构是 ImportDeclaration 包含着各种 import specifier

exportexport 也有 3 种语法:

named export

js
export { b, d };

default export

js
export default a;

all export

js
export * from 'c';

分别对应 ExportNamedDeclaration 、ExportDefaultDeclaration 、ExportAllDeclarationAST

比如这三种 export

js
export { b, d };
+export default a;
+export * from 'c';

对应的 AST 节点为

Program & Directive

program 是代表整个程序的节点,它有 body 属性代表程序体,存放 statement 数组,就是具体执行的语句的集合。还有 directives 属性,存放 Directive 节点,比如 "use strict" 这种指令会使用 Directive 节点表示。

Program 是包裹具体执行语句的节点,而 Directive 则是代码中的指令部分。

File & Comment

babelAST 最外层节点是 File ,它有 programcommentstokens 等属性,分别存放 Program 程序体、注释、 token 等,是最外层节点。

注释分为块注释和行内注释,对应 CommentBlockCommentLine 节点。

上面 6 种就是常见的一些 AST 节点类型, babel 就是通过这些节点来抽象源码中不同的部分。

AST 可视化查看工具

这么多 AST 我们都要记住么?

不需要。可以通过 axtexplorer.net 这个网站来可视化的查看。

这个网站可以查看代码 parse 以后的 AST ,可以切换 parse 的语言和用的 parser ,也可以修改 parse options

点击这里的 save 就可以保存下来,然后把 url 分享出去:

比如这个链接:https://astexplorer.net/

如果想查看全部的 AST 可以在 babel parser 仓库里的 AST 文档里查,或者直接去看 @babel/typestypescript 类型定义。

AST 的公共属性

每种 AST 都有自己的属性,但是它们也有一些公共的属性:

typeAST 节点的类型

startendloc:startend 代表该节点在源码中的开始和结束下标。而 loc 属性是一个对象,有 linecolumn 属性分别记录开始和结束的行列号。

leadingCommentsinnerCommentstrailingComments :表示开始的注释、中间的注释、结尾的注释,每个 AST 节点中都可能存在注释,而且可能在开始、中间、结束这三种位置,想拿到某个 AST 的注释就通过这三个属性。

比如这段有注释的代码的 AST

extra:记录一些额外的信息,用于处理一些特殊情况。比如 StringLiteralvalue 只是值的修改,而修改 extra.raw 则可以连同单双引号一起修改。 比如这段代码的 AST

修改 value 只能修改值,修改 extra.raw 可以连引号一起修改。

总结

了解了这些节点,就能知道平时写的代码是怎么用 AST 表示的。

当然也不需要记,可以用 (astexpoler.net) 可视化的查看。

AST 节点可能同时有多种类型,确定一种 AST 节点是什么类型主要看它的特点,比如 Statement 的特点是可以单独执行, Expression 的特点是有返回值,所以一些可以单独执行的 Expression 会包一层 ExpressionStatement

不同 AST 节点有不同的属性来存放对应的源码信息,但是都有一些公共属性如 type 、xxCommentsloc 等。

学会了 AST ,就可以把对代码的操作转为对 AST 的操作了,这是编译、静态分析的第一步。

三。编写词法分析器(Tokenizer)

词法分析器,也叫分词器 (Tokenizer),它的作用是将代码划分为一个个词法单元,便于进行后续的语法分析。比如下面的这段代码:

js
let foo = function () {};

在经过分词之后,代码会被切分为如下的 token 数组:

js
['let', 'foo', '=', 'function', '(', ')', '{', '}'];

从中你可以看到,原本一行普通的代码字符串被拆分成了拥有语法属性的 token 列表,不同的 token 之间也存在千丝万缕的联系,而后面所要介绍的语法分析器,就是来梳理各个 token 之间的联系,整理出 AST 数据结构。

当下我们所要实现的词法分析器,本质上是对代码字符串进行逐个字符的扫描,然后根据一定的语法规则进行分组。其中,涉及到几个关键的步骤:

  1. 确定语法规则,包括语言内置的关键词、单字符、分隔符等
  2. 逐个代码字符扫描,根据语法规则进行 token 分组

1. 确定 Token 的类型和规则

增加 Token 的类型

ts
export enum TokenType {
+  // let
+  Let = 'Let',
+  // =
+  Assign = 'Assign',
+  // function
+  Function = 'Function',
+  // 变量名
+  Identifier = 'Identifier',
+  // (
+  LeftParen = 'LeftParen',
+  // )
+  RightParen = 'RightParen',
+  // {
+  LeftCurly = 'LeftCurly',
+  // }
+  RightCurly = 'RightCurly',
+}
+
+export type Token = {
+  type: TokenType;
+  value?: string;
+  start: number;
+  end: number;
+  raw?: string;
+};

定义 Token 类型到规则的映射

ts
const TOKENS_GENERATOR: Record<string, (...args: any[]) => Token> = {
+  let(start: number) {
+    return { type: TokenType.Let, value: 'let', start, end: start + 3 };
+  },
+  assign(start: number) {
+    return { type: TokenType.Assign, value: '=', start, end: start + 1 };
+  },
+  function(start: number) {
+    return {
+      type: TokenType.Function,
+      value: 'function',
+      start,
+      end: start + 8,
+    };
+  },
+  leftParen(start: number) {
+    return { type: TokenType.LeftParen, value: '(', start, end: start + 1 };
+  },
+  rightParen(start: number) {
+    return { type: TokenType.RightParen, value: ')', start, end: start + 1 };
+  },
+  leftCurly(start: number) {
+    return { type: TokenType.LeftCurly, value: '{', start, end: start + 1 };
+  },
+  rightCurly(start: number) {
+    return { type: TokenType.RightCurly, value: '}', start, end: start + 1 };
+  },
+  identifier(start: number, value: string) {
+    return {
+      type: TokenType.Identifier,
+      value,
+      start,
+      end: start + value.length,
+    };
+  },
+};
+
+type SingleCharTokens = '(' | ')' | '{' | '}' | '=';
+
+// 单字符到 Token 生成器的映射
+const KNOWN_SINGLE_CHAR_TOKENS = new Map<SingleCharTokens, (typeof TOKENS_GENERATOR)[keyof typeof TOKENS_GENERATOR]>([
+  ['(', TOKENS_GENERATOR.leftParen],
+  [')', TOKENS_GENERATOR.rightParen],
+  ['{', TOKENS_GENERATOR.leftCurly],
+  ['}', TOKENS_GENERATOR.rightCurly],
+  ['=', TOKENS_GENERATOR.assign],
+]);

有了 Token 类型和对应生成的规则,我们便可以去遍历分析代码,输出分析后的结果。

2.代码字符扫描

在扫描字符的过程,我们需要对不同的字符各自进行不同的处理,具体的策略如下:

  • 当前字符为分隔符,如空格,直接跳过,不处理;
  • 当前字符为字母,需要继续扫描,获取完整的单词:
    • 如果单词为语法关键字,则新建相应关键字的 Token
    • 否则视为普通的变量名
  • 当前字符为单字符,如{、}、(、),则新建单字符对应的 Token
ts
export class Tokenizer {
+  private _tokens: Token[] = [];
+  private _currentIndex: number = 0;
+  private _source: string;
+  constructor(input: string) {
+    this._source = input;
+  }
+  tokenize(): Token[] {
+    while (this._currentIndex < this._source.length) {
+      let currentChar = this._source[this._currentIndex];
+      const startIndex = this._currentIndex;
+
+      // 根据语法规则进行 token 分组
+      // while 循环内部
+      let currentChar = this._source[this._currentIndex];
+      const startIndex = this._currentIndex;
+
+      const isAlpha = (char: string): boolean => {
+        return (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z');
+      };
+
+      // 1. 处理空格
+      if (currentChar === ' ') {
+        this._currentIndex++;
+        continue;
+      }
+      // 2. 处理字母
+      else if (isAlpha(currentChar)) {
+        let identifier = '';
+        while (isAlpha(currentChar)) {
+          identifier += currentChar;
+          this._currentIndex++;
+          currentChar = this._source[this._currentIndex];
+        }
+        let token: Token;
+        if (identifier in TOKENS_GENERATOR) {
+          // 如果是关键字
+          token = TOKENS_GENERATOR[identifier as keyof typeof TOKENS_GENERATOR](startIndex);
+        } else {
+          // 如果是普通标识符
+          token = TOKENS_GENERATOR['identifier'](startIndex, identifier);
+        }
+        this._tokens.push(token);
+        continue;
+      }
+      // 3. 处理单字符
+      else if (KNOWN_SINGLE_CHAR_TOKENS.has(currentChar as SingleCharTokens)) {
+        const token = KNOWN_SINGLE_CHAR_TOKENS.get(currentChar as SingleCharTokens)!(startIndex);
+        this._tokens.push(token);
+        this._currentIndex++;
+        continue;
+      }
+    }
+    return this._tokens;
+  }
+}

使用方式

ts
const tokenizer = new Tokenizer('let a = function() {}');

结果

ts
const tokenizer = [
+  { type: 'Let', value: 'let', start: 0, end: 3 },
+  { type: 'Identifier', value: 'a', start: 4, end: 5 },
+  { type: 'Assign', value: '=', start: 6, end: 7 },
+  { type: 'Function', value: 'function', start: 8, end: 16 },
+  { type: 'LeftParen', value: '(', start: 16, end: 17 },
+  { type: 'RightParen', value: ')', start: 17, end: 18 },
+  { type: 'LeftCurly', value: '{', start: 19, end: 20 },
+  { type: 'RightCurly', value: '}', start: 20, end: 21 },
+];

一个简易版本的分词器已经被我们开发出来了,不过目前的分词器还比较简陋,仅仅支持有限的语法,不过在明确了核心的开发步骤之后,后面继续完善的过程就比较简单了。

四。编写语法分析器(Parser)

在解析出词法 token 之后,我们就可以进入语法分析阶段了。在这个阶段,我们会依次遍历 token ,对代码进行语法结构层面的分析,最后的目标是生成 AST 数据结构。至于代码的 AST 结构到底是什么样子,你可以去 AST Explorer 网站进行在线预览:

接下来,我们要做的就是将 token 数组转换为上图所示的 AST 数据。

开发步骤主要分为:

  • 初始化类型声明
',150)]))}const _=o(u,[["render",D]]);export{S as __pageData,_ as default}; diff --git a/assets/cn_src_article_astParse_tokenizer.md.CPQ5Q4qA.lean.js b/assets/cn_src_article_astParse_tokenizer.md.CPQ5Q4qA.lean.js new file mode 100644 index 0000000000..dfe477f05f --- /dev/null +++ b/assets/cn_src_article_astParse_tokenizer.md.CPQ5Q4qA.lean.js @@ -0,0 +1,184 @@ +import{_ as a,a as n,b as h,c as p,d as k,e as t,f as l,g as e,h as d,i as E,j as r,k as g,l as c,m as i,n as y}from"./chunks/extra.Cu56q3CZ.js";import{_ as o,o as F,c as C,a3 as A}from"./chunks/framework.C-ai2y4t.js";const S=JSON.parse('{"title":"Abstract Syntax Tree","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/astParse/tokenizer.md","filePath":"cn/src/article/astParse/tokenizer.md","lastUpdated":1726550590000}'),u={name:"cn/src/article/astParse/tokenizer.md"};function D(B,s,m,b,v,T){return F(),C("div",{"data-pagefind-body":!0},s[0]||(s[0]=[A('

Abstract Syntax Tree

一.(abstract syntax tree)抽象语法树的作用

源码是一串按照语法格式来组织的字符串,人能够认识,但是计算机并不认识,想让计算机认识就要转成一种数据结构,通过不同的对象来保存不同的数据,并且按照依赖关系组织起来,这种数据结构就是抽象语法树(abstract syntax tree)。

之所以叫“抽象”语法树是因为数据结构中省略掉了一些无具体意义的分隔符比如 ; { } 等。

有了 AST,计算机就能理解源码字符串的意思,而理解是能够转换的前提,所以编译的第一步需要把源码 parseAST

转成 AST 之后就可以通过修改 AST ,分析 AST 的方式来修改和分析代码,比如 babel 就通过这种方式进行代码的转换,比如 rollupTree Shaking ,就是通过分析 AST的 导入导出语法,从而分析出没有使用的代码,进行去除。

二。常见的 AST 节点

常见的 AST 节点 AST 是对源码的抽象,字面量、标识符、表达式、语句、模块语法、class 语法都有各自的 AST。

我们分别来了解一下:

Literal

Literal 是字面量的意思,比如 let name = 'value'中,'value'就是一个字符串字面量 StringLiteral,相应的还有数字字面量 NumericLiteral,布尔字面量 BooleanLiteral,字符串字面量 StringLiteral,正则表达式字面量 RegExpLiteral 等。

下面这些字面量都有对应的 Literal 节点:

代码中的字面量很多,babel 就是通过 xxLiteral 来抽象这部分内容的。

Identifier

Identifer 是标识符的意思,变量名、属性名、参数名等各种声明和引用的名字,都是Identifer

我们知道, JS 中的标识符只能包含字母或数字或下划线 (“_”) 或美元符号 (“$”) ,且不能以数字开头。这是 Identifier 的词法特点。

尝试分析一下,下面这一段代码里面有多少 Identifier 呢?

js
const name = 'value';
+
+function say(name) {
+  console.log(name);
+}
+
+const obj = {
+  name: 'guang',
+};

答案是这些

Statement

statement 是语句,它是可以独立执行的单位,比如 break、continue、debugger、return 或者 if 语句、while 语句、for 语句,还有声明语句,表达式语句等。我们写的每一条可以独立执行的代码都是语句。

语句末尾一般会加一个分号分隔,或者用换行分隔。

下面这些我们经常写的代码,每一行都是一个 Statement

js
break;
+continue;
+return;
+debugger;
+throw Error();
+{}
+try {} catch(e) {} finally{}
+for (let key in obj) {}
+for (let i = 0;i < 10;i ++) {}
+while (true) {}
+do {} while (true)
+switch (v){case 1: break;default:;}
+label: console.log();
+with (a){}

它们对应的 AST 节点如下图所示:

语句是代码执行的最小单位,可以说,代码是由语句 (Statement) 构成的。

Declaration

声明语句是一种特殊的语句,它执行的逻辑是在作用域内声明一个变量、函数、 class、import、export 等。

比如下面这些语句都是声明语句:

js
const a = 1;
+function b() {}
+class C {}
+
+import d from 'e';
+
+export default e = 1;
+export { e };
+export * from 'e';

它们对应的 AST 节点如下图:

声明语句用于定义变量,这也是代码中一个基础组成部分。

Expression

expression 是表达式,特点是执行完以后有返回值,这是和语句 (statement) 的区别。

下面是一些常见的表达式

js
[1,2,3]
+a = 1
+1 + 2;
+-1;
+function(){};
+() => {};
+class{};
+a;
+this;
+super;
+a::b;

它们对应的 AST 如图:

细心的同学可能会问 identifiersuper 怎么也是表达式呢?

因为 identifier、super 有返回值,符合表达式的特点,所以也是 expression

我们判断 AST 节点是不是某种类型要看它是不是符合该种类型的特点,比如语句的特点是能够单独执行,表达式的特点是有返回值。

有的表达式可以单独执行,符合语句的特点,所以也是语句,比如赋值表达式、数组表达式等。

js
a = 1;
+[1, 2, 3];

但有的表达式不能单独执行,需要和其他类型的节点组合在一起构成语句。

比如匿名函数表达式和匿名 class 表达式单独执行会报错:

js
function(){};
+class{}

需要和其他部分一起构成一条语句,比如组成赋值语句:

js
a = function () {};
+b = class {};

这条赋值语句对应的 AST 是这样的:

你会发现赋值语句的 AST 节点 AssignmentExpression 包裹了一层 ExpressionStatement 的节点,代表这个表达式是被当成语句执行的。

Class

class 的语法也有专门的 AST 节点来表示。

整个 class 的内容是 ClassBody ,属性是 ClassProperty ,方法是 ClassMethod (通过 kind 属性来区分是 constructor 还是 method )。

比如下面的代码

js
class Guang extends Person {
+  name = 'guang';
+  constructor() {}
+  eat() {}
+}

对应的 AST 是这样的

classes next 的语法, babel 中有专门的 AST 来表示它的内容。

Modules

es module 是语法级别的模块规范,所以也有专门的 AST 节点。

importimport 有 3 种语法:

named import

js
import { c, d } from 'c';

default import

js
import a from 'a';

namespaced import:

js
import * as b from 'b';

这 3 种语法都对应 ImportDeclaration 节点,但是 specifiers 属性不同,分别对应 ImportSpicifier 、ImportDefaultSpecifier 、ImportNamespaceSpcifier

图中黄框标出的就是 specifier 部分。可以直观的看出整体结构相同,只是 specifier 部分不同,所以 import 语法的 AST 的结构是 ImportDeclaration 包含着各种 import specifier

exportexport 也有 3 种语法:

named export

js
export { b, d };

default export

js
export default a;

all export

js
export * from 'c';

分别对应 ExportNamedDeclaration 、ExportDefaultDeclaration 、ExportAllDeclarationAST

比如这三种 export

js
export { b, d };
+export default a;
+export * from 'c';

对应的 AST 节点为

Program & Directive

program 是代表整个程序的节点,它有 body 属性代表程序体,存放 statement 数组,就是具体执行的语句的集合。还有 directives 属性,存放 Directive 节点,比如 "use strict" 这种指令会使用 Directive 节点表示。

Program 是包裹具体执行语句的节点,而 Directive 则是代码中的指令部分。

File & Comment

babelAST 最外层节点是 File ,它有 programcommentstokens 等属性,分别存放 Program 程序体、注释、 token 等,是最外层节点。

注释分为块注释和行内注释,对应 CommentBlockCommentLine 节点。

上面 6 种就是常见的一些 AST 节点类型, babel 就是通过这些节点来抽象源码中不同的部分。

AST 可视化查看工具

这么多 AST 我们都要记住么?

不需要。可以通过 axtexplorer.net 这个网站来可视化的查看。

这个网站可以查看代码 parse 以后的 AST ,可以切换 parse 的语言和用的 parser ,也可以修改 parse options

点击这里的 save 就可以保存下来,然后把 url 分享出去:

比如这个链接:https://astexplorer.net/

如果想查看全部的 AST 可以在 babel parser 仓库里的 AST 文档里查,或者直接去看 @babel/typestypescript 类型定义。

AST 的公共属性

每种 AST 都有自己的属性,但是它们也有一些公共的属性:

typeAST 节点的类型

startendloc:startend 代表该节点在源码中的开始和结束下标。而 loc 属性是一个对象,有 linecolumn 属性分别记录开始和结束的行列号。

leadingCommentsinnerCommentstrailingComments :表示开始的注释、中间的注释、结尾的注释,每个 AST 节点中都可能存在注释,而且可能在开始、中间、结束这三种位置,想拿到某个 AST 的注释就通过这三个属性。

比如这段有注释的代码的 AST

extra:记录一些额外的信息,用于处理一些特殊情况。比如 StringLiteralvalue 只是值的修改,而修改 extra.raw 则可以连同单双引号一起修改。 比如这段代码的 AST

修改 value 只能修改值,修改 extra.raw 可以连引号一起修改。

总结

了解了这些节点,就能知道平时写的代码是怎么用 AST 表示的。

当然也不需要记,可以用 (astexpoler.net) 可视化的查看。

AST 节点可能同时有多种类型,确定一种 AST 节点是什么类型主要看它的特点,比如 Statement 的特点是可以单独执行, Expression 的特点是有返回值,所以一些可以单独执行的 Expression 会包一层 ExpressionStatement

不同 AST 节点有不同的属性来存放对应的源码信息,但是都有一些公共属性如 type 、xxCommentsloc 等。

学会了 AST ,就可以把对代码的操作转为对 AST 的操作了,这是编译、静态分析的第一步。

三。编写词法分析器(Tokenizer)

词法分析器,也叫分词器 (Tokenizer),它的作用是将代码划分为一个个词法单元,便于进行后续的语法分析。比如下面的这段代码:

js
let foo = function () {};

在经过分词之后,代码会被切分为如下的 token 数组:

js
['let', 'foo', '=', 'function', '(', ')', '{', '}'];

从中你可以看到,原本一行普通的代码字符串被拆分成了拥有语法属性的 token 列表,不同的 token 之间也存在千丝万缕的联系,而后面所要介绍的语法分析器,就是来梳理各个 token 之间的联系,整理出 AST 数据结构。

当下我们所要实现的词法分析器,本质上是对代码字符串进行逐个字符的扫描,然后根据一定的语法规则进行分组。其中,涉及到几个关键的步骤:

  1. 确定语法规则,包括语言内置的关键词、单字符、分隔符等
  2. 逐个代码字符扫描,根据语法规则进行 token 分组

1. 确定 Token 的类型和规则

增加 Token 的类型

ts
export enum TokenType {
+  // let
+  Let = 'Let',
+  // =
+  Assign = 'Assign',
+  // function
+  Function = 'Function',
+  // 变量名
+  Identifier = 'Identifier',
+  // (
+  LeftParen = 'LeftParen',
+  // )
+  RightParen = 'RightParen',
+  // {
+  LeftCurly = 'LeftCurly',
+  // }
+  RightCurly = 'RightCurly',
+}
+
+export type Token = {
+  type: TokenType;
+  value?: string;
+  start: number;
+  end: number;
+  raw?: string;
+};

定义 Token 类型到规则的映射

ts
const TOKENS_GENERATOR: Record<string, (...args: any[]) => Token> = {
+  let(start: number) {
+    return { type: TokenType.Let, value: 'let', start, end: start + 3 };
+  },
+  assign(start: number) {
+    return { type: TokenType.Assign, value: '=', start, end: start + 1 };
+  },
+  function(start: number) {
+    return {
+      type: TokenType.Function,
+      value: 'function',
+      start,
+      end: start + 8,
+    };
+  },
+  leftParen(start: number) {
+    return { type: TokenType.LeftParen, value: '(', start, end: start + 1 };
+  },
+  rightParen(start: number) {
+    return { type: TokenType.RightParen, value: ')', start, end: start + 1 };
+  },
+  leftCurly(start: number) {
+    return { type: TokenType.LeftCurly, value: '{', start, end: start + 1 };
+  },
+  rightCurly(start: number) {
+    return { type: TokenType.RightCurly, value: '}', start, end: start + 1 };
+  },
+  identifier(start: number, value: string) {
+    return {
+      type: TokenType.Identifier,
+      value,
+      start,
+      end: start + value.length,
+    };
+  },
+};
+
+type SingleCharTokens = '(' | ')' | '{' | '}' | '=';
+
+// 单字符到 Token 生成器的映射
+const KNOWN_SINGLE_CHAR_TOKENS = new Map<SingleCharTokens, (typeof TOKENS_GENERATOR)[keyof typeof TOKENS_GENERATOR]>([
+  ['(', TOKENS_GENERATOR.leftParen],
+  [')', TOKENS_GENERATOR.rightParen],
+  ['{', TOKENS_GENERATOR.leftCurly],
+  ['}', TOKENS_GENERATOR.rightCurly],
+  ['=', TOKENS_GENERATOR.assign],
+]);

有了 Token 类型和对应生成的规则,我们便可以去遍历分析代码,输出分析后的结果。

2.代码字符扫描

在扫描字符的过程,我们需要对不同的字符各自进行不同的处理,具体的策略如下:

  • 当前字符为分隔符,如空格,直接跳过,不处理;
  • 当前字符为字母,需要继续扫描,获取完整的单词:
    • 如果单词为语法关键字,则新建相应关键字的 Token
    • 否则视为普通的变量名
  • 当前字符为单字符,如{、}、(、),则新建单字符对应的 Token
ts
export class Tokenizer {
+  private _tokens: Token[] = [];
+  private _currentIndex: number = 0;
+  private _source: string;
+  constructor(input: string) {
+    this._source = input;
+  }
+  tokenize(): Token[] {
+    while (this._currentIndex < this._source.length) {
+      let currentChar = this._source[this._currentIndex];
+      const startIndex = this._currentIndex;
+
+      // 根据语法规则进行 token 分组
+      // while 循环内部
+      let currentChar = this._source[this._currentIndex];
+      const startIndex = this._currentIndex;
+
+      const isAlpha = (char: string): boolean => {
+        return (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z');
+      };
+
+      // 1. 处理空格
+      if (currentChar === ' ') {
+        this._currentIndex++;
+        continue;
+      }
+      // 2. 处理字母
+      else if (isAlpha(currentChar)) {
+        let identifier = '';
+        while (isAlpha(currentChar)) {
+          identifier += currentChar;
+          this._currentIndex++;
+          currentChar = this._source[this._currentIndex];
+        }
+        let token: Token;
+        if (identifier in TOKENS_GENERATOR) {
+          // 如果是关键字
+          token = TOKENS_GENERATOR[identifier as keyof typeof TOKENS_GENERATOR](startIndex);
+        } else {
+          // 如果是普通标识符
+          token = TOKENS_GENERATOR['identifier'](startIndex, identifier);
+        }
+        this._tokens.push(token);
+        continue;
+      }
+      // 3. 处理单字符
+      else if (KNOWN_SINGLE_CHAR_TOKENS.has(currentChar as SingleCharTokens)) {
+        const token = KNOWN_SINGLE_CHAR_TOKENS.get(currentChar as SingleCharTokens)!(startIndex);
+        this._tokens.push(token);
+        this._currentIndex++;
+        continue;
+      }
+    }
+    return this._tokens;
+  }
+}

使用方式

ts
const tokenizer = new Tokenizer('let a = function() {}');

结果

ts
const tokenizer = [
+  { type: 'Let', value: 'let', start: 0, end: 3 },
+  { type: 'Identifier', value: 'a', start: 4, end: 5 },
+  { type: 'Assign', value: '=', start: 6, end: 7 },
+  { type: 'Function', value: 'function', start: 8, end: 16 },
+  { type: 'LeftParen', value: '(', start: 16, end: 17 },
+  { type: 'RightParen', value: ')', start: 17, end: 18 },
+  { type: 'LeftCurly', value: '{', start: 19, end: 20 },
+  { type: 'RightCurly', value: '}', start: 20, end: 21 },
+];

一个简易版本的分词器已经被我们开发出来了,不过目前的分词器还比较简陋,仅仅支持有限的语法,不过在明确了核心的开发步骤之后,后面继续完善的过程就比较简单了。

四。编写语法分析器(Parser)

在解析出词法 token 之后,我们就可以进入语法分析阶段了。在这个阶段,我们会依次遍历 token ,对代码进行语法结构层面的分析,最后的目标是生成 AST 数据结构。至于代码的 AST 结构到底是什么样子,你可以去 AST Explorer 网站进行在线预览:

接下来,我们要做的就是将 token 数组转换为上图所示的 AST 数据。

开发步骤主要分为:

  • 初始化类型声明
',150)]))}const _=o(u,[["render",D]]);export{S as __pageData,_ as default}; diff --git a/assets/cn_src_article_babel.md.Bv2kTzb8.js b/assets/cn_src_article_babel.md.Bv2kTzb8.js new file mode 100644 index 0000000000..e531d687a4 --- /dev/null +++ b/assets/cn_src_article_babel.md.Bv2kTzb8.js @@ -0,0 +1 @@ +import{_ as a,o as t,c as l,a3 as r}from"./chunks/framework.C-ai2y4t.js";const m=JSON.parse('{"title":"Babel","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/babel.md","filePath":"cn/src/article/babel.md","lastUpdated":1726550590000}'),i={name:"cn/src/article/babel.md"};function s(b,e,o,c,p,n){return t(),l("div",{"data-pagefind-body":!0},e[0]||(e[0]=[r('

Babel

babel 核心库主要是:

  • @babel/parser 对源码进行 parse,可以通过 plugins、sourceType 等来指定 parse 语法,功能是把源码转成 AST。
  • @babel/traverse 通过 visitor 函数对遍历到的 ast 进行处理,分为 enter 和 exit 两个阶段,具体操作 AST 使用 path 的 api,还可以通过 state 来在遍历过程中传递一些数据
  • @babel/types 用于创建、判断 AST 节点,提供了 xxx、isXxx、assertXxx 的 api
  • @babel/template 当需要批量创建 AST 的时候可以使用 @babel/template 来简化 AST 创建逻辑。
  • @babel/code-frame 可以创建友好的报错信息
  • @babel/generator 打印 AST 成目标代码字符串,支持 comments、minified、sourceMaps 等选项。
  • @babel/core 基于上面的包来完成 babel 的编译流程,并应用 plugin 和 preset。
',3)]))}const u=a(i,[["render",s]]);export{m as __pageData,u as default}; diff --git a/assets/cn_src_article_babel.md.Bv2kTzb8.lean.js b/assets/cn_src_article_babel.md.Bv2kTzb8.lean.js new file mode 100644 index 0000000000..e531d687a4 --- /dev/null +++ b/assets/cn_src_article_babel.md.Bv2kTzb8.lean.js @@ -0,0 +1 @@ +import{_ as a,o as t,c as l,a3 as r}from"./chunks/framework.C-ai2y4t.js";const m=JSON.parse('{"title":"Babel","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/babel.md","filePath":"cn/src/article/babel.md","lastUpdated":1726550590000}'),i={name:"cn/src/article/babel.md"};function s(b,e,o,c,p,n){return t(),l("div",{"data-pagefind-body":!0},e[0]||(e[0]=[r('

Babel

babel 核心库主要是:

  • @babel/parser 对源码进行 parse,可以通过 plugins、sourceType 等来指定 parse 语法,功能是把源码转成 AST。
  • @babel/traverse 通过 visitor 函数对遍历到的 ast 进行处理,分为 enter 和 exit 两个阶段,具体操作 AST 使用 path 的 api,还可以通过 state 来在遍历过程中传递一些数据
  • @babel/types 用于创建、判断 AST 节点,提供了 xxx、isXxx、assertXxx 的 api
  • @babel/template 当需要批量创建 AST 的时候可以使用 @babel/template 来简化 AST 创建逻辑。
  • @babel/code-frame 可以创建友好的报错信息
  • @babel/generator 打印 AST 成目标代码字符串,支持 comments、minified、sourceMaps 等选项。
  • @babel/core 基于上面的包来完成 babel 的编译流程,并应用 plugin 和 preset。
',3)]))}const u=a(i,[["render",s]]);export{m as __pageData,u as default}; diff --git a/assets/cn_src_article_bundle.md.B9WVe3Nd.js b/assets/cn_src_article_bundle.md.B9WVe3Nd.js new file mode 100644 index 0000000000..2bbded68d0 --- /dev/null +++ b/assets/cn_src_article_bundle.md.B9WVe3Nd.js @@ -0,0 +1 @@ +import{_ as a,o as n,c as t,j as e,a as r}from"./chunks/framework.C-ai2y4t.js";const f=JSON.parse('{"title":"Bundle","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/bundle.md","filePath":"cn/src/article/bundle.md","lastUpdated":1726550590000}'),d={name:"cn/src/article/bundle.md"};function c(s,l,i,o,u,p){return n(),t("div",{"data-pagefind-body":!0},l[0]||(l[0]=[e("h1",{id:"bundle",tabindex:"-1"},[r("Bundle "),e("a",{class:"header-anchor",href:"#bundle","aria-label":'Permalink to "Bundle"'},"​")],-1),e("p",null,"Bundle 的本质就是输入,转换,输出。在机器上直接运行的代码,往往都难以维护和理解,我们需要将开发者方便理解和维护的代码,通过打包等工具转换成方便机器或者程序使用的代码。对于 web 前端来说,打包工具,至少需要以下功能:",-1),e("ul",null,[e("li",null,"编译能力"),e("li",null,"插件机制"),e("li",null,"HMR"),e("li",null,"cli 和命令行能力")],-1)]))}const m=a(d,[["render",c]]);export{f as __pageData,m as default}; diff --git a/assets/cn_src_article_bundle.md.B9WVe3Nd.lean.js b/assets/cn_src_article_bundle.md.B9WVe3Nd.lean.js new file mode 100644 index 0000000000..2bbded68d0 --- /dev/null +++ b/assets/cn_src_article_bundle.md.B9WVe3Nd.lean.js @@ -0,0 +1 @@ +import{_ as a,o as n,c as t,j as e,a as r}from"./chunks/framework.C-ai2y4t.js";const f=JSON.parse('{"title":"Bundle","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/bundle.md","filePath":"cn/src/article/bundle.md","lastUpdated":1726550590000}'),d={name:"cn/src/article/bundle.md"};function c(s,l,i,o,u,p){return n(),t("div",{"data-pagefind-body":!0},l[0]||(l[0]=[e("h1",{id:"bundle",tabindex:"-1"},[r("Bundle "),e("a",{class:"header-anchor",href:"#bundle","aria-label":'Permalink to "Bundle"'},"​")],-1),e("p",null,"Bundle 的本质就是输入,转换,输出。在机器上直接运行的代码,往往都难以维护和理解,我们需要将开发者方便理解和维护的代码,通过打包等工具转换成方便机器或者程序使用的代码。对于 web 前端来说,打包工具,至少需要以下功能:",-1),e("ul",null,[e("li",null,"编译能力"),e("li",null,"插件机制"),e("li",null,"HMR"),e("li",null,"cli 和命令行能力")],-1)]))}const m=a(d,[["render",c]]);export{f as __pageData,m as default}; diff --git a/assets/cn_src_article_designMode.md.Bo9IXX6C.js b/assets/cn_src_article_designMode.md.Bo9IXX6C.js new file mode 100644 index 0000000000..87f6dd1d48 --- /dev/null +++ b/assets/cn_src_article_designMode.md.Bo9IXX6C.js @@ -0,0 +1,752 @@ +import{_ as i,a,b as n,c as h,d as l,e as k,f as p,g as t,h as e,i as E,j as r,k as d,l as g,m as y,n as F,o as c,p as o,q as C,r as B,s as A,t as D,u,v as b,w as m,x as v,y as f,z as x,A as _,B as q}from"./chunks/访问者._0swtoJg.js";import{_ as P,o as w,c as j,a3 as M}from"./chunks/framework.C-ai2y4t.js";const W=JSON.parse('{"title":"23 种经典设计模式","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/designMode.md","filePath":"cn/src/article/designMode.md","lastUpdated":1726550590000}'),S={name:"cn/src/article/designMode.md"};function T(L,s,V,I,N,O){return w(),j("div",{"data-pagefind-body":!0},s[0]||(s[0]=[M(`

23 种经典设计模式

设计模式 Design Pattern 是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。。

在《设计模式:可复用面向对象软件的基础》一书中所介绍的 23 种经典设计模式,不过设计模式并不仅仅只有这 23 种,随着软件开发行业的发展,越来越多的新模式不断诞生并得以应用。有经验的开发者在学习设计模式可以和过往的经验互相印证,更容易理解这些设计模式。

设计模式一般包含模式名称、问题、目的、解决方案、效果等组成要素。问题描述了应该在何时使用模式,它包含了设计中存在的问题以及问题存在的原因。解决方案描述了一个设计模式的组成成分,以及这些组成成分之间的相互关系,各自的职责和协作方式,通常解决方案通过 UML 类图和核心代码来进行描述。效果描述了模式的优缺点以及在使用模式时应权衡的问题。

为什么要学习设计模式:

  • 设计模式来源众多专家的经验和智慧,它们是从许多优秀的软件系统中总结出的成功的、能够实现可维护性复用的设计方案,使用这些方案将可以让我们避免做一些重复性的工作

  • 设计模式提供了一套通用的设计词汇和一种通用的形式来方便开发人员之间沟通和交流,使得设计方案更加通俗易懂

  • 大部分设计模式都兼顾了系统的可重用性和可扩展性,这使得我们可以更好地重用一些已有的设计方案、功能模块甚至一个完整的软件系统,避免我们经常做一些重复的设计、编写一些重复的代码

  • 合理使用设计模式并对设计模式的使用情况进行文档化,将有助于别人更快地理解系统

  • 学习设计模式将有助于初学者更加深入地理解面向对象思想

储备知识

  • 抽象类:一般抽象类都是作为基类,比如说「电脑」就可以作为一个抽象类,根据抽象类派生出「台式电脑」和「笔记本电脑」2 种具体类。一般不对抽象类进行实例化。

  • 组合优于继承:不能滥用继承来拓展功能,配合组合会更灵活。同样拿「电脑」抽象类来举例,如果使用继承,区分不同类型的「电脑」我们可以派生出「台式电脑」和「笔记本电脑」,如果再增加一个维度,根据品牌又能继续细分出「联想台式电脑」、「联想笔记本电脑」、「苹果台式电脑」和「苹果笔记本电脑」等等,如果再增加一个维度继续细分下去,显然继承是无法胜任的。这个时候可以使用继承加组合方式,组合的对象也可以进行抽象化设计:

    ts
    // 品牌
    +interface Brand {
    +  // ...
    +}
    +interface Lenovo extends Brand {
    +  // ...
    +}
    +interface Apple extends Brand {
    +  // ...
    +}
    +// CPU
    +interface CPU {
    +  // ...
    +}
    +interface Inter extends CPU {
    +  // ...
    +}
    +interface AMD extends CPU {
    +  // ...
    +}
    +// 电脑
    +interface Computer {
    +  // ...
    +}
    +
    +interface DesktopComputer extends Computer {}
    +interface NotebookComputer extends Computer {}

一、UML 类图

每个模式都有相应的对象结构图,同时为了展示对象间的交互细节,有些时候会用到 UML 图来介绍其如何运行。这里不会将 UML 的各种元素都提到,只想讲讲类图中各个类之间的关系,能看懂类图中各个类之间的线条、箭头代表什么意思后,也就足够应对日常的工作和交流。同时,我们应该能将类图所表达的含义和最终的代码对应起来。有了这些知识,看后面章节的设计模式结构图就没有什么问题了。

1.1 继承

继承用一条带空心箭头的直接表示。

1.2 实现

实现关系用一条带空心箭头的虚线表示。

1.3 组合

与聚合关系一样,组合关系同样表示整体由部分构成的语义。比如公司由多个部门组成,但组合关系是一种强依赖的特殊聚合关系,如果整体不存在了,则部分也不存在了。例如,公司不存在了,部门也将不存在了。

1.4 聚合

聚合关系用于表示实体对象之间的关系,表示整体由部分构成的语义,例如一个部门由多个员工组成。与组合关系不同的是,整体和部分不是强依赖的,即使整体不存在了,部分仍然存在。例如,部门撤销了,人员不会消失,他们依然存在。

1.5 关联

关联关系是用一条直线表示的,它描述不同类的对象之间的结构关系,它是一种静态关系,通常与运行状态无关,一般由常识等因素决定的。它一般用来定义对象之间静态的、天然的结构,所以,关联关系是一种“强关联”的关系。

比如,乘车人和车票之间就是一种关联关系,学生和学校就是一种关联关系,关联关系默认不强调方向,表示对象间相互知道。如果特别强调方向,如下图,表示 A 知道 B,但 B 不知道 A。

1.6 依赖

依赖关系是用一套带箭头的虚线表示的,如 A 依赖于 B,他描述一个对象在运行期间会用到另一个对象的关系。

与关联关系不同的是,它是一种临时性的关系,通常在运行期间产生,并且随着运行时的变化,依赖关系也可能发生变化。显然,依赖也有方向,双向依赖是一种非常糟糕的结构,我们总是应该保持单向依赖,杜绝双向依赖的产生。

二、六大原则

2.1 开闭原则

一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

任何软件都需要面临一个很重要的问题,即它们的需求会随时间的推移而发生变化。当软件系统需要面对新的需求时,我们应该尽量保证系统的设计框架是稳定的。如果一个软件设计符合开闭原则,那么可以非常方便地对系统进行扩展,而且在扩展时无须修改现有代码,使得软件系统在拥有适应性和灵活性的同时具备较好的稳定性和延续性。随着软件规模越来越大,软件寿命越来越长,软件维护成本越来越高,设计满足开闭原则的软件系统也变得越来越重要。

为了满足开闭原则,需要对系统进行抽象化设计,抽象化是开闭原则的关键。在JavaC#等编程语言中,可以为系统定义一个相对稳定的抽象层,而将不同的实现行为移至具体的实现层中完成。在很多面向对象编程语言中都提供了接口、抽象类等机制,可以通过它们定义系统的抽象层,再通过具体类来进行扩展。如果需要修改系统的行为,无须对抽象层进行任何改动,只需要增加新的具体类来实现新的业务功能即可,实现在不修改已有代码的基础上扩展系统的功能,达到开闭原则的要求。

优点:实践开闭原则的优点在于可以在不改动原有代码的前提下给程序扩展功能。增加了程序的可扩展性,同时也降低了程序的维护成本。

2.2 里氏替换原则

所有引用基类对象的地方能够透明地使用其子类的对象

里氏代换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。例如:我喜欢动物,那我一定喜欢狗,因为狗是动物的子类。但是我喜欢狗,不能据此断定我喜欢动物,因为我并不喜欢老鼠,虽然它也是动物。

例如有两个类,一个类为BaseClass,另一个是SubClass类,并且SubClass类是BaseClass类的子类,那么一个方法如果可以接受一个BaseClass类型的基类对象base的话,如:method1(base),那么它必然可以接受一个BaseClass类型的子类对象submethod1(sub)能够正常运行。反过来的代换不成立,如一个方法method2接受BaseClass类型的子类对象sub为参数:method2(sub),那么一般而言不可以有method2(base),除非是重载方法。

里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

优点:可以检验继承使用的正确性,约束继承在使用上的泛滥。

2.3 依赖倒置原则

抽象不应该依赖于具体类,具体类应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。

依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。为了确保该原则的应用,一个具体类应当只实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法。

在引入抽象层后,系统将具有很好的灵活性,在程序中尽量使用抽象层进行编程,而将具体类写在配置文件中,这样一来,如果系统行为发生变化,只需要对抽象层进行扩展,并修改配置文件,而无须修改原有系统的源代码,在不修改的情况下来扩展系统的功能,满足开闭原则的要求。

优点:通过抽象来搭建框架,建立类和类的关联,以减少类间的耦合性。而且以抽象搭建的系统要比以具体实现搭建的系统更加稳定,扩展性更高,同时也便于维护。

2.4 单一职责原则

一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。

单一职责原则告诉我们:一个类不能太“累”!在软件系统中,一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。

单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关实践经验。

优点:如果类与方法的职责划分得很清晰,不但可以提高代码的可读性,更实际性地更降低了程序出错的风险,因为清晰的代码会让 bug 无处藏身,也有利于 bug 的追踪,也就是降低了程序的维护成本。

2.5 迪米特法则(最少知道原则)

一个软件实体应当尽可能少地与其他实体发生相互作用

如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。

迪米特法则要求我们在设计系统时,应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。

在将迪米特法则运用到系统设计中时,要注意下面的几点:在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及。在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限。在类的设计上,只要有可能,一个类型应当设计成不变类。在对其他类的引用上,一个对象对其他对象的引用应当降到最低。

优点:实践迪米特法则可以良好地降低类与类之间的耦合,减少类与类之间的关联程度,让类与类之间的协作更加直接。

2.6 接口分离原则

使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。

根据接口隔离原则,当一个接口太大时,我们需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干。

在使用接口隔离原则时,我们需要注意控制接口的粒度,接口不能太小,如果太小会导致系统中接口泛滥,不利于维护。接口也不能太大,太大的接口将违背接口隔离原则,灵活性较差,使用起来很不方便。

优点:避免同一个接口里面包含不同类职责的方法,接口责任划分更加明确,符合高内聚低耦合的思想。

2.7 合成复用原则(六大之外的)

尽量使用对象组合,而不是继承来达到复用的目的

合成复用原则就是在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分,新对象通过委派调用已有对象的方法达到复用功能的目的。简而言之,复用时要尽量使用组合/聚合关系(关联关系),少用继承。

在面向对象设计中,可以通过两种方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或通过继承,但首先应该考虑使用组合/聚合,组合/聚合可以使系统更加灵活,降低类与类之间的耦合度。一个类的变化对其他类造成的影响相对较少,其次才考虑继承,在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用。

优点:避免复用时滥用继承,合理使用组合关系,增加灵活性。

2.8 六大原则 - 学习心得

六大原则中,开闭原则里氏替换原则依赖倒置原则 联系比较紧密,后两者是实现开闭原则重要前提,使用中通过抽象化设计具有很好的可拓展性和可维护性。

知道最少原则 可以降低耦合,减少不必要的交互,主张设计接口和类要简单易使用,将复杂的逻辑封装并提供简单易用的接口。

单一职责原则 使项目中的类和方法根据职责细分,避免单个类负担过重。职责越多,被复用的可能性就越小或使用起来越麻烦。

接口分离原则 将功能复杂的接口细分成多个特定功能的接口,只做该做的事情,降低耦合,但是细化粒度不能太细,容易导致接口过多。单一职责原则强调单个类内部根据职责细分的设计,接口分离原则强调类之间的耦合,尽量建立最小的依赖关系。

三、模式分类

《设计模式:可复用面向对象软件的基础》一书中设计模式有 23 个,它们各具特色,每个模式都为某一个可重复的设计问题提供了一套解决方案。根据它们的用途,设计模式可分为创建型 (Creational),结构型 (Structural) 和行为型 (Behavioral) 三种,其中创建型模式主要用于描述如何创建对象,结构型模式主要用于描述如何实现类或对象的组合,行为型模式主要用于描述类或对象怎样交互以及怎样分配职责。

此外,根据某个模式主要是用于处理类之间的关系还是对象之间的关系,设计模式还可以分为类模式和对象模式。我们经常将两种分类方式结合使用,如单例模式是对象创建型模式,模板方法模式是类行为型模式。

3.1 创建型

创建型模式 (Creational Pattern) 对类的实例化过程进行了抽象,能够将模块中对象的创建和对象的使用分离。为了使结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则。

  1. 简单工厂模式(Simple Factory Pattern
  2. 工厂方法模式(Factory Method Pattern
  3. 抽象工厂模式(Abstract Factory Pattern
  4. 单例模式(Singleton Pattern
  5. 生成器模式(Builder Pattern
  6. 原型模式(Prototype Pattern

3.2 结构型

结构型模式 (Structural Pattern) 描述如何将类或者对 象结合在一起形成更大的结构,就像搭积木,可以通过 简单积木的组合形成复杂的、功能更为强大的结构。结构型模式可以分为类结构型模式和对象结构型模式:

  • 类结构型模式关心类的组合,由多个类可以组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系。

  • 对象结构型模式关心类与对象的组合,通过关联关系使得在一 个类中定义另一个类的实例对象,然后通过该对象调用其方法。根据“合成复用原则”,在系统中尽量使用关联关系来替代继 承关系,因此大部分结构型模式都是对象结构型模式。

  1. 外观模式
  2. 适配器模式
  3. 桥接模式
  4. 代理模式
  5. 装饰者模式
  6. 享元模式

3.3 行为型

行为型模式 (Behavioral Pattern) 是对在不同的对象之间划分责任和算法的抽象化。行为型模式不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。通过行为型模式,可以更加清晰地划分类与对象的职责,并研究系统在运行时实例对象之间的交互。

  1. 职责链模式
  2. 命令模式
  3. 解释器模式
  4. 迭代器模式
  5. 中介者模式
  6. 备忘录模式
  7. 观察者模式
  8. 状态模式
  9. 策略模式
  10. 模板方法模式
  11. 访问者模式

四、创建型

4.1 简单工厂模式

简单工厂模式 (Simple Factory Pattern):专门定义一个类(工厂类)来负责创建其他类的实例。可以根据创建方法的参数来返回不同类的实例,被创建的实例通常都具有共同的父类。

举例:

简单工厂模式像一个代工厂,一个工厂可以生产多种产品。举个例子,一个饮料加工厂同时帮百事可乐和可口可乐生产,加工厂根据输入参数Type来生产不同的产品。

ts
// 可乐抽象类
+interface Cola {}
+
+// 可口可乐产品类
+interface CocaCola extends Cola {}
+
+// 百事可乐产品类
+interface PepsiCola extends Cola {}
ts
// 简单工厂实现
+// SimpleFactory
+const createColaWithType = (type: number) => {
+  switch (type) {
+    case 0:
+      return new CocaCola();
+    case 1:
+      return new PepsiCola();
+    default:
+      return null;
+      break;
+  }
+};
ts
// 0 生产可口可乐
+const cocaCola: CocaCola = createColaWithType(0);
+
+// 1 生产百事可乐
+const pepsiCola: PepsiCola = createColaWithType(1);

优点:

  • 使用者只需要给工厂类传入一个正确的约定好的参数,就可以获取你所需要的对象,而不需要知道其创建细节,一定程度上减少系统的耦合。
  • 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,减少开发者的记忆成本。

缺点:

  • 如果业务上添加新产品的话,就需要修改工厂类原有的判断逻辑,这其实是违背了开闭原则的。
  • 在产品类型较多时,有可能造成工厂逻辑过于复杂。所以简单工厂模式比较适合产品种类比较少而且增多的概率很低的情况。

4.2 工厂方法模式

工厂方法模式 (Factory Method Pattern) 又称为工厂模式,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,即通过不同的工厂子类来创建不同的产品对象。

举例:

工厂方法和简单工厂有一些区别,简单工厂是由一个代工厂生产不同的产品,而工厂方法是对工厂进行抽象化,不同产品都由专门的具体工厂来生产。可口可乐工厂专门生产可口可乐,百事可乐工厂专门生产百事可乐。

ts
// 工厂抽象类
+class Cola {}
+
+// 可口可乐工厂
+class CocaCola extends Cola {}
+
+// 百事可乐工厂
+class PepsiCola extends Cola {}
ts
// 根据不同的工厂类生产不同的产品
+const cocaCola = new CocaCola();
+const pepsiCola = new PepsiCola();

优点:

  • 用户只需要关心其所需产品对应的具体工厂是哪一个即可,不需要关心产品的创建细节,也不需要知道具体产品类的类名。
  • 当系统中加入新产品时,不需要修改抽象工厂和抽象产品提供的接口,也无须修改客户端和其他的具体工厂和具体产品,而只要添加一个具体工厂和与其对应的具体产品就可以了,符合了开闭原则。

缺点:

  • 当系统中加入新产品时,除了需要提供新的产品类之外,还要提供与其对应的具体工厂类。因此系统中类的个数将成对增加,增加了系统的复杂度。

4.3 抽象工厂模式

抽象工厂模式并不直接生成实例,而是用于对产品类簇的创建。

抽象工厂模式 (Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

举例:

抽象工厂和工厂方法不同的地方在于,生产产品的工厂是抽象的。举例,可口可乐公司生产可乐的同时,也需要生产装可乐的瓶子和箱子,瓶子和箱子也是可口可乐专属定制的,同样百事可乐公司也会有这个需求。这个时候我们的工厂不仅仅是生产可乐饮料的工厂,还必须同时生产同一主题的瓶子和箱子,所以它是一个抽象的主题工厂,专门生产同一主题的不同商品。

ts
// 可乐抽象类和派生类
+class Cola {}
+
+class CocaCola extends Cola {}
+
+class PepsiCola extends Cola {}
+
+// 瓶子抽象类和派生类
+class Bottle {}
+
+class CocaColaBottle extends Bottle {}
+
+class PepsiColaBottle extends Bottle {}
+
+// 箱子抽象类和派生类
+class Box {}
+
+class CocaColaBox extends Box {}
+
+class PepsiColaBox extends Box {}
+
+// 工厂抽象类
+const Factory = {
+  createCola: () => new Cola(),
+  createBottle: () => new Bottle(),
+  createBox: () => new Box(),
+};
+
+// 可口可乐主题工厂
+const CocaColaFactory = {
+  createCola: () => new CocaCola(),
+  createBottle: () => new CocaColaBottle(),
+  createBox: () => new CocaColaBox(),
+};
+
+// 百事可乐主题工厂
+const PepsiColaFactory = {
+  createCola: () => new PepsiCola(),
+  createBottle: () => new PepsiColaBottle(),
+  createBox: () => new PepsiColaBox(),
+};
ts
// 可口可乐主题
+const cocaCola = CocaColaFactory.createCola();
+const cocaColaBottle = CocaColaFactory.createBottle();
+const cocaColaBox = CocaColaFactory.createBox();
+
+// 百事可乐主题
+const pepsiCola = PepsiColaFactory.createCola();
+const pepsiColaBottle = PepsiColaFactory.createBottle();
+const pepsiColaBox = PepsiColaFactory.createBox();

优点:

  • 具体产品在应用层代码隔离,不需要关心产品细节。只需要知道自己需要的产品是属于哪个工厂的即可 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。

缺点:

  • 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。

4.4 单例模式

单例模式 (Singleton Pattern):单例模式确保某一个类只有一个实例,并提供一个访问它的全剧访问点。

举例:

单例模式下,对应类只能生成一个实例。就像一个王国只能有一个国王,一旦王国里的事务多起来,这唯一的国王也容易职责过重。

ts
class Singleton {}
+
+function createSingleton() {
+  let instance;
+  return function () {
+    if (!instance) return new Singleton();
+    return instance;
+  };
+}

优点:

  • 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它。
  • 因为该类在系统内存中只存在一个对象,所以可以节约系统资源。

缺点:

  • 由于单例模式中没有抽象层,因此单例类很难进行扩展。
  • 对于有垃圾回收系统的语言 Java,C# 来说,如果对象长时间不被利用,则可能会被回收。那么如果这个单例持有一些数据的话,在回收后重新实例化时就不复存在了。

4.5 生成器模式

生成器模式 (Builder Pattern):也叫创建者模式,它将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

工厂模式主要是为了创建对象实例或者类簇(抽象工厂),关心的是最终产出 (创建) 的是什么,而不关心创建的过程。而建造者模式关心的是创建这个对象的整个过程,甚至于创建对象的每一个细节。

举例:

生成器模式的主要角色如下:

  1. 生成器:接口生命再所有类型生成器中通用的产品构造步骤
  2. 具体生成器:提供构造过程的不同实现。具体生成器也可以构造不遵循通用接口的产品
  3. 产品:是最终生成的对象。由不同生成器构造的产品无需属于同一类层次构造或接口
  4. 指挥者:定义调用构造步骤的顺序,这样你就可以创建和服用特定的产品配置
  5. 客户端:必须将某个生成器对象与主管类关联,一般情况下,你只需要通过指挥者类构造函数的参数进行一次性关联即可
ts
// 抽象建造者
+abstract class Builder {
+  public abstract buildPartA(): void;
+  public abstract buildPartB(): void;
+  public abstract buildPartC(): void;
+  public abstract buildProduct(): Product;
+}
+
+// 具体建造者
+class ConcreteBuilder extends Builder {
+  private product: Product;
+  constructor(product: Product) {
+    super();
+    this.product = product;
+  }
+
+  public buildPartA(): void {}
+  public buildPartB(): void {}
+  public buildPartC(): void {}
+
+  // 最终组建一个产品
+  public buildProduct(): Product {
+    return this.product;
+  }
+}
+
+// 产品角色
+class Product {
+  public doSomething(): void {
+    // 独立业务
+  }
+}
+
+// 指挥者
+class Director {
+  private _builder: Builder;
+  constructor(builder: Builder) {
+    this._builder = builder;
+  }
+
+  set builder(builder: Builder) {
+    this._builder = builder;
+  }
+
+  // 将处理建造的流程交给指挥者
+  public constructorProduct() {
+    this._builder.buildPartA();
+    this._builder.buildPartB();
+    this._builder.buildPartC();
+    return this._builder.buildProduct();
+  }
+}
+
+// 使用
+const builder: Builder = new ConcreteBuilder(new Product());
+const director: Director = new Director(builder);
+const product: Product = director.constructorProduct();

优点:

  • 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
  • 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
  • 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
  • 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。

缺点:

  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。

4.6 原型模式

原型模式(Prototype Pattern): 用原型实例指向创建对象的类,使用于创建新的对象的类的共享原型的属性与方法。

举例:

原型模式就像复印技术,根据原对象复印出一个新对象,并根据需求对新对象进行微调。

ts
// 因为不是构造函数,所以不用大写
+const car = {
+  drive: function () {},
+  name: '马自达 3',
+};
+
+// 使用 Object.create 创建一个新车 x
+const anotherCar = Object.create(someCar);
+anotherCar.name = '丰田佳美';
ts
const vehiclePrototype = {
+  init: function (carModel) {
+    this.model = carModel;
+  },
+  getModel: function () {
+    console.log('车辆模具是:' + this.model);
+  },
+};
+
+function vehicle(model) {
+  function F() {}
+  F.prototype = vehiclePrototype;
+
+  const f = new F();
+
+  f.init(model);
+  return f;
+}
+
+const car = vehicle('福特 Escort');
+car.getModel();

优点:

  • 可以利用原型模式简化对象的创建过程,尤其是对一些创建过程繁琐,包含对象层级比较多的对象来说,使用原型模式可以节约系统资源,提高对象生成的效率。
  • 可以很方便得通过改变值来生成新的对象:有些对象之间的差别可能只在于某些值的不同;用原型模式可以快速复制出新的对象并手动修改值即可。

缺点:

  • 对象包含的所有对象都需要配备一个克隆的方法,这就使得在对象层级比较多的情况下,代码量会很大,也更加复杂。

五、结构型

5.1 装饰模式

装饰模式 (Decorator Pattern) :向一个现有的对象添加新的功能,同时又不改变其结构的设计模式被称为装饰器模式,它是作为现有的类的一个包装。

可以将装饰器理解为游戏人物购买的装备,例如 LOL 中的英雄刚开始游戏时只有基础的攻击力和法强。但是在购买的装备后,在触发攻击和技能时,能够享受到装备带来的输出加成。我们可以理解为购买的装备给英雄的攻击和技能的相关方法进行了装饰。

举例:

装饰模式贴合开闭原则,在不改变原有类的情况下,对父类进行改造或新增功能。

装饰类

ts
@annotation
+class MyClass {}
+
+function annotation(target) {
+  target.annotated = true;
+}

装饰方法或属性

js
class MyClass {
+  @readonly
+  method() {}
+}
+
+function readonly(target, name, descriptor) {
+  descriptor.writable = false;
+  return descriptor;
+}

优点:

  • 比继承更加灵活:不同于在编译期起作用的继承;装饰者模式可以在运行时扩展一个对象的功能。另外也可以通过配置文件在运行时选择不同的装饰器,从而实现不同的行为。也可以通过不同的组合,可以实现不同效果。
  • 符合“开闭原则”:装饰者和被装饰者可以独立变化。用户可以根据需要增加新的装饰类,在使用时再对其进行组合,原有代码无须改变。

缺点:

  • 装饰者模式需要创建一些具体装饰类,会增加系统的复杂度。

5.2 外观模式

外观模式 (Facade Pattern):外观模式定义了一个高层接口,为子系统中的一组接口提供一个统一的接口。使得子系统更容易使用,不仅简化类中的接口,而且实现调用者和接口的解耦。外观模式又称为门面模式,它是一种结构型设计模式模式。

举例:

外观模式提供了简单明确的接口,但是在内部众多子系统功能进行整合。就像图片缓存,内部包含了涉及到其他子系统的如缓存、下载等处理,外观模式将这些复杂的逻辑都隐藏了。在兼容浏览器事件绑定,你只需要调一个addMyEvent接口就可以了,达到解耦合的目的。

js
const addMyEvent = function (el, ev, fn) {
+  if (el.addEventListener) {
+    el.addEventListener(ev, fn, false);
+  } else if (el.attachEvent) {
+    el.attachEvent('on' + ev, fn);
+  } else {
+    el['on' + ev] = fn;
+  }
+};

优点:

  • 实现了客户端与子系统间的解耦:客户端无需知道子系统的接口,简化了客户端调用子系统的调用过程,使得子系统使用起来更加容易。同时便于子系统的扩展和维护。
  • 符合迪米特法则(最少知道原则):子系统只需要将需要外部调用的接口暴露给外观类即可,而且他的接口则可以隐藏起来。

缺点:

  • 违背了开闭原则:在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的代码。

5.3 代理模式

代理模式 (Proxy Pattern) :为某个对象提供一个代理,并由这个代理对象控制对原对象的访问。

举例:

代理模式像一个房屋中介,买家只能通过中介来买房,代理具备被代理类的所有功能,就像房东有卖房功能,中介也具有卖房功能。此外代理实例还可以帮助被代理实例进行一些额外处理,比如中介可以帮助房东筛选优质买家的功能,帮助房东 pass 掉一些不符合条件的买家。还有消息队列也是该模式。

参考koa中的代理模式,把response上的一些属性和方法代理出来,方便使用

js
/**
+ * Response delegation.
+ */
+const delegate = require('delegates');
+
+const prototype = (module.exports = {});
+
+delegate(prototype, 'response')
+  .method('attachment')
+  .method('redirect')
+  .method('remove')
+  .method('vary')
+  .method('has')
+  .method('set')
+  .method('append')
+  .method('flushHeaders')
+  .access('status')
+  .access('message')
+  .access('body')
+  .access('length')
+  .access('type')
+  .access('lastModified')
+  .access('etag')
+  .getter('headerSent')
+  .getter('writable');

context,request,response做一个代理,保护真正的context,request,response

js
this.context = Object.create(context);
+this.request = Object.create(request);
+this.response = Object.create(response);

优点:

  • 降低系统的耦合度:代理模式能够协调调用者和被调用者,在一定程度上降低了系 统的耦合度。
  • 不同类型的代理可以对客户端对目标对象的访问进行不同的控制:
    • 远程代理,使得客户端可以访问在远程机器上的对象,远程机器 可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。
    • 虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。
    • 保护代理可以控制客户端对真实对象的使用权限。

缺点:

  • 由于在客户端和被代理对象之间增加了代理对象,因此可能会让客户端请求的速度变慢。

5.4 享元模式

享元模式 (Flyweight Pattern):享元模式是一种优化程序性能的模式,本质为减少对象创建的个数。运用共享技术复用大量细粒度的对象,降低程序内存的占用,提高程序的性能。以下情况可以使用享元模式:有大量相似的对象,占用了大量内存。对象中大部分状态可以抽离为外部状态。

举例:

举例,音乐服务根据收费划分出免费用户和会员用户,免费用户只能听部分免费音乐,会员用户可以听全部的音乐,并且可以下载。虽然权限上二者间有一些区别,但是他们所享受的音乐来是自于同一个音乐库,这样所有的音乐都只需要保存一份就可以了。另外如果出现音乐库里没有的音乐时,则需要新增该音乐,然后其他服务也可以享受新增的音乐,相当于享元池或缓存池的功能。

享元模式区保证共享内部状态如音乐库,而外部状态根据不同需求定制如各种访问权限,使用中不能去改变内部状态,以达到共享的目的。

ts
// 音乐服务
+const MusicService = {}
+
+// 共享的音乐库
+const musicLibrary = {};
+
+// 听音乐
+const listenToMusic = (music) => {
+    ...
+}
+// 下载音乐
+const downloadMusic = (music) => {
+    ...
+}
+
+
+// 免费音乐服务
+const FreeMusicService = {
+    listenFreeMusic: (music)=>{
+        if(isMusicFree(music)){
+            // 如果是免费则播放
+            listenToMusic()
+        }else{
+    	    // 如果是收费音乐,则提示用户升级 Vip
+            console.log("please upgrade to Vip")
+        }
+    }
+}
+
+
+// Vip 音乐服务
+const VipMusicService = {
+    // 可以听全部的音乐
+    listenMusic
+    // 可以下载音乐
+    downloadMusic
+}

优点:

  • 使用享元模可以减少内存中对象的数量,使得相同对象或相似对象在内存中只保存一份,降低系统的使用内存,也可以提性能。
  • 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。

缺点:

  • 使用享元模式需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
  • 对象在缓冲池中的复用需要考虑线程问题。

5.5 桥接模式

桥接模式 (Simple Factory Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。

举例:

球和人都可以进行运动,但球有运动和颜色,人可以运动和说话。对共同部分进行抽象。

js
class Speed {
+  // 运动模块
+  constructor(x, y) {
+    this.x = x;
+    this.y = y;
+  }
+  run() {
+    console.log(\`运动起来 \${this.x} + \${this.y}\`);
+  }
+}
+
+class Color {
+  // 着色模块
+  constructor(cl) {
+    this.color = cl;
+  }
+  draw() {
+    console.log(\`绘制颜色 \${this.color}\`);
+  }
+}
+
+class Speak {
+  constructor(wd) {
+    this.word = wd;
+  }
+  say() {
+    console.log(\`说话 \${this.word}\`);
+  }
+}
+
+class Ball {
+  // 创建球类,可以着色和运动
+  constructor(x, y, cl) {
+    this.speed = new Speed(x, y);
+    this.color = new Color(cl);
+  }
+  init() {
+    this.speed.run();
+    this.color.draw();
+  }
+}
+
+class Man {
+  // 人类,可以运动和说话
+  constructor(x, y, wd) {
+    this.speed = new Speed(x, y);
+    this.speak = new Speak(wd);
+  }
+  init() {
+    this.speed.run();
+    this.speak.say();
+  }
+}
+
+const man = new Man(1, 2, 'hello ?');
+man.init(); // 运动起来 1 + 2      说话 hello?

优点:

  • 扩展性好,符合开闭原则:将抽象与实现分离,让二者可以独立变化

缺点:

  • 在设计之前,需要识别出两个独立变化的维度。

5.6 适配器模式

适配器模式 (Adapter Pattern) :适配器模式是用来解决两个接口不兼容的情况,不需要改变已有的接口,通过包装一层的方式,实现两个接口正常协作。当我们试图调用模块或者对象的某个接口时,却发现这个接口的格式并不符合目前的需求,则可以用适配器模式。

举例:

事件绑定兼容各浏览器

js
function addEvent(ele, event, callback) {
+    if (ele.addEventListener) {
+      ele.addEventListener(event, callback)
+    } else if(ele.attachEvent) {
+      ele.attachEvent('on' + event, callback)
+    } else {
+      ele['on' + event] = callback
+    }
+  }
+

优点:

  • 符合开闭原则:使用适配器而不需要改变现有类,提高类的复用性。
  • 目标类和适配器类解耦,提高程序扩展性。

缺点:

  • 增加了系统的复杂性

六、行为型

6.1 职责链模式

职责链模式 (Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。职责链模式是一种对象行为型模式。类似多米诺骨牌,通过请求第一个条件,会持续执行后续的条件,直到返回结果为止。

举例:

场景:某电商针对已付过定金的用户有优惠政策,在正式购买后,已经支付过 500 元定金的用户会收到 100 元的优惠券,200 元定金的用户可以收到 50 元优惠券,没有支付过定金的用户只能正常购买。

js
const order500 = function (orderType, pay, stock) {
+  if (orderType === 1 && pay == true) {
+    console.log('500 元定金预购,得到 100 元优惠劵');
+  } else {
+    return 'nextSuccess';
+  }
+};
+const order200 = function (orderType, pay, stock) {
+  if (orderType === 2 && pay === true) {
+    console.log('200 元定金预购,得到 50 元優惠卷');
+  } else {
+    return 'nextSuccess';
+  }
+};
+const orderCommon = function (orderType, pay, stock) {
+  if (orderType == 3 && stock > 0) {
+    console.log('普通購買,无優惠卷');
+  } else {
+    console.log('库存不够');
+  }
+};
+//链路代码
+const chain = function (fn) {
+  this.fn = fn;
+  this.successor = null;
+};
+chain.prototype.setNext = function (successor) {
+  this.successor = successor;
+};
+chain.prototype.init = function () {
+  const result = this.fn.apply(this, arguments);
+  if (result == 'nextSuccess') {
+    this.successor.init.apply(this.successor, arguments);
+  }
+};
+const order500New = new chain(order500);
+const order200New = new chain(order200);
+const orderCommonNew = new chain(orderCommon);
+order500New.setNext(order200New);
+order200New.setNext(orderCommonNew);
+order500New.init(3, true, 500); // 普通购买,无优惠券

优点:

  • 职责链模式使得一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构,由客户端负责链的创建,降低了系统的耦合度。
  • 请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的引用,可简化对象的相互连接。
  • 在给对象分派职责时,职责链可以给我们更多的灵活性,可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的职责。
  • 在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新建链即可,从这一点来看是符合“开闭原则”的。

缺点:

  • 由于一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理。
  • 对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响,而且在进行代码调试时不太方便。
  • 如果建链不当,可能会造成循环调用,将导致系统陷入死循环。

6.2 命令模式

命令模式 (Command Pattern):将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;命令模式是一种对象行为型模式,其别名为动作 (Action) 模式或事务 (Transaction) 模式。

命令模式由三种角色构成:

  1. 发布者 invoker(发出命令,调用命令对象,不知道如何执行与谁执行);
  2. 接收者 receiver (提供对应接口处理请求,不知道谁发起请求);
  3. 命令对象 command(接收命令,调用接收者对应接口处理发布者的请求)。 发布者 invoker 和接收者 receiver 各自独立,将请求封装成命令对象 command,请求的具体执行由命令对象 command 调用接收者 receiver 对应接口执行。

举例:

和之前代理模式中的举例有些相似,不过命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。例如遥控器是一个调用者,不同按钮代表不同的命令,而电视是接收者。

js
class Receiver {
+  // 接收者类
+  execute() {
+    console.log('接收者执行请求');
+  }
+}
+
+class Command {
+  // 命令对象类
+  constructor(receiver) {
+    this.receiver = receiver;
+  }
+  execute() {
+    // 调用接收者对应接口执行
+    console.log('命令对象->接收者->对应接口执行');
+    this.receiver.execute();
+  }
+}
+
+class Invoker {
+  // 发布者类
+  constructor(command) {
+    this.command = command;
+  }
+  invoke() {
+    // 发布请求,调用命令对象
+    console.log('发布者发布请求');
+    this.command.execute();
+  }
+}
+
+const warehouse = new Receiver(); // 仓库
+const order = new Command(warehouse); // 订单
+const client = new Invoker(order); // 客户
+client.invoke();

优点:

  • 降低系统的耦合度。由于请求者与接收者之间不存在直接引用,因此请求者与接收者之间实现完全解耦,相同的请求者可以对应不同的接收者,同样,相同的接收者也可以供不同的请求者使用,两者之间具有良好的独立性。
  • 新的命令可以很容易地加入到系统中。由于增加新的具体命令类不会影响到其他类,因此增加新的具体命令类很容易,无须修改原有系统源代码,甚至客户类代码,满足“开闭原则”的要求。
  • 可以比较容易地设计一个命令队列或宏命令(组合命令)。
  • 为请求的撤销 (Undo) 和恢复 (Redo) 操作提供了一种设计和实现方案。

缺点:

  • 使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个对请求接收者的调用操作都需要设计一个具体命令类,因此在某些系统中可能需要提供大量的具体命令类,这将影响命令模式的使用。

6.3 解释器模式

解释器模式 (Interpreter Pattern):定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。解释器模式是一种类行为型模式。

举例:

给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。

js
class Context {
+  constructor() {
+    this._list = []; // 存放 终结符表达式
+    this._sum = 0; // 存放 非终结符表达式 (运算结果)
+  }
+
+  get sum() {
+    return this._sum;
+  }
+  set sum(newValue) {
+    this._sum = newValue;
+  }
+  add(expression) {
+    this._list.push(expression);
+  }
+  get list() {
+    return [...this._list];
+  }
+}
+
+class PlusExpression {
+  interpret(context) {
+    if (!(context instanceof Context)) {
+      throw new Error('TypeError');
+    }
+    context.sum = ++context.sum;
+  }
+}
+class MinusExpression {
+  interpret(context) {
+    if (!(context instanceof Context)) {
+      throw new Error('TypeError');
+    }
+    context.sum = --context.sum;
+  }
+}
+
+/** 以下是测试代码 **/
+const context = new Context();
+
+// 依次添加:加法 | 加法 | 减法 表达式
+context.add(new PlusExpression());
+context.add(new PlusExpression());
+context.add(new MinusExpression());
+
+// 依次执行:加法 | 加法 | 减法 表达式
+context.list.forEach((expression) => expression.interpret(context));
+console.log(context.sum);

优点:

  • 易于改变和扩展文法。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
  • 每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
  • 实现文法较为容易。在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成节点类代码。
  • 增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合“开闭原则”。

缺点:

  • 对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。
  • 执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。

6.4 迭代器模式

迭代器模式 (Iterator Pattern):一个相对简单的模式,目前绝大多数语言都内置了迭代器,以至于大家都不觉得这是一种设计模式。迭代器并不只迭代数组,迭代器可以中止。提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标 (Cursor)。迭代器模式是一种对象行为型模式。

举例:

迭代器帮助请求方获取数据,避免直接操作数据聚合类,使数据聚合类专注存储数据。具体应用有分页等功能,分页功能的迭代器将专门负责操作分页数据,将操作逻辑和数据源分离。

js
var each = function (arr, callback) {
+  for (var i = 0, len = arr.length; i < len; i++) {
+    callback.call(arr[i], i, arr[i]);
+  }
+};
+
+each([1, 2, 3, 4, 5], function (i, el) {
+  console.log('index: ', i);
+  console.log('item: ', el);
+});

优点:

  • 它支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法,我们也可以自己定义迭代器的子类以支持新的遍历方式。
  • 迭代器简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计。
  • 在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”的要求。

缺点:

  • 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
  • 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展,例如 JDK 内置迭代器 Iterator 就无法实现逆向遍历,如果需要实现逆向遍历,只能通过其子类 ListIterator 等来实现,而 ListIterator 迭代器无法用于操作 Set 类型的聚合对象。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是件很容易的事情。

6.5 中介者模式

中介者模式(Mediator Pattern):对象和对象之间借助第三方中介者进行通信。用一个中介对象(中介者)来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。

举例:

中介者模式将一个网状的系统结构变成一个以中介者对象为中心的星形结构,在这个星型结构中,使用中介者对象与其他对象的一对多关系来取代原有对象之间的多对多关系。所有成员通过中介者交互,方便拓展新的成员,例如下面的例子,一场测试结束后,公布结果:告知解答出题目的人挑战成功,否则挑战失败。在这段代码中 A、B、C 之间没有直接发生关系,而是通过另外的 playerMiddle 对象建立链接,姑且将之当成是中介者模式了。

js
const player = function (name) {
+  this.name = name;
+  playerMiddle.add(name);
+};
+player.prototype.win = function () {
+  playerMiddle.win(this.name);
+};
+player.prototype.lose = function () {
+  playerMiddle.lose(this.name);
+};
+const playerMiddle = (function () {
+  //将就用下这个 demo, 这个函数充当中介者
+  const players = [];
+  const winArr = [];
+  const loseArr = [];
+  return {
+    add: function (name) {
+      players.push(name);
+    },
+    win: function (name) {
+      winArr.push(name);
+      if (winArr.length + loseArr.length === players.length) {
+        this.show();
+      }
+    },
+    lose: function (name) {
+      loseArr.push(name);
+      if (winArr.length + loseArr.length === players.length) {
+        this.show();
+      }
+    },
+    show: function () {
+      for (let winner of winArr) {
+        console.log(winner + '挑戰成功;');
+      }
+      for (let loser of loseArr) {
+        console.log(loser + '挑战失败;');
+      }
+    },
+  };
+})();
+const a = new player('A 选手');
+const b = new player('B 选手');
+const c = new player('C 选手');
+a.win();
+b.lose();
+c.win();
+// A 选手挑战成功;
+// B 选手挑战成功;
+// C 选手挑战失败;

优点:

  • 中介者模式简化了对象之间的交互,它用中介者和同事的一对多交互代替了原来同事之间的多对多交互,一对多关系更容易理解、维护和扩展,将原本难以理解的网状结构转换成相对简单的星型结构。
  • 中介者模式可将各同事对象解耦。中介者有利于各同事之间的松耦合,我们可以独立的改变和复用每一个同事和中介者,增加新的中介者和新的同事类都比较方便,更好地符合“开闭原则”。
  • 可以减少子类生成,中介者将原本分布于多个对象间的行为集中在一起,改变这些行为只需生成新的中介者子类即可,这使各个同事类可被重用,无须对同事类进行扩展。

缺点:

  • 在具体中介者类中包含了大量同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。

6.6 备忘录模式

备忘录模式 (Memento Pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便日后对象使用或者对象恢复到以前的某个状态。它是一种对象行为型模式,其别名为 Token。

举例:

备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,当前很多软件都提供了撤销操作,其中就使用了备忘录模式。

当我们开发一个分页组件的时候,点击下一页获取新的数据,但是当点击上一页时,又重新获取数据,造成无谓的流量浪费,这时可以对数据进行缓存。

js
// 备忘录模式伪代码
+var Page = function () {
+  // 通过 cache 对象缓存数据
+  var cache = {};
+  return function (page, fn) {
+    if (cache[page]) {
+      showPage(page, cache[page]);
+    } else {
+      $.post('/url', function (data) {
+        showPage(page, data);
+        cache[page] = data;
+      });
+    }
+    fn && fn();
+  };
+};

优点:

  • 它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。
  • 备忘录实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动。备忘录保存了原发器的状态,采用列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。

缺点:

  • 资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源。

6.7 观察者模式

观察者模式 (Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布 - 订阅(Publish/Subscribe)模式、模型 - 视图(Model/View)模式、源 - 监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。

举例:

观察者模式是使用频率最高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。

JavaScript中观察者模式的实现主要用事件模型,DOM事件。

js
// 发布者
+var pub = function () {
+  console.log('欢迎订阅!');
+};
+// 订阅者
+var sub = document.body;
+
+// 订阅者实现订阅
+sub.addEventListener('click', pub, false);

优点:

  • 观察者模式可以实现表示层和数据逻辑层的分离,定义了稳定的消息更新传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层充当具体观察者角色。
  • 观察者模式在观察目标和观察者之间建立一个抽象的耦合。观察目标只需要维持一个抽象观察者的集合,无须了解其具体观察者。由于观察目标和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
  • 观察者模式支持广播通信,观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
  • 观察者模式满足“开闭原则”的要求,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便。

缺点:

  • 如果一个观察目标对象有很多直接和间接观察者,将所有的观察者都通知到会花费很多时间。
  • 如果在观察者和观察目标之间存在循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
  • 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

6.8 状态模式

状态模式 (State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象 (Objects for States),其实就是用一个对象或者数组记录一组状态,每个状态对应一个实现,实现的时候根据状态挨个去运行实现。状态模式是一种对象行为型模式。

举例:

状态模式用于解决复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,所以对象在不同状态下具有不同行为时可以使用状态模式。状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化。

比如超级玛丽,就可能同时有好几个状态比如 跳跃,移动,射击,蹲下 等,如果对这些动作一个个进行处理判断,需要多个 if-else 或者 switch 不仅丑陋不说,而且在遇到有组合动作的时候,实现就会变的更为复杂,这里可以使用状态模式来实现。

状态模式的思路是:首先创建一个状态对象或者数组,内部保存状态变量,然后内部封装好每种动作对应的状态,然后状态对象返回一个接口对象,它可以对内部的状态修改或者调用。

js
class SuperMarry {
+  constructor() {
+    this._currentState = [];
+    this.states = {
+      jump() {
+        console.log('跳跃!');
+      },
+      move() {
+        console.log('移动!');
+      },
+      shoot() {
+        console.log('射击!');
+      },
+      squat() {
+        console.log('蹲下!');
+      },
+    };
+  }
+
+  change(arr) {
+    // 更改当前动作
+    this._currentState = arr;
+    return this;
+  }
+
+  go() {
+    console.log('触发动作');
+    this._currentState.forEach((T) => this.states[T] && this.states[T]());
+    return this;
+  }
+}
+
+new SuperMarry()
+  .change(['jump', 'shoot'])
+  .go() // 触发动作  跳跃!射击!
+  .go() // 触发动作  跳跃!射击!
+  .change(['squat'])
+  .go(); // 触发动作  蹲下!

优点:

  • 封装了状态的转换规则,在状态模式中可以将状态的转换代码封装在环境类或者具体状态类中,可以对状态转换代码进行集中管理,而不是分散在一个个业务方法中。
  • 将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。
  • 允许状态转换逻辑与状态对象合成一体,而不是提供一个巨大的条件语句块,状态模式可以让我们避免使用庞大的条件语句来将业务方法和状态转换代码交织在一起。
  • 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点:

  • 状态模式的使用必然会增加系统中类和对象的个数,导致系统运行开销增大。
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,增加系统设计的难度。
  • 状态模式对“开闭原则”的支持并不太好,增加新的状态类需要修改那些负责状态转换的源代码,否则无法转换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

6.9 策略模式

策略模式 (Strategy Pattern):定义一些列算法,把他们封装起来,并且可以相互替换。就是把看似毫无联系的代码提取封装、复用,使之更容易被理解和拓展。常见的用于一次 if 判断、switch 枚举、数据字典等流程判断语句中。也称为政策模式 (Policy)。策略模式是一种对象行为型模式。

举例:

使用策略模式时,我们可以定义一些策略类,每一个策略类中封装一种具体的算法。在这里,每一个封装算法的类我们都可以称之为一种策略,根据传入不同的策略类,使环境类执行不同策略类中的算法。

在游戏中,我们每玩完一局游戏都有对用户进行等级评价,比如 S 级 4 倍经验,A 级 3 倍经验,B 级 2 倍经验,其他 1 倍经验,用函数来表达如下:

js
// 改为策略模式 分成两个函数来写
+const strategy = {
+  S: function (experience) {
+    return 4 * experience;
+  },
+  A: function (experience) {
+    return 3 * experience;
+  },
+  B: function (experience) {
+    return 2 * experience;
+  },
+};
+// getExperience 可以复用
+function getExperience(strategy, level, experience) {
+  return level in strategy ? strategy[level](experience) : experience;
+}
+var s = getExperience(strategy, 'S', 100);
+var a = getExperience(strategy, 'A', 100);
+console.log(s, a); // 400 300
js
// 指令处理集合
+var compileUtil = {
+    // v-text 更新视图原理
+    text: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'text');
+    },
+    // v-html 更新视图原理
+    html: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'html');
+    },
+    // v-class 绑定原理
+    class: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'class');
+    },
+    bind: function(node, vm, exp, dir) {
+        // 不同指令触发视图更新
+        var updaterFn = updater[dir + 'Updater'];
+        updaterFn && updaterFn(node, this._getVMVal(vm, exp));
+        new Watcher(vm, exp, function(value, oldValue) {
+            updaterFn && updaterFn(node, value, oldValue);
+        });
+    }
+    ......
+}

优点:

  • 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
  • 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族,恰当使用继承可以把公共的代码移到抽象策略类中,从而避免重复的代码。
  • 策略模式提供了一种可以替换继承关系的办法。如果不使用策略模式,那么使用算法的环境类就可能会有一些子类,每一个子类提供一种不同的算法。但是,这样一来算法的使用就和算法本身混在一起,不符合“单一职责原则”,决定使用哪一种算法的逻辑和该算法本身混合在一起,从而不可能再独立演化;而且使用继承无法实现算法或行为在程序运行时的动态切换。
  • 使用策略模式可以避免多重条件选择语句。多重条件选择语句不易维护,它把采取哪一种算法或行为的逻辑与算法或行为本身的实现逻辑混合在一起,将它们全部硬编码 (Hard Coding) 在一个庞大的多重条件选择语句中,比直接继承环境类的办法还要原始和落后。
  • 策略模式提供了一种算法的复用机制,由于将算法单独提取出来封装在策略类中,因此不同的环境类可以方便地复用这些策略类。

缺点:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
  • 策略模式将造成系统产生很多具体策略类,任何细小的变化都将导致系统要增加一个新的具体策略类。
  • 无法同时在客户端使用多个策略类,也就是说,在使用策略模式时,客户端每次只能使用一个策略类,不支持使用一个策略类完成部分功能后再使用另一个策略类来完成剩余功能的情况。

6.10 模板方法模式

模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

举例:

模板方法模式的使用场景

  • 模板方法模式常被架构师用于搭建项目的框架,架构师定好了框架的骨架,程序员继承框架的结构之后,负责往里面填空
  • 钩子方法:各种框架中的钩子函数往往在初始化时就规定各个钩子函数的名称以及执行时机,对于使用者只需要在钩子函数中注入自定义逻辑代码即可
  • 回调函数:回调函数在特定的时机执行,但是具体的操作交给具体的函数实现。把变化的部分封装成一个函数剩下的就成了模板

模板方法模式具体应用又分为三类:

  • 抽象方法:一个抽象方法由抽象类声明、由其具体子类实现。

  • 具体方法:一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。

  • 钩子方法:一个钩子方法由一个抽象类或具体类声明并实现,而其子类可能会加以扩展。通常在父类中给出的实现是一个空实现,并以该空实现作为方法的默认实现,当然钩子方法也可以提供一个非空的默认实现。通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制。

泡一杯咖啡

先我们先来泡一杯咖啡,一般来说,泡咖啡的步骤通常如下:

1.先把水煮沸;

2.用沸水冲泡咖啡;

3.把咖啡倒进杯子;

4.加糖和牛奶。

我们用 es5 来得到一杯香浓的咖啡吧:

js
var Coffee = function () {};
+Coffee.prototype.boilWater = function () {
+  console.log('水煮开了');
+};
+Coffee.prototype.brewCoffeeGriends = function () {
+  console.log('用沸水冲泡咖啡');
+};
+Coffee.prototype.pourInCup = function () {
+  console.log('把咖啡倒进杯子');
+};
+Coffee.prototype.addSugarAndMilk = function () {
+  console.log('加糖和牛奶');
+};
+// 封装 将实现的细节交给类的内部
+Coffee.prototype.init = function () {
+  this.boilWater();
+  this.brewCoffeeGriends();
+  this.pourInCup();
+  this.addSugarAndMilk();
+};
+var coffee = new Coffee();
+coffee.init();

泡一壶茶

其实呢,泡茶的步骤跟泡咖啡的步骤相差不大,大致是这样的:

1.把水煮沸;

2.用沸水浸泡茶叶;

3.把茶水倒进杯子;

4.加柠檬。

来,咱用 es6 来泡茶:

js
class Tea {
+  constructor() {}
+  boilWater() {
+    console.log('把水烧开');
+  }
+  steepTeaBag() {
+    console.log('浸泡茶叶');
+  }
+  pourInCup() {
+    console.log('倒进杯子');
+  }
+  addLemon() {
+    console.log('加柠檬');
+  }
+  init() {
+    this.boilWater();
+    this.steepTeaBag();
+    this.pourInCup();
+    this.addLemon();
+  }
+}
+var tea = new Tea();
+tea.init();

现在到了思考的时间,我们刚刚泡了一杯咖啡和一壶茶,有没有觉得这两个过程是大同小异的。我们能很容易的就找出他们的共同点,不同点就是原料不同嘛,茶和咖啡,我们可以把他们抽象为"饮料"哇;泡的方式不同嘛,一个是冲泡,一个是浸泡,我们可以把这个行为抽象为"泡";加入的调料也不同咯,加糖和牛奶,加柠檬,它们也可以抽象为"调料"吖。

这么一分析,是不是很清楚了吖,我们整理一下就是:

1.把水煮沸;

2.用沸水冲泡饮料;

3.把饮料倒进杯子;

4.加调料。

大家请注意!大家请注意!主角来了!之前我们已经扔出了概念,所以我们现在可以创建一个抽象父类来表示泡一杯饮料的过程。那么,抽象父类?

抽象类?

抽象类是不能被实例化的,一定是用来继承的。继承了抽象类的所有子类都将拥有跟抽象类一致的接口方法,抽象类的主要作用就是为它的子类定义这些公共接口。

通过上面分析,这里具体来说就是要把泡茶和泡咖啡的共同步骤共同点找出来,封装到父类,也就是抽象类中,然后不同的步骤写在子类中,也就是茶和咖啡中。抽象类既然不能被实例化,不怕啊,子类就是他的实例化。

泡饮料啦!

js
var Beverage = function () {};
+Beverage.prototype.boilWater = function () {
+  console.log('把水煮沸');
+};
+Beverage.prototype.brew = function () {};
+Beverage.prototype.pourInCup = function () {};
+Beverage.prototype.addCondiments = function () {};
+// 抽象方法
+Beverage.prototype.init = function () {
+  this.boilWater();
+  this.brew();
+  this.pourInCup();
+  this.addCondiments();
+};
+var Coffee = function () {
+  // 将父类的构造方法拿来执行一下
+  Beverage.apply(this, arguments);
+  // 就像 es6 的 super 执行 执行后 this 才会有对象的属性
+};
+Coffee.prototype = new Beverage();
+var coffee = new Coffee();
+coffee.init();
+var Tea = function () {};
+Tea.prototype = new Beverage();
+Tea.prototype.brew = function () {
+  console.log('用沸水浸泡茶叶');
+};
+Tea.prototype.pourInCup = function () {
+  console.log('把茶叶倒进杯子');
+};
+Tea.prototype.addCondiments = function () {
+  console.log('加柠檬');
+};
+var tea = new Tea();
+tea.init();

这里既泡了咖啡又泡了茶,是不是没有之前那么繁琐呢,这里的代码可是很高级的呢。

这里用一个父类 Beverage 来表示 Coffee 和 Tea,然后子类就是后面的 Coffee 和 Tea 啦,因为这里的 Beverage 是一个抽象的存在,需要子类来继承它。泡饮品的流程,可以理解为一个模板模式,抽象类 Beverage,抽象方法 init() 在子类中实现。js 的继承是基于原型链的继承,这里 prototype 就是类的原型链。这里由于 coffee 对象和 tea 对象的原型 prototype 上都没有对应的 init(),所以请求会顺着原型链,找到父类 Beverage 的 init()。子类寻找对应的属性和方法的时候会顺着原型链去查找,先找自己,没有找到会顺着去父类里面查找。

Beverage.prototype.init 被称为模板方法的原因是,该方法中封装了子类的算法框架,它作为一个算法的模板,指导子类以何种顺序去执行哪些方法。

优点:

  • 在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。
  • 模板方法模式是一种代码复用技术,它在类库设计中尤为重要,它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为,它鼓励我们恰当使用继承来实现代码复用。
  • 可实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行。
  • 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则。

缺点:

  • 需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合桥接模式来进行设计。

6.11 访问者模式

访问者模式 (Visitor Pattern):提供一个作用于某对象结构中的各元素的操作表示,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。

举例:

访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。访问者模式使得用户可以在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作。

在使用访问者模式时,被访问元素通常不是单独存在的,它们存储在一个集合中,这个集合被称为「对象结构」,访问者通过遍历对象结构实现对其中存储的元素的逐个操作。

js
// 访问者模式:DOM 事件绑定
+var bindEvent = function(dom, type, fn, data) {
+    if (dom.addEventListener) {
+        dom.addEventListener(type, fn, false);
+    } else if (dom.attachEvent) {
+        // dom.attachEvent('on'+type, fn);
+        var data = data || {};
+        dom.attachEvent('on' + type, function(e) {
+            // 在 IE 中 this 指向 window,使用 call 改变 this 的指向
+            fn.call(dom, e, data);
+        });
+    } else {
+        dom['on' + type] = fn;
+    }
+}
+function $(id) {
+    return document.getElementById(id);
+}
+
+bindEvent($(demo), 'click', function() {
+    // this 指向 dom 对象
+    this.style.background = 'red';
+});
+
+bindEvent($('btn'), 'click', function(e, data) {
+    $('text').innerHTML = e.type + data.text + this.tagName;
+}, { text: 'demo' });

访问者模式的思想就是在不改变操作对象的同时,为它添加新的操作方法,以实现对操作对象的访问。我们知道,call 和 apply 的作用就是更改函数执行时的作用域,这正是访问者模式的精髓。通过 call、apply 这两种方式我们就可以让某个对象在其它作用域中运行。

js
// 数组方法封装
+var Visitor = (function() {
+    return {
+        splice: function() {
+            var args = Array.prototype.splice.call(arguments, 1);
+            return Array.prototype.splice.apply(arguments[0], args);
+        },
+        push: function() {
+            var len = arguments[0].length || 0;
+            var args = this.splice(arguments, 1);
+            arguments[0].length = len + arguments.length - 1;
+            return Array.prototype.push.apply(arguments[0], args);
+        },
+        pop: function() {
+            return Array.prototype.pop.apply(arguments[0]);
+        }
+    }
+})();
+
+var a = new Object();
+Visitor.push(a,1,2,3,4);
+Visitor.push(a,4,5,6);
+Visitor.pop(a);
+Visitor.splice(a,2);

访问者模式解决了数据与数据的操作方法之间的耦合,让数据的操作方法独立于数据,使其可以自由演变。因此,访问者模式更适合于那些数据稳定、但数据的操作方法易变的环境下。

优点:

  • 增加新的访问操作很方便。使用访问者模式,增加新的访问操作就意味着增加一个新的具体访问者类,实现简单,无须修改源代码,符合“开闭原则”。
  • 将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中。类的职责更加清晰,有利于对象结构中元素对象的复用,相同的对象结构可以供多个不同的访问者访问。
  • 让用户能够在不修改现有元素类层次结构的情况下,定义作用于该层次结构的操作。

缺点:

  • 增加新的元素类很困难。在访问者模式中,每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”的要求。
  • 破坏封装。访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问。

总结

系统地学习设计模式后,你可以在过往的开发经历中发现,设计模式是无处不在的。在学习设计模式之前的很多时候我们是凭借过往经验和智慧来完善系统的设计,而这些经验很多和某个设计模式的思想不谋而合。

还有一些地方没有完全理解,文中有误之处还望不吝指出。

参考资料

`,384)]))}const z=P(S,[["render",T]]);export{W as __pageData,z as default}; diff --git a/assets/cn_src_article_designMode.md.Bo9IXX6C.lean.js b/assets/cn_src_article_designMode.md.Bo9IXX6C.lean.js new file mode 100644 index 0000000000..87f6dd1d48 --- /dev/null +++ b/assets/cn_src_article_designMode.md.Bo9IXX6C.lean.js @@ -0,0 +1,752 @@ +import{_ as i,a,b as n,c as h,d as l,e as k,f as p,g as t,h as e,i as E,j as r,k as d,l as g,m as y,n as F,o as c,p as o,q as C,r as B,s as A,t as D,u,v as b,w as m,x as v,y as f,z as x,A as _,B as q}from"./chunks/访问者._0swtoJg.js";import{_ as P,o as w,c as j,a3 as M}from"./chunks/framework.C-ai2y4t.js";const W=JSON.parse('{"title":"23 种经典设计模式","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/designMode.md","filePath":"cn/src/article/designMode.md","lastUpdated":1726550590000}'),S={name:"cn/src/article/designMode.md"};function T(L,s,V,I,N,O){return w(),j("div",{"data-pagefind-body":!0},s[0]||(s[0]=[M(`

23 种经典设计模式

设计模式 Design Pattern 是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。。

在《设计模式:可复用面向对象软件的基础》一书中所介绍的 23 种经典设计模式,不过设计模式并不仅仅只有这 23 种,随着软件开发行业的发展,越来越多的新模式不断诞生并得以应用。有经验的开发者在学习设计模式可以和过往的经验互相印证,更容易理解这些设计模式。

设计模式一般包含模式名称、问题、目的、解决方案、效果等组成要素。问题描述了应该在何时使用模式,它包含了设计中存在的问题以及问题存在的原因。解决方案描述了一个设计模式的组成成分,以及这些组成成分之间的相互关系,各自的职责和协作方式,通常解决方案通过 UML 类图和核心代码来进行描述。效果描述了模式的优缺点以及在使用模式时应权衡的问题。

为什么要学习设计模式:

  • 设计模式来源众多专家的经验和智慧,它们是从许多优秀的软件系统中总结出的成功的、能够实现可维护性复用的设计方案,使用这些方案将可以让我们避免做一些重复性的工作

  • 设计模式提供了一套通用的设计词汇和一种通用的形式来方便开发人员之间沟通和交流,使得设计方案更加通俗易懂

  • 大部分设计模式都兼顾了系统的可重用性和可扩展性,这使得我们可以更好地重用一些已有的设计方案、功能模块甚至一个完整的软件系统,避免我们经常做一些重复的设计、编写一些重复的代码

  • 合理使用设计模式并对设计模式的使用情况进行文档化,将有助于别人更快地理解系统

  • 学习设计模式将有助于初学者更加深入地理解面向对象思想

储备知识

  • 抽象类:一般抽象类都是作为基类,比如说「电脑」就可以作为一个抽象类,根据抽象类派生出「台式电脑」和「笔记本电脑」2 种具体类。一般不对抽象类进行实例化。

  • 组合优于继承:不能滥用继承来拓展功能,配合组合会更灵活。同样拿「电脑」抽象类来举例,如果使用继承,区分不同类型的「电脑」我们可以派生出「台式电脑」和「笔记本电脑」,如果再增加一个维度,根据品牌又能继续细分出「联想台式电脑」、「联想笔记本电脑」、「苹果台式电脑」和「苹果笔记本电脑」等等,如果再增加一个维度继续细分下去,显然继承是无法胜任的。这个时候可以使用继承加组合方式,组合的对象也可以进行抽象化设计:

    ts
    // 品牌
    +interface Brand {
    +  // ...
    +}
    +interface Lenovo extends Brand {
    +  // ...
    +}
    +interface Apple extends Brand {
    +  // ...
    +}
    +// CPU
    +interface CPU {
    +  // ...
    +}
    +interface Inter extends CPU {
    +  // ...
    +}
    +interface AMD extends CPU {
    +  // ...
    +}
    +// 电脑
    +interface Computer {
    +  // ...
    +}
    +
    +interface DesktopComputer extends Computer {}
    +interface NotebookComputer extends Computer {}

一、UML 类图

每个模式都有相应的对象结构图,同时为了展示对象间的交互细节,有些时候会用到 UML 图来介绍其如何运行。这里不会将 UML 的各种元素都提到,只想讲讲类图中各个类之间的关系,能看懂类图中各个类之间的线条、箭头代表什么意思后,也就足够应对日常的工作和交流。同时,我们应该能将类图所表达的含义和最终的代码对应起来。有了这些知识,看后面章节的设计模式结构图就没有什么问题了。

1.1 继承

继承用一条带空心箭头的直接表示。

1.2 实现

实现关系用一条带空心箭头的虚线表示。

1.3 组合

与聚合关系一样,组合关系同样表示整体由部分构成的语义。比如公司由多个部门组成,但组合关系是一种强依赖的特殊聚合关系,如果整体不存在了,则部分也不存在了。例如,公司不存在了,部门也将不存在了。

1.4 聚合

聚合关系用于表示实体对象之间的关系,表示整体由部分构成的语义,例如一个部门由多个员工组成。与组合关系不同的是,整体和部分不是强依赖的,即使整体不存在了,部分仍然存在。例如,部门撤销了,人员不会消失,他们依然存在。

1.5 关联

关联关系是用一条直线表示的,它描述不同类的对象之间的结构关系,它是一种静态关系,通常与运行状态无关,一般由常识等因素决定的。它一般用来定义对象之间静态的、天然的结构,所以,关联关系是一种“强关联”的关系。

比如,乘车人和车票之间就是一种关联关系,学生和学校就是一种关联关系,关联关系默认不强调方向,表示对象间相互知道。如果特别强调方向,如下图,表示 A 知道 B,但 B 不知道 A。

1.6 依赖

依赖关系是用一套带箭头的虚线表示的,如 A 依赖于 B,他描述一个对象在运行期间会用到另一个对象的关系。

与关联关系不同的是,它是一种临时性的关系,通常在运行期间产生,并且随着运行时的变化,依赖关系也可能发生变化。显然,依赖也有方向,双向依赖是一种非常糟糕的结构,我们总是应该保持单向依赖,杜绝双向依赖的产生。

二、六大原则

2.1 开闭原则

一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

任何软件都需要面临一个很重要的问题,即它们的需求会随时间的推移而发生变化。当软件系统需要面对新的需求时,我们应该尽量保证系统的设计框架是稳定的。如果一个软件设计符合开闭原则,那么可以非常方便地对系统进行扩展,而且在扩展时无须修改现有代码,使得软件系统在拥有适应性和灵活性的同时具备较好的稳定性和延续性。随着软件规模越来越大,软件寿命越来越长,软件维护成本越来越高,设计满足开闭原则的软件系统也变得越来越重要。

为了满足开闭原则,需要对系统进行抽象化设计,抽象化是开闭原则的关键。在JavaC#等编程语言中,可以为系统定义一个相对稳定的抽象层,而将不同的实现行为移至具体的实现层中完成。在很多面向对象编程语言中都提供了接口、抽象类等机制,可以通过它们定义系统的抽象层,再通过具体类来进行扩展。如果需要修改系统的行为,无须对抽象层进行任何改动,只需要增加新的具体类来实现新的业务功能即可,实现在不修改已有代码的基础上扩展系统的功能,达到开闭原则的要求。

优点:实践开闭原则的优点在于可以在不改动原有代码的前提下给程序扩展功能。增加了程序的可扩展性,同时也降低了程序的维护成本。

2.2 里氏替换原则

所有引用基类对象的地方能够透明地使用其子类的对象

里氏代换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。例如:我喜欢动物,那我一定喜欢狗,因为狗是动物的子类。但是我喜欢狗,不能据此断定我喜欢动物,因为我并不喜欢老鼠,虽然它也是动物。

例如有两个类,一个类为BaseClass,另一个是SubClass类,并且SubClass类是BaseClass类的子类,那么一个方法如果可以接受一个BaseClass类型的基类对象base的话,如:method1(base),那么它必然可以接受一个BaseClass类型的子类对象submethod1(sub)能够正常运行。反过来的代换不成立,如一个方法method2接受BaseClass类型的子类对象sub为参数:method2(sub),那么一般而言不可以有method2(base),除非是重载方法。

里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

优点:可以检验继承使用的正确性,约束继承在使用上的泛滥。

2.3 依赖倒置原则

抽象不应该依赖于具体类,具体类应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。

依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。为了确保该原则的应用,一个具体类应当只实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法。

在引入抽象层后,系统将具有很好的灵活性,在程序中尽量使用抽象层进行编程,而将具体类写在配置文件中,这样一来,如果系统行为发生变化,只需要对抽象层进行扩展,并修改配置文件,而无须修改原有系统的源代码,在不修改的情况下来扩展系统的功能,满足开闭原则的要求。

优点:通过抽象来搭建框架,建立类和类的关联,以减少类间的耦合性。而且以抽象搭建的系统要比以具体实现搭建的系统更加稳定,扩展性更高,同时也便于维护。

2.4 单一职责原则

一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。

单一职责原则告诉我们:一个类不能太“累”!在软件系统中,一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。

单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关实践经验。

优点:如果类与方法的职责划分得很清晰,不但可以提高代码的可读性,更实际性地更降低了程序出错的风险,因为清晰的代码会让 bug 无处藏身,也有利于 bug 的追踪,也就是降低了程序的维护成本。

2.5 迪米特法则(最少知道原则)

一个软件实体应当尽可能少地与其他实体发生相互作用

如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。

迪米特法则要求我们在设计系统时,应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。

在将迪米特法则运用到系统设计中时,要注意下面的几点:在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及。在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限。在类的设计上,只要有可能,一个类型应当设计成不变类。在对其他类的引用上,一个对象对其他对象的引用应当降到最低。

优点:实践迪米特法则可以良好地降低类与类之间的耦合,减少类与类之间的关联程度,让类与类之间的协作更加直接。

2.6 接口分离原则

使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。

根据接口隔离原则,当一个接口太大时,我们需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干。

在使用接口隔离原则时,我们需要注意控制接口的粒度,接口不能太小,如果太小会导致系统中接口泛滥,不利于维护。接口也不能太大,太大的接口将违背接口隔离原则,灵活性较差,使用起来很不方便。

优点:避免同一个接口里面包含不同类职责的方法,接口责任划分更加明确,符合高内聚低耦合的思想。

2.7 合成复用原则(六大之外的)

尽量使用对象组合,而不是继承来达到复用的目的

合成复用原则就是在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分,新对象通过委派调用已有对象的方法达到复用功能的目的。简而言之,复用时要尽量使用组合/聚合关系(关联关系),少用继承。

在面向对象设计中,可以通过两种方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或通过继承,但首先应该考虑使用组合/聚合,组合/聚合可以使系统更加灵活,降低类与类之间的耦合度。一个类的变化对其他类造成的影响相对较少,其次才考虑继承,在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用。

优点:避免复用时滥用继承,合理使用组合关系,增加灵活性。

2.8 六大原则 - 学习心得

六大原则中,开闭原则里氏替换原则依赖倒置原则 联系比较紧密,后两者是实现开闭原则重要前提,使用中通过抽象化设计具有很好的可拓展性和可维护性。

知道最少原则 可以降低耦合,减少不必要的交互,主张设计接口和类要简单易使用,将复杂的逻辑封装并提供简单易用的接口。

单一职责原则 使项目中的类和方法根据职责细分,避免单个类负担过重。职责越多,被复用的可能性就越小或使用起来越麻烦。

接口分离原则 将功能复杂的接口细分成多个特定功能的接口,只做该做的事情,降低耦合,但是细化粒度不能太细,容易导致接口过多。单一职责原则强调单个类内部根据职责细分的设计,接口分离原则强调类之间的耦合,尽量建立最小的依赖关系。

三、模式分类

《设计模式:可复用面向对象软件的基础》一书中设计模式有 23 个,它们各具特色,每个模式都为某一个可重复的设计问题提供了一套解决方案。根据它们的用途,设计模式可分为创建型 (Creational),结构型 (Structural) 和行为型 (Behavioral) 三种,其中创建型模式主要用于描述如何创建对象,结构型模式主要用于描述如何实现类或对象的组合,行为型模式主要用于描述类或对象怎样交互以及怎样分配职责。

此外,根据某个模式主要是用于处理类之间的关系还是对象之间的关系,设计模式还可以分为类模式和对象模式。我们经常将两种分类方式结合使用,如单例模式是对象创建型模式,模板方法模式是类行为型模式。

3.1 创建型

创建型模式 (Creational Pattern) 对类的实例化过程进行了抽象,能够将模块中对象的创建和对象的使用分离。为了使结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则。

  1. 简单工厂模式(Simple Factory Pattern
  2. 工厂方法模式(Factory Method Pattern
  3. 抽象工厂模式(Abstract Factory Pattern
  4. 单例模式(Singleton Pattern
  5. 生成器模式(Builder Pattern
  6. 原型模式(Prototype Pattern

3.2 结构型

结构型模式 (Structural Pattern) 描述如何将类或者对 象结合在一起形成更大的结构,就像搭积木,可以通过 简单积木的组合形成复杂的、功能更为强大的结构。结构型模式可以分为类结构型模式和对象结构型模式:

  • 类结构型模式关心类的组合,由多个类可以组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系。

  • 对象结构型模式关心类与对象的组合,通过关联关系使得在一 个类中定义另一个类的实例对象,然后通过该对象调用其方法。根据“合成复用原则”,在系统中尽量使用关联关系来替代继 承关系,因此大部分结构型模式都是对象结构型模式。

  1. 外观模式
  2. 适配器模式
  3. 桥接模式
  4. 代理模式
  5. 装饰者模式
  6. 享元模式

3.3 行为型

行为型模式 (Behavioral Pattern) 是对在不同的对象之间划分责任和算法的抽象化。行为型模式不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。通过行为型模式,可以更加清晰地划分类与对象的职责,并研究系统在运行时实例对象之间的交互。

  1. 职责链模式
  2. 命令模式
  3. 解释器模式
  4. 迭代器模式
  5. 中介者模式
  6. 备忘录模式
  7. 观察者模式
  8. 状态模式
  9. 策略模式
  10. 模板方法模式
  11. 访问者模式

四、创建型

4.1 简单工厂模式

简单工厂模式 (Simple Factory Pattern):专门定义一个类(工厂类)来负责创建其他类的实例。可以根据创建方法的参数来返回不同类的实例,被创建的实例通常都具有共同的父类。

举例:

简单工厂模式像一个代工厂,一个工厂可以生产多种产品。举个例子,一个饮料加工厂同时帮百事可乐和可口可乐生产,加工厂根据输入参数Type来生产不同的产品。

ts
// 可乐抽象类
+interface Cola {}
+
+// 可口可乐产品类
+interface CocaCola extends Cola {}
+
+// 百事可乐产品类
+interface PepsiCola extends Cola {}
ts
// 简单工厂实现
+// SimpleFactory
+const createColaWithType = (type: number) => {
+  switch (type) {
+    case 0:
+      return new CocaCola();
+    case 1:
+      return new PepsiCola();
+    default:
+      return null;
+      break;
+  }
+};
ts
// 0 生产可口可乐
+const cocaCola: CocaCola = createColaWithType(0);
+
+// 1 生产百事可乐
+const pepsiCola: PepsiCola = createColaWithType(1);

优点:

  • 使用者只需要给工厂类传入一个正确的约定好的参数,就可以获取你所需要的对象,而不需要知道其创建细节,一定程度上减少系统的耦合。
  • 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,减少开发者的记忆成本。

缺点:

  • 如果业务上添加新产品的话,就需要修改工厂类原有的判断逻辑,这其实是违背了开闭原则的。
  • 在产品类型较多时,有可能造成工厂逻辑过于复杂。所以简单工厂模式比较适合产品种类比较少而且增多的概率很低的情况。

4.2 工厂方法模式

工厂方法模式 (Factory Method Pattern) 又称为工厂模式,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,即通过不同的工厂子类来创建不同的产品对象。

举例:

工厂方法和简单工厂有一些区别,简单工厂是由一个代工厂生产不同的产品,而工厂方法是对工厂进行抽象化,不同产品都由专门的具体工厂来生产。可口可乐工厂专门生产可口可乐,百事可乐工厂专门生产百事可乐。

ts
// 工厂抽象类
+class Cola {}
+
+// 可口可乐工厂
+class CocaCola extends Cola {}
+
+// 百事可乐工厂
+class PepsiCola extends Cola {}
ts
// 根据不同的工厂类生产不同的产品
+const cocaCola = new CocaCola();
+const pepsiCola = new PepsiCola();

优点:

  • 用户只需要关心其所需产品对应的具体工厂是哪一个即可,不需要关心产品的创建细节,也不需要知道具体产品类的类名。
  • 当系统中加入新产品时,不需要修改抽象工厂和抽象产品提供的接口,也无须修改客户端和其他的具体工厂和具体产品,而只要添加一个具体工厂和与其对应的具体产品就可以了,符合了开闭原则。

缺点:

  • 当系统中加入新产品时,除了需要提供新的产品类之外,还要提供与其对应的具体工厂类。因此系统中类的个数将成对增加,增加了系统的复杂度。

4.3 抽象工厂模式

抽象工厂模式并不直接生成实例,而是用于对产品类簇的创建。

抽象工厂模式 (Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

举例:

抽象工厂和工厂方法不同的地方在于,生产产品的工厂是抽象的。举例,可口可乐公司生产可乐的同时,也需要生产装可乐的瓶子和箱子,瓶子和箱子也是可口可乐专属定制的,同样百事可乐公司也会有这个需求。这个时候我们的工厂不仅仅是生产可乐饮料的工厂,还必须同时生产同一主题的瓶子和箱子,所以它是一个抽象的主题工厂,专门生产同一主题的不同商品。

ts
// 可乐抽象类和派生类
+class Cola {}
+
+class CocaCola extends Cola {}
+
+class PepsiCola extends Cola {}
+
+// 瓶子抽象类和派生类
+class Bottle {}
+
+class CocaColaBottle extends Bottle {}
+
+class PepsiColaBottle extends Bottle {}
+
+// 箱子抽象类和派生类
+class Box {}
+
+class CocaColaBox extends Box {}
+
+class PepsiColaBox extends Box {}
+
+// 工厂抽象类
+const Factory = {
+  createCola: () => new Cola(),
+  createBottle: () => new Bottle(),
+  createBox: () => new Box(),
+};
+
+// 可口可乐主题工厂
+const CocaColaFactory = {
+  createCola: () => new CocaCola(),
+  createBottle: () => new CocaColaBottle(),
+  createBox: () => new CocaColaBox(),
+};
+
+// 百事可乐主题工厂
+const PepsiColaFactory = {
+  createCola: () => new PepsiCola(),
+  createBottle: () => new PepsiColaBottle(),
+  createBox: () => new PepsiColaBox(),
+};
ts
// 可口可乐主题
+const cocaCola = CocaColaFactory.createCola();
+const cocaColaBottle = CocaColaFactory.createBottle();
+const cocaColaBox = CocaColaFactory.createBox();
+
+// 百事可乐主题
+const pepsiCola = PepsiColaFactory.createCola();
+const pepsiColaBottle = PepsiColaFactory.createBottle();
+const pepsiColaBox = PepsiColaFactory.createBox();

优点:

  • 具体产品在应用层代码隔离,不需要关心产品细节。只需要知道自己需要的产品是属于哪个工厂的即可 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。

缺点:

  • 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。

4.4 单例模式

单例模式 (Singleton Pattern):单例模式确保某一个类只有一个实例,并提供一个访问它的全剧访问点。

举例:

单例模式下,对应类只能生成一个实例。就像一个王国只能有一个国王,一旦王国里的事务多起来,这唯一的国王也容易职责过重。

ts
class Singleton {}
+
+function createSingleton() {
+  let instance;
+  return function () {
+    if (!instance) return new Singleton();
+    return instance;
+  };
+}

优点:

  • 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它。
  • 因为该类在系统内存中只存在一个对象,所以可以节约系统资源。

缺点:

  • 由于单例模式中没有抽象层,因此单例类很难进行扩展。
  • 对于有垃圾回收系统的语言 Java,C# 来说,如果对象长时间不被利用,则可能会被回收。那么如果这个单例持有一些数据的话,在回收后重新实例化时就不复存在了。

4.5 生成器模式

生成器模式 (Builder Pattern):也叫创建者模式,它将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

工厂模式主要是为了创建对象实例或者类簇(抽象工厂),关心的是最终产出 (创建) 的是什么,而不关心创建的过程。而建造者模式关心的是创建这个对象的整个过程,甚至于创建对象的每一个细节。

举例:

生成器模式的主要角色如下:

  1. 生成器:接口生命再所有类型生成器中通用的产品构造步骤
  2. 具体生成器:提供构造过程的不同实现。具体生成器也可以构造不遵循通用接口的产品
  3. 产品:是最终生成的对象。由不同生成器构造的产品无需属于同一类层次构造或接口
  4. 指挥者:定义调用构造步骤的顺序,这样你就可以创建和服用特定的产品配置
  5. 客户端:必须将某个生成器对象与主管类关联,一般情况下,你只需要通过指挥者类构造函数的参数进行一次性关联即可
ts
// 抽象建造者
+abstract class Builder {
+  public abstract buildPartA(): void;
+  public abstract buildPartB(): void;
+  public abstract buildPartC(): void;
+  public abstract buildProduct(): Product;
+}
+
+// 具体建造者
+class ConcreteBuilder extends Builder {
+  private product: Product;
+  constructor(product: Product) {
+    super();
+    this.product = product;
+  }
+
+  public buildPartA(): void {}
+  public buildPartB(): void {}
+  public buildPartC(): void {}
+
+  // 最终组建一个产品
+  public buildProduct(): Product {
+    return this.product;
+  }
+}
+
+// 产品角色
+class Product {
+  public doSomething(): void {
+    // 独立业务
+  }
+}
+
+// 指挥者
+class Director {
+  private _builder: Builder;
+  constructor(builder: Builder) {
+    this._builder = builder;
+  }
+
+  set builder(builder: Builder) {
+    this._builder = builder;
+  }
+
+  // 将处理建造的流程交给指挥者
+  public constructorProduct() {
+    this._builder.buildPartA();
+    this._builder.buildPartB();
+    this._builder.buildPartC();
+    return this._builder.buildProduct();
+  }
+}
+
+// 使用
+const builder: Builder = new ConcreteBuilder(new Product());
+const director: Director = new Director(builder);
+const product: Product = director.constructorProduct();

优点:

  • 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
  • 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
  • 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
  • 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。

缺点:

  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。

4.6 原型模式

原型模式(Prototype Pattern): 用原型实例指向创建对象的类,使用于创建新的对象的类的共享原型的属性与方法。

举例:

原型模式就像复印技术,根据原对象复印出一个新对象,并根据需求对新对象进行微调。

ts
// 因为不是构造函数,所以不用大写
+const car = {
+  drive: function () {},
+  name: '马自达 3',
+};
+
+// 使用 Object.create 创建一个新车 x
+const anotherCar = Object.create(someCar);
+anotherCar.name = '丰田佳美';
ts
const vehiclePrototype = {
+  init: function (carModel) {
+    this.model = carModel;
+  },
+  getModel: function () {
+    console.log('车辆模具是:' + this.model);
+  },
+};
+
+function vehicle(model) {
+  function F() {}
+  F.prototype = vehiclePrototype;
+
+  const f = new F();
+
+  f.init(model);
+  return f;
+}
+
+const car = vehicle('福特 Escort');
+car.getModel();

优点:

  • 可以利用原型模式简化对象的创建过程,尤其是对一些创建过程繁琐,包含对象层级比较多的对象来说,使用原型模式可以节约系统资源,提高对象生成的效率。
  • 可以很方便得通过改变值来生成新的对象:有些对象之间的差别可能只在于某些值的不同;用原型模式可以快速复制出新的对象并手动修改值即可。

缺点:

  • 对象包含的所有对象都需要配备一个克隆的方法,这就使得在对象层级比较多的情况下,代码量会很大,也更加复杂。

五、结构型

5.1 装饰模式

装饰模式 (Decorator Pattern) :向一个现有的对象添加新的功能,同时又不改变其结构的设计模式被称为装饰器模式,它是作为现有的类的一个包装。

可以将装饰器理解为游戏人物购买的装备,例如 LOL 中的英雄刚开始游戏时只有基础的攻击力和法强。但是在购买的装备后,在触发攻击和技能时,能够享受到装备带来的输出加成。我们可以理解为购买的装备给英雄的攻击和技能的相关方法进行了装饰。

举例:

装饰模式贴合开闭原则,在不改变原有类的情况下,对父类进行改造或新增功能。

装饰类

ts
@annotation
+class MyClass {}
+
+function annotation(target) {
+  target.annotated = true;
+}

装饰方法或属性

js
class MyClass {
+  @readonly
+  method() {}
+}
+
+function readonly(target, name, descriptor) {
+  descriptor.writable = false;
+  return descriptor;
+}

优点:

  • 比继承更加灵活:不同于在编译期起作用的继承;装饰者模式可以在运行时扩展一个对象的功能。另外也可以通过配置文件在运行时选择不同的装饰器,从而实现不同的行为。也可以通过不同的组合,可以实现不同效果。
  • 符合“开闭原则”:装饰者和被装饰者可以独立变化。用户可以根据需要增加新的装饰类,在使用时再对其进行组合,原有代码无须改变。

缺点:

  • 装饰者模式需要创建一些具体装饰类,会增加系统的复杂度。

5.2 外观模式

外观模式 (Facade Pattern):外观模式定义了一个高层接口,为子系统中的一组接口提供一个统一的接口。使得子系统更容易使用,不仅简化类中的接口,而且实现调用者和接口的解耦。外观模式又称为门面模式,它是一种结构型设计模式模式。

举例:

外观模式提供了简单明确的接口,但是在内部众多子系统功能进行整合。就像图片缓存,内部包含了涉及到其他子系统的如缓存、下载等处理,外观模式将这些复杂的逻辑都隐藏了。在兼容浏览器事件绑定,你只需要调一个addMyEvent接口就可以了,达到解耦合的目的。

js
const addMyEvent = function (el, ev, fn) {
+  if (el.addEventListener) {
+    el.addEventListener(ev, fn, false);
+  } else if (el.attachEvent) {
+    el.attachEvent('on' + ev, fn);
+  } else {
+    el['on' + ev] = fn;
+  }
+};

优点:

  • 实现了客户端与子系统间的解耦:客户端无需知道子系统的接口,简化了客户端调用子系统的调用过程,使得子系统使用起来更加容易。同时便于子系统的扩展和维护。
  • 符合迪米特法则(最少知道原则):子系统只需要将需要外部调用的接口暴露给外观类即可,而且他的接口则可以隐藏起来。

缺点:

  • 违背了开闭原则:在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的代码。

5.3 代理模式

代理模式 (Proxy Pattern) :为某个对象提供一个代理,并由这个代理对象控制对原对象的访问。

举例:

代理模式像一个房屋中介,买家只能通过中介来买房,代理具备被代理类的所有功能,就像房东有卖房功能,中介也具有卖房功能。此外代理实例还可以帮助被代理实例进行一些额外处理,比如中介可以帮助房东筛选优质买家的功能,帮助房东 pass 掉一些不符合条件的买家。还有消息队列也是该模式。

参考koa中的代理模式,把response上的一些属性和方法代理出来,方便使用

js
/**
+ * Response delegation.
+ */
+const delegate = require('delegates');
+
+const prototype = (module.exports = {});
+
+delegate(prototype, 'response')
+  .method('attachment')
+  .method('redirect')
+  .method('remove')
+  .method('vary')
+  .method('has')
+  .method('set')
+  .method('append')
+  .method('flushHeaders')
+  .access('status')
+  .access('message')
+  .access('body')
+  .access('length')
+  .access('type')
+  .access('lastModified')
+  .access('etag')
+  .getter('headerSent')
+  .getter('writable');

context,request,response做一个代理,保护真正的context,request,response

js
this.context = Object.create(context);
+this.request = Object.create(request);
+this.response = Object.create(response);

优点:

  • 降低系统的耦合度:代理模式能够协调调用者和被调用者,在一定程度上降低了系 统的耦合度。
  • 不同类型的代理可以对客户端对目标对象的访问进行不同的控制:
    • 远程代理,使得客户端可以访问在远程机器上的对象,远程机器 可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。
    • 虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。
    • 保护代理可以控制客户端对真实对象的使用权限。

缺点:

  • 由于在客户端和被代理对象之间增加了代理对象,因此可能会让客户端请求的速度变慢。

5.4 享元模式

享元模式 (Flyweight Pattern):享元模式是一种优化程序性能的模式,本质为减少对象创建的个数。运用共享技术复用大量细粒度的对象,降低程序内存的占用,提高程序的性能。以下情况可以使用享元模式:有大量相似的对象,占用了大量内存。对象中大部分状态可以抽离为外部状态。

举例:

举例,音乐服务根据收费划分出免费用户和会员用户,免费用户只能听部分免费音乐,会员用户可以听全部的音乐,并且可以下载。虽然权限上二者间有一些区别,但是他们所享受的音乐来是自于同一个音乐库,这样所有的音乐都只需要保存一份就可以了。另外如果出现音乐库里没有的音乐时,则需要新增该音乐,然后其他服务也可以享受新增的音乐,相当于享元池或缓存池的功能。

享元模式区保证共享内部状态如音乐库,而外部状态根据不同需求定制如各种访问权限,使用中不能去改变内部状态,以达到共享的目的。

ts
// 音乐服务
+const MusicService = {}
+
+// 共享的音乐库
+const musicLibrary = {};
+
+// 听音乐
+const listenToMusic = (music) => {
+    ...
+}
+// 下载音乐
+const downloadMusic = (music) => {
+    ...
+}
+
+
+// 免费音乐服务
+const FreeMusicService = {
+    listenFreeMusic: (music)=>{
+        if(isMusicFree(music)){
+            // 如果是免费则播放
+            listenToMusic()
+        }else{
+    	    // 如果是收费音乐,则提示用户升级 Vip
+            console.log("please upgrade to Vip")
+        }
+    }
+}
+
+
+// Vip 音乐服务
+const VipMusicService = {
+    // 可以听全部的音乐
+    listenMusic
+    // 可以下载音乐
+    downloadMusic
+}

优点:

  • 使用享元模可以减少内存中对象的数量,使得相同对象或相似对象在内存中只保存一份,降低系统的使用内存,也可以提性能。
  • 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。

缺点:

  • 使用享元模式需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
  • 对象在缓冲池中的复用需要考虑线程问题。

5.5 桥接模式

桥接模式 (Simple Factory Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。

举例:

球和人都可以进行运动,但球有运动和颜色,人可以运动和说话。对共同部分进行抽象。

js
class Speed {
+  // 运动模块
+  constructor(x, y) {
+    this.x = x;
+    this.y = y;
+  }
+  run() {
+    console.log(\`运动起来 \${this.x} + \${this.y}\`);
+  }
+}
+
+class Color {
+  // 着色模块
+  constructor(cl) {
+    this.color = cl;
+  }
+  draw() {
+    console.log(\`绘制颜色 \${this.color}\`);
+  }
+}
+
+class Speak {
+  constructor(wd) {
+    this.word = wd;
+  }
+  say() {
+    console.log(\`说话 \${this.word}\`);
+  }
+}
+
+class Ball {
+  // 创建球类,可以着色和运动
+  constructor(x, y, cl) {
+    this.speed = new Speed(x, y);
+    this.color = new Color(cl);
+  }
+  init() {
+    this.speed.run();
+    this.color.draw();
+  }
+}
+
+class Man {
+  // 人类,可以运动和说话
+  constructor(x, y, wd) {
+    this.speed = new Speed(x, y);
+    this.speak = new Speak(wd);
+  }
+  init() {
+    this.speed.run();
+    this.speak.say();
+  }
+}
+
+const man = new Man(1, 2, 'hello ?');
+man.init(); // 运动起来 1 + 2      说话 hello?

优点:

  • 扩展性好,符合开闭原则:将抽象与实现分离,让二者可以独立变化

缺点:

  • 在设计之前,需要识别出两个独立变化的维度。

5.6 适配器模式

适配器模式 (Adapter Pattern) :适配器模式是用来解决两个接口不兼容的情况,不需要改变已有的接口,通过包装一层的方式,实现两个接口正常协作。当我们试图调用模块或者对象的某个接口时,却发现这个接口的格式并不符合目前的需求,则可以用适配器模式。

举例:

事件绑定兼容各浏览器

js
function addEvent(ele, event, callback) {
+    if (ele.addEventListener) {
+      ele.addEventListener(event, callback)
+    } else if(ele.attachEvent) {
+      ele.attachEvent('on' + event, callback)
+    } else {
+      ele['on' + event] = callback
+    }
+  }
+

优点:

  • 符合开闭原则:使用适配器而不需要改变现有类,提高类的复用性。
  • 目标类和适配器类解耦,提高程序扩展性。

缺点:

  • 增加了系统的复杂性

六、行为型

6.1 职责链模式

职责链模式 (Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。职责链模式是一种对象行为型模式。类似多米诺骨牌,通过请求第一个条件,会持续执行后续的条件,直到返回结果为止。

举例:

场景:某电商针对已付过定金的用户有优惠政策,在正式购买后,已经支付过 500 元定金的用户会收到 100 元的优惠券,200 元定金的用户可以收到 50 元优惠券,没有支付过定金的用户只能正常购买。

js
const order500 = function (orderType, pay, stock) {
+  if (orderType === 1 && pay == true) {
+    console.log('500 元定金预购,得到 100 元优惠劵');
+  } else {
+    return 'nextSuccess';
+  }
+};
+const order200 = function (orderType, pay, stock) {
+  if (orderType === 2 && pay === true) {
+    console.log('200 元定金预购,得到 50 元優惠卷');
+  } else {
+    return 'nextSuccess';
+  }
+};
+const orderCommon = function (orderType, pay, stock) {
+  if (orderType == 3 && stock > 0) {
+    console.log('普通購買,无優惠卷');
+  } else {
+    console.log('库存不够');
+  }
+};
+//链路代码
+const chain = function (fn) {
+  this.fn = fn;
+  this.successor = null;
+};
+chain.prototype.setNext = function (successor) {
+  this.successor = successor;
+};
+chain.prototype.init = function () {
+  const result = this.fn.apply(this, arguments);
+  if (result == 'nextSuccess') {
+    this.successor.init.apply(this.successor, arguments);
+  }
+};
+const order500New = new chain(order500);
+const order200New = new chain(order200);
+const orderCommonNew = new chain(orderCommon);
+order500New.setNext(order200New);
+order200New.setNext(orderCommonNew);
+order500New.init(3, true, 500); // 普通购买,无优惠券

优点:

  • 职责链模式使得一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构,由客户端负责链的创建,降低了系统的耦合度。
  • 请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的引用,可简化对象的相互连接。
  • 在给对象分派职责时,职责链可以给我们更多的灵活性,可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的职责。
  • 在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新建链即可,从这一点来看是符合“开闭原则”的。

缺点:

  • 由于一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理。
  • 对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响,而且在进行代码调试时不太方便。
  • 如果建链不当,可能会造成循环调用,将导致系统陷入死循环。

6.2 命令模式

命令模式 (Command Pattern):将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;命令模式是一种对象行为型模式,其别名为动作 (Action) 模式或事务 (Transaction) 模式。

命令模式由三种角色构成:

  1. 发布者 invoker(发出命令,调用命令对象,不知道如何执行与谁执行);
  2. 接收者 receiver (提供对应接口处理请求,不知道谁发起请求);
  3. 命令对象 command(接收命令,调用接收者对应接口处理发布者的请求)。 发布者 invoker 和接收者 receiver 各自独立,将请求封装成命令对象 command,请求的具体执行由命令对象 command 调用接收者 receiver 对应接口执行。

举例:

和之前代理模式中的举例有些相似,不过命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。例如遥控器是一个调用者,不同按钮代表不同的命令,而电视是接收者。

js
class Receiver {
+  // 接收者类
+  execute() {
+    console.log('接收者执行请求');
+  }
+}
+
+class Command {
+  // 命令对象类
+  constructor(receiver) {
+    this.receiver = receiver;
+  }
+  execute() {
+    // 调用接收者对应接口执行
+    console.log('命令对象->接收者->对应接口执行');
+    this.receiver.execute();
+  }
+}
+
+class Invoker {
+  // 发布者类
+  constructor(command) {
+    this.command = command;
+  }
+  invoke() {
+    // 发布请求,调用命令对象
+    console.log('发布者发布请求');
+    this.command.execute();
+  }
+}
+
+const warehouse = new Receiver(); // 仓库
+const order = new Command(warehouse); // 订单
+const client = new Invoker(order); // 客户
+client.invoke();

优点:

  • 降低系统的耦合度。由于请求者与接收者之间不存在直接引用,因此请求者与接收者之间实现完全解耦,相同的请求者可以对应不同的接收者,同样,相同的接收者也可以供不同的请求者使用,两者之间具有良好的独立性。
  • 新的命令可以很容易地加入到系统中。由于增加新的具体命令类不会影响到其他类,因此增加新的具体命令类很容易,无须修改原有系统源代码,甚至客户类代码,满足“开闭原则”的要求。
  • 可以比较容易地设计一个命令队列或宏命令(组合命令)。
  • 为请求的撤销 (Undo) 和恢复 (Redo) 操作提供了一种设计和实现方案。

缺点:

  • 使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个对请求接收者的调用操作都需要设计一个具体命令类,因此在某些系统中可能需要提供大量的具体命令类,这将影响命令模式的使用。

6.3 解释器模式

解释器模式 (Interpreter Pattern):定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。解释器模式是一种类行为型模式。

举例:

给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。

js
class Context {
+  constructor() {
+    this._list = []; // 存放 终结符表达式
+    this._sum = 0; // 存放 非终结符表达式 (运算结果)
+  }
+
+  get sum() {
+    return this._sum;
+  }
+  set sum(newValue) {
+    this._sum = newValue;
+  }
+  add(expression) {
+    this._list.push(expression);
+  }
+  get list() {
+    return [...this._list];
+  }
+}
+
+class PlusExpression {
+  interpret(context) {
+    if (!(context instanceof Context)) {
+      throw new Error('TypeError');
+    }
+    context.sum = ++context.sum;
+  }
+}
+class MinusExpression {
+  interpret(context) {
+    if (!(context instanceof Context)) {
+      throw new Error('TypeError');
+    }
+    context.sum = --context.sum;
+  }
+}
+
+/** 以下是测试代码 **/
+const context = new Context();
+
+// 依次添加:加法 | 加法 | 减法 表达式
+context.add(new PlusExpression());
+context.add(new PlusExpression());
+context.add(new MinusExpression());
+
+// 依次执行:加法 | 加法 | 减法 表达式
+context.list.forEach((expression) => expression.interpret(context));
+console.log(context.sum);

优点:

  • 易于改变和扩展文法。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
  • 每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
  • 实现文法较为容易。在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成节点类代码。
  • 增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合“开闭原则”。

缺点:

  • 对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。
  • 执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。

6.4 迭代器模式

迭代器模式 (Iterator Pattern):一个相对简单的模式,目前绝大多数语言都内置了迭代器,以至于大家都不觉得这是一种设计模式。迭代器并不只迭代数组,迭代器可以中止。提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标 (Cursor)。迭代器模式是一种对象行为型模式。

举例:

迭代器帮助请求方获取数据,避免直接操作数据聚合类,使数据聚合类专注存储数据。具体应用有分页等功能,分页功能的迭代器将专门负责操作分页数据,将操作逻辑和数据源分离。

js
var each = function (arr, callback) {
+  for (var i = 0, len = arr.length; i < len; i++) {
+    callback.call(arr[i], i, arr[i]);
+  }
+};
+
+each([1, 2, 3, 4, 5], function (i, el) {
+  console.log('index: ', i);
+  console.log('item: ', el);
+});

优点:

  • 它支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法,我们也可以自己定义迭代器的子类以支持新的遍历方式。
  • 迭代器简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计。
  • 在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”的要求。

缺点:

  • 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
  • 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展,例如 JDK 内置迭代器 Iterator 就无法实现逆向遍历,如果需要实现逆向遍历,只能通过其子类 ListIterator 等来实现,而 ListIterator 迭代器无法用于操作 Set 类型的聚合对象。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是件很容易的事情。

6.5 中介者模式

中介者模式(Mediator Pattern):对象和对象之间借助第三方中介者进行通信。用一个中介对象(中介者)来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。

举例:

中介者模式将一个网状的系统结构变成一个以中介者对象为中心的星形结构,在这个星型结构中,使用中介者对象与其他对象的一对多关系来取代原有对象之间的多对多关系。所有成员通过中介者交互,方便拓展新的成员,例如下面的例子,一场测试结束后,公布结果:告知解答出题目的人挑战成功,否则挑战失败。在这段代码中 A、B、C 之间没有直接发生关系,而是通过另外的 playerMiddle 对象建立链接,姑且将之当成是中介者模式了。

js
const player = function (name) {
+  this.name = name;
+  playerMiddle.add(name);
+};
+player.prototype.win = function () {
+  playerMiddle.win(this.name);
+};
+player.prototype.lose = function () {
+  playerMiddle.lose(this.name);
+};
+const playerMiddle = (function () {
+  //将就用下这个 demo, 这个函数充当中介者
+  const players = [];
+  const winArr = [];
+  const loseArr = [];
+  return {
+    add: function (name) {
+      players.push(name);
+    },
+    win: function (name) {
+      winArr.push(name);
+      if (winArr.length + loseArr.length === players.length) {
+        this.show();
+      }
+    },
+    lose: function (name) {
+      loseArr.push(name);
+      if (winArr.length + loseArr.length === players.length) {
+        this.show();
+      }
+    },
+    show: function () {
+      for (let winner of winArr) {
+        console.log(winner + '挑戰成功;');
+      }
+      for (let loser of loseArr) {
+        console.log(loser + '挑战失败;');
+      }
+    },
+  };
+})();
+const a = new player('A 选手');
+const b = new player('B 选手');
+const c = new player('C 选手');
+a.win();
+b.lose();
+c.win();
+// A 选手挑战成功;
+// B 选手挑战成功;
+// C 选手挑战失败;

优点:

  • 中介者模式简化了对象之间的交互,它用中介者和同事的一对多交互代替了原来同事之间的多对多交互,一对多关系更容易理解、维护和扩展,将原本难以理解的网状结构转换成相对简单的星型结构。
  • 中介者模式可将各同事对象解耦。中介者有利于各同事之间的松耦合,我们可以独立的改变和复用每一个同事和中介者,增加新的中介者和新的同事类都比较方便,更好地符合“开闭原则”。
  • 可以减少子类生成,中介者将原本分布于多个对象间的行为集中在一起,改变这些行为只需生成新的中介者子类即可,这使各个同事类可被重用,无须对同事类进行扩展。

缺点:

  • 在具体中介者类中包含了大量同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。

6.6 备忘录模式

备忘录模式 (Memento Pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便日后对象使用或者对象恢复到以前的某个状态。它是一种对象行为型模式,其别名为 Token。

举例:

备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,当前很多软件都提供了撤销操作,其中就使用了备忘录模式。

当我们开发一个分页组件的时候,点击下一页获取新的数据,但是当点击上一页时,又重新获取数据,造成无谓的流量浪费,这时可以对数据进行缓存。

js
// 备忘录模式伪代码
+var Page = function () {
+  // 通过 cache 对象缓存数据
+  var cache = {};
+  return function (page, fn) {
+    if (cache[page]) {
+      showPage(page, cache[page]);
+    } else {
+      $.post('/url', function (data) {
+        showPage(page, data);
+        cache[page] = data;
+      });
+    }
+    fn && fn();
+  };
+};

优点:

  • 它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。
  • 备忘录实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动。备忘录保存了原发器的状态,采用列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。

缺点:

  • 资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源。

6.7 观察者模式

观察者模式 (Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布 - 订阅(Publish/Subscribe)模式、模型 - 视图(Model/View)模式、源 - 监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。

举例:

观察者模式是使用频率最高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。

JavaScript中观察者模式的实现主要用事件模型,DOM事件。

js
// 发布者
+var pub = function () {
+  console.log('欢迎订阅!');
+};
+// 订阅者
+var sub = document.body;
+
+// 订阅者实现订阅
+sub.addEventListener('click', pub, false);

优点:

  • 观察者模式可以实现表示层和数据逻辑层的分离,定义了稳定的消息更新传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层充当具体观察者角色。
  • 观察者模式在观察目标和观察者之间建立一个抽象的耦合。观察目标只需要维持一个抽象观察者的集合,无须了解其具体观察者。由于观察目标和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
  • 观察者模式支持广播通信,观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
  • 观察者模式满足“开闭原则”的要求,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便。

缺点:

  • 如果一个观察目标对象有很多直接和间接观察者,将所有的观察者都通知到会花费很多时间。
  • 如果在观察者和观察目标之间存在循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
  • 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

6.8 状态模式

状态模式 (State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象 (Objects for States),其实就是用一个对象或者数组记录一组状态,每个状态对应一个实现,实现的时候根据状态挨个去运行实现。状态模式是一种对象行为型模式。

举例:

状态模式用于解决复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,所以对象在不同状态下具有不同行为时可以使用状态模式。状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化。

比如超级玛丽,就可能同时有好几个状态比如 跳跃,移动,射击,蹲下 等,如果对这些动作一个个进行处理判断,需要多个 if-else 或者 switch 不仅丑陋不说,而且在遇到有组合动作的时候,实现就会变的更为复杂,这里可以使用状态模式来实现。

状态模式的思路是:首先创建一个状态对象或者数组,内部保存状态变量,然后内部封装好每种动作对应的状态,然后状态对象返回一个接口对象,它可以对内部的状态修改或者调用。

js
class SuperMarry {
+  constructor() {
+    this._currentState = [];
+    this.states = {
+      jump() {
+        console.log('跳跃!');
+      },
+      move() {
+        console.log('移动!');
+      },
+      shoot() {
+        console.log('射击!');
+      },
+      squat() {
+        console.log('蹲下!');
+      },
+    };
+  }
+
+  change(arr) {
+    // 更改当前动作
+    this._currentState = arr;
+    return this;
+  }
+
+  go() {
+    console.log('触发动作');
+    this._currentState.forEach((T) => this.states[T] && this.states[T]());
+    return this;
+  }
+}
+
+new SuperMarry()
+  .change(['jump', 'shoot'])
+  .go() // 触发动作  跳跃!射击!
+  .go() // 触发动作  跳跃!射击!
+  .change(['squat'])
+  .go(); // 触发动作  蹲下!

优点:

  • 封装了状态的转换规则,在状态模式中可以将状态的转换代码封装在环境类或者具体状态类中,可以对状态转换代码进行集中管理,而不是分散在一个个业务方法中。
  • 将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。
  • 允许状态转换逻辑与状态对象合成一体,而不是提供一个巨大的条件语句块,状态模式可以让我们避免使用庞大的条件语句来将业务方法和状态转换代码交织在一起。
  • 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点:

  • 状态模式的使用必然会增加系统中类和对象的个数,导致系统运行开销增大。
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,增加系统设计的难度。
  • 状态模式对“开闭原则”的支持并不太好,增加新的状态类需要修改那些负责状态转换的源代码,否则无法转换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

6.9 策略模式

策略模式 (Strategy Pattern):定义一些列算法,把他们封装起来,并且可以相互替换。就是把看似毫无联系的代码提取封装、复用,使之更容易被理解和拓展。常见的用于一次 if 判断、switch 枚举、数据字典等流程判断语句中。也称为政策模式 (Policy)。策略模式是一种对象行为型模式。

举例:

使用策略模式时,我们可以定义一些策略类,每一个策略类中封装一种具体的算法。在这里,每一个封装算法的类我们都可以称之为一种策略,根据传入不同的策略类,使环境类执行不同策略类中的算法。

在游戏中,我们每玩完一局游戏都有对用户进行等级评价,比如 S 级 4 倍经验,A 级 3 倍经验,B 级 2 倍经验,其他 1 倍经验,用函数来表达如下:

js
// 改为策略模式 分成两个函数来写
+const strategy = {
+  S: function (experience) {
+    return 4 * experience;
+  },
+  A: function (experience) {
+    return 3 * experience;
+  },
+  B: function (experience) {
+    return 2 * experience;
+  },
+};
+// getExperience 可以复用
+function getExperience(strategy, level, experience) {
+  return level in strategy ? strategy[level](experience) : experience;
+}
+var s = getExperience(strategy, 'S', 100);
+var a = getExperience(strategy, 'A', 100);
+console.log(s, a); // 400 300
js
// 指令处理集合
+var compileUtil = {
+    // v-text 更新视图原理
+    text: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'text');
+    },
+    // v-html 更新视图原理
+    html: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'html');
+    },
+    // v-class 绑定原理
+    class: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'class');
+    },
+    bind: function(node, vm, exp, dir) {
+        // 不同指令触发视图更新
+        var updaterFn = updater[dir + 'Updater'];
+        updaterFn && updaterFn(node, this._getVMVal(vm, exp));
+        new Watcher(vm, exp, function(value, oldValue) {
+            updaterFn && updaterFn(node, value, oldValue);
+        });
+    }
+    ......
+}

优点:

  • 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
  • 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族,恰当使用继承可以把公共的代码移到抽象策略类中,从而避免重复的代码。
  • 策略模式提供了一种可以替换继承关系的办法。如果不使用策略模式,那么使用算法的环境类就可能会有一些子类,每一个子类提供一种不同的算法。但是,这样一来算法的使用就和算法本身混在一起,不符合“单一职责原则”,决定使用哪一种算法的逻辑和该算法本身混合在一起,从而不可能再独立演化;而且使用继承无法实现算法或行为在程序运行时的动态切换。
  • 使用策略模式可以避免多重条件选择语句。多重条件选择语句不易维护,它把采取哪一种算法或行为的逻辑与算法或行为本身的实现逻辑混合在一起,将它们全部硬编码 (Hard Coding) 在一个庞大的多重条件选择语句中,比直接继承环境类的办法还要原始和落后。
  • 策略模式提供了一种算法的复用机制,由于将算法单独提取出来封装在策略类中,因此不同的环境类可以方便地复用这些策略类。

缺点:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
  • 策略模式将造成系统产生很多具体策略类,任何细小的变化都将导致系统要增加一个新的具体策略类。
  • 无法同时在客户端使用多个策略类,也就是说,在使用策略模式时,客户端每次只能使用一个策略类,不支持使用一个策略类完成部分功能后再使用另一个策略类来完成剩余功能的情况。

6.10 模板方法模式

模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

举例:

模板方法模式的使用场景

  • 模板方法模式常被架构师用于搭建项目的框架,架构师定好了框架的骨架,程序员继承框架的结构之后,负责往里面填空
  • 钩子方法:各种框架中的钩子函数往往在初始化时就规定各个钩子函数的名称以及执行时机,对于使用者只需要在钩子函数中注入自定义逻辑代码即可
  • 回调函数:回调函数在特定的时机执行,但是具体的操作交给具体的函数实现。把变化的部分封装成一个函数剩下的就成了模板

模板方法模式具体应用又分为三类:

  • 抽象方法:一个抽象方法由抽象类声明、由其具体子类实现。

  • 具体方法:一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。

  • 钩子方法:一个钩子方法由一个抽象类或具体类声明并实现,而其子类可能会加以扩展。通常在父类中给出的实现是一个空实现,并以该空实现作为方法的默认实现,当然钩子方法也可以提供一个非空的默认实现。通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制。

泡一杯咖啡

先我们先来泡一杯咖啡,一般来说,泡咖啡的步骤通常如下:

1.先把水煮沸;

2.用沸水冲泡咖啡;

3.把咖啡倒进杯子;

4.加糖和牛奶。

我们用 es5 来得到一杯香浓的咖啡吧:

js
var Coffee = function () {};
+Coffee.prototype.boilWater = function () {
+  console.log('水煮开了');
+};
+Coffee.prototype.brewCoffeeGriends = function () {
+  console.log('用沸水冲泡咖啡');
+};
+Coffee.prototype.pourInCup = function () {
+  console.log('把咖啡倒进杯子');
+};
+Coffee.prototype.addSugarAndMilk = function () {
+  console.log('加糖和牛奶');
+};
+// 封装 将实现的细节交给类的内部
+Coffee.prototype.init = function () {
+  this.boilWater();
+  this.brewCoffeeGriends();
+  this.pourInCup();
+  this.addSugarAndMilk();
+};
+var coffee = new Coffee();
+coffee.init();

泡一壶茶

其实呢,泡茶的步骤跟泡咖啡的步骤相差不大,大致是这样的:

1.把水煮沸;

2.用沸水浸泡茶叶;

3.把茶水倒进杯子;

4.加柠檬。

来,咱用 es6 来泡茶:

js
class Tea {
+  constructor() {}
+  boilWater() {
+    console.log('把水烧开');
+  }
+  steepTeaBag() {
+    console.log('浸泡茶叶');
+  }
+  pourInCup() {
+    console.log('倒进杯子');
+  }
+  addLemon() {
+    console.log('加柠檬');
+  }
+  init() {
+    this.boilWater();
+    this.steepTeaBag();
+    this.pourInCup();
+    this.addLemon();
+  }
+}
+var tea = new Tea();
+tea.init();

现在到了思考的时间,我们刚刚泡了一杯咖啡和一壶茶,有没有觉得这两个过程是大同小异的。我们能很容易的就找出他们的共同点,不同点就是原料不同嘛,茶和咖啡,我们可以把他们抽象为"饮料"哇;泡的方式不同嘛,一个是冲泡,一个是浸泡,我们可以把这个行为抽象为"泡";加入的调料也不同咯,加糖和牛奶,加柠檬,它们也可以抽象为"调料"吖。

这么一分析,是不是很清楚了吖,我们整理一下就是:

1.把水煮沸;

2.用沸水冲泡饮料;

3.把饮料倒进杯子;

4.加调料。

大家请注意!大家请注意!主角来了!之前我们已经扔出了概念,所以我们现在可以创建一个抽象父类来表示泡一杯饮料的过程。那么,抽象父类?

抽象类?

抽象类是不能被实例化的,一定是用来继承的。继承了抽象类的所有子类都将拥有跟抽象类一致的接口方法,抽象类的主要作用就是为它的子类定义这些公共接口。

通过上面分析,这里具体来说就是要把泡茶和泡咖啡的共同步骤共同点找出来,封装到父类,也就是抽象类中,然后不同的步骤写在子类中,也就是茶和咖啡中。抽象类既然不能被实例化,不怕啊,子类就是他的实例化。

泡饮料啦!

js
var Beverage = function () {};
+Beverage.prototype.boilWater = function () {
+  console.log('把水煮沸');
+};
+Beverage.prototype.brew = function () {};
+Beverage.prototype.pourInCup = function () {};
+Beverage.prototype.addCondiments = function () {};
+// 抽象方法
+Beverage.prototype.init = function () {
+  this.boilWater();
+  this.brew();
+  this.pourInCup();
+  this.addCondiments();
+};
+var Coffee = function () {
+  // 将父类的构造方法拿来执行一下
+  Beverage.apply(this, arguments);
+  // 就像 es6 的 super 执行 执行后 this 才会有对象的属性
+};
+Coffee.prototype = new Beverage();
+var coffee = new Coffee();
+coffee.init();
+var Tea = function () {};
+Tea.prototype = new Beverage();
+Tea.prototype.brew = function () {
+  console.log('用沸水浸泡茶叶');
+};
+Tea.prototype.pourInCup = function () {
+  console.log('把茶叶倒进杯子');
+};
+Tea.prototype.addCondiments = function () {
+  console.log('加柠檬');
+};
+var tea = new Tea();
+tea.init();

这里既泡了咖啡又泡了茶,是不是没有之前那么繁琐呢,这里的代码可是很高级的呢。

这里用一个父类 Beverage 来表示 Coffee 和 Tea,然后子类就是后面的 Coffee 和 Tea 啦,因为这里的 Beverage 是一个抽象的存在,需要子类来继承它。泡饮品的流程,可以理解为一个模板模式,抽象类 Beverage,抽象方法 init() 在子类中实现。js 的继承是基于原型链的继承,这里 prototype 就是类的原型链。这里由于 coffee 对象和 tea 对象的原型 prototype 上都没有对应的 init(),所以请求会顺着原型链,找到父类 Beverage 的 init()。子类寻找对应的属性和方法的时候会顺着原型链去查找,先找自己,没有找到会顺着去父类里面查找。

Beverage.prototype.init 被称为模板方法的原因是,该方法中封装了子类的算法框架,它作为一个算法的模板,指导子类以何种顺序去执行哪些方法。

优点:

  • 在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。
  • 模板方法模式是一种代码复用技术,它在类库设计中尤为重要,它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为,它鼓励我们恰当使用继承来实现代码复用。
  • 可实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行。
  • 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则。

缺点:

  • 需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合桥接模式来进行设计。

6.11 访问者模式

访问者模式 (Visitor Pattern):提供一个作用于某对象结构中的各元素的操作表示,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。

举例:

访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。访问者模式使得用户可以在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作。

在使用访问者模式时,被访问元素通常不是单独存在的,它们存储在一个集合中,这个集合被称为「对象结构」,访问者通过遍历对象结构实现对其中存储的元素的逐个操作。

js
// 访问者模式:DOM 事件绑定
+var bindEvent = function(dom, type, fn, data) {
+    if (dom.addEventListener) {
+        dom.addEventListener(type, fn, false);
+    } else if (dom.attachEvent) {
+        // dom.attachEvent('on'+type, fn);
+        var data = data || {};
+        dom.attachEvent('on' + type, function(e) {
+            // 在 IE 中 this 指向 window,使用 call 改变 this 的指向
+            fn.call(dom, e, data);
+        });
+    } else {
+        dom['on' + type] = fn;
+    }
+}
+function $(id) {
+    return document.getElementById(id);
+}
+
+bindEvent($(demo), 'click', function() {
+    // this 指向 dom 对象
+    this.style.background = 'red';
+});
+
+bindEvent($('btn'), 'click', function(e, data) {
+    $('text').innerHTML = e.type + data.text + this.tagName;
+}, { text: 'demo' });

访问者模式的思想就是在不改变操作对象的同时,为它添加新的操作方法,以实现对操作对象的访问。我们知道,call 和 apply 的作用就是更改函数执行时的作用域,这正是访问者模式的精髓。通过 call、apply 这两种方式我们就可以让某个对象在其它作用域中运行。

js
// 数组方法封装
+var Visitor = (function() {
+    return {
+        splice: function() {
+            var args = Array.prototype.splice.call(arguments, 1);
+            return Array.prototype.splice.apply(arguments[0], args);
+        },
+        push: function() {
+            var len = arguments[0].length || 0;
+            var args = this.splice(arguments, 1);
+            arguments[0].length = len + arguments.length - 1;
+            return Array.prototype.push.apply(arguments[0], args);
+        },
+        pop: function() {
+            return Array.prototype.pop.apply(arguments[0]);
+        }
+    }
+})();
+
+var a = new Object();
+Visitor.push(a,1,2,3,4);
+Visitor.push(a,4,5,6);
+Visitor.pop(a);
+Visitor.splice(a,2);

访问者模式解决了数据与数据的操作方法之间的耦合,让数据的操作方法独立于数据,使其可以自由演变。因此,访问者模式更适合于那些数据稳定、但数据的操作方法易变的环境下。

优点:

  • 增加新的访问操作很方便。使用访问者模式,增加新的访问操作就意味着增加一个新的具体访问者类,实现简单,无须修改源代码,符合“开闭原则”。
  • 将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中。类的职责更加清晰,有利于对象结构中元素对象的复用,相同的对象结构可以供多个不同的访问者访问。
  • 让用户能够在不修改现有元素类层次结构的情况下,定义作用于该层次结构的操作。

缺点:

  • 增加新的元素类很困难。在访问者模式中,每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”的要求。
  • 破坏封装。访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问。

总结

系统地学习设计模式后,你可以在过往的开发经历中发现,设计模式是无处不在的。在学习设计模式之前的很多时候我们是凭借过往经验和智慧来完善系统的设计,而这些经验很多和某个设计模式的思想不谋而合。

还有一些地方没有完全理解,文中有误之处还望不吝指出。

参考资料

`,384)]))}const z=P(S,[["render",T]]);export{W as __pageData,z as default}; diff --git a/assets/cn_src_article_docPreview.md.CnTJNdd8.js b/assets/cn_src_article_docPreview.md.CnTJNdd8.js new file mode 100644 index 0000000000..cde6d54767 --- /dev/null +++ b/assets/cn_src_article_docPreview.md.CnTJNdd8.js @@ -0,0 +1,263 @@ +import{_ as i,o as a,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const t="/ran/assets/ms_ppt.C2zYd_IC.webp",p="/ran/assets/ms_excel.CJXFi2bf.webp",l="/ran/assets/ms_word.3k-0mjp0.webp",k="/ran/assets/ms_file_not.DgOrkG3n.webp",e="/ran/assets/ms_answer.Cgv6ylFF.webp",r="/ran/assets/ms_answer_2.D-D9H1v0.webp",E="/ran/assets/google_doc_view.BknjnOKw.webp",d="/ran/assets/ali_doc.CYo30EHy.webp",g="/ran/assets/xdoc.CeowcMPq.webp",o="/ran/assets/ow365.CXWyYekS.webp",y="/ran/assets/wps_office.DiET-U8x.webp",c="/ran/assets/wps_office_price.ler9htjh.webp",F="/ran/assets/xml.NyzOyhr4.webp",C="/ran/assets/firefox_pdf.BWQR-ogn.webp",f="/ran/assets/mdn_pdf.DbNmeC8H.webp",u="/ran/assets/kkfile_des.CENUMtpY.webp",A="/ran/assets/kkfile.X1tAqvNa.webp",m="/ran/assets/kkfile_output.DD8iZdbo.webp",B="/ran/assets/kkfile_doc.CPfEUxoD.webp",O=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/docPreview.md","filePath":"cn/src/article/docPreview.md","lastUpdated":1726550590000}'),D={name:"cn/src/article/docPreview.md"};function b(x,s,v,w,_,P){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h('

最全的 docx,pptx,xlsx(excel),pdf 文件预览方案总结

最近遇到了文件预览的需求,但一搜索发现,这还不是一个简单的功能。于是又去查询了很多资料,调研了一些方案,也踩了好多坑。最后总结方案如下

  1. 花钱解决 (使用市面上现有的文件预览服务)
    1. 微软
    2. google
    3. 阿里云 IMM
    4. XDOC
    5. Office Web 365
    6. wps 开放平台
  2. 前端方案
    1. pptx 的预览方案
    2. pdf 的预览方案
    3. docx 的预览方案
    4. xlsx(excel) 的预览方案
    5. 前端预览方案总结
  3. 服务端方案
    1. openOffice
    2. kkFileView
    3. onlyOffice

如果有其他人也遇到了同样的问题,有了这篇文章,希望能更方便的解决。

基本涵盖了所有解决方案。因此,标题写上 最全 的文件预览方案调研总结,应该不为过吧。

一:市面上现有的文件预览服务

1.微软

docx,pptx,xlsx可以说是office三件套,那自然得看一下 微软官方 提供的文件预览服务。使用方法特别简单,只需要将文件链接,拼接到参数后面即可。

记得encodeURL

js
https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}

(1).PPTX 预览效果:

image.png

  • 优点:还原度很高,功能很丰富,可以选择翻页,甚至支持点击播放动画。
  • 缺点:不知道是不是墙的原因,加载稍慢。

(2).Excel 预览效果:

image.png

(3).Doxc 预览效果

image.png

(4).PDF 预览效果

这个我测试没有成功,返回了一个错误,其他人可以试试。

image.png

(5).总的来说

对于docx,pptx,xlsx都有较好的支持,pdf不行。

还有一个坑点是:这个服务是否稳定,有什么限制,是否收费,都查不到一个定论。在office官方网站上甚至找不到介绍这个东西的地方。

目前只能找到一个Q&A:https://answers.microsoft.com/en-us/msoffice/forum/all/what-is-the-status-of-viewofficeappslivecom/830fd75c-9b47-43f9-89c9-4303703fd7f6

微软官方人员回答表示:

image.png

翻译翻译,就是:几乎永久使用,没有收费计划,不会存储预览的文件数据,限制文件10MB,建议用于 查看互联网上公开的文件

但经过某些用户测试发现:

image.png

使用了微软的文件预览服务,然后删除了文件地址,仍然可访问,但过一段时间会失效。

2.Google Drive 查看器

接入简单,同 Office Web Viewer,只需要把 src 改为https://drive.google.com/viewer?url=${encodeURIComponent(url)}即可。

限制25MB,支持以下格式:

image.png

测试效果,支持docx,pptx,xlsx,pdf预览,但pptx预览的效果不如微软,没有动画效果,样式有小部分会错乱。

由于某些众所周知的原因,不可用

3.阿里云 IMM

官方文档如下:https://help.aliyun.com/document_detail/63273.html

image.png

付费使用

4.XDOC 文档预览

说了一些大厂的,在介绍一些其他的,需要自行分辨

官网地址:https://view.xdocin.com/view-xdocin-com_6x5f4x.htm

image.png

5.Office Web 365

需要注意的是,虽然名字很像office,但我们看网页的Copyright可以发现,其实是一个西安的公司,不是微软

但毕竟也提供了文件预览的服务

官网地址:https://www.officeweb365.com/

image.png

6.WPS 开放平台

官方地址:https://solution.wps.cn/

image.png

付费使用,价格如下:

image.png

二:前端处理方案

1.pptx 的预览方案

先查一下有没有现成的轮子,目前pptx的开源预览方案能找到的只有这个:https://github.com/g21589/PPTX2HTML。但已经六七年没有更新,也没有维护,笔者使用的时候发现有很多兼容性问题。

简单来说就是,没有。对于这种情况,我们可以自行解析,主要步骤如下:

  1. 查询pptx的国际标准
  2. 解析pptx文件
  3. 渲染成html或者canvas进行展示

我们先去找一下pptx的国际标准,官方地址:officeopenxml

先解释下什么是officeopenxml:

Office OpenXML,也称为 OpenXML 或 OOXML,是一种基于 XML 的办公文档格式,包括文字处理文档、电子表格、演示文稿以及图表、图表、形状和其他图形材料。该规范由微软开发,并于 2006 年被 ECMA 国际采用为 ECMA-376。第二个版本于 2008 年 12 月发布,第三个版本于 2011 年 6 月发布。该规范已被 ISO 和 IEC 采用为 ISO/IEC 29500。

虽然 Microsoft 继续支持较旧的二进制格式 (.doc、.xls 和.ppt),但 OOXML 现在是所有 Microsoft Office 文档 (.docx、.xlsx 和.pptx) 的默认格式。

由此可见,Office OpenXML由微软开发,目前已经是国际标准。接下来我们看一下pptx里面有哪些内容,具体可以看pptx的官方标准:officeopenxml-pptx

PresentationML 或.pptx 文件是一个zip 文件,其中包含许多“部分”(通常是 UTF-8 或 UTF-16 编码)或 XML 文件。该包还可能包含其他媒体文件,例如图像。该结构根据 OOXML 标准 ECMA-376 第 2 部分中概述的开放打包约定进行组织。

image.png

根据国际标准,我们知道,pptx文件本质就是一个zip文件,其中包含许多部分:

部件的数量和类型将根据演示文稿中的内容而有所不同,但始终会有一个 [Content_Types].xml、一个或多个关系(.rels)部件和一个演示文稿部件(演示文稿.xml),它位于 ppt 文件夹中,用于 Microsoft Powerpoint 文件。通常,还将至少有一个幻灯片部件,以及一张母版幻灯片和一张版式幻灯片,从中形成幻灯片。

那么js如何读取zip呢?

找到一个工具:https://www.npmjs.com/package/jszip

于是我们可以开始尝试解析pptx了。

ts
import JSZip from 'jszip';
+// 加载 pptx 数据
+const zip = await JSZip.loadAsync(pptxData);
  • 解析[Content_Types].xml

每个pptx必然会有一个 [Content_Types].xml。此文件包含包中部件的所有内容类型的列表。每个部件及其类型都必须列在 [Content_Types].xml 中。通过它里面的内容,可以解析其他的文件数据

ts
const filesInfo = await getContentTypes(zip);
+
+async function getContentTypes(zip: JSZip) {
+  const ContentTypesJson = await readXmlFile(zip, '[Content_Types].xml');
+  const subObj = ContentTypesJson['Types']['Override'];
+  const slidesLocArray = [];
+  const slideLayoutsLocArray = [];
+  for (let i = 0; i < subObj.length; i++) {
+    switch (subObj[i]['attrs']['ContentType']) {
+      case 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml':
+        slidesLocArray.push(subObj[i]['attrs']['PartName'].substr(1));
+        break;
+      case 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml':
+        slideLayoutsLocArray.push(subObj[i]['attrs']['PartName'].substr(1));
+        break;
+      default:
+    }
+  }
+  return {
+    slides: slidesLocArray,
+    slideLayouts: slideLayoutsLocArray,
+  };
+}
  • 解析演示文稿

先获取ppt目录下的presentation.xml演示文稿的大小

由于演示文稿是xml格式,要真正的读取内容需要执行 readXmlFile

ts
const slideSize = await getSlideSize(zip);
+async function getSlideSize(zip: JSZip) {
+  const content = await readXmlFile(zip, 'ppt/presentation.xml');
+  const sldSzAttrs = content['p:presentation']['p:sldSz']['attrs'];
+  return {
+    width: (parseInt(sldSzAttrs['cx']) * 96) / 914400,
+    height: (parseInt(sldSzAttrs['cy']) * 96) / 914400,
+  };
+}
  • 加载主题

根据 officeopenxml的标准解释

每个包都包含一个关系部件,用于定义其他部件之间的关系以及与包外部资源的关系。这样可以将关系与内容分开,并且可以轻松地更改关系,而无需更改引用目标的源。

除了包的关系部分之外,作为一个或多个关系源的每个部件都有自己的关系部分。每个这样的关系部件都可以在部件的_rels 子文件夹中找到,并通过在部件名称后附加“.rels”来命名。

其中主题的相关信息就在ppt/_rels/presentation.xml.rels

ts
async function loadTheme(zip: JSZip) {
+  const preResContent = await readXmlFile(zip, 'ppt/_rels/presentation.xml.rels');
+  const relationshipArray = preResContent['Relationships']['Relationship'];
+  let themeURI;
+  if (relationshipArray.constructor === Array) {
+    for (let i = 0; i < relationshipArray.length; i++) {
+      if (
+        relationshipArray[i]['attrs']['Type'] ===
+        'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme'
+      ) {
+        themeURI = relationshipArray[i]['attrs']['Target'];
+        break;
+      }
+    }
+  } else if (
+    relationshipArray['attrs']['Type'] === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme'
+  ) {
+    themeURI = relationshipArray['attrs']['Target'];
+  }
+
+  if (themeURI === undefined) {
+    throw Error("Can't open theme file.");
+  }
+
+  return readXmlFile(zip, 'ppt/' + themeURI);
+}

后续ppt里面的其他内容,都可以这么去解析。根据officeopenxml标准,可能包含:

"+X+""+X+""+$+"
"+Lt+"
PartDescription
Comments AuthorsContains information about each author who has added a comment to the presentation.
CommentsContains comments for a single slide.
Handout MasterContains the look, position, and size of the slides, notes, header and footer text, date, or page number on the presentation's handout. There can be only one such part.
Notes MasterContains information about the content and formatting of all notes pages. There can be only one such part.
Notes SlideContains the notes for a single slide.
PresentationContains the definition of a slide presentation. There must be one and only one such part. See Presentation.
Presentation PropertiesContains all of the presentation's properties. There must be one and only one such part.
SlideContains the content of a single slide.
Slide LayoutContains the definition for a slide template. It defines the default appearance and positioning of drawing objects on the slide. There must be one or more such parts.
Slide MasterContains the master definition of formatting, text, and objects that appear on each slide in the presentation that is derived from the slide master. There must be one or more such parts.
Slide Synchronization DataContains properties specifying the current state of a slide that is being synchronized with a version of the slide stored on a central server.
User-Defined TagsContains a set of user-defined properties for an object in a presentation. There can be zero or more such parts.
View PropertiesContains display properties for the presentation.

等等内容,我们根据标准一点点解析并渲染就好了。

完整源码:ranui

使用文档:preview 组件

2.pdf 的预览方案

(1).iframe 和 embed

pdf比较特别,一般的浏览器默认支持预览pdf。因此,我们可以使用浏览器的能力:

html
<iframe src="viewFileUrl" />

但这样就完全依赖浏览器,对PDF的展示,交互,是否支持全看浏览器的能力,且不同的浏览器展示和交互往往不同,如果需要统一的话,最好还是尝试其他方案。

embed的解析方式也是一样,这里不举例子了

(2)pdfjs

npm: https://www.npmjs.com/package/pdfjs-dist

github 地址:https://github.com/mozilla/pdfjs-dist

mozilla出品,就是我们常见的MDN的老大。

而且目前 火狐浏览器 使用的 PDF 预览就是采用这个,我们可以用火狐浏览器打开pdf文件,查看浏览器使用的js就能发现

image.png

需要注意的是,最新版pdf.js限制了node版本,需要大于等于18

github 链接:https://github.com/mozilla/pdf.js/blob/master/package.json

image.png

如果你项目node版本小于这个情况,可能会无法使用。

如果遇到这种情况,可以用以前版本,以前的版本没有限制。

具体使用情况如下:

ts
import * as pdfjs from 'pdfjs-dist';
+import * as pdfjsWorker from 'pdfjs-dist/build/pdf.work.entry';
+
+interface Viewport {
+  width: number;
+  height: number;
+  viewBox: Array<number>;
+}
+
+interface RenderContext {
+  canvasContext: CanvasRenderingContext2D | null;
+  transform: Array<number>;
+  viewport: Viewport;
+}
+
+interface PDFPageProxy {
+  pageNumber: number;
+  getViewport: () => Viewport;
+  render: (options: RenderContext) => void;
+}
+
+interface PDFDocumentProxy {
+  numPages: number;
+  getPage: (x: number) => Promise<PDFPageProxy>;
+}
+
+class PdfPreview {
+  private pdfDoc: PDFDocumentProxy | undefined;
+  pageNumber: number;
+  total: number;
+  dom: HTMLElement;
+  pdf: string | ArrayBuffer;
+  constructor(pdf: string | ArrayBuffer, dom: HTMLElement | undefined) {
+    this.pageNumber = 1;
+    this.total = 0;
+    this.pdfDoc = undefined;
+    this.pdf = pdf;
+    this.dom = dom ? dom : document.body;
+  }
+  private getPdfPage = (number: number) => {
+    return new Promise((resolve, reject) => {
+      if (this.pdfDoc) {
+        this.pdfDoc.getPage(number).then((page: PDFPageProxy) => {
+          const viewport = page.getViewport();
+          const canvas = document.createElement('canvas');
+          this.dom.appendChild(canvas);
+          const context = canvas.getContext('2d');
+          const [_, __, width, height] = viewport.viewBox;
+          canvas.width = width;
+          canvas.height = height;
+          viewport.width = width;
+          viewport.height = height;
+          canvas.style.width = Math.floor(viewport.width) + 'px';
+          canvas.style.height = Math.floor(viewport.height) + 'px';
+          const renderContext = {
+            canvasContext: context,
+            viewport: viewport,
+            transform: [1, 0, 0, -1, 0, viewport.height],
+          };
+          page.render(renderContext);
+          resolve({ success: true, data: page });
+        });
+      } else {
+        reject({ success: false, data: null, message: 'pdfDoc is undefined' });
+      }
+    });
+  };
+  pdfPreview = () => {
+    window.pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;
+    window.pdfjsLib.getDocument(this.pdf).promise.then(async (doc: PDFDocumentProxy) => {
+      this.pdfDoc = doc;
+      this.total = doc.numPages;
+      for (let i = 1; i <= this.total; i++) {
+        await this.getPdfPage(i);
+      }
+    });
+  };
+  prevPage = () => {
+    if (this.pageNumber > 1) {
+      this.pageNumber -= 1;
+    } else {
+      this.pageNumber = 1;
+    }
+    this.getPdfPage(this.pageNumber);
+  };
+  nextPage = () => {
+    if (this.pageNumber < this.total) {
+      this.pageNumber += 1;
+    } else {
+      this.pageNumber = this.total;
+    }
+    this.getPdfPage(this.pageNumber);
+  };
+}
+
+const createReader = (file: File): Promise<string | ArrayBuffer | null> => {
+  return new Promise((resolve, reject) => {
+    const reader = new FileReader();
+    reader.readAsDataURL(file);
+    reader.onload = () => {
+      resolve(reader.result);
+    };
+    reader.onerror = (error) => {
+      reject(error);
+    };
+    reader.onabort = (abort) => {
+      reject(abort);
+    };
+  });
+};
+
+export const renderPdf = async (file: File, dom?: HTMLElement): Promise<void> => {
+  try {
+    if (typeof window !== 'undefined') {
+      const pdf = await createReader(file);
+      if (pdf) {
+        const PDF = new PdfPreview(pdf, dom);
+        PDF.pdfPreview();
+      }
+    }
+  } catch (error) {
+    console.log('renderPdf', error);
+  }
+};

3.docx 的预览方案

我们可以去查看docx的国际标准,去解析文件格式,渲染成htmlcanvas,不过比较好的是,已经有人这么做了,还开源了

npm地址:https://www.npmjs.com/package/docx-preview

使用方法如下:

ts
import { renderAsync } from 'docx-preview';
+
+interface DocxOptions {
+  bodyContainer?: HTMLElement | null;
+  styleContainer?: HTMLElement;
+  buffer: Blob;
+  docxOptions?: Partial<Record<string, string | boolean>>;
+}
+
+export const renderDocx = (options: DocxOptions): Promise<void> | undefined => {
+  if (typeof window !== 'undefined') {
+    const { bodyContainer, styleContainer, buffer, docxOptions = {} } = options;
+    const defaultOptions = {
+      className: 'docx',
+      ignoreLastRenderedPageBreak: false,
+    };
+    const configuration = Object.assign({}, defaultOptions, docxOptions);
+    if (bodyContainer) {
+      return renderAsync(buffer, bodyContainer, styleContainer, configuration);
+    } else {
+      const contain = document.createElement('div');
+      document.body.appendChild(contain);
+      return renderAsync(buffer, contain, styleContainer, configuration);
+    }
+  }
+};

4.xlsx 的预览方案

我们可以使用这个:

npm地址:https://www.npmjs.com/package/@vue-office/excel

支持vue2vue3,也有js的版本

对于xlsx的预览方案,这个是找到最好用的了。

5.前端预览方案总结

我们对以上找到的优秀的解决方案,进行改进和总结,并封装成一个web components组件:preview 组件

为什么是web components组件?

因为它跟框架无关,可以在任何框架中使用,且使用起来跟原生的div标签一样方便。

并编写使用文档:preview 组件文档, 文档支持交互体验。

源码公开,MIT协议。

目前docx,pdf,xlsx预览基本可以了,都是最好的方案。pptx预览效果不太好,因为需要自行解析。不过源码完全公开,需要的可以提issuepr或者干脆自取或修改,源码地址:https://github.com/chaxus/ran/tree/main/packages/ranui

三:服务端预览方案

1.openOffice

由于浏览器不能直接打开docx,pptx,xlsx等格式文件,但可以直接打开pdf和图片。因此,我们可以换一个思路,用服务端去转换下文件的格式,转换成浏览器能识别的格式,然后再让浏览器打开,这不就 OK 了吗,甚至不需要前端处理了。

我们可以借助openOffice的能力,先介绍一下openOffice:

Apache OpenOffice是领先的开源办公软件套件,用于文字处理,电子表格,演示文稿,图形,数据库等。它有多种语言版本,适用于所有常用计算机。它以国际开放标准格式存储您的所有数据,还可以从其他常见的办公软件包中读取和写入文件。它可以出于任何目的完全免费下载和使用。

官网如下:https://www.openoffice.org/

需要先下载opneOffice,找到bin目录,进行设置

java
configuration.setOfficeHome("这里的路径一般为 C:\\\\Program Files (x86)\\\\OpenOffice 4");

测试下转换的文件路径

java
    public static void main(String[] args) {
+        convertToPDF("/Users/Desktop/asdf.docx", "/Users/Desktop/adsf.pdf");
+    }

完整如下:

java

+package org.example;
+
+import org.artofsolving.jodconverter.OfficeDocumentConverter;
+import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
+import org.artofsolving.jodconverter.office.OfficeManager;
+
+import java.io.File;
+
+public class OfficeUtil {
+
+    private static OfficeManager officeManager;
+    private static int port[] = {8100};
+
+    /**
+     * start openOffice service.
+     */
+    public static void startService() {
+        DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();
+        try {
+            System.out.println("准备启动 office 转换服务....");
+            configuration.setOfficeHome("这里的路径一般为 C:\\\\Program Files (x86)\\\\OpenOffice 4");
+            configuration.setPortNumbers(port); // 设置转换端口,默认为 8100
+            configuration.setTaskExecutionTimeout(1000 * 60 * 30L);// 设置任务执行超时为 30 分钟
+            configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L);// 设置任务队列超时为 24 小时
+            officeManager = configuration.buildOfficeManager();
+            officeManager.start(); // 启动服务
+            System.out.println("office 转换服务启动成功!");
+        } catch (Exception e) {
+            System.out.println("office 转换服务启动失败!详细信息:" + e);
+        }
+    }
+
+    /**
+     * stop openOffice service.
+     */
+    public static void stopService() {
+        System.out.println("准备关闭 office 转换服务....");
+        if (officeManager != null) {
+            officeManager.stop();
+        }
+        System.out.println("office 转换服务关闭成功!");
+    }
+
+    public static void convertToPDF(String inputFile, String outputFile) {
+        startService();
+        System.out.println("进行文档转换转换:" + inputFile + " --> " + outputFile);
+        OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
+        converter.convert(new File(inputFile), new File(outputFile));
+        stopService();
+    }
+
+    public static void main(String[] args) {
+        convertToPDF("/Users/koolearn/Desktop/asdf.docx", "/Users/koolearn/Desktop/adsf.pdf");
+    }
+}

2.kkFileView

github地址:https://github.com/kekingcn/kkFileView

支持的文件预览格式非常丰富 image.png

接下来是 从零到一 的启动步骤,按着步骤来,任何人都能搞定

  1. 安装java:
sh
brew install java
  1. 安装maven,java的包管理工具:
sh
brew install mvn
  1. 检查是否安装成功

执行java --versionmvn -v。我这里遇到mvn找不到java home的报错。解决方式如下:

我用的是zsh,所以需要去.zshrc添加路径:

export JAVA_HOME=$(/usr/libexec/java_home)

添加完后,执行

source .zshrc
  1. 安装下libreoffice :

kkFileView明确要求的额外依赖,否则无法启动

brew install libreoffice
  1. mvn安装依赖

进入项目,在根目录执行依赖安装,同时清理缓存,跳过单测 (遇到了单测报错的问题)

mvn clean install -DskipTests
  1. 启动项目

找到主文件,主函数mian,点击vscode上面的Run即可执行,路径如下图

image.png

  1. 访问页面

启动完成后,点击终端输出的地址

image.png

  1. 最终结果

最终展示如下,可以添加链接进行预览,也可以选择本地文件进行预览

image.png

预览效果非常好

3.onlyOffice

官网地址:https://www.onlyoffice.com/zh

github地址:https://github.com/ONLYOFFICE

开发者版本和社区版免费,企业版付费:https://www.onlyoffice.com/zh/docs-enterprise-prices.aspx

预览的文件种类没有kkFileView多,但对office三件套有很好的支持,甚至支持多人编辑。

四:总结

  1. 外部服务,推荐微软的view.officeapps.live.com/op/view.aspx,但只建议预览一些互联网公开的文件,不建议使用在要求保密性和稳定性的文件。
  2. 对保密性和稳定性有要求,且不差钱的,可以试试大厂服务,阿里云解决方案。
  3. 服务端技术比较给力的,使用服务端预览方案。目前最好最全的效果是服务端预览方案。
  4. 不想花钱,没有服务器的,使用前端预览方案,客户端渲染零成本。

五:参考文档:

  1. 在 java 中如何使用 openOffice 进行格式转换
  2. MAC 搭建 OpenOffice 完整教程 - 保姆级
  3. 纯 js 实现 docx、xlsx、pdf 文件预览库,使用超简单
  4. 前端实现 word、excel、pdf、ppt、mp4、图片、文本等文件的预览
',178)]))}const j=i(D,[["render",b]]);export{O as __pageData,j as default}; diff --git a/assets/cn_src_article_docPreview.md.CnTJNdd8.lean.js b/assets/cn_src_article_docPreview.md.CnTJNdd8.lean.js new file mode 100644 index 0000000000..cde6d54767 --- /dev/null +++ b/assets/cn_src_article_docPreview.md.CnTJNdd8.lean.js @@ -0,0 +1,263 @@ +import{_ as i,o as a,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const t="/ran/assets/ms_ppt.C2zYd_IC.webp",p="/ran/assets/ms_excel.CJXFi2bf.webp",l="/ran/assets/ms_word.3k-0mjp0.webp",k="/ran/assets/ms_file_not.DgOrkG3n.webp",e="/ran/assets/ms_answer.Cgv6ylFF.webp",r="/ran/assets/ms_answer_2.D-D9H1v0.webp",E="/ran/assets/google_doc_view.BknjnOKw.webp",d="/ran/assets/ali_doc.CYo30EHy.webp",g="/ran/assets/xdoc.CeowcMPq.webp",o="/ran/assets/ow365.CXWyYekS.webp",y="/ran/assets/wps_office.DiET-U8x.webp",c="/ran/assets/wps_office_price.ler9htjh.webp",F="/ran/assets/xml.NyzOyhr4.webp",C="/ran/assets/firefox_pdf.BWQR-ogn.webp",f="/ran/assets/mdn_pdf.DbNmeC8H.webp",u="/ran/assets/kkfile_des.CENUMtpY.webp",A="/ran/assets/kkfile.X1tAqvNa.webp",m="/ran/assets/kkfile_output.DD8iZdbo.webp",B="/ran/assets/kkfile_doc.CPfEUxoD.webp",O=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/docPreview.md","filePath":"cn/src/article/docPreview.md","lastUpdated":1726550590000}'),D={name:"cn/src/article/docPreview.md"};function b(x,s,v,w,_,P){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h('

最全的 docx,pptx,xlsx(excel),pdf 文件预览方案总结

最近遇到了文件预览的需求,但一搜索发现,这还不是一个简单的功能。于是又去查询了很多资料,调研了一些方案,也踩了好多坑。最后总结方案如下

  1. 花钱解决 (使用市面上现有的文件预览服务)
    1. 微软
    2. google
    3. 阿里云 IMM
    4. XDOC
    5. Office Web 365
    6. wps 开放平台
  2. 前端方案
    1. pptx 的预览方案
    2. pdf 的预览方案
    3. docx 的预览方案
    4. xlsx(excel) 的预览方案
    5. 前端预览方案总结
  3. 服务端方案
    1. openOffice
    2. kkFileView
    3. onlyOffice

如果有其他人也遇到了同样的问题,有了这篇文章,希望能更方便的解决。

基本涵盖了所有解决方案。因此,标题写上 最全 的文件预览方案调研总结,应该不为过吧。

一:市面上现有的文件预览服务

1.微软

docx,pptx,xlsx可以说是office三件套,那自然得看一下 微软官方 提供的文件预览服务。使用方法特别简单,只需要将文件链接,拼接到参数后面即可。

记得encodeURL

js
https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}

(1).PPTX 预览效果:

image.png

  • 优点:还原度很高,功能很丰富,可以选择翻页,甚至支持点击播放动画。
  • 缺点:不知道是不是墙的原因,加载稍慢。

(2).Excel 预览效果:

image.png

(3).Doxc 预览效果

image.png

(4).PDF 预览效果

这个我测试没有成功,返回了一个错误,其他人可以试试。

image.png

(5).总的来说

对于docx,pptx,xlsx都有较好的支持,pdf不行。

还有一个坑点是:这个服务是否稳定,有什么限制,是否收费,都查不到一个定论。在office官方网站上甚至找不到介绍这个东西的地方。

目前只能找到一个Q&A:https://answers.microsoft.com/en-us/msoffice/forum/all/what-is-the-status-of-viewofficeappslivecom/830fd75c-9b47-43f9-89c9-4303703fd7f6

微软官方人员回答表示:

image.png

翻译翻译,就是:几乎永久使用,没有收费计划,不会存储预览的文件数据,限制文件10MB,建议用于 查看互联网上公开的文件

但经过某些用户测试发现:

image.png

使用了微软的文件预览服务,然后删除了文件地址,仍然可访问,但过一段时间会失效。

2.Google Drive 查看器

接入简单,同 Office Web Viewer,只需要把 src 改为https://drive.google.com/viewer?url=${encodeURIComponent(url)}即可。

限制25MB,支持以下格式:

image.png

测试效果,支持docx,pptx,xlsx,pdf预览,但pptx预览的效果不如微软,没有动画效果,样式有小部分会错乱。

由于某些众所周知的原因,不可用

3.阿里云 IMM

官方文档如下:https://help.aliyun.com/document_detail/63273.html

image.png

付费使用

4.XDOC 文档预览

说了一些大厂的,在介绍一些其他的,需要自行分辨

官网地址:https://view.xdocin.com/view-xdocin-com_6x5f4x.htm

image.png

5.Office Web 365

需要注意的是,虽然名字很像office,但我们看网页的Copyright可以发现,其实是一个西安的公司,不是微软

但毕竟也提供了文件预览的服务

官网地址:https://www.officeweb365.com/

image.png

6.WPS 开放平台

官方地址:https://solution.wps.cn/

image.png

付费使用,价格如下:

image.png

二:前端处理方案

1.pptx 的预览方案

先查一下有没有现成的轮子,目前pptx的开源预览方案能找到的只有这个:https://github.com/g21589/PPTX2HTML。但已经六七年没有更新,也没有维护,笔者使用的时候发现有很多兼容性问题。

简单来说就是,没有。对于这种情况,我们可以自行解析,主要步骤如下:

  1. 查询pptx的国际标准
  2. 解析pptx文件
  3. 渲染成html或者canvas进行展示

我们先去找一下pptx的国际标准,官方地址:officeopenxml

先解释下什么是officeopenxml:

Office OpenXML,也称为 OpenXML 或 OOXML,是一种基于 XML 的办公文档格式,包括文字处理文档、电子表格、演示文稿以及图表、图表、形状和其他图形材料。该规范由微软开发,并于 2006 年被 ECMA 国际采用为 ECMA-376。第二个版本于 2008 年 12 月发布,第三个版本于 2011 年 6 月发布。该规范已被 ISO 和 IEC 采用为 ISO/IEC 29500。

虽然 Microsoft 继续支持较旧的二进制格式 (.doc、.xls 和.ppt),但 OOXML 现在是所有 Microsoft Office 文档 (.docx、.xlsx 和.pptx) 的默认格式。

由此可见,Office OpenXML由微软开发,目前已经是国际标准。接下来我们看一下pptx里面有哪些内容,具体可以看pptx的官方标准:officeopenxml-pptx

PresentationML 或.pptx 文件是一个zip 文件,其中包含许多“部分”(通常是 UTF-8 或 UTF-16 编码)或 XML 文件。该包还可能包含其他媒体文件,例如图像。该结构根据 OOXML 标准 ECMA-376 第 2 部分中概述的开放打包约定进行组织。

image.png

根据国际标准,我们知道,pptx文件本质就是一个zip文件,其中包含许多部分:

部件的数量和类型将根据演示文稿中的内容而有所不同,但始终会有一个 [Content_Types].xml、一个或多个关系(.rels)部件和一个演示文稿部件(演示文稿.xml),它位于 ppt 文件夹中,用于 Microsoft Powerpoint 文件。通常,还将至少有一个幻灯片部件,以及一张母版幻灯片和一张版式幻灯片,从中形成幻灯片。

那么js如何读取zip呢?

找到一个工具:https://www.npmjs.com/package/jszip

于是我们可以开始尝试解析pptx了。

ts
import JSZip from 'jszip';
+// 加载 pptx 数据
+const zip = await JSZip.loadAsync(pptxData);
  • 解析[Content_Types].xml

每个pptx必然会有一个 [Content_Types].xml。此文件包含包中部件的所有内容类型的列表。每个部件及其类型都必须列在 [Content_Types].xml 中。通过它里面的内容,可以解析其他的文件数据

ts
const filesInfo = await getContentTypes(zip);
+
+async function getContentTypes(zip: JSZip) {
+  const ContentTypesJson = await readXmlFile(zip, '[Content_Types].xml');
+  const subObj = ContentTypesJson['Types']['Override'];
+  const slidesLocArray = [];
+  const slideLayoutsLocArray = [];
+  for (let i = 0; i < subObj.length; i++) {
+    switch (subObj[i]['attrs']['ContentType']) {
+      case 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml':
+        slidesLocArray.push(subObj[i]['attrs']['PartName'].substr(1));
+        break;
+      case 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml':
+        slideLayoutsLocArray.push(subObj[i]['attrs']['PartName'].substr(1));
+        break;
+      default:
+    }
+  }
+  return {
+    slides: slidesLocArray,
+    slideLayouts: slideLayoutsLocArray,
+  };
+}
  • 解析演示文稿

先获取ppt目录下的presentation.xml演示文稿的大小

由于演示文稿是xml格式,要真正的读取内容需要执行 readXmlFile

ts
const slideSize = await getSlideSize(zip);
+async function getSlideSize(zip: JSZip) {
+  const content = await readXmlFile(zip, 'ppt/presentation.xml');
+  const sldSzAttrs = content['p:presentation']['p:sldSz']['attrs'];
+  return {
+    width: (parseInt(sldSzAttrs['cx']) * 96) / 914400,
+    height: (parseInt(sldSzAttrs['cy']) * 96) / 914400,
+  };
+}
  • 加载主题

根据 officeopenxml的标准解释

每个包都包含一个关系部件,用于定义其他部件之间的关系以及与包外部资源的关系。这样可以将关系与内容分开,并且可以轻松地更改关系,而无需更改引用目标的源。

除了包的关系部分之外,作为一个或多个关系源的每个部件都有自己的关系部分。每个这样的关系部件都可以在部件的_rels 子文件夹中找到,并通过在部件名称后附加“.rels”来命名。

其中主题的相关信息就在ppt/_rels/presentation.xml.rels

ts
async function loadTheme(zip: JSZip) {
+  const preResContent = await readXmlFile(zip, 'ppt/_rels/presentation.xml.rels');
+  const relationshipArray = preResContent['Relationships']['Relationship'];
+  let themeURI;
+  if (relationshipArray.constructor === Array) {
+    for (let i = 0; i < relationshipArray.length; i++) {
+      if (
+        relationshipArray[i]['attrs']['Type'] ===
+        'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme'
+      ) {
+        themeURI = relationshipArray[i]['attrs']['Target'];
+        break;
+      }
+    }
+  } else if (
+    relationshipArray['attrs']['Type'] === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme'
+  ) {
+    themeURI = relationshipArray['attrs']['Target'];
+  }
+
+  if (themeURI === undefined) {
+    throw Error("Can't open theme file.");
+  }
+
+  return readXmlFile(zip, 'ppt/' + themeURI);
+}

后续ppt里面的其他内容,都可以这么去解析。根据officeopenxml标准,可能包含:

PartDescription
Comments AuthorsContains information about each author who has added a comment to the presentation.
CommentsContains comments for a single slide.
Handout MasterContains the look, position, and size of the slides, notes, header and footer text, date, or page number on the presentation's handout. There can be only one such part.
Notes MasterContains information about the content and formatting of all notes pages. There can be only one such part.
Notes SlideContains the notes for a single slide.
PresentationContains the definition of a slide presentation. There must be one and only one such part. See Presentation.
Presentation PropertiesContains all of the presentation's properties. There must be one and only one such part.
SlideContains the content of a single slide.
Slide LayoutContains the definition for a slide template. It defines the default appearance and positioning of drawing objects on the slide. There must be one or more such parts.
Slide MasterContains the master definition of formatting, text, and objects that appear on each slide in the presentation that is derived from the slide master. There must be one or more such parts.
Slide Synchronization DataContains properties specifying the current state of a slide that is being synchronized with a version of the slide stored on a central server.
User-Defined TagsContains a set of user-defined properties for an object in a presentation. There can be zero or more such parts.
View PropertiesContains display properties for the presentation.

等等内容,我们根据标准一点点解析并渲染就好了。

完整源码:ranui

使用文档:preview 组件

2.pdf 的预览方案

(1).iframe 和 embed

pdf比较特别,一般的浏览器默认支持预览pdf。因此,我们可以使用浏览器的能力:

html
<iframe src="viewFileUrl" />

但这样就完全依赖浏览器,对PDF的展示,交互,是否支持全看浏览器的能力,且不同的浏览器展示和交互往往不同,如果需要统一的话,最好还是尝试其他方案。

embed的解析方式也是一样,这里不举例子了

(2)pdfjs

npm: https://www.npmjs.com/package/pdfjs-dist

github 地址:https://github.com/mozilla/pdfjs-dist

mozilla出品,就是我们常见的MDN的老大。

而且目前 火狐浏览器 使用的 PDF 预览就是采用这个,我们可以用火狐浏览器打开pdf文件,查看浏览器使用的js就能发现

image.png

需要注意的是,最新版pdf.js限制了node版本,需要大于等于18

github 链接:https://github.com/mozilla/pdf.js/blob/master/package.json

image.png

如果你项目node版本小于这个情况,可能会无法使用。

如果遇到这种情况,可以用以前版本,以前的版本没有限制。

具体使用情况如下:

ts
import * as pdfjs from 'pdfjs-dist';
+import * as pdfjsWorker from 'pdfjs-dist/build/pdf.work.entry';
+
+interface Viewport {
+  width: number;
+  height: number;
+  viewBox: Array<number>;
+}
+
+interface RenderContext {
+  canvasContext: CanvasRenderingContext2D | null;
+  transform: Array<number>;
+  viewport: Viewport;
+}
+
+interface PDFPageProxy {
+  pageNumber: number;
+  getViewport: () => Viewport;
+  render: (options: RenderContext) => void;
+}
+
+interface PDFDocumentProxy {
+  numPages: number;
+  getPage: (x: number) => Promise<PDFPageProxy>;
+}
+
+class PdfPreview {
+  private pdfDoc: PDFDocumentProxy | undefined;
+  pageNumber: number;
+  total: number;
+  dom: HTMLElement;
+  pdf: string | ArrayBuffer;
+  constructor(pdf: string | ArrayBuffer, dom: HTMLElement | undefined) {
+    this.pageNumber = 1;
+    this.total = 0;
+    this.pdfDoc = undefined;
+    this.pdf = pdf;
+    this.dom = dom ? dom : document.body;
+  }
+  private getPdfPage = (number: number) => {
+    return new Promise((resolve, reject) => {
+      if (this.pdfDoc) {
+        this.pdfDoc.getPage(number).then((page: PDFPageProxy) => {
+          const viewport = page.getViewport();
+          const canvas = document.createElement('canvas');
+          this.dom.appendChild(canvas);
+          const context = canvas.getContext('2d');
+          const [_, __, width, height] = viewport.viewBox;
+          canvas.width = width;
+          canvas.height = height;
+          viewport.width = width;
+          viewport.height = height;
+          canvas.style.width = Math.floor(viewport.width) + 'px';
+          canvas.style.height = Math.floor(viewport.height) + 'px';
+          const renderContext = {
+            canvasContext: context,
+            viewport: viewport,
+            transform: [1, 0, 0, -1, 0, viewport.height],
+          };
+          page.render(renderContext);
+          resolve({ success: true, data: page });
+        });
+      } else {
+        reject({ success: false, data: null, message: 'pdfDoc is undefined' });
+      }
+    });
+  };
+  pdfPreview = () => {
+    window.pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;
+    window.pdfjsLib.getDocument(this.pdf).promise.then(async (doc: PDFDocumentProxy) => {
+      this.pdfDoc = doc;
+      this.total = doc.numPages;
+      for (let i = 1; i <= this.total; i++) {
+        await this.getPdfPage(i);
+      }
+    });
+  };
+  prevPage = () => {
+    if (this.pageNumber > 1) {
+      this.pageNumber -= 1;
+    } else {
+      this.pageNumber = 1;
+    }
+    this.getPdfPage(this.pageNumber);
+  };
+  nextPage = () => {
+    if (this.pageNumber < this.total) {
+      this.pageNumber += 1;
+    } else {
+      this.pageNumber = this.total;
+    }
+    this.getPdfPage(this.pageNumber);
+  };
+}
+
+const createReader = (file: File): Promise<string | ArrayBuffer | null> => {
+  return new Promise((resolve, reject) => {
+    const reader = new FileReader();
+    reader.readAsDataURL(file);
+    reader.onload = () => {
+      resolve(reader.result);
+    };
+    reader.onerror = (error) => {
+      reject(error);
+    };
+    reader.onabort = (abort) => {
+      reject(abort);
+    };
+  });
+};
+
+export const renderPdf = async (file: File, dom?: HTMLElement): Promise<void> => {
+  try {
+    if (typeof window !== 'undefined') {
+      const pdf = await createReader(file);
+      if (pdf) {
+        const PDF = new PdfPreview(pdf, dom);
+        PDF.pdfPreview();
+      }
+    }
+  } catch (error) {
+    console.log('renderPdf', error);
+  }
+};

3.docx 的预览方案

我们可以去查看docx的国际标准,去解析文件格式,渲染成htmlcanvas,不过比较好的是,已经有人这么做了,还开源了

npm地址:https://www.npmjs.com/package/docx-preview

使用方法如下:

ts
import { renderAsync } from 'docx-preview';
+
+interface DocxOptions {
+  bodyContainer?: HTMLElement | null;
+  styleContainer?: HTMLElement;
+  buffer: Blob;
+  docxOptions?: Partial<Record<string, string | boolean>>;
+}
+
+export const renderDocx = (options: DocxOptions): Promise<void> | undefined => {
+  if (typeof window !== 'undefined') {
+    const { bodyContainer, styleContainer, buffer, docxOptions = {} } = options;
+    const defaultOptions = {
+      className: 'docx',
+      ignoreLastRenderedPageBreak: false,
+    };
+    const configuration = Object.assign({}, defaultOptions, docxOptions);
+    if (bodyContainer) {
+      return renderAsync(buffer, bodyContainer, styleContainer, configuration);
+    } else {
+      const contain = document.createElement('div');
+      document.body.appendChild(contain);
+      return renderAsync(buffer, contain, styleContainer, configuration);
+    }
+  }
+};

4.xlsx 的预览方案

我们可以使用这个:

npm地址:https://www.npmjs.com/package/@vue-office/excel

支持vue2vue3,也有js的版本

对于xlsx的预览方案,这个是找到最好用的了。

5.前端预览方案总结

我们对以上找到的优秀的解决方案,进行改进和总结,并封装成一个web components组件:preview 组件

为什么是web components组件?

因为它跟框架无关,可以在任何框架中使用,且使用起来跟原生的div标签一样方便。

并编写使用文档:preview 组件文档, 文档支持交互体验。

源码公开,MIT协议。

目前docx,pdf,xlsx预览基本可以了,都是最好的方案。pptx预览效果不太好,因为需要自行解析。不过源码完全公开,需要的可以提issuepr或者干脆自取或修改,源码地址:https://github.com/chaxus/ran/tree/main/packages/ranui

三:服务端预览方案

1.openOffice

由于浏览器不能直接打开docx,pptx,xlsx等格式文件,但可以直接打开pdf和图片。因此,我们可以换一个思路,用服务端去转换下文件的格式,转换成浏览器能识别的格式,然后再让浏览器打开,这不就 OK 了吗,甚至不需要前端处理了。

我们可以借助openOffice的能力,先介绍一下openOffice:

Apache OpenOffice是领先的开源办公软件套件,用于文字处理,电子表格,演示文稿,图形,数据库等。它有多种语言版本,适用于所有常用计算机。它以国际开放标准格式存储您的所有数据,还可以从其他常见的办公软件包中读取和写入文件。它可以出于任何目的完全免费下载和使用。

官网如下:https://www.openoffice.org/

需要先下载opneOffice,找到bin目录,进行设置

java
configuration.setOfficeHome("这里的路径一般为 C:\\\\Program Files (x86)\\\\OpenOffice 4");

测试下转换的文件路径

java
    public static void main(String[] args) {
+        convertToPDF("/Users/Desktop/asdf.docx", "/Users/Desktop/adsf.pdf");
+    }

完整如下:

java

+package org.example;
+
+import org.artofsolving.jodconverter.OfficeDocumentConverter;
+import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
+import org.artofsolving.jodconverter.office.OfficeManager;
+
+import java.io.File;
+
+public class OfficeUtil {
+
+    private static OfficeManager officeManager;
+    private static int port[] = {8100};
+
+    /**
+     * start openOffice service.
+     */
+    public static void startService() {
+        DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();
+        try {
+            System.out.println("准备启动 office 转换服务....");
+            configuration.setOfficeHome("这里的路径一般为 C:\\\\Program Files (x86)\\\\OpenOffice 4");
+            configuration.setPortNumbers(port); // 设置转换端口,默认为 8100
+            configuration.setTaskExecutionTimeout(1000 * 60 * 30L);// 设置任务执行超时为 30 分钟
+            configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L);// 设置任务队列超时为 24 小时
+            officeManager = configuration.buildOfficeManager();
+            officeManager.start(); // 启动服务
+            System.out.println("office 转换服务启动成功!");
+        } catch (Exception e) {
+            System.out.println("office 转换服务启动失败!详细信息:" + e);
+        }
+    }
+
+    /**
+     * stop openOffice service.
+     */
+    public static void stopService() {
+        System.out.println("准备关闭 office 转换服务....");
+        if (officeManager != null) {
+            officeManager.stop();
+        }
+        System.out.println("office 转换服务关闭成功!");
+    }
+
+    public static void convertToPDF(String inputFile, String outputFile) {
+        startService();
+        System.out.println("进行文档转换转换:" + inputFile + " --> " + outputFile);
+        OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
+        converter.convert(new File(inputFile), new File(outputFile));
+        stopService();
+    }
+
+    public static void main(String[] args) {
+        convertToPDF("/Users/koolearn/Desktop/asdf.docx", "/Users/koolearn/Desktop/adsf.pdf");
+    }
+}

2.kkFileView

github地址:https://github.com/kekingcn/kkFileView

支持的文件预览格式非常丰富 image.png

接下来是 从零到一 的启动步骤,按着步骤来,任何人都能搞定

  1. 安装java:
sh
brew install java
  1. 安装maven,java的包管理工具:
sh
brew install mvn
  1. 检查是否安装成功

执行java --versionmvn -v。我这里遇到mvn找不到java home的报错。解决方式如下:

我用的是zsh,所以需要去.zshrc添加路径:

export JAVA_HOME=$(/usr/libexec/java_home)

添加完后,执行

source .zshrc
  1. 安装下libreoffice :

kkFileView明确要求的额外依赖,否则无法启动

brew install libreoffice
  1. mvn安装依赖

进入项目,在根目录执行依赖安装,同时清理缓存,跳过单测 (遇到了单测报错的问题)

mvn clean install -DskipTests
  1. 启动项目

找到主文件,主函数mian,点击vscode上面的Run即可执行,路径如下图

image.png

  1. 访问页面

启动完成后,点击终端输出的地址

image.png

  1. 最终结果

最终展示如下,可以添加链接进行预览,也可以选择本地文件进行预览

image.png

预览效果非常好

3.onlyOffice

官网地址:https://www.onlyoffice.com/zh

github地址:https://github.com/ONLYOFFICE

开发者版本和社区版免费,企业版付费:https://www.onlyoffice.com/zh/docs-enterprise-prices.aspx

预览的文件种类没有kkFileView多,但对office三件套有很好的支持,甚至支持多人编辑。

四:总结

  1. 外部服务,推荐微软的view.officeapps.live.com/op/view.aspx,但只建议预览一些互联网公开的文件,不建议使用在要求保密性和稳定性的文件。
  2. 对保密性和稳定性有要求,且不差钱的,可以试试大厂服务,阿里云解决方案。
  3. 服务端技术比较给力的,使用服务端预览方案。目前最好最全的效果是服务端预览方案。
  4. 不想花钱,没有服务器的,使用前端预览方案,客户端渲染零成本。

五:参考文档:

  1. 在 java 中如何使用 openOffice 进行格式转换
  2. MAC 搭建 OpenOffice 完整教程 - 保姆级
  3. 纯 js 实现 docx、xlsx、pdf 文件预览库,使用超简单
  4. 前端实现 word、excel、pdf、ppt、mp4、图片、文本等文件的预览
',178)]))}const j=i(D,[["render",b]]);export{O as __pageData,j as default}; diff --git a/assets/cn_src_article_functionalProgramming.md.XTLIxuFQ.js b/assets/cn_src_article_functionalProgramming.md.XTLIxuFQ.js new file mode 100644 index 0000000000..c859294d83 --- /dev/null +++ b/assets/cn_src_article_functionalProgramming.md.XTLIxuFQ.js @@ -0,0 +1,338 @@ +import{_ as i,o as a,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"函数式编程","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/functionalProgramming.md","filePath":"cn/src/article/functionalProgramming.md","lastUpdated":1726550590000}'),k={name:"cn/src/article/functionalProgramming.md"};function l(p,s,t,E,e,r){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h(`

函数式编程

  • 概述:函数式编程 (Functional Programming)FP就是编程规范之一,我们常听说的编程规范还有面向对象编程,面向过程编程。
  • 面向对象的编程思维方式:把现实世界中的事物抽象成程序世界的类和对象,通过封装,继承和多态演示事物事件的联系
  • 函数编程的思维方式:把现实世界的事物和事物之间的联系抽象到程序世界 (对运算过程进行抽象)
    • 程序的本质:根据输入,通过某种运算,获得相应的输出
    • 函数式编程中的函数不是指程序中的 (函数) 方法,而是数学中的函数,即映射关系
    • 相同的输入始终要得到相同的输出 (纯函数)
    • 函数式编程用来描述数据 (函数) 之间的映射关系
js
//非函数式编程,面向过程的编程方式
+let num1 = 1;
+let num2 = 2;
+let sum = num1 + num2;
+
+//函数式编程,对面向过程的抽象
+function sum(n1, n2) {
+  return n1 + n2;
+}
+let result = sum(1, 2);

一。JS函数基本知识

  • 函数可以储存在变量中
  • 函数可以作为参数
  • 函数可以作为返回值

JavaScript中,函数就是一个普通的对象,(可以通过new Function()),我们可以把函数存储到变量/数组中,它还可以作为另一个函数的参数和返回值,甚至我们还可以在程序运行的时候通过new Function('alert(1)')来构建一个新的函数

  • 把函数赋值给变量
js
let fn = function () {
+  console.log('First-class Function MDN');
+};

二。高阶函数

  • 高阶函数 (Higher-order function)
    • 可以把函数作为参数传递给另一个函数
    • 可以把函数作为另一个函数的返回结果
  1. 函数作为参数
js
//forEach
+function forEach(array, fn) {
+  for (let item of array) {
+    fn(item);
+  }
+}
+
+//filter
+function filter(array, fn) {
+  let result = [];
+  for (let item of array) {
+    if (fn(item)) {
+      result.push(item);
+    }
+  }
+  return result;
+}
+
+//测试
+let array = [1, 2, 3, 4, 5, 6, 7];
+forEach(array, function (item) {
+  console.log(item);
+});
+
+let r = filter(array, function (item) {
+  return item % 2 === 0;
+});
+console.log(r);
  1. 函数作为返回值
js
//高阶函数,函数作为返回值
+function makeFn() {
+  let msg = 'Highter-order Function';
+  return function () {
+    console.log(msg);
+  };
+}
+//第一种调用方式
+const fn = makeFn();
+fn();
+//第二种调用方式
+makeFn()();
+//once 只能执行一次的函数
+function once(fn) {
+  let done = false;
+  return function () {
+    if (!done) {
+      done = true;
+      return fn.apply(this, arguments);
+    }
+  };
+}
+let pay = once(function (money) {
+  console.log(\`支付\${money}\`);
+});
+pay(5);
+pay(5);
+pay(5);
+pay(5);
+pay(5);

三。闭包

概述:有权访问另一个函数作用域中的变量的函数

本质:函数执行的时候会入栈,当执行完后会移除栈,但是堆上的作用域成员因为被外部引用而不能释放。因此内部函数依然可以访问外部函数的成员。

:栈会自动分配内存,会自动释放,存放基本数据类型,占据固定大小的空间。

栈的溢出:递归调用方法,随着栈的深度增加,直到内存不够分配,产生溢出。

栈的优势:所有方法中的变量都存在栈中,随着方法执行的结束,这个方法的内存栈也随之销毁,存取速度很快,仅次于 CPU 的寄存器,可以共享。

:动态分配内存,大小不定,也不会自动释放内存,不会随着方法的结束而销毁堆内存,存放引用数据类型,实际保存的不是变量本身,而是指向该对象的指针。

堆溢出:循环创建对象,就是不断的 new 对象

四。纯函数

  • 概念:相同的输入永远会得到相同的输出,而且没有任何可观察的副作用,类似数学中的函数y=f(x)
  • 例子:slice函数就是纯函数,对一个数组,相同的输入永远得到相同的输出,splice 就是非纯函数,相同的输入可能会得到不同的结果,因为会改变原数组
  • 函数式编程不会保留计算中间的结果,所以变量不可变 (无状态)
  • 可以把一个函数的执行结果交给另一个函数去执行
  • 纯函数可以缓存,因为相同的输入必然有相同的输出
js
//memoize 函数
+function memoize(fn) {
+  let cache = {};
+  return function () {
+    let key = JSON.stringfy(arguments);
+    cache[key] = cache[key] || fn.apply(fn, arguments);
+    return cache[key];
+  };
+}
  • 可测试,让测试更方便
  • 多线程环境下操作共享的内存数据可能会出现意外的情况,而纯函数不需要共享的数据空间,只和输入有关,所以并行环境下可以任意运行纯函数
  • 副作用,副作用会让纯函数变的不纯,比如依赖外部的状态,就无法保证输出相同,带来副作用,副作用来源:配置文件,数据库,获取用户的输入等等...所有的外部交互都可能带来副作用,副作用使得方法通用性下降,不适合扩展和重用,同时给程序带来安全隐患,副作用不可能完全禁止,只能尽可能的在控制范围内。
js
//不纯的函数
+let mini = 18;
+function checkAge(age) {
+  return age > min;
+}
+//纯函数 (有硬编码,后续可以通过柯里化来解决)
+function checkAge(age) {
+  let mini = 18;
+  return age > mini;
+}

五。柯里化 (Haskell Brooks Curry)

js
//解决上述硬编码的问题
+function checkAge(min) {
+  return function (age) {
+    return age >= min;
+  };
+}
+let checkAge18 = checkAge(18);
+checkAge18(22);

es6进行简化

js
let checkAge = (min) => (age) => age >= min;
  • 当一个函数有多个参数的时候,可以先传递一部分,先调用它,并返回一个函数 (这部分参数以后保持不变)
  • 然后返回一个新的函数接受剩下的参数,返回结果
  • lodash中的柯里化函数
    • _.curry(func)
    • 功能:创建一个函数,该函数接受一个或多个 func 的参数,如果该函数所有的参数都被传递,则返回函数的结果,否则,返回该函数并等待继续传递参数
    • 参数:需要柯里化的函数
    • 返回值:柯里化后的函数
js
//lodash 中的 curry 的使用
+const _ = require('loadsh');
+function getSum(a, b, c) {
+  return a + b + c;
+}
+const curried = _.curry(getSum);
+console.log(curried(1, 2, 3)); //6
+console.log(curried(1)(2, 3)); //6
+console.log(curried(1)(2)(3)); //6

实现一个 curry 函数

js
function curry(func) {
+  return function curriedFn(...args) {
+    if (args.length < func.length) {
+      return function () {
+        return curriedFn(...args.concat(Array.form(arguments)));
+      };
+    } else {
+      return func(...args);
+    }
+  };
+}
  • 总结:柯里化可以让我们给一个函数传递较少的参数,返回一个记住来某些固定参数的新函数,这是一种对函数参数的缓存,让函数变的更灵活,让函数的粒度更小。可以把多元函数转换成一元的函数,可以组合使用函数产生强大的功能。

六。函数的组合

  • 纯函数和柯里化很容易让我们写出洋葱代码,比如h(f(g(x)))
    • 获取数组的最后一个元素并转化为大写字母,_.toUpper(._first(_.revers(array)))
    • 函数的组合可以让我们把细粒度的函数,重新组合成一个新的函数
  • lodash中的组合函数
    • lodash中的组合函数flow()flowRight(),都可以组合多个函数
    • flow()是从左到右执行
    • flowRight()是从右到左执行
    • 自己实现一个flowRight函数:
js
function composeRight(...args) {
+  return function (value) {
+    args.reverse().reduce(function (acc, fn) {
+      return fn(acc);
+    }, value);
+  };
+}
+//箭头函数
+const compose =
+  (...args) =>
+  (value) =>
+    args.reverse().reduce((acc, fn) => fn(acc), value);
+//如果是表达式赋值的话,不会变量提升
  • 函数的组合要满足结合律,即 f,g,h 三个函数,无论先组合那几个,结果都是等效的,即 flowRight(.toUpper,.first,_.revers)
  • 函数组合如何进行调试?
js
const log = (v) => {
+  console.log(v);
+  return v;
+};
  • lodash库中的 fp 模块
    • lodash的 fp 模块提供了实用的对函数式编程友好的方法
    • 提供了不可变的auto-curried iteratee-first data-last的方法
js
//lodash 方法
+const _ = require('lodash');
+_.map(['a', 'b', 'c'], _.toUpper);
+//=>['A','B','C']
+_.map(['a', 'b', 'c']);
+//=>['a','b','c']
+//loadsh/fp 模块
+const fp = require('lodasg/fp');
+fp.map(fp.toUpper, ['a', 'b', 'c']);
+fp.map(fp.toUpper)(['a', 'b', 'c']);

七.Point Free

我们可以把数据处理的过程定义成与数据无关的合成运算,不需要用到代表数据的那个参数,只要把简单的运算步骤合成到一起,在使用这种模式之前我们需要定义一些辅助的基本运算函数。

  • 不需要指明处理的数据
  • 只需要合成运算过程
  • 需要定义一些辅助的基本运算函数
js
const f = fp.flowRight(fp.join('-'), fp.map(_.toLower), fp.splite(''));

八。functor(函子)

  • 为什么要了解函子
    目前没有解决如何在函数式编程中,把副作用控制在可控的范围内,异常处理,异步操作等等。
  • Functor
    • 容器:包含值和值的变形关系 (这个变形关系就是函数)
    • 函子:是一个特殊的容器,通过一个普通对象来实现,该对象具有 map 方法,map 方法可以运行一个函数对值进行处理 (变形关系)
js
//Functor 函子
+class Container {
+  //函子内部要有一个值
+  constructor(value) {
+    //这个值是传入进来的,且不对外公布
+    this._value = value;
+  }
+  map(fn) {
+    //map 方法,接受一个处理值的函数,去处理这个值。
+    //并且要把处理的值,传给一个新的函子,最后返回这个新的函子
+    return new Container(fn(this._value));
+  }
+}
+
+//新建一个函子
+let r = new Container(5).map((x) => x + 1).map((x) => x * x);

of方法:

js
//of 方法用来返回一个函子对象
+class Container {
+  constructor(value) {
+    this._value = value;
+  }
+  static of(value) {
+    //传入值,返回一个新的函子对象
+    return new Container(value);
+  }
+  map(fn) {
+    return Container.of(fn(this._value));
+  }
+}
+let r = Container.of(5)
+  .map((x) => x + 1)
+  .map((x) => x * x);
+console.log(r); //打印出来的是一个函子,不是值,永远不会把这个值取出来,需要改变这个值的时候,使用 map 方法传入一个函数去处理,进行链式调用。
  • 总结
    • 函数式编程的运算不直接操作值,而是由函子完成
    • 函子就是一个实现了map契约的对象
    • 我们可以把函子想象成一个盒子,这个盒子里封装了一个值
    • 想要处理盒子中的值,我们需要给盒子的map方法传递一个处理值的函数(纯函数),由这个函数对值进行处理
    • 最终map方法返回一个包含新值的盒子(函子)
  • MayBe函子
    • 我们在编程过程中可能会遇到很多的错误,需要对这些错误进行相应的处理
    • MayBe 函子的作用就是可以对外部的空值情况做处理(控制副作用在允许的范围之内)
js
//MayBe 函子
+class MayBe {
+  static of(value) {
+    return new MayBe(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this._value));
+  }
+  isNothing() {
+    return this._value === null || this._value === undefined;
+  }
+}
+let r = MayBe.of(null)
+  .map((x) => x + 1)
+  .map((x) => x * x);
+console.log(r);
  • 问题:如果多次调用 map,中间出现了 null 空值的情况,最后会返回包含 null 的函子。虽然 maybe 函子可以处理空值的情况,但不知道是哪一步出现了空值
  • Either 函子
    • Either 两者中的任意一个,类似于 if...else...的处理
    • 异常会让函数变的不纯,Either 函子可以用来做异常处理
js
//Either 函子
+class Left {
+  static of(value) {
+    return new Left(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return this;
+  }
+}
+
+class Right {
+  static of(value) {
+    return new Right(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return Right.of(fn(this._value));
+  }
+}
+
+function parseJSON(str) {
+  try {
+    return Right.of(JSON.parse(str));
+  } catch (error) {
+    return Left.of({ error: error.message });
+  }
+}
+let l = parseJSON('{name:zs}'); //error
+console.log(l);
+let r = parseJSON('{"name":"zs"}');
+console.log(r);
+r.map((x) => x.toUpper());
  • IO 函子
    • IO 函子中的_value 是一个函数,这里是把函数当作值来处理
    • IO 函子可以把不纯的函数储存到_value 中,延迟执行这个不纯的操作 (惰性执行)
    • 把不纯的操作交给调用者来处理
js
const fp = require('lodash/fp');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+}
+//调用
+//因为是在 node 环境,所以直接传递 process 对象,node 的进程
+let r = IO.of(process).map((p) => p.execPath);
+console.log(r); //IO {_value :[Function]}
+console.log(r._value()); //执行 node 进程的路径
  • folktale
    • folktale 是一个标准的函数式编程库
    • 和 lodash,ramda 不同的是,他没有提供很多功能函数
    • 只提供了函数式处理的操作,例如,curry,compose 等,和一些函子 Task,Either,MayBe 等
js
//folktale  2.3.2
+//Task 处理异步任务
+const fs = require('fs');
+const { task } = require('folktale/concurrency/task');
+const { split, find } = require('loadsh/fp');
+
+function readFile(filename) {
+  return task((resolver) => {
+    fs.readFile(filename, 'utf-8', (error, data) => {
+      if (error) {
+        resolver.reject(err);
+      } else {
+        resolver.resolve(data);
+      }
+    });
+  });
+}
+//会返回一个 Task 函子
+readFile('package.json')
+  .run()
+  .listen({
+    //监听事件的状态
+    onRejected: (err) => {
+      console.log(err);
+    },
+    onResolved: (value) => {
+      console.log(value);
+    },
+  });
+//可以在 run 之前调用 map,去处理返回的结果
+readFile('package.json')
+  .map(split('\\n'))
+  .map(find((x) => x.includes('version')))
+  .run()
+  .listen({
+    //监听事件的状态
+    onRejected: (err) => {
+      console.log(err);
+    },
+    onResolved: (value) => {
+      console.log(value);
+    },
+  });
  • Pointed 函子
    • Pointed 函子是实现的静态方法 of 的函子
    • of 是为了避免使用 new 来创建对象,更深层的含义是 of 方法用来把值放到上下文 Context 中 (把值放到容器中,使用 map 来处理值)
  • Monad 函子
    • Monad 函子是为来解决 IO 函子嵌套的问题
js
const fp = require('lodash/fp');
+const fs = require('fs');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+}
+let readFile = function (filename) {
+  return new IO(function () {
+    return fs.readFileSync(filename, 'utf-8');
+  });
+};
+let print = function (x) {
+  return new IO(function (x) {
+    console.log(x);
+    return x;
+  });
+};
+let cat = fp.flowRight(print, readFile);
+let r = cat('package.json')._value()._value();
+console.log(r);
  • Monad 函子是一个可以变扁的 Pointed 函子,变扁就是解决函子嵌套的问题 IO(IO(x))
  • 一个函子如果具有 join 和 of 两个方法并遵守一些定律就是一个 Monad
js
//注意看 join 方法
+const fp = require('lodash/fp');
+const fs = require('fs');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+  join() {
+    return this._value();
+  }
+  flatMap(fn) {
+    //经常会用到 map 和 join 方法,所以就用 flatMap 将其变扁
+    return this.map(fn).join();
+  }
+}
+let print = function (x) {
+  return new IO(function () {
+    console.log(x);
+    return x;
+  });
+};
+let r = readFile('package.json') //这里可以用 map 去处理内容
+  .flatMap(print)
+  .join();

参考资料

`,66)]))}const y=i(k,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/cn_src_article_functionalProgramming.md.XTLIxuFQ.lean.js b/assets/cn_src_article_functionalProgramming.md.XTLIxuFQ.lean.js new file mode 100644 index 0000000000..c859294d83 --- /dev/null +++ b/assets/cn_src_article_functionalProgramming.md.XTLIxuFQ.lean.js @@ -0,0 +1,338 @@ +import{_ as i,o as a,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"函数式编程","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/functionalProgramming.md","filePath":"cn/src/article/functionalProgramming.md","lastUpdated":1726550590000}'),k={name:"cn/src/article/functionalProgramming.md"};function l(p,s,t,E,e,r){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h(`

函数式编程

  • 概述:函数式编程 (Functional Programming)FP就是编程规范之一,我们常听说的编程规范还有面向对象编程,面向过程编程。
  • 面向对象的编程思维方式:把现实世界中的事物抽象成程序世界的类和对象,通过封装,继承和多态演示事物事件的联系
  • 函数编程的思维方式:把现实世界的事物和事物之间的联系抽象到程序世界 (对运算过程进行抽象)
    • 程序的本质:根据输入,通过某种运算,获得相应的输出
    • 函数式编程中的函数不是指程序中的 (函数) 方法,而是数学中的函数,即映射关系
    • 相同的输入始终要得到相同的输出 (纯函数)
    • 函数式编程用来描述数据 (函数) 之间的映射关系
js
//非函数式编程,面向过程的编程方式
+let num1 = 1;
+let num2 = 2;
+let sum = num1 + num2;
+
+//函数式编程,对面向过程的抽象
+function sum(n1, n2) {
+  return n1 + n2;
+}
+let result = sum(1, 2);

一。JS函数基本知识

  • 函数可以储存在变量中
  • 函数可以作为参数
  • 函数可以作为返回值

JavaScript中,函数就是一个普通的对象,(可以通过new Function()),我们可以把函数存储到变量/数组中,它还可以作为另一个函数的参数和返回值,甚至我们还可以在程序运行的时候通过new Function('alert(1)')来构建一个新的函数

  • 把函数赋值给变量
js
let fn = function () {
+  console.log('First-class Function MDN');
+};

二。高阶函数

  • 高阶函数 (Higher-order function)
    • 可以把函数作为参数传递给另一个函数
    • 可以把函数作为另一个函数的返回结果
  1. 函数作为参数
js
//forEach
+function forEach(array, fn) {
+  for (let item of array) {
+    fn(item);
+  }
+}
+
+//filter
+function filter(array, fn) {
+  let result = [];
+  for (let item of array) {
+    if (fn(item)) {
+      result.push(item);
+    }
+  }
+  return result;
+}
+
+//测试
+let array = [1, 2, 3, 4, 5, 6, 7];
+forEach(array, function (item) {
+  console.log(item);
+});
+
+let r = filter(array, function (item) {
+  return item % 2 === 0;
+});
+console.log(r);
  1. 函数作为返回值
js
//高阶函数,函数作为返回值
+function makeFn() {
+  let msg = 'Highter-order Function';
+  return function () {
+    console.log(msg);
+  };
+}
+//第一种调用方式
+const fn = makeFn();
+fn();
+//第二种调用方式
+makeFn()();
+//once 只能执行一次的函数
+function once(fn) {
+  let done = false;
+  return function () {
+    if (!done) {
+      done = true;
+      return fn.apply(this, arguments);
+    }
+  };
+}
+let pay = once(function (money) {
+  console.log(\`支付\${money}\`);
+});
+pay(5);
+pay(5);
+pay(5);
+pay(5);
+pay(5);

三。闭包

概述:有权访问另一个函数作用域中的变量的函数

本质:函数执行的时候会入栈,当执行完后会移除栈,但是堆上的作用域成员因为被外部引用而不能释放。因此内部函数依然可以访问外部函数的成员。

:栈会自动分配内存,会自动释放,存放基本数据类型,占据固定大小的空间。

栈的溢出:递归调用方法,随着栈的深度增加,直到内存不够分配,产生溢出。

栈的优势:所有方法中的变量都存在栈中,随着方法执行的结束,这个方法的内存栈也随之销毁,存取速度很快,仅次于 CPU 的寄存器,可以共享。

:动态分配内存,大小不定,也不会自动释放内存,不会随着方法的结束而销毁堆内存,存放引用数据类型,实际保存的不是变量本身,而是指向该对象的指针。

堆溢出:循环创建对象,就是不断的 new 对象

四。纯函数

  • 概念:相同的输入永远会得到相同的输出,而且没有任何可观察的副作用,类似数学中的函数y=f(x)
  • 例子:slice函数就是纯函数,对一个数组,相同的输入永远得到相同的输出,splice 就是非纯函数,相同的输入可能会得到不同的结果,因为会改变原数组
  • 函数式编程不会保留计算中间的结果,所以变量不可变 (无状态)
  • 可以把一个函数的执行结果交给另一个函数去执行
  • 纯函数可以缓存,因为相同的输入必然有相同的输出
js
//memoize 函数
+function memoize(fn) {
+  let cache = {};
+  return function () {
+    let key = JSON.stringfy(arguments);
+    cache[key] = cache[key] || fn.apply(fn, arguments);
+    return cache[key];
+  };
+}
  • 可测试,让测试更方便
  • 多线程环境下操作共享的内存数据可能会出现意外的情况,而纯函数不需要共享的数据空间,只和输入有关,所以并行环境下可以任意运行纯函数
  • 副作用,副作用会让纯函数变的不纯,比如依赖外部的状态,就无法保证输出相同,带来副作用,副作用来源:配置文件,数据库,获取用户的输入等等...所有的外部交互都可能带来副作用,副作用使得方法通用性下降,不适合扩展和重用,同时给程序带来安全隐患,副作用不可能完全禁止,只能尽可能的在控制范围内。
js
//不纯的函数
+let mini = 18;
+function checkAge(age) {
+  return age > min;
+}
+//纯函数 (有硬编码,后续可以通过柯里化来解决)
+function checkAge(age) {
+  let mini = 18;
+  return age > mini;
+}

五。柯里化 (Haskell Brooks Curry)

js
//解决上述硬编码的问题
+function checkAge(min) {
+  return function (age) {
+    return age >= min;
+  };
+}
+let checkAge18 = checkAge(18);
+checkAge18(22);

es6进行简化

js
let checkAge = (min) => (age) => age >= min;
  • 当一个函数有多个参数的时候,可以先传递一部分,先调用它,并返回一个函数 (这部分参数以后保持不变)
  • 然后返回一个新的函数接受剩下的参数,返回结果
  • lodash中的柯里化函数
    • _.curry(func)
    • 功能:创建一个函数,该函数接受一个或多个 func 的参数,如果该函数所有的参数都被传递,则返回函数的结果,否则,返回该函数并等待继续传递参数
    • 参数:需要柯里化的函数
    • 返回值:柯里化后的函数
js
//lodash 中的 curry 的使用
+const _ = require('loadsh');
+function getSum(a, b, c) {
+  return a + b + c;
+}
+const curried = _.curry(getSum);
+console.log(curried(1, 2, 3)); //6
+console.log(curried(1)(2, 3)); //6
+console.log(curried(1)(2)(3)); //6

实现一个 curry 函数

js
function curry(func) {
+  return function curriedFn(...args) {
+    if (args.length < func.length) {
+      return function () {
+        return curriedFn(...args.concat(Array.form(arguments)));
+      };
+    } else {
+      return func(...args);
+    }
+  };
+}
  • 总结:柯里化可以让我们给一个函数传递较少的参数,返回一个记住来某些固定参数的新函数,这是一种对函数参数的缓存,让函数变的更灵活,让函数的粒度更小。可以把多元函数转换成一元的函数,可以组合使用函数产生强大的功能。

六。函数的组合

  • 纯函数和柯里化很容易让我们写出洋葱代码,比如h(f(g(x)))
    • 获取数组的最后一个元素并转化为大写字母,_.toUpper(._first(_.revers(array)))
    • 函数的组合可以让我们把细粒度的函数,重新组合成一个新的函数
  • lodash中的组合函数
    • lodash中的组合函数flow()flowRight(),都可以组合多个函数
    • flow()是从左到右执行
    • flowRight()是从右到左执行
    • 自己实现一个flowRight函数:
js
function composeRight(...args) {
+  return function (value) {
+    args.reverse().reduce(function (acc, fn) {
+      return fn(acc);
+    }, value);
+  };
+}
+//箭头函数
+const compose =
+  (...args) =>
+  (value) =>
+    args.reverse().reduce((acc, fn) => fn(acc), value);
+//如果是表达式赋值的话,不会变量提升
  • 函数的组合要满足结合律,即 f,g,h 三个函数,无论先组合那几个,结果都是等效的,即 flowRight(.toUpper,.first,_.revers)
  • 函数组合如何进行调试?
js
const log = (v) => {
+  console.log(v);
+  return v;
+};
  • lodash库中的 fp 模块
    • lodash的 fp 模块提供了实用的对函数式编程友好的方法
    • 提供了不可变的auto-curried iteratee-first data-last的方法
js
//lodash 方法
+const _ = require('lodash');
+_.map(['a', 'b', 'c'], _.toUpper);
+//=>['A','B','C']
+_.map(['a', 'b', 'c']);
+//=>['a','b','c']
+//loadsh/fp 模块
+const fp = require('lodasg/fp');
+fp.map(fp.toUpper, ['a', 'b', 'c']);
+fp.map(fp.toUpper)(['a', 'b', 'c']);

七.Point Free

我们可以把数据处理的过程定义成与数据无关的合成运算,不需要用到代表数据的那个参数,只要把简单的运算步骤合成到一起,在使用这种模式之前我们需要定义一些辅助的基本运算函数。

  • 不需要指明处理的数据
  • 只需要合成运算过程
  • 需要定义一些辅助的基本运算函数
js
const f = fp.flowRight(fp.join('-'), fp.map(_.toLower), fp.splite(''));

八。functor(函子)

  • 为什么要了解函子
    目前没有解决如何在函数式编程中,把副作用控制在可控的范围内,异常处理,异步操作等等。
  • Functor
    • 容器:包含值和值的变形关系 (这个变形关系就是函数)
    • 函子:是一个特殊的容器,通过一个普通对象来实现,该对象具有 map 方法,map 方法可以运行一个函数对值进行处理 (变形关系)
js
//Functor 函子
+class Container {
+  //函子内部要有一个值
+  constructor(value) {
+    //这个值是传入进来的,且不对外公布
+    this._value = value;
+  }
+  map(fn) {
+    //map 方法,接受一个处理值的函数,去处理这个值。
+    //并且要把处理的值,传给一个新的函子,最后返回这个新的函子
+    return new Container(fn(this._value));
+  }
+}
+
+//新建一个函子
+let r = new Container(5).map((x) => x + 1).map((x) => x * x);

of方法:

js
//of 方法用来返回一个函子对象
+class Container {
+  constructor(value) {
+    this._value = value;
+  }
+  static of(value) {
+    //传入值,返回一个新的函子对象
+    return new Container(value);
+  }
+  map(fn) {
+    return Container.of(fn(this._value));
+  }
+}
+let r = Container.of(5)
+  .map((x) => x + 1)
+  .map((x) => x * x);
+console.log(r); //打印出来的是一个函子,不是值,永远不会把这个值取出来,需要改变这个值的时候,使用 map 方法传入一个函数去处理,进行链式调用。
  • 总结
    • 函数式编程的运算不直接操作值,而是由函子完成
    • 函子就是一个实现了map契约的对象
    • 我们可以把函子想象成一个盒子,这个盒子里封装了一个值
    • 想要处理盒子中的值,我们需要给盒子的map方法传递一个处理值的函数(纯函数),由这个函数对值进行处理
    • 最终map方法返回一个包含新值的盒子(函子)
  • MayBe函子
    • 我们在编程过程中可能会遇到很多的错误,需要对这些错误进行相应的处理
    • MayBe 函子的作用就是可以对外部的空值情况做处理(控制副作用在允许的范围之内)
js
//MayBe 函子
+class MayBe {
+  static of(value) {
+    return new MayBe(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this._value));
+  }
+  isNothing() {
+    return this._value === null || this._value === undefined;
+  }
+}
+let r = MayBe.of(null)
+  .map((x) => x + 1)
+  .map((x) => x * x);
+console.log(r);
  • 问题:如果多次调用 map,中间出现了 null 空值的情况,最后会返回包含 null 的函子。虽然 maybe 函子可以处理空值的情况,但不知道是哪一步出现了空值
  • Either 函子
    • Either 两者中的任意一个,类似于 if...else...的处理
    • 异常会让函数变的不纯,Either 函子可以用来做异常处理
js
//Either 函子
+class Left {
+  static of(value) {
+    return new Left(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return this;
+  }
+}
+
+class Right {
+  static of(value) {
+    return new Right(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return Right.of(fn(this._value));
+  }
+}
+
+function parseJSON(str) {
+  try {
+    return Right.of(JSON.parse(str));
+  } catch (error) {
+    return Left.of({ error: error.message });
+  }
+}
+let l = parseJSON('{name:zs}'); //error
+console.log(l);
+let r = parseJSON('{"name":"zs"}');
+console.log(r);
+r.map((x) => x.toUpper());
  • IO 函子
    • IO 函子中的_value 是一个函数,这里是把函数当作值来处理
    • IO 函子可以把不纯的函数储存到_value 中,延迟执行这个不纯的操作 (惰性执行)
    • 把不纯的操作交给调用者来处理
js
const fp = require('lodash/fp');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+}
+//调用
+//因为是在 node 环境,所以直接传递 process 对象,node 的进程
+let r = IO.of(process).map((p) => p.execPath);
+console.log(r); //IO {_value :[Function]}
+console.log(r._value()); //执行 node 进程的路径
  • folktale
    • folktale 是一个标准的函数式编程库
    • 和 lodash,ramda 不同的是,他没有提供很多功能函数
    • 只提供了函数式处理的操作,例如,curry,compose 等,和一些函子 Task,Either,MayBe 等
js
//folktale  2.3.2
+//Task 处理异步任务
+const fs = require('fs');
+const { task } = require('folktale/concurrency/task');
+const { split, find } = require('loadsh/fp');
+
+function readFile(filename) {
+  return task((resolver) => {
+    fs.readFile(filename, 'utf-8', (error, data) => {
+      if (error) {
+        resolver.reject(err);
+      } else {
+        resolver.resolve(data);
+      }
+    });
+  });
+}
+//会返回一个 Task 函子
+readFile('package.json')
+  .run()
+  .listen({
+    //监听事件的状态
+    onRejected: (err) => {
+      console.log(err);
+    },
+    onResolved: (value) => {
+      console.log(value);
+    },
+  });
+//可以在 run 之前调用 map,去处理返回的结果
+readFile('package.json')
+  .map(split('\\n'))
+  .map(find((x) => x.includes('version')))
+  .run()
+  .listen({
+    //监听事件的状态
+    onRejected: (err) => {
+      console.log(err);
+    },
+    onResolved: (value) => {
+      console.log(value);
+    },
+  });
  • Pointed 函子
    • Pointed 函子是实现的静态方法 of 的函子
    • of 是为了避免使用 new 来创建对象,更深层的含义是 of 方法用来把值放到上下文 Context 中 (把值放到容器中,使用 map 来处理值)
  • Monad 函子
    • Monad 函子是为来解决 IO 函子嵌套的问题
js
const fp = require('lodash/fp');
+const fs = require('fs');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+}
+let readFile = function (filename) {
+  return new IO(function () {
+    return fs.readFileSync(filename, 'utf-8');
+  });
+};
+let print = function (x) {
+  return new IO(function (x) {
+    console.log(x);
+    return x;
+  });
+};
+let cat = fp.flowRight(print, readFile);
+let r = cat('package.json')._value()._value();
+console.log(r);
  • Monad 函子是一个可以变扁的 Pointed 函子,变扁就是解决函子嵌套的问题 IO(IO(x))
  • 一个函子如果具有 join 和 of 两个方法并遵守一些定律就是一个 Monad
js
//注意看 join 方法
+const fp = require('lodash/fp');
+const fs = require('fs');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+  join() {
+    return this._value();
+  }
+  flatMap(fn) {
+    //经常会用到 map 和 join 方法,所以就用 flatMap 将其变扁
+    return this.map(fn).join();
+  }
+}
+let print = function (x) {
+  return new IO(function () {
+    console.log(x);
+    return x;
+  });
+};
+let r = readFile('package.json') //这里可以用 map 去处理内容
+  .flatMap(print)
+  .join();

参考资料

`,66)]))}const y=i(k,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/cn_src_article_imagemin.md.Eq8Sl5vS.js b/assets/cn_src_article_imagemin.md.Eq8Sl5vS.js new file mode 100644 index 0000000000..3bbca004f9 --- /dev/null +++ b/assets/cn_src_article_imagemin.md.Eq8Sl5vS.js @@ -0,0 +1 @@ +import{_ as t,o as i,c as r,j as a,a as n}from"./chunks/framework.C-ai2y4t.js";const f=JSON.parse('{"title":"imagemin 图片压缩源码分析","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/imagemin.md","filePath":"cn/src/article/imagemin.md","lastUpdated":1726550590000}'),m={name:"cn/src/article/imagemin.md"};function s(c,e,o,d,l,p){return i(),r("div",{"data-pagefind-body":!0},e[0]||(e[0]=[a("h1",{id:"imagemin-图片压缩源码分析",tabindex:"-1"},[n("imagemin 图片压缩源码分析 "),a("a",{class:"header-anchor",href:"#imagemin-图片压缩源码分析","aria-label":'Permalink to "imagemin 图片压缩源码分析"'},"​")],-1)]))}const _=t(m,[["render",s]]);export{f as __pageData,_ as default}; diff --git a/assets/cn_src_article_imagemin.md.Eq8Sl5vS.lean.js b/assets/cn_src_article_imagemin.md.Eq8Sl5vS.lean.js new file mode 100644 index 0000000000..3bbca004f9 --- /dev/null +++ b/assets/cn_src_article_imagemin.md.Eq8Sl5vS.lean.js @@ -0,0 +1 @@ +import{_ as t,o as i,c as r,j as a,a as n}from"./chunks/framework.C-ai2y4t.js";const f=JSON.parse('{"title":"imagemin 图片压缩源码分析","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/imagemin.md","filePath":"cn/src/article/imagemin.md","lastUpdated":1726550590000}'),m={name:"cn/src/article/imagemin.md"};function s(c,e,o,d,l,p){return i(),r("div",{"data-pagefind-body":!0},e[0]||(e[0]=[a("h1",{id:"imagemin-图片压缩源码分析",tabindex:"-1"},[n("imagemin 图片压缩源码分析 "),a("a",{class:"header-anchor",href:"#imagemin-图片压缩源码分析","aria-label":'Permalink to "imagemin 图片压缩源码分析"'},"​")],-1)]))}const _=t(m,[["render",s]]);export{f as __pageData,_ as default}; diff --git a/assets/cn_src_article_javascript_domLoad.md.CX-aoztf.js b/assets/cn_src_article_javascript_domLoad.md.CX-aoztf.js new file mode 100644 index 0000000000..c0a012bb7a --- /dev/null +++ b/assets/cn_src_article_javascript_domLoad.md.CX-aoztf.js @@ -0,0 +1 @@ +import{_ as e,o as t,c as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"页面加载完成后事件","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/javascript/domLoad.md","filePath":"cn/src/article/javascript/domLoad.md","lastUpdated":1726550590000}'),n={name:"cn/src/article/javascript/domLoad.md"};function o(d,a,l,r,c,h){return t(),s("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

页面加载完成后事件

window.onload

DOMContentLoaded

js
document.addEventListener('DOMContentLoaded', fun);

<body onload="fun()">

readyState

js
document.readyState;\n\ndocument.onreadystatechange;

一个文档的 readyState 可以是以下之一:

  • loading / 加载。document 仍在加载。
  • interactive / 互动。文档已经完成加载,文档已被解析,但是诸如图像,样式表和框架之类的子资源仍在加载。
  • complete / 完成。T 文档和所有子资源已完成加载。状态表示 load 事件即将被触发。
',9)]))}const k=e(n,[["render",o]]);export{u as __pageData,k as default}; diff --git a/assets/cn_src_article_javascript_domLoad.md.CX-aoztf.lean.js b/assets/cn_src_article_javascript_domLoad.md.CX-aoztf.lean.js new file mode 100644 index 0000000000..c0a012bb7a --- /dev/null +++ b/assets/cn_src_article_javascript_domLoad.md.CX-aoztf.lean.js @@ -0,0 +1 @@ +import{_ as e,o as t,c as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"页面加载完成后事件","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/javascript/domLoad.md","filePath":"cn/src/article/javascript/domLoad.md","lastUpdated":1726550590000}'),n={name:"cn/src/article/javascript/domLoad.md"};function o(d,a,l,r,c,h){return t(),s("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

页面加载完成后事件

window.onload

DOMContentLoaded

js
document.addEventListener('DOMContentLoaded', fun);

<body onload="fun()">

readyState

js
document.readyState;\n\ndocument.onreadystatechange;

一个文档的 readyState 可以是以下之一:

  • loading / 加载。document 仍在加载。
  • interactive / 互动。文档已经完成加载,文档已被解析,但是诸如图像,样式表和框架之类的子资源仍在加载。
  • complete / 完成。T 文档和所有子资源已完成加载。状态表示 load 事件即将被触发。
',9)]))}const k=e(n,[["render",o]]);export{u as __pageData,k as default}; diff --git a/assets/cn_src_article_sort_bubble_index.md.B1Kqdm5g.js b/assets/cn_src_article_sort_bubble_index.md.B1Kqdm5g.js new file mode 100644 index 0000000000..7e5f99f9eb --- /dev/null +++ b/assets/cn_src_article_sort_bubble_index.md.B1Kqdm5g.js @@ -0,0 +1,13 @@ +import{_ as i}from"./chunks/bubble.Dg5jgvyl.js";import{_ as a,o as l,c as t,a3 as n}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"冒泡排序(Bubble Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/bubble/index.md","filePath":"cn/src/article/sort/bubble/index.md","lastUpdated":1726550590000}'),h={name:"cn/src/article/sort/bubble/index.md"};function k(p,s,e,r,E,d){return l(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n('

冒泡排序(Bubble Sort)

冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

算法描述

  • 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
  • 针对所有的元素重复以上的步骤,除了最后一个;
  • 重复步骤 1~3,直到排序完成。

动图演示

冒泡排序

代码演示

ts
const bubble = (list: number[]) => {
+  const size = list.length;
+  for (let i = 0; i < size; i++) {
+    for (let j = 0; j < size; j++) {
+      if (list[i] < list[j]) {
+        list[i] = list[i] ^ list[j];
+        list[j] = list[i] ^ list[j];
+        list[i] = list[i] ^ list[j];
+      }
+    }
+  }
+  return list;
+};
`,8)]))}const c=a(h,[["render",k]]);export{o as __pageData,c as default}; diff --git a/assets/cn_src_article_sort_bubble_index.md.B1Kqdm5g.lean.js b/assets/cn_src_article_sort_bubble_index.md.B1Kqdm5g.lean.js new file mode 100644 index 0000000000..7e5f99f9eb --- /dev/null +++ b/assets/cn_src_article_sort_bubble_index.md.B1Kqdm5g.lean.js @@ -0,0 +1,13 @@ +import{_ as i}from"./chunks/bubble.Dg5jgvyl.js";import{_ as a,o as l,c as t,a3 as n}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"冒泡排序(Bubble Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/bubble/index.md","filePath":"cn/src/article/sort/bubble/index.md","lastUpdated":1726550590000}'),h={name:"cn/src/article/sort/bubble/index.md"};function k(p,s,e,r,E,d){return l(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n('

冒泡排序(Bubble Sort)

冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

算法描述

  • 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
  • 针对所有的元素重复以上的步骤,除了最后一个;
  • 重复步骤 1~3,直到排序完成。

动图演示

冒泡排序

代码演示

ts
const bubble = (list: number[]) => {
+  const size = list.length;
+  for (let i = 0; i < size; i++) {
+    for (let j = 0; j < size; j++) {
+      if (list[i] < list[j]) {
+        list[i] = list[i] ^ list[j];
+        list[j] = list[i] ^ list[j];
+        list[i] = list[i] ^ list[j];
+      }
+    }
+  }
+  return list;
+};
`,8)]))}const c=a(h,[["render",k]]);export{o as __pageData,c as default}; diff --git a/assets/cn_src_article_sort_bucket_index.md.CkcMkruf.js b/assets/cn_src_article_sort_bucket_index.md.CkcMkruf.js new file mode 100644 index 0000000000..029c918b7c --- /dev/null +++ b/assets/cn_src_article_sort_bucket_index.md.CkcMkruf.js @@ -0,0 +1,57 @@ +import{_ as i,o as a,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"桶排序 (Bucket Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/bucket/index.md","filePath":"cn/src/article/sort/bucket/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/article/sort/bucket/index.md"};function l(t,s,p,E,e,r){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k(`

桶排序 (Bucket Sort)

高效与否的关键在于这个分桶函数。将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。

算法描述

  • 设置一个定量的数组当作空桶;
  • 遍历输入数据,并且把数据一个一个放到对应的桶里去;
  • 对每个不是空的桶进行排序;
  • 从不是空的桶里把排好序的数据拼接起来。

代码演示

ts
const count = (list: Array<number>, max: number = 100): Array<number> => {
+  const countList = new Array(max + 1);
+  for (let i = 0; i < list.length; i++) {
+    if (!countList[list[i]]) {
+      countList[list[i]] = 0;
+    }
+    countList[list[i]]++;
+  }
+  let startIndex = 0;
+  for (let i = 0; i < countList.length; i++) {
+    while (countList[i] > 0) {
+      list[startIndex++] = i;
+      countList[i]--;
+    }
+  }
+  return list;
+};
+const getMax = (list: Array<number>) => {
+  let max = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+const getMin = (list: Array<number>) => {
+  let min = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (min > list[i]) {
+      min = list[i];
+    }
+  }
+  return min;
+};
+
+/**
+ * @description: 桶排序
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const bucket = (list: Array<number>, bucketSize: number = 5, max?: number, min?: number): Array<number> => {
+  if (list.length === 0) return list;
+  if (!max) max = getMax(list);
+  if (!min) min = getMin(list);
+  const bucketCount = Math.floor((max - min) / bucketSize) + 1;
+  const buckets = new Array(bucketCount + 1).fill(0).map(() => new Array(0));
+
+  for (let i = 0; i < list.length; i++) {
+    buckets[Math.floor((list[i] - min) / bucketSize)].push(list[i]);
+  }
+  list = [];
+  for (let i = 0; i < bucketCount; i++) {
+    list = list.concat(count(buckets[i]));
+  }
+  return list;
+};

算法分析

桶排序最好情况下使用线性时间 O(n),桶排序的时间复杂度,取决与对各个桶之间数据进行排序的时间复杂度,因为其它部分的时间复杂度都为 O(n)。很显然,桶划分的越小,各个桶之间的数据越少,排序所用的时间也会越少。但相应的空间消耗就会增大。

`,8)]))}const y=i(n,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/cn_src_article_sort_bucket_index.md.CkcMkruf.lean.js b/assets/cn_src_article_sort_bucket_index.md.CkcMkruf.lean.js new file mode 100644 index 0000000000..029c918b7c --- /dev/null +++ b/assets/cn_src_article_sort_bucket_index.md.CkcMkruf.lean.js @@ -0,0 +1,57 @@ +import{_ as i,o as a,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"桶排序 (Bucket Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/bucket/index.md","filePath":"cn/src/article/sort/bucket/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/article/sort/bucket/index.md"};function l(t,s,p,E,e,r){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k(`

桶排序 (Bucket Sort)

高效与否的关键在于这个分桶函数。将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。

算法描述

  • 设置一个定量的数组当作空桶;
  • 遍历输入数据,并且把数据一个一个放到对应的桶里去;
  • 对每个不是空的桶进行排序;
  • 从不是空的桶里把排好序的数据拼接起来。

代码演示

ts
const count = (list: Array<number>, max: number = 100): Array<number> => {
+  const countList = new Array(max + 1);
+  for (let i = 0; i < list.length; i++) {
+    if (!countList[list[i]]) {
+      countList[list[i]] = 0;
+    }
+    countList[list[i]]++;
+  }
+  let startIndex = 0;
+  for (let i = 0; i < countList.length; i++) {
+    while (countList[i] > 0) {
+      list[startIndex++] = i;
+      countList[i]--;
+    }
+  }
+  return list;
+};
+const getMax = (list: Array<number>) => {
+  let max = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+const getMin = (list: Array<number>) => {
+  let min = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (min > list[i]) {
+      min = list[i];
+    }
+  }
+  return min;
+};
+
+/**
+ * @description: 桶排序
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const bucket = (list: Array<number>, bucketSize: number = 5, max?: number, min?: number): Array<number> => {
+  if (list.length === 0) return list;
+  if (!max) max = getMax(list);
+  if (!min) min = getMin(list);
+  const bucketCount = Math.floor((max - min) / bucketSize) + 1;
+  const buckets = new Array(bucketCount + 1).fill(0).map(() => new Array(0));
+
+  for (let i = 0; i < list.length; i++) {
+    buckets[Math.floor((list[i] - min) / bucketSize)].push(list[i]);
+  }
+  list = [];
+  for (let i = 0; i < bucketCount; i++) {
+    list = list.concat(count(buckets[i]));
+  }
+  return list;
+};

算法分析

桶排序最好情况下使用线性时间 O(n),桶排序的时间复杂度,取决与对各个桶之间数据进行排序的时间复杂度,因为其它部分的时间复杂度都为 O(n)。很显然,桶划分的越小,各个桶之间的数据越少,排序所用的时间也会越少。但相应的空间消耗就会增大。

`,8)]))}const y=i(n,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/cn_src_article_sort_count_index.md.DO0Khq-9.js b/assets/cn_src_article_sort_count_index.md.DO0Khq-9.js new file mode 100644 index 0000000000..15b64f70f0 --- /dev/null +++ b/assets/cn_src_article_sort_count_index.md.DO0Khq-9.js @@ -0,0 +1,34 @@ +import{_ as i}from"./chunks/count.CcfK-WL7.js";import{_ as a,o as n,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"计数排序( Count Sort )","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/count/index.md","filePath":"cn/src/article/sort/count/index.md","lastUpdated":1726550590000}'),t={name:"cn/src/article/sort/count/index.md"};function l(p,s,e,E,r,d){return n(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k('

计数排序( Count Sort )

计数排序(counting sort)就是一种牺牲内存空间来换取低时间复杂度的排序算法,同时它也是一种不基于比较的算法。这里的不基于比较指的是数组元素之间不存在比较大小的排序算法,我们知道,用分治法来解决排序问题最快也只能使算法的时间复杂度接近 Θ(nlogn),即基于比较的时间复杂度存在下界 Ω(nlog⁡n),而不基于比较的排序算法可以突破这一下界。

算法描述

  • 找出待排序的数组中最大和最小的元素;
  • 统计数组中每个值为 i 的元素出现的次数,存入数组 C 的第 i 项;
  • 对所有的计数累加(从 C 中的第一个元素开始,每一项和前一项相加);
  • 反向填充目标数组:将每个元素 i 放在新数组的第 C(i)项,每放一个元素就将 C(i)减去 1。

动图演示

计数排序

代码演示

ts
const getMax = (list: number[]) => {
+  let max = list[0];
+  for (let i = 1; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+/**
+ * @description: 计数排序
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const count = (list: number[]): number[] => {
+  if (list.length <= 1) return list;
+  const max = getMax(list);
+  const countList = new Array(max + 1).fill(0);
+  list.forEach((item) => {
+    if (!countList[item]) {
+      countList[item] = 1;
+    } else {
+      countList[item]++;
+    }
+  });
+  const result = [];
+  for (let i = 0; i < countList.length; i++) {
+    while (countList[i]) {
+      result.push(i);
+      countList[i]--;
+    }
+  }
+  return result;
+};

算法分析

计数排序是一个稳定的排序算法。当输入的元素是 n 个 0 到 k 之间的整数时,时间复杂度是 O(n+k),空间复杂度也是 O(n+k),其排序速度快于任何比较排序算法。当 k 不是很大并且序列比较集中时,计数排序是一个很有效的排序算法。

`,10)]))}const c=a(t,[["render",l]]);export{F as __pageData,c as default}; diff --git a/assets/cn_src_article_sort_count_index.md.DO0Khq-9.lean.js b/assets/cn_src_article_sort_count_index.md.DO0Khq-9.lean.js new file mode 100644 index 0000000000..15b64f70f0 --- /dev/null +++ b/assets/cn_src_article_sort_count_index.md.DO0Khq-9.lean.js @@ -0,0 +1,34 @@ +import{_ as i}from"./chunks/count.CcfK-WL7.js";import{_ as a,o as n,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"计数排序( Count Sort )","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/count/index.md","filePath":"cn/src/article/sort/count/index.md","lastUpdated":1726550590000}'),t={name:"cn/src/article/sort/count/index.md"};function l(p,s,e,E,r,d){return n(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k('

计数排序( Count Sort )

计数排序(counting sort)就是一种牺牲内存空间来换取低时间复杂度的排序算法,同时它也是一种不基于比较的算法。这里的不基于比较指的是数组元素之间不存在比较大小的排序算法,我们知道,用分治法来解决排序问题最快也只能使算法的时间复杂度接近 Θ(nlogn),即基于比较的时间复杂度存在下界 Ω(nlog⁡n),而不基于比较的排序算法可以突破这一下界。

算法描述

  • 找出待排序的数组中最大和最小的元素;
  • 统计数组中每个值为 i 的元素出现的次数,存入数组 C 的第 i 项;
  • 对所有的计数累加(从 C 中的第一个元素开始,每一项和前一项相加);
  • 反向填充目标数组:将每个元素 i 放在新数组的第 C(i)项,每放一个元素就将 C(i)减去 1。

动图演示

计数排序

代码演示

ts
const getMax = (list: number[]) => {
+  let max = list[0];
+  for (let i = 1; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+/**
+ * @description: 计数排序
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const count = (list: number[]): number[] => {
+  if (list.length <= 1) return list;
+  const max = getMax(list);
+  const countList = new Array(max + 1).fill(0);
+  list.forEach((item) => {
+    if (!countList[item]) {
+      countList[item] = 1;
+    } else {
+      countList[item]++;
+    }
+  });
+  const result = [];
+  for (let i = 0; i < countList.length; i++) {
+    while (countList[i]) {
+      result.push(i);
+      countList[i]--;
+    }
+  }
+  return result;
+};

算法分析

计数排序是一个稳定的排序算法。当输入的元素是 n 个 0 到 k 之间的整数时,时间复杂度是 O(n+k),空间复杂度也是 O(n+k),其排序速度快于任何比较排序算法。当 k 不是很大并且序列比较集中时,计数排序是一个很有效的排序算法。

`,10)]))}const c=a(t,[["render",l]]);export{F as __pageData,c as default}; diff --git a/assets/cn_src_article_sort_heap_index.md.DUTc1Z1Q.js b/assets/cn_src_article_sort_heap_index.md.DUTc1Z1Q.js new file mode 100644 index 0000000000..bd01ba333f --- /dev/null +++ b/assets/cn_src_article_sort_heap_index.md.DUTc1Z1Q.js @@ -0,0 +1,50 @@ +import{_ as i}from"./chunks/heap.xduQWyUN.js";import{_ as a,o as h,c as n,a3 as k}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"堆排序(Heap Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/heap/index.md","filePath":"cn/src/article/sort/heap/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/article/sort/heap/index.md"};function t(p,s,e,E,r,d){return h(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k('

堆排序(Heap Sort)

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

算法描述

  • 将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;
  • 将堆顶元素 R[1]与最后一个元素 R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足 R[1,2…n-1]<=R[n];
  • 由于交换后新的堆顶 R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将 R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为 n-1,则整个排序过程完成。
  • 升序用大根堆,降序用小根堆

动图演示

堆排序

代码演示

ts
class Heap {
+  value: Array<number>;
+  size: number;
+  constructor(arr: Array<number> = []) {
+    this.value = [...arr];
+    this.size = arr.length;
+    this.buildMaxHeap();
+  }
+  swap = (i: number, j: number) => {
+    if (this.value[i] === this.value[j]) return;
+    this.value[i] = this.value[i] ^ this.value[j];
+    this.value[j] = this.value[i] ^ this.value[j];
+    this.value[i] = this.value[i] ^ this.value[j];
+  };
+  heapHandler = (i: number) => {
+    const left = 2 * i + 1;
+    const right = 2 * i + 2;
+    let largest = i;
+    if (left < this.size && this.value[left] > this.value[largest]) {
+      largest = left;
+    }
+    if (right < this.size && this.value[right] > this.value[largest]) {
+      largest = right;
+    }
+    if (largest !== i) {
+      this.swap(i, largest);
+      this.heapHandler(largest);
+    }
+  };
+  buildMaxHeap = () => {
+    for (let i = this.size >> 1; i >= 0; i--) {
+      this.heapHandler(i);
+    }
+    for (let i = this.size - 1; i >= 0; i--) {
+      this.swap(0, i);
+      this.size--;
+      this.heapHandler(0);
+    }
+  };
+}
+
+/**
+ * @description: 堆排序
+ * @param {Array} list
+ * @return {Array}
+ */
+const heap = (list: Array<number>): Array<number> => {
+  const { value } = new Heap(list);
+  return value;
+};
`,8)]))}const C=a(l,[["render",t]]);export{F as __pageData,C as default}; diff --git a/assets/cn_src_article_sort_heap_index.md.DUTc1Z1Q.lean.js b/assets/cn_src_article_sort_heap_index.md.DUTc1Z1Q.lean.js new file mode 100644 index 0000000000..bd01ba333f --- /dev/null +++ b/assets/cn_src_article_sort_heap_index.md.DUTc1Z1Q.lean.js @@ -0,0 +1,50 @@ +import{_ as i}from"./chunks/heap.xduQWyUN.js";import{_ as a,o as h,c as n,a3 as k}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"堆排序(Heap Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/heap/index.md","filePath":"cn/src/article/sort/heap/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/article/sort/heap/index.md"};function t(p,s,e,E,r,d){return h(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k('

堆排序(Heap Sort)

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

算法描述

  • 将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;
  • 将堆顶元素 R[1]与最后一个元素 R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足 R[1,2…n-1]<=R[n];
  • 由于交换后新的堆顶 R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将 R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为 n-1,则整个排序过程完成。
  • 升序用大根堆,降序用小根堆

动图演示

堆排序

代码演示

ts
class Heap {
+  value: Array<number>;
+  size: number;
+  constructor(arr: Array<number> = []) {
+    this.value = [...arr];
+    this.size = arr.length;
+    this.buildMaxHeap();
+  }
+  swap = (i: number, j: number) => {
+    if (this.value[i] === this.value[j]) return;
+    this.value[i] = this.value[i] ^ this.value[j];
+    this.value[j] = this.value[i] ^ this.value[j];
+    this.value[i] = this.value[i] ^ this.value[j];
+  };
+  heapHandler = (i: number) => {
+    const left = 2 * i + 1;
+    const right = 2 * i + 2;
+    let largest = i;
+    if (left < this.size && this.value[left] > this.value[largest]) {
+      largest = left;
+    }
+    if (right < this.size && this.value[right] > this.value[largest]) {
+      largest = right;
+    }
+    if (largest !== i) {
+      this.swap(i, largest);
+      this.heapHandler(largest);
+    }
+  };
+  buildMaxHeap = () => {
+    for (let i = this.size >> 1; i >= 0; i--) {
+      this.heapHandler(i);
+    }
+    for (let i = this.size - 1; i >= 0; i--) {
+      this.swap(0, i);
+      this.size--;
+      this.heapHandler(0);
+    }
+  };
+}
+
+/**
+ * @description: 堆排序
+ * @param {Array} list
+ * @return {Array}
+ */
+const heap = (list: Array<number>): Array<number> => {
+  const { value } = new Heap(list);
+  return value;
+};
`,8)]))}const C=a(l,[["render",t]]);export{F as __pageData,C as default}; diff --git a/assets/cn_src_article_sort_index.md.B1KerO70.js b/assets/cn_src_article_sort_index.md.B1KerO70.js new file mode 100644 index 0000000000..d2d5da25f9 --- /dev/null +++ b/assets/cn_src_article_sort_index.md.B1KerO70.js @@ -0,0 +1 @@ +import{_ as t,a as e}from"./chunks/complexity.CSkvDr7k.js";import{_ as r,o as i,c as o,a3 as l}from"./chunks/framework.C-ai2y4t.js";const b=JSON.parse('{"title":"十大经典排序","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/index.md","filePath":"cn/src/article/sort/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/article/sort/index.md"};function s(c,a,d,p,m,h){return i(),o("div",{"data-pagefind-body":!0},a[0]||(a[0]=[l('

十大经典排序

十种常见排序算法可以分为两大类:

  • 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破 O(nlogn),因此也称为非线性时间比较类排序。
  • 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。

排序分类

算法复杂度

算法复杂度

相关概念

  • 稳定:如果 a 原本在 b 前面,而 a=b,排序之后 a 仍然在 b 的前面。
  • 不稳定:如果 a 原本在 b 的前面,而 a=b,排序之后 a 可能会出现在 b 的后面。
  • 时间复杂度:对排序数据的总的操作次数。反映当 n 变化时,操作次数呈现什么规律。
  • 空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模 n 的函数。
',8)]))}const f=r(n,[["render",s]]);export{b as __pageData,f as default}; diff --git a/assets/cn_src_article_sort_index.md.B1KerO70.lean.js b/assets/cn_src_article_sort_index.md.B1KerO70.lean.js new file mode 100644 index 0000000000..d2d5da25f9 --- /dev/null +++ b/assets/cn_src_article_sort_index.md.B1KerO70.lean.js @@ -0,0 +1 @@ +import{_ as t,a as e}from"./chunks/complexity.CSkvDr7k.js";import{_ as r,o as i,c as o,a3 as l}from"./chunks/framework.C-ai2y4t.js";const b=JSON.parse('{"title":"十大经典排序","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/index.md","filePath":"cn/src/article/sort/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/article/sort/index.md"};function s(c,a,d,p,m,h){return i(),o("div",{"data-pagefind-body":!0},a[0]||(a[0]=[l('

十大经典排序

十种常见排序算法可以分为两大类:

  • 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破 O(nlogn),因此也称为非线性时间比较类排序。
  • 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。

排序分类

算法复杂度

算法复杂度

相关概念

  • 稳定:如果 a 原本在 b 前面,而 a=b,排序之后 a 仍然在 b 的前面。
  • 不稳定:如果 a 原本在 b 的前面,而 a=b,排序之后 a 可能会出现在 b 的后面。
  • 时间复杂度:对排序数据的总的操作次数。反映当 n 变化时,操作次数呈现什么规律。
  • 空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模 n 的函数。
',8)]))}const f=r(n,[["render",s]]);export{b as __pageData,f as default}; diff --git a/assets/cn_src_article_sort_insert_index.md.D8ChYRq6.js b/assets/cn_src_article_sort_insert_index.md.D8ChYRq6.js new file mode 100644 index 0000000000..e36e9d20ab --- /dev/null +++ b/assets/cn_src_article_sort_insert_index.md.D8ChYRq6.js @@ -0,0 +1,13 @@ +import{_ as i}from"./chunks/insert.Bde3uDH4.js";import{_ as a,o as n,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"插入排序(Insert Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/insert/index.md","filePath":"cn/src/article/sort/insert/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/article/sort/insert/index.md"};function k(p,s,e,r,E,d){return n(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h('

插入排序(Insert Sort)

表现稳定的排序算法,因为无论什么数据进去都是 O(n2)的时间复杂度,所以用到它的时候,数据规模越小越好。优点是不占用额外的内存空间。工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

算法描述

  • 从第一个元素开始,该元素可以认为已经被排序;
  • 取出下一个元素,在已经排序的元素序列中从后向前扫描;
  • 如果该元素(已排序)大于新元素,将该元素移到下一位置;
  • 重复步骤 3,直到找到已排序的元素小于或者等于新元素的位置;
  • 将新元素插入到该位置后;
  • 重复步骤 2~5。

动图演示

插入排序

代码演示

ts
const insert = (list: number[]): number[] => {
+  const size = list.length;
+  for (let i = 1; i < size; i++) {
+    const current = list[i];
+    let preIndex = i - 1;
+    while (preIndex >= 0 && list[preIndex] > current) {
+      list[preIndex + 1] = list[preIndex];
+      preIndex--;
+    }
+    list[preIndex + 1] = current;
+  }
+  return list;
+};

算法分析

插入排序在实现上,通常采用 in-place 排序(即只需用到 O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

`,10)]))}const c=a(l,[["render",k]]);export{o as __pageData,c as default}; diff --git a/assets/cn_src_article_sort_insert_index.md.D8ChYRq6.lean.js b/assets/cn_src_article_sort_insert_index.md.D8ChYRq6.lean.js new file mode 100644 index 0000000000..e36e9d20ab --- /dev/null +++ b/assets/cn_src_article_sort_insert_index.md.D8ChYRq6.lean.js @@ -0,0 +1,13 @@ +import{_ as i}from"./chunks/insert.Bde3uDH4.js";import{_ as a,o as n,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"插入排序(Insert Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/insert/index.md","filePath":"cn/src/article/sort/insert/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/article/sort/insert/index.md"};function k(p,s,e,r,E,d){return n(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h('

插入排序(Insert Sort)

表现稳定的排序算法,因为无论什么数据进去都是 O(n2)的时间复杂度,所以用到它的时候,数据规模越小越好。优点是不占用额外的内存空间。工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

算法描述

  • 从第一个元素开始,该元素可以认为已经被排序;
  • 取出下一个元素,在已经排序的元素序列中从后向前扫描;
  • 如果该元素(已排序)大于新元素,将该元素移到下一位置;
  • 重复步骤 3,直到找到已排序的元素小于或者等于新元素的位置;
  • 将新元素插入到该位置后;
  • 重复步骤 2~5。

动图演示

插入排序

代码演示

ts
const insert = (list: number[]): number[] => {
+  const size = list.length;
+  for (let i = 1; i < size; i++) {
+    const current = list[i];
+    let preIndex = i - 1;
+    while (preIndex >= 0 && list[preIndex] > current) {
+      list[preIndex + 1] = list[preIndex];
+      preIndex--;
+    }
+    list[preIndex + 1] = current;
+  }
+  return list;
+};

算法分析

插入排序在实现上,通常采用 in-place 排序(即只需用到 O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

`,10)]))}const c=a(l,[["render",k]]);export{o as __pageData,c as default}; diff --git a/assets/cn_src_article_sort_merge_index.md.CywmRCFf.js b/assets/cn_src_article_sort_merge_index.md.CywmRCFf.js new file mode 100644 index 0000000000..81ce29ccf6 --- /dev/null +++ b/assets/cn_src_article_sort_merge_index.md.CywmRCFf.js @@ -0,0 +1,33 @@ +import{_ as i}from"./chunks/merge.D_M4N_iU.js";import{_ as a,o as h,c as n,a3 as k}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"归并排序(Merge Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/merge/index.md","filePath":"cn/src/article/sort/merge/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/article/sort/merge/index.md"};function t(p,s,e,E,r,d){return h(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k('

归并排序(Merge Sort)

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为 2-路归并。

算法描述

  • 把长度为 n 的输入序列分成两个长度为 n/2 的子序列;
  • 对这两个子序列分别采用归并排序;
  • 将两个排序好的子序列合并成一个最终的排序序列。

动图演示

归并排序

代码演示

ts
const combine = (left: Array<number>, right: Array<number>) => {
+  const list: Array<number> = [];
+  while (left.length > 0 && right.length > 0) {
+    if (left[0] <= right[0]) {
+      list.push(left.shift()!);
+    } else {
+      list.push(right.shift()!);
+    }
+  }
+
+  while (left.length) {
+    list.push(left.shift()!);
+  }
+  while (right.length) {
+    list.push(right.shift()!);
+  }
+  return list;
+};
+/**
+ * @description: 归并排序
+ * @param {Array} list
+ * @return {Array}
+ */
+const merge = (list: Array<number>): Array<number> => {
+  const { length } = list;
+  if (length <= 1) {
+    return list;
+  }
+  const middle = length >> 1;
+  const left = list.slice(0, middle);
+  const right = list.slice(middle);
+  return combine(merge(left), merge(right));
+};

算法分析

归并排序是一种稳定的排序方法。和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是 O(nlogn)的时间复杂度。代价是需要额外的内存空间。

`,10)]))}const c=a(l,[["render",t]]);export{F as __pageData,c as default}; diff --git a/assets/cn_src_article_sort_merge_index.md.CywmRCFf.lean.js b/assets/cn_src_article_sort_merge_index.md.CywmRCFf.lean.js new file mode 100644 index 0000000000..81ce29ccf6 --- /dev/null +++ b/assets/cn_src_article_sort_merge_index.md.CywmRCFf.lean.js @@ -0,0 +1,33 @@ +import{_ as i}from"./chunks/merge.D_M4N_iU.js";import{_ as a,o as h,c as n,a3 as k}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"归并排序(Merge Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/merge/index.md","filePath":"cn/src/article/sort/merge/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/article/sort/merge/index.md"};function t(p,s,e,E,r,d){return h(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k('

归并排序(Merge Sort)

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为 2-路归并。

算法描述

  • 把长度为 n 的输入序列分成两个长度为 n/2 的子序列;
  • 对这两个子序列分别采用归并排序;
  • 将两个排序好的子序列合并成一个最终的排序序列。

动图演示

归并排序

代码演示

ts
const combine = (left: Array<number>, right: Array<number>) => {
+  const list: Array<number> = [];
+  while (left.length > 0 && right.length > 0) {
+    if (left[0] <= right[0]) {
+      list.push(left.shift()!);
+    } else {
+      list.push(right.shift()!);
+    }
+  }
+
+  while (left.length) {
+    list.push(left.shift()!);
+  }
+  while (right.length) {
+    list.push(right.shift()!);
+  }
+  return list;
+};
+/**
+ * @description: 归并排序
+ * @param {Array} list
+ * @return {Array}
+ */
+const merge = (list: Array<number>): Array<number> => {
+  const { length } = list;
+  if (length <= 1) {
+    return list;
+  }
+  const middle = length >> 1;
+  const left = list.slice(0, middle);
+  const right = list.slice(middle);
+  return combine(merge(left), merge(right));
+};

算法分析

归并排序是一种稳定的排序方法。和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是 O(nlogn)的时间复杂度。代价是需要额外的内存空间。

`,10)]))}const c=a(l,[["render",t]]);export{F as __pageData,c as default}; diff --git a/assets/cn_src_article_sort_quick_index.md.BMawD0Bg.js b/assets/cn_src_article_sort_quick_index.md.BMawD0Bg.js new file mode 100644 index 0000000000..7f3e11bc9b --- /dev/null +++ b/assets/cn_src_article_sort_quick_index.md.BMawD0Bg.js @@ -0,0 +1,51 @@ +import{_ as i}from"./chunks/quick.WcLzRUPH.js";import{_ as a,o as n,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"快速排序(Quick Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/quick/index.md","filePath":"cn/src/article/sort/quick/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/article/sort/quick/index.md"};function t(p,s,e,r,E,d){return n(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k('

快速排序(Quick Sort)

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

算法描述

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

  • 从数列中挑出一个元素,称为 “基准”(pivot);
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

动图演示

快速排序

代码演示

ts
/**
+ * @description: 设置基准值pivot
+ * @param {Array} list
+ * @param {number} left
+ * @param {number} right
+ * @return {number} index
+ */
+const partition = (list: number[] = [], left: number, right: number) => {
+  const pivot = left;
+  let index = pivot + 1;
+  for (let i = index; i <= right; i++) {
+    if (list[i] < list[pivot]) {
+      if (list[i] !== list[index]) {
+        list[i] = list[i] ^ list[index];
+        list[index] = list[i] ^ list[index];
+        list[i] = list[i] ^ list[index];
+      }
+      index++;
+    }
+  }
+  if (list[index - 1] !== list[pivot]) {
+    list[index - 1] = list[index - 1] ^ list[pivot];
+    list[pivot] = list[index - 1] ^ list[pivot];
+    list[index - 1] = list[index - 1] ^ list[pivot];
+  }
+  return index - 1;
+};
+/**
+ * @description: 不断分区,设置基准值
+ * @param {Array} list
+ * @param {number} left
+ * @param {number} right
+ * @return {Array}
+ */
+const combine = (list: number[], left: number, right: number) => {
+  if (left < right) {
+    const partitionIndex: number = partition(list, left, right);
+    combine(list, partitionIndex + 1, right);
+    combine(list, left, partitionIndex - 1);
+  }
+  return list;
+};
+/**
+ * @description: 快速排序
+ * @param {Array} list
+ * @return {Array}
+ */
+const quick = (list: number[] = []): number[] => {
+  const size = list.length;
+  return combine(list, 0, size - 1);
+};
`,9)]))}const A=a(l,[["render",t]]);export{F as __pageData,A as default}; diff --git a/assets/cn_src_article_sort_quick_index.md.BMawD0Bg.lean.js b/assets/cn_src_article_sort_quick_index.md.BMawD0Bg.lean.js new file mode 100644 index 0000000000..7f3e11bc9b --- /dev/null +++ b/assets/cn_src_article_sort_quick_index.md.BMawD0Bg.lean.js @@ -0,0 +1,51 @@ +import{_ as i}from"./chunks/quick.WcLzRUPH.js";import{_ as a,o as n,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"快速排序(Quick Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/quick/index.md","filePath":"cn/src/article/sort/quick/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/article/sort/quick/index.md"};function t(p,s,e,r,E,d){return n(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k('

快速排序(Quick Sort)

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

算法描述

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

  • 从数列中挑出一个元素,称为 “基准”(pivot);
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

动图演示

快速排序

代码演示

ts
/**
+ * @description: 设置基准值pivot
+ * @param {Array} list
+ * @param {number} left
+ * @param {number} right
+ * @return {number} index
+ */
+const partition = (list: number[] = [], left: number, right: number) => {
+  const pivot = left;
+  let index = pivot + 1;
+  for (let i = index; i <= right; i++) {
+    if (list[i] < list[pivot]) {
+      if (list[i] !== list[index]) {
+        list[i] = list[i] ^ list[index];
+        list[index] = list[i] ^ list[index];
+        list[i] = list[i] ^ list[index];
+      }
+      index++;
+    }
+  }
+  if (list[index - 1] !== list[pivot]) {
+    list[index - 1] = list[index - 1] ^ list[pivot];
+    list[pivot] = list[index - 1] ^ list[pivot];
+    list[index - 1] = list[index - 1] ^ list[pivot];
+  }
+  return index - 1;
+};
+/**
+ * @description: 不断分区,设置基准值
+ * @param {Array} list
+ * @param {number} left
+ * @param {number} right
+ * @return {Array}
+ */
+const combine = (list: number[], left: number, right: number) => {
+  if (left < right) {
+    const partitionIndex: number = partition(list, left, right);
+    combine(list, partitionIndex + 1, right);
+    combine(list, left, partitionIndex - 1);
+  }
+  return list;
+};
+/**
+ * @description: 快速排序
+ * @param {Array} list
+ * @return {Array}
+ */
+const quick = (list: number[] = []): number[] => {
+  const size = list.length;
+  return combine(list, 0, size - 1);
+};
`,9)]))}const A=a(l,[["render",t]]);export{F as __pageData,A as default}; diff --git a/assets/cn_src_article_sort_radix_index.md.DIqt5q7a.js b/assets/cn_src_article_sort_radix_index.md.DIqt5q7a.js new file mode 100644 index 0000000000..f6c961ae0a --- /dev/null +++ b/assets/cn_src_article_sort_radix_index.md.DIqt5q7a.js @@ -0,0 +1,36 @@ +import{_ as i}from"./chunks/radix.CHOmrmB0.js";import{_ as a,o as h,c as n,a3 as k}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"基数排序(Radix Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/radix/index.md","filePath":"cn/src/article/sort/radix/index.md","lastUpdated":1726550590000}'),t={name:"cn/src/article/sort/radix/index.md"};function l(p,s,e,E,r,d){return h(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k('

基数排序(Radix Sort)

基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。桶排序扩展,类似于指定桶排序按位数排序规则,同时能利用计数排序适用于小范围数的特点。

算法描述

  • 取得数组中的最大数,并取得位数;
  • arr 为原始数组,从最低位开始取每个位组成 radix 数组;
  • 对 radix 进行计数排序(利用计数排序适用于小范围数的特点);

动图演示

基数排序

代码演示

ts
const getMax = (list: Array<number>) => {
+  let max = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+const getDigit = (num: number) => {
+  let digit = 1;
+  while (num >= 1) {
+    digit++;
+    num = num / 10;
+  }
+  return digit;
+};
+/**
+ * @description: 基数排序
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const radix = (list: Array<number>, maxDigit?: number): Array<number> => {
+  if (list.length === 0) return list;
+  if (!maxDigit) maxDigit = getDigit(getMax(list));
+  const buckets = new Array(maxDigit).fill(0).map(() => new Array(0));
+  for (let j = 0; j < list.length; j++) {
+    const digit = getDigit(list[j]);
+    buckets[digit - 1].push(list[j]);
+  }
+  list = [];
+  for (let i = 0; i < buckets.length; i++) {
+    list = list.concat(count(buckets[i]));
+  }
+  return list;
+};

算法分析

基数排序基于分配排序,所以是稳定的。但基数排序的性能比桶排序要略差,每一次关键字的桶分配都需要 O(n)的时间复杂度,而且分配之后得到新的关键字序列又需要 O(n)的时间复杂度。假如待排数据可以分为 d 个关键字,则基数排序的时间复杂度将是 O(d*2n) ,当然 d 要远远小于 n,因此基本上还是线性级别的。

基数排序的空间复杂度为 O(n+k),其中 k 为桶的数量。一般来说 n>>k,因此额外空间需要大概 n 个左右。

`,11)]))}const c=a(t,[["render",l]]);export{F as __pageData,c as default}; diff --git a/assets/cn_src_article_sort_radix_index.md.DIqt5q7a.lean.js b/assets/cn_src_article_sort_radix_index.md.DIqt5q7a.lean.js new file mode 100644 index 0000000000..f6c961ae0a --- /dev/null +++ b/assets/cn_src_article_sort_radix_index.md.DIqt5q7a.lean.js @@ -0,0 +1,36 @@ +import{_ as i}from"./chunks/radix.CHOmrmB0.js";import{_ as a,o as h,c as n,a3 as k}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"基数排序(Radix Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/radix/index.md","filePath":"cn/src/article/sort/radix/index.md","lastUpdated":1726550590000}'),t={name:"cn/src/article/sort/radix/index.md"};function l(p,s,e,E,r,d){return h(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k('

基数排序(Radix Sort)

基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。桶排序扩展,类似于指定桶排序按位数排序规则,同时能利用计数排序适用于小范围数的特点。

算法描述

  • 取得数组中的最大数,并取得位数;
  • arr 为原始数组,从最低位开始取每个位组成 radix 数组;
  • 对 radix 进行计数排序(利用计数排序适用于小范围数的特点);

动图演示

基数排序

代码演示

ts
const getMax = (list: Array<number>) => {
+  let max = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+const getDigit = (num: number) => {
+  let digit = 1;
+  while (num >= 1) {
+    digit++;
+    num = num / 10;
+  }
+  return digit;
+};
+/**
+ * @description: 基数排序
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const radix = (list: Array<number>, maxDigit?: number): Array<number> => {
+  if (list.length === 0) return list;
+  if (!maxDigit) maxDigit = getDigit(getMax(list));
+  const buckets = new Array(maxDigit).fill(0).map(() => new Array(0));
+  for (let j = 0; j < list.length; j++) {
+    const digit = getDigit(list[j]);
+    buckets[digit - 1].push(list[j]);
+  }
+  list = [];
+  for (let i = 0; i < buckets.length; i++) {
+    list = list.concat(count(buckets[i]));
+  }
+  return list;
+};

算法分析

基数排序基于分配排序,所以是稳定的。但基数排序的性能比桶排序要略差,每一次关键字的桶分配都需要 O(n)的时间复杂度,而且分配之后得到新的关键字序列又需要 O(n)的时间复杂度。假如待排数据可以分为 d 个关键字,则基数排序的时间复杂度将是 O(d*2n) ,当然 d 要远远小于 n,因此基本上还是线性级别的。

基数排序的空间复杂度为 O(n+k),其中 k 为桶的数量。一般来说 n>>k,因此额外空间需要大概 n 个左右。

`,11)]))}const c=a(t,[["render",l]]);export{F as __pageData,c as default}; diff --git a/assets/cn_src_article_sort_select_index.md.CwruXsFa.js b/assets/cn_src_article_sort_select_index.md.CwruXsFa.js new file mode 100644 index 0000000000..817b847e57 --- /dev/null +++ b/assets/cn_src_article_sort_select_index.md.CwruXsFa.js @@ -0,0 +1,17 @@ +import{_ as i}from"./chunks/select.BGReufCV.js";import{_ as a,o as n,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"选择排序(Selection Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/select/index.md","filePath":"cn/src/article/sort/select/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/article/sort/select/index.md"};function k(p,s,e,E,r,d){return n(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h('

选择排序(Selection Sort)

选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

算法描述

n 个记录的直接选择排序可经过 n-1 趟直接选择排序得到有序结果。具体算法描述如下:

  • 初始状态:无序区为 R[1..n],有序区为空;
  • 第 i 趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为 R[1..i-1]和 R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录 R[k],将它与无序区的第 1 个记录 R 交换,使 R[1..i]和 R[i+1..n)分别变为记录个数增加 1 个的新有序区和记录个数减少 1 个的新无序区;
  • n-1 趟结束,数组有序化了。

动图演示

选择排序

代码实现

js
const select = (list: number[]): number[] => {
+  const size = list.length;
+  for (let i = 0; i < size; i++) {
+    let minIndex = i;
+    for (let j = i + 1; j < size; j++) {
+      if (list[minIndex] >= list[j]) {
+        minIndex = j;
+      }
+    }
+    if (list[i] !== list[minIndex]) {
+      list[i] = list[i] ^ list[minIndex];
+      list[minIndex] = list[i] ^ list[minIndex];
+      list[i] = list[i] ^ list[minIndex];
+    }
+  }
+  return list;
+};

算法分析

表现最稳定的排序算法之一,因为无论什么数据进去都是 O(n2)的时间复杂度,所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。理论上讲,选择排序可能也是平时排序一般人想到的最多的排序方法了吧。

`,11)]))}const o=a(l,[["render",k]]);export{c as __pageData,o as default}; diff --git a/assets/cn_src_article_sort_select_index.md.CwruXsFa.lean.js b/assets/cn_src_article_sort_select_index.md.CwruXsFa.lean.js new file mode 100644 index 0000000000..817b847e57 --- /dev/null +++ b/assets/cn_src_article_sort_select_index.md.CwruXsFa.lean.js @@ -0,0 +1,17 @@ +import{_ as i}from"./chunks/select.BGReufCV.js";import{_ as a,o as n,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"选择排序(Selection Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/select/index.md","filePath":"cn/src/article/sort/select/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/article/sort/select/index.md"};function k(p,s,e,E,r,d){return n(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h('

选择排序(Selection Sort)

选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

算法描述

n 个记录的直接选择排序可经过 n-1 趟直接选择排序得到有序结果。具体算法描述如下:

  • 初始状态:无序区为 R[1..n],有序区为空;
  • 第 i 趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为 R[1..i-1]和 R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录 R[k],将它与无序区的第 1 个记录 R 交换,使 R[1..i]和 R[i+1..n)分别变为记录个数增加 1 个的新有序区和记录个数减少 1 个的新无序区;
  • n-1 趟结束,数组有序化了。

动图演示

选择排序

代码实现

js
const select = (list: number[]): number[] => {
+  const size = list.length;
+  for (let i = 0; i < size; i++) {
+    let minIndex = i;
+    for (let j = i + 1; j < size; j++) {
+      if (list[minIndex] >= list[j]) {
+        minIndex = j;
+      }
+    }
+    if (list[i] !== list[minIndex]) {
+      list[i] = list[i] ^ list[minIndex];
+      list[minIndex] = list[i] ^ list[minIndex];
+      list[i] = list[i] ^ list[minIndex];
+    }
+  }
+  return list;
+};

算法分析

表现最稳定的排序算法之一,因为无论什么数据进去都是 O(n2)的时间复杂度,所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。理论上讲,选择排序可能也是平时排序一般人想到的最多的排序方法了吧。

`,11)]))}const o=a(l,[["render",k]]);export{c as __pageData,o as default}; diff --git a/assets/cn_src_article_sort_shell_index.md.BjqTtSjT.js b/assets/cn_src_article_sort_shell_index.md.BjqTtSjT.js new file mode 100644 index 0000000000..0400976752 --- /dev/null +++ b/assets/cn_src_article_sort_shell_index.md.BjqTtSjT.js @@ -0,0 +1,20 @@ +import{_ as i}from"./chunks/shell.CGEkKxrp.js";import{_ as a,o as n,c as h,a3 as l}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"希尔排序(Shell Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/shell/index.md","filePath":"cn/src/article/sort/shell/index.md","lastUpdated":1726550590000}'),t={name:"cn/src/article/sort/shell/index.md"};function k(p,s,e,r,E,d){return n(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[l('

希尔排序(Shell Sort)

1959 年 Shell 发明,第一个突破 O(n2)的排序算法,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。

算法描述

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:

  • 选择一个增量序列 t1,t2,…,tk,其中 ti>tj,tk=1;
  • 按增量序列个数 k,对序列进行 k 趟排序;
  • 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

动图演示

希尔排序

代码实现

js
/**
+ * @description: 希尔排序,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
+ * @param {Array} list
+ * @return {Array}
+ */
+const shell = (list: number[]): number[] => {
+  const size = list.length;
+  for (let gap = size >> 1; gap > 0; gap >>= 1) {
+    for (let i = gap; i < size; i += gap) {
+      const current = list[i];
+      let preIndex = i - gap;
+      while (preIndex >= 0 && list[preIndex] > current) {
+        list[preIndex + gap] = list[preIndex];
+        preIndex -= gap;
+      }
+      list[preIndex + gap] = current;
+    }
+  }
+  return list;
+};

算法分析

希尔排序的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列。动态定义间隔序列的算法是《算法(第 4 版)》的合著者 Robert Sedgewick 提出的。

`,11)]))}const o=a(t,[["render",k]]);export{c as __pageData,o as default}; diff --git a/assets/cn_src_article_sort_shell_index.md.BjqTtSjT.lean.js b/assets/cn_src_article_sort_shell_index.md.BjqTtSjT.lean.js new file mode 100644 index 0000000000..0400976752 --- /dev/null +++ b/assets/cn_src_article_sort_shell_index.md.BjqTtSjT.lean.js @@ -0,0 +1,20 @@ +import{_ as i}from"./chunks/shell.CGEkKxrp.js";import{_ as a,o as n,c as h,a3 as l}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"希尔排序(Shell Sort)","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/sort/shell/index.md","filePath":"cn/src/article/sort/shell/index.md","lastUpdated":1726550590000}'),t={name:"cn/src/article/sort/shell/index.md"};function k(p,s,e,r,E,d){return n(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[l('

希尔排序(Shell Sort)

1959 年 Shell 发明,第一个突破 O(n2)的排序算法,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。

算法描述

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:

  • 选择一个增量序列 t1,t2,…,tk,其中 ti>tj,tk=1;
  • 按增量序列个数 k,对序列进行 k 趟排序;
  • 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

动图演示

希尔排序

代码实现

js
/**
+ * @description: 希尔排序,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
+ * @param {Array} list
+ * @return {Array}
+ */
+const shell = (list: number[]): number[] => {
+  const size = list.length;
+  for (let gap = size >> 1; gap > 0; gap >>= 1) {
+    for (let i = gap; i < size; i += gap) {
+      const current = list[i];
+      let preIndex = i - gap;
+      while (preIndex >= 0 && list[preIndex] > current) {
+        list[preIndex + gap] = list[preIndex];
+        preIndex -= gap;
+      }
+      list[preIndex + gap] = current;
+    }
+  }
+  return list;
+};

算法分析

希尔排序的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列。动态定义间隔序列的算法是《算法(第 4 版)》的合著者 Robert Sedgewick 提出的。

`,11)]))}const o=a(t,[["render",k]]);export{c as __pageData,o as default}; diff --git a/assets/cn_src_article_systemDesign.md.DXbjsTs-.js b/assets/cn_src_article_systemDesign.md.DXbjsTs-.js new file mode 100644 index 0000000000..367c6c6132 --- /dev/null +++ b/assets/cn_src_article_systemDesign.md.DXbjsTs-.js @@ -0,0 +1 @@ +import{_ as e,o as t,c as r,a3 as s}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"如何处理一个系统设计","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/systemDesign.md","filePath":"cn/src/article/systemDesign.md","lastUpdated":1726550590000}'),o={name:"cn/src/article/systemDesign.md"};function i(n,a,l,p,c,d){return t(),r("div",{"data-pagefind-body":!0},a[0]||(a[0]=[s('

如何处理一个系统设计

系统设计是一个开放式的对话。他们期望你去主导这个对话。

你可以使用下面的步骤来指引讨论。为了巩固这个过程,请使用下面的步骤完成系统设计的面试题和解答这个章节。

第一步:描述使用场景,约束和假设

把所有需要的东西聚集在一起,审视问题。不停的提问,以至于我们可以明确使用场景和约束。讨论假设。

谁会使用它? 他们会怎样使用它? 有多少用户? 系统的作用是什么? 系统的输入输出分别是什么? 我们希望处理多少数据? 我们希望每秒钟处理多少请求? 我们希望的读写比率?

第二步:创造一个高层级的设计

使用所有重要的组件来描绘出一个高层级的设计。

画出主要的组件和连接 证明你的想法

第三步:设计核心组件

对每一个核心组件进行详细深入的分析。举例来说,如果你被问到设计一个 url 缩写服务,开始讨论:

生成并储存一个完整 url 的 hash MD5 和 Base62 Hash 碰撞 SQL 还是 NoSQL 数据库模型 将一个 hashed url 翻译成完整的 url 数据库查找 API 和面向对象设计

第四步:扩展设计

确认和处理瓶颈以及一些限制。举例来说就是你需要下面的这些来完成扩展性的议题吗?

负载均衡 水平扩展 缓存 数据库分片 论述可能的解决办法和代价。每件事情需要取舍。可以使用可扩展系统的设计原则来处理瓶颈。

',15)]))}const m=e(o,[["render",i]]);export{u as __pageData,m as default}; diff --git a/assets/cn_src_article_systemDesign.md.DXbjsTs-.lean.js b/assets/cn_src_article_systemDesign.md.DXbjsTs-.lean.js new file mode 100644 index 0000000000..367c6c6132 --- /dev/null +++ b/assets/cn_src_article_systemDesign.md.DXbjsTs-.lean.js @@ -0,0 +1 @@ +import{_ as e,o as t,c as r,a3 as s}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"如何处理一个系统设计","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/systemDesign.md","filePath":"cn/src/article/systemDesign.md","lastUpdated":1726550590000}'),o={name:"cn/src/article/systemDesign.md"};function i(n,a,l,p,c,d){return t(),r("div",{"data-pagefind-body":!0},a[0]||(a[0]=[s('

如何处理一个系统设计

系统设计是一个开放式的对话。他们期望你去主导这个对话。

你可以使用下面的步骤来指引讨论。为了巩固这个过程,请使用下面的步骤完成系统设计的面试题和解答这个章节。

第一步:描述使用场景,约束和假设

把所有需要的东西聚集在一起,审视问题。不停的提问,以至于我们可以明确使用场景和约束。讨论假设。

谁会使用它? 他们会怎样使用它? 有多少用户? 系统的作用是什么? 系统的输入输出分别是什么? 我们希望处理多少数据? 我们希望每秒钟处理多少请求? 我们希望的读写比率?

第二步:创造一个高层级的设计

使用所有重要的组件来描绘出一个高层级的设计。

画出主要的组件和连接 证明你的想法

第三步:设计核心组件

对每一个核心组件进行详细深入的分析。举例来说,如果你被问到设计一个 url 缩写服务,开始讨论:

生成并储存一个完整 url 的 hash MD5 和 Base62 Hash 碰撞 SQL 还是 NoSQL 数据库模型 将一个 hashed url 翻译成完整的 url 数据库查找 API 和面向对象设计

第四步:扩展设计

确认和处理瓶颈以及一些限制。举例来说就是你需要下面的这些来完成扩展性的议题吗?

负载均衡 水平扩展 缓存 数据库分片 论述可能的解决办法和代价。每件事情需要取舍。可以使用可扩展系统的设计原则来处理瓶颈。

',15)]))}const m=e(o,[["render",i]]);export{u as __pageData,m as default}; diff --git a/assets/cn_src_article_typescript_calculate.md.C_dGguN1.js b/assets/cn_src_article_typescript_calculate.md.C_dGguN1.js new file mode 100644 index 0000000000..28af459e0f --- /dev/null +++ b/assets/cn_src_article_typescript_calculate.md.C_dGguN1.js @@ -0,0 +1,31 @@ +import{_ as i,o as a,c as h,a3 as n}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"数组长度做计数","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/typescript/calculate.md","filePath":"cn/src/article/typescript/calculate.md","lastUpdated":1726550590000}'),k={name:"cn/src/article/typescript/calculate.md"};function t(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

数组长度做计数

类型系统不是图灵完备,各种逻辑都能写么,但好像没发现数值相关的逻辑。

没错,数值相关的逻辑比较绕,被我单独摘了出来,就是这节要讲的内容。

这是类型体操的第四个套路:数组长度做计数。

TypeScript 类型系统没有加减乘除运算符,怎么做数值运算呢?

不知道大家有没有注意到数组类型取 length 就是数值。

比如:

ts
type num1 = [unknown]['length'];
+// type num1 = 1
+type num2 = [unknown, unknown]['length'];
+// type num1 = 2
+type num3 = [unknown, unknown, unknown]['length'];
+// type num1 = 3

而数组类型我们是能构造出来的,那么通过构造不同长度的数组然后取 length,不就是数值的运算么?

TypeScript 类型系统中没有加减乘除运算符,但是可以通过构造不同的数组然后取 length 的方式来完成数值计算,把数值的加减乘除转化为对数组的提取和构造。

(严格来说构造的是元组,大家知道数组和元组的区别就行)

这点可以说是类型体操中最麻烦的一个点,需要思维做一些转换,绕过这个弯来。

下面我们就来做一些真实的案例来掌握它吧。

数组长度实现加减乘除

Add

我们知道了数值计算要转换为对数组类型的操作,那么加法的实现很容易想到:

构造两个数组,然后合并成一个,取 length。

比如 3 + 2,就是构造一个长度为 3 的数组类型,再构造一个长度为 2 的数组类型,然后合并成一个数组,取 length。

构造多长的数组是不确定的,需要递归构造,这个我们实现过:

ts
type BuildArray<Length extends number, Ele = unknown, Arr extends unknown[] = []> = Arr['length'] extends Length
+  ? Arr
+  : BuildArray<Length, Ele, [...Arr, Ele]>;

类型参数 Length 是要构造的数组的长度。类型参数 Ele 是数组元素,默认为 unknown。类型参数 Arr 为构造出的数组,默认是 []。

如果 Arr 的长度到达了 Length,就返回构造出的 Arr,否则继续递归构造。

构造数组实现了,那么基于它就能实现加法:

ts
type Add<Num1 extends number, Num2 extends number> = [...BuildArray<Num1>, ...BuildArray<Num2>]['length'];

我们拿大一点的数测试下:

ts
type AddResult = Add<32, 25>;
+// type AddResult = 57

就这样,我们通过构造一定长度的数组取 length 的方式实现了加法运算。

Subtract

加法是构造数组,那减法怎么做呢?

减法是从数值中去掉一部分,很容易想到可以通过数组类型的提取来做。

比如 3 是 [unknown, unknown, unknown] 的数组类型,提取出 2 个元素之后,剩下的数组再取 length 就是 1。

所以减法的实现是这样的:

ts
type Subtract<Num1 extends number, Num2 extends number> =
+  BuildArray<Num1> extends [...arr1: BuildArray<Num2>, ...arr2: infer Rest] ? Rest['length'] : never;

类型参数 Num1、Num2 分别是被减数和减数,通过 extends 约束为 number。

构造 Num1 长度的数组,通过模式匹配提取出 Num2 长度个元素,剩下的放到 infer 声明的局部变量 Rest 里。

取 Rest 的长度返回,就是减法的结果。

就这样,我们通过数组类型的提取实现了减法运算。

Multiply

我们把加法转换为了数组构造,把减法转换为了数组提取。那乘法怎么做呢?

为了解释乘法,我去翻了下小学教材,找到了这样一张图:

1 乘以 5 就相当于 1 + 1 + 1 + 1 + 1,也就是说乘法就是多个加法结果的累加。

那么我们在加法的基础上,多加一个参数来传递中间结果的数组,算完之后再取一次 length 就能实现乘法:

ts
type Multiplication<Num1 extends number, Num2 extends number, ResultArr extends unknown[] = []> = Num2 extends 0
+  ? ResultArr['length']
+  : Multiplication<Num1, Subtract<Num2, 1>, [...BuildArray<Num1>, ...ResultArr]>;

类型参数 Num1 和 Num2 分别是被加数和加数。

因为乘法是多个加法结果的累加,我们加了一个类型参数 ResultArr 来保存中间结果,默认值是 [],相当于从 0 开始加。

每加一次就把 Num2 减一,直到 Num2 为 0,就代表加完了。

加的过程就是往 ResultArr 数组中放 Num1 个元素。

这样递归的进行累加,也就是递归的往 ResultArr 中放元素。

最后取 ResultArr 的 length 就是乘法的结果。

就这样,我们通过递归的累加实现了乘法。

Divide

乘法是递归的累加,那除法不就是递归的累减么?

我再去翻了下小学教材,找到了这样一张图:

我们有 9 个苹果,分给美羊羊 3 个,分给懒羊羊 3 个,分给沸羊羊 3 个,最后剩下 0 个。所以 9 / 3 = 3。

所以,除法的实现就是被减数不断减去减数,直到减为 0,记录减了几次就是结果。

也就是这样的:

ts
type Divide<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends 0
+  ? CountArr['length']
+  : Divide<Subtract<Num1, Num2>, Num2, [unknown, ...CountArr]>;

类型参数 Num1 和 Num2 分别是被减数和减数。

类型参数 CountArr 是用来记录减了几次的累加数组。

如果 Num1 减到了 0 ,那么这时候减了几次就是除法结果,也就是 CountArr['length']。

否则继续递归的减,让 Num1 减去 Num2,并且 CountArr 多加一个元素代表又减了一次。

这样就实现了除法:

就这样,我们通过递归的累减并记录减了几次实现了除法。

做完了加减乘除,我们再来做一些别的数值计算的类型体操。

数组长度实现计数

StrLen

数组长度可以取 length 来得到,但是字符串类型不能取 length,所以我们来实现一个求字符串长度的高级类型。

字符串长度不确定,明显要用递归。每次取一个并计数,直到取完,就是字符串长度。

ts
type StrLen<Str extends string, CountArr extends unknown[] = []> = Str extends \`\${string}\${infer Rest}\`
+  ? StrLen<Rest, [...CountArr, unknown]>
+  : CountArr['length'];

类型参数 Str 是待处理的字符串。类型参数 CountArr 是做计数的数组,默认值 [] 代表从 0 开始。

每次通过模式匹配提取去掉一个字符之后的剩余字符串,并且往计数数组里多放入一个元素。递归进行取字符和计数。

如果模式匹配不满足,代表计数结束,返回计数数组的长度 CountArr['length']。

这样就能求出字符串长度:

GreaterThan

能够做计数了,那也就能做两个数值的比较。

我们往一个数组类型中不断放入元素取长度,如果先到了 A,那就是 B 大,否则是 A 大:

ts
type GreaterThan<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends Num2
+  ? false
+  : CountArr['length'] extends Num2
+    ? true
+    : CountArr['length'] extends Num1
+      ? false
+      : GreaterThan<Num1, Num2, [...CountArr, unknown]>;

类型参数 Num1 和 Num2 是待比较的两个数。

类型参数 CountArr 是计数用的,会不断累加,默认值是 [] 代表从 0 开始。

如果 Num1 extends Num2 成立,代表相等,直接返回 false。

否则判断计数数组的长度,如果先到了 Num2,那么就是 Num1 大,返回 true。

反之,如果先到了 Num1,那么就是 Num2 大,返回 false。

如果都没到就往计数数组 CountArr 中放入一个元素,继续递归。

这样就实现了数值比较。

当 3 和 4 比较时:

Fibonacci

谈到了数值运算,就不得不提起经典的 Fibonacci 数列的计算。

Fibonacci 数列是 1、1、2、3、5、8、13、21、34、…… 这样的数列,有当前的数是前两个数的和的规律。

F(0) = 1,F(1) = 1, F(n) = F(n - 1) + F(n - 2)(n ≥ 2,n ∈ N*)

也就是递归的加法,在 TypeScript 类型编程里用构造数组来实现这种加法:

ts
type FibonacciLoop<
+  PrevArr extends unknown[],
+  CurrentArr extends unknown[],
+  IndexArr extends unknown[] = [],
+  Num extends number = 1,
+> = IndexArr['length'] extends Num
+  ? CurrentArr['length']
+  : FibonacciLoop<CurrentArr, [...PrevArr, ...CurrentArr], [...IndexArr, unknown], Num>;
+
+type Fibonacci<Num extends number> = FibonacciLoop<[1], [], [], Num>;

类型参数 PrevArr 是代表之前的累加值的数组。类型参数 CurrentArr 是代表当前数值的数组。

类型参数 IndexArr 用于记录 index,每次递归加一,默认值是 [],代表从 0 开始。

类型参数 Num 代表求数列的第几个数。

判断当前 index 也就是 IndexArr['length'] 是否到了 Num,到了就返回当前的数值 CurrentArr['length']。

否则求出当前 index 对应的数值,用之前的数加上当前的数 [...PrevArr, ... CurrentArr]。

然后继续递归,index + 1,也就是 [...IndexArr, unknown]。

这就是递归计算 Fibinacci 数列的数的过程。

可以正确的算出第 8 个数是 21:

`,99)]))}const F=i(k,[["render",t]]);export{g as __pageData,F as default}; diff --git a/assets/cn_src_article_typescript_calculate.md.C_dGguN1.lean.js b/assets/cn_src_article_typescript_calculate.md.C_dGguN1.lean.js new file mode 100644 index 0000000000..28af459e0f --- /dev/null +++ b/assets/cn_src_article_typescript_calculate.md.C_dGguN1.lean.js @@ -0,0 +1,31 @@ +import{_ as i,o as a,c as h,a3 as n}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"数组长度做计数","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/typescript/calculate.md","filePath":"cn/src/article/typescript/calculate.md","lastUpdated":1726550590000}'),k={name:"cn/src/article/typescript/calculate.md"};function t(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

数组长度做计数

类型系统不是图灵完备,各种逻辑都能写么,但好像没发现数值相关的逻辑。

没错,数值相关的逻辑比较绕,被我单独摘了出来,就是这节要讲的内容。

这是类型体操的第四个套路:数组长度做计数。

TypeScript 类型系统没有加减乘除运算符,怎么做数值运算呢?

不知道大家有没有注意到数组类型取 length 就是数值。

比如:

ts
type num1 = [unknown]['length'];
+// type num1 = 1
+type num2 = [unknown, unknown]['length'];
+// type num1 = 2
+type num3 = [unknown, unknown, unknown]['length'];
+// type num1 = 3

而数组类型我们是能构造出来的,那么通过构造不同长度的数组然后取 length,不就是数值的运算么?

TypeScript 类型系统中没有加减乘除运算符,但是可以通过构造不同的数组然后取 length 的方式来完成数值计算,把数值的加减乘除转化为对数组的提取和构造。

(严格来说构造的是元组,大家知道数组和元组的区别就行)

这点可以说是类型体操中最麻烦的一个点,需要思维做一些转换,绕过这个弯来。

下面我们就来做一些真实的案例来掌握它吧。

数组长度实现加减乘除

Add

我们知道了数值计算要转换为对数组类型的操作,那么加法的实现很容易想到:

构造两个数组,然后合并成一个,取 length。

比如 3 + 2,就是构造一个长度为 3 的数组类型,再构造一个长度为 2 的数组类型,然后合并成一个数组,取 length。

构造多长的数组是不确定的,需要递归构造,这个我们实现过:

ts
type BuildArray<Length extends number, Ele = unknown, Arr extends unknown[] = []> = Arr['length'] extends Length
+  ? Arr
+  : BuildArray<Length, Ele, [...Arr, Ele]>;

类型参数 Length 是要构造的数组的长度。类型参数 Ele 是数组元素,默认为 unknown。类型参数 Arr 为构造出的数组,默认是 []。

如果 Arr 的长度到达了 Length,就返回构造出的 Arr,否则继续递归构造。

构造数组实现了,那么基于它就能实现加法:

ts
type Add<Num1 extends number, Num2 extends number> = [...BuildArray<Num1>, ...BuildArray<Num2>]['length'];

我们拿大一点的数测试下:

ts
type AddResult = Add<32, 25>;
+// type AddResult = 57

就这样,我们通过构造一定长度的数组取 length 的方式实现了加法运算。

Subtract

加法是构造数组,那减法怎么做呢?

减法是从数值中去掉一部分,很容易想到可以通过数组类型的提取来做。

比如 3 是 [unknown, unknown, unknown] 的数组类型,提取出 2 个元素之后,剩下的数组再取 length 就是 1。

所以减法的实现是这样的:

ts
type Subtract<Num1 extends number, Num2 extends number> =
+  BuildArray<Num1> extends [...arr1: BuildArray<Num2>, ...arr2: infer Rest] ? Rest['length'] : never;

类型参数 Num1、Num2 分别是被减数和减数,通过 extends 约束为 number。

构造 Num1 长度的数组,通过模式匹配提取出 Num2 长度个元素,剩下的放到 infer 声明的局部变量 Rest 里。

取 Rest 的长度返回,就是减法的结果。

就这样,我们通过数组类型的提取实现了减法运算。

Multiply

我们把加法转换为了数组构造,把减法转换为了数组提取。那乘法怎么做呢?

为了解释乘法,我去翻了下小学教材,找到了这样一张图:

1 乘以 5 就相当于 1 + 1 + 1 + 1 + 1,也就是说乘法就是多个加法结果的累加。

那么我们在加法的基础上,多加一个参数来传递中间结果的数组,算完之后再取一次 length 就能实现乘法:

ts
type Multiplication<Num1 extends number, Num2 extends number, ResultArr extends unknown[] = []> = Num2 extends 0
+  ? ResultArr['length']
+  : Multiplication<Num1, Subtract<Num2, 1>, [...BuildArray<Num1>, ...ResultArr]>;

类型参数 Num1 和 Num2 分别是被加数和加数。

因为乘法是多个加法结果的累加,我们加了一个类型参数 ResultArr 来保存中间结果,默认值是 [],相当于从 0 开始加。

每加一次就把 Num2 减一,直到 Num2 为 0,就代表加完了。

加的过程就是往 ResultArr 数组中放 Num1 个元素。

这样递归的进行累加,也就是递归的往 ResultArr 中放元素。

最后取 ResultArr 的 length 就是乘法的结果。

就这样,我们通过递归的累加实现了乘法。

Divide

乘法是递归的累加,那除法不就是递归的累减么?

我再去翻了下小学教材,找到了这样一张图:

我们有 9 个苹果,分给美羊羊 3 个,分给懒羊羊 3 个,分给沸羊羊 3 个,最后剩下 0 个。所以 9 / 3 = 3。

所以,除法的实现就是被减数不断减去减数,直到减为 0,记录减了几次就是结果。

也就是这样的:

ts
type Divide<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends 0
+  ? CountArr['length']
+  : Divide<Subtract<Num1, Num2>, Num2, [unknown, ...CountArr]>;

类型参数 Num1 和 Num2 分别是被减数和减数。

类型参数 CountArr 是用来记录减了几次的累加数组。

如果 Num1 减到了 0 ,那么这时候减了几次就是除法结果,也就是 CountArr['length']。

否则继续递归的减,让 Num1 减去 Num2,并且 CountArr 多加一个元素代表又减了一次。

这样就实现了除法:

就这样,我们通过递归的累减并记录减了几次实现了除法。

做完了加减乘除,我们再来做一些别的数值计算的类型体操。

数组长度实现计数

StrLen

数组长度可以取 length 来得到,但是字符串类型不能取 length,所以我们来实现一个求字符串长度的高级类型。

字符串长度不确定,明显要用递归。每次取一个并计数,直到取完,就是字符串长度。

ts
type StrLen<Str extends string, CountArr extends unknown[] = []> = Str extends \`\${string}\${infer Rest}\`
+  ? StrLen<Rest, [...CountArr, unknown]>
+  : CountArr['length'];

类型参数 Str 是待处理的字符串。类型参数 CountArr 是做计数的数组,默认值 [] 代表从 0 开始。

每次通过模式匹配提取去掉一个字符之后的剩余字符串,并且往计数数组里多放入一个元素。递归进行取字符和计数。

如果模式匹配不满足,代表计数结束,返回计数数组的长度 CountArr['length']。

这样就能求出字符串长度:

GreaterThan

能够做计数了,那也就能做两个数值的比较。

我们往一个数组类型中不断放入元素取长度,如果先到了 A,那就是 B 大,否则是 A 大:

ts
type GreaterThan<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends Num2
+  ? false
+  : CountArr['length'] extends Num2
+    ? true
+    : CountArr['length'] extends Num1
+      ? false
+      : GreaterThan<Num1, Num2, [...CountArr, unknown]>;

类型参数 Num1 和 Num2 是待比较的两个数。

类型参数 CountArr 是计数用的,会不断累加,默认值是 [] 代表从 0 开始。

如果 Num1 extends Num2 成立,代表相等,直接返回 false。

否则判断计数数组的长度,如果先到了 Num2,那么就是 Num1 大,返回 true。

反之,如果先到了 Num1,那么就是 Num2 大,返回 false。

如果都没到就往计数数组 CountArr 中放入一个元素,继续递归。

这样就实现了数值比较。

当 3 和 4 比较时:

Fibonacci

谈到了数值运算,就不得不提起经典的 Fibonacci 数列的计算。

Fibonacci 数列是 1、1、2、3、5、8、13、21、34、…… 这样的数列,有当前的数是前两个数的和的规律。

F(0) = 1,F(1) = 1, F(n) = F(n - 1) + F(n - 2)(n ≥ 2,n ∈ N*)

也就是递归的加法,在 TypeScript 类型编程里用构造数组来实现这种加法:

ts
type FibonacciLoop<
+  PrevArr extends unknown[],
+  CurrentArr extends unknown[],
+  IndexArr extends unknown[] = [],
+  Num extends number = 1,
+> = IndexArr['length'] extends Num
+  ? CurrentArr['length']
+  : FibonacciLoop<CurrentArr, [...PrevArr, ...CurrentArr], [...IndexArr, unknown], Num>;
+
+type Fibonacci<Num extends number> = FibonacciLoop<[1], [], [], Num>;

类型参数 PrevArr 是代表之前的累加值的数组。类型参数 CurrentArr 是代表当前数值的数组。

类型参数 IndexArr 用于记录 index,每次递归加一,默认值是 [],代表从 0 开始。

类型参数 Num 代表求数列的第几个数。

判断当前 index 也就是 IndexArr['length'] 是否到了 Num,到了就返回当前的数值 CurrentArr['length']。

否则求出当前 index 对应的数值,用之前的数加上当前的数 [...PrevArr, ... CurrentArr]。

然后继续递归,index + 1,也就是 [...IndexArr, unknown]。

这就是递归计算 Fibinacci 数列的数的过程。

可以正确的算出第 8 个数是 21:

`,99)]))}const F=i(k,[["render",t]]);export{g as __pageData,F as default}; diff --git a/assets/cn_src_article_typescript_index.md.dV9VtsjJ.js b/assets/cn_src_article_typescript_index.md.dV9VtsjJ.js new file mode 100644 index 0000000000..a93efc6a2a --- /dev/null +++ b/assets/cn_src_article_typescript_index.md.dV9VtsjJ.js @@ -0,0 +1,156 @@ +import{_ as i,o as a,c as h,a3 as n}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"TypeScript 的类型系统","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/typescript/index.md","filePath":"cn/src/article/typescript/index.md","lastUpdated":1726550590000}'),k={name:"cn/src/article/typescript/index.md"};function p(t,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

TypeScript 的类型系统

一.类型是什么

类型具体点来说就是指 number、boolean、string 等基础类型和 Object、Function 等复合类型,它们是编程语言提供的对不同内容的抽象:

  • 不同类型变量占据的内存大小不同: boolean 类型的变量会分配 4 个字节的内存,而 number 类型的变量则会分配 8 个字节的内存,给变量声明了不同的类型就代表了会占据不同的内存空间。

  • 不同类型变量可做的操作不同: number 类型可以做加减乘除等运算,boolean 就不可以,复合类型中不同类型的对象可用的方法不同,比如 Date 和 RegExp,变量的类型不同代表可以对该变量做的操作就不同。

有了类型,那我们的操作必须和类型相匹配,否则就会报错,这就是类型检查。

如果能保证对某种类型只做该类型允许的操作,这就叫做类型安全。

类型检查可以在运行时做,也可以运行之前的编译期做。这是两种不同的类型,前者叫做动态类型检查,后者叫做静态类型检查。

两种类型检查各有优缺点。动态类型检查 在源码中不保留类型信息,对某个变量赋什么值、做什么操作都是允许的,写代码很灵活。但这也埋下了类型不安全的隐患,比如对 string 做了乘除,对 Date 对象调用了 exec 方法,这些都是运行时才能检查出来的错误。

其中,最常见的错误应该是 “null is not an object”、“undefined is not a function” 之类的了,写代码时没发现类型不匹配,到了运行的时候才发现,就会有很多这种报错。

所以,动态类型虽然代码写起来简单,但代码中很容易藏着一些类型不匹配的隐患。

静态类型检查则是在源码中保留类型信息,声明变量要指定类型,对变量做的操作要和类型匹配,会有专门的编译器在编译期间做检查。

静态类型给写代码增加了一些难度,因为你除了要考虑代码要表达的逻辑之外,还要考虑类型逻辑:变量是什么类型的、是不是匹配、要不要做类型转换等。

不过,静态类型也消除了类型不安全的隐患,因为在编译期间就做了类型检查,就不会出现对 string 做了乘除,调用了 Date 的 exec 方法这类问题。

所以,静态类型虽然代码写起来要考虑的问题多一些,会复杂一些,但是却消除了代码中潜藏类型不安全问题的可能。

知道了动态类型检查和静态类型检查的区别,我们自然可以得出这样的结论:

动态类型只适合简单的场景,对于大项目却不太合适,因为代码中可能藏着的隐患太多了,万一线上报一个类型不匹配的错误,那可能就是大问题。

而静态类型虽然会增加写代码的成本,但是却能更好的保证代码的健壮性,减少 Bug 率。

所以,大型项目注定会用静态类型语言开发。

二.类型系统的分类

1.简单的类型系统

变量、函数、类等都可以声明类型,编译器会基于声明的类型做类型检查,类型不匹配时会报错。

这是最基础的类型系统,能保证类型安全,但有些死板。

比如一个 add 函数既可以做整数加法、又可以做浮点数加法,却需要声明两个函数:

c
int add(int a, int b) {
+    return a + b;
+}
+
+double add(double a, double b) {
+    return a + b;
+}

这个问题的解决思路很容易想到:如果类型能传参数就好了,传入 int 就是整数加法,传入 double 就是浮点数加法。

所以,就有了第二种类型系统。

2.支持泛型的类型系统

泛型的英文是 Generic Type,通用的类型,它可以代表任何一种类型,也叫做类型参数。

它给类型系统增加了一些灵活性,在整体比较固定,部分变量的类型有变化的情况下,可以减少很多重复代码。

比如上面的 add 函数,有了泛型之后就可以这样写:

java
T add<T>(T a, T b) {
+    return a + b;
+}
+
+add(1,2);
+add(1.111, 2.2222);

声明时把会变化的类型声明成泛型(也就是类型参数),在调用的时候再确定类型。

Java 就是这种类型系统。如果你看过 Java 代码,你会发现泛型用的特别多,这确实是一个很好的增加类型系统灵活性的特性。

但是,这种类型系统的灵活性对于 JavaScript 来说还不够,因为 JavaScript 太过灵活了。

比如,在 Java 里,对象都是由类 new 出来的,你不能凭空创建对象,但是 JavaScript 却可以,它支持对象字面量。

那如果是一个返回对象某个属性值的函数,类型该怎么写呢?

ts
function getPropValue<T>(obj: T, key): key对应的属性值类型 {
+  return obj[key];
+}

好像拿到了 T,也不能拿到它的属性和属性值,如果能对类型参数 T 做一些逻辑处理就好了。

所以,就有了第三种类型系统。

3.支持类型编程的类型系统

在 Java 里面,拿到了对象的类型就能找到它的类,进一步拿到各种信息,所以类型系统支持泛型就足够了。

但是在 JavaScript 里面,对象可以字面量的方式创建,还可以灵活的增删属性,拿到对象并不能确定什么,所以要支持对传入的类型参数做进一步的处理。

对传入的类型参数(泛型)做各种逻辑运算,产生新的类型,这就是类型编程。

比如上面那个 getProps 的函数,类型可以这样写:

ts
function getPropValue<T extends object, Key extends keyof T>(obj: T, key: Key): T[Key] {
+  return obj[key];
+}

这里的 keyof T、T[Key] 就是对类型参数 T 的类型运算。

TypeScript 的类型系统就是第三种,支持对类型参数做各种逻辑处理,可以写很复杂的类型逻辑。

类型逻辑可以多复杂?

类型逻辑是对类型参数的各种处理,可以实现很多强大的功能:

比如这个 ParseQueryString 的类型:

ts
type res = ParseQueryString<'a=1&b=2&c=3'>;

它可以对传入的字符串的类型参数做解析,返回解析以后的结果。等于

ts
type res = {
+  a: '1';
+  b: '2';
+  c: '3';
+};

如果是 Java 的只支持泛型的类型系统可以做到么?明显不能。但是 TypeScript 的类型系统就可以,因为它可以对泛型(类型参数)做各种逻辑处理。

只不过,这个类型的类型逻辑的代码比较多(下面的 ts 类型暂时看不懂没关系,在顺口溜那节会有详解,这里只是用来直观感受下类型编程的复杂度的,等学完以后大家也能实现这样的复杂高级类型的):

ts
type ParseParam<Param extends string> = Param extends \`\${infer Key}=\${infer Value}\`
+  ? {
+      [K in Key]: Value;
+    }
+  : {};
+
+type MergeValues<One, Other> = One extends Other ? One : Other extends unknown[] ? [One, ...Other] : [One, Other];
+
+type MergeParams<OneParam extends Record<string, any>, OtherParam extends Record<string, any>> = {
+  [Key in keyof OneParam | keyof OtherParam]: Key extends keyof OneParam
+    ? Key extends keyof OtherParam
+      ? MergeValues<OneParam[Key], OtherParam[Key]>
+      : OneParam[Key]
+    : Key extends keyof OtherParam
+      ? OtherParam[Key]
+      : never;
+};
+type ParseQueryString<Str extends string> = Str extends \`\${infer Param}&\${infer Rest}\`
+  ? MergeParams<ParseParam<Param>, ParseQueryString<Rest>>
+  : ParseParam<Str>;

TypeScript 的类型系统是图灵完备的,也就是能描述各种可计算逻辑。简单点来理解就是循环、条件等各种 JS 里面有的语法它都有,JS 能写的逻辑它都能写。

对类型参数的编程是 TypeScript 类型系统最强大的部分,可以实现各种复杂的类型计算逻辑,是它的优点。但同时也被认为是它的缺点,因为除了业务逻辑外还要写很多类型逻辑。

不过,我倒是觉得这种复杂度是不可避免的,因为 JS 本身足够灵活,要准确定义类型那类型系统必然也要设计的足够灵活。

4.类型安全和型变

TypeScript 给 JavaScript 添加了一套静态类型系统,是为了保证类型安全的,也就是保证变量只能赋同类型的值,对象只能访问它有的属性、方法。

比如 number 类型的值不能赋值给 boolean 类型的变量,Date 类型的对象就不能调用 exec 方法。

这是类型检查做的事情,遇到类型安全问题会在编译时报错。

但是这种类型安全的限制也不能太死板,有的时候需要一些变通,比如子类型是可以赋值给父类型的变量的,可以完全当成父类型来使用,也就是“型变(variant)”(类型改变)。

这种“型变”分为两种,一种是子类型可以赋值给父类型,叫做协变(covariant),一种是父类型可以赋值给子类型,叫做逆变(contravariant)。

先来看下协变:

协变(covariant)

对具体成员的输出参数进行一次类型转换,且类型转换的准则是 “里氏替换原则”。

其中协变是很好理解的,比如我们有两个 interface:

ts
interface Animal {
+  name: string;
+  age: number;
+}
+
+interface Cat {
+  name: string;
+  age: number;
+  hobbies: string[];
+}

这里 Cat 是 Animal 的子类型,更具体,那么 Cat 类型的变量就可以赋值给 Animal 类型:

ts
let animal: Animal = {
+  name: 'cat',
+  age: 3,
+};
+
+let cat: Cat = {
+  name: 'Tony',
+  age: 5,
+  hobbies: ['run', 'swim'],
+};
+
+animal = cat;

这并不会报错,虽然这俩类型不一样,但是依然是类型安全的。

这种子类型可以赋值给父类型的情况就叫做协变。

为什么要支持协变很容易理解:类型系统支持了父子类型,那如果子类型还不能赋值给父类型,还叫父子类型么?

所以型变是实现类型父子关系必须的,它在保证类型安全的基础上,增加了类型系统的灵活性。

逆变相对难理解一些:

逆变(contravariant)

是对具体成员的输入参数进行一次类型转换,且类型转换的准则是"里氏替换原则"。

我们有这样两个函数:

ts
let printHobbies: (cat: Cat) => void;
+
+printHobbies = (cat) => {
+  console.log(cat.hobbies);
+};
+
+let printName: (animal: Animal) => void;
+
+printName = (animal) => {
+  console.log(animal.name);
+};

printHobbies 的参数 Guang 是 printName 参数 Person 的子类型。

那么问题来了,printName 能赋值给 printHobbies 么?printHobbies 能赋值给 printName 么?

测试一下发现是这样的:

ts
let printHobbies: (cat: Cat) => void;
+
+printHobbies = (cat) => {
+  console.log(cat.hobbies);
+};
+
+let printName: (animal: Animal) => void;
+
+printName = (animal) => {
+  console.log(animal.name);
+};
+
+printHobbies = printName;

printName 的参数 Person 不是 printHobbies 的参数 Guang 的父类型么,为啥能赋值给子类型?

因为这个函数调用的时候是按照 Guang 来约束的类型,但实际上函数只用到了父类型 Person 的属性和方法,当然不会有问题,依然是类型安全的。

这就是逆变,函数的参数有逆变的性质(而返回值是协变的,也就是子类型可以赋值给父类型)。

那反过来呢,如果 printHoobies 赋值给 printName 会发生什么?

因为函数声明的时候是按照 Person 来约束类型,但是调用的时候是按照 Guang 的类型来访问的属性和方法,那自然类型不安全了,所以就会报错。

但是在 ts2.x 之前支持这种赋值,也就是父类型可以赋值给子类型,子类型可以赋值给父类型,既逆变又协变,叫做“双向协变”。

但是这明显是有问题的,不能保证类型安全,所以之后 ts 加了一个编译选项 strictFunctionTypes,设置为 true 就只支持函数参数的逆变,设置为 false 则是双向协变。

我们把 strictFunctionTypes 关掉之后,就会发现两种赋值都可以了。

这样就支持函数参数的双向协变,类型检查不会报错,但不能严格保证类型安全。

开启之后,函数参数就只支持逆变,子类型赋值给父类型就会报错。

再举个逆变的例子,大家觉得下面这样的 ts 代码会报错么:

ts
type Func = (a: string) => void;
+
+const func: Func = (a: 'hello') => undefined;

答案是参数的位置会,返回值的位置不会:

参数的位置是逆变的,也就是被赋值的函数参数要是赋值的函数参数的子类型,而 string 不是 'hello' 的子类型,所以报错了。

返回值的位置是协变的,也就是赋值的函数的返回值是被赋值的函数的返回值的子类型,这里 undefined 是 void 的子类型,所以不报错。

不变(invariant)

逆变和协变都是型变,是针对父子类型而言的,非父子类型自然就不会型变,也就是不变:

非父子类型之间不会发生型变,只要类型不一样就会报错

那类型之间的父子关系是怎么确定的呢,好像也没有看到 extends 的继承?

像 java 里面的类型都是通过 extends 继承的,如果 A extends B,那 A 就是 B 的子类型。这种叫做名义类型系统(nominal type)。

而 ts 里不看这个,只要结构上是一致的,那么就可以确定父子关系,这种叫做结构类型系统(structual type)。

通过结构,更具体的那个是子类型。这里的 Cat 有 Animal 的所有属性,并且还多了一些属性,所以 Cat 是 Animal 的子类型。

注意,这里用的是更具体,而不是更多。

判断联合类型父子关系的时候, 'a' | 'b' 和 'a' | 'b' | 'c' 哪个更具体?

'a' | 'b' 更具体,所以 'a' | 'b' 是 'a' | 'b' | 'c' 的子类型。

三.TypeScript 类型系统

1.支持的类型

静态类型系统的目的是把类型检查从运行时提前到编译时,那 TS 类型系统中肯定要把 JS 的运行时类型拿过来,也就是 number、boolean、string、object、bigint、symbol、undefined、null 这些类型,还有就是它们的包装类型 Number、Boolean、String、Object、Symbol。

这些很容易理解,给 JS 添加静态类型,总没有必要重新造一套基础类型吧,直接复用 JS 的基础类型就行。

复合类型方面,JS 有 class、Array,这些 TypeScript 类型系统也都支持,但是又多加了三种类型:元组(Tuple)、接口(Interface)、枚举(Enum)。

元组

元组(Tuple)就是元素个数和类型固定的数组类型:

ts
type Tuple = [number, string];

接口

接口(Interface)可以描述函数、对象、构造器的结构:

对象:

ts
interface IPerson {
+  name: string;
+  age: number;
+}
+
+class Person implements IPerson {
+  name: string;
+  age: number;
+}
+
+const obj: IPerson = {
+  name: 'guang',
+  age: 18,
+};

函数:

ts
interface SayHello {
+  (name: string): string;
+}
+
+const func: SayHello = (name: string) => {
+  return 'hello,' + name;
+};

构造器:

ts
interface PersonConstructor {
+  new (name: string, age: number): IPerson;
+}
+
+function createPerson(ctor: PersonConstructor): IPerson {
+  return new ctor('guang', 18);
+}

对象类型、class 类型在 TypeScript 里也叫做索引类型,也就是索引了多个元素的类型的意思。对象可以动态添加属性,如果不知道会有什么属性,可以用可索引签名:

ts
interface IPerson {
+  [prop: string]: string | number;
+}
+const obj: IPerson = {};
+obj.name = 'guang';
+obj.age = 18;

总之,接口可以用来描述函数、构造器、索引类型(对象、class、数组)等复合类型。

枚举

枚举(Enum)是一系列值的复合:

ts
enum Transpiler {
+  Babel = 'babel',
+  Postcss = 'postcss',
+  Terser = 'terser',
+  Prettier = 'prettier',
+  TypeScriptCompiler = 'tsc',
+}
+
+const transpiler = Transpiler.TypeScriptCompiler;

此外,TypeScript 还支持字面量类型,也就是类似 1111、'aaaa'、{ a: 1} 这种值也可以做为类型。

其中,字符串的字面量类型有两种,一种是普通的字符串字面量,比如 'aaa',另一种是模版字面量,比如 aaa\${string},它的意思是以 aaa 开头,后面是任意 string 的字符串字面量类型。

所以想要约束以某个字符串开头的字符串字面量类型时可以这样写:

ts
function func(str: \`#\${string}\`) {}
+
+func('aaaa'); // error
+
+func('#aaaa'); // true

还有四种特殊的类型:void、never、any、unknown:

  • never 代表不可达,比如函数抛异常的时候,返回值就是 never。
  • void 代表空,可以是 undefined 或 never。
  • any 是任意类型,任何类型都可以赋值给它,它也可以赋值给任何类型(除了 never)。
  • unknown 是未知类型,任何类型都可以赋值给它,但是它不可以赋值给别的类型。

这些就是 TypeScript 类型系统中的全部类型了,大部分是从 JS 中迁移过来的,比如基础类型、Array、class 等,也添加了一些类型,比如 枚举(enum)、接口(interface)、元组等,还支持了字面量类型和 void、never、any、unknown 的特殊类型。

2.类型的装饰

除了描述类型的结构外,TypeScript 的类型系统还支持描述类型的属性,比如是否可选,是否只读等:

ts
interface IPerson {
+  readonly name: string;
+  age?: number;
+}
+
+type tuple = [string, number?];

3.类型运算

我们知道了 TypeScript 类型系统里有哪些类型,那么可以对这些类型做什么类型运算呢?

条件:extends ?

TypeScript 里的条件判断是 extends ? :,叫做条件类型(Conditional Type)比如:

ts
type res = 1 extends 2 ? true : false; // type res = false

这就是 TypeScript 类型系统里的 if else。

但是,上面这样的逻辑没啥意义,静态的值自己就能算出结果来,为什么要用代码去判断呢?

所以,类型运算逻辑都是用来做一些动态的类型的运算的,也就是对类型参数的运算。

ts
type isTwo<T> = T extends 2 ? true : false;
+
+type res = isTwo<1>; // type res = false
+type res2 = isTwo<2>; // type res = true

这种类型也叫做高级类型。

高级类型的特点是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

推导:infer

如何提取类型的一部分呢?答案是 infer。

比如提取元组类型的第一个元素:

ts
type First<Tuple extends unknown[]> = Tuple extends [infer T, ...infer R] ? T : never;
+
+type res = First<[1, 2, 3]>; // type res = 1

注意,第一个 extends 不是条件,条件类型是 extends ? :,这里的 extends 是约束的意思,也就是约束类型参数只能是数组类型。

因为不知道数组元素的具体类型,所以用 unknown。

infer 在后面的章节会大量用到,这里先简单了解即可。

联合:|

联合类型(Union)类似 js 里的或运算符 |,但是作用于类型,代表类型可以是几个类型之一。

ts
type Union = 1 | 2 | 3;

交叉:&

交叉类型(Intersection)类似 js 中的与运算符 &,但是作用于类型,代表对类型做合并。

ts
type ObjType = { a: number } & { c: boolean };

注意,同一类型可以合并,不同的类型没法合并,会被舍弃:

可以合并的

ts
type ObjType = { a: number } & { c: boolean };
+
+type res = { a: number; c: boolean } extends ObjType ? true : false; // type res = true

不可合并

ts
type res = 'aaaa' & 2222; // type res = never

映射类型

对象、class 在 TypeScript 对应的类型是索引类型(Index Type),那么如何对索引类型作修改呢?

答案是映射类型。

ts
type MapType<T> = {
+  [Key in keyof T]?: T[Key];
+};

keyof T 是查询索引类型中所有的索引,叫做索引查询。

T[Key] 是取索引类型某个索引的值,叫做索引访问。

in 是用于遍历联合类型的运算符。

比如我们把一个索引类型的值变成 3 个元素的数组:

ts
type MapType<T> = {
+  [Key in keyof T]: [T[Key], T[Key], T[Key]];
+};
+
+type res = MapType<{ a: 1; b: 2 }>; // type res = { a: [1, 1, 1]; b:[2, 2, 2]; }

映射类型就相当于把一个集合映射到另一个集合,这是它名字的由来。

除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。

我们用 as 把索引也做了修改,改成了 3 个 key 重复:

ts
type MapType<T> = {
+  [Key in keyof T as \`\${Key & string}\${Key & string}\${Key & string}\`]: [T[Key], T[Key], T[Key]];
+};
+
+// type res = { aaa: [1, 1, 1]; bbb: [2, 2, 2]; }

这里的 & string 可能大家会迷惑,解释一下:

因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是 string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型会把同一类型做合并,不同类型舍弃。

四.判断类型的类型

IsAny

如何判断一个类型是 any 类型呢?要根据它的特性来:

any 类型与任何类型的交叉都是 any,也就是 1 & any 结果是 any。

所以,可以这样写:

ts
type IsAny<T> = 'null' extends 'undefined' & T ? true : false;

IsEqual

之前我们实现 IsEqual 是这样写的:

ts
type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

问题出在 any 的判断上:

ts
type IsEqualResult = IsEqual<'aaa', any>;
+// type IsEqualResult = false

因为 any 可以是任何类型,任何类型也都是 any,所以当这样写判断不出 any 类型来。

所以,我们会这样写:

ts
type IsEqual<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;

这样就能正常判断了:

其中 T 是不传类型的,相当于一个临时变量

其目的是对比:

ts
<T>() => T extends X ? 1 : 2
+<T>() => T extends Y ? 1 : 2

这两个泛型函数类型是否相等,原理

IsUnion

还记得怎么判断 union 类型么?要根据它遇到条件类型时会分散成单个传入做计算的特性:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

IsNever

never 在条件类型中也比较特殊,如果条件类型左边是类型参数,并且传入的是 never,那么直接返回 never:

ts
type TestNever<T> = T extends number ? 1 : 2;

当 T 为 never 时:

ts
type TestNeverResult = TestNever<never>;
+// type TestNeverResult = never

所以,要判断 never 类型,就不能直接 T extends number,可以这样写:

ts
type IsNever<T> = [T] extends [never] ? true : false;

这样就能正常判断 never 类型了:

ts
type TestNeverResult = IsNever<never>;
+// type TestNeverResult = true

除此以外,any 在条件类型中也比较特殊,如果类型参数为 any,会直接返回 trueType 和 falseType 的合并:

ts
type TestAny<T> = T extends number ? 1 : 2;
+
+type TestAnyResult = TestAny<any>;
+// type TestAnyResult = 1 | 2

联合类型、never、any 在作为条件类型的类型参数时的这些特殊情况,也会在后面的原理篇来解释原因。

IsTuple

元组类型怎么判断呢?它和数组有什么区别呢?

元组类型的 length 是数字字面量,而数组的 length 是 number。

ts
type len

UnionToIntersection

类型之间是有父子关系的,更具体的那个是子类型,比如 A 和 B 的交叉类型 A & B 就是联合类型 A | B 的子类型,因为更具体。

如果允许父类型赋值给子类型,就叫做逆变

如果允许子类型赋值给父类型,就叫做协变

(关于逆变、协变等概念的详细解释可以看原理篇)

在 TypeScript 中有函数参数是有逆变的性质的,也就是如果参数可能是多个类型,参数类型会变成它们的交叉类型。

所以联合转交叉可以这样实现 :

ts
type UnionToIntersection<U> = (U extends U ? (x: U) => unknown : never) extends (x: infer R) => unknown ? R : never;

类型参数 U 是要转换的联合类型。

U extends U 是为了触发联合类型的 distributive 的性质,让每个类型单独传入做计算,最后合并。

利用 U 做为参数构造个函数,通过模式匹配取参数的类型。

结果就是交叉类型

函数参数的逆变性质一般就联合类型转交叉类型会用,记住就行。

GetOptional

如何提取索引类型中的可选索引呢?

这也要利用可选索引的特性:可选索引的值为 undefined 和值类型的联合类型。

过滤可选索引,就要构造一个新的索引类型,过程中做过滤:

ts
type GetOptional<Obj extends Record<string, any>> = {
+  [Key in keyof Obj as {} extends Pick<Obj, Key> ? Key : never]: Obj[Key];
+};

类型参数 Obj 为待处理的索引类型,类型约束为索引为 string、值为任意类型的索引类型 Record<string, any>。

用映射类型的语法重新构造索引类型,索引是之前的索引也就是 Key in keyof Obj,但要做一些过滤,也就是 as 之后的部分。

过滤的方式就是单独取出该索引之后,判断空对象是否是其子类型。

这里的 Pick 是 ts 提供的内置高级类型,就是取出某个 Key 构造新的索引类型:

ts
type Pick<T, K extends keyof T> = { [P in K]: T[P] };

比如单独取出 age 构造的新的索引类型是这样的:

可选的意思是这个索引可能没有,没有的时候,那 Pick<Obj, Key> 就是空的,所以 {} extends Pick<Obj, Key> 就能过滤出可选索引。

值的类型依然是之前的,也就是 Obj[Key]。

这样,就能过滤出所有可选索引,构造成新的索引类型:

总结

  • any 类型与任何类型的交叉都是 any,也就是 1 & any 结果是 any,可以用这个特性判断 any 类型。
  • 联合类型作为类型参数出现在条件类型左侧时,会分散成单个类型传入,最后合并。
  • never 作为类型参数出现在条件类型左侧时,会直接返回 never。
  • any 作为类型参数出现在条件类型左侧时,会直接返回 trueType 和 falseType 的联合类型。
  • 元组类型也是数组类型,但 length 是数字字面量,而数组的 length 是 number。可以用来判断元组类型。
  • 函数参数处会发生逆变,可以用来实现联合类型转交叉类型。
  • 可选索引的索引可能没有,那 Pick 出来的就可能是 {},可以用来过滤可选索引,反过来也可以过滤非可选索引。
  • 索引类型的索引为字符串字面量类型,而可索引签名不是,可以用这个特性过滤掉可索引签名。
  • keyof 只能拿到 class 的 public 的索引,可以用来过滤出 public 的属性。
  • 默认推导出来的不是字面量类型,加上 as const 可以推导出字面量类型,但带有 readonly 修饰,这样模式匹配的时候也得加上 readonly 才行。
`,253)]))}const y=i(k,[["render",p]]);export{g as __pageData,y as default}; diff --git a/assets/cn_src_article_typescript_index.md.dV9VtsjJ.lean.js b/assets/cn_src_article_typescript_index.md.dV9VtsjJ.lean.js new file mode 100644 index 0000000000..a93efc6a2a --- /dev/null +++ b/assets/cn_src_article_typescript_index.md.dV9VtsjJ.lean.js @@ -0,0 +1,156 @@ +import{_ as i,o as a,c as h,a3 as n}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"TypeScript 的类型系统","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/typescript/index.md","filePath":"cn/src/article/typescript/index.md","lastUpdated":1726550590000}'),k={name:"cn/src/article/typescript/index.md"};function p(t,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

TypeScript 的类型系统

一.类型是什么

类型具体点来说就是指 number、boolean、string 等基础类型和 Object、Function 等复合类型,它们是编程语言提供的对不同内容的抽象:

  • 不同类型变量占据的内存大小不同: boolean 类型的变量会分配 4 个字节的内存,而 number 类型的变量则会分配 8 个字节的内存,给变量声明了不同的类型就代表了会占据不同的内存空间。

  • 不同类型变量可做的操作不同: number 类型可以做加减乘除等运算,boolean 就不可以,复合类型中不同类型的对象可用的方法不同,比如 Date 和 RegExp,变量的类型不同代表可以对该变量做的操作就不同。

有了类型,那我们的操作必须和类型相匹配,否则就会报错,这就是类型检查。

如果能保证对某种类型只做该类型允许的操作,这就叫做类型安全。

类型检查可以在运行时做,也可以运行之前的编译期做。这是两种不同的类型,前者叫做动态类型检查,后者叫做静态类型检查。

两种类型检查各有优缺点。动态类型检查 在源码中不保留类型信息,对某个变量赋什么值、做什么操作都是允许的,写代码很灵活。但这也埋下了类型不安全的隐患,比如对 string 做了乘除,对 Date 对象调用了 exec 方法,这些都是运行时才能检查出来的错误。

其中,最常见的错误应该是 “null is not an object”、“undefined is not a function” 之类的了,写代码时没发现类型不匹配,到了运行的时候才发现,就会有很多这种报错。

所以,动态类型虽然代码写起来简单,但代码中很容易藏着一些类型不匹配的隐患。

静态类型检查则是在源码中保留类型信息,声明变量要指定类型,对变量做的操作要和类型匹配,会有专门的编译器在编译期间做检查。

静态类型给写代码增加了一些难度,因为你除了要考虑代码要表达的逻辑之外,还要考虑类型逻辑:变量是什么类型的、是不是匹配、要不要做类型转换等。

不过,静态类型也消除了类型不安全的隐患,因为在编译期间就做了类型检查,就不会出现对 string 做了乘除,调用了 Date 的 exec 方法这类问题。

所以,静态类型虽然代码写起来要考虑的问题多一些,会复杂一些,但是却消除了代码中潜藏类型不安全问题的可能。

知道了动态类型检查和静态类型检查的区别,我们自然可以得出这样的结论:

动态类型只适合简单的场景,对于大项目却不太合适,因为代码中可能藏着的隐患太多了,万一线上报一个类型不匹配的错误,那可能就是大问题。

而静态类型虽然会增加写代码的成本,但是却能更好的保证代码的健壮性,减少 Bug 率。

所以,大型项目注定会用静态类型语言开发。

二.类型系统的分类

1.简单的类型系统

变量、函数、类等都可以声明类型,编译器会基于声明的类型做类型检查,类型不匹配时会报错。

这是最基础的类型系统,能保证类型安全,但有些死板。

比如一个 add 函数既可以做整数加法、又可以做浮点数加法,却需要声明两个函数:

c
int add(int a, int b) {
+    return a + b;
+}
+
+double add(double a, double b) {
+    return a + b;
+}

这个问题的解决思路很容易想到:如果类型能传参数就好了,传入 int 就是整数加法,传入 double 就是浮点数加法。

所以,就有了第二种类型系统。

2.支持泛型的类型系统

泛型的英文是 Generic Type,通用的类型,它可以代表任何一种类型,也叫做类型参数。

它给类型系统增加了一些灵活性,在整体比较固定,部分变量的类型有变化的情况下,可以减少很多重复代码。

比如上面的 add 函数,有了泛型之后就可以这样写:

java
T add<T>(T a, T b) {
+    return a + b;
+}
+
+add(1,2);
+add(1.111, 2.2222);

声明时把会变化的类型声明成泛型(也就是类型参数),在调用的时候再确定类型。

Java 就是这种类型系统。如果你看过 Java 代码,你会发现泛型用的特别多,这确实是一个很好的增加类型系统灵活性的特性。

但是,这种类型系统的灵活性对于 JavaScript 来说还不够,因为 JavaScript 太过灵活了。

比如,在 Java 里,对象都是由类 new 出来的,你不能凭空创建对象,但是 JavaScript 却可以,它支持对象字面量。

那如果是一个返回对象某个属性值的函数,类型该怎么写呢?

ts
function getPropValue<T>(obj: T, key): key对应的属性值类型 {
+  return obj[key];
+}

好像拿到了 T,也不能拿到它的属性和属性值,如果能对类型参数 T 做一些逻辑处理就好了。

所以,就有了第三种类型系统。

3.支持类型编程的类型系统

在 Java 里面,拿到了对象的类型就能找到它的类,进一步拿到各种信息,所以类型系统支持泛型就足够了。

但是在 JavaScript 里面,对象可以字面量的方式创建,还可以灵活的增删属性,拿到对象并不能确定什么,所以要支持对传入的类型参数做进一步的处理。

对传入的类型参数(泛型)做各种逻辑运算,产生新的类型,这就是类型编程。

比如上面那个 getProps 的函数,类型可以这样写:

ts
function getPropValue<T extends object, Key extends keyof T>(obj: T, key: Key): T[Key] {
+  return obj[key];
+}

这里的 keyof T、T[Key] 就是对类型参数 T 的类型运算。

TypeScript 的类型系统就是第三种,支持对类型参数做各种逻辑处理,可以写很复杂的类型逻辑。

类型逻辑可以多复杂?

类型逻辑是对类型参数的各种处理,可以实现很多强大的功能:

比如这个 ParseQueryString 的类型:

ts
type res = ParseQueryString<'a=1&b=2&c=3'>;

它可以对传入的字符串的类型参数做解析,返回解析以后的结果。等于

ts
type res = {
+  a: '1';
+  b: '2';
+  c: '3';
+};

如果是 Java 的只支持泛型的类型系统可以做到么?明显不能。但是 TypeScript 的类型系统就可以,因为它可以对泛型(类型参数)做各种逻辑处理。

只不过,这个类型的类型逻辑的代码比较多(下面的 ts 类型暂时看不懂没关系,在顺口溜那节会有详解,这里只是用来直观感受下类型编程的复杂度的,等学完以后大家也能实现这样的复杂高级类型的):

ts
type ParseParam<Param extends string> = Param extends \`\${infer Key}=\${infer Value}\`
+  ? {
+      [K in Key]: Value;
+    }
+  : {};
+
+type MergeValues<One, Other> = One extends Other ? One : Other extends unknown[] ? [One, ...Other] : [One, Other];
+
+type MergeParams<OneParam extends Record<string, any>, OtherParam extends Record<string, any>> = {
+  [Key in keyof OneParam | keyof OtherParam]: Key extends keyof OneParam
+    ? Key extends keyof OtherParam
+      ? MergeValues<OneParam[Key], OtherParam[Key]>
+      : OneParam[Key]
+    : Key extends keyof OtherParam
+      ? OtherParam[Key]
+      : never;
+};
+type ParseQueryString<Str extends string> = Str extends \`\${infer Param}&\${infer Rest}\`
+  ? MergeParams<ParseParam<Param>, ParseQueryString<Rest>>
+  : ParseParam<Str>;

TypeScript 的类型系统是图灵完备的,也就是能描述各种可计算逻辑。简单点来理解就是循环、条件等各种 JS 里面有的语法它都有,JS 能写的逻辑它都能写。

对类型参数的编程是 TypeScript 类型系统最强大的部分,可以实现各种复杂的类型计算逻辑,是它的优点。但同时也被认为是它的缺点,因为除了业务逻辑外还要写很多类型逻辑。

不过,我倒是觉得这种复杂度是不可避免的,因为 JS 本身足够灵活,要准确定义类型那类型系统必然也要设计的足够灵活。

4.类型安全和型变

TypeScript 给 JavaScript 添加了一套静态类型系统,是为了保证类型安全的,也就是保证变量只能赋同类型的值,对象只能访问它有的属性、方法。

比如 number 类型的值不能赋值给 boolean 类型的变量,Date 类型的对象就不能调用 exec 方法。

这是类型检查做的事情,遇到类型安全问题会在编译时报错。

但是这种类型安全的限制也不能太死板,有的时候需要一些变通,比如子类型是可以赋值给父类型的变量的,可以完全当成父类型来使用,也就是“型变(variant)”(类型改变)。

这种“型变”分为两种,一种是子类型可以赋值给父类型,叫做协变(covariant),一种是父类型可以赋值给子类型,叫做逆变(contravariant)。

先来看下协变:

协变(covariant)

对具体成员的输出参数进行一次类型转换,且类型转换的准则是 “里氏替换原则”。

其中协变是很好理解的,比如我们有两个 interface:

ts
interface Animal {
+  name: string;
+  age: number;
+}
+
+interface Cat {
+  name: string;
+  age: number;
+  hobbies: string[];
+}

这里 Cat 是 Animal 的子类型,更具体,那么 Cat 类型的变量就可以赋值给 Animal 类型:

ts
let animal: Animal = {
+  name: 'cat',
+  age: 3,
+};
+
+let cat: Cat = {
+  name: 'Tony',
+  age: 5,
+  hobbies: ['run', 'swim'],
+};
+
+animal = cat;

这并不会报错,虽然这俩类型不一样,但是依然是类型安全的。

这种子类型可以赋值给父类型的情况就叫做协变。

为什么要支持协变很容易理解:类型系统支持了父子类型,那如果子类型还不能赋值给父类型,还叫父子类型么?

所以型变是实现类型父子关系必须的,它在保证类型安全的基础上,增加了类型系统的灵活性。

逆变相对难理解一些:

逆变(contravariant)

是对具体成员的输入参数进行一次类型转换,且类型转换的准则是"里氏替换原则"。

我们有这样两个函数:

ts
let printHobbies: (cat: Cat) => void;
+
+printHobbies = (cat) => {
+  console.log(cat.hobbies);
+};
+
+let printName: (animal: Animal) => void;
+
+printName = (animal) => {
+  console.log(animal.name);
+};

printHobbies 的参数 Guang 是 printName 参数 Person 的子类型。

那么问题来了,printName 能赋值给 printHobbies 么?printHobbies 能赋值给 printName 么?

测试一下发现是这样的:

ts
let printHobbies: (cat: Cat) => void;
+
+printHobbies = (cat) => {
+  console.log(cat.hobbies);
+};
+
+let printName: (animal: Animal) => void;
+
+printName = (animal) => {
+  console.log(animal.name);
+};
+
+printHobbies = printName;

printName 的参数 Person 不是 printHobbies 的参数 Guang 的父类型么,为啥能赋值给子类型?

因为这个函数调用的时候是按照 Guang 来约束的类型,但实际上函数只用到了父类型 Person 的属性和方法,当然不会有问题,依然是类型安全的。

这就是逆变,函数的参数有逆变的性质(而返回值是协变的,也就是子类型可以赋值给父类型)。

那反过来呢,如果 printHoobies 赋值给 printName 会发生什么?

因为函数声明的时候是按照 Person 来约束类型,但是调用的时候是按照 Guang 的类型来访问的属性和方法,那自然类型不安全了,所以就会报错。

但是在 ts2.x 之前支持这种赋值,也就是父类型可以赋值给子类型,子类型可以赋值给父类型,既逆变又协变,叫做“双向协变”。

但是这明显是有问题的,不能保证类型安全,所以之后 ts 加了一个编译选项 strictFunctionTypes,设置为 true 就只支持函数参数的逆变,设置为 false 则是双向协变。

我们把 strictFunctionTypes 关掉之后,就会发现两种赋值都可以了。

这样就支持函数参数的双向协变,类型检查不会报错,但不能严格保证类型安全。

开启之后,函数参数就只支持逆变,子类型赋值给父类型就会报错。

再举个逆变的例子,大家觉得下面这样的 ts 代码会报错么:

ts
type Func = (a: string) => void;
+
+const func: Func = (a: 'hello') => undefined;

答案是参数的位置会,返回值的位置不会:

参数的位置是逆变的,也就是被赋值的函数参数要是赋值的函数参数的子类型,而 string 不是 'hello' 的子类型,所以报错了。

返回值的位置是协变的,也就是赋值的函数的返回值是被赋值的函数的返回值的子类型,这里 undefined 是 void 的子类型,所以不报错。

不变(invariant)

逆变和协变都是型变,是针对父子类型而言的,非父子类型自然就不会型变,也就是不变:

非父子类型之间不会发生型变,只要类型不一样就会报错

那类型之间的父子关系是怎么确定的呢,好像也没有看到 extends 的继承?

像 java 里面的类型都是通过 extends 继承的,如果 A extends B,那 A 就是 B 的子类型。这种叫做名义类型系统(nominal type)。

而 ts 里不看这个,只要结构上是一致的,那么就可以确定父子关系,这种叫做结构类型系统(structual type)。

通过结构,更具体的那个是子类型。这里的 Cat 有 Animal 的所有属性,并且还多了一些属性,所以 Cat 是 Animal 的子类型。

注意,这里用的是更具体,而不是更多。

判断联合类型父子关系的时候, 'a' | 'b' 和 'a' | 'b' | 'c' 哪个更具体?

'a' | 'b' 更具体,所以 'a' | 'b' 是 'a' | 'b' | 'c' 的子类型。

三.TypeScript 类型系统

1.支持的类型

静态类型系统的目的是把类型检查从运行时提前到编译时,那 TS 类型系统中肯定要把 JS 的运行时类型拿过来,也就是 number、boolean、string、object、bigint、symbol、undefined、null 这些类型,还有就是它们的包装类型 Number、Boolean、String、Object、Symbol。

这些很容易理解,给 JS 添加静态类型,总没有必要重新造一套基础类型吧,直接复用 JS 的基础类型就行。

复合类型方面,JS 有 class、Array,这些 TypeScript 类型系统也都支持,但是又多加了三种类型:元组(Tuple)、接口(Interface)、枚举(Enum)。

元组

元组(Tuple)就是元素个数和类型固定的数组类型:

ts
type Tuple = [number, string];

接口

接口(Interface)可以描述函数、对象、构造器的结构:

对象:

ts
interface IPerson {
+  name: string;
+  age: number;
+}
+
+class Person implements IPerson {
+  name: string;
+  age: number;
+}
+
+const obj: IPerson = {
+  name: 'guang',
+  age: 18,
+};

函数:

ts
interface SayHello {
+  (name: string): string;
+}
+
+const func: SayHello = (name: string) => {
+  return 'hello,' + name;
+};

构造器:

ts
interface PersonConstructor {
+  new (name: string, age: number): IPerson;
+}
+
+function createPerson(ctor: PersonConstructor): IPerson {
+  return new ctor('guang', 18);
+}

对象类型、class 类型在 TypeScript 里也叫做索引类型,也就是索引了多个元素的类型的意思。对象可以动态添加属性,如果不知道会有什么属性,可以用可索引签名:

ts
interface IPerson {
+  [prop: string]: string | number;
+}
+const obj: IPerson = {};
+obj.name = 'guang';
+obj.age = 18;

总之,接口可以用来描述函数、构造器、索引类型(对象、class、数组)等复合类型。

枚举

枚举(Enum)是一系列值的复合:

ts
enum Transpiler {
+  Babel = 'babel',
+  Postcss = 'postcss',
+  Terser = 'terser',
+  Prettier = 'prettier',
+  TypeScriptCompiler = 'tsc',
+}
+
+const transpiler = Transpiler.TypeScriptCompiler;

此外,TypeScript 还支持字面量类型,也就是类似 1111、'aaaa'、{ a: 1} 这种值也可以做为类型。

其中,字符串的字面量类型有两种,一种是普通的字符串字面量,比如 'aaa',另一种是模版字面量,比如 aaa\${string},它的意思是以 aaa 开头,后面是任意 string 的字符串字面量类型。

所以想要约束以某个字符串开头的字符串字面量类型时可以这样写:

ts
function func(str: \`#\${string}\`) {}
+
+func('aaaa'); // error
+
+func('#aaaa'); // true

还有四种特殊的类型:void、never、any、unknown:

  • never 代表不可达,比如函数抛异常的时候,返回值就是 never。
  • void 代表空,可以是 undefined 或 never。
  • any 是任意类型,任何类型都可以赋值给它,它也可以赋值给任何类型(除了 never)。
  • unknown 是未知类型,任何类型都可以赋值给它,但是它不可以赋值给别的类型。

这些就是 TypeScript 类型系统中的全部类型了,大部分是从 JS 中迁移过来的,比如基础类型、Array、class 等,也添加了一些类型,比如 枚举(enum)、接口(interface)、元组等,还支持了字面量类型和 void、never、any、unknown 的特殊类型。

2.类型的装饰

除了描述类型的结构外,TypeScript 的类型系统还支持描述类型的属性,比如是否可选,是否只读等:

ts
interface IPerson {
+  readonly name: string;
+  age?: number;
+}
+
+type tuple = [string, number?];

3.类型运算

我们知道了 TypeScript 类型系统里有哪些类型,那么可以对这些类型做什么类型运算呢?

条件:extends ?

TypeScript 里的条件判断是 extends ? :,叫做条件类型(Conditional Type)比如:

ts
type res = 1 extends 2 ? true : false; // type res = false

这就是 TypeScript 类型系统里的 if else。

但是,上面这样的逻辑没啥意义,静态的值自己就能算出结果来,为什么要用代码去判断呢?

所以,类型运算逻辑都是用来做一些动态的类型的运算的,也就是对类型参数的运算。

ts
type isTwo<T> = T extends 2 ? true : false;
+
+type res = isTwo<1>; // type res = false
+type res2 = isTwo<2>; // type res = true

这种类型也叫做高级类型。

高级类型的特点是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

推导:infer

如何提取类型的一部分呢?答案是 infer。

比如提取元组类型的第一个元素:

ts
type First<Tuple extends unknown[]> = Tuple extends [infer T, ...infer R] ? T : never;
+
+type res = First<[1, 2, 3]>; // type res = 1

注意,第一个 extends 不是条件,条件类型是 extends ? :,这里的 extends 是约束的意思,也就是约束类型参数只能是数组类型。

因为不知道数组元素的具体类型,所以用 unknown。

infer 在后面的章节会大量用到,这里先简单了解即可。

联合:|

联合类型(Union)类似 js 里的或运算符 |,但是作用于类型,代表类型可以是几个类型之一。

ts
type Union = 1 | 2 | 3;

交叉:&

交叉类型(Intersection)类似 js 中的与运算符 &,但是作用于类型,代表对类型做合并。

ts
type ObjType = { a: number } & { c: boolean };

注意,同一类型可以合并,不同的类型没法合并,会被舍弃:

可以合并的

ts
type ObjType = { a: number } & { c: boolean };
+
+type res = { a: number; c: boolean } extends ObjType ? true : false; // type res = true

不可合并

ts
type res = 'aaaa' & 2222; // type res = never

映射类型

对象、class 在 TypeScript 对应的类型是索引类型(Index Type),那么如何对索引类型作修改呢?

答案是映射类型。

ts
type MapType<T> = {
+  [Key in keyof T]?: T[Key];
+};

keyof T 是查询索引类型中所有的索引,叫做索引查询。

T[Key] 是取索引类型某个索引的值,叫做索引访问。

in 是用于遍历联合类型的运算符。

比如我们把一个索引类型的值变成 3 个元素的数组:

ts
type MapType<T> = {
+  [Key in keyof T]: [T[Key], T[Key], T[Key]];
+};
+
+type res = MapType<{ a: 1; b: 2 }>; // type res = { a: [1, 1, 1]; b:[2, 2, 2]; }

映射类型就相当于把一个集合映射到另一个集合,这是它名字的由来。

除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。

我们用 as 把索引也做了修改,改成了 3 个 key 重复:

ts
type MapType<T> = {
+  [Key in keyof T as \`\${Key & string}\${Key & string}\${Key & string}\`]: [T[Key], T[Key], T[Key]];
+};
+
+// type res = { aaa: [1, 1, 1]; bbb: [2, 2, 2]; }

这里的 & string 可能大家会迷惑,解释一下:

因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是 string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型会把同一类型做合并,不同类型舍弃。

四.判断类型的类型

IsAny

如何判断一个类型是 any 类型呢?要根据它的特性来:

any 类型与任何类型的交叉都是 any,也就是 1 & any 结果是 any。

所以,可以这样写:

ts
type IsAny<T> = 'null' extends 'undefined' & T ? true : false;

IsEqual

之前我们实现 IsEqual 是这样写的:

ts
type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

问题出在 any 的判断上:

ts
type IsEqualResult = IsEqual<'aaa', any>;
+// type IsEqualResult = false

因为 any 可以是任何类型,任何类型也都是 any,所以当这样写判断不出 any 类型来。

所以,我们会这样写:

ts
type IsEqual<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;

这样就能正常判断了:

其中 T 是不传类型的,相当于一个临时变量

其目的是对比:

ts
<T>() => T extends X ? 1 : 2
+<T>() => T extends Y ? 1 : 2

这两个泛型函数类型是否相等,原理

IsUnion

还记得怎么判断 union 类型么?要根据它遇到条件类型时会分散成单个传入做计算的特性:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

IsNever

never 在条件类型中也比较特殊,如果条件类型左边是类型参数,并且传入的是 never,那么直接返回 never:

ts
type TestNever<T> = T extends number ? 1 : 2;

当 T 为 never 时:

ts
type TestNeverResult = TestNever<never>;
+// type TestNeverResult = never

所以,要判断 never 类型,就不能直接 T extends number,可以这样写:

ts
type IsNever<T> = [T] extends [never] ? true : false;

这样就能正常判断 never 类型了:

ts
type TestNeverResult = IsNever<never>;
+// type TestNeverResult = true

除此以外,any 在条件类型中也比较特殊,如果类型参数为 any,会直接返回 trueType 和 falseType 的合并:

ts
type TestAny<T> = T extends number ? 1 : 2;
+
+type TestAnyResult = TestAny<any>;
+// type TestAnyResult = 1 | 2

联合类型、never、any 在作为条件类型的类型参数时的这些特殊情况,也会在后面的原理篇来解释原因。

IsTuple

元组类型怎么判断呢?它和数组有什么区别呢?

元组类型的 length 是数字字面量,而数组的 length 是 number。

ts
type len

UnionToIntersection

类型之间是有父子关系的,更具体的那个是子类型,比如 A 和 B 的交叉类型 A & B 就是联合类型 A | B 的子类型,因为更具体。

如果允许父类型赋值给子类型,就叫做逆变

如果允许子类型赋值给父类型,就叫做协变

(关于逆变、协变等概念的详细解释可以看原理篇)

在 TypeScript 中有函数参数是有逆变的性质的,也就是如果参数可能是多个类型,参数类型会变成它们的交叉类型。

所以联合转交叉可以这样实现 :

ts
type UnionToIntersection<U> = (U extends U ? (x: U) => unknown : never) extends (x: infer R) => unknown ? R : never;

类型参数 U 是要转换的联合类型。

U extends U 是为了触发联合类型的 distributive 的性质,让每个类型单独传入做计算,最后合并。

利用 U 做为参数构造个函数,通过模式匹配取参数的类型。

结果就是交叉类型

函数参数的逆变性质一般就联合类型转交叉类型会用,记住就行。

GetOptional

如何提取索引类型中的可选索引呢?

这也要利用可选索引的特性:可选索引的值为 undefined 和值类型的联合类型。

过滤可选索引,就要构造一个新的索引类型,过程中做过滤:

ts
type GetOptional<Obj extends Record<string, any>> = {
+  [Key in keyof Obj as {} extends Pick<Obj, Key> ? Key : never]: Obj[Key];
+};

类型参数 Obj 为待处理的索引类型,类型约束为索引为 string、值为任意类型的索引类型 Record<string, any>。

用映射类型的语法重新构造索引类型,索引是之前的索引也就是 Key in keyof Obj,但要做一些过滤,也就是 as 之后的部分。

过滤的方式就是单独取出该索引之后,判断空对象是否是其子类型。

这里的 Pick 是 ts 提供的内置高级类型,就是取出某个 Key 构造新的索引类型:

ts
type Pick<T, K extends keyof T> = { [P in K]: T[P] };

比如单独取出 age 构造的新的索引类型是这样的:

可选的意思是这个索引可能没有,没有的时候,那 Pick<Obj, Key> 就是空的,所以 {} extends Pick<Obj, Key> 就能过滤出可选索引。

值的类型依然是之前的,也就是 Obj[Key]。

这样,就能过滤出所有可选索引,构造成新的索引类型:

总结

  • any 类型与任何类型的交叉都是 any,也就是 1 & any 结果是 any,可以用这个特性判断 any 类型。
  • 联合类型作为类型参数出现在条件类型左侧时,会分散成单个类型传入,最后合并。
  • never 作为类型参数出现在条件类型左侧时,会直接返回 never。
  • any 作为类型参数出现在条件类型左侧时,会直接返回 trueType 和 falseType 的联合类型。
  • 元组类型也是数组类型,但 length 是数字字面量,而数组的 length 是 number。可以用来判断元组类型。
  • 函数参数处会发生逆变,可以用来实现联合类型转交叉类型。
  • 可选索引的索引可能没有,那 Pick 出来的就可能是 {},可以用来过滤可选索引,反过来也可以过滤非可选索引。
  • 索引类型的索引为字符串字面量类型,而可索引签名不是,可以用这个特性过滤掉可索引签名。
  • keyof 只能拿到 class 的 public 的索引,可以用来过滤出 public 的属性。
  • 默认推导出来的不是字面量类型,加上 as const 可以推导出字面量类型,但带有 readonly 修饰,这样模式匹配的时候也得加上 readonly 才行。
`,253)]))}const y=i(k,[["render",p]]);export{g as __pageData,y as default}; diff --git a/assets/cn_src_article_typescript_pattern.md.Cyn9ELOY.js b/assets/cn_src_article_typescript_pattern.md.Cyn9ELOY.js new file mode 100644 index 0000000000..3db9deb1f4 --- /dev/null +++ b/assets/cn_src_article_typescript_pattern.md.Cyn9ELOY.js @@ -0,0 +1,93 @@ +import{_ as i,o as a,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"模式匹配提取","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/typescript/pattern.md","filePath":"cn/src/article/typescript/pattern.md","lastUpdated":1726550590000}'),n={name:"cn/src/article/typescript/pattern.md"};function k(p,s,l,e,r,d){return a(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h(`

模式匹配提取

字符串可以和正则做模式匹配,找到匹配的部分,提取子组,之后可以用 1,2 等引用匹配的子组。

ts
'abc'.replace(/a(b)c/, '$1,$1,$1');
+// 'b,b,b'

Typescript 的类型也同样可以做模式匹配。

比如这样一个 Promise 类型:

ts
type p = Promise<'value'>;

我们想提取 value 的类型,可以这样做:

ts
type GetValueType<P> = P extends Promise<infer Value> ? Value : never;

通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取的,通过 infer 声明一个局部变量 Value 来保存,如果匹配,就返回匹配到的 Value,否则就返回 never 代表没匹配到。

ts
// type GetValueResult = 'value'
+type GetValueResult = GetValueType<Promise<'value'>>;

这就是 Typescript 类型的模式匹配:

Typescript 类型的模式匹配是通过 extends 对类型参数做匹配,结果保存到通过 infer 声明的局部类型变量里,如果匹配就能从该局部变量里拿到提取出的类型。

这个模式匹配的套路有多有用呢?我们来看下在数组、字符串、函数、构造器等类型里的应用。

1.数组类型

提取第一个元素

数组类型想提取第一个元素的类型怎么做呢?

ts
type arr = [1, 2, 3];

用它来匹配一个模式类型,提取第一个元素的类型到通过 infer 声明的局部变量里返回。

ts
type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;

类型参数 Arr 通过 extends 约束为只能是数组类型,数组元素是 unkown 也就是可以是任何值。

any 和 unknown 的区别: any 和 unknown 都代表任意类型,但是 unknown 只能接收任意类型的值,而 any 除了可以接收任意类型的值,也可以赋值给任意类型(除了 never)。类型体操中经常用 unknown 接受和匹配任何类型,而很少把任何类型赋值给某个类型变量。

对 Arr 做模式匹配,把我们要提取的第一个元素的类型放到通过 infer 声明的 First 局部变量里,后面的元素可以是任何类型,用 unknown 接收,然后把局部变量 First 返回。

当类型参数 Arr 为 [1,2,3] 时:

ts
type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;
+type GetFirstValue = GetFirst<[1, 2, 3]>;
+// type GetFirstValue = 1

当类型参数 Arr 为 [] 时:

ts
type GetFirstResult = GetFirst<[]>;
+// type GetFirstResult = never

提取最后一个元素

可以提取第一个元素,当然也可以提取最后一个元素,修改下模式类型就行:

ts
type GetLastValue<Arr extends unknown[]> = Arr extends [...unknown, infer Last] ? Last : never;

当类型参数 Arr 为 [1,2,3]时:

ts
type GetLastResult = GetFirst<[1, 2, 3]>;
+// type GetLastResult = 3

PopArr

我们分别取了首尾元素,当然也可以取剩余的数组,比如取去掉了最后一个元素的数组:

ts
type PopArr<Arr extends unknown[]> = Arr extends [...infer Rest, unknown] ? Rest : never;

如果是空数组,就直接返回,否则匹配剩余的元素,放到 infer 声明的局部变量 Rest 里,返回 Rest。

当类型参数 Arr 为 [1,2,3] 时:

ts
type PopResult = PopArr<[1, 2, 3]>;
+// type PopResult = [1,2]

当类型参数 Arr 为 [] 时:

ts
type PopResult = PopArr<[]>;
+// type PopResult = []

ShiftArr

同理可得 ShiftArr 的实现:

ts
type ShiftArr<Arr extends unknown[]> = Arr extends [unknown, ...infer Rest] ? Rest : never;

当类型参数 Arr 为 [1,2,3]时:

ts
type ShiftResult = ShiftArr<[1, 2, 3]>;
+// type ShiftResult = [2,3]

2.字符串类型

字符串类型也同样可以做模式匹配,匹配一个模式字符串,把需要提取的部分放到 infer 声明的局部变量里。

StartsWith

判断字符串是否以某个前缀开头,也是通过模式匹配:

ts
type StartWith<str extends string, Prefix extends string> = Str extends \`\${Prefix}\${string}\` ? true : false;

需要声明字符串 Str、匹配的前缀 Prefix 两个类型参数,它们都是 string。

用 Str 去匹配一个模式类型,模式类型的前缀是 Prefix,后面是任意的 string,如果匹配返回 true,否则返回 false。

当匹配时:

ts
type StartWithResult = StartWidth<'prefix string', 'prefix'>;
+// type StartWithResult = true

不匹配时:

ts
type StartWithResult = StartWidth<'prefix string', 'string'>;
+// type StartWithResult = false

Replace

字符串可以匹配一个模式类型,提取想要的部分,自然也可以用这些再构成一个新的类型。

比如实现字符串替换:

ts
type ReplaceStr<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends \`\${infer Prefix}\${From}\${infer Suffix}\` ? \`\${Prefix}\${To}\${Suffix}\` : Str;

声明要替换的字符串 Str、待替换的字符串 From、替换成的字符串 3 个类型参数,通过 extends 约束为都是 string 类型。

用 Str 去匹配模式串,模式串由 From 和之前之后的字符串构成,把之前之后的字符串放到通过 infer 声明的局部变量 Prefix、Suffix 里。

用 Prefix、Suffix 加上替换到的字符串 To 构造成新的字符串类型返回。

当匹配时:

ts
type ReplaceResult = ReplaceStr<'str replace to result', 'result', 'aaaa'>;
+// type ReplaceResult =  'str replace to aaaa'

不匹配时:

ts
type ReplaceResult = ReplaceStr<'str replace to result', '???', 'aaaa'>;
+// type ReplaceResult =  'str replace to result'

Trim

能够匹配和替换字符串,那也就能实现去掉空白字符的 Trim:

不过因为我们不知道有多少个空白字符,所以只能一个个匹配和去掉,需要递归。

先实现 TrimRight:

ts
type TrimRight<Str extends string> = Str extends \`\${infer Rest}\${' ' | '\\n''\\t'}\` ? TrimRight<Rest> : Str

类型参数 Str 是要 Trim 的字符串。

如果 Str 匹配字符串 + 空白字符 (空格、换行、制表符),那就把字符串放到 infer 声明的局部变量 Rest 里。

把 Rest 作为类型参数递归 TrimRight,直到不匹配,这时的类型参数 Str 就是处理结果。

ts
type TrimRightResult = TrimRight<'value          '>;
+// type TrimRightResult = 'value'

同理可得 TrimLeft:

ts
type TrimLeft<Str extends string> = Str extends \`\${' '|'\\n'|'\\t'}\`\${infer Rest} ? TrimLeft<Rest> : Str

TrimRight 和 TrimLeft 结合就是 Trim:

ts
type Trim<Str extends string> = TrimRight<TrimLeft<Str>>;

3.函数

函数同样也可以做类型匹配,比如提取参数、返回值的类型。

GetParameters

函数类型可以通过模式匹配来提取参数的类型:

ts
type GetParameters<Func extends Function> = Func extends (...args: infer Args) => unknown ? Args : never;

类型参数 Func 是要匹配的函数类型,通过 extends 约束为 Function。

Func 和模式类型做匹配,参数类型放到用 infer 声明的局部变量 Args 里,返回值可以是任何类型,用 unknown。

返回提取到的参数类型 Args。

ts
type GetParametersResult = GetParameters<(name: string, age: number) => string>;
+// type GetParametersResult = [name:string,age:number]

GetReturnType

能提取参数类型,同样也可以提取返回值类型:

ts
type GetReturnType<Func extends Function> = Func extends (...args: unknown[]) => infer ReturnType ? ReturnType : never;

Func 和模式类型做匹配,提取返回值到通过 infer 声明的局部变量 ReturnType 里返回。

参数类型可以是任意类型,也就是 any[](注意,这里不能用 unknown,这里的解释涉及到参数的逆变性质,具体原因逆变那一节会解释)。

ts
type GetReturnTypeResult = GetReturnType<() => 'return value'>;
+// type GetReturnTypeResult = 'return value'

GetThisParameterType

方法里可以调用 this,比如这样:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello() {
+    return "hello, I'm " + this.name;
+  }
+}
+
+const dong = new Dong();
+dong.hello();

用对象.方法名的方式调用的时候,this 就指向那个对象。

但是方法也可以用 call 或者 apply 调用:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello() {
+    return "hello, I'm " + this.name;
+  }
+}
+
+const dong = new Dong();
+dong.hello().call({ x: 1 });

call 调用的时候,this 就变了,但这里却没有被检查出来 this 指向的错误。

如何让编译器能够检查出 this 指向的错误呢?

可以在方法声明时指定 this 的类型:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello(this: Dong) {
+    return "hello, I'm " + this.name;
+  }
+}

这样,当 call/apply 调用的时候,就能检查出 this 指向的对象是否是对的:

如果没有报错,说明没开启 strictBindCallApply 的编译选项,这个是控制是否按照原函数的类型来检查 bind、call、apply

这里的 this 类型同样也可以通过模式匹配提取出来:

ts
type GetThisParameterType<T> = T extends (this: infer This, ...args: unknown[]) => unknown ? This : unknown;

类型参数 T 是待处理的类型。

用 T 匹配一个模式类型,提取 this 的类型到 infer 声明的局部变量 ThisType 中,其余的参数是任意类型,也就是 any,返回值也是任意类型。

返回提取到的 ThisType。

这样就能提取出 this 的类型:

4.构造器类型

构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

同样,我们也可以通过模式匹配提取构造器的参数和返回值的类型:

GetInstanceType

构造器类型可以用 interface 声明,使用 new(): xx 的语法。

比如:

ts
interface Person {
+  name: string;
+}
+
+interface PersonConstructor {
+  new (name: string): Person;
+}

这里的 PersonConstructor 返回的是 Person 类型的实例对象,这个也可以通过模式匹配取出来。

ts
type GetInstanceType<ConstructorType extends new (...args: any) => any> = ConstructorType extends new (
+  ...args: any
+) => infer InstanceType
+  ? InstanceType
+  : any;

类型参数 ConstructorType 是待处理的类型,通过 extends 约束为构造器类型。

用 ConstructorType 匹配一个模式类型,提取返回的实例类型到 infer 声明的局部变量 InstanceType 里,返回 InstanceType。

这样就能取出构造器对应的实例类型:

ts
interface PersonConstructor {
+  new (name: string): Person;
+}
+
+type GetInstanceTypeResult = GetInstanceType<PersonConstructor>;
+// type GetInstanceTypeResult = Person

GetConstructorParameters

GetInstanceType 是提取构造器返回值类型,那同样也可以提取构造器的参数类型:

ts
type GetConstructorParameters<ConstructorType extends new (...args: any) => any> = ConstructorType extends new (
+  ...args: infer ParametersType
+) => any
+  ? ParametersType
+  : never;

类型参数 ConstructorType 为待处理的类型,通过 extends 约束为构造器类型。

用 ConstructorType 匹配一个模式类型,提取参数的部分到 infer 声明的局部变量 ParametersType 里,返回 ParametersType。

这样就能提取出构造器对应的参数类型:

ts
interface PersonConstructor {
+  new (name: string): Person;
+}
+
+type GetConstructorParametersResult = GetConstructorParameters<PersonConstructor>;
+// type GetConstructorParametersResult = [name:string]

索引类型

索引类型也同样可以用模式匹配提取某个索引的值的类型,这个用的也挺多的,比如 React 的 index.d.ts 里的 PropsWithRef 的高级类型,就是通过模式匹配提取了 ref 的值的类型:

ts
type PropsWithRef<P> = 'ref' extends keyof P
+  ? P extends { ref?: infer R | undefined }
+    ? string extends R
+      ? PropsWithRef<P> & { ref?: Exclude<R, string> | undefined }
+      : P
+    : P
+  : P;

我们简化一下那个高级类型,提取 Props 里 ref 的类型:

ts
type GetPropsRef<Props> = 'ref' extends keyof Props
+  ? Props extends { ref?: infer Value | undefined }
+    ? value
+    : never
+  : never;

类型参数 Props 为待处理的类型。

通过 keyof Props 取出 Props 的所有索引构成的联合类型,判断下 ref 是否在其中,也就是 'ref' extends keyof Props。

为什么要做这个判断,上面注释里写了:

在 ts3.0 里面如果没有对应的索引,Obj[Key] 返回的是 {} 而不是 never,所以这样做下兼容处理。

如果有 ref 这个索引的话,就通过 infer 提取 Value 的类型返回,否则返回 never。

ts
type GetPropsRefResult = GetPropsRef<{ ref: 1; name: 'str' }>;
+// type GetPropsRefResult = 1

当 ref 为 undefined 时:

ts
type GetPropsRefResult = GetPropsRef<{ ref: undefined; name: 'str' }>;
+// type GetPropsRefResult = undefined
`,145)]))}const F=i(n,[["render",k]]);export{y as __pageData,F as default}; diff --git a/assets/cn_src_article_typescript_pattern.md.Cyn9ELOY.lean.js b/assets/cn_src_article_typescript_pattern.md.Cyn9ELOY.lean.js new file mode 100644 index 0000000000..3db9deb1f4 --- /dev/null +++ b/assets/cn_src_article_typescript_pattern.md.Cyn9ELOY.lean.js @@ -0,0 +1,93 @@ +import{_ as i,o as a,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"模式匹配提取","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/typescript/pattern.md","filePath":"cn/src/article/typescript/pattern.md","lastUpdated":1726550590000}'),n={name:"cn/src/article/typescript/pattern.md"};function k(p,s,l,e,r,d){return a(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h(`

模式匹配提取

字符串可以和正则做模式匹配,找到匹配的部分,提取子组,之后可以用 1,2 等引用匹配的子组。

ts
'abc'.replace(/a(b)c/, '$1,$1,$1');
+// 'b,b,b'

Typescript 的类型也同样可以做模式匹配。

比如这样一个 Promise 类型:

ts
type p = Promise<'value'>;

我们想提取 value 的类型,可以这样做:

ts
type GetValueType<P> = P extends Promise<infer Value> ? Value : never;

通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取的,通过 infer 声明一个局部变量 Value 来保存,如果匹配,就返回匹配到的 Value,否则就返回 never 代表没匹配到。

ts
// type GetValueResult = 'value'
+type GetValueResult = GetValueType<Promise<'value'>>;

这就是 Typescript 类型的模式匹配:

Typescript 类型的模式匹配是通过 extends 对类型参数做匹配,结果保存到通过 infer 声明的局部类型变量里,如果匹配就能从该局部变量里拿到提取出的类型。

这个模式匹配的套路有多有用呢?我们来看下在数组、字符串、函数、构造器等类型里的应用。

1.数组类型

提取第一个元素

数组类型想提取第一个元素的类型怎么做呢?

ts
type arr = [1, 2, 3];

用它来匹配一个模式类型,提取第一个元素的类型到通过 infer 声明的局部变量里返回。

ts
type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;

类型参数 Arr 通过 extends 约束为只能是数组类型,数组元素是 unkown 也就是可以是任何值。

any 和 unknown 的区别: any 和 unknown 都代表任意类型,但是 unknown 只能接收任意类型的值,而 any 除了可以接收任意类型的值,也可以赋值给任意类型(除了 never)。类型体操中经常用 unknown 接受和匹配任何类型,而很少把任何类型赋值给某个类型变量。

对 Arr 做模式匹配,把我们要提取的第一个元素的类型放到通过 infer 声明的 First 局部变量里,后面的元素可以是任何类型,用 unknown 接收,然后把局部变量 First 返回。

当类型参数 Arr 为 [1,2,3] 时:

ts
type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;
+type GetFirstValue = GetFirst<[1, 2, 3]>;
+// type GetFirstValue = 1

当类型参数 Arr 为 [] 时:

ts
type GetFirstResult = GetFirst<[]>;
+// type GetFirstResult = never

提取最后一个元素

可以提取第一个元素,当然也可以提取最后一个元素,修改下模式类型就行:

ts
type GetLastValue<Arr extends unknown[]> = Arr extends [...unknown, infer Last] ? Last : never;

当类型参数 Arr 为 [1,2,3]时:

ts
type GetLastResult = GetFirst<[1, 2, 3]>;
+// type GetLastResult = 3

PopArr

我们分别取了首尾元素,当然也可以取剩余的数组,比如取去掉了最后一个元素的数组:

ts
type PopArr<Arr extends unknown[]> = Arr extends [...infer Rest, unknown] ? Rest : never;

如果是空数组,就直接返回,否则匹配剩余的元素,放到 infer 声明的局部变量 Rest 里,返回 Rest。

当类型参数 Arr 为 [1,2,3] 时:

ts
type PopResult = PopArr<[1, 2, 3]>;
+// type PopResult = [1,2]

当类型参数 Arr 为 [] 时:

ts
type PopResult = PopArr<[]>;
+// type PopResult = []

ShiftArr

同理可得 ShiftArr 的实现:

ts
type ShiftArr<Arr extends unknown[]> = Arr extends [unknown, ...infer Rest] ? Rest : never;

当类型参数 Arr 为 [1,2,3]时:

ts
type ShiftResult = ShiftArr<[1, 2, 3]>;
+// type ShiftResult = [2,3]

2.字符串类型

字符串类型也同样可以做模式匹配,匹配一个模式字符串,把需要提取的部分放到 infer 声明的局部变量里。

StartsWith

判断字符串是否以某个前缀开头,也是通过模式匹配:

ts
type StartWith<str extends string, Prefix extends string> = Str extends \`\${Prefix}\${string}\` ? true : false;

需要声明字符串 Str、匹配的前缀 Prefix 两个类型参数,它们都是 string。

用 Str 去匹配一个模式类型,模式类型的前缀是 Prefix,后面是任意的 string,如果匹配返回 true,否则返回 false。

当匹配时:

ts
type StartWithResult = StartWidth<'prefix string', 'prefix'>;
+// type StartWithResult = true

不匹配时:

ts
type StartWithResult = StartWidth<'prefix string', 'string'>;
+// type StartWithResult = false

Replace

字符串可以匹配一个模式类型,提取想要的部分,自然也可以用这些再构成一个新的类型。

比如实现字符串替换:

ts
type ReplaceStr<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends \`\${infer Prefix}\${From}\${infer Suffix}\` ? \`\${Prefix}\${To}\${Suffix}\` : Str;

声明要替换的字符串 Str、待替换的字符串 From、替换成的字符串 3 个类型参数,通过 extends 约束为都是 string 类型。

用 Str 去匹配模式串,模式串由 From 和之前之后的字符串构成,把之前之后的字符串放到通过 infer 声明的局部变量 Prefix、Suffix 里。

用 Prefix、Suffix 加上替换到的字符串 To 构造成新的字符串类型返回。

当匹配时:

ts
type ReplaceResult = ReplaceStr<'str replace to result', 'result', 'aaaa'>;
+// type ReplaceResult =  'str replace to aaaa'

不匹配时:

ts
type ReplaceResult = ReplaceStr<'str replace to result', '???', 'aaaa'>;
+// type ReplaceResult =  'str replace to result'

Trim

能够匹配和替换字符串,那也就能实现去掉空白字符的 Trim:

不过因为我们不知道有多少个空白字符,所以只能一个个匹配和去掉,需要递归。

先实现 TrimRight:

ts
type TrimRight<Str extends string> = Str extends \`\${infer Rest}\${' ' | '\\n''\\t'}\` ? TrimRight<Rest> : Str

类型参数 Str 是要 Trim 的字符串。

如果 Str 匹配字符串 + 空白字符 (空格、换行、制表符),那就把字符串放到 infer 声明的局部变量 Rest 里。

把 Rest 作为类型参数递归 TrimRight,直到不匹配,这时的类型参数 Str 就是处理结果。

ts
type TrimRightResult = TrimRight<'value          '>;
+// type TrimRightResult = 'value'

同理可得 TrimLeft:

ts
type TrimLeft<Str extends string> = Str extends \`\${' '|'\\n'|'\\t'}\`\${infer Rest} ? TrimLeft<Rest> : Str

TrimRight 和 TrimLeft 结合就是 Trim:

ts
type Trim<Str extends string> = TrimRight<TrimLeft<Str>>;

3.函数

函数同样也可以做类型匹配,比如提取参数、返回值的类型。

GetParameters

函数类型可以通过模式匹配来提取参数的类型:

ts
type GetParameters<Func extends Function> = Func extends (...args: infer Args) => unknown ? Args : never;

类型参数 Func 是要匹配的函数类型,通过 extends 约束为 Function。

Func 和模式类型做匹配,参数类型放到用 infer 声明的局部变量 Args 里,返回值可以是任何类型,用 unknown。

返回提取到的参数类型 Args。

ts
type GetParametersResult = GetParameters<(name: string, age: number) => string>;
+// type GetParametersResult = [name:string,age:number]

GetReturnType

能提取参数类型,同样也可以提取返回值类型:

ts
type GetReturnType<Func extends Function> = Func extends (...args: unknown[]) => infer ReturnType ? ReturnType : never;

Func 和模式类型做匹配,提取返回值到通过 infer 声明的局部变量 ReturnType 里返回。

参数类型可以是任意类型,也就是 any[](注意,这里不能用 unknown,这里的解释涉及到参数的逆变性质,具体原因逆变那一节会解释)。

ts
type GetReturnTypeResult = GetReturnType<() => 'return value'>;
+// type GetReturnTypeResult = 'return value'

GetThisParameterType

方法里可以调用 this,比如这样:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello() {
+    return "hello, I'm " + this.name;
+  }
+}
+
+const dong = new Dong();
+dong.hello();

用对象.方法名的方式调用的时候,this 就指向那个对象。

但是方法也可以用 call 或者 apply 调用:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello() {
+    return "hello, I'm " + this.name;
+  }
+}
+
+const dong = new Dong();
+dong.hello().call({ x: 1 });

call 调用的时候,this 就变了,但这里却没有被检查出来 this 指向的错误。

如何让编译器能够检查出 this 指向的错误呢?

可以在方法声明时指定 this 的类型:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello(this: Dong) {
+    return "hello, I'm " + this.name;
+  }
+}

这样,当 call/apply 调用的时候,就能检查出 this 指向的对象是否是对的:

如果没有报错,说明没开启 strictBindCallApply 的编译选项,这个是控制是否按照原函数的类型来检查 bind、call、apply

这里的 this 类型同样也可以通过模式匹配提取出来:

ts
type GetThisParameterType<T> = T extends (this: infer This, ...args: unknown[]) => unknown ? This : unknown;

类型参数 T 是待处理的类型。

用 T 匹配一个模式类型,提取 this 的类型到 infer 声明的局部变量 ThisType 中,其余的参数是任意类型,也就是 any,返回值也是任意类型。

返回提取到的 ThisType。

这样就能提取出 this 的类型:

4.构造器类型

构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

同样,我们也可以通过模式匹配提取构造器的参数和返回值的类型:

GetInstanceType

构造器类型可以用 interface 声明,使用 new(): xx 的语法。

比如:

ts
interface Person {
+  name: string;
+}
+
+interface PersonConstructor {
+  new (name: string): Person;
+}

这里的 PersonConstructor 返回的是 Person 类型的实例对象,这个也可以通过模式匹配取出来。

ts
type GetInstanceType<ConstructorType extends new (...args: any) => any> = ConstructorType extends new (
+  ...args: any
+) => infer InstanceType
+  ? InstanceType
+  : any;

类型参数 ConstructorType 是待处理的类型,通过 extends 约束为构造器类型。

用 ConstructorType 匹配一个模式类型,提取返回的实例类型到 infer 声明的局部变量 InstanceType 里,返回 InstanceType。

这样就能取出构造器对应的实例类型:

ts
interface PersonConstructor {
+  new (name: string): Person;
+}
+
+type GetInstanceTypeResult = GetInstanceType<PersonConstructor>;
+// type GetInstanceTypeResult = Person

GetConstructorParameters

GetInstanceType 是提取构造器返回值类型,那同样也可以提取构造器的参数类型:

ts
type GetConstructorParameters<ConstructorType extends new (...args: any) => any> = ConstructorType extends new (
+  ...args: infer ParametersType
+) => any
+  ? ParametersType
+  : never;

类型参数 ConstructorType 为待处理的类型,通过 extends 约束为构造器类型。

用 ConstructorType 匹配一个模式类型,提取参数的部分到 infer 声明的局部变量 ParametersType 里,返回 ParametersType。

这样就能提取出构造器对应的参数类型:

ts
interface PersonConstructor {
+  new (name: string): Person;
+}
+
+type GetConstructorParametersResult = GetConstructorParameters<PersonConstructor>;
+// type GetConstructorParametersResult = [name:string]

索引类型

索引类型也同样可以用模式匹配提取某个索引的值的类型,这个用的也挺多的,比如 React 的 index.d.ts 里的 PropsWithRef 的高级类型,就是通过模式匹配提取了 ref 的值的类型:

ts
type PropsWithRef<P> = 'ref' extends keyof P
+  ? P extends { ref?: infer R | undefined }
+    ? string extends R
+      ? PropsWithRef<P> & { ref?: Exclude<R, string> | undefined }
+      : P
+    : P
+  : P;

我们简化一下那个高级类型,提取 Props 里 ref 的类型:

ts
type GetPropsRef<Props> = 'ref' extends keyof Props
+  ? Props extends { ref?: infer Value | undefined }
+    ? value
+    : never
+  : never;

类型参数 Props 为待处理的类型。

通过 keyof Props 取出 Props 的所有索引构成的联合类型,判断下 ref 是否在其中,也就是 'ref' extends keyof Props。

为什么要做这个判断,上面注释里写了:

在 ts3.0 里面如果没有对应的索引,Obj[Key] 返回的是 {} 而不是 never,所以这样做下兼容处理。

如果有 ref 这个索引的话,就通过 infer 提取 Value 的类型返回,否则返回 never。

ts
type GetPropsRefResult = GetPropsRef<{ ref: 1; name: 'str' }>;
+// type GetPropsRefResult = 1

当 ref 为 undefined 时:

ts
type GetPropsRefResult = GetPropsRef<{ ref: undefined; name: 'str' }>;
+// type GetPropsRefResult = undefined
`,145)]))}const F=i(n,[["render",k]]);export{y as __pageData,F as default}; diff --git a/assets/cn_src_article_typescript_reconstruction.md.Bc8ysEy2.js b/assets/cn_src_article_typescript_reconstruction.md.Bc8ysEy2.js new file mode 100644 index 0000000000..905b08d298 --- /dev/null +++ b/assets/cn_src_article_typescript_reconstruction.md.Bc8ysEy2.js @@ -0,0 +1,48 @@ +import{_ as i,o as a,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"重新构造做变换","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/typescript/reconstruction.md","filePath":"cn/src/article/typescript/reconstruction.md","lastUpdated":1726550590000}'),k={name:"cn/src/article/typescript/reconstruction.md"};function n(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t(`

重新构造做变换

类型编程主要的目的就是对类型做各种转换,那么如何对类型做修改呢?

TypeScript 类型系统支持 3 种可以声明任意类型的变量: type、infer、类型参数。

type 叫做类型别名,其实就是声明一个变量存储某个类型:

ts
type ttt = Promise<number>;

infer 用于类型的提取,然后存到一个变量里,相当于局部变量:

ts
type GetValueType<P> = P extends Promise<infer Value> ? Value : never;

类型参数用于接受具体的类型,在类型运算中也相当于局部变量:

ts
type isTwo<T> = T extends 2 ? true : false;

但是,严格来说这三种也都不叫变量,因为它们不能被重新赋值。

TypeScript 设计可以做类型编程的类型系统的目的就是为了产生各种复杂的类型,那不能修改怎么产生新类型呢?

答案是重新构造。

这就涉及到了第二个类型体操套路:重新构造做变换。

重新构造

TypeScript 的 type、infer、类型参数声明的变量都不能修改,想对类型做各种变换产生新的类型就需要重新构造。

数组、字符串、函数等类型的重新构造比较简单。

索引类型,也就是多个元素的聚合类型的重新构造复杂一些,涉及到了映射类型的语法。

我们先从简单的开始:

数组类型的重新构造

Push

有这样一个元组类型:

ts
type tuple = [1, 2, 3];

我想给这个元组类型再添加一些类型,怎么做呢?

TypeScript 类型变量不支持修改,我们可以构造一个新的元组类型:

ts
type Push<Arr extends unknown[], Ele> = [...Arr, Ele];

类型参数 Arr 是要修改的数组/元组类型,元素的类型任意,也就是 unknown。

类型参数 Ele 是添加的元素的类型。

返回的是用 Arr 已有的元素加上 Ele 构造的新的元组类型。

ts
type PushResult = Push<[1, 2, 3], 4>;
+// type PushResult = [1,2,3,4]

这就是数组/元组的重新构造。

数组和元组的区别:数组类型是指任意多个同一类型的元素构成的,比如 number[]Array<number>,而元组则是数量固定,类型可以不同的元素构成的,比如 [1, true, 'name']

Unshift

可以在后面添加,同样也可以在前面添加:

ts
type Unshift<Arr extends unknown[], Ele> = [Ele, ...Arr];

Zip

有这样两个元组:

ts
type tuple1 = [1, 2];
+type tuple2 = ['name', 'value'];

我们想把它们合并成这样的元组:

ts
type tuple = [[1, 'name'], [2, 'value']];

思路很容易想到,提取元组中的两个元素,构造成新的元组:

ts
type Zip<One extends [unknown, unknown], Other extends [unknown, unknown]> = One extends [
+  infer OneFirst,
+  infer OneSecond,
+]
+  ? Other extends [infer OtherFirst, infer OtherSecond]
+    ? [[OneFirst, OtherFirst], [OneSecond, OtherSecond]]
+    : []
+  : [];

两个类型参数 One、Other 是两个元组,类型是 [unknown, unknown],代表 2 个任意类型的元素构成的元组。

通过 infer 分别提取 One 和 Other 的元素到 infer 声明的局部变量 OneFirst、OneSecond、OtherFirst、OtherSecond 里。

用提取的元素构造成新的元组返回即可:

ts
type ZipResult = Zip<[1, 2], ['name', 'value']>;
+// type ZipResult = [[1, 'name'], [2, 'value']];

但是这样只能合并两个元素的元组,如果是任意个呢?

那就得用递归了:

ts
type Zip<One extends unknown[], Other extends unknown[]> = One extends [infer OneFirst, ...infer OneRest]
+  ? Other extends [infer OtherFirst, ...infer OtherRest]
+    ? [[OneFirst, OtherFirst], ...Zip<OneRest, OtherRest>]
+    : []
+  : [];

类型参数 One、Other 声明为 unknown[],也就是元素个数任意,类型任意的数组。

每次提取 One 和 Other 的第一个元素 OneFirst、OtherFirst,剩余的放到 OneRest、OtherRest 里。

用 OneFirst、OtherFirst 构造成新的元组的一个元素,剩余元素继续递归处理 OneRest、OtherRest。

这样,就能处理任意个数元组的合并:

ts
type ZipResult = Zip<[1, 2, 3, 4, 5], ['name', 'value', 'three', 'four', 'five']>;
+// type ZipResult = [[1, 'name'], [2, 'value'], [3, 'three'], [4, 'four'], [5, 'five']];

了解了数组类型的重新构造,我们再来看下字符串类型的:

字符串类型的重新构造

CapitalizeStr

我们想把一个字符串字面量类型的 'guang' 转为首字母大写的 'Guang'。

需要用到字符串类型的提取和重新构造:

ts
type CapitalizeStr<Str extends string> = Str extends \`\${infer First}\${infer Rest}\` ? \`\${Uppercase<First>}\${Rest}\` : Str;

我们声明了类型参数 Str 是要处理的字符串类型,通过 extends 约束为 string。

通过 infer 提取出首个字符到局部变量 First,提取后面的字符到局部变量 Rest。

然后使用 TypeScript 提供的内置高级类型 Uppercase 把首字母转为大写,加上 Rest,构造成新的字符串类型返回。

这就是字符串类型的重新构造:从已有的字符串类型中提取出一些部分字符串,经过一系列变换,构造成新的字符串类型。

CamelCase

我们再来实现 dong_dong_dong 到 dongDongDong 的变换。

同样是提取和重新构造:

ts
type CamelCase<Str extends string> = Str extends \`\${infer Left}_\${infer Right}\${infer Rest}\`
+  ? \`\${Left}\${Uppercase<Right>}\${CamelCase<Rest>}\`
+  : Str;

类型参数 Str 是待处理的字符串类型,约束为 string。

提取 _ 之前和之后的两个字符到 infer 声明的局部变量 Left 和 Right,剩下的字符放到 Rest 里。

然后把右边的字符 Right 大写,和 Left 构造成新的字符串,剩余的字符 Rest 要继续递归的处理。

这样就完成了从下划线到驼峰形式的转换:

DropSubStr

可以修改自然也可以删除,我们再来做一个删除一段字符串的案例:删除字符串中的某个子串

ts
type DropSubStr<Str extends string, SubStr extends string> = Str extends \`\${infer Prefix}\${SubStr}\${infer Suffix}\`
+  ? DropSubStr<\`\${Prefix}\${Suffix}\`, SubStr>
+  : Str;

类型参数 Str 是待处理的字符串, SubStr 是要删除的字符串,都通过 extends 约束为 string 类型。

通过模式匹配提取 SubStr 之前和之后的字符串到 infer 声明的局部变量 Prefix、Suffix 中。

如果不匹配就直接返回 Str。

如果匹配,那就用 Prefix、Suffix 构造成新的字符串,然后继续递归删除 SubStr。直到不再匹配,也就是没有 SubStr 了。

字符串类型的重新构造之后,我们再来看下函数类型的重新构造:

函数类型的重新构造

AppendArgument

之前我们分别实现了参数和返回值的提取,那么重新构造就是用这些提取出的类型做下修改,构造一个新的类型即可。

比如在已有的函数类型上添加一个参数:

ts
type AppendArgument<Func extends Function, Arg> = Func extends (...args: infer Args) => infer ReturnType
+  ? (...args: [...Args, Arg]) => ReturnType
+  : never;

类型参数 Func 是待处理的函数类型,通过 extends 约束为 Function,Arg 是要添加的参数类型。

通过模式匹配提取参数到 infer 声明的局部变量 Args 中,提取返回值到局部变量 ReturnType 中。

用 Args 数组添加 Arg 构造成新的参数类型,结合 ReturnType 构造成新的函数类型返回。

这样就完成了函数类型的修改:

最后,我们再来看下索引类型的重新构造

索引类型的重新构造

索引类型是聚合多个元素的类型,class、对象等都是索引类型,比如这就是一个索引类型:

ts
type obj = {
+  name: string;
+  age: number;
+  gender: boolean;
+};

索引类型可以添加修饰符 readonly(只读)、?(可选):

ts
type obj = {
+  readonly name: string;
+  age?: number;
+  gender: boolean;
+};

对它的修改和构造新类型涉及到了映射类型的语法:

ts
type Mapping<Obj extends object> = {
+  [Key in keyof Obj]: Obj[Key];
+};

Mapping

映射的过程中可以对 value 做下修改,比如:

ts
type Mapping<Obj extends object> = {
+  [Key in keyof Obj]: [Obj[Key], Obj[Key], Obj[Key]];
+};

类型参数 Obj 是待处理的索引类型,通过 extends 约束为 object。

用 keyof 取出 Obj 的索引,作为新的索引类型的索引,也就是 Key in keyof Obj。

值的类型可以做变换,这里我们用之前索引类型的值 Obj[Key] 构造成了三个元素的元组类型 [Obj[Key], Obj[Key], Obj[Key]]:

UppercaseKey

除了可以对 Value 做修改,也可以对 Key 做修改,使用 as,这叫做重映射:

比如把索引类型的 Key 变为大写。

ts
type UppercaseKey<Obj extends object> = {
+  [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key];
+};

类型参数 Obj 是待处理的索引类型,通过 extends 约束为 object。

新的索引类型的索引为 Obj 中的索引,也就是 Key in keyof Obj,但要做一些变换,也就是 as 之后的。

通过 Uppercase 把索引 Key 转为大写,因为索引可能为 string、number、symbol 类型,而这里只能接受 string 类型,所以要 & string,也就是取索引中 string 的部分。

value 保持不变,也就是之前的索引 Key 对应的值的类型 Obj[Key]。

这样构造出的新的索引类型,就把原来索引类型的索引转为了大写:

Record

TypeScript 提供了内置的高级类型 Record 来创建索引类型:

ts
type Record<K extends string | number | symbol, T> = { [P in K]: T };

指定索引和值的类型分别为 K 和 T,就可以创建一个对应的索引类型。

上面的索引类型的约束我们用的 object,其实更语义化一点我推荐用 Record<string, any>:

ts
type UppercaseKey<Obj extends Record<string, any>> = {
+  [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key];
+};

也就是约束类型参数 Obj 为 key 为 string,值为任意类型的索引类型。

ToReadonly

索引类型的索引可以添加 readonly 的修饰符,代表只读。

那我们就可以实现给索引类型添加 readonly 修饰的高级类型:

ts
type ToReadonly<T> = {
+  readonly [Key in keyof T]: T[Key];
+};

通过映射类型构造了新的索引类型,给索引加上了 readonly 的修饰,其余的保持不变,索引依然为原来的索引 Key in keyof T,值依然为原来的值 T[Key]。

ToPartial

同理,索引类型还可以添加可选修饰符:

ts
type ToPartial<T> = {
+  [Key in keyof T]?: T[Key];
+};

给索引类型 T 的索引添加了 ? 可选修饰符,其余保持不变。

ToMutable

可以添加 readonly 修饰,当然也可以去掉:

ts
type ToMutable<T> = {
+  -readonly [Key in keyof T]: T[Key];
+};

给索引类型 T 的每个索引去掉 readonly 的修饰,其余保持不变。

ToRequired

同理,也可以去掉可选修饰符:

ts
type ToRequired<T> = {
+  [Key in keyof T]-?: T[Key];
+};

给索引类型 T 的索引去掉 ? 的修饰 ,其余保持不变。

FilterByValueType

可以在构造新索引类型的时候根据值的类型做下过滤:

ts
type FilterByValueType<Obj extends Record<string, any>, ValueType> = {
+  [Key in keyof Obj as Obj[Key] extends ValueType ? Key : never]: Obj[Key];
+};

类型参数 Obj 为要处理的索引类型,通过 extends 约束为索引为 string,值为任意类型的索引类型 Record<string, any>。

类型参数 ValueType 为要过滤出的值的类型。

构造新的索引类型,索引为 Obj 的索引,也就是 Key in keyof Obj,但要做一些变换,也就是 as 之后的部分。

如果原来索引的值 Obj[Key] 是 ValueType 类型,索引依然为之前的索引 Key,否则索引设置为 never,never 的索引会在生成新的索引类型时被去掉。

值保持不变,依然为原来索引的值,也就是 Obj[Key]。

这样就达到了过滤索引类型的索引,产生新的索引类型的目的:

`,144)]))}const y=i(k,[["render",n]]);export{E as __pageData,y as default}; diff --git a/assets/cn_src_article_typescript_reconstruction.md.Bc8ysEy2.lean.js b/assets/cn_src_article_typescript_reconstruction.md.Bc8ysEy2.lean.js new file mode 100644 index 0000000000..905b08d298 --- /dev/null +++ b/assets/cn_src_article_typescript_reconstruction.md.Bc8ysEy2.lean.js @@ -0,0 +1,48 @@ +import{_ as i,o as a,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"重新构造做变换","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/typescript/reconstruction.md","filePath":"cn/src/article/typescript/reconstruction.md","lastUpdated":1726550590000}'),k={name:"cn/src/article/typescript/reconstruction.md"};function n(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t(`

重新构造做变换

类型编程主要的目的就是对类型做各种转换,那么如何对类型做修改呢?

TypeScript 类型系统支持 3 种可以声明任意类型的变量: type、infer、类型参数。

type 叫做类型别名,其实就是声明一个变量存储某个类型:

ts
type ttt = Promise<number>;

infer 用于类型的提取,然后存到一个变量里,相当于局部变量:

ts
type GetValueType<P> = P extends Promise<infer Value> ? Value : never;

类型参数用于接受具体的类型,在类型运算中也相当于局部变量:

ts
type isTwo<T> = T extends 2 ? true : false;

但是,严格来说这三种也都不叫变量,因为它们不能被重新赋值。

TypeScript 设计可以做类型编程的类型系统的目的就是为了产生各种复杂的类型,那不能修改怎么产生新类型呢?

答案是重新构造。

这就涉及到了第二个类型体操套路:重新构造做变换。

重新构造

TypeScript 的 type、infer、类型参数声明的变量都不能修改,想对类型做各种变换产生新的类型就需要重新构造。

数组、字符串、函数等类型的重新构造比较简单。

索引类型,也就是多个元素的聚合类型的重新构造复杂一些,涉及到了映射类型的语法。

我们先从简单的开始:

数组类型的重新构造

Push

有这样一个元组类型:

ts
type tuple = [1, 2, 3];

我想给这个元组类型再添加一些类型,怎么做呢?

TypeScript 类型变量不支持修改,我们可以构造一个新的元组类型:

ts
type Push<Arr extends unknown[], Ele> = [...Arr, Ele];

类型参数 Arr 是要修改的数组/元组类型,元素的类型任意,也就是 unknown。

类型参数 Ele 是添加的元素的类型。

返回的是用 Arr 已有的元素加上 Ele 构造的新的元组类型。

ts
type PushResult = Push<[1, 2, 3], 4>;
+// type PushResult = [1,2,3,4]

这就是数组/元组的重新构造。

数组和元组的区别:数组类型是指任意多个同一类型的元素构成的,比如 number[]Array<number>,而元组则是数量固定,类型可以不同的元素构成的,比如 [1, true, 'name']

Unshift

可以在后面添加,同样也可以在前面添加:

ts
type Unshift<Arr extends unknown[], Ele> = [Ele, ...Arr];

Zip

有这样两个元组:

ts
type tuple1 = [1, 2];
+type tuple2 = ['name', 'value'];

我们想把它们合并成这样的元组:

ts
type tuple = [[1, 'name'], [2, 'value']];

思路很容易想到,提取元组中的两个元素,构造成新的元组:

ts
type Zip<One extends [unknown, unknown], Other extends [unknown, unknown]> = One extends [
+  infer OneFirst,
+  infer OneSecond,
+]
+  ? Other extends [infer OtherFirst, infer OtherSecond]
+    ? [[OneFirst, OtherFirst], [OneSecond, OtherSecond]]
+    : []
+  : [];

两个类型参数 One、Other 是两个元组,类型是 [unknown, unknown],代表 2 个任意类型的元素构成的元组。

通过 infer 分别提取 One 和 Other 的元素到 infer 声明的局部变量 OneFirst、OneSecond、OtherFirst、OtherSecond 里。

用提取的元素构造成新的元组返回即可:

ts
type ZipResult = Zip<[1, 2], ['name', 'value']>;
+// type ZipResult = [[1, 'name'], [2, 'value']];

但是这样只能合并两个元素的元组,如果是任意个呢?

那就得用递归了:

ts
type Zip<One extends unknown[], Other extends unknown[]> = One extends [infer OneFirst, ...infer OneRest]
+  ? Other extends [infer OtherFirst, ...infer OtherRest]
+    ? [[OneFirst, OtherFirst], ...Zip<OneRest, OtherRest>]
+    : []
+  : [];

类型参数 One、Other 声明为 unknown[],也就是元素个数任意,类型任意的数组。

每次提取 One 和 Other 的第一个元素 OneFirst、OtherFirst,剩余的放到 OneRest、OtherRest 里。

用 OneFirst、OtherFirst 构造成新的元组的一个元素,剩余元素继续递归处理 OneRest、OtherRest。

这样,就能处理任意个数元组的合并:

ts
type ZipResult = Zip<[1, 2, 3, 4, 5], ['name', 'value', 'three', 'four', 'five']>;
+// type ZipResult = [[1, 'name'], [2, 'value'], [3, 'three'], [4, 'four'], [5, 'five']];

了解了数组类型的重新构造,我们再来看下字符串类型的:

字符串类型的重新构造

CapitalizeStr

我们想把一个字符串字面量类型的 'guang' 转为首字母大写的 'Guang'。

需要用到字符串类型的提取和重新构造:

ts
type CapitalizeStr<Str extends string> = Str extends \`\${infer First}\${infer Rest}\` ? \`\${Uppercase<First>}\${Rest}\` : Str;

我们声明了类型参数 Str 是要处理的字符串类型,通过 extends 约束为 string。

通过 infer 提取出首个字符到局部变量 First,提取后面的字符到局部变量 Rest。

然后使用 TypeScript 提供的内置高级类型 Uppercase 把首字母转为大写,加上 Rest,构造成新的字符串类型返回。

这就是字符串类型的重新构造:从已有的字符串类型中提取出一些部分字符串,经过一系列变换,构造成新的字符串类型。

CamelCase

我们再来实现 dong_dong_dong 到 dongDongDong 的变换。

同样是提取和重新构造:

ts
type CamelCase<Str extends string> = Str extends \`\${infer Left}_\${infer Right}\${infer Rest}\`
+  ? \`\${Left}\${Uppercase<Right>}\${CamelCase<Rest>}\`
+  : Str;

类型参数 Str 是待处理的字符串类型,约束为 string。

提取 _ 之前和之后的两个字符到 infer 声明的局部变量 Left 和 Right,剩下的字符放到 Rest 里。

然后把右边的字符 Right 大写,和 Left 构造成新的字符串,剩余的字符 Rest 要继续递归的处理。

这样就完成了从下划线到驼峰形式的转换:

DropSubStr

可以修改自然也可以删除,我们再来做一个删除一段字符串的案例:删除字符串中的某个子串

ts
type DropSubStr<Str extends string, SubStr extends string> = Str extends \`\${infer Prefix}\${SubStr}\${infer Suffix}\`
+  ? DropSubStr<\`\${Prefix}\${Suffix}\`, SubStr>
+  : Str;

类型参数 Str 是待处理的字符串, SubStr 是要删除的字符串,都通过 extends 约束为 string 类型。

通过模式匹配提取 SubStr 之前和之后的字符串到 infer 声明的局部变量 Prefix、Suffix 中。

如果不匹配就直接返回 Str。

如果匹配,那就用 Prefix、Suffix 构造成新的字符串,然后继续递归删除 SubStr。直到不再匹配,也就是没有 SubStr 了。

字符串类型的重新构造之后,我们再来看下函数类型的重新构造:

函数类型的重新构造

AppendArgument

之前我们分别实现了参数和返回值的提取,那么重新构造就是用这些提取出的类型做下修改,构造一个新的类型即可。

比如在已有的函数类型上添加一个参数:

ts
type AppendArgument<Func extends Function, Arg> = Func extends (...args: infer Args) => infer ReturnType
+  ? (...args: [...Args, Arg]) => ReturnType
+  : never;

类型参数 Func 是待处理的函数类型,通过 extends 约束为 Function,Arg 是要添加的参数类型。

通过模式匹配提取参数到 infer 声明的局部变量 Args 中,提取返回值到局部变量 ReturnType 中。

用 Args 数组添加 Arg 构造成新的参数类型,结合 ReturnType 构造成新的函数类型返回。

这样就完成了函数类型的修改:

最后,我们再来看下索引类型的重新构造

索引类型的重新构造

索引类型是聚合多个元素的类型,class、对象等都是索引类型,比如这就是一个索引类型:

ts
type obj = {
+  name: string;
+  age: number;
+  gender: boolean;
+};

索引类型可以添加修饰符 readonly(只读)、?(可选):

ts
type obj = {
+  readonly name: string;
+  age?: number;
+  gender: boolean;
+};

对它的修改和构造新类型涉及到了映射类型的语法:

ts
type Mapping<Obj extends object> = {
+  [Key in keyof Obj]: Obj[Key];
+};

Mapping

映射的过程中可以对 value 做下修改,比如:

ts
type Mapping<Obj extends object> = {
+  [Key in keyof Obj]: [Obj[Key], Obj[Key], Obj[Key]];
+};

类型参数 Obj 是待处理的索引类型,通过 extends 约束为 object。

用 keyof 取出 Obj 的索引,作为新的索引类型的索引,也就是 Key in keyof Obj。

值的类型可以做变换,这里我们用之前索引类型的值 Obj[Key] 构造成了三个元素的元组类型 [Obj[Key], Obj[Key], Obj[Key]]:

UppercaseKey

除了可以对 Value 做修改,也可以对 Key 做修改,使用 as,这叫做重映射:

比如把索引类型的 Key 变为大写。

ts
type UppercaseKey<Obj extends object> = {
+  [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key];
+};

类型参数 Obj 是待处理的索引类型,通过 extends 约束为 object。

新的索引类型的索引为 Obj 中的索引,也就是 Key in keyof Obj,但要做一些变换,也就是 as 之后的。

通过 Uppercase 把索引 Key 转为大写,因为索引可能为 string、number、symbol 类型,而这里只能接受 string 类型,所以要 & string,也就是取索引中 string 的部分。

value 保持不变,也就是之前的索引 Key 对应的值的类型 Obj[Key]。

这样构造出的新的索引类型,就把原来索引类型的索引转为了大写:

Record

TypeScript 提供了内置的高级类型 Record 来创建索引类型:

ts
type Record<K extends string | number | symbol, T> = { [P in K]: T };

指定索引和值的类型分别为 K 和 T,就可以创建一个对应的索引类型。

上面的索引类型的约束我们用的 object,其实更语义化一点我推荐用 Record<string, any>:

ts
type UppercaseKey<Obj extends Record<string, any>> = {
+  [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key];
+};

也就是约束类型参数 Obj 为 key 为 string,值为任意类型的索引类型。

ToReadonly

索引类型的索引可以添加 readonly 的修饰符,代表只读。

那我们就可以实现给索引类型添加 readonly 修饰的高级类型:

ts
type ToReadonly<T> = {
+  readonly [Key in keyof T]: T[Key];
+};

通过映射类型构造了新的索引类型,给索引加上了 readonly 的修饰,其余的保持不变,索引依然为原来的索引 Key in keyof T,值依然为原来的值 T[Key]。

ToPartial

同理,索引类型还可以添加可选修饰符:

ts
type ToPartial<T> = {
+  [Key in keyof T]?: T[Key];
+};

给索引类型 T 的索引添加了 ? 可选修饰符,其余保持不变。

ToMutable

可以添加 readonly 修饰,当然也可以去掉:

ts
type ToMutable<T> = {
+  -readonly [Key in keyof T]: T[Key];
+};

给索引类型 T 的每个索引去掉 readonly 的修饰,其余保持不变。

ToRequired

同理,也可以去掉可选修饰符:

ts
type ToRequired<T> = {
+  [Key in keyof T]-?: T[Key];
+};

给索引类型 T 的索引去掉 ? 的修饰 ,其余保持不变。

FilterByValueType

可以在构造新索引类型的时候根据值的类型做下过滤:

ts
type FilterByValueType<Obj extends Record<string, any>, ValueType> = {
+  [Key in keyof Obj as Obj[Key] extends ValueType ? Key : never]: Obj[Key];
+};

类型参数 Obj 为要处理的索引类型,通过 extends 约束为索引为 string,值为任意类型的索引类型 Record<string, any>。

类型参数 ValueType 为要过滤出的值的类型。

构造新的索引类型,索引为 Obj 的索引,也就是 Key in keyof Obj,但要做一些变换,也就是 as 之后的部分。

如果原来索引的值 Obj[Key] 是 ValueType 类型,索引依然为之前的索引 Key,否则索引设置为 never,never 的索引会在生成新的索引类型时被去掉。

值保持不变,依然为原来索引的值,也就是 Obj[Key]。

这样就达到了过滤索引类型的索引,产生新的索引类型的目的:

`,144)]))}const y=i(k,[["render",n]]);export{E as __pageData,y as default}; diff --git a/assets/cn_src_article_typescript_recursion.md.DiOAHp83.js b/assets/cn_src_article_typescript_recursion.md.DiOAHp83.js new file mode 100644 index 0000000000..9a7e2163ff --- /dev/null +++ b/assets/cn_src_article_typescript_recursion.md.DiOAHp83.js @@ -0,0 +1,65 @@ +import{_ as i,o as a,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"递归复用","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/typescript/recursion.md","filePath":"cn/src/article/typescript/recursion.md","lastUpdated":1726550590000}'),n={name:"cn/src/article/typescript/recursion.md"};function t(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k(`

递归复用

递归是把问题分解为一系列相似的小问题,通过函数不断调用自身来解决这一个个小问题,直到满足结束条件,就完成了问题的求解。

TypeScript 的高级类型支持类型参数,可以做各种类型运算逻辑,返回新的类型,和函数调用是对应的,自然也支持递归。

TypeScript 类型系统不支持循环,但支持递归。当处理数量(个数、长度、层数)不固定的类型的时候,可以只处理一个类型,然后递归的调用自身处理下一个类型,直到结束条件也就是所有的类型都处理完了,就完成了不确定数量的类型编程,达到循环的效果。

既然提到了数组、字符串、对象等类型,那么我们就来看一下这些类型的递归案例吧。

Promise 的递归复用

DeepPromiseValueType

先用 Promise 热热身,实现一个提取不确定层数的 Promise 中的 value 类型的高级类型。

ts
type ttt = Promise<Promise<Promise<Record<string, any>>>>;

这里是 3 层 Promise,value 类型是索引类型。

数量不确定,一涉及到这个就要想到用递归来做,每次只处理一层的提取,然后剩下的到下次递归做,直到结束条件。

所以高级类型是这样的:

ts
type DeepPromiseValueType<P extends Promise<unknown>> =
+  P extends Promise<infer ValueType>
+    ? ValueType extends Promise<unknown>
+      ? DeepPromiseValueType<ValueType>
+      : ValueType
+    : never;

类型参数 P 是待处理的 Promise,通过 extends 约束为 Promise 类型,value 类型不确定,设为 unknown。

每次只处理一个类型的提取,也就是通过模式匹配提取出 value 的类型到 infer 声明的局部变量 ValueType 中。

然后判断如果 ValueType 依然是 Promise 类型,就递归处理。

结束条件就是 ValueType 不为 Promise 类型,那就处理完了所有的层数,返回这时的 ValueType。

这样,我们就提取到了最里层的 Promise 的 value 类型,也就是索引类型:

其实这个类型的实现可以进一步的简化:

ts
type DeepPromiseValueType2<T> = T extends Promise<infer ValueType> ? DeepPromiseValueType2<ValueType> : T;

不再约束类型参数必须是 Promise,这样就可以少一层判断。

接下来再看下数组类型的递归复用:

数组类型的递归

ReverseArr

有这样一个元组类型:

ts
type arr = [1, 2, 3, 4, 5];

我们把它反过来,也就是变成:

ts
type arr = [5, 4, 3, 2, 1];

这个学完了提取和构造很容易写出来:

ts
type ReverseArr<Arr extends unknown[]> = Arr extends [infer One, infer Two, infer Three, infer Four, infer Five]
+  ? [Five, Four, Three, Two, One]
+  : never;

但如果数组长度不确定呢?

数量不确定,条件反射的就要想到递归。

我们每次只处理一个类型,剩下的递归做,直到满足结束条件。

ts
type ReverseArr<Arr extends unknown[]> = Arr extends [infer First, ...infer Rest] ? [...ReverseArr<Rest>, First] : Arr;

类型参数 Arr 为待处理的数组类型,元素类型不确定,也就是 unknown。

每次只处理一个元素的提取,放到 infer 声明的局部变量 First 里,剩下的放到 Rest 里。

用 First 作为最后一个元素构造新数组,其余元素递归的取。

结束条件就是取完所有的元素,也就是不再满足模式匹配的条件,这时候就返回 Arr。

Includes

既然递归可以做循环用,那么像查找元素这种自然也就可以实现。

比如查找 [1, 2, 3, 4, 5] 中是否存在 4,是就返回 true,否则返回 false。

从长度不固定的数组中查找某个元素,数量不确定,这时候就应该想到递归。

ts
type Includes<Arr extends unknown[], FindItem> = Arr extends [infer First, ...infer Rest]
+  ? IsEqual<First, FindItem> extends true
+    ? true
+    : Includes<Rest, FindItem>
+  : false;
+
+type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

类型参数 Arr 是待查找的数组类型,元素类型任意,也就是 unknown。FindItem 待查找的元素类型。

每次提取一个元素到 infer 声明的局部变量 First 中,剩余的放到局部变量 Rest。

判断 First 是否是要查找的元素,也就是和 FindItem 相等,是的话就返回 true,否则继续递归判断下一个元素。

直到结束条件也就是提取不出下一个元素,这时返回 false。

相等的判断就是 A 是 B 的子类型并且 B 也是 A 的子类型,。

这样就完成了不确定长度的数组中的元素查找,用递归实现了循环。

RemoveItem

可以查找自然就可以删除,只需要改下返回结果,构造一个新的数组返回。

ts
type RemoveItem<Arr extends unknown[], Item, Result extends unknown[] = []> = Arr extends [infer First, ...infer Rest]
+  ? IsEqual<First, Item> extends true
+    ? RemoveItem<Rest, Item, Result>
+    : RemoveItem<Rest, Item, [...Result, First]>
+  : Result;
+
+type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

类型参数 Arr 是待处理的数组,元素类型任意,也就是 unknown[]。类型参数 Item 为待查找的元素类型。类型参数 Result 是构造出的新数组,默认值是 []。

通过模式匹配提取数组中的一个元素的类型,如果是 Item 类型的话就删除,也就是不放入构造的新数组,直接返回之前的 Result。

否则放入构造的新数组,也就是再构造一个新的数组 [...Result, First]。

直到模式匹配不再满足,也就是处理完了所有的元素,返回这时候的 Result。

这样我们就完成了不确定元素个数的数组的某个元素的删除:

BuildArray

我们学过数组类型的构造,如果构造的数组类型元素个数不确定,也需要递归。

比如传入 5 和元素类型,构造一个长度为 5 的该元素类型构成的数组。

ts
type BuildArray<Length extends number, Ele = unknown, Arr extends unknown[] = []> = Arr['length'] extends Length
+  ? Arr
+  : BuildArray<Length, Ele, [...Arr, Ele]>;

类型参数 Length 为数组长度,约束为 number。类型参数 Ele 为元素类型,默认值为 unknown。类型参数 Arr 为构造出的数组,默认值是 []。

每次判断下 Arr 的长度是否到了 Length,是的话就返回 Arr,否则在 Arr 上加一个元素,然后递归构造。

学完了数组类型的递归,我们再来看下字符串类型。

字符串类型的递归

ReplaceAll

学模式匹配的时候,我们实现过一个 Replace 的高级类型:

ts
type ReplaceStr<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends \`\${infer Prefix}\${From}\${infer Suffix}\` ? \`\${Prefix}\${To}\${Suffix}\` : Str;

它能把一个字符串中的某个字符替换成另一个:

但是如果有多个这样的字符就处理不了了。

如果不确定有多少个 From 字符,怎么处理呢?

在类型体操里,遇到数量不确定的问题,就要条件反射的想到递归。

每次递归只处理一个类型,这部分我们已经实现了,那么加上递归的调用就可以。

ts
type ReplaceAll<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends \`\${infer Left}\${From}\${infer Right}\` ? \`\${Left}\${To}\${ReplaceAll<Right, From, To>}\` : Str;

类型参数 Str 是待处理的字符串类型,From 是待替换的字符,To 是替换到的字符。

通过模式匹配提取 From 左右的字符串到 infer 声明的局部变量 Left 和 Right 里。

用 Left 和 To 构造新的字符串,剩余的 Right 部分继续递归的替换。

结束条件是不再满足模式匹配,也就是没有要替换的元素,这时就直接返回字符串 Str。

这样就实现了任意数量的字符串替换:

StringToUnion

我们想把字符串字面量类型的每个字符都提取出来组成联合类型,也就是把 'dong' 转为 'd' | 'o' | 'n' | 'g'。

怎么做呢?

很明显也是提取和构造:

ts
type StringToUnion<Str extends string> = Str extends \`\${infer One}\${infer Two}\${infer Three}\${infer Four}\`
+  ? One | Two | Three | Four
+  : never;

但如果字符串长度不确定呢?

数量不确定,在类型体操中就要条件反射的想到递归。

ts
type StringToUnion<Str extends string> = Str extends \`\${infer First}\${infer Rest}\`
+  ? First | StringToUnion<Rest>
+  : never;

类型参数 Str 为待处理的字符串类型,通过 extends 约束为 string。

通过模式匹配提取第一个字符到 infer 声明的局部变量 First,其余的字符放到局部变量 Rest。

用 First 构造联合类型,剩余的元素递归的取。

这样就完成了不确定长度的字符串的提取和联合类型的构造:

ReverseStr

我们实现了数组的反转,自然也可以实现字符串类型的反转。

同样是递归提取和构造。

ts
type ReverseStr<Str extends string, Result extends string = ''> = Str extends \`\${infer First}\${infer Rest}\`
+  ? ReverseStr<Rest, \`\${First}\${Result}\`>
+  : Result;

类型参数 Str 为待处理的字符串。类型参数 Result 为构造出的字符,默认值是空串。

通过模式匹配提取第一个字符到 infer 声明的局部变量 First,其余字符放到 Rest。

用 First 和之前的 Result 构造成新的字符串,把 First 放到前面,因为递归是从左到右处理,那么不断往前插就是把右边的放到了左边,完成了反转的效果。

直到模式匹配不满足,就处理完了所有的字符。

这样就完成了字符串的反转:

对象类型的递归

DeepReadonly

对象类型的递归,也可以叫做索引类型的递归。

我们之前实现了索引类型的映射,给索引加上了 readonly 的修饰:

ts
type ToReadonly<T> = {
+  readonly [Key in keyof T]: T[Key];
+};

如果这个索引类型层数不确定呢?

比如这样:

ts
type obj = {
+  a: {
+    b: {
+      c: {
+        f: () => 'dong';
+        d: {
+          e: {
+            guang: string;
+          };
+        };
+      };
+    };
+  };
+};

数量(层数)不确定,类型体操中应该自然的想到递归。

我们在之前的映射上加入递归的逻辑:

ts
type DeepReadonly<Obj extends Record<string, any>> = {
+  readonly [Key in keyof Obj]: Obj[Key] extends object
+    ? Obj[Key] extends Function
+      ? Obj[Key]
+      : DeepReadonly<Obj[Key]>
+    : Obj[Key];
+};

类型参数 Obj 是待处理的索引类型,约束为 Record<string, any>,也就是索引为 string,值为任意类型的索引类型。

索引映射自之前的索引,也就是 Key in keyof Obj,只不过加上了 readonly 的修饰。

值要做下判断,如果是 object 类型并且还是 Function,那么就直接取之前的值 Obj[Key]。

如果是 object 类型但不是 Function,那就是说也是一个索引类型,就递归处理 DeepReadonly<Obj[Key]>。

否则,值不是 object 就直接返回之前的值 Obj[Key]。

这样就完成了任意层数的索引类型的添加 readonly 修饰:

我们取处理以后的索引 a 的值看一下,发现 b 已经加上了 readonly 修饰。

测试一下:

为啥这里没有计算呀?

因为 ts 的类型只有被用到的时候才会做计算。

所以可以在前面加上一段 Obj extends never ? never 或者 Obj extends any 等,从而触发计算:

ts
type DeepReadonly<Obj extends Record<string, any>> = Obj extends any
+  ? {
+      readonly [Key in keyof Obj]: Obj[Key] extends object
+        ? Obj[Key] extends Function
+          ? Obj[Key]
+          : DeepReadonly<Obj[Key]>
+        : Obj[Key];
+    }
+  : never;
`,123)]))}const F=i(n,[["render",t]]);export{E as __pageData,F as default}; diff --git a/assets/cn_src_article_typescript_recursion.md.DiOAHp83.lean.js b/assets/cn_src_article_typescript_recursion.md.DiOAHp83.lean.js new file mode 100644 index 0000000000..9a7e2163ff --- /dev/null +++ b/assets/cn_src_article_typescript_recursion.md.DiOAHp83.lean.js @@ -0,0 +1,65 @@ +import{_ as i,o as a,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"递归复用","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/typescript/recursion.md","filePath":"cn/src/article/typescript/recursion.md","lastUpdated":1726550590000}'),n={name:"cn/src/article/typescript/recursion.md"};function t(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k(`

递归复用

递归是把问题分解为一系列相似的小问题,通过函数不断调用自身来解决这一个个小问题,直到满足结束条件,就完成了问题的求解。

TypeScript 的高级类型支持类型参数,可以做各种类型运算逻辑,返回新的类型,和函数调用是对应的,自然也支持递归。

TypeScript 类型系统不支持循环,但支持递归。当处理数量(个数、长度、层数)不固定的类型的时候,可以只处理一个类型,然后递归的调用自身处理下一个类型,直到结束条件也就是所有的类型都处理完了,就完成了不确定数量的类型编程,达到循环的效果。

既然提到了数组、字符串、对象等类型,那么我们就来看一下这些类型的递归案例吧。

Promise 的递归复用

DeepPromiseValueType

先用 Promise 热热身,实现一个提取不确定层数的 Promise 中的 value 类型的高级类型。

ts
type ttt = Promise<Promise<Promise<Record<string, any>>>>;

这里是 3 层 Promise,value 类型是索引类型。

数量不确定,一涉及到这个就要想到用递归来做,每次只处理一层的提取,然后剩下的到下次递归做,直到结束条件。

所以高级类型是这样的:

ts
type DeepPromiseValueType<P extends Promise<unknown>> =
+  P extends Promise<infer ValueType>
+    ? ValueType extends Promise<unknown>
+      ? DeepPromiseValueType<ValueType>
+      : ValueType
+    : never;

类型参数 P 是待处理的 Promise,通过 extends 约束为 Promise 类型,value 类型不确定,设为 unknown。

每次只处理一个类型的提取,也就是通过模式匹配提取出 value 的类型到 infer 声明的局部变量 ValueType 中。

然后判断如果 ValueType 依然是 Promise 类型,就递归处理。

结束条件就是 ValueType 不为 Promise 类型,那就处理完了所有的层数,返回这时的 ValueType。

这样,我们就提取到了最里层的 Promise 的 value 类型,也就是索引类型:

其实这个类型的实现可以进一步的简化:

ts
type DeepPromiseValueType2<T> = T extends Promise<infer ValueType> ? DeepPromiseValueType2<ValueType> : T;

不再约束类型参数必须是 Promise,这样就可以少一层判断。

接下来再看下数组类型的递归复用:

数组类型的递归

ReverseArr

有这样一个元组类型:

ts
type arr = [1, 2, 3, 4, 5];

我们把它反过来,也就是变成:

ts
type arr = [5, 4, 3, 2, 1];

这个学完了提取和构造很容易写出来:

ts
type ReverseArr<Arr extends unknown[]> = Arr extends [infer One, infer Two, infer Three, infer Four, infer Five]
+  ? [Five, Four, Three, Two, One]
+  : never;

但如果数组长度不确定呢?

数量不确定,条件反射的就要想到递归。

我们每次只处理一个类型,剩下的递归做,直到满足结束条件。

ts
type ReverseArr<Arr extends unknown[]> = Arr extends [infer First, ...infer Rest] ? [...ReverseArr<Rest>, First] : Arr;

类型参数 Arr 为待处理的数组类型,元素类型不确定,也就是 unknown。

每次只处理一个元素的提取,放到 infer 声明的局部变量 First 里,剩下的放到 Rest 里。

用 First 作为最后一个元素构造新数组,其余元素递归的取。

结束条件就是取完所有的元素,也就是不再满足模式匹配的条件,这时候就返回 Arr。

Includes

既然递归可以做循环用,那么像查找元素这种自然也就可以实现。

比如查找 [1, 2, 3, 4, 5] 中是否存在 4,是就返回 true,否则返回 false。

从长度不固定的数组中查找某个元素,数量不确定,这时候就应该想到递归。

ts
type Includes<Arr extends unknown[], FindItem> = Arr extends [infer First, ...infer Rest]
+  ? IsEqual<First, FindItem> extends true
+    ? true
+    : Includes<Rest, FindItem>
+  : false;
+
+type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

类型参数 Arr 是待查找的数组类型,元素类型任意,也就是 unknown。FindItem 待查找的元素类型。

每次提取一个元素到 infer 声明的局部变量 First 中,剩余的放到局部变量 Rest。

判断 First 是否是要查找的元素,也就是和 FindItem 相等,是的话就返回 true,否则继续递归判断下一个元素。

直到结束条件也就是提取不出下一个元素,这时返回 false。

相等的判断就是 A 是 B 的子类型并且 B 也是 A 的子类型,。

这样就完成了不确定长度的数组中的元素查找,用递归实现了循环。

RemoveItem

可以查找自然就可以删除,只需要改下返回结果,构造一个新的数组返回。

ts
type RemoveItem<Arr extends unknown[], Item, Result extends unknown[] = []> = Arr extends [infer First, ...infer Rest]
+  ? IsEqual<First, Item> extends true
+    ? RemoveItem<Rest, Item, Result>
+    : RemoveItem<Rest, Item, [...Result, First]>
+  : Result;
+
+type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

类型参数 Arr 是待处理的数组,元素类型任意,也就是 unknown[]。类型参数 Item 为待查找的元素类型。类型参数 Result 是构造出的新数组,默认值是 []。

通过模式匹配提取数组中的一个元素的类型,如果是 Item 类型的话就删除,也就是不放入构造的新数组,直接返回之前的 Result。

否则放入构造的新数组,也就是再构造一个新的数组 [...Result, First]。

直到模式匹配不再满足,也就是处理完了所有的元素,返回这时候的 Result。

这样我们就完成了不确定元素个数的数组的某个元素的删除:

BuildArray

我们学过数组类型的构造,如果构造的数组类型元素个数不确定,也需要递归。

比如传入 5 和元素类型,构造一个长度为 5 的该元素类型构成的数组。

ts
type BuildArray<Length extends number, Ele = unknown, Arr extends unknown[] = []> = Arr['length'] extends Length
+  ? Arr
+  : BuildArray<Length, Ele, [...Arr, Ele]>;

类型参数 Length 为数组长度,约束为 number。类型参数 Ele 为元素类型,默认值为 unknown。类型参数 Arr 为构造出的数组,默认值是 []。

每次判断下 Arr 的长度是否到了 Length,是的话就返回 Arr,否则在 Arr 上加一个元素,然后递归构造。

学完了数组类型的递归,我们再来看下字符串类型。

字符串类型的递归

ReplaceAll

学模式匹配的时候,我们实现过一个 Replace 的高级类型:

ts
type ReplaceStr<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends \`\${infer Prefix}\${From}\${infer Suffix}\` ? \`\${Prefix}\${To}\${Suffix}\` : Str;

它能把一个字符串中的某个字符替换成另一个:

但是如果有多个这样的字符就处理不了了。

如果不确定有多少个 From 字符,怎么处理呢?

在类型体操里,遇到数量不确定的问题,就要条件反射的想到递归。

每次递归只处理一个类型,这部分我们已经实现了,那么加上递归的调用就可以。

ts
type ReplaceAll<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends \`\${infer Left}\${From}\${infer Right}\` ? \`\${Left}\${To}\${ReplaceAll<Right, From, To>}\` : Str;

类型参数 Str 是待处理的字符串类型,From 是待替换的字符,To 是替换到的字符。

通过模式匹配提取 From 左右的字符串到 infer 声明的局部变量 Left 和 Right 里。

用 Left 和 To 构造新的字符串,剩余的 Right 部分继续递归的替换。

结束条件是不再满足模式匹配,也就是没有要替换的元素,这时就直接返回字符串 Str。

这样就实现了任意数量的字符串替换:

StringToUnion

我们想把字符串字面量类型的每个字符都提取出来组成联合类型,也就是把 'dong' 转为 'd' | 'o' | 'n' | 'g'。

怎么做呢?

很明显也是提取和构造:

ts
type StringToUnion<Str extends string> = Str extends \`\${infer One}\${infer Two}\${infer Three}\${infer Four}\`
+  ? One | Two | Three | Four
+  : never;

但如果字符串长度不确定呢?

数量不确定,在类型体操中就要条件反射的想到递归。

ts
type StringToUnion<Str extends string> = Str extends \`\${infer First}\${infer Rest}\`
+  ? First | StringToUnion<Rest>
+  : never;

类型参数 Str 为待处理的字符串类型,通过 extends 约束为 string。

通过模式匹配提取第一个字符到 infer 声明的局部变量 First,其余的字符放到局部变量 Rest。

用 First 构造联合类型,剩余的元素递归的取。

这样就完成了不确定长度的字符串的提取和联合类型的构造:

ReverseStr

我们实现了数组的反转,自然也可以实现字符串类型的反转。

同样是递归提取和构造。

ts
type ReverseStr<Str extends string, Result extends string = ''> = Str extends \`\${infer First}\${infer Rest}\`
+  ? ReverseStr<Rest, \`\${First}\${Result}\`>
+  : Result;

类型参数 Str 为待处理的字符串。类型参数 Result 为构造出的字符,默认值是空串。

通过模式匹配提取第一个字符到 infer 声明的局部变量 First,其余字符放到 Rest。

用 First 和之前的 Result 构造成新的字符串,把 First 放到前面,因为递归是从左到右处理,那么不断往前插就是把右边的放到了左边,完成了反转的效果。

直到模式匹配不满足,就处理完了所有的字符。

这样就完成了字符串的反转:

对象类型的递归

DeepReadonly

对象类型的递归,也可以叫做索引类型的递归。

我们之前实现了索引类型的映射,给索引加上了 readonly 的修饰:

ts
type ToReadonly<T> = {
+  readonly [Key in keyof T]: T[Key];
+};

如果这个索引类型层数不确定呢?

比如这样:

ts
type obj = {
+  a: {
+    b: {
+      c: {
+        f: () => 'dong';
+        d: {
+          e: {
+            guang: string;
+          };
+        };
+      };
+    };
+  };
+};

数量(层数)不确定,类型体操中应该自然的想到递归。

我们在之前的映射上加入递归的逻辑:

ts
type DeepReadonly<Obj extends Record<string, any>> = {
+  readonly [Key in keyof Obj]: Obj[Key] extends object
+    ? Obj[Key] extends Function
+      ? Obj[Key]
+      : DeepReadonly<Obj[Key]>
+    : Obj[Key];
+};

类型参数 Obj 是待处理的索引类型,约束为 Record<string, any>,也就是索引为 string,值为任意类型的索引类型。

索引映射自之前的索引,也就是 Key in keyof Obj,只不过加上了 readonly 的修饰。

值要做下判断,如果是 object 类型并且还是 Function,那么就直接取之前的值 Obj[Key]。

如果是 object 类型但不是 Function,那就是说也是一个索引类型,就递归处理 DeepReadonly<Obj[Key]>。

否则,值不是 object 就直接返回之前的值 Obj[Key]。

这样就完成了任意层数的索引类型的添加 readonly 修饰:

我们取处理以后的索引 a 的值看一下,发现 b 已经加上了 readonly 修饰。

测试一下:

为啥这里没有计算呀?

因为 ts 的类型只有被用到的时候才会做计算。

所以可以在前面加上一段 Obj extends never ? never 或者 Obj extends any 等,从而触发计算:

ts
type DeepReadonly<Obj extends Record<string, any>> = Obj extends any
+  ? {
+      readonly [Key in keyof Obj]: Obj[Key] extends object
+        ? Obj[Key] extends Function
+          ? Obj[Key]
+          : DeepReadonly<Obj[Key]>
+        : Obj[Key];
+    }
+  : never;
`,123)]))}const F=i(n,[["render",t]]);export{E as __pageData,F as default}; diff --git a/assets/cn_src_article_typescript_unionType.md.BTONe5Yt.js b/assets/cn_src_article_typescript_unionType.md.BTONe5Yt.js new file mode 100644 index 0000000000..0b2f106323 --- /dev/null +++ b/assets/cn_src_article_typescript_unionType.md.BTONe5Yt.js @@ -0,0 +1 @@ +import{_ as i,o as a,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"分布式条件类型","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/typescript/unionType.md","filePath":"cn/src/article/typescript/unionType.md","lastUpdated":1726550590000}'),k={name:"cn/src/article/typescript/unionType.md"};function n(p,s,l,e,d,r){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

分布式条件类型

当类型参数为联合类型,并且在条件类型左边直接引用该类型参数的时候,TypeScript 会把每一个元素单独传入来做类型运算,最后再合并成联合类型,这种语法叫做分布式条件类型。

比如这样一个联合类型:

ts
type Union = 'a' | 'b' | 'c';

我们想把其中的 a 大写,就可以这样写:

ts
type UppercaseA<Item extends string> = Item extends 'a' ? Uppercase<Item> : Item;
ts
type result = UppercaseA<Union>;\n// type result = 'A' | 'b' | 'c';

可以看到,我们类型参数 Item 约束为 string,条件类型的判断中也是判断是否是 a,但传入的是联合类型。

这就是 TypeScript 对联合类型在条件类型中使用时的特殊处理:会把联合类型的每一个元素单独传入做类型计算,最后合并。

这和联合类型遇到字符串时的处理一样:

这样确实是简化了类型编程逻辑的,不需要递归提取每个元素再处理。

TypeScript 之所以这样处理联合类型也很容易理解,因为联合类型的每个元素都是互不相关的,不像数组、索引、字符串那样元素之间是有关系的。所以设计成了每一个单独处理,最后合并。

知道了 TypeScript 怎么处理的联合类型,趁热打铁来练习一下:

CamelcaseUnion

Camelcase 我们实现过,就是提取字符串中的字符,首字母大写以后重新构造一个新的。

ts
type Camelcase<Str extends string> = Str extends `${infer Left}_${infer Right}${infer Rest}`\n  ? `${Left}${Uppercase<Right>}${Camelcase<Rest>}`\n  : Str;

提取 _ 左右的字符,把右边字符大写之后构造成新的字符串,余下的字符串递归处理。

ts
type CamelcaseResult = Camelcase<'aa_aa_aa'>;\n// type CamelcaseResult = 'aaAaAa'

如果是对字符串数组做 Camelcase,那就要递归处理每一个元素:

ts
type CamelcaseArr<Arr extends unknown[]> = Arr extends [infer Item, ...infer RestArr]\n  ? [Camelcase<Item & string>, ...CamelcaseArr<RestArr>]\n  : [];

类型参数 Arr 为待处理数组。

递归提取每一个元素做 Camelcase,因为 Camelcase 要求传入 string,这里要 & string 来变成 string 类型。

那如果是联合类型呢?

联合类型不需要递归提取每个元素,TypeScript 内部会把每一个元素传入单独做计算,之后把每个元素的计算结果合并成联合类型。

ts
type CamelcaseUnion<Item extends string> = Item extends `${infer Left}_${infer Right}${infer Rest}`\n  ? `${Left}${Uppercase<Right>}${CamelcaseUnion<Rest>}`\n  : Item;

这不和单个字符串的处理没区别么?

没错,对联合类型的处理和对单个类型的处理没什么区别,TypeScript 会把每个单独的类型拆开传入。不需要像数组类型那样需要递归提取每个元素做处理。

确实简化了很多,好像都是优点?

也不全是,其实这样处理也增加了一些认知成本,不信我们再来看个例子:

IsUnion

判断联合类型我们会这样写:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

当传入联合类型时,会返回 true:

ts
type IsUnionResult = IsUnion<'a' | 'b' 'c'>\n// type IsUnionResult = true

当传入其他类型时,会返回 false:

ts
type IsUnionResult = IsUnion<['a' | 'b' 'c']>\n// type IsUnionResult = false

这就是分布式条件类型带来的认知成本。

我们先来看这样一个类型:

ts
type TestUnion<A, B = A> = A extends A ? { a: A; b: B } : never;\n\ntype TestUnionResult = TestUnion<'a' | 'b' | 'c'>;

传入联合类型 'a' | 'b' | 'c' 的时候,结果是这样的:

A 和 B 都是同一个联合类型,为啥值还不一样呢?

因为条件类型中如果左边的类型是联合类型,会把每个元素单独传入做计算,而右边不会。

所以 A 是 'a' 的时候,B 是 'a' | 'b' | 'c', A 是 'b' 的时候,B 是 'a' | 'b' | 'c'。。。

那么利用这个特点就可以实现 Union 类型的判断:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

类型参数 A、B 是待判断的联合类型,B 默认值为 A,也就是同一个类型。

A extends A 这段看似没啥意义,主要是为了触发分布式条件类型,让 A 的每个类型单独传入。

[B] extends [A] 这样不直接写 B 就可以避免触发分布式条件类型,那么 B 就是整个联合类型。

B 是联合类型整体,而 A 是单个类型,自然不成立,而其它类型没有这种特殊处理,A 和 B 都是同一个,怎么判断都成立。

利用这个特点就可以判断出是否是联合类型。

其中有两个点比较困惑,我们重点记一下:

当 A 是联合类型时:

A extends A 这种写法是为了触发分布式条件类型,让每个类型单独传入处理的,没别的意义。

A extends A 和 [A] extends [A] 是不同的处理,前者是单个类型和整个类型做判断,后者两边都是整个联合类型,因为只有 extends 左边直接是类型参数才会触发分布式条件类型。

理解了这两点,分布式条件类型就算掌握了。

BEM

bem 是 css 命名规范,用 block__element--modifier 的形式来描述某个区块下面的某个元素的某个状态的样式。

那么我们可以写这样一个高级类型,传入 block、element、modifier,返回构造出的 class 名:

这样使用:

ts
type bemResult = BEM<'guang', ['aaa', 'bbb'], ['warning', 'success']>;

它的实现就是三部分的合并,但传入的是数组,要递归遍历取出每一个元素来和其他部分组合,这样太麻烦了。

而如果是联合类型就不用递归遍历了,因为联合类型遇到字符串也是会单独每个元素单独传入做处理。

数组转联合类型可以这样写:

ts
type union = ['aaa', 'bbb'][number];\n// type union = 'aaa' | 'bbb'

那么 BEM 就可以这样实现:

ts
type BEM<\n  Block extends string,\n  Element extends string[],\n  Modifiers extends string[],\n> = `${Block}__${Element[number]}--${Modifiers[number]}`;

类型参数 Block、Element、Modifiers 分别是 bem 规范的三部分,其中 Element 和 Modifiers 都可能多个,约束为 string[]。

构造一个字符串类型,其中 Element 和 Modifiers 通过索引访问来变为联合类型。

字符串类型中遇到联合类型的时候,会每个元素单独传入计算,也就是这样的效果:

ts
type RemResult = BEM<'a', ['b', 'c'], ['d', 'e']>;\n// type RemResult = 'a__b--d' | 'a__b--e' | 'a__c--d' | 'a__b--e'

可以看到,用好了联合类型,确实能简化类型编程逻辑。

AllCombinations

我们再来实现一个全组合的高级类型,也是联合类型相关的:

希望传入 'A' | 'B' 的时候,能够返回所有的组合: 'A' | 'B' | 'BA' | 'AB'。

这种全组合问题的实现思路就是两两组合,组合出的字符串再和其他字符串两两组和:

比如 'A' | 'B' | 'c',就是 A 和 B、C 组合,B 和 A、C 组合,C 和 A、B 组合。然后组合出来的字符串再和其他字符串组合。

任何两个类型的组合有四种:A、B、AB、BA

ts
type Combination<A extends string, B extends string> = A | B | `${A}${B}` | `${B}${A}`;

然后构造出来的字符串再和其他字符串组合。

所以全组合的高级类型就是这样:

ts
type AllCombinations<A extends string, B extends string = A> = A extends A\n  ? Combination<A, AllCombinations<Exclude<B, A>>>\n  : never;

类型参数 A、B 是待组合的两个联合类型,B 默认是 A 也就是同一个。

A extends A 的意义就是让联合类型每个类型单独传入做处理,上面我们刚学会。

A 的处理就是 A 和 B 中去掉 A 以后的所有类型组合,也就是 Combination<A, B 去掉 A 以后的所有组合>。

而 B 去掉 A 以后的所有组合就是 AllCombinations<Exclude<B, A>>,所以全组合就是 Combination<A, AllCombinations<Exclude<B, A>>>。

总结

联合类型中的每个类型都是相互独立的,TypeScript 对它做了特殊处理,也就是遇到字符串类型、条件类型的时候会把每个类型单独传入做计算,最后把每个类型的计算结果合并成联合类型。

条件类型左边是联合类型的时候就会触法这种处理,叫做分布式条件类型。

有两点特别要注意:

  • A extends A 不是没意义,意义是取出联合类型中的单个类型放入 A

  • A extends A 才是分布式条件类型, [A] extends [A] 就不是了,只有左边是单独的类型参数才可以。

我们后面做了一些案例,发现联合类型的这种 distributive 的特性确实能简化类型编程,但是也增加了认知成本,不过这也是不可避免的事。

',91)]))}const y=i(k,[["render",n]]);export{F as __pageData,y as default}; diff --git a/assets/cn_src_article_typescript_unionType.md.BTONe5Yt.lean.js b/assets/cn_src_article_typescript_unionType.md.BTONe5Yt.lean.js new file mode 100644 index 0000000000..0b2f106323 --- /dev/null +++ b/assets/cn_src_article_typescript_unionType.md.BTONe5Yt.lean.js @@ -0,0 +1 @@ +import{_ as i,o as a,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"分布式条件类型","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/typescript/unionType.md","filePath":"cn/src/article/typescript/unionType.md","lastUpdated":1726550590000}'),k={name:"cn/src/article/typescript/unionType.md"};function n(p,s,l,e,d,r){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

分布式条件类型

当类型参数为联合类型,并且在条件类型左边直接引用该类型参数的时候,TypeScript 会把每一个元素单独传入来做类型运算,最后再合并成联合类型,这种语法叫做分布式条件类型。

比如这样一个联合类型:

ts
type Union = 'a' | 'b' | 'c';

我们想把其中的 a 大写,就可以这样写:

ts
type UppercaseA<Item extends string> = Item extends 'a' ? Uppercase<Item> : Item;
ts
type result = UppercaseA<Union>;\n// type result = 'A' | 'b' | 'c';

可以看到,我们类型参数 Item 约束为 string,条件类型的判断中也是判断是否是 a,但传入的是联合类型。

这就是 TypeScript 对联合类型在条件类型中使用时的特殊处理:会把联合类型的每一个元素单独传入做类型计算,最后合并。

这和联合类型遇到字符串时的处理一样:

这样确实是简化了类型编程逻辑的,不需要递归提取每个元素再处理。

TypeScript 之所以这样处理联合类型也很容易理解,因为联合类型的每个元素都是互不相关的,不像数组、索引、字符串那样元素之间是有关系的。所以设计成了每一个单独处理,最后合并。

知道了 TypeScript 怎么处理的联合类型,趁热打铁来练习一下:

CamelcaseUnion

Camelcase 我们实现过,就是提取字符串中的字符,首字母大写以后重新构造一个新的。

ts
type Camelcase<Str extends string> = Str extends `${infer Left}_${infer Right}${infer Rest}`\n  ? `${Left}${Uppercase<Right>}${Camelcase<Rest>}`\n  : Str;

提取 _ 左右的字符,把右边字符大写之后构造成新的字符串,余下的字符串递归处理。

ts
type CamelcaseResult = Camelcase<'aa_aa_aa'>;\n// type CamelcaseResult = 'aaAaAa'

如果是对字符串数组做 Camelcase,那就要递归处理每一个元素:

ts
type CamelcaseArr<Arr extends unknown[]> = Arr extends [infer Item, ...infer RestArr]\n  ? [Camelcase<Item & string>, ...CamelcaseArr<RestArr>]\n  : [];

类型参数 Arr 为待处理数组。

递归提取每一个元素做 Camelcase,因为 Camelcase 要求传入 string,这里要 & string 来变成 string 类型。

那如果是联合类型呢?

联合类型不需要递归提取每个元素,TypeScript 内部会把每一个元素传入单独做计算,之后把每个元素的计算结果合并成联合类型。

ts
type CamelcaseUnion<Item extends string> = Item extends `${infer Left}_${infer Right}${infer Rest}`\n  ? `${Left}${Uppercase<Right>}${CamelcaseUnion<Rest>}`\n  : Item;

这不和单个字符串的处理没区别么?

没错,对联合类型的处理和对单个类型的处理没什么区别,TypeScript 会把每个单独的类型拆开传入。不需要像数组类型那样需要递归提取每个元素做处理。

确实简化了很多,好像都是优点?

也不全是,其实这样处理也增加了一些认知成本,不信我们再来看个例子:

IsUnion

判断联合类型我们会这样写:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

当传入联合类型时,会返回 true:

ts
type IsUnionResult = IsUnion<'a' | 'b' 'c'>\n// type IsUnionResult = true

当传入其他类型时,会返回 false:

ts
type IsUnionResult = IsUnion<['a' | 'b' 'c']>\n// type IsUnionResult = false

这就是分布式条件类型带来的认知成本。

我们先来看这样一个类型:

ts
type TestUnion<A, B = A> = A extends A ? { a: A; b: B } : never;\n\ntype TestUnionResult = TestUnion<'a' | 'b' | 'c'>;

传入联合类型 'a' | 'b' | 'c' 的时候,结果是这样的:

A 和 B 都是同一个联合类型,为啥值还不一样呢?

因为条件类型中如果左边的类型是联合类型,会把每个元素单独传入做计算,而右边不会。

所以 A 是 'a' 的时候,B 是 'a' | 'b' | 'c', A 是 'b' 的时候,B 是 'a' | 'b' | 'c'。。。

那么利用这个特点就可以实现 Union 类型的判断:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

类型参数 A、B 是待判断的联合类型,B 默认值为 A,也就是同一个类型。

A extends A 这段看似没啥意义,主要是为了触发分布式条件类型,让 A 的每个类型单独传入。

[B] extends [A] 这样不直接写 B 就可以避免触发分布式条件类型,那么 B 就是整个联合类型。

B 是联合类型整体,而 A 是单个类型,自然不成立,而其它类型没有这种特殊处理,A 和 B 都是同一个,怎么判断都成立。

利用这个特点就可以判断出是否是联合类型。

其中有两个点比较困惑,我们重点记一下:

当 A 是联合类型时:

A extends A 这种写法是为了触发分布式条件类型,让每个类型单独传入处理的,没别的意义。

A extends A 和 [A] extends [A] 是不同的处理,前者是单个类型和整个类型做判断,后者两边都是整个联合类型,因为只有 extends 左边直接是类型参数才会触发分布式条件类型。

理解了这两点,分布式条件类型就算掌握了。

BEM

bem 是 css 命名规范,用 block__element--modifier 的形式来描述某个区块下面的某个元素的某个状态的样式。

那么我们可以写这样一个高级类型,传入 block、element、modifier,返回构造出的 class 名:

这样使用:

ts
type bemResult = BEM<'guang', ['aaa', 'bbb'], ['warning', 'success']>;

它的实现就是三部分的合并,但传入的是数组,要递归遍历取出每一个元素来和其他部分组合,这样太麻烦了。

而如果是联合类型就不用递归遍历了,因为联合类型遇到字符串也是会单独每个元素单独传入做处理。

数组转联合类型可以这样写:

ts
type union = ['aaa', 'bbb'][number];\n// type union = 'aaa' | 'bbb'

那么 BEM 就可以这样实现:

ts
type BEM<\n  Block extends string,\n  Element extends string[],\n  Modifiers extends string[],\n> = `${Block}__${Element[number]}--${Modifiers[number]}`;

类型参数 Block、Element、Modifiers 分别是 bem 规范的三部分,其中 Element 和 Modifiers 都可能多个,约束为 string[]。

构造一个字符串类型,其中 Element 和 Modifiers 通过索引访问来变为联合类型。

字符串类型中遇到联合类型的时候,会每个元素单独传入计算,也就是这样的效果:

ts
type RemResult = BEM<'a', ['b', 'c'], ['d', 'e']>;\n// type RemResult = 'a__b--d' | 'a__b--e' | 'a__c--d' | 'a__b--e'

可以看到,用好了联合类型,确实能简化类型编程逻辑。

AllCombinations

我们再来实现一个全组合的高级类型,也是联合类型相关的:

希望传入 'A' | 'B' 的时候,能够返回所有的组合: 'A' | 'B' | 'BA' | 'AB'。

这种全组合问题的实现思路就是两两组合,组合出的字符串再和其他字符串两两组和:

比如 'A' | 'B' | 'c',就是 A 和 B、C 组合,B 和 A、C 组合,C 和 A、B 组合。然后组合出来的字符串再和其他字符串组合。

任何两个类型的组合有四种:A、B、AB、BA

ts
type Combination<A extends string, B extends string> = A | B | `${A}${B}` | `${B}${A}`;

然后构造出来的字符串再和其他字符串组合。

所以全组合的高级类型就是这样:

ts
type AllCombinations<A extends string, B extends string = A> = A extends A\n  ? Combination<A, AllCombinations<Exclude<B, A>>>\n  : never;

类型参数 A、B 是待组合的两个联合类型,B 默认是 A 也就是同一个。

A extends A 的意义就是让联合类型每个类型单独传入做处理,上面我们刚学会。

A 的处理就是 A 和 B 中去掉 A 以后的所有类型组合,也就是 Combination<A, B 去掉 A 以后的所有组合>。

而 B 去掉 A 以后的所有组合就是 AllCombinations<Exclude<B, A>>,所以全组合就是 Combination<A, AllCombinations<Exclude<B, A>>>。

总结

联合类型中的每个类型都是相互独立的,TypeScript 对它做了特殊处理,也就是遇到字符串类型、条件类型的时候会把每个类型单独传入做计算,最后把每个类型的计算结果合并成联合类型。

条件类型左边是联合类型的时候就会触法这种处理,叫做分布式条件类型。

有两点特别要注意:

  • A extends A 不是没意义,意义是取出联合类型中的单个类型放入 A

  • A extends A 才是分布式条件类型, [A] extends [A] 就不是了,只有左边是单独的类型参数才可以。

我们后面做了一些案例,发现联合类型的这种 distributive 的特性确实能简化类型编程,但是也增加了认知成本,不过这也是不可避免的事。

',91)]))}const y=i(k,[["render",n]]);export{F as __pageData,y as default}; diff --git a/assets/cn_src_article_video.md.Dw4RU8dr.js b/assets/cn_src_article_video.md.Dw4RU8dr.js new file mode 100644 index 0000000000..42fa754961 --- /dev/null +++ b/assets/cn_src_article_video.md.Dw4RU8dr.js @@ -0,0 +1,285 @@ +import{_ as i,o as a,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const t="/ran/assets/bilibili_video_code.DgWtgAEf.webp",p="/ran/assets/bili_demo_url.BQDGtHUp.webp",l="/ran/assets/bilibili_video_m4s.BccuY7bk.webp",k="/ran/assets/aqiyi_demo.s0swGzvF.webp",e="/ran/assets/tiktok_video.DuwKyIdt.webp",d="/ran/assets/tiktik_video_demo.mxxBzLay.webp",E="/ran/assets/red_book.DiBEvryP.webp",r="/ran/assets/safari_support_media.Bafr23bR.webp",g="/ran/assets/firefox_support_media.BLmSeBNy.webp",o="/ran/assets/ms_support.CaZSSiRt.webp",c="/ran/assets/ts_demo.D_l_mv9k.webp",y="/ran/assets/video_format.CRMCTmKB.webp",F="/ran/assets/xgplayer_docs.CpHb1Wan.webp",C="/ran/assets/bili_demo.CI8Ur8IA.webp",u="/ran/assets/rplayer_demo.CoJ7kuJt.webp",x=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/video.md","filePath":"cn/src/article/video.md","lastUpdated":1726550590000}'),B={name:"cn/src/article/video.md"};function m(A,s,b,v,D,f){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h('

实现自适应码率 Web 视频加密播放:前后端的挑战与解决方案

最近又遇到了web视频化的场景,之前也有过调研:H5 视频化调研浅析

但这次稍微复杂一些,这次解决的是:

  1. 视频播放的技术方案调研

服务端实现:

  1. 视频转码
  2. 生成不同码率的视频
  3. 进行视频标准加密
  4. 不同码率视频合并,用于动态码率播放

web端实现

  1. web端播放器的设计
  2. web端播放器的自定义扩展
  3. 可拖拽进度条
  4. 音量控制
  5. 根据当前带宽自适应码率切换
  6. 手动清晰度切换
  7. 倍速播放
  8. 样式自定义覆盖
  9. 标准加密视频播放
  10. 基于原生开发,可在所有框架运行,统一跨框架情况
  11. 各浏览器控件统一

其中web端源码已添加MIT协议并完全开源,如果看完对大家有帮助的话,欢迎大家star,issue,pr,也希望能友好交流~

demo 地址:https://chaxus.github.io/ran/src/ranui/player/

源码地址:https://github.com/chaxus/ran

demo文档做了国际化,可切换到中文

任何一个项目,立项肯定先是技术调研,我们先看看一些大公司的视频播放方案

一:一些知名公司的 web 视频播放方案

1.B 站

我们先看看 B 站的,毕竟 B 站的主营业务就是视频弹幕网站,简直专业对口。

先找一个例子:https://www.bilibili.com/video/BV1FM411N7LJ 访问它。

image.png

打开控制台,可以看到,视频在播放的时候,会不断的请求m4s的视频文件。

毕竟一整个视频文件往往比较大,不可能先请求完视频文件,再进行播放。因此将一个大的视频文件分割成很多小的片段,边加载边播放,是一种更好的方式。

image.png

每次请求的m4s文件大概在几十kb到几百kb不等。

image.png

那为什么不采用httprange呢,可以请求一个文件的部分内容,而且粒度更细,可以设置字节范围。在http请求的header中,类似这样

js
Range: bytes = 3171375 - 3203867;

我们可以检查这个链接请求https://upos-sz-mirror08c.bilivideo.com/upgcxcode/67/92/1008149267/1008149267-1-30064.m4s的请求头,就能发现,B 站采用的是,即分片加载,同时还用了range的方式。

2. 爱奇艺:(爱奇艺、土豆、优酷)

爱奇艺这里就不贴视频链接了,因为随便点一个视频,都要先看广告。

image.png

爱奇艺的视频主要请求的是f4v格式,也是分片加载。

播放一个视频时,请求多个f4v文件。

也采用Range。但和 B 站不一样的是,B 站的Range属性是在m4s请求的请求头里面,而爱奇艺的看起来是在querystring上,在请求query上带着range参数。

因为没发现这个请求的header里面有range参数。比如:

https://v-6fce1712.71edge.com/videos/other/20231113/6b/bb/3f3fe83b89124248c3216156dfe2f4c3.f4v?dis_k=2ba39ee8c55c4d23781e3fb9f91fa7a46&dis_t=1701439831&dis_dz=CNC-BeiJing&dis_st=46&src=iqiyi.com&dis_hit=0&dis_tag=01010000&uuid=72713f52-6569e957-351&cross-domain=1&ssl=1&pv=0.1&cphc=arta&range=0-9000

3.抖音:

抖音的方案简单粗暴,访问的链接是这个: https://m.ixigua.com/douyin/share/video/7206914252840370721?aweme_type=107&schema_type=1&utm_source=copy&utm_campaign=client_share&utm_medium=android&app=aweme

通过查看控制台,我们可以发现,直接请求了一个视频的地址

image.png

没有进行分片,但用到了请求range,所以可以看到视频,是边播放边缓冲一部分。

不过我在开发的时候发现,目前租用的服务云厂商,默认会帮我们实现这项技术。

因为我把mp4视频上传到云服务器,通过链接进行播放的时候,就是边缓冲边播放的。

我们可以直接把这个视频地址拿出来,放到浏览器里面能直接播放,这样观察更明显。

image.png

但 B 站和爱奇艺却不能这样,因为他们采用的m4sf4v都不是一种通用的视频格式,需要使用专门的软件或工具才能打开和编辑。

4.小红书:

测试用的例子链接:https://www.xiaohongshu.com/discovery/item/63b286d1000000001f00b495

小红书的方案更加简单粗暴,打开控制台,直接告诉你就是请求一个mp4,然后直接播放就完事了。

image.png

5.总结

看完了以上的各家大厂的方案,我们可以看到,基本原理都是边播放边加载,减少直接加载大视频文本的成本。并且通过分片传输,还能动态控制视频码率(清晰度)。做到根据网速,加载不同码率的分片文件,做到动态码率适应。

同时采用的视频格式,比如f4vm4s,都不是能直接播放的媒体格式,需要一定的处理。增加盗取视频的成本,增加一定的安全性。

如果没有强要求,也可以直接采用mp4,或者直接用video播放一个视频文件地址。

二:常见的视频格式与协议

我们知道视频的常见格式有mp4,同时上面介绍了 B 站播放用的m4s格式,爱奇艺用的f4v格式

  • 除了这些还有哪些视频格式?
  • 为什么有这么多视频格式,有哪些不同点呢?
  • 为什么这些公司会采用这种格式来播放视频呢?

1. B 站用的m4s

M4S格式不是一种通用的视频格式,需要使用专门的软件或工具才能打开和编辑。

M4S 通常会和 MPEG-DASH 流媒体技术一起,通过流式传输的视频的一小部分。播放器会按接收顺序播放这些片段。第一个 M4S 段会包含一些初始化的数据标识。

MPEG-DASH 是一种自适应比特率流媒体技术,通过将内容分解为一系列不同码率的M4S片段,然后根据当前网络带宽进行自动调整。如果想在在web音视频中采用DASH技术,可以看下 https://github.com/Dash-Industry-Forum/dash.js

2. 爱奇艺的f4v

F4V是一种流媒体格式,它是由Adobe公司推出的,继FLV格式之后支持H.264编码的流媒体格式。F4V格式的视频不是一种通用的视频格式,但通常情况下,都可以将文件后缀改为FLV,这样就可以使用支持FLV的播放器进行观看。

FLV格式跟常见的MP4格式比起来,结构更加简单,所以加载metadata(视频元数据,比如视频时长等信息) 会更快。具体结构我们可以在这里查到:https://en.wikipedia.org/wiki/Flash_Video#Flash_Video_Structure

比如,这是FLV文件的标准头,定义了从几个比特到几个比特之间,是什么含义。我们知道后,可以用MediaSource进行读取和转码。

FieldData TypeDefaultDetails
Signature 签名byte[3]"FLV"始终就是“FLV”
Version 版本uint81只有 0x01 才有效
Flags 标志uint8 位掩码0x050x04 是音频,0x01 是视频(所以 0x05 是音频 + 视频)
Header Sizeuint32_be9用于跳过较新的扩展标头

MP4格式会稍微复杂一些,具体标准在 ISO/IEC 14496-12 大概有两百多页,这里放不下,对这方面有兴趣的可以自行查看。

然而这并不表示MP4更差,因为它是一种基础通用标准,所以定义上会留有很多空间,和各种情况,甚至允许在标准之内进行自行发挥和扩展。而FLV格式则更加固定,但优点也是更加简单。

对于FLV的视频播放,我们可以采用:https://github.com/bilibili/flv.js flvjs主要作用就是用MediaSourceflv转码成mp4从而喂给浏览器进行播放。

接下来是一些其他的视频格式,简单介绍一下:

3.AVI

文件名以.avi结尾,AVI 最初由 Microsoft1992 年开发,是 Windows 的标准视频格式。AVI 文件使用较少的压缩来存储文件,并且比许多其他视频格式占用更多空间,这导致文件大小非常大,每分钟视频大约 2-3 GB

无损文件不会随着时间的推移而降低质量,无论您打开或保存文件多少次。此外,这允许在不使用任何编解码器的情况下播放。参考资料:Audio Video Interleave

4.MPEG

文件名以“.mpg”或“.mpeg”结尾,MPEG 是由 ISO 和 IEC 联合成立的工作组联盟,旨在制定媒体编码标准,包括音频、视频、图形和基因组数据的压缩编码;以及各种应用程序的传输和文件格式。MPEG 格式用于各种多媒体系统。最广为人知的旧 MPEG 媒体格式通常使用 MPEG-1、MPEG-2 和 MPEG-4 AVC 媒体编码,MPEG-2 系统传输流和节目流。较新的系统通常使用 MPEG 基本媒体文件格式和动态流式处理(又名 .MPEG-DASH)。参考资料:Moving Picture Experts Group

5.MP4

带有音频和视频的 MPEG-4 文件通常使用标准的 .mp4 扩展名。纯音频 MPEG-4 文件通常具有 .m4a 扩展名,原始 MPEG-4 可视比特流命名为 .m4v。Apple iPhone 使用 MPEG-4 音频作为其铃声,但使用.m4r 扩展名而不是.m4a 扩展名。参考资料:MPEG-4 Part 14

6.QuickTime

文件名以“.mov”结尾,QuickTime 能够包含媒体数据的抽象数据引用,并将媒体数据与媒体偏移和轨道编辑列表分离,这意味着 QuickTime 特别适合编辑,因为它能够就地导入和编辑(无需数据复制)。由于 QuickTime 和 MP4 容器格式都可以使用相同的 MPEG-4 格式,因此在仅限 QuickTime 的环境中,它们大多可以互换。MP4 作为国际标准,得到了更多的支持。参考资料:QuickTime File Format

7.TS

TS 是 MPEG2-TS 的简称,是一种音视频封装格式。TS 流的后缀通常是.ts、.mpg 或者.mpeg,多数播放器直接支持这种格式的播放。TS 格式主要用于直播的码流结构,具有很好的容错能力。

三:浏览器对各种视频格式的兼容性

上面了解常用的视频格式,和适用范围之后,还需要看一下当前浏览器,对各种视频格式的支持程度,然后制定技术方案。

1. Chrome

支持的视频格式从官方文档可以查到,主要有以下这些

  • MP4 (QuickTime/ MOV / ISO-BMFF / CMAF)
  • Ogg
  • WebM
  • WAV
  • HLS [Only on Android and only single-origin manifests]

官方文档如下:https://www.chromium.org/audio-video/

2. Safari

支持的视频格式有这些:

image.png

官方文档:https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html

3.Firefox

支持的视频格式:

image.png

官方文档:https://support.mozilla.org/en-US/kb/html5-audio-and-video-firefox

四:MediaSource 和视频编码,解码,封装介绍

上面介绍了一些视频格式,和目前浏览器的一些兼容性问题。就能发现,在web上播放音视频其实限制还是很大的。如何解决这些限制,就会用到MediaSource

视频其实是无数个图片的叠加,如果视频是一秒60帧,大约一秒中需要播放60张图片。这就导致一个几分钟的视频,就会非常大。比如上面介绍的无损格式,avi格式,每分钟视频大约 2-3 GB。这时候视频就需要进行编码。其实就是压缩。

编码分为视频编码和音频编码,常见的视频编码有:

  • MPEG 系列MPEG-1第二部分、MPEG-2第二部分(等同于H.262)、MPEG-4第二部分、MPEG-4第十部分(等同于H.264,有时候也被叫做“MPEG-4 AVC”或“H.264/AVC”)。
  • H.26x 系列H.261H.262H.263H.264(等同于MPEG-4第十部分)、H.265/HEVCITU-TISO/IEC联合推出)。
  • 其它视频编码WMV系列、RV系列、VC-1DivXXviDX264X265VP8VP9Sorenson VideoAVS

常见的音频编码有:AACMP3AC-3

编码之后,还需要将音频和视频合并在一个文件里,这就是封装

所以相对的,播放一个视频,就需要解封装,解码,音视频同步喂给声卡和显卡进行播放。

MediaSource做的就是这个工作,读取视频流,转换成浏览器能播放的格式。

以下是flv.jsparseChunks部分内容。读取buffer,一个字节一个字节的根据标准进行解析。然后转码。

js
if (byteStart === 0) {
+  // buffer with FLV header
+  if (chunk.byteLength > 13) {
+    let probeData = FLVDemuxer.probe(chunk);
+    offset = probeData.dataOffset;
+  } else {
+    return 0;
+  }
+}
+
+if (this._firstParse) {
+  // handle PreviousTagSize0 before Tag1
+  this._firstParse = false;
+  if (byteStart + offset !== this._dataOffset) {
+    Log.w(this.TAG, 'First time parsing but chunk byteStart invalid!');
+  }
+
+  let v = new DataView(chunk, offset);
+  let prevTagSize0 = v.getUint32(0, !le);
+  if (prevTagSize0 !== 0) {
+    Log.w(this.TAG, 'PrevTagSize0 !== 0 !!!');
+  }
+  offset += 4;
+}

1.MediaSource 兼容性

image.png

由此可见,基本都是绿色,但有一个特殊情况,就是Safari on IOS。这部分支持程度还是棕色。

五:HLS 播放方案

采用HLS技术方案,有以下几个原因:

1.兼容性

上面介绍了各种视频格式,还有浏览器的兼容性

其中 HLS协议是Apple公司实现的,在 Apple 的全系列产品包括 iPhoneiPadSafari 等都可以原生支持播放 HLS

对于其他浏览器,可以通过MediaSource解封装,解码,转码,进行播放。

这样也就解决了MediaSource的兼容性问题。

  1. 业务场景需求

目前对于视频的加密有着强需求,比如需要用户付费才能观看一些视频。而HLS协议天然自带标准加密,同时也能基于HLS扩展私有加密。

  1. HLS协议自带支持分片传输和动态码率自适应播放。
  2. 有现成的技术方案,Hls.js

六:服务端开发

选择了采用HLS协议的播放方式,那么首先需要处理视频,这部分目前是在服务端进行处理。利用ffmpeg的能力。

如果以后能将ffmpeg搬上浏览器,且没有性能问题就好了。现在有类似的webassemblynpm包,但性能有点小问题

1.视频的转码

视频的转码的ffmpeg命令如下:

sh
ffmpeg -i input.mp4 -hls_time 10 -hls_list_size 0 -c:v h264 -b:v 2M -hls_segment_filename output_%05d.ts output.m3u8 -y

每个参数的解释:

  • -i 指定输入的视频
  • -hls_time 指定分片的时间,单位是秒
  • -hls_list_size 指定hls列表的数量,这里不限制
  • -c:v 指定视频的编码格式
  • -b:v 指定视频的码率,这里是2M比特率
  • -hls_segment_filename 指定输出的ts文件名字,这里表示是output_ + 五位数字
  • output.m3u8指定输出m3u8文件的名字
  • -y有些场景,比如是否覆盖,直接选择是,避免程序卡住

为了自动化执行,这里会用到nodespawn模块,创建一个子进程,在子进程中执行ffmpeg的命令。

ts
const exec = ({ params, data }: ExecOption): Promise<ExecResult> => {
+  return new Promise((r, j) => {
+    const cp = spawn('ffmpeg', params);
+    cp.stderr.pipe(process.stdout);
+    cp.on('error', (err) => {
+      j(err);
+    });
+    cp.on('close', (code) => {
+      r({ code, data });
+    });
+    cp.on('exit', (code) => {
+      r({ code, data });
+    });
+  });
+};

这时候,视频就会在指定的位置输出了,会生成一个m3u8和多个ts

image.png

ts是视频文件,m3u8更像是索引文件,用来描述ts,比如在什么时间,播放什么ts。主要内容如下:

#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-TARGETDURATION:10
+#EXT-X-MEDIA-SEQUENCE:0
+#EXTINF:10.380622,
+5_00000.ts
+#EXTINF:10.380622,
+5_00001.ts
+#EXTINF:10.380622,
+5_00002.ts
+#EXTINF:10.380622,
+5_00003.ts
+#EXTINF:6.560556,
+5_00004.ts
+#EXTINF:1.619378,
+5_00005.ts
+#EXTINF:5.024189,
+5_00006.ts
+#EXT-X-ENDLIST

2.视频的标准加密

HLS协议标准加密采用的是AES对称加密方案。先来实现一个最标准的加密:

首先通过node原生模块crypto生成加密密钥:

ts
import crypto from 'node:crypto';
+// 生成加密密钥
+const key = crypto.createHash('sha256').update(crypto.randomBytes(32)).digest('base64');
+const filePathKey = path.join(__dirname, \`../../public/uploads/hls/\${dir}/\${fileName}.key\`);
+
+const content = \`\${ctx.origin}/uploads/hls/\${dir}/\${fileName}.key\\n\${filePathKey}\\n\`;
+// 密钥的文件
+const fileKey = await writeFile(path.join(__dirname, \`../../public/uploads/hls/\${dir}/\${fileName}.key\`), key);
+const keyInfoPath = path.join(__dirname, \`../../public/uploads/hls/\${dir}/\${fileName}_key.bin\`);
+// ffmpeg 需要的 key.info
+const keyInfo = await writeFile(keyInfoPath, content);

然后再执行ffmpeg命令,这里同样需要用nodespawn模块进行封装成接口:

sh
ffmpeg -i input.mp4 -hls_time 10 -hls_list_size 0 -c:v h264 -b:v 2M -hls_key_info_file keyInfoPath -hls_segment_filename output_%05d.ts output.m3u8 -y

主要就增加了一个hls_key_info_file参数,表示加密密钥的地址。这时候,生成的m3u8文件就发生了变化,多了一行:

#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-TARGETDURATION:10
+#EXT-X-MEDIA-SEQUENCE:0
+#EXT-X-KEY:METHOD=AES-128,URI="http://localhost:30103/uploads/hls/5_1701577743851/5.key",IV=0x00000000000000000000000000000000
+#EXTINF:10.380622,
+5_00000.ts
+#EXTINF:10.380622,
+5_00001.ts
+#EXTINF:10.380622,
+5_00002.ts
+#EXTINF:10.380622,
+5_00003.ts
+#EXTINF:6.560556,
+5_00004.ts
+#EXTINF:1.619378,
+5_00005.ts
+#EXTINF:5.024189,
+5_00006.ts
+#EXT-X-ENDLIST

多了

#EXT-X-KEY:METHOD=AES-128,URI="http://localhost:30103/uploads/hls/5_1701577743851/5.key",IV=0x00000000000000000000000000000000
  • METHOD字段表示加密方式,这里是AES
  • URI表示密钥地址,这里是http://localhost:30103/uploads/hls/5_1701577743851/5.key
  • IV是加密解密时的偏移量,现在是 0

上述加密方式,虽然视频确实加密了,但会把密钥地址写在m3u8里。等于把房间上锁,然后在锁上贴一个纸条,上面写了密码。

3.更好的安全方案

  • 有加密,必然需要解密

首先我们知道,视频要在web端进行播放,那么无论如何,都肯定需要先解密,再播放。

  • 肯定不能在web端放置密钥
  • web端需要知道如何获取密钥
  • 密钥用一次即失效,每次加密视频都生成新的密钥

目前更好的安全性方式主要有两种:

  1. 在请求密钥的地址上进行加固:
  • 校验cookie,既然是发起请求,那么同域名会自动携带cookie,只有购买过的用户才能获取密钥。(总不能让付费的用户也不能看吧)
  • 生成密钥链接时,带上ticket,短时间失效,控制时效性
  • 请求头携带auth,进行用户校验。比如jwt方案就是如此
  1. 采用私有加密方式,比如m3u8里的METHOD,可能不再是AES这种对称加密。自定义一套加密规则,这种方式安全性会极大提高,但同时就不遵守HLS协议的标准了。但大多数浏览器支持MediaSource。可以读取文件内容,进行自定义加密和解密。根据上文的兼容性调研,MediaSourceIOS上将会有兼容性问题,所以这种方案在IOS上也会有兼容性问题。

4.自适应码率播放

这里先介绍一下码率和清晰度的关系:

码率是指:

码率(也称为比特率)是指视频文件在单位时间内使用的数据流量。它反映了视频文件的数据压缩程度,码率越高,压缩比就越小,画面质量就越高,但文件体积也越大。通俗来说,码率可以看作是取样率,是视频编码中画面质量控制中最重要的部分。计算公式是文件体积=时间 X 码率/8。

所以简单来说,码率越高,清晰度就越好。成正比关系。

需要根据视频的质量,和业务场景,去定义,这里给出阿里云对码率和清晰度的定义,可供参考:

image.png

为了实现自适应码率播放,我们需要将不同码率的m3u8合并成一个多码率的m3u8

这里我没找到合适的ffmpeg命令,但总有办法的,最万能的方法就是,查看HLS协议中多码率的m3u8格式标准,自己写一个。

目前用node去写一个这样的索引文件,具体内容如下:

#EXTM3U
+#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1000000,CODECS="mp4a.40.2,avc1.64001f",RESOLUTION=1280x720,NAME="720"
+hls/5_1701577771368/5.m3u8
+#EXT-X-STREAM-INF:PROGRAM-ID=2,BANDWIDTH=50000,CODECS="mp4a.40.5,avc1.42000d",RESOLUTION=320x184,NAME="320"
+hls/5_1701577744714/5.m3u8
  • #EXT-X-STREAM-INF: 流媒体的描述
  • PROGRAM-ID: 表示唯一的ID
  • BANDWIDTH: 流媒体的带宽,即每秒传输的数据量。这里带宽为50000,意味着每秒传输的数据量大约为50kbps
  • CODECS: 流媒体使用的编解码器。这里是使用了mp4a.40.5AAC音频编码)和avc1.42000dAVC视频编码)。
  • RESOLUTION: 这个字段指示了视频的分辨率,即宽度和高度。在这个例子中,视频分辨率为320x184
  • NAME: 这个字段为流媒体提供了一个名称,本例中名称为"320"。我会习惯把清晰度放在NAME这个字段这里,方便web端获取

实现一个接口,传入以上的参数,动态拼接字符串,写入文件

ts
async generateMasterPlayList(ctx: Context): Promise<void> {
+    try {
+      const { paths, filename = Date.now() } = ctx.request.body;
+      let content = \`#EXTM3U\\n\`;
+      paths.forEach((item: MasterPlayListOption, index: number) => {
+        const { id = index, bandWidth, codecs, resolution, name, url } = item;
+        content += \`#EXT-X-STREAM-INF:PROGRAM-ID=\${id},BANDWIDTH=\${bandWidth},CODECS="\${codecs}",RESOLUTION=\${resolution},NAME="\${name}"\\n\${url}\\n\`;
+      });
+      const dir = path.join(__dirname, \`../../public/uploads/hls/\`);
+      if (!existsSync(dir)) {
+        await createDir(dir);
+      }
+      const filePath = dir + (filename.toString().endsWith('.m3u8') ? filename : \`\${filename}.m3u8\`)
+      const { success, error } = await writeFile(filePath, content);
+      const basename = path.basename(filePath);
+      return success
+        ? ctx.successHandler({
+            url: \`\${ctx.origin}/uploads/hls/\${basename}\`,
+          })
+        : ctx.failHandler(error);
+    } catch (error) {
+      ctx.errorHandler(error);
+    }
+  }

那么HLS是如何自适应码率的呢?

其实是根据BANDWIDTH这个字段,因为我们给不同的视频设置了不同的BANDWIDTH。那么就可以根据当前的网速,进行动态切换。

七:web 端的实现

上面做了大量的工作,主要是生成了HLS协议的视频播放的地址。接下来就是如何在web端进行播放。

1.技术选型

我首先是看了现有的播放器npm,比较知名的

其中知乎和西瓜的播放器是开源的,阿里云点播方案没有开源代码,但是有开源demo

image.png

但基本上实现的功能都很丰富,同时配置项会不断的增加。

如果只是简单的初始化一个播放器,那还好。但一般这种场景,我们都会对播放器进行一定程度的定制化。比如 B 站。

image.png

就多了很多自定义的控件。进度条也是小电视的形状。

我们这边也是如此,有自己的主题色,有自己的播放按钮等等,还有一些业务功能,也要放在控制条上。

上述的开源方案,都需要花时间去研究配置项,而且使用方法都是new Player(options)的形式。

但尽量视图的归视图,逻辑的归逻辑会更好些。

更何况实现一个播放器也不是很困难。

期望的player,能满足

  1. 配置够简单,最好看到就知道是怎么用的
  2. 方便扩展和样式覆盖
  3. 支持hls播放
  4. 尽量适配前端的各种框架
  5. 方便接入,实现价值

2.播放器设计

由于现在既有react项目,也有vue项目,甚至还有一些老的jquery项目。为了做到一次开发,任何项目都可以使用和接入。采用了web components技术方案。

web components就不做介绍了,具体可以去看这篇文章:手写 web components 组件简单来说就是可以自定义元素,让我们像使用div一样使用自定义元素。

播放器我们需要考虑的点有:

  1. video生命周期:loadedmetacanplay, ended, error
  2. video状态:播放,正在播放,暂停,静音等
  3. video属性:总时长,当前时长,音量大小,倍速等
  4. video交互:暂停,播放,知识点,清晰度,倍速,全屏,进度控制,音量控制等

(1).video 的生命周期

对于 video 的生命周期,我们期望做到两件事情:

  1. 我们能知道当前video处于什么生命周期
  2. 在不同的生命周期,能挂载自定义事件。比如视频触发了ended。我们需要在ended时期跳转下一个视频

因此,我们需要监听video的生命周期:

ts
listenEvent = () => {
+  if (!this._video) return;
+  this.clearListenerEvent();
+  this._video.addEventListener('canplay', this.onCanplay);
+  this._video.addEventListener('canplaythrough', this.onCanplaythrough);
+  this._video.addEventListener('complete', this.onComplete);
+  this._video.addEventListener('durationchange', this.onDurationchange);
+  this._video.addEventListener('emptied', this.onEmptied);
+  this._video.addEventListener('ended', this.onEnded);
+  this._video.addEventListener('error', this.onError);
+  this._video.addEventListener('loadeddata', this.onLoadeddata);
+  this._video.addEventListener('loadedmetadata', this.onLoadedmetadata);
+  this._video.addEventListener('loadstart', this.onLoadstart);
+  this._video.addEventListener('pause', this.onPause);
+  this._video.addEventListener('play', this.onPlay);
+  this._video.addEventListener('playing', this.onPlaying);
+  this._video.addEventListener('progress', this.onProgress);
+  this._video.addEventListener('ratechange', this.onRatechange);
+  this._video.addEventListener('seeked', this.onSeeked);
+  this._video.addEventListener('seeking', this.onSeeking);
+  this._video.addEventListener('stalled', this.onStalled);
+  this._video.addEventListener('suspend', this.onSuspend);
+  this._video.addEventListener('timeupdate', this.onTimeupdate);
+  this._video.addEventListener('volumechange', this.onVolumechange);
+  this._video.addEventListener('waiting', this.onWaiting);
+};

在触发不同的时期时,让开发者知道。所以我们要先自定义事件,进行触发

ts
const change = (name: string, value: unknown): void => {
+  const currentTime = this.getCurrentTime();
+  const duration = this.getTotalTime();
+  this.dispatchEvent(
+    new CustomEvent('change', {
+      detail: {
+        type: name,
+        data: value,
+        currentTime,
+        duration,
+        tag: this, // 整个 player 的实例
+      },
+    }),
+  );
+};
+const onCanplaythrough = (e: Event) => {
+  this.ctx.currentState = e.type;
+  this.change('canplaythrough', e);
+};

这样就可以,当生命周期事件触发后,就会触发onchange。 在使用上,我们可以:

jsx
<r-player onChange={change} src="hls/example.m3u8" ></r-player>
+
+const change = (e:CustomEvent) => {
+    const { type, data, currentTime, duration, tag } = e.detail
+    if(type === 'ended'){
+        console.log('video ended')
+    }
+}

其中type的类型有:

名称说明
canplay浏览器可以播放媒体文件了,但估计没有足够的数据来支撑播放到结束,不必停下来进一步缓冲内容。
canplaythrough浏览器估计它可以在不停止内容缓冲的情况下播放媒体直到结束。
completeOfflineAudioContext 渲染完成。
durationchangeduration 属性的值改变时触发。
emptied媒体内容变为空;例如,当这个 media 已经加载完成(或者部分加载完成),则发送此事件,并调用 load() 方法重新加载它。
ended视频停止播放,因为 media 已经到达结束点。
loadedmetadata已加载元数据。
progress在浏览器加载资源时周期性触发。
ratechange播放速率发生变化。
seeked跳帧(seek)操作完成。
seeking跳帧(seek)操作开始。
stalled用户代理(user agent)正在尝试获取媒体数据,但数据意外未出现。
suspend媒体数据加载已暂停。
loadeddatamedia 中的首帧已经完成加载。
timeupdatecurrentTime 属性指定的时间发生变化。
volumechange音量发生变化。
waiting由于暂时缺少数据,播放已停止。
play播放已开始。
playing由于缺乏数据而暂停或延迟后,播放准备开始。
pause播放已暂停。
volume音量发生变化。
fullscreen触发全屏事件

在不同的生命周期,能挂载事情,因此我们需要一个发布订阅类。

ts
type Callback = (...args: unknown[]) => unknown;
+
+type EventName = string | symbol;
+
+type EventItem = {
+  name?: string | symbol;
+  callback: Callback;
+  initialCallback?: Callback;
+};
+
+const NEW_LISTENER = 'NEW_LISTENER';
+
+export class SyncHook {
+  private _events: Record<EventName, Array<EventItem>>;
+  constructor() {
+    this._events = {};
+  }
+  on = (eventName: EventName, eventItem: EventItem | Callback): void => {
+    if (this._events[eventName] && eventName !== Symbol.for(NEW_LISTENER)) {
+      this.emit(Symbol.for(NEW_LISTENER), eventName);
+    }
+
+    const callbacks = this._events[eventName] || [];
+    if (typeof eventItem === 'function') {
+      callbacks.push({
+        name: eventName,
+        callback: eventItem,
+      });
+    } else {
+      callbacks.push(eventItem);
+    }
+
+    this._events[eventName] = callbacks;
+  };
+
+  emit = (eventName: EventName, ...args: Array<unknown>): void => {
+    const callbacks = this._events[eventName] || [];
+    callbacks.forEach((item) => {
+      const { callback } = item;
+      callback(...args);
+    });
+  };
+
+  once = (eventName: EventName, eventItem: EventItem | Callback): void => {
+    let one: EventItem;
+    if (typeof eventItem === 'function') {
+      one = {
+        name: eventName,
+        callback: (...args: Array<unknown>) => {
+          eventItem(...args);
+          this.off(eventName, one);
+        },
+        initialCallback: eventItem,
+      };
+    } else {
+      const { callback } = eventItem;
+      one = {
+        name: eventName,
+        callback: (...args: Array<unknown>) => {
+          callback(...args);
+          this.off(eventName, one);
+        },
+        initialCallback: callback,
+      };
+    }
+    this.on(eventName, one);
+  };
+
+  off = (eventName: EventName, eventItem: EventItem | Callback): void => {
+    const callbacks = this._events[eventName] || [];
+    const newCallbacks = callbacks.filter((item) => {
+      if (typeof eventItem === 'function') {
+        return item.callback !== eventItem && item.initialCallback !== eventItem;
+      } else {
+        const { callback } = eventItem;
+        return item.callback !== callback && item.initialCallback !== callback;
+      }
+    });
+    this._events[eventName] = newCallbacks;
+  };
+}

因此会给player元素上增加一个ctx属性,作为全局的上下文。

ts
this.ctx = {
+  currentTime: 0, // 当前时间
+  duration: 0, // 总时长
+  currentState: '', // 当前视频状态
+  action: new SyncHook(), // 不同时期触发的状态
+};

我们想订阅视频的结束事件,我们可以

通过Ref的方式:

<r-player ref={PlayerRef} onChange={change} src="hls/example.m3u8" ></r-player>
+
+const endedEvent = () => {
+    console.log('video ended')
+}
+
+PlayerRef.current.ctx.action.off('ended',endedEvent)
+
+PlayerRef.current.ctx.action.on('ended',endedEvent)

通过change方法获取的实例:

jsx
<r-player onChange={change} src="hls/example.m3u8" ></r-player>
+
+let player
+
+const endedEvent = () => {
+    console.log('video ended')
+}
+
+const change = (e:CustomEvent) => {
+    const { type, data, currentTime, duration, tag } = e.detail
+    player = tag
+}
+
+player.action.off('ended',endedEvent)
+player.action.on('ended',endedEvent)

(2).video 的状态和属性

需要在全局上下文中记录下播放器的状态和属性:

ts
this.ctx = {
+  currentTime: 0, // 当前时间
+  duration: 0, // 总时长
+  currentState: '', // 当前视频状态
+  action: new SyncHook(), // 不同时期触发的状态
+  volume: 0.5, // 当前音量
+  playbackRate: 1, // 当前倍速
+  clarity: '', // 当前清晰度
+  fullScreen: false, // 是否全屏
+  levels: [], // 清晰度列表
+  url: '', // 当前播放的地址
+  levelMap: new Map(), // 清晰度和名字的映射关系
+};

(3).自定义 video

默认长这个样子

image.png

demo 地址:https://chaxus.github.io/ran/src/ranui/player/

源码地址:https://github.com/chaxus/ran

如果不喜欢控制器或者按钮,直接样式覆盖,更符合直觉,没有学习成本。

css
.ran-player-controller {
+  display: none;
+}

由于播放器本身就是一个元素,那么可以任意的在里面添加元素,添加逻辑。

jsx
<r-player onChange={change} src="hls/example.m3u8">
+  <div>111111</div>
+</r-player>

所以,这就解决配置项,长达好几页的问题,同时看到也就知道怎么配置,怎么开发了。

八:总结

目前已经从前后端的角度,实现了

  1. 视频的标准加密
  2. 视频的动态码率播放
  3. 视频的分片加载
  4. 可拖拽进度条
  5. 音量控制
  6. 手动清晰度切换
  7. 倍速播放
  8. 样式自定义覆盖
  9. 基于原生开发,可在所有框架运行,统一跨框架情况,各浏览器控件统一

这是demo和源码地址:

demo和文档地址:https://chaxus.github.io/ran/src/ranui/player/

源码地址:https://github.com/chaxus/ran

demo文档做了国际化,可切换到中文

`,229)]))}const S=i(B,[["render",m]]);export{x as __pageData,S as default}; diff --git a/assets/cn_src_article_video.md.Dw4RU8dr.lean.js b/assets/cn_src_article_video.md.Dw4RU8dr.lean.js new file mode 100644 index 0000000000..42fa754961 --- /dev/null +++ b/assets/cn_src_article_video.md.Dw4RU8dr.lean.js @@ -0,0 +1,285 @@ +import{_ as i,o as a,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const t="/ran/assets/bilibili_video_code.DgWtgAEf.webp",p="/ran/assets/bili_demo_url.BQDGtHUp.webp",l="/ran/assets/bilibili_video_m4s.BccuY7bk.webp",k="/ran/assets/aqiyi_demo.s0swGzvF.webp",e="/ran/assets/tiktok_video.DuwKyIdt.webp",d="/ran/assets/tiktik_video_demo.mxxBzLay.webp",E="/ran/assets/red_book.DiBEvryP.webp",r="/ran/assets/safari_support_media.Bafr23bR.webp",g="/ran/assets/firefox_support_media.BLmSeBNy.webp",o="/ran/assets/ms_support.CaZSSiRt.webp",c="/ran/assets/ts_demo.D_l_mv9k.webp",y="/ran/assets/video_format.CRMCTmKB.webp",F="/ran/assets/xgplayer_docs.CpHb1Wan.webp",C="/ran/assets/bili_demo.CI8Ur8IA.webp",u="/ran/assets/rplayer_demo.CoJ7kuJt.webp",x=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/video.md","filePath":"cn/src/article/video.md","lastUpdated":1726550590000}'),B={name:"cn/src/article/video.md"};function m(A,s,b,v,D,f){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h('

实现自适应码率 Web 视频加密播放:前后端的挑战与解决方案

最近又遇到了web视频化的场景,之前也有过调研:H5 视频化调研浅析

但这次稍微复杂一些,这次解决的是:

  1. 视频播放的技术方案调研

服务端实现:

  1. 视频转码
  2. 生成不同码率的视频
  3. 进行视频标准加密
  4. 不同码率视频合并,用于动态码率播放

web端实现

  1. web端播放器的设计
  2. web端播放器的自定义扩展
  3. 可拖拽进度条
  4. 音量控制
  5. 根据当前带宽自适应码率切换
  6. 手动清晰度切换
  7. 倍速播放
  8. 样式自定义覆盖
  9. 标准加密视频播放
  10. 基于原生开发,可在所有框架运行,统一跨框架情况
  11. 各浏览器控件统一

其中web端源码已添加MIT协议并完全开源,如果看完对大家有帮助的话,欢迎大家star,issue,pr,也希望能友好交流~

demo 地址:https://chaxus.github.io/ran/src/ranui/player/

源码地址:https://github.com/chaxus/ran

demo文档做了国际化,可切换到中文

任何一个项目,立项肯定先是技术调研,我们先看看一些大公司的视频播放方案

一:一些知名公司的 web 视频播放方案

1.B 站

我们先看看 B 站的,毕竟 B 站的主营业务就是视频弹幕网站,简直专业对口。

先找一个例子:https://www.bilibili.com/video/BV1FM411N7LJ 访问它。

image.png

打开控制台,可以看到,视频在播放的时候,会不断的请求m4s的视频文件。

毕竟一整个视频文件往往比较大,不可能先请求完视频文件,再进行播放。因此将一个大的视频文件分割成很多小的片段,边加载边播放,是一种更好的方式。

image.png

每次请求的m4s文件大概在几十kb到几百kb不等。

image.png

那为什么不采用httprange呢,可以请求一个文件的部分内容,而且粒度更细,可以设置字节范围。在http请求的header中,类似这样

js
Range: bytes = 3171375 - 3203867;

我们可以检查这个链接请求https://upos-sz-mirror08c.bilivideo.com/upgcxcode/67/92/1008149267/1008149267-1-30064.m4s的请求头,就能发现,B 站采用的是,即分片加载,同时还用了range的方式。

2. 爱奇艺:(爱奇艺、土豆、优酷)

爱奇艺这里就不贴视频链接了,因为随便点一个视频,都要先看广告。

image.png

爱奇艺的视频主要请求的是f4v格式,也是分片加载。

播放一个视频时,请求多个f4v文件。

也采用Range。但和 B 站不一样的是,B 站的Range属性是在m4s请求的请求头里面,而爱奇艺的看起来是在querystring上,在请求query上带着range参数。

因为没发现这个请求的header里面有range参数。比如:

https://v-6fce1712.71edge.com/videos/other/20231113/6b/bb/3f3fe83b89124248c3216156dfe2f4c3.f4v?dis_k=2ba39ee8c55c4d23781e3fb9f91fa7a46&dis_t=1701439831&dis_dz=CNC-BeiJing&dis_st=46&src=iqiyi.com&dis_hit=0&dis_tag=01010000&uuid=72713f52-6569e957-351&cross-domain=1&ssl=1&pv=0.1&cphc=arta&range=0-9000

3.抖音:

抖音的方案简单粗暴,访问的链接是这个: https://m.ixigua.com/douyin/share/video/7206914252840370721?aweme_type=107&schema_type=1&utm_source=copy&utm_campaign=client_share&utm_medium=android&app=aweme

通过查看控制台,我们可以发现,直接请求了一个视频的地址

image.png

没有进行分片,但用到了请求range,所以可以看到视频,是边播放边缓冲一部分。

不过我在开发的时候发现,目前租用的服务云厂商,默认会帮我们实现这项技术。

因为我把mp4视频上传到云服务器,通过链接进行播放的时候,就是边缓冲边播放的。

我们可以直接把这个视频地址拿出来,放到浏览器里面能直接播放,这样观察更明显。

image.png

但 B 站和爱奇艺却不能这样,因为他们采用的m4sf4v都不是一种通用的视频格式,需要使用专门的软件或工具才能打开和编辑。

4.小红书:

测试用的例子链接:https://www.xiaohongshu.com/discovery/item/63b286d1000000001f00b495

小红书的方案更加简单粗暴,打开控制台,直接告诉你就是请求一个mp4,然后直接播放就完事了。

image.png

5.总结

看完了以上的各家大厂的方案,我们可以看到,基本原理都是边播放边加载,减少直接加载大视频文本的成本。并且通过分片传输,还能动态控制视频码率(清晰度)。做到根据网速,加载不同码率的分片文件,做到动态码率适应。

同时采用的视频格式,比如f4vm4s,都不是能直接播放的媒体格式,需要一定的处理。增加盗取视频的成本,增加一定的安全性。

如果没有强要求,也可以直接采用mp4,或者直接用video播放一个视频文件地址。

二:常见的视频格式与协议

我们知道视频的常见格式有mp4,同时上面介绍了 B 站播放用的m4s格式,爱奇艺用的f4v格式

  • 除了这些还有哪些视频格式?
  • 为什么有这么多视频格式,有哪些不同点呢?
  • 为什么这些公司会采用这种格式来播放视频呢?

1. B 站用的m4s

M4S格式不是一种通用的视频格式,需要使用专门的软件或工具才能打开和编辑。

M4S 通常会和 MPEG-DASH 流媒体技术一起,通过流式传输的视频的一小部分。播放器会按接收顺序播放这些片段。第一个 M4S 段会包含一些初始化的数据标识。

MPEG-DASH 是一种自适应比特率流媒体技术,通过将内容分解为一系列不同码率的M4S片段,然后根据当前网络带宽进行自动调整。如果想在在web音视频中采用DASH技术,可以看下 https://github.com/Dash-Industry-Forum/dash.js

2. 爱奇艺的f4v

F4V是一种流媒体格式,它是由Adobe公司推出的,继FLV格式之后支持H.264编码的流媒体格式。F4V格式的视频不是一种通用的视频格式,但通常情况下,都可以将文件后缀改为FLV,这样就可以使用支持FLV的播放器进行观看。

FLV格式跟常见的MP4格式比起来,结构更加简单,所以加载metadata(视频元数据,比如视频时长等信息) 会更快。具体结构我们可以在这里查到:https://en.wikipedia.org/wiki/Flash_Video#Flash_Video_Structure

比如,这是FLV文件的标准头,定义了从几个比特到几个比特之间,是什么含义。我们知道后,可以用MediaSource进行读取和转码。

FieldData TypeDefaultDetails
Signature 签名byte[3]"FLV"始终就是“FLV”
Version 版本uint81只有 0x01 才有效
Flags 标志uint8 位掩码0x050x04 是音频,0x01 是视频(所以 0x05 是音频 + 视频)
Header Sizeuint32_be9用于跳过较新的扩展标头

MP4格式会稍微复杂一些,具体标准在 ISO/IEC 14496-12 大概有两百多页,这里放不下,对这方面有兴趣的可以自行查看。

然而这并不表示MP4更差,因为它是一种基础通用标准,所以定义上会留有很多空间,和各种情况,甚至允许在标准之内进行自行发挥和扩展。而FLV格式则更加固定,但优点也是更加简单。

对于FLV的视频播放,我们可以采用:https://github.com/bilibili/flv.js flvjs主要作用就是用MediaSourceflv转码成mp4从而喂给浏览器进行播放。

接下来是一些其他的视频格式,简单介绍一下:

3.AVI

文件名以.avi结尾,AVI 最初由 Microsoft1992 年开发,是 Windows 的标准视频格式。AVI 文件使用较少的压缩来存储文件,并且比许多其他视频格式占用更多空间,这导致文件大小非常大,每分钟视频大约 2-3 GB

无损文件不会随着时间的推移而降低质量,无论您打开或保存文件多少次。此外,这允许在不使用任何编解码器的情况下播放。参考资料:Audio Video Interleave

4.MPEG

文件名以“.mpg”或“.mpeg”结尾,MPEG 是由 ISO 和 IEC 联合成立的工作组联盟,旨在制定媒体编码标准,包括音频、视频、图形和基因组数据的压缩编码;以及各种应用程序的传输和文件格式。MPEG 格式用于各种多媒体系统。最广为人知的旧 MPEG 媒体格式通常使用 MPEG-1、MPEG-2 和 MPEG-4 AVC 媒体编码,MPEG-2 系统传输流和节目流。较新的系统通常使用 MPEG 基本媒体文件格式和动态流式处理(又名 .MPEG-DASH)。参考资料:Moving Picture Experts Group

5.MP4

带有音频和视频的 MPEG-4 文件通常使用标准的 .mp4 扩展名。纯音频 MPEG-4 文件通常具有 .m4a 扩展名,原始 MPEG-4 可视比特流命名为 .m4v。Apple iPhone 使用 MPEG-4 音频作为其铃声,但使用.m4r 扩展名而不是.m4a 扩展名。参考资料:MPEG-4 Part 14

6.QuickTime

文件名以“.mov”结尾,QuickTime 能够包含媒体数据的抽象数据引用,并将媒体数据与媒体偏移和轨道编辑列表分离,这意味着 QuickTime 特别适合编辑,因为它能够就地导入和编辑(无需数据复制)。由于 QuickTime 和 MP4 容器格式都可以使用相同的 MPEG-4 格式,因此在仅限 QuickTime 的环境中,它们大多可以互换。MP4 作为国际标准,得到了更多的支持。参考资料:QuickTime File Format

7.TS

TS 是 MPEG2-TS 的简称,是一种音视频封装格式。TS 流的后缀通常是.ts、.mpg 或者.mpeg,多数播放器直接支持这种格式的播放。TS 格式主要用于直播的码流结构,具有很好的容错能力。

三:浏览器对各种视频格式的兼容性

上面了解常用的视频格式,和适用范围之后,还需要看一下当前浏览器,对各种视频格式的支持程度,然后制定技术方案。

1. Chrome

支持的视频格式从官方文档可以查到,主要有以下这些

  • MP4 (QuickTime/ MOV / ISO-BMFF / CMAF)
  • Ogg
  • WebM
  • WAV
  • HLS [Only on Android and only single-origin manifests]

官方文档如下:https://www.chromium.org/audio-video/

2. Safari

支持的视频格式有这些:

image.png

官方文档:https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html

3.Firefox

支持的视频格式:

image.png

官方文档:https://support.mozilla.org/en-US/kb/html5-audio-and-video-firefox

四:MediaSource 和视频编码,解码,封装介绍

上面介绍了一些视频格式,和目前浏览器的一些兼容性问题。就能发现,在web上播放音视频其实限制还是很大的。如何解决这些限制,就会用到MediaSource

视频其实是无数个图片的叠加,如果视频是一秒60帧,大约一秒中需要播放60张图片。这就导致一个几分钟的视频,就会非常大。比如上面介绍的无损格式,avi格式,每分钟视频大约 2-3 GB。这时候视频就需要进行编码。其实就是压缩。

编码分为视频编码和音频编码,常见的视频编码有:

  • MPEG 系列MPEG-1第二部分、MPEG-2第二部分(等同于H.262)、MPEG-4第二部分、MPEG-4第十部分(等同于H.264,有时候也被叫做“MPEG-4 AVC”或“H.264/AVC”)。
  • H.26x 系列H.261H.262H.263H.264(等同于MPEG-4第十部分)、H.265/HEVCITU-TISO/IEC联合推出)。
  • 其它视频编码WMV系列、RV系列、VC-1DivXXviDX264X265VP8VP9Sorenson VideoAVS

常见的音频编码有:AACMP3AC-3

编码之后,还需要将音频和视频合并在一个文件里,这就是封装

所以相对的,播放一个视频,就需要解封装,解码,音视频同步喂给声卡和显卡进行播放。

MediaSource做的就是这个工作,读取视频流,转换成浏览器能播放的格式。

以下是flv.jsparseChunks部分内容。读取buffer,一个字节一个字节的根据标准进行解析。然后转码。

js
if (byteStart === 0) {
+  // buffer with FLV header
+  if (chunk.byteLength > 13) {
+    let probeData = FLVDemuxer.probe(chunk);
+    offset = probeData.dataOffset;
+  } else {
+    return 0;
+  }
+}
+
+if (this._firstParse) {
+  // handle PreviousTagSize0 before Tag1
+  this._firstParse = false;
+  if (byteStart + offset !== this._dataOffset) {
+    Log.w(this.TAG, 'First time parsing but chunk byteStart invalid!');
+  }
+
+  let v = new DataView(chunk, offset);
+  let prevTagSize0 = v.getUint32(0, !le);
+  if (prevTagSize0 !== 0) {
+    Log.w(this.TAG, 'PrevTagSize0 !== 0 !!!');
+  }
+  offset += 4;
+}

1.MediaSource 兼容性

image.png

由此可见,基本都是绿色,但有一个特殊情况,就是Safari on IOS。这部分支持程度还是棕色。

五:HLS 播放方案

采用HLS技术方案,有以下几个原因:

1.兼容性

上面介绍了各种视频格式,还有浏览器的兼容性

其中 HLS协议是Apple公司实现的,在 Apple 的全系列产品包括 iPhoneiPadSafari 等都可以原生支持播放 HLS

对于其他浏览器,可以通过MediaSource解封装,解码,转码,进行播放。

这样也就解决了MediaSource的兼容性问题。

  1. 业务场景需求

目前对于视频的加密有着强需求,比如需要用户付费才能观看一些视频。而HLS协议天然自带标准加密,同时也能基于HLS扩展私有加密。

  1. HLS协议自带支持分片传输和动态码率自适应播放。
  2. 有现成的技术方案,Hls.js

六:服务端开发

选择了采用HLS协议的播放方式,那么首先需要处理视频,这部分目前是在服务端进行处理。利用ffmpeg的能力。

如果以后能将ffmpeg搬上浏览器,且没有性能问题就好了。现在有类似的webassemblynpm包,但性能有点小问题

1.视频的转码

视频的转码的ffmpeg命令如下:

sh
ffmpeg -i input.mp4 -hls_time 10 -hls_list_size 0 -c:v h264 -b:v 2M -hls_segment_filename output_%05d.ts output.m3u8 -y

每个参数的解释:

  • -i 指定输入的视频
  • -hls_time 指定分片的时间,单位是秒
  • -hls_list_size 指定hls列表的数量,这里不限制
  • -c:v 指定视频的编码格式
  • -b:v 指定视频的码率,这里是2M比特率
  • -hls_segment_filename 指定输出的ts文件名字,这里表示是output_ + 五位数字
  • output.m3u8指定输出m3u8文件的名字
  • -y有些场景,比如是否覆盖,直接选择是,避免程序卡住

为了自动化执行,这里会用到nodespawn模块,创建一个子进程,在子进程中执行ffmpeg的命令。

ts
const exec = ({ params, data }: ExecOption): Promise<ExecResult> => {
+  return new Promise((r, j) => {
+    const cp = spawn('ffmpeg', params);
+    cp.stderr.pipe(process.stdout);
+    cp.on('error', (err) => {
+      j(err);
+    });
+    cp.on('close', (code) => {
+      r({ code, data });
+    });
+    cp.on('exit', (code) => {
+      r({ code, data });
+    });
+  });
+};

这时候,视频就会在指定的位置输出了,会生成一个m3u8和多个ts

image.png

ts是视频文件,m3u8更像是索引文件,用来描述ts,比如在什么时间,播放什么ts。主要内容如下:

#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-TARGETDURATION:10
+#EXT-X-MEDIA-SEQUENCE:0
+#EXTINF:10.380622,
+5_00000.ts
+#EXTINF:10.380622,
+5_00001.ts
+#EXTINF:10.380622,
+5_00002.ts
+#EXTINF:10.380622,
+5_00003.ts
+#EXTINF:6.560556,
+5_00004.ts
+#EXTINF:1.619378,
+5_00005.ts
+#EXTINF:5.024189,
+5_00006.ts
+#EXT-X-ENDLIST

2.视频的标准加密

HLS协议标准加密采用的是AES对称加密方案。先来实现一个最标准的加密:

首先通过node原生模块crypto生成加密密钥:

ts
import crypto from 'node:crypto';
+// 生成加密密钥
+const key = crypto.createHash('sha256').update(crypto.randomBytes(32)).digest('base64');
+const filePathKey = path.join(__dirname, \`../../public/uploads/hls/\${dir}/\${fileName}.key\`);
+
+const content = \`\${ctx.origin}/uploads/hls/\${dir}/\${fileName}.key\\n\${filePathKey}\\n\`;
+// 密钥的文件
+const fileKey = await writeFile(path.join(__dirname, \`../../public/uploads/hls/\${dir}/\${fileName}.key\`), key);
+const keyInfoPath = path.join(__dirname, \`../../public/uploads/hls/\${dir}/\${fileName}_key.bin\`);
+// ffmpeg 需要的 key.info
+const keyInfo = await writeFile(keyInfoPath, content);

然后再执行ffmpeg命令,这里同样需要用nodespawn模块进行封装成接口:

sh
ffmpeg -i input.mp4 -hls_time 10 -hls_list_size 0 -c:v h264 -b:v 2M -hls_key_info_file keyInfoPath -hls_segment_filename output_%05d.ts output.m3u8 -y

主要就增加了一个hls_key_info_file参数,表示加密密钥的地址。这时候,生成的m3u8文件就发生了变化,多了一行:

#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-TARGETDURATION:10
+#EXT-X-MEDIA-SEQUENCE:0
+#EXT-X-KEY:METHOD=AES-128,URI="http://localhost:30103/uploads/hls/5_1701577743851/5.key",IV=0x00000000000000000000000000000000
+#EXTINF:10.380622,
+5_00000.ts
+#EXTINF:10.380622,
+5_00001.ts
+#EXTINF:10.380622,
+5_00002.ts
+#EXTINF:10.380622,
+5_00003.ts
+#EXTINF:6.560556,
+5_00004.ts
+#EXTINF:1.619378,
+5_00005.ts
+#EXTINF:5.024189,
+5_00006.ts
+#EXT-X-ENDLIST

多了

#EXT-X-KEY:METHOD=AES-128,URI="http://localhost:30103/uploads/hls/5_1701577743851/5.key",IV=0x00000000000000000000000000000000
  • METHOD字段表示加密方式,这里是AES
  • URI表示密钥地址,这里是http://localhost:30103/uploads/hls/5_1701577743851/5.key
  • IV是加密解密时的偏移量,现在是 0

上述加密方式,虽然视频确实加密了,但会把密钥地址写在m3u8里。等于把房间上锁,然后在锁上贴一个纸条,上面写了密码。

3.更好的安全方案

  • 有加密,必然需要解密

首先我们知道,视频要在web端进行播放,那么无论如何,都肯定需要先解密,再播放。

  • 肯定不能在web端放置密钥
  • web端需要知道如何获取密钥
  • 密钥用一次即失效,每次加密视频都生成新的密钥

目前更好的安全性方式主要有两种:

  1. 在请求密钥的地址上进行加固:
  • 校验cookie,既然是发起请求,那么同域名会自动携带cookie,只有购买过的用户才能获取密钥。(总不能让付费的用户也不能看吧)
  • 生成密钥链接时,带上ticket,短时间失效,控制时效性
  • 请求头携带auth,进行用户校验。比如jwt方案就是如此
  1. 采用私有加密方式,比如m3u8里的METHOD,可能不再是AES这种对称加密。自定义一套加密规则,这种方式安全性会极大提高,但同时就不遵守HLS协议的标准了。但大多数浏览器支持MediaSource。可以读取文件内容,进行自定义加密和解密。根据上文的兼容性调研,MediaSourceIOS上将会有兼容性问题,所以这种方案在IOS上也会有兼容性问题。

4.自适应码率播放

这里先介绍一下码率和清晰度的关系:

码率是指:

码率(也称为比特率)是指视频文件在单位时间内使用的数据流量。它反映了视频文件的数据压缩程度,码率越高,压缩比就越小,画面质量就越高,但文件体积也越大。通俗来说,码率可以看作是取样率,是视频编码中画面质量控制中最重要的部分。计算公式是文件体积=时间 X 码率/8。

所以简单来说,码率越高,清晰度就越好。成正比关系。

需要根据视频的质量,和业务场景,去定义,这里给出阿里云对码率和清晰度的定义,可供参考:

image.png

为了实现自适应码率播放,我们需要将不同码率的m3u8合并成一个多码率的m3u8

这里我没找到合适的ffmpeg命令,但总有办法的,最万能的方法就是,查看HLS协议中多码率的m3u8格式标准,自己写一个。

目前用node去写一个这样的索引文件,具体内容如下:

#EXTM3U
+#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1000000,CODECS="mp4a.40.2,avc1.64001f",RESOLUTION=1280x720,NAME="720"
+hls/5_1701577771368/5.m3u8
+#EXT-X-STREAM-INF:PROGRAM-ID=2,BANDWIDTH=50000,CODECS="mp4a.40.5,avc1.42000d",RESOLUTION=320x184,NAME="320"
+hls/5_1701577744714/5.m3u8
  • #EXT-X-STREAM-INF: 流媒体的描述
  • PROGRAM-ID: 表示唯一的ID
  • BANDWIDTH: 流媒体的带宽,即每秒传输的数据量。这里带宽为50000,意味着每秒传输的数据量大约为50kbps
  • CODECS: 流媒体使用的编解码器。这里是使用了mp4a.40.5AAC音频编码)和avc1.42000dAVC视频编码)。
  • RESOLUTION: 这个字段指示了视频的分辨率,即宽度和高度。在这个例子中,视频分辨率为320x184
  • NAME: 这个字段为流媒体提供了一个名称,本例中名称为"320"。我会习惯把清晰度放在NAME这个字段这里,方便web端获取

实现一个接口,传入以上的参数,动态拼接字符串,写入文件

ts
async generateMasterPlayList(ctx: Context): Promise<void> {
+    try {
+      const { paths, filename = Date.now() } = ctx.request.body;
+      let content = \`#EXTM3U\\n\`;
+      paths.forEach((item: MasterPlayListOption, index: number) => {
+        const { id = index, bandWidth, codecs, resolution, name, url } = item;
+        content += \`#EXT-X-STREAM-INF:PROGRAM-ID=\${id},BANDWIDTH=\${bandWidth},CODECS="\${codecs}",RESOLUTION=\${resolution},NAME="\${name}"\\n\${url}\\n\`;
+      });
+      const dir = path.join(__dirname, \`../../public/uploads/hls/\`);
+      if (!existsSync(dir)) {
+        await createDir(dir);
+      }
+      const filePath = dir + (filename.toString().endsWith('.m3u8') ? filename : \`\${filename}.m3u8\`)
+      const { success, error } = await writeFile(filePath, content);
+      const basename = path.basename(filePath);
+      return success
+        ? ctx.successHandler({
+            url: \`\${ctx.origin}/uploads/hls/\${basename}\`,
+          })
+        : ctx.failHandler(error);
+    } catch (error) {
+      ctx.errorHandler(error);
+    }
+  }

那么HLS是如何自适应码率的呢?

其实是根据BANDWIDTH这个字段,因为我们给不同的视频设置了不同的BANDWIDTH。那么就可以根据当前的网速,进行动态切换。

七:web 端的实现

上面做了大量的工作,主要是生成了HLS协议的视频播放的地址。接下来就是如何在web端进行播放。

1.技术选型

我首先是看了现有的播放器npm,比较知名的

其中知乎和西瓜的播放器是开源的,阿里云点播方案没有开源代码,但是有开源demo

image.png

但基本上实现的功能都很丰富,同时配置项会不断的增加。

如果只是简单的初始化一个播放器,那还好。但一般这种场景,我们都会对播放器进行一定程度的定制化。比如 B 站。

image.png

就多了很多自定义的控件。进度条也是小电视的形状。

我们这边也是如此,有自己的主题色,有自己的播放按钮等等,还有一些业务功能,也要放在控制条上。

上述的开源方案,都需要花时间去研究配置项,而且使用方法都是new Player(options)的形式。

但尽量视图的归视图,逻辑的归逻辑会更好些。

更何况实现一个播放器也不是很困难。

期望的player,能满足

  1. 配置够简单,最好看到就知道是怎么用的
  2. 方便扩展和样式覆盖
  3. 支持hls播放
  4. 尽量适配前端的各种框架
  5. 方便接入,实现价值

2.播放器设计

由于现在既有react项目,也有vue项目,甚至还有一些老的jquery项目。为了做到一次开发,任何项目都可以使用和接入。采用了web components技术方案。

web components就不做介绍了,具体可以去看这篇文章:手写 web components 组件简单来说就是可以自定义元素,让我们像使用div一样使用自定义元素。

播放器我们需要考虑的点有:

  1. video生命周期:loadedmetacanplay, ended, error
  2. video状态:播放,正在播放,暂停,静音等
  3. video属性:总时长,当前时长,音量大小,倍速等
  4. video交互:暂停,播放,知识点,清晰度,倍速,全屏,进度控制,音量控制等

(1).video 的生命周期

对于 video 的生命周期,我们期望做到两件事情:

  1. 我们能知道当前video处于什么生命周期
  2. 在不同的生命周期,能挂载自定义事件。比如视频触发了ended。我们需要在ended时期跳转下一个视频

因此,我们需要监听video的生命周期:

ts
listenEvent = () => {
+  if (!this._video) return;
+  this.clearListenerEvent();
+  this._video.addEventListener('canplay', this.onCanplay);
+  this._video.addEventListener('canplaythrough', this.onCanplaythrough);
+  this._video.addEventListener('complete', this.onComplete);
+  this._video.addEventListener('durationchange', this.onDurationchange);
+  this._video.addEventListener('emptied', this.onEmptied);
+  this._video.addEventListener('ended', this.onEnded);
+  this._video.addEventListener('error', this.onError);
+  this._video.addEventListener('loadeddata', this.onLoadeddata);
+  this._video.addEventListener('loadedmetadata', this.onLoadedmetadata);
+  this._video.addEventListener('loadstart', this.onLoadstart);
+  this._video.addEventListener('pause', this.onPause);
+  this._video.addEventListener('play', this.onPlay);
+  this._video.addEventListener('playing', this.onPlaying);
+  this._video.addEventListener('progress', this.onProgress);
+  this._video.addEventListener('ratechange', this.onRatechange);
+  this._video.addEventListener('seeked', this.onSeeked);
+  this._video.addEventListener('seeking', this.onSeeking);
+  this._video.addEventListener('stalled', this.onStalled);
+  this._video.addEventListener('suspend', this.onSuspend);
+  this._video.addEventListener('timeupdate', this.onTimeupdate);
+  this._video.addEventListener('volumechange', this.onVolumechange);
+  this._video.addEventListener('waiting', this.onWaiting);
+};

在触发不同的时期时,让开发者知道。所以我们要先自定义事件,进行触发

ts
const change = (name: string, value: unknown): void => {
+  const currentTime = this.getCurrentTime();
+  const duration = this.getTotalTime();
+  this.dispatchEvent(
+    new CustomEvent('change', {
+      detail: {
+        type: name,
+        data: value,
+        currentTime,
+        duration,
+        tag: this, // 整个 player 的实例
+      },
+    }),
+  );
+};
+const onCanplaythrough = (e: Event) => {
+  this.ctx.currentState = e.type;
+  this.change('canplaythrough', e);
+};

这样就可以,当生命周期事件触发后,就会触发onchange。 在使用上,我们可以:

jsx
<r-player onChange={change} src="hls/example.m3u8" ></r-player>
+
+const change = (e:CustomEvent) => {
+    const { type, data, currentTime, duration, tag } = e.detail
+    if(type === 'ended'){
+        console.log('video ended')
+    }
+}

其中type的类型有:

名称说明
canplay浏览器可以播放媒体文件了,但估计没有足够的数据来支撑播放到结束,不必停下来进一步缓冲内容。
canplaythrough浏览器估计它可以在不停止内容缓冲的情况下播放媒体直到结束。
completeOfflineAudioContext 渲染完成。
durationchangeduration 属性的值改变时触发。
emptied媒体内容变为空;例如,当这个 media 已经加载完成(或者部分加载完成),则发送此事件,并调用 load() 方法重新加载它。
ended视频停止播放,因为 media 已经到达结束点。
loadedmetadata已加载元数据。
progress在浏览器加载资源时周期性触发。
ratechange播放速率发生变化。
seeked跳帧(seek)操作完成。
seeking跳帧(seek)操作开始。
stalled用户代理(user agent)正在尝试获取媒体数据,但数据意外未出现。
suspend媒体数据加载已暂停。
loadeddatamedia 中的首帧已经完成加载。
timeupdatecurrentTime 属性指定的时间发生变化。
volumechange音量发生变化。
waiting由于暂时缺少数据,播放已停止。
play播放已开始。
playing由于缺乏数据而暂停或延迟后,播放准备开始。
pause播放已暂停。
volume音量发生变化。
fullscreen触发全屏事件

在不同的生命周期,能挂载事情,因此我们需要一个发布订阅类。

ts
type Callback = (...args: unknown[]) => unknown;
+
+type EventName = string | symbol;
+
+type EventItem = {
+  name?: string | symbol;
+  callback: Callback;
+  initialCallback?: Callback;
+};
+
+const NEW_LISTENER = 'NEW_LISTENER';
+
+export class SyncHook {
+  private _events: Record<EventName, Array<EventItem>>;
+  constructor() {
+    this._events = {};
+  }
+  on = (eventName: EventName, eventItem: EventItem | Callback): void => {
+    if (this._events[eventName] && eventName !== Symbol.for(NEW_LISTENER)) {
+      this.emit(Symbol.for(NEW_LISTENER), eventName);
+    }
+
+    const callbacks = this._events[eventName] || [];
+    if (typeof eventItem === 'function') {
+      callbacks.push({
+        name: eventName,
+        callback: eventItem,
+      });
+    } else {
+      callbacks.push(eventItem);
+    }
+
+    this._events[eventName] = callbacks;
+  };
+
+  emit = (eventName: EventName, ...args: Array<unknown>): void => {
+    const callbacks = this._events[eventName] || [];
+    callbacks.forEach((item) => {
+      const { callback } = item;
+      callback(...args);
+    });
+  };
+
+  once = (eventName: EventName, eventItem: EventItem | Callback): void => {
+    let one: EventItem;
+    if (typeof eventItem === 'function') {
+      one = {
+        name: eventName,
+        callback: (...args: Array<unknown>) => {
+          eventItem(...args);
+          this.off(eventName, one);
+        },
+        initialCallback: eventItem,
+      };
+    } else {
+      const { callback } = eventItem;
+      one = {
+        name: eventName,
+        callback: (...args: Array<unknown>) => {
+          callback(...args);
+          this.off(eventName, one);
+        },
+        initialCallback: callback,
+      };
+    }
+    this.on(eventName, one);
+  };
+
+  off = (eventName: EventName, eventItem: EventItem | Callback): void => {
+    const callbacks = this._events[eventName] || [];
+    const newCallbacks = callbacks.filter((item) => {
+      if (typeof eventItem === 'function') {
+        return item.callback !== eventItem && item.initialCallback !== eventItem;
+      } else {
+        const { callback } = eventItem;
+        return item.callback !== callback && item.initialCallback !== callback;
+      }
+    });
+    this._events[eventName] = newCallbacks;
+  };
+}

因此会给player元素上增加一个ctx属性,作为全局的上下文。

ts
this.ctx = {
+  currentTime: 0, // 当前时间
+  duration: 0, // 总时长
+  currentState: '', // 当前视频状态
+  action: new SyncHook(), // 不同时期触发的状态
+};

我们想订阅视频的结束事件,我们可以

通过Ref的方式:

<r-player ref={PlayerRef} onChange={change} src="hls/example.m3u8" ></r-player>
+
+const endedEvent = () => {
+    console.log('video ended')
+}
+
+PlayerRef.current.ctx.action.off('ended',endedEvent)
+
+PlayerRef.current.ctx.action.on('ended',endedEvent)

通过change方法获取的实例:

jsx
<r-player onChange={change} src="hls/example.m3u8" ></r-player>
+
+let player
+
+const endedEvent = () => {
+    console.log('video ended')
+}
+
+const change = (e:CustomEvent) => {
+    const { type, data, currentTime, duration, tag } = e.detail
+    player = tag
+}
+
+player.action.off('ended',endedEvent)
+player.action.on('ended',endedEvent)

(2).video 的状态和属性

需要在全局上下文中记录下播放器的状态和属性:

ts
this.ctx = {
+  currentTime: 0, // 当前时间
+  duration: 0, // 总时长
+  currentState: '', // 当前视频状态
+  action: new SyncHook(), // 不同时期触发的状态
+  volume: 0.5, // 当前音量
+  playbackRate: 1, // 当前倍速
+  clarity: '', // 当前清晰度
+  fullScreen: false, // 是否全屏
+  levels: [], // 清晰度列表
+  url: '', // 当前播放的地址
+  levelMap: new Map(), // 清晰度和名字的映射关系
+};

(3).自定义 video

默认长这个样子

image.png

demo 地址:https://chaxus.github.io/ran/src/ranui/player/

源码地址:https://github.com/chaxus/ran

如果不喜欢控制器或者按钮,直接样式覆盖,更符合直觉,没有学习成本。

css
.ran-player-controller {
+  display: none;
+}

由于播放器本身就是一个元素,那么可以任意的在里面添加元素,添加逻辑。

jsx
<r-player onChange={change} src="hls/example.m3u8">
+  <div>111111</div>
+</r-player>

所以,这就解决配置项,长达好几页的问题,同时看到也就知道怎么配置,怎么开发了。

八:总结

目前已经从前后端的角度,实现了

  1. 视频的标准加密
  2. 视频的动态码率播放
  3. 视频的分片加载
  4. 可拖拽进度条
  5. 音量控制
  6. 手动清晰度切换
  7. 倍速播放
  8. 样式自定义覆盖
  9. 基于原生开发,可在所有框架运行,统一跨框架情况,各浏览器控件统一

这是demo和源码地址:

demo和文档地址:https://chaxus.github.io/ran/src/ranui/player/

源码地址:https://github.com/chaxus/ran

demo文档做了国际化,可切换到中文

`,229)]))}const S=i(B,[["render",m]]);export{x as __pageData,S as default}; diff --git a/assets/cn_src_article_visual.md.CDvSxrkl.js b/assets/cn_src_article_visual.md.CDvSxrkl.js new file mode 100644 index 0000000000..683273db18 --- /dev/null +++ b/assets/cn_src_article_visual.md.CDvSxrkl.js @@ -0,0 +1,143 @@ +import{_ as h,o as n,c as l,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"实现曲线","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/visual.md","filePath":"cn/src/article/visual.md","lastUpdated":1726550590000}'),k={name:"cn/src/article/visual.md"};function p(t,a,e,E,r,d){return n(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

在业务持续演进的过程中,遭遇了高度定制化图表的需求。为了寻找解决方案,首先深入探索了现有的开源图表库,遗憾的是,这些库虽能覆盖大部分常见的功能,但在一些定制化设计上却显得力不从心,但 UI 层的定制化又是十分常见的。

为了精准复现设计愿景,我转而采用 canvas 技术手动绘制图表。这一过程中,尽管已尽力通过函数式编程范式封装和模块化绘制逻辑以提升代码的可维护性,但 canvas 的命令式特性在面临需求变动时,仍易导致直接而频繁的代码调整,影响了整体的开发效率和灵活性。

鉴于此,意识到,需要从更高层次的业务逻辑和设计理念出发,构建一个更为底层且灵活的图表绘制引擎。这样的引擎应能够抽象出绘制操作的核心要素,不仅服务于当前应用层的定制化需求,更应具备良好的扩展性和复用性,以便在未来面对更多样化的业务场景时,能够迅速响应并高效实现定制化图表的绘制需求。这样的策略转变,旨在从根本上提升图表定制化的开发效率和图表的维护性,确保业务迭代的顺畅进行。

一 技术设计

针对常见的绘制需求进行详尽的功能分析后,我们系统性地规划了高效且灵活的图表绘制引擎的核心构成要素。这些精心设计的组件旨在确保引擎不仅能够灵活应对多样化的定制需求,还具备出色的可维护性和可扩展性。具体而言,设计蓝图涵盖以下关键方面:

  1. **基础图形库:**构建一个丰富的基础图形类库,提供便捷的 API 来绘制常见的几何形状,如矩形、圆形、多边形、曲线等。这些基础图形应支持自定义样式和属性,以满足多样化的设计需求。
  2. **层级管理:**构建一个清晰的层级结构是绘制引擎的基础。这包括定义元素之间的堆叠顺序,如确保文字总是绘制在图表的上方,以及处理不同图表或元素之间的层级关系。层级管理将确保视觉呈现符合预期,即使在复杂的布局中也能保持清晰有序。
  3. **图形组的管理:**引入节点和组的概念,允许用户将多个图形元素组织成一个整体(即“组”)。这样的设计使得对组进行整体移动、缩放或变形时,组内所有元素都能同步响应,大大简化了复杂场景下的操作和管理。
  4. **变换矩阵:**对一个图形组执行平移、旋转、缩放等变形操作,从而以动态和灵活的方式调整图形的展示效果。为了实现这些变形操作,变形操作类通常会采用矩阵变换的原理。通过维护一个变换矩阵,并在绘制图形组之前应用该矩阵,可以一次性完成所有变形操作的计算,从而提高绘制效率。
  5. **事件系统:**集成一个高效的事件处理系统,允许用户将事件监听器绑定到单个图形元素或整个组上。这样,无论是用户交互(如点击、拖动)还是系统事件(如加载完成、数据更新),都能得到及时响应和处理。
  6. **应用层封装:**在应用层,我们需要封装绘制引擎提供的底层功能,使其更加贴近业务需求。这包括提供易于使用的 API 接口、优化性能、处理异常和错误等。同时,通过持续的应用层反馈,不断优化和调整绘制引擎,确保其能够更好地服务于业务的发展。

因此,在绘制引擎架构中,我们会首先实现一个节点类 Vertex,这个类代表了最原始的‘节点’的概念,所有可以被展示到 canvas 画布上的、各种类型的节点都会继承于这个类,这是一个抽象类,我们并不会直接实例化这个类。

这个类上面挂载了‘节点’的各种通用属性,比如:父元素、透明度、旋转角度、缩放、平移、节点是否可见等。

ts

为了进行图形组的管理,会继续实现一个容器类 Container,这个类代表了‘组’的概念,它提供了添加子元素,移除子元素等的方法;后续的要被渲染的一些类 (如 Graphics,Text,Sprite 等) 会继承于这个类;这个类本身不会被渲染 (因为它只是一个‘组’,它本身没有内容可以渲染)。

这个类继承于 Vertex 类,‘组’也算作‘节点’。

Graphics 这个类会用来构建一些几何图形元素;它会继承 Container 类。

在渲染引擎中,一切变换 (平移、旋转、缩放等) 都会转化成变换矩阵 (matrix),因为 canvas 只接受矩阵变换,虽然 canvas 为了开发的便捷,也提供了 ctx.rotate,ctx.scale 等操作,但是 canvas 中的这些操作会直接转换成变换矩阵,而不像 DOM 那样,有锚点的概念,所以 canvas 提供的 rotate,scale 等操作,和 DOM 提供的 rotate,scale 的表现是不一样的。

Matrix 类将会提供各种各样的与矩阵操作相关的函数 (矩阵相乘,矩阵求逆等),任何变换的叠加都将会转换成 matrix,方便我们调用 canvas 的指令。

Transform 类就类似 CSS 的 transform,它提供了一些更清晰、更符合人类直觉的变换,而不用直接使用矩阵变换,当然,这些变换最终会转换成矩阵变换。

线性变换从几何直观有三个要点:

  • 变换前是直线的,变换后依然是直线
  • 直线比例保持不变
  • 变换前是原点的,变换后依然是原点

比如有一个二维基向量

',18),s("r-math",{latex:"\\left[\\begin{matrix}x & 0 \\\\0 & y \\\\ \\end{matrix}\\right]"},null,-1),s("p",null,"旋转矩阵:",-1),s("r-math",{latex:"\\left[ \\begin{matrix} cos(r) & -sin(r) \\\\ sin(r) & cos(r) \\\\ \\end{matrix} \\right]"},null,-1),s("p",null,"浏览器的 skew:",-1),s("r-math",{latex:"\\left[ \\begin{matrix} 1 & tan(x) \\\\ tan(y) & 1 \\\\ \\end{matrix} \\right]"},null,-1),s("p",null,"pixijs 的 skew:",-1),s("r-math",{latex:"\\left[ \\begin{matrix} cos(y) & sin(x) \\\\ sin(y) & cos(x) \\\\ \\end{matrix} \\right]"},null,-1),i('

平移操作:

这里就需要仿射变换

仿射变换从几何直观只有两个要点:

  • 变换前是直线的,变换后依然是直线
  • 直线比例保持不变

少了原点保持不变这一条。

因此,平移不再是线性变化了,而是仿射变化。

每一个矩阵变换都是线性变换,反正则不成立。

仿射变换不能光通过矩阵乘法来实现,还得有加法。

主要用途是,通过高纬度的线性变换,模拟低维度的仿射变换。从而把平移操作也数据化。

实现曲线

二阶贝塞尔曲线

',11),s("r-math",{latex:"B(t) = (1-t)^2 \\mathbf{P_0} + 2t(1-t) \\mathbf{P_1} + t^2 \\mathbf{P_2}, \\quad t \\in [0, 1]"},null,-1),i(`

起点(P0):这是曲线开始的位置。在绘制过程中,曲线会精确地通过这个点。 控制点(P1):这个点是用来控制曲线形状和弯曲程度的。它不一定在曲线上,但会对曲线的走向产生重要影响。通过调整控制点的位置,可以改变曲线的弯曲程度和方向。 终点(P2):这是曲线结束的位置。同样地,曲线也会精确地通过这个点。

二 基础图形库:

常见的基础图形有:

  1. 椭圆
  2. 多边形
  3. 矩形
  4. 圆角矩形

先实现一个基础类,然后其他的所有图形类都继承这个抽象类:

ts
export abstract class Shape {
+  // 支持的所有几何图形都会继承自这个 Shape 基类
+  public abstract type: ShapeType;
+  constructor() {}
+}

其中ShapeType目前有以下几个属性:

ts
// 支持的形状类型
+export enum ShapeType {
+  Rectangle = 'rectangle',
+  Polygon = 'polygon',
+  Circle = 'circle',
+  Ellipse = 'ellipse',
+  RoundedRectangle = 'rounded rectangle',
+}

其中,我们只实现基础图形类的数据部分,渲染到逻辑统一到一个地方。尽量分离数据和实际的 UI 渲染操作。

1.圆

要绘制一个圆,只需要知道圆心和半径即可

数据类:

ts
export class Circle extends Shape {
+  public x: number;
+  public y: number;
+  public radius: number;
+  public readonly type = ShapeType.Circle;
+  constructor(x = 0, y = 0, radius = 0) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.radius = radius;
+  }
+}

绘制方法:

ts
const { x, y, radius } = circle;
+
+ctx.arc(x, y, radius, 0, 2 * Math.PI);
+
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fill();
+}
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.stroke();
+}

2.椭圆

椭圆的标准方程是:

`,17),s("r-math",{latex:"\\frac{x^2}{a^2} + \\frac{y^2}{b^2} = 1 \\quad (a > b > 0)"},null,-1),i(`

因此只需要圆心,长轴,短轴就可以确定一个圆,因此

ts
export class Ellipse extends Shape {
+  public x: number;
+  public y: number;
+  public radiusX: number;
+  public radiusY: number;
+  public readonly type = ShapeType.Ellipse;
+  constructor(x = 0, y = 0, radiusX = 0, radiusY = 0) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.radiusX = radiusX;
+    this.radiusY = radiusY;
+  }
+}

绘制方法:

ts
const { x, y, radiusX, radiusY } = ellipse;
+
+ctx.ellipse(x, y, radiusX, radiusY, 0, 0, Math.PI * 2);
+
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fill();
+}
+
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.stroke();
+}

3.多边形

多边形是由三条或三条以上不在同一直线上的线段首尾顺次连接所组成的封闭图形。这样的图形由多个点(称为顶点)和连接这些点的线段(称为边)构成,且所有边均在同一平面内。

简单来说,就是一个数组,里面很多个点的坐标,把点连起来,就是多边形了。

ts
export class Polygon extends Shape {
+  public points: number[]; // 多边形由多个点构成,points 数组每 2 个元素代表一个点的坐标
+  public closeStroke = false;
+  public readonly type = ShapeType.Polygon;
+  constructor(points: number[] = []) {
+    super();
+    this.points = points;
+  }
+}

绘制方法:

ts
const { points, closeStroke } = polygon;
+
+ctx.moveTo(points[0], points[1]);
+
+for (let i = 2; i < points.length; i += 2) {
+  ctx.lineTo(points[i], points[i + 1]);
+}
+
+if (closeStroke) {
+  ctx.closePath();
+}
+
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fill();
+}
+
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.stroke();
+}

4.矩形

ts
export class Rectangle extends Shape {
+  public x: number;
+  public y: number;
+  public width: number;
+  public height: number;
+  public type = ShapeType.Rectangle;
+  constructor(x = 0, y = 0, width = 0, height = 0) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+  }
+}

绘制方法:

ts
const { x, y, width, height } = rectangle;
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fillRect(x, y, width, height);
+}
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.strokeRect(x, y, width, height);
+}

5.圆角矩形

ts
export class RoundedRectangle extends Shape {
+  public x: number;
+  public y: number;
+  public width: number;
+  public height: number;
+  public radius: number;
+  public readonly type = ShapeType.RoundedRectangle;
+  constructor(x = 0, y = 0, width = 0, height = 0, radius = 20) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+
+    const r = Math.min(width, height) / 2;
+    this.radius = radius > r ? r : radius;
+  }
+}

绘制方法:

ts
const { x, y, width, height, radius } = roundedRectangle;
+ctx.moveTo(x + radius, y);
+ctx.arc(x + radius, y + radius, radius, Math.PI * 1.5, Math.PI, true);
+ctx.lineTo(x, y + height - radius);
+ctx.arc(x + radius, y + height - radius, radius, Math.PI, Math.PI / 2, true);
+ctx.lineTo(x + width - radius, y + height);
+ctx.arc(x + width - radius, y + height - radius, radius, Math.PI / 2, 0, true);
+ctx.lineTo(x + width, y + radius);
+ctx.arc(x + width - radius, y + radius, radius, 0, Math.PI * 1.5, true);
+ctx.closePath();
+
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fill();
+}
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.stroke();
+}

三 层级管理

在 canvas 绘图环境中,先绘制的图形会被后绘制的图形所覆盖,因此,层级的管理就自然地通过绘制顺序来实现。在这种情况下,最先被绘制的图形将位于最底层,而随后绘制的图形则逐层叠加,直至最上层。

我们已经实现了各种基础图形的绘制,接下来继续分离绘制时的数据和绘制操作。

我们需要一个容器类,在容器类中统一绘制所有的图形。

用一个 children 属性来添加所有的图形,在 render 方法中统一绘制。

同时,我们会根据 zIndex 属性来排序子元素,zIndex 越大的元素会被排在 children 数组的越后面,但是注意,排序的时候,要保证相同 zIndex 的相对顺序不变。

四 图形组的管理

我们会实现一个节点类 Vertex 这个类代表了最原始的‘节点’的概念,所有可以被展示到 canvas 画布上的、各种类型的节点都会继承于这个类,这是一个抽象类,我们并不会直接实例化这个类。

这个类上面挂载了‘节点’的各种属性,比如:父元素、透明度、旋转角度、缩放、平移、节点是否可见等。

为了进行图形组的管理,会继续实现一个容器类 Container,这个类代表了‘组’的概念,它提供了添加子元素,移除子元素等的方法;后续的要被渲染的一些类 (如 Graphics,Text,Sprite 等) 会继承于这个类;这个类本身不会被渲染 (因为它只是一个‘组’,它本身没有内容可以渲染)。

这个类继承于 Vertex 类,‘组’也算作‘节点’。

Graphics 这个类会用来构建一些几何图形元素;它会继承 Container 类。

在渲染引擎中,一切变换 (平移、旋转、缩放等) 都会转化成变换矩阵 (matrix),因为 canvas 只接受矩阵变换,虽然 canvas 为了开发的便捷,也提供了 ctx.rotate,ctx.scale 等操作,但是 canvas 中的这些操作会直接转换成变换矩阵,而不像 DOM 那样,有锚点的概念,所以 canvas 提供的 rotate,scale 等操作,和 DOM 提供的 rotate,scale 的表现是不一样的。

Matrix 类将会提供各种各样的与矩阵操作相关的函数 (矩阵相乘,矩阵求逆等),任何变换的叠加都将会转换成 matrix,方便我们调用 canvas 的指令。

Transform 类就类似 CSS 的 transform,它提供了一些更清晰、更符合人类直觉的变换,而不用直接使用矩阵变换,当然,这些变换最终会转换成矩阵变换。

参考资料:

  1. 如何通俗地讲解「仿射变换」?
  2. 仿射变换及其变换矩阵的理解
  3. 深入理解贝塞尔曲线
  4. 如何理解并应用贝塞尔曲线
`,35)]))}const F=h(k,[["render",p]]);export{y as __pageData,F as default}; diff --git a/assets/cn_src_article_visual.md.CDvSxrkl.lean.js b/assets/cn_src_article_visual.md.CDvSxrkl.lean.js new file mode 100644 index 0000000000..683273db18 --- /dev/null +++ b/assets/cn_src_article_visual.md.CDvSxrkl.lean.js @@ -0,0 +1,143 @@ +import{_ as h,o as n,c as l,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"实现曲线","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/article/visual.md","filePath":"cn/src/article/visual.md","lastUpdated":1726550590000}'),k={name:"cn/src/article/visual.md"};function p(t,a,e,E,r,d){return n(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

在业务持续演进的过程中,遭遇了高度定制化图表的需求。为了寻找解决方案,首先深入探索了现有的开源图表库,遗憾的是,这些库虽能覆盖大部分常见的功能,但在一些定制化设计上却显得力不从心,但 UI 层的定制化又是十分常见的。

为了精准复现设计愿景,我转而采用 canvas 技术手动绘制图表。这一过程中,尽管已尽力通过函数式编程范式封装和模块化绘制逻辑以提升代码的可维护性,但 canvas 的命令式特性在面临需求变动时,仍易导致直接而频繁的代码调整,影响了整体的开发效率和灵活性。

鉴于此,意识到,需要从更高层次的业务逻辑和设计理念出发,构建一个更为底层且灵活的图表绘制引擎。这样的引擎应能够抽象出绘制操作的核心要素,不仅服务于当前应用层的定制化需求,更应具备良好的扩展性和复用性,以便在未来面对更多样化的业务场景时,能够迅速响应并高效实现定制化图表的绘制需求。这样的策略转变,旨在从根本上提升图表定制化的开发效率和图表的维护性,确保业务迭代的顺畅进行。

一 技术设计

针对常见的绘制需求进行详尽的功能分析后,我们系统性地规划了高效且灵活的图表绘制引擎的核心构成要素。这些精心设计的组件旨在确保引擎不仅能够灵活应对多样化的定制需求,还具备出色的可维护性和可扩展性。具体而言,设计蓝图涵盖以下关键方面:

  1. **基础图形库:**构建一个丰富的基础图形类库,提供便捷的 API 来绘制常见的几何形状,如矩形、圆形、多边形、曲线等。这些基础图形应支持自定义样式和属性,以满足多样化的设计需求。
  2. **层级管理:**构建一个清晰的层级结构是绘制引擎的基础。这包括定义元素之间的堆叠顺序,如确保文字总是绘制在图表的上方,以及处理不同图表或元素之间的层级关系。层级管理将确保视觉呈现符合预期,即使在复杂的布局中也能保持清晰有序。
  3. **图形组的管理:**引入节点和组的概念,允许用户将多个图形元素组织成一个整体(即“组”)。这样的设计使得对组进行整体移动、缩放或变形时,组内所有元素都能同步响应,大大简化了复杂场景下的操作和管理。
  4. **变换矩阵:**对一个图形组执行平移、旋转、缩放等变形操作,从而以动态和灵活的方式调整图形的展示效果。为了实现这些变形操作,变形操作类通常会采用矩阵变换的原理。通过维护一个变换矩阵,并在绘制图形组之前应用该矩阵,可以一次性完成所有变形操作的计算,从而提高绘制效率。
  5. **事件系统:**集成一个高效的事件处理系统,允许用户将事件监听器绑定到单个图形元素或整个组上。这样,无论是用户交互(如点击、拖动)还是系统事件(如加载完成、数据更新),都能得到及时响应和处理。
  6. **应用层封装:**在应用层,我们需要封装绘制引擎提供的底层功能,使其更加贴近业务需求。这包括提供易于使用的 API 接口、优化性能、处理异常和错误等。同时,通过持续的应用层反馈,不断优化和调整绘制引擎,确保其能够更好地服务于业务的发展。

因此,在绘制引擎架构中,我们会首先实现一个节点类 Vertex,这个类代表了最原始的‘节点’的概念,所有可以被展示到 canvas 画布上的、各种类型的节点都会继承于这个类,这是一个抽象类,我们并不会直接实例化这个类。

这个类上面挂载了‘节点’的各种通用属性,比如:父元素、透明度、旋转角度、缩放、平移、节点是否可见等。

ts

为了进行图形组的管理,会继续实现一个容器类 Container,这个类代表了‘组’的概念,它提供了添加子元素,移除子元素等的方法;后续的要被渲染的一些类 (如 Graphics,Text,Sprite 等) 会继承于这个类;这个类本身不会被渲染 (因为它只是一个‘组’,它本身没有内容可以渲染)。

这个类继承于 Vertex 类,‘组’也算作‘节点’。

Graphics 这个类会用来构建一些几何图形元素;它会继承 Container 类。

在渲染引擎中,一切变换 (平移、旋转、缩放等) 都会转化成变换矩阵 (matrix),因为 canvas 只接受矩阵变换,虽然 canvas 为了开发的便捷,也提供了 ctx.rotate,ctx.scale 等操作,但是 canvas 中的这些操作会直接转换成变换矩阵,而不像 DOM 那样,有锚点的概念,所以 canvas 提供的 rotate,scale 等操作,和 DOM 提供的 rotate,scale 的表现是不一样的。

Matrix 类将会提供各种各样的与矩阵操作相关的函数 (矩阵相乘,矩阵求逆等),任何变换的叠加都将会转换成 matrix,方便我们调用 canvas 的指令。

Transform 类就类似 CSS 的 transform,它提供了一些更清晰、更符合人类直觉的变换,而不用直接使用矩阵变换,当然,这些变换最终会转换成矩阵变换。

线性变换从几何直观有三个要点:

  • 变换前是直线的,变换后依然是直线
  • 直线比例保持不变
  • 变换前是原点的,变换后依然是原点

比如有一个二维基向量

',18),s("r-math",{latex:"\\left[\\begin{matrix}x & 0 \\\\0 & y \\\\ \\end{matrix}\\right]"},null,-1),s("p",null,"旋转矩阵:",-1),s("r-math",{latex:"\\left[ \\begin{matrix} cos(r) & -sin(r) \\\\ sin(r) & cos(r) \\\\ \\end{matrix} \\right]"},null,-1),s("p",null,"浏览器的 skew:",-1),s("r-math",{latex:"\\left[ \\begin{matrix} 1 & tan(x) \\\\ tan(y) & 1 \\\\ \\end{matrix} \\right]"},null,-1),s("p",null,"pixijs 的 skew:",-1),s("r-math",{latex:"\\left[ \\begin{matrix} cos(y) & sin(x) \\\\ sin(y) & cos(x) \\\\ \\end{matrix} \\right]"},null,-1),i('

平移操作:

这里就需要仿射变换

仿射变换从几何直观只有两个要点:

  • 变换前是直线的,变换后依然是直线
  • 直线比例保持不变

少了原点保持不变这一条。

因此,平移不再是线性变化了,而是仿射变化。

每一个矩阵变换都是线性变换,反正则不成立。

仿射变换不能光通过矩阵乘法来实现,还得有加法。

主要用途是,通过高纬度的线性变换,模拟低维度的仿射变换。从而把平移操作也数据化。

实现曲线

二阶贝塞尔曲线

',11),s("r-math",{latex:"B(t) = (1-t)^2 \\mathbf{P_0} + 2t(1-t) \\mathbf{P_1} + t^2 \\mathbf{P_2}, \\quad t \\in [0, 1]"},null,-1),i(`

起点(P0):这是曲线开始的位置。在绘制过程中,曲线会精确地通过这个点。 控制点(P1):这个点是用来控制曲线形状和弯曲程度的。它不一定在曲线上,但会对曲线的走向产生重要影响。通过调整控制点的位置,可以改变曲线的弯曲程度和方向。 终点(P2):这是曲线结束的位置。同样地,曲线也会精确地通过这个点。

二 基础图形库:

常见的基础图形有:

  1. 椭圆
  2. 多边形
  3. 矩形
  4. 圆角矩形

先实现一个基础类,然后其他的所有图形类都继承这个抽象类:

ts
export abstract class Shape {
+  // 支持的所有几何图形都会继承自这个 Shape 基类
+  public abstract type: ShapeType;
+  constructor() {}
+}

其中ShapeType目前有以下几个属性:

ts
// 支持的形状类型
+export enum ShapeType {
+  Rectangle = 'rectangle',
+  Polygon = 'polygon',
+  Circle = 'circle',
+  Ellipse = 'ellipse',
+  RoundedRectangle = 'rounded rectangle',
+}

其中,我们只实现基础图形类的数据部分,渲染到逻辑统一到一个地方。尽量分离数据和实际的 UI 渲染操作。

1.圆

要绘制一个圆,只需要知道圆心和半径即可

数据类:

ts
export class Circle extends Shape {
+  public x: number;
+  public y: number;
+  public radius: number;
+  public readonly type = ShapeType.Circle;
+  constructor(x = 0, y = 0, radius = 0) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.radius = radius;
+  }
+}

绘制方法:

ts
const { x, y, radius } = circle;
+
+ctx.arc(x, y, radius, 0, 2 * Math.PI);
+
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fill();
+}
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.stroke();
+}

2.椭圆

椭圆的标准方程是:

`,17),s("r-math",{latex:"\\frac{x^2}{a^2} + \\frac{y^2}{b^2} = 1 \\quad (a > b > 0)"},null,-1),i(`

因此只需要圆心,长轴,短轴就可以确定一个圆,因此

ts
export class Ellipse extends Shape {
+  public x: number;
+  public y: number;
+  public radiusX: number;
+  public radiusY: number;
+  public readonly type = ShapeType.Ellipse;
+  constructor(x = 0, y = 0, radiusX = 0, radiusY = 0) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.radiusX = radiusX;
+    this.radiusY = radiusY;
+  }
+}

绘制方法:

ts
const { x, y, radiusX, radiusY } = ellipse;
+
+ctx.ellipse(x, y, radiusX, radiusY, 0, 0, Math.PI * 2);
+
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fill();
+}
+
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.stroke();
+}

3.多边形

多边形是由三条或三条以上不在同一直线上的线段首尾顺次连接所组成的封闭图形。这样的图形由多个点(称为顶点)和连接这些点的线段(称为边)构成,且所有边均在同一平面内。

简单来说,就是一个数组,里面很多个点的坐标,把点连起来,就是多边形了。

ts
export class Polygon extends Shape {
+  public points: number[]; // 多边形由多个点构成,points 数组每 2 个元素代表一个点的坐标
+  public closeStroke = false;
+  public readonly type = ShapeType.Polygon;
+  constructor(points: number[] = []) {
+    super();
+    this.points = points;
+  }
+}

绘制方法:

ts
const { points, closeStroke } = polygon;
+
+ctx.moveTo(points[0], points[1]);
+
+for (let i = 2; i < points.length; i += 2) {
+  ctx.lineTo(points[i], points[i + 1]);
+}
+
+if (closeStroke) {
+  ctx.closePath();
+}
+
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fill();
+}
+
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.stroke();
+}

4.矩形

ts
export class Rectangle extends Shape {
+  public x: number;
+  public y: number;
+  public width: number;
+  public height: number;
+  public type = ShapeType.Rectangle;
+  constructor(x = 0, y = 0, width = 0, height = 0) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+  }
+}

绘制方法:

ts
const { x, y, width, height } = rectangle;
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fillRect(x, y, width, height);
+}
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.strokeRect(x, y, width, height);
+}

5.圆角矩形

ts
export class RoundedRectangle extends Shape {
+  public x: number;
+  public y: number;
+  public width: number;
+  public height: number;
+  public radius: number;
+  public readonly type = ShapeType.RoundedRectangle;
+  constructor(x = 0, y = 0, width = 0, height = 0, radius = 20) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+
+    const r = Math.min(width, height) / 2;
+    this.radius = radius > r ? r : radius;
+  }
+}

绘制方法:

ts
const { x, y, width, height, radius } = roundedRectangle;
+ctx.moveTo(x + radius, y);
+ctx.arc(x + radius, y + radius, radius, Math.PI * 1.5, Math.PI, true);
+ctx.lineTo(x, y + height - radius);
+ctx.arc(x + radius, y + height - radius, radius, Math.PI, Math.PI / 2, true);
+ctx.lineTo(x + width - radius, y + height);
+ctx.arc(x + width - radius, y + height - radius, radius, Math.PI / 2, 0, true);
+ctx.lineTo(x + width, y + radius);
+ctx.arc(x + width - radius, y + radius, radius, 0, Math.PI * 1.5, true);
+ctx.closePath();
+
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fill();
+}
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.stroke();
+}

三 层级管理

在 canvas 绘图环境中,先绘制的图形会被后绘制的图形所覆盖,因此,层级的管理就自然地通过绘制顺序来实现。在这种情况下,最先被绘制的图形将位于最底层,而随后绘制的图形则逐层叠加,直至最上层。

我们已经实现了各种基础图形的绘制,接下来继续分离绘制时的数据和绘制操作。

我们需要一个容器类,在容器类中统一绘制所有的图形。

用一个 children 属性来添加所有的图形,在 render 方法中统一绘制。

同时,我们会根据 zIndex 属性来排序子元素,zIndex 越大的元素会被排在 children 数组的越后面,但是注意,排序的时候,要保证相同 zIndex 的相对顺序不变。

四 图形组的管理

我们会实现一个节点类 Vertex 这个类代表了最原始的‘节点’的概念,所有可以被展示到 canvas 画布上的、各种类型的节点都会继承于这个类,这是一个抽象类,我们并不会直接实例化这个类。

这个类上面挂载了‘节点’的各种属性,比如:父元素、透明度、旋转角度、缩放、平移、节点是否可见等。

为了进行图形组的管理,会继续实现一个容器类 Container,这个类代表了‘组’的概念,它提供了添加子元素,移除子元素等的方法;后续的要被渲染的一些类 (如 Graphics,Text,Sprite 等) 会继承于这个类;这个类本身不会被渲染 (因为它只是一个‘组’,它本身没有内容可以渲染)。

这个类继承于 Vertex 类,‘组’也算作‘节点’。

Graphics 这个类会用来构建一些几何图形元素;它会继承 Container 类。

在渲染引擎中,一切变换 (平移、旋转、缩放等) 都会转化成变换矩阵 (matrix),因为 canvas 只接受矩阵变换,虽然 canvas 为了开发的便捷,也提供了 ctx.rotate,ctx.scale 等操作,但是 canvas 中的这些操作会直接转换成变换矩阵,而不像 DOM 那样,有锚点的概念,所以 canvas 提供的 rotate,scale 等操作,和 DOM 提供的 rotate,scale 的表现是不一样的。

Matrix 类将会提供各种各样的与矩阵操作相关的函数 (矩阵相乘,矩阵求逆等),任何变换的叠加都将会转换成 matrix,方便我们调用 canvas 的指令。

Transform 类就类似 CSS 的 transform,它提供了一些更清晰、更符合人类直觉的变换,而不用直接使用矩阵变换,当然,这些变换最终会转换成矩阵变换。

参考资料:

  1. 如何通俗地讲解「仿射变换」?
  2. 仿射变换及其变换矩阵的理解
  3. 深入理解贝塞尔曲线
  4. 如何理解并应用贝塞尔曲线
`,35)]))}const F=h(k,[["render",p]]);export{y as __pageData,F as default}; diff --git a/assets/cn_src_note_centos.md.BW5LCWPK.js b/assets/cn_src_note_centos.md.BW5LCWPK.js new file mode 100644 index 0000000000..e9553fc081 --- /dev/null +++ b/assets/cn_src_note_centos.md.BW5LCWPK.js @@ -0,0 +1,22 @@ +import{_ as i,o as a,c as n,a3 as e}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"CentOS","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/note/centos.md","filePath":"cn/src/note/centos.md","lastUpdated":1726550590000}'),t={name:"cn/src/note/centos.md"};function p(l,s,h,k,r,d){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[e(`

CentOS

查看当前系统的版本:

sh
cat /etc/centos-release

YUM

YUM 是 Yellowdog Updater, Modified 的缩写,虽然不是 CentOS 开发的,但已成为 CentOS 系统中常用的包管理工具。YUM 作为 RPM 的前端程序,解决了 RPM 软件包之间的依赖性问题,并提供了更加便捷的软件包管理方式。

YUM 仓库源

CentOS 8 的官方支持已经结束,但您仍然可以使用 CentOS Stream 8 或其他第三方仓库。如果您正在使用 CentOS 8,并且希望继续使用类似的仓库,可以考虑切换到 CentOS Stream 8。

1.替换镜像源

由于众所周知的原因,访问官方镜像会非常慢,所以

修改 /etc/yum.repos.d/CentOS-AppStream.repo 文件(或相应的仓库配置文件),将 baseurl 或 mirrorlist 指向一个可用的源。

我个人尝试,发现需要修改三个文件:

sh
/etc/yum.repos.d/CentOS-Base.repo
+/etc/yum.repos.d/CentOS-AppStream.repo
+/etc/yum.repos.d/CentOS-Extras.repo

修改文件内容:

sh
[baseos]
+name=CentOS-8 - Base
+baseurl=http://vault.centos.org/8.5.2111/BaseOS/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[appstream]
+name=CentOS-8 - AppStream
+baseurl=http://vault.centos.org/8.5.2111/AppStream/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[extras]
+name=CentOS-8 - Extras
+baseurl=http://vault.centos.org/8.5.2111/extras/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial

更新缓存并重试

  1. 清理缓存:yum clean all
  2. 生成新的缓存:yum makecache
  3. 更新系统:yum update
`,16)]))}const g=i(t,[["render",p]]);export{E as __pageData,g as default}; diff --git a/assets/cn_src_note_centos.md.BW5LCWPK.lean.js b/assets/cn_src_note_centos.md.BW5LCWPK.lean.js new file mode 100644 index 0000000000..e9553fc081 --- /dev/null +++ b/assets/cn_src_note_centos.md.BW5LCWPK.lean.js @@ -0,0 +1,22 @@ +import{_ as i,o as a,c as n,a3 as e}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"CentOS","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/note/centos.md","filePath":"cn/src/note/centos.md","lastUpdated":1726550590000}'),t={name:"cn/src/note/centos.md"};function p(l,s,h,k,r,d){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[e(`

CentOS

查看当前系统的版本:

sh
cat /etc/centos-release

YUM

YUM 是 Yellowdog Updater, Modified 的缩写,虽然不是 CentOS 开发的,但已成为 CentOS 系统中常用的包管理工具。YUM 作为 RPM 的前端程序,解决了 RPM 软件包之间的依赖性问题,并提供了更加便捷的软件包管理方式。

YUM 仓库源

CentOS 8 的官方支持已经结束,但您仍然可以使用 CentOS Stream 8 或其他第三方仓库。如果您正在使用 CentOS 8,并且希望继续使用类似的仓库,可以考虑切换到 CentOS Stream 8。

1.替换镜像源

由于众所周知的原因,访问官方镜像会非常慢,所以

修改 /etc/yum.repos.d/CentOS-AppStream.repo 文件(或相应的仓库配置文件),将 baseurl 或 mirrorlist 指向一个可用的源。

我个人尝试,发现需要修改三个文件:

sh
/etc/yum.repos.d/CentOS-Base.repo
+/etc/yum.repos.d/CentOS-AppStream.repo
+/etc/yum.repos.d/CentOS-Extras.repo

修改文件内容:

sh
[baseos]
+name=CentOS-8 - Base
+baseurl=http://vault.centos.org/8.5.2111/BaseOS/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[appstream]
+name=CentOS-8 - AppStream
+baseurl=http://vault.centos.org/8.5.2111/AppStream/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[extras]
+name=CentOS-8 - Extras
+baseurl=http://vault.centos.org/8.5.2111/extras/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial

更新缓存并重试

  1. 清理缓存:yum clean all
  2. 生成新的缓存:yum makecache
  3. 更新系统:yum update
`,16)]))}const g=i(t,[["render",p]]);export{E as __pageData,g as default}; diff --git a/assets/cn_src_note_docker.md.C0hJL26s.js b/assets/cn_src_note_docker.md.C0hJL26s.js new file mode 100644 index 0000000000..cc95a50e2f --- /dev/null +++ b/assets/cn_src_note_docker.md.C0hJL26s.js @@ -0,0 +1,67 @@ +import{_ as i,o as a,c as e,a3 as l}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"docker","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/note/docker.md","filePath":"cn/src/note/docker.md","lastUpdated":1726550590000}'),n={name:"cn/src/note/docker.md"};function h(t,s,p,k,d,r){return a(),e("div",{"data-pagefind-body":!0},s[0]||(s[0]=[l(`

docker

查询 docker 是否在运行:

  1. 输入以下命令来查找 Docker 守护进程的 PID(进程 ID):
sh
ps -ef | grep docker

如果命令返回了包含/usr/local/bin/dockerd(或类似路径)的行,并且 PID 列有数字显示,那么 Docker 守护进程正在运行。

  1. 使用 docker ps 命令

虽然 docker ps 命令主要用于列出正在运行的容器,但如果 Docker 服务没有运行,该命令会返回一个错误消息。因此,你也可以通过运行该命令并观察输出来判断 Docker 服务是否启动。

如果 Docker 服务正在运行,该命令将列出所有正在运行的容器(如果没有运行的容器,则可能只显示表头)。如果 Docker 服务没有运行,你将看到一个错误消息,如“Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?”

  1. 使用 docker info 命令

docker info 命令提供 Docker 系统的详细信息,包括容器数量、镜像数量、Docker 版本等。如果 Docker 服务正在运行,该命令将正常输出这些信息。

如果 Docker 服务正在运行,你将看到一系列关于 Docker 系统的信息。如果 Docker 服务没有运行,你将看到一个错误消息,与 docker ps 命令类似。

安装 docker 的网站:https://hub.docker.com/

images

Docker 把应用程序及其依赖,打包在 image 文件里面。只有通过这个文件,才能生成 Docker 容器。image 文件可以看作容器的模板。Docker 根据 image 文件生成的容器实例。同一个 image 文件,可以生成多个同时运行的容器实例

image 是二进制文件。实际开发过程中,一个 image 文件往往通过继承另一个 image 文件,再加上一些个性化的设置而成。

shell
# 搜索镜像
+$ docker search [keywords]
+# 列出本机所有的image文件
+$docker image ls
+# 删除image文件
+$docker image rm [imageName]
+$docker image rmi [imageID]

从仓库拉取镜像

  • image 文件从仓库拉到本地
shell
$ docker image pull library/hello-world
+# docker image pull 是抓去image文件的命令。library/hello-world是image仓库的位置
+# 其中library是image文件所在的组,hello-world是image文件的名字
+
+# 由于官方提供的image文件,都在library里面,所以它是默认组,可以省略
+# 因此$ docker image pull hello-world
  • 抓取成功后,可以在本机看到这个 image 文件
shell
$ docker image ls
  • 运行/创建这个 image 文件
shell
$ docker container run hello-world
+# docker container run 命令会从image文件,生成一个正在运行的容器
+# 如果没有指定image文件,会从仓库自动抓取,docker image pull 不是必须
  • 运行 image 文件 (重复使用容器),docker container run 会新建容器,每运行一次,就会新建一个容器
shell
# 用来启动已生成,或者已经停止的容器文件
+$ docker container start [containerID]
  • 查看 docker 容器的输出
shell
# 命令用来查看docker容器的输出
+$ docker container logs [containerID]
+# docker run 命令运行容器的时候,没有-it参数,就药用这个来输出
  • 进入一个正在运行的 docker 容器
shell
# 如果docker run 命令运行容器的时候,没有使用-it参数,就可以使用这个进入容器
+$ docker container exec -it [containerID] /bin/bash
  • 关闭容器
shell
# 终止容器的运行,强行立即终止
+$ docker container kill [containeId]
+# 终止容器的运行,会自动进行收尾工作,可能不会终止
+$ docker container stop [containerId]

container

  • image 文件生成的容器实例,本身也是一个文件,称为容器文件。
  • 一旦容器生成,就会同时存在两个文件:image 文件和容器文件。关闭容器并不会删除容器文件,只是容器停止运行而已
shell
# 列出本机正在运行的容器
+$ docker container ls
+# 列出本机所有的容器,包括终止运行的容器
+$ docker container ls --all
  • 终止运行的容器文件,依然会占据硬盘空间,可以删除,删除完再查看就没有了
shell
$ docker container rm [containerID]

生成容器

  • docker container run 命令会从 image 文件生成容器
shell
$ docker container run -p 8000:3000 -it koa-demo /bin/bash
+# 或者
+$ docker container run -p 8000:3000 -it koa-demo:0.0.1 /bin/bash
+# -p 参数:容器的3000端口映射到本机器的8000端口
+# -it 参数:容器的shell映射到当前的shell,然后你在本机窗口输入命令,就会传入容器
+# koa-demo:0.0.1 image文件的名字(如果有标签,还需要提供标签,默认是latest标签)
+# /bin/bash: 容器启动以后,内部第一个执行的命令。这里是启动Bash,保证用户可以使用Shell。
  • 这就表示在容器里面了,可以执行命令了
shell
root@66d80f4aaf1e:/app# node demos/01.js
  • 需要注意的是,node 进程运行在 Docker 容器的虚拟环境里面,进程接触到的文件系统和网络接口都是虚拟的,与本机的文件系统和网络接口是隔离的,因此需要定义容器与物理机的端口映射
  • 停止容器,释放内存
shell
# 在容器的命令行,通过Ctrl + c停止node进程,然后Ctrl + d(或者输入exit)退出容器
+# 或者使用docker container kill终止容器运行
+# 可能需要本机的另一个终端窗口,查看容器的ID
+$ docker container ls
+# 或
+$ docker container ls --all
+# 停止容器的运行
+$ docker container kill [containerID]
+# 容器停止运行后,并不会消失,需要删除容器文件
+# 删除指定容器文件
+$ docker container rm [containerID]
+# 或
+# 通过--rm参数,在容器终止运行后自动删除容器文件
+$ docker container run --rm -p 8000:3000 -it koa-demo /bin/bash

DockerFile

  • 一个文本文件,用来配置 imageDocker 根据该文件生成二进制的 image 文件
  • 先获取一个项目
shell
$ git clone https://github.com/ruanyf/koa-demos.git
+$ cd koa-demos
  • 进入项目,编写 .dockerignore 文件。指的是下面三个路径要排除,不要打包进入 image 文件。
shell
.git
+node_modules
+npm-debug.log
  • 根目录下新建一个文本文件 Dockerfile
shell
FROM node:8.4
+# 该image文件继承官方的node image,冒号表示标签,这是8.4版本的node
+COPY . /app
+# .是当前目录下的所有文件(除了.dockerignore排除的文件),都拷贝进入image文件的/app目录
+WORKDIR /app
+# 指定接下来的工作路径为/app
+RUN npm install
+# 在/app目录下,运行npm install命令安装依赖。注意,安装后所有的依赖,都将打包进入image文件
+EXPOSE 3000
+# 将容器的3000端口暴露出来,允许外部连接这个端口
  • 有了 Dockerfile 文件以后,就可以使用 docker image build 命令创建 image 文件了。
shell
$ docker image build -t koa-demo .
+# 用-t参数来制定image文件的名字,最后的 . 代表Dockerfile文件所在的路径,因为是当前路径
+# 或者
+$ docker image build -t koa-demo:0.0.1 .
+# 后面还可以用冒号指定标签。如果不指定,默认标签就是latest。
+# 运行成功就可以用 docker image ls 来查看了

CMD 命令

  • 可以随着容器的启动而执行的命令,比如上个例子手动执行的 node demos/01.js。可以把这个命令写在 Dockerfile 里面
shell
FROM node:8.4
+COPY . /app
+WORKDIR /app
+RUN npm install --registry=https://registry.npm.taobao.org
+EXPOSR 3000
+# 表示容器启动后自动执行
+CMD node demos/01.js
  • CMD 命令和 RUN 命令的区别
    • RUN 命令在 image 文件的构建阶段执行,执行结果都会打包进行 image 文件
    • CMD 命令是容器启动后执行
    • 一个 dockerfile 可以有多个 RUN 命令,但只有一个 CMD 命令
    • 指定了 CMD 命令后,docker container run 命令就不能附加命令了 (比如前面的/bin/bash),否则他会覆盖 CMD 命令,现在可以使用
shell
$ docker container run --rm - p 8000:3000 -it koa-demo:0.0.1

问题:

  1. 如果遇到 docker desktop 登录不上,可以尝试 docker login进行登录,命令行登录会输出错误的信息,如果发现是网络问题,换一个代理即可。
  2. Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
shell
# docker服务没有启动
+$ service docker start

参考资料

`,62)]))}const F=i(n,[["render",h]]);export{c as __pageData,F as default}; diff --git a/assets/cn_src_note_docker.md.C0hJL26s.lean.js b/assets/cn_src_note_docker.md.C0hJL26s.lean.js new file mode 100644 index 0000000000..cc95a50e2f --- /dev/null +++ b/assets/cn_src_note_docker.md.C0hJL26s.lean.js @@ -0,0 +1,67 @@ +import{_ as i,o as a,c as e,a3 as l}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"docker","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/note/docker.md","filePath":"cn/src/note/docker.md","lastUpdated":1726550590000}'),n={name:"cn/src/note/docker.md"};function h(t,s,p,k,d,r){return a(),e("div",{"data-pagefind-body":!0},s[0]||(s[0]=[l(`

docker

查询 docker 是否在运行:

  1. 输入以下命令来查找 Docker 守护进程的 PID(进程 ID):
sh
ps -ef | grep docker

如果命令返回了包含/usr/local/bin/dockerd(或类似路径)的行,并且 PID 列有数字显示,那么 Docker 守护进程正在运行。

  1. 使用 docker ps 命令

虽然 docker ps 命令主要用于列出正在运行的容器,但如果 Docker 服务没有运行,该命令会返回一个错误消息。因此,你也可以通过运行该命令并观察输出来判断 Docker 服务是否启动。

如果 Docker 服务正在运行,该命令将列出所有正在运行的容器(如果没有运行的容器,则可能只显示表头)。如果 Docker 服务没有运行,你将看到一个错误消息,如“Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?”

  1. 使用 docker info 命令

docker info 命令提供 Docker 系统的详细信息,包括容器数量、镜像数量、Docker 版本等。如果 Docker 服务正在运行,该命令将正常输出这些信息。

如果 Docker 服务正在运行,你将看到一系列关于 Docker 系统的信息。如果 Docker 服务没有运行,你将看到一个错误消息,与 docker ps 命令类似。

安装 docker 的网站:https://hub.docker.com/

images

Docker 把应用程序及其依赖,打包在 image 文件里面。只有通过这个文件,才能生成 Docker 容器。image 文件可以看作容器的模板。Docker 根据 image 文件生成的容器实例。同一个 image 文件,可以生成多个同时运行的容器实例

image 是二进制文件。实际开发过程中,一个 image 文件往往通过继承另一个 image 文件,再加上一些个性化的设置而成。

shell
# 搜索镜像
+$ docker search [keywords]
+# 列出本机所有的image文件
+$docker image ls
+# 删除image文件
+$docker image rm [imageName]
+$docker image rmi [imageID]

从仓库拉取镜像

  • image 文件从仓库拉到本地
shell
$ docker image pull library/hello-world
+# docker image pull 是抓去image文件的命令。library/hello-world是image仓库的位置
+# 其中library是image文件所在的组,hello-world是image文件的名字
+
+# 由于官方提供的image文件,都在library里面,所以它是默认组,可以省略
+# 因此$ docker image pull hello-world
  • 抓取成功后,可以在本机看到这个 image 文件
shell
$ docker image ls
  • 运行/创建这个 image 文件
shell
$ docker container run hello-world
+# docker container run 命令会从image文件,生成一个正在运行的容器
+# 如果没有指定image文件,会从仓库自动抓取,docker image pull 不是必须
  • 运行 image 文件 (重复使用容器),docker container run 会新建容器,每运行一次,就会新建一个容器
shell
# 用来启动已生成,或者已经停止的容器文件
+$ docker container start [containerID]
  • 查看 docker 容器的输出
shell
# 命令用来查看docker容器的输出
+$ docker container logs [containerID]
+# docker run 命令运行容器的时候,没有-it参数,就药用这个来输出
  • 进入一个正在运行的 docker 容器
shell
# 如果docker run 命令运行容器的时候,没有使用-it参数,就可以使用这个进入容器
+$ docker container exec -it [containerID] /bin/bash
  • 关闭容器
shell
# 终止容器的运行,强行立即终止
+$ docker container kill [containeId]
+# 终止容器的运行,会自动进行收尾工作,可能不会终止
+$ docker container stop [containerId]

container

  • image 文件生成的容器实例,本身也是一个文件,称为容器文件。
  • 一旦容器生成,就会同时存在两个文件:image 文件和容器文件。关闭容器并不会删除容器文件,只是容器停止运行而已
shell
# 列出本机正在运行的容器
+$ docker container ls
+# 列出本机所有的容器,包括终止运行的容器
+$ docker container ls --all
  • 终止运行的容器文件,依然会占据硬盘空间,可以删除,删除完再查看就没有了
shell
$ docker container rm [containerID]

生成容器

  • docker container run 命令会从 image 文件生成容器
shell
$ docker container run -p 8000:3000 -it koa-demo /bin/bash
+# 或者
+$ docker container run -p 8000:3000 -it koa-demo:0.0.1 /bin/bash
+# -p 参数:容器的3000端口映射到本机器的8000端口
+# -it 参数:容器的shell映射到当前的shell,然后你在本机窗口输入命令,就会传入容器
+# koa-demo:0.0.1 image文件的名字(如果有标签,还需要提供标签,默认是latest标签)
+# /bin/bash: 容器启动以后,内部第一个执行的命令。这里是启动Bash,保证用户可以使用Shell。
  • 这就表示在容器里面了,可以执行命令了
shell
root@66d80f4aaf1e:/app# node demos/01.js
  • 需要注意的是,node 进程运行在 Docker 容器的虚拟环境里面,进程接触到的文件系统和网络接口都是虚拟的,与本机的文件系统和网络接口是隔离的,因此需要定义容器与物理机的端口映射
  • 停止容器,释放内存
shell
# 在容器的命令行,通过Ctrl + c停止node进程,然后Ctrl + d(或者输入exit)退出容器
+# 或者使用docker container kill终止容器运行
+# 可能需要本机的另一个终端窗口,查看容器的ID
+$ docker container ls
+# 或
+$ docker container ls --all
+# 停止容器的运行
+$ docker container kill [containerID]
+# 容器停止运行后,并不会消失,需要删除容器文件
+# 删除指定容器文件
+$ docker container rm [containerID]
+# 或
+# 通过--rm参数,在容器终止运行后自动删除容器文件
+$ docker container run --rm -p 8000:3000 -it koa-demo /bin/bash

DockerFile

  • 一个文本文件,用来配置 imageDocker 根据该文件生成二进制的 image 文件
  • 先获取一个项目
shell
$ git clone https://github.com/ruanyf/koa-demos.git
+$ cd koa-demos
  • 进入项目,编写 .dockerignore 文件。指的是下面三个路径要排除,不要打包进入 image 文件。
shell
.git
+node_modules
+npm-debug.log
  • 根目录下新建一个文本文件 Dockerfile
shell
FROM node:8.4
+# 该image文件继承官方的node image,冒号表示标签,这是8.4版本的node
+COPY . /app
+# .是当前目录下的所有文件(除了.dockerignore排除的文件),都拷贝进入image文件的/app目录
+WORKDIR /app
+# 指定接下来的工作路径为/app
+RUN npm install
+# 在/app目录下,运行npm install命令安装依赖。注意,安装后所有的依赖,都将打包进入image文件
+EXPOSE 3000
+# 将容器的3000端口暴露出来,允许外部连接这个端口
  • 有了 Dockerfile 文件以后,就可以使用 docker image build 命令创建 image 文件了。
shell
$ docker image build -t koa-demo .
+# 用-t参数来制定image文件的名字,最后的 . 代表Dockerfile文件所在的路径,因为是当前路径
+# 或者
+$ docker image build -t koa-demo:0.0.1 .
+# 后面还可以用冒号指定标签。如果不指定,默认标签就是latest。
+# 运行成功就可以用 docker image ls 来查看了

CMD 命令

  • 可以随着容器的启动而执行的命令,比如上个例子手动执行的 node demos/01.js。可以把这个命令写在 Dockerfile 里面
shell
FROM node:8.4
+COPY . /app
+WORKDIR /app
+RUN npm install --registry=https://registry.npm.taobao.org
+EXPOSR 3000
+# 表示容器启动后自动执行
+CMD node demos/01.js
  • CMD 命令和 RUN 命令的区别
    • RUN 命令在 image 文件的构建阶段执行,执行结果都会打包进行 image 文件
    • CMD 命令是容器启动后执行
    • 一个 dockerfile 可以有多个 RUN 命令,但只有一个 CMD 命令
    • 指定了 CMD 命令后,docker container run 命令就不能附加命令了 (比如前面的/bin/bash),否则他会覆盖 CMD 命令,现在可以使用
shell
$ docker container run --rm - p 8000:3000 -it koa-demo:0.0.1

问题:

  1. 如果遇到 docker desktop 登录不上,可以尝试 docker login进行登录,命令行登录会输出错误的信息,如果发现是网络问题,换一个代理即可。
  2. Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
shell
# docker服务没有启动
+$ service docker start

参考资料

`,62)]))}const F=i(n,[["render",h]]);export{c as __pageData,F as default}; diff --git a/assets/cn_src_note_libreoffice2wasm.md.CiwyBD9N.js b/assets/cn_src_note_libreoffice2wasm.md.CiwyBD9N.js new file mode 100644 index 0000000000..efe4b2ee86 --- /dev/null +++ b/assets/cn_src_note_libreoffice2wasm.md.CiwyBD9N.js @@ -0,0 +1,69 @@ +import{_ as i,o as a,c as e,a3 as l}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"克隆 Binaryen 仓库","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/note/libreoffice2wasm.md","filePath":"cn/src/note/libreoffice2wasm.md","lastUpdated":1726550590000}'),n={name:"cn/src/note/libreoffice2wasm.md"};function t(p,s,h,k,d,r){return a(),e("div",{"data-pagefind-body":!0},s[0]||(s[0]=[l(`

项目地址:

sh
git clone https://git.libreoffice.org/core

github 地址:https://github.com/LibreOffice/core/blob/master/static/README.wasm.md

容器化环境

由于是 c/c++ 的项目,编译过程需要很多系统级别配置。如果当前设备不支持的话,不建议强行去适配。可以进行容器化处理。

比如用一个最常见的服务器系统:

sh
docker image pull ubuntu

下载完成后,就可以去构建一个服务了:

sh
docker container run -p 30105:30105 --name=alit -itd ubuntu /bin/bash

构建并启动成功后,可以通过docker container ls去查看运行情况:

sh
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS                      NAMES
+efd831ab0ba8   ubuntu    "/bin/bash"   5 seconds ago   Up 4 seconds   0.0.0.0:30105->30105/tcp   alit

再将项目移动到容器中:

sh
docker cp ./core alit:/home
+# 总的来说,项目还是非常大的
+# Successfully copied 3.59GB to alit:/home

进入容器,进行操作。

sh
docker exec -it alit /bin/bash

这样,就可以把开发构建环境和电脑系统隔离开,防止一些系统级别不安全的操作了。

安装必要的依赖:

sh
dnf install -y git cmake python3 nodejs
+
+## 遇到问题:
+
+1. 执行 \`./autogen.sh\`报错,提示\`Failed to run aclocal at ./autogen.sh line 195.\`
+
+\`\`\`sh
+brew install automake

安装完成后,执行aclocal --version或者automake --version检查是否安装完成

  1. 执行 ./autogen.sh遇到报错:
sh
checking the GNU Make version... configure: error: failed (/usr/bin/make version >= 4.0 needed)
+Error running configure at ./autogen.sh line 323.

通过 make --version 检查 make 的版本,执行 brew install make,再执行 brew upgrade 进行升级。确保 make的版本大于 4.0

当使用 brew 安装 GNU Make 时,它通常会被命名为 gmake 而不是 make ,以区分于 macOS 系统自带的 BSD Make。如果你希望在使用 make 命令时实际上调用 gmake ,需要进行一些特殊处理来替换或设置别名。

在.zshrc 文件中添加如下行:

sh
# Configure the brew installation of gmake, alias to make
+alias make='gmake'

然后,保存文件并重新加载配置文件(通过 source ~/.zshrc 或重新打开终端)。

在项目中搜索并替换成:

sh
# args.makecmd = '/usr/bin/make'
+args.makecmd = '/opt/homebrew/bin/gmake'

在编译完成后,找到可执行的文件:

sh
find . -name soffice

然后执行

sh
/home/core/instdir/program/soffice --headless --convert-to pdf /home/office/pptx.pptx

将 LibreOffice 编译成 WebAssembly 并在 Web 上运行特定命令(如 soffice --headless --convert-to pdf /home/office/pptx.pptx)是一个复杂的任务。以下是一个大致的实现步骤和思路:

  1. 编译 LibreOffice 为 WebAssembly 假设你已经成功编译了 LibreOffice 并生成了 .wasm 文件和相关的 JavaScript 文件。

  2. 创建 HTML 和 JavaScript 文件 创建一个 HTML 文件来加载 WebAssembly 模块,并编写 JavaScript 代码来调用 soffice 命令。

HTML 文件 (index.html)

html
<!doctype html>
+<html>
+  <head>
+    <title>LibreOffice WebAssembly</title>
+    <script src="libreoffice.js"></script>
+  </head>
+  <body>
+    <input type="file" id="fileInput" />
+    <button onclick="convertToPDF()">Convert to PDF</button>
+    <script src="main.js"></script>
+  </body>
+</html>
+JavaScript 文件 (main.js) // Initialize the Module var Module = { onRuntimeInitialized: function() {
+console.log("LibreOffice WebAssembly Module Loaded"); } }; // Function to convert file to PDF function convertToPDF() {
+var fileInput = document.getElementById('fileInput'); if (fileInput.files.length == 0) { alert("Please select a file.");
+return; } var file = fileInput.files[0]; var reader = new FileReader(); reader.onload = function(event) { var
+arrayBuffer = event.target.result; var byteArray = new Uint8Array(arrayBuffer); // Write the file to the WASM virtual
+file system var filename = '/home/office/' + file.name; Module.FS_createDataFile('/', filename, byteArray, true, true);
+// Call the soffice command var command = 'soffice --headless --convert-to pdf ' + filename; Module.ccall( 'system', //
+name of C function 'number', // return type ['string'], // argument types [command] // arguments ); // Read the output
+PDF file var outputFilename = '/home/office/' + file.name.replace(/\\.[^/.]+$/, "") + '.pdf'; var output =
+Module.FS_readFile(outputFilename); // Create a blob and a link to download the PDF var blob = new Blob([output], {
+type: 'application/pdf' }); var link = document.createElement('a'); link.href = window.URL.createObjectURL(blob);
+link.download = file.name.replace(/\\.[^/.]+$/, "") + '.pdf'; link.click(); }; reader.readAsArrayBuffer(file); }
  1. 部署和测试 将生成的 .wasm 文件、JavaScript 文件和 HTML 文件部署到你的 Web 服务器上,打开 index.html 文件,选择一个 PPTX 文件并点击“Convert to PDF”按钮。这个过程会:

从文件输入中读取 PPTX 文件。 将文件写入 WebAssembly 模块的虚拟文件系统。 调用 soffice --headless --convert-to pdf 命令进行转换。 从虚拟文件系统中读取生成的 PDF 文件。 创建一个下载链接,允许用户下载生成的 PDF 文件。4. 注意事项 这个过程可能需要大量的内存和计算资源,可能需要优化和调整。 需要确保 Emscripten 的文件系统(MEMFS)能够正确处理大文件。 需要处理可能的错误和异常情况,并提供用户友好的错误提示。 通过这些步骤,你应该能够在 Web 上调用 soffice 命令并将 PPTX 文件转换为 PDF。如果遇到具体问题,请提供详细的错误信息,以便更好地帮助你解决问题。

减少 WebAssembly 文件的体积是一个常见的需求,尤其是在处理像 LibreOffice 这样的大型项目时。如果你只需要特定的功能(如将文件转换为 PDF),可以采取以下几种方法来减小生成的 WebAssembly 文件的体积:

  1. 精简功能模块 确保只编译你需要的功能模块。你已经在 autogen.input 中指定了 --with-main-module=writer,这会限制编译的模块,但你可以进一步精简。

  2. 移除不必要的组件 在 autogen.input 中,进一步禁用不必要的组件和功能。例如:

--disable-dbus --disable-odk --disable-postgresql-sdbc --disable-firebird-sdbc --disable-coinmp --disable-cve-tests --disable-gtk3 --disable-gstreamer-1-0 --disable-kf5 --disable-scripting-beanshell --disable-scripting-javascript --disable-extensions --disable-epm --disable-online-update --disable-python --disable-pdfimport --disable-lpsolve --disable-sdremote --disable-scripting --disable-avmedia --disable-coinmp --disable-report-builder --disable-odk --disable-pch --disable-skia --disable-scripting

  1. 使用 Emscripten 优化选项 Emscripten 提供了多种优化选项,可以帮助减小生成的 WebAssembly 文件的体积:

使用 -O3 或 -Oz 进行最大化优化。 使用 --closure 1 进行 JavaScript 代码的闭包优化。 使用 --llvm-lto 3 进行链接时间优化。 在编译时,确保使用这些选项:

emconfigure ./configure ... emmake make CXXFLAGS="-O3 --llvm-lto 3" LDFLAGS="-O3 --llvm-lto 3" 4. 移除调试信息 确保移除所有调试信息,这可以显著减小文件体积:

emconfigure ./configure ... emmake make CXXFLAGS="-O3 --llvm-lto 3 -g0" LDFLAGS="-O3 --llvm-lto 3 -g0" 5. 使用 WebAssembly Minifier 使用 WebAssembly Minifier 工具(如 wasm-opt)进一步优化和减小生成的 WebAssembly 文件:

wasm-opt -Oz -o optimized.wasm original.wasm 6. 自定义构建脚本 如果上述方法仍然不能满足需求,可以考虑编写自定义构建脚本,只包含必要的源文件和库,进一步精简生成的 WebAssembly 文件。

  1. 动态加载模块 如果可能,将一些功能模块拆分为单独的 WebAssembly 文件,并在需要时动态加载,以减少初始加载的体积。

示例 autogen.input 以下是一个示例 autogen.input 文件,结合了上述建议:

sh
--disable-debug
+--enable-sal-log
+--disable-crashdump
+--host=wasm32-local-emscripten
+--disable-gui
+--with-main-module=writer
+--with-package-format=emscripten
+--disable-dbus
+--disable-odk
+--disable-postgresql-sdbc
+--disable-firebird-sdbc
+--disable-coinmp
+--disable-cve-tests
+--disable-gtk3
+--disable-gstreamer-1-0
+--disable-kf5
+--disable-scripting-beanshell
+--disable-scripting-javascript
+--disable-extensions
+--disable-epm
+--disable-online-update
+--disable-python
+--disable-pdfimport
+--disable-lpsolve
+--disable-sdremote
+--disable-scripting
+--disable-avmedia
+--disable-coinmp
+--disable-report-builder
+--disable-odk
+--disable-pch
+--disable-skia
+--disable-scripting

通过这些步骤,你应该能够显著减小生成的 WebAssembly 文件的体积,同时保留将文件转换为 PDF 的功能。如果遇到具体问题,请提供详细的错误信息,以便更好地帮助你解决问题。

wasm-opt 是 Binaryen 项目的一部分,它是一个用于优化和处理 WebAssembly 二进制文件的工具。你可以在 Ubuntu 上通过以下步骤安装和使用 wasm-opt:

  1. 安装依赖项 首先,确保你的系统上已经安装了必要的依赖项:

sudo apt update sudo apt install cmake build-essential git 2. 下载和编译 Binaryen 接下来,从源码编译 Binaryen:

克隆 Binaryen 仓库

git clone https://github.com/WebAssembly/binaryen.git cd binaryen

创建并进入构建目录

mkdir build cd build

使用 CMake 配置构建

cmake ..

编译 Binaryen

make

安装 Binaryen

sudo make install 3. 使用 wasm-opt 安装完成后,你可以使用 wasm-opt 命令来优化 WebAssembly 文件。例如:

假设你有一个名为 original.wasm 的 WebAssembly 文件

wasm-opt -Oz -o optimized.wasm original.wasm 在这个命令中:

-Oz 表示进行最大化的尺寸优化。 -o optimized.wasm 指定输出文件名为 optimized.wasm。 original.wasm 是输入的 WebAssembly 文件。4. 验证安装 你可以通过运行以下命令来验证 wasm-opt 是否正确安装:

wasm-opt --version 这将输出 wasm-opt 的版本信息,确认它已成功安装并可以使用。

示例 假设你有一个名为 example.wasm 的 WebAssembly 文件,你可以通过以下命令优化它:

wasm-opt -Oz -o example_optimized.wasm example.wasm 这将生成一个优化后的 WebAssembly 文件 example_optimized.wasm,其体积通常会显著减小。

通过这些步骤,你应该能够在 Ubuntu 上成功安装和使用 wasm-opt 来优化你的 WebAssembly 文件。如果在安装或使用过程中遇到任何问题,请提供详细的错误信息,以便进一步帮助你解决问题。

--disable-debug --enable-sal-log --disable-crashdump --host=wasm32-local-emscripten --disable-gui --with-main-module=writer --with-package-format=emscripten --disable-dbus --disable-odk --disable-postgresql-sdbc --disable-firebird-sdbc --disable-coinmp --disable-cve-tests --disable-gtk3 --disable-gstreamer-1-0 --disable-kf5 --disable-scripting-beanshell --disable-scripting-javascript --disable-extensions --disable-epm --disable-online-update --disable-python --disable-pdfimport --disable-lpsolve --disable-sdremote --disable-scripting --disable-avmedia --disable-coinmp --disable-report-builder --disable-odk --disable-pch --disable-skia --disable-scripting

步骤 1:下载最新的 OpenSSL 源代码 首先,确保你在一个干净的目录中,然后下载最新版本的 OpenSSL 源代码。你可以访问 OpenSSL 官方网站 查看最新版本。假设最新版本是 openssl-3.0.9:

wget https://www.openssl.org/source/openssl-3.0.9.tar.gz tar -xzvf openssl-3.0.9.tar.gz cd openssl-3.0.9 步骤 2:编译和安装 OpenSSL 接下来,编译并安装 OpenSSL:

./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl shared zlib make make test make install 步骤 3:确认 OpenSSL 安装路径 确保 OpenSSL 的头文件和库文件已正确安装:

ls /usr/local/ssl/include ls /usr/local/ssl/lib 步骤 4:设置环境变量 设置正确的环境变量,以便编译时能找到 OpenSSL:

export PKG_CONFIG_PATH="/usr/local/ssl/lib/pkgconfig" export CFLAGS="-I/usr/local/ssl/include" export LDFLAGS="-L/usr/local/ssl/lib -lssl -lcrypto" 步骤 5:清理之前的配置 在重新运行 configure 脚本之前,清理之前的配置:

make clean 步骤 6:重新运行 configure 脚本 重新运行 configure 脚本,以确保它能找到新的 OpenSSL 版本:

emconfigure ./configure --disable-debug --enable-sal-log --disable-crashdump --host=wasm32-local-emscripten --disable-gui --with-main-module=writer --with-package-format=emscripten --disable-dbus --disable-odk --disable-postgresql-sdbc --disable-firebird-sdbc --disable-coinmp --disable-cve-tests --disable-gtk3 --disable-gstreamer-1-0 --disable-kf5 --disable-scripting-beanshell --disable-scripting-javascript --disable-extensions --disable-epm --disable-online-update --disable-python --disable-pdfimport --disable-lpsolve --disable-sdremote --disable-scripting --disable-avmedia --disable-coinmp --disable-report-builder --disable-odk --disable-pch --disable-skia --disable-scripting --srcdir=/home/core --enable-option-checking=fatal --disable-pthreads 步骤 7:检查 config.log 如果配置仍然失败,请检查 config.log 文件以获取更多详细信息:

cat config.log | grep openssl 通过确保 OpenSSL 已正确安装并设置正确的环境变量,我们应该能够解决配置过程中遇到的问题。如果问题仍然存在,请提供 config.log 文件中与 OpenSSL 相关的更多详细信息,以便进一步诊断和解决问题。

emconfigure ./configure --disable-debug --enable-sal-log --disable-crashdump --host=wasm32-local-emscripten --disable-gui --with-main-module=writer --with-package-format=emscripten --disable-dbus --disable-odk --disable-postgresql-sdbc --disable-firebird-sdbc --disable-coinmp --disable-cve-tests --disable-gtk3 --disable-gstreamer-1-0 --disable-kf5 --disable-scripting-beanshell --disable-scripting-javascript --disable-extensions --disable-epm --disable-online-update --disable-python --disable-pdfimport --disable-lpsolve --disable-sdremote --disable-scripting --disable-avmedia --disable-coinmp --disable-report-builder --disable-odk --disable-pch --disable-skia --disable-scripting --srcdir=/home/core --enable-option-checking=fatal

emmake make CXXFLAGS="-I/usr/local/ssl/include -O3 -g0 -msimd128" LDFLAGS="-L/usr/local/ssl/lib -lssl -lcrypto -O3 -g0"

emconfigure ./configure --disable-cups --disable-dbus --without-system-fontconfig --with-system-zlib --disable-dynamic-loading --disable-gui CXXFLAGS=-std=c++20 --host=wasm32-unknown-emscripten

root@8cb3480a4441:/home/core/instsetoo_native# vim CustomTarget_emscripten-install.mk

使用 file_packager.py 工具将文件预加载到虚拟文件系统中。确保 Emscripten 的环境变量已经正确设置,然后运行以下命令:

python3 /home/emsdk/upstream/emscripten/tools/file_packager.py preload.data --preload /home/core/instdir/share@/instdir/share --js-output=preload.js

`,85)]))}const g=i(n,[["render",t]]);export{c as __pageData,g as default}; diff --git a/assets/cn_src_note_libreoffice2wasm.md.CiwyBD9N.lean.js b/assets/cn_src_note_libreoffice2wasm.md.CiwyBD9N.lean.js new file mode 100644 index 0000000000..efe4b2ee86 --- /dev/null +++ b/assets/cn_src_note_libreoffice2wasm.md.CiwyBD9N.lean.js @@ -0,0 +1,69 @@ +import{_ as i,o as a,c as e,a3 as l}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"克隆 Binaryen 仓库","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/note/libreoffice2wasm.md","filePath":"cn/src/note/libreoffice2wasm.md","lastUpdated":1726550590000}'),n={name:"cn/src/note/libreoffice2wasm.md"};function t(p,s,h,k,d,r){return a(),e("div",{"data-pagefind-body":!0},s[0]||(s[0]=[l(`

项目地址:

sh
git clone https://git.libreoffice.org/core

github 地址:https://github.com/LibreOffice/core/blob/master/static/README.wasm.md

容器化环境

由于是 c/c++ 的项目,编译过程需要很多系统级别配置。如果当前设备不支持的话,不建议强行去适配。可以进行容器化处理。

比如用一个最常见的服务器系统:

sh
docker image pull ubuntu

下载完成后,就可以去构建一个服务了:

sh
docker container run -p 30105:30105 --name=alit -itd ubuntu /bin/bash

构建并启动成功后,可以通过docker container ls去查看运行情况:

sh
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS                      NAMES
+efd831ab0ba8   ubuntu    "/bin/bash"   5 seconds ago   Up 4 seconds   0.0.0.0:30105->30105/tcp   alit

再将项目移动到容器中:

sh
docker cp ./core alit:/home
+# 总的来说,项目还是非常大的
+# Successfully copied 3.59GB to alit:/home

进入容器,进行操作。

sh
docker exec -it alit /bin/bash

这样,就可以把开发构建环境和电脑系统隔离开,防止一些系统级别不安全的操作了。

安装必要的依赖:

sh
dnf install -y git cmake python3 nodejs
+
+## 遇到问题:
+
+1. 执行 \`./autogen.sh\`报错,提示\`Failed to run aclocal at ./autogen.sh line 195.\`
+
+\`\`\`sh
+brew install automake

安装完成后,执行aclocal --version或者automake --version检查是否安装完成

  1. 执行 ./autogen.sh遇到报错:
sh
checking the GNU Make version... configure: error: failed (/usr/bin/make version >= 4.0 needed)
+Error running configure at ./autogen.sh line 323.

通过 make --version 检查 make 的版本,执行 brew install make,再执行 brew upgrade 进行升级。确保 make的版本大于 4.0

当使用 brew 安装 GNU Make 时,它通常会被命名为 gmake 而不是 make ,以区分于 macOS 系统自带的 BSD Make。如果你希望在使用 make 命令时实际上调用 gmake ,需要进行一些特殊处理来替换或设置别名。

在.zshrc 文件中添加如下行:

sh
# Configure the brew installation of gmake, alias to make
+alias make='gmake'

然后,保存文件并重新加载配置文件(通过 source ~/.zshrc 或重新打开终端)。

在项目中搜索并替换成:

sh
# args.makecmd = '/usr/bin/make'
+args.makecmd = '/opt/homebrew/bin/gmake'

在编译完成后,找到可执行的文件:

sh
find . -name soffice

然后执行

sh
/home/core/instdir/program/soffice --headless --convert-to pdf /home/office/pptx.pptx

将 LibreOffice 编译成 WebAssembly 并在 Web 上运行特定命令(如 soffice --headless --convert-to pdf /home/office/pptx.pptx)是一个复杂的任务。以下是一个大致的实现步骤和思路:

  1. 编译 LibreOffice 为 WebAssembly 假设你已经成功编译了 LibreOffice 并生成了 .wasm 文件和相关的 JavaScript 文件。

  2. 创建 HTML 和 JavaScript 文件 创建一个 HTML 文件来加载 WebAssembly 模块,并编写 JavaScript 代码来调用 soffice 命令。

HTML 文件 (index.html)

html
<!doctype html>
+<html>
+  <head>
+    <title>LibreOffice WebAssembly</title>
+    <script src="libreoffice.js"></script>
+  </head>
+  <body>
+    <input type="file" id="fileInput" />
+    <button onclick="convertToPDF()">Convert to PDF</button>
+    <script src="main.js"></script>
+  </body>
+</html>
+JavaScript 文件 (main.js) // Initialize the Module var Module = { onRuntimeInitialized: function() {
+console.log("LibreOffice WebAssembly Module Loaded"); } }; // Function to convert file to PDF function convertToPDF() {
+var fileInput = document.getElementById('fileInput'); if (fileInput.files.length == 0) { alert("Please select a file.");
+return; } var file = fileInput.files[0]; var reader = new FileReader(); reader.onload = function(event) { var
+arrayBuffer = event.target.result; var byteArray = new Uint8Array(arrayBuffer); // Write the file to the WASM virtual
+file system var filename = '/home/office/' + file.name; Module.FS_createDataFile('/', filename, byteArray, true, true);
+// Call the soffice command var command = 'soffice --headless --convert-to pdf ' + filename; Module.ccall( 'system', //
+name of C function 'number', // return type ['string'], // argument types [command] // arguments ); // Read the output
+PDF file var outputFilename = '/home/office/' + file.name.replace(/\\.[^/.]+$/, "") + '.pdf'; var output =
+Module.FS_readFile(outputFilename); // Create a blob and a link to download the PDF var blob = new Blob([output], {
+type: 'application/pdf' }); var link = document.createElement('a'); link.href = window.URL.createObjectURL(blob);
+link.download = file.name.replace(/\\.[^/.]+$/, "") + '.pdf'; link.click(); }; reader.readAsArrayBuffer(file); }
  1. 部署和测试 将生成的 .wasm 文件、JavaScript 文件和 HTML 文件部署到你的 Web 服务器上,打开 index.html 文件,选择一个 PPTX 文件并点击“Convert to PDF”按钮。这个过程会:

从文件输入中读取 PPTX 文件。 将文件写入 WebAssembly 模块的虚拟文件系统。 调用 soffice --headless --convert-to pdf 命令进行转换。 从虚拟文件系统中读取生成的 PDF 文件。 创建一个下载链接,允许用户下载生成的 PDF 文件。4. 注意事项 这个过程可能需要大量的内存和计算资源,可能需要优化和调整。 需要确保 Emscripten 的文件系统(MEMFS)能够正确处理大文件。 需要处理可能的错误和异常情况,并提供用户友好的错误提示。 通过这些步骤,你应该能够在 Web 上调用 soffice 命令并将 PPTX 文件转换为 PDF。如果遇到具体问题,请提供详细的错误信息,以便更好地帮助你解决问题。

减少 WebAssembly 文件的体积是一个常见的需求,尤其是在处理像 LibreOffice 这样的大型项目时。如果你只需要特定的功能(如将文件转换为 PDF),可以采取以下几种方法来减小生成的 WebAssembly 文件的体积:

  1. 精简功能模块 确保只编译你需要的功能模块。你已经在 autogen.input 中指定了 --with-main-module=writer,这会限制编译的模块,但你可以进一步精简。

  2. 移除不必要的组件 在 autogen.input 中,进一步禁用不必要的组件和功能。例如:

--disable-dbus --disable-odk --disable-postgresql-sdbc --disable-firebird-sdbc --disable-coinmp --disable-cve-tests --disable-gtk3 --disable-gstreamer-1-0 --disable-kf5 --disable-scripting-beanshell --disable-scripting-javascript --disable-extensions --disable-epm --disable-online-update --disable-python --disable-pdfimport --disable-lpsolve --disable-sdremote --disable-scripting --disable-avmedia --disable-coinmp --disable-report-builder --disable-odk --disable-pch --disable-skia --disable-scripting

  1. 使用 Emscripten 优化选项 Emscripten 提供了多种优化选项,可以帮助减小生成的 WebAssembly 文件的体积:

使用 -O3 或 -Oz 进行最大化优化。 使用 --closure 1 进行 JavaScript 代码的闭包优化。 使用 --llvm-lto 3 进行链接时间优化。 在编译时,确保使用这些选项:

emconfigure ./configure ... emmake make CXXFLAGS="-O3 --llvm-lto 3" LDFLAGS="-O3 --llvm-lto 3" 4. 移除调试信息 确保移除所有调试信息,这可以显著减小文件体积:

emconfigure ./configure ... emmake make CXXFLAGS="-O3 --llvm-lto 3 -g0" LDFLAGS="-O3 --llvm-lto 3 -g0" 5. 使用 WebAssembly Minifier 使用 WebAssembly Minifier 工具(如 wasm-opt)进一步优化和减小生成的 WebAssembly 文件:

wasm-opt -Oz -o optimized.wasm original.wasm 6. 自定义构建脚本 如果上述方法仍然不能满足需求,可以考虑编写自定义构建脚本,只包含必要的源文件和库,进一步精简生成的 WebAssembly 文件。

  1. 动态加载模块 如果可能,将一些功能模块拆分为单独的 WebAssembly 文件,并在需要时动态加载,以减少初始加载的体积。

示例 autogen.input 以下是一个示例 autogen.input 文件,结合了上述建议:

sh
--disable-debug
+--enable-sal-log
+--disable-crashdump
+--host=wasm32-local-emscripten
+--disable-gui
+--with-main-module=writer
+--with-package-format=emscripten
+--disable-dbus
+--disable-odk
+--disable-postgresql-sdbc
+--disable-firebird-sdbc
+--disable-coinmp
+--disable-cve-tests
+--disable-gtk3
+--disable-gstreamer-1-0
+--disable-kf5
+--disable-scripting-beanshell
+--disable-scripting-javascript
+--disable-extensions
+--disable-epm
+--disable-online-update
+--disable-python
+--disable-pdfimport
+--disable-lpsolve
+--disable-sdremote
+--disable-scripting
+--disable-avmedia
+--disable-coinmp
+--disable-report-builder
+--disable-odk
+--disable-pch
+--disable-skia
+--disable-scripting

通过这些步骤,你应该能够显著减小生成的 WebAssembly 文件的体积,同时保留将文件转换为 PDF 的功能。如果遇到具体问题,请提供详细的错误信息,以便更好地帮助你解决问题。

wasm-opt 是 Binaryen 项目的一部分,它是一个用于优化和处理 WebAssembly 二进制文件的工具。你可以在 Ubuntu 上通过以下步骤安装和使用 wasm-opt:

  1. 安装依赖项 首先,确保你的系统上已经安装了必要的依赖项:

sudo apt update sudo apt install cmake build-essential git 2. 下载和编译 Binaryen 接下来,从源码编译 Binaryen:

克隆 Binaryen 仓库

git clone https://github.com/WebAssembly/binaryen.git cd binaryen

创建并进入构建目录

mkdir build cd build

使用 CMake 配置构建

cmake ..

编译 Binaryen

make

安装 Binaryen

sudo make install 3. 使用 wasm-opt 安装完成后,你可以使用 wasm-opt 命令来优化 WebAssembly 文件。例如:

假设你有一个名为 original.wasm 的 WebAssembly 文件

wasm-opt -Oz -o optimized.wasm original.wasm 在这个命令中:

-Oz 表示进行最大化的尺寸优化。 -o optimized.wasm 指定输出文件名为 optimized.wasm。 original.wasm 是输入的 WebAssembly 文件。4. 验证安装 你可以通过运行以下命令来验证 wasm-opt 是否正确安装:

wasm-opt --version 这将输出 wasm-opt 的版本信息,确认它已成功安装并可以使用。

示例 假设你有一个名为 example.wasm 的 WebAssembly 文件,你可以通过以下命令优化它:

wasm-opt -Oz -o example_optimized.wasm example.wasm 这将生成一个优化后的 WebAssembly 文件 example_optimized.wasm,其体积通常会显著减小。

通过这些步骤,你应该能够在 Ubuntu 上成功安装和使用 wasm-opt 来优化你的 WebAssembly 文件。如果在安装或使用过程中遇到任何问题,请提供详细的错误信息,以便进一步帮助你解决问题。

--disable-debug --enable-sal-log --disable-crashdump --host=wasm32-local-emscripten --disable-gui --with-main-module=writer --with-package-format=emscripten --disable-dbus --disable-odk --disable-postgresql-sdbc --disable-firebird-sdbc --disable-coinmp --disable-cve-tests --disable-gtk3 --disable-gstreamer-1-0 --disable-kf5 --disable-scripting-beanshell --disable-scripting-javascript --disable-extensions --disable-epm --disable-online-update --disable-python --disable-pdfimport --disable-lpsolve --disable-sdremote --disable-scripting --disable-avmedia --disable-coinmp --disable-report-builder --disable-odk --disable-pch --disable-skia --disable-scripting

步骤 1:下载最新的 OpenSSL 源代码 首先,确保你在一个干净的目录中,然后下载最新版本的 OpenSSL 源代码。你可以访问 OpenSSL 官方网站 查看最新版本。假设最新版本是 openssl-3.0.9:

wget https://www.openssl.org/source/openssl-3.0.9.tar.gz tar -xzvf openssl-3.0.9.tar.gz cd openssl-3.0.9 步骤 2:编译和安装 OpenSSL 接下来,编译并安装 OpenSSL:

./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl shared zlib make make test make install 步骤 3:确认 OpenSSL 安装路径 确保 OpenSSL 的头文件和库文件已正确安装:

ls /usr/local/ssl/include ls /usr/local/ssl/lib 步骤 4:设置环境变量 设置正确的环境变量,以便编译时能找到 OpenSSL:

export PKG_CONFIG_PATH="/usr/local/ssl/lib/pkgconfig" export CFLAGS="-I/usr/local/ssl/include" export LDFLAGS="-L/usr/local/ssl/lib -lssl -lcrypto" 步骤 5:清理之前的配置 在重新运行 configure 脚本之前,清理之前的配置:

make clean 步骤 6:重新运行 configure 脚本 重新运行 configure 脚本,以确保它能找到新的 OpenSSL 版本:

emconfigure ./configure --disable-debug --enable-sal-log --disable-crashdump --host=wasm32-local-emscripten --disable-gui --with-main-module=writer --with-package-format=emscripten --disable-dbus --disable-odk --disable-postgresql-sdbc --disable-firebird-sdbc --disable-coinmp --disable-cve-tests --disable-gtk3 --disable-gstreamer-1-0 --disable-kf5 --disable-scripting-beanshell --disable-scripting-javascript --disable-extensions --disable-epm --disable-online-update --disable-python --disable-pdfimport --disable-lpsolve --disable-sdremote --disable-scripting --disable-avmedia --disable-coinmp --disable-report-builder --disable-odk --disable-pch --disable-skia --disable-scripting --srcdir=/home/core --enable-option-checking=fatal --disable-pthreads 步骤 7:检查 config.log 如果配置仍然失败,请检查 config.log 文件以获取更多详细信息:

cat config.log | grep openssl 通过确保 OpenSSL 已正确安装并设置正确的环境变量,我们应该能够解决配置过程中遇到的问题。如果问题仍然存在,请提供 config.log 文件中与 OpenSSL 相关的更多详细信息,以便进一步诊断和解决问题。

emconfigure ./configure --disable-debug --enable-sal-log --disable-crashdump --host=wasm32-local-emscripten --disable-gui --with-main-module=writer --with-package-format=emscripten --disable-dbus --disable-odk --disable-postgresql-sdbc --disable-firebird-sdbc --disable-coinmp --disable-cve-tests --disable-gtk3 --disable-gstreamer-1-0 --disable-kf5 --disable-scripting-beanshell --disable-scripting-javascript --disable-extensions --disable-epm --disable-online-update --disable-python --disable-pdfimport --disable-lpsolve --disable-sdremote --disable-scripting --disable-avmedia --disable-coinmp --disable-report-builder --disable-odk --disable-pch --disable-skia --disable-scripting --srcdir=/home/core --enable-option-checking=fatal

emmake make CXXFLAGS="-I/usr/local/ssl/include -O3 -g0 -msimd128" LDFLAGS="-L/usr/local/ssl/lib -lssl -lcrypto -O3 -g0"

emconfigure ./configure --disable-cups --disable-dbus --without-system-fontconfig --with-system-zlib --disable-dynamic-loading --disable-gui CXXFLAGS=-std=c++20 --host=wasm32-unknown-emscripten

root@8cb3480a4441:/home/core/instsetoo_native# vim CustomTarget_emscripten-install.mk

使用 file_packager.py 工具将文件预加载到虚拟文件系统中。确保 Emscripten 的环境变量已经正确设置,然后运行以下命令:

python3 /home/emsdk/upstream/emscripten/tools/file_packager.py preload.data --preload /home/core/instdir/share@/instdir/share --js-output=preload.js

`,85)]))}const g=i(n,[["render",t]]);export{c as __pageData,g as default}; diff --git a/assets/cn_src_note_ubuntu.md.C-U8psaC.js b/assets/cn_src_note_ubuntu.md.C-U8psaC.js new file mode 100644 index 0000000000..940e7b737b --- /dev/null +++ b/assets/cn_src_note_ubuntu.md.C-U8psaC.js @@ -0,0 +1,3 @@ +import{_ as i,o as a,c as t,a3 as n}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"ubuntu","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/note/ubuntu.md","filePath":"cn/src/note/ubuntu.md","lastUpdated":1726550590000}'),h={name:"cn/src/note/ubuntu.md"};function l(k,s,e,p,F,d){return a(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

ubuntu

sh
apt update
+
+apt install openjdk-11-jdk  wget curl junit4 ant libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1.0-dev libgtk-3-dev libglib2.0-dev libatk1.0-dev libcairo2-dev zip flex uuid-runtime bison libxrandr-dev libxrender-dev libxext-dev libnss3-dev libnspr4-dev libkrb5-dev python3 python3-pip libxml2-utils xsltproc libxslt1-dev gperf libfontconfig1-dev libcups2-dev gcc make autoconf pkg-config automake
`,2)]))}const u=i(h,[["render",l]]);export{g as __pageData,u as default}; diff --git a/assets/cn_src_note_ubuntu.md.C-U8psaC.lean.js b/assets/cn_src_note_ubuntu.md.C-U8psaC.lean.js new file mode 100644 index 0000000000..940e7b737b --- /dev/null +++ b/assets/cn_src_note_ubuntu.md.C-U8psaC.lean.js @@ -0,0 +1,3 @@ +import{_ as i,o as a,c as t,a3 as n}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"ubuntu","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/note/ubuntu.md","filePath":"cn/src/note/ubuntu.md","lastUpdated":1726550590000}'),h={name:"cn/src/note/ubuntu.md"};function l(k,s,e,p,F,d){return a(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

ubuntu

sh
apt update
+
+apt install openjdk-11-jdk  wget curl junit4 ant libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1.0-dev libgtk-3-dev libglib2.0-dev libatk1.0-dev libcairo2-dev zip flex uuid-runtime bison libxrandr-dev libxrender-dev libxext-dev libnss3-dev libnspr4-dev libkrb5-dev python3 python3-pip libxml2-utils xsltproc libxslt1-dev gperf libfontconfig1-dev libcups2-dev gcc make autoconf pkg-config automake
`,2)]))}const u=i(h,[["render",l]]);export{g as __pageData,u as default}; diff --git a/assets/cn_src_ranui_button_index.md.BKYzspkY.js b/assets/cn_src_ranui_button_index.md.BKYzspkY.js new file mode 100644 index 0000000000..00a3dc6d91 --- /dev/null +++ b/assets/cn_src_ranui_button_index.md.BKYzspkY.js @@ -0,0 +1,9 @@ +import{_ as a,o as n,c as l,a3 as s,j as t}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"Button 按钮","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/button/index.md","filePath":"cn/src/ranui/button/index.md","lastUpdated":1726550590000}'),h={name:"cn/src/ranui/button/index.md"};function p(e,i,k,r,d,E){return n(),l("div",{"data-pagefind-body":!0},i[0]||(i[0]=[s(`

Button 按钮

按钮用于开始一个即时操作。

代码演示

Button
xml
 <r-button >Button</r-button>

属性

类型type

按钮有四种类型

主要按钮
警告按钮
文本按钮
默认按钮
xml
 <r-button type="primary">主要按钮</r-button>
+ <r-button type="warning">警告按钮</r-button>
+ <r-button type="text">文本按钮</r-button>
+ <r-button >默认按钮</r-button>

不可用状态disabled

添加 disabled 属性即可让按钮处于不可用状态,同时按钮样式也会改变。

主要按钮
警告按钮
文本按钮
默认按钮
xml
 <r-button type="primary" disabled>主要按钮</r-button>
+ <r-button type="warning" disabled>警告按钮</r-button>
+ <r-button type="text" disabled>文本按钮</r-button>
+ <r-button disabled>默认按钮</r-button>

图标icon

当需要在 Button 内嵌入 Icon 时,可以设置 icon 属性,或者直接在 Button 内使用 Icon 组件。

如果想控制 Icon 具体的位置,只能直接使用 Icon 组件,而非 icon 属性。

默认按钮
主要按钮
xml
<r-button type="default" icon="user">默认按钮</r-button>
+<r-button type="primary" icon="home">主要按钮</r-button>

特效 effect

如果需要纯净的 Button,可以加上 effect = false,屏蔽点击时候的水波纹特效

`,28),t("r-button",{type:"default",effect:"fase",icon:"user"},"默认按钮",-1),t("r-button",{type:"primary",effect:"fase",icon:"home"},"主要按钮",-1),s(`
xml
<r-button type="default" icon="user">默认按钮</r-button>
+<r-button type="primary" icon="home">主要按钮</r-button>
`,1)]))}const y=a(h,[["render",p]]);export{g as __pageData,y as default}; diff --git a/assets/cn_src_ranui_button_index.md.BKYzspkY.lean.js b/assets/cn_src_ranui_button_index.md.BKYzspkY.lean.js new file mode 100644 index 0000000000..00a3dc6d91 --- /dev/null +++ b/assets/cn_src_ranui_button_index.md.BKYzspkY.lean.js @@ -0,0 +1,9 @@ +import{_ as a,o as n,c as l,a3 as s,j as t}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"Button 按钮","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/button/index.md","filePath":"cn/src/ranui/button/index.md","lastUpdated":1726550590000}'),h={name:"cn/src/ranui/button/index.md"};function p(e,i,k,r,d,E){return n(),l("div",{"data-pagefind-body":!0},i[0]||(i[0]=[s(`

Button 按钮

按钮用于开始一个即时操作。

代码演示

Button
xml
 <r-button >Button</r-button>

属性

类型type

按钮有四种类型

主要按钮
警告按钮
文本按钮
默认按钮
xml
 <r-button type="primary">主要按钮</r-button>
+ <r-button type="warning">警告按钮</r-button>
+ <r-button type="text">文本按钮</r-button>
+ <r-button >默认按钮</r-button>

不可用状态disabled

添加 disabled 属性即可让按钮处于不可用状态,同时按钮样式也会改变。

主要按钮
警告按钮
文本按钮
默认按钮
xml
 <r-button type="primary" disabled>主要按钮</r-button>
+ <r-button type="warning" disabled>警告按钮</r-button>
+ <r-button type="text" disabled>文本按钮</r-button>
+ <r-button disabled>默认按钮</r-button>

图标icon

当需要在 Button 内嵌入 Icon 时,可以设置 icon 属性,或者直接在 Button 内使用 Icon 组件。

如果想控制 Icon 具体的位置,只能直接使用 Icon 组件,而非 icon 属性。

默认按钮
主要按钮
xml
<r-button type="default" icon="user">默认按钮</r-button>
+<r-button type="primary" icon="home">主要按钮</r-button>

特效 effect

如果需要纯净的 Button,可以加上 effect = false,屏蔽点击时候的水波纹特效

`,28),t("r-button",{type:"default",effect:"fase",icon:"user"},"默认按钮",-1),t("r-button",{type:"primary",effect:"fase",icon:"home"},"主要按钮",-1),s(`
xml
<r-button type="default" icon="user">默认按钮</r-button>
+<r-button type="primary" icon="home">主要按钮</r-button>
`,1)]))}const y=a(h,[["render",p]]);export{g as __pageData,y as default}; diff --git a/assets/cn_src_ranui_checkbox_index.md.tqLDdmuX.js b/assets/cn_src_ranui_checkbox_index.md.tqLDdmuX.js new file mode 100644 index 0000000000..ce12204ed8 --- /dev/null +++ b/assets/cn_src_ranui_checkbox_index.md.tqLDdmuX.js @@ -0,0 +1,2 @@ +import{_ as e,o as h,c as t,a3 as i,j as a}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"CheckBox 多选框","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/checkbox/index.md","filePath":"cn/src/ranui/checkbox/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/ranui/checkbox/index.md"};function n(k,s,c,p,d,r){return h(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[i('

CheckBox 多选框

代码演示

xml
 <r-checkbox ></r-checkbox>

属性

checked

xml
 <r-checkbox checked="true"></r-checkbox>\n <r-checkbox checked="false"></r-checkbox>

disabled

xml
 <r-checkbox checked="true" disabled></r-checkbox>\n <r-checkbox checked="false" disabled></r-checkbox>

事件event

改变的时候触发。

onchange

',16),a("r-checkbox",{onchange:"console.log(this.checked)"},null,-1),a("r-checkbox",{onchange:"console.log(this.checked)"},null,-1),i(`
xml
 <r-checkbox onchange="console.log(this.checked)"></r-checkbox>
+ <r-checkbox onchange="console.log(this.checked)"></r-checkbox>
`,1)]))}const g=e(l,[["render",n]]);export{E as __pageData,g as default}; diff --git a/assets/cn_src_ranui_checkbox_index.md.tqLDdmuX.lean.js b/assets/cn_src_ranui_checkbox_index.md.tqLDdmuX.lean.js new file mode 100644 index 0000000000..ce12204ed8 --- /dev/null +++ b/assets/cn_src_ranui_checkbox_index.md.tqLDdmuX.lean.js @@ -0,0 +1,2 @@ +import{_ as e,o as h,c as t,a3 as i,j as a}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"CheckBox 多选框","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/checkbox/index.md","filePath":"cn/src/ranui/checkbox/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/ranui/checkbox/index.md"};function n(k,s,c,p,d,r){return h(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[i('

CheckBox 多选框

代码演示

xml
 <r-checkbox ></r-checkbox>

属性

checked

xml
 <r-checkbox checked="true"></r-checkbox>\n <r-checkbox checked="false"></r-checkbox>

disabled

xml
 <r-checkbox checked="true" disabled></r-checkbox>\n <r-checkbox checked="false" disabled></r-checkbox>

事件event

改变的时候触发。

onchange

',16),a("r-checkbox",{onchange:"console.log(this.checked)"},null,-1),a("r-checkbox",{onchange:"console.log(this.checked)"},null,-1),i(`
xml
 <r-checkbox onchange="console.log(this.checked)"></r-checkbox>
+ <r-checkbox onchange="console.log(this.checked)"></r-checkbox>
`,1)]))}const g=e(l,[["render",n]]);export{E as __pageData,g as default}; diff --git a/assets/cn_src_ranui_icon_index.md.IS0pJHCF.js b/assets/cn_src_ranui_icon_index.md.IS0pJHCF.js new file mode 100644 index 0000000000..0d2f6c9c64 --- /dev/null +++ b/assets/cn_src_ranui_icon_index.md.IS0pJHCF.js @@ -0,0 +1,12 @@ +import{_ as p,o as E,c as r,a3 as e,j as n}from"./chunks/framework.C-ai2y4t.js";const o=()=>{setTimeout(()=>{const l=["add-user","book","check-circle","close-circle","eye-close","eye","info-circle","loading","lock","message","power-off","setting","team","unlock","user"];if(typeof document<"u"){const a=document.getElementById("icon-list"),s=document.createElement("div");s.style.setProperty("display","grid"),s.style.setProperty("grid-template-columns","repeat(3, 200px)"),s.style.setProperty("grid-template-rows","repeat(3, 200px);"),l.forEach(h=>{const i=document.createElement("div");i.style.setProperty("display","flex"),i.style.setProperty("align-items","center"),i.style.setProperty("margin","15px"),i.style.setProperty("justify-content","center"),i.style.setProperty("flex-flow","column nowrap");const t=document.createElement("r-icon");t.setAttribute("name",h),t.setAttribute("size","50"),i.appendChild(t);const k=document.createElement("span");k.innerHTML=h,i.appendChild(k),s==null||s.appendChild(i)}),a==null||a.appendChild(s)}},0)};o();const y=JSON.parse('{"title":"Icon 图标","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/icon/index.md","filePath":"cn/src/ranui/icon/index.md","lastUpdated":1726550590000}'),d={name:"cn/src/ranui/icon/index.md"};function g(l,a,s,h,i,t){return E(),r("div",{"data-pagefind-body":!0},a[0]||(a[0]=[e(`

Icon 图标

语义化的矢量图形

代码演示

xml
 <r-icon name="lock"  ></r-icon>
+ <r-icon name="eye"  ></r-icon>
+ <r-icon name="user"  ></r-icon>

属性

名称name

根据名称选择不同的图标

html
<r-icon name="lock"></r-icon>
+<r-icon name="eye"></r-icon>
+<r-icon name="user"></r-icon>

尺寸size

html
<r-icon name="lock" size="30"></r-icon>
+<r-icon name="lock" size="50"></r-icon>
+<r-icon name="lock" size="70"></r-icon>

颜色color

html
<r-icon name="lock" size="50" color="red"></r-icon>
+<r-icon name="lock" size="50" color="#1E90FF"></r-icon>
+<r-icon name="lock" size="50" color="#F44336"></r-icon>
+<r-icon name="lock" size="50" color="#3F51B5"></r-icon>

旋转spin

设置 spin 开启旋转,传入数字控制旋转的速度,数字越小旋转越快

`,18),n("div",{style:{display:"flex"}},[n("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:"0.7"}),n("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:""}),n("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:"5"})],-1),e(`
html
<r-icon name="loading" size="50" color="#1E90FF" spin="0.7"></r-icon>
+<r-icon name="loading" size="50" color="#1E90FF" spin></r-icon>
+<r-icon name="loading" size="50" color="#1E90FF" spin="5"></r-icon>

图标列表

`,3)]))}const F=p(d,[["render",g]]);export{y as __pageData,F as default}; diff --git a/assets/cn_src_ranui_icon_index.md.IS0pJHCF.lean.js b/assets/cn_src_ranui_icon_index.md.IS0pJHCF.lean.js new file mode 100644 index 0000000000..0d2f6c9c64 --- /dev/null +++ b/assets/cn_src_ranui_icon_index.md.IS0pJHCF.lean.js @@ -0,0 +1,12 @@ +import{_ as p,o as E,c as r,a3 as e,j as n}from"./chunks/framework.C-ai2y4t.js";const o=()=>{setTimeout(()=>{const l=["add-user","book","check-circle","close-circle","eye-close","eye","info-circle","loading","lock","message","power-off","setting","team","unlock","user"];if(typeof document<"u"){const a=document.getElementById("icon-list"),s=document.createElement("div");s.style.setProperty("display","grid"),s.style.setProperty("grid-template-columns","repeat(3, 200px)"),s.style.setProperty("grid-template-rows","repeat(3, 200px);"),l.forEach(h=>{const i=document.createElement("div");i.style.setProperty("display","flex"),i.style.setProperty("align-items","center"),i.style.setProperty("margin","15px"),i.style.setProperty("justify-content","center"),i.style.setProperty("flex-flow","column nowrap");const t=document.createElement("r-icon");t.setAttribute("name",h),t.setAttribute("size","50"),i.appendChild(t);const k=document.createElement("span");k.innerHTML=h,i.appendChild(k),s==null||s.appendChild(i)}),a==null||a.appendChild(s)}},0)};o();const y=JSON.parse('{"title":"Icon 图标","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/icon/index.md","filePath":"cn/src/ranui/icon/index.md","lastUpdated":1726550590000}'),d={name:"cn/src/ranui/icon/index.md"};function g(l,a,s,h,i,t){return E(),r("div",{"data-pagefind-body":!0},a[0]||(a[0]=[e(`

Icon 图标

语义化的矢量图形

代码演示

xml
 <r-icon name="lock"  ></r-icon>
+ <r-icon name="eye"  ></r-icon>
+ <r-icon name="user"  ></r-icon>

属性

名称name

根据名称选择不同的图标

html
<r-icon name="lock"></r-icon>
+<r-icon name="eye"></r-icon>
+<r-icon name="user"></r-icon>

尺寸size

html
<r-icon name="lock" size="30"></r-icon>
+<r-icon name="lock" size="50"></r-icon>
+<r-icon name="lock" size="70"></r-icon>

颜色color

html
<r-icon name="lock" size="50" color="red"></r-icon>
+<r-icon name="lock" size="50" color="#1E90FF"></r-icon>
+<r-icon name="lock" size="50" color="#F44336"></r-icon>
+<r-icon name="lock" size="50" color="#3F51B5"></r-icon>

旋转spin

设置 spin 开启旋转,传入数字控制旋转的速度,数字越小旋转越快

`,18),n("div",{style:{display:"flex"}},[n("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:"0.7"}),n("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:""}),n("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:"5"})],-1),e(`
html
<r-icon name="loading" size="50" color="#1E90FF" spin="0.7"></r-icon>
+<r-icon name="loading" size="50" color="#1E90FF" spin></r-icon>
+<r-icon name="loading" size="50" color="#1E90FF" spin="5"></r-icon>

图标列表

`,3)]))}const F=p(d,[["render",g]]);export{y as __pageData,F as default}; diff --git a/assets/cn_src_ranui_image_index.md.Dw0AwGab.js b/assets/cn_src_ranui_image_index.md.Dw0AwGab.js new file mode 100644 index 0000000000..de6d24b22f --- /dev/null +++ b/assets/cn_src_ranui_image_index.md.Dw0AwGab.js @@ -0,0 +1 @@ +import{_ as a,o as E,c as i,a3 as Q,j as e}from"./chunks/framework.C-ai2y4t.js";const B=JSON.parse('{"title":"Image 图片","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/image/index.md","filePath":"cn/src/ranui/image/index.md","lastUpdated":1726550590000}'),g={name:"cn/src/ranui/image/index.md"};function s(n,A,t,h,o,l){return E(),i("div",{"data-pagefind-body":!0},A[0]||(A[0]=[Q('

Image 图片

代码演示

xml
 <r-img src="" fallback=""></r-img>

属性

图片加载地址src

图片的地址

图片加载失败fallback

src配置的图片加载失败,兜底的图片地址,下面是默认加载失败图片

',8),e("r-img",{fallback:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg=="},null,-1)]))}const r=a(g,[["render",s]]);export{B as __pageData,r as default}; diff --git a/assets/cn_src_ranui_image_index.md.Dw0AwGab.lean.js b/assets/cn_src_ranui_image_index.md.Dw0AwGab.lean.js new file mode 100644 index 0000000000..de6d24b22f --- /dev/null +++ b/assets/cn_src_ranui_image_index.md.Dw0AwGab.lean.js @@ -0,0 +1 @@ +import{_ as a,o as E,c as i,a3 as Q,j as e}from"./chunks/framework.C-ai2y4t.js";const B=JSON.parse('{"title":"Image 图片","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/image/index.md","filePath":"cn/src/ranui/image/index.md","lastUpdated":1726550590000}'),g={name:"cn/src/ranui/image/index.md"};function s(n,A,t,h,o,l){return E(),i("div",{"data-pagefind-body":!0},A[0]||(A[0]=[Q('

Image 图片

代码演示

xml
 <r-img src="" fallback=""></r-img>

属性

图片加载地址src

图片的地址

图片加载失败fallback

src配置的图片加载失败,兜底的图片地址,下面是默认加载失败图片

',8),e("r-img",{fallback:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg=="},null,-1)]))}const r=a(g,[["render",s]]);export{B as __pageData,r as default}; diff --git a/assets/cn_src_ranui_index.md.tB1QXtFw.js b/assets/cn_src_ranui_index.md.tB1QXtFw.js new file mode 100644 index 0000000000..38f4a79824 --- /dev/null +++ b/assets/cn_src_ranui_index.md.tB1QXtFw.js @@ -0,0 +1,86 @@ +import{_ as t}from"./chunks/customElements.qitHOM3M.js";import{_ as n,o as l,c as h,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"ranui","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/index.md","filePath":"cn/src/ranui/index.md","lastUpdated":1726550590000}'),e={name:"cn/src/ranui/index.md"};function p(k,a,r,E,d,g){return l(),h("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

ranui

基于 Web Components开发方案

特点

  1. 跨框架兼容: 与 React, Vue, Preact, SolidJS, Svelte 等兼容。可以和遵循 W3C 标准的任何 JavaScript 项目集成。
  2. 原生体验: 易于入门,像使用本地 div 标签,简化项目大小和减少学习成本。
  3. 模块化设计: 可选导入和全量导入,以增强可维护性和可伸缩性。
  4. 交互式丰富文档: 提供详细的交互式文档,并附有有效的示例子。
  5. 支持类型校验: 基于 TypeScript 构建,具有类型支持,确保代码的健壮性和可维护性。
  6. 持久和稳定: 与框架 (React/vue) 无关,避免破坏性的更新,并确保持续的项目运行。

安装

使用 npm:

console
npm install ranui --save

引入方式

支持按需导入,以显著减少包体积大小

js
import 'ranui/button';

如果遇到样式问题,可以选择手动导入样式文件

js
import 'ranui/style';

如果遇到类型问题,可以选择手动导入类型文件

ts
import 'ranui/types';

或者

ts
import 'ranui/dist/typings';

也支持全量导入

ts
import 'ranui';
  • ES module
js
import 'ranui';

或者

js
import 'ranui/button';
  • UMD, IIFE, CJS
html
<script src="./ranui/dist/umd/index.umd.cjs"></script>

使用方式

它是基于Web Components的组件,你可以不用关注框架就可以使用它。

在大多数情况下,您可以像使用本地 div 标签一样使用它

下面是一些例子:

  • html
  • js
  • jsx
  • vue
  • tsx

html

html
<script src="./ranui/dist/umd/index.umd.cjs"></script>
+
+<body>
+  <r-button>Button</r-button>
+</body>

js

js
import 'ranui';
+
+const Button = document.createElement('r-button');
+Button.appendChild('this is button text');
+document.body.appendChild(Button);

jsx

jsx
import 'ranui';
+
+const App = () => {
+  return (
+    <>
+      <r-button>Button</r-button>
+    </>
+  );
+};

vue

vue
<template>
+  <r-button></r-button>
+</template>
+<script>
+import 'ranui';
+</script>

tsx

tsx
// react 18
+import type { SyntheticEvent } from 'react';
+import React, { useRef } from 'react';
+import 'ranui';
+
+const FilePreview = () => {
+  const ref = useRef<HTMLDivElement | null>(null);
+  const uploadFile = (e: SyntheticEvent<HTMLDivElement>) => {
+    if (ref.current) {
+      const uploadFile = document.createElement('input');
+      uploadFile.setAttribute('type', 'file');
+      uploadFile.click();
+      uploadFile.onchange = (e) => {
+        const { files = [] } = uploadFile;
+        if (files && files?.length > 0 && ref.current) {
+          ref.current.setAttribute('src', '');
+          const file = files[0];
+          const url = URL.createObjectURL(file);
+          ref.current.setAttribute('src', url);
+        }
+      };
+    }
+  };
+  return (
+    <div>
+      <r-preview ref={ref}></r-preview>
+      <r-button type="primary" onClick={uploadFile}>
+        choose file to preview
+      </r-button>
+    </div>
+  );
+};

Overview 组件总览

  • Button
主要按钮
警告按钮
文本按钮
默认按钮
  • Icon
`,46),s("div",{style:{display:"flex"}},[s("r-icon",{name:"lock",size:"50"}),s("r-icon",{name:"user",size:"50"}),s("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:""})],-1),i('
  • Skeleton
  • Input
  • message
',9),s("r-button",{onclick:"message.info('这是一条提示')"},"信息提示",-1),s("r-button",{onclick:"message.warning('这是一条提示')"},"警告提示",-1),s("r-button",{onclick:"message.error('这是一条提示')"},"错误提示",-1),s("r-button",{onclick:"message.success('这是一条提示')"},"成功提示",-1),s("r-button",{onclick:"message.toast('这是一条提示')"},"toast 提示",-1),s("ul",null,[s("li",null,[s("code",null,"Tab")])],-1),s("div",{style:{display:"block","margin-right":"8px","margin-bottom":"12px"}},[s("r-tabs",null,[s("r-tab",{label:"home",icon:"home"},"tab1"),s("r-tab",{label:"message",icon:"message"},"tab2"),s("r-tab",{label:"user",icon:"user"},"tab3")])],-1),s("ul",null,[s("li",null,[s("code",null,"Radar")])],-1),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},abilitys:'[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),s("ul",null,[s("li",null,[s("code",null,"Progress")])],-1),s("r-progress",{type:"drag"},null,-1),s("ul",null,[s("li",null,[s("code",null,"Player")])],-1),s("r-player",{style:{display:"block",width:"100%","max-width":"600px",height:"300px"},src:"/ran/hls/example.m3u8"},null,-1),s("ul",null,[s("li",null,[s("code",null,"Select")])],-1),s("r-select",{style:{width:"120px",height:"40px"},defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),s("ul",null,[s("li",null,[s("code",null,"Loading")])],-1),s("r-loading",{name:"circle-fold"},null,-1),s("ul",null,[s("li",null,[s("code",null,"math")])],-1),s("r-math",{latex:"x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}"},null,-1),i(`

Event 事件

  • react

@ranui/react 是由react高阶函数封装ranui而成,Event 事件遵循react事件规范。跟W3C标准略有不同。

  • 现代web标准

W3C标准中,你可以使用on属性在HTML元素上定义事件处理程序。但这是旧的事件处理程序的方法。

现代的web开发推荐使用addEventListener方法。

html
<r-button id="button">按钮</r-button>
+
+<script>
+  const button = document.getElementById('button');
+  button.addEventListener('click', function (event) {
+    alert('新的点击事件!');
+  });
+</script>

然而,如果你确实需要使用on属性,下面是一个示例:

html
<r-input onchange="change(this.value)"></r-input>
+
+<script>
+  function change(e) {
+    console.log('e--->', e);
+  }
+</script>

请注意,使用on属性来定义事件处理程序有一些限制和缺点。

例如,你不能使用事件捕获或事件委托,而且每个事件类型都需要一个单独的属性。

这也是为什么现代的web开发推荐使用addEventListener方法的原因。

还可以使用property的方式:

html
<r-input id="input"></r-input>
+
+<script>
+  const input = document.getElementById("input")
+  input.onchange = (e) {
+    console.log('e--->', e)
+  }
+</script>

style 自定义样式

::part伪类

html
<r-input id="input"></r-input>
+
+<style>
+  /* #input 指的是当前的自定义元素
+  ::part(input) 中的 input 指的是,当前自定义元素内部的 Shadow DOM 元素的类 */
+  #input::part(input) {
+    width: 100px;
+  }
+</style>

具体的伪类名称可以查看具体的具体介绍

通过sheet属性传入

会在所有的组件上加一个sheet属性,传入CSSStyleSheet字符串。会直接插入到Shadow DOM

css3变量var

通过给组件设置css3变量,从而自定义组件内部的指定样式,比如:

`,22),s("r-progress",{percent:"0.7",type:"drag"},null,-1),s("br",null,null,-1),s("r-progress",{percent:"0.7",type:"drag",style:{"--ran-progress-wrap-background":"linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)"}},null,-1),i(`
html
<r-progress percent="0.7" type="drag"></r-progress>
+<r-progress
+  percent="0.70"
+  type="drag"
+  style="--ran-progress-wrap-background:linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);"
+></r-progress>

具体css3变量名称可以参考每个组件的介绍和说明

Compatibility 兼容性

  • 不支持 IE,其他均有较好支持

Contributors 贡献者

Other 相关资源

  1. 优秀的组件设计
  2. 在线生成 CSS 渐变色
  3. 优秀设计作品,有 psd 和 sketch
  4. 3D UI 设计,类似于 3D 版的 figma
  5. 设计规范
  6. 优秀设计作品
  7. element UI 中文网
  8. Ant design 中文网
  9. 在线绘制 CSS 动画
  10. tailwindcss 组件库
  11. animate css 非常优秀的 css 动画
  12. can i use 检测兼容性 API 网站
  13. figma

协议和标准

  1. RFCs
  2. ECMA
  3. w3c
',11)]))}const u=n(e,[["render",p]]);export{y as __pageData,u as default}; diff --git a/assets/cn_src_ranui_index.md.tB1QXtFw.lean.js b/assets/cn_src_ranui_index.md.tB1QXtFw.lean.js new file mode 100644 index 0000000000..38f4a79824 --- /dev/null +++ b/assets/cn_src_ranui_index.md.tB1QXtFw.lean.js @@ -0,0 +1,86 @@ +import{_ as t}from"./chunks/customElements.qitHOM3M.js";import{_ as n,o as l,c as h,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"ranui","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/index.md","filePath":"cn/src/ranui/index.md","lastUpdated":1726550590000}'),e={name:"cn/src/ranui/index.md"};function p(k,a,r,E,d,g){return l(),h("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

ranui

基于 Web Components开发方案

特点

  1. 跨框架兼容: 与 React, Vue, Preact, SolidJS, Svelte 等兼容。可以和遵循 W3C 标准的任何 JavaScript 项目集成。
  2. 原生体验: 易于入门,像使用本地 div 标签,简化项目大小和减少学习成本。
  3. 模块化设计: 可选导入和全量导入,以增强可维护性和可伸缩性。
  4. 交互式丰富文档: 提供详细的交互式文档,并附有有效的示例子。
  5. 支持类型校验: 基于 TypeScript 构建,具有类型支持,确保代码的健壮性和可维护性。
  6. 持久和稳定: 与框架 (React/vue) 无关,避免破坏性的更新,并确保持续的项目运行。

安装

使用 npm:

console
npm install ranui --save

引入方式

支持按需导入,以显著减少包体积大小

js
import 'ranui/button';

如果遇到样式问题,可以选择手动导入样式文件

js
import 'ranui/style';

如果遇到类型问题,可以选择手动导入类型文件

ts
import 'ranui/types';

或者

ts
import 'ranui/dist/typings';

也支持全量导入

ts
import 'ranui';
  • ES module
js
import 'ranui';

或者

js
import 'ranui/button';
  • UMD, IIFE, CJS
html
<script src="./ranui/dist/umd/index.umd.cjs"></script>

使用方式

它是基于Web Components的组件,你可以不用关注框架就可以使用它。

在大多数情况下,您可以像使用本地 div 标签一样使用它

下面是一些例子:

  • html
  • js
  • jsx
  • vue
  • tsx

html

html
<script src="./ranui/dist/umd/index.umd.cjs"></script>
+
+<body>
+  <r-button>Button</r-button>
+</body>

js

js
import 'ranui';
+
+const Button = document.createElement('r-button');
+Button.appendChild('this is button text');
+document.body.appendChild(Button);

jsx

jsx
import 'ranui';
+
+const App = () => {
+  return (
+    <>
+      <r-button>Button</r-button>
+    </>
+  );
+};

vue

vue
<template>
+  <r-button></r-button>
+</template>
+<script>
+import 'ranui';
+</script>

tsx

tsx
// react 18
+import type { SyntheticEvent } from 'react';
+import React, { useRef } from 'react';
+import 'ranui';
+
+const FilePreview = () => {
+  const ref = useRef<HTMLDivElement | null>(null);
+  const uploadFile = (e: SyntheticEvent<HTMLDivElement>) => {
+    if (ref.current) {
+      const uploadFile = document.createElement('input');
+      uploadFile.setAttribute('type', 'file');
+      uploadFile.click();
+      uploadFile.onchange = (e) => {
+        const { files = [] } = uploadFile;
+        if (files && files?.length > 0 && ref.current) {
+          ref.current.setAttribute('src', '');
+          const file = files[0];
+          const url = URL.createObjectURL(file);
+          ref.current.setAttribute('src', url);
+        }
+      };
+    }
+  };
+  return (
+    <div>
+      <r-preview ref={ref}></r-preview>
+      <r-button type="primary" onClick={uploadFile}>
+        choose file to preview
+      </r-button>
+    </div>
+  );
+};

Overview 组件总览

  • Button
主要按钮
警告按钮
文本按钮
默认按钮
  • Icon
`,46),s("div",{style:{display:"flex"}},[s("r-icon",{name:"lock",size:"50"}),s("r-icon",{name:"user",size:"50"}),s("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:""})],-1),i('
  • Skeleton
  • Input
  • message
',9),s("r-button",{onclick:"message.info('这是一条提示')"},"信息提示",-1),s("r-button",{onclick:"message.warning('这是一条提示')"},"警告提示",-1),s("r-button",{onclick:"message.error('这是一条提示')"},"错误提示",-1),s("r-button",{onclick:"message.success('这是一条提示')"},"成功提示",-1),s("r-button",{onclick:"message.toast('这是一条提示')"},"toast 提示",-1),s("ul",null,[s("li",null,[s("code",null,"Tab")])],-1),s("div",{style:{display:"block","margin-right":"8px","margin-bottom":"12px"}},[s("r-tabs",null,[s("r-tab",{label:"home",icon:"home"},"tab1"),s("r-tab",{label:"message",icon:"message"},"tab2"),s("r-tab",{label:"user",icon:"user"},"tab3")])],-1),s("ul",null,[s("li",null,[s("code",null,"Radar")])],-1),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},abilitys:'[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),s("ul",null,[s("li",null,[s("code",null,"Progress")])],-1),s("r-progress",{type:"drag"},null,-1),s("ul",null,[s("li",null,[s("code",null,"Player")])],-1),s("r-player",{style:{display:"block",width:"100%","max-width":"600px",height:"300px"},src:"/ran/hls/example.m3u8"},null,-1),s("ul",null,[s("li",null,[s("code",null,"Select")])],-1),s("r-select",{style:{width:"120px",height:"40px"},defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),s("ul",null,[s("li",null,[s("code",null,"Loading")])],-1),s("r-loading",{name:"circle-fold"},null,-1),s("ul",null,[s("li",null,[s("code",null,"math")])],-1),s("r-math",{latex:"x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}"},null,-1),i(`

Event 事件

  • react

@ranui/react 是由react高阶函数封装ranui而成,Event 事件遵循react事件规范。跟W3C标准略有不同。

  • 现代web标准

W3C标准中,你可以使用on属性在HTML元素上定义事件处理程序。但这是旧的事件处理程序的方法。

现代的web开发推荐使用addEventListener方法。

html
<r-button id="button">按钮</r-button>
+
+<script>
+  const button = document.getElementById('button');
+  button.addEventListener('click', function (event) {
+    alert('新的点击事件!');
+  });
+</script>

然而,如果你确实需要使用on属性,下面是一个示例:

html
<r-input onchange="change(this.value)"></r-input>
+
+<script>
+  function change(e) {
+    console.log('e--->', e);
+  }
+</script>

请注意,使用on属性来定义事件处理程序有一些限制和缺点。

例如,你不能使用事件捕获或事件委托,而且每个事件类型都需要一个单独的属性。

这也是为什么现代的web开发推荐使用addEventListener方法的原因。

还可以使用property的方式:

html
<r-input id="input"></r-input>
+
+<script>
+  const input = document.getElementById("input")
+  input.onchange = (e) {
+    console.log('e--->', e)
+  }
+</script>

style 自定义样式

::part伪类

html
<r-input id="input"></r-input>
+
+<style>
+  /* #input 指的是当前的自定义元素
+  ::part(input) 中的 input 指的是,当前自定义元素内部的 Shadow DOM 元素的类 */
+  #input::part(input) {
+    width: 100px;
+  }
+</style>

具体的伪类名称可以查看具体的具体介绍

通过sheet属性传入

会在所有的组件上加一个sheet属性,传入CSSStyleSheet字符串。会直接插入到Shadow DOM

css3变量var

通过给组件设置css3变量,从而自定义组件内部的指定样式,比如:

`,22),s("r-progress",{percent:"0.7",type:"drag"},null,-1),s("br",null,null,-1),s("r-progress",{percent:"0.7",type:"drag",style:{"--ran-progress-wrap-background":"linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)"}},null,-1),i(`
html
<r-progress percent="0.7" type="drag"></r-progress>
+<r-progress
+  percent="0.70"
+  type="drag"
+  style="--ran-progress-wrap-background:linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);"
+></r-progress>

具体css3变量名称可以参考每个组件的介绍和说明

Compatibility 兼容性

  • 不支持 IE,其他均有较好支持

Contributors 贡献者

Other 相关资源

  1. 优秀的组件设计
  2. 在线生成 CSS 渐变色
  3. 优秀设计作品,有 psd 和 sketch
  4. 3D UI 设计,类似于 3D 版的 figma
  5. 设计规范
  6. 优秀设计作品
  7. element UI 中文网
  8. Ant design 中文网
  9. 在线绘制 CSS 动画
  10. tailwindcss 组件库
  11. animate css 非常优秀的 css 动画
  12. can i use 检测兼容性 API 网站
  13. figma

协议和标准

  1. RFCs
  2. ECMA
  3. w3c
',11)]))}const u=n(e,[["render",p]]);export{y as __pageData,u as default}; diff --git a/assets/cn_src_ranui_input_index.md.Ztjdnx-y.js b/assets/cn_src_ranui_input_index.md.Ztjdnx-y.js new file mode 100644 index 0000000000..f92552ae6b --- /dev/null +++ b/assets/cn_src_ranui_input_index.md.Ztjdnx-y.js @@ -0,0 +1,11 @@ +import{_ as t}from"./chunks/input-input.MnARRJC6.js";import{_ as n,o as h,c as l,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"Input 输入框","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/input/index.md","filePath":"cn/src/ranui/input/index.md","lastUpdated":1726550590000}'),e={name:"cn/src/ranui/input/index.md"};function p(k,a,d,r,E,o){return h(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

Input 输入框

通过鼠标或键盘输入内容,是最基础的表单域的包装。

代码演示

输入框:
xml
<r-input></r-input>

属性

标签label

提供类似于 Metiral Design 的输入体验。

html
<r-input label="user"></r-input>

占位placeholder

与原生placeholder一致。

html
<r-input placeholder="user"></r-input>

禁用disabled

通过disabled可以禁用输入框,禁用后该按钮上的事件失效。

html
<r-input label="user" disabled></r-input>

value

设置或返回输入框的value属性值。

类型type

目前支持passwordnumber这几种类型,设置后会出现额外的ui控件。

密码输入框

支持密码明文和密文切换。

html
<r-input icon="lock" type="password"></r-input>

图标icon

可以设置一个icon来表示标签标识。

html
<r-input icon="user"></r-input>

数字输入框

数字输入框,类似于原生input[type=number],支持minmaxstep属性,支持键盘上下键切换数字。

html
<r-input type="number" min="-10" max="10" step="0.5"></r-input>

name 属性名

跟 form 组件联动的时候有效,form 提交时收集的字段名字

status 状态

  • error

默认色值: #ff4d4f

',40),s("div",null,[s("r-input",{status:"error"})],-1),i('
xml
<r-input status="error"></r-input>
  • warning

默认色值: #ff7875

',3),s("div",null,[s("r-input",{status:"warning"})],-1),i('
xml
<r-input  status="warning"></r-input>

事件event

常见的回调事件。

onchange

文本改变的时候触发。

',5),s("r-input",{onchange:"console.log(this.value)"},null,-1),i(`
html
<r-input onchange="func(this.value)"></r-input>
js
const input = document.createElement('r-input');
+input.setAttribute('label', 'home');
+const func = (e) => {
+  console.log(e);
+};
+input.addEventListener('change', func);

oninput

输入时触发。

`,4),s("r-input",{oninput:"console.log(this.value)"},null,-1),i(`
js
const input = document.createElement('r-input');
+input.setAttribute('label', 'home');
+const func = (e) => {
+  console.log(e);
+};
+input.addEventListener('input', func);

事件的e参数结构 input方法

',2)]))}const y=n(e,[["render",p]]);export{u as __pageData,y as default}; diff --git a/assets/cn_src_ranui_input_index.md.Ztjdnx-y.lean.js b/assets/cn_src_ranui_input_index.md.Ztjdnx-y.lean.js new file mode 100644 index 0000000000..f92552ae6b --- /dev/null +++ b/assets/cn_src_ranui_input_index.md.Ztjdnx-y.lean.js @@ -0,0 +1,11 @@ +import{_ as t}from"./chunks/input-input.MnARRJC6.js";import{_ as n,o as h,c as l,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"Input 输入框","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/input/index.md","filePath":"cn/src/ranui/input/index.md","lastUpdated":1726550590000}'),e={name:"cn/src/ranui/input/index.md"};function p(k,a,d,r,E,o){return h(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

Input 输入框

通过鼠标或键盘输入内容,是最基础的表单域的包装。

代码演示

输入框:
xml
<r-input></r-input>

属性

标签label

提供类似于 Metiral Design 的输入体验。

html
<r-input label="user"></r-input>

占位placeholder

与原生placeholder一致。

html
<r-input placeholder="user"></r-input>

禁用disabled

通过disabled可以禁用输入框,禁用后该按钮上的事件失效。

html
<r-input label="user" disabled></r-input>

value

设置或返回输入框的value属性值。

类型type

目前支持passwordnumber这几种类型,设置后会出现额外的ui控件。

密码输入框

支持密码明文和密文切换。

html
<r-input icon="lock" type="password"></r-input>

图标icon

可以设置一个icon来表示标签标识。

html
<r-input icon="user"></r-input>

数字输入框

数字输入框,类似于原生input[type=number],支持minmaxstep属性,支持键盘上下键切换数字。

html
<r-input type="number" min="-10" max="10" step="0.5"></r-input>

name 属性名

跟 form 组件联动的时候有效,form 提交时收集的字段名字

status 状态

  • error

默认色值: #ff4d4f

',40),s("div",null,[s("r-input",{status:"error"})],-1),i('
xml
<r-input status="error"></r-input>
  • warning

默认色值: #ff7875

',3),s("div",null,[s("r-input",{status:"warning"})],-1),i('
xml
<r-input  status="warning"></r-input>

事件event

常见的回调事件。

onchange

文本改变的时候触发。

',5),s("r-input",{onchange:"console.log(this.value)"},null,-1),i(`
html
<r-input onchange="func(this.value)"></r-input>
js
const input = document.createElement('r-input');
+input.setAttribute('label', 'home');
+const func = (e) => {
+  console.log(e);
+};
+input.addEventListener('change', func);

oninput

输入时触发。

`,4),s("r-input",{oninput:"console.log(this.value)"},null,-1),i(`
js
const input = document.createElement('r-input');
+input.setAttribute('label', 'home');
+const func = (e) => {
+  console.log(e);
+};
+input.addEventListener('input', func);

事件的e参数结构 input方法

',2)]))}const y=n(e,[["render",p]]);export{u as __pageData,y as default}; diff --git a/assets/cn_src_ranui_loading_index.md.C0qf8XCk.js b/assets/cn_src_ranui_loading_index.md.C0qf8XCk.js new file mode 100644 index 0000000000..1f2a81fd9d --- /dev/null +++ b/assets/cn_src_ranui_loading_index.md.C0qf8XCk.js @@ -0,0 +1,4 @@ +import{_ as a}from"./chunks/loading.vue_vue_type_style_index_0_lang.Da-8gR4I.js";import{o as s,c as t,a3 as n,G as l}from"./chunks/framework.C-ai2y4t.js";import"./chunks/index.CBA5mFK_.js";const o=JSON.parse('{"title":"Loading","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/loading/index.md","filePath":"cn/src/ranui/loading/index.md","lastUpdated":1726550590000}'),e={name:"cn/src/ranui/loading/index.md"},g=Object.assign(e,{setup(h){return(d,i)=>(s(),t("div",{"data-pagefind-body":!0},[i[0]||(i[0]=n(`

Loading

一些好看的 loading

Code demo

xml
<r-loading name="circle"></r-loading>

属性

name

这里有很多好看的 loading,可供选择

xml
<r-loading name="double-bounce"></r-loading>
+<r-loading name="rotate"></r-loading>
+<r-loading name="stretch"></r-loading>
+<r-loading name="cube"></r-loading>

Loading list

`,14)),l(a)]))}});export{o as __pageData,g as default}; diff --git a/assets/cn_src_ranui_loading_index.md.C0qf8XCk.lean.js b/assets/cn_src_ranui_loading_index.md.C0qf8XCk.lean.js new file mode 100644 index 0000000000..1f2a81fd9d --- /dev/null +++ b/assets/cn_src_ranui_loading_index.md.C0qf8XCk.lean.js @@ -0,0 +1,4 @@ +import{_ as a}from"./chunks/loading.vue_vue_type_style_index_0_lang.Da-8gR4I.js";import{o as s,c as t,a3 as n,G as l}from"./chunks/framework.C-ai2y4t.js";import"./chunks/index.CBA5mFK_.js";const o=JSON.parse('{"title":"Loading","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/loading/index.md","filePath":"cn/src/ranui/loading/index.md","lastUpdated":1726550590000}'),e={name:"cn/src/ranui/loading/index.md"},g=Object.assign(e,{setup(h){return(d,i)=>(s(),t("div",{"data-pagefind-body":!0},[i[0]||(i[0]=n(`

Loading

一些好看的 loading

Code demo

xml
<r-loading name="circle"></r-loading>

属性

name

这里有很多好看的 loading,可供选择

xml
<r-loading name="double-bounce"></r-loading>
+<r-loading name="rotate"></r-loading>
+<r-loading name="stretch"></r-loading>
+<r-loading name="cube"></r-loading>

Loading list

`,14)),l(a)]))}});export{o as __pageData,g as default}; diff --git a/assets/cn_src_ranui_math_index.md.CaRU3RpB.js b/assets/cn_src_ranui_math_index.md.CaRU3RpB.js new file mode 100644 index 0000000000..90869c8f31 --- /dev/null +++ b/assets/cn_src_ranui_math_index.md.CaRU3RpB.js @@ -0,0 +1 @@ +import{_ as e,o as l,c as n,j as a,a as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"math 数学公式","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/math/index.md","filePath":"cn/src/ranui/math/index.md","lastUpdated":1726550590000}'),h={name:"cn/src/ranui/math/index.md"};function r(d,t,p,k,o,c){return l(),n("div",{"data-pagefind-body":!0},t[0]||(t[0]=[a("h1",{id:"math-数学公式",tabindex:"-1"},[s("math 数学公式 "),a("a",{class:"header-anchor",href:"#math-数学公式","aria-label":'Permalink to "math 数学公式"'},"​")],-1),a("p",null,[s("在 "),a("code",null,"HTML"),s(" 页面中高质量展示 "),a("code",null,"LaTeX"),s(" 数学公式")],-1),a("h2",{id:"代码演示",tabindex:"-1"},[s("代码演示 "),a("a",{class:"header-anchor",href:"#代码演示","aria-label":'Permalink to "代码演示"'},"​")],-1),a("r-math",{latex:"\\frac{x^2}{a^2} + \\frac{y^2}{b^2} = 1 \\quad (a > b > 0)"},null,-1),i('
xml
<r-math latex="\\frac{x^2}{a^2} + \\frac{y^2}{b^2} = 1 \\quad (a > b > 0)"></r-math>

属性

latex string

',3),a("r-math",{latex:"x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}"},null,-1),i('
xml
  <r-math latex="x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}"></r-math>
',1)]))}const m=e(h,[["render",r]]);export{E as __pageData,m as default}; diff --git a/assets/cn_src_ranui_math_index.md.CaRU3RpB.lean.js b/assets/cn_src_ranui_math_index.md.CaRU3RpB.lean.js new file mode 100644 index 0000000000..90869c8f31 --- /dev/null +++ b/assets/cn_src_ranui_math_index.md.CaRU3RpB.lean.js @@ -0,0 +1 @@ +import{_ as e,o as l,c as n,j as a,a as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"math 数学公式","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/math/index.md","filePath":"cn/src/ranui/math/index.md","lastUpdated":1726550590000}'),h={name:"cn/src/ranui/math/index.md"};function r(d,t,p,k,o,c){return l(),n("div",{"data-pagefind-body":!0},t[0]||(t[0]=[a("h1",{id:"math-数学公式",tabindex:"-1"},[s("math 数学公式 "),a("a",{class:"header-anchor",href:"#math-数学公式","aria-label":'Permalink to "math 数学公式"'},"​")],-1),a("p",null,[s("在 "),a("code",null,"HTML"),s(" 页面中高质量展示 "),a("code",null,"LaTeX"),s(" 数学公式")],-1),a("h2",{id:"代码演示",tabindex:"-1"},[s("代码演示 "),a("a",{class:"header-anchor",href:"#代码演示","aria-label":'Permalink to "代码演示"'},"​")],-1),a("r-math",{latex:"\\frac{x^2}{a^2} + \\frac{y^2}{b^2} = 1 \\quad (a > b > 0)"},null,-1),i('
xml
<r-math latex="\\frac{x^2}{a^2} + \\frac{y^2}{b^2} = 1 \\quad (a > b > 0)"></r-math>

属性

latex string

',3),a("r-math",{latex:"x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}"},null,-1),i('
xml
  <r-math latex="x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}"></r-math>
',1)]))}const m=e(h,[["render",r]]);export{E as __pageData,m as default}; diff --git a/assets/cn_src_ranui_message_index.md.DDK6JB1T.js b/assets/cn_src_ranui_message_index.md.DDK6JB1T.js new file mode 100644 index 0000000000..e2d5d2ffcd --- /dev/null +++ b/assets/cn_src_ranui_message_index.md.DDK6JB1T.js @@ -0,0 +1,5 @@ +import{_ as e,o as n,c as h,j as s,a,a3 as t}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"message 全局提示","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/message/index.md","filePath":"cn/src/ranui/message/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/ranui/message/index.md"};function k(p,i,r,d,o,g){return n(),h("div",{"data-pagefind-body":!0},i[0]||(i[0]=[s("h1",{id:"message-全局提示",tabindex:"-1"},[a("message 全局提示 "),s("a",{class:"header-anchor",href:"#message-全局提示","aria-label":'Permalink to "message 全局提示"'},"​")],-1),s("p",null,"全局展示操作反馈信息。",-1),s("h2",{id:"代码演示",tabindex:"-1"},[a("代码演示 "),s("a",{class:"header-anchor",href:"#代码演示","aria-label":'Permalink to "代码演示"'},"​")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{type:"primary",onclick:"message.info('这是一条提示')"},"点击触发全局提示")],-1),t('
xml
<r-button type="primary" onclick="message.info('这是一条提示')">点击触发全局提示</r-button>

属性

类型type

不同的提示类型

',4),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.info('这是一条提示')"},"信息提示")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.warning('这是一条提示')"},"警告提示")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.error('这是一条提示')"},"错误提示")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.success('这是一条提示')"},"成功提示")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.toast('这是一条提示')"},"toast提示")],-1),t(`
html
<r-button onclick="message.info('这是一条提示')">信息提示</r-button>
+<r-button onclick="message.warning('这是一条提示')">警告提示</r-button>
+<r-button onclick="message.error('这是一条提示')">错误提示</r-button>
+<r-button onclick="message.success('这是一条提示')">成功提示</r-button>
+<r-button onclick="message.toast('这是一条提示')">toast提示</r-button>

方法

组件提供了一些静态方法,使用方式和参数如下:

  1. 可以只传一个参数,提示的内容,默认提示 3000 毫秒

message.info('这是一条提示')

message.warning('这是一条提示')

message.error('这是一条提示')

message.success('这是一条提示')

message.toast('这是一条提示')"

  1. 也可以传一个对象,设置提示内容,关闭延时,关闭时触发的回调函数

message.info({content:'这是一条提示', duration: 2000, close: () => {}})

message.warning({content:'这是一条提示', duration: 2000, close: () => {}})

message.error({content:'这是一条提示', duration: 2000, close: () => {}})

message.success({content:'这是一条提示', duration: 2000, close: () => {}})

message.toast({content:'这是一条提示', duration: 2000, close: () => {}})

参数说明类型
content提示内容string
duration自动关闭的延时,单位毫秒。默认 3000 毫秒number
close关闭时触发的回调函数() => void
`,16)]))}const y=e(l,[["render",k]]);export{c as __pageData,y as default}; diff --git a/assets/cn_src_ranui_message_index.md.DDK6JB1T.lean.js b/assets/cn_src_ranui_message_index.md.DDK6JB1T.lean.js new file mode 100644 index 0000000000..e2d5d2ffcd --- /dev/null +++ b/assets/cn_src_ranui_message_index.md.DDK6JB1T.lean.js @@ -0,0 +1,5 @@ +import{_ as e,o as n,c as h,j as s,a,a3 as t}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"message 全局提示","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/message/index.md","filePath":"cn/src/ranui/message/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/ranui/message/index.md"};function k(p,i,r,d,o,g){return n(),h("div",{"data-pagefind-body":!0},i[0]||(i[0]=[s("h1",{id:"message-全局提示",tabindex:"-1"},[a("message 全局提示 "),s("a",{class:"header-anchor",href:"#message-全局提示","aria-label":'Permalink to "message 全局提示"'},"​")],-1),s("p",null,"全局展示操作反馈信息。",-1),s("h2",{id:"代码演示",tabindex:"-1"},[a("代码演示 "),s("a",{class:"header-anchor",href:"#代码演示","aria-label":'Permalink to "代码演示"'},"​")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{type:"primary",onclick:"message.info('这是一条提示')"},"点击触发全局提示")],-1),t('
xml
<r-button type="primary" onclick="message.info('这是一条提示')">点击触发全局提示</r-button>

属性

类型type

不同的提示类型

',4),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.info('这是一条提示')"},"信息提示")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.warning('这是一条提示')"},"警告提示")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.error('这是一条提示')"},"错误提示")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.success('这是一条提示')"},"成功提示")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.toast('这是一条提示')"},"toast提示")],-1),t(`
html
<r-button onclick="message.info('这是一条提示')">信息提示</r-button>
+<r-button onclick="message.warning('这是一条提示')">警告提示</r-button>
+<r-button onclick="message.error('这是一条提示')">错误提示</r-button>
+<r-button onclick="message.success('这是一条提示')">成功提示</r-button>
+<r-button onclick="message.toast('这是一条提示')">toast提示</r-button>

方法

组件提供了一些静态方法,使用方式和参数如下:

  1. 可以只传一个参数,提示的内容,默认提示 3000 毫秒

message.info('这是一条提示')

message.warning('这是一条提示')

message.error('这是一条提示')

message.success('这是一条提示')

message.toast('这是一条提示')"

  1. 也可以传一个对象,设置提示内容,关闭延时,关闭时触发的回调函数

message.info({content:'这是一条提示', duration: 2000, close: () => {}})

message.warning({content:'这是一条提示', duration: 2000, close: () => {}})

message.error({content:'这是一条提示', duration: 2000, close: () => {}})

message.success({content:'这是一条提示', duration: 2000, close: () => {}})

message.toast({content:'这是一条提示', duration: 2000, close: () => {}})

参数说明类型
content提示内容string
duration自动关闭的延时,单位毫秒。默认 3000 毫秒number
close关闭时触发的回调函数() => void
`,16)]))}const y=e(l,[["render",k]]);export{c as __pageData,y as default}; diff --git a/assets/cn_src_ranui_modal_index.md.Bl-bNDpJ.js b/assets/cn_src_ranui_modal_index.md.Bl-bNDpJ.js new file mode 100644 index 0000000000..e9e6b1fdbc --- /dev/null +++ b/assets/cn_src_ranui_modal_index.md.Bl-bNDpJ.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as t}from"./chunks/framework.C-ai2y4t.js";const l=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/modal/index.md","filePath":"cn/src/ranui/modal/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranui/modal/index.md"};function r(c,o,s,d,i,m){return a(),t("div")}const _=e(n,[["render",r]]);export{l as __pageData,_ as default}; diff --git a/assets/cn_src_ranui_modal_index.md.Bl-bNDpJ.lean.js b/assets/cn_src_ranui_modal_index.md.Bl-bNDpJ.lean.js new file mode 100644 index 0000000000..e9e6b1fdbc --- /dev/null +++ b/assets/cn_src_ranui_modal_index.md.Bl-bNDpJ.lean.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as t}from"./chunks/framework.C-ai2y4t.js";const l=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/modal/index.md","filePath":"cn/src/ranui/modal/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranui/modal/index.md"};function r(c,o,s,d,i,m){return a(),t("div")}const _=e(n,[["render",r]]);export{l as __pageData,_ as default}; diff --git a/assets/cn_src_ranui_player_index.md.BPeeUAmI.js b/assets/cn_src_ranui_player_index.md.BPeeUAmI.js new file mode 100644 index 0000000000..68a2255b8c --- /dev/null +++ b/assets/cn_src_ranui_player_index.md.BPeeUAmI.js @@ -0,0 +1 @@ +import{_ as e,o as d,c as a,a3 as r}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"r-player 视频播放器","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/player/index.md","filePath":"cn/src/ranui/player/index.md","lastUpdated":1726550590000}'),i={name:"cn/src/ranui/player/index.md"};function l(o,t,n,s,h,c){return d(),a("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

r-player 视频播放器

基于hlsjsweb components,让原生的标签r-player拥有统一的视频控件。 不采用new Player(options)的方式挂载到指定dom,视图的归视图,逻辑的归逻辑,所见及所得,更加直观。

  1. 可拖拽进度条
  2. 音量控制
  3. 根据当前带宽自适应码率切换
  4. 手动清晰度切换
  5. 倍速播放
  6. 样式自定义覆盖
  7. hls协议标准加密视频播放
  8. 基于原生开发,可在所有框架运行,统一跨框架情况
  9. 各浏览器控件统一

代码演示

xml
  <r-player src="/ran/hls/example.m3u8"></r-player>

属性

src

视频的资源地址

volume

设置初始音量,默认 0.5

currentTime

设置初始播放时间,默认从头开始播放

playbackRate

设置倍速,默认 1.0

debug

控制台会打印输出一些信息

事件event

onchange

监听任何播放器发生的变化,返回的值如下。

可通过这个方法获得播放器的实例

活着通过type判断不同的事件类型,进行不同的操作

属性说明类型
type发生变化的事件类型string
data事件的值Object
currentTime播放的当前时间number
duration视频的总时长number
tag播放器的实例Element

其中type类型有

名称说明
canplay浏览器可以播放媒体文件了,但估计没有足够的数据来支撑播放到结束,不必停下来进一步缓冲内容。
canplaythrough浏览器估计它可以在不停止内容缓冲的情况下播放媒体直到结束。
completeOfflineAudioContext 渲染完成。
durationchangeduration 属性的值改变时触发。
emptied媒体内容变为空;例如,当这个 media 已经加载完成(或者部分加载完成),则发送此事件,并调用 load() 方法重新加载它。
ended视频停止播放,因为 media 已经到达结束点。
loadedmetadata已加载元数据。
progress在浏览器加载资源时周期性触发。
ratechange播放速率发生变化。
seeked跳帧(seek)操作完成。
seeking跳帧(seek)操作开始。
stalled用户代理(user agent)正在尝试获取媒体数据,但数据意外未出现。
suspend媒体数据加载已暂停。
loadeddatamedia 中的首帧已经完成加载。
timeupdatecurrentTime 属性指定的时间发生变化。
volumechange音量发生变化。
waiting由于暂时缺少数据,播放已停止。
play播放已开始。
playing由于缺乏数据而暂停或延迟后,播放准备开始。
pause播放已暂停。
volume音量发生变化。
fullscreen触发全屏事件
',25)]))}const m=e(i,[["render",l]]);export{u as __pageData,m as default}; diff --git a/assets/cn_src_ranui_player_index.md.BPeeUAmI.lean.js b/assets/cn_src_ranui_player_index.md.BPeeUAmI.lean.js new file mode 100644 index 0000000000..68a2255b8c --- /dev/null +++ b/assets/cn_src_ranui_player_index.md.BPeeUAmI.lean.js @@ -0,0 +1 @@ +import{_ as e,o as d,c as a,a3 as r}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"r-player 视频播放器","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/player/index.md","filePath":"cn/src/ranui/player/index.md","lastUpdated":1726550590000}'),i={name:"cn/src/ranui/player/index.md"};function l(o,t,n,s,h,c){return d(),a("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

r-player 视频播放器

基于hlsjsweb components,让原生的标签r-player拥有统一的视频控件。 不采用new Player(options)的方式挂载到指定dom,视图的归视图,逻辑的归逻辑,所见及所得,更加直观。

  1. 可拖拽进度条
  2. 音量控制
  3. 根据当前带宽自适应码率切换
  4. 手动清晰度切换
  5. 倍速播放
  6. 样式自定义覆盖
  7. hls协议标准加密视频播放
  8. 基于原生开发,可在所有框架运行,统一跨框架情况
  9. 各浏览器控件统一

代码演示

xml
  <r-player src="/ran/hls/example.m3u8"></r-player>

属性

src

视频的资源地址

volume

设置初始音量,默认 0.5

currentTime

设置初始播放时间,默认从头开始播放

playbackRate

设置倍速,默认 1.0

debug

控制台会打印输出一些信息

事件event

onchange

监听任何播放器发生的变化,返回的值如下。

可通过这个方法获得播放器的实例

活着通过type判断不同的事件类型,进行不同的操作

属性说明类型
type发生变化的事件类型string
data事件的值Object
currentTime播放的当前时间number
duration视频的总时长number
tag播放器的实例Element

其中type类型有

名称说明
canplay浏览器可以播放媒体文件了,但估计没有足够的数据来支撑播放到结束,不必停下来进一步缓冲内容。
canplaythrough浏览器估计它可以在不停止内容缓冲的情况下播放媒体直到结束。
completeOfflineAudioContext 渲染完成。
durationchangeduration 属性的值改变时触发。
emptied媒体内容变为空;例如,当这个 media 已经加载完成(或者部分加载完成),则发送此事件,并调用 load() 方法重新加载它。
ended视频停止播放,因为 media 已经到达结束点。
loadedmetadata已加载元数据。
progress在浏览器加载资源时周期性触发。
ratechange播放速率发生变化。
seeked跳帧(seek)操作完成。
seeking跳帧(seek)操作开始。
stalled用户代理(user agent)正在尝试获取媒体数据,但数据意外未出现。
suspend媒体数据加载已暂停。
loadeddatamedia 中的首帧已经完成加载。
timeupdatecurrentTime 属性指定的时间发生变化。
volumechange音量发生变化。
waiting由于暂时缺少数据,播放已停止。
play播放已开始。
playing由于缺乏数据而暂停或延迟后,播放准备开始。
pause播放已暂停。
volume音量发生变化。
fullscreen触发全屏事件
',25)]))}const m=e(i,[["render",l]]);export{u as __pageData,m as default}; diff --git a/assets/cn_src_ranui_popover_index.md.CVPFx-rd.js b/assets/cn_src_ranui_popover_index.md.CVPFx-rd.js new file mode 100644 index 0000000000..8835bf5947 --- /dev/null +++ b/assets/cn_src_ranui_popover_index.md.CVPFx-rd.js @@ -0,0 +1,26 @@ +import{_ as t,o as n,c as l,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"Popover 气泡卡片","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/popover/index.md","filePath":"cn/src/ranui/popover/index.md","lastUpdated":1726550590000}'),h={name:"cn/src/ranui/popover/index.md"};function p(k,a,e,E,r,d){return n(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

Popover 气泡卡片

点击/鼠标移入元素,弹出气泡式的卡片浮层。

代码演示

popover
this is content
xml
<r-popover>
+    <r-button>popover</r-button>
+    <r-content>
+      <div>this is content</div>
+    </r-content>
+</r-popover>

属性

trigger

触发方式

  • hover
`,9),s("r-popover",{trigger:"hover"},[s("r-button",null,"hover"),s("r-content",null,[s("div",null,"hover")])],-1),i(`
xml
<r-popover trigger="hover">
+    <r-button>hover</r-button>
+    <r-content>
+      <div>hover</div>
+    </r-content>
+  </r-popover>
  • click
`,2),s("r-popover",{trigger:"click"},[s("r-button",null,"click"),s("r-content",null,[s("div",null,"click")])],-1),i(`
xml
<r-popover trigger="click">
+    <r-button>click</r-button>
+    <r-content>
+      <div>click</div>
+    </r-content>
+  </r-popover>

placement

展示的位置

  • bottom
`,4),s("r-popover",{trigger:"hover",placement:"bottom"},[s("r-button",null,"bottom"),s("r-content",null,[s("div",null,"bottom")])],-1),i(`
xml
<r-popover trigger="hover" placement="bottom">
+    <r-button>bottom</r-button>
+    <r-content>
+      <div>bottom</div>
+    </r-content>
+  </r-popover>
  • top
`,2),s("r-popover",{trigger:"hover",placement:"top"},[s("r-button",null,"top"),s("r-content",null,[s("div",null,"top")])],-1),i(`
xml
<r-popover trigger="hover" placement="top">
+    <r-button>top</r-button>
+    <r-content>
+      <div>top</div>
+    </r-content>
+  </r-popover>
`,1)]))}const c=t(h,[["render",p]]);export{o as __pageData,c as default}; diff --git a/assets/cn_src_ranui_popover_index.md.CVPFx-rd.lean.js b/assets/cn_src_ranui_popover_index.md.CVPFx-rd.lean.js new file mode 100644 index 0000000000..8835bf5947 --- /dev/null +++ b/assets/cn_src_ranui_popover_index.md.CVPFx-rd.lean.js @@ -0,0 +1,26 @@ +import{_ as t,o as n,c as l,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"Popover 气泡卡片","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/popover/index.md","filePath":"cn/src/ranui/popover/index.md","lastUpdated":1726550590000}'),h={name:"cn/src/ranui/popover/index.md"};function p(k,a,e,E,r,d){return n(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

Popover 气泡卡片

点击/鼠标移入元素,弹出气泡式的卡片浮层。

代码演示

popover
this is content
xml
<r-popover>
+    <r-button>popover</r-button>
+    <r-content>
+      <div>this is content</div>
+    </r-content>
+</r-popover>

属性

trigger

触发方式

  • hover
`,9),s("r-popover",{trigger:"hover"},[s("r-button",null,"hover"),s("r-content",null,[s("div",null,"hover")])],-1),i(`
xml
<r-popover trigger="hover">
+    <r-button>hover</r-button>
+    <r-content>
+      <div>hover</div>
+    </r-content>
+  </r-popover>
  • click
`,2),s("r-popover",{trigger:"click"},[s("r-button",null,"click"),s("r-content",null,[s("div",null,"click")])],-1),i(`
xml
<r-popover trigger="click">
+    <r-button>click</r-button>
+    <r-content>
+      <div>click</div>
+    </r-content>
+  </r-popover>

placement

展示的位置

  • bottom
`,4),s("r-popover",{trigger:"hover",placement:"bottom"},[s("r-button",null,"bottom"),s("r-content",null,[s("div",null,"bottom")])],-1),i(`
xml
<r-popover trigger="hover" placement="bottom">
+    <r-button>bottom</r-button>
+    <r-content>
+      <div>bottom</div>
+    </r-content>
+  </r-popover>
  • top
`,2),s("r-popover",{trigger:"hover",placement:"top"},[s("r-button",null,"top"),s("r-content",null,[s("div",null,"top")])],-1),i(`
xml
<r-popover trigger="hover" placement="top">
+    <r-button>top</r-button>
+    <r-content>
+      <div>top</div>
+    </r-content>
+  </r-popover>
`,1)]))}const c=t(h,[["render",p]]);export{o as __pageData,c as default}; diff --git a/assets/cn_src_ranui_preview_index.md.DI-R6RxP.js b/assets/cn_src_ranui_preview_index.md.DI-R6RxP.js new file mode 100644 index 0000000000..79469ae0cd --- /dev/null +++ b/assets/cn_src_ranui_preview_index.md.DI-R6RxP.js @@ -0,0 +1,20 @@ +import{_ as h,o as t,c as n,a3 as a,j as s}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"preview 文件预览","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/preview/index.md","filePath":"cn/src/ranui/preview/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/ranui/preview/index.md"};function k(p,i,e,E,r,d){return t(),n("div",{"data-pagefind-body":!0},i[0]||(i[0]=[a('

preview 文件预览

支持docxpptxpdf,xlsx文件的预览

代码演示

',3),s("div",{style:{width:"100px","margin-top":"10px"}},[s("r-preview",{id:"fhdjskafk"}),s("r-button",{type:"primary",onclick:"uploadFile('fhdjskafk')"},"choose file to preview")],-1),a(`
html
<r-preview id="preview"></r-preview>
+<r-button type="primary" onclick="uploadFile()">choose file to preview</r-button>
+
+<script>
+  const uploadFile = () => {
+    const preview = document.getElementById('preview');
+    const uploadFile = document.createElement('input');
+    uploadFile.setAttribute('type', 'file');
+    uploadFile.click();
+    uploadFile.onchange = (e) => {
+      const { files = [] } = uploadFile;
+      if (files.length > 0) {
+        preview.setAttribute('src', '');
+        const file = files[0];
+        const url = URL.createObjectURL(file);
+        preview.setAttribute('src', url);
+      }
+    };
+  };
+</script>

属性

资源地址src

src 地址即可打开弹窗,没有src就不展示

html
<r-preview src=""></r-preview>

是否可关闭closeable

closeable 默认为 true ,可以关闭,设置成 false 时, 表示不可关闭,将不会展示右上角的关闭按钮

html
<r-preview closeable="false"></r-preview>
`,8)]))}const c=h(l,[["render",k]]);export{y as __pageData,c as default}; diff --git a/assets/cn_src_ranui_preview_index.md.DI-R6RxP.lean.js b/assets/cn_src_ranui_preview_index.md.DI-R6RxP.lean.js new file mode 100644 index 0000000000..79469ae0cd --- /dev/null +++ b/assets/cn_src_ranui_preview_index.md.DI-R6RxP.lean.js @@ -0,0 +1,20 @@ +import{_ as h,o as t,c as n,a3 as a,j as s}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"preview 文件预览","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/preview/index.md","filePath":"cn/src/ranui/preview/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/ranui/preview/index.md"};function k(p,i,e,E,r,d){return t(),n("div",{"data-pagefind-body":!0},i[0]||(i[0]=[a('

preview 文件预览

支持docxpptxpdf,xlsx文件的预览

代码演示

',3),s("div",{style:{width:"100px","margin-top":"10px"}},[s("r-preview",{id:"fhdjskafk"}),s("r-button",{type:"primary",onclick:"uploadFile('fhdjskafk')"},"choose file to preview")],-1),a(`
html
<r-preview id="preview"></r-preview>
+<r-button type="primary" onclick="uploadFile()">choose file to preview</r-button>
+
+<script>
+  const uploadFile = () => {
+    const preview = document.getElementById('preview');
+    const uploadFile = document.createElement('input');
+    uploadFile.setAttribute('type', 'file');
+    uploadFile.click();
+    uploadFile.onchange = (e) => {
+      const { files = [] } = uploadFile;
+      if (files.length > 0) {
+        preview.setAttribute('src', '');
+        const file = files[0];
+        const url = URL.createObjectURL(file);
+        preview.setAttribute('src', url);
+      }
+    };
+  };
+</script>

属性

资源地址src

src 地址即可打开弹窗,没有src就不展示

html
<r-preview src=""></r-preview>

是否可关闭closeable

closeable 默认为 true ,可以关闭,设置成 false 时, 表示不可关闭,将不会展示右上角的关闭按钮

html
<r-preview closeable="false"></r-preview>
`,8)]))}const c=h(l,[["render",k]]);export{y as __pageData,c as default}; diff --git a/assets/cn_src_ranui_progress_index.md.B8zrCakA.js b/assets/cn_src_ranui_progress_index.md.B8zrCakA.js new file mode 100644 index 0000000000..f0bae462a5 --- /dev/null +++ b/assets/cn_src_ranui_progress_index.md.B8zrCakA.js @@ -0,0 +1 @@ +import{_ as t,o as h,c as e,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"progress 进度条","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/progress/index.md","filePath":"cn/src/ranui/progress/index.md","lastUpdated":1726550590000}'),p={name:"cn/src/ranui/progress/index.md"};function l(n,a,k,r,d,E){return h(),e("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

progress 进度条

可交互的进度条

代码演示

xml
<r-progress type="drag" ></r-progress>

属性

总进度total

设置进度条总进度,允许百分比和数字。

',8),s("r-progress",{percent:"30",total:"1000"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{percent:"70",total:"100"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{percent:"10%",total:"100%"},null,-1),i('
html
<r-progress percent="30" total="1000"></r-progress>\n<r-progress percent="70" total="100"></r-progress>\n<r-progress percent="10%" total="100%"></r-progress>

当前进度percent

设置进度条的当前进度,可以设置百分比和数字,percent不能超过total。如果不设置total,默认total100%也就是1

',3),s("r-progress",{type:"primary",percent:"30%"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"70%"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"100%"},null,-1),i('
html
<r-progress type="primary" percent="30%"></r-progress>\n<r-progress type="primary" percent="40%"></r-progress>\n<r-progress type="primary" percent="100%"></r-progress>

进度条的点dot

默认展示,设置成false可隐藏

',3),s("r-progress",{type:"drag",percent:"30%",dot:"false"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"40%",dot:"true"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"40%"},null,-1),i('
html
<r-progress type="drag" percent="30%" dot="false"></r-progress>\n<r-progress type="primary" percent="40%" dot="true"></r-progress>\n<r-progress type="primary" percent="40%"></r-progress>

类型type

  • primary: 默认的进度条,不设置type属性是默认
  • drag: 可拖动,可点击的进度条(拖动需要设置dottrue
',3),s("r-progress",{type:"drag",percent:"30%"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"40%"},null,-1),i('
html
<r-progress type="drag" percent="30%"></r-progress> <r-progress type="primary" percent="40%"></r-progress>

方法

change

percenttotal属性发生变化时,触发change事件。

属性说明类型
value当前进度string|number
percent当前进度string|number
total总进度string|number
',5)]))}const y=t(p,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/cn_src_ranui_progress_index.md.B8zrCakA.lean.js b/assets/cn_src_ranui_progress_index.md.B8zrCakA.lean.js new file mode 100644 index 0000000000..f0bae462a5 --- /dev/null +++ b/assets/cn_src_ranui_progress_index.md.B8zrCakA.lean.js @@ -0,0 +1 @@ +import{_ as t,o as h,c as e,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"progress 进度条","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/progress/index.md","filePath":"cn/src/ranui/progress/index.md","lastUpdated":1726550590000}'),p={name:"cn/src/ranui/progress/index.md"};function l(n,a,k,r,d,E){return h(),e("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

progress 进度条

可交互的进度条

代码演示

xml
<r-progress type="drag" ></r-progress>

属性

总进度total

设置进度条总进度,允许百分比和数字。

',8),s("r-progress",{percent:"30",total:"1000"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{percent:"70",total:"100"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{percent:"10%",total:"100%"},null,-1),i('
html
<r-progress percent="30" total="1000"></r-progress>\n<r-progress percent="70" total="100"></r-progress>\n<r-progress percent="10%" total="100%"></r-progress>

当前进度percent

设置进度条的当前进度,可以设置百分比和数字,percent不能超过total。如果不设置total,默认total100%也就是1

',3),s("r-progress",{type:"primary",percent:"30%"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"70%"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"100%"},null,-1),i('
html
<r-progress type="primary" percent="30%"></r-progress>\n<r-progress type="primary" percent="40%"></r-progress>\n<r-progress type="primary" percent="100%"></r-progress>

进度条的点dot

默认展示,设置成false可隐藏

',3),s("r-progress",{type:"drag",percent:"30%",dot:"false"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"40%",dot:"true"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"40%"},null,-1),i('
html
<r-progress type="drag" percent="30%" dot="false"></r-progress>\n<r-progress type="primary" percent="40%" dot="true"></r-progress>\n<r-progress type="primary" percent="40%"></r-progress>

类型type

  • primary: 默认的进度条,不设置type属性是默认
  • drag: 可拖动,可点击的进度条(拖动需要设置dottrue
',3),s("r-progress",{type:"drag",percent:"30%"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"40%"},null,-1),i('
html
<r-progress type="drag" percent="30%"></r-progress> <r-progress type="primary" percent="40%"></r-progress>

方法

change

percenttotal属性发生变化时,触发change事件。

属性说明类型
value当前进度string|number
percent当前进度string|number
total总进度string|number
',5)]))}const y=t(p,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/cn_src_ranui_radar_index.md.K6NP370R.js b/assets/cn_src_ranui_radar_index.md.K6NP370R.js new file mode 100644 index 0000000000..80b345d9ce --- /dev/null +++ b/assets/cn_src_ranui_radar_index.md.K6NP370R.js @@ -0,0 +1,55 @@ +import{_ as l,o as e,c as o,j as s,a as t,a3 as i}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"Radar 雷达图","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/radar/index.md","filePath":"cn/src/ranui/radar/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranui/radar/index.md"};function h(p,a,k,u,r,q){return e(),o("div",{"data-pagefind-body":!0},a[0]||(a[0]=[s("h1",{id:"radar-雷达图",tabindex:"-1"},[t("Radar 雷达图 "),s("a",{class:"header-anchor",href:"#radar-雷达图","aria-label":'Permalink to "Radar 雷达图"'},"​")],-1),s("p",null,"以二维形式综合对比多组数据的差异,常用于比较 2 组或更多组数据集",-1),s("h2",{id:"代码演示",tabindex:"-1"},[t("代码演示 "),s("a",{class:"header-anchor",href:"#代码演示","aria-label":'Permalink to "代码演示"'},"​")],-1),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},abilitys:'[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),i(`
xml
<r-radar
+    abilitys='[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

属性

需要展示的数据abilitys

一个数组对象,对象中属性如下

参数说明类型
abilityName展示的属性名称必传参数string
scoreRate展示维度的数值,最大 100必传参数number
backgroundColor属性名称的背景颜色可选参数string
fontSize属性名称的字体大小可选参数number
fontFamily属性名称的字体可选参数string
fontColor属性名称的字体颜色可选参数string
`,5),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},abilitys:'[{"abilityName":"生命","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),i(`
xml
<r-radar
+    abilitys='[{"abilityName":"生命","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

多边形颜色colorPolygon

`,2),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},colorPolygon:"green",abilitys:'[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),i(`
xml
<r-radar
+    colorPolygon="green"
+    abilitys='[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

顶点连线颜色colorLine

`,2),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},colorLine:"blue",abilitys:'[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),i(`
xml
<r-radar
+    colorLine="blue"
+    abilitys='[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+></r-radar>

数据渲染处的颜色fillColor

`,2),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},fillColor:"red",abilitys:'[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),i(`
xml
<r-radar
+    fillColor="red"
+    abilitys='[{"abilityName":"生命","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

数据渲染处线和点的颜色strokeColor

`,2),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},strokeColor:"blue",abilitys:'[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),i(`
xml
<r-radar
+    strokeColor="blue"
+    abilitys='[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

使用的例子数据

由于HTMlattribute只能获取string。因此需要传入的数据需要是json字符串格式,然后通过JSON.parse解析程数组对象,如果JSON格式有误,则无法解析。

json
[
+  {
+    "abilityName": "生命",
+    "scoreRate": "10",
+    "backgroundColor": "red",
+    "fontSize": "30",
+    "fontColor": "blue"
+  },
+  {
+    "abilityName": "攻击",
+    "scoreRate": "90"
+  },
+  {
+    "abilityName": "防御",
+    "scoreRate": "20"
+  },
+  {
+    "abilityName": "元素精通",
+    "scoreRate": "50"
+  },
+  {
+    "abilityName": "暴击率",
+    "scoreRate": "80"
+  },
+  {
+    "abilityName": "暴击伤害",
+    "scoreRate": "50"
+  }
+]
`,4)]))}const c=l(n,[["render",h]]);export{E as __pageData,c as default}; diff --git a/assets/cn_src_ranui_radar_index.md.K6NP370R.lean.js b/assets/cn_src_ranui_radar_index.md.K6NP370R.lean.js new file mode 100644 index 0000000000..80b345d9ce --- /dev/null +++ b/assets/cn_src_ranui_radar_index.md.K6NP370R.lean.js @@ -0,0 +1,55 @@ +import{_ as l,o as e,c as o,j as s,a as t,a3 as i}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"Radar 雷达图","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/radar/index.md","filePath":"cn/src/ranui/radar/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranui/radar/index.md"};function h(p,a,k,u,r,q){return e(),o("div",{"data-pagefind-body":!0},a[0]||(a[0]=[s("h1",{id:"radar-雷达图",tabindex:"-1"},[t("Radar 雷达图 "),s("a",{class:"header-anchor",href:"#radar-雷达图","aria-label":'Permalink to "Radar 雷达图"'},"​")],-1),s("p",null,"以二维形式综合对比多组数据的差异,常用于比较 2 组或更多组数据集",-1),s("h2",{id:"代码演示",tabindex:"-1"},[t("代码演示 "),s("a",{class:"header-anchor",href:"#代码演示","aria-label":'Permalink to "代码演示"'},"​")],-1),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},abilitys:'[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),i(`
xml
<r-radar
+    abilitys='[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

属性

需要展示的数据abilitys

一个数组对象,对象中属性如下

参数说明类型
abilityName展示的属性名称必传参数string
scoreRate展示维度的数值,最大 100必传参数number
backgroundColor属性名称的背景颜色可选参数string
fontSize属性名称的字体大小可选参数number
fontFamily属性名称的字体可选参数string
fontColor属性名称的字体颜色可选参数string
`,5),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},abilitys:'[{"abilityName":"生命","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),i(`
xml
<r-radar
+    abilitys='[{"abilityName":"生命","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

多边形颜色colorPolygon

`,2),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},colorPolygon:"green",abilitys:'[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),i(`
xml
<r-radar
+    colorPolygon="green"
+    abilitys='[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

顶点连线颜色colorLine

`,2),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},colorLine:"blue",abilitys:'[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),i(`
xml
<r-radar
+    colorLine="blue"
+    abilitys='[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+></r-radar>

数据渲染处的颜色fillColor

`,2),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},fillColor:"red",abilitys:'[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),i(`
xml
<r-radar
+    fillColor="red"
+    abilitys='[{"abilityName":"生命","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

数据渲染处线和点的颜色strokeColor

`,2),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},strokeColor:"blue",abilitys:'[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'},null,-1),i(`
xml
<r-radar
+    strokeColor="blue"
+    abilitys='[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

使用的例子数据

由于HTMlattribute只能获取string。因此需要传入的数据需要是json字符串格式,然后通过JSON.parse解析程数组对象,如果JSON格式有误,则无法解析。

json
[
+  {
+    "abilityName": "生命",
+    "scoreRate": "10",
+    "backgroundColor": "red",
+    "fontSize": "30",
+    "fontColor": "blue"
+  },
+  {
+    "abilityName": "攻击",
+    "scoreRate": "90"
+  },
+  {
+    "abilityName": "防御",
+    "scoreRate": "20"
+  },
+  {
+    "abilityName": "元素精通",
+    "scoreRate": "50"
+  },
+  {
+    "abilityName": "暴击率",
+    "scoreRate": "80"
+  },
+  {
+    "abilityName": "暴击伤害",
+    "scoreRate": "50"
+  }
+]
`,4)]))}const c=l(n,[["render",h]]);export{E as __pageData,c as default}; diff --git a/assets/cn_src_ranui_select_index.md.T7hcvhSo.js b/assets/cn_src_ranui_select_index.md.T7hcvhSo.js new file mode 100644 index 0000000000..54b8de0a9d --- /dev/null +++ b/assets/cn_src_ranui_select_index.md.T7hcvhSo.js @@ -0,0 +1,42 @@ +import{_ as h,o as l,c as n,j as s,a as t,a3 as i}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"Select 下拉选择框","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/select/index.md","filePath":"cn/src/ranui/select/index.md","lastUpdated":1726550590000}'),k={name:"cn/src/ranui/select/index.md"};function p(e,a,E,r,d,o){return l(),n("div",{"data-pagefind-body":!0},a[0]||(a[0]=[s("h1",{id:"select-下拉选择框",tabindex:"-1"},[t("Select 下拉选择框 "),s("a",{class:"header-anchor",href:"#select-下拉选择框","aria-label":'Permalink to "Select 下拉选择框"'},"​")],-1),s("p",null,"一个普通的下拉选择器。",-1),s("h2",{id:"代码演示",tabindex:"-1"},[t("代码演示 "),s("a",{class:"header-anchor",href:"#代码演示","aria-label":'Permalink to "代码演示"'},"​")],-1),s("r-select",{style:{width:"120px",height:"40px"},defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select style="width: 120px; height: 40px" defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

属性

默认值defaultValue

设置当前选中的值

`,4),s("r-select",{style:{width:"120px",height:"40px"},defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
    <r-select style="width: 120px; height: 40px" defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

不可用状态disabled

添加 disabled 属性即可让选择框处于不可用状态,同时样式也会改变。

`,3),s("r-select",{style:{width:"120px",height:"40px"},disabled:"",defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
    <r-select style="width: 120px; height: 40px" disabled defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

类型type

可以设置文本类型,不要边框和下拉图标

`,3),s("r-select",{style:{width:"120px",height:"40px"},type:"text",defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select
+      style="width: 120px; height: 40px"
+      type="text"
+      defaultValue="185"
+    >
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

下拉框的展示方向placement

下拉框展示方向默认往下,设置成top可以往上

`,3),s("r-select",{style:{width:"120px",height:"40px"},type:"text",defaultValue:"185",placement:"top"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select
+      style="width: 120px; height: 40px"
+      type="text"
+      defaultValue="185"
+      placement="top"
+    >
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

带搜索框 showSearch

展开后可对选项进行搜索

`,3),s("r-select",{style:{width:"120px",height:"40px"},showSearch:""},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select style="width: 120px; height: 40px" showSearch>
+<r-option value="185">Mike</r-option>
+<r-option value="186">Tom</r-option>
+<r-option value="187">Lucy</r-option>
+</r-select>

下拉框挂载元素的 idgetPopupContainerId

下拉框默认挂载到document.body上,可以传入元素的id,挂载到指定的元素内 \`

MikeTomLucy
xml
<r-select getPopupContainerId="elementid">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

下拉框的 class 名dropdownclass

如果需要自定义下拉框的样式,可以传入一个 class 名,进行自定义

trigger

select 组件触发的方法。默认 click ,点击触发。可以设置hover,或者click,hover,表示点击和鼠标移入都触发。

如果设置成 none,就不会触发。

`,10),s("r-select",{style:{width:"120px",height:"40px"},trigger:"click,hover"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select getPopupContainerId="elementid" trigger="click,hover">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>
`,1)]))}const c=h(k,[["render",p]]);export{y as __pageData,c as default}; diff --git a/assets/cn_src_ranui_select_index.md.T7hcvhSo.lean.js b/assets/cn_src_ranui_select_index.md.T7hcvhSo.lean.js new file mode 100644 index 0000000000..54b8de0a9d --- /dev/null +++ b/assets/cn_src_ranui_select_index.md.T7hcvhSo.lean.js @@ -0,0 +1,42 @@ +import{_ as h,o as l,c as n,j as s,a as t,a3 as i}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"Select 下拉选择框","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/select/index.md","filePath":"cn/src/ranui/select/index.md","lastUpdated":1726550590000}'),k={name:"cn/src/ranui/select/index.md"};function p(e,a,E,r,d,o){return l(),n("div",{"data-pagefind-body":!0},a[0]||(a[0]=[s("h1",{id:"select-下拉选择框",tabindex:"-1"},[t("Select 下拉选择框 "),s("a",{class:"header-anchor",href:"#select-下拉选择框","aria-label":'Permalink to "Select 下拉选择框"'},"​")],-1),s("p",null,"一个普通的下拉选择器。",-1),s("h2",{id:"代码演示",tabindex:"-1"},[t("代码演示 "),s("a",{class:"header-anchor",href:"#代码演示","aria-label":'Permalink to "代码演示"'},"​")],-1),s("r-select",{style:{width:"120px",height:"40px"},defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select style="width: 120px; height: 40px" defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

属性

默认值defaultValue

设置当前选中的值

`,4),s("r-select",{style:{width:"120px",height:"40px"},defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
    <r-select style="width: 120px; height: 40px" defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

不可用状态disabled

添加 disabled 属性即可让选择框处于不可用状态,同时样式也会改变。

`,3),s("r-select",{style:{width:"120px",height:"40px"},disabled:"",defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
    <r-select style="width: 120px; height: 40px" disabled defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

类型type

可以设置文本类型,不要边框和下拉图标

`,3),s("r-select",{style:{width:"120px",height:"40px"},type:"text",defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select
+      style="width: 120px; height: 40px"
+      type="text"
+      defaultValue="185"
+    >
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

下拉框的展示方向placement

下拉框展示方向默认往下,设置成top可以往上

`,3),s("r-select",{style:{width:"120px",height:"40px"},type:"text",defaultValue:"185",placement:"top"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select
+      style="width: 120px; height: 40px"
+      type="text"
+      defaultValue="185"
+      placement="top"
+    >
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

带搜索框 showSearch

展开后可对选项进行搜索

`,3),s("r-select",{style:{width:"120px",height:"40px"},showSearch:""},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select style="width: 120px; height: 40px" showSearch>
+<r-option value="185">Mike</r-option>
+<r-option value="186">Tom</r-option>
+<r-option value="187">Lucy</r-option>
+</r-select>

下拉框挂载元素的 idgetPopupContainerId

下拉框默认挂载到document.body上,可以传入元素的id,挂载到指定的元素内 \`

MikeTomLucy
xml
<r-select getPopupContainerId="elementid">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

下拉框的 class 名dropdownclass

如果需要自定义下拉框的样式,可以传入一个 class 名,进行自定义

trigger

select 组件触发的方法。默认 click ,点击触发。可以设置hover,或者click,hover,表示点击和鼠标移入都触发。

如果设置成 none,就不会触发。

`,10),s("r-select",{style:{width:"120px",height:"40px"},trigger:"click,hover"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select getPopupContainerId="elementid" trigger="click,hover">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>
`,1)]))}const c=h(k,[["render",p]]);export{y as __pageData,c as default}; diff --git a/assets/cn_src_ranui_skeleton_index.md.D7wv1w9E.js b/assets/cn_src_ranui_skeleton_index.md.D7wv1w9E.js new file mode 100644 index 0000000000..9bdbcdf625 --- /dev/null +++ b/assets/cn_src_ranui_skeleton_index.md.D7wv1w9E.js @@ -0,0 +1 @@ +import{_ as t,o as s,c as a,a3 as i}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"skeleton 骨架屏","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/skeleton/index.md","filePath":"cn/src/ranui/skeleton/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranui/skeleton/index.md"};function l(r,e,o,d,p,k){return s(),a("div",{"data-pagefind-body":!0},e[0]||(e[0]=[i('

skeleton 骨架屏

在需要等待加载内容的位置提供一个占位图形组合。

代码演示

骨架长度跟随父级元素的长度

xml
<r-skeleton ></r-skeleton>
',9)]))}const g=t(n,[["render",l]]);export{c as __pageData,g as default}; diff --git a/assets/cn_src_ranui_skeleton_index.md.D7wv1w9E.lean.js b/assets/cn_src_ranui_skeleton_index.md.D7wv1w9E.lean.js new file mode 100644 index 0000000000..9bdbcdf625 --- /dev/null +++ b/assets/cn_src_ranui_skeleton_index.md.D7wv1w9E.lean.js @@ -0,0 +1 @@ +import{_ as t,o as s,c as a,a3 as i}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"skeleton 骨架屏","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/skeleton/index.md","filePath":"cn/src/ranui/skeleton/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranui/skeleton/index.md"};function l(r,e,o,d,p,k){return s(),a("div",{"data-pagefind-body":!0},e[0]||(e[0]=[i('

skeleton 骨架屏

在需要等待加载内容的位置提供一个占位图形组合。

代码演示

骨架长度跟随父级元素的长度

xml
<r-skeleton ></r-skeleton>
',9)]))}const g=t(n,[["render",l]]);export{c as __pageData,g as default}; diff --git a/assets/cn_src_ranui_tab_index.md.D8xqztOz.js b/assets/cn_src_ranui_tab_index.md.D8xqztOz.js new file mode 100644 index 0000000000..23ba2783c2 --- /dev/null +++ b/assets/cn_src_ranui_tab_index.md.D8xqztOz.js @@ -0,0 +1,43 @@ +import{_ as t,o as l,c as h,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"Tab 图标","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/tab/index.md","filePath":"cn/src/ranui/tab/index.md","lastUpdated":1726550590000}'),k={name:"cn/src/ranui/tab/index.md"};function n(p,a,E,e,r,d){return l(),h("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

Tab 图标

标签页,其中r-tab需要和r-tabs搭配使用

代码演示

111112222233333
xml
<r-tabs >
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

属性

标签名label

r-tab的属性,设置标签的名称

111112222233333
xml
<r-tabs >
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

活跃标签active,标签的唯一标识ranKey

  • ranKeyr-tab的属性,用于确定同一个r-tabsr-tab的唯一值。如果ranKey没有设置,默认等于index。(不采用key字段是防止key是保留字段)
  • activer-tabs的属性,用于设置活跃的标签。active等于key的标签为活跃标签。
  1. 没有设置key
`,13),s("div",{style:{width:"100%"}},[s("r-tabs",{active:"1"},[s("r-tab",{label:"tab1"},"11111"),s("r-tab",{label:"tab2"},"22222"),s("r-tab",{label:"tab3"},"33333")])],-1),i(`
xml
 <r-tabs active="1">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+ </r-tabs>
  1. 设置key
`,2),s("div",{style:{width:"100%"}},[s("r-tabs",{active:"c"},[s("r-tab",{label:"tab1",ranKey:"a"},"11111"),s("r-tab",{label:"tab2",ranKey:"b"},"22222"),s("r-tab",{label:"tab3",ranKey:"c"},"33333"),s("r-tab",{label:"tab4"},"4")])],-1),i(`
xml
    <r-tabs active="c">
+      <r-tab label="tab1" ranKey="a">11111</r-tab>
+      <r-tab label="tab2" ranKey="b">22222</r-tab>
+      <r-tab label="tab3" ranKey="c">33333</r-tab>
+      <r-tab label="tab4">4</r-tab>
+    </r-tabs>

不可操作disabled

设置不可点击的标签

`,3),s("div",{style:{width:"100%"}},[s("r-tabs",{active:"c"},[s("r-tab",{label:"tab1",ranKey:"a",disabled:""},"11111"),s("r-tab",{label:"tab2",ranKey:"b"},"22222"),s("r-tab",{label:"tab3",ranKey:"c"},"33333"),s("r-tab",{label:"tab4"},"4")])],-1),i(`
xml
    <r-tabs active="c">
+      <r-tab label="tab1" ranKey="a" disabled>11111</r-tab>
+      <r-tab label="tab2" ranKey="b">22222</r-tab>
+      <r-tab label="tab3" ranKey="c">33333</r-tab>
+      <r-tab label="tab4">4</r-tab>
+    </r-tabs>

类型type

r-tabs属性,设置标签页的种类。如果不设置,默认为flat

  1. flat
111112222233333
xml
<r-tabs type="flat">
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>
  1. line
111112222233333
xml
<r-tabs type="line">
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

对齐方式align

设置标签的对齐方式,默认align="start"

  1. start
111112222233333
xml
 <r-tabs type="line" align="start">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
  1. center
111112222233333
xml
 <r-tabs type="line" align="center">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
  1. end
111112222233333
xml
 <r-tabs type="line" align="end">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
`,20)]))}const b=t(k,[["render",n]]);export{y as __pageData,b as default}; diff --git a/assets/cn_src_ranui_tab_index.md.D8xqztOz.lean.js b/assets/cn_src_ranui_tab_index.md.D8xqztOz.lean.js new file mode 100644 index 0000000000..23ba2783c2 --- /dev/null +++ b/assets/cn_src_ranui_tab_index.md.D8xqztOz.lean.js @@ -0,0 +1,43 @@ +import{_ as t,o as l,c as h,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"Tab 图标","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/tab/index.md","filePath":"cn/src/ranui/tab/index.md","lastUpdated":1726550590000}'),k={name:"cn/src/ranui/tab/index.md"};function n(p,a,E,e,r,d){return l(),h("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

Tab 图标

标签页,其中r-tab需要和r-tabs搭配使用

代码演示

111112222233333
xml
<r-tabs >
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

属性

标签名label

r-tab的属性,设置标签的名称

111112222233333
xml
<r-tabs >
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

活跃标签active,标签的唯一标识ranKey

  • ranKeyr-tab的属性,用于确定同一个r-tabsr-tab的唯一值。如果ranKey没有设置,默认等于index。(不采用key字段是防止key是保留字段)
  • activer-tabs的属性,用于设置活跃的标签。active等于key的标签为活跃标签。
  1. 没有设置key
`,13),s("div",{style:{width:"100%"}},[s("r-tabs",{active:"1"},[s("r-tab",{label:"tab1"},"11111"),s("r-tab",{label:"tab2"},"22222"),s("r-tab",{label:"tab3"},"33333")])],-1),i(`
xml
 <r-tabs active="1">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+ </r-tabs>
  1. 设置key
`,2),s("div",{style:{width:"100%"}},[s("r-tabs",{active:"c"},[s("r-tab",{label:"tab1",ranKey:"a"},"11111"),s("r-tab",{label:"tab2",ranKey:"b"},"22222"),s("r-tab",{label:"tab3",ranKey:"c"},"33333"),s("r-tab",{label:"tab4"},"4")])],-1),i(`
xml
    <r-tabs active="c">
+      <r-tab label="tab1" ranKey="a">11111</r-tab>
+      <r-tab label="tab2" ranKey="b">22222</r-tab>
+      <r-tab label="tab3" ranKey="c">33333</r-tab>
+      <r-tab label="tab4">4</r-tab>
+    </r-tabs>

不可操作disabled

设置不可点击的标签

`,3),s("div",{style:{width:"100%"}},[s("r-tabs",{active:"c"},[s("r-tab",{label:"tab1",ranKey:"a",disabled:""},"11111"),s("r-tab",{label:"tab2",ranKey:"b"},"22222"),s("r-tab",{label:"tab3",ranKey:"c"},"33333"),s("r-tab",{label:"tab4"},"4")])],-1),i(`
xml
    <r-tabs active="c">
+      <r-tab label="tab1" ranKey="a" disabled>11111</r-tab>
+      <r-tab label="tab2" ranKey="b">22222</r-tab>
+      <r-tab label="tab3" ranKey="c">33333</r-tab>
+      <r-tab label="tab4">4</r-tab>
+    </r-tabs>

类型type

r-tabs属性,设置标签页的种类。如果不设置,默认为flat

  1. flat
111112222233333
xml
<r-tabs type="flat">
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>
  1. line
111112222233333
xml
<r-tabs type="line">
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

对齐方式align

设置标签的对齐方式,默认align="start"

  1. start
111112222233333
xml
 <r-tabs type="line" align="start">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
  1. center
111112222233333
xml
 <r-tabs type="line" align="center">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
  1. end
111112222233333
xml
 <r-tabs type="line" align="end">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
`,20)]))}const b=t(k,[["render",n]]);export{y as __pageData,b as default}; diff --git a/assets/cn_src_ranui_tabs_index.md.jexz00Wi.js b/assets/cn_src_ranui_tabs_index.md.jexz00Wi.js new file mode 100644 index 0000000000..250309905b --- /dev/null +++ b/assets/cn_src_ranui_tabs_index.md.jexz00Wi.js @@ -0,0 +1,21 @@ +import{_ as t,o as h,c as l,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const b=JSON.parse('{"title":"Tab","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/tabs/index.md","filePath":"cn/src/ranui/tabs/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranui/tabs/index.md"};function k(e,a,p,E,r,d){return h(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

Tab

代码展示

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2">tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

属性

名称label

每个r-tab需要指定一个名称label,用于显示标签头。

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2">tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

禁用disabled

每个r-tab可以指定disabled属性,用来禁用该标签页。

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2" disabled>tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

标识key,active

每个r-tab需要指定一个标识key,没有会默认以序列号为key

active作用在r-tabs上,可以指定切换到具体标签页,也可以指定初始值。

`,16),s("r-tabs",{active:"B"},[s("r-tab",{label:"tab1","r-key":"A"},"tab1"),s("r-tab",{label:"tab2","r-key":"B"},"tab2"),s("r-tab",{label:"tab3","r-key":"C"},"tab3")],-1),i(`
html
<r-tabs active="B">
+  <r-tab label="tab1" r-key="A">tab1</r-tab>
+  <r-tab label="tab2" r-key="B">tab2</r-tab>
+  <r-tab label="tab3" r-key="C">tab3</r-tab>
+</r-tabs>

图标icon

每个r-tab可以指定icon,配合label实现图标加文字的效果。

tab1tab2tab3
html
<r-tabs>
+  <r-tab label="home" icon="home">tab1</r-tab>
+  <r-tab label="message" icon="message">tab2</r-tab>
+  <r-tab label="user" icon="user">tab3</r-tab>
+</r-tabs>

也可以单独指定icon,不使用label。但这种情况必须要设置iconsize,否则无法判断icon的大小

`,6),s("r-tabs",null,[s("r-tab",{icon:"home",iconSize:"22"},"tab1"),s("r-tab",{icon:"message",iconSize:"22"},"tab2"),s("r-tab",{icon:"user",iconSize:"22"},"tab3")],-1),i('
html
<r-tabs>\n  <r-tab icon="home" iconSize="22">tab1</r-tab>\n  <r-tab icon="message" iconSize="22">tab2</r-tab>\n  <r-tab icon="user" iconSize="22">tab3</r-tab>\n</r-tabs>

风格type

风格有 text,clean,

对齐align

事件event

onchange

切换完成时触发。

',7)]))}const o=t(n,[["render",k]]);export{b as __pageData,o as default}; diff --git a/assets/cn_src_ranui_tabs_index.md.jexz00Wi.lean.js b/assets/cn_src_ranui_tabs_index.md.jexz00Wi.lean.js new file mode 100644 index 0000000000..250309905b --- /dev/null +++ b/assets/cn_src_ranui_tabs_index.md.jexz00Wi.lean.js @@ -0,0 +1,21 @@ +import{_ as t,o as h,c as l,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const b=JSON.parse('{"title":"Tab","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranui/tabs/index.md","filePath":"cn/src/ranui/tabs/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranui/tabs/index.md"};function k(e,a,p,E,r,d){return h(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

Tab

代码展示

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2">tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

属性

名称label

每个r-tab需要指定一个名称label,用于显示标签头。

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2">tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

禁用disabled

每个r-tab可以指定disabled属性,用来禁用该标签页。

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2" disabled>tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

标识key,active

每个r-tab需要指定一个标识key,没有会默认以序列号为key

active作用在r-tabs上,可以指定切换到具体标签页,也可以指定初始值。

`,16),s("r-tabs",{active:"B"},[s("r-tab",{label:"tab1","r-key":"A"},"tab1"),s("r-tab",{label:"tab2","r-key":"B"},"tab2"),s("r-tab",{label:"tab3","r-key":"C"},"tab3")],-1),i(`
html
<r-tabs active="B">
+  <r-tab label="tab1" r-key="A">tab1</r-tab>
+  <r-tab label="tab2" r-key="B">tab2</r-tab>
+  <r-tab label="tab3" r-key="C">tab3</r-tab>
+</r-tabs>

图标icon

每个r-tab可以指定icon,配合label实现图标加文字的效果。

tab1tab2tab3
html
<r-tabs>
+  <r-tab label="home" icon="home">tab1</r-tab>
+  <r-tab label="message" icon="message">tab2</r-tab>
+  <r-tab label="user" icon="user">tab3</r-tab>
+</r-tabs>

也可以单独指定icon,不使用label。但这种情况必须要设置iconsize,否则无法判断icon的大小

`,6),s("r-tabs",null,[s("r-tab",{icon:"home",iconSize:"22"},"tab1"),s("r-tab",{icon:"message",iconSize:"22"},"tab2"),s("r-tab",{icon:"user",iconSize:"22"},"tab3")],-1),i('
html
<r-tabs>\n  <r-tab icon="home" iconSize="22">tab1</r-tab>\n  <r-tab icon="message" iconSize="22">tab2</r-tab>\n  <r-tab icon="user" iconSize="22">tab3</r-tab>\n</r-tabs>

风格type

风格有 text,clean,

对齐align

事件event

onchange

切换完成时触发。

',7)]))}const o=t(n,[["render",k]]);export{b as __pageData,o as default}; diff --git a/assets/cn_src_ranuts_binaryTree_index.md.1nqizYW3.js b/assets/cn_src_ranuts_binaryTree_index.md.1nqizYW3.js new file mode 100644 index 0000000000..78f2d7d59e --- /dev/null +++ b/assets/cn_src_ranuts_binaryTree_index.md.1nqizYW3.js @@ -0,0 +1 @@ +import{_ as e}from"./chunks/balanceTree.CCEoBiag.js";import{_ as r,o as i,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"二叉树的定义","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/binaryTree/index.md","filePath":"cn/src/ranuts/binaryTree/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/ranuts/binaryTree/index.md"};function o(n,a,d,s,c,u){return i(),t("div",{"data-pagefind-body":!0},a[0]||(a[0]=[h('

二叉树的定义

在计算机科学中,二叉树(Binary tree)是每个节点最多只有两个分支(即不存在分支度大于 2 的节点)的树结构。通常分支被称作“左子树”或“右子树”。二叉树的分支具有左右次序,不能随意颠倒[1]。。

二叉树的性质

  • 在二叉树的第 i 层上最多有 2^(i-1)个结点(i>=1)
  • 深度为 h 的二叉树,最多有 2^h-1 个结点,最少有 h 个结点(h>=1)
  • 包含 n 个结点的二叉树的高度至少为(log2n)+1
  • 非空的二叉树,分支度为 0 的总数为 n0,分支度为 2 的总数为 n2,则 n0=n2+1
  • 二叉树的总结点数 n = n1 + n2 + n0
  • 总连线数等于总节点数减一(B = n - 1)
  • 总连线数等于分支度为 2 的节点的两倍加上分支度为 1 的节点(B = n2 _ 2 + n1 _ 1)

二叉树的类型

满二叉树

一棵深度为 k 且有 2k-1 个节点的二叉树称为满二叉树。 除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树[2]

完全二叉树

一棵深度为 k 的有 n 个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为 i(1≤i≤n)的结点与满二叉树中编号为 i 的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。

二叉搜索树

二叉搜索树(BST)又称二叉查找树或二叉排序树。它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

平衡二叉树

平衡二叉树(AVL)一定是二叉搜索树,且左子树和右子树的高度差的绝对值不超过 1。 平衡二叉树

B 树

B 树属于多叉树又名平衡多路查找树(查找路径不只两个)

B+树

B+树是 B 树的变体,也是一种多路搜索树。

B*树

B* 树是 B+树的变体,在 B+树的非根和非叶子结点再增加指向兄弟的指针;B* 树定义了非叶子结点关键字个数至少为(2/3)M,即块的最低使用率为 2/3(代替 B+树的 1/2)。B 树分配新结点的概率比 B+树要低,空间使用率更高;

红黑树

红黑树是一种平衡二叉查找树的变体,它的左右子树高差有可能大于 1,所以红黑树不是严格意义上的平衡二叉树(AVL),但对它进行平衡的代价较低, 其平均统计性能要强于 AVL 。

遍历

前序遍历

后序遍历

中序遍历

层序遍历

常见算法题

镜像二叉树

重建二叉树

二叉树深度

二叉树节点总数

判断二叉树子结构

输入两棵二叉树 A 和 B,判断 B 是不是 A 的子结构。(ps:约定空树不是任意一个树的子结构)

参考文档

  1. 维基百科二叉树
  2. 百度百科满二叉树
',36)]))}const m=r(l,[["render",o]]);export{p as __pageData,m as default}; diff --git a/assets/cn_src_ranuts_binaryTree_index.md.1nqizYW3.lean.js b/assets/cn_src_ranuts_binaryTree_index.md.1nqizYW3.lean.js new file mode 100644 index 0000000000..78f2d7d59e --- /dev/null +++ b/assets/cn_src_ranuts_binaryTree_index.md.1nqizYW3.lean.js @@ -0,0 +1 @@ +import{_ as e}from"./chunks/balanceTree.CCEoBiag.js";import{_ as r,o as i,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"二叉树的定义","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/binaryTree/index.md","filePath":"cn/src/ranuts/binaryTree/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/ranuts/binaryTree/index.md"};function o(n,a,d,s,c,u){return i(),t("div",{"data-pagefind-body":!0},a[0]||(a[0]=[h('

二叉树的定义

在计算机科学中,二叉树(Binary tree)是每个节点最多只有两个分支(即不存在分支度大于 2 的节点)的树结构。通常分支被称作“左子树”或“右子树”。二叉树的分支具有左右次序,不能随意颠倒[1]。。

二叉树的性质

  • 在二叉树的第 i 层上最多有 2^(i-1)个结点(i>=1)
  • 深度为 h 的二叉树,最多有 2^h-1 个结点,最少有 h 个结点(h>=1)
  • 包含 n 个结点的二叉树的高度至少为(log2n)+1
  • 非空的二叉树,分支度为 0 的总数为 n0,分支度为 2 的总数为 n2,则 n0=n2+1
  • 二叉树的总结点数 n = n1 + n2 + n0
  • 总连线数等于总节点数减一(B = n - 1)
  • 总连线数等于分支度为 2 的节点的两倍加上分支度为 1 的节点(B = n2 _ 2 + n1 _ 1)

二叉树的类型

满二叉树

一棵深度为 k 且有 2k-1 个节点的二叉树称为满二叉树。 除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树[2]

完全二叉树

一棵深度为 k 的有 n 个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为 i(1≤i≤n)的结点与满二叉树中编号为 i 的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。

二叉搜索树

二叉搜索树(BST)又称二叉查找树或二叉排序树。它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

平衡二叉树

平衡二叉树(AVL)一定是二叉搜索树,且左子树和右子树的高度差的绝对值不超过 1。 平衡二叉树

B 树

B 树属于多叉树又名平衡多路查找树(查找路径不只两个)

B+树

B+树是 B 树的变体,也是一种多路搜索树。

B*树

B* 树是 B+树的变体,在 B+树的非根和非叶子结点再增加指向兄弟的指针;B* 树定义了非叶子结点关键字个数至少为(2/3)M,即块的最低使用率为 2/3(代替 B+树的 1/2)。B 树分配新结点的概率比 B+树要低,空间使用率更高;

红黑树

红黑树是一种平衡二叉查找树的变体,它的左右子树高差有可能大于 1,所以红黑树不是严格意义上的平衡二叉树(AVL),但对它进行平衡的代价较低, 其平均统计性能要强于 AVL 。

遍历

前序遍历

后序遍历

中序遍历

层序遍历

常见算法题

镜像二叉树

重建二叉树

二叉树深度

二叉树节点总数

判断二叉树子结构

输入两棵二叉树 A 和 B,判断 B 是不是 A 的子结构。(ps:约定空树不是任意一个树的子结构)

参考文档

  1. 维基百科二叉树
  2. 百度百科满二叉树
',36)]))}const m=r(l,[["render",o]]);export{p as __pageData,m as default}; diff --git a/assets/cn_src_ranuts_bundler_index.md.dO9RE_ls.js b/assets/cn_src_ranuts_bundler_index.md.dO9RE_ls.js new file mode 100644 index 0000000000..619e1fdfe6 --- /dev/null +++ b/assets/cn_src_ranuts_bundler_index.md.dO9RE_ls.js @@ -0,0 +1,10 @@ +import{_ as s}from"./chunks/bundle.BxrzsuA1.js";import{_ as a,o as e,c as p,a3 as t}from"./chunks/framework.C-ai2y4t.js";const h=JSON.parse('{"title":"Bundler","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/bundler/index.md","filePath":"cn/src/ranuts/bundler/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/ranuts/bundler/index.md"};function r(i,n,d,o,c,u){return e(),p("div",{"data-pagefind-body":!0},n[0]||(n[0]=[t(`

Bundler

Bundler的使用: 传入 options 参数

function build(options: Options):Promise<Build> {
+  const bundle = new Bundle({
+    entry: options.input
+  });
+  return bundle.build().then(() => {
+    return {
+      generate: () => bundle.render()
+    };
+  });
+}

架构图

',5)]))}const g=a(l,[["render",r]]);export{h as __pageData,g as default}; diff --git a/assets/cn_src_ranuts_bundler_index.md.dO9RE_ls.lean.js b/assets/cn_src_ranuts_bundler_index.md.dO9RE_ls.lean.js new file mode 100644 index 0000000000..619e1fdfe6 --- /dev/null +++ b/assets/cn_src_ranuts_bundler_index.md.dO9RE_ls.lean.js @@ -0,0 +1,10 @@ +import{_ as s}from"./chunks/bundle.BxrzsuA1.js";import{_ as a,o as e,c as p,a3 as t}from"./chunks/framework.C-ai2y4t.js";const h=JSON.parse('{"title":"Bundler","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/bundler/index.md","filePath":"cn/src/ranuts/bundler/index.md","lastUpdated":1726550590000}'),l={name:"cn/src/ranuts/bundler/index.md"};function r(i,n,d,o,c,u){return e(),p("div",{"data-pagefind-body":!0},n[0]||(n[0]=[t(`

Bundler

Bundler的使用: 传入 options 参数

function build(options: Options):Promise<Build> {
+  const bundle = new Bundle({
+    entry: options.input
+  });
+  return bundle.build().then(() => {
+    return {
+      generate: () => bundle.render()
+    };
+  });
+}

架构图

',5)]))}const g=a(l,[["render",r]]);export{h as __pageData,g as default}; diff --git a/assets/cn_src_ranuts_file_appendFile.md.CXY4tbQl.js b/assets/cn_src_ranuts_file_appendFile.md.CXY4tbQl.js new file mode 100644 index 0000000000..d794b9ee5a --- /dev/null +++ b/assets/cn_src_ranuts_file_appendFile.md.CXY4tbQl.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"AppendFile","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/file/appendFile.md","filePath":"cn/src/ranuts/file/appendFile.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranuts/file/appendFile.md"};function o(i,t,l,h,s,p){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

AppendFile

追加一些数据到文件内

API

Return

  • Promise
参数说明类型描述
success是否追加成功booleantrue 追加成功 false 追加失败
data追加失败的原因,添加成功后的文件内容any

Options

参数说明类型默认值
path文件路径,需要追加的文件stringundefined
content需要追加的内容string

Example

',9)]))}const b=e(n,[["render",o]]);export{u as __pageData,b as default}; diff --git a/assets/cn_src_ranuts_file_appendFile.md.CXY4tbQl.lean.js b/assets/cn_src_ranuts_file_appendFile.md.CXY4tbQl.lean.js new file mode 100644 index 0000000000..d794b9ee5a --- /dev/null +++ b/assets/cn_src_ranuts_file_appendFile.md.CXY4tbQl.lean.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"AppendFile","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/file/appendFile.md","filePath":"cn/src/ranuts/file/appendFile.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranuts/file/appendFile.md"};function o(i,t,l,h,s,p){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

AppendFile

追加一些数据到文件内

API

Return

  • Promise
参数说明类型描述
success是否追加成功booleantrue 追加成功 false 追加失败
data追加失败的原因,添加成功后的文件内容any

Options

参数说明类型默认值
path文件路径,需要追加的文件stringundefined
content需要追加的内容string

Example

',9)]))}const b=e(n,[["render",o]]);export{u as __pageData,b as default}; diff --git a/assets/cn_src_ranuts_file_fileInfo.md.BovJRTqz.js b/assets/cn_src_ranuts_file_fileInfo.md.BovJRTqz.js new file mode 100644 index 0000000000..51e33231a5 --- /dev/null +++ b/assets/cn_src_ranuts_file_fileInfo.md.BovJRTqz.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as r,a3 as d}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"QueryFileInfo","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/file/fileInfo.md","filePath":"cn/src/ranuts/file/fileInfo.md","lastUpdated":1726550590000}'),o={name:"cn/src/ranuts/file/fileInfo.md"};function i(n,t,l,h,s,c){return a(),r("div",{"data-pagefind-body":!0},t[0]||(t[0]=[d('

QueryFileInfo

查询一个文件的详细信息,一般用于区分文件还是目录,可以通过返回的 data 来判断(data.isDirectory())

API

Return

  • Promise
参数说明类型描述
success是否检查成功booleantrue 成功 false 失败
data文件的信息,或者错误的原因Stats

Options

参数说明类型默认值
path文件路径,需要检查的文件路径stringundefined

Example

',9)]))}const p=e(o,[["render",i]]);export{u as __pageData,p as default}; diff --git a/assets/cn_src_ranuts_file_fileInfo.md.BovJRTqz.lean.js b/assets/cn_src_ranuts_file_fileInfo.md.BovJRTqz.lean.js new file mode 100644 index 0000000000..51e33231a5 --- /dev/null +++ b/assets/cn_src_ranuts_file_fileInfo.md.BovJRTqz.lean.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as r,a3 as d}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"QueryFileInfo","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/file/fileInfo.md","filePath":"cn/src/ranuts/file/fileInfo.md","lastUpdated":1726550590000}'),o={name:"cn/src/ranuts/file/fileInfo.md"};function i(n,t,l,h,s,c){return a(),r("div",{"data-pagefind-body":!0},t[0]||(t[0]=[d('

QueryFileInfo

查询一个文件的详细信息,一般用于区分文件还是目录,可以通过返回的 data 来判断(data.isDirectory())

API

Return

  • Promise
参数说明类型描述
success是否检查成功booleantrue 成功 false 失败
data文件的信息,或者错误的原因Stats

Options

参数说明类型默认值
path文件路径,需要检查的文件路径stringundefined

Example

',9)]))}const p=e(o,[["render",i]]);export{u as __pageData,p as default}; diff --git a/assets/cn_src_ranuts_file_readDir.md.C8qesA-s.js b/assets/cn_src_ranuts_file_readDir.md.C8qesA-s.js new file mode 100644 index 0000000000..98ffb5342f --- /dev/null +++ b/assets/cn_src_ranuts_file_readDir.md.C8qesA-s.js @@ -0,0 +1 @@ +import{_ as e,o as r,c as l,a3 as d,j as t,a as n}from"./chunks/framework.C-ai2y4t.js";const m=JSON.parse('{"title":"ReadDir","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/file/readDir.md","filePath":"cn/src/ranuts/file/readDir.md","lastUpdated":1726550590000}'),i={name:"cn/src/ranuts/file/readDir.md"};function o(s,a,h,u,c,p){return r(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[d('

ReadDir

读一个目录下的所有文件

API

Return

  • Promise
参数说明类型描述
result目录下所有文件的数组array传入函数的参数

Options

',7),t("table",{tabindex:"0"},[t("thead",null,[t("tr",null,[t("th",null,"参数"),t("th",null,"说明"),t("th",null,"类型"),t("th",null,"默认值")])]),t("tbody",null,[t("tr",null,[t("td",null,"options"),t("td",{dirPath:""}),t("td",null,[t("code",null,"object")]),t("td",null,"传入函数的参数")]),t("tr",null,[t("td",null,"dirPath"),t("td",null,"文件的路径"),t("td",null,[t("code",null,"Stats")]),t("td")])])],-1),t("h2",{id:"example",tabindex:"-1"},[n("Example "),t("a",{class:"header-anchor",href:"#example","aria-label":'Permalink to "Example"'},"​")],-1)]))}const f=e(i,[["render",o]]);export{m as __pageData,f as default}; diff --git a/assets/cn_src_ranuts_file_readDir.md.C8qesA-s.lean.js b/assets/cn_src_ranuts_file_readDir.md.C8qesA-s.lean.js new file mode 100644 index 0000000000..98ffb5342f --- /dev/null +++ b/assets/cn_src_ranuts_file_readDir.md.C8qesA-s.lean.js @@ -0,0 +1 @@ +import{_ as e,o as r,c as l,a3 as d,j as t,a as n}from"./chunks/framework.C-ai2y4t.js";const m=JSON.parse('{"title":"ReadDir","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/file/readDir.md","filePath":"cn/src/ranuts/file/readDir.md","lastUpdated":1726550590000}'),i={name:"cn/src/ranuts/file/readDir.md"};function o(s,a,h,u,c,p){return r(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[d('

ReadDir

读一个目录下的所有文件

API

Return

  • Promise
参数说明类型描述
result目录下所有文件的数组array传入函数的参数

Options

',7),t("table",{tabindex:"0"},[t("thead",null,[t("tr",null,[t("th",null,"参数"),t("th",null,"说明"),t("th",null,"类型"),t("th",null,"默认值")])]),t("tbody",null,[t("tr",null,[t("td",null,"options"),t("td",{dirPath:""}),t("td",null,[t("code",null,"object")]),t("td",null,"传入函数的参数")]),t("tr",null,[t("td",null,"dirPath"),t("td",null,"文件的路径"),t("td",null,[t("code",null,"Stats")]),t("td")])])],-1),t("h2",{id:"example",tabindex:"-1"},[n("Example "),t("a",{class:"header-anchor",href:"#example","aria-label":'Permalink to "Example"'},"​")],-1)]))}const f=e(i,[["render",o]]);export{m as __pageData,f as default}; diff --git a/assets/cn_src_ranuts_file_readFile.md.-SzOLham.js b/assets/cn_src_ranuts_file_readFile.md.-SzOLham.js new file mode 100644 index 0000000000..80bbea06aa --- /dev/null +++ b/assets/cn_src_ranuts_file_readFile.md.-SzOLham.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"ReadFile","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/file/readFile.md","filePath":"cn/src/ranuts/file/readFile.md","lastUpdated":1726550590000}'),o={name:"cn/src/ranuts/file/readFile.md"};function i(l,t,n,h,s,c){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

ReadFile

观察一个文件是否改变

API

Return

  • Promise
参数说明类型描述
data文件是否被改变booleantrue 文件改变 false 文件没变

Options

参数说明类型默认值
path文件路径,需要监听的文件stringundefined
interval监听文件改变的时间,单位毫秒。number20

Example

',9)]))}const b=e(o,[["render",i]]);export{p as __pageData,b as default}; diff --git a/assets/cn_src_ranuts_file_readFile.md.-SzOLham.lean.js b/assets/cn_src_ranuts_file_readFile.md.-SzOLham.lean.js new file mode 100644 index 0000000000..80bbea06aa --- /dev/null +++ b/assets/cn_src_ranuts_file_readFile.md.-SzOLham.lean.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"ReadFile","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/file/readFile.md","filePath":"cn/src/ranuts/file/readFile.md","lastUpdated":1726550590000}'),o={name:"cn/src/ranuts/file/readFile.md"};function i(l,t,n,h,s,c){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

ReadFile

观察一个文件是否改变

API

Return

  • Promise
参数说明类型描述
data文件是否被改变booleantrue 文件改变 false 文件没变

Options

参数说明类型默认值
path文件路径,需要监听的文件stringundefined
interval监听文件改变的时间,单位毫秒。number20

Example

',9)]))}const b=e(o,[["render",i]]);export{p as __pageData,b as default}; diff --git a/assets/cn_src_ranuts_file_watchFile.md.C2RD93Hf.js b/assets/cn_src_ranuts_file_watchFile.md.C2RD93Hf.js new file mode 100644 index 0000000000..b5965179ad --- /dev/null +++ b/assets/cn_src_ranuts_file_watchFile.md.C2RD93Hf.js @@ -0,0 +1 @@ +import{_ as a,o as e,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"WatchFile","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/file/watchFile.md","filePath":"cn/src/ranuts/file/watchFile.md","lastUpdated":1726550590000}'),o={name:"cn/src/ranuts/file/watchFile.md"};function i(h,t,n,l,c,s){return e(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

WatchFile

观察一个文件是否改变

API

Return

  • Promise
参数说明类型描述
status文件是否被改变booleantrue 文件改变 false 文件没变

Options

参数说明类型默认值
path文件路径,需要监听的文件stringundefined
interval监听文件改变的时间,单位毫秒。number20
',8)]))}const b=a(o,[["render",i]]);export{p as __pageData,b as default}; diff --git a/assets/cn_src_ranuts_file_watchFile.md.C2RD93Hf.lean.js b/assets/cn_src_ranuts_file_watchFile.md.C2RD93Hf.lean.js new file mode 100644 index 0000000000..b5965179ad --- /dev/null +++ b/assets/cn_src_ranuts_file_watchFile.md.C2RD93Hf.lean.js @@ -0,0 +1 @@ +import{_ as a,o as e,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"WatchFile","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/file/watchFile.md","filePath":"cn/src/ranuts/file/watchFile.md","lastUpdated":1726550590000}'),o={name:"cn/src/ranuts/file/watchFile.md"};function i(h,t,n,l,c,s){return e(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

WatchFile

观察一个文件是否改变

API

Return

  • Promise
参数说明类型描述
status文件是否被改变booleantrue 文件改变 false 文件没变

Options

参数说明类型默认值
path文件路径,需要监听的文件stringundefined
interval监听文件改变的时间,单位毫秒。number20
',8)]))}const b=a(o,[["render",i]]);export{p as __pageData,b as default}; diff --git a/assets/cn_src_ranuts_file_writeFile.md.CbYE9IAV.js b/assets/cn_src_ranuts_file_writeFile.md.CbYE9IAV.js new file mode 100644 index 0000000000..c3b7ec8b9c --- /dev/null +++ b/assets/cn_src_ranuts_file_writeFile.md.CbYE9IAV.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"WriteFile","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/file/writeFile.md","filePath":"cn/src/ranuts/file/writeFile.md","lastUpdated":1726550590000}'),i={name:"cn/src/ranuts/file/writeFile.md"};function o(n,t,l,h,s,c){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

WriteFile

将内容写入文件

API

Return

  • Promise
参数说明类型描述
success是否写入成功booleantrue 成功 false 失败
data写入失败的原因,添加成功后的文件内容和文件路径any

Options

参数说明类型默认值
path文件路径,需要追加的文件stringundefined
content需要追加的内容string
',8)]))}const b=e(i,[["render",o]]);export{p as __pageData,b as default}; diff --git a/assets/cn_src_ranuts_file_writeFile.md.CbYE9IAV.lean.js b/assets/cn_src_ranuts_file_writeFile.md.CbYE9IAV.lean.js new file mode 100644 index 0000000000..c3b7ec8b9c --- /dev/null +++ b/assets/cn_src_ranuts_file_writeFile.md.CbYE9IAV.lean.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"WriteFile","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/file/writeFile.md","filePath":"cn/src/ranuts/file/writeFile.md","lastUpdated":1726550590000}'),i={name:"cn/src/ranuts/file/writeFile.md"};function o(n,t,l,h,s,c){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

WriteFile

将内容写入文件

API

Return

  • Promise
参数说明类型描述
success是否写入成功booleantrue 成功 false 失败
data写入失败的原因,添加成功后的文件内容和文件路径any

Options

参数说明类型默认值
path文件路径,需要追加的文件stringundefined
content需要追加的内容string
',8)]))}const b=e(i,[["render",o]]);export{p as __pageData,b as default}; diff --git a/assets/cn_src_ranuts_index.md.DE29xbkU.js b/assets/cn_src_ranuts_index.md.DE29xbkU.js new file mode 100644 index 0000000000..3f170a6954 --- /dev/null +++ b/assets/cn_src_ranuts_index.md.DE29xbkU.js @@ -0,0 +1 @@ +import{_ as r,o as d,c as a,a3 as i,G as o,B as l}from"./chunks/framework.C-ai2y4t.js";const b=JSON.parse('{"title":"ranuts overview","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/index.md","filePath":"cn/src/ranuts/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranuts/index.md"};function s(h,t,m,f,c,u){const e=l("TOTP");return d(),a("div",{"data-pagefind-body":!0},[t[0]||(t[0]=i('

ranuts overview

方法列表

方法说明详细内容
writeFile写入文件writeFile
readFile读取文件readFile
readDir读取目录,获取目录下所有文件的名字readDir
watchFile观察文件的内容是否发生变化watchFile
queryFileInfo查询文件信息queryFileInfo
filterObj过滤对象filterObj
EventEmitter发布订阅类EventEmitter
str2Xml字符串转成xmlstr2Xml
getMime根据文件格式后缀获取 mime typegetMime
getCookie获取指定 cookie 的值writeFile
formatJson格式化 JSONformatJson

TOTP

',4)),o(e)])}const v=r(n,[["render",s]]);export{b as __pageData,v as default}; diff --git a/assets/cn_src_ranuts_index.md.DE29xbkU.lean.js b/assets/cn_src_ranuts_index.md.DE29xbkU.lean.js new file mode 100644 index 0000000000..3f170a6954 --- /dev/null +++ b/assets/cn_src_ranuts_index.md.DE29xbkU.lean.js @@ -0,0 +1 @@ +import{_ as r,o as d,c as a,a3 as i,G as o,B as l}from"./chunks/framework.C-ai2y4t.js";const b=JSON.parse('{"title":"ranuts overview","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/index.md","filePath":"cn/src/ranuts/index.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranuts/index.md"};function s(h,t,m,f,c,u){const e=l("TOTP");return d(),a("div",{"data-pagefind-body":!0},[t[0]||(t[0]=i('

ranuts overview

方法列表

方法说明详细内容
writeFile写入文件writeFile
readFile读取文件readFile
readDir读取目录,获取目录下所有文件的名字readDir
watchFile观察文件的内容是否发生变化watchFile
queryFileInfo查询文件信息queryFileInfo
filterObj过滤对象filterObj
EventEmitter发布订阅类EventEmitter
str2Xml字符串转成xmlstr2Xml
getMime根据文件格式后缀获取 mime typegetMime
getCookie获取指定 cookie 的值writeFile
formatJson格式化 JSONformatJson

TOTP

',4)),o(e)])}const v=r(n,[["render",s]]);export{b as __pageData,v as default}; diff --git a/assets/cn_src_ranuts_mimeType_mimeType.md.B8my7NSy.js b/assets/cn_src_ranuts_mimeType_mimeType.md.B8my7NSy.js new file mode 100644 index 0000000000..0a53f31313 --- /dev/null +++ b/assets/cn_src_ranuts_mimeType_mimeType.md.B8my7NSy.js @@ -0,0 +1,8 @@ +import{_ as i,o as a,c as t,a3 as e}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"getMime","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/mimeType/mimeType.md","filePath":"cn/src/ranuts/mimeType/mimeType.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranuts/mimeType/mimeType.md"};function h(l,s,p,r,d,k){return a(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[e(`

getMime

传入文件格式后缀,返回mime type

API

Return

参数说明类型
string返回mime typestring

Options

参数说明类型默认值
ext文件后缀格式string

Example

js
import { getMime } from 'ranuts';
+
+const result = getMime('.pptx');
+console.log(result);
+// 'application/vnd.openxmlformats-officedocument.presentationml.presentation
+const res = getMime('.txt');
+console.log(result);
+// text/plain
`,9)]))}const m=i(n,[["render",h]]);export{c as __pageData,m as default}; diff --git a/assets/cn_src_ranuts_mimeType_mimeType.md.B8my7NSy.lean.js b/assets/cn_src_ranuts_mimeType_mimeType.md.B8my7NSy.lean.js new file mode 100644 index 0000000000..0a53f31313 --- /dev/null +++ b/assets/cn_src_ranuts_mimeType_mimeType.md.B8my7NSy.lean.js @@ -0,0 +1,8 @@ +import{_ as i,o as a,c as t,a3 as e}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"getMime","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/mimeType/mimeType.md","filePath":"cn/src/ranuts/mimeType/mimeType.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranuts/mimeType/mimeType.md"};function h(l,s,p,r,d,k){return a(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[e(`

getMime

传入文件格式后缀,返回mime type

API

Return

参数说明类型
string返回mime typestring

Options

参数说明类型默认值
ext文件后缀格式string

Example

js
import { getMime } from 'ranuts';
+
+const result = getMime('.pptx');
+console.log(result);
+// 'application/vnd.openxmlformats-officedocument.presentationml.presentation
+const res = getMime('.txt');
+console.log(result);
+// text/plain
`,9)]))}const m=i(n,[["render",h]]);export{c as __pageData,m as default}; diff --git a/assets/cn_src_ranuts_mode_subscribe.md.DStPx3te.js b/assets/cn_src_ranuts_mode_subscribe.md.DStPx3te.js new file mode 100644 index 0000000000..41e7b63578 --- /dev/null +++ b/assets/cn_src_ranuts_mode_subscribe.md.DStPx3te.js @@ -0,0 +1,32 @@ +import{_ as i,o as a,c as n,a3 as t}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"EventEmitter","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/mode/subscribe.md","filePath":"cn/src/ranuts/mode/subscribe.md","lastUpdated":1726550590000}'),h={name:"cn/src/ranuts/mode/subscribe.md"};function l(k,s,p,e,E,r){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t(`

EventEmitter

发布订阅的类

Class

Methods

方法参数说明默认值
on订阅事件订阅事件,传入参数事件名,回调函数
once订阅一次事件,传入参数事件名,回调函数订阅一次事件,触发一次后不再会触发
off取消订阅事件,传入参数事件名,回调函数取消订阅事件
emit触发事件,需要事件名触发事件

Example

js
import { Subscribe } from 'ranuts';
+
+const subscribe = new Subscribe();
+
+// 订阅事件1
+subscribe.on('event', () => {
+  console.log(1);
+});
+// 订阅事件2
+subscribe.on('event', () => {
+  console.log(2);
+});
+// 订阅事件3
+const eventThree = () => {
+  console.log(3);
+};
+subscribe.on('event', eventThree);
+// 订阅事件4,需要传递参数
+subscribe.on('event', (num) => {
+  console.log(num);
+});
+// 触发事件,同时传参数
+subscribe.emit('event', 4);
+// console.log(1) console.log(2) console.log(3) console.log(4)
+
+// 取消事件三
+subscribe.off('event', eventThree);
+
+// 订阅一次,触发一次自动取消
+subscribe.once('other', () => {
+  console.log(5);
+});
`,7)]))}const y=i(h,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/cn_src_ranuts_mode_subscribe.md.DStPx3te.lean.js b/assets/cn_src_ranuts_mode_subscribe.md.DStPx3te.lean.js new file mode 100644 index 0000000000..41e7b63578 --- /dev/null +++ b/assets/cn_src_ranuts_mode_subscribe.md.DStPx3te.lean.js @@ -0,0 +1,32 @@ +import{_ as i,o as a,c as n,a3 as t}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"EventEmitter","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/mode/subscribe.md","filePath":"cn/src/ranuts/mode/subscribe.md","lastUpdated":1726550590000}'),h={name:"cn/src/ranuts/mode/subscribe.md"};function l(k,s,p,e,E,r){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t(`

EventEmitter

发布订阅的类

Class

Methods

方法参数说明默认值
on订阅事件订阅事件,传入参数事件名,回调函数
once订阅一次事件,传入参数事件名,回调函数订阅一次事件,触发一次后不再会触发
off取消订阅事件,传入参数事件名,回调函数取消订阅事件
emit触发事件,需要事件名触发事件

Example

js
import { Subscribe } from 'ranuts';
+
+const subscribe = new Subscribe();
+
+// 订阅事件1
+subscribe.on('event', () => {
+  console.log(1);
+});
+// 订阅事件2
+subscribe.on('event', () => {
+  console.log(2);
+});
+// 订阅事件3
+const eventThree = () => {
+  console.log(3);
+};
+subscribe.on('event', eventThree);
+// 订阅事件4,需要传递参数
+subscribe.on('event', (num) => {
+  console.log(num);
+});
+// 触发事件,同时传参数
+subscribe.emit('event', 4);
+// console.log(1) console.log(2) console.log(3) console.log(4)
+
+// 取消事件三
+subscribe.off('event', eventThree);
+
+// 订阅一次,触发一次自动取消
+subscribe.once('other', () => {
+  console.log(5);
+});
`,7)]))}const y=i(h,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/cn_src_ranuts_utils_convertImageToBase64.md.BpukE7kU.js b/assets/cn_src_ranuts_utils_convertImageToBase64.md.BpukE7kU.js new file mode 100644 index 0000000000..9c5d8c74e1 --- /dev/null +++ b/assets/cn_src_ranuts_utils_convertImageToBase64.md.BpukE7kU.js @@ -0,0 +1,5 @@ +import{_ as t,o as s,c as e,a3 as i}from"./chunks/framework.C-ai2y4t.js";const k=JSON.parse('{"title":"convertImageToBase64","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/convertImageToBase64.md","filePath":"cn/src/ranuts/utils/convertImageToBase64.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranuts/utils/convertImageToBase64.md"};function d(r,a,o,h,l,p){return s(),e("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

convertImageToBase64

图片转base64

API

Return

参数说明类型
success是否转换成功boolean
data转换成功后的值string,ArrayBuffer , null
message转换成功或失败的原因string

Options

参数说明类型默认值
file传入的文件File

Example

js
import { convertImageToBase64 } from 'ranuts';
+
+convertImageToBase64(file).then((res) => {
+  console.log(result);
+});
`,9)]))}const g=t(n,[["render",d]]);export{k as __pageData,g as default}; diff --git a/assets/cn_src_ranuts_utils_convertImageToBase64.md.BpukE7kU.lean.js b/assets/cn_src_ranuts_utils_convertImageToBase64.md.BpukE7kU.lean.js new file mode 100644 index 0000000000..9c5d8c74e1 --- /dev/null +++ b/assets/cn_src_ranuts_utils_convertImageToBase64.md.BpukE7kU.lean.js @@ -0,0 +1,5 @@ +import{_ as t,o as s,c as e,a3 as i}from"./chunks/framework.C-ai2y4t.js";const k=JSON.parse('{"title":"convertImageToBase64","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/convertImageToBase64.md","filePath":"cn/src/ranuts/utils/convertImageToBase64.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranuts/utils/convertImageToBase64.md"};function d(r,a,o,h,l,p){return s(),e("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

convertImageToBase64

图片转base64

API

Return

参数说明类型
success是否转换成功boolean
data转换成功后的值string,ArrayBuffer , null
message转换成功或失败的原因string

Options

参数说明类型默认值
file传入的文件File

Example

js
import { convertImageToBase64 } from 'ranuts';
+
+convertImageToBase64(file).then((res) => {
+  console.log(result);
+});
`,9)]))}const g=t(n,[["render",d]]);export{k as __pageData,g as default}; diff --git a/assets/cn_src_ranuts_utils_filterObj.md.Be8VuZ1x.js b/assets/cn_src_ranuts_utils_filterObj.md.Be8VuZ1x.js new file mode 100644 index 0000000000..bfe3b75e16 --- /dev/null +++ b/assets/cn_src_ranuts_utils_filterObj.md.Be8VuZ1x.js @@ -0,0 +1,13 @@ +import{_ as a,o as i,c as t,a3 as n}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"filterObj","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/filterObj.md","filePath":"cn/src/ranuts/utils/filterObj.md","lastUpdated":1726550590000}'),e={name:"cn/src/ranuts/utils/filterObj.md"};function l(h,s,p,r,d,k){return i(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

filterObj

过滤对象的属性,去除对象中在 list 数组里面有的属性,返回一个新对象,一般是用于去除空字符和 null

API

Return

参数说明类型
Object返回的一个对象Object

Options

参数说明类型默认值
obj需要过滤的对象object
list需要过滤的熟悉数组array

Example

js
import { filterObj } from 'ranuts';
+
+const obj = {
+  name: 'chaxus',
+  age: 10,
+  address: 'spark',
+};
+
+const result = filterObj(obj, ['name', 'address']);
+
+console.log(result);
+
+// { age:10 }
`,9)]))}const c=a(e,[["render",l]]);export{E as __pageData,c as default}; diff --git a/assets/cn_src_ranuts_utils_filterObj.md.Be8VuZ1x.lean.js b/assets/cn_src_ranuts_utils_filterObj.md.Be8VuZ1x.lean.js new file mode 100644 index 0000000000..bfe3b75e16 --- /dev/null +++ b/assets/cn_src_ranuts_utils_filterObj.md.Be8VuZ1x.lean.js @@ -0,0 +1,13 @@ +import{_ as a,o as i,c as t,a3 as n}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"filterObj","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/filterObj.md","filePath":"cn/src/ranuts/utils/filterObj.md","lastUpdated":1726550590000}'),e={name:"cn/src/ranuts/utils/filterObj.md"};function l(h,s,p,r,d,k){return i(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

filterObj

过滤对象的属性,去除对象中在 list 数组里面有的属性,返回一个新对象,一般是用于去除空字符和 null

API

Return

参数说明类型
Object返回的一个对象Object

Options

参数说明类型默认值
obj需要过滤的对象object
list需要过滤的熟悉数组array

Example

js
import { filterObj } from 'ranuts';
+
+const obj = {
+  name: 'chaxus',
+  age: 10,
+  address: 'spark',
+};
+
+const result = filterObj(obj, ['name', 'address']);
+
+console.log(result);
+
+// { age:10 }
`,9)]))}const c=a(e,[["render",l]]);export{E as __pageData,c as default}; diff --git a/assets/cn_src_ranuts_utils_formatJson.md.DWRR6vH4.js b/assets/cn_src_ranuts_utils_formatJson.md.DWRR6vH4.js new file mode 100644 index 0000000000..db145bc5d8 --- /dev/null +++ b/assets/cn_src_ranuts_utils_formatJson.md.DWRR6vH4.js @@ -0,0 +1,10 @@ +import{_ as a,o as t,c as i,a3 as n}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"formatJson","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/formatJson.md","filePath":"cn/src/ranuts/utils/formatJson.md","lastUpdated":1726550590000}'),e={name:"cn/src/ranuts/utils/formatJson.md"};function h(l,s,r,d,p,o){return t(),i("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

formatJson

传入一个 JSON 或者 JSON 的字符串,添加空格和换行进行返回一个格式化的 JSON 字符串

API

Return

参数说明类型
string返回的一个对象Object

Options

参数说明类型默认值
json需要格式化的 JSON 对象object,string
callback错误回调,可选function

Example

js
import { formatJson } from 'ranuts';
+
+const json = {
+  name: 'chaxus',
+  age: 3,
+};
+
+const result = formatJson(json);
+
+console.log(result);
`,9)]))}const E=a(e,[["render",h]]);export{c as __pageData,E as default}; diff --git a/assets/cn_src_ranuts_utils_formatJson.md.DWRR6vH4.lean.js b/assets/cn_src_ranuts_utils_formatJson.md.DWRR6vH4.lean.js new file mode 100644 index 0000000000..db145bc5d8 --- /dev/null +++ b/assets/cn_src_ranuts_utils_formatJson.md.DWRR6vH4.lean.js @@ -0,0 +1,10 @@ +import{_ as a,o as t,c as i,a3 as n}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"formatJson","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/formatJson.md","filePath":"cn/src/ranuts/utils/formatJson.md","lastUpdated":1726550590000}'),e={name:"cn/src/ranuts/utils/formatJson.md"};function h(l,s,r,d,p,o){return t(),i("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

formatJson

传入一个 JSON 或者 JSON 的字符串,添加空格和换行进行返回一个格式化的 JSON 字符串

API

Return

参数说明类型
string返回的一个对象Object

Options

参数说明类型默认值
json需要格式化的 JSON 对象object,string
callback错误回调,可选function

Example

js
import { formatJson } from 'ranuts';
+
+const json = {
+  name: 'chaxus',
+  age: 3,
+};
+
+const result = formatJson(json);
+
+console.log(result);
`,9)]))}const E=a(e,[["render",h]]);export{c as __pageData,E as default}; diff --git a/assets/cn_src_ranuts_utils_getCookie.md.BFqNwYBM.js b/assets/cn_src_ranuts_utils_getCookie.md.BFqNwYBM.js new file mode 100644 index 0000000000..8ecd3df4c5 --- /dev/null +++ b/assets/cn_src_ranuts_utils_getCookie.md.BFqNwYBM.js @@ -0,0 +1,7 @@ +import{_ as t,o as s,c as i,a3 as e}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"getCookie","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/getCookie.md","filePath":"cn/src/ranuts/utils/getCookie.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranuts/utils/getCookie.md"};function h(o,a,l,r,d,p){return s(),i("div",{"data-pagefind-body":!0},a[0]||(a[0]=[e(`

getCookie

传入字符串,获取指定名字的 cookie 的值

API

Return

参数说明类型
sting返回的一个指定名称的 cookie 的值string

Options

参数说明类型默认值
name指定获取 cookie 的名称的值object

Example

js
import { getCookie } from 'ranuts';
+
+const result = getCookie('name');
+
+console.log(result);
+
+// ''
`,9)]))}const g=t(n,[["render",h]]);export{c as __pageData,g as default}; diff --git a/assets/cn_src_ranuts_utils_getCookie.md.BFqNwYBM.lean.js b/assets/cn_src_ranuts_utils_getCookie.md.BFqNwYBM.lean.js new file mode 100644 index 0000000000..8ecd3df4c5 --- /dev/null +++ b/assets/cn_src_ranuts_utils_getCookie.md.BFqNwYBM.lean.js @@ -0,0 +1,7 @@ +import{_ as t,o as s,c as i,a3 as e}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"getCookie","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/getCookie.md","filePath":"cn/src/ranuts/utils/getCookie.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranuts/utils/getCookie.md"};function h(o,a,l,r,d,p){return s(),i("div",{"data-pagefind-body":!0},a[0]||(a[0]=[e(`

getCookie

传入字符串,获取指定名字的 cookie 的值

API

Return

参数说明类型
sting返回的一个指定名称的 cookie 的值string

Options

参数说明类型默认值
name指定获取 cookie 的名称的值object

Example

js
import { getCookie } from 'ranuts';
+
+const result = getCookie('name');
+
+console.log(result);
+
+// ''
`,9)]))}const g=t(n,[["render",h]]);export{c as __pageData,g as default}; diff --git a/assets/cn_src_ranuts_utils_ocr.md.aSDPltJI.js b/assets/cn_src_ranuts_utils_ocr.md.aSDPltJI.js new file mode 100644 index 0000000000..e5f8d4dfd5 --- /dev/null +++ b/assets/cn_src_ranuts_utils_ocr.md.aSDPltJI.js @@ -0,0 +1,15 @@ +import{_ as d,o as a,c as r,a3 as i}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"OCR","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/ocr.md","filePath":"cn/src/ranuts/utils/ocr.md","lastUpdated":1726550590000}'),s={name:"cn/src/ranuts/utils/ocr.md"};function n(e,t,l,h,o,p){return a(),r("div",{"data-pagefind-body":!0},t[0]||(t[0]=[i(`

OCR

传入图片和对应的语言类型,返回图片中的文本。

API

Return

参数说明类型
success是否解析成功boolean
data解析成功后的对象obj
message解析成功或失败的原因string

Options

参数说明类型默认值
images图片的数组,支持urlbase64Array<string>
language指定生成文本的语言,具体参数见lang-codestring
langPath使用的时候需要能访问cdn.jsdelivr.net,会下载对应的语言包,如果无法访问,也可以将语言包放在本地,传入对应的 目录 路径string可选参数,默认走网络下载

Example

js
import { ocr } from 'ranuts';
+
+const images = ['https://chaxus.github.io/ran/ocr/eng.png'];
+const languages = 'eng';
+ocr({ images, language }).then((res) => {
+  console.log(res.data?.[0].data.text);
+});
+// Mild Splendour of the various-vested Night!
+// Mother of wildly-working visions! hail
+// I watch thy gliding, while with watery light
+// Thy weak eye glimmers through a fleecy veil;
+// And when thou lovest thy pale orb to shroud
+// Behind the gather’d blackness lost on high;
+// And when thou dartest from the wind-rent cloud
+// Thy placid lightning o’er the awaken’d sky.

Lang Code

Lang CodeLanguage
afrAfrikaans
amhAmharic
araArabic
asmAssamese
azeAzerbaijani
aze_cyrlAzerbaijani - Cyrillic
belBelarusian
benBengali
bodTibetan
bosBosnian
bulBulgarian
catCatalan; Valencian
cebCebuano
cesCzech
chi_simChinese - Simplified
chi_traChinese - Traditional
chrCherokee
cymWelsh
danDanish
deuGerman
dzoDzongkha
ellGreek, Modern (1453-)
engEnglish
enmEnglish, Middle (1100-1500)
epoEsperanto
estEstonian
eusBasque
fasPersian
finFinnish
fraFrench
frkGerman Fraktur
frmFrench, Middle (ca. 1400-1600)
gleIrish
glgGalician
grcGreek, Ancient (-1453)
gujGujarati
hatHaitian; Haitian Creole
hebHebrew
hinHindi
hrvCroatian
hunHungarian
ikuInuktitut
indIndonesian
islIcelandic
itaItalian
ita_oldItalian - Old
javJavanese
jpnJapanese
kanKannada
katGeorgian
kat_oldGeorgian - Old
kazKazakh
khmCentral Khmer
kirKirghiz; Kyrgyz
korKorean
kurKurdish
laoLao
latLatin
lavLatvian
litLithuanian
malMalayalam
marMarathi
mkdMacedonian
mltMaltese
msaMalay
myaBurmese
nepNepali
nldDutch; Flemish
norNorwegian
oriOriya
panPanjabi; Punjabi
polPolish
porPortuguese
pusPushto; Pashto
ronRomanian; Moldavian; Moldovan
rusRussian
sanSanskrit
sinSinhala; Sinhalese
slkSlovak
slvSlovenian
spaSpanish; Castilian
spa_oldSpanish; Castilian - Old
sqiAlbanian
srpSerbian
srp_latnSerbian - Latin
swaSwahili
sweSwedish
syrSyriac
tamTamil
telTelugu
tgkTajik
tglTagalog
thaThai
tirTigrinya
turTurkish
uigUighur; Uyghur
ukrUkrainian
urdUrdu
uzbUzbek
uzb_cyrlUzbek - Cyrillic
vieVietnamese
yidYiddish
`,11)]))}const g=d(s,[["render",n]]);export{c as __pageData,g as default}; diff --git a/assets/cn_src_ranuts_utils_ocr.md.aSDPltJI.lean.js b/assets/cn_src_ranuts_utils_ocr.md.aSDPltJI.lean.js new file mode 100644 index 0000000000..e5f8d4dfd5 --- /dev/null +++ b/assets/cn_src_ranuts_utils_ocr.md.aSDPltJI.lean.js @@ -0,0 +1,15 @@ +import{_ as d,o as a,c as r,a3 as i}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"OCR","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/ocr.md","filePath":"cn/src/ranuts/utils/ocr.md","lastUpdated":1726550590000}'),s={name:"cn/src/ranuts/utils/ocr.md"};function n(e,t,l,h,o,p){return a(),r("div",{"data-pagefind-body":!0},t[0]||(t[0]=[i(`

OCR

传入图片和对应的语言类型,返回图片中的文本。

API

Return

参数说明类型
success是否解析成功boolean
data解析成功后的对象obj
message解析成功或失败的原因string

Options

参数说明类型默认值
images图片的数组,支持urlbase64Array<string>
language指定生成文本的语言,具体参数见lang-codestring
langPath使用的时候需要能访问cdn.jsdelivr.net,会下载对应的语言包,如果无法访问,也可以将语言包放在本地,传入对应的 目录 路径string可选参数,默认走网络下载

Example

js
import { ocr } from 'ranuts';
+
+const images = ['https://chaxus.github.io/ran/ocr/eng.png'];
+const languages = 'eng';
+ocr({ images, language }).then((res) => {
+  console.log(res.data?.[0].data.text);
+});
+// Mild Splendour of the various-vested Night!
+// Mother of wildly-working visions! hail
+// I watch thy gliding, while with watery light
+// Thy weak eye glimmers through a fleecy veil;
+// And when thou lovest thy pale orb to shroud
+// Behind the gather’d blackness lost on high;
+// And when thou dartest from the wind-rent cloud
+// Thy placid lightning o’er the awaken’d sky.

Lang Code

Lang CodeLanguage
afrAfrikaans
amhAmharic
araArabic
asmAssamese
azeAzerbaijani
aze_cyrlAzerbaijani - Cyrillic
belBelarusian
benBengali
bodTibetan
bosBosnian
bulBulgarian
catCatalan; Valencian
cebCebuano
cesCzech
chi_simChinese - Simplified
chi_traChinese - Traditional
chrCherokee
cymWelsh
danDanish
deuGerman
dzoDzongkha
ellGreek, Modern (1453-)
engEnglish
enmEnglish, Middle (1100-1500)
epoEsperanto
estEstonian
eusBasque
fasPersian
finFinnish
fraFrench
frkGerman Fraktur
frmFrench, Middle (ca. 1400-1600)
gleIrish
glgGalician
grcGreek, Ancient (-1453)
gujGujarati
hatHaitian; Haitian Creole
hebHebrew
hinHindi
hrvCroatian
hunHungarian
ikuInuktitut
indIndonesian
islIcelandic
itaItalian
ita_oldItalian - Old
javJavanese
jpnJapanese
kanKannada
katGeorgian
kat_oldGeorgian - Old
kazKazakh
khmCentral Khmer
kirKirghiz; Kyrgyz
korKorean
kurKurdish
laoLao
latLatin
lavLatvian
litLithuanian
malMalayalam
marMarathi
mkdMacedonian
mltMaltese
msaMalay
myaBurmese
nepNepali
nldDutch; Flemish
norNorwegian
oriOriya
panPanjabi; Punjabi
polPolish
porPortuguese
pusPushto; Pashto
ronRomanian; Moldavian; Moldovan
rusRussian
sanSanskrit
sinSinhala; Sinhalese
slkSlovak
slvSlovenian
spaSpanish; Castilian
spa_oldSpanish; Castilian - Old
sqiAlbanian
srpSerbian
srp_latnSerbian - Latin
swaSwahili
sweSwedish
syrSyriac
tamTamil
telTelugu
tgkTajik
tglTagalog
thaThai
tirTigrinya
turTurkish
uigUighur; Uyghur
ukrUkrainian
urdUrdu
uzbUzbek
uzb_cyrlUzbek - Cyrillic
vieVietnamese
yidYiddish
`,11)]))}const g=d(s,[["render",n]]);export{c as __pageData,g as default}; diff --git a/assets/cn_src_ranuts_utils_str2xml.md.CxozQof2.js b/assets/cn_src_ranuts_utils_str2xml.md.CxozQof2.js new file mode 100644 index 0000000000..26948b9cb9 --- /dev/null +++ b/assets/cn_src_ranuts_utils_str2xml.md.CxozQof2.js @@ -0,0 +1,8 @@ +import{_ as s,o as a,c as i,a3 as e}from"./chunks/framework.C-ai2y4t.js";const k=JSON.parse('{"title":"str2Xml","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/str2xml.md","filePath":"cn/src/ranuts/utils/str2xml.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranuts/utils/str2xml.md"};function l(d,t,h,o,r,p){return a(),i("div",{"data-pagefind-body":!0},t[0]||(t[0]=[e(`

str2Xml

传入字符串,转成xml

API

Return

参数说明类型
HTMLElement返回一个HTMLElementHTMLElement

Options

参数说明类型默认值
xmlStr传入的参数string
format设置需要转换的格式,默认text/xmlDOMParserSupportedType

Example

比如在做图标库的时候,我们需要动态导入目录下的所有icon。这时候导入的是字符串,但字符串无法添加到xml中。 因此我们需要将字符串转换成xml,然后就可以将它加入到xml中。

js
import { str2Xml } from 'ranuts';
+
+// import 'assets/*.svg'
+const svg = \`<svg t="1667483498347" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8544" width="200" height="200"><path d="M858.5 763.6c-18.9-44.8-46.1-85-80.6-119.5-34.5-34.5-74.7-61.6-119.5-80.6-0.4-0.2-0.8-0.3-1.2-0.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-0.4 0.2-0.8 0.3-1.2 0.5-44.8 18.9-85 46-119.5 80.6-34.5 34.5-61.6 74.7-80.6 119.5C146.9 807.5 137 854 136 901.8c-0.1 4.5 3.5 8.2 8 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c0.1 4.4 3.6 7.8 8 7.8h60c4.5 0 8.1-3.7 8-8.2-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z" p-id="8545"></path></svg>\`;
+
+const icon = str2Xml(svg, 'image/svg+xml');
+
+document.body.appendChild(icon);
`,10)]))}const u=s(n,[["render",l]]);export{k as __pageData,u as default}; diff --git a/assets/cn_src_ranuts_utils_str2xml.md.CxozQof2.lean.js b/assets/cn_src_ranuts_utils_str2xml.md.CxozQof2.lean.js new file mode 100644 index 0000000000..26948b9cb9 --- /dev/null +++ b/assets/cn_src_ranuts_utils_str2xml.md.CxozQof2.lean.js @@ -0,0 +1,8 @@ +import{_ as s,o as a,c as i,a3 as e}from"./chunks/framework.C-ai2y4t.js";const k=JSON.parse('{"title":"str2Xml","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/str2xml.md","filePath":"cn/src/ranuts/utils/str2xml.md","lastUpdated":1726550590000}'),n={name:"cn/src/ranuts/utils/str2xml.md"};function l(d,t,h,o,r,p){return a(),i("div",{"data-pagefind-body":!0},t[0]||(t[0]=[e(`

str2Xml

传入字符串,转成xml

API

Return

参数说明类型
HTMLElement返回一个HTMLElementHTMLElement

Options

参数说明类型默认值
xmlStr传入的参数string
format设置需要转换的格式,默认text/xmlDOMParserSupportedType

Example

比如在做图标库的时候,我们需要动态导入目录下的所有icon。这时候导入的是字符串,但字符串无法添加到xml中。 因此我们需要将字符串转换成xml,然后就可以将它加入到xml中。

js
import { str2Xml } from 'ranuts';
+
+// import 'assets/*.svg'
+const svg = \`<svg t="1667483498347" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8544" width="200" height="200"><path d="M858.5 763.6c-18.9-44.8-46.1-85-80.6-119.5-34.5-34.5-74.7-61.6-119.5-80.6-0.4-0.2-0.8-0.3-1.2-0.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-0.4 0.2-0.8 0.3-1.2 0.5-44.8 18.9-85 46-119.5 80.6-34.5 34.5-61.6 74.7-80.6 119.5C146.9 807.5 137 854 136 901.8c-0.1 4.5 3.5 8.2 8 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c0.1 4.4 3.6 7.8 8 7.8h60c4.5 0 8.1-3.7 8-8.2-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z" p-id="8545"></path></svg>\`;
+
+const icon = str2Xml(svg, 'image/svg+xml');
+
+document.body.appendChild(icon);
`,10)]))}const u=s(n,[["render",l]]);export{k as __pageData,u as default}; diff --git a/assets/cn_src_ranuts_utils_task.md.Nv89-z_1.js b/assets/cn_src_ranuts_utils_task.md.Nv89-z_1.js new file mode 100644 index 0000000000..38920cc725 --- /dev/null +++ b/assets/cn_src_ranuts_utils_task.md.Nv89-z_1.js @@ -0,0 +1 @@ +import{_ as a,o as t,c as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const k=JSON.parse('{"title":"统计执行时间","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/task.md","filePath":"cn/src/ranuts/utils/task.md","lastUpdated":1726550590000}'),o={name:"cn/src/ranuts/utils/task.md"};function n(d,e,r,c,l,h){return t(),s("div",{"data-pagefind-body":!0},e[0]||(e[0]=[i('

统计执行时间

有的时候,我们需要统计一个函数的执行时间,用于分析性能。因此封装了startTasktaskEnd函数。同时介绍其他三种统计方法

  1. new Date().getTime(),
  2. console.time()console.timeEnd(),
  3. performance.now()

一.startTask,taskEnd

1.startTask

任务开始之前执行

Return

参数说明类型
taskId任务标识unique symbol

2.taskEnd

任务结束的时候执行,需要传入startTask返回的任务标识

Options

参数说明类型默认值
taskId任务标识unique symbol 无默认值,参数必传,否则无法识别是哪个任务

Return

参数说明类型
timetask执行的时间number

3.使用例子

js
const taskId = startTask();\n\n// do something\n\nconst time = taskEnd(taskId);\n\nconsole.log('task 执行花费的时间', time);

二.new Date().getTime()

new Date().getTime() 返回一个数值,表示从 1970 年 1 月 1 日 0 时 0 分 0 秒(UTC,即协调世界时)距离该日期对象所代表时间的毫秒数。用来计算 JS 执行时间会有两个问题:

  1. 某些情况下,毫秒级精度可能不够。
  2. new Date() 解析的时间在不同浏览器,或者不同设备上可能并不一致。MDN 说明

    由于浏览器之间的差异与不一致性,强烈不推荐使用 Date 构造函数来解析日期字符串 (或使用与其等价的 Date.parse)。对 RFC 2822 格式的日期仅有约定俗成的支持。对 ISO 8601 格式的支持中,仅有日期的串 (例如 "1970-01-01") 会被处理为 UTC 而不是本地时间,与其他格式的串的处理不同。

三.console.time(), console.timeEnd()

启动一个计时器来跟踪某一个操作的占用时长。每一个计时器必须拥有唯一的名字,页面中最多能同时运行 10,000 个计时器。当以此计时器名字为参数调用 console.timeEnd() 时,浏览器将以毫秒为单位,输出对应计时器所经过的时间。比起new Date().getTime(),统计时间更加精确,可以统计到 0.001 毫秒(比如:0.134ms)

四.performance.now()

performance.now()返回的时间精度最高可达微秒级,且不会受到系统时间的影响(系统时钟可能会被手动调整或被 NTP 等软件篡改)。另外,performance.timing.navigationStart + performance.now() 约等于 Date.now()。因此对于统计 JS 执行耗时方面,更推荐使用performance.now()

注意:为了提供对定时攻击和指纹的保护,performance.now() 的精度可能会根据浏览器的设置而被舍弃。 在 Firefox 中,privacy.reduceTimerPrecision 偏好是默认启用的,默认值为 1ms。可以启用 privacy.resistFingerprinting 这将精度改为 100ms 或privacy.resistFingerprinting.reduceTimerPrecision.microseconds 的值,以较大者为准。

',24)]))}const m=a(o,[["render",n]]);export{k as __pageData,m as default}; diff --git a/assets/cn_src_ranuts_utils_task.md.Nv89-z_1.lean.js b/assets/cn_src_ranuts_utils_task.md.Nv89-z_1.lean.js new file mode 100644 index 0000000000..38920cc725 --- /dev/null +++ b/assets/cn_src_ranuts_utils_task.md.Nv89-z_1.lean.js @@ -0,0 +1 @@ +import{_ as a,o as t,c as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const k=JSON.parse('{"title":"统计执行时间","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/ranuts/utils/task.md","filePath":"cn/src/ranuts/utils/task.md","lastUpdated":1726550590000}'),o={name:"cn/src/ranuts/utils/task.md"};function n(d,e,r,c,l,h){return t(),s("div",{"data-pagefind-body":!0},e[0]||(e[0]=[i('

统计执行时间

有的时候,我们需要统计一个函数的执行时间,用于分析性能。因此封装了startTasktaskEnd函数。同时介绍其他三种统计方法

  1. new Date().getTime(),
  2. console.time()console.timeEnd(),
  3. performance.now()

一.startTask,taskEnd

1.startTask

任务开始之前执行

Return

参数说明类型
taskId任务标识unique symbol

2.taskEnd

任务结束的时候执行,需要传入startTask返回的任务标识

Options

参数说明类型默认值
taskId任务标识unique symbol 无默认值,参数必传,否则无法识别是哪个任务

Return

参数说明类型
timetask执行的时间number

3.使用例子

js
const taskId = startTask();\n\n// do something\n\nconst time = taskEnd(taskId);\n\nconsole.log('task 执行花费的时间', time);

二.new Date().getTime()

new Date().getTime() 返回一个数值,表示从 1970 年 1 月 1 日 0 时 0 分 0 秒(UTC,即协调世界时)距离该日期对象所代表时间的毫秒数。用来计算 JS 执行时间会有两个问题:

  1. 某些情况下,毫秒级精度可能不够。
  2. new Date() 解析的时间在不同浏览器,或者不同设备上可能并不一致。MDN 说明

    由于浏览器之间的差异与不一致性,强烈不推荐使用 Date 构造函数来解析日期字符串 (或使用与其等价的 Date.parse)。对 RFC 2822 格式的日期仅有约定俗成的支持。对 ISO 8601 格式的支持中,仅有日期的串 (例如 "1970-01-01") 会被处理为 UTC 而不是本地时间,与其他格式的串的处理不同。

三.console.time(), console.timeEnd()

启动一个计时器来跟踪某一个操作的占用时长。每一个计时器必须拥有唯一的名字,页面中最多能同时运行 10,000 个计时器。当以此计时器名字为参数调用 console.timeEnd() 时,浏览器将以毫秒为单位,输出对应计时器所经过的时间。比起new Date().getTime(),统计时间更加精确,可以统计到 0.001 毫秒(比如:0.134ms)

四.performance.now()

performance.now()返回的时间精度最高可达微秒级,且不会受到系统时间的影响(系统时钟可能会被手动调整或被 NTP 等软件篡改)。另外,performance.timing.navigationStart + performance.now() 约等于 Date.now()。因此对于统计 JS 执行耗时方面,更推荐使用performance.now()

注意:为了提供对定时攻击和指纹的保护,performance.now() 的精度可能会根据浏览器的设置而被舍弃。 在 Firefox 中,privacy.reduceTimerPrecision 偏好是默认启用的,默认值为 1ms。可以启用 privacy.resistFingerprinting 这将精度改为 100ms 或privacy.resistFingerprinting.reduceTimerPrecision.microseconds 的值,以较大者为准。

',24)]))}const m=a(o,[["render",n]]);export{k as __pageData,m as default}; diff --git "a/assets/cn_src_types_TS\347\261\273\345\236\213.md.BoPQGs5F.js" "b/assets/cn_src_types_TS\347\261\273\345\236\213.md.BoPQGs5F.js" new file mode 100644 index 0000000000..fab233ec05 --- /dev/null +++ "b/assets/cn_src_types_TS\347\261\273\345\236\213.md.BoPQGs5F.js" @@ -0,0 +1,48 @@ +import{_ as i,o as a,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"TypeScript 类型系统中的类型","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/types/TS类型.md","filePath":"cn/src/types/TS类型.md","lastUpdated":1726550590000}'),l={name:"cn/src/types/TS类型.md"};function t(p,s,k,e,r,d){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h(`

TypeScript 类型系统中的类型

  1. 基本类型: number、boolean、string、object、bigint、symbol、undefined、null
  2. 复合类型: class、Array、元组(Tuple)、接口(Interface)、枚举(Enum)
  3. 特殊的类型:void、never、any、unknown

Tuple

元组(Tuple)就是元素个数和类型固定的数组类型:

ts
type Tuple = [number, string];

Interface

接口(Interface)可以描述函数、对象、构造器的结构:

  • 对象
ts
interface IPerson {
+  name: string;
+  age: number;
+}
+
+class Person implements IPerson {
+  name: string;
+  age: number;
+}
+
+const obj: IPerson = {
+  name: 'name',
+  age: 18,
+};
  • 函数
ts
interface SayHello {
+  (name: string): string;
+}
+
+const func: SayHello = (name: string) => {
+  return 'hello,' + name;
+};
  • 构造器
ts
interface PersonConstructor {
+  new (name: string, age: number): IPerson;
+}
+
+function createPerson(ctor: PersonConstructor): IPerson {
+  return new ctor('name', 18);
+}

对象类型、class 类型在 TypeScript 里也叫做索引类型,也就是索引了多个元素的类型的意思。对象可以动态添加属性,如果不知道会有什么属性,可以用可索引签名:

ts
interface IPerson {
+  [prop: string]: string | number;
+}
+const obj: IPerson = {};
+obj.name = 'name';
+obj.age = 18;

Enum

枚举(Enum)是一系列值的复合:

ts
enum Transpiler {
+  Babel = 'babel',
+  Postcss = 'postcss',
+  Terser = 'terser',
+  Prettier = 'prettier',
+  TypeScriptCompiler = 'tsc',
+}
+
+const transpiler = Transpiler.TypeScriptCompiler;

此外,TypeScript 还支持字面量类型,也就是类似 1111、'aaaa'、{ a: 1} 这种值也可以做为类型。

其中,字符串的字面量类型有两种,一种是普通的字符串字面量,比如 'aaa',另一种是模版字面量,比如 aaa\${string},它的意思是以 aaa 开头,后面是任意 string 的字符串字面量类型。

所以想要约束以某个字符串开头的字符串字面量类型时可以这样写:

ts
function func(str: \`#\${string}\`) {}
+
+func('aaa'); // error
+
+func('#aaa'); // true

void

代表空,可以是 undefined 或 never。

never

代表不可达,比如函数抛异常的时候,返回值就是 never。

any

是任意类型,任何类型都可以赋值给它,它也可以赋值给任何类型(除了 never)。

unknown

是未知类型,任何类型都可以赋值给它,但是它不可以赋值给别的类型。

类型的装饰

除了描述类型的结构外,TypeScript 的类型系统还支持描述类型的属性,比如是否可选,是否只读等:

ts
interface IPerson {
+  readonly name: string;
+  age?: number;
+}
+
+type tuple = [string, number?];
`,33)]))}const y=i(l,[["render",t]]);export{g as __pageData,y as default}; diff --git "a/assets/cn_src_types_TS\347\261\273\345\236\213.md.BoPQGs5F.lean.js" "b/assets/cn_src_types_TS\347\261\273\345\236\213.md.BoPQGs5F.lean.js" new file mode 100644 index 0000000000..fab233ec05 --- /dev/null +++ "b/assets/cn_src_types_TS\347\261\273\345\236\213.md.BoPQGs5F.lean.js" @@ -0,0 +1,48 @@ +import{_ as i,o as a,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"TypeScript 类型系统中的类型","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/types/TS类型.md","filePath":"cn/src/types/TS类型.md","lastUpdated":1726550590000}'),l={name:"cn/src/types/TS类型.md"};function t(p,s,k,e,r,d){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h(`

TypeScript 类型系统中的类型

  1. 基本类型: number、boolean、string、object、bigint、symbol、undefined、null
  2. 复合类型: class、Array、元组(Tuple)、接口(Interface)、枚举(Enum)
  3. 特殊的类型:void、never、any、unknown

Tuple

元组(Tuple)就是元素个数和类型固定的数组类型:

ts
type Tuple = [number, string];

Interface

接口(Interface)可以描述函数、对象、构造器的结构:

  • 对象
ts
interface IPerson {
+  name: string;
+  age: number;
+}
+
+class Person implements IPerson {
+  name: string;
+  age: number;
+}
+
+const obj: IPerson = {
+  name: 'name',
+  age: 18,
+};
  • 函数
ts
interface SayHello {
+  (name: string): string;
+}
+
+const func: SayHello = (name: string) => {
+  return 'hello,' + name;
+};
  • 构造器
ts
interface PersonConstructor {
+  new (name: string, age: number): IPerson;
+}
+
+function createPerson(ctor: PersonConstructor): IPerson {
+  return new ctor('name', 18);
+}

对象类型、class 类型在 TypeScript 里也叫做索引类型,也就是索引了多个元素的类型的意思。对象可以动态添加属性,如果不知道会有什么属性,可以用可索引签名:

ts
interface IPerson {
+  [prop: string]: string | number;
+}
+const obj: IPerson = {};
+obj.name = 'name';
+obj.age = 18;

Enum

枚举(Enum)是一系列值的复合:

ts
enum Transpiler {
+  Babel = 'babel',
+  Postcss = 'postcss',
+  Terser = 'terser',
+  Prettier = 'prettier',
+  TypeScriptCompiler = 'tsc',
+}
+
+const transpiler = Transpiler.TypeScriptCompiler;

此外,TypeScript 还支持字面量类型,也就是类似 1111、'aaaa'、{ a: 1} 这种值也可以做为类型。

其中,字符串的字面量类型有两种,一种是普通的字符串字面量,比如 'aaa',另一种是模版字面量,比如 aaa\${string},它的意思是以 aaa 开头,后面是任意 string 的字符串字面量类型。

所以想要约束以某个字符串开头的字符串字面量类型时可以这样写:

ts
function func(str: \`#\${string}\`) {}
+
+func('aaa'); // error
+
+func('#aaa'); // true

void

代表空,可以是 undefined 或 never。

never

代表不可达,比如函数抛异常的时候,返回值就是 never。

any

是任意类型,任何类型都可以赋值给它,它也可以赋值给任何类型(除了 never)。

unknown

是未知类型,任何类型都可以赋值给它,但是它不可以赋值给别的类型。

类型的装饰

除了描述类型的结构外,TypeScript 的类型系统还支持描述类型的属性,比如是否可选,是否只读等:

ts
interface IPerson {
+  readonly name: string;
+  age?: number;
+}
+
+type tuple = [string, number?];
`,33)]))}const y=i(l,[["render",t]]);export{g as __pageData,y as default}; diff --git "a/assets/cn_src_types_\346\250\241\345\274\217\345\214\271\351\205\215.md.CfyGKgqa.js" "b/assets/cn_src_types_\346\250\241\345\274\217\345\214\271\351\205\215.md.CfyGKgqa.js" new file mode 100644 index 0000000000..2ac2fd5836 --- /dev/null +++ "b/assets/cn_src_types_\346\250\241\345\274\217\345\214\271\351\205\215.md.CfyGKgqa.js" @@ -0,0 +1 @@ +import{_ as i,o as a,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"模式匹配","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/types/模式匹配.md","filePath":"cn/src/types/模式匹配.md","lastUpdated":1726550590000}'),k={name:"cn/src/types/模式匹配.md"};function n(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

模式匹配

Typescript 的类型也同样可以做模式匹配。

比如这样一个 Promise 类型:

ts
type p = Promise<'value'>;

我们想提取 value 的类型,可以这样做:

ts
type GetPromiseValue<T> = T extends Promise<infer value> ? value : never;

通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取的,通过 infer 声明一个局部变量 Value 来保存,如果匹配,就返回匹配到的 Value,否则就返回 never 代表没匹配到。

ts
type result = GetPromiseValue<Promise<'name'>>; // name

数组类型

数组类型想提取第一个元素的类型怎么做呢?

ts
type arr = [1, 2, 3];

用它来匹配一个模式类型,提取第一个元素的类型到通过 infer 声明的局部变量里返回。

ts
type GetArrayFirstItem<T extends unknown[]> = T extends [infer value, ...unknown[]] ? value : never;

类型参数 Arr 通过 extends 约束为只能是数组类型,数组元素是 unknown 也就是可以是任何值。

any 和 unknown 的区别: any 和 unknown 都代表任意类型,但是 unknown 只能接收任意类型的值,而 any 除了可以接收任意类型的值,也可以赋值给任意类型(除了 never)。类型体操中经常用 unknown 接受和匹配任何类型,而很少把任何类型赋值给某个类型变量。

对 Arr 做模式匹配,把我们要提取的第一个元素的类型放到通过 infer 声明的 First 局部变量里,后面的元素可以是任何类型,用 unknown 接收,然后把局部变量 First 返回。

当类型参数 Arr 为 [1,2,3] 时:

ts
type result = GetArrayFirstItem<[1, 2, 3]>; // 1

当类型参数 Arr 为 [] 时:

ts
type result = GetArrayFirstItem<[]>; // never

可以提取第一个元素,当然也可以提取最后一个元素,修改下模式类型就行:

ts
type GetArrayLastItem<T extends unknown[]> = T extends [...unknown[],inter L] ? L : never

我们分别取了首尾元素,当然也可以取剩余的数组,比如取去掉了最后一个元素的数组:

ts
type Pop<T extends unknown[]> = T extends [] ? [] : T extends [...infer Rest, unknown] ? Rest : never;

如果是空数组,就直接返回,否则匹配剩余的元素,放到 infer 声明的局部变量 Rest 里,返回 Rest。

当类型参数 Arr 为 [1,2,3] 时:

ts
type Result = Pop<[1, 2, 3]>; // [1,2]

当类型参数 Arr 为 [] 时:

ts
type Result = Pop<[]>; // []

同理可得 ShiftArr 的实现:

ts
type Shift<T extends unknown[]> = T extends [] ? [] : T extends [unknown, ...infer Rest] ? Rest : never;

字符串类型也同样可以做模式匹配,匹配一个模式字符串,把需要提取的部分放到 infer 声明的局部变量里。

判断字符串是否以某个前缀开头,也是通过模式匹配:

ts
type StartWidth<S extends string, P extends string> = S extends `${P}${string}` ? true : false;

需要声明字符串 Str、匹配的前缀 Prefix 两个类型参数,它们都是 string。

用 Str 去匹配一个模式类型,模式类型的前缀是 Prefix,后面是任意的 string,如果匹配返回 true,否则返回 false。

字符串可以匹配一个模式类型,提取想要的部分,自然也可以用这些再构成一个新的类型。

比如实现字符串替换:

ts
type Replace<S extends string, F extends string, T extends string> = S extends `${infer P}${F}${infer L}`\n  ? `${P}${T}${L}`\n  : S;

声明要替换的字符串 Str、待替换的字符串 From、替换成的字符串 3 个类型参数,通过 extends 约束为都是 string 类型。

用 Str 去匹配模式串,模式串由 From 和之前之后的字符串构成,把之前之后的字符串放到通过 infer 声明的局部变量 Prefix、Suffix 里。

用 Prefix、Suffix 加上替换到的字符串 To 构造成新的字符串类型返回。

Trim

能够匹配和替换字符串,那也就能实现去掉空白字符的 Trim:

不过因为我们不知道有多少个空白字符,所以只能一个个匹配和去掉,需要递归。

先实现 TrimRight:

ts
type TrimRight<S extends string> = S extends `${infer Rest}${' ' | '\\n' | '\\t'}` ? TrimRight<Rest> : S;

类型参数 Str 是要 Trim 的字符串。

如果 Str 匹配字符串 + 空白字符 (空格、换行、制表符),那就把字符串放到 infer 声明的局部变量 Rest 里。

把 Rest 作为类型参数递归 TrimRight,直到不匹配,这时的类型参数 Str 就是处理结果。

同理可得 TrimLeft:

ts
type TrimLeft<S extends string> = S extends `${' ' | '\\n' | '\\t'}${infer Rest}` ? TrimLeft<Rest> : S;

TrimRight 和 TrimLeft 结合就是 Trim:

ts
type Trim<S extends string> = TrimLeft<TrimRight<S>>;

函数

函数同样也可以做类型匹配,比如提取参数、返回值的类型。

GetParameters

函数类型可以通过模式匹配来提取参数的类型:

ts
type GetParameters<T extends Function> = T extends (...args: infer A) => unknown ? A : never;

类型参数 Func 是要匹配的函数类型,通过 extends 约束为 Function。

Func 和模式类型做匹配,参数类型放到用 infer 声明的局部变量 Args 里,返回值可以是任何类型,用 unknown。

返回提取到的参数类型 Args。

GetReturnType

ts
type GetReturnType<T extends Function> = T extends (...args: unknown[]) => infer R ? R : never;

Func 和模式类型做匹配,提取返回值到通过 infer 声明的局部变量 ReturnType 里返回。

参数类型可以是任意类型,也就是 any[](注意,这里不能用 unknown,这里的解释涉及到参数的逆变性质,具体原因逆变那一节会解释)。

GetThisParameterType

方法里可以调用 this,用对象.方法名的方式调用的时候,this 就指向那个对象。

但是方法也可以用 call 或者 apply 调用,call 调用的时候,this 就变了,但这里却没有被检查出来 this 指向的错误。

这里的 this 类型同样也可以通过模式匹配提取出来:

ts
type GetThisParameterType<T extends Function> = T extends (this: infer H, ...args: unknown[]) => unknown ? H : unknown;

构造器

构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

同样,我们也可以通过模式匹配提取构造器的参数和返回值的类型:

GetInstanceType

构造器类型可以用 interface 声明,使用 new(): xx 的语法。

ts
interface Person {\n  name: string;\n}\n\ninterface PersonConstructor {\n  new (name: string): Person;\n}

这里的 PersonConstructor 返回的是 Person 类型的实例对象,这个也可以通过模式匹配取出来。

ts
type GetInstanceType<C extends new (...args: unknown[]) => unknown> = C extends new (...args: unknown[]) => infer T\n  ? T\n  : unknown;
',79)]))}const y=i(k,[["render",n]]);export{F as __pageData,y as default}; diff --git "a/assets/cn_src_types_\346\250\241\345\274\217\345\214\271\351\205\215.md.CfyGKgqa.lean.js" "b/assets/cn_src_types_\346\250\241\345\274\217\345\214\271\351\205\215.md.CfyGKgqa.lean.js" new file mode 100644 index 0000000000..2ac2fd5836 --- /dev/null +++ "b/assets/cn_src_types_\346\250\241\345\274\217\345\214\271\351\205\215.md.CfyGKgqa.lean.js" @@ -0,0 +1 @@ +import{_ as i,o as a,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"模式匹配","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/types/模式匹配.md","filePath":"cn/src/types/模式匹配.md","lastUpdated":1726550590000}'),k={name:"cn/src/types/模式匹配.md"};function n(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

模式匹配

Typescript 的类型也同样可以做模式匹配。

比如这样一个 Promise 类型:

ts
type p = Promise<'value'>;

我们想提取 value 的类型,可以这样做:

ts
type GetPromiseValue<T> = T extends Promise<infer value> ? value : never;

通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取的,通过 infer 声明一个局部变量 Value 来保存,如果匹配,就返回匹配到的 Value,否则就返回 never 代表没匹配到。

ts
type result = GetPromiseValue<Promise<'name'>>; // name

数组类型

数组类型想提取第一个元素的类型怎么做呢?

ts
type arr = [1, 2, 3];

用它来匹配一个模式类型,提取第一个元素的类型到通过 infer 声明的局部变量里返回。

ts
type GetArrayFirstItem<T extends unknown[]> = T extends [infer value, ...unknown[]] ? value : never;

类型参数 Arr 通过 extends 约束为只能是数组类型,数组元素是 unknown 也就是可以是任何值。

any 和 unknown 的区别: any 和 unknown 都代表任意类型,但是 unknown 只能接收任意类型的值,而 any 除了可以接收任意类型的值,也可以赋值给任意类型(除了 never)。类型体操中经常用 unknown 接受和匹配任何类型,而很少把任何类型赋值给某个类型变量。

对 Arr 做模式匹配,把我们要提取的第一个元素的类型放到通过 infer 声明的 First 局部变量里,后面的元素可以是任何类型,用 unknown 接收,然后把局部变量 First 返回。

当类型参数 Arr 为 [1,2,3] 时:

ts
type result = GetArrayFirstItem<[1, 2, 3]>; // 1

当类型参数 Arr 为 [] 时:

ts
type result = GetArrayFirstItem<[]>; // never

可以提取第一个元素,当然也可以提取最后一个元素,修改下模式类型就行:

ts
type GetArrayLastItem<T extends unknown[]> = T extends [...unknown[],inter L] ? L : never

我们分别取了首尾元素,当然也可以取剩余的数组,比如取去掉了最后一个元素的数组:

ts
type Pop<T extends unknown[]> = T extends [] ? [] : T extends [...infer Rest, unknown] ? Rest : never;

如果是空数组,就直接返回,否则匹配剩余的元素,放到 infer 声明的局部变量 Rest 里,返回 Rest。

当类型参数 Arr 为 [1,2,3] 时:

ts
type Result = Pop<[1, 2, 3]>; // [1,2]

当类型参数 Arr 为 [] 时:

ts
type Result = Pop<[]>; // []

同理可得 ShiftArr 的实现:

ts
type Shift<T extends unknown[]> = T extends [] ? [] : T extends [unknown, ...infer Rest] ? Rest : never;

字符串类型也同样可以做模式匹配,匹配一个模式字符串,把需要提取的部分放到 infer 声明的局部变量里。

判断字符串是否以某个前缀开头,也是通过模式匹配:

ts
type StartWidth<S extends string, P extends string> = S extends `${P}${string}` ? true : false;

需要声明字符串 Str、匹配的前缀 Prefix 两个类型参数,它们都是 string。

用 Str 去匹配一个模式类型,模式类型的前缀是 Prefix,后面是任意的 string,如果匹配返回 true,否则返回 false。

字符串可以匹配一个模式类型,提取想要的部分,自然也可以用这些再构成一个新的类型。

比如实现字符串替换:

ts
type Replace<S extends string, F extends string, T extends string> = S extends `${infer P}${F}${infer L}`\n  ? `${P}${T}${L}`\n  : S;

声明要替换的字符串 Str、待替换的字符串 From、替换成的字符串 3 个类型参数,通过 extends 约束为都是 string 类型。

用 Str 去匹配模式串,模式串由 From 和之前之后的字符串构成,把之前之后的字符串放到通过 infer 声明的局部变量 Prefix、Suffix 里。

用 Prefix、Suffix 加上替换到的字符串 To 构造成新的字符串类型返回。

Trim

能够匹配和替换字符串,那也就能实现去掉空白字符的 Trim:

不过因为我们不知道有多少个空白字符,所以只能一个个匹配和去掉,需要递归。

先实现 TrimRight:

ts
type TrimRight<S extends string> = S extends `${infer Rest}${' ' | '\\n' | '\\t'}` ? TrimRight<Rest> : S;

类型参数 Str 是要 Trim 的字符串。

如果 Str 匹配字符串 + 空白字符 (空格、换行、制表符),那就把字符串放到 infer 声明的局部变量 Rest 里。

把 Rest 作为类型参数递归 TrimRight,直到不匹配,这时的类型参数 Str 就是处理结果。

同理可得 TrimLeft:

ts
type TrimLeft<S extends string> = S extends `${' ' | '\\n' | '\\t'}${infer Rest}` ? TrimLeft<Rest> : S;

TrimRight 和 TrimLeft 结合就是 Trim:

ts
type Trim<S extends string> = TrimLeft<TrimRight<S>>;

函数

函数同样也可以做类型匹配,比如提取参数、返回值的类型。

GetParameters

函数类型可以通过模式匹配来提取参数的类型:

ts
type GetParameters<T extends Function> = T extends (...args: infer A) => unknown ? A : never;

类型参数 Func 是要匹配的函数类型,通过 extends 约束为 Function。

Func 和模式类型做匹配,参数类型放到用 infer 声明的局部变量 Args 里,返回值可以是任何类型,用 unknown。

返回提取到的参数类型 Args。

GetReturnType

ts
type GetReturnType<T extends Function> = T extends (...args: unknown[]) => infer R ? R : never;

Func 和模式类型做匹配,提取返回值到通过 infer 声明的局部变量 ReturnType 里返回。

参数类型可以是任意类型,也就是 any[](注意,这里不能用 unknown,这里的解释涉及到参数的逆变性质,具体原因逆变那一节会解释)。

GetThisParameterType

方法里可以调用 this,用对象.方法名的方式调用的时候,this 就指向那个对象。

但是方法也可以用 call 或者 apply 调用,call 调用的时候,this 就变了,但这里却没有被检查出来 this 指向的错误。

这里的 this 类型同样也可以通过模式匹配提取出来:

ts
type GetThisParameterType<T extends Function> = T extends (this: infer H, ...args: unknown[]) => unknown ? H : unknown;

构造器

构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

同样,我们也可以通过模式匹配提取构造器的参数和返回值的类型:

GetInstanceType

构造器类型可以用 interface 声明,使用 new(): xx 的语法。

ts
interface Person {\n  name: string;\n}\n\ninterface PersonConstructor {\n  new (name: string): Person;\n}

这里的 PersonConstructor 返回的是 Person 类型的实例对象,这个也可以通过模式匹配取出来。

ts
type GetInstanceType<C extends new (...args: unknown[]) => unknown> = C extends new (...args: unknown[]) => infer T\n  ? T\n  : unknown;
',79)]))}const y=i(k,[["render",n]]);export{F as __pageData,y as default}; diff --git "a/assets/cn_src_types_\347\261\273\345\236\213\350\277\220\347\256\227.md.y4F25ckq.js" "b/assets/cn_src_types_\347\261\273\345\236\213\350\277\220\347\256\227.md.y4F25ckq.js" new file mode 100644 index 0000000000..dfd115c982 --- /dev/null +++ "b/assets/cn_src_types_\347\261\273\345\236\213\350\277\220\347\256\227.md.y4F25ckq.js" @@ -0,0 +1,27 @@ +import{_ as i,o as a,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"TypeScript 类型系统中的类型运算","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/types/类型运算.md","filePath":"cn/src/types/类型运算.md","lastUpdated":1726550590000}'),n={name:"cn/src/types/类型运算.md"};function p(t,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k(`

TypeScript 类型系统中的类型运算

条件:extends ? :

TypeScript 里的条件判断是 extends ? :,叫做条件类型(Conditional Type)比如:

ts
type isTwo<T> = T extends 2 ? true : false;
+
+type res = isTwo<1>; // true
+type res2 = isTwo<2>; // false

这种类型也叫做高级类型。

高级类型的特点是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

推导:infer

如何提取类型的一部分呢?答案是 infer。

比如提取元组类型的第一个元素:

ts
type FirstTupleItem<Tuple extends unknown[]> = Tuple extends [infer T, ...inter R] ? T : never;
+
+type res = First<[1,2,3]> // 1

注意,第一个 extends 不是条件,条件类型是 extends ? :,这里的 extends 是约束的意思,也就是约束类型参数只能是数组类型。

因为不知道数组元素的具体类型,所以用 unknown。

联合:|

联合类型(Union)类似 js 里的或运算符 |,但是作用于类型,代表类型可以是几个类型之一。

ts
type Union = 1 | 2 | 3;

交叉:&

交叉类型(Intersection)类似 js 中的与运算符 &,但是作用于类型,代表对类型做合并。

ts
type ObjType = { a: number } & { c: boolean };

注意,同一类型可以合并,不同的类型没法合并,会被舍弃:

ts
type res = 'a' & 2; // never

映射类型

对象、class 在 TypeScript 对应的类型是索引类型(Index Type),那么如何对索引类型作修改呢?

答案是映射类型。

ts
type MapType<T> = {
+  [key in keyof T]?: T[key];
+};

keyof T 是查询索引类型中所有的索引,叫做索引查询。

T[Key] 是取索引类型某个索引的值,叫做索引访问。

in 是用于遍历联合类型的运算符。

比如我们把一个索引类型的值变成 3 个元素的数组:

ts
type MapToArray<T> = {
+  [key in keyof T]: [T[key], T[key], T[key]];
+};
+
+// example:
+
+type res = MapToArray<{ a: 1; b: 2 }>;
+// type res = {
+//     a:[1,1,1]
+//     b:[2,2,2]
+// }

映射类型就相当于把一个集合映射到另一个集合,这是它名字的由来。

除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。

ts
type MapTypeFixKey<T> = {
+  [key in keyof T as \`\${key & string}\${key & string}\${key & string}\`]: [T[key], T[key], T[key]];
+};
+// example:
+
+type res = MapToArray<{ a: 1; b: 2 }>;
+// type res = {
+//     aaa:[1,1,1]
+//     bbb:[2,2,2]
+// }

这里的 & string 可能大家会迷惑,解释一下:

因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是 string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型会把同一类型做合并,不同类型舍弃。

因为 js 处理对象比较多,所以索引类型的映射比较重要。

`,35)]))}const E=i(n,[["render",p]]);export{g as __pageData,E as default}; diff --git "a/assets/cn_src_types_\347\261\273\345\236\213\350\277\220\347\256\227.md.y4F25ckq.lean.js" "b/assets/cn_src_types_\347\261\273\345\236\213\350\277\220\347\256\227.md.y4F25ckq.lean.js" new file mode 100644 index 0000000000..dfd115c982 --- /dev/null +++ "b/assets/cn_src_types_\347\261\273\345\236\213\350\277\220\347\256\227.md.y4F25ckq.lean.js" @@ -0,0 +1,27 @@ +import{_ as i,o as a,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"TypeScript 类型系统中的类型运算","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/types/类型运算.md","filePath":"cn/src/types/类型运算.md","lastUpdated":1726550590000}'),n={name:"cn/src/types/类型运算.md"};function p(t,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k(`

TypeScript 类型系统中的类型运算

条件:extends ? :

TypeScript 里的条件判断是 extends ? :,叫做条件类型(Conditional Type)比如:

ts
type isTwo<T> = T extends 2 ? true : false;
+
+type res = isTwo<1>; // true
+type res2 = isTwo<2>; // false

这种类型也叫做高级类型。

高级类型的特点是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

推导:infer

如何提取类型的一部分呢?答案是 infer。

比如提取元组类型的第一个元素:

ts
type FirstTupleItem<Tuple extends unknown[]> = Tuple extends [infer T, ...inter R] ? T : never;
+
+type res = First<[1,2,3]> // 1

注意,第一个 extends 不是条件,条件类型是 extends ? :,这里的 extends 是约束的意思,也就是约束类型参数只能是数组类型。

因为不知道数组元素的具体类型,所以用 unknown。

联合:|

联合类型(Union)类似 js 里的或运算符 |,但是作用于类型,代表类型可以是几个类型之一。

ts
type Union = 1 | 2 | 3;

交叉:&

交叉类型(Intersection)类似 js 中的与运算符 &,但是作用于类型,代表对类型做合并。

ts
type ObjType = { a: number } & { c: boolean };

注意,同一类型可以合并,不同的类型没法合并,会被舍弃:

ts
type res = 'a' & 2; // never

映射类型

对象、class 在 TypeScript 对应的类型是索引类型(Index Type),那么如何对索引类型作修改呢?

答案是映射类型。

ts
type MapType<T> = {
+  [key in keyof T]?: T[key];
+};

keyof T 是查询索引类型中所有的索引,叫做索引查询。

T[Key] 是取索引类型某个索引的值,叫做索引访问。

in 是用于遍历联合类型的运算符。

比如我们把一个索引类型的值变成 3 个元素的数组:

ts
type MapToArray<T> = {
+  [key in keyof T]: [T[key], T[key], T[key]];
+};
+
+// example:
+
+type res = MapToArray<{ a: 1; b: 2 }>;
+// type res = {
+//     a:[1,1,1]
+//     b:[2,2,2]
+// }

映射类型就相当于把一个集合映射到另一个集合,这是它名字的由来。

除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。

ts
type MapTypeFixKey<T> = {
+  [key in keyof T as \`\${key & string}\${key & string}\${key & string}\`]: [T[key], T[key], T[key]];
+};
+// example:
+
+type res = MapToArray<{ a: 1; b: 2 }>;
+// type res = {
+//     aaa:[1,1,1]
+//     bbb:[2,2,2]
+// }

这里的 & string 可能大家会迷惑,解释一下:

因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是 string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型会把同一类型做合并,不同类型舍弃。

因为 js 处理对象比较多,所以索引类型的映射比较重要。

`,35)]))}const E=i(n,[["render",p]]);export{g as __pageData,E as default}; diff --git "a/assets/cn_src_types_\351\253\230\347\272\247\347\261\273\345\236\213.md.CjvcQW1d.js" "b/assets/cn_src_types_\351\253\230\347\272\247\347\261\273\345\236\213.md.CjvcQW1d.js" new file mode 100644 index 0000000000..a95aacedd2 --- /dev/null +++ "b/assets/cn_src_types_\351\253\230\347\272\247\347\261\273\345\236\213.md.CjvcQW1d.js" @@ -0,0 +1 @@ +import{_ as e,o as r,c as t,a3 as i}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"TypeScript 内置的高级类型","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/types/高级类型.md","filePath":"cn/src/types/高级类型.md","lastUpdated":1726550590000}'),o={name:"cn/src/types/高级类型.md"};function l(n,a,h,c,s,d){return r(),t("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

TypeScript 内置的高级类型

Parameters

Parameters 用于提取函数类型的参数类型。

ReturnType

ReturnType 用于提取函数类型的返回值类型。

ConstructorParameters

构造器类型和函数类型的区别就是可以被 new。

Parameters 用于提取函数参数的类型,而 ConstructorParameters 用于提取构造器参数的类型。

InstanceType

提取了构造器参数的类型,自然也可以提取构造器返回值的类型,就是 InstanceType。

ThisParameterType

OmitThisParameter

Partial

Required

Readonly

Pick

Record

Exclude

Extract

Omit

Awaited

NonNullable

Uppercase

Lowercase

Capitalize

Uncapitalize

总结

比如用模式匹配可以实现:Parameters、ReturnType、ConstructorParameters、InstanceType、ThisParameterType。

用模式匹配 + 重新构造可以实现:OmitThisParameter

用重新构造可以实现:Partial、Required、Readonly、Pick、Record

用模式匹配 + 递归可以实现: Awaited

用联合类型在分布式条件类型的特性可以实现: Exclude

此外还有 NonNullable 和四个编译器内部实现的类型:Uppercase、Lowercase、Capitalize、Uncapitalize。

',33)]))}const m=e(o,[["render",l]]);export{u as __pageData,m as default}; diff --git "a/assets/cn_src_types_\351\253\230\347\272\247\347\261\273\345\236\213.md.CjvcQW1d.lean.js" "b/assets/cn_src_types_\351\253\230\347\272\247\347\261\273\345\236\213.md.CjvcQW1d.lean.js" new file mode 100644 index 0000000000..a95aacedd2 --- /dev/null +++ "b/assets/cn_src_types_\351\253\230\347\272\247\347\261\273\345\236\213.md.CjvcQW1d.lean.js" @@ -0,0 +1 @@ +import{_ as e,o as r,c as t,a3 as i}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"TypeScript 内置的高级类型","description":"","frontmatter":{},"headers":[],"relativePath":"cn/src/types/高级类型.md","filePath":"cn/src/types/高级类型.md","lastUpdated":1726550590000}'),o={name:"cn/src/types/高级类型.md"};function l(n,a,h,c,s,d){return r(),t("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

TypeScript 内置的高级类型

Parameters

Parameters 用于提取函数类型的参数类型。

ReturnType

ReturnType 用于提取函数类型的返回值类型。

ConstructorParameters

构造器类型和函数类型的区别就是可以被 new。

Parameters 用于提取函数参数的类型,而 ConstructorParameters 用于提取构造器参数的类型。

InstanceType

提取了构造器参数的类型,自然也可以提取构造器返回值的类型,就是 InstanceType。

ThisParameterType

OmitThisParameter

Partial

Required

Readonly

Pick

Record

Exclude

Extract

Omit

Awaited

NonNullable

Uppercase

Lowercase

Capitalize

Uncapitalize

总结

比如用模式匹配可以实现:Parameters、ReturnType、ConstructorParameters、InstanceType、ThisParameterType。

用模式匹配 + 重新构造可以实现:OmitThisParameter

用重新构造可以实现:Partial、Required、Readonly、Pick、Record

用模式匹配 + 递归可以实现: Awaited

用联合类型在分布式条件类型的特性可以实现: Exclude

此外还有 NonNullable 和四个编译器内部实现的类型:Uppercase、Lowercase、Capitalize、Uncapitalize。

',33)]))}const m=e(o,[["render",l]]);export{u as __pageData,m as default}; diff --git a/assets/complexity.DSLVsjHt.png b/assets/complexity.DSLVsjHt.png new file mode 100644 index 0000000000..1027e76324 Binary files /dev/null and b/assets/complexity.DSLVsjHt.png differ diff --git a/assets/count.CWSWBe_h.gif b/assets/count.CWSWBe_h.gif new file mode 100644 index 0000000000..2479350321 Binary files /dev/null and b/assets/count.CWSWBe_h.gif differ diff --git a/assets/customElements.DbqgaaNb.png b/assets/customElements.DbqgaaNb.png new file mode 100644 index 0000000000..77e68a968d Binary files /dev/null and b/assets/customElements.DbqgaaNb.png differ diff --git a/assets/export.ne8l5ppO.jpeg b/assets/export.ne8l5ppO.jpeg new file mode 100644 index 0000000000..3f0099d806 Binary files /dev/null and b/assets/export.ne8l5ppO.jpeg differ diff --git a/assets/extra.Da45cF33.jpeg b/assets/extra.Da45cF33.jpeg new file mode 100644 index 0000000000..58e8955cfc Binary files /dev/null and b/assets/extra.Da45cF33.jpeg differ diff --git a/assets/firefox_pdf.BWQR-ogn.webp b/assets/firefox_pdf.BWQR-ogn.webp new file mode 100644 index 0000000000..0e88d14b7b Binary files /dev/null and b/assets/firefox_pdf.BWQR-ogn.webp differ diff --git a/assets/firefox_support_media.BLmSeBNy.webp b/assets/firefox_support_media.BLmSeBNy.webp new file mode 100644 index 0000000000..f9ac109d03 Binary files /dev/null and b/assets/firefox_support_media.BLmSeBNy.webp differ diff --git a/assets/google_doc_view.BknjnOKw.webp b/assets/google_doc_view.BknjnOKw.webp new file mode 100644 index 0000000000..1110e795dd Binary files /dev/null and b/assets/google_doc_view.BknjnOKw.webp differ diff --git a/assets/heap.D4myjC6C.gif b/assets/heap.D4myjC6C.gif new file mode 100644 index 0000000000..31cc0f6a38 Binary files /dev/null and b/assets/heap.D4myjC6C.gif differ diff --git a/assets/import.BTsVI5Tc.jpeg b/assets/import.BTsVI5Tc.jpeg new file mode 100644 index 0000000000..7e0c175712 Binary files /dev/null and b/assets/import.BTsVI5Tc.jpeg differ diff --git a/assets/index.md.DiiJHNTD.js b/assets/index.md.DiiJHNTD.js new file mode 100644 index 0000000000..fd8e1e9128 --- /dev/null +++ b/assets/index.md.DiiJHNTD.js @@ -0,0 +1 @@ +import{_ as t,o as e,c as a}from"./chunks/framework.C-ai2y4t.js";const h=JSON.parse(`{"title":"Home","description":"","frontmatter":{"layout":"home","title":"Home","hero":{"name":"ran","tagline":"A Troupe of little vagrants of the world , leave your footprints in my words .","image":{"src":"/home.svg","alt":"logo"},"actions":[{"theme":"brand","text":"Thanks to star","link":"https://github.com/chaxus/ran"},{"theme":"alt","text":"Visit my GitHub","link":"https://github.com/chaxus/ran"}]},"features":[{"icon":"⚡️","title":"record","details":"Every journey has its final day."},{"icon":"🛠️","title":"solve","details":"If you can't measure it, you can't improve it."},{"icon":"🖖","title":"share","details":"If you want to go fast, go alone. If you want to go far, go together."}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1726550590000}`),o={name:"index.md"};function i(n,r,s,l,c,d){return e(),a("div")}const u=t(o,[["render",i]]);export{h as __pageData,u as default}; diff --git a/assets/index.md.DiiJHNTD.lean.js b/assets/index.md.DiiJHNTD.lean.js new file mode 100644 index 0000000000..fd8e1e9128 --- /dev/null +++ b/assets/index.md.DiiJHNTD.lean.js @@ -0,0 +1 @@ +import{_ as t,o as e,c as a}from"./chunks/framework.C-ai2y4t.js";const h=JSON.parse(`{"title":"Home","description":"","frontmatter":{"layout":"home","title":"Home","hero":{"name":"ran","tagline":"A Troupe of little vagrants of the world , leave your footprints in my words .","image":{"src":"/home.svg","alt":"logo"},"actions":[{"theme":"brand","text":"Thanks to star","link":"https://github.com/chaxus/ran"},{"theme":"alt","text":"Visit my GitHub","link":"https://github.com/chaxus/ran"}]},"features":[{"icon":"⚡️","title":"record","details":"Every journey has its final day."},{"icon":"🛠️","title":"solve","details":"If you can't measure it, you can't improve it."},{"icon":"🖖","title":"share","details":"If you want to go fast, go alone. If you want to go far, go together."}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1726550590000}`),o={name:"index.md"};function i(n,r,s,l,c,d){return e(),a("div")}const u=t(o,[["render",i]]);export{h as __pageData,u as default}; diff --git a/assets/input-input.1X1aE5oH.jpg b/assets/input-input.1X1aE5oH.jpg new file mode 100644 index 0000000000..9871c7cfd8 Binary files /dev/null and b/assets/input-input.1X1aE5oH.jpg differ diff --git a/assets/insert.gf3GhDvq.gif b/assets/insert.gf3GhDvq.gif new file mode 100644 index 0000000000..bab6db57b6 Binary files /dev/null and b/assets/insert.gf3GhDvq.gif differ diff --git a/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 b/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 new file mode 100644 index 0000000000..b6b603d596 Binary files /dev/null and b/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 differ diff --git a/assets/inter-italic-cyrillic.By2_1cv3.woff2 b/assets/inter-italic-cyrillic.By2_1cv3.woff2 new file mode 100644 index 0000000000..def40a4f65 Binary files /dev/null and b/assets/inter-italic-cyrillic.By2_1cv3.woff2 differ diff --git a/assets/inter-italic-greek-ext.1u6EdAuj.woff2 b/assets/inter-italic-greek-ext.1u6EdAuj.woff2 new file mode 100644 index 0000000000..e070c3d309 Binary files /dev/null and b/assets/inter-italic-greek-ext.1u6EdAuj.woff2 differ diff --git a/assets/inter-italic-greek.DJ8dCoTZ.woff2 b/assets/inter-italic-greek.DJ8dCoTZ.woff2 new file mode 100644 index 0000000000..a3c16ca40b Binary files /dev/null and b/assets/inter-italic-greek.DJ8dCoTZ.woff2 differ diff --git a/assets/inter-italic-latin-ext.CN1xVJS-.woff2 b/assets/inter-italic-latin-ext.CN1xVJS-.woff2 new file mode 100644 index 0000000000..2210a899ed Binary files /dev/null and b/assets/inter-italic-latin-ext.CN1xVJS-.woff2 differ diff --git a/assets/inter-italic-latin.C2AdPX0b.woff2 b/assets/inter-italic-latin.C2AdPX0b.woff2 new file mode 100644 index 0000000000..790d62dc7b Binary files /dev/null and b/assets/inter-italic-latin.C2AdPX0b.woff2 differ diff --git a/assets/inter-italic-vietnamese.BSbpV94h.woff2 b/assets/inter-italic-vietnamese.BSbpV94h.woff2 new file mode 100644 index 0000000000..1eec0775a6 Binary files /dev/null and b/assets/inter-italic-vietnamese.BSbpV94h.woff2 differ diff --git a/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 b/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 new file mode 100644 index 0000000000..2cfe61536e Binary files /dev/null and b/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 differ diff --git a/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 b/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 new file mode 100644 index 0000000000..e3886dd141 Binary files /dev/null and b/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 differ diff --git a/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 b/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 new file mode 100644 index 0000000000..36d67487dc Binary files /dev/null and b/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 differ diff --git a/assets/inter-roman-greek.BBVDIX6e.woff2 b/assets/inter-roman-greek.BBVDIX6e.woff2 new file mode 100644 index 0000000000..2bed1e85e8 Binary files /dev/null and b/assets/inter-roman-greek.BBVDIX6e.woff2 differ diff --git a/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 b/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 new file mode 100644 index 0000000000..9a8d1e2b5e Binary files /dev/null and b/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 differ diff --git a/assets/inter-roman-latin.Di8DUHzh.woff2 b/assets/inter-roman-latin.Di8DUHzh.woff2 new file mode 100644 index 0000000000..07d3c53aef Binary files /dev/null and b/assets/inter-roman-latin.Di8DUHzh.woff2 differ diff --git a/assets/inter-roman-vietnamese.BjW4sHH5.woff2 b/assets/inter-roman-vietnamese.BjW4sHH5.woff2 new file mode 100644 index 0000000000..57bdc22ae8 Binary files /dev/null and b/assets/inter-roman-vietnamese.BjW4sHH5.woff2 differ diff --git a/assets/kkfile.X1tAqvNa.webp b/assets/kkfile.X1tAqvNa.webp new file mode 100644 index 0000000000..81fbbb5beb Binary files /dev/null and b/assets/kkfile.X1tAqvNa.webp differ diff --git a/assets/kkfile_des.CENUMtpY.webp b/assets/kkfile_des.CENUMtpY.webp new file mode 100644 index 0000000000..be09d2c3da Binary files /dev/null and b/assets/kkfile_des.CENUMtpY.webp differ diff --git a/assets/kkfile_doc.CPfEUxoD.webp b/assets/kkfile_doc.CPfEUxoD.webp new file mode 100644 index 0000000000..d962f41bec Binary files /dev/null and b/assets/kkfile_doc.CPfEUxoD.webp differ diff --git a/assets/kkfile_output.DD8iZdbo.webp b/assets/kkfile_output.DD8iZdbo.webp new file mode 100644 index 0000000000..45b774e157 Binary files /dev/null and b/assets/kkfile_output.DD8iZdbo.webp differ diff --git a/assets/mdn_pdf.DbNmeC8H.webp b/assets/mdn_pdf.DbNmeC8H.webp new file mode 100644 index 0000000000..6ba803f486 Binary files /dev/null and b/assets/mdn_pdf.DbNmeC8H.webp differ diff --git a/assets/merge.Bguw-KQu.gif b/assets/merge.Bguw-KQu.gif new file mode 100644 index 0000000000..a29ca19d02 Binary files /dev/null and b/assets/merge.Bguw-KQu.gif differ diff --git a/assets/ms_answer.Cgv6ylFF.webp b/assets/ms_answer.Cgv6ylFF.webp new file mode 100644 index 0000000000..2d92dabee5 Binary files /dev/null and b/assets/ms_answer.Cgv6ylFF.webp differ diff --git a/assets/ms_answer_2.D-D9H1v0.webp b/assets/ms_answer_2.D-D9H1v0.webp new file mode 100644 index 0000000000..c0ce5e59ef Binary files /dev/null and b/assets/ms_answer_2.D-D9H1v0.webp differ diff --git a/assets/ms_excel.CJXFi2bf.webp b/assets/ms_excel.CJXFi2bf.webp new file mode 100644 index 0000000000..dd29ef3d99 Binary files /dev/null and b/assets/ms_excel.CJXFi2bf.webp differ diff --git a/assets/ms_file_not.DgOrkG3n.webp b/assets/ms_file_not.DgOrkG3n.webp new file mode 100644 index 0000000000..a3912844dd Binary files /dev/null and b/assets/ms_file_not.DgOrkG3n.webp differ diff --git a/assets/ms_ppt.C2zYd_IC.webp b/assets/ms_ppt.C2zYd_IC.webp new file mode 100644 index 0000000000..d3a443daf1 Binary files /dev/null and b/assets/ms_ppt.C2zYd_IC.webp differ diff --git a/assets/ms_support.CaZSSiRt.webp b/assets/ms_support.CaZSSiRt.webp new file mode 100644 index 0000000000..fa495ed3a0 Binary files /dev/null and b/assets/ms_support.CaZSSiRt.webp differ diff --git a/assets/ms_word.3k-0mjp0.webp b/assets/ms_word.3k-0mjp0.webp new file mode 100644 index 0000000000..5b04c96c62 Binary files /dev/null and b/assets/ms_word.3k-0mjp0.webp differ diff --git a/assets/ow365.CXWyYekS.webp b/assets/ow365.CXWyYekS.webp new file mode 100644 index 0000000000..80d5400e2c Binary files /dev/null and b/assets/ow365.CXWyYekS.webp differ diff --git a/assets/quick.DD28bswc.gif b/assets/quick.DD28bswc.gif new file mode 100644 index 0000000000..ad88d35762 Binary files /dev/null and b/assets/quick.DD28bswc.gif differ diff --git a/assets/radix.Bwrylu8F.gif b/assets/radix.Bwrylu8F.gif new file mode 100644 index 0000000000..2a556955a1 Binary files /dev/null and b/assets/radix.Bwrylu8F.gif differ diff --git a/assets/red_book.DiBEvryP.webp b/assets/red_book.DiBEvryP.webp new file mode 100644 index 0000000000..aa853cceba Binary files /dev/null and b/assets/red_book.DiBEvryP.webp differ diff --git a/assets/rplayer_demo.CoJ7kuJt.webp b/assets/rplayer_demo.CoJ7kuJt.webp new file mode 100644 index 0000000000..e218fcb29a Binary files /dev/null and b/assets/rplayer_demo.CoJ7kuJt.webp differ diff --git a/assets/safari_support_media.Bafr23bR.webp b/assets/safari_support_media.Bafr23bR.webp new file mode 100644 index 0000000000..dcd17e58bc Binary files /dev/null and b/assets/safari_support_media.Bafr23bR.webp differ diff --git a/assets/select.B8GwndZy.gif b/assets/select.B8GwndZy.gif new file mode 100644 index 0000000000..353459bc67 Binary files /dev/null and b/assets/select.B8GwndZy.gif differ diff --git a/assets/shell.CZ-z1IVg.gif b/assets/shell.CZ-z1IVg.gif new file mode 100644 index 0000000000..bbb3beacda Binary files /dev/null and b/assets/shell.CZ-z1IVg.gif differ diff --git a/assets/sort.CSVZS1AV.png b/assets/sort.CSVZS1AV.png new file mode 100644 index 0000000000..cadd6e1542 Binary files /dev/null and b/assets/sort.CSVZS1AV.png differ diff --git a/assets/src_article_astParse_tokenizer.md.BdbSK8yK.js b/assets/src_article_astParse_tokenizer.md.BdbSK8yK.js new file mode 100644 index 0000000000..d804a72b44 --- /dev/null +++ b/assets/src_article_astParse_tokenizer.md.BdbSK8yK.js @@ -0,0 +1,184 @@ +import{_ as a,a as n,b as h,c as p,d as k,e as t,f as l,g as e,h as d,i as E,j as r,k as g,l as c,m as i,n as y}from"./chunks/extra.Cu56q3CZ.js";import{_ as o,o as F,c as C,a3 as A}from"./chunks/framework.C-ai2y4t.js";const S=JSON.parse('{"title":"Abstract Syntax Tree","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/astParse/tokenizer.md","filePath":"src/article/astParse/tokenizer.md","lastUpdated":1726550590000}'),u={name:"src/article/astParse/tokenizer.md"};function D(B,s,m,b,v,T){return F(),C("div",{"data-pagefind-body":!0},s[0]||(s[0]=[A('

Abstract Syntax Tree

一.(abstract syntax tree)抽象语法树的作用

源码是一串按照语法格式来组织的字符串,人能够认识,但是计算机并不认识,想让计算机认识就要转成一种数据结构,通过不同的对象来保存不同的数据,并且按照依赖关系组织起来,这种数据结构就是抽象语法树(abstract syntax tree)。

之所以叫“抽象”语法树是因为数据结构中省略掉了一些无具体意义的分隔符比如 ; { } 等。

有了 AST,计算机就能理解源码字符串的意思,而理解是能够转换的前提,所以编译的第一步需要把源码 parseAST

转成 AST 之后就可以通过修改 AST ,分析 AST 的方式来修改和分析代码,比如 babel 就通过这种方式进行代码的转换,比如 rollupTree Shaking ,就是通过分析 AST的 导入导出语法,从而分析出没有使用的代码,进行去除。

二。常见的 AST 节点

常见的 AST 节点 AST 是对源码的抽象,字面量、标识符、表达式、语句、模块语法、class 语法都有各自的 AST。

我们分别来了解一下:

Literal

Literal 是字面量的意思,比如 let name = 'value'中,'value'就是一个字符串字面量 StringLiteral,相应的还有数字字面量 NumericLiteral,布尔字面量 BooleanLiteral,字符串字面量 StringLiteral,正则表达式字面量 RegExpLiteral 等。

下面这些字面量都有对应的 Literal 节点:

代码中的字面量很多,babel 就是通过 xxLiteral 来抽象这部分内容的。

Identifier

Identifer 是标识符的意思,变量名、属性名、参数名等各种声明和引用的名字,都是Identifer

我们知道, JS 中的标识符只能包含字母或数字或下划线 (“_”) 或美元符号 (“$”) ,且不能以数字开头。这是 Identifier 的词法特点。

尝试分析一下,下面这一段代码里面有多少 Identifier 呢?

js
const name = 'value';
+
+function say(name) {
+  console.log(name);
+}
+
+const obj = {
+  name: 'guang',
+};

答案是这些

Statement

statement 是语句,它是可以独立执行的单位,比如 break、continue、debugger、return 或者 if 语句、while 语句、for 语句,还有声明语句,表达式语句等。我们写的每一条可以独立执行的代码都是语句。

语句末尾一般会加一个分号分隔,或者用换行分隔。

下面这些我们经常写的代码,每一行都是一个 Statement

js
break;
+continue;
+return;
+debugger;
+throw Error();
+{}
+try {} catch(e) {} finally{}
+for (let key in obj) {}
+for (let i = 0;i < 10;i ++) {}
+while (true) {}
+do {} while (true)
+switch (v){case 1: break;default:;}
+label: console.log();
+with (a){}

它们对应的 AST 节点如下图所示:

语句是代码执行的最小单位,可以说,代码是由语句 (Statement) 构成的。

Declaration

声明语句是一种特殊的语句,它执行的逻辑是在作用域内声明一个变量、函数、 class、import、export 等。

比如下面这些语句都是声明语句:

js
const a = 1;
+function b() {}
+class C {}
+
+import d from 'e';
+
+export default e = 1;
+export { e };
+export * from 'e';

它们对应的 AST 节点如下图:

声明语句用于定义变量,这也是代码中一个基础组成部分。

Expression

expression 是表达式,特点是执行完以后有返回值,这是和语句 (statement) 的区别。

下面是一些常见的表达式

js
[1,2,3]
+a = 1
+1 + 2;
+-1;
+function(){};
+() => {};
+class{};
+a;
+this;
+super;
+a::b;

它们对应的 AST 如图:

细心的同学可能会问 identifiersuper 怎么也是表达式呢?

因为 identifier、super 有返回值,符合表达式的特点,所以也是 expression

我们判断 AST 节点是不是某种类型要看它是不是符合该种类型的特点,比如语句的特点是能够单独执行,表达式的特点是有返回值。

有的表达式可以单独执行,符合语句的特点,所以也是语句,比如赋值表达式、数组表达式等。

js
a = 1;
+[1, 2, 3];

但有的表达式不能单独执行,需要和其他类型的节点组合在一起构成语句。

比如匿名函数表达式和匿名 class 表达式单独执行会报错:

js
function(){};
+class{}

需要和其他部分一起构成一条语句,比如组成赋值语句:

js
a = function () {};
+b = class {};

这条赋值语句对应的 AST 是这样的:

你会发现赋值语句的 AST 节点 AssignmentExpression 包裹了一层 ExpressionStatement 的节点,代表这个表达式是被当成语句执行的。

Class

class 的语法也有专门的 AST 节点来表示。

整个 class 的内容是 ClassBody ,属性是 ClassProperty ,方法是 ClassMethod (通过 kind 属性来区分是 constructor 还是 method )。

比如下面的代码

js
class Guang extends Person {
+  name = 'guang';
+  constructor() {}
+  eat() {}
+}

对应的 AST 是这样的

classes next 的语法, babel 中有专门的 AST 来表示它的内容。

Modules

es module 是语法级别的模块规范,所以也有专门的 AST 节点。

importimport 有 3 种语法:

named import

js
import { c, d } from 'c';

default import

js
import a from 'a';

namespaced import:

js
import * as b from 'b';

这 3 种语法都对应 ImportDeclaration 节点,但是 specifiers 属性不同,分别对应 ImportSpicifier 、ImportDefaultSpecifier 、ImportNamespaceSpcifier

图中黄框标出的就是 specifier 部分。可以直观的看出整体结构相同,只是 specifier 部分不同,所以 import 语法的 AST 的结构是 ImportDeclaration 包含着各种 import specifier

exportexport 也有 3 种语法:

named export

js
export { b, d };

default export

js
export default a;

all export

js
export * from 'c';

分别对应 ExportNamedDeclaration 、ExportDefaultDeclaration 、ExportAllDeclarationAST

比如这三种 export

js
export { b, d };
+export default a;
+export * from 'c';

对应的 AST 节点为

Program & Directive

program 是代表整个程序的节点,它有 body 属性代表程序体,存放 statement 数组,就是具体执行的语句的集合。还有 directives 属性,存放 Directive 节点,比如 "use strict" 这种指令会使用 Directive 节点表示。

Program 是包裹具体执行语句的节点,而 Directive 则是代码中的指令部分。

File & Comment

babelAST 最外层节点是 File ,它有 programcommentstokens 等属性,分别存放 Program 程序体、注释、 token 等,是最外层节点。

注释分为块注释和行内注释,对应 CommentBlockCommentLine 节点。

上面 6 种就是常见的一些 AST 节点类型, babel 就是通过这些节点来抽象源码中不同的部分。

AST 可视化查看工具

这么多 AST 我们都要记住么?

不需要。可以通过 axtexplorer.net 这个网站来可视化的查看。

这个网站可以查看代码 parse 以后的 AST ,可以切换 parse 的语言和用的 parser ,也可以修改 parse options

点击这里的 save 就可以保存下来,然后把 url 分享出去:

比如这个链接:https://astexplorer.net/

如果想查看全部的 AST 可以在 babel parser 仓库里的 AST 文档里查,或者直接去看 @babel/typestypescript 类型定义。

AST 的公共属性

每种 AST 都有自己的属性,但是它们也有一些公共的属性:

typeAST 节点的类型

startendloc:startend 代表该节点在源码中的开始和结束下标。而 loc 属性是一个对象,有 linecolumn 属性分别记录开始和结束的行列号。

leadingCommentsinnerCommentstrailingComments :表示开始的注释、中间的注释、结尾的注释,每个 AST 节点中都可能存在注释,而且可能在开始、中间、结束这三种位置,想拿到某个 AST 的注释就通过这三个属性。

比如这段有注释的代码的 AST

extra:记录一些额外的信息,用于处理一些特殊情况。比如 StringLiteralvalue 只是值的修改,而修改 extra.raw 则可以连同单双引号一起修改。 比如这段代码的 AST

修改 value 只能修改值,修改 extra.raw 可以连引号一起修改。

总结

了解了这些节点,就能知道平时写的代码是怎么用 AST 表示的。

当然也不需要记,可以用 (astexpoler.net) 可视化的查看。

AST 节点可能同时有多种类型,确定一种 AST 节点是什么类型主要看它的特点,比如 Statement 的特点是可以单独执行, Expression 的特点是有返回值,所以一些可以单独执行的 Expression 会包一层 ExpressionStatement

不同 AST 节点有不同的属性来存放对应的源码信息,但是都有一些公共属性如 type 、xxCommentsloc 等。

学会了 AST ,就可以把对代码的操作转为对 AST 的操作了,这是编译、静态分析的第一步。

三。编写词法分析器(Tokenizer)

词法分析器,也叫分词器 (Tokenizer),它的作用是将代码划分为一个个词法单元,便于进行后续的语法分析。比如下面的这段代码:

js
let foo = function () {};

在经过分词之后,代码会被切分为如下的 token 数组:

js
['let', 'foo', '=', 'function', '(', ')', '{', '}'];

从中你可以看到,原本一行普通的代码字符串被拆分成了拥有语法属性的 token 列表,不同的 token 之间也存在千丝万缕的联系,而后面所要介绍的语法分析器,就是来梳理各个 token 之间的联系,整理出 AST 数据结构。

当下我们所要实现的词法分析器,本质上是对代码字符串进行逐个字符的扫描,然后根据一定的语法规则进行分组。其中,涉及到几个关键的步骤:

  1. 确定语法规则,包括语言内置的关键词、单字符、分隔符等
  2. 逐个代码字符扫描,根据语法规则进行 token 分组

1. 确定 Token 的类型和规则

增加 Token 的类型

ts
export enum TokenType {
+  // let
+  Let = 'Let',
+  // =
+  Assign = 'Assign',
+  // function
+  Function = 'Function',
+  // 变量名
+  Identifier = 'Identifier',
+  // (
+  LeftParen = 'LeftParen',
+  // )
+  RightParen = 'RightParen',
+  // {
+  LeftCurly = 'LeftCurly',
+  // }
+  RightCurly = 'RightCurly',
+}
+
+export type Token = {
+  type: TokenType;
+  value?: string;
+  start: number;
+  end: number;
+  raw?: string;
+};

定义 Token 类型到规则的映射

ts
const TOKENS_GENERATOR: Record<string, (...args: any[]) => Token> = {
+  let(start: number) {
+    return { type: TokenType.Let, value: 'let', start, end: start + 3 };
+  },
+  assign(start: number) {
+    return { type: TokenType.Assign, value: '=', start, end: start + 1 };
+  },
+  function(start: number) {
+    return {
+      type: TokenType.Function,
+      value: 'function',
+      start,
+      end: start + 8,
+    };
+  },
+  leftParen(start: number) {
+    return { type: TokenType.LeftParen, value: '(', start, end: start + 1 };
+  },
+  rightParen(start: number) {
+    return { type: TokenType.RightParen, value: ')', start, end: start + 1 };
+  },
+  leftCurly(start: number) {
+    return { type: TokenType.LeftCurly, value: '{', start, end: start + 1 };
+  },
+  rightCurly(start: number) {
+    return { type: TokenType.RightCurly, value: '}', start, end: start + 1 };
+  },
+  identifier(start: number, value: string) {
+    return {
+      type: TokenType.Identifier,
+      value,
+      start,
+      end: start + value.length,
+    };
+  },
+};
+
+type SingleCharTokens = '(' | ')' | '{' | '}' | '=';
+
+// 单字符到 Token 生成器的映射
+const KNOWN_SINGLE_CHAR_TOKENS = new Map<SingleCharTokens, (typeof TOKENS_GENERATOR)[keyof typeof TOKENS_GENERATOR]>([
+  ['(', TOKENS_GENERATOR.leftParen],
+  [')', TOKENS_GENERATOR.rightParen],
+  ['{', TOKENS_GENERATOR.leftCurly],
+  ['}', TOKENS_GENERATOR.rightCurly],
+  ['=', TOKENS_GENERATOR.assign],
+]);

有了 Token 类型和对应生成的规则,我们便可以去遍历分析代码,输出分析后的结果。

2.代码字符扫描

在扫描字符的过程,我们需要对不同的字符各自进行不同的处理,具体的策略如下:

  • 当前字符为分隔符,如空格,直接跳过,不处理;
  • 当前字符为字母,需要继续扫描,获取完整的单词:
    • 如果单词为语法关键字,则新建相应关键字的 Token
    • 否则视为普通的变量名
  • 当前字符为单字符,如{、}、(、),则新建单字符对应的 Token
ts
export class Tokenizer {
+  private _tokens: Token[] = [];
+  private _currentIndex: number = 0;
+  private _source: string;
+  constructor(input: string) {
+    this._source = input;
+  }
+  tokenize(): Token[] {
+    while (this._currentIndex < this._source.length) {
+      let currentChar = this._source[this._currentIndex];
+      const startIndex = this._currentIndex;
+
+      // 根据语法规则进行 token 分组
+      // while 循环内部
+      let currentChar = this._source[this._currentIndex];
+      const startIndex = this._currentIndex;
+
+      const isAlpha = (char: string): boolean => {
+        return (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z');
+      };
+
+      // 1. 处理空格
+      if (currentChar === ' ') {
+        this._currentIndex++;
+        continue;
+      }
+      // 2. 处理字母
+      else if (isAlpha(currentChar)) {
+        let identifier = '';
+        while (isAlpha(currentChar)) {
+          identifier += currentChar;
+          this._currentIndex++;
+          currentChar = this._source[this._currentIndex];
+        }
+        let token: Token;
+        if (identifier in TOKENS_GENERATOR) {
+          // 如果是关键字
+          token = TOKENS_GENERATOR[identifier as keyof typeof TOKENS_GENERATOR](startIndex);
+        } else {
+          // 如果是普通标识符
+          token = TOKENS_GENERATOR['identifier'](startIndex, identifier);
+        }
+        this._tokens.push(token);
+        continue;
+      }
+      // 3. 处理单字符
+      else if (KNOWN_SINGLE_CHAR_TOKENS.has(currentChar as SingleCharTokens)) {
+        const token = KNOWN_SINGLE_CHAR_TOKENS.get(currentChar as SingleCharTokens)!(startIndex);
+        this._tokens.push(token);
+        this._currentIndex++;
+        continue;
+      }
+    }
+    return this._tokens;
+  }
+}

使用方式

ts
const tokenizer = new Tokenizer('let a = function() {}');

结果

ts
const tokenizer = [
+  { type: 'Let', value: 'let', start: 0, end: 3 },
+  { type: 'Identifier', value: 'a', start: 4, end: 5 },
+  { type: 'Assign', value: '=', start: 6, end: 7 },
+  { type: 'Function', value: 'function', start: 8, end: 16 },
+  { type: 'LeftParen', value: '(', start: 16, end: 17 },
+  { type: 'RightParen', value: ')', start: 17, end: 18 },
+  { type: 'LeftCurly', value: '{', start: 19, end: 20 },
+  { type: 'RightCurly', value: '}', start: 20, end: 21 },
+];

一个简易版本的分词器已经被我们开发出来了,不过目前的分词器还比较简陋,仅仅支持有限的语法,不过在明确了核心的开发步骤之后,后面继续完善的过程就比较简单了。

四。编写语法分析器(Parser)

在解析出词法 token 之后,我们就可以进入语法分析阶段了。在这个阶段,我们会依次遍历 token ,对代码进行语法结构层面的分析,最后的目标是生成 AST 数据结构。至于代码的 AST 结构到底是什么样子,你可以去 AST Explorer 网站进行在线预览:

接下来,我们要做的就是将 token 数组转换为上图所示的 AST 数据。

开发步骤主要分为:

  • 初始化类型声明
',150)]))}const _=o(u,[["render",D]]);export{S as __pageData,_ as default}; diff --git a/assets/src_article_astParse_tokenizer.md.BdbSK8yK.lean.js b/assets/src_article_astParse_tokenizer.md.BdbSK8yK.lean.js new file mode 100644 index 0000000000..d804a72b44 --- /dev/null +++ b/assets/src_article_astParse_tokenizer.md.BdbSK8yK.lean.js @@ -0,0 +1,184 @@ +import{_ as a,a as n,b as h,c as p,d as k,e as t,f as l,g as e,h as d,i as E,j as r,k as g,l as c,m as i,n as y}from"./chunks/extra.Cu56q3CZ.js";import{_ as o,o as F,c as C,a3 as A}from"./chunks/framework.C-ai2y4t.js";const S=JSON.parse('{"title":"Abstract Syntax Tree","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/astParse/tokenizer.md","filePath":"src/article/astParse/tokenizer.md","lastUpdated":1726550590000}'),u={name:"src/article/astParse/tokenizer.md"};function D(B,s,m,b,v,T){return F(),C("div",{"data-pagefind-body":!0},s[0]||(s[0]=[A('

Abstract Syntax Tree

一.(abstract syntax tree)抽象语法树的作用

源码是一串按照语法格式来组织的字符串,人能够认识,但是计算机并不认识,想让计算机认识就要转成一种数据结构,通过不同的对象来保存不同的数据,并且按照依赖关系组织起来,这种数据结构就是抽象语法树(abstract syntax tree)。

之所以叫“抽象”语法树是因为数据结构中省略掉了一些无具体意义的分隔符比如 ; { } 等。

有了 AST,计算机就能理解源码字符串的意思,而理解是能够转换的前提,所以编译的第一步需要把源码 parseAST

转成 AST 之后就可以通过修改 AST ,分析 AST 的方式来修改和分析代码,比如 babel 就通过这种方式进行代码的转换,比如 rollupTree Shaking ,就是通过分析 AST的 导入导出语法,从而分析出没有使用的代码,进行去除。

二。常见的 AST 节点

常见的 AST 节点 AST 是对源码的抽象,字面量、标识符、表达式、语句、模块语法、class 语法都有各自的 AST。

我们分别来了解一下:

Literal

Literal 是字面量的意思,比如 let name = 'value'中,'value'就是一个字符串字面量 StringLiteral,相应的还有数字字面量 NumericLiteral,布尔字面量 BooleanLiteral,字符串字面量 StringLiteral,正则表达式字面量 RegExpLiteral 等。

下面这些字面量都有对应的 Literal 节点:

代码中的字面量很多,babel 就是通过 xxLiteral 来抽象这部分内容的。

Identifier

Identifer 是标识符的意思,变量名、属性名、参数名等各种声明和引用的名字,都是Identifer

我们知道, JS 中的标识符只能包含字母或数字或下划线 (“_”) 或美元符号 (“$”) ,且不能以数字开头。这是 Identifier 的词法特点。

尝试分析一下,下面这一段代码里面有多少 Identifier 呢?

js
const name = 'value';
+
+function say(name) {
+  console.log(name);
+}
+
+const obj = {
+  name: 'guang',
+};

答案是这些

Statement

statement 是语句,它是可以独立执行的单位,比如 break、continue、debugger、return 或者 if 语句、while 语句、for 语句,还有声明语句,表达式语句等。我们写的每一条可以独立执行的代码都是语句。

语句末尾一般会加一个分号分隔,或者用换行分隔。

下面这些我们经常写的代码,每一行都是一个 Statement

js
break;
+continue;
+return;
+debugger;
+throw Error();
+{}
+try {} catch(e) {} finally{}
+for (let key in obj) {}
+for (let i = 0;i < 10;i ++) {}
+while (true) {}
+do {} while (true)
+switch (v){case 1: break;default:;}
+label: console.log();
+with (a){}

它们对应的 AST 节点如下图所示:

语句是代码执行的最小单位,可以说,代码是由语句 (Statement) 构成的。

Declaration

声明语句是一种特殊的语句,它执行的逻辑是在作用域内声明一个变量、函数、 class、import、export 等。

比如下面这些语句都是声明语句:

js
const a = 1;
+function b() {}
+class C {}
+
+import d from 'e';
+
+export default e = 1;
+export { e };
+export * from 'e';

它们对应的 AST 节点如下图:

声明语句用于定义变量,这也是代码中一个基础组成部分。

Expression

expression 是表达式,特点是执行完以后有返回值,这是和语句 (statement) 的区别。

下面是一些常见的表达式

js
[1,2,3]
+a = 1
+1 + 2;
+-1;
+function(){};
+() => {};
+class{};
+a;
+this;
+super;
+a::b;

它们对应的 AST 如图:

细心的同学可能会问 identifiersuper 怎么也是表达式呢?

因为 identifier、super 有返回值,符合表达式的特点,所以也是 expression

我们判断 AST 节点是不是某种类型要看它是不是符合该种类型的特点,比如语句的特点是能够单独执行,表达式的特点是有返回值。

有的表达式可以单独执行,符合语句的特点,所以也是语句,比如赋值表达式、数组表达式等。

js
a = 1;
+[1, 2, 3];

但有的表达式不能单独执行,需要和其他类型的节点组合在一起构成语句。

比如匿名函数表达式和匿名 class 表达式单独执行会报错:

js
function(){};
+class{}

需要和其他部分一起构成一条语句,比如组成赋值语句:

js
a = function () {};
+b = class {};

这条赋值语句对应的 AST 是这样的:

你会发现赋值语句的 AST 节点 AssignmentExpression 包裹了一层 ExpressionStatement 的节点,代表这个表达式是被当成语句执行的。

Class

class 的语法也有专门的 AST 节点来表示。

整个 class 的内容是 ClassBody ,属性是 ClassProperty ,方法是 ClassMethod (通过 kind 属性来区分是 constructor 还是 method )。

比如下面的代码

js
class Guang extends Person {
+  name = 'guang';
+  constructor() {}
+  eat() {}
+}

对应的 AST 是这样的

classes next 的语法, babel 中有专门的 AST 来表示它的内容。

Modules

es module 是语法级别的模块规范,所以也有专门的 AST 节点。

importimport 有 3 种语法:

named import

js
import { c, d } from 'c';

default import

js
import a from 'a';

namespaced import:

js
import * as b from 'b';

这 3 种语法都对应 ImportDeclaration 节点,但是 specifiers 属性不同,分别对应 ImportSpicifier 、ImportDefaultSpecifier 、ImportNamespaceSpcifier

图中黄框标出的就是 specifier 部分。可以直观的看出整体结构相同,只是 specifier 部分不同,所以 import 语法的 AST 的结构是 ImportDeclaration 包含着各种 import specifier

exportexport 也有 3 种语法:

named export

js
export { b, d };

default export

js
export default a;

all export

js
export * from 'c';

分别对应 ExportNamedDeclaration 、ExportDefaultDeclaration 、ExportAllDeclarationAST

比如这三种 export

js
export { b, d };
+export default a;
+export * from 'c';

对应的 AST 节点为

Program & Directive

program 是代表整个程序的节点,它有 body 属性代表程序体,存放 statement 数组,就是具体执行的语句的集合。还有 directives 属性,存放 Directive 节点,比如 "use strict" 这种指令会使用 Directive 节点表示。

Program 是包裹具体执行语句的节点,而 Directive 则是代码中的指令部分。

File & Comment

babelAST 最外层节点是 File ,它有 programcommentstokens 等属性,分别存放 Program 程序体、注释、 token 等,是最外层节点。

注释分为块注释和行内注释,对应 CommentBlockCommentLine 节点。

上面 6 种就是常见的一些 AST 节点类型, babel 就是通过这些节点来抽象源码中不同的部分。

AST 可视化查看工具

这么多 AST 我们都要记住么?

不需要。可以通过 axtexplorer.net 这个网站来可视化的查看。

这个网站可以查看代码 parse 以后的 AST ,可以切换 parse 的语言和用的 parser ,也可以修改 parse options

点击这里的 save 就可以保存下来,然后把 url 分享出去:

比如这个链接:https://astexplorer.net/

如果想查看全部的 AST 可以在 babel parser 仓库里的 AST 文档里查,或者直接去看 @babel/typestypescript 类型定义。

AST 的公共属性

每种 AST 都有自己的属性,但是它们也有一些公共的属性:

typeAST 节点的类型

startendloc:startend 代表该节点在源码中的开始和结束下标。而 loc 属性是一个对象,有 linecolumn 属性分别记录开始和结束的行列号。

leadingCommentsinnerCommentstrailingComments :表示开始的注释、中间的注释、结尾的注释,每个 AST 节点中都可能存在注释,而且可能在开始、中间、结束这三种位置,想拿到某个 AST 的注释就通过这三个属性。

比如这段有注释的代码的 AST

extra:记录一些额外的信息,用于处理一些特殊情况。比如 StringLiteralvalue 只是值的修改,而修改 extra.raw 则可以连同单双引号一起修改。 比如这段代码的 AST

修改 value 只能修改值,修改 extra.raw 可以连引号一起修改。

总结

了解了这些节点,就能知道平时写的代码是怎么用 AST 表示的。

当然也不需要记,可以用 (astexpoler.net) 可视化的查看。

AST 节点可能同时有多种类型,确定一种 AST 节点是什么类型主要看它的特点,比如 Statement 的特点是可以单独执行, Expression 的特点是有返回值,所以一些可以单独执行的 Expression 会包一层 ExpressionStatement

不同 AST 节点有不同的属性来存放对应的源码信息,但是都有一些公共属性如 type 、xxCommentsloc 等。

学会了 AST ,就可以把对代码的操作转为对 AST 的操作了,这是编译、静态分析的第一步。

三。编写词法分析器(Tokenizer)

词法分析器,也叫分词器 (Tokenizer),它的作用是将代码划分为一个个词法单元,便于进行后续的语法分析。比如下面的这段代码:

js
let foo = function () {};

在经过分词之后,代码会被切分为如下的 token 数组:

js
['let', 'foo', '=', 'function', '(', ')', '{', '}'];

从中你可以看到,原本一行普通的代码字符串被拆分成了拥有语法属性的 token 列表,不同的 token 之间也存在千丝万缕的联系,而后面所要介绍的语法分析器,就是来梳理各个 token 之间的联系,整理出 AST 数据结构。

当下我们所要实现的词法分析器,本质上是对代码字符串进行逐个字符的扫描,然后根据一定的语法规则进行分组。其中,涉及到几个关键的步骤:

  1. 确定语法规则,包括语言内置的关键词、单字符、分隔符等
  2. 逐个代码字符扫描,根据语法规则进行 token 分组

1. 确定 Token 的类型和规则

增加 Token 的类型

ts
export enum TokenType {
+  // let
+  Let = 'Let',
+  // =
+  Assign = 'Assign',
+  // function
+  Function = 'Function',
+  // 变量名
+  Identifier = 'Identifier',
+  // (
+  LeftParen = 'LeftParen',
+  // )
+  RightParen = 'RightParen',
+  // {
+  LeftCurly = 'LeftCurly',
+  // }
+  RightCurly = 'RightCurly',
+}
+
+export type Token = {
+  type: TokenType;
+  value?: string;
+  start: number;
+  end: number;
+  raw?: string;
+};

定义 Token 类型到规则的映射

ts
const TOKENS_GENERATOR: Record<string, (...args: any[]) => Token> = {
+  let(start: number) {
+    return { type: TokenType.Let, value: 'let', start, end: start + 3 };
+  },
+  assign(start: number) {
+    return { type: TokenType.Assign, value: '=', start, end: start + 1 };
+  },
+  function(start: number) {
+    return {
+      type: TokenType.Function,
+      value: 'function',
+      start,
+      end: start + 8,
+    };
+  },
+  leftParen(start: number) {
+    return { type: TokenType.LeftParen, value: '(', start, end: start + 1 };
+  },
+  rightParen(start: number) {
+    return { type: TokenType.RightParen, value: ')', start, end: start + 1 };
+  },
+  leftCurly(start: number) {
+    return { type: TokenType.LeftCurly, value: '{', start, end: start + 1 };
+  },
+  rightCurly(start: number) {
+    return { type: TokenType.RightCurly, value: '}', start, end: start + 1 };
+  },
+  identifier(start: number, value: string) {
+    return {
+      type: TokenType.Identifier,
+      value,
+      start,
+      end: start + value.length,
+    };
+  },
+};
+
+type SingleCharTokens = '(' | ')' | '{' | '}' | '=';
+
+// 单字符到 Token 生成器的映射
+const KNOWN_SINGLE_CHAR_TOKENS = new Map<SingleCharTokens, (typeof TOKENS_GENERATOR)[keyof typeof TOKENS_GENERATOR]>([
+  ['(', TOKENS_GENERATOR.leftParen],
+  [')', TOKENS_GENERATOR.rightParen],
+  ['{', TOKENS_GENERATOR.leftCurly],
+  ['}', TOKENS_GENERATOR.rightCurly],
+  ['=', TOKENS_GENERATOR.assign],
+]);

有了 Token 类型和对应生成的规则,我们便可以去遍历分析代码,输出分析后的结果。

2.代码字符扫描

在扫描字符的过程,我们需要对不同的字符各自进行不同的处理,具体的策略如下:

  • 当前字符为分隔符,如空格,直接跳过,不处理;
  • 当前字符为字母,需要继续扫描,获取完整的单词:
    • 如果单词为语法关键字,则新建相应关键字的 Token
    • 否则视为普通的变量名
  • 当前字符为单字符,如{、}、(、),则新建单字符对应的 Token
ts
export class Tokenizer {
+  private _tokens: Token[] = [];
+  private _currentIndex: number = 0;
+  private _source: string;
+  constructor(input: string) {
+    this._source = input;
+  }
+  tokenize(): Token[] {
+    while (this._currentIndex < this._source.length) {
+      let currentChar = this._source[this._currentIndex];
+      const startIndex = this._currentIndex;
+
+      // 根据语法规则进行 token 分组
+      // while 循环内部
+      let currentChar = this._source[this._currentIndex];
+      const startIndex = this._currentIndex;
+
+      const isAlpha = (char: string): boolean => {
+        return (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z');
+      };
+
+      // 1. 处理空格
+      if (currentChar === ' ') {
+        this._currentIndex++;
+        continue;
+      }
+      // 2. 处理字母
+      else if (isAlpha(currentChar)) {
+        let identifier = '';
+        while (isAlpha(currentChar)) {
+          identifier += currentChar;
+          this._currentIndex++;
+          currentChar = this._source[this._currentIndex];
+        }
+        let token: Token;
+        if (identifier in TOKENS_GENERATOR) {
+          // 如果是关键字
+          token = TOKENS_GENERATOR[identifier as keyof typeof TOKENS_GENERATOR](startIndex);
+        } else {
+          // 如果是普通标识符
+          token = TOKENS_GENERATOR['identifier'](startIndex, identifier);
+        }
+        this._tokens.push(token);
+        continue;
+      }
+      // 3. 处理单字符
+      else if (KNOWN_SINGLE_CHAR_TOKENS.has(currentChar as SingleCharTokens)) {
+        const token = KNOWN_SINGLE_CHAR_TOKENS.get(currentChar as SingleCharTokens)!(startIndex);
+        this._tokens.push(token);
+        this._currentIndex++;
+        continue;
+      }
+    }
+    return this._tokens;
+  }
+}

使用方式

ts
const tokenizer = new Tokenizer('let a = function() {}');

结果

ts
const tokenizer = [
+  { type: 'Let', value: 'let', start: 0, end: 3 },
+  { type: 'Identifier', value: 'a', start: 4, end: 5 },
+  { type: 'Assign', value: '=', start: 6, end: 7 },
+  { type: 'Function', value: 'function', start: 8, end: 16 },
+  { type: 'LeftParen', value: '(', start: 16, end: 17 },
+  { type: 'RightParen', value: ')', start: 17, end: 18 },
+  { type: 'LeftCurly', value: '{', start: 19, end: 20 },
+  { type: 'RightCurly', value: '}', start: 20, end: 21 },
+];

一个简易版本的分词器已经被我们开发出来了,不过目前的分词器还比较简陋,仅仅支持有限的语法,不过在明确了核心的开发步骤之后,后面继续完善的过程就比较简单了。

四。编写语法分析器(Parser)

在解析出词法 token 之后,我们就可以进入语法分析阶段了。在这个阶段,我们会依次遍历 token ,对代码进行语法结构层面的分析,最后的目标是生成 AST 数据结构。至于代码的 AST 结构到底是什么样子,你可以去 AST Explorer 网站进行在线预览:

接下来,我们要做的就是将 token 数组转换为上图所示的 AST 数据。

开发步骤主要分为:

  • 初始化类型声明
',150)]))}const _=o(u,[["render",D]]);export{S as __pageData,_ as default}; diff --git a/assets/src_article_babel.md.C7cpU5Uf.js b/assets/src_article_babel.md.C7cpU5Uf.js new file mode 100644 index 0000000000..5cd8c02e20 --- /dev/null +++ b/assets/src_article_babel.md.C7cpU5Uf.js @@ -0,0 +1 @@ +import{_ as a,o as t,c as l,a3 as r}from"./chunks/framework.C-ai2y4t.js";const m=JSON.parse('{"title":"Babel","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/babel.md","filePath":"src/article/babel.md","lastUpdated":1726550590000}'),i={name:"src/article/babel.md"};function s(b,e,o,p,c,n){return t(),l("div",{"data-pagefind-body":!0},e[0]||(e[0]=[r('

Babel

babel 核心库主要是:

  • @babel/parser 对源码进行 parse,可以通过 plugins、sourceType 等来指定 parse 语法,功能是把源码转成 AST。
  • @babel/traverse 通过 visitor 函数对遍历到的 ast 进行处理,分为 enter 和 exit 两个阶段,具体操作 AST 使用 path 的 api,还可以通过 state 来在遍历过程中传递一些数据
  • @babel/types 用于创建、判断 AST 节点,提供了 xxx、isXxx、assertXxx 的 api
  • @babel/template 当需要批量创建 AST 的时候可以使用 @babel/template 来简化 AST 创建逻辑。
  • @babel/code-frame 可以创建友好的报错信息
  • @babel/generator 打印 AST 成目标代码字符串,支持 comments、minified、sourceMaps 等选项。
  • @babel/core 基于上面的包来完成 babel 的编译流程,并应用 plugin 和 preset。
',3)]))}const u=a(i,[["render",s]]);export{m as __pageData,u as default}; diff --git a/assets/src_article_babel.md.C7cpU5Uf.lean.js b/assets/src_article_babel.md.C7cpU5Uf.lean.js new file mode 100644 index 0000000000..5cd8c02e20 --- /dev/null +++ b/assets/src_article_babel.md.C7cpU5Uf.lean.js @@ -0,0 +1 @@ +import{_ as a,o as t,c as l,a3 as r}from"./chunks/framework.C-ai2y4t.js";const m=JSON.parse('{"title":"Babel","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/babel.md","filePath":"src/article/babel.md","lastUpdated":1726550590000}'),i={name:"src/article/babel.md"};function s(b,e,o,p,c,n){return t(),l("div",{"data-pagefind-body":!0},e[0]||(e[0]=[r('

Babel

babel 核心库主要是:

  • @babel/parser 对源码进行 parse,可以通过 plugins、sourceType 等来指定 parse 语法,功能是把源码转成 AST。
  • @babel/traverse 通过 visitor 函数对遍历到的 ast 进行处理,分为 enter 和 exit 两个阶段,具体操作 AST 使用 path 的 api,还可以通过 state 来在遍历过程中传递一些数据
  • @babel/types 用于创建、判断 AST 节点,提供了 xxx、isXxx、assertXxx 的 api
  • @babel/template 当需要批量创建 AST 的时候可以使用 @babel/template 来简化 AST 创建逻辑。
  • @babel/code-frame 可以创建友好的报错信息
  • @babel/generator 打印 AST 成目标代码字符串,支持 comments、minified、sourceMaps 等选项。
  • @babel/core 基于上面的包来完成 babel 的编译流程,并应用 plugin 和 preset。
',3)]))}const u=a(i,[["render",s]]);export{m as __pageData,u as default}; diff --git a/assets/src_article_bundle.md.CFyB1OVU.js b/assets/src_article_bundle.md.CFyB1OVU.js new file mode 100644 index 0000000000..d8d8c70a2c --- /dev/null +++ b/assets/src_article_bundle.md.CFyB1OVU.js @@ -0,0 +1 @@ +import{_ as a,o as t,c as n,j as e,a as r}from"./chunks/framework.C-ai2y4t.js";const f=JSON.parse('{"title":"Bundle","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/bundle.md","filePath":"src/article/bundle.md","lastUpdated":1726550590000}'),d={name:"src/article/bundle.md"};function s(i,l,c,o,u,p){return t(),n("div",{"data-pagefind-body":!0},l[0]||(l[0]=[e("h1",{id:"bundle",tabindex:"-1"},[r("Bundle "),e("a",{class:"header-anchor",href:"#bundle","aria-label":'Permalink to "Bundle"'},"​")],-1),e("p",null,"Bundle 的本质就是输入,转换,输出。在机器上直接运行的代码,往往都难以维护和理解,我们需要将开发者方便理解和维护的代码,通过打包等工具转换成方便机器或者程序使用的代码。对于 web 前端来说,打包工具,至少需要以下功能:",-1),e("ul",null,[e("li",null,"编译能力"),e("li",null,"插件机制"),e("li",null,"HMR"),e("li",null,"cli 和命令行能力")],-1)]))}const m=a(d,[["render",s]]);export{f as __pageData,m as default}; diff --git a/assets/src_article_bundle.md.CFyB1OVU.lean.js b/assets/src_article_bundle.md.CFyB1OVU.lean.js new file mode 100644 index 0000000000..d8d8c70a2c --- /dev/null +++ b/assets/src_article_bundle.md.CFyB1OVU.lean.js @@ -0,0 +1 @@ +import{_ as a,o as t,c as n,j as e,a as r}from"./chunks/framework.C-ai2y4t.js";const f=JSON.parse('{"title":"Bundle","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/bundle.md","filePath":"src/article/bundle.md","lastUpdated":1726550590000}'),d={name:"src/article/bundle.md"};function s(i,l,c,o,u,p){return t(),n("div",{"data-pagefind-body":!0},l[0]||(l[0]=[e("h1",{id:"bundle",tabindex:"-1"},[r("Bundle "),e("a",{class:"header-anchor",href:"#bundle","aria-label":'Permalink to "Bundle"'},"​")],-1),e("p",null,"Bundle 的本质就是输入,转换,输出。在机器上直接运行的代码,往往都难以维护和理解,我们需要将开发者方便理解和维护的代码,通过打包等工具转换成方便机器或者程序使用的代码。对于 web 前端来说,打包工具,至少需要以下功能:",-1),e("ul",null,[e("li",null,"编译能力"),e("li",null,"插件机制"),e("li",null,"HMR"),e("li",null,"cli 和命令行能力")],-1)]))}const m=a(d,[["render",s]]);export{f as __pageData,m as default}; diff --git a/assets/src_article_designMode.md.-Ql_1mMt.js b/assets/src_article_designMode.md.-Ql_1mMt.js new file mode 100644 index 0000000000..49dd00a79c --- /dev/null +++ b/assets/src_article_designMode.md.-Ql_1mMt.js @@ -0,0 +1,743 @@ +import{_ as i,a,b as n,c as e,d as t,e as h,f as l,g as p,h as k,i as r,j as o,k as d,l as E,m as c,n as g,o as y,p as F,q as u,r as m,s as b,t as f,u as C,v as A,w as B,x as v,y as D,z as w,A as x,B as j}from"./chunks/访问者._0swtoJg.js";import{_ as q,o as P,c as T,a3 as _}from"./chunks/framework.C-ai2y4t.js";const U=JSON.parse('{"title":"23 classic design patterns","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/designMode.md","filePath":"src/article/designMode.md","lastUpdated":1726550590000}'),I={name:"src/article/designMode.md"};function S(M,s,z,L,V,W){return P(),T("div",{"data-pagefind-body":!0},s[0]||(s[0]=[_(`

23 classic design patterns

The Design Pattern is a set of frequently used, widely known, cataloged code design experiences that are used in order to reuse code, make it easier for others to understand, and ensure code reliability.

In the book "Design Patterns: The Foundation of Reusable Object-Oriented Software" introduced 23 classic design patterns, but the design pattern is not only these 23, with the development of software development industry, more and more new patterns continue to be born and applied. Experienced developers learn design patterns that can be corroborated with past experience, making it easier to understand them.

A design pattern generally contains elements such as the pattern name, problem, purpose, solution, and effect. The problem describes when patterns should be used, and it contains problems with the design and why they exist. A solution describes the components of a design pattern and how these components relate to each other, their respective responsibilities, and how they work together. Typically, the solution is described through UML class diagrams and core code. Effects describe the advantages and disadvantages of the pattern and the trade-offs that should be made when using the pattern.

Why learn design patterns:

  • Design patterns are derived from the experience and wisdom of many experts. They are successful and reusable design solutions from many excellent software systems. Using these solutions will allow us to avoid doing some repetitive work

  • Design patterns provide a common set of design vocabulary and a common form to facilitate communication and exchange between developers, making design solutions more understandable

  • Most of the design patterns take into account the reusability and extensibility of the system, which enables us to better reuse some existing design schemes, functional modules and even a complete software system, so as to avoid us often doing some repetitive design and writing some repetitive code

  • Proper use of design patterns and documentation of their use will help others understand the system more quickly

  • Learning design patterns will help beginners understand object-oriented ideas more deeply

Reserve knowledge

  • Abstract class: The general abstract class is as a base class, for example, "computer" can be used as an abstract class, according to the abstract class derived "desktop computer" and "laptop computer" 2 concrete classes. Abstract classes are generally not instantiated.

  • Combination is better than inheritance: inheritance cannot be abused to expand functionality, and combination is more flexible. Also take the "computer" abstract class for example, if we use inheritance to distinguish different types of "computer" we can derive "desktop computer" and "laptop computer", if we add another dimension, according to the brand can continue to subdivide "Lenovo desktop computer", "Lenovo laptop", "Apple desktop computer" and "Apple laptop" and so on. If you add another dimension and continue to subdivide, it is clear that inheritance is not adequate. At this time, you can use inheritance and composition, and the combined object can also be abstract design:

    ts
    interface Brand {
    +  // ...
    +}
    +interface Lenovo extends Brand {
    +  // ...
    +}
    +interface Apple extends Brand {
    +  // ...
    +}
    +interface CPU {
    +  // ...
    +}
    +interface Inter extends CPU {
    +  // ...
    +}
    +interface AMD extends CPU {
    +  // ...
    +}
    +interface Computer {
    +  // ...
    +}
    +
    +interface DesktopComputer extends Computer {}
    +interface NotebookComputer extends Computer {}

I, UML class diagram

Each pattern has a corresponding object structure diagram, and in order to show the details of the interaction between objects, sometimes a 'UML' diagram is used to show how it works. Here will not be the various elements of 'UML' mentioned, just want to talk about the relationship between the classes in the class diagram, can understand the meaning of the lines and arrows between the classes in the class diagram, it is enough to deal with daily work and communication. At the same time, we should be able to match the meaning of the class diagram to the final code. With this knowledge, there is no problem looking at the design pattern structure diagram in the later sections.

1.1 inherit

Inheritance is represented directly by a hollow arrow.

1.2 realize

The implementation relationship is represented by a dashed line with a hollow arrow.

1.3 assembly

Like aggregation relations, composition relations also represent the semantics of a whole made up of parts. For example, a company is composed of multiple departments, but the combinatorial relationship is a special aggregation relationship of strong dependence, if the whole does not exist, then the part does not exist. For example, the company no longer exists, and the department will no longer exist.

1.4 Polymerization

Aggregation relationships are used to represent relationships between entity objects, representing the semantics of a whole made up of parts, such as a department consisting of multiple employees. Unlike combinatorial relations, the whole and the part are not strongly dependent, and even if the whole does not exist, the part still exists. For example, if the department is abolished, the personnel will not disappear, they will still exist.

1.5 Association

The association relationship is expressed by a straight line, which describes the structural relationship between objects of different classes. It is a static relationship, usually unrelated to the running state, and generally determined by common sense and other factors. It is generally used to define the static, natural structure between objects, so the association relationship is a "strong association" relationship.

For example, the relationship between the passenger and the ticket is an association relationship, the student and the school is an association relationship, the association relationship does not emphasize the direction by default, indicating that the object knows each other. If particular emphasis is placed on direction, as shown in the figure below, it means that A knows B, but B does not know A.

1.6 dependence

Dependencies are represented by A set of dotted lines with arrows, such as A depends on B, which describes the relationship between one object and another object at runtime.

Unlike an association relationship, it is a temporary relationship that usually occurs during run time, and dependencies may change as the run time changes. Obviously, dependence also has a direction, two-way dependence is a very bad structure, we should always maintain one-way dependence, eliminate the generation of two-way dependence.

II, six principles

2.1 Open and Close principle

> A software entity should be open for extension and closed for modification. That is, software entities should extend as far as possible without modifying the original code.

An important issue for any software is that its requirements change over time. When the software system needs to face new requirements, we should try to ensure that the design framework of the system is stable. If a software design conforms to the open-close principle, it can be very convenient to extend the system, and there is no need to modify the existing code when expanding, so that the software system has good stability and continuity while having adaptability and flexibility. As the software scale becomes larger and larger, the software life becomes longer and longer, and the software maintenance cost becomes higher and higher, it becomes more and more important to design the software system that meets the principle of open and close.

In order to meet the open-close principle, the system needs to be abstract design, abstraction is the key to the open-close principle. In programming languages such as Java and C#, a relatively stable abstraction layer can be defined for the system, and different implementation behaviors can be moved to the concrete implementation layer. In many object-oriented programming languages, interfaces, abstract classes and other mechanisms can be used to define the abstract layer of the system, and then extend it through concrete classes. If it is necessary to modify the behavior of the system, there is no need to make any changes to the abstract layer, only need to add new concrete classes to achieve new business functions, to achieve the expansion of the system function on the basis of not modifying the existing code, to meet the requirements of the open-close principle.

Advantages: The advantage of practicing the open-close principle is that you can extend the function of the program without changing the original code. The expansibility of the program is increased, and the maintenance cost of the program is reduced. **.

2.2 Richter Substitution Principle

> Any reference to a base class object can transparently use the object of its subclass

The Richter substitution principle tells us that replacing a base class object with its subclass object in software will not cause any errors and exceptions, and the reverse is not true, if a software entity uses a subclass object, then it may not be able to use the base class object. For example, if I like animals, then I must like dogs, because dogs are a subclass of animals. But I like dogs, and it does not follow that I like animals, because I do not like mice, even though they are animals.

For example, if there are two classes, one is BaseClass, the other is SubClass, and the SubClass is a subclass of the BaseClass class, then a method can accept a base class object of type BaseClass, such as: method1(base), then it must accept a subclass object of type BaseClass sub, and method1(sub) will work. The reverse substitution is not true, if a method method2 accepts sub of type BaseClass as an argument: method2(sub), then in general you can't have method2(base) unless it's an overloaded method.

Richter substitution principle is one of the important ways to achieve the open and close principle, because the use of base class objects can use subclass objects, so in the program to try to use the base class type to define the object, and then determine its subclass type at run time, with subclass objects to replace the parent object.

Advantages: You can test the correctness of the use of inheritance, and restrict the overflow of inheritance in use..

2.3 Reliance on the inversion principle

> Abstractions should not depend on concrete classes, and concrete classes should depend on abstractions. In other words, program against the interface, not the implementation.

The principle of dependency inversion requires us to refer to high-level abstract layer classes as far as possible when passing parameters in program code or in association relations, that is, to use interfaces and abstract classes for variable type declaration, parameter type declaration, method return type declaration, and data type conversion, etc., rather than using concrete classes to do these things. In order to ensure the application of this principle, a concrete class should only implement methods declared in the interface or abstract class, and not give extra methods, otherwise it will not be able to call the new methods added in the subclass.

After the introduction of the abstraction layer, the system will have good flexibility, in the program as far as possible to use the abstraction layer for programming, and the specific class is written in the configuration file, so that if the system behavior changes, only need to extend the abstraction layer, and modify the configuration file, without modifying the original system source code, in the case of no modification to expand the function of the system. Meet the requirements of the open and close principle.

Advantages: Build a framework through abstraction and establish associations between classes to reduce coupling between classes. Moreover, the system built with abstraction is more stable, more scalable, and easier to maintain than the system built with concrete implementation. **.

2.4 Principle of single responsibility

> A class is only responsible for the corresponding responsibilities in one functional area, or it can be defined that there should be only one reason for a class to change.

The principle of single responsibility tells us that a class can't be too "tired"! In a software system, the more responsibilities a class (from large modules to small methods) takes on, the less likely it is to be reused, and too many responsibilities a class takes on, the equivalent of coupling these responsibilities together, when one of the responsibilities changes, it may affect the operation of the other responsibilities, so the separation of these responsibilities. Encapsulate different responsibilities in different classes, that is, encapsulate different reasons for change in different classes, and encapsulate multiple responsibilities in the same class if they always change at the same time.

The principle of single responsibility is a guideline to achieve high cohesion and low coupling. It is the simplest but most difficult principle to apply. It requires designers to discover different responsibilities of a class and separate them, while discovering multiple responsibilities of a class requires designers to have strong analysis and design ability and relevant practical experience.

Advantages: If the class and method responsibilities are clearly divided, not only can improve the readability of the code, but also effectively reduce the risk of program errors, because the clear code will make the bug nowhere to hide, but also conducive to bug tracking, that is, reduce the maintenance cost of the program. **.

2.5 Demeter's Law (Least Know Principle)

> A software entity should interact with other entities as little as possible

If a system conforms to Dimitar's law, then when one of the modules is modified, it will affect the other modules as little as possible, and it will be relatively easy to expand, which is a limit on the communication between software entities, Dimitar's law requires limiting the width and depth of communication between software entities. Demeter's rule can reduce the coupling degree of the system and keep the loose coupling relationship between classes.

Demeter's law requires that when designing a system, we should minimize the interaction between objects, if two objects do not need to communicate directly with each other, then the two objects should not have any direct interaction, if one of the objects needs to call a method of another object, you can forward the call through a third party. In short, it is to reduce the coupling degree between existing objects by introducing a reasonable third party.

When applying Dimitter's rule to system design, we should pay attention to the following points: in the division of classes, we should try to create loosely coupled classes, the lower the degree of coupling between classes, the more conducive to reuse, and once a class in loose coupling is modified, it will not cause too much impact on the associated classes. In the structural design of the class, every class should minimize the access permissions of its member variables and member functions. In class design, whenever possible, a type should be designed as an invariant class. References to other classes from one object should be kept to a minimum.

Advantages: The practice of Demeter's rule can well reduce the coupling between classes, reduce the degree of correlation between classes, and make the collaboration between classes more direct..

2.6 Interface Separation Rule

> The use of multiple specialized interfaces rather than a single general interface means that the client should not rely on interfaces that it does not need.

According to the principle of interface isolation, when an interface is too large, we need to split it into smaller interfaces, and the client using the interface only needs to know the methods associated with it. Each interface should assume a relatively independent role, do not do what should not be done, do what should be done.

When using the interface isolation principle, you need to pay attention to the granularity of the control interface. If the interface is too small, the system may overflow interfaces, which is not conducive to maintenance. The interface can not be too large, too large interface will violate the interface isolation principle, poor flexibility, very inconvenient to use.

Advantages: Avoid the method of containing different responsibilities in the same interface, and the division of interface responsibilities is more clear, in line with the idea of high cohesion and low coupling..

2.7 Principle of Synthetic reuse (outside the six)

> Try to use object composition rather than inheritance for reuse purposes

The principle of composite reuse is to use some existing objects in a new object through association relations (including composition relations and aggregation relations), so that it becomes part of the new object, and the new object achieves the purpose of reuse functions by delegating methods to the existing object. In short, when reuse, use composition/aggregation relationships (association relationships) as much as possible and use inheritance less.

In object-oriented design, there are two ways to reuse existing designs and implementations in different environments, namely through composition/aggregation relationships or through inheritance, but the use of composition/aggregation should be considered first. Composition/aggregation can make the system more flexible and reduce the coupling degree between classes. Changes in a class have relatively little impact on other classes, and then inheritance is considered. When using inheritance, it is necessary to strictly follow the Richlist substitution principle. Effective use of inheritance will help to understand the problem and reduce complexity, while abuse of inheritance will increase the difficulty of system construction and maintenance as well as the complexity of the system, so inheritance reuse should be carefully used.

Advantages: Avoid abuse of inheritance when reuse, rational use of combination relations, increase flexibility..

2.8 Six principles - Learning experience

Among the six principles, the opening and closing principle, the Richter replacement principle, and the dependence and inversion principle are closely related, and the latter two are important prerequisites for realizing the opening and closing principle, and they have good scalability and maintainability through abstract design in use.

The principle of knowing the least can reduce coupling, reduce unnecessary interaction, advocate the design of interfaces and classes to be simple and easy to use, encapsulate complex logic and provide simple and easy-to-use interfaces.

Single Responsibility principle Divide the classes and methods in a project by responsibility to avoid overburdening a single class. The more responsibilities, the less likely they are to be reused or the more cumbersome they are to use.

Interface separation principle The function of the complex interface is subdivided into a number of specific functions of the interface, only do the thing to do, reduce the coupling, but the granularity can not be too fine, easy to lead to too many interfaces. The single responsibility principle emphasizes the design of a single class according to the subdivision of responsibilities, and the interface separation principle emphasizes the coupling between classes to establish the least possible dependency.

III. Pattern classification

There are 23 distinct design patterns in Design Patterns: The Foundations of Reusable Object-Oriented Software, each of which provides a solution to a repeatable design problem. According to their purpose, design patterns can be divided into three types: 'Creational', 'Structural' and 'Behavioral', in which the creational pattern is mainly used to describe how to create objects, and the structural pattern is mainly used to describe how to achieve the combination of classes or objects. Behavioral patterns are primarily used to describe how classes or objects interact and how responsibilities are assigned.

In addition, design patterns can be divided into class patterns and object patterns, depending on whether a pattern primarily deals with relationships between classes or between objects. We often use a combination of the two categories, for example, the singleton pattern is the object creation pattern, and the template method pattern is the class behavior pattern.

3.1 Create type

The 'Creational Pattern' abstracts the class instantiation process, separating the creation and use of objects in a module. In order to make the structure more clear, the outside world only needs to know their common interface for these objects, but is not clear about its specific implementation details, so that the design of the whole system is more in line with the principle of single responsibility.

  1. Simple Factory Pattern (' Simple Factory pattern ')
  2. Factory Method Pattern (' Factory method pattern ')
  3. Abstract Factory Pattern (' Abstract factory pattern ')
  4. 'Singleton Pattern'
  5. Builder Pattern (' Builder pattern ')
  6. Prototype Pattern (' Prototype pattern ')

3.2 Structural type

Structural patterns describe how classes or pairs of objects can be combined to form larger structures, like building blocks that can be combined to form complex, more powerful structures. Structured patterns can be divided into class structured patterns and object structured patterns:

  • The class structure pattern is concerned with the composition of classes. Multiple classes can be combined into a larger system. In the class structure pattern, there are generally only inheritance relations and implementation relations.

  • The object structure pattern is concerned with the combination of classes and objects, allowing an instance object of one class to be defined in another class through association, and its methods to be invoked through that object. According to the principle of "synthetic reuse", the associative relation is used to replace the successor relation in the system as much as possible, so most of the structural patterns are object structural patterns.

  1. Appearance mode
  2. Adapter mode
  3. Bridge mode
  4. Proxy mode
  5. Decorator mode
  6. Enjoy meta mode

3.3 Behavioral patterns

Behavioral patterns are abstractions that divide responsibilities and algorithms between different objects. The behavioral pattern focuses not only on the structure of classes and objects, but also on the interactions between them. Behavioral patterns allow you to more clearly divide the responsibilities of classes and objects and study the interactions between instance objects at runtime.

  1. Responsibility chain mode
  2. Command mode
  3. Interpreter mode
  4. Iterator mode
  5. Intermediary model
  6. Memo mode
  7. Observer mode
  8. Status mode
  9. Policy mode
  10. Template Method mode
  11. Visitor pattern

IV, create type

4.1 Simple Factory mode

Simple Factory Pattern: A single class (factory class) is defined to be responsible for creating instances of other classes. Instances of different classes can be returned based on the parameters of the creation method, and the created instances usually have a common parent class.

Example:

The simple factory model is like a foundry, a factory can produce a variety of products. For example, a beverage processing plant helps produce both Pepsi and Coca-Cola, and the processing plant produces different products according to the input parameter 'Type'.

ts
interface Cola {}
+
+interface CocaCola extends Cola {}
+
+interface PepsiCola extends Cola {}
ts
// SimpleFactory
+const createColaWithType = (type: number) => {
+  switch (type) {
+    case 0:
+      return new CocaCola();
+    case 1:
+      return new PepsiCola();
+    default:
+      return null;
+      break;
+  }
+};
ts
const cocaCola: CocaCola = createColaWithType(0);
+
+const pepsiCola: PepsiCola = createColaWithType(1);

Advantages:

  • The user only needs to pass a correct agreed parameter to the factory class, and you can get the object you need, without knowing its creation details, to reduce the coupling of the system to a certain extent.
  • The client does not need to know the class name of the specific product class created, only needs to know the parameters corresponding to the specific product class, reducing the memory cost of the developer.

Disadvantage:

  • If new products are added to the business, it is necessary to modify the original judgment logic of the factory class, which is actually contrary to the principle of opening and closing.
  • When there are many product types, the factory logic may be too complicated. Therefore, the simple factory model is more suitable for the situation where the product variety is relatively small and the probability of increasing is very low.

4.2 Factory Method mode

Factory Method Pattern (' factory method pattern ') is also known as the factory pattern, the factory parent class is responsible for defining the public interface for creating product objects, and the factory subclass is responsible for generating concrete product objects, that is, through different factory subclasses to create different product objects.

Example:

There are some differences between the factory method and the simple factory, the simple factory is the production of different products by a foundry, while the factory method is the abstraction of the factory, different products are produced by a specific factory. The Coca-Cola factory specializes in the production of Coca-Cola, and the Pepsi factory specializes in the production of Pepsi.

ts
// Factory abstract class
+class Cola {}
+
+// The Coca-Cola Factory
+class CocaCola extends Cola {}
+
+// Pepsi Factory
+class PepsiCola extends Cola {}
ts
// Different products are produced according to different factory types
+const cocaCola = new CocaCola();
+const pepsiCola = new PepsiCola();

Advantages:

  • Users only need to care about the specific factory corresponding to the product they need, do not need to care about the details of the creation of the product, do not need to know the class name of the specific product class.
  • When a new product is added to the system, it is not necessary to modify the interface provided by the abstract factory and the abstract product, nor to modify the client and other specific factories and specific products, but only to add a specific factory and its corresponding specific products, in line with the open and close principle.

Disadvantage:

  • When a new product is added to the system, in addition to the new product class, the corresponding specific factory class must be provided. Therefore, the number of classes in the system will be increased in pairs, increasing the complexity of the system.

4.3 Abstract factory pattern

The abstract factory pattern does not directly generate instances, but is used to create clusters of product classes.

Abstract Factory Pattern: Provides an interface for creating a series of related or interdependent objects without specifying their concrete classes.

Example:

The difference between the abstract factory and the factory method is that the factory that produces the product is abstract. For example, when Coca-Cola produces Coke, it also needs to produce bottles and boxes for Coke. The bottles and boxes are also customized by Coca-Cola, and Pepsi will also have this demand. At this time, our factory is not only a factory that produces cola drinks, but also has to produce bottles and boxes with the same theme at the same time, so it is an abstract theme factory, specializing in the production of different goods with the same theme.

ts
// Coke abstract classes and derived classes
+class Cola {}
+
+class CocaCola extends Cola {}
+
+class PepsiCola extends Cola {}
+
+// Bottle abstract and derived classes
+class Bottle {}
+
+class CocaColaBottle extends Bottle {}
+
+class PepsiColaBottle extends Bottle {}
+
+// Box abstract classes and derived classes
+class Box {}
+
+class CocaColaBox extends Box {}
+
+class PepsiColaBox extends Box {}
+
+// Factory abstract class
+const Factory = {
+  createCola: () => new Cola(),
+  createBottle: () => new Bottle(),
+  createBox: () => new Box(),
+};
+
+// Coca-Cola Theme Factory
+const CocaColaFactory = {
+  createCola: () => new CocaCola(),
+  createBottle: () => new CocaColaBottle(),
+  createBox: () => new CocaColaBox(),
+};
+
+// Pepsi Theme Factory
+const PepsiColaFactory = {
+  createCola: () => new PepsiCola(),
+  createBottle: () => new PepsiColaBottle(),
+  createBox: () => new PepsiColaBox(),
+};
ts
// Coca-Cola theme
+const cocaCola = CocaColaFactory.createCola();
+const cocaColaBottle = CocaColaFactory.createBottle();
+const cocaColaBox = CocaColaFactory.createBox();
+
+// Pepsi theme
+const pepsiCola = PepsiColaFactory.createCola();
+const pepsiColaBottle = PepsiColaFactory.createBottle();
+const pepsiColaBox = PepsiColaFactory.createBox();

Advantages:

  • Product specific code isolation at the application layer, do not need to care about product details. When multiple objects in a product family are designed to work together, it ensures that the client always uses only objects in the same product family. This is a very practical design pattern for software systems that need to determine their behavior based on the current environment.

Disadvantage:

  • Specifies the set of all products that can be created, the difficulty of extending new products in the product family, and the need to modify the interface of the abstract factory.

4.4 Singleton pattern

Singleton Pattern: The singleton pattern ensures that there is only one instance of a class and provides a full access point to it.

Example:

In singleton mode, the corresponding class can generate only one instance. Just as a kingdom can only have one king, once the affairs of the kingdom are too many, this only king is easy to take on too much responsibility.

ts
class Singleton {}
+
+function createSingleton() {
+  let instance;
+  return function () {
+    if (!instance) return new Singleton();
+    return instance;
+  };
+}

Advantages:

  • Provides controlled access to unique instances. Because a singleton encapsulates its unique instance, it has tight control over how and when customers access it.
  • This class saves system resources because it has only one object in system memory.

Disadvantage:

Since there is no abstraction layer in the singleton pattern, singleton classes are difficult to extend.

  • For languages that have garbage collection systems, such as Java and C#, objects may be recycled if they are not utilized for a long time. If the singleton holds some data, it will no longer exist when it is reinstantiated after collection.

4.5 Builder Pattern

Builder Pattern: Also known as the creator pattern, it separates the construction of a complex object from its representation, allowing the same construction process to create different representations.

The factory pattern is mainly for the creation of object instances or class clusters (abstract factories), concerned with the final output (creation) is what, not concerned with the creation process. The builder pattern is concerned with the entire process of creating the object, down to every detail of creating the object.

Example:

The main roles of the generator mode are as follows:

  1. Generator: The product construction steps common to all types of generators in the interface life
  2. Concrete generator: Provides different implementations of the construction process. Concrete generators can also construct products that do not follow a generic interface
  3. Product: is the final generated object. Products constructed from different generators need not belong to the same class of hierarchical constructs or interfaces
  4. Conductor: Define the order in which construction steps are called so that you can create and consume specific product configurations
  5. Client side: You must associate a generator object with a supervisor class. In general, you only need to do a one-time association through the parameters of the supervisor class constructor
ts
// Abstract Builder
+abstract class Builder {
+  public abstract buildPartA(): void;
+  public abstract buildPartB(): void;
+  public abstract buildPartC(): void;
+  public abstract buildProduct(): Product;
+}
+
+// Concrete builder
+class ConcreteBuilder extends Builder {
+  private product: Product;
+  constructor(product: Product) {
+    super();
+    this.product = product;
+  }
+
+  public buildPartA(): void {}
+  public buildPartB(): void {}
+  public buildPartC(): void {}
+
+  // Finally build a product
+  public buildProduct(): Product {
+    return this.product;
+  }
+}
+
+// Product role
+class Product {
+  public doSomething(): void {
+    // Independent business
+  }
+}
+
+// director
+class Director {
+  private _builder: Builder;
+  constructor(builder: Builder) {
+    this._builder = builder;
+  }
+
+  set builder(builder: Builder) {
+    this._builder = builder;
+  }
+
+  // Leave the process of handling the construction to the commander
+  public constructorProduct() {
+    this._builder.buildPartA();
+    this._builder.buildPartB();
+    this._builder.buildPartC();
+    return this._builder.buildProduct();
+  }
+}
+
+// Use
+const builder: Builder = new ConcreteBuilder(new Product());
+const director: Director = new Director(builder);
+const product: Product = director.constructorProduct();

Advantages:

  • The client does not have to know the details of the internal composition of the product, decoupling the product itself from the product creation process, so that the same creation process can create different product objects.
  • Each concrete builder is relatively independent, and has nothing to do with other concrete builders, so it is easy to replace concrete builders or add new concrete builders, and users can get different product objects using different concrete builders.
  • Adding new concrete builders does not need to modify the code of the original class library, the command class is programmed for the abstract builder class, the system is easy to expand, and conforms to the "open and close principle".
  • The product creation process can be more finely controlled. Breaking down the creation steps of complex products into different methods makes the creation process clearer and easier to use programs to control the creation process.

Disadvantage:

  • The products created by the builder mode generally have more in common and their components are similar. If the differences between products are large, the builder mode is not suitable for use, so its scope of use is limited. If the internal changes of the product are complex, it may lead to the need to define many concrete constructor classes to achieve such changes, resulting in a large system, increasing the difficulty of understanding the system and the cost of operation.

4.6 Prototype Pattern

Prototype Pattern: A prototype instance points to the class that created the object, and uses the properties and methods of the shared prototype used by the class that created the new object.

Example:

Prototype mode is like photocopying technology, copy a new object from the original object, and fine-tune the new object according to the needs.

ts
// Because it's not a constructor, you don't use capitalization
+const car = {
+  drive: function () {},
+  name: 'The Mazda 3',
+};
+
+// Create a new car x using Object.create
+const anotherCar = Object.create(someCar);
+anotherCar.name = 'Mike';
ts
const vehiclePrototype = {
+  init: function (carModel) {
+    this.model = carModel;
+  },
+  getModel: function () {
+    console.log('The vehicle mold is:' + this.model);
+  },
+};
+
+function vehicle(model) {
+  function F() {}
+  F.prototype = vehiclePrototype;
+
+  const f = new F();
+
+  f.init(model);
+  return f;
+}
+
+const car = vehicle('Ford Escort');
+car.getModel();

Advantages:

  • The prototype mode can be used to simplify the object creation process, especially for some objects with complicated creation process and many object levels, the prototype mode can save system resources and improve the efficiency of object generation.
  • It is easy to generate new objects by changing the values: some objects may differ only from one another in certain values; Using prototype mode, you can quickly copy new objects and manually modify the values.

Disadvantage:

  • All objects contained in an object need to be equipped with a clone method, which makes the amount of code in the case of more object levels will be large and more complex.

V, structural type

5.1 Decorative pattern

Decorator Pattern: The design pattern that adds new functionality to an existing object without changing its structure is called the decorator pattern, which acts as a wrapper around an existing class.

You can think of decorators as equipment purchased by game characters, such as heroes in LOL who start the game with only basic attack power and mana. However, after the purchase of equipment, you can enjoy the output bonus brought by the equipment when triggering attacks and skills. We can understand the purchase of equipment to give the hero's attack and skill related methods decorated.

Example:

The decorative mode conforms to the open-close principle and transforms or adds new functions to the parent class without changing the original class.

decoration

ts
@annotation
+class MyClass {}
+
+function annotation(target) {
+  target.annotated = true;
+}

Decorative method or attribute

js
class MyClass {
+  @readonly
+  method() {}
+}
+
+function readonly(target, name, descriptor) {
+  descriptor.writable = false;
+  return descriptor;
+}

Advantages:

  • More flexible than inheritance: unlike inheritance, which works at compile time; Decorator mode can extend the functionality of an object at run time. It is also possible to select different decorators at run time through configuration files to achieve different behavior. It can also achieve different effects through different combinations.
  • Comply with the "open and close principle" : the decorator and the decorator can vary independently. Users can add new decorative classes as needed, and then combine them when they are used, without changing the original code.

Disadvantage:

  • Decorator mode requires the creation of some concrete decorator classes, which increases the complexity of the system.

5.2 外观模式

Facade Pattern: A facade pattern defines a high-level interface that provides a unified interface for a set of interfaces in a subsystem. It makes the subsystem easier to use, not only simplifying the interfaces in the class, but also decoupling the caller from the interface. Appearance mode, also known as facade mode, is a structural design mode.

Example:

Appearance patterns provide a simple and unambiguous interface, but integrate many subsystem functions internally. Just like the image cache, which contains processing involving other subsystems such as caching, downloading, etc., the appearance pattern hides the complex logic. In the compatible browser event binding, you only need to call an 'addMyEvent' interface can be, to achieve the purpose of decoupling.

js
const addMyEvent = function (el, ev, fn) {
+  if (el.addEventListener) {
+    el.addEventListener(ev, fn, false);
+  } else if (el.attachEvent) {
+    el.attachEvent('on' + ev, fn);
+  } else {
+    el['on' + ev] = fn;
+  }
+};

Advantages:

  • Decoupling between the client and the subsystem is realized: the client does not need to know the interface of the subsystem, simplifying the process of the client calling the subsystem, making the subsystem easier to use. At the same time, it is easy to expand and maintain the subsystem.
  • Demeter's law (least know principle) : The subsystem only needs to expose the interface that needs external calls to the appearance class, and its interface can be hidden.

Disadvantage:

  • Violates the open-close principle: Adding a new subsystem without introducing abstract facade classes may require changes to facade classes or client code.

5.3 代理模式

Proxy Pattern: Provide a proxy for an object, and this proxy object controls access to the original object.

Example:

The agent model is like a housing agent, the buyer can only buy a house through the intermediary, the agent has all the functions of the agent, just as the landlord has the function of selling the house, the intermediary also has the function of selling the house. In addition, the agent instance can also help the agent to carry out some additional processing, such as the function of the intermediary to help the landlord screen quality buyers, and help the landlord pass some unqualified buyers. The same pattern applies to message queues.

Reference 'koa' in the proxy mode, the 'response' on some properties and methods proxy out, easy to use

js
/**
+ * Response delegation.
+ */
+const delegate = require('delegates');
+
+const prototype = (module.exports = {});
+
+delegate(prototype, 'response')
+  .method('attachment')
+  .method('redirect')
+  .method('remove')
+  .method('vary')
+  .method('has')
+  .method('set')
+  .method('append')
+  .method('flushHeaders')
+  .access('status')
+  .access('message')
+  .access('body')
+  .access('length')
+  .access('type')
+  .access('lastModified')
+  .access('etag')
+  .getter('headerSent')
+  .getter('writable');

Make a proxy for 'context', 'request', 'response', protecting the real 'context', 'request', 'response'

js
this.context = Object.create(context);
+this.request = Object.create(request);
+this.response = Object.create(response);

Advantages:

  • Reduce the coupling degree of the system: The proxy mode can coordinate the caller and the called, which reduces the coupling degree of the system to a certain extent.
  • Different types of proxies can have different controls on the client's access to the target object:
  • A remote agent that allows the client to access objects on a remote machine that may have better computational performance and processing speed and can respond and process client requests quickly. By using a small object to represent a large object, virtual agents can reduce the consumption of system resources, optimize the system, and increase the speed of operation.
  • The protection agent can control the client's permission to use real objects.

Disadvantage:

  • Adding a proxy object between the client and the proxy object may slow down client requests.

5.4 Flyweight Pattern

Flyweight Pattern: The meta mode is a mode that optimizes program performance, essentially reducing the number of objects created. Using sharing technology to reuse a large number of fine-grained objects, reduce the program memory occupation, improve the performance of the program. Share metamode can be used when there are a large number of similar objects that occupy a large amount of memory. Most of the state in an object can be extrapolated to external state.

Example:

For example, a music service can be divided into free users and member users based on fees. Free users can only listen to some free music, and member users can listen to all music and can download it. Although there are some differences in permissions between the two, the music they enjoy is from the same library, so all the music needs to be saved only one copy. In addition, if there is no music in the music library, you need to add the music, and then other services can also enjoy the new music, which is equivalent to the function of the share pool or cache pool.

The share mode area ensures that the internal state is shared, such as the music library, while the external state is customized according to different needs, such as various access rights, and the internal state cannot be changed during use to achieve the purpose of sharing.

ts
// Music service
+const MusicService = {}
+
+// Shared music library
+const musicLibrary = {};
+
+// Listen to music
+const listenToMusic = (music) => {
+    ...
+}
+// Download music
+const downloadMusic = (music) => {
+    ...
+}
+
+
+// Free music service
+const FreeMusicService = {
+    listenFreeMusic: (music)=>{
+        if(isMusicFree(music)){
+            // If it is free, play it
+            listenToMusic()
+        }else{
+         // If it is paid music, the user is prompted to upgrade the Vip Vip
+            console.log("please upgrade to Vip")
+        }
+    }
+}
+
+
+// Vip Music Service
+const VipMusicService = {
+    // You can listen to all the music
+    listenMusic
+    // You can download music
+    downloadMusic
+}

Advantages:

  • The use of the share module can reduce the number of objects in memory, so that the same object or similar objects in memory only one copy, reduce the system memory usage, can also improve performance.
  • The external state of the share meta pattern is relatively independent and does not affect its internal state, so that share meta objects can be shared in different environments.

Disadvantage:

  • Using the meta pattern requires the separation of internal and external states, which complicates the logic of the program.
  • Object reuse in buffer pools requires consideration of threading issues.

5.5 Simple Factory Pattern

Simple Factory Pattern: Separate the abstract part from its implementation part so that they can both vary independently.

Example:

Both balls and people can move, but balls have movement and colors, and people can move and talk. Abstract the common parts.

js
class Speed {
+  // Motion module
+  constructor(x, y) {
+    this.x = x;
+    this.y = y;
+  }
+  run() {
+    console.log(\`Get into motion \${this.x} + \${this.y}\`);
+  }
+}
+
+class Color {
+  // Coloring module
+  constructor(cl) {
+    this.color = cl;
+  }
+  draw() {
+    console.log(\`Draw color \${this.color}\`);
+  }
+}
+
+class Speak {
+  constructor(wd) {
+    this.word = wd;
+  }
+  say() {
+    console.log(\`talk \${this.word}\`);
+  }
+}
+
+class Ball {
+  // Create balls that can be colored and moved
+  constructor(x, y, cl) {
+    this.speed = new Speed(x, y);
+    this.color = new Color(cl);
+  }
+  init() {
+    this.speed.run();
+    this.color.draw();
+  }
+}
+
+class Man {
+  // Humans can move and talk
+  constructor(x, y, wd) {
+    this.speed = new Speed(x, y);
+    this.speak = new Speak(wd);
+  }
+  init() {
+    this.speed.run();
+    this.speak.say();
+  }
+}
+
+const man = new Man(1, 2, 'hello ?');
+man.init();

Advantages:

  • Good scalability, in line with the principle of open and close: separation of abstraction and implementation, so that the two can change independently

Disadvantage:

  • Two independently varying dimensions need to be identified before design.

5.6 Adapter Pattern

Adapter Pattern: Adapter mode is used to solve the incompatibility of two interfaces, do not need to change the existing interface, through the packaging of a layer, to achieve normal cooperation between the two interfaces. When we try to call an interface of a module or object, but find that the format of the interface does not meet the current requirements, we can use the adapter pattern.

Example:

Event binding is compatible with all browsers

js
function addEvent(ele, event, callback) {
+    if (ele.addEventListener) {
+      ele.addEventListener(event, callback)
+    } else if(ele.attachEvent) {
+      ele.attachEvent('on' + event, callback)
+    } else {
+      ele['on' + event] = callback
+    }
+  }
+

Advantages:

  • Comply with the principle of open and close: use adapters without changing existing classes, improving class reusability.
  • Decouple the target class from the adapter class to improve program extensibility.

Disadvantage:

  • Increased the complexity of the system

VI. Behavior pattern

6.1 Chain of Responsibility Pattern

Chain of Responsibility Pattern: Avoid coupling the request sender with the receiver, make it possible for multiple objects to receive the request, connect those objects into a chain, and pass the request along the chain until an object handles it. The responsibility chain pattern is an object behavior pattern. Similar to dominoes, by requesting the first condition, subsequent conditions continue to be executed until a result is returned.

Example:

Scenario: An e-commerce has a preferential policy for users who have paid a deposit, after the formal purchase, users who have paid a deposit of 500 yuan will receive a coupon of 100 yuan, users who have paid a deposit of 200 yuan can receive a coupon of 50 yuan, and users who have not paid a deposit can only buy normally.

js
const order500 = function (orderType, pay, stock) {
+  if (orderType === 1 && pay == true) {
+    console.log('500 yuan deposit advance purchase, get 100 yuan coupon');
+  } else {
+    return 'nextSuccess';
+  }
+};
+const order200 = function (orderType, pay, stock) {
+  if (orderType === 2 && pay === true) {
+    console.log('200 yuan deposit pre-order, get 50 yuan coupon');
+  } else {
+    return 'nextSuccess';
+  }
+};
+const orderCommon = function (orderType, pay, stock) {
+  if (orderType == 3 && stock > 0) {
+    console.log('Regular purchase, no coupon');
+  } else {
+    console.log('Insufficient stock');
+  }
+};
+// Link code
+const chain = function (fn) {
+  this.fn = fn;
+  this.successor = null;
+};
+chain.prototype.setNext = function (successor) {
+  this.successor = successor;
+};
+chain.prototype.init = function () {
+  const result = this.fn.apply(this, arguments);
+  if (result == 'nextSuccess') {
+    this.successor.init.apply(this.successor, arguments);
+  }
+};
+const order500New = new chain(order500);
+const order200New = new chain(order200);
+const orderCommonNew = new chain(orderCommon);
+order500New.setNext(order200New);
+order200New.setNext(orderCommonNew);
+order500New.init(3, true, 500); // Regular purchase, no coupons

Advantages:

The responsibility chain mode makes an object not need to know which other object handles its request, the object only needs to know that the request will be processed, the receiver and the sender have no clear information about each other, and the object in the chain does not need to know the chain structure, the client is responsible for the creation of the chain, reducing the coupling degree of the system.

  • The request processing object only needs to maintain a reference to its successor, rather than maintaining a reference to all of its candidate handlers, simplifying object interconnections. The responsibility chain gives us more flexibility when assigning responsibilities to objects. The responsibility for handling a request can be added or changed by dynamically adding or modifying the chain at runtime.
  • Adding a new specific request handler to the system does not need to modify the code of the original system, only needs to rebuild the chain on the client side, from this point of view is in line with the "open and closed principle".

Disadvantage:

Since a request has no clear recipient, there is no guarantee that it will be processed, and the request may not be processed until the end of the chain; A request may also not be processed because the chain of responsibility is not configured correctly.

  • For a long chain of responsibility, the processing of requests may involve multiple processing objects, which will affect system performance and make it inconvenient for code debugging.
  • If the chain is not properly built, circular calls may be caused, resulting in a dead loop of the system.

6.2 Command Pattern

Command Pattern: Encapsulating a request as an object allows us to parameterize customers with different requests; Command mode is an object behavior mode, which is alias' Action 'mode or' Transaction 'mode.

The command mode consists of three roles:

  1. Publisher 'invoker' (issues command, calls command object, does not know how to execute and whom to execute);
  2. receiver 'receiver' (provides the corresponding interface to process the request, and does not know who initiates the request);
  3. The command object 'command' (receives the command and invokes the corresponding interface of the receiver to process the publisher's request). The publisher invoker and the receiver are independent and encapsulate the request into a command object command. The specific execution of the request is executed by the command object calling the corresponding interface of the receiver.

Example:

Similar to the previous example in proxy mode, but the essence of command mode is to encapsulate commands, separating the responsibility for issuing commands from the responsibility for executing them. For example, the remote control is a caller, different buttons represent different commands, and the TV is the receiver.

js
class Receiver {
+  // Receiver class
+  execute() {
+    console.log('Receiver execute request');
+  }
+}
+
+class Command {
+  // Command object class
+  constructor(receiver) {
+    this.receiver = receiver;
+  }
+  execute() {
+    // The call receiver executes against the interface
+    console.log('Command object -> Receiver -> Corresponding interface execution');
+    this.receiver.execute();
+  }
+}
+
+class Invoker {
+  // Publisher class
+  constructor(command) {
+    this.command = command;
+  }
+  invoke() {
+    // Issue a request, invoke a command object
+    console.log('The publisher publishes the request');
+    this.command.execute();
+  }
+}
+
+const warehouse = new Receiver(); // Stash
+const order = new Command(warehouse); // Order for goods
+const client = new Invoker(order); // client
+client.invoke();

Advantages:

  • Reduce the coupling degree of the system. Since there is no direct reference between the requester and the receiver, the requester and the receiver realize complete decoupling, the same requester can correspond to different receivers, similarly, the same receiver can also be used by different requesters, and there is good independence between the two.
  • New commands can be easily added to the system. Since the addition of new specific command classes does not affect other classes, it is easy to add new specific command classes without modifying the original system source code, or even the customer class code, to meet the requirements of the "open and close principle".
  • It is relatively easy to design a command queue or macro command (composite command).
  • Provides a design and implementation scheme for requested Undo and Redo operations.

Disadvantage:

  • Using command mode may cause some systems to have too many specific command classes. Because a concrete command class needs to be designed for each call to the receiver of the request, a large number of concrete command classes may need to be provided in some systems, which will affect the use of command patterns.

6.3 Interpreter Pattern

Interpreter Pattern: Define the grammar of a language and build an interpreter to interpret sentences in that language, where "language" means code that uses a specified format and syntax. The interpreter pattern is a kind of behavior pattern.

Example:

Given a language, define a representation of its grammar and an interpreter that uses that representation to interpret sentences in the language.

js
class Context {
+  constructor() {
+    this._list = []; // Stores terminal expressions
+    this._sum = 0; // Store nonterminal expressions
+  }
+
+  get sum() {
+    return this._sum;
+  }
+  set sum(newValue) {
+    this._sum = newValue;
+  }
+  add(expression) {
+    this._list.push(expression);
+  }
+  get list() {
+    return [...this._list];
+  }
+}
+
+class PlusExpression {
+  interpret(context) {
+    if (!(context instanceof Context)) {
+      throw new Error('TypeError');
+    }
+    context.sum = ++context.sum;
+  }
+}
+class MinusExpression {
+  interpret(context) {
+    if (!(context instanceof Context)) {
+      throw new Error('TypeError');
+    }
+    context.sum = --context.sum;
+  }
+}
+
+/** Here is the test code **/
+const context = new Context();
+
+// Add in order: Add | add | subtract expression
+context.add(new PlusExpression());
+context.add(new PlusExpression());
+context.add(new MinusExpression());
+
+// Execute the following: add | add | subtract expression
+context.list.forEach((expression) => expression.interpret(context));
+console.log(context.sum);

Advantages:

  • Easy to change and extend grammar. Because classes are used in the interpreter schema to represent the grammar rules of the language, the grammar can be changed or extended through mechanisms such as inheritance. Each rule can be represented as a class, so it is easy to implement a simple language.
  • The grammar is easier to implement. Each expression node class in the abstract syntax tree is implemented in a similar way, the code for these classes is not particularly complicated, and some tools can automatically generate node class code.
  • It is easier to add new interpretation expressions. If the user needs to add a new interpretation expression, it only needs to add a new terminal expression or non-terminal expression class, and the original expression class code does not need to be modified, which conforms to the "open and closed principle".

Disadvantage:

  • Difficult to maintain for complex grammars. In the interpreter mode, each rule needs to define at least one class, so if a language contains too many grammar rules, the number of classes will increase dramatically, resulting in a system difficult to manage and maintain, at this time you can consider using a parser to replace the interpreter mode.
  • Low execution efficiency. Because of the large number of loops and recursive calls used in the interpreter mode, it is slow to interpret more complex sentences, and the debugging process of the code is cumbersome.

6.4 Iterator Pattern

Iterator Pattern: A relatively simple pattern, most languages now have iterators built in, so that people don't think of it as a design pattern. Iterators don't just iterate over arrays; iterators can be aborted. Provides a way to access aggregate objects without exposing the internal representation of the object, which is alias a Cursor. The iterator pattern is an object behavior pattern.

Example:

Iterators help requesters get the data, avoiding direct manipulation of the data aggregation class and allowing the data aggregation class to focus on storing the data. The specific application has pagination and other functions, and the iterator of the pagination function will be specially responsible for operating the pagination data, separating the operation logic from the data source.

js
var each = function (arr, callback) {
+  for (var i = 0, len = arr.length; i < len; i++) {
+    callback.call(arr[i], i, arr[i]);
+  }
+};
+
+each([1, 2, 3, 4, 5], function (i, el) {
+  console.log('index: ', i);
+  console.log('item: ', el);
+});

Advantages:

  • It supports traversing an aggregate object in different ways, and multiple traversing modes can be defined on the same aggregate object. Iterator mode can be changed by simply replacing the iterator with a different iterator, or we can define our own iterator subclasses to support the new iterator.
  • Iterators simplify aggregate classes. Due to the introduction of iterators, it is no longer necessary to provide data traversal methods in the original aggregate object, which can simplify the design of the aggregate class.
  • In the iterator mode, due to the introduction of the abstraction layer, it is convenient to add new aggregate classes and iterator classes without modifying the original code, which meets the requirements of the "open and closed principle".

Disadvantage:

Because the iterator pattern separates the responsibility of storing data and traversing data, adding new aggregate classes requires adding new iterator classes, and the number of classes increases in pairs, which increases the complexity of the system to some extent.

  • The design of the abstract Iterator is more difficult and needs to fully consider the future extension of the system, for example, the JDK built-in iterator cannot achieve reverse traversal, if you need to achieve reverse traversal, it can only be achieved through its subclass ListIterator, etc. ListIterator iterators cannot be used to manipulate aggregate objects of type Set. When customizing iterators, it is not easy to create an abstract iterator that considers all aspects.

6.5 Mediator Pattern

Mediator Pattern: Objects communicate with each other through third-party intermediaries. Encapsulate a set of object interactions with a mediator, which allows objects to be loosely coupled without explicitly referring to each other, and can change their interactions independently. The mediator model, also known as the mediator model, is an object behavior model.

Example:

The broker pattern turns a network system structure into a star structure centered on broker objects, where one-to-many relationships between broker objects and other objects replace many-to-many relationships between objects. All members interact through intermediaries to facilitate the expansion of new members, such as the following example, after the end of a test, the result is announced: tell the person who solved the challenge successfully, otherwise the challenge fails. In this code, there is no direct relationship between A, B, and C, but a link is established through another playerMiddle object, which is considered the mediator pattern.

js
const player = function (name) {
+  this.name = name;
+  playerMiddle.add(name);
+};
+player.prototype.win = function () {
+  playerMiddle.win(this.name);
+};
+player.prototype.lose = function () {
+  playerMiddle.lose(this.name);
+};
+const playerMiddle = (function () {
+  // We're going to use this demo, this function as a mediator
+  const players = [];
+  const winArr = [];
+  const loseArr = [];
+  return {
+    add: function (name) {
+      players.push(name);
+    },
+    win: function (name) {
+      winArr.push(name);
+      if (winArr.length + loseArr.length === players.length) {
+        this.show();
+      }
+    },
+    lose: function (name) {
+      loseArr.push(name);
+      if (winArr.length + loseArr.length === players.length) {
+        this.show();
+      }
+    },
+    show: function () {
+      for (let winner of winArr) {
+        console.log(winner + 'Challenge success;');
+      }
+      for (let loser of loseArr) {
+        console.log(loser + 'Challenge failure;');
+      }
+    },
+  };
+})();
+const a = new player('A-player');
+const b = new player('B-player');
+const c = new player('C-player');
+a.win();
+b.lose();
+c.win();
+// A Contestant successfully challenged;
+// B Contestant successfully challenged;
+// C Player fails to challenge;

Advantages:

The -mediator pattern simplifies interactions between objects. It replaces many-to-many interactions between colleagues with one-to-many interactions between intermediaries and colleagues. One-to-many relationships are easier to understand, maintain, and extend, transforming the previously difficult network structure into a relatively simple star structure.

  • Mediator mode decouples colleague objects. Intermediaries are conducive to the loose coupling between colleagues, we can independently change and reuse each colleague and intermediary, adding new intermediaries and new colleague classes are more convenient, better in line with the "open and close principle".
  • Can reduce subclass generation, intermediaries will be distributed across multiple objects in a group of behaviors, change these behaviors only need to generate new intermediary subclasses, this allows individual colleague classes can be reused without the need to extend the colleague classes.

Disadvantage:

The inclusion of a large number of details about interactions between colleagues in a specific broker class can make the specific broker class very complex and make the system difficult to maintain.

6.6 Memento Pattern

Memento Pattern: Capture the internal state of an object, without breaking the encapsulation, and save that state outside the object for later use or for the object to revert to a previous state. It is an object behavior pattern that is alias Token.

Example:

Memo mode provides a state recovery implementation mechanism, so that users can easily return to a specific historical step, when the new state is invalid or there is a problem, you can use the temporary storage of the memo to restore the state, many software provides undo operations, which uses the memo mode.

When we develop a paging component, click on the next page to get new data, but when click on the previous page, and get data again, resulting in unnecessary traffic waste, then the data can be cached.

js
// Memo mode pseudo-code
+var Page = function () {
+  // cache objects are used to cache data
+  var cache = {};
+  return function (page, fn) {
+    if (cache[page]) {
+      showPage(page, cache[page]);
+    } else {
+      $.post('/url', function (data) {
+        showPage(page, data);
+        cache[page] = data;
+      });
+    }
+    fn && fn();
+  };
+};

Advantages:

  • It provides a state recovery implementation mechanism, so that users can easily go back to a specific historical step, when the new state is invalid or there is a problem, you can use a temporary stored memo to restore the state.
  • Memos encapsulate information. A memos object is a representation of the state of the originator object and cannot be changed by other code. Memos save the state of the originator, using lists, stacks and other collections to store memos can achieve multiple undo operations.

Disadvantage:

  • Excessive resource consumption. If too many member variables of the originator class need to be saved, a large amount of storage space is inevitably required. Each time the state of an object is saved, certain system resources are consumed.

6.7 Observer Pattern

Observer Pattern: Define a one-to-many dependency relationship between objects so that each time an object's state changes, its dependent objects are notified and automatically updated. Aliases for the observer pattern include the 'Publish/Subscribe' pattern, the model-view (' Model/View ') pattern, the Source/Listener (' source/listener ') pattern, or the 'Dependents' pattern. The observer pattern is an object behavior pattern.

Example:

The observer pattern is one of the most frequently used design patterns, and it is used to establish a dependency relationship between objects. When one object changes, the other objects are automatically notified, and the other objects react accordingly.

The implementation of the observer pattern in JavaScript uses the event model, the DOM event.

js
// publisher
+var pub = function () {
+  console.log('Welcome to subscribe!');
+};
+// Subscribers
+var sub = document.body;
+
+// Subscribers implement subscriptions
+sub.addEventListener('click', pub, false);

Advantages:

The observer pattern can realize the separation of the presentation layer and the data logic layer, define a stable message update delivery mechanism, and abstract the update interface, so that there can be a variety of different presentation layers to act as a concrete observer role.

  • Observer mode establishes an abstract coupling between the object of observation and the observer. The object of observation needs only to maintain a set of abstract observers, without knowing its concrete observers. Because the object of observation and the observer are not tightly coupled, they can belong to different levels of abstraction. Observer mode supports broadcast communication, and the observer will send notifications to all registered observer objects, simplifying the difficulty of one-to-many system design.
  • Observer mode meets the requirements of the "open and close principle", adding new specific observers does not require modifying the original system code, and it is also convenient to add new observation targets when there is no correlation between specific observers and observation targets.

Disadvantage:

If an observation target has many direct and indirect observers, it takes a lot of time to notify all of them.

  • If there is a cyclic dependency between the observer and the observing target, the observing target will trigger a cyclic call between them, possibly causing the system to crash. The observer mode has no mechanism for the observer to know how the object being observed has changed, but only to know that the object being observed has changed.

6.8 State Pattern

State Pattern: By allowing an object to change its behavior when its internal state changes, the object appears to modify its class. Its alias is the state object (' Objects for States'), in fact, is to use an object or array to record a set of states, each state corresponds to an implementation, the implementation according to the state to run the implementation. The state pattern is an object behavior pattern.

Example:

State mode is used to solve the problem of state transition of complex objects and encapsulation of behavior in different states. When an object in the system has multiple states, these states can be transformed between, so objects in different states have different behaviors can be used when the state mode. The state mode separates the state of an object from the object and encapsulates it into a special state class, making the state of the object flexible.

For example, Super Mary may have several states at the same time, such as jumping, moving, shooting, squatting, etc. if these actions are processed and judged one by one, multiple if-else or switch are required. Not only is it ugly, but when there are combined actions, the implementation will become more complicated. This can be done using the state mode.

The idea of state mode is: first create a state object or array, store state variables inside, and then internally encapsulate the corresponding state of each action, and then the state object returns an interface object, which can modify or call the internal state.

js
class SuperMarry {
+  constructor() {
+    this._currentState = [];
+    this.states = {
+      jump() {
+        console.log('Jumping!');
+      },
+      move() {
+        console.log('Move!');
+      },
+      shoot() {
+        console.log('Shoot!');
+      },
+      squat() {
+        console.log('Keep down!');
+      },
+    };
+  }
+
+  change(arr) {
+    // Change current action
+    this._currentState = arr;
+    return this;
+  }
+
+  go() {
+    console.log('Trigger action');
+    this._currentState.forEach((T) => this.states[T] && this.states[T]());
+    return this;
+  }
+}
+
+new SuperMarry()
+  .change(['jump', 'shoot'])
+  .go() // Trigger action jump! Shoot!
+  .go() // Trigger action jump! Shoot!
+  .change(['squat'])
+  .go(); // Trigger action Crouch!

Advantages:

  • Encapsulates the state transition rules. In the state mode, the state transition code can be encapsulated in the environment class or specific state class, and the state transition code can be centrally managed, rather than dispersed in one business method.
  • Put all the behavior related to a state into a class, just inject a different state object to make the environment object have different behavior.
  • Allowing state transition logic to be integrated with state objects, rather than providing a huge block of conditional statements, state patterns allow us to avoid using huge conditional statements to interweave business methods and state transition code.
  • Multiple environment objects can share a state object, thereby reducing the number of objects in the system.

Disadvantage:

  • The use of state mode will inevitably increase the number of classes and objects in the system, resulting in increased system operating overhead.
  • The structure and implementation of the state mode are relatively complex, if used improperly will lead to the program structure and code confusion, increase the difficulty of system design.
  • The state mode does not support the "open and closed principle" very well, adding a new state class needs to modify the source code responsible for the state transition, otherwise it cannot be converted to the new state; And modifying the behavior of a state class also requires modifying the source code of the corresponding class.

6.9 Strategy Pattern

Strategy Pattern: Define a list of algorithms, wrap them up, and be interchangeable. It is to extract and encapsulate seemingly unrelated code and reuse it to make it easier to understand and expand. It is commonly used in process judgment statements such as if judgment, switch enumeration, and data dictionary. Also known as the Policy model (' policy '). Policy pattern is an object behavior pattern.

Example:

When using the policy pattern, we can define several policy classes, each of which encapsulates a specific algorithm. Here, each class that encapsulates an algorithm can be called a policy, and depending on which policy class is passed in, the environment class executes the algorithm in a different policy class.

In the game, we have A level evaluation of the user after each game, such as level S 4 times experience, level A 3 times experience, level B 2 times experience, and other 1 times experience, expressed by the function as follows:

js
// Instead, the policy pattern is written as two functions
+const strategy = {
+  S: function (experience) {
+    return 4 * experience;
+  },
+  A: function (experience) {
+    return 3 * experience;
+  },
+  B: function (experience) {
+    return 2 * experience;
+  },
+};
+// getExperience can be reused
+function getExperience(strategy, level, experience) {
+  return level in strategy ? strategy[level](experience) : experience;
+}
+var s = getExperience(strategy, 'S', 100);
+var a = getExperience(strategy, 'A', 100);
+console.log(s, a); // 400 300
js
// Instruction processing set
+var compileUtil = {
+    // v-text Works for updating views
+    text: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'text');
+    },
+    // v-html update view principle
+    html: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'html');
+    },
+    // v-class binding principle
+    class: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'class');
+    },
+    bind: function(node, vm, exp, dir) {
+        // The same instruction triggers the view update
+        var updaterFn = updater[dir + 'Updater'];
+        updaterFn && updaterFn(node, this._getVMVal(vm, exp));
+        new Watcher(vm, exp, function(value, oldValue) {
+            updaterFn && updaterFn(node, value, oldValue);
+        });
+    }
+    ......
+}

Advantages:

  • Policy mode provides perfect support for the "open and close principle", users can choose algorithms or behaviors without modifying the original system, and can flexibly add new algorithms or behaviors.
  • The policy pattern provides a way to manage related algorithm families. The hierarchy of a policy class defines an algorithm or family of behaviors, and proper use of inheritance can move common code into an abstract policy class, thereby avoiding duplicate code. The policy pattern provides a way to replace inheritance relationships. Without the policy pattern, an environment class that uses algorithms might have several subclasses, each of which provides a different algorithm. However, in this way, the use of the algorithm is mixed with the algorithm itself, which does not conform to the "single responsibility principle", and the logic of deciding which algorithm to use is mixed with the algorithm itself, so that it is impossible to evolve independently. And using inheritance can not realize the dynamic switching of algorithms or behaviors during program running.
  • Use policy mode to avoid multiple conditional selection statements. Multiple conditional selection statement is not easy to maintain, it takes the logic of which algorithm or behavior to take and the implementation logic of the algorithm or behavior itself mixed together, Hard Coding them all in a huge multiple conditional selection statement, than the direct inheritance of the environment class method is more primitive and backward.
  • The policy pattern provides an algorithm reuse mechanism. Since algorithms are extracted separately and encapsulated in policy classes, different environment classes can reuse these policy classes easily.

Disadvantage:

  • The client must know all the policy classes and decide which one to use. This means that the client must understand the difference between these algorithms in order to choose the right one at the right time. In other words, the policy pattern only applies if the client knows all the algorithms or behaviors.
  • The policy mode will cause the system to generate many specific policy classes, and any small change will cause the system to add a new specific policy class.
  • Multiple policy classes cannot be used on the client at the same time. That is, when the policy mode is used, the client can use only one policy class at a time. One policy class cannot be used to complete some functions and then another policy class is used to complete the remaining functions.

6.10 Template method pattern

Template method pattern : Define the framework of an algorithm in an operation, while deferring some steps to subclasses. The template method pattern allows subclasses to redefine certain steps of an algorithm without changing its structure.

Example:

Template method mode usage scenario

The template approach pattern is often used by the architect to build the framework of the project. The architect defines the skeleton of the framework and the programmer inherits the structure of the framework and is responsible for filling in the blanks Hook method: Hook functions in various frameworks often specify the name of each hook function and the execution time at initialization, and users only need to inject custom logic code into the hook function

  • Callback function: The callback function is executed at a specific time, but the specific operation is implemented by the specific function. Encapsulate the changes into a function and the rest becomes a template

The specific application of template method pattern is divided into three categories:

  • Abstract method: An abstract method is declared by an abstract class and implemented by its concrete subclasses.

  • Concrete method: A concrete method is declared and implemented by an abstract or concrete class, and its subclasses can be overridden or directly inherited.

  • Hook method: A hook method is declared and implemented by an abstract or concrete class, and its subclasses may extend it. Usually the implementation given in the parent class is an empty implementation that is used as the default implementation for the method, although the hook method can also provide a non-empty default implementation. The hook method implemented in the subclass constrains the execution of the parent class method, and realizes the reverse control of the subclass to the parent class behavior.

Make a cup of coffee

First let's make a cup of coffee, generally speaking, the steps of making coffee are usually as follows:

  1. Boil the water first.

  2. Brew coffee with boiling water;

  3. Pour the coffee into the cup;

  4. Add sugar and milk.

Let's use es5 to get a cup of coffee:

js
var Coffee = function () {};
+Coffee.prototype.boilWater = function () {
+  console.log('The water is boiling');
+};
+Coffee.prototype.brewCoffeeGriends = function () {
+  console.log('Brew coffee with boiling water');
+};
+Coffee.prototype.pourInCup = function () {
+  console.log('Pour the coffee into the cup');
+};
+Coffee.prototype.addSugarAndMilk = function () {
+  console.log('Add sugar and milk');
+};
+// Encapsulation hands over the implementation details to the internals of the class
+Coffee.prototype.init = function () {
+  this.boilWater();
+  this.brewCoffeeGriends();
+  this.pourInCup();
+  this.addSugarAndMilk();
+};
+var coffee = new Coffee();
+coffee.init();

Make a pot of tea

In fact, the steps for making tea are not very different from those for making coffee, which is roughly like this:

  1. Boil the water;

  2. Soak tea leaves in boiling water;

  3. Pour the tea into the cup;

  4. Add lemon.

Here, let's make tea with es6:

js
class Tea {
+  constructor() {}
+  boilWater() {
+    console.log('Bring water to a boil');
+  }
+  steepTeaBag() {
+    console.log('Soaked tea leaves');
+  }
+  pourInCup() {
+    console.log('Pour into a cup');
+  }
+  addLemon() {
+    console.log('Add lemon');
+  }
+  init() {
+    this.boilWater();
+    this.steepTeaBag();
+    this.pourInCup();
+    this.addLemon();
+  }
+}
+var tea = new Tea();
+tea.init();

Now it's time to think, we just made a cup of coffee and a pot of tea, do you think these two processes are much the same. We can easily find out what they have in common, the difference is the raw material, tea and coffee, we can abstract them as "drinks" wow; The way of soaking is different, one is brewing, the other is soaking, we can abstract this behavior as "soaking"; The spices added are also different, adding sugar and milk, adding lemon, they can also be abstracted as "seasoning".

Such an analysis, is not very clear acriz, we sort it out is:

  1. Boil the water;

  2. Brew drinks with boiling water;

  3. Pour the drink into the glass;

Step 4 Add seasoning.

Attention, everyone! Attention, everyone! Here comes the hero! We've thrown out the concept before, so we can now create an abstract superclass to represent the process of making a drink. So, abstract superclasses?

An abstract class?

Abstract classes cannot be instantiated; they must be inherited. All subclasses that inherit an abstract class will have interface methods identical to those of the abstract class, and the main role of the abstract class is to define these public interfaces for its subclasses.

Through the above analysis, it is specifically to find out the common steps of making tea and making coffee, encapsulate them into the parent class, that is, the abstract class, and then write different steps in the subclass, that is, tea and coffee. Since an abstract class cannot be instantiated, no fear, a subclass is its instantiation.

Make a drink!

js
var Beverage = function () {};
+Beverage.prototype.boilWater = function () {
+  console.log('Boil the water');
+};
+Beverage.prototype.brew = function () {};
+Beverage.prototype.pourInCup = function () {};
+Beverage.prototype.addCondiments = function () {};
+// Abstract method
+Beverage.prototype.init = function () {
+  this.boilWater();
+  this.brew();
+  this.pourInCup();
+  this.addCondiments();
+};
+var Coffee = function () {
+  // Take the constructor of the parent class and execute it
+  Beverage.apply(this, arguments);
+  // Just like es6's super execution, this will only have the properties of the object after execution
+};
+Coffee.prototype = new Beverage();
+var coffee = new Coffee();
+coffee.init();
+var Tea = function () {};
+Tea.prototype = new Beverage();
+Tea.prototype.brew = function () {
+  console.log('Soak the tea leaves in boiling water');
+};
+Tea.prototype.pourInCup = function () {
+  console.log('Pour the tea into the cup');
+};
+Tea.prototype.addCondiments = function () {
+  console.log('Add lemon');
+};
+var tea = new Tea();
+tea.init();

Both coffee and tea are made here, is it not as cumbersome as before, and the code here is very advanced.

Coffee and Tea are represented by the parent class Beverage, and then the subclass is Coffee and Tea, because Beverage is an abstract existence, and the subclass needs to inherit it. The process of brewing a drink can be understood as a template pattern, the abstract class Beverage, and the abstract method init() is implemented in the subclass. js inheritance is based on prototype chain inheritance, where prototype is the prototype chain of the class. Since there is no corresponding init() on the prototype of the coffee object and tea object, the request will follow the prototype chain to find the init() of the parent class Beverage. When subclasses look for corresponding properties and methods, they will follow the prototype chain to find them, first looking for themselves, and if they do not find them, they will follow the search inside the parent class.

The reason why Beverage.prototype.init is called a template method is that it encapsulates the algorithm framework of the subclass, which serves as a template for the algorithm and instructs the subclass to execute which methods in which order.

Advantages:

  • Formally define an algorithm in the parent class, and let its subclasses implement the details of the processing, and the subclasses implement the detailed processing algorithm without changing the order of execution of the steps in the algorithm.
  • Template method pattern is a code reuse technique, it is particularly important in class library design, it extracts the common behavior of the class library, puts the common behavior in the parent class, and through its subclasses to achieve different behavior, it encourages us to use inheritance properly to achieve code reuse. A reverse control structure can be implemented where subclasses override the hook methods of the parent class to decide whether a particular step needs to be performed.
  • In the template method pattern, the basic method of the parent class can be overridden by subclasses, different subclasses can provide different implementations of the basic method, and it is easy to replace and add new subclasses, which conforms to the principle of single responsibility and the principle of open and close.

Disadvantage:

  • It is necessary to provide a subclass for different implementations of each basic method. If there are too many variable basic methods in the parent class, the number of classes will increase, the system will become larger, and the design will become more abstract. In this case, the bridge pattern can be combined to design.

6.11 Visitor Pattern

Visitor Pattern:Provides a representation of operations that act on elements of an object structure, which allows us to define new operations on those elements without changing their class. Visitor pattern is an object behavior pattern.

Example:

Visitor pattern is a more complex behavioral design pattern, which consists of two main components: visitor and visited elements. These visited elements usually have different types, and different visitors can access them differently. The visitor pattern allows users to extend the functionality of the system without modifying the existing system, adding new operations to these different types of elements.

When using the visitor pattern, the accessed elements usually do not exist separately, they are stored in a collection called an "object structure", and the visitor iterates through the object structure to achieve a one-by-one operation on the elements stored in it.

js
// Visitor pattern: DOM event binding
+var bindEvent = function(dom, type, fn, data) {
+    if (dom.addEventListener) {
+        dom.addEventListener(type, fn, false);
+    } else if (dom.attachEvent) {
+        // dom.attachEvent('on'+type, fn);
+        var data = data || {};
+        dom.attachEvent('on' + type, function(e) {
+            // In IE this points to window, use call to change the point of this
+            fn.call(dom, e, data);
+        });
+    } else {
+        dom['on' + type] = fn;
+    }
+}
+function $(id) {
+    return document.getElementById(id);
+}
+
+bindEvent($(demo), 'click', function() {
+    // this points to the dom object
+    this.style.background = 'red';
+});
+
+bindEvent($('btn'), 'click', function(e, data) {
+    $('text').innerHTML = e.type + data.text + this.tagName;
+}, { text: 'demo' });

The idea of visitor pattern is to add new operation methods to the operand without changing it, so as to achieve access to the operand. We know that the purpose of call and apply is to change the scope of function execution, which is the essence of the visitor pattern. call and apply are two ways to make an object run in another scope.

js
// Array method encapsulation
+var Visitor = (function() {
+    return {
+        splice: function() {
+            var args = Array.prototype.splice.call(arguments, 1);
+            return Array.prototype.splice.apply(arguments[0], args);
+        },
+        push: function() {
+            var len = arguments[0].length || 0;
+            var args = this.splice(arguments, 1);
+            arguments[0].length = len + arguments.length - 1;
+            return Array.prototype.push.apply(arguments[0], args);
+        },
+        pop: function() {
+            return Array.prototype.pop.apply(arguments[0]);
+        }
+    }
+})();
+
+var a = new Object();
+Visitor.push(a,1,2,3,4);
+Visitor.push(a,4,5,6);
+Visitor.pop(a);
+Visitor.splice(a,2);

The visitor pattern solves the coupling between the data and the manipulation of the data, making the manipulation of the data independent of the data, so that it can freely evolve. Therefore, the visitor pattern is more suitable for those environments where the data is stable but the data manipulation method is variable.

Advantages:

  • Easy to add new access operations. Using the visitor pattern, adding a new access operation means adding a new concrete visitor class, which is simple to implement without modifying the source code and conforms to the "open and closed principle".
  • Centralize access to element objects into a single visitor object, rather than spreading it across individual element classes. Class responsibilities are clearer, facilitating reuse of element objects in the object structure, and the same object structure can be accessed by multiple different visitors.
  • Enables users to define operations that act on an existing element class hierarchy without modifying it.

Disadvantage:

  • Adding new element classes is difficult. In the visitor pattern, adding a new element class means adding a new abstract operation to the abstract visitor role and a corresponding concrete operation to each concrete visitor class, which violates the "open closed principle".
  • Break the package. The visitor pattern requires the visitor object to access and invoke the operations of each element object, which means that the element object must sometimes expose some of its own internal operations and internal state, otherwise it cannot be accessed by the visitor.

VII.Sum up

After systematically studying design patterns, you can see in your past development experience that design patterns are everywhere. Before learning design patterns, we often rely on past experience and wisdom to improve the design of a system, and many of these experiences coincide with the idea of a certain design pattern.

There are still some places that are not fully understood, and I would like to point out the mistakes in the article.

VIII.Reference material

`,385)]))}const N=q(I,[["render",S]]);export{U as __pageData,N as default}; diff --git a/assets/src_article_designMode.md.-Ql_1mMt.lean.js b/assets/src_article_designMode.md.-Ql_1mMt.lean.js new file mode 100644 index 0000000000..49dd00a79c --- /dev/null +++ b/assets/src_article_designMode.md.-Ql_1mMt.lean.js @@ -0,0 +1,743 @@ +import{_ as i,a,b as n,c as e,d as t,e as h,f as l,g as p,h as k,i as r,j as o,k as d,l as E,m as c,n as g,o as y,p as F,q as u,r as m,s as b,t as f,u as C,v as A,w as B,x as v,y as D,z as w,A as x,B as j}from"./chunks/访问者._0swtoJg.js";import{_ as q,o as P,c as T,a3 as _}from"./chunks/framework.C-ai2y4t.js";const U=JSON.parse('{"title":"23 classic design patterns","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/designMode.md","filePath":"src/article/designMode.md","lastUpdated":1726550590000}'),I={name:"src/article/designMode.md"};function S(M,s,z,L,V,W){return P(),T("div",{"data-pagefind-body":!0},s[0]||(s[0]=[_(`

23 classic design patterns

The Design Pattern is a set of frequently used, widely known, cataloged code design experiences that are used in order to reuse code, make it easier for others to understand, and ensure code reliability.

In the book "Design Patterns: The Foundation of Reusable Object-Oriented Software" introduced 23 classic design patterns, but the design pattern is not only these 23, with the development of software development industry, more and more new patterns continue to be born and applied. Experienced developers learn design patterns that can be corroborated with past experience, making it easier to understand them.

A design pattern generally contains elements such as the pattern name, problem, purpose, solution, and effect. The problem describes when patterns should be used, and it contains problems with the design and why they exist. A solution describes the components of a design pattern and how these components relate to each other, their respective responsibilities, and how they work together. Typically, the solution is described through UML class diagrams and core code. Effects describe the advantages and disadvantages of the pattern and the trade-offs that should be made when using the pattern.

Why learn design patterns:

  • Design patterns are derived from the experience and wisdom of many experts. They are successful and reusable design solutions from many excellent software systems. Using these solutions will allow us to avoid doing some repetitive work

  • Design patterns provide a common set of design vocabulary and a common form to facilitate communication and exchange between developers, making design solutions more understandable

  • Most of the design patterns take into account the reusability and extensibility of the system, which enables us to better reuse some existing design schemes, functional modules and even a complete software system, so as to avoid us often doing some repetitive design and writing some repetitive code

  • Proper use of design patterns and documentation of their use will help others understand the system more quickly

  • Learning design patterns will help beginners understand object-oriented ideas more deeply

Reserve knowledge

  • Abstract class: The general abstract class is as a base class, for example, "computer" can be used as an abstract class, according to the abstract class derived "desktop computer" and "laptop computer" 2 concrete classes. Abstract classes are generally not instantiated.

  • Combination is better than inheritance: inheritance cannot be abused to expand functionality, and combination is more flexible. Also take the "computer" abstract class for example, if we use inheritance to distinguish different types of "computer" we can derive "desktop computer" and "laptop computer", if we add another dimension, according to the brand can continue to subdivide "Lenovo desktop computer", "Lenovo laptop", "Apple desktop computer" and "Apple laptop" and so on. If you add another dimension and continue to subdivide, it is clear that inheritance is not adequate. At this time, you can use inheritance and composition, and the combined object can also be abstract design:

    ts
    interface Brand {
    +  // ...
    +}
    +interface Lenovo extends Brand {
    +  // ...
    +}
    +interface Apple extends Brand {
    +  // ...
    +}
    +interface CPU {
    +  // ...
    +}
    +interface Inter extends CPU {
    +  // ...
    +}
    +interface AMD extends CPU {
    +  // ...
    +}
    +interface Computer {
    +  // ...
    +}
    +
    +interface DesktopComputer extends Computer {}
    +interface NotebookComputer extends Computer {}

I, UML class diagram

Each pattern has a corresponding object structure diagram, and in order to show the details of the interaction between objects, sometimes a 'UML' diagram is used to show how it works. Here will not be the various elements of 'UML' mentioned, just want to talk about the relationship between the classes in the class diagram, can understand the meaning of the lines and arrows between the classes in the class diagram, it is enough to deal with daily work and communication. At the same time, we should be able to match the meaning of the class diagram to the final code. With this knowledge, there is no problem looking at the design pattern structure diagram in the later sections.

1.1 inherit

Inheritance is represented directly by a hollow arrow.

1.2 realize

The implementation relationship is represented by a dashed line with a hollow arrow.

1.3 assembly

Like aggregation relations, composition relations also represent the semantics of a whole made up of parts. For example, a company is composed of multiple departments, but the combinatorial relationship is a special aggregation relationship of strong dependence, if the whole does not exist, then the part does not exist. For example, the company no longer exists, and the department will no longer exist.

1.4 Polymerization

Aggregation relationships are used to represent relationships between entity objects, representing the semantics of a whole made up of parts, such as a department consisting of multiple employees. Unlike combinatorial relations, the whole and the part are not strongly dependent, and even if the whole does not exist, the part still exists. For example, if the department is abolished, the personnel will not disappear, they will still exist.

1.5 Association

The association relationship is expressed by a straight line, which describes the structural relationship between objects of different classes. It is a static relationship, usually unrelated to the running state, and generally determined by common sense and other factors. It is generally used to define the static, natural structure between objects, so the association relationship is a "strong association" relationship.

For example, the relationship between the passenger and the ticket is an association relationship, the student and the school is an association relationship, the association relationship does not emphasize the direction by default, indicating that the object knows each other. If particular emphasis is placed on direction, as shown in the figure below, it means that A knows B, but B does not know A.

1.6 dependence

Dependencies are represented by A set of dotted lines with arrows, such as A depends on B, which describes the relationship between one object and another object at runtime.

Unlike an association relationship, it is a temporary relationship that usually occurs during run time, and dependencies may change as the run time changes. Obviously, dependence also has a direction, two-way dependence is a very bad structure, we should always maintain one-way dependence, eliminate the generation of two-way dependence.

II, six principles

2.1 Open and Close principle

> A software entity should be open for extension and closed for modification. That is, software entities should extend as far as possible without modifying the original code.

An important issue for any software is that its requirements change over time. When the software system needs to face new requirements, we should try to ensure that the design framework of the system is stable. If a software design conforms to the open-close principle, it can be very convenient to extend the system, and there is no need to modify the existing code when expanding, so that the software system has good stability and continuity while having adaptability and flexibility. As the software scale becomes larger and larger, the software life becomes longer and longer, and the software maintenance cost becomes higher and higher, it becomes more and more important to design the software system that meets the principle of open and close.

In order to meet the open-close principle, the system needs to be abstract design, abstraction is the key to the open-close principle. In programming languages such as Java and C#, a relatively stable abstraction layer can be defined for the system, and different implementation behaviors can be moved to the concrete implementation layer. In many object-oriented programming languages, interfaces, abstract classes and other mechanisms can be used to define the abstract layer of the system, and then extend it through concrete classes. If it is necessary to modify the behavior of the system, there is no need to make any changes to the abstract layer, only need to add new concrete classes to achieve new business functions, to achieve the expansion of the system function on the basis of not modifying the existing code, to meet the requirements of the open-close principle.

Advantages: The advantage of practicing the open-close principle is that you can extend the function of the program without changing the original code. The expansibility of the program is increased, and the maintenance cost of the program is reduced. **.

2.2 Richter Substitution Principle

> Any reference to a base class object can transparently use the object of its subclass

The Richter substitution principle tells us that replacing a base class object with its subclass object in software will not cause any errors and exceptions, and the reverse is not true, if a software entity uses a subclass object, then it may not be able to use the base class object. For example, if I like animals, then I must like dogs, because dogs are a subclass of animals. But I like dogs, and it does not follow that I like animals, because I do not like mice, even though they are animals.

For example, if there are two classes, one is BaseClass, the other is SubClass, and the SubClass is a subclass of the BaseClass class, then a method can accept a base class object of type BaseClass, such as: method1(base), then it must accept a subclass object of type BaseClass sub, and method1(sub) will work. The reverse substitution is not true, if a method method2 accepts sub of type BaseClass as an argument: method2(sub), then in general you can't have method2(base) unless it's an overloaded method.

Richter substitution principle is one of the important ways to achieve the open and close principle, because the use of base class objects can use subclass objects, so in the program to try to use the base class type to define the object, and then determine its subclass type at run time, with subclass objects to replace the parent object.

Advantages: You can test the correctness of the use of inheritance, and restrict the overflow of inheritance in use..

2.3 Reliance on the inversion principle

> Abstractions should not depend on concrete classes, and concrete classes should depend on abstractions. In other words, program against the interface, not the implementation.

The principle of dependency inversion requires us to refer to high-level abstract layer classes as far as possible when passing parameters in program code or in association relations, that is, to use interfaces and abstract classes for variable type declaration, parameter type declaration, method return type declaration, and data type conversion, etc., rather than using concrete classes to do these things. In order to ensure the application of this principle, a concrete class should only implement methods declared in the interface or abstract class, and not give extra methods, otherwise it will not be able to call the new methods added in the subclass.

After the introduction of the abstraction layer, the system will have good flexibility, in the program as far as possible to use the abstraction layer for programming, and the specific class is written in the configuration file, so that if the system behavior changes, only need to extend the abstraction layer, and modify the configuration file, without modifying the original system source code, in the case of no modification to expand the function of the system. Meet the requirements of the open and close principle.

Advantages: Build a framework through abstraction and establish associations between classes to reduce coupling between classes. Moreover, the system built with abstraction is more stable, more scalable, and easier to maintain than the system built with concrete implementation. **.

2.4 Principle of single responsibility

> A class is only responsible for the corresponding responsibilities in one functional area, or it can be defined that there should be only one reason for a class to change.

The principle of single responsibility tells us that a class can't be too "tired"! In a software system, the more responsibilities a class (from large modules to small methods) takes on, the less likely it is to be reused, and too many responsibilities a class takes on, the equivalent of coupling these responsibilities together, when one of the responsibilities changes, it may affect the operation of the other responsibilities, so the separation of these responsibilities. Encapsulate different responsibilities in different classes, that is, encapsulate different reasons for change in different classes, and encapsulate multiple responsibilities in the same class if they always change at the same time.

The principle of single responsibility is a guideline to achieve high cohesion and low coupling. It is the simplest but most difficult principle to apply. It requires designers to discover different responsibilities of a class and separate them, while discovering multiple responsibilities of a class requires designers to have strong analysis and design ability and relevant practical experience.

Advantages: If the class and method responsibilities are clearly divided, not only can improve the readability of the code, but also effectively reduce the risk of program errors, because the clear code will make the bug nowhere to hide, but also conducive to bug tracking, that is, reduce the maintenance cost of the program. **.

2.5 Demeter's Law (Least Know Principle)

> A software entity should interact with other entities as little as possible

If a system conforms to Dimitar's law, then when one of the modules is modified, it will affect the other modules as little as possible, and it will be relatively easy to expand, which is a limit on the communication between software entities, Dimitar's law requires limiting the width and depth of communication between software entities. Demeter's rule can reduce the coupling degree of the system and keep the loose coupling relationship between classes.

Demeter's law requires that when designing a system, we should minimize the interaction between objects, if two objects do not need to communicate directly with each other, then the two objects should not have any direct interaction, if one of the objects needs to call a method of another object, you can forward the call through a third party. In short, it is to reduce the coupling degree between existing objects by introducing a reasonable third party.

When applying Dimitter's rule to system design, we should pay attention to the following points: in the division of classes, we should try to create loosely coupled classes, the lower the degree of coupling between classes, the more conducive to reuse, and once a class in loose coupling is modified, it will not cause too much impact on the associated classes. In the structural design of the class, every class should minimize the access permissions of its member variables and member functions. In class design, whenever possible, a type should be designed as an invariant class. References to other classes from one object should be kept to a minimum.

Advantages: The practice of Demeter's rule can well reduce the coupling between classes, reduce the degree of correlation between classes, and make the collaboration between classes more direct..

2.6 Interface Separation Rule

> The use of multiple specialized interfaces rather than a single general interface means that the client should not rely on interfaces that it does not need.

According to the principle of interface isolation, when an interface is too large, we need to split it into smaller interfaces, and the client using the interface only needs to know the methods associated with it. Each interface should assume a relatively independent role, do not do what should not be done, do what should be done.

When using the interface isolation principle, you need to pay attention to the granularity of the control interface. If the interface is too small, the system may overflow interfaces, which is not conducive to maintenance. The interface can not be too large, too large interface will violate the interface isolation principle, poor flexibility, very inconvenient to use.

Advantages: Avoid the method of containing different responsibilities in the same interface, and the division of interface responsibilities is more clear, in line with the idea of high cohesion and low coupling..

2.7 Principle of Synthetic reuse (outside the six)

> Try to use object composition rather than inheritance for reuse purposes

The principle of composite reuse is to use some existing objects in a new object through association relations (including composition relations and aggregation relations), so that it becomes part of the new object, and the new object achieves the purpose of reuse functions by delegating methods to the existing object. In short, when reuse, use composition/aggregation relationships (association relationships) as much as possible and use inheritance less.

In object-oriented design, there are two ways to reuse existing designs and implementations in different environments, namely through composition/aggregation relationships or through inheritance, but the use of composition/aggregation should be considered first. Composition/aggregation can make the system more flexible and reduce the coupling degree between classes. Changes in a class have relatively little impact on other classes, and then inheritance is considered. When using inheritance, it is necessary to strictly follow the Richlist substitution principle. Effective use of inheritance will help to understand the problem and reduce complexity, while abuse of inheritance will increase the difficulty of system construction and maintenance as well as the complexity of the system, so inheritance reuse should be carefully used.

Advantages: Avoid abuse of inheritance when reuse, rational use of combination relations, increase flexibility..

2.8 Six principles - Learning experience

Among the six principles, the opening and closing principle, the Richter replacement principle, and the dependence and inversion principle are closely related, and the latter two are important prerequisites for realizing the opening and closing principle, and they have good scalability and maintainability through abstract design in use.

The principle of knowing the least can reduce coupling, reduce unnecessary interaction, advocate the design of interfaces and classes to be simple and easy to use, encapsulate complex logic and provide simple and easy-to-use interfaces.

Single Responsibility principle Divide the classes and methods in a project by responsibility to avoid overburdening a single class. The more responsibilities, the less likely they are to be reused or the more cumbersome they are to use.

Interface separation principle The function of the complex interface is subdivided into a number of specific functions of the interface, only do the thing to do, reduce the coupling, but the granularity can not be too fine, easy to lead to too many interfaces. The single responsibility principle emphasizes the design of a single class according to the subdivision of responsibilities, and the interface separation principle emphasizes the coupling between classes to establish the least possible dependency.

III. Pattern classification

There are 23 distinct design patterns in Design Patterns: The Foundations of Reusable Object-Oriented Software, each of which provides a solution to a repeatable design problem. According to their purpose, design patterns can be divided into three types: 'Creational', 'Structural' and 'Behavioral', in which the creational pattern is mainly used to describe how to create objects, and the structural pattern is mainly used to describe how to achieve the combination of classes or objects. Behavioral patterns are primarily used to describe how classes or objects interact and how responsibilities are assigned.

In addition, design patterns can be divided into class patterns and object patterns, depending on whether a pattern primarily deals with relationships between classes or between objects. We often use a combination of the two categories, for example, the singleton pattern is the object creation pattern, and the template method pattern is the class behavior pattern.

3.1 Create type

The 'Creational Pattern' abstracts the class instantiation process, separating the creation and use of objects in a module. In order to make the structure more clear, the outside world only needs to know their common interface for these objects, but is not clear about its specific implementation details, so that the design of the whole system is more in line with the principle of single responsibility.

  1. Simple Factory Pattern (' Simple Factory pattern ')
  2. Factory Method Pattern (' Factory method pattern ')
  3. Abstract Factory Pattern (' Abstract factory pattern ')
  4. 'Singleton Pattern'
  5. Builder Pattern (' Builder pattern ')
  6. Prototype Pattern (' Prototype pattern ')

3.2 Structural type

Structural patterns describe how classes or pairs of objects can be combined to form larger structures, like building blocks that can be combined to form complex, more powerful structures. Structured patterns can be divided into class structured patterns and object structured patterns:

  • The class structure pattern is concerned with the composition of classes. Multiple classes can be combined into a larger system. In the class structure pattern, there are generally only inheritance relations and implementation relations.

  • The object structure pattern is concerned with the combination of classes and objects, allowing an instance object of one class to be defined in another class through association, and its methods to be invoked through that object. According to the principle of "synthetic reuse", the associative relation is used to replace the successor relation in the system as much as possible, so most of the structural patterns are object structural patterns.

  1. Appearance mode
  2. Adapter mode
  3. Bridge mode
  4. Proxy mode
  5. Decorator mode
  6. Enjoy meta mode

3.3 Behavioral patterns

Behavioral patterns are abstractions that divide responsibilities and algorithms between different objects. The behavioral pattern focuses not only on the structure of classes and objects, but also on the interactions between them. Behavioral patterns allow you to more clearly divide the responsibilities of classes and objects and study the interactions between instance objects at runtime.

  1. Responsibility chain mode
  2. Command mode
  3. Interpreter mode
  4. Iterator mode
  5. Intermediary model
  6. Memo mode
  7. Observer mode
  8. Status mode
  9. Policy mode
  10. Template Method mode
  11. Visitor pattern

IV, create type

4.1 Simple Factory mode

Simple Factory Pattern: A single class (factory class) is defined to be responsible for creating instances of other classes. Instances of different classes can be returned based on the parameters of the creation method, and the created instances usually have a common parent class.

Example:

The simple factory model is like a foundry, a factory can produce a variety of products. For example, a beverage processing plant helps produce both Pepsi and Coca-Cola, and the processing plant produces different products according to the input parameter 'Type'.

ts
interface Cola {}
+
+interface CocaCola extends Cola {}
+
+interface PepsiCola extends Cola {}
ts
// SimpleFactory
+const createColaWithType = (type: number) => {
+  switch (type) {
+    case 0:
+      return new CocaCola();
+    case 1:
+      return new PepsiCola();
+    default:
+      return null;
+      break;
+  }
+};
ts
const cocaCola: CocaCola = createColaWithType(0);
+
+const pepsiCola: PepsiCola = createColaWithType(1);

Advantages:

  • The user only needs to pass a correct agreed parameter to the factory class, and you can get the object you need, without knowing its creation details, to reduce the coupling of the system to a certain extent.
  • The client does not need to know the class name of the specific product class created, only needs to know the parameters corresponding to the specific product class, reducing the memory cost of the developer.

Disadvantage:

  • If new products are added to the business, it is necessary to modify the original judgment logic of the factory class, which is actually contrary to the principle of opening and closing.
  • When there are many product types, the factory logic may be too complicated. Therefore, the simple factory model is more suitable for the situation where the product variety is relatively small and the probability of increasing is very low.

4.2 Factory Method mode

Factory Method Pattern (' factory method pattern ') is also known as the factory pattern, the factory parent class is responsible for defining the public interface for creating product objects, and the factory subclass is responsible for generating concrete product objects, that is, through different factory subclasses to create different product objects.

Example:

There are some differences between the factory method and the simple factory, the simple factory is the production of different products by a foundry, while the factory method is the abstraction of the factory, different products are produced by a specific factory. The Coca-Cola factory specializes in the production of Coca-Cola, and the Pepsi factory specializes in the production of Pepsi.

ts
// Factory abstract class
+class Cola {}
+
+// The Coca-Cola Factory
+class CocaCola extends Cola {}
+
+// Pepsi Factory
+class PepsiCola extends Cola {}
ts
// Different products are produced according to different factory types
+const cocaCola = new CocaCola();
+const pepsiCola = new PepsiCola();

Advantages:

  • Users only need to care about the specific factory corresponding to the product they need, do not need to care about the details of the creation of the product, do not need to know the class name of the specific product class.
  • When a new product is added to the system, it is not necessary to modify the interface provided by the abstract factory and the abstract product, nor to modify the client and other specific factories and specific products, but only to add a specific factory and its corresponding specific products, in line with the open and close principle.

Disadvantage:

  • When a new product is added to the system, in addition to the new product class, the corresponding specific factory class must be provided. Therefore, the number of classes in the system will be increased in pairs, increasing the complexity of the system.

4.3 Abstract factory pattern

The abstract factory pattern does not directly generate instances, but is used to create clusters of product classes.

Abstract Factory Pattern: Provides an interface for creating a series of related or interdependent objects without specifying their concrete classes.

Example:

The difference between the abstract factory and the factory method is that the factory that produces the product is abstract. For example, when Coca-Cola produces Coke, it also needs to produce bottles and boxes for Coke. The bottles and boxes are also customized by Coca-Cola, and Pepsi will also have this demand. At this time, our factory is not only a factory that produces cola drinks, but also has to produce bottles and boxes with the same theme at the same time, so it is an abstract theme factory, specializing in the production of different goods with the same theme.

ts
// Coke abstract classes and derived classes
+class Cola {}
+
+class CocaCola extends Cola {}
+
+class PepsiCola extends Cola {}
+
+// Bottle abstract and derived classes
+class Bottle {}
+
+class CocaColaBottle extends Bottle {}
+
+class PepsiColaBottle extends Bottle {}
+
+// Box abstract classes and derived classes
+class Box {}
+
+class CocaColaBox extends Box {}
+
+class PepsiColaBox extends Box {}
+
+// Factory abstract class
+const Factory = {
+  createCola: () => new Cola(),
+  createBottle: () => new Bottle(),
+  createBox: () => new Box(),
+};
+
+// Coca-Cola Theme Factory
+const CocaColaFactory = {
+  createCola: () => new CocaCola(),
+  createBottle: () => new CocaColaBottle(),
+  createBox: () => new CocaColaBox(),
+};
+
+// Pepsi Theme Factory
+const PepsiColaFactory = {
+  createCola: () => new PepsiCola(),
+  createBottle: () => new PepsiColaBottle(),
+  createBox: () => new PepsiColaBox(),
+};
ts
// Coca-Cola theme
+const cocaCola = CocaColaFactory.createCola();
+const cocaColaBottle = CocaColaFactory.createBottle();
+const cocaColaBox = CocaColaFactory.createBox();
+
+// Pepsi theme
+const pepsiCola = PepsiColaFactory.createCola();
+const pepsiColaBottle = PepsiColaFactory.createBottle();
+const pepsiColaBox = PepsiColaFactory.createBox();

Advantages:

  • Product specific code isolation at the application layer, do not need to care about product details. When multiple objects in a product family are designed to work together, it ensures that the client always uses only objects in the same product family. This is a very practical design pattern for software systems that need to determine their behavior based on the current environment.

Disadvantage:

  • Specifies the set of all products that can be created, the difficulty of extending new products in the product family, and the need to modify the interface of the abstract factory.

4.4 Singleton pattern

Singleton Pattern: The singleton pattern ensures that there is only one instance of a class and provides a full access point to it.

Example:

In singleton mode, the corresponding class can generate only one instance. Just as a kingdom can only have one king, once the affairs of the kingdom are too many, this only king is easy to take on too much responsibility.

ts
class Singleton {}
+
+function createSingleton() {
+  let instance;
+  return function () {
+    if (!instance) return new Singleton();
+    return instance;
+  };
+}

Advantages:

  • Provides controlled access to unique instances. Because a singleton encapsulates its unique instance, it has tight control over how and when customers access it.
  • This class saves system resources because it has only one object in system memory.

Disadvantage:

Since there is no abstraction layer in the singleton pattern, singleton classes are difficult to extend.

  • For languages that have garbage collection systems, such as Java and C#, objects may be recycled if they are not utilized for a long time. If the singleton holds some data, it will no longer exist when it is reinstantiated after collection.

4.5 Builder Pattern

Builder Pattern: Also known as the creator pattern, it separates the construction of a complex object from its representation, allowing the same construction process to create different representations.

The factory pattern is mainly for the creation of object instances or class clusters (abstract factories), concerned with the final output (creation) is what, not concerned with the creation process. The builder pattern is concerned with the entire process of creating the object, down to every detail of creating the object.

Example:

The main roles of the generator mode are as follows:

  1. Generator: The product construction steps common to all types of generators in the interface life
  2. Concrete generator: Provides different implementations of the construction process. Concrete generators can also construct products that do not follow a generic interface
  3. Product: is the final generated object. Products constructed from different generators need not belong to the same class of hierarchical constructs or interfaces
  4. Conductor: Define the order in which construction steps are called so that you can create and consume specific product configurations
  5. Client side: You must associate a generator object with a supervisor class. In general, you only need to do a one-time association through the parameters of the supervisor class constructor
ts
// Abstract Builder
+abstract class Builder {
+  public abstract buildPartA(): void;
+  public abstract buildPartB(): void;
+  public abstract buildPartC(): void;
+  public abstract buildProduct(): Product;
+}
+
+// Concrete builder
+class ConcreteBuilder extends Builder {
+  private product: Product;
+  constructor(product: Product) {
+    super();
+    this.product = product;
+  }
+
+  public buildPartA(): void {}
+  public buildPartB(): void {}
+  public buildPartC(): void {}
+
+  // Finally build a product
+  public buildProduct(): Product {
+    return this.product;
+  }
+}
+
+// Product role
+class Product {
+  public doSomething(): void {
+    // Independent business
+  }
+}
+
+// director
+class Director {
+  private _builder: Builder;
+  constructor(builder: Builder) {
+    this._builder = builder;
+  }
+
+  set builder(builder: Builder) {
+    this._builder = builder;
+  }
+
+  // Leave the process of handling the construction to the commander
+  public constructorProduct() {
+    this._builder.buildPartA();
+    this._builder.buildPartB();
+    this._builder.buildPartC();
+    return this._builder.buildProduct();
+  }
+}
+
+// Use
+const builder: Builder = new ConcreteBuilder(new Product());
+const director: Director = new Director(builder);
+const product: Product = director.constructorProduct();

Advantages:

  • The client does not have to know the details of the internal composition of the product, decoupling the product itself from the product creation process, so that the same creation process can create different product objects.
  • Each concrete builder is relatively independent, and has nothing to do with other concrete builders, so it is easy to replace concrete builders or add new concrete builders, and users can get different product objects using different concrete builders.
  • Adding new concrete builders does not need to modify the code of the original class library, the command class is programmed for the abstract builder class, the system is easy to expand, and conforms to the "open and close principle".
  • The product creation process can be more finely controlled. Breaking down the creation steps of complex products into different methods makes the creation process clearer and easier to use programs to control the creation process.

Disadvantage:

  • The products created by the builder mode generally have more in common and their components are similar. If the differences between products are large, the builder mode is not suitable for use, so its scope of use is limited. If the internal changes of the product are complex, it may lead to the need to define many concrete constructor classes to achieve such changes, resulting in a large system, increasing the difficulty of understanding the system and the cost of operation.

4.6 Prototype Pattern

Prototype Pattern: A prototype instance points to the class that created the object, and uses the properties and methods of the shared prototype used by the class that created the new object.

Example:

Prototype mode is like photocopying technology, copy a new object from the original object, and fine-tune the new object according to the needs.

ts
// Because it's not a constructor, you don't use capitalization
+const car = {
+  drive: function () {},
+  name: 'The Mazda 3',
+};
+
+// Create a new car x using Object.create
+const anotherCar = Object.create(someCar);
+anotherCar.name = 'Mike';
ts
const vehiclePrototype = {
+  init: function (carModel) {
+    this.model = carModel;
+  },
+  getModel: function () {
+    console.log('The vehicle mold is:' + this.model);
+  },
+};
+
+function vehicle(model) {
+  function F() {}
+  F.prototype = vehiclePrototype;
+
+  const f = new F();
+
+  f.init(model);
+  return f;
+}
+
+const car = vehicle('Ford Escort');
+car.getModel();

Advantages:

  • The prototype mode can be used to simplify the object creation process, especially for some objects with complicated creation process and many object levels, the prototype mode can save system resources and improve the efficiency of object generation.
  • It is easy to generate new objects by changing the values: some objects may differ only from one another in certain values; Using prototype mode, you can quickly copy new objects and manually modify the values.

Disadvantage:

  • All objects contained in an object need to be equipped with a clone method, which makes the amount of code in the case of more object levels will be large and more complex.

V, structural type

5.1 Decorative pattern

Decorator Pattern: The design pattern that adds new functionality to an existing object without changing its structure is called the decorator pattern, which acts as a wrapper around an existing class.

You can think of decorators as equipment purchased by game characters, such as heroes in LOL who start the game with only basic attack power and mana. However, after the purchase of equipment, you can enjoy the output bonus brought by the equipment when triggering attacks and skills. We can understand the purchase of equipment to give the hero's attack and skill related methods decorated.

Example:

The decorative mode conforms to the open-close principle and transforms or adds new functions to the parent class without changing the original class.

decoration

ts
@annotation
+class MyClass {}
+
+function annotation(target) {
+  target.annotated = true;
+}

Decorative method or attribute

js
class MyClass {
+  @readonly
+  method() {}
+}
+
+function readonly(target, name, descriptor) {
+  descriptor.writable = false;
+  return descriptor;
+}

Advantages:

  • More flexible than inheritance: unlike inheritance, which works at compile time; Decorator mode can extend the functionality of an object at run time. It is also possible to select different decorators at run time through configuration files to achieve different behavior. It can also achieve different effects through different combinations.
  • Comply with the "open and close principle" : the decorator and the decorator can vary independently. Users can add new decorative classes as needed, and then combine them when they are used, without changing the original code.

Disadvantage:

  • Decorator mode requires the creation of some concrete decorator classes, which increases the complexity of the system.

5.2 外观模式

Facade Pattern: A facade pattern defines a high-level interface that provides a unified interface for a set of interfaces in a subsystem. It makes the subsystem easier to use, not only simplifying the interfaces in the class, but also decoupling the caller from the interface. Appearance mode, also known as facade mode, is a structural design mode.

Example:

Appearance patterns provide a simple and unambiguous interface, but integrate many subsystem functions internally. Just like the image cache, which contains processing involving other subsystems such as caching, downloading, etc., the appearance pattern hides the complex logic. In the compatible browser event binding, you only need to call an 'addMyEvent' interface can be, to achieve the purpose of decoupling.

js
const addMyEvent = function (el, ev, fn) {
+  if (el.addEventListener) {
+    el.addEventListener(ev, fn, false);
+  } else if (el.attachEvent) {
+    el.attachEvent('on' + ev, fn);
+  } else {
+    el['on' + ev] = fn;
+  }
+};

Advantages:

  • Decoupling between the client and the subsystem is realized: the client does not need to know the interface of the subsystem, simplifying the process of the client calling the subsystem, making the subsystem easier to use. At the same time, it is easy to expand and maintain the subsystem.
  • Demeter's law (least know principle) : The subsystem only needs to expose the interface that needs external calls to the appearance class, and its interface can be hidden.

Disadvantage:

  • Violates the open-close principle: Adding a new subsystem without introducing abstract facade classes may require changes to facade classes or client code.

5.3 代理模式

Proxy Pattern: Provide a proxy for an object, and this proxy object controls access to the original object.

Example:

The agent model is like a housing agent, the buyer can only buy a house through the intermediary, the agent has all the functions of the agent, just as the landlord has the function of selling the house, the intermediary also has the function of selling the house. In addition, the agent instance can also help the agent to carry out some additional processing, such as the function of the intermediary to help the landlord screen quality buyers, and help the landlord pass some unqualified buyers. The same pattern applies to message queues.

Reference 'koa' in the proxy mode, the 'response' on some properties and methods proxy out, easy to use

js
/**
+ * Response delegation.
+ */
+const delegate = require('delegates');
+
+const prototype = (module.exports = {});
+
+delegate(prototype, 'response')
+  .method('attachment')
+  .method('redirect')
+  .method('remove')
+  .method('vary')
+  .method('has')
+  .method('set')
+  .method('append')
+  .method('flushHeaders')
+  .access('status')
+  .access('message')
+  .access('body')
+  .access('length')
+  .access('type')
+  .access('lastModified')
+  .access('etag')
+  .getter('headerSent')
+  .getter('writable');

Make a proxy for 'context', 'request', 'response', protecting the real 'context', 'request', 'response'

js
this.context = Object.create(context);
+this.request = Object.create(request);
+this.response = Object.create(response);

Advantages:

  • Reduce the coupling degree of the system: The proxy mode can coordinate the caller and the called, which reduces the coupling degree of the system to a certain extent.
  • Different types of proxies can have different controls on the client's access to the target object:
  • A remote agent that allows the client to access objects on a remote machine that may have better computational performance and processing speed and can respond and process client requests quickly. By using a small object to represent a large object, virtual agents can reduce the consumption of system resources, optimize the system, and increase the speed of operation.
  • The protection agent can control the client's permission to use real objects.

Disadvantage:

  • Adding a proxy object between the client and the proxy object may slow down client requests.

5.4 Flyweight Pattern

Flyweight Pattern: The meta mode is a mode that optimizes program performance, essentially reducing the number of objects created. Using sharing technology to reuse a large number of fine-grained objects, reduce the program memory occupation, improve the performance of the program. Share metamode can be used when there are a large number of similar objects that occupy a large amount of memory. Most of the state in an object can be extrapolated to external state.

Example:

For example, a music service can be divided into free users and member users based on fees. Free users can only listen to some free music, and member users can listen to all music and can download it. Although there are some differences in permissions between the two, the music they enjoy is from the same library, so all the music needs to be saved only one copy. In addition, if there is no music in the music library, you need to add the music, and then other services can also enjoy the new music, which is equivalent to the function of the share pool or cache pool.

The share mode area ensures that the internal state is shared, such as the music library, while the external state is customized according to different needs, such as various access rights, and the internal state cannot be changed during use to achieve the purpose of sharing.

ts
// Music service
+const MusicService = {}
+
+// Shared music library
+const musicLibrary = {};
+
+// Listen to music
+const listenToMusic = (music) => {
+    ...
+}
+// Download music
+const downloadMusic = (music) => {
+    ...
+}
+
+
+// Free music service
+const FreeMusicService = {
+    listenFreeMusic: (music)=>{
+        if(isMusicFree(music)){
+            // If it is free, play it
+            listenToMusic()
+        }else{
+         // If it is paid music, the user is prompted to upgrade the Vip Vip
+            console.log("please upgrade to Vip")
+        }
+    }
+}
+
+
+// Vip Music Service
+const VipMusicService = {
+    // You can listen to all the music
+    listenMusic
+    // You can download music
+    downloadMusic
+}

Advantages:

  • The use of the share module can reduce the number of objects in memory, so that the same object or similar objects in memory only one copy, reduce the system memory usage, can also improve performance.
  • The external state of the share meta pattern is relatively independent and does not affect its internal state, so that share meta objects can be shared in different environments.

Disadvantage:

  • Using the meta pattern requires the separation of internal and external states, which complicates the logic of the program.
  • Object reuse in buffer pools requires consideration of threading issues.

5.5 Simple Factory Pattern

Simple Factory Pattern: Separate the abstract part from its implementation part so that they can both vary independently.

Example:

Both balls and people can move, but balls have movement and colors, and people can move and talk. Abstract the common parts.

js
class Speed {
+  // Motion module
+  constructor(x, y) {
+    this.x = x;
+    this.y = y;
+  }
+  run() {
+    console.log(\`Get into motion \${this.x} + \${this.y}\`);
+  }
+}
+
+class Color {
+  // Coloring module
+  constructor(cl) {
+    this.color = cl;
+  }
+  draw() {
+    console.log(\`Draw color \${this.color}\`);
+  }
+}
+
+class Speak {
+  constructor(wd) {
+    this.word = wd;
+  }
+  say() {
+    console.log(\`talk \${this.word}\`);
+  }
+}
+
+class Ball {
+  // Create balls that can be colored and moved
+  constructor(x, y, cl) {
+    this.speed = new Speed(x, y);
+    this.color = new Color(cl);
+  }
+  init() {
+    this.speed.run();
+    this.color.draw();
+  }
+}
+
+class Man {
+  // Humans can move and talk
+  constructor(x, y, wd) {
+    this.speed = new Speed(x, y);
+    this.speak = new Speak(wd);
+  }
+  init() {
+    this.speed.run();
+    this.speak.say();
+  }
+}
+
+const man = new Man(1, 2, 'hello ?');
+man.init();

Advantages:

  • Good scalability, in line with the principle of open and close: separation of abstraction and implementation, so that the two can change independently

Disadvantage:

  • Two independently varying dimensions need to be identified before design.

5.6 Adapter Pattern

Adapter Pattern: Adapter mode is used to solve the incompatibility of two interfaces, do not need to change the existing interface, through the packaging of a layer, to achieve normal cooperation between the two interfaces. When we try to call an interface of a module or object, but find that the format of the interface does not meet the current requirements, we can use the adapter pattern.

Example:

Event binding is compatible with all browsers

js
function addEvent(ele, event, callback) {
+    if (ele.addEventListener) {
+      ele.addEventListener(event, callback)
+    } else if(ele.attachEvent) {
+      ele.attachEvent('on' + event, callback)
+    } else {
+      ele['on' + event] = callback
+    }
+  }
+

Advantages:

  • Comply with the principle of open and close: use adapters without changing existing classes, improving class reusability.
  • Decouple the target class from the adapter class to improve program extensibility.

Disadvantage:

  • Increased the complexity of the system

VI. Behavior pattern

6.1 Chain of Responsibility Pattern

Chain of Responsibility Pattern: Avoid coupling the request sender with the receiver, make it possible for multiple objects to receive the request, connect those objects into a chain, and pass the request along the chain until an object handles it. The responsibility chain pattern is an object behavior pattern. Similar to dominoes, by requesting the first condition, subsequent conditions continue to be executed until a result is returned.

Example:

Scenario: An e-commerce has a preferential policy for users who have paid a deposit, after the formal purchase, users who have paid a deposit of 500 yuan will receive a coupon of 100 yuan, users who have paid a deposit of 200 yuan can receive a coupon of 50 yuan, and users who have not paid a deposit can only buy normally.

js
const order500 = function (orderType, pay, stock) {
+  if (orderType === 1 && pay == true) {
+    console.log('500 yuan deposit advance purchase, get 100 yuan coupon');
+  } else {
+    return 'nextSuccess';
+  }
+};
+const order200 = function (orderType, pay, stock) {
+  if (orderType === 2 && pay === true) {
+    console.log('200 yuan deposit pre-order, get 50 yuan coupon');
+  } else {
+    return 'nextSuccess';
+  }
+};
+const orderCommon = function (orderType, pay, stock) {
+  if (orderType == 3 && stock > 0) {
+    console.log('Regular purchase, no coupon');
+  } else {
+    console.log('Insufficient stock');
+  }
+};
+// Link code
+const chain = function (fn) {
+  this.fn = fn;
+  this.successor = null;
+};
+chain.prototype.setNext = function (successor) {
+  this.successor = successor;
+};
+chain.prototype.init = function () {
+  const result = this.fn.apply(this, arguments);
+  if (result == 'nextSuccess') {
+    this.successor.init.apply(this.successor, arguments);
+  }
+};
+const order500New = new chain(order500);
+const order200New = new chain(order200);
+const orderCommonNew = new chain(orderCommon);
+order500New.setNext(order200New);
+order200New.setNext(orderCommonNew);
+order500New.init(3, true, 500); // Regular purchase, no coupons

Advantages:

The responsibility chain mode makes an object not need to know which other object handles its request, the object only needs to know that the request will be processed, the receiver and the sender have no clear information about each other, and the object in the chain does not need to know the chain structure, the client is responsible for the creation of the chain, reducing the coupling degree of the system.

  • The request processing object only needs to maintain a reference to its successor, rather than maintaining a reference to all of its candidate handlers, simplifying object interconnections. The responsibility chain gives us more flexibility when assigning responsibilities to objects. The responsibility for handling a request can be added or changed by dynamically adding or modifying the chain at runtime.
  • Adding a new specific request handler to the system does not need to modify the code of the original system, only needs to rebuild the chain on the client side, from this point of view is in line with the "open and closed principle".

Disadvantage:

Since a request has no clear recipient, there is no guarantee that it will be processed, and the request may not be processed until the end of the chain; A request may also not be processed because the chain of responsibility is not configured correctly.

  • For a long chain of responsibility, the processing of requests may involve multiple processing objects, which will affect system performance and make it inconvenient for code debugging.
  • If the chain is not properly built, circular calls may be caused, resulting in a dead loop of the system.

6.2 Command Pattern

Command Pattern: Encapsulating a request as an object allows us to parameterize customers with different requests; Command mode is an object behavior mode, which is alias' Action 'mode or' Transaction 'mode.

The command mode consists of three roles:

  1. Publisher 'invoker' (issues command, calls command object, does not know how to execute and whom to execute);
  2. receiver 'receiver' (provides the corresponding interface to process the request, and does not know who initiates the request);
  3. The command object 'command' (receives the command and invokes the corresponding interface of the receiver to process the publisher's request). The publisher invoker and the receiver are independent and encapsulate the request into a command object command. The specific execution of the request is executed by the command object calling the corresponding interface of the receiver.

Example:

Similar to the previous example in proxy mode, but the essence of command mode is to encapsulate commands, separating the responsibility for issuing commands from the responsibility for executing them. For example, the remote control is a caller, different buttons represent different commands, and the TV is the receiver.

js
class Receiver {
+  // Receiver class
+  execute() {
+    console.log('Receiver execute request');
+  }
+}
+
+class Command {
+  // Command object class
+  constructor(receiver) {
+    this.receiver = receiver;
+  }
+  execute() {
+    // The call receiver executes against the interface
+    console.log('Command object -> Receiver -> Corresponding interface execution');
+    this.receiver.execute();
+  }
+}
+
+class Invoker {
+  // Publisher class
+  constructor(command) {
+    this.command = command;
+  }
+  invoke() {
+    // Issue a request, invoke a command object
+    console.log('The publisher publishes the request');
+    this.command.execute();
+  }
+}
+
+const warehouse = new Receiver(); // Stash
+const order = new Command(warehouse); // Order for goods
+const client = new Invoker(order); // client
+client.invoke();

Advantages:

  • Reduce the coupling degree of the system. Since there is no direct reference between the requester and the receiver, the requester and the receiver realize complete decoupling, the same requester can correspond to different receivers, similarly, the same receiver can also be used by different requesters, and there is good independence between the two.
  • New commands can be easily added to the system. Since the addition of new specific command classes does not affect other classes, it is easy to add new specific command classes without modifying the original system source code, or even the customer class code, to meet the requirements of the "open and close principle".
  • It is relatively easy to design a command queue or macro command (composite command).
  • Provides a design and implementation scheme for requested Undo and Redo operations.

Disadvantage:

  • Using command mode may cause some systems to have too many specific command classes. Because a concrete command class needs to be designed for each call to the receiver of the request, a large number of concrete command classes may need to be provided in some systems, which will affect the use of command patterns.

6.3 Interpreter Pattern

Interpreter Pattern: Define the grammar of a language and build an interpreter to interpret sentences in that language, where "language" means code that uses a specified format and syntax. The interpreter pattern is a kind of behavior pattern.

Example:

Given a language, define a representation of its grammar and an interpreter that uses that representation to interpret sentences in the language.

js
class Context {
+  constructor() {
+    this._list = []; // Stores terminal expressions
+    this._sum = 0; // Store nonterminal expressions
+  }
+
+  get sum() {
+    return this._sum;
+  }
+  set sum(newValue) {
+    this._sum = newValue;
+  }
+  add(expression) {
+    this._list.push(expression);
+  }
+  get list() {
+    return [...this._list];
+  }
+}
+
+class PlusExpression {
+  interpret(context) {
+    if (!(context instanceof Context)) {
+      throw new Error('TypeError');
+    }
+    context.sum = ++context.sum;
+  }
+}
+class MinusExpression {
+  interpret(context) {
+    if (!(context instanceof Context)) {
+      throw new Error('TypeError');
+    }
+    context.sum = --context.sum;
+  }
+}
+
+/** Here is the test code **/
+const context = new Context();
+
+// Add in order: Add | add | subtract expression
+context.add(new PlusExpression());
+context.add(new PlusExpression());
+context.add(new MinusExpression());
+
+// Execute the following: add | add | subtract expression
+context.list.forEach((expression) => expression.interpret(context));
+console.log(context.sum);

Advantages:

  • Easy to change and extend grammar. Because classes are used in the interpreter schema to represent the grammar rules of the language, the grammar can be changed or extended through mechanisms such as inheritance. Each rule can be represented as a class, so it is easy to implement a simple language.
  • The grammar is easier to implement. Each expression node class in the abstract syntax tree is implemented in a similar way, the code for these classes is not particularly complicated, and some tools can automatically generate node class code.
  • It is easier to add new interpretation expressions. If the user needs to add a new interpretation expression, it only needs to add a new terminal expression or non-terminal expression class, and the original expression class code does not need to be modified, which conforms to the "open and closed principle".

Disadvantage:

  • Difficult to maintain for complex grammars. In the interpreter mode, each rule needs to define at least one class, so if a language contains too many grammar rules, the number of classes will increase dramatically, resulting in a system difficult to manage and maintain, at this time you can consider using a parser to replace the interpreter mode.
  • Low execution efficiency. Because of the large number of loops and recursive calls used in the interpreter mode, it is slow to interpret more complex sentences, and the debugging process of the code is cumbersome.

6.4 Iterator Pattern

Iterator Pattern: A relatively simple pattern, most languages now have iterators built in, so that people don't think of it as a design pattern. Iterators don't just iterate over arrays; iterators can be aborted. Provides a way to access aggregate objects without exposing the internal representation of the object, which is alias a Cursor. The iterator pattern is an object behavior pattern.

Example:

Iterators help requesters get the data, avoiding direct manipulation of the data aggregation class and allowing the data aggregation class to focus on storing the data. The specific application has pagination and other functions, and the iterator of the pagination function will be specially responsible for operating the pagination data, separating the operation logic from the data source.

js
var each = function (arr, callback) {
+  for (var i = 0, len = arr.length; i < len; i++) {
+    callback.call(arr[i], i, arr[i]);
+  }
+};
+
+each([1, 2, 3, 4, 5], function (i, el) {
+  console.log('index: ', i);
+  console.log('item: ', el);
+});

Advantages:

  • It supports traversing an aggregate object in different ways, and multiple traversing modes can be defined on the same aggregate object. Iterator mode can be changed by simply replacing the iterator with a different iterator, or we can define our own iterator subclasses to support the new iterator.
  • Iterators simplify aggregate classes. Due to the introduction of iterators, it is no longer necessary to provide data traversal methods in the original aggregate object, which can simplify the design of the aggregate class.
  • In the iterator mode, due to the introduction of the abstraction layer, it is convenient to add new aggregate classes and iterator classes without modifying the original code, which meets the requirements of the "open and closed principle".

Disadvantage:

Because the iterator pattern separates the responsibility of storing data and traversing data, adding new aggregate classes requires adding new iterator classes, and the number of classes increases in pairs, which increases the complexity of the system to some extent.

  • The design of the abstract Iterator is more difficult and needs to fully consider the future extension of the system, for example, the JDK built-in iterator cannot achieve reverse traversal, if you need to achieve reverse traversal, it can only be achieved through its subclass ListIterator, etc. ListIterator iterators cannot be used to manipulate aggregate objects of type Set. When customizing iterators, it is not easy to create an abstract iterator that considers all aspects.

6.5 Mediator Pattern

Mediator Pattern: Objects communicate with each other through third-party intermediaries. Encapsulate a set of object interactions with a mediator, which allows objects to be loosely coupled without explicitly referring to each other, and can change their interactions independently. The mediator model, also known as the mediator model, is an object behavior model.

Example:

The broker pattern turns a network system structure into a star structure centered on broker objects, where one-to-many relationships between broker objects and other objects replace many-to-many relationships between objects. All members interact through intermediaries to facilitate the expansion of new members, such as the following example, after the end of a test, the result is announced: tell the person who solved the challenge successfully, otherwise the challenge fails. In this code, there is no direct relationship between A, B, and C, but a link is established through another playerMiddle object, which is considered the mediator pattern.

js
const player = function (name) {
+  this.name = name;
+  playerMiddle.add(name);
+};
+player.prototype.win = function () {
+  playerMiddle.win(this.name);
+};
+player.prototype.lose = function () {
+  playerMiddle.lose(this.name);
+};
+const playerMiddle = (function () {
+  // We're going to use this demo, this function as a mediator
+  const players = [];
+  const winArr = [];
+  const loseArr = [];
+  return {
+    add: function (name) {
+      players.push(name);
+    },
+    win: function (name) {
+      winArr.push(name);
+      if (winArr.length + loseArr.length === players.length) {
+        this.show();
+      }
+    },
+    lose: function (name) {
+      loseArr.push(name);
+      if (winArr.length + loseArr.length === players.length) {
+        this.show();
+      }
+    },
+    show: function () {
+      for (let winner of winArr) {
+        console.log(winner + 'Challenge success;');
+      }
+      for (let loser of loseArr) {
+        console.log(loser + 'Challenge failure;');
+      }
+    },
+  };
+})();
+const a = new player('A-player');
+const b = new player('B-player');
+const c = new player('C-player');
+a.win();
+b.lose();
+c.win();
+// A Contestant successfully challenged;
+// B Contestant successfully challenged;
+// C Player fails to challenge;

Advantages:

The -mediator pattern simplifies interactions between objects. It replaces many-to-many interactions between colleagues with one-to-many interactions between intermediaries and colleagues. One-to-many relationships are easier to understand, maintain, and extend, transforming the previously difficult network structure into a relatively simple star structure.

  • Mediator mode decouples colleague objects. Intermediaries are conducive to the loose coupling between colleagues, we can independently change and reuse each colleague and intermediary, adding new intermediaries and new colleague classes are more convenient, better in line with the "open and close principle".
  • Can reduce subclass generation, intermediaries will be distributed across multiple objects in a group of behaviors, change these behaviors only need to generate new intermediary subclasses, this allows individual colleague classes can be reused without the need to extend the colleague classes.

Disadvantage:

The inclusion of a large number of details about interactions between colleagues in a specific broker class can make the specific broker class very complex and make the system difficult to maintain.

6.6 Memento Pattern

Memento Pattern: Capture the internal state of an object, without breaking the encapsulation, and save that state outside the object for later use or for the object to revert to a previous state. It is an object behavior pattern that is alias Token.

Example:

Memo mode provides a state recovery implementation mechanism, so that users can easily return to a specific historical step, when the new state is invalid or there is a problem, you can use the temporary storage of the memo to restore the state, many software provides undo operations, which uses the memo mode.

When we develop a paging component, click on the next page to get new data, but when click on the previous page, and get data again, resulting in unnecessary traffic waste, then the data can be cached.

js
// Memo mode pseudo-code
+var Page = function () {
+  // cache objects are used to cache data
+  var cache = {};
+  return function (page, fn) {
+    if (cache[page]) {
+      showPage(page, cache[page]);
+    } else {
+      $.post('/url', function (data) {
+        showPage(page, data);
+        cache[page] = data;
+      });
+    }
+    fn && fn();
+  };
+};

Advantages:

  • It provides a state recovery implementation mechanism, so that users can easily go back to a specific historical step, when the new state is invalid or there is a problem, you can use a temporary stored memo to restore the state.
  • Memos encapsulate information. A memos object is a representation of the state of the originator object and cannot be changed by other code. Memos save the state of the originator, using lists, stacks and other collections to store memos can achieve multiple undo operations.

Disadvantage:

  • Excessive resource consumption. If too many member variables of the originator class need to be saved, a large amount of storage space is inevitably required. Each time the state of an object is saved, certain system resources are consumed.

6.7 Observer Pattern

Observer Pattern: Define a one-to-many dependency relationship between objects so that each time an object's state changes, its dependent objects are notified and automatically updated. Aliases for the observer pattern include the 'Publish/Subscribe' pattern, the model-view (' Model/View ') pattern, the Source/Listener (' source/listener ') pattern, or the 'Dependents' pattern. The observer pattern is an object behavior pattern.

Example:

The observer pattern is one of the most frequently used design patterns, and it is used to establish a dependency relationship between objects. When one object changes, the other objects are automatically notified, and the other objects react accordingly.

The implementation of the observer pattern in JavaScript uses the event model, the DOM event.

js
// publisher
+var pub = function () {
+  console.log('Welcome to subscribe!');
+};
+// Subscribers
+var sub = document.body;
+
+// Subscribers implement subscriptions
+sub.addEventListener('click', pub, false);

Advantages:

The observer pattern can realize the separation of the presentation layer and the data logic layer, define a stable message update delivery mechanism, and abstract the update interface, so that there can be a variety of different presentation layers to act as a concrete observer role.

  • Observer mode establishes an abstract coupling between the object of observation and the observer. The object of observation needs only to maintain a set of abstract observers, without knowing its concrete observers. Because the object of observation and the observer are not tightly coupled, they can belong to different levels of abstraction. Observer mode supports broadcast communication, and the observer will send notifications to all registered observer objects, simplifying the difficulty of one-to-many system design.
  • Observer mode meets the requirements of the "open and close principle", adding new specific observers does not require modifying the original system code, and it is also convenient to add new observation targets when there is no correlation between specific observers and observation targets.

Disadvantage:

If an observation target has many direct and indirect observers, it takes a lot of time to notify all of them.

  • If there is a cyclic dependency between the observer and the observing target, the observing target will trigger a cyclic call between them, possibly causing the system to crash. The observer mode has no mechanism for the observer to know how the object being observed has changed, but only to know that the object being observed has changed.

6.8 State Pattern

State Pattern: By allowing an object to change its behavior when its internal state changes, the object appears to modify its class. Its alias is the state object (' Objects for States'), in fact, is to use an object or array to record a set of states, each state corresponds to an implementation, the implementation according to the state to run the implementation. The state pattern is an object behavior pattern.

Example:

State mode is used to solve the problem of state transition of complex objects and encapsulation of behavior in different states. When an object in the system has multiple states, these states can be transformed between, so objects in different states have different behaviors can be used when the state mode. The state mode separates the state of an object from the object and encapsulates it into a special state class, making the state of the object flexible.

For example, Super Mary may have several states at the same time, such as jumping, moving, shooting, squatting, etc. if these actions are processed and judged one by one, multiple if-else or switch are required. Not only is it ugly, but when there are combined actions, the implementation will become more complicated. This can be done using the state mode.

The idea of state mode is: first create a state object or array, store state variables inside, and then internally encapsulate the corresponding state of each action, and then the state object returns an interface object, which can modify or call the internal state.

js
class SuperMarry {
+  constructor() {
+    this._currentState = [];
+    this.states = {
+      jump() {
+        console.log('Jumping!');
+      },
+      move() {
+        console.log('Move!');
+      },
+      shoot() {
+        console.log('Shoot!');
+      },
+      squat() {
+        console.log('Keep down!');
+      },
+    };
+  }
+
+  change(arr) {
+    // Change current action
+    this._currentState = arr;
+    return this;
+  }
+
+  go() {
+    console.log('Trigger action');
+    this._currentState.forEach((T) => this.states[T] && this.states[T]());
+    return this;
+  }
+}
+
+new SuperMarry()
+  .change(['jump', 'shoot'])
+  .go() // Trigger action jump! Shoot!
+  .go() // Trigger action jump! Shoot!
+  .change(['squat'])
+  .go(); // Trigger action Crouch!

Advantages:

  • Encapsulates the state transition rules. In the state mode, the state transition code can be encapsulated in the environment class or specific state class, and the state transition code can be centrally managed, rather than dispersed in one business method.
  • Put all the behavior related to a state into a class, just inject a different state object to make the environment object have different behavior.
  • Allowing state transition logic to be integrated with state objects, rather than providing a huge block of conditional statements, state patterns allow us to avoid using huge conditional statements to interweave business methods and state transition code.
  • Multiple environment objects can share a state object, thereby reducing the number of objects in the system.

Disadvantage:

  • The use of state mode will inevitably increase the number of classes and objects in the system, resulting in increased system operating overhead.
  • The structure and implementation of the state mode are relatively complex, if used improperly will lead to the program structure and code confusion, increase the difficulty of system design.
  • The state mode does not support the "open and closed principle" very well, adding a new state class needs to modify the source code responsible for the state transition, otherwise it cannot be converted to the new state; And modifying the behavior of a state class also requires modifying the source code of the corresponding class.

6.9 Strategy Pattern

Strategy Pattern: Define a list of algorithms, wrap them up, and be interchangeable. It is to extract and encapsulate seemingly unrelated code and reuse it to make it easier to understand and expand. It is commonly used in process judgment statements such as if judgment, switch enumeration, and data dictionary. Also known as the Policy model (' policy '). Policy pattern is an object behavior pattern.

Example:

When using the policy pattern, we can define several policy classes, each of which encapsulates a specific algorithm. Here, each class that encapsulates an algorithm can be called a policy, and depending on which policy class is passed in, the environment class executes the algorithm in a different policy class.

In the game, we have A level evaluation of the user after each game, such as level S 4 times experience, level A 3 times experience, level B 2 times experience, and other 1 times experience, expressed by the function as follows:

js
// Instead, the policy pattern is written as two functions
+const strategy = {
+  S: function (experience) {
+    return 4 * experience;
+  },
+  A: function (experience) {
+    return 3 * experience;
+  },
+  B: function (experience) {
+    return 2 * experience;
+  },
+};
+// getExperience can be reused
+function getExperience(strategy, level, experience) {
+  return level in strategy ? strategy[level](experience) : experience;
+}
+var s = getExperience(strategy, 'S', 100);
+var a = getExperience(strategy, 'A', 100);
+console.log(s, a); // 400 300
js
// Instruction processing set
+var compileUtil = {
+    // v-text Works for updating views
+    text: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'text');
+    },
+    // v-html update view principle
+    html: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'html');
+    },
+    // v-class binding principle
+    class: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'class');
+    },
+    bind: function(node, vm, exp, dir) {
+        // The same instruction triggers the view update
+        var updaterFn = updater[dir + 'Updater'];
+        updaterFn && updaterFn(node, this._getVMVal(vm, exp));
+        new Watcher(vm, exp, function(value, oldValue) {
+            updaterFn && updaterFn(node, value, oldValue);
+        });
+    }
+    ......
+}

Advantages:

  • Policy mode provides perfect support for the "open and close principle", users can choose algorithms or behaviors without modifying the original system, and can flexibly add new algorithms or behaviors.
  • The policy pattern provides a way to manage related algorithm families. The hierarchy of a policy class defines an algorithm or family of behaviors, and proper use of inheritance can move common code into an abstract policy class, thereby avoiding duplicate code. The policy pattern provides a way to replace inheritance relationships. Without the policy pattern, an environment class that uses algorithms might have several subclasses, each of which provides a different algorithm. However, in this way, the use of the algorithm is mixed with the algorithm itself, which does not conform to the "single responsibility principle", and the logic of deciding which algorithm to use is mixed with the algorithm itself, so that it is impossible to evolve independently. And using inheritance can not realize the dynamic switching of algorithms or behaviors during program running.
  • Use policy mode to avoid multiple conditional selection statements. Multiple conditional selection statement is not easy to maintain, it takes the logic of which algorithm or behavior to take and the implementation logic of the algorithm or behavior itself mixed together, Hard Coding them all in a huge multiple conditional selection statement, than the direct inheritance of the environment class method is more primitive and backward.
  • The policy pattern provides an algorithm reuse mechanism. Since algorithms are extracted separately and encapsulated in policy classes, different environment classes can reuse these policy classes easily.

Disadvantage:

  • The client must know all the policy classes and decide which one to use. This means that the client must understand the difference between these algorithms in order to choose the right one at the right time. In other words, the policy pattern only applies if the client knows all the algorithms or behaviors.
  • The policy mode will cause the system to generate many specific policy classes, and any small change will cause the system to add a new specific policy class.
  • Multiple policy classes cannot be used on the client at the same time. That is, when the policy mode is used, the client can use only one policy class at a time. One policy class cannot be used to complete some functions and then another policy class is used to complete the remaining functions.

6.10 Template method pattern

Template method pattern : Define the framework of an algorithm in an operation, while deferring some steps to subclasses. The template method pattern allows subclasses to redefine certain steps of an algorithm without changing its structure.

Example:

Template method mode usage scenario

The template approach pattern is often used by the architect to build the framework of the project. The architect defines the skeleton of the framework and the programmer inherits the structure of the framework and is responsible for filling in the blanks Hook method: Hook functions in various frameworks often specify the name of each hook function and the execution time at initialization, and users only need to inject custom logic code into the hook function

  • Callback function: The callback function is executed at a specific time, but the specific operation is implemented by the specific function. Encapsulate the changes into a function and the rest becomes a template

The specific application of template method pattern is divided into three categories:

  • Abstract method: An abstract method is declared by an abstract class and implemented by its concrete subclasses.

  • Concrete method: A concrete method is declared and implemented by an abstract or concrete class, and its subclasses can be overridden or directly inherited.

  • Hook method: A hook method is declared and implemented by an abstract or concrete class, and its subclasses may extend it. Usually the implementation given in the parent class is an empty implementation that is used as the default implementation for the method, although the hook method can also provide a non-empty default implementation. The hook method implemented in the subclass constrains the execution of the parent class method, and realizes the reverse control of the subclass to the parent class behavior.

Make a cup of coffee

First let's make a cup of coffee, generally speaking, the steps of making coffee are usually as follows:

  1. Boil the water first.

  2. Brew coffee with boiling water;

  3. Pour the coffee into the cup;

  4. Add sugar and milk.

Let's use es5 to get a cup of coffee:

js
var Coffee = function () {};
+Coffee.prototype.boilWater = function () {
+  console.log('The water is boiling');
+};
+Coffee.prototype.brewCoffeeGriends = function () {
+  console.log('Brew coffee with boiling water');
+};
+Coffee.prototype.pourInCup = function () {
+  console.log('Pour the coffee into the cup');
+};
+Coffee.prototype.addSugarAndMilk = function () {
+  console.log('Add sugar and milk');
+};
+// Encapsulation hands over the implementation details to the internals of the class
+Coffee.prototype.init = function () {
+  this.boilWater();
+  this.brewCoffeeGriends();
+  this.pourInCup();
+  this.addSugarAndMilk();
+};
+var coffee = new Coffee();
+coffee.init();

Make a pot of tea

In fact, the steps for making tea are not very different from those for making coffee, which is roughly like this:

  1. Boil the water;

  2. Soak tea leaves in boiling water;

  3. Pour the tea into the cup;

  4. Add lemon.

Here, let's make tea with es6:

js
class Tea {
+  constructor() {}
+  boilWater() {
+    console.log('Bring water to a boil');
+  }
+  steepTeaBag() {
+    console.log('Soaked tea leaves');
+  }
+  pourInCup() {
+    console.log('Pour into a cup');
+  }
+  addLemon() {
+    console.log('Add lemon');
+  }
+  init() {
+    this.boilWater();
+    this.steepTeaBag();
+    this.pourInCup();
+    this.addLemon();
+  }
+}
+var tea = new Tea();
+tea.init();

Now it's time to think, we just made a cup of coffee and a pot of tea, do you think these two processes are much the same. We can easily find out what they have in common, the difference is the raw material, tea and coffee, we can abstract them as "drinks" wow; The way of soaking is different, one is brewing, the other is soaking, we can abstract this behavior as "soaking"; The spices added are also different, adding sugar and milk, adding lemon, they can also be abstracted as "seasoning".

Such an analysis, is not very clear acriz, we sort it out is:

  1. Boil the water;

  2. Brew drinks with boiling water;

  3. Pour the drink into the glass;

Step 4 Add seasoning.

Attention, everyone! Attention, everyone! Here comes the hero! We've thrown out the concept before, so we can now create an abstract superclass to represent the process of making a drink. So, abstract superclasses?

An abstract class?

Abstract classes cannot be instantiated; they must be inherited. All subclasses that inherit an abstract class will have interface methods identical to those of the abstract class, and the main role of the abstract class is to define these public interfaces for its subclasses.

Through the above analysis, it is specifically to find out the common steps of making tea and making coffee, encapsulate them into the parent class, that is, the abstract class, and then write different steps in the subclass, that is, tea and coffee. Since an abstract class cannot be instantiated, no fear, a subclass is its instantiation.

Make a drink!

js
var Beverage = function () {};
+Beverage.prototype.boilWater = function () {
+  console.log('Boil the water');
+};
+Beverage.prototype.brew = function () {};
+Beverage.prototype.pourInCup = function () {};
+Beverage.prototype.addCondiments = function () {};
+// Abstract method
+Beverage.prototype.init = function () {
+  this.boilWater();
+  this.brew();
+  this.pourInCup();
+  this.addCondiments();
+};
+var Coffee = function () {
+  // Take the constructor of the parent class and execute it
+  Beverage.apply(this, arguments);
+  // Just like es6's super execution, this will only have the properties of the object after execution
+};
+Coffee.prototype = new Beverage();
+var coffee = new Coffee();
+coffee.init();
+var Tea = function () {};
+Tea.prototype = new Beverage();
+Tea.prototype.brew = function () {
+  console.log('Soak the tea leaves in boiling water');
+};
+Tea.prototype.pourInCup = function () {
+  console.log('Pour the tea into the cup');
+};
+Tea.prototype.addCondiments = function () {
+  console.log('Add lemon');
+};
+var tea = new Tea();
+tea.init();

Both coffee and tea are made here, is it not as cumbersome as before, and the code here is very advanced.

Coffee and Tea are represented by the parent class Beverage, and then the subclass is Coffee and Tea, because Beverage is an abstract existence, and the subclass needs to inherit it. The process of brewing a drink can be understood as a template pattern, the abstract class Beverage, and the abstract method init() is implemented in the subclass. js inheritance is based on prototype chain inheritance, where prototype is the prototype chain of the class. Since there is no corresponding init() on the prototype of the coffee object and tea object, the request will follow the prototype chain to find the init() of the parent class Beverage. When subclasses look for corresponding properties and methods, they will follow the prototype chain to find them, first looking for themselves, and if they do not find them, they will follow the search inside the parent class.

The reason why Beverage.prototype.init is called a template method is that it encapsulates the algorithm framework of the subclass, which serves as a template for the algorithm and instructs the subclass to execute which methods in which order.

Advantages:

  • Formally define an algorithm in the parent class, and let its subclasses implement the details of the processing, and the subclasses implement the detailed processing algorithm without changing the order of execution of the steps in the algorithm.
  • Template method pattern is a code reuse technique, it is particularly important in class library design, it extracts the common behavior of the class library, puts the common behavior in the parent class, and through its subclasses to achieve different behavior, it encourages us to use inheritance properly to achieve code reuse. A reverse control structure can be implemented where subclasses override the hook methods of the parent class to decide whether a particular step needs to be performed.
  • In the template method pattern, the basic method of the parent class can be overridden by subclasses, different subclasses can provide different implementations of the basic method, and it is easy to replace and add new subclasses, which conforms to the principle of single responsibility and the principle of open and close.

Disadvantage:

  • It is necessary to provide a subclass for different implementations of each basic method. If there are too many variable basic methods in the parent class, the number of classes will increase, the system will become larger, and the design will become more abstract. In this case, the bridge pattern can be combined to design.

6.11 Visitor Pattern

Visitor Pattern:Provides a representation of operations that act on elements of an object structure, which allows us to define new operations on those elements without changing their class. Visitor pattern is an object behavior pattern.

Example:

Visitor pattern is a more complex behavioral design pattern, which consists of two main components: visitor and visited elements. These visited elements usually have different types, and different visitors can access them differently. The visitor pattern allows users to extend the functionality of the system without modifying the existing system, adding new operations to these different types of elements.

When using the visitor pattern, the accessed elements usually do not exist separately, they are stored in a collection called an "object structure", and the visitor iterates through the object structure to achieve a one-by-one operation on the elements stored in it.

js
// Visitor pattern: DOM event binding
+var bindEvent = function(dom, type, fn, data) {
+    if (dom.addEventListener) {
+        dom.addEventListener(type, fn, false);
+    } else if (dom.attachEvent) {
+        // dom.attachEvent('on'+type, fn);
+        var data = data || {};
+        dom.attachEvent('on' + type, function(e) {
+            // In IE this points to window, use call to change the point of this
+            fn.call(dom, e, data);
+        });
+    } else {
+        dom['on' + type] = fn;
+    }
+}
+function $(id) {
+    return document.getElementById(id);
+}
+
+bindEvent($(demo), 'click', function() {
+    // this points to the dom object
+    this.style.background = 'red';
+});
+
+bindEvent($('btn'), 'click', function(e, data) {
+    $('text').innerHTML = e.type + data.text + this.tagName;
+}, { text: 'demo' });

The idea of visitor pattern is to add new operation methods to the operand without changing it, so as to achieve access to the operand. We know that the purpose of call and apply is to change the scope of function execution, which is the essence of the visitor pattern. call and apply are two ways to make an object run in another scope.

js
// Array method encapsulation
+var Visitor = (function() {
+    return {
+        splice: function() {
+            var args = Array.prototype.splice.call(arguments, 1);
+            return Array.prototype.splice.apply(arguments[0], args);
+        },
+        push: function() {
+            var len = arguments[0].length || 0;
+            var args = this.splice(arguments, 1);
+            arguments[0].length = len + arguments.length - 1;
+            return Array.prototype.push.apply(arguments[0], args);
+        },
+        pop: function() {
+            return Array.prototype.pop.apply(arguments[0]);
+        }
+    }
+})();
+
+var a = new Object();
+Visitor.push(a,1,2,3,4);
+Visitor.push(a,4,5,6);
+Visitor.pop(a);
+Visitor.splice(a,2);

The visitor pattern solves the coupling between the data and the manipulation of the data, making the manipulation of the data independent of the data, so that it can freely evolve. Therefore, the visitor pattern is more suitable for those environments where the data is stable but the data manipulation method is variable.

Advantages:

  • Easy to add new access operations. Using the visitor pattern, adding a new access operation means adding a new concrete visitor class, which is simple to implement without modifying the source code and conforms to the "open and closed principle".
  • Centralize access to element objects into a single visitor object, rather than spreading it across individual element classes. Class responsibilities are clearer, facilitating reuse of element objects in the object structure, and the same object structure can be accessed by multiple different visitors.
  • Enables users to define operations that act on an existing element class hierarchy without modifying it.

Disadvantage:

  • Adding new element classes is difficult. In the visitor pattern, adding a new element class means adding a new abstract operation to the abstract visitor role and a corresponding concrete operation to each concrete visitor class, which violates the "open closed principle".
  • Break the package. The visitor pattern requires the visitor object to access and invoke the operations of each element object, which means that the element object must sometimes expose some of its own internal operations and internal state, otherwise it cannot be accessed by the visitor.

VII.Sum up

After systematically studying design patterns, you can see in your past development experience that design patterns are everywhere. Before learning design patterns, we often rely on past experience and wisdom to improve the design of a system, and many of these experiences coincide with the idea of a certain design pattern.

There are still some places that are not fully understood, and I would like to point out the mistakes in the article.

VIII.Reference material

`,385)]))}const N=q(I,[["render",S]]);export{U as __pageData,N as default}; diff --git a/assets/src_article_functionalProgramming.md.DSVAXKFw.js b/assets/src_article_functionalProgramming.md.DSVAXKFw.js new file mode 100644 index 0000000000..d854896c3e --- /dev/null +++ b/assets/src_article_functionalProgramming.md.DSVAXKFw.js @@ -0,0 +1,338 @@ +import{_ as i,o as a,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"函数式编程","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/functionalProgramming.md","filePath":"src/article/functionalProgramming.md","lastUpdated":1726550590000}'),k={name:"src/article/functionalProgramming.md"};function l(p,s,t,E,e,r){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h(`

函数式编程

  • 概述:函数式编程 (Functional Programming)FP就是编程规范之一,我们常听说的编程规范还有面向对象编程,面向过程编程。
  • 面向对象的编程思维方式:把现实世界中的事物抽象成程序世界的类和对象,通过封装,继承和多态演示事物事件的联系
  • 函数编程的思维方式:把现实世界的事物和事物之间的联系抽象到程序世界 (对运算过程进行抽象)
    • 程序的本质:根据输入,通过某种运算,获得相应的输出
    • 函数式编程中的函数不是指程序中的 (函数) 方法,而是数学中的函数,即映射关系
    • 相同的输入始终要得到相同的输出 (纯函数)
    • 函数式编程用来描述数据 (函数) 之间的映射关系
js
//非函数式编程,面向过程的编程方式
+let num1 = 1;
+let num2 = 2;
+let sum = num1 + num2;
+
+//函数式编程,对面向过程的抽象
+function sum(n1, n2) {
+  return n1 + n2;
+}
+let result = sum(1, 2);

一。JS函数基本知识

  • 函数可以储存在变量中
  • 函数可以作为参数
  • 函数可以作为返回值

JavaScript中,函数就是一个普通的对象,(可以通过new Function()),我们可以把函数存储到变量/数组中,它还可以作为另一个函数的参数和返回值,甚至我们还可以在程序运行的时候通过new Function('alert(1)')来构建一个新的函数

  • 把函数赋值给变量
js
let fn = function () {
+  console.log('First-class Function MDN');
+};

二。高阶函数

  • 高阶函数 (Higher-order function)
    • 可以把函数作为参数传递给另一个函数
    • 可以把函数作为另一个函数的返回结果
  1. 函数作为参数
js
//forEach
+function forEach(array, fn) {
+  for (let item of array) {
+    fn(item);
+  }
+}
+
+//filter
+function filter(array, fn) {
+  let result = [];
+  for (let item of array) {
+    if (fn(item)) {
+      result.push(item);
+    }
+  }
+  return result;
+}
+
+//测试
+let array = [1, 2, 3, 4, 5, 6, 7];
+forEach(array, function (item) {
+  console.log(item);
+});
+
+let r = filter(array, function (item) {
+  return item % 2 === 0;
+});
+console.log(r);
  1. 函数作为返回值
js
//高阶函数,函数作为返回值
+function makeFn() {
+  let msg = 'Highter-order Function';
+  return function () {
+    console.log(msg);
+  };
+}
+//第一种调用方式
+const fn = makeFn();
+fn();
+//第二种调用方式
+makeFn()();
+//once 只能执行一次的函数
+function once(fn) {
+  let done = false;
+  return function () {
+    if (!done) {
+      done = true;
+      return fn.apply(this, arguments);
+    }
+  };
+}
+let pay = once(function (money) {
+  console.log(\`支付\${money}\`);
+});
+pay(5);
+pay(5);
+pay(5);
+pay(5);
+pay(5);

三。闭包

概述:有权访问另一个函数作用域中的变量的函数

本质:函数执行的时候会入栈,当执行完后会移除栈,但是堆上的作用域成员因为被外部引用而不能释放。因此内部函数依然可以访问外部函数的成员。

:栈会自动分配内存,会自动释放,存放基本数据类型,占据固定大小的空间。

栈的溢出:递归调用方法,随着栈的深度增加,直到内存不够分配,产生溢出。

栈的优势:所有方法中的变量都存在栈中,随着方法执行的结束,这个方法的内存栈也随之销毁,存取速度很快,仅次于 CPU 的寄存器,可以共享。

:动态分配内存,大小不定,也不会自动释放内存,不会随着方法的结束而销毁堆内存,存放引用数据类型,实际保存的不是变量本身,而是指向该对象的指针。

堆溢出:循环创建对象,就是不断的 new 对象

四。纯函数

  • 概念:相同的输入永远会得到相同的输出,而且没有任何可观察的副作用,类似数学中的函数y=f(x)
  • 例子:slice函数就是纯函数,对一个数组,相同的输入永远得到相同的输出,splice 就是非纯函数,相同的输入可能会得到不同的结果,因为会改变原数组
  • 函数式编程不会保留计算中间的结果,所以变量不可变 (无状态)
  • 可以把一个函数的执行结果交给另一个函数去执行
  • 纯函数可以缓存,因为相同的输入必然有相同的输出
js
//memoize 函数
+function memoize(fn) {
+  let cache = {};
+  return function () {
+    let key = JSON.stringfy(arguments);
+    cache[key] = cache[key] || fn.apply(fn, arguments);
+    return cache[key];
+  };
+}
  • 可测试,让测试更方便
  • 多线程环境下操作共享的内存数据可能会出现意外的情况,而纯函数不需要共享的数据空间,只和输入有关,所以并行环境下可以任意运行纯函数
  • 副作用,副作用会让纯函数变的不纯,比如依赖外部的状态,就无法保证输出相同,带来副作用,副作用来源:配置文件,数据库,获取用户的输入等等...所有的外部交互都可能带来副作用,副作用使得方法通用性下降,不适合扩展和重用,同时给程序带来安全隐患,副作用不可能完全禁止,只能尽可能的在控制范围内。
js
//不纯的函数
+let mini = 18;
+function checkAge(age) {
+  return age > min;
+}
+//纯函数 (有硬编码,后续可以通过柯里化来解决)
+function checkAge(age) {
+  let mini = 18;
+  return age > mini;
+}

五。柯里化 (Haskell Brooks Curry)

js
//解决上述硬编码的问题
+function checkAge(min) {
+  return function (age) {
+    return age >= min;
+  };
+}
+let checkAge18 = checkAge(18);
+checkAge18(22);

es6进行简化

js
let checkAge = (min) => (age) => age >= min;
  • 当一个函数有多个参数的时候,可以先传递一部分,先调用它,并返回一个函数 (这部分参数以后保持不变)
  • 然后返回一个新的函数接受剩下的参数,返回结果
  • lodash中的柯里化函数
    • _.curry(func)
    • 功能:创建一个函数,该函数接受一个或多个 func 的参数,如果该函数所有的参数都被传递,则返回函数的结果,否则,返回该函数并等待继续传递参数
    • 参数:需要柯里化的函数
    • 返回值:柯里化后的函数
js
//lodash 中的 curry 的使用
+const _ = require('loadsh');
+function getSum(a, b, c) {
+  return a + b + c;
+}
+const curried = _.curry(getSum);
+console.log(curried(1, 2, 3)); //6
+console.log(curried(1)(2, 3)); //6
+console.log(curried(1)(2)(3)); //6

实现一个 curry 函数

js
function curry(func) {
+  return function curriedFn(...args) {
+    if (args.length < func.length) {
+      return function () {
+        return curriedFn(...args.concat(Array.form(arguments)));
+      };
+    } else {
+      return func(...args);
+    }
+  };
+}
  • 总结:柯里化可以让我们给一个函数传递较少的参数,返回一个记住来某些固定参数的新函数,这是一种对函数参数的缓存,让函数变的更灵活,让函数的粒度更小。可以把多元函数转换成一元的函数,可以组合使用函数产生强大的功能。

六。函数的组合

  • 纯函数和柯里化很容易让我们写出洋葱代码,比如h(f(g(x)))
    • 获取数组的最后一个元素并转化为大写字母,_.toUpper(._first(_.revers(array)))
    • 函数的组合可以让我们把细粒度的函数,重新组合成一个新的函数
  • lodash中的组合函数
    • lodash中的组合函数flow()flowRight(),都可以组合多个函数
    • flow()是从左到右执行
    • flowRight()是从右到左执行
    • 自己实现一个flowRight函数:
js
function composeRight(...args) {
+  return function (value) {
+    args.reverse().reduce(function (acc, fn) {
+      return fn(acc);
+    }, value);
+  };
+}
+//箭头函数
+const compose =
+  (...args) =>
+  (value) =>
+    args.reverse().reduce((acc, fn) => fn(acc), value);
+//如果是表达式赋值的话,不会变量提升
  • 函数的组合要满足结合律,即 f,g,h 三个函数,无论先组合那几个,结果都是等效的,即 flowRight(.toUpper,.first,_.revers)
  • 函数组合如何进行调试?
js
const log = (v) => {
+  console.log(v);
+  return v;
+};
  • lodash库中的 fp 模块
    • lodash的 fp 模块提供了实用的对函数式编程友好的方法
    • 提供了不可变的auto-curried iteratee-first data-last的方法
js
//lodash 方法
+const _ = require('lodash');
+_.map(['a', 'b', 'c'], _.toUpper);
+//=>['A','B','C']
+_.map(['a', 'b', 'c']);
+//=>['a','b','c']
+//loadsh/fp 模块
+const fp = require('lodasg/fp');
+fp.map(fp.toUpper, ['a', 'b', 'c']);
+fp.map(fp.toUpper)(['a', 'b', 'c']);

七.Point Free

我们可以把数据处理的过程定义成与数据无关的合成运算,不需要用到代表数据的那个参数,只要把简单的运算步骤合成到一起,在使用这种模式之前我们需要定义一些辅助的基本运算函数。

  • 不需要指明处理的数据
  • 只需要合成运算过程
  • 需要定义一些辅助的基本运算函数
js
const f = fp.flowRight(fp.join('-'), fp.map(_.toLower), fp.splite(''));

八。functor(函子)

  • 为什么要了解函子
    目前没有解决如何在函数式编程中,把副作用控制在可控的范围内,异常处理,异步操作等等。
  • Functor
    • 容器:包含值和值的变形关系 (这个变形关系就是函数)
    • 函子:是一个特殊的容器,通过一个普通对象来实现,该对象具有 map 方法,map 方法可以运行一个函数对值进行处理 (变形关系)
js
//Functor 函子
+class Container {
+  //函子内部要有一个值
+  constructor(value) {
+    //这个值是传入进来的,且不对外公布
+    this._value = value;
+  }
+  map(fn) {
+    //map 方法,接受一个处理值的函数,去处理这个值。
+    //并且要把处理的值,传给一个新的函子,最后返回这个新的函子
+    return new Container(fn(this._value));
+  }
+}
+
+//新建一个函子
+let r = new Container(5).map((x) => x + 1).map((x) => x * x);

of方法:

js
//of 方法用来返回一个函子对象
+class Container {
+  constructor(value) {
+    this._value = value;
+  }
+  static of(value) {
+    //传入值,返回一个新的函子对象
+    return new Container(value);
+  }
+  map(fn) {
+    return Container.of(fn(this._value));
+  }
+}
+let r = Container.of(5)
+  .map((x) => x + 1)
+  .map((x) => x * x);
+console.log(r); //打印出来的是一个函子,不是值,永远不会把这个值取出来,需要改变这个值的时候,使用 map 方法传入一个函数去处理,进行链式调用。
  • 总结
    • 函数式编程的运算不直接操作值,而是由函子完成
    • 函子就是一个实现了map契约的对象
    • 我们可以把函子想象成一个盒子,这个盒子里封装了一个值
    • 想要处理盒子中的值,我们需要给盒子的map方法传递一个处理值的函数(纯函数),由这个函数对值进行处理
    • 最终map方法返回一个包含新值的盒子(函子)
  • MayBe函子
    • 我们在编程过程中可能会遇到很多的错误,需要对这些错误进行相应的处理
    • MayBe 函子的作用就是可以对外部的空值情况做处理(控制副作用在允许的范围之内)
js
//MayBe 函子
+class MayBe {
+  static of(value) {
+    return new MayBe(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this._value));
+  }
+  isNothing() {
+    return this._value === null || this._value === undefined;
+  }
+}
+let r = MayBe.of(null)
+  .map((x) => x + 1)
+  .map((x) => x * x);
+console.log(r);
  • 问题:如果多次调用 map,中间出现了 null 空值的情况,最后会返回包含 null 的函子。虽然 maybe 函子可以处理空值的情况,但不知道是哪一步出现了空值
  • Either 函子
    • Either 两者中的任意一个,类似于 if...else...的处理
    • 异常会让函数变的不纯,Either 函子可以用来做异常处理
js
//Either 函子
+class Left {
+  static of(value) {
+    return new Left(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return this;
+  }
+}
+
+class Right {
+  static of(value) {
+    return new Right(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return Right.of(fn(this._value));
+  }
+}
+
+function parseJSON(str) {
+  try {
+    return Right.of(JSON.parse(str));
+  } catch (error) {
+    return Left.of({ error: error.message });
+  }
+}
+let l = parseJSON('{name:zs}'); //error
+console.log(l);
+let r = parseJSON('{"name":"zs"}');
+console.log(r);
+r.map((x) => x.toUpper());
  • IO 函子
    • IO 函子中的_value 是一个函数,这里是把函数当作值来处理
    • IO 函子可以把不纯的函数储存到_value 中,延迟执行这个不纯的操作 (惰性执行)
    • 把不纯的操作交给调用者来处理
js
const fp = require('lodash/fp');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+}
+//调用
+//因为是在 node 环境,所以直接传递 process 对象,node 的进程
+let r = IO.of(process).map((p) => p.execPath);
+console.log(r); //IO {_value :[Function]}
+console.log(r._value()); //执行 node 进程的路径
  • folktale
    • folktale 是一个标准的函数式编程库
    • 和 lodash,ramda 不同的是,他没有提供很多功能函数
    • 只提供了函数式处理的操作,例如,curry,compose 等,和一些函子 Task,Either,MayBe 等
js
//folktale  2.3.2
+//Task 处理异步任务
+const fs = require('fs');
+const { task } = require('folktale/concurrency/task');
+const { split, find } = require('loadsh/fp');
+
+function readFile(filename) {
+  return task((resolver) => {
+    fs.readFile(filename, 'utf-8', (error, data) => {
+      if (error) {
+        resolver.reject(err);
+      } else {
+        resolver.resolve(data);
+      }
+    });
+  });
+}
+//会返回一个 Task 函子
+readFile('package.json')
+  .run()
+  .listen({
+    //监听事件的状态
+    onRejected: (err) => {
+      console.log(err);
+    },
+    onResolved: (value) => {
+      console.log(value);
+    },
+  });
+//可以在 run 之前调用 map,去处理返回的结果
+readFile('package.json')
+  .map(split('\\n'))
+  .map(find((x) => x.includes('version')))
+  .run()
+  .listen({
+    //监听事件的状态
+    onRejected: (err) => {
+      console.log(err);
+    },
+    onResolved: (value) => {
+      console.log(value);
+    },
+  });
  • Pointed 函子
    • Pointed 函子是实现的静态方法 of 的函子
    • of 是为了避免使用 new 来创建对象,更深层的含义是 of 方法用来把值放到上下文 Context 中 (把值放到容器中,使用 map 来处理值)
  • Monad 函子
    • Monad 函子是为来解决 IO 函子嵌套的问题
js
const fp = require('lodash/fp');
+const fs = require('fs');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+}
+let readFile = function (filename) {
+  return new IO(function () {
+    return fs.readFileSync(filename, 'utf-8');
+  });
+};
+let print = function (x) {
+  return new IO(function (x) {
+    console.log(x);
+    return x;
+  });
+};
+let cat = fp.flowRight(print, readFile);
+let r = cat('package.json')._value()._value();
+console.log(r);
  • Monad 函子是一个可以变扁的 Pointed 函子,变扁就是解决函子嵌套的问题 IO(IO(x))
  • 一个函子如果具有 join 和 of 两个方法并遵守一些定律就是一个 Monad
js
//注意看 join 方法
+const fp = require('lodash/fp');
+const fs = require('fs');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+  join() {
+    return this._value();
+  }
+  flatMap(fn) {
+    //经常会用到 map 和 join 方法,所以就用 flatMap 将其变扁
+    return this.map(fn).join();
+  }
+}
+let print = function (x) {
+  return new IO(function () {
+    console.log(x);
+    return x;
+  });
+};
+let r = readFile('package.json') //这里可以用 map 去处理内容
+  .flatMap(print)
+  .join();

参考资料

`,66)]))}const y=i(k,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/src_article_functionalProgramming.md.DSVAXKFw.lean.js b/assets/src_article_functionalProgramming.md.DSVAXKFw.lean.js new file mode 100644 index 0000000000..d854896c3e --- /dev/null +++ b/assets/src_article_functionalProgramming.md.DSVAXKFw.lean.js @@ -0,0 +1,338 @@ +import{_ as i,o as a,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"函数式编程","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/functionalProgramming.md","filePath":"src/article/functionalProgramming.md","lastUpdated":1726550590000}'),k={name:"src/article/functionalProgramming.md"};function l(p,s,t,E,e,r){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h(`

函数式编程

  • 概述:函数式编程 (Functional Programming)FP就是编程规范之一,我们常听说的编程规范还有面向对象编程,面向过程编程。
  • 面向对象的编程思维方式:把现实世界中的事物抽象成程序世界的类和对象,通过封装,继承和多态演示事物事件的联系
  • 函数编程的思维方式:把现实世界的事物和事物之间的联系抽象到程序世界 (对运算过程进行抽象)
    • 程序的本质:根据输入,通过某种运算,获得相应的输出
    • 函数式编程中的函数不是指程序中的 (函数) 方法,而是数学中的函数,即映射关系
    • 相同的输入始终要得到相同的输出 (纯函数)
    • 函数式编程用来描述数据 (函数) 之间的映射关系
js
//非函数式编程,面向过程的编程方式
+let num1 = 1;
+let num2 = 2;
+let sum = num1 + num2;
+
+//函数式编程,对面向过程的抽象
+function sum(n1, n2) {
+  return n1 + n2;
+}
+let result = sum(1, 2);

一。JS函数基本知识

  • 函数可以储存在变量中
  • 函数可以作为参数
  • 函数可以作为返回值

JavaScript中,函数就是一个普通的对象,(可以通过new Function()),我们可以把函数存储到变量/数组中,它还可以作为另一个函数的参数和返回值,甚至我们还可以在程序运行的时候通过new Function('alert(1)')来构建一个新的函数

  • 把函数赋值给变量
js
let fn = function () {
+  console.log('First-class Function MDN');
+};

二。高阶函数

  • 高阶函数 (Higher-order function)
    • 可以把函数作为参数传递给另一个函数
    • 可以把函数作为另一个函数的返回结果
  1. 函数作为参数
js
//forEach
+function forEach(array, fn) {
+  for (let item of array) {
+    fn(item);
+  }
+}
+
+//filter
+function filter(array, fn) {
+  let result = [];
+  for (let item of array) {
+    if (fn(item)) {
+      result.push(item);
+    }
+  }
+  return result;
+}
+
+//测试
+let array = [1, 2, 3, 4, 5, 6, 7];
+forEach(array, function (item) {
+  console.log(item);
+});
+
+let r = filter(array, function (item) {
+  return item % 2 === 0;
+});
+console.log(r);
  1. 函数作为返回值
js
//高阶函数,函数作为返回值
+function makeFn() {
+  let msg = 'Highter-order Function';
+  return function () {
+    console.log(msg);
+  };
+}
+//第一种调用方式
+const fn = makeFn();
+fn();
+//第二种调用方式
+makeFn()();
+//once 只能执行一次的函数
+function once(fn) {
+  let done = false;
+  return function () {
+    if (!done) {
+      done = true;
+      return fn.apply(this, arguments);
+    }
+  };
+}
+let pay = once(function (money) {
+  console.log(\`支付\${money}\`);
+});
+pay(5);
+pay(5);
+pay(5);
+pay(5);
+pay(5);

三。闭包

概述:有权访问另一个函数作用域中的变量的函数

本质:函数执行的时候会入栈,当执行完后会移除栈,但是堆上的作用域成员因为被外部引用而不能释放。因此内部函数依然可以访问外部函数的成员。

:栈会自动分配内存,会自动释放,存放基本数据类型,占据固定大小的空间。

栈的溢出:递归调用方法,随着栈的深度增加,直到内存不够分配,产生溢出。

栈的优势:所有方法中的变量都存在栈中,随着方法执行的结束,这个方法的内存栈也随之销毁,存取速度很快,仅次于 CPU 的寄存器,可以共享。

:动态分配内存,大小不定,也不会自动释放内存,不会随着方法的结束而销毁堆内存,存放引用数据类型,实际保存的不是变量本身,而是指向该对象的指针。

堆溢出:循环创建对象,就是不断的 new 对象

四。纯函数

  • 概念:相同的输入永远会得到相同的输出,而且没有任何可观察的副作用,类似数学中的函数y=f(x)
  • 例子:slice函数就是纯函数,对一个数组,相同的输入永远得到相同的输出,splice 就是非纯函数,相同的输入可能会得到不同的结果,因为会改变原数组
  • 函数式编程不会保留计算中间的结果,所以变量不可变 (无状态)
  • 可以把一个函数的执行结果交给另一个函数去执行
  • 纯函数可以缓存,因为相同的输入必然有相同的输出
js
//memoize 函数
+function memoize(fn) {
+  let cache = {};
+  return function () {
+    let key = JSON.stringfy(arguments);
+    cache[key] = cache[key] || fn.apply(fn, arguments);
+    return cache[key];
+  };
+}
  • 可测试,让测试更方便
  • 多线程环境下操作共享的内存数据可能会出现意外的情况,而纯函数不需要共享的数据空间,只和输入有关,所以并行环境下可以任意运行纯函数
  • 副作用,副作用会让纯函数变的不纯,比如依赖外部的状态,就无法保证输出相同,带来副作用,副作用来源:配置文件,数据库,获取用户的输入等等...所有的外部交互都可能带来副作用,副作用使得方法通用性下降,不适合扩展和重用,同时给程序带来安全隐患,副作用不可能完全禁止,只能尽可能的在控制范围内。
js
//不纯的函数
+let mini = 18;
+function checkAge(age) {
+  return age > min;
+}
+//纯函数 (有硬编码,后续可以通过柯里化来解决)
+function checkAge(age) {
+  let mini = 18;
+  return age > mini;
+}

五。柯里化 (Haskell Brooks Curry)

js
//解决上述硬编码的问题
+function checkAge(min) {
+  return function (age) {
+    return age >= min;
+  };
+}
+let checkAge18 = checkAge(18);
+checkAge18(22);

es6进行简化

js
let checkAge = (min) => (age) => age >= min;
  • 当一个函数有多个参数的时候,可以先传递一部分,先调用它,并返回一个函数 (这部分参数以后保持不变)
  • 然后返回一个新的函数接受剩下的参数,返回结果
  • lodash中的柯里化函数
    • _.curry(func)
    • 功能:创建一个函数,该函数接受一个或多个 func 的参数,如果该函数所有的参数都被传递,则返回函数的结果,否则,返回该函数并等待继续传递参数
    • 参数:需要柯里化的函数
    • 返回值:柯里化后的函数
js
//lodash 中的 curry 的使用
+const _ = require('loadsh');
+function getSum(a, b, c) {
+  return a + b + c;
+}
+const curried = _.curry(getSum);
+console.log(curried(1, 2, 3)); //6
+console.log(curried(1)(2, 3)); //6
+console.log(curried(1)(2)(3)); //6

实现一个 curry 函数

js
function curry(func) {
+  return function curriedFn(...args) {
+    if (args.length < func.length) {
+      return function () {
+        return curriedFn(...args.concat(Array.form(arguments)));
+      };
+    } else {
+      return func(...args);
+    }
+  };
+}
  • 总结:柯里化可以让我们给一个函数传递较少的参数,返回一个记住来某些固定参数的新函数,这是一种对函数参数的缓存,让函数变的更灵活,让函数的粒度更小。可以把多元函数转换成一元的函数,可以组合使用函数产生强大的功能。

六。函数的组合

  • 纯函数和柯里化很容易让我们写出洋葱代码,比如h(f(g(x)))
    • 获取数组的最后一个元素并转化为大写字母,_.toUpper(._first(_.revers(array)))
    • 函数的组合可以让我们把细粒度的函数,重新组合成一个新的函数
  • lodash中的组合函数
    • lodash中的组合函数flow()flowRight(),都可以组合多个函数
    • flow()是从左到右执行
    • flowRight()是从右到左执行
    • 自己实现一个flowRight函数:
js
function composeRight(...args) {
+  return function (value) {
+    args.reverse().reduce(function (acc, fn) {
+      return fn(acc);
+    }, value);
+  };
+}
+//箭头函数
+const compose =
+  (...args) =>
+  (value) =>
+    args.reverse().reduce((acc, fn) => fn(acc), value);
+//如果是表达式赋值的话,不会变量提升
  • 函数的组合要满足结合律,即 f,g,h 三个函数,无论先组合那几个,结果都是等效的,即 flowRight(.toUpper,.first,_.revers)
  • 函数组合如何进行调试?
js
const log = (v) => {
+  console.log(v);
+  return v;
+};
  • lodash库中的 fp 模块
    • lodash的 fp 模块提供了实用的对函数式编程友好的方法
    • 提供了不可变的auto-curried iteratee-first data-last的方法
js
//lodash 方法
+const _ = require('lodash');
+_.map(['a', 'b', 'c'], _.toUpper);
+//=>['A','B','C']
+_.map(['a', 'b', 'c']);
+//=>['a','b','c']
+//loadsh/fp 模块
+const fp = require('lodasg/fp');
+fp.map(fp.toUpper, ['a', 'b', 'c']);
+fp.map(fp.toUpper)(['a', 'b', 'c']);

七.Point Free

我们可以把数据处理的过程定义成与数据无关的合成运算,不需要用到代表数据的那个参数,只要把简单的运算步骤合成到一起,在使用这种模式之前我们需要定义一些辅助的基本运算函数。

  • 不需要指明处理的数据
  • 只需要合成运算过程
  • 需要定义一些辅助的基本运算函数
js
const f = fp.flowRight(fp.join('-'), fp.map(_.toLower), fp.splite(''));

八。functor(函子)

  • 为什么要了解函子
    目前没有解决如何在函数式编程中,把副作用控制在可控的范围内,异常处理,异步操作等等。
  • Functor
    • 容器:包含值和值的变形关系 (这个变形关系就是函数)
    • 函子:是一个特殊的容器,通过一个普通对象来实现,该对象具有 map 方法,map 方法可以运行一个函数对值进行处理 (变形关系)
js
//Functor 函子
+class Container {
+  //函子内部要有一个值
+  constructor(value) {
+    //这个值是传入进来的,且不对外公布
+    this._value = value;
+  }
+  map(fn) {
+    //map 方法,接受一个处理值的函数,去处理这个值。
+    //并且要把处理的值,传给一个新的函子,最后返回这个新的函子
+    return new Container(fn(this._value));
+  }
+}
+
+//新建一个函子
+let r = new Container(5).map((x) => x + 1).map((x) => x * x);

of方法:

js
//of 方法用来返回一个函子对象
+class Container {
+  constructor(value) {
+    this._value = value;
+  }
+  static of(value) {
+    //传入值,返回一个新的函子对象
+    return new Container(value);
+  }
+  map(fn) {
+    return Container.of(fn(this._value));
+  }
+}
+let r = Container.of(5)
+  .map((x) => x + 1)
+  .map((x) => x * x);
+console.log(r); //打印出来的是一个函子,不是值,永远不会把这个值取出来,需要改变这个值的时候,使用 map 方法传入一个函数去处理,进行链式调用。
  • 总结
    • 函数式编程的运算不直接操作值,而是由函子完成
    • 函子就是一个实现了map契约的对象
    • 我们可以把函子想象成一个盒子,这个盒子里封装了一个值
    • 想要处理盒子中的值,我们需要给盒子的map方法传递一个处理值的函数(纯函数),由这个函数对值进行处理
    • 最终map方法返回一个包含新值的盒子(函子)
  • MayBe函子
    • 我们在编程过程中可能会遇到很多的错误,需要对这些错误进行相应的处理
    • MayBe 函子的作用就是可以对外部的空值情况做处理(控制副作用在允许的范围之内)
js
//MayBe 函子
+class MayBe {
+  static of(value) {
+    return new MayBe(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this._value));
+  }
+  isNothing() {
+    return this._value === null || this._value === undefined;
+  }
+}
+let r = MayBe.of(null)
+  .map((x) => x + 1)
+  .map((x) => x * x);
+console.log(r);
  • 问题:如果多次调用 map,中间出现了 null 空值的情况,最后会返回包含 null 的函子。虽然 maybe 函子可以处理空值的情况,但不知道是哪一步出现了空值
  • Either 函子
    • Either 两者中的任意一个,类似于 if...else...的处理
    • 异常会让函数变的不纯,Either 函子可以用来做异常处理
js
//Either 函子
+class Left {
+  static of(value) {
+    return new Left(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return this;
+  }
+}
+
+class Right {
+  static of(value) {
+    return new Right(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return Right.of(fn(this._value));
+  }
+}
+
+function parseJSON(str) {
+  try {
+    return Right.of(JSON.parse(str));
+  } catch (error) {
+    return Left.of({ error: error.message });
+  }
+}
+let l = parseJSON('{name:zs}'); //error
+console.log(l);
+let r = parseJSON('{"name":"zs"}');
+console.log(r);
+r.map((x) => x.toUpper());
  • IO 函子
    • IO 函子中的_value 是一个函数,这里是把函数当作值来处理
    • IO 函子可以把不纯的函数储存到_value 中,延迟执行这个不纯的操作 (惰性执行)
    • 把不纯的操作交给调用者来处理
js
const fp = require('lodash/fp');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+}
+//调用
+//因为是在 node 环境,所以直接传递 process 对象,node 的进程
+let r = IO.of(process).map((p) => p.execPath);
+console.log(r); //IO {_value :[Function]}
+console.log(r._value()); //执行 node 进程的路径
  • folktale
    • folktale 是一个标准的函数式编程库
    • 和 lodash,ramda 不同的是,他没有提供很多功能函数
    • 只提供了函数式处理的操作,例如,curry,compose 等,和一些函子 Task,Either,MayBe 等
js
//folktale  2.3.2
+//Task 处理异步任务
+const fs = require('fs');
+const { task } = require('folktale/concurrency/task');
+const { split, find } = require('loadsh/fp');
+
+function readFile(filename) {
+  return task((resolver) => {
+    fs.readFile(filename, 'utf-8', (error, data) => {
+      if (error) {
+        resolver.reject(err);
+      } else {
+        resolver.resolve(data);
+      }
+    });
+  });
+}
+//会返回一个 Task 函子
+readFile('package.json')
+  .run()
+  .listen({
+    //监听事件的状态
+    onRejected: (err) => {
+      console.log(err);
+    },
+    onResolved: (value) => {
+      console.log(value);
+    },
+  });
+//可以在 run 之前调用 map,去处理返回的结果
+readFile('package.json')
+  .map(split('\\n'))
+  .map(find((x) => x.includes('version')))
+  .run()
+  .listen({
+    //监听事件的状态
+    onRejected: (err) => {
+      console.log(err);
+    },
+    onResolved: (value) => {
+      console.log(value);
+    },
+  });
  • Pointed 函子
    • Pointed 函子是实现的静态方法 of 的函子
    • of 是为了避免使用 new 来创建对象,更深层的含义是 of 方法用来把值放到上下文 Context 中 (把值放到容器中,使用 map 来处理值)
  • Monad 函子
    • Monad 函子是为来解决 IO 函子嵌套的问题
js
const fp = require('lodash/fp');
+const fs = require('fs');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+}
+let readFile = function (filename) {
+  return new IO(function () {
+    return fs.readFileSync(filename, 'utf-8');
+  });
+};
+let print = function (x) {
+  return new IO(function (x) {
+    console.log(x);
+    return x;
+  });
+};
+let cat = fp.flowRight(print, readFile);
+let r = cat('package.json')._value()._value();
+console.log(r);
  • Monad 函子是一个可以变扁的 Pointed 函子,变扁就是解决函子嵌套的问题 IO(IO(x))
  • 一个函子如果具有 join 和 of 两个方法并遵守一些定律就是一个 Monad
js
//注意看 join 方法
+const fp = require('lodash/fp');
+const fs = require('fs');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+  join() {
+    return this._value();
+  }
+  flatMap(fn) {
+    //经常会用到 map 和 join 方法,所以就用 flatMap 将其变扁
+    return this.map(fn).join();
+  }
+}
+let print = function (x) {
+  return new IO(function () {
+    console.log(x);
+    return x;
+  });
+};
+let r = readFile('package.json') //这里可以用 map 去处理内容
+  .flatMap(print)
+  .join();

参考资料

`,66)]))}const y=i(k,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/src_article_imagemin.md.DTz2O7QV.js b/assets/src_article_imagemin.md.DTz2O7QV.js new file mode 100644 index 0000000000..9d0840b961 --- /dev/null +++ b/assets/src_article_imagemin.md.DTz2O7QV.js @@ -0,0 +1 @@ +import{_ as t,o as i,c as r,j as a,a as m}from"./chunks/framework.C-ai2y4t.js";const f=JSON.parse('{"title":"imagemin 图片压缩源码分析","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/imagemin.md","filePath":"src/article/imagemin.md","lastUpdated":1726550590000}'),n={name:"src/article/imagemin.md"};function s(o,e,c,d,l,p){return i(),r("div",{"data-pagefind-body":!0},e[0]||(e[0]=[a("h1",{id:"imagemin-图片压缩源码分析",tabindex:"-1"},[m("imagemin 图片压缩源码分析 "),a("a",{class:"header-anchor",href:"#imagemin-图片压缩源码分析","aria-label":'Permalink to "imagemin 图片压缩源码分析"'},"​")],-1)]))}const _=t(n,[["render",s]]);export{f as __pageData,_ as default}; diff --git a/assets/src_article_imagemin.md.DTz2O7QV.lean.js b/assets/src_article_imagemin.md.DTz2O7QV.lean.js new file mode 100644 index 0000000000..9d0840b961 --- /dev/null +++ b/assets/src_article_imagemin.md.DTz2O7QV.lean.js @@ -0,0 +1 @@ +import{_ as t,o as i,c as r,j as a,a as m}from"./chunks/framework.C-ai2y4t.js";const f=JSON.parse('{"title":"imagemin 图片压缩源码分析","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/imagemin.md","filePath":"src/article/imagemin.md","lastUpdated":1726550590000}'),n={name:"src/article/imagemin.md"};function s(o,e,c,d,l,p){return i(),r("div",{"data-pagefind-body":!0},e[0]||(e[0]=[a("h1",{id:"imagemin-图片压缩源码分析",tabindex:"-1"},[m("imagemin 图片压缩源码分析 "),a("a",{class:"header-anchor",href:"#imagemin-图片压缩源码分析","aria-label":'Permalink to "imagemin 图片压缩源码分析"'},"​")],-1)]))}const _=t(n,[["render",s]]);export{f as __pageData,_ as default}; diff --git a/assets/src_article_javascript_domLoad.md.C2Dqx2X1.js b/assets/src_article_javascript_domLoad.md.C2Dqx2X1.js new file mode 100644 index 0000000000..68644d9104 --- /dev/null +++ b/assets/src_article_javascript_domLoad.md.C2Dqx2X1.js @@ -0,0 +1 @@ +import{_ as e,o as t,c as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"页面加载完成后事件","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/javascript/domLoad.md","filePath":"src/article/javascript/domLoad.md","lastUpdated":1726550590000}'),o={name:"src/article/javascript/domLoad.md"};function n(d,a,l,r,c,h){return t(),s("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

页面加载完成后事件

window.onload

DOMContentLoaded

js
document.addEventListener('DOMContentLoaded', fun);

<body onload="fun()">

readyState

js
document.readyState;\n\ndocument.onreadystatechange;

一个文档的 readyState 可以是以下之一:

  • loading / 加载。document 仍在加载。
  • interactive / 互动。文档已经完成加载,文档已被解析,但是诸如图像,样式表和框架之类的子资源仍在加载。
  • complete / 完成。T 文档和所有子资源已完成加载。状态表示 load 事件即将被触发。
',9)]))}const k=e(o,[["render",n]]);export{u as __pageData,k as default}; diff --git a/assets/src_article_javascript_domLoad.md.C2Dqx2X1.lean.js b/assets/src_article_javascript_domLoad.md.C2Dqx2X1.lean.js new file mode 100644 index 0000000000..68644d9104 --- /dev/null +++ b/assets/src_article_javascript_domLoad.md.C2Dqx2X1.lean.js @@ -0,0 +1 @@ +import{_ as e,o as t,c as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"页面加载完成后事件","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/javascript/domLoad.md","filePath":"src/article/javascript/domLoad.md","lastUpdated":1726550590000}'),o={name:"src/article/javascript/domLoad.md"};function n(d,a,l,r,c,h){return t(),s("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

页面加载完成后事件

window.onload

DOMContentLoaded

js
document.addEventListener('DOMContentLoaded', fun);

<body onload="fun()">

readyState

js
document.readyState;\n\ndocument.onreadystatechange;

一个文档的 readyState 可以是以下之一:

  • loading / 加载。document 仍在加载。
  • interactive / 互动。文档已经完成加载,文档已被解析,但是诸如图像,样式表和框架之类的子资源仍在加载。
  • complete / 完成。T 文档和所有子资源已完成加载。状态表示 load 事件即将被触发。
',9)]))}const k=e(o,[["render",n]]);export{u as __pageData,k as default}; diff --git a/assets/src_article_sort_bubble_index.md.fAtbvQz_.js b/assets/src_article_sort_bubble_index.md.fAtbvQz_.js new file mode 100644 index 0000000000..c252f70bba --- /dev/null +++ b/assets/src_article_sort_bubble_index.md.fAtbvQz_.js @@ -0,0 +1,13 @@ +import{_ as i}from"./chunks/bubble.Dg5jgvyl.js";import{_ as a,o as t,c as e,a3 as n}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"Bubble Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/bubble/index.md","filePath":"src/article/sort/bubble/index.md","lastUpdated":1726550590000}'),h={name:"src/article/sort/bubble/index.md"};function l(p,s,k,r,d,E){return t(),e("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n('

Bubble Sort

Bubble sort is a simple sort algorithm. It repeatedly visits the sequence to be sorted, comparing two elements at a time and swapping them if they are in the wrong order. The work of visiting the sequence is repeated until no more exchanges are needed, that is, the sequence has been sorted. The algorithm gets its name from the fact that smaller elements slowly "float" to the top of the sequence through exchange.

Algorithm description

  • Compare adjacent elements. If the first one is bigger than the second, swap them both;
  • Do the same for each pair of adjacent elements, from the first pair at the beginning to the last pair at the end, so that the last element should be the largest;
  • Repeat the above steps for all elements except the last one;
  • Repeat steps 1 to 3 until the sorting is complete.

GIF presentation

Bubble Sort

Code demo

ts
const bubble = (list: number[]) => {
+  const size = list.length;
+  for (let i = 0; i < size; i++) {
+    for (let j = 0; j < size; j++) {
+      if (list[i] < list[j]) {
+        list[i] = list[i] ^ list[j];
+        list[j] = list[i] ^ list[j];
+        list[i] = list[i] ^ list[j];
+      }
+    }
+  }
+  return list;
+};
`,8)]))}const y=a(h,[["render",l]]);export{c as __pageData,y as default}; diff --git a/assets/src_article_sort_bubble_index.md.fAtbvQz_.lean.js b/assets/src_article_sort_bubble_index.md.fAtbvQz_.lean.js new file mode 100644 index 0000000000..c252f70bba --- /dev/null +++ b/assets/src_article_sort_bubble_index.md.fAtbvQz_.lean.js @@ -0,0 +1,13 @@ +import{_ as i}from"./chunks/bubble.Dg5jgvyl.js";import{_ as a,o as t,c as e,a3 as n}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"Bubble Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/bubble/index.md","filePath":"src/article/sort/bubble/index.md","lastUpdated":1726550590000}'),h={name:"src/article/sort/bubble/index.md"};function l(p,s,k,r,d,E){return t(),e("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n('

Bubble Sort

Bubble sort is a simple sort algorithm. It repeatedly visits the sequence to be sorted, comparing two elements at a time and swapping them if they are in the wrong order. The work of visiting the sequence is repeated until no more exchanges are needed, that is, the sequence has been sorted. The algorithm gets its name from the fact that smaller elements slowly "float" to the top of the sequence through exchange.

Algorithm description

  • Compare adjacent elements. If the first one is bigger than the second, swap them both;
  • Do the same for each pair of adjacent elements, from the first pair at the beginning to the last pair at the end, so that the last element should be the largest;
  • Repeat the above steps for all elements except the last one;
  • Repeat steps 1 to 3 until the sorting is complete.

GIF presentation

Bubble Sort

Code demo

ts
const bubble = (list: number[]) => {
+  const size = list.length;
+  for (let i = 0; i < size; i++) {
+    for (let j = 0; j < size; j++) {
+      if (list[i] < list[j]) {
+        list[i] = list[i] ^ list[j];
+        list[j] = list[i] ^ list[j];
+        list[i] = list[i] ^ list[j];
+      }
+    }
+  }
+  return list;
+};
`,8)]))}const y=a(h,[["render",l]]);export{c as __pageData,y as default}; diff --git a/assets/src_article_sort_bucket_index.md.BhE2wW4O.js b/assets/src_article_sort_bucket_index.md.BhE2wW4O.js new file mode 100644 index 0000000000..ac0f346406 --- /dev/null +++ b/assets/src_article_sort_bucket_index.md.BhE2wW4O.js @@ -0,0 +1,57 @@ +import{_ as i,o as a,c as h,a3 as n}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"Bucket Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/bucket/index.md","filePath":"src/article/sort/bucket/index.md","lastUpdated":1726550590000}'),k={name:"src/article/sort/bucket/index.md"};function t(l,s,p,e,E,r){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

Bucket Sort

The key to efficiency is this bucket function. The data is divided into a limited number of buckets, and each bucket is sorted separately (it is possible to use another sorting algorithm or recursively continue to use bucket sorting).

Algorithm description

  • Set a quantitative array as an empty bucket;
  • Iterate over the input data and place the data one by one into the corresponding bucket;
  • Sort each bucket that is not empty;
  • Piecing together sorted data from a bucket that is never empty.

Code demo

ts
const count = (list: Array<number>, max: number = 100): Array<number> => {
+  const countList = new Array(max + 1);
+  for (let i = 0; i < list.length; i++) {
+    if (!countList[list[i]]) {
+      countList[list[i]] = 0;
+    }
+    countList[list[i]]++;
+  }
+  let startIndex = 0;
+  for (let i = 0; i < countList.length; i++) {
+    while (countList[i] > 0) {
+      list[startIndex++] = i;
+      countList[i]--;
+    }
+  }
+  return list;
+};
+const getMax = (list: Array<number>) => {
+  let max = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+const getMin = (list: Array<number>) => {
+  let min = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (min > list[i]) {
+      min = list[i];
+    }
+  }
+  return min;
+};
+
+/**
+ * @description: Bucket Sort
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const bucket = (list: Array<number>, bucketSize: number = 5, max?: number, min?: number): Array<number> => {
+  if (list.length === 0) return list;
+  if (!max) max = getMax(list);
+  if (!min) min = getMin(list);
+  const bucketCount = Math.floor((max - min) / bucketSize) + 1;
+  const buckets = new Array(bucketCount + 1).fill(0).map(() => new Array(0));
+
+  for (let i = 0; i < list.length; i++) {
+    buckets[Math.floor((list[i] - min) / bucketSize)].push(list[i]);
+  }
+  list = [];
+  for (let i = 0; i < bucketCount; i++) {
+    list = list.concat(count(buckets[i]));
+  }
+  return list;
+};

Algorithm analysis

Bucket sorting best uses linear time O(n), and the time complexity of bucket sorting depends on the time complexity of sorting data between buckets, because the time complexity of other parts is O(n). Obviously, the smaller the buckets, the less data there is between them, and the less time it takes to sort them. But the corresponding space consumption will increase.

`,8)]))}const y=i(k,[["render",t]]);export{g as __pageData,y as default}; diff --git a/assets/src_article_sort_bucket_index.md.BhE2wW4O.lean.js b/assets/src_article_sort_bucket_index.md.BhE2wW4O.lean.js new file mode 100644 index 0000000000..ac0f346406 --- /dev/null +++ b/assets/src_article_sort_bucket_index.md.BhE2wW4O.lean.js @@ -0,0 +1,57 @@ +import{_ as i,o as a,c as h,a3 as n}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"Bucket Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/bucket/index.md","filePath":"src/article/sort/bucket/index.md","lastUpdated":1726550590000}'),k={name:"src/article/sort/bucket/index.md"};function t(l,s,p,e,E,r){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

Bucket Sort

The key to efficiency is this bucket function. The data is divided into a limited number of buckets, and each bucket is sorted separately (it is possible to use another sorting algorithm or recursively continue to use bucket sorting).

Algorithm description

  • Set a quantitative array as an empty bucket;
  • Iterate over the input data and place the data one by one into the corresponding bucket;
  • Sort each bucket that is not empty;
  • Piecing together sorted data from a bucket that is never empty.

Code demo

ts
const count = (list: Array<number>, max: number = 100): Array<number> => {
+  const countList = new Array(max + 1);
+  for (let i = 0; i < list.length; i++) {
+    if (!countList[list[i]]) {
+      countList[list[i]] = 0;
+    }
+    countList[list[i]]++;
+  }
+  let startIndex = 0;
+  for (let i = 0; i < countList.length; i++) {
+    while (countList[i] > 0) {
+      list[startIndex++] = i;
+      countList[i]--;
+    }
+  }
+  return list;
+};
+const getMax = (list: Array<number>) => {
+  let max = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+const getMin = (list: Array<number>) => {
+  let min = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (min > list[i]) {
+      min = list[i];
+    }
+  }
+  return min;
+};
+
+/**
+ * @description: Bucket Sort
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const bucket = (list: Array<number>, bucketSize: number = 5, max?: number, min?: number): Array<number> => {
+  if (list.length === 0) return list;
+  if (!max) max = getMax(list);
+  if (!min) min = getMin(list);
+  const bucketCount = Math.floor((max - min) / bucketSize) + 1;
+  const buckets = new Array(bucketCount + 1).fill(0).map(() => new Array(0));
+
+  for (let i = 0; i < list.length; i++) {
+    buckets[Math.floor((list[i] - min) / bucketSize)].push(list[i]);
+  }
+  list = [];
+  for (let i = 0; i < bucketCount; i++) {
+    list = list.concat(count(buckets[i]));
+  }
+  return list;
+};

Algorithm analysis

Bucket sorting best uses linear time O(n), and the time complexity of bucket sorting depends on the time complexity of sorting data between buckets, because the time complexity of other parts is O(n). Obviously, the smaller the buckets, the less data there is between them, and the less time it takes to sort them. But the corresponding space consumption will increase.

`,8)]))}const y=i(k,[["render",t]]);export{g as __pageData,y as default}; diff --git a/assets/src_article_sort_count_index.md.DvPhDLiz.js b/assets/src_article_sort_count_index.md.DvPhDLiz.js new file mode 100644 index 0000000000..8d803f2077 --- /dev/null +++ b/assets/src_article_sort_count_index.md.DvPhDLiz.js @@ -0,0 +1,34 @@ +import{_ as i}from"./chunks/count.CcfK-WL7.js";import{_ as a,o as n,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"Count Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/count/index.md","filePath":"src/article/sort/count/index.md","lastUpdated":1726550590000}'),l={name:"src/article/sort/count/index.md"};function k(e,s,p,r,E,d){return n(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h('

Count Sort

counting sort is a kind of sorting algorithm that sacrifices memory space for low time complexity, and it is also a kind of algorithm that is not based on comparison. The non-comparison-based sorting algorithm here means that there is no comparison size between array elements. We know that the divide-and-conquer method to solve the sorting problem can only make the time complexity of the algorithm approach Θ(nlogn) at the fastest, that is, the time complexity based on comparison has a lower bound Ω(nlog⁡n), and the sorting algorithm based on no comparison can break through this lower bound.

Algorithm description

  • Find the largest and smallest elements of the array to be sorted;
  • Count the number of occurrences of each element with value i in the array, stored in the i - th item of the array C;
  • Add up all counts (starting with the first element in C and adding each term to the previous one);
  • Backfill the target array: Place each element i in the C(i) item of the new array, and subtract 1 from C(i) for each element.

GIF presentation

Count Sort

Code demo

ts
const getMax = (list: number[]) => {
+  let max = list[0];
+  for (let i = 1; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+/**
+ * @description: Count Sort
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const count = (list: number[]): number[] => {
+  if (list.length <= 1) return list;
+  const max = getMax(list);
+  const countList = new Array(max + 1).fill(0);
+  list.forEach((item) => {
+    if (!countList[item]) {
+      countList[item] = 1;
+    } else {
+      countList[item]++;
+    }
+  });
+  const result = [];
+  for (let i = 0; i < countList.length; i++) {
+    while (countList[i]) {
+      result.push(i);
+      countList[i]--;
+    }
+  }
+  return result;
+};

Algorithm analysis

Counting sort is a stable sorting algorithm. When the input elements are n integers between 0 and k, the time complexity is O(n+k) and the space complexity is also O(n+k), which sorts faster than any comparison sorting algorithm. Counting sort is an efficient sorting algorithm when k is not large and the sequence is concentrated.

`,10)]))}const c=a(l,[["render",k]]);export{y as __pageData,c as default}; diff --git a/assets/src_article_sort_count_index.md.DvPhDLiz.lean.js b/assets/src_article_sort_count_index.md.DvPhDLiz.lean.js new file mode 100644 index 0000000000..8d803f2077 --- /dev/null +++ b/assets/src_article_sort_count_index.md.DvPhDLiz.lean.js @@ -0,0 +1,34 @@ +import{_ as i}from"./chunks/count.CcfK-WL7.js";import{_ as a,o as n,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"Count Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/count/index.md","filePath":"src/article/sort/count/index.md","lastUpdated":1726550590000}'),l={name:"src/article/sort/count/index.md"};function k(e,s,p,r,E,d){return n(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h('

Count Sort

counting sort is a kind of sorting algorithm that sacrifices memory space for low time complexity, and it is also a kind of algorithm that is not based on comparison. The non-comparison-based sorting algorithm here means that there is no comparison size between array elements. We know that the divide-and-conquer method to solve the sorting problem can only make the time complexity of the algorithm approach Θ(nlogn) at the fastest, that is, the time complexity based on comparison has a lower bound Ω(nlog⁡n), and the sorting algorithm based on no comparison can break through this lower bound.

Algorithm description

  • Find the largest and smallest elements of the array to be sorted;
  • Count the number of occurrences of each element with value i in the array, stored in the i - th item of the array C;
  • Add up all counts (starting with the first element in C and adding each term to the previous one);
  • Backfill the target array: Place each element i in the C(i) item of the new array, and subtract 1 from C(i) for each element.

GIF presentation

Count Sort

Code demo

ts
const getMax = (list: number[]) => {
+  let max = list[0];
+  for (let i = 1; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+/**
+ * @description: Count Sort
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const count = (list: number[]): number[] => {
+  if (list.length <= 1) return list;
+  const max = getMax(list);
+  const countList = new Array(max + 1).fill(0);
+  list.forEach((item) => {
+    if (!countList[item]) {
+      countList[item] = 1;
+    } else {
+      countList[item]++;
+    }
+  });
+  const result = [];
+  for (let i = 0; i < countList.length; i++) {
+    while (countList[i]) {
+      result.push(i);
+      countList[i]--;
+    }
+  }
+  return result;
+};

Algorithm analysis

Counting sort is a stable sorting algorithm. When the input elements are n integers between 0 and k, the time complexity is O(n+k) and the space complexity is also O(n+k), which sorts faster than any comparison sorting algorithm. Counting sort is an efficient sorting algorithm when k is not large and the sequence is concentrated.

`,10)]))}const c=a(l,[["render",k]]);export{y as __pageData,c as default}; diff --git a/assets/src_article_sort_heap_index.md.qYkik3kq.js b/assets/src_article_sort_heap_index.md.qYkik3kq.js new file mode 100644 index 0000000000..5ceaf51b1c --- /dev/null +++ b/assets/src_article_sort_heap_index.md.qYkik3kq.js @@ -0,0 +1,50 @@ +import{_ as i}from"./chunks/heap.xduQWyUN.js";import{_ as a,o as h,c as n,a3 as k}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"Heap Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/heap/index.md","filePath":"src/article/sort/heap/index.md","lastUpdated":1726550590000}'),t={name:"src/article/sort/heap/index.md"};function l(p,s,e,r,E,d){return h(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k('

Heap Sort

Heapsort (Heapsort) is a kind of sorting algorithm designed by using the heap data structure. A heap is an almost complete binary tree structure, but also satisfies the property of a heap: the key value or index of a child node is always less than (or greater than) its parent node.

Algorithm description

  • The initial sequence of keywords to be sorted (R1,R2... .Rn) builds a large top heap, which is the initial disordered region;
  • Swap the top element R[1] with the last element R[n] to get a new unordered region (R1,R2,... Rn-1) and a new ordered region (Rn), satisfying R[1,2... n-1]< =R[n];
  • Since the new top R[1] may violate the nature of the heap after exchange, it is necessary to adjust the current disorder region (R1,R2,... Rn-1) adjusts to the new heap, then swaps R[1] again with the last element of the unordered area, giving a new unordered area (R1,R2... .Rn-2) and the new ordered region (RN-1,Rn). Repeat this process until the number of elements in the ordered area is n-1, then the sorting process is complete.
  • Use large root piles in ascending order and small root piles in descending order

GIF presentation

Heap Sort

Code demo

ts
class Heap {
+  value: Array<number>;
+  size: number;
+  constructor(arr: Array<number> = []) {
+    this.value = [...arr];
+    this.size = arr.length;
+    this.buildMaxHeap();
+  }
+  swap = (i: number, j: number) => {
+    if (this.value[i] === this.value[j]) return;
+    this.value[i] = this.value[i] ^ this.value[j];
+    this.value[j] = this.value[i] ^ this.value[j];
+    this.value[i] = this.value[i] ^ this.value[j];
+  };
+  heapHandler = (i: number) => {
+    const left = 2 * i + 1;
+    const right = 2 * i + 2;
+    let largest = i;
+    if (left < this.size && this.value[left] > this.value[largest]) {
+      largest = left;
+    }
+    if (right < this.size && this.value[right] > this.value[largest]) {
+      largest = right;
+    }
+    if (largest !== i) {
+      this.swap(i, largest);
+      this.heapHandler(largest);
+    }
+  };
+  buildMaxHeap = () => {
+    for (let i = this.size >> 1; i >= 0; i--) {
+      this.heapHandler(i);
+    }
+    for (let i = this.size - 1; i >= 0; i--) {
+      this.swap(0, i);
+      this.size--;
+      this.heapHandler(0);
+    }
+  };
+}
+
+/**
+ * @description: Heap Sort
+ * @param {Array} list
+ * @return {Array}
+ */
+const heap = (list: Array<number>): Array<number> => {
+  const { value } = new Heap(list);
+  return value;
+};
`,8)]))}const o=a(t,[["render",l]]);export{F as __pageData,o as default}; diff --git a/assets/src_article_sort_heap_index.md.qYkik3kq.lean.js b/assets/src_article_sort_heap_index.md.qYkik3kq.lean.js new file mode 100644 index 0000000000..5ceaf51b1c --- /dev/null +++ b/assets/src_article_sort_heap_index.md.qYkik3kq.lean.js @@ -0,0 +1,50 @@ +import{_ as i}from"./chunks/heap.xduQWyUN.js";import{_ as a,o as h,c as n,a3 as k}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"Heap Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/heap/index.md","filePath":"src/article/sort/heap/index.md","lastUpdated":1726550590000}'),t={name:"src/article/sort/heap/index.md"};function l(p,s,e,r,E,d){return h(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k('

Heap Sort

Heapsort (Heapsort) is a kind of sorting algorithm designed by using the heap data structure. A heap is an almost complete binary tree structure, but also satisfies the property of a heap: the key value or index of a child node is always less than (or greater than) its parent node.

Algorithm description

  • The initial sequence of keywords to be sorted (R1,R2... .Rn) builds a large top heap, which is the initial disordered region;
  • Swap the top element R[1] with the last element R[n] to get a new unordered region (R1,R2,... Rn-1) and a new ordered region (Rn), satisfying R[1,2... n-1]< =R[n];
  • Since the new top R[1] may violate the nature of the heap after exchange, it is necessary to adjust the current disorder region (R1,R2,... Rn-1) adjusts to the new heap, then swaps R[1] again with the last element of the unordered area, giving a new unordered area (R1,R2... .Rn-2) and the new ordered region (RN-1,Rn). Repeat this process until the number of elements in the ordered area is n-1, then the sorting process is complete.
  • Use large root piles in ascending order and small root piles in descending order

GIF presentation

Heap Sort

Code demo

ts
class Heap {
+  value: Array<number>;
+  size: number;
+  constructor(arr: Array<number> = []) {
+    this.value = [...arr];
+    this.size = arr.length;
+    this.buildMaxHeap();
+  }
+  swap = (i: number, j: number) => {
+    if (this.value[i] === this.value[j]) return;
+    this.value[i] = this.value[i] ^ this.value[j];
+    this.value[j] = this.value[i] ^ this.value[j];
+    this.value[i] = this.value[i] ^ this.value[j];
+  };
+  heapHandler = (i: number) => {
+    const left = 2 * i + 1;
+    const right = 2 * i + 2;
+    let largest = i;
+    if (left < this.size && this.value[left] > this.value[largest]) {
+      largest = left;
+    }
+    if (right < this.size && this.value[right] > this.value[largest]) {
+      largest = right;
+    }
+    if (largest !== i) {
+      this.swap(i, largest);
+      this.heapHandler(largest);
+    }
+  };
+  buildMaxHeap = () => {
+    for (let i = this.size >> 1; i >= 0; i--) {
+      this.heapHandler(i);
+    }
+    for (let i = this.size - 1; i >= 0; i--) {
+      this.swap(0, i);
+      this.size--;
+      this.heapHandler(0);
+    }
+  };
+}
+
+/**
+ * @description: Heap Sort
+ * @param {Array} list
+ * @return {Array}
+ */
+const heap = (list: Array<number>): Array<number> => {
+  const { value } = new Heap(list);
+  return value;
+};
`,8)]))}const o=a(t,[["render",l]]);export{F as __pageData,o as default}; diff --git a/assets/src_article_sort_index.md.DZ3i3D2R.js b/assets/src_article_sort_index.md.DZ3i3D2R.js new file mode 100644 index 0000000000..578a811005 --- /dev/null +++ b/assets/src_article_sort_index.md.DZ3i3D2R.js @@ -0,0 +1 @@ +import{_ as t,a}from"./chunks/complexity.CSkvDr7k.js";import{_ as o,o as i,c as r,a3 as n}from"./chunks/framework.C-ai2y4t.js";const b=JSON.parse('{"title":"Ten classic sorting algorithms","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/index.md","filePath":"src/article/sort/index.md","lastUpdated":1726550590000}'),s={name:"src/article/sort/index.md"};function l(c,e,m,d,h,p){return i(),r("div",{"data-pagefind-body":!0},e[0]||(e[0]=[n('

Ten classic sorting algorithms

The ten common sorting algorithms can be divided into two broad categories:

  • Comparator sort:By comparison to determine the relative order between elements, because its time complexity can not break through O(nlogn), so it is also called nonlinear time comparison class sorting.
  • Non-comparison sort:Instead of determining the relative order between elements by comparison, it can break through the time lower bound based on comparison sort and run in linear time, so it is also called linear time non-comparison sort.

Sorting algorithm classification

Algorithm complexity

Algorithm complexity

  • Stable: If a was originally in front of b and a=b, a is still in front of b after sorting.
  • Unstable: If a originally comes before b and a=b, a may come after b after sorting.
  • Time complexity: The total number of operations on sorted data. Reflects what rule the number of operations presents when n changes.
  • Spatial complexity: refers to the measure of the storage space required when the algorithm is executed in the computer, and it is also a function of the data size n.
',8)]))}const u=o(s,[["render",l]]);export{b as __pageData,u as default}; diff --git a/assets/src_article_sort_index.md.DZ3i3D2R.lean.js b/assets/src_article_sort_index.md.DZ3i3D2R.lean.js new file mode 100644 index 0000000000..578a811005 --- /dev/null +++ b/assets/src_article_sort_index.md.DZ3i3D2R.lean.js @@ -0,0 +1 @@ +import{_ as t,a}from"./chunks/complexity.CSkvDr7k.js";import{_ as o,o as i,c as r,a3 as n}from"./chunks/framework.C-ai2y4t.js";const b=JSON.parse('{"title":"Ten classic sorting algorithms","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/index.md","filePath":"src/article/sort/index.md","lastUpdated":1726550590000}'),s={name:"src/article/sort/index.md"};function l(c,e,m,d,h,p){return i(),r("div",{"data-pagefind-body":!0},e[0]||(e[0]=[n('

Ten classic sorting algorithms

The ten common sorting algorithms can be divided into two broad categories:

  • Comparator sort:By comparison to determine the relative order between elements, because its time complexity can not break through O(nlogn), so it is also called nonlinear time comparison class sorting.
  • Non-comparison sort:Instead of determining the relative order between elements by comparison, it can break through the time lower bound based on comparison sort and run in linear time, so it is also called linear time non-comparison sort.

Sorting algorithm classification

Algorithm complexity

Algorithm complexity

  • Stable: If a was originally in front of b and a=b, a is still in front of b after sorting.
  • Unstable: If a originally comes before b and a=b, a may come after b after sorting.
  • Time complexity: The total number of operations on sorted data. Reflects what rule the number of operations presents when n changes.
  • Spatial complexity: refers to the measure of the storage space required when the algorithm is executed in the computer, and it is also a function of the data size n.
',8)]))}const u=o(s,[["render",l]]);export{b as __pageData,u as default}; diff --git a/assets/src_article_sort_insert_index.md.CPhWGrRG.js b/assets/src_article_sort_insert_index.md.CPhWGrRG.js new file mode 100644 index 0000000000..8671eb4cc1 --- /dev/null +++ b/assets/src_article_sort_insert_index.md.CPhWGrRG.js @@ -0,0 +1,13 @@ +import{_ as i}from"./chunks/insert.Bde3uDH4.js";import{_ as a,o as t,c as e,a3 as n}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"Insert Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/insert/index.md","filePath":"src/article/sort/insert/index.md","lastUpdated":1726550590000}'),h={name:"src/article/sort/insert/index.md"};function l(p,s,r,k,d,o){return t(),e("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n('

Insert Sort

Stable sorting algorithm, because no matter what data is entered is O(n2) time complexity, so when it is used, the smaller the data size, the better. The advantage is that no additional memory space is taken up. It works by building an ordered sequence and, for unsorted data, scanning from back to front in the sorted sequence, finding the appropriate position and inserting it.

Algorithm description

  • Start with the first element, which can be considered to have been sorted;
  • Take the next element and scan it from back to front in the already sorted sequence of elements;
  • If the element (sorted) is larger than the new element, move the element to the next position;
  • Repeat step 3 until you find a position where the sorted element is less than or equal to the new element;
  • After inserting a new element into this position;
  • Repeat Steps 2 to 5.

GIF presentation

Insert Sort

Code demo

ts
const insert = (list: number[]): number[] => {
+  const size = list.length;
+  for (let i = 1; i < size; i++) {
+    const current = list[i];
+    let preIndex = i - 1;
+    while (preIndex >= 0 && list[preIndex] > current) {
+      list[preIndex + 1] = list[preIndex];
+      preIndex--;
+    }
+    list[preIndex + 1] = current;
+  }
+  return list;
+};

Algorithm analysis

Insertion sort in the implementation, usually use in-place sort (that is, only need to use O(1) of the additional space of the sort), so in the process of scanning from back to forward, the sorted elements need to be repeatedly moved backward step by step, to provide insertion space for the latest elements.

`,10)]))}const c=a(h,[["render",l]]);export{y as __pageData,c as default}; diff --git a/assets/src_article_sort_insert_index.md.CPhWGrRG.lean.js b/assets/src_article_sort_insert_index.md.CPhWGrRG.lean.js new file mode 100644 index 0000000000..8671eb4cc1 --- /dev/null +++ b/assets/src_article_sort_insert_index.md.CPhWGrRG.lean.js @@ -0,0 +1,13 @@ +import{_ as i}from"./chunks/insert.Bde3uDH4.js";import{_ as a,o as t,c as e,a3 as n}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"Insert Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/insert/index.md","filePath":"src/article/sort/insert/index.md","lastUpdated":1726550590000}'),h={name:"src/article/sort/insert/index.md"};function l(p,s,r,k,d,o){return t(),e("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n('

Insert Sort

Stable sorting algorithm, because no matter what data is entered is O(n2) time complexity, so when it is used, the smaller the data size, the better. The advantage is that no additional memory space is taken up. It works by building an ordered sequence and, for unsorted data, scanning from back to front in the sorted sequence, finding the appropriate position and inserting it.

Algorithm description

  • Start with the first element, which can be considered to have been sorted;
  • Take the next element and scan it from back to front in the already sorted sequence of elements;
  • If the element (sorted) is larger than the new element, move the element to the next position;
  • Repeat step 3 until you find a position where the sorted element is less than or equal to the new element;
  • After inserting a new element into this position;
  • Repeat Steps 2 to 5.

GIF presentation

Insert Sort

Code demo

ts
const insert = (list: number[]): number[] => {
+  const size = list.length;
+  for (let i = 1; i < size; i++) {
+    const current = list[i];
+    let preIndex = i - 1;
+    while (preIndex >= 0 && list[preIndex] > current) {
+      list[preIndex + 1] = list[preIndex];
+      preIndex--;
+    }
+    list[preIndex + 1] = current;
+  }
+  return list;
+};

Algorithm analysis

Insertion sort in the implementation, usually use in-place sort (that is, only need to use O(1) of the additional space of the sort), so in the process of scanning from back to forward, the sorted elements need to be repeatedly moved backward step by step, to provide insertion space for the latest elements.

`,10)]))}const c=a(h,[["render",l]]);export{y as __pageData,c as default}; diff --git a/assets/src_article_sort_merge_index.md.DCFZpDV3.js b/assets/src_article_sort_merge_index.md.DCFZpDV3.js new file mode 100644 index 0000000000..8228a19bf4 --- /dev/null +++ b/assets/src_article_sort_merge_index.md.DCFZpDV3.js @@ -0,0 +1,33 @@ +import{_ as i}from"./chunks/merge.D_M4N_iU.js";import{_ as a,o as n,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"Merge Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/merge/index.md","filePath":"src/article/sort/merge/index.md","lastUpdated":1726550590000}'),l={name:"src/article/sort/merge/index.md"};function k(e,s,p,r,E,d){return n(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

Merge Sort

Merge sort is an effective sort algorithm based on merge operation. This algorithm is a very typical application of Divide and Conquer. By combining the ordered subsequences, a completely ordered sequence is obtained. That is, each subsequence is ordered first, and then the subsequence segments are ordered. If two ordered tables are merged into one ordered table, it is called a 2-way merge.

Algorithm description

  • Divide the input sequence of length n into two subsequences of length n/2;
  • The two subsequences were merged and sorted respectively.
  • Merge two sorted subsequences into one final sorted sequence.

GIF presentation

Merge Sort

Code demo

ts
const combine = (left: Array<number>, right: Array<number>) => {
+  const list: Array<number> = [];
+  while (left.length > 0 && right.length > 0) {
+    if (left[0] <= right[0]) {
+      list.push(left.shift()!);
+    } else {
+      list.push(right.shift()!);
+    }
+  }
+
+  while (left.length) {
+    list.push(left.shift()!);
+  }
+  while (right.length) {
+    list.push(right.shift()!);
+  }
+  return list;
+};
+/**
+ * @description: Merge sort
+ * @param {Array} list
+ * @return {Array}
+ */
+const merge = (list: Array<number>): Array<number> => {
+  const { length } = list;
+  if (length <= 1) {
+    return list;
+  }
+  const middle = length >> 1;
+  const left = list.slice(0, middle);
+  const right = list.slice(middle);
+  return combine(merge(left), merge(right));
+};

Algorithm analysis

Merge sort is a stable sort method. Like select sort, merge sort performs independently of the input data, but performs much better than select sort because it is always O(nlogn) in time complexity. The trade-off is extra memory space.

`,10)]))}const F=a(l,[["render",k]]);export{o as __pageData,F as default}; diff --git a/assets/src_article_sort_merge_index.md.DCFZpDV3.lean.js b/assets/src_article_sort_merge_index.md.DCFZpDV3.lean.js new file mode 100644 index 0000000000..8228a19bf4 --- /dev/null +++ b/assets/src_article_sort_merge_index.md.DCFZpDV3.lean.js @@ -0,0 +1,33 @@ +import{_ as i}from"./chunks/merge.D_M4N_iU.js";import{_ as a,o as n,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"Merge Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/merge/index.md","filePath":"src/article/sort/merge/index.md","lastUpdated":1726550590000}'),l={name:"src/article/sort/merge/index.md"};function k(e,s,p,r,E,d){return n(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

Merge Sort

Merge sort is an effective sort algorithm based on merge operation. This algorithm is a very typical application of Divide and Conquer. By combining the ordered subsequences, a completely ordered sequence is obtained. That is, each subsequence is ordered first, and then the subsequence segments are ordered. If two ordered tables are merged into one ordered table, it is called a 2-way merge.

Algorithm description

  • Divide the input sequence of length n into two subsequences of length n/2;
  • The two subsequences were merged and sorted respectively.
  • Merge two sorted subsequences into one final sorted sequence.

GIF presentation

Merge Sort

Code demo

ts
const combine = (left: Array<number>, right: Array<number>) => {
+  const list: Array<number> = [];
+  while (left.length > 0 && right.length > 0) {
+    if (left[0] <= right[0]) {
+      list.push(left.shift()!);
+    } else {
+      list.push(right.shift()!);
+    }
+  }
+
+  while (left.length) {
+    list.push(left.shift()!);
+  }
+  while (right.length) {
+    list.push(right.shift()!);
+  }
+  return list;
+};
+/**
+ * @description: Merge sort
+ * @param {Array} list
+ * @return {Array}
+ */
+const merge = (list: Array<number>): Array<number> => {
+  const { length } = list;
+  if (length <= 1) {
+    return list;
+  }
+  const middle = length >> 1;
+  const left = list.slice(0, middle);
+  const right = list.slice(middle);
+  return combine(merge(left), merge(right));
+};

Algorithm analysis

Merge sort is a stable sort method. Like select sort, merge sort performs independently of the input data, but performs much better than select sort because it is always O(nlogn) in time complexity. The trade-off is extra memory space.

`,10)]))}const F=a(l,[["render",k]]);export{o as __pageData,F as default}; diff --git a/assets/src_article_sort_quick_index.md.tGhXdyib.js b/assets/src_article_sort_quick_index.md.tGhXdyib.js new file mode 100644 index 0000000000..9f12db7dfa --- /dev/null +++ b/assets/src_article_sort_quick_index.md.tGhXdyib.js @@ -0,0 +1,51 @@ +import{_ as i}from"./chunks/quick.WcLzRUPH.js";import{_ as a,o as n,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"Quick Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/quick/index.md","filePath":"src/article/sort/quick/index.md","lastUpdated":1726550590000}'),k={name:"src/article/sort/quick/index.md"};function l(p,s,e,r,E,d){return n(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

Quick Sort

The basic idea of quick sorting is that the records to be sorted are separated into two independent parts through one sort. The keywords of one part of the records are smaller than those of the other part. Then the two parts of the records can be sorted separately to achieve the entire sequence.

Algorithm description

Quicksort uses divide-and-conquer to divide a list into two sub-lists. The specific algorithm is described as follows:

  • Picking out an element from the sequence, called a "pivot";
  • Reorder the sequence so that all elements smaller than the base value are placed in front of the base value and all elements larger than the base value are placed behind the base value (the same number can go to either side). After the partition exits, the benchmark is in the middle of the sequence. This is called a partition operation;
  • Recursively sorts subsequences of elements less than the base value and subsequences of elements greater than the base value.

GIF presentation

Quick Sort

Code demo

ts
/**
+ * @description: Sets the base value pivot
+ * @param {Array} list
+ * @param {number} left
+ * @param {number} right
+ * @return {number} index
+ */
+const partition = (list: number[] = [], left: number, right: number) => {
+  const pivot = left;
+  let index = pivot + 1;
+  for (let i = index; i <= right; i++) {
+    if (list[i] < list[pivot]) {
+      if (list[i] !== list[index]) {
+        list[i] = list[i] ^ list[index];
+        list[index] = list[i] ^ list[index];
+        list[i] = list[i] ^ list[index];
+      }
+      index++;
+    }
+  }
+  if (list[index - 1] !== list[pivot]) {
+    list[index - 1] = list[index - 1] ^ list[pivot];
+    list[pivot] = list[index - 1] ^ list[pivot];
+    list[index - 1] = list[index - 1] ^ list[pivot];
+  }
+  return index - 1;
+};
+/**
+ * @description: Continuously partition, set the reference value
+ * @param {Array} list
+ * @param {number} left
+ * @param {number} right
+ * @return {Array}
+ */
+const combine = (list: number[], left: number, right: number) => {
+  if (left < right) {
+    const partitionIndex: number = partition(list, left, right);
+    combine(list, partitionIndex + 1, right);
+    combine(list, left, partitionIndex - 1);
+  }
+  return list;
+};
+/**
+ * @description: Quick sort
+ * @param {Array} list
+ * @return {Array}
+ */
+const quick = (list: number[] = []): number[] => {
+  const size = list.length;
+  return combine(list, 0, size - 1);
+};
`,9)]))}const o=a(k,[["render",l]]);export{F as __pageData,o as default}; diff --git a/assets/src_article_sort_quick_index.md.tGhXdyib.lean.js b/assets/src_article_sort_quick_index.md.tGhXdyib.lean.js new file mode 100644 index 0000000000..9f12db7dfa --- /dev/null +++ b/assets/src_article_sort_quick_index.md.tGhXdyib.lean.js @@ -0,0 +1,51 @@ +import{_ as i}from"./chunks/quick.WcLzRUPH.js";import{_ as a,o as n,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"Quick Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/quick/index.md","filePath":"src/article/sort/quick/index.md","lastUpdated":1726550590000}'),k={name:"src/article/sort/quick/index.md"};function l(p,s,e,r,E,d){return n(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

Quick Sort

The basic idea of quick sorting is that the records to be sorted are separated into two independent parts through one sort. The keywords of one part of the records are smaller than those of the other part. Then the two parts of the records can be sorted separately to achieve the entire sequence.

Algorithm description

Quicksort uses divide-and-conquer to divide a list into two sub-lists. The specific algorithm is described as follows:

  • Picking out an element from the sequence, called a "pivot";
  • Reorder the sequence so that all elements smaller than the base value are placed in front of the base value and all elements larger than the base value are placed behind the base value (the same number can go to either side). After the partition exits, the benchmark is in the middle of the sequence. This is called a partition operation;
  • Recursively sorts subsequences of elements less than the base value and subsequences of elements greater than the base value.

GIF presentation

Quick Sort

Code demo

ts
/**
+ * @description: Sets the base value pivot
+ * @param {Array} list
+ * @param {number} left
+ * @param {number} right
+ * @return {number} index
+ */
+const partition = (list: number[] = [], left: number, right: number) => {
+  const pivot = left;
+  let index = pivot + 1;
+  for (let i = index; i <= right; i++) {
+    if (list[i] < list[pivot]) {
+      if (list[i] !== list[index]) {
+        list[i] = list[i] ^ list[index];
+        list[index] = list[i] ^ list[index];
+        list[i] = list[i] ^ list[index];
+      }
+      index++;
+    }
+  }
+  if (list[index - 1] !== list[pivot]) {
+    list[index - 1] = list[index - 1] ^ list[pivot];
+    list[pivot] = list[index - 1] ^ list[pivot];
+    list[index - 1] = list[index - 1] ^ list[pivot];
+  }
+  return index - 1;
+};
+/**
+ * @description: Continuously partition, set the reference value
+ * @param {Array} list
+ * @param {number} left
+ * @param {number} right
+ * @return {Array}
+ */
+const combine = (list: number[], left: number, right: number) => {
+  if (left < right) {
+    const partitionIndex: number = partition(list, left, right);
+    combine(list, partitionIndex + 1, right);
+    combine(list, left, partitionIndex - 1);
+  }
+  return list;
+};
+/**
+ * @description: Quick sort
+ * @param {Array} list
+ * @return {Array}
+ */
+const quick = (list: number[] = []): number[] => {
+  const size = list.length;
+  return combine(list, 0, size - 1);
+};
`,9)]))}const o=a(k,[["render",l]]);export{F as __pageData,o as default}; diff --git a/assets/src_article_sort_radix_index.md.hf3O4ngq.js b/assets/src_article_sort_radix_index.md.hf3O4ngq.js new file mode 100644 index 0000000000..b6558c21f3 --- /dev/null +++ b/assets/src_article_sort_radix_index.md.hf3O4ngq.js @@ -0,0 +1,36 @@ +import{_ as i}from"./chunks/radix.CHOmrmB0.js";import{_ as a,o as t,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"Radix Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/radix/index.md","filePath":"src/article/sort/radix/index.md","lastUpdated":1726550590000}'),k={name:"src/article/sort/radix/index.md"};function l(p,s,e,r,E,d){return t(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h('

Radix Sort

Radix sort is sorted by the lowest order first, and then collected; Then sort by high order, and then collect; And so on until you reach the top. Sometimes properties are prioritized, first by low priority and then by high priority. The final order is that the higher priority comes first and the lower priority comes first if the higher priority is the same. Bucket sort extension, similar to specifying bucket sort by bit, but can take advantage of the count sort for a small range of numbers.

Algorithm description

  • Get the largest number in the array, and get the number of bits;
  • arr is the original array, and each bit is taken from the lowest point to form radix array.
  • radix was sorted by counting (taking advantage of the feature that counting sort is suitable for a small range of numbers);

GIF presentation

Radix Sort

Code demo

ts
const getMax = (list: Array<number>) => {
+  let max = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+const getDigit = (num: number) => {
+  let digit = 1;
+  while (num >= 1) {
+    digit++;
+    num = num / 10;
+  }
+  return digit;
+};
+/**
+ * @description: Radix Sort
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const radix = (list: Array<number>, maxDigit?: number): Array<number> => {
+  if (list.length === 0) return list;
+  if (!maxDigit) maxDigit = getDigit(getMax(list));
+  const buckets = new Array(maxDigit).fill(0).map(() => new Array(0));
+  for (let j = 0; j < list.length; j++) {
+    const digit = getDigit(list[j]);
+    buckets[digit - 1].push(list[j]);
+  }
+  list = [];
+  for (let i = 0; i < buckets.length; i++) {
+    list = list.concat(count(buckets[i]));
+  }
+  return list;
+};

Algorithm analysis

Radix sort is based on distributive sort, so it is stable. But the performance of radix sort is slightly worse than bucket sort, each keyword bucket allocation requires O(n) time complexity, and after allocation to get a new keyword sequence requires O(n) time complexity. If the data to be sorted can be divided into d keywords, the time complexity of radix sort will be O(d*2n), of course, d is far less than n, so it is basically linear level.

The spatial complexity of radix sort is O(n+k), where k is the number of buckets. Generally speaking, n> > k, so you need about n extra Spaces.

`,11)]))}const F=a(k,[["render",l]]);export{o as __pageData,F as default}; diff --git a/assets/src_article_sort_radix_index.md.hf3O4ngq.lean.js b/assets/src_article_sort_radix_index.md.hf3O4ngq.lean.js new file mode 100644 index 0000000000..b6558c21f3 --- /dev/null +++ b/assets/src_article_sort_radix_index.md.hf3O4ngq.lean.js @@ -0,0 +1,36 @@ +import{_ as i}from"./chunks/radix.CHOmrmB0.js";import{_ as a,o as t,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"Radix Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/radix/index.md","filePath":"src/article/sort/radix/index.md","lastUpdated":1726550590000}'),k={name:"src/article/sort/radix/index.md"};function l(p,s,e,r,E,d){return t(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h('

Radix Sort

Radix sort is sorted by the lowest order first, and then collected; Then sort by high order, and then collect; And so on until you reach the top. Sometimes properties are prioritized, first by low priority and then by high priority. The final order is that the higher priority comes first and the lower priority comes first if the higher priority is the same. Bucket sort extension, similar to specifying bucket sort by bit, but can take advantage of the count sort for a small range of numbers.

Algorithm description

  • Get the largest number in the array, and get the number of bits;
  • arr is the original array, and each bit is taken from the lowest point to form radix array.
  • radix was sorted by counting (taking advantage of the feature that counting sort is suitable for a small range of numbers);

GIF presentation

Radix Sort

Code demo

ts
const getMax = (list: Array<number>) => {
+  let max = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+const getDigit = (num: number) => {
+  let digit = 1;
+  while (num >= 1) {
+    digit++;
+    num = num / 10;
+  }
+  return digit;
+};
+/**
+ * @description: Radix Sort
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const radix = (list: Array<number>, maxDigit?: number): Array<number> => {
+  if (list.length === 0) return list;
+  if (!maxDigit) maxDigit = getDigit(getMax(list));
+  const buckets = new Array(maxDigit).fill(0).map(() => new Array(0));
+  for (let j = 0; j < list.length; j++) {
+    const digit = getDigit(list[j]);
+    buckets[digit - 1].push(list[j]);
+  }
+  list = [];
+  for (let i = 0; i < buckets.length; i++) {
+    list = list.concat(count(buckets[i]));
+  }
+  return list;
+};

Algorithm analysis

Radix sort is based on distributive sort, so it is stable. But the performance of radix sort is slightly worse than bucket sort, each keyword bucket allocation requires O(n) time complexity, and after allocation to get a new keyword sequence requires O(n) time complexity. If the data to be sorted can be divided into d keywords, the time complexity of radix sort will be O(d*2n), of course, d is far less than n, so it is basically linear level.

The spatial complexity of radix sort is O(n+k), where k is the number of buckets. Generally speaking, n> > k, so you need about n extra Spaces.

`,11)]))}const F=a(k,[["render",l]]);export{o as __pageData,F as default}; diff --git a/assets/src_article_sort_select_index.md.BmIakYmF.js b/assets/src_article_sort_select_index.md.BmIakYmF.js new file mode 100644 index 0000000000..e7f7e247ab --- /dev/null +++ b/assets/src_article_sort_select_index.md.BmIakYmF.js @@ -0,0 +1,17 @@ +import{_ as i}from"./chunks/select.BGReufCV.js";import{_ as a,o as t,c as n,a3 as e}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"Selection Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/select/index.md","filePath":"src/article/sort/select/index.md","lastUpdated":1726550590000}'),h={name:"src/article/sort/select/index.md"};function l(k,s,r,p,d,o){return t(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[e('

Selection Sort

Select-sort is a simple and intuitive sorting algorithm. It works by first finding the smallest (large) element in the unsorted sequence and storing it at the beginning of the sorted sequence, then continuing to find the smallest (large) element from the remaining unsorted elements and placing it at the end of the sorted sequence. And so on until all the elements are sorted.

Algorithm description

Ordering results can be obtained by direct selection sorting of n records through n-1 direct selection sorting. The specific algorithm is described as follows:

  • Initial state: disordered region is R[1..n], ordered region is empty;
  • i sort (i=1,2,3... n-1) At the beginning, the current ordered and disordered regions are R[1..i-1] and R(i.. n). The run sort selects the record R[k] with the smallest keyword from the current unordered area and swaps it with the first record R in the unordered area, so that R[1..i] and R[i+1..n) become a new ordered area with 1 more records and a new unordered area with 1 less records, respectively.
  • n-1 is done. The array is ordered.

GIF presentation

Selection Sort

Code demo

js
const select = (list: number[]): number[] => {
+  const size = list.length;
+  for (let i = 0; i < size; i++) {
+    let minIndex = i;
+    for (let j = i + 1; j < size; j++) {
+      if (list[minIndex] >= list[j]) {
+        minIndex = j;
+      }
+    }
+    if (list[i] !== list[minIndex]) {
+      list[i] = list[i] ^ list[minIndex];
+      list[minIndex] = list[i] ^ list[minIndex];
+      list[i] = list[i] ^ list[minIndex];
+    }
+  }
+  return list;
+};

Algorithm analysis

One of the most stable sorting algorithms, because whatever data goes in is O(n2) time complexity, so when using it, the smaller the data size, the better. The only benefit may be that it doesn't take up extra memory space. In theory, selection sorting may also be the most common sorting method that people think of.

`,11)]))}const y=a(h,[["render",l]]);export{c as __pageData,y as default}; diff --git a/assets/src_article_sort_select_index.md.BmIakYmF.lean.js b/assets/src_article_sort_select_index.md.BmIakYmF.lean.js new file mode 100644 index 0000000000..e7f7e247ab --- /dev/null +++ b/assets/src_article_sort_select_index.md.BmIakYmF.lean.js @@ -0,0 +1,17 @@ +import{_ as i}from"./chunks/select.BGReufCV.js";import{_ as a,o as t,c as n,a3 as e}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"Selection Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/select/index.md","filePath":"src/article/sort/select/index.md","lastUpdated":1726550590000}'),h={name:"src/article/sort/select/index.md"};function l(k,s,r,p,d,o){return t(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[e('

Selection Sort

Select-sort is a simple and intuitive sorting algorithm. It works by first finding the smallest (large) element in the unsorted sequence and storing it at the beginning of the sorted sequence, then continuing to find the smallest (large) element from the remaining unsorted elements and placing it at the end of the sorted sequence. And so on until all the elements are sorted.

Algorithm description

Ordering results can be obtained by direct selection sorting of n records through n-1 direct selection sorting. The specific algorithm is described as follows:

  • Initial state: disordered region is R[1..n], ordered region is empty;
  • i sort (i=1,2,3... n-1) At the beginning, the current ordered and disordered regions are R[1..i-1] and R(i.. n). The run sort selects the record R[k] with the smallest keyword from the current unordered area and swaps it with the first record R in the unordered area, so that R[1..i] and R[i+1..n) become a new ordered area with 1 more records and a new unordered area with 1 less records, respectively.
  • n-1 is done. The array is ordered.

GIF presentation

Selection Sort

Code demo

js
const select = (list: number[]): number[] => {
+  const size = list.length;
+  for (let i = 0; i < size; i++) {
+    let minIndex = i;
+    for (let j = i + 1; j < size; j++) {
+      if (list[minIndex] >= list[j]) {
+        minIndex = j;
+      }
+    }
+    if (list[i] !== list[minIndex]) {
+      list[i] = list[i] ^ list[minIndex];
+      list[minIndex] = list[i] ^ list[minIndex];
+      list[i] = list[i] ^ list[minIndex];
+    }
+  }
+  return list;
+};

Algorithm analysis

One of the most stable sorting algorithms, because whatever data goes in is O(n2) time complexity, so when using it, the smaller the data size, the better. The only benefit may be that it doesn't take up extra memory space. In theory, selection sorting may also be the most common sorting method that people think of.

`,11)]))}const y=a(h,[["render",l]]);export{c as __pageData,y as default}; diff --git a/assets/src_article_sort_shell_index.md.BefIpHA6.js b/assets/src_article_sort_shell_index.md.BefIpHA6.js new file mode 100644 index 0000000000..b23feb7728 --- /dev/null +++ b/assets/src_article_sort_shell_index.md.BefIpHA6.js @@ -0,0 +1,20 @@ +import{_ as i}from"./chunks/shell.CGEkKxrp.js";import{_ as a,o as n,c as e,a3 as t}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"Shell Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/shell/index.md","filePath":"src/article/sort/shell/index.md","lastUpdated":1726550590000}'),l={name:"src/article/sort/shell/index.md"};function h(p,s,k,r,d,o){return n(),e("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

Shell Sort

Shell was invented in 1959, and the first breakthrough O(n2) sorting algorithm was an improved version of simple insertion sorting. It differs from insertion sort in that it gives preference to more distant elements. Hill sort is also called reduced increment sort.

Algorithm description

First, the whole record sequence to be sorted is divided into several sub-sequences for direct insertion sorting. The specific algorithm is described as follows:

  • Select an incremental sequence t1, t2,... tk, wherein ti> tj, tk=1;
  • According to the number of incremental sequences k, the sequence is sorted by k passes.
  • For each sequence, according to the corresponding increment ti, the sequence to be sorted is divided into several sub-sequences with length m, and each sub-table is sorted by direct insertion. When the increment factor is only 1, the entire sequence is treated as a table, and the length of the table is the length of the entire sequence.

GIF presentation

Shell Sort

Code implementation

js
/**
+ * @description: Hill sort is an improved version of simple insertion sort. It differs from insertion sort in that it gives preference to more distant elements. Hill sort is also called reduced increment sort.
+ * @param {Array} list
+ * @return {Array}
+ */
+const shell = (list: number[]): number[] => {
+  const size = list.length;
+  for (let gap = size >> 1; gap > 0; gap >>= 1) {
+    for (let i = gap; i < size; i += gap) {
+      const current = list[i];
+      let preIndex = i - gap;
+      while (preIndex >= 0 && list[preIndex] > current) {
+        list[preIndex + gap] = list[preIndex];
+        preIndex -= gap;
+      }
+      list[preIndex + gap] = current;
+    }
+  }
+  return list;
+};

Algorithm analysis

The core of Hill sort is the setting of interval sequence. The interval sequence can be set in advance, and the interval sequence can be defined dynamically. The algorithm for dynamically defining interval sequences was developed by Robert Sedgewick, co-author of Algorithms (4th Edition).

`,11)]))}const y=a(l,[["render",h]]);export{c as __pageData,y as default}; diff --git a/assets/src_article_sort_shell_index.md.BefIpHA6.lean.js b/assets/src_article_sort_shell_index.md.BefIpHA6.lean.js new file mode 100644 index 0000000000..b23feb7728 --- /dev/null +++ b/assets/src_article_sort_shell_index.md.BefIpHA6.lean.js @@ -0,0 +1,20 @@ +import{_ as i}from"./chunks/shell.CGEkKxrp.js";import{_ as a,o as n,c as e,a3 as t}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"Shell Sort","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/sort/shell/index.md","filePath":"src/article/sort/shell/index.md","lastUpdated":1726550590000}'),l={name:"src/article/sort/shell/index.md"};function h(p,s,k,r,d,o){return n(),e("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

Shell Sort

Shell was invented in 1959, and the first breakthrough O(n2) sorting algorithm was an improved version of simple insertion sorting. It differs from insertion sort in that it gives preference to more distant elements. Hill sort is also called reduced increment sort.

Algorithm description

First, the whole record sequence to be sorted is divided into several sub-sequences for direct insertion sorting. The specific algorithm is described as follows:

  • Select an incremental sequence t1, t2,... tk, wherein ti> tj, tk=1;
  • According to the number of incremental sequences k, the sequence is sorted by k passes.
  • For each sequence, according to the corresponding increment ti, the sequence to be sorted is divided into several sub-sequences with length m, and each sub-table is sorted by direct insertion. When the increment factor is only 1, the entire sequence is treated as a table, and the length of the table is the length of the entire sequence.

GIF presentation

Shell Sort

Code implementation

js
/**
+ * @description: Hill sort is an improved version of simple insertion sort. It differs from insertion sort in that it gives preference to more distant elements. Hill sort is also called reduced increment sort.
+ * @param {Array} list
+ * @return {Array}
+ */
+const shell = (list: number[]): number[] => {
+  const size = list.length;
+  for (let gap = size >> 1; gap > 0; gap >>= 1) {
+    for (let i = gap; i < size; i += gap) {
+      const current = list[i];
+      let preIndex = i - gap;
+      while (preIndex >= 0 && list[preIndex] > current) {
+        list[preIndex + gap] = list[preIndex];
+        preIndex -= gap;
+      }
+      list[preIndex + gap] = current;
+    }
+  }
+  return list;
+};

Algorithm analysis

The core of Hill sort is the setting of interval sequence. The interval sequence can be set in advance, and the interval sequence can be defined dynamically. The algorithm for dynamically defining interval sequences was developed by Robert Sedgewick, co-author of Algorithms (4th Edition).

`,11)]))}const y=a(l,[["render",h]]);export{c as __pageData,y as default}; diff --git a/assets/src_article_typescript_calculate.md.CaDt8dND.js b/assets/src_article_typescript_calculate.md.CaDt8dND.js new file mode 100644 index 0000000000..f338d3bd15 --- /dev/null +++ b/assets/src_article_typescript_calculate.md.CaDt8dND.js @@ -0,0 +1,31 @@ +import{_ as i,o as a,c as h,a3 as n}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"数组长度做计数","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/typescript/calculate.md","filePath":"src/article/typescript/calculate.md","lastUpdated":1726550590000}'),k={name:"src/article/typescript/calculate.md"};function t(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

数组长度做计数

类型系统不是图灵完备,各种逻辑都能写么,但好像没发现数值相关的逻辑。

没错,数值相关的逻辑比较绕,被我单独摘了出来,就是这节要讲的内容。

这是类型体操的第四个套路:数组长度做计数。

TypeScript 类型系统没有加减乘除运算符,怎么做数值运算呢?

不知道大家有没有注意到数组类型取 length 就是数值。

比如:

ts
type num1 = [unknown]['length'];
+// type num1 = 1
+type num2 = [unknown, unknown]['length'];
+// type num1 = 2
+type num3 = [unknown, unknown, unknown]['length'];
+// type num1 = 3

而数组类型我们是能构造出来的,那么通过构造不同长度的数组然后取 length,不就是数值的运算么?

TypeScript 类型系统中没有加减乘除运算符,但是可以通过构造不同的数组然后取 length 的方式来完成数值计算,把数值的加减乘除转化为对数组的提取和构造。

(严格来说构造的是元组,大家知道数组和元组的区别就行)

这点可以说是类型体操中最麻烦的一个点,需要思维做一些转换,绕过这个弯来。

下面我们就来做一些真实的案例来掌握它吧。

数组长度实现加减乘除

Add

我们知道了数值计算要转换为对数组类型的操作,那么加法的实现很容易想到:

构造两个数组,然后合并成一个,取 length。

比如 3 + 2,就是构造一个长度为 3 的数组类型,再构造一个长度为 2 的数组类型,然后合并成一个数组,取 length。

构造多长的数组是不确定的,需要递归构造,这个我们实现过:

ts
type BuildArray<Length extends number, Ele = unknown, Arr extends unknown[] = []> = Arr['length'] extends Length
+  ? Arr
+  : BuildArray<Length, Ele, [...Arr, Ele]>;

类型参数 Length 是要构造的数组的长度。类型参数 Ele 是数组元素,默认为 unknown。类型参数 Arr 为构造出的数组,默认是 []。

如果 Arr 的长度到达了 Length,就返回构造出的 Arr,否则继续递归构造。

构造数组实现了,那么基于它就能实现加法:

ts
type Add<Num1 extends number, Num2 extends number> = [...BuildArray<Num1>, ...BuildArray<Num2>]['length'];

我们拿大一点的数测试下:

ts
type AddResult = Add<32, 25>;
+// type AddResult = 57

就这样,我们通过构造一定长度的数组取 length 的方式实现了加法运算。

Subtract

加法是构造数组,那减法怎么做呢?

减法是从数值中去掉一部分,很容易想到可以通过数组类型的提取来做。

比如 3 是 [unknown, unknown, unknown] 的数组类型,提取出 2 个元素之后,剩下的数组再取 length 就是 1。

所以减法的实现是这样的:

ts
type Subtract<Num1 extends number, Num2 extends number> =
+  BuildArray<Num1> extends [...arr1: BuildArray<Num2>, ...arr2: infer Rest] ? Rest['length'] : never;

类型参数 Num1、Num2 分别是被减数和减数,通过 extends 约束为 number。

构造 Num1 长度的数组,通过模式匹配提取出 Num2 长度个元素,剩下的放到 infer 声明的局部变量 Rest 里。

取 Rest 的长度返回,就是减法的结果。

就这样,我们通过数组类型的提取实现了减法运算。

Multiply

我们把加法转换为了数组构造,把减法转换为了数组提取。那乘法怎么做呢?

为了解释乘法,我去翻了下小学教材,找到了这样一张图:

1 乘以 5 就相当于 1 + 1 + 1 + 1 + 1,也就是说乘法就是多个加法结果的累加。

那么我们在加法的基础上,多加一个参数来传递中间结果的数组,算完之后再取一次 length 就能实现乘法:

ts
type Multiplication<Num1 extends number, Num2 extends number, ResultArr extends unknown[] = []> = Num2 extends 0
+  ? ResultArr['length']
+  : Multiplication<Num1, Subtract<Num2, 1>, [...BuildArray<Num1>, ...ResultArr]>;

类型参数 Num1 和 Num2 分别是被加数和加数。

因为乘法是多个加法结果的累加,我们加了一个类型参数 ResultArr 来保存中间结果,默认值是 [],相当于从 0 开始加。

每加一次就把 Num2 减一,直到 Num2 为 0,就代表加完了。

加的过程就是往 ResultArr 数组中放 Num1 个元素。

这样递归的进行累加,也就是递归的往 ResultArr 中放元素。

最后取 ResultArr 的 length 就是乘法的结果。

就这样,我们通过递归的累加实现了乘法。

Divide

乘法是递归的累加,那除法不就是递归的累减么?

我再去翻了下小学教材,找到了这样一张图:

我们有 9 个苹果,分给美羊羊 3 个,分给懒羊羊 3 个,分给沸羊羊 3 个,最后剩下 0 个。所以 9 / 3 = 3。

所以,除法的实现就是被减数不断减去减数,直到减为 0,记录减了几次就是结果。

也就是这样的:

ts
type Divide<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends 0
+  ? CountArr['length']
+  : Divide<Subtract<Num1, Num2>, Num2, [unknown, ...CountArr]>;

类型参数 Num1 和 Num2 分别是被减数和减数。

类型参数 CountArr 是用来记录减了几次的累加数组。

如果 Num1 减到了 0,那么这时候减了几次就是除法结果,也就是 CountArr['length']。

否则继续递归的减,让 Num1 减去 Num2,并且 CountArr 多加一个元素代表又减了一次。

这样就实现了除法:

就这样,我们通过递归的累减并记录减了几次实现了除法。

做完了加减乘除,我们再来做一些别的数值计算的类型体操。

数组长度实现计数

StrLen

数组长度可以取 length 来得到,但是字符串类型不能取 length,所以我们来实现一个求字符串长度的高级类型。

字符串长度不确定,明显要用递归。每次取一个并计数,直到取完,就是字符串长度。

ts
type StrLen<Str extends string, CountArr extends unknown[] = []> = Str extends \`\${string}\${infer Rest}\`
+  ? StrLen<Rest, [...CountArr, unknown]>
+  : CountArr['length'];

类型参数 Str 是待处理的字符串。类型参数 CountArr 是做计数的数组,默认值 [] 代表从 0 开始。

每次通过模式匹配提取去掉一个字符之后的剩余字符串,并且往计数数组里多放入一个元素。递归进行取字符和计数。

如果模式匹配不满足,代表计数结束,返回计数数组的长度 CountArr['length']。

这样就能求出字符串长度:

GreaterThan

能够做计数了,那也就能做两个数值的比较。

我们往一个数组类型中不断放入元素取长度,如果先到了 A,那就是 B 大,否则是 A 大:

ts
type GreaterThan<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends Num2
+  ? false
+  : CountArr['length'] extends Num2
+    ? true
+    : CountArr['length'] extends Num1
+      ? false
+      : GreaterThan<Num1, Num2, [...CountArr, unknown]>;

类型参数 Num1 和 Num2 是待比较的两个数。

类型参数 CountArr 是计数用的,会不断累加,默认值是 [] 代表从 0 开始。

如果 Num1 extends Num2 成立,代表相等,直接返回 false。

否则判断计数数组的长度,如果先到了 Num2,那么就是 Num1 大,返回 true。

反之,如果先到了 Num1,那么就是 Num2 大,返回 false。

如果都没到就往计数数组 CountArr 中放入一个元素,继续递归。

这样就实现了数值比较。

当 3 和 4 比较时:

Fibonacci

谈到了数值运算,就不得不提起经典的 Fibonacci 数列的计算。

Fibonacci 数列是 1、1、2、3、5、8、13、21、34、…… 这样的数列,有当前的数是前两个数的和的规律。

F(0) = 1, F(1) = 1, F(n) = F(n - 1) + F(n - 2)(n ≥ 2, n ∈ N*)

也就是递归的加法,在 TypeScript 类型编程里用构造数组来实现这种加法:

ts
type FibonacciLoop<
+  PrevArr extends unknown[],
+  CurrentArr extends unknown[],
+  IndexArr extends unknown[] = [],
+  Num extends number = 1,
+> = IndexArr['length'] extends Num
+  ? CurrentArr['length']
+  : FibonacciLoop<CurrentArr, [...PrevArr, ...CurrentArr], [...IndexArr, unknown], Num>;
+
+type Fibonacci<Num extends number> = FibonacciLoop<[1], [], [], Num>;

类型参数 PrevArr 是代表之前的累加值的数组。类型参数 CurrentArr 是代表当前数值的数组。

类型参数 IndexArr 用于记录 index,每次递归加一,默认值是 [],代表从 0 开始。

类型参数 Num 代表求数列的第几个数。

判断当前 index 也就是 IndexArr['length'] 是否到了 Num,到了就返回当前的数值 CurrentArr['length']。

否则求出当前 index 对应的数值,用之前的数加上当前的数 [...PrevArr, ... CurrentArr]。

然后继续递归,index + 1,也就是 [...IndexArr, unknown]。

这就是递归计算 Fibinacci 数列的数的过程。

可以正确的算出第 8 个数是 21:

`,99)]))}const F=i(k,[["render",t]]);export{g as __pageData,F as default}; diff --git a/assets/src_article_typescript_calculate.md.CaDt8dND.lean.js b/assets/src_article_typescript_calculate.md.CaDt8dND.lean.js new file mode 100644 index 0000000000..f338d3bd15 --- /dev/null +++ b/assets/src_article_typescript_calculate.md.CaDt8dND.lean.js @@ -0,0 +1,31 @@ +import{_ as i,o as a,c as h,a3 as n}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"数组长度做计数","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/typescript/calculate.md","filePath":"src/article/typescript/calculate.md","lastUpdated":1726550590000}'),k={name:"src/article/typescript/calculate.md"};function t(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

数组长度做计数

类型系统不是图灵完备,各种逻辑都能写么,但好像没发现数值相关的逻辑。

没错,数值相关的逻辑比较绕,被我单独摘了出来,就是这节要讲的内容。

这是类型体操的第四个套路:数组长度做计数。

TypeScript 类型系统没有加减乘除运算符,怎么做数值运算呢?

不知道大家有没有注意到数组类型取 length 就是数值。

比如:

ts
type num1 = [unknown]['length'];
+// type num1 = 1
+type num2 = [unknown, unknown]['length'];
+// type num1 = 2
+type num3 = [unknown, unknown, unknown]['length'];
+// type num1 = 3

而数组类型我们是能构造出来的,那么通过构造不同长度的数组然后取 length,不就是数值的运算么?

TypeScript 类型系统中没有加减乘除运算符,但是可以通过构造不同的数组然后取 length 的方式来完成数值计算,把数值的加减乘除转化为对数组的提取和构造。

(严格来说构造的是元组,大家知道数组和元组的区别就行)

这点可以说是类型体操中最麻烦的一个点,需要思维做一些转换,绕过这个弯来。

下面我们就来做一些真实的案例来掌握它吧。

数组长度实现加减乘除

Add

我们知道了数值计算要转换为对数组类型的操作,那么加法的实现很容易想到:

构造两个数组,然后合并成一个,取 length。

比如 3 + 2,就是构造一个长度为 3 的数组类型,再构造一个长度为 2 的数组类型,然后合并成一个数组,取 length。

构造多长的数组是不确定的,需要递归构造,这个我们实现过:

ts
type BuildArray<Length extends number, Ele = unknown, Arr extends unknown[] = []> = Arr['length'] extends Length
+  ? Arr
+  : BuildArray<Length, Ele, [...Arr, Ele]>;

类型参数 Length 是要构造的数组的长度。类型参数 Ele 是数组元素,默认为 unknown。类型参数 Arr 为构造出的数组,默认是 []。

如果 Arr 的长度到达了 Length,就返回构造出的 Arr,否则继续递归构造。

构造数组实现了,那么基于它就能实现加法:

ts
type Add<Num1 extends number, Num2 extends number> = [...BuildArray<Num1>, ...BuildArray<Num2>]['length'];

我们拿大一点的数测试下:

ts
type AddResult = Add<32, 25>;
+// type AddResult = 57

就这样,我们通过构造一定长度的数组取 length 的方式实现了加法运算。

Subtract

加法是构造数组,那减法怎么做呢?

减法是从数值中去掉一部分,很容易想到可以通过数组类型的提取来做。

比如 3 是 [unknown, unknown, unknown] 的数组类型,提取出 2 个元素之后,剩下的数组再取 length 就是 1。

所以减法的实现是这样的:

ts
type Subtract<Num1 extends number, Num2 extends number> =
+  BuildArray<Num1> extends [...arr1: BuildArray<Num2>, ...arr2: infer Rest] ? Rest['length'] : never;

类型参数 Num1、Num2 分别是被减数和减数,通过 extends 约束为 number。

构造 Num1 长度的数组,通过模式匹配提取出 Num2 长度个元素,剩下的放到 infer 声明的局部变量 Rest 里。

取 Rest 的长度返回,就是减法的结果。

就这样,我们通过数组类型的提取实现了减法运算。

Multiply

我们把加法转换为了数组构造,把减法转换为了数组提取。那乘法怎么做呢?

为了解释乘法,我去翻了下小学教材,找到了这样一张图:

1 乘以 5 就相当于 1 + 1 + 1 + 1 + 1,也就是说乘法就是多个加法结果的累加。

那么我们在加法的基础上,多加一个参数来传递中间结果的数组,算完之后再取一次 length 就能实现乘法:

ts
type Multiplication<Num1 extends number, Num2 extends number, ResultArr extends unknown[] = []> = Num2 extends 0
+  ? ResultArr['length']
+  : Multiplication<Num1, Subtract<Num2, 1>, [...BuildArray<Num1>, ...ResultArr]>;

类型参数 Num1 和 Num2 分别是被加数和加数。

因为乘法是多个加法结果的累加,我们加了一个类型参数 ResultArr 来保存中间结果,默认值是 [],相当于从 0 开始加。

每加一次就把 Num2 减一,直到 Num2 为 0,就代表加完了。

加的过程就是往 ResultArr 数组中放 Num1 个元素。

这样递归的进行累加,也就是递归的往 ResultArr 中放元素。

最后取 ResultArr 的 length 就是乘法的结果。

就这样,我们通过递归的累加实现了乘法。

Divide

乘法是递归的累加,那除法不就是递归的累减么?

我再去翻了下小学教材,找到了这样一张图:

我们有 9 个苹果,分给美羊羊 3 个,分给懒羊羊 3 个,分给沸羊羊 3 个,最后剩下 0 个。所以 9 / 3 = 3。

所以,除法的实现就是被减数不断减去减数,直到减为 0,记录减了几次就是结果。

也就是这样的:

ts
type Divide<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends 0
+  ? CountArr['length']
+  : Divide<Subtract<Num1, Num2>, Num2, [unknown, ...CountArr]>;

类型参数 Num1 和 Num2 分别是被减数和减数。

类型参数 CountArr 是用来记录减了几次的累加数组。

如果 Num1 减到了 0,那么这时候减了几次就是除法结果,也就是 CountArr['length']。

否则继续递归的减,让 Num1 减去 Num2,并且 CountArr 多加一个元素代表又减了一次。

这样就实现了除法:

就这样,我们通过递归的累减并记录减了几次实现了除法。

做完了加减乘除,我们再来做一些别的数值计算的类型体操。

数组长度实现计数

StrLen

数组长度可以取 length 来得到,但是字符串类型不能取 length,所以我们来实现一个求字符串长度的高级类型。

字符串长度不确定,明显要用递归。每次取一个并计数,直到取完,就是字符串长度。

ts
type StrLen<Str extends string, CountArr extends unknown[] = []> = Str extends \`\${string}\${infer Rest}\`
+  ? StrLen<Rest, [...CountArr, unknown]>
+  : CountArr['length'];

类型参数 Str 是待处理的字符串。类型参数 CountArr 是做计数的数组,默认值 [] 代表从 0 开始。

每次通过模式匹配提取去掉一个字符之后的剩余字符串,并且往计数数组里多放入一个元素。递归进行取字符和计数。

如果模式匹配不满足,代表计数结束,返回计数数组的长度 CountArr['length']。

这样就能求出字符串长度:

GreaterThan

能够做计数了,那也就能做两个数值的比较。

我们往一个数组类型中不断放入元素取长度,如果先到了 A,那就是 B 大,否则是 A 大:

ts
type GreaterThan<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends Num2
+  ? false
+  : CountArr['length'] extends Num2
+    ? true
+    : CountArr['length'] extends Num1
+      ? false
+      : GreaterThan<Num1, Num2, [...CountArr, unknown]>;

类型参数 Num1 和 Num2 是待比较的两个数。

类型参数 CountArr 是计数用的,会不断累加,默认值是 [] 代表从 0 开始。

如果 Num1 extends Num2 成立,代表相等,直接返回 false。

否则判断计数数组的长度,如果先到了 Num2,那么就是 Num1 大,返回 true。

反之,如果先到了 Num1,那么就是 Num2 大,返回 false。

如果都没到就往计数数组 CountArr 中放入一个元素,继续递归。

这样就实现了数值比较。

当 3 和 4 比较时:

Fibonacci

谈到了数值运算,就不得不提起经典的 Fibonacci 数列的计算。

Fibonacci 数列是 1、1、2、3、5、8、13、21、34、…… 这样的数列,有当前的数是前两个数的和的规律。

F(0) = 1, F(1) = 1, F(n) = F(n - 1) + F(n - 2)(n ≥ 2, n ∈ N*)

也就是递归的加法,在 TypeScript 类型编程里用构造数组来实现这种加法:

ts
type FibonacciLoop<
+  PrevArr extends unknown[],
+  CurrentArr extends unknown[],
+  IndexArr extends unknown[] = [],
+  Num extends number = 1,
+> = IndexArr['length'] extends Num
+  ? CurrentArr['length']
+  : FibonacciLoop<CurrentArr, [...PrevArr, ...CurrentArr], [...IndexArr, unknown], Num>;
+
+type Fibonacci<Num extends number> = FibonacciLoop<[1], [], [], Num>;

类型参数 PrevArr 是代表之前的累加值的数组。类型参数 CurrentArr 是代表当前数值的数组。

类型参数 IndexArr 用于记录 index,每次递归加一,默认值是 [],代表从 0 开始。

类型参数 Num 代表求数列的第几个数。

判断当前 index 也就是 IndexArr['length'] 是否到了 Num,到了就返回当前的数值 CurrentArr['length']。

否则求出当前 index 对应的数值,用之前的数加上当前的数 [...PrevArr, ... CurrentArr]。

然后继续递归,index + 1,也就是 [...IndexArr, unknown]。

这就是递归计算 Fibinacci 数列的数的过程。

可以正确的算出第 8 个数是 21:

`,99)]))}const F=i(k,[["render",t]]);export{g as __pageData,F as default}; diff --git a/assets/src_article_typescript_index.md.SzJeg7Vl.js b/assets/src_article_typescript_index.md.SzJeg7Vl.js new file mode 100644 index 0000000000..2bd51dfcdc --- /dev/null +++ b/assets/src_article_typescript_index.md.SzJeg7Vl.js @@ -0,0 +1,156 @@ +import{_ as i,o as a,c as h,a3 as n}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"TypeScript 的类型系统","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/typescript/index.md","filePath":"src/article/typescript/index.md","lastUpdated":1726550590000}'),k={name:"src/article/typescript/index.md"};function p(t,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

TypeScript 的类型系统

一。类型是什么

类型具体点来说就是指 number、boolean、string 等基础类型和 Object、Function 等复合类型,它们是编程语言提供的对不同内容的抽象:

  • 不同类型变量占据的内存大小不同: boolean 类型的变量会分配 4 个字节的内存,而 number 类型的变量则会分配 8 个字节的内存,给变量声明了不同的类型就代表了会占据不同的内存空间。

  • 不同类型变量可做的操作不同: number 类型可以做加减乘除等运算,boolean 就不可以,复合类型中不同类型的对象可用的方法不同,比如 Date 和 RegExp,变量的类型不同代表可以对该变量做的操作就不同。

有了类型,那我们的操作必须和类型相匹配,否则就会报错,这就是类型检查。

如果能保证对某种类型只做该类型允许的操作,这就叫做类型安全。

类型检查可以在运行时做,也可以运行之前的编译期做。这是两种不同的类型,前者叫做动态类型检查,后者叫做静态类型检查。

两种类型检查各有优缺点。动态类型检查 在源码中不保留类型信息,对某个变量赋什么值、做什么操作都是允许的,写代码很灵活。但这也埋下了类型不安全的隐患,比如对 string 做了乘除,对 Date 对象调用了 exec 方法,这些都是运行时才能检查出来的错误。

其中,最常见的错误应该是“null is not an object”、“undefined is not a function”之类的了,写代码时没发现类型不匹配,到了运行的时候才发现,就会有很多这种报错。

所以,动态类型虽然代码写起来简单,但代码中很容易藏着一些类型不匹配的隐患。

静态类型检查则是在源码中保留类型信息,声明变量要指定类型,对变量做的操作要和类型匹配,会有专门的编译器在编译期间做检查。

静态类型给写代码增加了一些难度,因为你除了要考虑代码要表达的逻辑之外,还要考虑类型逻辑:变量是什么类型的、是不是匹配、要不要做类型转换等。

不过,静态类型也消除了类型不安全的隐患,因为在编译期间就做了类型检查,就不会出现对 string 做了乘除,调用了 Date 的 exec 方法这类问题。

所以,静态类型虽然代码写起来要考虑的问题多一些,会复杂一些,但是却消除了代码中潜藏类型不安全问题的可能。

知道了动态类型检查和静态类型检查的区别,我们自然可以得出这样的结论:

动态类型只适合简单的场景,对于大项目却不太合适,因为代码中可能藏着的隐患太多了,万一线上报一个类型不匹配的错误,那可能就是大问题。

而静态类型虽然会增加写代码的成本,但是却能更好的保证代码的健壮性,减少 Bug 率。

所以,大型项目注定会用静态类型语言开发。

二。类型系统的分类

1.简单的类型系统

变量、函数、类等都可以声明类型,编译器会基于声明的类型做类型检查,类型不匹配时会报错。

这是最基础的类型系统,能保证类型安全,但有些死板。

比如一个 add 函数既可以做整数加法、又可以做浮点数加法,却需要声明两个函数:

c
int add(int a, int b) {
+    return a + b;
+}
+
+double add(double a, double b) {
+    return a + b;
+}

这个问题的解决思路很容易想到:如果类型能传参数就好了,传入 int 就是整数加法,传入 double 就是浮点数加法。

所以,就有了第二种类型系统。

2.支持泛型的类型系统

泛型的英文是 Generic Type,通用的类型,它可以代表任何一种类型,也叫做类型参数。

它给类型系统增加了一些灵活性,在整体比较固定,部分变量的类型有变化的情况下,可以减少很多重复代码。

比如上面的 add 函数,有了泛型之后就可以这样写:

java
T add<T>(T a, T b) {
+    return a + b;
+}
+
+add(1,2);
+add(1.111, 2.2222);

声明时把会变化的类型声明成泛型(也就是类型参数),在调用的时候再确定类型。

Java 就是这种类型系统。如果你看过 Java 代码,你会发现泛型用的特别多,这确实是一个很好的增加类型系统灵活性的特性。

但是,这种类型系统的灵活性对于 JavaScript 来说还不够,因为 JavaScript 太过灵活了。

比如,在 Java 里,对象都是由类 new 出来的,你不能凭空创建对象,但是 JavaScript 却可以,它支持对象字面量。

那如果是一个返回对象某个属性值的函数,类型该怎么写呢?

ts
function getPropValue<T>(obj: T, key): key对应的属性值类型 {
+  return obj[key];
+}

好像拿到了 T,也不能拿到它的属性和属性值,如果能对类型参数 T 做一些逻辑处理就好了。

所以,就有了第三种类型系统。

3.支持类型编程的类型系统

在 Java 里面,拿到了对象的类型就能找到它的类,进一步拿到各种信息,所以类型系统支持泛型就足够了。

但是在 JavaScript 里面,对象可以字面量的方式创建,还可以灵活的增删属性,拿到对象并不能确定什么,所以要支持对传入的类型参数做进一步的处理。

对传入的类型参数(泛型)做各种逻辑运算,产生新的类型,这就是类型编程。

比如上面那个 getProps 的函数,类型可以这样写:

ts
function getPropValue<T extends object, Key extends keyof T>(obj: T, key: Key): T[Key] {
+  return obj[key];
+}

这里的 keyof T、T[Key] 就是对类型参数 T 的类型运算。

TypeScript 的类型系统就是第三种,支持对类型参数做各种逻辑处理,可以写很复杂的类型逻辑。

类型逻辑可以多复杂?

类型逻辑是对类型参数的各种处理,可以实现很多强大的功能:

比如这个 ParseQueryString 的类型:

ts
type res = ParseQueryString<'a=1&b=2&c=3'>;

它可以对传入的字符串的类型参数做解析,返回解析以后的结果。等于

ts
type res = {
+  a: '1';
+  b: '2';
+  c: '3';
+};

如果是 Java 的只支持泛型的类型系统可以做到么?明显不能。但是 TypeScript 的类型系统就可以,因为它可以对泛型(类型参数)做各种逻辑处理。

只不过,这个类型的类型逻辑的代码比较多(下面的 ts 类型暂时看不懂没关系,在顺口溜那节会有详解,这里只是用来直观感受下类型编程的复杂度的,等学完以后大家也能实现这样的复杂高级类型的):

ts
type ParseParam<Param extends string> = Param extends \`\${infer Key}=\${infer Value}\`
+  ? {
+      [K in Key]: Value;
+    }
+  : {};
+
+type MergeValues<One, Other> = One extends Other ? One : Other extends unknown[] ? [One, ...Other] : [One, Other];
+
+type MergeParams<OneParam extends Record<string, any>, OtherParam extends Record<string, any>> = {
+  [Key in keyof OneParam | keyof OtherParam]: Key extends keyof OneParam
+    ? Key extends keyof OtherParam
+      ? MergeValues<OneParam[Key], OtherParam[Key]>
+      : OneParam[Key]
+    : Key extends keyof OtherParam
+      ? OtherParam[Key]
+      : never;
+};
+type ParseQueryString<Str extends string> = Str extends \`\${infer Param}&\${infer Rest}\`
+  ? MergeParams<ParseParam<Param>, ParseQueryString<Rest>>
+  : ParseParam<Str>;

TypeScript 的类型系统是图灵完备的,也就是能描述各种可计算逻辑。简单点来理解就是循环、条件等各种 JS 里面有的语法它都有,JS 能写的逻辑它都能写。

对类型参数的编程是 TypeScript 类型系统最强大的部分,可以实现各种复杂的类型计算逻辑,是它的优点。但同时也被认为是它的缺点,因为除了业务逻辑外还要写很多类型逻辑。

不过,我倒是觉得这种复杂度是不可避免的,因为 JS 本身足够灵活,要准确定义类型那类型系统必然也要设计的足够灵活。

4.类型安全和型变

TypeScript 给 JavaScript 添加了一套静态类型系统,是为了保证类型安全的,也就是保证变量只能赋同类型的值,对象只能访问它有的属性、方法。

比如 number 类型的值不能赋值给 boolean 类型的变量,Date 类型的对象就不能调用 exec 方法。

这是类型检查做的事情,遇到类型安全问题会在编译时报错。

但是这种类型安全的限制也不能太死板,有的时候需要一些变通,比如子类型是可以赋值给父类型的变量的,可以完全当成父类型来使用,也就是“型变(variant)”(类型改变)。

这种“型变”分为两种,一种是子类型可以赋值给父类型,叫做协变(covariant),一种是父类型可以赋值给子类型,叫做逆变(contravariant)。

先来看下协变:

协变(covariant)

对具体成员的输出参数进行一次类型转换,且类型转换的准则是“里氏替换原则”。

其中协变是很好理解的,比如我们有两个 interface:

ts
interface Animal {
+  name: string;
+  age: number;
+}
+
+interface Cat {
+  name: string;
+  age: number;
+  hobbies: string[];
+}

这里 Cat 是 Animal 的子类型,更具体,那么 Cat 类型的变量就可以赋值给 Animal 类型:

ts
let animal: Animal = {
+  name: 'cat',
+  age: 3,
+};
+
+let cat: Cat = {
+  name: 'Tony',
+  age: 5,
+  hobbies: ['run', 'swim'],
+};
+
+animal = cat;

这并不会报错,虽然这俩类型不一样,但是依然是类型安全的。

这种子类型可以赋值给父类型的情况就叫做协变。

为什么要支持协变很容易理解:类型系统支持了父子类型,那如果子类型还不能赋值给父类型,还叫父子类型么?

所以型变是实现类型父子关系必须的,它在保证类型安全的基础上,增加了类型系统的灵活性。

逆变相对难理解一些:

逆变(contravariant)

是对具体成员的输入参数进行一次类型转换,且类型转换的准则是"里氏替换原则"。

我们有这样两个函数:

ts
let printHobbies: (cat: Cat) => void;
+
+printHobbies = (cat) => {
+  console.log(cat.hobbies);
+};
+
+let printName: (animal: Animal) => void;
+
+printName = (animal) => {
+  console.log(animal.name);
+};

printHobbies 的参数 Guang 是 printName 参数 Person 的子类型。

那么问题来了,printName 能赋值给 printHobbies 么?printHobbies 能赋值给 printName 么?

测试一下发现是这样的:

ts
let printHobbies: (cat: Cat) => void;
+
+printHobbies = (cat) => {
+  console.log(cat.hobbies);
+};
+
+let printName: (animal: Animal) => void;
+
+printName = (animal) => {
+  console.log(animal.name);
+};
+
+printHobbies = printName;

printName 的参数 Person 不是 printHobbies 的参数 Guang 的父类型么,为啥能赋值给子类型?

因为这个函数调用的时候是按照 Guang 来约束的类型,但实际上函数只用到了父类型 Person 的属性和方法,当然不会有问题,依然是类型安全的。

这就是逆变,函数的参数有逆变的性质(而返回值是协变的,也就是子类型可以赋值给父类型)。

那反过来呢,如果 printHoobies 赋值给 printName 会发生什么?

因为函数声明的时候是按照 Person 来约束类型,但是调用的时候是按照 Guang 的类型来访问的属性和方法,那自然类型不安全了,所以就会报错。

但是在 ts2.x 之前支持这种赋值,也就是父类型可以赋值给子类型,子类型可以赋值给父类型,既逆变又协变,叫做“双向协变”。

但是这明显是有问题的,不能保证类型安全,所以之后 ts 加了一个编译选项 strictFunctionTypes,设置为 true 就只支持函数参数的逆变,设置为 false 则是双向协变。

我们把 strictFunctionTypes 关掉之后,就会发现两种赋值都可以了。

这样就支持函数参数的双向协变,类型检查不会报错,但不能严格保证类型安全。

开启之后,函数参数就只支持逆变,子类型赋值给父类型就会报错。

再举个逆变的例子,大家觉得下面这样的 ts 代码会报错么:

ts
type Func = (a: string) => void;
+
+const func: Func = (a: 'hello') => undefined;

答案是参数的位置会,返回值的位置不会:

参数的位置是逆变的,也就是被赋值的函数参数要是赋值的函数参数的子类型,而 string 不是 'hello' 的子类型,所以报错了。

返回值的位置是协变的,也就是赋值的函数的返回值是被赋值的函数的返回值的子类型,这里 undefined 是 void 的子类型,所以不报错。

不变(invariant)

逆变和协变都是型变,是针对父子类型而言的,非父子类型自然就不会型变,也就是不变:

非父子类型之间不会发生型变,只要类型不一样就会报错

那类型之间的父子关系是怎么确定的呢,好像也没有看到 extends 的继承?

像 java 里面的类型都是通过 extends 继承的,如果 A extends B,那 A 就是 B 的子类型。这种叫做名义类型系统(nominal type)。

而 ts 里不看这个,只要结构上是一致的,那么就可以确定父子关系,这种叫做结构类型系统(structual type)。

通过结构,更具体的那个是子类型。这里的 Cat 有 Animal 的所有属性,并且还多了一些属性,所以 Cat 是 Animal 的子类型。

注意,这里用的是更具体,而不是更多。

判断联合类型父子关系的时候, 'a' | 'b' 和 'a' | 'b' | 'c' 哪个更具体?

'a' | 'b' 更具体,所以 'a' | 'b' 是 'a' | 'b' | 'c' 的子类型。

三.TypeScript 类型系统

1.支持的类型

静态类型系统的目的是把类型检查从运行时提前到编译时,那 TS 类型系统中肯定要把 JS 的运行时类型拿过来,也就是 number、boolean、string、object、bigint、symbol、undefined、null 这些类型,还有就是它们的包装类型 Number、Boolean、String、Object、Symbol。

这些很容易理解,给 JS 添加静态类型,总没有必要重新造一套基础类型吧,直接复用 JS 的基础类型就行。

复合类型方面,JS 有 class、Array,这些 TypeScript 类型系统也都支持,但是又多加了三种类型:元组(Tuple)、接口(Interface)、枚举(Enum)。

元组

元组(Tuple)就是元素个数和类型固定的数组类型:

ts
type Tuple = [number, string];

接口

接口(Interface)可以描述函数、对象、构造器的结构:

对象:

ts
interface IPerson {
+  name: string;
+  age: number;
+}
+
+class Person implements IPerson {
+  name: string;
+  age: number;
+}
+
+const obj: IPerson = {
+  name: 'guang',
+  age: 18,
+};

函数:

ts
interface SayHello {
+  (name: string): string;
+}
+
+const func: SayHello = (name: string) => {
+  return 'hello,' + name;
+};

构造器:

ts
interface PersonConstructor {
+  new (name: string, age: number): IPerson;
+}
+
+function createPerson(ctor: PersonConstructor): IPerson {
+  return new ctor('guang', 18);
+}

对象类型、class 类型在 TypeScript 里也叫做索引类型,也就是索引了多个元素的类型的意思。对象可以动态添加属性,如果不知道会有什么属性,可以用可索引签名:

ts
interface IPerson {
+  [prop: string]: string | number;
+}
+const obj: IPerson = {};
+obj.name = 'guang';
+obj.age = 18;

总之,接口可以用来描述函数、构造器、索引类型(对象、class、数组)等复合类型。

枚举

枚举(Enum)是一系列值的复合:

ts
enum Transpiler {
+  Babel = 'babel',
+  Postcss = 'postcss',
+  Terser = 'terser',
+  Prettier = 'prettier',
+  TypeScriptCompiler = 'tsc',
+}
+
+const transpiler = Transpiler.TypeScriptCompiler;

此外,TypeScript 还支持字面量类型,也就是类似 1111、'aaaa'、{ a: 1} 这种值也可以做为类型。

其中,字符串的字面量类型有两种,一种是普通的字符串字面量,比如 'aaa',另一种是模版字面量,比如 aaa\${string},它的意思是以 aaa 开头,后面是任意 string 的字符串字面量类型。

所以想要约束以某个字符串开头的字符串字面量类型时可以这样写:

ts
function func(str: \`#\${string}\`) {}
+
+func('aaaa'); // error
+
+func('#aaaa'); // true

还有四种特殊的类型:void、never、any、unknown:

  • never 代表不可达,比如函数抛异常的时候,返回值就是 never。
  • void 代表空,可以是 undefined 或 never。
  • any 是任意类型,任何类型都可以赋值给它,它也可以赋值给任何类型(除了 never)。
  • unknown 是未知类型,任何类型都可以赋值给它,但是它不可以赋值给别的类型。

这些就是 TypeScript 类型系统中的全部类型了,大部分是从 JS 中迁移过来的,比如基础类型、Array、class 等,也添加了一些类型,比如 枚举(enum)、接口(interface)、元组等,还支持了字面量类型和 void、never、any、unknown 的特殊类型。

2.类型的装饰

除了描述类型的结构外,TypeScript 的类型系统还支持描述类型的属性,比如是否可选,是否只读等:

ts
interface IPerson {
+  readonly name: string;
+  age?: number;
+}
+
+type tuple = [string, number?];

3.类型运算

我们知道了 TypeScript 类型系统里有哪些类型,那么可以对这些类型做什么类型运算呢?

条件:extends ?

TypeScript 里的条件判断是 extends ? :,叫做条件类型(Conditional Type)比如:

ts
type res = 1 extends 2 ? true : false; // type res = false

这就是 TypeScript 类型系统里的 if else。

但是,上面这样的逻辑没啥意义,静态的值自己就能算出结果来,为什么要用代码去判断呢?

所以,类型运算逻辑都是用来做一些动态的类型的运算的,也就是对类型参数的运算。

ts
type isTwo<T> = T extends 2 ? true : false;
+
+type res = isTwo<1>; // type res = false
+type res2 = isTwo<2>; // type res = true

这种类型也叫做高级类型。

高级类型的特点是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

推导:infer

如何提取类型的一部分呢?答案是 infer。

比如提取元组类型的第一个元素:

ts
type First<Tuple extends unknown[]> = Tuple extends [infer T, ...infer R] ? T : never;
+
+type res = First<[1, 2, 3]>; // type res = 1

注意,第一个 extends 不是条件,条件类型是 extends ? :,这里的 extends 是约束的意思,也就是约束类型参数只能是数组类型。

因为不知道数组元素的具体类型,所以用 unknown。

infer 在后面的章节会大量用到,这里先简单了解即可。

联合:|

联合类型(Union)类似 js 里的或运算符 |,但是作用于类型,代表类型可以是几个类型之一。

ts
type Union = 1 | 2 | 3;

交叉:&

交叉类型(Intersection)类似 js 中的与运算符 &,但是作用于类型,代表对类型做合并。

ts
type ObjType = { a: number } & { c: boolean };

注意,同一类型可以合并,不同的类型没法合并,会被舍弃:

可以合并的

ts
type ObjType = { a: number } & { c: boolean };
+
+type res = { a: number; c: boolean } extends ObjType ? true : false; // type res = true

不可合并

ts
type res = 'aaaa' & 2222; // type res = never

映射类型

对象、class 在 TypeScript 对应的类型是索引类型(Index Type),那么如何对索引类型作修改呢?

答案是映射类型。

ts
type MapType<T> = {
+  [Key in keyof T]?: T[Key];
+};

keyof T 是查询索引类型中所有的索引,叫做索引查询。

T[Key] 是取索引类型某个索引的值,叫做索引访问。

in 是用于遍历联合类型的运算符。

比如我们把一个索引类型的值变成 3 个元素的数组:

ts
type MapType<T> = {
+  [Key in keyof T]: [T[Key], T[Key], T[Key]];
+};
+
+type res = MapType<{ a: 1; b: 2 }>; // type res = { a: [1, 1, 1]; b:[2, 2, 2]; }

映射类型就相当于把一个集合映射到另一个集合,这是它名字的由来。

除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。

我们用 as 把索引也做了修改,改成了 3 个 key 重复:

ts
type MapType<T> = {
+  [Key in keyof T as \`\${Key & string}\${Key & string}\${Key & string}\`]: [T[Key], T[Key], T[Key]];
+};
+
+// type res = { aaa: [1, 1, 1]; bbb: [2, 2, 2]; }

这里的 & string 可能大家会迷惑,解释一下:

因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是 string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型会把同一类型做合并,不同类型舍弃。

四。判断类型的类型

IsAny

如何判断一个类型是 any 类型呢?要根据它的特性来:

any 类型与任何类型的交叉都是 any,也就是 1 & any 结果是 any。

所以,可以这样写:

ts
type IsAny<T> = 'null' extends 'undefined' & T ? true : false;

IsEqual

之前我们实现 IsEqual 是这样写的:

ts
type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

问题出在 any 的判断上:

ts
type IsEqualResult = IsEqual<'aaa', any>;
+// type IsEqualResult = false

因为 any 可以是任何类型,任何类型也都是 any,所以当这样写判断不出 any 类型来。

所以,我们会这样写:

ts
type IsEqual<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;

这样就能正常判断了:

其中 T 是不传类型的,相当于一个临时变量

其目的是对比:

ts
<T>() => T extends X ? 1 : 2
+<T>() => T extends Y ? 1 : 2

这两个泛型函数类型是否相等,原理

IsUnion

还记得怎么判断 union 类型么?要根据它遇到条件类型时会分散成单个传入做计算的特性:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

IsNever

never 在条件类型中也比较特殊,如果条件类型左边是类型参数,并且传入的是 never,那么直接返回 never:

ts
type TestNever<T> = T extends number ? 1 : 2;

当 T 为 never 时:

ts
type TestNeverResult = TestNever<never>;
+// type TestNeverResult = never

所以,要判断 never 类型,就不能直接 T extends number,可以这样写:

ts
type IsNever<T> = [T] extends [never] ? true : false;

这样就能正常判断 never 类型了:

ts
type TestNeverResult = IsNever<never>;
+// type TestNeverResult = true

除此以外,any 在条件类型中也比较特殊,如果类型参数为 any,会直接返回 trueType 和 falseType 的合并:

ts
type TestAny<T> = T extends number ? 1 : 2;
+
+type TestAnyResult = TestAny<any>;
+// type TestAnyResult = 1 | 2

联合类型、never、any 在作为条件类型的类型参数时的这些特殊情况,也会在后面的原理篇来解释原因。

IsTuple

元组类型怎么判断呢?它和数组有什么区别呢?

元组类型的 length 是数字字面量,而数组的 length 是 number。

ts
type len

UnionToIntersection

类型之间是有父子关系的,更具体的那个是子类型,比如 A 和 B 的交叉类型 A & B 就是联合类型 A | B 的子类型,因为更具体。

如果允许父类型赋值给子类型,就叫做逆变

如果允许子类型赋值给父类型,就叫做协变

(关于逆变、协变等概念的详细解释可以看原理篇)

在 TypeScript 中有函数参数是有逆变的性质的,也就是如果参数可能是多个类型,参数类型会变成它们的交叉类型。

所以联合转交叉可以这样实现:

ts
type UnionToIntersection<U> = (U extends U ? (x: U) => unknown : never) extends (x: infer R) => unknown ? R : never;

类型参数 U 是要转换的联合类型。

U extends U 是为了触发联合类型的 distributive 的性质,让每个类型单独传入做计算,最后合并。

利用 U 做为参数构造个函数,通过模式匹配取参数的类型。

结果就是交叉类型

函数参数的逆变性质一般就联合类型转交叉类型会用,记住就行。

GetOptional

如何提取索引类型中的可选索引呢?

这也要利用可选索引的特性:可选索引的值为 undefined 和值类型的联合类型。

过滤可选索引,就要构造一个新的索引类型,过程中做过滤:

ts
type GetOptional<Obj extends Record<string, any>> = {
+  [Key in keyof Obj as {} extends Pick<Obj, Key> ? Key : never]: Obj[Key];
+};

类型参数 Obj 为待处理的索引类型,类型约束为索引为 string、值为任意类型的索引类型 Record<string, any>。

用映射类型的语法重新构造索引类型,索引是之前的索引也就是 Key in keyof Obj,但要做一些过滤,也就是 as 之后的部分。

过滤的方式就是单独取出该索引之后,判断空对象是否是其子类型。

这里的 Pick 是 ts 提供的内置高级类型,就是取出某个 Key 构造新的索引类型:

ts
type Pick<T, K extends keyof T> = { [P in K]: T[P] };

比如单独取出 age 构造的新的索引类型是这样的:

可选的意思是这个索引可能没有,没有的时候,那 Pick<Obj, Key> 就是空的,所以 {} extends Pick<Obj, Key> 就能过滤出可选索引。

值的类型依然是之前的,也就是 Obj[Key]。

这样,就能过滤出所有可选索引,构造成新的索引类型:

总结

  • any 类型与任何类型的交叉都是 any,也就是 1 & any 结果是 any,可以用这个特性判断 any 类型。
  • 联合类型作为类型参数出现在条件类型左侧时,会分散成单个类型传入,最后合并。
  • never 作为类型参数出现在条件类型左侧时,会直接返回 never。
  • any 作为类型参数出现在条件类型左侧时,会直接返回 trueType 和 falseType 的联合类型。
  • 元组类型也是数组类型,但 length 是数字字面量,而数组的 length 是 number。可以用来判断元组类型。
  • 函数参数处会发生逆变,可以用来实现联合类型转交叉类型。
  • 可选索引的索引可能没有,那 Pick 出来的就可能是 {},可以用来过滤可选索引,反过来也可以过滤非可选索引。
  • 索引类型的索引为字符串字面量类型,而可索引签名不是,可以用这个特性过滤掉可索引签名。
  • keyof 只能拿到 class 的 public 的索引,可以用来过滤出 public 的属性。
  • 默认推导出来的不是字面量类型,加上 as const 可以推导出字面量类型,但带有 readonly 修饰,这样模式匹配的时候也得加上 readonly 才行。
`,253)]))}const y=i(k,[["render",p]]);export{g as __pageData,y as default}; diff --git a/assets/src_article_typescript_index.md.SzJeg7Vl.lean.js b/assets/src_article_typescript_index.md.SzJeg7Vl.lean.js new file mode 100644 index 0000000000..2bd51dfcdc --- /dev/null +++ b/assets/src_article_typescript_index.md.SzJeg7Vl.lean.js @@ -0,0 +1,156 @@ +import{_ as i,o as a,c as h,a3 as n}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"TypeScript 的类型系统","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/typescript/index.md","filePath":"src/article/typescript/index.md","lastUpdated":1726550590000}'),k={name:"src/article/typescript/index.md"};function p(t,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

TypeScript 的类型系统

一。类型是什么

类型具体点来说就是指 number、boolean、string 等基础类型和 Object、Function 等复合类型,它们是编程语言提供的对不同内容的抽象:

  • 不同类型变量占据的内存大小不同: boolean 类型的变量会分配 4 个字节的内存,而 number 类型的变量则会分配 8 个字节的内存,给变量声明了不同的类型就代表了会占据不同的内存空间。

  • 不同类型变量可做的操作不同: number 类型可以做加减乘除等运算,boolean 就不可以,复合类型中不同类型的对象可用的方法不同,比如 Date 和 RegExp,变量的类型不同代表可以对该变量做的操作就不同。

有了类型,那我们的操作必须和类型相匹配,否则就会报错,这就是类型检查。

如果能保证对某种类型只做该类型允许的操作,这就叫做类型安全。

类型检查可以在运行时做,也可以运行之前的编译期做。这是两种不同的类型,前者叫做动态类型检查,后者叫做静态类型检查。

两种类型检查各有优缺点。动态类型检查 在源码中不保留类型信息,对某个变量赋什么值、做什么操作都是允许的,写代码很灵活。但这也埋下了类型不安全的隐患,比如对 string 做了乘除,对 Date 对象调用了 exec 方法,这些都是运行时才能检查出来的错误。

其中,最常见的错误应该是“null is not an object”、“undefined is not a function”之类的了,写代码时没发现类型不匹配,到了运行的时候才发现,就会有很多这种报错。

所以,动态类型虽然代码写起来简单,但代码中很容易藏着一些类型不匹配的隐患。

静态类型检查则是在源码中保留类型信息,声明变量要指定类型,对变量做的操作要和类型匹配,会有专门的编译器在编译期间做检查。

静态类型给写代码增加了一些难度,因为你除了要考虑代码要表达的逻辑之外,还要考虑类型逻辑:变量是什么类型的、是不是匹配、要不要做类型转换等。

不过,静态类型也消除了类型不安全的隐患,因为在编译期间就做了类型检查,就不会出现对 string 做了乘除,调用了 Date 的 exec 方法这类问题。

所以,静态类型虽然代码写起来要考虑的问题多一些,会复杂一些,但是却消除了代码中潜藏类型不安全问题的可能。

知道了动态类型检查和静态类型检查的区别,我们自然可以得出这样的结论:

动态类型只适合简单的场景,对于大项目却不太合适,因为代码中可能藏着的隐患太多了,万一线上报一个类型不匹配的错误,那可能就是大问题。

而静态类型虽然会增加写代码的成本,但是却能更好的保证代码的健壮性,减少 Bug 率。

所以,大型项目注定会用静态类型语言开发。

二。类型系统的分类

1.简单的类型系统

变量、函数、类等都可以声明类型,编译器会基于声明的类型做类型检查,类型不匹配时会报错。

这是最基础的类型系统,能保证类型安全,但有些死板。

比如一个 add 函数既可以做整数加法、又可以做浮点数加法,却需要声明两个函数:

c
int add(int a, int b) {
+    return a + b;
+}
+
+double add(double a, double b) {
+    return a + b;
+}

这个问题的解决思路很容易想到:如果类型能传参数就好了,传入 int 就是整数加法,传入 double 就是浮点数加法。

所以,就有了第二种类型系统。

2.支持泛型的类型系统

泛型的英文是 Generic Type,通用的类型,它可以代表任何一种类型,也叫做类型参数。

它给类型系统增加了一些灵活性,在整体比较固定,部分变量的类型有变化的情况下,可以减少很多重复代码。

比如上面的 add 函数,有了泛型之后就可以这样写:

java
T add<T>(T a, T b) {
+    return a + b;
+}
+
+add(1,2);
+add(1.111, 2.2222);

声明时把会变化的类型声明成泛型(也就是类型参数),在调用的时候再确定类型。

Java 就是这种类型系统。如果你看过 Java 代码,你会发现泛型用的特别多,这确实是一个很好的增加类型系统灵活性的特性。

但是,这种类型系统的灵活性对于 JavaScript 来说还不够,因为 JavaScript 太过灵活了。

比如,在 Java 里,对象都是由类 new 出来的,你不能凭空创建对象,但是 JavaScript 却可以,它支持对象字面量。

那如果是一个返回对象某个属性值的函数,类型该怎么写呢?

ts
function getPropValue<T>(obj: T, key): key对应的属性值类型 {
+  return obj[key];
+}

好像拿到了 T,也不能拿到它的属性和属性值,如果能对类型参数 T 做一些逻辑处理就好了。

所以,就有了第三种类型系统。

3.支持类型编程的类型系统

在 Java 里面,拿到了对象的类型就能找到它的类,进一步拿到各种信息,所以类型系统支持泛型就足够了。

但是在 JavaScript 里面,对象可以字面量的方式创建,还可以灵活的增删属性,拿到对象并不能确定什么,所以要支持对传入的类型参数做进一步的处理。

对传入的类型参数(泛型)做各种逻辑运算,产生新的类型,这就是类型编程。

比如上面那个 getProps 的函数,类型可以这样写:

ts
function getPropValue<T extends object, Key extends keyof T>(obj: T, key: Key): T[Key] {
+  return obj[key];
+}

这里的 keyof T、T[Key] 就是对类型参数 T 的类型运算。

TypeScript 的类型系统就是第三种,支持对类型参数做各种逻辑处理,可以写很复杂的类型逻辑。

类型逻辑可以多复杂?

类型逻辑是对类型参数的各种处理,可以实现很多强大的功能:

比如这个 ParseQueryString 的类型:

ts
type res = ParseQueryString<'a=1&b=2&c=3'>;

它可以对传入的字符串的类型参数做解析,返回解析以后的结果。等于

ts
type res = {
+  a: '1';
+  b: '2';
+  c: '3';
+};

如果是 Java 的只支持泛型的类型系统可以做到么?明显不能。但是 TypeScript 的类型系统就可以,因为它可以对泛型(类型参数)做各种逻辑处理。

只不过,这个类型的类型逻辑的代码比较多(下面的 ts 类型暂时看不懂没关系,在顺口溜那节会有详解,这里只是用来直观感受下类型编程的复杂度的,等学完以后大家也能实现这样的复杂高级类型的):

ts
type ParseParam<Param extends string> = Param extends \`\${infer Key}=\${infer Value}\`
+  ? {
+      [K in Key]: Value;
+    }
+  : {};
+
+type MergeValues<One, Other> = One extends Other ? One : Other extends unknown[] ? [One, ...Other] : [One, Other];
+
+type MergeParams<OneParam extends Record<string, any>, OtherParam extends Record<string, any>> = {
+  [Key in keyof OneParam | keyof OtherParam]: Key extends keyof OneParam
+    ? Key extends keyof OtherParam
+      ? MergeValues<OneParam[Key], OtherParam[Key]>
+      : OneParam[Key]
+    : Key extends keyof OtherParam
+      ? OtherParam[Key]
+      : never;
+};
+type ParseQueryString<Str extends string> = Str extends \`\${infer Param}&\${infer Rest}\`
+  ? MergeParams<ParseParam<Param>, ParseQueryString<Rest>>
+  : ParseParam<Str>;

TypeScript 的类型系统是图灵完备的,也就是能描述各种可计算逻辑。简单点来理解就是循环、条件等各种 JS 里面有的语法它都有,JS 能写的逻辑它都能写。

对类型参数的编程是 TypeScript 类型系统最强大的部分,可以实现各种复杂的类型计算逻辑,是它的优点。但同时也被认为是它的缺点,因为除了业务逻辑外还要写很多类型逻辑。

不过,我倒是觉得这种复杂度是不可避免的,因为 JS 本身足够灵活,要准确定义类型那类型系统必然也要设计的足够灵活。

4.类型安全和型变

TypeScript 给 JavaScript 添加了一套静态类型系统,是为了保证类型安全的,也就是保证变量只能赋同类型的值,对象只能访问它有的属性、方法。

比如 number 类型的值不能赋值给 boolean 类型的变量,Date 类型的对象就不能调用 exec 方法。

这是类型检查做的事情,遇到类型安全问题会在编译时报错。

但是这种类型安全的限制也不能太死板,有的时候需要一些变通,比如子类型是可以赋值给父类型的变量的,可以完全当成父类型来使用,也就是“型变(variant)”(类型改变)。

这种“型变”分为两种,一种是子类型可以赋值给父类型,叫做协变(covariant),一种是父类型可以赋值给子类型,叫做逆变(contravariant)。

先来看下协变:

协变(covariant)

对具体成员的输出参数进行一次类型转换,且类型转换的准则是“里氏替换原则”。

其中协变是很好理解的,比如我们有两个 interface:

ts
interface Animal {
+  name: string;
+  age: number;
+}
+
+interface Cat {
+  name: string;
+  age: number;
+  hobbies: string[];
+}

这里 Cat 是 Animal 的子类型,更具体,那么 Cat 类型的变量就可以赋值给 Animal 类型:

ts
let animal: Animal = {
+  name: 'cat',
+  age: 3,
+};
+
+let cat: Cat = {
+  name: 'Tony',
+  age: 5,
+  hobbies: ['run', 'swim'],
+};
+
+animal = cat;

这并不会报错,虽然这俩类型不一样,但是依然是类型安全的。

这种子类型可以赋值给父类型的情况就叫做协变。

为什么要支持协变很容易理解:类型系统支持了父子类型,那如果子类型还不能赋值给父类型,还叫父子类型么?

所以型变是实现类型父子关系必须的,它在保证类型安全的基础上,增加了类型系统的灵活性。

逆变相对难理解一些:

逆变(contravariant)

是对具体成员的输入参数进行一次类型转换,且类型转换的准则是"里氏替换原则"。

我们有这样两个函数:

ts
let printHobbies: (cat: Cat) => void;
+
+printHobbies = (cat) => {
+  console.log(cat.hobbies);
+};
+
+let printName: (animal: Animal) => void;
+
+printName = (animal) => {
+  console.log(animal.name);
+};

printHobbies 的参数 Guang 是 printName 参数 Person 的子类型。

那么问题来了,printName 能赋值给 printHobbies 么?printHobbies 能赋值给 printName 么?

测试一下发现是这样的:

ts
let printHobbies: (cat: Cat) => void;
+
+printHobbies = (cat) => {
+  console.log(cat.hobbies);
+};
+
+let printName: (animal: Animal) => void;
+
+printName = (animal) => {
+  console.log(animal.name);
+};
+
+printHobbies = printName;

printName 的参数 Person 不是 printHobbies 的参数 Guang 的父类型么,为啥能赋值给子类型?

因为这个函数调用的时候是按照 Guang 来约束的类型,但实际上函数只用到了父类型 Person 的属性和方法,当然不会有问题,依然是类型安全的。

这就是逆变,函数的参数有逆变的性质(而返回值是协变的,也就是子类型可以赋值给父类型)。

那反过来呢,如果 printHoobies 赋值给 printName 会发生什么?

因为函数声明的时候是按照 Person 来约束类型,但是调用的时候是按照 Guang 的类型来访问的属性和方法,那自然类型不安全了,所以就会报错。

但是在 ts2.x 之前支持这种赋值,也就是父类型可以赋值给子类型,子类型可以赋值给父类型,既逆变又协变,叫做“双向协变”。

但是这明显是有问题的,不能保证类型安全,所以之后 ts 加了一个编译选项 strictFunctionTypes,设置为 true 就只支持函数参数的逆变,设置为 false 则是双向协变。

我们把 strictFunctionTypes 关掉之后,就会发现两种赋值都可以了。

这样就支持函数参数的双向协变,类型检查不会报错,但不能严格保证类型安全。

开启之后,函数参数就只支持逆变,子类型赋值给父类型就会报错。

再举个逆变的例子,大家觉得下面这样的 ts 代码会报错么:

ts
type Func = (a: string) => void;
+
+const func: Func = (a: 'hello') => undefined;

答案是参数的位置会,返回值的位置不会:

参数的位置是逆变的,也就是被赋值的函数参数要是赋值的函数参数的子类型,而 string 不是 'hello' 的子类型,所以报错了。

返回值的位置是协变的,也就是赋值的函数的返回值是被赋值的函数的返回值的子类型,这里 undefined 是 void 的子类型,所以不报错。

不变(invariant)

逆变和协变都是型变,是针对父子类型而言的,非父子类型自然就不会型变,也就是不变:

非父子类型之间不会发生型变,只要类型不一样就会报错

那类型之间的父子关系是怎么确定的呢,好像也没有看到 extends 的继承?

像 java 里面的类型都是通过 extends 继承的,如果 A extends B,那 A 就是 B 的子类型。这种叫做名义类型系统(nominal type)。

而 ts 里不看这个,只要结构上是一致的,那么就可以确定父子关系,这种叫做结构类型系统(structual type)。

通过结构,更具体的那个是子类型。这里的 Cat 有 Animal 的所有属性,并且还多了一些属性,所以 Cat 是 Animal 的子类型。

注意,这里用的是更具体,而不是更多。

判断联合类型父子关系的时候, 'a' | 'b' 和 'a' | 'b' | 'c' 哪个更具体?

'a' | 'b' 更具体,所以 'a' | 'b' 是 'a' | 'b' | 'c' 的子类型。

三.TypeScript 类型系统

1.支持的类型

静态类型系统的目的是把类型检查从运行时提前到编译时,那 TS 类型系统中肯定要把 JS 的运行时类型拿过来,也就是 number、boolean、string、object、bigint、symbol、undefined、null 这些类型,还有就是它们的包装类型 Number、Boolean、String、Object、Symbol。

这些很容易理解,给 JS 添加静态类型,总没有必要重新造一套基础类型吧,直接复用 JS 的基础类型就行。

复合类型方面,JS 有 class、Array,这些 TypeScript 类型系统也都支持,但是又多加了三种类型:元组(Tuple)、接口(Interface)、枚举(Enum)。

元组

元组(Tuple)就是元素个数和类型固定的数组类型:

ts
type Tuple = [number, string];

接口

接口(Interface)可以描述函数、对象、构造器的结构:

对象:

ts
interface IPerson {
+  name: string;
+  age: number;
+}
+
+class Person implements IPerson {
+  name: string;
+  age: number;
+}
+
+const obj: IPerson = {
+  name: 'guang',
+  age: 18,
+};

函数:

ts
interface SayHello {
+  (name: string): string;
+}
+
+const func: SayHello = (name: string) => {
+  return 'hello,' + name;
+};

构造器:

ts
interface PersonConstructor {
+  new (name: string, age: number): IPerson;
+}
+
+function createPerson(ctor: PersonConstructor): IPerson {
+  return new ctor('guang', 18);
+}

对象类型、class 类型在 TypeScript 里也叫做索引类型,也就是索引了多个元素的类型的意思。对象可以动态添加属性,如果不知道会有什么属性,可以用可索引签名:

ts
interface IPerson {
+  [prop: string]: string | number;
+}
+const obj: IPerson = {};
+obj.name = 'guang';
+obj.age = 18;

总之,接口可以用来描述函数、构造器、索引类型(对象、class、数组)等复合类型。

枚举

枚举(Enum)是一系列值的复合:

ts
enum Transpiler {
+  Babel = 'babel',
+  Postcss = 'postcss',
+  Terser = 'terser',
+  Prettier = 'prettier',
+  TypeScriptCompiler = 'tsc',
+}
+
+const transpiler = Transpiler.TypeScriptCompiler;

此外,TypeScript 还支持字面量类型,也就是类似 1111、'aaaa'、{ a: 1} 这种值也可以做为类型。

其中,字符串的字面量类型有两种,一种是普通的字符串字面量,比如 'aaa',另一种是模版字面量,比如 aaa\${string},它的意思是以 aaa 开头,后面是任意 string 的字符串字面量类型。

所以想要约束以某个字符串开头的字符串字面量类型时可以这样写:

ts
function func(str: \`#\${string}\`) {}
+
+func('aaaa'); // error
+
+func('#aaaa'); // true

还有四种特殊的类型:void、never、any、unknown:

  • never 代表不可达,比如函数抛异常的时候,返回值就是 never。
  • void 代表空,可以是 undefined 或 never。
  • any 是任意类型,任何类型都可以赋值给它,它也可以赋值给任何类型(除了 never)。
  • unknown 是未知类型,任何类型都可以赋值给它,但是它不可以赋值给别的类型。

这些就是 TypeScript 类型系统中的全部类型了,大部分是从 JS 中迁移过来的,比如基础类型、Array、class 等,也添加了一些类型,比如 枚举(enum)、接口(interface)、元组等,还支持了字面量类型和 void、never、any、unknown 的特殊类型。

2.类型的装饰

除了描述类型的结构外,TypeScript 的类型系统还支持描述类型的属性,比如是否可选,是否只读等:

ts
interface IPerson {
+  readonly name: string;
+  age?: number;
+}
+
+type tuple = [string, number?];

3.类型运算

我们知道了 TypeScript 类型系统里有哪些类型,那么可以对这些类型做什么类型运算呢?

条件:extends ?

TypeScript 里的条件判断是 extends ? :,叫做条件类型(Conditional Type)比如:

ts
type res = 1 extends 2 ? true : false; // type res = false

这就是 TypeScript 类型系统里的 if else。

但是,上面这样的逻辑没啥意义,静态的值自己就能算出结果来,为什么要用代码去判断呢?

所以,类型运算逻辑都是用来做一些动态的类型的运算的,也就是对类型参数的运算。

ts
type isTwo<T> = T extends 2 ? true : false;
+
+type res = isTwo<1>; // type res = false
+type res2 = isTwo<2>; // type res = true

这种类型也叫做高级类型。

高级类型的特点是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

推导:infer

如何提取类型的一部分呢?答案是 infer。

比如提取元组类型的第一个元素:

ts
type First<Tuple extends unknown[]> = Tuple extends [infer T, ...infer R] ? T : never;
+
+type res = First<[1, 2, 3]>; // type res = 1

注意,第一个 extends 不是条件,条件类型是 extends ? :,这里的 extends 是约束的意思,也就是约束类型参数只能是数组类型。

因为不知道数组元素的具体类型,所以用 unknown。

infer 在后面的章节会大量用到,这里先简单了解即可。

联合:|

联合类型(Union)类似 js 里的或运算符 |,但是作用于类型,代表类型可以是几个类型之一。

ts
type Union = 1 | 2 | 3;

交叉:&

交叉类型(Intersection)类似 js 中的与运算符 &,但是作用于类型,代表对类型做合并。

ts
type ObjType = { a: number } & { c: boolean };

注意,同一类型可以合并,不同的类型没法合并,会被舍弃:

可以合并的

ts
type ObjType = { a: number } & { c: boolean };
+
+type res = { a: number; c: boolean } extends ObjType ? true : false; // type res = true

不可合并

ts
type res = 'aaaa' & 2222; // type res = never

映射类型

对象、class 在 TypeScript 对应的类型是索引类型(Index Type),那么如何对索引类型作修改呢?

答案是映射类型。

ts
type MapType<T> = {
+  [Key in keyof T]?: T[Key];
+};

keyof T 是查询索引类型中所有的索引,叫做索引查询。

T[Key] 是取索引类型某个索引的值,叫做索引访问。

in 是用于遍历联合类型的运算符。

比如我们把一个索引类型的值变成 3 个元素的数组:

ts
type MapType<T> = {
+  [Key in keyof T]: [T[Key], T[Key], T[Key]];
+};
+
+type res = MapType<{ a: 1; b: 2 }>; // type res = { a: [1, 1, 1]; b:[2, 2, 2]; }

映射类型就相当于把一个集合映射到另一个集合,这是它名字的由来。

除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。

我们用 as 把索引也做了修改,改成了 3 个 key 重复:

ts
type MapType<T> = {
+  [Key in keyof T as \`\${Key & string}\${Key & string}\${Key & string}\`]: [T[Key], T[Key], T[Key]];
+};
+
+// type res = { aaa: [1, 1, 1]; bbb: [2, 2, 2]; }

这里的 & string 可能大家会迷惑,解释一下:

因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是 string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型会把同一类型做合并,不同类型舍弃。

四。判断类型的类型

IsAny

如何判断一个类型是 any 类型呢?要根据它的特性来:

any 类型与任何类型的交叉都是 any,也就是 1 & any 结果是 any。

所以,可以这样写:

ts
type IsAny<T> = 'null' extends 'undefined' & T ? true : false;

IsEqual

之前我们实现 IsEqual 是这样写的:

ts
type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

问题出在 any 的判断上:

ts
type IsEqualResult = IsEqual<'aaa', any>;
+// type IsEqualResult = false

因为 any 可以是任何类型,任何类型也都是 any,所以当这样写判断不出 any 类型来。

所以,我们会这样写:

ts
type IsEqual<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;

这样就能正常判断了:

其中 T 是不传类型的,相当于一个临时变量

其目的是对比:

ts
<T>() => T extends X ? 1 : 2
+<T>() => T extends Y ? 1 : 2

这两个泛型函数类型是否相等,原理

IsUnion

还记得怎么判断 union 类型么?要根据它遇到条件类型时会分散成单个传入做计算的特性:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

IsNever

never 在条件类型中也比较特殊,如果条件类型左边是类型参数,并且传入的是 never,那么直接返回 never:

ts
type TestNever<T> = T extends number ? 1 : 2;

当 T 为 never 时:

ts
type TestNeverResult = TestNever<never>;
+// type TestNeverResult = never

所以,要判断 never 类型,就不能直接 T extends number,可以这样写:

ts
type IsNever<T> = [T] extends [never] ? true : false;

这样就能正常判断 never 类型了:

ts
type TestNeverResult = IsNever<never>;
+// type TestNeverResult = true

除此以外,any 在条件类型中也比较特殊,如果类型参数为 any,会直接返回 trueType 和 falseType 的合并:

ts
type TestAny<T> = T extends number ? 1 : 2;
+
+type TestAnyResult = TestAny<any>;
+// type TestAnyResult = 1 | 2

联合类型、never、any 在作为条件类型的类型参数时的这些特殊情况,也会在后面的原理篇来解释原因。

IsTuple

元组类型怎么判断呢?它和数组有什么区别呢?

元组类型的 length 是数字字面量,而数组的 length 是 number。

ts
type len

UnionToIntersection

类型之间是有父子关系的,更具体的那个是子类型,比如 A 和 B 的交叉类型 A & B 就是联合类型 A | B 的子类型,因为更具体。

如果允许父类型赋值给子类型,就叫做逆变

如果允许子类型赋值给父类型,就叫做协变

(关于逆变、协变等概念的详细解释可以看原理篇)

在 TypeScript 中有函数参数是有逆变的性质的,也就是如果参数可能是多个类型,参数类型会变成它们的交叉类型。

所以联合转交叉可以这样实现:

ts
type UnionToIntersection<U> = (U extends U ? (x: U) => unknown : never) extends (x: infer R) => unknown ? R : never;

类型参数 U 是要转换的联合类型。

U extends U 是为了触发联合类型的 distributive 的性质,让每个类型单独传入做计算,最后合并。

利用 U 做为参数构造个函数,通过模式匹配取参数的类型。

结果就是交叉类型

函数参数的逆变性质一般就联合类型转交叉类型会用,记住就行。

GetOptional

如何提取索引类型中的可选索引呢?

这也要利用可选索引的特性:可选索引的值为 undefined 和值类型的联合类型。

过滤可选索引,就要构造一个新的索引类型,过程中做过滤:

ts
type GetOptional<Obj extends Record<string, any>> = {
+  [Key in keyof Obj as {} extends Pick<Obj, Key> ? Key : never]: Obj[Key];
+};

类型参数 Obj 为待处理的索引类型,类型约束为索引为 string、值为任意类型的索引类型 Record<string, any>。

用映射类型的语法重新构造索引类型,索引是之前的索引也就是 Key in keyof Obj,但要做一些过滤,也就是 as 之后的部分。

过滤的方式就是单独取出该索引之后,判断空对象是否是其子类型。

这里的 Pick 是 ts 提供的内置高级类型,就是取出某个 Key 构造新的索引类型:

ts
type Pick<T, K extends keyof T> = { [P in K]: T[P] };

比如单独取出 age 构造的新的索引类型是这样的:

可选的意思是这个索引可能没有,没有的时候,那 Pick<Obj, Key> 就是空的,所以 {} extends Pick<Obj, Key> 就能过滤出可选索引。

值的类型依然是之前的,也就是 Obj[Key]。

这样,就能过滤出所有可选索引,构造成新的索引类型:

总结

  • any 类型与任何类型的交叉都是 any,也就是 1 & any 结果是 any,可以用这个特性判断 any 类型。
  • 联合类型作为类型参数出现在条件类型左侧时,会分散成单个类型传入,最后合并。
  • never 作为类型参数出现在条件类型左侧时,会直接返回 never。
  • any 作为类型参数出现在条件类型左侧时,会直接返回 trueType 和 falseType 的联合类型。
  • 元组类型也是数组类型,但 length 是数字字面量,而数组的 length 是 number。可以用来判断元组类型。
  • 函数参数处会发生逆变,可以用来实现联合类型转交叉类型。
  • 可选索引的索引可能没有,那 Pick 出来的就可能是 {},可以用来过滤可选索引,反过来也可以过滤非可选索引。
  • 索引类型的索引为字符串字面量类型,而可索引签名不是,可以用这个特性过滤掉可索引签名。
  • keyof 只能拿到 class 的 public 的索引,可以用来过滤出 public 的属性。
  • 默认推导出来的不是字面量类型,加上 as const 可以推导出字面量类型,但带有 readonly 修饰,这样模式匹配的时候也得加上 readonly 才行。
`,253)]))}const y=i(k,[["render",p]]);export{g as __pageData,y as default}; diff --git a/assets/src_article_typescript_pattern.md.Cl1kek3_.js b/assets/src_article_typescript_pattern.md.Cl1kek3_.js new file mode 100644 index 0000000000..e1b8ac6323 --- /dev/null +++ b/assets/src_article_typescript_pattern.md.Cl1kek3_.js @@ -0,0 +1,93 @@ +import{_ as i,o as a,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"模式匹配提取","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/typescript/pattern.md","filePath":"src/article/typescript/pattern.md","lastUpdated":1726550590000}'),n={name:"src/article/typescript/pattern.md"};function k(p,s,l,e,r,d){return a(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h(`

模式匹配提取

字符串可以和正则做模式匹配,找到匹配的部分,提取子组,之后可以用 1,2 等引用匹配的子组。

ts
'abc'.replace(/a(b)c/, '$1,$1,$1');
+// 'b,b,b'

Typescript 的类型也同样可以做模式匹配。

比如这样一个 Promise 类型:

ts
type p = Promise<'value'>;

我们想提取 value 的类型,可以这样做:

ts
type GetValueType<P> = P extends Promise<infer Value> ? Value : never;

通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取的,通过 infer 声明一个局部变量 Value 来保存,如果匹配,就返回匹配到的 Value,否则就返回 never 代表没匹配到。

ts
// type GetValueResult = 'value'
+type GetValueResult = GetValueType<Promise<'value'>>;

这就是 Typescript 类型的模式匹配:

Typescript 类型的模式匹配是通过 extends 对类型参数做匹配,结果保存到通过 infer 声明的局部类型变量里,如果匹配就能从该局部变量里拿到提取出的类型。

这个模式匹配的套路有多有用呢?我们来看下在数组、字符串、函数、构造器等类型里的应用。

1.数组类型

提取第一个元素

数组类型想提取第一个元素的类型怎么做呢?

ts
type arr = [1, 2, 3];

用它来匹配一个模式类型,提取第一个元素的类型到通过 infer 声明的局部变量里返回。

ts
type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;

类型参数 Arr 通过 extends 约束为只能是数组类型,数组元素是 unkown 也就是可以是任何值。

any 和 unknown 的区别:any 和 unknown 都代表任意类型,但是 unknown 只能接收任意类型的值,而 any 除了可以接收任意类型的值,也可以赋值给任意类型(除了 never)。类型体操中经常用 unknown 接受和匹配任何类型,而很少把任何类型赋值给某个类型变量。

对 Arr 做模式匹配,把我们要提取的第一个元素的类型放到通过 infer 声明的 First 局部变量里,后面的元素可以是任何类型,用 unknown 接收,然后把局部变量 First 返回。

当类型参数 Arr 为 [1,2,3] 时:

ts
type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;
+type GetFirstValue = GetFirst<[1, 2, 3]>;
+// type GetFirstValue = 1

当类型参数 Arr 为 [] 时:

ts
type GetFirstResult = GetFirst<[]>;
+// type GetFirstResult = never

提取最后一个元素

可以提取第一个元素,当然也可以提取最后一个元素,修改下模式类型就行:

ts
type GetLastValue<Arr extends unknown[]> = Arr extends [...unknown, infer Last] ? Last : never;

当类型参数 Arr 为 [1,2,3]时:

ts
type GetLastResult = GetFirst<[1, 2, 3]>;
+// type GetLastResult = 3

PopArr

我们分别取了首尾元素,当然也可以取剩余的数组,比如取去掉了最后一个元素的数组:

ts
type PopArr<Arr extends unknown[]> = Arr extends [...infer Rest, unknown] ? Rest : never;

如果是空数组,就直接返回,否则匹配剩余的元素,放到 infer 声明的局部变量 Rest 里,返回 Rest。

当类型参数 Arr 为 [1,2,3] 时:

ts
type PopResult = PopArr<[1, 2, 3]>;
+// type PopResult = [1,2]

当类型参数 Arr 为 [] 时:

ts
type PopResult = PopArr<[]>;
+// type PopResult = []

ShiftArr

同理可得 ShiftArr 的实现:

ts
type ShiftArr<Arr extends unknown[]> = Arr extends [unknown, ...infer Rest] ? Rest : never;

当类型参数 Arr 为 [1,2,3]时:

ts
type ShiftResult = ShiftArr<[1, 2, 3]>;
+// type ShiftResult = [2,3]

2.字符串类型

字符串类型也同样可以做模式匹配,匹配一个模式字符串,把需要提取的部分放到 infer 声明的局部变量里。

StartsWith

判断字符串是否以某个前缀开头,也是通过模式匹配:

ts
type StartWith<str extends string, Prefix extends string> = Str extends \`\${Prefix}\${string}\` ? true : false;

需要声明字符串 Str、匹配的前缀 Prefix 两个类型参数,它们都是 string。

用 Str 去匹配一个模式类型,模式类型的前缀是 Prefix,后面是任意的 string,如果匹配返回 true,否则返回 false。

当匹配时:

ts
type StartWithResult = StartWidth<'prefix string', 'prefix'>;
+// type StartWithResult = true

不匹配时:

ts
type StartWithResult = StartWidth<'prefix string', 'string'>;
+// type StartWithResult = false

Replace

字符串可以匹配一个模式类型,提取想要的部分,自然也可以用这些再构成一个新的类型。

比如实现字符串替换:

ts
type ReplaceStr<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends \`\${infer Prefix}\${From}\${infer Suffix}\` ? \`\${Prefix}\${To}\${Suffix}\` : Str;

声明要替换的字符串 Str、待替换的字符串 From、替换成的字符串 3 个类型参数,通过 extends 约束为都是 string 类型。

用 Str 去匹配模式串,模式串由 From 和之前之后的字符串构成,把之前之后的字符串放到通过 infer 声明的局部变量 Prefix、Suffix 里。

用 Prefix、Suffix 加上替换到的字符串 To 构造成新的字符串类型返回。

当匹配时:

ts
type ReplaceResult = ReplaceStr<'str replace to result', 'result', 'aaaa'>;
+// type ReplaceResult =  'str replace to aaaa'

不匹配时:

ts
type ReplaceResult = ReplaceStr<'str replace to result', '???', 'aaaa'>;
+// type ReplaceResult =  'str replace to result'

Trim

能够匹配和替换字符串,那也就能实现去掉空白字符的 Trim:

不过因为我们不知道有多少个空白字符,所以只能一个个匹配和去掉,需要递归。

先实现 TrimRight:

ts
type TrimRight<Str extends string> = Str extends \`\${infer Rest}\${' ' | '\\n''\\t'}\` ? TrimRight<Rest> : Str

类型参数 Str 是要 Trim 的字符串。

如果 Str 匹配字符串 + 空白字符 (空格、换行、制表符),那就把字符串放到 infer 声明的局部变量 Rest 里。

把 Rest 作为类型参数递归 TrimRight,直到不匹配,这时的类型参数 Str 就是处理结果。

ts
type TrimRightResult = TrimRight<'value          '>;
+// type TrimRightResult = 'value'

同理可得 TrimLeft:

ts
type TrimLeft<Str extends string> = Str extends \`\${' '|'\\n'|'\\t'}\`\${infer Rest} ? TrimLeft<Rest> : Str

TrimRight 和 TrimLeft 结合就是 Trim:

ts
type Trim<Str extends string> = TrimRight<TrimLeft<Str>>;

3.函数

函数同样也可以做类型匹配,比如提取参数、返回值的类型。

GetParameters

函数类型可以通过模式匹配来提取参数的类型:

ts
type GetParameters<Func extends Function> = Func extends (...args: infer Args) => unknown ? Args : never;

类型参数 Func 是要匹配的函数类型,通过 extends 约束为 Function。

Func 和模式类型做匹配,参数类型放到用 infer 声明的局部变量 Args 里,返回值可以是任何类型,用 unknown。

返回提取到的参数类型 Args。

ts
type GetParametersResult = GetParameters<(name: string, age: number) => string>;
+// type GetParametersResult = [name:string,age:number]

GetReturnType

能提取参数类型,同样也可以提取返回值类型:

ts
type GetReturnType<Func extends Function> = Func extends (...args: unknown[]) => infer ReturnType ? ReturnType : never;

Func 和模式类型做匹配,提取返回值到通过 infer 声明的局部变量 ReturnType 里返回。

参数类型可以是任意类型,也就是 any[](注意,这里不能用 unknown,这里的解释涉及到参数的逆变性质,具体原因逆变那一节会解释)。

ts
type GetReturnTypeResult = GetReturnType<() => 'return value'>;
+// type GetReturnTypeResult = 'return value'

GetThisParameterType

方法里可以调用 this,比如这样:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello() {
+    return "hello, I'm " + this.name;
+  }
+}
+
+const dong = new Dong();
+dong.hello();

用对象。方法名的方式调用的时候,this 就指向那个对象。

但是方法也可以用 call 或者 apply 调用:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello() {
+    return "hello, I'm " + this.name;
+  }
+}
+
+const dong = new Dong();
+dong.hello().call({ x: 1 });

call 调用的时候,this 就变了,但这里却没有被检查出来 this 指向的错误。

如何让编译器能够检查出 this 指向的错误呢?

可以在方法声明时指定 this 的类型:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello(this: Dong) {
+    return "hello, I'm " + this.name;
+  }
+}

这样,当 call/apply 调用的时候,就能检查出 this 指向的对象是否是对的:

如果没有报错,说明没开启 strictBindCallApply 的编译选项,这个是控制是否按照原函数的类型来检查 bind、call、apply

这里的 this 类型同样也可以通过模式匹配提取出来:

ts
type GetThisParameterType<T> = T extends (this: infer This, ...args: unknown[]) => unknown ? This : unknown;

类型参数 T 是待处理的类型。

用 T 匹配一个模式类型,提取 this 的类型到 infer 声明的局部变量 ThisType 中,其余的参数是任意类型,也就是 any,返回值也是任意类型。

返回提取到的 ThisType。

这样就能提取出 this 的类型:

4.构造器类型

构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

同样,我们也可以通过模式匹配提取构造器的参数和返回值的类型:

GetInstanceType

构造器类型可以用 interface 声明,使用 new(): xx 的语法。

比如:

ts
interface Person {
+  name: string;
+}
+
+interface PersonConstructor {
+  new (name: string): Person;
+}

这里的 PersonConstructor 返回的是 Person 类型的实例对象,这个也可以通过模式匹配取出来。

ts
type GetInstanceType<ConstructorType extends new (...args: any) => any> = ConstructorType extends new (
+  ...args: any
+) => infer InstanceType
+  ? InstanceType
+  : any;

类型参数 ConstructorType 是待处理的类型,通过 extends 约束为构造器类型。

用 ConstructorType 匹配一个模式类型,提取返回的实例类型到 infer 声明的局部变量 InstanceType 里,返回 InstanceType。

这样就能取出构造器对应的实例类型:

ts
interface PersonConstructor {
+  new (name: string): Person;
+}
+
+type GetInstanceTypeResult = GetInstanceType<PersonConstructor>;
+// type GetInstanceTypeResult = Person

GetConstructorParameters

GetInstanceType 是提取构造器返回值类型,那同样也可以提取构造器的参数类型:

ts
type GetConstructorParameters<ConstructorType extends new (...args: any) => any> = ConstructorType extends new (
+  ...args: infer ParametersType
+) => any
+  ? ParametersType
+  : never;

类型参数 ConstructorType 为待处理的类型,通过 extends 约束为构造器类型。

用 ConstructorType 匹配一个模式类型,提取参数的部分到 infer 声明的局部变量 ParametersType 里,返回 ParametersType。

这样就能提取出构造器对应的参数类型:

ts
interface PersonConstructor {
+  new (name: string): Person;
+}
+
+type GetConstructorParametersResult = GetConstructorParameters<PersonConstructor>;
+// type GetConstructorParametersResult = [name:string]

索引类型

索引类型也同样可以用模式匹配提取某个索引的值的类型,这个用的也挺多的,比如 React 的 index.d.ts 里的 PropsWithRef 的高级类型,就是通过模式匹配提取了 ref 的值的类型:

ts
type PropsWithRef<P> = 'ref' extends keyof P
+  ? P extends { ref?: infer R | undefined }
+    ? string extends R
+      ? PropsWithRef<P> & { ref?: Exclude<R, string> | undefined }
+      : P
+    : P
+  : P;

我们简化一下那个高级类型,提取 Props 里 ref 的类型:

ts
type GetPropsRef<Props> = 'ref' extends keyof Props
+  ? Props extends { ref?: infer Value | undefined }
+    ? value
+    : never
+  : never;

类型参数 Props 为待处理的类型。

通过 keyof Props 取出 Props 的所有索引构成的联合类型,判断下 ref 是否在其中,也就是 'ref' extends keyof Props。

为什么要做这个判断,上面注释里写了:

在 ts3.0 里面如果没有对应的索引,Obj[Key] 返回的是 {} 而不是 never,所以这样做下兼容处理。

如果有 ref 这个索引的话,就通过 infer 提取 Value 的类型返回,否则返回 never。

ts
type GetPropsRefResult = GetPropsRef<{ ref: 1; name: 'str' }>;
+// type GetPropsRefResult = 1

当 ref 为 undefined 时:

ts
type GetPropsRefResult = GetPropsRef<{ ref: undefined; name: 'str' }>;
+// type GetPropsRefResult = undefined
`,145)]))}const F=i(n,[["render",k]]);export{y as __pageData,F as default}; diff --git a/assets/src_article_typescript_pattern.md.Cl1kek3_.lean.js b/assets/src_article_typescript_pattern.md.Cl1kek3_.lean.js new file mode 100644 index 0000000000..e1b8ac6323 --- /dev/null +++ b/assets/src_article_typescript_pattern.md.Cl1kek3_.lean.js @@ -0,0 +1,93 @@ +import{_ as i,o as a,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"模式匹配提取","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/typescript/pattern.md","filePath":"src/article/typescript/pattern.md","lastUpdated":1726550590000}'),n={name:"src/article/typescript/pattern.md"};function k(p,s,l,e,r,d){return a(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h(`

模式匹配提取

字符串可以和正则做模式匹配,找到匹配的部分,提取子组,之后可以用 1,2 等引用匹配的子组。

ts
'abc'.replace(/a(b)c/, '$1,$1,$1');
+// 'b,b,b'

Typescript 的类型也同样可以做模式匹配。

比如这样一个 Promise 类型:

ts
type p = Promise<'value'>;

我们想提取 value 的类型,可以这样做:

ts
type GetValueType<P> = P extends Promise<infer Value> ? Value : never;

通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取的,通过 infer 声明一个局部变量 Value 来保存,如果匹配,就返回匹配到的 Value,否则就返回 never 代表没匹配到。

ts
// type GetValueResult = 'value'
+type GetValueResult = GetValueType<Promise<'value'>>;

这就是 Typescript 类型的模式匹配:

Typescript 类型的模式匹配是通过 extends 对类型参数做匹配,结果保存到通过 infer 声明的局部类型变量里,如果匹配就能从该局部变量里拿到提取出的类型。

这个模式匹配的套路有多有用呢?我们来看下在数组、字符串、函数、构造器等类型里的应用。

1.数组类型

提取第一个元素

数组类型想提取第一个元素的类型怎么做呢?

ts
type arr = [1, 2, 3];

用它来匹配一个模式类型,提取第一个元素的类型到通过 infer 声明的局部变量里返回。

ts
type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;

类型参数 Arr 通过 extends 约束为只能是数组类型,数组元素是 unkown 也就是可以是任何值。

any 和 unknown 的区别:any 和 unknown 都代表任意类型,但是 unknown 只能接收任意类型的值,而 any 除了可以接收任意类型的值,也可以赋值给任意类型(除了 never)。类型体操中经常用 unknown 接受和匹配任何类型,而很少把任何类型赋值给某个类型变量。

对 Arr 做模式匹配,把我们要提取的第一个元素的类型放到通过 infer 声明的 First 局部变量里,后面的元素可以是任何类型,用 unknown 接收,然后把局部变量 First 返回。

当类型参数 Arr 为 [1,2,3] 时:

ts
type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;
+type GetFirstValue = GetFirst<[1, 2, 3]>;
+// type GetFirstValue = 1

当类型参数 Arr 为 [] 时:

ts
type GetFirstResult = GetFirst<[]>;
+// type GetFirstResult = never

提取最后一个元素

可以提取第一个元素,当然也可以提取最后一个元素,修改下模式类型就行:

ts
type GetLastValue<Arr extends unknown[]> = Arr extends [...unknown, infer Last] ? Last : never;

当类型参数 Arr 为 [1,2,3]时:

ts
type GetLastResult = GetFirst<[1, 2, 3]>;
+// type GetLastResult = 3

PopArr

我们分别取了首尾元素,当然也可以取剩余的数组,比如取去掉了最后一个元素的数组:

ts
type PopArr<Arr extends unknown[]> = Arr extends [...infer Rest, unknown] ? Rest : never;

如果是空数组,就直接返回,否则匹配剩余的元素,放到 infer 声明的局部变量 Rest 里,返回 Rest。

当类型参数 Arr 为 [1,2,3] 时:

ts
type PopResult = PopArr<[1, 2, 3]>;
+// type PopResult = [1,2]

当类型参数 Arr 为 [] 时:

ts
type PopResult = PopArr<[]>;
+// type PopResult = []

ShiftArr

同理可得 ShiftArr 的实现:

ts
type ShiftArr<Arr extends unknown[]> = Arr extends [unknown, ...infer Rest] ? Rest : never;

当类型参数 Arr 为 [1,2,3]时:

ts
type ShiftResult = ShiftArr<[1, 2, 3]>;
+// type ShiftResult = [2,3]

2.字符串类型

字符串类型也同样可以做模式匹配,匹配一个模式字符串,把需要提取的部分放到 infer 声明的局部变量里。

StartsWith

判断字符串是否以某个前缀开头,也是通过模式匹配:

ts
type StartWith<str extends string, Prefix extends string> = Str extends \`\${Prefix}\${string}\` ? true : false;

需要声明字符串 Str、匹配的前缀 Prefix 两个类型参数,它们都是 string。

用 Str 去匹配一个模式类型,模式类型的前缀是 Prefix,后面是任意的 string,如果匹配返回 true,否则返回 false。

当匹配时:

ts
type StartWithResult = StartWidth<'prefix string', 'prefix'>;
+// type StartWithResult = true

不匹配时:

ts
type StartWithResult = StartWidth<'prefix string', 'string'>;
+// type StartWithResult = false

Replace

字符串可以匹配一个模式类型,提取想要的部分,自然也可以用这些再构成一个新的类型。

比如实现字符串替换:

ts
type ReplaceStr<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends \`\${infer Prefix}\${From}\${infer Suffix}\` ? \`\${Prefix}\${To}\${Suffix}\` : Str;

声明要替换的字符串 Str、待替换的字符串 From、替换成的字符串 3 个类型参数,通过 extends 约束为都是 string 类型。

用 Str 去匹配模式串,模式串由 From 和之前之后的字符串构成,把之前之后的字符串放到通过 infer 声明的局部变量 Prefix、Suffix 里。

用 Prefix、Suffix 加上替换到的字符串 To 构造成新的字符串类型返回。

当匹配时:

ts
type ReplaceResult = ReplaceStr<'str replace to result', 'result', 'aaaa'>;
+// type ReplaceResult =  'str replace to aaaa'

不匹配时:

ts
type ReplaceResult = ReplaceStr<'str replace to result', '???', 'aaaa'>;
+// type ReplaceResult =  'str replace to result'

Trim

能够匹配和替换字符串,那也就能实现去掉空白字符的 Trim:

不过因为我们不知道有多少个空白字符,所以只能一个个匹配和去掉,需要递归。

先实现 TrimRight:

ts
type TrimRight<Str extends string> = Str extends \`\${infer Rest}\${' ' | '\\n''\\t'}\` ? TrimRight<Rest> : Str

类型参数 Str 是要 Trim 的字符串。

如果 Str 匹配字符串 + 空白字符 (空格、换行、制表符),那就把字符串放到 infer 声明的局部变量 Rest 里。

把 Rest 作为类型参数递归 TrimRight,直到不匹配,这时的类型参数 Str 就是处理结果。

ts
type TrimRightResult = TrimRight<'value          '>;
+// type TrimRightResult = 'value'

同理可得 TrimLeft:

ts
type TrimLeft<Str extends string> = Str extends \`\${' '|'\\n'|'\\t'}\`\${infer Rest} ? TrimLeft<Rest> : Str

TrimRight 和 TrimLeft 结合就是 Trim:

ts
type Trim<Str extends string> = TrimRight<TrimLeft<Str>>;

3.函数

函数同样也可以做类型匹配,比如提取参数、返回值的类型。

GetParameters

函数类型可以通过模式匹配来提取参数的类型:

ts
type GetParameters<Func extends Function> = Func extends (...args: infer Args) => unknown ? Args : never;

类型参数 Func 是要匹配的函数类型,通过 extends 约束为 Function。

Func 和模式类型做匹配,参数类型放到用 infer 声明的局部变量 Args 里,返回值可以是任何类型,用 unknown。

返回提取到的参数类型 Args。

ts
type GetParametersResult = GetParameters<(name: string, age: number) => string>;
+// type GetParametersResult = [name:string,age:number]

GetReturnType

能提取参数类型,同样也可以提取返回值类型:

ts
type GetReturnType<Func extends Function> = Func extends (...args: unknown[]) => infer ReturnType ? ReturnType : never;

Func 和模式类型做匹配,提取返回值到通过 infer 声明的局部变量 ReturnType 里返回。

参数类型可以是任意类型,也就是 any[](注意,这里不能用 unknown,这里的解释涉及到参数的逆变性质,具体原因逆变那一节会解释)。

ts
type GetReturnTypeResult = GetReturnType<() => 'return value'>;
+// type GetReturnTypeResult = 'return value'

GetThisParameterType

方法里可以调用 this,比如这样:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello() {
+    return "hello, I'm " + this.name;
+  }
+}
+
+const dong = new Dong();
+dong.hello();

用对象。方法名的方式调用的时候,this 就指向那个对象。

但是方法也可以用 call 或者 apply 调用:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello() {
+    return "hello, I'm " + this.name;
+  }
+}
+
+const dong = new Dong();
+dong.hello().call({ x: 1 });

call 调用的时候,this 就变了,但这里却没有被检查出来 this 指向的错误。

如何让编译器能够检查出 this 指向的错误呢?

可以在方法声明时指定 this 的类型:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello(this: Dong) {
+    return "hello, I'm " + this.name;
+  }
+}

这样,当 call/apply 调用的时候,就能检查出 this 指向的对象是否是对的:

如果没有报错,说明没开启 strictBindCallApply 的编译选项,这个是控制是否按照原函数的类型来检查 bind、call、apply

这里的 this 类型同样也可以通过模式匹配提取出来:

ts
type GetThisParameterType<T> = T extends (this: infer This, ...args: unknown[]) => unknown ? This : unknown;

类型参数 T 是待处理的类型。

用 T 匹配一个模式类型,提取 this 的类型到 infer 声明的局部变量 ThisType 中,其余的参数是任意类型,也就是 any,返回值也是任意类型。

返回提取到的 ThisType。

这样就能提取出 this 的类型:

4.构造器类型

构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

同样,我们也可以通过模式匹配提取构造器的参数和返回值的类型:

GetInstanceType

构造器类型可以用 interface 声明,使用 new(): xx 的语法。

比如:

ts
interface Person {
+  name: string;
+}
+
+interface PersonConstructor {
+  new (name: string): Person;
+}

这里的 PersonConstructor 返回的是 Person 类型的实例对象,这个也可以通过模式匹配取出来。

ts
type GetInstanceType<ConstructorType extends new (...args: any) => any> = ConstructorType extends new (
+  ...args: any
+) => infer InstanceType
+  ? InstanceType
+  : any;

类型参数 ConstructorType 是待处理的类型,通过 extends 约束为构造器类型。

用 ConstructorType 匹配一个模式类型,提取返回的实例类型到 infer 声明的局部变量 InstanceType 里,返回 InstanceType。

这样就能取出构造器对应的实例类型:

ts
interface PersonConstructor {
+  new (name: string): Person;
+}
+
+type GetInstanceTypeResult = GetInstanceType<PersonConstructor>;
+// type GetInstanceTypeResult = Person

GetConstructorParameters

GetInstanceType 是提取构造器返回值类型,那同样也可以提取构造器的参数类型:

ts
type GetConstructorParameters<ConstructorType extends new (...args: any) => any> = ConstructorType extends new (
+  ...args: infer ParametersType
+) => any
+  ? ParametersType
+  : never;

类型参数 ConstructorType 为待处理的类型,通过 extends 约束为构造器类型。

用 ConstructorType 匹配一个模式类型,提取参数的部分到 infer 声明的局部变量 ParametersType 里,返回 ParametersType。

这样就能提取出构造器对应的参数类型:

ts
interface PersonConstructor {
+  new (name: string): Person;
+}
+
+type GetConstructorParametersResult = GetConstructorParameters<PersonConstructor>;
+// type GetConstructorParametersResult = [name:string]

索引类型

索引类型也同样可以用模式匹配提取某个索引的值的类型,这个用的也挺多的,比如 React 的 index.d.ts 里的 PropsWithRef 的高级类型,就是通过模式匹配提取了 ref 的值的类型:

ts
type PropsWithRef<P> = 'ref' extends keyof P
+  ? P extends { ref?: infer R | undefined }
+    ? string extends R
+      ? PropsWithRef<P> & { ref?: Exclude<R, string> | undefined }
+      : P
+    : P
+  : P;

我们简化一下那个高级类型,提取 Props 里 ref 的类型:

ts
type GetPropsRef<Props> = 'ref' extends keyof Props
+  ? Props extends { ref?: infer Value | undefined }
+    ? value
+    : never
+  : never;

类型参数 Props 为待处理的类型。

通过 keyof Props 取出 Props 的所有索引构成的联合类型,判断下 ref 是否在其中,也就是 'ref' extends keyof Props。

为什么要做这个判断,上面注释里写了:

在 ts3.0 里面如果没有对应的索引,Obj[Key] 返回的是 {} 而不是 never,所以这样做下兼容处理。

如果有 ref 这个索引的话,就通过 infer 提取 Value 的类型返回,否则返回 never。

ts
type GetPropsRefResult = GetPropsRef<{ ref: 1; name: 'str' }>;
+// type GetPropsRefResult = 1

当 ref 为 undefined 时:

ts
type GetPropsRefResult = GetPropsRef<{ ref: undefined; name: 'str' }>;
+// type GetPropsRefResult = undefined
`,145)]))}const F=i(n,[["render",k]]);export{y as __pageData,F as default}; diff --git a/assets/src_article_typescript_reconstruction.md.CPqflY5B.js b/assets/src_article_typescript_reconstruction.md.CPqflY5B.js new file mode 100644 index 0000000000..bf2a3cb09d --- /dev/null +++ b/assets/src_article_typescript_reconstruction.md.CPqflY5B.js @@ -0,0 +1,48 @@ +import{_ as i,o as a,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"重新构造做变换","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/typescript/reconstruction.md","filePath":"src/article/typescript/reconstruction.md","lastUpdated":1726550590000}'),k={name:"src/article/typescript/reconstruction.md"};function n(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t(`

重新构造做变换

类型编程主要的目的就是对类型做各种转换,那么如何对类型做修改呢?

TypeScript 类型系统支持 3 种可以声明任意类型的变量:type、infer、类型参数。

type 叫做类型别名,其实就是声明一个变量存储某个类型:

ts
type ttt = Promise<number>;

infer 用于类型的提取,然后存到一个变量里,相当于局部变量:

ts
type GetValueType<P> = P extends Promise<infer Value> ? Value : never;

类型参数用于接受具体的类型,在类型运算中也相当于局部变量:

ts
type isTwo<T> = T extends 2 ? true : false;

但是,严格来说这三种也都不叫变量,因为它们不能被重新赋值。

TypeScript 设计可以做类型编程的类型系统的目的就是为了产生各种复杂的类型,那不能修改怎么产生新类型呢?

答案是重新构造。

这就涉及到了第二个类型体操套路:重新构造做变换。

重新构造

TypeScript 的 type、infer、类型参数声明的变量都不能修改,想对类型做各种变换产生新的类型就需要重新构造。

数组、字符串、函数等类型的重新构造比较简单。

索引类型,也就是多个元素的聚合类型的重新构造复杂一些,涉及到了映射类型的语法。

我们先从简单的开始:

数组类型的重新构造

Push

有这样一个元组类型:

ts
type tuple = [1, 2, 3];

我想给这个元组类型再添加一些类型,怎么做呢?

TypeScript 类型变量不支持修改,我们可以构造一个新的元组类型:

ts
type Push<Arr extends unknown[], Ele> = [...Arr, Ele];

类型参数 Arr 是要修改的数组/元组类型,元素的类型任意,也就是 unknown。

类型参数 Ele 是添加的元素的类型。

返回的是用 Arr 已有的元素加上 Ele 构造的新的元组类型。

ts
type PushResult = Push<[1, 2, 3], 4>;
+// type PushResult = [1,2,3,4]

这就是数组/元组的重新构造。

数组和元组的区别:数组类型是指任意多个同一类型的元素构成的,比如 number[]Array<number>,而元组则是数量固定,类型可以不同的元素构成的,比如 [1, true, 'name']

Unshift

可以在后面添加,同样也可以在前面添加:

ts
type Unshift<Arr extends unknown[], Ele> = [Ele, ...Arr];

Zip

有这样两个元组:

ts
type tuple1 = [1, 2];
+type tuple2 = ['name', 'value'];

我们想把它们合并成这样的元组:

ts
type tuple = [[1, 'name'], [2, 'value']];

思路很容易想到,提取元组中的两个元素,构造成新的元组:

ts
type Zip<One extends [unknown, unknown], Other extends [unknown, unknown]> = One extends [
+  infer OneFirst,
+  infer OneSecond,
+]
+  ? Other extends [infer OtherFirst, infer OtherSecond]
+    ? [[OneFirst, OtherFirst], [OneSecond, OtherSecond]]
+    : []
+  : [];

两个类型参数 One、Other 是两个元组,类型是 [unknown, unknown],代表 2 个任意类型的元素构成的元组。

通过 infer 分别提取 One 和 Other 的元素到 infer 声明的局部变量 OneFirst、OneSecond、OtherFirst、OtherSecond 里。

用提取的元素构造成新的元组返回即可:

ts
type ZipResult = Zip<[1, 2], ['name', 'value']>;
+// type ZipResult = [[1, 'name'], [2, 'value']];

但是这样只能合并两个元素的元组,如果是任意个呢?

那就得用递归了:

ts
type Zip<One extends unknown[], Other extends unknown[]> = One extends [infer OneFirst, ...infer OneRest]
+  ? Other extends [infer OtherFirst, ...infer OtherRest]
+    ? [[OneFirst, OtherFirst], ...Zip<OneRest, OtherRest>]
+    : []
+  : [];

类型参数 One、Other 声明为 unknown[],也就是元素个数任意,类型任意的数组。

每次提取 One 和 Other 的第一个元素 OneFirst、OtherFirst,剩余的放到 OneRest、OtherRest 里。

用 OneFirst、OtherFirst 构造成新的元组的一个元素,剩余元素继续递归处理 OneRest、OtherRest。

这样,就能处理任意个数元组的合并:

ts
type ZipResult = Zip<[1, 2, 3, 4, 5], ['name', 'value', 'three', 'four', 'five']>;
+// type ZipResult = [[1, 'name'], [2, 'value'], [3, 'three'], [4, 'four'], [5, 'five']];

了解了数组类型的重新构造,我们再来看下字符串类型的:

字符串类型的重新构造

CapitalizeStr

我们想把一个字符串字面量类型的 'guang' 转为首字母大写的 'Guang'。

需要用到字符串类型的提取和重新构造:

ts
type CapitalizeStr<Str extends string> = Str extends \`\${infer First}\${infer Rest}\` ? \`\${Uppercase<First>}\${Rest}\` : Str;

我们声明了类型参数 Str 是要处理的字符串类型,通过 extends 约束为 string。

通过 infer 提取出首个字符到局部变量 First,提取后面的字符到局部变量 Rest。

然后使用 TypeScript 提供的内置高级类型 Uppercase 把首字母转为大写,加上 Rest,构造成新的字符串类型返回。

这就是字符串类型的重新构造:从已有的字符串类型中提取出一些部分字符串,经过一系列变换,构造成新的字符串类型。

CamelCase

我们再来实现 dong_dong_dong 到 dongDongDong 的变换。

同样是提取和重新构造:

ts
type CamelCase<Str extends string> = Str extends \`\${infer Left}_\${infer Right}\${infer Rest}\`
+  ? \`\${Left}\${Uppercase<Right>}\${CamelCase<Rest>}\`
+  : Str;

类型参数 Str 是待处理的字符串类型,约束为 string。

提取 _ 之前和之后的两个字符到 infer 声明的局部变量 Left 和 Right,剩下的字符放到 Rest 里。

然后把右边的字符 Right 大写,和 Left 构造成新的字符串,剩余的字符 Rest 要继续递归的处理。

这样就完成了从下划线到驼峰形式的转换:

DropSubStr

可以修改自然也可以删除,我们再来做一个删除一段字符串的案例:删除字符串中的某个子串

ts
type DropSubStr<Str extends string, SubStr extends string> = Str extends \`\${infer Prefix}\${SubStr}\${infer Suffix}\`
+  ? DropSubStr<\`\${Prefix}\${Suffix}\`, SubStr>
+  : Str;

类型参数 Str 是待处理的字符串,SubStr 是要删除的字符串,都通过 extends 约束为 string 类型。

通过模式匹配提取 SubStr 之前和之后的字符串到 infer 声明的局部变量 Prefix、Suffix 中。

如果不匹配就直接返回 Str。

如果匹配,那就用 Prefix、Suffix 构造成新的字符串,然后继续递归删除 SubStr。直到不再匹配,也就是没有 SubStr 了。

字符串类型的重新构造之后,我们再来看下函数类型的重新构造:

函数类型的重新构造

AppendArgument

之前我们分别实现了参数和返回值的提取,那么重新构造就是用这些提取出的类型做下修改,构造一个新的类型即可。

比如在已有的函数类型上添加一个参数:

ts
type AppendArgument<Func extends Function, Arg> = Func extends (...args: infer Args) => infer ReturnType
+  ? (...args: [...Args, Arg]) => ReturnType
+  : never;

类型参数 Func 是待处理的函数类型,通过 extends 约束为 Function,Arg 是要添加的参数类型。

通过模式匹配提取参数到 infer 声明的局部变量 Args 中,提取返回值到局部变量 ReturnType 中。

用 Args 数组添加 Arg 构造成新的参数类型,结合 ReturnType 构造成新的函数类型返回。

这样就完成了函数类型的修改:

最后,我们再来看下索引类型的重新构造

索引类型的重新构造

索引类型是聚合多个元素的类型,class、对象等都是索引类型,比如这就是一个索引类型:

ts
type obj = {
+  name: string;
+  age: number;
+  gender: boolean;
+};

索引类型可以添加修饰符 readonly(只读)、?(可选):

ts
type obj = {
+  readonly name: string;
+  age?: number;
+  gender: boolean;
+};

对它的修改和构造新类型涉及到了映射类型的语法:

ts
type Mapping<Obj extends object> = {
+  [Key in keyof Obj]: Obj[Key];
+};

Mapping

映射的过程中可以对 value 做下修改,比如:

ts
type Mapping<Obj extends object> = {
+  [Key in keyof Obj]: [Obj[Key], Obj[Key], Obj[Key]];
+};

类型参数 Obj 是待处理的索引类型,通过 extends 约束为 object。

用 keyof 取出 Obj 的索引,作为新的索引类型的索引,也就是 Key in keyof Obj。

值的类型可以做变换,这里我们用之前索引类型的值 Obj[Key] 构造成了三个元素的元组类型 [Obj[Key], Obj[Key], Obj[Key]]:

UppercaseKey

除了可以对 Value 做修改,也可以对 Key 做修改,使用 as,这叫做重映射:

比如把索引类型的 Key 变为大写。

ts
type UppercaseKey<Obj extends object> = {
+  [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key];
+};

类型参数 Obj 是待处理的索引类型,通过 extends 约束为 object。

新的索引类型的索引为 Obj 中的索引,也就是 Key in keyof Obj,但要做一些变换,也就是 as 之后的。

通过 Uppercase 把索引 Key 转为大写,因为索引可能为 string、number、symbol 类型,而这里只能接受 string 类型,所以要 & string,也就是取索引中 string 的部分。

value 保持不变,也就是之前的索引 Key 对应的值的类型 Obj[Key]。

这样构造出的新的索引类型,就把原来索引类型的索引转为了大写:

Record

TypeScript 提供了内置的高级类型 Record 来创建索引类型:

ts
type Record<K extends string | number | symbol, T> = { [P in K]: T };

指定索引和值的类型分别为 K 和 T,就可以创建一个对应的索引类型。

上面的索引类型的约束我们用的 object,其实更语义化一点我推荐用 Record<string, any>:

ts
type UppercaseKey<Obj extends Record<string, any>> = {
+  [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key];
+};

也就是约束类型参数 Obj 为 key 为 string,值为任意类型的索引类型。

ToReadonly

索引类型的索引可以添加 readonly 的修饰符,代表只读。

那我们就可以实现给索引类型添加 readonly 修饰的高级类型:

ts
type ToReadonly<T> = {
+  readonly [Key in keyof T]: T[Key];
+};

通过映射类型构造了新的索引类型,给索引加上了 readonly 的修饰,其余的保持不变,索引依然为原来的索引 Key in keyof T,值依然为原来的值 T[Key]。

ToPartial

同理,索引类型还可以添加可选修饰符:

ts
type ToPartial<T> = {
+  [Key in keyof T]?: T[Key];
+};

给索引类型 T 的索引添加了 ? 可选修饰符,其余保持不变。

ToMutable

可以添加 readonly 修饰,当然也可以去掉:

ts
type ToMutable<T> = {
+  -readonly [Key in keyof T]: T[Key];
+};

给索引类型 T 的每个索引去掉 readonly 的修饰,其余保持不变。

ToRequired

同理,也可以去掉可选修饰符:

ts
type ToRequired<T> = {
+  [Key in keyof T]-?: T[Key];
+};

给索引类型 T 的索引去掉 ? 的修饰,其余保持不变。

FilterByValueType

可以在构造新索引类型的时候根据值的类型做下过滤:

ts
type FilterByValueType<Obj extends Record<string, any>, ValueType> = {
+  [Key in keyof Obj as Obj[Key] extends ValueType ? Key : never]: Obj[Key];
+};

类型参数 Obj 为要处理的索引类型,通过 extends 约束为索引为 string,值为任意类型的索引类型 Record<string, any>。

类型参数 ValueType 为要过滤出的值的类型。

构造新的索引类型,索引为 Obj 的索引,也就是 Key in keyof Obj,但要做一些变换,也就是 as 之后的部分。

如果原来索引的值 Obj[Key] 是 ValueType 类型,索引依然为之前的索引 Key,否则索引设置为 never,never 的索引会在生成新的索引类型时被去掉。

值保持不变,依然为原来索引的值,也就是 Obj[Key]。

这样就达到了过滤索引类型的索引,产生新的索引类型的目的:

`,144)]))}const y=i(k,[["render",n]]);export{E as __pageData,y as default}; diff --git a/assets/src_article_typescript_reconstruction.md.CPqflY5B.lean.js b/assets/src_article_typescript_reconstruction.md.CPqflY5B.lean.js new file mode 100644 index 0000000000..bf2a3cb09d --- /dev/null +++ b/assets/src_article_typescript_reconstruction.md.CPqflY5B.lean.js @@ -0,0 +1,48 @@ +import{_ as i,o as a,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"重新构造做变换","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/typescript/reconstruction.md","filePath":"src/article/typescript/reconstruction.md","lastUpdated":1726550590000}'),k={name:"src/article/typescript/reconstruction.md"};function n(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t(`

重新构造做变换

类型编程主要的目的就是对类型做各种转换,那么如何对类型做修改呢?

TypeScript 类型系统支持 3 种可以声明任意类型的变量:type、infer、类型参数。

type 叫做类型别名,其实就是声明一个变量存储某个类型:

ts
type ttt = Promise<number>;

infer 用于类型的提取,然后存到一个变量里,相当于局部变量:

ts
type GetValueType<P> = P extends Promise<infer Value> ? Value : never;

类型参数用于接受具体的类型,在类型运算中也相当于局部变量:

ts
type isTwo<T> = T extends 2 ? true : false;

但是,严格来说这三种也都不叫变量,因为它们不能被重新赋值。

TypeScript 设计可以做类型编程的类型系统的目的就是为了产生各种复杂的类型,那不能修改怎么产生新类型呢?

答案是重新构造。

这就涉及到了第二个类型体操套路:重新构造做变换。

重新构造

TypeScript 的 type、infer、类型参数声明的变量都不能修改,想对类型做各种变换产生新的类型就需要重新构造。

数组、字符串、函数等类型的重新构造比较简单。

索引类型,也就是多个元素的聚合类型的重新构造复杂一些,涉及到了映射类型的语法。

我们先从简单的开始:

数组类型的重新构造

Push

有这样一个元组类型:

ts
type tuple = [1, 2, 3];

我想给这个元组类型再添加一些类型,怎么做呢?

TypeScript 类型变量不支持修改,我们可以构造一个新的元组类型:

ts
type Push<Arr extends unknown[], Ele> = [...Arr, Ele];

类型参数 Arr 是要修改的数组/元组类型,元素的类型任意,也就是 unknown。

类型参数 Ele 是添加的元素的类型。

返回的是用 Arr 已有的元素加上 Ele 构造的新的元组类型。

ts
type PushResult = Push<[1, 2, 3], 4>;
+// type PushResult = [1,2,3,4]

这就是数组/元组的重新构造。

数组和元组的区别:数组类型是指任意多个同一类型的元素构成的,比如 number[]Array<number>,而元组则是数量固定,类型可以不同的元素构成的,比如 [1, true, 'name']

Unshift

可以在后面添加,同样也可以在前面添加:

ts
type Unshift<Arr extends unknown[], Ele> = [Ele, ...Arr];

Zip

有这样两个元组:

ts
type tuple1 = [1, 2];
+type tuple2 = ['name', 'value'];

我们想把它们合并成这样的元组:

ts
type tuple = [[1, 'name'], [2, 'value']];

思路很容易想到,提取元组中的两个元素,构造成新的元组:

ts
type Zip<One extends [unknown, unknown], Other extends [unknown, unknown]> = One extends [
+  infer OneFirst,
+  infer OneSecond,
+]
+  ? Other extends [infer OtherFirst, infer OtherSecond]
+    ? [[OneFirst, OtherFirst], [OneSecond, OtherSecond]]
+    : []
+  : [];

两个类型参数 One、Other 是两个元组,类型是 [unknown, unknown],代表 2 个任意类型的元素构成的元组。

通过 infer 分别提取 One 和 Other 的元素到 infer 声明的局部变量 OneFirst、OneSecond、OtherFirst、OtherSecond 里。

用提取的元素构造成新的元组返回即可:

ts
type ZipResult = Zip<[1, 2], ['name', 'value']>;
+// type ZipResult = [[1, 'name'], [2, 'value']];

但是这样只能合并两个元素的元组,如果是任意个呢?

那就得用递归了:

ts
type Zip<One extends unknown[], Other extends unknown[]> = One extends [infer OneFirst, ...infer OneRest]
+  ? Other extends [infer OtherFirst, ...infer OtherRest]
+    ? [[OneFirst, OtherFirst], ...Zip<OneRest, OtherRest>]
+    : []
+  : [];

类型参数 One、Other 声明为 unknown[],也就是元素个数任意,类型任意的数组。

每次提取 One 和 Other 的第一个元素 OneFirst、OtherFirst,剩余的放到 OneRest、OtherRest 里。

用 OneFirst、OtherFirst 构造成新的元组的一个元素,剩余元素继续递归处理 OneRest、OtherRest。

这样,就能处理任意个数元组的合并:

ts
type ZipResult = Zip<[1, 2, 3, 4, 5], ['name', 'value', 'three', 'four', 'five']>;
+// type ZipResult = [[1, 'name'], [2, 'value'], [3, 'three'], [4, 'four'], [5, 'five']];

了解了数组类型的重新构造,我们再来看下字符串类型的:

字符串类型的重新构造

CapitalizeStr

我们想把一个字符串字面量类型的 'guang' 转为首字母大写的 'Guang'。

需要用到字符串类型的提取和重新构造:

ts
type CapitalizeStr<Str extends string> = Str extends \`\${infer First}\${infer Rest}\` ? \`\${Uppercase<First>}\${Rest}\` : Str;

我们声明了类型参数 Str 是要处理的字符串类型,通过 extends 约束为 string。

通过 infer 提取出首个字符到局部变量 First,提取后面的字符到局部变量 Rest。

然后使用 TypeScript 提供的内置高级类型 Uppercase 把首字母转为大写,加上 Rest,构造成新的字符串类型返回。

这就是字符串类型的重新构造:从已有的字符串类型中提取出一些部分字符串,经过一系列变换,构造成新的字符串类型。

CamelCase

我们再来实现 dong_dong_dong 到 dongDongDong 的变换。

同样是提取和重新构造:

ts
type CamelCase<Str extends string> = Str extends \`\${infer Left}_\${infer Right}\${infer Rest}\`
+  ? \`\${Left}\${Uppercase<Right>}\${CamelCase<Rest>}\`
+  : Str;

类型参数 Str 是待处理的字符串类型,约束为 string。

提取 _ 之前和之后的两个字符到 infer 声明的局部变量 Left 和 Right,剩下的字符放到 Rest 里。

然后把右边的字符 Right 大写,和 Left 构造成新的字符串,剩余的字符 Rest 要继续递归的处理。

这样就完成了从下划线到驼峰形式的转换:

DropSubStr

可以修改自然也可以删除,我们再来做一个删除一段字符串的案例:删除字符串中的某个子串

ts
type DropSubStr<Str extends string, SubStr extends string> = Str extends \`\${infer Prefix}\${SubStr}\${infer Suffix}\`
+  ? DropSubStr<\`\${Prefix}\${Suffix}\`, SubStr>
+  : Str;

类型参数 Str 是待处理的字符串,SubStr 是要删除的字符串,都通过 extends 约束为 string 类型。

通过模式匹配提取 SubStr 之前和之后的字符串到 infer 声明的局部变量 Prefix、Suffix 中。

如果不匹配就直接返回 Str。

如果匹配,那就用 Prefix、Suffix 构造成新的字符串,然后继续递归删除 SubStr。直到不再匹配,也就是没有 SubStr 了。

字符串类型的重新构造之后,我们再来看下函数类型的重新构造:

函数类型的重新构造

AppendArgument

之前我们分别实现了参数和返回值的提取,那么重新构造就是用这些提取出的类型做下修改,构造一个新的类型即可。

比如在已有的函数类型上添加一个参数:

ts
type AppendArgument<Func extends Function, Arg> = Func extends (...args: infer Args) => infer ReturnType
+  ? (...args: [...Args, Arg]) => ReturnType
+  : never;

类型参数 Func 是待处理的函数类型,通过 extends 约束为 Function,Arg 是要添加的参数类型。

通过模式匹配提取参数到 infer 声明的局部变量 Args 中,提取返回值到局部变量 ReturnType 中。

用 Args 数组添加 Arg 构造成新的参数类型,结合 ReturnType 构造成新的函数类型返回。

这样就完成了函数类型的修改:

最后,我们再来看下索引类型的重新构造

索引类型的重新构造

索引类型是聚合多个元素的类型,class、对象等都是索引类型,比如这就是一个索引类型:

ts
type obj = {
+  name: string;
+  age: number;
+  gender: boolean;
+};

索引类型可以添加修饰符 readonly(只读)、?(可选):

ts
type obj = {
+  readonly name: string;
+  age?: number;
+  gender: boolean;
+};

对它的修改和构造新类型涉及到了映射类型的语法:

ts
type Mapping<Obj extends object> = {
+  [Key in keyof Obj]: Obj[Key];
+};

Mapping

映射的过程中可以对 value 做下修改,比如:

ts
type Mapping<Obj extends object> = {
+  [Key in keyof Obj]: [Obj[Key], Obj[Key], Obj[Key]];
+};

类型参数 Obj 是待处理的索引类型,通过 extends 约束为 object。

用 keyof 取出 Obj 的索引,作为新的索引类型的索引,也就是 Key in keyof Obj。

值的类型可以做变换,这里我们用之前索引类型的值 Obj[Key] 构造成了三个元素的元组类型 [Obj[Key], Obj[Key], Obj[Key]]:

UppercaseKey

除了可以对 Value 做修改,也可以对 Key 做修改,使用 as,这叫做重映射:

比如把索引类型的 Key 变为大写。

ts
type UppercaseKey<Obj extends object> = {
+  [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key];
+};

类型参数 Obj 是待处理的索引类型,通过 extends 约束为 object。

新的索引类型的索引为 Obj 中的索引,也就是 Key in keyof Obj,但要做一些变换,也就是 as 之后的。

通过 Uppercase 把索引 Key 转为大写,因为索引可能为 string、number、symbol 类型,而这里只能接受 string 类型,所以要 & string,也就是取索引中 string 的部分。

value 保持不变,也就是之前的索引 Key 对应的值的类型 Obj[Key]。

这样构造出的新的索引类型,就把原来索引类型的索引转为了大写:

Record

TypeScript 提供了内置的高级类型 Record 来创建索引类型:

ts
type Record<K extends string | number | symbol, T> = { [P in K]: T };

指定索引和值的类型分别为 K 和 T,就可以创建一个对应的索引类型。

上面的索引类型的约束我们用的 object,其实更语义化一点我推荐用 Record<string, any>:

ts
type UppercaseKey<Obj extends Record<string, any>> = {
+  [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key];
+};

也就是约束类型参数 Obj 为 key 为 string,值为任意类型的索引类型。

ToReadonly

索引类型的索引可以添加 readonly 的修饰符,代表只读。

那我们就可以实现给索引类型添加 readonly 修饰的高级类型:

ts
type ToReadonly<T> = {
+  readonly [Key in keyof T]: T[Key];
+};

通过映射类型构造了新的索引类型,给索引加上了 readonly 的修饰,其余的保持不变,索引依然为原来的索引 Key in keyof T,值依然为原来的值 T[Key]。

ToPartial

同理,索引类型还可以添加可选修饰符:

ts
type ToPartial<T> = {
+  [Key in keyof T]?: T[Key];
+};

给索引类型 T 的索引添加了 ? 可选修饰符,其余保持不变。

ToMutable

可以添加 readonly 修饰,当然也可以去掉:

ts
type ToMutable<T> = {
+  -readonly [Key in keyof T]: T[Key];
+};

给索引类型 T 的每个索引去掉 readonly 的修饰,其余保持不变。

ToRequired

同理,也可以去掉可选修饰符:

ts
type ToRequired<T> = {
+  [Key in keyof T]-?: T[Key];
+};

给索引类型 T 的索引去掉 ? 的修饰,其余保持不变。

FilterByValueType

可以在构造新索引类型的时候根据值的类型做下过滤:

ts
type FilterByValueType<Obj extends Record<string, any>, ValueType> = {
+  [Key in keyof Obj as Obj[Key] extends ValueType ? Key : never]: Obj[Key];
+};

类型参数 Obj 为要处理的索引类型,通过 extends 约束为索引为 string,值为任意类型的索引类型 Record<string, any>。

类型参数 ValueType 为要过滤出的值的类型。

构造新的索引类型,索引为 Obj 的索引,也就是 Key in keyof Obj,但要做一些变换,也就是 as 之后的部分。

如果原来索引的值 Obj[Key] 是 ValueType 类型,索引依然为之前的索引 Key,否则索引设置为 never,never 的索引会在生成新的索引类型时被去掉。

值保持不变,依然为原来索引的值,也就是 Obj[Key]。

这样就达到了过滤索引类型的索引,产生新的索引类型的目的:

`,144)]))}const y=i(k,[["render",n]]);export{E as __pageData,y as default}; diff --git a/assets/src_article_typescript_recursion.md.Vf30DC2k.js b/assets/src_article_typescript_recursion.md.Vf30DC2k.js new file mode 100644 index 0000000000..e1578e2a74 --- /dev/null +++ b/assets/src_article_typescript_recursion.md.Vf30DC2k.js @@ -0,0 +1,65 @@ +import{_ as i,o as a,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"递归复用","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/typescript/recursion.md","filePath":"src/article/typescript/recursion.md","lastUpdated":1726550590000}'),n={name:"src/article/typescript/recursion.md"};function t(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k(`

递归复用

递归是把问题分解为一系列相似的小问题,通过函数不断调用自身来解决这一个个小问题,直到满足结束条件,就完成了问题的求解。

TypeScript 的高级类型支持类型参数,可以做各种类型运算逻辑,返回新的类型,和函数调用是对应的,自然也支持递归。

TypeScript 类型系统不支持循环,但支持递归。当处理数量(个数、长度、层数)不固定的类型的时候,可以只处理一个类型,然后递归的调用自身处理下一个类型,直到结束条件也就是所有的类型都处理完了,就完成了不确定数量的类型编程,达到循环的效果。

既然提到了数组、字符串、对象等类型,那么我们就来看一下这些类型的递归案例吧。

Promise 的递归复用

DeepPromiseValueType

先用 Promise 热热身,实现一个提取不确定层数的 Promise 中的 value 类型的高级类型。

ts
type ttt = Promise<Promise<Promise<Record<string, any>>>>;

这里是 3 层 Promise,value 类型是索引类型。

数量不确定,一涉及到这个就要想到用递归来做,每次只处理一层的提取,然后剩下的到下次递归做,直到结束条件。

所以高级类型是这样的:

ts
type DeepPromiseValueType<P extends Promise<unknown>> =
+  P extends Promise<infer ValueType>
+    ? ValueType extends Promise<unknown>
+      ? DeepPromiseValueType<ValueType>
+      : ValueType
+    : never;

类型参数 P 是待处理的 Promise,通过 extends 约束为 Promise 类型,value 类型不确定,设为 unknown。

每次只处理一个类型的提取,也就是通过模式匹配提取出 value 的类型到 infer 声明的局部变量 ValueType 中。

然后判断如果 ValueType 依然是 Promise 类型,就递归处理。

结束条件就是 ValueType 不为 Promise 类型,那就处理完了所有的层数,返回这时的 ValueType。

这样,我们就提取到了最里层的 Promise 的 value 类型,也就是索引类型:

其实这个类型的实现可以进一步的简化:

ts
type DeepPromiseValueType2<T> = T extends Promise<infer ValueType> ? DeepPromiseValueType2<ValueType> : T;

不再约束类型参数必须是 Promise,这样就可以少一层判断。

接下来再看下数组类型的递归复用:

数组类型的递归

ReverseArr

有这样一个元组类型:

ts
type arr = [1, 2, 3, 4, 5];

我们把它反过来,也就是变成:

ts
type arr = [5, 4, 3, 2, 1];

这个学完了提取和构造很容易写出来:

ts
type ReverseArr<Arr extends unknown[]> = Arr extends [infer One, infer Two, infer Three, infer Four, infer Five]
+  ? [Five, Four, Three, Two, One]
+  : never;

但如果数组长度不确定呢?

数量不确定,条件反射的就要想到递归。

我们每次只处理一个类型,剩下的递归做,直到满足结束条件。

ts
type ReverseArr<Arr extends unknown[]> = Arr extends [infer First, ...infer Rest] ? [...ReverseArr<Rest>, First] : Arr;

类型参数 Arr 为待处理的数组类型,元素类型不确定,也就是 unknown。

每次只处理一个元素的提取,放到 infer 声明的局部变量 First 里,剩下的放到 Rest 里。

用 First 作为最后一个元素构造新数组,其余元素递归的取。

结束条件就是取完所有的元素,也就是不再满足模式匹配的条件,这时候就返回 Arr。

Includes

既然递归可以做循环用,那么像查找元素这种自然也就可以实现。

比如查找 [1, 2, 3, 4, 5] 中是否存在 4,是就返回 true,否则返回 false。

从长度不固定的数组中查找某个元素,数量不确定,这时候就应该想到递归。

ts
type Includes<Arr extends unknown[], FindItem> = Arr extends [infer First, ...infer Rest]
+  ? IsEqual<First, FindItem> extends true
+    ? true
+    : Includes<Rest, FindItem>
+  : false;
+
+type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

类型参数 Arr 是待查找的数组类型,元素类型任意,也就是 unknown。FindItem 待查找的元素类型。

每次提取一个元素到 infer 声明的局部变量 First 中,剩余的放到局部变量 Rest。

判断 First 是否是要查找的元素,也就是和 FindItem 相等,是的话就返回 true,否则继续递归判断下一个元素。

直到结束条件也就是提取不出下一个元素,这时返回 false。

相等的判断就是 A 是 B 的子类型并且 B 也是 A 的子类型,。

这样就完成了不确定长度的数组中的元素查找,用递归实现了循环。

RemoveItem

可以查找自然就可以删除,只需要改下返回结果,构造一个新的数组返回。

ts
type RemoveItem<Arr extends unknown[], Item, Result extends unknown[] = []> = Arr extends [infer First, ...infer Rest]
+  ? IsEqual<First, Item> extends true
+    ? RemoveItem<Rest, Item, Result>
+    : RemoveItem<Rest, Item, [...Result, First]>
+  : Result;
+
+type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

类型参数 Arr 是待处理的数组,元素类型任意,也就是 unknown[]。类型参数 Item 为待查找的元素类型。类型参数 Result 是构造出的新数组,默认值是 []。

通过模式匹配提取数组中的一个元素的类型,如果是 Item 类型的话就删除,也就是不放入构造的新数组,直接返回之前的 Result。

否则放入构造的新数组,也就是再构造一个新的数组 [...Result, First]。

直到模式匹配不再满足,也就是处理完了所有的元素,返回这时候的 Result。

这样我们就完成了不确定元素个数的数组的某个元素的删除:

BuildArray

我们学过数组类型的构造,如果构造的数组类型元素个数不确定,也需要递归。

比如传入 5 和元素类型,构造一个长度为 5 的该元素类型构成的数组。

ts
type BuildArray<Length extends number, Ele = unknown, Arr extends unknown[] = []> = Arr['length'] extends Length
+  ? Arr
+  : BuildArray<Length, Ele, [...Arr, Ele]>;

类型参数 Length 为数组长度,约束为 number。类型参数 Ele 为元素类型,默认值为 unknown。类型参数 Arr 为构造出的数组,默认值是 []。

每次判断下 Arr 的长度是否到了 Length,是的话就返回 Arr,否则在 Arr 上加一个元素,然后递归构造。

学完了数组类型的递归,我们再来看下字符串类型。

字符串类型的递归

ReplaceAll

学模式匹配的时候,我们实现过一个 Replace 的高级类型:

ts
type ReplaceStr<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends \`\${infer Prefix}\${From}\${infer Suffix}\` ? \`\${Prefix}\${To}\${Suffix}\` : Str;

它能把一个字符串中的某个字符替换成另一个:

但是如果有多个这样的字符就处理不了了。

如果不确定有多少个 From 字符,怎么处理呢?

在类型体操里,遇到数量不确定的问题,就要条件反射的想到递归。

每次递归只处理一个类型,这部分我们已经实现了,那么加上递归的调用就可以。

ts
type ReplaceAll<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends \`\${infer Left}\${From}\${infer Right}\` ? \`\${Left}\${To}\${ReplaceAll<Right, From, To>}\` : Str;

类型参数 Str 是待处理的字符串类型,From 是待替换的字符,To 是替换到的字符。

通过模式匹配提取 From 左右的字符串到 infer 声明的局部变量 Left 和 Right 里。

用 Left 和 To 构造新的字符串,剩余的 Right 部分继续递归的替换。

结束条件是不再满足模式匹配,也就是没有要替换的元素,这时就直接返回字符串 Str。

这样就实现了任意数量的字符串替换:

StringToUnion

我们想把字符串字面量类型的每个字符都提取出来组成联合类型,也就是把 'dong' 转为 'd' | 'o' | 'n' | 'g'。

怎么做呢?

很明显也是提取和构造:

ts
type StringToUnion<Str extends string> = Str extends \`\${infer One}\${infer Two}\${infer Three}\${infer Four}\`
+  ? One | Two | Three | Four
+  : never;

但如果字符串长度不确定呢?

数量不确定,在类型体操中就要条件反射的想到递归。

ts
type StringToUnion<Str extends string> = Str extends \`\${infer First}\${infer Rest}\`
+  ? First | StringToUnion<Rest>
+  : never;

类型参数 Str 为待处理的字符串类型,通过 extends 约束为 string。

通过模式匹配提取第一个字符到 infer 声明的局部变量 First,其余的字符放到局部变量 Rest。

用 First 构造联合类型,剩余的元素递归的取。

这样就完成了不确定长度的字符串的提取和联合类型的构造:

ReverseStr

我们实现了数组的反转,自然也可以实现字符串类型的反转。

同样是递归提取和构造。

ts
type ReverseStr<Str extends string, Result extends string = ''> = Str extends \`\${infer First}\${infer Rest}\`
+  ? ReverseStr<Rest, \`\${First}\${Result}\`>
+  : Result;

类型参数 Str 为待处理的字符串。类型参数 Result 为构造出的字符,默认值是空串。

通过模式匹配提取第一个字符到 infer 声明的局部变量 First,其余字符放到 Rest。

用 First 和之前的 Result 构造成新的字符串,把 First 放到前面,因为递归是从左到右处理,那么不断往前插就是把右边的放到了左边,完成了反转的效果。

直到模式匹配不满足,就处理完了所有的字符。

这样就完成了字符串的反转:

对象类型的递归

DeepReadonly

对象类型的递归,也可以叫做索引类型的递归。

我们之前实现了索引类型的映射,给索引加上了 readonly 的修饰:

ts
type ToReadonly<T> = {
+  readonly [Key in keyof T]: T[Key];
+};

如果这个索引类型层数不确定呢?

比如这样:

ts
type obj = {
+  a: {
+    b: {
+      c: {
+        f: () => 'dong';
+        d: {
+          e: {
+            guang: string;
+          };
+        };
+      };
+    };
+  };
+};

数量(层数)不确定,类型体操中应该自然的想到递归。

我们在之前的映射上加入递归的逻辑:

ts
type DeepReadonly<Obj extends Record<string, any>> = {
+  readonly [Key in keyof Obj]: Obj[Key] extends object
+    ? Obj[Key] extends Function
+      ? Obj[Key]
+      : DeepReadonly<Obj[Key]>
+    : Obj[Key];
+};

类型参数 Obj 是待处理的索引类型,约束为 Record<string, any>,也就是索引为 string,值为任意类型的索引类型。

索引映射自之前的索引,也就是 Key in keyof Obj,只不过加上了 readonly 的修饰。

值要做下判断,如果是 object 类型并且还是 Function,那么就直接取之前的值 Obj[Key]。

如果是 object 类型但不是 Function,那就是说也是一个索引类型,就递归处理 DeepReadonly<Obj[Key]>。

否则,值不是 object 就直接返回之前的值 Obj[Key]。

这样就完成了任意层数的索引类型的添加 readonly 修饰:

我们取处理以后的索引 a 的值看一下,发现 b 已经加上了 readonly 修饰。

测试一下:

为啥这里没有计算呀?

因为 ts 的类型只有被用到的时候才会做计算。

所以可以在前面加上一段 Obj extends never ? never 或者 Obj extends any 等,从而触发计算:

ts
type DeepReadonly<Obj extends Record<string, any>> = Obj extends any
+  ? {
+      readonly [Key in keyof Obj]: Obj[Key] extends object
+        ? Obj[Key] extends Function
+          ? Obj[Key]
+          : DeepReadonly<Obj[Key]>
+        : Obj[Key];
+    }
+  : never;
`,123)]))}const F=i(n,[["render",t]]);export{E as __pageData,F as default}; diff --git a/assets/src_article_typescript_recursion.md.Vf30DC2k.lean.js b/assets/src_article_typescript_recursion.md.Vf30DC2k.lean.js new file mode 100644 index 0000000000..e1578e2a74 --- /dev/null +++ b/assets/src_article_typescript_recursion.md.Vf30DC2k.lean.js @@ -0,0 +1,65 @@ +import{_ as i,o as a,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"递归复用","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/typescript/recursion.md","filePath":"src/article/typescript/recursion.md","lastUpdated":1726550590000}'),n={name:"src/article/typescript/recursion.md"};function t(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k(`

递归复用

递归是把问题分解为一系列相似的小问题,通过函数不断调用自身来解决这一个个小问题,直到满足结束条件,就完成了问题的求解。

TypeScript 的高级类型支持类型参数,可以做各种类型运算逻辑,返回新的类型,和函数调用是对应的,自然也支持递归。

TypeScript 类型系统不支持循环,但支持递归。当处理数量(个数、长度、层数)不固定的类型的时候,可以只处理一个类型,然后递归的调用自身处理下一个类型,直到结束条件也就是所有的类型都处理完了,就完成了不确定数量的类型编程,达到循环的效果。

既然提到了数组、字符串、对象等类型,那么我们就来看一下这些类型的递归案例吧。

Promise 的递归复用

DeepPromiseValueType

先用 Promise 热热身,实现一个提取不确定层数的 Promise 中的 value 类型的高级类型。

ts
type ttt = Promise<Promise<Promise<Record<string, any>>>>;

这里是 3 层 Promise,value 类型是索引类型。

数量不确定,一涉及到这个就要想到用递归来做,每次只处理一层的提取,然后剩下的到下次递归做,直到结束条件。

所以高级类型是这样的:

ts
type DeepPromiseValueType<P extends Promise<unknown>> =
+  P extends Promise<infer ValueType>
+    ? ValueType extends Promise<unknown>
+      ? DeepPromiseValueType<ValueType>
+      : ValueType
+    : never;

类型参数 P 是待处理的 Promise,通过 extends 约束为 Promise 类型,value 类型不确定,设为 unknown。

每次只处理一个类型的提取,也就是通过模式匹配提取出 value 的类型到 infer 声明的局部变量 ValueType 中。

然后判断如果 ValueType 依然是 Promise 类型,就递归处理。

结束条件就是 ValueType 不为 Promise 类型,那就处理完了所有的层数,返回这时的 ValueType。

这样,我们就提取到了最里层的 Promise 的 value 类型,也就是索引类型:

其实这个类型的实现可以进一步的简化:

ts
type DeepPromiseValueType2<T> = T extends Promise<infer ValueType> ? DeepPromiseValueType2<ValueType> : T;

不再约束类型参数必须是 Promise,这样就可以少一层判断。

接下来再看下数组类型的递归复用:

数组类型的递归

ReverseArr

有这样一个元组类型:

ts
type arr = [1, 2, 3, 4, 5];

我们把它反过来,也就是变成:

ts
type arr = [5, 4, 3, 2, 1];

这个学完了提取和构造很容易写出来:

ts
type ReverseArr<Arr extends unknown[]> = Arr extends [infer One, infer Two, infer Three, infer Four, infer Five]
+  ? [Five, Four, Three, Two, One]
+  : never;

但如果数组长度不确定呢?

数量不确定,条件反射的就要想到递归。

我们每次只处理一个类型,剩下的递归做,直到满足结束条件。

ts
type ReverseArr<Arr extends unknown[]> = Arr extends [infer First, ...infer Rest] ? [...ReverseArr<Rest>, First] : Arr;

类型参数 Arr 为待处理的数组类型,元素类型不确定,也就是 unknown。

每次只处理一个元素的提取,放到 infer 声明的局部变量 First 里,剩下的放到 Rest 里。

用 First 作为最后一个元素构造新数组,其余元素递归的取。

结束条件就是取完所有的元素,也就是不再满足模式匹配的条件,这时候就返回 Arr。

Includes

既然递归可以做循环用,那么像查找元素这种自然也就可以实现。

比如查找 [1, 2, 3, 4, 5] 中是否存在 4,是就返回 true,否则返回 false。

从长度不固定的数组中查找某个元素,数量不确定,这时候就应该想到递归。

ts
type Includes<Arr extends unknown[], FindItem> = Arr extends [infer First, ...infer Rest]
+  ? IsEqual<First, FindItem> extends true
+    ? true
+    : Includes<Rest, FindItem>
+  : false;
+
+type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

类型参数 Arr 是待查找的数组类型,元素类型任意,也就是 unknown。FindItem 待查找的元素类型。

每次提取一个元素到 infer 声明的局部变量 First 中,剩余的放到局部变量 Rest。

判断 First 是否是要查找的元素,也就是和 FindItem 相等,是的话就返回 true,否则继续递归判断下一个元素。

直到结束条件也就是提取不出下一个元素,这时返回 false。

相等的判断就是 A 是 B 的子类型并且 B 也是 A 的子类型,。

这样就完成了不确定长度的数组中的元素查找,用递归实现了循环。

RemoveItem

可以查找自然就可以删除,只需要改下返回结果,构造一个新的数组返回。

ts
type RemoveItem<Arr extends unknown[], Item, Result extends unknown[] = []> = Arr extends [infer First, ...infer Rest]
+  ? IsEqual<First, Item> extends true
+    ? RemoveItem<Rest, Item, Result>
+    : RemoveItem<Rest, Item, [...Result, First]>
+  : Result;
+
+type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

类型参数 Arr 是待处理的数组,元素类型任意,也就是 unknown[]。类型参数 Item 为待查找的元素类型。类型参数 Result 是构造出的新数组,默认值是 []。

通过模式匹配提取数组中的一个元素的类型,如果是 Item 类型的话就删除,也就是不放入构造的新数组,直接返回之前的 Result。

否则放入构造的新数组,也就是再构造一个新的数组 [...Result, First]。

直到模式匹配不再满足,也就是处理完了所有的元素,返回这时候的 Result。

这样我们就完成了不确定元素个数的数组的某个元素的删除:

BuildArray

我们学过数组类型的构造,如果构造的数组类型元素个数不确定,也需要递归。

比如传入 5 和元素类型,构造一个长度为 5 的该元素类型构成的数组。

ts
type BuildArray<Length extends number, Ele = unknown, Arr extends unknown[] = []> = Arr['length'] extends Length
+  ? Arr
+  : BuildArray<Length, Ele, [...Arr, Ele]>;

类型参数 Length 为数组长度,约束为 number。类型参数 Ele 为元素类型,默认值为 unknown。类型参数 Arr 为构造出的数组,默认值是 []。

每次判断下 Arr 的长度是否到了 Length,是的话就返回 Arr,否则在 Arr 上加一个元素,然后递归构造。

学完了数组类型的递归,我们再来看下字符串类型。

字符串类型的递归

ReplaceAll

学模式匹配的时候,我们实现过一个 Replace 的高级类型:

ts
type ReplaceStr<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends \`\${infer Prefix}\${From}\${infer Suffix}\` ? \`\${Prefix}\${To}\${Suffix}\` : Str;

它能把一个字符串中的某个字符替换成另一个:

但是如果有多个这样的字符就处理不了了。

如果不确定有多少个 From 字符,怎么处理呢?

在类型体操里,遇到数量不确定的问题,就要条件反射的想到递归。

每次递归只处理一个类型,这部分我们已经实现了,那么加上递归的调用就可以。

ts
type ReplaceAll<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends \`\${infer Left}\${From}\${infer Right}\` ? \`\${Left}\${To}\${ReplaceAll<Right, From, To>}\` : Str;

类型参数 Str 是待处理的字符串类型,From 是待替换的字符,To 是替换到的字符。

通过模式匹配提取 From 左右的字符串到 infer 声明的局部变量 Left 和 Right 里。

用 Left 和 To 构造新的字符串,剩余的 Right 部分继续递归的替换。

结束条件是不再满足模式匹配,也就是没有要替换的元素,这时就直接返回字符串 Str。

这样就实现了任意数量的字符串替换:

StringToUnion

我们想把字符串字面量类型的每个字符都提取出来组成联合类型,也就是把 'dong' 转为 'd' | 'o' | 'n' | 'g'。

怎么做呢?

很明显也是提取和构造:

ts
type StringToUnion<Str extends string> = Str extends \`\${infer One}\${infer Two}\${infer Three}\${infer Four}\`
+  ? One | Two | Three | Four
+  : never;

但如果字符串长度不确定呢?

数量不确定,在类型体操中就要条件反射的想到递归。

ts
type StringToUnion<Str extends string> = Str extends \`\${infer First}\${infer Rest}\`
+  ? First | StringToUnion<Rest>
+  : never;

类型参数 Str 为待处理的字符串类型,通过 extends 约束为 string。

通过模式匹配提取第一个字符到 infer 声明的局部变量 First,其余的字符放到局部变量 Rest。

用 First 构造联合类型,剩余的元素递归的取。

这样就完成了不确定长度的字符串的提取和联合类型的构造:

ReverseStr

我们实现了数组的反转,自然也可以实现字符串类型的反转。

同样是递归提取和构造。

ts
type ReverseStr<Str extends string, Result extends string = ''> = Str extends \`\${infer First}\${infer Rest}\`
+  ? ReverseStr<Rest, \`\${First}\${Result}\`>
+  : Result;

类型参数 Str 为待处理的字符串。类型参数 Result 为构造出的字符,默认值是空串。

通过模式匹配提取第一个字符到 infer 声明的局部变量 First,其余字符放到 Rest。

用 First 和之前的 Result 构造成新的字符串,把 First 放到前面,因为递归是从左到右处理,那么不断往前插就是把右边的放到了左边,完成了反转的效果。

直到模式匹配不满足,就处理完了所有的字符。

这样就完成了字符串的反转:

对象类型的递归

DeepReadonly

对象类型的递归,也可以叫做索引类型的递归。

我们之前实现了索引类型的映射,给索引加上了 readonly 的修饰:

ts
type ToReadonly<T> = {
+  readonly [Key in keyof T]: T[Key];
+};

如果这个索引类型层数不确定呢?

比如这样:

ts
type obj = {
+  a: {
+    b: {
+      c: {
+        f: () => 'dong';
+        d: {
+          e: {
+            guang: string;
+          };
+        };
+      };
+    };
+  };
+};

数量(层数)不确定,类型体操中应该自然的想到递归。

我们在之前的映射上加入递归的逻辑:

ts
type DeepReadonly<Obj extends Record<string, any>> = {
+  readonly [Key in keyof Obj]: Obj[Key] extends object
+    ? Obj[Key] extends Function
+      ? Obj[Key]
+      : DeepReadonly<Obj[Key]>
+    : Obj[Key];
+};

类型参数 Obj 是待处理的索引类型,约束为 Record<string, any>,也就是索引为 string,值为任意类型的索引类型。

索引映射自之前的索引,也就是 Key in keyof Obj,只不过加上了 readonly 的修饰。

值要做下判断,如果是 object 类型并且还是 Function,那么就直接取之前的值 Obj[Key]。

如果是 object 类型但不是 Function,那就是说也是一个索引类型,就递归处理 DeepReadonly<Obj[Key]>。

否则,值不是 object 就直接返回之前的值 Obj[Key]。

这样就完成了任意层数的索引类型的添加 readonly 修饰:

我们取处理以后的索引 a 的值看一下,发现 b 已经加上了 readonly 修饰。

测试一下:

为啥这里没有计算呀?

因为 ts 的类型只有被用到的时候才会做计算。

所以可以在前面加上一段 Obj extends never ? never 或者 Obj extends any 等,从而触发计算:

ts
type DeepReadonly<Obj extends Record<string, any>> = Obj extends any
+  ? {
+      readonly [Key in keyof Obj]: Obj[Key] extends object
+        ? Obj[Key] extends Function
+          ? Obj[Key]
+          : DeepReadonly<Obj[Key]>
+        : Obj[Key];
+    }
+  : never;
`,123)]))}const F=i(n,[["render",t]]);export{E as __pageData,F as default}; diff --git a/assets/src_article_typescript_unionType.md.BIrMmR2O.js b/assets/src_article_typescript_unionType.md.BIrMmR2O.js new file mode 100644 index 0000000000..58a3f027c9 --- /dev/null +++ b/assets/src_article_typescript_unionType.md.BIrMmR2O.js @@ -0,0 +1 @@ +import{_ as i,o as a,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"分布式条件类型","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/typescript/unionType.md","filePath":"src/article/typescript/unionType.md","lastUpdated":1726550590000}'),k={name:"src/article/typescript/unionType.md"};function n(p,s,l,e,d,r){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

分布式条件类型

当类型参数为联合类型,并且在条件类型左边直接引用该类型参数的时候,TypeScript 会把每一个元素单独传入来做类型运算,最后再合并成联合类型,这种语法叫做分布式条件类型。

比如这样一个联合类型:

ts
type Union = 'a' | 'b' | 'c';

我们想把其中的 a 大写,就可以这样写:

ts
type UppercaseA<Item extends string> = Item extends 'a' ? Uppercase<Item> : Item;
ts
type result = UppercaseA<Union>;\n// type result = 'A' | 'b' | 'c';

可以看到,我们类型参数 Item 约束为 string,条件类型的判断中也是判断是否是 a,但传入的是联合类型。

这就是 TypeScript 对联合类型在条件类型中使用时的特殊处理:会把联合类型的每一个元素单独传入做类型计算,最后合并。

这和联合类型遇到字符串时的处理一样:

这样确实是简化了类型编程逻辑的,不需要递归提取每个元素再处理。

TypeScript 之所以这样处理联合类型也很容易理解,因为联合类型的每个元素都是互不相关的,不像数组、索引、字符串那样元素之间是有关系的。所以设计成了每一个单独处理,最后合并。

知道了 TypeScript 怎么处理的联合类型,趁热打铁来练习一下:

CamelcaseUnion

Camelcase 我们实现过,就是提取字符串中的字符,首字母大写以后重新构造一个新的。

ts
type Camelcase<Str extends string> = Str extends `${infer Left}_${infer Right}${infer Rest}`\n  ? `${Left}${Uppercase<Right>}${Camelcase<Rest>}`\n  : Str;

提取 _ 左右的字符,把右边字符大写之后构造成新的字符串,余下的字符串递归处理。

ts
type CamelcaseResult = Camelcase<'aa_aa_aa'>;\n// type CamelcaseResult = 'aaAaAa'

如果是对字符串数组做 Camelcase,那就要递归处理每一个元素:

ts
type CamelcaseArr<Arr extends unknown[]> = Arr extends [infer Item, ...infer RestArr]\n  ? [Camelcase<Item & string>, ...CamelcaseArr<RestArr>]\n  : [];

类型参数 Arr 为待处理数组。

递归提取每一个元素做 Camelcase,因为 Camelcase 要求传入 string,这里要 & string 来变成 string 类型。

那如果是联合类型呢?

联合类型不需要递归提取每个元素,TypeScript 内部会把每一个元素传入单独做计算,之后把每个元素的计算结果合并成联合类型。

ts
type CamelcaseUnion<Item extends string> = Item extends `${infer Left}_${infer Right}${infer Rest}`\n  ? `${Left}${Uppercase<Right>}${CamelcaseUnion<Rest>}`\n  : Item;

这不和单个字符串的处理没区别么?

没错,对联合类型的处理和对单个类型的处理没什么区别,TypeScript 会把每个单独的类型拆开传入。不需要像数组类型那样需要递归提取每个元素做处理。

确实简化了很多,好像都是优点?

也不全是,其实这样处理也增加了一些认知成本,不信我们再来看个例子:

IsUnion

判断联合类型我们会这样写:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

当传入联合类型时,会返回 true:

ts
type IsUnionResult = IsUnion<'a' | 'b' 'c'>\n// type IsUnionResult = true

当传入其他类型时,会返回 false:

ts
type IsUnionResult = IsUnion<['a' | 'b' 'c']>\n// type IsUnionResult = false

这就是分布式条件类型带来的认知成本。

我们先来看这样一个类型:

ts
type TestUnion<A, B = A> = A extends A ? { a: A; b: B } : never;\n\ntype TestUnionResult = TestUnion<'a' | 'b' | 'c'>;

传入联合类型 'a' | 'b' | 'c' 的时候,结果是这样的:

A 和 B 都是同一个联合类型,为啥值还不一样呢?

因为条件类型中如果左边的类型是联合类型,会把每个元素单独传入做计算,而右边不会。

所以 A 是 'a' 的时候,B 是 'a' | 'b' | 'c',A 是 'b' 的时候,B 是 'a' | 'b' | 'c'。。。

那么利用这个特点就可以实现 Union 类型的判断:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

类型参数 A、B 是待判断的联合类型,B 默认值为 A,也就是同一个类型。

A extends A 这段看似没啥意义,主要是为了触发分布式条件类型,让 A 的每个类型单独传入。

[B] extends [A] 这样不直接写 B 就可以避免触发分布式条件类型,那么 B 就是整个联合类型。

B 是联合类型整体,而 A 是单个类型,自然不成立,而其它类型没有这种特殊处理,A 和 B 都是同一个,怎么判断都成立。

利用这个特点就可以判断出是否是联合类型。

其中有两个点比较困惑,我们重点记一下:

当 A 是联合类型时:

A extends A 这种写法是为了触发分布式条件类型,让每个类型单独传入处理的,没别的意义。

A extends A 和 [A] extends [A] 是不同的处理,前者是单个类型和整个类型做判断,后者两边都是整个联合类型,因为只有 extends 左边直接是类型参数才会触发分布式条件类型。

理解了这两点,分布式条件类型就算掌握了。

BEM

bem 是 css 命名规范,用 block__element--modifier 的形式来描述某个区块下面的某个元素的某个状态的样式。

那么我们可以写这样一个高级类型,传入 block、element、modifier,返回构造出的 class 名:

这样使用:

ts
type bemResult = BEM<'guang', ['aaa', 'bbb'], ['warning', 'success']>;

它的实现就是三部分的合并,但传入的是数组,要递归遍历取出每一个元素来和其他部分组合,这样太麻烦了。

而如果是联合类型就不用递归遍历了,因为联合类型遇到字符串也是会单独每个元素单独传入做处理。

数组转联合类型可以这样写:

ts
type union = ['aaa', 'bbb'][number];\n// type union = 'aaa' | 'bbb'

那么 BEM 就可以这样实现:

ts
type BEM<\n  Block extends string,\n  Element extends string[],\n  Modifiers extends string[],\n> = `${Block}__${Element[number]}--${Modifiers[number]}`;

类型参数 Block、Element、Modifiers 分别是 bem 规范的三部分,其中 Element 和 Modifiers 都可能多个,约束为 string[]。

构造一个字符串类型,其中 Element 和 Modifiers 通过索引访问来变为联合类型。

字符串类型中遇到联合类型的时候,会每个元素单独传入计算,也就是这样的效果:

ts
type RemResult = BEM<'a', ['b', 'c'], ['d', 'e']>;\n// type RemResult = 'a__b--d' | 'a__b--e' | 'a__c--d' | 'a__b--e'

可以看到,用好了联合类型,确实能简化类型编程逻辑。

AllCombinations

我们再来实现一个全组合的高级类型,也是联合类型相关的:

希望传入 'A' | 'B' 的时候,能够返回所有的组合: 'A' | 'B' | 'BA' | 'AB'。

这种全组合问题的实现思路就是两两组合,组合出的字符串再和其他字符串两两组和:

比如 'A' | 'B' | 'c',就是 A 和 B、C 组合,B 和 A、C 组合,C 和 A、B 组合。然后组合出来的字符串再和其他字符串组合。

任何两个类型的组合有四种:A、B、AB、BA

ts
type Combination<A extends string, B extends string> = A | B | `${A}${B}` | `${B}${A}`;

然后构造出来的字符串再和其他字符串组合。

所以全组合的高级类型就是这样:

ts
type AllCombinations<A extends string, B extends string = A> = A extends A\n  ? Combination<A, AllCombinations<Exclude<B, A>>>\n  : never;

类型参数 A、B 是待组合的两个联合类型,B 默认是 A 也就是同一个。

A extends A 的意义就是让联合类型每个类型单独传入做处理,上面我们刚学会。

A 的处理就是 A 和 B 中去掉 A 以后的所有类型组合,也就是 Combination<A, B 去掉 A 以后的所有组合>。

而 B 去掉 A 以后的所有组合就是 AllCombinations<Exclude<B, A>>,所以全组合就是 Combination<A, AllCombinations<Exclude<B, A>>>。

总结

联合类型中的每个类型都是相互独立的,TypeScript 对它做了特殊处理,也就是遇到字符串类型、条件类型的时候会把每个类型单独传入做计算,最后把每个类型的计算结果合并成联合类型。

条件类型左边是联合类型的时候就会触法这种处理,叫做分布式条件类型。

有两点特别要注意:

  • A extends A 不是没意义,意义是取出联合类型中的单个类型放入 A

  • A extends A 才是分布式条件类型, [A] extends [A] 就不是了,只有左边是单独的类型参数才可以。

我们后面做了一些案例,发现联合类型的这种 distributive 的特性确实能简化类型编程,但是也增加了认知成本,不过这也是不可避免的事。

',91)]))}const y=i(k,[["render",n]]);export{F as __pageData,y as default}; diff --git a/assets/src_article_typescript_unionType.md.BIrMmR2O.lean.js b/assets/src_article_typescript_unionType.md.BIrMmR2O.lean.js new file mode 100644 index 0000000000..58a3f027c9 --- /dev/null +++ b/assets/src_article_typescript_unionType.md.BIrMmR2O.lean.js @@ -0,0 +1 @@ +import{_ as i,o as a,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"分布式条件类型","description":"","frontmatter":{},"headers":[],"relativePath":"src/article/typescript/unionType.md","filePath":"src/article/typescript/unionType.md","lastUpdated":1726550590000}'),k={name:"src/article/typescript/unionType.md"};function n(p,s,l,e,d,r){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

分布式条件类型

当类型参数为联合类型,并且在条件类型左边直接引用该类型参数的时候,TypeScript 会把每一个元素单独传入来做类型运算,最后再合并成联合类型,这种语法叫做分布式条件类型。

比如这样一个联合类型:

ts
type Union = 'a' | 'b' | 'c';

我们想把其中的 a 大写,就可以这样写:

ts
type UppercaseA<Item extends string> = Item extends 'a' ? Uppercase<Item> : Item;
ts
type result = UppercaseA<Union>;\n// type result = 'A' | 'b' | 'c';

可以看到,我们类型参数 Item 约束为 string,条件类型的判断中也是判断是否是 a,但传入的是联合类型。

这就是 TypeScript 对联合类型在条件类型中使用时的特殊处理:会把联合类型的每一个元素单独传入做类型计算,最后合并。

这和联合类型遇到字符串时的处理一样:

这样确实是简化了类型编程逻辑的,不需要递归提取每个元素再处理。

TypeScript 之所以这样处理联合类型也很容易理解,因为联合类型的每个元素都是互不相关的,不像数组、索引、字符串那样元素之间是有关系的。所以设计成了每一个单独处理,最后合并。

知道了 TypeScript 怎么处理的联合类型,趁热打铁来练习一下:

CamelcaseUnion

Camelcase 我们实现过,就是提取字符串中的字符,首字母大写以后重新构造一个新的。

ts
type Camelcase<Str extends string> = Str extends `${infer Left}_${infer Right}${infer Rest}`\n  ? `${Left}${Uppercase<Right>}${Camelcase<Rest>}`\n  : Str;

提取 _ 左右的字符,把右边字符大写之后构造成新的字符串,余下的字符串递归处理。

ts
type CamelcaseResult = Camelcase<'aa_aa_aa'>;\n// type CamelcaseResult = 'aaAaAa'

如果是对字符串数组做 Camelcase,那就要递归处理每一个元素:

ts
type CamelcaseArr<Arr extends unknown[]> = Arr extends [infer Item, ...infer RestArr]\n  ? [Camelcase<Item & string>, ...CamelcaseArr<RestArr>]\n  : [];

类型参数 Arr 为待处理数组。

递归提取每一个元素做 Camelcase,因为 Camelcase 要求传入 string,这里要 & string 来变成 string 类型。

那如果是联合类型呢?

联合类型不需要递归提取每个元素,TypeScript 内部会把每一个元素传入单独做计算,之后把每个元素的计算结果合并成联合类型。

ts
type CamelcaseUnion<Item extends string> = Item extends `${infer Left}_${infer Right}${infer Rest}`\n  ? `${Left}${Uppercase<Right>}${CamelcaseUnion<Rest>}`\n  : Item;

这不和单个字符串的处理没区别么?

没错,对联合类型的处理和对单个类型的处理没什么区别,TypeScript 会把每个单独的类型拆开传入。不需要像数组类型那样需要递归提取每个元素做处理。

确实简化了很多,好像都是优点?

也不全是,其实这样处理也增加了一些认知成本,不信我们再来看个例子:

IsUnion

判断联合类型我们会这样写:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

当传入联合类型时,会返回 true:

ts
type IsUnionResult = IsUnion<'a' | 'b' 'c'>\n// type IsUnionResult = true

当传入其他类型时,会返回 false:

ts
type IsUnionResult = IsUnion<['a' | 'b' 'c']>\n// type IsUnionResult = false

这就是分布式条件类型带来的认知成本。

我们先来看这样一个类型:

ts
type TestUnion<A, B = A> = A extends A ? { a: A; b: B } : never;\n\ntype TestUnionResult = TestUnion<'a' | 'b' | 'c'>;

传入联合类型 'a' | 'b' | 'c' 的时候,结果是这样的:

A 和 B 都是同一个联合类型,为啥值还不一样呢?

因为条件类型中如果左边的类型是联合类型,会把每个元素单独传入做计算,而右边不会。

所以 A 是 'a' 的时候,B 是 'a' | 'b' | 'c',A 是 'b' 的时候,B 是 'a' | 'b' | 'c'。。。

那么利用这个特点就可以实现 Union 类型的判断:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

类型参数 A、B 是待判断的联合类型,B 默认值为 A,也就是同一个类型。

A extends A 这段看似没啥意义,主要是为了触发分布式条件类型,让 A 的每个类型单独传入。

[B] extends [A] 这样不直接写 B 就可以避免触发分布式条件类型,那么 B 就是整个联合类型。

B 是联合类型整体,而 A 是单个类型,自然不成立,而其它类型没有这种特殊处理,A 和 B 都是同一个,怎么判断都成立。

利用这个特点就可以判断出是否是联合类型。

其中有两个点比较困惑,我们重点记一下:

当 A 是联合类型时:

A extends A 这种写法是为了触发分布式条件类型,让每个类型单独传入处理的,没别的意义。

A extends A 和 [A] extends [A] 是不同的处理,前者是单个类型和整个类型做判断,后者两边都是整个联合类型,因为只有 extends 左边直接是类型参数才会触发分布式条件类型。

理解了这两点,分布式条件类型就算掌握了。

BEM

bem 是 css 命名规范,用 block__element--modifier 的形式来描述某个区块下面的某个元素的某个状态的样式。

那么我们可以写这样一个高级类型,传入 block、element、modifier,返回构造出的 class 名:

这样使用:

ts
type bemResult = BEM<'guang', ['aaa', 'bbb'], ['warning', 'success']>;

它的实现就是三部分的合并,但传入的是数组,要递归遍历取出每一个元素来和其他部分组合,这样太麻烦了。

而如果是联合类型就不用递归遍历了,因为联合类型遇到字符串也是会单独每个元素单独传入做处理。

数组转联合类型可以这样写:

ts
type union = ['aaa', 'bbb'][number];\n// type union = 'aaa' | 'bbb'

那么 BEM 就可以这样实现:

ts
type BEM<\n  Block extends string,\n  Element extends string[],\n  Modifiers extends string[],\n> = `${Block}__${Element[number]}--${Modifiers[number]}`;

类型参数 Block、Element、Modifiers 分别是 bem 规范的三部分,其中 Element 和 Modifiers 都可能多个,约束为 string[]。

构造一个字符串类型,其中 Element 和 Modifiers 通过索引访问来变为联合类型。

字符串类型中遇到联合类型的时候,会每个元素单独传入计算,也就是这样的效果:

ts
type RemResult = BEM<'a', ['b', 'c'], ['d', 'e']>;\n// type RemResult = 'a__b--d' | 'a__b--e' | 'a__c--d' | 'a__b--e'

可以看到,用好了联合类型,确实能简化类型编程逻辑。

AllCombinations

我们再来实现一个全组合的高级类型,也是联合类型相关的:

希望传入 'A' | 'B' 的时候,能够返回所有的组合: 'A' | 'B' | 'BA' | 'AB'。

这种全组合问题的实现思路就是两两组合,组合出的字符串再和其他字符串两两组和:

比如 'A' | 'B' | 'c',就是 A 和 B、C 组合,B 和 A、C 组合,C 和 A、B 组合。然后组合出来的字符串再和其他字符串组合。

任何两个类型的组合有四种:A、B、AB、BA

ts
type Combination<A extends string, B extends string> = A | B | `${A}${B}` | `${B}${A}`;

然后构造出来的字符串再和其他字符串组合。

所以全组合的高级类型就是这样:

ts
type AllCombinations<A extends string, B extends string = A> = A extends A\n  ? Combination<A, AllCombinations<Exclude<B, A>>>\n  : never;

类型参数 A、B 是待组合的两个联合类型,B 默认是 A 也就是同一个。

A extends A 的意义就是让联合类型每个类型单独传入做处理,上面我们刚学会。

A 的处理就是 A 和 B 中去掉 A 以后的所有类型组合,也就是 Combination<A, B 去掉 A 以后的所有组合>。

而 B 去掉 A 以后的所有组合就是 AllCombinations<Exclude<B, A>>,所以全组合就是 Combination<A, AllCombinations<Exclude<B, A>>>。

总结

联合类型中的每个类型都是相互独立的,TypeScript 对它做了特殊处理,也就是遇到字符串类型、条件类型的时候会把每个类型单独传入做计算,最后把每个类型的计算结果合并成联合类型。

条件类型左边是联合类型的时候就会触法这种处理,叫做分布式条件类型。

有两点特别要注意:

  • A extends A 不是没意义,意义是取出联合类型中的单个类型放入 A

  • A extends A 才是分布式条件类型, [A] extends [A] 就不是了,只有左边是单独的类型参数才可以。

我们后面做了一些案例,发现联合类型的这种 distributive 的特性确实能简化类型编程,但是也增加了认知成本,不过这也是不可避免的事。

',91)]))}const y=i(k,[["render",n]]);export{F as __pageData,y as default}; diff --git a/assets/src_ranui_button_index.md.DhP8rReR.js b/assets/src_ranui_button_index.md.DhP8rReR.js new file mode 100644 index 0000000000..1c71cfe611 --- /dev/null +++ b/assets/src_ranui_button_index.md.DhP8rReR.js @@ -0,0 +1,9 @@ +import{_ as a,o as n,c as e,a3 as t,j as s}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"Button","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/button/index.md","filePath":"src/ranui/button/index.md","lastUpdated":1726550590000}'),l={name:"src/ranui/button/index.md"};function h(p,i,k,r,o,d){return n(),e("div",{"data-pagefind-body":!0},i[0]||(i[0]=[t(`

Button

The button is used to start an instant action.

Code demo

Button
xml
 <r-button >Button</r-button>

Attribute

type

There are four types of buttons

Primary button
Warning button
Text button
Default button
xml
 <r-button type="primary">Primary button</r-button>
+ <r-button type="warning">Warning button</r-button>
+ <r-button type="text">Text button</r-button>
+ <r-button >Default button</r-button>

disabled

Adding the disabled attribute makes the button unavailable and changes the button style.

Primary button
Warning button
Text button
Default button
xml
 <r-button type="primary" disabled>Primary butto</r-button>
+ <r-button type="warning" disabled>Warning button</r-button>
+ <r-button type="text" disabled>Text button</r-button>
+ <r-button disabled>Default button</r-button>

icon

When you need to embed an Icon inside a Button, you can set the icon property or use the Icon component directly inside a Button.

If you want to control the specific position of the Icon, you can only use the Icon component directly, not the icon property.

Default button
Primary button
xml
<r-button type="default" icon="user">Default button</r-button>
+<r-button type="primary" icon="home">Primary button</r-button>

特效 effect

If you want a pure Button, you can add effect = false to block the water ripple effect when clicked

`,28),s("r-button",{type:"default",effect:"fase",icon:"user"},"Default button",-1),s("r-button",{type:"primary",effect:"fase",icon:"home"},"Primary button",-1),t(`
xml
<r-button type="default" icon="user">Default button</r-button>
+<r-button type="primary" icon="home">Primary button</r-button>
`,1)]))}const u=a(l,[["render",h]]);export{g as __pageData,u as default}; diff --git a/assets/src_ranui_button_index.md.DhP8rReR.lean.js b/assets/src_ranui_button_index.md.DhP8rReR.lean.js new file mode 100644 index 0000000000..1c71cfe611 --- /dev/null +++ b/assets/src_ranui_button_index.md.DhP8rReR.lean.js @@ -0,0 +1,9 @@ +import{_ as a,o as n,c as e,a3 as t,j as s}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"Button","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/button/index.md","filePath":"src/ranui/button/index.md","lastUpdated":1726550590000}'),l={name:"src/ranui/button/index.md"};function h(p,i,k,r,o,d){return n(),e("div",{"data-pagefind-body":!0},i[0]||(i[0]=[t(`

Button

The button is used to start an instant action.

Code demo

Button
xml
 <r-button >Button</r-button>

Attribute

type

There are four types of buttons

Primary button
Warning button
Text button
Default button
xml
 <r-button type="primary">Primary button</r-button>
+ <r-button type="warning">Warning button</r-button>
+ <r-button type="text">Text button</r-button>
+ <r-button >Default button</r-button>

disabled

Adding the disabled attribute makes the button unavailable and changes the button style.

Primary button
Warning button
Text button
Default button
xml
 <r-button type="primary" disabled>Primary butto</r-button>
+ <r-button type="warning" disabled>Warning button</r-button>
+ <r-button type="text" disabled>Text button</r-button>
+ <r-button disabled>Default button</r-button>

icon

When you need to embed an Icon inside a Button, you can set the icon property or use the Icon component directly inside a Button.

If you want to control the specific position of the Icon, you can only use the Icon component directly, not the icon property.

Default button
Primary button
xml
<r-button type="default" icon="user">Default button</r-button>
+<r-button type="primary" icon="home">Primary button</r-button>

特效 effect

If you want a pure Button, you can add effect = false to block the water ripple effect when clicked

`,28),s("r-button",{type:"default",effect:"fase",icon:"user"},"Default button",-1),s("r-button",{type:"primary",effect:"fase",icon:"home"},"Primary button",-1),t(`
xml
<r-button type="default" icon="user">Default button</r-button>
+<r-button type="primary" icon="home">Primary button</r-button>
`,1)]))}const u=a(l,[["render",h]]);export{g as __pageData,u as default}; diff --git a/assets/src_ranui_checkbox_index.md.Bp6CThLb.js b/assets/src_ranui_checkbox_index.md.Bp6CThLb.js new file mode 100644 index 0000000000..f3d895d5aa --- /dev/null +++ b/assets/src_ranui_checkbox_index.md.Bp6CThLb.js @@ -0,0 +1,2 @@ +import{_ as e,o as h,c as t,a3 as i,j as a}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"CheckBox","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/checkbox/index.md","filePath":"src/ranui/checkbox/index.md","lastUpdated":1726550590000}'),l={name:"src/ranui/checkbox/index.md"};function k(n,s,c,d,p,o){return h(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[i('

CheckBox

Code demo

xml
 <r-checkbox ></r-checkbox>

Attribute

checked

xml
 <r-checkbox checked="true"></r-checkbox>\n <r-checkbox checked="false"></r-checkbox>

disabled

xml
 <r-checkbox checked="true" disabled></r-checkbox>\n <r-checkbox checked="false" disabled></r-checkbox>

event

Common callback events.

onchange

',16),a("r-checkbox",{onchange:"console.log(this.checked)"},null,-1),a("r-checkbox",{onchange:"console.log(this.checked)"},null,-1),i(`
xml
 <r-checkbox onchange="console.log(this.checked)"></r-checkbox>
+ <r-checkbox onchange="console.log(this.checked)"></r-checkbox>
`,1)]))}const g=e(l,[["render",k]]);export{E as __pageData,g as default}; diff --git a/assets/src_ranui_checkbox_index.md.Bp6CThLb.lean.js b/assets/src_ranui_checkbox_index.md.Bp6CThLb.lean.js new file mode 100644 index 0000000000..f3d895d5aa --- /dev/null +++ b/assets/src_ranui_checkbox_index.md.Bp6CThLb.lean.js @@ -0,0 +1,2 @@ +import{_ as e,o as h,c as t,a3 as i,j as a}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"CheckBox","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/checkbox/index.md","filePath":"src/ranui/checkbox/index.md","lastUpdated":1726550590000}'),l={name:"src/ranui/checkbox/index.md"};function k(n,s,c,d,p,o){return h(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[i('

CheckBox

Code demo

xml
 <r-checkbox ></r-checkbox>

Attribute

checked

xml
 <r-checkbox checked="true"></r-checkbox>\n <r-checkbox checked="false"></r-checkbox>

disabled

xml
 <r-checkbox checked="true" disabled></r-checkbox>\n <r-checkbox checked="false" disabled></r-checkbox>

event

Common callback events.

onchange

',16),a("r-checkbox",{onchange:"console.log(this.checked)"},null,-1),a("r-checkbox",{onchange:"console.log(this.checked)"},null,-1),i(`
xml
 <r-checkbox onchange="console.log(this.checked)"></r-checkbox>
+ <r-checkbox onchange="console.log(this.checked)"></r-checkbox>
`,1)]))}const g=e(l,[["render",k]]);export{E as __pageData,g as default}; diff --git a/assets/src_ranui_icon_index.md.mkEISxvO.js b/assets/src_ranui_icon_index.md.mkEISxvO.js new file mode 100644 index 0000000000..cf05982877 --- /dev/null +++ b/assets/src_ranui_icon_index.md.mkEISxvO.js @@ -0,0 +1,12 @@ +import{_ as p,o as r,c as E,a3 as e,j as n}from"./chunks/framework.C-ai2y4t.js";const o=()=>{setTimeout(()=>{const l=["add-user","book","check-circle","close-circle","eye-close","eye","info-circle","loading","lock","message","power-off","setting","team","unlock","user"];if(typeof document<"u"){const a=document.getElementById("icon-list"),s=document.createElement("div");s.style.setProperty("display","grid"),s.style.setProperty("grid-template-columns","repeat(3, 200px)"),s.style.setProperty("grid-template-rows","repeat(3, 200px);"),l.forEach(h=>{const i=document.createElement("div");i.style.setProperty("display","flex"),i.style.setProperty("align-items","center"),i.style.setProperty("margin","15px"),i.style.setProperty("justify-content","center"),i.style.setProperty("flex-flow","column nowrap");const t=document.createElement("r-icon");t.setAttribute("name",h),t.setAttribute("size","50"),i.appendChild(t);const k=document.createElement("span");k.innerHTML=h,i.appendChild(k),s==null||s.appendChild(i)}),a==null||a.appendChild(s)}},0)};o();const y=JSON.parse('{"title":"Icon","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/icon/index.md","filePath":"src/ranui/icon/index.md","lastUpdated":1726550590000}'),d={name:"src/ranui/icon/index.md"};function g(l,a,s,h,i,t){return r(),E("div",{"data-pagefind-body":!0},a[0]||(a[0]=[e(`

Icon

Semantic vector graphics

Code demo

xml
 <r-icon name="lock"  ></r-icon>
+ <r-icon name="eye"  ></r-icon>
+ <r-icon name="user"  ></r-icon>

Attribute

name

Select a different icon based on the name

html
<r-icon name="lock"></r-icon>
+<r-icon name="eye"></r-icon>
+<r-icon name="user"></r-icon>

size

html
<r-icon name="lock" size="30"></r-icon>
+<r-icon name="lock" size="50"></r-icon>
+<r-icon name="lock" size="70"></r-icon>

color

html
<r-icon name="lock" size="50" color="red"></r-icon>
+<r-icon name="lock" size="50" color="#1E90FF"></r-icon>
+<r-icon name="lock" size="50" color="#F44336"></r-icon>
+<r-icon name="lock" size="50" color="#3F51B5"></r-icon>

spin

Set spin to turn on the rotation, and pass in a number to control the rotation speed. The smaller the number, the faster the rotation

`,18),n("div",{style:{display:"flex"}},[n("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:"0.7"}),n("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:""}),n("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:"5"})],-1),e(`
html
<r-icon name="loading" size="50" color="#1E90FF" spin="0.7"></r-icon>
+<r-icon name="loading" size="50" color="#1E90FF" spin></r-icon>
+<r-icon name="loading" size="50" color="#1E90FF" spin="5"></r-icon>

Icon list

`,3)]))}const F=p(d,[["render",g]]);export{y as __pageData,F as default}; diff --git a/assets/src_ranui_icon_index.md.mkEISxvO.lean.js b/assets/src_ranui_icon_index.md.mkEISxvO.lean.js new file mode 100644 index 0000000000..cf05982877 --- /dev/null +++ b/assets/src_ranui_icon_index.md.mkEISxvO.lean.js @@ -0,0 +1,12 @@ +import{_ as p,o as r,c as E,a3 as e,j as n}from"./chunks/framework.C-ai2y4t.js";const o=()=>{setTimeout(()=>{const l=["add-user","book","check-circle","close-circle","eye-close","eye","info-circle","loading","lock","message","power-off","setting","team","unlock","user"];if(typeof document<"u"){const a=document.getElementById("icon-list"),s=document.createElement("div");s.style.setProperty("display","grid"),s.style.setProperty("grid-template-columns","repeat(3, 200px)"),s.style.setProperty("grid-template-rows","repeat(3, 200px);"),l.forEach(h=>{const i=document.createElement("div");i.style.setProperty("display","flex"),i.style.setProperty("align-items","center"),i.style.setProperty("margin","15px"),i.style.setProperty("justify-content","center"),i.style.setProperty("flex-flow","column nowrap");const t=document.createElement("r-icon");t.setAttribute("name",h),t.setAttribute("size","50"),i.appendChild(t);const k=document.createElement("span");k.innerHTML=h,i.appendChild(k),s==null||s.appendChild(i)}),a==null||a.appendChild(s)}},0)};o();const y=JSON.parse('{"title":"Icon","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/icon/index.md","filePath":"src/ranui/icon/index.md","lastUpdated":1726550590000}'),d={name:"src/ranui/icon/index.md"};function g(l,a,s,h,i,t){return r(),E("div",{"data-pagefind-body":!0},a[0]||(a[0]=[e(`

Icon

Semantic vector graphics

Code demo

xml
 <r-icon name="lock"  ></r-icon>
+ <r-icon name="eye"  ></r-icon>
+ <r-icon name="user"  ></r-icon>

Attribute

name

Select a different icon based on the name

html
<r-icon name="lock"></r-icon>
+<r-icon name="eye"></r-icon>
+<r-icon name="user"></r-icon>

size

html
<r-icon name="lock" size="30"></r-icon>
+<r-icon name="lock" size="50"></r-icon>
+<r-icon name="lock" size="70"></r-icon>

color

html
<r-icon name="lock" size="50" color="red"></r-icon>
+<r-icon name="lock" size="50" color="#1E90FF"></r-icon>
+<r-icon name="lock" size="50" color="#F44336"></r-icon>
+<r-icon name="lock" size="50" color="#3F51B5"></r-icon>

spin

Set spin to turn on the rotation, and pass in a number to control the rotation speed. The smaller the number, the faster the rotation

`,18),n("div",{style:{display:"flex"}},[n("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:"0.7"}),n("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:""}),n("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:"5"})],-1),e(`
html
<r-icon name="loading" size="50" color="#1E90FF" spin="0.7"></r-icon>
+<r-icon name="loading" size="50" color="#1E90FF" spin></r-icon>
+<r-icon name="loading" size="50" color="#1E90FF" spin="5"></r-icon>

Icon list

`,3)]))}const F=p(d,[["render",g]]);export{y as __pageData,F as default}; diff --git a/assets/src_ranui_image_index.md.DfDYyZub.js b/assets/src_ranui_image_index.md.DfDYyZub.js new file mode 100644 index 0000000000..80e11f201d --- /dev/null +++ b/assets/src_ranui_image_index.md.DfDYyZub.js @@ -0,0 +1 @@ +import{_ as a,o as i,c as e,a3 as E,j as g}from"./chunks/framework.C-ai2y4t.js";const r=JSON.parse('{"title":"Image","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/image/index.md","filePath":"src/ranui/image/index.md","lastUpdated":1726550590000}'),Q={name:"src/ranui/image/index.md"};function s(t,A,o,n,d,h){return i(),e("div",{"data-pagefind-body":!0},A[0]||(A[0]=[E('

Image

Code demo

xml
 <r-img src="" fallback=""></r-img>

Attribute

src

Image address

Image loading failurefallback

srcConfiguration of the picture loading failure, the bottom of the picture address, the following is the default loading failure picture

',8),g("r-img",{fallback:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg=="},null,-1)]))}const B=a(Q,[["render",s]]);export{r as __pageData,B as default}; diff --git a/assets/src_ranui_image_index.md.DfDYyZub.lean.js b/assets/src_ranui_image_index.md.DfDYyZub.lean.js new file mode 100644 index 0000000000..80e11f201d --- /dev/null +++ b/assets/src_ranui_image_index.md.DfDYyZub.lean.js @@ -0,0 +1 @@ +import{_ as a,o as i,c as e,a3 as E,j as g}from"./chunks/framework.C-ai2y4t.js";const r=JSON.parse('{"title":"Image","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/image/index.md","filePath":"src/ranui/image/index.md","lastUpdated":1726550590000}'),Q={name:"src/ranui/image/index.md"};function s(t,A,o,n,d,h){return i(),e("div",{"data-pagefind-body":!0},A[0]||(A[0]=[E('

Image

Code demo

xml
 <r-img src="" fallback=""></r-img>

Attribute

src

Image address

Image loading failurefallback

srcConfiguration of the picture loading failure, the bottom of the picture address, the following is the default loading failure picture

',8),g("r-img",{fallback:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg=="},null,-1)]))}const B=a(Q,[["render",s]]);export{r as __pageData,B as default}; diff --git a/assets/src_ranui_index.md.D31LFnZe.js b/assets/src_ranui_index.md.D31LFnZe.js new file mode 100644 index 0000000000..6b042f1fd4 --- /dev/null +++ b/assets/src_ranui_index.md.D31LFnZe.js @@ -0,0 +1,85 @@ +import{_ as t}from"./chunks/customElements.qitHOM3M.js";import{_ as n,o as l,c as e,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"ranui","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/index.md","filePath":"src/ranui/index.md","lastUpdated":1726550590000}'),h={name:"src/ranui/index.md"};function p(k,a,r,d,E,o){return l(),e("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

ranui

Development scheme based on Web Components

Feature

  1. Cross-Framework Compatibility: Works seamlessly with React, Vue, Preact, SolidJS, Svelte, and more. Integrates with any JavaScript project following W3C standards.
  2. Pure Native Experience: No need for npm, React/Vue, or build tools. Easy to start, like using native div tags, simplifying structure and reducing learning costs.
  3. Modular Design: Breaks systems into small, reusable components for enhanced maintainability and scalability.
  4. Open-Source: Licensed under MIT, providing free access to all source code for personal or commercial use.
  5. Interactive Documentation: Offers detailed, interactive documentation with live examples for efficient learning.
  6. Type-Checking: Built on TypeScript with full type support, ensuring robust and maintainable code.
  7. Stability and Durability: Provides exceptional stability, avoiding disruptive updates and ensuring continuous project operation.

Situation

Build Statusnpm-vnpm-dbrotlimodule formats: umd, esm

Usage

In most cases, you can use it just like a native div tag.

Here are some examples

  1. html
  2. js
  3. jsx
  4. vue
  5. tsx

1.html

html
<script src="./ranui/dist/umd/index.umd.cjs"></script>
+
+<body>
+  <r-button>Button</r-button>
+</body>

2.js

js
import 'ranui';
+
+const Button = document.createElement('r-button');
+Button.appendChild('this is button text');
+document.body.appendChild(Button);

3.jsx

jsx
import 'ranui';
+const App = () => {
+  return (
+    <>
+      <r-button>Button</r-button>
+    </>
+  );
+};

4.vue

vue
<template>
+  <r-button>Button</r-button>
+</template>
+<script>
+import 'ranui';
+</script>

5.tsx

tsx
// react 18
+import type { SyntheticEvent } from 'react';
+import React, { useRef } from 'react';
+import 'ranui';
+
+const FilePreview = () => {
+  const ref = useRef<HTMLDivElement | null>(null);
+  const uploadFile = (e: SyntheticEvent<HTMLDivElement>) => {
+    if (ref.current) {
+      const uploadFile = document.createElement('input');
+      uploadFile.setAttribute('type', 'file');
+      uploadFile.click();
+      uploadFile.onchange = (e) => {
+        const { files = [] } = uploadFile;
+        if (files && files?.length > 0 && ref.current) {
+          ref.current.setAttribute('src', '');
+          const file = files[0];
+          const url = URL.createObjectURL(file);
+          ref.current.setAttribute('src', url);
+        }
+      };
+    }
+  };
+  return (
+    <div>
+      <r-preview ref={ref}></r-preview>
+      <r-button type="primary" onClick={uploadFile}>
+        choose file to preview
+      </r-button>
+    </div>
+  );
+};

Import

Support for on-demand import

js
import 'ranui/button';

If there is a style problem, you can import the style manually

js
import 'ranui/style';

If there is a type problem, you can manually import the type

ts
import 'ranui/types';

Or

ts
import 'ranui/dist/typings';

It can also be imported globally, which is more convenient, so that there is no need to consider anything, so that it is done.

  • ES module
js
import 'ranui';
  • UMD, IIFE, CJS
html
<script src="./ranui/dist/umd/index.umd.cjs"></script>

Overview

  • Button
Primary button
Warning button
Text button
Default button
  • Icon
`,42),s("div",{style:{display:"flex"}},[s("r-icon",{name:"lock",size:"50"}),s("r-icon",{name:"user",size:"50"}),s("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:""})],-1),i('
  • Skeleton
  • Input
  • message
',9),s("r-button",{onclick:"message.info('This is a hint')"},"Information prompt",-1),s("r-button",{onclick:"message.warning('This is a hint')"},"Warning prompt",-1),s("r-button",{onclick:"message.error('This is a hint')"},"Error prompt",-1),s("r-button",{onclick:"message.success('This is a hint')"},"Success tip",-1),s("r-button",{onclick:"message.toast('This is a hint')"},"toast tip",-1),s("ul",null,[s("li",null,[s("code",null,"Tab")])],-1),s("div",{style:{display:"block","margin-right":"8px","margin-bottom":"12px"}},[s("r-tabs",null,[s("r-tab",{label:"home",icon:"home"},"tab1"),s("r-tab",{label:"message",icon:"message"},"tab2"),s("r-tab",{label:"user",icon:"user"},"tab3")])],-1),s("ul",null,[s("li",null,[s("code",null,"Radar")])],-1),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},abilitys:'[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),s("ul",null,[s("li",null,[s("code",null,"Progress")])],-1),s("r-progress",{type:"drag"},null,-1),s("ul",null,[s("li",null,[s("code",null,"Player")])],-1),s("r-player",{style:{display:"block",width:"100%","max-width":"600px",height:"300px"},src:"/ran/hls/example.m3u8"},null,-1),s("ul",null,[s("li",null,[s("code",null,"Select")])],-1),s("r-select",{style:{width:"120px",height:"40px"},defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),s("ul",null,[s("li",null,[s("code",null,"Loading")])],-1),s("r-loading",{name:"circle-fold"},null,-1),s("ul",null,[s("li",null,[s("code",null,"math")])],-1),s("r-math",{latex:"x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}"},null,-1),i(`

Event

  • react

@ranui/react By react higher-order functions encapsulated ranui and become, Event events follow react Event specification. It is slightly different from the W3C standard.

  • Modern 'web' standards

In the W3C standard, you can use the on attribute to define event handlers on HTML elements. But this is the old event handler approach.

Modern web development recommends the addEventListener method.

html
<r-button id="button">Button</r-button>
+
+<script>
+  const button = document.getElementById('button');
+  button.addEventListener('click', function (event) {
+    alert('New click event!');
+  });
+</script>

However, if you do need to use the 'on' attribute, here is an example:

html
<r-input onchange="change(this.value)"></r-input>
+
+<script>
+  function change(e) {
+    console.log('e--->', e);
+  }
+</script>

Note that using the 'on' attribute to define event handlers has some limitations and disadvantages.

For example, you can't use event capture or event delegation, and each event type requires a separate attribute.

This is why the addEventListener method is recommended for modern web development.

You can also use the 'property' method:

html
<r-input id="input"></r-input>
+
+<script>
+  const input = document.getElementById("input")
+  input.onchange = (e) {
+    console.log('e--->', e)
+  }
+</script>

style

::part

html
<r-input id="input"></r-input>
+
+<style>
+  /* #input refers to the current custom element
+input in ::part(input) refers to the class  of the Shadow DOM element inside the current custom element*/
+  #input::part(input) {
+    width: 100px;
+  }
+</style>

For specific pseudo-class names(::part), please refer to the specific introduction.

Pass in by attribute

A sheet attribute is added to all components, passing in a CSSStyleSheet string. It will be inserted directly into the Shadow DOM.

CSS3 variable var

By setting the CSS3 variable for a component, you can customize the specified styles within the component, such as:

`,22),s("r-progress",{percent:"0.7",type:"drag"},null,-1),s("br",null,null,-1),s("r-progress",{percent:"0.7",type:"drag",style:{"--ran-progress-wrap-background":"linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)"}},null,-1),i(`
html
<r-progress percent="0.7" type="drag"></r-progress>
+<r-progress
+  percent="0.70"
+  type="drag"
+  style="--ran-progress-wrap-background:linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);"
+></r-progress>

For specific CSS3 variable names, refer to the introduction and description of each component.

Compatibility

  • Do not support IE, others have better support

Contributors

Other

  1. 优秀的组件设计
  2. 在线生成 CSS 渐变色
  3. 优秀设计作品,有 psd 和 sketch
  4. 3D UI 设计,类似于 3D 版的 figma
  5. 设计规范
  6. 优秀设计作品
  7. element UI 中文网
  8. Ant design 中文网
  9. 在线绘制 CSS 动画
  10. tailwindcss
  11. animate css
  12. can i use
  13. figma

Protocols and standards

  1. RFCs
  2. ECMA
  3. w3c
',11)]))}const u=n(h,[["render",p]]);export{y as __pageData,u as default}; diff --git a/assets/src_ranui_index.md.D31LFnZe.lean.js b/assets/src_ranui_index.md.D31LFnZe.lean.js new file mode 100644 index 0000000000..6b042f1fd4 --- /dev/null +++ b/assets/src_ranui_index.md.D31LFnZe.lean.js @@ -0,0 +1,85 @@ +import{_ as t}from"./chunks/customElements.qitHOM3M.js";import{_ as n,o as l,c as e,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"ranui","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/index.md","filePath":"src/ranui/index.md","lastUpdated":1726550590000}'),h={name:"src/ranui/index.md"};function p(k,a,r,d,E,o){return l(),e("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

ranui

Development scheme based on Web Components

Feature

  1. Cross-Framework Compatibility: Works seamlessly with React, Vue, Preact, SolidJS, Svelte, and more. Integrates with any JavaScript project following W3C standards.
  2. Pure Native Experience: No need for npm, React/Vue, or build tools. Easy to start, like using native div tags, simplifying structure and reducing learning costs.
  3. Modular Design: Breaks systems into small, reusable components for enhanced maintainability and scalability.
  4. Open-Source: Licensed under MIT, providing free access to all source code for personal or commercial use.
  5. Interactive Documentation: Offers detailed, interactive documentation with live examples for efficient learning.
  6. Type-Checking: Built on TypeScript with full type support, ensuring robust and maintainable code.
  7. Stability and Durability: Provides exceptional stability, avoiding disruptive updates and ensuring continuous project operation.

Situation

Build Statusnpm-vnpm-dbrotlimodule formats: umd, esm

Usage

In most cases, you can use it just like a native div tag.

Here are some examples

  1. html
  2. js
  3. jsx
  4. vue
  5. tsx

1.html

html
<script src="./ranui/dist/umd/index.umd.cjs"></script>
+
+<body>
+  <r-button>Button</r-button>
+</body>

2.js

js
import 'ranui';
+
+const Button = document.createElement('r-button');
+Button.appendChild('this is button text');
+document.body.appendChild(Button);

3.jsx

jsx
import 'ranui';
+const App = () => {
+  return (
+    <>
+      <r-button>Button</r-button>
+    </>
+  );
+};

4.vue

vue
<template>
+  <r-button>Button</r-button>
+</template>
+<script>
+import 'ranui';
+</script>

5.tsx

tsx
// react 18
+import type { SyntheticEvent } from 'react';
+import React, { useRef } from 'react';
+import 'ranui';
+
+const FilePreview = () => {
+  const ref = useRef<HTMLDivElement | null>(null);
+  const uploadFile = (e: SyntheticEvent<HTMLDivElement>) => {
+    if (ref.current) {
+      const uploadFile = document.createElement('input');
+      uploadFile.setAttribute('type', 'file');
+      uploadFile.click();
+      uploadFile.onchange = (e) => {
+        const { files = [] } = uploadFile;
+        if (files && files?.length > 0 && ref.current) {
+          ref.current.setAttribute('src', '');
+          const file = files[0];
+          const url = URL.createObjectURL(file);
+          ref.current.setAttribute('src', url);
+        }
+      };
+    }
+  };
+  return (
+    <div>
+      <r-preview ref={ref}></r-preview>
+      <r-button type="primary" onClick={uploadFile}>
+        choose file to preview
+      </r-button>
+    </div>
+  );
+};

Import

Support for on-demand import

js
import 'ranui/button';

If there is a style problem, you can import the style manually

js
import 'ranui/style';

If there is a type problem, you can manually import the type

ts
import 'ranui/types';

Or

ts
import 'ranui/dist/typings';

It can also be imported globally, which is more convenient, so that there is no need to consider anything, so that it is done.

  • ES module
js
import 'ranui';
  • UMD, IIFE, CJS
html
<script src="./ranui/dist/umd/index.umd.cjs"></script>

Overview

  • Button
Primary button
Warning button
Text button
Default button
  • Icon
`,42),s("div",{style:{display:"flex"}},[s("r-icon",{name:"lock",size:"50"}),s("r-icon",{name:"user",size:"50"}),s("r-icon",{name:"loading",size:"50",color:"#1E90FF",spin:""})],-1),i('
  • Skeleton
  • Input
  • message
',9),s("r-button",{onclick:"message.info('This is a hint')"},"Information prompt",-1),s("r-button",{onclick:"message.warning('This is a hint')"},"Warning prompt",-1),s("r-button",{onclick:"message.error('This is a hint')"},"Error prompt",-1),s("r-button",{onclick:"message.success('This is a hint')"},"Success tip",-1),s("r-button",{onclick:"message.toast('This is a hint')"},"toast tip",-1),s("ul",null,[s("li",null,[s("code",null,"Tab")])],-1),s("div",{style:{display:"block","margin-right":"8px","margin-bottom":"12px"}},[s("r-tabs",null,[s("r-tab",{label:"home",icon:"home"},"tab1"),s("r-tab",{label:"message",icon:"message"},"tab2"),s("r-tab",{label:"user",icon:"user"},"tab3")])],-1),s("ul",null,[s("li",null,[s("code",null,"Radar")])],-1),s("r-radar",{style:{width:"300px",height:"300px",display:"block"},abilitys:'[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),s("ul",null,[s("li",null,[s("code",null,"Progress")])],-1),s("r-progress",{type:"drag"},null,-1),s("ul",null,[s("li",null,[s("code",null,"Player")])],-1),s("r-player",{style:{display:"block",width:"100%","max-width":"600px",height:"300px"},src:"/ran/hls/example.m3u8"},null,-1),s("ul",null,[s("li",null,[s("code",null,"Select")])],-1),s("r-select",{style:{width:"120px",height:"40px"},defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),s("ul",null,[s("li",null,[s("code",null,"Loading")])],-1),s("r-loading",{name:"circle-fold"},null,-1),s("ul",null,[s("li",null,[s("code",null,"math")])],-1),s("r-math",{latex:"x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}"},null,-1),i(`

Event

  • react

@ranui/react By react higher-order functions encapsulated ranui and become, Event events follow react Event specification. It is slightly different from the W3C standard.

  • Modern 'web' standards

In the W3C standard, you can use the on attribute to define event handlers on HTML elements. But this is the old event handler approach.

Modern web development recommends the addEventListener method.

html
<r-button id="button">Button</r-button>
+
+<script>
+  const button = document.getElementById('button');
+  button.addEventListener('click', function (event) {
+    alert('New click event!');
+  });
+</script>

However, if you do need to use the 'on' attribute, here is an example:

html
<r-input onchange="change(this.value)"></r-input>
+
+<script>
+  function change(e) {
+    console.log('e--->', e);
+  }
+</script>

Note that using the 'on' attribute to define event handlers has some limitations and disadvantages.

For example, you can't use event capture or event delegation, and each event type requires a separate attribute.

This is why the addEventListener method is recommended for modern web development.

You can also use the 'property' method:

html
<r-input id="input"></r-input>
+
+<script>
+  const input = document.getElementById("input")
+  input.onchange = (e) {
+    console.log('e--->', e)
+  }
+</script>

style

::part

html
<r-input id="input"></r-input>
+
+<style>
+  /* #input refers to the current custom element
+input in ::part(input) refers to the class  of the Shadow DOM element inside the current custom element*/
+  #input::part(input) {
+    width: 100px;
+  }
+</style>

For specific pseudo-class names(::part), please refer to the specific introduction.

Pass in by attribute

A sheet attribute is added to all components, passing in a CSSStyleSheet string. It will be inserted directly into the Shadow DOM.

CSS3 variable var

By setting the CSS3 variable for a component, you can customize the specified styles within the component, such as:

`,22),s("r-progress",{percent:"0.7",type:"drag"},null,-1),s("br",null,null,-1),s("r-progress",{percent:"0.7",type:"drag",style:{"--ran-progress-wrap-background":"linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000)"}},null,-1),i(`
html
<r-progress percent="0.7" type="drag"></r-progress>
+<r-progress
+  percent="0.70"
+  type="drag"
+  style="--ran-progress-wrap-background:linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);"
+></r-progress>

For specific CSS3 variable names, refer to the introduction and description of each component.

Compatibility

  • Do not support IE, others have better support

Contributors

Other

  1. 优秀的组件设计
  2. 在线生成 CSS 渐变色
  3. 优秀设计作品,有 psd 和 sketch
  4. 3D UI 设计,类似于 3D 版的 figma
  5. 设计规范
  6. 优秀设计作品
  7. element UI 中文网
  8. Ant design 中文网
  9. 在线绘制 CSS 动画
  10. tailwindcss
  11. animate css
  12. can i use
  13. figma

Protocols and standards

  1. RFCs
  2. ECMA
  3. w3c
',11)]))}const u=n(h,[["render",p]]);export{y as __pageData,u as default}; diff --git a/assets/src_ranui_input_index.md.DkK2wQig.js b/assets/src_ranui_input_index.md.DkK2wQig.js new file mode 100644 index 0000000000..8c2a600c6b --- /dev/null +++ b/assets/src_ranui_input_index.md.DkK2wQig.js @@ -0,0 +1,11 @@ +import{_ as t}from"./chunks/input-input.MnARRJC6.js";import{_ as n,o as e,c as h,a3 as s,j as i}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"Input","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/input/index.md","filePath":"src/ranui/input/index.md","lastUpdated":1726550590000}'),l={name:"src/ranui/input/index.md"};function p(k,a,r,d,E,o){return e(),h("div",{"data-pagefind-body":!0},a[0]||(a[0]=[s('

Input

Entering content via mouse or keyboard is the most basic form field packaging.

Code demo

Input field:
xml
<r-input></r-input>

Attribute

label

Provide an input experience similar to Metiral Design.

html
<r-input label="user"></r-input>

placeholder

Consistent with native 'placeholder'.

html
<r-input placeholder="user"></r-input>

disabled

The input box can be disabled by disabled. After disabled, the events on the button become invalid.

html
<r-input label="user" disabled></r-input>

value

Sets or returns the value of the 'value' property of the input box.

type

Currently support 'password', 'number' these types, set will appear additional 'ui' controls.

Password entry field

The password can be switched between plain text and ciphertext.

html
<r-input icon="lock" type="password"></r-input>

icon

You can set an 'icon' to represent the tag identifier.

html
<r-input icon="user"></r-input>

Digital input box

Numeric input box, similar to the native 'input[type=number]', support 'min', 'max', 'step' attributes, support keyboard up and down keys to switch numbers.

html
<r-input type="number" min="-10" max="10" step="0.5"></r-input>

name

Valid when associated with the form component, the field name collected when the form is submitted

status

  • error

Default color value: #ff4d4f

',40),i("div",null,[i("r-input",{status:"error"})],-1),s('
xml
<r-input status="error"></r-input>
  • warning

Default color value:#ff7875

',3),i("div",null,[i("r-input",{status:"warning"})],-1),s('
xml
<r-input  status="warning"></r-input>

event

Common callback events.

onchange

Triggered when text changes.

',5),i("r-input",{onchange:"console.log(this.value)"},null,-1),s(`
html
<r-input onchange="func(this.value)"></r-input>
js
const input = document.createElement('r-input');
+input.setAttribute('label', 'home');
+const func = (e) => {
+  console.log(e);
+};
+input.addEventListener('change', func);

oninput

Triggered when text changes.

`,4),i("r-input",{oninput:"console.log(this.value)"},null,-1),s(`
js
const input = document.createElement('r-input');
+input.setAttribute('label', 'home');
+const func = (e) => {
+  console.log(e);
+};
+input.addEventListener('input', func);

The e parameter structure of the event

input method

',3)]))}const y=n(l,[["render",p]]);export{c as __pageData,y as default}; diff --git a/assets/src_ranui_input_index.md.DkK2wQig.lean.js b/assets/src_ranui_input_index.md.DkK2wQig.lean.js new file mode 100644 index 0000000000..8c2a600c6b --- /dev/null +++ b/assets/src_ranui_input_index.md.DkK2wQig.lean.js @@ -0,0 +1,11 @@ +import{_ as t}from"./chunks/input-input.MnARRJC6.js";import{_ as n,o as e,c as h,a3 as s,j as i}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"Input","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/input/index.md","filePath":"src/ranui/input/index.md","lastUpdated":1726550590000}'),l={name:"src/ranui/input/index.md"};function p(k,a,r,d,E,o){return e(),h("div",{"data-pagefind-body":!0},a[0]||(a[0]=[s('

Input

Entering content via mouse or keyboard is the most basic form field packaging.

Code demo

Input field:
xml
<r-input></r-input>

Attribute

label

Provide an input experience similar to Metiral Design.

html
<r-input label="user"></r-input>

placeholder

Consistent with native 'placeholder'.

html
<r-input placeholder="user"></r-input>

disabled

The input box can be disabled by disabled. After disabled, the events on the button become invalid.

html
<r-input label="user" disabled></r-input>

value

Sets or returns the value of the 'value' property of the input box.

type

Currently support 'password', 'number' these types, set will appear additional 'ui' controls.

Password entry field

The password can be switched between plain text and ciphertext.

html
<r-input icon="lock" type="password"></r-input>

icon

You can set an 'icon' to represent the tag identifier.

html
<r-input icon="user"></r-input>

Digital input box

Numeric input box, similar to the native 'input[type=number]', support 'min', 'max', 'step' attributes, support keyboard up and down keys to switch numbers.

html
<r-input type="number" min="-10" max="10" step="0.5"></r-input>

name

Valid when associated with the form component, the field name collected when the form is submitted

status

  • error

Default color value: #ff4d4f

',40),i("div",null,[i("r-input",{status:"error"})],-1),s('
xml
<r-input status="error"></r-input>
  • warning

Default color value:#ff7875

',3),i("div",null,[i("r-input",{status:"warning"})],-1),s('
xml
<r-input  status="warning"></r-input>

event

Common callback events.

onchange

Triggered when text changes.

',5),i("r-input",{onchange:"console.log(this.value)"},null,-1),s(`
html
<r-input onchange="func(this.value)"></r-input>
js
const input = document.createElement('r-input');
+input.setAttribute('label', 'home');
+const func = (e) => {
+  console.log(e);
+};
+input.addEventListener('change', func);

oninput

Triggered when text changes.

`,4),i("r-input",{oninput:"console.log(this.value)"},null,-1),s(`
js
const input = document.createElement('r-input');
+input.setAttribute('label', 'home');
+const func = (e) => {
+  console.log(e);
+};
+input.addEventListener('input', func);

The e parameter structure of the event

input method

',3)]))}const y=n(l,[["render",p]]);export{c as __pageData,y as default}; diff --git a/assets/src_ranui_loading_index.md.CLsqr9az.js b/assets/src_ranui_loading_index.md.CLsqr9az.js new file mode 100644 index 0000000000..d0f639ad91 --- /dev/null +++ b/assets/src_ranui_loading_index.md.CLsqr9az.js @@ -0,0 +1,4 @@ +import{_ as a}from"./chunks/loading.vue_vue_type_style_index_0_lang.Da-8gR4I.js";import{o as s,c as t,a3 as n,G as l}from"./chunks/framework.C-ai2y4t.js";import"./chunks/index.CBA5mFK_.js";const o=JSON.parse('{"title":"Loading","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/loading/index.md","filePath":"src/ranui/loading/index.md","lastUpdated":1726550590000}'),e={name:"src/ranui/loading/index.md"},g=Object.assign(e,{setup(h){return(d,i)=>(s(),t("div",{"data-pagefind-body":!0},[i[0]||(i[0]=n(`

Loading

Some nice looking loading.

Code demo

xml
<r-loading name="circle"></r-loading>

Attribute

name

There's a lot of different loading here

xml
<r-loading name="double-bounce"></r-loading>
+<r-loading name="rotate"></r-loading>
+<r-loading name="stretch"></r-loading>
+<r-loading name="cube"></r-loading>

Loading list

`,14)),l(a)]))}});export{o as __pageData,g as default}; diff --git a/assets/src_ranui_loading_index.md.CLsqr9az.lean.js b/assets/src_ranui_loading_index.md.CLsqr9az.lean.js new file mode 100644 index 0000000000..d0f639ad91 --- /dev/null +++ b/assets/src_ranui_loading_index.md.CLsqr9az.lean.js @@ -0,0 +1,4 @@ +import{_ as a}from"./chunks/loading.vue_vue_type_style_index_0_lang.Da-8gR4I.js";import{o as s,c as t,a3 as n,G as l}from"./chunks/framework.C-ai2y4t.js";import"./chunks/index.CBA5mFK_.js";const o=JSON.parse('{"title":"Loading","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/loading/index.md","filePath":"src/ranui/loading/index.md","lastUpdated":1726550590000}'),e={name:"src/ranui/loading/index.md"},g=Object.assign(e,{setup(h){return(d,i)=>(s(),t("div",{"data-pagefind-body":!0},[i[0]||(i[0]=n(`

Loading

Some nice looking loading.

Code demo

xml
<r-loading name="circle"></r-loading>

Attribute

name

There's a lot of different loading here

xml
<r-loading name="double-bounce"></r-loading>
+<r-loading name="rotate"></r-loading>
+<r-loading name="stretch"></r-loading>
+<r-loading name="cube"></r-loading>

Loading list

`,14)),l(a)]))}});export{o as __pageData,g as default}; diff --git a/assets/src_ranui_math_index.md.C-RA_nK7.js b/assets/src_ranui_math_index.md.C-RA_nK7.js new file mode 100644 index 0000000000..a6524463e4 --- /dev/null +++ b/assets/src_ranui_math_index.md.C-RA_nK7.js @@ -0,0 +1 @@ +import{_ as e,o as l,c as h,j as a,a as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const m=JSON.parse('{"title":"math","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/math/index.md","filePath":"src/ranui/math/index.md","lastUpdated":1726550590000}'),n={name:"src/ranui/math/index.md"};function r(d,t,p,o,k,c){return l(),h("div",{"data-pagefind-body":!0},t[0]||(t[0]=[a("h1",{id:"math",tabindex:"-1"},[s("math "),a("a",{class:"header-anchor",href:"#math","aria-label":'Permalink to "math"'},"​")],-1),a("p",null,"High-quality display of LaTeX in HTML pages",-1),a("h2",{id:"code-demo",tabindex:"-1"},[s("Code demo "),a("a",{class:"header-anchor",href:"#code-demo","aria-label":'Permalink to "Code demo"'},"​")],-1),a("r-math",{latex:"\\frac{x^2}{a^2} + \\frac{y^2}{b^2} = 1 \\quad (a > b > 0)"},null,-1),i('
xml
<r-math latex="\\frac{x^2}{a^2} + \\frac{y^2}{b^2} = 1 \\quad (a > b > 0)"></r-math>

Attribute

latex string

',3),a("r-math",{latex:"x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}"},null,-1),i('
xml
  <r-math latex="x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}"></r-math>
',1)]))}const E=e(n,[["render",r]]);export{m as __pageData,E as default}; diff --git a/assets/src_ranui_math_index.md.C-RA_nK7.lean.js b/assets/src_ranui_math_index.md.C-RA_nK7.lean.js new file mode 100644 index 0000000000..a6524463e4 --- /dev/null +++ b/assets/src_ranui_math_index.md.C-RA_nK7.lean.js @@ -0,0 +1 @@ +import{_ as e,o as l,c as h,j as a,a as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const m=JSON.parse('{"title":"math","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/math/index.md","filePath":"src/ranui/math/index.md","lastUpdated":1726550590000}'),n={name:"src/ranui/math/index.md"};function r(d,t,p,o,k,c){return l(),h("div",{"data-pagefind-body":!0},t[0]||(t[0]=[a("h1",{id:"math",tabindex:"-1"},[s("math "),a("a",{class:"header-anchor",href:"#math","aria-label":'Permalink to "math"'},"​")],-1),a("p",null,"High-quality display of LaTeX in HTML pages",-1),a("h2",{id:"code-demo",tabindex:"-1"},[s("Code demo "),a("a",{class:"header-anchor",href:"#code-demo","aria-label":'Permalink to "Code demo"'},"​")],-1),a("r-math",{latex:"\\frac{x^2}{a^2} + \\frac{y^2}{b^2} = 1 \\quad (a > b > 0)"},null,-1),i('
xml
<r-math latex="\\frac{x^2}{a^2} + \\frac{y^2}{b^2} = 1 \\quad (a > b > 0)"></r-math>

Attribute

latex string

',3),a("r-math",{latex:"x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}"},null,-1),i('
xml
  <r-math latex="x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}"></r-math>
',1)]))}const E=e(n,[["render",r]]);export{m as __pageData,E as default}; diff --git a/assets/src_ranui_message_index.md.DywEIh7C.js b/assets/src_ranui_message_index.md.DywEIh7C.js new file mode 100644 index 0000000000..7bde5cabdf --- /dev/null +++ b/assets/src_ranui_message_index.md.DywEIh7C.js @@ -0,0 +1,5 @@ +import{_ as e,o as n,c as h,j as s,a as t,a3 as a}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"message","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/message/index.md","filePath":"src/ranui/message/index.md","lastUpdated":1726550590000}'),l={name:"src/ranui/message/index.md"};function p(o,i,k,r,d,g){return n(),h("div",{"data-pagefind-body":!0},i[0]||(i[0]=[s("h1",{id:"message",tabindex:"-1"},[t("message "),s("a",{class:"header-anchor",href:"#message","aria-label":'Permalink to "message"'},"​")],-1),s("p",null,"Global display of operation feedback.",-1),s("h2",{id:"code-demo",tabindex:"-1"},[t("Code demo "),s("a",{class:"header-anchor",href:"#code-demo","aria-label":'Permalink to "Code demo"'},"​")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{type:"primary",onclick:"message.info('This is a hint')"},"Click to trigger the global prompt")],-1),a('
xml
<r-button type="primary" onclick="message.info('This is a hint')">Click to trigger the global prompt</r-button>

Attribute

type

Different prompt types

',4),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.info('This is a hint')"},"Information prompt")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.warning('This is a hint')"},"Warning prompt")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.error('This is a hint')"},"Error prompt")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.success('This is a hint')"},"Success tip")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.toast('This is a hint')"},"toast tip")],-1),a(`
html
<r-button onclick="message.info('This is a hint')">Information prompt</r-button>
+<r-button onclick="message.warning('This is a hint')">Warning prompt</r-button>
+<r-button onclick="message.error('This is a hint')">Error prompt</r-button>
+<r-button onclick="message.success('This is a hint')">Success tip</r-button>
+<r-button onclick="message.toast('This is a hint')">toast tip</r-button>

Method

The component provides a number of static methods, using the following methods and parameters:

  1. You can pass only one parameter, prompt the content, the default prompt 3000 milliseconds

message.info('This is a hint')

message.warning('This is a hint')

message.error('This is a hint')

message.success('This is a hint')

message.toast('This is a hint')"

  1. You can also pass an object, set the prompt content, turn off the delay, and trigger the callback function when you close it

message.info({content:'This is a hint', duration: 2000, close: () => {}})

message.warning({content:'This is a hint', duration: 2000, close: () => {}})

message.error({content:'This is a hint', duration: 2000, close: () => {}})

message.success({content:'This is a hint', duration: 2000, close: () => {}})

message.toast({content:'This is a hint', duration: 2000, close: () => {}})

参数说明类型
contentPrompt contentstring
durationAutomatic shutdown delay, in milliseconds. Default 3000 msnumber
closeCallback function triggered when closed() => void
`,16)]))}const m=e(l,[["render",p]]);export{E as __pageData,m as default}; diff --git a/assets/src_ranui_message_index.md.DywEIh7C.lean.js b/assets/src_ranui_message_index.md.DywEIh7C.lean.js new file mode 100644 index 0000000000..7bde5cabdf --- /dev/null +++ b/assets/src_ranui_message_index.md.DywEIh7C.lean.js @@ -0,0 +1,5 @@ +import{_ as e,o as n,c as h,j as s,a as t,a3 as a}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"message","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/message/index.md","filePath":"src/ranui/message/index.md","lastUpdated":1726550590000}'),l={name:"src/ranui/message/index.md"};function p(o,i,k,r,d,g){return n(),h("div",{"data-pagefind-body":!0},i[0]||(i[0]=[s("h1",{id:"message",tabindex:"-1"},[t("message "),s("a",{class:"header-anchor",href:"#message","aria-label":'Permalink to "message"'},"​")],-1),s("p",null,"Global display of operation feedback.",-1),s("h2",{id:"code-demo",tabindex:"-1"},[t("Code demo "),s("a",{class:"header-anchor",href:"#code-demo","aria-label":'Permalink to "Code demo"'},"​")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{type:"primary",onclick:"message.info('This is a hint')"},"Click to trigger the global prompt")],-1),a('
xml
<r-button type="primary" onclick="message.info('This is a hint')">Click to trigger the global prompt</r-button>

Attribute

type

Different prompt types

',4),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.info('This is a hint')"},"Information prompt")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.warning('This is a hint')"},"Warning prompt")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.error('This is a hint')"},"Error prompt")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.success('This is a hint')"},"Success tip")],-1),s("div",{style:{display:"inline-block","margin-right":"8px","margin-bottom":"12px"}},[s("r-button",{onclick:"message.toast('This is a hint')"},"toast tip")],-1),a(`
html
<r-button onclick="message.info('This is a hint')">Information prompt</r-button>
+<r-button onclick="message.warning('This is a hint')">Warning prompt</r-button>
+<r-button onclick="message.error('This is a hint')">Error prompt</r-button>
+<r-button onclick="message.success('This is a hint')">Success tip</r-button>
+<r-button onclick="message.toast('This is a hint')">toast tip</r-button>

Method

The component provides a number of static methods, using the following methods and parameters:

  1. You can pass only one parameter, prompt the content, the default prompt 3000 milliseconds

message.info('This is a hint')

message.warning('This is a hint')

message.error('This is a hint')

message.success('This is a hint')

message.toast('This is a hint')"

  1. You can also pass an object, set the prompt content, turn off the delay, and trigger the callback function when you close it

message.info({content:'This is a hint', duration: 2000, close: () => {}})

message.warning({content:'This is a hint', duration: 2000, close: () => {}})

message.error({content:'This is a hint', duration: 2000, close: () => {}})

message.success({content:'This is a hint', duration: 2000, close: () => {}})

message.toast({content:'This is a hint', duration: 2000, close: () => {}})

参数说明类型
contentPrompt contentstring
durationAutomatic shutdown delay, in milliseconds. Default 3000 msnumber
closeCallback function triggered when closed() => void
`,16)]))}const m=e(l,[["render",p]]);export{E as __pageData,m as default}; diff --git a/assets/src_ranui_modal_index.md.B-J1TEAz.js b/assets/src_ranui_modal_index.md.B-J1TEAz.js new file mode 100644 index 0000000000..38a9b59b26 --- /dev/null +++ b/assets/src_ranui_modal_index.md.B-J1TEAz.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as t}from"./chunks/framework.C-ai2y4t.js";const l=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/modal/index.md","filePath":"src/ranui/modal/index.md","lastUpdated":1726550590000}'),r={name:"src/ranui/modal/index.md"};function n(o,s,d,c,i,m){return a(),t("div")}const _=e(r,[["render",n]]);export{l as __pageData,_ as default}; diff --git a/assets/src_ranui_modal_index.md.B-J1TEAz.lean.js b/assets/src_ranui_modal_index.md.B-J1TEAz.lean.js new file mode 100644 index 0000000000..38a9b59b26 --- /dev/null +++ b/assets/src_ranui_modal_index.md.B-J1TEAz.lean.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as t}from"./chunks/framework.C-ai2y4t.js";const l=JSON.parse('{"title":"","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/modal/index.md","filePath":"src/ranui/modal/index.md","lastUpdated":1726550590000}'),r={name:"src/ranui/modal/index.md"};function n(o,s,d,c,i,m){return a(),t("div")}const _=e(r,[["render",n]]);export{l as __pageData,_ as default}; diff --git a/assets/src_ranui_player_index.md.D9OUB_JI.js b/assets/src_ranui_player_index.md.D9OUB_JI.js new file mode 100644 index 0000000000..21cd0e1b8b --- /dev/null +++ b/assets/src_ranui_player_index.md.D9OUB_JI.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"r-player","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/player/index.md","filePath":"src/ranui/player/index.md","lastUpdated":1726550590000}'),i={name:"src/ranui/player/index.md"};function n(o,t,l,s,h,p){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

r-player

Video player

Based on 'hlsjs' and' web components', let the native tag 'r-player' have a unified video control. Do not use the 'new Player(options)' way to mount to the specified 'dom', view return view, logic return logic, see and get, more intuitive.

  1. Drag and drop the progress bar
  2. Volume control
  3. The bitrate is automatically switched based on the current bandwidth
  4. Manual definition switch
  5. Play at double speed
  6. Style custom overlay
  7. 'hls' protocol standard encryption video playback
  8. Based on native development, it can run in all frameworks and unify the cross-framework situation
  9. Unified browser controls

Code demo

xml
  <r-player src="/ran/hls/example.m3u8"></r-player>

Attribute

src

Resource address of the video

volume

Set the initial volume. The default is 0.5

currentTime

Set the initial playback time. By default, the playback starts from the beginning

playbackRate

Set the double speed. The default is 1.0

debug

console.log some info

event

onchange

Listen for any player changes, and the value returned is as follows.

An 'instance of the player' can be obtained through this method.

Live by 'type' to judge different event types, perform different operations

propertyexplains thatis of type
typeIndicates the type of the changed event'string'
dataThe value of the'Object'
currentTimeThe current playback time'number'
durationTotal duration of videos'number'
tagAn example of the player'Element'

Where 'type' type has

NameDescription
canplayYour browser is ready to play the media file, but it probably doesn't have enough data to play it to the end without pausing to buffer the content further.
canplaythroughThe browser estimates that it canplay media until the end without stopping content buffering.
completeOfflineAudioContext The rendering is complete.
durationchangeduration is triggered when the value of the duration property changes.
emptiedMedia content emptied; For example, when the media is already loaded (or partially loaded), this event is sent and the load() method is called to reload it.
endedThe video stops playing because the media has reached the end point.
loadedmetadataThe metadata is loaded.
progressis triggered periodically when the browser loads the resource.
ratechangeThe play rate changes.
seekedThe seek operation is complete.
seekingseek begins.
stalledThe user agent is trying to obtain media data but it has not appeared unexpectedly.
suspendMedia data loading has been suspended.
loadeddataThe first frame in media has been added. media has loaded.
timeupdateThe time specified by the currentTime property changes. currentTime attribute has changed.
volumechangeThe volume changes.
waitingPlaying has stopped due to lack of data.
playPlayback has started.
playingAfter a pause or delay due to lack of data, playback is ready to begin.
pausePlay is paused.
volumeThe volume changes.
fullscreenTriggers a full-screen event
',26)]))}const m=e(i,[["render",n]]);export{u as __pageData,m as default}; diff --git a/assets/src_ranui_player_index.md.D9OUB_JI.lean.js b/assets/src_ranui_player_index.md.D9OUB_JI.lean.js new file mode 100644 index 0000000000..21cd0e1b8b --- /dev/null +++ b/assets/src_ranui_player_index.md.D9OUB_JI.lean.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"r-player","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/player/index.md","filePath":"src/ranui/player/index.md","lastUpdated":1726550590000}'),i={name:"src/ranui/player/index.md"};function n(o,t,l,s,h,p){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

r-player

Video player

Based on 'hlsjs' and' web components', let the native tag 'r-player' have a unified video control. Do not use the 'new Player(options)' way to mount to the specified 'dom', view return view, logic return logic, see and get, more intuitive.

  1. Drag and drop the progress bar
  2. Volume control
  3. The bitrate is automatically switched based on the current bandwidth
  4. Manual definition switch
  5. Play at double speed
  6. Style custom overlay
  7. 'hls' protocol standard encryption video playback
  8. Based on native development, it can run in all frameworks and unify the cross-framework situation
  9. Unified browser controls

Code demo

xml
  <r-player src="/ran/hls/example.m3u8"></r-player>

Attribute

src

Resource address of the video

volume

Set the initial volume. The default is 0.5

currentTime

Set the initial playback time. By default, the playback starts from the beginning

playbackRate

Set the double speed. The default is 1.0

debug

console.log some info

event

onchange

Listen for any player changes, and the value returned is as follows.

An 'instance of the player' can be obtained through this method.

Live by 'type' to judge different event types, perform different operations

propertyexplains thatis of type
typeIndicates the type of the changed event'string'
dataThe value of the'Object'
currentTimeThe current playback time'number'
durationTotal duration of videos'number'
tagAn example of the player'Element'

Where 'type' type has

NameDescription
canplayYour browser is ready to play the media file, but it probably doesn't have enough data to play it to the end without pausing to buffer the content further.
canplaythroughThe browser estimates that it canplay media until the end without stopping content buffering.
completeOfflineAudioContext The rendering is complete.
durationchangeduration is triggered when the value of the duration property changes.
emptiedMedia content emptied; For example, when the media is already loaded (or partially loaded), this event is sent and the load() method is called to reload it.
endedThe video stops playing because the media has reached the end point.
loadedmetadataThe metadata is loaded.
progressis triggered periodically when the browser loads the resource.
ratechangeThe play rate changes.
seekedThe seek operation is complete.
seekingseek begins.
stalledThe user agent is trying to obtain media data but it has not appeared unexpectedly.
suspendMedia data loading has been suspended.
loadeddataThe first frame in media has been added. media has loaded.
timeupdateThe time specified by the currentTime property changes. currentTime attribute has changed.
volumechangeThe volume changes.
waitingPlaying has stopped due to lack of data.
playPlayback has started.
playingAfter a pause or delay due to lack of data, playback is ready to begin.
pausePlay is paused.
volumeThe volume changes.
fullscreenTriggers a full-screen event
',26)]))}const m=e(i,[["render",n]]);export{u as __pageData,m as default}; diff --git a/assets/src_ranui_popover_index.md.BCOhVsiF.js b/assets/src_ranui_popover_index.md.BCOhVsiF.js new file mode 100644 index 0000000000..2c056ba866 --- /dev/null +++ b/assets/src_ranui_popover_index.md.BCOhVsiF.js @@ -0,0 +1,26 @@ +import{_ as t,o as n,c as l,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"Popover","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/popover/index.md","filePath":"src/ranui/popover/index.md","lastUpdated":1726550590000}'),h={name:"src/ranui/popover/index.md"};function p(k,a,e,E,r,d){return n(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

Popover

Click/mouse to move into the element and pop up a bubbling card layer.

Code demo

popover
this is content
xml
<r-popover>
+    <r-button>popover</r-button>
+    <r-content>
+      <div>this is content</div>
+    </r-content>
+</r-popover>

Attribute

trigger

Trigger mode:

  • hover
`,9),s("r-popover",{trigger:"hover"},[s("r-button",null,"hover"),s("r-content",null,[s("div",null,"hover")])],-1),i(`
xml
<r-popover trigger="hover">
+    <r-button>hover</r-button>
+    <r-content>
+      <div>hover</div>
+    </r-content>
+  </r-popover>
  • click
`,2),s("r-popover",{trigger:"click"},[s("r-button",null,"click"),s("r-content",null,[s("div",null,"click")])],-1),i(`
xml
<r-popover trigger="click">
+    <r-button>click</r-button>
+    <r-content>
+      <div>click</div>
+    </r-content>
+  </r-popover>

placement

Display location

  • bottom
`,4),s("r-popover",{trigger:"hover",placement:"bottom"},[s("r-button",null,"bottom"),s("r-content",null,[s("div",null,"bottom")])],-1),i(`
xml
<r-popover trigger="hover" placement="bottom">
+    <r-button>bottom</r-button>
+    <r-content>
+      <div>bottom</div>
+    </r-content>
+  </r-popover>
  • top
`,2),s("r-popover",{trigger:"hover",placement:"top"},[s("r-button",null,"top"),s("r-content",null,[s("div",null,"top")])],-1),i(`
xml
<r-popover trigger="hover" placement="top">
+    <r-button>top</r-button>
+    <r-content>
+      <div>top</div>
+    </r-content>
+  </r-popover>
`,1)]))}const c=t(h,[["render",p]]);export{g as __pageData,c as default}; diff --git a/assets/src_ranui_popover_index.md.BCOhVsiF.lean.js b/assets/src_ranui_popover_index.md.BCOhVsiF.lean.js new file mode 100644 index 0000000000..2c056ba866 --- /dev/null +++ b/assets/src_ranui_popover_index.md.BCOhVsiF.lean.js @@ -0,0 +1,26 @@ +import{_ as t,o as n,c as l,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"Popover","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/popover/index.md","filePath":"src/ranui/popover/index.md","lastUpdated":1726550590000}'),h={name:"src/ranui/popover/index.md"};function p(k,a,e,E,r,d){return n(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

Popover

Click/mouse to move into the element and pop up a bubbling card layer.

Code demo

popover
this is content
xml
<r-popover>
+    <r-button>popover</r-button>
+    <r-content>
+      <div>this is content</div>
+    </r-content>
+</r-popover>

Attribute

trigger

Trigger mode:

  • hover
`,9),s("r-popover",{trigger:"hover"},[s("r-button",null,"hover"),s("r-content",null,[s("div",null,"hover")])],-1),i(`
xml
<r-popover trigger="hover">
+    <r-button>hover</r-button>
+    <r-content>
+      <div>hover</div>
+    </r-content>
+  </r-popover>
  • click
`,2),s("r-popover",{trigger:"click"},[s("r-button",null,"click"),s("r-content",null,[s("div",null,"click")])],-1),i(`
xml
<r-popover trigger="click">
+    <r-button>click</r-button>
+    <r-content>
+      <div>click</div>
+    </r-content>
+  </r-popover>

placement

Display location

  • bottom
`,4),s("r-popover",{trigger:"hover",placement:"bottom"},[s("r-button",null,"bottom"),s("r-content",null,[s("div",null,"bottom")])],-1),i(`
xml
<r-popover trigger="hover" placement="bottom">
+    <r-button>bottom</r-button>
+    <r-content>
+      <div>bottom</div>
+    </r-content>
+  </r-popover>
  • top
`,2),s("r-popover",{trigger:"hover",placement:"top"},[s("r-button",null,"top"),s("r-content",null,[s("div",null,"top")])],-1),i(`
xml
<r-popover trigger="hover" placement="top">
+    <r-button>top</r-button>
+    <r-content>
+      <div>top</div>
+    </r-content>
+  </r-popover>
`,1)]))}const c=t(h,[["render",p]]);export{g as __pageData,c as default}; diff --git a/assets/src_ranui_preview_index.md.Ky1AiWNQ.js b/assets/src_ranui_preview_index.md.Ky1AiWNQ.js new file mode 100644 index 0000000000..6722e257ad --- /dev/null +++ b/assets/src_ranui_preview_index.md.Ky1AiWNQ.js @@ -0,0 +1,20 @@ +import{_ as t,o as h,c as n,j as s,a,a3 as l}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"preview","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/preview/index.md","filePath":"src/ranui/preview/index.md","lastUpdated":1726550590000}'),e={name:"src/ranui/preview/index.md"};function p(k,i,E,r,d,g){return h(),n("div",{"data-pagefind-body":!0},i[0]||(i[0]=[s("h1",{id:"preview",tabindex:"-1"},[a("preview "),s("a",{class:"header-anchor",href:"#preview","aria-label":'Permalink to "preview"'},"​")],-1),s("p",null,"Support 'docx', 'pptx', 'pdf', 'xlsx' file preview",-1),s("h2",{id:"code-demo",tabindex:"-1"},[a("Code demo "),s("a",{class:"header-anchor",href:"#code-demo","aria-label":'Permalink to "Code demo"'},"​")],-1),s("div",{style:{width:"100px","margin-top":"10px"}},[s("r-preview",{id:"fdsafdsafdsafdsaf"}),s("r-button",{type:"primary",onclick:"uploadFile('fdsafdsafdsafdsaf')"},"choose file to preview")],-1),l(`
html
<r-preview id="preview"></r-preview>
+<r-button type="primary" onclick="uploadFile()">choose file to preview</r-button>
+
+<script>
+  const uploadFile = () => {
+    const preview = document.getElementById('preview');
+    const uploadFile = document.createElement('input');
+    uploadFile.setAttribute('type', 'file');
+    uploadFile.click();
+    uploadFile.onchange = (e) => {
+      const { files = [] } = uploadFile;
+      if (files.length > 0) {
+        preview.setAttribute('src', '');
+        const file = files[0];
+        const url = URL.createObjectURL(file);
+        preview.setAttribute('src', url);
+      }
+    };
+  };
+</script>

Attribute

src

If there is a 'src' address, the popup window will be opened, and if there is no 'src', it will not be displayed

html
<r-preview src=""></r-preview>

closeable

'closeable' defaults to 'true' and can be closed, when set to 'false', it cannot be closed, and the close button in the upper right corner will not be displayed

html
<r-preview closeable="false"></r-preview>
`,8)]))}const c=t(e,[["render",p]]);export{o as __pageData,c as default}; diff --git a/assets/src_ranui_preview_index.md.Ky1AiWNQ.lean.js b/assets/src_ranui_preview_index.md.Ky1AiWNQ.lean.js new file mode 100644 index 0000000000..6722e257ad --- /dev/null +++ b/assets/src_ranui_preview_index.md.Ky1AiWNQ.lean.js @@ -0,0 +1,20 @@ +import{_ as t,o as h,c as n,j as s,a,a3 as l}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"preview","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/preview/index.md","filePath":"src/ranui/preview/index.md","lastUpdated":1726550590000}'),e={name:"src/ranui/preview/index.md"};function p(k,i,E,r,d,g){return h(),n("div",{"data-pagefind-body":!0},i[0]||(i[0]=[s("h1",{id:"preview",tabindex:"-1"},[a("preview "),s("a",{class:"header-anchor",href:"#preview","aria-label":'Permalink to "preview"'},"​")],-1),s("p",null,"Support 'docx', 'pptx', 'pdf', 'xlsx' file preview",-1),s("h2",{id:"code-demo",tabindex:"-1"},[a("Code demo "),s("a",{class:"header-anchor",href:"#code-demo","aria-label":'Permalink to "Code demo"'},"​")],-1),s("div",{style:{width:"100px","margin-top":"10px"}},[s("r-preview",{id:"fdsafdsafdsafdsaf"}),s("r-button",{type:"primary",onclick:"uploadFile('fdsafdsafdsafdsaf')"},"choose file to preview")],-1),l(`
html
<r-preview id="preview"></r-preview>
+<r-button type="primary" onclick="uploadFile()">choose file to preview</r-button>
+
+<script>
+  const uploadFile = () => {
+    const preview = document.getElementById('preview');
+    const uploadFile = document.createElement('input');
+    uploadFile.setAttribute('type', 'file');
+    uploadFile.click();
+    uploadFile.onchange = (e) => {
+      const { files = [] } = uploadFile;
+      if (files.length > 0) {
+        preview.setAttribute('src', '');
+        const file = files[0];
+        const url = URL.createObjectURL(file);
+        preview.setAttribute('src', url);
+      }
+    };
+  };
+</script>

Attribute

src

If there is a 'src' address, the popup window will be opened, and if there is no 'src', it will not be displayed

html
<r-preview src=""></r-preview>

closeable

'closeable' defaults to 'true' and can be closed, when set to 'false', it cannot be closed, and the close button in the upper right corner will not be displayed

html
<r-preview closeable="false"></r-preview>
`,8)]))}const c=t(e,[["render",p]]);export{o as __pageData,c as default}; diff --git a/assets/src_ranui_progress_index.md.Cm1y50UG.js b/assets/src_ranui_progress_index.md.Cm1y50UG.js new file mode 100644 index 0000000000..d41ad35484 --- /dev/null +++ b/assets/src_ranui_progress_index.md.Cm1y50UG.js @@ -0,0 +1 @@ +import{_ as a,o as e,c as h,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"progress","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/progress/index.md","filePath":"src/ranui/progress/index.md","lastUpdated":1726550590000}'),p={name:"src/ranui/progress/index.md"};function l(r,t,n,k,d,E){return e(),h("div",{"data-pagefind-body":!0},t[0]||(t[0]=[i('

progress

Interactive progress bar

Code demo

xml
<r-progress type="drag" ></r-progress>

Attribute

total

Set progress bar Total progress, allowed percentages and numbers.

',8),s("r-progress",{percent:"30",total:"1000"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{percent:"70",total:"100"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{percent:"10%",total:"100%"},null,-1),i('
html
<r-progress percent="30" total="1000"></r-progress>\n<r-progress percent="70" total="100"></r-progress>\n<r-progress percent="10%" total="100%"></r-progress>

percent

Set the current progress of the progress bar, you can set the percentage and number, 'percent' cannot exceed 'total'. If 'total' is not set, the default 'total' is' 100% ', that is, '1'.

',3),s("r-progress",{type:"primary",percent:"30%"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"70%"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"100%"},null,-1),i('
html
<r-progress type="primary" percent="30%"></r-progress>\n<r-progress type="primary" percent="40%"></r-progress>\n<r-progress type="primary" percent="100%"></r-progress>

dot

Point of the progress bar, Default display, set to 'false' can be hidden

',3),s("r-progress",{type:"drag",percent:"30%",dot:"false"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"40%",dot:"true"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"40%"},null,-1),i('
html
<r-progress type="drag" percent="30%" dot="false"></r-progress>\n<r-progress type="primary" percent="40%" dot="true"></r-progress>\n<r-progress type="primary" percent="40%"></r-progress>

type

  • primary: Default progress bar, not setting the 'type' attribute is the default
  • drag: Draggable, clickable progress bar (dragging requires' dot 'to be' true ')
',3),s("r-progress",{type:"drag",percent:"30%"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"40%"},null,-1),i('
html
<r-progress type="drag" percent="30%"></r-progress> <r-progress type="primary" percent="40%"></r-progress>

Method

change

The 'change' event is triggered when the 'percent' and 'total' properties change.

propertyexplains thattype
valueCurrent progress'string or number'
percentCurrent progress'string or number'
totalTotal progress'string or number'
',5)]))}const y=a(p,[["render",l]]);export{o as __pageData,y as default}; diff --git a/assets/src_ranui_progress_index.md.Cm1y50UG.lean.js b/assets/src_ranui_progress_index.md.Cm1y50UG.lean.js new file mode 100644 index 0000000000..d41ad35484 --- /dev/null +++ b/assets/src_ranui_progress_index.md.Cm1y50UG.lean.js @@ -0,0 +1 @@ +import{_ as a,o as e,c as h,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const o=JSON.parse('{"title":"progress","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/progress/index.md","filePath":"src/ranui/progress/index.md","lastUpdated":1726550590000}'),p={name:"src/ranui/progress/index.md"};function l(r,t,n,k,d,E){return e(),h("div",{"data-pagefind-body":!0},t[0]||(t[0]=[i('

progress

Interactive progress bar

Code demo

xml
<r-progress type="drag" ></r-progress>

Attribute

total

Set progress bar Total progress, allowed percentages and numbers.

',8),s("r-progress",{percent:"30",total:"1000"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{percent:"70",total:"100"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{percent:"10%",total:"100%"},null,-1),i('
html
<r-progress percent="30" total="1000"></r-progress>\n<r-progress percent="70" total="100"></r-progress>\n<r-progress percent="10%" total="100%"></r-progress>

percent

Set the current progress of the progress bar, you can set the percentage and number, 'percent' cannot exceed 'total'. If 'total' is not set, the default 'total' is' 100% ', that is, '1'.

',3),s("r-progress",{type:"primary",percent:"30%"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"70%"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"100%"},null,-1),i('
html
<r-progress type="primary" percent="30%"></r-progress>\n<r-progress type="primary" percent="40%"></r-progress>\n<r-progress type="primary" percent="100%"></r-progress>

dot

Point of the progress bar, Default display, set to 'false' can be hidden

',3),s("r-progress",{type:"drag",percent:"30%",dot:"false"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"40%",dot:"true"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"40%"},null,-1),i('
html
<r-progress type="drag" percent="30%" dot="false"></r-progress>\n<r-progress type="primary" percent="40%" dot="true"></r-progress>\n<r-progress type="primary" percent="40%"></r-progress>

type

  • primary: Default progress bar, not setting the 'type' attribute is the default
  • drag: Draggable, clickable progress bar (dragging requires' dot 'to be' true ')
',3),s("r-progress",{type:"drag",percent:"30%"},null,-1),s("div",{style:{height:"20px",width:"10px"}},null,-1),s("r-progress",{type:"primary",percent:"40%"},null,-1),i('
html
<r-progress type="drag" percent="30%"></r-progress> <r-progress type="primary" percent="40%"></r-progress>

Method

change

The 'change' event is triggered when the 'percent' and 'total' properties change.

propertyexplains thattype
valueCurrent progress'string or number'
percentCurrent progress'string or number'
totalTotal progress'string or number'
',5)]))}const y=a(p,[["render",l]]);export{o as __pageData,y as default}; diff --git a/assets/src_ranui_radar_index.md.B7mPxzli.js b/assets/src_ranui_radar_index.md.B7mPxzli.js new file mode 100644 index 0000000000..58802dbf80 --- /dev/null +++ b/assets/src_ranui_radar_index.md.B7mPxzli.js @@ -0,0 +1,55 @@ +import{_ as e,o as l,c as o,j as t,a as s,a3 as a}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"Radar","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/radar/index.md","filePath":"src/ranui/radar/index.md","lastUpdated":1726550590000}'),n={name:"src/ranui/radar/index.md"};function h(p,i,r,k,u,d){return l(),o("div",{"data-pagefind-body":!0},i[0]||(i[0]=[t("h1",{id:"radar",tabindex:"-1"},[s("Radar "),t("a",{class:"header-anchor",href:"#radar","aria-label":'Permalink to "Radar"'},"​")],-1),t("p",null,"Comprehensive comparison of differences between multiple sets of data in two-dimensional form, often used to compare 2 or more sets of data",-1),t("h2",{id:"code-demo",tabindex:"-1"},[s("Code demo "),t("a",{class:"header-anchor",href:"#code-demo","aria-label":'Permalink to "Code demo"'},"​")],-1),t("r-radar",{style:{width:"300px",height:"300px",display:"block"},abilitys:'[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),a(`
xml
<r-radar
+abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

Attribute

abilitys

Data that needs to be presented

An array object with the following properties

keyDescriptiontype
abilityNameDisplays the attribute name'string'
scoreRateDisplays the dimension value. The maximum value is 100'number'
backgroundColorThe background color of theproperty is an optional string
fontSizeThe font size for the attribute nameThe optional parameter 'number'
fontFamilyThe font for the attribute nameis optional with 'string'
fontColorThe font color for theproperty is an optional parameter with string
`,6),t("r-radar",{style:{width:"300px",height:"300px",display:"block"},abilitys:'[{"abilityName":"HP","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),a(`
xml
<r-radar
+    abilitys='[{"abilityName":"HP","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

colorPolygon

`,2),t("r-radar",{style:{width:"300px",height:"300px",display:"block"},colorPolygon:"green",abilitys:'[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),a(`
xml
<r-radar
+    colorPolygon="green"
+    abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

colorLine

`,2),t("r-radar",{style:{width:"300px",height:"300px",display:"block"},colorLine:"blue",abilitys:'[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),a(`
xml
<r-radar
+    colorLine="blue"
+   abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
+></r-radar>

fillColor

`,2),t("r-radar",{style:{width:"300px",height:"300px",display:"block"},fillColor:"red",abilitys:'[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),a(`
xml
<r-radar
+    fillColor="red"
+   abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

strokeColor

`,2),t("r-radar",{style:{width:"300px",height:"300px",display:"block"},strokeColor:"blue",abilitys:'[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),a(`
xml
<r-radar
+    strokeColor="blue"
+   abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

Example data used

Because the 'attribute' of 'HTMl' can only get 'string'. Therefore, the data that needs to be passed in needs to be in the format of 'JSON' string, and then parsed by 'json.parse' array object, if the 'JSON' format is wrong, it cannot be parsed.

json
[
+  {
+    "abilityName": "HP",
+    "scoreRate": "10",
+    "backgroundColor": "red",
+    "fontSize": "30",
+    "fontColor": "blue"
+  },
+  {
+    "abilityName": "Attack",
+    "scoreRate": "90"
+  },
+  {
+    "abilityName": "DEF",
+    "scoreRate": "20"
+  },
+  {
+    "abilityName": "Element mastery",
+    "scoreRate": "50"
+  },
+  {
+    "abilityName": "Critical Hit Chance",
+    "scoreRate": "80"
+  },
+  {
+    "abilityName": "Critical hit damage",
+    "scoreRate": "50"
+  }
+]
`,4)]))}const c=e(n,[["render",h]]);export{E as __pageData,c as default}; diff --git a/assets/src_ranui_radar_index.md.B7mPxzli.lean.js b/assets/src_ranui_radar_index.md.B7mPxzli.lean.js new file mode 100644 index 0000000000..58802dbf80 --- /dev/null +++ b/assets/src_ranui_radar_index.md.B7mPxzli.lean.js @@ -0,0 +1,55 @@ +import{_ as e,o as l,c as o,j as t,a as s,a3 as a}from"./chunks/framework.C-ai2y4t.js";const E=JSON.parse('{"title":"Radar","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/radar/index.md","filePath":"src/ranui/radar/index.md","lastUpdated":1726550590000}'),n={name:"src/ranui/radar/index.md"};function h(p,i,r,k,u,d){return l(),o("div",{"data-pagefind-body":!0},i[0]||(i[0]=[t("h1",{id:"radar",tabindex:"-1"},[s("Radar "),t("a",{class:"header-anchor",href:"#radar","aria-label":'Permalink to "Radar"'},"​")],-1),t("p",null,"Comprehensive comparison of differences between multiple sets of data in two-dimensional form, often used to compare 2 or more sets of data",-1),t("h2",{id:"code-demo",tabindex:"-1"},[s("Code demo "),t("a",{class:"header-anchor",href:"#code-demo","aria-label":'Permalink to "Code demo"'},"​")],-1),t("r-radar",{style:{width:"300px",height:"300px",display:"block"},abilitys:'[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),a(`
xml
<r-radar
+abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

Attribute

abilitys

Data that needs to be presented

An array object with the following properties

keyDescriptiontype
abilityNameDisplays the attribute name'string'
scoreRateDisplays the dimension value. The maximum value is 100'number'
backgroundColorThe background color of theproperty is an optional string
fontSizeThe font size for the attribute nameThe optional parameter 'number'
fontFamilyThe font for the attribute nameis optional with 'string'
fontColorThe font color for theproperty is an optional parameter with string
`,6),t("r-radar",{style:{width:"300px",height:"300px",display:"block"},abilitys:'[{"abilityName":"HP","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),a(`
xml
<r-radar
+    abilitys='[{"abilityName":"HP","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

colorPolygon

`,2),t("r-radar",{style:{width:"300px",height:"300px",display:"block"},colorPolygon:"green",abilitys:'[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),a(`
xml
<r-radar
+    colorPolygon="green"
+    abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

colorLine

`,2),t("r-radar",{style:{width:"300px",height:"300px",display:"block"},colorLine:"blue",abilitys:'[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),a(`
xml
<r-radar
+    colorLine="blue"
+   abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
+></r-radar>

fillColor

`,2),t("r-radar",{style:{width:"300px",height:"300px",display:"block"},fillColor:"red",abilitys:'[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),a(`
xml
<r-radar
+    fillColor="red"
+   abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

strokeColor

`,2),t("r-radar",{style:{width:"300px",height:"300px",display:"block"},strokeColor:"blue",abilitys:'[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'},null,-1),a(`
xml
<r-radar
+    strokeColor="blue"
+   abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

Example data used

Because the 'attribute' of 'HTMl' can only get 'string'. Therefore, the data that needs to be passed in needs to be in the format of 'JSON' string, and then parsed by 'json.parse' array object, if the 'JSON' format is wrong, it cannot be parsed.

json
[
+  {
+    "abilityName": "HP",
+    "scoreRate": "10",
+    "backgroundColor": "red",
+    "fontSize": "30",
+    "fontColor": "blue"
+  },
+  {
+    "abilityName": "Attack",
+    "scoreRate": "90"
+  },
+  {
+    "abilityName": "DEF",
+    "scoreRate": "20"
+  },
+  {
+    "abilityName": "Element mastery",
+    "scoreRate": "50"
+  },
+  {
+    "abilityName": "Critical Hit Chance",
+    "scoreRate": "80"
+  },
+  {
+    "abilityName": "Critical hit damage",
+    "scoreRate": "50"
+  }
+]
`,4)]))}const c=e(n,[["render",h]]);export{E as __pageData,c as default}; diff --git a/assets/src_ranui_select_index.md.BX7CAaZq.js b/assets/src_ranui_select_index.md.BX7CAaZq.js new file mode 100644 index 0000000000..c490b33a06 --- /dev/null +++ b/assets/src_ranui_select_index.md.BX7CAaZq.js @@ -0,0 +1,42 @@ +import{_ as h,o as l,c as n,j as s,a as t,a3 as i}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"Select","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/select/index.md","filePath":"src/ranui/select/index.md","lastUpdated":1726550590000}'),p={name:"src/ranui/select/index.md"};function k(e,a,E,r,d,o){return l(),n("div",{"data-pagefind-body":!0},a[0]||(a[0]=[s("h1",{id:"select",tabindex:"-1"},[t("Select "),s("a",{class:"header-anchor",href:"#select","aria-label":'Permalink to "Select"'},"​")],-1),s("p",null,"A regular pull-down selector.",-1),s("h2",{id:"code-demo",tabindex:"-1"},[t("Code demo "),s("a",{class:"header-anchor",href:"#code-demo","aria-label":'Permalink to "Code demo"'},"​")],-1),s("r-select",{style:{width:"120px",height:"40px"},defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select style="width: 120px; height: 40px" defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

Attribute

defaultValue

Sets the currently selected value

`,4),s("r-select",{style:{width:"120px",height:"40px"},defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
    <r-select style="width: 120px; height: 40px" defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

disabled

Adding the disabled attribute makes the selection box unavailable and changes the style.

`,3),s("r-select",{style:{width:"120px",height:"40px"},disabled:"",defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
    <r-select style="width: 120px; height: 40px" disabled defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

type

You can set the text type without borders and drop-down ICONS

`,3),s("r-select",{style:{width:"120px",height:"40px"},type:"text",defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select
+      style="width: 120px; height: 40px"
+      type="text"
+      defaultValue="185"
+    >
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

placement

Drop-down box display direction default down, set to 'top' can go up

`,3),s("r-select",{style:{width:"120px",height:"40px"},type:"text",defaultValue:"185",placement:"top"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select
+      style="width: 120px; height: 40px"
+      type="text"
+      defaultValue="185"
+      placement="top"
+    >
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

showSearch

Expand to search for options

`,3),s("r-select",{style:{width:"120px",height:"40px"},showSearch:""},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select style="width: 120px; height: 40px" showSearch>
+<r-option value="185">Mike</r-option>
+<r-option value="186">Tom</r-option>
+<r-option value="187">Lucy</r-option>
+</r-select>

getPopupContainerId

The drop-down box is mounted to document.body by default, and can be mounted to the specified element by passing in the element's id \`

MikeTomLucy
xml
<r-select getPopupContainerId="elementid">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

If you need to customize the style of the drop-down box, you can pass in a 'class' name to customize

trigger

'select' The method that the component triggers. Default 'click', click trigger. You can set 'hover', or 'click,hover', which means that both click and mouse move trigger.

If it is set to none, it will not trigger.

`,10),s("r-select",{style:{width:"120px",height:"40px"},trigger:"click,hover"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select getPopupContainerId="elementid" action="click,hover">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>
`,1)]))}const u=h(p,[["render",k]]);export{y as __pageData,u as default}; diff --git a/assets/src_ranui_select_index.md.BX7CAaZq.lean.js b/assets/src_ranui_select_index.md.BX7CAaZq.lean.js new file mode 100644 index 0000000000..c490b33a06 --- /dev/null +++ b/assets/src_ranui_select_index.md.BX7CAaZq.lean.js @@ -0,0 +1,42 @@ +import{_ as h,o as l,c as n,j as s,a as t,a3 as i}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"Select","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/select/index.md","filePath":"src/ranui/select/index.md","lastUpdated":1726550590000}'),p={name:"src/ranui/select/index.md"};function k(e,a,E,r,d,o){return l(),n("div",{"data-pagefind-body":!0},a[0]||(a[0]=[s("h1",{id:"select",tabindex:"-1"},[t("Select "),s("a",{class:"header-anchor",href:"#select","aria-label":'Permalink to "Select"'},"​")],-1),s("p",null,"A regular pull-down selector.",-1),s("h2",{id:"code-demo",tabindex:"-1"},[t("Code demo "),s("a",{class:"header-anchor",href:"#code-demo","aria-label":'Permalink to "Code demo"'},"​")],-1),s("r-select",{style:{width:"120px",height:"40px"},defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select style="width: 120px; height: 40px" defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

Attribute

defaultValue

Sets the currently selected value

`,4),s("r-select",{style:{width:"120px",height:"40px"},defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
    <r-select style="width: 120px; height: 40px" defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

disabled

Adding the disabled attribute makes the selection box unavailable and changes the style.

`,3),s("r-select",{style:{width:"120px",height:"40px"},disabled:"",defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
    <r-select style="width: 120px; height: 40px" disabled defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

type

You can set the text type without borders and drop-down ICONS

`,3),s("r-select",{style:{width:"120px",height:"40px"},type:"text",defaultValue:"185"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select
+      style="width: 120px; height: 40px"
+      type="text"
+      defaultValue="185"
+    >
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

placement

Drop-down box display direction default down, set to 'top' can go up

`,3),s("r-select",{style:{width:"120px",height:"40px"},type:"text",defaultValue:"185",placement:"top"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select
+      style="width: 120px; height: 40px"
+      type="text"
+      defaultValue="185"
+      placement="top"
+    >
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

showSearch

Expand to search for options

`,3),s("r-select",{style:{width:"120px",height:"40px"},showSearch:""},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select style="width: 120px; height: 40px" showSearch>
+<r-option value="185">Mike</r-option>
+<r-option value="186">Tom</r-option>
+<r-option value="187">Lucy</r-option>
+</r-select>

getPopupContainerId

The drop-down box is mounted to document.body by default, and can be mounted to the specified element by passing in the element's id \`

MikeTomLucy
xml
<r-select getPopupContainerId="elementid">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

If you need to customize the style of the drop-down box, you can pass in a 'class' name to customize

trigger

'select' The method that the component triggers. Default 'click', click trigger. You can set 'hover', or 'click,hover', which means that both click and mouse move trigger.

If it is set to none, it will not trigger.

`,10),s("r-select",{style:{width:"120px",height:"40px"},trigger:"click,hover"},[s("r-option",{value:"185"},"Mike"),s("r-option",{value:"186"},"Tom"),s("r-option",{value:"187"},"Lucy")],-1),i(`
xml
<r-select getPopupContainerId="elementid" action="click,hover">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>
`,1)]))}const u=h(p,[["render",k]]);export{y as __pageData,u as default}; diff --git a/assets/src_ranui_skeleton_index.md.CLg9OTaj.js b/assets/src_ranui_skeleton_index.md.CLg9OTaj.js new file mode 100644 index 0000000000..2037495c64 --- /dev/null +++ b/assets/src_ranui_skeleton_index.md.CLg9OTaj.js @@ -0,0 +1 @@ +import{_ as t,o as s,c as a,a3 as i}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"skeleton","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/skeleton/index.md","filePath":"src/ranui/skeleton/index.md","lastUpdated":1726550590000}'),n={name:"src/ranui/skeleton/index.md"};function o(l,e,r,d,p,h){return s(),a("div",{"data-pagefind-body":!0},e[0]||(e[0]=[i('

skeleton

Provides a combination of placeholder graphics where you need to wait for content to load.

Code demo

The skeleton length follows the length of the parent element

xml
<r-skeleton ></r-skeleton>
',9)]))}const m=t(n,[["render",o]]);export{c as __pageData,m as default}; diff --git a/assets/src_ranui_skeleton_index.md.CLg9OTaj.lean.js b/assets/src_ranui_skeleton_index.md.CLg9OTaj.lean.js new file mode 100644 index 0000000000..2037495c64 --- /dev/null +++ b/assets/src_ranui_skeleton_index.md.CLg9OTaj.lean.js @@ -0,0 +1 @@ +import{_ as t,o as s,c as a,a3 as i}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"skeleton","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/skeleton/index.md","filePath":"src/ranui/skeleton/index.md","lastUpdated":1726550590000}'),n={name:"src/ranui/skeleton/index.md"};function o(l,e,r,d,p,h){return s(),a("div",{"data-pagefind-body":!0},e[0]||(e[0]=[i('

skeleton

Provides a combination of placeholder graphics where you need to wait for content to load.

Code demo

The skeleton length follows the length of the parent element

xml
<r-skeleton ></r-skeleton>
',9)]))}const m=t(n,[["render",o]]);export{c as __pageData,m as default}; diff --git a/assets/src_ranui_tab_index.md.DJ6wHDqA.js b/assets/src_ranui_tab_index.md.DJ6wHDqA.js new file mode 100644 index 0000000000..c5b45b2514 --- /dev/null +++ b/assets/src_ranui_tab_index.md.DJ6wHDqA.js @@ -0,0 +1,43 @@ +import{_ as t,o as l,c as h,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"Tab","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/tab/index.md","filePath":"src/ranui/tab/index.md","lastUpdated":1726550590000}'),k={name:"src/ranui/tab/index.md"};function n(p,a,e,E,r,d){return l(),h("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

Tab

TAB pages, where 'r-tab' needs to be used with 'r-tabs'

Code demo

111112222233333
xml
<r-tabs >
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

Attribute

label

'r-tab' property to set the name of the tag

111112222233333
xml
<r-tabs >
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

active tag 'active', the tag's unique identifier 'ranKey'

  • 'ranKey' is an attribute of 'r-tab' that determines the unique value of 'r-tab' under the same 'r-tabs'. If 'ranKey' is not set, it defaults to 'index'. (Not using the 'key' field is to prevent the 'key' is reserved field)
  • 'active' is an attribute of 'r-tabs', which is used to set active tabs. The label 'active' equals' key 'is an active label.
  1. 'key' is not set
`,13),s("div",{style:{width:"100%"}},[s("r-tabs",{active:"1"},[s("r-tab",{label:"tab1"},"11111"),s("r-tab",{label:"tab2"},"22222"),s("r-tab",{label:"tab3"},"33333")])],-1),i(`
xml
 <r-tabs active="1">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+ </r-tabs>
  1. Set 'key'
`,2),s("div",{style:{width:"100%"}},[s("r-tabs",{active:"c"},[s("r-tab",{label:"tab1",ranKey:"a"},"11111"),s("r-tab",{label:"tab2",ranKey:"b"},"22222"),s("r-tab",{label:"tab3",ranKey:"c"},"33333"),s("r-tab",{label:"tab4"},"4")])],-1),i(`
xml
    <r-tabs active="c">
+      <r-tab label="tab1" ranKey="a">11111</r-tab>
+      <r-tab label="tab2" ranKey="b">22222</r-tab>
+      <r-tab label="tab3" ranKey="c">33333</r-tab>
+      <r-tab label="tab4">4</r-tab>
+    </r-tabs>

disabled

Set unclickable labels

`,3),s("div",{style:{width:"100%"}},[s("r-tabs",{active:"c"},[s("r-tab",{label:"tab1",ranKey:"a",disabled:""},"11111"),s("r-tab",{label:"tab2",ranKey:"b"},"22222"),s("r-tab",{label:"tab3",ranKey:"c"},"33333"),s("r-tab",{label:"tab4"},"4")])],-1),i(`
xml
    <r-tabs active="c">
+      <r-tab label="tab1" ranKey="a" disabled>11111</r-tab>
+      <r-tab label="tab2" ranKey="b">22222</r-tab>
+      <r-tab label="tab3" ranKey="c">33333</r-tab>
+      <r-tab label="tab4">4</r-tab>
+    </r-tabs>

type

The 'r-tabs' property sets the types of tabs. If not set, the default is' flat '

  1. flat
111112222233333
xml
<r-tabs type="flat">
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>
  1. line
111112222233333
xml
<r-tabs type="line">
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

align

Set the alignment of the label. The default is' align="start" '

  1. start
111112222233333
xml
 <r-tabs type="line" align="start">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
  1. center
111112222233333
xml
 <r-tabs type="line" align="center">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
  1. end
111112222233333
xml
 <r-tabs type="line" align="end">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
`,20)]))}const b=t(k,[["render",n]]);export{y as __pageData,b as default}; diff --git a/assets/src_ranui_tab_index.md.DJ6wHDqA.lean.js b/assets/src_ranui_tab_index.md.DJ6wHDqA.lean.js new file mode 100644 index 0000000000..c5b45b2514 --- /dev/null +++ b/assets/src_ranui_tab_index.md.DJ6wHDqA.lean.js @@ -0,0 +1,43 @@ +import{_ as t,o as l,c as h,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const y=JSON.parse('{"title":"Tab","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/tab/index.md","filePath":"src/ranui/tab/index.md","lastUpdated":1726550590000}'),k={name:"src/ranui/tab/index.md"};function n(p,a,e,E,r,d){return l(),h("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

Tab

TAB pages, where 'r-tab' needs to be used with 'r-tabs'

Code demo

111112222233333
xml
<r-tabs >
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

Attribute

label

'r-tab' property to set the name of the tag

111112222233333
xml
<r-tabs >
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

active tag 'active', the tag's unique identifier 'ranKey'

  • 'ranKey' is an attribute of 'r-tab' that determines the unique value of 'r-tab' under the same 'r-tabs'. If 'ranKey' is not set, it defaults to 'index'. (Not using the 'key' field is to prevent the 'key' is reserved field)
  • 'active' is an attribute of 'r-tabs', which is used to set active tabs. The label 'active' equals' key 'is an active label.
  1. 'key' is not set
`,13),s("div",{style:{width:"100%"}},[s("r-tabs",{active:"1"},[s("r-tab",{label:"tab1"},"11111"),s("r-tab",{label:"tab2"},"22222"),s("r-tab",{label:"tab3"},"33333")])],-1),i(`
xml
 <r-tabs active="1">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+ </r-tabs>
  1. Set 'key'
`,2),s("div",{style:{width:"100%"}},[s("r-tabs",{active:"c"},[s("r-tab",{label:"tab1",ranKey:"a"},"11111"),s("r-tab",{label:"tab2",ranKey:"b"},"22222"),s("r-tab",{label:"tab3",ranKey:"c"},"33333"),s("r-tab",{label:"tab4"},"4")])],-1),i(`
xml
    <r-tabs active="c">
+      <r-tab label="tab1" ranKey="a">11111</r-tab>
+      <r-tab label="tab2" ranKey="b">22222</r-tab>
+      <r-tab label="tab3" ranKey="c">33333</r-tab>
+      <r-tab label="tab4">4</r-tab>
+    </r-tabs>

disabled

Set unclickable labels

`,3),s("div",{style:{width:"100%"}},[s("r-tabs",{active:"c"},[s("r-tab",{label:"tab1",ranKey:"a",disabled:""},"11111"),s("r-tab",{label:"tab2",ranKey:"b"},"22222"),s("r-tab",{label:"tab3",ranKey:"c"},"33333"),s("r-tab",{label:"tab4"},"4")])],-1),i(`
xml
    <r-tabs active="c">
+      <r-tab label="tab1" ranKey="a" disabled>11111</r-tab>
+      <r-tab label="tab2" ranKey="b">22222</r-tab>
+      <r-tab label="tab3" ranKey="c">33333</r-tab>
+      <r-tab label="tab4">4</r-tab>
+    </r-tabs>

type

The 'r-tabs' property sets the types of tabs. If not set, the default is' flat '

  1. flat
111112222233333
xml
<r-tabs type="flat">
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>
  1. line
111112222233333
xml
<r-tabs type="line">
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

align

Set the alignment of the label. The default is' align="start" '

  1. start
111112222233333
xml
 <r-tabs type="line" align="start">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
  1. center
111112222233333
xml
 <r-tabs type="line" align="center">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
  1. end
111112222233333
xml
 <r-tabs type="line" align="end">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
`,20)]))}const b=t(k,[["render",n]]);export{y as __pageData,b as default}; diff --git a/assets/src_ranui_tabs_index.md.DL4ch3vN.js b/assets/src_ranui_tabs_index.md.DL4ch3vN.js new file mode 100644 index 0000000000..8ff88b78e8 --- /dev/null +++ b/assets/src_ranui_tabs_index.md.DL4ch3vN.js @@ -0,0 +1,25 @@ +import{_ as t,o as h,c as l,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const b=JSON.parse('{"title":"Tab","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/tabs/index.md","filePath":"src/ranui/tabs/index.md","lastUpdated":1726550590000}'),n={name:"src/ranui/tabs/index.md"};function k(e,a,p,E,r,d){return h(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

Tab

Code demo

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2">tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

Attribute

label

Each 'r-tab' needs to specify a name 'label', which is used to display the label header.

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2">tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

disabled

Each 'r-tab' can be specified with the 'disabled' attribute to disable the TAB.

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2" disabled>tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

Identifies' key ', 'active'

Each 'r-tab' needs to specify an identifier 'key', no default sequence number is' key ',

'active' works on 'r-tabs' and can specify a switch to a specific TAB or an initial value.

`,16),s("r-tabs",{active:"B"},[s("r-tab",{label:"tab1","r-key":"A"},"tab1"),s("r-tab",{label:"tab2","r-key":"B"},"tab2"),s("r-tab",{label:"tab3","r-key":"C"},"tab3")],-1),i(`
html
<r-tabs active="B">
+  <r-tab label="tab1" r-key="A">tab1</r-tab>
+  <r-tab label="tab2" r-key="B">tab2</r-tab>
+  <r-tab label="tab3" r-key="C">tab3</r-tab>
+</r-tabs>

icon

Each 'r-tab' can specify 'icon', with 'label' to achieve the effect of icon plus text.

tab1tab2tab3
html
<r-tabs>
+  <r-tab label="home" icon="home">tab1</r-tab>
+  <r-tab label="message" icon="message">tab2</r-tab>
+  <r-tab label="user" icon="user">tab3</r-tab>
+</r-tabs>

It is also possible to specify 'icon' alone, without using 'label'. However, in this case, the size of the icon must be set, otherwise the size of the icon cannot be judged

`,6),s("r-tabs",null,[s("r-tab",{icon:"home",iconSize:"22"},"tab1"),s("r-tab",{icon:"message",iconSize:"22"},"tab2"),s("r-tab",{icon:"user",iconSize:"22"},"tab3")],-1),i(`
html
<r-tabs>
+  <r-tab icon="home" iconSize="22">tab1</r-tab>
+  <r-tab icon="message" iconSize="22">tab2</r-tab>
+  <r-tab icon="user" iconSize="22">tab3</r-tab>
+</r-tabs>

'type'

The style is text, clean,

event '

onchange

Triggered when the switch is complete.

`,6)]))}const y=t(n,[["render",k]]);export{b as __pageData,y as default}; diff --git a/assets/src_ranui_tabs_index.md.DL4ch3vN.lean.js b/assets/src_ranui_tabs_index.md.DL4ch3vN.lean.js new file mode 100644 index 0000000000..8ff88b78e8 --- /dev/null +++ b/assets/src_ranui_tabs_index.md.DL4ch3vN.lean.js @@ -0,0 +1,25 @@ +import{_ as t,o as h,c as l,a3 as i,j as s}from"./chunks/framework.C-ai2y4t.js";const b=JSON.parse('{"title":"Tab","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranui/tabs/index.md","filePath":"src/ranui/tabs/index.md","lastUpdated":1726550590000}'),n={name:"src/ranui/tabs/index.md"};function k(e,a,p,E,r,d){return h(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i(`

Tab

Code demo

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2">tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

Attribute

label

Each 'r-tab' needs to specify a name 'label', which is used to display the label header.

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2">tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

disabled

Each 'r-tab' can be specified with the 'disabled' attribute to disable the TAB.

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2" disabled>tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

Identifies' key ', 'active'

Each 'r-tab' needs to specify an identifier 'key', no default sequence number is' key ',

'active' works on 'r-tabs' and can specify a switch to a specific TAB or an initial value.

`,16),s("r-tabs",{active:"B"},[s("r-tab",{label:"tab1","r-key":"A"},"tab1"),s("r-tab",{label:"tab2","r-key":"B"},"tab2"),s("r-tab",{label:"tab3","r-key":"C"},"tab3")],-1),i(`
html
<r-tabs active="B">
+  <r-tab label="tab1" r-key="A">tab1</r-tab>
+  <r-tab label="tab2" r-key="B">tab2</r-tab>
+  <r-tab label="tab3" r-key="C">tab3</r-tab>
+</r-tabs>

icon

Each 'r-tab' can specify 'icon', with 'label' to achieve the effect of icon plus text.

tab1tab2tab3
html
<r-tabs>
+  <r-tab label="home" icon="home">tab1</r-tab>
+  <r-tab label="message" icon="message">tab2</r-tab>
+  <r-tab label="user" icon="user">tab3</r-tab>
+</r-tabs>

It is also possible to specify 'icon' alone, without using 'label'. However, in this case, the size of the icon must be set, otherwise the size of the icon cannot be judged

`,6),s("r-tabs",null,[s("r-tab",{icon:"home",iconSize:"22"},"tab1"),s("r-tab",{icon:"message",iconSize:"22"},"tab2"),s("r-tab",{icon:"user",iconSize:"22"},"tab3")],-1),i(`
html
<r-tabs>
+  <r-tab icon="home" iconSize="22">tab1</r-tab>
+  <r-tab icon="message" iconSize="22">tab2</r-tab>
+  <r-tab icon="user" iconSize="22">tab3</r-tab>
+</r-tabs>

'type'

The style is text, clean,

event '

onchange

Triggered when the switch is complete.

`,6)]))}const y=t(n,[["render",k]]);export{b as __pageData,y as default}; diff --git a/assets/src_ranuts_binaryTree_index.md.1xzpa2sH.js b/assets/src_ranuts_binaryTree_index.md.1xzpa2sH.js new file mode 100644 index 0000000000..84b1ce49f0 --- /dev/null +++ b/assets/src_ranuts_binaryTree_index.md.1xzpa2sH.js @@ -0,0 +1 @@ +import{_ as e}from"./chunks/balanceTree.CCEoBiag.js";import{_ as r,o as i,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"二叉树的定义","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/binaryTree/index.md","filePath":"src/ranuts/binaryTree/index.md","lastUpdated":1726550590000}'),l={name:"src/ranuts/binaryTree/index.md"};function o(n,a,d,s,c,u){return i(),t("div",{"data-pagefind-body":!0},a[0]||(a[0]=[h('

二叉树的定义

在计算机科学中,二叉树(Binary tree)是每个节点最多只有两个分支(即不存在分支度大于 2 的节点)的树结构。通常分支被称作“左子树”或“右子树”。二叉树的分支具有左右次序,不能随意颠倒[1]。。

二叉树的性质

  • 在二叉树的第 i 层上最多有 2^(i-1)个结点(i>=1)
  • 深度为 h 的二叉树,最多有 2^h-1 个结点,最少有 h 个结点(h>=1)
  • 包含 n 个结点的二叉树的高度至少为(log2n)+1
  • 非空的二叉树,分支度为 0 的总数为 n0,分支度为 2 的总数为 n2,则 n0=n2+1
  • 二叉树的总结点数 n = n1 + n2 + n0
  • 总连线数等于总节点数减一(B = n - 1)
  • 总连线数等于分支度为 2 的节点的两倍加上分支度为 1 的节点(B = n2 _ 2 + n1 _ 1)

二叉树的类型

满二叉树

一棵深度为 k 且有 2k-1 个节点的二叉树称为满二叉树。 除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树[2]

完全二叉树

一棵深度为 k 的有 n 个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为 i(1≤i≤n)的结点与满二叉树中编号为 i 的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。

二叉搜索树

二叉搜索树(BST)又称二叉查找树或二叉排序树。它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

平衡二叉树

平衡二叉树(AVL)一定是二叉搜索树,且左子树和右子树的高度差的绝对值不超过 1。 平衡二叉树

B 树

B 树属于多叉树又名平衡多路查找树(查找路径不只两个)

B+树

B+树是 B 树的变体,也是一种多路搜索树。

B*树

B* 树是 B+树的变体,在 B+树的非根和非叶子结点再增加指向兄弟的指针;B* 树定义了非叶子结点关键字个数至少为(2/3)M,即块的最低使用率为 2/3(代替 B+树的 1/2)。B 树分配新结点的概率比 B+树要低,空间使用率更高;

红黑树

红黑树是一种平衡二叉查找树的变体,它的左右子树高差有可能大于 1,所以红黑树不是严格意义上的平衡二叉树(AVL),但对它进行平衡的代价较低, 其平均统计性能要强于 AVL 。

遍历

前序遍历

后序遍历

中序遍历

层序遍历

常见算法题

镜像二叉树

重建二叉树

二叉树深度

二叉树节点总数

判断二叉树子结构

输入两棵二叉树 A 和 B,判断 B 是不是 A 的子结构。(ps:约定空树不是任意一个树的子结构)

参考文档

  1. 维基百科二叉树
  2. 百度百科满二叉树
',36)]))}const m=r(l,[["render",o]]);export{p as __pageData,m as default}; diff --git a/assets/src_ranuts_binaryTree_index.md.1xzpa2sH.lean.js b/assets/src_ranuts_binaryTree_index.md.1xzpa2sH.lean.js new file mode 100644 index 0000000000..84b1ce49f0 --- /dev/null +++ b/assets/src_ranuts_binaryTree_index.md.1xzpa2sH.lean.js @@ -0,0 +1 @@ +import{_ as e}from"./chunks/balanceTree.CCEoBiag.js";import{_ as r,o as i,c as t,a3 as h}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"二叉树的定义","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/binaryTree/index.md","filePath":"src/ranuts/binaryTree/index.md","lastUpdated":1726550590000}'),l={name:"src/ranuts/binaryTree/index.md"};function o(n,a,d,s,c,u){return i(),t("div",{"data-pagefind-body":!0},a[0]||(a[0]=[h('

二叉树的定义

在计算机科学中,二叉树(Binary tree)是每个节点最多只有两个分支(即不存在分支度大于 2 的节点)的树结构。通常分支被称作“左子树”或“右子树”。二叉树的分支具有左右次序,不能随意颠倒[1]。。

二叉树的性质

  • 在二叉树的第 i 层上最多有 2^(i-1)个结点(i>=1)
  • 深度为 h 的二叉树,最多有 2^h-1 个结点,最少有 h 个结点(h>=1)
  • 包含 n 个结点的二叉树的高度至少为(log2n)+1
  • 非空的二叉树,分支度为 0 的总数为 n0,分支度为 2 的总数为 n2,则 n0=n2+1
  • 二叉树的总结点数 n = n1 + n2 + n0
  • 总连线数等于总节点数减一(B = n - 1)
  • 总连线数等于分支度为 2 的节点的两倍加上分支度为 1 的节点(B = n2 _ 2 + n1 _ 1)

二叉树的类型

满二叉树

一棵深度为 k 且有 2k-1 个节点的二叉树称为满二叉树。 除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树[2]

完全二叉树

一棵深度为 k 的有 n 个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为 i(1≤i≤n)的结点与满二叉树中编号为 i 的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。

二叉搜索树

二叉搜索树(BST)又称二叉查找树或二叉排序树。它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

平衡二叉树

平衡二叉树(AVL)一定是二叉搜索树,且左子树和右子树的高度差的绝对值不超过 1。 平衡二叉树

B 树

B 树属于多叉树又名平衡多路查找树(查找路径不只两个)

B+树

B+树是 B 树的变体,也是一种多路搜索树。

B*树

B* 树是 B+树的变体,在 B+树的非根和非叶子结点再增加指向兄弟的指针;B* 树定义了非叶子结点关键字个数至少为(2/3)M,即块的最低使用率为 2/3(代替 B+树的 1/2)。B 树分配新结点的概率比 B+树要低,空间使用率更高;

红黑树

红黑树是一种平衡二叉查找树的变体,它的左右子树高差有可能大于 1,所以红黑树不是严格意义上的平衡二叉树(AVL),但对它进行平衡的代价较低, 其平均统计性能要强于 AVL 。

遍历

前序遍历

后序遍历

中序遍历

层序遍历

常见算法题

镜像二叉树

重建二叉树

二叉树深度

二叉树节点总数

判断二叉树子结构

输入两棵二叉树 A 和 B,判断 B 是不是 A 的子结构。(ps:约定空树不是任意一个树的子结构)

参考文档

  1. 维基百科二叉树
  2. 百度百科满二叉树
',36)]))}const m=r(l,[["render",o]]);export{p as __pageData,m as default}; diff --git a/assets/src_ranuts_bundler_index.md.BP7Aetz6.js b/assets/src_ranuts_bundler_index.md.BP7Aetz6.js new file mode 100644 index 0000000000..f29e6a977c --- /dev/null +++ b/assets/src_ranuts_bundler_index.md.BP7Aetz6.js @@ -0,0 +1,10 @@ +import{_ as s}from"./chunks/bundle.BxrzsuA1.js";import{_ as a,o as e,c as p,a3 as t}from"./chunks/framework.C-ai2y4t.js";const h=JSON.parse('{"title":"Bundler","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/bundler/index.md","filePath":"src/ranuts/bundler/index.md","lastUpdated":1726550590000}'),l={name:"src/ranuts/bundler/index.md"};function r(i,n,d,o,c,u){return e(),p("div",{"data-pagefind-body":!0},n[0]||(n[0]=[t(`

Bundler

Bundler的使用: 传入 options 参数

function build(options: Options):Promise<Build> {
+  const bundle = new Bundle({
+    entry: options.input
+  });
+  return bundle.build().then(() => {
+    return {
+      generate: () => bundle.render()
+    };
+  });
+}

架构图

',5)]))}const g=a(l,[["render",r]]);export{h as __pageData,g as default}; diff --git a/assets/src_ranuts_bundler_index.md.BP7Aetz6.lean.js b/assets/src_ranuts_bundler_index.md.BP7Aetz6.lean.js new file mode 100644 index 0000000000..f29e6a977c --- /dev/null +++ b/assets/src_ranuts_bundler_index.md.BP7Aetz6.lean.js @@ -0,0 +1,10 @@ +import{_ as s}from"./chunks/bundle.BxrzsuA1.js";import{_ as a,o as e,c as p,a3 as t}from"./chunks/framework.C-ai2y4t.js";const h=JSON.parse('{"title":"Bundler","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/bundler/index.md","filePath":"src/ranuts/bundler/index.md","lastUpdated":1726550590000}'),l={name:"src/ranuts/bundler/index.md"};function r(i,n,d,o,c,u){return e(),p("div",{"data-pagefind-body":!0},n[0]||(n[0]=[t(`

Bundler

Bundler的使用: 传入 options 参数

function build(options: Options):Promise<Build> {
+  const bundle = new Bundle({
+    entry: options.input
+  });
+  return bundle.build().then(() => {
+    return {
+      generate: () => bundle.render()
+    };
+  });
+}

架构图

',5)]))}const g=a(l,[["render",r]]);export{h as __pageData,g as default}; diff --git a/assets/src_ranuts_file_appendFile.md.D4zWKXVA.js b/assets/src_ranuts_file_appendFile.md.D4zWKXVA.js new file mode 100644 index 0000000000..3b847ed6f5 --- /dev/null +++ b/assets/src_ranuts_file_appendFile.md.D4zWKXVA.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"AppendFile","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/file/appendFile.md","filePath":"src/ranuts/file/appendFile.md","lastUpdated":1726550590000}'),n={name:"src/ranuts/file/appendFile.md"};function o(i,t,l,h,s,p){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

AppendFile

追加一些数据到文件内

API

Return

  • Promise
参数说明类型描述
success是否追加成功booleantrue 追加成功 false 追加失败
data追加失败的原因,添加成功后的文件内容any

Options

参数说明类型默认值
path文件路径,需要追加的文件stringundefined
content需要追加的内容string

Example

',9)]))}const b=e(n,[["render",o]]);export{u as __pageData,b as default}; diff --git a/assets/src_ranuts_file_appendFile.md.D4zWKXVA.lean.js b/assets/src_ranuts_file_appendFile.md.D4zWKXVA.lean.js new file mode 100644 index 0000000000..3b847ed6f5 --- /dev/null +++ b/assets/src_ranuts_file_appendFile.md.D4zWKXVA.lean.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"AppendFile","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/file/appendFile.md","filePath":"src/ranuts/file/appendFile.md","lastUpdated":1726550590000}'),n={name:"src/ranuts/file/appendFile.md"};function o(i,t,l,h,s,p){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

AppendFile

追加一些数据到文件内

API

Return

  • Promise
参数说明类型描述
success是否追加成功booleantrue 追加成功 false 追加失败
data追加失败的原因,添加成功后的文件内容any

Options

参数说明类型默认值
path文件路径,需要追加的文件stringundefined
content需要追加的内容string

Example

',9)]))}const b=e(n,[["render",o]]);export{u as __pageData,b as default}; diff --git a/assets/src_ranuts_file_fileInfo.md.CfdtUkZ-.js b/assets/src_ranuts_file_fileInfo.md.CfdtUkZ-.js new file mode 100644 index 0000000000..b33e96ef7c --- /dev/null +++ b/assets/src_ranuts_file_fileInfo.md.CfdtUkZ-.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as r,a3 as d}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"QueryFileInfo","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/file/fileInfo.md","filePath":"src/ranuts/file/fileInfo.md","lastUpdated":1726550590000}'),o={name:"src/ranuts/file/fileInfo.md"};function i(n,t,l,h,s,c){return a(),r("div",{"data-pagefind-body":!0},t[0]||(t[0]=[d('

QueryFileInfo

查询一个文件的详细信息,一般用于区分文件还是目录,可以通过返回的 data 来判断(data.isDirectory())

API

Return

  • Promise
参数说明类型描述
success是否检查成功booleantrue 成功 false 失败
data文件的信息,或者错误的原因Stats

Options

参数说明类型默认值
path文件路径,需要检查的文件路径stringundefined

Example

',9)]))}const p=e(o,[["render",i]]);export{u as __pageData,p as default}; diff --git a/assets/src_ranuts_file_fileInfo.md.CfdtUkZ-.lean.js b/assets/src_ranuts_file_fileInfo.md.CfdtUkZ-.lean.js new file mode 100644 index 0000000000..b33e96ef7c --- /dev/null +++ b/assets/src_ranuts_file_fileInfo.md.CfdtUkZ-.lean.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as r,a3 as d}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"QueryFileInfo","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/file/fileInfo.md","filePath":"src/ranuts/file/fileInfo.md","lastUpdated":1726550590000}'),o={name:"src/ranuts/file/fileInfo.md"};function i(n,t,l,h,s,c){return a(),r("div",{"data-pagefind-body":!0},t[0]||(t[0]=[d('

QueryFileInfo

查询一个文件的详细信息,一般用于区分文件还是目录,可以通过返回的 data 来判断(data.isDirectory())

API

Return

  • Promise
参数说明类型描述
success是否检查成功booleantrue 成功 false 失败
data文件的信息,或者错误的原因Stats

Options

参数说明类型默认值
path文件路径,需要检查的文件路径stringundefined

Example

',9)]))}const p=e(o,[["render",i]]);export{u as __pageData,p as default}; diff --git a/assets/src_ranuts_file_readDir.md.D1R8FXwd.js b/assets/src_ranuts_file_readDir.md.D1R8FXwd.js new file mode 100644 index 0000000000..73ed6c5953 --- /dev/null +++ b/assets/src_ranuts_file_readDir.md.D1R8FXwd.js @@ -0,0 +1 @@ +import{_ as e,o as r,c as l,a3 as d,j as t,a as n}from"./chunks/framework.C-ai2y4t.js";const m=JSON.parse('{"title":"ReadDir","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/file/readDir.md","filePath":"src/ranuts/file/readDir.md","lastUpdated":1726550590000}'),i={name:"src/ranuts/file/readDir.md"};function o(s,a,h,u,c,p){return r(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[d('

ReadDir

读一个目录下的所有文件

API

Return

  • Promise
参数说明类型描述
result目录下所有文件的数组array传入函数的参数

Options

',7),t("table",{tabindex:"0"},[t("thead",null,[t("tr",null,[t("th",null,"参数"),t("th",null,"说明"),t("th",null,"类型"),t("th",null,"默认值")])]),t("tbody",null,[t("tr",null,[t("td",null,"options"),t("td",{dirPath:""}),t("td",null,[t("code",null,"object")]),t("td",null,"传入函数的参数")]),t("tr",null,[t("td",null,"dirPath"),t("td",null,"文件的路径"),t("td",null,[t("code",null,"Stats")]),t("td")])])],-1),t("h2",{id:"example",tabindex:"-1"},[n("Example "),t("a",{class:"header-anchor",href:"#example","aria-label":'Permalink to "Example"'},"​")],-1)]))}const f=e(i,[["render",o]]);export{m as __pageData,f as default}; diff --git a/assets/src_ranuts_file_readDir.md.D1R8FXwd.lean.js b/assets/src_ranuts_file_readDir.md.D1R8FXwd.lean.js new file mode 100644 index 0000000000..73ed6c5953 --- /dev/null +++ b/assets/src_ranuts_file_readDir.md.D1R8FXwd.lean.js @@ -0,0 +1 @@ +import{_ as e,o as r,c as l,a3 as d,j as t,a as n}from"./chunks/framework.C-ai2y4t.js";const m=JSON.parse('{"title":"ReadDir","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/file/readDir.md","filePath":"src/ranuts/file/readDir.md","lastUpdated":1726550590000}'),i={name:"src/ranuts/file/readDir.md"};function o(s,a,h,u,c,p){return r(),l("div",{"data-pagefind-body":!0},a[0]||(a[0]=[d('

ReadDir

读一个目录下的所有文件

API

Return

  • Promise
参数说明类型描述
result目录下所有文件的数组array传入函数的参数

Options

',7),t("table",{tabindex:"0"},[t("thead",null,[t("tr",null,[t("th",null,"参数"),t("th",null,"说明"),t("th",null,"类型"),t("th",null,"默认值")])]),t("tbody",null,[t("tr",null,[t("td",null,"options"),t("td",{dirPath:""}),t("td",null,[t("code",null,"object")]),t("td",null,"传入函数的参数")]),t("tr",null,[t("td",null,"dirPath"),t("td",null,"文件的路径"),t("td",null,[t("code",null,"Stats")]),t("td")])])],-1),t("h2",{id:"example",tabindex:"-1"},[n("Example "),t("a",{class:"header-anchor",href:"#example","aria-label":'Permalink to "Example"'},"​")],-1)]))}const f=e(i,[["render",o]]);export{m as __pageData,f as default}; diff --git a/assets/src_ranuts_file_readFile.md.CVYw5eyB.js b/assets/src_ranuts_file_readFile.md.CVYw5eyB.js new file mode 100644 index 0000000000..e7a9b4309b --- /dev/null +++ b/assets/src_ranuts_file_readFile.md.CVYw5eyB.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"ReadFile","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/file/readFile.md","filePath":"src/ranuts/file/readFile.md","lastUpdated":1726550590000}'),o={name:"src/ranuts/file/readFile.md"};function i(l,t,n,h,s,c){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

ReadFile

观察一个文件是否改变

API

Return

  • Promise
参数说明类型描述
data文件是否被改变booleantrue 文件改变 false 文件没变

Options

参数说明类型默认值
path文件路径,需要监听的文件stringundefined
interval监听文件改变的时间,单位毫秒。number20

Example

',9)]))}const b=e(o,[["render",i]]);export{p as __pageData,b as default}; diff --git a/assets/src_ranuts_file_readFile.md.CVYw5eyB.lean.js b/assets/src_ranuts_file_readFile.md.CVYw5eyB.lean.js new file mode 100644 index 0000000000..e7a9b4309b --- /dev/null +++ b/assets/src_ranuts_file_readFile.md.CVYw5eyB.lean.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"ReadFile","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/file/readFile.md","filePath":"src/ranuts/file/readFile.md","lastUpdated":1726550590000}'),o={name:"src/ranuts/file/readFile.md"};function i(l,t,n,h,s,c){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

ReadFile

观察一个文件是否改变

API

Return

  • Promise
参数说明类型描述
data文件是否被改变booleantrue 文件改变 false 文件没变

Options

参数说明类型默认值
path文件路径,需要监听的文件stringundefined
interval监听文件改变的时间,单位毫秒。number20

Example

',9)]))}const b=e(o,[["render",i]]);export{p as __pageData,b as default}; diff --git a/assets/src_ranuts_file_watchFile.md.DibbbSlI.js b/assets/src_ranuts_file_watchFile.md.DibbbSlI.js new file mode 100644 index 0000000000..564405792a --- /dev/null +++ b/assets/src_ranuts_file_watchFile.md.DibbbSlI.js @@ -0,0 +1 @@ +import{_ as a,o as e,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"WatchFile","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/file/watchFile.md","filePath":"src/ranuts/file/watchFile.md","lastUpdated":1726550590000}'),o={name:"src/ranuts/file/watchFile.md"};function i(h,t,l,n,c,s){return e(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

WatchFile

观察一个文件是否改变

API

Return

  • Promise
参数说明类型描述
status文件是否被改变booleantrue 文件改变 false 文件没变

Options

参数说明类型默认值
path文件路径,需要监听的文件stringundefined
interval监听文件改变的时间,单位毫秒。number20
',8)]))}const b=a(o,[["render",i]]);export{p as __pageData,b as default}; diff --git a/assets/src_ranuts_file_watchFile.md.DibbbSlI.lean.js b/assets/src_ranuts_file_watchFile.md.DibbbSlI.lean.js new file mode 100644 index 0000000000..564405792a --- /dev/null +++ b/assets/src_ranuts_file_watchFile.md.DibbbSlI.lean.js @@ -0,0 +1 @@ +import{_ as a,o as e,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"WatchFile","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/file/watchFile.md","filePath":"src/ranuts/file/watchFile.md","lastUpdated":1726550590000}'),o={name:"src/ranuts/file/watchFile.md"};function i(h,t,l,n,c,s){return e(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

WatchFile

观察一个文件是否改变

API

Return

  • Promise
参数说明类型描述
status文件是否被改变booleantrue 文件改变 false 文件没变

Options

参数说明类型默认值
path文件路径,需要监听的文件stringundefined
interval监听文件改变的时间,单位毫秒。number20
',8)]))}const b=a(o,[["render",i]]);export{p as __pageData,b as default}; diff --git a/assets/src_ranuts_file_writeFile.md.C3kB2EaG.js b/assets/src_ranuts_file_writeFile.md.C3kB2EaG.js new file mode 100644 index 0000000000..1ba80c5f7d --- /dev/null +++ b/assets/src_ranuts_file_writeFile.md.C3kB2EaG.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"WriteFile","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/file/writeFile.md","filePath":"src/ranuts/file/writeFile.md","lastUpdated":1726550590000}'),i={name:"src/ranuts/file/writeFile.md"};function o(n,t,l,h,s,c){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

WriteFile

将内容写入文件

API

Return

  • Promise
参数说明类型描述
success是否写入成功booleantrue 成功 false 失败
data写入失败的原因,添加成功后的文件内容和文件路径any

Options

参数说明类型默认值
path文件路径,需要追加的文件stringundefined
content需要追加的内容string
',8)]))}const b=e(i,[["render",o]]);export{p as __pageData,b as default}; diff --git a/assets/src_ranuts_file_writeFile.md.C3kB2EaG.lean.js b/assets/src_ranuts_file_writeFile.md.C3kB2EaG.lean.js new file mode 100644 index 0000000000..1ba80c5f7d --- /dev/null +++ b/assets/src_ranuts_file_writeFile.md.C3kB2EaG.lean.js @@ -0,0 +1 @@ +import{_ as e,o as a,c as d,a3 as r}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"WriteFile","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/file/writeFile.md","filePath":"src/ranuts/file/writeFile.md","lastUpdated":1726550590000}'),i={name:"src/ranuts/file/writeFile.md"};function o(n,t,l,h,s,c){return a(),d("div",{"data-pagefind-body":!0},t[0]||(t[0]=[r('

WriteFile

将内容写入文件

API

Return

  • Promise
参数说明类型描述
success是否写入成功booleantrue 成功 false 失败
data写入失败的原因,添加成功后的文件内容和文件路径any

Options

参数说明类型默认值
path文件路径,需要追加的文件stringundefined
content需要追加的内容string
',8)]))}const b=e(i,[["render",o]]);export{p as __pageData,b as default}; diff --git a/assets/src_ranuts_index.md.BsUA76mi.js b/assets/src_ranuts_index.md.BsUA76mi.js new file mode 100644 index 0000000000..0cf2f43382 --- /dev/null +++ b/assets/src_ranuts_index.md.BsUA76mi.js @@ -0,0 +1 @@ +import{_ as r,o as d,c as a,a3 as i,G as o,B as l}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"ranuts overview","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/index.md","filePath":"src/ranuts/index.md","lastUpdated":1726550590000}'),h={name:"src/ranuts/index.md"};function s(n,t,f,m,c,u){const e=l("TOTP");return d(),a("div",{"data-pagefind-body":!0},[t[0]||(t[0]=i('

ranuts overview

Method list

Methoddescriptiondetail
writeFileWrite to filewriteFile
readFileRead filereadFile
readDirRead the directory and get the names of all the files in the directoryreadDir
watchFileCheck whether the contents of the file have changedwatchFile
queryFileInfoQuery file informationqueryFileInfo
filterObjFilter objectfilterObj
EventEmitterPublish-subscribe classEventEmitter
str2XmlString is converted to xmlstr2Xml
getMimeGets the mime type based on the file format suffixgetMime
getCookieGets the value of the specified cookiewriteFile
formatJsonFormatted JSONformatJson

TOTP

',4)),o(e)])}const v=r(h,[["render",s]]);export{p as __pageData,v as default}; diff --git a/assets/src_ranuts_index.md.BsUA76mi.lean.js b/assets/src_ranuts_index.md.BsUA76mi.lean.js new file mode 100644 index 0000000000..0cf2f43382 --- /dev/null +++ b/assets/src_ranuts_index.md.BsUA76mi.lean.js @@ -0,0 +1 @@ +import{_ as r,o as d,c as a,a3 as i,G as o,B as l}from"./chunks/framework.C-ai2y4t.js";const p=JSON.parse('{"title":"ranuts overview","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/index.md","filePath":"src/ranuts/index.md","lastUpdated":1726550590000}'),h={name:"src/ranuts/index.md"};function s(n,t,f,m,c,u){const e=l("TOTP");return d(),a("div",{"data-pagefind-body":!0},[t[0]||(t[0]=i('

ranuts overview

Method list

Methoddescriptiondetail
writeFileWrite to filewriteFile
readFileRead filereadFile
readDirRead the directory and get the names of all the files in the directoryreadDir
watchFileCheck whether the contents of the file have changedwatchFile
queryFileInfoQuery file informationqueryFileInfo
filterObjFilter objectfilterObj
EventEmitterPublish-subscribe classEventEmitter
str2XmlString is converted to xmlstr2Xml
getMimeGets the mime type based on the file format suffixgetMime
getCookieGets the value of the specified cookiewriteFile
formatJsonFormatted JSONformatJson

TOTP

',4)),o(e)])}const v=r(h,[["render",s]]);export{p as __pageData,v as default}; diff --git a/assets/src_ranuts_mimeType_mimeType.md.BMZ_GsW2.js b/assets/src_ranuts_mimeType_mimeType.md.BMZ_GsW2.js new file mode 100644 index 0000000000..d6e1694646 --- /dev/null +++ b/assets/src_ranuts_mimeType_mimeType.md.BMZ_GsW2.js @@ -0,0 +1,8 @@ +import{_ as i,o as a,c as t,a3 as e}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"getMime","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/mimeType/mimeType.md","filePath":"src/ranuts/mimeType/mimeType.md","lastUpdated":1726550590000}'),n={name:"src/ranuts/mimeType/mimeType.md"};function h(l,s,p,r,d,k){return a(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[e(`

getMime

传入文件格式后缀,返回mime type

API

Return

参数说明类型
string返回mime typestring

Options

参数说明类型默认值
ext文件后缀格式string

Example

js
import { getMime } from 'ranuts';
+
+const result = getMime('.pptx');
+console.log(result);
+// 'application/vnd.openxmlformats-officedocument.presentationml.presentation
+const res = getMime('.txt');
+console.log(result);
+// text/plain
`,9)]))}const m=i(n,[["render",h]]);export{c as __pageData,m as default}; diff --git a/assets/src_ranuts_mimeType_mimeType.md.BMZ_GsW2.lean.js b/assets/src_ranuts_mimeType_mimeType.md.BMZ_GsW2.lean.js new file mode 100644 index 0000000000..d6e1694646 --- /dev/null +++ b/assets/src_ranuts_mimeType_mimeType.md.BMZ_GsW2.lean.js @@ -0,0 +1,8 @@ +import{_ as i,o as a,c as t,a3 as e}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"getMime","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/mimeType/mimeType.md","filePath":"src/ranuts/mimeType/mimeType.md","lastUpdated":1726550590000}'),n={name:"src/ranuts/mimeType/mimeType.md"};function h(l,s,p,r,d,k){return a(),t("div",{"data-pagefind-body":!0},s[0]||(s[0]=[e(`

getMime

传入文件格式后缀,返回mime type

API

Return

参数说明类型
string返回mime typestring

Options

参数说明类型默认值
ext文件后缀格式string

Example

js
import { getMime } from 'ranuts';
+
+const result = getMime('.pptx');
+console.log(result);
+// 'application/vnd.openxmlformats-officedocument.presentationml.presentation
+const res = getMime('.txt');
+console.log(result);
+// text/plain
`,9)]))}const m=i(n,[["render",h]]);export{c as __pageData,m as default}; diff --git a/assets/src_ranuts_mode_subscribe.md.Bx_Pjw6l.js b/assets/src_ranuts_mode_subscribe.md.Bx_Pjw6l.js new file mode 100644 index 0000000000..2785ed707a --- /dev/null +++ b/assets/src_ranuts_mode_subscribe.md.Bx_Pjw6l.js @@ -0,0 +1,32 @@ +import{_ as i,o as a,c as n,a3 as t}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"EventEmitter","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/mode/subscribe.md","filePath":"src/ranuts/mode/subscribe.md","lastUpdated":1726550590000}'),h={name:"src/ranuts/mode/subscribe.md"};function l(k,s,p,e,E,r){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t(`

EventEmitter

发布订阅的类

Class

Methods

方法参数说明默认值
on订阅事件订阅事件,传入参数事件名,回调函数
once订阅一次事件,传入参数事件名,回调函数订阅一次事件,触发一次后不再会触发
off取消订阅事件,传入参数事件名,回调函数取消订阅事件
emit触发事件,需要事件名触发事件

Example

js
import { Subscribe } from 'ranuts';
+
+const subscribe = new Subscribe();
+
+// 订阅事件1
+subscribe.on('event', () => {
+  console.log(1);
+});
+// 订阅事件2
+subscribe.on('event', () => {
+  console.log(2);
+});
+// 订阅事件3
+const eventThree = () => {
+  console.log(3);
+};
+subscribe.on('event', eventThree);
+// 订阅事件4,需要传递参数
+subscribe.on('event', (num) => {
+  console.log(num);
+});
+// 触发事件,同时传参数
+subscribe.emit('event', 4);
+// console.log(1) console.log(2) console.log(3) console.log(4)
+
+// 取消事件三
+subscribe.off('event', eventThree);
+
+// 订阅一次,触发一次自动取消
+subscribe.once('other', () => {
+  console.log(5);
+});
`,7)]))}const y=i(h,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/src_ranuts_mode_subscribe.md.Bx_Pjw6l.lean.js b/assets/src_ranuts_mode_subscribe.md.Bx_Pjw6l.lean.js new file mode 100644 index 0000000000..2785ed707a --- /dev/null +++ b/assets/src_ranuts_mode_subscribe.md.Bx_Pjw6l.lean.js @@ -0,0 +1,32 @@ +import{_ as i,o as a,c as n,a3 as t}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"EventEmitter","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/mode/subscribe.md","filePath":"src/ranuts/mode/subscribe.md","lastUpdated":1726550590000}'),h={name:"src/ranuts/mode/subscribe.md"};function l(k,s,p,e,E,r){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t(`

EventEmitter

发布订阅的类

Class

Methods

方法参数说明默认值
on订阅事件订阅事件,传入参数事件名,回调函数
once订阅一次事件,传入参数事件名,回调函数订阅一次事件,触发一次后不再会触发
off取消订阅事件,传入参数事件名,回调函数取消订阅事件
emit触发事件,需要事件名触发事件

Example

js
import { Subscribe } from 'ranuts';
+
+const subscribe = new Subscribe();
+
+// 订阅事件1
+subscribe.on('event', () => {
+  console.log(1);
+});
+// 订阅事件2
+subscribe.on('event', () => {
+  console.log(2);
+});
+// 订阅事件3
+const eventThree = () => {
+  console.log(3);
+};
+subscribe.on('event', eventThree);
+// 订阅事件4,需要传递参数
+subscribe.on('event', (num) => {
+  console.log(num);
+});
+// 触发事件,同时传参数
+subscribe.emit('event', 4);
+// console.log(1) console.log(2) console.log(3) console.log(4)
+
+// 取消事件三
+subscribe.off('event', eventThree);
+
+// 订阅一次,触发一次自动取消
+subscribe.once('other', () => {
+  console.log(5);
+});
`,7)]))}const y=i(h,[["render",l]]);export{g as __pageData,y as default}; diff --git a/assets/src_ranuts_utils_convertImageToBase64.md.BbdsPOTo.js b/assets/src_ranuts_utils_convertImageToBase64.md.BbdsPOTo.js new file mode 100644 index 0000000000..7187633015 --- /dev/null +++ b/assets/src_ranuts_utils_convertImageToBase64.md.BbdsPOTo.js @@ -0,0 +1,5 @@ +import{_ as a,o as e,c as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const k=JSON.parse('{"title":"convertImageToBase64","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/convertImageToBase64.md","filePath":"src/ranuts/utils/convertImageToBase64.md","lastUpdated":1726550590000}'),n={name:"src/ranuts/utils/convertImageToBase64.md"};function r(o,t,d,h,l,c){return e(),s("div",{"data-pagefind-body":!0},t[0]||(t[0]=[i(`

convertImageToBase64

Picture turn 'base64'

API

Return

argumentInstructionstype
successWhether the conversion is successfulboolean
dataThe value after successful conversionstring,ArrayBuffer , null
messageThe reasons why the conversion succeeds or failsstring

Options

argumentInstructionstypeDefault value
fileIncoming fileFilenull

Example

js
import { convertImageToBase64 } from 'ranuts';
+
+convertImageToBase64(file).then((res) => {
+  console.log(result);
+});
`,9)]))}const u=a(n,[["render",r]]);export{k as __pageData,u as default}; diff --git a/assets/src_ranuts_utils_convertImageToBase64.md.BbdsPOTo.lean.js b/assets/src_ranuts_utils_convertImageToBase64.md.BbdsPOTo.lean.js new file mode 100644 index 0000000000..7187633015 --- /dev/null +++ b/assets/src_ranuts_utils_convertImageToBase64.md.BbdsPOTo.lean.js @@ -0,0 +1,5 @@ +import{_ as a,o as e,c as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const k=JSON.parse('{"title":"convertImageToBase64","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/convertImageToBase64.md","filePath":"src/ranuts/utils/convertImageToBase64.md","lastUpdated":1726550590000}'),n={name:"src/ranuts/utils/convertImageToBase64.md"};function r(o,t,d,h,l,c){return e(),s("div",{"data-pagefind-body":!0},t[0]||(t[0]=[i(`

convertImageToBase64

Picture turn 'base64'

API

Return

argumentInstructionstype
successWhether the conversion is successfulboolean
dataThe value after successful conversionstring,ArrayBuffer , null
messageThe reasons why the conversion succeeds or failsstring

Options

argumentInstructionstypeDefault value
fileIncoming fileFilenull

Example

js
import { convertImageToBase64 } from 'ranuts';
+
+convertImageToBase64(file).then((res) => {
+  console.log(result);
+});
`,9)]))}const u=a(n,[["render",r]]);export{k as __pageData,u as default}; diff --git a/assets/src_ranuts_utils_filterObj.md.CQHmrklO.js b/assets/src_ranuts_utils_filterObj.md.CQHmrklO.js new file mode 100644 index 0000000000..761bc82156 --- /dev/null +++ b/assets/src_ranuts_utils_filterObj.md.CQHmrklO.js @@ -0,0 +1,13 @@ +import{_ as a,o as t,c as i,a3 as e}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"filterObj","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/filterObj.md","filePath":"src/ranuts/utils/filterObj.md","lastUpdated":1726550590000}'),n={name:"src/ranuts/utils/filterObj.md"};function l(h,s,r,p,d,k){return t(),i("div",{"data-pagefind-body":!0},s[0]||(s[0]=[e(`

filterObj

Filter the properties of the object, remove the properties of the object in the list array, return a new object, usually used to remove null characters and null

API

Return

argumentInstructionstype
ObjectReturn an objectObject

Options

argumentInstructionstypeDefault value
objObjects to be filteredobject
listFamiliar array to filterarray

Example

js
import { filterObj } from 'ranuts';
+
+const obj = {
+  name: 'chaxus',
+  age: 10,
+  address: 'spark',
+};
+
+const result = filterObj(obj, ['name', 'address']);
+
+console.log(result);
+
+// { age:10 }
`,9)]))}const E=a(n,[["render",l]]);export{c as __pageData,E as default}; diff --git a/assets/src_ranuts_utils_filterObj.md.CQHmrklO.lean.js b/assets/src_ranuts_utils_filterObj.md.CQHmrklO.lean.js new file mode 100644 index 0000000000..761bc82156 --- /dev/null +++ b/assets/src_ranuts_utils_filterObj.md.CQHmrklO.lean.js @@ -0,0 +1,13 @@ +import{_ as a,o as t,c as i,a3 as e}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"filterObj","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/filterObj.md","filePath":"src/ranuts/utils/filterObj.md","lastUpdated":1726550590000}'),n={name:"src/ranuts/utils/filterObj.md"};function l(h,s,r,p,d,k){return t(),i("div",{"data-pagefind-body":!0},s[0]||(s[0]=[e(`

filterObj

Filter the properties of the object, remove the properties of the object in the list array, return a new object, usually used to remove null characters and null

API

Return

argumentInstructionstype
ObjectReturn an objectObject

Options

argumentInstructionstypeDefault value
objObjects to be filteredobject
listFamiliar array to filterarray

Example

js
import { filterObj } from 'ranuts';
+
+const obj = {
+  name: 'chaxus',
+  age: 10,
+  address: 'spark',
+};
+
+const result = filterObj(obj, ['name', 'address']);
+
+console.log(result);
+
+// { age:10 }
`,9)]))}const E=a(n,[["render",l]]);export{c as __pageData,E as default}; diff --git a/assets/src_ranuts_utils_formatJson.md.s6iqMas3.js b/assets/src_ranuts_utils_formatJson.md.s6iqMas3.js new file mode 100644 index 0000000000..fb041f85ae --- /dev/null +++ b/assets/src_ranuts_utils_formatJson.md.s6iqMas3.js @@ -0,0 +1,10 @@ +import{_ as a,o as t,c as i,a3 as n}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"formatJson","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/formatJson.md","filePath":"src/ranuts/utils/formatJson.md","lastUpdated":1726550590000}'),e={name:"src/ranuts/utils/formatJson.md"};function l(r,s,h,o,d,p){return t(),i("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

formatJson

Pass in a JSON or JSON string, add Spaces and newlines to return a formatted JSON string

API

Return

argumentInstructionstype
stringReturn an objectObject

Options

argumentInstructionstypeDefault value
jsonJSON objects that need to be formattedobject,stringnull
callbackError callback, optionalfunctionnull

Example

js
import { formatJson } from 'ranuts';
+
+const json = {
+  name: 'chaxus',
+  age: 3,
+};
+
+const result = formatJson(json);
+
+console.log(result);
`,9)]))}const E=a(e,[["render",l]]);export{c as __pageData,E as default}; diff --git a/assets/src_ranuts_utils_formatJson.md.s6iqMas3.lean.js b/assets/src_ranuts_utils_formatJson.md.s6iqMas3.lean.js new file mode 100644 index 0000000000..fb041f85ae --- /dev/null +++ b/assets/src_ranuts_utils_formatJson.md.s6iqMas3.lean.js @@ -0,0 +1,10 @@ +import{_ as a,o as t,c as i,a3 as n}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"formatJson","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/formatJson.md","filePath":"src/ranuts/utils/formatJson.md","lastUpdated":1726550590000}'),e={name:"src/ranuts/utils/formatJson.md"};function l(r,s,h,o,d,p){return t(),i("div",{"data-pagefind-body":!0},s[0]||(s[0]=[n(`

formatJson

Pass in a JSON or JSON string, add Spaces and newlines to return a formatted JSON string

API

Return

argumentInstructionstype
stringReturn an objectObject

Options

argumentInstructionstypeDefault value
jsonJSON objects that need to be formattedobject,stringnull
callbackError callback, optionalfunctionnull

Example

js
import { formatJson } from 'ranuts';
+
+const json = {
+  name: 'chaxus',
+  age: 3,
+};
+
+const result = formatJson(json);
+
+console.log(result);
`,9)]))}const E=a(e,[["render",l]]);export{c as __pageData,E as default}; diff --git a/assets/src_ranuts_utils_getCookie.md.CsUkD7RK.js b/assets/src_ranuts_utils_getCookie.md.CsUkD7RK.js new file mode 100644 index 0000000000..9ec68739db --- /dev/null +++ b/assets/src_ranuts_utils_getCookie.md.CsUkD7RK.js @@ -0,0 +1,7 @@ +import{_ as a,o as e,c as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"getCookie","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/getCookie.md","filePath":"src/ranuts/utils/getCookie.md","lastUpdated":1726550590000}'),n={name:"src/ranuts/utils/getCookie.md"};function h(o,t,l,r,d,p){return e(),s("div",{"data-pagefind-body":!0},t[0]||(t[0]=[i(`

getCookie

Pass in a string to get the value of the cookie with the specified name

API

Return

argumentInstructionstype
stingReturns the value of a cookie with the specified namestring

Options

argumentInstructionstypeDefault value
nameSpecifies the value of the name that gets the cookieobject

Example

js
import { getCookie } from 'ranuts';
+
+const result = getCookie('name');
+
+console.log(result);
+
+// ''
`,9)]))}const g=a(n,[["render",h]]);export{c as __pageData,g as default}; diff --git a/assets/src_ranuts_utils_getCookie.md.CsUkD7RK.lean.js b/assets/src_ranuts_utils_getCookie.md.CsUkD7RK.lean.js new file mode 100644 index 0000000000..9ec68739db --- /dev/null +++ b/assets/src_ranuts_utils_getCookie.md.CsUkD7RK.lean.js @@ -0,0 +1,7 @@ +import{_ as a,o as e,c as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"getCookie","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/getCookie.md","filePath":"src/ranuts/utils/getCookie.md","lastUpdated":1726550590000}'),n={name:"src/ranuts/utils/getCookie.md"};function h(o,t,l,r,d,p){return e(),s("div",{"data-pagefind-body":!0},t[0]||(t[0]=[i(`

getCookie

Pass in a string to get the value of the cookie with the specified name

API

Return

argumentInstructionstype
stingReturns the value of a cookie with the specified namestring

Options

argumentInstructionstypeDefault value
nameSpecifies the value of the name that gets the cookieobject

Example

js
import { getCookie } from 'ranuts';
+
+const result = getCookie('name');
+
+console.log(result);
+
+// ''
`,9)]))}const g=a(n,[["render",h]]);export{c as __pageData,g as default}; diff --git a/assets/src_ranuts_utils_ocr.md.B-CI4poJ.js b/assets/src_ranuts_utils_ocr.md.B-CI4poJ.js new file mode 100644 index 0000000000..a5208eb4e2 --- /dev/null +++ b/assets/src_ranuts_utils_ocr.md.B-CI4poJ.js @@ -0,0 +1,15 @@ +import{_ as d,o as a,c as r,a3 as i}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"OCR","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/ocr.md","filePath":"src/ranuts/utils/ocr.md","lastUpdated":1726550590000}'),s={name:"src/ranuts/utils/ocr.md"};function e(n,t,l,h,o,p){return a(),r("div",{"data-pagefind-body":!0},t[0]||(t[0]=[i(`

OCR

Pass in the image and the corresponding language type, and return the text in the image.

API

Return

argumentInstructionstype
successWhether the resolution is successfulboolean
dataThe object is parsed successfullyobj
messageAnalyze the reasons for success or failurestring

Options

argumentInstructionstypeDefault value
imagesAn array of images, supporting 'url' and 'base64'Array<string>null
languageSpecify the language in which the text will be generatedlang-codestring
langPathWhen using it, you need to be able to access cdn.jsdelivr.net, which will download the corresponding language package, if you cannot access it, you can also put the language package locally, passing the corresponding directory pathstringThis parameter is optional. By default, download from the network

Example

js
import { ocr } from 'ranuts';
+
+const images = ['https://chaxus.github.io/ran/ocr/eng.png'];
+const languages = 'eng';
+ocr({ images, language }).then((res) => {
+  console.log(res.data?.[0].data.text);
+});
+// Mild Splendour of the various-vested Night!
+// Mother of wildly-working visions! hail
+// I watch thy gliding, while with watery light
+// Thy weak eye glimmers through a fleecy veil;
+// And when thou lovest thy pale orb to shroud
+// Behind the gather’d blackness lost on high;
+// And when thou dartest from the wind-rent cloud
+// Thy placid lightning o’er the awaken’d sky.

Lang Code

Lang CodeLanguage
afrAfrikaans
amhAmharic
araArabic
asmAssamese
azeAzerbaijani
aze_cyrlAzerbaijani - Cyrillic
belBelarusian
benBengali
bodTibetan
bosBosnian
bulBulgarian
catCatalan; Valencian
cebCebuano
cesCzech
chi_simChinese - Simplified
chi_traChinese - Traditional
chrCherokee
cymWelsh
danDanish
deuGerman
dzoDzongkha
ellGreek, Modern (1453-)
engEnglish
enmEnglish, Middle (1100-1500)
epoEsperanto
estEstonian
eusBasque
fasPersian
finFinnish
fraFrench
frkGerman Fraktur
frmFrench, Middle (ca. 1400-1600)
gleIrish
glgGalician
grcGreek, Ancient (-1453)
gujGujarati
hatHaitian; Haitian Creole
hebHebrew
hinHindi
hrvCroatian
hunHungarian
ikuInuktitut
indIndonesian
islIcelandic
itaItalian
ita_oldItalian - Old
javJavanese
jpnJapanese
kanKannada
katGeorgian
kat_oldGeorgian - Old
kazKazakh
khmCentral Khmer
kirKirghiz; Kyrgyz
korKorean
kurKurdish
laoLao
latLatin
lavLatvian
litLithuanian
malMalayalam
marMarathi
mkdMacedonian
mltMaltese
msaMalay
myaBurmese
nepNepali
nldDutch; Flemish
norNorwegian
oriOriya
panPanjabi; Punjabi
polPolish
porPortuguese
pusPushto; Pashto
ronRomanian; Moldavian; Moldovan
rusRussian
sanSanskrit
sinSinhala; Sinhalese
slkSlovak
slvSlovenian
spaSpanish; Castilian
spa_oldSpanish; Castilian - Old
sqiAlbanian
srpSerbian
srp_latnSerbian - Latin
swaSwahili
sweSwedish
syrSyriac
tamTamil
telTelugu
tgkTajik
tglTagalog
thaThai
tirTigrinya
turTurkish
uigUighur; Uyghur
ukrUkrainian
urdUrdu
uzbUzbek
uzb_cyrlUzbek - Cyrillic
vieVietnamese
yidYiddish
`,11)]))}const g=d(s,[["render",e]]);export{c as __pageData,g as default}; diff --git a/assets/src_ranuts_utils_ocr.md.B-CI4poJ.lean.js b/assets/src_ranuts_utils_ocr.md.B-CI4poJ.lean.js new file mode 100644 index 0000000000..a5208eb4e2 --- /dev/null +++ b/assets/src_ranuts_utils_ocr.md.B-CI4poJ.lean.js @@ -0,0 +1,15 @@ +import{_ as d,o as a,c as r,a3 as i}from"./chunks/framework.C-ai2y4t.js";const c=JSON.parse('{"title":"OCR","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/ocr.md","filePath":"src/ranuts/utils/ocr.md","lastUpdated":1726550590000}'),s={name:"src/ranuts/utils/ocr.md"};function e(n,t,l,h,o,p){return a(),r("div",{"data-pagefind-body":!0},t[0]||(t[0]=[i(`

OCR

Pass in the image and the corresponding language type, and return the text in the image.

API

Return

argumentInstructionstype
successWhether the resolution is successfulboolean
dataThe object is parsed successfullyobj
messageAnalyze the reasons for success or failurestring

Options

argumentInstructionstypeDefault value
imagesAn array of images, supporting 'url' and 'base64'Array<string>null
languageSpecify the language in which the text will be generatedlang-codestring
langPathWhen using it, you need to be able to access cdn.jsdelivr.net, which will download the corresponding language package, if you cannot access it, you can also put the language package locally, passing the corresponding directory pathstringThis parameter is optional. By default, download from the network

Example

js
import { ocr } from 'ranuts';
+
+const images = ['https://chaxus.github.io/ran/ocr/eng.png'];
+const languages = 'eng';
+ocr({ images, language }).then((res) => {
+  console.log(res.data?.[0].data.text);
+});
+// Mild Splendour of the various-vested Night!
+// Mother of wildly-working visions! hail
+// I watch thy gliding, while with watery light
+// Thy weak eye glimmers through a fleecy veil;
+// And when thou lovest thy pale orb to shroud
+// Behind the gather’d blackness lost on high;
+// And when thou dartest from the wind-rent cloud
+// Thy placid lightning o’er the awaken’d sky.

Lang Code

Lang CodeLanguage
afrAfrikaans
amhAmharic
araArabic
asmAssamese
azeAzerbaijani
aze_cyrlAzerbaijani - Cyrillic
belBelarusian
benBengali
bodTibetan
bosBosnian
bulBulgarian
catCatalan; Valencian
cebCebuano
cesCzech
chi_simChinese - Simplified
chi_traChinese - Traditional
chrCherokee
cymWelsh
danDanish
deuGerman
dzoDzongkha
ellGreek, Modern (1453-)
engEnglish
enmEnglish, Middle (1100-1500)
epoEsperanto
estEstonian
eusBasque
fasPersian
finFinnish
fraFrench
frkGerman Fraktur
frmFrench, Middle (ca. 1400-1600)
gleIrish
glgGalician
grcGreek, Ancient (-1453)
gujGujarati
hatHaitian; Haitian Creole
hebHebrew
hinHindi
hrvCroatian
hunHungarian
ikuInuktitut
indIndonesian
islIcelandic
itaItalian
ita_oldItalian - Old
javJavanese
jpnJapanese
kanKannada
katGeorgian
kat_oldGeorgian - Old
kazKazakh
khmCentral Khmer
kirKirghiz; Kyrgyz
korKorean
kurKurdish
laoLao
latLatin
lavLatvian
litLithuanian
malMalayalam
marMarathi
mkdMacedonian
mltMaltese
msaMalay
myaBurmese
nepNepali
nldDutch; Flemish
norNorwegian
oriOriya
panPanjabi; Punjabi
polPolish
porPortuguese
pusPushto; Pashto
ronRomanian; Moldavian; Moldovan
rusRussian
sanSanskrit
sinSinhala; Sinhalese
slkSlovak
slvSlovenian
spaSpanish; Castilian
spa_oldSpanish; Castilian - Old
sqiAlbanian
srpSerbian
srp_latnSerbian - Latin
swaSwahili
sweSwedish
syrSyriac
tamTamil
telTelugu
tgkTajik
tglTagalog
thaThai
tirTigrinya
turTurkish
uigUighur; Uyghur
ukrUkrainian
urdUrdu
uzbUzbek
uzb_cyrlUzbek - Cyrillic
vieVietnamese
yidYiddish
`,11)]))}const g=d(s,[["render",e]]);export{c as __pageData,g as default}; diff --git a/assets/src_ranuts_utils_str2xml.md.DUodO238.js b/assets/src_ranuts_utils_str2xml.md.DUodO238.js new file mode 100644 index 0000000000..7ff2af9fe4 --- /dev/null +++ b/assets/src_ranuts_utils_str2xml.md.DUodO238.js @@ -0,0 +1,8 @@ +import{_ as s,o as a,c as i,a3 as e}from"./chunks/framework.C-ai2y4t.js";const k=JSON.parse('{"title":"str2Xml","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/str2xml.md","filePath":"src/ranuts/utils/str2xml.md","lastUpdated":1726550590000}'),n={name:"src/ranuts/utils/str2xml.md"};function l(r,t,h,d,o,p){return a(),i("div",{"data-pagefind-body":!0},t[0]||(t[0]=[e(`

str2Xml

Pass in a string and convert it to 'xml'

API

Return

argumentInstructionstype
HTMLElement返回一个HTMLElementHTMLElement

Options

argumentInstructionstypeDefault value
xmlStrIncoming parameterstringnull
formatSet the format to be converted. The default is' text/xml '' DOMParserSupportedType 'null

Example

For example, when doing icon library, we need to dynamically import all the 'ICONS' in the directory. In this case, strings are imported, but strings cannot be added to 'xml'. So we need to convert the string to 'xml', and then we can add it to 'xml'.

js
import { str2Xml } from 'ranuts';
+
+// import 'assets/*.svg'
+const svg = \`<svg t="1667483498347" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8544" width="200" height="200"><path d="M858.5 763.6c-18.9-44.8-46.1-85-80.6-119.5-34.5-34.5-74.7-61.6-119.5-80.6-0.4-0.2-0.8-0.3-1.2-0.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-0.4 0.2-0.8 0.3-1.2 0.5-44.8 18.9-85 46-119.5 80.6-34.5 34.5-61.6 74.7-80.6 119.5C146.9 807.5 137 854 136 901.8c-0.1 4.5 3.5 8.2 8 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c0.1 4.4 3.6 7.8 8 7.8h60c4.5 0 8.1-3.7 8-8.2-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z" p-id="8545"></path></svg>\`;
+
+const icon = str2Xml(svg, 'image/svg+xml');
+
+document.body.appendChild(icon);
`,10)]))}const u=s(n,[["render",l]]);export{k as __pageData,u as default}; diff --git a/assets/src_ranuts_utils_str2xml.md.DUodO238.lean.js b/assets/src_ranuts_utils_str2xml.md.DUodO238.lean.js new file mode 100644 index 0000000000..7ff2af9fe4 --- /dev/null +++ b/assets/src_ranuts_utils_str2xml.md.DUodO238.lean.js @@ -0,0 +1,8 @@ +import{_ as s,o as a,c as i,a3 as e}from"./chunks/framework.C-ai2y4t.js";const k=JSON.parse('{"title":"str2Xml","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/str2xml.md","filePath":"src/ranuts/utils/str2xml.md","lastUpdated":1726550590000}'),n={name:"src/ranuts/utils/str2xml.md"};function l(r,t,h,d,o,p){return a(),i("div",{"data-pagefind-body":!0},t[0]||(t[0]=[e(`

str2Xml

Pass in a string and convert it to 'xml'

API

Return

argumentInstructionstype
HTMLElement返回一个HTMLElementHTMLElement

Options

argumentInstructionstypeDefault value
xmlStrIncoming parameterstringnull
formatSet the format to be converted. The default is' text/xml '' DOMParserSupportedType 'null

Example

For example, when doing icon library, we need to dynamically import all the 'ICONS' in the directory. In this case, strings are imported, but strings cannot be added to 'xml'. So we need to convert the string to 'xml', and then we can add it to 'xml'.

js
import { str2Xml } from 'ranuts';
+
+// import 'assets/*.svg'
+const svg = \`<svg t="1667483498347" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8544" width="200" height="200"><path d="M858.5 763.6c-18.9-44.8-46.1-85-80.6-119.5-34.5-34.5-74.7-61.6-119.5-80.6-0.4-0.2-0.8-0.3-1.2-0.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-0.4 0.2-0.8 0.3-1.2 0.5-44.8 18.9-85 46-119.5 80.6-34.5 34.5-61.6 74.7-80.6 119.5C146.9 807.5 137 854 136 901.8c-0.1 4.5 3.5 8.2 8 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c0.1 4.4 3.6 7.8 8 7.8h60c4.5 0 8.1-3.7 8-8.2-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z" p-id="8545"></path></svg>\`;
+
+const icon = str2Xml(svg, 'image/svg+xml');
+
+document.body.appendChild(icon);
`,10)]))}const u=s(n,[["render",l]]);export{k as __pageData,u as default}; diff --git a/assets/src_ranuts_utils_task.md.hnoz85-k.js b/assets/src_ranuts_utils_task.md.hnoz85-k.js new file mode 100644 index 0000000000..99d7dce337 --- /dev/null +++ b/assets/src_ranuts_utils_task.md.hnoz85-k.js @@ -0,0 +1 @@ +import{_ as t,o as a,c as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const k=JSON.parse('{"title":"Statistical execution time","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/task.md","filePath":"src/ranuts/utils/task.md","lastUpdated":1726550590000}'),o={name:"src/ranuts/utils/task.md"};function n(d,e,r,c,l,h){return a(),s("div",{"data-pagefind-body":!0},e[0]||(e[0]=[i('

Statistical execution time

Sometimes, we need statistics on the execution time of a function to analyze performance. Therefore, the 'startTask' and 'taskEnd' functions are wrapped. Three other statistical methods are also introduced

  1. new Date().getTime(),
  2. console.time() , console.timeEnd(),
  3. performance.now()

一.startTask,taskEnd

1.startTask

Execute before the task begins

Return

参数说明类型
taskId任务标识unique symbol

2.taskEnd

任务结束的时候执行,需要传入startTask返回的任务标识

Options

参数说明类型默认值
taskId任务标识unique symbol 无默认值,参数必传,否则无法识别是哪个任务

Return

参数说明类型
timetask执行的时间number

3.使用例子

js
const taskId = startTask();\n\n// do something\n\nconst time = taskEnd(taskId);\n\nconsole.log('task 执行花费的时间', time);

二.new Date().getTime()

new Date().getTime() 返回一个数值,表示从 1970 年 1 月 1 日 0 时 0 分 0 秒(UTC,即协调世界时)距离该日期对象所代表时间的毫秒数。用来计算 JS 执行时间会有两个问题:

  1. 某些情况下,毫秒级精度可能不够。
  2. new Date() 解析的时间在不同浏览器,或者不同设备上可能并不一致。MDN 说明

    由于浏览器之间的差异与不一致性,强烈不推荐使用 Date 构造函数来解析日期字符串 (或使用与其等价的 Date.parse)。对 RFC 2822 格式的日期仅有约定俗成的支持。对 ISO 8601 格式的支持中,仅有日期的串 (例如 "1970-01-01") 会被处理为 UTC 而不是本地时间,与其他格式的串的处理不同。

三.console.time(), console.timeEnd()

启动一个计时器来跟踪某一个操作的占用时长。每一个计时器必须拥有唯一的名字,页面中最多能同时运行 10,000 个计时器。当以此计时器名字为参数调用 console.timeEnd() 时,浏览器将以毫秒为单位,输出对应计时器所经过的时间。比起new Date().getTime(),统计时间更加精确,可以统计到 0.001 毫秒(比如:0.134ms)

四.performance.now()

performance.now()返回的时间精度最高可达微秒级,且不会受到系统时间的影响(系统时钟可能会被手动调整或被 NTP 等软件篡改)。另外,performance.timing.navigationStart + performance.now() 约等于 Date.now()。因此对于统计 JS 执行耗时方面,更推荐使用performance.now()

注意:为了提供对定时攻击和指纹的保护,performance.now() 的精度可能会根据浏览器的设置而被舍弃。 在 Firefox 中,privacy.reduceTimerPrecision 偏好是默认启用的,默认值为 1ms。可以启用 privacy.resistFingerprinting 这将精度改为 100ms 或privacy.resistFingerprinting.reduceTimerPrecision.microseconds 的值,以较大者为准。

',24)]))}const m=t(o,[["render",n]]);export{k as __pageData,m as default}; diff --git a/assets/src_ranuts_utils_task.md.hnoz85-k.lean.js b/assets/src_ranuts_utils_task.md.hnoz85-k.lean.js new file mode 100644 index 0000000000..99d7dce337 --- /dev/null +++ b/assets/src_ranuts_utils_task.md.hnoz85-k.lean.js @@ -0,0 +1 @@ +import{_ as t,o as a,c as s,a3 as i}from"./chunks/framework.C-ai2y4t.js";const k=JSON.parse('{"title":"Statistical execution time","description":"","frontmatter":{},"headers":[],"relativePath":"src/ranuts/utils/task.md","filePath":"src/ranuts/utils/task.md","lastUpdated":1726550590000}'),o={name:"src/ranuts/utils/task.md"};function n(d,e,r,c,l,h){return a(),s("div",{"data-pagefind-body":!0},e[0]||(e[0]=[i('

Statistical execution time

Sometimes, we need statistics on the execution time of a function to analyze performance. Therefore, the 'startTask' and 'taskEnd' functions are wrapped. Three other statistical methods are also introduced

  1. new Date().getTime(),
  2. console.time() , console.timeEnd(),
  3. performance.now()

一.startTask,taskEnd

1.startTask

Execute before the task begins

Return

参数说明类型
taskId任务标识unique symbol

2.taskEnd

任务结束的时候执行,需要传入startTask返回的任务标识

Options

参数说明类型默认值
taskId任务标识unique symbol 无默认值,参数必传,否则无法识别是哪个任务

Return

参数说明类型
timetask执行的时间number

3.使用例子

js
const taskId = startTask();\n\n// do something\n\nconst time = taskEnd(taskId);\n\nconsole.log('task 执行花费的时间', time);

二.new Date().getTime()

new Date().getTime() 返回一个数值,表示从 1970 年 1 月 1 日 0 时 0 分 0 秒(UTC,即协调世界时)距离该日期对象所代表时间的毫秒数。用来计算 JS 执行时间会有两个问题:

  1. 某些情况下,毫秒级精度可能不够。
  2. new Date() 解析的时间在不同浏览器,或者不同设备上可能并不一致。MDN 说明

    由于浏览器之间的差异与不一致性,强烈不推荐使用 Date 构造函数来解析日期字符串 (或使用与其等价的 Date.parse)。对 RFC 2822 格式的日期仅有约定俗成的支持。对 ISO 8601 格式的支持中,仅有日期的串 (例如 "1970-01-01") 会被处理为 UTC 而不是本地时间,与其他格式的串的处理不同。

三.console.time(), console.timeEnd()

启动一个计时器来跟踪某一个操作的占用时长。每一个计时器必须拥有唯一的名字,页面中最多能同时运行 10,000 个计时器。当以此计时器名字为参数调用 console.timeEnd() 时,浏览器将以毫秒为单位,输出对应计时器所经过的时间。比起new Date().getTime(),统计时间更加精确,可以统计到 0.001 毫秒(比如:0.134ms)

四.performance.now()

performance.now()返回的时间精度最高可达微秒级,且不会受到系统时间的影响(系统时钟可能会被手动调整或被 NTP 等软件篡改)。另外,performance.timing.navigationStart + performance.now() 约等于 Date.now()。因此对于统计 JS 执行耗时方面,更推荐使用performance.now()

注意:为了提供对定时攻击和指纹的保护,performance.now() 的精度可能会根据浏览器的设置而被舍弃。 在 Firefox 中,privacy.reduceTimerPrecision 偏好是默认启用的,默认值为 1ms。可以启用 privacy.resistFingerprinting 这将精度改为 100ms 或privacy.resistFingerprinting.reduceTimerPrecision.microseconds 的值,以较大者为准。

',24)]))}const m=t(o,[["render",n]]);export{k as __pageData,m as default}; diff --git "a/assets/src_types_TS\347\261\273\345\236\213.md.D-rRgmPu.js" "b/assets/src_types_TS\347\261\273\345\236\213.md.D-rRgmPu.js" new file mode 100644 index 0000000000..8c5e25f70f --- /dev/null +++ "b/assets/src_types_TS\347\261\273\345\236\213.md.D-rRgmPu.js" @@ -0,0 +1,48 @@ +import{_ as i,o as a,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"TypeScript 类型系统中的类型","description":"","frontmatter":{},"headers":[],"relativePath":"src/types/TS类型.md","filePath":"src/types/TS类型.md","lastUpdated":1726550590000}'),l={name:"src/types/TS类型.md"};function t(p,s,k,e,r,d){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h(`

TypeScript 类型系统中的类型

  1. 基本类型: number、boolean、string、object、bigint、symbol、undefined、null
  2. 复合类型: class、Array、元组(Tuple)、接口(Interface)、枚举(Enum)
  3. 特殊的类型:void、never、any、unknown

Tuple

元组(Tuple)就是元素个数和类型固定的数组类型:

ts
type Tuple = [number, string];

Interface

接口(Interface)可以描述函数、对象、构造器的结构:

  • 对象
ts
interface IPerson {
+  name: string;
+  age: number;
+}
+
+class Person implements IPerson {
+  name: string;
+  age: number;
+}
+
+const obj: IPerson = {
+  name: 'name',
+  age: 18,
+};
  • 函数
ts
interface SayHello {
+  (name: string): string;
+}
+
+const func: SayHello = (name: string) => {
+  return 'hello,' + name;
+};
  • 构造器
ts
interface PersonConstructor {
+  new (name: string, age: number): IPerson;
+}
+
+function createPerson(ctor: PersonConstructor): IPerson {
+  return new ctor('name', 18);
+}

对象类型、class 类型在 TypeScript 里也叫做索引类型,也就是索引了多个元素的类型的意思。对象可以动态添加属性,如果不知道会有什么属性,可以用可索引签名:

ts
interface IPerson {
+  [prop: string]: string | number;
+}
+const obj: IPerson = {};
+obj.name = 'name';
+obj.age = 18;

Enum

枚举(Enum)是一系列值的复合:

ts
enum Transpiler {
+  Babel = 'babel',
+  Postcss = 'postcss',
+  Terser = 'terser',
+  Prettier = 'prettier',
+  TypeScriptCompiler = 'tsc',
+}
+
+const transpiler = Transpiler.TypeScriptCompiler;

此外,TypeScript 还支持字面量类型,也就是类似 1111、'aaaa'、{ a: 1} 这种值也可以做为类型。

其中,字符串的字面量类型有两种,一种是普通的字符串字面量,比如 'aaa',另一种是模版字面量,比如 aaa\${string},它的意思是以 aaa 开头,后面是任意 string 的字符串字面量类型。

所以想要约束以某个字符串开头的字符串字面量类型时可以这样写:

ts
function func(str: \`#\${string}\`) {}
+
+func('aaa'); // error
+
+func('#aaa'); // true

void

代表空,可以是 undefined 或 never。

never

代表不可达,比如函数抛异常的时候,返回值就是 never。

any

是任意类型,任何类型都可以赋值给它,它也可以赋值给任何类型(除了 never)。

unknown

是未知类型,任何类型都可以赋值给它,但是它不可以赋值给别的类型。

类型的装饰

除了描述类型的结构外,TypeScript 的类型系统还支持描述类型的属性,比如是否可选,是否只读等:

ts
interface IPerson {
+  readonly name: string;
+  age?: number;
+}
+
+type tuple = [string, number?];
`,33)]))}const y=i(l,[["render",t]]);export{g as __pageData,y as default}; diff --git "a/assets/src_types_TS\347\261\273\345\236\213.md.D-rRgmPu.lean.js" "b/assets/src_types_TS\347\261\273\345\236\213.md.D-rRgmPu.lean.js" new file mode 100644 index 0000000000..8c5e25f70f --- /dev/null +++ "b/assets/src_types_TS\347\261\273\345\236\213.md.D-rRgmPu.lean.js" @@ -0,0 +1,48 @@ +import{_ as i,o as a,c as n,a3 as h}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"TypeScript 类型系统中的类型","description":"","frontmatter":{},"headers":[],"relativePath":"src/types/TS类型.md","filePath":"src/types/TS类型.md","lastUpdated":1726550590000}'),l={name:"src/types/TS类型.md"};function t(p,s,k,e,r,d){return a(),n("div",{"data-pagefind-body":!0},s[0]||(s[0]=[h(`

TypeScript 类型系统中的类型

  1. 基本类型: number、boolean、string、object、bigint、symbol、undefined、null
  2. 复合类型: class、Array、元组(Tuple)、接口(Interface)、枚举(Enum)
  3. 特殊的类型:void、never、any、unknown

Tuple

元组(Tuple)就是元素个数和类型固定的数组类型:

ts
type Tuple = [number, string];

Interface

接口(Interface)可以描述函数、对象、构造器的结构:

  • 对象
ts
interface IPerson {
+  name: string;
+  age: number;
+}
+
+class Person implements IPerson {
+  name: string;
+  age: number;
+}
+
+const obj: IPerson = {
+  name: 'name',
+  age: 18,
+};
  • 函数
ts
interface SayHello {
+  (name: string): string;
+}
+
+const func: SayHello = (name: string) => {
+  return 'hello,' + name;
+};
  • 构造器
ts
interface PersonConstructor {
+  new (name: string, age: number): IPerson;
+}
+
+function createPerson(ctor: PersonConstructor): IPerson {
+  return new ctor('name', 18);
+}

对象类型、class 类型在 TypeScript 里也叫做索引类型,也就是索引了多个元素的类型的意思。对象可以动态添加属性,如果不知道会有什么属性,可以用可索引签名:

ts
interface IPerson {
+  [prop: string]: string | number;
+}
+const obj: IPerson = {};
+obj.name = 'name';
+obj.age = 18;

Enum

枚举(Enum)是一系列值的复合:

ts
enum Transpiler {
+  Babel = 'babel',
+  Postcss = 'postcss',
+  Terser = 'terser',
+  Prettier = 'prettier',
+  TypeScriptCompiler = 'tsc',
+}
+
+const transpiler = Transpiler.TypeScriptCompiler;

此外,TypeScript 还支持字面量类型,也就是类似 1111、'aaaa'、{ a: 1} 这种值也可以做为类型。

其中,字符串的字面量类型有两种,一种是普通的字符串字面量,比如 'aaa',另一种是模版字面量,比如 aaa\${string},它的意思是以 aaa 开头,后面是任意 string 的字符串字面量类型。

所以想要约束以某个字符串开头的字符串字面量类型时可以这样写:

ts
function func(str: \`#\${string}\`) {}
+
+func('aaa'); // error
+
+func('#aaa'); // true

void

代表空,可以是 undefined 或 never。

never

代表不可达,比如函数抛异常的时候,返回值就是 never。

any

是任意类型,任何类型都可以赋值给它,它也可以赋值给任何类型(除了 never)。

unknown

是未知类型,任何类型都可以赋值给它,但是它不可以赋值给别的类型。

类型的装饰

除了描述类型的结构外,TypeScript 的类型系统还支持描述类型的属性,比如是否可选,是否只读等:

ts
interface IPerson {
+  readonly name: string;
+  age?: number;
+}
+
+type tuple = [string, number?];
`,33)]))}const y=i(l,[["render",t]]);export{g as __pageData,y as default}; diff --git "a/assets/src_types_\346\250\241\345\274\217\345\214\271\351\205\215.md.Dp3VrzqR.js" "b/assets/src_types_\346\250\241\345\274\217\345\214\271\351\205\215.md.Dp3VrzqR.js" new file mode 100644 index 0000000000..0f66d7e252 --- /dev/null +++ "b/assets/src_types_\346\250\241\345\274\217\345\214\271\351\205\215.md.Dp3VrzqR.js" @@ -0,0 +1 @@ +import{_ as i,o as a,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"模式匹配","description":"","frontmatter":{},"headers":[],"relativePath":"src/types/模式匹配.md","filePath":"src/types/模式匹配.md","lastUpdated":1726550590000}'),k={name:"src/types/模式匹配.md"};function n(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

模式匹配

Typescript 的类型也同样可以做模式匹配。

比如这样一个 Promise 类型:

ts
type p = Promise<'value'>;

我们想提取 value 的类型,可以这样做:

ts
type GetPromiseValue<T> = T extends Promise<infer value> ? value : never;

通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取的,通过 infer 声明一个局部变量 Value 来保存,如果匹配,就返回匹配到的 Value,否则就返回 never 代表没匹配到。

ts
type result = GetPromiseValue<Promise<'name'>>; // name

数组类型

数组类型想提取第一个元素的类型怎么做呢?

ts
type arr = [1, 2, 3];

用它来匹配一个模式类型,提取第一个元素的类型到通过 infer 声明的局部变量里返回。

ts
type GetArrayFirstItem<T extends unknown[]> = T extends [infer value, ...unknown[]] ? value : never;

类型参数 Arr 通过 extends 约束为只能是数组类型,数组元素是 unknown 也就是可以是任何值。

any 和 unknown 的区别: any 和 unknown 都代表任意类型,但是 unknown 只能接收任意类型的值,而 any 除了可以接收任意类型的值,也可以赋值给任意类型(除了 never)。类型体操中经常用 unknown 接受和匹配任何类型,而很少把任何类型赋值给某个类型变量。

对 Arr 做模式匹配,把我们要提取的第一个元素的类型放到通过 infer 声明的 First 局部变量里,后面的元素可以是任何类型,用 unknown 接收,然后把局部变量 First 返回。

当类型参数 Arr 为 [1,2,3] 时:

ts
type result = GetArrayFirstItem<[1, 2, 3]>; // 1

当类型参数 Arr 为 [] 时:

ts
type result = GetArrayFirstItem<[]>; // never

可以提取第一个元素,当然也可以提取最后一个元素,修改下模式类型就行:

ts
type GetArrayLastItem<T extends unknown[]> = T extends [...unknown[],inter L] ? L : never

我们分别取了首尾元素,当然也可以取剩余的数组,比如取去掉了最后一个元素的数组:

ts
type Pop<T extends unknown[]> = T extends [] ? [] : T extends [...infer Rest, unknown] ? Rest : never;

如果是空数组,就直接返回,否则匹配剩余的元素,放到 infer 声明的局部变量 Rest 里,返回 Rest。

当类型参数 Arr 为 [1,2,3] 时:

ts
type Result = Pop<[1, 2, 3]>; // [1,2]

当类型参数 Arr 为 [] 时:

ts
type Result = Pop<[]>; // []

同理可得 ShiftArr 的实现:

ts
type Shift<T extends unknown[]> = T extends [] ? [] : T extends [unknown, ...infer Rest] ? Rest : never;

字符串类型也同样可以做模式匹配,匹配一个模式字符串,把需要提取的部分放到 infer 声明的局部变量里。

判断字符串是否以某个前缀开头,也是通过模式匹配:

ts
type StartWidth<S extends string, P extends string> = S extends `${P}${string}` ? true : false;

需要声明字符串 Str、匹配的前缀 Prefix 两个类型参数,它们都是 string。

用 Str 去匹配一个模式类型,模式类型的前缀是 Prefix,后面是任意的 string,如果匹配返回 true,否则返回 false。

字符串可以匹配一个模式类型,提取想要的部分,自然也可以用这些再构成一个新的类型。

比如实现字符串替换:

ts
type Replace<S extends string, F extends string, T extends string> = S extends `${infer P}${F}${infer L}`\n  ? `${P}${T}${L}`\n  : S;

声明要替换的字符串 Str、待替换的字符串 From、替换成的字符串 3 个类型参数,通过 extends 约束为都是 string 类型。

用 Str 去匹配模式串,模式串由 From 和之前之后的字符串构成,把之前之后的字符串放到通过 infer 声明的局部变量 Prefix、Suffix 里。

用 Prefix、Suffix 加上替换到的字符串 To 构造成新的字符串类型返回。

Trim

能够匹配和替换字符串,那也就能实现去掉空白字符的 Trim:

不过因为我们不知道有多少个空白字符,所以只能一个个匹配和去掉,需要递归。

先实现 TrimRight:

ts
type TrimRight<S extends string> = S extends `${infer Rest}${' ' | '\\n' | '\\t'}` ? TrimRight<Rest> : S;

类型参数 Str 是要 Trim 的字符串。

如果 Str 匹配字符串 + 空白字符 (空格、换行、制表符),那就把字符串放到 infer 声明的局部变量 Rest 里。

把 Rest 作为类型参数递归 TrimRight,直到不匹配,这时的类型参数 Str 就是处理结果。

同理可得 TrimLeft:

ts
type TrimLeft<S extends string> = S extends `${' ' | '\\n' | '\\t'}${infer Rest}` ? TrimLeft<Rest> : S;

TrimRight 和 TrimLeft 结合就是 Trim:

ts
type Trim<S extends string> = TrimLeft<TrimRight<S>>;

函数

函数同样也可以做类型匹配,比如提取参数、返回值的类型。

GetParameters

函数类型可以通过模式匹配来提取参数的类型:

ts
type GetParameters<T extends Function> = T extends (...args: infer A) => unknown ? A : never;

类型参数 Func 是要匹配的函数类型,通过 extends 约束为 Function。

Func 和模式类型做匹配,参数类型放到用 infer 声明的局部变量 Args 里,返回值可以是任何类型,用 unknown。

返回提取到的参数类型 Args。

GetReturnType

ts
type GetReturnType<T extends Function> = T extends (...args: unknown[]) => infer R ? R : never;

Func 和模式类型做匹配,提取返回值到通过 infer 声明的局部变量 ReturnType 里返回。

参数类型可以是任意类型,也就是 any[](注意,这里不能用 unknown,这里的解释涉及到参数的逆变性质,具体原因逆变那一节会解释)。

GetThisParameterType

方法里可以调用 this,用对象.方法名的方式调用的时候,this 就指向那个对象。

但是方法也可以用 call 或者 apply 调用,call 调用的时候,this 就变了,但这里却没有被检查出来 this 指向的错误。

这里的 this 类型同样也可以通过模式匹配提取出来:

ts
type GetThisParameterType<T extends Function> = T extends (this: infer H, ...args: unknown[]) => unknown ? H : unknown;

构造器

构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

同样,我们也可以通过模式匹配提取构造器的参数和返回值的类型:

GetInstanceType

构造器类型可以用 interface 声明,使用 new(): xx 的语法。

ts
interface Person {\n  name: string;\n}\n\ninterface PersonConstructor {\n  new (name: string): Person;\n}

这里的 PersonConstructor 返回的是 Person 类型的实例对象,这个也可以通过模式匹配取出来。

ts
type GetInstanceType<C extends new (...args: unknown[]) => unknown> = C extends new (...args: unknown[]) => infer T\n  ? T\n  : unknown;
',79)]))}const y=i(k,[["render",n]]);export{F as __pageData,y as default}; diff --git "a/assets/src_types_\346\250\241\345\274\217\345\214\271\351\205\215.md.Dp3VrzqR.lean.js" "b/assets/src_types_\346\250\241\345\274\217\345\214\271\351\205\215.md.Dp3VrzqR.lean.js" new file mode 100644 index 0000000000..0f66d7e252 --- /dev/null +++ "b/assets/src_types_\346\250\241\345\274\217\345\214\271\351\205\215.md.Dp3VrzqR.lean.js" @@ -0,0 +1 @@ +import{_ as i,o as a,c as h,a3 as t}from"./chunks/framework.C-ai2y4t.js";const F=JSON.parse('{"title":"模式匹配","description":"","frontmatter":{},"headers":[],"relativePath":"src/types/模式匹配.md","filePath":"src/types/模式匹配.md","lastUpdated":1726550590000}'),k={name:"src/types/模式匹配.md"};function n(p,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[t('

模式匹配

Typescript 的类型也同样可以做模式匹配。

比如这样一个 Promise 类型:

ts
type p = Promise<'value'>;

我们想提取 value 的类型,可以这样做:

ts
type GetPromiseValue<T> = T extends Promise<infer value> ? value : never;

通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取的,通过 infer 声明一个局部变量 Value 来保存,如果匹配,就返回匹配到的 Value,否则就返回 never 代表没匹配到。

ts
type result = GetPromiseValue<Promise<'name'>>; // name

数组类型

数组类型想提取第一个元素的类型怎么做呢?

ts
type arr = [1, 2, 3];

用它来匹配一个模式类型,提取第一个元素的类型到通过 infer 声明的局部变量里返回。

ts
type GetArrayFirstItem<T extends unknown[]> = T extends [infer value, ...unknown[]] ? value : never;

类型参数 Arr 通过 extends 约束为只能是数组类型,数组元素是 unknown 也就是可以是任何值。

any 和 unknown 的区别: any 和 unknown 都代表任意类型,但是 unknown 只能接收任意类型的值,而 any 除了可以接收任意类型的值,也可以赋值给任意类型(除了 never)。类型体操中经常用 unknown 接受和匹配任何类型,而很少把任何类型赋值给某个类型变量。

对 Arr 做模式匹配,把我们要提取的第一个元素的类型放到通过 infer 声明的 First 局部变量里,后面的元素可以是任何类型,用 unknown 接收,然后把局部变量 First 返回。

当类型参数 Arr 为 [1,2,3] 时:

ts
type result = GetArrayFirstItem<[1, 2, 3]>; // 1

当类型参数 Arr 为 [] 时:

ts
type result = GetArrayFirstItem<[]>; // never

可以提取第一个元素,当然也可以提取最后一个元素,修改下模式类型就行:

ts
type GetArrayLastItem<T extends unknown[]> = T extends [...unknown[],inter L] ? L : never

我们分别取了首尾元素,当然也可以取剩余的数组,比如取去掉了最后一个元素的数组:

ts
type Pop<T extends unknown[]> = T extends [] ? [] : T extends [...infer Rest, unknown] ? Rest : never;

如果是空数组,就直接返回,否则匹配剩余的元素,放到 infer 声明的局部变量 Rest 里,返回 Rest。

当类型参数 Arr 为 [1,2,3] 时:

ts
type Result = Pop<[1, 2, 3]>; // [1,2]

当类型参数 Arr 为 [] 时:

ts
type Result = Pop<[]>; // []

同理可得 ShiftArr 的实现:

ts
type Shift<T extends unknown[]> = T extends [] ? [] : T extends [unknown, ...infer Rest] ? Rest : never;

字符串类型也同样可以做模式匹配,匹配一个模式字符串,把需要提取的部分放到 infer 声明的局部变量里。

判断字符串是否以某个前缀开头,也是通过模式匹配:

ts
type StartWidth<S extends string, P extends string> = S extends `${P}${string}` ? true : false;

需要声明字符串 Str、匹配的前缀 Prefix 两个类型参数,它们都是 string。

用 Str 去匹配一个模式类型,模式类型的前缀是 Prefix,后面是任意的 string,如果匹配返回 true,否则返回 false。

字符串可以匹配一个模式类型,提取想要的部分,自然也可以用这些再构成一个新的类型。

比如实现字符串替换:

ts
type Replace<S extends string, F extends string, T extends string> = S extends `${infer P}${F}${infer L}`\n  ? `${P}${T}${L}`\n  : S;

声明要替换的字符串 Str、待替换的字符串 From、替换成的字符串 3 个类型参数,通过 extends 约束为都是 string 类型。

用 Str 去匹配模式串,模式串由 From 和之前之后的字符串构成,把之前之后的字符串放到通过 infer 声明的局部变量 Prefix、Suffix 里。

用 Prefix、Suffix 加上替换到的字符串 To 构造成新的字符串类型返回。

Trim

能够匹配和替换字符串,那也就能实现去掉空白字符的 Trim:

不过因为我们不知道有多少个空白字符,所以只能一个个匹配和去掉,需要递归。

先实现 TrimRight:

ts
type TrimRight<S extends string> = S extends `${infer Rest}${' ' | '\\n' | '\\t'}` ? TrimRight<Rest> : S;

类型参数 Str 是要 Trim 的字符串。

如果 Str 匹配字符串 + 空白字符 (空格、换行、制表符),那就把字符串放到 infer 声明的局部变量 Rest 里。

把 Rest 作为类型参数递归 TrimRight,直到不匹配,这时的类型参数 Str 就是处理结果。

同理可得 TrimLeft:

ts
type TrimLeft<S extends string> = S extends `${' ' | '\\n' | '\\t'}${infer Rest}` ? TrimLeft<Rest> : S;

TrimRight 和 TrimLeft 结合就是 Trim:

ts
type Trim<S extends string> = TrimLeft<TrimRight<S>>;

函数

函数同样也可以做类型匹配,比如提取参数、返回值的类型。

GetParameters

函数类型可以通过模式匹配来提取参数的类型:

ts
type GetParameters<T extends Function> = T extends (...args: infer A) => unknown ? A : never;

类型参数 Func 是要匹配的函数类型,通过 extends 约束为 Function。

Func 和模式类型做匹配,参数类型放到用 infer 声明的局部变量 Args 里,返回值可以是任何类型,用 unknown。

返回提取到的参数类型 Args。

GetReturnType

ts
type GetReturnType<T extends Function> = T extends (...args: unknown[]) => infer R ? R : never;

Func 和模式类型做匹配,提取返回值到通过 infer 声明的局部变量 ReturnType 里返回。

参数类型可以是任意类型,也就是 any[](注意,这里不能用 unknown,这里的解释涉及到参数的逆变性质,具体原因逆变那一节会解释)。

GetThisParameterType

方法里可以调用 this,用对象.方法名的方式调用的时候,this 就指向那个对象。

但是方法也可以用 call 或者 apply 调用,call 调用的时候,this 就变了,但这里却没有被检查出来 this 指向的错误。

这里的 this 类型同样也可以通过模式匹配提取出来:

ts
type GetThisParameterType<T extends Function> = T extends (this: infer H, ...args: unknown[]) => unknown ? H : unknown;

构造器

构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

同样,我们也可以通过模式匹配提取构造器的参数和返回值的类型:

GetInstanceType

构造器类型可以用 interface 声明,使用 new(): xx 的语法。

ts
interface Person {\n  name: string;\n}\n\ninterface PersonConstructor {\n  new (name: string): Person;\n}

这里的 PersonConstructor 返回的是 Person 类型的实例对象,这个也可以通过模式匹配取出来。

ts
type GetInstanceType<C extends new (...args: unknown[]) => unknown> = C extends new (...args: unknown[]) => infer T\n  ? T\n  : unknown;
',79)]))}const y=i(k,[["render",n]]);export{F as __pageData,y as default}; diff --git "a/assets/src_types_\347\261\273\345\236\213\350\277\220\347\256\227.md.4OgLnpMn.js" "b/assets/src_types_\347\261\273\345\236\213\350\277\220\347\256\227.md.4OgLnpMn.js" new file mode 100644 index 0000000000..d15b2d0a12 --- /dev/null +++ "b/assets/src_types_\347\261\273\345\236\213\350\277\220\347\256\227.md.4OgLnpMn.js" @@ -0,0 +1,27 @@ +import{_ as i,o as a,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"TypeScript 类型系统中的类型运算","description":"","frontmatter":{},"headers":[],"relativePath":"src/types/类型运算.md","filePath":"src/types/类型运算.md","lastUpdated":1726550590000}'),n={name:"src/types/类型运算.md"};function p(t,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k(`

TypeScript 类型系统中的类型运算

条件:extends ? :

TypeScript 里的条件判断是 extends ? :,叫做条件类型(Conditional Type)比如:

ts
type isTwo<T> = T extends 2 ? true : false;
+
+type res = isTwo<1>; // true
+type res2 = isTwo<2>; // false

这种类型也叫做高级类型。

高级类型的特点是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

推导:infer

如何提取类型的一部分呢?答案是 infer。

比如提取元组类型的第一个元素:

ts
type FirstTupleItem<Tuple extends unknown[]> = Tuple extends [infer T, ...inter R] ? T : never;
+
+type res = First<[1,2,3]> // 1

注意,第一个 extends 不是条件,条件类型是 extends ? :,这里的 extends 是约束的意思,也就是约束类型参数只能是数组类型。

因为不知道数组元素的具体类型,所以用 unknown。

联合:|

联合类型(Union)类似 js 里的或运算符 |,但是作用于类型,代表类型可以是几个类型之一。

ts
type Union = 1 | 2 | 3;

交叉:&

交叉类型(Intersection)类似 js 中的与运算符 &,但是作用于类型,代表对类型做合并。

ts
type ObjType = { a: number } & { c: boolean };

注意,同一类型可以合并,不同的类型没法合并,会被舍弃:

ts
type res = 'a' & 2; // never

映射类型

对象、class 在 TypeScript 对应的类型是索引类型(Index Type),那么如何对索引类型作修改呢?

答案是映射类型。

ts
type MapType<T> = {
+  [key in keyof T]?: T[key];
+};

keyof T 是查询索引类型中所有的索引,叫做索引查询。

T[Key] 是取索引类型某个索引的值,叫做索引访问。

in 是用于遍历联合类型的运算符。

比如我们把一个索引类型的值变成 3 个元素的数组:

ts
type MapToArray<T> = {
+  [key in keyof T]: [T[key], T[key], T[key]];
+};
+
+// example:
+
+type res = MapToArray<{ a: 1; b: 2 }>;
+// type res = {
+//     a:[1,1,1]
+//     b:[2,2,2]
+// }

映射类型就相当于把一个集合映射到另一个集合,这是它名字的由来。

除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。

ts
type MapTypeFixKey<T> = {
+  [key in keyof T as \`\${key & string}\${key & string}\${key & string}\`]: [T[key], T[key], T[key]];
+};
+// example:
+
+type res = MapToArray<{ a: 1; b: 2 }>;
+// type res = {
+//     aaa:[1,1,1]
+//     bbb:[2,2,2]
+// }

这里的 & string 可能大家会迷惑,解释一下:

因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是 string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型会把同一类型做合并,不同类型舍弃。

因为 js 处理对象比较多,所以索引类型的映射比较重要。

`,35)]))}const E=i(n,[["render",p]]);export{g as __pageData,E as default}; diff --git "a/assets/src_types_\347\261\273\345\236\213\350\277\220\347\256\227.md.4OgLnpMn.lean.js" "b/assets/src_types_\347\261\273\345\236\213\350\277\220\347\256\227.md.4OgLnpMn.lean.js" new file mode 100644 index 0000000000..d15b2d0a12 --- /dev/null +++ "b/assets/src_types_\347\261\273\345\236\213\350\277\220\347\256\227.md.4OgLnpMn.lean.js" @@ -0,0 +1,27 @@ +import{_ as i,o as a,c as h,a3 as k}from"./chunks/framework.C-ai2y4t.js";const g=JSON.parse('{"title":"TypeScript 类型系统中的类型运算","description":"","frontmatter":{},"headers":[],"relativePath":"src/types/类型运算.md","filePath":"src/types/类型运算.md","lastUpdated":1726550590000}'),n={name:"src/types/类型运算.md"};function p(t,s,l,e,r,d){return a(),h("div",{"data-pagefind-body":!0},s[0]||(s[0]=[k(`

TypeScript 类型系统中的类型运算

条件:extends ? :

TypeScript 里的条件判断是 extends ? :,叫做条件类型(Conditional Type)比如:

ts
type isTwo<T> = T extends 2 ? true : false;
+
+type res = isTwo<1>; // true
+type res2 = isTwo<2>; // false

这种类型也叫做高级类型。

高级类型的特点是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

推导:infer

如何提取类型的一部分呢?答案是 infer。

比如提取元组类型的第一个元素:

ts
type FirstTupleItem<Tuple extends unknown[]> = Tuple extends [infer T, ...inter R] ? T : never;
+
+type res = First<[1,2,3]> // 1

注意,第一个 extends 不是条件,条件类型是 extends ? :,这里的 extends 是约束的意思,也就是约束类型参数只能是数组类型。

因为不知道数组元素的具体类型,所以用 unknown。

联合:|

联合类型(Union)类似 js 里的或运算符 |,但是作用于类型,代表类型可以是几个类型之一。

ts
type Union = 1 | 2 | 3;

交叉:&

交叉类型(Intersection)类似 js 中的与运算符 &,但是作用于类型,代表对类型做合并。

ts
type ObjType = { a: number } & { c: boolean };

注意,同一类型可以合并,不同的类型没法合并,会被舍弃:

ts
type res = 'a' & 2; // never

映射类型

对象、class 在 TypeScript 对应的类型是索引类型(Index Type),那么如何对索引类型作修改呢?

答案是映射类型。

ts
type MapType<T> = {
+  [key in keyof T]?: T[key];
+};

keyof T 是查询索引类型中所有的索引,叫做索引查询。

T[Key] 是取索引类型某个索引的值,叫做索引访问。

in 是用于遍历联合类型的运算符。

比如我们把一个索引类型的值变成 3 个元素的数组:

ts
type MapToArray<T> = {
+  [key in keyof T]: [T[key], T[key], T[key]];
+};
+
+// example:
+
+type res = MapToArray<{ a: 1; b: 2 }>;
+// type res = {
+//     a:[1,1,1]
+//     b:[2,2,2]
+// }

映射类型就相当于把一个集合映射到另一个集合,这是它名字的由来。

除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。

ts
type MapTypeFixKey<T> = {
+  [key in keyof T as \`\${key & string}\${key & string}\${key & string}\`]: [T[key], T[key], T[key]];
+};
+// example:
+
+type res = MapToArray<{ a: 1; b: 2 }>;
+// type res = {
+//     aaa:[1,1,1]
+//     bbb:[2,2,2]
+// }

这里的 & string 可能大家会迷惑,解释一下:

因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是 string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型会把同一类型做合并,不同类型舍弃。

因为 js 处理对象比较多,所以索引类型的映射比较重要。

`,35)]))}const E=i(n,[["render",p]]);export{g as __pageData,E as default}; diff --git "a/assets/src_types_\351\253\230\347\272\247\347\261\273\345\236\213.md.C4cnhLAB.js" "b/assets/src_types_\351\253\230\347\272\247\347\261\273\345\236\213.md.C4cnhLAB.js" new file mode 100644 index 0000000000..31973810aa --- /dev/null +++ "b/assets/src_types_\351\253\230\347\272\247\347\261\273\345\236\213.md.C4cnhLAB.js" @@ -0,0 +1 @@ +import{_ as e,o as r,c as t,a3 as i}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"TypeScript 内置的高级类型","description":"","frontmatter":{},"headers":[],"relativePath":"src/types/高级类型.md","filePath":"src/types/高级类型.md","lastUpdated":1726550590000}'),o={name:"src/types/高级类型.md"};function l(n,a,h,c,s,d){return r(),t("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

TypeScript 内置的高级类型

Parameters

Parameters 用于提取函数类型的参数类型。

ReturnType

ReturnType 用于提取函数类型的返回值类型。

ConstructorParameters

构造器类型和函数类型的区别就是可以被 new。

Parameters 用于提取函数参数的类型,而 ConstructorParameters 用于提取构造器参数的类型。

InstanceType

提取了构造器参数的类型,自然也可以提取构造器返回值的类型,就是 InstanceType。

ThisParameterType

OmitThisParameter

Partial

Required

Readonly

Pick

Record

Exclude

Extract

Omit

Awaited

NonNullable

Uppercase

Lowercase

Capitalize

Uncapitalize

总结

比如用模式匹配可以实现:Parameters、ReturnType、ConstructorParameters、InstanceType、ThisParameterType。

用模式匹配 + 重新构造可以实现:OmitThisParameter

用重新构造可以实现:Partial、Required、Readonly、Pick、Record

用模式匹配 + 递归可以实现: Awaited

用联合类型在分布式条件类型的特性可以实现: Exclude

此外还有 NonNullable 和四个编译器内部实现的类型:Uppercase、Lowercase、Capitalize、Uncapitalize。

',33)]))}const m=e(o,[["render",l]]);export{u as __pageData,m as default}; diff --git "a/assets/src_types_\351\253\230\347\272\247\347\261\273\345\236\213.md.C4cnhLAB.lean.js" "b/assets/src_types_\351\253\230\347\272\247\347\261\273\345\236\213.md.C4cnhLAB.lean.js" new file mode 100644 index 0000000000..31973810aa --- /dev/null +++ "b/assets/src_types_\351\253\230\347\272\247\347\261\273\345\236\213.md.C4cnhLAB.lean.js" @@ -0,0 +1 @@ +import{_ as e,o as r,c as t,a3 as i}from"./chunks/framework.C-ai2y4t.js";const u=JSON.parse('{"title":"TypeScript 内置的高级类型","description":"","frontmatter":{},"headers":[],"relativePath":"src/types/高级类型.md","filePath":"src/types/高级类型.md","lastUpdated":1726550590000}'),o={name:"src/types/高级类型.md"};function l(n,a,h,c,s,d){return r(),t("div",{"data-pagefind-body":!0},a[0]||(a[0]=[i('

TypeScript 内置的高级类型

Parameters

Parameters 用于提取函数类型的参数类型。

ReturnType

ReturnType 用于提取函数类型的返回值类型。

ConstructorParameters

构造器类型和函数类型的区别就是可以被 new。

Parameters 用于提取函数参数的类型,而 ConstructorParameters 用于提取构造器参数的类型。

InstanceType

提取了构造器参数的类型,自然也可以提取构造器返回值的类型,就是 InstanceType。

ThisParameterType

OmitThisParameter

Partial

Required

Readonly

Pick

Record

Exclude

Extract

Omit

Awaited

NonNullable

Uppercase

Lowercase

Capitalize

Uncapitalize

总结

比如用模式匹配可以实现:Parameters、ReturnType、ConstructorParameters、InstanceType、ThisParameterType。

用模式匹配 + 重新构造可以实现:OmitThisParameter

用重新构造可以实现:Partial、Required、Readonly、Pick、Record

用模式匹配 + 递归可以实现: Awaited

用联合类型在分布式条件类型的特性可以实现: Exclude

此外还有 NonNullable 和四个编译器内部实现的类型:Uppercase、Lowercase、Capitalize、Uncapitalize。

',33)]))}const m=e(o,[["render",l]]);export{u as __pageData,m as default}; diff --git a/assets/style.Cbu_rzqE.css b/assets/style.Cbu_rzqE.css new file mode 100644 index 0000000000..a84503fd99 --- /dev/null +++ b/assets/style.Cbu_rzqE.css @@ -0,0 +1 @@ +.loading{border-radius:8px;border:1px solid #ebeef5;height:500px}.loading-icon{display:flex;height:100%;width:100%;justify-content:center;align-items:center;cursor:pointer}.loading-icon r-loading{--loading-stretch-div-animation-play-state: paused;--loading-rotate-div-animation-play-state: paused;--loading-double-bounce1-animation-play-state: paused;--loading-double-bounce2-animation-play-state: paused;--loading-cube1-animation-play-state: paused;--loading-cube2-animation-play-state: paused;--loading-dot-animation-play-state: paused;--loading-dot1-animation-play-state: paused;--loading-dot2-animation-play-state: paused;--loading-triple-bounce-div-animation-play-state: paused;--loading-scale-out-animation-play-state: paused;--loading-circle-container-div-animation-play-state: paused;--loading-circle-line-border-animation-play-state: paused;--loading-square-box1-animation-play-state: paused;--loading-square-box2-animation-play-state: paused;--loading-pulse-bubble-1-animation-play-state: paused;--loading-pulse-bubble-2-animation-play-state: paused;--loading-pulse-bubble-3-animation-play-state: paused;--loading-solar-earth-orbit-animation-play-state: paused;--loading-solar-venus-orbit-animation-play-state: paused;--loading-solar-mercury-orbit-animation-play-state: paused;--loading-cube-fold-item-before-animation-play-state: paused;--loading-circle-fold-item-before-animation-play-state: paused;--loading-cube-grid-item-animation-play-state: paused;--loading-circle-turn-animation-play-state: paused;--loading-circle-rotate-outer-animation-play-state: paused;--loading-circle-rotate-inner-animation-play-state: paused;--loading-circle-spin-inner-animation-play-state: paused;--loading-circle-spin-outer-animation-play-state: paused;--loading-dot-bar-item-animation-play-state: paused;--loading-dot-circle-item-1-animation-play-state: paused;--loading-dot-circle-item-2-animation-play-state: paused;--loading-dot-circle-item-3-animation-play-state: paused;--loading-dot-circle-item-4-animation-play-state: paused;--loading-dot-circle-item-5-animation-play-state: paused;--loading-line-item-animation-play-state: paused;--loading-dot-pulse-item-dot-animation-play-state: paused;--loading-dot-pulse-item-ball-animation-play-state: paused;--loading-line-scale-item-animation-play-state: paused;--loading-text-item-animation-play-state: paused;--loading-cube-dim-item-animation-play-state: paused;--loading-dot-line-item-animation-play-state: paused;--loading-arc-item-animation-play-state: paused;--loading-arc-item-after-animation-play-state: paused;--loading-arc-h1-after-animation-play-state: paused;--loading-drop-item-animation-play-state: paused;--loading-drop-dot-animation-play-state: paused;--loading-drop-dot-2-animation-play-state: paused;--loading-pacman-div-nth-child-2-animation-play-state: paused;--loading-pacman-div-nth-child-3-animation-play-state: paused;--loading-pacman-div-nth-child-4-animation-play-state: paused;--loading-pacman-div-nth-child-5-animation-play-state: paused;--loading-pacman-div-first-of-type-animation-play-state: paused;--loading-arc-item-before-animation-play-state: paused}.loading-icon:hover r-loading{--loading-stretch-div-animation-play-state: running;--loading-rotate-div-animation-play-state: running;--loading-double-bounce1-animation-play-state: running;--loading-double-bounce2-animation-play-state: running;--loading-cube1-animation-play-state: running;--loading-cube2-animation-play-state: running;--loading-dot-animation-play-state: running;--loading-dot1-animation-play-state: running;--loading-dot2-animation-play-state: running;--loading-triple-bounce-div-animation-play-state: running;--loading-scale-out-animation-play-state: running;--loading-circle-container-div-animation-play-state: running;--loading-circle-line-border-animation-play-state: running;--loading-square-box1-animation-play-state: running;--loading-square-box2-animation-play-state: running;--loading-pulse-bubble-1-animation-play-state: running;--loading-pulse-bubble-2-animation-play-state: running;--loading-pulse-bubble-3-animation-play-state: running;--loading-solar-earth-orbit-animation-play-state: running;--loading-solar-venus-orbit-animation-play-state: running;--loading-solar-mercury-orbit-animation-play-state: running;--loading-cube-fold-item-before-animation-play-state: running;--loading-circle-fold-item-before-animation-play-state: running;--loading-cube-grid-item-animation-play-state: running;--loading-circle-turn-animation-play-state: running;--loading-circle-rotate-outer-animation-play-state: running;--loading-circle-rotate-inner-animation-play-state: running;--loading-circle-spin-inner-animation-play-state: running;--loading-circle-spin-outer-animation-play-state: running;--loading-dot-bar-item-animation-play-state: running;--loading-dot-circle-item-1-animation-play-state: running;--loading-dot-circle-item-2-animation-play-state: running;--loading-dot-circle-item-3-animation-play-state: running;--loading-dot-circle-item-4-animation-play-state: running;--loading-dot-circle-item-5-animation-play-state: running;--loading-line-item-animation-play-state: running;--loading-dot-pulse-item-dot-animation-play-state: running;--loading-dot-pulse-item-ball-animation-play-state: running;--loading-line-scale-item-animation-play-state: running;--loading-text-item-animation-play-state: running;--loading-cube-dim-item-animation-play-state: running;--loading-dot-line-item-animation-play-state: running;--loading-arc-item-animation-play-state: running;--loading-arc-item-after-animation-play-state: running;--loading-arc-h1-after-animation-play-state: running;--loading-drop-item-animation-play-state: running;--loading-drop-dot-animation-play-state: running;--loading-drop-dot-2-animation-play-state: running;--loading-pacman-div-nth-child-2-animation-play-state: running;--loading-pacman-div-nth-child-3-animation-play-state: running;--loading-pacman-div-nth-child-4-animation-play-state: running;--loading-pacman-div-nth-child-5-animation-play-state: running;--loading-pacman-div-first-of-type-animation-play-state: running;--loading-arc-item-before-animation-play-state: running}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-roman-cyrillic.C5lxZ8CY.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-roman-greek-ext.CqjqNYQ-.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-roman-greek.BBVDIX6e.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-roman-vietnamese.BjW4sHH5.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-roman-latin-ext.4ZJIpNVo.woff2) format("woff2");unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:normal;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-roman-latin.Di8DUHzh.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-italic-cyrillic-ext.r48I6akx.woff2) format("woff2");unicode-range:U+0460-052F,U+1C80-1C88,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-italic-cyrillic.By2_1cv3.woff2) format("woff2");unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-italic-greek-ext.1u6EdAuj.woff2) format("woff2");unicode-range:U+1F00-1FFF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-italic-greek.DJ8dCoTZ.woff2) format("woff2");unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-italic-vietnamese.BSbpV94h.woff2) format("woff2");unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-italic-latin-ext.CN1xVJS-.woff2) format("woff2");unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter;font-style:italic;font-weight:100 900;font-display:swap;src:url(/ran/assets/inter-italic-latin.C2AdPX0b.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Punctuation SC;font-weight:400;src:local("PingFang SC Regular"),local("Noto Sans CJK SC"),local("Microsoft YaHei");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:500;src:local("PingFang SC Medium"),local("Noto Sans CJK SC"),local("Microsoft YaHei");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:600;src:local("PingFang SC Semibold"),local("Noto Sans CJK SC Bold"),local("Microsoft YaHei Bold");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}@font-face{font-family:Punctuation SC;font-weight:700;src:local("PingFang SC Semibold"),local("Noto Sans CJK SC Bold"),local("Microsoft YaHei Bold");unicode-range:U+201C,U+201D,U+2018,U+2019,U+2E3A,U+2014,U+2013,U+2026,U+00B7,U+007E,U+002F}:root{--vp-c-white: #ffffff;--vp-c-black: #000000;--vp-c-neutral: var(--vp-c-black);--vp-c-neutral-inverse: var(--vp-c-white)}.dark{--vp-c-neutral: var(--vp-c-white);--vp-c-neutral-inverse: var(--vp-c-black)}:root{--vp-c-gray-1: #dddde3;--vp-c-gray-2: #e4e4e9;--vp-c-gray-3: #ebebef;--vp-c-gray-soft: rgba(142, 150, 170, .14);--vp-c-indigo-1: #3451b2;--vp-c-indigo-2: #3a5ccc;--vp-c-indigo-3: #5672cd;--vp-c-indigo-soft: rgba(100, 108, 255, .14);--vp-c-purple-1: #6f42c1;--vp-c-purple-2: #7e4cc9;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .14);--vp-c-green-1: #18794e;--vp-c-green-2: #299764;--vp-c-green-3: #30a46c;--vp-c-green-soft: rgba(16, 185, 129, .14);--vp-c-yellow-1: #915930;--vp-c-yellow-2: #946300;--vp-c-yellow-3: #9f6a00;--vp-c-yellow-soft: rgba(234, 179, 8, .14);--vp-c-red-1: #b8272c;--vp-c-red-2: #d5393e;--vp-c-red-3: #e0575b;--vp-c-red-soft: rgba(244, 63, 94, .14);--vp-c-sponsor: #db2777}.dark{--vp-c-gray-1: #515c67;--vp-c-gray-2: #414853;--vp-c-gray-3: #32363f;--vp-c-gray-soft: rgba(101, 117, 133, .16);--vp-c-indigo-1: #a8b1ff;--vp-c-indigo-2: #5c73e7;--vp-c-indigo-3: #3e63dd;--vp-c-indigo-soft: rgba(100, 108, 255, .16);--vp-c-purple-1: #c8abfa;--vp-c-purple-2: #a879e6;--vp-c-purple-3: #8e5cd9;--vp-c-purple-soft: rgba(159, 122, 234, .16);--vp-c-green-1: #3dd68c;--vp-c-green-2: #30a46c;--vp-c-green-3: #298459;--vp-c-green-soft: rgba(16, 185, 129, .16);--vp-c-yellow-1: #f9b44e;--vp-c-yellow-2: #da8b17;--vp-c-yellow-3: #a46a0a;--vp-c-yellow-soft: rgba(234, 179, 8, .16);--vp-c-red-1: #f66f81;--vp-c-red-2: #f14158;--vp-c-red-3: #b62a3c;--vp-c-red-soft: rgba(244, 63, 94, .16)}:root{--vp-c-bg: #ffffff;--vp-c-bg-alt: #f6f6f7;--vp-c-bg-elv: #ffffff;--vp-c-bg-soft: #f6f6f7}.dark{--vp-c-bg: #1b1b1f;--vp-c-bg-alt: #161618;--vp-c-bg-elv: #202127;--vp-c-bg-soft: #202127}:root{--vp-c-border: #c2c2c4;--vp-c-divider: #e2e2e3;--vp-c-gutter: #e2e2e3}.dark{--vp-c-border: #3c3f44;--vp-c-divider: #2e2e32;--vp-c-gutter: #000000}:root{--vp-c-text-1: rgba(60, 60, 67);--vp-c-text-2: rgba(60, 60, 67, .78);--vp-c-text-3: rgba(60, 60, 67, .56)}.dark{--vp-c-text-1: rgba(255, 255, 245, .86);--vp-c-text-2: rgba(235, 235, 245, .6);--vp-c-text-3: rgba(235, 235, 245, .38)}:root{--vp-c-default-1: var(--vp-c-gray-1);--vp-c-default-2: var(--vp-c-gray-2);--vp-c-default-3: var(--vp-c-gray-3);--vp-c-default-soft: var(--vp-c-gray-soft);--vp-c-brand-1: var(--vp-c-indigo-1);--vp-c-brand-2: var(--vp-c-indigo-2);--vp-c-brand-3: var(--vp-c-indigo-3);--vp-c-brand-soft: var(--vp-c-indigo-soft);--vp-c-brand: var(--vp-c-brand-1);--vp-c-tip-1: var(--vp-c-brand-1);--vp-c-tip-2: var(--vp-c-brand-2);--vp-c-tip-3: var(--vp-c-brand-3);--vp-c-tip-soft: var(--vp-c-brand-soft);--vp-c-note-1: var(--vp-c-brand-1);--vp-c-note-2: var(--vp-c-brand-2);--vp-c-note-3: var(--vp-c-brand-3);--vp-c-note-soft: var(--vp-c-brand-soft);--vp-c-success-1: var(--vp-c-green-1);--vp-c-success-2: var(--vp-c-green-2);--vp-c-success-3: var(--vp-c-green-3);--vp-c-success-soft: var(--vp-c-green-soft);--vp-c-important-1: var(--vp-c-purple-1);--vp-c-important-2: var(--vp-c-purple-2);--vp-c-important-3: var(--vp-c-purple-3);--vp-c-important-soft: var(--vp-c-purple-soft);--vp-c-warning-1: var(--vp-c-yellow-1);--vp-c-warning-2: var(--vp-c-yellow-2);--vp-c-warning-3: var(--vp-c-yellow-3);--vp-c-warning-soft: var(--vp-c-yellow-soft);--vp-c-danger-1: var(--vp-c-red-1);--vp-c-danger-2: var(--vp-c-red-2);--vp-c-danger-3: var(--vp-c-red-3);--vp-c-danger-soft: var(--vp-c-red-soft);--vp-c-caution-1: var(--vp-c-red-1);--vp-c-caution-2: var(--vp-c-red-2);--vp-c-caution-3: var(--vp-c-red-3);--vp-c-caution-soft: var(--vp-c-red-soft)}:root{--vp-font-family-base: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--vp-font-family-mono: ui-monospace, "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;font-optical-sizing:auto}:root:where(:lang(zh)){--vp-font-family-base: "Punctuation SC", "Inter", ui-sans-serif, system-ui, "PingFang SC", "Noto Sans CJK SC", "Noto Sans SC", "Heiti SC", "Microsoft YaHei", "DengXian", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"}:root{--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, .04), 0 1px 2px rgba(0, 0, 0, .06);--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, .07), 0 1px 4px rgba(0, 0, 0, .07);--vp-shadow-3: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);--vp-shadow-4: 0 14px 44px rgba(0, 0, 0, .12), 0 3px 9px rgba(0, 0, 0, .12);--vp-shadow-5: 0 18px 56px rgba(0, 0, 0, .16), 0 4px 12px rgba(0, 0, 0, .16)}:root{--vp-z-index-footer: 10;--vp-z-index-local-nav: 20;--vp-z-index-nav: 30;--vp-z-index-layout-top: 40;--vp-z-index-backdrop: 50;--vp-z-index-sidebar: 60}@media (min-width: 960px){:root{--vp-z-index-sidebar: 25}}:root{--vp-layout-max-width: 1440px}:root{--vp-header-anchor-symbol: "#"}:root{--vp-code-line-height: 1.7;--vp-code-font-size: .875em;--vp-code-color: var(--vp-c-brand-1);--vp-code-link-color: var(--vp-c-brand-1);--vp-code-link-hover-color: var(--vp-c-brand-2);--vp-code-bg: var(--vp-c-default-soft);--vp-code-block-color: var(--vp-c-text-2);--vp-code-block-bg: var(--vp-c-bg-alt);--vp-code-block-divider-color: var(--vp-c-gutter);--vp-code-lang-color: var(--vp-c-text-3);--vp-code-line-highlight-color: var(--vp-c-default-soft);--vp-code-line-number-color: var(--vp-c-text-3);--vp-code-line-diff-add-color: var(--vp-c-success-soft);--vp-code-line-diff-add-symbol-color: var(--vp-c-success-1);--vp-code-line-diff-remove-color: var(--vp-c-danger-soft);--vp-code-line-diff-remove-symbol-color: var(--vp-c-danger-1);--vp-code-line-warning-color: var(--vp-c-warning-soft);--vp-code-line-error-color: var(--vp-c-danger-soft);--vp-code-copy-code-border-color: var(--vp-c-divider);--vp-code-copy-code-bg: var(--vp-c-bg-soft);--vp-code-copy-code-hover-border-color: var(--vp-c-divider);--vp-code-copy-code-hover-bg: var(--vp-c-bg);--vp-code-copy-code-active-text: var(--vp-c-text-2);--vp-code-copy-copied-text-content: "Copied";--vp-code-tab-divider: var(--vp-code-block-divider-color);--vp-code-tab-text-color: var(--vp-c-text-2);--vp-code-tab-bg: var(--vp-code-block-bg);--vp-code-tab-hover-text-color: var(--vp-c-text-1);--vp-code-tab-active-text-color: var(--vp-c-text-1);--vp-code-tab-active-bar-color: var(--vp-c-brand-1)}:root{--vp-button-brand-border: transparent;--vp-button-brand-text: var(--vp-c-white);--vp-button-brand-bg: var(--vp-c-brand-3);--vp-button-brand-hover-border: transparent;--vp-button-brand-hover-text: var(--vp-c-white);--vp-button-brand-hover-bg: var(--vp-c-brand-2);--vp-button-brand-active-border: transparent;--vp-button-brand-active-text: var(--vp-c-white);--vp-button-brand-active-bg: var(--vp-c-brand-1);--vp-button-alt-border: transparent;--vp-button-alt-text: var(--vp-c-text-1);--vp-button-alt-bg: var(--vp-c-default-3);--vp-button-alt-hover-border: transparent;--vp-button-alt-hover-text: var(--vp-c-text-1);--vp-button-alt-hover-bg: var(--vp-c-default-2);--vp-button-alt-active-border: transparent;--vp-button-alt-active-text: var(--vp-c-text-1);--vp-button-alt-active-bg: var(--vp-c-default-1);--vp-button-sponsor-border: var(--vp-c-text-2);--vp-button-sponsor-text: var(--vp-c-text-2);--vp-button-sponsor-bg: transparent;--vp-button-sponsor-hover-border: var(--vp-c-sponsor);--vp-button-sponsor-hover-text: var(--vp-c-sponsor);--vp-button-sponsor-hover-bg: transparent;--vp-button-sponsor-active-border: var(--vp-c-sponsor);--vp-button-sponsor-active-text: var(--vp-c-sponsor);--vp-button-sponsor-active-bg: transparent}:root{--vp-custom-block-font-size: 14px;--vp-custom-block-code-font-size: 13px;--vp-custom-block-info-border: transparent;--vp-custom-block-info-text: var(--vp-c-text-1);--vp-custom-block-info-bg: var(--vp-c-default-soft);--vp-custom-block-info-code-bg: var(--vp-c-default-soft);--vp-custom-block-note-border: transparent;--vp-custom-block-note-text: var(--vp-c-text-1);--vp-custom-block-note-bg: var(--vp-c-default-soft);--vp-custom-block-note-code-bg: var(--vp-c-default-soft);--vp-custom-block-tip-border: transparent;--vp-custom-block-tip-text: var(--vp-c-text-1);--vp-custom-block-tip-bg: var(--vp-c-tip-soft);--vp-custom-block-tip-code-bg: var(--vp-c-tip-soft);--vp-custom-block-important-border: transparent;--vp-custom-block-important-text: var(--vp-c-text-1);--vp-custom-block-important-bg: var(--vp-c-important-soft);--vp-custom-block-important-code-bg: var(--vp-c-important-soft);--vp-custom-block-warning-border: transparent;--vp-custom-block-warning-text: var(--vp-c-text-1);--vp-custom-block-warning-bg: var(--vp-c-warning-soft);--vp-custom-block-warning-code-bg: var(--vp-c-warning-soft);--vp-custom-block-danger-border: transparent;--vp-custom-block-danger-text: var(--vp-c-text-1);--vp-custom-block-danger-bg: var(--vp-c-danger-soft);--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);--vp-custom-block-caution-border: transparent;--vp-custom-block-caution-text: var(--vp-c-text-1);--vp-custom-block-caution-bg: var(--vp-c-caution-soft);--vp-custom-block-caution-code-bg: var(--vp-c-caution-soft);--vp-custom-block-details-border: var(--vp-custom-block-info-border);--vp-custom-block-details-text: var(--vp-custom-block-info-text);--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);--vp-custom-block-details-code-bg: var(--vp-custom-block-info-code-bg)}:root{--vp-input-border-color: var(--vp-c-border);--vp-input-bg-color: var(--vp-c-bg-alt);--vp-input-switch-bg-color: var(--vp-c-default-soft)}:root{--vp-nav-height: 64px;--vp-nav-bg-color: var(--vp-c-bg);--vp-nav-screen-bg-color: var(--vp-c-bg);--vp-nav-logo-height: 24px}.hide-nav{--vp-nav-height: 0px}.hide-nav .VPSidebar{--vp-nav-height: 22px}:root{--vp-local-nav-bg-color: var(--vp-c-bg)}:root{--vp-sidebar-width: 272px;--vp-sidebar-bg-color: var(--vp-c-bg-alt)}:root{--vp-backdrop-bg-color: rgba(0, 0, 0, .6)}:root{--vp-home-hero-name-color: var(--vp-c-brand-1);--vp-home-hero-name-background: transparent;--vp-home-hero-image-background-image: none;--vp-home-hero-image-filter: none}:root{--vp-badge-info-border: transparent;--vp-badge-info-text: var(--vp-c-text-2);--vp-badge-info-bg: var(--vp-c-default-soft);--vp-badge-tip-border: transparent;--vp-badge-tip-text: var(--vp-c-tip-1);--vp-badge-tip-bg: var(--vp-c-tip-soft);--vp-badge-warning-border: transparent;--vp-badge-warning-text: var(--vp-c-warning-1);--vp-badge-warning-bg: var(--vp-c-warning-soft);--vp-badge-danger-border: transparent;--vp-badge-danger-text: var(--vp-c-danger-1);--vp-badge-danger-bg: var(--vp-c-danger-soft)}:root{--vp-carbon-ads-text-color: var(--vp-c-text-1);--vp-carbon-ads-poweredby-color: var(--vp-c-text-2);--vp-carbon-ads-bg-color: var(--vp-c-bg-soft);--vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);--vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1)}:root{--vp-local-search-bg: var(--vp-c-bg);--vp-local-search-result-bg: var(--vp-c-bg);--vp-local-search-result-border: var(--vp-c-divider);--vp-local-search-result-selected-bg: var(--vp-c-bg);--vp-local-search-result-selected-border: var(--vp-c-brand-1);--vp-local-search-highlight-bg: var(--vp-c-brand-1);--vp-local-search-highlight-text: var(--vp-c-neutral-inverse)}@media (prefers-reduced-motion: reduce){*,:before,:after{animation-delay:-1ms!important;animation-duration:1ms!important;animation-iteration-count:1!important;background-attachment:initial!important;scroll-behavior:auto!important;transition-duration:0s!important;transition-delay:0s!important}}*,:before,:after{box-sizing:border-box}html{line-height:1.4;font-size:16px;-webkit-text-size-adjust:100%}html.dark{color-scheme:dark}body{margin:0;width:100%;min-width:320px;min-height:100vh;line-height:24px;font-family:var(--vp-font-family-base);font-size:16px;font-weight:400;color:var(--vp-c-text-1);background-color:var(--vp-c-bg);font-synthesis:style;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}main{display:block}h1,h2,h3,h4,h5,h6{margin:0;line-height:24px;font-size:16px;font-weight:400}p{margin:0}strong,b{font-weight:600}a,area,button,[role=button],input,label,select,summary,textarea{touch-action:manipulation}ol,ul{list-style:none;margin:0;padding:0}blockquote{margin:0}pre,code,kbd,samp{font-family:var(--vp-font-family-mono)}img,svg,video,canvas,audio,iframe,embed,object{display:block}figure{margin:0}button,input,optgroup,select,textarea{border:0;padding:0;line-height:inherit;color:inherit}button{padding:0;font-family:inherit;background-color:transparent;background-image:none}button:enabled,[role=button]:enabled{cursor:pointer}button:focus,button:focus-visible{outline:1px dotted;outline:4px auto -webkit-focus-ring-color}button:focus:not(:focus-visible){outline:none!important}input:focus,textarea:focus,select:focus{outline:none}table{border-collapse:collapse}input{background-color:transparent}input::-moz-placeholder,textarea::-moz-placeholder{color:var(--vp-c-text-3)}input::placeholder,textarea::placeholder{color:var(--vp-c-text-3)}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}select{-webkit-appearance:none}h1,h2,h3,h4,h5,h6,li,p{overflow-wrap:break-word}vite-error-overlay{z-index:9999}mjx-container{overflow-x:auto}mjx-container>svg{display:inline-block;margin:auto}[class^=vpi-],[class*=" vpi-"],.vp-icon{width:1em;height:1em}[class^=vpi-].bg,[class*=" vpi-"].bg,.vp-icon.bg{background-size:100% 100%;background-color:transparent}[class^=vpi-]:not(.bg),[class*=" vpi-"]:not(.bg),.vp-icon:not(.bg){-webkit-mask:var(--icon) no-repeat;mask:var(--icon) no-repeat;-webkit-mask-size:100% 100%;mask-size:100% 100%;background-color:currentColor;color:inherit}.vpi-align-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M21 6H3M15 12H3M17 18H3'/%3E%3C/svg%3E")}.vpi-arrow-right,.vpi-arrow-down,.vpi-arrow-left,.vpi-arrow-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M12 5l7 7-7 7'/%3E%3C/svg%3E")}.vpi-chevron-right,.vpi-chevron-down,.vpi-chevron-left,.vpi-chevron-up{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E")}.vpi-chevron-down,.vpi-arrow-down{transform:rotate(90deg)}.vpi-chevron-left,.vpi-arrow-left{transform:rotate(180deg)}.vpi-chevron-up,.vpi-arrow-up{transform:rotate(-90deg)}.vpi-square-pen{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7'/%3E%3Cpath d='M18.375 2.625a2.121 2.121 0 1 1 3 3L12 15l-4 1 1-4Z'/%3E%3C/svg%3E")}.vpi-plus{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M5 12h14M12 5v14'/%3E%3C/svg%3E")}.vpi-sun{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41'/%3E%3C/svg%3E")}.vpi-moon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z'/%3E%3C/svg%3E")}.vpi-more-horizontal{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='1'/%3E%3Ccircle cx='19' cy='12' r='1'/%3E%3Ccircle cx='5' cy='12' r='1'/%3E%3C/svg%3E")}.vpi-languages{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m5 8 6 6M4 14l6-6 2-3M2 5h12M7 2h1M22 22l-5-10-5 10M14 18h6'/%3E%3C/svg%3E")}.vpi-heart{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z'/%3E%3C/svg%3E")}.vpi-search{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E")}.vpi-layout-list{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='7' height='7' x='3' y='3' rx='1'/%3E%3Crect width='7' height='7' x='3' y='14' rx='1'/%3E%3Cpath d='M14 4h7M14 9h7M14 15h7M14 20h7'/%3E%3C/svg%3E")}.vpi-delete{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M20 5H9l-7 7 7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2ZM18 9l-6 6M12 9l6 6'/%3E%3C/svg%3E")}.vpi-corner-down-left{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='m9 10-5 5 5 5'/%3E%3Cpath d='M20 4v7a4 4 0 0 1-4 4H4'/%3E%3C/svg%3E")}:root{--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3C/svg%3E");--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='rgba(128,128,128,1)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Crect width='8' height='4' x='8' y='2' rx='1' ry='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='m9 14 2 2 4-4'/%3E%3C/svg%3E")}.vpi-social-discord{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418Z'/%3E%3C/svg%3E")}.vpi-social-facebook{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z'/%3E%3C/svg%3E")}.vpi-social-github{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E")}.vpi-social-instagram{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.03.084c-1.277.06-2.149.264-2.91.563a5.874 5.874 0 0 0-2.124 1.388 5.878 5.878 0 0 0-1.38 2.127C.321 4.926.12 5.8.064 7.076.008 8.354-.005 8.764.001 12.023c.007 3.259.021 3.667.083 4.947.061 1.277.264 2.149.563 2.911.308.789.72 1.457 1.388 2.123a5.872 5.872 0 0 0 2.129 1.38c.763.295 1.636.496 2.913.552 1.278.056 1.689.069 4.947.063 3.257-.007 3.668-.021 4.947-.082 1.28-.06 2.147-.265 2.91-.563a5.881 5.881 0 0 0 2.123-1.388 5.881 5.881 0 0 0 1.38-2.129c.295-.763.496-1.636.551-2.912.056-1.28.07-1.69.063-4.948-.006-3.258-.02-3.667-.081-4.947-.06-1.28-.264-2.148-.564-2.911a5.892 5.892 0 0 0-1.387-2.123 5.857 5.857 0 0 0-2.128-1.38C19.074.322 18.202.12 16.924.066 15.647.009 15.236-.006 11.977 0 8.718.008 8.31.021 7.03.084m.14 21.693c-1.17-.05-1.805-.245-2.228-.408a3.736 3.736 0 0 1-1.382-.895 3.695 3.695 0 0 1-.9-1.378c-.165-.423-.363-1.058-.417-2.228-.06-1.264-.072-1.644-.08-4.848-.006-3.204.006-3.583.061-4.848.05-1.169.246-1.805.408-2.228.216-.561.477-.96.895-1.382a3.705 3.705 0 0 1 1.379-.9c.423-.165 1.057-.361 2.227-.417 1.265-.06 1.644-.072 4.848-.08 3.203-.006 3.583.006 4.85.062 1.168.05 1.804.244 2.227.408.56.216.96.475 1.382.895.421.42.681.817.9 1.378.165.422.362 1.056.417 2.227.06 1.265.074 1.645.08 4.848.005 3.203-.006 3.583-.061 4.848-.051 1.17-.245 1.805-.408 2.23-.216.56-.477.96-.896 1.38a3.705 3.705 0 0 1-1.378.9c-.422.165-1.058.362-2.226.418-1.266.06-1.645.072-4.85.079-3.204.007-3.582-.006-4.848-.06m9.783-16.192a1.44 1.44 0 1 0 1.437-1.442 1.44 1.44 0 0 0-1.437 1.442M5.839 12.012a6.161 6.161 0 1 0 12.323-.024 6.162 6.162 0 0 0-12.323.024M8 12.008A4 4 0 1 1 12.008 16 4 4 0 0 1 8 12.008'/%3E%3C/svg%3E")}.vpi-social-linkedin{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.064 2.064 0 1 1 2.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z'/%3E%3C/svg%3E")}.vpi-social-mastodon{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z'/%3E%3C/svg%3E")}.vpi-social-npm{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M1.763 0C.786 0 0 .786 0 1.763v20.474C0 23.214.786 24 1.763 24h20.474c.977 0 1.763-.786 1.763-1.763V1.763C24 .786 23.214 0 22.237 0zM5.13 5.323l13.837.019-.009 13.836h-3.464l.01-10.382h-3.456L12.04 19.17H5.113z'/%3E%3C/svg%3E")}.vpi-social-slack{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zm10.122 2.521a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834zm-1.268 0a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zm-2.523 10.122a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zm0-1.268a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z'/%3E%3C/svg%3E")}.vpi-social-twitter,.vpi-social-x{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z'/%3E%3C/svg%3E")}.vpi-social-youtube{--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z'/%3E%3C/svg%3E")}.visually-hidden{position:absolute;width:1px;height:1px;white-space:nowrap;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden}.custom-block{border:1px solid transparent;border-radius:8px;padding:16px 16px 8px;line-height:24px;font-size:var(--vp-custom-block-font-size);color:var(--vp-c-text-2)}.custom-block.info{border-color:var(--vp-custom-block-info-border);color:var(--vp-custom-block-info-text);background-color:var(--vp-custom-block-info-bg)}.custom-block.info a,.custom-block.info code{color:var(--vp-c-brand-1)}.custom-block.info a:hover,.custom-block.info a:hover>code{color:var(--vp-c-brand-2)}.custom-block.info code{background-color:var(--vp-custom-block-info-code-bg)}.custom-block.note{border-color:var(--vp-custom-block-note-border);color:var(--vp-custom-block-note-text);background-color:var(--vp-custom-block-note-bg)}.custom-block.note a,.custom-block.note code{color:var(--vp-c-brand-1)}.custom-block.note a:hover,.custom-block.note a:hover>code{color:var(--vp-c-brand-2)}.custom-block.note code{background-color:var(--vp-custom-block-note-code-bg)}.custom-block.tip{border-color:var(--vp-custom-block-tip-border);color:var(--vp-custom-block-tip-text);background-color:var(--vp-custom-block-tip-bg)}.custom-block.tip a,.custom-block.tip code{color:var(--vp-c-tip-1)}.custom-block.tip a:hover,.custom-block.tip a:hover>code{color:var(--vp-c-tip-2)}.custom-block.tip code{background-color:var(--vp-custom-block-tip-code-bg)}.custom-block.important{border-color:var(--vp-custom-block-important-border);color:var(--vp-custom-block-important-text);background-color:var(--vp-custom-block-important-bg)}.custom-block.important a,.custom-block.important code{color:var(--vp-c-important-1)}.custom-block.important a:hover,.custom-block.important a:hover>code{color:var(--vp-c-important-2)}.custom-block.important code{background-color:var(--vp-custom-block-important-code-bg)}.custom-block.warning{border-color:var(--vp-custom-block-warning-border);color:var(--vp-custom-block-warning-text);background-color:var(--vp-custom-block-warning-bg)}.custom-block.warning a,.custom-block.warning code{color:var(--vp-c-warning-1)}.custom-block.warning a:hover,.custom-block.warning a:hover>code{color:var(--vp-c-warning-2)}.custom-block.warning code{background-color:var(--vp-custom-block-warning-code-bg)}.custom-block.danger{border-color:var(--vp-custom-block-danger-border);color:var(--vp-custom-block-danger-text);background-color:var(--vp-custom-block-danger-bg)}.custom-block.danger a,.custom-block.danger code{color:var(--vp-c-danger-1)}.custom-block.danger a:hover,.custom-block.danger a:hover>code{color:var(--vp-c-danger-2)}.custom-block.danger code{background-color:var(--vp-custom-block-danger-code-bg)}.custom-block.caution{border-color:var(--vp-custom-block-caution-border);color:var(--vp-custom-block-caution-text);background-color:var(--vp-custom-block-caution-bg)}.custom-block.caution a,.custom-block.caution code{color:var(--vp-c-caution-1)}.custom-block.caution a:hover,.custom-block.caution a:hover>code{color:var(--vp-c-caution-2)}.custom-block.caution code{background-color:var(--vp-custom-block-caution-code-bg)}.custom-block.details{border-color:var(--vp-custom-block-details-border);color:var(--vp-custom-block-details-text);background-color:var(--vp-custom-block-details-bg)}.custom-block.details a{color:var(--vp-c-brand-1)}.custom-block.details a:hover,.custom-block.details a:hover>code{color:var(--vp-c-brand-2)}.custom-block.details code{background-color:var(--vp-custom-block-details-code-bg)}.custom-block-title{font-weight:600}.custom-block p+p{margin:8px 0}.custom-block.details summary{margin:0 0 8px;font-weight:700;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.custom-block.details summary+p{margin:8px 0}.custom-block a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:2px;transition:opacity .25s}.custom-block a:hover{opacity:.75}.custom-block code{font-size:var(--vp-custom-block-code-font-size)}.custom-block.custom-block th,.custom-block.custom-block blockquote>p{font-size:var(--vp-custom-block-font-size);color:inherit}.dark .vp-code span{color:var(--shiki-dark, inherit)}html:not(.dark) .vp-code span{color:var(--shiki-light, inherit)}.vp-code-group{margin-top:16px}.vp-code-group .tabs{position:relative;display:flex;margin-right:-24px;margin-left:-24px;padding:0 12px;background-color:var(--vp-code-tab-bg);overflow-x:auto;overflow-y:hidden;box-shadow:inset 0 -1px var(--vp-code-tab-divider)}@media (min-width: 640px){.vp-code-group .tabs{margin-right:0;margin-left:0;border-radius:8px 8px 0 0}}.vp-code-group .tabs input{position:fixed;opacity:0;pointer-events:none}.vp-code-group .tabs label{position:relative;display:inline-block;border-bottom:1px solid transparent;padding:0 12px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-code-tab-text-color);white-space:nowrap;cursor:pointer;transition:color .25s}.vp-code-group .tabs label:after{position:absolute;right:8px;bottom:-1px;left:8px;z-index:1;height:2px;border-radius:2px;content:"";background-color:transparent;transition:background-color .25s}.vp-code-group label:hover{color:var(--vp-code-tab-hover-text-color)}.vp-code-group input:checked+label{color:var(--vp-code-tab-active-text-color)}.vp-code-group input:checked+label:after{background-color:var(--vp-code-tab-active-bar-color)}.vp-code-group div[class*=language-],.vp-block{display:none;margin-top:0!important;border-top-left-radius:0!important;border-top-right-radius:0!important}.vp-code-group div[class*=language-].active,.vp-block.active{display:block}.vp-block{padding:20px 24px}.vp-doc h1,.vp-doc h2,.vp-doc h3,.vp-doc h4,.vp-doc h5,.vp-doc h6{position:relative;font-weight:600;outline:none}.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:28px}.vp-doc h2{margin:48px 0 16px;border-top:1px solid var(--vp-c-divider);padding-top:24px;letter-spacing:-.02em;line-height:32px;font-size:24px}.vp-doc h3{margin:32px 0 0;letter-spacing:-.01em;line-height:28px;font-size:20px}.vp-doc h4{margin:24px 0 0;letter-spacing:-.01em;line-height:24px;font-size:18px}.vp-doc .header-anchor{position:absolute;top:0;left:0;margin-left:-.87em;font-weight:500;-webkit-user-select:none;-moz-user-select:none;user-select:none;opacity:0;text-decoration:none;transition:color .25s,opacity .25s}.vp-doc .header-anchor:before{content:var(--vp-header-anchor-symbol)}.vp-doc h1:hover .header-anchor,.vp-doc h1 .header-anchor:focus,.vp-doc h2:hover .header-anchor,.vp-doc h2 .header-anchor:focus,.vp-doc h3:hover .header-anchor,.vp-doc h3 .header-anchor:focus,.vp-doc h4:hover .header-anchor,.vp-doc h4 .header-anchor:focus,.vp-doc h5:hover .header-anchor,.vp-doc h5 .header-anchor:focus,.vp-doc h6:hover .header-anchor,.vp-doc h6 .header-anchor:focus{opacity:1}@media (min-width: 768px){.vp-doc h1{letter-spacing:-.02em;line-height:40px;font-size:32px}}.vp-doc h2 .header-anchor{top:24px}.vp-doc p,.vp-doc summary{margin:16px 0}.vp-doc p{line-height:28px}.vp-doc blockquote{margin:16px 0;border-left:2px solid var(--vp-c-divider);padding-left:16px;transition:border-color .5s;color:var(--vp-c-text-2)}.vp-doc blockquote>p{margin:0;font-size:16px;transition:color .5s}.vp-doc a{font-weight:500;color:var(--vp-c-brand-1);text-decoration:underline;text-underline-offset:2px;transition:color .25s,opacity .25s}.vp-doc a:hover{color:var(--vp-c-brand-2)}.vp-doc strong{font-weight:600}.vp-doc ul,.vp-doc ol{padding-left:1.25rem;margin:16px 0}.vp-doc ul{list-style:disc}.vp-doc ol{list-style:decimal}.vp-doc li+li{margin-top:8px}.vp-doc li>ol,.vp-doc li>ul{margin:8px 0 0}.vp-doc table{display:block;border-collapse:collapse;margin:20px 0;overflow-x:auto}.vp-doc tr{background-color:var(--vp-c-bg);border-top:1px solid var(--vp-c-divider);transition:background-color .5s}.vp-doc tr:nth-child(2n){background-color:var(--vp-c-bg-soft)}.vp-doc th,.vp-doc td{border:1px solid var(--vp-c-divider);padding:8px 16px}.vp-doc th{text-align:left;font-size:14px;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-doc td{font-size:14px}.vp-doc hr{margin:16px 0;border:none;border-top:1px solid var(--vp-c-divider)}.vp-doc .custom-block{margin:16px 0}.vp-doc .custom-block p{margin:8px 0;line-height:24px}.vp-doc .custom-block p:first-child{margin:0}.vp-doc .custom-block div[class*=language-]{margin:8px 0;border-radius:8px}.vp-doc .custom-block div[class*=language-] code{font-weight:400;background-color:transparent}.vp-doc .custom-block .vp-code-group .tabs{margin:0;border-radius:8px 8px 0 0}.vp-doc :not(pre,h1,h2,h3,h4,h5,h6)>code{font-size:var(--vp-code-font-size);color:var(--vp-code-color)}.vp-doc :not(pre)>code{border-radius:4px;padding:3px 6px;background-color:var(--vp-code-bg);transition:color .25s,background-color .5s}.vp-doc a>code{color:var(--vp-code-link-color)}.vp-doc a:hover>code{color:var(--vp-code-link-hover-color)}.vp-doc h1>code,.vp-doc h2>code,.vp-doc h3>code,.vp-doc h4>code{font-size:.9em}.vp-doc div[class*=language-],.vp-block{position:relative;margin:16px -24px;background-color:var(--vp-code-block-bg);overflow-x:auto;transition:background-color .5s}@media (min-width: 640px){.vp-doc div[class*=language-],.vp-block{border-radius:8px;margin:16px 0}}@media (max-width: 639px){.vp-doc li div[class*=language-]{border-radius:8px 0 0 8px}}.vp-doc div[class*=language-]+div[class*=language-],.vp-doc div[class$=-api]+div[class*=language-],.vp-doc div[class*=language-]+div[class$=-api]>div[class*=language-]{margin-top:-8px}.vp-doc [class*=language-] pre,.vp-doc [class*=language-] code{direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}.vp-doc [class*=language-] pre{position:relative;z-index:1;margin:0;padding:20px 0;background:transparent;overflow-x:auto}.vp-doc [class*=language-] code{display:block;padding:0 24px;width:-moz-fit-content;width:fit-content;min-width:100%;line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-block-color);transition:color .5s}.vp-doc [class*=language-] code .highlighted{background-color:var(--vp-code-line-highlight-color);transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .highlighted.error{background-color:var(--vp-code-line-error-color)}.vp-doc [class*=language-] code .highlighted.warning{background-color:var(--vp-code-line-warning-color)}.vp-doc [class*=language-] code .diff{transition:background-color .5s;margin:0 -24px;padding:0 24px;width:calc(100% + 48px);display:inline-block}.vp-doc [class*=language-] code .diff:before{position:absolute;left:10px}.vp-doc [class*=language-] .has-focused-lines .line:not(.has-focus){filter:blur(.095rem);opacity:.7;transition:filter .35s,opacity .35s}.vp-doc [class*=language-]:hover .has-focused-lines .line:not(.has-focus){filter:blur(0);opacity:1}.vp-doc [class*=language-] code .diff.remove{background-color:var(--vp-code-line-diff-remove-color);opacity:.7}.vp-doc [class*=language-] code .diff.remove:before{content:"-";color:var(--vp-code-line-diff-remove-symbol-color)}.vp-doc [class*=language-] code .diff.add{background-color:var(--vp-code-line-diff-add-color)}.vp-doc [class*=language-] code .diff.add:before{content:"+";color:var(--vp-code-line-diff-add-symbol-color)}.vp-doc div[class*=language-].line-numbers-mode{padding-left:32px}.vp-doc .line-numbers-wrapper{position:absolute;top:0;bottom:0;left:0;z-index:3;border-right:1px solid var(--vp-code-block-divider-color);padding-top:20px;width:32px;text-align:center;font-family:var(--vp-font-family-mono);line-height:var(--vp-code-line-height);font-size:var(--vp-code-font-size);color:var(--vp-code-line-number-color);transition:border-color .5s,color .5s}.vp-doc [class*=language-]>button.copy{direction:ltr;position:absolute;top:12px;right:12px;z-index:3;border:1px solid var(--vp-code-copy-code-border-color);border-radius:4px;width:40px;height:40px;background-color:var(--vp-code-copy-code-bg);opacity:0;cursor:pointer;background-image:var(--vp-icon-copy);background-position:50%;background-size:20px;background-repeat:no-repeat;transition:border-color .25s,background-color .25s,opacity .25s}.vp-doc [class*=language-]:hover>button.copy,.vp-doc [class*=language-]>button.copy:focus{opacity:1}.vp-doc [class*=language-]>button.copy:hover,.vp-doc [class*=language-]>button.copy.copied{border-color:var(--vp-code-copy-code-hover-border-color);background-color:var(--vp-code-copy-code-hover-bg)}.vp-doc [class*=language-]>button.copy.copied,.vp-doc [class*=language-]>button.copy:hover.copied{border-radius:0 4px 4px 0;background-color:var(--vp-code-copy-code-hover-bg);background-image:var(--vp-icon-copied)}.vp-doc [class*=language-]>button.copy.copied:before,.vp-doc [class*=language-]>button.copy:hover.copied:before{position:relative;top:-1px;transform:translate(calc(-100% - 1px));display:flex;justify-content:center;align-items:center;border:1px solid var(--vp-code-copy-code-hover-border-color);border-right:0;border-radius:4px 0 0 4px;padding:0 10px;width:-moz-fit-content;width:fit-content;height:40px;text-align:center;font-size:12px;font-weight:500;color:var(--vp-code-copy-code-active-text);background-color:var(--vp-code-copy-code-hover-bg);white-space:nowrap;content:var(--vp-code-copy-copied-text-content)}.vp-doc [class*=language-]>span.lang{position:absolute;top:2px;right:8px;z-index:2;font-size:12px;font-weight:500;color:var(--vp-code-lang-color);transition:color .4s,opacity .4s}.vp-doc [class*=language-]:hover>button.copy+span.lang,.vp-doc [class*=language-]>button.copy:focus+span.lang{opacity:0}.vp-doc .VPTeamMembers{margin-top:24px}.vp-doc .VPTeamMembers.small.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}.vp-doc .VPTeamMembers.small.count-2 .container,.vp-doc .VPTeamMembers.small.count-3 .container{max-width:100%!important}.vp-doc .VPTeamMembers.medium.count-1 .container{margin:0!important;max-width:calc((100% - 24px)/2)!important}:is(.vp-external-link-icon,.vp-doc a[href*="://"],.vp-doc a[target=_blank]):not(.no-icon):after{display:inline-block;margin-top:-1px;margin-left:4px;width:11px;height:11px;background:currentColor;color:var(--vp-c-text-3);flex-shrink:0;--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");-webkit-mask-image:var(--icon);mask-image:var(--icon)}.vp-external-link-icon:after{content:""}.external-link-icon-enabled :is(.vp-doc a[href*="://"],.vp-doc a[target=_blank]):after{content:"";color:currentColor}.vp-sponsor{border-radius:16px;overflow:hidden}.vp-sponsor.aside{border-radius:12px}.vp-sponsor-section+.vp-sponsor-section{margin-top:4px}.vp-sponsor-tier{margin:0 0 4px!important;text-align:center;letter-spacing:1px!important;line-height:24px;width:100%;font-weight:600;color:var(--vp-c-text-2);background-color:var(--vp-c-bg-soft)}.vp-sponsor.normal .vp-sponsor-tier{padding:13px 0 11px;font-size:14px}.vp-sponsor.aside .vp-sponsor-tier{padding:9px 0 7px;font-size:12px}.vp-sponsor-grid+.vp-sponsor-tier{margin-top:4px}.vp-sponsor-grid{display:flex;flex-wrap:wrap;gap:4px}.vp-sponsor-grid.xmini .vp-sponsor-grid-link{height:64px}.vp-sponsor-grid.xmini .vp-sponsor-grid-image{max-width:64px;max-height:22px}.vp-sponsor-grid.mini .vp-sponsor-grid-link{height:72px}.vp-sponsor-grid.mini .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.small .vp-sponsor-grid-link{height:96px}.vp-sponsor-grid.small .vp-sponsor-grid-image{max-width:96px;max-height:24px}.vp-sponsor-grid.medium .vp-sponsor-grid-link{height:112px}.vp-sponsor-grid.medium .vp-sponsor-grid-image{max-width:120px;max-height:36px}.vp-sponsor-grid.big .vp-sponsor-grid-link{height:184px}.vp-sponsor-grid.big .vp-sponsor-grid-image{max-width:192px;max-height:56px}.vp-sponsor-grid[data-vp-grid="2"] .vp-sponsor-grid-item{width:calc((100% - 4px)/2)}.vp-sponsor-grid[data-vp-grid="3"] .vp-sponsor-grid-item{width:calc((100% - 4px * 2) / 3)}.vp-sponsor-grid[data-vp-grid="4"] .vp-sponsor-grid-item{width:calc((100% - 12px)/4)}.vp-sponsor-grid[data-vp-grid="5"] .vp-sponsor-grid-item{width:calc((100% - 16px)/5)}.vp-sponsor-grid[data-vp-grid="6"] .vp-sponsor-grid-item{width:calc((100% - 4px * 5) / 6)}.vp-sponsor-grid-item{flex-shrink:0;width:100%;background-color:var(--vp-c-bg-soft);transition:background-color .25s}.vp-sponsor-grid-item:hover{background-color:var(--vp-c-default-soft)}.vp-sponsor-grid-item:hover .vp-sponsor-grid-image{filter:grayscale(0) invert(0)}.vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.dark .vp-sponsor-grid-item:hover{background-color:var(--vp-c-white)}.dark .vp-sponsor-grid-item.empty:hover{background-color:var(--vp-c-bg-soft)}.vp-sponsor-grid-link{display:flex}.vp-sponsor-grid-box{display:flex;justify-content:center;align-items:center;width:100%}.vp-sponsor-grid-image{max-width:100%;filter:grayscale(1);transition:filter .25s}.dark .vp-sponsor-grid-image{filter:grayscale(1) invert(1)}.VPBadge{display:inline-block;margin-left:2px;border:1px solid transparent;border-radius:12px;padding:0 10px;line-height:22px;font-size:12px;font-weight:500;transform:translateY(-2px)}.VPBadge.small{padding:0 6px;line-height:18px;font-size:10px;transform:translateY(-8px)}.VPDocFooter .VPBadge{display:none}.vp-doc h1>.VPBadge{margin-top:4px;vertical-align:top}.vp-doc h2>.VPBadge{margin-top:3px;padding:0 8px;vertical-align:top}.vp-doc h3>.VPBadge{vertical-align:middle}.vp-doc h4>.VPBadge,.vp-doc h5>.VPBadge,.vp-doc h6>.VPBadge{vertical-align:middle;line-height:18px}.VPBadge.info{border-color:var(--vp-badge-info-border);color:var(--vp-badge-info-text);background-color:var(--vp-badge-info-bg)}.VPBadge.tip{border-color:var(--vp-badge-tip-border);color:var(--vp-badge-tip-text);background-color:var(--vp-badge-tip-bg)}.VPBadge.warning{border-color:var(--vp-badge-warning-border);color:var(--vp-badge-warning-text);background-color:var(--vp-badge-warning-bg)}.VPBadge.danger{border-color:var(--vp-badge-danger-border);color:var(--vp-badge-danger-text);background-color:var(--vp-badge-danger-bg)}.VPBackdrop[data-v-aa2f5bb7]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:var(--vp-z-index-backdrop);background:var(--vp-backdrop-bg-color);transition:opacity .5s}.VPBackdrop.fade-enter-from[data-v-aa2f5bb7],.VPBackdrop.fade-leave-to[data-v-aa2f5bb7]{opacity:0}.VPBackdrop.fade-leave-active[data-v-aa2f5bb7]{transition-duration:.25s}@media (min-width: 1280px){.VPBackdrop[data-v-aa2f5bb7]{display:none}}.NotFound[data-v-46f27357]{padding:64px 24px 96px;text-align:center}@media (min-width: 768px){.NotFound[data-v-46f27357]{padding:96px 32px 168px}}.code[data-v-46f27357]{line-height:64px;font-size:64px;font-weight:600}.title[data-v-46f27357]{padding-top:12px;letter-spacing:2px;line-height:20px;font-size:20px;font-weight:700}.divider[data-v-46f27357]{margin:24px auto 18px;width:64px;height:1px;background-color:var(--vp-c-divider)}.quote[data-v-46f27357]{margin:0 auto;max-width:256px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.action[data-v-46f27357]{padding-top:20px}.link[data-v-46f27357]{display:inline-block;border:1px solid var(--vp-c-brand-1);border-radius:16px;padding:3px 16px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:border-color .25s,color .25s}.link[data-v-46f27357]:hover{border-color:var(--vp-c-brand-2);color:var(--vp-c-brand-2)}.root[data-v-fc78d431]{position:relative;z-index:1}.nested[data-v-fc78d431]{padding-right:16px;padding-left:16px}.outline-link[data-v-fc78d431]{display:block;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .5s}.outline-link[data-v-fc78d431]:hover,.outline-link.active[data-v-fc78d431]{color:var(--vp-c-text-1);transition:color .25s}.outline-link.nested[data-v-fc78d431]{padding-left:13px}.VPDocAsideOutline[data-v-e95709bb]{display:none}.VPDocAsideOutline.has-outline[data-v-e95709bb]{display:block}.content[data-v-e95709bb]{position:relative;border-left:1px solid var(--vp-c-divider);padding-left:16px;font-size:13px;font-weight:500}.outline-marker[data-v-e95709bb]{position:absolute;top:32px;left:-1px;z-index:0;opacity:0;width:2px;border-radius:2px;height:18px;background-color:var(--vp-c-brand-1);transition:top .25s cubic-bezier(0,1,.5,1),background-color .5s,opacity .25s}.outline-title[data-v-e95709bb]{line-height:32px;font-size:14px;font-weight:600}.VPDocAside[data-v-4bbff643]{display:flex;flex-direction:column;flex-grow:1}.spacer[data-v-4bbff643]{flex-grow:1}.VPDocAside[data-v-4bbff643] .spacer+.VPDocAsideSponsors,.VPDocAside[data-v-4bbff643] .spacer+.VPDocAsideCarbonAds{margin-top:24px}.VPDocAside[data-v-4bbff643] .VPDocAsideSponsors+.VPDocAsideCarbonAds{margin-top:16px}.VPLastUpdated[data-v-3c231858]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 640px){.VPLastUpdated[data-v-3c231858]{line-height:32px;font-size:14px;font-weight:500}}.VPDocFooter[data-v-00ab7d08]{margin-top:64px}.edit-info[data-v-00ab7d08]{padding-bottom:18px}@media (min-width: 640px){.edit-info[data-v-00ab7d08]{display:flex;justify-content:space-between;align-items:center;padding-bottom:14px}}.edit-link-button[data-v-00ab7d08]{display:flex;align-items:center;border:0;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.edit-link-button[data-v-00ab7d08]:hover{color:var(--vp-c-brand-2)}.edit-link-icon[data-v-00ab7d08]{margin-right:8px}.prev-next[data-v-00ab7d08]{border-top:1px solid var(--vp-c-divider);padding-top:24px;display:grid;grid-row-gap:8px}@media (min-width: 640px){.prev-next[data-v-00ab7d08]{grid-template-columns:repeat(2,1fr);grid-column-gap:16px}}.pager-link[data-v-00ab7d08]{display:block;border:1px solid var(--vp-c-divider);border-radius:8px;padding:11px 16px 13px;width:100%;height:100%;transition:border-color .25s}.pager-link[data-v-00ab7d08]:hover{border-color:var(--vp-c-brand-1)}.pager-link.next[data-v-00ab7d08]{margin-left:auto;text-align:right}.desc[data-v-00ab7d08]{display:block;line-height:20px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.title[data-v-00ab7d08]{display:block;line-height:20px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1);transition:color .25s}.VPDoc[data-v-9f8645df]{padding:32px 24px 96px;width:100%}@media (min-width: 768px){.VPDoc[data-v-9f8645df]{padding:48px 32px 128px}}@media (min-width: 960px){.VPDoc[data-v-9f8645df]{padding:48px 32px 0}.VPDoc:not(.has-sidebar) .container[data-v-9f8645df]{display:flex;justify-content:center;max-width:992px}.VPDoc:not(.has-sidebar) .content[data-v-9f8645df]{max-width:752px}}@media (min-width: 1280px){.VPDoc .container[data-v-9f8645df]{display:flex;justify-content:center}.VPDoc .aside[data-v-9f8645df]{display:block}}@media (min-width: 1440px){.VPDoc:not(.has-sidebar) .content[data-v-9f8645df]{max-width:784px}.VPDoc:not(.has-sidebar) .container[data-v-9f8645df]{max-width:1104px}}.container[data-v-9f8645df]{margin:0 auto;width:100%}.aside[data-v-9f8645df]{position:relative;display:none;order:2;flex-grow:1;padding-left:32px;width:100%;max-width:256px}.left-aside[data-v-9f8645df]{order:1;padding-left:unset;padding-right:32px}.aside-container[data-v-9f8645df]{position:fixed;top:0;padding-top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 48px);width:224px;height:100vh;overflow-x:hidden;overflow-y:auto;scrollbar-width:none}.aside-container[data-v-9f8645df]::-webkit-scrollbar{display:none}.aside-curtain[data-v-9f8645df]{position:fixed;bottom:0;z-index:10;width:224px;height:32px;background:linear-gradient(transparent,var(--vp-c-bg) 70%)}.aside-content[data-v-9f8645df]{display:flex;flex-direction:column;min-height:calc(100vh - (var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px));padding-bottom:32px}.content[data-v-9f8645df]{position:relative;margin:0 auto;width:100%}@media (min-width: 960px){.content[data-v-9f8645df]{padding:0 32px 128px}}@media (min-width: 1280px){.content[data-v-9f8645df]{order:1;margin:0;min-width:640px}}.content-container[data-v-9f8645df]{margin:0 auto}.VPDoc.has-aside .content-container[data-v-9f8645df]{max-width:688px}.VPButton[data-v-bbea5d5d]{display:inline-block;border:1px solid transparent;text-align:center;font-weight:600;white-space:nowrap;transition:color .25s,border-color .25s,background-color .25s}.VPButton[data-v-bbea5d5d]:active{transition:color .1s,border-color .1s,background-color .1s}.VPButton.medium[data-v-bbea5d5d]{border-radius:20px;padding:0 20px;line-height:38px;font-size:14px}.VPButton.big[data-v-bbea5d5d]{border-radius:24px;padding:0 24px;line-height:46px;font-size:16px}.VPButton.brand[data-v-bbea5d5d]{border-color:var(--vp-button-brand-border);color:var(--vp-button-brand-text);background-color:var(--vp-button-brand-bg)}.VPButton.brand[data-v-bbea5d5d]:hover{border-color:var(--vp-button-brand-hover-border);color:var(--vp-button-brand-hover-text);background-color:var(--vp-button-brand-hover-bg)}.VPButton.brand[data-v-bbea5d5d]:active{border-color:var(--vp-button-brand-active-border);color:var(--vp-button-brand-active-text);background-color:var(--vp-button-brand-active-bg)}.VPButton.alt[data-v-bbea5d5d]{border-color:var(--vp-button-alt-border);color:var(--vp-button-alt-text);background-color:var(--vp-button-alt-bg)}.VPButton.alt[data-v-bbea5d5d]:hover{border-color:var(--vp-button-alt-hover-border);color:var(--vp-button-alt-hover-text);background-color:var(--vp-button-alt-hover-bg)}.VPButton.alt[data-v-bbea5d5d]:active{border-color:var(--vp-button-alt-active-border);color:var(--vp-button-alt-active-text);background-color:var(--vp-button-alt-active-bg)}.VPButton.sponsor[data-v-bbea5d5d]{border-color:var(--vp-button-sponsor-border);color:var(--vp-button-sponsor-text);background-color:var(--vp-button-sponsor-bg)}.VPButton.sponsor[data-v-bbea5d5d]:hover{border-color:var(--vp-button-sponsor-hover-border);color:var(--vp-button-sponsor-hover-text);background-color:var(--vp-button-sponsor-hover-bg)}.VPButton.sponsor[data-v-bbea5d5d]:active{border-color:var(--vp-button-sponsor-active-border);color:var(--vp-button-sponsor-active-text);background-color:var(--vp-button-sponsor-active-bg)}html:not(.dark) .VPImage.dark[data-v-7b8f395d]{display:none}.dark .VPImage.light[data-v-7b8f395d]{display:none}.VPHero[data-v-0313f8fa]{margin-top:calc((var(--vp-nav-height) + var(--vp-layout-top-height, 0px)) * -1);padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 48px) 24px 48px}@media (min-width: 640px){.VPHero[data-v-0313f8fa]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 48px 64px}}@media (min-width: 960px){.VPHero[data-v-0313f8fa]{padding:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + 80px) 64px 64px}}.container[data-v-0313f8fa]{display:flex;flex-direction:column;margin:0 auto;max-width:1152px}@media (min-width: 960px){.container[data-v-0313f8fa]{flex-direction:row}}.main[data-v-0313f8fa]{position:relative;z-index:10;order:2;flex-grow:1;flex-shrink:0}.VPHero.has-image .container[data-v-0313f8fa]{text-align:center}@media (min-width: 960px){.VPHero.has-image .container[data-v-0313f8fa]{text-align:left}.main[data-v-0313f8fa]{order:1;width:calc((100% / 3) * 2)}.VPHero.has-image .main[data-v-0313f8fa]{max-width:592px}}.name[data-v-0313f8fa],.text[data-v-0313f8fa]{max-width:392px;letter-spacing:-.4px;line-height:40px;font-size:32px;font-weight:700;white-space:pre-wrap}.VPHero.has-image .name[data-v-0313f8fa],.VPHero.has-image .text[data-v-0313f8fa]{margin:0 auto}.name[data-v-0313f8fa]{color:var(--vp-home-hero-name-color)}.clip[data-v-0313f8fa]{background:var(--vp-home-hero-name-background);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:var(--vp-home-hero-name-color)}@media (min-width: 640px){.name[data-v-0313f8fa],.text[data-v-0313f8fa]{max-width:576px;line-height:56px;font-size:48px}}@media (min-width: 960px){.name[data-v-0313f8fa],.text[data-v-0313f8fa]{line-height:64px;font-size:56px}.VPHero.has-image .name[data-v-0313f8fa],.VPHero.has-image .text[data-v-0313f8fa]{margin:0}}.tagline[data-v-0313f8fa]{padding-top:8px;max-width:392px;line-height:28px;font-size:18px;font-weight:500;white-space:pre-wrap;color:var(--vp-c-text-2)}.VPHero.has-image .tagline[data-v-0313f8fa]{margin:0 auto}@media (min-width: 640px){.tagline[data-v-0313f8fa]{padding-top:12px;max-width:576px;line-height:32px;font-size:20px}}@media (min-width: 960px){.tagline[data-v-0313f8fa]{line-height:36px;font-size:24px}.VPHero.has-image .tagline[data-v-0313f8fa]{margin:0}}.actions[data-v-0313f8fa]{display:flex;flex-wrap:wrap;margin:-6px;padding-top:24px}.VPHero.has-image .actions[data-v-0313f8fa]{justify-content:center}@media (min-width: 640px){.actions[data-v-0313f8fa]{padding-top:32px}}@media (min-width: 960px){.VPHero.has-image .actions[data-v-0313f8fa]{justify-content:flex-start}}.action[data-v-0313f8fa]{flex-shrink:0;padding:6px}.image[data-v-0313f8fa]{order:1;margin:-76px -24px -48px}@media (min-width: 640px){.image[data-v-0313f8fa]{margin:-108px -24px -48px}}@media (min-width: 960px){.image[data-v-0313f8fa]{flex-grow:1;order:2;margin:0;min-height:100%}}.image-container[data-v-0313f8fa]{position:relative;margin:0 auto;width:320px;height:320px}@media (min-width: 640px){.image-container[data-v-0313f8fa]{width:392px;height:392px}}@media (min-width: 960px){.image-container[data-v-0313f8fa]{display:flex;justify-content:center;align-items:center;width:100%;height:100%;transform:translate(-32px,-32px)}}.image-bg[data-v-0313f8fa]{position:absolute;top:50%;left:50%;border-radius:50%;width:192px;height:192px;background-image:var(--vp-home-hero-image-background-image);filter:var(--vp-home-hero-image-filter);transform:translate(-50%,-50%)}@media (min-width: 640px){.image-bg[data-v-0313f8fa]{width:256px;height:256px}}@media (min-width: 960px){.image-bg[data-v-0313f8fa]{width:320px;height:320px}}[data-v-0313f8fa] .image-src{position:absolute;top:50%;left:50%;max-width:192px;max-height:192px;transform:translate(-50%,-50%)}@media (min-width: 640px){[data-v-0313f8fa] .image-src{max-width:256px;max-height:256px}}@media (min-width: 960px){[data-v-0313f8fa] .image-src{max-width:320px;max-height:320px}}.VPFeature[data-v-ce15ebd4]{display:block;border:1px solid var(--vp-c-bg-soft);border-radius:12px;height:100%;background-color:var(--vp-c-bg-soft);transition:border-color .25s,background-color .25s}.VPFeature.link[data-v-ce15ebd4]:hover{border-color:var(--vp-c-brand-1)}.box[data-v-ce15ebd4]{display:flex;flex-direction:column;padding:24px;height:100%}.box[data-v-ce15ebd4]>.VPImage{margin-bottom:20px}.icon[data-v-ce15ebd4]{display:flex;justify-content:center;align-items:center;margin-bottom:20px;border-radius:6px;background-color:var(--vp-c-default-soft);width:48px;height:48px;font-size:24px;transition:background-color .25s}.title[data-v-ce15ebd4]{line-height:24px;font-size:16px;font-weight:600}.details[data-v-ce15ebd4]{flex-grow:1;padding-top:8px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.link-text[data-v-ce15ebd4]{padding-top:8px}.link-text-value[data-v-ce15ebd4]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.link-text-icon[data-v-ce15ebd4]{margin-left:6px}.VPFeatures[data-v-b79e191c]{position:relative;padding:0 24px}@media (min-width: 640px){.VPFeatures[data-v-b79e191c]{padding:0 48px}}@media (min-width: 960px){.VPFeatures[data-v-b79e191c]{padding:0 64px}}.container[data-v-b79e191c]{margin:0 auto;max-width:1152px}.items[data-v-b79e191c]{display:flex;flex-wrap:wrap;margin:-8px}.item[data-v-b79e191c]{padding:8px;width:100%}@media (min-width: 640px){.item.grid-2[data-v-b79e191c],.item.grid-4[data-v-b79e191c],.item.grid-6[data-v-b79e191c]{width:50%}}@media (min-width: 768px){.item.grid-2[data-v-b79e191c],.item.grid-4[data-v-b79e191c]{width:50%}.item.grid-3[data-v-b79e191c],.item.grid-6[data-v-b79e191c]{width:calc(100% / 3)}}@media (min-width: 960px){.item.grid-4[data-v-b79e191c]{width:25%}}.container[data-v-269c2bad]{margin:auto;width:100%;max-width:1280px;padding:0 24px}@media (min-width: 640px){.container[data-v-269c2bad]{padding:0 48px}}@media (min-width: 960px){.container[data-v-269c2bad]{width:100%;padding:0 64px}}.vp-doc[data-v-269c2bad] .VPHomeSponsors,.vp-doc[data-v-269c2bad] .VPTeamPage{margin-left:var(--vp-offset, calc(50% - 50vw) );margin-right:var(--vp-offset, calc(50% - 50vw) )}.vp-doc[data-v-269c2bad] .VPHomeSponsors h2{border-top:none;letter-spacing:normal}.vp-doc[data-v-269c2bad] .VPHomeSponsors a,.vp-doc[data-v-269c2bad] .VPTeamPage a{text-decoration:none}.VPHome[data-v-c1e44215]{margin-bottom:96px}@media (min-width: 768px){.VPHome[data-v-c1e44215]{margin-bottom:128px}}.VPContent[data-v-c575eed1]{flex-grow:1;flex-shrink:0;margin:var(--vp-layout-top-height, 0px) auto 0;width:100%}.VPContent.is-home[data-v-c575eed1]{width:100%;max-width:100%}.VPContent.has-sidebar[data-v-c575eed1]{margin:0}@media (min-width: 960px){.VPContent[data-v-c575eed1]{padding-top:var(--vp-nav-height)}.VPContent.has-sidebar[data-v-c575eed1]{margin:var(--vp-layout-top-height, 0px) 0 0;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPContent.has-sidebar[data-v-c575eed1]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.VPFooter[data-v-042815a5]{position:relative;z-index:var(--vp-z-index-footer);border-top:1px solid var(--vp-c-gutter);padding:32px 24px;background-color:var(--vp-c-bg)}.VPFooter.has-sidebar[data-v-042815a5]{display:none}.VPFooter[data-v-042815a5] a{text-decoration-line:underline;text-underline-offset:2px;transition:color .25s}.VPFooter[data-v-042815a5] a:hover{color:var(--vp-c-text-1)}@media (min-width: 768px){.VPFooter[data-v-042815a5]{padding:32px}}.container[data-v-042815a5]{margin:0 auto;max-width:var(--vp-layout-max-width);text-align:center}.message[data-v-042815a5],.copyright[data-v-042815a5]{line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-2)}.VPLocalNavOutlineDropdown[data-v-fd549330]{padding:12px 20px 11px}@media (min-width: 960px){.VPLocalNavOutlineDropdown[data-v-fd549330]{padding:12px 36px 11px}}.VPLocalNavOutlineDropdown button[data-v-fd549330]{display:block;font-size:12px;font-weight:500;line-height:24px;color:var(--vp-c-text-2);transition:color .5s;position:relative}.VPLocalNavOutlineDropdown button[data-v-fd549330]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPLocalNavOutlineDropdown button.open[data-v-fd549330]{color:var(--vp-c-text-1)}.icon[data-v-fd549330]{display:inline-block;vertical-align:middle;margin-left:2px;font-size:14px;transform:rotate(0);transition:transform .25s}@media (min-width: 960px){.VPLocalNavOutlineDropdown button[data-v-fd549330]{font-size:14px}.icon[data-v-fd549330]{font-size:16px}}.open>.icon[data-v-fd549330]{transform:rotate(90deg)}.items[data-v-fd549330]{position:absolute;top:40px;right:16px;left:16px;display:grid;gap:1px;border:1px solid var(--vp-c-border);border-radius:8px;background-color:var(--vp-c-gutter);max-height:calc(var(--vp-vh, 100vh) - 86px);overflow:hidden auto;box-shadow:var(--vp-shadow-3)}@media (min-width: 960px){.items[data-v-fd549330]{right:auto;left:calc(var(--vp-sidebar-width) + 32px);width:320px}}.header[data-v-fd549330]{background-color:var(--vp-c-bg-soft)}.top-link[data-v-fd549330]{display:block;padding:0 16px;line-height:48px;font-size:14px;font-weight:500;color:var(--vp-c-brand-1)}.outline[data-v-fd549330]{padding:8px 0;background-color:var(--vp-c-bg-soft)}.flyout-enter-active[data-v-fd549330]{transition:all .2s ease-out}.flyout-leave-active[data-v-fd549330]{transition:all .15s ease-in}.flyout-enter-from[data-v-fd549330],.flyout-leave-to[data-v-fd549330]{opacity:0;transform:translateY(-16px)}.VPLocalNav[data-v-6c3804f2]{position:sticky;top:0;left:0;z-index:var(--vp-z-index-local-nav);border-bottom:1px solid var(--vp-c-gutter);padding-top:var(--vp-layout-top-height, 0px);width:100%;background-color:var(--vp-local-nav-bg-color)}.VPLocalNav.fixed[data-v-6c3804f2]{position:fixed}@media (min-width: 960px){.VPLocalNav[data-v-6c3804f2]{top:var(--vp-nav-height)}.VPLocalNav.has-sidebar[data-v-6c3804f2]{padding-left:var(--vp-sidebar-width)}.VPLocalNav.empty[data-v-6c3804f2]{display:none}}@media (min-width: 1280px){.VPLocalNav[data-v-6c3804f2]{display:none}}@media (min-width: 1440px){.VPLocalNav.has-sidebar[data-v-6c3804f2]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.container[data-v-6c3804f2]{display:flex;justify-content:space-between;align-items:center}.menu[data-v-6c3804f2]{display:flex;align-items:center;padding:12px 24px 11px;line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.menu[data-v-6c3804f2]:hover{color:var(--vp-c-text-1);transition:color .25s}@media (min-width: 768px){.menu[data-v-6c3804f2]{padding:0 32px}}@media (min-width: 960px){.menu[data-v-6c3804f2]{display:none}}.menu-icon[data-v-6c3804f2]{margin-right:8px;font-size:14px}.VPOutlineDropdown[data-v-6c3804f2]{padding:12px 24px 11px}@media (min-width: 768px){.VPOutlineDropdown[data-v-6c3804f2]{padding:12px 32px 11px}}.VPSwitch[data-v-bdb57495]{position:relative;border-radius:11px;display:block;width:40px;height:22px;flex-shrink:0;border:1px solid var(--vp-input-border-color);background-color:var(--vp-input-switch-bg-color);transition:border-color .25s!important}.VPSwitch[data-v-bdb57495]:hover{border-color:var(--vp-c-brand-1)}.check[data-v-bdb57495]{position:absolute;top:1px;left:1px;width:18px;height:18px;border-radius:50%;background-color:var(--vp-c-neutral-inverse);box-shadow:var(--vp-shadow-1);transition:transform .25s!important}.icon[data-v-bdb57495]{position:relative;display:block;width:18px;height:18px;border-radius:50%;overflow:hidden}.icon[data-v-bdb57495] [class^=vpi-]{position:absolute;top:3px;left:3px;width:12px;height:12px;color:var(--vp-c-text-2)}.dark .icon[data-v-bdb57495] [class^=vpi-]{color:var(--vp-c-text-1);transition:opacity .25s!important}.sun[data-v-41f06fec]{opacity:1}.moon[data-v-41f06fec],.dark .sun[data-v-41f06fec]{opacity:0}.dark .moon[data-v-41f06fec]{opacity:1}.dark .VPSwitchAppearance[data-v-41f06fec] .check{transform:translate(18px)}.VPNavBarAppearance[data-v-12ad808b]{display:none}@media (min-width: 1280px){.VPNavBarAppearance[data-v-12ad808b]{display:flex;align-items:center}}.VPMenuGroup+.VPMenuLink[data-v-7e61137e]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.link[data-v-7e61137e]{display:block;border-radius:6px;padding:0 12px;line-height:32px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);white-space:nowrap;transition:background-color .25s,color .25s}.link[data-v-7e61137e]:hover{color:var(--vp-c-brand-1);background-color:var(--vp-c-default-soft)}.link.active[data-v-7e61137e]{color:var(--vp-c-brand-1)}.VPMenuGroup[data-v-b7ccc091]{margin:12px -12px 0;border-top:1px solid var(--vp-c-divider);padding:12px 12px 0}.VPMenuGroup[data-v-b7ccc091]:first-child{margin-top:0;border-top:0;padding-top:0}.VPMenuGroup+.VPMenuGroup[data-v-b7ccc091]{margin-top:12px;border-top:1px solid var(--vp-c-divider)}.title[data-v-b7ccc091]{padding:0 12px;line-height:32px;font-size:14px;font-weight:600;color:var(--vp-c-text-2);white-space:nowrap;transition:color .25s}.VPMenu[data-v-e8a1c26e]{border-radius:12px;padding:12px;min-width:128px;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);box-shadow:var(--vp-shadow-3);transition:background-color .5s;max-height:calc(100vh - var(--vp-nav-height));overflow-y:auto}.VPMenu[data-v-e8a1c26e] .group{margin:0 -12px;padding:0 12px 12px}.VPMenu[data-v-e8a1c26e] .group+.group{border-top:1px solid var(--vp-c-divider);padding:11px 12px 12px}.VPMenu[data-v-e8a1c26e] .group:last-child{padding-bottom:0}.VPMenu[data-v-e8a1c26e] .group+.item{border-top:1px solid var(--vp-c-divider);padding:11px 16px 0}.VPMenu[data-v-e8a1c26e] .item{padding:0 16px;white-space:nowrap}.VPMenu[data-v-e8a1c26e] .label{flex-grow:1;line-height:28px;font-size:12px;font-weight:500;color:var(--vp-c-text-2);transition:color .5s}.VPMenu[data-v-e8a1c26e] .action{padding-left:24px}.VPFlyout[data-v-7e42a472]{position:relative}.VPFlyout[data-v-7e42a472]:hover{color:var(--vp-c-brand-1);transition:color .25s}.VPFlyout:hover .text[data-v-7e42a472]{color:var(--vp-c-text-2)}.VPFlyout:hover .icon[data-v-7e42a472]{fill:var(--vp-c-text-2)}.VPFlyout.active .text[data-v-7e42a472]{color:var(--vp-c-brand-1)}.VPFlyout.active:hover .text[data-v-7e42a472]{color:var(--vp-c-brand-2)}.VPFlyout:hover .menu[data-v-7e42a472],.button[aria-expanded=true]+.menu[data-v-7e42a472]{opacity:1;visibility:visible;transform:translateY(0)}.button[aria-expanded=false]+.menu[data-v-7e42a472]{opacity:0;visibility:hidden;transform:translateY(0)}.button[data-v-7e42a472]{display:flex;align-items:center;padding:0 12px;height:var(--vp-nav-height);color:var(--vp-c-text-1);transition:color .5s}.text[data-v-7e42a472]{display:flex;align-items:center;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.option-icon[data-v-7e42a472]{margin-right:0;font-size:16px}.text-icon[data-v-7e42a472]{margin-left:4px;font-size:14px}.icon[data-v-7e42a472]{font-size:20px;transition:fill .25s}.menu[data-v-7e42a472]{position:absolute;top:calc(var(--vp-nav-height) / 2 + 20px);right:0;opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s,transform .25s}.VPSocialLink[data-v-1d65eafe]{display:flex;justify-content:center;align-items:center;width:36px;height:36px;color:var(--vp-c-text-2);transition:color .5s}.VPSocialLink[data-v-1d65eafe]:hover{color:var(--vp-c-text-1);transition:color .25s}.VPSocialLink[data-v-1d65eafe]>svg,.VPSocialLink[data-v-1d65eafe]>[class^=vpi-social-]{width:20px;height:20px;fill:currentColor}.VPSocialLinks[data-v-259de3d6]{display:flex;justify-content:center}.VPNavBarExtra[data-v-1b59c413]{display:none;margin-right:-12px}@media (min-width: 768px){.VPNavBarExtra[data-v-1b59c413]{display:block}}@media (min-width: 1280px){.VPNavBarExtra[data-v-1b59c413]{display:none}}.trans-title[data-v-1b59c413]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.item.appearance[data-v-1b59c413],.item.social-links[data-v-1b59c413]{display:flex;align-items:center;padding:0 12px}.item.appearance[data-v-1b59c413]{min-width:176px}.appearance-action[data-v-1b59c413]{margin-right:-2px}.social-links-list[data-v-1b59c413]{margin:-4px -8px}.VPNavBarHamburger[data-v-0fa0fd27]{display:flex;justify-content:center;align-items:center;width:48px;height:var(--vp-nav-height)}@media (min-width: 768px){.VPNavBarHamburger[data-v-0fa0fd27]{display:none}}.container[data-v-0fa0fd27]{position:relative;width:16px;height:14px;overflow:hidden}.VPNavBarHamburger:hover .top[data-v-0fa0fd27]{top:0;left:0;transform:translate(4px)}.VPNavBarHamburger:hover .middle[data-v-0fa0fd27]{top:6px;left:0;transform:translate(0)}.VPNavBarHamburger:hover .bottom[data-v-0fa0fd27]{top:12px;left:0;transform:translate(8px)}.VPNavBarHamburger.active .top[data-v-0fa0fd27]{top:6px;transform:translate(0) rotate(225deg)}.VPNavBarHamburger.active .middle[data-v-0fa0fd27]{top:6px;transform:translate(16px)}.VPNavBarHamburger.active .bottom[data-v-0fa0fd27]{top:6px;transform:translate(0) rotate(135deg)}.VPNavBarHamburger.active:hover .top[data-v-0fa0fd27],.VPNavBarHamburger.active:hover .middle[data-v-0fa0fd27],.VPNavBarHamburger.active:hover .bottom[data-v-0fa0fd27]{background-color:var(--vp-c-text-2);transition:top .25s,background-color .25s,transform .25s}.top[data-v-0fa0fd27],.middle[data-v-0fa0fd27],.bottom[data-v-0fa0fd27]{position:absolute;width:16px;height:2px;background-color:var(--vp-c-text-1);transition:top .25s,background-color .5s,transform .25s}.top[data-v-0fa0fd27]{top:0;left:0;transform:translate(0)}.middle[data-v-0fa0fd27]{top:6px;left:0;transform:translate(8px)}.bottom[data-v-0fa0fd27]{top:12px;left:0;transform:translate(4px)}.VPNavBarMenuLink[data-v-e692fe86]{display:flex;align-items:center;padding:0 12px;line-height:var(--vp-nav-height);font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.VPNavBarMenuLink.active[data-v-e692fe86],.VPNavBarMenuLink[data-v-e692fe86]:hover{color:var(--vp-c-brand-1)}.VPNavBarMenu[data-v-30753f5b]{display:none}@media (min-width: 768px){.VPNavBarMenu[data-v-30753f5b]{display:flex}}.blog-search[data-v-fd998d3a]{flex:1;display:flex;padding-left:32px}.blog-search>.nav-search-btn-wait[data-v-fd998d3a]{cursor:pointer;display:flex;align-items:center;justify-content:center;box-sizing:border-box;border:1px solid transparent;transition:.2s border;border-radius:8px;padding:0 10px 0 12px;height:40px;background-color:var(--vp-c-bg-alt)}.blog-search .nav-search-btn-wait .metaKey[data-v-fd998d3a]{margin-left:10px;font-size:12px;border:1px solid var(--vp-c-divider);border-radius:4px;padding:0 6px}.blog-search .nav-search-btn-wait[data-v-fd998d3a]:hover{border:1px solid var(--vp-c-brand-1);border-radius:6px}.blog-search .nav-search-btn-wait .search-tip[data-v-fd998d3a]{color:#909399;font-size:12px;padding-left:8px;padding-right:16px}@media screen and (max-width: 759px){.blog-search>.nav-search-btn-wait[data-v-fd998d3a]{background-color:inherit}.metaKey[data-v-fd998d3a],.search-tip[data-v-fd998d3a]{display:none}.blog-search[data-v-fd998d3a]{flex:0}}.search-bar[data-v-fd998d3a]{display:flex;cursor:text;align-items:center;border-radius:4px;border:1px solid var(--vcp-c-brand)}.search-bar input[data-v-fd998d3a]{width:100%}.search-bar .search-actions[data-v-fd998d3a]{display:flex;gap:4px;padding-right:12px}.search-bar .search-actions.before[data-v-fd998d3a]{padding:0}.search-actions button[data-v-fd998d3a]{padding:8px}.local-search-icon[data-v-fd998d3a]{display:block;font-size:18px}.search-actions button.clear-button[data-v-fd998d3a]:disabled{opacity:.37}.search-actions button[data-v-fd998d3a]:not([disabled]):hover,.search-actions button.active[data-v-fd998d3a]:not([disabled]){color:var(--vp-c-brand-1)}.search-actions.before[data-v-fd998d3a]{display:none}@media screen and (max-width: 560px){.search-actions.before[data-v-fd998d3a]{display:flex}}:root{--font-sans: "Inter", --apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;--app-bg: var(--gray1);--app-text: #000000;--command-shadow: 0 16px 70px rgb(0 0 0 / 20%);--lowContrast: #ffffff;--highContrast: #000000;--vcp-c-brand: var(--vp-c-brand-2);--vcp-c-accent: #35495e;--gray1: hsl(0, 0%, 98%);--gray2: hsl(0, 0%, 97.3%);--gray3: hsl(0, 0%, 95.1%);--gray4: hsl(0, 0%, 93%);--gray5: hsl(0, 0%, 90.9%);--gray6: hsl(0, 0%, 88.7%);--gray7: hsl(0, 0%, 85.8%);--gray8: hsl(0, 0%, 78%);--gray9: hsl(0, 0%, 56.1%);--gray10: hsl(0, 0%, 52.3%);--gray11: hsl(0, 0%, 43.5%);--gray12: hsl(0, 0%, 9%);--grayA1: hsla(0, 0%, 0%, .012);--grayA2: hsla(0, 0%, 0%, .027);--grayA3: hsla(0, 0%, 0%, .047);--grayA4: hsla(0, 0%, 0%, .071);--grayA5: hsla(0, 0%, 0%, .09);--grayA6: hsla(0, 0%, 0%, .114);--grayA7: hsla(0, 0%, 0%, .141);--grayA8: hsla(0, 0%, 0%, .22);--grayA9: hsla(0, 0%, 0%, .439);--grayA10: hsla(0, 0%, 0%, .478);--grayA11: hsla(0, 0%, 0%, .565);--grayA12: hsla(0, 0%, 0%, .91);--blue1: hsl(206, 100%, 99.2%);--blue2: hsl(210, 100%, 98%);--blue3: hsl(209, 100%, 96.5%);--blue4: hsl(210, 98.8%, 94%);--blue5: hsl(209, 95%, 90.1%);--blue6: hsl(209, 81.2%, 84.5%);--blue7: hsl(208, 77.5%, 76.9%);--blue8: hsl(206, 81.9%, 65.3%);--blue9: hsl(206, 100%, 50%);--blue10: hsl(208, 100%, 47.3%);--blue11: hsl(211, 100%, 43.2%);--blue12: hsl(211, 100%, 15%)}.dark{--app-bg: var(--gray1);--app-text: #ffffff;--lowContrast: #000000;--highContrast: #ffffff;--gray1: hsl(0, 0%, 8.5%);--gray2: hsl(0, 0%, 11%);--gray3: hsl(0, 0%, 13.6%);--gray4: hsl(0, 0%, 15.8%);--gray5: hsl(0, 0%, 17.9%);--gray6: hsl(0, 0%, 20.5%);--gray7: hsl(0, 0%, 24.3%);--gray8: hsl(0, 0%, 31.2%);--gray9: hsl(0, 0%, 43.9%);--gray10: hsl(0, 0%, 49.4%);--gray11: hsl(0, 0%, 62.8%);--gray12: hsl(0, 0%, 93%);--grayA1: hsla(0, 0%, 100%, 0);--grayA2: hsla(0, 0%, 100%, .026);--grayA3: hsla(0, 0%, 100%, .056);--grayA4: hsla(0, 0%, 100%, .077);--grayA5: hsla(0, 0%, 100%, .103);--grayA6: hsla(0, 0%, 100%, .129);--grayA7: hsla(0, 0%, 100%, .172);--grayA8: hsla(0, 0%, 100%, .249);--grayA9: hsla(0, 0%, 100%, .386);--grayA10: hsla(0, 0%, 100%, .446);--grayA11: hsla(0, 0%, 100%, .592);--grayA12: hsla(0, 0%, 100%, .923);--blue1: hsl(212, 35%, 9.2%);--blue2: hsl(216, 50%, 11.8%);--blue3: hsl(214, 59.4%, 15.3%);--blue4: hsl(214, 65.8%, 17.9%);--blue5: hsl(213, 71.2%, 20.2%);--blue6: hsl(212, 77.4%, 23.1%);--blue7: hsl(211, 85.1%, 27.4%);--blue8: hsl(211, 89.7%, 34.1%);--blue9: hsl(206, 100%, 50%);--blue10: hsl(209, 100%, 60.6%);--blue11: hsl(210, 100%, 66.1%);--blue12: hsl(206, 98%, 95.8%)}div [command-dialog-mask]{background-color:#0000004d;height:100vh;left:0;position:fixed;top:0;width:100vw;z-index:200}div [command-dialog-wrapper]{position:relative;background:var(--gray2);border-radius:6px;box-shadow:none;flex-direction:column;margin:20vh auto auto;max-width:560px}div [command-dialog-footer]{border-top:1px solid var(--gray6);align-items:center;background:var(--gray4);color:var(--gray11);border-radius:0 0 8px 8px;box-shadow:none;display:flex;flex-direction:row-reverse;flex-shrink:0;height:44px;justify-content:space-between;padding:0 12px;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%;z-index:300;font-size:12px}.algolia [command-input]{font-family:var(--font-sans);width:100%;font-size:18px;padding:12px;outline:none;background:var(--bg);color:var(--gray12);caret-color:var(--vcp-c-brand);margin:0}.algolia [command-input]::-moz-placeholder{color:var(--gray9)}.algolia [command-input]::placeholder{color:var(--gray9)}.algolia [command-list]{height:var(--command-list-height);max-height:360px;overflow:auto;overscroll-behavior:contain;transition:.1s ease;transition-property:height}.algolia .detail-list [command-item]{min-height:56px;max-height:112px;padding:10px 16px;height:auto}.algolia .detail-list [command-item] .des{word-break:break-all;white-space:wrap;margin-top:6px;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical}.algolia [command-item]{position:relative;content-visibility:auto;cursor:pointer;height:56px;font-size:14px;display:flex;align-items:center;gap:12px;padding:0 16px;color:var(--gray12);-webkit-user-select:none;-moz-user-select:none;user-select:none;will-change:background,color;transition:all .15s ease;transition-property:none;border-radius:4px;margin-top:4px;background-color:var(--lowContrast)}.algolia [command-item]:first-child{margin-top:0}.algolia [command-item][aria-selected=true],.algolia [command-item]:hover{background:var(--vcp-c-brand);color:#fff}.algolia [command-item][aria-selected=true] svg,.algolia [command-item]:hover svg{color:#fff}.algolia [command-item][aria-selected=true] [command-linear-shortcuts],.algolia [command-item]:hover [command-linear-shortcuts]{display:flex;margin-left:auto;gap:8px}.algolia [command-item][aria-selected=true] [command-linear-shortcuts] kbd,.algolia [command-item]:hover [command-linear-shortcuts] kbd{font-family:var(--font-sans);font-size:13px;color:var(--gray11)}.algolia [command-item]:active{transition-property:background;background:var(--gray4)}.algolia [command-item] svg{width:16px;height:16px;color:var(--gray10)}.algolia [command-empty=""]{font-size:14px;display:flex;align-items:center;justify-content:center;height:64px;white-space:pre-wrap;color:var(--gray11)}.algolia [command-dialog-mask]{background-color:#4b4b4bcc}.algolia [command-dialog-header]{padding:12px}.algolia [command-dialog-body]{padding:0 12px 12px}.algolia [command-dialog-footer]{align-items:center;border-radius:0 0 8px 8px;box-shadow:0 -1px #e0e3e8,0 -3px 6px #45629b1f;display:flex;flex-direction:row-reverse;flex-shrink:0;height:44px;justify-content:space-between;padding:0 12px;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%;z-index:300}.algolia [command-group-heading]{color:var(--vcp-c-brand);font-size:.85em;font-weight:600;line-height:32px;margin:0 -4px;padding:0 4px;top:0;z-index:10;width:100%}.algolia .command-palette-commands{color:var(--docsearch-muted-color);display:flex;list-style:none;margin:0;padding:0}@media screen and (max-width: 560px){.algolia .command-palette-commands{display:none}div [command-dialog-wrapper]{margin:0;height:100vh}.algolia [command-dialog-footer]{justify-content:center}.algolia [command-input]{padding:6px 4px}.algolia [command-list]{max-height:calc(100vh - 120px)}}.algolia .command-palette-commands li{display:flex;align-items:center}.algolia .command-palette-commands li:not(:last-of-type){margin-right:.8em}.algolia .command-palette-logo a{display:flex;align-items:center;gap:8px}.algolia .command-palette-logo svg{height:24px;width:24px}.algolia .command-palette-commands-key{align-items:center;background:var(--gray3);border-radius:2px;display:flex;height:18px;justify-content:center;margin-right:.4em;padding:0 0 1px;color:var(--gray11);border:0;width:20px}.dark .algolia [command-dialog-footer]{box-shadow:none}div[command-group]{display:block!important}div[command-item]{display:flex!important}.search-dialog div[command-item]>div.link{width:100%}.search-dialog div[command-item] .title{display:flex;justify-content:space-between}.search-dialog div[command-item] .title i.prefix{color:var(--vp-c-brand-1)}.search-dialog div[command-item]:hover .title i.prefix,.search-dialog div[command-item][aria-selected=true] .title i.prefix{color:#fff}.search-dialog div[command-item] .des{text-overflow:ellipsis;overflow:hidden;word-break:keep-all;white-space:nowrap}.search-dialog div[command-item] .headings{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:inline-block}.search-dialog div[command-item] .date{min-width:86px;text-align:right}.search-dialog div[command-item] mark{background:none;color:var(--vp-c-brand-1)}.search-dialog div[command-item][aria-selected=true] mark,.search-dialog div[command-item]:hover mark{color:inherit;text-decoration:underline}.VPNavBarSocialLinks[data-v-b7887d5a]{display:none}@media (min-width: 1280px){.VPNavBarSocialLinks[data-v-b7887d5a]{display:flex;align-items:center}}.title[data-v-9f785053]{display:flex;align-items:center;border-bottom:1px solid transparent;width:100%;height:var(--vp-nav-height);font-size:16px;font-weight:600;color:var(--vp-c-text-1);transition:opacity .25s}@media (min-width: 960px){.title[data-v-9f785053]{flex-shrink:0}.VPNavBarTitle.has-sidebar .title[data-v-9f785053]{border-bottom-color:var(--vp-c-divider)}}[data-v-9f785053] .logo{margin-right:8px;height:var(--vp-nav-logo-height)}.VPNavBarTranslations[data-v-d78d18d0]{display:none}@media (min-width: 1280px){.VPNavBarTranslations[data-v-d78d18d0]{display:flex;align-items:center}}.title[data-v-d78d18d0]{padding:0 24px 0 12px;line-height:32px;font-size:14px;font-weight:700;color:var(--vp-c-text-1)}.VPNavBar[data-v-f9756f2d]{position:relative;height:var(--vp-nav-height);pointer-events:none;white-space:nowrap;transition:background-color .25s}.VPNavBar.screen-open[data-v-f9756f2d]{transition:none;background-color:var(--vp-nav-bg-color);border-bottom:1px solid var(--vp-c-divider)}.VPNavBar[data-v-f9756f2d]:not(.home){background-color:var(--vp-nav-bg-color)}@media (min-width: 960px){.VPNavBar[data-v-f9756f2d]:not(.home){background-color:transparent}.VPNavBar[data-v-f9756f2d]:not(.has-sidebar):not(.home.top){background-color:var(--vp-nav-bg-color)}}.wrapper[data-v-f9756f2d]{padding:0 8px 0 24px}@media (min-width: 768px){.wrapper[data-v-f9756f2d]{padding:0 32px}}@media (min-width: 960px){.VPNavBar.has-sidebar .wrapper[data-v-f9756f2d]{padding:0}}.container[data-v-f9756f2d]{display:flex;justify-content:space-between;margin:0 auto;max-width:calc(var(--vp-layout-max-width) - 64px);height:var(--vp-nav-height);pointer-events:none}.container>.title[data-v-f9756f2d],.container>.content[data-v-f9756f2d]{pointer-events:none}.container[data-v-f9756f2d] *{pointer-events:auto}@media (min-width: 960px){.VPNavBar.has-sidebar .container[data-v-f9756f2d]{max-width:100%}}.title[data-v-f9756f2d]{flex-shrink:0;height:calc(var(--vp-nav-height) - 1px);transition:background-color .5s}@media (min-width: 960px){.VPNavBar.has-sidebar .title[data-v-f9756f2d]{position:absolute;top:0;left:0;z-index:2;padding:0 32px;width:var(--vp-sidebar-width);height:var(--vp-nav-height);background-color:transparent}}@media (min-width: 1440px){.VPNavBar.has-sidebar .title[data-v-f9756f2d]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}.content[data-v-f9756f2d]{flex-grow:1}@media (min-width: 960px){.VPNavBar.has-sidebar .content[data-v-f9756f2d]{position:relative;z-index:1;padding-right:32px;padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .content[data-v-f9756f2d]{padding-right:calc((100vw - var(--vp-layout-max-width)) / 2 + 32px);padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.content-body[data-v-f9756f2d]{display:flex;justify-content:flex-end;align-items:center;height:var(--vp-nav-height);transition:background-color .5s}@media (min-width: 960px){.VPNavBar:not(.home.top) .content-body[data-v-f9756f2d]{position:relative;background-color:var(--vp-nav-bg-color)}.VPNavBar:not(.has-sidebar):not(.home.top) .content-body[data-v-f9756f2d]{background-color:transparent}}@media (max-width: 767px){.content-body[data-v-f9756f2d]{-moz-column-gap:.5rem;column-gap:.5rem}}.menu+.translations[data-v-f9756f2d]:before,.menu+.appearance[data-v-f9756f2d]:before,.menu+.social-links[data-v-f9756f2d]:before,.translations+.appearance[data-v-f9756f2d]:before,.appearance+.social-links[data-v-f9756f2d]:before{margin-right:8px;margin-left:8px;width:1px;height:24px;background-color:var(--vp-c-divider);content:""}.menu+.appearance[data-v-f9756f2d]:before,.translations+.appearance[data-v-f9756f2d]:before{margin-right:16px}.appearance+.social-links[data-v-f9756f2d]:before{margin-left:16px}.social-links[data-v-f9756f2d]{margin-right:-8px}.divider[data-v-f9756f2d]{width:100%;height:1px}@media (min-width: 960px){.VPNavBar.has-sidebar .divider[data-v-f9756f2d]{padding-left:var(--vp-sidebar-width)}}@media (min-width: 1440px){.VPNavBar.has-sidebar .divider[data-v-f9756f2d]{padding-left:calc((100vw - var(--vp-layout-max-width)) / 2 + var(--vp-sidebar-width))}}.divider-line[data-v-f9756f2d]{width:100%;height:1px;transition:background-color .5s}.VPNavBar:not(.home) .divider-line[data-v-f9756f2d]{background-color:var(--vp-c-gutter)}@media (min-width: 960px){.VPNavBar:not(.home.top) .divider-line[data-v-f9756f2d]{background-color:var(--vp-c-gutter)}.VPNavBar:not(.has-sidebar):not(.home.top) .divider[data-v-f9756f2d]{background-color:var(--vp-c-gutter)}}.VPNavScreenAppearance[data-v-f7aa697b]{display:flex;justify-content:space-between;align-items:center;border-radius:8px;padding:12px 14px 12px 16px;background-color:var(--vp-c-bg-soft)}.text[data-v-f7aa697b]{line-height:24px;font-size:12px;font-weight:500;color:var(--vp-c-text-2)}.VPNavScreenMenuLink[data-v-8f3b9429]{display:block;border-bottom:1px solid var(--vp-c-divider);padding:12px 0 11px;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:border-color .25s,color .25s}.VPNavScreenMenuLink[data-v-8f3b9429]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupLink[data-v-7b9fb56c]{display:block;margin-left:12px;line-height:32px;font-size:14px;font-weight:400;color:var(--vp-c-text-1);transition:color .25s}.VPNavScreenMenuGroupLink[data-v-7b9fb56c]:hover{color:var(--vp-c-brand-1)}.VPNavScreenMenuGroupSection[data-v-4af57996]{display:block}.title[data-v-4af57996]{line-height:32px;font-size:13px;font-weight:700;color:var(--vp-c-text-2);transition:color .25s}.VPNavScreenMenuGroup[data-v-9e6433b0]{border-bottom:1px solid var(--vp-c-divider);height:48px;overflow:hidden;transition:border-color .5s}.VPNavScreenMenuGroup .items[data-v-9e6433b0]{visibility:hidden}.VPNavScreenMenuGroup.open .items[data-v-9e6433b0]{visibility:visible}.VPNavScreenMenuGroup.open[data-v-9e6433b0]{padding-bottom:10px;height:auto}.VPNavScreenMenuGroup.open .button[data-v-9e6433b0]{padding-bottom:6px;color:var(--vp-c-brand-1)}.VPNavScreenMenuGroup.open .button-icon[data-v-9e6433b0]{transform:rotate(45deg)}.button[data-v-9e6433b0]{display:flex;justify-content:space-between;align-items:center;padding:12px 4px 11px 0;width:100%;line-height:24px;font-size:14px;font-weight:500;color:var(--vp-c-text-1);transition:color .25s}.button[data-v-9e6433b0]:hover{color:var(--vp-c-brand-1)}.button-icon[data-v-9e6433b0]{transition:transform .25s}.group[data-v-9e6433b0]:first-child{padding-top:0}.group+.group[data-v-9e6433b0],.group+.item[data-v-9e6433b0]{padding-top:4px}.VPNavScreenTranslations[data-v-642b9e57]{height:24px;overflow:hidden}.VPNavScreenTranslations.open[data-v-642b9e57]{height:auto}.title[data-v-642b9e57]{display:flex;align-items:center;font-size:14px;font-weight:500;color:var(--vp-c-text-1)}.icon[data-v-642b9e57]{font-size:16px}.icon.lang[data-v-642b9e57]{margin-right:8px}.icon.chevron[data-v-642b9e57]{margin-left:4px}.list[data-v-642b9e57]{padding:4px 0 0 24px}.link[data-v-642b9e57]{line-height:32px;font-size:13px;color:var(--vp-c-text-1)}.VPNavScreen[data-v-1b440f23]{position:fixed;top:calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px));right:0;bottom:0;left:0;padding:0 32px;width:100%;background-color:var(--vp-nav-screen-bg-color);overflow-y:auto;transition:background-color .25s;pointer-events:auto}.VPNavScreen.fade-enter-active[data-v-1b440f23],.VPNavScreen.fade-leave-active[data-v-1b440f23]{transition:opacity .25s}.VPNavScreen.fade-enter-active .container[data-v-1b440f23],.VPNavScreen.fade-leave-active .container[data-v-1b440f23]{transition:transform .25s ease}.VPNavScreen.fade-enter-from[data-v-1b440f23],.VPNavScreen.fade-leave-to[data-v-1b440f23]{opacity:0}.VPNavScreen.fade-enter-from .container[data-v-1b440f23],.VPNavScreen.fade-leave-to .container[data-v-1b440f23]{transform:translateY(-8px)}@media (min-width: 768px){.VPNavScreen[data-v-1b440f23]{display:none}}.container[data-v-1b440f23]{margin:0 auto;padding:24px 0 96px;max-width:288px}.menu+.translations[data-v-1b440f23],.menu+.appearance[data-v-1b440f23],.translations+.appearance[data-v-1b440f23]{margin-top:24px}.menu+.social-links[data-v-1b440f23]{margin-top:16px}.appearance+.social-links[data-v-1b440f23]{margin-top:16px}.VPNav[data-v-a62deceb]{position:relative;top:var(--vp-layout-top-height, 0px);left:0;z-index:var(--vp-z-index-nav);width:100%;pointer-events:none;transition:background-color .5s}@media (min-width: 960px){.VPNav[data-v-a62deceb]{position:fixed}}.VPSidebarItem.level-0[data-v-3d6ff150]{padding-bottom:24px}.VPSidebarItem.collapsed.level-0[data-v-3d6ff150]{padding-bottom:10px}.item[data-v-3d6ff150]{position:relative;display:flex;width:100%}.VPSidebarItem.collapsible>.item[data-v-3d6ff150]{cursor:pointer}.indicator[data-v-3d6ff150]{position:absolute;top:6px;bottom:6px;left:-17px;width:2px;border-radius:2px;transition:background-color .25s}.VPSidebarItem.level-2.is-active>.item>.indicator[data-v-3d6ff150],.VPSidebarItem.level-3.is-active>.item>.indicator[data-v-3d6ff150],.VPSidebarItem.level-4.is-active>.item>.indicator[data-v-3d6ff150],.VPSidebarItem.level-5.is-active>.item>.indicator[data-v-3d6ff150]{background-color:var(--vp-c-brand-1)}.link[data-v-3d6ff150]{display:flex;align-items:center;flex-grow:1}.text[data-v-3d6ff150]{flex-grow:1;padding:4px 0;line-height:24px;font-size:14px;transition:color .25s}.VPSidebarItem.level-0 .text[data-v-3d6ff150]{font-weight:700;color:var(--vp-c-text-1)}.VPSidebarItem.level-1 .text[data-v-3d6ff150],.VPSidebarItem.level-2 .text[data-v-3d6ff150],.VPSidebarItem.level-3 .text[data-v-3d6ff150],.VPSidebarItem.level-4 .text[data-v-3d6ff150],.VPSidebarItem.level-5 .text[data-v-3d6ff150]{font-weight:500;color:var(--vp-c-text-2)}.VPSidebarItem.level-0.is-link>.item>.link:hover .text[data-v-3d6ff150],.VPSidebarItem.level-1.is-link>.item>.link:hover .text[data-v-3d6ff150],.VPSidebarItem.level-2.is-link>.item>.link:hover .text[data-v-3d6ff150],.VPSidebarItem.level-3.is-link>.item>.link:hover .text[data-v-3d6ff150],.VPSidebarItem.level-4.is-link>.item>.link:hover .text[data-v-3d6ff150],.VPSidebarItem.level-5.is-link>.item>.link:hover .text[data-v-3d6ff150]{color:var(--vp-c-brand-1)}.VPSidebarItem.level-0.has-active>.item>.text[data-v-3d6ff150],.VPSidebarItem.level-1.has-active>.item>.text[data-v-3d6ff150],.VPSidebarItem.level-2.has-active>.item>.text[data-v-3d6ff150],.VPSidebarItem.level-3.has-active>.item>.text[data-v-3d6ff150],.VPSidebarItem.level-4.has-active>.item>.text[data-v-3d6ff150],.VPSidebarItem.level-5.has-active>.item>.text[data-v-3d6ff150],.VPSidebarItem.level-0.has-active>.item>.link>.text[data-v-3d6ff150],.VPSidebarItem.level-1.has-active>.item>.link>.text[data-v-3d6ff150],.VPSidebarItem.level-2.has-active>.item>.link>.text[data-v-3d6ff150],.VPSidebarItem.level-3.has-active>.item>.link>.text[data-v-3d6ff150],.VPSidebarItem.level-4.has-active>.item>.link>.text[data-v-3d6ff150],.VPSidebarItem.level-5.has-active>.item>.link>.text[data-v-3d6ff150]{color:var(--vp-c-text-1)}.VPSidebarItem.level-0.is-active>.item .link>.text[data-v-3d6ff150],.VPSidebarItem.level-1.is-active>.item .link>.text[data-v-3d6ff150],.VPSidebarItem.level-2.is-active>.item .link>.text[data-v-3d6ff150],.VPSidebarItem.level-3.is-active>.item .link>.text[data-v-3d6ff150],.VPSidebarItem.level-4.is-active>.item .link>.text[data-v-3d6ff150],.VPSidebarItem.level-5.is-active>.item .link>.text[data-v-3d6ff150]{color:var(--vp-c-brand-1)}.caret[data-v-3d6ff150]{display:flex;justify-content:center;align-items:center;margin-right:-7px;width:32px;height:32px;color:var(--vp-c-text-3);cursor:pointer;transition:color .25s;flex-shrink:0}.item:hover .caret[data-v-3d6ff150]{color:var(--vp-c-text-2)}.item:hover .caret[data-v-3d6ff150]:hover{color:var(--vp-c-text-1)}.caret-icon[data-v-3d6ff150]{font-size:18px;transform:rotate(90deg);transition:transform .25s}.VPSidebarItem.collapsed .caret-icon[data-v-3d6ff150]{transform:rotate(0)}.VPSidebarItem.level-1 .items[data-v-3d6ff150],.VPSidebarItem.level-2 .items[data-v-3d6ff150],.VPSidebarItem.level-3 .items[data-v-3d6ff150],.VPSidebarItem.level-4 .items[data-v-3d6ff150],.VPSidebarItem.level-5 .items[data-v-3d6ff150]{border-left:1px solid var(--vp-c-divider);padding-left:16px}.VPSidebarItem.collapsed .items[data-v-3d6ff150]{display:none}.no-transition[data-v-1952544a] .caret-icon{transition:none}.group+.group[data-v-1952544a]{border-top:1px solid var(--vp-c-divider);padding-top:10px}@media (min-width: 960px){.group[data-v-1952544a]{padding-top:10px;width:calc(var(--vp-sidebar-width) - 64px)}}.VPSidebar[data-v-452d748b]{position:fixed;top:var(--vp-layout-top-height, 0px);bottom:0;left:0;z-index:var(--vp-z-index-sidebar);padding:32px 32px 96px;width:calc(100vw - 64px);max-width:320px;background-color:var(--vp-sidebar-bg-color);opacity:0;box-shadow:var(--vp-c-shadow-3);overflow-x:hidden;overflow-y:auto;transform:translate(-100%);transition:opacity .5s,transform .25s ease;overscroll-behavior:contain}.VPSidebar.open[data-v-452d748b]{opacity:1;visibility:visible;transform:translate(0);transition:opacity .25s,transform .5s cubic-bezier(.19,1,.22,1)}.dark .VPSidebar[data-v-452d748b]{box-shadow:var(--vp-shadow-1)}@media (min-width: 960px){.VPSidebar[data-v-452d748b]{padding-top:var(--vp-nav-height);width:var(--vp-sidebar-width);max-width:100%;background-color:var(--vp-sidebar-bg-color);opacity:1;visibility:visible;box-shadow:none;transform:translate(0)}}@media (min-width: 1440px){.VPSidebar[data-v-452d748b]{padding-left:max(32px,calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));width:calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px)}}@media (min-width: 960px){.curtain[data-v-452d748b]{position:sticky;top:-64px;left:0;z-index:1;margin-top:calc(var(--vp-nav-height) * -1);margin-right:-32px;margin-left:-32px;height:var(--vp-nav-height);background-color:var(--vp-sidebar-bg-color)}}.nav[data-v-452d748b]{outline:0}.VPSkipLink[data-v-e8369309]{top:8px;left:8px;padding:8px 16px;z-index:999;border-radius:8px;font-size:12px;font-weight:700;text-decoration:none;color:var(--vp-c-brand-1);box-shadow:var(--vp-shadow-3);background-color:var(--vp-c-bg)}.VPSkipLink[data-v-e8369309]:focus{height:auto;width:auto;clip:auto;clip-path:none}@media (min-width: 1280px){.VPSkipLink[data-v-e8369309]{top:14px;left:16px}}.Layout[data-v-1e8cdb3b]{display:flex;flex-direction:column;min-height:100vh}.VPHomeSponsors[data-v-a42b2a8a]{border-top:1px solid var(--vp-c-gutter);padding-top:88px!important;margin:96px 0}@media (min-width: 768px){.VPHomeSponsors[data-v-a42b2a8a]{margin:128px 0}}.VPHomeSponsors[data-v-a42b2a8a]{padding:0 24px}@media (min-width: 768px){.VPHomeSponsors[data-v-a42b2a8a]{padding:0 48px}}@media (min-width: 960px){.VPHomeSponsors[data-v-a42b2a8a]{padding:0 64px}}.container[data-v-a42b2a8a]{margin:0 auto;max-width:1152px}.love[data-v-a42b2a8a]{margin:0 auto;width:-moz-fit-content;width:fit-content;font-size:28px;color:var(--vp-c-text-3)}.icon[data-v-a42b2a8a]{display:inline-block}.message[data-v-a42b2a8a]{margin:0 auto;padding-top:10px;max-width:320px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.sponsors[data-v-a42b2a8a]{padding-top:32px}.action[data-v-a42b2a8a]{padding-top:40px;text-align:center}.VPTeamPage[data-v-5c3f84c2]{margin:96px 0}@media (min-width: 768px){.VPTeamPage[data-v-5c3f84c2]{margin:128px 0}}.VPHome .VPTeamPageTitle[data-v-5c3f84c2-s]{border-top:1px solid var(--vp-c-gutter);padding-top:88px!important}.VPTeamPageSection+.VPTeamPageSection[data-v-5c3f84c2-s],.VPTeamMembers+.VPTeamPageSection[data-v-5c3f84c2-s]{margin-top:64px}.VPTeamMembers+.VPTeamMembers[data-v-5c3f84c2-s]{margin-top:24px}@media (min-width: 768px){.VPTeamPageTitle+.VPTeamPageSection[data-v-5c3f84c2-s]{margin-top:16px}.VPTeamPageSection+.VPTeamPageSection[data-v-5c3f84c2-s],.VPTeamMembers+.VPTeamPageSection[data-v-5c3f84c2-s]{margin-top:96px}}.VPTeamMembers[data-v-5c3f84c2-s]{padding:0 24px}@media (min-width: 768px){.VPTeamMembers[data-v-5c3f84c2-s]{padding:0 48px}}@media (min-width: 960px){.VPTeamMembers[data-v-5c3f84c2-s]{padding:0 64px}}.VPTeamPageTitle[data-v-16d5aec5]{padding:48px 32px;text-align:center}@media (min-width: 768px){.VPTeamPageTitle[data-v-16d5aec5]{padding:64px 48px 48px}}@media (min-width: 960px){.VPTeamPageTitle[data-v-16d5aec5]{padding:80px 64px 48px}}.title[data-v-16d5aec5]{letter-spacing:0;line-height:44px;font-size:36px;font-weight:500}@media (min-width: 768px){.title[data-v-16d5aec5]{letter-spacing:-.5px;line-height:56px;font-size:48px}}.lead[data-v-16d5aec5]{margin:0 auto;max-width:512px;padding-top:12px;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}@media (min-width: 768px){.lead[data-v-16d5aec5]{max-width:592px;letter-spacing:.15px;line-height:28px;font-size:20px}}.VPTeamPageSection[data-v-4dd28a8a]{padding:0 32px}@media (min-width: 768px){.VPTeamPageSection[data-v-4dd28a8a]{padding:0 48px}}@media (min-width: 960px){.VPTeamPageSection[data-v-4dd28a8a]{padding:0 64px}}.title[data-v-4dd28a8a]{position:relative;margin:0 auto;max-width:1152px;text-align:center;color:var(--vp-c-text-2)}.title-line[data-v-4dd28a8a]{position:absolute;top:16px;left:0;width:100%;height:1px;background-color:var(--vp-c-divider)}.title-text[data-v-4dd28a8a]{position:relative;display:inline-block;padding:0 24px;letter-spacing:0;line-height:32px;font-size:20px;font-weight:500;background-color:var(--vp-c-bg)}.lead[data-v-4dd28a8a]{margin:0 auto;max-width:480px;padding-top:12px;text-align:center;line-height:24px;font-size:16px;font-weight:500;color:var(--vp-c-text-2)}.members[data-v-4dd28a8a]{padding-top:40px}.VPTeamMembersItem[data-v-723d38e8]{display:flex;flex-direction:column;gap:2px;border-radius:12px;width:100%;height:100%;overflow:hidden}.VPTeamMembersItem.small .profile[data-v-723d38e8]{padding:32px}.VPTeamMembersItem.small .data[data-v-723d38e8]{padding-top:20px}.VPTeamMembersItem.small .avatar[data-v-723d38e8]{width:64px;height:64px}.VPTeamMembersItem.small .name[data-v-723d38e8]{line-height:24px;font-size:16px}.VPTeamMembersItem.small .affiliation[data-v-723d38e8]{padding-top:4px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .desc[data-v-723d38e8]{padding-top:12px;line-height:20px;font-size:14px}.VPTeamMembersItem.small .links[data-v-723d38e8]{margin:0 -16px -20px;padding:10px 0 0}.VPTeamMembersItem.medium .profile[data-v-723d38e8]{padding:48px 32px}.VPTeamMembersItem.medium .data[data-v-723d38e8]{padding-top:24px;text-align:center}.VPTeamMembersItem.medium .avatar[data-v-723d38e8]{width:96px;height:96px}.VPTeamMembersItem.medium .name[data-v-723d38e8]{letter-spacing:.15px;line-height:28px;font-size:20px}.VPTeamMembersItem.medium .affiliation[data-v-723d38e8]{padding-top:4px;font-size:16px}.VPTeamMembersItem.medium .desc[data-v-723d38e8]{padding-top:16px;max-width:288px;font-size:16px}.VPTeamMembersItem.medium .links[data-v-723d38e8]{margin:0 -16px -12px;padding:16px 12px 0}.profile[data-v-723d38e8]{flex-grow:1;background-color:var(--vp-c-bg-soft)}.data[data-v-723d38e8]{text-align:center}.avatar[data-v-723d38e8]{position:relative;flex-shrink:0;margin:0 auto;border-radius:50%;box-shadow:var(--vp-shadow-3)}.avatar-img[data-v-723d38e8]{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:50%;-o-object-fit:cover;object-fit:cover}.name[data-v-723d38e8]{margin:0;font-weight:600}.affiliation[data-v-723d38e8]{margin:0;font-weight:500;color:var(--vp-c-text-2)}.org.link[data-v-723d38e8]{color:var(--vp-c-text-2);transition:color .25s}.org.link[data-v-723d38e8]:hover{color:var(--vp-c-brand-1)}.desc[data-v-723d38e8]{margin:0 auto}.desc[data-v-723d38e8] a{font-weight:500;color:var(--vp-c-brand-1);text-decoration-style:dotted;transition:color .25s}.links[data-v-723d38e8]{display:flex;justify-content:center;height:56px}.sp-link[data-v-723d38e8]{display:flex;justify-content:center;align-items:center;text-align:center;padding:16px;font-size:14px;font-weight:500;color:var(--vp-c-sponsor);background-color:var(--vp-c-bg-soft);transition:color .25s,background-color .25s}.sp .sp-link.link[data-v-723d38e8]:hover,.sp .sp-link.link[data-v-723d38e8]:focus{outline:none;color:var(--vp-c-white);background-color:var(--vp-c-sponsor)}.sp-icon[data-v-723d38e8]{margin-right:8px;font-size:16px}.VPTeamMembers.small .container[data-v-a96b8245]{grid-template-columns:repeat(auto-fit,minmax(224px,1fr))}.VPTeamMembers.small.count-1 .container[data-v-a96b8245]{max-width:276px}.VPTeamMembers.small.count-2 .container[data-v-a96b8245]{max-width:576px}.VPTeamMembers.small.count-3 .container[data-v-a96b8245]{max-width:876px}.VPTeamMembers.medium .container[data-v-a96b8245]{grid-template-columns:repeat(auto-fit,minmax(256px,1fr))}@media (min-width: 375px){.VPTeamMembers.medium .container[data-v-a96b8245]{grid-template-columns:repeat(auto-fit,minmax(288px,1fr))}}.VPTeamMembers.medium.count-1 .container[data-v-a96b8245]{max-width:368px}.VPTeamMembers.medium.count-2 .container[data-v-a96b8245]{max-width:760px}.container[data-v-a96b8245]{display:grid;gap:24px;margin:0 auto;max-width:1152px}#app .VPNavBar{border-bottom:1px solid var(--vp-c-divider-light)}#app .VPHomeHero{margin-top:20px;margin-bottom:35px}#app .VPHomeHero .main{margin-top:-40px}#app .VPNavBarTitle .title{color:transparent;background:var(--vp-home-hero-name-background);-webkit-background-clip:text}.font-icon{padding:2px 8px;border-radius:4px;display:inline-block;background-color:var(--vp-c-gray-light-4)}.dark .font-icon{background-color:var(--vp-c-bg)}p img{margin-top:2px}@media (max-width: 960px){#app .image{margin-top:-75px}#app .VPHomeHero{margin-bottom:5px}#app .VPHomeHero .main{margin-top:50px}}:root{--vp-c-brand: #646cff;--vp-c-brand-light: #747bff;--vp-c-brand-lighter: #9499ff;--vp-c-brand-lightest: #bcc0ff;--vp-c-brand-dark: #535bf2;--vp-c-brand-darker: #454ce1;--vp-c-brand-dimm: rgba(100, 108, 255, .08)}:root{--vp-button-brand-border: var(--vp-c-brand-light);--vp-button-brand-bg: var(--vp-c-brand);--vp-button-brand-text: #fff;--vp-button-brand-hover-border: var(--vp-c-brand-light);--vp-button-alt-hover-text: var(--vp-c-brand);--vp-button-brand-hover-bg: var(--vp-c-brand-lighter);--vp-button-brand-hover-border: var(--vp-c-brand-lighter);--vp-button-brand-active-border: var(--vp-c-brand-light);--vp-button-brand-active-text: var(--vp-c-text-dark-1);--vp-button-brand-active-bg: var(--vp-button-brand-bg)}:root{--vp-home-hero-name-color: transparent;--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe 30%, #41d1ff);--vp-home-hero-image-background-image: linear-gradient(-45deg, #bd34fe 50%, #47caff 50%);--vp-home-hero-image-filter: blur(40px)}@media (min-width: 640px){:root{--vp-home-hero-image-filter: blur(56px)}}@media (min-width: 960px){:root{--vp-home-hero-image-filter: blur(72px)}}:root{--vp-custom-block-tip-border: var(--vp-c-brand);--vp-custom-block-tip-text: var(--vp-c-brand-darker);--vp-custom-block-tip-bg: var(--vp-c-brand-dimm)}.dark{--vp-custom-block-tip-border: var(--vp-c-brand);--vp-custom-block-tip-text: var(--vp-c-brand-lightest);--vp-custom-block-tip-bg: var(--vp-c-brand-dimm)}.DocSearch{--docsearch-primary-color: var(--vp-c-brand) !important}.dark .vp-doc a,.dark .vp-doc a>code,.dark .VPNavBarMenuLink.VPNavBarMenuLink:hover,.dark .VPNavBarMenuLink.VPNavBarMenuLink.active,.dark .link.link:hover,.dark .link.link.active,.dark .edit-link-button.edit-link-button,.dark .pager-link .title{color:var(--vp-c-brand-lighter)}.dark .vp-doc a:hover,.dark .vp-doc a>code:hover{color:var(--vp-c-brand-lightest);opacity:1}.dark .vp-doc .custom-block a{transition:color .25s}*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:currentColor}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.absolute{position:absolute}.relative{position:relative}.bottom-0{bottom:0}.left-0{left:0}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.block{display:block}.flex{display:flex}.h-14{height:3.5rem}.h-8{height:2rem}.w-64{width:16rem}.flex-row{flex-direction:row}.items-start{align-items:flex-start}.justify-start{justify-content:flex-start}.rounded-lg{border-radius:.5rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-\[\#3451b2\]{--tw-text-opacity: 1;color:rgb(52 81 178 / var(--tw-text-opacity))}.text-\[\#ff4d4f\]{--tw-text-opacity: 1;color:rgb(255 77 79 / var(--tw-text-opacity))}@keyframes loading{2.04%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAQM0lEQVR4nO2de5CXVRnHP3sRFBUML6FugC6I5jqKkKiUrBMXDW1qpvGWJo33UmuyBBStBC856kxqiplGWmq30QlBbuV6Qy0JGW6iLIqudwXBS4Lsbn887LTB7vnd3uec877v85nZgT+W7zn83vf7e87lOc+pam9vxzCMrqkO3QHDiBkziGE4MIMYhgMziGE4MIMYhgMziGE4MIMYhgMziGE4MIMYhgMziGE4MIMYhgMziGE4MIMYhgMziGE4MIMYhgMziGE4MIMYhgMziGE4MIMYhgMziGE4MIMYhgMziGE4MIMYhgMziGE4MIMYhgMziGE4MIMYhgMziGE4qA3dgZzSE9gD2BP4DHgLeD9oj4wuMYPo0Qs4GGjY+rM/sB/QH/hcF7+/FngYmA4s89RHowBVdv1BYtQBjcAxwAjEHDVl6LQDvwMuAdYl1TmjPMwg5dMTMcTXtv4MSlj/ZWAc8FLCukYJmEFKoxZ5aU8Bvg70Vm7vbSQarVVux+gGM0hxDAbOAc4A+nlu+1lgJNDquV0DM4iLKmA8cCESNUJyLnBn4D7kEjPI9tQCpwKTgC8G7ksHa5A5jj0sz9hG4f+oBk4HXgDuIR5zgCwRfyl0J/KIGUQYCywB7gXqA/elOxpDdyCP5H2jsB64GVmmjR0t4w4HvoGsltUBOwHvACuAvwMPAh8ptR09eTVIT+BS4PKtf08DOyWsNxK4ETHGtgxAhnRnAh8AN2z93U8T7kP05HGINRxYBFxFeswBsDkhnSpgGvAkXZtjW3bb+vvPI59drsiTQWqAK4CnkTSQtPFyQjq3IZGzVIYAzwBTydHIIy/LvHXAfcBXQnekAo4FmirUuBj4ZeVdYSFwGjnY4c+DQUYDDwC7h+5IBbyJZAFvqUBjILAS2DGJDgHrEZPMSUgvSrI+xLoUmEu6zQHyrV+JOQAmk5w5QFL2Z23VrUpQNyqyGkF6AHcAEwL3IwlWAYdR2QrSTsC7wM6J9Gh77gXOJrmFhGjIYgTpg4T9CYH7kQQbgW9R+fLqSPTMAZLEOR/57DNF1gyyJ/AoMqFNO+uQHf4kThc2JKBRiGOAx5BnkBmyZJA6ZHVlaOiOJEATMAxJdU+C3RLSKcShyDJ6naf21MmKQeqQlyrpU30+2QTMBI5HIuArCWr7fM71yLPIhEmysOHTMayKNcmwMx8jSZHNwOvAq53+XIHeJPd1Jd3u6DDJUcjiQGpJu0H6APOIN3K8hExeHwcWA6uBtgD9+HeANuuRZ9MIbAjQfiKkeZm3B7LH0Ri4H51pR8zwAPAI8ew0VwOvAfsEaLsJOZGZyiXgtM5BqoDfEI85XgQmIrvdjUhtq1jMARK1fh2o7caAbVdMWiPIZOCa0J1A5j43AbMJM3Qqhd7Iacm9A7U/Ebg+UNtlk0aDjEWGLyGj3wLkzPqigH0oh5CfXRsy1FoQoO2ySZtB+iPnEroq3emDxcg34fxA7SfBBOAuwphkHbJX0hKg7bJI0xykFrifMOb4ELgIOTCUZnMAzEDKGYVYfu2LPMNySrIGIU0GuRI4OkC7s5BUjVuJf55RLHOAQ5D/m2++THkHtoKQliHWcOQ0m89vns3AD4HbPbbpmyrgPOS8eS+P7W5BNhGf89hmWaTBIDsiG10HeWxzDXAS6ZuEl8tBSPWSIR7bXI7km23y2GbJpGGINQm/5pgLHE5+zAFy0vAIZIXLFwcjB9qiJvYIcgCwFNk198GdwAXkt1B0DfArZNjlg02IUZo9tVcysUeQW/BnjqlIkei8mgPk/34+UubHBz2Rwn3REnMEOR7ZofbBZOA6T22lhUnAtZ7aGockNkZHrAapRTYEfdSvmoosIRvbMw0/S7LLkA3E6JbRYx1inY4fc0zHzOFiCpIUqk0DcuVEdMQYQWqRpDrtA1CzkWvU8jznKIYaZENR+xKhZuBAKi9vlCgxRpBvo2+OVcg3lpmjMK3IZ5VU6dPuqCfCKBJbBKlCxqOal9d8guzMr1RsI4sMQ4piaK4qLkdSYKJ5KWOLIOPRv9npEswc5bAISb3R5GAiu6slNoNcpKw/C6m4aJTH7ejvtmu/AyUR0xBrEHJ0VavO6zokZeUdJf280B8ZBu+q2MYBSMGL4MQUQc5Ftwjy5Zg5kuBV4DLlNs5W1i+aWCJIDVJ1Q+u89PPIJDO6jaiUUo2kqmtVsXwLKTwXfJUxlggyGt1iAhdi5kiSNuTosRb9gDGK+kUTi0FOVtSeBTylqJ9X5qNbgOEkRe2iiWGItQPwNnpnzY9CTiMayTMMvVOBG4G9CHygKoYIMgo9c8zDzKHJIqQ2mAa9kSsVghKDQTQ3hm5Q1DaEmxS1xytqF0UMQ6zl6OyeNwODiShtIaNUI5XpNc6zr0aeYTBCR5A69FJL7sbM4YM25LPWYBCB7xkJbRCte8tbgd8qaRvbcx96X0aNSrpFkVWDPIbcLW74oQX5zDUIOlEPbZAjlXRnKuka3XO/ku4RSrpFEXKS3gO5kkzjlqtBRFxKJqMMINl7FTtoRZZ8P1HQLkjICNKAjjlWYuYIwVp0MnBr8FOfoEtCGuQQJV2tsbBRmLlKurk0yAFKukndLW6UzpNKug1KugUJaZADlXTNIOHQuk13fyXdgoQ0yEAFzY1IxRIjDM3ARwq6uTSIxg7pKuzcR0jagCUKul9Q0CyKUAbpiaQyJ80aBU2jNDRWEPvir4j5/xHKILsr6ZpBwvOGku6eSrpOQhlE6/zHWiVdo3heVdLNlUH6Kum+p6RrFI9WDpxmmaFuCWUQrfGkxgqKURofKOnuoqTrJJRBtL4NzCDh0Uru66mk6yR0Nm/SfBy6AwYbQncgSbJmEMNIlKwZpE/oDhjsHLoDSRLKIFq1jjRr+xrFoTWZ/lBJ10kog2hNpndT0jWKR8sgm5V0nYQyiNa3gWZ9X6M49lDSXaek6ySUQd5V0u2vpGsUzwAl3fVKuk6yZpB9lHSN4tFKTX9fSddJKINsRidkat+OaxRGwyDvEKiIdchl3tcUNA8le0vXaaIanRKkLQqaRRHyZdJITd8FiyIhGYKU6EmaVxQ0iyJrBgE4XEnXKMwIJd0XlHQLEtIgy5R0v6ykaxRGyyAvKukWJKRBlivpjlPSNQozSkl3qZJuQUKWHu2FVCGpUdAeiJ0u9E09cp9H0mxB8rtytZMOUmtVa5hlUcQ/JyrpLiWQOSD8kug/lXRPVdI1ukfLIEHvmAxtkMeVdEcR+GainLE3evOPJ5R0iyK0QZqUdKuA05S0je35LjpzSQhskBgu8XwJuc8jaVYh9x9apUVdqpBnqLFBu4KAld0hfAQBmKWkOwTdK6YNYTR62Qta1ykUTZYNAvAjRW1D+LGi9mxF7aKIYYjVE8nW1MjhARgOLFLSzjtHAk8raa8HPg98pqRfFDFEkE3AXxX1r1PUzjtTFLUfIrA5IA6DAPxJUXs0MEZRP6+MBMYr6v9RUbtoYhhigSwRtgD9lPQXI0MtW9FKhmpk2HqYkv6byJ0grUr6RRNLBGkF7lHUHwp8T1E/b5yLnjkAfk8E5oB4IgjAYHTTmj9ELoPUKs+fF/ZCrtrWqtDfjlzwqpH4WDKxRBCQzSbNde9dgemK+nmgCrgbPXMAzCcSc0BcBgG4RVn/eOAC5TayzHnoTsxB/x0oiZiGWCDfUEvRTS/YDByN7Y2UykHAc8g5Hi1WIMPgaF7K2CJIO/AL5TZ6AH9G7xq4LNIbeBBdcwBcT0TmgPgiCEAtckhfuzrJXGS4EMVqScTUAH9DP6+tGTgQOUEYDbFFEJAP6Kce2hmHTdqL4Vb8JH1OIzJzQJwRBMS4S5DxqDZXo5sykWauAq7w0M5yZF8lOoPEGEFAdrwv8dTW5cAkT22liUn4MQfAT4jQHBCvQQDm4S/d+Vpgqqe20sBVyGfig3nAI57aKplYh1gd1CPh19cNp3cA3ye/E/ca4HbgHE/tbQYOIWBhuELEHEFAVjau9tjeecBM9M6mxEwf5PCaL3OARKlozQHxRxCQ6LEIv2eTVwHfRHKO8sAw5MiB1t0eXbESqaP8qcc2Syb2CAJyoGoCfidxQ5Bd4/PJ/sWgFwAL8WuOVuA7RG4OSIdBQF5W35PoXsh4fCZy9DNr9AceBm5Dsgt8cg3yTKMnDUOsDmqQOlohqre/i3zjzQnQdtJUI2djrkEynH2zECkyF+Wy7rakySAg1RKXoJtu3R1twFnAjABtJ8UYJNdtaKD21yMbgqk5k5OWIVYHLcDJhDk6Ww3cBYwN0HalDEPOWcwjnDnagFNIkTkgfQYBWABMDtR2NRJB0rAMXA2cAPwDGe+PDtsdpiAGTRVpG2J1ZgZwZqC2fwb8PFDbhahD6hKfhRxdjYF7kWeVupctzQbpgaSsNwZo+w2k6kYsVVIGIKclTwGOIa6l6SYkczrYHR+VkGaDgOz+NqFbYaM7jgD+FaDdaqTY91DEDGOQghcx8jzyBbYhcD/KpjZ0BypkAzJpfhr/1z8fjp5BeiCV6fsD+3b6sx65C35npXaTZDXybFJrDki/QUD2KBqRSOLTJPsqaB6H7FGMxV+CpgbNwLHIs0k1aVzF6ooWxCTNHttMcv4xEHgUSfs+kXSbYzXyLFoC9yMRsmIQkAdyFLKR6IMPEtIZgSRjNiakF5LFSMWYTJgDsmUQkJA+Cr27DzuTxA29DcjeQIjMgKR5lIwMqzqTNYOATArHIGvvWnwMPFWhxo7AX0jHpmMhZiDzp1RPyLsiiwYBWXM/E7gMnb2KPwD/qVDjB0hafZppAyYil3imcp+jEGnfBymG44D7SK5Q3KdIlcFXKtCoRXKS9k6iQ4F4H9mYXBC6I5pkNYJ0Zg6yqbYwIb2JVGYOkJT9NJvjCWRzNtPmgHwYBGAtMnmfRmUFGaYDNyfQn5EJaIRgC3AlMhnPzEqVi7wYBOThXoFcPLmqjH9/NcldwrNfQjo+WY4so08lR1Vf8mSQDp5DhgdTKG4v41lkSDSF5LJRfR9xrYRNSNQYRkqOySZJHibpLnZBqpd8Fcl92gtZnWpBjPEQOi/FHcg1ZrEzG7gYvxkKUZGFXKxK+AjZL9HcM+mK2F+4ZUjp19QdcEqaPA6xYqApdAe6oRk4A8kYzr05wIZYoahCkvp81qJysQK4DriflFQb8YVFkDC0Iy9kaOYi2cMNyDDTzLENFkHCUYPkc43w3O5biBnuRG4WNhyYQcIyAHgG6KfczkbkGrUHkKhhkaJIzCDhGYy8tElvHq5GlmlnI4sCmxLWzwVmkDjoC9yIZCCXU5GkFdnpfhY5C9NETlJBtDGDxEUDUlH+BGT4tS3rkSzgl4E1yH7FMsQcn3jqY64wg8TL7sjcZAfklN572DDJO2YQw3Bg+yCG4cAMYhgOzCCG4cAMYhgOzCCG4cAMYhgOzCCG4cAMYhgOzCCG4cAMYhgOzCCG4cAMYhgOzCCG4cAMYhgOzCCG4cAMYhgOzCCG4cAMYhgOzCCG4cAMYhgOzCCG4cAMYhgOzCCG4cAMYhgOzCCG4cAMYhgOzCCG4cAMYhgO/gsTCA6Q6lB0DgAAAABJRU5ErkJggg==)}4.08%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAPNklEQVR4nO3debBXZR3H8TfcC4gaKIKiIgoKioqZhoh7pSKamo2Z5lKM1bg0OjUtWGlqm2MrOYZajrllY5bbiKBmiLtmoyziAi64hIqChgsCl/74XpSE+9xzf7/zPc9zzvm8Zhinmfieh3t/n99zznm2bitXrkRE1q577AaIpEwBEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRgNbYDaipnkD/9j99gXWB3h/5/7wDLAUWAW8AC4H3CmyjoIB46gWMBHYARgDDgS2BwVgwGvE68BLwDDAXmAM8DMxstrGydt10/EFuBgH7tP/ZDQtHUV9AzwCTgAuBdwu6Zi0oII3rAewHHAwcBGwXtTXmWeBY4P7YDakKBaRrWoD9gS8BhwIbxm3OWi0DjgRuit2QKlBAstkG+DpwPDAwcluyWAZ8Crg3dkPKTgHpWDdgHHA6cED7/y6T+cD2wNuxG1JmGgdZUyvwFezN0C3AgZQvHGBvy06L3YiyUw/yoe7ACcAPga0jtyUv/wG2AFbEbkhZqQcx44DHgMuoTjgANgVGxW5EmdU9IMOAW4HJwI6R2+JldOwGlFldA9ILOAeYhY1hVNmg2A0oszpONdkd+CM2BaQOesRuQJnVqQdpBc4G7qE+4QCb6CgNqksPMhj4CzAmdkMieDx2A8qsDq95DwKuAjaK3ZAI2rCR/9diN6Ssqn6LNQF7Q1XHcIANdCocTahqD9ITuBQ4LnZDItsNWy8iDariM0hf4AZsKnqdTUThaFrVepABwB3ATrEbEtkdwCHA+7EbUnZV6kEGAdOo1lSRRlwLjMc3HNsCe2BLiFuBJcBTwHRs7XxlVCUgCge8CPwAuMKpfis2mfObdDwtpw2YAvyMiqxFqcIt1gBs8G947IZk8C4wG3gC23zhJWABH75pWgIsB9YD1m//b39sHGcosBX2rb0xtijqBeAR4HrgRvx6jWHANcCuXfg7f8DW0pR6jXzZA9IXuBvbICFF84B/YL3bv7GdSMo29Xw01its0MDffRAYC7yZa4sKVOaA9MRm4n46dkNWsxK7tbgGG4N4Pm5zmjYE+BfQr4ka07EVmaV8YVDmgFxJOuMczwAXAVcDL0duS166YR/uvXKodRX2/FK6D1tZH9K/QxrhuB24AOst2iK3JW+Hk084wH5Xc7CH91IpYw8yFps+EnOazG3Y0twqD8Tdie2Mkpc24LPYbXFplC0gg4BHiTe36mHgu9hDd5VtiI1n5P0ltAjYGdtxpRTKNFmxFZuyHiMcbwHfwBZbTYtw/aLtgs9nY0PsBUZpbu3LFJAzgD0jXPcGbFvRC6nec0ZHNnOsvQe2cK0UyhKQXYGzCr7mUuBk4Ahs+5w6aXGuP4GS7LZShoD0AC6n2G75CewXeFGB10yJ98BeC/aavpfzdZpWhoB8j2LXkE/GRo/rfObGnAKusS1225y01N9iDcM+qEV90/we266zbNNBPLyA/5ZB72NLE550vk7DUu9BfkVx4fgRcCoKxyqXFXCNnsBvC7hOw1LuQcZik+SKcAZwXkHXKov+2OTKvgVc62ASHUBMtQfpDvyioGudi8KxNgspbnf4X5LoZzHJRgFHU8wU9knYrZWs3RXY+I+37bHDiZKT4i1WK/aa1Xt14GTgMPTM0ZkWbDHWIc7XmYcNyC53vk6XpNiDfBH/cDwJHIPCkcUK7ExG7zdNW7dfJymp9SDdsNe6nuMe72D7Rc12vEYVbY8tnurteI052Hr3ZKb0pNaDjMN/UPA0FI5GPA582/kaI0jsOIrUAuL91uRGbMdFacwk7NnNU1LnKqZ0izUM21vJy1vYzievOF6jDgZit0KNbOKQ1XDgacf6maXUg3zVuf6ZKBx5WICtpvR0onP9zFLpQVqwjc8GOtWfgU2ZT+oVYom1YA/sOzvVX4Cdzhv995VKD3IAfuEAWw0Y/YddISvwfVYYCOzvWD+zVAJylGPtqdjmcpKvu7GfrZcvONbOLIVbrF7Aq0Afp/pjgAecatfd7sD9TrXfwiZMLnOqn0kKPci++IVjKgqHpwfw60X6APs41c4shYAc7Fj71461xUx0rH2oY+1MUrjFehrYxqHus+11k5m2UFHdsXUjQxxqP4lNYIwmdg8yCJ9wAFyMwlGENuASp9rbAps71c4kdkD2c6q7nGKWjIq5DL8vo/2c6mYSOyBeD2HTsTdjUoxXgPucasfYLPADsQMy2qnuDU51pWPXOdXd3aluJjEf0nsD/8VnF7/B2LY1UpzB+BwYtAI7im6pQ+1OxexBdsQnHDNQOGKYj8+qwxZssVYUMQPitTCqEqerlpTXlJ6PO9XtVBUDco9TXencXU51o42FxAyI18YMXnODpHNeP/thTnU7FTMgQx1qLsZG0CWOZ/E5F91jlD6TmAEZ7FBzrkNNya4N29Msb9FG02MFpCd2HFfePH450jWPO9TcGPvMFC5WQAY41VUPEt9zTnW9PjNBVQvIAqe6kp3X78DjjqNTsQKyvlPdRU51JbvXnOp6bjPUIQVE8rbQqe46TnWDYgXE6x/7hlNdyc5rQ3CvL9Wg2LN586bd2uNbHLsBeapaQERyVbWAFHGenoR5zNCOJlZAljjVbXWqK9n1c6r7nlPdoFgB8frH9neqK9l5jVd4fakGxQqI14NclNFW+T8KSA68xis8N8CWbLx+B14DkEGxAuL1j93Kqa5k57XPWa0C8j4+2/JEW7ssH/BY/bcI+8wULuZr3pccam5H9V5dl41HDzLfoWYmMT9MHiv/ehNx9ZkwBJ9Jhc841MwkZkC8Dmkc41RXOuf1s5/nVLdTMQPitfpvX6e60rm9nOpGO9c+ZkAec6q7t1Nd6ZzXPrrRAhJz69FewNv4zN3ZkogPdjW1BT4/8xXAx/DZLaVTMXuQpdg2oR6OcKorHfucU93ZRAoHxH8l6nV+4JFOdaVjXgF50KluJrED4rWP7h7AJk61ZU0b43vWSzSxAzLNqW53YLxTbVnTePyWGkxzqptJCod4PoGdRZc3HeJZDM9DPOcScV9eiN+DAExxqjsEGOtUWz60P36zF25xqptZCgG52bH26Y61xXzLsfZkx9qZpHCL1QPbS6mPU/0x+L0tq7vd8Tvy4C3s4T/K0WurpNCDLMPvAEiAsx1r193ZjrX/RuRwQBoBAfirY+2xaPqJh73xfca71rF2ZincYoG9InwBv+WajwKfRBvL5aUVeATYyan+AmAQCfy+UulBlgOXO9bfGTjJsX7dnIJfOACuIIFwQDo9CNj77qcc6y8GRqAjEpq1CfZ78nqpAjAcv/VCXZJKDwL2A5nqWH8D4FKgm+M16uBifMMxlUTCAWkFBOB3zvUPBk52vkaVnQgc7nwN789Al6R0iwUW2FnYrZCXd7EHdo+z9KpsB+AhYF3Ha8wGRgLJfChT60HagPOcr9Eb+Du+twlV0wcbl/AMB8DPSSgckF4PAvYK8Qlga+fr3ILdLiTxtiRhLcBN2O2pp3nYtk3Lna/TJan1IGA/oB8XcJ1DgIkFXKfsLsA/HABnkVg4IM0eBCy4Mylmp8QvY+/dZU3nYB9cbzOxsarkliakGhCAcRQzm/NNbN2I1+GTZTUBeyYowkH4vuJvWIq3WKvcit9akdX1BU4r4DplchbFheNmEg0HpN2DgK00nAH0dL7Oi9i2NXXXgo1DnFLQ9ZZir3WTGRj8qJR7EIAnKeabbBA+u5KXSR/sbVVR4QD4CQmHA9LvQcA2mHsMn3Xrq/s8cL3zNVI1EpteXuSXxGzgE9h6oGSl3oOAdcPH4z9eUdcTck8CHqbYcCzH3h4mHQ4oR0DAfoHeI+x1GzDcFOsxJ2G9dJHOxdaTJK8sAQFb3nmfY/2XHWunpDtwKjZbwWs3xJB7Ke4NWdPK8AyyusHY6sC8T1Jtw46Q9jpcNBX7AecDoyJd/3VsQPDFSNfvsjL1IGC7hx9L/iOud1HtcIzCxhr+SbxwtGG/u9KEA8oXELABxDNzrpnUGoScdAcOBW7DpqkfGLc5TCDhAcGOlO0Wa5Vu2Pyp43KodQ+28XIpfxBrsRn2TX0SMDRyW1a5CnsTWTplDQjY6PrtNLer+BvY4imPA0WLtCU2O/kY7JSnlJYV34nNq4tyjHOzyhwQsLGLqcDoBv7uYmySXNTzJxrQgk2u3AV76P4M/mtnGjUT2z/rzdgNaVTZAwK2QnAi8LUu/J1HsG9br2kOPbHFWEcAu2LzvHoArwLPA89hRxvPx2YRvw0saf9vK7B+e50B2F5hm7f/2Q5b+trbqd15ego71PO12A1pRhUCssqewPexXqGjlw+zgN9gzy9ei3NOAH6Kze+qq3lY71aqN1ZrU6WArNIfey4Zjn0TL8e+te/DJj96WRe4DDjK8RplUJlwQDUDEkNPbI37/rEbEtkM7GdQ6tuq1ZVxHCRF56NwTMN67sqEA9SD5GEUNhBXZ1dhm8qV8lVuiHqQ5uU9ql8mK4EzsEHAyoUD1IM0awC2GXYdv2hex2YyFLFvQDReR/fWxb7UMxz3A0dj4ziVVsdfbp6K2LcrJSuwvbL2oQbhAPUgzeoXuwEFmo09iJdtak5T1IM0J/k11Tl4H1siuys1CweoB2lWJUaLA6Zgm+olvTWPJ/UgzanqN+osbMPqcdQ4HKDXvM1qwU7n3TR2Q3IyD9vM7QoS3Eg6BvUgzVmBHQ9QdrOB8dh0+j+hcHxAPUjz1sOOcxscuyFdtBJbkTkRW+evD8JaKCD52BPbMaRH7IZksAC4ErgEmBu5LclTQPJzGHAdaYZkEXbMwJ+BO6jfLpINU0DyNQa4GhgSuyHYzolTsEOIplGPMZvcKSD5641t7XkyxW27sxzbIOEhYHr7n6qP0RRCAfE1ElsvMgLbiWQotvnCRg3WW4jNgXoe2xRhDvYGaia2C77kTAGJYx1s7Xw/bJ/hXqx5Bvm7wDvYljkL2/9Ucs1FyhQQkQANFIoEKCAiAQqISIACIhKggIgEKCAiAQqISIACIhKggIgEKCAiAQqISIACIhKggIgEKCAiAQqISIACIhKggIgEKCAiAQqISIACIhKggIgEKCAiAQqISIACIhKggIgEKCAiAQqISIACIhLwP+Yq5x0YvZqZAAAAAElFTkSuQmCC)}6.12%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAOcUlEQVR4nO3debBXZR3H8fddAFcgE0TAQFMBQXNnwlJyV5RxGUtLzXIZl9FyDM3KSScbbax0dNJx1BY1rbHUARdwKbUgtbRUQC5giLmCmiyCbJf++EJs9z73t5zveZ7zO5/XDNNMY9/zSPdzz3POeZ7v07R69WpEpGPNsQcgkjIFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAlpjD6CkugGfXvOnN9Ad6LXRP7MAWAl8uN6fZTmOUVBAPPUARgC7A7sCQ4BBwA5A3xprzgPeAl4HZq758zIwFfikvuFKR5p0/EFmdgAOAg4ARgG7kd8voFXAdOBvwBTgz8AbOV27oSkgtesGjAaOBY7A7hIpmQ1MAsYDT6PpWU0UkOp0Aw4BvgaMBXrGHU7FFmJBuRd4HFgRdzjFoYBUZghwFnA6tT8/pGI+cCdwOzAj8liSp4B0rhkYA3wLu2s0ooeBccCrsQeSKgVkU63AqcB3sTtHo1sGXAjcFnsgKVJA1mnGplBXYq9jy2Yc8NPYg0iNAmLGANcBw2IPJLKxwITYg0hJ2QMyFLgeODL2QBLxLrALsDj2QFJR1rVYPYAfAi+hcKyvH3B+7EGkpIx3kH2Bu7C7h2xqJuV4OVGRMt1BWrEH8GdROEJ2pZwvKTpUlsWKA4HfYeukpGufA+bGHkQKynAHORz4FwpHNbaJPYBUNHpAvgM8iu27EKlao06xugO3AmdEHkdRvRV7AKloxLdYvYD7gMNiD6TA+gDvxx5EChrtDtIHmAjsHXsgBTYFheP/GikgA7ENQrvFHkjB3Rx7AClplClWf+AZ4LOxB1Jw/wT2w7bwCo1xB+mD3TmKEI6l2N6LqcDbwDvAe1gzhtXYTr+Pga2w3YpbY11PdgQGr/nPYWv+e4+xnYbCsYGiB2Rr7JljROyBdKINeGrNn+exbiTtddZsxr527wPsj33nqXdlwFLgeGBanXUaTpGnWN2xHXGHxh7IetqxMNwPPEh+r0sHY4suT8B2P1bzfWsOcArwXPbDKr4iB+QO4JuxB7HGbOAW4G5suhRTf6ypxGlYT67OzANuxJb7L8lhXIVU1IBcQhq73x4CbsI6haT4FzkCa000FHuuWY5N86YAf8U6N0pAEQNyKPZQHnOZzCRsP4mmJQ2uaAEZCLyIvbmK4QXgIuw3sJRAkRYrtmBL1mOE4yPgAuytkcJRIkV6zfs94ixZn4A1jYv98C0RFGWKtS+2E7Alx2t+gr0MuIU0H8AlB0UISA9s7j88x2u2ASeiD2elV4RnkMvJNxyPAiNROIT07yC7YOuWuud0vduA89B6pHr1Bo4DDsS+wWyBTVn/DUwGHsDWoiUv9YBMxM7eyMO12N1KatcbuAI4FwtFZ1Zhqw6+T+K7F1MOyBjsS3UergCuzulajWok8AfsW1WlFgJfx9atJSnVgLRgXQ/zePb4CdbJXWo3GngE2LyG/207tm7sniwHlJVUA3IG8KscrnMHcDZ6jVuPQdhGq0/VUWMF9rzybCYjylCKAWnFTj7y3gD1GHA0eiCv10PYdLheM7DVx0ktoEzxNe+p+IdjNvBlFI56HUA24QB723V6RrUyk1pAmvB/HlgGnAQscL5OGZyZcb1xJPYzmdRgsN9G3p3FL8FakUr9sj46YihwTMY165JaQC52rv8g8Avna5TFtsD2DnUvcqhZs5Qe0ofgeyzxQuw31DuO1yiTEcArTrWHkcgR1SndQc5xrn85CkeW6u3OEuL9s1CxVO4grdiSg75O9Z8DRuH7f2rZ9MI2knl4D/siH/2Vbyp3kMPxCwfApSgcWVsAvOZUezvyW4MXlEpATnGsPQlrSyrZ81wrd7Jj7YqlMMXqhnUT7+lUf29sKYRkbzi2HcHDQmxWscypfkVSuIMcjF84HkXh8DQNW7LjoSe2CDKqFAKS1VKFjtzoWFvMDY61j3asXZEUplhtWDPmrM3EvntE/xdscE3AdHyO1p6N7SqNJvYdZBA+4QB1I8nLauB2p9o7U90GrMzFDsgXneq2Y03mJB/34vfLaLRT3Yo0akCeAt51qi2behv7O/fg9TNSkdgB2c+p7n1OdaVzv3equ79T3YrEfEjfHHvX7dH+dCCJd8toQIOwoxWytgo7SWypQ+0uxbyDjMAnHG0oHDHMBWY51G3BVvdGETMgXsc1P+lUV7rm9dFwD6e6XYoZEK/fCk871ZWueR0N4fGNpSIxA7KzU11tp43nRae6Xj8rXYoZkMEONZdgX18ljln4HAi6k0PNisQMyGccak5F+z5iWoXPNtwBDjUrEisgrfgcpTbToaZUZ45Dzb7YtojcxQqI1zmDer0b3xtOdT13nHYqVkC2dar7plNdqZxXQHo71Q2KFZCtnOpq/VV8Xp1jejnVDWq0gKidaHyfONXN65SxDcQKyJZOdVc41ZXKebzmhZJNsbx8HHsA0lh38UYLSPRGY+KyADWaRgtIlAc52YDX9DmKWAHxalkZOllV8uH1QS/K9DlWQJY71d3Mqa5UzusuvtipblCsgHg9yHmcVyHV6edUt1QB8ZpieSyAlOp4tel536luUKyAzHOqq4DE57Xydr5T3aBYAVmBT0h2dKgp1fFoBDifSK/wY77mfduh5u7YJn+JoxlrxpE1rwWQXYoZEI/DV7Ygci/XktsZn1ftrzvUrEjMgHhtjd3bqa50bU+nutG2UccMiNcppqOc6krXDnKq+6pT3S7FDMjLTnUPd6orXTvEqe50p7pdit16dBE+D9WDsU5/kp8B+OzoXImdNlW61qNL8TuI/kinutK5Y53qvkKkcED81bzPO9X9ilNd6dxJTnX/7lS3IrED8henuqOB/k61ZVP98DvoxutnpCKxA/KUU90mfM9elw2djN/PUtSApHCI5yx8eq/OwDrIR/8XbHBN2N+110GsQxzqViz2HQTgEae6Q9HDeh6OwO8g1klOdSvWyAEB+LZjbTEXOdZ+2LF2RVKYYvXAVvb2dKo/ApjmVLvs9sLvyIOFWAfOqK2cUriDLAPGO9Y/27F22V3jWHs8CfQ5SyEg4Hum+TGOtcvsQOz5w8u9jrUrlsIUC6yX0pvAdk71e9NgDc0ia8aOWxvpVH8etnQlep+zVO4gK4F7HOtHO4ClQZ2LXzgA7iaBcEA6dxCw17Jey5p3x06fkvptj3338HqpAvaz0OZYv2Kp3EHA/tK9jnDWsQjZuRnfcPyJRMIBaQUE4EaHmu8QqWVMA7oAOM75Gtc7169KagF5iOx3Gk7MuF5Z7Qn8zPkabSTwcXB9qQWkHbgu45p3ZFyvjHoB92EfdT1dS2Jr51J6SF+rFdskMzSDWg+j7yD1asGWA3lvZX4N+/88ibdXa6V2BwH7C/oG9X9F/S82Z5baNQG3ks8+/6tJLByQZkAAngXOwKZctVgKnID2pdfrGuDMHK4zDbgrh+tULdWAgH04PBFbtFaNN4Ev4bcZqyx+AFyW07UuA1bldK2qpBwQgAexTU+/oeu/wCXAz7GPgs85j6vRXQP8KKdrTSKxN1frS/EhvTP9geOBA4CdsMNylmCvhZ/BwuR1rEJZtAC3kN8K6OXYdoRZOV2vakUKiPjqha2gPSrHa14FXJnj9aqmgAjAcOCP5Lv/exqwD7YfKFmpP4OIrybgfOAf5BuOVdhbyqTDAQ12prVUpS9wO34dEUOuwkKZPE2xyqcZ28/xY2wjWd4mY13gk3ytuzEFpFxGYSum94l0/fnY+S0eTa5d6BmkHEZiq5onEy8c7cBXKVA4QM8glWoFvoD9Bh4MdMfO7Z6BfbFPcbdiE3AYcCFpLNi8FHgi9iCqpSlW2BbAxVhztL6Bf+4VbC3Rb/E5nLQafYFTgfPwaelai1+Sz5quzCkgnRuJfTir5mjpdmzb8P3YlOb17IfVoQHYTr8TsC7rKU2dnwDGYF/NC0cB6dgRwAPYKVj1mAE8hp2D8gLWjLnWFcprNWPTvP2xMIwmcoPngBex8S2KPI6aKSCbGo4d2lJvODqyCOvcMge7u8zB1o8twlYtLwa2BLphzxB9sV5h22Nr0UYAw5zGlrWpwMHYm6vCUkA21IKFY6/YAym417DOi7Gfx+qW0lw1BSejcNRrOjatKnw4QAHZ2PmxB1Bwa585CvWtI0RTrHW2peDz5cgexw7ybKgeyLqDrKOpVe1+jX2MbKhwgAKyPjW4rl47MA7rQlPI7xxd0VITqdUH2Nqqx2IPxJMCss6HsQdQIJOxN34N8zDeGU2x1nkp9gAKYBW22Wk0JQgH6C3WxtrwO9K46GYAp1GQnYBZ0R1kQ2p0vanlWOeRPSlZOEB3kI1thfVo6hd7IImYiC33z/pIisLQHWRDi4FzYg8iAa9i3zWOosThAAWkIxOwd/tlNBf7pjGChNuB5klTrM6dDdyE/6ExKWjDDq9J5nTZVCggYcOwE6/GxB6IkyeBG7ADcurdyNWQFJDKDAXOAk4H+kQeS73mAXdiTeOSOU02VQpIdbphnUJOAcbiexxylhYC47GmEk9S/+ldpaGA1K4H1iFwLLaHPZUOImvNxM7emIC1JlIoaqCAZOcz2MlWo4DPYwf/tOR07ZXYTr4p2Dqpp4H/5HTthqaA+NkMe126B7Z8ZVesG8kAwj22QuZhP/hzseeHmVhPrqkUoFN6ESkgcfQAtlnvTyt2gM36FmDLPD7ClpZ/gKZJuVNARAL0JV0kQAERCVBARAIUEJEABUQkQAERCVBARAIUEJEABUQkQAERCVBARAIUEJEABUQkQAERCVBARAIUEJEABUQkQAERCVBARAIUEJEABUQkQAERCVBARAIUEJEABUQkQAERCVBARAIUEJGA/wGoO9WRqPBNhgAAAABJRU5ErkJggg==)}8.16%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAOF0lEQVR4nO3de5Cf0x3H8fcmu6tKhURQIlpEiohbqlH3S6Kson9kqDJtelFaOnQGMWgN6tqpGepS01KDDtWpSyVt4l631J2wCbooqYoSkhYlt/7x3ZVNbM4+v98+3+ec53k+r5nfrHE5z8naz57nOec839OybNkyRKRvg2J3QCRlCohIgAIiEqCAiAQoICIBCohIgAIiEqCAiAQoICIBCohIgAIiEqCAiAQoICIBCohIgAIiEqCAiAQoICIBCohIgAIiEqCAiAQoICIBCohIgAIiEqCAiAQoICIBCohIgAIiEqCAiAS0xu5AjQ0D1u3+tHX/vcHAZ7r/+r/AO8C7vb4uLbiPtaeA+FkD2AoY0/11s+7PBlg4BjfR5jygq9fnJeBZYBaweOBdlpW16PiD3IwE9gZ2AXYCtqa5EDTjf8ATwCPdn/uBuQVdu9IUkOatBuwJdAD7A5tH7c0nzQFmAH8C7gMWxe1OOSkgjWkF9gMOAw4C1orbncwWALcANwB3obBkpoBkMwr4PnAEsH7kvgzUPOAa4Crg+ch9SZ4Csmot2O3TccDEyH3xcgdwCTAVzZD1SQH5pFbgG8BJ2OxTHcwGzgd+h26/VqCALDcIOBI4HZuOraOXgLOA69C0MaCA9JgI/BzYJnZHEtEJnAhMi92R2OoekM2Ai4EDYnckUTOwZ7AXYncklrruxWrDbqWeQ+EImYit0p+JrfvUTh1HkHHYFKdupxrTCXwHmBm7I0Wq0wgyGDgN+x+scDRuK+BBbORtidyXwtRlBNkYm8LcNXZHKuIK4JjYnShCHUaQfbGNfApHfo7GZrkqr+ojyInAedTjF0HRFmG3qpXerlLVH5x24LfABVT3zxhbG3BG7E54q+IIMgS4GdgrdkdqYDG2eXN+7I54qdpv1+HAvSgcRWkFJsTuhKcqBWQE8DCwXeyO1My2sTvgqSoBGYGNHHXdZBjThrE74KkKRRuGA3dTjnAsxGZ95mA7Z+cBbwNvAR9hlUzAJhnWAdbu/roxy4s+bEFabzJW+j2SsgdkCBaOUbE7sgpPY6vPDwAPAf/Ioc0WYDRWGGI8sA8WmljeiHhtd2WexWoHpmOFE1KxGLgHuLX7U1RlkU2xTZeHYJVVitwKchhwY4HXK1RZA9ICXIu9+ZeCLuBKbO3lzbhdYQT2fZmMjTSeFmF1vio7zVvWgEwBzo3dCeBObKX+biC1b2QLNqqcgN2GebgB+LpT20koY0D2B24n7gzcNOzV1LJs/d4BOBv73uXlI6xq5Is5tpmcsk3zjsTel47V71nYImQH5QkH2GbNA7Dnk8dyanMKFQ8HlCsgrdjD4NAI114A/BD7TXxvhOvn5R5s9usYbMq5WVcAF+XSo8SVKSCnYdOaRZuB1dm9jGpU+liG/YBvie1Za8QS4BRq8i4IlOcZZDy2llBUMWiA97Ht8peT3gN4njqw56nt+/n3pmHheMa9RwkpQ0BWw+6hiyzi9jK2plCnH4btseeUrYH1sNHydeBxrAD2q/G6Fk8ZAnIm9h50Ue4GJlHhuX3JLvWAjMIOiGkv6HpXAMdi99oiyT+kX0Jx4TgDe/hUOORjKW9W7MDO4ijCKdiKuMgKUr3FGgw8ha3UejsfW/QS+YRUb7GOpJhwXIWNHiJ9SnEEacVeKPJ+AWoqcDB65pCAFEeQI/APRxc2SikcEpTaCNKCTet6Lgq+D+xMvRYBpUmpjSAd+K+YH4vCIRmlFpDjnNufBlztfA2pkJRusUbhe5LRfGAs8E/Ha0jFpDSCfM+5/ZNQOKRBqYwgg7EKIBs4tf8kdrJUpWs4Sf5SGUEm4BcOgONROKQJqQRkkmPbtwJ/dWxfKiyFW6w2rATnOk7t70y5CixIQlLYzbsHfuG4E4UjJUOxqjBbAcOw0kFzgb8Bj5LgbXAKATnQse0LHNuW7MZhRTcOZNV1BeYCl2LvAL1XUL/6lcIt1mzgCw7tdmFrK9H/gDXWjr1nczzZ6wW/AhyOnfUSXeyH9OH4hAPg1ygcMa2O7Zg+gcaKaX8OuA84yKFPDYsdEK+jmZdihaQlnquxI7ib0QbchE2wRBU7ILs5tXsfFT+3InFHAocOsI12rMzs6gPvTvNiB8RrBLnFqV3pXzvws5za2pTIVRxjPqS3Y+9meFRL3ISaFjpLwCTg9zm21wVsnmN7DYk5gozGJxyzUThiOiTn9jYDtsm5zcxiBsRr9up+p3Ylm3EObX7Roc1MYgZka6d2H3BqV7LZ2KHNLR3azKSKI8hDTu1KNm0ObUY7xThmQDz+0B9g549LPB6HmH7eoc1MYgbE4/2POWj1PLY8zoJf2QiHNjOJGZDhDm12OrQpjXnZoc2hRFowjBWQYfjcq2p6Nz6PgACs5dRuUKyAeIweAP9yaley8/olpYDkwOMBURrzjlO7tQqI12Gc/3ZqV7IbyPHSIbUKiJfkXtmsIa+ADHFqNyhWQNZwavd9p3Yluw9idyBPsQLiMYMFVgRA4vI6U3KRU7tBVbvFivpyjQDwaad2oxRyiBWQBU7tRnmQkxV4TcBEESsglZrpkBWs69RulNPAqhYQrwJ0kt16Tu1GmcKvWkBGOrUr2X3WqV0FJAfRtkXLxzx+SS0C3nZot1+xAvIBduJT3hSQ+DzOmIy2QyLmNO9chzY3cWhTsmvB503RaDXOYgbEY1u01wOiZLMpPmtRLzq0mUnMgHj8oaOstsrHvuzU7hyndvsVMyCzHdp8zaFNyc6rUuZzTu32K2ZAHnVo8zGHNiW73Z3areUIMgsrK5kn1eSNZyQ+D+hLgOcd2s0k9mbFy3Js6zXswE6JI++Soz2eIOIu7dgBuZz86lidira7x+QVkKiVMmMH5APgCAb+g30jcO3AuyNN2gA7jNVD1FrLsQMCdhbdJJqfor0TmJxfd6QJ38LvZ6nWI0iP27DfQK808N8sAy4COqjYa54l0wJ816ntOUQuxJFKQMBGkjHAKYS3oSzBHsZ3An6Mnjti2xc7w8PDdKd2M0vhGOi+DMLOhPgSVpe1HdvN2Qncg89GR2nOHTR/WGd/JmC30NGkGhAph/H4nWf+DrA+kbcPpXSLJeUzxbHtm0lgb50CIs3aHTjYsf2bHNvOTLdY0oxB2L637Z3afwN79oxSqKE3jSDSjMn4hQNs0Td6OEAjiDRuI+AZ7FAbL1sQ8SWp3jSCSKOuxDccM0gkHKCASGMmAwc4X+MS5/YbolssyWostubhVXsXbCF4DAkdxKoRRLJYB/gjvuEAuJCEwgEaQaR/g7G9bx3O1+nC3khc7HydhmgEkZAW7KHcOxwAZ5NYOEAjiISdB5xcwHWeBbYjkbWP3jSCyKpMoZhw9FwruXCAAiJ9+ylwbkHXmg5MLehaDdMtlvQ2GPglcHRB1/sIm9ZNZmFwZa2xOyDJGIrtoN27wGueT8LhgHqPICOBrwI7AhtivyzexMpcTgOejNe1wo3Fiu4VeXxEJ7AD8GGB12xYHQMyFru/7m/LxJPA6SR8f5yDFuAYbIHOexGwtyVYHd+ZBV6zKXV7SJ+CVerLsp9oe+B2bAV5Q89ORbIR8BfgUooNB9iaR/LhgHqNIJfT/MPnQmzK81ckthWiCa3AUcA5wJAI158J7EaCi4J9qUtATgB+kUM7jwEnYZVVymhP4GJgm0jXn4+NzK9Gun7D6hCQUdhKbXuObf4ZOA27XSuD8djzlPdW9ZClwIHY96406vAMcib5hgNgf+BxrGZTB/awm5oWYB+sbtXDxA0HWHHxUoUDqj+CDMUKALQ5X+d54GrgenwOJ23Eelit3KPwq3jYqOuBIynh81vVA3IocEOB11uGPZ/cjK2l5HW0Q39GYCV4Dgb2Iq0F4HuB/ShpidiqB+QcrNZvLC8Ad2EzN49gI00e3/BNsAMzdwV2AbbNoU0Pz2J9XBC7I82qekCuIq2jERZioenq/ryGldh8t/trz2/ZNbHnpnWBYVgJzk2xF4pGA2sV2uvmvIiFN2p19oFKaSj2kNokxFrAuO5PlXVhe7pKHQ5I7wcob6/H7kANdWHrLbEnK3JR9YA8HbsDNfMUsDMVCQdU/xlkKDCP6t9KpuAe4GuU+IG8L1UfQeYDf4jdiRq4BvgKFQsHVH8EAZv1mYX/YmEdLcV2SF8YuyNeqj6CgK09nBq7ExX0FrYAWNlwQD1GkB4D2e4uK3oAOBxbx6m0OowgPX4A/AS7LZDmLMF2Be9JDcIB9RpBeowHfgNsFbsjJTML+Db2Tkxt1GkE6TETKxZwFiXdQFewD7GRd0dqFg6o5wjS2xbYeRQTY3ckUdOAH2Gr47VUxxGktxewmZgOrAyNmFks/77UNhyggPSYhm0Zn0xx73CkqAt72Wo77Ci02qv7LVZf2rApzJOBLSP3pSidwAXYm3+lqDZSFAVk1QZhtxjHARMi98XLDOwZbColfB22CApINqOxKc5vYi8vldk84DqsxlfSdXFToIA0pg2rFHIYcAhxCq81YyFwG/Z+/nR0G5WZAtK8NmAPrAD2ROx12JT8HSuzMxUrnJB0kehUKSD5GYGV1Nyp+7MD8KmCrr0Eq0r/CPAgcDclql6YMgXETytW4nMMVnBhs16fZp5jlgBvY3W+eoo+dGKVQzqB9wbeZVmZAhLHIGBt7Pzxnq9rdv+z/7D8vL5F2Lbyt7BwSMEUEJEAraSLBCggIgEKiEiAAiISoICIBCggIgEKiEiAAiISoICIBCggIgEKiEiAAiISoICIBCggIgEKiEiAAiISoICIBCggIgEKiEiAAiISoICIBCggIgEKiEiAAiISoICIBCggIgEKiEiAAiIS8H9UZtFm3Zb9FwAAAABJRU5ErkJggg==)}10.2%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAOJ0lEQVR4nO3debCXVR3H8fddgKwUSiVQlFRUREnDJcFQlhQwyzRnzBRXbMrSPzQDl8ZyTLF1Wswsc1+mKXdkccVEMUWFLquCFupobnnBXOPSH9/fjTtwOfyW5zznnOf5vGZ+g86F85z7u/fzO+c5z1ma1q5di4h0rzl0BURipoCIOCggIg4KiIiDAiLioICIOCggIg4KiIiDAiLioICIOCggIg4KiIiDAiLioICIOCggIg4KiIiDAiLioICIOCggIg4KiIiDAiLioICIOCggIg4KiIiDAiLioICIOCggIg4KiIhDa+gKlFRPoA/Qu/LqA3y8y9dXAR3AGuD1Li/tNJ4zBcSfXsAewFBgxy6vnYC+dZTXgYXkZWAZsLTLn0uAdxuvsqyvSccfZGZbYBRwADACC0dLTtf+L/AU8CgwF3gEeCmnaxeaAlK/HsBI4MvAIcBuYauzgSXANOAO4DGsuyY1UkBq0wJ8ATgaOBK7f0jBG8BdwPXAbKy7JlVQQKozCJgEnAD0C1yXRv0TuBa4Bng+bFXip4BsXDMwHjgDGBe4Lr7MBH4K3B+6IrFSQDbUCnwdmEJ89xW+PAn8BLgFu+GXCgVknWZgIvB9bCi2jFYAPwRuRPcpgALSaQLW1RgSuiKRWAScBcwKXZHQyh6QXYBfY8O0sqEZ2D3Y8tAVCaWsc7F6YV2JNhQOlwnAQuAC7D0rnTK2IPsBVwG7h65IYhYBJwLzAtcjV2VqQVqxVmMuCkc9dseeyF9AflNogitLCzIQuBkYHroiBfEocAywMnRFfCtDCzIem8incGRnBPaeFvUB6v8VPSBTgOnAJ0NXpIC2xN7byaEr4lNRu1g9sRvxY0NXpCRuAE4BPghdkawVMSC9gduxtRmSnweBI4D20BXJUtECsjU28W5o6IqUVBswFngtdEWyUqSADMA+xQaFrkjJLQdGAy+GrkgWinKTPgBbCKRwhDcI+1kMCFyPTBShBemLjcunMAN3FbAYeK7yWgn8G3gL67t/WPl7LcAWwFaVV1/s+xsM7Fr5WuxWYOvz/xW6Io1IPSC9gYeAPUNXZCOeAe7Fnt7Pq/x/Fm/4Dthznc9XXrHecz2GrdtPdo1JygHpia2IGx26Il2sxe6DbsOeETyX03UHAocBh2M3yTF1nc8FLgldiXqlHJBrgeNDV6JiGXA1ttAo9M3pttjCr5Ow6fyhtQPbAatDV6QeqQZkMjA1dCWwIeWfY+smYnsjm7BpNmcTvpU9FbgycB3qElNTXK2DgYsD12E6sDe2BdB04gsHWJ1mAGOAfbHuaCiHBrx2Q1JrQQYACwg3t+oJ4HvYMGaKxgI/BoblfN3nsW1Xk5NSC9KCTVkPEY524JvA50g3HGBdwn2B75DvPcFWOV4rUykF5HxsSDNvt2Pb/1xBnF2pWnUAl2EbVEzL6ZrJbpKeShdrH+xZQp5v9HvA6SR6c1mD07CBBp9rzv+BPbtJTgotSE9sm8w8w7EMW7te9HAA/BbYH3jW4zWe8li2VykEZAr5riG/B7vXaMvxmqHNxz4QHvBUfsgRtIbE3sXaGftFzWvLmSuBb5Hw1IgG9cTuTyZlWGY7sD02Dy05sbcgvyC/cFyKPdAqazjAVgSeir0XWbmERMMBcbcgE7CHcHm4FOvKyTpTaXy9+VzgINbNUk5OrAFpxvrFecxSVTg2bgr1TzRcChxI4qsLY+1iHUc+4bgahcNlKnY/8l6N/+5e7JlV0uGAOFuQZmxR0a6er3MPNkU82eY/RzsBPwKOwr2r4nLgIuA6ivFQNcqAHAX82fM1lmMPHwu1A0cO+mMfKvth8+I2A17FPtDux07XLdS5IjEG5Cngsx7Lfx97MDbf4zWkIGK7BxmP33CAnXehcEhVYgvIGZ7Lnw783vM1pEBi6mINxNYNNHkqfzU2gzX0klhJSEwtyEn4CwfY0lOFQ2oSSwvSjB1w72uzsb9j9zaFGmER/2JpQQ7B7058Z6JwSB1iCchRHsu+GxujF6lZDF2sFuBlbGd2H4ZjO/yJ1CyGFmQE/sIxG4VDGhBDQI7wWHayW15KHGLoYi3Fz8TEFdiKxODfoKQrdAvSD3+zdq9C4ZAGhQ6Ir32uOrCAiDQkdEAO9FTuQ8ArnsqWEilqQG7zVK6UTMib9J7AO7hXqNVrIHa8mUhDQrYgg/ETjsUoHJKRkAEZ4qnchz2VKyVUxID81VO5UkIhA7KHp3LneipXSihkQHxMb/8PttW+SCZCBqSnhzKXoKfnkqGQAfGxJ1WZjiyQHIQMyBIPZS7wUKaUWMiA+DisxdcBMFJSIZ+kfxR4gexOrV0A7JVRWSJA2BbkHeBnGZZ3YYZlSfZ6Y6d3TceWWK+tvN7AWv7JwDbBarcRoRdM9QIeBz7TYDl3AF9pvDriQStwFnAesPkm/u6H2KGi5wNve65XVUIHBOx44MeAvnX++4XASOCtzGokWdkauJXa1/08CxyK7cIfVOjp7mDbjR5AfccQzwHGoHDEqA/WdapnUdzO2FEKwc9WjyEgYJ8Uw4BfUt2BNquxk6FGU4BTjArqGhqbTtQXuJ38DnHtVgxdrPVtA0wExgF7sm6U6xXgaeAu4CZ0+E3MjgRuyais84CLMyqrZjEGRNI3H/twy8KbwHbYqGfuYuliSXEMJbtwgPUgDsuwvJooIJK1MYmUWRUFRLKWZevRabCHMquigEjWfJxv38dDmVVRQCRLTcBuHsr9wEOZVVFAJEufBj7modxgR+cpIJKl4Z7KXeip3E1SQCRLvnbKXOyp3E1SQCRLIz2VGywgepIuWdkeO6k4a2uwxXVBbtTVgkhWDvdU7kI0iiUF4OsovaA7ZSogkoV+wEGeylZAJHkn4+93aY6ncquim3RpVBO2GnQnD2UvI+A8LFALIo07GD/hANsBJSgFRBp1jseygx+lpy6WNGJ//B038RrQH3sOEoxaEGnE+R7LvpPA4QAFROo3Fviix/L/4rHsqqmLJfVoxnaYaXRHzI15ETupuMNT+VVTCyL1OBV/4QD4IxGEA9SCSO0GYLNrN7XPbr3WYjsq+pj4WDO1IFKrK/AXDoCZRBIOUECkNt/ANpX26Veey6+JulhSrb2wXfh97pX7NLZHczRaQ1fAg2Zst/ixwBBsE+R3sZGRx4Fp2AEuUr3e2LCr742kg+3BuzFFakGagOOxh1eDHH9vDfbDPg9YkUO9UtcD+1A5xPN1lmEfaFGMXnUqyj3IlsAsbMt9VzgAWoCjsZVqp/itViFcgf9wgLUeUYUDitGCbI0tqql3WvQ5wNTsqlMoU7GzA31rw+5xogtI6i1ID+x8wkbWDFyCAtKdvMJB5TrRhQPSD8iZZLNZ2WQUkq7yDMfdwIycrlWzlLtYWwArsRGWrFwJfJuAu2gE1gpcDkzK6XrvY5td13M+ZS5SbkGOJttwgP1izCDgbuIB9cY+zfMKB9iNebThgLQDMt5TuWOw5yV7eSo/RkOBv5HPaFWnRSTQrU05ID6fuO6MPTU+zeM1YjEJ+0DYNcdr/hc4kQS6sikHpJ/n8nsBl2Gn6g7wfK0Q+mNrvv8AfCTna18EzMv5mnVJ+SZ9FX5nlXa1GntecjmRDkfWoAmbdHgp2d/DVWMOMIoIltNWI+UW5PUcr7U58BvgCWyOV6pGYfcavyNMON4EjiGRcEDaAZkf4JrDgPuwka59Aly/XsOwEaoHgX0D1aED+BoBT4uqR8oBCbmp2HisNXkAmIB1W2LThK3duA94Ev/rODblXODewHWoWcr3IJsDLxCmq7C+Z4CrgeuBlwLXZQBwLHAS+Y5MuVwHnBC6EvVIOSBgN84xrSHoAO7H5odNI7+loztiLcQRwGjiatEexFrc6Id0u5N6QFqBh7Ed/mLUho3azMF2IHw+gzKbgF2we6Dh2N64u2RQrg8LsGMR2kNXpF6pBwTgU8Aj+NtAOUursIVBS7HFWq9io3GvV77WObrTA+s69gE+gR1vtmPlNQSbhxa7FcAI7HtMVhECAtbvnk0aISmDFdiQclIjVt1JeRSrqxexH8jywPUQ+xmMogDhgOIEBOwHMgLr90sYbdjPoBDhgGIFBGzL/JHYyInkazb23r8WuB6ZKlpAwEZMxgM3hK5IidwIjCPh0aqNKWJAwMbcJwJTSH9yYczWYs+ijiPR5xybUpRRLJdx2CfclqErUjBvYk/sZ4auiE9lCAjYc4SbsRtIadxcbFZuNJtM+1LULtb6VgIHAj8goanWEeoALsTey8KHA8rTgnS1D7YD4+6B65GaRcDJ2PLc0ihLC9LVPGBvrDV5P2xVkvAB1mrsTcnCAeVsQboahJ1HMSF0RSJ1D3A6Np2/lMrYgnS1HJsmPh7rQohZjL0v4yhxOEAB6TQLO5TyeMp9JMIKbDueoUS8HWieyt7F6k4r8FXgbKzfXQZLsE3cbsL2rJIKBcRtLPBd/O3iGNos7B5sJppx0C0FpDo7YF2PE7AD7lP2CnAttlG3lgdsggJSm2ZsrcNE4EukM32lHbgV+BO2y4kellZJAalfC7YW/nDgMGC3sNXZwBJsmPZObN3+h2GrkyYFJDvbYqfrDsfmfA0jv1OE12BnLj6Krc+fTfjthwpBAfFnM6xVGYztT9X5Z39gK+obYn8VG4p9rsurDQuHZgV4oICE0YSFpPPVggWm624lbwNvYfcP7ZX/LuSai5gpICIOepIu4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIw/8AVr7ws4NFHfAAAAAASUVORK5CYII=)}12.24%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAOB0lEQVR4nO3debBmRXkH4OfOwDBGtrALBIkghn1PSBAhqESRIpgSShMjqIFgpYIQgyjRuMSqABo1/mNKFB0tSgImLEJYRBYRC4MsgywCokhA2csJGNlmJn+8d2pYhvbe756lz/e9T9WtqWHmdvd8l9/pPt19+kwtX75cSmnV5vXdgJRqlgFJqSADklJBBiSlggxISgUZkJQKMiApFWRAUirIgKRUkAFJqSADklJBBiSlggxISgUZkJQKMiApFWRAUirIgKRUkAFJqSADklJBBiSlggxISgUZkJQKMiApFWRAUirIgKRUkAFJqSADklJBBiSlgtX6bsAE2wAbYwHWmf5va2E+npj++uX0r4/hATzTfTMnWwakPatjG2yPHbAdNsem2GT6z2djKX6Be3EP7sYPsRg/wtNNNDo911S+/qAxG2MfvGb61x10dwF6GrfiGlwx/XV/R3WPtQzI6Obj1Xgz3oBX9ducF7gFl+McEZilvbZmoDIgszNfhOHPcLC4jxiCh3EezsK35XBsxjIgM/MKvBPvxst6bstcPYAv4Qv4Wc9tqV4G5MVN4Y04Dq+d/v04WY6L8HmcP/379DwZkBdaDW/BB7Bzz23pymKchDOxrOe2VCUDstI8vB3/iK16bktfbsc/42syKMiArLA//gW79N2QSizGsWL2a6JN+laTbfBNMbOT4VhpZzFFfDa27rktvZrUgKyGD+ImHNRzW2p2iFhP+QcTuutiEodYu+A07Np3QwbmOrxLXFQmxiT1IPPxMfxAhmMUu4uQfER8lhNhUnqQLfB1/FHfDRkT38XbxMbJsTYJPcjrcb0MR5NejRvxur4b0rZxD8j7xWrx+n03ZAytj4txfN8NadO4DrEWiL1Gh/fdkAmxCEfhqb4b0rRxDMg6+IYJ6P4rc6nYorOk74Y0adwCsiG+ZXL2UNXmRhyAh/puSFPG6R5kc3xHhqNPu+BK8bMYC+PSg2wu9g1N6ibD2tyF/YzBNPA4BGRDXI1X9t2QGfgVbpv+um/660ExJFmOx8XJJWthIdYUz7r/jrgIbI0dp/+8dndibwMfbg09IOuITXW1rozfgqvEsOMa8QTfXD/wKWyJPbCvuFJvP8cy23ID/tiAb9yHHJAFuFBsVa/FM1YelHAOft5RvRuLwyMOFaeq1LSx8HLxHP8gp4CHHJCvqGed43acKh40erDntmwgPpejxHb+GizCEX03YhRDDcjxOKXvRoiV5FNwWd8NWYUpMfw6AX/Sb1MQ7ajhZzYrQwzIAWJo1ecU9XliZ/D1PbZhNvbEh8RRRX1ZJg7BuKTHNsza0AKyuViM6mtv1XX4O7HeMkT74jP6m9R4VKxTDWb6d0gLhfNxhn7CsUSM6fc03HAQs2l74K/1M7O0nvgZ1jSJUDSkgBwv5tW7dq6YRj3VeJwdtUxs5Nwe/9VD/XuL4d4gDGWItROuFVO7XXlSnOzxbx3W2Yej8Vms0WGdS0VQvt9hnSMZQkBWF+Hoco/VHThMHH8zCXYRO6C73KpzK3YTF6JqDWGIdaJuw3EZ/sDkhIOY+NhDt9PV24mfbdVq70G2FPuWFnZU32l4j4Gu+jag6wfNnhB76Kqd1aq9B/m07sJxsji9fVLDQfzb3yk+iy4sFBekatXcg7xed4tKJ4vDqtNKJ4nV77bdqZ4tMS9Qa0DmiffvbddBXZ8y5gcPzMEpuvlsNsAjHdQza7UOsQ7TTTi+Kk4+Sat2gtho2LZqz/+tMSDzxCsI2nYJjjQei39tWS52ELQ91H1Jy+WPrMaAHIZtW67jp+JkwEm+IZ+pp/BW/KTFOh5tsew5qe0eZAo3a3d49YQ4ZfGGFusYRzuLpyKbnlVcLh4h/lXD5Taith5kH+3fe7xXhmMUi/G3LZR7rUrDQX0BeVPL5V8kNh2m0XxR8xscT2+4vEbVNsS6SHtPv/0SO4iTRNLoNhPvCFmvgbIeEq/YfryBslpRWw+ySYtlnyjD0YT78DcNlXWMisNBfQFpy41ij1Fqxhn43BzL+NfpcqpWW0DaOhHkGPEMQmrOseLx3VF8Csc12JbW1BaQG1so82JxeFtq1nLxfP6bcc8Mv+dn+FOxfaWqm98XU9tN+n7ioLEm/aGYv0/tWSAWEw8TU/VrP+vP/le8su0M/LuBLc7WFpApcQhbU+fsnieuWKlbG+G38Gs80HNb5qS2gBAvYTmrgXKWijezTtKTgalhtd2DEM9Gn9lAOR+X4UhzVGMPQnTP54uTwUdxOv7SQG4EU71q7EHg/3CQ2W9DWIZP4B0yHKkBtQaECMnbxXmyMxkqXYa98GERlJTmrNYh1qrsKfZp7Sjeh7FMvH/jejEcu6O/pqVxNaSApNS5modYKfUuA5JSQQYkpYIMSEoFGZCUCjIgKRVkQFIqyICkVJABSakgA5JSQQYkpYIMSEoFGZCUCjIgKRVkQFIqyICkVJABSakgA5JSQQYkpYIMSEoFGZCUCjIgKRVkQFIqyICkVJABSakgA5JSQQYkpYLV+m5AGlvbiFdY7IZNxcX4AfxQvFj12v6aNnN5eHVq2p44Cfv/hr+3WLyq4putt2gOMiCpKfPwMZxodkP303GUeB9MdTIgqQlT+Br+YsTvv1wMx6oLSd6kpyZ82OjhIN5F+eWG2tKo7EHSXO2M6zC/gbIOFW85rsY4BGRjvER0zw/23JZJdK54j2QT7sSrVPQC1iEOsRaIVzxfgCW4Hz8VU4hLxPsK3zH991K79tJcOOCV2LfB8uZsaAE5WLys86s4EGs/78/XxpuwSFyNDum0dZPnoy2UeWALZY5sKAGZwidFd/7yGX7PFjgbn57+/tSsfcRbh5u2SwtljmwoK+mfwXtH/N7jxA3kqN+fXmg+PtdS2Ru1VO5IhtCDvNXc/+c+Zrqc1IyjVHalb0vts1hr4ifYsIGyHsVOuK+BsibZZrgZ67ZU/sV4Q0tlz1rtPci7NBMOWA9faKisSTWFL2ovHMQerWrUHpC5rM6uyoH4q4bLnCRHav/qfkHL5c9KzUOsl+Ixzc9APSHm76u6Ug3ArvgeFrZYx63YQS4UzshW2pmeXYj/xG+3UPa4Wg//od1wwD+pKBzUHZD1Wiz7FThDrrbPxAJ8Hb/bcj234cyW65i1mgPy65bLP0DctOci4oubwqnis2rbx7Gsg3pmpeaA/LiDOg7HyR3UM1SniH1tbbtVhb0HdQfkEbGfqm3Hi0dE03OdhL/vqK5jVdh7UHdA4KyO6jlB/A+Rw61wkvhMunA2vtVRXbNW8zQvbC56kbZnT1ZYJLZRPNVRfbVZgM+LBdouPIFtcXdH9c1a7T3IvWIc3JXDcaF2V4prta74t3cVDqKnurvD+mat9h4E1sD12K7DOu/CW3Bjh3X2aWdxk7xNh3UuFkcEPd1hnbNWew8CT4qr2tIO69wK1+DoDuvsy9H4vm7D8ZSYHas6HAwjIMQP8BMd17mGGI9fIHawjpvNcI74N67Rcd0fwU0d1zmSIQyxVlgNV2DvHupegveLnaxVTkfOwpTYsPlJrNND/VeL5867HBGMbEgBIWa1Fmt3G0rJDeIJxSt7qn+uXiMeQd69p/ofEQ9a3dtT/bM2lCHWCvfibfq7iu8qerFzxQ3mUOwm2nyl/sKxDH9uQOFgeAGBS/DBnttwMP4bF4lTAWtdYNxftPE6zR7PM4oPiJ/doAxtiPVsXxHrFjW4Q2x8XISHe27LRuLcsCPFIWw1WIQj+m7EKIYckAVWXsFr8Qy+I7bInC0Os+vCpuIMsEPE51HTaTWX4Y0GujthyAEhZmEuF/cGNbpF3LNciR+IVeO5fuBT4mywvcRs0D7Yfo5ltuUGEdglfTdkVEMPCHGow9Xi2MraPSbesPRjcbP6P6KXeVzsS3pMXP3XFEHYUAyZNpv+2nb666VdN3wEd4op+Yf6bshcjENAiOnfK8QKeOrfXdjPwGasVmWIs1ircq/4gdzWczsSPzIm4WB8AkL8QPY1ORsMa7RYLEaORTgYr4AQ4939cGnP7ZhEl4oL1KDvOZ5v3AJCzJiseAVC6sYi8ZkPdrbqxYxjQIg59yPEBsOhby6s2TLxaO4RBrrO8ZuMyyxWyevEGVjr992QMfOI2BdX7fPkTRjXHuTZLhU7SL/bd0PGyPfEBsixDgeTERBWTgN/VGwHSaNZKg54ew3u6bktnZiEIdbz7YTT9Lfte6huEI8+T9Q0+qT0IM92k9jH9CFjemPZsCdxIn7fhIWDyexBnm1r8ehpvg131c7H+8R2/ok06QFZYT98Vhx/k6KneJ/Yqj7RJnGItSpXiFmZI3B7ry3p113iIbTdZTiQPciqzMNh4hHRSelRFotTDr8hZ/meIwPy4qZwEN4j3stX63Pno1qOb4t30F+osjc71SIDMjMvF4davxsb99yWufoFvoQvi1dsp4IMyOysjtfiUHFKyAb9NmfGHsZ54t2MFxnIoW01yICMbr6Y/VpxUEJtz4XfLsJwtthmk6EYQQakOZuIwOwnFiK3Ez1OF57BzbhKnKpyle5OVBlrGZD2rI7fEzNhO2JLbCGen3+Z6IFm42ncj5+LvWW3ilDcIhbyqj8pfYgyIP2YL3qctcTbs9ad/nWhGAo9Nv33lojtMA/o/0C6iZQBSakgV9JTKsiApFSQAUmpIAOSUkEGJKWCDEhKBRmQlAoyICkVZEBSKsiApFSQAUmpIAOSUkEGJKWCDEhKBRmQlAoyICkVZEBSKsiApFSQAUmpIAOSUkEGJKWCDEhKBRmQlAoyICkVZEBSKsiApFSQAUmpIAOSUsH/AwvR5eemNoVKAAAAAElFTkSuQmCC)}14.29%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAANpUlEQVR4nO3debRe0x3G8e8dCCWsZCWGoKFEYo4ppaZMhEaTdqmhKKmiVKkaiopVq6qkg6VaNVZRtKVTIkiIUIQQVEIGiQgyGGJJK1FJ3OT2j9+9K5dc233f9+yz9z7n+ayVlT9ys/fv3rxP9jn77L1PXXNzMyLSvvrQBYjETAERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBGHxtAFlFQjsCnQFVgP2ADoDDS0/PkyoAlYDbwLLG75JTlTQPzpBOwA7ATsAvQGtgC2wsJRV2F7TVhIFgFzgJeBmcCsll8rMqlaPqZOrz/ITA/gQGB/4AAsGA3Ov5Gdj4DngSeBycATWJCkRgpI9RqwMAwHDgd6hS1nLTOAscB9wCRgVdhy0qSAVKYeGAwcj4WiS9hyOmwJcC9wO/AIdm8jHaCAdEwv4ETgBOweImULgD8Ct2H3MeKggLgNBs4FDg1diCfjgKuACYA+CO1QQNbWCBwDnA/sGriWvLwE/BK4E5stkxYKyBp1wJHAZcD2gWsJZS4wErgb3acACkirQ4BRQN/QhURiKhaUsaELCa3sAekJXAMMC11IpO4DzgTmhS4klLKuxVoXuBB7Eq1wfLqh2POUi7GVAaVTxhGkL3AH9qRbOm4WcBz2xL40yjSC1AMXAE+jcFSjD/azu4j8ltAEV5YRZCts1DgwdCEFMQk4FngjdCG+lSEgB2HTlpuELqRg3gWOwpauFFbRL7G+jz0lVjiy1w14CDg7dCE+FXUEWRe4ARgRuI6yuA04FVgZupCsFTEgnwP+DgwJXUjJjAeOAD4IXUiWihaQ7tjDrb1DF1JSU7BnJ4XZHlykgGwJTCS+jUtlMxsYhC2rT15RArIl8CiwbeA6xMwF+lOAkBQhIN2xefkURo6lwIvYRqWF2AfoHWzH3wrgw5av64wtu++GfX+bA1sDO2KHP2yQZ9FVmo1tSU76civ1gHTGDiiIdd/GVKy+x4GnyO7B2nbAPsB+rDkgIkZTsYez74cupFqpB+Qe4Ouhi2hjFfbcZTQwBhsl8tAT2yM/DNsFGdPzrfHYjXuSh0akHJDhwD9DF9FiFvB7bDnLW4Fr2Rw7VGIEdkkWg+uB00MXUY2UA/IssGfgGiZgW1UfJL493XXYaHIOceypPxfb/56UVAOyE7aPOpTx2KrWfwesoRK7Y1uJhwasYTVwMDYVn4yYrlUrMShQv88BA7D/kVMJB1ith2M39c8EqqEeuAvYLFD/VUk1IHlfW78PfA/4Iva8JVVPAvsC38GmlvO2KXZySjL7SVINSJ6rcx/Anj1cS6IzMZ+wGrgR+57uDdD/QGwLbxJSDciHn/0lmfTxXey6PfTMlA+LsWnhU8l/geElJHKCTKoBec1z+/OwB3HXEd/sVNZuwr7XuTn22QjcTAKv30g1ID5vNCcAewHTPPYRm5ewFdDjcuxzT+yMgKilOs27IfBmy+9ZuhU4hfIev9mA3Z+clFN/K7AJl1dz6q9iqY4gy7An11kahX0wyhoOsEmIk4Gf5dRfJ+xBa7RSHUHAVrnOwt7zV6srsQd/ssZl2PGjeRhEpA8QUx1BwGZhTqT2Q5ZHoXC05xLsZ5OHq4n0sxhlURUYi90zVBuSK7EjSKV9FwK35NDPLtgRQtFJ+RKrrcHYyRo9Ovj1S4GzsJtycVsXe1g60HM/M4Gdiey1C6mPIK0mYE+GRwLzHV/3HraitDcKR0etxE4recVzPzsQ4ShSlBGkrTpsh+Ee2IhSD7yNzfU/Q7lnqWrRF3vFtM9T3mdiK7Wj+VAWMSDiz2nY6gKfDiPfB5ZORbnEknxcD9zvuY8zPLdfEY0gUqktgOnAxp7ab8aOb4rirVYaQaRSC/E7NV6HraKOgkYQqUY99qap3Ty1vwg7DDD4h1MjiFRjNX5fe9CDSF7FrYBItR7FDq/wpY/HtjtMAZFaXOqx7S4e2+4wBURqMRl/o8hyT+1WRAGRWl3tqd3XPbVbEc1iSa3qsNPqszxdfzm2zyePwzmcNIJIrZqxI5GydD8RhAM0gkg2OmOXRFndWA8gkgP6NIJIFpaS3fbce4gkHKARRLJTB/wN+FoNbczDjlx6L5OKMqARRLLSjL2XpNql6vOAQ4goHKCASLb+h50ifzmVbUwbDfTD/67FiukSS3zZDvghcDSwUTt/3oS9eOgq4OEc66qIAiK+rYNtf+6FvbX3A+wkxSkk8HJPBUTEQfcgIg4KiIiDAiLioICIOCggIg4KiIiDAiLioICIOCggIg4KiIiDAiLioICIOCggIg4KiIiDAiLioICIOCggIg4KiIiDAiLi0Bi6gA7aCNgb+AKwAfAuMAd7DdhHAeuSgos9IIOAc7ADxdqr9X3gL8DPifBMJUlfrKeadANuBoZ38OubgFHAj4FVvoqS8okxINthB4ptU8XfHQccgZ3wJ1Kz2ALSFXiW6sLR6h9YSKL6xiRNsc1iXU9t4QA7Xfz0DGoRiWoE6Q88klFbS4Ce2HsrRKoW0whyZoZtdQFOyrA9KalYRpD1sfdCrJdhm3OA3uheRGoQywjSl2zDAXaa+JCM25SSiSUgPT21e7andqUkYglI1qNHqyHAPp7alhKIJSBLPLZ9qce2peBiCcgsj20PwaaQRSoWyyxWHbAA6OGp/anYa8BWe2pfCiqWEaQZuMtj+7sBp3psXwoqlhEEbInJXGw08eG/wE7AQk/tSwHFMoKAvUj+Po/tbwzc6LF9KaCYAgJwref2vwyc5rkPKZCYLrHALq+mAzt47GMF9mzkBY99FFkj0A/YGdgUm/hYhG1/nkbBlvbEFhCAY4A/ee7jFWyP+38891MkmwPnASOwfTvtmQ/cAPwaWJZPWX7FGJB64CX8jiIAE4HDgJWe+ymCEcA1QOcOfv0i4ERggq+C8hLbPQjYkP2THPoZCFyXQz+puwL4Ax0PB9jzrPEUYMtBjCMIWHBfAHbJoa9RwIU59JOiK4ELavj7q7GDN8ZmU07+Yg0I2P/wD+fU10+BS3LqKxVXkM1/HO8BfYDFGbSVuxgvsVpNxA5gyMNI4HL8PaRMSR02cmQ1qnYFLs6ordzFPIKAnaQ4A+iUU3+3YEtSynq2ViNwE3ZTnqVl2CxYcjNbMY8gAK8Cl+XY30nY9XKXHPuMRVfgAbIPB8CG2CmZyYk9IGA30c/l2N+hwBTsQVhZ7IqdRzbYYx/9PLbtTQoBaQJObvk9L9sCk4FTcuwzhDrsDLHJ1H4e2WfZ2nP7XqQQELAp3zwvtcBOkb8RGAN0z7nvPGyGLQ79HXaqjG959JG5VAICNss0MUC/XwFexm7eU/p5fZoG4Azsezosx37fybGvzKT0D74KOA54O0DfXbA1Rk8BXwrQf1b6A08Dv8XeuZKnGTn3l4mUAgLwFnAs4bbO9gMmYTNduweqoRq7YyffPwLsGaiGvB76Ziq1gIBdZp0fuIah2PLuB4CDifMBYx12YMVDWK0hD9F7DtvGkJzYHxS6XEc8m59mALcCdwBvhi2FzYDjgW9jSzxi8FVgdOgiqpFyQBqwWZiYjhddjS3xHoNdhr2eU79bAMOwhYGDsZ9NLP4KHBm6iGqlHBCwG83HsFNLYjQdeBy7b5lMdu9R/DywL3AAsD/xfv/TsPqSfQ1F6gEBe0bxBLB96EI64ANsenUG8Bp2ObYYe2tvE2s+SOtj68+6AJsAW2KjRG9sC0AlezNCmQPsR6KreFsVISBgH6BHsSfgEt5cbEp5QeA6apbiLFZ7FmD/ILMD1yE2cvSnAOGA4gQE7B9kf2yhoYQxBbusKkQ4oFgBAbveHYDth5Z8jcdGjqTvOT6paAEBuxEeBtwWupASuRX7mRfu/fRFDAjYUT4jgB9Q3t2BeWjC3uL1LQp6fFJRZrFcBgB3A91CF1Iw7wBHAf8KXYhPRR1B2mpdoDcpdCEF8hiwFwUPB5QjIABvAAcBPyLfnYlFsxI77WQAdsxo4ZXhEuuT9gDuJJ6FfKmYji2CLNWh32UZQdp6Hnsv+0hgeeBaUvAhcBH2H0upwgHlHEHa2gb4Dba/Q9Y2BjiL/FYlR6eMI0hb84DDsX3nUwPXEpMXsG0EwylxOEABaTUWu4T4BrbQrqxmA0djP4sHA9cShbJfYrWnETsc4jzKc3jcNOAXwJ/RLN/HKCCfrg7bnXcOdtpiEY0DfkUBXnTjiwLSMb2xNyZ9E9t7krL5wO3YWrU5gWuJngJSmXrsIdkJ2I19KodcL8Hus+7ARotQxyYlRwGpXgO292EoNhO2Y9hy1jIHC8VobEuyFm1WQQHJTg9sw9Y+2OmLewDr5NT3KtYcEPEEtlZqUU59F5oC4k8nbDlLH+yNvb2BXliQumOzZZVoxo5dnQ8sxA5/eBELxkzs/e+SMQUknO4tv7ph9zaN2ItmwEaEpdjmr+XYe/7eRlOwuVNARBz0JF3EQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBGH/wN/ftWisEI28QAAAABJRU5ErkJggg==)}16.33%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAANEElEQVR4nO3defDXRR3H8efvAAMxbzAUNdG876MU7/ugQ5s008wy7ZhxaiLLLNFwTDOnmcZmKnXMUZnMRrFJTS4VFY+EQFDAEBRFEvHCW65ff7x/v/gisr/vsfvZ/Xz29Zj5jc2o+3kbvNj97O5nt62rqwsR+XjtsQsQSZkCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDp2xC8hUB7BpzU8nMIA1fz3eBD4A3gdeBRYDK4otUxSQcPoAuwB7AzsA2wHbA9sCmzXRXhfwCrCw++dpYE7NX99ruWJZS5uuP/BmIHAkcBiwH7AH0LegZ68EZgCTgUeAh4EXC3p2pSkgzesADgFOBo4Cdo1bzlpmA/cAd2HBWR63nHJSQBrTARwNnAp8Htg8bjl1WwqMAW4CJgGr4pZTHgpIfbYDvgmcDWwVt5SWLQRGA9cB8yLXkjwFxO0Y4MfAsbELCaALG379DpgYuZZkKSBr6wS+ClyAvWjn4CngcuA2NPxagwKyWhtwGnAZNh2bo9nAKBSU/1NAzPHAFcBesQtJxAxsaDk+diGx5R6QDbCX1dNiF5KoMcAI4LnYhcSSc0A2AyYAe8YuJHEfYL3rFWS4lpJrQDqB+4GDYxdSIk9i09zTI9dRqFx3816AwtGoPYEngF+Q0R6+HHuQjbF9SuvHLqTEJmO7CRbFLiS0HHuQs1E4WjUMmIZtzqy0HAMyPHYBFTEQmwa+MHYhIeU4xHoLm94Vf24AvksFZ7lyC8gGWEDEv3HYe8nS2IX4lNsQqyN2ARV2LPAg5fkEoC659SBtwIfY57ASxlPYNzOLYxfiQ249SBf2DbeEsxs2DVz272aAjBZ8aown3qbEt7CAzgPmY+sIr3X/LGX1Dtq+QH9gI2AQMBgYAuyEHQSxYaFVN24o8ABwILAkbimtyW2IBfabbBY23ArtGexjpIeAqcCzWC/Wqm2w33zDsEMidvfQZghTgSOAt2MX0qwcAwJwC3BGgHZXYX9y3gncAbwU4BkfZwhwEnAKdoBESkPn8dja07LYhTQj14BsgW26G+SpvbnYWsCNwMue2mzWYCz83wY+E7mWHjcDZ8Uuohm5BgTgAGz4M6CFNiYCVwNj8TN08qkNOAH4IfZtfWwjgN/GLqJROQcEYF9sONTojMtY4CLg394rCuNzwKXAcRFrWIWtlZTqgIiUxqoxTMVecH+PrY/0ZhL2Unw85QkHwGNYzYcQ73uOduxb960jPb8pufcgtQZiWyUOx2a6BmCHRb8APArcTrlCsS7twHnYKSabRHj+g9gu4JURnt0wBSRfnwKuB06M8OyLsE94k6eAyDnANUC/Ap+5AlvHmVLgM5uigAjYe9jt2DUNRZmF7WhIeot87i/pYmZiM3pjC3zmLtjZW0lTDyK1OoA/AOcW9Lz3sc2N8wt6XsPUg0itldgM168Lel4/bIo9WepBZF0upLiZpmOwQ/ySo4CIyy+BkQU8Zxp2bV1yB2ZriCUul2BrJaHtDXytgOc0TD2I9KYD+Du2nT6kecCOJLbCrh5EerMSOBPb0h/SUOArgZ/RMPUgUq9dgH8R9lTKJ7HhVjK/KdWDSL1mAT8K/Iw9sV3HyVBApBHXYu8jIZ0fuP2GaIgljdoCmEO4k1W6gE8DCwK13xD1INKolwl7YHUbxW116ZV6EGlGO/A4trgXwmJgSxKY8lUPIs1Yhd3SFcog7MvO6BQQadYDwN0B209iTURDLGnF/tjaSAivYxMCUT+oUg8irXiCcLtwNyGBYZYCIq26KmDb0RcNNcSSVrVh+7SGBmh7JrBHgHbrph5EWtWFrbCHsDt2PFE0Coj4cDPhPnaKetW0AiI+/Beb9g3hwEDt1kUBEV/+Fqjd/QO1Wxe9pIsvWxNmg+Ey7PruKBfwqAcRX17ArpzzrS8Rr5hTQMSnUIuGIaaQ66KAiE+PBGq3f6B2e6WAiE9PBGo32i25Coj4NBe78z1Eu1EoIOLbJM/tvQE87bnNuikg4ttfPLf3VyJ+Wah1EPGtEzsiyMdlPCuAnYFnPbTVFPUg4tsK4Pue2rqKiOEABUTCmEDrp8JPxA7PjkoBkVAuA0Y1+e/eC3wB642iUkAkpEuwU+Hr3aP1HvBTYHj3/44u9Zf09YFtsP047wDPk8CfKtKwvsAZ2Cnxw4D1av5eF3Zo9e3An4AlhVfnkGJANge+A3wZO8y4rebvfQhMBm4BRhNph6e0pBPYFhiA/fotAN6NWZBLSgHpAEZg3XI9e28WYLMl94QsSvKWSkD6Y11sM6dYjCKB2Q6pphQC0onNWhzVQhsjsVkTEa9SCMjlwEUe2kn2KmEpr9gB2R6YjfUirZqLXROmWS7xJvY6yAj8hANs78+XPLUlAsQNSAdwmuc2T/fcnmQuZkB2BTb23OZhntuTzMUMiI/t0B+1aaB2JVMxA7JBoHajHjQm1RIzIKE2ox0UqF3JUMyAzAvU7tGB2pUMxVwH6Ysd59I3QNvbYCf9ibQkZg+yDJgeqO0TA7UrmYm9UBjqoLEkbkiV8osdkEcDtXs4kW8mkmqIHZD7ArXbDnw9UNuSkdibFQFmEOZ4+3nYomH0/0Apr9g9CMD4QO0ORVO+0qIUAnJvwLZ/ErBtyUAKQ6w+wMvAJoHaP4Bws2VScSn0IMsJdwEk6Ht1aUEKAYGwATkJm/YVaVgKQyywj6deAgYFan8K8FnCXXYvFZVKD7ISuD5g+/sB5wVsXyoqlR4EbIPhc6x5kqJPS4GdsAkBkbqk0oOAnZQYcsp3Q+CPAduXCkopIADXBG7/i2ioJQ1IaYgFNryahh1aHcq72NrIrIDPkIpIrQfpAq4M/Iz1gTuBjQI/RyogtR4EbMr3GWwvVUh3Y0OuaDeoSvpS60HAfsNeWsBzTkIv7dKLFHsQsOBOAfYu4Fm6PkHWKcUeBGzFu6iduCOBCwt6lpRMqgEBu8rgnwU96wrCTw5ICaU6xOqxHfAU0K+g510HfA+9uEu3lHsQgPkUe3PUudjsVqhjUaVkUu9BwD6omo5djlOUudgtuzMLfKYkKPUeBOyDqm9Q7M1ROwCPA+cU+ExJUBkCAjblO7LgZ/bDtuDfjc7YylYZhlg9OrBztA6N8OzXgZ8D11KNj672wYaQBwJbY9fgvQPMAR4AbgNeiVVcSsoUELBfzGmEO+ChN9OB84GHIz2/VYdiC6O93cT1ITajdzHwZuiiUla2gIDdpz6OuMPDsdh2mMci1tCIfYBfAcc1+O8txC5Gneq9opIoyztIrYnABZFrOA47V3gcdpJ8qK8gW9EGHI8tuE6l8XAAbIUNuQ7wV1a5lLEH6XET6Zy/+x/shX40sChyLVsAZwPfwt99jYuBvcjwc+UyB6QvcBdwTOxCaqzCerg7sNmvFwt67pbAKdhw6HDCjAxGA2cGaDdpZQ4I2Ir3/cC+sQtZh5nAJGAyNiRb4KHNNmB77L/5EOydbEcP7famC1usnVPAs5JR9oAAbI795gv9gZUPS7FPfedgvcsibPjyJnap6bLuf64dO2Ri0+6fwdi+tKHY/fKfLLTq1X5DZucdVyEgsPplsgwhKbNp2IxYNqoSELBTGScAu8UupMKWA+uR0Z0rZZzmXZfFwJHYhTwSRh9s6JeNKgUEYAm2WjwudiEVltW3MlULCNiL8HDghtiFVNDb3T/ZqGJAwMbK5wA/oxqbC1OR3UVEVQ1IjyuxhUTtTPXjrtgFFK1Ks1gug7Et3MNiF1Ji7wJDgDdiF1KkqvcgPRZhWzAuptgvE6vkcjILB+TTg9TaC7iRsAdkV83DwBFk+IdLLj1IrenA/thpih9ErqUMngROJsNwQJ4BAZvlGoVtvhsTuZaU3YptiHw1diGx5BqQHs9h28SPRSvwtaYDJwCnk9m6x0flHpAe47GDsk8HZkeuJaZnsf8P9iHsdXilkeNLem/agVOxU0xy2fg4A9vKfiuZvmusiwLidhTwA2zrSorfnbdqHHA11oPKx1BA6jMUO7f3DOzbkzJbiE1z/xk7+1gcFJDGtGNnSp2FTX2WZev3EuAf2G6CCWS2I7cVCkjz+mBbV4ZjR//sHLectTyNHSAxBngIhaIpCog/Q4CDgYOw4OyBHZdahGXYi/YU7JCI+9AGTS8UkHD6Azthi5E7Y4ctbNX9M5DmXvpfBZ7HpmPnY9c0TMMOgljecsWyFgUkjk7sG/rNsFPkP8Ga97avwA6TXgG8VvOjYVLBFBARB62kizgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4vA/yly9fVHkLdMAAAAASUVORK5CYII=)}18.37%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAMwUlEQVR4nO3de4weVRnH8e+23UIp0gICAi3XtkBbwSpFJNRyCReBgBBRUDASETUYgyA30XgJNyFYRFFQFMNFURAEuYlSICDWopTGtpRyLyCUCm1RKNDurn88u7i74On7zjvPPDPz/j5J0z/YPHNI+ttzZs6cZzp6enoQkXc2JHoAImWmgIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISMKw6AG0qeHABsAoYHTv3+sM+pkVwKu9f5YBLwKrCxyjoIB4Gg5MBCb1/j0BGAtsCWwCdDRZrwdYAjwHLAYWAI/0/r0AWJnLqGWADn3+IFejgc8CHwOmAkMLuu5qYC4wG5gF3AU8U9C1a00ByUcHcDxwJrZcKoMFwB3A7cBMYFXscKpJAWndWsAvgcOiB5KwDLgBuBa4E4WlYQpIa4Zg//AOjh5IE5YAvwAuAx6LHUr5KSCtOQ04J3oQLZgJfA+4FXsIIIMoINltgT1FWjt6IDmYB5wH/Ao9Sh5AG4XZnUA9wgEwGbgCWAQchf5dvEUzSDYd2H7EptEDcTIXOB24LXog0fSbIpsJ1DccADth9yW3AFsHjyWUApLNuOgBFOQAbD/lDOxxdttRQLIpy2ZgEdbGNkD/DrwveCyFU0Cy+Xf0AAJMwl5lOZ3iXqEJp4Bk81T0AIJ0AmcD9wCbBY+lEHqKlc1Q4CXaa6k12BLgCODu4HG40gySTRfw2+hBBNsE+BNwYvRAPGkGyW4itgPd7LmOOroM+AL2i6NWNINktwD4UfQgSuJY4GZg3eiB5E0zSGtGYDesU6MHUhJzgP2ApdEDyYtmkNasBA7EHn8KTMHeEN4oeiB5UUBatxSYDnwf6A4eSxlMxkIyJnogedASK187AF/GzqS/+x3++6vAfOyt2Wew5gsvAcuxLiZv9v7cCGAksB6wMfaPbQywfe+fKjxefgzYjYovtxQQH0OA8cA22DtMr2KhWEw+B5O2Aj4I7ArsDbw3h5oe/gbsCfwneiBZKSD1sBnwEeBwLDBlauf0R+Ag/jc7VooCUj8bAkcDx2FLvjK4Evh09CCyUEDqbS/gZGD/6IEAJ2Hn3ytFAWkPU4DvYEudKN3AvljbocpQQNrL7sAFwC5B11+GnVasTNdH7YO0l/uADwFfxB4tF2194GoqdJ5EAWk/3cAl2A38LQHXn4YduqoELbHkOOBCbHOyKF3Ycm9WgdfMRAERsPuC67GNzaLMxx4elLpPsJZYAtYHa2esG3xRJmGtW0tNM4j01wlcChxT0PXewGavRwq6XtM0g0h/q7APAH23oOutBcwo6FqZaAaR/+dc4NSCrrUfxS7vGqaASMqZWFdFb/OwpnSlO9OuJZakfAP4eQHXmYy9YFk6mkFkTYZiDRm8X3h8HDsMVqrvk2gGkTXpAo4EHnW+zrZYI7pS0QwijZoIPACs43iNh7HlVmnO9msGkUYtwL6q5WkHynF25S0KiDTjp9grKZ6+5Fy/KVpiSbPeg80m6zvV7wG2w/+epyGaQaRZLwBfdazfgb1hXAqaQSSLDuxVda+Tic9jfcDCb9Y1g0gWPVgTBi+bYu2LwikgktV9wI2O9Y9yrN0wLbGkFVOAB51qL8eaYIfurGsGkVbMwV5D8TAaO5YbSgGRVl3oWPsQx9oN0RJLWtWB7Yts71D7UWCCQ92GaQaRVvVgx3Q9jMc2JsMoIJKHa/Dbs9jDqW5DFBDJwwvYZw48THOq2xAFRPLyO6e6uznVbYhu0iUvY/BpSr0K+xxdSIM5zSCSl2exbol568QOa4Uoe0BGYhtGnqfYJD/3ONXdyanuGpUtIJ3AJ4AbgCXYxx+XYR/BXAxcBRyAPXuX8rnXqa7HHktDynQPcjBwEbBlAz87D/g8cL/riKRZ4/A56PRrgho6lGEGGYJ9u+5GGgsH2MH+e4GveA1KMnkcn08+F9l1foAyBOSHZPuH3hcsz3MJ0pwefG7UG/3FmbvogByDfQ6sFedhH6uXcnjcoebGBH22LTIgo8nns8BDsHeBhuVQS1r3pFPdDZ3qJkUG5HgsJHkYD3w8p1rSmuec6m7gVDcpMiB5H6n8VM71JJuXnOq21QyyKfk/255O/D2V+AWk06luUtQ/qPEONUdiwZNYXu9MreVUNykqIF7ryY2c6krjXnGqW+Rnqt+iJYlIQlRAVjrVXc+prjRuqVPdl53qJkUF5A2nuiE3cjLA89jLpXkLaWYdFRCvG7mQR4EyQDf5v/a+EAte4aICUqtn5fI2V+dc76qc6zUsKiBe68nNnepKc35Dfkui5cDFOdVqWt1mkK2d6kpzVmPndfJoBXQiFpIQUQHpAl50qLutQ03J5i7glBZr/Bi4PIexZBa5D/K0Q81J6DhumVyAzQBZZpIZlOB7hZEBecKh5rpoFimbGVjzt3kN/vzTWNPqrMHKVd0CArCzU13J7n5gR+BA7AnX4P5ZL2KN547A3tO7qdDRJUQeMlroVHca1itWyqUHuLX3D1grp+HYnpjHxmIuIgMy16nudKe6kq/Xev+UWmTbn07sN4fH6yFjsU5/Ii2JvAdZhU8HDICDnOpKm4l+3d2r8dtHnepKm4kOiFeryn0I/jKR1EN0QO52qjuEoFaVUi9l6M27CJ8z6guxtvnh/4NSXdEzCMAtTnW3B/Zyqi1togwBudGx9gmOtaUNlGGJNQw7x5xXl8XB3g/McaotNVeGGWQ1vu/efNOxttRcGQICvkcqDwF2d6wvNVaGJRZYUJ/FrzPibGBX9ERLmlSWGaSb/A/697cL9i0SkaaUZQYB2wt5BL8TgcuwfZEXnOpLDZVlBgHrgnG7Y/31CeyOIdVUpoCAfa/Q02HA55yvITVSpiUWWGDnATs4XuM1YCqwwPEaUhNlm0G6gbOdr7EOdv7Za2NSaqRsMwjYzvpC/LuT3I4drOpyvo5UWNlmELCd9TMLuM7+wE9QHy1JKOMMAvZN7IeAyQVc6yzg6wVcRyqojDMI2LLnpIKudQZwbkHXkoopa0AA7gBuK+hap2Ih0XJLBijrEqvPdlj/rKK+cHo51pXc6wM/UjFlnkHAXj05q8DrHQPcjO26i5R+BgFrLDcH69xelCewXXev7o9SEWWfQcCWO8dS7H7FNsBfgOMKvKaUUBUCAjAL+FbB1xwBXIotudRjq01VYYnVZyj21aJpAddeDpyObSyGf7NCilOlgIA1pZ5L3E30bGx/5r6g60vBqrLE6vMMcDhxv8V3wdql/h6YEjQGKVDVAgJwJ3By8BgOAh7ENjLVnK7GqrbE6u8K4OjoQfR6GLs/uRK/T1xLgCoHZDj2hGmf6IH0sxqb4a7FZpd/xg5HWlXlgIB91fYuyvvhzn9ggZkF/BV4KoeaHcAWwARgJPAGtrH5KHrClruqBwRgI+xDPOOiB9KAFdhhsIVYH7BnsS+8voJ9jm5l788NB0Zhpx43xAIxFgvFJCwYg/0LuA64CFvySQ7qEBCAMdiSpojzI2XXDfwAOA14PXgslVeXgIDNJDNRSPrMxp62LY0eSJXVKSBgIfkD2qPo8wD2WeyVa/pBeWdV3AdJWQp8GN8GdFUyFTg/ehBVVrcZpM9Q4BLsLeB214MtO9UHLIO6zSB9urAOiiehtj4dFHe+v3bqOoP0twdwDbBJ8DgircAeF7f7L4um1XUG6e9u7DNsfw4eR6RRWGd7aVI7BATslY/pwNdo34YMW0UPoIraJSBgy4tzsFfW5wePJcK7ogdQRe0UkD4PAR/Auim2007ziugBVFE7BgTsBb+zsHX5rcFjKcpj0QOoonYNSJ8ngQOBA6h3i5/ngUXRg6iidg9In9uwJ11HYaGpm2vQF34zaYd9kGYNA44ETqEeLz6+jrVwXRw9kCrSDPJ2q7Gjsztib8POjB1Oy76NwpGZZpDGjMPe6/oM1dqRvwk4FJ00zEwBaU4nsDfWeuhQyt3k+nrgk9gTO8lIAcmuE2v5sz+wL+V5lWMFtsdzMboxb5kCkp+xwJ7Arthu/U7YDX8RurDDUdcBP8NapUoOFBA/I7BZZSL2FGki1nxhc+w+ptmvWfUAS4CnsQ6Ti7AzHvN7/34zl1HLAApIjGHAxtg9zMjeP6MG/cxr2HJpee/fL6MQFE4BEUnQPohIggIikqCAiCQoICIJCohIggIikqCAiCQoICIJCohIggIikqCAiCQoICIJCohIggIikqCAiCQoICIJCohIggIikqCAiCQoICIJCohIggIikqCAiCQoICIJCohIggIikqCAiCQoICIJ/wXQTHy71qwxPwAAAABJRU5ErkJggg==)}20.41%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAMaUlEQVR4nO3de9BVVRnH8e8LCugEYqII0RUVEG9o5o3KUUlkvI3aOE46MeO1sWZsbLz1hzpTXmqamkkb791snCYta1AkTSzAMhEJURAxi4iLGoqYgeD79scjyTSyzj7n3c9+1t7n9/nPP3jWGuF31tp7rb1WT19fHyLy/gZEd0AkZwqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCTtEd0CSRgGnA5OBscBgYCPwd2ApsAxYAiwC3g7qY6P16PqDLI0GvgmcTbEfsbexkDwF/AF4FFjj1rsuooDk5wTgbuCD/azzPDALuB+YA2zpZ72upIDk5Qzg55T/bPgaMAML3u+Ad0qu31gKSD4OAv4IDHFuZzUWlNuBF5zbqj0FJA8DsOeHgypssw+bgn0feAjorbDt2tBr3jycRrXhAOgBpgIPAIsp/kKgqyggeTg3uP0JwE+xV8dfRP8u/kdTrHg7AhuwNY5cPANchk29upp+KeLtTV7hANgfmIk9o+wV3JdQCki8PaI7kPA57PnkavILcSUUkHi5z3EHA9cAC4FPxnalegpIvFXRHShoPLZOczVd9LZLD+nxBmAr3cOiO9KGPwGfB1ZGd8SbRpB4vdgDcZ0cDjwNTInuiDcFJA83R3egAyOw18BXRnfEk6ZY+fgNcFJ0Jzp0F/AlGvhNigKSj9HAAmBkdEc69BhwKrA+uB+l0hQrH6uAE4F10R3p0NHAbGD34H6USgHJy3zgCGyrRx1NwkaSMcH9KI0Ckp9lwCHAV4EVwX3pxL40KCR6BsnbAOBI4ChgIrZYNx4YGtmpghYDxwCvRHekPxSQ+unBNhAegp12cgy2XT1HC7D+1fbBXQFphjHAycApwHHkNXV+BJgGbI7uSCcUkObZEzgLuACbjuXgDuD86E50QgFprh7gWOBS7NPaaJcB347uRLsUkO4wCduFe0pgH3qx6d/swD60TQHpLkcB3wEOC2p/LXAw9dnin9XDnPibhy1Enk/Miv1I7GC8gQFtd0QB6T592EPzeOxY0qpNBi4PaLcjmmLJdGy7/c4VtrkZ+BT2GW/WFBABW6W/DxhXYZuLsW/cN1XYZts0xRKAZ7Ff9FkVtrkf8LUK2+uIRhDZ1kBsunVhRe1txDY3vlRRe23TCCLbege4CLihovaGADdV1FZHFBB5P1cCV1XU1jTg+IraapumWJJyA9W8kv0LtoCY3RUMGkEk5QpszcTbgcAXKminbRpBpJUdgQexfVSeXsQWL7O6S1EjiLSyGTtFcblzO2OBM53baJtGECnqAOAJfO9QfA5bH8nmH6VGEClqEXCJcxv7YkcfZUMBkXbcij2PePqyc/22aIol7doTWAIMd6rfB+yD/zNPIRpBpF1r8F1E7MHO+c2CRhDpxADsjpBDneqvBT6EbX0JpRFEOtGLHQbhZST+6y6FKCDSqTnADMf6Ways5zrFGoq97puMLSANAf4DPI/9xTz47n9LrEnY6Yke3sBOig+9cyS3gAzHjqe5gPQnoOux7xauA/5dQb9k+x7CbzfuFOxkxjA5TbEmYyupl9D6++hdsDcpi7AzaiXOjY61wxcNcxlBTsBO2BjUwZ99E/sFe7zUHklRPdgnux4HaC8H9naoW1gOI8gE4F46CwfAB7D7/T5SWo+kHX3YCruHvQi+ZyQ6ID3Aj+j/kTO7Abf0uzfSqXvwW7P4rFPdQqIDcjJ2mkYZTgA+XVItac/LwMNOtUP/TqMDUvbpGeeVXE+K+6VT3SOd6hYS+ZA+CHvXPbjEmq/SsFtWa2QUPodSb8GeM0MOmIscQSZSbjgARtCQyyNraDV2+ELZdsA+ogoRGZB9neqOcKorrT3mVPdAp7otNTEgEmeeU92wtZDIgHjdn7fWqa609qRT3b2c6rYUGRCPZ4UN2FxYYvwNeN2hblcGxGPle6lDTWnPsw41w168RAVkEPZtc9kUkHgvOtQcgb3NqlxUQHZzqvsPp7pS3F+d6oa8nYwKiNeJGApIPK+XJCELwE0LyKtOdaU4r4AMdaqbFBUQrwsjPd6gSHtec6rb6ecQ/RIVEK9fAwUknteeqV2c6iZF7+YtW1ZH53cpr8M0epzqJjUtICKligqI1x77nZzqSnEh6xVeogKy3qlu2dvnpX1ebyg3ONVNigqI12FguzrVleK8AvKWU92kqIB4/RqMdKorxXmteIe8oYwKyCtOdRWQeB92qttVAfFa8f6EU10pzisg/3KqmxQVkC34hGSsQ01pj8eHcGsIOsQ6ch1kpUPNiQ41pT0eAVnhULOQyIB43EE3HPiYQ10pZhQ+24g8fkwLaVpAwO9aMGnN6yVJ2IdwkQF5wanuUU51Jc5zUQ1HBsTjkDGAo53qSmtebyfDAhJ59Ohg7G4Pj707o9HpJlFeodzFwk3AMLrwLdYm7EJ6D+E3E3WxB0uu9yiB9xRGb3f3uhXqNKe60todJdfzupynkOiAzHGqOwXYw6m2pM0BZpZU68/Y7WFhogPye6e6A4GznGpLaxfR/60hbwHT8ft2qJDogKzEbz3kQoI+0xRWYLeHvdnhn38bOAO/Z9TCogMC8IBT3QnolW+kx7H//+0eJLcaOJbypmn9kkNAZjjWvtyxtrT2FHAAcB2tvyJ9C/gedi3GXOd+FZbDPemDsHfnw5zqHww87VRbitsJmIZdyjnu3f/eiJ3lOxf7oQz5rDYlh4AA/AQ4x6n2DOAkp9rScDlMsQB+5lj7RHQ9tHQolxFkIPBP/HaDPgkcDvQ61ZeGymUEeQffUeRQyr+TXbpALiMI2DVby/Bbu3gde/W7xqm+NFAuIwjYguHDjvWHA3c61pcGyikgADc515+GplrShpymWGDTq8X43qG+ETgMWOTYhjREbiNIH7bq6mkIcB9+R2RKg+Q2goB9YbgU/zOuHsGmXJud25Eay20EATtU7toK2jkO+EEF7UiN5TiCgAV3AXBgBW3dCFxRQTtSQzmOIGAr3lXtxL0cuLKitqRmcg0IwCzKPwBge64Drq+oLamRXKdYW30cOxNpSEXt3QpcjG19Ecl6BAF4CfhGhe1diH3h6PVtitRM7iMI2AFz84H9KmzzeeB04NkK25QM5T6CgB0wdw7VrleMw46cmV5hm5KhOgQEYCFwTcVt7gz8EPgVsHvFbUsm6jDF2mog8BgwOaDtddjr4DsJPqdJqlWngIAdSr2AuMs6nwAuBeYFtS8Vq8sUa6tV2ImJUZ/OHoadwHE/MCmoD1KhugUEYDbxW0NOwUaymdieLp3g2FB1m2Jt63bgvOhOvGspcBtwD/qkt1HqHJAdsa0ox0V3ZBu92Db6X2OnkoddPinlqHNAAHbBLlg5OLoj27EE699c7BjO5egtWK3UPSBgaxSPUu1Ke6c2YNOxpdgq/TzskGed15WpJgQEYAy2RuL9FaKHFcB3gZvR143ZaUpAwEIyC98DHzw9g92JsSy6I/KeJgUEbLo1i/quUawDjsc2Z0oGmhYQsAf3+6nv5TlrsZcOq6I7IvVcKGxlPfYrfFd0Rzo0ErgluhNimhgQsDvuzgWuop5viE5CVzZkoakB2ep6YCrwanRHOnBxdAekmc8g72cM8AvsjpC6eAPYlXqOgI3R9BFkq5XYlOUa7GC6OhhGPdd1GqVbAgLvndh4BLaSXQejozvQ7bopIFvNBw7CRpNNsV1pSdvog3VjQMCCcS22f+u3wX1JeTm6A92uWx7SW5kKfAvYP7oj29gEDEX7s0J16wjy/x7Cpl3TsYvtczAbhSOcAvKeXuDHwHjsHK4lsd3RfYo50BRr+wZgU6+vYFtXqnxgXggcgtZAwikgxewNnA+cDYxybmsj9ip6oXM7UoAC0p6BwLFYUE7EVrrL1AucCdxbcl3pkALSuR2w1flTsSnYuH7WW4cFb2Y/60iJFJDy7AkcA3wGe344ABhU4M9tAe4Gvo6+AcmOAuJnEBaSCcA+2Nuxj2KXAW3CXifPxa6kXh3UR2lBARFJ0DqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISMJ/AQTLWspwuVXaAAAAAElFTkSuQmCC)}22.45%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAL4ElEQVR4nO3daaxdVRnG8X8HoMxShtRSBiFQCkhpwCJDBYoyCFgUTABDhFACRmOQKBBCQCgRSYxBjAmIiBOIiAIOFKkiBIIiVAppoRWLgAxlsKVQLJX2Xj+8PdqG23XPud3vetfe+/kl91Obd617z37O2tNaa1h/fz8iMrDh0R0QKZkCIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpIwMroDktVYYG9gDNAHvATMARZHdqpkCkjzbQxMB84EJg7w7/3AQ8C1wC3AynxdK98wbeLZaEcA3wd27PL/LwQuBm7FRpjWU0Ca6xzgOwztOnMucB4wq9Ie1ZAC0kwnAz+toM5dwLnA0xXUqiUFpHl2xkaATSuqtwK4ArgKeLeimrWh27zNcyXVhQNgI2AGdrdr/wrr1oJGkGYZBzyH3xffSuBy4GvAKqc2iqIRpFk+he9nOhILyANYGBtPAWmWAzO28xhwZKb2wiggzfKBjG1tA8wELsjYZnYKSLOMytzecODrwI3AhpnbzkIBaZY3g9o9HfgdsGVQ+24UkGZZENj2YcAfgW0D+1A5BaRZ7gtufxL24mNj7nDpOUizbI69wr5ZcD8WYiPKC8H9WG8aQZrlLeDb0Z0AdsVGs/cH92O9aQRpns2Ax4FdojuC9eNQYGl0R4ZKI0jzLANOJO6O1pomArdT41vACkgzzcEmS70S3RHgcGzSVi0pIM31KLAP8LPojgCfAb4S3Ymh0DVIO0zC3sA9OrAPfcBx2OsptaGAtMshwNXAfkHt/wvYlxrd/tUpVrs8CEwGzibmztLW2MoptVlNRwFpnz7gu8AewK8D2j8YuDSg3SHRKZZMB74FbJKxzVXAh7EbCUVTQARstcXbgPEZ25yHXQutyNhmz3SKJWCroBwA3J2xzb2AizK2NyQaQWRNI7DF5s7O1N4KLCgLM7XXM40gsqZV2IqMMzK1txFlvFy5ThpBZF0uxNbYyuEY8p7edU0BkZRLgMsytPME9rS/uAWzdYolKZcD12VoZx/sfa3ilD6CDAOmACdh9813ws5b3wTmA/diizQ/F9XBFhgB3Akc69zOQuzhZVH7k5QckCnANdi7OymrgJuB84FF3p1qqS2Ah7ED2NOpVLMqfWVKDMgw7FWEXl9HeB0bae6vvEcCsCfwCL5P3J/CbvsWc1CWeA1yNUN7V2cb4B5sgo5U70ngC85tTACOcm6jJ6WNIGew/rPPlmCnZc+vf3dkAHcA0xzrzwQ+7li/JyUFZFtsJ6MqVue7EzihgjryXmOw96hGO9XvB3ajkKfrJZ1inUt1S1dOw+6rS/UWYQ8RvQwDznKs35NSAjICO72q0mcrrif/dwPwF8f6p1HIsVlEJ4CpVL/IWOP3rgjUB3zZsf5Y4KOO9btWSkA8nqKOp0ZTO2voAXxnJJ7qWLtrJVykbwC8CrzPofZWwBsOdcXsh9+swCXAdgQ/WS9hBJmCTzigJRtNBpqN7QviYSts2dJQJQTkE05131r9I76+6Vjb69joWgkB8VrM7BGnurK2WcDfnGp/zKlu16IDMha/hQLucKora+sHrneqPQE7RsJEB2SqU90+4OdOteW9bsJvstMRTnW7Eh2QQ5zq/gG9+p7Ty9jf3MNBTnW7Eh2QDznVvd2prqyb1998slPdrkQ+B9kYmxno8TBvB2q0QHJDbI/P33wVtvficofag4ocQfbGJxzzUDgivIj97as2AjtWQkQGZIJT3fuc6srgvK5D9nSqO6jIgHj90g861ZXBPeRU1+vLdFCRAfF6/uH5GrakPexU13uxiHWKDMiODjWXAs841JXuPIvPxjw7ONTsSmRAPH5pj4tE6Y3HZ+DxZdqVqICMwuagV83rnSDp3gKHmttgjwWyiwqI14R/rWQSz+sz2MqpblLTAqLnH/FedKrrdcwkRQXE69vgNae60j2vz6BVARnlVFfTa+Mtcaq7kVPdpKiAbOpUVwGJ57X/utcxkxT9Nq9I0RQQkQQFRCQhKiBvO9Wtam1fGTqvJZy8jpmkqICscKob8jBJ1uIVkHec6iZFBWSxU12P11ekN16fgdft46SmBWR7p7rSvXFOdb2OmaSogHh9G4S99Sn/4/UZtCogy7FNN6vmNQlLure7Q83XaNk1CPi89bmXQ03pjcdn8E+Hml2JDIjHL70lsLNDXenOLvjcag+bxhAZkPlOdQ9wqiuD81rkzWMSVlciA/KUU93QpSpbzmsp2Sed6g4qMiBev3ToYsctd5hTXa8v00FFLz36FrZyXtXG4TezTQY2Dp/rypXAFrRw6dHlwONOtcN3Jmqh453qPkFQOCD+bV6vRd4+6VRX1s3rbx66U1h0QLyWqjyC6vddl3Ubg9+1X+hSstEB8VrseDg+e6/LwD6N37F0r1PdrkQH5CX87lCcBQxzqi1rO8Gp7gLsGAkTHRCwXVI97E4Bu6S2hNdOYXc71e1aCQH5lWPt8xxri9l89Y8Hz2OjK5HPQTpGAq/iNxtwf2C2U22xGYQe0xfeALYD3nWo3bUSRpCV+H5TXOpYW2AZPltA30lwOKCMgADc7Fj7eGCKY/22W4nPy4Q3OdTsWSkB+T2+dyu+QTm/axPdU3G9lwm+vdtRykHTB/zYsf5k4EzH+m33w4rr3Yht/xyuhIv0jl2Bp/F7drEYm+22yKl+290BTKugzlJgNwpZqb+UEQRgIb73vUcD1zrWb7svUs3drC9RSDigrIAAXONcfxpwhnMbbfU8cCLwn/WocQ12elWMkk6xwE6v5uG7L/a/sSe/YbPUGu5Q4DZsX8FeXLb6p6gDsrQRpB+Y4dzGJsAvsEk4Ur37gQ9iN126udCeA3wE+CqFhQPKG0HAnqzPxy7aPf0WO+Uq4m5JQ+0EnAJMBfbAvpRWAM8Bf8ZGmgcoMBgdJQYE4DTgRxnauQ44J0M7UlOlBmQ48BiwT4a2LgUuz9CO1FBp1yAdfcAFmdq6DLgwU1tSM6UGBOyZyMxMbV2JRhEZQKmnWB27Yrd9c20BfB3weXThLquVPIKAPV2/KmN7ZwO/QVu5yWqljyBgo8ds8q7cvgA4CZibsU0pUOkjCNh989PJe9ozHngYmJ6xTSlQHQIC8Ch2IZ3TJsD12GzHMZnblkLU4RSrYyRwH3BwQNtLgfOB7+EzvVQKVaeAgC2QPAfYOqj92cC5BK/2J/nU5RSr4wXsNZSob/H9sHeHZgKTgvogGdUtIGAHZ/ST76OBvwK3YEvTSEPV7RRrTT+hjPV3XwGOw24kSMPUOSAbYq+jHB7dEeBNbKLQnOiOSLXqHBCwJ973AxOjOwI8g/VjWXRHpDp1vAZZ01LgGOyVlGi7ABdFd0KqVfcRpGMc9ozEexbiYJYBY7G9F6UB6j6CdLyA7bD69+B+bIb2R2yUpgQELCQHYTMRIx0W3L5UqEkBAVtw7HDsdCvK+MC2pWJNCwjYhftRwA+C2tdyQg3SxICAre53BvbEPfdrKe9kbk8cNTUgHVdht4Ffz9jmPzK2Jc6aHhCwvSsmAX/K1F6udiSDNgQE7A7XFOASbEckL33ALx3rS2ZtCQjYlN0ZwIH4LVx9KxZGaYimPEnv1QbYwnQXU92SQm8DewPPVlRPCtCmEWRN7wJXYKuQ31VRzekoHI3T1oB0PA0cCxzJ0Jf46QM+h02ekoZpe0A6ZmGvqp9Cb28GP4+FS1u7NVRbr0FSRgInY9siHMTAm4o+DtyArXKyPF/XJDcFJG00sC/2CvtwbIfcufju6S4FUUBEEnQNIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgkKCAiCQqISIICIpKggIgk/BeiFQ9jtjBjnQAAAABJRU5ErkJggg==)}24.49%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAALN0lEQVR4nO3dfayWZQHH8e/BIwTNl6QgExJXISdTVDSTEiXXcJRr+UczrZjLsma2pYk5/zCWldVqWam9uUYrrbZsvUA6ZtjLBKIkUCAglgZWBJTgxIBzOP1xwXaG51zPfZ7n/t3Xdd/P77PxF+f8rhvO8zv3+3X1DA4OYmbDG5N6A8xy5oKYRbggZhEuiFmEC2IW4YKYRbggZhEuiFmEC2IW4YKYRbggZhEuiFmEC2IW4YKYRbggZhEuiFmEC2IW4YKYRbggZhEuiFmEC2IW4YKYRbggZhEuiFmEC2IW4YKYRbggZhEuiFmEC2IW4YKYRbggZhEuiFmEC2IW4YKYRbggZhEuiFmEC2IW4YKYRbggZhEuiFmEC2IW4YKYRbggZhEuiFmEC2IW0Zt6A6xWJgCvASYCB4Gnge1Jt0jMBbFWxgLvBxYAFwLHHPX3/wAeBO4G/lLtpun1DA4Opt4Gy9c84BvAtAJfe+jw1y4EnhduU6VcEBvJQuDzbXzfOmA+8Ey5m5OGC2LD+RhwVwffvxW4hAacn7ggdrQ3Ao/x4nON0dpAKMnOTjcoJRfEjrYaOK+krDXAXGBPSXmV830QG+oSyisHwDnATwhXwmrJBbGhrhRkXgp8S5BbCRfEhnqLKHcB4apY7fgcxIbaj+5w6BDh8u/DonwJF8SGUn8YdhPOS7aJxylNnQsyFZgJvJzw2+mfwFrg3yk3quaUe5AjVgBzgH7xOKWoW0EmAB8GrgX6RvialcC9wP3U5IeQkSeAN1QwzqeARRWM07E6FeQy4DvAKQW/fi3hIbt1si1qnnuAj1QwzgDwZmBVBWN1pC5Xsa4HllK8HBAOv1YCl0u2qJl+XNE4xwDfBcZVNF7b6lCQ9wFfB3ra+N7xhBtVs0vdouZ6lPBLpQp9wK0VjdW23A+xXks4RBrfYc42wrH13o63qPnOJzyLVcW7QgeAs4BNFYzVltz3IHfReTkgXPH6RAk53WA18PGKxhoLfKWisdqS8x5kHvBQiXm7Cecw+0vMbLLbgDsqGusdwJKKxhqVXPcgY4AvlZw5kfAwnhXzGdp7YaodXyTTz2KWGwVcDZwhyPXJ+uh8ErivgnH6CJfks5NjQXqB20XZp4lym+w6yj3UHckiMpxEJMeCXEWYWkbhOFFukw0QHoPfLB7n1cB7xWOMWm4F6SHs1lVq/fpnQnuAK4B94nEWktlnMquNAd7OyM9YlUH9W7DJ1hMmc1DqI3wGspFbQdQ/gOXi/Ka7D/ipeIwbxPmjktN9kNPRzsy3EXi9ML9bTCbMWHKScIw+MpmlMac9yAfF+Z8V53eLHcDN4jGuFecXlssepJcwydhkUf5a4FzCi1XWuR7Ci08XiPJ3AFPI4H2eXPYg89CVA8JvPJejPINon9eaTPhMJJdLQRTTzRyx7PAfK9cK4GfCfOVnorAcDrHGEu5PHC/KnwU8LsrudjOBP4uynwUmEdYhSSaHPchcdOVYjsuhtBbdU7gnEj4bSeVQEOWNoS8Lsy0o+6nroeYLswvJ4RBrM/A6Qe4mwn0Pn5zrPYnm6evNhPtjyaTeg0xDUw6Ab+NyVGWxKHc64XJvMqkLopoLdhD4oSjbXuwBdLMyzhHlFpK6IBeJcn9DQ5YAq4ntwG9F2arPSCGpC3KhKPcBUa6NTPV/rrpbX0jKk/TxwHN0vtTXcKbSgPXxamYa8DdBbj/wUsIUQZVLuQc5E005NuNypPAUYfHOsvVSzXzBw0pZEMVlQYBHRLnW2q9FuWeKcltKWZAZoly/FJWOqiCqWwEtpSyI6gbQn0S51prquaxkNwtTFuRUQeY+wrGwpbEFzcyVyaZrSlkQxR3SDfjueUoDaF6VTXY3PVVBxhGWTivbE4JMG531gsxJwLGC3JZSFURRDgjrFFpaTwsye4BXCHJbSlWQl4ly/yXKteJ2iXJPFOVGNa0gXuE2vR2i3K4qiOp4UvXby4pT/QxeIsqNSlUQ1Su2A6JcK061QJHqMxOV+mles6y5IGYRLohZRKqCqJZjzn5h+i6geIUBEi3hnaog/xPlqm5AWnGqn0GSCeRSFeRZUa5yfl8rZpIo97+i3KimFcR7kPReKcrtqoLsRDNNjOIRehudk0W5SW4CpyrIQTSPhahe47XiFK/H7kJ3AzIq5WVexcQKM9BdRbHWxqBZ5i7ZJBwpC6KYImYcCd9fNqYBEwS5ikfoC0lZkE2i3LNFudbaLFGu6rPSUsqCbBHlvlWUa62p1vNItuJtyoKoXo91QdK5VJSreI23kJRTj44FnifMnFe20/DsJlWbAmwT5A4AxwEvCLJbSrkHOYBuL5LFCqldRrUa1AYSlQPSP827SpT7HlGujUz1f75ClFtI6oL8TpQ7h8QrE3WZU4CLRdmqz0ghqQuiWnSlB+9FqnQl4f9c4fei3EJyWMRzE2EturKtJ+G0+V1kDOE8QTF/7hY0n43CUu9BAH4lyj2DDNbZ7gLz0U0u/ZAot7AcCrJUmH2TMNuCG4XZS4TZheRwiHUs4cle1cRgZwNrRdnd7lx0y03sJUw3mmTptSNy2IMcBH4pzF8kzO52dwqzf07ickAeBQHtmubvRLeabjd72+E/Klmsc5/DIRaEx022o3unfBWhJFn8YxtgDPA4MFOUv4NwH6tflF9YLnuQfuD7wvwLgGuE+d3mKnTlgPBZSF4OyGcPAuFtwI3C/P8Q3nZTzT7eTTYAfcL8GSR8B2SoXPYgEJ75XybMPwm4V5jfLWahLccyMikH5FUQgK+J898FfEA8RtOpb75+VZw/KrkVZAnawywIPwDPftI+5aMfG8ng5uBQuRXkEPAF8RgTgAeBE8TjNJVyrcA7yexKY24FgXAF4+/iMaYTrrN7iqDRe06UuxW4X5TdthwL0g/cXsE4lwHfrGCcplFM1wThiYcsLu0OlWNBAL6H/lwEwgm78nGJJnpMkLke+IEgt2O5FuQQcHNFY90C3FbRWE3wKLC75MybCD/z7ORaEAhXM6p6H+AO4KMVjVV3+4F7SsxbCjxcYl6pcrqTPpzTgXWEKYLU+oHZwOoKxqq744Engakd5rwAnAX8teMtEsl5DwLhjurnKhqrl8xuUmVsL+E99E5XfbqOjMsB+e9BIExIvQbt4w1DzSUcZ1trlwM/AsaP8vsGgRuAu0vfopLlvgeBcMx7DWGGvSq8u6JxmuAXwJsY3RubzxDeY8++HFCPgkB4n+PTFY11UUXjNMU64DxgAbAy8nUbCVerppPBZAxF1eEQ64hewjxa6rcDD+DlpDsxifCuyMmEX8C7CHsYxby9cnUqCISrJmuAieJxVJOgWc3U5RDriG3A1WhvKiWfKMDyUbeCQLipdKswX7Wwj9VQHQsC4ZH4xaLspHPBWl7qWhCADwGPCHKzmG7G8lC3k/SjnQAsB84pKe+PwPklZVkD1HkPArCHsJrUhhKyBoDrS8ixBql7QQB2EkqytcOcG4E/dL451iRNKAiEWRkvJtzVbcct+EFFG0ZTCgLhGZ/ZhHcVit4neYrw6q16ogirqbqfpI9kBuF84grgVUf93QBhYcjFhFd7fWPQRtTUggw1BTiVsA7JbsK5yr6kW2S10Q0FMWtbk85BzErngphFuCBmES6IWYQLYhbhgphFuCBmES6IWYQLYhbhgphFuCBmES6IWYQLYhbhgphFuCBmES6IWYQLYhbhgphFuCBmES6IWYQLYhbhgphFuCBmES6IWYQLYhbhgphFuCBmES6IWYQLYhbhgphFuCBmES6IWYQLYhbhgphFuCBmES6IWYQLYhbhgphFuCBmES6IWYQLYhbhgphFuCBmES6IWYQLYhbxf3q2xaqg4XFVAAAAAElFTkSuQmCC)}26.53%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAKQElEQVR4nO3da6ilZRnG8f+ek1lkankoJ020dGwqmhS1g4cmT0xGB5VKJYPBPlmJnSUwojIRLDIoi0LGCtIILEtHJyfLShSjtHQ8EKZmHnLUSHN0ZvfhUZpy73utvdd7r+dZa/1/H8V9ve8wc+33fD9T09PTSJrZgto7ILXMgkgBCyIFLIgUsCBSwIJIAQsiBSyIFLAgUsCCSAELIgUsiBSwIFLAgkgBCyIFLIgUsCBSwIJIAQsiBSyIFLAgUsCCSAELIgUsiBSwIFLAgkgBCyIFLIgUsCBSwIJIAQsiBSyIFLAgUsCCSAELIgUsiBSwIFLAgkgBCyIFLIgUsCBSwIJIAQsiBSyIFLAgUsCCSAELIgUsiBSwIFJgUe0d6NAUcDiwClgB7PbMf7sf+CNwOfBz4KlaO6jRMzU9PV17H7rwTuBsYJ8e/9/dwOeA7wBj8QdXrlEvyDbAN4EPzPHn1gLvBTZ2vkcaK6NckCXAT4Aj5/nzNwNvAR7pbI80dkb5Iv0C5l8OgOXADyjXKdKMRrUgn2Lup1UzObqjHI2pUTzFOpJyN6qrct8F7AVs7ihPY2TUjiC7U06LutzvPYCVHeZpjIxSQRZRyrFjQvYg1zIaY6NUkM8Cb0zKfk1SrkbcqBRkf+DMxPxdErM1wkahIM8D1gALE7fh6yea0Si8i/VpYN/kbdyXnD9pnk+58XEA5Z24hcBDlIez6yiv/IyE1guyD+WZR7YbhrCNSbAL5Vrxg5SSzGSaUpKzgGuHs1vz1/pzkCsYzh2mNwA3DmE74+x44FvAi+bwM+cDZwCbUvaoAy0XZBXw0yFs5zrgoCFsZ5x9FDhvnj97JXAs8GR3u9OdVguyiPINx7IhbOtQ4JohbGdcHQdcPGDGRcDJHexL51q9i3USwynHuViOQexMeWl0UCcB7+kgp3MtHkEWA7dTXgHJtA44Ct/BGsR5lNOrLtxJuVv5dEd5nWjxCHIi+eX4C3AClmMQ21DuVnVlL8qRpCmtHUEWAH8i97nH48CBlHvymr+3US6wu3QL5TudLR3nzltrR5BV5D8UPAPL0YUVCZnLgGMScuettYJ8JDn/Mso37Brcy5JyT0/KnZeWCrIvud9lbARW4zST1q2k93SaoWmpIKuT8z8D/D15G5Mkc9jFqYnZc9LKRfpi4B7KffUMv6e8Mt/Mxd8YeDfwo6TsB4ClNPCWdStHkJXklQPgNCxH164m75nFzpS7ZNW1UpATE7OvYATeGh1BG4FLEvPfn5jdtxZOsZYADwLbJeUfDPwuKXvS7Q9cn5T9GLATld/0beEIcih55bgCy5HpBuAXSdnbAW9Nyu5bCwV5R2L2uYnZKs5JzF6VmN2XFk6xNgCvSsi945nc6n/AMTdFeUUk49nFHcArE3L7VvsIspSccgB8A8sxDNOU5SQy7A28Iim7L7ULcnhS7hbKJBQNxxrybqMfkpTbl9oFyRoEt57ysEnDcR/dv9n7rDcn5faldkEOTsr9cVKuZndpUm7VeQE1L9K3Af5FzkC4pcC9Cbma3e6USfld2wy8EHgiIbunmkeQ/cgpxwYsRw1/BW5KyF0IvDYhty81C/K6pNz1SbnqbX1S7n5JuT3VLEjW/e1fJ+Wqt6y3FiayIFkfxfw2KVe9XZeUW+1hYc2C7JmQ+QRlYonquJOcpbWzp9zMqmZBdkvIvBW/+6jttoTMiSvIEnIWrXFaSX13JmTuQPk3M3S1CvLipNx7knLVvzuScl+SlBuqVZCMhTjBoQwt+FtS7kQVZIekXN+/qi/jIh3yPqoL1SrI4qTch5Jy1b+scUCzrViVqlZB5rIK0Vw0NRl8QlmQhjW7lNcEGau/g3EryOO1d0B1ftNnGbeCVLlXrv8xVn8HtQqS9Zt++6Rc9S9rafFHk3JDFkRdy3peUWVOb62CPJaUm/V8Rf3LmrGc9XwlVKsgWc8rshZ1Uf92Tcp9OCk3NG4F2TspV/1bmpT7j6TcUK2CbCLnkLlXQqbmZnlC5v1Uer5S8zZvxgSMrCmN6s8CchZhrTaEY9wKsgMeRWraE9g2IbfaV6I1C3J7Uu6BSbnqLWsQ4Iak3J5qFuTPSblVJ/FNuKwxoVm/THsax4IclpSr3g5Lyv1DUm5PNUePbgv8k5zpintQJv1peHYj55PnzcALgCcTsnuqeQR5gryjyNuTcjW7dyXl3kylckD9t3mzJvFlLuummWUVpOogwNoFyRoTegTw0qRsPdfO5F1/VF3Cu3ZBrknKXQCcnJSt5zqZvH9L65Ny+9LCIp63k/MO1QZgGa5TmG2KMk0x4+/wNvJmOPel9hEE4PKk3H2AI5Oy9V8ryXtJdG1Sbt9aKMhlidmfSMxW8bHE7Kxl3frWwinWEuBB8gaDHQDckJQ96Q4i7y7TY8BOVJ6S0sIRZBO5vynOSMyedGclZl9KAyOEWigIwPcTs4/DT3EzvAk4KjH/e4nZfWulIFeRN1d3EXB4UvakWgB8LTH/AWBdYn7fWinIU8BFifnVVkkdU6cCr0/MX0OlKSb/r5WCAFyQmO04oO7sCnwxeRvfTs7vW0sF2UAjh1XNaoryjzfzmm4dZSm9JrRUEIDzknKzFnWZNB8CViVv46vJ+XPSwnOQrS2gvN68rOPcIyg3AjR/yynLPGcOp74VeDUNLcTa2hFkC3BOx5mPAr/qOHPS7Eh5LpE9uf3LNFQOaK8gUO5mdblS6nep+MHNGFgI/JCcde23dheNPPvYWosFeRr4ZEdZG4EvdZQ1qc6mvJCY7SwaubW7tdauQba2BjhpwIzjgUs62JdJdQjwyyFs5xbKs6rmltBr8QjyrNXAlQP8/OlYjkF1fT04m4/TYDmg7YI8SRm+cP4cf+5R4ATgK53v0WRZwXCG8K0l95OHgbRcEChvc55GGUh2FfHXgY8DX6d8KHVx/q6NvWFMhtkEfHgI25m3rOWyunYt5VnGyykXjMspKxltpgw2vp7yBNZFPLuz/xC2cTYVx4r2o+WLdNV1PbkluZXywuO/E7cxsNZPsVTP4sTszZRJKE2XAyyIZnd/YvYXGJHPoC2IZnNTUu5vgM8nZXfOgmg2GSN3HgbeR6PPPGbiRbpms5DyTtweHeVtAY6hgVlXc+ERRLPZTLdTS85kxMoBHkEUmwJ+Bhw9YM6FwCkD700FFkS9bE/5nma+yzuvBY6lgRlX8+Eplnp5hPJW73xOjy6krNUykuUAC6L+bKScZq0G7u7j/99AWVDnFEb8YzVPsTRXiyl3o46mfMOxC+Ul0nuBGylv5l7NmCw7YUGkgKdYUsCCSAELIgUsiBSwIFLAgkgBCyIFLIgUsCBSwIJIAQsiBSyIFLAgUsCCSAELIgUsiBSwIFLAgkgBCyIFLIgUsCBSwIJIAQsiBSyIFLAgUsCCSAELIgUsiBSwIFLAgkgBCyIFLIgUsCBSwIJIAQsiBSyIFLAgUsCCSAELIgUsiBSwIFLAgkgBCyIFLIgUsCBSwIJIAQsiBSyIFLAgUuA/LBeTMNiQpxQAAAAASUVORK5CYII=)}28.57%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAJ6klEQVR4nO3dfeyWVR3H8TcgksaDPQi2CK0ssrTMJrkKih6lWuZYbj38UzOdqzWcZcVmrlzN5hpu2RaO3Nq0mg/DnrDCSqqxZstY0DDL1LSShxIzJCH49ccZj8Lhuu/f9b3Oue/7/foXft9z/dg+fM91Xec6Z8LY2BiSDm9i6QuQamZApAwDImUYECnDgEgZBkTKMCBShgGRMgyIlGFApAwDImUYECnDgEgZBkTKMCBShgGRMgyIlGFApAwDImUYECnDgEgZBkTKMCBShgGRMgyIlGFApAwDImUYECnDgEgZBkTKMCBShgGRMgyIlGFApAwDImUYECnDgEgZBkTKMCBShgGRMgyIlHFM6QsoZCZwPLALeBTYXfZyVKtR6SCTgMXASuAxYBPwAPAIsB1YA3wCmFbqAlWnCWNjY6WvIdoC4OvAaQ3+7jbgs8ByYOj/YXR0wx6QTwFX03unvBX4ILCz9SvSQBnWgEwGrgMuGkeN75KmZd6fjLBhvAeZAaxifOEAOA/4zPgvR4Ns2DrITOCnwOkt1XsKmAs81FI9DZhh6iCzgbW0Fw6AKcBlLdbTgBmWDjIbuAt4cUDtLcBJwJ6A2qrcMHSQWcSFA+BE4OVBtVW5QQ/IDOBO4sKx10uD66tSgxyQY0mPYtu85ziS6R2MoQoNckBuAN7Y0VhPdjSOKjOoAbmM9Ka7Kw90OJYqMohPsRYCq0kLELuwAzgBl52MpEHrIHOAm+kuHAC3YzhG1iAFZBLwbeC5HY+7rOPxVJFBCsjlwOs6HvObwG86HlMVGZR7kDOBu0mrdLuygRTIJzocU5UZhA4yBbiRbsOxHliE4Rh5gxCQTwKv6HC8nwDzSZ/jasTVPsU6GdgIHNfReNcDHwP+19F4qlztHWQZ3YXjy8DFGA4doOaALALO72isz+HXgzqMWqdYE4B7SE+vol1FCoj0NLV2kAvoJhzfAK7sYBwNqBo7yETSO4gm+1iNxyrgPbhriTJq7CAfIj4cfyatBjYcyqqxg6wn9iOo7cA5pC4lZdXWQRYS/4XgEgyHGqotIEuC6/8AWBE8hoZITVOsF5HuDSYE1X+MdG+zKai+hlBNHeSjxIUDYCmGQz2qpYNMBB4EXhBU/7fAPNz8TT2qpYPMJy4ckO5tDId6VktAInco+THwq8D6GmI1TLEmA5tJO4dEmIefzapPNXSQ1xMXjtUYDo1DDafcLgqsfW1gbfXveaRNxyGdMvxowWvJqmGK9XvgjIC695Hee3hzXof5wIWk/xBPPOTPNpNe4i4nbc5RjdIBmQ08HFT7cuCaoNpqbg7plOGmM4XbgUuopKuUvgeJ2nx6DPhWUG01twD4Hb1No98LrAPODrmiHpUOyDlBde8C/hZUW82cBfwIeHYfPzuLdO5L9GcPR1U6IPOC6t4SVFfNTAVuY3wbbkwHVgLPaOWK+lQyIFOI+6z2jqC6amYpcEoLdeYCl7ZQp28lb9LPJuaJxb1U0JpH2FTg78C0luptIT3MKbLDfskO8rKguquD6qqZd9FeOCA9En5zi/V6UjIgUQdj/jqorppZEFBzfkDNRkoG5CVBdat60TSCTg2oGTXbOKqSAZkbUHMb6atElTMloObsgJqNlAxIxC/9x4Ca6s1TATXnBNRspFRAJhFzlNp9ATXVm4glIrPo9nyYfUoF5DlBdZ1elRdxrsoE9q/+7VSpgEQdxLk5qK6a+2tQ3RlBdbOGLSBbg+qquaidY54ZVDerVECixjUg5f07qO5IBSTql/1PUF01tz2o7khNsaKeSHh8WnkRj3mLKb3cXarasAUk4i2uehO1EciuoLpZpQLyeFDdIjdyOsjUoLpR9zZZpQIS9ctOD6qr5qIe4RfZnWbYAlLkbasOMlTvuIZtilVsUZv2mRlUd6QCsom0NU/bii2L1j4R34MA/DOoblapgOwiZknCSQE11ZuIL0W3UuhE4pKPeSMWtfmYt7yID+EiVgg3UjIgEb/0UL3FHUCnErNTf7EP4UoG5N6Amn4PUlbURoB/Cqp7VCUD8suAmr8IqKnmoraSLfalaMmA/Iy0KVhbngB+2GI99e5tQXUjZhuNlAzITmBZi/Wuw+XuJZ1CzPY8O0lnyBRRerHiMtq5AXsQ+FILddS/qJPC1lHw4UvpgPwXOJ/xfYW2A1iM3aO09wXVLboRYOmAAGwE3kp/Lw7/BZwL3NPqFalXzwfeFFS76FayNQQE0km0Z5KO32rqDuDV+OSqBh8gbc0TYU1Q3UZKn1F4OPOAi4F38/SFb1tIwVhBzGNi9W4iaRYQscRkPfDKgLqN1XAM9KHuZv+88yT2r6/aBPyjyBUp51ziduovfhBSjQE5UNVnaAuAJYG1iwekximWBkfUKWGQduqfSaFv0feq5SZdg+mqwNq3UDgcYEDUvzcA7wisf1Ng7cacYqkfE0lTq9cE1X+YtHSlyEYNB7KDqB8XERcOSN2jeDjADqLezSK993hWUP0x0odXfwmq3xM7iHq1grhwAHyfSsIBBkS9uZC0wiHStcH1e+IUS02dTlo4GLm96wbgjMD6PbODqIkTgJXE7318TXD9ntlBdDSTgO8B7wweZyOpS1Xx9GovO4hyJgDLiQ8HwOepLBxgB1HeF4ArOhhnHXAWMdvRjosdREdyBd2EA2ApFYYD6l/urjKuBj7d0VgrqWBZ+5E4xdKBjgG+RlpK0oUdwGnAQx2N1zM7iPaaAdwMvL3DMb9IxeEAO4iS2cAqun1J9wfSgseqNxw3IJoGrCW9g+jKLtLmHOs6HLMvPsXSV+k2HABXMgDhADvIqIv8pvxI1gILKHRiVK/sIKPt0o7H2wq8nwEJB9hBRtmxpJ1DjutovN2k4xF+3tF4rbCDjK5X0V04IL14HKhwgAEZZS/scKybgK90OF5rDMjoOr6jcdYAH+lorNYZkNE1njNZmtoAnEc6JWogGZDRFX0w5v2kc18eDx4nlE+xRtdE0sbgJwbUvp90oM4jAbU7ZQcZXXuA7wTUHZpwgB1k1J1MOkR1Skv1NgBvATa3VK84O8hoe4j2dmi/k7Sh9dCEA+wgSruW3EZ62tSv64GPU8FxBW2zg2g3cAFwax8/uwe4nHSm5NCFAwyIkp2kkFxCWp/VxEZgIRVu9tYmp1g61DTgw8Bi4LUcfAO/DbgLuJF0ZPfArMrtlwFRziTSKcOTgScZshvwJgyIlOE9iJRhQKQMAyJlGBApw4BIGQZEyjAgUoYBkTIMiJRhQKQMAyJlGBApw4BIGQZEyjAgUoYBkTIMiJRhQKQMAyJlGBApw4BIGQZEyjAgUoYBkTIMiJRhQKQMAyJlGBApw4BIGQZEyjAgUoYBkTIMiJRhQKQMAyJlGBApw4BIGQZEyjAgUoYBkTIMiJTxf9Wwp7za76RaAAAAAElFTkSuQmCC)}30.61%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAJjUlEQVR4nO3dfcyXVR3H8TcPt8VsiE1NirZYmQWl9oQsYqOwDbU2Nnp0szQmmm4ui2nZaFb0IGWttsr5BOVWM7LYmkSKyUZUCJYSUmaMtlpIWRbDJB7741jZFuf+/e7fOdc5v+t6vzbnP/f9PZfox+8518M5444ePYqk/2986QuQamZApAgDIkUYECnCgEgRBkSKMCBShAGRIgyIFGFApAgDIkUYECnCgEgRBkSKMCBShAGRIgyIFGFApAgDIkUYECnCgEgRBkSKMCBShAGRIgyIFGFApAgDIkUYECnCgEgRBkSKMCBShAGRIgyIFGFApAgDIkUYkLiR0hegsgzIf40HzgNWAo8Ch4ADT//1MPAVYE6xq1MR4zzlFoAFwA3AjB5+dhNwBfBQ1itSFboekNOALwLn9/l7B4DLCN1GLdbVKdYIcB1h6tRvOACOA24DliS8JlWoix3ktcAqYGaCWoeANwCbE9RShbrUQSYAnwB+RppwAEwEbqZbf46d0pV/sdOA+4BlhKCk9EpgYeKaqkQXAnIu8CAwN+MYF2asrYLavgb5ELCC/P8j2AtMAVr9h9lFbe0gxxFuwX6eZv4ZJwNTGxhHDWtjQE4A1gEXNTzuSQ2PpwZMLH0BiZ0MrCXcym3aUwXGVGZtWoNMA9YDpxcY+yhwPIakddrSQU4BNgAvLjT+NgxHK7VhDXIycC/lwgFwZ8GxldGwT7EmAxuBMwpew35gOvBYwWtQJsPcQSYCqykbDoDPYDhaa5g7yE3AJYWvYSPwJsJLi2qhYe0gSykfjs3AWzEcrTaMHWQeYVFeMtw3Ah/EO1etN2wBmQr8AnheofG3AFcSXplXBwzTFGsCcAdlwvFXYDEwG8PRKcP0oPBq8r6yfixrgPfjnapOGpYp1pnA/YS3dJvyD8J06tYGx1RlhqGDPAv4Os2G4xFgEWFTB3XYMKxBlhI6SFPWEdYahkPVT7GmAzuAZzc03k3A5cDhhsZT5WrvIF+iuXB8GrgUw6FnqDkgCwhPqpvwMeCjDY2lIVLrFGs88ABwVgNjXQ98uIFxNIRq7SDvpJlw3IrhUESNHWQi8GvyfwB1D2Ff3oOZx9EQq7GDvJv84dgJvAPDoVHU1kHGEb7vfkXGMfYTnnN4vodGVVsHWUDecAB8AMOhHtXWQe4BzslYfy1jOw9EHVVTQF5COBswlycIxx7szjiGWqamKdbizPWvxXCoT7V0kBHg9+T7GOoBYBZwJFN9tVQtHWQ+eb8UvArDoTGoJSBvz1h7LWF7HqlvNUyxRoA9wImZ6r+asNGD1LcaOsh88oXjbgyHBlBDQM7LWHtFxtrqgBqmWDuAl2eo+ytgRoa66pDSHWQaecIBcEumuuqQ0gGZn6nuIeAbmWqrQ0oHZHamuvcCj2eqrQ4pHZBZmequzlRXHVNykT4J2Euezeuej+9dKYGSHWQGecKxHcOhREoGZFqmuusz1VUHlQxIrr12PZ5AyZQMyN8y1d2cqa46qGRAcmwOvQf4XYa66qiSAfkj4XWQlFx/KKnSz0FuS1xvVeJ66rjSLys+h7CJ2ykJav0EmJOgjvQfpTvIPsL5f4PaDyxJUEf6H6UDAvBdYPkAv38EuBBPhFIGNQQEYBlhl/V+N1bYRzhL8DvJr0iinoBAOKdjDrClx59fA5zx9N+lLEov0o9lLmH39dmEcwonAU8CvwE2AN8kfIkoZVVrQNQ+M4ALgHnAS4HjgaeAXYTXg75NhdszGRDlNh34ArCwh5/dAlxJRe/TGRDltBC4nfC8q1dHCPsoX5/livpkQJTL24A7GPuNoOWEu5tFGRDlMBPYyuBn3C8iPCcrxoAoh03A6xPU+RPhvMp9CWqNSU3PQdQO55AmHBDe0bssUa0xMSBK7aLE9d6XuF5fnGIptcdIf9bLCwjfDzXODqKUXkSeg5BmZqjZEwOilM7OVHdKprqjMiBKKddWsgcy1R2VAVFKuc64/0OmuqNyka5UppJnIX0ImEx4sbFxdhClkuuksG0UCgcYEKWT66Ti+zPV7YkBUQonke8wpKKvvhsQpfAe8uzUD+EwpGJcpCuF1h7EagfRoOaT7yDW4lvJGhAN6uqMtddmrN0Tp1gaxKuAn2eq/QThva6Dmer3xA6iQQyyI+ZovkfhcIAB0djNJd/DQajkpGKnWBqL8YQHeK/JVH8P8ELsIBpSS8gXDoCVVBAOsIOof1MJO+mfmHGM04DfZqzfMzuI+nULecOxnkrCAQZE/bmUvAtzCNuUVsMplnp1JuHFwUE3g4vZTjjSopr/KO0g6sUU4E7yhgNgBRWFA+wgGt0IcBfw5szj7AReRviCsBp2EI3ma+QPB4SNqqsKB9hBFPdZ4JoGxnmQ8Fyl3zMqs7OD6FiW0Uw4AD5CheGAfF+Babh9inCITRO+D6xraKy+OcXSM00Avkp4laQJ+wlfDO5qaLy+2UH0b1OAbwELGhxzORWHA+wgCmYSnnOc3uCYDxH28v1ng2P2zUW6FhNeXW8yHAeA91J5OMApVpedSnjG0cvxzKldR+gg1XOK1T3jCadAfQ54boHxNwJvBA4XGLtvBqRbZgNfBl5XaPw9hI0edhcav2+uQbphEmE69VPKheMI8C6GKBzgGqQLTgB+SL7Tn3p1DbCh8DX0zSlWu00EfkTYgaSkm2nu4WNSTrHa7VrKh+Nu4PLC1zBmdpD2OpXwlDr3R04x2wgB3VvwGgZiB2mvSygbju2EMwuHNhxgQNpsUcGxdxJ2ff9zwWtIwilWO00CngTGFRj7EULnKHYybUp2kHaaRplwbCWsOVoRDjAgbTWpwJj3ETrH0E+rnsmAtNPjDY+3ivAdyd8bHjc7A9JOu2nm7tERYClwMeEV9tYxIO10lPAEPae/AG8Bbsg8TlEGpL1uz1h7I3AW8IOMY1TBgLTXGuCXiWseBj5J+J6jNXeqYnwO0m5nAz8mzVvbDxM+tNqaoNbQsIO022bgigFrHAQ+TvjQqVPhADtIV1wM3Agc1+fv3QVcBTya/IqGhB2kG1YCs4BNPf78DuBcwl2qzoYD7CBdNAe4AJhHOAtwhLD43kVYr6wmbAVa5V65TTMgGqGSE2VrZECkCNcgUoQBkSIMiBRhQKQIAyJFGBApwoBIEQZEijAgUoQBkSIMiBRhQKQIAyJFGBApwoBIEQZEijAgUoQBkSIMiBRhQKQIAyJFGBApwoBIEQZEijAgUoQBkSIMiBRhQKQIAyJFGBApwoBIEQZEijAgUoQBkSIMiBTxL7JNyRXx/my6AAAAAElFTkSuQmCC)}32.65%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAI3UlEQVR4nO3dfajfVR3A8ffdk0rZ1LkMGwXqiKkDZ2VWZC2nqYloQUaiaDOTAu1xlm0l2INKYVHZJpqDslKo1vBhrY3CmYlZBu5qYkMKjUpn2ZMPm97+OK3C7v3s/n6/7/d7zvn93q+/7z3nXLhvzvfp9/uOTUxMIGlyM3IvQCqZgUgBA5ECBiIFDEQKGIgUMBApYCBSwECkgIFIAQORAgYiBQxEChiIFDAQKWAgUsBApICBSAEDkQIGIgUMRAoYiBQwEClgIFLAQKSAgUgBA5ECBiIFDEQKGIgUMBApMCv3Aio2E1gIvBzYC9gO3A88lnNRapaB9GYWsAw4AzgZ2GeSn7kXWAtcDfy9s5WpFWO+YWpaFgLnA2cC86f5O38E3g98t61FqX0GMrUx0i5xIXDsAON8GljVyIrUOQP5f7NJh1ArgEUNjbkS+ExDY6lDBvJfM0hhfAo4uOGxJ4A3AlsaHlctM5DkRODzwKEtzvEr4EhSLKrEqN8HWQjcBNxCu3EAHMFg5zLKYFQDmU06cd4KvLXDeU/vcC41YBTvg7wKuA44PMPcr8swpwYwSjvITOBi4GfkiQPgkEzzqk+jcpK+ALgeOCb3Qkj3V1SJUTjEWgrcCOyfeyHAU7kXoN4M+yHWh4FNlBEHwAO5F6DeDOsOMhv4GrA890Ke57bcC1BvhjGQuaRDquNzL2QS38q9APVm2AKZD/wQWJJ7IZO4Dbgz9yLUm2G6inUgKY5cl3Ajz5Duv9ybeyHqzbDsIAuAn9D8Q4ZNOR/jqNIwXMWaD2ygzDh2AueR7tyrQrXvIHNJh1WH5V7IJMaBc/G8o2o1BzKH9HHWkk7IdwI/Aq4B1gHP5V2OBlVzIGso5/Hx+4HVwHeAP2VeixpUayAXAWfnXgRwK3AF6QKBhlCNl3mXkc47cl5gWA9cAtyTcQ3qQG2BvIz0T7lfpvl/DnwQ+Gmm+dWxmg6xZgLfJk8cT5AefLwOT7xHSk2BrCTPJ/LWA+8F/pBhbmVWyyHW0cDtpF2kK/8kHU5d3eGcKkwNgewB/IJubwZuA07Dx0NGXg2PmnycbuPYiA8W6t9K30FeQfpHnd3RfNeSHizc2dF8KlzpO8gX6S6Oy0nPThmH/qPkQE4CTuhorlXAxzqaSxUp9RBrjHRo1cW5x+UYh6ZQ6g6ylG7iWINxKFBqIKd1MMcG0hugpCmVGshRLY//IOmLpJ9teR5VrtRAFrQ49j+AU4G/tjiHhkSpgezR4tgXAve1OL6GSKmBbG9p3O+RbgZK01JqIOMtjPk48L4WxtUQKzWQzS2MuYL07nJp2kq9UTgPeBjYs6Hx7iI9Ml/kH6tylbqDbAeuamisCeACjEN9KHUHAdib9OrkgwYc50rgQ4MvR6Oo5EAgPW6yBdi3z9/fRHqL7TONrUgjpdRDrF3GSe8VfKiP370ROAXj0ABKDwTSu8yXAF8Gdkzj5x8BziI9SvJki+vSCCj9EOv5DgTOAI4jHX7NB54mRXE36RtI1uGuoYbUFojUqRoOsaRsDEQKGIgUMBApYCBSwECkgIFIAQORAgYiBQxEChiIFDAQKWAgUsBApICBSAEDkQIGIgUMRAoYiBQwEClgIFLAQKSAgUgBA5ECBiIFDEQKGIgUMBApYCBSwECkgIFIAQORAgYiBQxEChiIFDAQNWkO8A7gm8Cvgb+RXqj6CLAR+CjpRazV8CWeasqZwOeAl+7m53YAq4FVwBNtL2pQBqJB7QWsJe0cvXgIOAXY2vSCmmQgGsQc4GZgWZ+//2fgDcB4YytqmOcgGsRl9B8HwL7AemDvZpbTPANRv14DfKCBcQ4CLmlgnFZ4iKV+jAF3Akc1NN5TwAJge0PjNcYdRP14N83FAbAn8M4Gx2uMgahXBwBXtDDusS2MOTADUa+uAvZrYdzDWhhzYAaiXiwH3tbS2PNaGncgBqLpOhT4UovjP93i2H0zEE3Hi4B1wAtanOPhFsfum4Fod2YCNwALW57nrpbH74uBaHe+CpzQwTzf72COnnmjUJHLgIs6mGccWAwU98/oDqKprKSbOABWUGAcALNyL0BF6mrnANgA3NLRXD3zEEv/axbpw0zLO5pvB+nQ6oGO5uuZO4h22Yd0ter4Duf8LAXHAe4gShaTriId3OGc48ArKfQG4S6epOs80qPrXcbxLHAuhccBHmKNspcAa0ifC+/apaQoi+ch1uiZAZwDfAGYm2H+O4BjSLtI8QxktLweuBJ4dab5HweWAL/LNH/PPAcZDUuAHwC3ky+O54DTqSgO8Bxk2L2JdJf6xMzrALgY2JR7Eb3yEGv4vJj0+e7zgUWZ17LLWtJ5T3UMZDjMAE4lXTo9jrKODDYDJ5G+o7c6BlK/o4FrKPMz3fcAS6ngO3in4kl63d4DbKHMOMaBt1BxHOAOUrNzgK/nXsQUtpEuEBT5MdpeGEidFgN3k748ujRbSTvH73MvpAkeYtXpK5QZxz3AmxmSOMBAanQ06VGN0mwknZA/mnshTTKQ+rwr9wImcS1wMpWfkE/GQOpT0u7xHPAR0v2XHZnX0gpP0uvzJOnb0HN7jPTatR/nXkib3EHqU0Ict5EegBzqOMBAapTzkY2dwCdIV6qqv8cxHQZSn99kmncr8FrSFy1U8WGnJhhIfe7oeL5ngE8CR5JuTo4UA6nPDR3OdTNwOOkz5EN5lWp3vIpVnzHgl8ARLc5xH+ny7a0tzlEFd5D6TAAX0M532W4DziI96zXycYCB1GoLsKrB8e4nPR28CPgG6Qag8BCrdpeSvoW9X5tJr1W7iUK/XT03A6nf20kvuTlgmj//KGmXWA082NaihoWBDIcXkr5C9GzS+cPz/YW0S1xP+maRnZ2trHIGMnz2J51LzCM9t/Vb0k4xMjf3mmQgUsCrWFLAQKSAgUgBA5ECBiIFDEQKGIgUMBApYCBSwECkgIFIAQORAgYiBQxEChiIFDAQKWAgUsBApICBSAEDkQIGIgUMRAoYiBQwEClgIFLAQKSAgUgBA5ECBiIFDEQKGIgU+BcqaIq/jbff/wAAAABJRU5ErkJggg==)}34.69%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAH6ElEQVR4nO3dfaiedRnA8e85m8sRYqm9bNHr1ERzxozKMpGw8iWzoMCcSRRIGhmY4aQoy4JWkGAw/UsonQoVheZaNM3sZSXN2HRhk/VmzdbLLIbVtLOnP37W1tq5es557vu57ud3fz+wv7bd9wXju9/9fqYGgwGSDm46ewCpywxEChiIFDAQKWAgUsBApICBSAEDkQIGIgUMRAoYiBQwEClgIFLAQKSAgUgBA5ECBiIFDEQKGIgUMBApYCBSwECkgIFIAQORAgYiBQxEChiIFDAQKWAgUmBh9gAVWwwsB04AjgOOAZ751O/tBDYBdwJbU6bTUKb88QeNeSFwGnAqcApwPLBgiL93L7AK2NjeaJovA5m/Q4DTgXOBNwHHjrCtAbAa+CgwM/JkaoyBzM0C4AxgJSWMZzS8/VuAdwF7G96u5slzkOEcDVwMXAQ8p8X9XAA8DFzd4j40B64gs5uiHDpdDrxhjPudAU4GNo9xn5qFgfyvhZRDqA9TrkBluB04L2nf2o+B7DMNXAh8DFiWPMsAeB7waPIcveeNwuIs4KfAF8mPA/Yd3ilZ30/SlwHXAWdnD3IQy7MHUH9XkEWUK0Vb6WYcAEuzB1A/V5BXAjeSdwI+rH9kD6B+rSALgY8DP6T7cQDsyh5A/VlBXgDcRnlGalLcnz2A+nGZ90zgZuDI7EHmYIZyDvKH7EH6rvZDrFXAOiYrDoCvYRydUOsKsohyIr4ye5B5eAI4CXgoexDVeQ5yOPB1yqPok+gjGEdn1LaCPAu4Czgxe5B5ugG4JHsI7VPTOchiYD2TGcc/gauAS7MH0X+r6RBrNbAie4g5GgDfoBxWPZA8iw6ilkOs44EtDPcOeKbHgQcps26iXGF7JHUihWpZQd5PN+P4OXAPcDfwE+CXlFVDE6KWFeT3tPsq7LAGwA+AWyn3MnyfY8LVsIK8iPw4fgFcT/nowo7kWdSgWgLJsoHyPsmd+CWSKtUQSMa5x92UK08/Sti3xqiGQB4f4742AVdQTrzVAzXcKNw2hn3sBi4DXoVx9EoNgeyi3W9I3U75+PQX8LOgvVNDIAA3tbDNPZT7K+fhlanequU+yGGUS61HNbS9bcA7KHe81WO1rCC7gQ82tK0NlA87GIeqCQTKTbprR9zGjZTPAP119HFUg5oCAfgQ8Nl5/L0B5XHz9wJPNjqRJlot5yAHOoty1WmYz4g+SHkP43utTqSJVGsgUG6CvhU4H3gNsGS/3/st5Uef3YaPiShQcyAHWgw8jfLFQr9aqKH0KRBpzmo7SZcaZSBSwECkgIFIAQORAgYiBQxEChiIFDAQKWAgUsBApICBSAEDkQIGIgUMRAoYiBQwEClgIFLAQKSAgUgBA5ECBiIFDEQKGIgUMBApYCBSwECkgIFIAQORAgYiBQxEChiIFDAQKWAgUsBApICBSAEDkQIGIgUMRAoYiBQwEClgIFLAQKSAgUgBA5ECBiIFDEQKGIgUMBApYCBSwECkgIFIAQORAgYiBQxEChiIFDAQKWAgUsBApICBSAEDkQIGIgUMRAoszB5AE+XQp37tAf6ePMtYuIIoMg2cC6wFHqFE8RjwN2AH8BXg7VT8H+3UYDDInkHd9DpgDfCyIf7sduADwDdbnSiBK4gOZhXwXYaLA2AZsA5YDUy1NVQGVxDt7xDgBuA9I2zjWuDyZsbJZyD6t8Mp5xRnNLCtlcAtDWwnnYEIYDnwZeDYhrb3J+AlwO6GtpfGcxBdCtxHc3EAHAVc3OD20riC9NdS4HrgLS1tfzPw8pa2PTYG0j8LKKvGp4HDWt7XkcCulvfRKg+x+uV04MfAdbQfBzR72JbCQPrh1cBdwHeAk8e436ePcV+tqPYRATENnANcRjOXbudjJmm/jTGQ+iwFLgAuoVxqzfSr5P2PzJP0OiwB3ga8E3gt3XjcYyfw3OwhRuUKMnmmgBcDrwBeTznxfmnmQLP4avYATXAF6b7nA2dTTq6XUx4g7PrJ7wxl1p9lDzIqV5DuOpFyr+LNdOOQaS7WUEEc4ArSRVPAlcA1TOZ/YPcDp1LJG4eT+A9QuzXA+7KHmKcHgDOpJA7wRmHXXMHkxnEP5S3EPybP0SgPsbrjOMoDfouyB5mHtZSXrJ7IHqRpriDdcQ2TF8cAuAq4kArjAFeQrng25SshC7IHmYM/U8JYnz1ImzxJ74Y3MllxbATOB36TPUjbPMTqhhXZAwxpBrgaOI0exAGuIF1xRPYAQ9hKORG/L3uQcXIF6YZDswcI7AE+QVnlehUHuIJ0xY7sAWaxjvI+yfbsQbK4gnTDluwBDrCF8oDkOfQ4DvAyb1csAX5H/kOJ24FPAjcDe5Nn6QRXkG54FLgjcf9bgXdT7uZ/CeP4D1eQ7jgJ2MR474d8G/g88C3KXXEdwBWkOzYDnxrDfnYCnwOOodygXI9xzMoVpFumgZsoH11o0l8oh3BrgQ1U8LWRcfEyb7fsBS6i3KW+ktFO2rdRDp3uoDyK/uSow/WRK0h3nQJ8hvJYx/8zQ3nFdSPwfeBe4NftjdYfBtJ9J1DuR6xg32d0HgMeBh6iXIHaQkVv8XWJgUgBr2JJAQORAgYiBQxEChiIFDAQKWAgUsBApICBSAEDkQIGIgUMRAoYiBQwEClgIFLAQKSAgUgBA5ECBiIFDEQKGIgUMBApYCBSwECkgIFIAQORAgYiBQxEChiIFPgX79BTOfrC0hAAAAAASUVORK5CYII=)}36.73%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAGuElEQVR4nO3dTaxcdR2H8WdKS+1LXBBT24ZUCV0ATQwQEQQkprVK0zRGW0QNLBoVN8jCjQuNC4EFGzaygRi7qPGtVhelKagQo1aaNogxqXRRUmgIrQ1hYYAKt+1l8b9NlZiv83bmf87M80kmd3N65pfbee6ZM+dlevRpfn6+30Wl1uv1en0tt6jhOaROMxApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApWFx7gBm1CFi18PgAsBxYyaX/jzngLeAC8E/gJeDc5MeUgTRnKXAtcM3Cz+uAjwBXUsK4bIB1nQV+D/wI2Ad4q/0J6e8e8Pj1B324ErgN+OTC4wZgSQPPcwTYCRxtYN0zo9+vPzCQ4S2hBLEF2ApsmOBznwXupmxNNAQDacYi4NPAPcB24IMVZ5mjhPm7ijN0loGM13rgm8BXgbWVZ/lPb1C2XKdrD9I1BjK6HvA54AHgTgb4XU3Yj4Gv1R6iawxkNDuABymfQLXdHLAOtyID8TsKh7MC+CWwh27EAeXDgu21h5hWBnLJCuBZ4K7agwzhU7UHmFYGcsku4BO1hxjSVbUHmFYGUuygm1uOi5bWHmBaGUj5oOIHtYcY0Tu1B5hWBgK3U86V6rITtQeYVgZSjnV03R9rDzCtDASurz3AiOaAX9ceYloZCKypPcCIduNBwsYYSLcvRHoD+G7tIaaZgcCp2gMMaQ74Cm49GmUg8NfaAwzhLOX0kt/WHmTaGQjsrz3AgI4AN+HFUhNhIPA8cLj2EP/HWeBJ4PPAzXi57cR4unuxEXhmAs/zJnAMeBE4CbwGnAFeB94F3l5YbimwDO9q0hivBxncD4H7x7zOo5SDeH8BDgHHx7x+DclABrcE2AtsG2EdFyhbot9Q9m1OjmEuNcBAhnMZ8AjwbQa7xPYY8ATwc7r7sfFMMZDR3AI8BGwKy1ygbCUeo9xZZKZ+QV1nIOPxUcp9rz4GrKZEcYpy7OQpyk62OshApMCbNkhjYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSsLj2AJqItcCdwI3AGsofxtPA34EDwMvVJms5A5lePWAzcD+wlfxu4Rnge8ChCczVKb1+F5yfn29yDo3PGuDLwH3ANQP8u3ngUeA7wPkG5mqVXq+/l76BTId1lK3EF4BNjLZvuQ/YDsyNYa7WMpDpth64BbgVuAPYMOb1PwZ8a8zrbBUDab/FwNXAhyl/8f+98ABYDlwOfAhYRdnJXgdcS3nbtHIC820Cnp3A81RhIO3UA7YB36C8AJfVHSc6DNxce4imGEj7bAB2ATfVHmQAHweerz1EE/oNxAOFk7ENOEK34oCy4z/TPA7SvM8Ce4EltQcZwo21B6jNLUizVgM/o5txQDmmMtMMpFkPA1fUHmIEM/8Ow0Casxq4t/YQIzpVe4DaDKQ5X6S7b60u+lvtAWozkObcUXuAMXi69gC1GUhzrqo9wIheBP5ce4jaDKQ5S2sPMKLvU87wnWkG0px3ag8wgj3Ar2oP0QYG0pwTtQcY0mFgZ+0h2sJAmvOn2gMMYQ+wEXir9iBtYSDN2Ut3Ljo6BtwFfAnj+C8G0pzTwO7aQwTzlBs2bAGuw32O/8nT3Zu1GjhKu043eQ34KfA4cLzyLNV4PUh7bAb2U/eo+r8ob/l+AvwBuFBxllYwkHbZBvyCyV5BeJQS5gHgIN3ZH5oIA2mfJq8onANeAJ5beBwEXm3geaaGgbTTxWvSvw58hsG2KOeBM5QX/ivAPyingxxb+NnlA5MTZyDt9/67mqzg0n7KOeBN4G3KnU7OLDxmft9hXAxECrxpgzQGBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIF7wFOjQWI0xRjWQAAAABJRU5ErkJggg==)}38.78%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAGOUlEQVR4nO3dy6tVZQCG8eeo3cxLUBmSBGZShEVFFwrKpCwIiiCIatKNbrP+gIYNqlGz7pdBgwYFglHQhUrBoKKioiwtIaxQK9JILbPT4DuQGb6ufVx7fXttnx+cyfHger08nL33WnudCTo0OTnZ5eE0piYmJjo71ozOjiT1kIFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIwazaAw5TRwALgOOAecBcYPY+v/43sAPYBfwObAN+AvZ2O1MGMnwLgBuA5cAZwMKpz03HNuA74FvgG2A98CnwBfDHIS/V/3R3H3kOux9/cDzwIHAn5TvGMO0FPgfWTX28A2we8jGr6fLHHxjIcFwKvMT0v1O0YS3wCPBKxQ1DYSD9dhWwCjim9pApq4HbgF8q72iNgfTXqcBHwPzaQ/azEVjBmDzs8idM9dcTjF4cAKcBrwFzag/pGwNpz6XAlbVHBMuAh2qP6BsDac/dtQc0cC+wtPaIPjGQ9qysPaCBmcB9tUf0iU/S23EC5SReH2yivJjQWz5J75+Tag8YwGLKSUw1YCDt+Kv2gAGdXHtAXxhIO36sPWBA/rs35F9UO3YAG2qPGMD22gP6wkDas7r2gIZ2Uq4IVgMG0p6nKO/jGHVv4ftKGjOQ9qynRDLqnq89oE88D9Ku+cAHjO7Z6s+Ac+jHd7oD8jxIf20HrmE0r5rdA9xBz+PomoG0byNwEbCm9pD93AN8WHtE3xjIcPxAef/FrcCXlbfsBG4Bnqu8o5d8DtKNc4HLgNMpdy/ZBWyhnGDcSnlotoN/z8jPBo6kXON1IuVGD4uBJZTL1uc2PO6rwP306xzNQfmOQh3MYuBC4GLgAko4RwO7ga8pD+9epNzIYewYiBT4KpY0IgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECmbVHjAmlgE3AcuBpcDRwG7gG+AD4D3gfWBTrYGanokuDzY5Odnl4bqwFHgUuKbh1/8GfE4JZxPwI7AN+An4E9g59XWzgHnAfGABsBA4CThm6mu+AtYAH7fxh+ibiYnu/tsayPTdDDwNzK644UvgIeAF4O+KOzplIKPvduDZ2iP2sYYS7A+1h3TBQEbb+cA64IjaQ/azGVgBbKw9ZNgMZHTNAD4Bzqo95AA2ABcA22sPGaYuA/Fl3sFcz+jGAeVFg4drjxgnBjKY22oPaOAu4IzaI8aFgTQ3E7ii9ogGZlAiUQsMpLlTqPuS7iCurT1gXBhIc/NrDxjAUsqJRh0iA2mubyfiFtYeMA4MpLnvaw8YkNfZtcBAmvuZfl1suKX2gHFgIINZVXtAQ1soF0DqEBnIYB4D9tYe0cAbtQeMCwMZzAbg8dojGniy9oBx4bVYg5tDeQPUstpDDuBNYGXtEcPkxYqjbxHwNnBa7SH72Q6cB3xbe8gwebHi6NsMXASsrj1kH7uAGxnzOLpmINP3C3Ad5bKOtZW3bAWuBl6vvGPs+BCrPYuAy4FLpj6WUS5wHKY9wDPAA5TzNIcFn4OMh6OAM4GzKZefLwFOpVz0eOI0f8+tlBs9rAfeBV6e+txhxUDG30zgBEoox1LuVjKP/z7k3Um5C8oO4FdKCHu6nTmaDEQKfBVLGhEGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgX/ACtN2/R85LfmAAAAAElFTkSuQmCC)}40.82%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAGXUlEQVR4nO3dW6ilYxzH8e8ae5TzqbiYDDKGRCQihZwmkkJKDnHhxoXTBckFMlNKXIxwqRwGiVCIyAgRJZkGySGnXFDDOGdmWC7epdkze83P3rP3ep9n7ff7qXWzZ+33+Tezv/s9rHfN6jFEv98f9mVpXuv1elO+tqDAHNLYMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApmCg9gGZkB+BIYAmwK/An8DmwFthQcK55y0DGwxLgBuAiYM8hf74BeB94d/B4A/iutenmsakfiICfD1KRhcBy4EaavcdMrAFeHDzeBjbN7Wjzz7DPBzGQeu0GPAucNgfbWg88BawC3gT+mYNtzjsGMj52oPnNf+YItv0N8BjwAM35iwYMZHzcDNwx4jX6wAvASuDVEa81FgxkPOwHfAns1OKaHwJ30uxZOnv45WcUjoeraDcOgCOAR2hO5g9qee2quQepz1qaH9hS1gGn01wF6xQPseq3G/Az2/h3adEPwLHAt4XnaJWHWPVbTPk4APYFHio9RA0MpC4LSw8wyanAOaWHKM1A6vJH6QG2ck3pAUrzHKQuC4HfqWdPsgnYB/il9CBt8BykfhtpLrXWYgI4pvQQJRlIfR4uPcBWFpUeoCQDqc8qmvulalHL4V4RBlKfDcDVpYeY5KfSA5RkIHV6DlhReoiBj0sPUJKB1OtW4LbCM3wNfFZ4hqIMpG7LgWWU+yF9sNC61fB1kPEwAZwHXAycQvPaxKitBw4GfmxhrSp4s+L8cQhwPHACzZ23h41gjSuo75LzSBnI/HUgzX1T59O8h322NzzeA1w/y22MHQPphkXApcCVwNLt+P4VNBcHOvdDYCDd0gPOotkTLJvG8z8YPPf1UQ5VMwPprqU0e5VTgUNp/vO532jeEPUW8DSwmg7uNSYzECnwbl5phgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxkuB5wOnA/sAZYB/wFfA+8AdwOLC02nVrTG/bFfr/f9hw1OQVYCRw9jee+PHjuS0Cn/9Lmg15vag4GslmPZs9wy3Z876fAA8CjwHdzOZTaYyDZSuC6WW6jD6wGngFeAL6a5fbUIgPZtsuBh0aw3U+AV4F3gHeBz0awhuaIgQy3N/AFsGcLa60DXgceB54FNrWwpqZpWCBexYJraScOgH2AC4AngY+BM1taV9vJPUhznnBAwfVvA5YXXF8D7kGmOoSycUBz5cxAKtX1QA4vPcDALcC5pYfQVF0PZK/SA0xyH7Bj6SG0pa4HsrH0AJMsBi4rPYS21PVAanvV+/LSA2hLXb+KtTvNaxMTpQcZ2AjsQl17ts7wKtZUv9C80l2LhcBBpYfQZl0PBODe0gNsZefSA2gzA2luKnyt9BCTeHhVka6fg/xnf+A9YN/Cc/SBPYBfC8/RSZ6DbNu3wDKaE/aSPsI4qmIgm60BjqO5Lb2UpwqurSE8xJpqAXAJcBNwRIvr/klzBev7FtfUJB5iTc8/wCrgSOAM4Hnaeb/5CoyjOu5BpmcJcCXNnmXxCLb/CnA28PcItq1p8h2Fs7cAOInmnqkLmZs3Wq0GzsOT8+IMZG5NACfS/OY/Gzhqht//N3AXcCu+9lEFAxmtRcDJwPGDxzEMv319PfAEcDfweWvT6X8ZSLt2pDnRXwLsBPxGE8RaPNeokoFIgZd5pRkyECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECn4F109/5jz2BfBAAAAAElFTkSuQmCC)}42.86%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAGGklEQVR4nO3dR4hdVRzH8e/EKLZNrFhAsxAxlgQLBOwLRbAgiBtBEQyxFxCN2FYq6kKwRiSCKLoJLiIKRhciKgQbCZaQuFBh1KjRIFgGS8bFNTDI8HPie/fc9879frZ5c/5n8+Xcm7n3zcT09DSSZjev6w1Io8xApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApMBApGB+1xtQUQuBC4ATgEOAXYAfgY+B14F3gO2d7W4ETfhHPHvhOOAB4Jz/+Nxm4B7geQwFMJA+uBW4j+a0mKsNwApgbSs7GiMGUreHgRsG+PlXgOuBz4eznfHjTXq9rmOwOADOBT4F7gJ2HXhHY8gTpE6HAxuB3Ye45gbgcmD9ENcceZ4gdbqT4cYBsBh4j+Y02Zn7mbHmCVKfvYHvGX4gM70FXAJMtjhjJHiC1OcM2o0D4FSaS61TWp7TOQOpz5JCc/YFXgOWFprXCQOpz34FZ+0BvAgsKDizKAPRoA4G7u16E20xkPp818HMZZQ9uYoxkPp08XuKXYGLO5jbOgOpz5vALx3MPbODma0zkPr8AjzXwdwjO5jZOn9RWKdDgU3AngVnfknziEtVPEHqNMngDyrurKnC84owkHo9TfOSVClVPhJvIHW7jeZ9jt8LzFpXYEZxBlK/x4BjgZdbnrO65fU7YSD9sBk4HzgN+KCF9dfSvFhVHf8Xq3/mActp3lMfxjNUvwPHA58MYa2R4wnSP9uBJ4FFwJohrHcTlcYBBtJnW4ALgSuB3/7nGrcBK4e2oxHkJZYAjgKeBU6c4+e/pblMe6m1HY0IA9EO82geOLyW5k3BiVk+8xmwCngC+Lnc1rpjIJrNApqvJz2I5gsatgIf0TxO0isGIgXepEuBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUjB/K430JHDgGOB/YC/gG+AD4BtXW5Ko6dPgewNXAMsA46Y5d+ngbeBx4HVwPZyW9Oompienu56DyVcADwFHDjHz78PXAZsbG1HGgt9uAdZAaxh7nEAnEhzybW8lR1pbNR+glwNPDHgGmuAq4Atg29H46bmQI4GPgR2G8Ja24DbaS7TvDfpkZovsR5iOHEALABWAu8Cpw5pTY2BWk+QRcAnLa7/MnAzsLnFGRoBtZ4gF7e8/nnAR8B1Lc9Rx2oNZGmBGbsBjwL3F5iljtQayMKCs1YAVxScp4JqvQf5guZxklJ+BY4EJgvOVAG1niA/FZ63J3BH4ZkqoNZANnUw81Jgrw7mqkW1BvJGBzP3Ak7vYK5aVGsgq4E/Opi7pIOZalGtgWwFVnUw94AOZqpFtQYCzU3z111vQuOt5kC2ARcBvxWcubXgLBVQcyAA64CzgR8KzVtfaI4KqfUXhf92KPAC7T6JOwXsD/zc4gwVVvsJssMkcCZwN/BnSzOexziq05cTZKYlwDPA4iGuOQUcRfOIiyrSlxNkpvXASTSnydSQ1rwF46hSH0+QmRbSPLJ+7gBrPALcOJztaNT08QSZ6XOal5/OATbs5M/+RfOou3FUrO+B7LAWOJ7mu7Dm8hrtq/98/sE2N6Xu9f0SazbzgJOBs4BjgH1oTouvaL4r6yWak0c9YCBS4CWWFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFBiIFPwNh2DX1pOZxIQAAAAASUVORK5CYII=)}44.9%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAF2klEQVR4nO3cT4iVVRyH8WfKJq0gECSULMEgAqEIgjYRGmhgFmGhgbRQ2hltCvsnZWUotEtoESmEkDsJE8KFokFEgRUIEmRoRhaKkJilZLfFOzemYfo6f95zr+fyfEBEmPd3juDjed9778xQp9NB0viu6fcGpKuZgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUiBgUjBjH5vQFe9a4GlwHLgHmAezX+sp4FvgX3Ax8DFfm2wpKFOp9PvPejqtQrYDCy8wtedBt4A3gMul95ULxmIxnMD8AGwepLXHQSeAM60vqM+MRCNNQx8Ciye4vVHgCU0p0r1fEjXWNuYehwAi4D9wJx2ttNfniAabTHNP+42DMRJYiAa7RDwQIvzDgMPAudbnNlTBqKuhcD3BebuA1YAlwrMLs5nEHUtKzR3Kc3Lv1UyEHUtKjh7LfB0wfnFGIi6bik8/x3gxsJrtM5A1FX6GWEOsKbwGq0zEHWd6sEak31nvu8MRF1f9WCN+2k+/FgNX+ZV12yaU2S48DrzgZ8Kr9EaTxB1nQU+6sE61/VgjdZ4gmi024GjwKyCa8yjN887rfAE0WgngPUF558Hfik4v3UGorG2A68Xmn0IqOqWxUA0nk3A1gJzdxWYWZTPIEq2ABtamnUcuJPKPrToCaLkJWBHS7PWU1kcYCDKOsAzwJ5pznkb2Dv97fSegehKLtN8RGT3FK9/C3ilve30loFoIi4AK4HngHMTvOZH4FFgY6lN9YIP6Zqs2cA64EngXv772aqLwOfAzpFf1T1zjGUgmo6ZwIKR338DTgJ/9XNDbTMQKfAZRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRAoMRApm9HsDBcwA5gM3A38Cx0d+lyZtUE6QYWAtsB84D/wAfA0cHfnzl8ALwOx+bVB1Gup0Ov3ew3StALYBt03ga88BG4F3ger/4iqv9kDeBF6dwnW7gTXAhXa3o0FTcyCbgZencf0e4HHgcjvb0SCqNZDlwCctzNkBrMPbLf2PGgMZBr4DFrQ0byvwYkuzNGBqfBVrFe3FAbAB2NLiPA2QGgNZXWDmBuC1AnNVudpusYZoXqq9qdD8dcD2QrNVodoCmQv8XHD+H8BdwImCa6gitd1izSw8fxawqfAaqkhtJ8itwMnCa1yiOanOFl5HFajtBDlF+Q8eDgPLCq+hStQWyGXgix6sc18P1lAFagsEYFcP1pjbgzVUgRoD2QmcLrzGcOH5qkSNgfwOPF94jV8Lz1clagwE4EPKvqF3pOBsVaS2l3lHG6b5yPrSArPvAI4VmKvK1HqCQPN+xUrgcMtzP8M4NKLmQKD5fvOHafeWyA8t6l+1BwLNK1pLaCeS94EDLczRgKj5GWSsOTQ/1WTRFK8/QHMaXWptR6reIJwgXaeBxcDBKVy7C3gE49AYgxQIwBngIeBZJvZm4jGab8B6Cn/CicYxSLdYY10PPEbzMvDdNLdgf9N8P8k3wF5gH/5UEwWDHIg0bYN2iyW1ykCkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECk4B9ond6XzYmBagAAAABJRU5ErkJggg==)}46.94%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAFj0lEQVR4nO3dS6iUZQCH8eeY6EKiCFuVKWUYZkVRBNXpAkEZQVBQdCHIRUREUuQyirZFF4qWYdFlEQVtilzYRYnACKyUIpM8JgRpGNFCJafFlxuTfzPf977Od2ae30rwzJ93cZ4zl2/OmZnBYICkE1sw7gNIfWYgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUrBw3AfQRJkF7gCuApYDi4E/gB+AT4B3gJ/Hdbg2ZgaDwbjPoPnvGuAF4PL/+boB8BawAfi19qFKMBB1MQM8CTz977+HdQC4E9hc4UxFGYi6eBFY3/K2R4BbgU3ljlOegait+4HXO24cBC4B5rofpw4DURtLgR+B0wtsfQTcUmCnCl/mVRuPUiYOgLXATYW2ivMeRKOaAfYAywpufkfzUOtowc0ivAfRqFZRNg6ANcC9hTeLMBCN6sJKuxsq7XZiIBrVqZV2LwJWV9puzUA0qppPWmcrbrdiIBrVvorb51XcbsVANKqvqfdq0+JKu60ZiEb1O/B5pe3DlXZbMxC18Uql3V2VdlszELXxPrCtwu6WCpudGIjaGACPF978BthZeLMzA1FbW4EPCu49V3CrGN+LpS7OpfnJv6TjzhbgOupeY2nFexB1sRt4gG7f2PuAezpuVGMg6updYB3NbwiOag64Efil6IkKMhCVsBG4Gtgxwm3eBi4Fvq9xoFJ8DqKSTqH5sz/rgOv575Xx/TRP7F+luSLfewaiWhYBK4Ezad6aspd59jexwECkyOcgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUrBw3AdoaQWwjCbw34BdwOFxHkiTaT4FchnwMHAbsPS4/zsEfAq8BrwH/H1ST6aJNR8+YeoM4GWajwoexg6ajybeVu1Emhp9D+QC4GPgnBFvdwR4kObTV6XW+hzI2cCXwFktbz8A7qL5HG+plb4GMgN8Bsx23PkLuBjY3flEmkp9fZn3PrrHAbAEeL7AjqZUX+9BttP85C9lFthacE9Too+BrKZ5JaqkbcCVNM9LpKH18SFWiYdWx7sCuL3CriZcHwNZWWn3kUq7mmB9DGRRpd1raS46SkPrYyCHKu0uoHm7ijS0PgbyU8XtthcdNaX6GMiWitszFbc1gfoYyE7g20rbf1ba1YTqYyAAz1baLX19RROujxcKoQl3O7Cm4OZeYDleLNQI+noPchR4ovDmRoxDI+rrPcgxHwJrC+wcBM4H9hfY0hTp6z3IMQ/RfHN3tR7jUAt9D2SO5peejnTYeAl4o8xxNG36HgjAJuBm4MCItxsATwGPFT+RpsZ8CARgM80rWm8y3BPtr2jee/XMkF8vnVDfn6SfyArgbuAGYBVwGs37t/YAX9D82Z+aV+M1ReZjINJJM18eYkljYSBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBS8A9jir92v7sBgwAAAABJRU5ErkJggg==)}48.98%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAFI0lEQVR4nO3dUcjv9xzA8feDjpYxa4uSudiWJMWFVrhU3K415hTKhZhIaFeSG3dKSHHngmKmkztZrtQoXFhJ0qzFUtZOzKxFnMfFr2md9Nlznv/vd/5/53m9bs/5f/qeet7n+///f7/f9ykAAAAAAAAAAAAAAAAA4Np3dHx8vO81wMF60b4XAIdMIDAQCAwEAgOBwEAgMBAIDAQCA4HAQCAwEAgMBAIDgcBAIDAQCAwEAgOBwEAgMBAIDAQCA4HAQCAwEAgMBAIDgcBAIDAQCAwEAgOBwEAgMBAIDAQCA4HAQCAwEAgMBAIDgcBAIDAQCAwEAgOBwEAgMBAIDAQCA4HAQCAwEAgMBAIDgcBAIDAQCAwEAgOBwEAgMHjJvhfAmXJj9frquurZ6pHq4l5X9AIEwtZuru6t3le98X/8+W+r+6uvVU9exXWdyNHx8fG+18C16aj6RPWF6uUn+PvPVJ+rvlwdzA+lQNjCuerb1XtO8doL1fnqn6uu6JQEwtqOWt4ynSaO51yo7u4AdhLfYrG2j7VbHFV3VZ9aYS07s4Owppuq31c3rDDr79Vt1RMrzDo1Owhr+kjrxFF1ffXRlWadmkBY03tXnnd+5XlXzFss1vKK6qkN5t5SPb7B3BOxg7CW2zaa+7aN5p6IQFjLWp89Lnf7RnNPRCCs5a8bzX3pRnNPRCCs5dG2ubC31yvqAmEtf6t+vcHcRzeYeWICYU0PbjDzoQ1mnphAWNP9K8/7afXHlWdeEYGwpl9UP1lx3hdXnHUqLhSytjdXv2z3h/EerN69+3J2YwdhbQ+3PCi1iz9UH1xhLTsTCFv4RvWZ6tIpXvtI9c7qz6uu6JQEwla+1PIW6bEreM23qjtaIjkIPoOwtXPVB6oPtdxXdfl/yherH7Qc2vCrq7u0FyYQrqaXVW9oOcTh39Wf2u4K/CoEAgOfQWAgEBgIBAYCgYFAYHDoh1cfVbdWr6leXD3dctjxM/tcFGfHoQbylurj1Z0th5E936XqZ9U3W668HsQZrlybDu06yI3VV1quvJ7EY9WHqx9vtSDOtkMK5Pbqh135KRaXqvta7v2BVR1KIK+ufl69bocZ97bcRQqrOZRAflS9a8cZ/6re2vI8AqziEL7mvbPd46jlC4evrjAH/usQdpCHqrevOO+OlmejYWf73kFuad04qu5ZeR5n2L4DeccGM9d4uwbV/gO5dYOZb2o5ih92tu9Azm0w87nbU2Bn+w7kHxvNfeVGczlj9h3IVqdXbPGbjjiD9v0172vb5uzVG1pOG4ed7HsHebzl9vU1PZw4WMm+A6n6zsrzvrfyPM6wfb/FqnpVyy+fv36FWU+1/DLJiyvMgoPYQZ6oPr/SrM8mDlZ0CDtILdcuvl/dtcOMB1puMzmIfxDXhkPYQWr5oT5fXTjl6x+o3p84WNmhBFLLs+V3V5/u5IcyPF19smXn8Gw6qzuUt1iXu7nl0IZ7Wg47vtxvqu9WX6+evIrr4ow51ECe76aW59Svq56tflf9Za8r4sz4fwgE9uaQPoPAwREIDAQCA4HAQCAwEAgMBAIDgcBAIDAQCAwEAgOBwEAgMBAIDAQCA4HAQCAwEAgMBAIDgcBAIDAQCAwEAgOBwEAgMBAIDAQCA4HAQCAwEAgMBAIDgcBAIDAQCAwEAgOBwEAgMBAIDAQCA4HAQCAwEAgMBAIDgcBAIDAQCAwEAgOBwEAgMBAIDAQCA4HAQCAwEAgAAAAAAAAAAAAAAAAAAGfcfwCQI7TGlZBEdwAAAABJRU5ErkJggg==)}51.02%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAEjUlEQVR4nO3cTYydUxzH8V+rKkUbjSYoCyKIsJAQC1ILJBJWiJdgISFNpTY2Nt4W2FixKxErBAlWGpaIjaQ7qdAIG9omraq3omosnpJq9O/eO+eZc/H5JLOYzDz/nNzkOzPPfc6ZBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4V1q2sLDQew0wt5b3XgDMM4FAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBhRe8F8L91yuGP75Ps6byWY5rHQFYnuT7JlUnOOfz5viSfJXkvyTtJfu62Oma1IsmNSe5IsiHJqUd87bskHyR5LckrSQ4s+eqOYdnCwkLvNfxhbZJHk2xMcmLxfV8neSbJU0l+WoJ1sXhXJ9mS5LwJvndnkgeSvDrqiiY0L4FsyPCCnDHFNZ8kuSnJ9lFWRCsPJXk8ybIpr9uS5P4kh5qvaArzEMgNSd5McvwM1+5Pck2SbU1XRCsPZ4hjVi8kuafRWmbSO5CLk3yYZNUiZuxOckmSXU1WRCvXJXm7wZxNSZ5tMGcmPQNZniGOSxvMeiPJzQ3m0MbKDH8Cn91g1rdJzk2nd7p6Pge5JW3iSIZ7kcsazWLxbkubOJJkTZLNjWZNrWcg9zaet7HxPGZ3V+N5dzaeN7Fef2KdlOHZxiw35sfyZZKzGs5jNsdleK6xmPvKv7M+w1vAS6rXb5AL0zaOJDkzf334RB/r0z6OJDl/hJn/qFcgp48097SR5jK5sX5IrR1pbqlXIGNtcVk50lwm98tIc38daW6pVyD7Rpq7d6S5TG73SHO7POfqFcinI8w8kOSrEeYynb0Z3jBp6WCSjxvPnEivQHYm2dF45vvpvG+HP21tPO/dJD80njmRns9BXmo878XG85jdc43nPd943sR6bjVZl+GMx5oGs75IckHGu0Fkeq9n2OGwWNuSXJ7ktwazptbzN8ieJA82mrUp4pg3m7P4G/YDSe5OpziS/mfSn82wpXkxHslwypD5sivDUYb9M15/MMN+vY+arWgGvQNJhj1UW2a4biHDeYMn2i6HhrYluSLDzt5p7Mxwzuet5iua0jwEcijJfUluz+R7bXYkuTbJk2Mtima2Zziv81iG49KVH5M8neSiDO9Kdtf7wNTRVmUI5dYM/7Rh9RFf25vhRXs5wwnELk9WWZQTMhykuirDGY+1GTY2fp7hnzZsPfz53Ji3QI62LsnJSb45/AFLat4Dga7m4R4E5pZAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkCgIBAoCAQKAoGCQKAgECgIBAoCgYJAoCAQKAgECgKBgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPjv+R02e5WvOhUGtgAAAABJRU5ErkJggg==)}53.06%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAFEElEQVR4nO3dTehlcxzH8c8wiIXyEAkRIrKgmISQsCDJUvKwsNJEQllLUh6ahZqlLGRhYeNhYSJCoqZRIjKiIZkIG0/D/C3O0Bj5/u//3t/vf47u67Wcmfvtt3nPuefcc34nAQAAAAAAAAAAAAAAAACApbZhZWVl7DXAZB009gJgygQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAKFjWMvYAanJjkxySFJvk/ySZKfx1wQy2OqgZybZHOSG5Mcd8Df/ZHkzSRPJ3kmyW/ruzSWyYaVlZWx17C/I5NsSXJ7kg0z/PvPktyR5LWOa2KJTSmQk5JsS3LWGj+3N8n9SZ5oviKW3lQCOTbJO0lOX2DGnUm2tlkODKYSyItJrl1wxp4km5LsWHw5MJjCZd7rs3gcyXCVa0uDOfC3KQRyX8NZl2c4ikATYwdyQpLLGs+8qfE8ltjYgVzZYealHWaypMYO5MIOMxe5Egb/MHYgJ3eYeVSHmSypsQM5uMPM7zrMZEmNHchPHWZ+2mEmS2rsQD7sMPOdDjNZUmMH8mqHma90mMmSGvtWk4OSfJzkjEbzvslw4r+n0TyW3NhHkL1JHmo475GIg4bGPoIkw3Mf27L4j4bvJbk4ye8Lrwj2mUIgyfDU4NuZ/0e+r5JckuSLZiuCjP8V6y+7k1yRZPscn/0ow/1c4qC5qQSSJF9m+Ir0YGbblGFPkseTXJDh0VtobipfsQ50bJJbklyX5PwkR+/78x+TvJ/k5QybNnw9yupYGlMN5ECHZdjNxAk46+r/EgiMYkrnIDA5AoGCQKAgEMawMcOFl8kTCOvhhCQPJHk9yQ8ZfsP6JcPDbduS3JPh0v7kuIpFT0dk+OH3rgz7llV+TvJokoeT/Np5XTMTCL2cluSFJGev8XPbk9yQ4c6K0QmEHk5J8laG97rMY2eG2452N1vRnJyD0NrGJM9l/jiS4a7uZzPbKzC6EgitbU6b/c6uTHJrgzkL8RWLlg5JsivJ8Y3mfZrhfTF7G81bM0cQWrom7eJIhr0KLmo4b80EQktXd5jZY//mmQmElnr8b39Oh5kzEwgttdq+aX9HdJg5M4HQ0jEdZv7RYebMBEJL33eYuavDzJkJhJZ2dpj5XoeZMxMILb3ZYWaP/ZtnJhBaerbxvDcy8s41AqGldzM889HKYw1nzcWtJrR2XoZQVnv+YzUvZdgXbVSOILS2I8ndC87YmeS2BmtZmEDoYWuSezPfTYYfZ9in+duWC5qXQOjliSRXZfZ9k1eSPJVkUybyNGHiHIT+Dk1yc4avTJfm32823p3k+SRPJvlgfZe2OoGwng5PcmaGd9nvyfBel8/HXNBqBAIF5yBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCBQEAgWBQEEgUBAIFAQCBYFAQSBQEAgUBAIFgUBBIFAQCAAAAAAAAAAAAAAAAAAAAP/lTwgpqTr0JDXaAAAAAElFTkSuQmCC)}55.1%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAFcUlEQVR4nO3dTYhVZRzH8e+ovRtI0iqDIimIXoggDIKyIgqtQFopUZugrIhq5SasRa5Kooi2QYWLiDKsFsLUKpe9GWUJQeqiqKy0stTb4kwUIT9mznke7zNzv5/VwMz58wzcr889Z871TI1GIySd2KJxL0BqmYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIgYFIwZJxL6Cn84FLgeXAH8A+4JOZr6Vi5lMgy4CNwD3AxSf4/hHgXeA54P2TtywtZFOj0Wjca5iN9cDzwDmz/PntwH3Ad9VWpIkwHwJ5Fni0x3H7gFuB3WWXo0nSeiBPAE8OOP4AcA2wv8xyNGlaDuR6YBqYGjhnGrgJaPYXVbtavcy7CHiB4XEArAbWFZijCdRqIOuBywrOe7zgLE2QFt9iLQa+BC4qPHcFnotojlrcQdZSPg6AayvM1ALXYiB3VZpbIzotcC0GsqrS3DMqzdUC1mIgF1Sae7DSXC1gLQZS6/6wryvN1QLW4lWsX4GlhWceBc7FXURz1OIO8kWFme9gHOqhxUCmK8zcUmGmJkCLgbxaeN4OYFfhmZoQLQbyMd2LuoTjwKZCszSBWgwE4GHgUIE5W4FPC8zRhGrxKtY/1tB9MrBvxDtnZvxZbEWaOK3uINC9zVoHHO5x7NvAnRiHBmo5EIC3gKvodoPZ+AF4kC6O32otSpOj5bdY/7cKuBe4EVjJvx+m+pnuKtWbwCuUOXeRgPkVyH+dApwFHKP7y7tUxXwNRDopWj8HkcbKQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKRgybgXoAXvbGAx3ZPC/hrzWubMHUSlLQXuB94DDgK/AD8BR4A9wEt0D0OaF3w+iEqZAh4AngKWz+LndwIbga9qLmooA1EJZwLbgNvneNxhYAPdsyibZCAa6lS6JxLf3PP448AdMzOa4zmIhnqa/nFA9xrcBlxYZjlluYNoiMuBjyjzD+0OYG2BOUW5g2iILZR7Da0Briw0qxgDUV+r6F7UJW0oPG8wA1FfmyrMXF1h5iCeg6iPZcD3lL8T4xDdX96b4Q6iPq6jzm1KSyvMHMRA1MfKSnOPVprbm4Goj2WV5n5TaW5vBqI+fq80d1elub0ZiPrYW2nu65Xm9uZVLPVxHrCv8My9wCXAscJzB3EHUR/7gQ8Lz9xMY3GAgai/ZwrO+gx4reC8YgxEfb0BTBeYMwIeorvtvTkGor5GwN3AgYFzNgMfDF5NJQaiIfYDt9D/hH0r3Ud0m2UgGmo3cDWwfQ7H/Eh35+5jVVZUkJd5VdINwCPAbcBpJ/j+HuBl4EW6//GkeQaiGk4HrgBWzHz9A/A58O04F9WHgUiB5yBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBS8DeemLYlPdyJCQAAAABJRU5ErkJggg==)}57.14%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAFlElEQVR4nO3cP6iVZQDH8e81DScdUgqHhCChoD9CNBRZWqaJ/YGWnNJC3BpqyWyREhuaWqIacmhQyBIKTUyioUCJJISEwv44iJYNGoig3NPwtnS493eP9z7POT2H72c+748HuV/e93jPuRO9Xg9JU5s36gNI/2cGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgXjGMgiYCvwCfAbcBn4G/gV+BTY9u9rpBlN9Hq9UZ+hlAXAy8B2YPEMr70EvAW8DVytfC41bFwCWQocAB64zuuOAU8D54ufSGNhHAJZCnwN3DHL638CHgQuFDuRxkbr70EWA4eZfRwAK4B9wESRE2mstBzIjcB+YGWBrTXACwV2NGZafsT6ENhccO934DZgsuCmGtfqHeQVysYBsBxYVXhTjWsxkDuB3ZW2H620q0a1GMibdL/zqGEub/Y1hloLZBnwTMX9JRW31aDWAtlA3f+O9bfq+o/WArmv8v6ZyvtqTGuB3FJ5/3jlfTWmtUDmV9yeBD6ruK8GtRbIXxW39wNnK+6rQa0FcrLS7hVgR6VtNay1QA5X2n0J+LnSthrWWiAnKf9GejfwQeFNjYkWP6y4HjhUaGsP3ad4m/tH0HC0dgcB+ILuB3uujtB9P904NK0W7yAAC4GDwOpZXn8cWEv33XRpWi3eQaD7X6eNwN5ZXPs58DjGoQG0Ggh0f85nE/AccHqA158BtgBPARcrnktjpNVHrH7zgMfoPsy4ku4jKRN0f63kB7o39YeBa6M6oNo0LoFIVbT8iCVVZyBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSYCBSMH/UB1CT5gPrgCeAe4CbgR5wDjgBHAS+BCZHdcBSJnq93qjPoHZMAM8DO4FbZ3jtaWAHsK/2oWoyEA1qMfARsPE6r9sLvAhcLn6iITAQDWIRcAS4f5bXfwVsAK4UO9GQ+CZdM7kR+JjZxwGwGni3zHGGy0CUTADvAWsLbG0G1hfYGSoDUbKL7ge7lJ0Ft4bC9yCazlbg/Qq7dwMnK+xW4R1EU7kdeKfS9rpKu1UYiKayC1hYafuuSrtVGIj6LQOerbh/U8Xt4gxE/Z6k7s/FtYrbxRmI+s3l9x2DOFd5vygDUb+ZPmM1V99V3i/KQNRvQcXtHt0nfZthIOp3oeL2AeBsxf3iDET9TlXavQq8Xmm7GgNRv6OVdrcDP1barsaPmqjfPOAXYHnBzT3AloJ7Q+MdRP0mgTcK7h0FthXcGyrvIJrKBN13ytfMcecE3XdBLs75RCNiIJrOEuAbYMUsrz8FPAz8WexEI+AjlqZzAVgFHJvFtd8yBnGAgSg7DzwEvAZcGuD1F4FXgUcYgzjARywNbhGwie5rs/fSPYLdAPwBfA8covsTP4OE1AwDkQIfsaTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTgH82MsyJpg53RAAAAAElFTkSuQmCC)}59.18%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAFz0lEQVR4nO3dS6hVVRzH8a9pmdKkN2VEJUlRYhSGI4lsUoFJDaJCKirpQUTmwIJqGkRBI0mCsrKQJtagcCCVNIhedDGIDC1CC/LRpCzzcRvsBAfxy+vde5191/5+xves/wLv17X3OWfrtPHxcST9t5NGvQGpzwxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgxECgykMR94HvgC+AMYBw4C24H1wK3AjJHtTiMzbeD/DfRc4EVg6XH87A7gCWBjpztSrww1kJOBJ4GngJkTfO0a4FHgcNubUv8MMZCrgNeABZNY4w3gbppLMVVsSPcg04Gngc+ZXBwAy4GVk96Rem8oJ8j5wNvA4hbX/BOYB+xscU31zBBOkBuAMdqNA2AWsKrlNdUztZ8gtwNv0t1btHuBc/GGvVo1nyCLaG6mu/z84kwmfz+jHqs1kFOAdTRv53bt8gIzNCK1BnIvzQ10CWcVmqMRqDWQhwrOOlBwlgqrMZA5lL0v2FFwlgqrMZCrC846AnxZcJ4KqzGQ8wrO2kLzVq8qVWMgJT+TeKngLI1AjYHsKzTnI+DdQrM0IjUGMlZgxm78Nu8g1BjIDuC7DtffDSwBfupwhnqixkAAXulo3U+Aa4GtHa2vnqn1y4qzgW00n4m04TdgNU14R1paU1NArSfIfuA+2vllfp/mH3VY29J6mkJqDQRgE/DIJF7/F7ACuBnY1cqONOXUeol1rLto/vafPYHXfAPcifcag1fzCXLUeuAKYAP/f4m0j+a59YUYhxjGCXKsOcAymoepLgZOA34Fvgc2Ax/QPGsuAcMLRJqQIVxiSSfMQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKRgxqg3oN6ZBdwILAEuBc4Bfgd+AD4FNgK7Rra7wqaNj4+Peg/qh1OBVcDjwBnh544A7wCrgR+739ZoGYgA5gNvAVdO4DX7gRXA+k521BPeg+gB4DMmFgfAbOBN4MHWd9QjniDDNQdYC9w0yXWO/LvGpknvqIcMZHhOAu4HngNOb2nNXcA8msuuqniJNSwXAR8DL9NeHNCcRg+3uF5veIIMx3xgM3B2R+t/B1zW0dojYyDDcCHwBd3FcdRcYEfHM4ryEqt+04B1dB8HwIICM4oykPrdAlxXaFb6gHFKMpD6PVZw1vSCs4owkLqdCSwuOO+XgrOKMJC6XUPZP+OvCs4qwkDqdknBWWNU+C1fA6nbzIKz1hScVYyB1G1PoTnbgFcLzSrKQOr2bYEZB4G7gb8LzCrOQOo2BuztcP1DwHKaJw2rZCB1O0zzzEYX9tA8mruho/V7we9i1e8CmnuEWS2uuQW4A/i5xTV7yROkfjuBp1ta6xDwDHA9A4gDPEGG4ugXFpdPYo0x4B7g6zY2NFV4ggzDOHAvJ/ZZxQHgWWAhA4sDPEGGaBnwAsf3Kft7wEpge6c76jEDGaYZwFLgNmARzQNVM2ieKf8W+BB4Hdg6qg32hYFIgfcgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUmAgUvAPsjfNuCouGV8AAAAASUVORK5CYII=)}61.22%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAGJ0lEQVR4nO3dS6ycYxzH8e9ohaJxSxA0VCghomrhGkmxkIqSYCG1UNcVQiIS1iRICFbiUhFCgkTQpotKE4nbAmmki5ZUmyJ0IaQocRmL14Kcc35nru/zzrzfz3Iy8/6fnJPvmXnnfeZMh1l0u93ZbpamWqfTmXHbfgXWIU0MA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5ECA5GChaUXMEWOBVYAS6j+8HwHbAG+LLkoDcdABrcQuBBYBVwBnDHH/XYAzwFPAj/XszSNysxvDMEv0Ak6wMXADcB1wKF9PPZ74Fbg7TGsSyMw2xfoGEhvTgbWAmuAE4Y81n3AI0OvSCNnIP27BLib6iXUrD+rAd0GPDPC42kEDKQ3C6ieKe4BzhrTjN//Pfa2MR1fAzCQ+a0AXgDOrGHWW8BVNcxRjwwkWw28CiyqaV6X6txmR03zNA+/5XZuK4HXqS8OqP44XVPjPA3AQOAw4BVg/wKzzy8wU30wEHgAOLrQ7CWF5qpHbQ/kYOD2gvNLPGupD20P5HJgccH5vxScrR60PZALCs/3OkjDtT2QYbeNDOvdwvM1j7YHUnI3889UFwvVYG0P5LeCs58A9hacrx60PZDtheZ+ATxUaLb60PZANheY+QNwNfBrgdnqU9v3Yi0AvqK+C3ZfU+35+qymeeqDe7Fm+gt4tIY5XWAdsBzjmChtfwaB6p2sj4BzxnDsrVTvVK2jOu9Qg7ndfW4nAh8DRw15nC7Vec0bwAZg55DHU40MJFsGbASWDvDYbcDzwMvAN6NclOpjIPM7jOqcZC3VCfx8NgGPUYXV2h/atDCQ3i0DbqH6Zw2n8f83M74A1gPPUp1jaEoYyGAOpDo36QB7gH1ll6NxMRAp8DqI1CcDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkQIDkYKFpReg2i0CjgK6wB7gt7LLaTafQdrhDOBxYDvwK7AT2AX8AmwFHgGWlVpck3Vmu7Hb7da9Do1eB7gcuAe4rIf7/wWsA+4Ffhzjuhqr05mZg4FMn+OANcBNwKkDPP4rqrC2j3JRk8BApteJwCrgGmAlc/xe+7AHOJfqpVhrGMh0OQVYC6ymOscYtU+A84A/x3DsRjKQ6XAk8ChwI8M/U8znTuCpMc9oDAOZfGcDbwHH1zRvN7CU6gR+6s0WiG/zTo7TgU3UFwfAEuDiGuc1joFMhoOAN4EjCsxeWWBmYxjIZLif6qS8hFZfQDSQ5lsM3FVw/oEFZxdnIM23Gjik4PzWvM07GwNpvksLz99VeH5RBtJ8g2wXGaUPCs8vykCa7+CCs/cCGwvOL85Amu+PgrOfptoS31oG0ny7C839Hniw0OzGMJDm+7DAzD+A62np50L+y0Ca7w2qj8fWZR9wLbC5xpmNZSDNtwN4u6ZZnwMXUW2IFO7mnRSnAluAA8Z0/C3AY8DLtGTn7mzczTu5tgF3jPiYXeAdqguRy4EXaXEcc/Hf/kyOZ4DDgYeHPM4uqmeKdcCXwy5q2vkSa/JcSRXL0X085ifgNeAl4D3qPemfGH6icHocQvVx2JuBk+a4z1ZgPbABeJ+WbzrshYFMp5OBs4BjgL+pLix+CnxbclGTyECkwHexpD4ZiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBT8AxkU4lnlgRK5AAAAAElFTkSuQmCC)}63.27%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAGCUlEQVR4nO3dzYtVdQCH8WfUShNb5AtElqVWQ4mF0LtG7cJeKAh6wYjQitpF9FeEtAxCCUMIoTcCoVZFWkmBi1Cx0speCHxpkZhWTtPiGOgw8+Ve597zu+fc5wOzEZnzxfFhzpx7zp0RajQ+Pl7n4dRSIyMjtR1rRm1HkhrIQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKRgVukBQ2omsABYCMwF5gDzzvz5/44DvwPfAH/WPVAVA+mfi4DrgZXAKLAMWApcSRVGp8aAz4A3gK3A6d7OVFLf+8jT+l9/sBi4G7jjzMcKzv2O0AvfAuuBnT3+vI1S568/MJDpewB4GVhT0/HGgBeA12s63sAxkGaYD2wB7it0/CepTrmGjoEMvsXAx8DyghtOAquA/QU3FOFvmBps84CPKBsHVFe+Nhbe0HoG0r1XqK5ODYK1DM6WVjKQ7owCG0qPmODR0gPazEC68zy9v3Q7XatLD2gzA+nOw6UHTGJJ6QFtZiCdWwRcUXrEJOaXHtBmBtK5y0sPmMKx0gPazEA6N7f0gCkcLD2gzQykc4dLD5jCjtID2sxX0js3i+oW9Nmlh0xwDXCg9Ig6+Ur6YDpNdXvJIHmXIYujbgbSnS2lB5zlBPBS6RFtZyDdeRvYW3oE8C+wDvix8I7WM5DujFHdalLyqb6/gSeA9wtuGBoG0r1dVLeclLAbuBXYVuj4Q8erWOdvHbCJ6tnzfjpBdXFgM/AB1enVUPOBqeYYBV4F7u3w7x8H9lC9uPcD8BtwBDgK/EMVw9n+AA5RndrpDANpnpXA48BdVO9eMhs4RRXCV8AXwJdUUWiaDEQKfKFQGhAGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgUGIgWzSg/QebkauAW4HbgZWAbMBk4BB4FPgbeAr0sNbIuROg82Pj5e5+GaYCawBLhkwp/PBS4AFgALgcuoolgGrADmdfj5PwReBPb3YuygGBmp77+tgdRvBvAgsB64hyqGfvoL2ABs7fNxamMg7XUTsBlYVeDYzwCbChy35wyknR4F3gQuLHT808AaYFeh4/eMgbTPQ8A7lL9quBe4ERgrvGNa6gyk9BdsGFxFdf4/CP/WNwCPlB7RJIPwRWu7jfT/B/FuPFV6QJN4itVfy4HvSo+Y4BTVZeLTpYecL0+x2uOx0gMmMRtYWnpEUxhIf60pPWAKi0oPaAoD6a9lpQdM4UTpAU1hIP01v/SAKfxaekBTGEh/HSs9YBI/A4dLj2gKA+mvQ6UHTOK90gOaxED6a2fpAROMAa+VHtEkBtJf20oPmGATLbv1vd98obD/tgNrS48A9gG3AcdLD5kub1Zsl1FgNzCn4IYDVM+e/FJwQ8/4Snq77AeeLXj87VTfOVoRR90MpB5bgeeo9zbzHVRPLt7PYF5ubgRPseq1muqJwmt7/HnHgD3A52c+PqHF3zH8GaTdZgHrgKeBO6neuKFTR4CfgO+p3r1kP9U7l+yjevZ8KBjI8LgYuA64lHPfqWSM6mrTSar7po4AR2n4k4C9YiBS4FUsaUAYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBQYiBT8B+ejz5IMYRU4AAAAAElFTkSuQmCC)}65.31%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAGaElEQVR4nO3dS4hVdQDH8e9MRfaytDfZQzTRgoogekIPyqiIym0UBLUQqpURFLQoCqIWQUGLIqLAXYVERW+llxGURalYUZZRaWrZG9NpcSZGhpnfzGnuuf9z73w/MBtx5v4Y/c65M/ecMwNM0dDQ0FQ/hNSYgYGBKb3/YId2SH3JQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKTAQKRg79IDprnjgGOBfYCZjHzB2g3sAP4A/gK2AD8O/7m6yEC67yTgZuAa4Kga77cL2AxsAjYC60a9/d3ZmQKY2r3h8dcf1HAQ8CBwEx34vI/yD/AJ8AHwNrCSKqRpb6q//sBAumMO8DLV0aNbNgAvAS8CbwI7u/jYrWEg7TcLWA0sKLhhO/AC8DTwGtPoexkDab9ngCWlR+xhDXAr8FbpId3gb5hqt0toVxwApwGrgDtKD+kFBtKs20oPGMcAcC9wd+khbedTrOYcRvXaRdu/CF0NrCg9oik+xWqvc+iNz++jwAGlR7RVL/wD9qp5pQdM0tHAjaVHtJWBNOfg0gNquL70gLYykOZsLz2ghtOBQ0qPaCMDac4XpQfUtLD0gDYykOasprdesT609IA2MpDmbAVeKT2iBs8GHoOBNOv+0gNq+Kr0gDYykGatBJaXHjEJWzGQMRlI85YCn5YeMYHn6K3vl7rGQJq3A7iI6izaNhoCHik9oq0MpDu2UJ168hDVpbNt8iTwcekRbeXJit03j5Fr0o8vvGU9cCbVUa4vecFUbzscmAvsD/zKyNFlP2AGMBs4AjiG6g4oi6he0DuwA4/9OdVTv76+dt1Apqf5VE/Zzh1+O7nm+z9LdfOIbR3e1ToGIqieql0FXAmcT3WfrdF2A69S3Vnlte5NK8tANNpM4Cyqo8yBwO/A18B7TIMjxmgGIgVeUSg1yECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkwECkYO/SA3rUbOBs4ATgAOA34AtgNbCj3Cx1moHUczGwDLiEsY++O4FVwPPACmBj96apCQNT/QBDQ0Od2NF2s4HHgCU13+8z4J3ht3epjjLqooGBqf0XN5CJzQHeAE7swMf6DVgPrAO+Ab4DNgPbgL+AP4f/3l7AQcAfwFfAlg489rRkIM2aCbwPLCy8YyPwHPAI8GXhLT3FQJr1BHBD6RF72AU8DNzByNFGgYE051TgIzrwOWrAGmAxPvWa0FQD8XWQ8d1CO+MAOI3q+6KZpYf0O48gYxuk+ub50NJDJrAcuLb0iDbzKVYz5tE7P5K9EFhZekRb+RSrGXNLD6jh9tID+pmBjG3f0gNqWEz7nwr2LAMZ29bSA2oYBM4qPaJfGcjY1pceUNP80gP6lYGM7Wfgw9IjaphVekC/MpDxPVV6QA2/lB7QrwxkfI8D35ceMUmen9UQAxnf78DS0iMmYTfVqfRqgIFkK4B7So+YwOvAT6VH9CsDmdhdwJ1AW08ZeKD0gH5mIJNzH3A+1Vm0bfIs8GrpEf3Mc7HqGaS6Lv064ArK/nh1A9ULhNsLbmg9T1YsZx+qEwUvBy4DFnTxsdcClwKbuviYPclA2mMOcAFwHnAGcAqdv2vMENXNI5YBv3b4Y/clA2mvfYFFo96OpwrpCKobM0zWD4xck762szP7m4H0pkHgSOBwYAawP9XVgf/90GQX1RFiJ/At1R1Q9D8YiBR4wZTUIAORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORAgORgn8BLyjxnaJDDwEAAAAASUVORK5CYII=)}67.35%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAHbUlEQVR4nO3daYxdZRnA8f+0BbpIopgqkVFQFi2lLLYsklgTFtlBGgPFSGKMlBgCERL9BCEEjAkmLiGEBIRAMCn6AVsWrVBJHEKDpSwFaqOojVqwBQUJIoW2M3x4UmhweGauc+5933vu//d5es6TZv495z3nvbdDY2NjSBrftNIDSDUzEClhIFLCQKSEgUgJA5ESBiIlDERKGIiUMBApYSBSwkCkhIFICQOREgYiJQxEShiIlDAQKWEgUsJApISBSAkDkRIGIiUMREoYiJQwEClhIFLCQKSEgUiJGaUH0KQsAE4C5gEfAbYBfwOeBtYDG4EdxaZrMQOp2znA1cBRE/zcW8CzwOPACPAw8NfujjYYhvz/Qaq0N3A7sGQKx/gj8GvgfuAhYPvUxxo8BlKffYhf7EUNHvPfwH3AT4HVwM4Gj91qBlKXacCDwAldPMcW4E7gZuBPXTxPKxhIXb4F/LCH53sA+BGwCvAXYRwGUo85xML6wwXOvQG4Dvg5MFrg/NXyPUg9vkyZOADmA8uJJ2FL8ffiHf5F1OOs0gMQ71mWA08R710GnoHU47OlB9jNAuJhwb3AwYVnKco1SD22AXuVHmIcbwLXAtczgO9SDKQe26l7Z8MG4OvA2tKD9JK3WPX4R+kBJjAfeAS4EpheeJaeMZB6PF16gEmYQdxujQDDhWfpCQOpx6rSA3TgeGAdsZhvNdcg9dgH+Dswu/QgHdhM7BnbWnqQbvEKUo+X6e02kyYMAzeVHqKbvILUZSbxlKjfbl2+QKxLWscrSF22AWcDz5cepEOXlh6gW7yC1GkYuBs4uvQgk/Q68CFa+CLRK0idNhNPiq4AXio8y2TMId6TtI5XkPrtCZwGnEjs1zoC+EDRicZ3JvHx3lYxkP4zBBxIxLKY2HX76aIThXOBFaWHaJqBtMMw8S/4UiKaoQIztPJJloG0z8eIUC4BPtXD884F/tnD8/WEgbTXNOAM4hHsyV0+11NM/N1dfcmnWO01Snzg6YvA54ivEuqWO7p47KK8ggyWxcAPgIUNHvN54lOHbzR4zGp4BRksI8AxwDLg1YaOuYyWxgEGMohGgVuAzzD1x7LfAX455YkqZiCDawvx7uIiYqtIJ3YClwHfb3qo2hiIfkLsHl45yZ9fAxwH3NC1iSriIl27OxS4gHjpdzAwi/hWk01EGD8DfldsugIMREp4iyUlDERKGIiUMBApYSBSwkCkhIFICQOREgYiJQxEShiIlDAQKWEgUsJApISBSAkDkRIGIiUMREoYiJQwEClhIFLCQKSEgUgJA5ESBiIlDERKGIiUMBApYSBSwkCkhIFICQOREgYiJQxEShiIlDAQKWEgUsJApISBSAkDkRIGIiUMREoYiJQwEClhIFLCQKSEgUgJA5ESBiIlDERKGIiUMBApYSBSwkCkhIFICQOREgYiJQxEShiIlDAQKWEgUsJApISBSAkDkRIGIiUMREoYiJQwEClhIFLCQKSEgUgJA5ESBiIlZpQeoIBjgfOB44FPAnsBbwDPAb8FlgO/LzadqjI0NjZWeoZeWQT8mAhjIiuBy4FNXZ1I1RuUW6xLgUeZXBwA5wDPAN/o2kTqC4NwBfk2cP0U/vwK4JvAlmbGUT9peyCnA/c3cJxXidBuBUYbOJ76RJsDmUUsvPdr8JiPA1cAIw0eUxVr8xrkYpqNA2Ah8aRrFXBcw8dWhdp8BXkSOLLL53gQuIG4jfPWq4XaGshc4MUenu8vwI3AXcALPTyvuqytgSwmboV6bYxYn9wF3AdsLjCDGtTWQL4E/KL0EMAfgNVENE8AfyYiUp9oayBnEP+C1+Y/wHoilt8AvwLeKjqRUm0N5EhikV67l4DvEQv9HYVn0TjaGsgewCvAnNKDTNJjwBJcs1Snre9BthO3L/3iaGKv2AGF59B7tDUQiNuWfrIfcA8ws/QgelebAxmhjidZnVgAXFl6CL2rrWuQXT4KrAOGSw/Sgf8CHwdeLj2I2n0FAdhK7OjdWnqQDswGvlJ6CIW2BwLxwadFwJrSg3Tg1NIDKAxCIBCPTxcDV9Ef7xsOLz2AQtvXIOM5BrgNmF96kMQO4l2OChuUK8ju1gJHEU+L3iw8y/vZWXoAhUEMBOJF4neJx6o17tlyy3wlBjWQXZ4DzgJOJhbztXii9AAKgx7ILquJDY4XABsLzwJwb+kBFAZxkT6RacB5xBqlxEL+X8D+wOsFzq338Aryv0aJTwQuIF4yPtDj81+HcVTDK8jkHAQsAy4E9u3ieR4i1kN+AUQlDKQz04GTgK8CZwIfbPDY64BTcA9WVQzk/7cHcALx8d5TgEOmcKy7ga8Br019LDXJQJqzP/B5YkvLQuAwYM8J/syTwDXEt8mrQgbSPTOAecARxN6qTxAfhnqReJS8mrrevWgcBiIlfMwrJQxEShiIlDAQKWEgUsJApISBSAkDkRIGIiUMREoYiJQwEClhIFLCQKSEgUgJA5ESBiIlDERKGIiUMBApYSBSwkCkhIFICQOREgYiJQxEShiIlDAQKWEgUuJtHEpN14taYyIAAAAASUVORK5CYII=)}69.39%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAIjklEQVR4nO3df6jddR3H8eeuc7rWnITLiDWVNLEUmdRAoeEiZ24ilWCFFmUlRjOzRZOosIJMCcrK8Aca5YY0FC1MKjcspRk6HDF1yTZkcwiyqDvdpm3u3v743BuX293be875fr+f8/me5wPEP3bv5/1m+jrvz/d8z+d7ZoyOjiJpakO5G5D6mQGRAgZEChgQKWBApIABkQIGRAoYEClgQKSAAZECBkQKGBApYECkgAGRAgZEChgQKWBApIABkQIGRAoYEClgQKSAAZECBkQKGBApYECkgAGRAgZEChgQKWBApIABkQIGRAoYEClgQNrlfcCNwBPAv4FR4ADwHHAXsAKYma27As3wG6ZaYSFwC/DRafzsy8AaUmC21tlUGxiQ8i0H7gWO6+J3HwF+DjwEjFTZVFsYkLKtAB4Aju5xna3ATcBa4I1em2oTA1Ku04DNwJwK13wBuIG0BXOi4EV6yX5BteEAOAX4FfB30tZt4DlBynQusLGBOg8D1wLbG6jVl5wgZfpMQ3WWA8+Stl29XucUyQlSpm3AqQ3XfAb4HLCp4bpZOUHKcwzNhwPgTOBvwLeAozLUz8IJUp63k2725fQYcAXwYuY+aucEKc9/cjcALAGeBpbmbqRuBqQ8e4F9uZsATgDWA6tyN1InA1Kmp3I3MGYI+BHpc12zMvdSCwNSpvtzNzDJlaR7JvNyN1I1L9LLNA/YSf/9D7kZuBDYk7uRqjhByrQX+E7uJqawCHgcWJC7kao4Qco1RPqY+kW5G5nCDuB8YHfmPnpmQMr2FlJI+vHt1ueBD1L4dsstVtkOAB8Bbs3dyBROJx3I6rfrpI4YkPIdBFYC5wD30V8Hns4mHegq9i1gt1jtMx+4HPgi8N7MvYxbA3w6dxPdMCDtthT4Ov1x+Ol60rHeohiQwbCIdKbjkow9jADLgA0Ze+iYARks5wE/BhZnqv8y6VrppUz1O+ZF+mDZSDquexUwnKH+iaRHFBXz8DoDMnhGgDuBM4DfZai/hHToqghusXQV8BNgdoM1D5IeW7SrwZpdcYLoDtI1yY4Ga84iPS2l7zlBNO54YB1wQUP1dgPvaqhW15wgGjcMXEx6cFwTFgAnN1SrawZEEx0kPdrn5obqvbuhOl0zIJpsFFhNM3e95zZQoycGREfSxEdDXq15/Z4ZEEWuB+6ucf1tNa5dCd/F0ps5mnQoa1nF6+4CTqp4zco5QfRmDgGXUf2r/b0Vr1cLJ4im6yzgSeDYCtZ6nXQnve/PrDtBNF1bgC9VtNb3KSAc4ARR534KXNPD7z9E+jbew9W0Uy8niDp1HXB7l7/7AOl6pohwgAFR5w4DV5O+5Wq6j/TZT3rI9aXAazX1VQu3WOrFW4EvAJ8EPsD/v+BuIX0A8jbgn822Vg0DoqrMId3XeBvpDvkLwCtZO6qAAZECXoNIAQMiBQyIFDAgUsCASAEDIgUMiBQwIFLAgEgBAyIFDIgUMCBSwIBIAQMiBQyIFDAgUsCASAEDIgUMiBQwIFLAgEgBAyIFDIgUMCBSwIBIAQMiBQyIFDAgUsCASAEDIgUMiBQwIFLAgEgBAyIFDIgUMCBSwIBIAQMiBQyIFDAgUsCASAEDIgUMiBQwIFLAgEiBmbkbqMhxwCnAXOBfwE5gf9aO1AolB+QE4GrgMuCsSX82AjwF/Aa4E9jXbGtqixmjo6O5e+jUDOA64HvAnGn8/B5gFXBPnU2pnUoLyGxgLfCxLn73duDLwOFKO1KrlRSQo4AHgYt7WONnwFeqaUeDoKR3sVbTWzgArgE+23srGhSlTJAFwDbg2ArWeh1YDGypYC21XCkTZCXVhIOxde4H5lW0nlqslAmyE1hY8Zp/Im3ZDlW8rlqkhAmykOrDAbAMuK2GddUiJQTktBrXvhL4YY3rq3AlBGRuzeuvxpDoCEoIyKsN1FgN3ES6Sy/9TwkB2dFQnW8AvwRmNVRPBSjlXawXSfdCmvAI6QOQww3VUx8rYYIArGuw1gXAJuDMBmuqT5UyQRaS7qQ3uf15DfgqcEeDNdVnSpkgu4AbG645m/QJ4N8C72i4tvpEKRME0uGuDcCSDLWHSRfxd5EOY2lAlBQQgHcCTwMnZqr/JOmw1sZM9dWwUrZY414CLiffq/hi4K+kbdeiTD2oQaUFBNI265uZe7iENMl+DyzN3ItqVNoWa6J7gCtyNzHmOdLDIdaSzsCrJUoOyCzgD/TXK/gbpGPBPwA2Z+5FFSg5IJAOPf0FODt3I1O4FfgacDB3I+pe6QEBmA88Dpyeu5EpPEo6lHUgdyPqTokX6ZPtAT5Mcx9q7MRS4D7a8fc8kNryH243cD7wfOY+pnIR6Uy9CtSGLdZE84E/0n/3KPYCJ439WwVpywQZt4e0rdmQu5FJ5tE/b0mrA20LCKRX6eXA3bkbmeTS3A2oc23bYk22CriZ/ngh2Ef95+tVsbYHBNKWax3p6xJyOx6vQ4rSD6+sdXsUOAd4LHcjwDG5G1BnBiEgkM60fwj4Nnm//sDpUZhB2GJN9n7S00uaPnO+nXofgqcaDMoEmWgTacv1XZr9nNT6BmupIoM4QSY6FbiF9LZw3c4Dnmigjio0iBNkou3AirF/nqmxznoMR5EGfYJMNES6230D6Sulq7Kf9NGXbRWuqYYM+gSZaAT4NfAe0te0ba1gzUPAJzAcxXKCHNkQ6SzHStLTFjv1CvAp4OEqm1KzDMj0nAF8nrQFm84jhx4EriU98E4FMyCdmQlcCHwcOBc4mfQExmHgH8CfgTXAs3naU9UMiBTwIl0KGBApYECkgAGRAgZEChgQKWBApIABkQIGRAoYEClgQKSAAZECBkQKGBApYECkgAGRAgZEChgQKWBApIABkQIGRAoYEClgQKSAAZECBkQKGBApYECkgAGRAgZEChgQKWBApIABkQL/BUc+hdEKzAiuAAAAAElFTkSuQmCC)}71.43%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAJkUlEQVR4nO3dfcxXZR3H8TcC4uyBHjDI2aqxigebC3UxpdIyZDq25qLHLaVIcz2YtVJqK2prin/kWmWplau1HjbXKpOAKI3ULNByKVLmqsUISWpIKQje9MeXe7tz9y5+D+c65/qd8379xQb393v+4HNf1znXua4z5fDhw0ia3DFNX4BUMgMiJRgQKcGASAkGREowIFKCAZESDIiUYECkBAMiJRgQKcGASAkGREowIFKCAZESDIiUYECkBAMiJRgQKcGASAkGREowIFKCAZESDIiUYECkBAMiJRgQKcGASAkGREowIFKCAZESDIiUYECkBAMiJRgQKcGASAnTmr4ANeZ44HTgFUf+/CTwF+A3wL8avK6iGJDuOQX4OHABcNwkfz8GbAKuBdbXeF1FmuJnoDvjWOAa4EPAlB5/Zj3wAeDhXBdVOgPSDc8CfgqcOcDPHgDWAlcB+6u8qFFgQNpvKnArcO6QdbYBFwJbh76iEeJTrPa7nOHDAbAA+DWwBpheQb2R4AjSbrOAvwLPqLjuXcBbgR0V1y2OI0i7raT6cACcAfweWJqhdlEMSLtdkLH284mnXFdk7NE4p1jtNR14nHrWum4C3kcsNraKI0h7zaG+heCVwEZgZk39amNA2mtqzf1eB/wcOKHmvlkZkPb6TwM9TwVuB05qoHcW3oO0226a+Y3+MPBaYGcDvSvlCNJuv2io71xgAy2YbhmQdvtWg71PJh4Dj/SNu1OsdjsG2AIsavAaNgHnAQcbvIaBOYK02xhwCc3+5zwHuK7B/kMxIO23Fbi04WtYBXys4WsYiFOs7rgIuJ7YONWEMWI0ua2h/gMxIN1yMnAjsLih/o8Q90Mj8/jXKVa33E/sKrwY2NNA/9nA96l/lX9gBqR7xohRZAHwowb6LwFWN9B3IE6xtBL4EnH0T10OEdO8e2rsORADIoCFwM3AvBp7PgC8isLXR5xiCeI/62Li9ZC6LASurLHfQBxBNNFU4MvE4mIdDgCvBB6qqV/fHEE00VPEzsCra+o3gzjBsVgGRJNZDXyypl7nA8tq6tU3p1hKuZp6DmXYRky1xmro1RdHEKVcCXythj4LgHfW0KdvjiA6munAOuI9qpweJh4zH8rcpy+OIDqag8AK4M+Z+8ylwFHEEUS9OgW4m8m/KVKVB4kXKou5F3EEUa/uAy7L3GM+8VSrGAZE/bgBuCVzjw9mrt8Xp1jq1xxgO3kPY5h/pEfjHEHUr13k3z67KnP9njmCaBDHEF/DPS1T/UeI0xkbf+TrCKJBjAEfzlh/NtV8FWtoBkSDupO8N+xvy1i7Z06xNIxF5NsV+BjwAuKV+MY4gmgY95Lv/N9nA2dlqt0zA6JhfT5j7SUZa/fEgGhY68i3ZvHyTHV7ZkA0rMPkeyV+Rqa6PTMgqsJ3iaBUbX+Gmn0xIKrCTuLTa1X7U4aafTEgqsp3MtT8VYaafXEdRFWZSbynVdV+kV3Ai2j4dRNHEFVlL/DVCutdSwHvYjmCqErPJU5pfOGQdbYRq/SNrqKDI4iq9W/gLcATQ9TYS+yBbzwcYEBUvTuANwH7BvjZ3cAbiRGkCAZEOWwkpkib+/iZW4jT3rdkuaIBeQ+i3JYSOwTPJV5AnOhR4lWVrxAnphTHgKguU4EXE6+wjxGPcf9OnhX4yhgQKcF7ECnBgEgJBkRKMCBSggGREgyIlGBApAQDIiUYECnBgEgJBkRKmNb0BfRgCrE3eQ4R6N3A34CnmrwodUPJAVkMXAqcB8x62t89BmwgDizbWPN1qUNKfJv3RGLz//Ie//1m4D3k/0yxOqi0gJwO/ITYM9CPfcCbcTRRxUoKyALgLgb/OOQTxO61Oyq7InVeKQGZQXxrYsGQdf4BLCRO15CGVspj3ssYPhwQ5zF9qoI6ElDGCDKN2Js8p6J6+4/U2ltRPXVYCSPI2VQXDoizYVdUWE8dVkJAXpOh5jsy1FQHlRCQHJ/ZOotYT5GGUkJAqjouf6IpwNsz1FXHlBCQXIcUryKCIg2shIDk+szWPOI9LmlgJQQk58r3RzLWVgeUsA4yg3iF/ekHG1flVGKVXupbCSPIAeDHGeuvyVhbLVdCQAC+l7H2cuDMjPXVYiVMsSBeN9kBzM5UfyvwauLYfalnpYwgh4BvZ6x/GrGpSupLKSMIxGPZBzPW33ukx66MPdQypYwgANuBn2WsPxO4IWN9tVBJAQH4Yub6y4GLM/dQi5Q0xYII7P3A/Iw99hMnptyXsYdaorQRZAxYm7nHccDNwHMy91ELlDaCQDzy3Q7MzdxnE/Gu1sHMfTTCShtBIB75fqaGPucA19XQRyOsxBEEIrh/oJqDHI5mLXBlDX00gkocQSDuRT5aU68rgE/U1EsjptSAAKwHbq2p1+eAq2rqpRFS6hRr3MuIqdaMmvpdD7wfT47XESWPIAAPEb/d63IJMWoNevypWqb0EQRgOvA74kjRumwnDsN+oMaeKlDpIwjEOsWFxOPfuswDfgusrLGnCjQKAQG4h3rWRiY6HvgG8EP6/xyDWmIUpljjpgK3A0sa6L0HWA18HTdddcooBQTitMR7ybfz8GjuBt5LvFCpDhiVKda4ncSJiU39Fl9MTPcuaqi/ajZqAQG4jWZfDTkWuAm38HbCqE2xJrqROF60KQeBM4gDIdRSoxyQ6cA64q3cptxLfHjUG/eWGsUp1riDxGJek6cmLgKWNdhfmY1yQCBOKllGs0+V3tVgb2U2ylOsiU4ENpN/F+Jk/okLia016iPIuJ3EV6W2NdD7BGBWA31Vg7YEBOLo0rOIdYq6PbOBnqpBmwICMd15A/DLmvu6f6Sl2hYQiBv3pcRiXh0O4XGmrdXGgAA8CbybWHHP/RRiKx4d1FptDci4tcRj4D0Ze/wgY201rC2PeY/mJOIjPVV/SOe/wEuARyuuq0K0fQQZtwM4m9h0VeXOxDUYjlbryggy0WnANxn+ULoNwPn4BKvVujKCTLSV+PLtZ4kPiA7iTmAFhqP1uhgQiE8gfJo4KWV9Hz93GPgC8HpgX4brUmG6OMWazDLgcuLV+cl+aewnnlZdg98V6RQD8v+eR3wN96XEzsHHgT8CW478WR1jQKSErt6DSD0xIFKCAZESDIiUYECkBAMiJRgQKcGASAkGREowIFKCAZESDIiUYECkBAMiJRgQKcGASAkGREowIFKCAZESDIiUYECkBAMiJRgQKcGASAkGREowIFKCAZESDIiUYECkBAMiJRgQKcGASAkGREowIFKCAZESDIiU8D8fRLfKuL+RJwAAAABJRU5ErkJggg==)}73.47%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAJw0lEQVR4nO3de6hlZRnH8e854w0vY0pThhKZjpZNU1mZ0QVLsoHu96KgsAv4hyYRaVJElqVCoUYUFhaSUGRlWaBGNUThpZq8jPdOhShpEzPqqHg75/TH44kxju/sffZ63nftvb+ff4fzPJvh/M6z11rvet+ZxcVFJC1vtvUHkPrMgEgFBkQqMCBSgQGRCgyIVGBApAIDIhUYEKnAgEgFBkQqMCBSgQGRCgyIVGBApAIDIhUYEKnAgEgFBkQqMCBSgQGRCgyIVGBApAIDIhUYEKnAgEgFBkQqMCBSgQGRCgyIVGBApAIDIhUYEKnAgEgFBkQqMCBSgQGRCgyIVGBApAIDIhUYEKnAgEgFu7T+AOq1WWAtcAiwG3A/cBtwZ8sPVZMB0XKOAE4G3gXsv8y/zwEXAd8A/lPxc1U3s7i42PozqD/2BM4GTmCwr9/bgc8A3878UC0ZEC1ZA1wGHLmCn70Q+DjwaKefqAcMiAD2Av4AvHiEGlcA7yamysTwLpYAvsZo4QA4DtgIPHPkT9MjThC9BPgLMNNRvTngGCbkTpcTRJ+iu3BA3BLeCBzQYc1mnCDTbRdgG7B3Qu3NwOuBLQm1q3GCTLf15IQDYB3wa2B1Uv0qDMh0OyS5/ouAHwO7JvdJY0Cm214VehwHnE+31znVGJDpdl+lPh8hnriPHQMy3W6v2OsrxEX7WPEu1nSbBe4mlpnUsIV47nJXpX4jc4JMtwXgRxX7rSEu2sdmFbkB0TnAYxX7vRI4tWK/kRgQzRHXBzV9gdHXflXhNYgAVgG/BDZU7Hk9cBTwSMWeQ3OCCGCeeHvw0oo91wOfrdhvRZwg2tEq4qHe8ZX6PUy83vuPSv2G5gTRjuaBjwKnV+q3B/D1Sr1WxAmip3IacEalXhuAyyv1GooBUcmZwCkV+mwmFjYuVOg1FL9iqeRU4DsV+qwD3luhz9CcINqZWreAbyaC0qsp4gTRzswD7yN/YePzgQ8k9xiaE0SDeiFwFbG5XJbNT/TpDSeIBnUDcGJyj3XAsck9hmJANIwLiOuRTCcl1x+KX7E0rAOAG1l+U+suLBI7ys8l1R+KE0TDupt4iJhlhtjntxecIFqJWeBPrGyj60HcBTybHtzydYJoJRbIvVY4kJ68v25AtFJ/JHf91IcSaw/Mr1gaxSuIZyMZthHvsM8n1R+IE0SjuJq8KbIf8Nqk2gMzIBrVeYm135ZYeyB+xdKoZomFhocl1L4VeF5C3YE5QTSqBfKWxB9O43NGDIi6cBF5zyya3u41IOrCv4DfJNU+JqnuQAyIunJJUt2XJdUdiBfp6sqB5Bzc+ThxClaTDeb6GpBVxBtmzyH+c7YTb7TdTqz2VD9tBl6QUPcoYu1XdX3bZfsI4GTiQPr9lvn3e4AfEnsp3VHxc2kwG8kJyDoaBaQv1yB7ELuMX08sdV4uHBCH1H+SmCSfIyaN+uP3SXXXJtXdqT4EZD/gd8Qv/qC/8LsBXwJ+Su470hrOn5PqHp5Ud6daB2R34FfA0Sv8+bcCP2BMD4icQH8H7k2oe2hCzYG0DshXiQNVRvEO8jcT0OBuSqj5rISaA2l5F+tQ4Ba6uY64HzgY2NpBLY3me8Sptl3bjbonYQFtJ8jJdHeRvRr4WEe1NJqsowyekVS3qFVAZohbuV3qup5W5p6kurVO4n2SVgF5LnHLtktHEreL1dbdSXX3Sqpb1CogByfUXEU8eVdb9yXVnaqA7J1U1wnS3vakuk2ed7W+zavJ03STha4ZEKlg0gLi2ix1qlVAHkqqu09SXQ3u4aS6DyTVLWoVkAeT6u6bVFeD+yc51yFNzlKftIA03QFDQEyQTR3XvIdYCFldq4BsSarb9cNHrczFCfWaLBpsFZB/J9XNeACp4X2XWEDahXniZbomWgXkMXKmSMbufhreVuDzHdU6D/hbR7WG1nK5+3XA+o5r3stTv66rumaAnxDv66zUlcDraLSjCbR9DpLxV+FpxEJItbdInPHxixX+/FXAm2gYDmgbkFuT6jbdaExP8hDwTuLr1qMD/sw8cC4xObYlfa6BtQzI7Ul1m58poSeZB75M7ExyLk/9vsg2YhPs9cTLdFkPHIfS8hrk5cA1CXVvJPZRUj/NEGFZS6x8eIB4uHgzPVzo2DIguxP/ORmb1x1EnJQqjaTlV6xHgBuSajc/mUiTofVq3qyNxt6eVFdTpnVANibVPZaGeylpcrQOyG+T6s4CH0yqrSnSh+MPbiFn79XbiCMUso4G0xRoPUEALkuqexiwIam2pkQfAvLzxNonJdbWFOjDV6xVxMrerEWGRwNXJ9XWhOvDBJln5QvaBvHFxNqacH0ICMQZH1neCLwqsb4mWB++YkEE9Q7ipNQMm4i1X97R0lD6MkEWyJ0iRxJnH0pD6csEATiEWAKfdZzaVuIE1qzdxzWB+jJBAOaASxPr70+8byANrE8BgXhBP9ObgeOTe2iC9Okr1pIbyH3h6SHi2UjWUntNkL5NEIAzk+vvSey2sTq5jyZAHyfILLCZWGiY6TLiK1fvXvNUf/RxgiwAp1foswH4VoU+GmN9nCAQwb2OOpsvnAWcWqGPxlAfJwjEFPl0pV6nAKdV6qUx09eAAFwOXFKp1xm4qFHL6OtXrCUHAzdR7/TaC4BP4IW7ntDnCQJxqtBZFfsdD/yMRkcOq3/6PkEgNpi7hu53gi/xFrCA/k8QiA3mPgw8XrHnBro730JjbBwCAnAt9S+iTyNWGGuKjUtAIJagXFmx367ELuOaYuNwDbKjA4G/Amsq9dtCnJzrm4hTapwmCMSO7e+n3i/sGuCISr3UQ+MWEIjtSms++V5bsZd6ZhwDAnA28P1Kvfat1Ec9NK4BWSSeeF9RodeDFXqop8Y1IBBnrb+HWPWbaS65vnps3O5iLWcNcV2SsTT+AWJL1JoPKdUj4zxBlmwB3kDOX/pLMBxTbRImyJKDiBOrunr6vQi8lHjuoik1CRNkyZ3EHrybOqp3PoZj6k3SBFmyD3AxcNwINa4FXo13sKbeJE2QJduBtwAXrvDnNxHhMhyayIAAPEoskT+BCMwgFoBvAq8hLvylifyK9f+eDpxInHq73AX8VmIjuXOI13ul/5mGgOzoIOJwz9XElJkjdpR3ta6WNW0BkYYyqdcgUicMiFRgQKQCAyIVGBCpwIBIBQZEKjAgUoEBkQoMiFRgQKQCAyIVGBCpwIBIBQZEKjAgUoEBkQoMiFRgQKQCAyIVGBCpwIBIBQZEKjAgUoEBkQoMiFRgQKQCAyIVGBCpwIBIBQZEKjAgUoEBkQoMiFRgQKQCAyIVGBCpwIBIBQZEKjAgUoEBkQoMiFTwX5SHo1b+jj/nAAAAAElFTkSuQmCC)}75.51%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAJ+UlEQVR4nO3dS6xdVR3H8W+5LYUoBVRAoBVfYB9gASsWMWigghJFcCCJGhXUBAkxPtGIglGIMHHAwIgOMMSBaAIKGkUpESMCWhEEKqIoYkstFSsgQfq6DhaVNtD/2efe/T9r73u+nwkdtL99bji/u/ZjrbVnTU5OIum57Vb7A0hdZkGkgAWRAhZEClgQKWBBpIAFkQIWRApYEClgQaSABZECFkQKWBApYEGkgAWRAhZEClgQKWBBpIAFkQIWRApYEClgQaSABZECFkQKWBApYEGkgAWRAhZEClgQKWBBpIAFkQIWRApYEClgQaSABZECFkQKWBApYEGkgAWRAhZEClgQKWBBpIAFkQIWRApYEClgQaSABZECFkQKWBApYEGkwOzaH0C9tCdwKrACWAy8EHgKWAOsAn4A3F7t07Vo1uTkZO3PoP7YHfgYcB6lFJFbgE8+/d/esiBqaj5lZDh6iH8zCVwEXPj0n3vHgqiJQ4CbgYOn+O+/DpxDD0viRboG2QO4jqmXA+Bs4NPtfJzRsiAa5HPAES3kfAV4Sws5I+UpliL7An8HntdS3kbgSODBlvLSOYIocgbtlQNK4a6iR48XLIgiJydkLge+kJCbwlMsRe4HXp6QuxU4DrgtIbtVjiCKDHoYOFUTwBXA3KT81lgQ1bIIOL/2hxjEUyxF7gaWJOZvBg4H7ks8xrQ4gihyR3L+HOCy5GNMiwVR5NoRHONk4G0jOM6UeIqlyO7AA8CBycdZDSwFtiQfZ2iOIIpsYjQX0ouB947gOEPrwwgyARwDLAMWUH6rrQfuAW4CHq330cbCLOBq4LTk49wPLKRjo0iXCzIP+DjwEeCAXfydTZT/eRdRCqMc+1JWCmY8NNzRmcC3ko8xlK4W5ATgSppPsd4KXAx86ek/q31LgVsp09+z3Eu5rbwt8RhD6eI1yHuAnzHc+oMJ4ALge/RoIlzP3Amcm3yMhXTsjlbXRpATgespX/ipupyyQEc5fgSckpi/krIZRCd0qSB7UYbYg1rIOpWyCk7tO5hyvbd34jEWUb4L1XXpFOsTtFMOgEvp1s82k6wFPpV8jA8l5zfWlRFkAngI2L/FzJMo1zJq326Uu1pHJeWvp9zS35yU31hXfsuuoN1yAJzecp6esY2yP1aWA8hZrDW0rhTkXQmZr0nI1DN+QdknK8sZidmNdeEUaw5lSN235dx/kD+HaNwtA36TlP0Y5aziqaT8RrowgpxA++WAHqxWmwFWUW7LZ5gHHJ+U3VgXCpK1V9LDSbna2SWJ2dUfGnahICcl5d6VlKud3UTeisC3JuU2VrsgCyhTnTPckJSrnU0C30zKPpSyaXY1tQtyQlLuNuCapGw925XkTVN/U1JuI7UL8rqk3BvxGmSUHqbc9s1wXFJuI7ULckxS7lVJudq1rBF7eVJuIzWfg+wBPE7O9PSDKVNXNDrzKRtdt20rZX/gKs9Dao4gryanHHdjOWpYA/whIXeCvBs5A9UsyKKk3JVJuRos6zpkaVLuQDULcmhSbq9fGtlzv0zKzfquDFSzIAuTcn+dlKvBfpWU+6qk3IFqFuSVCZkbgb8m5KqZB4AnE3IPSchspGZBMmba/jEhU81tI2ep7HReIDottQoyAeyXkNvZXcLHyN0JmftRNrAbuVoFeRE5P/BfEjI1nIxnIbPJ+YU6UK2CZP2w65Ny1dzapNy2l2Q3Uqsg+yTlOv+qvg1JuXsm5YZqFSRr98N/JeWquayCtPk66sZqFSRrf9dO7Qw+prL21c3cE3iXZlpB/pOUq+YeS8odq4JIvVCrIP9Nyp2XlKvmnp+Um/WdCc20gjgi1pd1A2asCvJEUm6Vh0nayQuScqvcgKlVkIwJbWBBuiDrgd6/k3JDtQqS9UCv2qQ2/d+u3ic5XVnPV0K1CrKBnCFzQUKmhpPxos9J4J8JuQPVKsgkOb8RDk/I1HAOS8jcQKWXs9a865MxqW0h3smqLWP137qEzEZqfpn+lpC5J/DShFw18zJydur/c0JmIzULkrX67/VJuRosayPAai/0rFmQPyXlviEpV4Mdm5Sb9V0ZqGZB7kzKrf7SlTF2YlJuxoZ0jdTcenQu5Yn6REL2AspOfxqdg8i58bIF2Isxm2oCZa/VrJfcnJaUq107JSn3TiqVA+rfEr01KddXQI9e1ltpq24EWLsgNyflHk+lRf5jan/yXoZ0W1JuI7UL8vOk3NnA+5Ky9Wynk/ddujEpt5HaBVlD3i28D1Nps7ExtCIpdzU5+2w1VrsgAD9Oyj0MeGNStnZ2RFLuT5NyG+tCQX6YmP3ZxGw9I+t67ydJuY3VfA6y3VzK+pCs9eSvBVYlZatYB7y45cyNlLUlm1vOHUoXRpCngGsT8z+fmK3iwYTMa6hcDuhGQSD3rbTvwOkn2X6bkPndhMyhdeEUC2AO5W5F1nLN3wHLyNv1b9y9mXYvqB+mTF2pskhqR10ZQTYD307MPwo4KzF/3K2k3QmFX6MD5YDujCBQVgNmztp8FFhC3vb84+7ttHMt+RDlu/B4C1nT1pURBMqimMxXOO8NfCMxf9xdB1w+zYytlBkQnSgHdKsgAJcl558CfDD5GOPsXMrdp6nYBryfjr3nvkunWFAKew95r4iGMnV6OXkLtsbdBHABcD7N1/qspYwcVeddPZeujSDbgEuTj7EHcDU5mwuonCZdCCwFvgNsCv7ueuCLwGI6WA7o3ggCZSbuvcArko/zfeCdlD26lGdvypy4JZTb+Jsot/RXUdZ6dOJu1a50sSAAHwCuGMFxzhrRcdRTXS3IbMo1wuLk46yj7KMVnQZojHXtGmS7LcBnRnCcA3H9ugJdLQiUafDXj+A4p47gGOqpLhcE4KPkz+g8MjlfPdb1gtwHXJJ8jPnJ+eqxrl6k72guZTbuoqT8R4F9krLVc10fQaAsqDqTvPvljyTlagboQ0Gg7I10cVL275NyNQP0pSAAXyZnJ8ZR3ClTT/XhGmRHLwHuoL15VE9QNrre2FKeZpg+jSBQNgd4N+0tnf0qlkOBvo0g253H9Gf93kV5I1K1ncPVfX0tyCzKuuWzp/jv1wLHkfOeRM0gfTvF2m4SOIdy4T5sw2+nLJiyHBqorwWBUowLKCPBLQ3+/iOUCZDH4tun1FBfT7Gey9GUTeKWUaaPzKWUYjVwA2XHjSerfTr10kwqiNS6Pp9iSeksiBSwIFLAgkgBCyIFLIgUsCBSwIJIAQsiBSyIFLAgUsCCSAELIgUsiBSwIFLAgkgBCyIFLIgUsCBSwIJIAQsiBSyIFLAgUsCCSAELIgUsiBSwIFLAgkgBCyIFLIgUsCBSwIJIAQsiBSyIFLAgUsCCSAELIgUsiBSwIFLAgkgBCyIFLIgUsCBSwIJIAQsiBSyIFLAgUsCCSAELIgUsiBT4H1RRjOTW0wyiAAAAAElFTkSuQmCC)}77.55%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAKZklEQVR4nO3df6xXdR3H8ee9XiKmQyvBLCKTrCtpSuqEMsCFaWZpZNOVNTVra0tzsykaURtU1lZLzLkVW60frlZS2vJXtLC0aOGU4W5XEXNUCFSWzGYJ3G9/fHA1kPf33O89r+/n8z3f1+Mf/xBe53C/53XPOZ9zPp/vQKvVwsxe2GDuHTArmQtiFnBBzAIuiFnABTELuCBmARfELOCCmAVcELOAC2IWcEHMAi6IWcAFMQu4IGYBF8Qs4IKYBVwQs4ALYhZwQcwCLohZwAUxC7ggZgEXxCzggpgFXBCzgAtiFnBBzAIuiFnABTELuCBmARfELOCCmAVcELOAC2IWcEHMAi6IWcAFMQu4IGYBF8Qs4IKYBVwQs4ALYhZwQcwCLohZwAUxC7ggZgEXxCzggpgFXBCzgAtiFhjKvQM1mg6cBcwBXkEq/3bgYeAOYEu+XbNe1YSCDAPLgcXEZ8R7gGXA77qxU9YMA61WK/c+TMRVwBeASRX/fAv4CnANsEe1U9YcvVyQlcDlHf7dnwDn45JYG716k341nZcD4Dzghpr2xRqsF88gbwfupJ5ynwGsqSHHGqrXCjITeAh4SU15DwAn15RlDdRLl1hDwC3UVw6Ak3BBLNBLw7zLgLcIcs8B1gty+9lhwGzgpcAzwJ+BzaRRxJ7SKwU5FbhOlD1HlNtvpgAfBi4G3gQM7PP/nwJWA18DNnR1zyagF+5BJpPuO4ZF+euBU0TZ/eJc4GbgyAp/tgV8C7gS2Cncp1r0wj3Ip9CVA3rjZ1Cy5aTnSlXKAenMcgnpjYYZqp2qS+kHx+uBJeJtbBPnN9l1wNIO/+4w8EvSfUqxSi/IDVR/jaRTG8X5TXUasGKCGa8FvlHDvsiUXJB3AWd2YTt3dWEbTTNAutne90a8E4uBd9SQI1HqTfoQaaRjtng7m0in+jHxdppmEfDzGvM2AidS4OdQ6hnkIvTlgPRspbgPpQdcUHPe8cAHa86sRYlnkCFgFJgl3s5q4L3ibTTVH6h/ZHHz3szdNedOSIlnkIvQl2MzcKl4G02m+HxmkT77opR2BhkERkjDuyr/BubSQ09zC6Q6aEZJl9bFHJSlnUHOQVsOSPNIXI6JeU6UOwycLcruSGkFuUKcfwewSryNfvCoMPtKYfa4lVSQYeBtwvyngY8K8/vJvcLsRaQHiEUoqSCXifOvAv4i3ka/+IE4/2Pi/MpKuUkfIs0ZOEKU/yBpYpSfedTnt6TBDoW/ktY2yz7kW8oZ5Ex05YB0Xety1OtaYfY00noB2ZVSkAuF2bcBvxLm96u1aBe8+IAwu7ISLrEmAzuAqaL8U/CUWpW5pEsthZ3A4cAuUX4lJZxBFqArx924HErrSD9jhanA6aLsykooyDuF2V8SZluyUpj9bmF2JSVcYj0KHCPKHaag1xYaapA0beBoQfYm4HWC3Mpyn0FmoCkHpJlqLofeGHCTKPsY4NWi7EpyF2ShKHc38G1Rtu3vFnTD6AtEuZXkLohiIThIw7o7RNm2v22kYV8F1TFSSe6CqJ7E/liUawf2Q1Hum0W5leS8SZ8M/As4SJD9KtKrK9Y9LweeFOSOAYcAzwqy28p5BpmNphwjuBw5bAMeEeQOAm8Q5FbeeC4niHJ/Lcq19taKclXHSls5C6Ia3r1PlGvtrRXlKpeeDeUsiGpq7W9Eudae6r2sbBOochbkKEHms8ATglyrZgtp4KVuiqf0leQsiGJl71E87yOnFmnNrLpVXTm+drkKMgnNBKmHBZk2PoqCTANeJMhtK1dBpolyPbyb3x9FucoZpweUqyCHiXL9ekl+qs9AdcyEXBCr299FuYeKckO5CjJZlPs3Ua5Vp/oMpohyQ7kKovptoFoS06pTLdVzsCg3lPttXrOiuSBmARfELJCrIIrXESAtYWp5qR7oPS3KDeUqiGryy+GiXKtO9Rn8R5QbylUQ1W+Dl4lyrbrpotx/inJDuQqi+seqPhyrzgWpwXZR7mtEuVad4i1tSF+J0HW5CvIcmn/wsYJMG5/jBJnbybSIdc5hXsUKGMcCA4Jcq2YQzfTYbG9p5yzI44LMg4GZglyr5ig070w9IcisJGdBHhPlzhPlWnuqRd4UywlVkrMgo6LchaJca+80Ue4mUW5bOQuyQZS7UJRr7b1VlKs6VtrKufToFOAZNCU9krTSn3XPDOBPgtw9pHvLvnqSDul1kxFR9nmiXDsw1c98I5nKAfnf5lUt8vY+Ua4d2HtEuetEuZXkLsj9otyFpNXGrTumA/NF2apjpJLcBblXlDsIvF+Ubfv7ELqpBmtFuZU0+Us8H9+b65UWtQZIQ/aKL9vs+y/xBLhHlHs0cJYo2/7ndHQH8Z2i3MpKKMjtwuwrhNmWXC3M/pkwu5ISLrEmkdZSmirKn0fmkZAGOxn4vSh7J+nmP9sQL5RxBtkF/FSYv1yY3e+WCrNvJ3M5oIyCAHxPmL0Iv36iMB84V5j/fWF2ZSVcYkEaItyKbtX3dfgt3zoNAuuBOaL87aRXV1SrNFZWyhlkN/AdYf5cdC/S9aNL0JUD4LsUUA4opyAAN4vzLxDn94tXAl8Wb2OVOL+ykgryGLBGmL9AmN1Pvo72qwh+gW6u0LiVVBCArwqzsz6RbYjLgLPF21gpzh+XUm7SnzdAegVe9b3YXtChcyeQBjteLNzGI8BsCno9qLQzSAv4oig7y7IxDXEocCvacgBcT0HlgPLOIJCGfEeBWTXnjuJ1szp1K7BYvI3NpCuHIkavnlfaGQTSD0jx9Ps+QWY/uBB9OQBWUFg5oMwzCKTiPgQcX2PmGWhHyZpokHTmVUxH+H8jpHuc4gpS4hkE0nXoNTXmbSANH9r4zEdfDoAlFFgOKLcgkOYCrK4hpwV8fO9/bXy6MZ/mbrQvq05IyQUB+AgTX4FxKb7/6FSdl7gvZBfwCfE2JqT0gjxFmrHW6ZPVFcDn69udvqNe+OJ6Mi4rWkXpBYG0svepwDepfpn0JGmdpk+rdqpPKJ9JjAKfE+bXohcKAml22aWkN0hXkc4s+2oBDwCXk56h3Na1vWuuraLcPcDFFDAhqp1Sh3nbGSCVYAZwCKkwI2T6mq4G+yzwGUHucmCZILd2vVoQ6w7FnPP7STM8ixzW3ZcLYu2sB06qKesfwInAlpry5HrlHsTyWVJTzhjptZWeKQe4INbeGuCmGnKuRbdIoIwvsayKg4Af0flXHNxIjy7i5zOIVbEHOJ80F308v1F3AZ+kR8sBLohVt4d0sM+j/aXSGOmM80b0CzxI+RLLOjWTND/9OOAIUim2Ag8CdwE78u1afVwQs4AvscwCLohZwAUxC7ggZgEXxCzggpgFXBCzgAtiFnBBzAIuiFnABTELuCBmARfELOCCmAVcELOAC2IWcEHMAi6IWcAFMQu4IGYBF8Qs4IKYBVwQs4ALYhZwQcwCLohZwAUxC7ggZgEXxCzggpgFXBCzgAtiFnBBzAIuiFnABTELuCBmARfELOCCmAVcELOAC2IWcEHMAi6IWcAFMQu4IGYBF8Qs4IKYBVwQs4ALYhZwQcwCLohZ4L8QQJg9yFm40gAAAABJRU5ErkJggg==)}79.59%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAALJElEQVR4nO3da4xdVRnG8f9Mp51gkAF0UGhLCVJsLaASEJRAS0XaUlJFJdGqERWExEQjUQskBQoS5IP6QUlKwFugaETTEHrXUqBB0BqMvRdaglKLiKWiBtMynfrhtXaa6bznnJn97rXO3s/vc/usM5dn9m3ttToOHDiAiBxZZ+oPIJIzFUTEoYKIOFQQEYcKIuJQQUQcKoiIQwURcaggIg4VRMShgog4VBARhwoi4lBBRBwqiIhDBRFxqCAiDhVExKGCiDhUEBGHCiLiUEFEHCqIiEMFEXGoICIOFUTEoYKIOFQQEYcKIuJQQUQcKoiIQwURcaggIg4VRMShgog4VBARhwoi4uhK/QEy0QvMAM4BTsK+L38FNgIrgOfTfTRJqe4FeQdwO3Al/vfiUeBWYG0Jn0ky0lHTfdLHADcANwHdLfy/u4HrgX0RH0ryU8eCnAP8BHjXMP//SuDDwN7CPpFkq04X6V3ALcBTDL8cYNcqCwv5RJK9uhxBxgE/Ay4oMHMO8EiBeZKhOhRkJvAA8JaCc7cAU4DKfwPrrOqnWN8AllJ8OQAmA1MDciUjVS3IGOyocRexX+PlgdmSgSo+B+kBFgMXlzDW2SWMIQlVrSC9wGrgzJLGG1vSOJJIlQoyDnviPbHEMat6iir/U5WCjAMew6aOlOmlkseTklXhL2AvsIbyywGwPsGYUqJ2L0gPds1xWqLxlycaV0rSzg8Kx2DzoqYlGv9F4FSgL9H4UoJ2PoL8iHTlAFiAylF57VqQecDchOOvAn6YcHwpSTueYs0ClpCu3BuxKSavJhpfStRuR5DxwP2k+9zLgQtROWqjnQrSBfycmImHjfwL+CIwG/hHgvElkXZ6UDgfOD/BuKuAa4A/JxhbEmuXa5BzsTcBR5U45uvAl4EflDimZKYdCtIN/AF7/6Is24CPAZtKHFMy1A7XIPMotxzLgPNQOYT8jyCnAxuwp+ZluAf4ErC/pPEkc7kfQb5LeeX4JnAdKocMkPNdrFnAZSWNdSPwrZLGkjaS6ylWJ3ZqNZL1q5p1G7ZelsgguZ5izaWccixE5RBHjkeQLmAr8S9ALcWWENU1hwwpx2uQTxBfjq3YUUrliNUJTMeWRzob21qiE3gZ+CO2tcRS4I1UH7CR3I4gHdi1x5TAMV4H3oeec0T7OHAnjd/2fAnbWuJeMlylMrdrkFnElgPsOYfKEecobNG+h2juVegTsedPvyLNRFRXbkeQ5dhaulEWAx8NzK+7buxnONxF+zYCFwF7CvtEI5RTQU4DnsVOsyLsASYBfwvKF7sreO0IM1Zgz7+y+MXM6RTrauLKAfB1VI5IUxl5OcDOIK4qIKcQuRxBOrFVQk4Kyl+HTUDM4outqCewty2L8CdsxZj+gvKGLZcjyCXElQPgq6gckSZSXDkAJgCXFpg3bLkU5JOB2UuAJwPzJeaX+cqAzJblUJAu7Il2lJsDs8VErKZ/BTA6ILclORRkKnBcUPZK7G1EifW2gMzjyGAHrxwKEnn0+E5gthwSNVWkrNcdhpRDQS4Jyt2GPZ2VeLuCcmcF5TYtdUHGEve++X3ozlVZ1gXlTsL2fkkmdUGmB+X2A4uCsmWwlcQ9s7goKLcpqQvygaDc1Wj3pzL9HdvhK0KtC3JeUO7ioFwZ2kNBue8Pym1KyqkmR2Fr3kasljgO+EtArgxtHDZdqGh9wNHA3oDshlIeQSYTU45NqBwp7MSmqxeti/K29R4kZUHOCspdHZQrjT0elFvLgkS9OfiboFxpbG1Q7ulBuQ2lLEjUwgxPB+VKY1HPQ2pZkFMCMl/D3iWQNJ7HfgZFi17lZkgpCzIhIFOLMaQX8TOIfFfIlaog3cDxAbnbAjKlNc8FZPZS3iLmh0lVkKjlXbRNWnovBOWeEJTrqlpBdgblSvOiZvZGvTPkqlpBXgnKlea9HJTbE5TrSlWQqDWBI+6gSGuifgbHBOW6UhXk6KDcfwblSvOi9pGv1UV6lOTrKEm1VK0gIoVSQaRolfqdSvXF7AvKPTYoV5oXdTH976BcV6qCRF1MJ7kVKIeJ+hn0BeW6UhUk6lZgxAJm0preoNzdQbmuVAWJ2iAl2aQ2+b+oZXpqVZCofTpOCcqV5p0clFurguwjZlrIxIBMac07AzJfpYaLNkRMaoveAFQai/gZJHsJLmVBdgRk9mA7E0kaE4i5i/VCQGZTUhbk2aDcc4NypbHzg3Ij/pg2pYoFKXIrMGlN1FKyyV6lTlmQDUG5yTddqbEPBuWuD8ptKOXSo93Y9IGId0PGo7cLyzaWmO/5fuDNwH8CshtKeQTZC2wOyr48KFeGNicodz2JygHpZ14+FZSbxQ6pNXNFUO5vg3KbkrogTwTlTgPeGpQtg51I3PVH0qVkq1qQTmBGULYM9inifpceDcptSuqC7AS2BmXreUg5OoCrg7K3kHgri9QFAVgelKuZveX4EDHzrwB+HZTbtBwKsiwod3RQrhzu+sDshwOzm5JDQR4n5v2QqAXM5JD3Enett4e4DXmalkNB3iBm082oJ/VyyG2B2Q+T6DXbgXIoCMTskLoqIFMOuYDYB7I/DcxuWsqpJgN1YpuvFLVnyFoS769dcZ3YTl5Rdwp3YdOFki8EmMsRpB9YUGDe/AKzZLDPEXsb/X4yKAfkcwQBu5++DJg5wpx7gOtG/nFkCCdgz66itiM4gO1JuD0ovyW5HEHAvjFzGdle22uArxTzcWQIC4ndq2MlmZQD8ioI2K29aQxvr/NFwGwSvdxfE1cRNynxoO8F57ckp1OsgTqAa4BbsYlwnu3AjcAvgj9T3U0Bfge8KXCMTcCZ2NlEFnItyEGjsaPCTODd2MqJ/dhdjmeAJdhktiwu6CrsGGza+aTgcT4DPBA8RktyL4ikNwp7aDc7eJwdWAGTPxwcKLdrEMnP94kvB9jpdFblAB1BxLcAuLmEcTZj1x7ZnSrrCCJDuYFyygHwNTIsB6ggcmS3A3eWNNYy4t4JGjGdYslAo4C7gWtLGm8fdmoVtYjgiEXtVy7tpwd4ELisxDHvIONygI4gYqYAvyTu1dkj2YK9cJX1zAddg8gXsCfkZZZjP/BZMi8H6BSrzk4G7gUuTTD2HcC6BOO2TKdY9XNwmZ5vY2velu1pbAX+7B4KHokKUi/HYhfisxKNvxu77ngx0fgt0ylWfRyPrRJyRqLx+7HJiG1TDtBFel10YIsgpCoHwE1k/EBwKCpIPXyeNBfjBz0I3JVw/GHTNUj1dWErxoxPNP5j2OJy+xKNPyI6glTfDNKVYwPwEdq0HKCC1EGqO1bbsT1DXks0fiFUkOo7K8GYO4CLgVcSjF0oFaT6Gi16UbTnsJVpKrGJqgpSfWW+iLQBW7O3EuUAFaQOytqhaQ02haTtT6sGUkGq75kSxliELc3U1hfkR6KCVN+SwOx+YB7wadr4Vq5HDwqrrwNbsXBywbm7sWKsKDg3KzqCVN8B7K98kZ4E3kPFywEqSF08Avy4gJw+bIG3aVToTpVHp1j10Y0tITrcTTc3Y6/J/r6wT9QGdASpj73AHGxZn1b/3y3Yi061KgfoCFJXF2KnStOdf9OHba46H5s6UksqSL2dij2/OAN4O1aKXdiRYiUVe+g3HCqIiEPXICIOFUTEoYKIOFQQEYcKIuJQQUQcKoiIQwURcaggIg4VRMShgog4VBARhwoi4lBBRBwqiIhDBRFxqCAiDhVExKGCiDhUEBGHCiLiUEFEHCqIiEMFEXGoICIOFUTEoYKIOFQQEYcKIuJQQUQcKoiIQwURcaggIg4VRMShgog4VBARhwoi4vgvm/XRlnxwZ3wAAAAASUVORK5CYII=)}81.63%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAL00lEQVR4nO3de7BWVRnH8e/hpnYRTRHF41SIF/KGl8xRKhJE1JpyJssmHTUtc8wwy0TzjyyvM85009SS0Mlu4xQ6moiIMYkzjEU5gCIGjE1qphRoalwE+uMBg+Csd+/37Gc/a7/v7zPj+I88ayHnx1p77bXX6tm4cSMisn0DojsgkjMFRCRBARFJUEBEEhQQkQQFRCRBARFJUEBEEhQQkQQFRCRBARFJUEBEEhQQkQQFRCRBARFJUEBEEhQQkQQFRCRBARFJUEBEEhQQkQQFRCRBARFJUEBEEhQQkQQFRCRBARFJUEBEEhQQkQQFRCRBAalOL3A6cDMwH3gN2AisA5YA04BT0P/zRunR/SBtGwyMA07a9M+BBX/dYmAyMMunW1IlBaScQcAE4DTgVGDXftS6AbgcG2UkUwpIMQcA5wBnAXtWWPdm4EsV1pOKKSB968GmTpOBiY7tnAv8xLG+9IMCsq1BwBnAFGzk8PYKMApYUUNbUpJWVP5nAHA28DS24lRHOACGAl+uqS0pSSOIORl7aD44qP1ngfcGtS0J3R6Q/YAfACdGdwTYF1ge3QnZWrdOsXYArgIWkkc4oPh7FKnRoOgOBDgKuAM4KLgf/29YdAdkW900ggwCvg3MI79wAKyO7oBsq1tGkF7gl8Bx0R1J+Ft0B2Rb3fCQfhLwM/q3LcTbWqx/b0R3RLbW6VOsS4H7yTscADNROLLUqVOsIcBU7I14E3w3ugOyfZ0YkKHAr4Hx0R0p6H7gkehOyPZ12jPIMOAhYEx0Rwp6Dlt2/kd0R2T7OmkE6QUepr49VP31PDAJhSNrnfKQ3gvMoTnheAQ4GngyuiOS1gkBGQbMxvYy5e5R7EvECcALwX2RApo+xRoKzAD2j+5IH54CfgfM3fRvTacapskBGYKtVh0Z3ZEtbMCmendjq1PPhfZG+q3JAfkh+SzlLsbeu9yFRomO0tSAfA37ljvab7GXfLPR6SQdqYnvQcZj7zoiFxjuxb4n+XNgH6QGTQvICOAJ4r6dmIeNXo8FtS81a9Iy70DgV8SE45/AecCxKBxdpUnPIJcBYwPavQf4AvByQNsSrClTrDHA49h5uHV5Azv1cFqNbUpmmhCQIdhp6XUeybMEe+O9uMY2JUNNeAa5lHrD8QDwARQOIf8RZCS2oW/Hmtr7MXABsL6m9iRzuY8gN1FfOK7HHsYVDnlLzqtYE7EDF+pwORYQka3kOsUagL2lPrSGtq4FvlFDO9JAuU6xzqCecNwOXFlDO9JQOY4gg7ArCLw/gJqFner+pnM70mA5jiCfxj8cS4FPoXBIC7mNIAOARcBoxzZWY9+DL3RsQzpEbiPIKfiGA+BiFA4pKLeAXOhc/wHgNuc2pIPkNMXaD3jGsf4qbHR60bEN6TA5jSBfdK5/BQqHlJTLCDIQOwFkT6f6fwCOwU4dESkslxFkAn7hAPgqCoe0IZeAnOlY+z7sREOR0nKYYg0GVgA7O9U/Ap0+Im3KYTfvh/ELx0wUjlzshO3OPgG78npXYA12N+M87Nv/pWG960MOI8j3gYucao9Hl9NE2xF7BrwEeFeL//ZeYAq2Fy8LOQRkKT57rxZj1z2H/wa72L7AdOCQEr9mLTAZuNWlRyVFT7F68duYeBsKR6T9sTPEdi/564YAt2BTsOuq7lRZ0atY45zqvgn8wqm2tLYzdm5x2XBs6VrgtGq6077ogHzIqe4s4CWn2tLa1cCoCupsHknCRAfkKKe6053qSmu9VLdtaDfgKxXVaktkQHag3MNbURuxy2skxllUewLmuUBPhfVKiQzIofgsEiwA/u5QV4qZVHG9EdhqZIjIgHidljjHqa4U43HYRtg1e5EB2c+p7lynutLaTvjsiqjigb8tkQHxutP8T051pbU1TnW9flZaigzISIeaq4DlDnWlmA3YZUNV8z7lpk+RARnhUPMph5pSjseGw70dahYSFZDBwB4OdT2/aZdi/uJQcw/sq9PaRQXE657BvzrVleI8/gx68PkLtaWogOzmVFfvP+I971TX62cmKSogb3eqq4s243ntgfP6mUmKCsg7nOqudKorxa1yquv1M5PUaQF53amuFOf1Z/BOp7pJ0bt5q7Y2ugPC6ugOVKnTAiJSqU4LSF0XfkrfhkR3oEpRAfm3U92QlQ7ZitefwWtOdZOiAuL1m93Fqa4U5/WJbFcFxGulI+Rtq2zFa5dEyAplVEA8dnxC4KY2ecteTnW9fmaSogLyEj5nVr3boaaU8x6nuiG7JKICsh6fLQleXylKcR5/Bi8B6xzqthS5zOuxqS3s00x5y/scar7gULOQyIAsc6i5G533bqdJRuKzkhj2lWjkD9MSp7o7ONWV1o5wquv1s9JSZEA8Ps18FfiPQ10pZqxTXY+vFAuJDMh8h5oLHGpKceOc6i5yqttSZECepPqHrwcrrifF7YXPoXFvEvgXX2RANgJTK6y3DrizwnpSzkfxOUN3IX7nbbUUveLzHap7Q3ordte6xDjVqe4fneoWEh2QlcAFFdRZClxZQR1pzx7Y5Zwefu9Ut5DogADcDVzRj1+/AjgFW8GSGJ/B7zq/OU51C8khIGB30V1A+U9mFwLHoAPjIvUA5zvVXkbwtDmXgIA9QxyGXQXcyr+wKdXR+LyRl+I+Aox2qv2AU93CcrgGentGAZ/ARod9sLfjK7H7s2cBM9ALwVw8CJzoVPsE4GGn2oXkGhBphsPxu27iVeyW3JBdvJvlNMWS5rnKsfZ9BIcDFBBp3weBjznW/6lj7cI0xZJ2DADmAe93qv8idp30eqf6hWkEkXacj184AH5OBuEAjSBS3p7AYnyPWNqfwC3uW9IIImVNxTccM8kkHKCASDnnAyc7t3Gzc/1SNMWSog4BHsf3/OPFwMHYbblZ0AgiRewC/Ab/w8GvIaNwgEYQaW0QtifKazv7ZsuAA7EvCLOhEURSeoBb8A8HwLfILBygEUTSrqF/3+oUtQDb15XV9Ao0gkjfplBPOAAuJcNwgN9XYNJs12EBqcMM4KGa2ipNUyzZ0kDsmePzNbW3GjiIwKNFW9EIIpsNxfZAeb8I3NLVZBwO0AgiZjQwHTigxjYXAUeS+dXdekiXc7Czp+oMxzrgTDIPB2iK1c2GAT/Cvv2v2zeBJwLaLU1TrO7TA3wOuAG7T6Vuc7FDrrP43qMVBaS7HAfciJ0WE+FlYAyBN0aVpWeQ7nA4cA/2t3dUODZgJzA2JhygZ5BO1gOMBy7GjmaNdhkwO7oTZWmK1XmGA2cA5+J34mFZU4HzojvRDgWkM/Ri93Ochj0A5zR1no29fMx+SXd7FJBmGo6diTt20789rl6uwnxsmvdKdEfapYA0Rw/wceAS7NC23D2DBfjl6I70hx7Sm2EEdtLg8dEdKWgZNnI0OhyggDTBQdhROHtHd6SgJcAEOuQ6PE2x8jYc2yfVG92Rgp4AJtIBI8dmOa12yLZupznhmI2toHVMOEABydnx2NJtE9yFLeU2drWqLwpIvi6O7kABG4Cv05Ct6+3QM0ie3oZdOTckuiMJK4HPYt+UdyytYuVpDHmH4zHgdDpkpSpFU6w87RPdgT6sx74jH0cXhAM0guTK+wzcdjwJnI0tO3cNjSB5ymmpdA12LOiRdFk4QCNIrp6O7sAmM4GLyOhCm7ppBMnTcuDZwPYXYR9ZTaKLwwEKSM4irkFehh0DdBh25UHX03uQfO0OLMVOPPS2BLgeeyOe3RUEkTSC5GsF9u2Hp4ewqdRo4A4Ujm1oBMnfTcCFFdZ7EbgTmIaNHJKgVaz8XQS8hp0K0q6V2Nm7dwMPo5GiMI0gzXEC8D2Kn1TyNLZPagYwBzsPV0pSQJplAHAS8EngWGAkNgt4HZsuzQMexQ6I64qtIN4UEJEErWKJJCggIgkKiEiCAiKSoICIJCggIgkKiEiCAiKSoICIJCggIgkKiEiCAiKSoICIJCggIgkKiEiCAiKSoICIJCggIgkKiEiCAiKSoICIJCggIgkKiEiCAiKSoICIJCggIgkKiEiCAiKSoICIJCggIgn/BZv6F87Jrjj7AAAAAElFTkSuQmCC)}83.67%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAMLklEQVR4nO3df6xXdR3H8efl8sMUE7VLN2A2DQEtXJqWlT9QUlhz6szNMmf5u62mVjrzx+ZqadbKzNkfTl3lsrkyUzMH2hR/VSrqEkER0dmCFEIg8BcCtz/e14l4+dzvj/M+78855/XYnP/g+7y58uJzPuecz+fTMzAwgIgMbUR0AyI5U0BEEhQQkQQFRCRBARFJUEBEEhQQkQQFRCRBARFJUEBEEhQQkQQFRCRBARFJUEBEEhQQkQQFRCRBARFJUEBEEhQQkQQFRCRBARFJUEBEEhQQkQQFRCRBARFJUEBEEhQQkQQFRCRhZHQDDTUSGA/sAuwAjAV23OrXrBv8Zz2wBngF2FRij4IC4mkMsA+wNzAFmAbsDkzAwtHTZr3NwApgGbAYeAC4FVhZUL8yhB4df1CYScAM4BBgf2A6/n8BvQ3cAFwCrHK+ViMpIJ0bBRwKHA0cCUwN7GUFcDzwYGAPtaSAtKcXOAL4KnAUMC62nfd4CzgWmBPdSJ0oIK2ZCpyBBaM/uJeUdcB+wPPRjdSFArJtI4DZwNnArOBe2nEfcHh0E3WhgLzfSOBE4HvAXsG9dGomcG90E3WgF4XvGgF8HXgW+A3VDQfA6dEN1IVGEHMk8FPs0WwdrAL6AP3P7VLTR5DJ2FOfudQnHAC7Ah+JbqIOmhqQUcBFwNNUawLejvHRDdRBEz812Q+4Efh4dCPONkY3UAdNGkF6gQuBR6h/OACWRzdQB00ZQSYCNwMHRTdSkn8Br0Y3UQdNGEEOA56gOeEA+HN0A3VR94B8F7iHZk1YB4Bro5uoi7reYvVif0hOi24kwI3Agugm6qKOLwrHAn/AvqNqmhextSiafxSkbiNIH/bSb9/oRgK8jH0RoHAUqE5zkD7sA70mhuPvwGfQZ+6Fq0tAJgHzgE8E91G2pcCZwMHYo10pWB3mIH3Aw8Ce0Y20YA32tfBzwEvYy7wVwFrgNeDNwV+3HTaX2gl7Ajdx8N+jsZWDS4D7gfnog0RXVZ+DjAXuIt9wLMBu+x4GHgdeiG1H2lXlgIwG/oQ9tcnFRuy9y23AHdjEWSqsygG5DvhCdBODFmH9/A67ZZKaqGpAvgOcHN0EcCdwFXYbpblADVVxkn4Etsgp8gnc7cD3gScDe5ASVC0gk4CngJ2Drv8YNno9FHR9KVmV3oP0Yvf4EeFYC5yFvYxTOBqkSnOQi7EXYmW7E9s0Tk+kGqgqt1ifBv6GjSJleQP4Nvp0vNGqEJBR2GS4zGWyS4HjsPmONFgV5iAXUm447gYOQOEQ8h9BpmJ/UEeXdL1fYZPxt0u6nmQu9xHkSsoLx4+BU1E4ZAs5B2QW8MWSrvUjbLNqkffI9RZrJDYxL2N9x+XYI2SR98l1BDmJcsLxzvl+IkPKcQQZiS0q+pjzdeZgx6jpaGXZphxHkJPwD8cS4CsoHDKM3EaQHmz0mOJ4jdexRVbPOF5DaiK3EWQWvuEAOBeFQ1qUW0DOda7/R2zln0hLcrrFmgIsdqy/GtgbfZUrbchpBPHeR/c8FA5pUy4jSC+28dkEp/qPYYudsvjNSnXkMoLMxC8cYHMbhUPalktATnKsfTu22EqkbTncYo3E9pLyWmu+H9p9RDqUwwhyMH7h+AsKh3Qhh4Ac41j75461pQFyuMV6Fls5WLRF2BfB4b9Bqa7oEaQfn3CAfcqucEhXogMyw6nuJmyTOZGu1DUgf0VvzaUA0QHxOtvjdqe60jCRk/RRwHp8di2ZBCxzqCsNEzmCTMcnHAtROKQg0QHxMM+prjRQ5O7uk53q6niC/O05+M/22Km9L2CrPDdHNjWUyIB4nUz7uFNd6c5u2FfVJzD0l9urgVuwI+0WldhXUuQk/XHsQ8Ii/Q8Yh14Q5qQXOB+4FDv/fTibgWuAC3j33PgwkQF5BRhfcM1HsYVRkocxwO+Bozv4b/+B7Vu2qtCO2hQ1SR8B9DnUfd6hpnSmB/uaoZNwAByIne41prCOOhAVkD7sB1i0Fx1qSme+iR1C1I0DsY3Fw0QF5ENOdZc71ZX2jAN+WFCts/H7oHVYUQHZ0anuSqe60p7TgZ0KqtULnFNQrbZFBaSVpxmd+K9TXWnP8Q71PG7JhxUVkO2d6m50qiutG03xH6H24b+h+ZCiAuJ1rNo6p7rSut3wOa67UQF5w6nueqe60rqxTnU/4FQ3KSogSx1qbsJ2Z5RYXg9gNjjVTYoMSNFPnOYT9EOU9/D6vu91p7pJUQEZwD5MK1LR9aQzXu+4Qr7LilwP8guKOwJtLXB9QbWkOx6fEEHQA5jIgCwGri6o1iXAmoJqSXe8NiEPeccVvWnDhdhXm924FfhlAb1IMXZ3qDlA0FcS0QF5C/ukudOQ3AGciNZ/5MRjpehKglYbRgcE7Hv/w7DbrVZ/CG9io89xWMgkDz3ANIe6/3ao2ZIcAgL2B/4cbCOH67Dll0NZjm1IPRW4Ap1znpvJwAcd6i5xqNmSyDXpQ1kEnAl8A9gL2ANbMPM69kMK+0FJSz7lVFcB2cpmbH+rhdGNSFsOcqobtlI0l1ssqYcZTnUXONUdVg7ng0g9TMRnMr0B+wDybYfaw9IIIkXpdHOG4SwgKByggEhxjnWqO9+pbksUEClCP3bWvYd5TnVbooBIEU7EZxUhKCBScT3AaU61FxN8UpgCIt2aCeztVHuOU92WKSDSrXMda4cfpaf3INKNfYEnnGqvxjY3D93KSSOIdONSx9p3ksE+ZwqIdOpzwDGO9X/rWLtlusWSTvQAjwAHONVfjm1AF76cQSOIdOIU/MIBNnqEhwM0gkj7+rF1Ozs7XmMq8Jxj/ZZpBJF2XYNvOOaSSThAAZH2nAF8yfkaVznXb4tusaRVe2Ff1nodXQE2ckwjo11qNIJIK8Zhb7U9wwF2HmE24QCNIDK8Xuyl3Wzn6yzFRo/wl4Nb0ggiKT3AtfiHA+zQz6zCARpBJO0y4KISrvM09l1XdgHJddsfiXc5tntlGc4jw3CAAiJDuwK4oKRr3YW9+8iSbrFkS6OwOccpJV1vA7APtnIwSxpB5B07AzcDR5Z4zcvIOBygEUTMPtg5K2UetbwQm5iH7XnVCj3mlbOw81nKDMcm4FQyDwfoFqvJ+rGjJo4KuPYPgEcDrts23WI1Tw/20eFPgJ0Crv8gdmBSFus9hqOANMtBwJX4LnZKWY3Nd8JOjGqX5iDNsC9wG/a3d1Q4NgMnUKFwgOYgddYDHI7tWxUxz9ja+cA90U20S7dY9TMe2yv3DPx2PGzXjcDXopvohAJSD/3Y+RzHAkeQ153BPdgItiG6kU4oINW0B3Zg5uex26jpse1s03zsidX66EY6pYD46wH2Bw4F9sRO7d0ArACWDf57LfaH6M3B/2Y7YAfsMex4YALwUWAKtqhoXHntd2wJFuCV0Y10I6ehuG56sbfFF1DuW+ocLAJmUfFwgALiZTfsw7/PRjcS4Gnstq/y4QAFxMNk7H1Df3QjAZ6kJiPHO/SisFi7AHfTzHDMAQ6hRuEABaRoVwK7RzcR4AbsUW5ln1Zti55iFWc68E/sqVVTbMIeQvwsuhEvmoMU5yyaFY4VwJeB+6Ib8aQRpDgvYU+vmuAhLBzLohvxpjlIMXahGeHYiO2TNYMGhAN0i1WUCdENlGAhcDJ+h3ZmSSNIMer8F81bwMX4nmibrTr/jy3TiugGnMwFvgU8H91IFI0gxfgPsCq6iQItwN6Iz6bB4QAFpCgD2Bv0qluK7ar4Serx++maAlKc66Mb6MIz2Iq/acCvsfXjgt6DFO1ebIFQVcwFrsa+o1IohqCAFGsy9qRnx+hGEl4GbsI2jct6X9wcKCDFm41tsTMmupEtrMGOUbsJWyNeiU3bcqCA+DgYuAVbLhtlMTbRvgO4nwrsg5sjBcTPrti5e6dh52542og9mp0PPADMo2IbtOVKAfHXBxyHLSaaCkzERpZ2nyAOYC8klwMvAs9i54ovAp7C3nhLwRSQGL3Ah7HdScZik/qtJ/brsAVIrwGvYuHI8hy/OlNARBL0olAkQQERSVBARBIUEJEEBUQkQQERSVBARBIUEJEEBUQkQQERSVBARBIUEJEEBUQkQQERSVBARBIUEJEEBUQkQQERSVBARBIUEJEEBUQkQQERSVBARBIUEJEEBUQkQQERSVBARBIUEJGE/wMkpE6tIAqrOgAAAABJRU5ErkJggg==)}85.71%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAMfklEQVR4nO3de7BWVRnH8e974HhpVERBkTBRNIwQNUPRQRTRLlI5WtJoMjXYYDU6pdaQlWl003HMsbKIUavRKfOSWl4iQAEZNJRAINQAxTIURMDLIAad0x/PoQ5wWOe97LWftd/9+8ycOf/A2s+B93fWWnuvvValvb0dEelai3cBIilTQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJKCndwEltQfQu9PXPsDuO/yZ14G3gU3AOmAtsDXHGgUFJKbdgCHA0cBRwMCOr0OAPnW0146FZDXwArAM+HvH96XAO40WLDur6PiDzPQHRgGnACdh4cjrF9AWYBEwH3gceAR4OadrNzUFpH49gZHAWcBY4AjfcnayFJgOPAjMRsOzuiggtWkBTgPGAx/H5g9FsAG4F7gLmIHCUjUFpDpHABOwYLzbuZZGvQzc2vH1vHMtyVNAdq0CjAG+jA2hKr7lZK4dG4Jd3/FdH4QuKCA7awHGAd8EhjrXkpfFwHXAHWj4tR0F5P+2BePbwPuca/HyHDARmONdSCoUEHMGNtQ4yruQBLQBlwE3eheSgrIH5FAsGGd7F5Kgi4GbvIvwVtaAtAJXdHzt4VxLqrYCJwJPeRfiqYwBOQb4FbYERMKewEJSWmVazdsTm4A/icJRrRHAqd5FeCpLQPoDjwLfQQs0a3WedwGeyhCQMcBCbN2U1O4U7wI8NXtAJgF/Bg7wLqTABnkX4KlZJ+mtwBRs/ZQ0rjew0bsID80YkF7YqtUzvAtpEm3Yy1//8S7EQ7NNWPsCM9ET8Sy9SEnDAc01B+mHvUmncGTrMe8CPDVLDzIAmEXJJ5SR3OldgKdmmIP0BeYBh3sXUoU3sKXlK4FVwEvAa8B6bBeTbXYD3gXsh92B6w+8B1tlfCS2C0oe/gYMw+YhpVT0HmRv4GHSDccSbOn4bOwJ/qqM2j0cOB7bHGIMFpoYLqHE4YBi9yC7YRsSnO5dSCdt2Dvf9wN/wHqIPByMvfV4LrY0JIu55dXYyoNSK3JAbgMu8C6iw3PALcDt+G+3cyDwWeDz1L/Tyg+Ab6HXcAsbkEuBH3kXgb3LfQPwJ9L7MFWwZ0Ffo/pe9lXgS8DdsYoqmiIGZAy2fMTzFvU0bAjyhGMNtTgaewHqHGziv6NFWI88FXgrx7qSV7SAHIz9Z3b1n5yHRdjEda7T9RtVwSb4h2Evir0KPIvdRZMuFCkgPbAHgaMcrr0e2+VkKiW/q1M2RbrNOwmfcDyETXi9J9/ioCg9yHDsYWCegX4bG07dkuM1JTFFCEgr8Ffy3cRtOfBJ7EGflFgRFit+lXzDMQ34IAqHkH4PMgjbxj+vrXmmYs8BSru8W7aXeg/yY/ILx7XARSgc0knKPcgYbF1THq4ArsnpWlIgqQakBViAbfIW23ex/bJEdpLqEOsz5BOOm1E4JCDFHqQFWx0b+x2Ph7Fj1DTnkF1KsQcZR/xwLAfOR+GQbqTWg1SwBYHDIl5jE/ZkflnEa0iTSK0HOZO44QB7l0ThkKqkFpAvRm7/PuxhoEhVUhpiDcSOJY51muzr2OYGr0RqX5pQSj3IROIetTwJhUNqlEoP0gPbAaRfpPYXYBPzJH5YKY5UepBTiRcOgMtROKQOqQTk0xHbfgDbuE2kZikMsVqBNdgZFDGcAMyP1LY0uRR6kFHEC8d0FA5pQAoB+WjEtq+P2LaUQApDrMXEOdNjJbb1pvsPKMXl3YMMIN6BN1NQOKRB3gGJtc9VO/CbSG1LiXgHZESkdmcBqyO1LSXSrAG5K1K7UjKek/Q9gDeJs1viQOx0VpGGePYgg4kTjmdROCQjngHZP1K7MyO1KyXkGZBY154XqV0pIc+ArInUblFOfZIC8JyktwIbsfPAs7KGuMvmpWQ8e5At2FmDWXog4/ak5Lyfg0zJuL1fZNyelJx3QKYBj2bU1j3Akxm1JQKksZr3UOwEqX0baGMNtp/W2kwqEung3YMAvIDtkVvv+dzrsHdKFA7JXAoBATt3fBSwosa/twQYCSzMvCIR0gkI2Id8GHAl1iuErAYuA47DdoIXiSKFOUhXWoHRwMnYTu97YkOw5VhvMwvtzC45SDUg0nx6YPufjcRehd4LO4t+BfAYdjdzi1dxuxJjNa1IZ63Axdhx3v0Df24dcCO20cbbOdRVFfUgEtNg7OW1WvYdWIEdopTEjRcFRGI5FltK1KeOv/sWdut+bqYV1UEBkRgOwLZzOrCBNjYCH8Cek7lJ6TavNI+f0Vg4wFZW3JJBLQ1RDyJZG062271+BFuz50I9iGTtoozb+0LG7dVEPYhk7RUaH151tgkbbrk8I1EPIlkaRLbhAHvj9MiM26yaAiJZOiFSu1mHrmoKiGTppEjttkVqt1sKiGRpTKR2X4vUbrc0SZesHAKsitDuVmBvYHOEtrulHkSycmakdhfiFA5QQCQ750Zq13UjQAVEstAfe9cjBgVECu98oBKp7TmR2q2KJunSqAr2KvSgCG0vwfYpcKMeRBr1IeKEA7LfmrZmCog06vKIbT8cse2qaIgljTge+EuktjdgS0xcN3JQDyKNuDJi23eTwC4nCojU6xTgYxHb/13EtqumIZbUo4LtpH9cpPZfAQaQwOaA6kGkHhOJFw6AX5JAOEA9iNSuH3bUdq9I7bcDhxFn4WPN1INIraYQLxwAD5FIOEABkdpMBM6KfI2fR26/JhpiSbWGYBPzLE8l3tFi4BhsmJUE9SBSjX2B+4gbDoAfklA4QD2IdK8H8Edsr9yYVmCbXbu9f94V9SDSnSnEDwfAZBILB6gHkbDJxF1Oss0i7LlKcgFRDyK78nXyCQfY4TrJhQN0wpR07RpgUk7XegiYmdO1aqYhlnTWAzu6YGJO19sMDAVW5nS9mqkHkW32Ae4EPpzjNSeTcDhAPYiYo4B7sNNn87IUO0HK/Z2PEE3S5ULsrcA8w7EVmEDi4QANscrsIOBm4u2IGHIVtmwleRpilU8LNgn/PrCfw/XnAKeRyPse3VFAwvbDDm/pi91xeR5bElHUf7SRwE+wBYEe1ndc+59O16+Zhlg72wv7DTuerj9I64HfAz8Fns6xrkaMAK4m3ztUO2oDxlGgcIB6kB19CnsO0LfKPz8DuA6YTnq9SgU7IfZS4AznWgAuA27wLqJWCoipAN8DvlHn31+OTXh/DazJqqg6HQRcgN2dGuxcyza3Yz1y4Sgg5ipsCNKoNmAWcBfwIPkNJwYAn8De9judtG7fzwDGAv/2LqQeCgiMBh6J1Paz2DqjecB8bIKfhYHAcGxvqlHYg74ULcD+fd/0LqReZQ9IC/aa5/tzut4bWGieAf4BrAbWYhP/TWz/W7YXdhdtf6yHGIhtEj0MWxaSuhXYoZ6vehfSiLIHZCzwgHcRTWgldqDOS851NCylsaqHcd4FNKGl2POWwocD9BzkZO8CmswS7CjoQg+rOivzEKsHNuYvey+alenYQZ6vexeSpTJ/OPam3D9/lm7F5nNNFQ4o9wdkI7bsWurXhr27fiEFWLpejzIHBBJ/my1xa7HzCa/1LiSmsgdktncBBTUXOJaEN1vIStkD8lvvAgpmK7YsZzT2kLPplfku1jaPY8vBJexp4HPYJm+lUfYeBOASNFkP2Yz1GsMpWThAAQF4CviKdxGJuhc79mAyTXqXqjsKiLkJC0mS2186WILdoToHeMG5Fleag2xvFDCVdF40ytszWG9xJ/plAagH2dEcbCvM8dgy+LJYCpyH/ex3oHD8j3qQXatg73Jf3vG94ltO5tqxtx5vxJ5n6IPQBQWkOodhOwFOwN75LrJ/Abdh66eWO9eSPAWkNj2xd77PBc4GevuWU7UN2DFqt2GvF2sIVSUFpH49sXfCx2JDsKG+5exkOTaEuh9bGqJnPXVQQLJzELal5onA8dimc605XXsrsAzbHGI2drOhFEtBYlNA4tkd61WGAO/t+H4o0B84gPom/euAF4FVHV9LsCUgyyjotjqpU0B89MRC0gc7e3xPbBeTzt7BdkHZ0Olrc441CgqISJAeFIoEKCAiAQqISIACIhKggIgEKCAiAQqISIACIhKggIgEKCAiAQqISIACIhKggIgEKCAiAQqISIACIhKggIgEKCAiAQqISIACIhKggIgEKCAiAQqISIACIhKggIgEKCAiAQqISIACIhLwX0RtpuHcxjHsAAAAAElFTkSuQmCC)}87.76%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAANVUlEQVR4nO3de7CXRR3H8ffvHOBo6IgmiEoqgRcUFTALNcsbaorgVJqXUcsUtLS0nDRLxzFRUtIaNK9DjeW9mlBRMBXGG4ZjeBRExZNp3hBLUElR4PTH98dw5LL+Ls8+u/s8n9fMGWbssPuNcz6/fZ59dvepdHZ2IiJr1xK6AJGYKSAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuLQLXQBJVUBegN9gA2A9bp8AXwE/K/65/vAW8BCYHnulZacAuJPGzAI2KH6NQgYAGyBBaO1zvY6saC8CXQA84Dnq3/OBT7IpGr5hIpef5CZLYAvA8OBPYFhQPec+l4GtAOPV78eAl7Jqe9CU0Aa1wrsBRxa/dopbDlrmAtMrX49DCwNW06aFJD6tAD7AscBo4FeYcup2WLgz8DNwAx0L1MzBaQ22wHfxoLRL2wpTXsDuAn4LfBS4Fqip4CsWwU4APgRcHDgWnzoBO4BrgTuA1aELSdOCsiaugHHAmcBgwPXkpd5wIXA7Sgon6CArNICHAlchE3HltE8YDzwRxQUQAFZaSQWjF1DFxKJduBMYHroQkIre0D6AxOxaVpZ02TsUvPF0IWEUta1WG3Az4FnUThcRgNzgJ9S0lUXZRxBhmLTnINCF5KYp4ATgdmhC8lTmUaQVuyTcBYKRyOGAE9gI29pfm/KMoJ8DrgFWxoizXsQe2j6euhCfCtDQPbF5vc3DV1IwSwEjgHuD12IT0UfKs8A/obC4UNvYBr2b1xYRR1BegDXA8eHLqQkrgdOwzZ4FUoRA9ITW7l6UOhCSuYB4OvAu6ELyVLRAtIbmALsHrqQkpqFPVd6O3QhWSlSQPphsyvbhi6k5OZgo3chZriKEpB+2Eagsi4yjE0HsAc205W0IgSkN7aldPvQhdRgCfActsTlFexT9i3skmQZdoIJwPrYcpheQF9gM2AbVh0AkcJOxoexKfakdy+mHpANsR9ErKtw52L1PYodppDVor9tgC9hn9L7ATtn1G7Wvo/tXExWygFpxW7IY5qtWoE9OJuM1fZyTv32A74GHAHsTzzPt94Etibh6d+UA3INMDZ0EVXPAr/DFkG+EbiWvsDRwKnEMWExCrgrdBGNiuWTpl5nEUc4pmIj2GBgAuHDAfapfQV2T3YQ9rQ7pAMD99+UFEeQfbCHUiHDPQU4j3SWfg/HVuGG2PsyA7tZT1JqI0hf4FbC1T0LOzVxJOmEA2yCYCT2i/pUzn1vnHN/mUopIK3YkvXNAvT9DnZJtwcwM0D/WZkB7AacAryXU5/JXaJ0lVJAzsEur/J2F3Y9fx3FOOljBXAttmns7hz6ezWHPrxJJSA7A+fn3OcS4CRsFib5J8Jr8RpwGPaswue5vU96bNu7FG7Su2NbPfN8GNgBHI6tKyqDXbAV0AM9tD2MtO7XPiGFEeRc8g3HvcAXKE84AJ7GnsxnfQ7WTBIOB8Q/gvTHTvtry6m/ScAYEl8/1IRuwNXYpWWzOrH3pTyWQVvBxD6CTCC/cIzDfjHKGg6wBZNjgMsyaGs8iYcD4h5B9ie/AwEuBn6WU1+pOAe4pMG/Own7sIn2l6tWsQakBTsfNo/T1X+J/TLImr6FTQlvVOP3f4ytMLiUAoQD4r3EOpJ8wjEJhcPlNuwZ0K9x7zX/CDsRfjD2gVOIcECcI0gLNoPk+/TD+7G1Sckuxc5ZG7A3dnTrltX/9h9sBmwG9pq3wokxIEdhS0p86sCmchd57kcSF1tAKtjosaPHPpZiq1vzXrQnCYrtHmQEfsMB8AMUDqlRbAE53XP792CLDkVqEtMl1gBgPnaZ5cNiYCdskZ5ITWIaQcbiLxxg07kKh9QlphHkJew4Gx/asY1CZV5GIg2IZQTpi79wgN2YKxxSt1gC8nmPbU8DHvLYvhRYLAHp4bHtCzy2LQUXS0CWeGr3PuxED5GGxBKQ+Z7avcJTu1ISsQRkETbTlKUXCH+qoCQuloCAnWubpYkUaNm1hBHTc5Be2CrbTTJo6w3s4GZf9zZSEjGNIIuAMzNq64coHJKBmAICcCN2qkYzrgDuyKAWkegCArai98oG/+6vgB9nWIuUXEz3IKv7JvAbYIsavvcVLFh3eq1ISifmgACsBxyDbcPdE+jZ5X97D3gEex3CrWhvuXgQe0C6qmCLGtuAD4EFaBpXPEspICK5i/EmXSQaCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4tAtdAFSChVgM+yUmqXAmyRy4IZGEPGlB3A89urtxdh5yS8Br2NHNt0HnIiFJlo61UR8GIWdrr9VDd/7OnaW8p+8VtQgjSCSpQowAZhMbeEAOznzDixQrZ7qaphGEMnS5TR3Qv/VwPcyqiUTCohk5Qjg9gzaOQE75T8KCohkoSf2nsnNM2jrv8AA7H0xwekeRLLwHbIJB9gbxk7OqK2maQSRZlWA54DtMmyzHRiSYXsN0wgizTqIbMMBsCv2zsrgFBBpVlbvlVzdtp7arYsCIs0YDhzoqe2en/4t/ikg0owLPLYdxRvDFBBp1Few+w9f/umx7ZppFksa0Qo8id1M+/AvoL+ntuuiEUQacTL+wgERvedeI4jUa0tgLrCRp/Y7sRmsDk/t10UjiNTrOvyFA2AKkYQDFBCpzxjgEM99TPTcfl10iSW1GgI8jr2n3pdngcFEtB1XI4jUohe2489nOAB+QUThgGKPIBsB+wC7AJ+t/rfXgNnAw9jhAfLpemD3BQd47mceNnqs8NxPXYp4qsl2wHnAkdgPd23eBSYB44EFOdWVqqvxHw6AC4ksHFCsEaQC/AQbprvX+HcWA2OB23wVlbjxwNk59DMHe64SXUCKcg9SAW7AfqC1hgPsMuxW4BwfRSVuHPmEA+AMIgwHFCcg47Azlhp1CXApFrSyqwAXAefm1N9fgAdy6qtuRbjE2gu76c7il/sG4FRgWQZtpagVexDYzIdNPZYCg7AD5aJUhBHkMrL75D8JO/Fvk4zaS0kv4C7yCwfYyB1tOCD9EWQo8A8P7b4IfAN42kPbMRoM/BU7TSQv7cDuwMc59lm31EeQ0Z7aHQjMIrJDzDz5LvaEPM9wfAQcR+ThgPQDspvHttuAq7DLji099hNKb+BO7L4r7+2tFwLP5NxnQ1IPSL8c+hiJPeUdS/r/XmD/H8YAzwOHBeh/BjYdn4TUf+B5TctuCFyD7aLbJ6c+fdgDmAlcC2wcoP8FwNHA8gB9NyT1gLyTc39DgOnA3diJHqkYitX8GPDFQDWsAI7CXp6TjNQDMidQv4din8RTsWNvYnzAWMFquxeb6Ts0bDmcjV1eJSX1ad7DsBvN0OZji/puIfwn5ObAsdh5uTsGrmWla4FTQhfRiNQD0gN4GegbupCqFdiyiTuwT+5Xc+p3a2yEGI2tvI3pymAaVlsy9x1dpR4QsGcVV4UuYh2eAR7ELsf+jh1nk4WB2D3QXsDewE4ZtZu1dqy+90IX0qgiBKQVu3HeO3QhNViEnYT+HBaWBdgl2SJsXdIH1e/bANursynQB3tN2VbYJdMORHIs56d4HvuZLAxdSDOKEBCwh14zyfdpsKxbBzYdntclpjcxXas2YyF2FGaoWS1ZZT4FCQcUJyBgrxPeF1tDJWE8gd0XFSIcUKyAALwNjCDiDTgFNg37gEr6nmN1RQsI2IEMhwDXhy6kRG4ERgFLQheStSIGBGw59Rjs7UdR7nUuiOXYv/EJRPI+j6wVZRbL5QDgZmymS7LzNna00vTQhfhU1BGkq/uxRYYPhi6kQB4FhlHwcEA5AgI2wzUCO1AuySUPkViGnXbyVeDfgWvJRRkusVY3FDtVMYr3cCdkHrYIcnboQvJUlhGkq9nYYQHnovN5a/EhNvIOpWThgHKOIF0NBCbg7/CH1E0BTifyo3l8KuMI0tWLwOHAftjKUzHt2F6bkZQ4HKCArDQdm5U5AbvWLqsObM/4MGyLbumV/RJrbVqw+f3zsWMxy2AOdql5E+U9dnWtFJB1a8H2dJ+GLV2Jcd95s6YCl2PPivSLsBYKSG36YzsXj8X2fKfsVeAPwO+BF8KWEj8FpD6t2F6HY7Cze32+DjlLi4DJWDCmo/VpNVNAGteGbSk9uPoV277wudg07RRsaYhWEDRAAcnOVtiuxuHVr13J7x2QH2NnXz2GHUT9CLa8RpqkgPizPjaqDAK2r/45ADuiqA/13/QvB97CfvE7sOnolQdAzEOrArxQQMJoxZbf98FOMOkBfIZVb+X9sMvX+1gwFqKZptwpICIOepIu4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIgwIi4qCAiDgoICIOCoiIw/8B/FrGt/wZrEkAAAAASUVORK5CYII=)}89.8%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAANz0lEQVR4nO3debCf0wHG8e/NJlpKS1BiD4MkYm+YaJJaa9dqtVW11BLUjNrpUKXTEUv9UTutplqlTMVStSSxtigVEUEtoUUqiApaQpLbP56bkSE5ub/ffd/3nPO+z2fmTsbMzTnHvb8n57xnezs6Ozsxs0XrFbsBZilzQMwCHBCzAAfELMABMQtwQMwCHBCzAAfELMABMQtwQMwCHBCzAAfELMABMQtwQMwCHBCzAAfELMABMQtwQMwCHBCzAAfELMABMQtwQMwCHBCzAAfELMABMQtwQMwCHBCzAAfELKBP7AY0VG9gZeBzQH9g+a4/+wPzgHe7vm828CHwOvBG9c00B6Q8fYENgGHAxsCawBrAQOCLKCSt+AiYCcwAXgGmAU91fT2DgmQF6/DrDwqzCjCq62s4sBEKSRXmAVOAB7q+7gdeq6juWnNA2tcbhWEv4CsoECl5DrgVuAmFZl7c5uTJAWlNX2A74BvAHsCKcZvTbW+hsPweuAuHpdsckO5ZEzgUOAQ9XOfsVeDXXV/PR21JBhyQxesAdgOOAHbu+u+6mQicC9wJ+IOwCA7Ip/UCvgmcjGagmuAJFJRrgbmR25IUB+RjvYD9gVOB9SO3JZYXgdPQs8r8yG1JggMio4ALgE0ityMVk4GT0AN9ozU9IIPQ0GKv2A1J1O3AUcD02A2Jpal7sfqgodSTOBwhO6Of0clUt+iZlCb2IMOAXwKbx25IZp4EDgYeid2QKjWpB+kNnA48isPRjiHAX1Fv0pjPTVN6kNWBa4ARsRtSE5OA76FFx1prQkC2R/P7K8RuSM3MAvZFi421Vfeu8gTgDhyOMqyAfrY/iN2QMtW1B+kHXA4cELshDXE5cDQ1PJNSx4AsB9yAhlZWnYnA19EpyNqoW0AGoNXfpuyhSs1kYCdqdDy4Ts8gA4H7cDhi2hS4F/0uaqEuPchA4B5g3cjtMHkB7W97JXI7eqwOARkAPEge4XgXrUg/hz48L6OLGN4D5gDvoG0wy6DzJyuiA1qrAquhY70bAp+tuuFteBoYSebDrdwDshxwN+raUzQN9Wz3ohX8l+j5waQOYC10McS2aPFzaA/LLMtkYDQZP7jnHJB+aLfp6NgNWchcFIYbgBtR71CFgeiM/J7oAomUrnOaCOxCplPAuQakA7iKdNY5nkVrAeOANyO3ZWV08Osg0rlp5TJgTOxGtCPXgJwIjI3dCLSSPBYNo1L8QW6PdhPsGLshaCHxwtiNaFWOAdkJuI24U9Q3Az8ln63fw1B7d4vYhnnofMmEiG1oWW4BGQg8Try9VZOBH6LnjBxtC5wHbBWp/lnoGtYZkepvWU4LhX2A64kTjtloDL0F+YYDdCXpcHSVUYyZpRWA35DR5y6bhqJLBIZHqPc2YDB60KzDTR+dwKXoYu3xEerfDj1DZiGXIdYmwMNoarcqc4Bj0IepzsagG136V1jnXGBrtDaUtBwC0hc9DFe5x+p5dP/u4xXWGdNg1JsMqrDOqcBmJH5RXQ5DrFOpNhyTgC1pTjhAK/5fotrTgUOB4yqsry2p9yCroNv+qur+xwGHkemqbwH6AJegS7qr8D66DCLZe7dS70HGUF04xgIH0txwgIY7hwHnV1Tf0sBFFdXVltQDUtWlbmPRdTamWa7jgTMrqm9nEj79mfIQ6zNoe3jZIT6XjKYdK3Y+cGwF9TyG1piS+zCm3IOsQfntG4fWV2zRjke3UJZtM+A7FdTTspR7kGGUO5N0F9qb1ORnju7oizZlln2sYDp67URSr4dLuQcpc9v4dHTpmcOxZB8B+1D+TNM6wO4l19GylAMyg3L2C30AfA34Twll19VbaMJkTsn17F1y+S1LOSCd6Dht0Y5G7xS31kyl/IW9WLuMFyvlgABcXXB5twFXFlxmk1wM3FJi+WuXWHZbUn5IBwV4Clpt7am30PaGbM4iJGpV4Blg2RLK7iSxf7STaswizEfbHorY0HYkDkcRZlDeouqsksptW+oBAW1zP6qHZZwLXFdAW0wupZyt6tNKKLNHcggI6MaQg2lvWvYMvFJetPnoMoiiJfeukdSfQT5pKHpQ7M6bop5C764oYybM5FZg14LK6gTWQ9eWJiO3gCywDdqaMBL9UJdCzynTgb+gs+t3UI8jsikbjCZRehdQ1m/RfV5JyTUglo6fAaf0sIzX0W0nVd1E2W0OiPVUb3TNarvbRN5HW97vK6xFBcrlId3SNQ/t1bqmjb/7Jrr1MclwgANixfgQ2A89Q7zcje/vBH6HJl0eKLFdPeYhlhWtH9oMuhe6x2w1dNZ9NnpnyAR0edxzsRrYCgfELMBDLLMAB8QswAExC3BAzAIcELMAB8QswAExC3BAzAIcELMAB8QswAExC3BAzAIcELMAB8QswAExC3BAzAIcELMAB8QswAExC3BAzAIcELMAB8QswAExC3BAzAIcELMAB8QswAExC3BAzAIcELMAB8QswAExC8gpIOsBZwEPAm+jtxR9BLwEXAt8C728xawwObxAZxXgPPTa544lfO/LwKnolcJmPZZ6QEagN6iu2OLfuwY4CL07z6xtKQfky8DtwNJt/v1bgL3RW1jN2pLqM8jKwPW0Hw7Qe7vPKqY51lSpBuQ8YKUCyjkRGFxAORbWC/gq8CvgH2jypBP4AJgKXAhsE611PZDiEGtd9IrgJT2Qd9efgN0KKss+bTQKwEbd+N4HgCNRaLKQYg/SndmqVuwKjCqwPPvYj4FJdC8coEmXR9EEShZSDMh2JZR5Lmn+v+bsHOCMNv5ePzQUO6zQ1pQkxSHWG7Q+rdsdRwEXl1BuE+2LFmd7Yi7qUR7ueXPKk2JA5lPsEGuBd4ENgBkllN0kq6JniC8UUNaTwDD0O09SisOOshb3lgUupZzwNckVFBMOgCHAXgWVVYoUA/JSiWXvjmZRrD2HALsUXOb+BZdXqBQDUvaY9HxgaMl11NEw4BcllDuahHv1FANyY8nlLwWMp7hhQhN8Hvgj0L+EspdDzzVJSjEgtwDTS65jHeAGoG/J9dRBP+A69DMrSxmzloVIMSDzgNMrqGc0cAkJd+8J6AAuB3YouZ45JZffthSneUG/mEeBzSqo6+fAcRXUk6NzgBNKrmM+mmH8X8n1tCXFHgS00e2kiuo6FvhJRXXl5GzKDwdoTSXJcEC6AQGYgM6DVOF0tIPYwy05m+r+gRpfUT1tSXWItcA6aLW1J+dCWnElcATaBtFE/dAzxwEV1fcBsDbwWkX1tSzlHgQ0m1Xl8OcQ1Gs1cQp4eeDPVBcOUE+VbDgg/R4EoA/wGNUu7j2PtkBMq7DOmDZBJzgHVVjnFGBLdLgqWan3IKDhzsFUO+wZhGbRxlRYZyxjgIeoNhwfAgeSeDggj4CAPqynVVxnf7ROciO6eqhuVkOnLS9BuwuqdCbweMV1tiWHIdYCvYA7KedA1ZLMBk4GLkNT0DnrBRwKjEXbPKr2ELAtmUyE5BQQ0J6dJ4AVItX/N+B44P5I9ffUSOACYNNI9c9CzzuvRKq/ZbkMsRaYga4YjXXX1VbAfWi/2LBIbWjHlsBNwD3EC8d8YD8yCgfkFxDQAuIxkduwGxpD3wFsH7kti9OB9pvdjnq+PeI2h1PQzysruQ2xFnYpcHjsRnR5CrgKuBqYGbktK6K1jMOA9SO3ZYFx6CaT7D5sOQekH3AbcR7aF2cuugbnJuBmqhtOrIyuWd0HPWf0qaje7rgb2JlM70nOOSCgWZi7iTeuXpKp6LK0+9HszUv0/F/RDmAtYAsUhlGke3vkZDTMmx27Ie3KPSAAA4B7gQ1jN6Qb/gs8jYZkr6JJh5nAmyg476Fe6HNobWIZ1DusDgxE70gZgraHp+4FYGt0jVO26hAQ0IfnHnRtqcX3AurZspqxWpQcZ7EW5RX0C3k6cjsMnqEm4YD6BAT0CxmJxr0WxxT0XpdahAPqFRDQeHc0MDF2QxpoAvoHKutnjk+qW0BAMya7oIM/Vo1x6Bb9bGerFqeOAQHNuR8OHI1fwVam+eglRQeS6TrHktRlFitkO3SvU6wNjnU1C+2LmxC7IWWqaw+ysIloY+Gk2A2pkQfQ4mytwwHNCAhoUW4HtGEui3MIiZqL3io1Cr2TvvaaMMT6pC3RG46GxG5IZv4OfB9N5TZGU3qQhT2Cbmw8BXg/cltyMAf4ETCchoUDmtmDLGwd4CK029Q+bTy6XfH52A2JpYk9yMKmo/d774hX4Bf2OFpw3ZsGhwMckAXuQtvHvwu8GLktMT2L1jQ2R5s/G6/pQ6xF6YPm908ANo7clqpMQbcc/oGEX6gZgwOyeB1o6HUCaZ1aLEonOq9+CXArGR6HrYID0j2D0NDjQHThWs5moku6rwD+GbktyXNAWtMbLTh+G91skssl12+iM/LXo50FyV/5mQoHpH29gRHAnigs68VtzqdMQ+f1x6MHbm/abIMDUpxV0JWaI7q+hqEQVeEjdM79IRSGe0j8tQK5cEDK0w/YANio62swOju/KrqIodU37M4D/o1O6/0L3ZAyFc1APYOHTaVwQOIZAKyEgrTgEullUa/zQdfX211/voMerj1MqpgDYhbglXSzAAfELMABMQtwQMwCHBCzAAfELMABMQtwQMwCHBCzAAfELMABMQtwQMwCHBCzAAfELMABMQtwQMwCHBCzAAfELMABMQtwQMwCHBCzAAfELMABMQtwQMwCHBCzAAfELMABMQtwQMwC/g/tf+FHXlzLOAAAAABJRU5ErkJggg==)}91.84%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAOTElEQVR4nO3debCXVR3H8fddQCwVzT1wQ3FBQFMwEE3cEBiXaRPNcMktzdHGyVwySzKXrJlq1FJz3CLTTMdlWNyAKZVMSQXEhUVJckFKrpagXG5/fO8dfyL38FvOec55nufzmvmN46jnHO/l8zvPec7W1NHRgYisXXPsBoikTAERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBEHBUTEQQERcVBARBwUEBGH1tgNKKkmYLOKTwv2ZbVRxb/zPvAusLzz8y7wYbbNFAUknPWB3YBdgV0q/ro1Fop6eu+3gQXAworPbGAOsLLxJsuamnT9gTd9gBHAcGBfYC+y+wJqx0LyBPA4MB1YklHdhaaA1K8FGAYcBRyO9RYpmQc8BNwP/AX4KG5z8kkBqU0zMBIYDxwBbBq1NdVbDtwD3AU8jPU4UgUFpDo7ACcCJwDbxW1Kw94EbgVuAl6J3JbkKSBuBwPfA0bHbkggU4FfA5MB/UFYCwXk01qBrwLnAXtHbktW5gFXAn8AVkVuS1IUkI81A8cBPwJ2jNyWWBYAlwG3o3EKoIB0OQz4BbB77IYkYi7Wg06O3ZDYyh6QnbBn8DGxG5Koh4CzKPFgvqxrsdbDHqXmoHC4jMJ+RhOwn1nplLEHGQLcgh6navUCcDIwM3ZDslSmHqQF6zVmonDUYwC2jOVSSrSGryw9yLbAHdgaKWncTGAcsDh2Q0IrQw9yGDALhcOnYcCzlGD8VvSAnA9MIj9rpvJkE+BB4AJsf0shFfURqye21uibsRtSEhOBb1HADV1FDEhv4F7gwNgNKZkZ2NL/5bEb4lPRArI58CgwKHZDSmoOcBCwNHZDfClSQPoC07DZcYlnPtZ7vx67IT4UZZDeF9tmqnDEtxP2u+gbuR1eFKEH2RKbwMrDCtw24CXgRWzl7NvAO52fNj5eQdsDG0ttjL0t2hbo1/kZwCdPP0nVAmx/fq4ft/IekFZsv/Ww2A3pxmzgr52fJ4FFHspsAnbGlswMBw7t/PsUPQccQI4H7nkPyIXA5bEbUWE19pLgPmyO4LWM6u0HjAW+jD3/pzQvMR2brM3lK+A8B2RD4J/Yo0hsLwM3YxuNYh+30xfb+HUSdg5XCm7D9vTn7g9bngNyCnBj5DZMA64GppDeL78JWwpyLra3PrbzgZ/FbkSt8vwWa2zEuqcAQ7F3/qkeeNCBLbM5BDvELvbuwCuw/SW5kuceZCF2HE+WZgHfx8YZeXQA1uMNjVT/MmBPcjRHkuceJMsFiO9hW0+Hkt9wgC0H+SJwBnHeLG0K/JEc7SfJc0B6ZFTPg9jcw7XYW6q86wB+ix2Vek+E+kcAF0Woty55fsRaBGwfsPyV2AD3uoB1pOA04FdArwzrbMfmrp7OsM665LkHmRWw7FewX2DRwwFwA/bo+GKGdbZg5wL0zLDOuuQ5IFMClfsYsA+2Y64s5mBfCA9nWOfu2GarpOX5EWsjbE+0z4nC3wHfIaezvh60AtcAp2dU3wpsLPRqRvXVLM89SBv2bt2Xq4BTKW84wM7l/Tb2s8hCL+y1c7Ly3IOAvcmagS3aa8RV5KC7z9ilwCUZ1XUgtmYrOXkPCNguwhnUf8PThdjJ5vJpPwEuzqCe2dgEYnKv0fP8iNVlKbA/tQ8wV2DruRSO7l2CLcIMbRBwdAb11KwIPUiXJuB47BvPtbOwHbgb+AG2qUfcWoEHCH+J0DxgIIn1IkUKSJdmbLb2YGwGfAvgA2z9z1PYzPgb0VqXT5tgk3r9AtdzLLYUJRlFDIiEsQd25GjIGffZnfUk84eyCGMQycZzwDmB6xiE7T5MhgIitbgR22MS0hmBy6+JHrGkVn2wK9pCbXVeje3zSeLkePUgUqslhJ1UbcZWGCdBPYjUowVbTT04UPlvYT1V9Jt21YNIPdoJO2DfEhgZsPyqKSBSr+nA1IDlfz1g2VXTI5Y0Yhh2YmQIS4GtifyYpR5EGjGTcL3I5iTwmKWASKN+GbDsIwKWXRU9YkmjmrE9/CHWac0m3JuyqqgHkUatxo4RCmEQ9qgVjQIiPkwk3ALDqOcKKyDiw7+wS4xCiHoZqwIivkwMVO6QQOVWRYN08aUvdl+Lbx8Cn8VOXMmcehDx5XXs/kXfelL/gRwNU0DEp1An338hULnrpICITzMClTsgULnrpICIT/8IVO6WgcpdJwVEfJoPvB+7ET4pIOJTB2FOxX8zQJlVUUDEt6cClBnq0W2dFBDxzfdtuh8Bj3gus2oKiPj2GDYW8eVu4N8ey6uJAiK+rcbOPfZhJdldwbBWCoiEcBdwp4dyzsdvb1SzVNdibQOMAfbm43fgbcDz2BbP2ZHaJdX7DHZQeL2rcX8DnOmvOfVJLSADgcuAI7HrDLrzd6zrDXWRp/jRC9tMdUIN/80q7B71JK5mSykg5wGXY/dRVOtW7E69FUFaJL6MBiZg1013pwO4H7vfZU4WjapGKgG5jvoPLZ4GHA78z19zJJCu09sHY7cUg52i+Az2ejjEcvmGpBCQc2j8ZIw7gWM8tEXkE2IHZCesO13PQ1njsLcnIt7Efs07AT/hAPgp8f9/pGBi9iCfwxah9fBY5qFEXJYgxRPzG/cQ/IYDbO5ExJuYAQmxjXKfAGVKicUMyFYBytwT9wSjSE2KNqjdAHszJuJFzIC8FajcaCdgSPHEDMgLgco9IFC5UkIxAxJqG2XUw46lWGLOg7QC/8VOzvNtG+ykP5GGxOxBVhFu1ebhgcqVkon9FuvpQOUeF6hcKZnYAZkWqNwRwOcDlS0lEjsgoQ47bkK9iHgQe7k72D7zQQHKXQj0x07ZEKlL7B4E7BylEPoBowKVLSWRQkAeCFj2dwOWLSWQwiNWC/AG4a77HQ7MDFS2FFwKPUg7cE/A8n8csGwpuBQCAvCngGUfBowMWL4UWAqPWGCPWUsId5PQ88BeWG8lUrVUepB24KaA5Q8GTg1YvhRUKj0IwLbAIsKFdjmwO9ZTiVQllR4EYDF22HEovYEb0JZcqUFKAQE70TuksehRS2qQ0iMW2Lf7c4RZetJlBTCssx4Rp9QCAnbG7h2B61gIDAH+E7ieotka22uzD9AXWB94G9s+/SjwOAVb+5ZiQJqxjVS7Ba5nCnAEtnFL3HbEjnb9GvZKvjvzsftdbsOuM8i91MYgYN9AEzKoZzQatFfjZOwLaxzucIAduXQLdgvYpmGblY0UexCw4D5L2LFIl8uAH2ZQTx5dAFxR5387DzthZqm/5mQvxR4ErBc5O6O6LgYuzaiuPLmS+sMB9oh8H/7PX85UqgEBmI7dkZ2FS7A/EGKuxG6YbdRw4FwP5UST6iNWl+2xrrpXRvVdD5xFeQfuPYFrgVM8lrkcWyXR5rHMzKTcgwC8SmPdfK1OByZhs+5lszF2T6DPcID9LMd5LjMzqQcErLufm2F9h2IbrAZmWGdsewJPAQcFKn90oHKDy0NAPgROJNul6rtid7GflmGdsZyJfSH0D1jHXgHLDioPAQE7YC6LuZFKvbAxyZ+xGeSi6YudB3At/u6J7E6ofT7BpT5Ir9SKvdkaEaHu5dicwPXkf4a4GbuT/gpgw4zqbCOn47q89CBgb5aOAZZFqLs3ttL4b+T7eoWDsUfHa8guHBDnd+ZFngICdmL7N4i3IG4o1otNIl8X9QzB3lA9QpzxwLMR6vQibwEBeAi4MHIbxgCzsD9wY0lzPVcT1s7HsF4j5pukSRHrbkiexiCVmrBFccdHbkeXl4CbgYnEv5ekDzAeOAnYOXJbwMZv2wDvxW5IPfIaELBZ36mkdaRPB3Zi/b3Yt+bCjOrdDtuncRQ2zkjpyeAisp3s9SrPAQEbPM8A9ojdkG68DDwMPIm9qn4ZP2/BdsDWOe3X+cli1XM9ZgL7k+OlO3kPCNiRpU9im3pS14btvlvY+VmM7Wp8F3sU+ajz32sBNgI26/xsgf3/7Qrs0vnPUrcAeyUf6jbjTBQhIGCTXtPJR0jKYAH26Bt7PNawlJ5VG/E69guZH7kdYr+DkRQgHFCcgID9QvYl3MWgsm6zsd9BIcIBxQoI2PbO/bCBu2RrGjYgz/UW2zUVLSBgg91R2JyEZOP32ETk8tgN8a2IAQFbIj8em3Ev1DlNiVmNLeIcj/3MC6cob7FcxmC9ySaxG1Iwy7CbhKfGbkhIZQgI2J7oO7EjR6VxTwDHYvM4hVbUR6w1LcYGkBPQI1cj2rEr7b5ECcIB5elBKg3DLusZELshOTMX2/r8dOR2ZKosPUilmdieiJ9Q0IGlZyuxXmNvShYOKGcPUqk/trtuVOyGJGoydsJlaVcolLEHqfQKdgvuWLI9Wih1c7F5jbGUOByggHSZjC2ZPwlbaFdWC7BNaIMp+OvbapX9EWttWrF97xcQ/o6SVDwDXI0dcZTbvRshKCDd69rTfTb2GFZEU4CfY7dDyVooINXpj10kcwKwVeS2NOo14FZsT/+iuE1JnwJSmxbs7N6jga+Qn8PQlmGnKN6ObSzTZGmVFJD69cBm54/EXhOnNl6Zh907fx8295Pl2caFoYD40wfbSTcC2zQ0kHXf6efLKuycriew/fmPA0syqrvQFJBw1sNCMgjoV/HZETuEoVargXeAN7BzuF6s+Os84IPGmyxrUkDi6IldWNO787MxsEHFP2/DAtGOhaLro19WxhQQEQfNpIs4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuKggIg4KCAiDgqIiIMCIuLwf83O9mGlNXT/AAAAAElFTkSuQmCC)}93.88%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAOYElEQVR4nO3debCXVR3H8fe9LO6ioEIKkSyRAiZqiAtuhCaaC5VjamrmmDZD9UfuuUyauZUzOoU66piJNWaJpqi45oqMqckiqGCGC7iDS4lcbn98742rwLnP73ef73PO73k+rxkGZ4Tvc7j397nnPOc55zxNra2tiMiaNcdugEjKFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQnoHrsBFdUMbAJs2uH3Ddv+3wdAS9t/LwfeAd5u+10KpoD46Q6MBEYAg4DBbb+GAFvUUa8FC8liYAGwEJgDzAbmAh91vcnyeU16/UFu+gO7AzsDo4EdgHULunYLFpaZwGPAg8ArBV271BSQ+vUA9gS+CewLfCVuc1bzEnAXMA0LzCdxm9OYFJDadAe+DnwXOBjoFbc5mS0Dbgf+BNwDrIjbnMahgGQzDDgOOAboG7ktXbUEuBG4CngxcluSp4CsXTNwADAJGB+5LV6mA1cAdwL6IKyBArK6HsCRwCnANpHbUpS5wMXAFDT8+gwFZJVuwPeAs7Bp2SpaAJwH/AFYGbktSVBAzATgEmDb2A1JxCzgZ9gQrNKqHpBhwOXYNK2sbhrwY6xnqaSqrsVaFxtKPIfCETIBewB5FnZvVjlV7EHGANdjvYdkNwub6n4qdkOKVKUepAk4G1uKoXDUbiQwA/g5NqFRCVXpQZqAq4HjYzekJB4FjgAWxW6It6r0IGeicORpd+BpbNlNqVWhB9kO+2ZWZlhQoJXAadgUeSlVoQc5H4XDSzP2BP56oGfcpvgoew+yJfAqdg8ivh4EDgWWxm5Insreg+yPwlGUvYGHgM0jtyNXZQ/IqNgNqJjtgcex3ZWlUPaAbBW7ARU0BOtJShGSsh/akNoN1jJsk9JL2PqmRcB7wPttvy9v+3MbAOsAmwF9sE1ag7BtvcOAjQttde0GAw8AuwFvRW5Ll5Q9IIsjX/8F4H7sCfRMYD75hHYgsCv2PGI34Ks51MzbUOzfPpYGvnEv+yzWicDkAq/Xiv3knIqthF1Y0HX7Y3vkD8ZullP6wfcQsB+reseGUvaAfAl4uYDrzMeeBdyITSvHtAVwLHACNtRJwU3YLs2GU/aAgB198w2n2g8Av267RmpfyCZgH+xJdwpLQk4HLozdiFpVISA7YeP/PJ+H3IWtan06x5qexmB7OiZEbMNK4EDsa9cwyj7NC7Z/4eIca43DPmiNEg6wSYIDsPuTWZHa0IwNQb8Y6fp1qUIPArYW6ybgsDr//jLgVOwsqUb/gnXH7k8uIM7Bd08Ae9Agp6dUoQcBO7v2COCyOv7uVOz4nytp/HCAfTB/BwwnzqEMu2DDvYZQlR6koz2AX2HPEUJmY/tIbndvUTxNwEnYcvX1C7xuC/YMZ0aB16xLFQPSbiR20zgKmxrtjr2H4xns/Nrkv3k52g7rKbcu8JpzgB1J/FDtKgdEPqs3cDM2CVGU80l8uKWASEfdsHutorYnL8deMJTsIdpVuUmXbFqwGa5LC7peT+zw7GQpIPJ5rcDJ2IPQIuxH3AeYQRpiSchF2Cn33uZgm62SezaiHkRCTgOuLeA6w4GjCrhOzdSDSGe6Yc+CvIdBC7ANYUn1IupBpDMt2E937xPeB5Pgknj1IJLVCOBJfJ+4P48Nt5L5UKoHkaxmY+8K8bQNtuo4GQqI1OJabCuxp0nO9WuiIZbUqh82Ldvb8RrDsAMvolMPIrVajG2f9fQD5/qZqQeRejRjuyu9Tq5cDAwggSlf9SBSj5XATxzr98MOnIhOAZF6PQLc4Vh/omPtzDTEkq4Yg+0x97AEe33FSqf6magHka6Yge2+9NAXO1Y1qpSOqOxoGHAQsAM2Hm0C3sWOrLkH+6mlri8Nl2JL1j1MxIZy0aQ2xPoatsR6707+3Dxsq+Yt7i2SzjRhOwI9jjmdgy1xiSaVIVYT8Ausy+4sHGCrPv+MBWRDx3ZJ51qxV2x7GE7kN1al0IM0YQc/H13n358JjMcOd5M4+gKv4/MDdyJwq0PdTFLoQc6g/nAAjAZuyKktUp8l+N0r7OlUN5PYARkOnJtDnYNJcC9BxfzFqe4eTnUziT3EugX4Vk61XsFuFFtyqie1GQD826Hup9gelCjLTmL2IJsDh+RYbyB2LyJxLMJeJJS3Hti0fxQxAzIe2++cJ68X5Ug2f3equ61T3U7FDMj2DVJTsvO6UR/pVLdTMQMy0KHmlg41JTuvA78r2YN4vGko+kOdilsI/Mehbn+HmpmULSBvONSU7FZiJ5PkLdrIIFZAegBfcKi7yKGm1GaOQ81+DjUziRWQvuT71tl2Ckh8rznU7IG95KhwsQKykVNdjwdVUhuPgEDFArKeU90lTnUluzed6np9ZoJiBWRjp7ofOdWV7LwCsoFT3aBYAfH6x3pMMUoaPO5ZOxVzFsvDB051JTuv70Evp7pBsZe75y3vtV1Su1Ktpo4VkKVOdb1mxyQ7r+/Bp051g2IFREtCystrtinKBEysgHj9Y6PMlctneE3ARDlzIFZAvGabFJD4+jrVjTJDGSsgXnPlWznVlew8FqFCpBnKmAHxuOlSQOIb4FCzlUirJGJO8y52qDncoabUxiMgb1CxWSywg8bytg3le7bTaDy2MURbhBrzw/SqQ831gEEOdSU7jyUhlQzIXKe6Y5zqSjYeI4NXHGpmEjMgs5zqjnWqK9k82yA1MyljDxL1LFfh7pzrtQD35lwzs5gBmY/PzMQwfGZSJJt7yXdINBV4K8d6NYkZkBXAbKfaeR5pKrVpAc7MqdYK4JycatUl9pTow0518zoQW+ozBbgthzrn4nNKSmaxA+J1lutY/NYESTZHYy83qtcNwAU5taVusQPyqFPdZuAYp9qSzTJgHLW/N2QlcB5wLAlsi4gdkLfw60JPINI+Zvm/D4FvA9/BXrzamQex51hnk0A4IP4LdAAuA37qVHs8cJ9TbalNE7AL9srokUBvLASLgaeB2/F5v0iXpBCQsfjdrN+D3hkiXZBCQJqx5QleN9W74Hcsv5Rc7HsQsJuyqY7185qTlwpKISAAf3WsfSBanyV1SmGIBdAdO5nd65j7Z4CdsN5KJLNUepAV2IMhL6OA4x3rS0ml0oMAfBnfab53sS25Hlt9paRS6UEAXgCmO9bvDVzrWF9KKKWAAFzhXH8CcJzzNaREUhpigT1tnYMdvuDlY2Bn/JbaS4mk1oO0Ahc5X2N97LnLps7XkRJIrQcBm/KdBwx2vs404CBKdly/5Cu1HgRsyvf8Aq4zAbgKrfiVgBR7ELBe5FmKOSnxYuDUAq4jDSjFHgSsFzmloGudgtZryVqk2oO0uxvbP1CES7GwJP0FkWKlHpCh2HRsz4Kudw1wIrpxlzapDrHavYjdIxTleGyTVe8CrykJS70HAVgH+AfFvtrgZexsrecKvGZsY7Dh7ChgM+w+8E1sJfQd+B0Vm7RGCAjYN+9Rin3N88fAycBkyn1fchDwS2BEJ3/uceB0/LZHJyn1IVa7Gdg3sUjrA7/FJgrK+OaqLYFbsQPeOgsHwK7YOWa/oULvo2+UHgTs2cjD2B7zoi0FzgCuxoYejawJ+CG2pGfjOmvcDBxBBSYzGqUHAftgHo7t6yhaL6w3eRrYK8L187IPdtrhZOoPB8BhFN+jR9FIPUi7/bGbxpjhnoad/tcop6XsgC3f2T/Hmq3AaOCpHGsmp5F6kHZ3Ef/J9wTgCeyo/3GkuZ6rCWvn/dgsYJ7haK9/Xs41k9OIPUi7Kdg4OAULsPuT6/F7B3xW/YGjsLNthxVwva2BfxVwnSgaOSA9sYd6e0VuR0crsPNlb2v75fGi0jUZhPUWh2D3GUX2aCcBVxZ4vUI1ckDAbp4fwc56TdE/gcewZziPk8+bl5qwnmE09nxoHHbgRSyTgR9FvL6rRg8IwObYh3Bo7IZksAw7uWUesBBYArwDvA18AnzU9ud6YjseN2n7fQC2gWwI9u/sygxU3m4FJsZuhJcyBARs3P0Q/rsQZXVTgUNjN8JLI85ircmr2L3IS5HbUUWvxW6Ap7IEBCwkuxLxndoV9UzsBngqyxCro17YuHjv2A2pgFZsePt67IZ4KVMP0m4p9tKc38duSAXcQYnDAeXsQTo6GbiQcv4giK0FW8JS6j0zZf/gXIJtAno7dkNK6FxKHg4ofw/SbgBwE7B77IaUxDXYW4RL/+Epew/SbhE2DXwWFdjD4GglcA4VCQdUpwfpaCfgOtJdnpKq+dgCyEZZ4p+LqvQgHT0F7Ii9rP6TyG1pBMuxvSTbU7FwQDV7kI4GA5djK2FlddOBSdjLjSqpij1IRwuAA7CZrkoea7MWc1n1dalsOEABaTcdG0Ici4WmqhYC3we2w7YVV17Vh1hr0h04Ejund9vIbSnK89gJllOATyO3JSkKyNo1YcOMScC+kdvi5V7svZB3onfIr5ECks1Q7Cypo4C+kdvSVUuwdWrX4fva7VJQQGrTHbtxPRw7sjOlnX0hS7E98n8E7qPxD78rjAJSv3WwJfUTsCN1hsRtzmrmYZMPf8OODNW9RR0UkPwMxAKzG3agwnCKO8P2v9ipjzOBJ7FDIoo6UaXUFBA/G2CzYCOwsAzCHkz2A/pQX3jexLYVL2j7tRB7wdAsNGxyoYDE0wd7D0cfVr1BqxuwUdt/fwi8B7zf4XfNNBVMAREJ0JN0kQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAv4Hf5vftK5i/ZwAAAAASUVORK5CYII=)}95.92%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAOmklEQVR4nO3deYyV1RnH8S8zwCgRFzY3wAVZFLEoKhQTRatCKy6piVarVq1drK3VWiu2NtpoWhq1Lq1LU5fWpbY2bdxQqGjRRCvWXVBAUHFBBVQEI8oy9I9nxpmRmTP3zr3Pe857398n4Q8jPO/hzv1x3ve8Z+m2YcMGRKR9dbEbIJIyBUQkQAERCVBARAIUEJEABUQkQAERCVBARAIUEJEABUQkQAERCVBARAIUEJEABUQkQAERCVBARAIUEJEABUQkQAERCVBARAIUEJEABUQkQAERCVBARAIUEJEABUQkQAERCVBARAK6x25AQTUAfVr96g5s8YXf8xGwBlgBvA980PTfkiEFxM8mwO7AKGA4MAzYARgIDOhizaXAW8DrwHxgAfAiMAf4rLLmSnu66fiDqhkMTAD2A8YBI4H6jK69DpgL/Bd4DHgEeDOja9c0BaTrGoADgCOAicAucZuzkQXADOBeYBawNmprckoBKU8P4BDgOOBIoHfc5pRsJXAPcDvwEApLyRSQ0owAvgOcCPSP3JZKLQP+AtyAPcdIgAIStjtwKTApdkOcPARcBUwDGiO3JUkKSMd+CPwOu62qdfOBqcBt2AO/NFFA2ncxcEHsRkSwGLgIuAX1KIAC0p7jsYfZInsZOBe79So0BaStvsBCYMvYDUnEdOBsYF7shsSiuVht/RSFo7VJwPPYbVdD3KbEoR6kRT3wNrB17IYkah42zP1U7IZkST1Ii9EoHCEjgCew3qQwc/gUkBZ7xG5ADtQDF2JTVwbGbUo2FJAWXZ1hW0T7Ac8Bh8ZuiDcFpIVekJWnL/AANrBRsxSQFu/GbkAO1WFTcW4GekZuiwsFpMXTsRuQYycD97Hxqsjc0zBvWwuBIbEbkWPPYO9OlsVuSLWoB2nr+tgNyLm9qLERLvUgbfXC5iENjt2QnFsE7A8sid2QSikgGzsAeBif3nUlNrX8VeA1bPOFFcCqpv/3MbAZ9iKuDluctTWwLbA9tj5lBLCpQ9uqbQ5wEDm/3VJA2ncCtuqu0pDMAx4EZmODAAuofBp5HbAjsC+2ScQEbNeUFD2DtW9V5HZ0mQLSsUnArUC/Mv5MIzATuAt7R/B69ZvVru2Bo4CvY1/IlJ4tZwKHkdM9vRSQsD7AL4HTsFufjszBwnQb8e+7B2A94Omks9PKTcC3YzeiKxSQ0vTCplXsg23+tgm22+Fc4D/Y5m2p6QYcDJwJTI7cFrA37pfHbkS5FJBiGIfNwp0YsQ2NTdefGbENZVNAimU8cDUwJtL1lwN7Ytun5kJKD3Pi73Fs9OsMbHg5a/2Av5PdlqwVU0CKpxG4Fhsavi/C9ccDP49w3S7RLVaxdcNGuy7HBh6ysh57Lkp++a4CImA70f+TbF84zsWehZI+tkG3WAL2ZR2LvdzMykjg/Ayv1yV560G2xh4yB2ELdD4EXsKmNKyP2K5aUQ9ch23UnYU12PyyVzK6XtnyEJA64BjgR9gDXns+xN5kX0qOhhAT9htgSkbXmkHCm4OnHpBdsOkbY0v8/Z9i3fZVQNJ/sRy4ANujOAuTSXSb05QDMhbb+rIrOx3eApyKbrsqNRU4L4PrzAW+RII/r1Qf0ofR9XAAnARcWb3mFNYU4MYMrjMS27UxOSn2IHXAk1RnOkSyXXeO1AP3478H1iJsMVhS2y+l2IOcRPXmCl1BjqY1JGo9Nkiy0Pk6Q7Bp+klJrQepw4Ztq/nC6nDiTKmoNaOxvXk9d3mfD+xKQgMsqfUgh1H9t7lHV7leUT0HnON8jeHYdyAZqQXkLIeapQ4RS+euAe52vsbZzvXLktIt1nB8TjL6lHzsApIX22FbI23ueI0RJHJEdUo9yPec6mY5S7UIluA/h+q7zvVLlkoP0h073cnjCIL3KW9nEulcHbb4yuv2dSm2U0v0Id9UepCJ+J3PkURXXWMagZ851h9AImePpBKQbzjWztUmATnyKDbbwctxjrVLlsItVgPWpXo99A0j4enUObcnttTAw0ps69WoG86l0INMwC8cM1A4PD2L3yKrzYEDnWqXLIWAeL4Y0oRFf1c71o7+0jCFWyyvQ2sWYOPp0f+CNa4b9v5qmEPtV5zqlix2DzIQvxOdrkfhyMIGbBshD0OJfFZL7IBMcKq7AdugTLJxJ5Uf69CR/Z3qliR2QLz+8rOIv8t6kbyDfeYeCh2QfZzq3ulUVzrm1WPv7VS3JDEf0jfFTh7yWNC0A/CGQ13p2EDgTYe664HewGqH2p2K2YPshk84XkHhiOEtfKb11GN7Z0URMyCjnOpqakk8Xp/9SKe6nYrdg3h41KmudM7rs/f6rnQqZkB2dqr7nFNd6ZzXZ+/1XelUzIDs5FDzEzT3KqaF2M+g2jy+KyWJGZBBDjXnkODufAXSCLzgUDfa2/RYAemBTWWutlcdakp5PH4G/bDvTOZiBcQjHKDh3RR4vAsBv+9MUKyAbOVU1+uHI6Xz+hn0caobFCsgWzjVfceprpTuXae6vZ3qBsUKiNdWPB4jKFKej53q9nKqGxQrIF5LbKPM15E2vA7lLFQP4mVV7AZIbf0Mai0gIlVVawGJ0g1LGzX1M4gVEK9u2PPsCimN10bhK53qBsUKiNfD9GZOdaV0XqNNnzrVDYoVEK9/DbZxqiul29ap7kdOdYNiBeQDp7oeEyClPF4/gw+d6gbFCsgyp7oKSHxeM2+9vjNBsQKyFljuUDfawhr5nMfPYBn2nclczGFej5m3e1B7Q9d54rXBQrRJqDG/TK851OwF7OJQV0ozFJ9RLI/vSkliBsRrcdNop7rSOa/PfpFT3U7FDMhLTnWjblVZcF6f/ctOdTsVMyBzneoe7FRXOuf12b/oVLdTtbr16CBspz/JzmBgsUPdwm49uhqfHTAAvuZUVzrm9Zm/QMR1PrGHRJ9yqnusU13p2DFOdb2+IyWJHRCvrSon4DcnSDa2HX6HIUXdSrZWA1KH379osrFjsbMKPcxyqluSFA7xXIC9YPKoq0M8/Xke4rmIyC9+Y/cgANOd6g4DJjrVlhYT8TuJ9n6nuiVLISDTHGuf6VhbzFmOtT2/GyVJ4RarJzZb02sroL2AZ51qF91Q7FbWw0pgAH7bCJUkhR5kDXCPY/1fO9YuuhMca99D5HBAGgEBuMOx9iQ0P8uL57SevznWLlkKt1gA3YG3sS7Vw2xgPH6H3RfVcqCvQ92lwPbAOofaZUmlB1kH3OZYfyzwfcf6ReURDoDbSSAckE4PAjAcG0/3shLYFVjieI2iWY3PRuQj8DlSumyp9CBgH8jDjvU3B651rF9EHiv9HiaRcEBaAQG4wrn+kcAZztcoktkONa90qNllKd1igU1beBm73fLyGTAOHRddDZOBe6tYbz52Jnoygymp9SAbgKnO12gA/oHfKVdF8gDVPXZ7KgmFA9LrQcCGfOcBQ5yv829skY+Oja7MYcB9VajzNLAviQUktR4EbHjvkgyucyjwR/ymaRfFNOAPFdZYARxPYuGANHsQsHXqzwMjM7jWb4EpGVynltUDNwEndeHPrsBmO3g88FcsxR4E7LbnvIyudR5wQUbXqlXrgZOBsynvmILZwD4kGg5ItwdpNp3s1nRMBc7P6Fq1bCBwLnAisFUHv+dx4PfAnSR4W9Va6gEZCszBpsRn4U/A6ejBvRrqsaUGu2FBWYPtsfsk8F7EdpUl9YAAXARcmOH1HgCOI9KBLZKWPASkARsCzOKBvdl84Gj8dn+UnEj1Ib21z7AHwCxve4Zj+zH9AA0DF1oeAgL2Zf1VxtfcBLgGW9nmtU5FEpeHW6xm9dg+WuMjXHsF8AvgehIfdZHqylNAwIYQnwX6Rbr+09hOKY9Hur5kLC+3WM3ewkaYYv0rPgZ4DHs/My5SGyRDeetBmp0DXBa7EdgkvauBmaS5g+Mo4EBsBLAv9pZ7MfA/bLLmJ/Galg95DQjAjcCpsRvRZCFwHbaufmnktmyHbcdzIuEDNT8GbgAuxu/c+tzLc0B6YjNJUzpRqhHbbPlfwF3YTi1Z2BH4KnAU9nmUc+u8HAuT1xawuZbngICdPDQLm9KQovlY+2ZhUyxep/LnpzpsL9wx2G4th2CbHFSiEfgWvjvL5FLeAwLQH1vo73E+d7WtxhaDzcF6l3eweUnLsC/pOuzWZzNsk4newJZYD7ETsDP2EtNjm9ZG4CDgEYfauVULAQG7734U/1WIte4NbGskPbw3ydswb0eWYCcceR0tXRSDsek10qRWepBm/bGHzVSfSfIg+qE1KamVHqTZMuw++sHYDcmxIVT+0F8zai0gYOs4JgN/jtyOPBsTuwGpqMWAgK1eOwVb+qnJheXbJnYDUlGrAWl2GfYC7f3YDcmZ7rEbkIpaDwjYnKPR2CRDKU3s6TLJKEJAwGYBT8AWXWlDhs69ELsBqai1Yd5S7A3cikZqOvIedrqT/iGhOD1Ia09ht1wXYQ/z0tbNKByfK2IP0toI7EySSbEbkogV2EtCDWo0KWIP0to8bJRrMnYuSdGdgcLRRtED0mwaNhv4FGzFXRFdAvw1diNSU/RbrPZ0x1bkTcH3pKtUrAV+QuVHGNQkBaRjddjhMD8GvhK5LV6mY7MN5sRuSKoUkNIMB07DVt31j9yWSi0DbsHWo3seu10TFJDy9MB6k28CR+Czss/DKuBu4A5spvPauM3JDwWk63pgb+cPx84wGRa1NRtbCMzAtk59BNvjWMqkgFTPIOAAYD/gy9heVFlN+luP7UT/BDbnbBa2fFYqpID4acCGjkdhvctwbPOFgXR9M+yl2LyyxcACbNeUF7GH7HKOPpMSKSBx9AT6YLsdbtn03188t/0jbJeTD1r90m1SxhQQkQC9SRcJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCRAAREJUEBEAhQQkQAFRCTg/0sG59p1S5BOAAAAAElFTkSuQmCC)}97.96%{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAPQ0lEQVR4nO3de5BXZR3H8feyy3INEjE0FUMRRcTMO3lPIcFRs6vX0mwaL6lNF8PGBNEJJ81JmBSbHK+ZTZmpg4KSkqJppoaooIKkYoKiiCkowtIf392RdHn2t/s73/M855zPa+Y30wz5fc7s/j77nPOc59Kwfv16RKR93WJfgEjKFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQlQQEQCFBCRAAVEJEABEQloin0BFdUTGAgMADYBegC9P/L/WQ2sAlYCy1s/a3K8RkEB8dQAjAT2AHYEhgFDgK2wYHTFG8CLrZ/ngPnA08A84P06r1fa0aDjDzLXBzgTOA0YnFOba7GQ/AO4v/WzJKe2S00BydbBwPVYLxHbAmAGMB34G/BB3MspJgUkO8cD15LmbesK4Hbg98AsYF3cyykOBSQbY4C7KMao4FLgBuA3wMLI15I8BaR+A4BngEGxL6ST1gP3AJdj4dYXoR1F+IuXunMoXjjARtnGYM8oTwEnkebtYVTqQerTE7tl6R/7QjKyCLgIG2hoiXwtSVAPUp+DKE84ALYDrgHmAmMjX0sSFJD67B37ApzsDNzZ+tk+8rVEpYDUJ4X3HZ7GYs8nF2DTYSpHAalP99gXkINm4HzgMWCfyNeSOwWkPm/GvoAcjQDmABOp0GiXAlKfBbEvIGeNwARsrlde88yiUkDqMyv2BUQyCngcOCz2hXhTQOrzAnbbUUWbYqNc42NfiCe9KKzfodiUjSq7ETiFEi7oUg9Sv1nYF6TKTgBmUq6XpoB6kKz0Bu6lvC8Oa/Uk1qO+HvtCslLGgPQAPgdsi63uWw0sxh4qVzu22x+4mQo8uHZgETYFpxQrGssUkJHAj4AvA33b+ff3gDuAS4BHna6hG3AqMAl7iK2q0oSkDAFpBn4BnIVN4a7F1cDZwLtO19Qb+CpwJLZpwxbYW/elwL9bPy8AL2EbMbzT+nkXewnXFvCBrf/tlq2f4cBOQC+n687Sc8B+FPx2q+gB6Y8NNX6+C//tXGA0xfsFNgJDgd2wv9KHYLNwUzQP2B/buqiQihyQZmx49YA6ajyO/ZXzfDbJw2DgCOAYYF9q70nzcC826bGQQ8BFDUgDcB1wYga1pmK3Z2XxaWwDiVOxgYoU3Eg2v6vcFTUg5wI/z6jWOmz9Q9nmVXUDDsf26Bod+VrAliZfEvsiOquIATkMW0ed5UvOK4AzMqyXmr2AC7E16LG0AOOwF4qFUbSAbAM8ge1nm6VlwOYZ10zRQdiI356R2n8D2JUCDf8WaapJE3AT2YcDbFeSIQ51UzMbW/T0PeDtCO1vir1MLcx6kiIFZAJdG86tVdmXz7ZpAX6Nbaj9lwjt74s9QxZCUQKyB/4/1J7O9VPzKnA0cDr57wx/PrB7zm12SREC0hMbJmx0bucd5/qpuhJ7JslzFK8JG6ZPfk1/EQIyHtghh3bKNszbGfOwmcjTc2xzBPCTHNvrktRHsYZhv7xm53bmYqMrVdcITMFuu/LwPjbJ9Pmc2uu01HuQy/EPB9hWm2IvTc/ABkTy0AP4ZU5tdUnKPchYbCKit+XYEG9Vn0E2ZjwwOae2DiPRF4ip9iDdgEtzaussFI72XIyta8nDJST6XUzyorCJbTvl0M4U7NQlad8EbJTL20hsJnJyUrzFasJGlLzXOEwHjkLHkXWkETu+bZxzO4uwl5drndvplBR7kOPwD8ezre0oHB1bBxyL/cw8bQd8w7mNTkutB2nAzv0e7tjGauwt7nzHNspoBHbMdG/HNp7GbreS+VKm1oOMxTccAD9E4eiKp/FfWDaCxA7uSS0g3r+Au4Bpzm2U2dXAbc5tJLW6M6VbrGH43ue+hT0ELnNsowoGYTuW9HNsYxiJvF1PqQf5tnP981A4srAM+JlzG99xrl+zVHqQJuBl/Fb1zcUezDVqlY0m7MSpXZzqL8XW50T/faXSgxyK75LXM0ngh10ia7FViV42J42NJpIJyNcca88EHnCsX1UP4Dt/Kol3IincYnXHdjf02jp/FPCwU+2q2wf4u1Ptt4FPkf9qx/+TQg9yAH7hmInC4elh/HqRfsCBTrVrlkJAjnCs/SvH2mIuc6ztPf+rQyncYi3AZ0ntYmyT5xaH2vKhbsBCfLZNWghs71C3ZrF7kC3xW2/+WxSOPLQAVznVHkrk7ZhiB+Rgp7ot2LQIycc1+E1TP8ipbk1iB8RrI7gH0VvzPL0G3O9Uu57jLeoWOyD7ONW9xamubJzXLo1RD0aN+ZDeE1sL7rEh3DbY8WaSn63x+Zmvw4Z8VznU7lDMHmQ4PuF4FoUjhpexY6Cz1oitE4kiZkA+61TX615YOvagU91KBmRHp7qadxXPHKe6lQzIUKe6DznVlY55zcuKdopvzIB4HDC5Gjt/XOJYjM+Rz9EOI40ZkC0dai4goR0xKspjqezWDjVrEisgzdhU5qw941BTOsfjGIkB5LOJ+cfECshmTnUXO9WV2i10quv1nQmKFRCPgzjB1jJLXF5TfCoVkE861V3uVFdq96ZT3b5OdYNiBcTrwEwFJD6vgHzCqW5QrIB4/TVY41RXarfCqW4Pp7pBsWfzZu2/sS9AyrW9UtkCIpKpsgXE+yx16ViUZwUvsQLitdeR1/Cx1M7rhV6UcyRjBcTrWWGAU12p3UCnuu851Q2KFRCvvwYKSHxeAXnLqW5QrIC87lR3kFNdqZ3XJuRew8dBZQuI1xoTqZ3HBnLg950JihWQNfi8cfVapSi18zjf/jUivQSOOcz7skPNqNtUCg34/JF6xaFmTWIGxGPlX3/8unjp2LZAL4e60VaJxgzIIqe6o5zqSse8dsr0WmPSoZgBedqp7n5OdaVj+zvV9VilWJMyBmRfp7rSMa99dOc61e1QzK1He2PHbHnMnxqMzyCAbNxg4EWHuuuAPkQ6ii1mD7IKv17kS051ZeOOdqr7JBHPKYw9m/cRp7oKSP6+4lQ36hmTsQPieaaEx7ZC0r5B+D37Rd0pM3ZAZjvVbQJOdqotH3cKft+le53q1iSFQzyfx2cOlQ7xzIfnIZ7PEnn6UOweBGC6U90hwKFOteVDY/CbvTDDqW7NUgjInY61f+BYW8z3HWvf4Vi7JincYvXAZmv2c6o/isgjISW2D35HHqzEdlP8wKl+TVLoQd4H/uxYf6Jj7aqb6Fj7FiKHA9IICMAfHGt/Eb85QlW2P/az9fJHx9o1S+EWC2y6yRL8lms+CeyO32H3VdMIPIbfOZNLsTNBov++UulB1gHXO9bfBTjdsX7VnIpfOACuI4FwQDo9CNhqwOcc678NDMNve/6qGIRNP/faoR9gB3y/CzVLpQcBe2E407F+P+Aqx/pV0ABcg284ZpJIOCCtgABMca5/FDYtQrrmVGCscxve34FOSekWC+wv1Dx8z8VeBeyF31T7shqOPZh7rDlvMx/73SfzpUytB1kPTHZuozc2xu71YrKM+gG34hsOgItJKByQXg8CNhN3Af6Hx98JHEnJzrNw0AjcBhzu3M4ibGJiEqNXbVLrQcB+QOfn0M44YGoO7RTdZfiHA+BCEgsHpNmDgAX3X8DIHNqaBEzIoZ0iOha4KYd2nsF+18ktTUg1IGDTGPKa7nwudv8rH+qLranx2q19Q+OAu3Jop9NSvMVqM5P8pjtPJp/buiL5LvmEYwaJhgPS7kHA3q7PI78TTq8AzkIP7mC3uJ7TScA2pB5JQi8GPyrlHgTs7fpFObZ3OjZiU/Uh4E3wDwdYz51sOCD9HgSgO/AEvi8PP2oB8HWs96qiUfjvJvIssCuRjlarVeo9CNiimW+R7xDgjsCjwGk5tpmSvs711wEnkHg4oBgBAZviMCnnNntgzyS3Alvk3HZs3l/cycA/ndvIRBFusdo0Yftoxdic+m3gp8CVJDhW72AIfmdyPAQcSIIvBdtTpIAAbIWNrmwaqf1HgXPw2/AuJUvJ/lDUFdhzx0sZ13VTlFusNkuA44n3V3xP4D7sHc1eka4hL7dkXK8FOI4ChQOKFxCwL+f4yNcwBtt4+27gCIr5c+zIVLJ9H3QeCWwE11lFu8Xa0A3YSEgKXgCmAb8D/hP5WrI0BTgzgzo3YCORhfuyFTkgzdgUhS/EvpANrAceBG7GpskU6naiHb2AOcBuddS4HxhNpGOc61XkgICdavsA+cz67YpFwF+xh/rHsU2eizaNZTPgHrr2Zv0hbCLiykyvKEdFDwjYL3AOtmNJ6lZjU7vnY2d/vwK8Cixv/fd3sOHPPtjLur7YiN1g7Ijlz7R+NsdeoL6KvU+4HfgTtpzYQx/gcmpfz78euz07h4L2HG3KEBCw4d/Z+K9CTNkb2IzkafiN8u0J/BgbmOjZzr+/g20jeyklmaZTloCAQtJmBnAMvrc1vbDnkiGt//tdbKDiCSKeJ+ihTAEBu92ahe2kWGWPYIMXXrdclVG28fvXsfMJZ0e+jtj2RpvkZaJsPUibZuBq0nlPEstorEeVLipbD9JmDXAitta8lH8BaqTNKOpU1h5kQ4cBNxJvgmNs2+E3M7f0ytqDbGgGNuLidVRY6nSQaR2qEBCwKR8HABdQvDfZ9Yp6jHLRVSUgYG+oJwL7Ua2NqwfEvoAiq1JA2jyMHcc2iYJPg6hR9IMwi6yKAQF72zsB2JmENy3LyJLYF1BkVQ1Im+ex2abjgKciX4uXR2JfQJFVYZi3Vt2Ab2Ir38oyn2slNvM3+e11UlX1HmRDLcC12KjPydi09KKbhsJRF/UgG9eAncd3NjZloyHu5XTaMmAn4M3YF1JkCkhthmK7nZ+I3bKkrgUL992xL6ToFJDOaQQOwbavORLb5Dk1a4GTsA0kpE4KSNd1x3YIPByb75XCG+sl2EDDfbEvpCwUkOxshU1nOQDbVG4ktl1qHl7CtkWdiq3uk4woIH56YCEZgZ0xPgzYpvXT1ZnFb2K9xGLsXI0F2KYN86j2tH43CkgczdjxZgOxrYt68/EzyFdhb/xXYMFYjoZsc6eAiAToRaFIgAIiEqCAiAQoICIBCohIgAIiEqCAiAQoICIBCohIgAIiEqCAiAQoICIBCohIgAIiEqCAiAQoICIBCohIgAIiEqCAiAQoICIBCohIgAIiEqCAiAQoICIBCohIgAIiEqCAiAQoICIB/wMME/GfzEEmxwAAAABJRU5ErkJggg==)}to{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAQQklEQVR4nO2de7DVVRXHP/dyAwMTUfEVgnpBRUBBSIlM0AEfqDU1k68kdcpXZQ8tRU2aEdJ01Cm1xDR8jplN5aRAKKOgZWo+IHmIcFHRgroKIo8E4dIf617BuHefc+/5rb327/zWZ+YMfwjftT2/8/3tx9p77ZotW7bgOE7r1Fo3wHFSxg3iOAHcII4TwA3iOAHcII4TwA3iOAHcII4TwA3iOAHcII4TwA3iOAHcII4TwA3iOAHcII4TwA3iOAHcII4TwA3iOAHcII4TwA3iOAHcII4TwA3iOAHcII4TwA3iOAHcII4TwA3iOAHcII4TwA3iOAHcII4TwA3iOAHqrBvgtMmuwF7IM2oE3gE2mLaogLhB0uJQ4ALgRGCfVv77KmAZ8DqwFJjX/JkPrI/UxkJR49cfJMFuwM+BMzr47zcjJnkOeAqYBbydScsKjhvEnkHAo0DvjHWXANOaP7Pw4VmHcIPYsh/y1u+pHOd94E/Ag8AMYJNyvKrBDWJHHWKOwyLHXQHcB9wBLI4cO3e4Qey4CLjZuA0zgFuBqYD/EFrBDWJDLbISlfW8o6MsAH4K/AYffn0MTxTaMIJ0zAFwMHAv8CpwJv67+Aj/ImwYZd2ANqhH5idzgWON25IERU8UdgNOBkYjb9HuSE7hDeAF4A9IIi5r+ipoZslAZH4yHZkrNdg2x46izkF2AC5p/vQo8XdnN/+9FzOM/zDwxQz1NNkA/AS4ngLmUoo4xBoGzAEmUdocACOB54HLM2zD2gy1tOkCXI28IIYZtyU6RTJIHTAReBY4sJ3/tha4Brgxo7bkccgyAPnurgI6GbclGkUZYvUBHkBWjyrl68CUCjXGAI9l0BYrnkb2jVX9fq8iGOR4xBzlDKfKYS3QD8lId5TOyI9Le4uJJu8CpwEzrRuiSTUPsWqQecNUsjMHwI7AZRVqbER27+aZXZGVrkutG6JJtfYgnYE7gXFK+quAPYAPK9DoiuQbUl/yLYe7gfMR41cV1diDdAceR88cID3SZyrUWA98BVhXeXPMORvJmXQ3bkfmVJtBeiJ5i6MixDokA405yOnB9zLQsuYY4EnyPa/ajmoySC/gb8ix1RjsmZHObCS/MDsjPUuGAM8gz6IqqBaD9EJOzdVHjJnleLsB2Z91EvAI+c5Y90WeRVWYpBom6T2RniOmOQDOQSanGnRG9ob1Bj69zZ/1SA/ZTSlulixB8k6N1g2phLwbpDvythpsEPsQ4BWDuLXIW3owsg1mDJKXSZE5SM+42rgdHSbPBumMrMOPMoj9JnKePJUvrw9wApK4OwrJAaXCLOA4croEnOc5yK+wO1cxmXTMAWLYycj30RtJZL5m2aBtGIXkpFIybdnktQe5FLjOKPbbwEGkn7+oBcYCFwNHG7cF4ArgWutGtJc8GmQ0MrSy6P2akDH/EwaxK2EocuZ8tGEbmpBhYK42aebNIL2Q7Rm7GMRuAs4C7jeInRVjkJ53iFH8VcjiwjKj+O0mT3OQTkjVDQtzNCLDlTybA2QLzjDgO8Aag/g9kGeYm6PeeTLIlcCRBnGnIuVBZxjE1qAJuAU5dz7VIP4IYIJB3A6RlyHWMCQZGPPN819kgns7aa1YZc2FwM+QZfNYbAaGI4UxkiYPBumCnIceEDHmIuBLwMKIMS0ZCjwE7B8x5kKk7OoHEWO2mzwMsS4lrjmmA4dTHHOAvIAOI+4wsj8wPmK8DpF6D1KP3HvRJVK824FvIUOAItIJuA04N1K8jcj8LpWk5nak3oPcTDxzTEJudyqqOUD+389Dqr/EoDOyYJAsKfcgxxKvy78cSaQ5WxlPvMz3WGRomxypGqQWSQgOjBBrElLrydmeq4nz3cxHtvEn13unOsQ6nTjmuBM3R4gJyCZIbQagW0Ogw6TYg9QhZfi1D0DNQM6DJ/fWSoxOyPVtY5XjNCCbQJO6nyTFHuR09M2xtDmOm6M0m5HvapFynHrgq8ox2k1qPUgNckpPM++xEdnukGW19iLQH8l8d1WMsQAZWifzo0ytBxmLflLwe7g5OsJC5BoITQ5Ghr3JkJpBLlLWn44kwpyOcTv6Gxy1fwPtIqUhVj90M6prkO47N2cREmV3pDfROnawBTgAqYpiTko9yDeU9a/AzZEF/0GOHmhRg2TzkyCVHqQTctY7q2qF/8/LyJb5JiX9olGLzOO0yi0tB/YhgVXGVHqQMeiZA6TKh5sjO5qAbyvq74Xt+fmPSMUgpyhqz0SOmjrZ8ld0J+ynKmqXTQpDrC7IuHYnJf2hwEtK2kVnOHLSU4Ms7mCpmBR6kKPQM8eTuDk0eRa9Mj49kNKqpqRgEM3E0E2K2o5wg6K29v6vkqQwxFqMzjVki5DMrE/OdalBnqHG/rkFxD1uvR3WPUgv9O7om4KbIwZbqPxa7LY4GON7RqwNMkpJdwty9bMTh7vQy1l8Xkm3LKwNonWX4GwKcMl9QixH7wq5QhvkcCXdB5V0nbZ5REl3uJJuWVhO0rsC7yPbTLJmX+TODCce9ehsMNyEXDlncgGPZQ8yAB1zLMbNYUEDOsX26ohTn6BVrA2iQbUUmc4jWvOQQUq6JbE0iNZb4WklXac0zynpHqCkWxJLg2gVSn5ZSdcpjZZBDlLSLUm1GWQtMhZ2bFiELLxkzb4KmmVhaZB9FDTn4tlzS5rQKQ9klk23MkhndM40e+9hz1IFzd2JV8T8Y1gZpKeS7r+UdJ3y0TAIwK5KukGqzSBelMEerRxUDyXdIFYG+ZSS7nIlXad83lHStbjd2MwgOyrpvqek65TPWiXdmJeMfoSVQbQmXOanvxw1g2iNOoJY7+bNmtXWDXBYZ92ALKk2gzhOplSbQbpZN8Chu3UDssTKIGuUdLUm/0751CjpblDSDWJlEK3DL24Qe3ZW0tWa/AexMshKJd3dlHSd8tlLSVdr1BHEyiCrlHT7KOk65dNbSbdRSTeIlUHeVdLVOmPilM/eSrqFMsgGpGB11rhB7NGosLiSAhZt0KhbdSDVt3SdJ2qBQxV031LQLAvLH9MbCpo7ISZxbKhHZyVRawt9SSwN8qqS7hFKuk5phijpFtIgWjfaukHs0CoTOk9JtySWBnlFSdf80pUCc5yS7nwl3ZJYlh7tjOz8rFPQ7oufT49NH3TmlZuRueV6Be2SWPYgG9HrRU5W0nXa5ngl3XkYmQPsl0SfVdJ1g8TnNCXd55V0y8LaIFplQkeityfI2Z5e6M39nlLSLYtqNUgn4BwlbWd7zkBvm/ssJd2ySOESz/nIXXRZ0wD0w8+pa1OLXLapkaBdgjxDM6x7ENC7rqAeGK2k7WxlLHq7F6Yq6ZZNCgaZpqj9A0VtR7hYUdvcICkMsT4B/Bu9ynmfRW+1rOgcBryopP0+UpPX5KhtCyn0IB8CDyvq/0hRu+hcp6j9e4zNAWkYBOC3itonAp9T1C8qY9Cd4z2kqF02KQyxQJZl30IvdzEHGIrfHZIVtcAL6O3eXYHkVjYr6ZdNKj3IZuB+Rf3BwHmK+kXjm+iZA+BeEjAHpNODgGwwfA29hNNKoD86R32LRG9kf5RmrdwDkOu8zUmlBwFJCj2uqL8LMAU9AxaFyeiaYwaJmAPSMgjALcr6JwLnK8eoZi4ETlCOof0baBcpDbFA3u7z0Nl60sJ6YBiwUDFGNTIUeAbdezrmA4NIaHtQaj3IFuB65RhdgT8ih3Cc8uiBLLtqX2JzHQmZA9LrQUBOGL6KTn2lbZkGfIFEVksSphOy5UPrOG0LDcBBwCblOO0itR4E5AuaFCHOWODWCHHyzmT0zQHwYxIzB6TZg4C8teYCAyLEmghMiBAnj0wkzladeUjBueQSuSn2ICDDnh9GinUVMD5SrDwxnnj72C4hQXNAugYBmA48FinWtcDVkWLlgYnIdxKDacR7zu0m1SFWCwcglU9iXQF8B7LWX9SJeyfgF8TLFW1AhtHJlmhKuQcB2XoS600GcC6yYlNV9+yVyU7AI8RNpP6EhM0B6fcgADsALyH7qGKxFDgFvcNAqdEfyQ3FLPw9H0k+mp/5CJF6DwLwAfA14g579keyxhdGjGlBDXAB8iKIaY5NwNkkbg7Ih0FAzh5cEzlmZ+CXwKPoXStmyR7IkOo24JORY09Enmny5GGI1UIdMBsYYRB7DXAlMoFNcjmynRwH3Af0NIj9F2AUOVkIyZNBQN7kc9Ar8FCKl4HL0N2Wr82ZwD3YjB5WIglBjdvFVMjLEKuFZUgNWKu3+BBkzf5xZIKZN47BzhxNwKnkyByQP4OA/ECtK5WMRsbQTwAnkY/vsRt25gC4HJhpFLvD5G2I1UIN8rDHWTekmdeAXwMPkO4bcjxxc0rbcg+yapU78moQkFWmGciELxW2INXIH0S2yrxp25yPqAFeRy65ic0sZFHA5BrnSsmzQUAy3rOQqiUpshiZr8xGFheWYDN/GgT8wyDuHOQFttogdibk3SAgS5XPIFVRUmcdso2/AfgnsujQ8ucC9N6yZwN3KWm3RQNS9rUxctxM0bgfMDaNwNFIT6J9CrFSuiF5nNZyORuQBYjbyb5o894Z65WiAek5cm0OyMfqSzm8jTyQJcbtqIQuyNVxj5K92WPthoat5kh1saJdVItBQB7ICCSZl3dGIsvIWV1rtiIjnVLMRYZVVWEOqC6DwNbh1hPWDcmAnZGhVhYLEDEm6E8hhs79sGpbqs0gICsmJwB3G7cjC7oBv0NKFVXC34FVlTenTe5Dqr3ndrWqLarRICCrQecg+6byvrmwL/D9CjU+RJJ1WdMEXAGcRU7zHKWohmXeUoxGEne7WjekAhqR6wAq+RHuieRldsykRdIjnQH8OSO9JKnWHmRbZiLjeK0rp2PQk8on7CuA72bQFpC80xCq3BxQDIOArKocjdS/Sq44WZkcmYHGFOCmCv79ZqSo30jS2UajSlEMAvJwJyLLkPON29IRssqLXILMG9o7N1sEDEfqiOX1JdNuimSQFl5AznJMIAdnorchq7kDyK7ew5E9YqVYhRwvGExOjslmSREm6SHqkfsotO+8yAKtLeMDgS8jV0Lsi9TGWo3sDZuJnFtfpxA3F1TDXqxKaECKWB8L3Ij8WFJFaxvNvOaP0wpFHGK1xmPIWelxpFvIbJZ1A4pI0YdYrVEHnI6cwNO86ao9LAP2I/9Jz9zhPcj2bEK2TgxEdtfOsG0OADfg5jDBe5Dy6IfU7R2HZKRj8hJwBAVaWk0JN0j7qEPOV5+GXN+mfc9hI2KO15XjOG3gBuk4XZCDQWObP1kf+V2GlBR6JWNdpx24QbKjF2KYo5C3/gAkp9ARHkD2Tb2TScucDuMG0aMrYpKBzZ/9kZWo3rReOvUt5IDUZORknpMAbhAbugC7Ibt0NwHLgXdNW+S0ihvEcQJ4HsRxArhBHCeAG8RxArhBHCeAG8RxArhBHCeAG8RxArhBHCeAG8RxArhBHCeAG8RxArhBHCeAG8RxArhBHCeAG8RxArhBHCeAG8RxArhBHCeAG8RxArhBHCeAG8RxArhBHCeAG8RxArhBHCeAG8RxArhBHCeAG8RxArhBHCfA/wAuDSDlTBJcZgAAAABJRU5ErkJggg==)}}.video-speed-dropdown,.video-clarity-dropdown{z-index:101;--ran-dropdown-padding: 0px;--ran-dropdown-background: rgba(91, 91, 91, .6);--ran-dropdown-option-item-hover-background-color: #595959;--ran-dropdown-option-active-hover-background-color: #595959;--ran-dropdown-option-item-padding: 2px 4px;--ran-dropdown-content-color: #fff;--ran-dropdown-content-font-size: 12px;--ran-dropdown-option-active-background-color: transparent;--ran-dropdown-content-text-align: center}.video-control_loading{z-index:var(--video-control-loading-z-index, 10);top:var(--video-control-loading-top, calc(50vh - 60px) );left:var(--video-control-loading-left, calc(50vw - 60px) );position:var(--video-control-loading-position, fixed);width:var(--video-control-loading-width, 120px);height:var(--video-control-loading-height, 120px);background-position:var(--video-control-loading-background-position, center);background-repeat:var(--video-control-loading-background-repeat, no-repeat);background-size:var(--video-control-loading-background-size, contain);animation:var(--video-control-loading-animation, loading 1s infinite)}.ran-player{display:var(--ran-player-display, block);height:var(--ran-player-height, 100%);width:var(--ran-player-width, 100%);position:var(--ran-player-position, relative);overflow:var(--ran-player-overflow, hidden)}.ran-player-contain{width:var(--ran-player-contain-width, 100%);height:var(--ran-player-contain-height, 100%)}.ran-player-contain-video{width:var(--ran-player-contain-video-width, 100%);height:var(--ran-player-contain-video-height, 100%)}.ran-player video::-webkit-media-controls-fullscreen-button{display:none}.ran-player video::-webkit-media-controls-play-button{display:none}.ran-player video::-webkit-media-controls-timeline{display:none}.ran-player video::-webkit-media-controls-current-time-display{display:none}.ran-player video::-webkit-media-controls-time-remaining-display{display:none}.ran-player video::-webkit-media-controls-mute-button{display:none}.ran-player video::-webkit-media-controls-toggle-closed-captions-button{display:none}.ran-player video::-webkit-media-controls-volume-slider{display:none}.ran-player video::-webkit-media-controls-enclosure{display:none}.ran-player video{outline:none}.ran-player .prism-player{position:var(--ran-player-prism-position, relative)}.ran-player-play-btn{background:var(--ran-player-play-btn-background, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPQAAAD0CAYAAACsLwv+AAAAAXNSR0IArs4c6QAAG7pJREFUeAHtnXusFUWexxu5C1xMBHlsQJR3hMkwyhIyGXEFoyYzjghkBOWls5vwcFZAwkvIJOvF8Z91NkYXnY2a7AAaVnQzipJxJlEioGj8A8FxM0rk6fBwQUZM5DVw2e/3pPtyzr19zunu04+q7m8lv9vvql99qr63qru663RyFKwgcOnSpSvg6DWwIbBBsL6wPrDernnr3bHdBda13RKbznnYuXbL09j+GnbCXXrrx7F9ELYfdqRTp06tWCoYTqCT4f4Vzj0ItxcyfQPsB7BRsKGwwbCBMAo1i8B/BIdgB2D7YJ/C/gT7BEI/iaWCIQQk6AwLAuJlKzsOdhPsRhhFPABmUzgMZynu3bAPYDsgcrbuChkQkKBThA4BX4/kboHd7Bq38xj2IFPvu7YdAue2QgoEJOgEIUPAVyL622B3ujYYyyKGA8j0W65tgcC/KyKENPIsQcdMGSJml3kabCKMrXFW971I2sjA+/HtsM2wVyFudtkVYiIgQccAEiLuh2imwu6DsTstroAQIFzCOeyab4T9D8R9LMA1OqUGAVW8GnBqHYKIOTxEAT8AGw/jsJJCdAKtuHQbbD1sI8TN4TSFkAQk6JDAIOQxuGQubCbsqpCX6/RgBL7FaRtgL0DYO4NdorNIQIIOUA8g4macdj9sPoyCVkiPAAX9HOxFiPtMesnamZIEXaPcIGSOEz/kGt/EUsiOAN9ke5YGYWucu0o5SNA+YCDkEdi9BMb7424+p2hXdgTOImneZz8JYX+enRtmpixBl5ULhDwSmy2we2FiAwgGBz4hfwXWAmF/ZrCfqbqmSgvcEPIwLB6F8UFXZ5iCPQQuwlU+QFsNYe+1x+1kPC20oCHk64D1X2H/BGuCKdhL4AJcXwt7DML+0t5sNOZ5IQUNIXMMeTlsBYzrCvkhwPHrJ2C/hrALN5ZdOEFDzDNQ2P8GY+uskF8CbKUfgaj/O79Z7JizwggaQub48RrYuI4YtCfHBHYgbwsh7EK8oJL71xUh5GYYu2AfwSTmHCu3StZY5h+xDrAuVDknN7tz3UKjAG9HST0PG5qbElNGGiGwDxfPQ2v9TiORmHxtLltoCPlq2H8B/NswidnkGpiub6wLb7NusI6km3Q6qeWuhUZB/QjoXoYNSgehUrGUwEH4PR2t9YeW+u/rdm5aaAi5E2wpcrkNJjH7Frd2lhFgHdnGOsO6U7bf6tVcZAQF0gulsA7GWUIURCAsAc6e8nO01ifDXmja+dYLGmLmU0x2sTWubFrtsssfjluzC85hLmuDtV1udpNgfNNrK0xitrYKGuM469BW1inWLWO8CumIlY4DeG/kcz3spyHzq9NFIAiB3+OkB9Ba81dErArWCRpi5iR87GJfaxVpOWsbgb/AYXbBOYmhNcGqLjfEzOlxt8AkZmuqmLWOso5tceucNZmwRtAAy6mA2DJ3sYauHLWdAOvay27dsyIvVggaQFeD5jMwK/y1ouTlZFACrHPPuHUw6DWZnWf0PTQgEuZ/wuZlRkgJi8BlAvwu4Be4r269vMusNWMFDTF3BaoNsJ+ZhUzeFJzA75D/mRD1ORM5GCloiLkHYG2CTTARmnwqPIGtIDAZoj5lGgnjBA0x83ei/gDj7yUriICpBPh72D+BqI+Z5KBRgoaYhwIOP3kcYhIk+SICVQjsx/47IGp+Z21EMEbQbsu8A1QkZiOqhpwISICiHmdKS23EMJB7z8xutsQcsBbpNGMIsM7+wa3DmTuVuaABgk+z+QBM98yZVwc5EJEA6+4mty5HjCKeyzIVNAAwfQ5N6Wl2POWpWLIjwDq8wa3TmXmRqaCRa740onHmzIpfCcdMgHWZdTqzkJmg8Z/sMeRab4BlVvRKOCEC89y6nVD0taPN5Ck3MvwvcIu/9asgAnkl8BCefP8m7cylLmiImZ9A8qupzHoHaUNWeoUkwPe9+T31q2nmPlVBQ8ycnIDfM3dJM5NKSwQyInAe6d4GUac2SUJqgoaYOW3QLpgmJ8iodinZTAhw5pPREHUq0xml0u2FmPmPYz1MYs6kTinRDAmwzq93NZC4G6kIGrngbzFrQr/Ei1MJGEqAdZ8aSDwk3uXGfybOm70V1pR4bpSACJhL4AJcm4CuN79XSCwkKmiImb9owftmzZudWBEqYosIcDJ/3k8n9gsdiXW53XuGdciAxGxRjZOriRKgFtYleT+dmKDhOH84Tr81lWj9UOQWEqAmqI1EQiJdbvwH4k+6boP9XSJeK1IRsJvA3+D+eHS9P4w7G7ELGmK+Gk7yvnlg3M4qPhHIEYFDyAvvp/8aZ56S6HI/CQcl5jhLSXHlkQA1Qq3EGmJtodE63w7v3o7VQ0UmAvkmwDnJ3okri7EJGmJuhlOfwobG5ZziEYECENiHPI6CqM/Ekdc4u9yPwSGJOY5SURxFIkDNUDuxhFhaaLTOY+DNR7DOsXilSESgWAQuIrs/RCu9s9FsX9FoBO71a7CUmGOCqWgKR4DaoYYaDg0LGq3zDHjB97UVREAEohMY52opegy4sqEuNxzojjg+g+n1zoaKQReLQInAl/g7El3v01F5NNpCr0DCEnNU+rpOBCoJUEvUVOQQuYVG68zEP4dxuEpBBEQgHgJsndlKs7UOHRppoR9FahJzaOS6QARqEuBtLLUVKURqodE6D0NqvHfWpAWRsOsiEahJgJMhsJXeW/Msn4NRW2j+B5GYfYBqlwjEQIDaitRKh26h0TqPRGJ8xZNjZwoiIALJELiIaPlKKHvCgUOUFroFsUvMgRHrRBGIRIAaawl7ZagWGq3zCCTwZ1io68I6pfNFQARKBC7h7/fQSnM0KVAI20IvQawScyC0OkkEGiZArVFzgUNgcaJ17otYD8G6BY5dJ4qACDRK4CwiGIhW+niQiMK00A8hQok5CFWdIwLxEaDmqL1AIVALjdaZL5Cwde4TKFadJAIiECeBE4iMrXTdSRCCttD3I0KJOc4iUlwiEJwAtUcN1g1BBT2/bkw6ITKBZcuWOV999VXk63VhIQgE0mBdQaO7zdlIaAoJEXj33XedqVOnOi+99JJz8SLfJ1AQgQ4Exrha7HCgfEddQePkueUXaD0ZAmfOnHGeeuopZ9asWc7u3buTSUSx2k6grhZrPhTDfwR++XEUdpXtJEz2f+zYsRXu4eGHM2XKFGfBggVOjx49Ko5po9AEvkXu+6N+VJ0AoV4LfR8ikJhTrkP4R+q89tprzj333ONs3rw55dSVnMEEqEVqsmqoJ+gHql6pA4kT+Oabb5yWlhZn7ty5zr59nL5ZQQScmpqs2uVGK9EP8A7D6olejBsk0L7L7RddU1OTM3v2bGfOnDlOt256v8ePUUH2tSKfA9DtPuaX31pinYYLah33i0/7EiJw4cIFZ+3atc60adOc9957L6FUFK0FBKhJatM31BLsvb5XaGemBI4ePeosXrzY4dj1sWO+/6Qz9U+Jp0KgqjZ9u9zobg+AW1/CfI+n4nKBEgnS5fbD0dzc7MyfP9+ZMWOG07mzPlH3Y5TTffys8jp0u3lLXBGqtdBs0iXmClTmbWjs2rwySckjatO3211N0BNTckzJxEDgiy++KD0se/zxx51Tp07FEKOisICAr0Y7tMLobl+JzJyEdbEgU7lwMWqX2y/zPXv2LN1jT5zoW95+l2ifnQTOw+1e6HZ/V+6+Xwt9G06QmMspWbSusWuLCqsxV6lRarUi+An6zooztGElgY8//tiZOXOm88wzzzhnz3LSC4UcEuigVQk6h6XsZUlj1x6J3C47CLriHhr3z9cj64FnGMwtppQzFuc9dC3Xb7311tL4db9+fAlQIScERuA+eo+Xl/Yt9C3eAS3zR4DfXfNNM313nauyrdBse0HfnKusKjMdCGjsugMS23dUaLZ9l5vdbXa7FVIkkFaXu32W0FVzJk+e7CxcuFDfXbeHY8/2HpQjfwCjFNpaaNw/98UeidkFU4QFytx5/fXX9d213YV9vavdUi7aBI2tcXbnS95HJaCx66jkjLmuTbvlgr7JGPfkSCYENHadCfY4Em3Tbrmgb4wjZsVhN4Hysevt27fbnZnieN+m3baHYuiH81Osa4rDwJycZvVQLAgBjV0HoZT5OYfxYOxaelFqoSHmXliXmDMvF/Mc0Ni1eWXi49EAV8NtUwzd4HOSdolAiYDGrq2oCCUNe/fQErQVZZatk/ruOlv+dVKvEPT365yswyJQIoCuXdvY9Ztvvikq5hAoadhroYea45c8sYEAx65Xr15dmilFc4YbUWIlDXuCHmyES3LCOgK7du3Sd9dmlNpgutEJXSiKmj8k3YU7FNInYPKwVRga/fv3d1asWOHcckvFB0BhotC50Qmcx6XNFDTHrzhlr0JGBPIiaA+fxq49Eqkvr2PrPCT1ZJVgrgl4Y9cvvviifu863ZIeQkEPSjdNpVYEAhy7fvrpp/V71+kW9iAKmp9NKohAIgQ0dp0I1mqR9qWg+1Q7qv0iEAcBjV3HQTFQHH0o6N6BTtVJItAggfKx67179zYYmy73IdBbLbQPFe1KlgDHrmfNmuWsWbNGc4bHi1otdLw8FVtQAvzuet26dc7UqVOdbdu2Bb1M59UmUGqh1eWuDUlHEyTA37hesmSJs3TpUv3edeOcS4Lu3ng8ikEEGiOwdevW0pzhGrtuiGN33kN3bSgKXSwCMREoH7vmfbZCaAJd+ernV7js70NfqgtiI5C3Vz/jAMM5wydNmuQsWrRIc4YHB/p/bKH1UUZwYDozJQIcu960aVNpzvA33ngjpVStT6YLW+jTyEaz9VmxOANqoesX3ujRo51Vq1Y5w4YNq39ycc84oxa6uIVvVc41dh2ouLpQ0AoiYAUBjV3XLyYKmh9GK4iAVQRaW1ut8jclZ883IaFzMN1Dp0RcyUQn0NTU5EyfPt158MEHnW7dukWPKL9XnqOg1ULnt4BzkzM+FFu5cqUzfPjw3OQpgYy0tdAJxK0oRaBxAj169Cj9fvWUKVMajyz/MaiFzn8Z25lDvlhy1113OYsXL3Z69uxpZybS97rUQnMcWkEEjCHAsWaOObObrRCKwGneQ38d6hKdLAIJEeCDrjlz5jizZ892+ABMITSBryXo0Mx0QRIExo8fX5rTu1+/fklEX5Q4T1DQJ4qSW+XTPAIU8LJlyxzO5a3QMAG10A0jVASRCGhMORK2eheVBK0Wuh4mHY+VgMaUY8VZHlmpy328fI/WRSApAhx+WrBggaMx5aQIO8d5D30wsegVsQiAAMeUJ06c6Dz88MMaU062RhykoPcnm4ZiLzIBjSmnWvr7KegjML7PrZlLUmWf78Q0ppx6+VLDR5rQHWrFrCWHsDE8dReUYC4JaEw5k2I9RC2zhWY4AJOgSUIhMgGOKS9fvtyZMGFC5Dh0YWQCB3ilJ+h9kaPRhYUnwDHlGTNmOPPnz9d3ytnVhpKGPUF/mp0fStlmAhpTNqb0Shr2BP0nY9ySI1YQ0JiyccVU0rAn6E+Mc08OGUlAY8pGFgudKmm4JGgU0kk86T6MnQOMdVeOZU5AY8qZF0E1Bw5TwzzotdBcZ5MtQZOEQgUBjinPnTu39JvO+k65Ao0pG223zOWC3g3vfmKKh/LDDAIaUzajHOp4Qe2WQrmgP/B2aikCGlO2qg60abdc0DusyoKcTYSAxpQTwZp0pG3abRM0bqqP48HYHqR8fdKpK34zCXBMWT8IZ2bZ1PBqD7XrHW8TtLvjfSwlaI9OQZYcU164cKEzefLkguQ4V9mkZtuCn6D/ue2oVnJNAP/Znbvvvrv0o+qa+9raoq4p6O3WZkuOhyKgMeVQuEw+uUKzFS00/mPvwX30AXg/2OQcyLfoBDSmHJ2dgVceoGbL/aoQtHvgLSx/UX6S1vNBgJ818vNGzX2dj/JELqjViiBBV+DI54bGlPNZrshVIEFvwYmakigHdYBjyjNnznTmzZun75RzUJ7tskCNUqsVoUMLjT75d7iP5o327RVnasMqAhpTtqq4oji7nVptf2EHQbsnbMZSgm5Py4JtjSlbUEjxuPimXzSd/HaiheZXV1/CfI/7XaN90QmMHTs2+sXulfhvXRpT5tzX/JF0hVwTuITcXYcy5yfPFcG3heaJEDUHrP+x4mxtGElg+PDhzsqVK/V7ykaWTiJOve8nZqbkK2jXhY1YStAuDBMXHFPmAy8++NJ3yiaWUGI+UZu+oWqXGi00f6iXTfoVvldqZ2wEonS5NaYcG37bImqFwwPQQh/zc7xqC80LIOptuOhWvwu1LxsCGlPOhrtBqW6rJmb6WFXQbgbWY3mru65FhgQ0ppwhfLOSpiarhqpdbl6BFro7FkdhV3FbIRkC9brcGlNOhruFsX4Ln/ujhT5dzfeaLTQvhKg34OIHq0Wg/ckR4JjyokWLnEmTJiWXiGK2icCGWmJmRmoK2s3pC1hK0C6MNBYotJKIKWaNKadB3Jo0qMWaoa6gUbl2opXeiVjG1IxJB2MhoDHlWDDmMZKd1GK9jNUVtBvBc1jSFBIi0Nzc3Db3defOnRNKRdFaTCCQ/mo+FPMyjxa6GeuHYH28fVrGR2Dp0qX6Tjk+nHmM6QQyNRAt9Jl6mQskaEYCUbdg8SjXFURABFIlsBpibgmSYhhB90WEbKW7BYlY54iACMRC4CxiYevcNlVvrVivqHWw/JgbYc1B7fLztS4CIhALgfVBxczUArfQPBnd7hFY/DnsdbxWQQREIDQBfib5PQj686BXBm6hGaEb8StBI9d5IiACDRF4JYyYmVKoFpoXoJUeicWnMI2tEIiCCCRD4CKiHQVBfxYm+lAtNCN2E+DroAoiIALJEeBrnqHETFdCt9C8CK30MCyYWNAXU3iZggiIQDACF3DaSAh6b7DTL58VuoXmpW5Cay9HozUREIEYCayNImamH6mF5oVopa/Dgq00P7FUEAERiIcAP41k68xJOkOHSC00U3ETfCJ0irpABESgFoEnooqZkUZuoXkxWmm2zmyl2VoriIAINEaArTJb56oTGNSLPnILzYjdhB+pl4iOi4AIBCLwSCNiZgoNtdCei2ipOYf3OG9bSxEQgdAEdkDMN4e+qt0FcQmakx98BNPLJu0Aa1MEAhDgSyQ/hKDrTmBQL66Gutxe5K4jT3rbWoqACIQi8GQcYmaKsbTQjAjdbk6CwFdCh3JbQQREIBCBfTiLr3jWnbwgSGyxtNBMyHVoXpBEdY4IiEAbgXlxiZkxxiZoRgbH3sHit1xXEAERqEvgt65m6p4Y9ITYutxeguh6X431j2GDvH1aioAIdCBwEHv+AYL+a4cjDeyItYWmH66D07H6twb80qUikGcC1Mb0uMVMYLELmpHC0Q+xWMV1BREQgQ4EVrka6XCg0R2xd7k9h9D1ZtxvwCZ6+7QUARFwNoPBJAia0wvFHhITND2FqHthsQumd70JRKHoBPiu9miI+WRSIBLpcnvOuo7zfpofbCuIQJEJUAO8b05MzISbqKCZADKwA4tfcl1BBApM4JeuFhJFkGiX2/PcvZ/mvcNPvX1aikCBCPweeZ0IQSdy31zOMRVBM0GIujcWvJ++ltsKIlAQAn9BPnnf/HUa+U28y+1lws0Q76fPe/u0FIGcE2Bd531zKmImy9QEzcSQMX43PRvWym0FEcgxAdbx2W6dTy2bqQqauUIGX8ViUWo5VEIikA2BRW5dTzX11AXN3CGjz2Lxq1RzqsREID0Cj7l1PL0U3ZRSeyjmlzM8KOOv0uuTSz842mcrgech5vlZOZ+1oNlDYBf8Z1kBULoiECOB3yGuaRB0Zs+IMhU0QaKV7orFH2ETuK0gApYS2Aq/fwwxn8vS/8wFzcxD1D2wIJAbua0gApYR2A1/J0DMp7L22whBEwJE3Q8LviY6hNsKImAJgf3wcxzEfMwEfzN5yu2XcRfIHThGQAoiYAMB1tU7TBEzgRkjaDoDMJwBkRP2swujIAImE2AdZcvMOmtMMErQpOL+t+MDMt5TK4iAiQRYN3nPbEQ3uxyQcYKmcwDFhws/hnEYQEEETCLAOsmn2Zk/APODYqSg6SiA8fH/NNjz3FYQAQMIsC5ynDnToalaHIwVNJ0GuFYY37rRa6K1SlHH0iDwK9ZF1sk0EouahjHDVvUygGGth3DOf8CM/idULx86bh0BCnghhPwbGzy3RtCECVGzC/4SrAu3FUQgYQL8npmfQPL1ZCuCVYImUYiav6H7MkwznxCIQlIEONMIJyfgN/zWBOu6ry7g0SDMeZoURCAJAqxbnDbIKjEThHWCptMAzSldOIH/IzBOj6ogAnEQYF1ineKEfqlNGxSH414c1nW5Pce9JbrgfLOMXXBN5u9B0TIKAU6Czy42vyewNljZQpfTdguAXXBOE6wgAlEIsO6wi221mJlx6wXNTKAgTmIxCbYcpl+9BASFQARYV1hn+FtTrEPWB+u73O1LAF3wH2HfRtjA9se0LQJlBA5h/T4I+cOyfdav5qKFLi8Ft4DYBV9bvl/rIlBGYC3W2cXOlZiZv9y10MyUF9Ba3451vn871NunZaEJ8FPHeRDyO3mlkLsWuryg3IIbhX3/DrtYfkzrhSLAsmcdGJVnMbNEc91CM4NeQGs9ButrYBzmUigOAT655rvYO4uQ5Vy30OUFyAKF8bXRmTCOOSrkmwDLeCbLvChiZnEWpoUur7torbtjewWMQxZcV8gPgdPIyq9hT0DIXC9UKKSgvRKGsPl22aOwn8OavP1aWkmAr22ug62GkAvbAyu0oL1qC2EPwzqFze54Z2+/llYQ4AOvDTAKea8VHifopARdBhfCHonNFti9MLEBBIPDJfj2CqwFQv7MYD9TdU2V1gc3hD0Cu5fAHoB18zlFu7IjcBZJr4c9CSF/np0bZqYsQdcoFwi7Lw5z6iNanxqn6lDyBE4giWdpEPLx5JOzMwUJOkC5QdjNOO1+GCcs5Hi2QnoEOH78HOxFCPlMesnamZIEHbLcIG4Kei6MD9CuCnm5Tg9G4FucxgddL0DEhXghJBiW+mdJ0PUZ+Z4BYXP8+j4Y77PHwwrzkg7ymkRoRaTbYLw/3gghF24MOQ6oEnQMFCFu/nLmNBifjvNtNHEFhACBT6o5bxefVr8KER8LcI1OqUFAFa8GnCiHIO4BuI7ingi7BdYFpnCZwHmsbodxlhCK+PDlQ1prlIAE3SjBGtdD3Ffi8G2wO10bjGURwwFk+i3XtkDE3xURQhp5lqDToOymAYFfj1W22uyW07idx7AHmWJXmrYdAua2QgoEJOgUIFdLAgLvi2PjYDfBboTdALsGZlM4Amc/gfH3kj+A7YCANU4MEFkECToL6jXShMh74TCFTfs+bChsMGwgLKv78fNI+xDsAGwf7H9hFPEnEO9JLBUMISBBG1IQ9dyA0K/AOWy9h8AGwdi68+213mVLrnM4rSuM4qd561h1KEz+FCqX3jqHhzipPI1vY3lLtrIHYfthRyBcDispGE7g/wFAEx//6c86OAAAAABJRU5ErkJggg==) no-repeat);background-size:var(--ran-player-play-btn-background-size, contain);width:var(--ran-player-play-btn-width, 64px);height:var(--ran-player-play-btn-height, 64px);position:var(--ran-player-play-btn-position, absolute);top:var(--ran-player-play-btn-top, 50%);left:var(--ran-player-play-btn-left, 50%);transform:var(--ran-player-play-btn-transform, translate(-50%, -50%))}.ran-player .prism-auto-stream-selector{display:var(--ran-player-prism-auto-stream-selector-display, none)}.ran-player-controller{position:var(--ran-player-controller-position, absolute);bottom:var(--ran-player-controller-bottom, 0);left:var(--ran-player-controller-left, 0);background:var(--ran-player-controller-background, linear-gradient(180deg, rgba(217, 217, 217, .5) 0%, rgba(91, 91, 91, .5) 100%));width:var(--ran-player-controller-width, calc(100% - 32px) );height:var(--ran-player-controller-height, 34px);padding:var(--ran-player-controller-padding, 16px);opacity:var(--ran-player-controller-opacity, 0);transition:var(--ran-player-controller-transition, opacity .5s);box-sizing:var(--ran-player-controller-box-sizing, content-box)}.ran-player-controller-tip{position:var(--ran-player-controller-tip-position, absolute);top:var(--ran-player-controller-tip-top, -12px);max-width:var(--ran-player-controller-tip-max-width, 60px);height:var(--ran-player-controller-tip-height, 24px);line-height:var(--ran-player-controller-tip-line-height, 9px);transform-origin:var(--ran-x, 50%) var(--ran-y, 50%);box-sizing:var(--ran-player-controller-tip-box-sizing, border-box);margin:var(--ran-player-controller-tip-margin, 0);padding:var(--ran-player-controller-tip-padding, 4px 6px);color:var(--ran-player-controller-tip-color, #fff);font-size:var(--ran-player-controller-tip-font-size, 10px);list-style:var(--ran-player-controller-tip-list-style, none);font-family:var(--ran-player-controller-tip-font-family, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");z-index:var(--ran-player-controller-tip-z-index, 100);font-variant:var(--ran-player-controller-tip-font-variant, initial);background:var(--ran-player-controller-tip-background, rgba(0, 0, 0, .5));border-radius:var(--ran-player-controller-tip-border-radius, 8px);outline:var(--ran-player-controller-tip-outline, none);box-shadow:var(--ran-player-controller-tip-box-shadow, 0 6px 16px 0 rgba(0, 0, 0, .08), 0 3px 6px -4px rgba(0, 0, 0, .12), 0 9px 28px 8px rgba(0, 0, 0, .05));overflow:var(--ran-player-controller-tip-overflow, hidden);white-space:var(--ran-player-controller-tip-white-space, nowrap);text-overflow:var(--ran-player-controller-tip-text-overflow, ellipsis);opacity:var(--ran-player-controller-tip-opacity, 0);text-align:var(--ran-player-controller-tip-text-align, center)}.ran-player-controller-tip-time{margin-top:var(--ran-player-controller-tip-time-margin-top, 4px);max-width:var(--ran-player-controller-tip-time-max-width, 80px);overflow:var(--ran-player-controller-tip-time-overflow, hidden);white-space:var(--ran-player-controller-tip-time-white-space, nowrap);text-overflow:var(--ran-player-controller-tip-time-text-overflow, ellipsis);text-align:var(--ran-player-controller-tip-time-text-align, center)}.ran-player-controller-tip-text{margin-top:var(--ran-player-controller-tip-text-margin-top, 4px);max-width:var(--ran-player-controller-tip-text-max-width, 80px);overflow:var(--ran-player-controller-tip-text-overflow, hidden);white-space:var(--ran-player-controller-tip-text-white-space, nowrap);text-overflow:var(--ran-player-controller-tip-text-text-overflow, ellipsis);text-align:var(--ran-player-controller-tip-text-text-align, center)}.ran-player-controller-progress{position:var(--ran-player-controller-progress-position, relative);width:var(--ran-player-controller-progress-width, 100%);height:var(--ran-player-controller-progress-height, 4px);cursor:var(--ran-player-controller-progress-cursor, pointer);box-sizing:var(--ran-player-controller-progress-box-sizing, content-box)}.ran-player-controller-progress:focus{outline:var(--ran-player-controller-progress-focus-outline, 0);-webkit-tap-highlight-color:transparent}.ran-player-controller-progress:active{outline:var(--ran-player-controller-progress-active-outline, 0);-webkit-tap-highlight-color:transparent}.ran-player-controller-progress-wrap{width:var(--ran-player-controller-progress-wrap-width, 100%);height:var(--ran-player-controller-progress-wrap-height, 100%);border-radius:var(--ran-player-controller-progress-wrap-border-radius, 20px);background:var(--ran-player-controller-progress-wrap-background, rgba(255, 255, 255, .3));position:var(--ran-player-controller-progress-wrap-position, relative);overflow:var(--ran-player-controller-progress-wrap-overflow, hidden);pointer-events:var(--ran-player-controller-progress-wrap-pointer-events, none);box-sizing:var(--ran-player-controller-progress-wrap-box-sizing, content-box)}.ran-player-controller-progress-wrap-value{position:var(--ran-player-controller-progress-wrap-value-position, absolute);top:var(--ran-player-controller-progress-wrap-value-top, 0px);left:var(--ran-player-controller-progress-wrap-value-left, 0);height:var(--ran-player-controller-progress-wrap-value-height, 100%);width:var(--ran-player-controller-progress-wrap-value-width, 100%);transform:var(--ran-player-controller-progress-wrap-value-transform, scaleX(0));transform-origin:var(--ran-player-controller-progress-wrap-value-transform-origin, 0 0);will-change:var(--ran-player-controller-progress-wrap-value-will-change, transform);background:var(--ran-player-controller-progress-wrap-value-background, rgba(255, 255, 255, .8));border-radius:var(--ran-player-controller-progress-wrap-value-border-radius, 20px);box-sizing:var(--ran-player-controller-progress-wrap-value-box-sizing, content-box);cursor:var(--ran-player-controller-progress-wrap-value-cursor, pointer)}.ran-player-controller-progress-dot{position:var(--ran-player-controller-progress-dot-position, absolute);top:var(--ran-player-controller-progress-dot-top, -2px);left:var(--ran-player-controller-progress-dot-left, -2px);border-radius:var(--ran-player-controller-progress-dot-border-radius, 50%);z-index:var(--ran-player-controller-progress-dot-z-index, 9);width:var(--ran-player-controller-progress-dot-width, 8px);height:var(--ran-player-controller-progress-dot-height, 8px);background:var(--ran-player-controller-progress-dot-background, #ffffff);cursor:var(--ran-player-controller-progress-dot-cursor, pointer)}.ran-player-controller-bottom{margin-top:var(--ran-player-controller-bottom-margin-top, 8px);width:var(--ran-player-controller-bottom-width, 100%);display:var(--ran-player-controller-bottom-display, flex);justify-content:var(--ran-player-controller-bottom-justify-content, space-between);align-items:var(--ran-player-controller-bottom-align-items, center)}.ran-player-controller-bottom-left{-webkit-user-select:var(--ran-player-controller-bottom-left-user-select, none);-moz-user-select:var(--ran-player-controller-bottom-left-user-select, none);user-select:var(--ran-player-controller-bottom-left-user-select, none);display:var(--ran-player-controller-bottom-left-display, flex);justify-content:var(--ran-player-controller-bottom-left-justify-content, flex-start);align-items:var(--ran-player-controller-bottom-left-align-items, center)}.ran-player-controller-bottom-left-btn{width:var(--ran-player-controller-bottom-left-btn-width, 20px);height:var(--ran-player-controller-bottom-left-btn-height, 20px);cursor:var(--ran-player-controller-bottom-left-btn-cursor, pointer);outline:var(--ran-player-controller-bottom-left-btn-outline, 0);-webkit-tap-highlight-color:transparent}.ran-player-controller-bottom-left-btn:active,.ran-player-controller-bottom-left-btn:focus{outline:var(--ran-player-controller-bottom-left-btn-focus-outline, 0);-webkit-tap-highlight-color:transparent}.ran-player-controller-bottom-left-btn-play{background:var(--ran-player-controller-bottom-left-btn-play-background, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAA8JJREFUeAHtmktoE0EYxzPZpA001M1mRVFQUETBixcP3r148SYIgngRm7ZQKSgqUlAQUdCD9VBE0INY8HHw4gMfIB5EraBIsRX0pijdTZqa2qZ5jP+tNp2mSbvZ7mOmnYWw385jM//ffDP7zeyGQvKQBCQBSUASkAQkAUmgQQKGYTxIp9MbGqzGXfGw0xbRUGhvqVz+bKTTxymlUaf3CboecdqAEcMAg38HIWQwTEhK07RXM2minB17ACsQHrC9TOlLwzRvjI2N6Wwe77YrACyRgEDwOzRVKAybpnnYuuZdvNU+x41kh0AtoRgWr5VwOJVIJD7WyuclzTUPqBYED9iFSXJgxDQvwY5X5/Ny7ZkHsALhDd/xR13JZPI+m86D7ZkHsOLgAesxSd6DNzwcHR3dxOYFbfsCoCKS0j2FYnEQQdRpQGmqpAdo+DIEaunDHw+HIpF2XVVf1Mr3K81fD2BUIYraSovF5/CGW7lcbg2T5asZGIAZlQBxYDKfH0ZI3Y5h4Xt7AhsCMwDYMxrzjkYiqdWq+p5N99L2nfhCYuANO0mp9Bbe0IuV5qqFyrqVxxUAS5Q1DGi53IkgaggQ9rsltN59uAPANHQtIPRjgfU0m81uYdJdNXkGMC0UHrEbC6xPCKLOwI65qh4342oStCHuK/YdOhBSP7FR1lYR7j2gSsVmhNSPMSzujIyPr6vKc3QpGoBpkRgK+8jExBD2HbpgK46U/68k2hCYr5WQD9iJadN1/c38zMVThPSAObIo3RHC5gu8oQ8rzcScPBsX4gOASAwDgrnhCFaaQ1hbHLShu1JkWQCoqHHwVIswlYU1seNk7cBeUxTlpKqqmUaEiA8AkyDGQFvS4SQoLAD0+G/0fA9exvTiXGqk19myQgKA4Ls0Fjuqt7T8YMU4sUUD4HooLAqAPJ71F3RNO4/en3TS0/XqcA8Agp81RaMdra2tX+qJWEo6zwB+4tVaNya5/qUIXKwud4EQerxMwuGrEL/Na/EWHK48AI+2AaoobX5uinIBAL2exSR3KplI9FkesJjbupkfOAD0+u1Yc3N3PB7/5aYwu/cKDACEc/FqLAgAkxB/Dvt6F+HuU3Z7yqty/gIg5FFUUTqxYvvmlaBG7+sLAPQ0tx9IeAoAwkt43XUlqWk9sHON9o4f5T0DAMFCfCTlOgAIT2OSO4Eo7jpsOADfh6sAIPgmFi7HsHAx+JY92zpXAEC4sJ/KLhXAHyxcziKEvQwIhVmuK8CyPpfPZDIbV4BUKVESkAQkAUlAEpAElimBv8g7O0lnTWYLAAAAAElFTkSuQmCC) no-repeat);background-size:var(--ran-player-controller-bottom-left-btn-play-background-size, contain)}.ran-player-controller-bottom-left-btn-pause{background:var(--ran-player-controller-bottom-left-btn-pause-background, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAAHdbkFIAAAAAXNSR0IArs4c6QAAAQdJREFUeAHtmdkOwjAMBFv+/5+hllhkKrlRz0B38uIoh2OPVyGiw3BYe75bOMz9R+uECxa0QjhyPnKXv9y/IM3mEYrrPDvOXWcE49Q0X43vzgEHQuxtP0oLDJXaqvHYg5Bg8Bs6iChofQl8XSfzUPI1kufyD14eX7s+9u6+jnIAW/oEAAEIQKA7gS2XF3sgAIF7EeBJ1v0qJgAIQAACEIAABCAAge4E7vXGJxsIQAACEIDAvxFY/H9qKZnq82C1p/rMWK0/27/OtX8LAUBScLUowLXyyhsFiISrRQGulVfeKEAkXC0KcK288kYBIuFqUYBr5ZU3ChAJV4sCXCtP3hCAAAQgMBF4AShmQIQewFksAAAAAElFTkSuQmCC) no-repeat);background-size:var(--ran-player-controller-bottom-left-btn-pause-background-size, contain)}.ran-player-controller-bottom-left-time{margin-left:var(--ran-player-controller-bottom-left-time-margin-left, 16px);display:var(--ran-player-controller-bottom-left-time-display, flex);justify-content:var(--ran-player-controller-bottom-left-time-justify-content, flex-start);align-items:var(--ran-player-controller-bottom-left-time-align-items, center)}.ran-player-controller-bottom-left-time-current{color:var(--ran-player-controller-bottom-left-time-current-color, #fff);font-family:var(--ran-player-controller-bottom-left-time-current-font-family, PingFang SC);font-size:var(--ran-player-controller-bottom-left-time-current-font-size, 12px);min-width:var(--ran-player-controller-bottom-left-time-current-min-width, 40px);font-style:var(--ran-player-controller-bottom-left-time-current-font-style, normal);font-weight:var(--ran-player-controller-bottom-left-time-current-font-weight, 400);line-height:var(--ran-player-controller-bottom-left-time-current-line-height, normal);text-align:var(--ran-player-controller-bottom-left-time-current-text-align, center);position:var(--ran-player-controller-bottom-left-time-current-position, relative);top:var(--ran-player-controller-bottom-left-time-current-top, 2px)}.ran-player-controller-bottom-left-time-divide{color:var(--ran-player-controller-bottom-left-time-divide-color, #fff);font-family:var(--ran-player-controller-bottom-left-time-divide-font-family, PingFang SC);font-size:var(--ran-player-controller-bottom-left-time-divide-font-size, 12px);font-style:var(--ran-player-controller-bottom-left-time-divide-font-style, normal);font-weight:var(--ran-player-controller-bottom-left-time-divide-font-weight, 400);line-height:var(--ran-player-controller-bottom-left-time-divide-line-height, normal);margin:var(--ran-player-controller-bottom-left-time-divide-margin, 0 2px);text-align:var(--ran-player-controller-bottom-left-time-divide-text-align, center);position:var(--ran-player-controller-bottom-left-time-divide-position, relative);top:var(--ran-player-controller-bottom-left-time-divide-top, 2px)}.ran-player-controller-bottom-left-time-duration{color:var(--ran-player-controller-bottom-left-time-duration-color, #fff);font-family:var(--ran-player-controller-bottom-left-time-duration-font-family, PingFang SC);font-size:var(--ran-player-controller-bottom-left-time-duration-font-size, 12px);font-style:var(--ran-player-controller-bottom-left-time-duration-font-style, normal);font-weight:var(--ran-player-controller-bottom-left-time-duration-font-weight, 400);line-height:var(--ran-player-controller-bottom-left-time-duration-line-height, normal);min-width:var(--ran-player-controller-bottom-left-time-duration-min-width, 40px);text-align:var(--ran-player-controller-bottom-left-time-duration-text-align, center);position:var(--ran-player-controller-bottom-left-time-duration-position, relative);top:var(--ran-player-controller-bottom-left-time-duration-top, 2px)}.ran-player-controller-bottom-right{-webkit-user-select:var(--ran-player-controller-bottom-right-user-select, none);-moz-user-select:var(--ran-player-controller-bottom-right-user-select, none);user-select:var(--ran-player-controller-bottom-right-user-select, none);display:var(--ran-player-controller-bottom-right-display, flex);justify-content:var(--ran-player-controller-bottom-right-justify-content, flex-end);align-items:var(--ran-player-controller-bottom-right-align-items, center)}.ran-player-controller-bottom-right-volume{display:var(--ran-player-controller-bottom-right-volume-display, flex);justify-content:var(--ran-player-controller-bottom-right-volume-justify-content, space-between);align-items:var(--ran-player-controller-bottom-right-volume-align-items, center);margin-right:var(--ran-player-controller-bottom-right-volume-margin-right, 12px);cursor:var(--ran-player-controller-bottom-right-align-volume-cursor, pointer)}.ran-player-controller-bottom-right-volume-icon-volume{background:var(--ran-player-controller-bottom-right-align-volume-icon-volume-background, url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%3e%3cg%20opacity='0.8'%3e%3cpath%20d='M7.12053%2017.4845L7.42033%2016.797L7.27695%2016.7345H7.12053V17.4845ZM7.00016%207.48447V8.23447H7.1541L7.2956%208.17383L7.00016%207.48447ZM12.6061%205.08193L12.3106%204.39257L12.3106%204.39257L12.6061%205.08193ZM12.6003%2019.8741L12.3005%2020.5616L12.6003%2019.8741ZM7.12053%2016.7345H5V18.2345H7.12053V16.7345ZM5%2016.7345C4.30964%2016.7345%203.75%2016.1748%203.75%2015.4845H2.25C2.25%2017.0033%203.48122%2018.2345%205%2018.2345V16.7345ZM3.75%2015.4845V9.48447H2.25V15.4845H3.75ZM3.75%209.48447C3.75%208.79411%204.30964%208.23447%205%208.23447V6.73447C3.48122%206.73447%202.25%207.96569%202.25%209.48447H3.75ZM5%208.23447H7.00016V6.73447H5V8.23447ZM7.2956%208.17383L12.9015%205.77129L12.3106%204.39257L6.70472%206.79511L7.2956%208.17383ZM12.9015%205.77129C13.0665%205.70059%2013.25%205.8216%2013.25%206.00108H14.75C14.75%204.74472%2013.4654%203.89767%2012.3106%204.39257L12.9015%205.77129ZM13.25%206.00108V18.9575H14.75V6.00108H13.25ZM13.25%2018.9575C13.25%2019.1377%2013.0652%2019.2587%2012.9001%2019.1867L12.3005%2020.5616C13.4565%2021.0657%2014.75%2020.2186%2014.75%2018.9575H13.25ZM12.9001%2019.1867L7.42033%2016.797L6.82073%2018.1719L12.3005%2020.5616L12.9001%2019.1867Z'%20fill='white'/%3e%3cpath%20d='M17.625%2010.4849C17.8679%2011.2753%2017.9986%2012.1148%2017.9986%2012.9849C17.9986%2013.8549%2017.8679%2014.6944%2017.625%2015.4849'%20stroke='white'%20stroke-width='1.5'%20stroke-linecap='round'/%3e%3cpath%20d='M19.3359%206.48486C20.3972%208.41302%2021.0009%2010.6284%2021.0009%2012.9849C21.0009%2014.9436%2020%2017.4849%2019.3359%2018.4849'%20stroke='white'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/g%3e%3c/svg%3e") no-repeat);background-size:var(--ran-player-controller-bottom-right-align-volume-icon-volume-background-size, contain)}.ran-player-controller-bottom-right-volume-icon-mute{background:var(--ran-player-controller-bottom-right-align-volume-icon-mute-background, url("data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%3e%3cg%20opacity='0.8'%3e%3cpath%20d='M7.15802%2017.4845L7.4592%2016.7976L7.31522%2016.7345H7.15802V17.4845ZM7.00016%207.48447V8.23447H7.1541L7.2956%208.17383L7.00016%207.48447ZM12.6061%205.08193L12.3106%204.39257L12.3106%204.39257L12.6061%205.08193ZM12.5984%2019.87L12.8996%2019.1831H12.8996L12.5984%2019.87ZM7.15802%2016.7345H5V18.2345H7.15802V16.7345ZM5%2016.7345C4.30964%2016.7345%203.75%2016.1748%203.75%2015.4845H2.25C2.25%2017.0033%203.48122%2018.2345%205%2018.2345V16.7345ZM3.75%2015.4845V9.48447H2.25V15.4845H3.75ZM3.75%209.48447C3.75%208.79411%204.30964%208.23447%205%208.23447V6.73447C3.48122%206.73447%202.25%207.96569%202.25%209.48447H3.75ZM5%208.23447H7.00016V6.73447H5V8.23447ZM7.2956%208.17383L12.9015%205.77129L12.3106%204.39257L6.70472%206.79511L7.2956%208.17383ZM12.9015%205.77129C13.0665%205.70059%2013.25%205.8216%2013.25%206.00108H14.75C14.75%204.74472%2013.4654%203.89767%2012.3106%204.39257L12.9015%205.77129ZM13.25%206.00108V18.9542H14.75V6.00108H13.25ZM13.25%2018.9542C13.25%2019.1345%2013.0648%2019.2555%2012.8996%2019.1831L12.2972%2020.5568C13.4536%2021.0639%2014.75%2020.2168%2014.75%2018.9542H13.25ZM12.8996%2019.1831L7.4592%2016.7976L6.85684%2018.1713L12.2972%2020.5568L12.8996%2019.1831Z'%20fill='white'/%3e%3c/g%3e%3cg%20opacity='0.8'%3e%3cpath%20d='M18%2014.2427L22.2426%2010'%20stroke='white'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3cpath%20d='M22.2422%2014.2427L17.9995%2010'%20stroke='white'%20stroke-width='1.5'%20stroke-linecap='round'%20stroke-linejoin='round'/%3e%3c/g%3e%3c/svg%3e") no-repeat);background-size:var(--ran-player-controller-bottom-right-align-volume-icon-mute-background-size, contain)}.ran-player-controller-bottom-right-volume-icon{width:var(--ran-player-controller-bottom-right-align-volume-icon-width, 18px);height:var(--ran-player-controller-bottom-right-align-volume-icon-height, 18px);margin-right:6px}.ran-player-controller-bottom-right-volume-progress{width:var(--ran-player-controller-bottom-right-align-volume-progress-width, 50px);--ran-progress-wrap-height: 4px;--ran-progress-wrap-background: rgba(255, 255, 255, .3);--ran-progress-wrap-value-background: rgba(255, 255, 255, .8);--ran-progress-dot-top: -2px;--ran-progress-dot-left: -4px;--ran-progress-dot-width: 8px;--ran-progress-dot-height: 8px;--ran-progress-dot-background: #ffffff}.ran-player-controller-bottom-right-volume-progress .ran-progress-wrap{--ran-progress-wrap-height: 4px;--ran-progress-wrap-background: rgba(255, 255, 255, .3)}.ran-player-controller-bottom-right-volume-progress .ran-progress-wrap-value{--ran-progress-wrap-value-background: rgba(255, 255, 255, .8)}.ran-player-controller-bottom-right-volume-progress .ran-progress-dot{--ran-progress-dot-top: -2px;--ran-progress-dot-left: -4px;--ran-progress-dot-width: 8px;--ran-progress-dot-height: 8px;--ran-progress-dot-background: #ffffff}.ran-player-controller-bottom-right-speed{width:var(--ran-player-controller-bottom-right-align-speed-width, 30px);height:var(--ran-player-controller-bottom-right-align-speed-height, 20px);color:var(--ran-player-controller-bottom-right-align-speed-color, #fff);font-family:var(--ran-player-controller-bottom-right-align-speed-font-family, PingFang SC);font-size:var(--ran-player-controller-bottom-right-align-speed-font-size, 14px);font-style:var(--ran-player-controller-bottom-right-align-speed-font-style, normal);font-weight:var(--ran-player-controller-bottom-right-align-speed-font-weight, 400);line-height:var(--ran-player-controller-bottom-right-align-speed-line-height, normal);margin-right:var(--ran-player-controller-bottom-right-align-speed-margin-right, 22px);cursor:var(--ran-player-controller-bottom-right-align-speed-cursor, pointer);outline:var(--ran-player-controller-bottom-right-align-speed-outline, 0);-webkit-tap-highlight-color:transparent}.ran-player-controller-bottom-right-speed:active,.ran-player-controller-bottom-right-speed:focus{outline:var(--ran-player-controller-bottom-right-align-speed-focus-outline, 0);-webkit-tap-highlight-color:transparent}.ran-player-controller-bottom-right-speed r-select{width:46px;height:20px;outline:0;-webkit-tap-highlight-color:transparent}.ran-player-controller-bottom-right-speed r-select:active,.ran-player-controller-bottom-right-speed r-select:focus{outline:0;-webkit-tap-highlight-color:transparent}.ran-player-controller-bottom-right-speed r-select::part(selection){background-color:transparent}.ran-player-controller-bottom-right-speed r-select::part(selection-item){top:1px;color:#fff;font-size:12px}.ran-player-controller-bottom-right-clarity{color:var(--ran-player-controller-bottom-right-align-clarity-color, #fff);font-family:var(--ran-player-controller-bottom-right-align-clarity-font-family, PingFang SC);font-size:var(--ran-player-controller-bottom-right-align-clarity-font-size, 14px);width:var(--ran-player-controller-bottom-right-align-clarity-width, 30px);height:var(--ran-player-controller-bottom-right-align-clarity-height, 20px);font-style:var(--ran-player-controller-bottom-right-align-clarity-font-style, normal);font-weight:var(--ran-player-controller-bottom-right-align-clarity-font-weight, 400);line-height:var(--ran-player-controller-bottom-right-align-clarity-line-height, normal);cursor:var(--ran-player-controller-bottom-right-align-clarity-cursor, pointer);margin-right:var(--ran-player-controller-bottom-right-align-clarity-margin-right, 12px);outline:var(--ran-player-controller-bottom-right-align-clarity-outline, 0);-webkit-tap-highlight-color:transparent}.ran-player-controller-bottom-right-clarity:active,.ran-player-controller-bottom-right-clarity:focus{outline:var(--ran-player-controller-bottom-right-align-clarity-focus-outline, 0);-webkit-tap-highlight-color:transparent}.ran-player-controller-bottom-right-clarity r-select{width:46px;height:20px;outline:0;-webkit-tap-highlight-color:transparent}.ran-player-controller-bottom-right-clarity r-select:active,.ran-player-controller-bottom-right-clarity r-select:focus{outline:0;-webkit-tap-highlight-color:transparent}.ran-player-controller-bottom-right-clarity r-select::part(selection){background-color:transparent}.ran-player-controller-bottom-right-clarity r-select::part(selection-item){top:1px;color:#fff;font-size:12px}.ran-player-controller-bottom-right-knowledge{color:var(--ran-player-controller-bottom-right-align-knowledge-color, #fff);font-family:var(--ran-player-controller-bottom-right-align-knowledge-font-family, PingFang SC);font-size:var(--ran-player-controller-bottom-right-align-knowledge-font-size, 14px);font-style:var(--ran-player-controller-bottom-right-align-knowledge-font-style, normal);font-weight:var(--ran-player-controller-bottom-right-align-knowledge-font-weight, 400);line-height:var(--ran-player-controller-bottom-right-align-knowledge-line-height, normal);margin-right:var(--ran-player-controller-bottom-right-align-knowledge-margin-right, 24px);cursor:var(--ran-player-controller-bottom-right-align-knowledge-cursor, pointer)}.ran-player-controller-bottom-right-full{background:var(--ran-player-controller-bottom-right-align-full-background, url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAGFSURBVHgB7VjRcYJAEN1j/KUAKcAUYAGhAK3AAvxPA1pAGrCAVBD/QwGhACnAFGABZF+yMMt5es4IBx/3ZnaUu2PfOzjg9hlyoK7rlH9yjrmj+2yMOdID4DzrGzkqjhPn+bE7Zg4hbxxruk9EPlEiZucZgxwHLSxRnZjJh09Mz1hBkHD/wSgxB45MDS7p/9JerCR93LKlRJuTY8N5L82JO45viS+OJQ0M5siFq+HdNx1z1YjIKRAwcYs7xRp6UWNKvmwFBQJzYVmUqukVghaqoaTwqNT/LKHx0XlopiCogyjIBwjS35Mzhcc1P96oHCsaCWPzR0RERFxhSi/Gma4OHqkmhhCj+fEt05vwjMKjwx+3Hz5MXlBKI8PeoC0oPHRRWkFQoTtDVK0NpCjVfKdE6ulP1fgeonqViWt35AgXpDEbsHbgfNhmg6twfNZsABeWhm02bFtBcrLLAbmFfR/+kC0GB+1TJg1b6t6+oYFJbbRhZVyj5GrBhHA9dX34QxBQtH6Qwi//yug9jgFQZgAAAABJRU5ErkJggg==));background-size:var(--ran-player-controller-bottom-right-align-full-background-size, contain);width:var(--ran-player-controller-bottom-right-align-full-width, 16px);height:var(--ran-player-controller-bottom-right-align-full-height, 16px);cursor:var(--ran-player-controller-bottom-right-align-full-cursor, pointer)}.ran-input{position:relative;display:flex;width:var(--ran-input-width, calc(100% - 12px) );height:var(--ran-input-height, calc(100% - 4px) );min-width:0;padding:var(--ran-input-padding, 2px 6px);color:#000000d9;font-size:var(--ran-input-font-size, 12px);line-height:var(--ran-input-line-height, 1.5715);background-color:var(--ran-input-background-color, #fff);background-image:var(--ran-input-background-image, none);border:var(--ran-input-border, 1px solid #d9d9d9);border-radius:var(--ran-input-border-radius, 2px);transition:var(--ran-input-transition, all .3s)}.ran-input .ran-icon{display:flex;align-items:center;justify-content:center}.ran-input:active{border-color:#40a9ff;box-shadow:0 0 0 2px #1890ff33;border-right-width:1px;outline:0}.ran-input:hover{border-color:#40a9ff;border-right-width:1px}.ran-input>.ran-input-content:hover~.ran-input-label{color:#40a9ff}.ran-input[value]>.ran-input-label{transform:translateY(calc(-50% - .43em)) scale(.8);color:#00000040}.ran-input[status=error]{border-color:#ff4d4f}.ran-input[status=error]>.ran-input-content~.ran-input-label{color:#ff4d4f}.ran-input[status=warning]{border-color:#ff7875}.ran-input[status=warning]>.ran-input-content~.ran-input-label{color:#ff7875}.ran-input[disabled]{color:#00000040;background-color:#f5f5f5;border-color:#d9d9d9;box-shadow:none;cursor:not-allowed;opacity:1}.ran-input[disabled]>.ran-input-content{color:#00000040;background-color:#f5f5f5;border-color:#d9d9d9;box-shadow:none;cursor:not-allowed;opacity:1}.ran-input[disabled]>.ran-input-content~.ran-input-label{color:#00000040;background-color:#f5f5f5}.ran-input[disabled]>.ran-input-label{color:#999;border-color:#d9d9d9;box-shadow:none;cursor:not-allowed}.ran-input-content{writing-mode:horizontal-tb;text-rendering:auto;letter-spacing:normal;word-spacing:normal;text-transform:none;text-indent:0px;text-shadow:none;text-align:start;-webkit-rtl-ordering:logical;cursor:text;touch-action:manipulation;-webkit-appearance:none;text-overflow:ellipsis;box-sizing:border-box;margin:0;font-variant:tabular-nums;list-style:none;font-feature-settings:"tnum";position:relative;border:none;width:100%;min-width:0;color:#000000d9;font-size:14px;line-height:1.48;background-color:#fff;background-image:none;transition:all .3s;outline:none}.ran-input-content:focus,.ran-input-content:hover{border:none;outline:0}.ran-input-content::-moz-placeholder{color:#999}.ran-input-content::placeholder{color:#999}.ran-input-content:-moz-placeholder-shown~.ran-input-label{transform:translateY(calc(-50% - .43em)) scale(.8)}.ran-input-content:placeholder-shown~.ran-input-label{transform:translateY(calc(-50% - .43em)) scale(.8)}.ran-input-content:focus~.ran-input-label{transform:translateY(calc(-50% - .43em)) scale(.8)}.ran-input-content::-webkit-search-cancel-button{display:none;-webkit-appearance:none}.ran-input-label{pointer-events:none;position:absolute;font-size:14px;left:8px;transition:transform .3s,color .3s,background-color .3s,-webkit-backdrop-filter .3s;transition:transform .3s,color .3s,background-color .3s,backdrop-filter .3s;transition:transform .3s,color .3s,background-color .3s,backdrop-filter .3s,-webkit-backdrop-filter .3s;transform-origin:left;padding:0 .2em;color:#999;background:#fff;opacity:.9}.ran-icon{display:flex;align-items:center;justify-content:center}@keyframes rotate{to{transform:rotate(360deg)}}ra-select{display:inline-block;cursor:pointer;position:relative;width:120px;height:40px;outline:0;-webkit-tap-highlight-color:transparent}ra-select,ra-select:focus,ra-select:active{outline:0;-webkit-tap-highlight-color:transparent}ra-select r-option{display:none}ra-select[disabled]{cursor:not-allowed;pointer-events:all;opacity:.6}ra-select:not([disabled]):not([type=text]):hover .select{cursor:pointer}ra-select:not([disabled]):not([type=text]):hover .selection{border:1px solid #1890ff}ra-select:not([disabled]):not([type=text]):hover .selection-search{cursor:pointer}ra-select:not([disabled]):not([type=text]):hover .selection-item{cursor:pointer;color:#bfbfbf}ra-select:not([disabled]):focus .selection{border:1px solid #1890ff}ra-select:not([disabled]):focus .selection-search{cursor:pointer}ra-select:not([disabled]):focus .selection-item{cursor:pointer;color:#bfbfbf}ra-select .selection-search{display:none}ra-select[showSearch]:not([disabled]) .selection-search{cursor:text;display:block}ra-select[showSearch]:not([disabled]) .selection-item{cursor:pointer}ra-select[showSearch]:not([disabled]):focus .selection-search{display:block;cursor:text;opacity:1}ra-select[type=text] .selection{border:none}ra-select[type=text] .icon{display:none}.ran-select{width:100%;height:100%;box-sizing:border-box;margin:0;padding:0;color:#000000e0;font-size:14px;line-height:1.57142857;list-style:none;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";position:relative;display:inline-block}.ran-select .selection{position:relative;background-color:#fff;border:1px solid #d9d9d9;transition:all .2s cubic-bezier(.645,.045,.355,1);width:100%;height:100%;padding:0 11px;box-sizing:border-box;margin:0;color:#000000e0;font-size:14px;line-height:1.57142857;list-style:none;font-family:inherit;display:flex;border-radius:6px}.ran-select .selection-search{position:absolute;top:0;left:0;height:100%;inset-inline-start:11px;inset-inline-end:11px;opacity:0;margin:0;padding:0;background:transparent;border:none;outline:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;font-family:inherit;cursor:not-allowed}.ran-select .selection-search::-webkit-search-cancel-button{display:none;-webkit-appearance:none}.ran-select .selection-search .ran-input{border:none;padding:0;height:100%;outline:none}.ran-select .selection-search .ran-input:active{border:none;padding:0;height:100%;outline:none;border-color:transparent;box-shadow:none;border-right-width:0px}.ran-select .selection-item{position:absolute;top:0;left:12px;margin:0;padding:0;background:transparent;border:none;outline:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;font-family:inherit;height:100%;-webkit-user-select:none;-moz-user-select:none;user-select:none;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;cursor:pointer}.ran-select .selection-select{color:#00000040}.ran-select .selection .icon{display:flex;align-items:center;color:#00000040;font-style:normal;text-align:center;text-transform:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;position:absolute;top:50%;inset-inline-start:auto;inset-inline-end:8px;height:12px;margin-top:-3px;font-size:12px;pointer-events:none}.ran-colorpicker{box-sizing:border-box;min-width:32px;height:32px;border-radius:6px;border:1px solid #d9d9d9;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:all .2s;background:#fff;padding:3px}.ran-colorpicker-block{position:relative;border-radius:4px;width:24px;height:24px;box-shadow:inset 0 0 1px #00000040;background-image:conic-gradient(rgba(0,0,0,.06) 0 25%,transparent 0 50%,rgba(0,0,0,.06) 0 75%,transparent 0);background-size:50% 50%}.ran-colorpicker-inner{width:100%;height:100%;border-radius:inherit}.ran-color-picker{box-sizing:border-box}.ran-color-picker-inner-content{box-sizing:border-box;display:flex;flex-direction:column;width:234px}.ran-color-picker-panel{box-sizing:border-box;margin-bottom:12px}.ran-color-picker-input-container{display:flex;width:100%;align-items:center;justify-content:space-between}.ran-color-picker-input-container-select{display:block;width:42px;height:24px;position:relative}.ran-color-picker-input-container-select-item{display:block;width:42px;height:24px}.ran-color-picker-input-container-select-item .selection{border:none;padding:0}.ran-color-picker-input-container-select-item .selection-item{font-size:12px;left:0}.ran-color-picker-input-container-select-item .icon .ran-icon{position:relative;left:6px}.ran-color-picker-input-container-select .ranui-select-dropdown-option-item{padding:2px}.ran-color-picker-input-container-select .ranui-select-dropdown-option-item-content{font-size:12px;text-align:center}.ran-color-picker-input-container-input-color{width:138px;height:24px}.ran-color-picker-input-container-input-color::part(ran-input){border-radius:6px}.ran-color-picker-input-container-input-number{width:42px;height:24px}.ran-color-picker-input-container-input-number::part(ran-input){border-radius:6px}.ran-color-picker-palette{position:relative;min-height:160px;overflow:hidden;border-radius:4px}.ran-color-picker-palette-dot{position:absolute;z-index:1;will-change:top,left}.ran-color-picker-palette-dot-inner{width:12px;height:12px;border:2px solid #fff;border-radius:50%;cursor:pointer;box-shadow:inset 0 0 1px #00000040,0 0 0 1px #0000000f;background-color:transparent}.ran-color-picker-saturation{background-color:#006aff;background-image:linear-gradient(0deg,#000000,transparent),linear-gradient(90deg,#fff,#fff0);position:absolute;border-radius:inherit;box-shadow:inset 0 0 1px #00000040;top:0;right:0;bottom:0;left:0}.ran-color-picker-slider-container{box-sizing:border-box;display:flex;gap:12px;margin-bottom:12px}.ran-color-picker-slider-container-group{flex:1;box-sizing:border-box}.ran-color-picker-slider-container-group-hue{display:block;margin-bottom:12px}.ran-color-picker-slider-container-group-hue .ran-progress{position:relative;height:8px}.ran-color-picker-slider-container-group-hue .ran-progress-dot{z-index:1;width:8px;height:8px;top:-2px;left:-4px;border:2px solid #fff;border-radius:50%;cursor:pointer;box-shadow:inset 0 0 1px #00000040,0 0 0 1px #0000000f}.ran-color-picker-slider-container-group-hue .ran-progress-wrap{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:4px;box-shadow:inset 0 0 1px #00000040}.ran-color-picker-slider-container-group-hue .ran-progress-wrap-value{background:transparent}.ran-color-picker-slider-container-group-alpha{background-image:conic-gradient(rgba(0,0,0,.06) 0 25%,transparent 0 50%,rgba(0,0,0,.06) 0 75%,transparent 0);background-size:8px 8px;border-radius:4px;box-sizing:border-box}.ran-color-picker-slider-container-group-alpha .ran-progress{position:relative;height:8px}.ran-color-picker-slider-container-group-alpha .ran-progress-dot{top:-2px;left:-4px;z-index:1;width:8px;height:8px;border:2px solid #fff;position:relative;border-radius:50%;cursor:pointer;box-shadow:inset 0 0 1px #00000040,0 0 0 1px #0000000f}.ran-color-picker-slider-container-group-alpha .ran-progress-wrap{position:absolute;top:0;right:0;bottom:0;left:0;border-radius:4px;box-shadow:inset 0 0 1px #00000040}.ran-color-picker-slider-container-group-alpha .ran-progress-wrap-value{background:transparent}.ran-color-picker-slider-container-color-block{position:relative;border-radius:4px;width:28px;height:28px;box-shadow:inset 0 0 1px #00000040;background-image:conic-gradient(rgba(0,0,0,.06) 0 25%,transparent 0 50%,rgba(0,0,0,.06) 0 75%,transparent 0);background-size:50% 50%}.ran-color-picker-slider-container-color-block-inner{width:100%;height:100%;border:1px solid rgba(0,0,0,.06);border-radius:inherit}.remove-wap-active-focus{outline:0;-webkit-tap-highlight-color:transparent}.remove-wap-active-focus:active,.remove-wap-active-focus:focus{outline:0;-webkit-tap-highlight-color:transparent}body{margin:0}.x-spreadsheet{font-size:13px;line-height:normal;-webkit-user-select:none;user-select:none;-moz-user-select:none;font-family:Lato,Source Sans Pro,Roboto,Helvetica,Arial,sans-serif;box-sizing:content-box;background:#fff;-webkit-font-smoothing:antialiased}.x-spreadsheet textarea{font:400 13px Arial,Lato,Source Sans Pro,Roboto,Helvetica,sans-serif}.x-spreadsheet-sheet{position:relative;overflow:hidden}.x-spreadsheet-table{vertical-align:bottom}.x-spreadsheet-tooltip{font-family:inherit;position:absolute;padding:5px 10px;color:#fff;border-radius:1px;background:#000;font-size:12px;z-index:201}.x-spreadsheet-tooltip:before{pointer-events:none;position:absolute;left:calc(50% - 4px);top:-4px;content:"";width:8px;height:8px;background:inherit;transform:rotate(45deg);z-index:1;box-shadow:1px 1px 3px -1px #0000004d}.x-spreadsheet-color-palette{padding:5px}.x-spreadsheet-color-palette table{margin:0;padding:0;border-collapse:separate;border-spacing:2;background:#fff}.x-spreadsheet-color-palette table td{margin:0;cursor:pointer;border:1px solid transparent}.x-spreadsheet-color-palette table td:hover{border-color:#ddd}.x-spreadsheet-color-palette table td .x-spreadsheet-color-palette-cell{width:16px;height:16px}.x-spreadsheet-border-palette{padding:6px}.x-spreadsheet-border-palette table{margin:0;padding:0;border-collapse:separate;border-spacing:0;background:#fff;table-layout:fixed}.x-spreadsheet-border-palette table td{margin:0}.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left{border-right:1px solid #eee;padding-right:6px}.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell{width:30px;height:30px;cursor:pointer;text-align:center}.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell .x-spreadsheet-icon-img{opacity:.8}.x-spreadsheet-border-palette .x-spreadsheet-border-palette-left .x-spreadsheet-border-palette-cell:hover{background-color:#eee}.x-spreadsheet-border-palette .x-spreadsheet-border-palette-right{padding-left:6px}.x-spreadsheet-border-palette .x-spreadsheet-border-palette-right .x-spreadsheet-toolbar-btn{margin-top:0;margin-bottom:3px}.x-spreadsheet-border-palette .x-spreadsheet-border-palette-right .x-spreadsheet-line-type{position:relative;left:0;top:-3px}.x-spreadsheet-dropdown{position:relative}.x-spreadsheet-dropdown .x-spreadsheet-dropdown-content{position:absolute;z-index:200;background:#fff;box-shadow:1px 2px 5px 2px #33333326}.x-spreadsheet-dropdown.bottom-left .x-spreadsheet-dropdown-content{top:calc(100% + 5px);left:0}.x-spreadsheet-dropdown.bottom-right .x-spreadsheet-dropdown-content{top:calc(100% + 5px);right:0}.x-spreadsheet-dropdown.top-left .x-spreadsheet-dropdown-content{bottom:calc(100% + 5px);left:0}.x-spreadsheet-dropdown.top-right .x-spreadsheet-dropdown-content{bottom:calc(100% + 5px);right:0}.x-spreadsheet-dropdown .x-spreadsheet-dropdown-title{padding:0 5px;display:inline-block}.x-spreadsheet-dropdown .x-spreadsheet-dropdown-header .x-spreadsheet-icon.arrow-left{margin-left:4px}.x-spreadsheet-dropdown .x-spreadsheet-dropdown-header .x-spreadsheet-icon.arrow-right{width:10px;margin-right:4px}.x-spreadsheet-dropdown .x-spreadsheet-dropdown-header .x-spreadsheet-icon.arrow-right .arrow-down{left:-130px}.x-spreadsheet-resizer{position:absolute;z-index:11}.x-spreadsheet-resizer .x-spreadsheet-resizer-hover{background-color:#4b89ff40}.x-spreadsheet-resizer .x-spreadsheet-resizer-line{position:absolute}.x-spreadsheet-resizer.horizontal{cursor:row-resize}.x-spreadsheet-resizer.horizontal .x-spreadsheet-resizer-line{border-bottom:2px dashed #4b89ff;left:0;bottom:0}.x-spreadsheet-resizer.vertical{cursor:col-resize}.x-spreadsheet-resizer.vertical .x-spreadsheet-resizer-line{border-right:2px dashed #4b89ff;top:0;right:0}.x-spreadsheet-scrollbar{position:absolute;bottom:0;right:0;background-color:#f4f5f8;opacity:.9;z-index:12}.x-spreadsheet-scrollbar.horizontal{right:15px;overflow-x:scroll;overflow-y:hidden}.x-spreadsheet-scrollbar.horizontal>div{height:1px;background:#ddd}.x-spreadsheet-scrollbar.vertical{bottom:15px;overflow-x:hidden;overflow-y:scroll}.x-spreadsheet-scrollbar.vertical>div{width:1px;background:#ddd}.x-spreadsheet-overlayer{position:absolute;left:0;top:0;z-index:10}.x-spreadsheet-overlayer .x-spreadsheet-overlayer-content{position:absolute;overflow:hidden;pointer-events:none;width:100%;height:100%}.x-spreadsheet-editor,.x-spreadsheet-selector{box-sizing:content-box;position:absolute;overflow:hidden;pointer-events:none;top:0;left:0;width:100%;height:100%}.x-spreadsheet-selector .hide-input{position:absolute;z-index:0}.x-spreadsheet-selector .hide-input input{padding:0;width:0;border:none!important}.x-spreadsheet-selector .x-spreadsheet-selector-area{position:absolute;border:2px solid #4b89ff;background:#4b89ff1a;z-index:5}.x-spreadsheet-selector .x-spreadsheet-selector-clipboard,.x-spreadsheet-selector .x-spreadsheet-selector-autofill{position:absolute;background:transparent;z-index:100}.x-spreadsheet-selector .x-spreadsheet-selector-clipboard{border:2px dashed #4b89ff}.x-spreadsheet-selector .x-spreadsheet-selector-autofill{border:1px dashed rgba(0,0,0,.45)}.x-spreadsheet-selector .x-spreadsheet-selector-corner{pointer-events:auto;position:absolute;cursor:crosshair;font-size:0;height:5px;width:5px;right:-5px;bottom:-5px;border:2px solid #ffffff;background:#4b89ff}.x-spreadsheet-editor{z-index:20}.x-spreadsheet-editor .x-spreadsheet-editor-area{position:absolute;text-align:left;border:2px solid #4b89ff;line-height:0;z-index:100;pointer-events:auto}.x-spreadsheet-editor .x-spreadsheet-editor-area textarea{box-sizing:content-box;border:none;padding:0 3px;outline:none;resize:none;text-align:start;overflow-y:hidden;font:400 13px Arial,Lato,Source Sans Pro,Roboto,Helvetica,sans-serif;color:inherit;white-space:normal;word-wrap:break-word;line-height:22px;margin:0}.x-spreadsheet-editor .x-spreadsheet-editor-area .textline{overflow:hidden;visibility:hidden;position:fixed;top:0;left:0}.x-spreadsheet-item{-webkit-user-select:none;-moz-user-select:none;user-select:none;background:0;border:1px solid transparent;outline:none;height:26px;color:#000000e6;line-height:26px;list-style:none;padding:2px 10px;cursor:default;text-align:left;overflow:hidden}.x-spreadsheet-item.disabled{pointer-events:none;opacity:.5}.x-spreadsheet-item:hover,.x-spreadsheet-item.active{background:#0000000d}.x-spreadsheet-item.divider{height:0;padding:0;margin:5px 0;border:none;border-bottom:1px solid rgba(0,0,0,.1)}.x-spreadsheet-item .label{float:right;opacity:.65;font-size:1em}.x-spreadsheet-item.state,.x-spreadsheet-header.state{padding-left:35px!important;position:relative}.x-spreadsheet-item.state:before,.x-spreadsheet-header.state:before{content:"";position:absolute;width:10px;height:10px;left:12px;top:calc(50% - 5px);background:#00000014;border-radius:2px}.x-spreadsheet-item.state.checked:before,.x-spreadsheet-header.state.checked:before{background:#4b89ff}.x-spreadsheet-checkbox{position:relative;display:inline-block;backface-visibility:hidden;outline:0;vertical-align:baseline;font-style:normal;font-size:1rem;line-height:1em}.x-spreadsheet-checkbox>input{position:absolute;top:0;left:0;opacity:0!important;outline:0;z-index:-1}.x-spreadsheet-suggest,.x-spreadsheet-contextmenu,.x-spreadsheet-sort-filter{position:absolute;box-shadow:1px 2px 5px 2px #33333326;background:#fff;z-index:100;width:260px;pointer-events:auto;overflow:auto}.x-spreadsheet-suggest{width:200px}.x-spreadsheet-filter{border:1px solid #e9e9e9;font-size:12px;margin:10px}.x-spreadsheet-filter .x-spreadsheet-header{padding:.5em .75em;background:#f8f8f9;border-bottom:1px solid #e9e9e9;border-left:1px solid transparent}.x-spreadsheet-filter .x-spreadsheet-body{height:200px;overflow-y:auto}.x-spreadsheet-filter .x-spreadsheet-body .x-spreadsheet-item{height:20px;line-height:20px}.x-spreadsheet-sort-filter .x-spreadsheet-buttons{margin:10px}.x-spreadsheet-toolbar,.x-spreadsheet-bottombar{height:40px;padding:0 30px;text-align:left;background:#f5f6f7;display:flex}.x-spreadsheet-bottombar{position:relative;border-top:1px solid #e0e2e4}.x-spreadsheet-bottombar .x-spreadsheet-menu>li{line-height:40px;height:40px;padding-top:0;padding-bottom:0;vertical-align:middle;border-right:1px solid #e8eaed}.x-spreadsheet-menu{list-style:none;margin:0;padding:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.x-spreadsheet-menu>li{float:left;line-height:1.25em;padding:.785em 1em;margin:0;vertical-align:middle;text-align:left;color:#80868b;white-space:nowrap;cursor:pointer;transition:all .3s;font-weight:700}.x-spreadsheet-menu>li.active{background-color:#fff;color:#000000a6}.x-spreadsheet-menu>li .x-spreadsheet-icon{margin:0 6px}.x-spreadsheet-menu>li .x-spreadsheet-icon .x-spreadsheet-icon-img:hover{opacity:.85}.x-spreadsheet-menu>li .x-spreadsheet-dropdown{display:inline-block}.x-spreadsheet-toolbar{border-bottom:1px solid #e0e2e4}.x-spreadsheet-toolbar .x-spreadsheet-toolbar-btns{display:inline-flex}.x-spreadsheet-toolbar .x-spreadsheet-toolbar-more{padding:0 6px 6px;text-align:left}.x-spreadsheet-toolbar .x-spreadsheet-toolbar-more .x-spreadsheet-toolbar-divider{margin-top:0}.x-spreadsheet-toolbar .x-spreadsheet-toolbar-btn{flex:0 0 auto;display:inline-block;border:1px solid transparent;height:26px;line-height:26px;min-width:26px;margin:6px 1px 0;padding:0;text-align:center;border-radius:2px}.x-spreadsheet-toolbar .x-spreadsheet-toolbar-btn.disabled{pointer-events:none;opacity:.5}.x-spreadsheet-toolbar .x-spreadsheet-toolbar-btn:hover,.x-spreadsheet-toolbar .x-spreadsheet-toolbar-btn.active{background:#00000014}.x-spreadsheet-toolbar-divider{display:inline-block;border-right:1px solid #e0e2e4;width:0;vertical-align:middle;height:18px;margin:12px 3px 0}.x-spreadsheet-print{position:absolute;left:0;top:0;z-index:100;width:100%;height:100%;display:flex;flex-direction:column}.x-spreadsheet-print-bar{background:#424242;height:60px;line-height:60px;padding:0 30px}.x-spreadsheet-print-bar .-title{color:#fff;font-weight:700;font-size:1.2em;float:left}.x-spreadsheet-print-bar .-right{float:right;margin-top:12px}.x-spreadsheet-print-content{display:flex;flex:auto;flex-direction:row;background:#d0d0d0;height:calc(100% - 60px)}.x-spreadsheet-print-content .-sider{flex:0 0 300px;width:300px;border-left:2px solid #ccc;background:#fff}.x-spreadsheet-print-content .-content{flex:auto;overflow-x:auto;overflow-y:scroll;height:100%}.x-spreadsheet-canvas-card-wraper{margin:40px 20px}.x-spreadsheet-canvas-card{background:#fff;margin:auto;page-break-before:auto;page-break-after:always;box-shadow:0 8px 10px 1px #00000024,0 3px 14px 3px #0000001f,0 4px 5px #0003}.x-spreadsheet-calendar{color:#000000a6;background:#fff;-webkit-user-select:none;-moz-user-select:none;user-select:none}.x-spreadsheet-calendar .calendar-header{font-weight:700;line-height:30px;text-align:center;width:100%;float:left;background:#f9fafb}.x-spreadsheet-calendar .calendar-header .calendar-header-left{padding-left:5px;float:left}.x-spreadsheet-calendar .calendar-header .calendar-header-right{float:right}.x-spreadsheet-calendar .calendar-header .calendar-header-right a{padding:3px 0;margin-right:2px;border-radius:2px}.x-spreadsheet-calendar .calendar-header .calendar-header-right a:hover{background:#00000014}.x-spreadsheet-calendar .calendar-body{border-collapse:collapse;border-spacing:0}.x-spreadsheet-calendar .calendar-body th,.x-spreadsheet-calendar .calendar-body td{width:100%/7;min-width:32px;text-align:center;font-weight:700;line-height:30px;padding:0}.x-spreadsheet-calendar .calendar-body td>.cell:hover{background:#ecf6fd}.x-spreadsheet-calendar .calendar-body td>.cell.active,.x-spreadsheet-calendar .calendar-body td>.cell.active:hover{background:#ecf6fd;color:#2185d0}.x-spreadsheet-calendar .calendar-body td>.cell.disabled{pointer-events:none;opacity:.5}.x-spreadsheet-datepicker{box-shadow:2px 2px 5px #0003;position:absolute;left:0;top:calc(100% + 5px);z-index:10;width:auto}.x-spreadsheet-buttons{display:flex;justify-content:flex-end}.x-spreadsheet-buttons .x-spreadsheet-button{margin-left:8px}.x-spreadsheet-button{display:inline-block;border-radius:3px;line-height:1em;min-height:1em;white-space:nowrap;text-align:center;cursor:pointer;font-size:1em;font-weight:700;padding:.75em 1em;color:#0009;background:#e0e1e2;text-decoration:none;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;outline:none;vertical-align:baseline;zoom:1;-webkit-user-select:none;-moz-user-select:none;user-select:none;transition:all .1s linear}.x-spreadsheet-button.active,.x-spreadsheet-button:hover{background-color:#c0c1c2;color:#000c}.x-spreadsheet-button.primary{color:#fff;background-color:#2185d0}.x-spreadsheet-button.primary:hover,.x-spreadsheet-button.primary.active{color:#fff;background-color:#1678c2}.x-spreadsheet-form-input{font-size:1em;position:relative;font-weight:400;display:inline-flex;color:#000000de}.x-spreadsheet-form-input input{z-index:1;margin:0;max-width:100%;flex:1 0 auto;outline:0;-webkit-tap-highlight-color:rgba(255,255,255,0);text-align:left;line-height:30px;height:30px;padding:0 8px;background:#fff;border:1px solid #e9e9e9;border-radius:3px;transition:box-shadow .1s ease,border-color .1s ease;box-shadow:inset 0 1px 2px #0a0a0a0f}.x-spreadsheet-form-input input:focus{border-color:#4b89ff;box-shadow:inset 0 1px 2px #4b89ff33}.x-spreadsheet-form-select{position:relative;display:inline-block;background:#fff;border:1px solid #e9e9e9;border-radius:2px;cursor:pointer;color:#000000de;-webkit-user-select:none;-moz-user-select:none;user-select:none;box-shadow:inset 0 1px 2px #0a0a0a0f}.x-spreadsheet-form-select .input-text{text-overflow:ellipsis;white-space:nowrap;min-width:60px;width:auto;height:30px;line-height:30px;padding:0 8px}.x-spreadsheet-form-fields{display:flex;flex-direction:row;flex-wrap:wrap}.x-spreadsheet-form-fields .x-spreadsheet-form-field{flex:0 1 auto}.x-spreadsheet-form-fields .x-spreadsheet-form-field .label{display:inline-block;margin:0 10px 0 0}.x-spreadsheet-form-field{display:block;vertical-align:middle;margin-left:10px;margin-bottom:10px}.x-spreadsheet-form-field:first-child{margin-left:0}.x-spreadsheet-form-field.error .x-spreadsheet-form-select,.x-spreadsheet-form-field.error input{border-color:#f04134}.x-spreadsheet-form-field .tip{color:#f04134;font-size:.9em}.x-spreadsheet-dimmer{display:none;position:absolute;top:0!important;left:0!important;width:100%;height:100%;text-align:center;vertical-align:middle;background-color:#0009;opacity:0;animation-fill-mode:both;animation-duration:.5s;transition:background-color .5s linear;-webkit-user-select:none;-moz-user-select:none;user-select:none;z-index:1000}.x-spreadsheet-dimmer.active{display:block;opacity:1}form fieldset{border:none}form fieldset label{display:block;margin-bottom:.5em;font-size:1em;color:#666}form fieldset select{font-size:1.1em;width:100%;background-color:#fff;border:none;border-bottom:2px solid #ddd;padding:.5em .85em;border-radius:2px}.x-spreadsheet-modal,.x-spreadsheet-toast{font-size:13px;position:fixed;z-index:1001;text-align:left;line-height:1.25em;min-width:360px;color:#000000de;font-family:Lato,Source Sans Pro,Roboto,Helvetica,Arial,sans-serif;border-radius:4px;border:1px solid rgba(0,0,0,.1);background-color:#fff;background-clip:padding-box;box-shadow:#0003 0 2px 8px}.x-spreadsheet-toast{background-color:#ffffffd9}.x-spreadsheet-modal-header,.x-spreadsheet-toast-header{font-weight:600;background-clip:padding-box;background-color:#ffffffd9;border-bottom:1px solid rgba(0,0,0,.05);border-radius:4px 4px 0 0}.x-spreadsheet-modal-header .x-spreadsheet-icon,.x-spreadsheet-toast-header .x-spreadsheet-icon{position:absolute;right:.8em;top:.65em;border-radius:18px}.x-spreadsheet-modal-header .x-spreadsheet-icon:hover,.x-spreadsheet-toast-header .x-spreadsheet-icon:hover{opacity:1;background:#00000014}.x-spreadsheet-toast-header{color:#f2711c}.x-spreadsheet-modal-header{border-bottom:1px solid #e0e2e4;background:#00000014;font-size:1.0785em}.x-spreadsheet-modal-header,.x-spreadsheet-modal-content,.x-spreadsheet-toast-header,.x-spreadsheet-toast-content{padding:.75em 1em}@media screen and (min-width: 320px) and (max-width: 480px){.x-spreadsheet-toolbar{display:none}}.x-spreadsheet-icon{width:18px;height:18px;margin:1px 1px 2px;text-align:center;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;user-select:none;overflow:hidden;position:relative;display:inline-block}.x-spreadsheet-icon .x-spreadsheet-icon-img{background-image:url("data:image/svg+xml,%3c?xml%20version='1.0'%20encoding='UTF-8'?%3e%3c!DOCTYPE%20svg%20PUBLIC%20'-//W3C//DTD%20SVG%201.1//EN'%20'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'%3e%3csvg%20xmlns:xlink='http://www.w3.org/1999/xlink'%20xmlns='http://www.w3.org/2000/svg'%20version='1.1'%20x='0'%20y='0'%20width='262px'%20height='72px'%20viewBox='0%200%20262%2072'%20preserveAspectRatio='none'%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(0,0)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M11.5656391,4.43436088%20L9,7%20L16,7%20L16,0%20L13.0418424,2.95815758%20C11.5936787,1.73635959%209.72260775,1%207.67955083,1%20C4.22126258,1%201.25575599,3.10984908%200,6%20L2,7%20C2.93658775,4.60974406%205.12943697,3.08011229%207.67955083,3%20C9.14881247,3.0528747%2010.4994783,3.57862053%2011.5656391,4.43436088%20Z'%20transform='matrix(-1%200%200%201%2017%205)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(18,0)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M11.5656391,4.43436088%20L9,7%20L16,7%20L16,0%20L13.0418424,2.95815758%20C11.5936787,1.73635959%209.72260775,1%207.67955083,1%20C4.22126258,1%201.25575599,3.10984908%200,6%20L2,7%20C2.93658775,4.60974406%205.12943697,3.08011229%207.67955083,3%20C9.14881247,3.0528747%2010.4994783,3.57862053%2011.5656391,4.43436088%20Z'%20transform='translate(1%205)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(36,0)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M13,14%20L3,14%20L3,11%20L0,11%20L0,6.00591905%20C0,4.89808055%200.894513756,4%201.99406028,4%20L14.0059397,4%20C15.1072288,4%2016,4.88655484%2016,6.00591905%20L16,11%20L13,11%20L13,14%20Z%20M5,9%20L11,9%20L11,12%20L5,12%20L5,9%20Z%20M3,0%20L13,0%20L13,3%20L3,3%20L3,0%20Z%20M12,6%20L14,6%20L14,8%20L12,8%20L12,6%20Z'%20transform='translate(1%202)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(54,0)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M9,0%20L1,0%20C0.45,0%200,0.45%200,1%20L0,4%20C0,4.55%200.45,5%201,5%20L9,5%20C9.55,5%2010,4.55%2010,4%20L10,3%20L11,3%20L11,6%20L4,6%20L4,14%20L6,14%20L6,8%20L13,8%20L13,2%20L10,2%20L10,1%20C10,0.45%209.55,0%209,0%20Z'%20transform='translate(3%202)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(72,0)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M0.27,1.55%20L5.43,6.7%20L3,12%20L5.5,12%20L7.14,8.42%20L11.73,13%20L13,11.73%20L1.55,0.27%20L0.27,1.55%20L0.27,1.55%20Z%20M3.82,0%20L5.82,2%20L7.58,2%20L7.03,3.21%20L8.74,4.92%20L10.08,2%20L14,2%20L14,0%20L3.82,0%20L3.82,0%20Z'%20transform='translate(2%203)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(90,0)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M9,3.5%20C9,1.57%207.43,0%205.5,0%20L1.77635684e-15,0%20L1.77635684e-15,12%20L6.25,12%20C8.04,12%209.5,10.54%209.5,8.75%20C9.5,7.45%208.73,6.34%207.63,5.82%20C8.46,5.24%209,4.38%209,3.5%20Z%20M5,2%20C5.82999992,2%206.5,2.67%206.5,3.5%20C6.5,4.33%205.82999992,5%205,5%20L3,5%20L3,2%20L5,2%20Z%20M3,10%20L3,7%20L5.5,7%20C6.32999992,7%207,7.67%207,8.5%20C7,9.33%206.32999992,10%205.5,10%20L3,10%20Z'%20transform='translate(4%203)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(108,0)'%3e%3cpolygon%20fill='%23000000'%20fill-rule='evenodd'%20points='4%200%204%202%206.58%202%202.92%2010%200%2010%200%2012%208%2012%208%2010%205.42%2010%209.08%202%2012%202%2012%200'%20transform='translate(3%203)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(126,0)'%3e%3cpath%20fill='%23000000'%20d='M6,12%20C8.76,12%2011,9.76%2011,7%20L11,0%20L9,0%20L9,7%20C9,8.75029916%207.49912807,10%206,10%20C4.50087193,10%203,8.75837486%203,7%20L3,0%20L1,0%20L1,7%20C1,9.76%203.24,12%206,12%20Z%20M0,13%20L0,15%20L12,15%20L12,13%20L0,13%20Z'%20transform='translate(3%203)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(144,0)'%3e%3cpath%20fill='%23010101'%20fill-rule='evenodd'%20d='M2.8875,3.06%20C2.8875,2.6025%202.985,2.18625%203.18375,1.8075%20C3.3825,1.42875%203.66,1.10625%204.02,0.84%20C4.38,0.57375%204.80375,0.3675%205.29875,0.22125%20C5.79375,0.075%206.33375,0%206.92625,0%20C7.53375,0%208.085,0.0825%208.58,0.25125%20C9.075,0.42%209.49875,0.6525%209.85125,0.95625%20C10.20375,1.25625%2010.47375,1.6125%2010.665,2.02875%20C10.85625,2.44125%2010.95,2.895%2010.95,3.38625%20L8.6925,3.38625%20C8.6925,3.1575%208.655,2.94375%208.58375,2.74875%20C8.5125,2.55%208.4,2.38125%208.25,2.2425%20C8.1,2.10375%207.9125,1.99125%207.6875,1.91625%20C7.4625,1.8375%207.19625,1.8%206.88875,1.8%20C6.5925,1.8%206.3375,1.83375%206.11625,1.8975%20C5.89875,1.96125%205.71875,2.05125%205.57625,2.1675%20C5.43375,2.28375%205.325,2.41875%205.25375,2.5725%20C5.1825,2.72625%205.145,2.895%205.145,3.0675%20C5.145,3.4275%205.32875,3.73125%205.69625,3.975%20C5.71780203,3.98908066%205.73942012,4.00311728%205.76118357,4.01733315%20C6.02342923,4.18863185%206.5,4.5%207,5%20L4,5%20C4,5%203.21375,4.37625%203.17625,4.30875%20C2.985,3.9525%202.8875,3.53625%202.8875,3.06%20Z%20M14,6%20L0,6%20L0,8%20L7.21875,8%20C7.35375,8.0525%207.51875,8.105%207.63125,8.15375%20C7.90875,8.2775%208.12625,8.40875%208.28375,8.53625%20C8.44125,8.6675%208.54625,8.81%208.6025,8.96%20C8.65875,9.11375%208.685,9.28625%208.685,9.47375%20C8.685,9.65%208.65125,9.815%208.58375,9.965%20C8.51625,10.11875%208.41125,10.25%208.2725,10.35875%20C8.13375,10.4675%207.95375,10.55375%207.74,10.6175%20C7.5225,10.68125%207.27125,10.71125%206.97875,10.71125%20C6.6525,10.71125%206.35625,10.6775%206.09,10.61375%20C5.82375,10.55%205.59875,10.445%205.41125,10.3025%20C5.22375,10.16%205.0775,9.9725%204.9725,9.74375%20C4.8675,9.515%204.78125,9.17%204.78125,9%20L2.55,9%20C2.55,9.2525%202.61,9.6875%202.72625,10.025%20C2.8425,10.3625%203.0075,10.66625%203.21375,10.9325%20C3.42,11.19875%203.6675,11.4275%203.94875,11.6225%20C4.23,11.8175%204.53375,11.9825%204.86375,12.11%20C5.19375,12.24125%205.535,12.33875%205.89875,12.39875%20C6.25875,12.4625%206.6225,12.4925%206.9825,12.4925%20C7.5825,12.4925%208.13,12.425%208.6175,12.28625%20C9.105,12.1475%209.525,11.94875%209.87,11.69375%20C10.215,11.435%2010.48125,11.12%2010.6725,10.74125%20C10.86375,10.3625%2010.95375,9.935%2010.95375,9.455%20C10.95375,9.005%2010.875,8.6%2010.72125,8.24375%20C10.68375,8.1575%2010.6425,8.075%2010.59375,7.9925%20L14,8%20L14,6%20Z'%20transform='translate(2%203)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(162,0)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M7,0%20L5,0%20L0.5,12%20L2.5,12%20L3.62,9%20L8.37,9%20L9.49,12%20L11.49,12%20L7,0%20L7,0%20Z%20M4.38,7%20L6,2.67%20L7.62,7%20L4.38,7%20L4.38,7%20Z'%20transform='translate(3%201)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(180,0)'%3e%3cg%20fill='none'%20fill-rule='evenodd'%3e%3cpath%20fill='%23000000'%20d='M14.5,8.87%20C14.5,8.87%2013,10.49%2013,11.49%20C13,12.32%2013.67,12.99%2014.5,12.99%20C15.33,12.99%2016,12.32%2016,11.49%20C16,10.5%2014.5,8.87%2014.5,8.87%20L14.5,8.87%20Z%20M12.71,6.79%20L5.91,0%20L4.85,1.06%20L6.44,2.65%20L2.29,6.79%20C1.9,7.18%201.9,7.81%202.29,8.2%20L6.79,12.7%20C6.99,12.9%207.24,13%207.5,13%20C7.76,13%208.01,12.9%208.21,12.71%20L12.71,8.21%20C13.1,7.82%2013.1,7.18%2012.71,6.79%20L12.71,6.79%20Z%20M4.21,7%20L7.5,3.71%20L10.79,7%20L4.21,7%20L4.21,7%20Z'/%3e%3c/g%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(198,0)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M3,6%20L1,6%20L1,2%20L8,2%20L8,4%20L3,4%20L3,6%20Z%20M10,4%20L10,2%20L17,2%20L17,6%20L15,6%20L15,4%20L10,4%20Z%20M10,14%20L15,14%20L15,12%20L17,12%20L17,16%20L10,16%20L10,14%20Z%20M1,12%20L3,12%20L3,14%20L8,14%20L8,16%20L1,16%20L1,12%20Z%20M1,8%20L5,8%20L5,6%20L8,9%20L5,12%20L5,10%20L1,10%20L1,8%20Z%20M10,9%20L13,6%20L13,8%20L17,8%20L17,10%20L13,10%20L13,12%20L10,9%20Z'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(216,0)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M0,14%20L10,14%20L10,12%20L0,12%20L0,14%20Z%20M10,4%20L0,4%20L0,6%20L10,6%20L10,4%20Z%20M0,0%20L0,2%20L14,2%20L14,0%20L0,0%20Z%20M0,10%20L14,10%20L14,8%20L0,8%20L0,10%20Z'%20transform='translate(2%202)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(234,0)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M2,12%20L2,14%20L12,14%20L12,12%20L2,12%20Z%20M2,4%20L2,6%20L12,6%20L12,4%20L2,4%20Z%20M0,10%20L14,10%20L14,8%20L0,8%20L0,10%20Z%20M0,0%20L0,2%20L14,2%20L14,0%20L0,0%20Z'%20transform='translate(2%202)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(0,18)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M4,14%20L14,14%20L14,12%20L4,12%20L4,14%20Z%20M0,10%20L14,10%20L14,8%20L0,8%20L0,10%20Z%20M0,0%20L0,2%20L14,2%20L14,0%20L0,0%20Z%20M4,6%20L14,6%20L14,4%20L4,4%20L4,6%20Z'%20transform='translate(2%202)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(18,18)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M0,0%20L0,2%20L12,2%20L12,0%20L0,0%20L0,0%20Z%20M2.5,7%20L5,7%20L5,14%20L7,14%20L7,7%20L9.5,7%20L6,3.5%20L2.5,7%20L2.5,7%20Z'%20transform='translate(3%202)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(36,18)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M9.5,3%20L7,3%20L7,0%20L5,0%20L5,3%20L2.5,3%20L6,6.5%20L9.5,3%20L9.5,3%20Z%20M0,8%20L0,10%20L12,10%20L12,8%20L0,8%20L0,8%20Z%20M2.5,15%20L5,15%20L5,18%20L7,18%20L7,15%20L9.5,15%20L6,11.5%20L2.5,15%20L2.5,15%20Z'%20transform='translate(3)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(54,18)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M9.5,7%20L7,7%20L7,0%20L5,0%20L5,7%20L2.5,7%20L6,10.5%20L9.5,7%20L9.5,7%20Z%20M0,12%20L0,14%20L12,14%20L12,12%20L0,12%20L0,12%20Z'%20transform='translate(3%202)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(72,18)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M14,0%20L0,0%20L0,2%20L14,2%20L14,0%20Z%20M0,12%20L4,12%20L4,10%20L0,10%20L0,12%20Z%20M11.5,5%20L0,5%20L0,7%20L11.75,7%20C12.58,7%2013.25,7.67%2013.25,8.5%20C13.25,9.33%2012.58,10%2011.75,10%20L9,10%20L9,8%20L6,11%20L9,14%20L9,12%20L11.5,12%20C13.43,12%2015,10.43%2015,8.5%20C15,6.57%2013.43,5%2011.5,5%20Z'%20transform='translate(2%203)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(90,18)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M0,0%20L0,1%20L6,7%20L6,12%20L8,11%20L8,7%20L14,1%20L14,0%20L0,0%20Z%20M4,3%20L10,3%20L7,6%20L4,3%20Z'%20transform='translate(2%203)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(108,18)'%3e%3cpolygon%20fill='%23000000'%20fill-rule='evenodd'%20points='10%200%200%200%200%201.8%205.5%207%200%2012.2%200%2014%2010%2014%2010%2012%203.1%2012%208%207%203.1%202%2010%202'%20transform='translate(4%202)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(126,18)'%3e%3cpolygon%20fill='%23000000'%20fill-rule='evenodd'%20points='0%200%204%204%208%200'%20transform='translate(5%207)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(144,18)'%3e%3cpolygon%20fill='%23000000'%20fill-rule='evenodd'%20points='-2%202%202%206%206%202'%20transform='rotate(-90%208%203)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(162,18)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M1.9,4%20C1.9,2.84%202.84,1.9%204,1.9%20L8,1.9%20L8,0%20L4,0%20C1.79,0%200,1.79%200,4%20C0,6.21%201.79,8%204,8%20L8,8%20L8,6.1%20L4,6.1%20C2.84,6.1%201.9,5.16%201.9,4%20L1.9,4%20Z%20M14,0%20L10,0%20L10,1.9%20L14,1.9%20C15.16,1.9%2016.1,2.84%2016.1,4%20C16.1,5.16%2015.16,6.1%2014,6.1%20L10,6.1%20L10,8%20L14,8%20C16.21,8%2018,6.21%2018,4%20C18,1.79%2016.21,0%2014,0%20L14,0%20Z%20M6,5%20L12,5%20L12,3%20L6,3%20L6,5%20L6,5%20Z'%20transform='translate(0%205)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(180,18)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M15,0%20C15.55,0%2016,0.45%2016,1%20L16,15%20C16,15.55%2015.55,16%2015,16%20L1,16%20C0.45,16%200,15.55%200,15%20L0,1%20C0,0.45%200.45,0%201,0%20L15,0%20Z%20M2,2%20L2,14%20L14,14%20L14,2%20L2,2%20Z%20M6,12%20L4,12%20L4,7%20L6,7%20L6,12%20L6,12%20Z%20M9,12%20L7,12%20L7,4%20L9,4%20L9,12%20L9,12%20Z%20M12,12%20L10,12%20L10,8%20L12,8%20L12,12%20L12,12%20Z'%20transform='translate(1%201)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(198,18)'%3e%3cg%20fill='none'%20fill-rule='evenodd'%3e%3cpath%20stroke='%23000000'%20d='M1.5%203.5H16.5V15.5H1.5z'/%3e%3cpath%20fill='%23000000'%20d='M6%208H7V15H6z'/%3e%3cpath%20fill='%23D8D8D8'%20d='M2%204H16V7H2z'/%3e%3cpath%20fill='%23000000'%20d='M2%207H16V8H2zM2%2011H16V12H2z'/%3e%3c/g%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(216,18)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M2,0.5%20C1.17,0.5%200.5,1.17%200.5,2%20C0.5,2.83%201.17,3.5%202,3.5%20C2.83,3.5%203.5,2.83%203.5,2%20C3.5,1.17%202.83,0.5%202,0.5%20L2,0.5%20Z%20M12,0.5%20C11.17,0.5%2010.5,1.17%2010.5,2%20C10.5,2.83%2011.17,3.5%2012,3.5%20C12.83,3.5%2013.5,2.83%2013.5,2%20C13.5,1.17%2012.83,0.5%2012,0.5%20L12,0.5%20Z%20M7,0.5%20C6.17,0.5%205.5,1.17%205.5,2%20C5.5,2.83%206.17,3.5%207,3.5%20C7.83,3.5%208.5,2.83%208.5,2%20C8.5,1.17%207.83,0.5%207,0.5%20L7,0.5%20Z'%20transform='translate(2%207)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(234,18)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M6,4%20L6,0%20L4,0%20L4,4%20L0,4%20L0,6%20L4,6%20L4,10%20L6,10%20L6,6%20L10,6%20L10,4%20L6,4%20Z'%20transform='translate(4%204)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(0,36)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M0,0%20L0,14%20L14,14%20L14,0%20L0,0%20L0,0%20Z%20M6,12%20L2,12%20L2,8%20L6,8%20L6,12%20L6,12%20Z%20M6,6%20L2,6%20L2,2%20L6,2%20L6,6%20L6,6%20Z%20M12,12%20L8,12%20L8,8%20L12,8%20L12,12%20L12,12%20Z%20M12,6%20L8,6%20L8,2%20L12,2%20L12,6%20L12,6%20Z'%20transform='translate(2%202)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(18,36)'%3e%3cg%20fill='%23000000'%20fill-rule='evenodd'%20transform='translate(2%202)'%3e%3cpath%20d='M0,14%20L2,14%20L2,12%20L0,12%20L0,14%20L0,14%20Z%20M2,3%20L0,3%20L0,5%20L2,5%20L2,3%20L2,3%20Z%20M3,14%20L5,14%20L5,12%20L3,12%20L3,14%20L3,14%20Z%20M11,0%20L9,0%20L9,2%20L11,2%20L11,0%20L11,0%20Z%20M2,0%20L0,0%20L0,2%20L2,2%20L2,0%20L2,0%20Z%20M5,0%20L3,0%20L3,2%20L5,2%20L5,0%20L5,0%20Z%20M0,11%20L2,11%20L2,9%20L0,9%20L0,11%20L0,11%20Z%20M9,14%20L11,14%20L11,12%20L9,12%20L9,14%20L9,14%20Z%20M12,0%20L12,2%20L14,2%20L14,0%20L12,0%20L12,0%20Z%20M12,5%20L14,5%20L14,3%20L12,3%20L12,5%20L12,5%20Z%20M12,14%20L14,14%20L14,12%20L12,12%20L12,14%20L12,14%20Z%20M12,11%20L14,11%20L14,9%20L12,9%20L12,11%20L12,11%20Z'%20opacity='.54'/%3e%3cpolygon%20points='8%200%206%200%206%206%200%206%200%208%206%208%206%2014%208%2014%208%208%2014%208%2014%206%208%206'/%3e%3c/g%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(36,36)'%3e%3cg%20fill='%23000000'%20fill-rule='evenodd'%20transform='translate(2%202)'%3e%3cpath%20d='M6,14%20L8,14%20L8,12%20L6,12%20L6,14%20L6,14%20Z%20M3,2%20L5,2%20L5,0%20L3,0%20L3,2%20L3,2%20Z%20M6,11%20L8,11%20L8,9%20L6,9%20L6,11%20L6,11%20Z%20M3,14%20L5,14%20L5,12%20L3,12%20L3,14%20L3,14%20Z%20M0,5%20L2,5%20L2,3%20L0,3%20L0,5%20L0,5%20Z%20M0,14%20L2,14%20L2,12%20L0,12%20L0,14%20L0,14%20Z%20M0,2%20L2,2%20L2,0%20L0,0%20L0,2%20L0,2%20Z%20M0,11%20L2,11%20L2,9%20L0,9%20L0,11%20L0,11%20Z%20M12,11%20L14,11%20L14,9%20L12,9%20L12,11%20L12,11%20Z%20M12,14%20L14,14%20L14,12%20L12,12%20L12,14%20L12,14%20Z%20M12,5%20L14,5%20L14,3%20L12,3%20L12,5%20L12,5%20Z%20M12,0%20L12,2%20L14,2%20L14,0%20L12,0%20L12,0%20Z%20M6,2%20L8,2%20L8,0%20L6,0%20L6,2%20L6,2%20Z%20M9,2%20L11,2%20L11,0%20L9,0%20L9,2%20L9,2%20Z%20M6,5%20L8,5%20L8,3%20L6,3%20L6,5%20L6,5%20Z%20M9,14%20L11,14%20L11,12%20L9,12%20L9,14%20L9,14%20Z'%20opacity='.54'/%3e%3cpolygon%20points='0%208%2014%208%2014%206%200%206'/%3e%3c/g%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(54,36)'%3e%3cg%20fill='%23000000'%20fill-rule='evenodd'%20transform='translate(2%202)'%3e%3cpath%20d='M3,14%20L5,14%20L5,12%20L3,12%20L3,14%20L3,14%20Z%20M0,5%20L2,5%20L2,3%20L0,3%20L0,5%20L0,5%20Z%20M0,2%20L2,2%20L2,0%20L0,0%20L0,2%20L0,2%20Z%20M3,8%20L5,8%20L5,6%20L3,6%20L3,8%20L3,8%20Z%20M3,2%20L5,2%20L5,0%20L3,0%20L3,2%20L3,2%20Z%20M0,14%20L2,14%20L2,12%20L0,12%20L0,14%20L0,14%20Z%20M0,8%20L2,8%20L2,6%20L0,6%20L0,8%20L0,8%20Z%20M0,11%20L2,11%20L2,9%20L0,9%20L0,11%20L0,11%20Z%20M12,0%20L12,2%20L14,2%20L14,0%20L12,0%20L12,0%20Z%20M12,8%20L14,8%20L14,6%20L12,6%20L12,8%20L12,8%20Z%20M12,14%20L14,14%20L14,12%20L12,12%20L12,14%20L12,14%20Z%20M12,5%20L14,5%20L14,3%20L12,3%20L12,5%20L12,5%20Z%20M12,11%20L14,11%20L14,9%20L12,9%20L12,11%20L12,11%20Z%20M9,14%20L11,14%20L11,12%20L9,12%20L9,14%20L9,14%20Z%20M9,8%20L11,8%20L11,6%20L9,6%20L9,8%20L9,8%20Z%20M9,2%20L11,2%20L11,0%20L9,0%20L9,2%20L9,2%20Z'%20opacity='.54'/%3e%3cpolygon%20points='6%2014%208%2014%208%200%206%200'/%3e%3c/g%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(72,36)'%3e%3cg%20fill='%23000000'%20fill-rule='evenodd'%20transform='translate(2%202)'%3e%3cpath%20d='M8,3%20L6,3%20L6,5%20L8,5%20L8,3%20L8,3%20Z%20M11,6%20L9,6%20L9,8%20L11,8%20L11,6%20L11,6%20Z%20M8,6%20L6,6%20L6,8%20L8,8%20L8,6%20L8,6%20Z%20M8,9%20L6,9%20L6,11%20L8,11%20L8,9%20L8,9%20Z%20M5,6%20L3,6%20L3,8%20L5,8%20L5,6%20L5,6%20Z'%20opacity='.54'/%3e%3cpath%20d='M0,0%20L14,0%20L14,14%20L0,14%20L0,0%20Z%20M12,12%20L12,2%20L2,2%20L2,12%20L12,12%20Z'/%3e%3c/g%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(90,36)'%3e%3cg%20fill='%23000000'%20fill-rule='evenodd'%20transform='translate(2%202)'%3e%3cpath%20d='M6,8%20L8,8%20L8,6%20L6,6%20L6,8%20L6,8%20Z%20M6,5%20L8,5%20L8,3%20L6,3%20L6,5%20L6,5%20Z%20M6,11%20L8,11%20L8,9%20L6,9%20L6,11%20L6,11%20Z%20M6,14%20L8,14%20L8,12%20L6,12%20L6,14%20L6,14%20Z%20M3,14%20L5,14%20L5,12%20L3,12%20L3,14%20L3,14%20Z%20M3,2%20L5,2%20L5,0%20L3,0%20L3,2%20L3,2%20Z%20M3,8%20L5,8%20L5,6%20L3,6%20L3,8%20L3,8%20Z%20M12,14%20L14,14%20L14,12%20L12,12%20L12,14%20L12,14%20Z%20M12,8%20L14,8%20L14,6%20L12,6%20L12,8%20L12,8%20Z%20M12,11%20L14,11%20L14,9%20L12,9%20L12,11%20L12,11%20Z%20M12,5%20L14,5%20L14,3%20L12,3%20L12,5%20L12,5%20Z%20M6,2%20L8,2%20L8,0%20L6,0%20L6,2%20L6,2%20Z%20M12,0%20L12,2%20L14,2%20L14,0%20L12,0%20L12,0%20Z%20M9,14%20L11,14%20L11,12%20L9,12%20L9,14%20L9,14%20Z%20M9,8%20L11,8%20L11,6%20L9,6%20L9,8%20L9,8%20Z%20M9,2%20L11,2%20L11,0%20L9,0%20L9,2%20L9,2%20Z'%20opacity='.54'/%3e%3cpolygon%20points='0%2014%202%2014%202%200%200%200'/%3e%3c/g%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(108,36)'%3e%3cg%20fill='%23000000'%20fill-rule='evenodd'%20transform='translate(2%202)'%3e%3cpath%20d='M3,8%20L5,8%20L5,6%20L3,6%20L3,8%20L3,8%20Z%20M0,14%20L2,14%20L2,12%20L0,12%20L0,14%20L0,14%20Z%20M6,14%20L8,14%20L8,12%20L6,12%20L6,14%20L6,14%20Z%20M6,11%20L8,11%20L8,9%20L6,9%20L6,11%20L6,11%20Z%20M3,14%20L5,14%20L5,12%20L3,12%20L3,14%20L3,14%20Z%20M0,11%20L2,11%20L2,9%20L0,9%20L0,11%20L0,11%20Z%20M6,8%20L8,8%20L8,6%20L6,6%20L6,8%20L6,8%20Z%20M0,5%20L2,5%20L2,3%20L0,3%20L0,5%20L0,5%20Z%20M0,8%20L2,8%20L2,6%20L0,6%20L0,8%20L0,8%20Z%20M12,8%20L14,8%20L14,6%20L12,6%20L12,8%20L12,8%20Z%20M12,11%20L14,11%20L14,9%20L12,9%20L12,11%20L12,11%20Z%20M12,5%20L14,5%20L14,3%20L12,3%20L12,5%20L12,5%20Z%20M6,5%20L8,5%20L8,3%20L6,3%20L6,5%20L6,5%20Z%20M9,14%20L11,14%20L11,12%20L9,12%20L9,14%20L9,14%20Z%20M9,8%20L11,8%20L11,6%20L9,6%20L9,8%20L9,8%20Z%20M12,14%20L14,14%20L14,12%20L12,12%20L12,14%20L12,14%20Z'%20opacity='.54'/%3e%3cpolygon%20points='0%200%200%202%2014%202%2014%200'/%3e%3c/g%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(126,36)'%3e%3cg%20fill='%23000000'%20fill-rule='evenodd'%20transform='translate(2%202)'%3e%3cpath%20d='M0,2%20L2,2%20L2,0%20L0,0%20L0,2%20L0,2%20Z%20M3,2%20L5,2%20L5,0%20L3,0%20L3,2%20L3,2%20Z%20M3,8%20L5,8%20L5,6%20L3,6%20L3,8%20L3,8%20Z%20M3,14%20L5,14%20L5,12%20L3,12%20L3,14%20L3,14%20Z%20M0,5%20L2,5%20L2,3%20L0,3%20L0,5%20L0,5%20Z%20M0,8%20L2,8%20L2,6%20L0,6%20L0,8%20L0,8%20Z%20M0,14%20L2,14%20L2,12%20L0,12%20L0,14%20L0,14%20Z%20M0,11%20L2,11%20L2,9%20L0,9%20L0,11%20L0,11%20Z%20M9,8%20L11,8%20L11,6%20L9,6%20L9,8%20L9,8%20Z%20M6,14%20L8,14%20L8,12%20L6,12%20L6,14%20L6,14%20Z%20M9,14%20L11,14%20L11,12%20L9,12%20L9,14%20L9,14%20Z%20M6,2%20L8,2%20L8,0%20L6,0%20L6,2%20L6,2%20Z%20M9,2%20L11,2%20L11,0%20L9,0%20L9,2%20L9,2%20Z%20M6,11%20L8,11%20L8,9%20L6,9%20L6,11%20L6,11%20Z%20M6,5%20L8,5%20L8,3%20L6,3%20L6,5%20L6,5%20Z%20M6,8%20L8,8%20L8,6%20L6,6%20L6,8%20L6,8%20Z'%20opacity='.54'/%3e%3cpolygon%20points='12%200%2012%2014%2014%2014%2014%200'/%3e%3c/g%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(144,36)'%3e%3cg%20fill='%23000000'%20fill-rule='evenodd'%20transform='translate(2%202)'%3e%3cpath%20d='M5,0%20L3,0%20L3,2%20L5,2%20L5,0%20L5,0%20Z%20M8,6%20L6,6%20L6,8%20L8,8%20L8,6%20L8,6%20Z%20M8,9%20L6,9%20L6,11%20L8,11%20L8,9%20L8,9%20Z%20M11,6%20L9,6%20L9,8%20L11,8%20L11,6%20L11,6%20Z%20M5,6%20L3,6%20L3,8%20L5,8%20L5,6%20L5,6%20Z%20M11,0%20L9,0%20L9,2%20L11,2%20L11,0%20L11,0%20Z%20M8,3%20L6,3%20L6,5%20L8,5%20L8,3%20L8,3%20Z%20M8,0%20L6,0%20L6,2%20L8,2%20L8,0%20L8,0%20Z%20M2,9%20L0,9%20L0,11%20L2,11%20L2,9%20L2,9%20Z%20M12,11%20L14,11%20L14,9%20L12,9%20L12,11%20L12,11%20Z%20M12,5%20L14,5%20L14,3%20L12,3%20L12,5%20L12,5%20Z%20M12,8%20L14,8%20L14,6%20L12,6%20L12,8%20L12,8%20Z%20M12,0%20L12,2%20L14,2%20L14,0%20L12,0%20L12,0%20Z%20M2,0%20L0,0%20L0,2%20L2,2%20L2,0%20L2,0%20Z%20M2,3%20L0,3%20L0,5%20L2,5%20L2,3%20L2,3%20Z%20M2,6%20L0,6%20L0,8%20L2,8%20L2,6%20L2,6%20Z'%20opacity='.54'/%3e%3cpolygon%20points='0%2014%2014%2014%2014%2012%200%2012'/%3e%3c/g%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(162,36)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M6,14%20L8,14%20L8,12%20L6,12%20L6,14%20L6,14%20Z%20M3,8%20L5,8%20L5,6%20L3,6%20L3,8%20L3,8%20Z%20M3,2%20L5,2%20L5,0%20L3,0%20L3,2%20L3,2%20Z%20M6,11%20L8,11%20L8,9%20L6,9%20L6,11%20L6,11%20Z%20M3,14%20L5,14%20L5,12%20L3,12%20L3,14%20L3,14%20Z%20M0,5%20L2,5%20L2,3%20L0,3%20L0,5%20L0,5%20Z%20M0,14%20L2,14%20L2,12%20L0,12%20L0,14%20L0,14%20Z%20M0,2%20L2,2%20L2,0%20L0,0%20L0,2%20L0,2%20Z%20M0,8%20L2,8%20L2,6%20L0,6%20L0,8%20L0,8%20Z%20M6,8%20L8,8%20L8,6%20L6,6%20L6,8%20L6,8%20Z%20M0,11%20L2,11%20L2,9%20L0,9%20L0,11%20L0,11%20Z%20M12,11%20L14,11%20L14,9%20L12,9%20L12,11%20L12,11%20Z%20M12,14%20L14,14%20L14,12%20L12,12%20L12,14%20L12,14%20Z%20M12,8%20L14,8%20L14,6%20L12,6%20L12,8%20L12,8%20Z%20M12,5%20L14,5%20L14,3%20L12,3%20L12,5%20L12,5%20Z%20M12,0%20L12,2%20L14,2%20L14,0%20L12,0%20L12,0%20Z%20M6,2%20L8,2%20L8,0%20L6,0%20L6,2%20L6,2%20Z%20M9,2%20L11,2%20L11,0%20L9,0%20L9,2%20L9,2%20Z%20M6,5%20L8,5%20L8,3%20L6,3%20L6,5%20L6,5%20Z%20M9,14%20L11,14%20L11,12%20L9,12%20L9,14%20L9,14%20Z%20M9,8%20L11,8%20L11,6%20L9,6%20L9,8%20L9,8%20Z'%20transform='translate(2%202)'%20opacity='.54'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(180,36)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M6.5,3.62%20L0,10.12%20L0,13%20L2.88,13%20L9.38,6.5%20L6.5,3.62%20Z%20M11.85,4.02%20C12.05,3.82%2012.05,3.51%2011.85,3.31%20L9.68,1.14%20C9.48,0.94%209.17,0.94%208.97,1.14%20L7.62,2.5%20L10.5,5.38%20L11.85,4.02%20L11.85,4.02%20Z'%20transform='translate(4)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(198,36)'%3e%3cpath%20fill='%23000000'%20fill-rule='evenodd'%20d='M0,0%20L14,0%20L14,2%20L0,2%20L0,0%20Z%20M0,4%20L6,4%20L6,6%20L0,6%20L0,4%20Z%20M0,8%20L2,8%20L2,10%20L0,10%20L0,8%20Z%20M8,4%20L14,4%20L14,6%20L8,6%20L8,4%20Z%20M4,8%20L6,8%20L6,10%20L4,10%20L4,8%20Z%20M8,8%20L10,8%20L10,10%20L8,10%20L8,8%20Z%20M12,8%20L14,8%20L14,10%20L12,10%20L12,8%20Z'%20transform='translate(2%204)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(216,36)'%3e%3cpolygon%20fill='%23000000'%20fill-rule='evenodd'%20points='-2%202%202%206%206%202'%20transform='rotate(90%203%2010)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(234,36)'%3e%3cpolygon%20fill='%23000000'%20fill-rule='evenodd'%20points='7.53%201.53%206.47%20.47%204%202.94%201.53%20.47%20.47%201.53%202.94%204%20.47%206.47%201.53%207.53%204%205.06%206.47%207.53%207.53%206.47%205.06%204'%20transform='translate(5%205)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(0,54)'%3e%3cpolygon%20fill='%23000000'%20fill-rule='evenodd'%20points='8.44%20.44%205%203.88%201.56%20.44%20.5%201.5%205%206%209.5%201.5'%20transform='translate(4%206)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(18,54)'%3e%3cpolygon%20fill='%23000000'%20fill-rule='evenodd'%20points='5%200%20.5%204.5%201.56%205.56%205%202.12%208.44%205.56%209.5%204.5'%20transform='translate(4%206)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(36,54)'%3e%3cpolygon%20fill='%23000000'%20fill-rule='evenodd'%20points='8.44%20.44%205%203.88%201.56%20.44%20.5%201.5%205%206%209.5%201.5'%20transform='rotate(90%204%208)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(54,54)'%3e%3cpolygon%20fill='%23000000'%20fill-rule='evenodd'%20points='5%200%20.5%204.5%201.56%205.56%205%202.12%208.44%205.56%209.5%204.5'%20transform='rotate(90%204%208)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(72,54)'%3e%3cpolygon%20fill='%23000000'%20fill-rule='evenodd'%20points='12%205%203.125%205%207.06%201.06%206%200%200%206%206%2012%207.06%2010.94%203.125%207%2012%207'%20transform='matrix(-1%200%200%201%2015%203)'/%3e%3c/g%3e%3cg%20xmlns='http://www.w3.org/2000/svg'%20transform='translate(90,54)'%3e%3cpolygon%20fill='%23000000'%20fill-rule='evenodd'%20points='12%205%203.125%205%207.06%201.06%206%200%200%206%206%2012%207.06%2010.94%203.125%207%2012%207'%20transform='translate(3%203)'/%3e%3c/g%3e%3c/svg%3e");position:absolute;width:262px;height:444px;opacity:.56}.x-spreadsheet-icon .x-spreadsheet-icon-img.undo{left:0;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.redo{left:-18px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.print{left:-36px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.paintformat{left:-54px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.clearformat{left:-72px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.font-bold{left:-90px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.font-italic{left:-108px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.underline{left:-126px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.strike{left:-144px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.color{left:-162px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.bgcolor{left:-180px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.merge{left:-198px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.align-left{left:-216px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.align-center{left:-234px;top:0}.x-spreadsheet-icon .x-spreadsheet-icon-img.align-right{left:0;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.align-top{left:-18px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.align-middle{left:-36px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.align-bottom{left:-54px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.textwrap{left:-72px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.autofilter{left:-90px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.formula{left:-108px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.arrow-down{left:-126px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.arrow-right{left:-144px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.link{left:-162px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.chart{left:-180px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.freeze{left:-198px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.ellipsis{left:-216px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.add{left:-234px;top:-18px}.x-spreadsheet-icon .x-spreadsheet-icon-img.border-all{left:0;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.border-inside{left:-18px;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.border-horizontal{left:-36px;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.border-vertical{left:-54px;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.border-outside{left:-72px;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.border-left{left:-90px;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.border-top{left:-108px;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.border-right{left:-126px;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.border-bottom{left:-144px;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.border-none{left:-162px;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.line-color{left:-180px;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.line-type{left:-198px;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.close{left:-234px;top:-36px}.x-spreadsheet-icon .x-spreadsheet-icon-img.chevron-down{left:0;top:-54px}.x-spreadsheet-icon .x-spreadsheet-icon-img.chevron-up{left:-18px;top:-54px}.x-spreadsheet-icon .x-spreadsheet-icon-img.chevron-left{left:-36px;top:-54px}.x-spreadsheet-icon .x-spreadsheet-icon-img.chevron-right{left:-54px;top:-54px} diff --git a/assets/tiktik_video_demo.mxxBzLay.webp b/assets/tiktik_video_demo.mxxBzLay.webp new file mode 100644 index 0000000000..b9ce833bdb Binary files /dev/null and b/assets/tiktik_video_demo.mxxBzLay.webp differ diff --git a/assets/tiktok_video.DuwKyIdt.webp b/assets/tiktok_video.DuwKyIdt.webp new file mode 100644 index 0000000000..3686c0da76 Binary files /dev/null and b/assets/tiktok_video.DuwKyIdt.webp differ diff --git a/assets/ts_demo.D_l_mv9k.webp b/assets/ts_demo.D_l_mv9k.webp new file mode 100644 index 0000000000..f895430e47 Binary files /dev/null and b/assets/ts_demo.D_l_mv9k.webp differ diff --git a/assets/video_format.CRMCTmKB.webp b/assets/video_format.CRMCTmKB.webp new file mode 100644 index 0000000000..2d6a4a7430 Binary files /dev/null and b/assets/video_format.CRMCTmKB.webp differ diff --git a/assets/wps_office.DiET-U8x.webp b/assets/wps_office.DiET-U8x.webp new file mode 100644 index 0000000000..dae2ee8489 Binary files /dev/null and b/assets/wps_office.DiET-U8x.webp differ diff --git a/assets/wps_office_price.ler9htjh.webp b/assets/wps_office_price.ler9htjh.webp new file mode 100644 index 0000000000..58bc565c1b Binary files /dev/null and b/assets/wps_office_price.ler9htjh.webp differ diff --git a/assets/xdoc.CeowcMPq.webp b/assets/xdoc.CeowcMPq.webp new file mode 100644 index 0000000000..495397f25e Binary files /dev/null and b/assets/xdoc.CeowcMPq.webp differ diff --git a/assets/xgplayer_docs.CpHb1Wan.webp b/assets/xgplayer_docs.CpHb1Wan.webp new file mode 100644 index 0000000000..3fc242eb98 Binary files /dev/null and b/assets/xgplayer_docs.CpHb1Wan.webp differ diff --git a/assets/xml.NyzOyhr4.webp b/assets/xml.NyzOyhr4.webp new file mode 100644 index 0000000000..d19c5f5e88 Binary files /dev/null and b/assets/xml.NyzOyhr4.webp differ diff --git "a/assets/\344\272\253\345\205\203.EIifVVTy.png" "b/assets/\344\272\253\345\205\203.EIifVVTy.png" new file mode 100644 index 0000000000..93eb5e54f5 Binary files /dev/null and "b/assets/\344\272\253\345\205\203.EIifVVTy.png" differ diff --git "a/assets/\345\215\225\344\276\213.B4dKFqxx.jpg" "b/assets/\345\215\225\344\276\213.B4dKFqxx.jpg" new file mode 100644 index 0000000000..89f3fc0aac Binary files /dev/null and "b/assets/\345\215\225\344\276\213.B4dKFqxx.jpg" differ diff --git "a/assets/\345\216\237\345\236\213.DYbH0CSA.jpg" "b/assets/\345\216\237\345\236\213.DYbH0CSA.jpg" new file mode 100644 index 0000000000..75eba17001 Binary files /dev/null and "b/assets/\345\216\237\345\236\213.DYbH0CSA.jpg" differ diff --git "a/assets/\345\244\207\345\277\230\345\275\225.meL0YZxn.jpg" "b/assets/\345\244\207\345\277\230\345\275\225.meL0YZxn.jpg" new file mode 100644 index 0000000000..1725438a52 Binary files /dev/null and "b/assets/\345\244\207\345\277\230\345\275\225.meL0YZxn.jpg" differ diff --git "a/assets/\345\244\226\350\247\202.Cm0-J0eF.png" "b/assets/\345\244\226\350\247\202.Cm0-J0eF.png" new file mode 100644 index 0000000000..fa55be42a5 Binary files /dev/null and "b/assets/\345\244\226\350\247\202.Cm0-J0eF.png" differ diff --git "a/assets/\345\273\272\351\200\240\350\200\205.B6neb_7R.jpeg" "b/assets/\345\273\272\351\200\240\350\200\205.B6neb_7R.jpeg" new file mode 100644 index 0000000000..ec569e213f Binary files /dev/null and "b/assets/\345\273\272\351\200\240\350\200\205.B6neb_7R.jpeg" differ diff --git "a/assets/\346\212\275\350\261\241\345\267\245\345\216\202.DlwNEriZ.png" "b/assets/\346\212\275\350\261\241\345\267\245\345\216\202.DlwNEriZ.png" new file mode 100644 index 0000000000..40eeffb724 Binary files /dev/null and "b/assets/\346\212\275\350\261\241\345\267\245\345\216\202.DlwNEriZ.png" differ diff --git "a/assets/\346\241\245\346\216\245.DX0mO5JC.png" "b/assets/\346\241\245\346\216\245.DX0mO5JC.png" new file mode 100644 index 0000000000..8292ae2656 Binary files /dev/null and "b/assets/\346\241\245\346\216\245.DX0mO5JC.png" differ diff --git "a/assets/\347\212\266\346\200\201.Bt_a2OKX.png" "b/assets/\347\212\266\346\200\201.Bt_a2OKX.png" new file mode 100644 index 0000000000..7c40301cf9 Binary files /dev/null and "b/assets/\347\212\266\346\200\201.Bt_a2OKX.png" differ diff --git "a/assets/\347\255\226\347\225\245.BAijEgGz.png" "b/assets/\347\255\226\347\225\245.BAijEgGz.png" new file mode 100644 index 0000000000..9365092fe4 Binary files /dev/null and "b/assets/\347\255\226\347\225\245.BAijEgGz.png" differ diff --git "a/assets/\347\273\204\345\220\210.StqZ1pDc.png" "b/assets/\347\273\204\345\220\210.StqZ1pDc.png" new file mode 100644 index 0000000000..86d39f54b1 Binary files /dev/null and "b/assets/\347\273\204\345\220\210.StqZ1pDc.png" differ diff --git "a/assets/\347\273\247\346\211\277.Dta6_xdc.png" "b/assets/\347\273\247\346\211\277.Dta6_xdc.png" new file mode 100644 index 0000000000..850c4f0621 Binary files /dev/null and "b/assets/\347\273\247\346\211\277.Dta6_xdc.png" differ diff --git "a/assets/\350\243\205\351\245\260.CuuWN9YK.jpg" "b/assets/\350\243\205\351\245\260.CuuWN9YK.jpg" new file mode 100644 index 0000000000..b492370be9 Binary files /dev/null and "b/assets/\350\243\205\351\245\260.CuuWN9YK.jpg" differ diff --git "a/assets/\350\247\243\351\207\212\345\231\250.DymUKGTa.jpg" "b/assets/\350\247\243\351\207\212\345\231\250.DymUKGTa.jpg" new file mode 100644 index 0000000000..2f057d2cf0 Binary files /dev/null and "b/assets/\350\247\243\351\207\212\345\231\250.DymUKGTa.jpg" differ diff --git "a/assets/\350\256\277\351\227\256\350\200\205.aEI4m-5a.png" "b/assets/\350\256\277\351\227\256\350\200\205.aEI4m-5a.png" new file mode 100644 index 0000000000..3e51211ee9 Binary files /dev/null and "b/assets/\350\256\277\351\227\256\350\200\205.aEI4m-5a.png" differ diff --git "a/assets/\351\200\202\351\205\215\345\231\250.C2VH4lXy.png" "b/assets/\351\200\202\351\205\215\345\231\250.C2VH4lXy.png" new file mode 100644 index 0000000000..37fa5f9270 Binary files /dev/null and "b/assets/\351\200\202\351\205\215\345\231\250.C2VH4lXy.png" differ diff --git a/cn/index.html b/cn/index.html new file mode 100644 index 0000000000..b9e8c4eee0 --- /dev/null +++ b/cn/index.html @@ -0,0 +1,49 @@ + + + + + + Home | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

ran

风起于青萍之末

A ship in harbor is safe, but that is not what ships are built for.

logo

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/astParse/tokenizer.html b/cn/src/article/astParse/tokenizer.html new file mode 100644 index 0000000000..cfe995e641 --- /dev/null +++ b/cn/src/article/astParse/tokenizer.html @@ -0,0 +1,233 @@ + + + + + + Abstract Syntax Tree | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Abstract Syntax Tree

一.(abstract syntax tree)抽象语法树的作用

源码是一串按照语法格式来组织的字符串,人能够认识,但是计算机并不认识,想让计算机认识就要转成一种数据结构,通过不同的对象来保存不同的数据,并且按照依赖关系组织起来,这种数据结构就是抽象语法树(abstract syntax tree)。

之所以叫“抽象”语法树是因为数据结构中省略掉了一些无具体意义的分隔符比如 ; { } 等。

有了 AST,计算机就能理解源码字符串的意思,而理解是能够转换的前提,所以编译的第一步需要把源码 parseAST

转成 AST 之后就可以通过修改 AST ,分析 AST 的方式来修改和分析代码,比如 babel 就通过这种方式进行代码的转换,比如 rollupTree Shaking ,就是通过分析 AST的 导入导出语法,从而分析出没有使用的代码,进行去除。

二。常见的 AST 节点

常见的 AST 节点 AST 是对源码的抽象,字面量、标识符、表达式、语句、模块语法、class 语法都有各自的 AST。

我们分别来了解一下:

Literal

Literal 是字面量的意思,比如 let name = 'value'中,'value'就是一个字符串字面量 StringLiteral,相应的还有数字字面量 NumericLiteral,布尔字面量 BooleanLiteral,字符串字面量 StringLiteral,正则表达式字面量 RegExpLiteral 等。

下面这些字面量都有对应的 Literal 节点:

代码中的字面量很多,babel 就是通过 xxLiteral 来抽象这部分内容的。

Identifier

Identifer 是标识符的意思,变量名、属性名、参数名等各种声明和引用的名字,都是Identifer

我们知道, JS 中的标识符只能包含字母或数字或下划线 (“_”) 或美元符号 (“$”) ,且不能以数字开头。这是 Identifier 的词法特点。

尝试分析一下,下面这一段代码里面有多少 Identifier 呢?

js
const name = 'value';
+
+function say(name) {
+  console.log(name);
+}
+
+const obj = {
+  name: 'guang',
+};

答案是这些

Statement

statement 是语句,它是可以独立执行的单位,比如 break、continue、debugger、return 或者 if 语句、while 语句、for 语句,还有声明语句,表达式语句等。我们写的每一条可以独立执行的代码都是语句。

语句末尾一般会加一个分号分隔,或者用换行分隔。

下面这些我们经常写的代码,每一行都是一个 Statement

js
break;
+continue;
+return;
+debugger;
+throw Error();
+{}
+try {} catch(e) {} finally{}
+for (let key in obj) {}
+for (let i = 0;i < 10;i ++) {}
+while (true) {}
+do {} while (true)
+switch (v){case 1: break;default:;}
+label: console.log();
+with (a){}

它们对应的 AST 节点如下图所示:

语句是代码执行的最小单位,可以说,代码是由语句 (Statement) 构成的。

Declaration

声明语句是一种特殊的语句,它执行的逻辑是在作用域内声明一个变量、函数、 class、import、export 等。

比如下面这些语句都是声明语句:

js
const a = 1;
+function b() {}
+class C {}
+
+import d from 'e';
+
+export default e = 1;
+export { e };
+export * from 'e';

它们对应的 AST 节点如下图:

声明语句用于定义变量,这也是代码中一个基础组成部分。

Expression

expression 是表达式,特点是执行完以后有返回值,这是和语句 (statement) 的区别。

下面是一些常见的表达式

js
[1,2,3]
+a = 1
+1 + 2;
+-1;
+function(){};
+() => {};
+class{};
+a;
+this;
+super;
+a::b;

它们对应的 AST 如图:

细心的同学可能会问 identifiersuper 怎么也是表达式呢?

因为 identifier、super 有返回值,符合表达式的特点,所以也是 expression

我们判断 AST 节点是不是某种类型要看它是不是符合该种类型的特点,比如语句的特点是能够单独执行,表达式的特点是有返回值。

有的表达式可以单独执行,符合语句的特点,所以也是语句,比如赋值表达式、数组表达式等。

js
a = 1;
+[1, 2, 3];

但有的表达式不能单独执行,需要和其他类型的节点组合在一起构成语句。

比如匿名函数表达式和匿名 class 表达式单独执行会报错:

js
function(){};
+class{}

需要和其他部分一起构成一条语句,比如组成赋值语句:

js
a = function () {};
+b = class {};

这条赋值语句对应的 AST 是这样的:

你会发现赋值语句的 AST 节点 AssignmentExpression 包裹了一层 ExpressionStatement 的节点,代表这个表达式是被当成语句执行的。

Class

class 的语法也有专门的 AST 节点来表示。

整个 class 的内容是 ClassBody ,属性是 ClassProperty ,方法是 ClassMethod (通过 kind 属性来区分是 constructor 还是 method )。

比如下面的代码

js
class Guang extends Person {
+  name = 'guang';
+  constructor() {}
+  eat() {}
+}

对应的 AST 是这样的

classes next 的语法, babel 中有专门的 AST 来表示它的内容。

Modules

es module 是语法级别的模块规范,所以也有专门的 AST 节点。

importimport 有 3 种语法:

named import

js
import { c, d } from 'c';

default import

js
import a from 'a';

namespaced import:

js
import * as b from 'b';

这 3 种语法都对应 ImportDeclaration 节点,但是 specifiers 属性不同,分别对应 ImportSpicifier 、ImportDefaultSpecifier 、ImportNamespaceSpcifier

图中黄框标出的就是 specifier 部分。可以直观的看出整体结构相同,只是 specifier 部分不同,所以 import 语法的 AST 的结构是 ImportDeclaration 包含着各种 import specifier

exportexport 也有 3 种语法:

named export

js
export { b, d };

default export

js
export default a;

all export

js
export * from 'c';

分别对应 ExportNamedDeclaration 、ExportDefaultDeclaration 、ExportAllDeclarationAST

比如这三种 export

js
export { b, d };
+export default a;
+export * from 'c';

对应的 AST 节点为

Program & Directive

program 是代表整个程序的节点,它有 body 属性代表程序体,存放 statement 数组,就是具体执行的语句的集合。还有 directives 属性,存放 Directive 节点,比如 "use strict" 这种指令会使用 Directive 节点表示。

Program 是包裹具体执行语句的节点,而 Directive 则是代码中的指令部分。

File & Comment

babelAST 最外层节点是 File ,它有 programcommentstokens 等属性,分别存放 Program 程序体、注释、 token 等,是最外层节点。

注释分为块注释和行内注释,对应 CommentBlockCommentLine 节点。

上面 6 种就是常见的一些 AST 节点类型, babel 就是通过这些节点来抽象源码中不同的部分。

AST 可视化查看工具

这么多 AST 我们都要记住么?

不需要。可以通过 axtexplorer.net 这个网站来可视化的查看。

这个网站可以查看代码 parse 以后的 AST ,可以切换 parse 的语言和用的 parser ,也可以修改 parse options

点击这里的 save 就可以保存下来,然后把 url 分享出去:

比如这个链接:https://astexplorer.net/

如果想查看全部的 AST 可以在 babel parser 仓库里的 AST 文档里查,或者直接去看 @babel/typestypescript 类型定义。

AST 的公共属性

每种 AST 都有自己的属性,但是它们也有一些公共的属性:

typeAST 节点的类型

startendloc:startend 代表该节点在源码中的开始和结束下标。而 loc 属性是一个对象,有 linecolumn 属性分别记录开始和结束的行列号。

leadingCommentsinnerCommentstrailingComments :表示开始的注释、中间的注释、结尾的注释,每个 AST 节点中都可能存在注释,而且可能在开始、中间、结束这三种位置,想拿到某个 AST 的注释就通过这三个属性。

比如这段有注释的代码的 AST

extra:记录一些额外的信息,用于处理一些特殊情况。比如 StringLiteralvalue 只是值的修改,而修改 extra.raw 则可以连同单双引号一起修改。 比如这段代码的 AST

修改 value 只能修改值,修改 extra.raw 可以连引号一起修改。

总结

了解了这些节点,就能知道平时写的代码是怎么用 AST 表示的。

当然也不需要记,可以用 (astexpoler.net) 可视化的查看。

AST 节点可能同时有多种类型,确定一种 AST 节点是什么类型主要看它的特点,比如 Statement 的特点是可以单独执行, Expression 的特点是有返回值,所以一些可以单独执行的 Expression 会包一层 ExpressionStatement

不同 AST 节点有不同的属性来存放对应的源码信息,但是都有一些公共属性如 type 、xxCommentsloc 等。

学会了 AST ,就可以把对代码的操作转为对 AST 的操作了,这是编译、静态分析的第一步。

三。编写词法分析器(Tokenizer)

词法分析器,也叫分词器 (Tokenizer),它的作用是将代码划分为一个个词法单元,便于进行后续的语法分析。比如下面的这段代码:

js
let foo = function () {};

在经过分词之后,代码会被切分为如下的 token 数组:

js
['let', 'foo', '=', 'function', '(', ')', '{', '}'];

从中你可以看到,原本一行普通的代码字符串被拆分成了拥有语法属性的 token 列表,不同的 token 之间也存在千丝万缕的联系,而后面所要介绍的语法分析器,就是来梳理各个 token 之间的联系,整理出 AST 数据结构。

当下我们所要实现的词法分析器,本质上是对代码字符串进行逐个字符的扫描,然后根据一定的语法规则进行分组。其中,涉及到几个关键的步骤:

  1. 确定语法规则,包括语言内置的关键词、单字符、分隔符等
  2. 逐个代码字符扫描,根据语法规则进行 token 分组

1. 确定 Token 的类型和规则

增加 Token 的类型

ts
export enum TokenType {
+  // let
+  Let = 'Let',
+  // =
+  Assign = 'Assign',
+  // function
+  Function = 'Function',
+  // 变量名
+  Identifier = 'Identifier',
+  // (
+  LeftParen = 'LeftParen',
+  // )
+  RightParen = 'RightParen',
+  // {
+  LeftCurly = 'LeftCurly',
+  // }
+  RightCurly = 'RightCurly',
+}
+
+export type Token = {
+  type: TokenType;
+  value?: string;
+  start: number;
+  end: number;
+  raw?: string;
+};

定义 Token 类型到规则的映射

ts
const TOKENS_GENERATOR: Record<string, (...args: any[]) => Token> = {
+  let(start: number) {
+    return { type: TokenType.Let, value: 'let', start, end: start + 3 };
+  },
+  assign(start: number) {
+    return { type: TokenType.Assign, value: '=', start, end: start + 1 };
+  },
+  function(start: number) {
+    return {
+      type: TokenType.Function,
+      value: 'function',
+      start,
+      end: start + 8,
+    };
+  },
+  leftParen(start: number) {
+    return { type: TokenType.LeftParen, value: '(', start, end: start + 1 };
+  },
+  rightParen(start: number) {
+    return { type: TokenType.RightParen, value: ')', start, end: start + 1 };
+  },
+  leftCurly(start: number) {
+    return { type: TokenType.LeftCurly, value: '{', start, end: start + 1 };
+  },
+  rightCurly(start: number) {
+    return { type: TokenType.RightCurly, value: '}', start, end: start + 1 };
+  },
+  identifier(start: number, value: string) {
+    return {
+      type: TokenType.Identifier,
+      value,
+      start,
+      end: start + value.length,
+    };
+  },
+};
+
+type SingleCharTokens = '(' | ')' | '{' | '}' | '=';
+
+// 单字符到 Token 生成器的映射
+const KNOWN_SINGLE_CHAR_TOKENS = new Map<SingleCharTokens, (typeof TOKENS_GENERATOR)[keyof typeof TOKENS_GENERATOR]>([
+  ['(', TOKENS_GENERATOR.leftParen],
+  [')', TOKENS_GENERATOR.rightParen],
+  ['{', TOKENS_GENERATOR.leftCurly],
+  ['}', TOKENS_GENERATOR.rightCurly],
+  ['=', TOKENS_GENERATOR.assign],
+]);

有了 Token 类型和对应生成的规则,我们便可以去遍历分析代码,输出分析后的结果。

2.代码字符扫描

在扫描字符的过程,我们需要对不同的字符各自进行不同的处理,具体的策略如下:

  • 当前字符为分隔符,如空格,直接跳过,不处理;
  • 当前字符为字母,需要继续扫描,获取完整的单词:
    • 如果单词为语法关键字,则新建相应关键字的 Token
    • 否则视为普通的变量名
  • 当前字符为单字符,如{、}、(、),则新建单字符对应的 Token
ts
export class Tokenizer {
+  private _tokens: Token[] = [];
+  private _currentIndex: number = 0;
+  private _source: string;
+  constructor(input: string) {
+    this._source = input;
+  }
+  tokenize(): Token[] {
+    while (this._currentIndex < this._source.length) {
+      let currentChar = this._source[this._currentIndex];
+      const startIndex = this._currentIndex;
+
+      // 根据语法规则进行 token 分组
+      // while 循环内部
+      let currentChar = this._source[this._currentIndex];
+      const startIndex = this._currentIndex;
+
+      const isAlpha = (char: string): boolean => {
+        return (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z');
+      };
+
+      // 1. 处理空格
+      if (currentChar === ' ') {
+        this._currentIndex++;
+        continue;
+      }
+      // 2. 处理字母
+      else if (isAlpha(currentChar)) {
+        let identifier = '';
+        while (isAlpha(currentChar)) {
+          identifier += currentChar;
+          this._currentIndex++;
+          currentChar = this._source[this._currentIndex];
+        }
+        let token: Token;
+        if (identifier in TOKENS_GENERATOR) {
+          // 如果是关键字
+          token = TOKENS_GENERATOR[identifier as keyof typeof TOKENS_GENERATOR](startIndex);
+        } else {
+          // 如果是普通标识符
+          token = TOKENS_GENERATOR['identifier'](startIndex, identifier);
+        }
+        this._tokens.push(token);
+        continue;
+      }
+      // 3. 处理单字符
+      else if (KNOWN_SINGLE_CHAR_TOKENS.has(currentChar as SingleCharTokens)) {
+        const token = KNOWN_SINGLE_CHAR_TOKENS.get(currentChar as SingleCharTokens)!(startIndex);
+        this._tokens.push(token);
+        this._currentIndex++;
+        continue;
+      }
+    }
+    return this._tokens;
+  }
+}

使用方式

ts
const tokenizer = new Tokenizer('let a = function() {}');

结果

ts
const tokenizer = [
+  { type: 'Let', value: 'let', start: 0, end: 3 },
+  { type: 'Identifier', value: 'a', start: 4, end: 5 },
+  { type: 'Assign', value: '=', start: 6, end: 7 },
+  { type: 'Function', value: 'function', start: 8, end: 16 },
+  { type: 'LeftParen', value: '(', start: 16, end: 17 },
+  { type: 'RightParen', value: ')', start: 17, end: 18 },
+  { type: 'LeftCurly', value: '{', start: 19, end: 20 },
+  { type: 'RightCurly', value: '}', start: 20, end: 21 },
+];

一个简易版本的分词器已经被我们开发出来了,不过目前的分词器还比较简陋,仅仅支持有限的语法,不过在明确了核心的开发步骤之后,后面继续完善的过程就比较简单了。

四。编写语法分析器(Parser)

在解析出词法 token 之后,我们就可以进入语法分析阶段了。在这个阶段,我们会依次遍历 token ,对代码进行语法结构层面的分析,最后的目标是生成 AST 数据结构。至于代码的 AST 结构到底是什么样子,你可以去 AST Explorer 网站进行在线预览:

接下来,我们要做的就是将 token 数组转换为上图所示的 AST 数据。

开发步骤主要分为:

  • 初始化类型声明

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/babel.html b/cn/src/article/babel.html new file mode 100644 index 0000000000..431c57b268 --- /dev/null +++ b/cn/src/article/babel.html @@ -0,0 +1,49 @@ + + + + + + Babel | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Babel

babel 核心库主要是:

  • @babel/parser 对源码进行 parse,可以通过 plugins、sourceType 等来指定 parse 语法,功能是把源码转成 AST。
  • @babel/traverse 通过 visitor 函数对遍历到的 ast 进行处理,分为 enter 和 exit 两个阶段,具体操作 AST 使用 path 的 api,还可以通过 state 来在遍历过程中传递一些数据
  • @babel/types 用于创建、判断 AST 节点,提供了 xxx、isXxx、assertXxx 的 api
  • @babel/template 当需要批量创建 AST 的时候可以使用 @babel/template 来简化 AST 创建逻辑。
  • @babel/code-frame 可以创建友好的报错信息
  • @babel/generator 打印 AST 成目标代码字符串,支持 comments、minified、sourceMaps 等选项。
  • @babel/core 基于上面的包来完成 babel 的编译流程,并应用 plugin 和 preset。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/bundle.html b/cn/src/article/bundle.html new file mode 100644 index 0000000000..8c895aa84a --- /dev/null +++ b/cn/src/article/bundle.html @@ -0,0 +1,49 @@ + + + + + + Bundle | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Bundle

Bundle 的本质就是输入,转换,输出。在机器上直接运行的代码,往往都难以维护和理解,我们需要将开发者方便理解和维护的代码,通过打包等工具转换成方便机器或者程序使用的代码。对于 web 前端来说,打包工具,至少需要以下功能:

  • 编译能力
  • 插件机制
  • HMR
  • cli 和命令行能力

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/designMode.html b/cn/src/article/designMode.html new file mode 100644 index 0000000000..35aac2987d --- /dev/null +++ b/cn/src/article/designMode.html @@ -0,0 +1,801 @@ + + + + + + 23 种经典设计模式 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

23 种经典设计模式

设计模式 Design Pattern 是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。。

在《设计模式:可复用面向对象软件的基础》一书中所介绍的 23 种经典设计模式,不过设计模式并不仅仅只有这 23 种,随着软件开发行业的发展,越来越多的新模式不断诞生并得以应用。有经验的开发者在学习设计模式可以和过往的经验互相印证,更容易理解这些设计模式。

设计模式一般包含模式名称、问题、目的、解决方案、效果等组成要素。问题描述了应该在何时使用模式,它包含了设计中存在的问题以及问题存在的原因。解决方案描述了一个设计模式的组成成分,以及这些组成成分之间的相互关系,各自的职责和协作方式,通常解决方案通过 UML 类图和核心代码来进行描述。效果描述了模式的优缺点以及在使用模式时应权衡的问题。

为什么要学习设计模式:

  • 设计模式来源众多专家的经验和智慧,它们是从许多优秀的软件系统中总结出的成功的、能够实现可维护性复用的设计方案,使用这些方案将可以让我们避免做一些重复性的工作

  • 设计模式提供了一套通用的设计词汇和一种通用的形式来方便开发人员之间沟通和交流,使得设计方案更加通俗易懂

  • 大部分设计模式都兼顾了系统的可重用性和可扩展性,这使得我们可以更好地重用一些已有的设计方案、功能模块甚至一个完整的软件系统,避免我们经常做一些重复的设计、编写一些重复的代码

  • 合理使用设计模式并对设计模式的使用情况进行文档化,将有助于别人更快地理解系统

  • 学习设计模式将有助于初学者更加深入地理解面向对象思想

储备知识

  • 抽象类:一般抽象类都是作为基类,比如说「电脑」就可以作为一个抽象类,根据抽象类派生出「台式电脑」和「笔记本电脑」2 种具体类。一般不对抽象类进行实例化。

  • 组合优于继承:不能滥用继承来拓展功能,配合组合会更灵活。同样拿「电脑」抽象类来举例,如果使用继承,区分不同类型的「电脑」我们可以派生出「台式电脑」和「笔记本电脑」,如果再增加一个维度,根据品牌又能继续细分出「联想台式电脑」、「联想笔记本电脑」、「苹果台式电脑」和「苹果笔记本电脑」等等,如果再增加一个维度继续细分下去,显然继承是无法胜任的。这个时候可以使用继承加组合方式,组合的对象也可以进行抽象化设计:

    ts
    // 品牌
    +interface Brand {
    +  // ...
    +}
    +interface Lenovo extends Brand {
    +  // ...
    +}
    +interface Apple extends Brand {
    +  // ...
    +}
    +// CPU
    +interface CPU {
    +  // ...
    +}
    +interface Inter extends CPU {
    +  // ...
    +}
    +interface AMD extends CPU {
    +  // ...
    +}
    +// 电脑
    +interface Computer {
    +  // ...
    +}
    +
    +interface DesktopComputer extends Computer {}
    +interface NotebookComputer extends Computer {}

一、UML 类图

每个模式都有相应的对象结构图,同时为了展示对象间的交互细节,有些时候会用到 UML 图来介绍其如何运行。这里不会将 UML 的各种元素都提到,只想讲讲类图中各个类之间的关系,能看懂类图中各个类之间的线条、箭头代表什么意思后,也就足够应对日常的工作和交流。同时,我们应该能将类图所表达的含义和最终的代码对应起来。有了这些知识,看后面章节的设计模式结构图就没有什么问题了。

1.1 继承

继承用一条带空心箭头的直接表示。

1.2 实现

实现关系用一条带空心箭头的虚线表示。

1.3 组合

与聚合关系一样,组合关系同样表示整体由部分构成的语义。比如公司由多个部门组成,但组合关系是一种强依赖的特殊聚合关系,如果整体不存在了,则部分也不存在了。例如,公司不存在了,部门也将不存在了。

1.4 聚合

聚合关系用于表示实体对象之间的关系,表示整体由部分构成的语义,例如一个部门由多个员工组成。与组合关系不同的是,整体和部分不是强依赖的,即使整体不存在了,部分仍然存在。例如,部门撤销了,人员不会消失,他们依然存在。

1.5 关联

关联关系是用一条直线表示的,它描述不同类的对象之间的结构关系,它是一种静态关系,通常与运行状态无关,一般由常识等因素决定的。它一般用来定义对象之间静态的、天然的结构,所以,关联关系是一种“强关联”的关系。

比如,乘车人和车票之间就是一种关联关系,学生和学校就是一种关联关系,关联关系默认不强调方向,表示对象间相互知道。如果特别强调方向,如下图,表示 A 知道 B,但 B 不知道 A。

1.6 依赖

依赖关系是用一套带箭头的虚线表示的,如 A 依赖于 B,他描述一个对象在运行期间会用到另一个对象的关系。

与关联关系不同的是,它是一种临时性的关系,通常在运行期间产生,并且随着运行时的变化,依赖关系也可能发生变化。显然,依赖也有方向,双向依赖是一种非常糟糕的结构,我们总是应该保持单向依赖,杜绝双向依赖的产生。

二、六大原则

2.1 开闭原则

一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

任何软件都需要面临一个很重要的问题,即它们的需求会随时间的推移而发生变化。当软件系统需要面对新的需求时,我们应该尽量保证系统的设计框架是稳定的。如果一个软件设计符合开闭原则,那么可以非常方便地对系统进行扩展,而且在扩展时无须修改现有代码,使得软件系统在拥有适应性和灵活性的同时具备较好的稳定性和延续性。随着软件规模越来越大,软件寿命越来越长,软件维护成本越来越高,设计满足开闭原则的软件系统也变得越来越重要。

为了满足开闭原则,需要对系统进行抽象化设计,抽象化是开闭原则的关键。在JavaC#等编程语言中,可以为系统定义一个相对稳定的抽象层,而将不同的实现行为移至具体的实现层中完成。在很多面向对象编程语言中都提供了接口、抽象类等机制,可以通过它们定义系统的抽象层,再通过具体类来进行扩展。如果需要修改系统的行为,无须对抽象层进行任何改动,只需要增加新的具体类来实现新的业务功能即可,实现在不修改已有代码的基础上扩展系统的功能,达到开闭原则的要求。

优点:实践开闭原则的优点在于可以在不改动原有代码的前提下给程序扩展功能。增加了程序的可扩展性,同时也降低了程序的维护成本。

2.2 里氏替换原则

所有引用基类对象的地方能够透明地使用其子类的对象

里氏代换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。例如:我喜欢动物,那我一定喜欢狗,因为狗是动物的子类。但是我喜欢狗,不能据此断定我喜欢动物,因为我并不喜欢老鼠,虽然它也是动物。

例如有两个类,一个类为BaseClass,另一个是SubClass类,并且SubClass类是BaseClass类的子类,那么一个方法如果可以接受一个BaseClass类型的基类对象base的话,如:method1(base),那么它必然可以接受一个BaseClass类型的子类对象submethod1(sub)能够正常运行。反过来的代换不成立,如一个方法method2接受BaseClass类型的子类对象sub为参数:method2(sub),那么一般而言不可以有method2(base),除非是重载方法。

里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

优点:可以检验继承使用的正确性,约束继承在使用上的泛滥。

2.3 依赖倒置原则

抽象不应该依赖于具体类,具体类应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。

依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。为了确保该原则的应用,一个具体类应当只实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法。

在引入抽象层后,系统将具有很好的灵活性,在程序中尽量使用抽象层进行编程,而将具体类写在配置文件中,这样一来,如果系统行为发生变化,只需要对抽象层进行扩展,并修改配置文件,而无须修改原有系统的源代码,在不修改的情况下来扩展系统的功能,满足开闭原则的要求。

优点:通过抽象来搭建框架,建立类和类的关联,以减少类间的耦合性。而且以抽象搭建的系统要比以具体实现搭建的系统更加稳定,扩展性更高,同时也便于维护。

2.4 单一职责原则

一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。

单一职责原则告诉我们:一个类不能太“累”!在软件系统中,一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。

单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关实践经验。

优点:如果类与方法的职责划分得很清晰,不但可以提高代码的可读性,更实际性地更降低了程序出错的风险,因为清晰的代码会让 bug 无处藏身,也有利于 bug 的追踪,也就是降低了程序的维护成本。

2.5 迪米特法则(最少知道原则)

一个软件实体应当尽可能少地与其他实体发生相互作用

如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。

迪米特法则要求我们在设计系统时,应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。

在将迪米特法则运用到系统设计中时,要注意下面的几点:在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及。在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限。在类的设计上,只要有可能,一个类型应当设计成不变类。在对其他类的引用上,一个对象对其他对象的引用应当降到最低。

优点:实践迪米特法则可以良好地降低类与类之间的耦合,减少类与类之间的关联程度,让类与类之间的协作更加直接。

2.6 接口分离原则

使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。

根据接口隔离原则,当一个接口太大时,我们需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干。

在使用接口隔离原则时,我们需要注意控制接口的粒度,接口不能太小,如果太小会导致系统中接口泛滥,不利于维护。接口也不能太大,太大的接口将违背接口隔离原则,灵活性较差,使用起来很不方便。

优点:避免同一个接口里面包含不同类职责的方法,接口责任划分更加明确,符合高内聚低耦合的思想。

2.7 合成复用原则(六大之外的)

尽量使用对象组合,而不是继承来达到复用的目的

合成复用原则就是在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分,新对象通过委派调用已有对象的方法达到复用功能的目的。简而言之,复用时要尽量使用组合/聚合关系(关联关系),少用继承。

在面向对象设计中,可以通过两种方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或通过继承,但首先应该考虑使用组合/聚合,组合/聚合可以使系统更加灵活,降低类与类之间的耦合度。一个类的变化对其他类造成的影响相对较少,其次才考虑继承,在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用。

优点:避免复用时滥用继承,合理使用组合关系,增加灵活性。

2.8 六大原则 - 学习心得

六大原则中,开闭原则里氏替换原则依赖倒置原则 联系比较紧密,后两者是实现开闭原则重要前提,使用中通过抽象化设计具有很好的可拓展性和可维护性。

知道最少原则 可以降低耦合,减少不必要的交互,主张设计接口和类要简单易使用,将复杂的逻辑封装并提供简单易用的接口。

单一职责原则 使项目中的类和方法根据职责细分,避免单个类负担过重。职责越多,被复用的可能性就越小或使用起来越麻烦。

接口分离原则 将功能复杂的接口细分成多个特定功能的接口,只做该做的事情,降低耦合,但是细化粒度不能太细,容易导致接口过多。单一职责原则强调单个类内部根据职责细分的设计,接口分离原则强调类之间的耦合,尽量建立最小的依赖关系。

三、模式分类

《设计模式:可复用面向对象软件的基础》一书中设计模式有 23 个,它们各具特色,每个模式都为某一个可重复的设计问题提供了一套解决方案。根据它们的用途,设计模式可分为创建型 (Creational),结构型 (Structural) 和行为型 (Behavioral) 三种,其中创建型模式主要用于描述如何创建对象,结构型模式主要用于描述如何实现类或对象的组合,行为型模式主要用于描述类或对象怎样交互以及怎样分配职责。

此外,根据某个模式主要是用于处理类之间的关系还是对象之间的关系,设计模式还可以分为类模式和对象模式。我们经常将两种分类方式结合使用,如单例模式是对象创建型模式,模板方法模式是类行为型模式。

3.1 创建型

创建型模式 (Creational Pattern) 对类的实例化过程进行了抽象,能够将模块中对象的创建和对象的使用分离。为了使结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则。

  1. 简单工厂模式(Simple Factory Pattern
  2. 工厂方法模式(Factory Method Pattern
  3. 抽象工厂模式(Abstract Factory Pattern
  4. 单例模式(Singleton Pattern
  5. 生成器模式(Builder Pattern
  6. 原型模式(Prototype Pattern

3.2 结构型

结构型模式 (Structural Pattern) 描述如何将类或者对 象结合在一起形成更大的结构,就像搭积木,可以通过 简单积木的组合形成复杂的、功能更为强大的结构。结构型模式可以分为类结构型模式和对象结构型模式:

  • 类结构型模式关心类的组合,由多个类可以组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系。

  • 对象结构型模式关心类与对象的组合,通过关联关系使得在一 个类中定义另一个类的实例对象,然后通过该对象调用其方法。根据“合成复用原则”,在系统中尽量使用关联关系来替代继 承关系,因此大部分结构型模式都是对象结构型模式。

  1. 外观模式
  2. 适配器模式
  3. 桥接模式
  4. 代理模式
  5. 装饰者模式
  6. 享元模式

3.3 行为型

行为型模式 (Behavioral Pattern) 是对在不同的对象之间划分责任和算法的抽象化。行为型模式不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。通过行为型模式,可以更加清晰地划分类与对象的职责,并研究系统在运行时实例对象之间的交互。

  1. 职责链模式
  2. 命令模式
  3. 解释器模式
  4. 迭代器模式
  5. 中介者模式
  6. 备忘录模式
  7. 观察者模式
  8. 状态模式
  9. 策略模式
  10. 模板方法模式
  11. 访问者模式

四、创建型

4.1 简单工厂模式

简单工厂模式 (Simple Factory Pattern):专门定义一个类(工厂类)来负责创建其他类的实例。可以根据创建方法的参数来返回不同类的实例,被创建的实例通常都具有共同的父类。

举例:

简单工厂模式像一个代工厂,一个工厂可以生产多种产品。举个例子,一个饮料加工厂同时帮百事可乐和可口可乐生产,加工厂根据输入参数Type来生产不同的产品。

ts
// 可乐抽象类
+interface Cola {}
+
+// 可口可乐产品类
+interface CocaCola extends Cola {}
+
+// 百事可乐产品类
+interface PepsiCola extends Cola {}
ts
// 简单工厂实现
+// SimpleFactory
+const createColaWithType = (type: number) => {
+  switch (type) {
+    case 0:
+      return new CocaCola();
+    case 1:
+      return new PepsiCola();
+    default:
+      return null;
+      break;
+  }
+};
ts
// 0 生产可口可乐
+const cocaCola: CocaCola = createColaWithType(0);
+
+// 1 生产百事可乐
+const pepsiCola: PepsiCola = createColaWithType(1);

优点:

  • 使用者只需要给工厂类传入一个正确的约定好的参数,就可以获取你所需要的对象,而不需要知道其创建细节,一定程度上减少系统的耦合。
  • 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,减少开发者的记忆成本。

缺点:

  • 如果业务上添加新产品的话,就需要修改工厂类原有的判断逻辑,这其实是违背了开闭原则的。
  • 在产品类型较多时,有可能造成工厂逻辑过于复杂。所以简单工厂模式比较适合产品种类比较少而且增多的概率很低的情况。

4.2 工厂方法模式

工厂方法模式 (Factory Method Pattern) 又称为工厂模式,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,即通过不同的工厂子类来创建不同的产品对象。

举例:

工厂方法和简单工厂有一些区别,简单工厂是由一个代工厂生产不同的产品,而工厂方法是对工厂进行抽象化,不同产品都由专门的具体工厂来生产。可口可乐工厂专门生产可口可乐,百事可乐工厂专门生产百事可乐。

ts
// 工厂抽象类
+class Cola {}
+
+// 可口可乐工厂
+class CocaCola extends Cola {}
+
+// 百事可乐工厂
+class PepsiCola extends Cola {}
ts
// 根据不同的工厂类生产不同的产品
+const cocaCola = new CocaCola();
+const pepsiCola = new PepsiCola();

优点:

  • 用户只需要关心其所需产品对应的具体工厂是哪一个即可,不需要关心产品的创建细节,也不需要知道具体产品类的类名。
  • 当系统中加入新产品时,不需要修改抽象工厂和抽象产品提供的接口,也无须修改客户端和其他的具体工厂和具体产品,而只要添加一个具体工厂和与其对应的具体产品就可以了,符合了开闭原则。

缺点:

  • 当系统中加入新产品时,除了需要提供新的产品类之外,还要提供与其对应的具体工厂类。因此系统中类的个数将成对增加,增加了系统的复杂度。

4.3 抽象工厂模式

抽象工厂模式并不直接生成实例,而是用于对产品类簇的创建。

抽象工厂模式 (Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

举例:

抽象工厂和工厂方法不同的地方在于,生产产品的工厂是抽象的。举例,可口可乐公司生产可乐的同时,也需要生产装可乐的瓶子和箱子,瓶子和箱子也是可口可乐专属定制的,同样百事可乐公司也会有这个需求。这个时候我们的工厂不仅仅是生产可乐饮料的工厂,还必须同时生产同一主题的瓶子和箱子,所以它是一个抽象的主题工厂,专门生产同一主题的不同商品。

ts
// 可乐抽象类和派生类
+class Cola {}
+
+class CocaCola extends Cola {}
+
+class PepsiCola extends Cola {}
+
+// 瓶子抽象类和派生类
+class Bottle {}
+
+class CocaColaBottle extends Bottle {}
+
+class PepsiColaBottle extends Bottle {}
+
+// 箱子抽象类和派生类
+class Box {}
+
+class CocaColaBox extends Box {}
+
+class PepsiColaBox extends Box {}
+
+// 工厂抽象类
+const Factory = {
+  createCola: () => new Cola(),
+  createBottle: () => new Bottle(),
+  createBox: () => new Box(),
+};
+
+// 可口可乐主题工厂
+const CocaColaFactory = {
+  createCola: () => new CocaCola(),
+  createBottle: () => new CocaColaBottle(),
+  createBox: () => new CocaColaBox(),
+};
+
+// 百事可乐主题工厂
+const PepsiColaFactory = {
+  createCola: () => new PepsiCola(),
+  createBottle: () => new PepsiColaBottle(),
+  createBox: () => new PepsiColaBox(),
+};
ts
// 可口可乐主题
+const cocaCola = CocaColaFactory.createCola();
+const cocaColaBottle = CocaColaFactory.createBottle();
+const cocaColaBox = CocaColaFactory.createBox();
+
+// 百事可乐主题
+const pepsiCola = PepsiColaFactory.createCola();
+const pepsiColaBottle = PepsiColaFactory.createBottle();
+const pepsiColaBox = PepsiColaFactory.createBox();

优点:

  • 具体产品在应用层代码隔离,不需要关心产品细节。只需要知道自己需要的产品是属于哪个工厂的即可 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。

缺点:

  • 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。

4.4 单例模式

单例模式 (Singleton Pattern):单例模式确保某一个类只有一个实例,并提供一个访问它的全剧访问点。

举例:

单例模式下,对应类只能生成一个实例。就像一个王国只能有一个国王,一旦王国里的事务多起来,这唯一的国王也容易职责过重。

ts
class Singleton {}
+
+function createSingleton() {
+  let instance;
+  return function () {
+    if (!instance) return new Singleton();
+    return instance;
+  };
+}

优点:

  • 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它。
  • 因为该类在系统内存中只存在一个对象,所以可以节约系统资源。

缺点:

  • 由于单例模式中没有抽象层,因此单例类很难进行扩展。
  • 对于有垃圾回收系统的语言 Java,C# 来说,如果对象长时间不被利用,则可能会被回收。那么如果这个单例持有一些数据的话,在回收后重新实例化时就不复存在了。

4.5 生成器模式

生成器模式 (Builder Pattern):也叫创建者模式,它将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

工厂模式主要是为了创建对象实例或者类簇(抽象工厂),关心的是最终产出 (创建) 的是什么,而不关心创建的过程。而建造者模式关心的是创建这个对象的整个过程,甚至于创建对象的每一个细节。

举例:

生成器模式的主要角色如下:

  1. 生成器:接口生命再所有类型生成器中通用的产品构造步骤
  2. 具体生成器:提供构造过程的不同实现。具体生成器也可以构造不遵循通用接口的产品
  3. 产品:是最终生成的对象。由不同生成器构造的产品无需属于同一类层次构造或接口
  4. 指挥者:定义调用构造步骤的顺序,这样你就可以创建和服用特定的产品配置
  5. 客户端:必须将某个生成器对象与主管类关联,一般情况下,你只需要通过指挥者类构造函数的参数进行一次性关联即可
ts
// 抽象建造者
+abstract class Builder {
+  public abstract buildPartA(): void;
+  public abstract buildPartB(): void;
+  public abstract buildPartC(): void;
+  public abstract buildProduct(): Product;
+}
+
+// 具体建造者
+class ConcreteBuilder extends Builder {
+  private product: Product;
+  constructor(product: Product) {
+    super();
+    this.product = product;
+  }
+
+  public buildPartA(): void {}
+  public buildPartB(): void {}
+  public buildPartC(): void {}
+
+  // 最终组建一个产品
+  public buildProduct(): Product {
+    return this.product;
+  }
+}
+
+// 产品角色
+class Product {
+  public doSomething(): void {
+    // 独立业务
+  }
+}
+
+// 指挥者
+class Director {
+  private _builder: Builder;
+  constructor(builder: Builder) {
+    this._builder = builder;
+  }
+
+  set builder(builder: Builder) {
+    this._builder = builder;
+  }
+
+  // 将处理建造的流程交给指挥者
+  public constructorProduct() {
+    this._builder.buildPartA();
+    this._builder.buildPartB();
+    this._builder.buildPartC();
+    return this._builder.buildProduct();
+  }
+}
+
+// 使用
+const builder: Builder = new ConcreteBuilder(new Product());
+const director: Director = new Director(builder);
+const product: Product = director.constructorProduct();

优点:

  • 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
  • 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
  • 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
  • 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。

缺点:

  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。

4.6 原型模式

原型模式(Prototype Pattern): 用原型实例指向创建对象的类,使用于创建新的对象的类的共享原型的属性与方法。

举例:

原型模式就像复印技术,根据原对象复印出一个新对象,并根据需求对新对象进行微调。

ts
// 因为不是构造函数,所以不用大写
+const car = {
+  drive: function () {},
+  name: '马自达 3',
+};
+
+// 使用 Object.create 创建一个新车 x
+const anotherCar = Object.create(someCar);
+anotherCar.name = '丰田佳美';
ts
const vehiclePrototype = {
+  init: function (carModel) {
+    this.model = carModel;
+  },
+  getModel: function () {
+    console.log('车辆模具是:' + this.model);
+  },
+};
+
+function vehicle(model) {
+  function F() {}
+  F.prototype = vehiclePrototype;
+
+  const f = new F();
+
+  f.init(model);
+  return f;
+}
+
+const car = vehicle('福特 Escort');
+car.getModel();

优点:

  • 可以利用原型模式简化对象的创建过程,尤其是对一些创建过程繁琐,包含对象层级比较多的对象来说,使用原型模式可以节约系统资源,提高对象生成的效率。
  • 可以很方便得通过改变值来生成新的对象:有些对象之间的差别可能只在于某些值的不同;用原型模式可以快速复制出新的对象并手动修改值即可。

缺点:

  • 对象包含的所有对象都需要配备一个克隆的方法,这就使得在对象层级比较多的情况下,代码量会很大,也更加复杂。

五、结构型

5.1 装饰模式

装饰模式 (Decorator Pattern) :向一个现有的对象添加新的功能,同时又不改变其结构的设计模式被称为装饰器模式,它是作为现有的类的一个包装。

可以将装饰器理解为游戏人物购买的装备,例如 LOL 中的英雄刚开始游戏时只有基础的攻击力和法强。但是在购买的装备后,在触发攻击和技能时,能够享受到装备带来的输出加成。我们可以理解为购买的装备给英雄的攻击和技能的相关方法进行了装饰。

举例:

装饰模式贴合开闭原则,在不改变原有类的情况下,对父类进行改造或新增功能。

装饰类

ts
@annotation
+class MyClass {}
+
+function annotation(target) {
+  target.annotated = true;
+}

装饰方法或属性

js
class MyClass {
+  @readonly
+  method() {}
+}
+
+function readonly(target, name, descriptor) {
+  descriptor.writable = false;
+  return descriptor;
+}

优点:

  • 比继承更加灵活:不同于在编译期起作用的继承;装饰者模式可以在运行时扩展一个对象的功能。另外也可以通过配置文件在运行时选择不同的装饰器,从而实现不同的行为。也可以通过不同的组合,可以实现不同效果。
  • 符合“开闭原则”:装饰者和被装饰者可以独立变化。用户可以根据需要增加新的装饰类,在使用时再对其进行组合,原有代码无须改变。

缺点:

  • 装饰者模式需要创建一些具体装饰类,会增加系统的复杂度。

5.2 外观模式

外观模式 (Facade Pattern):外观模式定义了一个高层接口,为子系统中的一组接口提供一个统一的接口。使得子系统更容易使用,不仅简化类中的接口,而且实现调用者和接口的解耦。外观模式又称为门面模式,它是一种结构型设计模式模式。

举例:

外观模式提供了简单明确的接口,但是在内部众多子系统功能进行整合。就像图片缓存,内部包含了涉及到其他子系统的如缓存、下载等处理,外观模式将这些复杂的逻辑都隐藏了。在兼容浏览器事件绑定,你只需要调一个addMyEvent接口就可以了,达到解耦合的目的。

js
const addMyEvent = function (el, ev, fn) {
+  if (el.addEventListener) {
+    el.addEventListener(ev, fn, false);
+  } else if (el.attachEvent) {
+    el.attachEvent('on' + ev, fn);
+  } else {
+    el['on' + ev] = fn;
+  }
+};

优点:

  • 实现了客户端与子系统间的解耦:客户端无需知道子系统的接口,简化了客户端调用子系统的调用过程,使得子系统使用起来更加容易。同时便于子系统的扩展和维护。
  • 符合迪米特法则(最少知道原则):子系统只需要将需要外部调用的接口暴露给外观类即可,而且他的接口则可以隐藏起来。

缺点:

  • 违背了开闭原则:在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的代码。

5.3 代理模式

代理模式 (Proxy Pattern) :为某个对象提供一个代理,并由这个代理对象控制对原对象的访问。

举例:

代理模式像一个房屋中介,买家只能通过中介来买房,代理具备被代理类的所有功能,就像房东有卖房功能,中介也具有卖房功能。此外代理实例还可以帮助被代理实例进行一些额外处理,比如中介可以帮助房东筛选优质买家的功能,帮助房东 pass 掉一些不符合条件的买家。还有消息队列也是该模式。

参考koa中的代理模式,把response上的一些属性和方法代理出来,方便使用

js
/**
+ * Response delegation.
+ */
+const delegate = require('delegates');
+
+const prototype = (module.exports = {});
+
+delegate(prototype, 'response')
+  .method('attachment')
+  .method('redirect')
+  .method('remove')
+  .method('vary')
+  .method('has')
+  .method('set')
+  .method('append')
+  .method('flushHeaders')
+  .access('status')
+  .access('message')
+  .access('body')
+  .access('length')
+  .access('type')
+  .access('lastModified')
+  .access('etag')
+  .getter('headerSent')
+  .getter('writable');

context,request,response做一个代理,保护真正的context,request,response

js
this.context = Object.create(context);
+this.request = Object.create(request);
+this.response = Object.create(response);

优点:

  • 降低系统的耦合度:代理模式能够协调调用者和被调用者,在一定程度上降低了系 统的耦合度。
  • 不同类型的代理可以对客户端对目标对象的访问进行不同的控制:
    • 远程代理,使得客户端可以访问在远程机器上的对象,远程机器 可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。
    • 虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。
    • 保护代理可以控制客户端对真实对象的使用权限。

缺点:

  • 由于在客户端和被代理对象之间增加了代理对象,因此可能会让客户端请求的速度变慢。

5.4 享元模式

享元模式 (Flyweight Pattern):享元模式是一种优化程序性能的模式,本质为减少对象创建的个数。运用共享技术复用大量细粒度的对象,降低程序内存的占用,提高程序的性能。以下情况可以使用享元模式:有大量相似的对象,占用了大量内存。对象中大部分状态可以抽离为外部状态。

举例:

举例,音乐服务根据收费划分出免费用户和会员用户,免费用户只能听部分免费音乐,会员用户可以听全部的音乐,并且可以下载。虽然权限上二者间有一些区别,但是他们所享受的音乐来是自于同一个音乐库,这样所有的音乐都只需要保存一份就可以了。另外如果出现音乐库里没有的音乐时,则需要新增该音乐,然后其他服务也可以享受新增的音乐,相当于享元池或缓存池的功能。

享元模式区保证共享内部状态如音乐库,而外部状态根据不同需求定制如各种访问权限,使用中不能去改变内部状态,以达到共享的目的。

ts
// 音乐服务
+const MusicService = {}
+
+// 共享的音乐库
+const musicLibrary = {};
+
+// 听音乐
+const listenToMusic = (music) => {
+    ...
+}
+// 下载音乐
+const downloadMusic = (music) => {
+    ...
+}
+
+
+// 免费音乐服务
+const FreeMusicService = {
+    listenFreeMusic: (music)=>{
+        if(isMusicFree(music)){
+            // 如果是免费则播放
+            listenToMusic()
+        }else{
+    	    // 如果是收费音乐,则提示用户升级 Vip
+            console.log("please upgrade to Vip")
+        }
+    }
+}
+
+
+// Vip 音乐服务
+const VipMusicService = {
+    // 可以听全部的音乐
+    listenMusic
+    // 可以下载音乐
+    downloadMusic
+}

优点:

  • 使用享元模可以减少内存中对象的数量,使得相同对象或相似对象在内存中只保存一份,降低系统的使用内存,也可以提性能。
  • 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。

缺点:

  • 使用享元模式需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
  • 对象在缓冲池中的复用需要考虑线程问题。

5.5 桥接模式

桥接模式 (Simple Factory Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。

举例:

球和人都可以进行运动,但球有运动和颜色,人可以运动和说话。对共同部分进行抽象。

js
class Speed {
+  // 运动模块
+  constructor(x, y) {
+    this.x = x;
+    this.y = y;
+  }
+  run() {
+    console.log(`运动起来 ${this.x} + ${this.y}`);
+  }
+}
+
+class Color {
+  // 着色模块
+  constructor(cl) {
+    this.color = cl;
+  }
+  draw() {
+    console.log(`绘制颜色 ${this.color}`);
+  }
+}
+
+class Speak {
+  constructor(wd) {
+    this.word = wd;
+  }
+  say() {
+    console.log(`说话 ${this.word}`);
+  }
+}
+
+class Ball {
+  // 创建球类,可以着色和运动
+  constructor(x, y, cl) {
+    this.speed = new Speed(x, y);
+    this.color = new Color(cl);
+  }
+  init() {
+    this.speed.run();
+    this.color.draw();
+  }
+}
+
+class Man {
+  // 人类,可以运动和说话
+  constructor(x, y, wd) {
+    this.speed = new Speed(x, y);
+    this.speak = new Speak(wd);
+  }
+  init() {
+    this.speed.run();
+    this.speak.say();
+  }
+}
+
+const man = new Man(1, 2, 'hello ?');
+man.init(); // 运动起来 1 + 2      说话 hello?

优点:

  • 扩展性好,符合开闭原则:将抽象与实现分离,让二者可以独立变化

缺点:

  • 在设计之前,需要识别出两个独立变化的维度。

5.6 适配器模式

适配器模式 (Adapter Pattern) :适配器模式是用来解决两个接口不兼容的情况,不需要改变已有的接口,通过包装一层的方式,实现两个接口正常协作。当我们试图调用模块或者对象的某个接口时,却发现这个接口的格式并不符合目前的需求,则可以用适配器模式。

举例:

事件绑定兼容各浏览器

js
function addEvent(ele, event, callback) {
+    if (ele.addEventListener) {
+      ele.addEventListener(event, callback)
+    } else if(ele.attachEvent) {
+      ele.attachEvent('on' + event, callback)
+    } else {
+      ele['on' + event] = callback
+    }
+  }
+

优点:

  • 符合开闭原则:使用适配器而不需要改变现有类,提高类的复用性。
  • 目标类和适配器类解耦,提高程序扩展性。

缺点:

  • 增加了系统的复杂性

六、行为型

6.1 职责链模式

职责链模式 (Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。职责链模式是一种对象行为型模式。类似多米诺骨牌,通过请求第一个条件,会持续执行后续的条件,直到返回结果为止。

举例:

场景:某电商针对已付过定金的用户有优惠政策,在正式购买后,已经支付过 500 元定金的用户会收到 100 元的优惠券,200 元定金的用户可以收到 50 元优惠券,没有支付过定金的用户只能正常购买。

js
const order500 = function (orderType, pay, stock) {
+  if (orderType === 1 && pay == true) {
+    console.log('500 元定金预购,得到 100 元优惠劵');
+  } else {
+    return 'nextSuccess';
+  }
+};
+const order200 = function (orderType, pay, stock) {
+  if (orderType === 2 && pay === true) {
+    console.log('200 元定金预购,得到 50 元優惠卷');
+  } else {
+    return 'nextSuccess';
+  }
+};
+const orderCommon = function (orderType, pay, stock) {
+  if (orderType == 3 && stock > 0) {
+    console.log('普通購買,无優惠卷');
+  } else {
+    console.log('库存不够');
+  }
+};
+//链路代码
+const chain = function (fn) {
+  this.fn = fn;
+  this.successor = null;
+};
+chain.prototype.setNext = function (successor) {
+  this.successor = successor;
+};
+chain.prototype.init = function () {
+  const result = this.fn.apply(this, arguments);
+  if (result == 'nextSuccess') {
+    this.successor.init.apply(this.successor, arguments);
+  }
+};
+const order500New = new chain(order500);
+const order200New = new chain(order200);
+const orderCommonNew = new chain(orderCommon);
+order500New.setNext(order200New);
+order200New.setNext(orderCommonNew);
+order500New.init(3, true, 500); // 普通购买,无优惠券

优点:

  • 职责链模式使得一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构,由客户端负责链的创建,降低了系统的耦合度。
  • 请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的引用,可简化对象的相互连接。
  • 在给对象分派职责时,职责链可以给我们更多的灵活性,可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的职责。
  • 在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新建链即可,从这一点来看是符合“开闭原则”的。

缺点:

  • 由于一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理。
  • 对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响,而且在进行代码调试时不太方便。
  • 如果建链不当,可能会造成循环调用,将导致系统陷入死循环。

6.2 命令模式

命令模式 (Command Pattern):将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;命令模式是一种对象行为型模式,其别名为动作 (Action) 模式或事务 (Transaction) 模式。

命令模式由三种角色构成:

  1. 发布者 invoker(发出命令,调用命令对象,不知道如何执行与谁执行);
  2. 接收者 receiver (提供对应接口处理请求,不知道谁发起请求);
  3. 命令对象 command(接收命令,调用接收者对应接口处理发布者的请求)。 发布者 invoker 和接收者 receiver 各自独立,将请求封装成命令对象 command,请求的具体执行由命令对象 command 调用接收者 receiver 对应接口执行。

举例:

和之前代理模式中的举例有些相似,不过命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。例如遥控器是一个调用者,不同按钮代表不同的命令,而电视是接收者。

js
class Receiver {
+  // 接收者类
+  execute() {
+    console.log('接收者执行请求');
+  }
+}
+
+class Command {
+  // 命令对象类
+  constructor(receiver) {
+    this.receiver = receiver;
+  }
+  execute() {
+    // 调用接收者对应接口执行
+    console.log('命令对象->接收者->对应接口执行');
+    this.receiver.execute();
+  }
+}
+
+class Invoker {
+  // 发布者类
+  constructor(command) {
+    this.command = command;
+  }
+  invoke() {
+    // 发布请求,调用命令对象
+    console.log('发布者发布请求');
+    this.command.execute();
+  }
+}
+
+const warehouse = new Receiver(); // 仓库
+const order = new Command(warehouse); // 订单
+const client = new Invoker(order); // 客户
+client.invoke();

优点:

  • 降低系统的耦合度。由于请求者与接收者之间不存在直接引用,因此请求者与接收者之间实现完全解耦,相同的请求者可以对应不同的接收者,同样,相同的接收者也可以供不同的请求者使用,两者之间具有良好的独立性。
  • 新的命令可以很容易地加入到系统中。由于增加新的具体命令类不会影响到其他类,因此增加新的具体命令类很容易,无须修改原有系统源代码,甚至客户类代码,满足“开闭原则”的要求。
  • 可以比较容易地设计一个命令队列或宏命令(组合命令)。
  • 为请求的撤销 (Undo) 和恢复 (Redo) 操作提供了一种设计和实现方案。

缺点:

  • 使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个对请求接收者的调用操作都需要设计一个具体命令类,因此在某些系统中可能需要提供大量的具体命令类,这将影响命令模式的使用。

6.3 解释器模式

解释器模式 (Interpreter Pattern):定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。解释器模式是一种类行为型模式。

举例:

给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。

js
class Context {
+  constructor() {
+    this._list = []; // 存放 终结符表达式
+    this._sum = 0; // 存放 非终结符表达式 (运算结果)
+  }
+
+  get sum() {
+    return this._sum;
+  }
+  set sum(newValue) {
+    this._sum = newValue;
+  }
+  add(expression) {
+    this._list.push(expression);
+  }
+  get list() {
+    return [...this._list];
+  }
+}
+
+class PlusExpression {
+  interpret(context) {
+    if (!(context instanceof Context)) {
+      throw new Error('TypeError');
+    }
+    context.sum = ++context.sum;
+  }
+}
+class MinusExpression {
+  interpret(context) {
+    if (!(context instanceof Context)) {
+      throw new Error('TypeError');
+    }
+    context.sum = --context.sum;
+  }
+}
+
+/** 以下是测试代码 **/
+const context = new Context();
+
+// 依次添加:加法 | 加法 | 减法 表达式
+context.add(new PlusExpression());
+context.add(new PlusExpression());
+context.add(new MinusExpression());
+
+// 依次执行:加法 | 加法 | 减法 表达式
+context.list.forEach((expression) => expression.interpret(context));
+console.log(context.sum);

优点:

  • 易于改变和扩展文法。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。
  • 每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
  • 实现文法较为容易。在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成节点类代码。
  • 增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合“开闭原则”。

缺点:

  • 对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。
  • 执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。

6.4 迭代器模式

迭代器模式 (Iterator Pattern):一个相对简单的模式,目前绝大多数语言都内置了迭代器,以至于大家都不觉得这是一种设计模式。迭代器并不只迭代数组,迭代器可以中止。提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标 (Cursor)。迭代器模式是一种对象行为型模式。

举例:

迭代器帮助请求方获取数据,避免直接操作数据聚合类,使数据聚合类专注存储数据。具体应用有分页等功能,分页功能的迭代器将专门负责操作分页数据,将操作逻辑和数据源分离。

js
var each = function (arr, callback) {
+  for (var i = 0, len = arr.length; i < len; i++) {
+    callback.call(arr[i], i, arr[i]);
+  }
+};
+
+each([1, 2, 3, 4, 5], function (i, el) {
+  console.log('index: ', i);
+  console.log('item: ', el);
+});

优点:

  • 它支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法,我们也可以自己定义迭代器的子类以支持新的遍历方式。
  • 迭代器简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计。
  • 在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”的要求。

缺点:

  • 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
  • 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展,例如 JDK 内置迭代器 Iterator 就无法实现逆向遍历,如果需要实现逆向遍历,只能通过其子类 ListIterator 等来实现,而 ListIterator 迭代器无法用于操作 Set 类型的聚合对象。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是件很容易的事情。

6.5 中介者模式

中介者模式(Mediator Pattern):对象和对象之间借助第三方中介者进行通信。用一个中介对象(中介者)来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。

举例:

中介者模式将一个网状的系统结构变成一个以中介者对象为中心的星形结构,在这个星型结构中,使用中介者对象与其他对象的一对多关系来取代原有对象之间的多对多关系。所有成员通过中介者交互,方便拓展新的成员,例如下面的例子,一场测试结束后,公布结果:告知解答出题目的人挑战成功,否则挑战失败。在这段代码中 A、B、C 之间没有直接发生关系,而是通过另外的 playerMiddle 对象建立链接,姑且将之当成是中介者模式了。

js
const player = function (name) {
+  this.name = name;
+  playerMiddle.add(name);
+};
+player.prototype.win = function () {
+  playerMiddle.win(this.name);
+};
+player.prototype.lose = function () {
+  playerMiddle.lose(this.name);
+};
+const playerMiddle = (function () {
+  //将就用下这个 demo, 这个函数充当中介者
+  const players = [];
+  const winArr = [];
+  const loseArr = [];
+  return {
+    add: function (name) {
+      players.push(name);
+    },
+    win: function (name) {
+      winArr.push(name);
+      if (winArr.length + loseArr.length === players.length) {
+        this.show();
+      }
+    },
+    lose: function (name) {
+      loseArr.push(name);
+      if (winArr.length + loseArr.length === players.length) {
+        this.show();
+      }
+    },
+    show: function () {
+      for (let winner of winArr) {
+        console.log(winner + '挑戰成功;');
+      }
+      for (let loser of loseArr) {
+        console.log(loser + '挑战失败;');
+      }
+    },
+  };
+})();
+const a = new player('A 选手');
+const b = new player('B 选手');
+const c = new player('C 选手');
+a.win();
+b.lose();
+c.win();
+// A 选手挑战成功;
+// B 选手挑战成功;
+// C 选手挑战失败;

优点:

  • 中介者模式简化了对象之间的交互,它用中介者和同事的一对多交互代替了原来同事之间的多对多交互,一对多关系更容易理解、维护和扩展,将原本难以理解的网状结构转换成相对简单的星型结构。
  • 中介者模式可将各同事对象解耦。中介者有利于各同事之间的松耦合,我们可以独立的改变和复用每一个同事和中介者,增加新的中介者和新的同事类都比较方便,更好地符合“开闭原则”。
  • 可以减少子类生成,中介者将原本分布于多个对象间的行为集中在一起,改变这些行为只需生成新的中介者子类即可,这使各个同事类可被重用,无须对同事类进行扩展。

缺点:

  • 在具体中介者类中包含了大量同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。

6.6 备忘录模式

备忘录模式 (Memento Pattern):在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便日后对象使用或者对象恢复到以前的某个状态。它是一种对象行为型模式,其别名为 Token。

举例:

备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,当前很多软件都提供了撤销操作,其中就使用了备忘录模式。

当我们开发一个分页组件的时候,点击下一页获取新的数据,但是当点击上一页时,又重新获取数据,造成无谓的流量浪费,这时可以对数据进行缓存。

js
// 备忘录模式伪代码
+var Page = function () {
+  // 通过 cache 对象缓存数据
+  var cache = {};
+  return function (page, fn) {
+    if (cache[page]) {
+      showPage(page, cache[page]);
+    } else {
+      $.post('/url', function (data) {
+        showPage(page, data);
+        cache[page] = data;
+      });
+    }
+    fn && fn();
+  };
+};

优点:

  • 它提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原。
  • 备忘录实现了对信息的封装,一个备忘录对象是一种原发器对象状态的表示,不会被其他代码所改动。备忘录保存了原发器的状态,采用列表、堆栈等集合来存储备忘录对象可以实现多次撤销操作。

缺点:

  • 资源消耗过大,如果需要保存的原发器类的成员变量太多,就不可避免需要占用大量的存储空间,每保存一次对象的状态都需要消耗一定的系统资源。

6.7 观察者模式

观察者模式 (Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布 - 订阅(Publish/Subscribe)模式、模型 - 视图(Model/View)模式、源 - 监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。

举例:

观察者模式是使用频率最高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。

JavaScript中观察者模式的实现主要用事件模型,DOM事件。

js
// 发布者
+var pub = function () {
+  console.log('欢迎订阅!');
+};
+// 订阅者
+var sub = document.body;
+
+// 订阅者实现订阅
+sub.addEventListener('click', pub, false);

优点:

  • 观察者模式可以实现表示层和数据逻辑层的分离,定义了稳定的消息更新传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层充当具体观察者角色。
  • 观察者模式在观察目标和观察者之间建立一个抽象的耦合。观察目标只需要维持一个抽象观察者的集合,无须了解其具体观察者。由于观察目标和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
  • 观察者模式支持广播通信,观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
  • 观察者模式满足“开闭原则”的要求,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便。

缺点:

  • 如果一个观察目标对象有很多直接和间接观察者,将所有的观察者都通知到会花费很多时间。
  • 如果在观察者和观察目标之间存在循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
  • 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

6.8 状态模式

状态模式 (State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象 (Objects for States),其实就是用一个对象或者数组记录一组状态,每个状态对应一个实现,实现的时候根据状态挨个去运行实现。状态模式是一种对象行为型模式。

举例:

状态模式用于解决复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,所以对象在不同状态下具有不同行为时可以使用状态模式。状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化。

比如超级玛丽,就可能同时有好几个状态比如 跳跃,移动,射击,蹲下 等,如果对这些动作一个个进行处理判断,需要多个 if-else 或者 switch 不仅丑陋不说,而且在遇到有组合动作的时候,实现就会变的更为复杂,这里可以使用状态模式来实现。

状态模式的思路是:首先创建一个状态对象或者数组,内部保存状态变量,然后内部封装好每种动作对应的状态,然后状态对象返回一个接口对象,它可以对内部的状态修改或者调用。

js
class SuperMarry {
+  constructor() {
+    this._currentState = [];
+    this.states = {
+      jump() {
+        console.log('跳跃!');
+      },
+      move() {
+        console.log('移动!');
+      },
+      shoot() {
+        console.log('射击!');
+      },
+      squat() {
+        console.log('蹲下!');
+      },
+    };
+  }
+
+  change(arr) {
+    // 更改当前动作
+    this._currentState = arr;
+    return this;
+  }
+
+  go() {
+    console.log('触发动作');
+    this._currentState.forEach((T) => this.states[T] && this.states[T]());
+    return this;
+  }
+}
+
+new SuperMarry()
+  .change(['jump', 'shoot'])
+  .go() // 触发动作  跳跃!射击!
+  .go() // 触发动作  跳跃!射击!
+  .change(['squat'])
+  .go(); // 触发动作  蹲下!

优点:

  • 封装了状态的转换规则,在状态模式中可以将状态的转换代码封装在环境类或者具体状态类中,可以对状态转换代码进行集中管理,而不是分散在一个个业务方法中。
  • 将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。
  • 允许状态转换逻辑与状态对象合成一体,而不是提供一个巨大的条件语句块,状态模式可以让我们避免使用庞大的条件语句来将业务方法和状态转换代码交织在一起。
  • 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点:

  • 状态模式的使用必然会增加系统中类和对象的个数,导致系统运行开销增大。
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,增加系统设计的难度。
  • 状态模式对“开闭原则”的支持并不太好,增加新的状态类需要修改那些负责状态转换的源代码,否则无法转换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

6.9 策略模式

策略模式 (Strategy Pattern):定义一些列算法,把他们封装起来,并且可以相互替换。就是把看似毫无联系的代码提取封装、复用,使之更容易被理解和拓展。常见的用于一次 if 判断、switch 枚举、数据字典等流程判断语句中。也称为政策模式 (Policy)。策略模式是一种对象行为型模式。

举例:

使用策略模式时,我们可以定义一些策略类,每一个策略类中封装一种具体的算法。在这里,每一个封装算法的类我们都可以称之为一种策略,根据传入不同的策略类,使环境类执行不同策略类中的算法。

在游戏中,我们每玩完一局游戏都有对用户进行等级评价,比如 S 级 4 倍经验,A 级 3 倍经验,B 级 2 倍经验,其他 1 倍经验,用函数来表达如下:

js
// 改为策略模式 分成两个函数来写
+const strategy = {
+  S: function (experience) {
+    return 4 * experience;
+  },
+  A: function (experience) {
+    return 3 * experience;
+  },
+  B: function (experience) {
+    return 2 * experience;
+  },
+};
+// getExperience 可以复用
+function getExperience(strategy, level, experience) {
+  return level in strategy ? strategy[level](experience) : experience;
+}
+var s = getExperience(strategy, 'S', 100);
+var a = getExperience(strategy, 'A', 100);
+console.log(s, a); // 400 300
js
// 指令处理集合
+var compileUtil = {
+    // v-text 更新视图原理
+    text: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'text');
+    },
+    // v-html 更新视图原理
+    html: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'html');
+    },
+    // v-class 绑定原理
+    class: function(node, vm, exp) {
+        this.bind(node, vm, exp, 'class');
+    },
+    bind: function(node, vm, exp, dir) {
+        // 不同指令触发视图更新
+        var updaterFn = updater[dir + 'Updater'];
+        updaterFn && updaterFn(node, this._getVMVal(vm, exp));
+        new Watcher(vm, exp, function(value, oldValue) {
+            updaterFn && updaterFn(node, value, oldValue);
+        });
+    }
+    ......
+}

优点:

  • 策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
  • 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族,恰当使用继承可以把公共的代码移到抽象策略类中,从而避免重复的代码。
  • 策略模式提供了一种可以替换继承关系的办法。如果不使用策略模式,那么使用算法的环境类就可能会有一些子类,每一个子类提供一种不同的算法。但是,这样一来算法的使用就和算法本身混在一起,不符合“单一职责原则”,决定使用哪一种算法的逻辑和该算法本身混合在一起,从而不可能再独立演化;而且使用继承无法实现算法或行为在程序运行时的动态切换。
  • 使用策略模式可以避免多重条件选择语句。多重条件选择语句不易维护,它把采取哪一种算法或行为的逻辑与算法或行为本身的实现逻辑混合在一起,将它们全部硬编码 (Hard Coding) 在一个庞大的多重条件选择语句中,比直接继承环境类的办法还要原始和落后。
  • 策略模式提供了一种算法的复用机制,由于将算法单独提取出来封装在策略类中,因此不同的环境类可以方便地复用这些策略类。

缺点:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
  • 策略模式将造成系统产生很多具体策略类,任何细小的变化都将导致系统要增加一个新的具体策略类。
  • 无法同时在客户端使用多个策略类,也就是说,在使用策略模式时,客户端每次只能使用一个策略类,不支持使用一个策略类完成部分功能后再使用另一个策略类来完成剩余功能的情况。

6.10 模板方法模式

模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

举例:

模板方法模式的使用场景

  • 模板方法模式常被架构师用于搭建项目的框架,架构师定好了框架的骨架,程序员继承框架的结构之后,负责往里面填空
  • 钩子方法:各种框架中的钩子函数往往在初始化时就规定各个钩子函数的名称以及执行时机,对于使用者只需要在钩子函数中注入自定义逻辑代码即可
  • 回调函数:回调函数在特定的时机执行,但是具体的操作交给具体的函数实现。把变化的部分封装成一个函数剩下的就成了模板

模板方法模式具体应用又分为三类:

  • 抽象方法:一个抽象方法由抽象类声明、由其具体子类实现。

  • 具体方法:一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。

  • 钩子方法:一个钩子方法由一个抽象类或具体类声明并实现,而其子类可能会加以扩展。通常在父类中给出的实现是一个空实现,并以该空实现作为方法的默认实现,当然钩子方法也可以提供一个非空的默认实现。通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制。

泡一杯咖啡

先我们先来泡一杯咖啡,一般来说,泡咖啡的步骤通常如下:

1.先把水煮沸;

2.用沸水冲泡咖啡;

3.把咖啡倒进杯子;

4.加糖和牛奶。

我们用 es5 来得到一杯香浓的咖啡吧:

js
var Coffee = function () {};
+Coffee.prototype.boilWater = function () {
+  console.log('水煮开了');
+};
+Coffee.prototype.brewCoffeeGriends = function () {
+  console.log('用沸水冲泡咖啡');
+};
+Coffee.prototype.pourInCup = function () {
+  console.log('把咖啡倒进杯子');
+};
+Coffee.prototype.addSugarAndMilk = function () {
+  console.log('加糖和牛奶');
+};
+// 封装 将实现的细节交给类的内部
+Coffee.prototype.init = function () {
+  this.boilWater();
+  this.brewCoffeeGriends();
+  this.pourInCup();
+  this.addSugarAndMilk();
+};
+var coffee = new Coffee();
+coffee.init();

泡一壶茶

其实呢,泡茶的步骤跟泡咖啡的步骤相差不大,大致是这样的:

1.把水煮沸;

2.用沸水浸泡茶叶;

3.把茶水倒进杯子;

4.加柠檬。

来,咱用 es6 来泡茶:

js
class Tea {
+  constructor() {}
+  boilWater() {
+    console.log('把水烧开');
+  }
+  steepTeaBag() {
+    console.log('浸泡茶叶');
+  }
+  pourInCup() {
+    console.log('倒进杯子');
+  }
+  addLemon() {
+    console.log('加柠檬');
+  }
+  init() {
+    this.boilWater();
+    this.steepTeaBag();
+    this.pourInCup();
+    this.addLemon();
+  }
+}
+var tea = new Tea();
+tea.init();

现在到了思考的时间,我们刚刚泡了一杯咖啡和一壶茶,有没有觉得这两个过程是大同小异的。我们能很容易的就找出他们的共同点,不同点就是原料不同嘛,茶和咖啡,我们可以把他们抽象为"饮料"哇;泡的方式不同嘛,一个是冲泡,一个是浸泡,我们可以把这个行为抽象为"泡";加入的调料也不同咯,加糖和牛奶,加柠檬,它们也可以抽象为"调料"吖。

这么一分析,是不是很清楚了吖,我们整理一下就是:

1.把水煮沸;

2.用沸水冲泡饮料;

3.把饮料倒进杯子;

4.加调料。

大家请注意!大家请注意!主角来了!之前我们已经扔出了概念,所以我们现在可以创建一个抽象父类来表示泡一杯饮料的过程。那么,抽象父类?

抽象类?

抽象类是不能被实例化的,一定是用来继承的。继承了抽象类的所有子类都将拥有跟抽象类一致的接口方法,抽象类的主要作用就是为它的子类定义这些公共接口。

通过上面分析,这里具体来说就是要把泡茶和泡咖啡的共同步骤共同点找出来,封装到父类,也就是抽象类中,然后不同的步骤写在子类中,也就是茶和咖啡中。抽象类既然不能被实例化,不怕啊,子类就是他的实例化。

泡饮料啦!

js
var Beverage = function () {};
+Beverage.prototype.boilWater = function () {
+  console.log('把水煮沸');
+};
+Beverage.prototype.brew = function () {};
+Beverage.prototype.pourInCup = function () {};
+Beverage.prototype.addCondiments = function () {};
+// 抽象方法
+Beverage.prototype.init = function () {
+  this.boilWater();
+  this.brew();
+  this.pourInCup();
+  this.addCondiments();
+};
+var Coffee = function () {
+  // 将父类的构造方法拿来执行一下
+  Beverage.apply(this, arguments);
+  // 就像 es6 的 super 执行 执行后 this 才会有对象的属性
+};
+Coffee.prototype = new Beverage();
+var coffee = new Coffee();
+coffee.init();
+var Tea = function () {};
+Tea.prototype = new Beverage();
+Tea.prototype.brew = function () {
+  console.log('用沸水浸泡茶叶');
+};
+Tea.prototype.pourInCup = function () {
+  console.log('把茶叶倒进杯子');
+};
+Tea.prototype.addCondiments = function () {
+  console.log('加柠檬');
+};
+var tea = new Tea();
+tea.init();

这里既泡了咖啡又泡了茶,是不是没有之前那么繁琐呢,这里的代码可是很高级的呢。

这里用一个父类 Beverage 来表示 Coffee 和 Tea,然后子类就是后面的 Coffee 和 Tea 啦,因为这里的 Beverage 是一个抽象的存在,需要子类来继承它。泡饮品的流程,可以理解为一个模板模式,抽象类 Beverage,抽象方法 init() 在子类中实现。js 的继承是基于原型链的继承,这里 prototype 就是类的原型链。这里由于 coffee 对象和 tea 对象的原型 prototype 上都没有对应的 init(),所以请求会顺着原型链,找到父类 Beverage 的 init()。子类寻找对应的属性和方法的时候会顺着原型链去查找,先找自己,没有找到会顺着去父类里面查找。

Beverage.prototype.init 被称为模板方法的原因是,该方法中封装了子类的算法框架,它作为一个算法的模板,指导子类以何种顺序去执行哪些方法。

优点:

  • 在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。
  • 模板方法模式是一种代码复用技术,它在类库设计中尤为重要,它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为,它鼓励我们恰当使用继承来实现代码复用。
  • 可实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行。
  • 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则。

缺点:

  • 需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合桥接模式来进行设计。

6.11 访问者模式

访问者模式 (Visitor Pattern):提供一个作用于某对象结构中的各元素的操作表示,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。

举例:

访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。访问者模式使得用户可以在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作。

在使用访问者模式时,被访问元素通常不是单独存在的,它们存储在一个集合中,这个集合被称为「对象结构」,访问者通过遍历对象结构实现对其中存储的元素的逐个操作。

js
// 访问者模式:DOM 事件绑定
+var bindEvent = function(dom, type, fn, data) {
+    if (dom.addEventListener) {
+        dom.addEventListener(type, fn, false);
+    } else if (dom.attachEvent) {
+        // dom.attachEvent('on'+type, fn);
+        var data = data || {};
+        dom.attachEvent('on' + type, function(e) {
+            // 在 IE 中 this 指向 window,使用 call 改变 this 的指向
+            fn.call(dom, e, data);
+        });
+    } else {
+        dom['on' + type] = fn;
+    }
+}
+function $(id) {
+    return document.getElementById(id);
+}
+
+bindEvent($(demo), 'click', function() {
+    // this 指向 dom 对象
+    this.style.background = 'red';
+});
+
+bindEvent($('btn'), 'click', function(e, data) {
+    $('text').innerHTML = e.type + data.text + this.tagName;
+}, { text: 'demo' });

访问者模式的思想就是在不改变操作对象的同时,为它添加新的操作方法,以实现对操作对象的访问。我们知道,call 和 apply 的作用就是更改函数执行时的作用域,这正是访问者模式的精髓。通过 call、apply 这两种方式我们就可以让某个对象在其它作用域中运行。

js
// 数组方法封装
+var Visitor = (function() {
+    return {
+        splice: function() {
+            var args = Array.prototype.splice.call(arguments, 1);
+            return Array.prototype.splice.apply(arguments[0], args);
+        },
+        push: function() {
+            var len = arguments[0].length || 0;
+            var args = this.splice(arguments, 1);
+            arguments[0].length = len + arguments.length - 1;
+            return Array.prototype.push.apply(arguments[0], args);
+        },
+        pop: function() {
+            return Array.prototype.pop.apply(arguments[0]);
+        }
+    }
+})();
+
+var a = new Object();
+Visitor.push(a,1,2,3,4);
+Visitor.push(a,4,5,6);
+Visitor.pop(a);
+Visitor.splice(a,2);

访问者模式解决了数据与数据的操作方法之间的耦合,让数据的操作方法独立于数据,使其可以自由演变。因此,访问者模式更适合于那些数据稳定、但数据的操作方法易变的环境下。

优点:

  • 增加新的访问操作很方便。使用访问者模式,增加新的访问操作就意味着增加一个新的具体访问者类,实现简单,无须修改源代码,符合“开闭原则”。
  • 将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中。类的职责更加清晰,有利于对象结构中元素对象的复用,相同的对象结构可以供多个不同的访问者访问。
  • 让用户能够在不修改现有元素类层次结构的情况下,定义作用于该层次结构的操作。

缺点:

  • 增加新的元素类很困难。在访问者模式中,每增加一个新的元素类都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”的要求。
  • 破坏封装。访问者模式要求访问者对象访问并调用每一个元素对象的操作,这意味着元素对象有时候必须暴露一些自己的内部操作和内部状态,否则无法供访问者访问。

总结

系统地学习设计模式后,你可以在过往的开发经历中发现,设计模式是无处不在的。在学习设计模式之前的很多时候我们是凭借过往经验和智慧来完善系统的设计,而这些经验很多和某个设计模式的思想不谋而合。

还有一些地方没有完全理解,文中有误之处还望不吝指出。

参考资料

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/docPreview.html b/cn/src/article/docPreview.html new file mode 100644 index 0000000000..73d8b6b675 --- /dev/null +++ b/cn/src/article/docPreview.html @@ -0,0 +1,311 @@ + + + + + + ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

最全的 docx,pptx,xlsx(excel),pdf 文件预览方案总结

最近遇到了文件预览的需求,但一搜索发现,这还不是一个简单的功能。于是又去查询了很多资料,调研了一些方案,也踩了好多坑。最后总结方案如下

  1. 花钱解决 (使用市面上现有的文件预览服务)
    1. 微软
    2. google
    3. 阿里云 IMM
    4. XDOC
    5. Office Web 365
    6. wps 开放平台
  2. 前端方案
    1. pptx 的预览方案
    2. pdf 的预览方案
    3. docx 的预览方案
    4. xlsx(excel) 的预览方案
    5. 前端预览方案总结
  3. 服务端方案
    1. openOffice
    2. kkFileView
    3. onlyOffice

如果有其他人也遇到了同样的问题,有了这篇文章,希望能更方便的解决。

基本涵盖了所有解决方案。因此,标题写上 最全 的文件预览方案调研总结,应该不为过吧。

一:市面上现有的文件预览服务

1.微软

docx,pptx,xlsx可以说是office三件套,那自然得看一下 微软官方 提供的文件预览服务。使用方法特别简单,只需要将文件链接,拼接到参数后面即可。

记得encodeURL

js
https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}

(1).PPTX 预览效果:

image.png

  • 优点:还原度很高,功能很丰富,可以选择翻页,甚至支持点击播放动画。
  • 缺点:不知道是不是墙的原因,加载稍慢。

(2).Excel 预览效果:

image.png

(3).Doxc 预览效果

image.png

(4).PDF 预览效果

这个我测试没有成功,返回了一个错误,其他人可以试试。

image.png

(5).总的来说

对于docx,pptx,xlsx都有较好的支持,pdf不行。

还有一个坑点是:这个服务是否稳定,有什么限制,是否收费,都查不到一个定论。在office官方网站上甚至找不到介绍这个东西的地方。

目前只能找到一个Q&A:https://answers.microsoft.com/en-us/msoffice/forum/all/what-is-the-status-of-viewofficeappslivecom/830fd75c-9b47-43f9-89c9-4303703fd7f6

微软官方人员回答表示:

image.png

翻译翻译,就是:几乎永久使用,没有收费计划,不会存储预览的文件数据,限制文件10MB,建议用于 查看互联网上公开的文件

但经过某些用户测试发现:

image.png

使用了微软的文件预览服务,然后删除了文件地址,仍然可访问,但过一段时间会失效。

2.Google Drive 查看器

接入简单,同 Office Web Viewer,只需要把 src 改为https://drive.google.com/viewer?url=${encodeURIComponent(url)}即可。

限制25MB,支持以下格式:

image.png

测试效果,支持docx,pptx,xlsx,pdf预览,但pptx预览的效果不如微软,没有动画效果,样式有小部分会错乱。

由于某些众所周知的原因,不可用

3.阿里云 IMM

官方文档如下:https://help.aliyun.com/document_detail/63273.html

image.png

付费使用

4.XDOC 文档预览

说了一些大厂的,在介绍一些其他的,需要自行分辨

官网地址:https://view.xdocin.com/view-xdocin-com_6x5f4x.htm

image.png

5.Office Web 365

需要注意的是,虽然名字很像office,但我们看网页的Copyright可以发现,其实是一个西安的公司,不是微软

但毕竟也提供了文件预览的服务

官网地址:https://www.officeweb365.com/

image.png

6.WPS 开放平台

官方地址:https://solution.wps.cn/

image.png

付费使用,价格如下:

image.png

二:前端处理方案

1.pptx 的预览方案

先查一下有没有现成的轮子,目前pptx的开源预览方案能找到的只有这个:https://github.com/g21589/PPTX2HTML。但已经六七年没有更新,也没有维护,笔者使用的时候发现有很多兼容性问题。

简单来说就是,没有。对于这种情况,我们可以自行解析,主要步骤如下:

  1. 查询pptx的国际标准
  2. 解析pptx文件
  3. 渲染成html或者canvas进行展示

我们先去找一下pptx的国际标准,官方地址:officeopenxml

先解释下什么是officeopenxml:

Office OpenXML,也称为 OpenXML 或 OOXML,是一种基于 XML 的办公文档格式,包括文字处理文档、电子表格、演示文稿以及图表、图表、形状和其他图形材料。该规范由微软开发,并于 2006 年被 ECMA 国际采用为 ECMA-376。第二个版本于 2008 年 12 月发布,第三个版本于 2011 年 6 月发布。该规范已被 ISO 和 IEC 采用为 ISO/IEC 29500。

虽然 Microsoft 继续支持较旧的二进制格式 (.doc、.xls 和.ppt),但 OOXML 现在是所有 Microsoft Office 文档 (.docx、.xlsx 和.pptx) 的默认格式。

由此可见,Office OpenXML由微软开发,目前已经是国际标准。接下来我们看一下pptx里面有哪些内容,具体可以看pptx的官方标准:officeopenxml-pptx

PresentationML 或.pptx 文件是一个zip 文件,其中包含许多“部分”(通常是 UTF-8 或 UTF-16 编码)或 XML 文件。该包还可能包含其他媒体文件,例如图像。该结构根据 OOXML 标准 ECMA-376 第 2 部分中概述的开放打包约定进行组织。

image.png

根据国际标准,我们知道,pptx文件本质就是一个zip文件,其中包含许多部分:

部件的数量和类型将根据演示文稿中的内容而有所不同,但始终会有一个 [Content_Types].xml、一个或多个关系(.rels)部件和一个演示文稿部件(演示文稿.xml),它位于 ppt 文件夹中,用于 Microsoft Powerpoint 文件。通常,还将至少有一个幻灯片部件,以及一张母版幻灯片和一张版式幻灯片,从中形成幻灯片。

那么js如何读取zip呢?

找到一个工具:https://www.npmjs.com/package/jszip

于是我们可以开始尝试解析pptx了。

ts
import JSZip from 'jszip';
+// 加载 pptx 数据
+const zip = await JSZip.loadAsync(pptxData);
  • 解析[Content_Types].xml

每个pptx必然会有一个 [Content_Types].xml。此文件包含包中部件的所有内容类型的列表。每个部件及其类型都必须列在 [Content_Types].xml 中。通过它里面的内容,可以解析其他的文件数据

ts
const filesInfo = await getContentTypes(zip);
+
+async function getContentTypes(zip: JSZip) {
+  const ContentTypesJson = await readXmlFile(zip, '[Content_Types].xml');
+  const subObj = ContentTypesJson['Types']['Override'];
+  const slidesLocArray = [];
+  const slideLayoutsLocArray = [];
+  for (let i = 0; i < subObj.length; i++) {
+    switch (subObj[i]['attrs']['ContentType']) {
+      case 'application/vnd.openxmlformats-officedocument.presentationml.slide+xml':
+        slidesLocArray.push(subObj[i]['attrs']['PartName'].substr(1));
+        break;
+      case 'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml':
+        slideLayoutsLocArray.push(subObj[i]['attrs']['PartName'].substr(1));
+        break;
+      default:
+    }
+  }
+  return {
+    slides: slidesLocArray,
+    slideLayouts: slideLayoutsLocArray,
+  };
+}
  • 解析演示文稿

先获取ppt目录下的presentation.xml演示文稿的大小

由于演示文稿是xml格式,要真正的读取内容需要执行 readXmlFile

ts
const slideSize = await getSlideSize(zip);
+async function getSlideSize(zip: JSZip) {
+  const content = await readXmlFile(zip, 'ppt/presentation.xml');
+  const sldSzAttrs = content['p:presentation']['p:sldSz']['attrs'];
+  return {
+    width: (parseInt(sldSzAttrs['cx']) * 96) / 914400,
+    height: (parseInt(sldSzAttrs['cy']) * 96) / 914400,
+  };
+}
  • 加载主题

根据 officeopenxml的标准解释

每个包都包含一个关系部件,用于定义其他部件之间的关系以及与包外部资源的关系。这样可以将关系与内容分开,并且可以轻松地更改关系,而无需更改引用目标的源。

除了包的关系部分之外,作为一个或多个关系源的每个部件都有自己的关系部分。每个这样的关系部件都可以在部件的_rels 子文件夹中找到,并通过在部件名称后附加“.rels”来命名。

其中主题的相关信息就在ppt/_rels/presentation.xml.rels

ts
async function loadTheme(zip: JSZip) {
+  const preResContent = await readXmlFile(zip, 'ppt/_rels/presentation.xml.rels');
+  const relationshipArray = preResContent['Relationships']['Relationship'];
+  let themeURI;
+  if (relationshipArray.constructor === Array) {
+    for (let i = 0; i < relationshipArray.length; i++) {
+      if (
+        relationshipArray[i]['attrs']['Type'] ===
+        'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme'
+      ) {
+        themeURI = relationshipArray[i]['attrs']['Target'];
+        break;
+      }
+    }
+  } else if (
+    relationshipArray['attrs']['Type'] === 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme'
+  ) {
+    themeURI = relationshipArray['attrs']['Target'];
+  }
+
+  if (themeURI === undefined) {
+    throw Error("Can't open theme file.");
+  }
+
+  return readXmlFile(zip, 'ppt/' + themeURI);
+}

后续ppt里面的其他内容,都可以这么去解析。根据officeopenxml标准,可能包含:

PartDescription
Comments AuthorsContains information about each author who has added a comment to the presentation.
CommentsContains comments for a single slide.
Handout MasterContains the look, position, and size of the slides, notes, header and footer text, date, or page number on the presentation's handout. There can be only one such part.
Notes MasterContains information about the content and formatting of all notes pages. There can be only one such part.
Notes SlideContains the notes for a single slide.
PresentationContains the definition of a slide presentation. There must be one and only one such part. See Presentation.
Presentation PropertiesContains all of the presentation's properties. There must be one and only one such part.
SlideContains the content of a single slide.
Slide LayoutContains the definition for a slide template. It defines the default appearance and positioning of drawing objects on the slide. There must be one or more such parts.
Slide MasterContains the master definition of formatting, text, and objects that appear on each slide in the presentation that is derived from the slide master. There must be one or more such parts.
Slide Synchronization DataContains properties specifying the current state of a slide that is being synchronized with a version of the slide stored on a central server.
User-Defined TagsContains a set of user-defined properties for an object in a presentation. There can be zero or more such parts.
View PropertiesContains display properties for the presentation.

等等内容,我们根据标准一点点解析并渲染就好了。

完整源码:ranui

使用文档:preview 组件

2.pdf 的预览方案

(1).iframe 和 embed

pdf比较特别,一般的浏览器默认支持预览pdf。因此,我们可以使用浏览器的能力:

html
<iframe src="viewFileUrl" />

但这样就完全依赖浏览器,对PDF的展示,交互,是否支持全看浏览器的能力,且不同的浏览器展示和交互往往不同,如果需要统一的话,最好还是尝试其他方案。

embed的解析方式也是一样,这里不举例子了

(2)pdfjs

npm: https://www.npmjs.com/package/pdfjs-dist

github 地址:https://github.com/mozilla/pdfjs-dist

mozilla出品,就是我们常见的MDN的老大。

而且目前 火狐浏览器 使用的 PDF 预览就是采用这个,我们可以用火狐浏览器打开pdf文件,查看浏览器使用的js就能发现

image.png

需要注意的是,最新版pdf.js限制了node版本,需要大于等于18

github 链接:https://github.com/mozilla/pdf.js/blob/master/package.json

image.png

如果你项目node版本小于这个情况,可能会无法使用。

如果遇到这种情况,可以用以前版本,以前的版本没有限制。

具体使用情况如下:

ts
import * as pdfjs from 'pdfjs-dist';
+import * as pdfjsWorker from 'pdfjs-dist/build/pdf.work.entry';
+
+interface Viewport {
+  width: number;
+  height: number;
+  viewBox: Array<number>;
+}
+
+interface RenderContext {
+  canvasContext: CanvasRenderingContext2D | null;
+  transform: Array<number>;
+  viewport: Viewport;
+}
+
+interface PDFPageProxy {
+  pageNumber: number;
+  getViewport: () => Viewport;
+  render: (options: RenderContext) => void;
+}
+
+interface PDFDocumentProxy {
+  numPages: number;
+  getPage: (x: number) => Promise<PDFPageProxy>;
+}
+
+class PdfPreview {
+  private pdfDoc: PDFDocumentProxy | undefined;
+  pageNumber: number;
+  total: number;
+  dom: HTMLElement;
+  pdf: string | ArrayBuffer;
+  constructor(pdf: string | ArrayBuffer, dom: HTMLElement | undefined) {
+    this.pageNumber = 1;
+    this.total = 0;
+    this.pdfDoc = undefined;
+    this.pdf = pdf;
+    this.dom = dom ? dom : document.body;
+  }
+  private getPdfPage = (number: number) => {
+    return new Promise((resolve, reject) => {
+      if (this.pdfDoc) {
+        this.pdfDoc.getPage(number).then((page: PDFPageProxy) => {
+          const viewport = page.getViewport();
+          const canvas = document.createElement('canvas');
+          this.dom.appendChild(canvas);
+          const context = canvas.getContext('2d');
+          const [_, __, width, height] = viewport.viewBox;
+          canvas.width = width;
+          canvas.height = height;
+          viewport.width = width;
+          viewport.height = height;
+          canvas.style.width = Math.floor(viewport.width) + 'px';
+          canvas.style.height = Math.floor(viewport.height) + 'px';
+          const renderContext = {
+            canvasContext: context,
+            viewport: viewport,
+            transform: [1, 0, 0, -1, 0, viewport.height],
+          };
+          page.render(renderContext);
+          resolve({ success: true, data: page });
+        });
+      } else {
+        reject({ success: false, data: null, message: 'pdfDoc is undefined' });
+      }
+    });
+  };
+  pdfPreview = () => {
+    window.pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;
+    window.pdfjsLib.getDocument(this.pdf).promise.then(async (doc: PDFDocumentProxy) => {
+      this.pdfDoc = doc;
+      this.total = doc.numPages;
+      for (let i = 1; i <= this.total; i++) {
+        await this.getPdfPage(i);
+      }
+    });
+  };
+  prevPage = () => {
+    if (this.pageNumber > 1) {
+      this.pageNumber -= 1;
+    } else {
+      this.pageNumber = 1;
+    }
+    this.getPdfPage(this.pageNumber);
+  };
+  nextPage = () => {
+    if (this.pageNumber < this.total) {
+      this.pageNumber += 1;
+    } else {
+      this.pageNumber = this.total;
+    }
+    this.getPdfPage(this.pageNumber);
+  };
+}
+
+const createReader = (file: File): Promise<string | ArrayBuffer | null> => {
+  return new Promise((resolve, reject) => {
+    const reader = new FileReader();
+    reader.readAsDataURL(file);
+    reader.onload = () => {
+      resolve(reader.result);
+    };
+    reader.onerror = (error) => {
+      reject(error);
+    };
+    reader.onabort = (abort) => {
+      reject(abort);
+    };
+  });
+};
+
+export const renderPdf = async (file: File, dom?: HTMLElement): Promise<void> => {
+  try {
+    if (typeof window !== 'undefined') {
+      const pdf = await createReader(file);
+      if (pdf) {
+        const PDF = new PdfPreview(pdf, dom);
+        PDF.pdfPreview();
+      }
+    }
+  } catch (error) {
+    console.log('renderPdf', error);
+  }
+};

3.docx 的预览方案

我们可以去查看docx的国际标准,去解析文件格式,渲染成htmlcanvas,不过比较好的是,已经有人这么做了,还开源了

npm地址:https://www.npmjs.com/package/docx-preview

使用方法如下:

ts
import { renderAsync } from 'docx-preview';
+
+interface DocxOptions {
+  bodyContainer?: HTMLElement | null;
+  styleContainer?: HTMLElement;
+  buffer: Blob;
+  docxOptions?: Partial<Record<string, string | boolean>>;
+}
+
+export const renderDocx = (options: DocxOptions): Promise<void> | undefined => {
+  if (typeof window !== 'undefined') {
+    const { bodyContainer, styleContainer, buffer, docxOptions = {} } = options;
+    const defaultOptions = {
+      className: 'docx',
+      ignoreLastRenderedPageBreak: false,
+    };
+    const configuration = Object.assign({}, defaultOptions, docxOptions);
+    if (bodyContainer) {
+      return renderAsync(buffer, bodyContainer, styleContainer, configuration);
+    } else {
+      const contain = document.createElement('div');
+      document.body.appendChild(contain);
+      return renderAsync(buffer, contain, styleContainer, configuration);
+    }
+  }
+};

4.xlsx 的预览方案

我们可以使用这个:

npm地址:https://www.npmjs.com/package/@vue-office/excel

支持vue2vue3,也有js的版本

对于xlsx的预览方案,这个是找到最好用的了。

5.前端预览方案总结

我们对以上找到的优秀的解决方案,进行改进和总结,并封装成一个web components组件:preview 组件

为什么是web components组件?

因为它跟框架无关,可以在任何框架中使用,且使用起来跟原生的div标签一样方便。

并编写使用文档:preview 组件文档, 文档支持交互体验。

源码公开,MIT协议。

目前docx,pdf,xlsx预览基本可以了,都是最好的方案。pptx预览效果不太好,因为需要自行解析。不过源码完全公开,需要的可以提issuepr或者干脆自取或修改,源码地址:https://github.com/chaxus/ran/tree/main/packages/ranui

三:服务端预览方案

1.openOffice

由于浏览器不能直接打开docx,pptx,xlsx等格式文件,但可以直接打开pdf和图片。因此,我们可以换一个思路,用服务端去转换下文件的格式,转换成浏览器能识别的格式,然后再让浏览器打开,这不就 OK 了吗,甚至不需要前端处理了。

我们可以借助openOffice的能力,先介绍一下openOffice:

Apache OpenOffice是领先的开源办公软件套件,用于文字处理,电子表格,演示文稿,图形,数据库等。它有多种语言版本,适用于所有常用计算机。它以国际开放标准格式存储您的所有数据,还可以从其他常见的办公软件包中读取和写入文件。它可以出于任何目的完全免费下载和使用。

官网如下:https://www.openoffice.org/

需要先下载opneOffice,找到bin目录,进行设置

java
configuration.setOfficeHome("这里的路径一般为 C:\\Program Files (x86)\\OpenOffice 4");

测试下转换的文件路径

java
    public static void main(String[] args) {
+        convertToPDF("/Users/Desktop/asdf.docx", "/Users/Desktop/adsf.pdf");
+    }

完整如下:

java

+package org.example;
+
+import org.artofsolving.jodconverter.OfficeDocumentConverter;
+import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
+import org.artofsolving.jodconverter.office.OfficeManager;
+
+import java.io.File;
+
+public class OfficeUtil {
+
+    private static OfficeManager officeManager;
+    private static int port[] = {8100};
+
+    /**
+     * start openOffice service.
+     */
+    public static void startService() {
+        DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();
+        try {
+            System.out.println("准备启动 office 转换服务....");
+            configuration.setOfficeHome("这里的路径一般为 C:\\Program Files (x86)\\OpenOffice 4");
+            configuration.setPortNumbers(port); // 设置转换端口,默认为 8100
+            configuration.setTaskExecutionTimeout(1000 * 60 * 30L);// 设置任务执行超时为 30 分钟
+            configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L);// 设置任务队列超时为 24 小时
+            officeManager = configuration.buildOfficeManager();
+            officeManager.start(); // 启动服务
+            System.out.println("office 转换服务启动成功!");
+        } catch (Exception e) {
+            System.out.println("office 转换服务启动失败!详细信息:" + e);
+        }
+    }
+
+    /**
+     * stop openOffice service.
+     */
+    public static void stopService() {
+        System.out.println("准备关闭 office 转换服务....");
+        if (officeManager != null) {
+            officeManager.stop();
+        }
+        System.out.println("office 转换服务关闭成功!");
+    }
+
+    public static void convertToPDF(String inputFile, String outputFile) {
+        startService();
+        System.out.println("进行文档转换转换:" + inputFile + " --> " + outputFile);
+        OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
+        converter.convert(new File(inputFile), new File(outputFile));
+        stopService();
+    }
+
+    public static void main(String[] args) {
+        convertToPDF("/Users/koolearn/Desktop/asdf.docx", "/Users/koolearn/Desktop/adsf.pdf");
+    }
+}

2.kkFileView

github地址:https://github.com/kekingcn/kkFileView

支持的文件预览格式非常丰富 image.png

接下来是 从零到一 的启动步骤,按着步骤来,任何人都能搞定

  1. 安装java:
sh
brew install java
  1. 安装maven,java的包管理工具:
sh
brew install mvn
  1. 检查是否安装成功

执行java --versionmvn -v。我这里遇到mvn找不到java home的报错。解决方式如下:

我用的是zsh,所以需要去.zshrc添加路径:

export JAVA_HOME=$(/usr/libexec/java_home)

添加完后,执行

source .zshrc
  1. 安装下libreoffice :

kkFileView明确要求的额外依赖,否则无法启动

brew install libreoffice
  1. mvn安装依赖

进入项目,在根目录执行依赖安装,同时清理缓存,跳过单测 (遇到了单测报错的问题)

mvn clean install -DskipTests
  1. 启动项目

找到主文件,主函数mian,点击vscode上面的Run即可执行,路径如下图

image.png

  1. 访问页面

启动完成后,点击终端输出的地址

image.png

  1. 最终结果

最终展示如下,可以添加链接进行预览,也可以选择本地文件进行预览

image.png

预览效果非常好

3.onlyOffice

官网地址:https://www.onlyoffice.com/zh

github地址:https://github.com/ONLYOFFICE

开发者版本和社区版免费,企业版付费:https://www.onlyoffice.com/zh/docs-enterprise-prices.aspx

预览的文件种类没有kkFileView多,但对office三件套有很好的支持,甚至支持多人编辑。

四:总结

  1. 外部服务,推荐微软的view.officeapps.live.com/op/view.aspx,但只建议预览一些互联网公开的文件,不建议使用在要求保密性和稳定性的文件。
  2. 对保密性和稳定性有要求,且不差钱的,可以试试大厂服务,阿里云解决方案。
  3. 服务端技术比较给力的,使用服务端预览方案。目前最好最全的效果是服务端预览方案。
  4. 不想花钱,没有服务器的,使用前端预览方案,客户端渲染零成本。

五:参考文档:

  1. 在 java 中如何使用 openOffice 进行格式转换
  2. MAC 搭建 OpenOffice 完整教程 - 保姆级
  3. 纯 js 实现 docx、xlsx、pdf 文件预览库,使用超简单
  4. 前端实现 word、excel、pdf、ppt、mp4、图片、文本等文件的预览

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/functionalProgramming.html b/cn/src/article/functionalProgramming.html new file mode 100644 index 0000000000..f3423a83f5 --- /dev/null +++ b/cn/src/article/functionalProgramming.html @@ -0,0 +1,386 @@ + + + + + + 函数式编程 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

函数式编程

  • 概述:函数式编程 (Functional Programming)FP就是编程规范之一,我们常听说的编程规范还有面向对象编程,面向过程编程。
  • 面向对象的编程思维方式:把现实世界中的事物抽象成程序世界的类和对象,通过封装,继承和多态演示事物事件的联系
  • 函数编程的思维方式:把现实世界的事物和事物之间的联系抽象到程序世界 (对运算过程进行抽象)
    • 程序的本质:根据输入,通过某种运算,获得相应的输出
    • 函数式编程中的函数不是指程序中的 (函数) 方法,而是数学中的函数,即映射关系
    • 相同的输入始终要得到相同的输出 (纯函数)
    • 函数式编程用来描述数据 (函数) 之间的映射关系
js
//非函数式编程,面向过程的编程方式
+let num1 = 1;
+let num2 = 2;
+let sum = num1 + num2;
+
+//函数式编程,对面向过程的抽象
+function sum(n1, n2) {
+  return n1 + n2;
+}
+let result = sum(1, 2);

一。JS函数基本知识

  • 函数可以储存在变量中
  • 函数可以作为参数
  • 函数可以作为返回值

JavaScript中,函数就是一个普通的对象,(可以通过new Function()),我们可以把函数存储到变量/数组中,它还可以作为另一个函数的参数和返回值,甚至我们还可以在程序运行的时候通过new Function('alert(1)')来构建一个新的函数

  • 把函数赋值给变量
js
let fn = function () {
+  console.log('First-class Function MDN');
+};

二。高阶函数

  • 高阶函数 (Higher-order function)
    • 可以把函数作为参数传递给另一个函数
    • 可以把函数作为另一个函数的返回结果
  1. 函数作为参数
js
//forEach
+function forEach(array, fn) {
+  for (let item of array) {
+    fn(item);
+  }
+}
+
+//filter
+function filter(array, fn) {
+  let result = [];
+  for (let item of array) {
+    if (fn(item)) {
+      result.push(item);
+    }
+  }
+  return result;
+}
+
+//测试
+let array = [1, 2, 3, 4, 5, 6, 7];
+forEach(array, function (item) {
+  console.log(item);
+});
+
+let r = filter(array, function (item) {
+  return item % 2 === 0;
+});
+console.log(r);
  1. 函数作为返回值
js
//高阶函数,函数作为返回值
+function makeFn() {
+  let msg = 'Highter-order Function';
+  return function () {
+    console.log(msg);
+  };
+}
+//第一种调用方式
+const fn = makeFn();
+fn();
+//第二种调用方式
+makeFn()();
+//once 只能执行一次的函数
+function once(fn) {
+  let done = false;
+  return function () {
+    if (!done) {
+      done = true;
+      return fn.apply(this, arguments);
+    }
+  };
+}
+let pay = once(function (money) {
+  console.log(`支付${money}`);
+});
+pay(5);
+pay(5);
+pay(5);
+pay(5);
+pay(5);

三。闭包

概述:有权访问另一个函数作用域中的变量的函数

本质:函数执行的时候会入栈,当执行完后会移除栈,但是堆上的作用域成员因为被外部引用而不能释放。因此内部函数依然可以访问外部函数的成员。

:栈会自动分配内存,会自动释放,存放基本数据类型,占据固定大小的空间。

栈的溢出:递归调用方法,随着栈的深度增加,直到内存不够分配,产生溢出。

栈的优势:所有方法中的变量都存在栈中,随着方法执行的结束,这个方法的内存栈也随之销毁,存取速度很快,仅次于 CPU 的寄存器,可以共享。

:动态分配内存,大小不定,也不会自动释放内存,不会随着方法的结束而销毁堆内存,存放引用数据类型,实际保存的不是变量本身,而是指向该对象的指针。

堆溢出:循环创建对象,就是不断的 new 对象

四。纯函数

  • 概念:相同的输入永远会得到相同的输出,而且没有任何可观察的副作用,类似数学中的函数y=f(x)
  • 例子:slice函数就是纯函数,对一个数组,相同的输入永远得到相同的输出,splice 就是非纯函数,相同的输入可能会得到不同的结果,因为会改变原数组
  • 函数式编程不会保留计算中间的结果,所以变量不可变 (无状态)
  • 可以把一个函数的执行结果交给另一个函数去执行
  • 纯函数可以缓存,因为相同的输入必然有相同的输出
js
//memoize 函数
+function memoize(fn) {
+  let cache = {};
+  return function () {
+    let key = JSON.stringfy(arguments);
+    cache[key] = cache[key] || fn.apply(fn, arguments);
+    return cache[key];
+  };
+}
  • 可测试,让测试更方便
  • 多线程环境下操作共享的内存数据可能会出现意外的情况,而纯函数不需要共享的数据空间,只和输入有关,所以并行环境下可以任意运行纯函数
  • 副作用,副作用会让纯函数变的不纯,比如依赖外部的状态,就无法保证输出相同,带来副作用,副作用来源:配置文件,数据库,获取用户的输入等等...所有的外部交互都可能带来副作用,副作用使得方法通用性下降,不适合扩展和重用,同时给程序带来安全隐患,副作用不可能完全禁止,只能尽可能的在控制范围内。
js
//不纯的函数
+let mini = 18;
+function checkAge(age) {
+  return age > min;
+}
+//纯函数 (有硬编码,后续可以通过柯里化来解决)
+function checkAge(age) {
+  let mini = 18;
+  return age > mini;
+}

五。柯里化 (Haskell Brooks Curry)

js
//解决上述硬编码的问题
+function checkAge(min) {
+  return function (age) {
+    return age >= min;
+  };
+}
+let checkAge18 = checkAge(18);
+checkAge18(22);

es6进行简化

js
let checkAge = (min) => (age) => age >= min;
  • 当一个函数有多个参数的时候,可以先传递一部分,先调用它,并返回一个函数 (这部分参数以后保持不变)
  • 然后返回一个新的函数接受剩下的参数,返回结果
  • lodash中的柯里化函数
    • _.curry(func)
    • 功能:创建一个函数,该函数接受一个或多个 func 的参数,如果该函数所有的参数都被传递,则返回函数的结果,否则,返回该函数并等待继续传递参数
    • 参数:需要柯里化的函数
    • 返回值:柯里化后的函数
js
//lodash 中的 curry 的使用
+const _ = require('loadsh');
+function getSum(a, b, c) {
+  return a + b + c;
+}
+const curried = _.curry(getSum);
+console.log(curried(1, 2, 3)); //6
+console.log(curried(1)(2, 3)); //6
+console.log(curried(1)(2)(3)); //6

实现一个 curry 函数

js
function curry(func) {
+  return function curriedFn(...args) {
+    if (args.length < func.length) {
+      return function () {
+        return curriedFn(...args.concat(Array.form(arguments)));
+      };
+    } else {
+      return func(...args);
+    }
+  };
+}
  • 总结:柯里化可以让我们给一个函数传递较少的参数,返回一个记住来某些固定参数的新函数,这是一种对函数参数的缓存,让函数变的更灵活,让函数的粒度更小。可以把多元函数转换成一元的函数,可以组合使用函数产生强大的功能。

六。函数的组合

  • 纯函数和柯里化很容易让我们写出洋葱代码,比如h(f(g(x)))
    • 获取数组的最后一个元素并转化为大写字母,_.toUpper(._first(_.revers(array)))
    • 函数的组合可以让我们把细粒度的函数,重新组合成一个新的函数
  • lodash中的组合函数
    • lodash中的组合函数flow()flowRight(),都可以组合多个函数
    • flow()是从左到右执行
    • flowRight()是从右到左执行
    • 自己实现一个flowRight函数:
js
function composeRight(...args) {
+  return function (value) {
+    args.reverse().reduce(function (acc, fn) {
+      return fn(acc);
+    }, value);
+  };
+}
+//箭头函数
+const compose =
+  (...args) =>
+  (value) =>
+    args.reverse().reduce((acc, fn) => fn(acc), value);
+//如果是表达式赋值的话,不会变量提升
  • 函数的组合要满足结合律,即 f,g,h 三个函数,无论先组合那几个,结果都是等效的,即 flowRight(.toUpper,.first,_.revers)
  • 函数组合如何进行调试?
js
const log = (v) => {
+  console.log(v);
+  return v;
+};
  • lodash库中的 fp 模块
    • lodash的 fp 模块提供了实用的对函数式编程友好的方法
    • 提供了不可变的auto-curried iteratee-first data-last的方法
js
//lodash 方法
+const _ = require('lodash');
+_.map(['a', 'b', 'c'], _.toUpper);
+//=>['A','B','C']
+_.map(['a', 'b', 'c']);
+//=>['a','b','c']
+//loadsh/fp 模块
+const fp = require('lodasg/fp');
+fp.map(fp.toUpper, ['a', 'b', 'c']);
+fp.map(fp.toUpper)(['a', 'b', 'c']);

七.Point Free

我们可以把数据处理的过程定义成与数据无关的合成运算,不需要用到代表数据的那个参数,只要把简单的运算步骤合成到一起,在使用这种模式之前我们需要定义一些辅助的基本运算函数。

  • 不需要指明处理的数据
  • 只需要合成运算过程
  • 需要定义一些辅助的基本运算函数
js
const f = fp.flowRight(fp.join('-'), fp.map(_.toLower), fp.splite(''));

八。functor(函子)

  • 为什么要了解函子
    目前没有解决如何在函数式编程中,把副作用控制在可控的范围内,异常处理,异步操作等等。
  • Functor
    • 容器:包含值和值的变形关系 (这个变形关系就是函数)
    • 函子:是一个特殊的容器,通过一个普通对象来实现,该对象具有 map 方法,map 方法可以运行一个函数对值进行处理 (变形关系)
js
//Functor 函子
+class Container {
+  //函子内部要有一个值
+  constructor(value) {
+    //这个值是传入进来的,且不对外公布
+    this._value = value;
+  }
+  map(fn) {
+    //map 方法,接受一个处理值的函数,去处理这个值。
+    //并且要把处理的值,传给一个新的函子,最后返回这个新的函子
+    return new Container(fn(this._value));
+  }
+}
+
+//新建一个函子
+let r = new Container(5).map((x) => x + 1).map((x) => x * x);

of方法:

js
//of 方法用来返回一个函子对象
+class Container {
+  constructor(value) {
+    this._value = value;
+  }
+  static of(value) {
+    //传入值,返回一个新的函子对象
+    return new Container(value);
+  }
+  map(fn) {
+    return Container.of(fn(this._value));
+  }
+}
+let r = Container.of(5)
+  .map((x) => x + 1)
+  .map((x) => x * x);
+console.log(r); //打印出来的是一个函子,不是值,永远不会把这个值取出来,需要改变这个值的时候,使用 map 方法传入一个函数去处理,进行链式调用。
  • 总结
    • 函数式编程的运算不直接操作值,而是由函子完成
    • 函子就是一个实现了map契约的对象
    • 我们可以把函子想象成一个盒子,这个盒子里封装了一个值
    • 想要处理盒子中的值,我们需要给盒子的map方法传递一个处理值的函数(纯函数),由这个函数对值进行处理
    • 最终map方法返回一个包含新值的盒子(函子)
  • MayBe函子
    • 我们在编程过程中可能会遇到很多的错误,需要对这些错误进行相应的处理
    • MayBe 函子的作用就是可以对外部的空值情况做处理(控制副作用在允许的范围之内)
js
//MayBe 函子
+class MayBe {
+  static of(value) {
+    return new MayBe(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this._value));
+  }
+  isNothing() {
+    return this._value === null || this._value === undefined;
+  }
+}
+let r = MayBe.of(null)
+  .map((x) => x + 1)
+  .map((x) => x * x);
+console.log(r);
  • 问题:如果多次调用 map,中间出现了 null 空值的情况,最后会返回包含 null 的函子。虽然 maybe 函子可以处理空值的情况,但不知道是哪一步出现了空值
  • Either 函子
    • Either 两者中的任意一个,类似于 if...else...的处理
    • 异常会让函数变的不纯,Either 函子可以用来做异常处理
js
//Either 函子
+class Left {
+  static of(value) {
+    return new Left(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return this;
+  }
+}
+
+class Right {
+  static of(value) {
+    return new Right(value);
+  }
+  constructor(value) {
+    this._value = value;
+  }
+  map(fn) {
+    return Right.of(fn(this._value));
+  }
+}
+
+function parseJSON(str) {
+  try {
+    return Right.of(JSON.parse(str));
+  } catch (error) {
+    return Left.of({ error: error.message });
+  }
+}
+let l = parseJSON('{name:zs}'); //error
+console.log(l);
+let r = parseJSON('{"name":"zs"}');
+console.log(r);
+r.map((x) => x.toUpper());
  • IO 函子
    • IO 函子中的_value 是一个函数,这里是把函数当作值来处理
    • IO 函子可以把不纯的函数储存到_value 中,延迟执行这个不纯的操作 (惰性执行)
    • 把不纯的操作交给调用者来处理
js
const fp = require('lodash/fp');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+}
+//调用
+//因为是在 node 环境,所以直接传递 process 对象,node 的进程
+let r = IO.of(process).map((p) => p.execPath);
+console.log(r); //IO {_value :[Function]}
+console.log(r._value()); //执行 node 进程的路径
  • folktale
    • folktale 是一个标准的函数式编程库
    • 和 lodash,ramda 不同的是,他没有提供很多功能函数
    • 只提供了函数式处理的操作,例如,curry,compose 等,和一些函子 Task,Either,MayBe 等
js
//folktale  2.3.2
+//Task 处理异步任务
+const fs = require('fs');
+const { task } = require('folktale/concurrency/task');
+const { split, find } = require('loadsh/fp');
+
+function readFile(filename) {
+  return task((resolver) => {
+    fs.readFile(filename, 'utf-8', (error, data) => {
+      if (error) {
+        resolver.reject(err);
+      } else {
+        resolver.resolve(data);
+      }
+    });
+  });
+}
+//会返回一个 Task 函子
+readFile('package.json')
+  .run()
+  .listen({
+    //监听事件的状态
+    onRejected: (err) => {
+      console.log(err);
+    },
+    onResolved: (value) => {
+      console.log(value);
+    },
+  });
+//可以在 run 之前调用 map,去处理返回的结果
+readFile('package.json')
+  .map(split('\n'))
+  .map(find((x) => x.includes('version')))
+  .run()
+  .listen({
+    //监听事件的状态
+    onRejected: (err) => {
+      console.log(err);
+    },
+    onResolved: (value) => {
+      console.log(value);
+    },
+  });
  • Pointed 函子
    • Pointed 函子是实现的静态方法 of 的函子
    • of 是为了避免使用 new 来创建对象,更深层的含义是 of 方法用来把值放到上下文 Context 中 (把值放到容器中,使用 map 来处理值)
  • Monad 函子
    • Monad 函子是为来解决 IO 函子嵌套的问题
js
const fp = require('lodash/fp');
+const fs = require('fs');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+}
+let readFile = function (filename) {
+  return new IO(function () {
+    return fs.readFileSync(filename, 'utf-8');
+  });
+};
+let print = function (x) {
+  return new IO(function (x) {
+    console.log(x);
+    return x;
+  });
+};
+let cat = fp.flowRight(print, readFile);
+let r = cat('package.json')._value()._value();
+console.log(r);
  • Monad 函子是一个可以变扁的 Pointed 函子,变扁就是解决函子嵌套的问题 IO(IO(x))
  • 一个函子如果具有 join 和 of 两个方法并遵守一些定律就是一个 Monad
js
//注意看 join 方法
+const fp = require('lodash/fp');
+const fs = require('fs');
+class IO {
+  static of(x) {
+    return new IO(function () {
+      return x;
+    });
+  }
+  constructor(fn) {
+    this._value = fn;
+  }
+  map(fn) {
+    return IO.of(fp.flowRight(fn, this._value));
+  }
+  join() {
+    return this._value();
+  }
+  flatMap(fn) {
+    //经常会用到 map 和 join 方法,所以就用 flatMap 将其变扁
+    return this.map(fn).join();
+  }
+}
+let print = function (x) {
+  return new IO(function () {
+    console.log(x);
+    return x;
+  });
+};
+let r = readFile('package.json') //这里可以用 map 去处理内容
+  .flatMap(print)
+  .join();

参考资料

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/imagemin.html b/cn/src/article/imagemin.html new file mode 100644 index 0000000000..380ec49bf3 --- /dev/null +++ b/cn/src/article/imagemin.html @@ -0,0 +1,49 @@ + + + + + + imagemin 图片压缩源码分析 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cn/src/article/javascript/domLoad.html b/cn/src/article/javascript/domLoad.html new file mode 100644 index 0000000000..e26978b678 --- /dev/null +++ b/cn/src/article/javascript/domLoad.html @@ -0,0 +1,51 @@ + + + + + + 页面加载完成后事件 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

页面加载完成后事件

window.onload

DOMContentLoaded

js
document.addEventListener('DOMContentLoaded', fun);

<body onload="fun()">

readyState

js
document.readyState;
+
+document.onreadystatechange;

一个文档的 readyState 可以是以下之一:

  • loading / 加载。document 仍在加载。
  • interactive / 互动。文档已经完成加载,文档已被解析,但是诸如图像,样式表和框架之类的子资源仍在加载。
  • complete / 完成。T 文档和所有子资源已完成加载。状态表示 load 事件即将被触发。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/sort/bubble/index.html b/cn/src/article/sort/bubble/index.html new file mode 100644 index 0000000000..03c39fa713 --- /dev/null +++ b/cn/src/article/sort/bubble/index.html @@ -0,0 +1,62 @@ + + + + + + 冒泡排序(Bubble Sort) | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

冒泡排序(Bubble Sort)

冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

算法描述

  • 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
  • 针对所有的元素重复以上的步骤,除了最后一个;
  • 重复步骤 1~3,直到排序完成。

动图演示

冒泡排序

代码演示

ts
const bubble = (list: number[]) => {
+  const size = list.length;
+  for (let i = 0; i < size; i++) {
+    for (let j = 0; j < size; j++) {
+      if (list[i] < list[j]) {
+        list[i] = list[i] ^ list[j];
+        list[j] = list[i] ^ list[j];
+        list[i] = list[i] ^ list[j];
+      }
+    }
+  }
+  return list;
+};

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/sort/bucket/index.html b/cn/src/article/sort/bucket/index.html new file mode 100644 index 0000000000..392d46e7ac --- /dev/null +++ b/cn/src/article/sort/bucket/index.html @@ -0,0 +1,105 @@ + + + + + + 桶排序 (Bucket Sort) | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

桶排序 (Bucket Sort)

高效与否的关键在于这个分桶函数。将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。

算法描述

  • 设置一个定量的数组当作空桶;
  • 遍历输入数据,并且把数据一个一个放到对应的桶里去;
  • 对每个不是空的桶进行排序;
  • 从不是空的桶里把排好序的数据拼接起来。

代码演示

ts
const count = (list: Array<number>, max: number = 100): Array<number> => {
+  const countList = new Array(max + 1);
+  for (let i = 0; i < list.length; i++) {
+    if (!countList[list[i]]) {
+      countList[list[i]] = 0;
+    }
+    countList[list[i]]++;
+  }
+  let startIndex = 0;
+  for (let i = 0; i < countList.length; i++) {
+    while (countList[i] > 0) {
+      list[startIndex++] = i;
+      countList[i]--;
+    }
+  }
+  return list;
+};
+const getMax = (list: Array<number>) => {
+  let max = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+const getMin = (list: Array<number>) => {
+  let min = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (min > list[i]) {
+      min = list[i];
+    }
+  }
+  return min;
+};
+
+/**
+ * @description: 桶排序
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const bucket = (list: Array<number>, bucketSize: number = 5, max?: number, min?: number): Array<number> => {
+  if (list.length === 0) return list;
+  if (!max) max = getMax(list);
+  if (!min) min = getMin(list);
+  const bucketCount = Math.floor((max - min) / bucketSize) + 1;
+  const buckets = new Array(bucketCount + 1).fill(0).map(() => new Array(0));
+
+  for (let i = 0; i < list.length; i++) {
+    buckets[Math.floor((list[i] - min) / bucketSize)].push(list[i]);
+  }
+  list = [];
+  for (let i = 0; i < bucketCount; i++) {
+    list = list.concat(count(buckets[i]));
+  }
+  return list;
+};

算法分析

桶排序最好情况下使用线性时间 O(n),桶排序的时间复杂度,取决与对各个桶之间数据进行排序的时间复杂度,因为其它部分的时间复杂度都为 O(n)。很显然,桶划分的越小,各个桶之间的数据越少,排序所用的时间也会越少。但相应的空间消耗就会增大。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/sort/count/index.html b/cn/src/article/sort/count/index.html new file mode 100644 index 0000000000..d3f6b08688 --- /dev/null +++ b/cn/src/article/sort/count/index.html @@ -0,0 +1,83 @@ + + + + + + 计数排序( Count Sort ) | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

计数排序( Count Sort )

计数排序(counting sort)就是一种牺牲内存空间来换取低时间复杂度的排序算法,同时它也是一种不基于比较的算法。这里的不基于比较指的是数组元素之间不存在比较大小的排序算法,我们知道,用分治法来解决排序问题最快也只能使算法的时间复杂度接近 Θ(nlogn),即基于比较的时间复杂度存在下界 Ω(nlog⁡n),而不基于比较的排序算法可以突破这一下界。

算法描述

  • 找出待排序的数组中最大和最小的元素;
  • 统计数组中每个值为 i 的元素出现的次数,存入数组 C 的第 i 项;
  • 对所有的计数累加(从 C 中的第一个元素开始,每一项和前一项相加);
  • 反向填充目标数组:将每个元素 i 放在新数组的第 C(i)项,每放一个元素就将 C(i)减去 1。

动图演示

计数排序

代码演示

ts
const getMax = (list: number[]) => {
+  let max = list[0];
+  for (let i = 1; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+/**
+ * @description: 计数排序
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const count = (list: number[]): number[] => {
+  if (list.length <= 1) return list;
+  const max = getMax(list);
+  const countList = new Array(max + 1).fill(0);
+  list.forEach((item) => {
+    if (!countList[item]) {
+      countList[item] = 1;
+    } else {
+      countList[item]++;
+    }
+  });
+  const result = [];
+  for (let i = 0; i < countList.length; i++) {
+    while (countList[i]) {
+      result.push(i);
+      countList[i]--;
+    }
+  }
+  return result;
+};

算法分析

计数排序是一个稳定的排序算法。当输入的元素是 n 个 0 到 k 之间的整数时,时间复杂度是 O(n+k),空间复杂度也是 O(n+k),其排序速度快于任何比较排序算法。当 k 不是很大并且序列比较集中时,计数排序是一个很有效的排序算法。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/sort/heap/index.html b/cn/src/article/sort/heap/index.html new file mode 100644 index 0000000000..7804146ab5 --- /dev/null +++ b/cn/src/article/sort/heap/index.html @@ -0,0 +1,99 @@ + + + + + + 堆排序(Heap Sort) | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

堆排序(Heap Sort)

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

算法描述

  • 将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;
  • 将堆顶元素 R[1]与最后一个元素 R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足 R[1,2…n-1]<=R[n];
  • 由于交换后新的堆顶 R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,然后再次将 R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为 n-1,则整个排序过程完成。
  • 升序用大根堆,降序用小根堆

动图演示

堆排序

代码演示

ts
class Heap {
+  value: Array<number>;
+  size: number;
+  constructor(arr: Array<number> = []) {
+    this.value = [...arr];
+    this.size = arr.length;
+    this.buildMaxHeap();
+  }
+  swap = (i: number, j: number) => {
+    if (this.value[i] === this.value[j]) return;
+    this.value[i] = this.value[i] ^ this.value[j];
+    this.value[j] = this.value[i] ^ this.value[j];
+    this.value[i] = this.value[i] ^ this.value[j];
+  };
+  heapHandler = (i: number) => {
+    const left = 2 * i + 1;
+    const right = 2 * i + 2;
+    let largest = i;
+    if (left < this.size && this.value[left] > this.value[largest]) {
+      largest = left;
+    }
+    if (right < this.size && this.value[right] > this.value[largest]) {
+      largest = right;
+    }
+    if (largest !== i) {
+      this.swap(i, largest);
+      this.heapHandler(largest);
+    }
+  };
+  buildMaxHeap = () => {
+    for (let i = this.size >> 1; i >= 0; i--) {
+      this.heapHandler(i);
+    }
+    for (let i = this.size - 1; i >= 0; i--) {
+      this.swap(0, i);
+      this.size--;
+      this.heapHandler(0);
+    }
+  };
+}
+
+/**
+ * @description: 堆排序
+ * @param {Array} list
+ * @return {Array}
+ */
+const heap = (list: Array<number>): Array<number> => {
+  const { value } = new Heap(list);
+  return value;
+};

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/sort/index.html b/cn/src/article/sort/index.html new file mode 100644 index 0000000000..6b31234ed4 --- /dev/null +++ b/cn/src/article/sort/index.html @@ -0,0 +1,50 @@ + + + + + + 十大经典排序 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

十大经典排序

十种常见排序算法可以分为两大类:

  • 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破 O(nlogn),因此也称为非线性时间比较类排序。
  • 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。

排序分类

算法复杂度

算法复杂度

相关概念

  • 稳定:如果 a 原本在 b 前面,而 a=b,排序之后 a 仍然在 b 的前面。
  • 不稳定:如果 a 原本在 b 的前面,而 a=b,排序之后 a 可能会出现在 b 的后面。
  • 时间复杂度:对排序数据的总的操作次数。反映当 n 变化时,操作次数呈现什么规律。
  • 空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模 n 的函数。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/sort/insert/index.html b/cn/src/article/sort/insert/index.html new file mode 100644 index 0000000000..ad93e7e3e1 --- /dev/null +++ b/cn/src/article/sort/insert/index.html @@ -0,0 +1,62 @@ + + + + + + 插入排序(Insert Sort) | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

插入排序(Insert Sort)

表现稳定的排序算法,因为无论什么数据进去都是 O(n2)的时间复杂度,所以用到它的时候,数据规模越小越好。优点是不占用额外的内存空间。工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

算法描述

  • 从第一个元素开始,该元素可以认为已经被排序;
  • 取出下一个元素,在已经排序的元素序列中从后向前扫描;
  • 如果该元素(已排序)大于新元素,将该元素移到下一位置;
  • 重复步骤 3,直到找到已排序的元素小于或者等于新元素的位置;
  • 将新元素插入到该位置后;
  • 重复步骤 2~5。

动图演示

插入排序

代码演示

ts
const insert = (list: number[]): number[] => {
+  const size = list.length;
+  for (let i = 1; i < size; i++) {
+    const current = list[i];
+    let preIndex = i - 1;
+    while (preIndex >= 0 && list[preIndex] > current) {
+      list[preIndex + 1] = list[preIndex];
+      preIndex--;
+    }
+    list[preIndex + 1] = current;
+  }
+  return list;
+};

算法分析

插入排序在实现上,通常采用 in-place 排序(即只需用到 O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/sort/merge/index.html b/cn/src/article/sort/merge/index.html new file mode 100644 index 0000000000..606c7c41cb --- /dev/null +++ b/cn/src/article/sort/merge/index.html @@ -0,0 +1,82 @@ + + + + + + 归并排序(Merge Sort) | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

归并排序(Merge Sort)

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为 2-路归并。

算法描述

  • 把长度为 n 的输入序列分成两个长度为 n/2 的子序列;
  • 对这两个子序列分别采用归并排序;
  • 将两个排序好的子序列合并成一个最终的排序序列。

动图演示

归并排序

代码演示

ts
const combine = (left: Array<number>, right: Array<number>) => {
+  const list: Array<number> = [];
+  while (left.length > 0 && right.length > 0) {
+    if (left[0] <= right[0]) {
+      list.push(left.shift()!);
+    } else {
+      list.push(right.shift()!);
+    }
+  }
+
+  while (left.length) {
+    list.push(left.shift()!);
+  }
+  while (right.length) {
+    list.push(right.shift()!);
+  }
+  return list;
+};
+/**
+ * @description: 归并排序
+ * @param {Array} list
+ * @return {Array}
+ */
+const merge = (list: Array<number>): Array<number> => {
+  const { length } = list;
+  if (length <= 1) {
+    return list;
+  }
+  const middle = length >> 1;
+  const left = list.slice(0, middle);
+  const right = list.slice(middle);
+  return combine(merge(left), merge(right));
+};

算法分析

归并排序是一种稳定的排序方法。和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是 O(nlogn)的时间复杂度。代价是需要额外的内存空间。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/sort/quick/index.html b/cn/src/article/sort/quick/index.html new file mode 100644 index 0000000000..4fb26eed0b --- /dev/null +++ b/cn/src/article/sort/quick/index.html @@ -0,0 +1,100 @@ + + + + + + 快速排序(Quick Sort) | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

快速排序(Quick Sort)

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

算法描述

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

  • 从数列中挑出一个元素,称为 “基准”(pivot);
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

动图演示

快速排序

代码演示

ts
/**
+ * @description: 设置基准值pivot
+ * @param {Array} list
+ * @param {number} left
+ * @param {number} right
+ * @return {number} index
+ */
+const partition = (list: number[] = [], left: number, right: number) => {
+  const pivot = left;
+  let index = pivot + 1;
+  for (let i = index; i <= right; i++) {
+    if (list[i] < list[pivot]) {
+      if (list[i] !== list[index]) {
+        list[i] = list[i] ^ list[index];
+        list[index] = list[i] ^ list[index];
+        list[i] = list[i] ^ list[index];
+      }
+      index++;
+    }
+  }
+  if (list[index - 1] !== list[pivot]) {
+    list[index - 1] = list[index - 1] ^ list[pivot];
+    list[pivot] = list[index - 1] ^ list[pivot];
+    list[index - 1] = list[index - 1] ^ list[pivot];
+  }
+  return index - 1;
+};
+/**
+ * @description: 不断分区,设置基准值
+ * @param {Array} list
+ * @param {number} left
+ * @param {number} right
+ * @return {Array}
+ */
+const combine = (list: number[], left: number, right: number) => {
+  if (left < right) {
+    const partitionIndex: number = partition(list, left, right);
+    combine(list, partitionIndex + 1, right);
+    combine(list, left, partitionIndex - 1);
+  }
+  return list;
+};
+/**
+ * @description: 快速排序
+ * @param {Array} list
+ * @return {Array}
+ */
+const quick = (list: number[] = []): number[] => {
+  const size = list.length;
+  return combine(list, 0, size - 1);
+};

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/sort/radix/index.html b/cn/src/article/sort/radix/index.html new file mode 100644 index 0000000000..ffe3d50757 --- /dev/null +++ b/cn/src/article/sort/radix/index.html @@ -0,0 +1,85 @@ + + + + + + 基数排序(Radix Sort) | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

基数排序(Radix Sort)

基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。桶排序扩展,类似于指定桶排序按位数排序规则,同时能利用计数排序适用于小范围数的特点。

算法描述

  • 取得数组中的最大数,并取得位数;
  • arr 为原始数组,从最低位开始取每个位组成 radix 数组;
  • 对 radix 进行计数排序(利用计数排序适用于小范围数的特点);

动图演示

基数排序

代码演示

ts
const getMax = (list: Array<number>) => {
+  let max = list[0];
+  for (let i = 0; i < list.length; i++) {
+    if (max < list[i]) {
+      max = list[i];
+    }
+  }
+  return max;
+};
+const getDigit = (num: number) => {
+  let digit = 1;
+  while (num >= 1) {
+    digit++;
+    num = num / 10;
+  }
+  return digit;
+};
+/**
+ * @description: 基数排序
+ * @param {Array<number>} list
+ * @return {Array<number>}
+ */
+const radix = (list: Array<number>, maxDigit?: number): Array<number> => {
+  if (list.length === 0) return list;
+  if (!maxDigit) maxDigit = getDigit(getMax(list));
+  const buckets = new Array(maxDigit).fill(0).map(() => new Array(0));
+  for (let j = 0; j < list.length; j++) {
+    const digit = getDigit(list[j]);
+    buckets[digit - 1].push(list[j]);
+  }
+  list = [];
+  for (let i = 0; i < buckets.length; i++) {
+    list = list.concat(count(buckets[i]));
+  }
+  return list;
+};

算法分析

基数排序基于分配排序,所以是稳定的。但基数排序的性能比桶排序要略差,每一次关键字的桶分配都需要 O(n)的时间复杂度,而且分配之后得到新的关键字序列又需要 O(n)的时间复杂度。假如待排数据可以分为 d 个关键字,则基数排序的时间复杂度将是 O(d*2n) ,当然 d 要远远小于 n,因此基本上还是线性级别的。

基数排序的空间复杂度为 O(n+k),其中 k 为桶的数量。一般来说 n>>k,因此额外空间需要大概 n 个左右。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/sort/select/index.html b/cn/src/article/sort/select/index.html new file mode 100644 index 0000000000..c3d8bc9461 --- /dev/null +++ b/cn/src/article/sort/select/index.html @@ -0,0 +1,66 @@ + + + + + + 选择排序(Selection Sort) | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

选择排序(Selection Sort)

选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

算法描述

n 个记录的直接选择排序可经过 n-1 趟直接选择排序得到有序结果。具体算法描述如下:

  • 初始状态:无序区为 R[1..n],有序区为空;
  • 第 i 趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为 R[1..i-1]和 R(i..n)。该趟排序从当前无序区中-选出关键字最小的记录 R[k],将它与无序区的第 1 个记录 R 交换,使 R[1..i]和 R[i+1..n)分别变为记录个数增加 1 个的新有序区和记录个数减少 1 个的新无序区;
  • n-1 趟结束,数组有序化了。

动图演示

选择排序

代码实现

js
const select = (list: number[]): number[] => {
+  const size = list.length;
+  for (let i = 0; i < size; i++) {
+    let minIndex = i;
+    for (let j = i + 1; j < size; j++) {
+      if (list[minIndex] >= list[j]) {
+        minIndex = j;
+      }
+    }
+    if (list[i] !== list[minIndex]) {
+      list[i] = list[i] ^ list[minIndex];
+      list[minIndex] = list[i] ^ list[minIndex];
+      list[i] = list[i] ^ list[minIndex];
+    }
+  }
+  return list;
+};

算法分析

表现最稳定的排序算法之一,因为无论什么数据进去都是 O(n2)的时间复杂度,所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。理论上讲,选择排序可能也是平时排序一般人想到的最多的排序方法了吧。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/sort/shell/index.html b/cn/src/article/sort/shell/index.html new file mode 100644 index 0000000000..70feec67e6 --- /dev/null +++ b/cn/src/article/sort/shell/index.html @@ -0,0 +1,69 @@ + + + + + + 希尔排序(Shell Sort) | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

希尔排序(Shell Sort)

1959 年 Shell 发明,第一个突破 O(n2)的排序算法,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。

算法描述

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:

  • 选择一个增量序列 t1,t2,…,tk,其中 ti>tj,tk=1;
  • 按增量序列个数 k,对序列进行 k 趟排序;
  • 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

动图演示

希尔排序

代码实现

js
/**
+ * @description: 希尔排序,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
+ * @param {Array} list
+ * @return {Array}
+ */
+const shell = (list: number[]): number[] => {
+  const size = list.length;
+  for (let gap = size >> 1; gap > 0; gap >>= 1) {
+    for (let i = gap; i < size; i += gap) {
+      const current = list[i];
+      let preIndex = i - gap;
+      while (preIndex >= 0 && list[preIndex] > current) {
+        list[preIndex + gap] = list[preIndex];
+        preIndex -= gap;
+      }
+      list[preIndex + gap] = current;
+    }
+  }
+  return list;
+};

算法分析

希尔排序的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列。动态定义间隔序列的算法是《算法(第 4 版)》的合著者 Robert Sedgewick 提出的。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/systemDesign.html b/cn/src/article/systemDesign.html new file mode 100644 index 0000000000..e1dd101824 --- /dev/null +++ b/cn/src/article/systemDesign.html @@ -0,0 +1,49 @@ + + + + + + 如何处理一个系统设计 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

如何处理一个系统设计

系统设计是一个开放式的对话。他们期望你去主导这个对话。

你可以使用下面的步骤来指引讨论。为了巩固这个过程,请使用下面的步骤完成系统设计的面试题和解答这个章节。

第一步:描述使用场景,约束和假设

把所有需要的东西聚集在一起,审视问题。不停的提问,以至于我们可以明确使用场景和约束。讨论假设。

谁会使用它? 他们会怎样使用它? 有多少用户? 系统的作用是什么? 系统的输入输出分别是什么? 我们希望处理多少数据? 我们希望每秒钟处理多少请求? 我们希望的读写比率?

第二步:创造一个高层级的设计

使用所有重要的组件来描绘出一个高层级的设计。

画出主要的组件和连接 证明你的想法

第三步:设计核心组件

对每一个核心组件进行详细深入的分析。举例来说,如果你被问到设计一个 url 缩写服务,开始讨论:

生成并储存一个完整 url 的 hash MD5 和 Base62 Hash 碰撞 SQL 还是 NoSQL 数据库模型 将一个 hashed url 翻译成完整的 url 数据库查找 API 和面向对象设计

第四步:扩展设计

确认和处理瓶颈以及一些限制。举例来说就是你需要下面的这些来完成扩展性的议题吗?

负载均衡 水平扩展 缓存 数据库分片 论述可能的解决办法和代价。每件事情需要取舍。可以使用可扩展系统的设计原则来处理瓶颈。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/typescript/calculate.html b/cn/src/article/typescript/calculate.html new file mode 100644 index 0000000000..dfee8e58e4 --- /dev/null +++ b/cn/src/article/typescript/calculate.html @@ -0,0 +1,79 @@ + + + + + + 数组长度做计数 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

数组长度做计数

类型系统不是图灵完备,各种逻辑都能写么,但好像没发现数值相关的逻辑。

没错,数值相关的逻辑比较绕,被我单独摘了出来,就是这节要讲的内容。

这是类型体操的第四个套路:数组长度做计数。

TypeScript 类型系统没有加减乘除运算符,怎么做数值运算呢?

不知道大家有没有注意到数组类型取 length 就是数值。

比如:

ts
type num1 = [unknown]['length'];
+// type num1 = 1
+type num2 = [unknown, unknown]['length'];
+// type num1 = 2
+type num3 = [unknown, unknown, unknown]['length'];
+// type num1 = 3

而数组类型我们是能构造出来的,那么通过构造不同长度的数组然后取 length,不就是数值的运算么?

TypeScript 类型系统中没有加减乘除运算符,但是可以通过构造不同的数组然后取 length 的方式来完成数值计算,把数值的加减乘除转化为对数组的提取和构造。

(严格来说构造的是元组,大家知道数组和元组的区别就行)

这点可以说是类型体操中最麻烦的一个点,需要思维做一些转换,绕过这个弯来。

下面我们就来做一些真实的案例来掌握它吧。

数组长度实现加减乘除

Add

我们知道了数值计算要转换为对数组类型的操作,那么加法的实现很容易想到:

构造两个数组,然后合并成一个,取 length。

比如 3 + 2,就是构造一个长度为 3 的数组类型,再构造一个长度为 2 的数组类型,然后合并成一个数组,取 length。

构造多长的数组是不确定的,需要递归构造,这个我们实现过:

ts
type BuildArray<Length extends number, Ele = unknown, Arr extends unknown[] = []> = Arr['length'] extends Length
+  ? Arr
+  : BuildArray<Length, Ele, [...Arr, Ele]>;

类型参数 Length 是要构造的数组的长度。类型参数 Ele 是数组元素,默认为 unknown。类型参数 Arr 为构造出的数组,默认是 []。

如果 Arr 的长度到达了 Length,就返回构造出的 Arr,否则继续递归构造。

构造数组实现了,那么基于它就能实现加法:

ts
type Add<Num1 extends number, Num2 extends number> = [...BuildArray<Num1>, ...BuildArray<Num2>]['length'];

我们拿大一点的数测试下:

ts
type AddResult = Add<32, 25>;
+// type AddResult = 57

就这样,我们通过构造一定长度的数组取 length 的方式实现了加法运算。

Subtract

加法是构造数组,那减法怎么做呢?

减法是从数值中去掉一部分,很容易想到可以通过数组类型的提取来做。

比如 3 是 [unknown, unknown, unknown] 的数组类型,提取出 2 个元素之后,剩下的数组再取 length 就是 1。

所以减法的实现是这样的:

ts
type Subtract<Num1 extends number, Num2 extends number> =
+  BuildArray<Num1> extends [...arr1: BuildArray<Num2>, ...arr2: infer Rest] ? Rest['length'] : never;

类型参数 Num1、Num2 分别是被减数和减数,通过 extends 约束为 number。

构造 Num1 长度的数组,通过模式匹配提取出 Num2 长度个元素,剩下的放到 infer 声明的局部变量 Rest 里。

取 Rest 的长度返回,就是减法的结果。

就这样,我们通过数组类型的提取实现了减法运算。

Multiply

我们把加法转换为了数组构造,把减法转换为了数组提取。那乘法怎么做呢?

为了解释乘法,我去翻了下小学教材,找到了这样一张图:

1 乘以 5 就相当于 1 + 1 + 1 + 1 + 1,也就是说乘法就是多个加法结果的累加。

那么我们在加法的基础上,多加一个参数来传递中间结果的数组,算完之后再取一次 length 就能实现乘法:

ts
type Multiplication<Num1 extends number, Num2 extends number, ResultArr extends unknown[] = []> = Num2 extends 0
+  ? ResultArr['length']
+  : Multiplication<Num1, Subtract<Num2, 1>, [...BuildArray<Num1>, ...ResultArr]>;

类型参数 Num1 和 Num2 分别是被加数和加数。

因为乘法是多个加法结果的累加,我们加了一个类型参数 ResultArr 来保存中间结果,默认值是 [],相当于从 0 开始加。

每加一次就把 Num2 减一,直到 Num2 为 0,就代表加完了。

加的过程就是往 ResultArr 数组中放 Num1 个元素。

这样递归的进行累加,也就是递归的往 ResultArr 中放元素。

最后取 ResultArr 的 length 就是乘法的结果。

就这样,我们通过递归的累加实现了乘法。

Divide

乘法是递归的累加,那除法不就是递归的累减么?

我再去翻了下小学教材,找到了这样一张图:

我们有 9 个苹果,分给美羊羊 3 个,分给懒羊羊 3 个,分给沸羊羊 3 个,最后剩下 0 个。所以 9 / 3 = 3。

所以,除法的实现就是被减数不断减去减数,直到减为 0,记录减了几次就是结果。

也就是这样的:

ts
type Divide<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends 0
+  ? CountArr['length']
+  : Divide<Subtract<Num1, Num2>, Num2, [unknown, ...CountArr]>;

类型参数 Num1 和 Num2 分别是被减数和减数。

类型参数 CountArr 是用来记录减了几次的累加数组。

如果 Num1 减到了 0 ,那么这时候减了几次就是除法结果,也就是 CountArr['length']。

否则继续递归的减,让 Num1 减去 Num2,并且 CountArr 多加一个元素代表又减了一次。

这样就实现了除法:

就这样,我们通过递归的累减并记录减了几次实现了除法。

做完了加减乘除,我们再来做一些别的数值计算的类型体操。

数组长度实现计数

StrLen

数组长度可以取 length 来得到,但是字符串类型不能取 length,所以我们来实现一个求字符串长度的高级类型。

字符串长度不确定,明显要用递归。每次取一个并计数,直到取完,就是字符串长度。

ts
type StrLen<Str extends string, CountArr extends unknown[] = []> = Str extends `${string}${infer Rest}`
+  ? StrLen<Rest, [...CountArr, unknown]>
+  : CountArr['length'];

类型参数 Str 是待处理的字符串。类型参数 CountArr 是做计数的数组,默认值 [] 代表从 0 开始。

每次通过模式匹配提取去掉一个字符之后的剩余字符串,并且往计数数组里多放入一个元素。递归进行取字符和计数。

如果模式匹配不满足,代表计数结束,返回计数数组的长度 CountArr['length']。

这样就能求出字符串长度:

GreaterThan

能够做计数了,那也就能做两个数值的比较。

我们往一个数组类型中不断放入元素取长度,如果先到了 A,那就是 B 大,否则是 A 大:

ts
type GreaterThan<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends Num2
+  ? false
+  : CountArr['length'] extends Num2
+    ? true
+    : CountArr['length'] extends Num1
+      ? false
+      : GreaterThan<Num1, Num2, [...CountArr, unknown]>;

类型参数 Num1 和 Num2 是待比较的两个数。

类型参数 CountArr 是计数用的,会不断累加,默认值是 [] 代表从 0 开始。

如果 Num1 extends Num2 成立,代表相等,直接返回 false。

否则判断计数数组的长度,如果先到了 Num2,那么就是 Num1 大,返回 true。

反之,如果先到了 Num1,那么就是 Num2 大,返回 false。

如果都没到就往计数数组 CountArr 中放入一个元素,继续递归。

这样就实现了数值比较。

当 3 和 4 比较时:

Fibonacci

谈到了数值运算,就不得不提起经典的 Fibonacci 数列的计算。

Fibonacci 数列是 1、1、2、3、5、8、13、21、34、…… 这样的数列,有当前的数是前两个数的和的规律。

F(0) = 1,F(1) = 1, F(n) = F(n - 1) + F(n - 2)(n ≥ 2,n ∈ N*)

也就是递归的加法,在 TypeScript 类型编程里用构造数组来实现这种加法:

ts
type FibonacciLoop<
+  PrevArr extends unknown[],
+  CurrentArr extends unknown[],
+  IndexArr extends unknown[] = [],
+  Num extends number = 1,
+> = IndexArr['length'] extends Num
+  ? CurrentArr['length']
+  : FibonacciLoop<CurrentArr, [...PrevArr, ...CurrentArr], [...IndexArr, unknown], Num>;
+
+type Fibonacci<Num extends number> = FibonacciLoop<[1], [], [], Num>;

类型参数 PrevArr 是代表之前的累加值的数组。类型参数 CurrentArr 是代表当前数值的数组。

类型参数 IndexArr 用于记录 index,每次递归加一,默认值是 [],代表从 0 开始。

类型参数 Num 代表求数列的第几个数。

判断当前 index 也就是 IndexArr['length'] 是否到了 Num,到了就返回当前的数值 CurrentArr['length']。

否则求出当前 index 对应的数值,用之前的数加上当前的数 [...PrevArr, ... CurrentArr]。

然后继续递归,index + 1,也就是 [...IndexArr, unknown]。

这就是递归计算 Fibinacci 数列的数的过程。

可以正确的算出第 8 个数是 21:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/typescript/index.html b/cn/src/article/typescript/index.html new file mode 100644 index 0000000000..d74745128c --- /dev/null +++ b/cn/src/article/typescript/index.html @@ -0,0 +1,204 @@ + + + + + + TypeScript 的类型系统 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

TypeScript 的类型系统

一.类型是什么

类型具体点来说就是指 number、boolean、string 等基础类型和 Object、Function 等复合类型,它们是编程语言提供的对不同内容的抽象:

  • 不同类型变量占据的内存大小不同: boolean 类型的变量会分配 4 个字节的内存,而 number 类型的变量则会分配 8 个字节的内存,给变量声明了不同的类型就代表了会占据不同的内存空间。

  • 不同类型变量可做的操作不同: number 类型可以做加减乘除等运算,boolean 就不可以,复合类型中不同类型的对象可用的方法不同,比如 Date 和 RegExp,变量的类型不同代表可以对该变量做的操作就不同。

有了类型,那我们的操作必须和类型相匹配,否则就会报错,这就是类型检查。

如果能保证对某种类型只做该类型允许的操作,这就叫做类型安全。

类型检查可以在运行时做,也可以运行之前的编译期做。这是两种不同的类型,前者叫做动态类型检查,后者叫做静态类型检查。

两种类型检查各有优缺点。动态类型检查 在源码中不保留类型信息,对某个变量赋什么值、做什么操作都是允许的,写代码很灵活。但这也埋下了类型不安全的隐患,比如对 string 做了乘除,对 Date 对象调用了 exec 方法,这些都是运行时才能检查出来的错误。

其中,最常见的错误应该是 “null is not an object”、“undefined is not a function” 之类的了,写代码时没发现类型不匹配,到了运行的时候才发现,就会有很多这种报错。

所以,动态类型虽然代码写起来简单,但代码中很容易藏着一些类型不匹配的隐患。

静态类型检查则是在源码中保留类型信息,声明变量要指定类型,对变量做的操作要和类型匹配,会有专门的编译器在编译期间做检查。

静态类型给写代码增加了一些难度,因为你除了要考虑代码要表达的逻辑之外,还要考虑类型逻辑:变量是什么类型的、是不是匹配、要不要做类型转换等。

不过,静态类型也消除了类型不安全的隐患,因为在编译期间就做了类型检查,就不会出现对 string 做了乘除,调用了 Date 的 exec 方法这类问题。

所以,静态类型虽然代码写起来要考虑的问题多一些,会复杂一些,但是却消除了代码中潜藏类型不安全问题的可能。

知道了动态类型检查和静态类型检查的区别,我们自然可以得出这样的结论:

动态类型只适合简单的场景,对于大项目却不太合适,因为代码中可能藏着的隐患太多了,万一线上报一个类型不匹配的错误,那可能就是大问题。

而静态类型虽然会增加写代码的成本,但是却能更好的保证代码的健壮性,减少 Bug 率。

所以,大型项目注定会用静态类型语言开发。

二.类型系统的分类

1.简单的类型系统

变量、函数、类等都可以声明类型,编译器会基于声明的类型做类型检查,类型不匹配时会报错。

这是最基础的类型系统,能保证类型安全,但有些死板。

比如一个 add 函数既可以做整数加法、又可以做浮点数加法,却需要声明两个函数:

c
int add(int a, int b) {
+    return a + b;
+}
+
+double add(double a, double b) {
+    return a + b;
+}

这个问题的解决思路很容易想到:如果类型能传参数就好了,传入 int 就是整数加法,传入 double 就是浮点数加法。

所以,就有了第二种类型系统。

2.支持泛型的类型系统

泛型的英文是 Generic Type,通用的类型,它可以代表任何一种类型,也叫做类型参数。

它给类型系统增加了一些灵活性,在整体比较固定,部分变量的类型有变化的情况下,可以减少很多重复代码。

比如上面的 add 函数,有了泛型之后就可以这样写:

java
T add<T>(T a, T b) {
+    return a + b;
+}
+
+add(1,2);
+add(1.111, 2.2222);

声明时把会变化的类型声明成泛型(也就是类型参数),在调用的时候再确定类型。

Java 就是这种类型系统。如果你看过 Java 代码,你会发现泛型用的特别多,这确实是一个很好的增加类型系统灵活性的特性。

但是,这种类型系统的灵活性对于 JavaScript 来说还不够,因为 JavaScript 太过灵活了。

比如,在 Java 里,对象都是由类 new 出来的,你不能凭空创建对象,但是 JavaScript 却可以,它支持对象字面量。

那如果是一个返回对象某个属性值的函数,类型该怎么写呢?

ts
function getPropValue<T>(obj: T, key): key对应的属性值类型 {
+  return obj[key];
+}

好像拿到了 T,也不能拿到它的属性和属性值,如果能对类型参数 T 做一些逻辑处理就好了。

所以,就有了第三种类型系统。

3.支持类型编程的类型系统

在 Java 里面,拿到了对象的类型就能找到它的类,进一步拿到各种信息,所以类型系统支持泛型就足够了。

但是在 JavaScript 里面,对象可以字面量的方式创建,还可以灵活的增删属性,拿到对象并不能确定什么,所以要支持对传入的类型参数做进一步的处理。

对传入的类型参数(泛型)做各种逻辑运算,产生新的类型,这就是类型编程。

比如上面那个 getProps 的函数,类型可以这样写:

ts
function getPropValue<T extends object, Key extends keyof T>(obj: T, key: Key): T[Key] {
+  return obj[key];
+}

这里的 keyof T、T[Key] 就是对类型参数 T 的类型运算。

TypeScript 的类型系统就是第三种,支持对类型参数做各种逻辑处理,可以写很复杂的类型逻辑。

类型逻辑可以多复杂?

类型逻辑是对类型参数的各种处理,可以实现很多强大的功能:

比如这个 ParseQueryString 的类型:

ts
type res = ParseQueryString<'a=1&b=2&c=3'>;

它可以对传入的字符串的类型参数做解析,返回解析以后的结果。等于

ts
type res = {
+  a: '1';
+  b: '2';
+  c: '3';
+};

如果是 Java 的只支持泛型的类型系统可以做到么?明显不能。但是 TypeScript 的类型系统就可以,因为它可以对泛型(类型参数)做各种逻辑处理。

只不过,这个类型的类型逻辑的代码比较多(下面的 ts 类型暂时看不懂没关系,在顺口溜那节会有详解,这里只是用来直观感受下类型编程的复杂度的,等学完以后大家也能实现这样的复杂高级类型的):

ts
type ParseParam<Param extends string> = Param extends `${infer Key}=${infer Value}`
+  ? {
+      [K in Key]: Value;
+    }
+  : {};
+
+type MergeValues<One, Other> = One extends Other ? One : Other extends unknown[] ? [One, ...Other] : [One, Other];
+
+type MergeParams<OneParam extends Record<string, any>, OtherParam extends Record<string, any>> = {
+  [Key in keyof OneParam | keyof OtherParam]: Key extends keyof OneParam
+    ? Key extends keyof OtherParam
+      ? MergeValues<OneParam[Key], OtherParam[Key]>
+      : OneParam[Key]
+    : Key extends keyof OtherParam
+      ? OtherParam[Key]
+      : never;
+};
+type ParseQueryString<Str extends string> = Str extends `${infer Param}&${infer Rest}`
+  ? MergeParams<ParseParam<Param>, ParseQueryString<Rest>>
+  : ParseParam<Str>;

TypeScript 的类型系统是图灵完备的,也就是能描述各种可计算逻辑。简单点来理解就是循环、条件等各种 JS 里面有的语法它都有,JS 能写的逻辑它都能写。

对类型参数的编程是 TypeScript 类型系统最强大的部分,可以实现各种复杂的类型计算逻辑,是它的优点。但同时也被认为是它的缺点,因为除了业务逻辑外还要写很多类型逻辑。

不过,我倒是觉得这种复杂度是不可避免的,因为 JS 本身足够灵活,要准确定义类型那类型系统必然也要设计的足够灵活。

4.类型安全和型变

TypeScript 给 JavaScript 添加了一套静态类型系统,是为了保证类型安全的,也就是保证变量只能赋同类型的值,对象只能访问它有的属性、方法。

比如 number 类型的值不能赋值给 boolean 类型的变量,Date 类型的对象就不能调用 exec 方法。

这是类型检查做的事情,遇到类型安全问题会在编译时报错。

但是这种类型安全的限制也不能太死板,有的时候需要一些变通,比如子类型是可以赋值给父类型的变量的,可以完全当成父类型来使用,也就是“型变(variant)”(类型改变)。

这种“型变”分为两种,一种是子类型可以赋值给父类型,叫做协变(covariant),一种是父类型可以赋值给子类型,叫做逆变(contravariant)。

先来看下协变:

协变(covariant)

对具体成员的输出参数进行一次类型转换,且类型转换的准则是 “里氏替换原则”。

其中协变是很好理解的,比如我们有两个 interface:

ts
interface Animal {
+  name: string;
+  age: number;
+}
+
+interface Cat {
+  name: string;
+  age: number;
+  hobbies: string[];
+}

这里 Cat 是 Animal 的子类型,更具体,那么 Cat 类型的变量就可以赋值给 Animal 类型:

ts
let animal: Animal = {
+  name: 'cat',
+  age: 3,
+};
+
+let cat: Cat = {
+  name: 'Tony',
+  age: 5,
+  hobbies: ['run', 'swim'],
+};
+
+animal = cat;

这并不会报错,虽然这俩类型不一样,但是依然是类型安全的。

这种子类型可以赋值给父类型的情况就叫做协变。

为什么要支持协变很容易理解:类型系统支持了父子类型,那如果子类型还不能赋值给父类型,还叫父子类型么?

所以型变是实现类型父子关系必须的,它在保证类型安全的基础上,增加了类型系统的灵活性。

逆变相对难理解一些:

逆变(contravariant)

是对具体成员的输入参数进行一次类型转换,且类型转换的准则是"里氏替换原则"。

我们有这样两个函数:

ts
let printHobbies: (cat: Cat) => void;
+
+printHobbies = (cat) => {
+  console.log(cat.hobbies);
+};
+
+let printName: (animal: Animal) => void;
+
+printName = (animal) => {
+  console.log(animal.name);
+};

printHobbies 的参数 Guang 是 printName 参数 Person 的子类型。

那么问题来了,printName 能赋值给 printHobbies 么?printHobbies 能赋值给 printName 么?

测试一下发现是这样的:

ts
let printHobbies: (cat: Cat) => void;
+
+printHobbies = (cat) => {
+  console.log(cat.hobbies);
+};
+
+let printName: (animal: Animal) => void;
+
+printName = (animal) => {
+  console.log(animal.name);
+};
+
+printHobbies = printName;

printName 的参数 Person 不是 printHobbies 的参数 Guang 的父类型么,为啥能赋值给子类型?

因为这个函数调用的时候是按照 Guang 来约束的类型,但实际上函数只用到了父类型 Person 的属性和方法,当然不会有问题,依然是类型安全的。

这就是逆变,函数的参数有逆变的性质(而返回值是协变的,也就是子类型可以赋值给父类型)。

那反过来呢,如果 printHoobies 赋值给 printName 会发生什么?

因为函数声明的时候是按照 Person 来约束类型,但是调用的时候是按照 Guang 的类型来访问的属性和方法,那自然类型不安全了,所以就会报错。

但是在 ts2.x 之前支持这种赋值,也就是父类型可以赋值给子类型,子类型可以赋值给父类型,既逆变又协变,叫做“双向协变”。

但是这明显是有问题的,不能保证类型安全,所以之后 ts 加了一个编译选项 strictFunctionTypes,设置为 true 就只支持函数参数的逆变,设置为 false 则是双向协变。

我们把 strictFunctionTypes 关掉之后,就会发现两种赋值都可以了。

这样就支持函数参数的双向协变,类型检查不会报错,但不能严格保证类型安全。

开启之后,函数参数就只支持逆变,子类型赋值给父类型就会报错。

再举个逆变的例子,大家觉得下面这样的 ts 代码会报错么:

ts
type Func = (a: string) => void;
+
+const func: Func = (a: 'hello') => undefined;

答案是参数的位置会,返回值的位置不会:

参数的位置是逆变的,也就是被赋值的函数参数要是赋值的函数参数的子类型,而 string 不是 'hello' 的子类型,所以报错了。

返回值的位置是协变的,也就是赋值的函数的返回值是被赋值的函数的返回值的子类型,这里 undefined 是 void 的子类型,所以不报错。

不变(invariant)

逆变和协变都是型变,是针对父子类型而言的,非父子类型自然就不会型变,也就是不变:

非父子类型之间不会发生型变,只要类型不一样就会报错

那类型之间的父子关系是怎么确定的呢,好像也没有看到 extends 的继承?

像 java 里面的类型都是通过 extends 继承的,如果 A extends B,那 A 就是 B 的子类型。这种叫做名义类型系统(nominal type)。

而 ts 里不看这个,只要结构上是一致的,那么就可以确定父子关系,这种叫做结构类型系统(structual type)。

通过结构,更具体的那个是子类型。这里的 Cat 有 Animal 的所有属性,并且还多了一些属性,所以 Cat 是 Animal 的子类型。

注意,这里用的是更具体,而不是更多。

判断联合类型父子关系的时候, 'a' | 'b' 和 'a' | 'b' | 'c' 哪个更具体?

'a' | 'b' 更具体,所以 'a' | 'b' 是 'a' | 'b' | 'c' 的子类型。

三.TypeScript 类型系统

1.支持的类型

静态类型系统的目的是把类型检查从运行时提前到编译时,那 TS 类型系统中肯定要把 JS 的运行时类型拿过来,也就是 number、boolean、string、object、bigint、symbol、undefined、null 这些类型,还有就是它们的包装类型 Number、Boolean、String、Object、Symbol。

这些很容易理解,给 JS 添加静态类型,总没有必要重新造一套基础类型吧,直接复用 JS 的基础类型就行。

复合类型方面,JS 有 class、Array,这些 TypeScript 类型系统也都支持,但是又多加了三种类型:元组(Tuple)、接口(Interface)、枚举(Enum)。

元组

元组(Tuple)就是元素个数和类型固定的数组类型:

ts
type Tuple = [number, string];

接口

接口(Interface)可以描述函数、对象、构造器的结构:

对象:

ts
interface IPerson {
+  name: string;
+  age: number;
+}
+
+class Person implements IPerson {
+  name: string;
+  age: number;
+}
+
+const obj: IPerson = {
+  name: 'guang',
+  age: 18,
+};

函数:

ts
interface SayHello {
+  (name: string): string;
+}
+
+const func: SayHello = (name: string) => {
+  return 'hello,' + name;
+};

构造器:

ts
interface PersonConstructor {
+  new (name: string, age: number): IPerson;
+}
+
+function createPerson(ctor: PersonConstructor): IPerson {
+  return new ctor('guang', 18);
+}

对象类型、class 类型在 TypeScript 里也叫做索引类型,也就是索引了多个元素的类型的意思。对象可以动态添加属性,如果不知道会有什么属性,可以用可索引签名:

ts
interface IPerson {
+  [prop: string]: string | number;
+}
+const obj: IPerson = {};
+obj.name = 'guang';
+obj.age = 18;

总之,接口可以用来描述函数、构造器、索引类型(对象、class、数组)等复合类型。

枚举

枚举(Enum)是一系列值的复合:

ts
enum Transpiler {
+  Babel = 'babel',
+  Postcss = 'postcss',
+  Terser = 'terser',
+  Prettier = 'prettier',
+  TypeScriptCompiler = 'tsc',
+}
+
+const transpiler = Transpiler.TypeScriptCompiler;

此外,TypeScript 还支持字面量类型,也就是类似 1111、'aaaa'、{ a: 1} 这种值也可以做为类型。

其中,字符串的字面量类型有两种,一种是普通的字符串字面量,比如 'aaa',另一种是模版字面量,比如 aaa${string},它的意思是以 aaa 开头,后面是任意 string 的字符串字面量类型。

所以想要约束以某个字符串开头的字符串字面量类型时可以这样写:

ts
function func(str: `#${string}`) {}
+
+func('aaaa'); // error
+
+func('#aaaa'); // true

还有四种特殊的类型:void、never、any、unknown:

  • never 代表不可达,比如函数抛异常的时候,返回值就是 never。
  • void 代表空,可以是 undefined 或 never。
  • any 是任意类型,任何类型都可以赋值给它,它也可以赋值给任何类型(除了 never)。
  • unknown 是未知类型,任何类型都可以赋值给它,但是它不可以赋值给别的类型。

这些就是 TypeScript 类型系统中的全部类型了,大部分是从 JS 中迁移过来的,比如基础类型、Array、class 等,也添加了一些类型,比如 枚举(enum)、接口(interface)、元组等,还支持了字面量类型和 void、never、any、unknown 的特殊类型。

2.类型的装饰

除了描述类型的结构外,TypeScript 的类型系统还支持描述类型的属性,比如是否可选,是否只读等:

ts
interface IPerson {
+  readonly name: string;
+  age?: number;
+}
+
+type tuple = [string, number?];

3.类型运算

我们知道了 TypeScript 类型系统里有哪些类型,那么可以对这些类型做什么类型运算呢?

条件:extends ?

TypeScript 里的条件判断是 extends ? :,叫做条件类型(Conditional Type)比如:

ts
type res = 1 extends 2 ? true : false; // type res = false

这就是 TypeScript 类型系统里的 if else。

但是,上面这样的逻辑没啥意义,静态的值自己就能算出结果来,为什么要用代码去判断呢?

所以,类型运算逻辑都是用来做一些动态的类型的运算的,也就是对类型参数的运算。

ts
type isTwo<T> = T extends 2 ? true : false;
+
+type res = isTwo<1>; // type res = false
+type res2 = isTwo<2>; // type res = true

这种类型也叫做高级类型。

高级类型的特点是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

推导:infer

如何提取类型的一部分呢?答案是 infer。

比如提取元组类型的第一个元素:

ts
type First<Tuple extends unknown[]> = Tuple extends [infer T, ...infer R] ? T : never;
+
+type res = First<[1, 2, 3]>; // type res = 1

注意,第一个 extends 不是条件,条件类型是 extends ? :,这里的 extends 是约束的意思,也就是约束类型参数只能是数组类型。

因为不知道数组元素的具体类型,所以用 unknown。

infer 在后面的章节会大量用到,这里先简单了解即可。

联合:|

联合类型(Union)类似 js 里的或运算符 |,但是作用于类型,代表类型可以是几个类型之一。

ts
type Union = 1 | 2 | 3;

交叉:&

交叉类型(Intersection)类似 js 中的与运算符 &,但是作用于类型,代表对类型做合并。

ts
type ObjType = { a: number } & { c: boolean };

注意,同一类型可以合并,不同的类型没法合并,会被舍弃:

可以合并的

ts
type ObjType = { a: number } & { c: boolean };
+
+type res = { a: number; c: boolean } extends ObjType ? true : false; // type res = true

不可合并

ts
type res = 'aaaa' & 2222; // type res = never

映射类型

对象、class 在 TypeScript 对应的类型是索引类型(Index Type),那么如何对索引类型作修改呢?

答案是映射类型。

ts
type MapType<T> = {
+  [Key in keyof T]?: T[Key];
+};

keyof T 是查询索引类型中所有的索引,叫做索引查询。

T[Key] 是取索引类型某个索引的值,叫做索引访问。

in 是用于遍历联合类型的运算符。

比如我们把一个索引类型的值变成 3 个元素的数组:

ts
type MapType<T> = {
+  [Key in keyof T]: [T[Key], T[Key], T[Key]];
+};
+
+type res = MapType<{ a: 1; b: 2 }>; // type res = { a: [1, 1, 1]; b:[2, 2, 2]; }

映射类型就相当于把一个集合映射到另一个集合,这是它名字的由来。

除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。

我们用 as 把索引也做了修改,改成了 3 个 key 重复:

ts
type MapType<T> = {
+  [Key in keyof T as `${Key & string}${Key & string}${Key & string}`]: [T[Key], T[Key], T[Key]];
+};
+
+// type res = { aaa: [1, 1, 1]; bbb: [2, 2, 2]; }

这里的 & string 可能大家会迷惑,解释一下:

因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是 string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型会把同一类型做合并,不同类型舍弃。

四.判断类型的类型

IsAny

如何判断一个类型是 any 类型呢?要根据它的特性来:

any 类型与任何类型的交叉都是 any,也就是 1 & any 结果是 any。

所以,可以这样写:

ts
type IsAny<T> = 'null' extends 'undefined' & T ? true : false;

IsEqual

之前我们实现 IsEqual 是这样写的:

ts
type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

问题出在 any 的判断上:

ts
type IsEqualResult = IsEqual<'aaa', any>;
+// type IsEqualResult = false

因为 any 可以是任何类型,任何类型也都是 any,所以当这样写判断不出 any 类型来。

所以,我们会这样写:

ts
type IsEqual<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;

这样就能正常判断了:

其中 T 是不传类型的,相当于一个临时变量

其目的是对比:

ts
<T>() => T extends X ? 1 : 2
+<T>() => T extends Y ? 1 : 2

这两个泛型函数类型是否相等,原理

IsUnion

还记得怎么判断 union 类型么?要根据它遇到条件类型时会分散成单个传入做计算的特性:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

IsNever

never 在条件类型中也比较特殊,如果条件类型左边是类型参数,并且传入的是 never,那么直接返回 never:

ts
type TestNever<T> = T extends number ? 1 : 2;

当 T 为 never 时:

ts
type TestNeverResult = TestNever<never>;
+// type TestNeverResult = never

所以,要判断 never 类型,就不能直接 T extends number,可以这样写:

ts
type IsNever<T> = [T] extends [never] ? true : false;

这样就能正常判断 never 类型了:

ts
type TestNeverResult = IsNever<never>;
+// type TestNeverResult = true

除此以外,any 在条件类型中也比较特殊,如果类型参数为 any,会直接返回 trueType 和 falseType 的合并:

ts
type TestAny<T> = T extends number ? 1 : 2;
+
+type TestAnyResult = TestAny<any>;
+// type TestAnyResult = 1 | 2

联合类型、never、any 在作为条件类型的类型参数时的这些特殊情况,也会在后面的原理篇来解释原因。

IsTuple

元组类型怎么判断呢?它和数组有什么区别呢?

元组类型的 length 是数字字面量,而数组的 length 是 number。

ts
type len

UnionToIntersection

类型之间是有父子关系的,更具体的那个是子类型,比如 A 和 B 的交叉类型 A & B 就是联合类型 A | B 的子类型,因为更具体。

如果允许父类型赋值给子类型,就叫做逆变

如果允许子类型赋值给父类型,就叫做协变

(关于逆变、协变等概念的详细解释可以看原理篇)

在 TypeScript 中有函数参数是有逆变的性质的,也就是如果参数可能是多个类型,参数类型会变成它们的交叉类型。

所以联合转交叉可以这样实现 :

ts
type UnionToIntersection<U> = (U extends U ? (x: U) => unknown : never) extends (x: infer R) => unknown ? R : never;

类型参数 U 是要转换的联合类型。

U extends U 是为了触发联合类型的 distributive 的性质,让每个类型单独传入做计算,最后合并。

利用 U 做为参数构造个函数,通过模式匹配取参数的类型。

结果就是交叉类型

函数参数的逆变性质一般就联合类型转交叉类型会用,记住就行。

GetOptional

如何提取索引类型中的可选索引呢?

这也要利用可选索引的特性:可选索引的值为 undefined 和值类型的联合类型。

过滤可选索引,就要构造一个新的索引类型,过程中做过滤:

ts
type GetOptional<Obj extends Record<string, any>> = {
+  [Key in keyof Obj as {} extends Pick<Obj, Key> ? Key : never]: Obj[Key];
+};

类型参数 Obj 为待处理的索引类型,类型约束为索引为 string、值为任意类型的索引类型 Record<string, any>。

用映射类型的语法重新构造索引类型,索引是之前的索引也就是 Key in keyof Obj,但要做一些过滤,也就是 as 之后的部分。

过滤的方式就是单独取出该索引之后,判断空对象是否是其子类型。

这里的 Pick 是 ts 提供的内置高级类型,就是取出某个 Key 构造新的索引类型:

ts
type Pick<T, K extends keyof T> = { [P in K]: T[P] };

比如单独取出 age 构造的新的索引类型是这样的:

可选的意思是这个索引可能没有,没有的时候,那 Pick<Obj, Key> 就是空的,所以 {} extends Pick<Obj, Key> 就能过滤出可选索引。

值的类型依然是之前的,也就是 Obj[Key]。

这样,就能过滤出所有可选索引,构造成新的索引类型:

总结

  • any 类型与任何类型的交叉都是 any,也就是 1 & any 结果是 any,可以用这个特性判断 any 类型。
  • 联合类型作为类型参数出现在条件类型左侧时,会分散成单个类型传入,最后合并。
  • never 作为类型参数出现在条件类型左侧时,会直接返回 never。
  • any 作为类型参数出现在条件类型左侧时,会直接返回 trueType 和 falseType 的联合类型。
  • 元组类型也是数组类型,但 length 是数字字面量,而数组的 length 是 number。可以用来判断元组类型。
  • 函数参数处会发生逆变,可以用来实现联合类型转交叉类型。
  • 可选索引的索引可能没有,那 Pick 出来的就可能是 {},可以用来过滤可选索引,反过来也可以过滤非可选索引。
  • 索引类型的索引为字符串字面量类型,而可索引签名不是,可以用这个特性过滤掉可索引签名。
  • keyof 只能拿到 class 的 public 的索引,可以用来过滤出 public 的属性。
  • 默认推导出来的不是字面量类型,加上 as const 可以推导出字面量类型,但带有 readonly 修饰,这样模式匹配的时候也得加上 readonly 才行。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/typescript/pattern.html b/cn/src/article/typescript/pattern.html new file mode 100644 index 0000000000..5cf1657d56 --- /dev/null +++ b/cn/src/article/typescript/pattern.html @@ -0,0 +1,141 @@ + + + + + + 模式匹配提取 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

模式匹配提取

字符串可以和正则做模式匹配,找到匹配的部分,提取子组,之后可以用 1,2 等引用匹配的子组。

ts
'abc'.replace(/a(b)c/, '$1,$1,$1');
+// 'b,b,b'

Typescript 的类型也同样可以做模式匹配。

比如这样一个 Promise 类型:

ts
type p = Promise<'value'>;

我们想提取 value 的类型,可以这样做:

ts
type GetValueType<P> = P extends Promise<infer Value> ? Value : never;

通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取的,通过 infer 声明一个局部变量 Value 来保存,如果匹配,就返回匹配到的 Value,否则就返回 never 代表没匹配到。

ts
// type GetValueResult = 'value'
+type GetValueResult = GetValueType<Promise<'value'>>;

这就是 Typescript 类型的模式匹配:

Typescript 类型的模式匹配是通过 extends 对类型参数做匹配,结果保存到通过 infer 声明的局部类型变量里,如果匹配就能从该局部变量里拿到提取出的类型。

这个模式匹配的套路有多有用呢?我们来看下在数组、字符串、函数、构造器等类型里的应用。

1.数组类型

提取第一个元素

数组类型想提取第一个元素的类型怎么做呢?

ts
type arr = [1, 2, 3];

用它来匹配一个模式类型,提取第一个元素的类型到通过 infer 声明的局部变量里返回。

ts
type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;

类型参数 Arr 通过 extends 约束为只能是数组类型,数组元素是 unkown 也就是可以是任何值。

any 和 unknown 的区别: any 和 unknown 都代表任意类型,但是 unknown 只能接收任意类型的值,而 any 除了可以接收任意类型的值,也可以赋值给任意类型(除了 never)。类型体操中经常用 unknown 接受和匹配任何类型,而很少把任何类型赋值给某个类型变量。

对 Arr 做模式匹配,把我们要提取的第一个元素的类型放到通过 infer 声明的 First 局部变量里,后面的元素可以是任何类型,用 unknown 接收,然后把局部变量 First 返回。

当类型参数 Arr 为 [1,2,3] 时:

ts
type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;
+type GetFirstValue = GetFirst<[1, 2, 3]>;
+// type GetFirstValue = 1

当类型参数 Arr 为 [] 时:

ts
type GetFirstResult = GetFirst<[]>;
+// type GetFirstResult = never

提取最后一个元素

可以提取第一个元素,当然也可以提取最后一个元素,修改下模式类型就行:

ts
type GetLastValue<Arr extends unknown[]> = Arr extends [...unknown, infer Last] ? Last : never;

当类型参数 Arr 为 [1,2,3]时:

ts
type GetLastResult = GetFirst<[1, 2, 3]>;
+// type GetLastResult = 3

PopArr

我们分别取了首尾元素,当然也可以取剩余的数组,比如取去掉了最后一个元素的数组:

ts
type PopArr<Arr extends unknown[]> = Arr extends [...infer Rest, unknown] ? Rest : never;

如果是空数组,就直接返回,否则匹配剩余的元素,放到 infer 声明的局部变量 Rest 里,返回 Rest。

当类型参数 Arr 为 [1,2,3] 时:

ts
type PopResult = PopArr<[1, 2, 3]>;
+// type PopResult = [1,2]

当类型参数 Arr 为 [] 时:

ts
type PopResult = PopArr<[]>;
+// type PopResult = []

ShiftArr

同理可得 ShiftArr 的实现:

ts
type ShiftArr<Arr extends unknown[]> = Arr extends [unknown, ...infer Rest] ? Rest : never;

当类型参数 Arr 为 [1,2,3]时:

ts
type ShiftResult = ShiftArr<[1, 2, 3]>;
+// type ShiftResult = [2,3]

2.字符串类型

字符串类型也同样可以做模式匹配,匹配一个模式字符串,把需要提取的部分放到 infer 声明的局部变量里。

StartsWith

判断字符串是否以某个前缀开头,也是通过模式匹配:

ts
type StartWith<str extends string, Prefix extends string> = Str extends `${Prefix}${string}` ? true : false;

需要声明字符串 Str、匹配的前缀 Prefix 两个类型参数,它们都是 string。

用 Str 去匹配一个模式类型,模式类型的前缀是 Prefix,后面是任意的 string,如果匹配返回 true,否则返回 false。

当匹配时:

ts
type StartWithResult = StartWidth<'prefix string', 'prefix'>;
+// type StartWithResult = true

不匹配时:

ts
type StartWithResult = StartWidth<'prefix string', 'string'>;
+// type StartWithResult = false

Replace

字符串可以匹配一个模式类型,提取想要的部分,自然也可以用这些再构成一个新的类型。

比如实现字符串替换:

ts
type ReplaceStr<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends `${infer Prefix}${From}${infer Suffix}` ? `${Prefix}${To}${Suffix}` : Str;

声明要替换的字符串 Str、待替换的字符串 From、替换成的字符串 3 个类型参数,通过 extends 约束为都是 string 类型。

用 Str 去匹配模式串,模式串由 From 和之前之后的字符串构成,把之前之后的字符串放到通过 infer 声明的局部变量 Prefix、Suffix 里。

用 Prefix、Suffix 加上替换到的字符串 To 构造成新的字符串类型返回。

当匹配时:

ts
type ReplaceResult = ReplaceStr<'str replace to result', 'result', 'aaaa'>;
+// type ReplaceResult =  'str replace to aaaa'

不匹配时:

ts
type ReplaceResult = ReplaceStr<'str replace to result', '???', 'aaaa'>;
+// type ReplaceResult =  'str replace to result'

Trim

能够匹配和替换字符串,那也就能实现去掉空白字符的 Trim:

不过因为我们不知道有多少个空白字符,所以只能一个个匹配和去掉,需要递归。

先实现 TrimRight:

ts
type TrimRight<Str extends string> = Str extends `${infer Rest}${' ' | '\n''\t'}` ? TrimRight<Rest> : Str

类型参数 Str 是要 Trim 的字符串。

如果 Str 匹配字符串 + 空白字符 (空格、换行、制表符),那就把字符串放到 infer 声明的局部变量 Rest 里。

把 Rest 作为类型参数递归 TrimRight,直到不匹配,这时的类型参数 Str 就是处理结果。

ts
type TrimRightResult = TrimRight<'value          '>;
+// type TrimRightResult = 'value'

同理可得 TrimLeft:

ts
type TrimLeft<Str extends string> = Str extends `${' '|'\n'|'\t'}`${infer Rest} ? TrimLeft<Rest> : Str

TrimRight 和 TrimLeft 结合就是 Trim:

ts
type Trim<Str extends string> = TrimRight<TrimLeft<Str>>;

3.函数

函数同样也可以做类型匹配,比如提取参数、返回值的类型。

GetParameters

函数类型可以通过模式匹配来提取参数的类型:

ts
type GetParameters<Func extends Function> = Func extends (...args: infer Args) => unknown ? Args : never;

类型参数 Func 是要匹配的函数类型,通过 extends 约束为 Function。

Func 和模式类型做匹配,参数类型放到用 infer 声明的局部变量 Args 里,返回值可以是任何类型,用 unknown。

返回提取到的参数类型 Args。

ts
type GetParametersResult = GetParameters<(name: string, age: number) => string>;
+// type GetParametersResult = [name:string,age:number]

GetReturnType

能提取参数类型,同样也可以提取返回值类型:

ts
type GetReturnType<Func extends Function> = Func extends (...args: unknown[]) => infer ReturnType ? ReturnType : never;

Func 和模式类型做匹配,提取返回值到通过 infer 声明的局部变量 ReturnType 里返回。

参数类型可以是任意类型,也就是 any[](注意,这里不能用 unknown,这里的解释涉及到参数的逆变性质,具体原因逆变那一节会解释)。

ts
type GetReturnTypeResult = GetReturnType<() => 'return value'>;
+// type GetReturnTypeResult = 'return value'

GetThisParameterType

方法里可以调用 this,比如这样:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello() {
+    return "hello, I'm " + this.name;
+  }
+}
+
+const dong = new Dong();
+dong.hello();

用对象.方法名的方式调用的时候,this 就指向那个对象。

但是方法也可以用 call 或者 apply 调用:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello() {
+    return "hello, I'm " + this.name;
+  }
+}
+
+const dong = new Dong();
+dong.hello().call({ x: 1 });

call 调用的时候,this 就变了,但这里却没有被检查出来 this 指向的错误。

如何让编译器能够检查出 this 指向的错误呢?

可以在方法声明时指定 this 的类型:

ts
class Dong {
+  name: string;
+
+  constructor() {
+    this.name = 'dong';
+  }
+
+  hello(this: Dong) {
+    return "hello, I'm " + this.name;
+  }
+}

这样,当 call/apply 调用的时候,就能检查出 this 指向的对象是否是对的:

如果没有报错,说明没开启 strictBindCallApply 的编译选项,这个是控制是否按照原函数的类型来检查 bind、call、apply

这里的 this 类型同样也可以通过模式匹配提取出来:

ts
type GetThisParameterType<T> = T extends (this: infer This, ...args: unknown[]) => unknown ? This : unknown;

类型参数 T 是待处理的类型。

用 T 匹配一个模式类型,提取 this 的类型到 infer 声明的局部变量 ThisType 中,其余的参数是任意类型,也就是 any,返回值也是任意类型。

返回提取到的 ThisType。

这样就能提取出 this 的类型:

4.构造器类型

构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

同样,我们也可以通过模式匹配提取构造器的参数和返回值的类型:

GetInstanceType

构造器类型可以用 interface 声明,使用 new(): xx 的语法。

比如:

ts
interface Person {
+  name: string;
+}
+
+interface PersonConstructor {
+  new (name: string): Person;
+}

这里的 PersonConstructor 返回的是 Person 类型的实例对象,这个也可以通过模式匹配取出来。

ts
type GetInstanceType<ConstructorType extends new (...args: any) => any> = ConstructorType extends new (
+  ...args: any
+) => infer InstanceType
+  ? InstanceType
+  : any;

类型参数 ConstructorType 是待处理的类型,通过 extends 约束为构造器类型。

用 ConstructorType 匹配一个模式类型,提取返回的实例类型到 infer 声明的局部变量 InstanceType 里,返回 InstanceType。

这样就能取出构造器对应的实例类型:

ts
interface PersonConstructor {
+  new (name: string): Person;
+}
+
+type GetInstanceTypeResult = GetInstanceType<PersonConstructor>;
+// type GetInstanceTypeResult = Person

GetConstructorParameters

GetInstanceType 是提取构造器返回值类型,那同样也可以提取构造器的参数类型:

ts
type GetConstructorParameters<ConstructorType extends new (...args: any) => any> = ConstructorType extends new (
+  ...args: infer ParametersType
+) => any
+  ? ParametersType
+  : never;

类型参数 ConstructorType 为待处理的类型,通过 extends 约束为构造器类型。

用 ConstructorType 匹配一个模式类型,提取参数的部分到 infer 声明的局部变量 ParametersType 里,返回 ParametersType。

这样就能提取出构造器对应的参数类型:

ts
interface PersonConstructor {
+  new (name: string): Person;
+}
+
+type GetConstructorParametersResult = GetConstructorParameters<PersonConstructor>;
+// type GetConstructorParametersResult = [name:string]

索引类型

索引类型也同样可以用模式匹配提取某个索引的值的类型,这个用的也挺多的,比如 React 的 index.d.ts 里的 PropsWithRef 的高级类型,就是通过模式匹配提取了 ref 的值的类型:

ts
type PropsWithRef<P> = 'ref' extends keyof P
+  ? P extends { ref?: infer R | undefined }
+    ? string extends R
+      ? PropsWithRef<P> & { ref?: Exclude<R, string> | undefined }
+      : P
+    : P
+  : P;

我们简化一下那个高级类型,提取 Props 里 ref 的类型:

ts
type GetPropsRef<Props> = 'ref' extends keyof Props
+  ? Props extends { ref?: infer Value | undefined }
+    ? value
+    : never
+  : never;

类型参数 Props 为待处理的类型。

通过 keyof Props 取出 Props 的所有索引构成的联合类型,判断下 ref 是否在其中,也就是 'ref' extends keyof Props。

为什么要做这个判断,上面注释里写了:

在 ts3.0 里面如果没有对应的索引,Obj[Key] 返回的是 {} 而不是 never,所以这样做下兼容处理。

如果有 ref 这个索引的话,就通过 infer 提取 Value 的类型返回,否则返回 never。

ts
type GetPropsRefResult = GetPropsRef<{ ref: 1; name: 'str' }>;
+// type GetPropsRefResult = 1

当 ref 为 undefined 时:

ts
type GetPropsRefResult = GetPropsRef<{ ref: undefined; name: 'str' }>;
+// type GetPropsRefResult = undefined

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/typescript/reconstruction.html b/cn/src/article/typescript/reconstruction.html new file mode 100644 index 0000000000..227cfa7465 --- /dev/null +++ b/cn/src/article/typescript/reconstruction.html @@ -0,0 +1,96 @@ + + + + + + 重新构造做变换 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

重新构造做变换

类型编程主要的目的就是对类型做各种转换,那么如何对类型做修改呢?

TypeScript 类型系统支持 3 种可以声明任意类型的变量: type、infer、类型参数。

type 叫做类型别名,其实就是声明一个变量存储某个类型:

ts
type ttt = Promise<number>;

infer 用于类型的提取,然后存到一个变量里,相当于局部变量:

ts
type GetValueType<P> = P extends Promise<infer Value> ? Value : never;

类型参数用于接受具体的类型,在类型运算中也相当于局部变量:

ts
type isTwo<T> = T extends 2 ? true : false;

但是,严格来说这三种也都不叫变量,因为它们不能被重新赋值。

TypeScript 设计可以做类型编程的类型系统的目的就是为了产生各种复杂的类型,那不能修改怎么产生新类型呢?

答案是重新构造。

这就涉及到了第二个类型体操套路:重新构造做变换。

重新构造

TypeScript 的 type、infer、类型参数声明的变量都不能修改,想对类型做各种变换产生新的类型就需要重新构造。

数组、字符串、函数等类型的重新构造比较简单。

索引类型,也就是多个元素的聚合类型的重新构造复杂一些,涉及到了映射类型的语法。

我们先从简单的开始:

数组类型的重新构造

Push

有这样一个元组类型:

ts
type tuple = [1, 2, 3];

我想给这个元组类型再添加一些类型,怎么做呢?

TypeScript 类型变量不支持修改,我们可以构造一个新的元组类型:

ts
type Push<Arr extends unknown[], Ele> = [...Arr, Ele];

类型参数 Arr 是要修改的数组/元组类型,元素的类型任意,也就是 unknown。

类型参数 Ele 是添加的元素的类型。

返回的是用 Arr 已有的元素加上 Ele 构造的新的元组类型。

ts
type PushResult = Push<[1, 2, 3], 4>;
+// type PushResult = [1,2,3,4]

这就是数组/元组的重新构造。

数组和元组的区别:数组类型是指任意多个同一类型的元素构成的,比如 number[]Array<number>,而元组则是数量固定,类型可以不同的元素构成的,比如 [1, true, 'name']

Unshift

可以在后面添加,同样也可以在前面添加:

ts
type Unshift<Arr extends unknown[], Ele> = [Ele, ...Arr];

Zip

有这样两个元组:

ts
type tuple1 = [1, 2];
+type tuple2 = ['name', 'value'];

我们想把它们合并成这样的元组:

ts
type tuple = [[1, 'name'], [2, 'value']];

思路很容易想到,提取元组中的两个元素,构造成新的元组:

ts
type Zip<One extends [unknown, unknown], Other extends [unknown, unknown]> = One extends [
+  infer OneFirst,
+  infer OneSecond,
+]
+  ? Other extends [infer OtherFirst, infer OtherSecond]
+    ? [[OneFirst, OtherFirst], [OneSecond, OtherSecond]]
+    : []
+  : [];

两个类型参数 One、Other 是两个元组,类型是 [unknown, unknown],代表 2 个任意类型的元素构成的元组。

通过 infer 分别提取 One 和 Other 的元素到 infer 声明的局部变量 OneFirst、OneSecond、OtherFirst、OtherSecond 里。

用提取的元素构造成新的元组返回即可:

ts
type ZipResult = Zip<[1, 2], ['name', 'value']>;
+// type ZipResult = [[1, 'name'], [2, 'value']];

但是这样只能合并两个元素的元组,如果是任意个呢?

那就得用递归了:

ts
type Zip<One extends unknown[], Other extends unknown[]> = One extends [infer OneFirst, ...infer OneRest]
+  ? Other extends [infer OtherFirst, ...infer OtherRest]
+    ? [[OneFirst, OtherFirst], ...Zip<OneRest, OtherRest>]
+    : []
+  : [];

类型参数 One、Other 声明为 unknown[],也就是元素个数任意,类型任意的数组。

每次提取 One 和 Other 的第一个元素 OneFirst、OtherFirst,剩余的放到 OneRest、OtherRest 里。

用 OneFirst、OtherFirst 构造成新的元组的一个元素,剩余元素继续递归处理 OneRest、OtherRest。

这样,就能处理任意个数元组的合并:

ts
type ZipResult = Zip<[1, 2, 3, 4, 5], ['name', 'value', 'three', 'four', 'five']>;
+// type ZipResult = [[1, 'name'], [2, 'value'], [3, 'three'], [4, 'four'], [5, 'five']];

了解了数组类型的重新构造,我们再来看下字符串类型的:

字符串类型的重新构造

CapitalizeStr

我们想把一个字符串字面量类型的 'guang' 转为首字母大写的 'Guang'。

需要用到字符串类型的提取和重新构造:

ts
type CapitalizeStr<Str extends string> = Str extends `${infer First}${infer Rest}` ? `${Uppercase<First>}${Rest}` : Str;

我们声明了类型参数 Str 是要处理的字符串类型,通过 extends 约束为 string。

通过 infer 提取出首个字符到局部变量 First,提取后面的字符到局部变量 Rest。

然后使用 TypeScript 提供的内置高级类型 Uppercase 把首字母转为大写,加上 Rest,构造成新的字符串类型返回。

这就是字符串类型的重新构造:从已有的字符串类型中提取出一些部分字符串,经过一系列变换,构造成新的字符串类型。

CamelCase

我们再来实现 dong_dong_dong 到 dongDongDong 的变换。

同样是提取和重新构造:

ts
type CamelCase<Str extends string> = Str extends `${infer Left}_${infer Right}${infer Rest}`
+  ? `${Left}${Uppercase<Right>}${CamelCase<Rest>}`
+  : Str;

类型参数 Str 是待处理的字符串类型,约束为 string。

提取 _ 之前和之后的两个字符到 infer 声明的局部变量 Left 和 Right,剩下的字符放到 Rest 里。

然后把右边的字符 Right 大写,和 Left 构造成新的字符串,剩余的字符 Rest 要继续递归的处理。

这样就完成了从下划线到驼峰形式的转换:

DropSubStr

可以修改自然也可以删除,我们再来做一个删除一段字符串的案例:删除字符串中的某个子串

ts
type DropSubStr<Str extends string, SubStr extends string> = Str extends `${infer Prefix}${SubStr}${infer Suffix}`
+  ? DropSubStr<`${Prefix}${Suffix}`, SubStr>
+  : Str;

类型参数 Str 是待处理的字符串, SubStr 是要删除的字符串,都通过 extends 约束为 string 类型。

通过模式匹配提取 SubStr 之前和之后的字符串到 infer 声明的局部变量 Prefix、Suffix 中。

如果不匹配就直接返回 Str。

如果匹配,那就用 Prefix、Suffix 构造成新的字符串,然后继续递归删除 SubStr。直到不再匹配,也就是没有 SubStr 了。

字符串类型的重新构造之后,我们再来看下函数类型的重新构造:

函数类型的重新构造

AppendArgument

之前我们分别实现了参数和返回值的提取,那么重新构造就是用这些提取出的类型做下修改,构造一个新的类型即可。

比如在已有的函数类型上添加一个参数:

ts
type AppendArgument<Func extends Function, Arg> = Func extends (...args: infer Args) => infer ReturnType
+  ? (...args: [...Args, Arg]) => ReturnType
+  : never;

类型参数 Func 是待处理的函数类型,通过 extends 约束为 Function,Arg 是要添加的参数类型。

通过模式匹配提取参数到 infer 声明的局部变量 Args 中,提取返回值到局部变量 ReturnType 中。

用 Args 数组添加 Arg 构造成新的参数类型,结合 ReturnType 构造成新的函数类型返回。

这样就完成了函数类型的修改:

最后,我们再来看下索引类型的重新构造

索引类型的重新构造

索引类型是聚合多个元素的类型,class、对象等都是索引类型,比如这就是一个索引类型:

ts
type obj = {
+  name: string;
+  age: number;
+  gender: boolean;
+};

索引类型可以添加修饰符 readonly(只读)、?(可选):

ts
type obj = {
+  readonly name: string;
+  age?: number;
+  gender: boolean;
+};

对它的修改和构造新类型涉及到了映射类型的语法:

ts
type Mapping<Obj extends object> = {
+  [Key in keyof Obj]: Obj[Key];
+};

Mapping

映射的过程中可以对 value 做下修改,比如:

ts
type Mapping<Obj extends object> = {
+  [Key in keyof Obj]: [Obj[Key], Obj[Key], Obj[Key]];
+};

类型参数 Obj 是待处理的索引类型,通过 extends 约束为 object。

用 keyof 取出 Obj 的索引,作为新的索引类型的索引,也就是 Key in keyof Obj。

值的类型可以做变换,这里我们用之前索引类型的值 Obj[Key] 构造成了三个元素的元组类型 [Obj[Key], Obj[Key], Obj[Key]]:

UppercaseKey

除了可以对 Value 做修改,也可以对 Key 做修改,使用 as,这叫做重映射:

比如把索引类型的 Key 变为大写。

ts
type UppercaseKey<Obj extends object> = {
+  [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key];
+};

类型参数 Obj 是待处理的索引类型,通过 extends 约束为 object。

新的索引类型的索引为 Obj 中的索引,也就是 Key in keyof Obj,但要做一些变换,也就是 as 之后的。

通过 Uppercase 把索引 Key 转为大写,因为索引可能为 string、number、symbol 类型,而这里只能接受 string 类型,所以要 & string,也就是取索引中 string 的部分。

value 保持不变,也就是之前的索引 Key 对应的值的类型 Obj[Key]。

这样构造出的新的索引类型,就把原来索引类型的索引转为了大写:

Record

TypeScript 提供了内置的高级类型 Record 来创建索引类型:

ts
type Record<K extends string | number | symbol, T> = { [P in K]: T };

指定索引和值的类型分别为 K 和 T,就可以创建一个对应的索引类型。

上面的索引类型的约束我们用的 object,其实更语义化一点我推荐用 Record<string, any>:

ts
type UppercaseKey<Obj extends Record<string, any>> = {
+  [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key];
+};

也就是约束类型参数 Obj 为 key 为 string,值为任意类型的索引类型。

ToReadonly

索引类型的索引可以添加 readonly 的修饰符,代表只读。

那我们就可以实现给索引类型添加 readonly 修饰的高级类型:

ts
type ToReadonly<T> = {
+  readonly [Key in keyof T]: T[Key];
+};

通过映射类型构造了新的索引类型,给索引加上了 readonly 的修饰,其余的保持不变,索引依然为原来的索引 Key in keyof T,值依然为原来的值 T[Key]。

ToPartial

同理,索引类型还可以添加可选修饰符:

ts
type ToPartial<T> = {
+  [Key in keyof T]?: T[Key];
+};

给索引类型 T 的索引添加了 ? 可选修饰符,其余保持不变。

ToMutable

可以添加 readonly 修饰,当然也可以去掉:

ts
type ToMutable<T> = {
+  -readonly [Key in keyof T]: T[Key];
+};

给索引类型 T 的每个索引去掉 readonly 的修饰,其余保持不变。

ToRequired

同理,也可以去掉可选修饰符:

ts
type ToRequired<T> = {
+  [Key in keyof T]-?: T[Key];
+};

给索引类型 T 的索引去掉 ? 的修饰 ,其余保持不变。

FilterByValueType

可以在构造新索引类型的时候根据值的类型做下过滤:

ts
type FilterByValueType<Obj extends Record<string, any>, ValueType> = {
+  [Key in keyof Obj as Obj[Key] extends ValueType ? Key : never]: Obj[Key];
+};

类型参数 Obj 为要处理的索引类型,通过 extends 约束为索引为 string,值为任意类型的索引类型 Record<string, any>。

类型参数 ValueType 为要过滤出的值的类型。

构造新的索引类型,索引为 Obj 的索引,也就是 Key in keyof Obj,但要做一些变换,也就是 as 之后的部分。

如果原来索引的值 Obj[Key] 是 ValueType 类型,索引依然为之前的索引 Key,否则索引设置为 never,never 的索引会在生成新的索引类型时被去掉。

值保持不变,依然为原来索引的值,也就是 Obj[Key]。

这样就达到了过滤索引类型的索引,产生新的索引类型的目的:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/typescript/recursion.html b/cn/src/article/typescript/recursion.html new file mode 100644 index 0000000000..9c014a2364 --- /dev/null +++ b/cn/src/article/typescript/recursion.html @@ -0,0 +1,113 @@ + + + + + + 递归复用 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

递归复用

递归是把问题分解为一系列相似的小问题,通过函数不断调用自身来解决这一个个小问题,直到满足结束条件,就完成了问题的求解。

TypeScript 的高级类型支持类型参数,可以做各种类型运算逻辑,返回新的类型,和函数调用是对应的,自然也支持递归。

TypeScript 类型系统不支持循环,但支持递归。当处理数量(个数、长度、层数)不固定的类型的时候,可以只处理一个类型,然后递归的调用自身处理下一个类型,直到结束条件也就是所有的类型都处理完了,就完成了不确定数量的类型编程,达到循环的效果。

既然提到了数组、字符串、对象等类型,那么我们就来看一下这些类型的递归案例吧。

Promise 的递归复用

DeepPromiseValueType

先用 Promise 热热身,实现一个提取不确定层数的 Promise 中的 value 类型的高级类型。

ts
type ttt = Promise<Promise<Promise<Record<string, any>>>>;

这里是 3 层 Promise,value 类型是索引类型。

数量不确定,一涉及到这个就要想到用递归来做,每次只处理一层的提取,然后剩下的到下次递归做,直到结束条件。

所以高级类型是这样的:

ts
type DeepPromiseValueType<P extends Promise<unknown>> =
+  P extends Promise<infer ValueType>
+    ? ValueType extends Promise<unknown>
+      ? DeepPromiseValueType<ValueType>
+      : ValueType
+    : never;

类型参数 P 是待处理的 Promise,通过 extends 约束为 Promise 类型,value 类型不确定,设为 unknown。

每次只处理一个类型的提取,也就是通过模式匹配提取出 value 的类型到 infer 声明的局部变量 ValueType 中。

然后判断如果 ValueType 依然是 Promise 类型,就递归处理。

结束条件就是 ValueType 不为 Promise 类型,那就处理完了所有的层数,返回这时的 ValueType。

这样,我们就提取到了最里层的 Promise 的 value 类型,也就是索引类型:

其实这个类型的实现可以进一步的简化:

ts
type DeepPromiseValueType2<T> = T extends Promise<infer ValueType> ? DeepPromiseValueType2<ValueType> : T;

不再约束类型参数必须是 Promise,这样就可以少一层判断。

接下来再看下数组类型的递归复用:

数组类型的递归

ReverseArr

有这样一个元组类型:

ts
type arr = [1, 2, 3, 4, 5];

我们把它反过来,也就是变成:

ts
type arr = [5, 4, 3, 2, 1];

这个学完了提取和构造很容易写出来:

ts
type ReverseArr<Arr extends unknown[]> = Arr extends [infer One, infer Two, infer Three, infer Four, infer Five]
+  ? [Five, Four, Three, Two, One]
+  : never;

但如果数组长度不确定呢?

数量不确定,条件反射的就要想到递归。

我们每次只处理一个类型,剩下的递归做,直到满足结束条件。

ts
type ReverseArr<Arr extends unknown[]> = Arr extends [infer First, ...infer Rest] ? [...ReverseArr<Rest>, First] : Arr;

类型参数 Arr 为待处理的数组类型,元素类型不确定,也就是 unknown。

每次只处理一个元素的提取,放到 infer 声明的局部变量 First 里,剩下的放到 Rest 里。

用 First 作为最后一个元素构造新数组,其余元素递归的取。

结束条件就是取完所有的元素,也就是不再满足模式匹配的条件,这时候就返回 Arr。

Includes

既然递归可以做循环用,那么像查找元素这种自然也就可以实现。

比如查找 [1, 2, 3, 4, 5] 中是否存在 4,是就返回 true,否则返回 false。

从长度不固定的数组中查找某个元素,数量不确定,这时候就应该想到递归。

ts
type Includes<Arr extends unknown[], FindItem> = Arr extends [infer First, ...infer Rest]
+  ? IsEqual<First, FindItem> extends true
+    ? true
+    : Includes<Rest, FindItem>
+  : false;
+
+type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

类型参数 Arr 是待查找的数组类型,元素类型任意,也就是 unknown。FindItem 待查找的元素类型。

每次提取一个元素到 infer 声明的局部变量 First 中,剩余的放到局部变量 Rest。

判断 First 是否是要查找的元素,也就是和 FindItem 相等,是的话就返回 true,否则继续递归判断下一个元素。

直到结束条件也就是提取不出下一个元素,这时返回 false。

相等的判断就是 A 是 B 的子类型并且 B 也是 A 的子类型,。

这样就完成了不确定长度的数组中的元素查找,用递归实现了循环。

RemoveItem

可以查找自然就可以删除,只需要改下返回结果,构造一个新的数组返回。

ts
type RemoveItem<Arr extends unknown[], Item, Result extends unknown[] = []> = Arr extends [infer First, ...infer Rest]
+  ? IsEqual<First, Item> extends true
+    ? RemoveItem<Rest, Item, Result>
+    : RemoveItem<Rest, Item, [...Result, First]>
+  : Result;
+
+type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

类型参数 Arr 是待处理的数组,元素类型任意,也就是 unknown[]。类型参数 Item 为待查找的元素类型。类型参数 Result 是构造出的新数组,默认值是 []。

通过模式匹配提取数组中的一个元素的类型,如果是 Item 类型的话就删除,也就是不放入构造的新数组,直接返回之前的 Result。

否则放入构造的新数组,也就是再构造一个新的数组 [...Result, First]。

直到模式匹配不再满足,也就是处理完了所有的元素,返回这时候的 Result。

这样我们就完成了不确定元素个数的数组的某个元素的删除:

BuildArray

我们学过数组类型的构造,如果构造的数组类型元素个数不确定,也需要递归。

比如传入 5 和元素类型,构造一个长度为 5 的该元素类型构成的数组。

ts
type BuildArray<Length extends number, Ele = unknown, Arr extends unknown[] = []> = Arr['length'] extends Length
+  ? Arr
+  : BuildArray<Length, Ele, [...Arr, Ele]>;

类型参数 Length 为数组长度,约束为 number。类型参数 Ele 为元素类型,默认值为 unknown。类型参数 Arr 为构造出的数组,默认值是 []。

每次判断下 Arr 的长度是否到了 Length,是的话就返回 Arr,否则在 Arr 上加一个元素,然后递归构造。

学完了数组类型的递归,我们再来看下字符串类型。

字符串类型的递归

ReplaceAll

学模式匹配的时候,我们实现过一个 Replace 的高级类型:

ts
type ReplaceStr<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends `${infer Prefix}${From}${infer Suffix}` ? `${Prefix}${To}${Suffix}` : Str;

它能把一个字符串中的某个字符替换成另一个:

但是如果有多个这样的字符就处理不了了。

如果不确定有多少个 From 字符,怎么处理呢?

在类型体操里,遇到数量不确定的问题,就要条件反射的想到递归。

每次递归只处理一个类型,这部分我们已经实现了,那么加上递归的调用就可以。

ts
type ReplaceAll<
+  Str extends string,
+  From extends string,
+  To extends string,
+> = Str extends `${infer Left}${From}${infer Right}` ? `${Left}${To}${ReplaceAll<Right, From, To>}` : Str;

类型参数 Str 是待处理的字符串类型,From 是待替换的字符,To 是替换到的字符。

通过模式匹配提取 From 左右的字符串到 infer 声明的局部变量 Left 和 Right 里。

用 Left 和 To 构造新的字符串,剩余的 Right 部分继续递归的替换。

结束条件是不再满足模式匹配,也就是没有要替换的元素,这时就直接返回字符串 Str。

这样就实现了任意数量的字符串替换:

StringToUnion

我们想把字符串字面量类型的每个字符都提取出来组成联合类型,也就是把 'dong' 转为 'd' | 'o' | 'n' | 'g'。

怎么做呢?

很明显也是提取和构造:

ts
type StringToUnion<Str extends string> = Str extends `${infer One}${infer Two}${infer Three}${infer Four}`
+  ? One | Two | Three | Four
+  : never;

但如果字符串长度不确定呢?

数量不确定,在类型体操中就要条件反射的想到递归。

ts
type StringToUnion<Str extends string> = Str extends `${infer First}${infer Rest}`
+  ? First | StringToUnion<Rest>
+  : never;

类型参数 Str 为待处理的字符串类型,通过 extends 约束为 string。

通过模式匹配提取第一个字符到 infer 声明的局部变量 First,其余的字符放到局部变量 Rest。

用 First 构造联合类型,剩余的元素递归的取。

这样就完成了不确定长度的字符串的提取和联合类型的构造:

ReverseStr

我们实现了数组的反转,自然也可以实现字符串类型的反转。

同样是递归提取和构造。

ts
type ReverseStr<Str extends string, Result extends string = ''> = Str extends `${infer First}${infer Rest}`
+  ? ReverseStr<Rest, `${First}${Result}`>
+  : Result;

类型参数 Str 为待处理的字符串。类型参数 Result 为构造出的字符,默认值是空串。

通过模式匹配提取第一个字符到 infer 声明的局部变量 First,其余字符放到 Rest。

用 First 和之前的 Result 构造成新的字符串,把 First 放到前面,因为递归是从左到右处理,那么不断往前插就是把右边的放到了左边,完成了反转的效果。

直到模式匹配不满足,就处理完了所有的字符。

这样就完成了字符串的反转:

对象类型的递归

DeepReadonly

对象类型的递归,也可以叫做索引类型的递归。

我们之前实现了索引类型的映射,给索引加上了 readonly 的修饰:

ts
type ToReadonly<T> = {
+  readonly [Key in keyof T]: T[Key];
+};

如果这个索引类型层数不确定呢?

比如这样:

ts
type obj = {
+  a: {
+    b: {
+      c: {
+        f: () => 'dong';
+        d: {
+          e: {
+            guang: string;
+          };
+        };
+      };
+    };
+  };
+};

数量(层数)不确定,类型体操中应该自然的想到递归。

我们在之前的映射上加入递归的逻辑:

ts
type DeepReadonly<Obj extends Record<string, any>> = {
+  readonly [Key in keyof Obj]: Obj[Key] extends object
+    ? Obj[Key] extends Function
+      ? Obj[Key]
+      : DeepReadonly<Obj[Key]>
+    : Obj[Key];
+};

类型参数 Obj 是待处理的索引类型,约束为 Record<string, any>,也就是索引为 string,值为任意类型的索引类型。

索引映射自之前的索引,也就是 Key in keyof Obj,只不过加上了 readonly 的修饰。

值要做下判断,如果是 object 类型并且还是 Function,那么就直接取之前的值 Obj[Key]。

如果是 object 类型但不是 Function,那就是说也是一个索引类型,就递归处理 DeepReadonly<Obj[Key]>。

否则,值不是 object 就直接返回之前的值 Obj[Key]。

这样就完成了任意层数的索引类型的添加 readonly 修饰:

我们取处理以后的索引 a 的值看一下,发现 b 已经加上了 readonly 修饰。

测试一下:

为啥这里没有计算呀?

因为 ts 的类型只有被用到的时候才会做计算。

所以可以在前面加上一段 Obj extends never ? never 或者 Obj extends any 等,从而触发计算:

ts
type DeepReadonly<Obj extends Record<string, any>> = Obj extends any
+  ? {
+      readonly [Key in keyof Obj]: Obj[Key] extends object
+        ? Obj[Key] extends Function
+          ? Obj[Key]
+          : DeepReadonly<Obj[Key]>
+        : Obj[Key];
+    }
+  : never;

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/typescript/unionType.html b/cn/src/article/typescript/unionType.html new file mode 100644 index 0000000000..940640fb6a --- /dev/null +++ b/cn/src/article/typescript/unionType.html @@ -0,0 +1,69 @@ + + + + + + 分布式条件类型 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

分布式条件类型

当类型参数为联合类型,并且在条件类型左边直接引用该类型参数的时候,TypeScript 会把每一个元素单独传入来做类型运算,最后再合并成联合类型,这种语法叫做分布式条件类型。

比如这样一个联合类型:

ts
type Union = 'a' | 'b' | 'c';

我们想把其中的 a 大写,就可以这样写:

ts
type UppercaseA<Item extends string> = Item extends 'a' ? Uppercase<Item> : Item;
ts
type result = UppercaseA<Union>;
+// type result = 'A' | 'b' | 'c';

可以看到,我们类型参数 Item 约束为 string,条件类型的判断中也是判断是否是 a,但传入的是联合类型。

这就是 TypeScript 对联合类型在条件类型中使用时的特殊处理:会把联合类型的每一个元素单独传入做类型计算,最后合并。

这和联合类型遇到字符串时的处理一样:

这样确实是简化了类型编程逻辑的,不需要递归提取每个元素再处理。

TypeScript 之所以这样处理联合类型也很容易理解,因为联合类型的每个元素都是互不相关的,不像数组、索引、字符串那样元素之间是有关系的。所以设计成了每一个单独处理,最后合并。

知道了 TypeScript 怎么处理的联合类型,趁热打铁来练习一下:

CamelcaseUnion

Camelcase 我们实现过,就是提取字符串中的字符,首字母大写以后重新构造一个新的。

ts
type Camelcase<Str extends string> = Str extends `${infer Left}_${infer Right}${infer Rest}`
+  ? `${Left}${Uppercase<Right>}${Camelcase<Rest>}`
+  : Str;

提取 _ 左右的字符,把右边字符大写之后构造成新的字符串,余下的字符串递归处理。

ts
type CamelcaseResult = Camelcase<'aa_aa_aa'>;
+// type CamelcaseResult = 'aaAaAa'

如果是对字符串数组做 Camelcase,那就要递归处理每一个元素:

ts
type CamelcaseArr<Arr extends unknown[]> = Arr extends [infer Item, ...infer RestArr]
+  ? [Camelcase<Item & string>, ...CamelcaseArr<RestArr>]
+  : [];

类型参数 Arr 为待处理数组。

递归提取每一个元素做 Camelcase,因为 Camelcase 要求传入 string,这里要 & string 来变成 string 类型。

那如果是联合类型呢?

联合类型不需要递归提取每个元素,TypeScript 内部会把每一个元素传入单独做计算,之后把每个元素的计算结果合并成联合类型。

ts
type CamelcaseUnion<Item extends string> = Item extends `${infer Left}_${infer Right}${infer Rest}`
+  ? `${Left}${Uppercase<Right>}${CamelcaseUnion<Rest>}`
+  : Item;

这不和单个字符串的处理没区别么?

没错,对联合类型的处理和对单个类型的处理没什么区别,TypeScript 会把每个单独的类型拆开传入。不需要像数组类型那样需要递归提取每个元素做处理。

确实简化了很多,好像都是优点?

也不全是,其实这样处理也增加了一些认知成本,不信我们再来看个例子:

IsUnion

判断联合类型我们会这样写:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

当传入联合类型时,会返回 true:

ts
type IsUnionResult = IsUnion<'a' | 'b' 'c'>
+// type IsUnionResult = true

当传入其他类型时,会返回 false:

ts
type IsUnionResult = IsUnion<['a' | 'b' 'c']>
+// type IsUnionResult = false

这就是分布式条件类型带来的认知成本。

我们先来看这样一个类型:

ts
type TestUnion<A, B = A> = A extends A ? { a: A; b: B } : never;
+
+type TestUnionResult = TestUnion<'a' | 'b' | 'c'>;

传入联合类型 'a' | 'b' | 'c' 的时候,结果是这样的:

A 和 B 都是同一个联合类型,为啥值还不一样呢?

因为条件类型中如果左边的类型是联合类型,会把每个元素单独传入做计算,而右边不会。

所以 A 是 'a' 的时候,B 是 'a' | 'b' | 'c', A 是 'b' 的时候,B 是 'a' | 'b' | 'c'。。。

那么利用这个特点就可以实现 Union 类型的判断:

ts
type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

类型参数 A、B 是待判断的联合类型,B 默认值为 A,也就是同一个类型。

A extends A 这段看似没啥意义,主要是为了触发分布式条件类型,让 A 的每个类型单独传入。

[B] extends [A] 这样不直接写 B 就可以避免触发分布式条件类型,那么 B 就是整个联合类型。

B 是联合类型整体,而 A 是单个类型,自然不成立,而其它类型没有这种特殊处理,A 和 B 都是同一个,怎么判断都成立。

利用这个特点就可以判断出是否是联合类型。

其中有两个点比较困惑,我们重点记一下:

当 A 是联合类型时:

A extends A 这种写法是为了触发分布式条件类型,让每个类型单独传入处理的,没别的意义。

A extends A 和 [A] extends [A] 是不同的处理,前者是单个类型和整个类型做判断,后者两边都是整个联合类型,因为只有 extends 左边直接是类型参数才会触发分布式条件类型。

理解了这两点,分布式条件类型就算掌握了。

BEM

bem 是 css 命名规范,用 block__element--modifier 的形式来描述某个区块下面的某个元素的某个状态的样式。

那么我们可以写这样一个高级类型,传入 block、element、modifier,返回构造出的 class 名:

这样使用:

ts
type bemResult = BEM<'guang', ['aaa', 'bbb'], ['warning', 'success']>;

它的实现就是三部分的合并,但传入的是数组,要递归遍历取出每一个元素来和其他部分组合,这样太麻烦了。

而如果是联合类型就不用递归遍历了,因为联合类型遇到字符串也是会单独每个元素单独传入做处理。

数组转联合类型可以这样写:

ts
type union = ['aaa', 'bbb'][number];
+// type union = 'aaa' | 'bbb'

那么 BEM 就可以这样实现:

ts
type BEM<
+  Block extends string,
+  Element extends string[],
+  Modifiers extends string[],
+> = `${Block}__${Element[number]}--${Modifiers[number]}`;

类型参数 Block、Element、Modifiers 分别是 bem 规范的三部分,其中 Element 和 Modifiers 都可能多个,约束为 string[]。

构造一个字符串类型,其中 Element 和 Modifiers 通过索引访问来变为联合类型。

字符串类型中遇到联合类型的时候,会每个元素单独传入计算,也就是这样的效果:

ts
type RemResult = BEM<'a', ['b', 'c'], ['d', 'e']>;
+// type RemResult = 'a__b--d' | 'a__b--e' | 'a__c--d' | 'a__b--e'

可以看到,用好了联合类型,确实能简化类型编程逻辑。

AllCombinations

我们再来实现一个全组合的高级类型,也是联合类型相关的:

希望传入 'A' | 'B' 的时候,能够返回所有的组合: 'A' | 'B' | 'BA' | 'AB'。

这种全组合问题的实现思路就是两两组合,组合出的字符串再和其他字符串两两组和:

比如 'A' | 'B' | 'c',就是 A 和 B、C 组合,B 和 A、C 组合,C 和 A、B 组合。然后组合出来的字符串再和其他字符串组合。

任何两个类型的组合有四种:A、B、AB、BA

ts
type Combination<A extends string, B extends string> = A | B | `${A}${B}` | `${B}${A}`;

然后构造出来的字符串再和其他字符串组合。

所以全组合的高级类型就是这样:

ts
type AllCombinations<A extends string, B extends string = A> = A extends A
+  ? Combination<A, AllCombinations<Exclude<B, A>>>
+  : never;

类型参数 A、B 是待组合的两个联合类型,B 默认是 A 也就是同一个。

A extends A 的意义就是让联合类型每个类型单独传入做处理,上面我们刚学会。

A 的处理就是 A 和 B 中去掉 A 以后的所有类型组合,也就是 Combination<A, B 去掉 A 以后的所有组合>。

而 B 去掉 A 以后的所有组合就是 AllCombinations<Exclude<B, A>>,所以全组合就是 Combination<A, AllCombinations<Exclude<B, A>>>。

总结

联合类型中的每个类型都是相互独立的,TypeScript 对它做了特殊处理,也就是遇到字符串类型、条件类型的时候会把每个类型单独传入做计算,最后把每个类型的计算结果合并成联合类型。

条件类型左边是联合类型的时候就会触法这种处理,叫做分布式条件类型。

有两点特别要注意:

  • A extends A 不是没意义,意义是取出联合类型中的单个类型放入 A

  • A extends A 才是分布式条件类型, [A] extends [A] 就不是了,只有左边是单独的类型参数才可以。

我们后面做了一些案例,发现联合类型的这种 distributive 的特性确实能简化类型编程,但是也增加了认知成本,不过这也是不可避免的事。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/video.html b/cn/src/article/video.html new file mode 100644 index 0000000000..16c66da55f --- /dev/null +++ b/cn/src/article/video.html @@ -0,0 +1,333 @@ + + + + + + ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

实现自适应码率 Web 视频加密播放:前后端的挑战与解决方案

最近又遇到了web视频化的场景,之前也有过调研:H5 视频化调研浅析

但这次稍微复杂一些,这次解决的是:

  1. 视频播放的技术方案调研

服务端实现:

  1. 视频转码
  2. 生成不同码率的视频
  3. 进行视频标准加密
  4. 不同码率视频合并,用于动态码率播放

web端实现

  1. web端播放器的设计
  2. web端播放器的自定义扩展
  3. 可拖拽进度条
  4. 音量控制
  5. 根据当前带宽自适应码率切换
  6. 手动清晰度切换
  7. 倍速播放
  8. 样式自定义覆盖
  9. 标准加密视频播放
  10. 基于原生开发,可在所有框架运行,统一跨框架情况
  11. 各浏览器控件统一

其中web端源码已添加MIT协议并完全开源,如果看完对大家有帮助的话,欢迎大家star,issue,pr,也希望能友好交流~

demo 地址:https://chaxus.github.io/ran/src/ranui/player/

源码地址:https://github.com/chaxus/ran

demo文档做了国际化,可切换到中文

任何一个项目,立项肯定先是技术调研,我们先看看一些大公司的视频播放方案

一:一些知名公司的 web 视频播放方案

1.B 站

我们先看看 B 站的,毕竟 B 站的主营业务就是视频弹幕网站,简直专业对口。

先找一个例子:https://www.bilibili.com/video/BV1FM411N7LJ 访问它。

image.png

打开控制台,可以看到,视频在播放的时候,会不断的请求m4s的视频文件。

毕竟一整个视频文件往往比较大,不可能先请求完视频文件,再进行播放。因此将一个大的视频文件分割成很多小的片段,边加载边播放,是一种更好的方式。

image.png

每次请求的m4s文件大概在几十kb到几百kb不等。

image.png

那为什么不采用httprange呢,可以请求一个文件的部分内容,而且粒度更细,可以设置字节范围。在http请求的header中,类似这样

js
Range: bytes = 3171375 - 3203867;

我们可以检查这个链接请求https://upos-sz-mirror08c.bilivideo.com/upgcxcode/67/92/1008149267/1008149267-1-30064.m4s的请求头,就能发现,B 站采用的是,即分片加载,同时还用了range的方式。

2. 爱奇艺:(爱奇艺、土豆、优酷)

爱奇艺这里就不贴视频链接了,因为随便点一个视频,都要先看广告。

image.png

爱奇艺的视频主要请求的是f4v格式,也是分片加载。

播放一个视频时,请求多个f4v文件。

也采用Range。但和 B 站不一样的是,B 站的Range属性是在m4s请求的请求头里面,而爱奇艺的看起来是在querystring上,在请求query上带着range参数。

因为没发现这个请求的header里面有range参数。比如:

https://v-6fce1712.71edge.com/videos/other/20231113/6b/bb/3f3fe83b89124248c3216156dfe2f4c3.f4v?dis_k=2ba39ee8c55c4d23781e3fb9f91fa7a46&dis_t=1701439831&dis_dz=CNC-BeiJing&dis_st=46&src=iqiyi.com&dis_hit=0&dis_tag=01010000&uuid=72713f52-6569e957-351&cross-domain=1&ssl=1&pv=0.1&cphc=arta&range=0-9000

3.抖音:

抖音的方案简单粗暴,访问的链接是这个: https://m.ixigua.com/douyin/share/video/7206914252840370721?aweme_type=107&schema_type=1&utm_source=copy&utm_campaign=client_share&utm_medium=android&app=aweme

通过查看控制台,我们可以发现,直接请求了一个视频的地址

image.png

没有进行分片,但用到了请求range,所以可以看到视频,是边播放边缓冲一部分。

不过我在开发的时候发现,目前租用的服务云厂商,默认会帮我们实现这项技术。

因为我把mp4视频上传到云服务器,通过链接进行播放的时候,就是边缓冲边播放的。

我们可以直接把这个视频地址拿出来,放到浏览器里面能直接播放,这样观察更明显。

image.png

但 B 站和爱奇艺却不能这样,因为他们采用的m4sf4v都不是一种通用的视频格式,需要使用专门的软件或工具才能打开和编辑。

4.小红书:

测试用的例子链接:https://www.xiaohongshu.com/discovery/item/63b286d1000000001f00b495

小红书的方案更加简单粗暴,打开控制台,直接告诉你就是请求一个mp4,然后直接播放就完事了。

image.png

5.总结

看完了以上的各家大厂的方案,我们可以看到,基本原理都是边播放边加载,减少直接加载大视频文本的成本。并且通过分片传输,还能动态控制视频码率(清晰度)。做到根据网速,加载不同码率的分片文件,做到动态码率适应。

同时采用的视频格式,比如f4vm4s,都不是能直接播放的媒体格式,需要一定的处理。增加盗取视频的成本,增加一定的安全性。

如果没有强要求,也可以直接采用mp4,或者直接用video播放一个视频文件地址。

二:常见的视频格式与协议

我们知道视频的常见格式有mp4,同时上面介绍了 B 站播放用的m4s格式,爱奇艺用的f4v格式

  • 除了这些还有哪些视频格式?
  • 为什么有这么多视频格式,有哪些不同点呢?
  • 为什么这些公司会采用这种格式来播放视频呢?

1. B 站用的m4s

M4S格式不是一种通用的视频格式,需要使用专门的软件或工具才能打开和编辑。

M4S 通常会和 MPEG-DASH 流媒体技术一起,通过流式传输的视频的一小部分。播放器会按接收顺序播放这些片段。第一个 M4S 段会包含一些初始化的数据标识。

MPEG-DASH 是一种自适应比特率流媒体技术,通过将内容分解为一系列不同码率的M4S片段,然后根据当前网络带宽进行自动调整。如果想在在web音视频中采用DASH技术,可以看下 https://github.com/Dash-Industry-Forum/dash.js

2. 爱奇艺的f4v

F4V是一种流媒体格式,它是由Adobe公司推出的,继FLV格式之后支持H.264编码的流媒体格式。F4V格式的视频不是一种通用的视频格式,但通常情况下,都可以将文件后缀改为FLV,这样就可以使用支持FLV的播放器进行观看。

FLV格式跟常见的MP4格式比起来,结构更加简单,所以加载metadata(视频元数据,比如视频时长等信息) 会更快。具体结构我们可以在这里查到:https://en.wikipedia.org/wiki/Flash_Video#Flash_Video_Structure

比如,这是FLV文件的标准头,定义了从几个比特到几个比特之间,是什么含义。我们知道后,可以用MediaSource进行读取和转码。

FieldData TypeDefaultDetails
Signature 签名byte[3]"FLV"始终就是“FLV”
Version 版本uint81只有 0x01 才有效
Flags 标志uint8 位掩码0x050x04 是音频,0x01 是视频(所以 0x05 是音频 + 视频)
Header Sizeuint32_be9用于跳过较新的扩展标头

MP4格式会稍微复杂一些,具体标准在 ISO/IEC 14496-12 大概有两百多页,这里放不下,对这方面有兴趣的可以自行查看。

然而这并不表示MP4更差,因为它是一种基础通用标准,所以定义上会留有很多空间,和各种情况,甚至允许在标准之内进行自行发挥和扩展。而FLV格式则更加固定,但优点也是更加简单。

对于FLV的视频播放,我们可以采用:https://github.com/bilibili/flv.js flvjs主要作用就是用MediaSourceflv转码成mp4从而喂给浏览器进行播放。

接下来是一些其他的视频格式,简单介绍一下:

3.AVI

文件名以.avi结尾,AVI 最初由 Microsoft1992 年开发,是 Windows 的标准视频格式。AVI 文件使用较少的压缩来存储文件,并且比许多其他视频格式占用更多空间,这导致文件大小非常大,每分钟视频大约 2-3 GB

无损文件不会随着时间的推移而降低质量,无论您打开或保存文件多少次。此外,这允许在不使用任何编解码器的情况下播放。参考资料:Audio Video Interleave

4.MPEG

文件名以“.mpg”或“.mpeg”结尾,MPEG 是由 ISO 和 IEC 联合成立的工作组联盟,旨在制定媒体编码标准,包括音频、视频、图形和基因组数据的压缩编码;以及各种应用程序的传输和文件格式。MPEG 格式用于各种多媒体系统。最广为人知的旧 MPEG 媒体格式通常使用 MPEG-1、MPEG-2 和 MPEG-4 AVC 媒体编码,MPEG-2 系统传输流和节目流。较新的系统通常使用 MPEG 基本媒体文件格式和动态流式处理(又名 .MPEG-DASH)。参考资料:Moving Picture Experts Group

5.MP4

带有音频和视频的 MPEG-4 文件通常使用标准的 .mp4 扩展名。纯音频 MPEG-4 文件通常具有 .m4a 扩展名,原始 MPEG-4 可视比特流命名为 .m4v。Apple iPhone 使用 MPEG-4 音频作为其铃声,但使用.m4r 扩展名而不是.m4a 扩展名。参考资料:MPEG-4 Part 14

6.QuickTime

文件名以“.mov”结尾,QuickTime 能够包含媒体数据的抽象数据引用,并将媒体数据与媒体偏移和轨道编辑列表分离,这意味着 QuickTime 特别适合编辑,因为它能够就地导入和编辑(无需数据复制)。由于 QuickTime 和 MP4 容器格式都可以使用相同的 MPEG-4 格式,因此在仅限 QuickTime 的环境中,它们大多可以互换。MP4 作为国际标准,得到了更多的支持。参考资料:QuickTime File Format

7.TS

TS 是 MPEG2-TS 的简称,是一种音视频封装格式。TS 流的后缀通常是.ts、.mpg 或者.mpeg,多数播放器直接支持这种格式的播放。TS 格式主要用于直播的码流结构,具有很好的容错能力。

三:浏览器对各种视频格式的兼容性

上面了解常用的视频格式,和适用范围之后,还需要看一下当前浏览器,对各种视频格式的支持程度,然后制定技术方案。

1. Chrome

支持的视频格式从官方文档可以查到,主要有以下这些

  • MP4 (QuickTime/ MOV / ISO-BMFF / CMAF)
  • Ogg
  • WebM
  • WAV
  • HLS [Only on Android and only single-origin manifests]

官方文档如下:https://www.chromium.org/audio-video/

2. Safari

支持的视频格式有这些:

image.png

官方文档:https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/Using_HTML5_Audio_Video/Device-SpecificConsiderations/Device-SpecificConsiderations.html

3.Firefox

支持的视频格式:

image.png

官方文档:https://support.mozilla.org/en-US/kb/html5-audio-and-video-firefox

四:MediaSource 和视频编码,解码,封装介绍

上面介绍了一些视频格式,和目前浏览器的一些兼容性问题。就能发现,在web上播放音视频其实限制还是很大的。如何解决这些限制,就会用到MediaSource

视频其实是无数个图片的叠加,如果视频是一秒60帧,大约一秒中需要播放60张图片。这就导致一个几分钟的视频,就会非常大。比如上面介绍的无损格式,avi格式,每分钟视频大约 2-3 GB。这时候视频就需要进行编码。其实就是压缩。

编码分为视频编码和音频编码,常见的视频编码有:

  • MPEG 系列MPEG-1第二部分、MPEG-2第二部分(等同于H.262)、MPEG-4第二部分、MPEG-4第十部分(等同于H.264,有时候也被叫做“MPEG-4 AVC”或“H.264/AVC”)。
  • H.26x 系列H.261H.262H.263H.264(等同于MPEG-4第十部分)、H.265/HEVCITU-TISO/IEC联合推出)。
  • 其它视频编码WMV系列、RV系列、VC-1DivXXviDX264X265VP8VP9Sorenson VideoAVS

常见的音频编码有:AACMP3AC-3

编码之后,还需要将音频和视频合并在一个文件里,这就是封装

所以相对的,播放一个视频,就需要解封装,解码,音视频同步喂给声卡和显卡进行播放。

MediaSource做的就是这个工作,读取视频流,转换成浏览器能播放的格式。

以下是flv.jsparseChunks部分内容。读取buffer,一个字节一个字节的根据标准进行解析。然后转码。

js
if (byteStart === 0) {
+  // buffer with FLV header
+  if (chunk.byteLength > 13) {
+    let probeData = FLVDemuxer.probe(chunk);
+    offset = probeData.dataOffset;
+  } else {
+    return 0;
+  }
+}
+
+if (this._firstParse) {
+  // handle PreviousTagSize0 before Tag1
+  this._firstParse = false;
+  if (byteStart + offset !== this._dataOffset) {
+    Log.w(this.TAG, 'First time parsing but chunk byteStart invalid!');
+  }
+
+  let v = new DataView(chunk, offset);
+  let prevTagSize0 = v.getUint32(0, !le);
+  if (prevTagSize0 !== 0) {
+    Log.w(this.TAG, 'PrevTagSize0 !== 0 !!!');
+  }
+  offset += 4;
+}

1.MediaSource 兼容性

image.png

由此可见,基本都是绿色,但有一个特殊情况,就是Safari on IOS。这部分支持程度还是棕色。

五:HLS 播放方案

采用HLS技术方案,有以下几个原因:

1.兼容性

上面介绍了各种视频格式,还有浏览器的兼容性

其中 HLS协议是Apple公司实现的,在 Apple 的全系列产品包括 iPhoneiPadSafari 等都可以原生支持播放 HLS

对于其他浏览器,可以通过MediaSource解封装,解码,转码,进行播放。

这样也就解决了MediaSource的兼容性问题。

  1. 业务场景需求

目前对于视频的加密有着强需求,比如需要用户付费才能观看一些视频。而HLS协议天然自带标准加密,同时也能基于HLS扩展私有加密。

  1. HLS协议自带支持分片传输和动态码率自适应播放。
  2. 有现成的技术方案,Hls.js

六:服务端开发

选择了采用HLS协议的播放方式,那么首先需要处理视频,这部分目前是在服务端进行处理。利用ffmpeg的能力。

如果以后能将ffmpeg搬上浏览器,且没有性能问题就好了。现在有类似的webassemblynpm包,但性能有点小问题

1.视频的转码

视频的转码的ffmpeg命令如下:

sh
ffmpeg -i input.mp4 -hls_time 10 -hls_list_size 0 -c:v h264 -b:v 2M -hls_segment_filename output_%05d.ts output.m3u8 -y

每个参数的解释:

  • -i 指定输入的视频
  • -hls_time 指定分片的时间,单位是秒
  • -hls_list_size 指定hls列表的数量,这里不限制
  • -c:v 指定视频的编码格式
  • -b:v 指定视频的码率,这里是2M比特率
  • -hls_segment_filename 指定输出的ts文件名字,这里表示是output_ + 五位数字
  • output.m3u8指定输出m3u8文件的名字
  • -y有些场景,比如是否覆盖,直接选择是,避免程序卡住

为了自动化执行,这里会用到nodespawn模块,创建一个子进程,在子进程中执行ffmpeg的命令。

ts
const exec = ({ params, data }: ExecOption): Promise<ExecResult> => {
+  return new Promise((r, j) => {
+    const cp = spawn('ffmpeg', params);
+    cp.stderr.pipe(process.stdout);
+    cp.on('error', (err) => {
+      j(err);
+    });
+    cp.on('close', (code) => {
+      r({ code, data });
+    });
+    cp.on('exit', (code) => {
+      r({ code, data });
+    });
+  });
+};

这时候,视频就会在指定的位置输出了,会生成一个m3u8和多个ts

image.png

ts是视频文件,m3u8更像是索引文件,用来描述ts,比如在什么时间,播放什么ts。主要内容如下:

#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-TARGETDURATION:10
+#EXT-X-MEDIA-SEQUENCE:0
+#EXTINF:10.380622,
+5_00000.ts
+#EXTINF:10.380622,
+5_00001.ts
+#EXTINF:10.380622,
+5_00002.ts
+#EXTINF:10.380622,
+5_00003.ts
+#EXTINF:6.560556,
+5_00004.ts
+#EXTINF:1.619378,
+5_00005.ts
+#EXTINF:5.024189,
+5_00006.ts
+#EXT-X-ENDLIST

2.视频的标准加密

HLS协议标准加密采用的是AES对称加密方案。先来实现一个最标准的加密:

首先通过node原生模块crypto生成加密密钥:

ts
import crypto from 'node:crypto';
+// 生成加密密钥
+const key = crypto.createHash('sha256').update(crypto.randomBytes(32)).digest('base64');
+const filePathKey = path.join(__dirname, `../../public/uploads/hls/${dir}/${fileName}.key`);
+
+const content = `${ctx.origin}/uploads/hls/${dir}/${fileName}.key\n${filePathKey}\n`;
+// 密钥的文件
+const fileKey = await writeFile(path.join(__dirname, `../../public/uploads/hls/${dir}/${fileName}.key`), key);
+const keyInfoPath = path.join(__dirname, `../../public/uploads/hls/${dir}/${fileName}_key.bin`);
+// ffmpeg 需要的 key.info
+const keyInfo = await writeFile(keyInfoPath, content);

然后再执行ffmpeg命令,这里同样需要用nodespawn模块进行封装成接口:

sh
ffmpeg -i input.mp4 -hls_time 10 -hls_list_size 0 -c:v h264 -b:v 2M -hls_key_info_file keyInfoPath -hls_segment_filename output_%05d.ts output.m3u8 -y

主要就增加了一个hls_key_info_file参数,表示加密密钥的地址。这时候,生成的m3u8文件就发生了变化,多了一行:

#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-TARGETDURATION:10
+#EXT-X-MEDIA-SEQUENCE:0
+#EXT-X-KEY:METHOD=AES-128,URI="http://localhost:30103/uploads/hls/5_1701577743851/5.key",IV=0x00000000000000000000000000000000
+#EXTINF:10.380622,
+5_00000.ts
+#EXTINF:10.380622,
+5_00001.ts
+#EXTINF:10.380622,
+5_00002.ts
+#EXTINF:10.380622,
+5_00003.ts
+#EXTINF:6.560556,
+5_00004.ts
+#EXTINF:1.619378,
+5_00005.ts
+#EXTINF:5.024189,
+5_00006.ts
+#EXT-X-ENDLIST

多了

#EXT-X-KEY:METHOD=AES-128,URI="http://localhost:30103/uploads/hls/5_1701577743851/5.key",IV=0x00000000000000000000000000000000
  • METHOD字段表示加密方式,这里是AES
  • URI表示密钥地址,这里是http://localhost:30103/uploads/hls/5_1701577743851/5.key
  • IV是加密解密时的偏移量,现在是 0

上述加密方式,虽然视频确实加密了,但会把密钥地址写在m3u8里。等于把房间上锁,然后在锁上贴一个纸条,上面写了密码。

3.更好的安全方案

  • 有加密,必然需要解密

首先我们知道,视频要在web端进行播放,那么无论如何,都肯定需要先解密,再播放。

  • 肯定不能在web端放置密钥
  • web端需要知道如何获取密钥
  • 密钥用一次即失效,每次加密视频都生成新的密钥

目前更好的安全性方式主要有两种:

  1. 在请求密钥的地址上进行加固:
  • 校验cookie,既然是发起请求,那么同域名会自动携带cookie,只有购买过的用户才能获取密钥。(总不能让付费的用户也不能看吧)
  • 生成密钥链接时,带上ticket,短时间失效,控制时效性
  • 请求头携带auth,进行用户校验。比如jwt方案就是如此
  1. 采用私有加密方式,比如m3u8里的METHOD,可能不再是AES这种对称加密。自定义一套加密规则,这种方式安全性会极大提高,但同时就不遵守HLS协议的标准了。但大多数浏览器支持MediaSource。可以读取文件内容,进行自定义加密和解密。根据上文的兼容性调研,MediaSourceIOS上将会有兼容性问题,所以这种方案在IOS上也会有兼容性问题。

4.自适应码率播放

这里先介绍一下码率和清晰度的关系:

码率是指:

码率(也称为比特率)是指视频文件在单位时间内使用的数据流量。它反映了视频文件的数据压缩程度,码率越高,压缩比就越小,画面质量就越高,但文件体积也越大。通俗来说,码率可以看作是取样率,是视频编码中画面质量控制中最重要的部分。计算公式是文件体积=时间 X 码率/8。

所以简单来说,码率越高,清晰度就越好。成正比关系。

需要根据视频的质量,和业务场景,去定义,这里给出阿里云对码率和清晰度的定义,可供参考:

image.png

为了实现自适应码率播放,我们需要将不同码率的m3u8合并成一个多码率的m3u8

这里我没找到合适的ffmpeg命令,但总有办法的,最万能的方法就是,查看HLS协议中多码率的m3u8格式标准,自己写一个。

目前用node去写一个这样的索引文件,具体内容如下:

#EXTM3U
+#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1000000,CODECS="mp4a.40.2,avc1.64001f",RESOLUTION=1280x720,NAME="720"
+hls/5_1701577771368/5.m3u8
+#EXT-X-STREAM-INF:PROGRAM-ID=2,BANDWIDTH=50000,CODECS="mp4a.40.5,avc1.42000d",RESOLUTION=320x184,NAME="320"
+hls/5_1701577744714/5.m3u8
  • #EXT-X-STREAM-INF: 流媒体的描述
  • PROGRAM-ID: 表示唯一的ID
  • BANDWIDTH: 流媒体的带宽,即每秒传输的数据量。这里带宽为50000,意味着每秒传输的数据量大约为50kbps
  • CODECS: 流媒体使用的编解码器。这里是使用了mp4a.40.5AAC音频编码)和avc1.42000dAVC视频编码)。
  • RESOLUTION: 这个字段指示了视频的分辨率,即宽度和高度。在这个例子中,视频分辨率为320x184
  • NAME: 这个字段为流媒体提供了一个名称,本例中名称为"320"。我会习惯把清晰度放在NAME这个字段这里,方便web端获取

实现一个接口,传入以上的参数,动态拼接字符串,写入文件

ts
async generateMasterPlayList(ctx: Context): Promise<void> {
+    try {
+      const { paths, filename = Date.now() } = ctx.request.body;
+      let content = `#EXTM3U\n`;
+      paths.forEach((item: MasterPlayListOption, index: number) => {
+        const { id = index, bandWidth, codecs, resolution, name, url } = item;
+        content += `#EXT-X-STREAM-INF:PROGRAM-ID=${id},BANDWIDTH=${bandWidth},CODECS="${codecs}",RESOLUTION=${resolution},NAME="${name}"\n${url}\n`;
+      });
+      const dir = path.join(__dirname, `../../public/uploads/hls/`);
+      if (!existsSync(dir)) {
+        await createDir(dir);
+      }
+      const filePath = dir + (filename.toString().endsWith('.m3u8') ? filename : `${filename}.m3u8`)
+      const { success, error } = await writeFile(filePath, content);
+      const basename = path.basename(filePath);
+      return success
+        ? ctx.successHandler({
+            url: `${ctx.origin}/uploads/hls/${basename}`,
+          })
+        : ctx.failHandler(error);
+    } catch (error) {
+      ctx.errorHandler(error);
+    }
+  }

那么HLS是如何自适应码率的呢?

其实是根据BANDWIDTH这个字段,因为我们给不同的视频设置了不同的BANDWIDTH。那么就可以根据当前的网速,进行动态切换。

七:web 端的实现

上面做了大量的工作,主要是生成了HLS协议的视频播放的地址。接下来就是如何在web端进行播放。

1.技术选型

我首先是看了现有的播放器npm,比较知名的

其中知乎和西瓜的播放器是开源的,阿里云点播方案没有开源代码,但是有开源demo

image.png

但基本上实现的功能都很丰富,同时配置项会不断的增加。

如果只是简单的初始化一个播放器,那还好。但一般这种场景,我们都会对播放器进行一定程度的定制化。比如 B 站。

image.png

就多了很多自定义的控件。进度条也是小电视的形状。

我们这边也是如此,有自己的主题色,有自己的播放按钮等等,还有一些业务功能,也要放在控制条上。

上述的开源方案,都需要花时间去研究配置项,而且使用方法都是new Player(options)的形式。

但尽量视图的归视图,逻辑的归逻辑会更好些。

更何况实现一个播放器也不是很困难。

期望的player,能满足

  1. 配置够简单,最好看到就知道是怎么用的
  2. 方便扩展和样式覆盖
  3. 支持hls播放
  4. 尽量适配前端的各种框架
  5. 方便接入,实现价值

2.播放器设计

由于现在既有react项目,也有vue项目,甚至还有一些老的jquery项目。为了做到一次开发,任何项目都可以使用和接入。采用了web components技术方案。

web components就不做介绍了,具体可以去看这篇文章:手写 web components 组件简单来说就是可以自定义元素,让我们像使用div一样使用自定义元素。

播放器我们需要考虑的点有:

  1. video生命周期:loadedmetacanplay, ended, error
  2. video状态:播放,正在播放,暂停,静音等
  3. video属性:总时长,当前时长,音量大小,倍速等
  4. video交互:暂停,播放,知识点,清晰度,倍速,全屏,进度控制,音量控制等

(1).video 的生命周期

对于 video 的生命周期,我们期望做到两件事情:

  1. 我们能知道当前video处于什么生命周期
  2. 在不同的生命周期,能挂载自定义事件。比如视频触发了ended。我们需要在ended时期跳转下一个视频

因此,我们需要监听video的生命周期:

ts
listenEvent = () => {
+  if (!this._video) return;
+  this.clearListenerEvent();
+  this._video.addEventListener('canplay', this.onCanplay);
+  this._video.addEventListener('canplaythrough', this.onCanplaythrough);
+  this._video.addEventListener('complete', this.onComplete);
+  this._video.addEventListener('durationchange', this.onDurationchange);
+  this._video.addEventListener('emptied', this.onEmptied);
+  this._video.addEventListener('ended', this.onEnded);
+  this._video.addEventListener('error', this.onError);
+  this._video.addEventListener('loadeddata', this.onLoadeddata);
+  this._video.addEventListener('loadedmetadata', this.onLoadedmetadata);
+  this._video.addEventListener('loadstart', this.onLoadstart);
+  this._video.addEventListener('pause', this.onPause);
+  this._video.addEventListener('play', this.onPlay);
+  this._video.addEventListener('playing', this.onPlaying);
+  this._video.addEventListener('progress', this.onProgress);
+  this._video.addEventListener('ratechange', this.onRatechange);
+  this._video.addEventListener('seeked', this.onSeeked);
+  this._video.addEventListener('seeking', this.onSeeking);
+  this._video.addEventListener('stalled', this.onStalled);
+  this._video.addEventListener('suspend', this.onSuspend);
+  this._video.addEventListener('timeupdate', this.onTimeupdate);
+  this._video.addEventListener('volumechange', this.onVolumechange);
+  this._video.addEventListener('waiting', this.onWaiting);
+};

在触发不同的时期时,让开发者知道。所以我们要先自定义事件,进行触发

ts
const change = (name: string, value: unknown): void => {
+  const currentTime = this.getCurrentTime();
+  const duration = this.getTotalTime();
+  this.dispatchEvent(
+    new CustomEvent('change', {
+      detail: {
+        type: name,
+        data: value,
+        currentTime,
+        duration,
+        tag: this, // 整个 player 的实例
+      },
+    }),
+  );
+};
+const onCanplaythrough = (e: Event) => {
+  this.ctx.currentState = e.type;
+  this.change('canplaythrough', e);
+};

这样就可以,当生命周期事件触发后,就会触发onchange。 在使用上,我们可以:

jsx
<r-player onChange={change} src="hls/example.m3u8" ></r-player>
+
+const change = (e:CustomEvent) => {
+    const { type, data, currentTime, duration, tag } = e.detail
+    if(type === 'ended'){
+        console.log('video ended')
+    }
+}

其中type的类型有:

名称说明
canplay浏览器可以播放媒体文件了,但估计没有足够的数据来支撑播放到结束,不必停下来进一步缓冲内容。
canplaythrough浏览器估计它可以在不停止内容缓冲的情况下播放媒体直到结束。
completeOfflineAudioContext 渲染完成。
durationchangeduration 属性的值改变时触发。
emptied媒体内容变为空;例如,当这个 media 已经加载完成(或者部分加载完成),则发送此事件,并调用 load() 方法重新加载它。
ended视频停止播放,因为 media 已经到达结束点。
loadedmetadata已加载元数据。
progress在浏览器加载资源时周期性触发。
ratechange播放速率发生变化。
seeked跳帧(seek)操作完成。
seeking跳帧(seek)操作开始。
stalled用户代理(user agent)正在尝试获取媒体数据,但数据意外未出现。
suspend媒体数据加载已暂停。
loadeddatamedia 中的首帧已经完成加载。
timeupdatecurrentTime 属性指定的时间发生变化。
volumechange音量发生变化。
waiting由于暂时缺少数据,播放已停止。
play播放已开始。
playing由于缺乏数据而暂停或延迟后,播放准备开始。
pause播放已暂停。
volume音量发生变化。
fullscreen触发全屏事件

在不同的生命周期,能挂载事情,因此我们需要一个发布订阅类。

ts
type Callback = (...args: unknown[]) => unknown;
+
+type EventName = string | symbol;
+
+type EventItem = {
+  name?: string | symbol;
+  callback: Callback;
+  initialCallback?: Callback;
+};
+
+const NEW_LISTENER = 'NEW_LISTENER';
+
+export class SyncHook {
+  private _events: Record<EventName, Array<EventItem>>;
+  constructor() {
+    this._events = {};
+  }
+  on = (eventName: EventName, eventItem: EventItem | Callback): void => {
+    if (this._events[eventName] && eventName !== Symbol.for(NEW_LISTENER)) {
+      this.emit(Symbol.for(NEW_LISTENER), eventName);
+    }
+
+    const callbacks = this._events[eventName] || [];
+    if (typeof eventItem === 'function') {
+      callbacks.push({
+        name: eventName,
+        callback: eventItem,
+      });
+    } else {
+      callbacks.push(eventItem);
+    }
+
+    this._events[eventName] = callbacks;
+  };
+
+  emit = (eventName: EventName, ...args: Array<unknown>): void => {
+    const callbacks = this._events[eventName] || [];
+    callbacks.forEach((item) => {
+      const { callback } = item;
+      callback(...args);
+    });
+  };
+
+  once = (eventName: EventName, eventItem: EventItem | Callback): void => {
+    let one: EventItem;
+    if (typeof eventItem === 'function') {
+      one = {
+        name: eventName,
+        callback: (...args: Array<unknown>) => {
+          eventItem(...args);
+          this.off(eventName, one);
+        },
+        initialCallback: eventItem,
+      };
+    } else {
+      const { callback } = eventItem;
+      one = {
+        name: eventName,
+        callback: (...args: Array<unknown>) => {
+          callback(...args);
+          this.off(eventName, one);
+        },
+        initialCallback: callback,
+      };
+    }
+    this.on(eventName, one);
+  };
+
+  off = (eventName: EventName, eventItem: EventItem | Callback): void => {
+    const callbacks = this._events[eventName] || [];
+    const newCallbacks = callbacks.filter((item) => {
+      if (typeof eventItem === 'function') {
+        return item.callback !== eventItem && item.initialCallback !== eventItem;
+      } else {
+        const { callback } = eventItem;
+        return item.callback !== callback && item.initialCallback !== callback;
+      }
+    });
+    this._events[eventName] = newCallbacks;
+  };
+}

因此会给player元素上增加一个ctx属性,作为全局的上下文。

ts
this.ctx = {
+  currentTime: 0, // 当前时间
+  duration: 0, // 总时长
+  currentState: '', // 当前视频状态
+  action: new SyncHook(), // 不同时期触发的状态
+};

我们想订阅视频的结束事件,我们可以

通过Ref的方式:

<r-player ref={PlayerRef} onChange={change} src="hls/example.m3u8" ></r-player>
+
+const endedEvent = () => {
+    console.log('video ended')
+}
+
+PlayerRef.current.ctx.action.off('ended',endedEvent)
+
+PlayerRef.current.ctx.action.on('ended',endedEvent)

通过change方法获取的实例:

jsx
<r-player onChange={change} src="hls/example.m3u8" ></r-player>
+
+let player
+
+const endedEvent = () => {
+    console.log('video ended')
+}
+
+const change = (e:CustomEvent) => {
+    const { type, data, currentTime, duration, tag } = e.detail
+    player = tag
+}
+
+player.action.off('ended',endedEvent)
+player.action.on('ended',endedEvent)

(2).video 的状态和属性

需要在全局上下文中记录下播放器的状态和属性:

ts
this.ctx = {
+  currentTime: 0, // 当前时间
+  duration: 0, // 总时长
+  currentState: '', // 当前视频状态
+  action: new SyncHook(), // 不同时期触发的状态
+  volume: 0.5, // 当前音量
+  playbackRate: 1, // 当前倍速
+  clarity: '', // 当前清晰度
+  fullScreen: false, // 是否全屏
+  levels: [], // 清晰度列表
+  url: '', // 当前播放的地址
+  levelMap: new Map(), // 清晰度和名字的映射关系
+};

(3).自定义 video

默认长这个样子

image.png

demo 地址:https://chaxus.github.io/ran/src/ranui/player/

源码地址:https://github.com/chaxus/ran

如果不喜欢控制器或者按钮,直接样式覆盖,更符合直觉,没有学习成本。

css
.ran-player-controller {
+  display: none;
+}

由于播放器本身就是一个元素,那么可以任意的在里面添加元素,添加逻辑。

jsx
<r-player onChange={change} src="hls/example.m3u8">
+  <div>111111</div>
+</r-player>

所以,这就解决配置项,长达好几页的问题,同时看到也就知道怎么配置,怎么开发了。

八:总结

目前已经从前后端的角度,实现了

  1. 视频的标准加密
  2. 视频的动态码率播放
  3. 视频的分片加载
  4. 可拖拽进度条
  5. 音量控制
  6. 手动清晰度切换
  7. 倍速播放
  8. 样式自定义覆盖
  9. 基于原生开发,可在所有框架运行,统一跨框架情况,各浏览器控件统一

这是demo和源码地址:

demo和文档地址:https://chaxus.github.io/ran/src/ranui/player/

源码地址:https://github.com/chaxus/ran

demo文档做了国际化,可切换到中文

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/article/visual.html b/cn/src/article/visual.html new file mode 100644 index 0000000000..7aef9fa37b --- /dev/null +++ b/cn/src/article/visual.html @@ -0,0 +1,191 @@ + + + + + + 实现曲线 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

在业务持续演进的过程中,遭遇了高度定制化图表的需求。为了寻找解决方案,首先深入探索了现有的开源图表库,遗憾的是,这些库虽能覆盖大部分常见的功能,但在一些定制化设计上却显得力不从心,但 UI 层的定制化又是十分常见的。

为了精准复现设计愿景,我转而采用 canvas 技术手动绘制图表。这一过程中,尽管已尽力通过函数式编程范式封装和模块化绘制逻辑以提升代码的可维护性,但 canvas 的命令式特性在面临需求变动时,仍易导致直接而频繁的代码调整,影响了整体的开发效率和灵活性。

鉴于此,意识到,需要从更高层次的业务逻辑和设计理念出发,构建一个更为底层且灵活的图表绘制引擎。这样的引擎应能够抽象出绘制操作的核心要素,不仅服务于当前应用层的定制化需求,更应具备良好的扩展性和复用性,以便在未来面对更多样化的业务场景时,能够迅速响应并高效实现定制化图表的绘制需求。这样的策略转变,旨在从根本上提升图表定制化的开发效率和图表的维护性,确保业务迭代的顺畅进行。

一 技术设计

针对常见的绘制需求进行详尽的功能分析后,我们系统性地规划了高效且灵活的图表绘制引擎的核心构成要素。这些精心设计的组件旨在确保引擎不仅能够灵活应对多样化的定制需求,还具备出色的可维护性和可扩展性。具体而言,设计蓝图涵盖以下关键方面:

  1. **基础图形库:**构建一个丰富的基础图形类库,提供便捷的 API 来绘制常见的几何形状,如矩形、圆形、多边形、曲线等。这些基础图形应支持自定义样式和属性,以满足多样化的设计需求。
  2. **层级管理:**构建一个清晰的层级结构是绘制引擎的基础。这包括定义元素之间的堆叠顺序,如确保文字总是绘制在图表的上方,以及处理不同图表或元素之间的层级关系。层级管理将确保视觉呈现符合预期,即使在复杂的布局中也能保持清晰有序。
  3. **图形组的管理:**引入节点和组的概念,允许用户将多个图形元素组织成一个整体(即“组”)。这样的设计使得对组进行整体移动、缩放或变形时,组内所有元素都能同步响应,大大简化了复杂场景下的操作和管理。
  4. **变换矩阵:**对一个图形组执行平移、旋转、缩放等变形操作,从而以动态和灵活的方式调整图形的展示效果。为了实现这些变形操作,变形操作类通常会采用矩阵变换的原理。通过维护一个变换矩阵,并在绘制图形组之前应用该矩阵,可以一次性完成所有变形操作的计算,从而提高绘制效率。
  5. **事件系统:**集成一个高效的事件处理系统,允许用户将事件监听器绑定到单个图形元素或整个组上。这样,无论是用户交互(如点击、拖动)还是系统事件(如加载完成、数据更新),都能得到及时响应和处理。
  6. **应用层封装:**在应用层,我们需要封装绘制引擎提供的底层功能,使其更加贴近业务需求。这包括提供易于使用的 API 接口、优化性能、处理异常和错误等。同时,通过持续的应用层反馈,不断优化和调整绘制引擎,确保其能够更好地服务于业务的发展。

因此,在绘制引擎架构中,我们会首先实现一个节点类 Vertex,这个类代表了最原始的‘节点’的概念,所有可以被展示到 canvas 画布上的、各种类型的节点都会继承于这个类,这是一个抽象类,我们并不会直接实例化这个类。

这个类上面挂载了‘节点’的各种通用属性,比如:父元素、透明度、旋转角度、缩放、平移、节点是否可见等。

ts

为了进行图形组的管理,会继续实现一个容器类 Container,这个类代表了‘组’的概念,它提供了添加子元素,移除子元素等的方法;后续的要被渲染的一些类 (如 Graphics,Text,Sprite 等) 会继承于这个类;这个类本身不会被渲染 (因为它只是一个‘组’,它本身没有内容可以渲染)。

这个类继承于 Vertex 类,‘组’也算作‘节点’。

Graphics 这个类会用来构建一些几何图形元素;它会继承 Container 类。

在渲染引擎中,一切变换 (平移、旋转、缩放等) 都会转化成变换矩阵 (matrix),因为 canvas 只接受矩阵变换,虽然 canvas 为了开发的便捷,也提供了 ctx.rotate,ctx.scale 等操作,但是 canvas 中的这些操作会直接转换成变换矩阵,而不像 DOM 那样,有锚点的概念,所以 canvas 提供的 rotate,scale 等操作,和 DOM 提供的 rotate,scale 的表现是不一样的。

Matrix 类将会提供各种各样的与矩阵操作相关的函数 (矩阵相乘,矩阵求逆等),任何变换的叠加都将会转换成 matrix,方便我们调用 canvas 的指令。

Transform 类就类似 CSS 的 transform,它提供了一些更清晰、更符合人类直觉的变换,而不用直接使用矩阵变换,当然,这些变换最终会转换成矩阵变换。

线性变换从几何直观有三个要点:

  • 变换前是直线的,变换后依然是直线
  • 直线比例保持不变
  • 变换前是原点的,变换后依然是原点

比如有一个二维基向量

旋转矩阵:

浏览器的 skew:

pixijs 的 skew:

平移操作:

这里就需要仿射变换

仿射变换从几何直观只有两个要点:

  • 变换前是直线的,变换后依然是直线
  • 直线比例保持不变

少了原点保持不变这一条。

因此,平移不再是线性变化了,而是仿射变化。

每一个矩阵变换都是线性变换,反正则不成立。

仿射变换不能光通过矩阵乘法来实现,还得有加法。

主要用途是,通过高纬度的线性变换,模拟低维度的仿射变换。从而把平移操作也数据化。

实现曲线

二阶贝塞尔曲线

起点(P0):这是曲线开始的位置。在绘制过程中,曲线会精确地通过这个点。 控制点(P1):这个点是用来控制曲线形状和弯曲程度的。它不一定在曲线上,但会对曲线的走向产生重要影响。通过调整控制点的位置,可以改变曲线的弯曲程度和方向。 终点(P2):这是曲线结束的位置。同样地,曲线也会精确地通过这个点。

二 基础图形库:

常见的基础图形有:

  1. 椭圆
  2. 多边形
  3. 矩形
  4. 圆角矩形

先实现一个基础类,然后其他的所有图形类都继承这个抽象类:

ts
export abstract class Shape {
+  // 支持的所有几何图形都会继承自这个 Shape 基类
+  public abstract type: ShapeType;
+  constructor() {}
+}

其中ShapeType目前有以下几个属性:

ts
// 支持的形状类型
+export enum ShapeType {
+  Rectangle = 'rectangle',
+  Polygon = 'polygon',
+  Circle = 'circle',
+  Ellipse = 'ellipse',
+  RoundedRectangle = 'rounded rectangle',
+}

其中,我们只实现基础图形类的数据部分,渲染到逻辑统一到一个地方。尽量分离数据和实际的 UI 渲染操作。

1.圆

要绘制一个圆,只需要知道圆心和半径即可

数据类:

ts
export class Circle extends Shape {
+  public x: number;
+  public y: number;
+  public radius: number;
+  public readonly type = ShapeType.Circle;
+  constructor(x = 0, y = 0, radius = 0) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.radius = radius;
+  }
+}

绘制方法:

ts
const { x, y, radius } = circle;
+
+ctx.arc(x, y, radius, 0, 2 * Math.PI);
+
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fill();
+}
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.stroke();
+}

2.椭圆

椭圆的标准方程是:

因此只需要圆心,长轴,短轴就可以确定一个圆,因此

ts
export class Ellipse extends Shape {
+  public x: number;
+  public y: number;
+  public radiusX: number;
+  public radiusY: number;
+  public readonly type = ShapeType.Ellipse;
+  constructor(x = 0, y = 0, radiusX = 0, radiusY = 0) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.radiusX = radiusX;
+    this.radiusY = radiusY;
+  }
+}

绘制方法:

ts
const { x, y, radiusX, radiusY } = ellipse;
+
+ctx.ellipse(x, y, radiusX, radiusY, 0, 0, Math.PI * 2);
+
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fill();
+}
+
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.stroke();
+}

3.多边形

多边形是由三条或三条以上不在同一直线上的线段首尾顺次连接所组成的封闭图形。这样的图形由多个点(称为顶点)和连接这些点的线段(称为边)构成,且所有边均在同一平面内。

简单来说,就是一个数组,里面很多个点的坐标,把点连起来,就是多边形了。

ts
export class Polygon extends Shape {
+  public points: number[]; // 多边形由多个点构成,points 数组每 2 个元素代表一个点的坐标
+  public closeStroke = false;
+  public readonly type = ShapeType.Polygon;
+  constructor(points: number[] = []) {
+    super();
+    this.points = points;
+  }
+}

绘制方法:

ts
const { points, closeStroke } = polygon;
+
+ctx.moveTo(points[0], points[1]);
+
+for (let i = 2; i < points.length; i += 2) {
+  ctx.lineTo(points[i], points[i + 1]);
+}
+
+if (closeStroke) {
+  ctx.closePath();
+}
+
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fill();
+}
+
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.stroke();
+}

4.矩形

ts
export class Rectangle extends Shape {
+  public x: number;
+  public y: number;
+  public width: number;
+  public height: number;
+  public type = ShapeType.Rectangle;
+  constructor(x = 0, y = 0, width = 0, height = 0) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+  }
+}

绘制方法:

ts
const { x, y, width, height } = rectangle;
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fillRect(x, y, width, height);
+}
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.strokeRect(x, y, width, height);
+}

5.圆角矩形

ts
export class RoundedRectangle extends Shape {
+  public x: number;
+  public y: number;
+  public width: number;
+  public height: number;
+  public radius: number;
+  public readonly type = ShapeType.RoundedRectangle;
+  constructor(x = 0, y = 0, width = 0, height = 0, radius = 20) {
+    super();
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+
+    const r = Math.min(width, height) / 2;
+    this.radius = radius > r ? r : radius;
+  }
+}

绘制方法:

ts
const { x, y, width, height, radius } = roundedRectangle;
+ctx.moveTo(x + radius, y);
+ctx.arc(x + radius, y + radius, radius, Math.PI * 1.5, Math.PI, true);
+ctx.lineTo(x, y + height - radius);
+ctx.arc(x + radius, y + height - radius, radius, Math.PI, Math.PI / 2, true);
+ctx.lineTo(x + width - radius, y + height);
+ctx.arc(x + width - radius, y + height - radius, radius, Math.PI / 2, 0, true);
+ctx.lineTo(x + width, y + radius);
+ctx.arc(x + width - radius, y + radius, radius, 0, Math.PI * 1.5, true);
+ctx.closePath();
+
+if (fillStyle.visible) {
+  ctx.globalAlpha = fillStyle.alpha * this.worldAlpha;
+  ctx.fill();
+}
+if (lineStyle.visible) {
+  ctx.globalAlpha = lineStyle.alpha * this.worldAlpha;
+  ctx.stroke();
+}

三 层级管理

在 canvas 绘图环境中,先绘制的图形会被后绘制的图形所覆盖,因此,层级的管理就自然地通过绘制顺序来实现。在这种情况下,最先被绘制的图形将位于最底层,而随后绘制的图形则逐层叠加,直至最上层。

我们已经实现了各种基础图形的绘制,接下来继续分离绘制时的数据和绘制操作。

我们需要一个容器类,在容器类中统一绘制所有的图形。

用一个 children 属性来添加所有的图形,在 render 方法中统一绘制。

同时,我们会根据 zIndex 属性来排序子元素,zIndex 越大的元素会被排在 children 数组的越后面,但是注意,排序的时候,要保证相同 zIndex 的相对顺序不变。

四 图形组的管理

我们会实现一个节点类 Vertex 这个类代表了最原始的‘节点’的概念,所有可以被展示到 canvas 画布上的、各种类型的节点都会继承于这个类,这是一个抽象类,我们并不会直接实例化这个类。

这个类上面挂载了‘节点’的各种属性,比如:父元素、透明度、旋转角度、缩放、平移、节点是否可见等。

为了进行图形组的管理,会继续实现一个容器类 Container,这个类代表了‘组’的概念,它提供了添加子元素,移除子元素等的方法;后续的要被渲染的一些类 (如 Graphics,Text,Sprite 等) 会继承于这个类;这个类本身不会被渲染 (因为它只是一个‘组’,它本身没有内容可以渲染)。

这个类继承于 Vertex 类,‘组’也算作‘节点’。

Graphics 这个类会用来构建一些几何图形元素;它会继承 Container 类。

在渲染引擎中,一切变换 (平移、旋转、缩放等) 都会转化成变换矩阵 (matrix),因为 canvas 只接受矩阵变换,虽然 canvas 为了开发的便捷,也提供了 ctx.rotate,ctx.scale 等操作,但是 canvas 中的这些操作会直接转换成变换矩阵,而不像 DOM 那样,有锚点的概念,所以 canvas 提供的 rotate,scale 等操作,和 DOM 提供的 rotate,scale 的表现是不一样的。

Matrix 类将会提供各种各样的与矩阵操作相关的函数 (矩阵相乘,矩阵求逆等),任何变换的叠加都将会转换成 matrix,方便我们调用 canvas 的指令。

Transform 类就类似 CSS 的 transform,它提供了一些更清晰、更符合人类直觉的变换,而不用直接使用矩阵变换,当然,这些变换最终会转换成矩阵变换。

参考资料:

  1. 如何通俗地讲解「仿射变换」?
  2. 仿射变换及其变换矩阵的理解
  3. 深入理解贝塞尔曲线
  4. 如何理解并应用贝塞尔曲线

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/note/centos.html b/cn/src/note/centos.html new file mode 100644 index 0000000000..f51f24f687 --- /dev/null +++ b/cn/src/note/centos.html @@ -0,0 +1,70 @@ + + + + + + CentOS | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

CentOS

查看当前系统的版本:

sh
cat /etc/centos-release

YUM

YUM 是 Yellowdog Updater, Modified 的缩写,虽然不是 CentOS 开发的,但已成为 CentOS 系统中常用的包管理工具。YUM 作为 RPM 的前端程序,解决了 RPM 软件包之间的依赖性问题,并提供了更加便捷的软件包管理方式。

YUM 仓库源

CentOS 8 的官方支持已经结束,但您仍然可以使用 CentOS Stream 8 或其他第三方仓库。如果您正在使用 CentOS 8,并且希望继续使用类似的仓库,可以考虑切换到 CentOS Stream 8。

1.替换镜像源

由于众所周知的原因,访问官方镜像会非常慢,所以

修改 /etc/yum.repos.d/CentOS-AppStream.repo 文件(或相应的仓库配置文件),将 baseurl 或 mirrorlist 指向一个可用的源。

我个人尝试,发现需要修改三个文件:

sh
/etc/yum.repos.d/CentOS-Base.repo
+/etc/yum.repos.d/CentOS-AppStream.repo
+/etc/yum.repos.d/CentOS-Extras.repo

修改文件内容:

sh
[baseos]
+name=CentOS-8 - Base
+baseurl=http://vault.centos.org/8.5.2111/BaseOS/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[appstream]
+name=CentOS-8 - AppStream
+baseurl=http://vault.centos.org/8.5.2111/AppStream/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial
+
+[extras]
+name=CentOS-8 - Extras
+baseurl=http://vault.centos.org/8.5.2111/extras/$basearch/os/
+gpgcheck=1
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-centosofficial

更新缓存并重试

  1. 清理缓存:yum clean all
  2. 生成新的缓存:yum makecache
  3. 更新系统:yum update

Last updated:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/note/docker.html b/cn/src/note/docker.html new file mode 100644 index 0000000000..077b6227bf --- /dev/null +++ b/cn/src/note/docker.html @@ -0,0 +1,115 @@ + + + + + + docker | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

docker

查询 docker 是否在运行:

  1. 输入以下命令来查找 Docker 守护进程的 PID(进程 ID):
sh
ps -ef | grep docker

如果命令返回了包含/usr/local/bin/dockerd(或类似路径)的行,并且 PID 列有数字显示,那么 Docker 守护进程正在运行。

  1. 使用 docker ps 命令

虽然 docker ps 命令主要用于列出正在运行的容器,但如果 Docker 服务没有运行,该命令会返回一个错误消息。因此,你也可以通过运行该命令并观察输出来判断 Docker 服务是否启动。

如果 Docker 服务正在运行,该命令将列出所有正在运行的容器(如果没有运行的容器,则可能只显示表头)。如果 Docker 服务没有运行,你将看到一个错误消息,如“Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?”

  1. 使用 docker info 命令

docker info 命令提供 Docker 系统的详细信息,包括容器数量、镜像数量、Docker 版本等。如果 Docker 服务正在运行,该命令将正常输出这些信息。

如果 Docker 服务正在运行,你将看到一系列关于 Docker 系统的信息。如果 Docker 服务没有运行,你将看到一个错误消息,与 docker ps 命令类似。

安装 docker 的网站:https://hub.docker.com/

images

Docker 把应用程序及其依赖,打包在 image 文件里面。只有通过这个文件,才能生成 Docker 容器。image 文件可以看作容器的模板。Docker 根据 image 文件生成的容器实例。同一个 image 文件,可以生成多个同时运行的容器实例

image 是二进制文件。实际开发过程中,一个 image 文件往往通过继承另一个 image 文件,再加上一些个性化的设置而成。

shell
# 搜索镜像
+$ docker search [keywords]
+# 列出本机所有的image文件
+$docker image ls
+# 删除image文件
+$docker image rm [imageName]
+$docker image rmi [imageID]

从仓库拉取镜像

  • image 文件从仓库拉到本地
shell
$ docker image pull library/hello-world
+# docker image pull 是抓去image文件的命令。library/hello-world是image仓库的位置
+# 其中library是image文件所在的组,hello-world是image文件的名字
+
+# 由于官方提供的image文件,都在library里面,所以它是默认组,可以省略
+# 因此$ docker image pull hello-world
  • 抓取成功后,可以在本机看到这个 image 文件
shell
$ docker image ls
  • 运行/创建这个 image 文件
shell
$ docker container run hello-world
+# docker container run 命令会从image文件,生成一个正在运行的容器
+# 如果没有指定image文件,会从仓库自动抓取,docker image pull 不是必须
  • 运行 image 文件 (重复使用容器),docker container run 会新建容器,每运行一次,就会新建一个容器
shell
# 用来启动已生成,或者已经停止的容器文件
+$ docker container start [containerID]
  • 查看 docker 容器的输出
shell
# 命令用来查看docker容器的输出
+$ docker container logs [containerID]
+# docker run 命令运行容器的时候,没有-it参数,就药用这个来输出
  • 进入一个正在运行的 docker 容器
shell
# 如果docker run 命令运行容器的时候,没有使用-it参数,就可以使用这个进入容器
+$ docker container exec -it [containerID] /bin/bash
  • 关闭容器
shell
# 终止容器的运行,强行立即终止
+$ docker container kill [containeId]
+# 终止容器的运行,会自动进行收尾工作,可能不会终止
+$ docker container stop [containerId]

container

  • image 文件生成的容器实例,本身也是一个文件,称为容器文件。
  • 一旦容器生成,就会同时存在两个文件:image 文件和容器文件。关闭容器并不会删除容器文件,只是容器停止运行而已
shell
# 列出本机正在运行的容器
+$ docker container ls
+# 列出本机所有的容器,包括终止运行的容器
+$ docker container ls --all
  • 终止运行的容器文件,依然会占据硬盘空间,可以删除,删除完再查看就没有了
shell
$ docker container rm [containerID]

生成容器

  • docker container run 命令会从 image 文件生成容器
shell
$ docker container run -p 8000:3000 -it koa-demo /bin/bash
+# 或者
+$ docker container run -p 8000:3000 -it koa-demo:0.0.1 /bin/bash
+# -p 参数:容器的3000端口映射到本机器的8000端口
+# -it 参数:容器的shell映射到当前的shell,然后你在本机窗口输入命令,就会传入容器
+# koa-demo:0.0.1 image文件的名字(如果有标签,还需要提供标签,默认是latest标签)
+# /bin/bash: 容器启动以后,内部第一个执行的命令。这里是启动Bash,保证用户可以使用Shell。
  • 这就表示在容器里面了,可以执行命令了
shell
root@66d80f4aaf1e:/app# node demos/01.js
  • 需要注意的是,node 进程运行在 Docker 容器的虚拟环境里面,进程接触到的文件系统和网络接口都是虚拟的,与本机的文件系统和网络接口是隔离的,因此需要定义容器与物理机的端口映射
  • 停止容器,释放内存
shell
# 在容器的命令行,通过Ctrl + c停止node进程,然后Ctrl + d(或者输入exit)退出容器
+# 或者使用docker container kill终止容器运行
+# 可能需要本机的另一个终端窗口,查看容器的ID
+$ docker container ls
+# 或
+$ docker container ls --all
+# 停止容器的运行
+$ docker container kill [containerID]
+# 容器停止运行后,并不会消失,需要删除容器文件
+# 删除指定容器文件
+$ docker container rm [containerID]
+# 或
+# 通过--rm参数,在容器终止运行后自动删除容器文件
+$ docker container run --rm -p 8000:3000 -it koa-demo /bin/bash

DockerFile

  • 一个文本文件,用来配置 imageDocker 根据该文件生成二进制的 image 文件
  • 先获取一个项目
shell
$ git clone https://github.com/ruanyf/koa-demos.git
+$ cd koa-demos
  • 进入项目,编写 .dockerignore 文件。指的是下面三个路径要排除,不要打包进入 image 文件。
shell
.git
+node_modules
+npm-debug.log
  • 根目录下新建一个文本文件 Dockerfile
shell
FROM node:8.4
+# 该image文件继承官方的node image,冒号表示标签,这是8.4版本的node
+COPY . /app
+# .是当前目录下的所有文件(除了.dockerignore排除的文件),都拷贝进入image文件的/app目录
+WORKDIR /app
+# 指定接下来的工作路径为/app
+RUN npm install
+# 在/app目录下,运行npm install命令安装依赖。注意,安装后所有的依赖,都将打包进入image文件
+EXPOSE 3000
+# 将容器的3000端口暴露出来,允许外部连接这个端口
  • 有了 Dockerfile 文件以后,就可以使用 docker image build 命令创建 image 文件了。
shell
$ docker image build -t koa-demo .
+# 用-t参数来制定image文件的名字,最后的 . 代表Dockerfile文件所在的路径,因为是当前路径
+# 或者
+$ docker image build -t koa-demo:0.0.1 .
+# 后面还可以用冒号指定标签。如果不指定,默认标签就是latest。
+# 运行成功就可以用 docker image ls 来查看了

CMD 命令

  • 可以随着容器的启动而执行的命令,比如上个例子手动执行的 node demos/01.js。可以把这个命令写在 Dockerfile 里面
shell
FROM node:8.4
+COPY . /app
+WORKDIR /app
+RUN npm install --registry=https://registry.npm.taobao.org
+EXPOSR 3000
+# 表示容器启动后自动执行
+CMD node demos/01.js
  • CMD 命令和 RUN 命令的区别
    • RUN 命令在 image 文件的构建阶段执行,执行结果都会打包进行 image 文件
    • CMD 命令是容器启动后执行
    • 一个 dockerfile 可以有多个 RUN 命令,但只有一个 CMD 命令
    • 指定了 CMD 命令后,docker container run 命令就不能附加命令了 (比如前面的/bin/bash),否则他会覆盖 CMD 命令,现在可以使用
shell
$ docker container run --rm - p 8000:3000 -it koa-demo:0.0.1

问题:

  1. 如果遇到 docker desktop 登录不上,可以尝试 docker login进行登录,命令行登录会输出错误的信息,如果发现是网络问题,换一个代理即可。
  2. Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
shell
# docker服务没有启动
+$ service docker start

参考资料

Last updated:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/note/libreoffice2wasm.html b/cn/src/note/libreoffice2wasm.html new file mode 100644 index 0000000000..d79d434dd4 --- /dev/null +++ b/cn/src/note/libreoffice2wasm.html @@ -0,0 +1,117 @@ + + + + + + 克隆 Binaryen 仓库 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

项目地址:

sh
git clone https://git.libreoffice.org/core

github 地址:https://github.com/LibreOffice/core/blob/master/static/README.wasm.md

容器化环境

由于是 c/c++ 的项目,编译过程需要很多系统级别配置。如果当前设备不支持的话,不建议强行去适配。可以进行容器化处理。

比如用一个最常见的服务器系统:

sh
docker image pull ubuntu

下载完成后,就可以去构建一个服务了:

sh
docker container run -p 30105:30105 --name=alit -itd ubuntu /bin/bash

构建并启动成功后,可以通过docker container ls去查看运行情况:

sh
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS                      NAMES
+efd831ab0ba8   ubuntu    "/bin/bash"   5 seconds ago   Up 4 seconds   0.0.0.0:30105->30105/tcp   alit

再将项目移动到容器中:

sh
docker cp ./core alit:/home
+# 总的来说,项目还是非常大的
+# Successfully copied 3.59GB to alit:/home

进入容器,进行操作。

sh
docker exec -it alit /bin/bash

这样,就可以把开发构建环境和电脑系统隔离开,防止一些系统级别不安全的操作了。

安装必要的依赖:

sh
dnf install -y git cmake python3 nodejs
+
+## 遇到问题:
+
+1. 执行 `./autogen.sh`报错,提示`Failed to run aclocal at ./autogen.sh line 195.`
+
+```sh
+brew install automake

安装完成后,执行aclocal --version或者automake --version检查是否安装完成

  1. 执行 ./autogen.sh遇到报错:
sh
checking the GNU Make version... configure: error: failed (/usr/bin/make version >= 4.0 needed)
+Error running configure at ./autogen.sh line 323.

通过 make --version 检查 make 的版本,执行 brew install make,再执行 brew upgrade 进行升级。确保 make的版本大于 4.0

当使用 brew 安装 GNU Make 时,它通常会被命名为 gmake 而不是 make ,以区分于 macOS 系统自带的 BSD Make。如果你希望在使用 make 命令时实际上调用 gmake ,需要进行一些特殊处理来替换或设置别名。

在.zshrc 文件中添加如下行:

sh
# Configure the brew installation of gmake, alias to make
+alias make='gmake'

然后,保存文件并重新加载配置文件(通过 source ~/.zshrc 或重新打开终端)。

在项目中搜索并替换成:

sh
# args.makecmd = '/usr/bin/make'
+args.makecmd = '/opt/homebrew/bin/gmake'

在编译完成后,找到可执行的文件:

sh
find . -name soffice

然后执行

sh
/home/core/instdir/program/soffice --headless --convert-to pdf /home/office/pptx.pptx

将 LibreOffice 编译成 WebAssembly 并在 Web 上运行特定命令(如 soffice --headless --convert-to pdf /home/office/pptx.pptx)是一个复杂的任务。以下是一个大致的实现步骤和思路:

  1. 编译 LibreOffice 为 WebAssembly 假设你已经成功编译了 LibreOffice 并生成了 .wasm 文件和相关的 JavaScript 文件。

  2. 创建 HTML 和 JavaScript 文件 创建一个 HTML 文件来加载 WebAssembly 模块,并编写 JavaScript 代码来调用 soffice 命令。

HTML 文件 (index.html)

html
<!doctype html>
+<html>
+  <head>
+    <title>LibreOffice WebAssembly</title>
+    <script src="libreoffice.js"></script>
+  </head>
+  <body>
+    <input type="file" id="fileInput" />
+    <button onclick="convertToPDF()">Convert to PDF</button>
+    <script src="main.js"></script>
+  </body>
+</html>
+JavaScript 文件 (main.js) // Initialize the Module var Module = { onRuntimeInitialized: function() {
+console.log("LibreOffice WebAssembly Module Loaded"); } }; // Function to convert file to PDF function convertToPDF() {
+var fileInput = document.getElementById('fileInput'); if (fileInput.files.length == 0) { alert("Please select a file.");
+return; } var file = fileInput.files[0]; var reader = new FileReader(); reader.onload = function(event) { var
+arrayBuffer = event.target.result; var byteArray = new Uint8Array(arrayBuffer); // Write the file to the WASM virtual
+file system var filename = '/home/office/' + file.name; Module.FS_createDataFile('/', filename, byteArray, true, true);
+// Call the soffice command var command = 'soffice --headless --convert-to pdf ' + filename; Module.ccall( 'system', //
+name of C function 'number', // return type ['string'], // argument types [command] // arguments ); // Read the output
+PDF file var outputFilename = '/home/office/' + file.name.replace(/\.[^/.]+$/, "") + '.pdf'; var output =
+Module.FS_readFile(outputFilename); // Create a blob and a link to download the PDF var blob = new Blob([output], {
+type: 'application/pdf' }); var link = document.createElement('a'); link.href = window.URL.createObjectURL(blob);
+link.download = file.name.replace(/\.[^/.]+$/, "") + '.pdf'; link.click(); }; reader.readAsArrayBuffer(file); }
  1. 部署和测试 将生成的 .wasm 文件、JavaScript 文件和 HTML 文件部署到你的 Web 服务器上,打开 index.html 文件,选择一个 PPTX 文件并点击“Convert to PDF”按钮。这个过程会:

从文件输入中读取 PPTX 文件。 将文件写入 WebAssembly 模块的虚拟文件系统。 调用 soffice --headless --convert-to pdf 命令进行转换。 从虚拟文件系统中读取生成的 PDF 文件。 创建一个下载链接,允许用户下载生成的 PDF 文件。4. 注意事项 这个过程可能需要大量的内存和计算资源,可能需要优化和调整。 需要确保 Emscripten 的文件系统(MEMFS)能够正确处理大文件。 需要处理可能的错误和异常情况,并提供用户友好的错误提示。 通过这些步骤,你应该能够在 Web 上调用 soffice 命令并将 PPTX 文件转换为 PDF。如果遇到具体问题,请提供详细的错误信息,以便更好地帮助你解决问题。

减少 WebAssembly 文件的体积是一个常见的需求,尤其是在处理像 LibreOffice 这样的大型项目时。如果你只需要特定的功能(如将文件转换为 PDF),可以采取以下几种方法来减小生成的 WebAssembly 文件的体积:

  1. 精简功能模块 确保只编译你需要的功能模块。你已经在 autogen.input 中指定了 --with-main-module=writer,这会限制编译的模块,但你可以进一步精简。

  2. 移除不必要的组件 在 autogen.input 中,进一步禁用不必要的组件和功能。例如:

--disable-dbus --disable-odk --disable-postgresql-sdbc --disable-firebird-sdbc --disable-coinmp --disable-cve-tests --disable-gtk3 --disable-gstreamer-1-0 --disable-kf5 --disable-scripting-beanshell --disable-scripting-javascript --disable-extensions --disable-epm --disable-online-update --disable-python --disable-pdfimport --disable-lpsolve --disable-sdremote --disable-scripting --disable-avmedia --disable-coinmp --disable-report-builder --disable-odk --disable-pch --disable-skia --disable-scripting

  1. 使用 Emscripten 优化选项 Emscripten 提供了多种优化选项,可以帮助减小生成的 WebAssembly 文件的体积:

使用 -O3 或 -Oz 进行最大化优化。 使用 --closure 1 进行 JavaScript 代码的闭包优化。 使用 --llvm-lto 3 进行链接时间优化。 在编译时,确保使用这些选项:

emconfigure ./configure ... emmake make CXXFLAGS="-O3 --llvm-lto 3" LDFLAGS="-O3 --llvm-lto 3" 4. 移除调试信息 确保移除所有调试信息,这可以显著减小文件体积:

emconfigure ./configure ... emmake make CXXFLAGS="-O3 --llvm-lto 3 -g0" LDFLAGS="-O3 --llvm-lto 3 -g0" 5. 使用 WebAssembly Minifier 使用 WebAssembly Minifier 工具(如 wasm-opt)进一步优化和减小生成的 WebAssembly 文件:

wasm-opt -Oz -o optimized.wasm original.wasm 6. 自定义构建脚本 如果上述方法仍然不能满足需求,可以考虑编写自定义构建脚本,只包含必要的源文件和库,进一步精简生成的 WebAssembly 文件。

  1. 动态加载模块 如果可能,将一些功能模块拆分为单独的 WebAssembly 文件,并在需要时动态加载,以减少初始加载的体积。

示例 autogen.input 以下是一个示例 autogen.input 文件,结合了上述建议:

sh
--disable-debug
+--enable-sal-log
+--disable-crashdump
+--host=wasm32-local-emscripten
+--disable-gui
+--with-main-module=writer
+--with-package-format=emscripten
+--disable-dbus
+--disable-odk
+--disable-postgresql-sdbc
+--disable-firebird-sdbc
+--disable-coinmp
+--disable-cve-tests
+--disable-gtk3
+--disable-gstreamer-1-0
+--disable-kf5
+--disable-scripting-beanshell
+--disable-scripting-javascript
+--disable-extensions
+--disable-epm
+--disable-online-update
+--disable-python
+--disable-pdfimport
+--disable-lpsolve
+--disable-sdremote
+--disable-scripting
+--disable-avmedia
+--disable-coinmp
+--disable-report-builder
+--disable-odk
+--disable-pch
+--disable-skia
+--disable-scripting

通过这些步骤,你应该能够显著减小生成的 WebAssembly 文件的体积,同时保留将文件转换为 PDF 的功能。如果遇到具体问题,请提供详细的错误信息,以便更好地帮助你解决问题。

wasm-opt 是 Binaryen 项目的一部分,它是一个用于优化和处理 WebAssembly 二进制文件的工具。你可以在 Ubuntu 上通过以下步骤安装和使用 wasm-opt:

  1. 安装依赖项 首先,确保你的系统上已经安装了必要的依赖项:

sudo apt update sudo apt install cmake build-essential git 2. 下载和编译 Binaryen 接下来,从源码编译 Binaryen:

克隆 Binaryen 仓库

git clone https://github.com/WebAssembly/binaryen.git cd binaryen

创建并进入构建目录

mkdir build cd build

使用 CMake 配置构建

cmake ..

编译 Binaryen

make

安装 Binaryen

sudo make install 3. 使用 wasm-opt 安装完成后,你可以使用 wasm-opt 命令来优化 WebAssembly 文件。例如:

假设你有一个名为 original.wasm 的 WebAssembly 文件

wasm-opt -Oz -o optimized.wasm original.wasm 在这个命令中:

-Oz 表示进行最大化的尺寸优化。 -o optimized.wasm 指定输出文件名为 optimized.wasm。 original.wasm 是输入的 WebAssembly 文件。4. 验证安装 你可以通过运行以下命令来验证 wasm-opt 是否正确安装:

wasm-opt --version 这将输出 wasm-opt 的版本信息,确认它已成功安装并可以使用。

示例 假设你有一个名为 example.wasm 的 WebAssembly 文件,你可以通过以下命令优化它:

wasm-opt -Oz -o example_optimized.wasm example.wasm 这将生成一个优化后的 WebAssembly 文件 example_optimized.wasm,其体积通常会显著减小。

通过这些步骤,你应该能够在 Ubuntu 上成功安装和使用 wasm-opt 来优化你的 WebAssembly 文件。如果在安装或使用过程中遇到任何问题,请提供详细的错误信息,以便进一步帮助你解决问题。

--disable-debug --enable-sal-log --disable-crashdump --host=wasm32-local-emscripten --disable-gui --with-main-module=writer --with-package-format=emscripten --disable-dbus --disable-odk --disable-postgresql-sdbc --disable-firebird-sdbc --disable-coinmp --disable-cve-tests --disable-gtk3 --disable-gstreamer-1-0 --disable-kf5 --disable-scripting-beanshell --disable-scripting-javascript --disable-extensions --disable-epm --disable-online-update --disable-python --disable-pdfimport --disable-lpsolve --disable-sdremote --disable-scripting --disable-avmedia --disable-coinmp --disable-report-builder --disable-odk --disable-pch --disable-skia --disable-scripting

步骤 1:下载最新的 OpenSSL 源代码 首先,确保你在一个干净的目录中,然后下载最新版本的 OpenSSL 源代码。你可以访问 OpenSSL 官方网站 查看最新版本。假设最新版本是 openssl-3.0.9:

wget https://www.openssl.org/source/openssl-3.0.9.tar.gz tar -xzvf openssl-3.0.9.tar.gz cd openssl-3.0.9 步骤 2:编译和安装 OpenSSL 接下来,编译并安装 OpenSSL:

./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl shared zlib make make test make install 步骤 3:确认 OpenSSL 安装路径 确保 OpenSSL 的头文件和库文件已正确安装:

ls /usr/local/ssl/include ls /usr/local/ssl/lib 步骤 4:设置环境变量 设置正确的环境变量,以便编译时能找到 OpenSSL:

export PKG_CONFIG_PATH="/usr/local/ssl/lib/pkgconfig" export CFLAGS="-I/usr/local/ssl/include" export LDFLAGS="-L/usr/local/ssl/lib -lssl -lcrypto" 步骤 5:清理之前的配置 在重新运行 configure 脚本之前,清理之前的配置:

make clean 步骤 6:重新运行 configure 脚本 重新运行 configure 脚本,以确保它能找到新的 OpenSSL 版本:

emconfigure ./configure --disable-debug --enable-sal-log --disable-crashdump --host=wasm32-local-emscripten --disable-gui --with-main-module=writer --with-package-format=emscripten --disable-dbus --disable-odk --disable-postgresql-sdbc --disable-firebird-sdbc --disable-coinmp --disable-cve-tests --disable-gtk3 --disable-gstreamer-1-0 --disable-kf5 --disable-scripting-beanshell --disable-scripting-javascript --disable-extensions --disable-epm --disable-online-update --disable-python --disable-pdfimport --disable-lpsolve --disable-sdremote --disable-scripting --disable-avmedia --disable-coinmp --disable-report-builder --disable-odk --disable-pch --disable-skia --disable-scripting --srcdir=/home/core --enable-option-checking=fatal --disable-pthreads 步骤 7:检查 config.log 如果配置仍然失败,请检查 config.log 文件以获取更多详细信息:

cat config.log | grep openssl 通过确保 OpenSSL 已正确安装并设置正确的环境变量,我们应该能够解决配置过程中遇到的问题。如果问题仍然存在,请提供 config.log 文件中与 OpenSSL 相关的更多详细信息,以便进一步诊断和解决问题。

emconfigure ./configure --disable-debug --enable-sal-log --disable-crashdump --host=wasm32-local-emscripten --disable-gui --with-main-module=writer --with-package-format=emscripten --disable-dbus --disable-odk --disable-postgresql-sdbc --disable-firebird-sdbc --disable-coinmp --disable-cve-tests --disable-gtk3 --disable-gstreamer-1-0 --disable-kf5 --disable-scripting-beanshell --disable-scripting-javascript --disable-extensions --disable-epm --disable-online-update --disable-python --disable-pdfimport --disable-lpsolve --disable-sdremote --disable-scripting --disable-avmedia --disable-coinmp --disable-report-builder --disable-odk --disable-pch --disable-skia --disable-scripting --srcdir=/home/core --enable-option-checking=fatal

emmake make CXXFLAGS="-I/usr/local/ssl/include -O3 -g0 -msimd128" LDFLAGS="-L/usr/local/ssl/lib -lssl -lcrypto -O3 -g0"

emconfigure ./configure --disable-cups --disable-dbus --without-system-fontconfig --with-system-zlib --disable-dynamic-loading --disable-gui CXXFLAGS=-std=c++20 --host=wasm32-unknown-emscripten

root@8cb3480a4441:/home/core/instsetoo_native# vim CustomTarget_emscripten-install.mk

使用 file_packager.py 工具将文件预加载到虚拟文件系统中。确保 Emscripten 的环境变量已经正确设置,然后运行以下命令:

python3 /home/emsdk/upstream/emscripten/tools/file_packager.py preload.data --preload /home/core/instdir/share@/instdir/share --js-output=preload.js

Last updated:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/note/ubuntu.html b/cn/src/note/ubuntu.html new file mode 100644 index 0000000000..06e9642afd --- /dev/null +++ b/cn/src/note/ubuntu.html @@ -0,0 +1,51 @@ + + + + + + ubuntu | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

ubuntu

sh
apt update
+
+apt install openjdk-11-jdk  wget curl junit4 ant libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1.0-dev libgtk-3-dev libglib2.0-dev libatk1.0-dev libcairo2-dev zip flex uuid-runtime bison libxrandr-dev libxrender-dev libxext-dev libnss3-dev libnspr4-dev libkrb5-dev python3 python3-pip libxml2-utils xsltproc libxslt1-dev gperf libfontconfig1-dev libcups2-dev gcc make autoconf pkg-config automake

Last updated:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/button/index.html b/cn/src/ranui/button/index.html new file mode 100644 index 0000000000..999ab3d36a --- /dev/null +++ b/cn/src/ranui/button/index.html @@ -0,0 +1,57 @@ + + + + + + Button 按钮 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Button 按钮

按钮用于开始一个即时操作。

代码演示

Button
xml
 <r-button >Button</r-button>

属性

类型type

按钮有四种类型

主要按钮
警告按钮
文本按钮
默认按钮
xml
 <r-button type="primary">主要按钮</r-button>
+ <r-button type="warning">警告按钮</r-button>
+ <r-button type="text">文本按钮</r-button>
+ <r-button >默认按钮</r-button>

不可用状态disabled

添加 disabled 属性即可让按钮处于不可用状态,同时按钮样式也会改变。

主要按钮
警告按钮
文本按钮
默认按钮
xml
 <r-button type="primary" disabled>主要按钮</r-button>
+ <r-button type="warning" disabled>警告按钮</r-button>
+ <r-button type="text" disabled>文本按钮</r-button>
+ <r-button disabled>默认按钮</r-button>

图标icon

当需要在 Button 内嵌入 Icon 时,可以设置 icon 属性,或者直接在 Button 内使用 Icon 组件。

如果想控制 Icon 具体的位置,只能直接使用 Icon 组件,而非 icon 属性。

默认按钮
主要按钮
xml
<r-button type="default" icon="user">默认按钮</r-button>
+<r-button type="primary" icon="home">主要按钮</r-button>

特效 effect

如果需要纯净的 Button,可以加上 effect = false,屏蔽点击时候的水波纹特效

默认按钮主要按钮
xml
<r-button type="default" icon="user">默认按钮</r-button>
+<r-button type="primary" icon="home">主要按钮</r-button>

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/checkbox/index.html b/cn/src/ranui/checkbox/index.html new file mode 100644 index 0000000000..7b816e8dcb --- /dev/null +++ b/cn/src/ranui/checkbox/index.html @@ -0,0 +1,52 @@ + + + + + + CheckBox 多选框 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

CheckBox 多选框

代码演示

xml
 <r-checkbox ></r-checkbox>

属性

checked

xml
 <r-checkbox checked="true"></r-checkbox>
+ <r-checkbox checked="false"></r-checkbox>

disabled

xml
 <r-checkbox checked="true" disabled></r-checkbox>
+ <r-checkbox checked="false" disabled></r-checkbox>

事件event

改变的时候触发。

onchange

xml
 <r-checkbox onchange="console.log(this.checked)"></r-checkbox>
+ <r-checkbox onchange="console.log(this.checked)"></r-checkbox>

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/icon/index.html b/cn/src/ranui/icon/index.html new file mode 100644 index 0000000000..7454e0ff5f --- /dev/null +++ b/cn/src/ranui/icon/index.html @@ -0,0 +1,60 @@ + + + + + + Icon 图标 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Icon 图标

语义化的矢量图形

代码演示

xml
 <r-icon name="lock"  ></r-icon>
+ <r-icon name="eye"  ></r-icon>
+ <r-icon name="user"  ></r-icon>

属性

名称name

根据名称选择不同的图标

html
<r-icon name="lock"></r-icon>
+<r-icon name="eye"></r-icon>
+<r-icon name="user"></r-icon>

尺寸size

html
<r-icon name="lock" size="30"></r-icon>
+<r-icon name="lock" size="50"></r-icon>
+<r-icon name="lock" size="70"></r-icon>

颜色color

html
<r-icon name="lock" size="50" color="red"></r-icon>
+<r-icon name="lock" size="50" color="#1E90FF"></r-icon>
+<r-icon name="lock" size="50" color="#F44336"></r-icon>
+<r-icon name="lock" size="50" color="#3F51B5"></r-icon>

旋转spin

设置 spin 开启旋转,传入数字控制旋转的速度,数字越小旋转越快

html
<r-icon name="loading" size="50" color="#1E90FF" spin="0.7"></r-icon>
+<r-icon name="loading" size="50" color="#1E90FF" spin></r-icon>
+<r-icon name="loading" size="50" color="#1E90FF" spin="5"></r-icon>

图标列表

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/image/index.html b/cn/src/ranui/image/index.html new file mode 100644 index 0000000000..515b116be3 --- /dev/null +++ b/cn/src/ranui/image/index.html @@ -0,0 +1,49 @@ + + + + + + Image 图片 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Image 图片

代码演示

xml
 <r-img src="" fallback=""></r-img>

属性

图片加载地址src

图片的地址

图片加载失败fallback

src配置的图片加载失败,兜底的图片地址,下面是默认加载失败图片

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/index.html b/cn/src/ranui/index.html new file mode 100644 index 0000000000..51e47ffdd8 --- /dev/null +++ b/cn/src/ranui/index.html @@ -0,0 +1,135 @@ + + + + + + ranui | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

ranui

基于 Web Components开发方案

特点

  1. 跨框架兼容: 与 React, Vue, Preact, SolidJS, Svelte 等兼容。可以和遵循 W3C 标准的任何 JavaScript 项目集成。
  2. 原生体验: 易于入门,像使用本地 div 标签,简化项目大小和减少学习成本。
  3. 模块化设计: 可选导入和全量导入,以增强可维护性和可伸缩性。
  4. 交互式丰富文档: 提供详细的交互式文档,并附有有效的示例子。
  5. 支持类型校验: 基于 TypeScript 构建,具有类型支持,确保代码的健壮性和可维护性。
  6. 持久和稳定: 与框架 (React/vue) 无关,避免破坏性的更新,并确保持续的项目运行。

安装

使用 npm:

console
npm install ranui --save

引入方式

支持按需导入,以显著减少包体积大小

js
import 'ranui/button';

如果遇到样式问题,可以选择手动导入样式文件

js
import 'ranui/style';

如果遇到类型问题,可以选择手动导入类型文件

ts
import 'ranui/types';

或者

ts
import 'ranui/dist/typings';

也支持全量导入

ts
import 'ranui';
  • ES module
js
import 'ranui';

或者

js
import 'ranui/button';
  • UMD, IIFE, CJS
html
<script src="./ranui/dist/umd/index.umd.cjs"></script>

使用方式

它是基于Web Components的组件,你可以不用关注框架就可以使用它。

在大多数情况下,您可以像使用本地 div 标签一样使用它

下面是一些例子:

  • html
  • js
  • jsx
  • vue
  • tsx

html

html
<script src="./ranui/dist/umd/index.umd.cjs"></script>
+
+<body>
+  <r-button>Button</r-button>
+</body>

js

js
import 'ranui';
+
+const Button = document.createElement('r-button');
+Button.appendChild('this is button text');
+document.body.appendChild(Button);

jsx

jsx
import 'ranui';
+
+const App = () => {
+  return (
+    <>
+      <r-button>Button</r-button>
+    </>
+  );
+};

vue

vue
<template>
+  <r-button></r-button>
+</template>
+<script>
+import 'ranui';
+</script>

tsx

tsx
// react 18
+import type { SyntheticEvent } from 'react';
+import React, { useRef } from 'react';
+import 'ranui';
+
+const FilePreview = () => {
+  const ref = useRef<HTMLDivElement | null>(null);
+  const uploadFile = (e: SyntheticEvent<HTMLDivElement>) => {
+    if (ref.current) {
+      const uploadFile = document.createElement('input');
+      uploadFile.setAttribute('type', 'file');
+      uploadFile.click();
+      uploadFile.onchange = (e) => {
+        const { files = [] } = uploadFile;
+        if (files && files?.length > 0 && ref.current) {
+          ref.current.setAttribute('src', '');
+          const file = files[0];
+          const url = URL.createObjectURL(file);
+          ref.current.setAttribute('src', url);
+        }
+      };
+    }
+  };
+  return (
+    <div>
+      <r-preview ref={ref}></r-preview>
+      <r-button type="primary" onClick={uploadFile}>
+        choose file to preview
+      </r-button>
+    </div>
+  );
+};

Overview 组件总览

  • Button
主要按钮
警告按钮
文本按钮
默认按钮
  • Icon
  • Skeleton
  • Input
  • message
信息提示警告提示错误提示成功提示toast 提示
  • Tab
tab1tab2tab3
  • Radar
  • Progress
  • Player
  • Select
MikeTomLucy
  • Loading
  • math

Event 事件

  • react

@ranui/react 是由react高阶函数封装ranui而成,Event 事件遵循react事件规范。跟W3C标准略有不同。

  • 现代web标准

W3C标准中,你可以使用on属性在HTML元素上定义事件处理程序。但这是旧的事件处理程序的方法。

现代的web开发推荐使用addEventListener方法。

html
<r-button id="button">按钮</r-button>
+
+<script>
+  const button = document.getElementById('button');
+  button.addEventListener('click', function (event) {
+    alert('新的点击事件!');
+  });
+</script>

然而,如果你确实需要使用on属性,下面是一个示例:

html
<r-input onchange="change(this.value)"></r-input>
+
+<script>
+  function change(e) {
+    console.log('e--->', e);
+  }
+</script>

请注意,使用on属性来定义事件处理程序有一些限制和缺点。

例如,你不能使用事件捕获或事件委托,而且每个事件类型都需要一个单独的属性。

这也是为什么现代的web开发推荐使用addEventListener方法的原因。

还可以使用property的方式:

html
<r-input id="input"></r-input>
+
+<script>
+  const input = document.getElementById("input")
+  input.onchange = (e) {
+    console.log('e--->', e)
+  }
+</script>

style 自定义样式

::part伪类

html
<r-input id="input"></r-input>
+
+<style>
+  /* #input 指的是当前的自定义元素
+  ::part(input) 中的 input 指的是,当前自定义元素内部的 Shadow DOM 元素的类 */
+  #input::part(input) {
+    width: 100px;
+  }
+</style>

具体的伪类名称可以查看具体的具体介绍

通过sheet属性传入

会在所有的组件上加一个sheet属性,传入CSSStyleSheet字符串。会直接插入到Shadow DOM

css3变量var

通过给组件设置css3变量,从而自定义组件内部的指定样式,比如:


html
<r-progress percent="0.7" type="drag"></r-progress>
+<r-progress
+  percent="0.70"
+  type="drag"
+  style="--ran-progress-wrap-background:linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);"
+></r-progress>

具体css3变量名称可以参考每个组件的介绍和说明

Compatibility 兼容性

  • 不支持 IE,其他均有较好支持

Contributors 贡献者

Other 相关资源

  1. 优秀的组件设计
  2. 在线生成 CSS 渐变色
  3. 优秀设计作品,有 psd 和 sketch
  4. 3D UI 设计,类似于 3D 版的 figma
  5. 设计规范
  6. 优秀设计作品
  7. element UI 中文网
  8. Ant design 中文网
  9. 在线绘制 CSS 动画
  10. tailwindcss 组件库
  11. animate css 非常优秀的 css 动画
  12. can i use 检测兼容性 API 网站
  13. figma

协议和标准

  1. RFCs
  2. ECMA
  3. w3c

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/input/index.html b/cn/src/ranui/input/index.html new file mode 100644 index 0000000000..0d1fb3b934 --- /dev/null +++ b/cn/src/ranui/input/index.html @@ -0,0 +1,60 @@ + + + + + + Input 输入框 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Input 输入框

通过鼠标或键盘输入内容,是最基础的表单域的包装。

代码演示

输入框:
xml
<r-input></r-input>

属性

标签label

提供类似于 Metiral Design 的输入体验。

html
<r-input label="user"></r-input>

占位placeholder

与原生placeholder一致。

html
<r-input placeholder="user"></r-input>

禁用disabled

通过disabled可以禁用输入框,禁用后该按钮上的事件失效。

html
<r-input label="user" disabled></r-input>

value

设置或返回输入框的value属性值。

类型type

目前支持passwordnumber这几种类型,设置后会出现额外的ui控件。

密码输入框

支持密码明文和密文切换。

html
<r-input icon="lock" type="password"></r-input>

图标icon

可以设置一个icon来表示标签标识。

html
<r-input icon="user"></r-input>

数字输入框

数字输入框,类似于原生input[type=number],支持minmaxstep属性,支持键盘上下键切换数字。

html
<r-input type="number" min="-10" max="10" step="0.5"></r-input>

name 属性名

跟 form 组件联动的时候有效,form 提交时收集的字段名字

status 状态

  • error

默认色值: #ff4d4f

xml
<r-input status="error"></r-input>
  • warning

默认色值: #ff7875

xml
<r-input  status="warning"></r-input>

事件event

常见的回调事件。

onchange

文本改变的时候触发。

html
<r-input onchange="func(this.value)"></r-input>
js
const input = document.createElement('r-input');
+input.setAttribute('label', 'home');
+const func = (e) => {
+  console.log(e);
+};
+input.addEventListener('change', func);

oninput

输入时触发。

js
const input = document.createElement('r-input');
+input.setAttribute('label', 'home');
+const func = (e) => {
+  console.log(e);
+};
+input.addEventListener('input', func);

事件的e参数结构 input方法

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/loading/index.html b/cn/src/ranui/loading/index.html new file mode 100644 index 0000000000..d911dbe2f8 --- /dev/null +++ b/cn/src/ranui/loading/index.html @@ -0,0 +1,54 @@ + + + + + + Loading | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Loading

一些好看的 loading

Code demo

xml
<r-loading name="circle"></r-loading>

属性

name

这里有很多好看的 loading,可供选择

xml
<r-loading name="double-bounce"></r-loading>
+<r-loading name="rotate"></r-loading>
+<r-loading name="stretch"></r-loading>
+<r-loading name="cube"></r-loading>

Loading list

Move the mouse over the icon to see the loading animation

stretch
rotate
double-bounce
cube
dot
triple-bounce
scale-out
circle
circle-line
square
pulse
solar
cube-fold
circle-fold
cube-grid
circle-turn
circle-rotate
circle-spin
dot-bar
dot-circle
line
dot-pulse
line-scale
text
cube-dim
dot-line
arc
drop
pacman

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/math/index.html b/cn/src/ranui/math/index.html new file mode 100644 index 0000000000..0214a3c47c --- /dev/null +++ b/cn/src/ranui/math/index.html @@ -0,0 +1,49 @@ + + + + + + math 数学公式 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

math 数学公式

HTML 页面中高质量展示 LaTeX 数学公式

代码演示

xml
<r-math latex="\frac{x^2}{a^2} + \frac{y^2}{b^2} = 1 \quad (a > b > 0)"></r-math>

属性

latex string

xml
  <r-math latex="x = {-b \pm \sqrt{b^2-4ac} \over 2a}"></r-math>

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/message/index.html b/cn/src/ranui/message/index.html new file mode 100644 index 0000000000..0673a53670 --- /dev/null +++ b/cn/src/ranui/message/index.html @@ -0,0 +1,53 @@ + + + + + + message 全局提示 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

message 全局提示

全局展示操作反馈信息。

代码演示

点击触发全局提示
xml
<r-button type="primary" onclick="message.info('这是一条提示')">点击触发全局提示</r-button>

属性

类型type

不同的提示类型

信息提示
警告提示
错误提示
成功提示
toast提示
html
<r-button onclick="message.info('这是一条提示')">信息提示</r-button>
+<r-button onclick="message.warning('这是一条提示')">警告提示</r-button>
+<r-button onclick="message.error('这是一条提示')">错误提示</r-button>
+<r-button onclick="message.success('这是一条提示')">成功提示</r-button>
+<r-button onclick="message.toast('这是一条提示')">toast提示</r-button>

方法

组件提供了一些静态方法,使用方式和参数如下:

  1. 可以只传一个参数,提示的内容,默认提示 3000 毫秒

message.info('这是一条提示')

message.warning('这是一条提示')

message.error('这是一条提示')

message.success('这是一条提示')

message.toast('这是一条提示')"

  1. 也可以传一个对象,设置提示内容,关闭延时,关闭时触发的回调函数

message.info({content:'这是一条提示', duration: 2000, close: () => {}})

message.warning({content:'这是一条提示', duration: 2000, close: () => {}})

message.error({content:'这是一条提示', duration: 2000, close: () => {}})

message.success({content:'这是一条提示', duration: 2000, close: () => {}})

message.toast({content:'这是一条提示', duration: 2000, close: () => {}})

参数说明类型
content提示内容string
duration自动关闭的延时,单位毫秒。默认 3000 毫秒number
close关闭时触发的回调函数() => void

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/modal/index.html b/cn/src/ranui/modal/index.html new file mode 100644 index 0000000000..3ba8c9031a --- /dev/null +++ b/cn/src/ranui/modal/index.html @@ -0,0 +1,49 @@ + + + + + + ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cn/src/ranui/player/index.html b/cn/src/ranui/player/index.html new file mode 100644 index 0000000000..e55f5e334a --- /dev/null +++ b/cn/src/ranui/player/index.html @@ -0,0 +1,49 @@ + + + + + + r-player 视频播放器 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

r-player 视频播放器

基于hlsjsweb components,让原生的标签r-player拥有统一的视频控件。 不采用new Player(options)的方式挂载到指定dom,视图的归视图,逻辑的归逻辑,所见及所得,更加直观。

  1. 可拖拽进度条
  2. 音量控制
  3. 根据当前带宽自适应码率切换
  4. 手动清晰度切换
  5. 倍速播放
  6. 样式自定义覆盖
  7. hls协议标准加密视频播放
  8. 基于原生开发,可在所有框架运行,统一跨框架情况
  9. 各浏览器控件统一

代码演示

xml
  <r-player src="/ran/hls/example.m3u8"></r-player>

属性

src

视频的资源地址

volume

设置初始音量,默认 0.5

currentTime

设置初始播放时间,默认从头开始播放

playbackRate

设置倍速,默认 1.0

debug

控制台会打印输出一些信息

事件event

onchange

监听任何播放器发生的变化,返回的值如下。

可通过这个方法获得播放器的实例

活着通过type判断不同的事件类型,进行不同的操作

属性说明类型
type发生变化的事件类型string
data事件的值Object
currentTime播放的当前时间number
duration视频的总时长number
tag播放器的实例Element

其中type类型有

名称说明
canplay浏览器可以播放媒体文件了,但估计没有足够的数据来支撑播放到结束,不必停下来进一步缓冲内容。
canplaythrough浏览器估计它可以在不停止内容缓冲的情况下播放媒体直到结束。
completeOfflineAudioContext 渲染完成。
durationchangeduration 属性的值改变时触发。
emptied媒体内容变为空;例如,当这个 media 已经加载完成(或者部分加载完成),则发送此事件,并调用 load() 方法重新加载它。
ended视频停止播放,因为 media 已经到达结束点。
loadedmetadata已加载元数据。
progress在浏览器加载资源时周期性触发。
ratechange播放速率发生变化。
seeked跳帧(seek)操作完成。
seeking跳帧(seek)操作开始。
stalled用户代理(user agent)正在尝试获取媒体数据,但数据意外未出现。
suspend媒体数据加载已暂停。
loadeddatamedia 中的首帧已经完成加载。
timeupdatecurrentTime 属性指定的时间发生变化。
volumechange音量发生变化。
waiting由于暂时缺少数据,播放已停止。
play播放已开始。
playing由于缺乏数据而暂停或延迟后,播放准备开始。
pause播放已暂停。
volume音量发生变化。
fullscreen触发全屏事件

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/popover/index.html b/cn/src/ranui/popover/index.html new file mode 100644 index 0000000000..f502ede22f --- /dev/null +++ b/cn/src/ranui/popover/index.html @@ -0,0 +1,74 @@ + + + + + + Popover 气泡卡片 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Popover 气泡卡片

点击/鼠标移入元素,弹出气泡式的卡片浮层。

代码演示

popover
this is content
xml
<r-popover>
+    <r-button>popover</r-button>
+    <r-content>
+      <div>this is content</div>
+    </r-content>
+</r-popover>

属性

trigger

触发方式

  • hover
hover
hover
xml
<r-popover trigger="hover">
+    <r-button>hover</r-button>
+    <r-content>
+      <div>hover</div>
+    </r-content>
+  </r-popover>
  • click
click
click
xml
<r-popover trigger="click">
+    <r-button>click</r-button>
+    <r-content>
+      <div>click</div>
+    </r-content>
+  </r-popover>

placement

展示的位置

  • bottom
bottom
bottom
xml
<r-popover trigger="hover" placement="bottom">
+    <r-button>bottom</r-button>
+    <r-content>
+      <div>bottom</div>
+    </r-content>
+  </r-popover>
  • top
top
top
xml
<r-popover trigger="hover" placement="top">
+    <r-button>top</r-button>
+    <r-content>
+      <div>top</div>
+    </r-content>
+  </r-popover>

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/preview/index.html b/cn/src/ranui/preview/index.html new file mode 100644 index 0000000000..2f984af919 --- /dev/null +++ b/cn/src/ranui/preview/index.html @@ -0,0 +1,68 @@ + + + + + + preview 文件预览 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

preview 文件预览

支持docxpptxpdf,xlsx文件的预览

代码演示

choose file to preview
html
<r-preview id="preview"></r-preview>
+<r-button type="primary" onclick="uploadFile()">choose file to preview</r-button>
+
+<script>
+  const uploadFile = () => {
+    const preview = document.getElementById('preview');
+    const uploadFile = document.createElement('input');
+    uploadFile.setAttribute('type', 'file');
+    uploadFile.click();
+    uploadFile.onchange = (e) => {
+      const { files = [] } = uploadFile;
+      if (files.length > 0) {
+        preview.setAttribute('src', '');
+        const file = files[0];
+        const url = URL.createObjectURL(file);
+        preview.setAttribute('src', url);
+      }
+    };
+  };
+</script>

属性

资源地址src

src 地址即可打开弹窗,没有src就不展示

html
<r-preview src=""></r-preview>

是否可关闭closeable

closeable 默认为 true ,可以关闭,设置成 false 时, 表示不可关闭,将不会展示右上角的关闭按钮

html
<r-preview closeable="false"></r-preview>

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/progress/index.html b/cn/src/ranui/progress/index.html new file mode 100644 index 0000000000..fc19942dbc --- /dev/null +++ b/cn/src/ranui/progress/index.html @@ -0,0 +1,55 @@ + + + + + + progress 进度条 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

progress 进度条

可交互的进度条

代码演示

xml
<r-progress type="drag" ></r-progress>

属性

总进度total

设置进度条总进度,允许百分比和数字。

html
<r-progress percent="30" total="1000"></r-progress>
+<r-progress percent="70" total="100"></r-progress>
+<r-progress percent="10%" total="100%"></r-progress>

当前进度percent

设置进度条的当前进度,可以设置百分比和数字,percent不能超过total。如果不设置total,默认total100%也就是1

html
<r-progress type="primary" percent="30%"></r-progress>
+<r-progress type="primary" percent="40%"></r-progress>
+<r-progress type="primary" percent="100%"></r-progress>

进度条的点dot

默认展示,设置成false可隐藏

html
<r-progress type="drag" percent="30%" dot="false"></r-progress>
+<r-progress type="primary" percent="40%" dot="true"></r-progress>
+<r-progress type="primary" percent="40%"></r-progress>

类型type

  • primary: 默认的进度条,不设置type属性是默认
  • drag: 可拖动,可点击的进度条(拖动需要设置dottrue
html
<r-progress type="drag" percent="30%"></r-progress> <r-progress type="primary" percent="40%"></r-progress>

方法

change

percenttotal属性发生变化时,触发change事件。

属性说明类型
value当前进度string|number
percent当前进度string|number
total总进度string|number

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/radar/index.html b/cn/src/ranui/radar/index.html new file mode 100644 index 0000000000..4ccf2d9a94 --- /dev/null +++ b/cn/src/ranui/radar/index.html @@ -0,0 +1,103 @@ + + + + + + Radar 雷达图 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Radar 雷达图

以二维形式综合对比多组数据的差异,常用于比较 2 组或更多组数据集

代码演示

xml
<r-radar
+    abilitys='[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

属性

需要展示的数据abilitys

一个数组对象,对象中属性如下

参数说明类型
abilityName展示的属性名称必传参数string
scoreRate展示维度的数值,最大 100必传参数number
backgroundColor属性名称的背景颜色可选参数string
fontSize属性名称的字体大小可选参数number
fontFamily属性名称的字体可选参数string
fontColor属性名称的字体颜色可选参数string
xml
<r-radar
+    abilitys='[{"abilityName":"生命","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

多边形颜色colorPolygon

xml
<r-radar
+    colorPolygon="green"
+    abilitys='[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

顶点连线颜色colorLine

xml
<r-radar
+    colorLine="blue"
+    abilitys='[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+></r-radar>

数据渲染处的颜色fillColor

xml
<r-radar
+    fillColor="red"
+    abilitys='[{"abilityName":"生命","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

数据渲染处线和点的颜色strokeColor

xml
<r-radar
+    strokeColor="blue"
+    abilitys='[{"abilityName":"生命","scoreRate":"10"},{"abilityName":"攻击","scoreRate":"90"},{"abilityName":"防御","scoreRate":"20"},{"abilityName":"元素精通","scoreRate":"50"},{"abilityName":"暴击率","scoreRate":"80"},{"abilityName":"暴击伤害","scoreRate":"50"}]'
+    style="width:300px;height:300px;display: block;"
+>
+</r-radar>

使用的例子数据

由于HTMlattribute只能获取string。因此需要传入的数据需要是json字符串格式,然后通过JSON.parse解析程数组对象,如果JSON格式有误,则无法解析。

json
[
+  {
+    "abilityName": "生命",
+    "scoreRate": "10",
+    "backgroundColor": "red",
+    "fontSize": "30",
+    "fontColor": "blue"
+  },
+  {
+    "abilityName": "攻击",
+    "scoreRate": "90"
+  },
+  {
+    "abilityName": "防御",
+    "scoreRate": "20"
+  },
+  {
+    "abilityName": "元素精通",
+    "scoreRate": "50"
+  },
+  {
+    "abilityName": "暴击率",
+    "scoreRate": "80"
+  },
+  {
+    "abilityName": "暴击伤害",
+    "scoreRate": "50"
+  }
+]

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/select/index.html b/cn/src/ranui/select/index.html new file mode 100644 index 0000000000..81f8884792 --- /dev/null +++ b/cn/src/ranui/select/index.html @@ -0,0 +1,90 @@ + + + + + + Select 下拉选择框 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Select 下拉选择框

一个普通的下拉选择器。

代码演示

MikeTomLucy
xml
<r-select style="width: 120px; height: 40px" defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

属性

默认值defaultValue

设置当前选中的值

MikeTomLucy
xml
    <r-select style="width: 120px; height: 40px" defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

不可用状态disabled

添加 disabled 属性即可让选择框处于不可用状态,同时样式也会改变。

MikeTomLucy
xml
    <r-select style="width: 120px; height: 40px" disabled defaultValue="185">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

类型type

可以设置文本类型,不要边框和下拉图标

MikeTomLucy
xml
<r-select
+      style="width: 120px; height: 40px"
+      type="text"
+      defaultValue="185"
+    >
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

下拉框的展示方向placement

下拉框展示方向默认往下,设置成top可以往上

MikeTomLucy
xml
<r-select
+      style="width: 120px; height: 40px"
+      type="text"
+      defaultValue="185"
+      placement="top"
+    >
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

带搜索框 showSearch

展开后可对选项进行搜索

MikeTomLucy
xml
<r-select style="width: 120px; height: 40px" showSearch>
+<r-option value="185">Mike</r-option>
+<r-option value="186">Tom</r-option>
+<r-option value="187">Lucy</r-option>
+</r-select>

下拉框挂载元素的 idgetPopupContainerId

下拉框默认挂载到document.body上,可以传入元素的id,挂载到指定的元素内 `

MikeTomLucy
xml
<r-select getPopupContainerId="elementid">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

下拉框的 class 名dropdownclass

如果需要自定义下拉框的样式,可以传入一个 class 名,进行自定义

trigger

select 组件触发的方法。默认 click ,点击触发。可以设置hover,或者click,hover,表示点击和鼠标移入都触发。

如果设置成 none,就不会触发。

MikeTomLucy
xml
<r-select getPopupContainerId="elementid" trigger="click,hover">
+      <r-option value="185">Mike</r-option>
+      <r-option value="186">Tom</r-option>
+      <r-option value="187">Lucy</r-option>
+    </r-select>

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/skeleton/index.html b/cn/src/ranui/skeleton/index.html new file mode 100644 index 0000000000..2fd222df3a --- /dev/null +++ b/cn/src/ranui/skeleton/index.html @@ -0,0 +1,49 @@ + + + + + + skeleton 骨架屏 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

skeleton 骨架屏

在需要等待加载内容的位置提供一个占位图形组合。

代码演示

骨架长度跟随父级元素的长度

xml
<r-skeleton ></r-skeleton>

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/tab/index.html b/cn/src/ranui/tab/index.html new file mode 100644 index 0000000000..ee7466bcc3 --- /dev/null +++ b/cn/src/ranui/tab/index.html @@ -0,0 +1,91 @@ + + + + + + Tab 图标 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Tab 图标

标签页,其中r-tab需要和r-tabs搭配使用

代码演示

111112222233333
xml
<r-tabs >
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

属性

标签名label

r-tab的属性,设置标签的名称

111112222233333
xml
<r-tabs >
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

活跃标签active,标签的唯一标识ranKey

  • ranKeyr-tab的属性,用于确定同一个r-tabsr-tab的唯一值。如果ranKey没有设置,默认等于index。(不采用key字段是防止key是保留字段)
  • activer-tabs的属性,用于设置活跃的标签。active等于key的标签为活跃标签。
  1. 没有设置key
111112222233333
xml
 <r-tabs active="1">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+ </r-tabs>
  1. 设置key
1111122222333334
xml
    <r-tabs active="c">
+      <r-tab label="tab1" ranKey="a">11111</r-tab>
+      <r-tab label="tab2" ranKey="b">22222</r-tab>
+      <r-tab label="tab3" ranKey="c">33333</r-tab>
+      <r-tab label="tab4">4</r-tab>
+    </r-tabs>

不可操作disabled

设置不可点击的标签

1111122222333334
xml
    <r-tabs active="c">
+      <r-tab label="tab1" ranKey="a" disabled>11111</r-tab>
+      <r-tab label="tab2" ranKey="b">22222</r-tab>
+      <r-tab label="tab3" ranKey="c">33333</r-tab>
+      <r-tab label="tab4">4</r-tab>
+    </r-tabs>

类型type

r-tabs属性,设置标签页的种类。如果不设置,默认为flat

  1. flat
111112222233333
xml
<r-tabs type="flat">
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>
  1. line
111112222233333
xml
<r-tabs type="line">
+      <r-tab label="tab1">11111</r-tab>
+      <r-tab label="tab2">22222</r-tab>
+      <r-tab label="tab3">33333</r-tab>
+</r-tabs>

对齐方式align

设置标签的对齐方式,默认align="start"

  1. start
111112222233333
xml
 <r-tabs type="line" align="start">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
  1. center
111112222233333
xml
 <r-tabs type="line" align="center">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>
  1. end
111112222233333
xml
 <r-tabs type="line" align="end">
+        <r-tab label="tab1">11111</r-tab>
+        <r-tab label="tab2">22222</r-tab>
+        <r-tab label="tab3">33333</r-tab>
+    </r-tabs>

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranui/tabs/index.html b/cn/src/ranui/tabs/index.html new file mode 100644 index 0000000000..c8cf547c8d --- /dev/null +++ b/cn/src/ranui/tabs/index.html @@ -0,0 +1,73 @@ + + + + + + Tab | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Tab

代码展示

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2">tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

属性

名称label

每个r-tab需要指定一个名称label,用于显示标签头。

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2">tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

禁用disabled

每个r-tab可以指定disabled属性,用来禁用该标签页。

tab1tab2tab3
xml
<r-tabs>
+    <r-tab label="tab1">tab1</r-tab>
+    <r-tab label="tab2" disabled>tab2</r-tab>
+    <r-tab label="tab3">tab3</r-tab>
+</r-tabs>

标识key,active

每个r-tab需要指定一个标识key,没有会默认以序列号为key

active作用在r-tabs上,可以指定切换到具体标签页,也可以指定初始值。

tab1tab2tab3
html
<r-tabs active="B">
+  <r-tab label="tab1" r-key="A">tab1</r-tab>
+  <r-tab label="tab2" r-key="B">tab2</r-tab>
+  <r-tab label="tab3" r-key="C">tab3</r-tab>
+</r-tabs>

图标icon

每个r-tab可以指定icon,配合label实现图标加文字的效果。

tab1tab2tab3
html
<r-tabs>
+  <r-tab label="home" icon="home">tab1</r-tab>
+  <r-tab label="message" icon="message">tab2</r-tab>
+  <r-tab label="user" icon="user">tab3</r-tab>
+</r-tabs>

也可以单独指定icon,不使用label。但这种情况必须要设置iconsize,否则无法判断icon的大小

tab1tab2tab3
html
<r-tabs>
+  <r-tab icon="home" iconSize="22">tab1</r-tab>
+  <r-tab icon="message" iconSize="22">tab2</r-tab>
+  <r-tab icon="user" iconSize="22">tab3</r-tab>
+</r-tabs>

风格type

风格有 text,clean,

对齐align

事件event

onchange

切换完成时触发。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/binaryTree/index.html b/cn/src/ranuts/binaryTree/index.html new file mode 100644 index 0000000000..7a0acbf515 --- /dev/null +++ b/cn/src/ranuts/binaryTree/index.html @@ -0,0 +1,50 @@ + + + + + + 二叉树的定义 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

二叉树的定义

在计算机科学中,二叉树(Binary tree)是每个节点最多只有两个分支(即不存在分支度大于 2 的节点)的树结构。通常分支被称作“左子树”或“右子树”。二叉树的分支具有左右次序,不能随意颠倒[1]。。

二叉树的性质

  • 在二叉树的第 i 层上最多有 2^(i-1)个结点(i>=1)
  • 深度为 h 的二叉树,最多有 2^h-1 个结点,最少有 h 个结点(h>=1)
  • 包含 n 个结点的二叉树的高度至少为(log2n)+1
  • 非空的二叉树,分支度为 0 的总数为 n0,分支度为 2 的总数为 n2,则 n0=n2+1
  • 二叉树的总结点数 n = n1 + n2 + n0
  • 总连线数等于总节点数减一(B = n - 1)
  • 总连线数等于分支度为 2 的节点的两倍加上分支度为 1 的节点(B = n2 _ 2 + n1 _ 1)

二叉树的类型

满二叉树

一棵深度为 k 且有 2k-1 个节点的二叉树称为满二叉树。 除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树[2]

完全二叉树

一棵深度为 k 的有 n 个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为 i(1≤i≤n)的结点与满二叉树中编号为 i 的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。

二叉搜索树

二叉搜索树(BST)又称二叉查找树或二叉排序树。它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

平衡二叉树

平衡二叉树(AVL)一定是二叉搜索树,且左子树和右子树的高度差的绝对值不超过 1。 平衡二叉树

B 树

B 树属于多叉树又名平衡多路查找树(查找路径不只两个)

B+树

B+树是 B 树的变体,也是一种多路搜索树。

B*树

B* 树是 B+树的变体,在 B+树的非根和非叶子结点再增加指向兄弟的指针;B* 树定义了非叶子结点关键字个数至少为(2/3)M,即块的最低使用率为 2/3(代替 B+树的 1/2)。B 树分配新结点的概率比 B+树要低,空间使用率更高;

红黑树

红黑树是一种平衡二叉查找树的变体,它的左右子树高差有可能大于 1,所以红黑树不是严格意义上的平衡二叉树(AVL),但对它进行平衡的代价较低, 其平均统计性能要强于 AVL 。

遍历

前序遍历

后序遍历

中序遍历

层序遍历

常见算法题

镜像二叉树

重建二叉树

二叉树深度

二叉树节点总数

判断二叉树子结构

输入两棵二叉树 A 和 B,判断 B 是不是 A 的子结构。(ps:约定空树不是任意一个树的子结构)

参考文档

  1. 维基百科二叉树
  2. 百度百科满二叉树

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/bundler/index.html b/cn/src/ranuts/bundler/index.html new file mode 100644 index 0000000000..bb7293e622 --- /dev/null +++ b/cn/src/ranuts/bundler/index.html @@ -0,0 +1,59 @@ + + + + + + Bundler | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

Bundler

Bundler的使用: 传入 options 参数

function build(options: Options):Promise<Build> {
+  const bundle = new Bundle({
+    entry: options.input
+  });
+  return bundle.build().then(() => {
+    return {
+      generate: () => bundle.render()
+    };
+  });
+}

架构图

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/file/appendFile.html b/cn/src/ranuts/file/appendFile.html new file mode 100644 index 0000000000..f29edbc3c5 --- /dev/null +++ b/cn/src/ranuts/file/appendFile.html @@ -0,0 +1,49 @@ + + + + + + AppendFile | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

AppendFile

追加一些数据到文件内

API

Return

  • Promise
参数说明类型描述
success是否追加成功booleantrue 追加成功 false 追加失败
data追加失败的原因,添加成功后的文件内容any

Options

参数说明类型默认值
path文件路径,需要追加的文件stringundefined
content需要追加的内容string

Example

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/file/fileInfo.html b/cn/src/ranuts/file/fileInfo.html new file mode 100644 index 0000000000..adad4c5b64 --- /dev/null +++ b/cn/src/ranuts/file/fileInfo.html @@ -0,0 +1,49 @@ + + + + + + QueryFileInfo | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

QueryFileInfo

查询一个文件的详细信息,一般用于区分文件还是目录,可以通过返回的 data 来判断(data.isDirectory())

API

Return

  • Promise
参数说明类型描述
success是否检查成功booleantrue 成功 false 失败
data文件的信息,或者错误的原因Stats

Options

参数说明类型默认值
path文件路径,需要检查的文件路径stringundefined

Example

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/file/readDir.html b/cn/src/ranuts/file/readDir.html new file mode 100644 index 0000000000..3fea0f4d00 --- /dev/null +++ b/cn/src/ranuts/file/readDir.html @@ -0,0 +1,49 @@ + + + + + + ReadDir | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

ReadDir

读一个目录下的所有文件

API

Return

  • Promise
参数说明类型描述
result目录下所有文件的数组array传入函数的参数

Options

参数说明类型默认值
optionsobject传入函数的参数
dirPath文件的路径Stats

Example

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/file/readFile.html b/cn/src/ranuts/file/readFile.html new file mode 100644 index 0000000000..65d02828ed --- /dev/null +++ b/cn/src/ranuts/file/readFile.html @@ -0,0 +1,49 @@ + + + + + + ReadFile | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

ReadFile

观察一个文件是否改变

API

Return

  • Promise
参数说明类型描述
data文件是否被改变booleantrue 文件改变 false 文件没变

Options

参数说明类型默认值
path文件路径,需要监听的文件stringundefined
interval监听文件改变的时间,单位毫秒。number20

Example

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/file/watchFile.html b/cn/src/ranuts/file/watchFile.html new file mode 100644 index 0000000000..1312d56204 --- /dev/null +++ b/cn/src/ranuts/file/watchFile.html @@ -0,0 +1,49 @@ + + + + + + WatchFile | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

WatchFile

观察一个文件是否改变

API

Return

  • Promise
参数说明类型描述
status文件是否被改变booleantrue 文件改变 false 文件没变

Options

参数说明类型默认值
path文件路径,需要监听的文件stringundefined
interval监听文件改变的时间,单位毫秒。number20

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/file/writeFile.html b/cn/src/ranuts/file/writeFile.html new file mode 100644 index 0000000000..9c7785b497 --- /dev/null +++ b/cn/src/ranuts/file/writeFile.html @@ -0,0 +1,49 @@ + + + + + + WriteFile | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

WriteFile

将内容写入文件

API

Return

  • Promise
参数说明类型描述
success是否写入成功booleantrue 成功 false 失败
data写入失败的原因,添加成功后的文件内容和文件路径any

Options

参数说明类型默认值
path文件路径,需要追加的文件stringundefined
content需要追加的内容string

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/index.html b/cn/src/ranuts/index.html new file mode 100644 index 0000000000..d6375001fe --- /dev/null +++ b/cn/src/ranuts/index.html @@ -0,0 +1,49 @@ + + + + + + ranuts overview | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

ranuts overview

方法列表

方法说明详细内容
writeFile写入文件writeFile
readFile读取文件readFile
readDir读取目录,获取目录下所有文件的名字readDir
watchFile观察文件的内容是否发生变化watchFile
queryFileInfo查询文件信息queryFileInfo
filterObj过滤对象filterObj
EventEmitter发布订阅类EventEmitter
str2Xml字符串转成xmlstr2Xml
getMime根据文件格式后缀获取 mime typegetMime
getCookie获取指定 cookie 的值writeFile
formatJson格式化 JSONformatJson

TOTP

2FA Verification
Generate
code:
expires:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/mimeType/mimeType.html b/cn/src/ranuts/mimeType/mimeType.html new file mode 100644 index 0000000000..dc660d868c --- /dev/null +++ b/cn/src/ranuts/mimeType/mimeType.html @@ -0,0 +1,56 @@ + + + + + + getMime | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

getMime

传入文件格式后缀,返回mime type

API

Return

参数说明类型
string返回mime typestring

Options

参数说明类型默认值
ext文件后缀格式string

Example

js
import { getMime } from 'ranuts';
+
+const result = getMime('.pptx');
+console.log(result);
+// 'application/vnd.openxmlformats-officedocument.presentationml.presentation
+const res = getMime('.txt');
+console.log(result);
+// text/plain

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/mode/subscribe.html b/cn/src/ranuts/mode/subscribe.html new file mode 100644 index 0000000000..115078068e --- /dev/null +++ b/cn/src/ranuts/mode/subscribe.html @@ -0,0 +1,80 @@ + + + + + + EventEmitter | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

EventEmitter

发布订阅的类

Class

Methods

方法参数说明默认值
on订阅事件订阅事件,传入参数事件名,回调函数
once订阅一次事件,传入参数事件名,回调函数订阅一次事件,触发一次后不再会触发
off取消订阅事件,传入参数事件名,回调函数取消订阅事件
emit触发事件,需要事件名触发事件

Example

js
import { Subscribe } from 'ranuts';
+
+const subscribe = new Subscribe();
+
+// 订阅事件1
+subscribe.on('event', () => {
+  console.log(1);
+});
+// 订阅事件2
+subscribe.on('event', () => {
+  console.log(2);
+});
+// 订阅事件3
+const eventThree = () => {
+  console.log(3);
+};
+subscribe.on('event', eventThree);
+// 订阅事件4,需要传递参数
+subscribe.on('event', (num) => {
+  console.log(num);
+});
+// 触发事件,同时传参数
+subscribe.emit('event', 4);
+// console.log(1) console.log(2) console.log(3) console.log(4)
+
+// 取消事件三
+subscribe.off('event', eventThree);
+
+// 订阅一次,触发一次自动取消
+subscribe.once('other', () => {
+  console.log(5);
+});

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/utils/convertImageToBase64.html b/cn/src/ranuts/utils/convertImageToBase64.html new file mode 100644 index 0000000000..4342c2af63 --- /dev/null +++ b/cn/src/ranuts/utils/convertImageToBase64.html @@ -0,0 +1,53 @@ + + + + + + convertImageToBase64 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

convertImageToBase64

图片转base64

API

Return

参数说明类型
success是否转换成功boolean
data转换成功后的值string,ArrayBuffer , null
message转换成功或失败的原因string

Options

参数说明类型默认值
file传入的文件File

Example

js
import { convertImageToBase64 } from 'ranuts';
+
+convertImageToBase64(file).then((res) => {
+  console.log(result);
+});

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/utils/filterObj.html b/cn/src/ranuts/utils/filterObj.html new file mode 100644 index 0000000000..5b8b2b4cec --- /dev/null +++ b/cn/src/ranuts/utils/filterObj.html @@ -0,0 +1,61 @@ + + + + + + filterObj | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

filterObj

过滤对象的属性,去除对象中在 list 数组里面有的属性,返回一个新对象,一般是用于去除空字符和 null

API

Return

参数说明类型
Object返回的一个对象Object

Options

参数说明类型默认值
obj需要过滤的对象object
list需要过滤的熟悉数组array

Example

js
import { filterObj } from 'ranuts';
+
+const obj = {
+  name: 'chaxus',
+  age: 10,
+  address: 'spark',
+};
+
+const result = filterObj(obj, ['name', 'address']);
+
+console.log(result);
+
+// { age:10 }

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/utils/formatJson.html b/cn/src/ranuts/utils/formatJson.html new file mode 100644 index 0000000000..a918a8ec6f --- /dev/null +++ b/cn/src/ranuts/utils/formatJson.html @@ -0,0 +1,58 @@ + + + + + + formatJson | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

formatJson

传入一个 JSON 或者 JSON 的字符串,添加空格和换行进行返回一个格式化的 JSON 字符串

API

Return

参数说明类型
string返回的一个对象Object

Options

参数说明类型默认值
json需要格式化的 JSON 对象object,string
callback错误回调,可选function

Example

js
import { formatJson } from 'ranuts';
+
+const json = {
+  name: 'chaxus',
+  age: 3,
+};
+
+const result = formatJson(json);
+
+console.log(result);

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/utils/getCookie.html b/cn/src/ranuts/utils/getCookie.html new file mode 100644 index 0000000000..c35714ece7 --- /dev/null +++ b/cn/src/ranuts/utils/getCookie.html @@ -0,0 +1,55 @@ + + + + + + getCookie | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

getCookie

传入字符串,获取指定名字的 cookie 的值

API

Return

参数说明类型
sting返回的一个指定名称的 cookie 的值string

Options

参数说明类型默认值
name指定获取 cookie 的名称的值object

Example

js
import { getCookie } from 'ranuts';
+
+const result = getCookie('name');
+
+console.log(result);
+
+// ''

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/utils/ocr.html b/cn/src/ranuts/utils/ocr.html new file mode 100644 index 0000000000..8fd4612807 --- /dev/null +++ b/cn/src/ranuts/utils/ocr.html @@ -0,0 +1,63 @@ + + + + + + OCR | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

OCR

传入图片和对应的语言类型,返回图片中的文本。

API

Return

参数说明类型
success是否解析成功boolean
data解析成功后的对象obj
message解析成功或失败的原因string

Options

参数说明类型默认值
images图片的数组,支持urlbase64Array<string>
language指定生成文本的语言,具体参数见lang-codestring
langPath使用的时候需要能访问cdn.jsdelivr.net,会下载对应的语言包,如果无法访问,也可以将语言包放在本地,传入对应的 目录 路径string可选参数,默认走网络下载

Example

js
import { ocr } from 'ranuts';
+
+const images = ['https://chaxus.github.io/ran/ocr/eng.png'];
+const languages = 'eng';
+ocr({ images, language }).then((res) => {
+  console.log(res.data?.[0].data.text);
+});
+// Mild Splendour of the various-vested Night!
+// Mother of wildly-working visions! hail
+// I watch thy gliding, while with watery light
+// Thy weak eye glimmers through a fleecy veil;
+// And when thou lovest thy pale orb to shroud
+// Behind the gather’d blackness lost on high;
+// And when thou dartest from the wind-rent cloud
+// Thy placid lightning o’er the awaken’d sky.

Lang Code

Lang CodeLanguage
afrAfrikaans
amhAmharic
araArabic
asmAssamese
azeAzerbaijani
aze_cyrlAzerbaijani - Cyrillic
belBelarusian
benBengali
bodTibetan
bosBosnian
bulBulgarian
catCatalan; Valencian
cebCebuano
cesCzech
chi_simChinese - Simplified
chi_traChinese - Traditional
chrCherokee
cymWelsh
danDanish
deuGerman
dzoDzongkha
ellGreek, Modern (1453-)
engEnglish
enmEnglish, Middle (1100-1500)
epoEsperanto
estEstonian
eusBasque
fasPersian
finFinnish
fraFrench
frkGerman Fraktur
frmFrench, Middle (ca. 1400-1600)
gleIrish
glgGalician
grcGreek, Ancient (-1453)
gujGujarati
hatHaitian; Haitian Creole
hebHebrew
hinHindi
hrvCroatian
hunHungarian
ikuInuktitut
indIndonesian
islIcelandic
itaItalian
ita_oldItalian - Old
javJavanese
jpnJapanese
kanKannada
katGeorgian
kat_oldGeorgian - Old
kazKazakh
khmCentral Khmer
kirKirghiz; Kyrgyz
korKorean
kurKurdish
laoLao
latLatin
lavLatvian
litLithuanian
malMalayalam
marMarathi
mkdMacedonian
mltMaltese
msaMalay
myaBurmese
nepNepali
nldDutch; Flemish
norNorwegian
oriOriya
panPanjabi; Punjabi
polPolish
porPortuguese
pusPushto; Pashto
ronRomanian; Moldavian; Moldovan
rusRussian
sanSanskrit
sinSinhala; Sinhalese
slkSlovak
slvSlovenian
spaSpanish; Castilian
spa_oldSpanish; Castilian - Old
sqiAlbanian
srpSerbian
srp_latnSerbian - Latin
swaSwahili
sweSwedish
syrSyriac
tamTamil
telTelugu
tgkTajik
tglTagalog
thaThai
tirTigrinya
turTurkish
uigUighur; Uyghur
ukrUkrainian
urdUrdu
uzbUzbek
uzb_cyrlUzbek - Cyrillic
vieVietnamese
yidYiddish

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/utils/str2xml.html b/cn/src/ranuts/utils/str2xml.html new file mode 100644 index 0000000000..8277356d7a --- /dev/null +++ b/cn/src/ranuts/utils/str2xml.html @@ -0,0 +1,56 @@ + + + + + + str2Xml | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

str2Xml

传入字符串,转成xml

API

Return

参数说明类型
HTMLElement返回一个HTMLElementHTMLElement

Options

参数说明类型默认值
xmlStr传入的参数string
format设置需要转换的格式,默认text/xmlDOMParserSupportedType

Example

比如在做图标库的时候,我们需要动态导入目录下的所有icon。这时候导入的是字符串,但字符串无法添加到xml中。 因此我们需要将字符串转换成xml,然后就可以将它加入到xml中。

js
import { str2Xml } from 'ranuts';
+
+// import 'assets/*.svg'
+const svg = `<svg t="1667483498347" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8544" width="200" height="200"><path d="M858.5 763.6c-18.9-44.8-46.1-85-80.6-119.5-34.5-34.5-74.7-61.6-119.5-80.6-0.4-0.2-0.8-0.3-1.2-0.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-0.4 0.2-0.8 0.3-1.2 0.5-44.8 18.9-85 46-119.5 80.6-34.5 34.5-61.6 74.7-80.6 119.5C146.9 807.5 137 854 136 901.8c-0.1 4.5 3.5 8.2 8 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c0.1 4.4 3.6 7.8 8 7.8h60c4.5 0 8.1-3.7 8-8.2-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z" p-id="8545"></path></svg>`;
+
+const icon = str2Xml(svg, 'image/svg+xml');
+
+document.body.appendChild(icon);

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/cn/src/ranuts/utils/task.html b/cn/src/ranuts/utils/task.html new file mode 100644 index 0000000000..249a0e3a7c --- /dev/null +++ b/cn/src/ranuts/utils/task.html @@ -0,0 +1,55 @@ + + + + + + 统计执行时间 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

统计执行时间

有的时候,我们需要统计一个函数的执行时间,用于分析性能。因此封装了startTasktaskEnd函数。同时介绍其他三种统计方法

  1. new Date().getTime(),
  2. console.time()console.timeEnd(),
  3. performance.now()

一.startTask,taskEnd

1.startTask

任务开始之前执行

Return

参数说明类型
taskId任务标识unique symbol

2.taskEnd

任务结束的时候执行,需要传入startTask返回的任务标识

Options

参数说明类型默认值
taskId任务标识unique symbol 无默认值,参数必传,否则无法识别是哪个任务

Return

参数说明类型
timetask执行的时间number

3.使用例子

js
const taskId = startTask();
+
+// do something
+
+const time = taskEnd(taskId);
+
+console.log('task 执行花费的时间', time);

二.new Date().getTime()

new Date().getTime() 返回一个数值,表示从 1970 年 1 月 1 日 0 时 0 分 0 秒(UTC,即协调世界时)距离该日期对象所代表时间的毫秒数。用来计算 JS 执行时间会有两个问题:

  1. 某些情况下,毫秒级精度可能不够。
  2. new Date() 解析的时间在不同浏览器,或者不同设备上可能并不一致。MDN 说明

    由于浏览器之间的差异与不一致性,强烈不推荐使用 Date 构造函数来解析日期字符串 (或使用与其等价的 Date.parse)。对 RFC 2822 格式的日期仅有约定俗成的支持。对 ISO 8601 格式的支持中,仅有日期的串 (例如 "1970-01-01") 会被处理为 UTC 而不是本地时间,与其他格式的串的处理不同。

三.console.time(), console.timeEnd()

启动一个计时器来跟踪某一个操作的占用时长。每一个计时器必须拥有唯一的名字,页面中最多能同时运行 10,000 个计时器。当以此计时器名字为参数调用 console.timeEnd() 时,浏览器将以毫秒为单位,输出对应计时器所经过的时间。比起new Date().getTime(),统计时间更加精确,可以统计到 0.001 毫秒(比如:0.134ms)

四.performance.now()

performance.now()返回的时间精度最高可达微秒级,且不会受到系统时间的影响(系统时钟可能会被手动调整或被 NTP 等软件篡改)。另外,performance.timing.navigationStart + performance.now() 约等于 Date.now()。因此对于统计 JS 执行耗时方面,更推荐使用performance.now()

注意:为了提供对定时攻击和指纹的保护,performance.now() 的精度可能会根据浏览器的设置而被舍弃。 在 Firefox 中,privacy.reduceTimerPrecision 偏好是默认启用的,默认值为 1ms。可以启用 privacy.resistFingerprinting 这将精度改为 100ms 或privacy.resistFingerprinting.reduceTimerPrecision.microseconds 的值,以较大者为准。

Released under the MIT License.

+ + + + \ No newline at end of file diff --git "a/cn/src/types/TS\347\261\273\345\236\213.html" "b/cn/src/types/TS\347\261\273\345\236\213.html" new file mode 100644 index 0000000000..6bc8b30dda --- /dev/null +++ "b/cn/src/types/TS\347\261\273\345\236\213.html" @@ -0,0 +1,96 @@ + + + + + + TypeScript 类型系统中的类型 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

TypeScript 类型系统中的类型

  1. 基本类型: number、boolean、string、object、bigint、symbol、undefined、null
  2. 复合类型: class、Array、元组(Tuple)、接口(Interface)、枚举(Enum)
  3. 特殊的类型:void、never、any、unknown

Tuple

元组(Tuple)就是元素个数和类型固定的数组类型:

ts
type Tuple = [number, string];

Interface

接口(Interface)可以描述函数、对象、构造器的结构:

  • 对象
ts
interface IPerson {
+  name: string;
+  age: number;
+}
+
+class Person implements IPerson {
+  name: string;
+  age: number;
+}
+
+const obj: IPerson = {
+  name: 'name',
+  age: 18,
+};
  • 函数
ts
interface SayHello {
+  (name: string): string;
+}
+
+const func: SayHello = (name: string) => {
+  return 'hello,' + name;
+};
  • 构造器
ts
interface PersonConstructor {
+  new (name: string, age: number): IPerson;
+}
+
+function createPerson(ctor: PersonConstructor): IPerson {
+  return new ctor('name', 18);
+}

对象类型、class 类型在 TypeScript 里也叫做索引类型,也就是索引了多个元素的类型的意思。对象可以动态添加属性,如果不知道会有什么属性,可以用可索引签名:

ts
interface IPerson {
+  [prop: string]: string | number;
+}
+const obj: IPerson = {};
+obj.name = 'name';
+obj.age = 18;

Enum

枚举(Enum)是一系列值的复合:

ts
enum Transpiler {
+  Babel = 'babel',
+  Postcss = 'postcss',
+  Terser = 'terser',
+  Prettier = 'prettier',
+  TypeScriptCompiler = 'tsc',
+}
+
+const transpiler = Transpiler.TypeScriptCompiler;

此外,TypeScript 还支持字面量类型,也就是类似 1111、'aaaa'、{ a: 1} 这种值也可以做为类型。

其中,字符串的字面量类型有两种,一种是普通的字符串字面量,比如 'aaa',另一种是模版字面量,比如 aaa${string},它的意思是以 aaa 开头,后面是任意 string 的字符串字面量类型。

所以想要约束以某个字符串开头的字符串字面量类型时可以这样写:

ts
function func(str: `#${string}`) {}
+
+func('aaa'); // error
+
+func('#aaa'); // true

void

代表空,可以是 undefined 或 never。

never

代表不可达,比如函数抛异常的时候,返回值就是 never。

any

是任意类型,任何类型都可以赋值给它,它也可以赋值给任何类型(除了 never)。

unknown

是未知类型,任何类型都可以赋值给它,但是它不可以赋值给别的类型。

类型的装饰

除了描述类型的结构外,TypeScript 的类型系统还支持描述类型的属性,比如是否可选,是否只读等:

ts
interface IPerson {
+  readonly name: string;
+  age?: number;
+}
+
+type tuple = [string, number?];

Last updated:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git "a/cn/src/types/\346\250\241\345\274\217\345\214\271\351\205\215.html" "b/cn/src/types/\346\250\241\345\274\217\345\214\271\351\205\215.html" new file mode 100644 index 0000000000..83689ec853 --- /dev/null +++ "b/cn/src/types/\346\250\241\345\274\217\345\214\271\351\205\215.html" @@ -0,0 +1,59 @@ + + + + + + 模式匹配 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

模式匹配

Typescript 的类型也同样可以做模式匹配。

比如这样一个 Promise 类型:

ts
type p = Promise<'value'>;

我们想提取 value 的类型,可以这样做:

ts
type GetPromiseValue<T> = T extends Promise<infer value> ? value : never;

通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取的,通过 infer 声明一个局部变量 Value 来保存,如果匹配,就返回匹配到的 Value,否则就返回 never 代表没匹配到。

ts
type result = GetPromiseValue<Promise<'name'>>; // name

数组类型

数组类型想提取第一个元素的类型怎么做呢?

ts
type arr = [1, 2, 3];

用它来匹配一个模式类型,提取第一个元素的类型到通过 infer 声明的局部变量里返回。

ts
type GetArrayFirstItem<T extends unknown[]> = T extends [infer value, ...unknown[]] ? value : never;

类型参数 Arr 通过 extends 约束为只能是数组类型,数组元素是 unknown 也就是可以是任何值。

any 和 unknown 的区别: any 和 unknown 都代表任意类型,但是 unknown 只能接收任意类型的值,而 any 除了可以接收任意类型的值,也可以赋值给任意类型(除了 never)。类型体操中经常用 unknown 接受和匹配任何类型,而很少把任何类型赋值给某个类型变量。

对 Arr 做模式匹配,把我们要提取的第一个元素的类型放到通过 infer 声明的 First 局部变量里,后面的元素可以是任何类型,用 unknown 接收,然后把局部变量 First 返回。

当类型参数 Arr 为 [1,2,3] 时:

ts
type result = GetArrayFirstItem<[1, 2, 3]>; // 1

当类型参数 Arr 为 [] 时:

ts
type result = GetArrayFirstItem<[]>; // never

可以提取第一个元素,当然也可以提取最后一个元素,修改下模式类型就行:

ts
type GetArrayLastItem<T extends unknown[]> = T extends [...unknown[],inter L] ? L : never

我们分别取了首尾元素,当然也可以取剩余的数组,比如取去掉了最后一个元素的数组:

ts
type Pop<T extends unknown[]> = T extends [] ? [] : T extends [...infer Rest, unknown] ? Rest : never;

如果是空数组,就直接返回,否则匹配剩余的元素,放到 infer 声明的局部变量 Rest 里,返回 Rest。

当类型参数 Arr 为 [1,2,3] 时:

ts
type Result = Pop<[1, 2, 3]>; // [1,2]

当类型参数 Arr 为 [] 时:

ts
type Result = Pop<[]>; // []

同理可得 ShiftArr 的实现:

ts
type Shift<T extends unknown[]> = T extends [] ? [] : T extends [unknown, ...infer Rest] ? Rest : never;

字符串类型也同样可以做模式匹配,匹配一个模式字符串,把需要提取的部分放到 infer 声明的局部变量里。

判断字符串是否以某个前缀开头,也是通过模式匹配:

ts
type StartWidth<S extends string, P extends string> = S extends `${P}${string}` ? true : false;

需要声明字符串 Str、匹配的前缀 Prefix 两个类型参数,它们都是 string。

用 Str 去匹配一个模式类型,模式类型的前缀是 Prefix,后面是任意的 string,如果匹配返回 true,否则返回 false。

字符串可以匹配一个模式类型,提取想要的部分,自然也可以用这些再构成一个新的类型。

比如实现字符串替换:

ts
type Replace<S extends string, F extends string, T extends string> = S extends `${infer P}${F}${infer L}`
+  ? `${P}${T}${L}`
+  : S;

声明要替换的字符串 Str、待替换的字符串 From、替换成的字符串 3 个类型参数,通过 extends 约束为都是 string 类型。

用 Str 去匹配模式串,模式串由 From 和之前之后的字符串构成,把之前之后的字符串放到通过 infer 声明的局部变量 Prefix、Suffix 里。

用 Prefix、Suffix 加上替换到的字符串 To 构造成新的字符串类型返回。

Trim

能够匹配和替换字符串,那也就能实现去掉空白字符的 Trim:

不过因为我们不知道有多少个空白字符,所以只能一个个匹配和去掉,需要递归。

先实现 TrimRight:

ts
type TrimRight<S extends string> = S extends `${infer Rest}${' ' | '\n' | '\t'}` ? TrimRight<Rest> : S;

类型参数 Str 是要 Trim 的字符串。

如果 Str 匹配字符串 + 空白字符 (空格、换行、制表符),那就把字符串放到 infer 声明的局部变量 Rest 里。

把 Rest 作为类型参数递归 TrimRight,直到不匹配,这时的类型参数 Str 就是处理结果。

同理可得 TrimLeft:

ts
type TrimLeft<S extends string> = S extends `${' ' | '\n' | '\t'}${infer Rest}` ? TrimLeft<Rest> : S;

TrimRight 和 TrimLeft 结合就是 Trim:

ts
type Trim<S extends string> = TrimLeft<TrimRight<S>>;

函数

函数同样也可以做类型匹配,比如提取参数、返回值的类型。

GetParameters

函数类型可以通过模式匹配来提取参数的类型:

ts
type GetParameters<T extends Function> = T extends (...args: infer A) => unknown ? A : never;

类型参数 Func 是要匹配的函数类型,通过 extends 约束为 Function。

Func 和模式类型做匹配,参数类型放到用 infer 声明的局部变量 Args 里,返回值可以是任何类型,用 unknown。

返回提取到的参数类型 Args。

GetReturnType

ts
type GetReturnType<T extends Function> = T extends (...args: unknown[]) => infer R ? R : never;

Func 和模式类型做匹配,提取返回值到通过 infer 声明的局部变量 ReturnType 里返回。

参数类型可以是任意类型,也就是 any[](注意,这里不能用 unknown,这里的解释涉及到参数的逆变性质,具体原因逆变那一节会解释)。

GetThisParameterType

方法里可以调用 this,用对象.方法名的方式调用的时候,this 就指向那个对象。

但是方法也可以用 call 或者 apply 调用,call 调用的时候,this 就变了,但这里却没有被检查出来 this 指向的错误。

这里的 this 类型同样也可以通过模式匹配提取出来:

ts
type GetThisParameterType<T extends Function> = T extends (this: infer H, ...args: unknown[]) => unknown ? H : unknown;

构造器

构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

同样,我们也可以通过模式匹配提取构造器的参数和返回值的类型:

GetInstanceType

构造器类型可以用 interface 声明,使用 new(): xx 的语法。

ts
interface Person {
+  name: string;
+}
+
+interface PersonConstructor {
+  new (name: string): Person;
+}

这里的 PersonConstructor 返回的是 Person 类型的实例对象,这个也可以通过模式匹配取出来。

ts
type GetInstanceType<C extends new (...args: unknown[]) => unknown> = C extends new (...args: unknown[]) => infer T
+  ? T
+  : unknown;

Last updated:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git "a/cn/src/types/\347\261\273\345\236\213\350\277\220\347\256\227.html" "b/cn/src/types/\347\261\273\345\236\213\350\277\220\347\256\227.html" new file mode 100644 index 0000000000..89b42fe52b --- /dev/null +++ "b/cn/src/types/\347\261\273\345\236\213\350\277\220\347\256\227.html" @@ -0,0 +1,75 @@ + + + + + + TypeScript 类型系统中的类型运算 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

TypeScript 类型系统中的类型运算

条件:extends ? :

TypeScript 里的条件判断是 extends ? :,叫做条件类型(Conditional Type)比如:

ts
type isTwo<T> = T extends 2 ? true : false;
+
+type res = isTwo<1>; // true
+type res2 = isTwo<2>; // false

这种类型也叫做高级类型。

高级类型的特点是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

推导:infer

如何提取类型的一部分呢?答案是 infer。

比如提取元组类型的第一个元素:

ts
type FirstTupleItem<Tuple extends unknown[]> = Tuple extends [infer T, ...inter R] ? T : never;
+
+type res = First<[1,2,3]> // 1

注意,第一个 extends 不是条件,条件类型是 extends ? :,这里的 extends 是约束的意思,也就是约束类型参数只能是数组类型。

因为不知道数组元素的具体类型,所以用 unknown。

联合:|

联合类型(Union)类似 js 里的或运算符 |,但是作用于类型,代表类型可以是几个类型之一。

ts
type Union = 1 | 2 | 3;

交叉:&

交叉类型(Intersection)类似 js 中的与运算符 &,但是作用于类型,代表对类型做合并。

ts
type ObjType = { a: number } & { c: boolean };

注意,同一类型可以合并,不同的类型没法合并,会被舍弃:

ts
type res = 'a' & 2; // never

映射类型

对象、class 在 TypeScript 对应的类型是索引类型(Index Type),那么如何对索引类型作修改呢?

答案是映射类型。

ts
type MapType<T> = {
+  [key in keyof T]?: T[key];
+};

keyof T 是查询索引类型中所有的索引,叫做索引查询。

T[Key] 是取索引类型某个索引的值,叫做索引访问。

in 是用于遍历联合类型的运算符。

比如我们把一个索引类型的值变成 3 个元素的数组:

ts
type MapToArray<T> = {
+  [key in keyof T]: [T[key], T[key], T[key]];
+};
+
+// example:
+
+type res = MapToArray<{ a: 1; b: 2 }>;
+// type res = {
+//     a:[1,1,1]
+//     b:[2,2,2]
+// }

映射类型就相当于把一个集合映射到另一个集合,这是它名字的由来。

除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。

ts
type MapTypeFixKey<T> = {
+  [key in keyof T as `${key & string}${key & string}${key & string}`]: [T[key], T[key], T[key]];
+};
+// example:
+
+type res = MapToArray<{ a: 1; b: 2 }>;
+// type res = {
+//     aaa:[1,1,1]
+//     bbb:[2,2,2]
+// }

这里的 & string 可能大家会迷惑,解释一下:

因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是 string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型会把同一类型做合并,不同类型舍弃。

因为 js 处理对象比较多,所以索引类型的映射比较重要。

Last updated:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git "a/cn/src/types/\351\253\230\347\272\247\347\261\273\345\236\213.html" "b/cn/src/types/\351\253\230\347\272\247\347\261\273\345\236\213.html" new file mode 100644 index 0000000000..9c7b23c5d8 --- /dev/null +++ "b/cn/src/types/\351\253\230\347\272\247\347\261\273\345\236\213.html" @@ -0,0 +1,49 @@ + + + + + + TypeScript 内置的高级类型 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

TypeScript 内置的高级类型

Parameters

Parameters 用于提取函数类型的参数类型。

ReturnType

ReturnType 用于提取函数类型的返回值类型。

ConstructorParameters

构造器类型和函数类型的区别就是可以被 new。

Parameters 用于提取函数参数的类型,而 ConstructorParameters 用于提取构造器参数的类型。

InstanceType

提取了构造器参数的类型,自然也可以提取构造器返回值的类型,就是 InstanceType。

ThisParameterType

OmitThisParameter

Partial

Required

Readonly

Pick

Record

Exclude

Extract

Omit

Awaited

NonNullable

Uppercase

Lowercase

Capitalize

Uncapitalize

总结

比如用模式匹配可以实现:Parameters、ReturnType、ConstructorParameters、InstanceType、ThisParameterType。

用模式匹配 + 重新构造可以实现:OmitThisParameter

用重新构造可以实现:Partial、Required、Readonly、Pick、Record

用模式匹配 + 递归可以实现: Awaited

用联合类型在分布式条件类型的特性可以实现: Exclude

此外还有 NonNullable 和四个编译器内部实现的类型:Uppercase、Lowercase、Capitalize、Uncapitalize。

Last updated:

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000..a9e9a99b33 Binary files /dev/null and b/favicon.ico differ diff --git a/hashmap.json b/hashmap.json new file mode 100644 index 0000000000..cae89570c9 --- /dev/null +++ b/hashmap.json @@ -0,0 +1 @@ +{"cn_index.md":"Ci9FwTgY","cn_src_article_astparse_tokenizer.md":"CPQ5Q4qA","cn_src_article_babel.md":"Bv2kTzb8","cn_src_article_bundle.md":"B9WVe3Nd","cn_src_article_designmode.md":"Bo9IXX6C","cn_src_article_docpreview.md":"CnTJNdd8","cn_src_article_functionalprogramming.md":"XTLIxuFQ","cn_src_article_imagemin.md":"Eq8Sl5vS","cn_src_article_javascript_domload.md":"CX-aoztf","cn_src_article_sort_bubble_index.md":"B1Kqdm5g","cn_src_article_sort_bucket_index.md":"CkcMkruf","cn_src_article_sort_count_index.md":"DO0Khq-9","cn_src_article_sort_heap_index.md":"DUTc1Z1Q","cn_src_article_sort_index.md":"B1KerO70","cn_src_article_sort_insert_index.md":"D8ChYRq6","cn_src_article_sort_merge_index.md":"CywmRCFf","cn_src_article_sort_quick_index.md":"BMawD0Bg","cn_src_article_sort_radix_index.md":"DIqt5q7a","cn_src_article_sort_select_index.md":"CwruXsFa","cn_src_article_sort_shell_index.md":"BjqTtSjT","cn_src_article_systemdesign.md":"DXbjsTs-","cn_src_article_typescript_calculate.md":"C_dGguN1","cn_src_article_typescript_index.md":"dV9VtsjJ","cn_src_article_typescript_pattern.md":"Cyn9ELOY","cn_src_article_typescript_reconstruction.md":"Bc8ysEy2","cn_src_article_typescript_recursion.md":"DiOAHp83","cn_src_article_typescript_uniontype.md":"BTONe5Yt","cn_src_article_video.md":"Dw4RU8dr","cn_src_article_visual.md":"CDvSxrkl","cn_src_note_centos.md":"BW5LCWPK","cn_src_note_docker.md":"C0hJL26s","cn_src_note_libreoffice2wasm.md":"CiwyBD9N","cn_src_note_ubuntu.md":"C-U8psaC","cn_src_ranui_button_index.md":"BKYzspkY","cn_src_ranui_checkbox_index.md":"tqLDdmuX","cn_src_ranui_icon_index.md":"IS0pJHCF","cn_src_ranui_image_index.md":"Dw0AwGab","cn_src_ranui_index.md":"tB1QXtFw","cn_src_ranui_input_index.md":"Ztjdnx-y","cn_src_ranui_loading_index.md":"C0qf8XCk","cn_src_ranui_math_index.md":"CaRU3RpB","cn_src_ranui_message_index.md":"DDK6JB1T","cn_src_ranui_modal_index.md":"Bl-bNDpJ","cn_src_ranui_player_index.md":"BPeeUAmI","cn_src_ranui_popover_index.md":"CVPFx-rd","cn_src_ranui_preview_index.md":"DI-R6RxP","cn_src_ranui_progress_index.md":"B8zrCakA","cn_src_ranui_radar_index.md":"K6NP370R","cn_src_ranui_select_index.md":"T7hcvhSo","cn_src_ranui_skeleton_index.md":"D7wv1w9E","cn_src_ranui_tab_index.md":"D8xqztOz","cn_src_ranui_tabs_index.md":"jexz00Wi","cn_src_ranuts_binarytree_index.md":"1nqizYW3","cn_src_ranuts_bundler_index.md":"dO9RE_ls","cn_src_ranuts_file_appendfile.md":"CXY4tbQl","cn_src_ranuts_file_fileinfo.md":"BovJRTqz","cn_src_ranuts_file_readdir.md":"C8qesA-s","cn_src_ranuts_file_readfile.md":"-SzOLham","cn_src_ranuts_file_watchfile.md":"C2RD93Hf","cn_src_ranuts_file_writefile.md":"CbYE9IAV","cn_src_ranuts_index.md":"DE29xbkU","cn_src_ranuts_mimetype_mimetype.md":"B8my7NSy","cn_src_ranuts_mode_subscribe.md":"DStPx3te","cn_src_ranuts_utils_convertimagetobase64.md":"BpukE7kU","cn_src_ranuts_utils_filterobj.md":"Be8VuZ1x","cn_src_ranuts_utils_formatjson.md":"DWRR6vH4","cn_src_ranuts_utils_getcookie.md":"BFqNwYBM","cn_src_ranuts_utils_ocr.md":"aSDPltJI","cn_src_ranuts_utils_str2xml.md":"CxozQof2","cn_src_ranuts_utils_task.md":"Nv89-z_1","cn_src_types_ts类型.md":"BoPQGs5F","cn_src_types_模式匹配.md":"CfyGKgqa","cn_src_types_类型运算.md":"y4F25ckq","cn_src_types_高级类型.md":"CjvcQW1d","index.md":"DiiJHNTD","src_article_astparse_tokenizer.md":"BdbSK8yK","src_article_babel.md":"C7cpU5Uf","src_article_bundle.md":"CFyB1OVU","src_article_designmode.md":"-Ql_1mMt","src_article_functionalprogramming.md":"DSVAXKFw","src_article_imagemin.md":"DTz2O7QV","src_article_javascript_domload.md":"C2Dqx2X1","src_article_sort_bubble_index.md":"fAtbvQz_","src_article_sort_bucket_index.md":"BhE2wW4O","src_article_sort_count_index.md":"DvPhDLiz","src_article_sort_heap_index.md":"qYkik3kq","src_article_sort_index.md":"DZ3i3D2R","src_article_sort_insert_index.md":"CPhWGrRG","src_article_sort_merge_index.md":"DCFZpDV3","src_article_sort_quick_index.md":"tGhXdyib","src_article_sort_radix_index.md":"hf3O4ngq","src_article_sort_select_index.md":"BmIakYmF","src_article_sort_shell_index.md":"BefIpHA6","src_article_typescript_calculate.md":"CaDt8dND","src_article_typescript_index.md":"SzJeg7Vl","src_article_typescript_pattern.md":"Cl1kek3_","src_article_typescript_reconstruction.md":"CPqflY5B","src_article_typescript_recursion.md":"Vf30DC2k","src_article_typescript_uniontype.md":"BIrMmR2O","src_ranui_button_index.md":"DhP8rReR","src_ranui_checkbox_index.md":"Bp6CThLb","src_ranui_icon_index.md":"mkEISxvO","src_ranui_image_index.md":"DfDYyZub","src_ranui_index.md":"D31LFnZe","src_ranui_input_index.md":"DkK2wQig","src_ranui_loading_index.md":"CLsqr9az","src_ranui_math_index.md":"C-RA_nK7","src_ranui_message_index.md":"DywEIh7C","src_ranui_modal_index.md":"B-J1TEAz","src_ranui_player_index.md":"D9OUB_JI","src_ranui_popover_index.md":"BCOhVsiF","src_ranui_preview_index.md":"Ky1AiWNQ","src_ranui_progress_index.md":"Cm1y50UG","src_ranui_radar_index.md":"B7mPxzli","src_ranui_select_index.md":"BX7CAaZq","src_ranui_skeleton_index.md":"CLg9OTaj","src_ranui_tab_index.md":"DJ6wHDqA","src_ranui_tabs_index.md":"DL4ch3vN","src_ranuts_binarytree_index.md":"1xzpa2sH","src_ranuts_bundler_index.md":"BP7Aetz6","src_ranuts_file_appendfile.md":"D4zWKXVA","src_ranuts_file_fileinfo.md":"CfdtUkZ-","src_ranuts_file_readdir.md":"D1R8FXwd","src_ranuts_file_readfile.md":"CVYw5eyB","src_ranuts_file_watchfile.md":"DibbbSlI","src_ranuts_file_writefile.md":"C3kB2EaG","src_ranuts_index.md":"BsUA76mi","src_ranuts_mimetype_mimetype.md":"BMZ_GsW2","src_ranuts_mode_subscribe.md":"Bx_Pjw6l","src_ranuts_utils_convertimagetobase64.md":"BbdsPOTo","src_ranuts_utils_filterobj.md":"CQHmrklO","src_ranuts_utils_formatjson.md":"s6iqMas3","src_ranuts_utils_getcookie.md":"CsUkD7RK","src_ranuts_utils_ocr.md":"B-CI4poJ","src_ranuts_utils_str2xml.md":"DUodO238","src_ranuts_utils_task.md":"hnoz85-k","src_types_ts类型.md":"D-rRgmPu","src_types_模式匹配.md":"Dp3VrzqR","src_types_类型运算.md":"4OgLnpMn","src_types_高级类型.md":"C4cnhLAB"} diff --git a/hls/5_1701577744714/5.key b/hls/5_1701577744714/5.key new file mode 100644 index 0000000000..7d0d880c2c --- /dev/null +++ b/hls/5_1701577744714/5.key @@ -0,0 +1 @@ +7J5FlfYN3s377LCDp936ik6rPGjsNGSE4FquHZittVM= \ No newline at end of file diff --git a/hls/5_1701577744714/5.m3u8 b/hls/5_1701577744714/5.m3u8 new file mode 100644 index 0000000000..d73d9618de --- /dev/null +++ b/hls/5_1701577744714/5.m3u8 @@ -0,0 +1,20 @@ +#EXTM3U +#EXT-X-VERSION:3 +#EXT-X-TARGETDURATION:10 +#EXT-X-MEDIA-SEQUENCE:0 +#EXT-X-KEY:METHOD=AES-128,URI="5.key",IV=0x00000000000000000000000000000000 +#EXTINF:10.380622, +5_00000.ts +#EXTINF:10.380622, +5_00001.ts +#EXTINF:10.380622, +5_00002.ts +#EXTINF:10.380622, +5_00003.ts +#EXTINF:6.560556, +5_00004.ts +#EXTINF:1.619378, +5_00005.ts +#EXTINF:5.024189, +5_00006.ts +#EXT-X-ENDLIST diff --git a/hls/5_1701577744714/5_00000.ts b/hls/5_1701577744714/5_00000.ts new file mode 100644 index 0000000000..97ca63748a Binary files /dev/null and b/hls/5_1701577744714/5_00000.ts differ diff --git a/hls/5_1701577744714/5_00001.ts b/hls/5_1701577744714/5_00001.ts new file mode 100644 index 0000000000..d8dbf8a53e Binary files /dev/null and b/hls/5_1701577744714/5_00001.ts differ diff --git a/hls/5_1701577744714/5_00002.ts b/hls/5_1701577744714/5_00002.ts new file mode 100644 index 0000000000..2faaf32715 Binary files /dev/null and b/hls/5_1701577744714/5_00002.ts differ diff --git a/hls/5_1701577744714/5_00003.ts b/hls/5_1701577744714/5_00003.ts new file mode 100644 index 0000000000..5bea7afef4 Binary files /dev/null and b/hls/5_1701577744714/5_00003.ts differ diff --git a/hls/5_1701577744714/5_00004.ts b/hls/5_1701577744714/5_00004.ts new file mode 100644 index 0000000000..b0e8eb1f03 Binary files /dev/null and b/hls/5_1701577744714/5_00004.ts differ diff --git a/hls/5_1701577744714/5_00005.ts b/hls/5_1701577744714/5_00005.ts new file mode 100644 index 0000000000..ffca3fe158 Binary files /dev/null and b/hls/5_1701577744714/5_00005.ts differ diff --git a/hls/5_1701577744714/5_00006.ts b/hls/5_1701577744714/5_00006.ts new file mode 100644 index 0000000000..1e0cd440db Binary files /dev/null and b/hls/5_1701577744714/5_00006.ts differ diff --git a/hls/5_1701577771368/5.key b/hls/5_1701577771368/5.key new file mode 100644 index 0000000000..ce9cf4eab0 --- /dev/null +++ b/hls/5_1701577771368/5.key @@ -0,0 +1 @@ +Yrn8D93LzuskhQnfzID5K9Uk3tYt1DezYCXnJ6QQV44= \ No newline at end of file diff --git a/hls/5_1701577771368/5.m3u8 b/hls/5_1701577771368/5.m3u8 new file mode 100644 index 0000000000..d73d9618de --- /dev/null +++ b/hls/5_1701577771368/5.m3u8 @@ -0,0 +1,20 @@ +#EXTM3U +#EXT-X-VERSION:3 +#EXT-X-TARGETDURATION:10 +#EXT-X-MEDIA-SEQUENCE:0 +#EXT-X-KEY:METHOD=AES-128,URI="5.key",IV=0x00000000000000000000000000000000 +#EXTINF:10.380622, +5_00000.ts +#EXTINF:10.380622, +5_00001.ts +#EXTINF:10.380622, +5_00002.ts +#EXTINF:10.380622, +5_00003.ts +#EXTINF:6.560556, +5_00004.ts +#EXTINF:1.619378, +5_00005.ts +#EXTINF:5.024189, +5_00006.ts +#EXT-X-ENDLIST diff --git a/hls/5_1701577771368/5_00000.ts b/hls/5_1701577771368/5_00000.ts new file mode 100644 index 0000000000..4668cb52d8 Binary files /dev/null and b/hls/5_1701577771368/5_00000.ts differ diff --git a/hls/5_1701577771368/5_00001.ts b/hls/5_1701577771368/5_00001.ts new file mode 100644 index 0000000000..ccd9bd6f10 Binary files /dev/null and b/hls/5_1701577771368/5_00001.ts differ diff --git a/hls/5_1701577771368/5_00002.ts b/hls/5_1701577771368/5_00002.ts new file mode 100644 index 0000000000..e2330d2deb Binary files /dev/null and b/hls/5_1701577771368/5_00002.ts differ diff --git a/hls/5_1701577771368/5_00003.ts b/hls/5_1701577771368/5_00003.ts new file mode 100644 index 0000000000..e8052a7289 Binary files /dev/null and b/hls/5_1701577771368/5_00003.ts differ diff --git a/hls/5_1701577771368/5_00004.ts b/hls/5_1701577771368/5_00004.ts new file mode 100644 index 0000000000..aa6190d22e Binary files /dev/null and b/hls/5_1701577771368/5_00004.ts differ diff --git a/hls/5_1701577771368/5_00005.ts b/hls/5_1701577771368/5_00005.ts new file mode 100644 index 0000000000..bb08759b14 Binary files /dev/null and b/hls/5_1701577771368/5_00005.ts differ diff --git a/hls/5_1701577771368/5_00006.ts b/hls/5_1701577771368/5_00006.ts new file mode 100644 index 0000000000..5044beef60 Binary files /dev/null and b/hls/5_1701577771368/5_00006.ts differ diff --git a/hls/example.m3u8 b/hls/example.m3u8 new file mode 100644 index 0000000000..bb75509b9f --- /dev/null +++ b/hls/example.m3u8 @@ -0,0 +1,5 @@ +#EXTM3U +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1000000,CODECS="mp4a.40.2,avc1.64001f",RESOLUTION=1280x720,NAME="720" +5_1701577771368/5.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=2,BANDWIDTH=50000,CODECS="mp4a.40.5,avc1.42000d",RESOLUTION=320x184,NAME="320" +5_1701577744714/5.m3u8 diff --git a/home.svg b/home.svg new file mode 100644 index 0000000000..2857b17a7f --- /dev/null +++ b/home.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000..9202b635fa Binary files /dev/null and b/icon.png differ diff --git a/icon_144.png b/icon_144.png new file mode 100644 index 0000000000..d3a56cda07 Binary files /dev/null and b/icon_144.png differ diff --git a/icon_168.png b/icon_168.png new file mode 100644 index 0000000000..a88bd5c3c1 Binary files /dev/null and b/icon_168.png differ diff --git a/icon_192.png b/icon_192.png new file mode 100644 index 0000000000..674c10ef06 Binary files /dev/null and b/icon_192.png differ diff --git a/icon_48.png b/icon_48.png new file mode 100644 index 0000000000..cad207f289 Binary files /dev/null and b/icon_48.png differ diff --git a/icon_72.png b/icon_72.png new file mode 100644 index 0000000000..04575ca142 Binary files /dev/null and b/icon_72.png differ diff --git a/icon_96.png b/icon_96.png new file mode 100644 index 0000000000..286b4a1cfa Binary files /dev/null and b/icon_96.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000000..508585a053 --- /dev/null +++ b/index.html @@ -0,0 +1,49 @@ + + + + + + Home | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Skip to content

ran

A Troupe of little vagrants of the world , leave your footprints in my words .

logo

Released under the MIT License.

+ + + + \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000000..5c21b73d65 --- /dev/null +++ b/manifest.json @@ -0,0 +1,58 @@ +{ + "name": "ran", + "short_name": "ran", + "id":"/ran/", + "start_url": "/ran/", + "display": "standalone", + "background_color": "#fff", + "description": "A Troupe of little vagrants of the world, leave your footprints in my words .", + "icons": [ + { + "src": "/ran/icon_48.png", + "sizes": "48x48", + "type": "image/png" + }, + { + "src": "/ran/icon_72.png", + "sizes": "72x72", + "type": "image/png" + }, + { + "src": "/ran/icon_96.png", + "sizes": "96x96", + "type": "image/png" + }, + { + "src": "/ran/icon_144.png", + "sizes": "144x144", + "type": "image/png" + }, + { + "src": "/ran/icon_168.png", + "sizes": "168x168", + "type": "image/png" + }, + { + "src": "/ran/icon_192.png", + "sizes": "192x192", + "type": "image/png" + } + ], + "screenshots" : [ + { + "src": "/ran/screenshots_2560x1440.jpg", + "sizes": "2560x1440", + "type": "image/jpg", + "form_factor": "wide", + "label": "Home screen of Awesome App" + }, + { + "src": "/ran/screenshots_748x1340.jpg", + "sizes": "748x1340", + "type": "image/jpg", + "form_factor": "narrow", + "label": "List of Awesome Resources available in Awesome App" + } + ] + } + \ No newline at end of file diff --git a/ocr/chi_sim.png b/ocr/chi_sim.png new file mode 100644 index 0000000000..184d067124 Binary files /dev/null and b/ocr/chi_sim.png differ diff --git a/ocr/eng.png b/ocr/eng.png new file mode 100644 index 0000000000..2e1ddbe381 Binary files /dev/null and b/ocr/eng.png differ diff --git a/pagefind/fragment/en_106ee7d.pf_fragment b/pagefind/fragment/en_106ee7d.pf_fragment new file mode 100644 index 0000000000..eb831f591b Binary files /dev/null and b/pagefind/fragment/en_106ee7d.pf_fragment differ diff --git a/pagefind/fragment/en_12451bd.pf_fragment b/pagefind/fragment/en_12451bd.pf_fragment new file mode 100644 index 0000000000..fe417504db Binary files /dev/null and b/pagefind/fragment/en_12451bd.pf_fragment differ diff --git a/pagefind/fragment/en_13157a1.pf_fragment b/pagefind/fragment/en_13157a1.pf_fragment new file mode 100644 index 0000000000..4bc26c5188 Binary files /dev/null and b/pagefind/fragment/en_13157a1.pf_fragment differ diff --git a/pagefind/fragment/en_19ba7e6.pf_fragment b/pagefind/fragment/en_19ba7e6.pf_fragment new file mode 100644 index 0000000000..fc43ac0a25 Binary files /dev/null and b/pagefind/fragment/en_19ba7e6.pf_fragment differ diff --git a/pagefind/fragment/en_1d9d6e5.pf_fragment b/pagefind/fragment/en_1d9d6e5.pf_fragment new file mode 100644 index 0000000000..fb0190ec4e Binary files /dev/null and b/pagefind/fragment/en_1d9d6e5.pf_fragment differ diff --git a/pagefind/fragment/en_1f67d37.pf_fragment b/pagefind/fragment/en_1f67d37.pf_fragment new file mode 100644 index 0000000000..b333c9387a Binary files /dev/null and b/pagefind/fragment/en_1f67d37.pf_fragment differ diff --git a/pagefind/fragment/en_1fd6515.pf_fragment b/pagefind/fragment/en_1fd6515.pf_fragment new file mode 100644 index 0000000000..22b6186f40 Binary files /dev/null and b/pagefind/fragment/en_1fd6515.pf_fragment differ diff --git a/pagefind/fragment/en_222d98b.pf_fragment b/pagefind/fragment/en_222d98b.pf_fragment new file mode 100644 index 0000000000..81c67696e2 Binary files /dev/null and b/pagefind/fragment/en_222d98b.pf_fragment differ diff --git a/pagefind/fragment/en_229996f.pf_fragment b/pagefind/fragment/en_229996f.pf_fragment new file mode 100644 index 0000000000..be55c96769 Binary files /dev/null and b/pagefind/fragment/en_229996f.pf_fragment differ diff --git a/pagefind/fragment/en_2771bf1.pf_fragment b/pagefind/fragment/en_2771bf1.pf_fragment new file mode 100644 index 0000000000..6c55b0b866 Binary files /dev/null and b/pagefind/fragment/en_2771bf1.pf_fragment differ diff --git a/pagefind/fragment/en_27a0b4a.pf_fragment b/pagefind/fragment/en_27a0b4a.pf_fragment new file mode 100644 index 0000000000..67072a051b Binary files /dev/null and b/pagefind/fragment/en_27a0b4a.pf_fragment differ diff --git a/pagefind/fragment/en_27ced55.pf_fragment b/pagefind/fragment/en_27ced55.pf_fragment new file mode 100644 index 0000000000..94b5631274 Binary files /dev/null and b/pagefind/fragment/en_27ced55.pf_fragment differ diff --git a/pagefind/fragment/en_2ac4367.pf_fragment b/pagefind/fragment/en_2ac4367.pf_fragment new file mode 100644 index 0000000000..674648cf87 Binary files /dev/null and b/pagefind/fragment/en_2ac4367.pf_fragment differ diff --git a/pagefind/fragment/en_33bec34.pf_fragment b/pagefind/fragment/en_33bec34.pf_fragment new file mode 100644 index 0000000000..8e8a0d8bb5 Binary files /dev/null and b/pagefind/fragment/en_33bec34.pf_fragment differ diff --git a/pagefind/fragment/en_346b990.pf_fragment b/pagefind/fragment/en_346b990.pf_fragment new file mode 100644 index 0000000000..6188fed8c9 Binary files /dev/null and b/pagefind/fragment/en_346b990.pf_fragment differ diff --git a/pagefind/fragment/en_349bd7e.pf_fragment b/pagefind/fragment/en_349bd7e.pf_fragment new file mode 100644 index 0000000000..19449093bb Binary files /dev/null and b/pagefind/fragment/en_349bd7e.pf_fragment differ diff --git a/pagefind/fragment/en_39ca4e7.pf_fragment b/pagefind/fragment/en_39ca4e7.pf_fragment new file mode 100644 index 0000000000..75f9694513 Binary files /dev/null and b/pagefind/fragment/en_39ca4e7.pf_fragment differ diff --git a/pagefind/fragment/en_3bf4f84.pf_fragment b/pagefind/fragment/en_3bf4f84.pf_fragment new file mode 100644 index 0000000000..59c988e48b Binary files /dev/null and b/pagefind/fragment/en_3bf4f84.pf_fragment differ diff --git a/pagefind/fragment/en_3f75462.pf_fragment b/pagefind/fragment/en_3f75462.pf_fragment new file mode 100644 index 0000000000..3559e1b43a Binary files /dev/null and b/pagefind/fragment/en_3f75462.pf_fragment differ diff --git a/pagefind/fragment/en_422fcc1.pf_fragment b/pagefind/fragment/en_422fcc1.pf_fragment new file mode 100644 index 0000000000..dad96ecbb3 Binary files /dev/null and b/pagefind/fragment/en_422fcc1.pf_fragment differ diff --git a/pagefind/fragment/en_45b0a69.pf_fragment b/pagefind/fragment/en_45b0a69.pf_fragment new file mode 100644 index 0000000000..72cfc4a2a1 Binary files /dev/null and b/pagefind/fragment/en_45b0a69.pf_fragment differ diff --git a/pagefind/fragment/en_55a7cf9.pf_fragment b/pagefind/fragment/en_55a7cf9.pf_fragment new file mode 100644 index 0000000000..5a1826c4f6 Binary files /dev/null and b/pagefind/fragment/en_55a7cf9.pf_fragment differ diff --git a/pagefind/fragment/en_58cb4c9.pf_fragment b/pagefind/fragment/en_58cb4c9.pf_fragment new file mode 100644 index 0000000000..36983fe078 Binary files /dev/null and b/pagefind/fragment/en_58cb4c9.pf_fragment differ diff --git a/pagefind/fragment/en_58e1be6.pf_fragment b/pagefind/fragment/en_58e1be6.pf_fragment new file mode 100644 index 0000000000..7d7699c6a5 Binary files /dev/null and b/pagefind/fragment/en_58e1be6.pf_fragment differ diff --git a/pagefind/fragment/en_5ff5133.pf_fragment b/pagefind/fragment/en_5ff5133.pf_fragment new file mode 100644 index 0000000000..da44121858 Binary files /dev/null and b/pagefind/fragment/en_5ff5133.pf_fragment differ diff --git a/pagefind/fragment/en_65ccfe9.pf_fragment b/pagefind/fragment/en_65ccfe9.pf_fragment new file mode 100644 index 0000000000..68150f2efb Binary files /dev/null and b/pagefind/fragment/en_65ccfe9.pf_fragment differ diff --git a/pagefind/fragment/en_6a66788.pf_fragment b/pagefind/fragment/en_6a66788.pf_fragment new file mode 100644 index 0000000000..7775f903e7 Binary files /dev/null and b/pagefind/fragment/en_6a66788.pf_fragment differ diff --git a/pagefind/fragment/en_706f2f9.pf_fragment b/pagefind/fragment/en_706f2f9.pf_fragment new file mode 100644 index 0000000000..dfa3627a4f Binary files /dev/null and b/pagefind/fragment/en_706f2f9.pf_fragment differ diff --git a/pagefind/fragment/en_7322c43.pf_fragment b/pagefind/fragment/en_7322c43.pf_fragment new file mode 100644 index 0000000000..bd2065cb88 Binary files /dev/null and b/pagefind/fragment/en_7322c43.pf_fragment differ diff --git a/pagefind/fragment/en_738928a.pf_fragment b/pagefind/fragment/en_738928a.pf_fragment new file mode 100644 index 0000000000..40ab7f837d Binary files /dev/null and b/pagefind/fragment/en_738928a.pf_fragment differ diff --git a/pagefind/fragment/en_7755d1b.pf_fragment b/pagefind/fragment/en_7755d1b.pf_fragment new file mode 100644 index 0000000000..c502b0aff4 Binary files /dev/null and b/pagefind/fragment/en_7755d1b.pf_fragment differ diff --git a/pagefind/fragment/en_7a4eb73.pf_fragment b/pagefind/fragment/en_7a4eb73.pf_fragment new file mode 100644 index 0000000000..298779e6ec Binary files /dev/null and b/pagefind/fragment/en_7a4eb73.pf_fragment differ diff --git a/pagefind/fragment/en_7b5a911.pf_fragment b/pagefind/fragment/en_7b5a911.pf_fragment new file mode 100644 index 0000000000..d05b457e0e Binary files /dev/null and b/pagefind/fragment/en_7b5a911.pf_fragment differ diff --git a/pagefind/fragment/en_919ab78.pf_fragment b/pagefind/fragment/en_919ab78.pf_fragment new file mode 100644 index 0000000000..1ac7b6978c Binary files /dev/null and b/pagefind/fragment/en_919ab78.pf_fragment differ diff --git a/pagefind/fragment/en_91e701d.pf_fragment b/pagefind/fragment/en_91e701d.pf_fragment new file mode 100644 index 0000000000..616d3565c9 Binary files /dev/null and b/pagefind/fragment/en_91e701d.pf_fragment differ diff --git a/pagefind/fragment/en_9573fab.pf_fragment b/pagefind/fragment/en_9573fab.pf_fragment new file mode 100644 index 0000000000..694d2831d9 Binary files /dev/null and b/pagefind/fragment/en_9573fab.pf_fragment differ diff --git a/pagefind/fragment/en_9755f3c.pf_fragment b/pagefind/fragment/en_9755f3c.pf_fragment new file mode 100644 index 0000000000..6bade63498 Binary files /dev/null and b/pagefind/fragment/en_9755f3c.pf_fragment differ diff --git a/pagefind/fragment/en_98546ec.pf_fragment b/pagefind/fragment/en_98546ec.pf_fragment new file mode 100644 index 0000000000..1a5d0330dd Binary files /dev/null and b/pagefind/fragment/en_98546ec.pf_fragment differ diff --git a/pagefind/fragment/en_a034a97.pf_fragment b/pagefind/fragment/en_a034a97.pf_fragment new file mode 100644 index 0000000000..2757b61273 Binary files /dev/null and b/pagefind/fragment/en_a034a97.pf_fragment differ diff --git a/pagefind/fragment/en_a116508.pf_fragment b/pagefind/fragment/en_a116508.pf_fragment new file mode 100644 index 0000000000..bb9cf8a5ed Binary files /dev/null and b/pagefind/fragment/en_a116508.pf_fragment differ diff --git a/pagefind/fragment/en_a3a3739.pf_fragment b/pagefind/fragment/en_a3a3739.pf_fragment new file mode 100644 index 0000000000..fc9c0b9d9d Binary files /dev/null and b/pagefind/fragment/en_a3a3739.pf_fragment differ diff --git a/pagefind/fragment/en_a4a4e1c.pf_fragment b/pagefind/fragment/en_a4a4e1c.pf_fragment new file mode 100644 index 0000000000..e4659fb880 Binary files /dev/null and b/pagefind/fragment/en_a4a4e1c.pf_fragment differ diff --git a/pagefind/fragment/en_a79eb77.pf_fragment b/pagefind/fragment/en_a79eb77.pf_fragment new file mode 100644 index 0000000000..4c9818dd41 Binary files /dev/null and b/pagefind/fragment/en_a79eb77.pf_fragment differ diff --git a/pagefind/fragment/en_a8a649f.pf_fragment b/pagefind/fragment/en_a8a649f.pf_fragment new file mode 100644 index 0000000000..8ac18821fd Binary files /dev/null and b/pagefind/fragment/en_a8a649f.pf_fragment differ diff --git a/pagefind/fragment/en_b0cf238.pf_fragment b/pagefind/fragment/en_b0cf238.pf_fragment new file mode 100644 index 0000000000..5dbc76f047 Binary files /dev/null and b/pagefind/fragment/en_b0cf238.pf_fragment differ diff --git a/pagefind/fragment/en_b1c2dff.pf_fragment b/pagefind/fragment/en_b1c2dff.pf_fragment new file mode 100644 index 0000000000..4207fb8119 Binary files /dev/null and b/pagefind/fragment/en_b1c2dff.pf_fragment differ diff --git a/pagefind/fragment/en_b2b1326.pf_fragment b/pagefind/fragment/en_b2b1326.pf_fragment new file mode 100644 index 0000000000..85cff477aa Binary files /dev/null and b/pagefind/fragment/en_b2b1326.pf_fragment differ diff --git a/pagefind/fragment/en_b46590e.pf_fragment b/pagefind/fragment/en_b46590e.pf_fragment new file mode 100644 index 0000000000..b9a15aa9fa Binary files /dev/null and b/pagefind/fragment/en_b46590e.pf_fragment differ diff --git a/pagefind/fragment/en_b5741b3.pf_fragment b/pagefind/fragment/en_b5741b3.pf_fragment new file mode 100644 index 0000000000..8c227ec6bd Binary files /dev/null and b/pagefind/fragment/en_b5741b3.pf_fragment differ diff --git a/pagefind/fragment/en_b5a7787.pf_fragment b/pagefind/fragment/en_b5a7787.pf_fragment new file mode 100644 index 0000000000..89166133c8 Binary files /dev/null and b/pagefind/fragment/en_b5a7787.pf_fragment differ diff --git a/pagefind/fragment/en_b7a3e23.pf_fragment b/pagefind/fragment/en_b7a3e23.pf_fragment new file mode 100644 index 0000000000..b1e5360f60 Binary files /dev/null and b/pagefind/fragment/en_b7a3e23.pf_fragment differ diff --git a/pagefind/fragment/en_bc653ea.pf_fragment b/pagefind/fragment/en_bc653ea.pf_fragment new file mode 100644 index 0000000000..d246e71a1f Binary files /dev/null and b/pagefind/fragment/en_bc653ea.pf_fragment differ diff --git a/pagefind/fragment/en_c24a847.pf_fragment b/pagefind/fragment/en_c24a847.pf_fragment new file mode 100644 index 0000000000..773fdeb18c Binary files /dev/null and b/pagefind/fragment/en_c24a847.pf_fragment differ diff --git a/pagefind/fragment/en_c2a5686.pf_fragment b/pagefind/fragment/en_c2a5686.pf_fragment new file mode 100644 index 0000000000..4ce4f8af2b Binary files /dev/null and b/pagefind/fragment/en_c2a5686.pf_fragment differ diff --git a/pagefind/fragment/en_c485c6f.pf_fragment b/pagefind/fragment/en_c485c6f.pf_fragment new file mode 100644 index 0000000000..ea8a028bad Binary files /dev/null and b/pagefind/fragment/en_c485c6f.pf_fragment differ diff --git a/pagefind/fragment/en_c8893d7.pf_fragment b/pagefind/fragment/en_c8893d7.pf_fragment new file mode 100644 index 0000000000..dac582af39 Binary files /dev/null and b/pagefind/fragment/en_c8893d7.pf_fragment differ diff --git a/pagefind/fragment/en_cb594e2.pf_fragment b/pagefind/fragment/en_cb594e2.pf_fragment new file mode 100644 index 0000000000..c1a00bdaac Binary files /dev/null and b/pagefind/fragment/en_cb594e2.pf_fragment differ diff --git a/pagefind/fragment/en_dd6246f.pf_fragment b/pagefind/fragment/en_dd6246f.pf_fragment new file mode 100644 index 0000000000..fea22296f8 Binary files /dev/null and b/pagefind/fragment/en_dd6246f.pf_fragment differ diff --git a/pagefind/fragment/en_e2846bf.pf_fragment b/pagefind/fragment/en_e2846bf.pf_fragment new file mode 100644 index 0000000000..9a2b9477f3 Binary files /dev/null and b/pagefind/fragment/en_e2846bf.pf_fragment differ diff --git a/pagefind/fragment/en_e34b39a.pf_fragment b/pagefind/fragment/en_e34b39a.pf_fragment new file mode 100644 index 0000000000..d6a0449462 Binary files /dev/null and b/pagefind/fragment/en_e34b39a.pf_fragment differ diff --git a/pagefind/fragment/en_e8f3a9e.pf_fragment b/pagefind/fragment/en_e8f3a9e.pf_fragment new file mode 100644 index 0000000000..784ec21086 Binary files /dev/null and b/pagefind/fragment/en_e8f3a9e.pf_fragment differ diff --git a/pagefind/fragment/en_ee118c9.pf_fragment b/pagefind/fragment/en_ee118c9.pf_fragment new file mode 100644 index 0000000000..2992d37993 Binary files /dev/null and b/pagefind/fragment/en_ee118c9.pf_fragment differ diff --git a/pagefind/fragment/en_f5a1553.pf_fragment b/pagefind/fragment/en_f5a1553.pf_fragment new file mode 100644 index 0000000000..1d7b341224 Binary files /dev/null and b/pagefind/fragment/en_f5a1553.pf_fragment differ diff --git a/pagefind/fragment/en_fba3fcb.pf_fragment b/pagefind/fragment/en_fba3fcb.pf_fragment new file mode 100644 index 0000000000..99c47eb61c Binary files /dev/null and b/pagefind/fragment/en_fba3fcb.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_0ef213d.pf_fragment b/pagefind/fragment/zh-cn_0ef213d.pf_fragment new file mode 100644 index 0000000000..492e22d820 Binary files /dev/null and b/pagefind/fragment/zh-cn_0ef213d.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_1ec4ddb.pf_fragment b/pagefind/fragment/zh-cn_1ec4ddb.pf_fragment new file mode 100644 index 0000000000..a971411848 Binary files /dev/null and b/pagefind/fragment/zh-cn_1ec4ddb.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_1f33c04.pf_fragment b/pagefind/fragment/zh-cn_1f33c04.pf_fragment new file mode 100644 index 0000000000..7b1707ba23 Binary files /dev/null and b/pagefind/fragment/zh-cn_1f33c04.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_20bbef4.pf_fragment b/pagefind/fragment/zh-cn_20bbef4.pf_fragment new file mode 100644 index 0000000000..945047909f Binary files /dev/null and b/pagefind/fragment/zh-cn_20bbef4.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_32113cf.pf_fragment b/pagefind/fragment/zh-cn_32113cf.pf_fragment new file mode 100644 index 0000000000..c9366e000b Binary files /dev/null and b/pagefind/fragment/zh-cn_32113cf.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_3ad6344.pf_fragment b/pagefind/fragment/zh-cn_3ad6344.pf_fragment new file mode 100644 index 0000000000..c23d615f82 Binary files /dev/null and b/pagefind/fragment/zh-cn_3ad6344.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_3de2e5c.pf_fragment b/pagefind/fragment/zh-cn_3de2e5c.pf_fragment new file mode 100644 index 0000000000..7f88a009ee Binary files /dev/null and b/pagefind/fragment/zh-cn_3de2e5c.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_3e43b1f.pf_fragment b/pagefind/fragment/zh-cn_3e43b1f.pf_fragment new file mode 100644 index 0000000000..d551cbd37f Binary files /dev/null and b/pagefind/fragment/zh-cn_3e43b1f.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_3fb29d3.pf_fragment b/pagefind/fragment/zh-cn_3fb29d3.pf_fragment new file mode 100644 index 0000000000..2c63f02c2e Binary files /dev/null and b/pagefind/fragment/zh-cn_3fb29d3.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_4152685.pf_fragment b/pagefind/fragment/zh-cn_4152685.pf_fragment new file mode 100644 index 0000000000..7932562843 Binary files /dev/null and b/pagefind/fragment/zh-cn_4152685.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_44fa7df.pf_fragment b/pagefind/fragment/zh-cn_44fa7df.pf_fragment new file mode 100644 index 0000000000..e4b9090754 Binary files /dev/null and b/pagefind/fragment/zh-cn_44fa7df.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_489c27d.pf_fragment b/pagefind/fragment/zh-cn_489c27d.pf_fragment new file mode 100644 index 0000000000..1eecc0b414 Binary files /dev/null and b/pagefind/fragment/zh-cn_489c27d.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_50313a9.pf_fragment b/pagefind/fragment/zh-cn_50313a9.pf_fragment new file mode 100644 index 0000000000..1cff5e6370 Binary files /dev/null and b/pagefind/fragment/zh-cn_50313a9.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_5042f4c.pf_fragment b/pagefind/fragment/zh-cn_5042f4c.pf_fragment new file mode 100644 index 0000000000..c97a8f9b60 Binary files /dev/null and b/pagefind/fragment/zh-cn_5042f4c.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_5190b59.pf_fragment b/pagefind/fragment/zh-cn_5190b59.pf_fragment new file mode 100644 index 0000000000..807bb4d8c9 Binary files /dev/null and b/pagefind/fragment/zh-cn_5190b59.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_51dafe6.pf_fragment b/pagefind/fragment/zh-cn_51dafe6.pf_fragment new file mode 100644 index 0000000000..ec9157e83c Binary files /dev/null and b/pagefind/fragment/zh-cn_51dafe6.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_539d75f.pf_fragment b/pagefind/fragment/zh-cn_539d75f.pf_fragment new file mode 100644 index 0000000000..918322c6a3 Binary files /dev/null and b/pagefind/fragment/zh-cn_539d75f.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_542bc65.pf_fragment b/pagefind/fragment/zh-cn_542bc65.pf_fragment new file mode 100644 index 0000000000..cc6b67819d Binary files /dev/null and b/pagefind/fragment/zh-cn_542bc65.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_544fd92.pf_fragment b/pagefind/fragment/zh-cn_544fd92.pf_fragment new file mode 100644 index 0000000000..9f9ca09b67 Binary files /dev/null and b/pagefind/fragment/zh-cn_544fd92.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_58279de.pf_fragment b/pagefind/fragment/zh-cn_58279de.pf_fragment new file mode 100644 index 0000000000..3a1454aa93 Binary files /dev/null and b/pagefind/fragment/zh-cn_58279de.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_59bdbd3.pf_fragment b/pagefind/fragment/zh-cn_59bdbd3.pf_fragment new file mode 100644 index 0000000000..a213622ae9 Binary files /dev/null and b/pagefind/fragment/zh-cn_59bdbd3.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_5bab657.pf_fragment b/pagefind/fragment/zh-cn_5bab657.pf_fragment new file mode 100644 index 0000000000..8b2f4151ab Binary files /dev/null and b/pagefind/fragment/zh-cn_5bab657.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_5bb9206.pf_fragment b/pagefind/fragment/zh-cn_5bb9206.pf_fragment new file mode 100644 index 0000000000..305ce2fbf5 Binary files /dev/null and b/pagefind/fragment/zh-cn_5bb9206.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_5bc7914.pf_fragment b/pagefind/fragment/zh-cn_5bc7914.pf_fragment new file mode 100644 index 0000000000..9ca19d7731 Binary files /dev/null and b/pagefind/fragment/zh-cn_5bc7914.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_5ca356d.pf_fragment b/pagefind/fragment/zh-cn_5ca356d.pf_fragment new file mode 100644 index 0000000000..be85f2200f Binary files /dev/null and b/pagefind/fragment/zh-cn_5ca356d.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_5d1b782.pf_fragment b/pagefind/fragment/zh-cn_5d1b782.pf_fragment new file mode 100644 index 0000000000..c654e52d8f Binary files /dev/null and b/pagefind/fragment/zh-cn_5d1b782.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_5df12ef.pf_fragment b/pagefind/fragment/zh-cn_5df12ef.pf_fragment new file mode 100644 index 0000000000..c42967d95f Binary files /dev/null and b/pagefind/fragment/zh-cn_5df12ef.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_61c329a.pf_fragment b/pagefind/fragment/zh-cn_61c329a.pf_fragment new file mode 100644 index 0000000000..577a1d7325 Binary files /dev/null and b/pagefind/fragment/zh-cn_61c329a.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_622d568.pf_fragment b/pagefind/fragment/zh-cn_622d568.pf_fragment new file mode 100644 index 0000000000..452ebca536 Binary files /dev/null and b/pagefind/fragment/zh-cn_622d568.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_66f42e8.pf_fragment b/pagefind/fragment/zh-cn_66f42e8.pf_fragment new file mode 100644 index 0000000000..8a39e90ed7 Binary files /dev/null and b/pagefind/fragment/zh-cn_66f42e8.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_677ff04.pf_fragment b/pagefind/fragment/zh-cn_677ff04.pf_fragment new file mode 100644 index 0000000000..fe9de90915 Binary files /dev/null and b/pagefind/fragment/zh-cn_677ff04.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_67d6c7a.pf_fragment b/pagefind/fragment/zh-cn_67d6c7a.pf_fragment new file mode 100644 index 0000000000..c59f039950 Binary files /dev/null and b/pagefind/fragment/zh-cn_67d6c7a.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_6ea83e5.pf_fragment b/pagefind/fragment/zh-cn_6ea83e5.pf_fragment new file mode 100644 index 0000000000..cde97a8e13 Binary files /dev/null and b/pagefind/fragment/zh-cn_6ea83e5.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_715eacf.pf_fragment b/pagefind/fragment/zh-cn_715eacf.pf_fragment new file mode 100644 index 0000000000..1decd3f0be Binary files /dev/null and b/pagefind/fragment/zh-cn_715eacf.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_7355cce.pf_fragment b/pagefind/fragment/zh-cn_7355cce.pf_fragment new file mode 100644 index 0000000000..de77c8be16 Binary files /dev/null and b/pagefind/fragment/zh-cn_7355cce.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_75a264c.pf_fragment b/pagefind/fragment/zh-cn_75a264c.pf_fragment new file mode 100644 index 0000000000..f58f666d7d Binary files /dev/null and b/pagefind/fragment/zh-cn_75a264c.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_7d7b75a.pf_fragment b/pagefind/fragment/zh-cn_7d7b75a.pf_fragment new file mode 100644 index 0000000000..dec1d62d16 Binary files /dev/null and b/pagefind/fragment/zh-cn_7d7b75a.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_7e8750b.pf_fragment b/pagefind/fragment/zh-cn_7e8750b.pf_fragment new file mode 100644 index 0000000000..b08cf0d1cf Binary files /dev/null and b/pagefind/fragment/zh-cn_7e8750b.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_87504f6.pf_fragment b/pagefind/fragment/zh-cn_87504f6.pf_fragment new file mode 100644 index 0000000000..bd71ee8f5e Binary files /dev/null and b/pagefind/fragment/zh-cn_87504f6.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_8a3cd5f.pf_fragment b/pagefind/fragment/zh-cn_8a3cd5f.pf_fragment new file mode 100644 index 0000000000..6808a9024c Binary files /dev/null and b/pagefind/fragment/zh-cn_8a3cd5f.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_8df5615.pf_fragment b/pagefind/fragment/zh-cn_8df5615.pf_fragment new file mode 100644 index 0000000000..43df6d0c89 Binary files /dev/null and b/pagefind/fragment/zh-cn_8df5615.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_95fa787.pf_fragment b/pagefind/fragment/zh-cn_95fa787.pf_fragment new file mode 100644 index 0000000000..164a4cb2c3 Binary files /dev/null and b/pagefind/fragment/zh-cn_95fa787.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_9968bf4.pf_fragment b/pagefind/fragment/zh-cn_9968bf4.pf_fragment new file mode 100644 index 0000000000..0b76ae6f81 Binary files /dev/null and b/pagefind/fragment/zh-cn_9968bf4.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_a1e1243.pf_fragment b/pagefind/fragment/zh-cn_a1e1243.pf_fragment new file mode 100644 index 0000000000..ff144a9868 Binary files /dev/null and b/pagefind/fragment/zh-cn_a1e1243.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_a66a688.pf_fragment b/pagefind/fragment/zh-cn_a66a688.pf_fragment new file mode 100644 index 0000000000..a9a0521e16 Binary files /dev/null and b/pagefind/fragment/zh-cn_a66a688.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_a7edffe.pf_fragment b/pagefind/fragment/zh-cn_a7edffe.pf_fragment new file mode 100644 index 0000000000..2e86a2b7c3 Binary files /dev/null and b/pagefind/fragment/zh-cn_a7edffe.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_ac92f78.pf_fragment b/pagefind/fragment/zh-cn_ac92f78.pf_fragment new file mode 100644 index 0000000000..ac03b6c584 Binary files /dev/null and b/pagefind/fragment/zh-cn_ac92f78.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_af6cbe1.pf_fragment b/pagefind/fragment/zh-cn_af6cbe1.pf_fragment new file mode 100644 index 0000000000..e2c77b3f7f Binary files /dev/null and b/pagefind/fragment/zh-cn_af6cbe1.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_b7b2564.pf_fragment b/pagefind/fragment/zh-cn_b7b2564.pf_fragment new file mode 100644 index 0000000000..408b331728 Binary files /dev/null and b/pagefind/fragment/zh-cn_b7b2564.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_c1151c9.pf_fragment b/pagefind/fragment/zh-cn_c1151c9.pf_fragment new file mode 100644 index 0000000000..a1efe934ab Binary files /dev/null and b/pagefind/fragment/zh-cn_c1151c9.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_c2e89f3.pf_fragment b/pagefind/fragment/zh-cn_c2e89f3.pf_fragment new file mode 100644 index 0000000000..56c8fd33a0 Binary files /dev/null and b/pagefind/fragment/zh-cn_c2e89f3.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_c4595ab.pf_fragment b/pagefind/fragment/zh-cn_c4595ab.pf_fragment new file mode 100644 index 0000000000..6aa492c35f Binary files /dev/null and b/pagefind/fragment/zh-cn_c4595ab.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_c4a5919.pf_fragment b/pagefind/fragment/zh-cn_c4a5919.pf_fragment new file mode 100644 index 0000000000..3491749896 Binary files /dev/null and b/pagefind/fragment/zh-cn_c4a5919.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_c4f682e.pf_fragment b/pagefind/fragment/zh-cn_c4f682e.pf_fragment new file mode 100644 index 0000000000..8a3fcc5928 Binary files /dev/null and b/pagefind/fragment/zh-cn_c4f682e.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_c551e89.pf_fragment b/pagefind/fragment/zh-cn_c551e89.pf_fragment new file mode 100644 index 0000000000..2a4308d5f3 Binary files /dev/null and b/pagefind/fragment/zh-cn_c551e89.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_c82f3b2.pf_fragment b/pagefind/fragment/zh-cn_c82f3b2.pf_fragment new file mode 100644 index 0000000000..dd4a5bc4fe Binary files /dev/null and b/pagefind/fragment/zh-cn_c82f3b2.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_cfbcb39.pf_fragment b/pagefind/fragment/zh-cn_cfbcb39.pf_fragment new file mode 100644 index 0000000000..7966b3eb2b Binary files /dev/null and b/pagefind/fragment/zh-cn_cfbcb39.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_cfc7c79.pf_fragment b/pagefind/fragment/zh-cn_cfc7c79.pf_fragment new file mode 100644 index 0000000000..d61e50c3ef Binary files /dev/null and b/pagefind/fragment/zh-cn_cfc7c79.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_d32fcee.pf_fragment b/pagefind/fragment/zh-cn_d32fcee.pf_fragment new file mode 100644 index 0000000000..d8a00f9bad Binary files /dev/null and b/pagefind/fragment/zh-cn_d32fcee.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_d98338a.pf_fragment b/pagefind/fragment/zh-cn_d98338a.pf_fragment new file mode 100644 index 0000000000..6adbfcd4b2 Binary files /dev/null and b/pagefind/fragment/zh-cn_d98338a.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_e1f4a79.pf_fragment b/pagefind/fragment/zh-cn_e1f4a79.pf_fragment new file mode 100644 index 0000000000..eb532478a1 Binary files /dev/null and b/pagefind/fragment/zh-cn_e1f4a79.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_e347438.pf_fragment b/pagefind/fragment/zh-cn_e347438.pf_fragment new file mode 100644 index 0000000000..8e2069efca Binary files /dev/null and b/pagefind/fragment/zh-cn_e347438.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_e41081e.pf_fragment b/pagefind/fragment/zh-cn_e41081e.pf_fragment new file mode 100644 index 0000000000..2463f8f825 Binary files /dev/null and b/pagefind/fragment/zh-cn_e41081e.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_e64f93e.pf_fragment b/pagefind/fragment/zh-cn_e64f93e.pf_fragment new file mode 100644 index 0000000000..4a675a4fbd Binary files /dev/null and b/pagefind/fragment/zh-cn_e64f93e.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_e6b1657.pf_fragment b/pagefind/fragment/zh-cn_e6b1657.pf_fragment new file mode 100644 index 0000000000..c8b4291a22 Binary files /dev/null and b/pagefind/fragment/zh-cn_e6b1657.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_e6cc6a8.pf_fragment b/pagefind/fragment/zh-cn_e6cc6a8.pf_fragment new file mode 100644 index 0000000000..6fd4768bac Binary files /dev/null and b/pagefind/fragment/zh-cn_e6cc6a8.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_e88bc3f.pf_fragment b/pagefind/fragment/zh-cn_e88bc3f.pf_fragment new file mode 100644 index 0000000000..c44bfc1a9e Binary files /dev/null and b/pagefind/fragment/zh-cn_e88bc3f.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_f09c929.pf_fragment b/pagefind/fragment/zh-cn_f09c929.pf_fragment new file mode 100644 index 0000000000..fc074d969f Binary files /dev/null and b/pagefind/fragment/zh-cn_f09c929.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_f379427.pf_fragment b/pagefind/fragment/zh-cn_f379427.pf_fragment new file mode 100644 index 0000000000..5c6e82c9fb Binary files /dev/null and b/pagefind/fragment/zh-cn_f379427.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_f7dcce8.pf_fragment b/pagefind/fragment/zh-cn_f7dcce8.pf_fragment new file mode 100644 index 0000000000..31c5ef44f6 Binary files /dev/null and b/pagefind/fragment/zh-cn_f7dcce8.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_f83f580.pf_fragment b/pagefind/fragment/zh-cn_f83f580.pf_fragment new file mode 100644 index 0000000000..e064f391fd Binary files /dev/null and b/pagefind/fragment/zh-cn_f83f580.pf_fragment differ diff --git a/pagefind/fragment/zh-cn_f9c4333.pf_fragment b/pagefind/fragment/zh-cn_f9c4333.pf_fragment new file mode 100644 index 0000000000..1755645619 Binary files /dev/null and b/pagefind/fragment/zh-cn_f9c4333.pf_fragment differ diff --git a/pagefind/index/en_bc39585.pf_index b/pagefind/index/en_bc39585.pf_index new file mode 100644 index 0000000000..1f35eedd3a Binary files /dev/null and b/pagefind/index/en_bc39585.pf_index differ diff --git a/pagefind/index/en_d22f299.pf_index b/pagefind/index/en_d22f299.pf_index new file mode 100644 index 0000000000..1f70b4e52f Binary files /dev/null and b/pagefind/index/en_d22f299.pf_index differ diff --git a/pagefind/index/en_e8e8597.pf_index b/pagefind/index/en_e8e8597.pf_index new file mode 100644 index 0000000000..8d99df7938 Binary files /dev/null and b/pagefind/index/en_e8e8597.pf_index differ diff --git a/pagefind/index/zh-cn_28c9eca.pf_index b/pagefind/index/zh-cn_28c9eca.pf_index new file mode 100644 index 0000000000..db9ca1422a Binary files /dev/null and b/pagefind/index/zh-cn_28c9eca.pf_index differ diff --git a/pagefind/index/zh-cn_42b3c8b.pf_index b/pagefind/index/zh-cn_42b3c8b.pf_index new file mode 100644 index 0000000000..167196b04e Binary files /dev/null and b/pagefind/index/zh-cn_42b3c8b.pf_index differ diff --git a/pagefind/index/zh-cn_83d69b2.pf_index b/pagefind/index/zh-cn_83d69b2.pf_index new file mode 100644 index 0000000000..8432b54c77 Binary files /dev/null and b/pagefind/index/zh-cn_83d69b2.pf_index differ diff --git a/pagefind/index/zh-cn_b7a0b84.pf_index b/pagefind/index/zh-cn_b7a0b84.pf_index new file mode 100644 index 0000000000..82876e2322 Binary files /dev/null and b/pagefind/index/zh-cn_b7a0b84.pf_index differ diff --git a/pagefind/index/zh-cn_e75ebf3.pf_index b/pagefind/index/zh-cn_e75ebf3.pf_index new file mode 100644 index 0000000000..09287f6061 Binary files /dev/null and b/pagefind/index/zh-cn_e75ebf3.pf_index differ diff --git a/pagefind/pagefind-entry.json b/pagefind/pagefind-entry.json new file mode 100644 index 0000000000..1d0043403a --- /dev/null +++ b/pagefind/pagefind-entry.json @@ -0,0 +1 @@ +{"version":"1.1.1","languages":{"en":{"hash":"en_c73d434e5f","wasm":"en","page_count":64},"zh-cn":{"hash":"zh-cn_dcc472e46a518","wasm":null,"page_count":72}}} \ No newline at end of file diff --git a/pagefind/pagefind-highlight.js b/pagefind/pagefind-highlight.js new file mode 100644 index 0000000000..c823fbfe7d --- /dev/null +++ b/pagefind/pagefind-highlight.js @@ -0,0 +1,1069 @@ +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); + +// node_modules/mark.js/dist/mark.js +var require_mark = __commonJS({ + "node_modules/mark.js/dist/mark.js"(exports, module) { + (function(global, factory) { + typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : global.Mark = factory(); + })(exports, function() { + "use strict"; + 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; + }; + var classCallCheck = function(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + var createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) + descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + return function(Constructor, protoProps, staticProps) { + if (protoProps) + defineProperties(Constructor.prototype, protoProps); + if (staticProps) + defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + var _extends = Object.assign || function(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + return target; + }; + var DOMIterator = function() { + function DOMIterator2(ctx) { + var iframes = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true; + var exclude = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : []; + var iframesTimeout = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : 5e3; + classCallCheck(this, DOMIterator2); + this.ctx = ctx; + this.iframes = iframes; + this.exclude = exclude; + this.iframesTimeout = iframesTimeout; + } + createClass(DOMIterator2, [{ + key: "getContexts", + value: function getContexts() { + var ctx = void 0, filteredCtx = []; + if (typeof this.ctx === "undefined" || !this.ctx) { + ctx = []; + } else if (NodeList.prototype.isPrototypeOf(this.ctx)) { + ctx = Array.prototype.slice.call(this.ctx); + } else if (Array.isArray(this.ctx)) { + ctx = this.ctx; + } else if (typeof this.ctx === "string") { + ctx = Array.prototype.slice.call(document.querySelectorAll(this.ctx)); + } else { + ctx = [this.ctx]; + } + ctx.forEach(function(ctx2) { + var isDescendant = filteredCtx.filter(function(contexts) { + return contexts.contains(ctx2); + }).length > 0; + if (filteredCtx.indexOf(ctx2) === -1 && !isDescendant) { + filteredCtx.push(ctx2); + } + }); + return filteredCtx; + } + }, { + key: "getIframeContents", + value: function getIframeContents(ifr, successFn) { + var errorFn = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : function() { + }; + var doc = void 0; + try { + var ifrWin = ifr.contentWindow; + doc = ifrWin.document; + if (!ifrWin || !doc) { + throw new Error("iframe inaccessible"); + } + } catch (e) { + errorFn(); + } + if (doc) { + successFn(doc); + } + } + }, { + key: "isIframeBlank", + value: function isIframeBlank(ifr) { + var bl = "about:blank", src = ifr.getAttribute("src").trim(), href = ifr.contentWindow.location.href; + return href === bl && src !== bl && src; + } + }, { + key: "observeIframeLoad", + value: function observeIframeLoad(ifr, successFn, errorFn) { + var _this = this; + var called = false, tout = null; + var listener = function listener2() { + if (called) { + return; + } + called = true; + clearTimeout(tout); + try { + if (!_this.isIframeBlank(ifr)) { + ifr.removeEventListener("load", listener2); + _this.getIframeContents(ifr, successFn, errorFn); + } + } catch (e) { + errorFn(); + } + }; + ifr.addEventListener("load", listener); + tout = setTimeout(listener, this.iframesTimeout); + } + }, { + key: "onIframeReady", + value: function onIframeReady(ifr, successFn, errorFn) { + try { + if (ifr.contentWindow.document.readyState === "complete") { + if (this.isIframeBlank(ifr)) { + this.observeIframeLoad(ifr, successFn, errorFn); + } else { + this.getIframeContents(ifr, successFn, errorFn); + } + } else { + this.observeIframeLoad(ifr, successFn, errorFn); + } + } catch (e) { + errorFn(); + } + } + }, { + key: "waitForIframes", + value: function waitForIframes(ctx, done) { + var _this2 = this; + var eachCalled = 0; + this.forEachIframe(ctx, function() { + return true; + }, function(ifr) { + eachCalled++; + _this2.waitForIframes(ifr.querySelector("html"), function() { + if (!--eachCalled) { + done(); + } + }); + }, function(handled) { + if (!handled) { + done(); + } + }); + } + }, { + key: "forEachIframe", + value: function forEachIframe(ctx, filter, each) { + var _this3 = this; + var end = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : function() { + }; + var ifr = ctx.querySelectorAll("iframe"), open = ifr.length, handled = 0; + ifr = Array.prototype.slice.call(ifr); + var checkEnd = function checkEnd2() { + if (--open <= 0) { + end(handled); + } + }; + if (!open) { + checkEnd(); + } + ifr.forEach(function(ifr2) { + if (DOMIterator2.matches(ifr2, _this3.exclude)) { + checkEnd(); + } else { + _this3.onIframeReady(ifr2, function(con) { + if (filter(ifr2)) { + handled++; + each(con); + } + checkEnd(); + }, checkEnd); + } + }); + } + }, { + key: "createIterator", + value: function createIterator(ctx, whatToShow, filter) { + return document.createNodeIterator(ctx, whatToShow, filter, false); + } + }, { + key: "createInstanceOnIframe", + value: function createInstanceOnIframe(contents) { + return new DOMIterator2(contents.querySelector("html"), this.iframes); + } + }, { + key: "compareNodeIframe", + value: function compareNodeIframe(node, prevNode, ifr) { + var compCurr = node.compareDocumentPosition(ifr), prev = Node.DOCUMENT_POSITION_PRECEDING; + if (compCurr & prev) { + if (prevNode !== null) { + var compPrev = prevNode.compareDocumentPosition(ifr), after = Node.DOCUMENT_POSITION_FOLLOWING; + if (compPrev & after) { + return true; + } + } else { + return true; + } + } + return false; + } + }, { + key: "getIteratorNode", + value: function getIteratorNode(itr) { + var prevNode = itr.previousNode(); + var node = void 0; + if (prevNode === null) { + node = itr.nextNode(); + } else { + node = itr.nextNode() && itr.nextNode(); + } + return { + prevNode, + node + }; + } + }, { + key: "checkIframeFilter", + value: function checkIframeFilter(node, prevNode, currIfr, ifr) { + var key = false, handled = false; + ifr.forEach(function(ifrDict, i) { + if (ifrDict.val === currIfr) { + key = i; + handled = ifrDict.handled; + } + }); + if (this.compareNodeIframe(node, prevNode, currIfr)) { + if (key === false && !handled) { + ifr.push({ + val: currIfr, + handled: true + }); + } else if (key !== false && !handled) { + ifr[key].handled = true; + } + return true; + } + if (key === false) { + ifr.push({ + val: currIfr, + handled: false + }); + } + return false; + } + }, { + key: "handleOpenIframes", + value: function handleOpenIframes(ifr, whatToShow, eCb, fCb) { + var _this4 = this; + ifr.forEach(function(ifrDict) { + if (!ifrDict.handled) { + _this4.getIframeContents(ifrDict.val, function(con) { + _this4.createInstanceOnIframe(con).forEachNode(whatToShow, eCb, fCb); + }); + } + }); + } + }, { + key: "iterateThroughNodes", + value: function iterateThroughNodes(whatToShow, ctx, eachCb, filterCb, doneCb) { + var _this5 = this; + var itr = this.createIterator(ctx, whatToShow, filterCb); + var ifr = [], elements = [], node = void 0, prevNode = void 0, retrieveNodes = function retrieveNodes2() { + var _getIteratorNode = _this5.getIteratorNode(itr); + prevNode = _getIteratorNode.prevNode; + node = _getIteratorNode.node; + return node; + }; + while (retrieveNodes()) { + if (this.iframes) { + this.forEachIframe(ctx, function(currIfr) { + return _this5.checkIframeFilter(node, prevNode, currIfr, ifr); + }, function(con) { + _this5.createInstanceOnIframe(con).forEachNode(whatToShow, function(ifrNode) { + return elements.push(ifrNode); + }, filterCb); + }); + } + elements.push(node); + } + elements.forEach(function(node2) { + eachCb(node2); + }); + if (this.iframes) { + this.handleOpenIframes(ifr, whatToShow, eachCb, filterCb); + } + doneCb(); + } + }, { + key: "forEachNode", + value: function forEachNode(whatToShow, each, filter) { + var _this6 = this; + var done = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : function() { + }; + var contexts = this.getContexts(); + var open = contexts.length; + if (!open) { + done(); + } + contexts.forEach(function(ctx) { + var ready = function ready2() { + _this6.iterateThroughNodes(whatToShow, ctx, each, filter, function() { + if (--open <= 0) { + done(); + } + }); + }; + if (_this6.iframes) { + _this6.waitForIframes(ctx, ready); + } else { + ready(); + } + }); + } + }], [{ + key: "matches", + value: function matches(element, selector) { + var selectors = typeof selector === "string" ? [selector] : selector, fn = element.matches || element.matchesSelector || element.msMatchesSelector || element.mozMatchesSelector || element.oMatchesSelector || element.webkitMatchesSelector; + if (fn) { + var match = false; + selectors.every(function(sel) { + if (fn.call(element, sel)) { + match = true; + return false; + } + return true; + }); + return match; + } else { + return false; + } + } + }]); + return DOMIterator2; + }(); + var Mark$1 = function() { + function Mark3(ctx) { + classCallCheck(this, Mark3); + this.ctx = ctx; + this.ie = false; + var ua = window.navigator.userAgent; + if (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident") > -1) { + this.ie = true; + } + } + createClass(Mark3, [{ + key: "log", + value: function log(msg) { + var level = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "debug"; + var log2 = this.opt.log; + if (!this.opt.debug) { + return; + } + if ((typeof log2 === "undefined" ? "undefined" : _typeof(log2)) === "object" && typeof log2[level] === "function") { + log2[level]("mark.js: " + msg); + } + } + }, { + key: "escapeStr", + value: function escapeStr(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + } + }, { + key: "createRegExp", + value: function createRegExp(str) { + if (this.opt.wildcards !== "disabled") { + str = this.setupWildcardsRegExp(str); + } + str = this.escapeStr(str); + if (Object.keys(this.opt.synonyms).length) { + str = this.createSynonymsRegExp(str); + } + if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) { + str = this.setupIgnoreJoinersRegExp(str); + } + if (this.opt.diacritics) { + str = this.createDiacriticsRegExp(str); + } + str = this.createMergedBlanksRegExp(str); + if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) { + str = this.createJoinersRegExp(str); + } + if (this.opt.wildcards !== "disabled") { + str = this.createWildcardsRegExp(str); + } + str = this.createAccuracyRegExp(str); + return str; + } + }, { + key: "createSynonymsRegExp", + value: function createSynonymsRegExp(str) { + var syn = this.opt.synonyms, sens = this.opt.caseSensitive ? "" : "i", joinerPlaceholder = this.opt.ignoreJoiners || this.opt.ignorePunctuation.length ? "\0" : ""; + for (var index in syn) { + if (syn.hasOwnProperty(index)) { + var value = syn[index], k1 = this.opt.wildcards !== "disabled" ? this.setupWildcardsRegExp(index) : this.escapeStr(index), k2 = this.opt.wildcards !== "disabled" ? this.setupWildcardsRegExp(value) : this.escapeStr(value); + if (k1 !== "" && k2 !== "") { + str = str.replace(new RegExp("(" + this.escapeStr(k1) + "|" + this.escapeStr(k2) + ")", "gm" + sens), joinerPlaceholder + ("(" + this.processSynomyms(k1) + "|") + (this.processSynomyms(k2) + ")") + joinerPlaceholder); + } + } + } + return str; + } + }, { + key: "processSynomyms", + value: function processSynomyms(str) { + if (this.opt.ignoreJoiners || this.opt.ignorePunctuation.length) { + str = this.setupIgnoreJoinersRegExp(str); + } + return str; + } + }, { + key: "setupWildcardsRegExp", + value: function setupWildcardsRegExp(str) { + str = str.replace(/(?:\\)*\?/g, function(val) { + return val.charAt(0) === "\\" ? "?" : ""; + }); + return str.replace(/(?:\\)*\*/g, function(val) { + return val.charAt(0) === "\\" ? "*" : ""; + }); + } + }, { + key: "createWildcardsRegExp", + value: function createWildcardsRegExp(str) { + var spaces = this.opt.wildcards === "withSpaces"; + return str.replace(/\u0001/g, spaces ? "[\\S\\s]?" : "\\S?").replace(/\u0002/g, spaces ? "[\\S\\s]*?" : "\\S*"); + } + }, { + key: "setupIgnoreJoinersRegExp", + value: function setupIgnoreJoinersRegExp(str) { + return str.replace(/[^(|)\\]/g, function(val, indx, original) { + var nextChar = original.charAt(indx + 1); + if (/[(|)\\]/.test(nextChar) || nextChar === "") { + return val; + } else { + return val + "\0"; + } + }); + } + }, { + key: "createJoinersRegExp", + value: function createJoinersRegExp(str) { + var joiner = []; + var ignorePunctuation = this.opt.ignorePunctuation; + if (Array.isArray(ignorePunctuation) && ignorePunctuation.length) { + joiner.push(this.escapeStr(ignorePunctuation.join(""))); + } + if (this.opt.ignoreJoiners) { + joiner.push("\\u00ad\\u200b\\u200c\\u200d"); + } + return joiner.length ? str.split(/\u0000+/).join("[" + joiner.join("") + "]*") : str; + } + }, { + key: "createDiacriticsRegExp", + value: function createDiacriticsRegExp(str) { + var sens = this.opt.caseSensitive ? "" : "i", dct = this.opt.caseSensitive ? ["a\xE0\xE1\u1EA3\xE3\u1EA1\u0103\u1EB1\u1EAF\u1EB3\u1EB5\u1EB7\xE2\u1EA7\u1EA5\u1EA9\u1EAB\u1EAD\xE4\xE5\u0101\u0105", "A\xC0\xC1\u1EA2\xC3\u1EA0\u0102\u1EB0\u1EAE\u1EB2\u1EB4\u1EB6\xC2\u1EA6\u1EA4\u1EA8\u1EAA\u1EAC\xC4\xC5\u0100\u0104", "c\xE7\u0107\u010D", "C\xC7\u0106\u010C", "d\u0111\u010F", "D\u0110\u010E", "e\xE8\xE9\u1EBB\u1EBD\u1EB9\xEA\u1EC1\u1EBF\u1EC3\u1EC5\u1EC7\xEB\u011B\u0113\u0119", "E\xC8\xC9\u1EBA\u1EBC\u1EB8\xCA\u1EC0\u1EBE\u1EC2\u1EC4\u1EC6\xCB\u011A\u0112\u0118", "i\xEC\xED\u1EC9\u0129\u1ECB\xEE\xEF\u012B", "I\xCC\xCD\u1EC8\u0128\u1ECA\xCE\xCF\u012A", "l\u0142", "L\u0141", "n\xF1\u0148\u0144", "N\xD1\u0147\u0143", "o\xF2\xF3\u1ECF\xF5\u1ECD\xF4\u1ED3\u1ED1\u1ED5\u1ED7\u1ED9\u01A1\u1EDF\u1EE1\u1EDB\u1EDD\u1EE3\xF6\xF8\u014D", "O\xD2\xD3\u1ECE\xD5\u1ECC\xD4\u1ED2\u1ED0\u1ED4\u1ED6\u1ED8\u01A0\u1EDE\u1EE0\u1EDA\u1EDC\u1EE2\xD6\xD8\u014C", "r\u0159", "R\u0158", "s\u0161\u015B\u0219\u015F", "S\u0160\u015A\u0218\u015E", "t\u0165\u021B\u0163", "T\u0164\u021A\u0162", "u\xF9\xFA\u1EE7\u0169\u1EE5\u01B0\u1EEB\u1EE9\u1EED\u1EEF\u1EF1\xFB\xFC\u016F\u016B", "U\xD9\xDA\u1EE6\u0168\u1EE4\u01AF\u1EEA\u1EE8\u1EEC\u1EEE\u1EF0\xDB\xDC\u016E\u016A", "y\xFD\u1EF3\u1EF7\u1EF9\u1EF5\xFF", "Y\xDD\u1EF2\u1EF6\u1EF8\u1EF4\u0178", "z\u017E\u017C\u017A", "Z\u017D\u017B\u0179"] : ["a\xE0\xE1\u1EA3\xE3\u1EA1\u0103\u1EB1\u1EAF\u1EB3\u1EB5\u1EB7\xE2\u1EA7\u1EA5\u1EA9\u1EAB\u1EAD\xE4\xE5\u0101\u0105A\xC0\xC1\u1EA2\xC3\u1EA0\u0102\u1EB0\u1EAE\u1EB2\u1EB4\u1EB6\xC2\u1EA6\u1EA4\u1EA8\u1EAA\u1EAC\xC4\xC5\u0100\u0104", "c\xE7\u0107\u010DC\xC7\u0106\u010C", "d\u0111\u010FD\u0110\u010E", "e\xE8\xE9\u1EBB\u1EBD\u1EB9\xEA\u1EC1\u1EBF\u1EC3\u1EC5\u1EC7\xEB\u011B\u0113\u0119E\xC8\xC9\u1EBA\u1EBC\u1EB8\xCA\u1EC0\u1EBE\u1EC2\u1EC4\u1EC6\xCB\u011A\u0112\u0118", "i\xEC\xED\u1EC9\u0129\u1ECB\xEE\xEF\u012BI\xCC\xCD\u1EC8\u0128\u1ECA\xCE\xCF\u012A", "l\u0142L\u0141", "n\xF1\u0148\u0144N\xD1\u0147\u0143", "o\xF2\xF3\u1ECF\xF5\u1ECD\xF4\u1ED3\u1ED1\u1ED5\u1ED7\u1ED9\u01A1\u1EDF\u1EE1\u1EDB\u1EDD\u1EE3\xF6\xF8\u014DO\xD2\xD3\u1ECE\xD5\u1ECC\xD4\u1ED2\u1ED0\u1ED4\u1ED6\u1ED8\u01A0\u1EDE\u1EE0\u1EDA\u1EDC\u1EE2\xD6\xD8\u014C", "r\u0159R\u0158", "s\u0161\u015B\u0219\u015FS\u0160\u015A\u0218\u015E", "t\u0165\u021B\u0163T\u0164\u021A\u0162", "u\xF9\xFA\u1EE7\u0169\u1EE5\u01B0\u1EEB\u1EE9\u1EED\u1EEF\u1EF1\xFB\xFC\u016F\u016BU\xD9\xDA\u1EE6\u0168\u1EE4\u01AF\u1EEA\u1EE8\u1EEC\u1EEE\u1EF0\xDB\xDC\u016E\u016A", "y\xFD\u1EF3\u1EF7\u1EF9\u1EF5\xFFY\xDD\u1EF2\u1EF6\u1EF8\u1EF4\u0178", "z\u017E\u017C\u017AZ\u017D\u017B\u0179"]; + var handled = []; + str.split("").forEach(function(ch) { + dct.every(function(dct2) { + if (dct2.indexOf(ch) !== -1) { + if (handled.indexOf(dct2) > -1) { + return false; + } + str = str.replace(new RegExp("[" + dct2 + "]", "gm" + sens), "[" + dct2 + "]"); + handled.push(dct2); + } + return true; + }); + }); + return str; + } + }, { + key: "createMergedBlanksRegExp", + value: function createMergedBlanksRegExp(str) { + return str.replace(/[\s]+/gmi, "[\\s]+"); + } + }, { + key: "createAccuracyRegExp", + value: function createAccuracyRegExp(str) { + var _this = this; + var chars = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\xA1\xBF"; + var acc = this.opt.accuracy, val = typeof acc === "string" ? acc : acc.value, ls = typeof acc === "string" ? [] : acc.limiters, lsJoin = ""; + ls.forEach(function(limiter) { + lsJoin += "|" + _this.escapeStr(limiter); + }); + switch (val) { + case "partially": + default: + return "()(" + str + ")"; + case "complementary": + lsJoin = "\\s" + (lsJoin ? lsJoin : this.escapeStr(chars)); + return "()([^" + lsJoin + "]*" + str + "[^" + lsJoin + "]*)"; + case "exactly": + return "(^|\\s" + lsJoin + ")(" + str + ")(?=$|\\s" + lsJoin + ")"; + } + } + }, { + key: "getSeparatedKeywords", + value: function getSeparatedKeywords(sv) { + var _this2 = this; + var stack = []; + sv.forEach(function(kw) { + if (!_this2.opt.separateWordSearch) { + if (kw.trim() && stack.indexOf(kw) === -1) { + stack.push(kw); + } + } else { + kw.split(" ").forEach(function(kwSplitted) { + if (kwSplitted.trim() && stack.indexOf(kwSplitted) === -1) { + stack.push(kwSplitted); + } + }); + } + }); + return { + "keywords": stack.sort(function(a, b) { + return b.length - a.length; + }), + "length": stack.length + }; + } + }, { + key: "isNumeric", + value: function isNumeric(value) { + return Number(parseFloat(value)) == value; + } + }, { + key: "checkRanges", + value: function checkRanges(array) { + var _this3 = this; + if (!Array.isArray(array) || Object.prototype.toString.call(array[0]) !== "[object Object]") { + this.log("markRanges() will only accept an array of objects"); + this.opt.noMatch(array); + return []; + } + var stack = []; + var last = 0; + array.sort(function(a, b) { + return a.start - b.start; + }).forEach(function(item) { + var _callNoMatchOnInvalid = _this3.callNoMatchOnInvalidRanges(item, last), start = _callNoMatchOnInvalid.start, end = _callNoMatchOnInvalid.end, valid = _callNoMatchOnInvalid.valid; + if (valid) { + item.start = start; + item.length = end - start; + stack.push(item); + last = end; + } + }); + return stack; + } + }, { + key: "callNoMatchOnInvalidRanges", + value: function callNoMatchOnInvalidRanges(range, last) { + var start = void 0, end = void 0, valid = false; + if (range && typeof range.start !== "undefined") { + start = parseInt(range.start, 10); + end = start + parseInt(range.length, 10); + if (this.isNumeric(range.start) && this.isNumeric(range.length) && end - last > 0 && end - start > 0) { + valid = true; + } else { + this.log("Ignoring invalid or overlapping range: " + ("" + JSON.stringify(range))); + this.opt.noMatch(range); + } + } else { + this.log("Ignoring invalid range: " + JSON.stringify(range)); + this.opt.noMatch(range); + } + return { + start, + end, + valid + }; + } + }, { + key: "checkWhitespaceRanges", + value: function checkWhitespaceRanges(range, originalLength, string) { + var end = void 0, valid = true, max = string.length, offset = originalLength - max, start = parseInt(range.start, 10) - offset; + start = start > max ? max : start; + end = start + parseInt(range.length, 10); + if (end > max) { + end = max; + this.log("End range automatically set to the max value of " + max); + } + if (start < 0 || end - start < 0 || start > max || end > max) { + valid = false; + this.log("Invalid range: " + JSON.stringify(range)); + this.opt.noMatch(range); + } else if (string.substring(start, end).replace(/\s+/g, "") === "") { + valid = false; + this.log("Skipping whitespace only range: " + JSON.stringify(range)); + this.opt.noMatch(range); + } + return { + start, + end, + valid + }; + } + }, { + key: "getTextNodes", + value: function getTextNodes(cb) { + var _this4 = this; + var val = "", nodes = []; + this.iterator.forEachNode(NodeFilter.SHOW_TEXT, function(node) { + nodes.push({ + start: val.length, + end: (val += node.textContent).length, + node + }); + }, function(node) { + if (_this4.matchesExclude(node.parentNode)) { + return NodeFilter.FILTER_REJECT; + } else { + return NodeFilter.FILTER_ACCEPT; + } + }, function() { + cb({ + value: val, + nodes + }); + }); + } + }, { + key: "matchesExclude", + value: function matchesExclude(el) { + return DOMIterator.matches(el, this.opt.exclude.concat(["script", "style", "title", "head", "html"])); + } + }, { + key: "wrapRangeInTextNode", + value: function wrapRangeInTextNode(node, start, end) { + var hEl = !this.opt.element ? "mark" : this.opt.element, startNode = node.splitText(start), ret = startNode.splitText(end - start); + var repl = document.createElement(hEl); + repl.setAttribute("data-markjs", "true"); + if (this.opt.className) { + repl.setAttribute("class", this.opt.className); + } + repl.textContent = startNode.textContent; + startNode.parentNode.replaceChild(repl, startNode); + return ret; + } + }, { + key: "wrapRangeInMappedTextNode", + value: function wrapRangeInMappedTextNode(dict, start, end, filterCb, eachCb) { + var _this5 = this; + dict.nodes.every(function(n, i) { + var sibl = dict.nodes[i + 1]; + if (typeof sibl === "undefined" || sibl.start > start) { + if (!filterCb(n.node)) { + return false; + } + var s = start - n.start, e = (end > n.end ? n.end : end) - n.start, startStr = dict.value.substr(0, n.start), endStr = dict.value.substr(e + n.start); + n.node = _this5.wrapRangeInTextNode(n.node, s, e); + dict.value = startStr + endStr; + dict.nodes.forEach(function(k, j) { + if (j >= i) { + if (dict.nodes[j].start > 0 && j !== i) { + dict.nodes[j].start -= e; + } + dict.nodes[j].end -= e; + } + }); + end -= e; + eachCb(n.node.previousSibling, n.start); + if (end > n.end) { + start = n.end; + } else { + return false; + } + } + return true; + }); + } + }, { + key: "wrapMatches", + value: function wrapMatches(regex, ignoreGroups, filterCb, eachCb, endCb) { + var _this6 = this; + var matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1; + this.getTextNodes(function(dict) { + dict.nodes.forEach(function(node) { + node = node.node; + var match = void 0; + while ((match = regex.exec(node.textContent)) !== null && match[matchIdx] !== "") { + if (!filterCb(match[matchIdx], node)) { + continue; + } + var pos = match.index; + if (matchIdx !== 0) { + for (var i = 1; i < matchIdx; i++) { + pos += match[i].length; + } + } + node = _this6.wrapRangeInTextNode(node, pos, pos + match[matchIdx].length); + eachCb(node.previousSibling); + regex.lastIndex = 0; + } + }); + endCb(); + }); + } + }, { + key: "wrapMatchesAcrossElements", + value: function wrapMatchesAcrossElements(regex, ignoreGroups, filterCb, eachCb, endCb) { + var _this7 = this; + var matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1; + this.getTextNodes(function(dict) { + var match = void 0; + while ((match = regex.exec(dict.value)) !== null && match[matchIdx] !== "") { + var start = match.index; + if (matchIdx !== 0) { + for (var i = 1; i < matchIdx; i++) { + start += match[i].length; + } + } + var end = start + match[matchIdx].length; + _this7.wrapRangeInMappedTextNode(dict, start, end, function(node) { + return filterCb(match[matchIdx], node); + }, function(node, lastIndex) { + regex.lastIndex = lastIndex; + eachCb(node); + }); + } + endCb(); + }); + } + }, { + key: "wrapRangeFromIndex", + value: function wrapRangeFromIndex(ranges, filterCb, eachCb, endCb) { + var _this8 = this; + this.getTextNodes(function(dict) { + var originalLength = dict.value.length; + ranges.forEach(function(range, counter) { + var _checkWhitespaceRange = _this8.checkWhitespaceRanges(range, originalLength, dict.value), start = _checkWhitespaceRange.start, end = _checkWhitespaceRange.end, valid = _checkWhitespaceRange.valid; + if (valid) { + _this8.wrapRangeInMappedTextNode(dict, start, end, function(node) { + return filterCb(node, range, dict.value.substring(start, end), counter); + }, function(node) { + eachCb(node, range); + }); + } + }); + endCb(); + }); + } + }, { + key: "unwrapMatches", + value: function unwrapMatches(node) { + var parent = node.parentNode; + var docFrag = document.createDocumentFragment(); + while (node.firstChild) { + docFrag.appendChild(node.removeChild(node.firstChild)); + } + parent.replaceChild(docFrag, node); + if (!this.ie) { + parent.normalize(); + } else { + this.normalizeTextNode(parent); + } + } + }, { + key: "normalizeTextNode", + value: function normalizeTextNode(node) { + if (!node) { + return; + } + if (node.nodeType === 3) { + while (node.nextSibling && node.nextSibling.nodeType === 3) { + node.nodeValue += node.nextSibling.nodeValue; + node.parentNode.removeChild(node.nextSibling); + } + } else { + this.normalizeTextNode(node.firstChild); + } + this.normalizeTextNode(node.nextSibling); + } + }, { + key: "markRegExp", + value: function markRegExp(regexp, opt) { + var _this9 = this; + this.opt = opt; + this.log('Searching with expression "' + regexp + '"'); + var totalMatches = 0, fn = "wrapMatches"; + var eachCb = function eachCb2(element) { + totalMatches++; + _this9.opt.each(element); + }; + if (this.opt.acrossElements) { + fn = "wrapMatchesAcrossElements"; + } + this[fn](regexp, this.opt.ignoreGroups, function(match, node) { + return _this9.opt.filter(node, match, totalMatches); + }, eachCb, function() { + if (totalMatches === 0) { + _this9.opt.noMatch(regexp); + } + _this9.opt.done(totalMatches); + }); + } + }, { + key: "mark", + value: function mark(sv, opt) { + var _this10 = this; + this.opt = opt; + var totalMatches = 0, fn = "wrapMatches"; + var _getSeparatedKeywords = this.getSeparatedKeywords(typeof sv === "string" ? [sv] : sv), kwArr = _getSeparatedKeywords.keywords, kwArrLen = _getSeparatedKeywords.length, sens = this.opt.caseSensitive ? "" : "i", handler = function handler2(kw) { + var regex = new RegExp(_this10.createRegExp(kw), "gm" + sens), matches = 0; + _this10.log('Searching with expression "' + regex + '"'); + _this10[fn](regex, 1, function(term, node) { + return _this10.opt.filter(node, kw, totalMatches, matches); + }, function(element) { + matches++; + totalMatches++; + _this10.opt.each(element); + }, function() { + if (matches === 0) { + _this10.opt.noMatch(kw); + } + if (kwArr[kwArrLen - 1] === kw) { + _this10.opt.done(totalMatches); + } else { + handler2(kwArr[kwArr.indexOf(kw) + 1]); + } + }); + }; + if (this.opt.acrossElements) { + fn = "wrapMatchesAcrossElements"; + } + if (kwArrLen === 0) { + this.opt.done(totalMatches); + } else { + handler(kwArr[0]); + } + } + }, { + key: "markRanges", + value: function markRanges(rawRanges, opt) { + var _this11 = this; + this.opt = opt; + var totalMatches = 0, ranges = this.checkRanges(rawRanges); + if (ranges && ranges.length) { + this.log("Starting to mark with the following ranges: " + JSON.stringify(ranges)); + this.wrapRangeFromIndex(ranges, function(node, range, match, counter) { + return _this11.opt.filter(node, range, match, counter); + }, function(element, range) { + totalMatches++; + _this11.opt.each(element, range); + }, function() { + _this11.opt.done(totalMatches); + }); + } else { + this.opt.done(totalMatches); + } + } + }, { + key: "unmark", + value: function unmark(opt) { + var _this12 = this; + this.opt = opt; + var sel = this.opt.element ? this.opt.element : "*"; + sel += "[data-markjs]"; + if (this.opt.className) { + sel += "." + this.opt.className; + } + this.log('Removal selector "' + sel + '"'); + this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT, function(node) { + _this12.unwrapMatches(node); + }, function(node) { + var matchesSel = DOMIterator.matches(node, sel), matchesExclude = _this12.matchesExclude(node); + if (!matchesSel || matchesExclude) { + return NodeFilter.FILTER_REJECT; + } else { + return NodeFilter.FILTER_ACCEPT; + } + }, this.opt.done); + } + }, { + key: "opt", + set: function set$$1(val) { + this._opt = _extends({}, { + "element": "", + "className": "", + "exclude": [], + "iframes": false, + "iframesTimeout": 5e3, + "separateWordSearch": true, + "diacritics": true, + "synonyms": {}, + "accuracy": "partially", + "acrossElements": false, + "caseSensitive": false, + "ignoreJoiners": false, + "ignoreGroups": 0, + "ignorePunctuation": [], + "wildcards": "disabled", + "each": function each() { + }, + "noMatch": function noMatch() { + }, + "filter": function filter() { + return true; + }, + "done": function done() { + }, + "debug": false, + "log": window.console + }, val); + }, + get: function get$$1() { + return this._opt; + } + }, { + key: "iterator", + get: function get$$1() { + return new DOMIterator(this.ctx, this.opt.iframes, this.opt.exclude, this.opt.iframesTimeout); + } + }]); + return Mark3; + }(); + function Mark2(ctx) { + var _this = this; + var instance = new Mark$1(ctx); + this.mark = function(sv, opt) { + instance.mark(sv, opt); + return _this; + }; + this.markRegExp = function(sv, opt) { + instance.markRegExp(sv, opt); + return _this; + }; + this.markRanges = function(sv, opt) { + instance.markRanges(sv, opt); + return _this; + }; + this.unmark = function(opt) { + instance.unmark(opt); + return _this; + }; + return this; + } + return Mark2; + }); + } +}); + +// lib/highlight.ts +var import_mark = __toESM(require_mark(), 1); +var PagefindHighlight = class { + constructor(options = { + markContext: null, + highlightParam: "pagefind-highlight", + markOptions: { + className: "pagefind-highlight", + exclude: ["[data-pagefind-ignore]", "[data-pagefind-ignore] *"] + }, + addStyles: true + }) { + var _a, _b; + const { highlightParam, markContext, markOptions, addStyles } = options; + this.highlightParam = highlightParam ?? "pagefind-highlight"; + this.addStyles = addStyles ?? true; + this.markContext = markContext !== void 0 ? markContext : null; + this.markOptions = markOptions !== void 0 ? markOptions : { + className: "pagefind-highlight", + exclude: ["[data-pagefind-ignore]", "[data-pagefind-ignore] *"] + }; + (_a = this.markOptions).className ?? (_a.className = "pagefind__highlight"); + (_b = this.markOptions).exclude ?? (_b.exclude = [ + "[data-pagefind-ignore]", + "[data-pagefind-ignore] *" + ]); + this.markOptions.separateWordSearch = false; + this.highlight(); + } + getHighlightParams(paramName) { + const urlParams = new URLSearchParams(window.location.search); + return urlParams.getAll(paramName); + } + // Inline styles might be too hard to override + addHighlightStyles(className) { + if (!className) + return; + const styleElement = document.createElement("style"); + styleElement.innerText = `:where(.${className}) { background-color: yellow; color: black; }`; + document.head.appendChild(styleElement); + } + createMarkInstance() { + if (this.markContext) { + return new import_mark.default(this.markContext); + } + const pagefindBody = document.querySelectorAll("[data-pagefind-body]"); + if (pagefindBody.length !== 0) { + return new import_mark.default(pagefindBody); + } else { + return new import_mark.default(document.body); + } + } + markText(instance, text) { + instance.mark(text, this.markOptions); + } + highlight() { + const params = this.getHighlightParams(this.highlightParam); + if (!params || params.length === 0) + return; + this.addStyles && this.addHighlightStyles(this.markOptions.className); + const markInstance = this.createMarkInstance(); + this.markText(markInstance, params); + } +}; +window.PagefindHighlight = PagefindHighlight; +export { + PagefindHighlight as default +}; +/*! Bundled license information: + +mark.js/dist/mark.js: + (*!*************************************************** + * mark.js v8.11.1 + * https://markjs.io/ + * Copyright (c) 2014–2018, Julian Kühnel + * Released under the MIT license https://git.io/vwTVl + *****************************************************) +*/ diff --git a/pagefind/pagefind-modular-ui.css b/pagefind/pagefind-modular-ui.css new file mode 100644 index 0000000000..9c6793ed2b --- /dev/null +++ b/pagefind/pagefind-modular-ui.css @@ -0,0 +1,214 @@ +:root { + --pagefind-ui-scale: 0.8; + --pagefind-ui-primary: #034AD8; + --pagefind-ui-fade: #707070; + --pagefind-ui-text: #393939; + --pagefind-ui-background: #ffffff; + --pagefind-ui-border: #eeeeee; + --pagefind-ui-tag: #eeeeee; + --pagefind-ui-border-width: 2px; + --pagefind-ui-border-radius: 8px; + --pagefind-ui-image-border-radius: 8px; + --pagefind-ui-image-box-ratio: 3 / 2; + --pagefind-ui-font: system, -apple-system, ".SFNSText-Regular", + "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", + "Lucida Grande", sans-serif; +} + +[data-pfmod-hidden] { + display: none !important; +} + +[data-pfmod-suppressed] { + opacity: 0 !important; + pointer-events: none !important; +} + +[data-pfmod-sr-hidden] { + -webkit-clip: rect(0 0 0 0) !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + height: 1px !important; + overflow: hidden !important; + overflow: clip !important; + position: absolute !important; + white-space: nowrap !important; + width: 1px !important; +} + +[data-pfmod-loading] { + color: var(--pagefind-ui-text); + background-color: var(--pagefind-ui-text); + border-radius: var(--pagefind-ui-border-radius); + opacity: 0.1; + pointer-events: none; +} + +/* Input */ + +.pagefind-modular-input-wrapper { + position: relative; +} + +.pagefind-modular-input-wrapper::before { + background-color: var(--pagefind-ui-text); + width: calc(18px * var(--pagefind-ui-scale)); + height: calc(18px * var(--pagefind-ui-scale)); + top: calc(23px * var(--pagefind-ui-scale)); + left: calc(20px * var(--pagefind-ui-scale)); + content: ""; + position: absolute; + display: block; + opacity: 0.7; + -webkit-mask-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A"); + mask-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A"); + -webkit-mask-size: 100%; + mask-size: 100%; + z-index: 9; + pointer-events: none; +} + +.pagefind-modular-input { + height: calc(64px * var(--pagefind-ui-scale)); + padding: 0 calc(70px * var(--pagefind-ui-scale)) 0 calc(54px * var(--pagefind-ui-scale)); + background-color: var(--pagefind-ui-background); + border: var(--pagefind-ui-border-width) solid var(--pagefind-ui-border); + border-radius: var(--pagefind-ui-border-radius); + font-size: calc(21px * var(--pagefind-ui-scale)); + position: relative; + appearance: none; + -webkit-appearance: none; + display: flex; + width: 100%; + box-sizing: border-box; + font-weight: 700; +} + +.pagefind-modular-input::placeholder { + opacity: 0.2; +} + +.pagefind-modular-input-clear { + position: absolute; + top: calc(2px * var(--pagefind-ui-scale)); + right: calc(2px * var(--pagefind-ui-scale)); + height: calc(60px * var(--pagefind-ui-scale)); + border-radius: var(--pagefind-ui-border-radius); + padding: 0 calc(15px * var(--pagefind-ui-scale)) 0 calc(2px * var(--pagefind-ui-scale)); + color: var(--pagefind-ui-text); + font-size: calc(14px * var(--pagefind-ui-scale)); + cursor: pointer; + background-color: var(--pagefind-ui-background); + border: none; + appearance: none; +} + +/* ResultList */ + +.pagefind-modular-list-result { + list-style-type: none; + display: flex; + align-items: flex-start; + gap: min(calc(40px * var(--pagefind-ui-scale)), 3%); + padding: calc(30px * var(--pagefind-ui-scale)) 0 calc(40px * var(--pagefind-ui-scale)); + border-top: solid var(--pagefind-ui-border-width) var(--pagefind-ui-border); +} + +.pagefind-modular-list-result:last-of-type { + border-bottom: solid var(--pagefind-ui-border-width) var(--pagefind-ui-border); +} + +.pagefind-modular-list-thumb { + width: min(30%, + calc((30% - (100px * var(--pagefind-ui-scale))) * 100000)); + max-width: calc(120px * var(--pagefind-ui-scale)); + margin-top: calc(10px * var(--pagefind-ui-scale)); + aspect-ratio: var(--pagefind-ui-image-box-ratio); + position: relative; +} + +.pagefind-modular-list-image { + display: block; + position: absolute; + left: 50%; + transform: translateX(-50%); + font-size: 0; + width: auto; + height: auto; + max-width: 100%; + max-height: 100%; + border-radius: var(--pagefind-ui-image-border-radius); +} + +.pagefind-modular-list-inner { + flex: 1; + display: flex; + flex-direction: column; + align-items: flex-start; + margin-top: calc(10px * var(--pagefind-ui-scale)); +} + +.pagefind-modular-list-title { + display: inline-block; + font-weight: 700; + font-size: calc(21px * var(--pagefind-ui-scale)); + margin-top: 0; + margin-bottom: 0; +} + +.pagefind-modular-list-link { + color: var(--pagefind-ui-text); + text-decoration: none; +} + +.pagefind-modular-list-link:hover { + text-decoration: underline; +} + +.pagefind-modular-list-excerpt { + display: inline-block; + font-weight: 400; + font-size: calc(16px * var(--pagefind-ui-scale)); + margin-top: calc(4px * var(--pagefind-ui-scale)); + margin-bottom: 0; + min-width: calc(250px * var(--pagefind-ui-scale)); +} + +/* FilterPills */ + +.pagefind-modular-filter-pills-wrapper { + overflow-x: scroll; + padding: 15px 0; +} + +.pagefind-modular-filter-pills { + display: flex; + gap: 6px; +} + +.pagefind-modular-filter-pill { + display: flex; + justify-content: center; + align-items: center; + border: none; + appearance: none; + padding: 0 calc(24px * var(--pagefind-ui-scale)); + background-color: var(--pagefind-ui-background); + color: var(--pagefind-ui-fade); + border: var(--pagefind-ui-border-width) solid var(--pagefind-ui-border); + border-radius: calc(25px * var(--pagefind-ui-scale)); + font-size: calc(18px * var(--pagefind-ui-scale)); + height: calc(50px * var(--pagefind-ui-scale)); + cursor: pointer; + white-space: nowrap; +} + +.pagefind-modular-filter-pill:hover { + border-color: var(--pagefind-ui-primary); +} + +.pagefind-modular-filter-pill[aria-pressed="true"] { + border-color: var(--pagefind-ui-primary); + color: var(--pagefind-ui-primary); +} \ No newline at end of file diff --git a/pagefind/pagefind-modular-ui.js b/pagefind/pagefind-modular-ui.js new file mode 100644 index 0000000000..43f738f01d --- /dev/null +++ b/pagefind/pagefind-modular-ui.js @@ -0,0 +1,8 @@ +(()=>{var b=Object.defineProperty;var w=(i,e)=>{for(var t in e)b(i,t,{get:e[t],enumerable:!0})};var f={};w(f,{FilterPills:()=>h,Input:()=>l,Instance:()=>p,ResultList:()=>a,Summary:()=>o});var r=class i{constructor(e){this.element=document.createElement(e)}id(e){return this.element.id=e,this}class(e){return this.element.classList.add(e),this}attrs(e){for(let[t,s]of Object.entries(e))this.element.setAttribute(t,s);return this}text(e){return this.element.innerText=e,this}html(e){return this.element.innerHTML=e,this}handle(e,t){return this.element.addEventListener(e,t),this}addTo(e){return e instanceof i?e.element.appendChild(this.element):e.appendChild(this.element),this.element}};var T=async(i=100)=>new Promise(e=>setTimeout(e,i)),l=class{constructor(e={}){if(this.inputEl=null,this.clearEl=null,this.instance=null,this.searchID=0,this.debounceTimeoutMs=e.debounceTimeoutMs??300,e.inputElement){if(e.containerElement){console.warn("[Pagefind Input component]: inputElement and containerElement both supplied. Ignoring the container option.");return}this.initExisting(e.inputElement)}else if(e.containerElement)this.initContainer(e.containerElement);else{console.error("[Pagefind Input component]: No selector supplied for containerElement or inputElement");return}this.inputEl.addEventListener("input",async t=>{if(this.instance&&typeof t?.target?.value=="string"){this.updateState(t.target.value);let s=++this.searchID;if(await T(this.debounceTimeoutMs),s!==this.searchID)return null;this.instance?.triggerSearch(t.target.value)}}),this.inputEl.addEventListener("keydown",t=>{t.key==="Escape"&&(++this.searchID,this.inputEl.value="",this.instance?.triggerSearch(""),this.updateState("")),t.key==="Enter"&&t.preventDefault()}),this.inputEl.addEventListener("focus",()=>{this.instance?.triggerLoad()})}initContainer(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind Input component]: No container found for ${e} selector`);return}if(t.tagName==="INPUT")console.warn(`[Pagefind Input component]: Encountered input element for ${e} when a container was expected`),console.warn("[Pagefind Input component]: Treating containerElement option as inputElement and proceeding"),this.initExisting(e);else{t.innerHTML="";let s=0;for(;document.querySelector(`#pfmod-input-${s}`);)s+=1;let n=new r("form").class("pagefind-modular-input-wrapper").attrs({role:"search","aria-label":"Search this site",action:"javascript:void(0);"});new r("label").attrs({for:`pfmod-input-${s}`,"data-pfmod-sr-hidden":"true"}).text("Search this site").addTo(n),this.inputEl=new r("input").id(`pfmod-input-${s}`).class("pagefind-modular-input").attrs({autocapitalize:"none",enterkeyhint:"search"}).addTo(n),this.clearEl=new r("button").class("pagefind-modular-input-clear").attrs({"data-pfmod-suppressed":"true"}).text("Clear").handle("click",()=>{this.inputEl.value="",this.instance.triggerSearch(""),this.updateState("")}).addTo(n),n.addTo(t)}}initExisting(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind Input component]: No input element found for ${e} selector`);return}if(t.tagName!=="INPUT"){console.error(`[Pagefind Input component]: Expected ${e} to be an element`);return}this.inputEl=t}updateState(e){this.clearEl&&(e&&e?.length?this.clearEl.removeAttribute("data-pfmod-suppressed"):this.clearEl.setAttribute("data-pfmod-suppressed","true"))}register(e){this.instance=e,this.instance.on("search",(t,s)=>{this.inputEl&&document.activeElement!==this.inputEl&&(this.inputEl.value=t,this.updateState(t))})}focus(){this.inputEl&&this.inputEl.focus()}};var g=i=>{if(i instanceof Element)return[i];if(Array.isArray(i)&&i.every(e=>e instanceof Element))return i;if(typeof i=="string"||i instanceof String){let e=document.createElement("div");return e.innerHTML=i,[...e.childNodes]}else return console.error(`[Pagefind ResultList component]: Expected template function to return an HTML element or string, got ${typeof i}`),[]},v=()=>{let i=(e=30)=>". ".repeat(Math.floor(10+Math.random()*e));return`
  • +
    +
    +

    ${i(30)}

    +

    ${i(40)}

    +
    +
  • `},y=i=>{let e=new r("li").class("pagefind-modular-list-result"),t=new r("div").class("pagefind-modular-list-thumb").addTo(e);i?.meta?.image&&new r("img").class("pagefind-modular-list-image").attrs({src:i.meta.image,alt:i.meta.image_alt||i.meta.title}).addTo(t);let s=new r("div").class("pagefind-modular-list-inner").addTo(e),n=new r("p").class("pagefind-modular-list-title").addTo(s);return new r("a").class("pagefind-modular-list-link").text(i.meta?.title).attrs({href:i.meta?.url||i.url}).addTo(n),new r("p").class("pagefind-modular-list-excerpt").html(i.excerpt).addTo(s),e.element},E=i=>{if(!(i instanceof HTMLElement))return null;let e=window.getComputedStyle(i).overflowY;return e!=="visible"&&e!=="hidden"?i:E(i.parentNode)},d=class{constructor(e={}){this.rawResult=e.result,this.placeholderNodes=e.placeholderNodes,this.resultFn=e.resultFn,this.intersectionEl=e.intersectionEl,this.result=null,this.waitForIntersection()}waitForIntersection(){if(!this.placeholderNodes?.length)return;let e={root:this.intersectionEl,rootMargin:"0px",threshold:.01};new IntersectionObserver((s,n)=>{this.result===null&&s?.[0]?.isIntersecting&&(this.load(),n.disconnect())},e).observe(this.placeholderNodes[0])}async load(){if(!this.placeholderNodes?.length)return;this.result=await this.rawResult.data();let e=this.resultFn(this.result),t=g(e);for(;this.placeholderNodes.length>1;)this.placeholderNodes.pop().remove();this.placeholderNodes[0].replaceWith(...t)}},a=class{constructor(e){if(this.intersectionEl=document.body,this.containerEl=null,this.results=[],this.placeholderTemplate=e.placeholderTemplate??v,this.resultTemplate=e.resultTemplate??y,e.containerElement)this.initContainer(e.containerElement);else{console.error("[Pagefind ResultList component]: No selector supplied for containerElement");return}}initContainer(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind ResultList component]: No container found for ${e} selector`);return}this.containerEl=t}append(e){for(let t of e)this.containerEl.appendChild(t)}register(e){e.on("results",t=>{this.containerEl&&(this.containerEl.innerHTML="",this.intersectionEl=E(this.containerEl),this.results=t.results.map(s=>{let n=g(this.placeholderTemplate());return this.append(n),new d({result:s,placeholderNodes:n,resultFn:this.resultTemplate,intersectionEl:this.intersectionEl})}))}),e.on("loading",()=>{this.containerEl&&(this.containerEl.innerHTML="")})}};var o=class{constructor(e={}){if(this.containerEl=null,this.defaultMessage=e.defaultMessage??"",this.term="",e.containerElement)this.initContainer(e.containerElement);else{console.error("[Pagefind Summary component]: No selector supplied for containerElement");return}}initContainer(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind Summary component]: No container found for ${e} selector`);return}this.containerEl=t,this.containerEl.innerText=this.defaultMessage}register(e){e.on("search",(t,s)=>{this.term=t}),e.on("results",t=>{if(!this.containerEl||!t)return;if(!this.term){this.containerEl.innerText=this.defaultMessage;return}let s=t?.results?.length??0;this.containerEl.innerText=`${s} result${s===1?"":"s"} for ${this.term}`}),e.on("loading",()=>{this.containerEl&&(this.containerEl.innerText=`Searching for ${this.term}...`)})}};var h=class{constructor(e={}){if(this.instance=null,this.wrapper=null,this.pillContainer=null,this.available={},this.selected=["All"],this.total=0,this.filterMemo="",this.filter=e.filter,this.ordering=e.ordering??null,this.alwaysShow=e.alwaysShow??!1,this.selectMultiple=e.selectMultiple??!1,!this.filter?.length){console.error("[Pagefind FilterPills component]: No filter option supplied, nothing to display");return}if(e.containerElement)this.initContainer(e.containerElement);else{console.error("[Pagefind FilterPills component]: No selector supplied for containerElement");return}}initContainer(e){let t=document.querySelector(e);if(!t){console.error(`[Pagefind FilterPills component]: No container found for ${e} selector`);return}t.innerHTML="";let s=`pagefind_modular_filter_pills_${this.filter}`,n=new r("div").class("pagefind-modular-filter-pills-wrapper").attrs({role:"group","aria-labelledby":s});this.alwaysShow||n.attrs({"data-pfmod-hidden":!0}),new r("div").id(s).class("pagefind-modular-filter-pills-label").attrs({"data-pfmod-sr-hidden":!0}).text(`Filter results by ${this.filter}`).addTo(n),this.pillContainer=new r("div").class("pagefind-modular-filter-pills").addTo(n),this.wrapper=n.addTo(t)}update(){let e=this.available.map(t=>t[0]).join("~");e==this.filterMemo?this.updateExisting():(this.renderNew(),this.filterMemo=e)}pushFilters(){let e=this.selected.filter(t=>t!=="All");this.instance.triggerFilter(this.filter,e)}pillInner(e,t){return this.total?`${e} (${t})`:`${e}`}renderNew(){this.available.forEach(([e,t])=>{new r("button").class("pagefind-modular-filter-pill").html(this.pillInner(e,t)).attrs({"aria-pressed":this.selected.includes(e),type:"button"}).handle("click",()=>{e==="All"?this.selected=["All"]:this.selected.includes(e)?this.selected=this.selected.filter(s=>s!==e):this.selectMultiple?this.selected.push(e):this.selected=[e],this.selected?.length?this.selected?.length>1&&(this.selected=this.selected.filter(s=>s!=="All")):this.selected=["All"],this.update(),this.pushFilters()}).addTo(this.pillContainer)})}updateExisting(){let e=[...this.pillContainer.childNodes];this.available.forEach(([t,s],n)=>{e[n].innerHTML=this.pillInner(t,s),e[n].setAttribute("aria-pressed",this.selected.includes(t))})}register(e){this.instance=e,this.instance.on("filters",t=>{if(!this.pillContainer)return;this.selectMultiple?t=t.available:t=t.total;let s=t[this.filter];if(!s){console.warn(`[Pagefind FilterPills component]: No possible values found for the ${this.filter} filter`);return}this.available=Object.entries(s),Array.isArray(this.ordering)?this.available.sort((n,c)=>{let m=this.ordering.indexOf(n[0]),_=this.ordering.indexOf(c[0]);return(m===-1?1/0:m)-(_===-1?1/0:_)}):this.available.sort((n,c)=>n[0].localeCompare(c[0])),this.available.unshift(["All",this.total]),this.update()}),e.on("results",t=>{this.pillContainer&&(this.total=t?.unfilteredResultCount||0,this.available?.[0]?.[0]==="All"&&(this.available[0][1]=this.total),this.total||this.alwaysShow?this.wrapper.removeAttribute("data-pfmod-hidden"):this.wrapper.setAttribute("data-pfmod-hidden","true"),this.update())})}};var P=async(i=50)=>await new Promise(e=>setTimeout(e,i)),u;try{document?.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"&&(u=new URL(document.currentScript.src).pathname.match(/^(.*\/)(?:pagefind-)?modular-ui.js.*$/)[1])}catch{u="/pagefind/"}var p=class{constructor(e={}){this.__pagefind__=null,this.__initializing__=null,this.__searchID__=0,this.__hooks__={search:[],filters:[],loading:[],results:[]},this.components=[],this.searchTerm="",this.searchFilters={},this.searchResult={},this.availableFilters=null,this.totalFilters=null,this.options={bundlePath:e.bundlePath??u,mergeIndex:e.mergeIndex??[]},delete e.bundlePath,delete e.resetStyles,delete e.processResult,delete e.processTerm,delete e.debounceTimeoutMs,delete e.mergeIndex,delete e.translations,this.pagefindOptions=e}add(e){e?.register?.(this),this.components.push(e)}on(e,t){if(!this.__hooks__[e]){let s=Object.keys(this.__hooks__).join(", ");console.error(`[Pagefind Composable]: Unknown event type ${e}. Supported events: [${s}]`);return}if(typeof t!="function"){console.error(`[Pagefind Composable]: Expected callback to be a function, received ${typeof t}`);return}this.__hooks__[e].push(t)}triggerLoad(){this.__load__()}triggerSearch(e){this.searchTerm=e,this.__dispatch__("search",e,this.searchFilters),this.__search__(e,this.searchFilters)}triggerSearchWithFilters(e,t){this.searchTerm=e,this.searchFilters=t,this.__dispatch__("search",e,t),this.__search__(e,t)}triggerFilters(e){this.searchFilters=e,this.__dispatch__("search",this.searchTerm,e),this.__search__(this.searchTerm,e)}triggerFilter(e,t){this.searchFilters=this.searchFilters||{},this.searchFilters[e]=t,this.__dispatch__("search",this.searchTerm,this.searchFilters),this.__search__(this.searchTerm,this.searchFilters)}__dispatch__(e,...t){this.__hooks__[e]?.forEach(s=>s?.(...t))}async __clear__(){this.__dispatch__("results",{results:[],unfilteredTotalCount:0}),this.availableFilters=await this.__pagefind__.filters(),this.totalFilters=this.availableFilters,this.__dispatch__("filters",{available:this.availableFilters,total:this.totalFilters})}async __search__(e,t){this.__dispatch__("loading"),await this.__load__();let s=++this.__searchID__;if(!e||!e.length)return this.__clear__();let n=await this.__pagefind__.search(e,{filters:t});n&&this.__searchID__===s&&(n.filters&&Object.keys(n.filters)?.length&&(this.availableFilters=n.filters,this.totalFilters=n.totalFilters,this.__dispatch__("filters",{available:this.availableFilters,total:this.totalFilters})),this.searchResult=n,this.__dispatch__("results",this.searchResult))}async __load__(){if(this.__initializing__){for(;!this.__pagefind__;)await P(50);return}if(this.__initializing__=!0,!this.__pagefind__){let e;try{e=await import(`${this.options.bundlePath}pagefind.js`)}catch(t){console.error(t),console.error([`Pagefind couldn't be loaded from ${this.options.bundlePath}pagefind.js`,"You can configure this by passing a bundlePath option to PagefindComposable Instance"].join(` +`)),document?.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?console.error(`[DEBUG: Loaded from ${document.currentScript?.src??"bad script location"}]`):console.error("no known script location")}await e.options(this.pagefindOptions||{});for(let t of this.options.mergeIndex){if(!t.bundlePath)throw new Error("mergeIndex requires a bundlePath parameter");let s=t.bundlePath;delete t.bundlePath,await e.mergeIndex(s,t)}this.__pagefind__=e}this.availableFilters=await this.__pagefind__.filters(),this.totalFilters=this.availableFilters,this.__dispatch__("filters",{available:this.availableFilters,total:this.totalFilters})}};window.PagefindModularUI=f;})(); diff --git a/pagefind/pagefind-ui.css b/pagefind/pagefind-ui.css new file mode 100644 index 0000000000..d7984a98a4 --- /dev/null +++ b/pagefind/pagefind-ui.css @@ -0,0 +1 @@ +.pagefind-ui__result.svelte-j9e30.svelte-j9e30{list-style-type:none;display:flex;align-items:flex-start;gap:min(calc(40px * var(--pagefind-ui-scale)),3%);padding:calc(30px * var(--pagefind-ui-scale)) 0 calc(40px * var(--pagefind-ui-scale));border-top:solid var(--pagefind-ui-border-width) var(--pagefind-ui-border)}.pagefind-ui__result.svelte-j9e30.svelte-j9e30:last-of-type{border-bottom:solid var(--pagefind-ui-border-width) var(--pagefind-ui-border)}.pagefind-ui__result-thumb.svelte-j9e30.svelte-j9e30{width:min(30%,calc((30% - (100px * var(--pagefind-ui-scale))) * 100000));max-width:calc(120px * var(--pagefind-ui-scale));margin-top:calc(10px * var(--pagefind-ui-scale));aspect-ratio:var(--pagefind-ui-image-box-ratio);position:relative}.pagefind-ui__result-image.svelte-j9e30.svelte-j9e30{display:block;position:absolute;left:50%;transform:translate(-50%);font-size:0;width:auto;height:auto;max-width:100%;max-height:100%;border-radius:var(--pagefind-ui-image-border-radius)}.pagefind-ui__result-inner.svelte-j9e30.svelte-j9e30{flex:1;display:flex;flex-direction:column;align-items:flex-start;margin-top:calc(10px * var(--pagefind-ui-scale))}.pagefind-ui__result-title.svelte-j9e30.svelte-j9e30{display:inline-block;font-weight:700;font-size:calc(21px * var(--pagefind-ui-scale));margin-top:0;margin-bottom:0}.pagefind-ui__result-title.svelte-j9e30 .pagefind-ui__result-link.svelte-j9e30{color:var(--pagefind-ui-text);text-decoration:none}.pagefind-ui__result-title.svelte-j9e30 .pagefind-ui__result-link.svelte-j9e30:hover{text-decoration:underline}.pagefind-ui__result-excerpt.svelte-j9e30.svelte-j9e30{display:inline-block;font-weight:400;font-size:calc(16px * var(--pagefind-ui-scale));margin-top:calc(4px * var(--pagefind-ui-scale));margin-bottom:0;min-width:calc(250px * var(--pagefind-ui-scale))}.pagefind-ui__loading.svelte-j9e30.svelte-j9e30{color:var(--pagefind-ui-text);background-color:var(--pagefind-ui-text);border-radius:var(--pagefind-ui-border-radius);opacity:.1;pointer-events:none}.pagefind-ui__result-tags.svelte-j9e30.svelte-j9e30{list-style-type:none;padding:0;display:flex;gap:calc(20px * var(--pagefind-ui-scale));flex-wrap:wrap;margin-top:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__result-tag.svelte-j9e30.svelte-j9e30{padding:calc(4px * var(--pagefind-ui-scale)) calc(8px * var(--pagefind-ui-scale));font-size:calc(14px * var(--pagefind-ui-scale));border-radius:var(--pagefind-ui-border-radius);background-color:var(--pagefind-ui-tag)}.pagefind-ui__result.svelte-4xnkmf.svelte-4xnkmf{list-style-type:none;display:flex;align-items:flex-start;gap:min(calc(40px * var(--pagefind-ui-scale)),3%);padding:calc(30px * var(--pagefind-ui-scale)) 0 calc(40px * var(--pagefind-ui-scale));border-top:solid var(--pagefind-ui-border-width) var(--pagefind-ui-border)}.pagefind-ui__result.svelte-4xnkmf.svelte-4xnkmf:last-of-type{border-bottom:solid var(--pagefind-ui-border-width) var(--pagefind-ui-border)}.pagefind-ui__result-nested.svelte-4xnkmf.svelte-4xnkmf{display:flex;flex-direction:column;padding-left:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__result-nested.svelte-4xnkmf.svelte-4xnkmf:first-of-type{padding-top:calc(10px * var(--pagefind-ui-scale))}.pagefind-ui__result-nested.svelte-4xnkmf .pagefind-ui__result-link.svelte-4xnkmf{font-size:.9em;position:relative}.pagefind-ui__result-nested.svelte-4xnkmf .pagefind-ui__result-link.svelte-4xnkmf:before{content:"\2937 ";position:absolute;top:0;right:calc(100% + .1em)}.pagefind-ui__result-thumb.svelte-4xnkmf.svelte-4xnkmf{width:min(30%,calc((30% - (100px * var(--pagefind-ui-scale))) * 100000));max-width:calc(120px * var(--pagefind-ui-scale));margin-top:calc(10px * var(--pagefind-ui-scale));aspect-ratio:var(--pagefind-ui-image-box-ratio);position:relative}.pagefind-ui__result-image.svelte-4xnkmf.svelte-4xnkmf{display:block;position:absolute;left:50%;transform:translate(-50%);font-size:0;width:auto;height:auto;max-width:100%;max-height:100%;border-radius:var(--pagefind-ui-image-border-radius)}.pagefind-ui__result-inner.svelte-4xnkmf.svelte-4xnkmf{flex:1;display:flex;flex-direction:column;align-items:flex-start;margin-top:calc(10px * var(--pagefind-ui-scale))}.pagefind-ui__result-title.svelte-4xnkmf.svelte-4xnkmf{display:inline-block;font-weight:700;font-size:calc(21px * var(--pagefind-ui-scale));margin-top:0;margin-bottom:0}.pagefind-ui__result-title.svelte-4xnkmf .pagefind-ui__result-link.svelte-4xnkmf{color:var(--pagefind-ui-text);text-decoration:none}.pagefind-ui__result-title.svelte-4xnkmf .pagefind-ui__result-link.svelte-4xnkmf:hover{text-decoration:underline}.pagefind-ui__result-excerpt.svelte-4xnkmf.svelte-4xnkmf{display:inline-block;font-weight:400;font-size:calc(16px * var(--pagefind-ui-scale));margin-top:calc(4px * var(--pagefind-ui-scale));margin-bottom:0;min-width:calc(250px * var(--pagefind-ui-scale))}.pagefind-ui__loading.svelte-4xnkmf.svelte-4xnkmf{color:var(--pagefind-ui-text);background-color:var(--pagefind-ui-text);border-radius:var(--pagefind-ui-border-radius);opacity:.1;pointer-events:none}.pagefind-ui__result-tags.svelte-4xnkmf.svelte-4xnkmf{list-style-type:none;padding:0;display:flex;gap:calc(20px * var(--pagefind-ui-scale));flex-wrap:wrap;margin-top:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__result-tag.svelte-4xnkmf.svelte-4xnkmf{padding:calc(4px * var(--pagefind-ui-scale)) calc(8px * var(--pagefind-ui-scale));font-size:calc(14px * var(--pagefind-ui-scale));border-radius:var(--pagefind-ui-border-radius);background-color:var(--pagefind-ui-tag)}legend.svelte-1v2r7ls.svelte-1v2r7ls{position:absolute;clip:rect(0 0 0 0)}.pagefind-ui__filter-panel.svelte-1v2r7ls.svelte-1v2r7ls{min-width:min(calc(260px * var(--pagefind-ui-scale)),100%);flex:1;display:flex;flex-direction:column;margin-top:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__filter-group.svelte-1v2r7ls.svelte-1v2r7ls{border:0;padding:0}.pagefind-ui__filter-block.svelte-1v2r7ls.svelte-1v2r7ls{padding:0;display:block;border-bottom:solid calc(2px * var(--pagefind-ui-scale)) var(--pagefind-ui-border);padding:calc(20px * var(--pagefind-ui-scale)) 0}.pagefind-ui__filter-name.svelte-1v2r7ls.svelte-1v2r7ls{font-size:calc(16px * var(--pagefind-ui-scale));position:relative;display:flex;align-items:center;list-style:none;font-weight:700;cursor:pointer;height:calc(24px * var(--pagefind-ui-scale))}.pagefind-ui__filter-name.svelte-1v2r7ls.svelte-1v2r7ls::-webkit-details-marker{display:none}.pagefind-ui__filter-name.svelte-1v2r7ls.svelte-1v2r7ls:after{position:absolute;content:"";right:calc(6px * var(--pagefind-ui-scale));top:50%;width:calc(8px * var(--pagefind-ui-scale));height:calc(8px * var(--pagefind-ui-scale));border:solid calc(2px * var(--pagefind-ui-scale)) currentColor;border-right:0;border-top:0;transform:translateY(-70%) rotate(-45deg)}.pagefind-ui__filter-block[open].svelte-1v2r7ls .pagefind-ui__filter-name.svelte-1v2r7ls:after{transform:translateY(-70%) rotate(-225deg)}.pagefind-ui__filter-group.svelte-1v2r7ls.svelte-1v2r7ls{display:flex;flex-direction:column;gap:calc(20px * var(--pagefind-ui-scale));padding-top:calc(30px * var(--pagefind-ui-scale))}.pagefind-ui__filter-value.svelte-1v2r7ls.svelte-1v2r7ls{position:relative;display:flex;align-items:center;gap:calc(8px * var(--pagefind-ui-scale))}.pagefind-ui__filter-value.svelte-1v2r7ls.svelte-1v2r7ls:before{position:absolute;content:"";top:50%;left:calc(8px * var(--pagefind-ui-scale));width:0px;height:0px;border:solid 1px #fff;opacity:0;transform:translate(calc(4.5px * var(--pagefind-ui-scale) * -1),calc(.8px * var(--pagefind-ui-scale))) skew(-5deg) rotate(-45deg);transform-origin:top left;border-top:0;border-right:0;pointer-events:none}.pagefind-ui__filter-value.pagefind-ui__filter-value--checked.svelte-1v2r7ls.svelte-1v2r7ls:before{opacity:1;width:calc(9px * var(--pagefind-ui-scale));height:calc(4px * var(--pagefind-ui-scale));transition:width .1s ease-out .1s,height .1s ease-in}.pagefind-ui__filter-checkbox.svelte-1v2r7ls.svelte-1v2r7ls{margin:0;width:calc(16px * var(--pagefind-ui-scale));height:calc(16px * var(--pagefind-ui-scale));border:solid 1px var(--pagefind-ui-border);appearance:none;-webkit-appearance:none;border-radius:calc(var(--pagefind-ui-border-radius) / 2);background-color:var(--pagefind-ui-background);cursor:pointer}.pagefind-ui__filter-checkbox.svelte-1v2r7ls.svelte-1v2r7ls:checked{background-color:var(--pagefind-ui-primary);border:solid 1px var(--pagefind-ui-primary)}.pagefind-ui__filter-label.svelte-1v2r7ls.svelte-1v2r7ls{cursor:pointer;font-size:calc(16px * var(--pagefind-ui-scale));font-weight:400}.pagefind-ui--reset *:where(:not(html,iframe,canvas,img,svg,video):not(svg *,symbol *)){all:unset;display:revert;outline:revert}.pagefind-ui--reset *,.pagefind-ui--reset *:before,.pagefind-ui--reset *:after{box-sizing:border-box}.pagefind-ui--reset a,.pagefind-ui--reset button{cursor:revert}.pagefind-ui--reset ol,.pagefind-ui--reset ul,.pagefind-ui--reset menu{list-style:none}.pagefind-ui--reset img{max-width:100%}.pagefind-ui--reset table{border-collapse:collapse}.pagefind-ui--reset input,.pagefind-ui--reset textarea{-webkit-user-select:auto}.pagefind-ui--reset textarea{white-space:revert}.pagefind-ui--reset meter{-webkit-appearance:revert;appearance:revert}.pagefind-ui--reset ::placeholder{color:unset}.pagefind-ui--reset :where([hidden]){display:none}.pagefind-ui--reset :where([contenteditable]:not([contenteditable="false"])){-moz-user-modify:read-write;-webkit-user-modify:read-write;overflow-wrap:break-word;-webkit-line-break:after-white-space;-webkit-user-select:auto}.pagefind-ui--reset :where([draggable="true"]){-webkit-user-drag:element}.pagefind-ui--reset mark{all:revert}:root{--pagefind-ui-scale:.8;--pagefind-ui-primary:#393939;--pagefind-ui-text:#393939;--pagefind-ui-background:#ffffff;--pagefind-ui-border:#eeeeee;--pagefind-ui-tag:#eeeeee;--pagefind-ui-border-width:2px;--pagefind-ui-border-radius:8px;--pagefind-ui-image-border-radius:8px;--pagefind-ui-image-box-ratio:3 / 2;--pagefind-ui-font:system, -apple-system, "BlinkMacSystemFont", ".SFNSText-Regular", "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", "Lucida Grande", "Ubuntu", "arial", sans-serif}.pagefind-ui.svelte-e9gkc3{width:100%;color:var(--pagefind-ui-text);font-family:var(--pagefind-ui-font)}.pagefind-ui__hidden.svelte-e9gkc3{display:none!important}.pagefind-ui__suppressed.svelte-e9gkc3{opacity:0;pointer-events:none}.pagefind-ui__form.svelte-e9gkc3{position:relative}.pagefind-ui__form.svelte-e9gkc3:before{background-color:var(--pagefind-ui-text);width:calc(18px * var(--pagefind-ui-scale));height:calc(18px * var(--pagefind-ui-scale));top:calc(23px * var(--pagefind-ui-scale));left:calc(20px * var(--pagefind-ui-scale));content:"";position:absolute;display:block;opacity:.7;-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A");mask-image:url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A");-webkit-mask-size:100%;mask-size:100%;z-index:9;pointer-events:none}.pagefind-ui__search-input.svelte-e9gkc3{height:calc(64px * var(--pagefind-ui-scale));padding:0 calc(70px * var(--pagefind-ui-scale)) 0 calc(54px * var(--pagefind-ui-scale));background-color:var(--pagefind-ui-background);border:var(--pagefind-ui-border-width) solid var(--pagefind-ui-border);border-radius:var(--pagefind-ui-border-radius);font-size:calc(21px * var(--pagefind-ui-scale));position:relative;appearance:none;-webkit-appearance:none;display:flex;width:100%;box-sizing:border-box;font-weight:700}.pagefind-ui__search-input.svelte-e9gkc3::placeholder{opacity:.2}.pagefind-ui__search-clear.svelte-e9gkc3{position:absolute;top:calc(3px * var(--pagefind-ui-scale));right:calc(3px * var(--pagefind-ui-scale));height:calc(58px * var(--pagefind-ui-scale));padding:0 calc(15px * var(--pagefind-ui-scale)) 0 calc(2px * var(--pagefind-ui-scale));color:var(--pagefind-ui-text);font-size:calc(14px * var(--pagefind-ui-scale));cursor:pointer;background-color:var(--pagefind-ui-background);border-radius:var(--pagefind-ui-border-radius)}.pagefind-ui__drawer.svelte-e9gkc3{gap:calc(60px * var(--pagefind-ui-scale));display:flex;flex-direction:row;flex-wrap:wrap}.pagefind-ui__results-area.svelte-e9gkc3{min-width:min(calc(400px * var(--pagefind-ui-scale)),100%);flex:1000;margin-top:calc(20px * var(--pagefind-ui-scale))}.pagefind-ui__results.svelte-e9gkc3{padding:0}.pagefind-ui__message.svelte-e9gkc3{box-sizing:content-box;font-size:calc(16px * var(--pagefind-ui-scale));height:calc(24px * var(--pagefind-ui-scale));padding:calc(20px * var(--pagefind-ui-scale)) 0;display:flex;align-items:center;font-weight:700;margin-top:0}.pagefind-ui__button.svelte-e9gkc3{margin-top:calc(40px * var(--pagefind-ui-scale));border:var(--pagefind-ui-border-width) solid var(--pagefind-ui-border);border-radius:var(--pagefind-ui-border-radius);height:calc(48px * var(--pagefind-ui-scale));padding:0 calc(12px * var(--pagefind-ui-scale));font-size:calc(16px * var(--pagefind-ui-scale));color:var(--pagefind-ui-primary);background:var(--pagefind-ui-background);width:100%;text-align:center;font-weight:700;cursor:pointer}.pagefind-ui__button.svelte-e9gkc3:hover{border-color:var(--pagefind-ui-primary);color:var(--pagefind-ui-primary);background:var(--pagefind-ui-background)} diff --git a/pagefind/pagefind-ui.js b/pagefind/pagefind-ui.js new file mode 100644 index 0000000000..b637f554be --- /dev/null +++ b/pagefind/pagefind-ui.js @@ -0,0 +1,2 @@ +(()=>{var bs=Object.defineProperty;var S=(n,e)=>{for(var t in e)bs(n,t,{get:e[t],enumerable:!0})};function z(){}function ft(n){return n()}function _n(){return Object.create(null)}function G(n){n.forEach(ft)}function $e(n){return typeof n=="function"}function K(n,e){return n!=n?e==e:n!==e||n&&typeof n=="object"||typeof n=="function"}var Qe;function ie(n,e){return Qe||(Qe=document.createElement("a")),Qe.href=e,n===Qe.href}function fn(n){return Object.keys(n).length===0}var dn=typeof window<"u"?window:typeof globalThis<"u"?globalThis:global,de=class{constructor(e){this.options=e,this._listeners="WeakMap"in dn?new WeakMap:void 0}observe(e,t){return this._listeners.set(e,t),this._getObserver().observe(e,this.options),()=>{this._listeners.delete(e),this._observer.unobserve(e)}}_getObserver(){var e;return(e=this._observer)!==null&&e!==void 0?e:this._observer=new ResizeObserver(t=>{var s;for(let r of t)de.entries.set(r.target,r),(s=this._listeners.get(r.target))===null||s===void 0||s(r)})}};de.entries="WeakMap"in dn?new WeakMap:void 0;var hn=!1;function Ts(){hn=!0}function Cs(){hn=!1}function b(n,e){n.appendChild(e)}function y(n,e,t){n.insertBefore(e,t||null)}function k(n){n.parentNode&&n.parentNode.removeChild(n)}function Q(n,e){for(let t=0;tn.removeEventListener(e,t,s)}function E(n,e,t){t==null?n.removeAttribute(e):n.getAttribute(e)!==t&&n.setAttribute(e,t)}function ys(n){return Array.from(n.childNodes)}function N(n,e){e=""+e,n.data!==e&&(n.data=e)}function dt(n,e){n.value=e??""}function B(n,e,t){n.classList[t?"add":"remove"](e)}var et=class{constructor(e=!1){this.is_svg=!1,this.is_svg=e,this.e=this.n=null}c(e){this.h(e)}m(e,t,s=null){this.e||(this.is_svg?this.e=ks(t.nodeName):this.e=C(t.nodeType===11?"TEMPLATE":t.nodeName),this.t=t.tagName!=="TEMPLATE"?t:t.content,this.c(e)),this.i(s)}h(e){this.e.innerHTML=e,this.n=Array.from(this.e.nodeName==="TEMPLATE"?this.e.content.childNodes:this.e.childNodes)}i(e){for(let t=0;tn.indexOf(s)===-1?e.push(s):t.push(s)),t.forEach(s=>s()),re=e}var xe=new Set,ee;function ae(){ee={r:0,c:[],p:ee}}function oe(){ee.r||G(ee.c),ee=ee.p}function D(n,e){n&&n.i&&(xe.delete(n),n.i(e))}function P(n,e,t,s){if(n&&n.o){if(xe.has(n))return;xe.add(n),ee.c.push(()=>{xe.delete(n),s&&(t&&n.d(1),s())}),n.o(e)}else s&&s()}function En(n,e){P(n,1,1,()=>{e.delete(n.key)})}function Rn(n,e,t,s,r,l,i,a,o,h,c,m){let p=n.length,d=l.length,_=p,u={};for(;_--;)u[n[_].key]=_;let f=[],T=new Map,R=new Map,M=[];for(_=d;_--;){let v=m(r,l,_),H=t(v),O=i.get(H);O?s&&M.push(()=>O.p(v,e)):(O=h(H,v),O.c()),T.set(H,f[_]=O),H in u&&R.set(H,Math.abs(_-u[H]))}let U=new Set,X=new Set;function V(v){D(v,1),v.m(a,c),i.set(v.key,v),c=v.first,d--}for(;p&&d;){let v=f[d-1],H=n[p-1],O=v.key,W=H.key;v===H?(c=v.first,p--,d--):T.has(W)?!i.has(O)||U.has(O)?V(v):X.has(W)?p--:R.get(O)>R.get(W)?(X.add(O),V(v)):(U.add(W),p--):(o(H,i),p--)}for(;p--;){let v=n[p];T.has(v.key)||o(v,i)}for(;d;)V(f[d-1]);return G(M),f}var ws=["allowfullscreen","allowpaymentrequest","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","inert","ismap","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected"],ma=new Set([...ws]);function bn(n,e,t){let s=n.$$.props[e];s!==void 0&&(n.$$.bound[s]=t,t(n.$$.ctx[s]))}function tt(n){n&&n.c()}function me(n,e,t,s){let{fragment:r,after_update:l}=n.$$;r&&r.m(e,t),s||_t(()=>{let i=n.$$.on_mount.map(ft).filter($e);n.$$.on_destroy?n.$$.on_destroy.push(...i):G(i),n.$$.on_mount=[]}),l.forEach(_t)}function ue(n,e){let t=n.$$;t.fragment!==null&&(vs(t.after_update),G(t.on_destroy),t.fragment&&t.fragment.d(e),t.on_destroy=t.fragment=null,t.ctx=[])}function Hs(n,e){n.$$.dirty[0]===-1&&(se.push(n),Ms(),n.$$.dirty.fill(0)),n.$$.dirty[e/31|0]|=1<{let _=d.length?d[0]:p;return h.ctx&&r(h.ctx[m],h.ctx[m]=_)&&(!h.skip_bound&&h.bound[m]&&h.bound[m](_),c&&Hs(n,m)),p}):[],h.update(),c=!0,G(h.before_update),h.fragment=s?s(h.ctx):!1,e.target){if(e.hydrate){Ts();let m=ys(e.target);h.fragment&&h.fragment.l(m),m.forEach(k)}else h.fragment&&h.fragment.c();e.intro&&D(n.$$.fragment),me(n,e.target,e.anchor,e.customElement),Cs(),gn()}fe(o)}var Fs;typeof HTMLElement=="function"&&(Fs=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){let{on_mount:n}=this.$$;this.$$.on_disconnect=n.map(ft).filter($e);for(let e in this.$$.slotted)this.appendChild(this.$$.slotted[e])}attributeChangedCallback(n,e,t){this[n]=t}disconnectedCallback(){G(this.$$.on_disconnect)}$destroy(){ue(this,1),this.$destroy=z}$on(n,e){if(!$e(e))return z;let t=this.$$.callbacks[n]||(this.$$.callbacks[n]=[]);return t.push(e),()=>{let s=t.indexOf(e);s!==-1&&t.splice(s,1)}}$set(n){this.$$set&&!fn(n)&&(this.$$.skip_bound=!0,this.$$set(n),this.$$.skip_bound=!1)}});var q=class{$destroy(){ue(this,1),this.$destroy=z}$on(e,t){if(!$e(t))return z;let s=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return s.push(t),()=>{let r=s.indexOf(t);r!==-1&&s.splice(r,1)}}$set(e){this.$$set&&!fn(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}};function I(n){let e=typeof n=="string"?n.charCodeAt(0):n;return e>=97&&e<=122||e>=65&&e<=90}function $(n){let e=typeof n=="string"?n.charCodeAt(0):n;return e>=48&&e<=57}function Z(n){return I(n)||$(n)}var Tn=["art-lojban","cel-gaulish","no-bok","no-nyn","zh-guoyu","zh-hakka","zh-min","zh-min-nan","zh-xiang"];var pt={"en-gb-oed":"en-GB-oxendict","i-ami":"ami","i-bnn":"bnn","i-default":null,"i-enochian":null,"i-hak":"hak","i-klingon":"tlh","i-lux":"lb","i-mingo":null,"i-navajo":"nv","i-pwn":"pwn","i-tao":"tao","i-tay":"tay","i-tsu":"tsu","sgn-be-fr":"sfb","sgn-be-nl":"vgt","sgn-ch-de":"sgg","art-lojban":"jbo","cel-gaulish":null,"no-bok":"nb","no-nyn":"nn","zh-guoyu":"cmn","zh-hakka":"hak","zh-min":null,"zh-min-nan":"nan","zh-xiang":"hsn"};var Ns={}.hasOwnProperty;function nt(n,e={}){let t=Cn(),s=String(n),r=s.toLowerCase(),l=0;if(n==null)throw new Error("Expected string, got `"+n+"`");if(Ns.call(pt,r)){let a=pt[r];return(e.normalize===void 0||e.normalize===null||e.normalize)&&typeof a=="string"?nt(a):(t[Tn.includes(r)?"regular":"irregular"]=s,t)}for(;I(r.charCodeAt(l))&&l<9;)l++;if(l>1&&l<9){if(t.language=s.slice(0,l),l<4){let a=0;for(;r.charCodeAt(l)===45&&I(r.charCodeAt(l+1))&&I(r.charCodeAt(l+2))&&I(r.charCodeAt(l+3))&&!I(r.charCodeAt(l+4));){if(a>2)return i(l,3,"Too many extended language subtags, expected at most 3 subtags");t.extendedLanguageSubtags.push(s.slice(l+1,l+4)),l+=4,a++}}for(r.charCodeAt(l)===45&&I(r.charCodeAt(l+1))&&I(r.charCodeAt(l+2))&&I(r.charCodeAt(l+3))&&I(r.charCodeAt(l+4))&&!I(r.charCodeAt(l+5))&&(t.script=s.slice(l+1,l+5),l+=5),r.charCodeAt(l)===45&&(I(r.charCodeAt(l+1))&&I(r.charCodeAt(l+2))&&!I(r.charCodeAt(l+3))?(t.region=s.slice(l+1,l+3),l+=3):$(r.charCodeAt(l+1))&&$(r.charCodeAt(l+2))&&$(r.charCodeAt(l+3))&&!$(r.charCodeAt(l+4))&&(t.region=s.slice(l+1,l+4),l+=4));r.charCodeAt(l)===45;){let a=l+1,o=a;for(;Z(r.charCodeAt(o));){if(o-a>7)return i(o,1,"Too long variant, expected at most 8 characters");o++}if(o-a>4||o-a>3&&$(r.charCodeAt(a)))t.variants.push(s.slice(a,o)),l=o;else break}for(;r.charCodeAt(l)===45&&!(r.charCodeAt(l+1)===120||!Z(r.charCodeAt(l+1))||r.charCodeAt(l+2)!==45||!Z(r.charCodeAt(l+3)));){let a=l+2,o=0;for(;r.charCodeAt(a)===45&&Z(r.charCodeAt(a+1))&&Z(r.charCodeAt(a+2));){let h=a+1;for(a=h+2,o++;Z(r.charCodeAt(a));){if(a-h>7)return i(a,2,"Too long extension, expected at most 8 characters");a++}}if(!o)return i(a,4,"Empty extension, extensions must have at least 2 characters of content");t.extensions.push({singleton:s.charAt(l+1),extensions:s.slice(l+3,a).split("-")}),l=a}}else l=0;if(l===0&&r.charCodeAt(l)===120||r.charCodeAt(l)===45&&r.charCodeAt(l+1)===120){l=l?l+2:1;let a=l;for(;r.charCodeAt(a)===45&&Z(r.charCodeAt(a+1));){let o=l+1;for(a=o;Z(r.charCodeAt(a));){if(a-o>7)return i(a,5,"Too long private-use area, expected at most 8 characters");a++}t.privateuse.push(s.slice(l+1,a)),l=a}}if(l!==s.length)return i(l,6,"Found superfluous content after tag");return t;function i(a,o,h){return e.warning&&e.warning(h,o,a),e.forgiving?t:Cn()}}function Cn(){return{language:null,extendedLanguageSubtags:[],script:null,region:null,variants:[],extensions:[],privateuse:[],irregular:null,regular:null}}function kn(n,e,t){let s=n.slice();return s[8]=e[t][0],s[9]=e[t][1],s}function Os(n){let e,t,s,r,l,i=n[0]&&yn(n);return{c(){i&&i.c(),e=A(),t=C("div"),s=C("p"),s.textContent=`${n[3](30)}`,r=A(),l=C("p"),l.textContent=`${n[3](40)}`,E(s,"class","pagefind-ui__result-title pagefind-ui__loading svelte-j9e30"),E(l,"class","pagefind-ui__result-excerpt pagefind-ui__loading svelte-j9e30"),E(t,"class","pagefind-ui__result-inner svelte-j9e30")},m(a,o){i&&i.m(a,o),y(a,e,o),y(a,t,o),b(t,s),b(t,r),b(t,l)},p(a,o){a[0]?i||(i=yn(a),i.c(),i.m(e.parentNode,e)):i&&(i.d(1),i=null)},d(a){i&&i.d(a),a&&k(e),a&&k(t)}}}function js(n){let e,t,s,r,l=n[1].meta?.title+"",i,a,o,h,c=n[1].excerpt+"",m,p=n[0]&&Sn(n),d=n[2].length&&An(n);return{c(){p&&p.c(),e=A(),t=C("div"),s=C("p"),r=C("a"),i=w(l),o=A(),h=C("p"),m=A(),d&&d.c(),E(r,"class","pagefind-ui__result-link svelte-j9e30"),E(r,"href",a=n[1].meta?.url||n[1].url),E(s,"class","pagefind-ui__result-title svelte-j9e30"),E(h,"class","pagefind-ui__result-excerpt svelte-j9e30"),E(t,"class","pagefind-ui__result-inner svelte-j9e30")},m(_,u){p&&p.m(_,u),y(_,e,u),y(_,t,u),b(t,s),b(s,r),b(r,i),b(t,o),b(t,h),h.innerHTML=c,b(t,m),d&&d.m(t,null)},p(_,u){_[0]?p?p.p(_,u):(p=Sn(_),p.c(),p.m(e.parentNode,e)):p&&(p.d(1),p=null),u&2&&l!==(l=_[1].meta?.title+"")&&N(i,l),u&2&&a!==(a=_[1].meta?.url||_[1].url)&&E(r,"href",a),u&2&&c!==(c=_[1].excerpt+"")&&(h.innerHTML=c),_[2].length?d?d.p(_,u):(d=An(_),d.c(),d.m(t,null)):d&&(d.d(1),d=null)},d(_){p&&p.d(_),_&&k(e),_&&k(t),d&&d.d()}}}function yn(n){let e;return{c(){e=C("div"),E(e,"class","pagefind-ui__result-thumb pagefind-ui__loading svelte-j9e30")},m(t,s){y(t,e,s)},d(t){t&&k(e)}}}function Sn(n){let e,t=n[1].meta.image&&Mn(n);return{c(){e=C("div"),t&&t.c(),E(e,"class","pagefind-ui__result-thumb svelte-j9e30")},m(s,r){y(s,e,r),t&&t.m(e,null)},p(s,r){s[1].meta.image?t?t.p(s,r):(t=Mn(s),t.c(),t.m(e,null)):t&&(t.d(1),t=null)},d(s){s&&k(e),t&&t.d()}}}function Mn(n){let e,t,s;return{c(){e=C("img"),E(e,"class","pagefind-ui__result-image svelte-j9e30"),ie(e.src,t=n[1].meta?.image)||E(e,"src",t),E(e,"alt",s=n[1].meta?.image_alt||n[1].meta?.title)},m(r,l){y(r,e,l)},p(r,l){l&2&&!ie(e.src,t=r[1].meta?.image)&&E(e,"src",t),l&2&&s!==(s=r[1].meta?.image_alt||r[1].meta?.title)&&E(e,"alt",s)},d(r){r&&k(e)}}}function An(n){let e,t=n[2],s=[];for(let r=0;rn.toLocaleUpperCase();function Ds(n,e,t){let{show_images:s=!0}=e,{process_result:r=null}=e,{result:l={data:async()=>{}}}=e,i=["title","image","image_alt","url"],a,o=[],h=async m=>{t(1,a=await m.data()),t(1,a=r?.(a)??a),t(2,o=Object.entries(a.meta).filter(([p])=>!i.includes(p)))},c=(m=30)=>". ".repeat(Math.floor(10+Math.random()*m));return n.$$set=m=>{"show_images"in m&&t(0,s=m.show_images),"process_result"in m&&t(4,r=m.process_result),"result"in m&&t(5,l=m.result)},n.$$.update=()=>{if(n.$$.dirty&32)e:h(l)},[s,a,o,c,r,l]}var gt=class extends q{constructor(e){super(),Y(this,e,Ds,zs,K,{show_images:0,process_result:4,result:5})}},Hn=gt;function Fn(n,e,t){let s=n.slice();return s[11]=e[t][0],s[12]=e[t][1],s}function Nn(n,e,t){let s=n.slice();return s[15]=e[t],s}function Us(n){let e,t,s,r,l,i=n[0]&&On(n);return{c(){i&&i.c(),e=A(),t=C("div"),s=C("p"),s.textContent=`${n[5](30)}`,r=A(),l=C("p"),l.textContent=`${n[5](40)}`,E(s,"class","pagefind-ui__result-title pagefind-ui__loading svelte-4xnkmf"),E(l,"class","pagefind-ui__result-excerpt pagefind-ui__loading svelte-4xnkmf"),E(t,"class","pagefind-ui__result-inner svelte-4xnkmf")},m(a,o){i&&i.m(a,o),y(a,e,o),y(a,t,o),b(t,s),b(t,r),b(t,l)},p(a,o){a[0]?i||(i=On(a),i.c(),i.m(e.parentNode,e)):i&&(i.d(1),i=null)},d(a){i&&i.d(a),a&&k(e),a&&k(t)}}}function Is(n){let e,t,s,r,l=n[1].meta?.title+"",i,a,o,h,c,m=n[0]&&jn(n),p=n[4]&&Dn(n),d=n[3],_=[];for(let f=0;fn.toLocaleUpperCase();function Ls(n,e,t){let{show_images:s=!0}=e,{process_result:r=null}=e,{result:l={data:async()=>{}}}=e,i=["title","image","image_alt","url"],a,o=[],h=[],c=!1,m=(_,u)=>{if(_.length<=u)return _;let f=[..._].sort((T,R)=>R.locations.length-T.locations.length).slice(0,3).map(T=>T.url);return _.filter(T=>f.includes(T.url))},p=async _=>{t(1,a=await _.data()),t(1,a=r?.(a)??a),t(2,o=Object.entries(a.meta).filter(([u])=>!i.includes(u))),Array.isArray(a.sub_results)&&(t(4,c=a.sub_results?.[0]?.url===(a.meta?.url||a.url)),c?t(3,h=m(a.sub_results.slice(1),3)):t(3,h=m([...a.sub_results],3)))},d=(_=30)=>". ".repeat(Math.floor(10+Math.random()*_));return n.$$set=_=>{"show_images"in _&&t(0,s=_.show_images),"process_result"in _&&t(6,r=_.process_result),"result"in _&&t(7,l=_.result)},n.$$.update=()=>{if(n.$$.dirty&128)e:p(l)},[s,a,o,h,c,d,r,l]}var Et=class extends q{constructor(e){super(),Y(this,e,Ls,Ps,K,{show_images:0,process_result:6,result:7})}},qn=Et;function Bn(n,e,t){let s=n.slice();return s[10]=e[t][0],s[11]=e[t][1],s[12]=e,s[13]=t,s}function Vn(n,e,t){let s=n.slice();return s[14]=e[t][0],s[15]=e[t][1],s[16]=e,s[17]=t,s}function Wn(n){let e,t,s=n[4]("filters_label",n[5],n[6])+"",r,l,i=Object.entries(n[1]),a=[];for(let o=0;on.toLocaleUpperCase(),Zn=n=>n.toLowerCase();function Bs(n,e,t){let{available_filters:s=null}=e,{show_empty_filters:r=!0}=e,{open_filters:l=[]}=e,{translate:i=()=>""}=e,{automatic_translations:a={}}=e,{translations:o={}}=e,{selected_filters:h={}}=e,c=!1,m=!1;function p(d,_){h[`${d}:${_}`]=this.checked,t(0,h)}return n.$$set=d=>{"available_filters"in d&&t(1,s=d.available_filters),"show_empty_filters"in d&&t(2,r=d.show_empty_filters),"open_filters"in d&&t(3,l=d.open_filters),"translate"in d&&t(4,i=d.translate),"automatic_translations"in d&&t(5,a=d.automatic_translations),"translations"in d&&t(6,o=d.translations),"selected_filters"in d&&t(0,h=d.selected_filters)},n.$$.update=()=>{if(n.$$.dirty&258){e:if(s&&!c){t(8,c=!0);let d=Object.entries(s||{});d.length===1&&Object.entries(d[0][1])?.length<=6&&t(7,m=!0)}}},[h,s,r,l,i,a,o,m,c,p]}var Rt=class extends q{constructor(e){super(),Y(this,e,Bs,qs,K,{available_filters:1,show_empty_filters:2,open_filters:3,translate:4,automatic_translations:5,translations:6,selected_filters:0})}},Xn=Rt;var bt={};S(bt,{comments:()=>Ws,default:()=>Js,direction:()=>Gs,strings:()=>Ks,thanks_to:()=>Vs});var Vs="Jan Claasen ",Ws="",Gs="ltr",Ks={placeholder:"Soek",clear_search:"Opruim",load_more:"Laai nog resultate",search_label:"Soek hierdie webwerf",filters_label:"Filters",zero_results:"Geen resultate vir [SEARCH_TERM]",many_results:"[COUNT] resultate vir [SEARCH_TERM]",one_result:"[COUNT] resultate vir [SEARCH_TERM]",alt_search:"Geen resultate vir [SEARCH_TERM]. Toon resultate vir [DIFFERENT_TERM] in plaas daarvan",search_suggestion:"Geen resultate vir [SEARCH_TERM]. Probeer eerder een van die volgende terme:",searching:"Soek vir [SEARCH_TERM]"},Js={thanks_to:Vs,comments:Ws,direction:Gs,strings:Ks};var Tt={};S(Tt,{comments:()=>Zs,default:()=>xs,direction:()=>Xs,strings:()=>Qs,thanks_to:()=>Ys});var Ys="Maruf Alom ",Zs="",Xs="ltr",Qs={placeholder:"\u0985\u09A8\u09C1\u09B8\u09A8\u09CD\u09A7\u09BE\u09A8 \u0995\u09B0\u09C1\u09A8",clear_search:"\u09AE\u09C1\u099B\u09C7 \u09AB\u09C7\u09B2\u09C1\u09A8",load_more:"\u0986\u09B0\u09CB \u09AB\u09B2\u09BE\u09AB\u09B2 \u09A6\u09C7\u0996\u09C1\u09A8",search_label:"\u098F\u0987 \u0993\u09DF\u09C7\u09AC\u09B8\u09BE\u0987\u099F\u09C7 \u0985\u09A8\u09C1\u09B8\u09A8\u09CD\u09A7\u09BE\u09A8 \u0995\u09B0\u09C1\u09A8",filters_label:"\u09AB\u09BF\u09B2\u09CD\u099F\u09BE\u09B0",zero_results:"[SEARCH_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF \u0995\u09BF\u099B\u09C1 \u0996\u09C1\u0981\u099C\u09C7 \u09AA\u09BE\u0993\u09DF\u09BE \u09AF\u09BE\u09DF\u09A8\u09BF",many_results:"[COUNT]-\u099F\u09BF \u09AB\u09B2\u09BE\u09AB\u09B2 \u09AA\u09BE\u0993\u09DF\u09BE \u0997\u09BF\u09DF\u09C7\u099B\u09C7 [SEARCH_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF",one_result:"[COUNT]-\u099F\u09BF \u09AB\u09B2\u09BE\u09AB\u09B2 \u09AA\u09BE\u0993\u09DF\u09BE \u0997\u09BF\u09DF\u09C7\u099B\u09C7 [SEARCH_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF",alt_search:"\u0995\u09CB\u09A8 \u0995\u09BF\u099B\u09C1 \u0996\u09C1\u0981\u099C\u09C7 \u09AA\u09BE\u0993\u09DF\u09BE \u09AF\u09BE\u09DF\u09A8\u09BF [SEARCH_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF. \u09AA\u09B0\u09BF\u09AC\u09B0\u09CD\u09A4\u09C7 [DIFFERENT_TERM] \u098F\u09B0 \u099C\u09A8\u09CD\u09AF \u09A6\u09C7\u0996\u09BE\u09A8\u09CB \u09B9\u099A\u09CD\u099B\u09C7",search_suggestion:"\u0995\u09CB\u09A8 \u0995\u09BF\u099B\u09C1 \u0996\u09C1\u0981\u099C\u09C7 \u09AA\u09BE\u0993\u09DF\u09BE \u09AF\u09BE\u09DF\u09A8\u09BF [SEARCH_TERM] \u098F\u09B0 \u09AC\u09BF\u09B7\u09DF\u09C7. \u09A8\u09BF\u09A8\u09CD\u09AE\u09C7\u09B0 \u09AC\u09BF\u09B7\u09DF\u09AC\u09B8\u09CD\u09A4\u09C1 \u0996\u09C1\u0981\u099C\u09C7 \u09A6\u09C7\u0996\u09C1\u09A8:",searching:"\u0985\u09A8\u09C1\u09B8\u09A8\u09CD\u09A7\u09BE\u09A8 \u099A\u09B2\u099B\u09C7 [SEARCH_TERM]..."},xs={thanks_to:Ys,comments:Zs,direction:Xs,strings:Qs};var Ct={};S(Ct,{comments:()=>er,default:()=>sr,direction:()=>tr,strings:()=>nr,thanks_to:()=>$s});var $s="Pablo Villaverde ",er="",tr="ltr",nr={placeholder:"Cerca",clear_search:"Netejar",load_more:"Veure m\xE9es resultats",search_label:"Cerca en aquest lloc",filters_label:"Filtres",zero_results:"No es van trobar resultats per [SEARCH_TERM]",many_results:"[COUNT] resultats trobats per [SEARCH_TERM]",one_result:"[COUNT] resultat trobat per [SEARCH_TERM]",alt_search:"No es van trobar resultats per [SEARCH_TERM]. Mostrant al seu lloc resultats per [DIFFERENT_TERM]",search_suggestion:"No es van trobar resultats per [SEARCH_TERM]. Proveu una de les cerques seg\xFCents:",searching:"Cercant [SEARCH_TERM]..."},sr={thanks_to:$s,comments:er,direction:tr,strings:nr};var kt={};S(kt,{comments:()=>lr,default:()=>or,direction:()=>ir,strings:()=>ar,thanks_to:()=>rr});var rr="Dalibor Hon ",lr="",ir="ltr",ar={placeholder:"Hledat",clear_search:"Smazat",load_more:"Na\u010D\xEDst dal\u0161\xED v\xFDsledky",search_label:"Prohledat tuto str\xE1nku",filters_label:"Filtry",zero_results:"\u017D\xE1dn\xE9 v\xFDsledky pro [SEARCH_TERM]",many_results:"[COUNT] v\xFDsledk\u016F pro [SEARCH_TERM]",one_result:"[COUNT] v\xFDsledek pro [SEARCH_TERM]",alt_search:"\u017D\xE1dn\xE9 v\xFDsledky pro [SEARCH_TERM]. Zobrazuj\xED se v\xFDsledky pro [DIFFERENT_TERM]",search_suggestion:"\u017D\xE1dn\xE9 v\xFDsledky pro [SEARCH_TERM]. Souvisej\xEDc\xED v\xFDsledky hled\xE1n\xED:",searching:"Hled\xE1m [SEARCH_TERM]..."},or={thanks_to:rr,comments:lr,direction:ir,strings:ar};var yt={};S(yt,{comments:()=>cr,default:()=>dr,direction:()=>_r,strings:()=>fr,thanks_to:()=>ur});var ur="Jonas Smedegaard ",cr="",_r="ltr",fr={placeholder:"S\xF8g",clear_search:"Nulstil",load_more:"Indl\xE6s flere resultater",search_label:"S\xF8g p\xE5 dette website",filters_label:"Filtre",zero_results:"Ingen resultater for [SEARCH_TERM]",many_results:"[COUNT] resultater for [SEARCH_TERM]",one_result:"[COUNT] resultat for [SEARCH_TERM]",alt_search:"Ingen resultater for [SEARCH_TERM]. Viser resultater for [DIFFERENT_TERM] i stedet",search_suggestion:"Ingen resultater for [SEARCH_TERM]. Pr\xF8v et af disse s\xF8geord i stedet:",searching:"S\xF8ger efter [SEARCH_TERM]..."},dr={thanks_to:ur,comments:cr,direction:_r,strings:fr};var St={};S(St,{comments:()=>mr,default:()=>Er,direction:()=>pr,strings:()=>gr,thanks_to:()=>hr});var hr="Jan Claasen ",mr="",pr="ltr",gr={placeholder:"Suche",clear_search:"L\xF6schen",load_more:"Mehr Ergebnisse laden",search_label:"Suche diese Seite",filters_label:"Filter",zero_results:"Keine Ergebnisse f\xFCr [SEARCH_TERM]",many_results:"[COUNT] Ergebnisse f\xFCr [SEARCH_TERM]",one_result:"[COUNT] Ergebnis f\xFCr [SEARCH_TERM]",alt_search:"Keine Ergebnisse f\xFCr [SEARCH_TERM]. Stattdessen werden Ergebnisse f\xFCr [DIFFERENT_TERM] angezeigt",search_suggestion:"Keine Ergebnisse f\xFCr [SEARCH_TERM]. Versuchen Sie eine der folgenden Suchen:",searching:"Suche f\xFCr [SEARCH_TERM]"},Er={thanks_to:hr,comments:mr,direction:pr,strings:gr};var Mt={};S(Mt,{comments:()=>br,default:()=>kr,direction:()=>Tr,strings:()=>Cr,thanks_to:()=>Rr});var Rr="Liam Bigelow ",br="",Tr="ltr",Cr={placeholder:"Search",clear_search:"Clear",load_more:"Load more results",search_label:"Search this site",filters_label:"Filters",zero_results:"No results for [SEARCH_TERM]",many_results:"[COUNT] results for [SEARCH_TERM]",one_result:"[COUNT] result for [SEARCH_TERM]",alt_search:"No results for [SEARCH_TERM]. Showing results for [DIFFERENT_TERM] instead",search_suggestion:"No results for [SEARCH_TERM]. Try one of the following searches:",searching:"Searching for [SEARCH_TERM]..."},kr={thanks_to:Rr,comments:br,direction:Tr,strings:Cr};var At={};S(At,{comments:()=>Sr,default:()=>vr,direction:()=>Mr,strings:()=>Ar,thanks_to:()=>yr});var yr="Pablo Villaverde ",Sr="",Mr="ltr",Ar={placeholder:"Buscar",clear_search:"Limpiar",load_more:"Ver m\xE1s resultados",search_label:"Buscar en este sitio",filters_label:"Filtros",zero_results:"No se encontraron resultados para [SEARCH_TERM]",many_results:"[COUNT] resultados encontrados para [SEARCH_TERM]",one_result:"[COUNT] resultado encontrado para [SEARCH_TERM]",alt_search:"No se encontraron resultados para [SEARCH_TERM]. Mostrando en su lugar resultados para [DIFFERENT_TERM]",search_suggestion:"No se encontraron resultados para [SEARCH_TERM]. Prueba una de las siguientes b\xFAsquedas:",searching:"Buscando [SEARCH_TERM]..."},vr={thanks_to:yr,comments:Sr,direction:Mr,strings:Ar};var vt={};S(vt,{comments:()=>Hr,default:()=>Or,direction:()=>Fr,strings:()=>Nr,thanks_to:()=>wr});var wr="Valtteri Laitinen ",Hr="",Fr="ltr",Nr={placeholder:"Haku",clear_search:"Tyhjenn\xE4",load_more:"Lataa lis\xE4\xE4 tuloksia",search_label:"Hae t\xE4lt\xE4 sivustolta",filters_label:"Suodattimet",zero_results:"Ei tuloksia haulle [SEARCH_TERM]",many_results:"[COUNT] tulosta haulle [SEARCH_TERM]",one_result:"[COUNT] tulos haulle [SEARCH_TERM]",alt_search:"Ei tuloksia haulle [SEARCH_TERM]. N\xE4ytet\xE4\xE4n tulokset sen sijaan haulle [DIFFERENT_TERM]",search_suggestion:"Ei tuloksia haulle [SEARCH_TERM]. Kokeile jotain seuraavista:",searching:"Haetaan [SEARCH_TERM]..."},Or={thanks_to:wr,comments:Hr,direction:Fr,strings:Nr};var wt={};S(wt,{comments:()=>zr,default:()=>Ir,direction:()=>Dr,strings:()=>Ur,thanks_to:()=>jr});var jr="Nicolas Friedli ",zr="",Dr="ltr",Ur={placeholder:"Rechercher",clear_search:"Nettoyer",load_more:"Charger plus de r\xE9sultats",search_label:"Recherche sur ce site",filters_label:"Filtres",zero_results:"Pas de r\xE9sultat pour [SEARCH_TERM]",many_results:"[COUNT] r\xE9sultats pour [SEARCH_TERM]",one_result:"[COUNT] r\xE9sultat pour [SEARCH_TERM]",alt_search:"Pas de r\xE9sultat pour [SEARCH_TERM]. Montre les r\xE9sultats pour [DIFFERENT_TERM] \xE0 la place",search_suggestion:"Pas de r\xE9sultat pour [SEARCH_TERM]. Essayer une des recherches suivantes:",searching:"Recherche [SEARCH_TERM]..."},Ir={thanks_to:jr,comments:zr,direction:Dr,strings:Ur};var Ht={};S(Ht,{comments:()=>Lr,default:()=>Vr,direction:()=>qr,strings:()=>Br,thanks_to:()=>Pr});var Pr="Pablo Villaverde ",Lr="",qr="ltr",Br={placeholder:"Buscar",clear_search:"Limpar",load_more:"Ver m\xE1is resultados",search_label:"Buscar neste sitio",filters_label:"Filtros",zero_results:"Non se atoparon resultados para [SEARCH_TERM]",many_results:"[COUNT] resultados atopados para [SEARCH_TERM]",one_result:"[COUNT] resultado atopado para [SEARCH_TERM]",alt_search:"Non se atoparon resultados para [SEARCH_TERM]. Amosando no seu lugar resultados para [DIFFERENT_TERM]",search_suggestion:"Non se atoparon resultados para [SEARCH_TERM]. Probe unha das seguintes pesquisas:",searching:"Buscando [SEARCH_TERM]..."},Vr={thanks_to:Pr,comments:Lr,direction:qr,strings:Br};var Ft={};S(Ft,{comments:()=>Gr,default:()=>Yr,direction:()=>Kr,strings:()=>Jr,thanks_to:()=>Wr});var Wr="Amit Yadav ",Gr="",Kr="ltr",Jr={placeholder:"\u0916\u094B\u091C\u0947\u0902",clear_search:"\u0938\u093E\u092B \u0915\u0930\u0947\u0902",load_more:"\u0914\u0930 \u0905\u0927\u093F\u0915 \u092A\u0930\u093F\u0923\u093E\u092E \u0932\u094B\u0921 \u0915\u0930\u0947\u0902",search_label:"\u0907\u0938 \u0938\u093E\u0907\u091F \u092E\u0947\u0902 \u0916\u094B\u091C\u0947\u0902",filters_label:"\u092B\u093C\u093F\u0932\u094D\u091F\u0930",zero_results:"\u0915\u094B\u0908 \u092A\u0930\u093F\u0923\u093E\u092E [SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E",many_results:"[COUNT] \u092A\u0930\u093F\u0923\u093E\u092E [SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u092E\u093F\u0932\u0947",one_result:"[COUNT] \u092A\u0930\u093F\u0923\u093E\u092E [SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u092E\u093F\u0932\u093E",alt_search:"[SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u0915\u094B\u0908 \u092A\u0930\u093F\u0923\u093E\u092E \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E\u0964 \u0907\u0938\u0915\u0947 \u092C\u091C\u093E\u092F [DIFFERENT_TERM] \u0915\u0947 \u0932\u093F\u090F \u092A\u0930\u093F\u0923\u093E\u092E \u0926\u093F\u0916\u093E \u0930\u0939\u093E \u0939\u0948",search_suggestion:"[SEARCH_TERM] \u0915\u0947 \u0932\u093F\u090F \u0915\u094B\u0908 \u092A\u0930\u093F\u0923\u093E\u092E \u0928\u0939\u0940\u0902 \u092E\u093F\u0932\u093E\u0964 \u0928\u093F\u092E\u094D\u0928\u0932\u093F\u0916\u093F\u0924 \u0916\u094B\u091C\u094B\u0902 \u092E\u0947\u0902 \u0938\u0947 \u0915\u094B\u0908 \u090F\u0915 \u0906\u091C\u093C\u092E\u093E\u090F\u0902:",searching:"[SEARCH_TERM] \u0915\u0940 \u0916\u094B\u091C \u0915\u0940 \u091C\u093E \u0930\u0939\u0940 \u0939\u0948..."},Yr={thanks_to:Wr,comments:Gr,direction:Kr,strings:Jr};var Nt={};S(Nt,{comments:()=>Xr,default:()=>$r,direction:()=>Qr,strings:()=>xr,thanks_to:()=>Zr});var Zr="Diomed ",Xr="",Qr="ltr",xr={placeholder:"Tra\u017Ei",clear_search:"O\u010Disti",load_more:"U\u010Ditaj vi\u0161e rezultata",search_label:"Pretra\u017Ei ovu stranicu",filters_label:"Filteri",zero_results:"Nema rezultata za [SEARCH_TERM]",many_results:"[COUNT] rezultata za [SEARCH_TERM]",one_result:"[COUNT] rezultat za [SEARCH_TERM]",alt_search:"Nema rezultata za [SEARCH_TERM]. Prikazujem rezultate za [DIFFERENT_TERM]",search_suggestion:"Nema rezultata za [SEARCH_TERM]. Poku\u0161aj s jednom od ovih pretraga:",searching:"Pretra\u017Eujem [SEARCH_TERM]..."},$r={thanks_to:Zr,comments:Xr,direction:Qr,strings:xr};var Ot={};S(Ot,{comments:()=>tl,default:()=>rl,direction:()=>nl,strings:()=>sl,thanks_to:()=>el});var el="Adam Laki ",tl="",nl="ltr",sl={placeholder:"Keres\xE9s",clear_search:"T\xF6rl\xE9s",load_more:"Tov\xE1bbi tal\xE1latok bet\xF6lt\xE9se",search_label:"Keres\xE9s az oldalon",filters_label:"Sz\u0171r\xE9s",zero_results:"Nincs tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre",many_results:"[COUNT] db tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre",one_result:"[COUNT] db tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre",alt_search:"Nincs tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre. Tal\xE1latok mutat\xE1sa ink\xE1bb a(z) [DIFFERENT_TERM] kifejez\xE9sre",search_suggestion:"Nincs tal\xE1lat a(z) [SEARCH_TERM] kifejez\xE9sre. Pr\xF3b\xE1ld meg a k\xF6vetkez\u0151 keres\xE9sek egyik\xE9t:",searching:"Keres\xE9s a(z) [SEARCH_TERM] kifejez\xE9sre..."},rl={thanks_to:el,comments:tl,direction:nl,strings:sl};var jt={};S(jt,{comments:()=>il,default:()=>ul,direction:()=>al,strings:()=>ol,thanks_to:()=>ll});var ll="Nixentric",il="",al="ltr",ol={placeholder:"Cari",clear_search:"Bersihkan",load_more:"Muat lebih banyak hasil",search_label:"Telusuri situs ini",filters_label:"Filter",zero_results:"[SEARCH_TERM] tidak ditemukan",many_results:"Ditemukan [COUNT] hasil untuk [SEARCH_TERM]",one_result:"Ditemukan [COUNT] hasil untuk [SEARCH_TERM]",alt_search:"[SEARCH_TERM] tidak ditemukan. Menampilkan hasil [DIFFERENT_TERM] sebagai gantinya",search_suggestion:"[SEARCH_TERM] tidak ditemukan. Coba salah satu pencarian berikut ini:",searching:"Mencari [SEARCH_TERM]..."},ul={thanks_to:ll,comments:il,direction:al,strings:ol};var zt={};S(zt,{comments:()=>_l,default:()=>hl,direction:()=>fl,strings:()=>dl,thanks_to:()=>cl});var cl="Cosette Bruhns Alonso, Andrew Janco ",_l="",fl="ltr",dl={placeholder:"Cerca",clear_search:"Cancella la cronologia",load_more:"Mostra pi\xF9 risultati",search_label:"Cerca nel sito",filters_label:"Filtri di ricerca",zero_results:"Nessun risultato per [SEARCH_TERM]",many_results:"[COUNT] risultati per [SEARCH_TERM]",one_result:"[COUNT] risultato per [SEARCH_TERM]",alt_search:"Nessun risultato per [SEARCH_TERM]. Mostrando risultati per [DIFFERENT_TERM] come alternativa.",search_suggestion:"Nessun risultato per [SEARCH_TERM]. Prova una delle seguenti ricerche:",searching:"Cercando [SEARCH_TERM]..."},hl={thanks_to:cl,comments:_l,direction:fl,strings:dl};var Dt={};S(Dt,{comments:()=>pl,default:()=>Rl,direction:()=>gl,strings:()=>El,thanks_to:()=>ml});var ml="Tate",pl="",gl="ltr",El={placeholder:"\u691C\u7D22",clear_search:"\u30AF\u30EA\u30A2",load_more:"\u6B21\u3092\u8AAD\u307F\u8FBC\u3080",search_label:"\u3053\u306E\u30B5\u30A4\u30C8\u3092\u691C\u7D22",filters_label:"\u30D5\u30A3\u30EB\u30BF",zero_results:"[SEARCH_TERM]\u306E\u691C\u7D22\u306B\u4E00\u81F4\u3059\u308B\u60C5\u5831\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F",many_results:"[SEARCH_TERM]\u306E[COUNT]\u4EF6\u306E\u691C\u7D22\u7D50\u679C",one_result:"[SEARCH_TERM]\u306E[COUNT]\u4EF6\u306E\u691C\u7D22\u7D50\u679C",alt_search:"[SEARCH_TERM]\u306E\u691C\u7D22\u306B\u4E00\u81F4\u3059\u308B\u60C5\u5831\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002[DIFFERENT_TERM]\u306E\u691C\u7D22\u7D50\u679C\u3092\u8868\u793A\u3057\u3066\u3044\u307E\u3059",search_suggestion:"[SEARCH_TERM]\u306E\u691C\u7D22\u306B\u4E00\u81F4\u3059\u308B\u60C5\u5831\u306F\u3042\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u6B21\u306E\u3044\u305A\u308C\u304B\u306E\u691C\u7D22\u3092\u8A66\u3057\u3066\u304F\u3060\u3055\u3044",searching:"[SEARCH_TERM]\u3092\u691C\u7D22\u3057\u3066\u3044\u307E\u3059"},Rl={thanks_to:ml,comments:pl,direction:gl,strings:El};var Ut={};S(Ut,{comments:()=>Tl,default:()=>yl,direction:()=>Cl,strings:()=>kl,thanks_to:()=>bl});var bl="Seokho Son ",Tl="",Cl="ltr",kl={placeholder:"\uAC80\uC0C9\uC5B4",clear_search:"\uBE44\uC6B0\uAE30",load_more:"\uAC80\uC0C9 \uACB0\uACFC \uB354 \uBCF4\uAE30",search_label:"\uC0AC\uC774\uD2B8 \uAC80\uC0C9",filters_label:"\uD544\uD130",zero_results:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC \uC5C6\uC74C",many_results:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC [COUNT]\uAC74",one_result:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC [COUNT]\uAC74",alt_search:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC \uC5C6\uC74C. [DIFFERENT_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC",search_suggestion:"[SEARCH_TERM]\uC5D0 \uB300\uD55C \uACB0\uACFC \uC5C6\uC74C. \uCD94\uCC9C \uAC80\uC0C9\uC5B4: ",searching:"[SEARCH_TERM] \uAC80\uC0C9 \uC911..."},yl={thanks_to:bl,comments:Tl,direction:Cl,strings:kl};var It={};S(It,{comments:()=>Ml,default:()=>wl,direction:()=>Al,strings:()=>vl,thanks_to:()=>Sl});var Sl="",Ml="",Al="ltr",vl={placeholder:"Rapu",clear_search:"Whakakore",load_more:"Whakauta \u0113tahi otinga k\u0113",search_label:"Rapu",filters_label:"T\u0101tari",zero_results:"Otinga kore ki [SEARCH_TERM]",many_results:"[COUNT] otinga ki [SEARCH_TERM]",one_result:"[COUNT] otinga ki [SEARCH_TERM]",alt_search:"Otinga kore ki [SEARCH_TERM]. Otinga k\u0113 ki [DIFFERENT_TERM]",search_suggestion:"Otinga kore ki [SEARCH_TERM]. whakam\u0101tau ki ng\u0101 mea atu:",searching:"Rapu ki [SEARCH_TERM]..."},wl={thanks_to:Sl,comments:Ml,direction:Al,strings:vl};var Pt={};S(Pt,{comments:()=>Fl,default:()=>jl,direction:()=>Nl,strings:()=>Ol,thanks_to:()=>Hl});var Hl="Paul van Brouwershaven",Fl="",Nl="ltr",Ol={placeholder:"Zoeken",clear_search:"Reset",load_more:"Meer resultaten laden",search_label:"Doorzoek deze site",filters_label:"Filters",zero_results:"Geen resultaten voor [SEARCH_TERM]",many_results:"[COUNT] resultaten voor [SEARCH_TERM]",one_result:"[COUNT] resultaat voor [SEARCH_TERM]",alt_search:"Geen resultaten voor [SEARCH_TERM]. In plaats daarvan worden resultaten voor [DIFFERENT_TERM] weergegeven",search_suggestion:"Geen resultaten voor [SEARCH_TERM]. Probeer een van de volgende zoekopdrachten:",searching:"Zoeken naar [SEARCH_TERM]..."},jl={thanks_to:Hl,comments:Fl,direction:Nl,strings:Ol};var Lt={};S(Lt,{comments:()=>Dl,default:()=>Pl,direction:()=>Ul,strings:()=>Il,thanks_to:()=>zl});var zl="Christopher Wingate",Dl="",Ul="ltr",Il={placeholder:"S\xF8k",clear_search:"Fjern",load_more:"Last flere resultater",search_label:"S\xF8k p\xE5 denne siden",filters_label:"Filtre",zero_results:"Ingen resultater for [SEARCH_TERM]",many_results:"[COUNT] resultater for [SEARCH_TERM]",one_result:"[COUNT] resultat for [SEARCH_TERM]",alt_search:"Ingen resultater for [SEARCH_TERM]. Viser resultater for [DIFFERENT_TERM] i stedet",search_suggestion:"Ingen resultater for [SEARCH_TERM]. Pr\xF8v en av disse s\xF8keordene i stedet:",searching:"S\xF8ker etter [SEARCH_TERM]"},Pl={thanks_to:zl,comments:Dl,direction:Ul,strings:Il};var qt={};S(qt,{comments:()=>ql,default:()=>Wl,direction:()=>Bl,strings:()=>Vl,thanks_to:()=>Ll});var Ll="",ql="",Bl="ltr",Vl={placeholder:"Szukaj",clear_search:"Wyczy\u015B\u0107",load_more:"Za\u0142aduj wi\u0119cej",search_label:"Przeszukaj t\u0119 stron\u0119",filters_label:"Filtry",zero_results:"Brak wynik\xF3w dla [SEARCH_TERM]",many_results:"[COUNT] wynik\xF3w dla [SEARCH_TERM]",one_result:"[COUNT] wynik dla [SEARCH_TERM]",alt_search:"Brak wynik\xF3w dla [SEARCH_TERM]. Wy\u015Bwietlam wyniki dla [DIFFERENT_TERM]",search_suggestion:"Brak wynik\xF3w dla [SEARCH_TERM]. Pokrewne wyniki wyszukiwania:",searching:"Szukam [SEARCH_TERM]..."},Wl={thanks_to:Ll,comments:ql,direction:Bl,strings:Vl};var Bt={};S(Bt,{comments:()=>Kl,default:()=>Zl,direction:()=>Jl,strings:()=>Yl,thanks_to:()=>Gl});var Gl="Jonatah",Kl="",Jl="ltr",Yl={placeholder:"Pesquisar",clear_search:"Limpar",load_more:"Ver mais resultados",search_label:"Pesquisar",filters_label:"Filtros",zero_results:"Nenhum resultado encontrado para [SEARCH_TERM]",many_results:"[COUNT] resultados encontrados para [SEARCH_TERM]",one_result:"[COUNT] resultado encontrado para [SEARCH_TERM]",alt_search:"Nenhum resultado encontrado para [SEARCH_TERM]. Exibindo resultados para [DIFFERENT_TERM]",search_suggestion:"Nenhum resultado encontrado para [SEARCH_TERM]. Tente uma das seguintes pesquisas:",searching:"Pesquisando por [SEARCH_TERM]..."},Zl={thanks_to:Gl,comments:Kl,direction:Jl,strings:Yl};var Vt={};S(Vt,{comments:()=>Ql,default:()=>ei,direction:()=>xl,strings:()=>$l,thanks_to:()=>Xl});var Xl="Bogdan Mateescu ",Ql="",xl="ltr",$l={placeholder:"C\u0103utare",clear_search:"\u015Eterge\u0163i",load_more:"\xCEnc\u0103rca\u021Bi mai multe rezultate",search_label:"C\u0103uta\u021Bi \xEEn acest site",filters_label:"Filtre",zero_results:"Niciun rezultat pentru [SEARCH_TERM]",many_results:"[COUNT] rezultate pentru [SEARCH_TERM]",one_result:"[COUNT] rezultat pentru [SEARCH_TERM]",alt_search:"Niciun rezultat pentru [SEARCH_TERM]. Se afi\u0219eaz\u0103 \xEEn schimb rezultatele pentru [DIFFERENT_TERM]",search_suggestion:"Niciun rezultat pentru [SEARCH_TERM]. \xCEncerca\u021Bi una dintre urm\u0103toarele c\u0103ut\u0103ri:",searching:"Se caut\u0103 dup\u0103: [SEARCH_TERM]..."},ei={thanks_to:Xl,comments:Ql,direction:xl,strings:$l};var Wt={};S(Wt,{comments:()=>ni,default:()=>li,direction:()=>si,strings:()=>ri,thanks_to:()=>ti});var ti="Aleksandr Gordeev",ni="",si="ltr",ri={placeholder:"\u041F\u043E\u0438\u0441\u043A",clear_search:"\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u044C \u043F\u043E\u043B\u0435",load_more:"\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0435\u0449\u0435",search_label:"\u041F\u043E\u0438\u0441\u043A \u043F\u043E \u0441\u0430\u0439\u0442\u0443",filters_label:"\u0424\u0438\u043B\u044C\u0442\u0440\u044B",zero_results:"\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]",many_results:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u043E\u0432 \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]",one_result:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]",alt_search:"\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]. \u041F\u043E\u043A\u0430\u0437\u0430\u043D\u044B \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [DIFFERENT_TERM]",search_suggestion:"\u041D\u0438\u0447\u0435\u0433\u043E \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]. \u041F\u043E\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u043E\u0434\u0438\u043D \u0438\u0437 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u043D\u0442\u043E\u0432",searching:"\u041F\u043E\u0438\u0441\u043A \u043F\u043E \u0437\u0430\u043F\u0440\u043E\u0441\u0443: [SEARCH_TERM]"},li={thanks_to:ti,comments:ni,direction:si,strings:ri};var Gt={};S(Gt,{comments:()=>ai,default:()=>ci,direction:()=>oi,strings:()=>ui,thanks_to:()=>ii});var ii="Andrija Sagicc",ai="",oi="ltr",ui={placeholder:"\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430",clear_search:"\u0411\u0440\u0438\u0441\u0430\u045A\u0435",load_more:"\u041F\u0440\u0438\u043A\u0430\u0437 \u0432\u0438\u0448\u0435 \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430",search_label:"\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430 \u0441\u0430\u0458\u0442\u0430",filters_label:"\u0424\u0438\u043B\u0442\u0435\u0440\u0438",zero_results:"\u041D\u0435\u043C\u0430 \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]",many_results:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]",one_result:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]",alt_search:"\u041D\u0435\u043C\u0430 \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]. \u041F\u0440\u0438\u043A\u0430\u0437 \u0434\u043E\u0434\u0430\u0442\u043D\u0438\u043A \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [DIFFERENT_TERM]",search_suggestion:"\u041D\u0435\u043C\u0430 \u0440\u0435\u0437\u0443\u043B\u0442\u0430\u0442\u0430 \u0437\u0430 [SEARCH_TERM]. \u041F\u043E\u043A\u0443\u0448\u0430\u0458\u0442\u0435 \u0441\u0430 \u043D\u0435\u043A\u043E\u043C \u043E\u0434 \u0441\u043B\u0435\u0434\u0435\u045B\u0438\u0445 \u043F\u0440\u0435\u0442\u0440\u0430\u0433\u0430:",searching:"\u041F\u0440\u0435\u0442\u0440\u0430\u0433\u0430 \u0442\u0435\u0440\u043C\u0438\u043D\u0430 [SEARCH_TERM]..."},ci={thanks_to:ii,comments:ai,direction:oi,strings:ui};var Kt={};S(Kt,{comments:()=>fi,default:()=>mi,direction:()=>di,strings:()=>hi,thanks_to:()=>_i});var _i="Montazar Al-Jaber ",fi="",di="ltr",hi={placeholder:"S\xF6k",clear_search:"Rensa",load_more:"Visa fler tr\xE4ffar",search_label:"S\xF6k p\xE5 denna sida",filters_label:"Filter",zero_results:"[SEARCH_TERM] gav inga tr\xE4ffar",many_results:"[SEARCH_TERM] gav [COUNT] tr\xE4ffar",one_result:"[SEARCH_TERM] gav [COUNT] tr\xE4ff",alt_search:"[SEARCH_TERM] gav inga tr\xE4ffar. Visar resultat f\xF6r [DIFFERENT_TERM] ist\xE4llet",search_suggestion:"[SEARCH_TERM] gav inga tr\xE4ffar. F\xF6rs\xF6k igen med en av f\xF6ljande s\xF6kord:",searching:"S\xF6ker efter [SEARCH_TERM]..."},mi={thanks_to:_i,comments:fi,direction:di,strings:hi};var Jt={};S(Jt,{comments:()=>gi,default:()=>bi,direction:()=>Ei,strings:()=>Ri,thanks_to:()=>pi});var pi="Anonymous",gi="",Ei="ltr",Ri={placeholder:"Tafuta",clear_search:"Futa",load_more:"Pakia matokeo zaidi",search_label:"Tafuta tovuti hii",filters_label:"Vichujio",zero_results:"Hakuna matokeo ya [SEARCH_TERM]",many_results:"Matokeo [COUNT] ya [SEARCH_TERM]",one_result:"Tokeo [COUNT] la [SEARCH_TERM]",alt_search:"Hakuna mayokeo ya [SEARCH_TERM]. Badala yake, inaonyesha matokeo ya [DIFFERENT_TERM]",search_suggestion:"Hakuna matokeo ya [SEARCH_TERM]. Jaribu mojawapo ya utafutaji ufuatao:",searching:"Kutafuta [SEARCH_TERM]..."},bi={thanks_to:pi,comments:gi,direction:Ei,strings:Ri};var Yt={};S(Yt,{comments:()=>Ci,default:()=>Si,direction:()=>ki,strings:()=>yi,thanks_to:()=>Ti});var Ti="",Ci="",ki="ltr",yi={placeholder:"\u0BA4\u0BC7\u0B9F\u0BC1\u0B95",clear_search:"\u0B85\u0BB4\u0BBF\u0B95\u0BCD\u0B95\u0BC1\u0B95",load_more:"\u0BAE\u0BC7\u0BB2\u0BC1\u0BAE\u0BCD \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BC8\u0B95\u0BCD \u0B95\u0BBE\u0B9F\u0BCD\u0B9F\u0BC1\u0B95",search_label:"\u0B87\u0BA8\u0BCD\u0BA4 \u0BA4\u0BB3\u0BA4\u0BCD\u0BA4\u0BBF\u0BB2\u0BCD \u0BA4\u0BC7\u0B9F\u0BC1\u0B95",filters_label:"\u0BB5\u0B9F\u0BBF\u0B95\u0B9F\u0BCD\u0B9F\u0BB2\u0BCD\u0B95\u0BB3\u0BCD",zero_results:"[SEARCH_TERM] \u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD \u0B87\u0BB2\u0BCD\u0BB2\u0BC8",many_results:"[SEARCH_TERM] \u0B95\u0BCD\u0B95\u0BBE\u0BA9 [COUNT] \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD",one_result:"[SEARCH_TERM] \u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1",alt_search:"[SEARCH_TERM] \u0B87\u0BA4\u0BCD\u0BA4\u0BC7\u0B9F\u0BB2\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD \u0B87\u0BB2\u0BCD\u0BB2\u0BC8, \u0B87\u0BA8\u0BCD\u0BA4 \u0BA4\u0BC7\u0B9F\u0BB2\u0BCD\u0B95\u0BB3\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0B92\u0BA4\u0BCD\u0BA4 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD [DIFFERENT_TERM]",search_suggestion:"[SEARCH_TERM] \u0B87\u0BA4\u0BCD \u0BA4\u0BC7\u0B9F\u0BB2\u0BC1\u0B95\u0BCD\u0B95\u0BBE\u0BA9 \u0BAE\u0BC1\u0B9F\u0BBF\u0BB5\u0BC1\u0B95\u0BB3\u0BCD \u0B87\u0BB2\u0BCD\u0BB2\u0BC8.\u0B87\u0BA4\u0BB1\u0BCD\u0B95\u0BC1 \u0BAA\u0BA4\u0BBF\u0BB2\u0BC0\u0B9F\u0BBE\u0BA9 \u0BA4\u0BC7\u0B9F\u0BB2\u0BCD\u0B95\u0BB3\u0BC8 \u0BA4\u0BC7\u0B9F\u0BC1\u0B95:",searching:"[SEARCH_TERM] \u0BA4\u0BC7\u0B9F\u0BAA\u0BCD\u0BAA\u0B9F\u0BC1\u0B95\u0BBF\u0BA9\u0BCD\u0BB1\u0BA4\u0BC1"},Si={thanks_to:Ti,comments:Ci,direction:ki,strings:yi};var Zt={};S(Zt,{comments:()=>Ai,default:()=>Hi,direction:()=>vi,strings:()=>wi,thanks_to:()=>Mi});var Mi="Taylan \xD6zg\xFCr Bildik",Ai="",vi="ltr",wi={placeholder:"Ara\u015Ft\u0131r",clear_search:"Temizle",load_more:"Daha fazla sonu\xE7",search_label:"Site genelinde arama",filters_label:"Filtreler",zero_results:"[SEARCH_TERM] i\xE7in sonu\xE7 yok",many_results:"[SEARCH_TERM] i\xE7in [COUNT] sonu\xE7 bulundu",one_result:"[SEARCH_TERM] i\xE7in [COUNT] sonu\xE7 bulundu",alt_search:"[SEARCH_TERM] i\xE7in sonu\xE7 yok. Bunun yerine [DIFFERENT_TERM] i\xE7in sonu\xE7lar g\xF6steriliyor",search_suggestion:"[SEARCH_TERM] i\xE7in sonu\xE7 yok. Alternatif olarak a\u015Fa\u011F\u0131daki kelimelerden birini deneyebilirsiniz:",searching:"[SEARCH_TERM] ara\u015Ft\u0131r\u0131l\u0131yor..."},Hi={thanks_to:Mi,comments:Ai,direction:vi,strings:wi};var Xt={};S(Xt,{comments:()=>Ni,default:()=>zi,direction:()=>Oi,strings:()=>ji,thanks_to:()=>Fi});var Fi="Vladyslav Lyshenko ",Ni="",Oi="ltr",ji={placeholder:"\u041F\u043E\u0448\u0443\u043A",clear_search:"\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u043F\u043E\u043B\u0435",load_more:"\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438 \u0449\u0435",search_label:"\u041F\u043E\u0448\u0443\u043A \u043F\u043E \u0441\u0430\u0439\u0442\u0443",filters_label:"\u0424\u0456\u043B\u044C\u0442\u0440\u0438",zero_results:"\u041D\u0456\u0447\u043E\u0433\u043E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u0437\u0430 \u0437\u0430\u043F\u0438\u0442\u043E\u043C: [SEARCH_TERM]",many_results:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u0456\u0432 \u043D\u0430 \u0437\u0430\u043F\u0438\u0442: [SEARCH_TERM]",one_result:"[COUNT] \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442 \u0437\u0430 \u0437\u0430\u043F\u0438\u0442\u043E\u043C: [SEARCH_TERM]",alt_search:"\u041D\u0456\u0447\u043E\u0433\u043E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043D\u0430 \u0437\u0430\u043F\u0438\u0442: [SEARCH_TERM]. \u041F\u043E\u043A\u0430\u0437\u0430\u043D\u043E \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u0438 \u043D\u0430 \u0437\u0430\u043F\u0438\u0442: [DIFFERENT_TERM]",search_suggestion:"\u041D\u0456\u0447\u043E\u0433\u043E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E \u043D\u0430 \u0437\u0430\u043F\u0438\u0442: [SEARCH_TERM]. \u0421\u043F\u0440\u043E\u0431\u0443\u0439\u0442\u0435 \u043E\u0434\u0438\u043D \u0456\u0437 \u0442\u0430\u043A\u0438\u0445 \u0432\u0430\u0440\u0456\u0430\u043D\u0442\u0456\u0432",searching:"\u041F\u043E\u0448\u0443\u043A \u0437\u0430 \u0437\u0430\u043F\u0438\u0442\u043E\u043C: [SEARCH_TERM]"},zi={thanks_to:Fi,comments:Ni,direction:Oi,strings:ji};var Qt={};S(Qt,{comments:()=>Ui,default:()=>Li,direction:()=>Ii,strings:()=>Pi,thanks_to:()=>Di});var Di="Long Nhat Nguyen",Ui="",Ii="ltr",Pi={placeholder:"T\xECm ki\u1EBFm",clear_search:"X\xF3a",load_more:"Nhi\u1EC1u k\u1EBFt qu\u1EA3 h\u01A1n",search_label:"T\xECm ki\u1EBFm trong trang n\xE0y",filters_label:"B\u1ED9 l\u1ECDc",zero_results:"Kh\xF4ng t\xECm th\u1EA5y k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]",many_results:"[COUNT] k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]",one_result:"[COUNT] k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]",alt_search:"Kh\xF4ng t\xECm th\u1EA5y k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]. Ki\u1EC3m th\u1ECB k\u1EBFt qu\u1EA3 thay th\u1EBF v\u1EDBi [DIFFERENT_TERM]",search_suggestion:"Kh\xF4ng t\xECm th\u1EA5y k\u1EBFt qu\u1EA3 cho [SEARCH_TERM]. Th\u1EED m\u1ED9t trong c\xE1c t\xECm ki\u1EBFm:",searching:"\u0110ang t\xECm ki\u1EBFm cho [SEARCH_TERM]..."},Li={thanks_to:Di,comments:Ui,direction:Ii,strings:Pi};var xt={};S(xt,{comments:()=>Bi,default:()=>Gi,direction:()=>Vi,strings:()=>Wi,thanks_to:()=>qi});var qi="Amber Song",Bi="",Vi="ltr",Wi={placeholder:"\u641C\u7D22",clear_search:"\u6E05\u9664",load_more:"\u52A0\u8F7D\u66F4\u591A\u7ED3\u679C",search_label:"\u7AD9\u5185\u641C\u7D22",filters_label:"\u7B5B\u9009",zero_results:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",many_results:"\u627E\u5230 [COUNT] \u4E2A [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",one_result:"\u627E\u5230 [COUNT] \u4E2A [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",alt_search:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C\u3002\u6539\u4E3A\u663E\u793A [DIFFERENT_TERM] \u7684\u76F8\u5173\u7ED3\u679C",search_suggestion:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C\u3002\u8BF7\u5C1D\u8BD5\u4EE5\u4E0B\u641C\u7D22\u3002",searching:"\u6B63\u5728\u641C\u7D22 [SEARCH_TERM]..."},Gi={thanks_to:qi,comments:Bi,direction:Vi,strings:Wi};var $t={};S($t,{comments:()=>Ji,default:()=>Xi,direction:()=>Yi,strings:()=>Zi,thanks_to:()=>Ki});var Ki="Amber Song",Ji="",Yi="ltr",Zi={placeholder:"\u641C\u7D22",clear_search:"\u6E05\u9664",load_more:"\u52A0\u8F09\u66F4\u591A\u7D50\u679C",search_label:"\u7AD9\u5167\u641C\u7D22",filters_label:"\u7BE9\u9078",zero_results:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C",many_results:"\u627E\u5230 [COUNT] \u500B [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C",one_result:"\u627E\u5230 [COUNT] \u500B [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C",alt_search:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C\u3002\u6539\u70BA\u986F\u793A [DIFFERENT_TERM] \u7684\u76F8\u95DC\u7D50\u679C",search_suggestion:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u95DC\u7D50\u679C\u3002\u8ACB\u5617\u8A66\u4EE5\u4E0B\u641C\u7D22\u3002",searching:"\u6B63\u5728\u641C\u7D22 [SEARCH_TERM]..."},Xi={thanks_to:Ki,comments:Ji,direction:Yi,strings:Zi};var en={};S(en,{comments:()=>xi,default:()=>ta,direction:()=>$i,strings:()=>ea,thanks_to:()=>Qi});var Qi="Amber Song",xi="",$i="ltr",ea={placeholder:"\u641C\u7D22",clear_search:"\u6E05\u9664",load_more:"\u52A0\u8F7D\u66F4\u591A\u7ED3\u679C",search_label:"\u7AD9\u5185\u641C\u7D22",filters_label:"\u7B5B\u9009",zero_results:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",many_results:"\u627E\u5230 [COUNT] \u4E2A [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",one_result:"\u627E\u5230 [COUNT] \u4E2A [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C",alt_search:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C\u3002\u6539\u4E3A\u663E\u793A [DIFFERENT_TERM] \u7684\u76F8\u5173\u7ED3\u679C",search_suggestion:"\u672A\u627E\u5230 [SEARCH_TERM] \u7684\u76F8\u5173\u7ED3\u679C\u3002\u8BF7\u5C1D\u8BD5\u4EE5\u4E0B\u641C\u7D22\u3002",searching:"\u6B63\u5728\u641C\u7D22 [SEARCH_TERM]..."},ta={thanks_to:Qi,comments:xi,direction:$i,strings:ea};var na=[bt,Tt,Ct,kt,yt,St,Mt,At,vt,wt,Ht,Ft,Nt,Ot,jt,zt,Dt,Ut,It,Pt,Lt,qt,Bt,Vt,Wt,Gt,Kt,Jt,Yt,Zt,Xt,Qt,xt,$t,en],Qn=na,xn=["../../translations/af.json","../../translations/bn.json","../../translations/ca.json","../../translations/cs.json","../../translations/da.json","../../translations/de.json","../../translations/en.json","../../translations/es.json","../../translations/fi.json","../../translations/fr.json","../../translations/gl.json","../../translations/hi.json","../../translations/hr.json","../../translations/hu.json","../../translations/id.json","../../translations/it.json","../../translations/ja.json","../../translations/ko.json","../../translations/mi.json","../../translations/nl.json","../../translations/no.json","../../translations/pl.json","../../translations/pt.json","../../translations/ro.json","../../translations/ru.json","../../translations/sr.json","../../translations/sv.json","../../translations/sw.json","../../translations/ta.json","../../translations/tr.json","../../translations/uk.json","../../translations/vi.json","../../translations/zh-cn.json","../../translations/zh-tw.json","../../translations/zh.json"];function $n(n,e,t){let s=n.slice();return s[51]=e[t],s}function es(n){let e,t,s;function r(i){n[37](i)}let l={show_empty_filters:n[5],open_filters:n[6],available_filters:n[18],translate:n[20],automatic_translations:n[19],translations:n[7]};return n[0]!==void 0&&(l.selected_filters=n[0]),e=new Xn({props:l}),le.push(()=>bn(e,"selected_filters",r)),{c(){tt(e.$$.fragment)},m(i,a){me(e,i,a),s=!0},p(i,a){let o={};a[0]&32&&(o.show_empty_filters=i[5]),a[0]&64&&(o.open_filters=i[6]),a[0]&262144&&(o.available_filters=i[18]),a[0]&524288&&(o.automatic_translations=i[19]),a[0]&128&&(o.translations=i[7]),!t&&a[0]&1&&(t=!0,o.selected_filters=i[0],pn(()=>t=!1)),e.$set(o)},i(i){s||(D(e.$$.fragment,i),s=!0)},o(i){P(e.$$.fragment,i),s=!1},d(i){ue(e,i)}}}function ts(n){let e,t,s,r,l=[la,ra],i=[];function a(o,h){return o[14]?0:1}return t=a(n,[-1,-1]),s=i[t]=l[t](n),{c(){e=C("div"),s.c(),E(e,"class","pagefind-ui__results-area svelte-e9gkc3")},m(o,h){y(o,e,h),i[t].m(e,null),r=!0},p(o,h){let c=t;t=a(o,h),t===c?i[t].p(o,h):(ae(),P(i[c],1,1,()=>{i[c]=null}),oe(),s=i[t],s?s.p(o,h):(s=i[t]=l[t](o),s.c()),D(s,1),s.m(e,null))},i(o){r||(D(s),r=!0)},o(o){P(s),r=!1},d(o){o&&k(e),i[t].d()}}}function ra(n){let e,t,s,r=[],l=new Map,i,a,o;function h(u,f){return u[13].results.length===0?oa:u[13].results.length===1?aa:ia}let c=h(n,[-1,-1]),m=c(n),p=n[13].results.slice(0,n[17]),d=u=>u[51].id;for(let u=0;un[17]&&ss(n);return{c(){e=C("p"),m.c(),t=A(),s=C("ol");for(let u=0;uu[17]?_?_.p(u,f):(_=ss(u),_.c(),_.m(a.parentNode,a)):_&&(_.d(1),_=null)},i(u){if(!o){for(let f=0;f{o[p]=null}),oe(),r=o[s],r?r.p(e,m):(r=o[s]=a[s](e),r.c()),D(r,1),r.m(l.parentNode,l))},i(c){i||(D(r),i=!0)},o(c){P(r),i=!1},d(c){c&&k(t),o[s].d(c),c&&k(l)}}}function ss(n){let e,t=n[20]("load_more",n[19],n[7])+"",s,r,l;return{c(){e=C("button"),s=w(t),E(e,"type","button"),E(e,"class","pagefind-ui__button svelte-e9gkc3")},m(i,a){y(i,e,a),b(e,s),r||(l=J(e,"click",n[22]),r=!0)},p(i,a){a[0]&524416&&t!==(t=i[20]("load_more",i[19],i[7])+"")&&N(s,t)},d(i){i&&k(e),r=!1,l()}}}function rs(n){let e,t=n[20]("searching",n[19],n[7]).replace(/\[SEARCH_TERM\]/,n[16])+"",s;return{c(){e=C("p"),s=w(t),E(e,"class","pagefind-ui__message svelte-e9gkc3")},m(r,l){y(r,e,l),b(e,s)},p(r,l){l[0]&589952&&t!==(t=r[20]("searching",r[19],r[7]).replace(/\[SEARCH_TERM\]/,r[16])+"")&&N(s,t)},d(r){r&&k(e)}}}function _a(n){let e,t,s,r,l,i,a=n[20]("clear_search",n[19],n[7])+"",o,h,c,m,p,d,_,u,f=n[12]&&es(n),T=n[15]&&ts(n);return{c(){e=C("div"),t=C("form"),s=C("input"),l=A(),i=C("button"),o=w(a),h=A(),c=C("div"),f&&f.c(),m=A(),T&&T.c(),E(s,"class","pagefind-ui__search-input svelte-e9gkc3"),E(s,"type","text"),E(s,"placeholder",r=n[20]("placeholder",n[19],n[7])),E(s,"autocapitalize","none"),E(s,"enterkeyhint","search"),s.autofocus=n[8],E(i,"class","pagefind-ui__search-clear svelte-e9gkc3"),B(i,"pagefind-ui__suppressed",!n[9]),E(c,"class","pagefind-ui__drawer svelte-e9gkc3"),B(c,"pagefind-ui__hidden",!n[15]),E(t,"class","pagefind-ui__form svelte-e9gkc3"),E(t,"role","search"),E(t,"aria-label",p=n[20]("search_label",n[19],n[7])),E(t,"action","javascript:void(0);"),E(e,"class","pagefind-ui svelte-e9gkc3"),B(e,"pagefind-ui--reset",n[1])},m(R,M){y(R,e,M),b(e,t),b(t,s),dt(s,n[9]),n[34](s),b(t,l),b(t,i),b(i,o),n[35](i),b(t,h),b(t,c),f&&f.m(c,null),b(c,m),T&&T.m(c,null),d=!0,n[8]&&s.focus(),_||(u=[J(s,"focus",n[21]),J(s,"keydown",n[32]),J(s,"input",n[33]),J(i,"click",n[36]),J(t,"submit",fa)],_=!0)},p(R,M){(!d||M[0]&524416&&r!==(r=R[20]("placeholder",R[19],R[7])))&&E(s,"placeholder",r),(!d||M[0]&256)&&(s.autofocus=R[8]),M[0]&512&&s.value!==R[9]&&dt(s,R[9]),(!d||M[0]&524416)&&a!==(a=R[20]("clear_search",R[19],R[7])+"")&&N(o,a),(!d||M[0]&512)&&B(i,"pagefind-ui__suppressed",!R[9]),R[12]?f?(f.p(R,M),M[0]&4096&&D(f,1)):(f=es(R),f.c(),D(f,1),f.m(c,m)):f&&(ae(),P(f,1,1,()=>{f=null}),oe()),R[15]?T?(T.p(R,M),M[0]&32768&&D(T,1)):(T=ts(R),T.c(),D(T,1),T.m(c,null)):T&&(ae(),P(T,1,1,()=>{T=null}),oe()),(!d||M[0]&32768)&&B(c,"pagefind-ui__hidden",!R[15]),(!d||M[0]&524416&&p!==(p=R[20]("search_label",R[19],R[7])))&&E(t,"aria-label",p),(!d||M[0]&2)&&B(e,"pagefind-ui--reset",R[1])},i(R){d||(D(f),D(T),d=!0)},o(R){P(f),P(T),d=!1},d(R){R&&k(e),n[34](null),n[35](null),f&&f.d(),T&&T.d(),_=!1,G(u)}}}var fa=n=>n.preventDefault();function da(n,e,t){let s={},r=xn.map(g=>g.match(/([^\/]+)\.json$/)[1]);for(let g=0;gj[g]??F[g]??"";ht(()=>{let g=document?.querySelector?.("html")?.getAttribute?.("lang")||"en",F=nt(g.toLocaleLowerCase());t(19,on=s[`${F.language}-${F.script}-${F.region}`]||s[`${F.language}-${F.region}`]||s[`${F.language}`]||s.en)}),mt(()=>{H?.destroy?.(),H=null});let un=async()=>{if(!rt&&(t(12,rt=!0),!H)){let g;try{g=await import(`${l}pagefind.js`)}catch(j){console.error(j),console.error([`Pagefind couldn't be loaded from ${this.options.bundlePath}pagefind.js`,"You can configure this by passing a bundlePath option to PagefindUI"].join(` +`)),document?.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?console.error(`[DEBUG: Loaded from ${document.currentScript.src??"bad script location"}]`):console.error("no known script location")}c||t(24,c=h?12:30);let F={...f||{},excerptLength:c};await g.options(F);for(let j of T){if(!j.bundlePath)throw new Error("mergeIndex requires a bundlePath parameter");let L=j.bundlePath;delete j.bundlePath,await g.mergeIndex(L,j)}H=g,os()}},os=async()=>{H&&(an=await H.filters(),(!ce||!Object.keys(ce).length)&&t(18,ce=an))},us=g=>{let F={};return Object.entries(g).filter(([,j])=>j).forEach(([j])=>{let[L,te]=j.split(/:(.*)$/);F[L]=F[L]||[],F[L].push(te)}),F},_e,cs=async(g,F)=>{if(!g){t(15,it=!1),_e&&clearTimeout(_e);return}let j=us(F),L=()=>_s(g,j);u>0&&g?(_e&&clearTimeout(_e),_e=setTimeout(L,u),await cn(),H.preload(g,{filters:j})):L(),fs()},cn=async()=>{for(;!H;)un(),await new Promise(g=>setTimeout(g,50))},_s=async(g,F)=>{t(16,ln=g||""),typeof p=="function"&&(g=p(g)),t(14,lt=!0),t(15,it=!0),await cn();let j=++rn,L={filters:F};X&&typeof X=="object"&&(L.sort=X);let te=await H.search(g,L);rn===j&&(te.filters&&Object.keys(te.filters)?.length&&t(18,ce=te.filters),t(13,sn=te),t(14,lt=!1),t(17,at=i))},fs=()=>{let g=W.offsetWidth;g!=is&&t(10,O.style.paddingRight=`${g+2}px`,O)},ds=g=>{g?.preventDefault(),t(17,at+=i)},hs=g=>{g.key==="Escape"&&(t(9,v=""),O.blur()),g.key==="Enter"&&g.preventDefault()};function ms(){v=this.value,t(9,v),t(23,R)}function ps(g){le[g?"unshift":"push"](()=>{O=g,t(10,O)})}function gs(g){le[g?"unshift":"push"](()=>{W=g,t(11,W)})}let Es=()=>{t(9,v=""),O.blur()};function Rs(g){V=g,t(0,V)}return n.$$set=g=>{"base_path"in g&&t(25,l=g.base_path),"page_size"in g&&t(26,i=g.page_size),"reset_styles"in g&&t(1,a=g.reset_styles),"show_images"in g&&t(2,o=g.show_images),"show_sub_results"in g&&t(3,h=g.show_sub_results),"excerpt_length"in g&&t(24,c=g.excerpt_length),"process_result"in g&&t(4,m=g.process_result),"process_term"in g&&t(27,p=g.process_term),"show_empty_filters"in g&&t(5,d=g.show_empty_filters),"open_filters"in g&&t(6,_=g.open_filters),"debounce_timeout_ms"in g&&t(28,u=g.debounce_timeout_ms),"pagefind_options"in g&&t(29,f=g.pagefind_options),"merge_index"in g&&t(30,T=g.merge_index),"trigger_search_term"in g&&t(23,R=g.trigger_search_term),"translations"in g&&t(7,M=g.translations),"autofocus"in g&&t(8,U=g.autofocus),"sort"in g&&t(31,X=g.sort),"selected_filters"in g&&t(0,V=g.selected_filters)},n.$$.update=()=>{if(n.$$.dirty[0]&8388608)e:R&&(t(9,v=R),t(23,R=""));if(n.$$.dirty[0]&513)e:cs(v,V)},[V,a,o,h,m,d,_,M,U,v,O,W,rt,sn,lt,it,ln,at,ce,on,as,un,ds,R,c,l,i,p,u,f,T,X,hs,ms,ps,gs,Es,Rs]}var tn=class extends q{constructor(e){super(),Y(this,e,da,_a,K,{base_path:25,page_size:26,reset_styles:1,show_images:2,show_sub_results:3,excerpt_length:24,process_result:4,process_term:27,show_empty_filters:5,open_filters:6,debounce_timeout_ms:28,pagefind_options:29,merge_index:30,trigger_search_term:23,translations:7,autofocus:8,sort:31,selected_filters:0},null,[-1,-1])}},ls=tn;var nn;try{document?.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"&&(nn=new URL(document.currentScript.src).pathname.match(/^(.*\/)(?:pagefind-)?ui.js.*$/)[1])}catch{nn="/pagefind/"}var st=class{constructor(e){this._pfs=null;let t=e.element??"[data-pagefind-ui]",s=e.bundlePath??nn,r=e.pageSize??5,l=e.resetStyles??!0,i=e.showImages??!0,a=e.showSubResults??!1,o=e.excerptLength??0,h=e.processResult??null,c=e.processTerm??null,m=e.showEmptyFilters??!0,p=e.openFilters??[],d=e.debounceTimeoutMs??300,_=e.mergeIndex??[],u=e.translations??[],f=e.autofocus??!1,T=e.sort??null;delete e.element,delete e.bundlePath,delete e.pageSize,delete e.resetStyles,delete e.showImages,delete e.showSubResults,delete e.excerptLength,delete e.processResult,delete e.processTerm,delete e.showEmptyFilters,delete e.openFilters,delete e.debounceTimeoutMs,delete e.mergeIndex,delete e.translations,delete e.autofocus,delete e.sort;let R=t instanceof HTMLElement?t:document.querySelector(t);R?this._pfs=new ls({target:R,props:{base_path:s,page_size:r,reset_styles:l,show_images:i,show_sub_results:a,excerpt_length:o,process_result:h,process_term:c,show_empty_filters:m,open_filters:p,debounce_timeout_ms:d,merge_index:_,translations:u,autofocus:f,sort:T,pagefind_options:e}}):console.error(`Pagefind UI couldn't find the selector ${t}`)}triggerSearch(e){this._pfs.$$set({trigger_search_term:e})}triggerFilters(e){let t={};for(let[s,r]of Object.entries(e))if(Array.isArray(r))for(let l of r)t[`${s}:${l}`]=!0;else t[`${s}:${r}`]=!0;this._pfs.$$set({selected_filters:t})}destroy(){this._pfs.$destroy()}};window.PagefindUI=st;})(); diff --git a/pagefind/pagefind.en_c73d434e5f.pf_meta b/pagefind/pagefind.en_c73d434e5f.pf_meta new file mode 100644 index 0000000000..b9fd65d806 Binary files /dev/null and b/pagefind/pagefind.en_c73d434e5f.pf_meta differ diff --git a/pagefind/pagefind.js b/pagefind/pagefind.js new file mode 100644 index 0000000000..b58a7da874 --- /dev/null +++ b/pagefind/pagefind.js @@ -0,0 +1,9 @@ +const pagefind_version="1.1.1";let wasm_bindgen;(function(){const __exports={};let script_src;if(typeof document!=='undefined'&&document.currentScript!==null){script_src=new URL("UNHANDLED",location.href).toString()}let wasm=undefined;let cachedUint8Memory0=null;function getUint8Memory0(){if(cachedUint8Memory0===null||cachedUint8Memory0.byteLength===0){cachedUint8Memory0=new Uint8Array(wasm.memory.buffer)}return cachedUint8Memory0}let WASM_VECTOR_LEN=0;function passArray8ToWasm0(arg,malloc){const ptr=malloc(arg.length*1,1)>>>0;getUint8Memory0().set(arg,ptr/1);WASM_VECTOR_LEN=arg.length;return ptr}__exports.init_pagefind=function(metadata_bytes){const ptr0=passArray8ToWasm0(metadata_bytes,wasm.__wbindgen_malloc);const len0=WASM_VECTOR_LEN;const ret=wasm.init_pagefind(ptr0,len0);return ret>>>0};const cachedTextEncoder=(typeof TextEncoder!=='undefined'?new TextEncoder('utf-8'):{encode:()=>{throw Error('TextEncoder not available')}});const encodeString=(typeof cachedTextEncoder.encodeInto==='function'?function(arg,view){return cachedTextEncoder.encodeInto(arg,view)}:function(arg,view){const buf=cachedTextEncoder.encode(arg);view.set(buf);return{read:arg.length,written:buf.length}});function passStringToWasm0(arg,malloc,realloc){if(realloc===undefined){const buf=cachedTextEncoder.encode(arg);const ptr=malloc(buf.length,1)>>>0;getUint8Memory0().subarray(ptr,ptr+buf.length).set(buf);WASM_VECTOR_LEN=buf.length;return ptr}let len=arg.length;let ptr=malloc(len,1)>>>0;const mem=getUint8Memory0();let offset=0;for(;offset0x7F)break;mem[ptr+offset]=code}if(offset!==len){if(offset!==0){arg=arg.slice(offset)}ptr=realloc(ptr,len,len=offset+arg.length*3,1)>>>0;const view=getUint8Memory0().subarray(ptr+offset,ptr+len);const ret=encodeString(arg,view);offset+=ret.written;ptr=realloc(ptr,len,offset,1)>>>0}WASM_VECTOR_LEN=offset;return ptr}__exports.set_ranking_weights=function(ptr,weights){const ptr0=passStringToWasm0(weights,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;const ret=wasm.set_ranking_weights(ptr,ptr0,len0);return ret>>>0};__exports.load_index_chunk=function(ptr,chunk_bytes){const ptr0=passArray8ToWasm0(chunk_bytes,wasm.__wbindgen_malloc);const len0=WASM_VECTOR_LEN;const ret=wasm.load_index_chunk(ptr,ptr0,len0);return ret>>>0};__exports.load_filter_chunk=function(ptr,chunk_bytes){const ptr0=passArray8ToWasm0(chunk_bytes,wasm.__wbindgen_malloc);const len0=WASM_VECTOR_LEN;const ret=wasm.load_filter_chunk(ptr,ptr0,len0);return ret>>>0};__exports.add_synthetic_filter=function(ptr,filter){const ptr0=passStringToWasm0(filter,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;const ret=wasm.add_synthetic_filter(ptr,ptr0,len0);return ret>>>0};let cachedInt32Memory0=null;function getInt32Memory0(){if(cachedInt32Memory0===null||cachedInt32Memory0.byteLength===0){cachedInt32Memory0=new Int32Array(wasm.memory.buffer)}return cachedInt32Memory0}const cachedTextDecoder=(typeof TextDecoder!=='undefined'?new TextDecoder('utf-8',{ignoreBOM:true,fatal:true}):{decode:()=>{throw Error('TextDecoder not available')}});if(typeof TextDecoder!=='undefined'){cachedTextDecoder.decode()};function getStringFromWasm0(ptr,len){ptr=ptr>>>0;return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr,ptr+len))}__exports.request_indexes=function(ptr,query){let deferred2_0;let deferred2_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);const ptr0=passStringToWasm0(query,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;wasm.request_indexes(retptr,ptr,ptr0,len0);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred2_0=r0;deferred2_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred2_0,deferred2_1,1)}};__exports.request_filter_indexes=function(ptr,filters){let deferred2_0;let deferred2_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);const ptr0=passStringToWasm0(filters,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;wasm.request_filter_indexes(retptr,ptr,ptr0,len0);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred2_0=r0;deferred2_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred2_0,deferred2_1,1)}};__exports.request_all_filter_indexes=function(ptr){let deferred1_0;let deferred1_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);wasm.request_all_filter_indexes(retptr,ptr);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred1_0=r0;deferred1_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred1_0,deferred1_1,1)}};__exports.filters=function(ptr){let deferred1_0;let deferred1_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);wasm.filters(retptr,ptr);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred1_0=r0;deferred1_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred1_0,deferred1_1,1)}};__exports.search=function(ptr,query,filter,sort,exact){let deferred4_0;let deferred4_1;try{const retptr=wasm.__wbindgen_add_to_stack_pointer(-16);const ptr0=passStringToWasm0(query,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len0=WASM_VECTOR_LEN;const ptr1=passStringToWasm0(filter,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len1=WASM_VECTOR_LEN;const ptr2=passStringToWasm0(sort,wasm.__wbindgen_malloc,wasm.__wbindgen_realloc);const len2=WASM_VECTOR_LEN;wasm.search(retptr,ptr,ptr0,len0,ptr1,len1,ptr2,len2,exact);var r0=getInt32Memory0()[retptr/4+0];var r1=getInt32Memory0()[retptr/4+1];deferred4_0=r0;deferred4_1=r1;return getStringFromWasm0(r0,r1)}finally{wasm.__wbindgen_add_to_stack_pointer(16);wasm.__wbindgen_free(deferred4_0,deferred4_1,1)}};async function __wbg_load(module,imports){if(typeof Response==='function'&&module instanceof Response){if(typeof WebAssembly.instantiateStreaming==='function'){try{return await WebAssembly.instantiateStreaming(module,imports)}catch(e){if(module.headers.get('Content-Type')!='application/wasm'){console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",e)}else{throw e}}}const bytes=await module.arrayBuffer();return await WebAssembly.instantiate(bytes,imports)}else{const instance=await WebAssembly.instantiate(module,imports);if(instance instanceof WebAssembly.Instance){return{instance,module}}else{return instance}}}function __wbg_get_imports(){const imports={};imports.wbg={};return imports}function __wbg_init_memory(imports,maybe_memory){}function __wbg_finalize_init(instance,module){wasm=instance.exports;__wbg_init.__wbindgen_wasm_module=module;cachedInt32Memory0=null;cachedUint8Memory0=null;return wasm}function initSync(module){if(wasm!==undefined)return wasm;const imports=__wbg_get_imports();__wbg_init_memory(imports);if(!(module instanceof WebAssembly.Module)){module=new WebAssembly.Module(module)}const instance=new WebAssembly.Instance(module,imports);return __wbg_finalize_init(instance,module)}async function __wbg_init(input){if(wasm!==undefined)return wasm;if(typeof input==='undefined'&&typeof script_src!=='undefined'){input=script_src.replace(/\.js$/,'_bg.wasm')}const imports=__wbg_get_imports();if(typeof input==='string'||(typeof Request==='function'&&input instanceof Request)||(typeof URL==='function'&&input instanceof URL)){input=fetch(input)}__wbg_init_memory(imports);const{instance,module}=await __wbg_load(await input,imports);return __wbg_finalize_init(instance,module)}wasm_bindgen=Object.assign(__wbg_init,{initSync},__exports)})();var u8=Uint8Array;var u16=Uint16Array;var u32=Uint32Array;var fleb=new u8([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]);var fdeb=new u8([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]);var clim=new u8([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]);var freb=function(eb,start){var b=new u16(31);for(var i2=0;i2<31;++i2){b[i2]=start+=1<>>1|(i&21845)<<1;x=(x&52428)>>>2|(x&13107)<<2;x=(x&61680)>>>4|(x&3855)<<4;rev[i]=((x&65280)>>>8|(x&255)<<8)>>>1}var x;var i;var hMap=function(cd,mb,r){var s=cd.length;var i2=0;var l=new u16(mb);for(;i2>>rvb]=sv}}}}else{co=new u16(s);for(i2=0;i2>>15-cd[i2]}}}return co};var flt=new u8(288);for(i=0;i<144;++i)flt[i]=8;var i;for(i=144;i<256;++i)flt[i]=9;var i;for(i=256;i<280;++i)flt[i]=7;var i;for(i=280;i<288;++i)flt[i]=8;var i;var fdt=new u8(32);for(i=0;i<32;++i)fdt[i]=5;var i;var flrm=hMap(flt,9,1);var fdrm=hMap(fdt,5,1);var max=function(a){var m=a[0];for(var i2=1;i2m)m=a[i2]}return m};var bits=function(d,p,m){var o=p/8|0;return(d[o]|d[o+1]<<8)>>(p&7)&m};var bits16=function(d,p){var o=p/8|0;return(d[o]|d[o+1]<<8|d[o+2]<<16)>>(p&7)};var shft=function(p){return(p+7)/8|0};var slc=function(v,s,e){if(s==null||s<0)s=0;if(e==null||e>v.length)e=v.length;var n=new(v.BYTES_PER_ELEMENT==2?u16:v.BYTES_PER_ELEMENT==4?u32:u8)(e-s);n.set(v.subarray(s,e));return n};var ec=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"];var err=function(ind,msg,nt){var e=new Error(msg||ec[ind]);e.code=ind;if(Error.captureStackTrace)Error.captureStackTrace(e,err);if(!nt)throw e;return e};var inflt=function(dat,buf,st){var sl=dat.length;if(!sl||st&&st.f&&!st.l)return buf||new u8(0);var noBuf=!buf||st;var noSt=!st||st.i;if(!st)st={};if(!buf)buf=new u8(sl*3);var cbuf=function(l2){var bl=buf.length;if(l2>bl){var nbuf=new u8(Math.max(bl*2,l2));nbuf.set(buf);buf=nbuf}};var final=st.f||0,pos=st.p||0,bt=st.b||0,lm=st.l,dm=st.d,lbt=st.m,dbt=st.n;var tbts=sl*8;do{if(!lm){final=bits(dat,pos,1);var type=bits(dat,pos+1,3);pos+=3;if(!type){var s=shft(pos)+4,l=dat[s-4]|dat[s-3]<<8,t=s+l;if(t>sl){if(noSt)err(0);break}if(noBuf)cbuf(bt+l);buf.set(dat.subarray(s,t),bt);st.b=bt+=l,st.p=pos=t*8,st.f=final;continue}else if(type==1)lm=flrm,dm=fdrm,lbt=9,dbt=5;else if(type==2){var hLit=bits(dat,pos,31)+257,hcLen=bits(dat,pos+10,15)+4;var tl=hLit+bits(dat,pos+5,31)+1;pos+=14;var ldt=new u8(tl);var clt=new u8(19);for(var i2=0;i2>>4;if(s<16){ldt[i2++]=s}else{var c=0,n=0;if(s==16)n=3+bits(dat,pos,3),pos+=2,c=ldt[i2-1];else if(s==17)n=3+bits(dat,pos,7),pos+=3;else if(s==18)n=11+bits(dat,pos,127),pos+=7;while(n--)ldt[i2++]=c}}var lt=ldt.subarray(0,hLit),dt=ldt.subarray(hLit);lbt=max(lt);dbt=max(dt);lm=hMap(lt,lbt,1);dm=hMap(dt,dbt,1)}else err(1);if(pos>tbts){if(noSt)err(0);break}}if(noBuf)cbuf(bt+131072);var lms=(1<>>4;pos+=c&15;if(pos>tbts){if(noSt)err(0);break}if(!c)err(2);if(sym<256)buf[bt++]=sym;else if(sym==256){lpos=pos,lm=null;break}else{var add=sym-254;if(sym>264){var i2=sym-257,b=fleb[i2];add=bits(dat,pos,(1<>>4;if(!d)err(3);pos+=d&15;var dt=fd[dsym];if(dsym>3){var b=fdeb[dsym];dt+=bits16(dat,pos)&(1<tbts){if(noSt)err(0);break}if(noBuf)cbuf(bt+131072);var end=bt+add;for(;bt>3&1)+(flg>>4&1);zs>0;zs-=!d[st++]);return st+(flg&2)};var gzl=function(d){var l=d.length;return(d[l-4]|d[l-3]<<8|d[l-2]<<16|d[l-1]<<24)>>>0};function gunzipSync(data,out){return inflt(data.subarray(gzs(data),-8),out||new u8(gzl(data)))}var td=typeof TextDecoder!="undefined"&&new TextDecoder();var tds=0;try{td.decode(et,{stream:true});tds=1}catch(e){}var gz_default=gunzipSync;var calculate_excerpt_region=(word_positions,excerpt_length)=>{if(word_positions.length===0){return 0}let words=[];for(const word of word_positions){words[word.location]=words[word.location]||0;words[word.location]+=word.balanced_score}if(words.length<=excerpt_length){return 0}let densest=words.slice(0,excerpt_length).reduce((partialSum,a)=>partialSum+a,0);let working_sum=densest;let densest_at=[0];for(let i2=0;i2densest){densest=working_sum;densest_at=[i2]}else if(working_sum===densest&&densest_at[densest_at.length-1]===i2-1){densest_at.push(i2)}}let midpoint=densest_at[Math.floor(densest_at.length/2)];return midpoint};var build_excerpt=(content,start,length,locations,not_before,not_from)=>{let is_zws_delimited=content.includes("\u200B");let fragment_words=[];if(is_zws_delimited){fragment_words=content.split("\u200B")}else{fragment_words=content.split(/[\r\n\s]+/g)}for(let word of locations){if(fragment_words[word]?.startsWith(``)){continue}fragment_words[word]=`${fragment_words[word]}`}let endcap=not_from??fragment_words.length;let startcap=not_before??0;if(endcap-startcapendcap){start=endcap-length}if(start{const anchors=fragment.anchors.filter((a)=>/h\d/i.test(a.element)&&a.text?.length&&/\S/.test(a.text)).sort((a,b)=>a.location-b.location);const results=[];let current_anchor_position=0;let current_anchor={title:fragment.meta["title"],url:fragment.url,weighted_locations:[],locations:[],excerpt:""};const add_result=(end_range)=>{if(current_anchor.locations.length){const relative_weighted_locations=current_anchor.weighted_locations.map((l)=>{return{weight:l.weight,balanced_score:l.balanced_score,location:l.location-current_anchor_position}});const excerpt_start=calculate_excerpt_region(relative_weighted_locations,desired_excerpt_length)+current_anchor_position;const excerpt_length=end_range?Math.min(end_range-excerpt_start,desired_excerpt_length):desired_excerpt_length;current_anchor.excerpt=build_excerpt(fragment.raw_content??"",excerpt_start,excerpt_length,current_anchor.locations,current_anchor_position,end_range);results.push(current_anchor)}};for(let word of fragment.weighted_locations){if(!anchors.length||word.location=anchors[0].location){next_anchor=anchors.shift()}let anchored_url=fragment.url;try{const url_is_fq=/^((https?:)?\/\/)/.test(anchored_url);if(url_is_fq){let fq_url=new URL(anchored_url);fq_url.hash=next_anchor.id;anchored_url=fq_url.toString()}else{if(!/^\//.test(anchored_url)){anchored_url=`/${anchored_url}`}let fq_url=new URL(`https://example.com${anchored_url}`);fq_url.hash=next_anchor.id;anchored_url=fq_url.toString().replace(/^https:\/\/example.com/,"")}}catch(e){console.error(`Pagefind: Couldn't process ${anchored_url} for a search result`)}current_anchor_position=next_anchor.location;current_anchor={title:next_anchor.text,url:anchored_url,anchor:next_anchor,weighted_locations:[word],locations:[word.location],excerpt:""}}}add_result(anchors[0]?.location);return results};var asyncSleep=async(ms=100)=>{return new Promise((r)=>setTimeout(r,ms))};var PagefindInstance=class{constructor(opts={}){this.version=pagefind_version;this.backend=wasm_bindgen;this.decoder=new TextDecoder("utf-8");this.wasm=null;this.basePath=opts.basePath||"/pagefind/";this.primary=opts.primary||false;if(this.primary&&!opts.basePath){this.initPrimary()}if(/[^\/]$/.test(this.basePath)){this.basePath=`${this.basePath}/`}if(window?.location?.origin&&this.basePath.startsWith(window.location.origin)){this.basePath=this.basePath.replace(window.location.origin,"")}this.baseUrl=opts.baseUrl||this.defaultBaseUrl();if(!/^(\/|https?:\/\/)/.test(this.baseUrl)){this.baseUrl=`/${this.baseUrl}`}this.indexWeight=opts.indexWeight??1;this.excerptLength=opts.excerptLength??30;this.mergeFilter=opts.mergeFilter??{};this.ranking=opts.ranking;this.highlightParam=opts.highlightParam??null;this.loaded_chunks={};this.loaded_filters={};this.loaded_fragments={};this.raw_ptr=null;this.searchMeta=null;this.languages=null}initPrimary(){let derivedBasePath=import.meta.url.match(/^(.*\/)pagefind.js.*$/)?.[1];if(derivedBasePath){this.basePath=derivedBasePath}else{console.warn(["Pagefind couldn't determine the base of the bundle from the import path. Falling back to the default.","Set a basePath option when initialising Pagefind to ignore this message."].join("\n"))}}defaultBaseUrl(){let default_base=this.basePath.match(/^(.*\/)_?pagefind/)?.[1];return default_base||"/"}async options(options2){const opts=["basePath","baseUrl","indexWeight","excerptLength","mergeFilter","highlightParam","ranking"];for(const[k,v]of Object.entries(options2)){if(k==="mergeFilter"){let filters2=this.stringifyFilters(v);let ptr=await this.getPtr();this.raw_ptr=this.backend.add_synthetic_filter(ptr,filters2)}else if(k==="ranking"){await this.set_ranking(options2.ranking)}else if(opts.includes(k)){if(k==="basePath"&&typeof v==="string")this.basePath=v;if(k==="baseUrl"&&typeof v==="string")this.baseUrl=v;if(k==="indexWeight"&&typeof v==="number")this.indexWeight=v;if(k==="excerptLength"&&typeof v==="number")this.excerptLength=v;if(k==="mergeFilter"&&typeof v==="object")this.mergeFilter=v;if(k==="highlightParam"&&typeof v==="string")this.highlightParam=v}else{console.warn(`Unknown Pagefind option ${k}. Allowed options: [${opts.join(", ")}]`)}}}decompress(data,file="unknown file"){if(this.decoder.decode(data.slice(0,12))==="pagefind_dcd"){return data.slice(12)}data=gz_default(data);if(this.decoder.decode(data.slice(0,12))!=="pagefind_dcd"){console.error(`Decompressing ${file} appears to have failed: Missing signature`);return data}return data.slice(12)}async set_ranking(ranking){if(!ranking)return;let rankingWeights={term_similarity:ranking.termSimilarity??null,page_length:ranking.pageLength??null,term_saturation:ranking.termSaturation??null,term_frequency:ranking.termFrequency??null};let ptr=await this.getPtr();this.raw_ptr=this.backend.set_ranking_weights(ptr,JSON.stringify(rankingWeights))}async init(language,opts){await this.loadEntry();let index=this.findIndex(language);let lang_wasm=index.wasm?index.wasm:"unknown";let resources=[this.loadMeta(index.hash)];if(opts.load_wasm===true){resources.push(this.loadWasm(lang_wasm))}await Promise.all(resources);this.raw_ptr=this.backend.init_pagefind(new Uint8Array(this.searchMeta));if(Object.keys(this.mergeFilter)?.length){let filters2=this.stringifyFilters(this.mergeFilter);let ptr=await this.getPtr();this.raw_ptr=this.backend.add_synthetic_filter(ptr,filters2)}if(this.ranking){await this.set_ranking(this.ranking)}}async loadEntry(){try{let entry_response=await fetch(`${this.basePath}pagefind-entry.json?ts=${Date.now()}`);let entry_json=await entry_response.json();this.languages=entry_json.languages;if(entry_json.version!==this.version){if(this.primary){console.warn(["Pagefind JS version doesn't match the version in your search index.",`Pagefind JS: ${this.version}. Pagefind index: ${entry_json.version}`,"If you upgraded Pagefind recently, you likely have a cached pagefind.js file.","If you encounter any search errors, try clearing your cache."].join("\n"))}else{console.warn(["Merging a Pagefind index from a different version than the main Pagefind instance.",`Main Pagefind JS: ${this.version}. Merged index (${this.basePath}): ${entry_json.version}`,"If you encounter any search errors, make sure that both sites are running the same version of Pagefind."].join("\n"))}}}catch(e){console.error(`Failed to load Pagefind metadata: +${e?.toString()}`);throw new Error("Failed to load Pagefind metadata")}}findIndex(language){if(this.languages){let index=this.languages[language];if(index)return index;index=this.languages[language.split("-")[0]];if(index)return index;let topLang=Object.values(this.languages).sort((a,b)=>b.page_count-a.page_count);if(topLang[0])return topLang[0]}throw new Error("Pagefind Error: No language indexes found.")}async loadMeta(index){try{let compressed_resp=await fetch(`${this.basePath}pagefind.${index}.pf_meta`);let compressed_meta=await compressed_resp.arrayBuffer();this.searchMeta=this.decompress(new Uint8Array(compressed_meta),"Pagefind metadata")}catch(e){console.error(`Failed to load the meta index: +${e?.toString()}`)}}async loadWasm(language){try{const wasm_url=`${this.basePath}wasm.${language}.pagefind`;let compressed_resp=await fetch(wasm_url);let compressed_wasm=await compressed_resp.arrayBuffer();const final_wasm=this.decompress(new Uint8Array(compressed_wasm),"Pagefind WebAssembly");if(!final_wasm){throw new Error("No WASM after decompression")}this.wasm=await this.backend(final_wasm)}catch(e){console.error(`Failed to load the Pagefind WASM: +${e?.toString()}`);throw new Error(`Failed to load the Pagefind WASM: +${e?.toString()}`)}}async _loadGenericChunk(url,method){try{let compressed_resp=await fetch(url);let compressed_chunk=await compressed_resp.arrayBuffer();let chunk=this.decompress(new Uint8Array(compressed_chunk),url);let ptr=await this.getPtr();this.raw_ptr=this.backend[method](ptr,chunk)}catch(e){console.error(`Failed to load the index chunk ${url}: +${e?.toString()}`)}}async loadChunk(hash){if(!this.loaded_chunks[hash]){const url=`${this.basePath}index/${hash}.pf_index`;this.loaded_chunks[hash]=this._loadGenericChunk(url,"load_index_chunk")}return await this.loaded_chunks[hash]}async loadFilterChunk(hash){if(!this.loaded_filters[hash]){const url=`${this.basePath}filter/${hash}.pf_filter`;this.loaded_filters[hash]=this._loadGenericChunk(url,"load_filter_chunk")}return await this.loaded_filters[hash]}async _loadFragment(hash){let compressed_resp=await fetch(`${this.basePath}fragment/${hash}.pf_fragment`);let compressed_fragment=await compressed_resp.arrayBuffer();let fragment=this.decompress(new Uint8Array(compressed_fragment),`Fragment ${hash}`);return JSON.parse(new TextDecoder().decode(fragment))}async loadFragment(hash,weighted_locations=[],search_term){if(!this.loaded_fragments[hash]){this.loaded_fragments[hash]=this._loadFragment(hash)}let fragment=await this.loaded_fragments[hash];fragment.weighted_locations=weighted_locations;fragment.locations=weighted_locations.map((l)=>l.location);if(!fragment.raw_content){fragment.raw_content=fragment.content.replace(//g,">");fragment.content=fragment.content.replace(/\u200B/g,"")}if(!fragment.raw_url){fragment.raw_url=fragment.url}fragment.url=this.processedUrl(fragment.raw_url,search_term);const excerpt_start=calculate_excerpt_region(weighted_locations,this.excerptLength);fragment.excerpt=build_excerpt(fragment.raw_content,excerpt_start,this.excerptLength,fragment.locations);fragment.sub_results=calculate_sub_results(fragment,this.excerptLength);return fragment}fullUrl(raw){if(/^(https?:)?\/\//.test(raw)){return raw}return`${this.baseUrl}/${raw}`.replace(/\/+/g,"/").replace(/^(https?:\/)/,"$1/")}processedUrl(url,search_term){const normalized=this.fullUrl(url);if(this.highlightParam===null){return normalized}let individual_terms=search_term.split(/\s+/);try{let processed=new URL(normalized);for(const term of individual_terms){processed.searchParams.append(this.highlightParam,term)}return processed.toString()}catch(e){try{let processed=new URL(`https://example.com${normalized}`);for(const term of individual_terms){processed.searchParams.append(this.highlightParam,term)}return processed.toString().replace(/^https:\/\/example\.com/,"")}catch(e2){return normalized}}}async getPtr(){while(this.raw_ptr===null){await asyncSleep(50)}if(!this.raw_ptr){console.error("Pagefind: WASM Error (No pointer)");throw new Error("Pagefind: WASM Error (No pointer)")}return this.raw_ptr}parseFilters(str){let output={};if(!str)return output;for(const block of str.split("__PF_FILTER_DELIM__")){let[filter,values]=block.split(/:(.*)$/);output[filter]={};if(values){for(const valueBlock of values.split("__PF_VALUE_DELIM__")){if(valueBlock){let extract=valueBlock.match(/^(.*):(\d+)$/);if(extract){let[,value,count]=extract;output[filter][value]=parseInt(count)??count}}}}}return output}stringifyFilters(obj={}){return JSON.stringify(obj)}stringifySorts(obj={}){let sorts=Object.entries(obj);for(let[sort,direction]of sorts){if(sorts.length>1){console.warn(`Pagefind was provided multiple sort options in this search, but can only operate on one. Using the ${sort} sort.`)}if(direction!=="asc"&&direction!=="desc"){console.warn(`Pagefind was provided a sort with unknown direction ${direction}. Supported: [asc, desc]`)}return`${sort}:${direction}`}return``}async filters(){let ptr=await this.getPtr();let filters2=this.backend.request_all_filter_indexes(ptr);let filter_chunks=filters2.split(" ").filter((v)=>v).map((chunk)=>this.loadFilterChunk(chunk));await Promise.all([...filter_chunks]);ptr=await this.getPtr();let results=this.backend.filters(ptr);return this.parseFilters(results)}async preload(term,options2={}){await this.search(term,{...options2,preload:true})}async search(term,options2={}){options2={verbose:false,filters:{},sort:{},...options2};const log=(str)=>{if(options2.verbose)console.log(str)};log(`Starting search on ${this.basePath}`);let start=Date.now();let ptr=await this.getPtr();let filter_only=term===null;term=term??"";let exact_search=/^\s*".+"\s*$/.test(term);if(exact_search){log(`Running an exact search`)}term=term.toLowerCase().trim().replace(/[\.`~!@#\$%\^&\*\(\)\{\}\[\]\\\|:;'",<>\/\?\-]/g,"").replace(/\s{2,}/g," ").trim();log(`Normalized search term to ${term}`);if(!term?.length&&!filter_only){return{results:[],unfilteredResultCount:0,filters:{},totalFilters:{},timings:{preload:Date.now()-start,search:Date.now()-start,total:Date.now()-start}}}let sort_list=this.stringifySorts(options2.sort);log(`Stringified sort to ${sort_list}`);const filter_list=this.stringifyFilters(options2.filters);log(`Stringified filters to ${filter_list}`);let index_resp=this.backend.request_indexes(ptr,term);let filter_resp=this.backend.request_filter_indexes(ptr,filter_list);let chunks=index_resp.split(" ").filter((v)=>v).map((chunk)=>this.loadChunk(chunk));let filter_chunks=filter_resp.split(" ").filter((v)=>v).map((chunk)=>this.loadFilterChunk(chunk));await Promise.all([...chunks,...filter_chunks]);log(`Loaded necessary chunks to run search`);if(options2.preload){log(`Preload \u2014 bailing out of search operation now.`);return null}ptr=await this.getPtr();let searchStart=Date.now();let result=this.backend.search(ptr,term,filter_list,sort_list,exact_search);log(`Got the raw search result: ${result}`);let[unfilteredResultCount,all_results,filters2,totalFilters]=result.split(/:([^:]*):(.*)__PF_UNFILTERED_DELIM__(.*)$/);let filterObj=this.parseFilters(filters2);let totalFilterObj=this.parseFilters(totalFilters);log(`Remaining filters: ${JSON.stringify(result)}`);let results=all_results.length?all_results.split(" "):[];let resultsInterface=results.map((result2)=>{let[hash,score,all_locations]=result2.split("@");log(`Processing result: + hash:${hash} + score:${score} + locations:${all_locations}`);let weighted_locations=all_locations.length?all_locations.split(",").map((l)=>{let[weight,balanced_score,location]=l.split(">");return{weight:parseInt(weight)/24,balanced_score:parseFloat(balanced_score),location:parseInt(location)}}):[];let locations=weighted_locations.map((l)=>l.location);return{id:hash,score:parseFloat(score)*this.indexWeight,words:locations,data:async()=>await this.loadFragment(hash,weighted_locations,term)}});const searchTime=Date.now()-searchStart;const realTime=Date.now()-start;log(`Found ${results.length} result${results.length == 1 ? "" : "s"} for "${term}" in ${Date.now() - searchStart}ms (${Date.now() - start}ms realtime)`);return{results:resultsInterface,unfilteredResultCount:parseInt(unfilteredResultCount),filters:filterObj,totalFilters:totalFilterObj,timings:{preload:realTime-searchTime,search:searchTime,total:realTime}}}};var Pagefind=class{constructor(options2={}){this.backend=wasm_bindgen;this.primaryLanguage="unknown";this.searchID=0;this.primary=new PagefindInstance({...options2,primary:true});this.instances=[this.primary];this.init(options2?.language)}async options(options2){await this.primary.options(options2)}async init(overrideLanguage){if(document?.querySelector){const langCode=document.querySelector("html")?.getAttribute("lang")||"unknown";this.primaryLanguage=langCode.toLocaleLowerCase()}await this.primary.init(overrideLanguage?overrideLanguage:this.primaryLanguage,{load_wasm:true})}async mergeIndex(indexPath,options2={}){if(this.primary.basePath.startsWith(indexPath)){console.warn(`Skipping mergeIndex ${indexPath} that appears to be the same as the primary index (${this.primary.basePath})`);return}let newInstance=new PagefindInstance({primary:false,basePath:indexPath});this.instances.push(newInstance);while(this.primary.wasm===null){await asyncSleep(50)}await newInstance.init(options2.language||this.primaryLanguage,{load_wasm:false});delete options2["language"];await newInstance.options(options2)}mergeFilters(filters2){const merged={};for(const searchFilter of filters2){for(const[filterKey,values]of Object.entries(searchFilter)){if(!merged[filterKey]){merged[filterKey]=values;continue}else{const filter=merged[filterKey];for(const[valueKey,count]of Object.entries(values)){filter[valueKey]=(filter[valueKey]||0)+count}}}}return merged}async filters(){let filters2=await Promise.all(this.instances.map((i2)=>i2.filters()));return this.mergeFilters(filters2)}async preload(term,options2={}){await Promise.all(this.instances.map((i2)=>i2.preload(term,options2)))}async debouncedSearch(term,options2,debounceTimeoutMs){const thisSearchID=++this.searchID;this.preload(term,options2);await asyncSleep(debounceTimeoutMs);if(thisSearchID!==this.searchID){return null}const searchResult=await this.search(term,options2);if(thisSearchID!==this.searchID){return null}return searchResult}async search(term,options2={}){let search2=await Promise.all(this.instances.map((i2)=>i2.search(term,options2)));const filters2=this.mergeFilters(search2.map((s)=>s.filters));const totalFilters=this.mergeFilters(search2.map((s)=>s.totalFilters));const results=search2.map((s)=>s.results).flat().sort((a,b)=>b.score-a.score);const timings=search2.map((s)=>s.timings);const unfilteredResultCount=search2.reduce((sum,s)=>sum+s.unfilteredResultCount,0);return{results,unfilteredResultCount,filters:filters2,totalFilters,timings}}};var pagefind=void 0;var initial_options=void 0;var init_pagefind=()=>{if(!pagefind){pagefind=new Pagefind(initial_options??{})}};var options=async(new_options)=>{if(pagefind){await pagefind.options(new_options)}else{initial_options=new_options}};var init=async()=>{init_pagefind()};var destroy=async()=>{pagefind=void 0;initial_options=void 0};var mergeIndex=async(indexPath,options2)=>{init_pagefind();return await pagefind.mergeIndex(indexPath,options2)};var search=async(term,options2)=>{init_pagefind();return await pagefind.search(term,options2)};var debouncedSearch=async(term,options2,debounceTimeoutMs=300)=>{init_pagefind();return await pagefind.debouncedSearch(term,options2,debounceTimeoutMs)};var preload=async(term,options2)=>{init_pagefind();return await pagefind.preload(term,options2)};var filters=async()=>{init_pagefind();return await pagefind.filters()};export{debouncedSearch,destroy,filters,init,mergeIndex,options,preload,search} \ No newline at end of file diff --git a/pagefind/pagefind.zh-cn_dcc472e46a518.pf_meta b/pagefind/pagefind.zh-cn_dcc472e46a518.pf_meta new file mode 100644 index 0000000000..2e02255196 Binary files /dev/null and b/pagefind/pagefind.zh-cn_dcc472e46a518.pf_meta differ diff --git a/pagefind/wasm.en.pagefind b/pagefind/wasm.en.pagefind new file mode 100644 index 0000000000..12d499fd13 Binary files /dev/null and b/pagefind/wasm.en.pagefind differ diff --git a/pagefind/wasm.unknown.pagefind b/pagefind/wasm.unknown.pagefind new file mode 100644 index 0000000000..76b3ed3777 Binary files /dev/null and b/pagefind/wasm.unknown.pagefind differ diff --git a/screenshots_2560x1440.jpg b/screenshots_2560x1440.jpg new file mode 100644 index 0000000000..8e17bcdece Binary files /dev/null and b/screenshots_2560x1440.jpg differ diff --git a/screenshots_748x1340.jpg b/screenshots_748x1340.jpg new file mode 100644 index 0000000000..1866888805 Binary files /dev/null and b/screenshots_748x1340.jpg differ diff --git a/src/article/astParse/tokenizer.html b/src/article/astParse/tokenizer.html new file mode 100644 index 0000000000..3785f7d915 --- /dev/null +++ b/src/article/astParse/tokenizer.html @@ -0,0 +1,233 @@ + + + + + + Abstract Syntax Tree | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Abstract Syntax Tree

    一.(abstract syntax tree)抽象语法树的作用

    源码是一串按照语法格式来组织的字符串,人能够认识,但是计算机并不认识,想让计算机认识就要转成一种数据结构,通过不同的对象来保存不同的数据,并且按照依赖关系组织起来,这种数据结构就是抽象语法树(abstract syntax tree)。

    之所以叫“抽象”语法树是因为数据结构中省略掉了一些无具体意义的分隔符比如 ; { } 等。

    有了 AST,计算机就能理解源码字符串的意思,而理解是能够转换的前提,所以编译的第一步需要把源码 parseAST

    转成 AST 之后就可以通过修改 AST ,分析 AST 的方式来修改和分析代码,比如 babel 就通过这种方式进行代码的转换,比如 rollupTree Shaking ,就是通过分析 AST的 导入导出语法,从而分析出没有使用的代码,进行去除。

    二。常见的 AST 节点

    常见的 AST 节点 AST 是对源码的抽象,字面量、标识符、表达式、语句、模块语法、class 语法都有各自的 AST。

    我们分别来了解一下:

    Literal

    Literal 是字面量的意思,比如 let name = 'value'中,'value'就是一个字符串字面量 StringLiteral,相应的还有数字字面量 NumericLiteral,布尔字面量 BooleanLiteral,字符串字面量 StringLiteral,正则表达式字面量 RegExpLiteral 等。

    下面这些字面量都有对应的 Literal 节点:

    代码中的字面量很多,babel 就是通过 xxLiteral 来抽象这部分内容的。

    Identifier

    Identifer 是标识符的意思,变量名、属性名、参数名等各种声明和引用的名字,都是Identifer

    我们知道, JS 中的标识符只能包含字母或数字或下划线 (“_”) 或美元符号 (“$”) ,且不能以数字开头。这是 Identifier 的词法特点。

    尝试分析一下,下面这一段代码里面有多少 Identifier 呢?

    js
    const name = 'value';
    +
    +function say(name) {
    +  console.log(name);
    +}
    +
    +const obj = {
    +  name: 'guang',
    +};

    答案是这些

    Statement

    statement 是语句,它是可以独立执行的单位,比如 break、continue、debugger、return 或者 if 语句、while 语句、for 语句,还有声明语句,表达式语句等。我们写的每一条可以独立执行的代码都是语句。

    语句末尾一般会加一个分号分隔,或者用换行分隔。

    下面这些我们经常写的代码,每一行都是一个 Statement

    js
    break;
    +continue;
    +return;
    +debugger;
    +throw Error();
    +{}
    +try {} catch(e) {} finally{}
    +for (let key in obj) {}
    +for (let i = 0;i < 10;i ++) {}
    +while (true) {}
    +do {} while (true)
    +switch (v){case 1: break;default:;}
    +label: console.log();
    +with (a){}

    它们对应的 AST 节点如下图所示:

    语句是代码执行的最小单位,可以说,代码是由语句 (Statement) 构成的。

    Declaration

    声明语句是一种特殊的语句,它执行的逻辑是在作用域内声明一个变量、函数、 class、import、export 等。

    比如下面这些语句都是声明语句:

    js
    const a = 1;
    +function b() {}
    +class C {}
    +
    +import d from 'e';
    +
    +export default e = 1;
    +export { e };
    +export * from 'e';

    它们对应的 AST 节点如下图:

    声明语句用于定义变量,这也是代码中一个基础组成部分。

    Expression

    expression 是表达式,特点是执行完以后有返回值,这是和语句 (statement) 的区别。

    下面是一些常见的表达式

    js
    [1,2,3]
    +a = 1
    +1 + 2;
    +-1;
    +function(){};
    +() => {};
    +class{};
    +a;
    +this;
    +super;
    +a::b;

    它们对应的 AST 如图:

    细心的同学可能会问 identifiersuper 怎么也是表达式呢?

    因为 identifier、super 有返回值,符合表达式的特点,所以也是 expression

    我们判断 AST 节点是不是某种类型要看它是不是符合该种类型的特点,比如语句的特点是能够单独执行,表达式的特点是有返回值。

    有的表达式可以单独执行,符合语句的特点,所以也是语句,比如赋值表达式、数组表达式等。

    js
    a = 1;
    +[1, 2, 3];

    但有的表达式不能单独执行,需要和其他类型的节点组合在一起构成语句。

    比如匿名函数表达式和匿名 class 表达式单独执行会报错:

    js
    function(){};
    +class{}

    需要和其他部分一起构成一条语句,比如组成赋值语句:

    js
    a = function () {};
    +b = class {};

    这条赋值语句对应的 AST 是这样的:

    你会发现赋值语句的 AST 节点 AssignmentExpression 包裹了一层 ExpressionStatement 的节点,代表这个表达式是被当成语句执行的。

    Class

    class 的语法也有专门的 AST 节点来表示。

    整个 class 的内容是 ClassBody ,属性是 ClassProperty ,方法是 ClassMethod (通过 kind 属性来区分是 constructor 还是 method )。

    比如下面的代码

    js
    class Guang extends Person {
    +  name = 'guang';
    +  constructor() {}
    +  eat() {}
    +}

    对应的 AST 是这样的

    classes next 的语法, babel 中有专门的 AST 来表示它的内容。

    Modules

    es module 是语法级别的模块规范,所以也有专门的 AST 节点。

    importimport 有 3 种语法:

    named import

    js
    import { c, d } from 'c';

    default import

    js
    import a from 'a';

    namespaced import:

    js
    import * as b from 'b';

    这 3 种语法都对应 ImportDeclaration 节点,但是 specifiers 属性不同,分别对应 ImportSpicifier 、ImportDefaultSpecifier 、ImportNamespaceSpcifier

    图中黄框标出的就是 specifier 部分。可以直观的看出整体结构相同,只是 specifier 部分不同,所以 import 语法的 AST 的结构是 ImportDeclaration 包含着各种 import specifier

    exportexport 也有 3 种语法:

    named export

    js
    export { b, d };

    default export

    js
    export default a;

    all export

    js
    export * from 'c';

    分别对应 ExportNamedDeclaration 、ExportDefaultDeclaration 、ExportAllDeclarationAST

    比如这三种 export

    js
    export { b, d };
    +export default a;
    +export * from 'c';

    对应的 AST 节点为

    Program & Directive

    program 是代表整个程序的节点,它有 body 属性代表程序体,存放 statement 数组,就是具体执行的语句的集合。还有 directives 属性,存放 Directive 节点,比如 "use strict" 这种指令会使用 Directive 节点表示。

    Program 是包裹具体执行语句的节点,而 Directive 则是代码中的指令部分。

    File & Comment

    babelAST 最外层节点是 File ,它有 programcommentstokens 等属性,分别存放 Program 程序体、注释、 token 等,是最外层节点。

    注释分为块注释和行内注释,对应 CommentBlockCommentLine 节点。

    上面 6 种就是常见的一些 AST 节点类型, babel 就是通过这些节点来抽象源码中不同的部分。

    AST 可视化查看工具

    这么多 AST 我们都要记住么?

    不需要。可以通过 axtexplorer.net 这个网站来可视化的查看。

    这个网站可以查看代码 parse 以后的 AST ,可以切换 parse 的语言和用的 parser ,也可以修改 parse options

    点击这里的 save 就可以保存下来,然后把 url 分享出去:

    比如这个链接:https://astexplorer.net/

    如果想查看全部的 AST 可以在 babel parser 仓库里的 AST 文档里查,或者直接去看 @babel/typestypescript 类型定义。

    AST 的公共属性

    每种 AST 都有自己的属性,但是它们也有一些公共的属性:

    typeAST 节点的类型

    startendloc:startend 代表该节点在源码中的开始和结束下标。而 loc 属性是一个对象,有 linecolumn 属性分别记录开始和结束的行列号。

    leadingCommentsinnerCommentstrailingComments :表示开始的注释、中间的注释、结尾的注释,每个 AST 节点中都可能存在注释,而且可能在开始、中间、结束这三种位置,想拿到某个 AST 的注释就通过这三个属性。

    比如这段有注释的代码的 AST

    extra:记录一些额外的信息,用于处理一些特殊情况。比如 StringLiteralvalue 只是值的修改,而修改 extra.raw 则可以连同单双引号一起修改。 比如这段代码的 AST

    修改 value 只能修改值,修改 extra.raw 可以连引号一起修改。

    总结

    了解了这些节点,就能知道平时写的代码是怎么用 AST 表示的。

    当然也不需要记,可以用 (astexpoler.net) 可视化的查看。

    AST 节点可能同时有多种类型,确定一种 AST 节点是什么类型主要看它的特点,比如 Statement 的特点是可以单独执行, Expression 的特点是有返回值,所以一些可以单独执行的 Expression 会包一层 ExpressionStatement

    不同 AST 节点有不同的属性来存放对应的源码信息,但是都有一些公共属性如 type 、xxCommentsloc 等。

    学会了 AST ,就可以把对代码的操作转为对 AST 的操作了,这是编译、静态分析的第一步。

    三。编写词法分析器(Tokenizer)

    词法分析器,也叫分词器 (Tokenizer),它的作用是将代码划分为一个个词法单元,便于进行后续的语法分析。比如下面的这段代码:

    js
    let foo = function () {};

    在经过分词之后,代码会被切分为如下的 token 数组:

    js
    ['let', 'foo', '=', 'function', '(', ')', '{', '}'];

    从中你可以看到,原本一行普通的代码字符串被拆分成了拥有语法属性的 token 列表,不同的 token 之间也存在千丝万缕的联系,而后面所要介绍的语法分析器,就是来梳理各个 token 之间的联系,整理出 AST 数据结构。

    当下我们所要实现的词法分析器,本质上是对代码字符串进行逐个字符的扫描,然后根据一定的语法规则进行分组。其中,涉及到几个关键的步骤:

    1. 确定语法规则,包括语言内置的关键词、单字符、分隔符等
    2. 逐个代码字符扫描,根据语法规则进行 token 分组

    1. 确定 Token 的类型和规则

    增加 Token 的类型

    ts
    export enum TokenType {
    +  // let
    +  Let = 'Let',
    +  // =
    +  Assign = 'Assign',
    +  // function
    +  Function = 'Function',
    +  // 变量名
    +  Identifier = 'Identifier',
    +  // (
    +  LeftParen = 'LeftParen',
    +  // )
    +  RightParen = 'RightParen',
    +  // {
    +  LeftCurly = 'LeftCurly',
    +  // }
    +  RightCurly = 'RightCurly',
    +}
    +
    +export type Token = {
    +  type: TokenType;
    +  value?: string;
    +  start: number;
    +  end: number;
    +  raw?: string;
    +};

    定义 Token 类型到规则的映射

    ts
    const TOKENS_GENERATOR: Record<string, (...args: any[]) => Token> = {
    +  let(start: number) {
    +    return { type: TokenType.Let, value: 'let', start, end: start + 3 };
    +  },
    +  assign(start: number) {
    +    return { type: TokenType.Assign, value: '=', start, end: start + 1 };
    +  },
    +  function(start: number) {
    +    return {
    +      type: TokenType.Function,
    +      value: 'function',
    +      start,
    +      end: start + 8,
    +    };
    +  },
    +  leftParen(start: number) {
    +    return { type: TokenType.LeftParen, value: '(', start, end: start + 1 };
    +  },
    +  rightParen(start: number) {
    +    return { type: TokenType.RightParen, value: ')', start, end: start + 1 };
    +  },
    +  leftCurly(start: number) {
    +    return { type: TokenType.LeftCurly, value: '{', start, end: start + 1 };
    +  },
    +  rightCurly(start: number) {
    +    return { type: TokenType.RightCurly, value: '}', start, end: start + 1 };
    +  },
    +  identifier(start: number, value: string) {
    +    return {
    +      type: TokenType.Identifier,
    +      value,
    +      start,
    +      end: start + value.length,
    +    };
    +  },
    +};
    +
    +type SingleCharTokens = '(' | ')' | '{' | '}' | '=';
    +
    +// 单字符到 Token 生成器的映射
    +const KNOWN_SINGLE_CHAR_TOKENS = new Map<SingleCharTokens, (typeof TOKENS_GENERATOR)[keyof typeof TOKENS_GENERATOR]>([
    +  ['(', TOKENS_GENERATOR.leftParen],
    +  [')', TOKENS_GENERATOR.rightParen],
    +  ['{', TOKENS_GENERATOR.leftCurly],
    +  ['}', TOKENS_GENERATOR.rightCurly],
    +  ['=', TOKENS_GENERATOR.assign],
    +]);

    有了 Token 类型和对应生成的规则,我们便可以去遍历分析代码,输出分析后的结果。

    2.代码字符扫描

    在扫描字符的过程,我们需要对不同的字符各自进行不同的处理,具体的策略如下:

    • 当前字符为分隔符,如空格,直接跳过,不处理;
    • 当前字符为字母,需要继续扫描,获取完整的单词:
      • 如果单词为语法关键字,则新建相应关键字的 Token
      • 否则视为普通的变量名
    • 当前字符为单字符,如{、}、(、),则新建单字符对应的 Token
    ts
    export class Tokenizer {
    +  private _tokens: Token[] = [];
    +  private _currentIndex: number = 0;
    +  private _source: string;
    +  constructor(input: string) {
    +    this._source = input;
    +  }
    +  tokenize(): Token[] {
    +    while (this._currentIndex < this._source.length) {
    +      let currentChar = this._source[this._currentIndex];
    +      const startIndex = this._currentIndex;
    +
    +      // 根据语法规则进行 token 分组
    +      // while 循环内部
    +      let currentChar = this._source[this._currentIndex];
    +      const startIndex = this._currentIndex;
    +
    +      const isAlpha = (char: string): boolean => {
    +        return (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z');
    +      };
    +
    +      // 1. 处理空格
    +      if (currentChar === ' ') {
    +        this._currentIndex++;
    +        continue;
    +      }
    +      // 2. 处理字母
    +      else if (isAlpha(currentChar)) {
    +        let identifier = '';
    +        while (isAlpha(currentChar)) {
    +          identifier += currentChar;
    +          this._currentIndex++;
    +          currentChar = this._source[this._currentIndex];
    +        }
    +        let token: Token;
    +        if (identifier in TOKENS_GENERATOR) {
    +          // 如果是关键字
    +          token = TOKENS_GENERATOR[identifier as keyof typeof TOKENS_GENERATOR](startIndex);
    +        } else {
    +          // 如果是普通标识符
    +          token = TOKENS_GENERATOR['identifier'](startIndex, identifier);
    +        }
    +        this._tokens.push(token);
    +        continue;
    +      }
    +      // 3. 处理单字符
    +      else if (KNOWN_SINGLE_CHAR_TOKENS.has(currentChar as SingleCharTokens)) {
    +        const token = KNOWN_SINGLE_CHAR_TOKENS.get(currentChar as SingleCharTokens)!(startIndex);
    +        this._tokens.push(token);
    +        this._currentIndex++;
    +        continue;
    +      }
    +    }
    +    return this._tokens;
    +  }
    +}

    使用方式

    ts
    const tokenizer = new Tokenizer('let a = function() {}');

    结果

    ts
    const tokenizer = [
    +  { type: 'Let', value: 'let', start: 0, end: 3 },
    +  { type: 'Identifier', value: 'a', start: 4, end: 5 },
    +  { type: 'Assign', value: '=', start: 6, end: 7 },
    +  { type: 'Function', value: 'function', start: 8, end: 16 },
    +  { type: 'LeftParen', value: '(', start: 16, end: 17 },
    +  { type: 'RightParen', value: ')', start: 17, end: 18 },
    +  { type: 'LeftCurly', value: '{', start: 19, end: 20 },
    +  { type: 'RightCurly', value: '}', start: 20, end: 21 },
    +];

    一个简易版本的分词器已经被我们开发出来了,不过目前的分词器还比较简陋,仅仅支持有限的语法,不过在明确了核心的开发步骤之后,后面继续完善的过程就比较简单了。

    四。编写语法分析器(Parser)

    在解析出词法 token 之后,我们就可以进入语法分析阶段了。在这个阶段,我们会依次遍历 token ,对代码进行语法结构层面的分析,最后的目标是生成 AST 数据结构。至于代码的 AST 结构到底是什么样子,你可以去 AST Explorer 网站进行在线预览:

    接下来,我们要做的就是将 token 数组转换为上图所示的 AST 数据。

    开发步骤主要分为:

    • 初始化类型声明

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/babel.html b/src/article/babel.html new file mode 100644 index 0000000000..5e0f254937 --- /dev/null +++ b/src/article/babel.html @@ -0,0 +1,49 @@ + + + + + + Babel | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Babel

    babel 核心库主要是:

    • @babel/parser 对源码进行 parse,可以通过 plugins、sourceType 等来指定 parse 语法,功能是把源码转成 AST。
    • @babel/traverse 通过 visitor 函数对遍历到的 ast 进行处理,分为 enter 和 exit 两个阶段,具体操作 AST 使用 path 的 api,还可以通过 state 来在遍历过程中传递一些数据
    • @babel/types 用于创建、判断 AST 节点,提供了 xxx、isXxx、assertXxx 的 api
    • @babel/template 当需要批量创建 AST 的时候可以使用 @babel/template 来简化 AST 创建逻辑。
    • @babel/code-frame 可以创建友好的报错信息
    • @babel/generator 打印 AST 成目标代码字符串,支持 comments、minified、sourceMaps 等选项。
    • @babel/core 基于上面的包来完成 babel 的编译流程,并应用 plugin 和 preset。

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/bundle.html b/src/article/bundle.html new file mode 100644 index 0000000000..d94574e5ca --- /dev/null +++ b/src/article/bundle.html @@ -0,0 +1,49 @@ + + + + + + Bundle | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Bundle

    Bundle 的本质就是输入,转换,输出。在机器上直接运行的代码,往往都难以维护和理解,我们需要将开发者方便理解和维护的代码,通过打包等工具转换成方便机器或者程序使用的代码。对于 web 前端来说,打包工具,至少需要以下功能:

    • 编译能力
    • 插件机制
    • HMR
    • cli 和命令行能力

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/designMode.html b/src/article/designMode.html new file mode 100644 index 0000000000..d2901e08eb --- /dev/null +++ b/src/article/designMode.html @@ -0,0 +1,792 @@ + + + + + + 23 classic design patterns | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    23 classic design patterns

    The Design Pattern is a set of frequently used, widely known, cataloged code design experiences that are used in order to reuse code, make it easier for others to understand, and ensure code reliability.

    In the book "Design Patterns: The Foundation of Reusable Object-Oriented Software" introduced 23 classic design patterns, but the design pattern is not only these 23, with the development of software development industry, more and more new patterns continue to be born and applied. Experienced developers learn design patterns that can be corroborated with past experience, making it easier to understand them.

    A design pattern generally contains elements such as the pattern name, problem, purpose, solution, and effect. The problem describes when patterns should be used, and it contains problems with the design and why they exist. A solution describes the components of a design pattern and how these components relate to each other, their respective responsibilities, and how they work together. Typically, the solution is described through UML class diagrams and core code. Effects describe the advantages and disadvantages of the pattern and the trade-offs that should be made when using the pattern.

    Why learn design patterns:

    • Design patterns are derived from the experience and wisdom of many experts. They are successful and reusable design solutions from many excellent software systems. Using these solutions will allow us to avoid doing some repetitive work

    • Design patterns provide a common set of design vocabulary and a common form to facilitate communication and exchange between developers, making design solutions more understandable

    • Most of the design patterns take into account the reusability and extensibility of the system, which enables us to better reuse some existing design schemes, functional modules and even a complete software system, so as to avoid us often doing some repetitive design and writing some repetitive code

    • Proper use of design patterns and documentation of their use will help others understand the system more quickly

    • Learning design patterns will help beginners understand object-oriented ideas more deeply

    Reserve knowledge

    • Abstract class: The general abstract class is as a base class, for example, "computer" can be used as an abstract class, according to the abstract class derived "desktop computer" and "laptop computer" 2 concrete classes. Abstract classes are generally not instantiated.

    • Combination is better than inheritance: inheritance cannot be abused to expand functionality, and combination is more flexible. Also take the "computer" abstract class for example, if we use inheritance to distinguish different types of "computer" we can derive "desktop computer" and "laptop computer", if we add another dimension, according to the brand can continue to subdivide "Lenovo desktop computer", "Lenovo laptop", "Apple desktop computer" and "Apple laptop" and so on. If you add another dimension and continue to subdivide, it is clear that inheritance is not adequate. At this time, you can use inheritance and composition, and the combined object can also be abstract design:

      ts
      interface Brand {
      +  // ...
      +}
      +interface Lenovo extends Brand {
      +  // ...
      +}
      +interface Apple extends Brand {
      +  // ...
      +}
      +interface CPU {
      +  // ...
      +}
      +interface Inter extends CPU {
      +  // ...
      +}
      +interface AMD extends CPU {
      +  // ...
      +}
      +interface Computer {
      +  // ...
      +}
      +
      +interface DesktopComputer extends Computer {}
      +interface NotebookComputer extends Computer {}

    I, UML class diagram

    Each pattern has a corresponding object structure diagram, and in order to show the details of the interaction between objects, sometimes a 'UML' diagram is used to show how it works. Here will not be the various elements of 'UML' mentioned, just want to talk about the relationship between the classes in the class diagram, can understand the meaning of the lines and arrows between the classes in the class diagram, it is enough to deal with daily work and communication. At the same time, we should be able to match the meaning of the class diagram to the final code. With this knowledge, there is no problem looking at the design pattern structure diagram in the later sections.

    1.1 inherit

    Inheritance is represented directly by a hollow arrow.

    1.2 realize

    The implementation relationship is represented by a dashed line with a hollow arrow.

    1.3 assembly

    Like aggregation relations, composition relations also represent the semantics of a whole made up of parts. For example, a company is composed of multiple departments, but the combinatorial relationship is a special aggregation relationship of strong dependence, if the whole does not exist, then the part does not exist. For example, the company no longer exists, and the department will no longer exist.

    1.4 Polymerization

    Aggregation relationships are used to represent relationships between entity objects, representing the semantics of a whole made up of parts, such as a department consisting of multiple employees. Unlike combinatorial relations, the whole and the part are not strongly dependent, and even if the whole does not exist, the part still exists. For example, if the department is abolished, the personnel will not disappear, they will still exist.

    1.5 Association

    The association relationship is expressed by a straight line, which describes the structural relationship between objects of different classes. It is a static relationship, usually unrelated to the running state, and generally determined by common sense and other factors. It is generally used to define the static, natural structure between objects, so the association relationship is a "strong association" relationship.

    For example, the relationship between the passenger and the ticket is an association relationship, the student and the school is an association relationship, the association relationship does not emphasize the direction by default, indicating that the object knows each other. If particular emphasis is placed on direction, as shown in the figure below, it means that A knows B, but B does not know A.

    1.6 dependence

    Dependencies are represented by A set of dotted lines with arrows, such as A depends on B, which describes the relationship between one object and another object at runtime.

    Unlike an association relationship, it is a temporary relationship that usually occurs during run time, and dependencies may change as the run time changes. Obviously, dependence also has a direction, two-way dependence is a very bad structure, we should always maintain one-way dependence, eliminate the generation of two-way dependence.

    II, six principles

    2.1 Open and Close principle

    > A software entity should be open for extension and closed for modification. That is, software entities should extend as far as possible without modifying the original code.

    An important issue for any software is that its requirements change over time. When the software system needs to face new requirements, we should try to ensure that the design framework of the system is stable. If a software design conforms to the open-close principle, it can be very convenient to extend the system, and there is no need to modify the existing code when expanding, so that the software system has good stability and continuity while having adaptability and flexibility. As the software scale becomes larger and larger, the software life becomes longer and longer, and the software maintenance cost becomes higher and higher, it becomes more and more important to design the software system that meets the principle of open and close.

    In order to meet the open-close principle, the system needs to be abstract design, abstraction is the key to the open-close principle. In programming languages such as Java and C#, a relatively stable abstraction layer can be defined for the system, and different implementation behaviors can be moved to the concrete implementation layer. In many object-oriented programming languages, interfaces, abstract classes and other mechanisms can be used to define the abstract layer of the system, and then extend it through concrete classes. If it is necessary to modify the behavior of the system, there is no need to make any changes to the abstract layer, only need to add new concrete classes to achieve new business functions, to achieve the expansion of the system function on the basis of not modifying the existing code, to meet the requirements of the open-close principle.

    Advantages: The advantage of practicing the open-close principle is that you can extend the function of the program without changing the original code. The expansibility of the program is increased, and the maintenance cost of the program is reduced. **.

    2.2 Richter Substitution Principle

    > Any reference to a base class object can transparently use the object of its subclass

    The Richter substitution principle tells us that replacing a base class object with its subclass object in software will not cause any errors and exceptions, and the reverse is not true, if a software entity uses a subclass object, then it may not be able to use the base class object. For example, if I like animals, then I must like dogs, because dogs are a subclass of animals. But I like dogs, and it does not follow that I like animals, because I do not like mice, even though they are animals.

    For example, if there are two classes, one is BaseClass, the other is SubClass, and the SubClass is a subclass of the BaseClass class, then a method can accept a base class object of type BaseClass, such as: method1(base), then it must accept a subclass object of type BaseClass sub, and method1(sub) will work. The reverse substitution is not true, if a method method2 accepts sub of type BaseClass as an argument: method2(sub), then in general you can't have method2(base) unless it's an overloaded method.

    Richter substitution principle is one of the important ways to achieve the open and close principle, because the use of base class objects can use subclass objects, so in the program to try to use the base class type to define the object, and then determine its subclass type at run time, with subclass objects to replace the parent object.

    Advantages: You can test the correctness of the use of inheritance, and restrict the overflow of inheritance in use..

    2.3 Reliance on the inversion principle

    > Abstractions should not depend on concrete classes, and concrete classes should depend on abstractions. In other words, program against the interface, not the implementation.

    The principle of dependency inversion requires us to refer to high-level abstract layer classes as far as possible when passing parameters in program code or in association relations, that is, to use interfaces and abstract classes for variable type declaration, parameter type declaration, method return type declaration, and data type conversion, etc., rather than using concrete classes to do these things. In order to ensure the application of this principle, a concrete class should only implement methods declared in the interface or abstract class, and not give extra methods, otherwise it will not be able to call the new methods added in the subclass.

    After the introduction of the abstraction layer, the system will have good flexibility, in the program as far as possible to use the abstraction layer for programming, and the specific class is written in the configuration file, so that if the system behavior changes, only need to extend the abstraction layer, and modify the configuration file, without modifying the original system source code, in the case of no modification to expand the function of the system. Meet the requirements of the open and close principle.

    Advantages: Build a framework through abstraction and establish associations between classes to reduce coupling between classes. Moreover, the system built with abstraction is more stable, more scalable, and easier to maintain than the system built with concrete implementation. **.

    2.4 Principle of single responsibility

    > A class is only responsible for the corresponding responsibilities in one functional area, or it can be defined that there should be only one reason for a class to change.

    The principle of single responsibility tells us that a class can't be too "tired"! In a software system, the more responsibilities a class (from large modules to small methods) takes on, the less likely it is to be reused, and too many responsibilities a class takes on, the equivalent of coupling these responsibilities together, when one of the responsibilities changes, it may affect the operation of the other responsibilities, so the separation of these responsibilities. Encapsulate different responsibilities in different classes, that is, encapsulate different reasons for change in different classes, and encapsulate multiple responsibilities in the same class if they always change at the same time.

    The principle of single responsibility is a guideline to achieve high cohesion and low coupling. It is the simplest but most difficult principle to apply. It requires designers to discover different responsibilities of a class and separate them, while discovering multiple responsibilities of a class requires designers to have strong analysis and design ability and relevant practical experience.

    Advantages: If the class and method responsibilities are clearly divided, not only can improve the readability of the code, but also effectively reduce the risk of program errors, because the clear code will make the bug nowhere to hide, but also conducive to bug tracking, that is, reduce the maintenance cost of the program. **.

    2.5 Demeter's Law (Least Know Principle)

    > A software entity should interact with other entities as little as possible

    If a system conforms to Dimitar's law, then when one of the modules is modified, it will affect the other modules as little as possible, and it will be relatively easy to expand, which is a limit on the communication between software entities, Dimitar's law requires limiting the width and depth of communication between software entities. Demeter's rule can reduce the coupling degree of the system and keep the loose coupling relationship between classes.

    Demeter's law requires that when designing a system, we should minimize the interaction between objects, if two objects do not need to communicate directly with each other, then the two objects should not have any direct interaction, if one of the objects needs to call a method of another object, you can forward the call through a third party. In short, it is to reduce the coupling degree between existing objects by introducing a reasonable third party.

    When applying Dimitter's rule to system design, we should pay attention to the following points: in the division of classes, we should try to create loosely coupled classes, the lower the degree of coupling between classes, the more conducive to reuse, and once a class in loose coupling is modified, it will not cause too much impact on the associated classes. In the structural design of the class, every class should minimize the access permissions of its member variables and member functions. In class design, whenever possible, a type should be designed as an invariant class. References to other classes from one object should be kept to a minimum.

    Advantages: The practice of Demeter's rule can well reduce the coupling between classes, reduce the degree of correlation between classes, and make the collaboration between classes more direct..

    2.6 Interface Separation Rule

    > The use of multiple specialized interfaces rather than a single general interface means that the client should not rely on interfaces that it does not need.

    According to the principle of interface isolation, when an interface is too large, we need to split it into smaller interfaces, and the client using the interface only needs to know the methods associated with it. Each interface should assume a relatively independent role, do not do what should not be done, do what should be done.

    When using the interface isolation principle, you need to pay attention to the granularity of the control interface. If the interface is too small, the system may overflow interfaces, which is not conducive to maintenance. The interface can not be too large, too large interface will violate the interface isolation principle, poor flexibility, very inconvenient to use.

    Advantages: Avoid the method of containing different responsibilities in the same interface, and the division of interface responsibilities is more clear, in line with the idea of high cohesion and low coupling..

    2.7 Principle of Synthetic reuse (outside the six)

    > Try to use object composition rather than inheritance for reuse purposes

    The principle of composite reuse is to use some existing objects in a new object through association relations (including composition relations and aggregation relations), so that it becomes part of the new object, and the new object achieves the purpose of reuse functions by delegating methods to the existing object. In short, when reuse, use composition/aggregation relationships (association relationships) as much as possible and use inheritance less.

    In object-oriented design, there are two ways to reuse existing designs and implementations in different environments, namely through composition/aggregation relationships or through inheritance, but the use of composition/aggregation should be considered first. Composition/aggregation can make the system more flexible and reduce the coupling degree between classes. Changes in a class have relatively little impact on other classes, and then inheritance is considered. When using inheritance, it is necessary to strictly follow the Richlist substitution principle. Effective use of inheritance will help to understand the problem and reduce complexity, while abuse of inheritance will increase the difficulty of system construction and maintenance as well as the complexity of the system, so inheritance reuse should be carefully used.

    Advantages: Avoid abuse of inheritance when reuse, rational use of combination relations, increase flexibility..

    2.8 Six principles - Learning experience

    Among the six principles, the opening and closing principle, the Richter replacement principle, and the dependence and inversion principle are closely related, and the latter two are important prerequisites for realizing the opening and closing principle, and they have good scalability and maintainability through abstract design in use.

    The principle of knowing the least can reduce coupling, reduce unnecessary interaction, advocate the design of interfaces and classes to be simple and easy to use, encapsulate complex logic and provide simple and easy-to-use interfaces.

    Single Responsibility principle Divide the classes and methods in a project by responsibility to avoid overburdening a single class. The more responsibilities, the less likely they are to be reused or the more cumbersome they are to use.

    Interface separation principle The function of the complex interface is subdivided into a number of specific functions of the interface, only do the thing to do, reduce the coupling, but the granularity can not be too fine, easy to lead to too many interfaces. The single responsibility principle emphasizes the design of a single class according to the subdivision of responsibilities, and the interface separation principle emphasizes the coupling between classes to establish the least possible dependency.

    III. Pattern classification

    There are 23 distinct design patterns in Design Patterns: The Foundations of Reusable Object-Oriented Software, each of which provides a solution to a repeatable design problem. According to their purpose, design patterns can be divided into three types: 'Creational', 'Structural' and 'Behavioral', in which the creational pattern is mainly used to describe how to create objects, and the structural pattern is mainly used to describe how to achieve the combination of classes or objects. Behavioral patterns are primarily used to describe how classes or objects interact and how responsibilities are assigned.

    In addition, design patterns can be divided into class patterns and object patterns, depending on whether a pattern primarily deals with relationships between classes or between objects. We often use a combination of the two categories, for example, the singleton pattern is the object creation pattern, and the template method pattern is the class behavior pattern.

    3.1 Create type

    The 'Creational Pattern' abstracts the class instantiation process, separating the creation and use of objects in a module. In order to make the structure more clear, the outside world only needs to know their common interface for these objects, but is not clear about its specific implementation details, so that the design of the whole system is more in line with the principle of single responsibility.

    1. Simple Factory Pattern (' Simple Factory pattern ')
    2. Factory Method Pattern (' Factory method pattern ')
    3. Abstract Factory Pattern (' Abstract factory pattern ')
    4. 'Singleton Pattern'
    5. Builder Pattern (' Builder pattern ')
    6. Prototype Pattern (' Prototype pattern ')

    3.2 Structural type

    Structural patterns describe how classes or pairs of objects can be combined to form larger structures, like building blocks that can be combined to form complex, more powerful structures. Structured patterns can be divided into class structured patterns and object structured patterns:

    • The class structure pattern is concerned with the composition of classes. Multiple classes can be combined into a larger system. In the class structure pattern, there are generally only inheritance relations and implementation relations.

    • The object structure pattern is concerned with the combination of classes and objects, allowing an instance object of one class to be defined in another class through association, and its methods to be invoked through that object. According to the principle of "synthetic reuse", the associative relation is used to replace the successor relation in the system as much as possible, so most of the structural patterns are object structural patterns.

    1. Appearance mode
    2. Adapter mode
    3. Bridge mode
    4. Proxy mode
    5. Decorator mode
    6. Enjoy meta mode

    3.3 Behavioral patterns

    Behavioral patterns are abstractions that divide responsibilities and algorithms between different objects. The behavioral pattern focuses not only on the structure of classes and objects, but also on the interactions between them. Behavioral patterns allow you to more clearly divide the responsibilities of classes and objects and study the interactions between instance objects at runtime.

    1. Responsibility chain mode
    2. Command mode
    3. Interpreter mode
    4. Iterator mode
    5. Intermediary model
    6. Memo mode
    7. Observer mode
    8. Status mode
    9. Policy mode
    10. Template Method mode
    11. Visitor pattern

    IV, create type

    4.1 Simple Factory mode

    Simple Factory Pattern: A single class (factory class) is defined to be responsible for creating instances of other classes. Instances of different classes can be returned based on the parameters of the creation method, and the created instances usually have a common parent class.

    Example:

    The simple factory model is like a foundry, a factory can produce a variety of products. For example, a beverage processing plant helps produce both Pepsi and Coca-Cola, and the processing plant produces different products according to the input parameter 'Type'.

    ts
    interface Cola {}
    +
    +interface CocaCola extends Cola {}
    +
    +interface PepsiCola extends Cola {}
    ts
    // SimpleFactory
    +const createColaWithType = (type: number) => {
    +  switch (type) {
    +    case 0:
    +      return new CocaCola();
    +    case 1:
    +      return new PepsiCola();
    +    default:
    +      return null;
    +      break;
    +  }
    +};
    ts
    const cocaCola: CocaCola = createColaWithType(0);
    +
    +const pepsiCola: PepsiCola = createColaWithType(1);

    Advantages:

    • The user only needs to pass a correct agreed parameter to the factory class, and you can get the object you need, without knowing its creation details, to reduce the coupling of the system to a certain extent.
    • The client does not need to know the class name of the specific product class created, only needs to know the parameters corresponding to the specific product class, reducing the memory cost of the developer.

    Disadvantage:

    • If new products are added to the business, it is necessary to modify the original judgment logic of the factory class, which is actually contrary to the principle of opening and closing.
    • When there are many product types, the factory logic may be too complicated. Therefore, the simple factory model is more suitable for the situation where the product variety is relatively small and the probability of increasing is very low.

    4.2 Factory Method mode

    Factory Method Pattern (' factory method pattern ') is also known as the factory pattern, the factory parent class is responsible for defining the public interface for creating product objects, and the factory subclass is responsible for generating concrete product objects, that is, through different factory subclasses to create different product objects.

    Example:

    There are some differences between the factory method and the simple factory, the simple factory is the production of different products by a foundry, while the factory method is the abstraction of the factory, different products are produced by a specific factory. The Coca-Cola factory specializes in the production of Coca-Cola, and the Pepsi factory specializes in the production of Pepsi.

    ts
    // Factory abstract class
    +class Cola {}
    +
    +// The Coca-Cola Factory
    +class CocaCola extends Cola {}
    +
    +// Pepsi Factory
    +class PepsiCola extends Cola {}
    ts
    // Different products are produced according to different factory types
    +const cocaCola = new CocaCola();
    +const pepsiCola = new PepsiCola();

    Advantages:

    • Users only need to care about the specific factory corresponding to the product they need, do not need to care about the details of the creation of the product, do not need to know the class name of the specific product class.
    • When a new product is added to the system, it is not necessary to modify the interface provided by the abstract factory and the abstract product, nor to modify the client and other specific factories and specific products, but only to add a specific factory and its corresponding specific products, in line with the open and close principle.

    Disadvantage:

    • When a new product is added to the system, in addition to the new product class, the corresponding specific factory class must be provided. Therefore, the number of classes in the system will be increased in pairs, increasing the complexity of the system.

    4.3 Abstract factory pattern

    The abstract factory pattern does not directly generate instances, but is used to create clusters of product classes.

    Abstract Factory Pattern: Provides an interface for creating a series of related or interdependent objects without specifying their concrete classes.

    Example:

    The difference between the abstract factory and the factory method is that the factory that produces the product is abstract. For example, when Coca-Cola produces Coke, it also needs to produce bottles and boxes for Coke. The bottles and boxes are also customized by Coca-Cola, and Pepsi will also have this demand. At this time, our factory is not only a factory that produces cola drinks, but also has to produce bottles and boxes with the same theme at the same time, so it is an abstract theme factory, specializing in the production of different goods with the same theme.

    ts
    // Coke abstract classes and derived classes
    +class Cola {}
    +
    +class CocaCola extends Cola {}
    +
    +class PepsiCola extends Cola {}
    +
    +// Bottle abstract and derived classes
    +class Bottle {}
    +
    +class CocaColaBottle extends Bottle {}
    +
    +class PepsiColaBottle extends Bottle {}
    +
    +// Box abstract classes and derived classes
    +class Box {}
    +
    +class CocaColaBox extends Box {}
    +
    +class PepsiColaBox extends Box {}
    +
    +// Factory abstract class
    +const Factory = {
    +  createCola: () => new Cola(),
    +  createBottle: () => new Bottle(),
    +  createBox: () => new Box(),
    +};
    +
    +// Coca-Cola Theme Factory
    +const CocaColaFactory = {
    +  createCola: () => new CocaCola(),
    +  createBottle: () => new CocaColaBottle(),
    +  createBox: () => new CocaColaBox(),
    +};
    +
    +// Pepsi Theme Factory
    +const PepsiColaFactory = {
    +  createCola: () => new PepsiCola(),
    +  createBottle: () => new PepsiColaBottle(),
    +  createBox: () => new PepsiColaBox(),
    +};
    ts
    // Coca-Cola theme
    +const cocaCola = CocaColaFactory.createCola();
    +const cocaColaBottle = CocaColaFactory.createBottle();
    +const cocaColaBox = CocaColaFactory.createBox();
    +
    +// Pepsi theme
    +const pepsiCola = PepsiColaFactory.createCola();
    +const pepsiColaBottle = PepsiColaFactory.createBottle();
    +const pepsiColaBox = PepsiColaFactory.createBox();

    Advantages:

    • Product specific code isolation at the application layer, do not need to care about product details. When multiple objects in a product family are designed to work together, it ensures that the client always uses only objects in the same product family. This is a very practical design pattern for software systems that need to determine their behavior based on the current environment.

    Disadvantage:

    • Specifies the set of all products that can be created, the difficulty of extending new products in the product family, and the need to modify the interface of the abstract factory.

    4.4 Singleton pattern

    Singleton Pattern: The singleton pattern ensures that there is only one instance of a class and provides a full access point to it.

    Example:

    In singleton mode, the corresponding class can generate only one instance. Just as a kingdom can only have one king, once the affairs of the kingdom are too many, this only king is easy to take on too much responsibility.

    ts
    class Singleton {}
    +
    +function createSingleton() {
    +  let instance;
    +  return function () {
    +    if (!instance) return new Singleton();
    +    return instance;
    +  };
    +}

    Advantages:

    • Provides controlled access to unique instances. Because a singleton encapsulates its unique instance, it has tight control over how and when customers access it.
    • This class saves system resources because it has only one object in system memory.

    Disadvantage:

    Since there is no abstraction layer in the singleton pattern, singleton classes are difficult to extend.

    • For languages that have garbage collection systems, such as Java and C#, objects may be recycled if they are not utilized for a long time. If the singleton holds some data, it will no longer exist when it is reinstantiated after collection.

    4.5 Builder Pattern

    Builder Pattern: Also known as the creator pattern, it separates the construction of a complex object from its representation, allowing the same construction process to create different representations.

    The factory pattern is mainly for the creation of object instances or class clusters (abstract factories), concerned with the final output (creation) is what, not concerned with the creation process. The builder pattern is concerned with the entire process of creating the object, down to every detail of creating the object.

    Example:

    The main roles of the generator mode are as follows:

    1. Generator: The product construction steps common to all types of generators in the interface life
    2. Concrete generator: Provides different implementations of the construction process. Concrete generators can also construct products that do not follow a generic interface
    3. Product: is the final generated object. Products constructed from different generators need not belong to the same class of hierarchical constructs or interfaces
    4. Conductor: Define the order in which construction steps are called so that you can create and consume specific product configurations
    5. Client side: You must associate a generator object with a supervisor class. In general, you only need to do a one-time association through the parameters of the supervisor class constructor
    ts
    // Abstract Builder
    +abstract class Builder {
    +  public abstract buildPartA(): void;
    +  public abstract buildPartB(): void;
    +  public abstract buildPartC(): void;
    +  public abstract buildProduct(): Product;
    +}
    +
    +// Concrete builder
    +class ConcreteBuilder extends Builder {
    +  private product: Product;
    +  constructor(product: Product) {
    +    super();
    +    this.product = product;
    +  }
    +
    +  public buildPartA(): void {}
    +  public buildPartB(): void {}
    +  public buildPartC(): void {}
    +
    +  // Finally build a product
    +  public buildProduct(): Product {
    +    return this.product;
    +  }
    +}
    +
    +// Product role
    +class Product {
    +  public doSomething(): void {
    +    // Independent business
    +  }
    +}
    +
    +// director
    +class Director {
    +  private _builder: Builder;
    +  constructor(builder: Builder) {
    +    this._builder = builder;
    +  }
    +
    +  set builder(builder: Builder) {
    +    this._builder = builder;
    +  }
    +
    +  // Leave the process of handling the construction to the commander
    +  public constructorProduct() {
    +    this._builder.buildPartA();
    +    this._builder.buildPartB();
    +    this._builder.buildPartC();
    +    return this._builder.buildProduct();
    +  }
    +}
    +
    +// Use
    +const builder: Builder = new ConcreteBuilder(new Product());
    +const director: Director = new Director(builder);
    +const product: Product = director.constructorProduct();

    Advantages:

    • The client does not have to know the details of the internal composition of the product, decoupling the product itself from the product creation process, so that the same creation process can create different product objects.
    • Each concrete builder is relatively independent, and has nothing to do with other concrete builders, so it is easy to replace concrete builders or add new concrete builders, and users can get different product objects using different concrete builders.
    • Adding new concrete builders does not need to modify the code of the original class library, the command class is programmed for the abstract builder class, the system is easy to expand, and conforms to the "open and close principle".
    • The product creation process can be more finely controlled. Breaking down the creation steps of complex products into different methods makes the creation process clearer and easier to use programs to control the creation process.

    Disadvantage:

    • The products created by the builder mode generally have more in common and their components are similar. If the differences between products are large, the builder mode is not suitable for use, so its scope of use is limited. If the internal changes of the product are complex, it may lead to the need to define many concrete constructor classes to achieve such changes, resulting in a large system, increasing the difficulty of understanding the system and the cost of operation.

    4.6 Prototype Pattern

    Prototype Pattern: A prototype instance points to the class that created the object, and uses the properties and methods of the shared prototype used by the class that created the new object.

    Example:

    Prototype mode is like photocopying technology, copy a new object from the original object, and fine-tune the new object according to the needs.

    ts
    // Because it's not a constructor, you don't use capitalization
    +const car = {
    +  drive: function () {},
    +  name: 'The Mazda 3',
    +};
    +
    +// Create a new car x using Object.create
    +const anotherCar = Object.create(someCar);
    +anotherCar.name = 'Mike';
    ts
    const vehiclePrototype = {
    +  init: function (carModel) {
    +    this.model = carModel;
    +  },
    +  getModel: function () {
    +    console.log('The vehicle mold is:' + this.model);
    +  },
    +};
    +
    +function vehicle(model) {
    +  function F() {}
    +  F.prototype = vehiclePrototype;
    +
    +  const f = new F();
    +
    +  f.init(model);
    +  return f;
    +}
    +
    +const car = vehicle('Ford Escort');
    +car.getModel();

    Advantages:

    • The prototype mode can be used to simplify the object creation process, especially for some objects with complicated creation process and many object levels, the prototype mode can save system resources and improve the efficiency of object generation.
    • It is easy to generate new objects by changing the values: some objects may differ only from one another in certain values; Using prototype mode, you can quickly copy new objects and manually modify the values.

    Disadvantage:

    • All objects contained in an object need to be equipped with a clone method, which makes the amount of code in the case of more object levels will be large and more complex.

    V, structural type

    5.1 Decorative pattern

    Decorator Pattern: The design pattern that adds new functionality to an existing object without changing its structure is called the decorator pattern, which acts as a wrapper around an existing class.

    You can think of decorators as equipment purchased by game characters, such as heroes in LOL who start the game with only basic attack power and mana. However, after the purchase of equipment, you can enjoy the output bonus brought by the equipment when triggering attacks and skills. We can understand the purchase of equipment to give the hero's attack and skill related methods decorated.

    Example:

    The decorative mode conforms to the open-close principle and transforms or adds new functions to the parent class without changing the original class.

    decoration

    ts
    @annotation
    +class MyClass {}
    +
    +function annotation(target) {
    +  target.annotated = true;
    +}

    Decorative method or attribute

    js
    class MyClass {
    +  @readonly
    +  method() {}
    +}
    +
    +function readonly(target, name, descriptor) {
    +  descriptor.writable = false;
    +  return descriptor;
    +}

    Advantages:

    • More flexible than inheritance: unlike inheritance, which works at compile time; Decorator mode can extend the functionality of an object at run time. It is also possible to select different decorators at run time through configuration files to achieve different behavior. It can also achieve different effects through different combinations.
    • Comply with the "open and close principle" : the decorator and the decorator can vary independently. Users can add new decorative classes as needed, and then combine them when they are used, without changing the original code.

    Disadvantage:

    • Decorator mode requires the creation of some concrete decorator classes, which increases the complexity of the system.

    5.2 外观模式

    Facade Pattern: A facade pattern defines a high-level interface that provides a unified interface for a set of interfaces in a subsystem. It makes the subsystem easier to use, not only simplifying the interfaces in the class, but also decoupling the caller from the interface. Appearance mode, also known as facade mode, is a structural design mode.

    Example:

    Appearance patterns provide a simple and unambiguous interface, but integrate many subsystem functions internally. Just like the image cache, which contains processing involving other subsystems such as caching, downloading, etc., the appearance pattern hides the complex logic. In the compatible browser event binding, you only need to call an 'addMyEvent' interface can be, to achieve the purpose of decoupling.

    js
    const addMyEvent = function (el, ev, fn) {
    +  if (el.addEventListener) {
    +    el.addEventListener(ev, fn, false);
    +  } else if (el.attachEvent) {
    +    el.attachEvent('on' + ev, fn);
    +  } else {
    +    el['on' + ev] = fn;
    +  }
    +};

    Advantages:

    • Decoupling between the client and the subsystem is realized: the client does not need to know the interface of the subsystem, simplifying the process of the client calling the subsystem, making the subsystem easier to use. At the same time, it is easy to expand and maintain the subsystem.
    • Demeter's law (least know principle) : The subsystem only needs to expose the interface that needs external calls to the appearance class, and its interface can be hidden.

    Disadvantage:

    • Violates the open-close principle: Adding a new subsystem without introducing abstract facade classes may require changes to facade classes or client code.

    5.3 代理模式

    Proxy Pattern: Provide a proxy for an object, and this proxy object controls access to the original object.

    Example:

    The agent model is like a housing agent, the buyer can only buy a house through the intermediary, the agent has all the functions of the agent, just as the landlord has the function of selling the house, the intermediary also has the function of selling the house. In addition, the agent instance can also help the agent to carry out some additional processing, such as the function of the intermediary to help the landlord screen quality buyers, and help the landlord pass some unqualified buyers. The same pattern applies to message queues.

    Reference 'koa' in the proxy mode, the 'response' on some properties and methods proxy out, easy to use

    js
    /**
    + * Response delegation.
    + */
    +const delegate = require('delegates');
    +
    +const prototype = (module.exports = {});
    +
    +delegate(prototype, 'response')
    +  .method('attachment')
    +  .method('redirect')
    +  .method('remove')
    +  .method('vary')
    +  .method('has')
    +  .method('set')
    +  .method('append')
    +  .method('flushHeaders')
    +  .access('status')
    +  .access('message')
    +  .access('body')
    +  .access('length')
    +  .access('type')
    +  .access('lastModified')
    +  .access('etag')
    +  .getter('headerSent')
    +  .getter('writable');

    Make a proxy for 'context', 'request', 'response', protecting the real 'context', 'request', 'response'

    js
    this.context = Object.create(context);
    +this.request = Object.create(request);
    +this.response = Object.create(response);

    Advantages:

    • Reduce the coupling degree of the system: The proxy mode can coordinate the caller and the called, which reduces the coupling degree of the system to a certain extent.
    • Different types of proxies can have different controls on the client's access to the target object:
    • A remote agent that allows the client to access objects on a remote machine that may have better computational performance and processing speed and can respond and process client requests quickly. By using a small object to represent a large object, virtual agents can reduce the consumption of system resources, optimize the system, and increase the speed of operation.
    • The protection agent can control the client's permission to use real objects.

    Disadvantage:

    • Adding a proxy object between the client and the proxy object may slow down client requests.

    5.4 Flyweight Pattern

    Flyweight Pattern: The meta mode is a mode that optimizes program performance, essentially reducing the number of objects created. Using sharing technology to reuse a large number of fine-grained objects, reduce the program memory occupation, improve the performance of the program. Share metamode can be used when there are a large number of similar objects that occupy a large amount of memory. Most of the state in an object can be extrapolated to external state.

    Example:

    For example, a music service can be divided into free users and member users based on fees. Free users can only listen to some free music, and member users can listen to all music and can download it. Although there are some differences in permissions between the two, the music they enjoy is from the same library, so all the music needs to be saved only one copy. In addition, if there is no music in the music library, you need to add the music, and then other services can also enjoy the new music, which is equivalent to the function of the share pool or cache pool.

    The share mode area ensures that the internal state is shared, such as the music library, while the external state is customized according to different needs, such as various access rights, and the internal state cannot be changed during use to achieve the purpose of sharing.

    ts
    // Music service
    +const MusicService = {}
    +
    +// Shared music library
    +const musicLibrary = {};
    +
    +// Listen to music
    +const listenToMusic = (music) => {
    +    ...
    +}
    +// Download music
    +const downloadMusic = (music) => {
    +    ...
    +}
    +
    +
    +// Free music service
    +const FreeMusicService = {
    +    listenFreeMusic: (music)=>{
    +        if(isMusicFree(music)){
    +            // If it is free, play it
    +            listenToMusic()
    +        }else{
    +         // If it is paid music, the user is prompted to upgrade the Vip Vip
    +            console.log("please upgrade to Vip")
    +        }
    +    }
    +}
    +
    +
    +// Vip Music Service
    +const VipMusicService = {
    +    // You can listen to all the music
    +    listenMusic
    +    // You can download music
    +    downloadMusic
    +}

    Advantages:

    • The use of the share module can reduce the number of objects in memory, so that the same object or similar objects in memory only one copy, reduce the system memory usage, can also improve performance.
    • The external state of the share meta pattern is relatively independent and does not affect its internal state, so that share meta objects can be shared in different environments.

    Disadvantage:

    • Using the meta pattern requires the separation of internal and external states, which complicates the logic of the program.
    • Object reuse in buffer pools requires consideration of threading issues.

    5.5 Simple Factory Pattern

    Simple Factory Pattern: Separate the abstract part from its implementation part so that they can both vary independently.

    Example:

    Both balls and people can move, but balls have movement and colors, and people can move and talk. Abstract the common parts.

    js
    class Speed {
    +  // Motion module
    +  constructor(x, y) {
    +    this.x = x;
    +    this.y = y;
    +  }
    +  run() {
    +    console.log(`Get into motion ${this.x} + ${this.y}`);
    +  }
    +}
    +
    +class Color {
    +  // Coloring module
    +  constructor(cl) {
    +    this.color = cl;
    +  }
    +  draw() {
    +    console.log(`Draw color ${this.color}`);
    +  }
    +}
    +
    +class Speak {
    +  constructor(wd) {
    +    this.word = wd;
    +  }
    +  say() {
    +    console.log(`talk ${this.word}`);
    +  }
    +}
    +
    +class Ball {
    +  // Create balls that can be colored and moved
    +  constructor(x, y, cl) {
    +    this.speed = new Speed(x, y);
    +    this.color = new Color(cl);
    +  }
    +  init() {
    +    this.speed.run();
    +    this.color.draw();
    +  }
    +}
    +
    +class Man {
    +  // Humans can move and talk
    +  constructor(x, y, wd) {
    +    this.speed = new Speed(x, y);
    +    this.speak = new Speak(wd);
    +  }
    +  init() {
    +    this.speed.run();
    +    this.speak.say();
    +  }
    +}
    +
    +const man = new Man(1, 2, 'hello ?');
    +man.init();

    Advantages:

    • Good scalability, in line with the principle of open and close: separation of abstraction and implementation, so that the two can change independently

    Disadvantage:

    • Two independently varying dimensions need to be identified before design.

    5.6 Adapter Pattern

    Adapter Pattern: Adapter mode is used to solve the incompatibility of two interfaces, do not need to change the existing interface, through the packaging of a layer, to achieve normal cooperation between the two interfaces. When we try to call an interface of a module or object, but find that the format of the interface does not meet the current requirements, we can use the adapter pattern.

    Example:

    Event binding is compatible with all browsers

    js
    function addEvent(ele, event, callback) {
    +    if (ele.addEventListener) {
    +      ele.addEventListener(event, callback)
    +    } else if(ele.attachEvent) {
    +      ele.attachEvent('on' + event, callback)
    +    } else {
    +      ele['on' + event] = callback
    +    }
    +  }
    +

    Advantages:

    • Comply with the principle of open and close: use adapters without changing existing classes, improving class reusability.
    • Decouple the target class from the adapter class to improve program extensibility.

    Disadvantage:

    • Increased the complexity of the system

    VI. Behavior pattern

    6.1 Chain of Responsibility Pattern

    Chain of Responsibility Pattern: Avoid coupling the request sender with the receiver, make it possible for multiple objects to receive the request, connect those objects into a chain, and pass the request along the chain until an object handles it. The responsibility chain pattern is an object behavior pattern. Similar to dominoes, by requesting the first condition, subsequent conditions continue to be executed until a result is returned.

    Example:

    Scenario: An e-commerce has a preferential policy for users who have paid a deposit, after the formal purchase, users who have paid a deposit of 500 yuan will receive a coupon of 100 yuan, users who have paid a deposit of 200 yuan can receive a coupon of 50 yuan, and users who have not paid a deposit can only buy normally.

    js
    const order500 = function (orderType, pay, stock) {
    +  if (orderType === 1 && pay == true) {
    +    console.log('500 yuan deposit advance purchase, get 100 yuan coupon');
    +  } else {
    +    return 'nextSuccess';
    +  }
    +};
    +const order200 = function (orderType, pay, stock) {
    +  if (orderType === 2 && pay === true) {
    +    console.log('200 yuan deposit pre-order, get 50 yuan coupon');
    +  } else {
    +    return 'nextSuccess';
    +  }
    +};
    +const orderCommon = function (orderType, pay, stock) {
    +  if (orderType == 3 && stock > 0) {
    +    console.log('Regular purchase, no coupon');
    +  } else {
    +    console.log('Insufficient stock');
    +  }
    +};
    +// Link code
    +const chain = function (fn) {
    +  this.fn = fn;
    +  this.successor = null;
    +};
    +chain.prototype.setNext = function (successor) {
    +  this.successor = successor;
    +};
    +chain.prototype.init = function () {
    +  const result = this.fn.apply(this, arguments);
    +  if (result == 'nextSuccess') {
    +    this.successor.init.apply(this.successor, arguments);
    +  }
    +};
    +const order500New = new chain(order500);
    +const order200New = new chain(order200);
    +const orderCommonNew = new chain(orderCommon);
    +order500New.setNext(order200New);
    +order200New.setNext(orderCommonNew);
    +order500New.init(3, true, 500); // Regular purchase, no coupons

    Advantages:

    The responsibility chain mode makes an object not need to know which other object handles its request, the object only needs to know that the request will be processed, the receiver and the sender have no clear information about each other, and the object in the chain does not need to know the chain structure, the client is responsible for the creation of the chain, reducing the coupling degree of the system.

    • The request processing object only needs to maintain a reference to its successor, rather than maintaining a reference to all of its candidate handlers, simplifying object interconnections. The responsibility chain gives us more flexibility when assigning responsibilities to objects. The responsibility for handling a request can be added or changed by dynamically adding or modifying the chain at runtime.
    • Adding a new specific request handler to the system does not need to modify the code of the original system, only needs to rebuild the chain on the client side, from this point of view is in line with the "open and closed principle".

    Disadvantage:

    Since a request has no clear recipient, there is no guarantee that it will be processed, and the request may not be processed until the end of the chain; A request may also not be processed because the chain of responsibility is not configured correctly.

    • For a long chain of responsibility, the processing of requests may involve multiple processing objects, which will affect system performance and make it inconvenient for code debugging.
    • If the chain is not properly built, circular calls may be caused, resulting in a dead loop of the system.

    6.2 Command Pattern

    Command Pattern: Encapsulating a request as an object allows us to parameterize customers with different requests; Command mode is an object behavior mode, which is alias' Action 'mode or' Transaction 'mode.

    The command mode consists of three roles:

    1. Publisher 'invoker' (issues command, calls command object, does not know how to execute and whom to execute);
    2. receiver 'receiver' (provides the corresponding interface to process the request, and does not know who initiates the request);
    3. The command object 'command' (receives the command and invokes the corresponding interface of the receiver to process the publisher's request). The publisher invoker and the receiver are independent and encapsulate the request into a command object command. The specific execution of the request is executed by the command object calling the corresponding interface of the receiver.

    Example:

    Similar to the previous example in proxy mode, but the essence of command mode is to encapsulate commands, separating the responsibility for issuing commands from the responsibility for executing them. For example, the remote control is a caller, different buttons represent different commands, and the TV is the receiver.

    js
    class Receiver {
    +  // Receiver class
    +  execute() {
    +    console.log('Receiver execute request');
    +  }
    +}
    +
    +class Command {
    +  // Command object class
    +  constructor(receiver) {
    +    this.receiver = receiver;
    +  }
    +  execute() {
    +    // The call receiver executes against the interface
    +    console.log('Command object -> Receiver -> Corresponding interface execution');
    +    this.receiver.execute();
    +  }
    +}
    +
    +class Invoker {
    +  // Publisher class
    +  constructor(command) {
    +    this.command = command;
    +  }
    +  invoke() {
    +    // Issue a request, invoke a command object
    +    console.log('The publisher publishes the request');
    +    this.command.execute();
    +  }
    +}
    +
    +const warehouse = new Receiver(); // Stash
    +const order = new Command(warehouse); // Order for goods
    +const client = new Invoker(order); // client
    +client.invoke();

    Advantages:

    • Reduce the coupling degree of the system. Since there is no direct reference between the requester and the receiver, the requester and the receiver realize complete decoupling, the same requester can correspond to different receivers, similarly, the same receiver can also be used by different requesters, and there is good independence between the two.
    • New commands can be easily added to the system. Since the addition of new specific command classes does not affect other classes, it is easy to add new specific command classes without modifying the original system source code, or even the customer class code, to meet the requirements of the "open and close principle".
    • It is relatively easy to design a command queue or macro command (composite command).
    • Provides a design and implementation scheme for requested Undo and Redo operations.

    Disadvantage:

    • Using command mode may cause some systems to have too many specific command classes. Because a concrete command class needs to be designed for each call to the receiver of the request, a large number of concrete command classes may need to be provided in some systems, which will affect the use of command patterns.

    6.3 Interpreter Pattern

    Interpreter Pattern: Define the grammar of a language and build an interpreter to interpret sentences in that language, where "language" means code that uses a specified format and syntax. The interpreter pattern is a kind of behavior pattern.

    Example:

    Given a language, define a representation of its grammar and an interpreter that uses that representation to interpret sentences in the language.

    js
    class Context {
    +  constructor() {
    +    this._list = []; // Stores terminal expressions
    +    this._sum = 0; // Store nonterminal expressions
    +  }
    +
    +  get sum() {
    +    return this._sum;
    +  }
    +  set sum(newValue) {
    +    this._sum = newValue;
    +  }
    +  add(expression) {
    +    this._list.push(expression);
    +  }
    +  get list() {
    +    return [...this._list];
    +  }
    +}
    +
    +class PlusExpression {
    +  interpret(context) {
    +    if (!(context instanceof Context)) {
    +      throw new Error('TypeError');
    +    }
    +    context.sum = ++context.sum;
    +  }
    +}
    +class MinusExpression {
    +  interpret(context) {
    +    if (!(context instanceof Context)) {
    +      throw new Error('TypeError');
    +    }
    +    context.sum = --context.sum;
    +  }
    +}
    +
    +/** Here is the test code **/
    +const context = new Context();
    +
    +// Add in order: Add | add | subtract expression
    +context.add(new PlusExpression());
    +context.add(new PlusExpression());
    +context.add(new MinusExpression());
    +
    +// Execute the following: add | add | subtract expression
    +context.list.forEach((expression) => expression.interpret(context));
    +console.log(context.sum);

    Advantages:

    • Easy to change and extend grammar. Because classes are used in the interpreter schema to represent the grammar rules of the language, the grammar can be changed or extended through mechanisms such as inheritance. Each rule can be represented as a class, so it is easy to implement a simple language.
    • The grammar is easier to implement. Each expression node class in the abstract syntax tree is implemented in a similar way, the code for these classes is not particularly complicated, and some tools can automatically generate node class code.
    • It is easier to add new interpretation expressions. If the user needs to add a new interpretation expression, it only needs to add a new terminal expression or non-terminal expression class, and the original expression class code does not need to be modified, which conforms to the "open and closed principle".

    Disadvantage:

    • Difficult to maintain for complex grammars. In the interpreter mode, each rule needs to define at least one class, so if a language contains too many grammar rules, the number of classes will increase dramatically, resulting in a system difficult to manage and maintain, at this time you can consider using a parser to replace the interpreter mode.
    • Low execution efficiency. Because of the large number of loops and recursive calls used in the interpreter mode, it is slow to interpret more complex sentences, and the debugging process of the code is cumbersome.

    6.4 Iterator Pattern

    Iterator Pattern: A relatively simple pattern, most languages now have iterators built in, so that people don't think of it as a design pattern. Iterators don't just iterate over arrays; iterators can be aborted. Provides a way to access aggregate objects without exposing the internal representation of the object, which is alias a Cursor. The iterator pattern is an object behavior pattern.

    Example:

    Iterators help requesters get the data, avoiding direct manipulation of the data aggregation class and allowing the data aggregation class to focus on storing the data. The specific application has pagination and other functions, and the iterator of the pagination function will be specially responsible for operating the pagination data, separating the operation logic from the data source.

    js
    var each = function (arr, callback) {
    +  for (var i = 0, len = arr.length; i < len; i++) {
    +    callback.call(arr[i], i, arr[i]);
    +  }
    +};
    +
    +each([1, 2, 3, 4, 5], function (i, el) {
    +  console.log('index: ', i);
    +  console.log('item: ', el);
    +});

    Advantages:

    • It supports traversing an aggregate object in different ways, and multiple traversing modes can be defined on the same aggregate object. Iterator mode can be changed by simply replacing the iterator with a different iterator, or we can define our own iterator subclasses to support the new iterator.
    • Iterators simplify aggregate classes. Due to the introduction of iterators, it is no longer necessary to provide data traversal methods in the original aggregate object, which can simplify the design of the aggregate class.
    • In the iterator mode, due to the introduction of the abstraction layer, it is convenient to add new aggregate classes and iterator classes without modifying the original code, which meets the requirements of the "open and closed principle".

    Disadvantage:

    Because the iterator pattern separates the responsibility of storing data and traversing data, adding new aggregate classes requires adding new iterator classes, and the number of classes increases in pairs, which increases the complexity of the system to some extent.

    • The design of the abstract Iterator is more difficult and needs to fully consider the future extension of the system, for example, the JDK built-in iterator cannot achieve reverse traversal, if you need to achieve reverse traversal, it can only be achieved through its subclass ListIterator, etc. ListIterator iterators cannot be used to manipulate aggregate objects of type Set. When customizing iterators, it is not easy to create an abstract iterator that considers all aspects.

    6.5 Mediator Pattern

    Mediator Pattern: Objects communicate with each other through third-party intermediaries. Encapsulate a set of object interactions with a mediator, which allows objects to be loosely coupled without explicitly referring to each other, and can change their interactions independently. The mediator model, also known as the mediator model, is an object behavior model.

    Example:

    The broker pattern turns a network system structure into a star structure centered on broker objects, where one-to-many relationships between broker objects and other objects replace many-to-many relationships between objects. All members interact through intermediaries to facilitate the expansion of new members, such as the following example, after the end of a test, the result is announced: tell the person who solved the challenge successfully, otherwise the challenge fails. In this code, there is no direct relationship between A, B, and C, but a link is established through another playerMiddle object, which is considered the mediator pattern.

    js
    const player = function (name) {
    +  this.name = name;
    +  playerMiddle.add(name);
    +};
    +player.prototype.win = function () {
    +  playerMiddle.win(this.name);
    +};
    +player.prototype.lose = function () {
    +  playerMiddle.lose(this.name);
    +};
    +const playerMiddle = (function () {
    +  // We're going to use this demo, this function as a mediator
    +  const players = [];
    +  const winArr = [];
    +  const loseArr = [];
    +  return {
    +    add: function (name) {
    +      players.push(name);
    +    },
    +    win: function (name) {
    +      winArr.push(name);
    +      if (winArr.length + loseArr.length === players.length) {
    +        this.show();
    +      }
    +    },
    +    lose: function (name) {
    +      loseArr.push(name);
    +      if (winArr.length + loseArr.length === players.length) {
    +        this.show();
    +      }
    +    },
    +    show: function () {
    +      for (let winner of winArr) {
    +        console.log(winner + 'Challenge success;');
    +      }
    +      for (let loser of loseArr) {
    +        console.log(loser + 'Challenge failure;');
    +      }
    +    },
    +  };
    +})();
    +const a = new player('A-player');
    +const b = new player('B-player');
    +const c = new player('C-player');
    +a.win();
    +b.lose();
    +c.win();
    +// A Contestant successfully challenged;
    +// B Contestant successfully challenged;
    +// C Player fails to challenge;

    Advantages:

    The -mediator pattern simplifies interactions between objects. It replaces many-to-many interactions between colleagues with one-to-many interactions between intermediaries and colleagues. One-to-many relationships are easier to understand, maintain, and extend, transforming the previously difficult network structure into a relatively simple star structure.

    • Mediator mode decouples colleague objects. Intermediaries are conducive to the loose coupling between colleagues, we can independently change and reuse each colleague and intermediary, adding new intermediaries and new colleague classes are more convenient, better in line with the "open and close principle".
    • Can reduce subclass generation, intermediaries will be distributed across multiple objects in a group of behaviors, change these behaviors only need to generate new intermediary subclasses, this allows individual colleague classes can be reused without the need to extend the colleague classes.

    Disadvantage:

    The inclusion of a large number of details about interactions between colleagues in a specific broker class can make the specific broker class very complex and make the system difficult to maintain.

    6.6 Memento Pattern

    Memento Pattern: Capture the internal state of an object, without breaking the encapsulation, and save that state outside the object for later use or for the object to revert to a previous state. It is an object behavior pattern that is alias Token.

    Example:

    Memo mode provides a state recovery implementation mechanism, so that users can easily return to a specific historical step, when the new state is invalid or there is a problem, you can use the temporary storage of the memo to restore the state, many software provides undo operations, which uses the memo mode.

    When we develop a paging component, click on the next page to get new data, but when click on the previous page, and get data again, resulting in unnecessary traffic waste, then the data can be cached.

    js
    // Memo mode pseudo-code
    +var Page = function () {
    +  // cache objects are used to cache data
    +  var cache = {};
    +  return function (page, fn) {
    +    if (cache[page]) {
    +      showPage(page, cache[page]);
    +    } else {
    +      $.post('/url', function (data) {
    +        showPage(page, data);
    +        cache[page] = data;
    +      });
    +    }
    +    fn && fn();
    +  };
    +};

    Advantages:

    • It provides a state recovery implementation mechanism, so that users can easily go back to a specific historical step, when the new state is invalid or there is a problem, you can use a temporary stored memo to restore the state.
    • Memos encapsulate information. A memos object is a representation of the state of the originator object and cannot be changed by other code. Memos save the state of the originator, using lists, stacks and other collections to store memos can achieve multiple undo operations.

    Disadvantage:

    • Excessive resource consumption. If too many member variables of the originator class need to be saved, a large amount of storage space is inevitably required. Each time the state of an object is saved, certain system resources are consumed.

    6.7 Observer Pattern

    Observer Pattern: Define a one-to-many dependency relationship between objects so that each time an object's state changes, its dependent objects are notified and automatically updated. Aliases for the observer pattern include the 'Publish/Subscribe' pattern, the model-view (' Model/View ') pattern, the Source/Listener (' source/listener ') pattern, or the 'Dependents' pattern. The observer pattern is an object behavior pattern.

    Example:

    The observer pattern is one of the most frequently used design patterns, and it is used to establish a dependency relationship between objects. When one object changes, the other objects are automatically notified, and the other objects react accordingly.

    The implementation of the observer pattern in JavaScript uses the event model, the DOM event.

    js
    // publisher
    +var pub = function () {
    +  console.log('Welcome to subscribe!');
    +};
    +// Subscribers
    +var sub = document.body;
    +
    +// Subscribers implement subscriptions
    +sub.addEventListener('click', pub, false);

    Advantages:

    The observer pattern can realize the separation of the presentation layer and the data logic layer, define a stable message update delivery mechanism, and abstract the update interface, so that there can be a variety of different presentation layers to act as a concrete observer role.

    • Observer mode establishes an abstract coupling between the object of observation and the observer. The object of observation needs only to maintain a set of abstract observers, without knowing its concrete observers. Because the object of observation and the observer are not tightly coupled, they can belong to different levels of abstraction. Observer mode supports broadcast communication, and the observer will send notifications to all registered observer objects, simplifying the difficulty of one-to-many system design.
    • Observer mode meets the requirements of the "open and close principle", adding new specific observers does not require modifying the original system code, and it is also convenient to add new observation targets when there is no correlation between specific observers and observation targets.

    Disadvantage:

    If an observation target has many direct and indirect observers, it takes a lot of time to notify all of them.

    • If there is a cyclic dependency between the observer and the observing target, the observing target will trigger a cyclic call between them, possibly causing the system to crash. The observer mode has no mechanism for the observer to know how the object being observed has changed, but only to know that the object being observed has changed.

    6.8 State Pattern

    State Pattern: By allowing an object to change its behavior when its internal state changes, the object appears to modify its class. Its alias is the state object (' Objects for States'), in fact, is to use an object or array to record a set of states, each state corresponds to an implementation, the implementation according to the state to run the implementation. The state pattern is an object behavior pattern.

    Example:

    State mode is used to solve the problem of state transition of complex objects and encapsulation of behavior in different states. When an object in the system has multiple states, these states can be transformed between, so objects in different states have different behaviors can be used when the state mode. The state mode separates the state of an object from the object and encapsulates it into a special state class, making the state of the object flexible.

    For example, Super Mary may have several states at the same time, such as jumping, moving, shooting, squatting, etc. if these actions are processed and judged one by one, multiple if-else or switch are required. Not only is it ugly, but when there are combined actions, the implementation will become more complicated. This can be done using the state mode.

    The idea of state mode is: first create a state object or array, store state variables inside, and then internally encapsulate the corresponding state of each action, and then the state object returns an interface object, which can modify or call the internal state.

    js
    class SuperMarry {
    +  constructor() {
    +    this._currentState = [];
    +    this.states = {
    +      jump() {
    +        console.log('Jumping!');
    +      },
    +      move() {
    +        console.log('Move!');
    +      },
    +      shoot() {
    +        console.log('Shoot!');
    +      },
    +      squat() {
    +        console.log('Keep down!');
    +      },
    +    };
    +  }
    +
    +  change(arr) {
    +    // Change current action
    +    this._currentState = arr;
    +    return this;
    +  }
    +
    +  go() {
    +    console.log('Trigger action');
    +    this._currentState.forEach((T) => this.states[T] && this.states[T]());
    +    return this;
    +  }
    +}
    +
    +new SuperMarry()
    +  .change(['jump', 'shoot'])
    +  .go() // Trigger action jump! Shoot!
    +  .go() // Trigger action jump! Shoot!
    +  .change(['squat'])
    +  .go(); // Trigger action Crouch!

    Advantages:

    • Encapsulates the state transition rules. In the state mode, the state transition code can be encapsulated in the environment class or specific state class, and the state transition code can be centrally managed, rather than dispersed in one business method.
    • Put all the behavior related to a state into a class, just inject a different state object to make the environment object have different behavior.
    • Allowing state transition logic to be integrated with state objects, rather than providing a huge block of conditional statements, state patterns allow us to avoid using huge conditional statements to interweave business methods and state transition code.
    • Multiple environment objects can share a state object, thereby reducing the number of objects in the system.

    Disadvantage:

    • The use of state mode will inevitably increase the number of classes and objects in the system, resulting in increased system operating overhead.
    • The structure and implementation of the state mode are relatively complex, if used improperly will lead to the program structure and code confusion, increase the difficulty of system design.
    • The state mode does not support the "open and closed principle" very well, adding a new state class needs to modify the source code responsible for the state transition, otherwise it cannot be converted to the new state; And modifying the behavior of a state class also requires modifying the source code of the corresponding class.

    6.9 Strategy Pattern

    Strategy Pattern: Define a list of algorithms, wrap them up, and be interchangeable. It is to extract and encapsulate seemingly unrelated code and reuse it to make it easier to understand and expand. It is commonly used in process judgment statements such as if judgment, switch enumeration, and data dictionary. Also known as the Policy model (' policy '). Policy pattern is an object behavior pattern.

    Example:

    When using the policy pattern, we can define several policy classes, each of which encapsulates a specific algorithm. Here, each class that encapsulates an algorithm can be called a policy, and depending on which policy class is passed in, the environment class executes the algorithm in a different policy class.

    In the game, we have A level evaluation of the user after each game, such as level S 4 times experience, level A 3 times experience, level B 2 times experience, and other 1 times experience, expressed by the function as follows:

    js
    // Instead, the policy pattern is written as two functions
    +const strategy = {
    +  S: function (experience) {
    +    return 4 * experience;
    +  },
    +  A: function (experience) {
    +    return 3 * experience;
    +  },
    +  B: function (experience) {
    +    return 2 * experience;
    +  },
    +};
    +// getExperience can be reused
    +function getExperience(strategy, level, experience) {
    +  return level in strategy ? strategy[level](experience) : experience;
    +}
    +var s = getExperience(strategy, 'S', 100);
    +var a = getExperience(strategy, 'A', 100);
    +console.log(s, a); // 400 300
    js
    // Instruction processing set
    +var compileUtil = {
    +    // v-text Works for updating views
    +    text: function(node, vm, exp) {
    +        this.bind(node, vm, exp, 'text');
    +    },
    +    // v-html update view principle
    +    html: function(node, vm, exp) {
    +        this.bind(node, vm, exp, 'html');
    +    },
    +    // v-class binding principle
    +    class: function(node, vm, exp) {
    +        this.bind(node, vm, exp, 'class');
    +    },
    +    bind: function(node, vm, exp, dir) {
    +        // The same instruction triggers the view update
    +        var updaterFn = updater[dir + 'Updater'];
    +        updaterFn && updaterFn(node, this._getVMVal(vm, exp));
    +        new Watcher(vm, exp, function(value, oldValue) {
    +            updaterFn && updaterFn(node, value, oldValue);
    +        });
    +    }
    +    ......
    +}

    Advantages:

    • Policy mode provides perfect support for the "open and close principle", users can choose algorithms or behaviors without modifying the original system, and can flexibly add new algorithms or behaviors.
    • The policy pattern provides a way to manage related algorithm families. The hierarchy of a policy class defines an algorithm or family of behaviors, and proper use of inheritance can move common code into an abstract policy class, thereby avoiding duplicate code. The policy pattern provides a way to replace inheritance relationships. Without the policy pattern, an environment class that uses algorithms might have several subclasses, each of which provides a different algorithm. However, in this way, the use of the algorithm is mixed with the algorithm itself, which does not conform to the "single responsibility principle", and the logic of deciding which algorithm to use is mixed with the algorithm itself, so that it is impossible to evolve independently. And using inheritance can not realize the dynamic switching of algorithms or behaviors during program running.
    • Use policy mode to avoid multiple conditional selection statements. Multiple conditional selection statement is not easy to maintain, it takes the logic of which algorithm or behavior to take and the implementation logic of the algorithm or behavior itself mixed together, Hard Coding them all in a huge multiple conditional selection statement, than the direct inheritance of the environment class method is more primitive and backward.
    • The policy pattern provides an algorithm reuse mechanism. Since algorithms are extracted separately and encapsulated in policy classes, different environment classes can reuse these policy classes easily.

    Disadvantage:

    • The client must know all the policy classes and decide which one to use. This means that the client must understand the difference between these algorithms in order to choose the right one at the right time. In other words, the policy pattern only applies if the client knows all the algorithms or behaviors.
    • The policy mode will cause the system to generate many specific policy classes, and any small change will cause the system to add a new specific policy class.
    • Multiple policy classes cannot be used on the client at the same time. That is, when the policy mode is used, the client can use only one policy class at a time. One policy class cannot be used to complete some functions and then another policy class is used to complete the remaining functions.

    6.10 Template method pattern

    Template method pattern : Define the framework of an algorithm in an operation, while deferring some steps to subclasses. The template method pattern allows subclasses to redefine certain steps of an algorithm without changing its structure.

    Example:

    Template method mode usage scenario

    The template approach pattern is often used by the architect to build the framework of the project. The architect defines the skeleton of the framework and the programmer inherits the structure of the framework and is responsible for filling in the blanks Hook method: Hook functions in various frameworks often specify the name of each hook function and the execution time at initialization, and users only need to inject custom logic code into the hook function

    • Callback function: The callback function is executed at a specific time, but the specific operation is implemented by the specific function. Encapsulate the changes into a function and the rest becomes a template

    The specific application of template method pattern is divided into three categories:

    • Abstract method: An abstract method is declared by an abstract class and implemented by its concrete subclasses.

    • Concrete method: A concrete method is declared and implemented by an abstract or concrete class, and its subclasses can be overridden or directly inherited.

    • Hook method: A hook method is declared and implemented by an abstract or concrete class, and its subclasses may extend it. Usually the implementation given in the parent class is an empty implementation that is used as the default implementation for the method, although the hook method can also provide a non-empty default implementation. The hook method implemented in the subclass constrains the execution of the parent class method, and realizes the reverse control of the subclass to the parent class behavior.

    Make a cup of coffee

    First let's make a cup of coffee, generally speaking, the steps of making coffee are usually as follows:

    1. Boil the water first.

    2. Brew coffee with boiling water;

    3. Pour the coffee into the cup;

    4. Add sugar and milk.

    Let's use es5 to get a cup of coffee:

    js
    var Coffee = function () {};
    +Coffee.prototype.boilWater = function () {
    +  console.log('The water is boiling');
    +};
    +Coffee.prototype.brewCoffeeGriends = function () {
    +  console.log('Brew coffee with boiling water');
    +};
    +Coffee.prototype.pourInCup = function () {
    +  console.log('Pour the coffee into the cup');
    +};
    +Coffee.prototype.addSugarAndMilk = function () {
    +  console.log('Add sugar and milk');
    +};
    +// Encapsulation hands over the implementation details to the internals of the class
    +Coffee.prototype.init = function () {
    +  this.boilWater();
    +  this.brewCoffeeGriends();
    +  this.pourInCup();
    +  this.addSugarAndMilk();
    +};
    +var coffee = new Coffee();
    +coffee.init();

    Make a pot of tea

    In fact, the steps for making tea are not very different from those for making coffee, which is roughly like this:

    1. Boil the water;

    2. Soak tea leaves in boiling water;

    3. Pour the tea into the cup;

    4. Add lemon.

    Here, let's make tea with es6:

    js
    class Tea {
    +  constructor() {}
    +  boilWater() {
    +    console.log('Bring water to a boil');
    +  }
    +  steepTeaBag() {
    +    console.log('Soaked tea leaves');
    +  }
    +  pourInCup() {
    +    console.log('Pour into a cup');
    +  }
    +  addLemon() {
    +    console.log('Add lemon');
    +  }
    +  init() {
    +    this.boilWater();
    +    this.steepTeaBag();
    +    this.pourInCup();
    +    this.addLemon();
    +  }
    +}
    +var tea = new Tea();
    +tea.init();

    Now it's time to think, we just made a cup of coffee and a pot of tea, do you think these two processes are much the same. We can easily find out what they have in common, the difference is the raw material, tea and coffee, we can abstract them as "drinks" wow; The way of soaking is different, one is brewing, the other is soaking, we can abstract this behavior as "soaking"; The spices added are also different, adding sugar and milk, adding lemon, they can also be abstracted as "seasoning".

    Such an analysis, is not very clear acriz, we sort it out is:

    1. Boil the water;

    2. Brew drinks with boiling water;

    3. Pour the drink into the glass;

    Step 4 Add seasoning.

    Attention, everyone! Attention, everyone! Here comes the hero! We've thrown out the concept before, so we can now create an abstract superclass to represent the process of making a drink. So, abstract superclasses?

    An abstract class?

    Abstract classes cannot be instantiated; they must be inherited. All subclasses that inherit an abstract class will have interface methods identical to those of the abstract class, and the main role of the abstract class is to define these public interfaces for its subclasses.

    Through the above analysis, it is specifically to find out the common steps of making tea and making coffee, encapsulate them into the parent class, that is, the abstract class, and then write different steps in the subclass, that is, tea and coffee. Since an abstract class cannot be instantiated, no fear, a subclass is its instantiation.

    Make a drink!

    js
    var Beverage = function () {};
    +Beverage.prototype.boilWater = function () {
    +  console.log('Boil the water');
    +};
    +Beverage.prototype.brew = function () {};
    +Beverage.prototype.pourInCup = function () {};
    +Beverage.prototype.addCondiments = function () {};
    +// Abstract method
    +Beverage.prototype.init = function () {
    +  this.boilWater();
    +  this.brew();
    +  this.pourInCup();
    +  this.addCondiments();
    +};
    +var Coffee = function () {
    +  // Take the constructor of the parent class and execute it
    +  Beverage.apply(this, arguments);
    +  // Just like es6's super execution, this will only have the properties of the object after execution
    +};
    +Coffee.prototype = new Beverage();
    +var coffee = new Coffee();
    +coffee.init();
    +var Tea = function () {};
    +Tea.prototype = new Beverage();
    +Tea.prototype.brew = function () {
    +  console.log('Soak the tea leaves in boiling water');
    +};
    +Tea.prototype.pourInCup = function () {
    +  console.log('Pour the tea into the cup');
    +};
    +Tea.prototype.addCondiments = function () {
    +  console.log('Add lemon');
    +};
    +var tea = new Tea();
    +tea.init();

    Both coffee and tea are made here, is it not as cumbersome as before, and the code here is very advanced.

    Coffee and Tea are represented by the parent class Beverage, and then the subclass is Coffee and Tea, because Beverage is an abstract existence, and the subclass needs to inherit it. The process of brewing a drink can be understood as a template pattern, the abstract class Beverage, and the abstract method init() is implemented in the subclass. js inheritance is based on prototype chain inheritance, where prototype is the prototype chain of the class. Since there is no corresponding init() on the prototype of the coffee object and tea object, the request will follow the prototype chain to find the init() of the parent class Beverage. When subclasses look for corresponding properties and methods, they will follow the prototype chain to find them, first looking for themselves, and if they do not find them, they will follow the search inside the parent class.

    The reason why Beverage.prototype.init is called a template method is that it encapsulates the algorithm framework of the subclass, which serves as a template for the algorithm and instructs the subclass to execute which methods in which order.

    Advantages:

    • Formally define an algorithm in the parent class, and let its subclasses implement the details of the processing, and the subclasses implement the detailed processing algorithm without changing the order of execution of the steps in the algorithm.
    • Template method pattern is a code reuse technique, it is particularly important in class library design, it extracts the common behavior of the class library, puts the common behavior in the parent class, and through its subclasses to achieve different behavior, it encourages us to use inheritance properly to achieve code reuse. A reverse control structure can be implemented where subclasses override the hook methods of the parent class to decide whether a particular step needs to be performed.
    • In the template method pattern, the basic method of the parent class can be overridden by subclasses, different subclasses can provide different implementations of the basic method, and it is easy to replace and add new subclasses, which conforms to the principle of single responsibility and the principle of open and close.

    Disadvantage:

    • It is necessary to provide a subclass for different implementations of each basic method. If there are too many variable basic methods in the parent class, the number of classes will increase, the system will become larger, and the design will become more abstract. In this case, the bridge pattern can be combined to design.

    6.11 Visitor Pattern

    Visitor Pattern:Provides a representation of operations that act on elements of an object structure, which allows us to define new operations on those elements without changing their class. Visitor pattern is an object behavior pattern.

    Example:

    Visitor pattern is a more complex behavioral design pattern, which consists of two main components: visitor and visited elements. These visited elements usually have different types, and different visitors can access them differently. The visitor pattern allows users to extend the functionality of the system without modifying the existing system, adding new operations to these different types of elements.

    When using the visitor pattern, the accessed elements usually do not exist separately, they are stored in a collection called an "object structure", and the visitor iterates through the object structure to achieve a one-by-one operation on the elements stored in it.

    js
    // Visitor pattern: DOM event binding
    +var bindEvent = function(dom, type, fn, data) {
    +    if (dom.addEventListener) {
    +        dom.addEventListener(type, fn, false);
    +    } else if (dom.attachEvent) {
    +        // dom.attachEvent('on'+type, fn);
    +        var data = data || {};
    +        dom.attachEvent('on' + type, function(e) {
    +            // In IE this points to window, use call to change the point of this
    +            fn.call(dom, e, data);
    +        });
    +    } else {
    +        dom['on' + type] = fn;
    +    }
    +}
    +function $(id) {
    +    return document.getElementById(id);
    +}
    +
    +bindEvent($(demo), 'click', function() {
    +    // this points to the dom object
    +    this.style.background = 'red';
    +});
    +
    +bindEvent($('btn'), 'click', function(e, data) {
    +    $('text').innerHTML = e.type + data.text + this.tagName;
    +}, { text: 'demo' });

    The idea of visitor pattern is to add new operation methods to the operand without changing it, so as to achieve access to the operand. We know that the purpose of call and apply is to change the scope of function execution, which is the essence of the visitor pattern. call and apply are two ways to make an object run in another scope.

    js
    // Array method encapsulation
    +var Visitor = (function() {
    +    return {
    +        splice: function() {
    +            var args = Array.prototype.splice.call(arguments, 1);
    +            return Array.prototype.splice.apply(arguments[0], args);
    +        },
    +        push: function() {
    +            var len = arguments[0].length || 0;
    +            var args = this.splice(arguments, 1);
    +            arguments[0].length = len + arguments.length - 1;
    +            return Array.prototype.push.apply(arguments[0], args);
    +        },
    +        pop: function() {
    +            return Array.prototype.pop.apply(arguments[0]);
    +        }
    +    }
    +})();
    +
    +var a = new Object();
    +Visitor.push(a,1,2,3,4);
    +Visitor.push(a,4,5,6);
    +Visitor.pop(a);
    +Visitor.splice(a,2);

    The visitor pattern solves the coupling between the data and the manipulation of the data, making the manipulation of the data independent of the data, so that it can freely evolve. Therefore, the visitor pattern is more suitable for those environments where the data is stable but the data manipulation method is variable.

    Advantages:

    • Easy to add new access operations. Using the visitor pattern, adding a new access operation means adding a new concrete visitor class, which is simple to implement without modifying the source code and conforms to the "open and closed principle".
    • Centralize access to element objects into a single visitor object, rather than spreading it across individual element classes. Class responsibilities are clearer, facilitating reuse of element objects in the object structure, and the same object structure can be accessed by multiple different visitors.
    • Enables users to define operations that act on an existing element class hierarchy without modifying it.

    Disadvantage:

    • Adding new element classes is difficult. In the visitor pattern, adding a new element class means adding a new abstract operation to the abstract visitor role and a corresponding concrete operation to each concrete visitor class, which violates the "open closed principle".
    • Break the package. The visitor pattern requires the visitor object to access and invoke the operations of each element object, which means that the element object must sometimes expose some of its own internal operations and internal state, otherwise it cannot be accessed by the visitor.

    VII.Sum up

    After systematically studying design patterns, you can see in your past development experience that design patterns are everywhere. Before learning design patterns, we often rely on past experience and wisdom to improve the design of a system, and many of these experiences coincide with the idea of a certain design pattern.

    There are still some places that are not fully understood, and I would like to point out the mistakes in the article.

    VIII.Reference material

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/functionalProgramming.html b/src/article/functionalProgramming.html new file mode 100644 index 0000000000..d75c930a6b --- /dev/null +++ b/src/article/functionalProgramming.html @@ -0,0 +1,386 @@ + + + + + + 函数式编程 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    函数式编程

    • 概述:函数式编程 (Functional Programming)FP就是编程规范之一,我们常听说的编程规范还有面向对象编程,面向过程编程。
    • 面向对象的编程思维方式:把现实世界中的事物抽象成程序世界的类和对象,通过封装,继承和多态演示事物事件的联系
    • 函数编程的思维方式:把现实世界的事物和事物之间的联系抽象到程序世界 (对运算过程进行抽象)
      • 程序的本质:根据输入,通过某种运算,获得相应的输出
      • 函数式编程中的函数不是指程序中的 (函数) 方法,而是数学中的函数,即映射关系
      • 相同的输入始终要得到相同的输出 (纯函数)
      • 函数式编程用来描述数据 (函数) 之间的映射关系
    js
    //非函数式编程,面向过程的编程方式
    +let num1 = 1;
    +let num2 = 2;
    +let sum = num1 + num2;
    +
    +//函数式编程,对面向过程的抽象
    +function sum(n1, n2) {
    +  return n1 + n2;
    +}
    +let result = sum(1, 2);

    一。JS函数基本知识

    • 函数可以储存在变量中
    • 函数可以作为参数
    • 函数可以作为返回值

    JavaScript中,函数就是一个普通的对象,(可以通过new Function()),我们可以把函数存储到变量/数组中,它还可以作为另一个函数的参数和返回值,甚至我们还可以在程序运行的时候通过new Function('alert(1)')来构建一个新的函数

    • 把函数赋值给变量
    js
    let fn = function () {
    +  console.log('First-class Function MDN');
    +};

    二。高阶函数

    • 高阶函数 (Higher-order function)
      • 可以把函数作为参数传递给另一个函数
      • 可以把函数作为另一个函数的返回结果
    1. 函数作为参数
    js
    //forEach
    +function forEach(array, fn) {
    +  for (let item of array) {
    +    fn(item);
    +  }
    +}
    +
    +//filter
    +function filter(array, fn) {
    +  let result = [];
    +  for (let item of array) {
    +    if (fn(item)) {
    +      result.push(item);
    +    }
    +  }
    +  return result;
    +}
    +
    +//测试
    +let array = [1, 2, 3, 4, 5, 6, 7];
    +forEach(array, function (item) {
    +  console.log(item);
    +});
    +
    +let r = filter(array, function (item) {
    +  return item % 2 === 0;
    +});
    +console.log(r);
    1. 函数作为返回值
    js
    //高阶函数,函数作为返回值
    +function makeFn() {
    +  let msg = 'Highter-order Function';
    +  return function () {
    +    console.log(msg);
    +  };
    +}
    +//第一种调用方式
    +const fn = makeFn();
    +fn();
    +//第二种调用方式
    +makeFn()();
    +//once 只能执行一次的函数
    +function once(fn) {
    +  let done = false;
    +  return function () {
    +    if (!done) {
    +      done = true;
    +      return fn.apply(this, arguments);
    +    }
    +  };
    +}
    +let pay = once(function (money) {
    +  console.log(`支付${money}`);
    +});
    +pay(5);
    +pay(5);
    +pay(5);
    +pay(5);
    +pay(5);

    三。闭包

    概述:有权访问另一个函数作用域中的变量的函数

    本质:函数执行的时候会入栈,当执行完后会移除栈,但是堆上的作用域成员因为被外部引用而不能释放。因此内部函数依然可以访问外部函数的成员。

    :栈会自动分配内存,会自动释放,存放基本数据类型,占据固定大小的空间。

    栈的溢出:递归调用方法,随着栈的深度增加,直到内存不够分配,产生溢出。

    栈的优势:所有方法中的变量都存在栈中,随着方法执行的结束,这个方法的内存栈也随之销毁,存取速度很快,仅次于 CPU 的寄存器,可以共享。

    :动态分配内存,大小不定,也不会自动释放内存,不会随着方法的结束而销毁堆内存,存放引用数据类型,实际保存的不是变量本身,而是指向该对象的指针。

    堆溢出:循环创建对象,就是不断的 new 对象

    四。纯函数

    • 概念:相同的输入永远会得到相同的输出,而且没有任何可观察的副作用,类似数学中的函数y=f(x)
    • 例子:slice函数就是纯函数,对一个数组,相同的输入永远得到相同的输出,splice 就是非纯函数,相同的输入可能会得到不同的结果,因为会改变原数组
    • 函数式编程不会保留计算中间的结果,所以变量不可变 (无状态)
    • 可以把一个函数的执行结果交给另一个函数去执行
    • 纯函数可以缓存,因为相同的输入必然有相同的输出
    js
    //memoize 函数
    +function memoize(fn) {
    +  let cache = {};
    +  return function () {
    +    let key = JSON.stringfy(arguments);
    +    cache[key] = cache[key] || fn.apply(fn, arguments);
    +    return cache[key];
    +  };
    +}
    • 可测试,让测试更方便
    • 多线程环境下操作共享的内存数据可能会出现意外的情况,而纯函数不需要共享的数据空间,只和输入有关,所以并行环境下可以任意运行纯函数
    • 副作用,副作用会让纯函数变的不纯,比如依赖外部的状态,就无法保证输出相同,带来副作用,副作用来源:配置文件,数据库,获取用户的输入等等...所有的外部交互都可能带来副作用,副作用使得方法通用性下降,不适合扩展和重用,同时给程序带来安全隐患,副作用不可能完全禁止,只能尽可能的在控制范围内。
    js
    //不纯的函数
    +let mini = 18;
    +function checkAge(age) {
    +  return age > min;
    +}
    +//纯函数 (有硬编码,后续可以通过柯里化来解决)
    +function checkAge(age) {
    +  let mini = 18;
    +  return age > mini;
    +}

    五。柯里化 (Haskell Brooks Curry)

    js
    //解决上述硬编码的问题
    +function checkAge(min) {
    +  return function (age) {
    +    return age >= min;
    +  };
    +}
    +let checkAge18 = checkAge(18);
    +checkAge18(22);

    es6进行简化

    js
    let checkAge = (min) => (age) => age >= min;
    • 当一个函数有多个参数的时候,可以先传递一部分,先调用它,并返回一个函数 (这部分参数以后保持不变)
    • 然后返回一个新的函数接受剩下的参数,返回结果
    • lodash中的柯里化函数
      • _.curry(func)
      • 功能:创建一个函数,该函数接受一个或多个 func 的参数,如果该函数所有的参数都被传递,则返回函数的结果,否则,返回该函数并等待继续传递参数
      • 参数:需要柯里化的函数
      • 返回值:柯里化后的函数
    js
    //lodash 中的 curry 的使用
    +const _ = require('loadsh');
    +function getSum(a, b, c) {
    +  return a + b + c;
    +}
    +const curried = _.curry(getSum);
    +console.log(curried(1, 2, 3)); //6
    +console.log(curried(1)(2, 3)); //6
    +console.log(curried(1)(2)(3)); //6

    实现一个 curry 函数

    js
    function curry(func) {
    +  return function curriedFn(...args) {
    +    if (args.length < func.length) {
    +      return function () {
    +        return curriedFn(...args.concat(Array.form(arguments)));
    +      };
    +    } else {
    +      return func(...args);
    +    }
    +  };
    +}
    • 总结:柯里化可以让我们给一个函数传递较少的参数,返回一个记住来某些固定参数的新函数,这是一种对函数参数的缓存,让函数变的更灵活,让函数的粒度更小。可以把多元函数转换成一元的函数,可以组合使用函数产生强大的功能。

    六。函数的组合

    • 纯函数和柯里化很容易让我们写出洋葱代码,比如h(f(g(x)))
      • 获取数组的最后一个元素并转化为大写字母,_.toUpper(._first(_.revers(array)))
      • 函数的组合可以让我们把细粒度的函数,重新组合成一个新的函数
    • lodash中的组合函数
      • lodash中的组合函数flow()flowRight(),都可以组合多个函数
      • flow()是从左到右执行
      • flowRight()是从右到左执行
      • 自己实现一个flowRight函数:
    js
    function composeRight(...args) {
    +  return function (value) {
    +    args.reverse().reduce(function (acc, fn) {
    +      return fn(acc);
    +    }, value);
    +  };
    +}
    +//箭头函数
    +const compose =
    +  (...args) =>
    +  (value) =>
    +    args.reverse().reduce((acc, fn) => fn(acc), value);
    +//如果是表达式赋值的话,不会变量提升
    • 函数的组合要满足结合律,即 f,g,h 三个函数,无论先组合那几个,结果都是等效的,即 flowRight(.toUpper,.first,_.revers)
    • 函数组合如何进行调试?
    js
    const log = (v) => {
    +  console.log(v);
    +  return v;
    +};
    • lodash库中的 fp 模块
      • lodash的 fp 模块提供了实用的对函数式编程友好的方法
      • 提供了不可变的auto-curried iteratee-first data-last的方法
    js
    //lodash 方法
    +const _ = require('lodash');
    +_.map(['a', 'b', 'c'], _.toUpper);
    +//=>['A','B','C']
    +_.map(['a', 'b', 'c']);
    +//=>['a','b','c']
    +//loadsh/fp 模块
    +const fp = require('lodasg/fp');
    +fp.map(fp.toUpper, ['a', 'b', 'c']);
    +fp.map(fp.toUpper)(['a', 'b', 'c']);

    七.Point Free

    我们可以把数据处理的过程定义成与数据无关的合成运算,不需要用到代表数据的那个参数,只要把简单的运算步骤合成到一起,在使用这种模式之前我们需要定义一些辅助的基本运算函数。

    • 不需要指明处理的数据
    • 只需要合成运算过程
    • 需要定义一些辅助的基本运算函数
    js
    const f = fp.flowRight(fp.join('-'), fp.map(_.toLower), fp.splite(''));

    八。functor(函子)

    • 为什么要了解函子
      目前没有解决如何在函数式编程中,把副作用控制在可控的范围内,异常处理,异步操作等等。
    • Functor
      • 容器:包含值和值的变形关系 (这个变形关系就是函数)
      • 函子:是一个特殊的容器,通过一个普通对象来实现,该对象具有 map 方法,map 方法可以运行一个函数对值进行处理 (变形关系)
    js
    //Functor 函子
    +class Container {
    +  //函子内部要有一个值
    +  constructor(value) {
    +    //这个值是传入进来的,且不对外公布
    +    this._value = value;
    +  }
    +  map(fn) {
    +    //map 方法,接受一个处理值的函数,去处理这个值。
    +    //并且要把处理的值,传给一个新的函子,最后返回这个新的函子
    +    return new Container(fn(this._value));
    +  }
    +}
    +
    +//新建一个函子
    +let r = new Container(5).map((x) => x + 1).map((x) => x * x);

    of方法:

    js
    //of 方法用来返回一个函子对象
    +class Container {
    +  constructor(value) {
    +    this._value = value;
    +  }
    +  static of(value) {
    +    //传入值,返回一个新的函子对象
    +    return new Container(value);
    +  }
    +  map(fn) {
    +    return Container.of(fn(this._value));
    +  }
    +}
    +let r = Container.of(5)
    +  .map((x) => x + 1)
    +  .map((x) => x * x);
    +console.log(r); //打印出来的是一个函子,不是值,永远不会把这个值取出来,需要改变这个值的时候,使用 map 方法传入一个函数去处理,进行链式调用。
    • 总结
      • 函数式编程的运算不直接操作值,而是由函子完成
      • 函子就是一个实现了map契约的对象
      • 我们可以把函子想象成一个盒子,这个盒子里封装了一个值
      • 想要处理盒子中的值,我们需要给盒子的map方法传递一个处理值的函数(纯函数),由这个函数对值进行处理
      • 最终map方法返回一个包含新值的盒子(函子)
    • MayBe函子
      • 我们在编程过程中可能会遇到很多的错误,需要对这些错误进行相应的处理
      • MayBe 函子的作用就是可以对外部的空值情况做处理(控制副作用在允许的范围之内)
    js
    //MayBe 函子
    +class MayBe {
    +  static of(value) {
    +    return new MayBe(value);
    +  }
    +  constructor(value) {
    +    this._value = value;
    +  }
    +  map(fn) {
    +    return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this._value));
    +  }
    +  isNothing() {
    +    return this._value === null || this._value === undefined;
    +  }
    +}
    +let r = MayBe.of(null)
    +  .map((x) => x + 1)
    +  .map((x) => x * x);
    +console.log(r);
    • 问题:如果多次调用 map,中间出现了 null 空值的情况,最后会返回包含 null 的函子。虽然 maybe 函子可以处理空值的情况,但不知道是哪一步出现了空值
    • Either 函子
      • Either 两者中的任意一个,类似于 if...else...的处理
      • 异常会让函数变的不纯,Either 函子可以用来做异常处理
    js
    //Either 函子
    +class Left {
    +  static of(value) {
    +    return new Left(value);
    +  }
    +  constructor(value) {
    +    this._value = value;
    +  }
    +  map(fn) {
    +    return this;
    +  }
    +}
    +
    +class Right {
    +  static of(value) {
    +    return new Right(value);
    +  }
    +  constructor(value) {
    +    this._value = value;
    +  }
    +  map(fn) {
    +    return Right.of(fn(this._value));
    +  }
    +}
    +
    +function parseJSON(str) {
    +  try {
    +    return Right.of(JSON.parse(str));
    +  } catch (error) {
    +    return Left.of({ error: error.message });
    +  }
    +}
    +let l = parseJSON('{name:zs}'); //error
    +console.log(l);
    +let r = parseJSON('{"name":"zs"}');
    +console.log(r);
    +r.map((x) => x.toUpper());
    • IO 函子
      • IO 函子中的_value 是一个函数,这里是把函数当作值来处理
      • IO 函子可以把不纯的函数储存到_value 中,延迟执行这个不纯的操作 (惰性执行)
      • 把不纯的操作交给调用者来处理
    js
    const fp = require('lodash/fp');
    +class IO {
    +  static of(x) {
    +    return new IO(function () {
    +      return x;
    +    });
    +  }
    +  constructor(fn) {
    +    this._value = fn;
    +  }
    +  map(fn) {
    +    return IO.of(fp.flowRight(fn, this._value));
    +  }
    +}
    +//调用
    +//因为是在 node 环境,所以直接传递 process 对象,node 的进程
    +let r = IO.of(process).map((p) => p.execPath);
    +console.log(r); //IO {_value :[Function]}
    +console.log(r._value()); //执行 node 进程的路径
    • folktale
      • folktale 是一个标准的函数式编程库
      • 和 lodash,ramda 不同的是,他没有提供很多功能函数
      • 只提供了函数式处理的操作,例如,curry,compose 等,和一些函子 Task,Either,MayBe 等
    js
    //folktale  2.3.2
    +//Task 处理异步任务
    +const fs = require('fs');
    +const { task } = require('folktale/concurrency/task');
    +const { split, find } = require('loadsh/fp');
    +
    +function readFile(filename) {
    +  return task((resolver) => {
    +    fs.readFile(filename, 'utf-8', (error, data) => {
    +      if (error) {
    +        resolver.reject(err);
    +      } else {
    +        resolver.resolve(data);
    +      }
    +    });
    +  });
    +}
    +//会返回一个 Task 函子
    +readFile('package.json')
    +  .run()
    +  .listen({
    +    //监听事件的状态
    +    onRejected: (err) => {
    +      console.log(err);
    +    },
    +    onResolved: (value) => {
    +      console.log(value);
    +    },
    +  });
    +//可以在 run 之前调用 map,去处理返回的结果
    +readFile('package.json')
    +  .map(split('\n'))
    +  .map(find((x) => x.includes('version')))
    +  .run()
    +  .listen({
    +    //监听事件的状态
    +    onRejected: (err) => {
    +      console.log(err);
    +    },
    +    onResolved: (value) => {
    +      console.log(value);
    +    },
    +  });
    • Pointed 函子
      • Pointed 函子是实现的静态方法 of 的函子
      • of 是为了避免使用 new 来创建对象,更深层的含义是 of 方法用来把值放到上下文 Context 中 (把值放到容器中,使用 map 来处理值)
    • Monad 函子
      • Monad 函子是为来解决 IO 函子嵌套的问题
    js
    const fp = require('lodash/fp');
    +const fs = require('fs');
    +class IO {
    +  static of(x) {
    +    return new IO(function () {
    +      return x;
    +    });
    +  }
    +  constructor(fn) {
    +    this._value = fn;
    +  }
    +  map(fn) {
    +    return IO.of(fp.flowRight(fn, this._value));
    +  }
    +}
    +let readFile = function (filename) {
    +  return new IO(function () {
    +    return fs.readFileSync(filename, 'utf-8');
    +  });
    +};
    +let print = function (x) {
    +  return new IO(function (x) {
    +    console.log(x);
    +    return x;
    +  });
    +};
    +let cat = fp.flowRight(print, readFile);
    +let r = cat('package.json')._value()._value();
    +console.log(r);
    • Monad 函子是一个可以变扁的 Pointed 函子,变扁就是解决函子嵌套的问题 IO(IO(x))
    • 一个函子如果具有 join 和 of 两个方法并遵守一些定律就是一个 Monad
    js
    //注意看 join 方法
    +const fp = require('lodash/fp');
    +const fs = require('fs');
    +class IO {
    +  static of(x) {
    +    return new IO(function () {
    +      return x;
    +    });
    +  }
    +  constructor(fn) {
    +    this._value = fn;
    +  }
    +  map(fn) {
    +    return IO.of(fp.flowRight(fn, this._value));
    +  }
    +  join() {
    +    return this._value();
    +  }
    +  flatMap(fn) {
    +    //经常会用到 map 和 join 方法,所以就用 flatMap 将其变扁
    +    return this.map(fn).join();
    +  }
    +}
    +let print = function (x) {
    +  return new IO(function () {
    +    console.log(x);
    +    return x;
    +  });
    +};
    +let r = readFile('package.json') //这里可以用 map 去处理内容
    +  .flatMap(print)
    +  .join();

    参考资料

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/imagemin.html b/src/article/imagemin.html new file mode 100644 index 0000000000..4ef261bed7 --- /dev/null +++ b/src/article/imagemin.html @@ -0,0 +1,49 @@ + + + + + + imagemin 图片压缩源码分析 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    imagemin 图片压缩源码分析

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/javascript/domLoad.html b/src/article/javascript/domLoad.html new file mode 100644 index 0000000000..1ad50f984c --- /dev/null +++ b/src/article/javascript/domLoad.html @@ -0,0 +1,51 @@ + + + + + + 页面加载完成后事件 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    页面加载完成后事件

    window.onload

    DOMContentLoaded

    js
    document.addEventListener('DOMContentLoaded', fun);

    <body onload="fun()">

    readyState

    js
    document.readyState;
    +
    +document.onreadystatechange;

    一个文档的 readyState 可以是以下之一:

    • loading / 加载。document 仍在加载。
    • interactive / 互动。文档已经完成加载,文档已被解析,但是诸如图像,样式表和框架之类的子资源仍在加载。
    • complete / 完成。T 文档和所有子资源已完成加载。状态表示 load 事件即将被触发。

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/sort/bubble/index.html b/src/article/sort/bubble/index.html new file mode 100644 index 0000000000..f346bf9faa --- /dev/null +++ b/src/article/sort/bubble/index.html @@ -0,0 +1,62 @@ + + + + + + Bubble Sort | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Bubble Sort

    Bubble sort is a simple sort algorithm. It repeatedly visits the sequence to be sorted, comparing two elements at a time and swapping them if they are in the wrong order. The work of visiting the sequence is repeated until no more exchanges are needed, that is, the sequence has been sorted. The algorithm gets its name from the fact that smaller elements slowly "float" to the top of the sequence through exchange.

    Algorithm description

    • Compare adjacent elements. If the first one is bigger than the second, swap them both;
    • Do the same for each pair of adjacent elements, from the first pair at the beginning to the last pair at the end, so that the last element should be the largest;
    • Repeat the above steps for all elements except the last one;
    • Repeat steps 1 to 3 until the sorting is complete.

    GIF presentation

    Bubble Sort

    Code demo

    ts
    const bubble = (list: number[]) => {
    +  const size = list.length;
    +  for (let i = 0; i < size; i++) {
    +    for (let j = 0; j < size; j++) {
    +      if (list[i] < list[j]) {
    +        list[i] = list[i] ^ list[j];
    +        list[j] = list[i] ^ list[j];
    +        list[i] = list[i] ^ list[j];
    +      }
    +    }
    +  }
    +  return list;
    +};

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/sort/bucket/index.html b/src/article/sort/bucket/index.html new file mode 100644 index 0000000000..27b6678ab5 --- /dev/null +++ b/src/article/sort/bucket/index.html @@ -0,0 +1,105 @@ + + + + + + Bucket Sort | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Bucket Sort

    The key to efficiency is this bucket function. The data is divided into a limited number of buckets, and each bucket is sorted separately (it is possible to use another sorting algorithm or recursively continue to use bucket sorting).

    Algorithm description

    • Set a quantitative array as an empty bucket;
    • Iterate over the input data and place the data one by one into the corresponding bucket;
    • Sort each bucket that is not empty;
    • Piecing together sorted data from a bucket that is never empty.

    Code demo

    ts
    const count = (list: Array<number>, max: number = 100): Array<number> => {
    +  const countList = new Array(max + 1);
    +  for (let i = 0; i < list.length; i++) {
    +    if (!countList[list[i]]) {
    +      countList[list[i]] = 0;
    +    }
    +    countList[list[i]]++;
    +  }
    +  let startIndex = 0;
    +  for (let i = 0; i < countList.length; i++) {
    +    while (countList[i] > 0) {
    +      list[startIndex++] = i;
    +      countList[i]--;
    +    }
    +  }
    +  return list;
    +};
    +const getMax = (list: Array<number>) => {
    +  let max = list[0];
    +  for (let i = 0; i < list.length; i++) {
    +    if (max < list[i]) {
    +      max = list[i];
    +    }
    +  }
    +  return max;
    +};
    +const getMin = (list: Array<number>) => {
    +  let min = list[0];
    +  for (let i = 0; i < list.length; i++) {
    +    if (min > list[i]) {
    +      min = list[i];
    +    }
    +  }
    +  return min;
    +};
    +
    +/**
    + * @description: Bucket Sort
    + * @param {Array<number>} list
    + * @return {Array<number>}
    + */
    +const bucket = (list: Array<number>, bucketSize: number = 5, max?: number, min?: number): Array<number> => {
    +  if (list.length === 0) return list;
    +  if (!max) max = getMax(list);
    +  if (!min) min = getMin(list);
    +  const bucketCount = Math.floor((max - min) / bucketSize) + 1;
    +  const buckets = new Array(bucketCount + 1).fill(0).map(() => new Array(0));
    +
    +  for (let i = 0; i < list.length; i++) {
    +    buckets[Math.floor((list[i] - min) / bucketSize)].push(list[i]);
    +  }
    +  list = [];
    +  for (let i = 0; i < bucketCount; i++) {
    +    list = list.concat(count(buckets[i]));
    +  }
    +  return list;
    +};

    Algorithm analysis

    Bucket sorting best uses linear time O(n), and the time complexity of bucket sorting depends on the time complexity of sorting data between buckets, because the time complexity of other parts is O(n). Obviously, the smaller the buckets, the less data there is between them, and the less time it takes to sort them. But the corresponding space consumption will increase.

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/sort/count/index.html b/src/article/sort/count/index.html new file mode 100644 index 0000000000..34cc4dbb3a --- /dev/null +++ b/src/article/sort/count/index.html @@ -0,0 +1,83 @@ + + + + + + Count Sort | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Count Sort

    counting sort is a kind of sorting algorithm that sacrifices memory space for low time complexity, and it is also a kind of algorithm that is not based on comparison. The non-comparison-based sorting algorithm here means that there is no comparison size between array elements. We know that the divide-and-conquer method to solve the sorting problem can only make the time complexity of the algorithm approach Θ(nlogn) at the fastest, that is, the time complexity based on comparison has a lower bound Ω(nlog⁡n), and the sorting algorithm based on no comparison can break through this lower bound.

    Algorithm description

    • Find the largest and smallest elements of the array to be sorted;
    • Count the number of occurrences of each element with value i in the array, stored in the i - th item of the array C;
    • Add up all counts (starting with the first element in C and adding each term to the previous one);
    • Backfill the target array: Place each element i in the C(i) item of the new array, and subtract 1 from C(i) for each element.

    GIF presentation

    Count Sort

    Code demo

    ts
    const getMax = (list: number[]) => {
    +  let max = list[0];
    +  for (let i = 1; i < list.length; i++) {
    +    if (max < list[i]) {
    +      max = list[i];
    +    }
    +  }
    +  return max;
    +};
    +/**
    + * @description: Count Sort
    + * @param {Array<number>} list
    + * @return {Array<number>}
    + */
    +const count = (list: number[]): number[] => {
    +  if (list.length <= 1) return list;
    +  const max = getMax(list);
    +  const countList = new Array(max + 1).fill(0);
    +  list.forEach((item) => {
    +    if (!countList[item]) {
    +      countList[item] = 1;
    +    } else {
    +      countList[item]++;
    +    }
    +  });
    +  const result = [];
    +  for (let i = 0; i < countList.length; i++) {
    +    while (countList[i]) {
    +      result.push(i);
    +      countList[i]--;
    +    }
    +  }
    +  return result;
    +};

    Algorithm analysis

    Counting sort is a stable sorting algorithm. When the input elements are n integers between 0 and k, the time complexity is O(n+k) and the space complexity is also O(n+k), which sorts faster than any comparison sorting algorithm. Counting sort is an efficient sorting algorithm when k is not large and the sequence is concentrated.

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/sort/heap/index.html b/src/article/sort/heap/index.html new file mode 100644 index 0000000000..cef27cbc91 --- /dev/null +++ b/src/article/sort/heap/index.html @@ -0,0 +1,99 @@ + + + + + + Heap Sort | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Heap Sort

    Heapsort (Heapsort) is a kind of sorting algorithm designed by using the heap data structure. A heap is an almost complete binary tree structure, but also satisfies the property of a heap: the key value or index of a child node is always less than (or greater than) its parent node.

    Algorithm description

    • The initial sequence of keywords to be sorted (R1,R2... .Rn) builds a large top heap, which is the initial disordered region;
    • Swap the top element R[1] with the last element R[n] to get a new unordered region (R1,R2,... Rn-1) and a new ordered region (Rn), satisfying R[1,2... n-1]< =R[n];
    • Since the new top R[1] may violate the nature of the heap after exchange, it is necessary to adjust the current disorder region (R1,R2,... Rn-1) adjusts to the new heap, then swaps R[1] again with the last element of the unordered area, giving a new unordered area (R1,R2... .Rn-2) and the new ordered region (RN-1,Rn). Repeat this process until the number of elements in the ordered area is n-1, then the sorting process is complete.
    • Use large root piles in ascending order and small root piles in descending order

    GIF presentation

    Heap Sort

    Code demo

    ts
    class Heap {
    +  value: Array<number>;
    +  size: number;
    +  constructor(arr: Array<number> = []) {
    +    this.value = [...arr];
    +    this.size = arr.length;
    +    this.buildMaxHeap();
    +  }
    +  swap = (i: number, j: number) => {
    +    if (this.value[i] === this.value[j]) return;
    +    this.value[i] = this.value[i] ^ this.value[j];
    +    this.value[j] = this.value[i] ^ this.value[j];
    +    this.value[i] = this.value[i] ^ this.value[j];
    +  };
    +  heapHandler = (i: number) => {
    +    const left = 2 * i + 1;
    +    const right = 2 * i + 2;
    +    let largest = i;
    +    if (left < this.size && this.value[left] > this.value[largest]) {
    +      largest = left;
    +    }
    +    if (right < this.size && this.value[right] > this.value[largest]) {
    +      largest = right;
    +    }
    +    if (largest !== i) {
    +      this.swap(i, largest);
    +      this.heapHandler(largest);
    +    }
    +  };
    +  buildMaxHeap = () => {
    +    for (let i = this.size >> 1; i >= 0; i--) {
    +      this.heapHandler(i);
    +    }
    +    for (let i = this.size - 1; i >= 0; i--) {
    +      this.swap(0, i);
    +      this.size--;
    +      this.heapHandler(0);
    +    }
    +  };
    +}
    +
    +/**
    + * @description: Heap Sort
    + * @param {Array} list
    + * @return {Array}
    + */
    +const heap = (list: Array<number>): Array<number> => {
    +  const { value } = new Heap(list);
    +  return value;
    +};

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/sort/index.html b/src/article/sort/index.html new file mode 100644 index 0000000000..fe297fc432 --- /dev/null +++ b/src/article/sort/index.html @@ -0,0 +1,50 @@ + + + + + + Ten classic sorting algorithms | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Ten classic sorting algorithms

    The ten common sorting algorithms can be divided into two broad categories:

    • Comparator sort:By comparison to determine the relative order between elements, because its time complexity can not break through O(nlogn), so it is also called nonlinear time comparison class sorting.
    • Non-comparison sort:Instead of determining the relative order between elements by comparison, it can break through the time lower bound based on comparison sort and run in linear time, so it is also called linear time non-comparison sort.

    Sorting algorithm classification

    Algorithm complexity

    Algorithm complexity

    • Stable: If a was originally in front of b and a=b, a is still in front of b after sorting.
    • Unstable: If a originally comes before b and a=b, a may come after b after sorting.
    • Time complexity: The total number of operations on sorted data. Reflects what rule the number of operations presents when n changes.
    • Spatial complexity: refers to the measure of the storage space required when the algorithm is executed in the computer, and it is also a function of the data size n.

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/sort/insert/index.html b/src/article/sort/insert/index.html new file mode 100644 index 0000000000..19ae619a26 --- /dev/null +++ b/src/article/sort/insert/index.html @@ -0,0 +1,62 @@ + + + + + + Insert Sort | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Insert Sort

    Stable sorting algorithm, because no matter what data is entered is O(n2) time complexity, so when it is used, the smaller the data size, the better. The advantage is that no additional memory space is taken up. It works by building an ordered sequence and, for unsorted data, scanning from back to front in the sorted sequence, finding the appropriate position and inserting it.

    Algorithm description

    • Start with the first element, which can be considered to have been sorted;
    • Take the next element and scan it from back to front in the already sorted sequence of elements;
    • If the element (sorted) is larger than the new element, move the element to the next position;
    • Repeat step 3 until you find a position where the sorted element is less than or equal to the new element;
    • After inserting a new element into this position;
    • Repeat Steps 2 to 5.

    GIF presentation

    Insert Sort

    Code demo

    ts
    const insert = (list: number[]): number[] => {
    +  const size = list.length;
    +  for (let i = 1; i < size; i++) {
    +    const current = list[i];
    +    let preIndex = i - 1;
    +    while (preIndex >= 0 && list[preIndex] > current) {
    +      list[preIndex + 1] = list[preIndex];
    +      preIndex--;
    +    }
    +    list[preIndex + 1] = current;
    +  }
    +  return list;
    +};

    Algorithm analysis

    Insertion sort in the implementation, usually use in-place sort (that is, only need to use O(1) of the additional space of the sort), so in the process of scanning from back to forward, the sorted elements need to be repeatedly moved backward step by step, to provide insertion space for the latest elements.

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/sort/merge/index.html b/src/article/sort/merge/index.html new file mode 100644 index 0000000000..f79f93df8d --- /dev/null +++ b/src/article/sort/merge/index.html @@ -0,0 +1,82 @@ + + + + + + Merge Sort | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Merge Sort

    Merge sort is an effective sort algorithm based on merge operation. This algorithm is a very typical application of Divide and Conquer. By combining the ordered subsequences, a completely ordered sequence is obtained. That is, each subsequence is ordered first, and then the subsequence segments are ordered. If two ordered tables are merged into one ordered table, it is called a 2-way merge.

    Algorithm description

    • Divide the input sequence of length n into two subsequences of length n/2;
    • The two subsequences were merged and sorted respectively.
    • Merge two sorted subsequences into one final sorted sequence.

    GIF presentation

    Merge Sort

    Code demo

    ts
    const combine = (left: Array<number>, right: Array<number>) => {
    +  const list: Array<number> = [];
    +  while (left.length > 0 && right.length > 0) {
    +    if (left[0] <= right[0]) {
    +      list.push(left.shift()!);
    +    } else {
    +      list.push(right.shift()!);
    +    }
    +  }
    +
    +  while (left.length) {
    +    list.push(left.shift()!);
    +  }
    +  while (right.length) {
    +    list.push(right.shift()!);
    +  }
    +  return list;
    +};
    +/**
    + * @description: Merge sort
    + * @param {Array} list
    + * @return {Array}
    + */
    +const merge = (list: Array<number>): Array<number> => {
    +  const { length } = list;
    +  if (length <= 1) {
    +    return list;
    +  }
    +  const middle = length >> 1;
    +  const left = list.slice(0, middle);
    +  const right = list.slice(middle);
    +  return combine(merge(left), merge(right));
    +};

    Algorithm analysis

    Merge sort is a stable sort method. Like select sort, merge sort performs independently of the input data, but performs much better than select sort because it is always O(nlogn) in time complexity. The trade-off is extra memory space.

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/sort/quick/index.html b/src/article/sort/quick/index.html new file mode 100644 index 0000000000..cbde7666e7 --- /dev/null +++ b/src/article/sort/quick/index.html @@ -0,0 +1,100 @@ + + + + + + Quick Sort | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Quick Sort

    The basic idea of quick sorting is that the records to be sorted are separated into two independent parts through one sort. The keywords of one part of the records are smaller than those of the other part. Then the two parts of the records can be sorted separately to achieve the entire sequence.

    Algorithm description

    Quicksort uses divide-and-conquer to divide a list into two sub-lists. The specific algorithm is described as follows:

    • Picking out an element from the sequence, called a "pivot";
    • Reorder the sequence so that all elements smaller than the base value are placed in front of the base value and all elements larger than the base value are placed behind the base value (the same number can go to either side). After the partition exits, the benchmark is in the middle of the sequence. This is called a partition operation;
    • Recursively sorts subsequences of elements less than the base value and subsequences of elements greater than the base value.

    GIF presentation

    Quick Sort

    Code demo

    ts
    /**
    + * @description: Sets the base value pivot
    + * @param {Array} list
    + * @param {number} left
    + * @param {number} right
    + * @return {number} index
    + */
    +const partition = (list: number[] = [], left: number, right: number) => {
    +  const pivot = left;
    +  let index = pivot + 1;
    +  for (let i = index; i <= right; i++) {
    +    if (list[i] < list[pivot]) {
    +      if (list[i] !== list[index]) {
    +        list[i] = list[i] ^ list[index];
    +        list[index] = list[i] ^ list[index];
    +        list[i] = list[i] ^ list[index];
    +      }
    +      index++;
    +    }
    +  }
    +  if (list[index - 1] !== list[pivot]) {
    +    list[index - 1] = list[index - 1] ^ list[pivot];
    +    list[pivot] = list[index - 1] ^ list[pivot];
    +    list[index - 1] = list[index - 1] ^ list[pivot];
    +  }
    +  return index - 1;
    +};
    +/**
    + * @description: Continuously partition, set the reference value
    + * @param {Array} list
    + * @param {number} left
    + * @param {number} right
    + * @return {Array}
    + */
    +const combine = (list: number[], left: number, right: number) => {
    +  if (left < right) {
    +    const partitionIndex: number = partition(list, left, right);
    +    combine(list, partitionIndex + 1, right);
    +    combine(list, left, partitionIndex - 1);
    +  }
    +  return list;
    +};
    +/**
    + * @description: Quick sort
    + * @param {Array} list
    + * @return {Array}
    + */
    +const quick = (list: number[] = []): number[] => {
    +  const size = list.length;
    +  return combine(list, 0, size - 1);
    +};

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/sort/radix/index.html b/src/article/sort/radix/index.html new file mode 100644 index 0000000000..f017ce7f7b --- /dev/null +++ b/src/article/sort/radix/index.html @@ -0,0 +1,85 @@ + + + + + + Radix Sort | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Radix Sort

    Radix sort is sorted by the lowest order first, and then collected; Then sort by high order, and then collect; And so on until you reach the top. Sometimes properties are prioritized, first by low priority and then by high priority. The final order is that the higher priority comes first and the lower priority comes first if the higher priority is the same. Bucket sort extension, similar to specifying bucket sort by bit, but can take advantage of the count sort for a small range of numbers.

    Algorithm description

    • Get the largest number in the array, and get the number of bits;
    • arr is the original array, and each bit is taken from the lowest point to form radix array.
    • radix was sorted by counting (taking advantage of the feature that counting sort is suitable for a small range of numbers);

    GIF presentation

    Radix Sort

    Code demo

    ts
    const getMax = (list: Array<number>) => {
    +  let max = list[0];
    +  for (let i = 0; i < list.length; i++) {
    +    if (max < list[i]) {
    +      max = list[i];
    +    }
    +  }
    +  return max;
    +};
    +const getDigit = (num: number) => {
    +  let digit = 1;
    +  while (num >= 1) {
    +    digit++;
    +    num = num / 10;
    +  }
    +  return digit;
    +};
    +/**
    + * @description: Radix Sort
    + * @param {Array<number>} list
    + * @return {Array<number>}
    + */
    +const radix = (list: Array<number>, maxDigit?: number): Array<number> => {
    +  if (list.length === 0) return list;
    +  if (!maxDigit) maxDigit = getDigit(getMax(list));
    +  const buckets = new Array(maxDigit).fill(0).map(() => new Array(0));
    +  for (let j = 0; j < list.length; j++) {
    +    const digit = getDigit(list[j]);
    +    buckets[digit - 1].push(list[j]);
    +  }
    +  list = [];
    +  for (let i = 0; i < buckets.length; i++) {
    +    list = list.concat(count(buckets[i]));
    +  }
    +  return list;
    +};

    Algorithm analysis

    Radix sort is based on distributive sort, so it is stable. But the performance of radix sort is slightly worse than bucket sort, each keyword bucket allocation requires O(n) time complexity, and after allocation to get a new keyword sequence requires O(n) time complexity. If the data to be sorted can be divided into d keywords, the time complexity of radix sort will be O(d*2n), of course, d is far less than n, so it is basically linear level.

    The spatial complexity of radix sort is O(n+k), where k is the number of buckets. Generally speaking, n> > k, so you need about n extra Spaces.

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/sort/select/index.html b/src/article/sort/select/index.html new file mode 100644 index 0000000000..4dfd5ef641 --- /dev/null +++ b/src/article/sort/select/index.html @@ -0,0 +1,66 @@ + + + + + + Selection Sort | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Selection Sort

    Select-sort is a simple and intuitive sorting algorithm. It works by first finding the smallest (large) element in the unsorted sequence and storing it at the beginning of the sorted sequence, then continuing to find the smallest (large) element from the remaining unsorted elements and placing it at the end of the sorted sequence. And so on until all the elements are sorted.

    Algorithm description

    Ordering results can be obtained by direct selection sorting of n records through n-1 direct selection sorting. The specific algorithm is described as follows:

    • Initial state: disordered region is R[1..n], ordered region is empty;
    • i sort (i=1,2,3... n-1) At the beginning, the current ordered and disordered regions are R[1..i-1] and R(i.. n). The run sort selects the record R[k] with the smallest keyword from the current unordered area and swaps it with the first record R in the unordered area, so that R[1..i] and R[i+1..n) become a new ordered area with 1 more records and a new unordered area with 1 less records, respectively.
    • n-1 is done. The array is ordered.

    GIF presentation

    Selection Sort

    Code demo

    js
    const select = (list: number[]): number[] => {
    +  const size = list.length;
    +  for (let i = 0; i < size; i++) {
    +    let minIndex = i;
    +    for (let j = i + 1; j < size; j++) {
    +      if (list[minIndex] >= list[j]) {
    +        minIndex = j;
    +      }
    +    }
    +    if (list[i] !== list[minIndex]) {
    +      list[i] = list[i] ^ list[minIndex];
    +      list[minIndex] = list[i] ^ list[minIndex];
    +      list[i] = list[i] ^ list[minIndex];
    +    }
    +  }
    +  return list;
    +};

    Algorithm analysis

    One of the most stable sorting algorithms, because whatever data goes in is O(n2) time complexity, so when using it, the smaller the data size, the better. The only benefit may be that it doesn't take up extra memory space. In theory, selection sorting may also be the most common sorting method that people think of.

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/sort/shell/index.html b/src/article/sort/shell/index.html new file mode 100644 index 0000000000..4d42d3b496 --- /dev/null +++ b/src/article/sort/shell/index.html @@ -0,0 +1,69 @@ + + + + + + Shell Sort | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Shell Sort

    Shell was invented in 1959, and the first breakthrough O(n2) sorting algorithm was an improved version of simple insertion sorting. It differs from insertion sort in that it gives preference to more distant elements. Hill sort is also called reduced increment sort.

    Algorithm description

    First, the whole record sequence to be sorted is divided into several sub-sequences for direct insertion sorting. The specific algorithm is described as follows:

    • Select an incremental sequence t1, t2,... tk, wherein ti> tj, tk=1;
    • According to the number of incremental sequences k, the sequence is sorted by k passes.
    • For each sequence, according to the corresponding increment ti, the sequence to be sorted is divided into several sub-sequences with length m, and each sub-table is sorted by direct insertion. When the increment factor is only 1, the entire sequence is treated as a table, and the length of the table is the length of the entire sequence.

    GIF presentation

    Shell Sort

    Code implementation

    js
    /**
    + * @description: Hill sort is an improved version of simple insertion sort. It differs from insertion sort in that it gives preference to more distant elements. Hill sort is also called reduced increment sort.
    + * @param {Array} list
    + * @return {Array}
    + */
    +const shell = (list: number[]): number[] => {
    +  const size = list.length;
    +  for (let gap = size >> 1; gap > 0; gap >>= 1) {
    +    for (let i = gap; i < size; i += gap) {
    +      const current = list[i];
    +      let preIndex = i - gap;
    +      while (preIndex >= 0 && list[preIndex] > current) {
    +        list[preIndex + gap] = list[preIndex];
    +        preIndex -= gap;
    +      }
    +      list[preIndex + gap] = current;
    +    }
    +  }
    +  return list;
    +};

    Algorithm analysis

    The core of Hill sort is the setting of interval sequence. The interval sequence can be set in advance, and the interval sequence can be defined dynamically. The algorithm for dynamically defining interval sequences was developed by Robert Sedgewick, co-author of Algorithms (4th Edition).

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/typescript/calculate.html b/src/article/typescript/calculate.html new file mode 100644 index 0000000000..2c605f4fa8 --- /dev/null +++ b/src/article/typescript/calculate.html @@ -0,0 +1,79 @@ + + + + + + 数组长度做计数 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    数组长度做计数

    类型系统不是图灵完备,各种逻辑都能写么,但好像没发现数值相关的逻辑。

    没错,数值相关的逻辑比较绕,被我单独摘了出来,就是这节要讲的内容。

    这是类型体操的第四个套路:数组长度做计数。

    TypeScript 类型系统没有加减乘除运算符,怎么做数值运算呢?

    不知道大家有没有注意到数组类型取 length 就是数值。

    比如:

    ts
    type num1 = [unknown]['length'];
    +// type num1 = 1
    +type num2 = [unknown, unknown]['length'];
    +// type num1 = 2
    +type num3 = [unknown, unknown, unknown]['length'];
    +// type num1 = 3

    而数组类型我们是能构造出来的,那么通过构造不同长度的数组然后取 length,不就是数值的运算么?

    TypeScript 类型系统中没有加减乘除运算符,但是可以通过构造不同的数组然后取 length 的方式来完成数值计算,把数值的加减乘除转化为对数组的提取和构造。

    (严格来说构造的是元组,大家知道数组和元组的区别就行)

    这点可以说是类型体操中最麻烦的一个点,需要思维做一些转换,绕过这个弯来。

    下面我们就来做一些真实的案例来掌握它吧。

    数组长度实现加减乘除

    Add

    我们知道了数值计算要转换为对数组类型的操作,那么加法的实现很容易想到:

    构造两个数组,然后合并成一个,取 length。

    比如 3 + 2,就是构造一个长度为 3 的数组类型,再构造一个长度为 2 的数组类型,然后合并成一个数组,取 length。

    构造多长的数组是不确定的,需要递归构造,这个我们实现过:

    ts
    type BuildArray<Length extends number, Ele = unknown, Arr extends unknown[] = []> = Arr['length'] extends Length
    +  ? Arr
    +  : BuildArray<Length, Ele, [...Arr, Ele]>;

    类型参数 Length 是要构造的数组的长度。类型参数 Ele 是数组元素,默认为 unknown。类型参数 Arr 为构造出的数组,默认是 []。

    如果 Arr 的长度到达了 Length,就返回构造出的 Arr,否则继续递归构造。

    构造数组实现了,那么基于它就能实现加法:

    ts
    type Add<Num1 extends number, Num2 extends number> = [...BuildArray<Num1>, ...BuildArray<Num2>]['length'];

    我们拿大一点的数测试下:

    ts
    type AddResult = Add<32, 25>;
    +// type AddResult = 57

    就这样,我们通过构造一定长度的数组取 length 的方式实现了加法运算。

    Subtract

    加法是构造数组,那减法怎么做呢?

    减法是从数值中去掉一部分,很容易想到可以通过数组类型的提取来做。

    比如 3 是 [unknown, unknown, unknown] 的数组类型,提取出 2 个元素之后,剩下的数组再取 length 就是 1。

    所以减法的实现是这样的:

    ts
    type Subtract<Num1 extends number, Num2 extends number> =
    +  BuildArray<Num1> extends [...arr1: BuildArray<Num2>, ...arr2: infer Rest] ? Rest['length'] : never;

    类型参数 Num1、Num2 分别是被减数和减数,通过 extends 约束为 number。

    构造 Num1 长度的数组,通过模式匹配提取出 Num2 长度个元素,剩下的放到 infer 声明的局部变量 Rest 里。

    取 Rest 的长度返回,就是减法的结果。

    就这样,我们通过数组类型的提取实现了减法运算。

    Multiply

    我们把加法转换为了数组构造,把减法转换为了数组提取。那乘法怎么做呢?

    为了解释乘法,我去翻了下小学教材,找到了这样一张图:

    1 乘以 5 就相当于 1 + 1 + 1 + 1 + 1,也就是说乘法就是多个加法结果的累加。

    那么我们在加法的基础上,多加一个参数来传递中间结果的数组,算完之后再取一次 length 就能实现乘法:

    ts
    type Multiplication<Num1 extends number, Num2 extends number, ResultArr extends unknown[] = []> = Num2 extends 0
    +  ? ResultArr['length']
    +  : Multiplication<Num1, Subtract<Num2, 1>, [...BuildArray<Num1>, ...ResultArr]>;

    类型参数 Num1 和 Num2 分别是被加数和加数。

    因为乘法是多个加法结果的累加,我们加了一个类型参数 ResultArr 来保存中间结果,默认值是 [],相当于从 0 开始加。

    每加一次就把 Num2 减一,直到 Num2 为 0,就代表加完了。

    加的过程就是往 ResultArr 数组中放 Num1 个元素。

    这样递归的进行累加,也就是递归的往 ResultArr 中放元素。

    最后取 ResultArr 的 length 就是乘法的结果。

    就这样,我们通过递归的累加实现了乘法。

    Divide

    乘法是递归的累加,那除法不就是递归的累减么?

    我再去翻了下小学教材,找到了这样一张图:

    我们有 9 个苹果,分给美羊羊 3 个,分给懒羊羊 3 个,分给沸羊羊 3 个,最后剩下 0 个。所以 9 / 3 = 3。

    所以,除法的实现就是被减数不断减去减数,直到减为 0,记录减了几次就是结果。

    也就是这样的:

    ts
    type Divide<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends 0
    +  ? CountArr['length']
    +  : Divide<Subtract<Num1, Num2>, Num2, [unknown, ...CountArr]>;

    类型参数 Num1 和 Num2 分别是被减数和减数。

    类型参数 CountArr 是用来记录减了几次的累加数组。

    如果 Num1 减到了 0,那么这时候减了几次就是除法结果,也就是 CountArr['length']。

    否则继续递归的减,让 Num1 减去 Num2,并且 CountArr 多加一个元素代表又减了一次。

    这样就实现了除法:

    就这样,我们通过递归的累减并记录减了几次实现了除法。

    做完了加减乘除,我们再来做一些别的数值计算的类型体操。

    数组长度实现计数

    StrLen

    数组长度可以取 length 来得到,但是字符串类型不能取 length,所以我们来实现一个求字符串长度的高级类型。

    字符串长度不确定,明显要用递归。每次取一个并计数,直到取完,就是字符串长度。

    ts
    type StrLen<Str extends string, CountArr extends unknown[] = []> = Str extends `${string}${infer Rest}`
    +  ? StrLen<Rest, [...CountArr, unknown]>
    +  : CountArr['length'];

    类型参数 Str 是待处理的字符串。类型参数 CountArr 是做计数的数组,默认值 [] 代表从 0 开始。

    每次通过模式匹配提取去掉一个字符之后的剩余字符串,并且往计数数组里多放入一个元素。递归进行取字符和计数。

    如果模式匹配不满足,代表计数结束,返回计数数组的长度 CountArr['length']。

    这样就能求出字符串长度:

    GreaterThan

    能够做计数了,那也就能做两个数值的比较。

    我们往一个数组类型中不断放入元素取长度,如果先到了 A,那就是 B 大,否则是 A 大:

    ts
    type GreaterThan<Num1 extends number, Num2 extends number, CountArr extends unknown[] = []> = Num1 extends Num2
    +  ? false
    +  : CountArr['length'] extends Num2
    +    ? true
    +    : CountArr['length'] extends Num1
    +      ? false
    +      : GreaterThan<Num1, Num2, [...CountArr, unknown]>;

    类型参数 Num1 和 Num2 是待比较的两个数。

    类型参数 CountArr 是计数用的,会不断累加,默认值是 [] 代表从 0 开始。

    如果 Num1 extends Num2 成立,代表相等,直接返回 false。

    否则判断计数数组的长度,如果先到了 Num2,那么就是 Num1 大,返回 true。

    反之,如果先到了 Num1,那么就是 Num2 大,返回 false。

    如果都没到就往计数数组 CountArr 中放入一个元素,继续递归。

    这样就实现了数值比较。

    当 3 和 4 比较时:

    Fibonacci

    谈到了数值运算,就不得不提起经典的 Fibonacci 数列的计算。

    Fibonacci 数列是 1、1、2、3、5、8、13、21、34、…… 这样的数列,有当前的数是前两个数的和的规律。

    F(0) = 1, F(1) = 1, F(n) = F(n - 1) + F(n - 2)(n ≥ 2, n ∈ N*)

    也就是递归的加法,在 TypeScript 类型编程里用构造数组来实现这种加法:

    ts
    type FibonacciLoop<
    +  PrevArr extends unknown[],
    +  CurrentArr extends unknown[],
    +  IndexArr extends unknown[] = [],
    +  Num extends number = 1,
    +> = IndexArr['length'] extends Num
    +  ? CurrentArr['length']
    +  : FibonacciLoop<CurrentArr, [...PrevArr, ...CurrentArr], [...IndexArr, unknown], Num>;
    +
    +type Fibonacci<Num extends number> = FibonacciLoop<[1], [], [], Num>;

    类型参数 PrevArr 是代表之前的累加值的数组。类型参数 CurrentArr 是代表当前数值的数组。

    类型参数 IndexArr 用于记录 index,每次递归加一,默认值是 [],代表从 0 开始。

    类型参数 Num 代表求数列的第几个数。

    判断当前 index 也就是 IndexArr['length'] 是否到了 Num,到了就返回当前的数值 CurrentArr['length']。

    否则求出当前 index 对应的数值,用之前的数加上当前的数 [...PrevArr, ... CurrentArr]。

    然后继续递归,index + 1,也就是 [...IndexArr, unknown]。

    这就是递归计算 Fibinacci 数列的数的过程。

    可以正确的算出第 8 个数是 21:

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/typescript/index.html b/src/article/typescript/index.html new file mode 100644 index 0000000000..540a7868f8 --- /dev/null +++ b/src/article/typescript/index.html @@ -0,0 +1,204 @@ + + + + + + TypeScript 的类型系统 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    TypeScript 的类型系统

    一。类型是什么

    类型具体点来说就是指 number、boolean、string 等基础类型和 Object、Function 等复合类型,它们是编程语言提供的对不同内容的抽象:

    • 不同类型变量占据的内存大小不同: boolean 类型的变量会分配 4 个字节的内存,而 number 类型的变量则会分配 8 个字节的内存,给变量声明了不同的类型就代表了会占据不同的内存空间。

    • 不同类型变量可做的操作不同: number 类型可以做加减乘除等运算,boolean 就不可以,复合类型中不同类型的对象可用的方法不同,比如 Date 和 RegExp,变量的类型不同代表可以对该变量做的操作就不同。

    有了类型,那我们的操作必须和类型相匹配,否则就会报错,这就是类型检查。

    如果能保证对某种类型只做该类型允许的操作,这就叫做类型安全。

    类型检查可以在运行时做,也可以运行之前的编译期做。这是两种不同的类型,前者叫做动态类型检查,后者叫做静态类型检查。

    两种类型检查各有优缺点。动态类型检查 在源码中不保留类型信息,对某个变量赋什么值、做什么操作都是允许的,写代码很灵活。但这也埋下了类型不安全的隐患,比如对 string 做了乘除,对 Date 对象调用了 exec 方法,这些都是运行时才能检查出来的错误。

    其中,最常见的错误应该是“null is not an object”、“undefined is not a function”之类的了,写代码时没发现类型不匹配,到了运行的时候才发现,就会有很多这种报错。

    所以,动态类型虽然代码写起来简单,但代码中很容易藏着一些类型不匹配的隐患。

    静态类型检查则是在源码中保留类型信息,声明变量要指定类型,对变量做的操作要和类型匹配,会有专门的编译器在编译期间做检查。

    静态类型给写代码增加了一些难度,因为你除了要考虑代码要表达的逻辑之外,还要考虑类型逻辑:变量是什么类型的、是不是匹配、要不要做类型转换等。

    不过,静态类型也消除了类型不安全的隐患,因为在编译期间就做了类型检查,就不会出现对 string 做了乘除,调用了 Date 的 exec 方法这类问题。

    所以,静态类型虽然代码写起来要考虑的问题多一些,会复杂一些,但是却消除了代码中潜藏类型不安全问题的可能。

    知道了动态类型检查和静态类型检查的区别,我们自然可以得出这样的结论:

    动态类型只适合简单的场景,对于大项目却不太合适,因为代码中可能藏着的隐患太多了,万一线上报一个类型不匹配的错误,那可能就是大问题。

    而静态类型虽然会增加写代码的成本,但是却能更好的保证代码的健壮性,减少 Bug 率。

    所以,大型项目注定会用静态类型语言开发。

    二。类型系统的分类

    1.简单的类型系统

    变量、函数、类等都可以声明类型,编译器会基于声明的类型做类型检查,类型不匹配时会报错。

    这是最基础的类型系统,能保证类型安全,但有些死板。

    比如一个 add 函数既可以做整数加法、又可以做浮点数加法,却需要声明两个函数:

    c
    int add(int a, int b) {
    +    return a + b;
    +}
    +
    +double add(double a, double b) {
    +    return a + b;
    +}

    这个问题的解决思路很容易想到:如果类型能传参数就好了,传入 int 就是整数加法,传入 double 就是浮点数加法。

    所以,就有了第二种类型系统。

    2.支持泛型的类型系统

    泛型的英文是 Generic Type,通用的类型,它可以代表任何一种类型,也叫做类型参数。

    它给类型系统增加了一些灵活性,在整体比较固定,部分变量的类型有变化的情况下,可以减少很多重复代码。

    比如上面的 add 函数,有了泛型之后就可以这样写:

    java
    T add<T>(T a, T b) {
    +    return a + b;
    +}
    +
    +add(1,2);
    +add(1.111, 2.2222);

    声明时把会变化的类型声明成泛型(也就是类型参数),在调用的时候再确定类型。

    Java 就是这种类型系统。如果你看过 Java 代码,你会发现泛型用的特别多,这确实是一个很好的增加类型系统灵活性的特性。

    但是,这种类型系统的灵活性对于 JavaScript 来说还不够,因为 JavaScript 太过灵活了。

    比如,在 Java 里,对象都是由类 new 出来的,你不能凭空创建对象,但是 JavaScript 却可以,它支持对象字面量。

    那如果是一个返回对象某个属性值的函数,类型该怎么写呢?

    ts
    function getPropValue<T>(obj: T, key): key对应的属性值类型 {
    +  return obj[key];
    +}

    好像拿到了 T,也不能拿到它的属性和属性值,如果能对类型参数 T 做一些逻辑处理就好了。

    所以,就有了第三种类型系统。

    3.支持类型编程的类型系统

    在 Java 里面,拿到了对象的类型就能找到它的类,进一步拿到各种信息,所以类型系统支持泛型就足够了。

    但是在 JavaScript 里面,对象可以字面量的方式创建,还可以灵活的增删属性,拿到对象并不能确定什么,所以要支持对传入的类型参数做进一步的处理。

    对传入的类型参数(泛型)做各种逻辑运算,产生新的类型,这就是类型编程。

    比如上面那个 getProps 的函数,类型可以这样写:

    ts
    function getPropValue<T extends object, Key extends keyof T>(obj: T, key: Key): T[Key] {
    +  return obj[key];
    +}

    这里的 keyof T、T[Key] 就是对类型参数 T 的类型运算。

    TypeScript 的类型系统就是第三种,支持对类型参数做各种逻辑处理,可以写很复杂的类型逻辑。

    类型逻辑可以多复杂?

    类型逻辑是对类型参数的各种处理,可以实现很多强大的功能:

    比如这个 ParseQueryString 的类型:

    ts
    type res = ParseQueryString<'a=1&b=2&c=3'>;

    它可以对传入的字符串的类型参数做解析,返回解析以后的结果。等于

    ts
    type res = {
    +  a: '1';
    +  b: '2';
    +  c: '3';
    +};

    如果是 Java 的只支持泛型的类型系统可以做到么?明显不能。但是 TypeScript 的类型系统就可以,因为它可以对泛型(类型参数)做各种逻辑处理。

    只不过,这个类型的类型逻辑的代码比较多(下面的 ts 类型暂时看不懂没关系,在顺口溜那节会有详解,这里只是用来直观感受下类型编程的复杂度的,等学完以后大家也能实现这样的复杂高级类型的):

    ts
    type ParseParam<Param extends string> = Param extends `${infer Key}=${infer Value}`
    +  ? {
    +      [K in Key]: Value;
    +    }
    +  : {};
    +
    +type MergeValues<One, Other> = One extends Other ? One : Other extends unknown[] ? [One, ...Other] : [One, Other];
    +
    +type MergeParams<OneParam extends Record<string, any>, OtherParam extends Record<string, any>> = {
    +  [Key in keyof OneParam | keyof OtherParam]: Key extends keyof OneParam
    +    ? Key extends keyof OtherParam
    +      ? MergeValues<OneParam[Key], OtherParam[Key]>
    +      : OneParam[Key]
    +    : Key extends keyof OtherParam
    +      ? OtherParam[Key]
    +      : never;
    +};
    +type ParseQueryString<Str extends string> = Str extends `${infer Param}&${infer Rest}`
    +  ? MergeParams<ParseParam<Param>, ParseQueryString<Rest>>
    +  : ParseParam<Str>;

    TypeScript 的类型系统是图灵完备的,也就是能描述各种可计算逻辑。简单点来理解就是循环、条件等各种 JS 里面有的语法它都有,JS 能写的逻辑它都能写。

    对类型参数的编程是 TypeScript 类型系统最强大的部分,可以实现各种复杂的类型计算逻辑,是它的优点。但同时也被认为是它的缺点,因为除了业务逻辑外还要写很多类型逻辑。

    不过,我倒是觉得这种复杂度是不可避免的,因为 JS 本身足够灵活,要准确定义类型那类型系统必然也要设计的足够灵活。

    4.类型安全和型变

    TypeScript 给 JavaScript 添加了一套静态类型系统,是为了保证类型安全的,也就是保证变量只能赋同类型的值,对象只能访问它有的属性、方法。

    比如 number 类型的值不能赋值给 boolean 类型的变量,Date 类型的对象就不能调用 exec 方法。

    这是类型检查做的事情,遇到类型安全问题会在编译时报错。

    但是这种类型安全的限制也不能太死板,有的时候需要一些变通,比如子类型是可以赋值给父类型的变量的,可以完全当成父类型来使用,也就是“型变(variant)”(类型改变)。

    这种“型变”分为两种,一种是子类型可以赋值给父类型,叫做协变(covariant),一种是父类型可以赋值给子类型,叫做逆变(contravariant)。

    先来看下协变:

    协变(covariant)

    对具体成员的输出参数进行一次类型转换,且类型转换的准则是“里氏替换原则”。

    其中协变是很好理解的,比如我们有两个 interface:

    ts
    interface Animal {
    +  name: string;
    +  age: number;
    +}
    +
    +interface Cat {
    +  name: string;
    +  age: number;
    +  hobbies: string[];
    +}

    这里 Cat 是 Animal 的子类型,更具体,那么 Cat 类型的变量就可以赋值给 Animal 类型:

    ts
    let animal: Animal = {
    +  name: 'cat',
    +  age: 3,
    +};
    +
    +let cat: Cat = {
    +  name: 'Tony',
    +  age: 5,
    +  hobbies: ['run', 'swim'],
    +};
    +
    +animal = cat;

    这并不会报错,虽然这俩类型不一样,但是依然是类型安全的。

    这种子类型可以赋值给父类型的情况就叫做协变。

    为什么要支持协变很容易理解:类型系统支持了父子类型,那如果子类型还不能赋值给父类型,还叫父子类型么?

    所以型变是实现类型父子关系必须的,它在保证类型安全的基础上,增加了类型系统的灵活性。

    逆变相对难理解一些:

    逆变(contravariant)

    是对具体成员的输入参数进行一次类型转换,且类型转换的准则是"里氏替换原则"。

    我们有这样两个函数:

    ts
    let printHobbies: (cat: Cat) => void;
    +
    +printHobbies = (cat) => {
    +  console.log(cat.hobbies);
    +};
    +
    +let printName: (animal: Animal) => void;
    +
    +printName = (animal) => {
    +  console.log(animal.name);
    +};

    printHobbies 的参数 Guang 是 printName 参数 Person 的子类型。

    那么问题来了,printName 能赋值给 printHobbies 么?printHobbies 能赋值给 printName 么?

    测试一下发现是这样的:

    ts
    let printHobbies: (cat: Cat) => void;
    +
    +printHobbies = (cat) => {
    +  console.log(cat.hobbies);
    +};
    +
    +let printName: (animal: Animal) => void;
    +
    +printName = (animal) => {
    +  console.log(animal.name);
    +};
    +
    +printHobbies = printName;

    printName 的参数 Person 不是 printHobbies 的参数 Guang 的父类型么,为啥能赋值给子类型?

    因为这个函数调用的时候是按照 Guang 来约束的类型,但实际上函数只用到了父类型 Person 的属性和方法,当然不会有问题,依然是类型安全的。

    这就是逆变,函数的参数有逆变的性质(而返回值是协变的,也就是子类型可以赋值给父类型)。

    那反过来呢,如果 printHoobies 赋值给 printName 会发生什么?

    因为函数声明的时候是按照 Person 来约束类型,但是调用的时候是按照 Guang 的类型来访问的属性和方法,那自然类型不安全了,所以就会报错。

    但是在 ts2.x 之前支持这种赋值,也就是父类型可以赋值给子类型,子类型可以赋值给父类型,既逆变又协变,叫做“双向协变”。

    但是这明显是有问题的,不能保证类型安全,所以之后 ts 加了一个编译选项 strictFunctionTypes,设置为 true 就只支持函数参数的逆变,设置为 false 则是双向协变。

    我们把 strictFunctionTypes 关掉之后,就会发现两种赋值都可以了。

    这样就支持函数参数的双向协变,类型检查不会报错,但不能严格保证类型安全。

    开启之后,函数参数就只支持逆变,子类型赋值给父类型就会报错。

    再举个逆变的例子,大家觉得下面这样的 ts 代码会报错么:

    ts
    type Func = (a: string) => void;
    +
    +const func: Func = (a: 'hello') => undefined;

    答案是参数的位置会,返回值的位置不会:

    参数的位置是逆变的,也就是被赋值的函数参数要是赋值的函数参数的子类型,而 string 不是 'hello' 的子类型,所以报错了。

    返回值的位置是协变的,也就是赋值的函数的返回值是被赋值的函数的返回值的子类型,这里 undefined 是 void 的子类型,所以不报错。

    不变(invariant)

    逆变和协变都是型变,是针对父子类型而言的,非父子类型自然就不会型变,也就是不变:

    非父子类型之间不会发生型变,只要类型不一样就会报错

    那类型之间的父子关系是怎么确定的呢,好像也没有看到 extends 的继承?

    像 java 里面的类型都是通过 extends 继承的,如果 A extends B,那 A 就是 B 的子类型。这种叫做名义类型系统(nominal type)。

    而 ts 里不看这个,只要结构上是一致的,那么就可以确定父子关系,这种叫做结构类型系统(structual type)。

    通过结构,更具体的那个是子类型。这里的 Cat 有 Animal 的所有属性,并且还多了一些属性,所以 Cat 是 Animal 的子类型。

    注意,这里用的是更具体,而不是更多。

    判断联合类型父子关系的时候, 'a' | 'b' 和 'a' | 'b' | 'c' 哪个更具体?

    'a' | 'b' 更具体,所以 'a' | 'b' 是 'a' | 'b' | 'c' 的子类型。

    三.TypeScript 类型系统

    1.支持的类型

    静态类型系统的目的是把类型检查从运行时提前到编译时,那 TS 类型系统中肯定要把 JS 的运行时类型拿过来,也就是 number、boolean、string、object、bigint、symbol、undefined、null 这些类型,还有就是它们的包装类型 Number、Boolean、String、Object、Symbol。

    这些很容易理解,给 JS 添加静态类型,总没有必要重新造一套基础类型吧,直接复用 JS 的基础类型就行。

    复合类型方面,JS 有 class、Array,这些 TypeScript 类型系统也都支持,但是又多加了三种类型:元组(Tuple)、接口(Interface)、枚举(Enum)。

    元组

    元组(Tuple)就是元素个数和类型固定的数组类型:

    ts
    type Tuple = [number, string];

    接口

    接口(Interface)可以描述函数、对象、构造器的结构:

    对象:

    ts
    interface IPerson {
    +  name: string;
    +  age: number;
    +}
    +
    +class Person implements IPerson {
    +  name: string;
    +  age: number;
    +}
    +
    +const obj: IPerson = {
    +  name: 'guang',
    +  age: 18,
    +};

    函数:

    ts
    interface SayHello {
    +  (name: string): string;
    +}
    +
    +const func: SayHello = (name: string) => {
    +  return 'hello,' + name;
    +};

    构造器:

    ts
    interface PersonConstructor {
    +  new (name: string, age: number): IPerson;
    +}
    +
    +function createPerson(ctor: PersonConstructor): IPerson {
    +  return new ctor('guang', 18);
    +}

    对象类型、class 类型在 TypeScript 里也叫做索引类型,也就是索引了多个元素的类型的意思。对象可以动态添加属性,如果不知道会有什么属性,可以用可索引签名:

    ts
    interface IPerson {
    +  [prop: string]: string | number;
    +}
    +const obj: IPerson = {};
    +obj.name = 'guang';
    +obj.age = 18;

    总之,接口可以用来描述函数、构造器、索引类型(对象、class、数组)等复合类型。

    枚举

    枚举(Enum)是一系列值的复合:

    ts
    enum Transpiler {
    +  Babel = 'babel',
    +  Postcss = 'postcss',
    +  Terser = 'terser',
    +  Prettier = 'prettier',
    +  TypeScriptCompiler = 'tsc',
    +}
    +
    +const transpiler = Transpiler.TypeScriptCompiler;

    此外,TypeScript 还支持字面量类型,也就是类似 1111、'aaaa'、{ a: 1} 这种值也可以做为类型。

    其中,字符串的字面量类型有两种,一种是普通的字符串字面量,比如 'aaa',另一种是模版字面量,比如 aaa${string},它的意思是以 aaa 开头,后面是任意 string 的字符串字面量类型。

    所以想要约束以某个字符串开头的字符串字面量类型时可以这样写:

    ts
    function func(str: `#${string}`) {}
    +
    +func('aaaa'); // error
    +
    +func('#aaaa'); // true

    还有四种特殊的类型:void、never、any、unknown:

    • never 代表不可达,比如函数抛异常的时候,返回值就是 never。
    • void 代表空,可以是 undefined 或 never。
    • any 是任意类型,任何类型都可以赋值给它,它也可以赋值给任何类型(除了 never)。
    • unknown 是未知类型,任何类型都可以赋值给它,但是它不可以赋值给别的类型。

    这些就是 TypeScript 类型系统中的全部类型了,大部分是从 JS 中迁移过来的,比如基础类型、Array、class 等,也添加了一些类型,比如 枚举(enum)、接口(interface)、元组等,还支持了字面量类型和 void、never、any、unknown 的特殊类型。

    2.类型的装饰

    除了描述类型的结构外,TypeScript 的类型系统还支持描述类型的属性,比如是否可选,是否只读等:

    ts
    interface IPerson {
    +  readonly name: string;
    +  age?: number;
    +}
    +
    +type tuple = [string, number?];

    3.类型运算

    我们知道了 TypeScript 类型系统里有哪些类型,那么可以对这些类型做什么类型运算呢?

    条件:extends ?

    TypeScript 里的条件判断是 extends ? :,叫做条件类型(Conditional Type)比如:

    ts
    type res = 1 extends 2 ? true : false; // type res = false

    这就是 TypeScript 类型系统里的 if else。

    但是,上面这样的逻辑没啥意义,静态的值自己就能算出结果来,为什么要用代码去判断呢?

    所以,类型运算逻辑都是用来做一些动态的类型的运算的,也就是对类型参数的运算。

    ts
    type isTwo<T> = T extends 2 ? true : false;
    +
    +type res = isTwo<1>; // type res = false
    +type res2 = isTwo<2>; // type res = true

    这种类型也叫做高级类型。

    高级类型的特点是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

    推导:infer

    如何提取类型的一部分呢?答案是 infer。

    比如提取元组类型的第一个元素:

    ts
    type First<Tuple extends unknown[]> = Tuple extends [infer T, ...infer R] ? T : never;
    +
    +type res = First<[1, 2, 3]>; // type res = 1

    注意,第一个 extends 不是条件,条件类型是 extends ? :,这里的 extends 是约束的意思,也就是约束类型参数只能是数组类型。

    因为不知道数组元素的具体类型,所以用 unknown。

    infer 在后面的章节会大量用到,这里先简单了解即可。

    联合:|

    联合类型(Union)类似 js 里的或运算符 |,但是作用于类型,代表类型可以是几个类型之一。

    ts
    type Union = 1 | 2 | 3;

    交叉:&

    交叉类型(Intersection)类似 js 中的与运算符 &,但是作用于类型,代表对类型做合并。

    ts
    type ObjType = { a: number } & { c: boolean };

    注意,同一类型可以合并,不同的类型没法合并,会被舍弃:

    可以合并的

    ts
    type ObjType = { a: number } & { c: boolean };
    +
    +type res = { a: number; c: boolean } extends ObjType ? true : false; // type res = true

    不可合并

    ts
    type res = 'aaaa' & 2222; // type res = never

    映射类型

    对象、class 在 TypeScript 对应的类型是索引类型(Index Type),那么如何对索引类型作修改呢?

    答案是映射类型。

    ts
    type MapType<T> = {
    +  [Key in keyof T]?: T[Key];
    +};

    keyof T 是查询索引类型中所有的索引,叫做索引查询。

    T[Key] 是取索引类型某个索引的值,叫做索引访问。

    in 是用于遍历联合类型的运算符。

    比如我们把一个索引类型的值变成 3 个元素的数组:

    ts
    type MapType<T> = {
    +  [Key in keyof T]: [T[Key], T[Key], T[Key]];
    +};
    +
    +type res = MapType<{ a: 1; b: 2 }>; // type res = { a: [1, 1, 1]; b:[2, 2, 2]; }

    映射类型就相当于把一个集合映射到另一个集合,这是它名字的由来。

    除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。

    我们用 as 把索引也做了修改,改成了 3 个 key 重复:

    ts
    type MapType<T> = {
    +  [Key in keyof T as `${Key & string}${Key & string}${Key & string}`]: [T[Key], T[Key], T[Key]];
    +};
    +
    +// type res = { aaa: [1, 1, 1]; bbb: [2, 2, 2]; }

    这里的 & string 可能大家会迷惑,解释一下:

    因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是 string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型会把同一类型做合并,不同类型舍弃。

    四。判断类型的类型

    IsAny

    如何判断一个类型是 any 类型呢?要根据它的特性来:

    any 类型与任何类型的交叉都是 any,也就是 1 & any 结果是 any。

    所以,可以这样写:

    ts
    type IsAny<T> = 'null' extends 'undefined' & T ? true : false;

    IsEqual

    之前我们实现 IsEqual 是这样写的:

    ts
    type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

    问题出在 any 的判断上:

    ts
    type IsEqualResult = IsEqual<'aaa', any>;
    +// type IsEqualResult = false

    因为 any 可以是任何类型,任何类型也都是 any,所以当这样写判断不出 any 类型来。

    所以,我们会这样写:

    ts
    type IsEqual<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;

    这样就能正常判断了:

    其中 T 是不传类型的,相当于一个临时变量

    其目的是对比:

    ts
    <T>() => T extends X ? 1 : 2
    +<T>() => T extends Y ? 1 : 2

    这两个泛型函数类型是否相等,原理

    IsUnion

    还记得怎么判断 union 类型么?要根据它遇到条件类型时会分散成单个传入做计算的特性:

    ts
    type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

    IsNever

    never 在条件类型中也比较特殊,如果条件类型左边是类型参数,并且传入的是 never,那么直接返回 never:

    ts
    type TestNever<T> = T extends number ? 1 : 2;

    当 T 为 never 时:

    ts
    type TestNeverResult = TestNever<never>;
    +// type TestNeverResult = never

    所以,要判断 never 类型,就不能直接 T extends number,可以这样写:

    ts
    type IsNever<T> = [T] extends [never] ? true : false;

    这样就能正常判断 never 类型了:

    ts
    type TestNeverResult = IsNever<never>;
    +// type TestNeverResult = true

    除此以外,any 在条件类型中也比较特殊,如果类型参数为 any,会直接返回 trueType 和 falseType 的合并:

    ts
    type TestAny<T> = T extends number ? 1 : 2;
    +
    +type TestAnyResult = TestAny<any>;
    +// type TestAnyResult = 1 | 2

    联合类型、never、any 在作为条件类型的类型参数时的这些特殊情况,也会在后面的原理篇来解释原因。

    IsTuple

    元组类型怎么判断呢?它和数组有什么区别呢?

    元组类型的 length 是数字字面量,而数组的 length 是 number。

    ts
    type len

    UnionToIntersection

    类型之间是有父子关系的,更具体的那个是子类型,比如 A 和 B 的交叉类型 A & B 就是联合类型 A | B 的子类型,因为更具体。

    如果允许父类型赋值给子类型,就叫做逆变

    如果允许子类型赋值给父类型,就叫做协变

    (关于逆变、协变等概念的详细解释可以看原理篇)

    在 TypeScript 中有函数参数是有逆变的性质的,也就是如果参数可能是多个类型,参数类型会变成它们的交叉类型。

    所以联合转交叉可以这样实现:

    ts
    type UnionToIntersection<U> = (U extends U ? (x: U) => unknown : never) extends (x: infer R) => unknown ? R : never;

    类型参数 U 是要转换的联合类型。

    U extends U 是为了触发联合类型的 distributive 的性质,让每个类型单独传入做计算,最后合并。

    利用 U 做为参数构造个函数,通过模式匹配取参数的类型。

    结果就是交叉类型

    函数参数的逆变性质一般就联合类型转交叉类型会用,记住就行。

    GetOptional

    如何提取索引类型中的可选索引呢?

    这也要利用可选索引的特性:可选索引的值为 undefined 和值类型的联合类型。

    过滤可选索引,就要构造一个新的索引类型,过程中做过滤:

    ts
    type GetOptional<Obj extends Record<string, any>> = {
    +  [Key in keyof Obj as {} extends Pick<Obj, Key> ? Key : never]: Obj[Key];
    +};

    类型参数 Obj 为待处理的索引类型,类型约束为索引为 string、值为任意类型的索引类型 Record<string, any>。

    用映射类型的语法重新构造索引类型,索引是之前的索引也就是 Key in keyof Obj,但要做一些过滤,也就是 as 之后的部分。

    过滤的方式就是单独取出该索引之后,判断空对象是否是其子类型。

    这里的 Pick 是 ts 提供的内置高级类型,就是取出某个 Key 构造新的索引类型:

    ts
    type Pick<T, K extends keyof T> = { [P in K]: T[P] };

    比如单独取出 age 构造的新的索引类型是这样的:

    可选的意思是这个索引可能没有,没有的时候,那 Pick<Obj, Key> 就是空的,所以 {} extends Pick<Obj, Key> 就能过滤出可选索引。

    值的类型依然是之前的,也就是 Obj[Key]。

    这样,就能过滤出所有可选索引,构造成新的索引类型:

    总结

    • any 类型与任何类型的交叉都是 any,也就是 1 & any 结果是 any,可以用这个特性判断 any 类型。
    • 联合类型作为类型参数出现在条件类型左侧时,会分散成单个类型传入,最后合并。
    • never 作为类型参数出现在条件类型左侧时,会直接返回 never。
    • any 作为类型参数出现在条件类型左侧时,会直接返回 trueType 和 falseType 的联合类型。
    • 元组类型也是数组类型,但 length 是数字字面量,而数组的 length 是 number。可以用来判断元组类型。
    • 函数参数处会发生逆变,可以用来实现联合类型转交叉类型。
    • 可选索引的索引可能没有,那 Pick 出来的就可能是 {},可以用来过滤可选索引,反过来也可以过滤非可选索引。
    • 索引类型的索引为字符串字面量类型,而可索引签名不是,可以用这个特性过滤掉可索引签名。
    • keyof 只能拿到 class 的 public 的索引,可以用来过滤出 public 的属性。
    • 默认推导出来的不是字面量类型,加上 as const 可以推导出字面量类型,但带有 readonly 修饰,这样模式匹配的时候也得加上 readonly 才行。

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/typescript/pattern.html b/src/article/typescript/pattern.html new file mode 100644 index 0000000000..8c752de9e1 --- /dev/null +++ b/src/article/typescript/pattern.html @@ -0,0 +1,141 @@ + + + + + + 模式匹配提取 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    模式匹配提取

    字符串可以和正则做模式匹配,找到匹配的部分,提取子组,之后可以用 1,2 等引用匹配的子组。

    ts
    'abc'.replace(/a(b)c/, '$1,$1,$1');
    +// 'b,b,b'

    Typescript 的类型也同样可以做模式匹配。

    比如这样一个 Promise 类型:

    ts
    type p = Promise<'value'>;

    我们想提取 value 的类型,可以这样做:

    ts
    type GetValueType<P> = P extends Promise<infer Value> ? Value : never;

    通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取的,通过 infer 声明一个局部变量 Value 来保存,如果匹配,就返回匹配到的 Value,否则就返回 never 代表没匹配到。

    ts
    // type GetValueResult = 'value'
    +type GetValueResult = GetValueType<Promise<'value'>>;

    这就是 Typescript 类型的模式匹配:

    Typescript 类型的模式匹配是通过 extends 对类型参数做匹配,结果保存到通过 infer 声明的局部类型变量里,如果匹配就能从该局部变量里拿到提取出的类型。

    这个模式匹配的套路有多有用呢?我们来看下在数组、字符串、函数、构造器等类型里的应用。

    1.数组类型

    提取第一个元素

    数组类型想提取第一个元素的类型怎么做呢?

    ts
    type arr = [1, 2, 3];

    用它来匹配一个模式类型,提取第一个元素的类型到通过 infer 声明的局部变量里返回。

    ts
    type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;

    类型参数 Arr 通过 extends 约束为只能是数组类型,数组元素是 unkown 也就是可以是任何值。

    any 和 unknown 的区别:any 和 unknown 都代表任意类型,但是 unknown 只能接收任意类型的值,而 any 除了可以接收任意类型的值,也可以赋值给任意类型(除了 never)。类型体操中经常用 unknown 接受和匹配任何类型,而很少把任何类型赋值给某个类型变量。

    对 Arr 做模式匹配,把我们要提取的第一个元素的类型放到通过 infer 声明的 First 局部变量里,后面的元素可以是任何类型,用 unknown 接收,然后把局部变量 First 返回。

    当类型参数 Arr 为 [1,2,3] 时:

    ts
    type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;
    +type GetFirstValue = GetFirst<[1, 2, 3]>;
    +// type GetFirstValue = 1

    当类型参数 Arr 为 [] 时:

    ts
    type GetFirstResult = GetFirst<[]>;
    +// type GetFirstResult = never

    提取最后一个元素

    可以提取第一个元素,当然也可以提取最后一个元素,修改下模式类型就行:

    ts
    type GetLastValue<Arr extends unknown[]> = Arr extends [...unknown, infer Last] ? Last : never;

    当类型参数 Arr 为 [1,2,3]时:

    ts
    type GetLastResult = GetFirst<[1, 2, 3]>;
    +// type GetLastResult = 3

    PopArr

    我们分别取了首尾元素,当然也可以取剩余的数组,比如取去掉了最后一个元素的数组:

    ts
    type PopArr<Arr extends unknown[]> = Arr extends [...infer Rest, unknown] ? Rest : never;

    如果是空数组,就直接返回,否则匹配剩余的元素,放到 infer 声明的局部变量 Rest 里,返回 Rest。

    当类型参数 Arr 为 [1,2,3] 时:

    ts
    type PopResult = PopArr<[1, 2, 3]>;
    +// type PopResult = [1,2]

    当类型参数 Arr 为 [] 时:

    ts
    type PopResult = PopArr<[]>;
    +// type PopResult = []

    ShiftArr

    同理可得 ShiftArr 的实现:

    ts
    type ShiftArr<Arr extends unknown[]> = Arr extends [unknown, ...infer Rest] ? Rest : never;

    当类型参数 Arr 为 [1,2,3]时:

    ts
    type ShiftResult = ShiftArr<[1, 2, 3]>;
    +// type ShiftResult = [2,3]

    2.字符串类型

    字符串类型也同样可以做模式匹配,匹配一个模式字符串,把需要提取的部分放到 infer 声明的局部变量里。

    StartsWith

    判断字符串是否以某个前缀开头,也是通过模式匹配:

    ts
    type StartWith<str extends string, Prefix extends string> = Str extends `${Prefix}${string}` ? true : false;

    需要声明字符串 Str、匹配的前缀 Prefix 两个类型参数,它们都是 string。

    用 Str 去匹配一个模式类型,模式类型的前缀是 Prefix,后面是任意的 string,如果匹配返回 true,否则返回 false。

    当匹配时:

    ts
    type StartWithResult = StartWidth<'prefix string', 'prefix'>;
    +// type StartWithResult = true

    不匹配时:

    ts
    type StartWithResult = StartWidth<'prefix string', 'string'>;
    +// type StartWithResult = false

    Replace

    字符串可以匹配一个模式类型,提取想要的部分,自然也可以用这些再构成一个新的类型。

    比如实现字符串替换:

    ts
    type ReplaceStr<
    +  Str extends string,
    +  From extends string,
    +  To extends string,
    +> = Str extends `${infer Prefix}${From}${infer Suffix}` ? `${Prefix}${To}${Suffix}` : Str;

    声明要替换的字符串 Str、待替换的字符串 From、替换成的字符串 3 个类型参数,通过 extends 约束为都是 string 类型。

    用 Str 去匹配模式串,模式串由 From 和之前之后的字符串构成,把之前之后的字符串放到通过 infer 声明的局部变量 Prefix、Suffix 里。

    用 Prefix、Suffix 加上替换到的字符串 To 构造成新的字符串类型返回。

    当匹配时:

    ts
    type ReplaceResult = ReplaceStr<'str replace to result', 'result', 'aaaa'>;
    +// type ReplaceResult =  'str replace to aaaa'

    不匹配时:

    ts
    type ReplaceResult = ReplaceStr<'str replace to result', '???', 'aaaa'>;
    +// type ReplaceResult =  'str replace to result'

    Trim

    能够匹配和替换字符串,那也就能实现去掉空白字符的 Trim:

    不过因为我们不知道有多少个空白字符,所以只能一个个匹配和去掉,需要递归。

    先实现 TrimRight:

    ts
    type TrimRight<Str extends string> = Str extends `${infer Rest}${' ' | '\n''\t'}` ? TrimRight<Rest> : Str

    类型参数 Str 是要 Trim 的字符串。

    如果 Str 匹配字符串 + 空白字符 (空格、换行、制表符),那就把字符串放到 infer 声明的局部变量 Rest 里。

    把 Rest 作为类型参数递归 TrimRight,直到不匹配,这时的类型参数 Str 就是处理结果。

    ts
    type TrimRightResult = TrimRight<'value          '>;
    +// type TrimRightResult = 'value'

    同理可得 TrimLeft:

    ts
    type TrimLeft<Str extends string> = Str extends `${' '|'\n'|'\t'}`${infer Rest} ? TrimLeft<Rest> : Str

    TrimRight 和 TrimLeft 结合就是 Trim:

    ts
    type Trim<Str extends string> = TrimRight<TrimLeft<Str>>;

    3.函数

    函数同样也可以做类型匹配,比如提取参数、返回值的类型。

    GetParameters

    函数类型可以通过模式匹配来提取参数的类型:

    ts
    type GetParameters<Func extends Function> = Func extends (...args: infer Args) => unknown ? Args : never;

    类型参数 Func 是要匹配的函数类型,通过 extends 约束为 Function。

    Func 和模式类型做匹配,参数类型放到用 infer 声明的局部变量 Args 里,返回值可以是任何类型,用 unknown。

    返回提取到的参数类型 Args。

    ts
    type GetParametersResult = GetParameters<(name: string, age: number) => string>;
    +// type GetParametersResult = [name:string,age:number]

    GetReturnType

    能提取参数类型,同样也可以提取返回值类型:

    ts
    type GetReturnType<Func extends Function> = Func extends (...args: unknown[]) => infer ReturnType ? ReturnType : never;

    Func 和模式类型做匹配,提取返回值到通过 infer 声明的局部变量 ReturnType 里返回。

    参数类型可以是任意类型,也就是 any[](注意,这里不能用 unknown,这里的解释涉及到参数的逆变性质,具体原因逆变那一节会解释)。

    ts
    type GetReturnTypeResult = GetReturnType<() => 'return value'>;
    +// type GetReturnTypeResult = 'return value'

    GetThisParameterType

    方法里可以调用 this,比如这样:

    ts
    class Dong {
    +  name: string;
    +
    +  constructor() {
    +    this.name = 'dong';
    +  }
    +
    +  hello() {
    +    return "hello, I'm " + this.name;
    +  }
    +}
    +
    +const dong = new Dong();
    +dong.hello();

    用对象。方法名的方式调用的时候,this 就指向那个对象。

    但是方法也可以用 call 或者 apply 调用:

    ts
    class Dong {
    +  name: string;
    +
    +  constructor() {
    +    this.name = 'dong';
    +  }
    +
    +  hello() {
    +    return "hello, I'm " + this.name;
    +  }
    +}
    +
    +const dong = new Dong();
    +dong.hello().call({ x: 1 });

    call 调用的时候,this 就变了,但这里却没有被检查出来 this 指向的错误。

    如何让编译器能够检查出 this 指向的错误呢?

    可以在方法声明时指定 this 的类型:

    ts
    class Dong {
    +  name: string;
    +
    +  constructor() {
    +    this.name = 'dong';
    +  }
    +
    +  hello(this: Dong) {
    +    return "hello, I'm " + this.name;
    +  }
    +}

    这样,当 call/apply 调用的时候,就能检查出 this 指向的对象是否是对的:

    如果没有报错,说明没开启 strictBindCallApply 的编译选项,这个是控制是否按照原函数的类型来检查 bind、call、apply

    这里的 this 类型同样也可以通过模式匹配提取出来:

    ts
    type GetThisParameterType<T> = T extends (this: infer This, ...args: unknown[]) => unknown ? This : unknown;

    类型参数 T 是待处理的类型。

    用 T 匹配一个模式类型,提取 this 的类型到 infer 声明的局部变量 ThisType 中,其余的参数是任意类型,也就是 any,返回值也是任意类型。

    返回提取到的 ThisType。

    这样就能提取出 this 的类型:

    4.构造器类型

    构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

    同样,我们也可以通过模式匹配提取构造器的参数和返回值的类型:

    GetInstanceType

    构造器类型可以用 interface 声明,使用 new(): xx 的语法。

    比如:

    ts
    interface Person {
    +  name: string;
    +}
    +
    +interface PersonConstructor {
    +  new (name: string): Person;
    +}

    这里的 PersonConstructor 返回的是 Person 类型的实例对象,这个也可以通过模式匹配取出来。

    ts
    type GetInstanceType<ConstructorType extends new (...args: any) => any> = ConstructorType extends new (
    +  ...args: any
    +) => infer InstanceType
    +  ? InstanceType
    +  : any;

    类型参数 ConstructorType 是待处理的类型,通过 extends 约束为构造器类型。

    用 ConstructorType 匹配一个模式类型,提取返回的实例类型到 infer 声明的局部变量 InstanceType 里,返回 InstanceType。

    这样就能取出构造器对应的实例类型:

    ts
    interface PersonConstructor {
    +  new (name: string): Person;
    +}
    +
    +type GetInstanceTypeResult = GetInstanceType<PersonConstructor>;
    +// type GetInstanceTypeResult = Person

    GetConstructorParameters

    GetInstanceType 是提取构造器返回值类型,那同样也可以提取构造器的参数类型:

    ts
    type GetConstructorParameters<ConstructorType extends new (...args: any) => any> = ConstructorType extends new (
    +  ...args: infer ParametersType
    +) => any
    +  ? ParametersType
    +  : never;

    类型参数 ConstructorType 为待处理的类型,通过 extends 约束为构造器类型。

    用 ConstructorType 匹配一个模式类型,提取参数的部分到 infer 声明的局部变量 ParametersType 里,返回 ParametersType。

    这样就能提取出构造器对应的参数类型:

    ts
    interface PersonConstructor {
    +  new (name: string): Person;
    +}
    +
    +type GetConstructorParametersResult = GetConstructorParameters<PersonConstructor>;
    +// type GetConstructorParametersResult = [name:string]

    索引类型

    索引类型也同样可以用模式匹配提取某个索引的值的类型,这个用的也挺多的,比如 React 的 index.d.ts 里的 PropsWithRef 的高级类型,就是通过模式匹配提取了 ref 的值的类型:

    ts
    type PropsWithRef<P> = 'ref' extends keyof P
    +  ? P extends { ref?: infer R | undefined }
    +    ? string extends R
    +      ? PropsWithRef<P> & { ref?: Exclude<R, string> | undefined }
    +      : P
    +    : P
    +  : P;

    我们简化一下那个高级类型,提取 Props 里 ref 的类型:

    ts
    type GetPropsRef<Props> = 'ref' extends keyof Props
    +  ? Props extends { ref?: infer Value | undefined }
    +    ? value
    +    : never
    +  : never;

    类型参数 Props 为待处理的类型。

    通过 keyof Props 取出 Props 的所有索引构成的联合类型,判断下 ref 是否在其中,也就是 'ref' extends keyof Props。

    为什么要做这个判断,上面注释里写了:

    在 ts3.0 里面如果没有对应的索引,Obj[Key] 返回的是 {} 而不是 never,所以这样做下兼容处理。

    如果有 ref 这个索引的话,就通过 infer 提取 Value 的类型返回,否则返回 never。

    ts
    type GetPropsRefResult = GetPropsRef<{ ref: 1; name: 'str' }>;
    +// type GetPropsRefResult = 1

    当 ref 为 undefined 时:

    ts
    type GetPropsRefResult = GetPropsRef<{ ref: undefined; name: 'str' }>;
    +// type GetPropsRefResult = undefined

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/typescript/reconstruction.html b/src/article/typescript/reconstruction.html new file mode 100644 index 0000000000..e70b240dd2 --- /dev/null +++ b/src/article/typescript/reconstruction.html @@ -0,0 +1,96 @@ + + + + + + 重新构造做变换 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    重新构造做变换

    类型编程主要的目的就是对类型做各种转换,那么如何对类型做修改呢?

    TypeScript 类型系统支持 3 种可以声明任意类型的变量:type、infer、类型参数。

    type 叫做类型别名,其实就是声明一个变量存储某个类型:

    ts
    type ttt = Promise<number>;

    infer 用于类型的提取,然后存到一个变量里,相当于局部变量:

    ts
    type GetValueType<P> = P extends Promise<infer Value> ? Value : never;

    类型参数用于接受具体的类型,在类型运算中也相当于局部变量:

    ts
    type isTwo<T> = T extends 2 ? true : false;

    但是,严格来说这三种也都不叫变量,因为它们不能被重新赋值。

    TypeScript 设计可以做类型编程的类型系统的目的就是为了产生各种复杂的类型,那不能修改怎么产生新类型呢?

    答案是重新构造。

    这就涉及到了第二个类型体操套路:重新构造做变换。

    重新构造

    TypeScript 的 type、infer、类型参数声明的变量都不能修改,想对类型做各种变换产生新的类型就需要重新构造。

    数组、字符串、函数等类型的重新构造比较简单。

    索引类型,也就是多个元素的聚合类型的重新构造复杂一些,涉及到了映射类型的语法。

    我们先从简单的开始:

    数组类型的重新构造

    Push

    有这样一个元组类型:

    ts
    type tuple = [1, 2, 3];

    我想给这个元组类型再添加一些类型,怎么做呢?

    TypeScript 类型变量不支持修改,我们可以构造一个新的元组类型:

    ts
    type Push<Arr extends unknown[], Ele> = [...Arr, Ele];

    类型参数 Arr 是要修改的数组/元组类型,元素的类型任意,也就是 unknown。

    类型参数 Ele 是添加的元素的类型。

    返回的是用 Arr 已有的元素加上 Ele 构造的新的元组类型。

    ts
    type PushResult = Push<[1, 2, 3], 4>;
    +// type PushResult = [1,2,3,4]

    这就是数组/元组的重新构造。

    数组和元组的区别:数组类型是指任意多个同一类型的元素构成的,比如 number[]Array<number>,而元组则是数量固定,类型可以不同的元素构成的,比如 [1, true, 'name']

    Unshift

    可以在后面添加,同样也可以在前面添加:

    ts
    type Unshift<Arr extends unknown[], Ele> = [Ele, ...Arr];

    Zip

    有这样两个元组:

    ts
    type tuple1 = [1, 2];
    +type tuple2 = ['name', 'value'];

    我们想把它们合并成这样的元组:

    ts
    type tuple = [[1, 'name'], [2, 'value']];

    思路很容易想到,提取元组中的两个元素,构造成新的元组:

    ts
    type Zip<One extends [unknown, unknown], Other extends [unknown, unknown]> = One extends [
    +  infer OneFirst,
    +  infer OneSecond,
    +]
    +  ? Other extends [infer OtherFirst, infer OtherSecond]
    +    ? [[OneFirst, OtherFirst], [OneSecond, OtherSecond]]
    +    : []
    +  : [];

    两个类型参数 One、Other 是两个元组,类型是 [unknown, unknown],代表 2 个任意类型的元素构成的元组。

    通过 infer 分别提取 One 和 Other 的元素到 infer 声明的局部变量 OneFirst、OneSecond、OtherFirst、OtherSecond 里。

    用提取的元素构造成新的元组返回即可:

    ts
    type ZipResult = Zip<[1, 2], ['name', 'value']>;
    +// type ZipResult = [[1, 'name'], [2, 'value']];

    但是这样只能合并两个元素的元组,如果是任意个呢?

    那就得用递归了:

    ts
    type Zip<One extends unknown[], Other extends unknown[]> = One extends [infer OneFirst, ...infer OneRest]
    +  ? Other extends [infer OtherFirst, ...infer OtherRest]
    +    ? [[OneFirst, OtherFirst], ...Zip<OneRest, OtherRest>]
    +    : []
    +  : [];

    类型参数 One、Other 声明为 unknown[],也就是元素个数任意,类型任意的数组。

    每次提取 One 和 Other 的第一个元素 OneFirst、OtherFirst,剩余的放到 OneRest、OtherRest 里。

    用 OneFirst、OtherFirst 构造成新的元组的一个元素,剩余元素继续递归处理 OneRest、OtherRest。

    这样,就能处理任意个数元组的合并:

    ts
    type ZipResult = Zip<[1, 2, 3, 4, 5], ['name', 'value', 'three', 'four', 'five']>;
    +// type ZipResult = [[1, 'name'], [2, 'value'], [3, 'three'], [4, 'four'], [5, 'five']];

    了解了数组类型的重新构造,我们再来看下字符串类型的:

    字符串类型的重新构造

    CapitalizeStr

    我们想把一个字符串字面量类型的 'guang' 转为首字母大写的 'Guang'。

    需要用到字符串类型的提取和重新构造:

    ts
    type CapitalizeStr<Str extends string> = Str extends `${infer First}${infer Rest}` ? `${Uppercase<First>}${Rest}` : Str;

    我们声明了类型参数 Str 是要处理的字符串类型,通过 extends 约束为 string。

    通过 infer 提取出首个字符到局部变量 First,提取后面的字符到局部变量 Rest。

    然后使用 TypeScript 提供的内置高级类型 Uppercase 把首字母转为大写,加上 Rest,构造成新的字符串类型返回。

    这就是字符串类型的重新构造:从已有的字符串类型中提取出一些部分字符串,经过一系列变换,构造成新的字符串类型。

    CamelCase

    我们再来实现 dong_dong_dong 到 dongDongDong 的变换。

    同样是提取和重新构造:

    ts
    type CamelCase<Str extends string> = Str extends `${infer Left}_${infer Right}${infer Rest}`
    +  ? `${Left}${Uppercase<Right>}${CamelCase<Rest>}`
    +  : Str;

    类型参数 Str 是待处理的字符串类型,约束为 string。

    提取 _ 之前和之后的两个字符到 infer 声明的局部变量 Left 和 Right,剩下的字符放到 Rest 里。

    然后把右边的字符 Right 大写,和 Left 构造成新的字符串,剩余的字符 Rest 要继续递归的处理。

    这样就完成了从下划线到驼峰形式的转换:

    DropSubStr

    可以修改自然也可以删除,我们再来做一个删除一段字符串的案例:删除字符串中的某个子串

    ts
    type DropSubStr<Str extends string, SubStr extends string> = Str extends `${infer Prefix}${SubStr}${infer Suffix}`
    +  ? DropSubStr<`${Prefix}${Suffix}`, SubStr>
    +  : Str;

    类型参数 Str 是待处理的字符串,SubStr 是要删除的字符串,都通过 extends 约束为 string 类型。

    通过模式匹配提取 SubStr 之前和之后的字符串到 infer 声明的局部变量 Prefix、Suffix 中。

    如果不匹配就直接返回 Str。

    如果匹配,那就用 Prefix、Suffix 构造成新的字符串,然后继续递归删除 SubStr。直到不再匹配,也就是没有 SubStr 了。

    字符串类型的重新构造之后,我们再来看下函数类型的重新构造:

    函数类型的重新构造

    AppendArgument

    之前我们分别实现了参数和返回值的提取,那么重新构造就是用这些提取出的类型做下修改,构造一个新的类型即可。

    比如在已有的函数类型上添加一个参数:

    ts
    type AppendArgument<Func extends Function, Arg> = Func extends (...args: infer Args) => infer ReturnType
    +  ? (...args: [...Args, Arg]) => ReturnType
    +  : never;

    类型参数 Func 是待处理的函数类型,通过 extends 约束为 Function,Arg 是要添加的参数类型。

    通过模式匹配提取参数到 infer 声明的局部变量 Args 中,提取返回值到局部变量 ReturnType 中。

    用 Args 数组添加 Arg 构造成新的参数类型,结合 ReturnType 构造成新的函数类型返回。

    这样就完成了函数类型的修改:

    最后,我们再来看下索引类型的重新构造

    索引类型的重新构造

    索引类型是聚合多个元素的类型,class、对象等都是索引类型,比如这就是一个索引类型:

    ts
    type obj = {
    +  name: string;
    +  age: number;
    +  gender: boolean;
    +};

    索引类型可以添加修饰符 readonly(只读)、?(可选):

    ts
    type obj = {
    +  readonly name: string;
    +  age?: number;
    +  gender: boolean;
    +};

    对它的修改和构造新类型涉及到了映射类型的语法:

    ts
    type Mapping<Obj extends object> = {
    +  [Key in keyof Obj]: Obj[Key];
    +};

    Mapping

    映射的过程中可以对 value 做下修改,比如:

    ts
    type Mapping<Obj extends object> = {
    +  [Key in keyof Obj]: [Obj[Key], Obj[Key], Obj[Key]];
    +};

    类型参数 Obj 是待处理的索引类型,通过 extends 约束为 object。

    用 keyof 取出 Obj 的索引,作为新的索引类型的索引,也就是 Key in keyof Obj。

    值的类型可以做变换,这里我们用之前索引类型的值 Obj[Key] 构造成了三个元素的元组类型 [Obj[Key], Obj[Key], Obj[Key]]:

    UppercaseKey

    除了可以对 Value 做修改,也可以对 Key 做修改,使用 as,这叫做重映射:

    比如把索引类型的 Key 变为大写。

    ts
    type UppercaseKey<Obj extends object> = {
    +  [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key];
    +};

    类型参数 Obj 是待处理的索引类型,通过 extends 约束为 object。

    新的索引类型的索引为 Obj 中的索引,也就是 Key in keyof Obj,但要做一些变换,也就是 as 之后的。

    通过 Uppercase 把索引 Key 转为大写,因为索引可能为 string、number、symbol 类型,而这里只能接受 string 类型,所以要 & string,也就是取索引中 string 的部分。

    value 保持不变,也就是之前的索引 Key 对应的值的类型 Obj[Key]。

    这样构造出的新的索引类型,就把原来索引类型的索引转为了大写:

    Record

    TypeScript 提供了内置的高级类型 Record 来创建索引类型:

    ts
    type Record<K extends string | number | symbol, T> = { [P in K]: T };

    指定索引和值的类型分别为 K 和 T,就可以创建一个对应的索引类型。

    上面的索引类型的约束我们用的 object,其实更语义化一点我推荐用 Record<string, any>:

    ts
    type UppercaseKey<Obj extends Record<string, any>> = {
    +  [Key in keyof Obj as Uppercase<Key & string>]: Obj[Key];
    +};

    也就是约束类型参数 Obj 为 key 为 string,值为任意类型的索引类型。

    ToReadonly

    索引类型的索引可以添加 readonly 的修饰符,代表只读。

    那我们就可以实现给索引类型添加 readonly 修饰的高级类型:

    ts
    type ToReadonly<T> = {
    +  readonly [Key in keyof T]: T[Key];
    +};

    通过映射类型构造了新的索引类型,给索引加上了 readonly 的修饰,其余的保持不变,索引依然为原来的索引 Key in keyof T,值依然为原来的值 T[Key]。

    ToPartial

    同理,索引类型还可以添加可选修饰符:

    ts
    type ToPartial<T> = {
    +  [Key in keyof T]?: T[Key];
    +};

    给索引类型 T 的索引添加了 ? 可选修饰符,其余保持不变。

    ToMutable

    可以添加 readonly 修饰,当然也可以去掉:

    ts
    type ToMutable<T> = {
    +  -readonly [Key in keyof T]: T[Key];
    +};

    给索引类型 T 的每个索引去掉 readonly 的修饰,其余保持不变。

    ToRequired

    同理,也可以去掉可选修饰符:

    ts
    type ToRequired<T> = {
    +  [Key in keyof T]-?: T[Key];
    +};

    给索引类型 T 的索引去掉 ? 的修饰,其余保持不变。

    FilterByValueType

    可以在构造新索引类型的时候根据值的类型做下过滤:

    ts
    type FilterByValueType<Obj extends Record<string, any>, ValueType> = {
    +  [Key in keyof Obj as Obj[Key] extends ValueType ? Key : never]: Obj[Key];
    +};

    类型参数 Obj 为要处理的索引类型,通过 extends 约束为索引为 string,值为任意类型的索引类型 Record<string, any>。

    类型参数 ValueType 为要过滤出的值的类型。

    构造新的索引类型,索引为 Obj 的索引,也就是 Key in keyof Obj,但要做一些变换,也就是 as 之后的部分。

    如果原来索引的值 Obj[Key] 是 ValueType 类型,索引依然为之前的索引 Key,否则索引设置为 never,never 的索引会在生成新的索引类型时被去掉。

    值保持不变,依然为原来索引的值,也就是 Obj[Key]。

    这样就达到了过滤索引类型的索引,产生新的索引类型的目的:

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/typescript/recursion.html b/src/article/typescript/recursion.html new file mode 100644 index 0000000000..0952c1650f --- /dev/null +++ b/src/article/typescript/recursion.html @@ -0,0 +1,113 @@ + + + + + + 递归复用 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    递归复用

    递归是把问题分解为一系列相似的小问题,通过函数不断调用自身来解决这一个个小问题,直到满足结束条件,就完成了问题的求解。

    TypeScript 的高级类型支持类型参数,可以做各种类型运算逻辑,返回新的类型,和函数调用是对应的,自然也支持递归。

    TypeScript 类型系统不支持循环,但支持递归。当处理数量(个数、长度、层数)不固定的类型的时候,可以只处理一个类型,然后递归的调用自身处理下一个类型,直到结束条件也就是所有的类型都处理完了,就完成了不确定数量的类型编程,达到循环的效果。

    既然提到了数组、字符串、对象等类型,那么我们就来看一下这些类型的递归案例吧。

    Promise 的递归复用

    DeepPromiseValueType

    先用 Promise 热热身,实现一个提取不确定层数的 Promise 中的 value 类型的高级类型。

    ts
    type ttt = Promise<Promise<Promise<Record<string, any>>>>;

    这里是 3 层 Promise,value 类型是索引类型。

    数量不确定,一涉及到这个就要想到用递归来做,每次只处理一层的提取,然后剩下的到下次递归做,直到结束条件。

    所以高级类型是这样的:

    ts
    type DeepPromiseValueType<P extends Promise<unknown>> =
    +  P extends Promise<infer ValueType>
    +    ? ValueType extends Promise<unknown>
    +      ? DeepPromiseValueType<ValueType>
    +      : ValueType
    +    : never;

    类型参数 P 是待处理的 Promise,通过 extends 约束为 Promise 类型,value 类型不确定,设为 unknown。

    每次只处理一个类型的提取,也就是通过模式匹配提取出 value 的类型到 infer 声明的局部变量 ValueType 中。

    然后判断如果 ValueType 依然是 Promise 类型,就递归处理。

    结束条件就是 ValueType 不为 Promise 类型,那就处理完了所有的层数,返回这时的 ValueType。

    这样,我们就提取到了最里层的 Promise 的 value 类型,也就是索引类型:

    其实这个类型的实现可以进一步的简化:

    ts
    type DeepPromiseValueType2<T> = T extends Promise<infer ValueType> ? DeepPromiseValueType2<ValueType> : T;

    不再约束类型参数必须是 Promise,这样就可以少一层判断。

    接下来再看下数组类型的递归复用:

    数组类型的递归

    ReverseArr

    有这样一个元组类型:

    ts
    type arr = [1, 2, 3, 4, 5];

    我们把它反过来,也就是变成:

    ts
    type arr = [5, 4, 3, 2, 1];

    这个学完了提取和构造很容易写出来:

    ts
    type ReverseArr<Arr extends unknown[]> = Arr extends [infer One, infer Two, infer Three, infer Four, infer Five]
    +  ? [Five, Four, Three, Two, One]
    +  : never;

    但如果数组长度不确定呢?

    数量不确定,条件反射的就要想到递归。

    我们每次只处理一个类型,剩下的递归做,直到满足结束条件。

    ts
    type ReverseArr<Arr extends unknown[]> = Arr extends [infer First, ...infer Rest] ? [...ReverseArr<Rest>, First] : Arr;

    类型参数 Arr 为待处理的数组类型,元素类型不确定,也就是 unknown。

    每次只处理一个元素的提取,放到 infer 声明的局部变量 First 里,剩下的放到 Rest 里。

    用 First 作为最后一个元素构造新数组,其余元素递归的取。

    结束条件就是取完所有的元素,也就是不再满足模式匹配的条件,这时候就返回 Arr。

    Includes

    既然递归可以做循环用,那么像查找元素这种自然也就可以实现。

    比如查找 [1, 2, 3, 4, 5] 中是否存在 4,是就返回 true,否则返回 false。

    从长度不固定的数组中查找某个元素,数量不确定,这时候就应该想到递归。

    ts
    type Includes<Arr extends unknown[], FindItem> = Arr extends [infer First, ...infer Rest]
    +  ? IsEqual<First, FindItem> extends true
    +    ? true
    +    : Includes<Rest, FindItem>
    +  : false;
    +
    +type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

    类型参数 Arr 是待查找的数组类型,元素类型任意,也就是 unknown。FindItem 待查找的元素类型。

    每次提取一个元素到 infer 声明的局部变量 First 中,剩余的放到局部变量 Rest。

    判断 First 是否是要查找的元素,也就是和 FindItem 相等,是的话就返回 true,否则继续递归判断下一个元素。

    直到结束条件也就是提取不出下一个元素,这时返回 false。

    相等的判断就是 A 是 B 的子类型并且 B 也是 A 的子类型,。

    这样就完成了不确定长度的数组中的元素查找,用递归实现了循环。

    RemoveItem

    可以查找自然就可以删除,只需要改下返回结果,构造一个新的数组返回。

    ts
    type RemoveItem<Arr extends unknown[], Item, Result extends unknown[] = []> = Arr extends [infer First, ...infer Rest]
    +  ? IsEqual<First, Item> extends true
    +    ? RemoveItem<Rest, Item, Result>
    +    : RemoveItem<Rest, Item, [...Result, First]>
    +  : Result;
    +
    +type IsEqual<A, B> = (A extends B ? true : false) & (B extends A ? true : false);

    类型参数 Arr 是待处理的数组,元素类型任意,也就是 unknown[]。类型参数 Item 为待查找的元素类型。类型参数 Result 是构造出的新数组,默认值是 []。

    通过模式匹配提取数组中的一个元素的类型,如果是 Item 类型的话就删除,也就是不放入构造的新数组,直接返回之前的 Result。

    否则放入构造的新数组,也就是再构造一个新的数组 [...Result, First]。

    直到模式匹配不再满足,也就是处理完了所有的元素,返回这时候的 Result。

    这样我们就完成了不确定元素个数的数组的某个元素的删除:

    BuildArray

    我们学过数组类型的构造,如果构造的数组类型元素个数不确定,也需要递归。

    比如传入 5 和元素类型,构造一个长度为 5 的该元素类型构成的数组。

    ts
    type BuildArray<Length extends number, Ele = unknown, Arr extends unknown[] = []> = Arr['length'] extends Length
    +  ? Arr
    +  : BuildArray<Length, Ele, [...Arr, Ele]>;

    类型参数 Length 为数组长度,约束为 number。类型参数 Ele 为元素类型,默认值为 unknown。类型参数 Arr 为构造出的数组,默认值是 []。

    每次判断下 Arr 的长度是否到了 Length,是的话就返回 Arr,否则在 Arr 上加一个元素,然后递归构造。

    学完了数组类型的递归,我们再来看下字符串类型。

    字符串类型的递归

    ReplaceAll

    学模式匹配的时候,我们实现过一个 Replace 的高级类型:

    ts
    type ReplaceStr<
    +  Str extends string,
    +  From extends string,
    +  To extends string,
    +> = Str extends `${infer Prefix}${From}${infer Suffix}` ? `${Prefix}${To}${Suffix}` : Str;

    它能把一个字符串中的某个字符替换成另一个:

    但是如果有多个这样的字符就处理不了了。

    如果不确定有多少个 From 字符,怎么处理呢?

    在类型体操里,遇到数量不确定的问题,就要条件反射的想到递归。

    每次递归只处理一个类型,这部分我们已经实现了,那么加上递归的调用就可以。

    ts
    type ReplaceAll<
    +  Str extends string,
    +  From extends string,
    +  To extends string,
    +> = Str extends `${infer Left}${From}${infer Right}` ? `${Left}${To}${ReplaceAll<Right, From, To>}` : Str;

    类型参数 Str 是待处理的字符串类型,From 是待替换的字符,To 是替换到的字符。

    通过模式匹配提取 From 左右的字符串到 infer 声明的局部变量 Left 和 Right 里。

    用 Left 和 To 构造新的字符串,剩余的 Right 部分继续递归的替换。

    结束条件是不再满足模式匹配,也就是没有要替换的元素,这时就直接返回字符串 Str。

    这样就实现了任意数量的字符串替换:

    StringToUnion

    我们想把字符串字面量类型的每个字符都提取出来组成联合类型,也就是把 'dong' 转为 'd' | 'o' | 'n' | 'g'。

    怎么做呢?

    很明显也是提取和构造:

    ts
    type StringToUnion<Str extends string> = Str extends `${infer One}${infer Two}${infer Three}${infer Four}`
    +  ? One | Two | Three | Four
    +  : never;

    但如果字符串长度不确定呢?

    数量不确定,在类型体操中就要条件反射的想到递归。

    ts
    type StringToUnion<Str extends string> = Str extends `${infer First}${infer Rest}`
    +  ? First | StringToUnion<Rest>
    +  : never;

    类型参数 Str 为待处理的字符串类型,通过 extends 约束为 string。

    通过模式匹配提取第一个字符到 infer 声明的局部变量 First,其余的字符放到局部变量 Rest。

    用 First 构造联合类型,剩余的元素递归的取。

    这样就完成了不确定长度的字符串的提取和联合类型的构造:

    ReverseStr

    我们实现了数组的反转,自然也可以实现字符串类型的反转。

    同样是递归提取和构造。

    ts
    type ReverseStr<Str extends string, Result extends string = ''> = Str extends `${infer First}${infer Rest}`
    +  ? ReverseStr<Rest, `${First}${Result}`>
    +  : Result;

    类型参数 Str 为待处理的字符串。类型参数 Result 为构造出的字符,默认值是空串。

    通过模式匹配提取第一个字符到 infer 声明的局部变量 First,其余字符放到 Rest。

    用 First 和之前的 Result 构造成新的字符串,把 First 放到前面,因为递归是从左到右处理,那么不断往前插就是把右边的放到了左边,完成了反转的效果。

    直到模式匹配不满足,就处理完了所有的字符。

    这样就完成了字符串的反转:

    对象类型的递归

    DeepReadonly

    对象类型的递归,也可以叫做索引类型的递归。

    我们之前实现了索引类型的映射,给索引加上了 readonly 的修饰:

    ts
    type ToReadonly<T> = {
    +  readonly [Key in keyof T]: T[Key];
    +};

    如果这个索引类型层数不确定呢?

    比如这样:

    ts
    type obj = {
    +  a: {
    +    b: {
    +      c: {
    +        f: () => 'dong';
    +        d: {
    +          e: {
    +            guang: string;
    +          };
    +        };
    +      };
    +    };
    +  };
    +};

    数量(层数)不确定,类型体操中应该自然的想到递归。

    我们在之前的映射上加入递归的逻辑:

    ts
    type DeepReadonly<Obj extends Record<string, any>> = {
    +  readonly [Key in keyof Obj]: Obj[Key] extends object
    +    ? Obj[Key] extends Function
    +      ? Obj[Key]
    +      : DeepReadonly<Obj[Key]>
    +    : Obj[Key];
    +};

    类型参数 Obj 是待处理的索引类型,约束为 Record<string, any>,也就是索引为 string,值为任意类型的索引类型。

    索引映射自之前的索引,也就是 Key in keyof Obj,只不过加上了 readonly 的修饰。

    值要做下判断,如果是 object 类型并且还是 Function,那么就直接取之前的值 Obj[Key]。

    如果是 object 类型但不是 Function,那就是说也是一个索引类型,就递归处理 DeepReadonly<Obj[Key]>。

    否则,值不是 object 就直接返回之前的值 Obj[Key]。

    这样就完成了任意层数的索引类型的添加 readonly 修饰:

    我们取处理以后的索引 a 的值看一下,发现 b 已经加上了 readonly 修饰。

    测试一下:

    为啥这里没有计算呀?

    因为 ts 的类型只有被用到的时候才会做计算。

    所以可以在前面加上一段 Obj extends never ? never 或者 Obj extends any 等,从而触发计算:

    ts
    type DeepReadonly<Obj extends Record<string, any>> = Obj extends any
    +  ? {
    +      readonly [Key in keyof Obj]: Obj[Key] extends object
    +        ? Obj[Key] extends Function
    +          ? Obj[Key]
    +          : DeepReadonly<Obj[Key]>
    +        : Obj[Key];
    +    }
    +  : never;

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/article/typescript/unionType.html b/src/article/typescript/unionType.html new file mode 100644 index 0000000000..9ab839c787 --- /dev/null +++ b/src/article/typescript/unionType.html @@ -0,0 +1,69 @@ + + + + + + 分布式条件类型 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    分布式条件类型

    当类型参数为联合类型,并且在条件类型左边直接引用该类型参数的时候,TypeScript 会把每一个元素单独传入来做类型运算,最后再合并成联合类型,这种语法叫做分布式条件类型。

    比如这样一个联合类型:

    ts
    type Union = 'a' | 'b' | 'c';

    我们想把其中的 a 大写,就可以这样写:

    ts
    type UppercaseA<Item extends string> = Item extends 'a' ? Uppercase<Item> : Item;
    ts
    type result = UppercaseA<Union>;
    +// type result = 'A' | 'b' | 'c';

    可以看到,我们类型参数 Item 约束为 string,条件类型的判断中也是判断是否是 a,但传入的是联合类型。

    这就是 TypeScript 对联合类型在条件类型中使用时的特殊处理:会把联合类型的每一个元素单独传入做类型计算,最后合并。

    这和联合类型遇到字符串时的处理一样:

    这样确实是简化了类型编程逻辑的,不需要递归提取每个元素再处理。

    TypeScript 之所以这样处理联合类型也很容易理解,因为联合类型的每个元素都是互不相关的,不像数组、索引、字符串那样元素之间是有关系的。所以设计成了每一个单独处理,最后合并。

    知道了 TypeScript 怎么处理的联合类型,趁热打铁来练习一下:

    CamelcaseUnion

    Camelcase 我们实现过,就是提取字符串中的字符,首字母大写以后重新构造一个新的。

    ts
    type Camelcase<Str extends string> = Str extends `${infer Left}_${infer Right}${infer Rest}`
    +  ? `${Left}${Uppercase<Right>}${Camelcase<Rest>}`
    +  : Str;

    提取 _ 左右的字符,把右边字符大写之后构造成新的字符串,余下的字符串递归处理。

    ts
    type CamelcaseResult = Camelcase<'aa_aa_aa'>;
    +// type CamelcaseResult = 'aaAaAa'

    如果是对字符串数组做 Camelcase,那就要递归处理每一个元素:

    ts
    type CamelcaseArr<Arr extends unknown[]> = Arr extends [infer Item, ...infer RestArr]
    +  ? [Camelcase<Item & string>, ...CamelcaseArr<RestArr>]
    +  : [];

    类型参数 Arr 为待处理数组。

    递归提取每一个元素做 Camelcase,因为 Camelcase 要求传入 string,这里要 & string 来变成 string 类型。

    那如果是联合类型呢?

    联合类型不需要递归提取每个元素,TypeScript 内部会把每一个元素传入单独做计算,之后把每个元素的计算结果合并成联合类型。

    ts
    type CamelcaseUnion<Item extends string> = Item extends `${infer Left}_${infer Right}${infer Rest}`
    +  ? `${Left}${Uppercase<Right>}${CamelcaseUnion<Rest>}`
    +  : Item;

    这不和单个字符串的处理没区别么?

    没错,对联合类型的处理和对单个类型的处理没什么区别,TypeScript 会把每个单独的类型拆开传入。不需要像数组类型那样需要递归提取每个元素做处理。

    确实简化了很多,好像都是优点?

    也不全是,其实这样处理也增加了一些认知成本,不信我们再来看个例子:

    IsUnion

    判断联合类型我们会这样写:

    ts
    type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

    当传入联合类型时,会返回 true:

    ts
    type IsUnionResult = IsUnion<'a' | 'b' 'c'>
    +// type IsUnionResult = true

    当传入其他类型时,会返回 false:

    ts
    type IsUnionResult = IsUnion<['a' | 'b' 'c']>
    +// type IsUnionResult = false

    这就是分布式条件类型带来的认知成本。

    我们先来看这样一个类型:

    ts
    type TestUnion<A, B = A> = A extends A ? { a: A; b: B } : never;
    +
    +type TestUnionResult = TestUnion<'a' | 'b' | 'c'>;

    传入联合类型 'a' | 'b' | 'c' 的时候,结果是这样的:

    A 和 B 都是同一个联合类型,为啥值还不一样呢?

    因为条件类型中如果左边的类型是联合类型,会把每个元素单独传入做计算,而右边不会。

    所以 A 是 'a' 的时候,B 是 'a' | 'b' | 'c',A 是 'b' 的时候,B 是 'a' | 'b' | 'c'。。。

    那么利用这个特点就可以实现 Union 类型的判断:

    ts
    type IsUnion<A, B = A> = A extends A ? ([B] extends [A] ? false : true) : never;

    类型参数 A、B 是待判断的联合类型,B 默认值为 A,也就是同一个类型。

    A extends A 这段看似没啥意义,主要是为了触发分布式条件类型,让 A 的每个类型单独传入。

    [B] extends [A] 这样不直接写 B 就可以避免触发分布式条件类型,那么 B 就是整个联合类型。

    B 是联合类型整体,而 A 是单个类型,自然不成立,而其它类型没有这种特殊处理,A 和 B 都是同一个,怎么判断都成立。

    利用这个特点就可以判断出是否是联合类型。

    其中有两个点比较困惑,我们重点记一下:

    当 A 是联合类型时:

    A extends A 这种写法是为了触发分布式条件类型,让每个类型单独传入处理的,没别的意义。

    A extends A 和 [A] extends [A] 是不同的处理,前者是单个类型和整个类型做判断,后者两边都是整个联合类型,因为只有 extends 左边直接是类型参数才会触发分布式条件类型。

    理解了这两点,分布式条件类型就算掌握了。

    BEM

    bem 是 css 命名规范,用 block__element--modifier 的形式来描述某个区块下面的某个元素的某个状态的样式。

    那么我们可以写这样一个高级类型,传入 block、element、modifier,返回构造出的 class 名:

    这样使用:

    ts
    type bemResult = BEM<'guang', ['aaa', 'bbb'], ['warning', 'success']>;

    它的实现就是三部分的合并,但传入的是数组,要递归遍历取出每一个元素来和其他部分组合,这样太麻烦了。

    而如果是联合类型就不用递归遍历了,因为联合类型遇到字符串也是会单独每个元素单独传入做处理。

    数组转联合类型可以这样写:

    ts
    type union = ['aaa', 'bbb'][number];
    +// type union = 'aaa' | 'bbb'

    那么 BEM 就可以这样实现:

    ts
    type BEM<
    +  Block extends string,
    +  Element extends string[],
    +  Modifiers extends string[],
    +> = `${Block}__${Element[number]}--${Modifiers[number]}`;

    类型参数 Block、Element、Modifiers 分别是 bem 规范的三部分,其中 Element 和 Modifiers 都可能多个,约束为 string[]。

    构造一个字符串类型,其中 Element 和 Modifiers 通过索引访问来变为联合类型。

    字符串类型中遇到联合类型的时候,会每个元素单独传入计算,也就是这样的效果:

    ts
    type RemResult = BEM<'a', ['b', 'c'], ['d', 'e']>;
    +// type RemResult = 'a__b--d' | 'a__b--e' | 'a__c--d' | 'a__b--e'

    可以看到,用好了联合类型,确实能简化类型编程逻辑。

    AllCombinations

    我们再来实现一个全组合的高级类型,也是联合类型相关的:

    希望传入 'A' | 'B' 的时候,能够返回所有的组合: 'A' | 'B' | 'BA' | 'AB'。

    这种全组合问题的实现思路就是两两组合,组合出的字符串再和其他字符串两两组和:

    比如 'A' | 'B' | 'c',就是 A 和 B、C 组合,B 和 A、C 组合,C 和 A、B 组合。然后组合出来的字符串再和其他字符串组合。

    任何两个类型的组合有四种:A、B、AB、BA

    ts
    type Combination<A extends string, B extends string> = A | B | `${A}${B}` | `${B}${A}`;

    然后构造出来的字符串再和其他字符串组合。

    所以全组合的高级类型就是这样:

    ts
    type AllCombinations<A extends string, B extends string = A> = A extends A
    +  ? Combination<A, AllCombinations<Exclude<B, A>>>
    +  : never;

    类型参数 A、B 是待组合的两个联合类型,B 默认是 A 也就是同一个。

    A extends A 的意义就是让联合类型每个类型单独传入做处理,上面我们刚学会。

    A 的处理就是 A 和 B 中去掉 A 以后的所有类型组合,也就是 Combination<A, B 去掉 A 以后的所有组合>。

    而 B 去掉 A 以后的所有组合就是 AllCombinations<Exclude<B, A>>,所以全组合就是 Combination<A, AllCombinations<Exclude<B, A>>>。

    总结

    联合类型中的每个类型都是相互独立的,TypeScript 对它做了特殊处理,也就是遇到字符串类型、条件类型的时候会把每个类型单独传入做计算,最后把每个类型的计算结果合并成联合类型。

    条件类型左边是联合类型的时候就会触法这种处理,叫做分布式条件类型。

    有两点特别要注意:

    • A extends A 不是没意义,意义是取出联合类型中的单个类型放入 A

    • A extends A 才是分布式条件类型, [A] extends [A] 就不是了,只有左边是单独的类型参数才可以。

    我们后面做了一些案例,发现联合类型的这种 distributive 的特性确实能简化类型编程,但是也增加了认知成本,不过这也是不可避免的事。

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/button/index.html b/src/ranui/button/index.html new file mode 100644 index 0000000000..93f187e980 --- /dev/null +++ b/src/ranui/button/index.html @@ -0,0 +1,57 @@ + + + + + + Button | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Button

    The button is used to start an instant action.

    Code demo

    Button
    xml
     <r-button >Button</r-button>

    Attribute

    type

    There are four types of buttons

    Primary button
    Warning button
    Text button
    Default button
    xml
     <r-button type="primary">Primary button</r-button>
    + <r-button type="warning">Warning button</r-button>
    + <r-button type="text">Text button</r-button>
    + <r-button >Default button</r-button>

    disabled

    Adding the disabled attribute makes the button unavailable and changes the button style.

    Primary button
    Warning button
    Text button
    Default button
    xml
     <r-button type="primary" disabled>Primary butto</r-button>
    + <r-button type="warning" disabled>Warning button</r-button>
    + <r-button type="text" disabled>Text button</r-button>
    + <r-button disabled>Default button</r-button>

    icon

    When you need to embed an Icon inside a Button, you can set the icon property or use the Icon component directly inside a Button.

    If you want to control the specific position of the Icon, you can only use the Icon component directly, not the icon property.

    Default button
    Primary button
    xml
    <r-button type="default" icon="user">Default button</r-button>
    +<r-button type="primary" icon="home">Primary button</r-button>

    特效 effect

    If you want a pure Button, you can add effect = false to block the water ripple effect when clicked

    Default buttonPrimary button
    xml
    <r-button type="default" icon="user">Default button</r-button>
    +<r-button type="primary" icon="home">Primary button</r-button>

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/checkbox/index.html b/src/ranui/checkbox/index.html new file mode 100644 index 0000000000..66c77f66f9 --- /dev/null +++ b/src/ranui/checkbox/index.html @@ -0,0 +1,52 @@ + + + + + + CheckBox | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    CheckBox

    Code demo

    xml
     <r-checkbox ></r-checkbox>

    Attribute

    checked

    xml
     <r-checkbox checked="true"></r-checkbox>
    + <r-checkbox checked="false"></r-checkbox>

    disabled

    xml
     <r-checkbox checked="true" disabled></r-checkbox>
    + <r-checkbox checked="false" disabled></r-checkbox>

    event

    Common callback events.

    onchange

    xml
     <r-checkbox onchange="console.log(this.checked)"></r-checkbox>
    + <r-checkbox onchange="console.log(this.checked)"></r-checkbox>

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/icon/index.html b/src/ranui/icon/index.html new file mode 100644 index 0000000000..2888428949 --- /dev/null +++ b/src/ranui/icon/index.html @@ -0,0 +1,60 @@ + + + + + + Icon | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Icon

    Semantic vector graphics

    Code demo

    xml
     <r-icon name="lock"  ></r-icon>
    + <r-icon name="eye"  ></r-icon>
    + <r-icon name="user"  ></r-icon>

    Attribute

    name

    Select a different icon based on the name

    html
    <r-icon name="lock"></r-icon>
    +<r-icon name="eye"></r-icon>
    +<r-icon name="user"></r-icon>

    size

    html
    <r-icon name="lock" size="30"></r-icon>
    +<r-icon name="lock" size="50"></r-icon>
    +<r-icon name="lock" size="70"></r-icon>

    color

    html
    <r-icon name="lock" size="50" color="red"></r-icon>
    +<r-icon name="lock" size="50" color="#1E90FF"></r-icon>
    +<r-icon name="lock" size="50" color="#F44336"></r-icon>
    +<r-icon name="lock" size="50" color="#3F51B5"></r-icon>

    spin

    Set spin to turn on the rotation, and pass in a number to control the rotation speed. The smaller the number, the faster the rotation

    html
    <r-icon name="loading" size="50" color="#1E90FF" spin="0.7"></r-icon>
    +<r-icon name="loading" size="50" color="#1E90FF" spin></r-icon>
    +<r-icon name="loading" size="50" color="#1E90FF" spin="5"></r-icon>

    Icon list

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/image/index.html b/src/ranui/image/index.html new file mode 100644 index 0000000000..0a0e16d06f --- /dev/null +++ b/src/ranui/image/index.html @@ -0,0 +1,49 @@ + + + + + + Image | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Image

    Code demo

    xml
     <r-img src="" fallback=""></r-img>

    Attribute

    src

    Image address

    Image loading failurefallback

    srcConfiguration of the picture loading failure, the bottom of the picture address, the following is the default loading failure picture

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/index.html b/src/ranui/index.html new file mode 100644 index 0000000000..cda13505ff --- /dev/null +++ b/src/ranui/index.html @@ -0,0 +1,134 @@ + + + + + + ranui | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    ranui

    Development scheme based on Web Components

    Feature

    1. Cross-Framework Compatibility: Works seamlessly with React, Vue, Preact, SolidJS, Svelte, and more. Integrates with any JavaScript project following W3C standards.
    2. Pure Native Experience: No need for npm, React/Vue, or build tools. Easy to start, like using native div tags, simplifying structure and reducing learning costs.
    3. Modular Design: Breaks systems into small, reusable components for enhanced maintainability and scalability.
    4. Open-Source: Licensed under MIT, providing free access to all source code for personal or commercial use.
    5. Interactive Documentation: Offers detailed, interactive documentation with live examples for efficient learning.
    6. Type-Checking: Built on TypeScript with full type support, ensuring robust and maintainable code.
    7. Stability and Durability: Provides exceptional stability, avoiding disruptive updates and ensuring continuous project operation.

    Situation

    Build Statusnpm-vnpm-dbrotlimodule formats: umd, esm

    Usage

    In most cases, you can use it just like a native div tag.

    Here are some examples

    1. html
    2. js
    3. jsx
    4. vue
    5. tsx

    1.html

    html
    <script src="./ranui/dist/umd/index.umd.cjs"></script>
    +
    +<body>
    +  <r-button>Button</r-button>
    +</body>

    2.js

    js
    import 'ranui';
    +
    +const Button = document.createElement('r-button');
    +Button.appendChild('this is button text');
    +document.body.appendChild(Button);

    3.jsx

    jsx
    import 'ranui';
    +const App = () => {
    +  return (
    +    <>
    +      <r-button>Button</r-button>
    +    </>
    +  );
    +};

    4.vue

    vue
    <template>
    +  <r-button>Button</r-button>
    +</template>
    +<script>
    +import 'ranui';
    +</script>

    5.tsx

    tsx
    // react 18
    +import type { SyntheticEvent } from 'react';
    +import React, { useRef } from 'react';
    +import 'ranui';
    +
    +const FilePreview = () => {
    +  const ref = useRef<HTMLDivElement | null>(null);
    +  const uploadFile = (e: SyntheticEvent<HTMLDivElement>) => {
    +    if (ref.current) {
    +      const uploadFile = document.createElement('input');
    +      uploadFile.setAttribute('type', 'file');
    +      uploadFile.click();
    +      uploadFile.onchange = (e) => {
    +        const { files = [] } = uploadFile;
    +        if (files && files?.length > 0 && ref.current) {
    +          ref.current.setAttribute('src', '');
    +          const file = files[0];
    +          const url = URL.createObjectURL(file);
    +          ref.current.setAttribute('src', url);
    +        }
    +      };
    +    }
    +  };
    +  return (
    +    <div>
    +      <r-preview ref={ref}></r-preview>
    +      <r-button type="primary" onClick={uploadFile}>
    +        choose file to preview
    +      </r-button>
    +    </div>
    +  );
    +};

    Import

    Support for on-demand import

    js
    import 'ranui/button';

    If there is a style problem, you can import the style manually

    js
    import 'ranui/style';

    If there is a type problem, you can manually import the type

    ts
    import 'ranui/types';

    Or

    ts
    import 'ranui/dist/typings';

    It can also be imported globally, which is more convenient, so that there is no need to consider anything, so that it is done.

    • ES module
    js
    import 'ranui';
    • UMD, IIFE, CJS
    html
    <script src="./ranui/dist/umd/index.umd.cjs"></script>

    Overview

    • Button
    Primary button
    Warning button
    Text button
    Default button
    • Icon
    • Skeleton
    • Input
    • message
    Information promptWarning promptError promptSuccess tiptoast tip
    • Tab
    tab1tab2tab3
    • Radar
    • Progress
    • Player
    • Select
    MikeTomLucy
    • Loading
    • math

    Event

    • react

    @ranui/react By react higher-order functions encapsulated ranui and become, Event events follow react Event specification. It is slightly different from the W3C standard.

    • Modern 'web' standards

    In the W3C standard, you can use the on attribute to define event handlers on HTML elements. But this is the old event handler approach.

    Modern web development recommends the addEventListener method.

    html
    <r-button id="button">Button</r-button>
    +
    +<script>
    +  const button = document.getElementById('button');
    +  button.addEventListener('click', function (event) {
    +    alert('New click event!');
    +  });
    +</script>

    However, if you do need to use the 'on' attribute, here is an example:

    html
    <r-input onchange="change(this.value)"></r-input>
    +
    +<script>
    +  function change(e) {
    +    console.log('e--->', e);
    +  }
    +</script>

    Note that using the 'on' attribute to define event handlers has some limitations and disadvantages.

    For example, you can't use event capture or event delegation, and each event type requires a separate attribute.

    This is why the addEventListener method is recommended for modern web development.

    You can also use the 'property' method:

    html
    <r-input id="input"></r-input>
    +
    +<script>
    +  const input = document.getElementById("input")
    +  input.onchange = (e) {
    +    console.log('e--->', e)
    +  }
    +</script>

    style

    ::part

    html
    <r-input id="input"></r-input>
    +
    +<style>
    +  /* #input refers to the current custom element
    +input in ::part(input) refers to the class  of the Shadow DOM element inside the current custom element*/
    +  #input::part(input) {
    +    width: 100px;
    +  }
    +</style>

    For specific pseudo-class names(::part), please refer to the specific introduction.

    Pass in by attribute

    A sheet attribute is added to all components, passing in a CSSStyleSheet string. It will be inserted directly into the Shadow DOM.

    CSS3 variable var

    By setting the CSS3 variable for a component, you can customize the specified styles within the component, such as:


    html
    <r-progress percent="0.7" type="drag"></r-progress>
    +<r-progress
    +  percent="0.70"
    +  type="drag"
    +  style="--ran-progress-wrap-background:linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);"
    +></r-progress>

    For specific CSS3 variable names, refer to the introduction and description of each component.

    Compatibility

    • Do not support IE, others have better support

    Contributors

    Other

    1. 优秀的组件设计
    2. 在线生成 CSS 渐变色
    3. 优秀设计作品,有 psd 和 sketch
    4. 3D UI 设计,类似于 3D 版的 figma
    5. 设计规范
    6. 优秀设计作品
    7. element UI 中文网
    8. Ant design 中文网
    9. 在线绘制 CSS 动画
    10. tailwindcss
    11. animate css
    12. can i use
    13. figma

    Protocols and standards

    1. RFCs
    2. ECMA
    3. w3c

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/input/index.html b/src/ranui/input/index.html new file mode 100644 index 0000000000..f0dac06f2b --- /dev/null +++ b/src/ranui/input/index.html @@ -0,0 +1,60 @@ + + + + + + Input | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Input

    Entering content via mouse or keyboard is the most basic form field packaging.

    Code demo

    Input field:
    xml
    <r-input></r-input>

    Attribute

    label

    Provide an input experience similar to Metiral Design.

    html
    <r-input label="user"></r-input>

    placeholder

    Consistent with native 'placeholder'.

    html
    <r-input placeholder="user"></r-input>

    disabled

    The input box can be disabled by disabled. After disabled, the events on the button become invalid.

    html
    <r-input label="user" disabled></r-input>

    value

    Sets or returns the value of the 'value' property of the input box.

    type

    Currently support 'password', 'number' these types, set will appear additional 'ui' controls.

    Password entry field

    The password can be switched between plain text and ciphertext.

    html
    <r-input icon="lock" type="password"></r-input>

    icon

    You can set an 'icon' to represent the tag identifier.

    html
    <r-input icon="user"></r-input>

    Digital input box

    Numeric input box, similar to the native 'input[type=number]', support 'min', 'max', 'step' attributes, support keyboard up and down keys to switch numbers.

    html
    <r-input type="number" min="-10" max="10" step="0.5"></r-input>

    name

    Valid when associated with the form component, the field name collected when the form is submitted

    status

    • error

    Default color value: #ff4d4f

    xml
    <r-input status="error"></r-input>
    • warning

    Default color value:#ff7875

    xml
    <r-input  status="warning"></r-input>

    event

    Common callback events.

    onchange

    Triggered when text changes.

    html
    <r-input onchange="func(this.value)"></r-input>
    js
    const input = document.createElement('r-input');
    +input.setAttribute('label', 'home');
    +const func = (e) => {
    +  console.log(e);
    +};
    +input.addEventListener('change', func);

    oninput

    Triggered when text changes.

    js
    const input = document.createElement('r-input');
    +input.setAttribute('label', 'home');
    +const func = (e) => {
    +  console.log(e);
    +};
    +input.addEventListener('input', func);

    The e parameter structure of the event

    input method

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/loading/index.html b/src/ranui/loading/index.html new file mode 100644 index 0000000000..144e0e2804 --- /dev/null +++ b/src/ranui/loading/index.html @@ -0,0 +1,54 @@ + + + + + + Loading | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Loading

    Some nice looking loading.

    Code demo

    xml
    <r-loading name="circle"></r-loading>

    Attribute

    name

    There's a lot of different loading here

    xml
    <r-loading name="double-bounce"></r-loading>
    +<r-loading name="rotate"></r-loading>
    +<r-loading name="stretch"></r-loading>
    +<r-loading name="cube"></r-loading>

    Loading list

    Move the mouse over the icon to see the loading animation

    stretch
    rotate
    double-bounce
    cube
    dot
    triple-bounce
    scale-out
    circle
    circle-line
    square
    pulse
    solar
    cube-fold
    circle-fold
    cube-grid
    circle-turn
    circle-rotate
    circle-spin
    dot-bar
    dot-circle
    line
    dot-pulse
    line-scale
    text
    cube-dim
    dot-line
    arc
    drop
    pacman

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/math/index.html b/src/ranui/math/index.html new file mode 100644 index 0000000000..0ac2dea6fa --- /dev/null +++ b/src/ranui/math/index.html @@ -0,0 +1,49 @@ + + + + + + math | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    math

    High-quality display of LaTeX in HTML pages

    Code demo

    xml
    <r-math latex="\frac{x^2}{a^2} + \frac{y^2}{b^2} = 1 \quad (a > b > 0)"></r-math>

    Attribute

    latex string

    xml
      <r-math latex="x = {-b \pm \sqrt{b^2-4ac} \over 2a}"></r-math>

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/message/index.html b/src/ranui/message/index.html new file mode 100644 index 0000000000..e4a5ffd10a --- /dev/null +++ b/src/ranui/message/index.html @@ -0,0 +1,53 @@ + + + + + + message | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    message

    Global display of operation feedback.

    Code demo

    Click to trigger the global prompt
    xml
    <r-button type="primary" onclick="message.info('This is a hint')">Click to trigger the global prompt</r-button>

    Attribute

    type

    Different prompt types

    Information prompt
    Warning prompt
    Error prompt
    Success tip
    toast tip
    html
    <r-button onclick="message.info('This is a hint')">Information prompt</r-button>
    +<r-button onclick="message.warning('This is a hint')">Warning prompt</r-button>
    +<r-button onclick="message.error('This is a hint')">Error prompt</r-button>
    +<r-button onclick="message.success('This is a hint')">Success tip</r-button>
    +<r-button onclick="message.toast('This is a hint')">toast tip</r-button>

    Method

    The component provides a number of static methods, using the following methods and parameters:

    1. You can pass only one parameter, prompt the content, the default prompt 3000 milliseconds

    message.info('This is a hint')

    message.warning('This is a hint')

    message.error('This is a hint')

    message.success('This is a hint')

    message.toast('This is a hint')"

    1. You can also pass an object, set the prompt content, turn off the delay, and trigger the callback function when you close it

    message.info({content:'This is a hint', duration: 2000, close: () => {}})

    message.warning({content:'This is a hint', duration: 2000, close: () => {}})

    message.error({content:'This is a hint', duration: 2000, close: () => {}})

    message.success({content:'This is a hint', duration: 2000, close: () => {}})

    message.toast({content:'This is a hint', duration: 2000, close: () => {}})

    参数说明类型
    contentPrompt contentstring
    durationAutomatic shutdown delay, in milliseconds. Default 3000 msnumber
    closeCallback function triggered when closed() => void

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/modal/index.html b/src/ranui/modal/index.html new file mode 100644 index 0000000000..a142f0779f --- /dev/null +++ b/src/ranui/modal/index.html @@ -0,0 +1,49 @@ + + + + + + ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/player/index.html b/src/ranui/player/index.html new file mode 100644 index 0000000000..f7b4a1a67f --- /dev/null +++ b/src/ranui/player/index.html @@ -0,0 +1,49 @@ + + + + + + r-player | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    r-player

    Video player

    Based on 'hlsjs' and' web components', let the native tag 'r-player' have a unified video control. Do not use the 'new Player(options)' way to mount to the specified 'dom', view return view, logic return logic, see and get, more intuitive.

    1. Drag and drop the progress bar
    2. Volume control
    3. The bitrate is automatically switched based on the current bandwidth
    4. Manual definition switch
    5. Play at double speed
    6. Style custom overlay
    7. 'hls' protocol standard encryption video playback
    8. Based on native development, it can run in all frameworks and unify the cross-framework situation
    9. Unified browser controls

    Code demo

    xml
      <r-player src="/ran/hls/example.m3u8"></r-player>

    Attribute

    src

    Resource address of the video

    volume

    Set the initial volume. The default is 0.5

    currentTime

    Set the initial playback time. By default, the playback starts from the beginning

    playbackRate

    Set the double speed. The default is 1.0

    debug

    console.log some info

    event

    onchange

    Listen for any player changes, and the value returned is as follows.

    An 'instance of the player' can be obtained through this method.

    Live by 'type' to judge different event types, perform different operations

    propertyexplains thatis of type
    typeIndicates the type of the changed event'string'
    dataThe value of the'Object'
    currentTimeThe current playback time'number'
    durationTotal duration of videos'number'
    tagAn example of the player'Element'

    Where 'type' type has

    NameDescription
    canplayYour browser is ready to play the media file, but it probably doesn't have enough data to play it to the end without pausing to buffer the content further.
    canplaythroughThe browser estimates that it canplay media until the end without stopping content buffering.
    completeOfflineAudioContext The rendering is complete.
    durationchangeduration is triggered when the value of the duration property changes.
    emptiedMedia content emptied; For example, when the media is already loaded (or partially loaded), this event is sent and the load() method is called to reload it.
    endedThe video stops playing because the media has reached the end point.
    loadedmetadataThe metadata is loaded.
    progressis triggered periodically when the browser loads the resource.
    ratechangeThe play rate changes.
    seekedThe seek operation is complete.
    seekingseek begins.
    stalledThe user agent is trying to obtain media data but it has not appeared unexpectedly.
    suspendMedia data loading has been suspended.
    loadeddataThe first frame in media has been added. media has loaded.
    timeupdateThe time specified by the currentTime property changes. currentTime attribute has changed.
    volumechangeThe volume changes.
    waitingPlaying has stopped due to lack of data.
    playPlayback has started.
    playingAfter a pause or delay due to lack of data, playback is ready to begin.
    pausePlay is paused.
    volumeThe volume changes.
    fullscreenTriggers a full-screen event

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/popover/index.html b/src/ranui/popover/index.html new file mode 100644 index 0000000000..0559a015d2 --- /dev/null +++ b/src/ranui/popover/index.html @@ -0,0 +1,74 @@ + + + + + + Popover | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Popover

    Click/mouse to move into the element and pop up a bubbling card layer.

    Code demo

    popover
    this is content
    xml
    <r-popover>
    +    <r-button>popover</r-button>
    +    <r-content>
    +      <div>this is content</div>
    +    </r-content>
    +</r-popover>

    Attribute

    trigger

    Trigger mode:

    • hover
    hover
    hover
    xml
    <r-popover trigger="hover">
    +    <r-button>hover</r-button>
    +    <r-content>
    +      <div>hover</div>
    +    </r-content>
    +  </r-popover>
    • click
    click
    click
    xml
    <r-popover trigger="click">
    +    <r-button>click</r-button>
    +    <r-content>
    +      <div>click</div>
    +    </r-content>
    +  </r-popover>

    placement

    Display location

    • bottom
    bottom
    bottom
    xml
    <r-popover trigger="hover" placement="bottom">
    +    <r-button>bottom</r-button>
    +    <r-content>
    +      <div>bottom</div>
    +    </r-content>
    +  </r-popover>
    • top
    top
    top
    xml
    <r-popover trigger="hover" placement="top">
    +    <r-button>top</r-button>
    +    <r-content>
    +      <div>top</div>
    +    </r-content>
    +  </r-popover>

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/preview/index.html b/src/ranui/preview/index.html new file mode 100644 index 0000000000..3c7eee42a7 --- /dev/null +++ b/src/ranui/preview/index.html @@ -0,0 +1,68 @@ + + + + + + preview | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    preview

    Support 'docx', 'pptx', 'pdf', 'xlsx' file preview

    Code demo

    choose file to preview
    html
    <r-preview id="preview"></r-preview>
    +<r-button type="primary" onclick="uploadFile()">choose file to preview</r-button>
    +
    +<script>
    +  const uploadFile = () => {
    +    const preview = document.getElementById('preview');
    +    const uploadFile = document.createElement('input');
    +    uploadFile.setAttribute('type', 'file');
    +    uploadFile.click();
    +    uploadFile.onchange = (e) => {
    +      const { files = [] } = uploadFile;
    +      if (files.length > 0) {
    +        preview.setAttribute('src', '');
    +        const file = files[0];
    +        const url = URL.createObjectURL(file);
    +        preview.setAttribute('src', url);
    +      }
    +    };
    +  };
    +</script>

    Attribute

    src

    If there is a 'src' address, the popup window will be opened, and if there is no 'src', it will not be displayed

    html
    <r-preview src=""></r-preview>

    closeable

    'closeable' defaults to 'true' and can be closed, when set to 'false', it cannot be closed, and the close button in the upper right corner will not be displayed

    html
    <r-preview closeable="false"></r-preview>

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/progress/index.html b/src/ranui/progress/index.html new file mode 100644 index 0000000000..b9e794adf6 --- /dev/null +++ b/src/ranui/progress/index.html @@ -0,0 +1,55 @@ + + + + + + progress | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    progress

    Interactive progress bar

    Code demo

    xml
    <r-progress type="drag" ></r-progress>

    Attribute

    total

    Set progress bar Total progress, allowed percentages and numbers.

    html
    <r-progress percent="30" total="1000"></r-progress>
    +<r-progress percent="70" total="100"></r-progress>
    +<r-progress percent="10%" total="100%"></r-progress>

    percent

    Set the current progress of the progress bar, you can set the percentage and number, 'percent' cannot exceed 'total'. If 'total' is not set, the default 'total' is' 100% ', that is, '1'.

    html
    <r-progress type="primary" percent="30%"></r-progress>
    +<r-progress type="primary" percent="40%"></r-progress>
    +<r-progress type="primary" percent="100%"></r-progress>

    dot

    Point of the progress bar, Default display, set to 'false' can be hidden

    html
    <r-progress type="drag" percent="30%" dot="false"></r-progress>
    +<r-progress type="primary" percent="40%" dot="true"></r-progress>
    +<r-progress type="primary" percent="40%"></r-progress>

    type

    • primary: Default progress bar, not setting the 'type' attribute is the default
    • drag: Draggable, clickable progress bar (dragging requires' dot 'to be' true ')
    html
    <r-progress type="drag" percent="30%"></r-progress> <r-progress type="primary" percent="40%"></r-progress>

    Method

    change

    The 'change' event is triggered when the 'percent' and 'total' properties change.

    propertyexplains thattype
    valueCurrent progress'string or number'
    percentCurrent progress'string or number'
    totalTotal progress'string or number'

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/radar/index.html b/src/ranui/radar/index.html new file mode 100644 index 0000000000..9ed3ba5045 --- /dev/null +++ b/src/ranui/radar/index.html @@ -0,0 +1,103 @@ + + + + + + Radar | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Radar

    Comprehensive comparison of differences between multiple sets of data in two-dimensional form, often used to compare 2 or more sets of data

    Code demo

    xml
    <r-radar
    +abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
    +    style="width:300px;height:300px;display: block;"
    +>
    +</r-radar>

    Attribute

    abilitys

    Data that needs to be presented

    An array object with the following properties

    keyDescriptiontype
    abilityNameDisplays the attribute name'string'
    scoreRateDisplays the dimension value. The maximum value is 100'number'
    backgroundColorThe background color of theproperty is an optional string
    fontSizeThe font size for the attribute nameThe optional parameter 'number'
    fontFamilyThe font for the attribute nameis optional with 'string'
    fontColorThe font color for theproperty is an optional parameter with string
    xml
    <r-radar
    +    abilitys='[{"abilityName":"HP","scoreRate":"10","backgroundColor":"red","fontSize":"30","fontColor":"blue"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
    +    style="width:300px;height:300px;display: block;"
    +>
    +</r-radar>

    colorPolygon

    xml
    <r-radar
    +    colorPolygon="green"
    +    abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
    +    style="width:300px;height:300px;display: block;"
    +>
    +</r-radar>

    colorLine

    xml
    <r-radar
    +    colorLine="blue"
    +   abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
    +></r-radar>

    fillColor

    xml
    <r-radar
    +    fillColor="red"
    +   abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
    +    style="width:300px;height:300px;display: block;"
    +>
    +</r-radar>

    strokeColor

    xml
    <r-radar
    +    strokeColor="blue"
    +   abilitys='[{"abilityName":"HP","scoreRate":"10"},{"abilityName":"Attack","scoreRate":"90"},{"abilityName":"DEF","scoreRate":"20"},{"abilityName":"Element mastery","scoreRate":"50"},{"abilityName":"Critical Hit Chance","scoreRate":"80"},{"abilityName":"Critical hit damage","scoreRate":"50"}]'
    +    style="width:300px;height:300px;display: block;"
    +>
    +</r-radar>

    Example data used

    Because the 'attribute' of 'HTMl' can only get 'string'. Therefore, the data that needs to be passed in needs to be in the format of 'JSON' string, and then parsed by 'json.parse' array object, if the 'JSON' format is wrong, it cannot be parsed.

    json
    [
    +  {
    +    "abilityName": "HP",
    +    "scoreRate": "10",
    +    "backgroundColor": "red",
    +    "fontSize": "30",
    +    "fontColor": "blue"
    +  },
    +  {
    +    "abilityName": "Attack",
    +    "scoreRate": "90"
    +  },
    +  {
    +    "abilityName": "DEF",
    +    "scoreRate": "20"
    +  },
    +  {
    +    "abilityName": "Element mastery",
    +    "scoreRate": "50"
    +  },
    +  {
    +    "abilityName": "Critical Hit Chance",
    +    "scoreRate": "80"
    +  },
    +  {
    +    "abilityName": "Critical hit damage",
    +    "scoreRate": "50"
    +  }
    +]

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/select/index.html b/src/ranui/select/index.html new file mode 100644 index 0000000000..492e9247b8 --- /dev/null +++ b/src/ranui/select/index.html @@ -0,0 +1,90 @@ + + + + + + Select | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Select

    A regular pull-down selector.

    Code demo

    MikeTomLucy
    xml
    <r-select style="width: 120px; height: 40px" defaultValue="185">
    +      <r-option value="185">Mike</r-option>
    +      <r-option value="186">Tom</r-option>
    +      <r-option value="187">Lucy</r-option>
    +    </r-select>

    Attribute

    defaultValue

    Sets the currently selected value

    MikeTomLucy
    xml
        <r-select style="width: 120px; height: 40px" defaultValue="185">
    +      <r-option value="185">Mike</r-option>
    +      <r-option value="186">Tom</r-option>
    +      <r-option value="187">Lucy</r-option>
    +    </r-select>

    disabled

    Adding the disabled attribute makes the selection box unavailable and changes the style.

    MikeTomLucy
    xml
        <r-select style="width: 120px; height: 40px" disabled defaultValue="185">
    +      <r-option value="185">Mike</r-option>
    +      <r-option value="186">Tom</r-option>
    +      <r-option value="187">Lucy</r-option>
    +    </r-select>

    type

    You can set the text type without borders and drop-down ICONS

    MikeTomLucy
    xml
    <r-select
    +      style="width: 120px; height: 40px"
    +      type="text"
    +      defaultValue="185"
    +    >
    +      <r-option value="185">Mike</r-option>
    +      <r-option value="186">Tom</r-option>
    +      <r-option value="187">Lucy</r-option>
    +    </r-select>

    placement

    Drop-down box display direction default down, set to 'top' can go up

    MikeTomLucy
    xml
    <r-select
    +      style="width: 120px; height: 40px"
    +      type="text"
    +      defaultValue="185"
    +      placement="top"
    +    >
    +      <r-option value="185">Mike</r-option>
    +      <r-option value="186">Tom</r-option>
    +      <r-option value="187">Lucy</r-option>
    +    </r-select>

    showSearch

    Expand to search for options

    MikeTomLucy
    xml
    <r-select style="width: 120px; height: 40px" showSearch>
    +<r-option value="185">Mike</r-option>
    +<r-option value="186">Tom</r-option>
    +<r-option value="187">Lucy</r-option>
    +</r-select>

    getPopupContainerId

    The drop-down box is mounted to document.body by default, and can be mounted to the specified element by passing in the element's id `

    MikeTomLucy
    xml
    <r-select getPopupContainerId="elementid">
    +      <r-option value="185">Mike</r-option>
    +      <r-option value="186">Tom</r-option>
    +      <r-option value="187">Lucy</r-option>
    +    </r-select>

    If you need to customize the style of the drop-down box, you can pass in a 'class' name to customize

    trigger

    'select' The method that the component triggers. Default 'click', click trigger. You can set 'hover', or 'click,hover', which means that both click and mouse move trigger.

    If it is set to none, it will not trigger.

    MikeTomLucy
    xml
    <r-select getPopupContainerId="elementid" action="click,hover">
    +      <r-option value="185">Mike</r-option>
    +      <r-option value="186">Tom</r-option>
    +      <r-option value="187">Lucy</r-option>
    +    </r-select>

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/skeleton/index.html b/src/ranui/skeleton/index.html new file mode 100644 index 0000000000..9feb85711b --- /dev/null +++ b/src/ranui/skeleton/index.html @@ -0,0 +1,49 @@ + + + + + + skeleton | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    skeleton

    Provides a combination of placeholder graphics where you need to wait for content to load.

    Code demo

    The skeleton length follows the length of the parent element

    xml
    <r-skeleton ></r-skeleton>

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/tab/index.html b/src/ranui/tab/index.html new file mode 100644 index 0000000000..9c62af7d21 --- /dev/null +++ b/src/ranui/tab/index.html @@ -0,0 +1,91 @@ + + + + + + Tab | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Tab

    TAB pages, where 'r-tab' needs to be used with 'r-tabs'

    Code demo

    111112222233333
    xml
    <r-tabs >
    +      <r-tab label="tab1">11111</r-tab>
    +      <r-tab label="tab2">22222</r-tab>
    +      <r-tab label="tab3">33333</r-tab>
    +</r-tabs>

    Attribute

    label

    'r-tab' property to set the name of the tag

    111112222233333
    xml
    <r-tabs >
    +      <r-tab label="tab1">11111</r-tab>
    +      <r-tab label="tab2">22222</r-tab>
    +      <r-tab label="tab3">33333</r-tab>
    +</r-tabs>

    active tag 'active', the tag's unique identifier 'ranKey'

    • 'ranKey' is an attribute of 'r-tab' that determines the unique value of 'r-tab' under the same 'r-tabs'. If 'ranKey' is not set, it defaults to 'index'. (Not using the 'key' field is to prevent the 'key' is reserved field)
    • 'active' is an attribute of 'r-tabs', which is used to set active tabs. The label 'active' equals' key 'is an active label.
    1. 'key' is not set
    111112222233333
    xml
     <r-tabs active="1">
    +        <r-tab label="tab1">11111</r-tab>
    +        <r-tab label="tab2">22222</r-tab>
    +        <r-tab label="tab3">33333</r-tab>
    + </r-tabs>
    1. Set 'key'
    1111122222333334
    xml
        <r-tabs active="c">
    +      <r-tab label="tab1" ranKey="a">11111</r-tab>
    +      <r-tab label="tab2" ranKey="b">22222</r-tab>
    +      <r-tab label="tab3" ranKey="c">33333</r-tab>
    +      <r-tab label="tab4">4</r-tab>
    +    </r-tabs>

    disabled

    Set unclickable labels

    1111122222333334
    xml
        <r-tabs active="c">
    +      <r-tab label="tab1" ranKey="a" disabled>11111</r-tab>
    +      <r-tab label="tab2" ranKey="b">22222</r-tab>
    +      <r-tab label="tab3" ranKey="c">33333</r-tab>
    +      <r-tab label="tab4">4</r-tab>
    +    </r-tabs>

    type

    The 'r-tabs' property sets the types of tabs. If not set, the default is' flat '

    1. flat
    111112222233333
    xml
    <r-tabs type="flat">
    +      <r-tab label="tab1">11111</r-tab>
    +      <r-tab label="tab2">22222</r-tab>
    +      <r-tab label="tab3">33333</r-tab>
    +</r-tabs>
    1. line
    111112222233333
    xml
    <r-tabs type="line">
    +      <r-tab label="tab1">11111</r-tab>
    +      <r-tab label="tab2">22222</r-tab>
    +      <r-tab label="tab3">33333</r-tab>
    +</r-tabs>

    align

    Set the alignment of the label. The default is' align="start" '

    1. start
    111112222233333
    xml
     <r-tabs type="line" align="start">
    +        <r-tab label="tab1">11111</r-tab>
    +        <r-tab label="tab2">22222</r-tab>
    +        <r-tab label="tab3">33333</r-tab>
    +    </r-tabs>
    1. center
    111112222233333
    xml
     <r-tabs type="line" align="center">
    +        <r-tab label="tab1">11111</r-tab>
    +        <r-tab label="tab2">22222</r-tab>
    +        <r-tab label="tab3">33333</r-tab>
    +    </r-tabs>
    1. end
    111112222233333
    xml
     <r-tabs type="line" align="end">
    +        <r-tab label="tab1">11111</r-tab>
    +        <r-tab label="tab2">22222</r-tab>
    +        <r-tab label="tab3">33333</r-tab>
    +    </r-tabs>

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranui/tabs/index.html b/src/ranui/tabs/index.html new file mode 100644 index 0000000000..ace5fad3ec --- /dev/null +++ b/src/ranui/tabs/index.html @@ -0,0 +1,73 @@ + + + + + + Tab | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Tab

    Code demo

    tab1tab2tab3
    xml
    <r-tabs>
    +    <r-tab label="tab1">tab1</r-tab>
    +    <r-tab label="tab2">tab2</r-tab>
    +    <r-tab label="tab3">tab3</r-tab>
    +</r-tabs>

    Attribute

    label

    Each 'r-tab' needs to specify a name 'label', which is used to display the label header.

    tab1tab2tab3
    xml
    <r-tabs>
    +    <r-tab label="tab1">tab1</r-tab>
    +    <r-tab label="tab2">tab2</r-tab>
    +    <r-tab label="tab3">tab3</r-tab>
    +</r-tabs>

    disabled

    Each 'r-tab' can be specified with the 'disabled' attribute to disable the TAB.

    tab1tab2tab3
    xml
    <r-tabs>
    +    <r-tab label="tab1">tab1</r-tab>
    +    <r-tab label="tab2" disabled>tab2</r-tab>
    +    <r-tab label="tab3">tab3</r-tab>
    +</r-tabs>

    Identifies' key ', 'active'

    Each 'r-tab' needs to specify an identifier 'key', no default sequence number is' key ',

    'active' works on 'r-tabs' and can specify a switch to a specific TAB or an initial value.

    tab1tab2tab3
    html
    <r-tabs active="B">
    +  <r-tab label="tab1" r-key="A">tab1</r-tab>
    +  <r-tab label="tab2" r-key="B">tab2</r-tab>
    +  <r-tab label="tab3" r-key="C">tab3</r-tab>
    +</r-tabs>

    icon

    Each 'r-tab' can specify 'icon', with 'label' to achieve the effect of icon plus text.

    tab1tab2tab3
    html
    <r-tabs>
    +  <r-tab label="home" icon="home">tab1</r-tab>
    +  <r-tab label="message" icon="message">tab2</r-tab>
    +  <r-tab label="user" icon="user">tab3</r-tab>
    +</r-tabs>

    It is also possible to specify 'icon' alone, without using 'label'. However, in this case, the size of the icon must be set, otherwise the size of the icon cannot be judged

    tab1tab2tab3
    html
    <r-tabs>
    +  <r-tab icon="home" iconSize="22">tab1</r-tab>
    +  <r-tab icon="message" iconSize="22">tab2</r-tab>
    +  <r-tab icon="user" iconSize="22">tab3</r-tab>
    +</r-tabs>

    'type'

    The style is text, clean,

    event '

    onchange

    Triggered when the switch is complete.

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/binaryTree/index.html b/src/ranuts/binaryTree/index.html new file mode 100644 index 0000000000..02a529f26e --- /dev/null +++ b/src/ranuts/binaryTree/index.html @@ -0,0 +1,50 @@ + + + + + + 二叉树的定义 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    二叉树的定义

    在计算机科学中,二叉树(Binary tree)是每个节点最多只有两个分支(即不存在分支度大于 2 的节点)的树结构。通常分支被称作“左子树”或“右子树”。二叉树的分支具有左右次序,不能随意颠倒[1]。。

    二叉树的性质

    • 在二叉树的第 i 层上最多有 2^(i-1)个结点(i>=1)
    • 深度为 h 的二叉树,最多有 2^h-1 个结点,最少有 h 个结点(h>=1)
    • 包含 n 个结点的二叉树的高度至少为(log2n)+1
    • 非空的二叉树,分支度为 0 的总数为 n0,分支度为 2 的总数为 n2,则 n0=n2+1
    • 二叉树的总结点数 n = n1 + n2 + n0
    • 总连线数等于总节点数减一(B = n - 1)
    • 总连线数等于分支度为 2 的节点的两倍加上分支度为 1 的节点(B = n2 _ 2 + n1 _ 1)

    二叉树的类型

    满二叉树

    一棵深度为 k 且有 2k-1 个节点的二叉树称为满二叉树。 除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树[2]

    完全二叉树

    一棵深度为 k 的有 n 个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为 i(1≤i≤n)的结点与满二叉树中编号为 i 的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。

    二叉搜索树

    二叉搜索树(BST)又称二叉查找树或二叉排序树。它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

    平衡二叉树

    平衡二叉树(AVL)一定是二叉搜索树,且左子树和右子树的高度差的绝对值不超过 1。 平衡二叉树

    B 树

    B 树属于多叉树又名平衡多路查找树(查找路径不只两个)

    B+树

    B+树是 B 树的变体,也是一种多路搜索树。

    B*树

    B* 树是 B+树的变体,在 B+树的非根和非叶子结点再增加指向兄弟的指针;B* 树定义了非叶子结点关键字个数至少为(2/3)M,即块的最低使用率为 2/3(代替 B+树的 1/2)。B 树分配新结点的概率比 B+树要低,空间使用率更高;

    红黑树

    红黑树是一种平衡二叉查找树的变体,它的左右子树高差有可能大于 1,所以红黑树不是严格意义上的平衡二叉树(AVL),但对它进行平衡的代价较低, 其平均统计性能要强于 AVL 。

    遍历

    前序遍历

    后序遍历

    中序遍历

    层序遍历

    常见算法题

    镜像二叉树

    重建二叉树

    二叉树深度

    二叉树节点总数

    判断二叉树子结构

    输入两棵二叉树 A 和 B,判断 B 是不是 A 的子结构。(ps:约定空树不是任意一个树的子结构)

    参考文档

    1. 维基百科二叉树
    2. 百度百科满二叉树

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/bundler/index.html b/src/ranuts/bundler/index.html new file mode 100644 index 0000000000..fa354eebc1 --- /dev/null +++ b/src/ranuts/bundler/index.html @@ -0,0 +1,59 @@ + + + + + + Bundler | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Bundler

    Bundler的使用: 传入 options 参数

    function build(options: Options):Promise<Build> {
    +  const bundle = new Bundle({
    +    entry: options.input
    +  });
    +  return bundle.build().then(() => {
    +    return {
    +      generate: () => bundle.render()
    +    };
    +  });
    +}

    架构图

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/file/appendFile.html b/src/ranuts/file/appendFile.html new file mode 100644 index 0000000000..3e2fcf7b8a --- /dev/null +++ b/src/ranuts/file/appendFile.html @@ -0,0 +1,49 @@ + + + + + + AppendFile | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    AppendFile

    追加一些数据到文件内

    API

    Return

    • Promise
    参数说明类型描述
    success是否追加成功booleantrue 追加成功 false 追加失败
    data追加失败的原因,添加成功后的文件内容any

    Options

    参数说明类型默认值
    path文件路径,需要追加的文件stringundefined
    content需要追加的内容string

    Example

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/file/fileInfo.html b/src/ranuts/file/fileInfo.html new file mode 100644 index 0000000000..46b923c67c --- /dev/null +++ b/src/ranuts/file/fileInfo.html @@ -0,0 +1,49 @@ + + + + + + QueryFileInfo | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    QueryFileInfo

    查询一个文件的详细信息,一般用于区分文件还是目录,可以通过返回的 data 来判断(data.isDirectory())

    API

    Return

    • Promise
    参数说明类型描述
    success是否检查成功booleantrue 成功 false 失败
    data文件的信息,或者错误的原因Stats

    Options

    参数说明类型默认值
    path文件路径,需要检查的文件路径stringundefined

    Example

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/file/readDir.html b/src/ranuts/file/readDir.html new file mode 100644 index 0000000000..5f84dba414 --- /dev/null +++ b/src/ranuts/file/readDir.html @@ -0,0 +1,49 @@ + + + + + + ReadDir | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    ReadDir

    读一个目录下的所有文件

    API

    Return

    • Promise
    参数说明类型描述
    result目录下所有文件的数组array传入函数的参数

    Options

    参数说明类型默认值
    optionsobject传入函数的参数
    dirPath文件的路径Stats

    Example

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/file/readFile.html b/src/ranuts/file/readFile.html new file mode 100644 index 0000000000..53f7e4eebe --- /dev/null +++ b/src/ranuts/file/readFile.html @@ -0,0 +1,49 @@ + + + + + + ReadFile | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    ReadFile

    观察一个文件是否改变

    API

    Return

    • Promise
    参数说明类型描述
    data文件是否被改变booleantrue 文件改变 false 文件没变

    Options

    参数说明类型默认值
    path文件路径,需要监听的文件stringundefined
    interval监听文件改变的时间,单位毫秒。number20

    Example

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/file/watchFile.html b/src/ranuts/file/watchFile.html new file mode 100644 index 0000000000..5b2ea9563d --- /dev/null +++ b/src/ranuts/file/watchFile.html @@ -0,0 +1,49 @@ + + + + + + WatchFile | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    WatchFile

    观察一个文件是否改变

    API

    Return

    • Promise
    参数说明类型描述
    status文件是否被改变booleantrue 文件改变 false 文件没变

    Options

    参数说明类型默认值
    path文件路径,需要监听的文件stringundefined
    interval监听文件改变的时间,单位毫秒。number20

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/file/writeFile.html b/src/ranuts/file/writeFile.html new file mode 100644 index 0000000000..6620c0523d --- /dev/null +++ b/src/ranuts/file/writeFile.html @@ -0,0 +1,49 @@ + + + + + + WriteFile | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    WriteFile

    将内容写入文件

    API

    Return

    • Promise
    参数说明类型描述
    success是否写入成功booleantrue 成功 false 失败
    data写入失败的原因,添加成功后的文件内容和文件路径any

    Options

    参数说明类型默认值
    path文件路径,需要追加的文件stringundefined
    content需要追加的内容string

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/index.html b/src/ranuts/index.html new file mode 100644 index 0000000000..8e10203b1b --- /dev/null +++ b/src/ranuts/index.html @@ -0,0 +1,49 @@ + + + + + + ranuts overview | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    ranuts overview

    Method list

    Methoddescriptiondetail
    writeFileWrite to filewriteFile
    readFileRead filereadFile
    readDirRead the directory and get the names of all the files in the directoryreadDir
    watchFileCheck whether the contents of the file have changedwatchFile
    queryFileInfoQuery file informationqueryFileInfo
    filterObjFilter objectfilterObj
    EventEmitterPublish-subscribe classEventEmitter
    str2XmlString is converted to xmlstr2Xml
    getMimeGets the mime type based on the file format suffixgetMime
    getCookieGets the value of the specified cookiewriteFile
    formatJsonFormatted JSONformatJson

    TOTP

    2FA Verification
    Generate
    code:
    expires:

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/mimeType/mimeType.html b/src/ranuts/mimeType/mimeType.html new file mode 100644 index 0000000000..0460809137 --- /dev/null +++ b/src/ranuts/mimeType/mimeType.html @@ -0,0 +1,56 @@ + + + + + + getMime | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    getMime

    传入文件格式后缀,返回mime type

    API

    Return

    参数说明类型
    string返回mime typestring

    Options

    参数说明类型默认值
    ext文件后缀格式string

    Example

    js
    import { getMime } from 'ranuts';
    +
    +const result = getMime('.pptx');
    +console.log(result);
    +// 'application/vnd.openxmlformats-officedocument.presentationml.presentation
    +const res = getMime('.txt');
    +console.log(result);
    +// text/plain

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/mode/subscribe.html b/src/ranuts/mode/subscribe.html new file mode 100644 index 0000000000..c906966262 --- /dev/null +++ b/src/ranuts/mode/subscribe.html @@ -0,0 +1,80 @@ + + + + + + EventEmitter | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    EventEmitter

    发布订阅的类

    Class

    Methods

    方法参数说明默认值
    on订阅事件订阅事件,传入参数事件名,回调函数
    once订阅一次事件,传入参数事件名,回调函数订阅一次事件,触发一次后不再会触发
    off取消订阅事件,传入参数事件名,回调函数取消订阅事件
    emit触发事件,需要事件名触发事件

    Example

    js
    import { Subscribe } from 'ranuts';
    +
    +const subscribe = new Subscribe();
    +
    +// 订阅事件1
    +subscribe.on('event', () => {
    +  console.log(1);
    +});
    +// 订阅事件2
    +subscribe.on('event', () => {
    +  console.log(2);
    +});
    +// 订阅事件3
    +const eventThree = () => {
    +  console.log(3);
    +};
    +subscribe.on('event', eventThree);
    +// 订阅事件4,需要传递参数
    +subscribe.on('event', (num) => {
    +  console.log(num);
    +});
    +// 触发事件,同时传参数
    +subscribe.emit('event', 4);
    +// console.log(1) console.log(2) console.log(3) console.log(4)
    +
    +// 取消事件三
    +subscribe.off('event', eventThree);
    +
    +// 订阅一次,触发一次自动取消
    +subscribe.once('other', () => {
    +  console.log(5);
    +});

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/utils/convertImageToBase64.html b/src/ranuts/utils/convertImageToBase64.html new file mode 100644 index 0000000000..b960cac8fb --- /dev/null +++ b/src/ranuts/utils/convertImageToBase64.html @@ -0,0 +1,53 @@ + + + + + + convertImageToBase64 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    convertImageToBase64

    Picture turn 'base64'

    API

    Return

    argumentInstructionstype
    successWhether the conversion is successfulboolean
    dataThe value after successful conversionstring,ArrayBuffer , null
    messageThe reasons why the conversion succeeds or failsstring

    Options

    argumentInstructionstypeDefault value
    fileIncoming fileFilenull

    Example

    js
    import { convertImageToBase64 } from 'ranuts';
    +
    +convertImageToBase64(file).then((res) => {
    +  console.log(result);
    +});

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/utils/filterObj.html b/src/ranuts/utils/filterObj.html new file mode 100644 index 0000000000..d90d3d00a7 --- /dev/null +++ b/src/ranuts/utils/filterObj.html @@ -0,0 +1,61 @@ + + + + + + filterObj | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    filterObj

    Filter the properties of the object, remove the properties of the object in the list array, return a new object, usually used to remove null characters and null

    API

    Return

    argumentInstructionstype
    ObjectReturn an objectObject

    Options

    argumentInstructionstypeDefault value
    objObjects to be filteredobject
    listFamiliar array to filterarray

    Example

    js
    import { filterObj } from 'ranuts';
    +
    +const obj = {
    +  name: 'chaxus',
    +  age: 10,
    +  address: 'spark',
    +};
    +
    +const result = filterObj(obj, ['name', 'address']);
    +
    +console.log(result);
    +
    +// { age:10 }

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/utils/formatJson.html b/src/ranuts/utils/formatJson.html new file mode 100644 index 0000000000..a60bec63df --- /dev/null +++ b/src/ranuts/utils/formatJson.html @@ -0,0 +1,58 @@ + + + + + + formatJson | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    formatJson

    Pass in a JSON or JSON string, add Spaces and newlines to return a formatted JSON string

    API

    Return

    argumentInstructionstype
    stringReturn an objectObject

    Options

    argumentInstructionstypeDefault value
    jsonJSON objects that need to be formattedobject,stringnull
    callbackError callback, optionalfunctionnull

    Example

    js
    import { formatJson } from 'ranuts';
    +
    +const json = {
    +  name: 'chaxus',
    +  age: 3,
    +};
    +
    +const result = formatJson(json);
    +
    +console.log(result);

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/utils/getCookie.html b/src/ranuts/utils/getCookie.html new file mode 100644 index 0000000000..3e93ef1f2f --- /dev/null +++ b/src/ranuts/utils/getCookie.html @@ -0,0 +1,55 @@ + + + + + + getCookie | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    getCookie

    Pass in a string to get the value of the cookie with the specified name

    API

    Return

    argumentInstructionstype
    stingReturns the value of a cookie with the specified namestring

    Options

    argumentInstructionstypeDefault value
    nameSpecifies the value of the name that gets the cookieobject

    Example

    js
    import { getCookie } from 'ranuts';
    +
    +const result = getCookie('name');
    +
    +console.log(result);
    +
    +// ''

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/utils/ocr.html b/src/ranuts/utils/ocr.html new file mode 100644 index 0000000000..6cc76f9171 --- /dev/null +++ b/src/ranuts/utils/ocr.html @@ -0,0 +1,63 @@ + + + + + + OCR | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    OCR

    Pass in the image and the corresponding language type, and return the text in the image.

    API

    Return

    argumentInstructionstype
    successWhether the resolution is successfulboolean
    dataThe object is parsed successfullyobj
    messageAnalyze the reasons for success or failurestring

    Options

    argumentInstructionstypeDefault value
    imagesAn array of images, supporting 'url' and 'base64'Array<string>null
    languageSpecify the language in which the text will be generatedlang-codestring
    langPathWhen using it, you need to be able to access cdn.jsdelivr.net, which will download the corresponding language package, if you cannot access it, you can also put the language package locally, passing the corresponding directory pathstringThis parameter is optional. By default, download from the network

    Example

    js
    import { ocr } from 'ranuts';
    +
    +const images = ['https://chaxus.github.io/ran/ocr/eng.png'];
    +const languages = 'eng';
    +ocr({ images, language }).then((res) => {
    +  console.log(res.data?.[0].data.text);
    +});
    +// Mild Splendour of the various-vested Night!
    +// Mother of wildly-working visions! hail
    +// I watch thy gliding, while with watery light
    +// Thy weak eye glimmers through a fleecy veil;
    +// And when thou lovest thy pale orb to shroud
    +// Behind the gather’d blackness lost on high;
    +// And when thou dartest from the wind-rent cloud
    +// Thy placid lightning o’er the awaken’d sky.

    Lang Code

    Lang CodeLanguage
    afrAfrikaans
    amhAmharic
    araArabic
    asmAssamese
    azeAzerbaijani
    aze_cyrlAzerbaijani - Cyrillic
    belBelarusian
    benBengali
    bodTibetan
    bosBosnian
    bulBulgarian
    catCatalan; Valencian
    cebCebuano
    cesCzech
    chi_simChinese - Simplified
    chi_traChinese - Traditional
    chrCherokee
    cymWelsh
    danDanish
    deuGerman
    dzoDzongkha
    ellGreek, Modern (1453-)
    engEnglish
    enmEnglish, Middle (1100-1500)
    epoEsperanto
    estEstonian
    eusBasque
    fasPersian
    finFinnish
    fraFrench
    frkGerman Fraktur
    frmFrench, Middle (ca. 1400-1600)
    gleIrish
    glgGalician
    grcGreek, Ancient (-1453)
    gujGujarati
    hatHaitian; Haitian Creole
    hebHebrew
    hinHindi
    hrvCroatian
    hunHungarian
    ikuInuktitut
    indIndonesian
    islIcelandic
    itaItalian
    ita_oldItalian - Old
    javJavanese
    jpnJapanese
    kanKannada
    katGeorgian
    kat_oldGeorgian - Old
    kazKazakh
    khmCentral Khmer
    kirKirghiz; Kyrgyz
    korKorean
    kurKurdish
    laoLao
    latLatin
    lavLatvian
    litLithuanian
    malMalayalam
    marMarathi
    mkdMacedonian
    mltMaltese
    msaMalay
    myaBurmese
    nepNepali
    nldDutch; Flemish
    norNorwegian
    oriOriya
    panPanjabi; Punjabi
    polPolish
    porPortuguese
    pusPushto; Pashto
    ronRomanian; Moldavian; Moldovan
    rusRussian
    sanSanskrit
    sinSinhala; Sinhalese
    slkSlovak
    slvSlovenian
    spaSpanish; Castilian
    spa_oldSpanish; Castilian - Old
    sqiAlbanian
    srpSerbian
    srp_latnSerbian - Latin
    swaSwahili
    sweSwedish
    syrSyriac
    tamTamil
    telTelugu
    tgkTajik
    tglTagalog
    thaThai
    tirTigrinya
    turTurkish
    uigUighur; Uyghur
    ukrUkrainian
    urdUrdu
    uzbUzbek
    uzb_cyrlUzbek - Cyrillic
    vieVietnamese
    yidYiddish

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/utils/str2xml.html b/src/ranuts/utils/str2xml.html new file mode 100644 index 0000000000..554d8d226a --- /dev/null +++ b/src/ranuts/utils/str2xml.html @@ -0,0 +1,56 @@ + + + + + + str2Xml | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    str2Xml

    Pass in a string and convert it to 'xml'

    API

    Return

    argumentInstructionstype
    HTMLElement返回一个HTMLElementHTMLElement

    Options

    argumentInstructionstypeDefault value
    xmlStrIncoming parameterstringnull
    formatSet the format to be converted. The default is' text/xml '' DOMParserSupportedType 'null

    Example

    For example, when doing icon library, we need to dynamically import all the 'ICONS' in the directory. In this case, strings are imported, but strings cannot be added to 'xml'. So we need to convert the string to 'xml', and then we can add it to 'xml'.

    js
    import { str2Xml } from 'ranuts';
    +
    +// import 'assets/*.svg'
    +const svg = `<svg t="1667483498347" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8544" width="200" height="200"><path d="M858.5 763.6c-18.9-44.8-46.1-85-80.6-119.5-34.5-34.5-74.7-61.6-119.5-80.6-0.4-0.2-0.8-0.3-1.2-0.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-0.4 0.2-0.8 0.3-1.2 0.5-44.8 18.9-85 46-119.5 80.6-34.5 34.5-61.6 74.7-80.6 119.5C146.9 807.5 137 854 136 901.8c-0.1 4.5 3.5 8.2 8 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c0.1 4.4 3.6 7.8 8 7.8h60c4.5 0 8.1-3.7 8-8.2-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z" p-id="8545"></path></svg>`;
    +
    +const icon = str2Xml(svg, 'image/svg+xml');
    +
    +document.body.appendChild(icon);

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/src/ranuts/utils/task.html b/src/ranuts/utils/task.html new file mode 100644 index 0000000000..0ad99e9433 --- /dev/null +++ b/src/ranuts/utils/task.html @@ -0,0 +1,55 @@ + + + + + + Statistical execution time | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    Statistical execution time

    Sometimes, we need statistics on the execution time of a function to analyze performance. Therefore, the 'startTask' and 'taskEnd' functions are wrapped. Three other statistical methods are also introduced

    1. new Date().getTime(),
    2. console.time() , console.timeEnd(),
    3. performance.now()

    一.startTask,taskEnd

    1.startTask

    Execute before the task begins

    Return

    参数说明类型
    taskId任务标识unique symbol

    2.taskEnd

    任务结束的时候执行,需要传入startTask返回的任务标识

    Options

    参数说明类型默认值
    taskId任务标识unique symbol 无默认值,参数必传,否则无法识别是哪个任务

    Return

    参数说明类型
    timetask执行的时间number

    3.使用例子

    js
    const taskId = startTask();
    +
    +// do something
    +
    +const time = taskEnd(taskId);
    +
    +console.log('task 执行花费的时间', time);

    二.new Date().getTime()

    new Date().getTime() 返回一个数值,表示从 1970 年 1 月 1 日 0 时 0 分 0 秒(UTC,即协调世界时)距离该日期对象所代表时间的毫秒数。用来计算 JS 执行时间会有两个问题:

    1. 某些情况下,毫秒级精度可能不够。
    2. new Date() 解析的时间在不同浏览器,或者不同设备上可能并不一致。MDN 说明

      由于浏览器之间的差异与不一致性,强烈不推荐使用 Date 构造函数来解析日期字符串 (或使用与其等价的 Date.parse)。对 RFC 2822 格式的日期仅有约定俗成的支持。对 ISO 8601 格式的支持中,仅有日期的串 (例如 "1970-01-01") 会被处理为 UTC 而不是本地时间,与其他格式的串的处理不同。

    三.console.time(), console.timeEnd()

    启动一个计时器来跟踪某一个操作的占用时长。每一个计时器必须拥有唯一的名字,页面中最多能同时运行 10,000 个计时器。当以此计时器名字为参数调用 console.timeEnd() 时,浏览器将以毫秒为单位,输出对应计时器所经过的时间。比起new Date().getTime(),统计时间更加精确,可以统计到 0.001 毫秒(比如:0.134ms)

    四.performance.now()

    performance.now()返回的时间精度最高可达微秒级,且不会受到系统时间的影响(系统时钟可能会被手动调整或被 NTP 等软件篡改)。另外,performance.timing.navigationStart + performance.now() 约等于 Date.now()。因此对于统计 JS 执行耗时方面,更推荐使用performance.now()

    注意:为了提供对定时攻击和指纹的保护,performance.now() 的精度可能会根据浏览器的设置而被舍弃。 在 Firefox 中,privacy.reduceTimerPrecision 偏好是默认启用的,默认值为 1ms。可以启用 privacy.resistFingerprinting 这将精度改为 100ms 或privacy.resistFingerprinting.reduceTimerPrecision.microseconds 的值,以较大者为准。

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git "a/src/types/TS\347\261\273\345\236\213.html" "b/src/types/TS\347\261\273\345\236\213.html" new file mode 100644 index 0000000000..db987fb92a --- /dev/null +++ "b/src/types/TS\347\261\273\345\236\213.html" @@ -0,0 +1,96 @@ + + + + + + TypeScript 类型系统中的类型 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    TypeScript 类型系统中的类型

    1. 基本类型: number、boolean、string、object、bigint、symbol、undefined、null
    2. 复合类型: class、Array、元组(Tuple)、接口(Interface)、枚举(Enum)
    3. 特殊的类型:void、never、any、unknown

    Tuple

    元组(Tuple)就是元素个数和类型固定的数组类型:

    ts
    type Tuple = [number, string];

    Interface

    接口(Interface)可以描述函数、对象、构造器的结构:

    • 对象
    ts
    interface IPerson {
    +  name: string;
    +  age: number;
    +}
    +
    +class Person implements IPerson {
    +  name: string;
    +  age: number;
    +}
    +
    +const obj: IPerson = {
    +  name: 'name',
    +  age: 18,
    +};
    • 函数
    ts
    interface SayHello {
    +  (name: string): string;
    +}
    +
    +const func: SayHello = (name: string) => {
    +  return 'hello,' + name;
    +};
    • 构造器
    ts
    interface PersonConstructor {
    +  new (name: string, age: number): IPerson;
    +}
    +
    +function createPerson(ctor: PersonConstructor): IPerson {
    +  return new ctor('name', 18);
    +}

    对象类型、class 类型在 TypeScript 里也叫做索引类型,也就是索引了多个元素的类型的意思。对象可以动态添加属性,如果不知道会有什么属性,可以用可索引签名:

    ts
    interface IPerson {
    +  [prop: string]: string | number;
    +}
    +const obj: IPerson = {};
    +obj.name = 'name';
    +obj.age = 18;

    Enum

    枚举(Enum)是一系列值的复合:

    ts
    enum Transpiler {
    +  Babel = 'babel',
    +  Postcss = 'postcss',
    +  Terser = 'terser',
    +  Prettier = 'prettier',
    +  TypeScriptCompiler = 'tsc',
    +}
    +
    +const transpiler = Transpiler.TypeScriptCompiler;

    此外,TypeScript 还支持字面量类型,也就是类似 1111、'aaaa'、{ a: 1} 这种值也可以做为类型。

    其中,字符串的字面量类型有两种,一种是普通的字符串字面量,比如 'aaa',另一种是模版字面量,比如 aaa${string},它的意思是以 aaa 开头,后面是任意 string 的字符串字面量类型。

    所以想要约束以某个字符串开头的字符串字面量类型时可以这样写:

    ts
    function func(str: `#${string}`) {}
    +
    +func('aaa'); // error
    +
    +func('#aaa'); // true

    void

    代表空,可以是 undefined 或 never。

    never

    代表不可达,比如函数抛异常的时候,返回值就是 never。

    any

    是任意类型,任何类型都可以赋值给它,它也可以赋值给任何类型(除了 never)。

    unknown

    是未知类型,任何类型都可以赋值给它,但是它不可以赋值给别的类型。

    类型的装饰

    除了描述类型的结构外,TypeScript 的类型系统还支持描述类型的属性,比如是否可选,是否只读等:

    ts
    interface IPerson {
    +  readonly name: string;
    +  age?: number;
    +}
    +
    +type tuple = [string, number?];

    Last updated:

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git "a/src/types/\346\250\241\345\274\217\345\214\271\351\205\215.html" "b/src/types/\346\250\241\345\274\217\345\214\271\351\205\215.html" new file mode 100644 index 0000000000..9f46ed20a1 --- /dev/null +++ "b/src/types/\346\250\241\345\274\217\345\214\271\351\205\215.html" @@ -0,0 +1,59 @@ + + + + + + 模式匹配 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    模式匹配

    Typescript 的类型也同样可以做模式匹配。

    比如这样一个 Promise 类型:

    ts
    type p = Promise<'value'>;

    我们想提取 value 的类型,可以这样做:

    ts
    type GetPromiseValue<T> = T extends Promise<infer value> ? value : never;

    通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取的,通过 infer 声明一个局部变量 Value 来保存,如果匹配,就返回匹配到的 Value,否则就返回 never 代表没匹配到。

    ts
    type result = GetPromiseValue<Promise<'name'>>; // name

    数组类型

    数组类型想提取第一个元素的类型怎么做呢?

    ts
    type arr = [1, 2, 3];

    用它来匹配一个模式类型,提取第一个元素的类型到通过 infer 声明的局部变量里返回。

    ts
    type GetArrayFirstItem<T extends unknown[]> = T extends [infer value, ...unknown[]] ? value : never;

    类型参数 Arr 通过 extends 约束为只能是数组类型,数组元素是 unknown 也就是可以是任何值。

    any 和 unknown 的区别: any 和 unknown 都代表任意类型,但是 unknown 只能接收任意类型的值,而 any 除了可以接收任意类型的值,也可以赋值给任意类型(除了 never)。类型体操中经常用 unknown 接受和匹配任何类型,而很少把任何类型赋值给某个类型变量。

    对 Arr 做模式匹配,把我们要提取的第一个元素的类型放到通过 infer 声明的 First 局部变量里,后面的元素可以是任何类型,用 unknown 接收,然后把局部变量 First 返回。

    当类型参数 Arr 为 [1,2,3] 时:

    ts
    type result = GetArrayFirstItem<[1, 2, 3]>; // 1

    当类型参数 Arr 为 [] 时:

    ts
    type result = GetArrayFirstItem<[]>; // never

    可以提取第一个元素,当然也可以提取最后一个元素,修改下模式类型就行:

    ts
    type GetArrayLastItem<T extends unknown[]> = T extends [...unknown[],inter L] ? L : never

    我们分别取了首尾元素,当然也可以取剩余的数组,比如取去掉了最后一个元素的数组:

    ts
    type Pop<T extends unknown[]> = T extends [] ? [] : T extends [...infer Rest, unknown] ? Rest : never;

    如果是空数组,就直接返回,否则匹配剩余的元素,放到 infer 声明的局部变量 Rest 里,返回 Rest。

    当类型参数 Arr 为 [1,2,3] 时:

    ts
    type Result = Pop<[1, 2, 3]>; // [1,2]

    当类型参数 Arr 为 [] 时:

    ts
    type Result = Pop<[]>; // []

    同理可得 ShiftArr 的实现:

    ts
    type Shift<T extends unknown[]> = T extends [] ? [] : T extends [unknown, ...infer Rest] ? Rest : never;

    字符串类型也同样可以做模式匹配,匹配一个模式字符串,把需要提取的部分放到 infer 声明的局部变量里。

    判断字符串是否以某个前缀开头,也是通过模式匹配:

    ts
    type StartWidth<S extends string, P extends string> = S extends `${P}${string}` ? true : false;

    需要声明字符串 Str、匹配的前缀 Prefix 两个类型参数,它们都是 string。

    用 Str 去匹配一个模式类型,模式类型的前缀是 Prefix,后面是任意的 string,如果匹配返回 true,否则返回 false。

    字符串可以匹配一个模式类型,提取想要的部分,自然也可以用这些再构成一个新的类型。

    比如实现字符串替换:

    ts
    type Replace<S extends string, F extends string, T extends string> = S extends `${infer P}${F}${infer L}`
    +  ? `${P}${T}${L}`
    +  : S;

    声明要替换的字符串 Str、待替换的字符串 From、替换成的字符串 3 个类型参数,通过 extends 约束为都是 string 类型。

    用 Str 去匹配模式串,模式串由 From 和之前之后的字符串构成,把之前之后的字符串放到通过 infer 声明的局部变量 Prefix、Suffix 里。

    用 Prefix、Suffix 加上替换到的字符串 To 构造成新的字符串类型返回。

    Trim

    能够匹配和替换字符串,那也就能实现去掉空白字符的 Trim:

    不过因为我们不知道有多少个空白字符,所以只能一个个匹配和去掉,需要递归。

    先实现 TrimRight:

    ts
    type TrimRight<S extends string> = S extends `${infer Rest}${' ' | '\n' | '\t'}` ? TrimRight<Rest> : S;

    类型参数 Str 是要 Trim 的字符串。

    如果 Str 匹配字符串 + 空白字符 (空格、换行、制表符),那就把字符串放到 infer 声明的局部变量 Rest 里。

    把 Rest 作为类型参数递归 TrimRight,直到不匹配,这时的类型参数 Str 就是处理结果。

    同理可得 TrimLeft:

    ts
    type TrimLeft<S extends string> = S extends `${' ' | '\n' | '\t'}${infer Rest}` ? TrimLeft<Rest> : S;

    TrimRight 和 TrimLeft 结合就是 Trim:

    ts
    type Trim<S extends string> = TrimLeft<TrimRight<S>>;

    函数

    函数同样也可以做类型匹配,比如提取参数、返回值的类型。

    GetParameters

    函数类型可以通过模式匹配来提取参数的类型:

    ts
    type GetParameters<T extends Function> = T extends (...args: infer A) => unknown ? A : never;

    类型参数 Func 是要匹配的函数类型,通过 extends 约束为 Function。

    Func 和模式类型做匹配,参数类型放到用 infer 声明的局部变量 Args 里,返回值可以是任何类型,用 unknown。

    返回提取到的参数类型 Args。

    GetReturnType

    ts
    type GetReturnType<T extends Function> = T extends (...args: unknown[]) => infer R ? R : never;

    Func 和模式类型做匹配,提取返回值到通过 infer 声明的局部变量 ReturnType 里返回。

    参数类型可以是任意类型,也就是 any[](注意,这里不能用 unknown,这里的解释涉及到参数的逆变性质,具体原因逆变那一节会解释)。

    GetThisParameterType

    方法里可以调用 this,用对象.方法名的方式调用的时候,this 就指向那个对象。

    但是方法也可以用 call 或者 apply 调用,call 调用的时候,this 就变了,但这里却没有被检查出来 this 指向的错误。

    这里的 this 类型同样也可以通过模式匹配提取出来:

    ts
    type GetThisParameterType<T extends Function> = T extends (this: infer H, ...args: unknown[]) => unknown ? H : unknown;

    构造器

    构造器和函数的区别是,构造器是用于创建对象的,所以可以被 new。

    同样,我们也可以通过模式匹配提取构造器的参数和返回值的类型:

    GetInstanceType

    构造器类型可以用 interface 声明,使用 new(): xx 的语法。

    ts
    interface Person {
    +  name: string;
    +}
    +
    +interface PersonConstructor {
    +  new (name: string): Person;
    +}

    这里的 PersonConstructor 返回的是 Person 类型的实例对象,这个也可以通过模式匹配取出来。

    ts
    type GetInstanceType<C extends new (...args: unknown[]) => unknown> = C extends new (...args: unknown[]) => infer T
    +  ? T
    +  : unknown;

    Last updated:

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git "a/src/types/\347\261\273\345\236\213\350\277\220\347\256\227.html" "b/src/types/\347\261\273\345\236\213\350\277\220\347\256\227.html" new file mode 100644 index 0000000000..bb756b7b18 --- /dev/null +++ "b/src/types/\347\261\273\345\236\213\350\277\220\347\256\227.html" @@ -0,0 +1,75 @@ + + + + + + TypeScript 类型系统中的类型运算 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    TypeScript 类型系统中的类型运算

    条件:extends ? :

    TypeScript 里的条件判断是 extends ? :,叫做条件类型(Conditional Type)比如:

    ts
    type isTwo<T> = T extends 2 ? true : false;
    +
    +type res = isTwo<1>; // true
    +type res2 = isTwo<2>; // false

    这种类型也叫做高级类型。

    高级类型的特点是传入类型参数,经过一系列类型运算逻辑后,返回新的类型。

    推导:infer

    如何提取类型的一部分呢?答案是 infer。

    比如提取元组类型的第一个元素:

    ts
    type FirstTupleItem<Tuple extends unknown[]> = Tuple extends [infer T, ...inter R] ? T : never;
    +
    +type res = First<[1,2,3]> // 1

    注意,第一个 extends 不是条件,条件类型是 extends ? :,这里的 extends 是约束的意思,也就是约束类型参数只能是数组类型。

    因为不知道数组元素的具体类型,所以用 unknown。

    联合:|

    联合类型(Union)类似 js 里的或运算符 |,但是作用于类型,代表类型可以是几个类型之一。

    ts
    type Union = 1 | 2 | 3;

    交叉:&

    交叉类型(Intersection)类似 js 中的与运算符 &,但是作用于类型,代表对类型做合并。

    ts
    type ObjType = { a: number } & { c: boolean };

    注意,同一类型可以合并,不同的类型没法合并,会被舍弃:

    ts
    type res = 'a' & 2; // never

    映射类型

    对象、class 在 TypeScript 对应的类型是索引类型(Index Type),那么如何对索引类型作修改呢?

    答案是映射类型。

    ts
    type MapType<T> = {
    +  [key in keyof T]?: T[key];
    +};

    keyof T 是查询索引类型中所有的索引,叫做索引查询。

    T[Key] 是取索引类型某个索引的值,叫做索引访问。

    in 是用于遍历联合类型的运算符。

    比如我们把一个索引类型的值变成 3 个元素的数组:

    ts
    type MapToArray<T> = {
    +  [key in keyof T]: [T[key], T[key], T[key]];
    +};
    +
    +// example:
    +
    +type res = MapToArray<{ a: 1; b: 2 }>;
    +// type res = {
    +//     a:[1,1,1]
    +//     b:[2,2,2]
    +// }

    映射类型就相当于把一个集合映射到另一个集合,这是它名字的由来。

    除了值可以变化,索引也可以做变化,用 as 运算符,叫做重映射。

    ts
    type MapTypeFixKey<T> = {
    +  [key in keyof T as `${key & string}${key & string}${key & string}`]: [T[key], T[key], T[key]];
    +};
    +// example:
    +
    +type res = MapToArray<{ a: 1; b: 2 }>;
    +// type res = {
    +//     aaa:[1,1,1]
    +//     bbb:[2,2,2]
    +// }

    这里的 & string 可能大家会迷惑,解释一下:

    因为索引类型(对象、class 等)可以用 string、number 和 symbol 作为 key,这里 keyof T 取出的索引就是 string | number | symbol 的联合类型,和 string 取交叉部分就只剩下 string 了。就像前面所说,交叉类型会把同一类型做合并,不同类型舍弃。

    因为 js 处理对象比较多,所以索引类型的映射比较重要。

    Last updated:

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git "a/src/types/\351\253\230\347\272\247\347\261\273\345\236\213.html" "b/src/types/\351\253\230\347\272\247\347\261\273\345\236\213.html" new file mode 100644 index 0000000000..af897bc66d --- /dev/null +++ "b/src/types/\351\253\230\347\272\247\347\261\273\345\236\213.html" @@ -0,0 +1,49 @@ + + + + + + TypeScript 内置的高级类型 | ran + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Skip to content

    TypeScript 内置的高级类型

    Parameters

    Parameters 用于提取函数类型的参数类型。

    ReturnType

    ReturnType 用于提取函数类型的返回值类型。

    ConstructorParameters

    构造器类型和函数类型的区别就是可以被 new。

    Parameters 用于提取函数参数的类型,而 ConstructorParameters 用于提取构造器参数的类型。

    InstanceType

    提取了构造器参数的类型,自然也可以提取构造器返回值的类型,就是 InstanceType。

    ThisParameterType

    OmitThisParameter

    Partial

    Required

    Readonly

    Pick

    Record

    Exclude

    Extract

    Omit

    Awaited

    NonNullable

    Uppercase

    Lowercase

    Capitalize

    Uncapitalize

    总结

    比如用模式匹配可以实现:Parameters、ReturnType、ConstructorParameters、InstanceType、ThisParameterType。

    用模式匹配 + 重新构造可以实现:OmitThisParameter

    用重新构造可以实现:Partial、Required、Readonly、Pick、Record

    用模式匹配 + 递归可以实现: Awaited

    用联合类型在分布式条件类型的特性可以实现: Exclude

    此外还有 NonNullable 和四个编译器内部实现的类型:Uppercase、Lowercase、Capitalize、Uncapitalize。

    Last updated:

    Released under the MIT License.

    + + + + \ No newline at end of file diff --git a/sw1726551022.js b/sw1726551022.js new file mode 100644 index 0000000000..6be3cc8020 --- /dev/null +++ b/sw1726551022.js @@ -0,0 +1,918 @@ +const SERVICE_WORK_CACHE_FILE_PATHS = [ +"/ran/src/types/高级类型.html", +"/ran/src/types/类型运算.html", +"/ran/src/types/模式匹配.html", +"/ran/src/types/TS类型.html", +"/ran/src/article/javascript/domLoad.html", +"/ran/src/article/typescript/calculate.html", +"/ran/src/article/typescript/recursion.html", +"/ran/src/article/typescript/pattern.html", +"/ran/src/article/typescript/unionType.html", +"/ran/src/article/typescript/index.html", +"/ran/src/article/typescript/reconstruction.html", +"/ran/src/article/babel.html", +"/ran/src/article/designMode.html", +"/ran/src/article/sort/bucket/index.html", +"/ran/src/article/sort/heap/index.html", +"/ran/src/article/sort/insert/index.html", +"/ran/src/article/sort/radix/index.html", +"/ran/src/article/sort/bubble/index.html", +"/ran/src/article/sort/merge/index.html", +"/ran/src/article/sort/select/index.html", +"/ran/src/article/sort/count/index.html", +"/ran/src/article/sort/index.html", +"/ran/src/article/sort/shell/index.html", +"/ran/src/article/sort/quick/index.html", +"/ran/src/article/bundle.html", +"/ran/src/article/functionalProgramming.html", +"/ran/src/article/astParse/tokenizer.html", +"/ran/src/article/imagemin.html", +"/ran/src/ranuts/utils/filterObj.html", +"/ran/src/ranuts/utils/task.html", +"/ran/src/ranuts/utils/str2xml.html", +"/ran/src/ranuts/utils/convertImageToBase64.html", +"/ran/src/ranuts/utils/getCookie.html", +"/ran/src/ranuts/utils/formatJson.html", +"/ran/src/ranuts/utils/ocr.html", +"/ran/src/ranuts/bundler/index.html", +"/ran/src/ranuts/mimeType/mimeType.html", +"/ran/src/ranuts/mode/subscribe.html", +"/ran/src/ranuts/index.html", +"/ran/src/ranuts/binaryTree/index.html", +"/ran/src/ranuts/file/readFile.html", +"/ran/src/ranuts/file/writeFile.html", +"/ran/src/ranuts/file/fileInfo.html", +"/ran/src/ranuts/file/readDir.html", +"/ran/src/ranuts/file/watchFile.html", +"/ran/src/ranuts/file/appendFile.html", +"/ran/src/ranui/checkbox/index.html", +"/ran/src/ranui/input/index.html", +"/ran/src/ranui/loading/index.html", +"/ran/src/ranui/image/index.html", +"/ran/src/ranui/tabs/index.html", +"/ran/src/ranui/icon/index.html", +"/ran/src/ranui/math/index.html", +"/ran/src/ranui/player/index.html", +"/ran/src/ranui/modal/index.html", +"/ran/src/ranui/button/index.html", +"/ran/src/ranui/popover/index.html", +"/ran/src/ranui/message/index.html", +"/ran/src/ranui/progress/index.html", +"/ran/src/ranui/tab/index.html", +"/ran/src/ranui/select/index.html", +"/ran/src/ranui/preview/index.html", +"/ran/src/ranui/index.html", +"/ran/src/ranui/radar/index.html", +"/ran/src/ranui/skeleton/index.html", +"/ran/icon_72.png", +"/ran/404.html", +"/ran/home.svg", +"/ran/assets/Statement.9lGuRes5.jpeg", +"/ran/assets/src_ranui_select_index.md.BX7CAaZq.lean.js", +"/ran/assets/src_article_typescript_unionType.md.BIrMmR2O.js", +"/ran/assets/cn_src_article_sort_count_index.md.DO0Khq-9.js", +"/ran/assets/src_article_typescript_index.md.SzJeg7Vl.js", +"/ran/assets/cn_src_note_ubuntu.md.C-U8psaC.lean.js", +"/ran/assets/cn_src_types_TS类型.md.BoPQGs5F.js", +"/ran/assets/inter-roman-greek.BBVDIX6e.woff2", +"/ran/assets/cn_src_article_systemDesign.md.DXbjsTs-.lean.js", +"/ran/assets/extra.Da45cF33.jpeg", +"/ran/assets/src_ranui_popover_index.md.BCOhVsiF.lean.js", +"/ran/assets/src_article_sort_bubble_index.md.fAtbvQz_.js", +"/ran/assets/cn_src_ranuts_binaryTree_index.md.1nqizYW3.lean.js", +"/ran/assets/src_types_高级类型.md.C4cnhLAB.js", +"/ran/assets/cn_src_types_类型运算.md.y4F25ckq.lean.js", +"/ran/assets/export.ne8l5ppO.jpeg", +"/ran/assets/cn_src_ranuts_mimeType_mimeType.md.B8my7NSy.js", +"/ran/assets/bili_demo_url.BQDGtHUp.webp", +"/ran/assets/src_types_模式匹配.md.Dp3VrzqR.lean.js", +"/ran/assets/cn_src_ranui_radar_index.md.K6NP370R.js", +"/ran/assets/cn_src_article_sort_insert_index.md.D8ChYRq6.js", +"/ran/assets/src_ranui_button_index.md.DhP8rReR.js", +"/ran/assets/src_ranui_preview_index.md.Ky1AiWNQ.js", +"/ran/assets/src_article_sort_shell_index.md.BefIpHA6.js", +"/ran/assets/ms_ppt.C2zYd_IC.webp", +"/ran/assets/cn_src_ranui_modal_index.md.Bl-bNDpJ.js", +"/ran/assets/cn_src_article_imagemin.md.Eq8Sl5vS.lean.js", +"/ran/assets/src_ranui_tabs_index.md.DL4ch3vN.js", +"/ran/assets/cn_src_article_sort_index.md.B1KerO70.js", +"/ran/assets/inter-italic-cyrillic.By2_1cv3.woff2", +"/ran/assets/bilibili_video_code.DgWtgAEf.webp", +"/ran/assets/src_article_bundle.md.CFyB1OVU.js", +"/ran/assets/cn_src_ranuts_file_readDir.md.C8qesA-s.lean.js", +"/ran/assets/src_ranuts_utils_str2xml.md.DUodO238.lean.js", +"/ran/assets/抽象工厂.DlwNEriZ.png", +"/ran/assets/享元.EIifVVTy.png", +"/ran/assets/src_ranuts_file_watchFile.md.DibbbSlI.js", +"/ran/assets/适配器.C2VH4lXy.png", +"/ran/assets/cn_src_article_functionalProgramming.md.XTLIxuFQ.js", +"/ran/assets/cn_src_article_javascript_domLoad.md.CX-aoztf.lean.js", +"/ran/assets/File.BiH2GpuW.jpeg", +"/ran/assets/import.BTsVI5Tc.jpeg", +"/ran/assets/src_article_sort_radix_index.md.hf3O4ngq.lean.js", +"/ran/assets/src_article_sort_index.md.DZ3i3D2R.js", +"/ran/assets/cn_src_ranui_modal_index.md.Bl-bNDpJ.lean.js", +"/ran/assets/xgplayer_docs.CpHb1Wan.webp", +"/ran/assets/inter-roman-latin.Di8DUHzh.woff2", +"/ran/assets/cn_src_ranui_loading_index.md.C0qf8XCk.lean.js", +"/ran/assets/src_ranuts_file_readFile.md.CVYw5eyB.js", +"/ran/assets/cn_src_article_typescript_calculate.md.C_dGguN1.lean.js", +"/ran/assets/src_article_designMode.md.-Ql_1mMt.lean.js", +"/ran/assets/src_article_sort_count_index.md.DvPhDLiz.lean.js", +"/ran/assets/cn_src_ranuts_utils_getCookie.md.BFqNwYBM.lean.js", +"/ran/assets/ow365.CXWyYekS.webp", +"/ran/assets/cn_src_ranuts_utils_ocr.md.aSDPltJI.js", +"/ran/assets/cn_src_article_sort_heap_index.md.DUTc1Z1Q.js", +"/ran/assets/cn_src_article_typescript_unionType.md.BTONe5Yt.lean.js", +"/ran/assets/cn_src_ranui_popover_index.md.CVPFx-rd.js", +"/ran/assets/cn_src_ranuts_file_readFile.md.-SzOLham.lean.js", +"/ran/assets/heap.D4myjC6C.gif", +"/ran/assets/src_article_sort_bucket_index.md.BhE2wW4O.js", +"/ran/assets/src_ranuts_utils_filterObj.md.CQHmrklO.js", +"/ran/assets/bubble.Csp5B4TH.gif", +"/ran/assets/cn_src_ranui_preview_index.md.DI-R6RxP.js", +"/ran/assets/状态.Bt_a2OKX.png", +"/ran/assets/src_article_sort_insert_index.md.CPhWGrRG.js", +"/ran/assets/src_article_designMode.md.-Ql_1mMt.js", +"/ran/assets/wps_office.DiET-U8x.webp", +"/ran/assets/ali_doc.CYo30EHy.webp", +"/ran/assets/src_ranui_index.md.D31LFnZe.js", +"/ran/assets/ms_answer.Cgv6ylFF.webp", +"/ran/assets/cn_src_ranui_skeleton_index.md.D7wv1w9E.lean.js", +"/ran/assets/cn_src_ranuts_bundler_index.md.dO9RE_ls.js", +"/ran/assets/cn_src_article_sort_radix_index.md.DIqt5q7a.lean.js", +"/ran/assets/index.md.DiiJHNTD.js", +"/ran/assets/inter-italic-vietnamese.BSbpV94h.woff2", +"/ran/assets/cn_src_ranui_player_index.md.BPeeUAmI.js", +"/ran/assets/cn_src_ranuts_utils_getCookie.md.BFqNwYBM.js", +"/ran/assets/Literal.Dl-JxujV.jpeg", +"/ran/assets/src_types_高级类型.md.C4cnhLAB.lean.js", +"/ran/assets/src_article_typescript_recursion.md.Vf30DC2k.js", +"/ran/assets/cn_src_ranui_image_index.md.Dw0AwGab.lean.js", +"/ran/assets/index.md.DiiJHNTD.lean.js", +"/ran/assets/src_types_模式匹配.md.Dp3VrzqR.js", +"/ran/assets/src_ranuts_utils_str2xml.md.DUodO238.js", +"/ran/assets/src_ranui_checkbox_index.md.Bp6CThLb.js", +"/ran/assets/src_ranui_message_index.md.DywEIh7C.lean.js", +"/ran/assets/firefox_support_media.BLmSeBNy.webp", +"/ran/assets/src_article_sort_bubble_index.md.fAtbvQz_.lean.js", +"/ran/assets/inter-italic-latin.C2AdPX0b.woff2", +"/ran/assets/src_ranui_tabs_index.md.DL4ch3vN.lean.js", +"/ran/assets/src_ranui_progress_index.md.Cm1y50UG.js", +"/ran/assets/src_article_sort_insert_index.md.CPhWGrRG.lean.js", +"/ran/assets/cn_src_article_sort_index.md.B1KerO70.lean.js", +"/ran/assets/cn_src_article_typescript_recursion.md.DiOAHp83.lean.js", +"/ran/assets/src_ranui_modal_index.md.B-J1TEAz.js", +"/ran/assets/video_format.CRMCTmKB.webp", +"/ran/assets/cn_src_ranuts_file_fileInfo.md.BovJRTqz.js", +"/ran/assets/cn_src_article_babel.md.Bv2kTzb8.js", +"/ran/assets/src_article_bundle.md.CFyB1OVU.lean.js", +"/ran/assets/bundle.bky0NmdF.png", +"/ran/assets/cn_src_article_functionalProgramming.md.XTLIxuFQ.lean.js", +"/ran/assets/cn_src_ranuts_utils_str2xml.md.CxozQof2.js", +"/ran/assets/src_ranuts_index.md.BsUA76mi.js", +"/ran/assets/cn_src_article_typescript_unionType.md.BTONe5Yt.js", +"/ran/assets/count.CWSWBe_h.gif", +"/ran/assets/src_article_babel.md.C7cpU5Uf.lean.js", +"/ran/assets/google_doc_view.BknjnOKw.webp", +"/ran/assets/cn_src_ranuts_index.md.DE29xbkU.lean.js", +"/ran/assets/merge.Bguw-KQu.gif", +"/ran/assets/cn_src_ranuts_utils_str2xml.md.CxozQof2.lean.js", +"/ran/assets/src_ranui_math_index.md.C-RA_nK7.lean.js", +"/ran/assets/src_ranuts_file_fileInfo.md.CfdtUkZ-.js", +"/ran/assets/cn_src_ranuts_mimeType_mimeType.md.B8my7NSy.lean.js", +"/ran/assets/cn_src_article_bundle.md.B9WVe3Nd.lean.js", +"/ran/assets/src_article_imagemin.md.DTz2O7QV.js", +"/ran/assets/继承.Dta6_xdc.png", +"/ran/assets/red_book.DiBEvryP.webp", +"/ran/assets/inter-italic-greek-ext.1u6EdAuj.woff2", +"/ran/assets/cn_src_note_centos.md.BW5LCWPK.lean.js", +"/ran/assets/style.Cbu_rzqE.css", +"/ran/assets/src_article_sort_quick_index.md.tGhXdyib.lean.js", +"/ran/assets/radix.Bwrylu8F.gif", +"/ran/assets/解释器.DymUKGTa.jpg", +"/ran/assets/src_ranui_modal_index.md.B-J1TEAz.lean.js", +"/ran/assets/complexity.DSLVsjHt.png", +"/ran/assets/ms_file_not.DgOrkG3n.webp", +"/ran/assets/xml.NyzOyhr4.webp", +"/ran/assets/src_ranuts_binaryTree_index.md.1xzpa2sH.js", +"/ran/assets/cn_src_ranui_index.md.tB1QXtFw.lean.js", +"/ran/assets/cn_src_article_sort_bubble_index.md.B1Kqdm5g.lean.js", +"/ran/assets/cn_src_article_typescript_index.md.dV9VtsjJ.js", +"/ran/assets/cn_src_article_sort_select_index.md.CwruXsFa.lean.js", +"/ran/assets/src_ranuts_file_appendFile.md.D4zWKXVA.js", +"/ran/assets/备忘录.meL0YZxn.jpg", +"/ran/assets/src_article_sort_quick_index.md.tGhXdyib.js", +"/ran/assets/src_ranui_button_index.md.DhP8rReR.lean.js", +"/ran/assets/select.B8GwndZy.gif", +"/ran/assets/cn_src_ranui_message_index.md.DDK6JB1T.lean.js", +"/ran/assets/cn_src_ranui_message_index.md.DDK6JB1T.js", +"/ran/assets/cn_src_article_sort_merge_index.md.CywmRCFf.lean.js", +"/ran/assets/src_ranui_tab_index.md.DJ6wHDqA.js", +"/ran/assets/src_ranui_icon_index.md.mkEISxvO.lean.js", +"/ran/assets/src_article_functionalProgramming.md.DSVAXKFw.lean.js", +"/ran/assets/src_ranui_image_index.md.DfDYyZub.js", +"/ran/assets/src_article_imagemin.md.DTz2O7QV.lean.js", +"/ran/assets/src_ranui_input_index.md.DkK2wQig.js", +"/ran/assets/cn_src_ranuts_file_readFile.md.-SzOLham.js", +"/ran/assets/src_article_sort_bucket_index.md.BhE2wW4O.lean.js", +"/ran/assets/sort.CSVZS1AV.png", +"/ran/assets/cn_index.md.Ci9FwTgY.lean.js", +"/ran/assets/src_ranuts_utils_task.md.hnoz85-k.lean.js", +"/ran/assets/cn_src_ranui_checkbox_index.md.tqLDdmuX.lean.js", +"/ran/assets/quick.DD28bswc.gif", +"/ran/assets/cn_src_article_video.md.Dw4RU8dr.lean.js", +"/ran/assets/cn_src_ranui_skeleton_index.md.D7wv1w9E.js", +"/ran/assets/src_types_类型运算.md.4OgLnpMn.lean.js", +"/ran/assets/cn_src_ranui_button_index.md.BKYzspkY.js", +"/ran/assets/src_ranui_image_index.md.DfDYyZub.lean.js", +"/ran/assets/src_ranuts_utils_getCookie.md.CsUkD7RK.js", +"/ran/assets/kkfile_des.CENUMtpY.webp", +"/ran/assets/src_ranui_radar_index.md.B7mPxzli.lean.js", +"/ran/assets/src_article_sort_index.md.DZ3i3D2R.lean.js", +"/ran/assets/src_ranui_radar_index.md.B7mPxzli.js", +"/ran/assets/cn_src_article_designMode.md.Bo9IXX6C.lean.js", +"/ran/assets/cn_src_ranuts_utils_ocr.md.aSDPltJI.lean.js", +"/ran/assets/cn_src_ranuts_file_watchFile.md.C2RD93Hf.js", +"/ran/assets/src_ranui_progress_index.md.Cm1y50UG.lean.js", +"/ran/assets/cn_src_article_docPreview.md.CnTJNdd8.lean.js", +"/ran/assets/src_ranui_loading_index.md.CLsqr9az.lean.js", +"/ran/assets/bilibili_video_m4s.BccuY7bk.webp", +"/ran/assets/ExpressionStatement.zaIHlhIF.jpeg", +"/ran/assets/xdoc.CeowcMPq.webp", +"/ran/assets/外观.Cm0-J0eF.png", +"/ran/assets/cn_src_ranuts_utils_convertImageToBase64.md.BpukE7kU.lean.js", +"/ran/assets/rplayer_demo.CoJ7kuJt.webp", +"/ran/assets/src_ranuts_bundler_index.md.BP7Aetz6.js", +"/ran/assets/src_ranui_select_index.md.BX7CAaZq.js", +"/ran/assets/cn_src_article_sort_bucket_index.md.CkcMkruf.lean.js", +"/ran/assets/cn_src_article_imagemin.md.Eq8Sl5vS.js", +"/ran/assets/cn_src_note_centos.md.BW5LCWPK.js", +"/ran/assets/cn_src_article_typescript_pattern.md.Cyn9ELOY.lean.js", +"/ran/assets/cn_src_article_sort_quick_index.md.BMawD0Bg.lean.js", +"/ran/assets/src_ranuts_utils_convertImageToBase64.md.BbdsPOTo.lean.js", +"/ran/assets/组合.StqZ1pDc.png", +"/ran/assets/cn_src_article_sort_shell_index.md.BjqTtSjT.js", +"/ran/assets/src_ranuts_utils_ocr.md.B-CI4poJ.lean.js", +"/ran/assets/cn_src_ranuts_mode_subscribe.md.DStPx3te.lean.js", +"/ran/assets/src_ranui_math_index.md.C-RA_nK7.js", +"/ran/assets/src_ranuts_mimeType_mimeType.md.BMZ_GsW2.js", +"/ran/assets/safari_support_media.Bafr23bR.webp", +"/ran/assets/src_article_sort_shell_index.md.BefIpHA6.lean.js", +"/ran/assets/cn_src_ranui_tabs_index.md.jexz00Wi.js", +"/ran/assets/cn_src_ranuts_mode_subscribe.md.DStPx3te.js", +"/ran/assets/cn_src_types_高级类型.md.CjvcQW1d.lean.js", +"/ran/assets/src_article_typescript_recursion.md.Vf30DC2k.lean.js", +"/ran/assets/chunks/pdf-Cx0VWKFo.BP4nEulL.js", +"/ran/assets/chunks/warning-circle-DDUgEDIv.1BX6MOiy.js", +"/ran/assets/chunks/warning-circle-fill-lODUKz0i.7RyGfSeR.js", +"/ran/assets/chunks/check-circle-fill-B_pd8ZSs.Dxgzakn4.js", +"/ran/assets/chunks/colz-DJZvo_8B.DBiU5Tau.js", +"/ran/assets/chunks/index-Ba501-HG.DsTDD0-N.js", +"/ran/assets/chunks/message-D36_Zo2l.CR8K3LhI.js", +"/ran/assets/chunks/close-CFnkhudp.IMqD2L1-.js", +"/ran/assets/chunks/select.BGReufCV.js", +"/ran/assets/chunks/loading-Dcc5RApI.D3l74EUI.js", +"/ran/assets/chunks/complexity.CSkvDr7k.js", +"/ran/assets/chunks/home-BUQ4USMk.BqTharGj.js", +"/ran/assets/chunks/radix.CHOmrmB0.js", +"/ran/assets/chunks/close-circle-fill-jSqPPw9i.BsLXh5-a.js", +"/ran/assets/chunks/lock-Cr7BnmWN.0WfYXC2j.js", +"/ran/assets/chunks/extra.Cu56q3CZ.js", +"/ran/assets/chunks/loading-scene-BMc2wqKm.Di19NrRU.js", +"/ran/assets/chunks/info-circle-COnL5bTJ.B9YJorcw.js", +"/ran/assets/chunks/check-circle-szyAJiap.CM_vbBX5.js", +"/ran/assets/chunks/book-nTEFXU2x.DPEdiL1I.js", +"/ran/assets/chunks/merge.D_M4N_iU.js", +"/ran/assets/chunks/insert.Bde3uDH4.js", +"/ran/assets/chunks/loading.vue_vue_type_style_index_0_lang.Da-8gR4I.js", +"/ran/assets/chunks/eye-close-BVr3NJtg.DsdsDDgX.js", +"/ran/assets/chunks/en.Bkn4-Vvy.js", +"/ran/assets/chunks/index-Co9E57uv.BBrTYzuH.js", +"/ran/assets/chunks/bundle.BxrzsuA1.js", +"/ran/assets/chunks/commonjs-dynamic-modules-DLbDWi6a.CRNIONdy.js", +"/ran/assets/chunks/power-off-lQRbiBak.r13EH4bb.js", +"/ran/assets/chunks/katex-es-DoRbtDCO.BDSjlQ-m.js", +"/ran/assets/chunks/theme.CPGewkGm.js", +"/ran/assets/chunks/unlock-CeU74z9n.58atcEuH.js", +"/ran/assets/chunks/sprite-CH2zLtZy.Djo3sTkk.js", +"/ran/assets/chunks/close-circle-CwmuN2C6.D612j4KD.js", +"/ran/assets/chunks/zh-CN.PUkQxDBJ.js", +"/ran/assets/chunks/team-tl4NJXPC.D7881a1v.js", +"/ran/assets/chunks/framework.C-ai2y4t.js", +"/ran/assets/chunks/heap.xduQWyUN.js", +"/ran/assets/chunks/info-circle-fill-CFeVMdci.CUxFtRNn.js", +"/ran/assets/chunks/docx-VUApAnRr.Cl4GUa7G.js", +"/ran/assets/chunks/preview-CJbz9GjO.C8N16-9H.js", +"/ran/assets/chunks/customElements.qitHOM3M.js", +"/ran/assets/chunks/user-B-eVXwuk.DyoYYAjs.js", +"/ran/assets/chunks/shell.CGEkKxrp.js", +"/ran/assets/chunks/add-user-BN1JlY7e.D6YNNzf8.js", +"/ran/assets/chunks/setting-DemlgzVC.DkD4YPwp.js", +"/ran/assets/chunks/bubble.Dg5jgvyl.js", +"/ran/assets/chunks/balanceTree.CCEoBiag.js", +"/ran/assets/chunks/访问者._0swtoJg.js", +"/ran/assets/chunks/jszip.min-BIf20mgf.BsDI-Ugu.js", +"/ran/assets/chunks/index.CBA5mFK_.js", +"/ran/assets/chunks/eye-D_mEt17f.DJFa_ttF.js", +"/ran/assets/chunks/count.CcfK-WL7.js", +"/ran/assets/chunks/pwa-install.es.Bwp47-dV.js", +"/ran/assets/chunks/input-input.MnARRJC6.js", +"/ran/assets/chunks/quick.WcLzRUPH.js", +"/ran/assets/src_ranui_skeleton_index.md.CLg9OTaj.lean.js", +"/ran/assets/cn_src_article_systemDesign.md.DXbjsTs-.js", +"/ran/assets/cn_src_ranui_tab_index.md.D8xqztOz.lean.js", +"/ran/assets/cn_src_article_babel.md.Bv2kTzb8.lean.js", +"/ran/assets/cn_src_ranui_preview_index.md.DI-R6RxP.lean.js", +"/ran/assets/cn_src_ranuts_utils_formatJson.md.DWRR6vH4.js", +"/ran/assets/cn_src_article_visual.md.CDvSxrkl.js", +"/ran/assets/kkfile_doc.CPfEUxoD.webp", +"/ran/assets/cn_src_ranuts_file_readDir.md.C8qesA-s.js", +"/ran/assets/cn_src_article_typescript_index.md.dV9VtsjJ.lean.js", +"/ran/assets/ms_excel.CJXFi2bf.webp", +"/ran/assets/原型.DYbH0CSA.jpg", +"/ran/assets/src_article_functionalProgramming.md.DSVAXKFw.js", +"/ran/assets/src_ranuts_index.md.BsUA76mi.lean.js", +"/ran/assets/cn_src_article_sort_bubble_index.md.B1Kqdm5g.js", +"/ran/assets/src_ranui_message_index.md.DywEIh7C.js", +"/ran/assets/src_article_typescript_reconstruction.md.CPqflY5B.js", +"/ran/assets/src_ranuts_utils_ocr.md.B-CI4poJ.js", +"/ran/assets/src_article_typescript_pattern.md.Cl1kek3_.lean.js", +"/ran/assets/cn_src_article_sort_merge_index.md.CywmRCFf.js", +"/ran/assets/src_ranuts_utils_convertImageToBase64.md.BbdsPOTo.js", +"/ran/assets/src_ranuts_file_readDir.md.D1R8FXwd.lean.js", +"/ran/assets/inter-roman-latin-ext.4ZJIpNVo.woff2", +"/ran/assets/cn_src_ranui_progress_index.md.B8zrCakA.lean.js", +"/ran/assets/src_ranuts_file_watchFile.md.DibbbSlI.lean.js", +"/ran/assets/ms_word.3k-0mjp0.webp", +"/ran/assets/inter-italic-greek.DJ8dCoTZ.woff2", +"/ran/assets/cn_src_ranui_popover_index.md.CVPFx-rd.lean.js", +"/ran/assets/tiktik_video_demo.mxxBzLay.webp", +"/ran/assets/src_article_sort_count_index.md.DvPhDLiz.js", +"/ran/assets/src_ranuts_bundler_index.md.BP7Aetz6.lean.js", +"/ran/assets/inter-italic-cyrillic-ext.r48I6akx.woff2", +"/ran/assets/cn_src_ranui_button_index.md.BKYzspkY.lean.js", +"/ran/assets/cn_src_ranuts_file_appendFile.md.CXY4tbQl.js", +"/ran/assets/inter-italic-latin-ext.CN1xVJS-.woff2", +"/ran/assets/cn_src_ranuts_utils_convertImageToBase64.md.BpukE7kU.js", +"/ran/assets/cn_src_article_visual.md.CDvSxrkl.lean.js", +"/ran/assets/src_ranuts_binaryTree_index.md.1xzpa2sH.lean.js", +"/ran/assets/cn_src_ranui_icon_index.md.IS0pJHCF.js", +"/ran/assets/cn_src_ranuts_utils_filterObj.md.Be8VuZ1x.lean.js", +"/ran/assets/Expression.DczLaznn.jpeg", +"/ran/assets/src_article_sort_radix_index.md.hf3O4ngq.js", +"/ran/assets/src_article_sort_select_index.md.BmIakYmF.lean.js", +"/ran/assets/cn_src_ranui_select_index.md.T7hcvhSo.lean.js", +"/ran/assets/src_types_类型运算.md.4OgLnpMn.js", +"/ran/assets/src_ranuts_utils_task.md.hnoz85-k.js", +"/ran/assets/cn_src_ranuts_index.md.DE29xbkU.js", +"/ran/assets/cn_src_ranui_math_index.md.CaRU3RpB.js", +"/ran/assets/customElements.DbqgaaNb.png", +"/ran/assets/cn_src_types_高级类型.md.CjvcQW1d.js", +"/ran/assets/src_article_sort_merge_index.md.DCFZpDV3.lean.js", +"/ran/assets/cn_src_article_sort_quick_index.md.BMawD0Bg.js", +"/ran/assets/cn_src_ranui_icon_index.md.IS0pJHCF.lean.js", +"/ran/assets/src_article_babel.md.C7cpU5Uf.js", +"/ran/assets/cn_src_ranuts_file_watchFile.md.C2RD93Hf.lean.js", +"/ran/assets/cn_src_article_astParse_tokenizer.md.CPQ5Q4qA.lean.js", +"/ran/assets/src_ranuts_file_readDir.md.D1R8FXwd.js", +"/ran/assets/wps_office_price.ler9htjh.webp", +"/ran/assets/kkfile_output.DD8iZdbo.webp", +"/ran/assets/cn_src_article_designMode.md.Bo9IXX6C.js", +"/ran/assets/src_types_TS类型.md.D-rRgmPu.js", +"/ran/assets/cn_src_note_docker.md.C0hJL26s.js", +"/ran/assets/cn_src_article_sort_radix_index.md.DIqt5q7a.js", +"/ran/assets/src_ranui_preview_index.md.Ky1AiWNQ.lean.js", +"/ran/assets/src_ranui_player_index.md.D9OUB_JI.js", +"/ran/assets/cn_index.md.Ci9FwTgY.js", +"/ran/assets/cn_src_ranui_input_index.md.Ztjdnx-y.js", +"/ran/assets/ts_demo.D_l_mv9k.webp", +"/ran/assets/src_ranui_icon_index.md.mkEISxvO.js", +"/ran/assets/装饰.CuuWN9YK.jpg", +"/ran/assets/cn_src_ranuts_utils_formatJson.md.DWRR6vH4.lean.js", +"/ran/assets/桥接.DX0mO5JC.png", +"/ran/assets/Program.BBf_t-me.jpeg", +"/ran/assets/Comment.BYtNY-L1.jpeg", +"/ran/assets/src_ranuts_file_appendFile.md.D4zWKXVA.lean.js", +"/ran/assets/inter-roman-greek-ext.CqjqNYQ-.woff2", +"/ran/assets/src_article_sort_select_index.md.BmIakYmF.js", +"/ran/assets/策略.BAijEgGz.png", +"/ran/assets/cn_src_article_sort_heap_index.md.DUTc1Z1Q.lean.js", +"/ran/assets/axtexplorer.D7PG-3cx.jpeg", +"/ran/assets/ms_answer_2.D-D9H1v0.webp", +"/ran/assets/inter-roman-cyrillic.C5lxZ8CY.woff2", +"/ran/assets/cn_src_article_javascript_domLoad.md.CX-aoztf.js", +"/ran/assets/Identifier.lJSxyFTe.jpeg", +"/ran/assets/cn_src_ranuts_file_writeFile.md.CbYE9IAV.lean.js", +"/ran/assets/src_ranuts_utils_formatJson.md.s6iqMas3.lean.js", +"/ran/assets/src_article_astParse_tokenizer.md.BdbSK8yK.js", +"/ran/assets/cn_src_ranui_input_index.md.Ztjdnx-y.lean.js", +"/ran/assets/cn_src_article_sort_select_index.md.CwruXsFa.js", +"/ran/assets/aqiyi_demo.s0swGzvF.webp", +"/ran/assets/src_ranuts_file_fileInfo.md.CfdtUkZ-.lean.js", +"/ran/assets/input-input.1X1aE5oH.jpg", +"/ran/assets/cn_src_ranuts_utils_task.md.Nv89-z_1.lean.js", +"/ran/assets/cn_src_article_typescript_reconstruction.md.Bc8ysEy2.js", +"/ran/assets/cn_src_note_ubuntu.md.C-U8psaC.js", +"/ran/assets/cn_src_ranui_tab_index.md.D8xqztOz.js", +"/ran/assets/cn_src_ranuts_utils_filterObj.md.Be8VuZ1x.js", +"/ran/assets/src_article_typescript_reconstruction.md.CPqflY5B.lean.js", +"/ran/assets/cn_src_types_类型运算.md.y4F25ckq.js", +"/ran/assets/cn_src_article_video.md.Dw4RU8dr.js", +"/ran/assets/src_ranuts_utils_filterObj.md.CQHmrklO.lean.js", +"/ran/assets/src_ranui_player_index.md.D9OUB_JI.lean.js", +"/ran/assets/cn_src_ranui_index.md.tB1QXtFw.js", +"/ran/assets/src_ranuts_mode_subscribe.md.Bx_Pjw6l.js", +"/ran/assets/cn_src_ranui_image_index.md.Dw0AwGab.js", +"/ran/assets/cn_src_ranui_math_index.md.CaRU3RpB.lean.js", +"/ran/assets/src_article_sort_merge_index.md.DCFZpDV3.js", +"/ran/assets/cn_src_types_模式匹配.md.CfyGKgqa.js", +"/ran/assets/cn_src_article_typescript_reconstruction.md.Bc8ysEy2.lean.js", +"/ran/assets/src_article_typescript_unionType.md.BIrMmR2O.lean.js", +"/ran/assets/cn_src_ranuts_utils_task.md.Nv89-z_1.js", +"/ran/assets/访问者.aEI4m-5a.png", +"/ran/assets/cn_src_types_模式匹配.md.CfyGKgqa.lean.js", +"/ran/assets/src_ranuts_utils_formatJson.md.s6iqMas3.js", +"/ran/assets/cn_src_article_sort_bucket_index.md.CkcMkruf.js", +"/ran/assets/cn_src_ranui_select_index.md.T7hcvhSo.js", +"/ran/assets/src_ranui_input_index.md.DkK2wQig.lean.js", +"/ran/assets/cn_src_article_sort_count_index.md.DO0Khq-9.lean.js", +"/ran/assets/src_types_TS类型.md.D-rRgmPu.lean.js", +"/ran/assets/src_ranuts_utils_getCookie.md.CsUkD7RK.lean.js", +"/ran/assets/cn_src_types_TS类型.md.BoPQGs5F.lean.js", +"/ran/assets/insert.gf3GhDvq.gif", +"/ran/assets/bili_demo.CI8Ur8IA.webp", +"/ran/assets/src_article_typescript_calculate.md.CaDt8dND.lean.js", +"/ran/assets/src_ranuts_file_writeFile.md.C3kB2EaG.js", +"/ran/assets/src_article_sort_heap_index.md.qYkik3kq.js", +"/ran/assets/cn_src_note_libreoffice2wasm.md.CiwyBD9N.js", +"/ran/assets/cn_src_article_sort_insert_index.md.D8ChYRq6.lean.js", +"/ran/assets/cn_src_article_typescript_pattern.md.Cyn9ELOY.js", +"/ran/assets/cn_src_article_bundle.md.B9WVe3Nd.js", +"/ran/assets/tiktok_video.DuwKyIdt.webp", +"/ran/assets/app.BaY_JH1S.js", +"/ran/assets/src_ranuts_file_readFile.md.CVYw5eyB.lean.js", +"/ran/assets/cn_src_ranuts_file_writeFile.md.CbYE9IAV.js", +"/ran/assets/mdn_pdf.DbNmeC8H.webp", +"/ran/assets/src_article_typescript_calculate.md.CaDt8dND.js", +"/ran/assets/src_ranui_index.md.D31LFnZe.lean.js", +"/ran/assets/cn_src_ranui_tabs_index.md.jexz00Wi.lean.js", +"/ran/assets/src_article_sort_heap_index.md.qYkik3kq.lean.js", +"/ran/assets/src_article_javascript_domLoad.md.C2Dqx2X1.js", +"/ran/assets/inter-roman-vietnamese.BjW4sHH5.woff2", +"/ran/assets/src_ranui_checkbox_index.md.Bp6CThLb.lean.js", +"/ran/assets/cn_src_ranuts_file_appendFile.md.CXY4tbQl.lean.js", +"/ran/assets/cn_src_ranui_loading_index.md.C0qf8XCk.js", +"/ran/assets/src_ranuts_mimeType_mimeType.md.BMZ_GsW2.lean.js", +"/ran/assets/src_article_javascript_domLoad.md.C2Dqx2X1.lean.js", +"/ran/assets/Class.Cx5QD1OX.jpeg", +"/ran/assets/shell.CZ-z1IVg.gif", +"/ran/assets/cn_src_ranui_checkbox_index.md.tqLDdmuX.js", +"/ran/assets/balanceTree.DP_9yIkO.png", +"/ran/assets/cn_src_ranui_radar_index.md.K6NP370R.lean.js", +"/ran/assets/cn_src_note_libreoffice2wasm.md.CiwyBD9N.lean.js", +"/ran/assets/建造者.B6neb_7R.jpeg", +"/ran/assets/kkfile.X1tAqvNa.webp", +"/ran/assets/cn_src_article_sort_shell_index.md.BjqTtSjT.lean.js", +"/ran/assets/src_article_astParse_tokenizer.md.BdbSK8yK.lean.js", +"/ran/assets/cn_src_article_astParse_tokenizer.md.CPQ5Q4qA.js", +"/ran/assets/cn_src_ranuts_bundler_index.md.dO9RE_ls.lean.js", +"/ran/assets/src_ranui_tab_index.md.DJ6wHDqA.lean.js", +"/ran/assets/Declaration.CplvpFd-.jpeg", +"/ran/assets/ms_support.CaZSSiRt.webp", +"/ran/assets/src_ranui_loading_index.md.CLsqr9az.js", +"/ran/assets/cn_src_ranuts_binaryTree_index.md.1nqizYW3.js", +"/ran/assets/cn_src_article_docPreview.md.CnTJNdd8.js", +"/ran/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2", +"/ran/assets/src_ranui_popover_index.md.BCOhVsiF.js", +"/ran/assets/cn_src_ranui_progress_index.md.B8zrCakA.js", +"/ran/assets/cn_src_ranuts_file_fileInfo.md.BovJRTqz.lean.js", +"/ran/assets/src_ranui_skeleton_index.md.CLg9OTaj.js", +"/ran/assets/cn_src_article_typescript_calculate.md.C_dGguN1.js", +"/ran/assets/cn_src_article_typescript_recursion.md.DiOAHp83.js", +"/ran/assets/src_article_typescript_index.md.SzJeg7Vl.lean.js", +"/ran/assets/cn_src_note_docker.md.C0hJL26s.lean.js", +"/ran/assets/单例.B4dKFqxx.jpg", +"/ran/assets/src_ranuts_mode_subscribe.md.Bx_Pjw6l.lean.js", +"/ran/assets/cn_src_ranui_player_index.md.BPeeUAmI.lean.js", +"/ran/assets/src_ranuts_file_writeFile.md.C3kB2EaG.lean.js", +"/ran/assets/src_article_typescript_pattern.md.Cl1kek3_.js", +"/ran/assets/axtexplorerSave.a5hTrvd2.jpeg", +"/ran/assets/firefox_pdf.BWQR-ogn.webp", +"/ran/icon_48.png", +"/ran/icon_144.png", +"/ran/pagefind/pagefind-entry.json", +"/ran/pagefind/pagefind-modular-ui.js", +"/ran/pagefind/pagefind.zh-cn_dcc472e46a518.pf_meta", +"/ran/pagefind/pagefind.en_c73d434e5f.pf_meta", +"/ran/pagefind/pagefind-ui.js", +"/ran/pagefind/pagefind-modular-ui.css", +"/ran/pagefind/wasm.unknown.pagefind", +"/ran/pagefind/pagefind.js", +"/ran/pagefind/pagefind-ui.css", +"/ran/pagefind/index/en_bc39585.pf_index", +"/ran/pagefind/index/zh-cn_28c9eca.pf_index", +"/ran/pagefind/index/zh-cn_e75ebf3.pf_index", +"/ran/pagefind/index/zh-cn_b7a0b84.pf_index", +"/ran/pagefind/index/en_e8e8597.pf_index", +"/ran/pagefind/index/zh-cn_83d69b2.pf_index", +"/ran/pagefind/index/en_d22f299.pf_index", +"/ran/pagefind/index/zh-cn_42b3c8b.pf_index", +"/ran/pagefind/wasm.en.pagefind", +"/ran/pagefind/pagefind-highlight.js", +"/ran/pagefind/fragment/zh-cn_a66a688.pf_fragment", +"/ran/pagefind/fragment/zh-cn_e1f4a79.pf_fragment", +"/ran/pagefind/fragment/en_a116508.pf_fragment", +"/ran/pagefind/fragment/en_1f67d37.pf_fragment", +"/ran/pagefind/fragment/zh-cn_95fa787.pf_fragment", +"/ran/pagefind/fragment/zh-cn_66f42e8.pf_fragment", +"/ran/pagefind/fragment/en_3bf4f84.pf_fragment", +"/ran/pagefind/fragment/zh-cn_f9c4333.pf_fragment", +"/ran/pagefind/fragment/zh-cn_489c27d.pf_fragment", +"/ran/pagefind/fragment/zh-cn_4152685.pf_fragment", +"/ran/pagefind/fragment/en_349bd7e.pf_fragment", +"/ran/pagefind/fragment/zh-cn_c1151c9.pf_fragment", +"/ran/pagefind/fragment/en_9755f3c.pf_fragment", +"/ran/pagefind/fragment/zh-cn_e64f93e.pf_fragment", +"/ran/pagefind/fragment/en_58e1be6.pf_fragment", +"/ran/pagefind/fragment/en_c8893d7.pf_fragment", +"/ran/pagefind/fragment/en_7b5a911.pf_fragment", +"/ran/pagefind/fragment/en_b0cf238.pf_fragment", +"/ran/pagefind/fragment/en_7a4eb73.pf_fragment", +"/ran/pagefind/fragment/zh-cn_cfc7c79.pf_fragment", +"/ran/pagefind/fragment/zh-cn_7d7b75a.pf_fragment", +"/ran/pagefind/fragment/zh-cn_5d1b782.pf_fragment", +"/ran/pagefind/fragment/zh-cn_9968bf4.pf_fragment", +"/ran/pagefind/fragment/en_58cb4c9.pf_fragment", +"/ran/pagefind/fragment/zh-cn_f09c929.pf_fragment", +"/ran/pagefind/fragment/en_2771bf1.pf_fragment", +"/ran/pagefind/fragment/zh-cn_20bbef4.pf_fragment", +"/ran/pagefind/fragment/zh-cn_c82f3b2.pf_fragment", +"/ran/pagefind/fragment/en_27ced55.pf_fragment", +"/ran/pagefind/fragment/zh-cn_6ea83e5.pf_fragment", +"/ran/pagefind/fragment/zh-cn_e6cc6a8.pf_fragment", +"/ran/pagefind/fragment/zh-cn_50313a9.pf_fragment", +"/ran/pagefind/fragment/en_45b0a69.pf_fragment", +"/ran/pagefind/fragment/en_cb594e2.pf_fragment", +"/ran/pagefind/fragment/zh-cn_75a264c.pf_fragment", +"/ran/pagefind/fragment/zh-cn_5bab657.pf_fragment", +"/ran/pagefind/fragment/zh-cn_67d6c7a.pf_fragment", +"/ran/pagefind/fragment/zh-cn_5bc7914.pf_fragment", +"/ran/pagefind/fragment/zh-cn_544fd92.pf_fragment", +"/ran/pagefind/fragment/en_c2a5686.pf_fragment", +"/ran/pagefind/fragment/en_e34b39a.pf_fragment", +"/ran/pagefind/fragment/zh-cn_d98338a.pf_fragment", +"/ran/pagefind/fragment/zh-cn_c4595ab.pf_fragment", +"/ran/pagefind/fragment/en_fba3fcb.pf_fragment", +"/ran/pagefind/fragment/en_7755d1b.pf_fragment", +"/ran/pagefind/fragment/en_229996f.pf_fragment", +"/ran/pagefind/fragment/en_65ccfe9.pf_fragment", +"/ran/pagefind/fragment/zh-cn_e88bc3f.pf_fragment", +"/ran/pagefind/fragment/zh-cn_3de2e5c.pf_fragment", +"/ran/pagefind/fragment/zh-cn_c4a5919.pf_fragment", +"/ran/pagefind/fragment/en_738928a.pf_fragment", +"/ran/pagefind/fragment/zh-cn_7e8750b.pf_fragment", +"/ran/pagefind/fragment/zh-cn_622d568.pf_fragment", +"/ran/pagefind/fragment/en_12451bd.pf_fragment", +"/ran/pagefind/fragment/en_a034a97.pf_fragment", +"/ran/pagefind/fragment/en_b7a3e23.pf_fragment", +"/ran/pagefind/fragment/en_f5a1553.pf_fragment", +"/ran/pagefind/fragment/zh-cn_ac92f78.pf_fragment", +"/ran/pagefind/fragment/en_b1c2dff.pf_fragment", +"/ran/pagefind/fragment/en_91e701d.pf_fragment", +"/ran/pagefind/fragment/zh-cn_5bb9206.pf_fragment", +"/ran/pagefind/fragment/en_39ca4e7.pf_fragment", +"/ran/pagefind/fragment/zh-cn_af6cbe1.pf_fragment", +"/ran/pagefind/fragment/zh-cn_f379427.pf_fragment", +"/ran/pagefind/fragment/en_98546ec.pf_fragment", +"/ran/pagefind/fragment/zh-cn_87504f6.pf_fragment", +"/ran/pagefind/fragment/en_bc653ea.pf_fragment", +"/ran/pagefind/fragment/zh-cn_5df12ef.pf_fragment", +"/ran/pagefind/fragment/zh-cn_c2e89f3.pf_fragment", +"/ran/pagefind/fragment/en_9573fab.pf_fragment", +"/ran/pagefind/fragment/en_33bec34.pf_fragment", +"/ran/pagefind/fragment/zh-cn_e347438.pf_fragment", +"/ran/pagefind/fragment/zh-cn_542bc65.pf_fragment", +"/ran/pagefind/fragment/zh-cn_3e43b1f.pf_fragment", +"/ran/pagefind/fragment/zh-cn_44fa7df.pf_fragment", +"/ran/pagefind/fragment/en_a3a3739.pf_fragment", +"/ran/pagefind/fragment/en_422fcc1.pf_fragment", +"/ran/pagefind/fragment/en_2ac4367.pf_fragment", +"/ran/pagefind/fragment/zh-cn_e41081e.pf_fragment", +"/ran/pagefind/fragment/zh-cn_cfbcb39.pf_fragment", +"/ran/pagefind/fragment/zh-cn_1ec4ddb.pf_fragment", +"/ran/pagefind/fragment/zh-cn_c4f682e.pf_fragment", +"/ran/pagefind/fragment/zh-cn_f83f580.pf_fragment", +"/ran/pagefind/fragment/en_706f2f9.pf_fragment", +"/ran/pagefind/fragment/en_a4a4e1c.pf_fragment", +"/ran/pagefind/fragment/zh-cn_5ca356d.pf_fragment", +"/ran/pagefind/fragment/zh-cn_a7edffe.pf_fragment", +"/ran/pagefind/fragment/en_6a66788.pf_fragment", +"/ran/pagefind/fragment/zh-cn_58279de.pf_fragment", +"/ran/pagefind/fragment/zh-cn_61c329a.pf_fragment", +"/ran/pagefind/fragment/en_1d9d6e5.pf_fragment", +"/ran/pagefind/fragment/en_3f75462.pf_fragment", +"/ran/pagefind/fragment/en_1fd6515.pf_fragment", +"/ran/pagefind/fragment/zh-cn_f7dcce8.pf_fragment", +"/ran/pagefind/fragment/en_106ee7d.pf_fragment", +"/ran/pagefind/fragment/en_7322c43.pf_fragment", +"/ran/pagefind/fragment/en_b2b1326.pf_fragment", +"/ran/pagefind/fragment/en_19ba7e6.pf_fragment", +"/ran/pagefind/fragment/zh-cn_59bdbd3.pf_fragment", +"/ran/pagefind/fragment/en_e8f3a9e.pf_fragment", +"/ran/pagefind/fragment/zh-cn_d32fcee.pf_fragment", +"/ran/pagefind/fragment/en_c24a847.pf_fragment", +"/ran/pagefind/fragment/zh-cn_c551e89.pf_fragment", +"/ran/pagefind/fragment/en_b46590e.pf_fragment", +"/ran/pagefind/fragment/zh-cn_b7b2564.pf_fragment", +"/ran/pagefind/fragment/zh-cn_5190b59.pf_fragment", +"/ran/pagefind/fragment/en_e2846bf.pf_fragment", +"/ran/pagefind/fragment/zh-cn_3fb29d3.pf_fragment", +"/ran/pagefind/fragment/zh-cn_e6b1657.pf_fragment", +"/ran/pagefind/fragment/zh-cn_7355cce.pf_fragment", +"/ran/pagefind/fragment/en_919ab78.pf_fragment", +"/ran/pagefind/fragment/zh-cn_715eacf.pf_fragment", +"/ran/pagefind/fragment/en_b5a7787.pf_fragment", +"/ran/pagefind/fragment/en_27a0b4a.pf_fragment", +"/ran/pagefind/fragment/en_a79eb77.pf_fragment", +"/ran/pagefind/fragment/en_222d98b.pf_fragment", +"/ran/pagefind/fragment/zh-cn_51dafe6.pf_fragment", +"/ran/pagefind/fragment/en_55a7cf9.pf_fragment", +"/ran/pagefind/fragment/en_13157a1.pf_fragment", +"/ran/pagefind/fragment/zh-cn_1f33c04.pf_fragment", +"/ran/pagefind/fragment/zh-cn_32113cf.pf_fragment", +"/ran/pagefind/fragment/zh-cn_5042f4c.pf_fragment", +"/ran/pagefind/fragment/zh-cn_677ff04.pf_fragment", +"/ran/pagefind/fragment/en_dd6246f.pf_fragment", +"/ran/pagefind/fragment/zh-cn_8a3cd5f.pf_fragment", +"/ran/pagefind/fragment/zh-cn_8df5615.pf_fragment", +"/ran/pagefind/fragment/en_ee118c9.pf_fragment", +"/ran/pagefind/fragment/zh-cn_a1e1243.pf_fragment", +"/ran/pagefind/fragment/en_346b990.pf_fragment", +"/ran/pagefind/fragment/zh-cn_539d75f.pf_fragment", +"/ran/pagefind/fragment/en_b5741b3.pf_fragment", +"/ran/pagefind/fragment/en_a8a649f.pf_fragment", +"/ran/pagefind/fragment/en_c485c6f.pf_fragment", +"/ran/pagefind/fragment/en_5ff5133.pf_fragment", +"/ran/pagefind/fragment/zh-cn_0ef213d.pf_fragment", +"/ran/pagefind/fragment/zh-cn_3ad6344.pf_fragment", +"/ran/icon_96.png", +"/ran/ocr/chi_sim.png", +"/ran/ocr/eng.png", +"/ran/screenshots_2560x1440.jpg", +"/ran/screenshots_748x1340.jpg", +"/ran/sw1726551022.js", +"/ran/hashmap.json", +"/ran/icon_168.png", +"/ran/cn/src/types/高级类型.html", +"/ran/cn/src/types/类型运算.html", +"/ran/cn/src/types/模式匹配.html", +"/ran/cn/src/types/TS类型.html", +"/ran/cn/src/article/javascript/domLoad.html", +"/ran/cn/src/article/typescript/calculate.html", +"/ran/cn/src/article/typescript/recursion.html", +"/ran/cn/src/article/typescript/pattern.html", +"/ran/cn/src/article/typescript/unionType.html", +"/ran/cn/src/article/typescript/index.html", +"/ran/cn/src/article/typescript/reconstruction.html", +"/ran/cn/src/article/visual.html", +"/ran/cn/src/article/video.html", +"/ran/cn/src/article/babel.html", +"/ran/cn/src/article/designMode.html", +"/ran/cn/src/article/sort/bucket/index.html", +"/ran/cn/src/article/sort/heap/index.html", +"/ran/cn/src/article/sort/insert/index.html", +"/ran/cn/src/article/sort/radix/index.html", +"/ran/cn/src/article/sort/bubble/index.html", +"/ran/cn/src/article/sort/merge/index.html", +"/ran/cn/src/article/sort/select/index.html", +"/ran/cn/src/article/sort/count/index.html", +"/ran/cn/src/article/sort/index.html", +"/ran/cn/src/article/sort/shell/index.html", +"/ran/cn/src/article/sort/quick/index.html", +"/ran/cn/src/article/systemDesign.html", +"/ran/cn/src/article/bundle.html", +"/ran/cn/src/article/docPreview.html", +"/ran/cn/src/article/functionalProgramming.html", +"/ran/cn/src/article/astParse/tokenizer.html", +"/ran/cn/src/article/imagemin.html", +"/ran/cn/src/ranuts/utils/filterObj.html", +"/ran/cn/src/ranuts/utils/task.html", +"/ran/cn/src/ranuts/utils/str2xml.html", +"/ran/cn/src/ranuts/utils/convertImageToBase64.html", +"/ran/cn/src/ranuts/utils/getCookie.html", +"/ran/cn/src/ranuts/utils/formatJson.html", +"/ran/cn/src/ranuts/utils/ocr.html", +"/ran/cn/src/ranuts/bundler/index.html", +"/ran/cn/src/ranuts/mimeType/mimeType.html", +"/ran/cn/src/ranuts/mode/subscribe.html", +"/ran/cn/src/ranuts/index.html", +"/ran/cn/src/ranuts/binaryTree/index.html", +"/ran/cn/src/ranuts/file/readFile.html", +"/ran/cn/src/ranuts/file/writeFile.html", +"/ran/cn/src/ranuts/file/fileInfo.html", +"/ran/cn/src/ranuts/file/readDir.html", +"/ran/cn/src/ranuts/file/watchFile.html", +"/ran/cn/src/ranuts/file/appendFile.html", +"/ran/cn/src/ranui/checkbox/index.html", +"/ran/cn/src/ranui/input/index.html", +"/ran/cn/src/ranui/loading/index.html", +"/ran/cn/src/ranui/image/index.html", +"/ran/cn/src/ranui/tabs/index.html", +"/ran/cn/src/ranui/icon/index.html", +"/ran/cn/src/ranui/math/index.html", +"/ran/cn/src/ranui/player/index.html", +"/ran/cn/src/ranui/modal/index.html", +"/ran/cn/src/ranui/button/index.html", +"/ran/cn/src/ranui/popover/index.html", +"/ran/cn/src/ranui/message/index.html", +"/ran/cn/src/ranui/progress/index.html", +"/ran/cn/src/ranui/tab/index.html", +"/ran/cn/src/ranui/select/index.html", +"/ran/cn/src/ranui/preview/index.html", +"/ran/cn/src/ranui/index.html", +"/ran/cn/src/ranui/radar/index.html", +"/ran/cn/src/ranui/skeleton/index.html", +"/ran/cn/src/note/ubuntu.html", +"/ran/cn/src/note/docker.html", +"/ran/cn/src/note/libreoffice2wasm.html", +"/ran/cn/src/note/centos.html", +"/ran/cn/index.html", +"/ran/index.html", +"/ran/favicon.ico", +"/ran/hls/example.m3u8", +"/ran/hls/5_1701577771368/5_00003.ts", +"/ran/hls/5_1701577771368/5_00000.ts", +"/ran/hls/5_1701577771368/5_00005.ts", +"/ran/hls/5_1701577771368/5.m3u8", +"/ran/hls/5_1701577771368/5_00001.ts", +"/ran/hls/5_1701577771368/5_00004.ts", +"/ran/hls/5_1701577771368/5.key", +"/ran/hls/5_1701577771368/5_00006.ts", +"/ran/hls/5_1701577771368/5_00002.ts", +"/ran/hls/5_1701577744714/5_00003.ts", +"/ran/hls/5_1701577744714/5_00000.ts", +"/ran/hls/5_1701577744714/5_00005.ts", +"/ran/hls/5_1701577744714/5.m3u8", +"/ran/hls/5_1701577744714/5_00001.ts", +"/ran/hls/5_1701577744714/5_00004.ts", +"/ran/hls/5_1701577744714/5.key", +"/ran/hls/5_1701577744714/5_00006.ts", +"/ran/hls/5_1701577744714/5_00002.ts", +"/ran/icon.png", +"/ran/manifest.json", +"/ran/icon_192.png", +]; +const VERSION = "1726551022"; +const CACHE_NAME = 'chaxus_ran_' + VERSION + +const IGNORE_REQUEST_LIST = [ + // google 上报不需要缓存 + 'google', + // 插件请求不用缓存 + 'chrome-extension', + // 百度的请求不用缓存 + 'baidu.com', + 'blob:', + 'www.google-analytics.com' +] + +// 请求方法 +const REQUEST_METHOD = { + GET: 'GET' +} +// 响应状态码 +const RESPONSE_STATUS = { + SUCCESS: 200 +} +// service worker 可监听的事件 +const SERVICE_WORK = { + INSTALL: 'install', + FETCH: 'fetch', + ACTIVATE: 'activate', + MESSAGE: 'message', + SYNC: 'sync', + PUSH: 'push' +} +/** + * @description: 更新缓存 + * @param {*} fetchedResponse + * @param {*} request + * @return {*} + */ +const updateCache = (fetchedResponse, request) => { + const { url } = request + const { status } = fetchedResponse + // 只缓存状态码为 200 的请求 + if (status !== RESPONSE_STATUS.SUCCESS) return + if (filterRequest(request)) { + caches.open(CACHE_NAME).then(cache => { + // 将请求到的资源添加到缓存中 + // 判断下只有 fetch 的请求才有 clone 方法,才可以被缓存,从 cache 中获取的响应没有 clone + if (fetchedResponse?.clone) { + cache.put(url, fetchedResponse.clone()); + } + }).catch(error => { + console.log('service worker update cache error:', error, request) + }) + } +} +/** + * @description: 忽略 IGNORE_REQUEST_LIST 列表中的请求和非GET方法的请求 + * @param {*} request + * @return {*} + */ +const filterRequest = (request) => { + const { url, method } = request + return !IGNORE_REQUEST_LIST.some(item => url.includes(item)) && method === REQUEST_METHOD.GET +} + +/** + * 缓存优先 + * @param {*} request + * @returns + */ +const cacheFirst = async (request) => { + // 从缓存中读取 respondWith 表示拦截请求并返回自定义的响应 + try { + const { url } = request + const responseFromCache = await caches.match(url); + // 如果缓存中有,返回已经缓存的资源 + if (responseFromCache) return responseFromCache + // 如果缓存中没有,就从网络中请求,并更新到缓存中 + const responseFromServer = await fetch(request); + updateCache(responseFromServer, request) + return responseFromServer + } catch (error) { + // 当缓存中也没有,请求也不可用的时候 + // 始终需要一个一个响应 + // 甚至可以设置回落的请求,在catch中继续发起请求 + console.log('service worker cacheFirst error:', error, request) + return new Response("Network error happened", { + status: 408, + headers: { "Content-Type": "text/plain" }, + }); + } +} + + +const deleteCache = async (key) => { + try { + await caches.delete(key); + } catch (error) { + console.log('service worker deleteCache error:', error, key) + } +}; + +const deleteOldCaches = async () => { + const cacheKeepList = [CACHE_NAME]; + try { + const keyList = await caches.keys(); + const cachesToDelete = keyList.filter((key) => !cacheKeepList.includes(key)); + await Promise.all(cachesToDelete.map(deleteCache)); + } catch (error) { + console.log('service worker deleteOldCaches error:', deleteOldCaches, cacheKeepList) + } + +}; + +this.addEventListener(SERVICE_WORK.INSTALL, function (event) { + // 确保 Service Worker 不会在 waitUntil() 里面的代码执行完毕之前安装完成 + event.waitUntil( + // 创建了叫做 chaxus_ran 的新缓存 + caches.open(CACHE_NAME).then(function (cache) { + // SERVICE_WORK_CACHE_FILE_PATHS 从 bin/build.sh 中生成注入,会去缓存所有的资源 + // 不用 cache.addAll 避免一个请求失败,全部缓存失败,类似Promise.all + // 可以使用 cache.add 但 Cache.add/Cache.addAll 不会缓存 Response.status 值不在 200 范围内的响应, + // 而 cache.put 允许你存储任何请求/响应对。因此,Cache.add/Cache.addAll 不能用于不透明的响应,而 Cache.put 可以。 + return SERVICE_WORK_CACHE_FILE_PATHS.map(url => + fetch(url).then(response => { + // 检查响应是否成功 + if (!response.ok) { + console.log('service worker fetch response error:', url) + } + // 将响应添加到缓存 + return cache.put(url, response); + }).catch(error => { + console.log('service worker self installed error:', url, error); + }) + ) + }) + ); +}); + +this.addEventListener(SERVICE_WORK.FETCH, async (event) => { + // 拦截请求 + try { + cacheFirst(event.request) + } catch (error) { + console.log('service worker self fetch error:', error, event) + } +}); + +this.addEventListener(SERVICE_WORK.ACTIVATE, (event) => { + event.waitUntil(deleteOldCaches()); +}); + + +